백오피스 프로젝트를 개발하던 중에 Jackson 라이브러리를 통해 '역직렬화'를 사용해 보았다.
먼저 상황은 다음과 같았다.
프로모션 관련 백오피스 기능이었는데,
프로모션을 등록할 때 섹션 종류가 총 3가지가 있었다. (buttion, image, detail)
이 때 프론트에서 세팅해야하는 JSON 데이터 포맷을
맨 처음에는 아래 이미지에서 A와 같이 되도록 코드를 작성했었다.
sectionType이 달라짐에 따라
"imageSection" , "buttonSection", "detailSection" 과 같은 필드가 따로 따로 생기는 방식이었다.
프론트 입장을 고려했을 때는
A 보다는 B 방식이 데이터를 다루는 데 있어서 더 편하다고 판단하였고
B 와 같이 JSON 포맷이 되도록 하기 위해 Jackson의 역직렬화 어노테이션을 이용해서 코드를 작성해보았다.
전체적인 코드 틀은 다음과 같다. (세세한 필드는 생략)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
visible = true,
property = "sectionType")
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = ImageSection.class, name = "image"),
@JsonSubTypes.Type(value = ButtonSection.class, name = "button"),
@JsonSubTypes.Type(value = DetailSection.class, name = "detail"),
})
@Data
public class PromotionSection {
@Schema(description = "섹션 타입", example = "image / button / detail")
private PromotionSectionType sectionType;
@Getter
@Setter
public static class ImageSection extends PromotionSection {
// ...생략
}
@Getter
@Setter
public static class ButtonSection extends PromotionSection {
// ...생략
}
@Getter
@Setter
public static class DetailSection extends PromotionSection {
// ...생략
}
이렇게 되면 JSON 요청 데이터에서
"sectionType" 이라는 필드의 값이 "image"면 ImageSection을 DTO로 인식하게 된다.
Jackson 라이브러리는 @JsonTypeInfo와 @JsonSubTypes 어노테이션 설정을 통해
JSON 데이터 내에 있는 특정 필드의 값을 기준으로 객체의 타입을 인식하고 매핑하기 때문이다.
사용됐던
@JsonTypeInfo 어노테이션과 @JsonSubTypes 어노테이션을
아래와 같이 조금 더 자세히 살펴보고자 한다.
- use = JsonTypeInfo.Id.NAME
- Id Enum Value는 직렬화 중에 식별자를 어떤 것으로 할 지 정의하는 value 이다.
- 구현 클래스마다 이름이 달라서 여기서는 NAME으로 설정해 주었다.
- use 부분은 어노테이션이 위치한 클래스의 유형 및 하위 유형의 인스턴스에 대한 정보를 직렬화, 역직렬화 할때 지정해야하는 프로퍼티이다.
- 정리하면 "직렬화 할 때 클래스 명으로 식별하겠다" 라는 의미이다.
- include = JsonTypeInfo.As.EXISTING_PROPERTY
- 다형성 정보를 JSON 데이터에 추가하는 방식 중 하나이다.
- EXISTING_PROPERTY를 사용하면 JSON 데이터를 자바 객체로 변환하거나 자바 객체를 JSON 데이터로 변환할 때, getter와 setter 메서드를 사용할 수 있게 된다.
- 이를 통해 좀 더 간단하고 편리한 역직렬화 및 직렬화를 할 수 있다.
- visible = true
- 설정을 true로 하면, 다형성 정보가 JSON 데이터에 포함되어 해당 객체의 타입을 식별하는 프로퍼티의 값이 표시된다.
- 따로 설정하지 않으면 해당 정보는 JSON 데이터에 포함되지 않게 된다.
- property = "sectionType"
- JSON 데이터 내에서 어떤 프로퍼티를 사용하여 객체의 다형성 정보를 식별할 것인지를 나타낸다.
- 이를 통해 Jackson은 해당 프로퍼티를 기반으로 객체의 타입을 식별하고, 그에 맞게 역직렬화를 수행한다.
- @JsonSubTypes.Type(name = "XXX", value = XXX.class)
- JSON 데이터에서 사용되는 논리적 이름과 직렬화 가능한 하위 클래스의 유형을 연결하기 위해 @JsonTypeInfo와 함께 사용되는 주석이다.
- Type 요소는 JSON 데이터에 사용되는 논리적인 이름과 각 하위 클래스의 실제 클래스를 연결한다.
- value
- 직렬화 가능한 하위 클래스의 실제 자바 클래스를 지정한다.
- JSON 데이터에서 해당 클래스가 식별될 때 이 클래스로 역직렬화된다.
- name
- JSON 데이터에서 사용되는 논리적 이름을 지정한다.
- JSON 데이터에 나타날 식별자 역할을 하며, 이 값은 JsonTypeInfo에서 설정한 property에 해당한다.
'Programming > Java & Spring 관련 내용 정리' 카테고리의 다른 글
JPA에서 @BatchSize 를 쓸 것인가 vs Fetch Join을 쓸 것인가 (0) | 2024.08.06 |
---|---|
[Java] 인터페이스를 통해 if문의 향연을 고쳐보았다. (0) | 2023.09.11 |
[Java] 인터페이스 사용하여 필터링 기능을 구현해 보았다. (0) | 2023.08.11 |
[Spring] 멀티 쓰레드 환경에서 자원이 공유돼 버렸다. (0) | 2023.05.31 |
[Spring] @Async는 왜 제대로 동작하지 못했는가악! (0) | 2023.03.23 |