본문 바로가기

Programming/Java & JSP & Spring

[Spring] @ModelAttribute vs @RequestParam

@ModelAttribute와 @RequestParam의 차이

우선 파라미터로 받는 부분만 말하자면, RequestParam은 1:1로 받는 반면,

ModelAttribute는 도메인 오브젝트나 DTO 요청 파라미터를 바인딩해서 한번에 받는다.

 

@RequestParam과 단지 바인딩의 차이만 있는 것은 아니다. 검증 작업이 추가적으로 진행된다.

RequestParam은 파라미터 타입이 잘못 들어오면 400 Bad Request를 날리지만,

ModelAttribute는 타입 변환에 실패하더라도 작업은 계속 진행된다.

 

주의할 점

위에서 설명했듯이 ModelAttribute는 타입변환에 실패하더라도 작업은 진행된다.

단지 타입 변환 중에 발생한 예외가 BindException 타입의 오브젝트에 담겨서 컨트롤러로 전달될 뿐이다.

따라서, 사용자의 입력값에 오류가 있을 때는 이에 대한 처리를 컨트롤러에게 맡겨야 한다.

 

따라서 @ModelAttribute를 통해 폼의 정보를 전달 받을 때는 Errors 또는 BindingResult파라미터를 함께 사용해야한다. → 타입이 일치하지 않으면 예외를 던진다.

(주의할점은 BindingResult파라미터는 @ModelAttribute 파라미터 뒤에 와야한다.)

Model에 ModelAttribute를 추가하면 BindingResult도 자동으로 추가된다.

 

또한 주의할 점은 ModelAttributes는 RequestMapping어노테이션보다 먼저 객체 초기화를 한 후에, 인자를 하나씩 매핑해서 받아들이는 형식이다.

(따라서 코틀린에서 객체안의 변수를 val키워드를 사용한다면, val로 초기화가 되어서 인자를 못받아들인다. -> 결론적으로 ModelAttribute를 사용하는 객체안의 변수는 var 키워드를 사용하자)

 

생략가능

@RequestParam과 동일하게 어노테이션을 생략할 수 있다. 하지만 작성하는 것을 권장한다. 이유는 위와 동일하다.

그러면 Spring은 어떻게 두개의 어노테이션을 생략하는데도 무엇을 보고 RequestParam 인지 ModelAttribute 인지를 판단할까?

그건 단순하게 String, int, long 등의 단순한 타입이라면 RequestParam이라고 판단하고 그게 아니라 모델 경우에는 @ModelAttribute로 판단한다.

@ModelAtrribute는 파라미터 뿐만 아니라 컨트롤러 클래스의 일반 메소드에도 부여할 수 있다.

@ModelAttributes 메소드가 생성하는 오브젝트는 클래스 내의 다른 컨트롤러 메소드의 모델에 자동으로 추가된다.