@Controller
과 @RestController
에 대해 알아볼거다. 다만 별로 다룰 내용이 많진 않다.@Controller
Sping framework의 유서깊은, MVC의 controller을 나타내는 annotation이다. 자주 언급했지만 @Component
의 하위 annotation이고 AOP 측면에서 활용이 가능하다는 것 말고 특별한 기능을 가지진 않는다. 물론 이 AOP 측면을 활용해서 DispatcherServlet
이 request를 handle할 controller을 탐지할 수 있는거지만 말이다.
뭐 내부동작은 저렇고, 어쨌든 프로그램에서 MVC의 controller 역할을 하는 영역을 annotate하는 것이라고만 기억해도 충분하다.
이 때 보통 @RequestMapping
계열의 annotation을 같이 사용한다. 밑은 간단한 예제.
@Controller
@RequestMapping("books")
public class SimpleBookController {
@GetMapping("/{id}", produces = "application/json")
public @ResponseBody Book getBook(@PathVariable int id) {
return findBookById(id);
}
private Book findBookById(int id) {
// ...
}
}
@RequestMapping
@RequestMapping
은 저 경로로 요청이 오는 것들에 대해 처리한다는 것을 지칭한다는 annotation인 것은 이미 봤다. 그런데 지금까지 본 예제는 method 레벨에서 사용했었는데 위의 경우 class level에서 @RequestMapping
을 하고 있다. 게다가 앞에 slash도 없다(...)
먼저 후자부터 설명하자면, 사실 @RequestMapping
앞에 slash를 넣을 필요는 없다. 자동으로 앞에 추가해주기 때문. 관련 stackoverflow 글
그럼 위의 경우 @RequestMapping("books")
는 사실 @RequestMapping("/books")
인 것인데, 저게 무슨 의미냐면 하위 @RequestMapping
계열들의 앞에 /books
가 달려있다는걸 나타내는 것이다. 즉 이 controller은 /books
하위의 request들만 일단 처리한다는 것을 의미. 위의 GetMapping
의 경우 /books/{id}
를 실제로 의미한다는 것이다.
@PathVariable
그저 mapping측에서 쓴 url의 {}
로 둘러싸인 부분 (URI template variable)이 동일 이름의, 이 annotation으로 설정된 parameter에 들어가야 한다는 것을 의미한다. 이 때 자동으로 형변환이 된다는 것도 재밌는 부분.
이름을 꼭 똑같이 할 필요는 없고, name
property를 줘가지고 mapping하는 것도 가능하며 꼭 필요하다는 뜻의 required
property도 설정하는 것이 가능하다.
@ResponseBody
HTTP request를 할 때 실제 request/response 관련 내용물이 'body'의 영역에 있다는 것은 알고 있을 것이다. 반환한 객체 내용물을 그 body 내용물로 변환해가지고 전달하라고 지칭 할 때 저 annotation을 사용한다.
HttpMessageConverter
그러면 잠깐, 어떻게 자기 알아서 Book
이라는 instance를 적절한 HTTP response body로 변환하는거냐고요? 바로 HttpMessageConverter
이라는 녀석이 담당합니다. 이에 관한 Baeldung 글
여기서 자세히 다루진 않을건데, 일단 Spring MVC 활용시 (@EnableWebMvc
활용시) 기본적으로 등록되는 HttpMessageConverters
들이 존재하고 이 중에 Jackson Library라는 것이 존재한다. 얘가 Spring의 경우 이를 사용하려면 classpath에 Jackson을 넣어야 하고 Spring boot는 web starter에 이게 기본으로 포함되어 있다. 이게 자동으로 @ResponseBody
가 annotate된 @RequestMapping
annotated 메서드에서 반환한 class instance를 JSON으로 변환해준다. (xml로 변환하는건 따로 있다.) 그러면 그게 그대로 HTTP response body로 들어가면 된다.
당연히 customize하는 방법도 있는데 그건 baeldung 글을 참고하도록 하자.
@RestController
얘는 좀 나중에 등장한 Spring의 annotation인데, MVC기반으로 REST-ful API를 개발할 때 좀 더 편리하게 개발하라고 만든 annotation이다.
그냥 @Controller
과 @ResponseBody
를 합한거다. class에 그러면 @Responsebody
가 설정되는 건데 이러면 그 안의 모든 @RequestMapping
annotated 메서드가 @Responsebody
가 달려있다고 가정한다.
REST-ful API이면 분명 모든 @RequestMapping
annotated 메서드에 @ResponseBody
를 붙여야 할텐데 이를 처리해주는 annotation이라고 볼 수 있다.
@RestController
@RequestMapping("books-rest")
public class SimpleBookRestController {
@GetMapping("/{id}", produces = "application/json")
public Book getBook(@PathVariable int id) {
return findBookById(id);
}
private Book findBookById(int id) {
// ...
}
}