분명 DTO 에 'is'가 있거든요
유저의 정보 변경 `DTO` 에 `boolean` 타입의 필드들이 있습니다.
Lombok의 `@Getter`도 붙여줬기 때문에 이 DTO가 직렬화되면 JSON 필드 이름은 `isAgreeToTerms` 같이 될 것이라고 예상했습니다.
직렬화는 됐는데 'is'가 없어요
직렬화된 JSON 필드를 `swagger ui`를 통해 확인해 보겠습니다.
확인해 보니, `is` prefix 가 제외돼서 직렬화된 것을 확인할 수 있었습니다.
예상과 다른 필드 이름은 백엔드와 프론트엔드의 데이터 교환에서 장애를 발생시킵니다.
프론트엔드 개발자는 `swagger`에 있는 대로 필드 이름을 사용하기 때문입니다.
위의 예시 코드에선 `boolean` 타입이 문제가 될 수 있습니다.
`is`가 없는 JSON 필드들은 모두 `null`로 받기 때문에 primitive 타입인 `boolean` 필드를 매핑하는 과정에서 예외가 발생합니다.
원인 찾기
근본적인 문제 해결을 위해 원인을 찾아야 합니다.
spring 에선 기본적으로 DTO 같은 POJO를 `직렬화` 또는 `역직렬화` 할 때 `Jackson ObjectMapper`를 사용합니다.
Jackson ObjectMapper 는 `Java 필드`와 `JSON 필드`를 어떻게 변환할까요?
https://github.com/FasterXML/jackson-docs 에서 소개하는 외부 문서인 Jenkov 문서를 보겠습니다.
문서에 따르면 Java 객체의 getter, setter 메서드와 일치시켜 JSON 객체의 필드로 매핑합니다.
`get` 부분과 `set` 부분을 제거하고 나머지 이름의 첫 번째 문자를 소문자로 변환해서요.
예시의 DTO 코드에서 Lombok 의 `@Getter`는 boolean 타입에 대해 `is` 접두사를 붙여줍니다.
`Jackson ObjectMapper`는 직렬화/역직렬화 시 `boolean` 타입을 매핑할 때 `get`을 제거하는 것처럼 `is`를 제거합니다.
이러한 이유로 분명 `isXXX` 라는 Java 객체 필드가 있음에도 `is`가 제거된 것이죠.
해결 방법: 필드 이름에 `is`를 사용하지 않기
여러 해결 방법이 있지만 제 생각엔 `is`가 붙은 필드 이름을 사용하지 않는 것이 가장 좋다고 생각합니다.
별도의 코드 추가 없이 primitive 타입을 사용할 수 있기 때문입니다.
아래 다른 해결 방법들을 보시면 이해가 가실 겁니다.
다른 해결 방법 1. @JsonProperty 사용
우선, `@JsonProperty` 애너테이션만 지정하면 애너테이션에 의해 `is`가 붙은 필드 1개, Jackson이 만든 `is`가 붙지 않은 필드 2개가 생깁니다.
{
"isAgreeToTerms": false,
"agreeToTerms": false,
}
해당 Java 객체 필드에 Lombok의 애너테이션인 `@Getter(AccessLevel.NONE)`를 추가로 붙여야 합니다.
다른 해결 방법 2. Java 객체에 wrapper 타입인 Boolean 타입 사용
Java 객체 필드로 primitive 타입 대신 wrapper 타입인 `Boolean` 타입을 사용하면 해결할 수 있습니다.
하지만, `null`이 들어가면 안 되는 상황 등에서 문제가 발생할 수 있기 때문에 별도의 검증 코드가 추가돼야 합니다.
읽어주셔서 감사합니다.
참고
- https://medium.com/@baejae/boolean에-is-붙이지-마세요-7b717246d942
- https://jenkov.com/tutorials/java-json/jackson-objectmapper.html
Jackson ObjectMapper
The <em>Jackson ObjectMapper</em> can read JSON into Java objects and write Java objects to JSON. This Jackson ObjectMapper tutorial explains how to use the Jackson ObjectMapper class.
jenkov.com
Boolean에 is 붙이지 마세요!
만약, 당신이 java에서 boolean을 다룬다면
medium.com
'Spring' 카테고리의 다른 글
Spring Event Deep Dive (0) | 2025.01.16 |
---|---|
[Spring] MockMvc 사용 시 Page 인터페이스의 직렬화 문제 (0) | 2024.12.31 |
[Spring] 회원탈퇴 시 Kakao OAuth2 연결끊기: REST API로 연결끊기 (OpenFeign) (2) | 2024.10.30 |
[Spring Batch] ItemWriter 가 List<T> 를 전달받으려면? (Spring Batch 5) (0) | 2024.07.01 |
[Spring] Response DTO 직렬화 문제 (1) | 2024.06.13 |