📦 JSON 관련 어노테이션 (Jackson)
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/ |