[Spring] @Controller VS @RestController

2025. 1. 6. 10:39·BackEnd/Spring & JPA

1. @Controller 란?

@Controller는 Spring MVC 패턴에서 주로 사용되는 어노테이션으로, 웹 페이지(View)를 반환하기 위해 사용됩니다. 이 어노테이션을 통해 컨트롤러 클래스를 정의하면, 클라이언트 요청을 받아서 JSP나 Thymeleaf와 같은 뷰(View)를 생성하여 반환할 수 있습니다. Spring에서 @Controller는 주로 전통적인 웹 애플리케이션에서 페이지를 렌더링할 때 사용됩니다.

1.1 @Controller 동작 흐름

  1. 클라이언트 요청: 클라이언트는 브라우저 또는 HTTP 클라이언트를 통해 DispatcherServlet으로 URI에 해당하는 요청을 보냅니다. 예를 들어 /users/detailView와 같은 URI로 요청이 들어옵니다.
  2. Handler Mapping: Spring의 DispatcherServlet은 해당 요청을 처리하기 위한 Handler Mapping을 통해 어떤 컨트롤러가 이 요청을 처리할지 결정합니다. 이 과정에서 요청된 URI와 매핑되는 컨트롤러를 찾습니다.
  3. Handler Adapter: 선택된 핸들러(즉, 컨트롤러)와 요청을 이어주는 역할을 담당합니다. Handler Adapter는 요청을 해당 컨트롤러의 적절한 메서드로 전달할 준비를 합니다.
  4. Controller에서 비즈니스 로직 실행: 선택된 Controller는 클라이언트의 요청을 처리하기 위해 필요한 비즈니스 로직을 실행합니다. 예를 들어, UserService에서 사용자를 찾거나 데이터를 처리하는 로직을 호출할 수 있습니다.
  5. 뷰 이름 반환: 비즈니스 로직이 끝난 후, 컨트롤러는 뷰 이름(예: "users/detailView")을 반환합니다. 이 뷰 이름은 클라이언트에게 반환될 페이지의 경로를 나타냅니다.
  6. View Resolver: Spring의 View Resolver는 반환된 뷰 이름을 해석하여, 실제로 클라이언트에게 보여줄 뷰(JSP, Thymeleaf 템플릿)를 결정합니다. 예를 들어, users/detailView.jsp 파일을 찾습니다.
  7. Handler Adapter는 뷰로부터 받은 정보와 데이터를 바탕으로 HTML을 준비합니다.
  8. Dispatcher Servlet은 최종적으로 HTML을 클라이언트에게 반환합니다.

뷰 반환 예시 코드 (@Controller 사용)

@Controller
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    // View 반환: 사용자 상세 정보를 보여주는 페이지
    @GetMapping(value = "/users/detailView")
    public String detailView(Model model, @RequestParam String userName){
        User user = userService.findUser(userName);  // 비즈니스 로직 호출
        model.addAttribute("user", user);  // 뷰에 전달할 데이터 추가
        return "users/detailView";  // JSP나 Thymeleaf 템플릿으로 View를 렌더링
    }
}

위 코드에서 detailView 메서드는 사용자 이름을 파라미터로 받아, 그에 맞는 사용자 정보를 UserService로부터 가져와서 Model 객체에 추가합니다. 이렇게 추가된 데이터는 뷰 템플릿(users/detailView.jsp 또는 users/detailView.html)에 전달되어, 서버 사이드에서 페이지가 렌더링됩니다.

Model 객체는 서버 측에서 데이터를 HTML 페이지에 주입하는 역할을 하며, 반환된 문자열 "users/detailView"는 Spring의 ViewResolver에 의해 JSP나 Thymeleaf 템플릿 파일로 해석됩니다. 이 템플릿은 데이터를 받아 클라이언트에게 HTML로 렌더링된 페이지를 반환합니다.

이 방식은 주로 전통적인 서버 사이드 렌더링 웹 애플리케이션에서 사용되며, 사용자가 웹 브라우저를 통해 접근할 때 동적으로 생성된 HTML 페이지를 반환하는 데 적합합니다.

@Controller로 JSON 데이터 반환하기

@Controller
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    // JSON 데이터 반환: @ResponseBody 어노테이션을 추가하여 데이터를 반환
    @GetMapping(value = "/users")
    @ResponseBody
    public ResponseEntity<User> findUser(@RequestParam String userName){
        User user = userService.findUser(userName);  // 비즈니스 로직 호출
        return ResponseEntity.ok(user);  // JSON으로 사용자 정보 반환
    }
}

위 코드는 @Controller를 사용하면서도 JSON 데이터를 반환하는 방식입니다. 메서드가 데이터 객체(User)를 반환하는 경우, Spring은 이 데이터를 JSON 형식으로 직렬화하여 HTTP 응답 본문에 포함합니다.

