과거의 내가 미래의 나에게
HTTP 학습 (4-4) - 상태 코드(4xx번대) 본문
오늘은 400번대 상태코드에 대해서 쭉 살펴보았다.
4xx (Client Error): 서버가 클라이언트의 오류로 인해 요청을 처리할 수 없거나 하지 않음
400번대 상태 코드는 클라이언트의 오류로 인해 클라이언트의 요청을 처리하지 않고 반환하는 코드이다. 클라이언트가 이와 관련된 상태코드를 받았다면 동일한 요청을 동일한 형태로 다시 보내서는 안될 것이다.
■ 400 (Bad Request): 클라이언트가 잘못된 요청을 하여 요청을 처리할 수 없음을 의미한다.
요청 파라미터가 알맞지 않거나 메시지에 오류가 있는 등 클라이언트의 요청 내용이 문제가 있을 시 반환되는 값이다. 이 때 백엔드 쪽에서 어느 부분이 잘못된 지 명시해준다면 클라이언트는 훨씬 더 빠르게 수정할 수 있어서 완전 좋다.
사족으로 아예 상태코드 신경도 안쓰는 백엔드 개발자와 꼼꼼히 다 써주는 백엔드 개발자를 둘 다 만나봤는데 전자를 겪다가 후자를 겪으니 무릎꿇고 감사하고 싶었다ㅎㅎ... 보통 전자의 경우는 API 문서도...여기까지!!
■ 401 (Unauthorized): 인증이 필요한 요청일 때 인증이 없다면 반환하는 상태 코드이다.
요청한 클라이언트가 인증되지 않았거나 관련된 인증 정보가 없어서 요청이 거부된 상황이다. 예시로 로그인이 필요한 서비스에 로그인 없이 접근하려할 때 해당 상태코드가 사용되기도 한단다.
■ 402 (Payment Required): 디지털 결제 시스템을 활성화하기 위해 생성되었다는데 향후 사용을 위해 예약된 비표준 응답 상태 코드라 사용되고 있진 않은 듯 하다.
■ 403 (Forbidden): 권한이 필요한 요청일 때 권한이 없다면 반환하는 상태 코드이다.
401 상태코드와 다소 비슷하지만 401의 경우 아예 인증되지 않은 클라이언트일 경우이고 403은 인증은 되었지만 인증된 사용자가 접근할 권한이 없다는 것이라는 차이가 있다. 예시로 로그인된 사용자가 관리자만 접근 가능한 페이지에 접근하려 시도했을 때가 있다.
단, 이와 같은 경우 접근하려는 곳에 리소스가 존재한다는 힌트를 주는 것이므로 경우에 따라서는 권한이 없을 경우 403 상태코드가 아니나 404 상태코드를 반환하는 경우도 있다고 한다.
■ 404 (Not Found): 요청한 리소스를 찾을 수 없을 때 반환하는 상태 코드이다.
클라이언트가 준 URL로 접근하려했으나 존재하지 않아 리소스를 반환할 수 없다는 의미로 존재하지 않은 리소스를 요청하였으니 클라이언트한테 다시 살펴보라는 의미이다.
리소스가 없다는 의미는 클라이언트가 요청한 URL 경로 자체가 없다는 것 일수도, 혹은 경로는 있지만 도착한 곳에 아무 리소스가 없다는 의미일 수도 있다. 경로가 없는 것은 프레임워크들이 알아서 처리해준다고 한다.
■ 405 (Method Not Allowed): 서버가 요청 메서드를 알고 있지만 대상 리소스가 이 메서드를 지원하지 않음을 가리킨다.
요청한 URL이 특정 메서드를 지원하고 있지 않다면 해당 상태코드를 반환한다. 예를 들어 특정 URL이 get 요청으로만 데이터를 조회할 수 있는데, 클라이언트가 post로 요청한다면 해당 상태코드를 반환한다는 것이다.
해당 상태코드를 반환할 때는 요청한 URL이 어떤 메서드를 지원하는지에 대한 정보를 ALLOW 헤더를 통해 알려줄 수 있다 한다.
■ 406 (Not Acceptable): 콘텐츠 협상에서 결국 맞는 사항을 찾지 못했을 때 반환하는 상태 코드이다.
하나의 리소스는 다양한 형태로 존재할 수 있다. 예를 들어 동일한 페이지이지만 한국어로 이루어졌을 수도, 영어로 이루졌을 수도 있다. 또는 이미지라는 리소스에 대해 다양한 포맷 형태가 존재하기도 한다.
콘텐츠 협상은 클라이언트가 리소스를 요청했을 때 리소스가 위와 같이 형태가 다양할 때, 어떠한 형태로 받을 지에 대해 서버와 클라이언트가 정하는 과정이다.
이 때 협상이 실패하여 결국 클라이언트가 원하는 형태의 리소스를 반환할 수 없을 때 서버는 해당 상태코드를 반환하게 된다.
다만, 실제로는 해당 반환코드를 사용하는 대신 원하는 형태가 없다면 기본값으로 설정된 리소스를 보내는 형식으로 쓰고있다. 사용자 경험상 에러 페이지를 반환받는 것 보단 뭐라도 받는 것이 더 낫기 때문인 것 같다.
■ 407 (Proxy Authentication Required): 프록시 서버에 대한 인증이 필요로 할 때 반환하는 상태 코드이다.
401 상태 코드가 서버에서 인증이 필요로 하여 반환하는 것이라면 이는 프록시 서버에서 인증이 필요로 할 때 반환하는 것이다.
■ 408 (Request Timeout): 서버가 요청 대기 시간이 너무 길어 서버측에서 요청을 종료할 때 사용하는 상태 코드이다.
클라이언트의 요청이 너무 많은 시간이 소요될 것 같으면 해당 상태 코드를 반환하고 끊을 수가 있다. 요청이 많이 걸리는 이유로는 클라이언트가 요청한 데이터가 너무나도 큰 것이 이유일 수도 있고 혹은 인터넷이 매우 느려서일 수도 있다.
이 경우는 서버가 요청을 종료시키는 것이기 때문에 헤더에 Connectino: close를 반드시 같이 보내주어야한다.
■ 409 (Conflict): 서버의 현재 상태와 요청사항이 충돌했을 때 반환하는 상태 코드이다.
다른 400번대 상태코드에 있는 상황(인증, 권한 유무 등) 외에 클라이언트의 요청이 서버가 처리하기 곤란하다면 해당 상태 코드로 처리한다. 예를 들어 클라이언트가 특정 리소스를 업로드했는데 이는 현재 존재하는 리소스보다 오래된 것이기때문에 리소스의 최신을 유지하기 위해 409 상태코드를 반환할 수도 있다.
상황에 따라 여러 곳에서 쓰일 수 있기에 충돌이 발생한 이유에 대해 구체적인 본문을 포함시켜야 할 것이다.
■ 410 (Gone): 클라이언트가 요청한 리소스가 영구히 삭제된 상태일 때 반환하는 상태 코드이다.
404 상태코드와 비슷하나 404은 리소스가 영구적으로 없는건지 일시적으로 없는건지 판단할 수 없을 때 사용되고, 410 상태 코드는 리소스가 영구히 삭제됨을 알 수 있을 때 사용한다.
■ 411 ( Length Required ): 요청 메시지에 Content-Length 헤더가 없을 시 반환하는 상태 코드이다.
모든 요청에 Content-Length가 필요한 것은 아니지만 대부분의 요청에서는 요청 본문의 끝을 알 수 있는 Content-Length가 필요로 하다. 따라서 서버가 Content-Length를 필요로 하는데 해당 헤더가 없다면 411 상태코드를 통해 Content-Length를 넣어서 재요청해달라 하는 것이다.
■ 412 (Precondition Failed): 클라이언트의 조건부 요청에 대해 처리를 실패했을 때 반환하는 상태 코드이다.
If-Unmodified-Since나 If-Match 같은 조건 헤더를 단 요청에서 조건에 맞지 않을 때 반환한다.
예시로 쇼핑몰 사이트에서 물건이 단 1개 남았을 때, 사용자 2명이 동시 접속하여 동시 구매를 눌렀을 때, 조금이라도 빨리 누른 사람은 구매에 성공하지만 나머지 한 사람은 구매에 실패해야만 한다.
이를 구현하기위해 서버는 두 사람이 물건 페이지에 각각 접속 했을 때 각자에게 e-tag라는 페이지의 id값을 준다. 그리고 먼저 물건을 산 사람은 서버에 if-match를 통해 보내준 e-tag가 현재 페이지의 e-tag가 같은지 확인해달라 요청하고, 동일하다면 요청을 처리한 후 페이지 e-tag값을 변경한다. 그 후 다른 사람이 요청한 e-tag는 이제 과거의 e-tag가 되어 페이지의 e-tag와 같지 않기에 412 상태 코드를 반환하여 실패처리 한다.
참고로 304 상태 코드도 조건부 헤더를 사용하는데, 위와 다른 점은 304는 get과 head에서만 동작하고, 412는 이를 제외한 나머지 메서드에서 동작한다.
■ 413 (Content Too Large): 요청한 본문이 서버에서 정의한 제한보다 더 클 때 반환하는 상태 코드이다.
요청한 본문이 서버에서 정의한 것보다 커서 처리할 수 없을 때 반환하는 것으로 서버는 연결을 끊거나 혹은 Retry-After 헤더 필드를 반환한다.
Retry-After는 서버가 클라이언트한테 언제 다시 요청해야하는지 알려주는 헤더로서, 접근 불가하거나 혹은 서버에 사용자가 일시적으로 급격히 모여 처리할 수가 없을 때 사용되는데, 후자의 경우일 경우 413 상태 코드를 반환하는 듯 하다.
■ 414 (URL Too Long): 클라이언트가 보낸 URL이 서버가 해석가능한 URL보다 더 길 때 반환하는 상태 코드이다.
예를 들어 post 요청을 get으로 변경했는데, 이 때 필요한 쿼리 파라미터가 너무 많아서 URL 길이가 과도하게 넘어갈 때 반환하기도 한단다.
■ 415 (Unsupported Media Type): 클라이언트가 요청한 미디어 포맷이 서버에서 지원하지 않을 때 반환하는 상태 코드이다.
■ 416 (Range No Satisfiable): 서버가 요청받은 범위에 대해서 응답할 수 없을 때 반환하는 상태 코드이다.
클라이언트가 range 헤더를 통해 특정 범위의 리소스를 요청했을 때 그러한 범위를 가지고 있지 않거나 혹은 잘못된 범위를 요청했을 때 반환한다.
■ 417 (Expectation Failed): 클라이언트가 Expect 헤더를 포함한 요청을 수행할 수 없을 때 반환하는 상태 코드이다.
Expect 헤더는 클라이언트가 요청을 보내기 전 서버가 특정 동작을 수행 가능한지에 대한 여부를 확인할 수 있게끔 도와주는 것으로 보통 Expect: 100-continue가 많이 쓰인다.
만약 수행가능하면 100 상태 코드를 반환하겠지만 수행 불가하다 하면 417 상태 코드를 반환하게 된다.
■ 418 (I'm a teapot): 이게 뭐람! 만우절 농담이랍니다!
서버는 찻주전자이기 때문에 커피를 끓이는 것을 거절합니다. 설명하자면 길기 때문에 해당 상태코드에 대한 이야기는 잘 정리된 타 블로그를 연결해놓는다.
■ 421 (Misdirected Request): 클라이언트가 서버에게 잘못된 요청을 보냈을 때 반환하는 상태 코드이다.
클라이언트가 요청을 해야할 서버가 아닌 다른 서버에게 요청을 보냈을 때 같이 잘못된 요청을 보냈을 때 반환된다.
■ 422 (Unprocessable Entity): 클라이언트의 요청을 올바르나 서버에서 요청한 것을 처리할 수 없을 때 반환하는 상태 코드이다.
요청을 하는 형식이나 방법은 전부 맞지만 의미적으로 잘못된 요청이기에 처리하지 않고 반환한다. 주로 유효성 검사에서 사용된다.
■ 423 (Locked): 요청한 리소스가 잠겨있을 때 반환하는 상태 코드이다. WebDAV 전용
■ 424 (Failed Dependency): 요청한 동작이 다른 동작에 의존하고 있는데, 그 다른 동작이 실패했을 경우 반환하는 상태 코드이다. WebDav 전용
■ 426 (Upgrade Required): 서버가 현재 프로토콜을 사용하여 요청을 처리하는 것은 거부한다는 상태 코드이다.
예를 들어 HTTP/1.1 버젼으로 서버에게 요청했을 때, 서버가 HTTP/2.0만 받는다면 해당 상태코드를 반환하며 Upgrade 헤더에 서버가 필요한 프로토콜 정보를 실어서 반환한다.
■ 428 (precondition Required): 조건부 요청이 반드시 필요한 요청에 조건 헤더가 누락되었을 시 반환하는 상태 코드이다.
서버에서 요청을 처리할 때 조건부 정보가 필요하지만 클라이언트에서 관련된 정보를 보내지 않았을 때 반환하는 것이다.
■ 429 (Too Many Requests): 클라이언트가 일정 시간동안 너무 많은 요청을 보낸 경우 반환되는 상태 코드이다.
서버는 새로운 요청을 하기 전에 얼마나 기다려야하는 지에 대한 정보는 Retry-After 헤더에 실어서 보내 줄 수도 있다.
■ 431 (Request header Fields Too Large): HTTP 헤더가 너무 커서 처리가 불가할 때 반환하는 상태 코드이다.
헤더 전체의 크기가 너무 크거나 단일 헤더 필드가 너무 클 경우 사용된다.
■ 451 (Unavailable For Legal Reasons): 클라이언트가 원하는 리소스가 법적 문제로 인해 사용할 수 없는 리소스일 때 반환하는 상태 코드이다.
참고 문서
- 4XX (Client Error) 상태 코드 - 총정리 모음 - https://inpa.tistory.com/entry/HTTP-%F0%9F%8C%90-4XX-Client-Error-%EC%83%81%ED%83%9C-%EC%BD%94%EB%93%9C-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0
- mdn web docs - https://developer.mozilla.org/ko/docs/Web/HTTP/Status/400