@RestController vs @Controller
by 볼빵빵오춘기혼자 토이 프로젝트를 하다 @Controller만 이용하다가 '@RestController도 있잖아'라는 생각이 들었다.
그래서 @RestController와 @Controller를 비교해보기로 했다.
글 쓰기, 글 수정하기, 글 삭제하기, 글 읽기, 댓글, 전체 글 조회(리스트) 기능을 구현할 때 어떤 애노테이션을 사용하는 것이 좋을까?
@RestController와 @Controller는 Spring MVC에서 주로 사용되는 두 가지 애노테이션이다. 이 두 애노테이션은 서로 다른 용도로 사용되며, 각각의 특성과 사용 방법에 대해 자세히 알아보자.
@Controller
- @Controller는 전통적인 MVC 패턴에서 사용되는 애노테이션으로, 주로 HTML 페이지를 반환하는 데 사용된다.
- Spring MVC의 뷰 리졸버(View Resolver)와 함께 사용되어 JSP, Thymeleaf, FreeMarker 등과 같은 템플릿 엔진을 통해 HTML 페이지를 생성한다.
- 따라서 @Controller는 주로 사용자가 브라우저를 통해 접근하는 웹 애플리케이션을 개발할 때 사용된다.
ex) 사용자가 회원가입 폼을 작성하고 제출하는 웹 페이지를 반환할 때 사용된다.
@Controller public class UserController { @GetMapping("/register") public String showRegistrationForm() { return "register"; } @PostMapping("/register") public String registerUser(@RequestParam String username, @RequestParam String password, Model model) { // 사용자 등록 로직 처리 model.addAttribute("username", username); return "welcome"; } }
⇒ /register URL에 접근하면 register.html 페이지를 반환. 사용자가 폼을 제출하면 welcome.html 페이지를 반환.
@RestController
- @RestController는 RESTful 웹 서비스(API)를 만들 때 사용되는 애노테이션이다.
- @Controller와 @ResponseBody를 합친 것으로, 반환되는 데이터는 뷰가 아닌 JSON이나 XML 형식의 데이터이다.
- 따라서, @RestController는 주로 클라이언트 애플리케이션(모바일 앱, 프론트엔드 JavaScript 애플리케이션 등)이 데이터를 요청할 때 사용된다.
ex) 클라이언트가 사용자 정보를 요청하면 JSON 형식의 데이터를 반환한다.
@RestController public class UserRestController { @GetMapping("/api/users/{id}") public User getUser(@PathVariable Long id) { // 사용자 정보 조회 로직 return new User(id, "username", "password"); } @PostMapping("/api/users") public User createUser(@RequestBody User user) { // 사용자 생성 로직 return user; } }
⇒ /api/users/{id} URL에 GET 요청을 보내면 사용자 정보를 JSON 형식으로 반환. /api/users URL에 POST 요청을 보내면 새로운 사용자를 생성하고 그 정보를 JSON 형식으로 반환.
요약
@Controller
- 주로 웹 애플리케이션에서 HTML 페이지를 반환할 때 사용된다.
- 사용자가 브라우저를 통해 접근하고, 서버에서 HTML 페이지를 렌더링하여 반환할 때 적합하다.
@RestController
- RESTful API를 구현할 때 사용되며, 주로 JSON이나 XML 형식의 데이터를 반환한다.
- 프론트엔드 애플리케이션이나 모바일 앱이 데이터를 요청할 때 적합하다.
정리
글 쓰기, 글 수정하기, 글 삭제하기, 글 읽기, 댓글, 전체 글 조회(리스트) 어떤 걸 쓰는게 좋을까? 에 대한 생각을 정리해봤다.
글쓰기 (Create), 글 수정하기 (Update)
⇒ @Controller가 적절
- 사용자가 브라우저를 통해 글 작성 폼을 제출할 때 주로 사용된다.
- 폼 제출 후 성공/실패 메시지나 리디렉션을 처리하기 적합하기 때문이다.
@Controller public class PostController { // 글 쓸 때 @GetMapping("/posts/new") public String showCreateForm(Model model) { model.addAttribute("post", new Post()); return "create-post"; } @PostMapping("/posts") public String createPost(@ModelAttribute Post post) { postService.save(post); return "redirect:/posts"; } // 글 수정할 때 @GetMapping("/posts/{id}/edit") public String showEditForm(@PathVariable Long id, Model model) { Post post = postService.findById(id); model.addAttribute("post", post); return "edit-post"; } @PostMapping("/posts/{id}") public String updatePost(@PathVariable Long id, @ModelAttribute Post post) { postService.update(id, post); return "redirect:/posts"; } }
글 읽기(Read)
⇒ @Controller가 적절
- 사용자가 브라우저를 통해 글을 읽을 때 HTML 페이지로 제공한다.
@Controller public class PostController { @GetMapping("/posts/{id}") public String readPost(@PathVariable Long id, Model model) { Post post = postService.findById(id); model.addAttribute("post", post); return "view-post"; } }
글 삭제하기 (Delete)
⇒ @RestController가 적절
- 글 삭제는 비동기적으로 수행되는 경우가 많고, 삭제 후 페이지 리디렉션이 필요 없을 때가 많다.
- 또한, RESTful API에서는 주로 JSON 응답을 사용한다.
@RestController @RequestMapping("/api/posts") public class PostRestController { @DeleteMapping("/{id}") public ResponseEntity<Void> deletePost(@PathVariable Long id) { postService.delete(id); return ResponseEntity.noContent().build(); } }
전체 글 조회 (List)
⇒ @Controller와 @RestController 둘 다 사용 가능, 상황에 따라 다름.
- @Controller: 사용자가 브라우저를 통해 전체 글 목록을 HTML 페이지로 볼 때 적합하다.
- @RestController: JSON 형식으로 전체 글 목록을 제공할 때 적합하다. 프론트엔드 애플리케이션이나 모바일 앱에서 사용된다.
@Controller public class PostController { @GetMapping("/posts") public String listPosts(Model model) { List<Post> posts = postService.findAll(); model.addAttribute("posts", posts); return "list-posts"; } }
@RestController @RequestMapping("/api/posts") public class PostRestController { @GetMapping public ResponseEntity<List<Post>> listPosts() { List<Post> posts = postService.findAll(); return ResponseEntity.ok(posts); } }
댓글(Comment)
⇒ @Controller와 @RestController 둘 다 사용 가능, 상황에 따라 다름.
- @Controller
- 사용자가 브라우저를 통해 댓글을 포함한 글을 읽을 때 HTML 페이지로 제공되기때문에 댓글을 페이지에 바로 렌더링해서 보여줄 때 적합하다.
- 서버 사이드 렌더링으로, 페이지 로드 시점에 댓글이 함께 로드된다.
- 댓글 데이터를 바로 HTML로 변환하여 클라이언트에 제공하기 때문에 추가적인 JavaScript 작업이 필요 없다.
@Controller public class PostController { @GetMapping("/posts/{id}") public String readPost(@PathVariable Long id, Model model) { Post post = postService.findById(id); List<Comment> comments = commentService.findByPostId(id); model.addAttribute("post", post); model.addAttribute("comments", comments); return "view-post"; } }
- @RestController
- 댓글 데이터를 JSON 형식으로 제공하고, 프론트엔드에서 AJAX를 사용하여 댓글을 비동기적으로 로드하거나 조작할 때 적합하다.
- 댓글을 동적으로 로드하거나 추가적인 인터랙티브 기능을 구현할 때 유용하다.
- 비동기 요청을 통해 필요한 시점에만 댓글을 로드하여 초기 페이지 로딩 시간을 줄일 수 있다.
- 프론트엔드에서 댓글을 동적으로 추가, 수정, 삭제할 수 있어 사용자 경험이 향상된다.
@RestController @RequestMapping("/api/comments") public class CommentRestController { @GetMapping("/post/{postId}") public ResponseEntity<List<Comment>> getComments(@PathVariable Long postId) { List<Comment> comments = commentService.findByPostId(postId); return ResponseEntity.ok(comments); } @PostMapping public ResponseEntity<Comment> addComment(@RequestBody Comment comment) { Comment savedComment = commentService.save(comment); return ResponseEntity.status(HttpStatus.CREATED).body(savedComment); } }
@Controller | @RestController | |
글 쓰기 | O | |
글 수정 | O | |
글 읽기 | O | |
글 삭제 | O | |
전체 글 조회 |
O | O |
댓글 | O | O |
✅ 무조건적으로 "글 쓰기 기능에는 @Controller를 써야 해!", "글 삭제 기능에는 @RestController를 써야 해!"라고 정해진 규칙이 있는 것은 아니다. 상황에 맞게 @Controller와 @RestController가 각각 언제 사용되는지 잘 이해하고, 그에 따라 적절히 선택하여 사용하면 된다.

블로그의 정보
Hello 춘기's world
볼빵빵오춘기