본문 바로가기
# Study/Spring

[Spring] @Controller, @RestController 차이

by Jiy0ung 2025. 1. 21.

보통 웹에서 화면 전환 없이 이루어지는 동작들은 대부분 비동기 통신이다. 비동기 통신을 하기 위해서는 클라이언트가 서버로 요청 메시지의 body에 데이터를 담아서 보내야 하고, 서버도 클라이언트에 응답하기 위해서 body에 데이터를 담아 보내야한다.

이 때의 body를 각각 Request Body와 Response Body라고 부르는데, 이러한 body에 담기는 데이터 형식은 JSON이다.

 

@RequestBody 어노테이션은 이러한 비동기 통신에서 쓰이는 body안의 데이터(JSON)를 자바 객체(VO)로 변환해주는 어노테이션이고, @ResponseBody 어노테이션은 보내려는 자바 객체(VO)를 데이터객체(JSON)로 바꿔 body안에 넣어주는 어노테이션이다.

 

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

전통적인 Spring MVC의 컨트롤러인 @Controller와 Restful 웹서비스의 컨트롤러인 @RestController의 주요 차이점은 HTTP Response Body가 생성되는 방식이다.


1. @Controller

[Controller로 View를 반환]

Spirng MVC의 Controller인 @Controller는 주로 view를 반환하기 위해 사용한다.

 

동작과정

1) Client에서 보낸 요청은 DispatcherServlet을 거쳐 HandlerMapping을 통해 Controller를 찾고 요청을 수행하게 된다.

2) Controller는 받은 요청을 처리하고 난 뒤 ViewName을 반환한다.

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

[Controller로 Data를 반환]

Data를 반환하는 경우 ResponseEntity(HttpStatus + HttpHeaders + HttpBody) 형태의 데이터로 사용해야 하는데,

@ResponseBody 어노테이션을 사용하면 JSON 형태의 데이터도 반환할 수 있다.

 

동작과정

1) Client에서 보낸 요청은 DispatcherServlet을 거쳐 HandlerMapping을 통해 Controller를 찾고 요청을 수행하게 된다.

2) Controller는 받은 요청을 처리하고 난 뒤 객체를 반환한다.

3) 반환되는 객체는 JSON으로 Serialize되어 사용자에게 반환된다. 

 

[예제 코드]

@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/detail")
    public String detailView(Model model, @RequestParam String userName){
        User user = userService.findUser(userName);
        model.addAttribute("user", user);
        return "/users/detail";
    }
}

 

[참고]
@Controller를 통해 객체를 반환할 때, 일반적인 경우엔 ResponseEntity로 감싸서 반환한다.
그리고 객체를 반환할 때는 View를 반환할 때와 마찬가지로 ViewResolver 대신 HttpMessageConverter가 동작한다. HttpMessageConverter에는 여러 Converter가 등록되어 있으며, 반환해야 하는 데이터의 종류에 따라 Converter도 그에 맞게 달라진다.
예를 들어, 단순 문자열인 경우에는 StringHttpMessageConverter가 사용되고, JSON 객체의 경우에는 MappingJackson2HttpMessageConverter가 사용된다. Spring은 클라이언트의 HTTP Accept Header와 서버의 Controller 반환 타입 정보를 조합해 적합한 HttpMessageConverter를 선택하여 처리한다.

 

2. @RestController

@RestController는 @Controller에 @ResponseBody가 추가된 것이다. 당연하게도 RestController 주용도는 JSON 형태로 객체 데이터를 반환 하는 것이다. 객체를 ResponseEntity로 감싸서 반환하는 것으로 동작 과정도 @Controller에 @ResponseBody를 붙인 것과 동일하다.

 

동작과정

1) Client에서 보낸 요청은 DispatcherServlet을 거쳐 HandlerMapping을 통해 Controller를 찾고 요청을 수행하게 된다.

2) Controller는 받은 요청을 처리하고 난 뒤 객체를 반환한다.

3) 반환되는 객체는 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를 설정해줄 수 없다.

그래서 객체를 상황에 맞는 ResponseEntity로 감싸서 반환해주어야 한다.