새로운 프로젝트를 받으면서, 레거시 코드로 인해 발생한 간단한 해프닝을 공유하려고 한다. 레거시 코드라 PUT method에서 RequestParam으로 데이터를 받는 케이스가 있었다..!

문제 상황

  • UDC에서 POST , PUT method에서 body로 보내지 않고, RequestParam 으로 데이터를 보냄
  • 프론트 요청으로 queryParam에 Boolean? 값을 추가함
    @PutMapping
    fun update(
    	@RequestParam(required = false) name: String?,
    	@RequestParam(required = false) isEnabled: Boolean?,
    )
    
  • 프론트에서 “null” 을 넣어서 보내니 400에러가 발생한다고 문의가 들어옴. 값을 넣지 않으면 정상 동작(null로 들어감)
  • 뿐만 아니라 string value에 null을 집어 넣으면 "null" 로 들어가서 db까지 null string으로 저장되는 문제 발생

원인 파악

  1. string value (”null”)을 boolean으로 converting하지 못하는 것으로 예상
    • spring의 @RequestParam 에서 사용하는 converter 확인
      • StringToBooleanConverter 코드
        final class StringToBooleanConverter implements Converter<String, Boolean> {
        
            private static final Set<String> trueValues = new HashSet<>(8);
        
            private static final Set<String> falseValues = new HashSet<>(8);
        
            static {
                trueValues.add("true");
                trueValues.add("on");
                trueValues.add("yes");
                trueValues.add("1");
        
                falseValues.add("false");
                falseValues.add("off");
                falseValues.add("no");
                falseValues.add("0");
            }
        
        
            @Override
            @Nullable
            public Boolean convert(String source) {
                String value = source.trim();
                if (value.isEmpty()) {
                    return null;
                }
                value = value.toLowerCase();
                if (trueValues.contains(value)) {
                    return Boolean.TRUE;
                }
                else if (falseValues.contains(value)) {
                    return Boolean.FALSE;
                }
                else {
                    throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
                }
            }
        
        }
    • 코드를 보면, string "null" 값에 대한 처리는 없음
  2. string의 경우에는 별도의 convert 없이 받는 데이터 그대로 string으로 넘겨줌
  3. @RequestBody 의 경우 jackson converter로 json 객체를 parsing하고, json 객체에는 null과 "null" 을 구분할 수 있기 때문에 큰 문제가 없었음

해결 방법

  1. 별도의 converter 등록하기
    위 converter에서 null string 체크 로직을 추가한 custom converter를 등록하면 된다. 그러나 requestParam은 url에서 파싱한 string 값이고, 이미 요청할 때 string 값을 넣은 것이기 때문에 null 변환이 있는게 더 어색해 보인다.
  2. RequestParam → RequestBody 변환하기
    PUT 요청에서는 requestBody를 쓰는게 일반적이기 때문에 더 자연스러워 보인다.

 

레거시 코드라서 볼 수 있었던 일종의 해프닝이다. 이 계기로 여러 converter들의 코드를 확인해보고, query string을 파싱방법을 리마인드 할 수 있어서 재밌었다.

'Spring' 카테고리의 다른 글

FilterChain을 2번 호출한다고?  (1) 2024.09.14
PermitAll의 함정  (0) 2024.08.16
테스트 환경 설정하기  (1) 2024.08.08

+ Recent posts