1. @Controller 란?
@Controller
는 Spring MVC 패턴에서 주로 사용되는 어노테이션으로, 웹 페이지(View)를 반환하기 위해 사용됩니다. 이 어노테이션을 통해 컨트롤러 클래스를 정의하면, 클라이언트 요청을 받아서 JSP나 Thymeleaf와 같은 뷰(View)를 생성하여 반환할 수 있습니다. Spring에서 @Controller
는 주로 전통적인 웹 애플리케이션에서 페이지를 렌더링할 때 사용됩니다.
1.1 @Controller 동작 흐름
- 클라이언트 요청: 클라이언트는 브라우저 또는 HTTP 클라이언트를 통해 DispatcherServlet으로 URI에 해당하는 요청을 보냅니다. 예를 들어
/users/detailView
와 같은 URI로 요청이 들어옵니다. - Handler Mapping: Spring의 DispatcherServlet은 해당 요청을 처리하기 위한 Handler Mapping을 통해 어떤 컨트롤러가 이 요청을 처리할지 결정합니다. 이 과정에서 요청된 URI와 매핑되는 컨트롤러를 찾습니다.
- Handler Adapter: 선택된 핸들러(즉, 컨트롤러)와 요청을 이어주는 역할을 담당합니다. Handler Adapter는 요청을 해당 컨트롤러의 적절한 메서드로 전달할 준비를 합니다.
- Controller에서 비즈니스 로직 실행: 선택된 Controller는 클라이언트의 요청을 처리하기 위해 필요한 비즈니스 로직을 실행합니다. 예를 들어,
UserService
에서 사용자를 찾거나 데이터를 처리하는 로직을 호출할 수 있습니다. - 뷰 이름 반환: 비즈니스 로직이 끝난 후, 컨트롤러는 뷰 이름(예:
"users/detailView"
)을 반환합니다. 이 뷰 이름은 클라이언트에게 반환될 페이지의 경로를 나타냅니다. - View Resolver: Spring의 View Resolver는 반환된 뷰 이름을 해석하여, 실제로 클라이언트에게 보여줄 뷰(JSP, Thymeleaf 템플릿)를 결정합니다. 예를 들어,
users/detailView.jsp
파일을 찾습니다. - Handler Adapter는 뷰로부터 받은 정보와 데이터를 바탕으로 HTML을 준비합니다.
- 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 동작 흐름
- 클라이언트 API 요청: 클라이언트는 URI를 통해 API 요청을 보냅니다. 예를 들어,
/api/v1/users
와 같은 URI로 JSON 데이터를 요청합니다. - Handler Mapping: DispatcherServlet이 이 API 요청을 받아 적절한 Controller를 찾기 위해 Handler Mapping을 사용합니다. 요청된 URI가 어떤 컨트롤러 메서드에 매핑될지 결정합니다.
- Handler Adapter: API 요청을 처리할 컨트롤러 메서드를 결정한 후, Handler Adapter는 해당 메서드를 호출할 준비를 합니다.
- Controller에서 비즈니스 로직 실행:
@RestController
에 정의된 메서드가 호출되고, 비즈니스 로직이 실행됩니다. 여기서 서비스 계층을 호출하여 데이터베이스에서 데이터를 가져오거나, 처리 결과를 반환합니다. - ResponseEntity 객체 생성: 메서드의 반환 값은
ResponseEntity
로 감싸져 반환됩니다. 이 객체에는 응답 본문뿐만 아니라 HTTP 상태 코드와 같은 추가 정보도 포함될 수 있습니다. - JSON 직렬화: 메서드가 반환한 객체는 자동으로 JSON 또는 XML 형식으로 직렬화됩니다. 이 과정에서
@ResponseBody
나@RestController
가 이를 처리합니다. - Handler Adapter는 직렬화된 데이터를 준비한 후 DispatcherServlet에 전달합니다.
- 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] @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 |