[Spring Boot] Spring Boot는 무엇이고, 요청은 어떻게 처리될까? - Servlet과 DispatcherServlet

이전 글에서는 API 명세서와 RESTful API 설계에 대해 정리했습니다.

그때는 GET /users/{id} 같은 형태로 API를 어떻게 설계할지에 집중했다면,

이번에는 그 다음 단계인 **“그 요청이 실제로 서버 안에서 어떻게 처리되는지”**를 정리해보려고 합니다.

백엔드 공부를 처음 시작하면

@RestController, @GetMapping, @PostMapping 같은 어노테이션을 먼저 접하게 됩니다.

그래서 처음에는 “그냥 이렇게 작성하면 요청이 연결되는구나” 정도로 이해하고 넘어가기 쉽습니다.

그런데 한 번쯤은 이런 궁금증이 생깁니다.

“브라우저나 앱에서 요청을 보내면, 그 요청은 어떻게 내가 작성한 Controller 메서드까지 도달할까?”

이번 글에서는 이 흐름을 이해하기 위해

먼저 Spring Boot가 무엇인지,

그리고 그 위에서 돌아가는 Servlet, DispatcherServlet,

마지막으로 클라이언트 요청이 Controller까지 도달하는 과정을 차근차근 정리해보겠습니다.


Spring Boot란?

Spring Boot는 Spring 기반 애플리케이션을 더 쉽고 빠르게 시작할 수 있게 도와주는 도구입니다.

Spring 자체는 굉장히 강력한 프레임워크이지만, 처음 접하면 설정해야 할 것도 많고 구조도 꽤 크게 느껴집니다.

반면 Spring Boot는 자주 사용하는 설정을 기본적으로 잡아주고, 프로젝트를 바로 실행할 수 있는 형태로 만들어주기 때문에 개발자가 훨씬 빠르게 기능 구현에 들어갈 수 있습니다.

쉽게 말하면

Spring이 “강력하지만 처음엔 조금 무겁게 느껴질 수 있는 프레임워크”라면,

Spring Boot는 그 Spring을 훨씬 실용적으로 시작하게 해주는 도구라고 볼 수 있습니다.

저도 처음에는 Spring Boot를 그냥 “Spring을 더 편하게 쓰게 해주는 버전” 정도로 생각했는데,

공부할수록 단순히 편리한 수준이 아니라 웹 애플리케이션을 빠르게 만들고 실행할 수 있게 해주는 시작점이라는 느낌이 더 강했습니다.


왜 Spring Boot를 많이 사용할까?

Spring Boot가 많이 쓰이는 이유는 결국

빠르게 시작할 수 있고, 바로 실행해볼 수 있기 때문이라고 생각합니다.

예를 들어 백엔드 프로젝트를 시작할 때

설정 파일을 하나하나 맞추고, 서버를 따로 준비하고, 실행 환경을 복잡하게 잡는 과정이 길어지면

정작 중요한 비즈니스 로직을 구현하기 전에 지치기 쉽습니다.

그런데 Spring Boot는 이런 초기 부담을 많이 줄여줍니다.

특히 체감되는 장점은 이런 부분이었습니다.

1. 설정을 많이 줄여준다

처음부터 복잡한 설정을 전부 직접 하지 않아도 되기 때문에

프로젝트를 시작하는 속도가 빠릅니다.

2. 실행까지 가는 흐름이 짧다

코드를 작성하고 바로 실행해서

HTTP 요청을 보내보고 응답을 확인하는 경험까지 가는 속도가 빠릅니다.

3. 웹 애플리케이션을 만들기에 편하다

Spring MVC와 함께 사용하면

컨트롤러를 만들고, 요청을 매핑하고, JSON 응답을 주는 흐름까지 비교적 자연스럽게 이어집니다.

그래서 백엔드 입문자 입장에서도 “이론만 배우는 것”이 아니라

직접 API를 만들고 테스트해보는 경험을 가져갈 수 있다는 점이 큰 장점이라고 느꼈습니다.


서블릿이란?

Spring Boot에서 요청 처리 흐름을 이해하려면 먼저 서블릿(Servlet) 이라는 개념을 알아야 합니다.

서블릿은 간단히 말하면

클라이언트의 HTTP 요청을 받아서 처리하고, 그 결과를 응답으로 돌려주는 자바 기반 서버 기술입니다.

브라우저나 앱이 서버에 요청을 보내면 서버는 그 요청을 받아 처리해야 합니다.

자바 웹 기술에서는 이 역할을 하는 기반이 바로 서블릿입니다.

