-
Spring Framework 시리즈 13화 – @Controller와 @RestController 내부 구조와 처리 흐름기술과 산업/언어 및 프레임워크 2025. 6. 5. 11:19728x90
스프링에서 자주 사용하는 @Controller와 @RestController, 그리고 @RequestMapping 애노테이션이 DispatcherServlet과 어떻게 연결되고 처리되는지 흐름 중심으로 설명합니다.
@Controller와 @RestController는 뭐가 다른가요?
가장 간단히 정리하면:
애노테이션반환 방식용도
@Controller 뷰 이름 웹 페이지 응답 (HTML) @RestController HTTP 본문(JSON 등) API 응답 즉, @RestController는 사실상 아래 두 가지의 합성입니다.
@RestController == @Controller + @ResponseBody
DispatcherServlet과 어떻게 연결될까?
Spring MVC가 내부적으로 요청을 처리할 때, DispatcherServlet은 먼저 HandlerMapping을 통해 어떤 메서드가 이 요청을 처리할지 찾습니다.
그때 @RequestMapping, @GetMapping, @PostMapping 같은 애노테이션이 붙은 메서드를 RequestMappingHandlerMapping이 인식해서 매핑 테이블을 구성합니다.
예제
@RestController public class HelloApi { @GetMapping("/api/hello") public String hello() { return "hello world"; } }
이 코드는 Spring 부팅 시 다음처럼 매핑됩니다.
GET /api/hello → HelloApi.hello()
매핑 구조를 관리하는 핵심 클래스
컴포넌트역할
RequestMappingHandlerMapping 애노테이션 기반 메서드 매핑 수집 RequestMappingHandlerAdapter 매핑된 메서드를 실행하고 결과를 반환 HandlerMethod 메서드 정보를 캡슐화한 객체 HandlerInterceptor (옵션) 요청 전후 로직 삽입
그럼 우리가 만든 컨트롤러는 실제로 어떤 객체로 바뀌는가?
Spring 부팅 시, @Controller나 @RestController가 붙은 클래스들은 Bean으로 등록된 후,
RequestMappingHandlerMapping이 해당 클래스의 public 메서드를 모두 스캔해서 RequestMappingInfo로 정리해둡니다.
@RequestMapping(path = "/users", method = GET) → HandlerMethod: UserController.list()
이렇게 매핑 테이블이 만들어지고, 요청이 들어오면 그 경로와 method를 기준으로 적절한 HandlerMethod가 호출되는 구조입니다.
응답 방식의 차이: 뷰 vs 바디
// HTML View 반환 @Controller public class WebController { @GetMapping("/home") public String home(Model model) { model.addAttribute("msg", "Hello Spring!"); return "home"; // → home.html } }
// JSON 반환 @RestController public class ApiController { @GetMapping("/api/data") public Map<String, String> data() { return Map.of("message", "Hello JSON"); } }
- @Controller는 ViewResolver를 통해 .html 등을 렌더링
- @RestController는 Jackson 등을 이용해 객체를 JSON 등으로 변환해서 본문에 직접 반환
동작 흐름 요약
요청 → DispatcherServlet → RequestMappingHandlerMapping (어떤 메서드?) → HandlerAdapter (어떻게 실행?) → @Controller or @RestController → 메서드 실행 → 결과 반환 (뷰 이름 or 객체) → ViewResolver (필요 시) → 응답 전송
실무 팁 – RestController에도 ViewResolver가 동작할까?
결론부터 말하자면, @RestController는 ViewResolver를 사용하지 않습니다.
이유는 @ResponseBody가 자동 적용되어 있기 때문입니다.
하지만, 실수로 @RestController에서 문자열을 반환하면 다음과 같은 일이 벌어질 수 있습니다:
@RestController public class WrongController { @GetMapping("/test") public String test() { return "test"; // 텍스트 응답으로 "test"가 감 } }
→ 이걸 @Controller로 바꾸면 "test.html"을 찾으려고 하겠죠?
우리가 매일 쓰는 애노테이션의 이면
스프링이 편한 이유 중 하나는 복잡한 구조를 간단한 애노테이션 하나로 추상화해줬기 때문입니다.
하지만 내부 구조를 이해하면, 디버깅이 쉬워지고 확장도 훨씬 자유로워집니다.
@Controller, @RestController, @RequestMapping의 핵심은 결국 요청을 적절한 메서드로 연결해주는 일입니다.
그리고 이 모든 것은 DispatcherServlet이 뒤에서 조용히 처리하고 있죠.
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
Spring Boot 고급 시리즈 3화 – 트랜잭션 전파와 고립 수준, 언제 어떻게 사용할까? (2) 2025.06.05 Spring AI 시리즈 6화 – RAG 구축하기 (1): Vector Store란 무엇인가 (3) 2025.06.05 Spring Framework 시리즈 12화 – Spring MVC 구조의 출발점: DispatcherServlet과 요청 처리 흐름 (0) 2025.06.03 Spring AI 시리즈 5화 – Prompt Template과 Prompt Engineering 전략 (2) 2025.06.03 Spring Framework 시리즈 11화 – 테스트 가능한 구조 만들기와 DI 테스트 전략 (0) 2025.06.02