대체로 Spring으로 애플리케이션을 구성한다면, Controller에서 값을 받아서 비즈니스 로직을 처리하도록 넘기게 된다. 이때, 이러한 Method Parameter를 어떻게 받는지에 대해서 이야기해보고자 한다.
어찌보면 간단한 개념을 왜 정리하지? 싶을 수도 있으나, 공식 문서를 보게되면 굉장히 많은 Method Argument를 제공하고 있다는 것을 볼 수 있다. 그렇기에, 일단 지금 쓰는 것을 제대로 소화하고, 그 이유를 이해한 뒤에 추가적으로 다른 개념들을 이해하면 더 좋을 것 같아서 정리해본다.
@RequestParam
@Controller
@RequestMapping("/pets")
public class EditPetForm {
// ...
@GetMapping
public String getCatInfo(@RequestParam("catName") String catName, Model model) {
Cat cat = this.clinic.getCat(catName);
model.addAttribute("cat", cat);
return "catInfo";
}
// ...
}
위의 예시는 catName을 가지고 cat을 가져오도록 @Request Param을 설정한 경우이다.
@RequestParam에서는 아래와 같은 세 타입의 옵션을 추가할 수 있다. (위의 예시는 name이 추가된 형태) 아래에 나와있듯이 기본 required 값이 true이기 때문에 만약 해당 값이 안들어가있다면 400에러가 바로 발생하게 된다.
이름 | 타입 | 설명 |
name, value (Alias for name) | String | 파라미터 이름 |
required | bollean | 해당 파라미터의 필수 여부 (기본값 = true) |
defaultValue | String | 해당 파라미터 기본값 |
@RequestBody
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
// ...
}
파라미터를 객체로 받게 되며, 이는 MessageConverter를 통해서 자바의 객체로 변환된다.
이로 인해서 Request가 가지는 특징은 다음과 같다.
1. POST요청과 함께 사용되어야한다.
: MessageConverter는 HTTP 요청의 Body내용을 자바의 객체로 변환시킨다. GET방식의 메서드는 애초에 Body가 존재하지 않기때문에 에러를 발생시킨다.
2. JSON 데이터받을 때 주로 사용
: JSON이나 XML과 같은 데이터를 MessageConverter를 이용해서 자바의 객체로 변환한다.
3. Setter가 없어도 된다.
: @ModelAttribute는 자바의 객체로 1:1 매핑이기에 Setter가 필수지만 @RequestBody는 MessageConverter를 통한 자바의 객체로 변환이기때문에 Setter가 없어도 괜찮다.
- 다만 직렬화를 위해 기본 생성자는 필수다.
- 또한 데이터 바인딩을 위한 필드명을 알아내기 위해 getter나 setter 중 1가지는 정의되어 있어야 한다.
여담을 조금 적자면 나는 스프링을 처음 공부할때 일단 뭔지도 모르고 쓰다보니 GET 메서드에서 해당 어노테이션을 썼다가 한동안 헤멘적이 있었다.
@ModelAttribute
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) {
// ...
}
@RequestParam과 비슷한데, 차이점은 1:1로 하나씩 파라미터를 받을 때는 @RequestBody, 여러 파라미터들을 받아서 자바의 객체로 매핑하는 경우는 @ModelAttribute 라고 한다. 또한, @RequestBody와는 달리 Setter가 필수적으로 요구된다고 한다.
공식문서에 따르면, 위의 Pet 인스턴스의 경우 다음 방법중 하나로 소싱된다고 한다.
- @ModelAttribute메서드 에 의해 추가되었을 수 있는 모델에서 검색
- 모델 특성이 @SessionAttributes 주석에 나열된 경우 HTTP 세션에서 검색
- 모델 속성 이름이 경로 변수 또는 요청 매개변수와 같은 요청 값의 이름과 일치 하는 곳을 검색
- 기본 생성자로 인스턴스화
- 서블릿 요청 매개변수와 일치하는 인수를 사용하여 "기본 생성자"를 통해 인스턴스화
개인적으로 ModelAttribute는 거의 사용해본 적이 없던터라, @RequestBody와 @ModelAttribute를 비교한 좋은 테코블 포스팅도 함께 공유한다. 링크
어노테이션이 없으면?
어노테이션이 없어도 값을 받을 수 있다. 다만, 이 경우에는 변수명과 동일한 파라미터 값만을 받을 수 있으며, String과 Long 타입은 @RequestParam으로 취급하지만 그 이외에는 @ModelAttribute로 취급하게 된다.
@PostMapping("/getWithdoutAnnotation");
public void getWithdoutAnnotation(String id, UserVO user){
log.info("get parameter" + id);
log.info("get parameter" + user.getId());
}
참고자료
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-methods
'프로그래밍 공부 > Spring' 카테고리의 다른 글
[Spring] 의존 자동 주입, @AutoWired (2) | 2022.05.07 |
---|---|
[Spring] @Component vs @Bean (4) | 2022.05.06 |
[Spring] Java Bean vs Spring Bean (1) | 2022.04.26 |
[Spring] @ExceptionHandler 와 @ControllerAdvice (0) | 2022.04.26 |
[Spring] DI(Dependency Injection, 의존성 주입)이란? (0) | 2022.04.25 |