isPublic boolean 저장 오류 해결

·2025년 7월 9일

troubleshooting

목록 보기
9/9

1. 문제 상황 1

문제 1] true로 입력해도 무조건 false가 반환된다.
문제 2] ResponseDto에 isPublic으로 필드명을 했지만 public으로 출력된다.

사실 두 번째 문제보다 첫 번째 문제가 데이터 저장 자체가 이상하게 된 것이기 때문에 큰일이였습니다.


2. 원인 분석 1

어디서부터 데이터가 이상하게 된지 확인하기 위해서 log를 출력해봤다.

2025-07-09T16:37:17.130+09:00  INFO 9255 --- [nio-8080-exec-2] t.travel.plan.controller.PlanController  : controller = false
// 생략
2025-07-09T16:37:17.208+09:00  INFO 9255 --- [nio-8080-exec-2] t.travel.plan.dto.PlanCreateReqDto       : PlanCreateReqDto = false 
// DTO -> Plan 변환 과정 직전
// 생략 
2025-07-09T16:37:17.229+09:00  INFO 9255 --- [nio-8080-exec-2] travel.travel.plan.dto.PlanResDto        : PlanResDto = false

처음 controller에서 부터 이상하게 된 것을 확인했다.

컨트롤러에서 DTO 값이 이미 false이기 때문에
즉, JSON→DTO 바인딩이 실패한 것이라고 파악했다.

(1) Jackson과 Lombok의 동작 방식

Spring Boot에서는 보통 JSON 데이터를 Jackson이 객체로 바꾼다.
Lombok을 쓸 때 boolean 필드를 선언하면 다음과 같이 동작한다.

// 필드
private boolean isPublic;

// Lombok이 만든 getter
public boolean isPublic() {...}

Jackson은 역직렬화(즉, JSON → Java 객체)할 때,
"어떤 필드에 값을 넣을지"를 getter/setter 메서드명이나 필드명을 보고 결정한다.

isPublic이라는 필드는 getter가 isPublic()이 되고,

Jackson은 내부적으로 프로퍼티명 추론 시 getter의 'is'를 떼버리고
→ public이라는 이름으로 인식하는 경우가 많다.

즉,
실제로는 "isPublic" → "public"으로 필드명이 변환되는 셈이다.

(2) 실제로 무슨 일이 ??

프론트는 "isPublic": true로 요청을 보내는데

백엔드는 이를 public이라는 프로퍼티명으로 찾으려고 하니까,
isPublic에는 아무 값도 들어가지 않아 default(false)로 남는다.

정리하면,

JSON 필드명("isPublic")
DTO 필드명(isPublic)
getter명(isPublic())

이 세 개가 완벽히 일치하지 않으면,
Spring/Jackson이 원하는 대로 매핑해주지 못하는 경우가 생긴다.

3. @JsonProperty란?

@JsonProperty
Jackson에게 이 필드는 반드시 이 이름으로 매핑하라고 명령하는 역할이다.

@JsonProperty("isPublic")
private boolean isPublic;

이렇게 쓰면 JSON의 "isPublic" 값을
DTO의 isPublic 필드와 직접 1:1로 매핑한다.

이 덕분에
getter/setter 이름, 필드명, JSON 프로퍼티명 등이 엉켜도 정확하게 원하는 이름으로 값이 들어오게 만들 수 있다.

4. 해결 1

@Getter
public class PlanCreateReqDto {

    @NotNull(message = "공개/비공개 설정은 필수입니다.")
    @JsonProperty("isPublic")
    private boolean isPublic;
	
    // 생략
}
@Getter
public class PlanResDto {
    private Long planId;

    @JsonProperty("isPublic")
    private boolean isPublic;

    // 생략
}

true로 입력하면 true로 출력하도록 변경은 성공했다.
그러나 두번째 문제에 대해서 해결되지 않았고 또한 public 과 isPublic이 둘 다 출력되는 상태였다.

4. 문제 상황 2

isPublic이라고 필드가 나왔지만
public 필드도 동시에 나오는 문제가 남아있다.

5. 원인 분석 2

private boolean isPublic;
→ Lombok의 @Getter가 자동으로 isPublic()라는 메서드를 생성한다.
→ Jackson은 getter 메서드 이름(isPublic())을 보고, JSON 속성명을 public으로 인식하게 되고
{ "public": true } 형태와 필드명으로도 한 번 더 직렬화해서 둘 다 나가는 경우가 된 것이다.

6. 해결

@AllArgsConstructor
@Getter
@Builder
public class PlanResDto {
    private Long planId;

    private boolean isPublic;

    // 생략

    @JsonProperty("isPublic")
    public boolean getIsPublic() {
        return isPublic;
    }
    // 생략

}

getter를 직접 명시해서 해결했다.

원래 목표대로
isPublic 만 나오고 true를 넣어도 true로 잘 나왔다.





0개의 댓글