이를 위해서는 @ResponseBody 어노테이션을 사용해야 합니다. @ResponseBody는 메서드의 반환값을 HTML 뷰가 아닌 HTTP 응답 본문으로 직접 변환하도록 명시하는 역할을 합니다. ResponseEntity를 사용하여 응답 데이터뿐만 아니라 HTTP 상태 코드까지 함께 설정할 수 있습니다.

예를 들어, 위 코드에서는 User 객체를 조회하여 200 OK 상태와 함께 JSON 형식으로 클라이언트에게 응답합니다.

이 방식은 단일 페이지 애플리케이션(SPA)에서 주로 사용되며, 프론트엔드(Vue.js, React.js 등)와 통신할 때 데이터를 JSON 형식으로 주고받는 경우에 적합합니다.

2. @RestController 란?

@RestController는 @Controller와 @ResponseBody를 결합한 어노테이션입니다. 즉, @RestController가 붙은 클래스의 모든 메서드는 자동으로 JSON 또는 XML 형식으로 데이터를 반환합니다. 이를 통해 RESTful 웹 서비스를 쉽게 구현할 수 있습니다. REST API 개발 시, 데이터는 뷰(View) 대신 JSON 형태로 반환되어야 하기 때문에 @RestController는 API 서버에서 데이터를 클라이언트로 반환하는 데 적합합니다.

2.1 @RestController 동작 흐름

  1. 클라이언트 API 요청: 클라이언트는 URI를 통해 API 요청을 보냅니다. 예를 들어, /api/v1/users와 같은 URI로 JSON 데이터를 요청합니다.
  2. Handler Mapping: DispatcherServlet이 이 API 요청을 받아 적절한 Controller를 찾기 위해 Handler Mapping을 사용합니다. 요청된 URI가 어떤 컨트롤러 메서드에 매핑될지 결정합니다.
  3. Handler Adapter: API 요청을 처리할 컨트롤러 메서드를 결정한 후, Handler Adapter는 해당 메서드를 호출할 준비를 합니다.
  4. Controller에서 비즈니스 로직 실행: @RestController에 정의된 메서드가 호출되고, 비즈니스 로직이 실행됩니다. 여기서 서비스 계층을 호출하여 데이터베이스에서 데이터를 가져오거나, 처리 결과를 반환합니다.
  5. ResponseEntity 객체 생성: 메서드의 반환 값은 ResponseEntity로 감싸져 반환됩니다. 이 객체에는 응답 본문뿐만 아니라 HTTP 상태 코드와 같은 추가 정보도 포함될 수 있습니다.
  6. JSON 직렬화: 메서드가 반환한 객체는 자동으로 JSON 또는 XML 형식으로 직렬화됩니다. 이 과정에서 @ResponseBody나 @RestController가 이를 처리합니다.
  7. Handler Adapter는 직렬화된 데이터를 준비한 후 DispatcherServlet에 전달합니다.
  8. Dispatcher Servlet은 직렬화된 JSON 데이터를 HTTP 응답 본문으로 클라이언트에 반환합니다.

@RestController 예시

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    // JSON 데이터 반환: @ResponseBody를 따로 붙이지 않아도 자동으로 JSON 반환
    @GetMapping(value = "/{userName}")
    public User findUser(@PathVariable String userName){
        return userService.findUser(userName);  // User 객체를 반환하면 JSON으로 직렬화
    }

    // ResponseEntity 사용 예시: 상태 코드 설정
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.saveUser(user);  // 새로운 사용자 저장
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);  // 201 Created 상태 반환
    }
}

위 코드에서 @RestController는 반환된 User 객체를 자동으로 JSON으로 변환하여 클라이언트에게 응답합니다. 이때 ResponseEntity를 사용하면 HTTP 상태 코드와 응답 본문을 함께 제어할 수 있습니다. 예를 들어, createUser 메서드에서는 201 Created 상태 코드를 설정하여, 객체가 성공적으로 생성되었음을 알릴 수 있습니다.

3. @Controller와 @RestController의 차이점

  • @Controller는 뷰를 반환하는데 특화되어 있기 때문에, 전통적인 웹 애플리케이션에서 주로 사용됩니다. 이때 뷰는 JSP나 Thymeleaf와 같은 템플릿 엔진을 통해 렌더링됩니다.
  • 반면에 @RestController는 데이터만을 반환하는 데 특화되어 있어, 주로 REST API를 개발할 때 사용됩니다.
  • @Controller에서 JSON 데이터를 반환하려면 @ResponseBody를 추가해야 하지만, @RestController는 이 작업을 자동으로 처리합니다.

4. RESTful 웹 서비스에서 @Controller와 @RestController의 사용

전통적인 Spring MVC 애플리케이션에서는 @Controller가 주로 사용되며, 뷰(View)와 데이터를 모두 반환할 수 있습니다. 예를 들어, 한 메서드에서는 JSP 페이지를 반환하고, 다른 메서드에서는 JSON 데이터를 반환할 수 있습니다. 반면에 RESTful API 서버에서는 클라이언트에게 HTML 페이지가 아닌 JSON 형식의 데이터를 제공하는 것이 목적이므로, @RestController가 적합합니다.

