[Spring] @Controller와 @RestController 차이

🔹 @Controller와 @RestController

Spring Framework를 사용하여 개발을 한다면, @Controller와 @RestController를 빈번하게 사용하게 된다.

 

@Controller와 @RestController은 Spring에서 컨트롤러를 지정해 주기 위한 어노테이션이다.

전통적인 Spring MVC의 컨트롤러인 @Controller와 Restful 웹 서비스의 컨트롤러인 @RestController의

주요 차이점은 HTTP Response Body가 생성되는 방식이다.

 

@Controller의 역할은 Model 객체를 만들어 데이터를 담고 View를 반환하는 것이고,

@RestController는 단순히 객체만을 반환하고 객체 데이터는 JSON 또는 XML 형식으로 HTTP 응답에 담아 전송한다.

 

물론 @Controller도 @ResponseBody를 사용해서 만들 수 있지만 이러한 방식은 Restful 웹 서비스의 기본 동작이기 때문에

Spring은 @Controller와 @ResponseBody의 동작을 조합한 @RestController를 도입했다.

@Controller
@ResponseBody
public class Controller {
	business logic ...
}

@RestController
public class RestFulController {
	business logic ...
}

위 코드는 Spring MVC에서 동일한 동작을 하며,

@RestController는 @Controller와 @ResponseBody의 동작을 하나로 결합한 컨트롤러라고 볼 수 있다.

 

🔹 @Controller

[ Controller - View ]

@Controller는 주로 View를 반환하기 위해 사용된다.

[ 동작 방식 ]

1. Client는 URI 형식으로 웹 서비스에 요청을 보낸다.

2. Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.

3. DispatcherServlet은 ViewResolver를 통해 ViewName에 해당하는 View를 찾아 사용자에게 반환한다.

 

[ Controller - View ]

Spring MVC의 컨트롤러에서도 Data를 반환해야 하는 경우도 있다.

데이터를 반환하기 위해 @ResponseBody 어노테이션을 사용해 주면, 이를 통해 Controller도 JSON 형태로 데이터를 반환할 수 있다.

[ 동작 방식 ]

1. Client는 URI 형식으로 웹 서비스에 요청을 보낸다.

2. Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.

3. @ResponseBody를 사용하여 Client에게 JSON 형태로 데이터를 반환한다.

 

[ @Controller 예제 코드 ]

@Controller
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    
    @GetMapping("/users")
    @ResponseBody
    public ResponseEntity<User> findUser(@RequestParam String userName){
        return ResponseEntity.ok(userService.findUser(userName));
    }
    
    @GetMapping("/users/detailView")
    public String detailView(Model model, @RequestParam String userName){
        User user = userService.findUser(userName);
        model.addAttribute("user", user);
        return "/users/detailView";
    }
}

@Controller는 보통 View를 반환하지만

위와 같이 @ResponseBody 어노테이션을 사용하면 객체를 반환할 수 있다.

 

참고로 View를 반환하는 Controller와 객체를 반환하는 RestController는 분리하여 작성하는 것이 좋다.

 

@RequestParam은 Request Header 안의 파라미터를 Mapping 해주는 어노테이션이다.

 

🔹 @RestController

@RestController는 Spring MVC Controller에 @ResponseBody가 추가된 것이다.

이로써 @RestController는 JSON 형태로 객체 데이터를 반환한다.

[ 동작 방식 ]

1. Client는 URI 형식으로 웹 서비스에 요청을 보낸다.

2. Mapping 되는 Handler와 그 Type을 찾는 DispatcherServlet이 요청을 인터셉트한다.

3. RestController는 해당 요청을 처리하고 데이터를 반환한다.

 

[ @RestController 예제 코드 ]

@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;
    
    @GetMapping("/users")
    public User findUser(@RequestParam String userName) {
        return userService.findUser(userName);
    }
    
    @GetMapping("/users")
    public ResponseEntity<User> findUserWithResponseEntity(@RequestParam String userName){
        return ResponseEntity.ok(userService.findUser(userName));
    }
}

findUser는 User 객체를 그대로 반환하고 있다.

이러한 경우 클라이언트가 예상하는 HttpStatus를 설정해 줄 수 없다는 문제가 있다.

따라서 REST API를 개발한다면 객체를 상황에 맞는 ResponseEntity로 감싸서 반환해 주어야 한다.



 

 

 

📃 reference