🚦 HTTP 상태 코드
📖 정의
HTTP 상태 코드는 서버가 클라이언트의 요청을 어떻게 처리했는지 알려주는 3자리 숫자입니다. 첫 번째 자리 숫자에 따라 5개의 그룹으로 분류됩니다.
🎯 비유로 이해하기
레스토랑 주문 시스템
2xx (성공) = "주문하신 음식 나왔습니다!"
├─ 200: 음식 완성, 바로 드세요
├─ 201: 새로운 메뉴 등록 완료
└─ 204: 음식 치웠습니다 (테이블 정리 완료)
3xx (리다이렉션) = "다른 곳으로 안내해드릴게요"
├─ 301: 매장이 영구적으로 이전했습니다
├─ 302: 임시로 다른 곳에서 서빙합니다
└─ 304: 이미 드신 음식이라 새로 안 나옵니다 (캐시)
4xx (클라이언트 오류) = "손님 실수입니다"
├─ 400: 주문을 이해할 수 없어요
├─ 401: 회원만 주문 가능합니다
├─ 403: 이 메뉴는 주문 불가능합니다
├─ 404: 그런 메뉴 없습니다
└─ 429: 주문을 너무 많이 하셨어요
5xx (서버 오류) = "저희 실수입니다"
├─ 500: 주방에 문제가 생겼습니다
├─ 502: 주방과 연결이 안 됩니다
├─ 503: 지금 너무 바빠서 주문 받을 수 없어요
└─ 504: 주방 응답이 너무 느립니다
💡 상태 코드 그룹
┌─────┬─────────────┬────────────────────┐
│ 코드│ 분류 │ 의미 │
├─────┼─────────────┼────────────────────┤
│ 1xx │ 정보 │ 요청 처리 중 │
│ 2xx │ 성공 │ 요청 성공 │
│ 3xx │ 리다이렉션 │ 추가 조치 필요 │
│ 4xx │ 클라이언트 │ 클라이언트 오류 │
│ 5xx │ 서버 오류 │ 서버 오류 │
└─────┴─────────────┴────────────────────┘
✅ 2xx - 성공
200 OK
가장 일반적인 성공 응답
요청:
GET /api/users/123 HTTP/1.1
응답:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 123,
"name": "홍길동",
"email": "hong@example.com"
}
fetch('https://api.example.com/users/123')
.then(response => {
if (response.status === 200) {
return response.json();
}
})
.then(data => console.log(data));
사용 사례:
- GET 요청 성공
- PUT, PATCH 요청 성공
- 데이터가 포함된 모든 성공 응답
201 Created
새로운 리소스 생성 성공
요청:
POST /api/users HTTP/1.1
Content-Type: application/json
{
"name": "홍길동",
"email": "hong@example.com"
}
응답:
HTTP/1.1 201 Created
Location: /api/users/123
Content-Type: application/json
{
"id": 123,
"name": "홍길동",
"email": "hong@example.com"
}
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: '홍길동',
email: 'hong@example.com'
})
})
.then(response => {
if (response.status === 201) {
console.log('사용자 생성 성공!');
// Location 헤더에서 새 리소스 URL 확인
console.log(response.headers.get('Location'));
return response.json();
}
});
204 No Content
성공했지만 반환할 내용이 없음
요청:
DELETE /api/users/123 HTTP/1.1
응답:
HTTP/1.1 204 No Content
fetch('https://api.example.com/users/123', {
method: 'DELETE'
})
.then(response => {
if (response.status === 204) {
console.log('삭제 성공!');
// 응답 바디 없음
}
});
사용 사례:
- DELETE 요청 성공
- PUT, PATCH 후 반환 데이터 없을 때
- 작업 성공했지만 클라이언트에게 전달할 내용 없을 때
기타 2xx 코드
202 Accepted
├─ 요청 접수됨, 처리는 비동기로 진행
└─ 예: 대용량 파일 처리, 이메일 전송
206 Partial Content
├─ 일부 콘텐츠만 반환
└─ 예: 동영상 스트리밍, 대용량 파일 다운로드
🔀 3xx - 리다이렉션
301 Moved Permanently
리소스가 영구적으로 이동
요청:
GET /old-page HTTP/1.1
응답:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/new-page
// 브라우저가 자동으로 리다이렉트
fetch('https://api.example.com/old-endpoint')
.then(response => {
if (response.status === 301) {
console.log('영구 이동:', response.headers.get('Location'));
}
});
사용 사례:
- 사이트 주소 변경
- API 엔드포인트 영구 변경
- SEO: 검색 엔진이 새 URL 저장
302 Found (Temporary Redirect)
리소스가 일시적으로 이동
응답:
HTTP/1.1 302 Found
Location: https://example.com/temp-page
사용 사례:
- 임시 페이지로 이동
- 로그인 페이지로 리다이렉트
- A/B 테스팅
304 Not Modified
캐시된 데이터 사용 가능
요청:
GET /api/users/123 HTTP/1.1
If-None-Match: "abc123"
응답:
HTTP/1.1 304 Not Modified
ETag: "abc123"
// 브라우저가 자동으로 캐시 사용
fetch('https://api.example.com/users/123')
.then(response => {
if (response.status === 304) {
console.log('캐시 사용 중');
}
});
장점:
- 네트워크 대역폭 절약
- 응답 속도 향상
- 서버 부하 감소
기타 3xx 코드
303 See Other
├─ 다른 URL에서 GET으로 조회
└─ 예: POST 후 결과 페이지로 이동
307 Temporary Redirect
├─ 302와 유사하지만 메서드 유지 보장
└─ 예: POST → POST로 리다이렉트
308 Permanent Redirect
├─ 301과 유사하지만 메서드 유지 보장
└─ 예: POST → POST로 영구 리다이렉트
❌ 4xx - 클라이언트 오류
400 Bad Request
잘못된 요청 형식
요청:
POST /api/users HTTP/1.1
Content-Type: application/json
{
"name": "", // 빈 이름
"email": "invalid-email" // 잘못된 이메일 형식
}
응답:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Validation Error",
"message": "Invalid request data",
"details": [
{
"field": "name",
"message": "Name is required"
},
{
"field": "email",
"message": "Invalid email format"
}
]
}
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: '',
email: 'invalid-email'
})
})
.then(response => {
if (response.status === 400) {
return response.json();
}
})
.then(error => {
console.error('유효성 검사 실패:', error);
});