서블릿 객체의 생명주기가 궁금해요!

서블릿 객체(Servlet)와 쓰레드(Thread)란?
"서블릿은 클라이언트의 요청을 처리하는 자바 객체이고, 쓰레드는 이를 병렬로 실행하는 작업 단위이다!"
📌 서블릿 컨테이너, 쓰레드 관리, 그리고 서버 확장 기법
이번 글에서는 서블릿 컨테이너(Servlet Container)의 역할, 쓰레드(Thread)와 객체 재사용 원리, 그리고 **서버 확장 전략(Scaling)**에 대해 정리하겠습니다.
✅ 서블릿(Servlet) 객체란?
"클라이언트 요청을 처리하는 자바 기반의 웹 컴포넌트!"
📌 서블릿의 특징
✅ 웹 브라우저의 요청을 처리하고 응답을 반환
✅ 최초 요청 시 한 번만 생성되며, 이후에는 재사용됨
✅ 여러 요청을 동시에 처리하기 위해 쓰레드(Thread)를 활용
📌 "서블릿은 요청이 들어오면 실행되며, 쓰레드를 통해 동시 요청을 처리한다!"
✅ 쓰레드(Thread)란?
"프로그램 내에서 독립적으로 실행되는 작업 단위!"
📌 쓰레드의 특징
✅ 멀티쓰레드(Multi-Threading) 방식으로 동작
✅ 여러 개의 요청을 동시에 처리 가능
✅ 쓰레드 풀(Thread Pool)을 활용하여 재사용 가능
📌 "서블릿 하나만 있어도 여러 개의 쓰레드가 생성되어 동시 요청을 처리할 수 있다!"
✅ 서블릿 컨테이너(Servlet Container)란?
"클라이언트 요청을 받아 서블릿(Servlet)을 실행하고, 쓰레드를 생성하여 요청을 처리하는 역할을 하는 소프트웨어 환경!"
📌 서블릿 컨테이너의 역할
✅ 클라이언트 요청(Request) 수신
✅ 서블릿 객체(Servlet) 생성 및 실행
✅ 요청을 처리할 쓰레드(Thread) 생성
✅ 처리 결과를 클라이언트에게 응답(Response)
📌 "서블릿 컨테이너는 클라이언트 요청을 효율적으로 처리하고, 서블릿과 쓰레드를 관리하는 핵심 요소!"
✅ 톰캣(Tomcat)과 웹 서버(Apache) 차이
"정적인 파일은 웹 서버(Apache)가 처리하고, 동적인 요청은 톰캣(Tomcat)이 처리한다!"
📌 톰캣과 웹 서버 비교
| 구분 | 웹 서버(Apache) | 서블릿 컨테이너(Tomcat) |
| 처리 방식 | HTML, CSS, JS 같은 정적 파일 처리 | 자바 서블릿(Servlet), JSP 같은 동적 요청 처리 |
| 작동 방식 | 요청된 파일을 그대로 반환 | 요청을 분석 후 서블릿을 실행하고 HTML로 변환 |
| 예제 요청 | index.html, style.css | user/login, product/list (JSP, Servlet) |
📌 "정적인 파일은 Apache, 동적인 요청은 Tomcat이 처리한다!"
✅ URL vs URI – 차이점 간단 정리
"URL은 자원의 '위치'를, URI는 자원의 '식별자'를 의미한다!"
| 구분 | 설명 | 예시 |
| URL (Uniform Resource Locator) | 특정 자원의 위치(주소) 를 나타냄 | https://example.com/index.html |
| URI (Uniform Resource Identifier) | 자원의 식별자 (위치 포함 가능) | /users/123, mailto:user@example.com |
📌 "모든 URL은 URI이지만, 모든 URI가 URL은 아니다!"
✅ 스프링은 URI를 사용한다
"스프링에서는 파일 경로(URL)를 직접 요청하지 않고, URI를 통해 자원을 식별하여 처리한다!"
📌 스프링에서는 정적 파일(URL)이 아닌, URI를 통해 요청을 처리한다!
❌ URL 요청: `https://example.com/images/logo.png`
✅ URI 요청: `https://example.com/api/users/1`
📌 "스프링에서는 URL이 아닌 URI를 사용하여 컨트롤러에서 요청을 처리한다!"
✅ 요청 처리 흐름 – 서블릿과 쓰레드(Thread)의 역할
"클라이언트 요청이 들어오면, 서블릿 컨테이너는 서블릿 객체와 쓰레드를 사용해 요청을 처리한다!"
🔹 서블릿 요청 처리 과정
1️⃣ 클라이언트가 요청(Request) 보냄
2️⃣ 서블릿 컨테이너가 요청을 수신
3️⃣ 서블릿 객체 생성 (최초 요청 시 1번만 생성됨)
4️⃣ 새로운 쓰레드(Thread) 생성 후 요청을 처리
5️⃣ 응답(Response) 반환 후 쓰레드 재사용 (Thread Pool)
📌 "최초 요청 시 서블릿 객체가 생성되며, 이후에는 동일한 객체를 재사용한다!"

