HTTP의 특성인 Stateless에 대해 설명해 주세요.
Stateless(무상태)란 서버가 클라이언트의 이전 요청 정보를 저장하지 않고, 매 요청을 독립적으로 처리하는 HTTP의 핵심 특성입니다.
왜 HTTP는 Stateless로 설계되었는가
[초기 웹의 목적]
단순한 문서(HTML) 전달 → 요청-응답 후 연결 유지 필요 없음
[만약 Stateful이었다면]
서버가 모든 클라이언트의 상태를 메모리에 유지
→ 동시 접속자 10만 명 = 10만 개의 상태 관리
→ 서버 자원 고갈
→ 특정 서버에 종속 (그 서버가 죽으면 상태 유실)
결국 Stateless는 서버의 자원 효율성과 확장성을 위한 설계 선택입니다.
Stateless의 동작 방식
[Stateful — 서버가 기억함]
요청 1: "사과 2개 주세요" → 서버: (사과 2개 기억)
요청 2: "배도 1개 추가요" → 서버: (사과 2개 + 배 1개 기억)
요청 3: "결제할게요" → 서버: 사과 2개 + 배 1개 = 5,000원
→ 서버가 중간에 바뀌면? 새 서버는 이전 대화를 모름 → 장애 X
[Stateless — 서버가 기억하지 않음]
요청 1: "사과 2개 주세요" → 서버A: 처리
요청 2: "사과 2개 + 배 1개 주세요" → 서버B: 처리 가능 O
요청 3: "사과 2개 + 배 1개 결제할게요" → 서버C: 처리 가능 O
→ 매 요청에 필요한 모든 정보를 포함 → 어떤 서버든 처리 가능
Stateless가 주는 이점
| 이점 | 설명 |
|---|---|
| 서버 확장(Scale-Out) | 어떤 서버든 요청 처리 가능 → 서버 증설이 자유로움 |
| 장애 대응 | 서버 1대가 죽어도 다른 서버가 동일하게 처리 |
| 서버 자원 절약 | 클라이언트 상태를 메모리에 유지할 필요 없음 |
| 단순한 서버 설계 | 요청 간 의존성이 없어 구현이 간단 |
[Scale-Out과의 관계]
Stateful 서버:
클라이언트 → 로드밸런서 → 반드시 서버A로 (상태가 서버A에 있으므로)
서버B는 처리 불가 X
Stateless 서버:
클라이언트 → 로드밸런서 → 서버A, B, C 아무 데나 가능 O
Stateless의 한계
HTTP가 Stateless이기 때문에 상태 유지가 필요한 기능에서는 별도의 보완 메커니즘이 필요합니다.
[문제]
POST /login → 로그인 성공
GET /mypage → 서버: "누구세요?" ← 이전 요청을 기억하지 않음
[보완 메커니즘]
매 요청에 "나는 인증된 사용자입니다"라는 정보를 함께 전달해야 함
| 보완 방식 | 상태 저장 위치 | Stateless 유지 여부 |
|---|---|---|
| 쿠키 | 클라이언트 | △ (서버는 저장 안 하지만 클라이언트가 매번 전송) |
| 세션 | 서버 (메모리/Redis) | X (서버가 상태 보유) |
| JWT | 클라이언트 (토큰 자체에 정보 포함) | O (서버 저장 없음) |
// 쿠키/세션 — 브라우저가 자동 전송
GET /mypage HTTP/1.1
Cookie: JSESSIONID=abc123
// JWT — 클라이언트가 직접 포함
GET /mypage HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
HTTP의 또 다른 특성: Connectionless와의 관계
Connectionless (비연결성): 요청-응답 후 TCP 연결을 끊음
Stateless (무상태): 요청 간 클라이언트 정보를 저장하지 않음
→ 이 두 가지가 결합되어 HTTP는 가볍고 확장성 높은 프로토콜이 됨
→ 단, 매번 연결을 새로 맺는 비용이 발생하여 HTTP/1.1부터 Keep-Alive 도입
면접 포인트
- Stateless의 핵심 가치는 서버 확장성(Scale-Out) 입니다. 서버가 상태를 갖지 않으므로 어떤 서버든 동일한 요청을 처리할 수 있고, 이는 대규모 서비스의 기반이 됩니다.
- Stateless의 한계를 보완하기 위해 쿠키, 세션, JWT 등을 사용하며, 각 방식은 Stateless 유지 여부와 보안 통제력 사이의 트레이드오프가 있습니다.
- REST API가 Stateless를 원칙으로 삼는 이유도 HTTP의 이 특성을 최대한 활용하여 서버 간 상태 공유 없이 독립적으로 확장 가능한 구조를 만들기 위함입니다.