새발블로그
[Spring] 직렬화와 역직렬화 본문
1. 직렬화/역직렬화란?
- 직렬화(Serialization): Java 객체 → JSON 문자열 변환
- 역직렬화(Deserialization): JSON 문자열 → Java 객체 변환
REST API 개발에서:
- 응답(Response) 은 직렬화
- 요청(Request) 은 역직렬화
2. Jackson이란?
- Java 객체 ↔ JSON 변환을 담당하는 라이브러리
- Spring MVC에서 JSON 응답을 만들 때 MappingJackson2HttpMessageConverter를 통해 자동 적용
- 단, Spring Legacy에서는 직접 설정을 해줘야 동작
3. Spring Legacy에서 Jackson 설정하기
3-1. Maven 의존성 추가
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.15.2</version>
</dependency>
3-2. XML 설정 (servlet-context.xml)
<annotation-driven>
<message-converters>
<!-- Jackson Converter 등록 -->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<!-- Java8 날짜/시간 지원 -->
<property name="modules">
<list>
<bean class="com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"/>
</list>
</property>
<!-- null 필드 제외 -->
<property name="serializationInclusion" value="NON_NULL"/>
</bean>
</property>
</bean>
</message-converters>
</annotation-driven>
3-3. Java Config 설정 (WebConfig)
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule()); // LocalDateTime 지원
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // null 제외
converters.add(new MappingJackson2HttpMessageConverter(mapper));
}
}
4. 기본 동작 예시
Controller
@RestController
public class SampleController {
@GetMapping("/hello")
public User hello() {
return new User("홍길동", 29); // 자동 JSON 직렬화
}
}
응답(JSON)
{
"name": "홍길동",
"age": 29
}
5. 자주 쓰는 Jackson 어노테이션
| 어노테이션 | 설명 |
| @JsonProperty("이름") | JSON 필드명 변경 |
| @JsonIgnore | JSON 변환에서 제외 |
| @JsonInclude(Include.NON_NULL) | null 값 제외 |
| @JsonFormat(pattern = "...") | 날짜/시간 포맷 지정 |
예시
public class User {
@JsonProperty("username")
private String name;
@JsonIgnore
private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
}
6. LocalDateTime 직렬화 문제 해결
- 문제: 기본 Jackson은 LocalDateTime 변환 불가
- 해결: jackson-datatype-jsr310 모듈 + JavaTimeModule 등록
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime orderDt;
7. Lombok과 직렬화 주의점
- @Builder: 객체 생성은 편리하지만, Jackson 역직렬화 시 기본 생성자가 필요
- @NoArgsConstructor + @AllArgsConstructor: Entity/DTO에서 함께 쓰면 안전
8. 추가 Trouble Shooting
1. 필드명 매핑 실패
- 문제: JSON user_name → Java userName 자동 매핑 실패
- 해결1: @JsonProperty("user_name")
- 해결2: 전역 Naming 전략 설정
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
2. 한글 깨짐 (???)
- 문제: 응답 JSON이 ???로 출력
- 해결: web.xml에 인코딩 필터 추가
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3. null 값 포함
- 문제: 불필요한 null 필드 응답
- 해결: @JsonInclude(JsonInclude.Include.NON_NULL)
'Server > Spring' 카테고리의 다른 글
| [Spring] WebSocket + STOMP (0) | 2025.09.22 |
|---|---|
| [Spring] AOP (Aspect Oriented Programming) (0) | 2025.09.22 |
| [Spring] 파일 업로드 & 다운로드 (0) | 2025.09.22 |
| [Spring] Spring + MyBatis (0) | 2025.09.22 |
| [Spring] Spring 어노테이션 (0) | 2025.07.11 |