즉,

  • 요청이 들어오고
  • 서버 쪽에서 이를 해석하고
  • 필요한 로직을 수행한 뒤
  • 응답을 만들어서 돌려주는

이 기본적인 웹 요청/응답 구조를 자바에서 담당하는 기술이 서블릿이라고 이해하면 됩니다.

중요한 점은, 우리가 Spring Boot와 Spring MVC를 사용한다고 해서

서블릿과 완전히 별개의 구조 위에서 동작하는 것은 아니라는 점입니다.

오히려 Spring MVC는

이 서블릿 기반 위에서 더 편리하게 웹 애플리케이션을 만들 수 있도록 구성된 프레임워크에 가깝습니다.

즉, 우리가 평소에 사용하는 Controller도

결국은 이 서블릿 기반 요청 처리 흐름 위에서 동작하고 있는 것입니다.


DispatcherServlet이란?

Spring MVC에서 가장 핵심적인 역할을 하는 것이 바로 DispatcherServlet입니다.

이름만 보면 조금 낯설 수 있는데,

쉽게 말하면 스프링 MVC의 중앙 관리자라고 생각하면 됩니다.

클라이언트 요청이 들어오면 Spring MVC는 이 요청을 먼저 DispatcherServlet이 받습니다.

그리고 이 DispatcherServlet이

  • 어떤 컨트롤러가 이 요청을 처리해야 하는지 찾고
  • 그 컨트롤러 메서드를 실행하도록 연결하고
  • 최종적으로 응답이 나갈 수 있도록 흐름을 조정합니다.

즉, DispatcherServlet은 요청을 받아서 적절한 곳으로 분배(dispatch) 해주는 역할을 합니다.

그래서 Spring MVC를 이해할 때 자주 나오는 표현이 Front Controller 패턴입니다.

예전처럼 요청마다 각각 따로 처리하는 것이 아니라,

중앙에서 먼저 요청을 받고 공통 흐름을 제어한 뒤 적절한 컨트롤러로 넘겨주는 구조라고 보면 됩니다.

처음에는 이 개념이 조금 추상적으로 느껴졌는데, 막상 흐름을 떠올려보면 꽤 자연스럽습니다.

브라우저가 서버에 바로 “컨트롤러 3번 실행해주세요”라고 말하는 게 아니라,

먼저 중앙에 있는 DispatcherServlet이 요청을 받고

“이 요청은 이 컨트롤러가 처리해야겠네” 하고 연결해주는 방식인 것입니다.


클라이언트 요청은 Controller까지 어떻게 도달할까?

이제 가장 중요한 부분인 요청 처리 흐름을 정리해보겠습니다.

예를 들어 아래와 같은 API가 있다고 가정해보겠습니다.

@GetMapping("/users/{id}")
public UserResponse getUser(@PathVariable Long id) {
    return userService.findById(id);
}

클라이언트가 GET /users/1 요청을 보내면

Spring 내부에서는 대략 이런 흐름으로 요청이 처리됩니다.

1. 클라이언트가 HTTP 요청을 보낸다

브라우저, 앱, Postman 같은 클라이언트가

서버에 GET /users/1 요청을 보냅니다.

이 단계는 우리가 API 명세서를 설계할 때 보던 바로 그 요청입니다.

이전 글에서 정리했던 엔드포인트가 이제 실제로 사용되는 순간이라고 볼 수 있습니다.

2. 서버가 요청을 받는다

Spring Boot 애플리케이션이 실행 중이라면

서버는 들어온 HTTP 요청을 받게 됩니다.

여기서부터 본격적으로 “이 요청을 누가 처리할 것인가?”를 찾는 과정이 시작됩니다.

3. DispatcherServlet이 요청을 먼저 받는다

Spring MVC에서는 DispatcherServlet이 요청을 먼저 받습니다.

즉, 요청 처리의 시작점은 Controller가 아니라 DispatcherServlet입니다.

그래서 스프링에서는 컨트롤러가 마치 바로 요청을 받는 것처럼 보이지만,

실제로는 그 전에 항상 DispatcherServlet이 한 번 요청을 받아서 정리해주는 단계가 있습니다.

4. 어떤 컨트롤러가 처리할지 찾는다

이제 DispatcherServlet은 들어온 요청의 URL, HTTP 메서드 같은 정보를 보고

어떤 컨트롤러 메서드가 이 요청을 처리해야 하는지 찾습니다.

예를 들어 요청이 GET /users/1이라면

@GetMapping("/users/{id}")가 붙은 메서드가 후보가 됩니다.

즉, 우리가 작성한 @GetMapping, @PostMapping 같은 어노테이션은

