티스토리 뷰

Spring에서 Controller를 지정해주는 어노테이션은 크게 2가지가 있습니다. @Controller@RestController입니다.

두 어노테이션의 차이점은 HTTP ResponseBody가 생성되는 방식에 있습니다.


@Controller

Controller로 View 반환하기

전통적인 Spring MVC의 컨트롤러인 @Controller는 주로 View를 반환하기 위해 사용합니다.

Controller는 아래와 같은 Process에 의해 동작합니다.

1. Client가 URI 형식으로 요청을 보냅니다.

2. Dispatcher Servlet이 요청을 처리할 대상을 찾습니다.

3. Handler Adapter가 요청을 Controller로 전송합니다.

4. Controller는 요청을 처리한 후에 ViewName을 반환합니다.

5. Dispatcher Servlet은 View Resolver를 통해 ViewName에 해당하는 View를 찾아 반환합니다.

 

이 때, View를 렌더링하기 위해 View Resolver가 사용되고, View Resolver 설정에 맞게 View를 찾아 렌더링합니다.

 

 

Controller로 Data 반환하기

Controller로 요청한 작업이 끝난 후 View를 반환하지 않고 Data를 반환해야 하는 경우가 있습니다. 그 때 @ResponseBody를 사용합니다. 이를 통해 Controller도 Json 형태의 데이터를 반환할 수 있습니다.

  1. Client는 URI 형식으로 웹 서비스에 요청을 보냅니다.
  2. DispatcherServlet이 요청을 처리할 대상을 찾습니다.
  3. HandlerAdapter을 통해 요청을 Controller로 전송합니다.
  4. Cotroller는 요청 처리 후 객체를 반환합니다.
  5. 반한되는 객체는 JSON으로 Serialize되어 사용자에게 반환됩니다.

 

 

Controller를 통해 객체를 반환할 때 ResponseEntity로 감싸서 반환합니다. 그리고 객체를 반환하기 위해서는 ViewResolver가 아닌 HttpMessageConverter가 동작합니다. 

HttpMessageConverter는 여러 Converter가 등록되어 있고, 반환해야 하는 데이터에 따라 사용되는 Converter가 다릅니다.

  • 단순 문자열: StringHttpMessageConverter
  • 객체: MappingJackson2HttpMessageConverter

 

 

Spring은 클라이언트의 Http Accept 헤더서버의 컨트롤러 반환 타입 정보. 둘을 조합하여 적합한 HttpMessageConverter를 선택하여 이를 처리합니다.

MessageConverter가 동작하는 시점은 Handler Adapter와 Controller가 요청을 주고 받는 시점입니다.

 

 

@Controller 예제 코드

@Controller
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @GetMapping(value = "/users")
    public @ResponseBody ResponseEntity<User> findUser(@RequestParam("userName") String userName){
        return ResponseEntity.ok(userService.findUser(user));
    }
    
    @GetMapping(value = "/users/detailView")
    public String detailView(Model model, @RequestParam("userName") String userName){
        User user = userService.findUser(userName);
        model.addAttribute("user", user);
        return "/users/detailView";
    }
}

@RestController

@RestController@Controller에 @ResponseBody가 추가된 것 입니다.

이 @RestController의 주 용도는 JSON 형태로 객체 데이터를 반환하는 것입니다.

이러한 이유로 REST API를 개발할 때 주로 사용하며 객체를 ResponseEntity로 감싸서 반환합니다. 

@Controller에 @RequestBody를 붙인 것과 동일합니다.

  1. Client는 URI 형식으로 웹 서비스에 요청을 보내게 됩니다.
  2. DispatcherServlet이 요청을 처리할 대상을 찾습니다.
  3. HandlerAdapter을 통해 요청을 Controller로 위임합니다.
  4. Controller는 요청을 처리한 후 객체를 반환합니다.
  5. 반환 되는 객체는 JSON로 Serialize되어 사용자에게 반환합니다.

 

 

@RestController 예제 코드

@RestController
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @GetMapping(value = "/users")
    public User findUser(@RequestParam("userName") String userName){
        return userService.findUser(user);
    }

    @GetMapping(value = "/users")
    public ResponseEntity<User> findUserWithResponseEntity(@RequestParam("userName") String userName){
        return ResponseEntity.ok(userService.findUser(user));
    }
}

 

findUser()는 User 객체 그대로 반환하고 있습니다.

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

예를 들어, 어떤 객체 생성 요청이라면 201 CREATED를 기대할 것 이지만 객체를 그대로 반환하면 HttpStatus를 설정해줄 수 없게 됩니다. 그래서 객체를 상황에 맞는 ResponseEntity로 감싸서 반환해주어야 합니다.

공지사항
최근에 올라온 글
Total
Today
Yesterday