1. 개요
현재 프로젝트에서 댓글 알림을 위한 FCM 토큰 저장 기능에서 발생한 문제이다. body는 다음과 같다.
@Getter
public class FcmTokenDto {
private String FCMToken;
}
이를 호출하는 컨트롤러 로직은 다음과 같다.
@PostMapping("/subscribe")
public ApiResponse<String> subscribe(@AuthenticationPrincipal CustomUserDetails principal,
@RequestBody FcmTokenDto fcmTokenDto) {
fcmNotificationTokenService.subscribe(principal, fcmTokenDto);
return ApiResponse.createSuccess("토큰 저장 및 갱신 완료");
}
그런데 이 기능이 정상동작하고 db를 확인해보니 fcmTokenDto.getFCMToken이 null인 것을 확인했다. 컨트롤러에서 로그를 찍어서 확인했으므로 RequestBody에서 가져올 때의 문제라고 짐작했다. 그 원인에 대해 알아보고 이를 해결하고자 한다.
2. Jackson
Jackson은 스프링부트에서 json으로 데이터를 매핑하기 위해 사용되는 라이브러리이다. 이 라이브러리는 기본적으로 JavaBeans 규약을 사용하지만 몇 가지 다른 점이 있다.
JavaBeans 규약의 일부를 발췌하자면
- 자바빈은 특정 패키지에 속해 있어야 한다.
- 기본 생성자가 존재해야 한다.
- 멤버변수의 접근제어자는 private로 선언되어야 한다.
- 멤버변수에 접근 가능한 getter와 setter가 public으로 선언되어 있어야 한다
등이 있다.
https://stackoverflow.com/questions/2948083/naming-convention-for-getters-setters-in-java
Naming convention for getters/setters in Java
if I have the following private member: private int xIndex; How should I name my getter/setter: getXindex() setXindex(int value) or getxIndex() setxIndex(int value) EDIT: or getXIndex() set...
stackoverflow.com
그 중에는 이런 규약이 있다.
클래스의 이름은 일반적으로 대문자로 시작하지만, 개발자들은 식별자가 소문자로 시작하는 것에 익숙하기 때문에 첫 번째 글자를 소문자로 변환한다. 다만, 모든 문자를 대문자로 사용하는 경우도 있기 때문에 이런 경우는 예외로 둔다.
그리고 예외 케이스를 판별하기 위해 첫 두 문자가 모두 대문자인지를 확인한다. 모두 대문자일 경우 모든 문자를 대문자로 사용한다고 간주, 그대로 사용한다.
Jackson은 이와 살짝 다르다. Jackson에서는 맨 앞 두 글자가 모두 대문자인 경우 모든 문자를 소문자로 바꿔버린다.
3. 위 규칙이 초래했던 문제
다시 앞 문자의 필드명을 살펴보자.
private String FCMToken;
getFCMToken()을 위의 규칙에 적용시켜 보면 첫 두 글자가 대문자이므로 모든 문자를 소문자로 바꾼다. 따라서 다음과 같은 getter가 생성될 것이다.
public String getFCMToken(){
return fcmtoken;
}
이는 존재하지 않는 필드값이므로 null을 리턴한다.
4. 해결
원인을 알았으니 해결책을 찾을 수 있다. 다음과 같은 방법으로 해결할 수 있다.
- 직접 Getter 메서드를 생성해서 사용
public String getFCMToken(){
return FCMToken;
}
2. 필드명을 작성할 때 첫 번째가 소문자, 두 번째가 대문자인 케이스를 만들지 않는다.
@Getter
public class FcmTokenDto {
private String fcmToken;
}
코드가 깔끔한 것이 좋으므로 2번 방법을 사용하여 해결했다. 프론트에서 이제 막 알림 개발에 들어가서 필드를 바꿔도 큰 문제가 없었다. 앞으로 필드명을 지을 때 이를 고려해야 겠다.
참고)
@RequestBody로 받았는데 null인 경우
Postman에 @RequestBody에 필요한 값들을 넣어서 서버에 요청을 보냈는데 자꾸 null값을 가져오는 문제가?? Jackson과 Lombok @Getter 동작 원리에서 이유를 찾아보자!
velog.io
https://www.baeldung.com/spring-httpmessageconverter-rest
'Proj > 구구모' 카테고리의 다른 글
FCM 알림 구현 (0) | 2024.07.17 |
---|---|
댓글 알림 구현(feat. sse) (0) | 2024.06.25 |
EC2 한국 시간으로 변경 (0) | 2024.06.08 |
스프링 스케쥴러를 이용한 게시글 마감 처리 (0) | 2024.06.07 |
추천 게시글 기능 구현 (0) | 2024.06.04 |