HTTP 상태 코드 실무 정리 - 실제로 마주치는 것만
상태 코드는 수십 개지만 실무에서 실제로 보는 건 열 개 남짓입니다.
전체를 외우는 것보다 "이게 나오면 어디를 봐야 하는지" 를 아는 게 낫습니다.
결론부터 — 첫 자리로 책임 소재가 갈립니다
| 앞자리 | 뜻 | 누구 문제인가 |
|---|---|---|
2xx |
성공 | — |
3xx |
다른 곳으로 이동 | 설정 문제일 수 있음 |
4xx |
요청이 잘못됨 | 보내는 쪽 (주소·권한·인증) |
5xx |
서버가 처리 못 함 | 서버 쪽 |
4xx가 나오면 내 요청을, 5xx가 나오면 서버를 봅니다. 이 구분만 해도 절반은 잡힙니다.
자주 보는 것들
2xx — 성공
| 코드 | 의미 | 비고 |
|---|---|---|
200 |
정상 | |
204 |
성공했지만 줄 내용 없음 | API에서 삭제 처리 등 |
206 |
일부만 전송 | 동영상 구간 재생, 이어받기 |
3xx — 이동
| 코드 | 의미 | 주의 |
|---|---|---|
301 |
영구 이동 | 브라우저가 강하게 캐시한다 |
302 |
임시 이동 | 검색엔진은 옛 주소를 유지한다 |
304 |
안 바뀜 | 캐시 쓰라는 뜻. 오류가 아니다 |
307/308 |
이동하되 메서드 유지 | POST를 보존해야 할 때 |
304 Not Modified를 오류로 착각하기 쉽습니다.
"네가 가진 캐시가 최신이니 그대로 써라"는 정상 응답입니다.
4xx — 요청 쪽 문제
| 코드 | 의미 | 실무에서 |
|---|---|---|
400 |
요청 형식이 잘못됨 | JSON 문법 오류 등 |
401 |
인증 안 됨 | 로그인하면 될 수도 |
403 |
인증은 됐는데 권한 없음 | 로그인해도 안 된다 |
404 |
없음 | 주소 오타 or 삭제됨 |
429 |
너무 많이 요청함 | 잠시 기다렸다 재시도 |
401과 403은 헷갈립니다.
401= "네가 누군지 모르겠다" → 로그인하면 해결될 수 있음403= "누군지는 알겠는데 넌 안 된다" → 로그인해도 안 됨
403과 404도 구분이 애매할 때가 있습니다.
없는 글을 요청했을 때 404를 주는 서비스도 있고 403을 주는 서비스도 있습니다.
비공개 글이라 막는 건지 아예 없는 건지, 응답만으로는 알 수 없습니다.
5xx — 서버 쪽 문제
| 코드 | 의미 | 어디를 보나 |
|---|---|---|
500 |
서버 내부 오류 | 애플리케이션 로그 |
502 |
게이트웨이 오류 | 프록시는 살아있고 뒷단이 죽었다 |
503 |
서비스 이용 불가 | 과부하·점검 중 |
504 |
게이트웨이 시간 초과 | 뒷단이 너무 느리다 |
502와 504의 차이가 중요합니다.
리버스 프록시(nginx·Caddy 등) 뒤에 애플리케이션을 두는 구조에서는
502→ 뒷단 프로세스가 죽었거나 포트가 안 맞는다504→ 뒷단은 살아있는데 응답이 너무 오래 걸린다
프록시 자체가 죽으면 상태 코드조차 못 받습니다.
⚠️ 000은 상태 코드가 아닙니다
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
# 000
000은 "응답을 아예 못 받았다"는 curl의 표시입니다. 서버가 뭔가를 준 게 아닙니다.
| 원인 | 확인 |
|---|---|
| 인증서 거부 | -k 붙이면 되는지 비교 |
| 연결 거부 | 포트가 열려 있는지 |
| DNS 실패 | 이름이 풀리는지 |
| 타임아웃 | 방화벽 |
curl -v https://example.com/ 2>&1 >/dev/null | grep -iE 'certificate|refused|resolve|timed out'
404와 000은 완전히 다릅니다. 404는 서버가 살아서 "없다"고 답한 것이고, 000은 서버와 대화조차 못 한 것입니다.
저는 000을 보고 "서버가 뭔가 응답은 했구나" 하고 한참 엉뚱한 곳을 팠습니다.
curl로 사이트를 확인하는데 000이 나왔습니다. 숫자가 찍히니 상태 코드인 줄 알고 서버 설정과 애플리케이션 로그를 뒤졌습니다. 로그에는 아무것도 없었습니다. 당연했습니다. 요청이 서버까지 도달하지도 못했으니까요.
-k를 붙여 다시 재보니 200이 나왔고, 그제서야 인증서 문제라는 걸 알았습니다. 000은 상태 코드가 아니라 "응답을 못 받았다"는 표시였던 겁니다.
404였다면 서버가 살아서 "없다"고 답한 것이니 완전히 다른 방향으로 봐야 했습니다. 이 구분을 몰라서 시간을 버렸습니다.
상태 코드 빠르게 확인하기
# 하나
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/
# 여러 주소 한 번에
for u in https://example.com/ https://example.com/about https://example.com/없는주소; do
printf "%-40s %s\n" "$u" "$(curl -s -o /dev/null -w '%{http_code}' "$u")"
done
# 리다이렉트까지 따라가서 최종 결과
curl -s -o /dev/null -L -w '%{http_code} %{url_effective}\n' https://example.com/
사이트가 살아있는지 감시할 때는 리다이렉트를 따라간 최종 코드를 봐야 합니다.
301만 보고 "정상"이라 판단하면, 그 끝이 500이어도 모릅니다.
정리
- 4xx는 요청 쪽, 5xx는 서버 쪽. 이 구분이 출발점입니다
401은 로그인하면 될 수도,403은 로그인해도 안 됩니다304는 오류가 아닙니다. 캐시 쓰라는 정상 응답입니다502는 뒷단이 죽은 것,504는 뒷단이 느린 것입니다000은 상태 코드가 아니라 "응답 못 받음" 입니다. 404와 혼동하지 마세요