인프런 김영한 강사님의 스프링 MVC 강의를 들으며 애매모호하게 알고 있던 개념에 대해 다시 배우고 있다.
아래는 웹 애플리케이션에 대한 강의를 간략하게 정리한 것이다.
모든 건 HTTP로부터 시작된다 – 서블릿과 스프링 웹의 기본 이해
HTTP 요청 하나가 오면, 그 뒤에서 어떤 일이 일어날까?
서버는 어떻게 요청을 해석하고, 어떻게 응답을 만들어줄까?
이번 글에서는 웹 서버와 서블릿, WAS의 역할을 이해하면서 스프링 웹의 기반이 되는 구조를 정리한다.
웹 시대의 중심은 HTTP
HTTP는 모든 것을 전송할 수 있다.
텍스트, 이미지, 음성, 영상은 물론이고, 우리가 자주 쓰는 JSON, XML 같은 데이터 형식도 모두 HTTP로 오간다.
심지어 서버 간 데이터 통신도 대부분 HTTP를 사용한다.
요즘 시대, 웹을 다룬다면 결국 HTTP를 다루는 것이다.
웹 서버와 웹 애플리케이션 서버(WAS)는 뭐가 다른가?
| 구성요소 | 역할 |
|---|---|
| 웹 서버(Web Server) | 정적인 리소스(HTML, CSS, JS, 이미지 등) 제공 |
| WAS(Web Application Server) | 웹 서버 기능 + 프로그램 코드 실행 + 동적인 처리 |
예시로 구분하자면
- 웹 서버: NGINX, Apache
- WAS: Tomcat, Jetty
즉, 정적 리소스는 웹 서버,
비즈니스 로직은 WAS가 처리한다.
웹 시스템 구성: 왜 웹 서버와 WAS를 나눌까?
단일 WAS만으로도 모든 것을 처리할 수 있다.
하지만 이렇게 되면 정적 리소스 요청 하나 때문에 WAS가 낭비된다.
그래서 구조를 나눈다:
[WEB 서버] → 정적 파일 처리
↓ (동적 로직 필요)
[WAS] → 애플리케이션 로직 실행장점
- 웹 서버가 정적 리소스 부하를 먼저 받아줌
- WAS는 비싼 로직 처리에 집중 가능
- 서버 자원 효율적 사용 → 성능 향상
WAS는 어떻게 요청을 처리할까?
HTTP 요청이 들어오면 다음과 같은 일이 일어난다:
- TCP/IP 소켓 연결 수립
- HTTP 메시지 파싱
- URL 분석 (
/save) - POST 방식이면 바디 파싱 (e.g.,
username=kim&age=20) - 파싱한 데이터를 바탕으로 비즈니스 로직 실행
- HTTP 응답 메시지 구성 (
200 OK, HTML or JSON 등) - TCP 응답 전송, 소켓 종료
이걸 개발자가 직접 구현해야 한다면?
엄청난 고생이다. 그래서 등장한 것이 **서블릿(Servlet)**이다.
서블릿이란?
서블릿은 WAS(Tomcat 등)가 제공하는 HTTP 요청 처리용 자바 클래스다.
서블릿 컨테이너가 다음을 처리해준다:
- HTTP 메시지 파싱
- 요청 정보 전달 (
HttpServletRequest) - 응답 정보 설정 (
HttpServletResponse) - 객체 생성/초기화/소멸 관리
- 멀티 쓰레드 처리
서블릿 기본 예시
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
// 요청 정보 꺼내기
// 응답 작성
}
}
이 코드를 등록하면 /hello로 들어온 요청은 이 서블릿이 처리한다.
서블릿 컨테이너가 해주는 일
- 최초 요청 시 서블릿 객체를 한 번만 생성
- 이후 요청마다 동일한 서블릿 객체에 쓰레드를 붙여 실행
- 종료 시 자동으로 소멸
즉, 서블릿은 싱글톤으로 동작하며, 멀티 쓰레드 환경에 주의해야 한다.
멀티 쓰레드 환경이란?
한 번에 여러 요청이 들어오면 WAS는 쓰레드를 여러 개 만들어 처리한다.
요청 1 → 쓰레드 A
요청 2 → 쓰레드 B
...
서블릿은 하나의 인스턴스를 여러 쓰레드가 동시에 접근하기 때문에,
공유 상태(멤버 변수 등)를 사용하면 위험하다.
쓰레드 풀(Thread Pool)이란?
WAS는 매 요청마다 쓰레드를 새로 만드는 게 아니라,
미리 만들어 놓은 쓰레드 풀에서 꺼내어 사용한다.
| 특징 | 설명 |
|---|---|
| 성능 | 쓰레드 생성 비용 ↓, 응답 속도 ↑ |
| 안정성 | 과도한 요청 시 대기 또는 거절 설정 가능 |
| 관리 | 최대 동시 처리 수 제한 가능 (e.g., 톰캣 기본 200개) |
개발자는 멀티 쓰레드를 몰라도 된다?
웬만한 동시성 처리는 WAS가 알아서 해준다.
그래서 개발자는 싱글 쓰레드 방식으로 코딩하듯이 편하게 개발할 수 있다.
단, 싱글톤 빈(서블릿, @Component 등) 안에서
공유 변수만 잘 피하면 안전하다.
정적 리소스 vs 동적 처리 vs API
| 목적 | 설명 | 처리 위치 |
|---|---|---|
| 정적 리소스 | HTML, CSS, JS 등 고정 파일 | Web Server |
| 동적 HTML | 요청을 받아 서버에서 동적으로 HTML 생성 | WAS (JSP, 타임리프 등) |
| API 응답 | JSON 형식으로 데이터만 제공 | WAS |
서버 사이드 렌더링(SSR) vs 클라이언트 사이드 렌더링(CSR)
| 구분 | 설명 | 예시 |
|---|---|---|
| SSR | 서버가 HTML을 완성해서 응답 | JSP, 타임리프 |
| CSR | 클라이언트가 자바스크립트로 HTML 생성 | React, Vue |
'SpringBoot' 카테고리의 다른 글
| Spring MVC: 요청 매핑과 파라미터 처리 (0) | 2025.06.13 |
|---|---|
| Spring MVC 구조: 어댑터 패턴과 다형성은 왜 중요한가? (0) | 2025.05.20 |
| RequestScope로 요청별 로그 분리하기 (0) | 2025.05.07 |
| 스프링 DI: 생존자 주입을 권장하는 이유 (0) | 2025.05.05 |
| 스프링 빈 자동 등록과 의존성 주입 (1) | 2025.05.01 |