본문 바로가기

웹 프로그래밍/Spring Framework

[SpringMVC] @ModelAttribute @RequestBody 에 대해서.

이슈

Spring MVc에서 파라미터 앞에 @ModelAttribute와 @RequestBody를 쓰는 코드들이 많다. 하지만 바인딩이 안되는 경우 에러를 찾지 못하는 난감한 경우가 있는데 이런 경우에 대한 명확한 해답을 아래 제시한다.



설명

Client에서 Server로 Ajax call을 날렸다. 분명히 날렸음에도 인자값은 전달되지않고 Null Pointer Exception을 발생시켜버린다. 이유가 무엇일까?


1. GET/POST 등은 각각의 다른 방식으로 데이터를 서버로 전송한다. 

GET/POST는 프로토콜 차이로 인해서 각각의 다른 데이터 방식의 데이터를 담아 전송한다. 중요한건 GET방식은 URL에 데이터를 담아 전송하며 1차원 데이터밖에 담지 못한다(2차원 배열, 객체속 객체 등등은 불가능하다.) 따라서 검색조건 수준의 데이터를 담는게 옳바르다, POST 방식은 Request 의 Body에 데이터를 담는데 이 경우 JSON, 다차원 데이터를 담을 수 있다. 객체속 JSON 리스트라던지 여러가지 데이터가 가능하다. 


자 그럼 만약 당신이 컨트롤러를 작성할 때 GET방식 메서드의 파라미터 앞에 @RequestBody 어노테이션을 붙혔다. 그럼 데이터 바인딩이 가능할까? 


 "GET 방식 프로토콜은 Request 패킷에 Body가 존재하지 않는다. 따라서 데이터를 가져올 수 없다. "


다른 케이스로, 어떤 개발자는 당연히 자동으로 바인딩해주는 줄 알고 파라미터에 @RequestBody 어노테이션을 쓰지 않았다. 하지만 테스트를 해보니 'java.lang.NullPointerException'가 개발자를 반겼다. 어디서부터 문제인가?


 "@RequestBody 어노테이션으로 명시해주지 않은 파라미터는 GET방식으로 데이터를 바인딩 시키기 때문에 결과적으로 NULL이 들어간다. POST방식은 Body에 데이터가 들어가 있기 때문이다."



결론 : GET방식일 떄는 @RequestBody를 명시하지 않아야하고, POST방식일떄는 반드시 명시해야한다.



2. @ModelAttribute는 어디에 사용해야할까?

@ModelAttribute 어노테이션은 Parameter에 쓸 경우 받아오고자하는 데이터의 이름을 지정하여 해당 데이터만을 가져온다. 만약 당신이 { name : '뼈발자', comment : '인생은 최건우처럼' } 이라고 ajax-data에 넣었다고 치고 컨트롤러에 @ModelAttribute('comment') String comment 라고 하면 comment속엔 '인생은 최건우처럼'만을 받아온다. 


결론 : @ModelAttribute는 받아오는 데이터를 '지정'한다.