Spring

@RequestParam 사용 시 Null에 대한 고민 정리

ybs 2021. 9. 20. 17:27
반응형

RequestParam 애노테이션에서 required = false 인 경우, 값이 없을 때 null 로 채워진다.

RequestParamMethodArgumentResolver 에서 request.getParameterValues(name) 가 null 이고 결국 리턴되는 arg는 null 이 된다.

public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver implements UriComponentsContributor {

	@Nullable
	protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
    	...
        
    	if (arg == null) {
            String[] paramValues = request.getParameterValues(name);
            if (paramValues != null) {
                arg = paramValues.length == 1 ? paramValues[0] : paramValues;
            }
        }

    return arg;
}

 

cf) primitive type 이면 "cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type." 메세지와 함께 IllegalStateException 이 발생한다.

 

그런데 이전 글 에서 설명했듯이 request body를 여러번 읽는 경우 컨트롤러에서 POST + @RequestParam 일 때 form data 를 읽어오지 못하는 문제가 있다. 

 

그러므로 ybs 변수값이 null 이라고 해도 추가적인 확인이 더 필요하다(POST + form data body 인지).

나는 그 작업을 아래와 같이 만들었는데 getYbs 메서드를 통해 정확한 ybs 값을 얻고 기존에 있는 ybs 변수를 재활용 했다(이후 프로세스 호환을 위해).

@RequestMapping(value = "/test10")
public String test(
	HttpServletRequest request,
	@RequestParam(value = "ybs", required = false) String ybs) {

	ybs = getYbs(request, ybs);
	return "hello";
}

private String getYbs(HttpServletRequest request, String ybs) {
	if (isNotBlank(ybs)) {
    	return ybs;
    }

	if ("POST".equalsIgnoreCase(request.getMethod()) &&
		request.getContentType().equals("application/x-www-form-urlencoded") &&
		request.getContentLength() > 0 &&
		isBlank(request.getQueryString())
	) {
		// body 를 얻고 ybs 값 파싱 해서 리턴
        
        // 방어로직에 걸리면 null 리턴
	}

	return null;
}

 

이전에 쓴 메서드 리턴에 대한 고민 글 에서도 한번 다뤘지만, 그동안 나는 메서드에서 null 리턴 보다는 예외나 Optional 리턴을 우선적으로 고려했다. 그런데 지금 같은 상황에서는 null 리턴이 더 자연스럽다고 생각한다. 그 이유는 RequestParamMethodArgumentResolver 에서 애당초 null을 리턴해주기 때문이고, 또 getYbs 메서드 결과를 ybs 변수에 다시 할당하기 때문이다. 물론 다른 변수를 쓸 수 있지만 오히려 그게 더 헷갈리게 한다고 생각한다.

반응형