일할 때, 프론트 담당자에게 연락이 왔다.
똑같은 의미의 응답값이 중복되서 응답되고 있다는 것
이런 데이터가 오고 있다는 것이였다.
{
"xvalue": "2022-05-19T10:00:00",
"yvalueR": 3.0,
"yvalueL": 20.0,
"xValue": "2022-05-19T10:00:00",
"yValueR": 3.0,
"yValueL": 20.0
}
그래서 해당 응답 객체를 살펴보니 아래와 같이 선언되어 있었다.
@Getter
@Builder
public static class Value {
@JsonProperty("xValue")
private final LocalDateTime xValue;
@JsonProperty("yValueR")
private final Float yValueR;
@JsonProperty("yValueL")
private final Float yValueL;
}
뭐가 문제지? 하고 서칭을 좀 해보니 Lombok의 @Getter
와 @JsonProperty
를 같이 사용해서 발생하는 문제였다!
Lombok을 사용하여 getter/setter를 생성하는 경우 변수명이 위 xValue와 같이 두 번째 단어가 대문자라면, getXValue()
, setXValue()
와 같이 생성된다.
그리고 해당 getXValue()
, setXValue()
를 사용하여 변수명을 추정할 때 이어진 대문자를 모두 소문자로 변경한 값으로 추정하기 때문에 xvalue라는 변수명으로 추정한다.
아마 초기에 위 문제를 해결하기 위해 @JsonProperty("xValue")
코드를 추가한 것이라고 생각한다
Object와 JSON 간의 Serialize, Deserialize를 담당하는 라이브러리이다.
(위 진행했던 프로젝트에서는 별도의 설정 변경 없이 그대로 사용했다)
Jackson 라이브러리의 기본 네이밍 전략은 lowerCamelCase이다.
jackson-databind 라이브러리 내의 PropertyNamingStrategies.class
를 살펴보면 다음과 같은 코드가 보인다
public static class LowerCamelCaseStrategy extends NamingBase {
private static final long serialVersionUID = 2L;
public LowerCamelCaseStrategy() {
}
public String translate(String input) {
return input;
}
}
translate(String input)
을 살펴보면, input 그대로 return 하고 있기 때문에 해당 lowerCamelCase 형식이 default 설정값이라는 것을 확인할 수 있다.
Object to JSON으로 Deserialize를 진행할 때는 getter 메소드를 통해서 역직렬화를 진행한다.
(이게 Jackson을 사용할 때 getter()를 신경써야 하는 이유다)
다만 처음의 문제상황은 @JsonProperty
를 Lombok의 @Getter
와 같이 사용하면서 중복된 응답값이 발생했다.
변수에 선언한 @JsonProperty
에서 선언한 값으로 Deserialize를 진행하는데 Lombok으로 생성된 getter()에서도 Deseiralize를 진행한다.
@JsonProperty("xValue")
로 인해서 xValue 응답값이 생성되고, Lombok의 @Getter
로 생성된 getXValue()
에서도 xvalue 응답값이 생성된다.
그래서 최종적으로 xValue, xvalue 응답값이 생성되며 중복된 응답값이 발생한 것이다.
문제 상황을 파악했으니 이를 해결하기 위해 어떻게 하는게 좋을지를 찾아봤다.
1. Lombok의 @Getter 제거
응답 객체에 @Getter
를 선언한 이유는 jackson 라이브러리가 getter()로 Deserialize를 진행하기 때문이다. @JsonProperty
가 선언되어 있다면 @JsonProperty
가 Deserialize를 진행하기 때문에 getter()가 존재하지 않아도 정상적으로 동작한다.
Lombok의 @Getter
가 xValue를 getXValue()
를 자동 생성하고 있기 때문에 응답값이 xvalue로 나오고 있다. getter()가 필요하다면, @Getter
를 사용하지 않고 getxValue()
로 직접 선언해주면 xValue로 응답값이 나온다.
위 프로젝트에서는 해당 객체를 테스트코드에서 응답값 자체 검증을 진행하지 않고 있어서 getter()를 사용하지 않고 있었다. 그래서 Lombok의 @Getter
를 제거해도 다른 문제가 발생하지 않았다.
2. getter() 직접 선언
getxValue()
와 같이 getter()를 직접 선언해 준다면, getter를 사용할 수도 있고 @JsonProperty
도 필요없어진다.
다만, 다른 객체들은 @Getter
가 선언되어 있는데 해당 객체에서만 사용하지 않아서 추후 리팩토링할 때 까먹고 수정할 수도 있고 인텔리제이 IDEA에서 lombok이 설정되어있으면 getter()대신 @Getter
를 사용하라고 추천하기도 하니 그런 외압들을 받아들여서 수정하는 것을 방지하고자 주석으로 설명을 추가할 필요가 있다.
@JsonProperty
설명 확인 (해당 변수에 대한 getter/setter를 정의하는 것으로 보임)@Getter
이슈 관련 블로그