Spring Boot에서 @RestController 요청 처리 과정

Pure·2025년 5월 25일
2

Spring

목록 보기
4/9

Spring Boot를 이용한 RESTful 웹 개발을 하다 보면 @RestController를 달아둔 메서드만 작성해도 간단하게 JSON 응답이 반환됩니다. 하지만 내부적으로는 수많은 컴포넌트가 유기적으로 동작하며 이 결과를 만들어냅니다.

이번 글에서는 Spring Boot에서 HTTP 요청이 들어와 @RestController가 이를 처리하고, 응답으로 변환되어 반환되기까지의 전체 과정을 이해하는 데 초점을 맞춰 설명하겠습니다.

🎯 요청-응답 처리 흐름 한눈에 보기

[클라이언트 요청]
        ↓
DispatcherServlet
        ↓
HandlerMapping → Handler(Controller)
        ↓
HandlerAdapter 호출
        ↓
Controller 메서드 실행
        ↓
[응답 객체 반환]
        ↓
HttpMessageConverter가 객체 → JSON 등으로 변환
        ↓
HttpServletResponse에 응답 작성
        ↓
[클라이언트 응답 전달]

1. DispatcherServlet: 프론트 컨트롤러 역할

모든 HTTP 요청은 DispatcherServlet을 통해 시작됩니다. Spring Boot는 내부적으로 / 경로에 DispatcherServlet을 자동 등록하여 모든 요청을 이 객체가 받아들이도록 합니다.

@Configuration
public class WebConfig {
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }
}

DispatcherServlet의 역할:

  • 요청을 적절한 컨트롤러로 위임
  • 응답을 받아서 최종적으로 클라이언트에 반환

2. HandlerMapping: 어떤 컨트롤러가 처리할지 결정

DispatcherServlet은 내부적으로 등록된 여러 HandlerMapping 중 적절한 매핑을 통해 요청을 처리할 Handler(Controller 메서드)를 찾습니다.

대표적으로는 다음과 같은 매핑 전략이 있습니다:

  • RequestMappingHandlerMapping: @RequestMapping, @GetMapping 등을 분석
  • SimpleUrlHandlerMapping: XML 또는 수동 등록 핸들러

예시: GET /users 요청 → UserController.getUsers()

3. HandlerAdapter: Handler 실행을 돕는 어댑터

찾아낸 핸들러는 객체일 뿐 실행 방법을 DispatcherServlet이 직접 알 수 없습니다. 그래서 필요한 것이 HandlerAdapter입니다.

RequestMappingHandlerAdapter: @RestController, @Controller 메서드를 실행해줌

인자 바인딩, 유효성 검사, @RequestBody 변환 등도 여기서 수행

핸들러 메서드를 호출한 결과로 Java 객체가 반환됩니다.

4. @RestController와 응답 반환

@RestController는 @Controller + @ResponseBody가 결합된 애노테이션입니다.

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping
    public List<User> getUsers() {
        return userService.findAll();
    }
}

위처럼 반환된 List<User>는 View 이름이 아니라 객체 자체이므로, 이 객체를 HTTP 응답 본문으로 변환해주는 과정이 필요합니다.

@RestController와 @Controller의 차이점 자세히 보기

5. HttpMessageConverter: 응답 객체를 JSON으로 변환

이 시점에 등장하는 핵심 컴포넌트가 바로 HttpMessageConverter입니다.

Spring은 Java 객체를 HTTP 응답 본문으로 직렬화(serialize)하거나, 반대로 요청 본문을 Java 객체로 역직렬화(deserialize)할 때 이 컴포넌트를 사용합니다.

동작 타이밍

  • 요청 처리 시: @RequestBody → JSON을 객체로 변환

  • 응답 처리 시: 컨트롤러가 반환한 객체 → JSON으로 변환 (여기서 사용!)

기본 컨버터들

클래스설명
MappingJackson2HttpMessageConverterJSON 변환 (Jackson 기반)
StringHttpMessageConverter문자열 처리
ByteArrayHttpMessageConverter바이너리 처리
FormHttpMessageConverterx-www-form-urlencoded 처리

Spring Boot는 자동으로 MappingJackson2HttpMessageConverter를 등록하고, application/json으로 응답을 보냅니다.

6. 최종 응답 전송

변환된 JSON 문자열은 HttpServletResponse 객체에 작성되며, 상태 코드와 Content-Type 헤더도 함께 설정됩니다.

HTTP/1.1 200 OK
Content-Type: application/json

[
  {
    "id": 1,
    "name": "Juyong"
  }
]

7. 정리: 핵심 흐름

단계설명
1DispatcherServlet이 요청 수신
2HandlerMapping이 적절한 Controller 메서드 탐색
3HandlerAdapter가 메서드 실행
4@RestController 메서드가 객체 반환
5HttpMessageConverter가 객체를 JSON 등으로 직렬화
6응답 본문으로 작성되어 클라이언트에 전송

[옵션] @RestController vs @Controller: 언제 어떤 걸 써야 할까?

Spring에서는 @Controller와 @RestController를 모두 제공하는데, 두 애노테이션은 사용하는 상황과 목적이 다릅니다.

애노테이션주로 쓰는 상황반환 결과설명
@Controller웹 페이지 렌더링View 이름 (HTML, JSP 등)서버에서 뷰 템플릿을 조합해 HTML을 반환하고 싶은 경우
@RestControllerREST API 응답JSON, XML, 문자열 등데이터를 API 형태로 전달하고 싶은 경우 (프론트엔드 분리 구조에 적합)

예제 1: @Controller를 사용하는 상황

HTML을 직접 렌더링하여 브라우저에 전달하고 싶을 때 사용.

@Controller
public class HomeController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("username", "이주용");
        return "home";  // templates/home.html 이 렌더링됨 (Thymeleaf 등)
    }
}

예제 2: @RestController를 사용하는 상황

데이터를 JSON으로 응답하여 클라이언트 애플리케이션에서 처리하도록 할 때

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

    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();  // 자동으로 JSON으로 변환됨
    }
}

참고하면 좋은 글

🔗 Spring 공식 문서: Web MVC DispatcherServlet
🔗 Velog: SOAP에서 REST로의 전환

profile
Clean Code를 위한 한 걸음

0개의 댓글