HTTP 상태 코드는 클라이언트가 보낸 요청에 대한 서버의 응답 결과를 나타내는 3자리 숫자 코드다.
이 코드를 통해 요청이 성공했는지, 실패했는지, 추가적인 작업이 필요한지를 알 수 있다.
1. 상태 코드 범위
| 1xx (정보) | 요청이 수신되어 처리 중임. |
| 2xx (성공) | 요청이 정상적으로 처리됨. |
| 3xx (리다이렉션) | 추가 작업이 필요하거나 다른 URL로 이동됨. |
| 4xx (클라이언트 오류) | 클라이언트의 요청이 잘못됨. |
| 5xx (서버 오류) | 서버에서 요청을 처리하는 중 오류 발생. |
🤨 만약 모르는 상태 코드가 나타나면?
- 클라이언트가 모르는 상태 코드를 서버가 반환하면 어떻게 처리해야 할까?
- 클라이언트는 상위 상태코드로 해석해서 처리하면 된다.
- 299 → 2xx (Successful)
- 451 → 4xx (Client Error)
- 599 → 5xx (Server Error)
- 따라서 미래에 새로운 상태 코드가 추가되어도, 클라이언트를 변경하지 않아도 된다.
2. 주요 상태 코드
| 200 OK | 요청이 성공적으로 처리됨 |
| 201 Created | POST 요청으로 새로운 리소스가 생성됨 (생성된 리소스는 응답의 Location 헤더 필드로 식별) |
| 202 Accepted | 요청이 접수되었으나, 완료되지 않음 (예: 요청 접수 후 1시간 뒤에 배치 프로세스가 요청 처리) |
| 204 No Content | 요청은 성공적으로 처리되었으나, 본문이 없음 (예: 웹 문서 편집기에서 저장 버튼) |
| 301 Moved Permanently | 리소스가 영구적으로 이동됨 |
| 302 Found | 리소스가 일시적으로 이동됨 |
| 304 Not Modified |
캐시된 리소스를 그대로 사용해도 됨 |
| 400 Bad Request | 잘못된 요청 (문법 오류 등) |
| 401 Unauthorized | 인증 필요 |
| 403 Forbidden | 접근 권한 없음 |
| 404 Not Found | 요청한 리소스를 찾을 수 없음 |
| 500 Internal Server Error | 서버 내부 오류 |
| 503 Service Unavailable | 서버 과부하 또는 유지보수 중 |
✅ 2.1. 1xx (정보 응답)
- 요청을 정상적으로 받았으며, 처리를 계속 진행해야 한다는 뜻이다.
- 일반적으로 클라이언트와 서버 간의 연결을 유지할 때 사용된다.
- 거의 사용하지 않는다.
| 100 Continue | 계속 진행 | 클라이언트가 요청을 계속해서 보내도 됨 (Expect: 100-continue) |
| 101 Switching Protocols | 프로토콜 변경 | 서버가 요청에 따라 다른 프로토콜로 변경함 (예: HTTP → WebSocket) |
| 103 Early Hints | 사전 정보 제공 | 정식 응답 전에 사전 정보(예: Link 헤더)를 제공 |
✔️ 100 Continue 예시
POST /upload HTTP/1.1
Host: api.example.com
Expect: 100-continue
HTTP/1.1 100 Continue
(서버가 100 Continue를 보내면 클라이언트는 요청 본문을 보냄)
✅ 2.2. 2xx (성공 응답)
- 요청이 정상적으로 처리되었다는 뜻이다.
| 200 OK | 성공 | 요청이 정상적으로 처리됨 |
| 201 Created | 리소스 생성됨 | 요청으로 인해 새로운 리소스가 생성됨 |
| 202 Accepted | 요청 접수됨 | 요청을 받았으나, 즉시 처리되지 않음 (예: 배치 처리 같은 비동기 작업) |
| 204 No Content | 콘텐츠 없음 | 요청이 성공했으나, 응답 본문이 없음 (예: 웹 문서 편집기의 저장 버튼) |
✔️ 201 Created 예시
POST /users HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"name": "Alice"
}
HTTP/1.1 201 Created
Location: /users/123
(새로운 사용자가 id=123으로 생성됨)
✅ 2.3. 3xx (리다이렉션 응답)
- 요청을 완료하려면 클라이언트의 추가 조치가 필요하거나, 다른 URL로 이동해야 한다는 뜻이다.
- 브라우저 또는 클라이언트가 새로운 URL로 요청을 변경하여 재시도하도록 유도한다.
- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동(리다이렉트)한다.
| 301 Moved Permanently | 영구 이동 | 요청한 리소스가 새로운 URL로 이동됨 |
| 302 Found | 일시적 이동 | 요청한 리소스가 일시적으로 다른 URL에 있음 |
| 303 See Other | 다른 URL 참조 | POST 요청 이후 GET 요청을 수행하도록 유도 |
| 304 Not Modified | 변경 없음 | 캐시된 리소스를 그대로 사용해도 됨 |
| 307 Temporary Redirect | 임시 리다이렉트 | 302와 유사하지만 요청 메서드 유지 |
| 308 Permanent Redirect | 영구 리다이렉트 | 301과 유사하지만 요청 메서드 유지 |
리다이렉션은 크게 영구(Permanent) 리다이렉션과 일시(Temporary) 리다이렉션로 구분되며, 각 상태 코드마다 요청 메서드와 본문 유지 여부, 브라우저/클라이언트의 처리 방식이 다르다.
1️⃣ 영구 리다이렉션
📌 301 Moved Permanently
- 클라이언트가 요청한 리소스가 영구적으로 다른 URI로 이동했음을 나타낸다.
- 이후 모든 요청은 새 URI로 해야 한다.
- 브라우저는 자동으로 새 URI를 캐시하고, 검색 엔진도 링크를 새 URI로 갱신한다.
| 캐시 가능 여부 | ✅ 가능 (브라우저와 검색 엔진이 기억함) |
| 요청 메서드 유지 | ❌ 변경될 수도 있음 (전통적으로는 POST → GET으로 변경됨, 비표준적임) |
| 요청 본문 유지 | ❌ 제거될 수도 있음 |
| 사용 예시 | 사이트 주소 변경 (http://example.com → https://example.com) |
📌 308 Permanent Redirect
- 301과 동일하게 영구 이동을 의미하지만, 반드시 요청 메서드와 본문을 그대로 유지해야 한다!
- HTTP/1.1 이후에 등장한 정식 명세 기반의 영구 리다이렉션
| 캐시 가능 여부 | ✅ 가능 |
| 요청 메서드 유지 | ✅ 유지 (POST → POST, PUT → PUT) |
| 요청 본문 유지 | ✅ 유지 |
| 사용 예시 | REST API에서 POST 요청을 다른 URI로 리다이렉트할 때 |
2️⃣ 일시 리다이렉션
📌 302 Found
- 요청한 리소스가 일시적으로 다른 URI에 있음을 나타낸다.
- 클라이언트는 기존 URI를 계속 사용해야 하며, 지금만 새 URI로 이동해야 한다.
- HTTP/1.0에서는 원래 의미가 "Moved Temporarily"였으나, 브라우저가 POST를 GET으로 바꾸는 비표준 동작을 해 문제 발생함
| 캐시 가능 여부 | 🚫 불가 |
| 요청 메서드 유지 | ❌ 보장되지 않음 (POST → GET이 되기도 함) |
| 요청 본문 유지 | ❌ 제거될 수도 있음 |
| 클라이언트 동작 | 새 URI로 이동하되, 원래 URI는 계속 유지 |
| 사용 예시 | 로그인 후 홈 화면으로 리디렉션 등 |
📌 307 Temporary Redirect
- 302과 동일하게 임시 이동을 의미하지만, 반드시 요청 메서드와 본문을 그대로 유지해야 한다!
- 302의 비표준 동작을 바로잡은 HTTP/1.1 명세에 따른 상태 코드
| 캐시 가능 여부 | 🚫 불가 |
| 요청 메서드 유지 | ✅ 반드시 유지 |
| 요청 본문 유지 | ✅ 반드시 유지 |
| 클라이언트 동작 | 새 URI로 리다이렉션하되, 동일한 방식으로 재전송 |
| 사용 예시 | 유지보수 중 다른 서버로 일시 이동, POST 요청을 유지해야 할 때 |
📌 303 See Other
- 요청이 성공적으로 처리되었으며, 결과는 다른 URI에 존재함을 명시
- 반드시 GET 방식으로 새 URI를 요청하게끔 유도한다.
- 웹에서 Form 제출 후 페이지를 새로고침할 때 중복 요청 방지를 위해 자주 사용된다.
| 캐시 가능 여부 | 🚫 불가 |
| 요청 방식 유지 | ❌ GET으로 변경됨 |
| 주 사용처 | PRG 패턴(Post → Redirect → Get) |
| 사용 예시 | 게시글 작성 후 결과 화면으로 이동, 결제 완료 후 영수증 페이지로 이동 등 |
🔷 PRG 패턴과 303 See Other
PRG (Post → Redirect → Get) 패턴은 POST 중복 요청을 방지하기 위한 대표적인 웹 디자인 패턴이다.
303 See Other를 사용하면 POST 요청 후 GET 요청으로 변경되어 중복 요청을 방지할 수 있다.
🚨 문제점
사용자가 POST로 주문한 후, 브라우저를 새로고침하면 동일한 요청이 재전송된다!
💡 해결 방법
1. 클라이언트가 POST /orders 요청 (주문 요청)
2. 서버는 303 See Other 응답과 함께 Location: /orders/123 제공 (302 Found의 경우 GET으로 변경하면 된다.)
3. 클라이언트는 자동으로 GET /orders/123 요청
→ 사용자가 페이지를 새로고침해도 GET 요청만 반복되므로 중복 주문을 방지할 수 있다!
🔷 결론
- 처음 302 Found의 의도는 요청 메서드를 유지하는 것
- 그런데 웹 브라우저들이 대부분 GET으로 바꾸어버림
- 그래서 모호한 302 대신, 명확한 307, 303이 등장 (301 대신 308도 등장)
- 307, 303을 권장하지만, 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용
- 자동 리다이렉션 시 GET으로 변해도 되면 그냥 302를 사용해도 큰 문제 없음
📌 304 Not Modified
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다.
- 즉, 클라이언트가 이미 저장한 캐시 데이터를 그대로 사용해도 된다라는 뜻!
- 따라서 클라이언트는 로컬 PC에 저장된 캐시로 리다이렉트한다.
- 장점: 성능 최적화, 네트워크 트래픽 감소
- 주의점: 로컬 캐시를 사용해야 하므로, 응답에 본문을 포함하면 안 된다!
🔷 3xx 리다이렉션 상태 코드 요약
| 상태 코드 | 의미 | 메서드 유지 | 사용 예 |
| 300 Multiple Choices | 여러 개의 선택 가능 | ❌ | 다양한 포맷 제공 |
| 301 Moved Permanently | 영구 이동 | ❌ | 도메인 변경 |
| 302 Found | 일시적 이동 | ❌ | 로그인 후 리다이렉트 |
| 303 See Other | PRG 패턴 | ❌ (GET으로 변경) | POST 후 GET 요청 |
| 304 Not Modified | 캐시된 데이터 사용 | ✅ | 캐싱 최적화 |
| 307 Temporary Redirect | 임시 이동 (메서드 유지) | ✅ | API 리다이렉트 |
| 308 Permanent Redirect | 영구 이동 (메서드 유지) | ✅ | POST 유지 필요 |
✅ 2.4. 4xx (클라이언트 오류)
- 클라이언트의 잘못된 요청으로 인해 서버가 요청을 처리할 수 없음을 나타낸다.
- 클라이언트가 이미 잘못된 요청을 보내고 있기 때문에, 재시도해도 실패함!
| 400 Bad Request | 요청이 잘못됨 (예: JSON 형식 오류) |
| 401 Unauthorized | 인증이 필요함 (응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명) |
| 403 Forbidden | 요청이 거부됨 (접근 권한 부족) |
| 404 Not Found | 해당 리소스를 찾을 수 없음 (또는 접근 권한 부족) |
| 405 Method Not Allowed | 요청한 HTTP 메서드가 지원되지 않음 |
✅ 2.5. 5xx (서버 오류)
- 서버가 요청을 처리하는 중에 문제가 발생했음을 나타낸다.
- 서버에 문제가 있기 때문에, 클라이언트가 재시도하면 성공할 수도 있다!
| 500 Internal Server Error | 서버 내부 오류 |
| 501 Not Implemented | 요청한 기능이 지원되지 않음 |
| 502 Bad Gateway | 프록시 서버에서 잘못된 응답을 받음 |
| 503 Service Unavailable | 서버가 과부하 상태이거나 유지보수 중 (Retry-After 헤더를 통해 복구 소요 시간 응답 가능) |
| 504 Gateway Timeout | 서버가 응답을 받을 수 없음 |
✔️ 503 Service Unavailable 예시
GET /service-status HTTP/1.1
Host: api.example.com
HTTP/1.1 503 Service Unavailable
Retry-After: 3600
(서버가 1시간 후 다시 요청하라고 안내)
'HTTP' 카테고리의 다른 글
| [HTTP] HTTP 헤더 (0) | 2025.04.07 |
|---|---|
| [HTTP] 클라이언트가 서버로 데이터를 전송하는 방법 (0) | 2025.04.06 |
| [HTTP] HTTP 메서드 (0) | 2025.04.06 |
| [HTTP] HTTP 메시지 (0) | 2025.04.06 |
| [HTTP] HTTP의 주요 특징 (0) | 2025.04.01 |