본문 바로가기
학습/Spring

[spring] @Controller vs @RestController

by KKambi 2021. 5. 25.

저는 회사에서 Restful API 서버만을 구현하기 때문에 아무 생각 없이 @RestController 어노테이션만을 사용해왔습니다. 그런데 어느 날, @Controller와 @RestController의 차이가 뭐냐는 질문을 받게 되었고 저는 자신있게 대답하지 못했죠. 스프링을 처음 배우던 과거에 @Controller를 사용해봤음에도 말이에요.

그래서 이번 기회에 두 어노테이션의 차이를 자세하게 알아보려 합니다. 이상한 부분이 있으면 댓글로 달아주세요.
저도 초보 개발자라 정리한 부분이 틀릴 수 있어요!

 

 

배경 - MVC 패턴과 Restful API

MVC(Model-View-Controller) 구조에서 서버는 Controller로 사용자의 요청을 제어하며 Model로 DB의 데이터를 맵핑한 뒤 View를 통해 사용자에게 데이터를 보여줍니다. 서버에서 데이터를 가져와 삽입하고 사용자에게 보여질 HTML까지 렌더링하여 제공하기 때문에 이러한 구조에선 Server-Side Rendering을 수행하게 됩니다. 저는 JSP나 Mustache를 사용해봤었어요.

그런데 기술이 발전하고 모바일 환경이 중요해지면서 사용자의 브라우저에 데이터를 더욱 빠르게 제공해야만 했죠. 서버사이드 렌더링으로 서버의 부하가 심해지는 일을 막고 싶었습니다.

그래서 Client-Side Rendering이 등장했고 많은 웹 서비스들이 이 구조를 적용하고 있습니다. 서버는 (보통은 JSON 형식으로) 데이터를 제공하는 역할을 맡게 됐고, 사용자에게 View를 대신 제공하는 서버가 등장했죠. 보통 전자를 API서버/백엔드서버/WAS, 후자를 웹서버/프론트엔드서버라 부르게 됩니다. 제 파트는 Spring Boot로 API를 구현하는 일을 하고 있구요, 웹 파트에서 Vue.js로 구축한 서버와 주로 통신하고 있습니다. 여기서 자원의 제공 방식을 정의한 게 REST입니다.

Restful은 REST를 따르는 것을 말한다네요. REST의 원칙을 완벽히 지키는 일이 현실적으로 어려워서 그렇겠죠?

 

다른 포스트에서도 첨부한 적이 있는데요. 짧은 소고인데도 제게 큰 도움이 되었네요. 한 번 읽어보세요! 

 

API 서버와 MVC에 관한 소고

0. 앨런 케이가 OOP를 이야기하며 스몰토크를 만들었을 때 결국 가장 크게 염두에 둔 것은 GUI에 대한 접근이었다. 그리고 GUI는 실제로 아이콘을, 버튼을, 창의 동작을 어떻게 컴퓨터에게 이해시킬

blog.kivol.net

 

 

@Controller

MVC 패턴에서의 전통적인 스프링 컨트롤러입니다. Classpath Scanning을 통해 빈으로 등록되는 컴포넌트의 하나죠.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}
@Target : 어노테이션이 위치할 수 있는 타겟
@Retention : 어노테이션이 언제 필요한가 (어노테이션의 생존 기간)
@Documented : Java docs에 해당 어노테이션이 적혀있음

 

그런데 전통적인 컨트롤러는 View를 반환하기 위한 것입니다. HTTP 응답으로 데이터를 반환하기 위해선 별도의 어노테이션이 필요합니다. 윗 메소드의 리턴 타입에 붙은 @ResponseBody를 통해, 반환된 객체를 Serialize하여 HttpResponse에 담을 수 있죠.

@RequiredArgsConstructor
@Controller
@RequestMapping("/v1/books")
public class BookController {

    private final BookService bookService;

    @GetMapping("/{bookIdx}")
    public @ResponseBody Book findBook(@PathVariable(name = "bookIdx") Long bookIdx) {
        return bookService.findBook(bookIdx);
    }

    @GetMapping("/{bookIdx}")
    public String findBook(Model model, @PathVariable(name = "bookIdx") Long bookIdx) {
        Book book = bookService.findBook(userName);
        model.addAttribute("book", book);
        return "/bookInfo";
    }
}

 

 

@RestController

@Controller와 @ResponseBody를 합친 것으로, Restful 웹서비스를 위해 Spring 4.0부터 제공하는 어노테이션입니다. 컨트롤러 메소드에 일일이 @ResponseBody를 붙여주는 작업을 제거하기 위해 생겼습니다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

 

해당 어노테이션으로 우리는 @ResponseBody를 추가하는 단순 작업을 하지 않아도 됩니다.

@RequiredArgsConstructor
@RestController
@RequestMapping("/v1/books")
public class BookController {

    private final BookService bookService;

    @GetMapping("/{bookIdx}")
    public Book findBook(@PathVariable(name = "bookIdx") Long bookIdx) {
        return bookService.findBook(bookIdx);
    }
}

 

 

참고 자료

 

The Spring @Controller and @RestController Annotations | Baeldung

Learn about the differences between @Controller and @RestController annotations in Spring MVC.

www.baeldung.com

 

[Spring] @Controller와 @RestController 차이

Spring에서 컨트롤러를 지정해주기 위한 어노테이션은 @Controller와 @RestController가 있습니다. 전통적인 Spring MVC의 컨트롤러인 @Controller와 Restuful 웹서비스의 컨트롤러인 @RestController의 주요한 차..

mangkyu.tistory.com

 

댓글