Jackson Getter 네이밍 오류

윤현일·2025년 2월 25일

진짜 이러면 DTO에 미친사람처럼 보일 수 있게지만...초보 개발자라 그렇습니다.

문제 상황

현재 요구사항 :

/email/send 요청 에서 이메일을 받으면, 인증 번호를 생성해서 해당 이메일로 전송하고,

/email/verify 요청 에서 이메일과 인증 번호를 입력하면 이메일 인증이 완료되는 로직을 구현 중이다.

우선 이런 식으로 Email 요청 관련해서 request와 response DTO를 구분 없이 사용했다.

@Getter
public class EmailDTO {
    private final String email;
    private final String vCode;

    public EmailDTO(String email, String vCode) {
        this.email = email;
        this.vCode = vCode;
    }
}

이럴경우

이메일 요청까지는 정상적으로 되지만,

이메일 검증에서 인증코드가 일치하지 않는다고 나온다.

requestDTO문제인가 싶어서 @jsonproperty 를 사용해봤다.

로컬에서 테스트는 정상적으로 작동 했으나, 프론트에서 연결이 잘 안된다는 문제점이 있었다.

현재 /email/verify 요청에서 DTO가 잘못되었다는 것을 깨닫고, 롬복을 적용한 DTO 클래스를 새로 선언해줬다.

하지만 여전히 같은 문제가 발생 했다.

게다가, 스웨거에서 vCode가 vcode로 나왔다.

{
  "email": "string",
  "vcode": "string"
}

그래서 원래 json을 직렬화 할때 대문자가 소문자로 바뀌나? 싶어서 email -> emailRequest로 바꿔봤지만, 놀랍게도 vcode만 대문자 C가 소문자 c로 바뀌어 있었다.

해결 과정

아하! 그러면 swagger오류인가보다~ 하고 단순멍청하게 vcode 를 vCode로 손수 써봤다.

당연히 어림도 없었다. 이러면 스웨거 오류도 아니고, 사실 맞다고 해도 프론트에서 객체명을 받을때 뭘로 받아야하는지 확실 하지도 않았다.

우선 로그를 찍어봤다.

로그 결과 vCode로는 잘 들어오지만, 어떻게 된건지 null 값이 나왔다.

  • swagger 에서 vcode로 뜸
  • controller에선 vCode로 받아들임
  • null값으로 들어감**

이런식으로 문제가 좁혀졌다.

그래서 이번에는 아예 requestDTO에서 vCode 의 워딩을 바꿔봤다.

public class EmailRequestDTO {
    private String email;
    private String verificationCode;
}
  • vCode -> verificationCode
오잉?? dto의 변수명만 바꾸니 해결이 되었다...

심지어 swagger에서도 대소문자가 알맞게 찍혔다.

도대체 왜이러는 건지 하고 구글링을 해봤다.

Jackson 네이밍 규칙

Jackson 라이브러리는 객체를 JSON으로 직렬화하거나 JSON을 객체로 역직렬화할 때, Getter 메서드의 이름을 기반으로 JSON 키를 생성한다.
이 과정에서 JavaBeans 명명 규칙을 따르는데, 규칙은 다음과 같다

  1. 첫 번째 문자만 대문자인 경우: 해당 문자를 소문자로 변환한다.
    ex) getName() -> name
  2. 첫 번째와 두 번째 문자가 모두 대문자인 경우: 두 문자를 그대로 유지한다.
    ex) getURL() → URL
  3. 첫 번째 글자가 소문자이고, 두 번째 글자가 대문자인 경우 → 전체 필드를 소문자로 변환
    ex) getAbcde() → abcde (정상)
    ex) getABCde() → aBCde (잘못된 변환)

그러므로 나의 문제에 대입 시켰을때는 기존 DTO에서 필드명을 vCode와 같은 카멜케이스(CamelCase) 형태로 정의했을 때,
Jackson이 이를 JSON 키로 변환하는 과정에서 일부 문자의 대소문자가 예상과 다르게 변환되었던 것이다.

필드명 -> lombok -> jackson
vCode -> getVCode() -> vcode

이로 인해 Swagger에서는 vcode로 표시되고, Controller에서 vCode로 받으려고 하니까 매칭되지 않아 null이 반환되었다.

앞으로 이런 상황을 예방 하려면, getter를 직접 선언 하거나, @JsonProperty를 사용해 명시적으로 변환하거나, 애초에 변수명을 문제가 생기지 않게끔 사용하면 된다...

참고 문헌 : https://yungenie.tistory.com/m/16

profile
라이틔얼

0개의 댓글