✅ 서블릿 생명주기와 주요 메서드 (init(), service(), doGet() 등)
"서블릿은 생성 → 요청 처리 → 종료의 과정을 거치며, 각각의 단계에서 특정 메서드가 호출된다!"
✅ 서블릿의 생명주기(Lifecycle)
"서블릿은 클라이언트 요청을 처리하기 위해 특정 메서드를 실행하며, 최초 실행부터 종료까지 다음과 같은 흐름을 따른다!"
🔹 서블릿 동작 과정
1️⃣ 클라이언트 요청 발생 (Request)
2️⃣ 서블릿 컨테이너가 서블릿 객체를 생성 (init() 호출)
3️⃣ 요청에 따라 service() 메서드 실행 (doGet(), doPost() 등 호출)
4️⃣ 응답을 반환 (Response)
5️⃣ 서버가 종료되거나 필요하지 않으면 destroy() 메서드 호출 → 서블릿 종료
📌 "서블릿은 요청이 처음 발생할 때만 생성되며, 이후에는 같은 객체를 재사용한다!"
✅ 서블릿의 주요 메서드
"서블릿은 생명주기에 따라 init(), service(), doGet(), doPost() 등의 메서드를 실행한다!"
🔹 init() – 서블릿 초기화 (최초 요청 시 1번만 실행)
- 서블릿이 처음 로드될 때 1번만 실행되는 초기화 메서드
- 설정값을 불러오거나, DB 연결을 설정할 때 사용
@Override
public void init() throws ServletException {
System.out.println("서블릿 초기화 - init() 실행!");
}
📌 "서블릿이 처음 요청될 때 한 번만 실행되며, 이후에는 다시 실행되지 않는다!"
🔹 service() – 요청을 받아 적절한 메서드로 전달
- 모든 HTTP 요청(GET, POST 등)을 처리하는 중앙 메서드
- 클라이언트가 요청하면 doGet(), doPost() 같은 메서드를 호출
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
System.out.println("요청 처리 - service() 실행!");
if (req.getMethod().equals("GET")) {
doGet(req, res);
} else if (req.getMethod().equals("POST")) {
doPost(req, res);
}
}
📌 "service()는 요청이 들어올 때마다 실행되며, 적절한 메서드(doGet(), doPost())를 호출한다!"
🔹 doGet() – GET 요청 처리 (조회 요청)
- GET 방식의 HTTP 요청을 처리
- 보통 데이터 조회 시 사용됨
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<h1>GET 요청 처리</h1>");
}
📌 "클라이언트가 GET 방식으로 요청하면 doGet()이 실행된다!"
🔹 doPost() – POST 요청 처리 (데이터 등록/변경 요청)
- POST 방식의 HTTP 요청을 처리
- 보통 데이터 생성, 업데이트 요청 시 사용됨
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<h1>POST 요청 처리</h1>");
}
📌 "클라이언트가 POST 방식으로 요청하면 doPost()가 실행된다!"
✅ 서블릿 생명주기 정리
| 메서드 | 실행 시점 | 실행 횟수 | 역할 |
| init() | 서블릿이 처음 로드될 때 | 한 번만 실행 | 서블릿 초기화 |
| service() | 클라이언트가 요청할 때마다 | 여러 번 실행 | 요청을 적절한 메서드로 전달 |
| doGet() | GET 요청이 들어올 때 | 여러 번 실행 | 데이터 조회 처리 |
| doPost() | POST 요청이 들어올 때 | 여러 번 실행 | 데이터 등록/수정 처리 |
| destroy() | 서블릿이 종료될 때 | 한 번만 실행 | 리소스 정리 |
📌 "서블릿은 init()으로 초기화되고, service()를 통해 요청을 받아 doGet(), doPost() 등의 메서드로 분기 처리된다!"
✅ 쓰레드(Thread)와 쓰레드 풀(Thread Pool) 개념
"매 요청마다 쓰레드를 새로 생성하지 않고, 미리 만들어진 쓰레드를 재사용하여 성능을 최적화한다!"
🔹 쓰레드 풀(Thread Pool) 작동 원리
- 최대 동시 요청 개수만큼 미리 쓰레드 생성
- 새로운 요청이 오면 기존 쓰레드를 재사용
- 동시 요청이 많아질 경우, 쓰레드 풀 최대 개수를 초과하면 대기 상태로 전환
📌 "서버는 필요할 때마다 쓰레드를 새로 생성하는 것이 아니라, 기존 쓰레드를 재사용하여 리소스를 절약한다!"
🔹 쓰레드 풀의 장점
| 기존 방식 (쓰레드 생성 & 제거) | 쓰레드 풀 (Thread Pool) |
| 요청이 올 때마다 쓰레드를 새로 생성 | 미리 생성된 쓰레드를 재사용 |
| 쓰레드 생성 & 제거 비용 큼 | 성능 최적화, 리소스 절약 |
| 요청이 많아질수록 서버 부하 증가 | 정해진 개수 내에서 효율적으로 관리 |
📌 "쓰레드 풀을 사용하면 요청 처리 속도를 최적화할 수 있다!"
✅ 동시 요청 한계 – 최대 쓰레드 수 설정
"서버는 동시 요청을 처리할 수 있는 최대 쓰레드 개수를 설정하여 부하를 조절한다!"
🔹 동시 요청 개수 예제
✅ 최대 쓰레드 수: 20개
✅ 동시 접속자 수: 25명
1️⃣ 처음 20명의 요청은 즉시 처리됨
2️⃣ 추가 5명은 대기 상태로 전환됨
3️⃣ 기존 요청이 완료되면, 대기 중인 요청을 처리
📌 "최대 동시 요청 개수를 초과하면 일부 요청은 대기 상태가 된다!"
✅ 서버 성능 확장 전략 – 스케일 업 vs 스케일 아웃
"트래픽이 많아질 경우, 성능을 확장하는 방법에는 스케일 업(Scale Up)과 스케일 아웃(Scale Out)이 있다!"
🔹 스케일 업(Scale Up)
- 서버 성능을 업그레이드하여 더 많은 요청을 처리
- CPU, RAM, 네트워크 성능을 향상
📌 "더 강력한 하드웨어로 서버를 업그레이드하여 성능을 높이는 방법!"
🔹 스케일 아웃(Scale Out)
- 서버 개수를 늘려서 트래픽을 분산
- 여러 대의 서버가 동시에 요청을 처리 (로드 밸런싱 적용)
📌 "여러 대의 서버를 추가하여 트래픽을 분산 처리하는 방법!"
✅ 스케일 업 vs 스케일 아웃 비교
| 방식 | 설명 | 장점 | 단점 |
| 스케일 업 | 서버 성능을 업그레이드 | 간단한 적용, 추가 장비 불필요 | 하드웨어 한계 존재 |
| 스케일 아웃 | 서버 개수를 늘려 트래픽 분산 | 무한 확장 가능, 로드 밸런싱 적용 가능 | 서버 관리 비용 증가 |
📌 "트래픽이 많아질 경우, 일반적으로 스케일 아웃(Scale Out) 방식을 선호한다!"
🔥 핵심 정리
| 개념 | 설명 |
| 서블릿 컨테이너 | 서블릿 객체와 쓰레드를 관리하는 환경 (예: 톰캣) |
| 웹 서버(Apache) | 정적 파일(HTML, CSS, JS) 처리 |
| 톰캣(Tomcat) | 자바 서블릿(Servlet), JSP 같은 동적 요청 처리 |
| 쓰레드(Thread) | 요청을 병렬로 처리하는 작업 단위 |
| 쓰레드 풀(Thread Pool) | 미리 생성된 쓰레드를 재사용하여 성능 최적화 |
| 최대 동시 요청 개수 | 설정된 쓰레드 개수를 초과하면 일부 요청은 대기 |
| 스케일 업 (Scale Up) | 서버 성능을 업그레이드하여 처리량 증가 |
| 스케일 아웃 (Scale Out) | 여러 대의 서버를 추가하여 트래픽 분산 |
📢 마무리
서블릿 컨테이너는 클라이언트 요청을 처리하기 위해 서블릿 객체와 쓰레드를 관리하는 역할을 합니다.
📌 쓰레드 풀(Thread Pool)을 사용하면 서버의 성능을 최적화할 수 있으며,
📌 트래픽 증가 시 스케일 업(Scale Up) 또는 스케일 아웃(Scale Out) 전략을 활용하여 확장할 수 있습니다!

'스프링(Spring) 및 자바(JAVA)' 카테고리의 다른 글
| 스프링 부트 개념 정리 - 이론12 (0) | 2025.03.11 |
|---|---|
| 스프링 부트 개념 정리 - 이론11 (0) | 2025.03.11 |
| 스프링 부트 개념 정리 - 이론09 (0) | 2025.03.09 |
| 스프링 부트 개념 정리 - 이론08 (0) | 2025.03.09 |
| 스프링 부트 개념 정리 - 이론07 (0) | 2025.03.08 |