본문 바로가기

Proj/구구모

Trouble Shooting: @RequestBody에서 데이터를 꺼내는 데 null

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 규약의 일부를 발췌하자면

  1. 자바빈은 특정 패키지에 속해 있어야 한다.
  2. 기본 생성자가 존재해야 한다.
  3. 멤버변수의 접근제어자는 private로 선언되어야 한다.
  4. 멤버변수에 접근 가능한 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. 해결

원인을 알았으니 해결책을 찾을 수 있다. 다음과 같은 방법으로 해결할 수 있다.

  1. 직접 Getter 메서드를 생성해서 사용
public String getFCMToken(){
	return FCMToken;
}

 

   2. 필드명을 작성할 때 첫 번째가 소문자, 두 번째가 대문자인 케이스를 만들지 않는다.

@Getter
public class FcmTokenDto {


    private String fcmToken;
}

 

코드가 깔끔한 것이 좋으므로 2번 방법을 사용하여 해결했다. 프론트에서 이제 막 알림 개발에 들어가서 필드를 바꿔도 큰 문제가 없었다. 앞으로 필드명을 지을 때 이를 고려해야 겠다.

 

참고)

https://velog.io/@ssol_916/RequestBody%EB%A1%9C-%EB%B0%9B%EC%95%98%EB%8A%94%EB%8D%B0-null%EC%9D%B8-%EA%B2%BD%EC%9A%B0#%EC%9D%B4%EB%A6%84-%EC%A2%80-%EC%9E%98-%EC%A7%80%EC%96%B4

 

@RequestBody로 받았는데 null인 경우

Postman에 @RequestBody에 필요한 값들을 넣어서 서버에 요청을 보냈는데 자꾸 null값을 가져오는 문제가?? Jackson과 Lombok @Getter 동작 원리에서 이유를 찾아보자!

velog.io

https://www.baeldung.com/spring-httpmessageconverter-rest

 

'Proj > 구구모' 카테고리의 다른 글