@Controller, @RestController 어떠한 차이가??
스프링 MVC구조에서 컨트롤러는 지정하는 방법으로는 @Controller, @RestController 어노테이션을 이용할 수 있다.
일단 기본적으로 스프링 MVC 패턴에서 컨트롤러는 MVC의 기본 흐름 상에서 들어온 클라이언트의 요청을 처리하여 결과를 리턴해 주게 되는데, 여기서 @RestController는 Rest표시에서 알 수 있다시피 Restful 웹서비스에서 주로 사용되는 컨트롤러로, HTTP ResponseBody를 생성하는 방식에서 차이점을 보인다고 한다.
@Controller이란?
MVC구조에서 컨트롤러 클래스를 bean으로 등록하면 일반적으로 @Controller 어노테이션을 사용하는 것을 알 수있다.
해당 어노테이션을 통해 해당 클래스가 Controller로 사용될 것임을 Spring Framework에 알려주게 되는데 @Controller의 경우 일반적으로 클라이언트 요청에 대해서 View를 반환하거나 데이터를 반환하기도 한다. 물론 view를 반환하냐, 데이터를 반환하느냐에 따라 처리가 조금 다르기도 하지만 그 처리로 인해 @RestController가 나오게 된다.
View 반환
view가 반환되는 과정을 보면 클라이언트 요청을 받아 Dispatcher Servelet이 컨트롤러로 던져주면, 결곡 viewResolver가 작동해서 view를 반환하게 되는데, 일반적인 MVC구조상에서는 이렇게 view를 반환하는 경우가 대부분이다.
위 그림들을 통해 view가 반환되는 경우의 처리과정을 살펴보면 다음과 같다.
- client로 url형식으로 요청을 받게 된다.
- Dispatcher Servlet은 요청을 Handler Mapping에게 전달하고 Handler Mapping이 알맞은 컨트롤러와 메서드를 찾게 된다.
- 그리고 Handler Adapter를 통해 해당 메서드를 실행하고 그 결과를 받는다.
- 결과가 viewname일 경우 view resolver에게 할당한다.
- view resolver는 해당 view를 찾아 클라이언트에게 전달하게 된다.
이렇게 일반적이 view를 반환할 경우 view resolver가 사용된다. 하지만, 데이터를 반환하게 되는 경우 조금 다르게 처리되게 된다.
Data 반환
데이터의 반환의 경우 view resolver의 사용이 필요하지 않는다. 다만 해당 데이터 처리 시 JSON으로 응답을 하기 위해서, 해당 컨트롤러의 응답이 JSON임을 알려줘야 하는데 이를 @ResponseBody를 통해서 알려주게 된다.
- client로 url형식으로 요청을 받게 된다.
- Dispatcher Servlet은 요청을 Handler Mapping에게 전달하고 Handler Mapping이 알맞은 컨트롤러와 메서드를 찾게 된다.
- 그리고 Handler Adapter를 통해 해당 메서드를 실행하고 그 결과를 받는다.
- @ResponseBody를 통해 해당 요청을 클라이언트에게 Json형태로 응답하게 된다.
@RestController란?
Rest-Controller에서 알 수 있다시피 RestFul 웹서비스에서 주로 사용되는 컨트롤러이다. Restfull에서의 서비스에 사용되다 보니 기본적으로 응답은 view가 아닌 데이터 위주의 응답을 목적으로 하고 있는 컨트롤러이다.
즉, ResponseBody가 기본적으로 사용되는 컨트롤러인 것이다. 소스코드를 살펴보면 알 수 있겠지만, 기본적으로 해당 컨트롤러에서는 기존의 Controller에서 Json응답을 주기 위해 사용하던 @ResponseBody를 사용하지 않더라도 Json으로 응답을 줄 수가 있다.
즉, @Controller+@ResponseBody 버전으로 이해하면 된다.
@Controller, @RestController 소스코드
두 소스를 살펴보면 가장 큰 차이점은 @ResponseBody가 붙어있는지 여부가 될 것이다.
@RestController의 경우 Restful 웹서비스에서 사용함과 동시에 ResponseBody를 통해 기본적으로 view대신 객체로 작성되어 Json응답이 되게 함을 알 수 있습니다.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
* @since 4.0.1
*/
@AliasFor(annotation = Controller.class)
String value() default "";
}
다만 부수적으로 좀 더 자세히 살펴보면 Controller의 경우 @Component를 갖고 RestController의 경우 @Controller를 갖는데, 이는 결국 RestController 또한, Controller로서 작동되며 궁극적으론 Component로써 등록되어 사용됨을 알 수 있다.
다만 개인적으로 컨트롤러를 작성할 시에 View가 사용되는 컨트롤러와 Restful로 서비스하는 컨트롤러는 구분하여 사용하는 것이 좋을 것이라 생각되며, 해당 어노테이션을 통해 해당 컨트롤러가 어떠한 서비스로 사용되는지를 편하게 보여줄 수 있을 것 같다는 생각이 든다.
더불어 @ResponseBody를 적어주지 않는 것 또한 꽤나 이점으로 작용할 것 같은 생각이 든다.
'프레임워크 > 스프링&스프링부트' 카테고리의 다른 글
@SpringBootApplication 이해하기 (0) | 2022.02.01 |
---|---|
API Versioning (0) | 2021.09.28 |
[Spring Boot]build 설정파일 (0) | 2021.07.31 |
[Spring]스프링 프로젝트 빌드 및 실행하기 (0) | 2021.07.22 |
[Spring Boot]ContentNegotiatingViewResolver (0) | 2021.07.20 |