Spring MVC 애플리케이션에서 JSON 데이터 처리 시 발생하는 특정 문제를 해결하기 위해 Jackson ObjectMapper 설정을 커스터마이징하는 방법을 알아봅니다. 클라이언트와 서버 간의 데이터 불일치로 인해 프론트엔드에서 상태 변경이 제대로 적용되지 않는 경우가 종종 발생합니다.
이러한 문제를 해결하기 위해 Java 객체를 JSON 객체로 변환하는 데 Jackson ObjectMapper를 활용합니다. 아래는 사용자 정의 Jackson ObjectMapper 클래스의 예시입니다.
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
public class CustomObjectMapper extends ObjectMapper {
private static final String DATE_FORMAT = "yyyy-MM-dd";
private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String TIME_FORMAT = "HH:mm:ss";
public CustomObjectMapper() {
super();
// 알 수 없는 속성이 수신될 때 예외 발생 방지
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 역직렬화 시 속성이 존재하지 않는 경우 호환성 처리
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule customModule = new SimpleModule()
// 날짜/시간 관련 역직렬화 설정
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(TIME_FORMAT)))
// BigInteger 및 Long 타입을 문자열로 직렬화
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
// 날짜/시간 관련 직렬화 설정
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(TIME_FORMAT)));
// 사용자 정의 직렬화/역직렬화 기능 모듈 등록
this.registerModule(customModule);
}
}
WebMvcConfigurer를 구현하는 클래스에서 이 사용자 정의 ObjectMapper를 설정할 수 있습니다. extendMessageConverters 메서드를 오버라이드하여 기본 메시지 변환기에 사용자 정의 설정을 적용합니다.
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
import java.util.logging.Logger;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private static final Logger log = Logger.getLogger(WebMvcConfig.class.getName());
@Override
public void extendMessageConverters(List> converters) {
log.info("메시지 변환기 확장 중...");
// 사용자 정의 ObjectMapper를 사용하는 메시지 변환기 생성
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
messageConverter.setObjectMapper(new CustomObjectMapper());
// 생성된 메시지 변환기를 변환기 목록의 맨 앞에 추가
// 이는 사용자 정의 변환기가 기본 변환기보다 우선적으로 사용되도록 합니다.
converters.add(0, messageConverter);
}
}