@Controller은 전통적인 Spring 컨트롤러에 사용되며, 프레임워크의 일부로 오랫동안 사용되어 왔다.
Spring 4.0에서는 RESTful 웹 서비스를 더 쉽게 만들 수 있도록 @RestController 애노테이션을 도입했다. 이 애노테이션은 @Controller와 @ResponseBody를 결합하여, 컨트롤러 클래스의 모든 요청 처리 메서드에 @ResponseBody를 붙일 필요가 없도록 한다.
controller - view, restcontroller - 데이터
@Controller
전통적인 컨트롤러는 @Controller 애노테이션을 사용하여 주석을 달 수 있다. 이 애노테이션은 단순히 @Component 클래스의 특수화된 형태로, classpath scanning을 통해 구현 클래스를 자동으로 감지할 수 있게 해준다.
일반적으로 요청 처리 메서드에는 @RequestMapping 애노테이션과 함께 @Controller를 사용한다.
- 클라이언트는 URI 형식으로 웹 서비스에 요청을 보낸다.
- DispatcherServlet이 요청을 처리할 대상을 찾는다.
- HandlerAdapter을 통해 요청을 처리할 Controller로 위임한다.
- Controller은 요청을 처리한 후 객체를 반환한다.
- 반환되는 객체는 Json으로 Serialize되어 사용자에게 반환된다.
컨트롤러를 통해 객체를 반환할 때는 일반적으로 ResponseEntity를 감싸서 반환을 한다.
객체를 반환하기 위해서는 viewResolver 대신에 HttpMessageConverter가 동작한다. HttpMessageConverter에는 여러 Converter가 등록되어 있고, 반환해야 하는 데이터에 따라 사용되는 Converter가 달라진다. 단순 문자열인 경우에는 StringHttpMessageConverter가 사용되고, 객체인 경우에는 MappingJackson2HttpMessageConverter가 사용되며, 데이터 종류에 따라 서로 다른 MessageConverter가 작동하게 된다.
Spring은 클라이언트의 HTTP Accept 헤더와 서버의 컨트롤러 반환 타입 정보를 조합해 적합한 HttpMessageConverter를 선택하여 이를 처리한다. MessageConverter가 동작하는 시점은 HandlerAdapter와 Controller가 요청을 주고 받는 시점이다. 그림의 4번에서는 메세지 → 객체로, 6번에서는 객체 → 메시지로 변환하는데 MessageConverter가 사용된다.
예제
@Controller
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping(value = "/users")
@ResponseBody
public ResponseEntity<User> findUser(@RequestParam String userName){
return ResponseEntity.ok(userService.findUser(userName));
}
@GetMapping(value = "/users/detailView")
public String detailView(Model model, @RequestParam String userName){
User user = userService.findUser(userName);
model.addAttribute("user", user);
return "/users/detailView";
}
}
- findUser는 User 객체를 ResponseEntity로 감싸서 반환하고 있고, User을 json으로 반환하기 위해 @ResponseBody 어노테이션을 붙여주고 있다.
- detailView 함수에서는 View를 전달해주고 있기 때문에 String을 반환값으로 설정해주었다.
이렇게 데이터를 반환하는 RestController와 View를 반환하는 Controller은 분리하여 작성하는 것이 좋다.
@RestController
@RestController는 controller의 특수한 버전이다. 이 애노테이션은 @Controller와 @ResponseBody를 포함하며 결과적으로 컨트롤러 구현을 단순화한다.
RestController의 주용도는 Json형태로 객체 데이터를 반환하는 것이다. 데이터를 응답으로 제공하는 REST API를 개발할 때 주로 사용하며 객체를 ResponseEntity로 감싸서 반환한다.
- 클라이언트는 URI 형식으로 웹 서비스에 요청을 보낸다.
- DispatcherServlet이 요청을 처리할 대상을 찾는다.
- HandlerAdapter을 통해 요청을 처리할 Controller로 위임한다.
- Controller은 요청을 처리한 후 객체를 반환한다.
- 반환되는 객체는 Json으로 Serialize되어 사용자에게 반환된다.
예제
@RestController
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping(value = "/users")
public User findUser(@RequestParam String userName){
return userService.findUser(userName);
}
@GetMapping(value = "/users")
public ResponseEntity<User> findUserWithResponseEntity(@RequestParam String userName){
return ResponseEntity.ok(userService.findUser(userName));
}
}
findUser는 User 객체를 그대로 반환하고 있다. 이러한 경우의 문제는 클라이언트가 예상하는 HttpStatus를 설정해줄 수 없다는 것이다.
예를 들어 어떤 객체의 생성 요청이라면 201 CREATED를 기대할 것이지만 객체를 그대로 반환하면 HttpStatus를 설정해줄 수 없다. 그래서 findUserWithResponseEntity처럼 객체를 상황에 맞는 ResponseEntity로 감싸서 반환해주어야 한다.
참조
https://www.baeldung.com/spring-controller-vs-restcontroller
https://mangkyu.tistory.com/49
'Spring' 카테고리의 다른 글
RESTful API (0) | 2024.07.09 |
---|---|
[Spring] JdbcTemplate (0) | 2024.07.09 |
[Spring] JDBC (0) | 2024.07.09 |
[Spring] Spring vs Spring Boot (0) | 2024.07.09 |
[Spring] Maven과 Gradle (0) | 2024.07.08 |