카테고리 없음

📦 JSON 관련 어노테이션 (Jackson)

creator7087 2025. 5. 7. 20:04

Jackson은 Java에서 JSON 데이터를 처리하기 위한 강력한 라이브러리로, 다양한 어노테이션을 통해 직렬화 및 역직렬화 과정을 세밀하게 제어할 수 있습니다. 아래는 Jackson의 주요 어노테이션과 커스텀 컨버터에 대한 정리입니다. 특히 프론트엔드와 관련이 많이 되어있기에  하나의 케이스를 생각할지 범용성을 높일 지에  사용하기 전에 생각은 필수입니다.

📘 @JsonProperty

🔹 정의

Jackson에서 필드, 메서드, 생성자 파라미터에 적용되어 JSON의 필드 이름을 명시적으로 지정하거나, 읽기/쓰기 접근 제어를 가능하게 하는 어노테이션입니다

더보기

✅ 장점

  • JSON 키와 Java 필드명을 다르게 지정할 수 있어 API 명세와 유연하게 매핑 가능
  • access 속성을 통해 직렬화 또는 역직렬화 전용으로 설정 가능 (READ_ONLY, WRITE_ONLY)
  • 생성자 기반 객체 생성 시 정확한 JSON 필드 매핑 가능 (생성자 파라미터에 사용)

❌ 단점

  • 어노테이션을 잘못 지정하거나 누락하면 역직렬화 오류 발생 가능
  • 생성자에서 사용할 경우 @JsonCreator와 함께 사용하지 않으면 매핑 실패할 수 있음
  • 필드/메서드/생성자 등 다양한 위치에서 사용 가능하므로 일관성이 깨질 수 있음

💡 사용 상황

  • JSON 필드명과 Java 필드명이 다를 때 (예: user_name → userName)
  • 보안 상 민감한 필드(비밀번호 등)를 응답에서는 숨기고, 입력에서는 허용할 때
  • 생성자를 통한 객체 생성 시 매개변수와 JSON 키를 정확히 매핑하고 싶을 때

📌 규칙

항목 권장 사항
클래스 내 위치 필드, getter/setter, 생성자 파라미터
JSON 키 매핑 필요한 경우 JSON 필드명 명시 (@JsonProperty("json_key"))
읽기/쓰기 접근 제어 access = JsonProperty.Access.READ_ONLY 또는 WRITE_ONLY
생성자 사용 시 주의사항 @JsonCreator와 함께 사용 필수

 

📘 @JsonInclude

🔹 정의

JSON 직렬화 시 null 값이나 기본값 등을 포함할지 말지를 제어하는 Jackson 어노테이션입니다.

더보기

✅ 장점

  • null인 필드를 JSON 출력에서 자동으로 생략할 수 있어 응답이 간결해짐
  • API 응답 데이터에서 불필요한 정보 제거 가능
  • NON_EMPTY, NON_NULL, NON_DEFAULT 등 다양한 정책으로 조절 가능

❌ 단점

  • 직렬화 기준이 바뀌면 클라이언트와의 JSON 계약이 바뀔 수 있음
  • 필드가 생략되면 프론트엔드에서 예상치 못한 동작이 생길 수 있음
  • 클래스 단위와 필드 단위에서 모두 설정 가능해 혼동될 수 있음

💡 사용 상황

  • API 응답에서 null 필드를 생략하여 데이터 용량 줄이기
  • 기본값(null, false, 0 등)이 클라이언트에서 의미 없거나 혼동될 경우
  • 공통 응답 객체(CommonWrapperResponse)에서 data가 없을 때 빈 객체 출력 생략 등

📌 규칙

항목 권장 사항
적용 위치 클래스 또는 필드
설정 옵션 Include.NON_NULL, Include.NON_EMPTY, Include.NON_DEFAULT
전체 설정 ObjectMapper.setSerializationInclusion(...) 로 전역 설정 가능

 

사용 시 유의사항:  프론트에서 생략된 필드에 대한 처리가 필요할 수 있음

📘 @JsonFormat

🔹 정의

Jackson에서 날짜 및 시간 필드를 직렬화하거나 역직렬화할 때 사용되는 어노테이션입니다. 날짜와 시간의 형식을 지정하거나, 직렬화/역직렬화 시 형식 변경을 설정할 수 있습니다.

더보기

✅ 장점

  • 날짜 및 시간 포맷을 명확하게 정의하여 API 응답에서 일관된 형식을 유지할 수 있음
  • 직렬화/역직렬화 시 날짜/시간 형식의 자동 변환을 처리해줘 코드가 깔끔해짐
  • 클라이언트가 지정된 형식에 맞추지 않더라도 자동으로 변환 가능

