개요
Spring boot를 사용한 백엔드 개발을 하다보면 자연스럽게 JSON데이터를 객체로 매핑해야하는 경우가 있습니다.
이러한 Java 객체와 JSON 간의 변환 작업, 즉 '직렬화(Serialization)'와 '역직렬화(Deserialization)'는 매우 중요한 과정인데, 본 글에서는 이 과정을 효율적으로 처리하기 위한 강력한 도구인 ObjectMapper에 대해서 정리하고자 합니다.
직렬화 & 역직렬화란❓
직렬화(Serialization)
직렬화는 객체의 상태를 바이트 스트림이나 다른 형식(JSON, XML 등)으로 변환하는 과정입니다. 이 과정을 통해 메모리에 존재하는 객체를 외부에서 사용할 수 있는 형태로 변환합니다.
주요 목적:
- 네트워크를 통한 데이터 전송
- 파일 시스템에 데이터 저장
- 다른 시스템이나 언어와의 데이터 교환
역직렬화(Deserialization)
역직렬화는 직렬화의 반대 과정으로, 바이트 스트림이나 다른 형식(JSON, XML 등)의 데이터를 다시 객체로 변환하는 과정입니다.
주요 목적:
- 전송받은 데이터를 응용 프로그램에서 사용 가능한 객체로 복원
- 저장된 데이터를 메모리에 로드
Spring에서의 직렬화 & 역직렬화 : ObjectMapper
Spring(Java)에서 직렬화는 일반적으로 Jackson 라이브러리를 활용합니다. 이 중 Jackson 라이브러리의 ObjectMapper라는 클래스가 있는데 이 클래스가 직렬화를 처리합니다.
Spring Boot는 기본적으로 Jackson을 내장하고 있으며, 이를 활용하여 JSON 데이터를 Java 객체로 변환하거나, Java 객체를 JSON으로 변환할 수 있습니다.
client에서 보낸 Json 데이터를 DTO 객체로 받으면, Spring에서 알아서 Json의 Key값과 DTO 객체의 멤버변수를 매칭해서 Value값을 DTO 객체에 자동으로 대입해주었는데, 그 과정을 바로 SpringBoot의 Object Mapper 클래스가 해주게 됩니다.
ObjectMapper란❓
ObjectMapper는 Jackson 라이브러리의 핵심 클래스로, Java 객체와 JSON 데이터 간의 변환을 담당합니다. 객체 지향 프로그래밍과 데이터 교환 형식 간의 다리 역할을 수행합니다.
주요 기능:
1. 직렬화(Serialization)
String json = objectMapper.writeValueAsString(myObject);
Java 객체를 JSON 문자열로 변환합니다.
2. 역직렬화(Deserialization)
MyClass obj = objectMapper.readValue(jsonString, MyClass.class);
JSON 문자열을 Java 객체로 변환합니다.
3. 다양한 입출력 지원
objectMapper.writeValue(new File("data.json"), myObject);
MyClass obj = objectMapper.readValue(new File("data.json"), MyClass.class);
문자열뿐만 아니라 파일, 스트림, URL 등 다양한 소스에서 읽고 쓸 수 있습니다.
4. 트리 모델 지원
JsonNode rootNode = objectMapper.readTree(jsonString);
String name = rootNode.get("name").asText();
JSON을 트리 구조로 처리할 수 있는 JsonNode API를 제공합니다.
ObjectMapper 커스텀
기본적으로 제공되는 ObjectMapper를 사용해도 되지만, 커스텀이 필요한 경우가 있습니다.
커스터마이징할 상황:
- 날짜/시간 형식 지정
- 기본적으로 JSON에서는 날짜를 타임스탬프로 표현하지만, "yyyy-MM-dd HH:mm:ss"와 같은 특정 형식으로 직렬화/역직렬화하고 싶은 경우
- null 값 처리
- null 값을 가진 필드를 JSON에서 제외하거나 특정 방식으로 처리해야 하는 경우
- 알 수 없는 속성 처리
- API 버전 호환성을 위해 알 수 없는 JSON 속성이 있어도
예외가 발생하지 않도록 설정
- API 버전 호환성을 위해 알 수 없는 JSON 속성이 있어도
- Enum 값 처리
- Enum 값을 단순 이름이 아닌 다른 방식(예: toString() 메소드 결과)으로 직렬화/역직렬화
- 명명 전략 적용
- Java의 camelCase를 JSON의 snake_case로 변환하는 등의 필드 이름 전략 설정
- 특정 타입 변환기 등록
- 복잡한 객체 타입을 위한 커스텀 직렬화/역직렬화 로직 추가
- 모듈 등록
- Java 8 날짜/시간 타입 지원이나 추가 데이터 타입 처리를 위한 모듈 등록
- 보안 설정
- 민감한 데이터를 자동으로 마스킹하거나 제외시키는 설정
- 성능 최적화
- 특정 기능을 비활성화하여 성능을 향상시키는 설정
- 다형성 처리
- 상속 관계에 있는 클래스들을 적절하게 처리하기 위한 설정
이 외에도 자신의 프로젝트에 맞는 커스텀 ObjectMapper가 필요한 경우가 있을 것 입니다. 이러한 커스텀이 필요한 경우를 살펴보겠습니다.
예시: 명명 전략 적용 (camelCase ↔ snake_case)
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
var objectMapper = new ObjectMapper();
// 모듈 등록
objectMapper.registerModule(new Jdk8Module()); // Java 8 타입 지원
objectMapper.registerModule(new JavaTimeModule()); // Java 시간 관련 타입 지원
// 기본 설정
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 날짜를 타임스탬프가 아닌 ISO-8601 형식으로
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 알 수 없는 속성 무시
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 빈 객체 직렬화 허용
// 명명 전략 설정 (camelCase -> snake_case)
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.SnakeCaseStrategy());
return objectMapper;
}
}
SnakeCaseStrategy를 적용하여 Java의 camelCase 필드명(예: firstName)을 JSON의 snake_case 형식(예: first_name)으로 변환합니다.
이런식으로 default로 제공되는 objcetMapper 이외에 추가적인 커스텀이 필요한 경우 ObjectMapper를 커스텀하여 Bean에다 등록하여 사용할 수 있습니다.
'Framework > Spring\Spring boot' 카테고리의 다른 글
[Springboot] Spring Boot에서 Service와 ServiceImpl 분리, 꼭 필요할까❓ (0) | 2025.02.28 |
---|---|
[Spring boot] DTO와 Entity 변환 위치에 대한 고찰 - Controller vs Service Layer (0) | 2024.12.25 |
[Spring boot] Cache Manager와 @Cacheable 어노테이션 이해하기 (0) | 2024.09.02 |
[Spring boot] @Pattern 어노테이션: 정규 표현식으로 입력 검증 간편하게 하기 (0) | 2024.08.27 |
[Spring boot] @PostConstruct : 빈의 안전한 초기화 콜백 (0) | 2024.08.25 |