4.1 @Controller와 @RestController를 분리한 구조

@Controller로 뷰 반환

@Controller
@RequiredArgsConstructor
public class PageController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("message", "Welcome to the home page!");
        return "home";  // home.jsp 또는 home.html 렌더링
    }
}

@RestController로 API 반환

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/users")
public class UserApiController {

    private final UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findUserById(id);
        if (user != null) {
            return ResponseEntity.ok(user);  // JSON 형식으로 반환
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        }
    }
}

위 예시처럼 @Controller는 페이지를 반환하는 데 사용하고, @RestController는 데이터를 반환하는 데 사용하여 역할을 분리하는 것이 일반적입니다.

5. 결론

  • @Controller는 전통적인 Spring MVC에서 페이지(View)를 반환하는 데 사용됩니다. 웹 애플리케이션에서 HTML 페이지를 렌더링하거나, 특정 조건에서는 @ResponseBody를 통해 JSON 데이터를 반환할 수 있습니다. 주로 서버 사이드 렌더링(SSR) 방식의 애플리케이션에서 사용되며, 뷰 템플릿과 데이터를 결합하여 클라이언트에 완성된 HTML 페이지를 제공합니다.
  • @RestController는 RESTful 웹 서비스를 개발할 때 주로 사용됩니다. @ResponseBody가 자동으로 적용되어 데이터(JSON, XML 등)가 클라이언트로 바로 반환됩니다. 이를 통해 API 설계 시 데이터를 쉽게 전달할 수 있고, 주로 프론트엔드와의 통신에서 데이터를 제공하는 역할을 합니다.
  • 두 어노테이션을 선택하는 기준은 애플리케이션의 목적에 따라 달라집니다. 전통적인 서버 사이드 웹 애플리케이션을 구축하는 경우에는 @Controller가 더 적합하며, REST API를 제공하는 서버는 @RestController가 더 적합합니다.
  • 현재 Spring Boot 백엔드 애플리케이션에서는 대부분 API 서버로서의 역할을 하며, 프론트엔드는 주로 Vue.js나 React.js와 같은 프레임워크를 사용하여 클라이언트 측에서 페이지를 렌더링합니다. 이때는 백엔드에서 주로 JSON 형태의 데이터를 제공하기 때문에 @RestController를 사용하여 API 서버를 구축하는 것이 일반적입니다.
  • 따라서, API 서버 구축과 데이터 제공을 목표로 한다면 @RestController를 사용하고, 뷰를 렌더링하여 직접 HTML 페이지를 반환하는 방식이 필요하다면 @Controller를 사용하는 것이 이상적입니다.

'BackEnd > Spring & JPA' 카테고리의 다른 글

[Spring Boot] MySQL Master/Slave 복제 설정과 Read/Write 자동 분기 처리 방법 정리  (0) 2025.03.24
[Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)  (0) 2025.02.13
[Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유  (0) 2025.01.21
[Spring] @ResponseBody VS ResponseEntity<T>  (0) 2025.01.06
[Spring] 스프링 개념 및 동작 원리 정리  (0) 2025.01.05
'BackEnd/Spring & JPA' 카테고리의 다른 글
  • [Spring] @RequestPart를 활용하여 JSON + MultipartFile 동시 전송하기 (Feat. 게시판에서 게시물 생성과 첨부 파일 업로드 한번에 처리하기)
  • [Spring Data JPA] JPA 엔티티 설계 시 생성자 접근 제한을 PROTECTED로 설정하는 이유
  • [Spring] @ResponseBody VS ResponseEntity<T>
  • [Spring] 스프링 개념 및 동작 원리 정리
개발자 동긔
개발자 동긔
배우고 느낀점들을 기록합니다. 열정 넘치는 백엔드 개발자로 남고싶습니다.
  • 개발자 동긔
    Donker Dev
    개발자 동긔
  • 전체
    오늘
    어제
    • Category (39)
      • BackEnd (23)
        • JAVA (15)
        • Spring & JPA (7)
      • Database (4)
      • Computer Science (2)
        • Network (0)
        • Security (0)
        • Web (1)
      • DevOps (6)
        • Docker (1)
        • Jenkins (0)
        • Monitoring (2)
        • CICD (1)
      • 트러블 슈팅 (3)
      • 성능 개선 (1)
      • Project (0)
  • 인기 글

  • 태그

    Database
    interface
    인터페이스
    nginx
    mysql master/slave replication
    java
    docker
    restful api 설계
    SSH
    master/slave db 이중화 처리
    spring cloud msa
    CICD
    Jenkins
    spring boot
    restful api
    docker compose
    Spring
    와일드카드
    JPA
    @RequestBody
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
개발자 동긔
[Spring] @Controller VS @RestController
상단으로

티스토리툴바