HTTP 상태 코드 레퍼런스
브라우저 안에서만 처리됩니다. 입력한 내용과 선택한 파일은 서버로 전송되지 않습니다. 익명 방문 통계만 집계합니다.
1xx · 정보 응답
- 100 Continue 계속
클라이언트가 계속 요청 본문을 보내도 좋다는 중간 응답이다.
Expect: 100-continue 헤더를 보낸 요청에 대해, 서버가 헤더만 먼저 보고 이 응답을 줘서 큰 본문을 무의미하게 전송하는 일을 막는다. 최종 응답이 아니므로 클라이언트는 이어서 진짜 결과를 기다려야 한다.
RFC 9110 §15.2.1
- 101 Switching Protocols 프로토콜 전환
Upgrade 헤더로 요청한 다른 프로토콜로 전환한다.
대표적으로 WebSocket 핸드셰이크에서 쓴다. 서버가 전환에 동의하면 같은 TCP 연결 위에서 이후로는 HTTP 가 아닌 새 프로토콜이 오간다.
RFC 9110 §15.2.2
- 102 Processing 처리 중
요청을 처리하고 있지만 아직 최종 응답이 없다.
오래 걸리는 WebDAV 배치 작업에서 클라이언트나 중간 프록시가 시간 초과로 연결을 끊지 않도록 서버가 중간에 보내는 신호다. 최종 결과가 아니라는 점을 클라이언트가 오해하면 안 된다.
RFC 2518
- 103 Early Hints 조기 힌트
최종 응답 전에 미리 불러올 자원을 알려준다.
서버가 본문을 만드는 동안 Link 헤더로 CSS·폰트 같은 핵심 자원을 먼저 알려줘 브라우저가 그 사이 preload 하게 한다. 최종 상태 코드가 아니라 힌트이므로 실제 결과(대개 200)가 뒤따른다.
RFC 8297
2xx · 성공
- 200 OK 성공
요청이 성공적으로 처리됐다.
가장 흔한 성공 응답이다. GET 뿐 아니라 POST·PUT 이 몸값 있는 결과를 돌려줄 때도 쓴다.
RFC 9110 §15.3.1
- 201 Created 생성됨
요청으로 새 리소스가 만들어졌다.
POST 로 리소스를 만든 뒤 돌려준다. Location 헤더에 새로 생긴 리소스의 URI 를 함께 주는 것이 관례다.
RFC 9110 §15.3.2
- 202 Accepted 접수됨
요청을 접수했지만 아직 처리를 끝내지 않았다.
비동기 처리 큐에 넣었다는 뜻일 뿐 처리 성공을 보장하지 않는다 — 흔한 오해는 202 를 200 처럼 "다 됐다"로 읽는 것이다. 나중에 작업 상태를 확인할 수 있는 URL 을 함께 주는 것이 일반적이다.
RFC 9110 §15.3.3
- 203 Non-Authoritative Information 비공인 정보
원 서버가 아닌 중간 프록시가 응답 메타데이터를 가공해 전달했다.
캐시나 프록시가 원 서버 응답의 헤더 등을 변형했을 때 200 대신 이 코드로 그 사실을 명시한다. 실무에서는 거의 쓰이지 않는다.
RFC 9110 §15.3.4
- 204 No Content 내용 없음
성공했지만 돌려줄 본문이 없다.
DELETE 나 상태만 바뀌는 PUT 처럼 클라이언트가 이미 결과를 알고 있는 요청에 쓴다. 본문이 없으므로 클라이언트는 화면을 갱신할 필요가 없다.
RFC 9110 §15.3.5
- 205 Reset Content 콘텐츠 재설정
성공했으니 클라이언트가 입력 폼 등을 초기화해도 된다.
본문이 없다는 점은 204 와 같지만, "화면을 리셋하라"는 의미를 명시적으로 담는다. 브라우저 지원이 제각각이라 실무에서 자주 쓰이지는 않는다.
RFC 9110 §15.3.6
- 206 Partial Content 일부 콘텐츠
Range 요청에 대해 리소스 일부만 돌려준다.
동영상 스트리밍이나 다운로드 재개(resume)에서 Range 헤더로 요청한 바이트 구간만 응답할 때 쓴다. Content-Range 헤더로 전체 중 어느 구간인지 알려준다.
RFC 9110 §15.3.7
- 207 Multi-Status 다중 상태
WebDAV 에서 여러 리소스에 대한 개별 결과를 한 응답에 담는다.
PROPFIND 처럼 한 요청이 여러 리소스에 걸쳐 서로 다른 결과를 낼 수 있을 때, 응답 본문(XML)에 리소스별 상태 코드를 나열한다. HTTP 상태 코드 하나로는 표현할 수 없는 상황을 위한 코드다.
RFC 4918 §11.1
- 208 Already Reported 이미 보고됨
207 응답 안에서 이미 나열한 바인딩을 다시 반복하지 않는다.
WebDAV 바인딩 확장에서 같은 리소스가 여러 컬렉션에 걸쳐 있을 때, 207 안에서 중복 나열을 피하려고 쓴다. 207 과 별개로 단독으로는 의미가 없다.
RFC 5842
- 226 IM Used IM 사용됨
델타(차이분) 인코딩된 instance-manipulation 결과를 돌려준다.
클라이언트가 A-IM 헤더로 요청한 델타 인코딩을 서버가 적용해 응답했다는 뜻이다. 대역폭을 아끼는 델타 압축 협상에 쓰이며 실무에서는 매우 드물게 나타난다.
RFC 3229
3xx · 리다이렉션
- 300 Multiple Choices 다중 선택
요청한 리소스에 여러 표현이 있어 클라이언트가 골라야 한다.
언어별·포맷별로 여러 버전이 있을 때 목록을 돌려주고 선택을 맡긴다. 실제로 이 코드를 그대로 활용하는 서버는 드물고, 대신 서버가 자동으로 하나를 골라 200 이나 다른 30x 로 응답하는 경우가 많다.
RFC 9110 §15.4.1
- 301 Moved Permanently 영구 이동
리소스가 새 URI 로 영구히 이동했다.
검색엔진이 링크를 새 주소로 바꿔 인덱싱한다. 원 규격은 재요청 메서드를 GET 으로 바꿀 수 있게 허용해서, 브라우저 다수가 POST 를 GET 으로 바꿔 재요청한다 — 메서드를 반드시 지키려면 308 을 쓴다.
RFC 9110 §15.4.2
- 302 Found 임시 이동
리소스가 다른 URI 에 임시로 있다.
로그인 후 리다이렉트처럼 임시로 다른 곳을 보여줄 때 쓴다. 301 과 같은 이유로 메서드가 GET 으로 바뀔 수 있다 — 메서드를 지켜야 하면 307 을 쓴다.
RFC 9110 §15.4.3
- 303 See Other 다른 위치 참조
결과를 GET 으로 다른 URI 에서 조회하라는 뜻이다.
POST 로 리소스를 처리한 뒤 결과 페이지를 GET 으로 보여줄 때 쓴다(Post/Redirect/Get 패턴) — 새로고침 시 폼이 중복 제출되는 문제를 막는다. 302 와 달리 메서드를 GET 으로 바꾸는 것이 규격에 명시돼 있다.
RFC 9110 §15.4.4
- 304 Not Modified 수정되지 않음
캐시된 버전이 여전히 유효하다.
If-None-Match/If-Modified-Since 조건부 요청에 대해, 서버가 변경이 없다고 판단하면 본문 없이 이걸 돌려준다. 브라우저는 로컬 캐시를 그대로 쓴다.
RFC 9110 §15.4.5
- 305 Use Proxy 프록시 사용
지정된 프록시를 통해서만 이 리소스에 접근할 수 있다.
보안 문제(응답 안에 프록시 주소를 실어 보내는 방식 자체의 위험) 때문에 대부분의 브라우저가 이 코드를 무시하도록 규격에서 폐기(deprecated)했다. 오늘날 실제 트래픽에서 만날 일은 거의 없다.
RFC 9110 §15.4.6
- 307 Temporary Redirect 임시 리다이렉트(메서드 유지)
메서드를 바꾸지 않고 임시로 다른 URI 로 보낸다.
302 와 뜻은 같지만 클라이언트가 POST 를 GET 으로 바꿔 재요청하는 것을 금지한다. 폼 재제출처럼 메서드 보존이 중요한 리다이렉트에 쓴다.
RFC 9110 §15.4.8
- 308 Permanent Redirect 영구 리다이렉트(메서드 유지)
메서드를 바꾸지 않고 영구히 다른 URI 로 보낸다.
301 과 뜻은 같지만 메서드를 바꾸지 않는다. API 엔드포인트를 영구 이전하면서 POST 요청을 그대로 유지하고 싶을 때 301 대신 쓴다.
RFC 9110 §15.4.9
4xx · 클라이언트 오류
- 400 Bad Request 잘못된 요청
요청 구문이나 내용이 잘못됐다.
잘못된 JSON, 빠진 필수 파라미터처럼 클라이언트 쪽 요청 자체의 문제일 때 쓴다. 인증·인가 문제와는 구분된다(401/403 참고).
RFC 9110 §15.5.1
- 401 Unauthorized 인증 필요
인증하지 않아 요청을 처리할 수 없다.
이름과 달리 "인가"가 아니라 "인증" 문제다 — 로그인하지 않았거나 자격증명이 유효하지 않을 때 쓴다. 인증은 됐지만 권한이 없으면 403 을 쓴다.
RFC 9110 §15.5.2
- 402 Payment Required 결제 필요
결제가 필요하다는 뜻으로 예약돼 있지만 표준화된 용례가 없다.
원래 디지털 결제 시스템을 염두에 두고 예약됐지만 실제로 규격화되지 못했다. 일부 API 가 크레딧 소진이나 과금 필요 상황을 알리는 용도로 비공식적으로 재활용한다.
RFC 9110 §15.5.3
- 403 Forbidden 접근 금지
인증됐지만 이 리소스에 접근할 권한이 없다.
누구인지는 알지만(또는 알아도 상관없지만) 그 사람에게는 허용되지 않은 요청이다. 401 과 자주 혼동되는데, 401 은 "네가 누군지 증명해라", 403 은 "누군지 알아도 안 된다"이다.
RFC 9110 §15.5.4
- 404 Not Found 찾을 수 없음
요청한 리소스를 찾을 수 없다.
리소스가 아예 없거나, 있어도 없는 척 숨기고 싶을 때(존재 자체를 노출하고 싶지 않은 경우) 쓴다. 라우팅 설정 오류로도 흔히 발생한다.
RFC 9110 §15.5.5
- 405 Method Not Allowed 허용되지 않은 메서드
리소스는 있지만 이 메서드를 지원하지 않는다.
예를 들어 읽기 전용 엔드포인트에 DELETE 를 보낸 경우다. 응답에 Allow 헤더로 실제 지원하는 메서드 목록을 함께 주는 것이 규격이다.
RFC 9110 §15.5.6
- 406 Not Acceptable 허용되지 않음
Accept 헤더가 요구하는 형식으로 응답할 수 없다.
클라이언트가 Accept·Accept-Language 등으로 요구한 표현을 서버가 만들어 줄 수 없을 때 쓴다. 실무에서는 서버가 이를 엄격히 지키기보다 기본 표현을 그냥 돌려주는 경우가 많아 실제로는 드물게 보인다.
RFC 9110 §15.5.7
- 407 Proxy Authentication Required 프록시 인증 필요
401 과 같지만 원 서버가 아니라 프록시가 인증을 요구한다.
포워드 프록시(사내망 게이트웨이 등) 앞에서 인증이 안 됐을 때 쓴다. Proxy-Authenticate 헤더로 인증 방식을 알려주며, 브라우저는 401 과 다른 별도의 자격증명 입력창을 띄운다.
RFC 9110 §15.5.8
- 408 Request Timeout 요청 시간 초과
클라이언트가 제한 시간 안에 요청을 다 보내지 않았다.
서버가 연결을 열어 놓고 기다리다 시간 초과로 끊을 때 쓴다. 클라이언트가 이 응답을 받기 전에 서버가 이미 연결을 닫아버리는 경우도 많아, 브라우저 화면에는 안 뜨고 조용한 재시도로 이어지기도 한다.
RFC 9110 §15.5.9
- 409 Conflict 충돌
현재 리소스 상태와 충돌해 요청을 처리할 수 없다.
동시 편집으로 버전이 어긋나거나, 이미 존재하는 리소스를 다시 만들려 할 때 쓴다. 클라이언트가 최신 상태를 다시 읽고 재시도해야 하는 경우가 많다.
RFC 9110 §15.5.10
- 410 Gone 사라짐
리소스가 있었지만 영구히 사라졌고 다시 오지 않는다.
404 와 달리 "예전엔 있었는데 의도적으로, 영구히 지웠다"는 뜻을 명시한다. 검색엔진이 인덱스에서 더 적극적으로 제거하도록 유도할 때 유용하다.
RFC 9110 §15.5.11
- 411 Length Required 길이 필요
Content-Length 헤더 없이는 요청을 받을 수 없다.
본문이 있는 요청인데 길이를 미리 알려주지 않으면 거부하는 서버가 낼 수 있는 코드다. 청크 전송 인코딩(Transfer-Encoding: chunked)을 쓰면 우회할 수 있다.
RFC 9110 §15.5.12
- 412 Precondition Failed 사전 조건 실패
If-Match 등 조건부 헤더의 전제 조건이 맞지 않는다.
동시 수정 충돌을 막으려고 If-Match/If-Unmodified-Since 로 "내가 마지막으로 본 버전일 때만 수정하라"고 요청했는데, 그 사이 리소스가 바뀌었을 때 쓴다. 낙관적 동시성 제어(optimistic concurrency)의 핵심 응답이다.
RFC 9110 §15.5.13
- 413 Content Too Large 요청 본문 너무 큼
요청 본문이 서버가 처리할 수 있는 한도를 넘었다.
파일 업로드 용량 제한에 흔히 걸린다. 예전 이름은 Payload Too Large 다. 리버스 프록시(nginx client_max_body_size 등)가 애플리케이션보다 먼저 이 응답을 낼 때가 많다.
RFC 9110 §15.5.14
- 414 URI Too Long URI 너무 김
요청 URI 가 서버가 처리할 수 있는 길이를 넘었다.
GET 요청에 너무 많은 파라미터를 실어 보내거나, 리다이렉트 루프로 URI 에 값이 계속 덧붙는 버그에서 흔히 발생한다.
RFC 9110 §15.5.15
- 415 Unsupported Media Type 지원하지 않는 미디어 타입
요청 본문의 Content-Type 을 서버가 처리할 수 없다.
JSON 만 받는 API 에 폼 데이터나 XML 을 보내면 발생한다. Content-Type 헤더를 실제 본문 형식과 맞춰야 한다.
RFC 9110 §15.5.16
- 416 Range Not Satisfiable 범위를 만족할 수 없음
요청한 Range 가 리소스 크기를 벗어난다.
이미 받은 파일 크기를 기준으로 이어받기(resume)를 시도했는데 서버의 실제 파일이 더 작아졌을 때(파일이 바뀌었을 때) 흔히 발생한다. Content-Range 헤더로 실제 전체 크기를 알려준다.
RFC 9110 §15.5.17
- 417 Expectation Failed 예상 실패
Expect 헤더가 요구한 조건을 서버가 만족시킬 수 없다.
100-continue 외의 Expect 값을 서버가 이해하지 못하거나 지원하지 않을 때 쓴다. 실무에서 Expect 헤더 자체를 잘 안 쓰기 때문에 매우 드물게 나타난다.
RFC 9110 §15.5.18
- 418 I'm a teapot 나는 주전자 비표준 · RFC 2324 (HTCPCP)
농담으로 만들어진 코드로, 정식 HTTP 표준이 아니다.
1998년 만우절 장난으로 발표된 Hyper Text Coffee Pot Control Protocol(HTCPCP)에서 "주전자에게 커피를 내리라고 하면 이 코드로 거절한다"는 농담으로 정의됐다. 재미로 이 코드를 실제 지원하는 서비스도 있지만, IANA 레지스트리에서 정식 상태 코드로는 등록돼 있지 않다.
- 421 Misdirected Request 잘못 전달된 요청
연결이 재사용되면서 처리 권한이 없는 서버로 요청이 잘못 왔다.
HTTP/2 연결 재사용에서, 같은 TLS 연결이 여러 도메인을 처리할 수 있다고 광고했지만 실제로는 그 도메인 요청을 처리할 권한이 없을 때 쓴다. 클라이언트는 같은 요청을 새 연결로 재시도할 수 있다.
RFC 9110 §15.5.20
- 422 Unprocessable Content 처리할 수 없는 콘텐츠
구문은 올바르지만 의미상 처리할 수 없다.
JSON 문법은 맞는데 값이 검증 규칙을 어길 때(필수 필드 누락, 범위 초과 등) 쓴다. 구문 오류인 400 과 달리 "형식은 맞지만 내용이 틀렸다"는 뜻이다.
RFC 9110 §15.5.21
- 423 Locked 잠김
WebDAV 에서 리소스가 잠겨 있어 접근할 수 없다.
다른 클라이언트가 LOCK 으로 리소스를 선점한 상태다. 잠금이 풀리거나 만료될 때까지 수정 요청이 거부된다.
RFC 4918 §11.3
- 424 Failed Dependency 의존성 실패
이 요청이 의존하던 다른 요청이 실패해 함께 실패했다.
WebDAV 의 여러 하위 요청을 묶어 처리할 때, 먼저 실패한 요청 때문에 뒤따르는 요청도 처리되지 않았음을 알린다.
RFC 4918 §11.4
- 425 Too Early 너무 이름
재전송(replay) 공격 위험이 있어 아직 처리하지 않는다.
TLS 1.3 의 0-RTT(Early Data)로 온 요청은 재전송 공격에 취약할 수 있어, 멱등하지 않은 요청이면 서버가 이 코드로 정식 핸드셰이크 완료 후 다시 보내라고 요구할 수 있다.
RFC 8470
- 426 Upgrade Required 업그레이드 필요
이 리소스는 다른 프로토콜로만 처리할 수 있다.
서버가 평문 HTTP 대신 TLS 나 특정 HTTP 버전으로의 업그레이드를 강제할 때 쓴다. Upgrade 헤더로 요구하는 프로토콜을 함께 알려준다.
RFC 9110 §15.5.22
- 428 Precondition Required 사전 조건 필요
조건부 요청(If-Match 등) 없이는 수정을 허용하지 않는다.
412 가 "조건이 틀렸다"는 뜻이라면 이건 "조건 자체가 없다"는 뜻이다. 여러 클라이언트가 동시에 같은 리소스를 수정해 최신 값을 덮어쓰는 lost update 문제를 막으려고 서버가 조건부 헤더 사용을 강제할 때 쓴다.
RFC 6585 §3
- 429 Too Many Requests 너무 많은 요청
주어진 시간 안에 너무 많은 요청을 보냈다.
레이트 리밋에 걸렸을 때 쓴다. 언제 다시 시도할 수 있는지 Retry-After 헤더로 알려주는 것이 관례이며, 클라이언트는 이 값을 존중해 재시도 간격을 둬야 한다.
RFC 6585 §4
- 431 Request Header Fields Too Large 요청 헤더 필드 너무 큼
요청 헤더 전체 또는 개별 헤더 하나가 너무 크다.
쿠키가 과도하게 쌓이거나 헤더에 큰 값을 실었을 때 발생한다. 413 이 본문 크기 문제라면 이건 헤더 크기 문제다.
RFC 6585 §5
- 440 Login Time-out 로그인 시간 초과 비표준 · IIS
세션이 만료돼 다시 로그인해야 한다.
IIS 가 인증 세션 만료를 알릴 때 쓰는 비표준 코드로, 표준 401 보다 "세션이 만료됐다"는 구체적인 의미를 담는다. IANA 표준 목록에는 없다.
- 444 No Response 응답 없음 비표준 · nginx
아무 응답도 보내지 않고 연결을 끊는다.
봇 트래픽이나 형식이 이상한 요청(잘못된 Host 헤더 등)을 응답 한 바이트도 쓰지 않고 조용히 차단할 때 쓰는 nginx 내부 전용 코드다. 실제로 이 숫자가 네트워크로 나가지는 않는다 — 클라이언트는 상태 코드가 아니라 그냥 연결이 끊긴 것으로 본다. nginx 접근 로그를 분석할 때만 보이는 값이다.
- 449 Retry With 추가 정보로 재시도 비표준 · IIS
추가 정보를 담아 요청을 다시 보내야 한다.
IIS/ASP.NET 이 요청을 처리하려면 클라이언트가 더 많은 정보(예: 추가 파라미터)를 담아 재요청해야 함을 알릴 때 쓰는 비표준 코드다.
- 450 Blocked by Windows Parental Controls 윈도우 자녀 보호에 의해 차단됨 비표준 · IIS
윈도우 자녀 보호 기능이 이 페이지 접근을 막았다.
마이크로소프트 생태계(주로 데스크톱 클라이언트)에서 자녀 보호 설정 때문에 접근이 차단됐을 때 쓰는 비표준 코드다. 웹 서버 자체보다 클라이언트·OS 레벨 정책과 관련이 깊다.
- 451 Unavailable For Legal Reasons 법적 사유로 이용 불가
법적 사유로 이 리소스를 제공할 수 없다.
법원 명령이나 정부 규제 등으로 접근이 차단됐음을 명시적으로 알린다. 403 과 달리 "이유가 법적 문제"라는 것을 검열 투명성 보고 등에서 구분해낼 수 있게 한다.
RFC 7725
- 460 Client Closed Connection 클라이언트 연결 조기 종료 비표준 · AWS ALB
클라이언트가 유휴 시간 초과 전에 로드밸런서와의 연결을 먼저 끊었다.
ALB 가 응답을 준비하는 도중 클라이언트가 연결을 닫아버린 상황을 액세스 로그에 남기기 위한 코드다. 실제로 클라이언트에 전송되는 코드가 아니라 액세스 로그 분석용이며, IANA 표준 목록에는 없다.
- 463 Malformed X-Forwarded-For Header X-Forwarded-For 헤더 오류 비표준 · AWS ALB
X-Forwarded-For 헤더에 IP 주소가 너무 많이(30개 초과) 담겨 있다.
여러 프록시를 거치며 X-Forwarded-For 에 주소가 계속 추가돼 ALB 가 정한 한도(30개)를 넘으면 이 코드를 낸다. 프록시 체인이 비정상적으로 길거나 헤더가 조작됐을 가능성을 의심할 신호다.
- 494 Request Header Too Large 요청 헤더 너무 큼 비표준 · nginx
요청 헤더가 nginx 의 버퍼 한도를 넘었다.
large_client_header_buffers 설정을 넘는 헤더(과도한 쿠키 등)를 보내면 발생한다. 표준 431 과 뜻은 비슷하지만 nginx 가 자체적으로 붙인 비표준 코드다.
- 495 SSL Certificate Error SSL 인증서 오류 비표준 · nginx
mTLS 에서 클라이언트 인증서 검증에 실패했다.
상호 TLS(mTLS)를 쓰는 nginx 에서 클라이언트가 제시한 인증서가 유효하지 않을 때 낸다. 표준 400 계열을 nginx 가 세분화한 비표준 코드다.
- 496 SSL Certificate Required SSL 인증서 필요 비표준 · nginx
mTLS 인증서가 필요한데 제시되지 않았다.
ssl_verify_client 가 필수로 설정된 nginx 에서 클라이언트가 인증서를 아예 보내지 않으면 이 코드를 낸다.
- 499 Client Closed Request 클라이언트가 요청을 닫음 비표준 · nginx
서버가 응답하기 전에 클라이언트가 연결을 끊었다.
느린 백엔드 처리 중 사용자가 탭을 닫거나 요청을 취소했을 때 흔히 남는다. 502/504 와 달리 원인이 서버가 아니라 클라이언트 쪽 이탈이라는 점에서 로그 분석 시 구분해야 한다.
5xx · 서버 오류
- 500 Internal Server Error 내부 서버 오류
서버에 예기치 못한 오류가 발생했다.
서버 쪽 코드가 처리 중 예외를 던졌을 때 쓰는 포괄적 오류다. 구체적 원인을 알 수 없거나 클라이언트에 노출하고 싶지 않을 때도 쓰인다.
RFC 9110 §15.6.1
- 501 Not Implemented 구현되지 않음
서버가 이 요청 메서드를 지원하지 않는다.
PATCH 같은 메서드를 서버 코드가 아예 처리하지 못할 때 쓴다. 500 과 달리 "일시적 오류"가 아니라 "애초에 구현이 없다"는 뜻이라 재시도해도 소용없다.
RFC 9110 §15.6.2
- 502 Bad Gateway 불량 게이트웨이
게이트웨이·프록시가 upstream 서버로부터 잘못된 응답을 받았다.
이 오류를 내는 주체는 원 서버가 아니라 앞단의 리버스 프록시나 로드밸런서다 — upstream(실제 애플리케이션 서버)이 죽었거나, 잘못된 응답을 돌려주거나, 연결 자체를 못 맺을 때 발생한다.
RFC 9110 §15.6.3
- 503 Service Unavailable 서비스 이용 불가
서버가 일시적으로 요청을 처리할 수 없다.
과부하나 점검 중일 때 쓴다. 502/504 와 달리 서버 자신이 직접 내는 경우가 많고(앞단이 아니라), Retry-After 로 언제 복구되는지 알려줄 수 있다.
RFC 9110 §15.6.4
- 504 Gateway Timeout 게이트웨이 시간 초과
게이트웨이·프록시가 upstream 응답을 시간 안에 받지 못했다.
502 와 마찬가지로 이 오류를 내는 주체는 원 서버가 아니라 앞단이다 — upstream 이 응답은 하지만 프록시가 정해둔 제한 시간 안에 끝내지 못했을 때 발생한다. 오래 걸리는 백엔드 작업이나 잘못된 타임아웃 설정이 흔한 원인이다.
RFC 9110 §15.6.5
- 505 HTTP Version Not Supported 지원하지 않는 HTTP 버전
요청에 쓰인 HTTP 버전을 서버가 지원하지 않는다.
오래된 HTTP/0.9 요청이나, 반대로 서버가 아직 지원하지 않는 새 버전을 클라이언트가 강제할 때 드물게 발생한다.
RFC 9110 §15.6.6
- 506 Variant Also Negotiates 변형도 협상함
서버의 콘텐츠 협상 설정 자체가 잘못됐다.
투명 콘텐츠 협상(transparent content negotiation)에서 협상 대상으로 지정된 리소스가 자기 자신을 다시 가리키는 등 서버 설정 오류일 때 쓴다. 실무에서 거의 볼 일이 없는 설정 버그 신호다.
RFC 2295
- 507 Insufficient Storage 저장 공간 부족
요청을 완료할 저장 공간이 서버에 없다.
WebDAV 로 파일을 업로드하는 등 서버 디스크가 가득 찼을 때 낸다. 클라이언트 쪽 요청 자체는 문제가 없다는 점에서 4xx 가 아니라 5xx 다.
RFC 4918 §11.5
- 508 Loop Detected 루프 감지됨
WebDAV 처리 중 무한 루프(순환 참조)를 감지했다.
컬렉션이 자기 자신을 다시 참조하는 등 무한히 순회하게 되는 상황을 서버가 감지해 끊을 때 쓴다. 208(Already Reported)이 같은 문제를 정상 경로에서 예방하는 장치라면, 이건 그 예방이 실패했을 때의 안전장치다.
RFC 5842
- 510 Not Extended 확장되지 않음
요청이 요구하는 HTTP 확장을 서버가 지원하지 않는다.
HTTP Extension Framework 를 쓰는 요청에서, 서버가 그 확장을 처리할 수 없을 때 어떤 확장이 더 필요한지를 응답에 담아 알려준다. 이 확장 프레임워크 자체가 널리 쓰이지 않아 실무에서는 거의 나타나지 않는다.
RFC 2774
- 511 Network Authentication Required 네트워크 인증 필요
네트워크 접속 자체에 인증이 필요하다(공용 와이파이 로그인 등).
카페·공항의 공용 와이파이에서 로그인 페이지를 거치기 전까지 모든 요청을 이 코드로 가로채는 캡티브 포털(captive portal)이 흔히 쓴다. 401 과 달리 애플리케이션이 아니라 네트워크 인프라 계층의 인증 요구다.
RFC 6585 §6
- 520 Unknown Error 알 수 없는 오류 비표준 · Cloudflare
origin 서버가 비어 있거나 알 수 없는 응답을 돌려줬다.
Cloudflare 가 origin 과 TCP 연결에는 성공했지만 받은 응답이 HTTP 규격을 벗어나 해석할 수 없을 때(빈 응답, 깨진 헤더 등) 이 코드를 낸다. 원인은 사실상 origin 서버 쪽 오류인 경우가 대부분이다.
- 521 Web Server Is Down 웹 서버 다운 비표준 · Cloudflare
origin 서버가 Cloudflare 의 연결 자체를 거부했다.
origin 서버가 다운됐거나 방화벽이 Cloudflare 의 IP 대역을 막고 있을 때 발생한다. origin 이 살아 있다면 방화벽 허용 목록에 Cloudflare IP 범위가 있는지부터 확인해야 한다.
- 522 Connection Timed Out 연결 시간 초과 비표준 · Cloudflare
Cloudflare 가 origin 서버에 연결을 시도했지만 응답이 없어 시간 초과됐다.
TCP 연결 단계에서부터 막힌 경우로, origin 서버 과부하나 네트워크 경로 문제, 방화벽의 조용한 드롭(drop)이 흔한 원인이다.
- 523 Origin Is Unreachable origin 서버에 도달할 수 없음 비표준 · Cloudflare
Cloudflare 가 origin 서버의 IP 로 라우팅할 수 없다.
DNS 설정이 더 이상 존재하지 않는 IP 를 가리키거나 origin 이 네트워크에서 완전히 사라졌을 때 발생한다. 522(응답 없음)와 달리 아예 목적지에 도달하지 못했다는 뜻이다.
- 524 A Timeout Occurred 시간 초과 발생 비표준 · Cloudflare
TCP 연결은 됐지만 origin 이 시간 안에 HTTP 응답을 완성하지 못했다.
504 의 Cloudflare 버전으로, 느린 백엔드 처리가 Cloudflare 의 타임아웃을 넘길 때 흔히 발생한다. 표준 504 와 뜻은 같지만 Cloudflare 가 자신의 타임아웃임을 명시하려고 세분화했다.
- 525 SSL Handshake Failed SSL 핸드셰이크 실패 비표준 · Cloudflare
Cloudflare 와 origin 사이의 TLS 핸드셰이크가 실패했다.
origin 서버의 TLS 설정(지원하지 않는 프로토콜 버전·암호 스위트 등)이 Cloudflare 와 맞지 않을 때 발생한다. 클라이언트-Cloudflare 구간의 TLS 와는 별개로, Cloudflare-origin 구간의 문제다.
- 526 Invalid SSL Certificate 유효하지 않은 SSL 인증서 비표준 · Cloudflare
origin 서버의 SSL 인증서를 Cloudflare 가 신뢰할 수 없다.
만료됐거나, 도메인이 일치하지 않거나, 신뢰되지 않는 CA 가 발급한 인증서를 origin 이 제시할 때 발생한다. Cloudflare 의 SSL/TLS 모드가 Full(Strict) 일 때 특히 엄격하게 검사한다.
- 527 Railgun Error Railgun 오류 비표준 · Cloudflare
Cloudflare 와 origin 사이의 Railgun 연결이 끊겼다.
Railgun 은 Cloudflare 와 origin 서버 사이의 트래픽을 압축해 전송하던 레거시 기능으로, 현재는 사실상 단종됐다. 이 코드를 실무에서 마주칠 일은 거의 없다.
사용법
- 위 검색칸에 코드 번호·영문 이름·한국어 뜻 중 아무거나 입력합니다. 검색어를 여러 개 띄어 쓰면 전부 만족하는 항목만 남습니다.
- 각 항목에서 언제 쓰는지와 흔한 오해를 확인합니다. 회색 뱃지가 붙은 항목은 RFC 표준이 아니라 특정 서버·인프라(nginx, Cloudflare 등)가 내는 비표준 코드입니다.
- 항목 오른쪽의 "링크 복사" 버튼으로 그 코드로 바로 이동하는 앵커 링크를 복사해 동료에게 공유할 수 있습니다.
자주 묻는 질문
301 과 302 는 언제 갈리나요?
둘 다 "다른 곳으로 이동했다"는 뜻이지만 영속성이 다릅니다. 301(영구 이동)은 검색엔진이 링크를 새 주소로 바꿔 인덱싱하게 하고, 302(임시 이동)는 원래 주소를 그대로 인덱싱에 남겨 둡니다. 도메인을 영구히 옮겼다면 301, 점검 페이지처럼 잠깐 다른 곳을 보여줄 뿐이라면 302 를 씁니다. 다만 둘 다 브라우저가 POST 를 GET 으로 바꿔 재요청할 수 있다는 흔한 함정이 있어, 메서드를 반드시 지켜야 한다면 각각 308·307 을 대신 씁니다.
401 과 403 의 차이는 무엇인가요?
401(Unauthorized)은 이름과 달리 "인가"가 아니라 "인증" 문제입니다 — 로그인하지 않았거나 자격증명이 없거나 틀렸을 때 씁니다. 403(Forbidden)은 인증(로그인)은 됐지만 그 사용자에게는 이 리소스에 접근할 권한이 없을 때 씁니다. 한 문장으로 줄이면 401 은 "네가 누군지 증명해라", 403 은 "누군지 알아도 안 된다"입니다.
502·504 는 누가 내는 오류인가요?
둘 다 실제 애플리케이션 서버(origin)가 아니라 앞단의 리버스 프록시나 로드밸런서, CDN 이 내는 오류입니다. 502(Bad Gateway)는 upstream 이 죽었거나 이상한 응답을 돌려줬을 때, 504(Gateway Timeout)는 upstream 이 응답은 하지만 프록시가 정한 시간 안에 끝내지 못했을 때 씁니다. 그래서 이 오류를 보면 애플리케이션 코드보다 먼저 프록시·로드밸런서 설정과 백엔드 상태부터 확인하는 것이 순서입니다.
nginx·Cloudflare·ALB 같은 비표준 코드를 실제로 써도 되나요?
서버·인프라가 자기 내부 사정(연결 조기 종료, SSL 핸드셰이크 실패 등)을 로그에 남기거나 클라이언트에 더 구체적으로 알리려고 자체적으로 정의한 코드라서, 그 인프라 앞에서는 실제로 쓰이고 있고 막을 방법도 없습니다. 다만 이 코드들은 IANA 표준 레지스트리에 없으므로, 여러분이 만드는 애플리케이션의 API 응답 코드로 새로 채택하는 것은 권장하지 않습니다 — 표준 클라이언트 라이브러리나 다른 팀의 코드가 이 숫자를 알아서 해석해 줄 것이라고 기대할 수 없기 때문입니다.