❌ 단점

  • 형식 지정이 잘못되면 직렬화 오류역직렬화 실패가 발생할 수 있음
  • 날짜 및 시간 포맷이 클라이언트와 맞지 않으면 API 계약 변경이 필요할 수 있음

💡 사용 상황

  • 날짜/시간 정보를 클라이언트와 서버 간 일관되게 주고 받을 때
  • API 응답에서 명시적인 날짜/시간 포맷을 요구하는 경우

📌 규칙


항목 권장 사항
적용 위치 필드, 클래스
포맷 설정 shape (ex. JsonFormat.Shape.STRING)와 pattern으로 형식 지정
형식 지정 yyyy-MM-dd HH:mm:ss와 같은 표준 형식 사용
주의사항 클라이언트와의 형식 일치가 중요

📘 @JsonAlias

🔹 정의

@JsonAlias는 여러 이름으로 전달된 JSON 필드를 하나의 Java 필드에 매핑할 수 있도록 해주는 어노테이션입니다. 클라이언트가 다양한 방식으로 데이터를 보낼 수 있게 해주며, 키 이름에 유연성을 부여합니다.

더보기

✅ 장점

  • 여러 이름으로 전달된 필드를 하나의 필드에 매핑 가능 (예: user_name, user-name, userName)
  • 외부 시스템, 클라이언트에서 필드 이름 차이로 인한 문제를 유연하게 처리할 수 있음

❌ 단점

  • 키 이름이 많아지면 코드의 가독성에 영향을 미칠 수 있음
  • 여러 이름을 처리하는 경우 유효성 검증이 추가로 필요할 수 있음

💡 사용 상황

  • 클라이언트가 여러 키 이름을 사용하여 데이터를 보낼 수 있을 때 (예: 다양한 이름의 username)
  • 외부 시스템과 필드명이 일치하지 않는 경우, 다양한 이름을 하나로 매핑해야 할 때

📌 규칙

항목 권장 사항
적용 위치 필드 또는 생성자 파라미터
키 네이밍 처리 @JsonAlias로 다양한 이름을 하나로 매핑
주의사항 필드 이름이 많은 경우 유효성 검증이 필요할 수 있음

📘 @JsonProperty

🔹 정의

@JsonProperty는 필드나 메서드의 이름을 JSON에서 사용하는 이름과 매핑하는 어노테이션입니다. 이 어노테이션을 사용하면 직렬화역직렬화 시 필드의 이름을 직접 지정할 수 있습니다. 또한, null 값 처리, 기본값 설정, required 속성 등을 지정할 수 있습니다.

더보기

✅ 장점

  • 필드 이름을 세밀하게 제어할 수 있어, 클라이언트와의 계약에 맞는 필드 이름을 설정할 수 있음
  • null 값 처리기본값 설정 등 다양한 추가 기능을 활용할 수 있음

❌ 단점

  • 너무 많은 설정을 추가하면 코드가 길어지고 가독성이 떨어질 수 있음
  • 일관된 네이밍 전략을 적용하기에는 어려울 수 있음 (특히 복잡한 객체 구조일 때)

💡 사용 상황

  • 필드 이름을 외부와 다르게 매핑하고 싶을 때
  • 필드에 대해 null 처리기본값 설정이 필요할 때

🧩 코드 예시

public class User {
    @JsonProperty("user_name") // JSON에서는 "user_name"으로 사용
    private String username;

    @JsonProperty(defaultValue = "Guest") // 기본값 설정
    private String nickname;

    @JsonProperty(required = true) // 필수 필드
    private String email;
}

 

결과 JSON

{
        "user_name": "bob",
        "nickname": "Guest",
        "email": "bob@example.com"
        }

 

📘 @JsonCreator

🔹 정의

@JsonCreator는 역직렬화 시에 사용자 정의 생성자를 호출하는데 사용됩니다. 객체의 생성자가 여러 개 있을 때, Jackson이 어떤 생성자를 사용할지 결정할 수 있습니다. 주로 JSON 데이터를 객체로 변환할 때 사용됩니다.

더보기

✅ 장점

  • 커스텀 생성자를 사용하여 객체 생성을 세밀하게 제어할 수 있음
  • 생성자 인자에 **@JsonProperty**를 적용하여 명시적인 필드 바인딩 가능

❌ 단점

  • 생성자가 복잡해지면 역직렬화가 어려워질 수 있음
  • 기본 생성자가 없는 경우, 역직렬화가 실패할 수 있음

💡 사용 상황

  • 커스텀 생성자로 객체를 생성해야 하는 경우
  • 특정 파라미터에 대해 명시적인 매핑이 필요할 때