이 단계에서 요청과 메서드를 연결하는 기준이 됩니다.

5. 컨트롤러 메서드를 실행한다

처리할 메서드를 찾았으면

이제 실제로 그 컨트롤러 메서드를 실행합니다.

이 과정에서 PathVariable, RequestParam, RequestBody 같은 값들도

스프링이 알아서 꺼내서 메서드 파라미터에 넣어줍니다.

그래서 우리는 Controller에서

@PathVariable Long id

처럼 선언만 해도 요청 URL의 값을 자연스럽게 받을 수 있는 것입니다.

6. 컨트롤러가 응답 값을 반환한다

컨트롤러 메서드가 실행되면

문자열이나 객체, DTO 같은 응답 값을 반환합니다.

@RestController를 사용하고 있다면

보통 이 반환값은 JSON 응답으로 이어집니다.

즉, 우리는 자바 객체를 반환했지만

클라이언트는 JSON 형태의 응답을 받게 됩니다.

7. 응답이 클라이언트에게 전달된다

마지막으로 스프링이 컨트롤러의 반환값을

HTTP 응답 형식으로 바꿔서 클라이언트에게 돌려줍니다.

그래서 브라우저나 Postman에서는

최종적으로 JSON 응답, 상태 코드, 헤더 등을 확인할 수 있게 됩니다.


한 번에 정리하면 이런 흐름이다!

지금까지 내용을 한 줄로 정리하면 이렇습니다.

클라이언트 요청 → 서버 → DispatcherServlet → 컨트롤러 매핑 탐색 → 컨트롤러 실행 → 응답 반환

처음에는 @GetMapping 하나만 보였는데,

실제로는 이 뒤에서 DispatcherServlet이 요청을 받고,

적절한 컨트롤러를 찾고, 실행 결과를 다시 응답으로 돌려주는 흐름이 존재하는 것입니다.

이걸 이해하고 나면

스프링 MVC가 단순히 “어노테이션 몇 개로 API를 만드는 기술”이 아니라,

웹 요청을 체계적으로 처리하기 위한 구조라는 점이 훨씬 잘 보이게 됩니다.


왜 이 흐름을 이해해야 할까?

처음에는 API가 잘 동작하기만 하면 충분하다고 느낄 수 있습니다.

저도 처음에는 “요청 보내면 응답 오네, 그러면 된 거 아닌가?”

정도로 생각했던 적이 있습니다.

그런데 요청 흐름을 한 번 이해하고 나면 컨트롤러를 보는 시선이 달라집니다.

예를 들어

  • 왜 @GetMapping으로 URL을 명확하게 연결해야 하는지
  • 왜 컨트롤러가 요청 처리의 시작점처럼 보이는지
  • 왜 @RestController를 쓰면 JSON 응답이 나가는지
  • 왜 잘못된 경로로 요청하면 404가 뜨는지

같은 것들이 전부 하나의 흐름 안에서 연결됩니다.

즉, 스프링 코드를 단순히 외워서 쓰는 것이 아니라

“내가 작성한 코드가 요청 처리 전체 흐름 안에서 어디에 위치하는지” 이해할 수 있게 됩니다.

그리고 이 지점이 이전 글에서 다룬 API 설계와도 자연스럽게 이어집니다.

이전 글이 “어떤 API를 만들 것인가”에 대한 이야기였다면,

이번 글은 “그 API가 실제로 서버 안에서 어떻게 동작하는가”에 대한 이야기이기 때문입니다.


마무리

이번 글에서는

Spring Boot가 무엇인지,

왜 많이 사용하는지,

서블릿이 무엇인지,

그리고 클라이언트 요청이 Controller까지 도달하는 흐름을 정리해봤습니다.

정리하면 이렇게 볼 수 있습니다.

  • Spring Boot는 Spring 애플리케이션을 더 빠르고 쉽게 시작할 수 있게 도와주는 도구입니다.
  • Spring MVC는 서블릿 기반 위에서 동작합니다.
  • DispatcherServlet은 요청을 가장 먼저 받고, 적절한 컨트롤러로 연결해주는 핵심 역할을 합니다.
  • 우리가 작성한 @GetMapping, @PostMapping 메서드는 이 흐름 안에서 실행됩니다.

이전 글이 API를 어떻게 설계할지에 대한 내용이었다면,

이번 글은 설계한 API가 서버 안에서 어떻게 처리되는지에 대한 정리였습니다.

다음 글에서는 여기서 한 단계 더 들어가서,

Controller와 Service 같은 객체를 스프링이 어떻게 만들고 연결하는지,

IoC, DI, 스프링 빈에 대해 정리해보려고 합니다.