@RequestParam을 사용하며 겪은 실수를 공유해 보았습니다.
먼저 간단하게 @RequestParam에 대해 알아보자면 Spring MVC에서 쿼리 스트링 정보를 쉽게 가져오는데 사용할 수 있습니다.
예를 들어 /user?name=hellozin
이라는 요청에서 "hellozin"
이라는 값을 가져오기 위해 아래와 같이 컨트롤러를 구현하면
@GetMapping("/user")
@ResponseBody
public String getUserName(@RequestParam String name) {
return name;
}
@RequestParam을 통해 name 변수에 "hellozin"
이라는 문자열을 받아 처리할 수 있습니다.
하지만 저대로 사용하게 되면 요청 쿼리 스트링에 "name" 필드가 없을 경우 즉, /user
와 같이 @RequestParam이 적용된 필드가 없으면 Bad Request, Required String parameter 'name' is not present
라는 예외를 발생시킵니다.
이를 해결하기 위해 @RequestParam(required = false)
와 같이 required 속성을 추가하면 해당 필드가 쿼리스트링에 존재하지 않아도 예외가 발생하지 않습니다.
다만 주의할 점은 Argument Resolver에 등록한 CustomArgument에 @RequestParam(required = false)
을 적용하면 Spring이 해당 Argument를 무시한다는 것입니다. 이미 스프링에 익숙하신 분들은 당연하다는 생각이 드시겠지만 혹시 저와 같은 실수를 겪으신 분들을 위해 정리해 보겠습니다.
일반적으로 CustomArgument는 다음과 같이 정의됩니다.
여기까지 하면 해당 Argument를 처리할 때 HandlerMethodArgumentResolver에 정의한 resolveArgument()
메소드에 위임해주게 됩니다.
하지만 다음과 같이 CustomArgument에 @RequestParam(required=false)
를 적용하면
@GetMapping("/user")
@ResponseBody
public String getUserName(@RequestParam(required = false) CustomUser user) {
return user.getName();
}
HandlerMethodArgumentResolver가 처리 하는 과정에서 아까 등록한 resolver가 불리지 않고 처리가 종료됩니다. 이 동안 어떠한 에러나 경고도 주어지지 않아 실수를 파악하는데 오랜 시간이 걸렸습니다.
결국 Map<K,V> 형태나 CustomArgument의 경우 required=false
속성 없이도 예외가 발생하지 않기 때문에 직접 null 체크나 원하는 처리를 할 수 있습니다.
정말 당연하고 쉬운 내용이지만 쉽게 발견하지 못한 문제였기 때문에 포스팅 해보았습니다. 틀린 내용이 있다면 언제든지 지적 부탁드립니다.