Skip to main content

@Controller와 @RestController 차이점

Spring에서 클래스에 컨트롤러를 지정해주기 위한 어노테이션은 @Controller@RestController가 있습니다. ControllerHTTP ResponseBody가 생성되는 방식이고 @Controller + @ResponseBody 조합이 @RestController라고 할 수 있습니다.

@Controller란?

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

@Controller
public class TestController {

@RequestMapping(value = "api/test", method = {RequestMethod.POST})
public String test() {
return "test";
}
}

아래 과정을 통해서 Spring MVC ContainerClient 요청으로부터 View를 반환합니다.

과정

  1. ClientURL 형식으로 요청을 보낸다.
  2. DispatcherServlet이 요청을 위임할 Handler Mapping을 찾는다.
  3. Handler Mapping을 통해 요청을 Controller로 위임한다.
  4. Controller는 요청을 처리한 후 View Name에 해당하는 View를 찾아서 Client한테 반환한다.
  5. Handler Adopter는 이걸 DisparcherServlet에게 반환한다.
  6. DispatcherServletview Resolver를 통해 View Name에 해당하는 View를 찾아서 Client한테 반환한다.

위 과정을 거치면서 View를 찾아서 렌더링 하는 과정을 거치게 됩니다.

하지만 Spring을 사용하다보면 Data를 반환해야하는 경우가 있을 텐데 이 경우 Controller를 반환하기 위해 @ResponseBody 어노테이션을 활용해서 JSON 형태의 데이터를 반환할 수 있습니다.

과정

  1. ClientURL 형식으로 요청을 보낸다.
  2. DispatcherServlet이 요청을 위임할 Handler Mapping을 찾는다.
  3. Handler Mapping을 통해 요청을 Controller로 위임한다.
  4. Controller는 요청을 처리한 후 객체를 반환한다.
  5. 반환되는 객체는 JSON으로 직렬화되어서 Client에게 반환된다.

컨트롤러를 통해 객체를 반환할 때 일반적으로 ResponseEntity로 감싸서 반환합니다. 그리고 객체를 반환하기 위해서는 View를 반환할 때 사용된 View Resolver 대신에 HttpMessageConverter가 동작합니다.

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

단순 문자열인 경우 StringHttpMessageConverter가 사용되고, 객체인 경우에는 MappingJackson2HttpMessageConverter가 사용되고, 데이터의 종류에 따라 서로 다른 MessageConverter가 작동하게 됩니다.

SpringClientHTTP Accept Header와 서버의 컨트롤러 반환 타입 정보 2개를 조합해서 적합한 HttpMessageConverter를 선택해서 처리합니다. Message Converter가 동작하는 시점은 HandlerAdapterController가 요청을 주고받는 시점입니다.

상단 그림을 보면 4번에서 Message를 객체로 반환, 6번에서는 객체를 Message로 변환하는데 Message Converter가 사용됩니다.

@Controller
@RequiredArgsConstructor

public class TestController {
private final MemberService memberService;

@GetMapping("api/board/member")
public @ResponseBody ResponseEntity<Member> findMember(@RequestParam("id") String id) {
return ResponseEntity.ok(memberService.findMember(member));
}
}

상단 코드에서 findMember()Member이라는 이름을 가진 객체를 ResponseEntity로 감싸서 반환하고, MemberJSON으로 반환하기 위해 @ResponseBody 어노테이션을 붙여주었습니다.

이 2가지를 한 곳에 작성하는 것보다는 데이터를 반환하는 ControllerView를 반환하는 Controller를 분리해서 작성하는 것이 더욱 좋은 방법입니다.

@RestController란

@RestController 어노테이션은 Restful Web Service에서 사용되는 컨트롤러 어노테이션입니다. @Controller + @ResponseBody가 합쳐진 형태로 JSON 형태의 객체 데이터를 반환합니다.

@RestController
@RequiredArgsConstructor
public class TestController {
private final MemberService memberService;

@GetMapping("api/board/member")
public Member findMember(RequestParam("id") String id) {
return memberService.findMember(member);
}

@GetMapping("api/board/member")
public ResponseEntity<Member> findMemberResponseEntity(@RequestParam("id") String id) {
return ResponseEntity.ok(memberService.findMember(member));
}
}

findMember()Member 객체 그대로를 반환하고 있습니다.

이러한 경우에 문제는 Client가 예상하는 HttpStatus를 설정할 수 없기에 객체 상황에 맞는 ResponseEntity로 감싸서 반환해줘야합니다.

결론

@Controller@RestController의 차이점은 용도의 차이라고 말할 수 있다고 생각합니다. @Controller 어노테이션은 공식적으로 Spring 2.5버전에서 추가되었고, @RestController는 Spring 4.0 버전에 추가되었습니다.

과거에는 JSP, HTML과 같은 view를 전달해 주었기에 주로 @Controller를 사용하였고, 최근에는 FrontendBackend가 나누어져서 개발하는 경우가 많기 때문에 @RestController를 사용합니다.