서블릿은 언제 만들어지고, 요청은 어떻게 처리될까?
톰캣을 기준으로 서버 기동 시점 → 요청 처리 시점 → 종료 시점까지
서블릿이 어떻게 동작하는지를 전체 흐름으로 정리한다.
서버(톰캣) 기동 시점에 일어나는 일
1) 웹 애플리케이션 로딩
톰캣 서버를 기동하면, 배포된 웹 애플리케이션을 로딩한다.
이 단계는 흔히 “웹앱을 올린다”라고 표현한다.
이때 톰캣은 단순히 파일을 읽는 것이 아니라,
해당 웹앱을 어떻게 실행할지에 대한 내부 준비 작업을 수행한다.
2) 서블릿 매핑 정보 생성 (URL ↔ 서블릿)
웹앱이 로딩되면 톰캣은
“어떤 URL 요청이 어떤 서블릿으로 가야 하는지”에 대한
매핑 테이블을 만든다.
이 매핑 정보는 다음 두 가지 방식 중 하나에서 생성된다.
① web.xml 방식 (전통 방식)
- <servlet>
- <servlet-mapping>
을 읽어서 URL과 서블릿 클래스를 연결한다.
② @WebServlet 어노테이션 방식
- 클래스패스를 스캔한다
- @WebServlet("/hello")가 붙은 클래스를 찾는다
- 해당 URL 패턴을 매핑 테이블에 등록한다
여기서 가장 중요한 점은 다음과 같다.
이 시점은 “서블릿 객체 생성”이 아니라 “매핑 정보 등록” 단계이다.
즉, 이 시점에는 보통 new HelloServlet()이 호출되지 않는다.
3) (선택) load-on-startup이 있는 경우
다음 조건이 있으면 서버 시작 시점에 서블릿 객체를 미리 생성한다.
- web.xml에 <load-on-startup> 설정이 있는 경우
- 또는 환경/설정에 따라 어노테이션 기반 선로딩이 적용된 경우
이 경우 흐름은 다음과 같다.
- new 서블릿() 실행
- init() 메서드 1회 호출
하지만 이 설정이 없다면,
대부분의 서블릿은 첫 요청이 들어올 때 생성된다.
클라이언트 요청이 들어오는 순간의 흐름
이제 브라우저가 실제로 요청을 보내는 시점이다.
1) 브라우저가 HTTP 요청 전송
예를 들어 다음과 같은 요청이 들어온다.
2) 톰캣이 커넥션 수신 후 작업 스레드 할당
톰캣은 요청을 수신하면 다음을 수행한다.
- 스레드 풀에서 작업 스레드 하나를 가져온다
- 해당 스레드가 이 요청을 처리하도록 배정된다
👉 요청은 스레드 단위로 처리된다.
3) 요청/응답 객체 생성
톰캣은 요청 내용을 파싱한 뒤 다음 객체들을 준비한다.
- HttpServletRequest
- HttpServletResponse
실제로는 톰캣 내부 구현체가 존재하고,
그 위에 서블릿 API 인터페이스를 씌운 파사드 객체를 제공한다.
이 객체들은 요청 하나당 새로 생성된다.
4) URL 매핑 테이블 조회
톰캣은 요청 `URL(/hello)`을 보고
서버 시작 시 만들어둔 매핑 테이블을 조회한다.
그 결과,
“이 요청은 HelloServlet이 처리해야 한다”
라는 결론을 얻는다.
5) 서블릿 인스턴스 생성 여부 확인
여기가 가장 핵심적인 포인트이다.
- 해당 서블릿이 아직 한 번도 호출된 적 없다면
- new HelloServlet() 실행
- init() 메서드 1회 호출
- 생성된 인스턴스를 컨테이너가 보관한다
- 이미 한 번 생성된 적이 있다면
- 새로 만들지 않고 기존 인스턴스를 재사용한다
즉,
서블릿 인스턴스는 보통 1개만 생성된다.
6) service() → doGet / doPost 호출
톰캣은 서블릿 인스턴스에 대해 다음을 호출한다.
service(request, response)
`HttpServlet` 내부에서는 `HTTP` 메서드를 확인해 다음으로 분기한다.
- GET 요청 → doGet()
- POST 요청 → doPost()
이 메서드들은 요청마다 호출된다.
7) 응답 생성 및 전송
서블릿 코드에서
response.getWriter().write(...)
등으로 응답을 작성하면,
- 톰캣이 헤더와 바디를 조합한다
- 소켓을 통해 클라이언트(브라우저)로 전송한다
요청 처리가 끝나면 다음과 같은 일이 일어난다.
- request / response 객체는 버려진다
- 작업 스레드는 스레드 풀로 반환된다
- 서블릿 인스턴스는 살아남아 재사용된다
서버 또는 웹앱 종료 시점
destroy() 호출
톰캣 서버를 종료하거나
웹 애플리케이션을 내릴 때 다음 작업이 수행된다.
- 서블릿마다 destroy() 메서드 1회 호출
이 메서드는 자원 정리 목적이다.
정리
- URL ↔ 서블릿 매핑 등록은 서버 시작 시점
- 서블릿 객체 생성은 보통 첫 요청 시점
- 요청마다 생성되는 것은 request / response 객체
- 서블릿 인스턴스는 1개 생성 후 계속 재사용
- 종료 시점에만 destroy()가 1회 호출된다
이 흐름이 이해되면
- 왜 서블릿 필드에 상태를 두면 위험한가
- 왜 멀티스레드 문제가 발생하는가
- 왜 request는 안전하고 session은 공유되는가
이런 의문들도 자연스럽게 풀린다.
'Backend > Servlet' 카테고리의 다른 글
| forward와 JSP 실행 흐름 (0) | 2026.02.06 |
|---|---|
| 멀티스레드 환경에서 Servlet 사용 (0) | 2026.02.06 |
| Servlet Container와 Servlet의 관계 (0) | 2026.02.05 |
| RequestMapping static Map은 괜찮은 이유 (0) | 2026.02.05 |
| 서블릿에서의 static (0) | 2026.02.05 |