🧩 코드 예시

public class User {
    private String username;
    private String email;

    @JsonCreator
    public User(@JsonProperty("user_name") String username, @JsonProperty("email") String email) {
        this.username = username;
        this.email = email;
    }
}

 

결과 JSON

{
        "user_name": "bob",
        "email": "bob@example.com"
        }

 

📘 @JsonDeserialize / @JsonSerialize

🔹 정의

@JsonDeserialize와 @JsonSerialize는 객체의 직렬화역직렬화 시에 커스텀 로직을 적용할 수 있도록 해주는 어노테이션입니다. 이를 사용하여 커스텀 직렬화/역직렬화 로직을 작성할 수 있습니다.-

더보기

✅ 장점

  • 직렬화/역직렬화 로직을 커스터마이즈할 수 있어 복잡한 객체 변환을 처리할 수 있음
  • 고유한 데이터 형식이나 변환 규칙을 적용할 때 유용

❌ 단점

  • 커스텀 로직을 작성해야 하므로 코드가 복잡해질 수 있음
  • 직렬화/역직렬화 시 성능 저하를 초래할 수 있음

💡 사용 상황

  • 특수한 변환 규칙이 필요할 때
  • 복잡한 객체를 변환할 때
  • List<Enum>같은 특이한 경우

@JsonSerialize(using = CustomDateSerializer.class)
@JsonDeserialize(using = CustomDateDeserializer.class)
private LocalDate birthDate;

 

→ CustomDateSerializer와 CustomDateDeserializer를 사용해 날짜의 직렬화와 역직렬화 방식을 정의할 수 있음.

📘 @JsonValue

🔹정의

해당 필드나 메서드의 반환값을 객체 전체의 JSON 표현으로 사용하게 만듭니다.

더보기

✅ 장점

  • Enum이나 VO의 직렬화 결과를 커스터마이징할 때 유용
  • 간단한 객체 표현 시 직관적인 JSON 생성 가능

❌ 단점

  • 역직렬화는 지원하지 않음 (@JsonCreator를 함께 사용해야 역직렬화 가능)
  • 복잡한 객체에서는 사용을 피해야 함 (가독성 저하)

💡 사용 상황

  • Enum을 값(코드) 중심으로 직렬화하고 싶은 경우
  • VO 클래스에서 하나의 필드만 JSON으로 표현하고 싶은 경우

🧩 코드 예시

public enum Status {
    ACTIVE("A"), INACTIVE("I");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    @JsonValue
    public String getCode() {
        return code;
    }
}

결과 JSON

"ACTIVE"

📘 @JsonTypeInfo

🔹 정의

직렬화 시 타입 정보를 JSON에 포함하여 역직렬화 시 어떤 하위 클래스를 사용할지 지정하게 해주는 어노테이션입니다.

더보기

✅ 장점

  • 추상 클래스나 인터페이스의 하위 타입을 자동으로 매핑 가능
  • 다양한 JSON 구조에서도 타입을 인식 가능

❌ 단점

  • JSON에 type 등의 추가 필드가 생김
  • 외부와 통신 시 JSON 형식을 제어하기 어려울 수 있음

📌 사용 상황

  • 부모 타입(인터페이스, 추상 클래스)으로 JSON을 주고받되, 실제 객체는 하위 타입에 따라 다를 때
  • 전략 패턴, 이벤트 처리, 다형적 응답에 활용

🧩 코드 예시

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = Cat.class, name = "cat"),
        @JsonSubTypes.Type(value = Dog.class, name = "dog")
})
public abstract class Animal {
    public String name;
}
결과 JSON
        {
                "type": "cat",
                "name": "Nabi"
                }

 

✅ 추천 Jackson 관련 사이트 & 문서

Jackson 공식 문서 (Fasterxml) Jackson의 모든 기능과 어노테이션 문서, 세부 API 설명 포함 https://github.com/FasterXML/jackson
Baeldung Jackson 어노테이션별 실용 예제, 직렬화/역직렬화 등 실무 중심 설명 https://www.baeldung.com/jackson
Mkyong 가볍고 직관적인 Jackson 튜토리얼 제공 (한국어보다 영어 원문 추천) https://mkyong.com/tag/jackson/
Stack Overflow 특이 케이스나 복잡한 구조 처리 시 참고할 수 있는 실전 Q&A 다수 https://stackoverflow.com/questions/tagged/jackson
Reflectoring.io JSON 처리뿐 아니라 전체 Java 웹 개발 관점에서 Jackson 활용법을 설명 https://reflectoring.io/