HTTP 응답 상태 코드

송은·2023년 8월 20일
0
post-thumbnail

클라이언트가 서버에게 작업을 요청하면 서버는 요청받은 작업을 수행한 결과를 응답으로 보내주는데
이 때 HTTP 상태 코드를 통해서 작업의 성공/실패 여부와 작업이 실패했다면 어떤 이유로 실패했는지 알려주게 된다.

200 = 성공
400 = 클라이언트가 잘못 요청함
500 = 서버가 잘못함

각 상황에 맞는 코드가 표준으로 정해져있다.

100번대

100번대 코드는 프로토콜을 교체해도 된다던가 계속 요청을 보내도 된다는 상태를 의미
거의 만나본 적은 없다고 한다.

100 Continue

계속. 이 임시적인 응답은 지금까지의 상태가 괜찮으며 클라이언트가 계속해서 요청을 하거나 이미 요청을 완료한 경우에는 무시해도 되는 것을 알려준다.

101 Switching Protocol

프로토콜 전환. 클라이언트가 보낸 Upgrade 요청 헤더에 대한 응답에 들어가며 서버에서 프로토콜을 변경할 것임을 알려준다.

102 Processing

처리. 서버가 요청을 수신하였으며 이를 처리하고 있지만, 아직 제대로 된 응답을 알려 줄 수 없음을 의미한다.

103 Early Hints

사전 도움. 주로 Link 헤더와 함께 사용되어 서버가 응답을 준비하는 동안 사용자 에이전트(user agent)가 사전 로딩(preloading)을 시작할 수 있도록 한다.


200번대

200번대 코드들은 클라이언트가 요청한 작업을 서버가 성공적으로 수행했다는 상태를 보여주는 코드이다.
"요청한 작업이 성공" 이라는 응답만으로 만족시킬 수 있지만, 더 디테일한 상태를 정의해야하는 상황이라면 200번대의 상태 코드를 적극적으로 활용하면 된다.

200 OK

작업이 성공했음을 의미한다.

201 Created

작업이 성공되었고 리소스가 새롭게 생성되었다는 것을 의미한다.
👉 일반적으로 회원가입 같은 POST 요청 또는 일부 PUT 요청 이후에 따라온다.

202 Accepted

서버가 요청을 접수했지만 아직 처리하지 않았음을 의미한다.

203 Non-Authoritative Information

서버의 원본 대신 사용자의 로컬이나 다른 복사본이 제공되었다는 상태코드이다. 프록시로 인해서 발생하는 상태코드이기도 하다.

이러한 조건에서는 203 응답이 아니라 200 OK 응답이 반드시 우선되기 때문에 보기 쉬운 상태코드는 아니다.

204 Not Content

작업이 성공되었고 컨텐츠 또한 더 이상 깔끔하게 존재하지 않음을 의미한다. (👉 게시글 삭제)


300번대

리다이렉션에 관련된 상태를 의미한다.
클라이언트가 요청한 리소스가 옮겨졌거나 삭제됐거나 해서, 정상적인 방법으로는 더 이상 해당 리소스에 접근할 수 없고 다른 URL을 통해서 그 리소스에 접근해야 하는 경우이다.

서버는 "여기에 주소 리소스 있음" 이라는 정보를 줄 수 있는데 이 때 사용되는 상태 코드들이 바로 300번대 코드들이다.

301 Permanently Moved

Permanently라는 뜻이 영구히, 영구적인 이라는 뜻이므로 영구적으로 이동한다는 것이다.
요청된 리소스가 영구적으로 이동 페이지로 이동되었다는 것이다.

301 Redirect 라는 별칭으로 불릴만큼 리다이렉션을 위한 중요 코드 중 하나이다.
브라우저는 자신의 요청의 응답으로 301을 받으면
HTTP 헤더에 있는 Location 필드를 찾고
해당 필드가 존재할 경우 Location 필드에 담긴 URL로 자동 리다이렉션한다.

HTTP/1.1 301 MovedPermanetly
Location: https://www.youtube.com/playlist?list=PLoF8DwY4sqhEcVl7CJAXJnlA48M_WZiUU

구글과 같은 검색 엔진의 봇들은 특정 페이지에 접근했는데 응답으로 301 상태 코드를 받을 경우
자동으로 페이지 정보를 갱신하기도 하기때문에
SEO 관점에서도 이 상태 코드를 올바르게 사용하는 것은 매우 중요하다.

이런 리다이렉션 설정은 보통 서버 엔진의 설정 파일 내에서도 할 수 있고, 백엔드 애플리케이션 내에서 직접 할 수도 있다.

👉 일반적인 경우 HTTP 프로토콜로 접속한 사용자를 HTTPS 프로토콜을 사용해야만 접근 가능한 포트로 보내버릴 때에 많이 사용된다. (PORT 80 접속 → PORT 443 리다이렉트)

302 Temporaily Moved

Temporaily라는 뜻이 임시적, 임시적인 이라는 뜻이므로, 임시적으로 이동했다는 것을 의미한다.
요청한 리소스가 임시적으로 이동 페이지로 이동되었다는 것이다.

301과 302의 차이는 검색엔진에서 크롤링하는 페이지가 다르다는 것이다.

브라우저에서 사용자가 A라는 페이지를 요청했는데, URL이 B라는 페이지로 변경되었다면 해당 페이지가 리다이렉트가 되었다는 것을 뜻한다.

👉 이럴 때 301 리다이렉트를 한다면 검색엔진 크롤링에서는 B라는 페이지에 대한 수집을 하지만
302 리다이렉트를 한다면 A라는 페이지에 대해서 수집한다.

304 Not Modified

클라이언트가 요청한 리소스가 이전 요청과 비교했을 때 전혀 달라진 점이 없는 것을 의미한다.

서버가 응답으로 이 상태 코드를 보내주면 클라이언트는 굳이 서버에게 리소스를 재전송 받아야 할 필요가 없다.
자신이 캐싱해두었던 리소스를 사용하게 되며, 이 과정에서 불필요한 통신 페이로드 낭비를 줄일 수 있다.

이 과정에서 서버로부터 요청된 리소스를 받는 것이 아니라, 자신이 캐싱해두었던 리소스를 사용하는 것이므로 이 또한 캐싱된 소스로 리다이렉션 되었다고 하는 것이다.
그런 이유로 304 코드는 암묵적인 리다이렉션으로 불리기도 한다.

브라우저 역시 이 응답을 위한 자체 캐싱 기능이 있다.
304 상태 코드를 응답으로 받았는데 캐싱된 리소스가 없을 경우에는
빈 화면을 띄우거나 에러 화면이 노출된다.

👉 그러니 이런 상황을 만나면 브라우저에 Cached Resource 가 없는 것이 아닌가에 대한 의심을 해볼 수 있다.


400번대

400번대 코드는 클라이언트가 서버에게 보낸 요청이 잘못된 경우를 의미한다.
가장 많이 마주하게 되는 응답 상태 코드가 400~500번대 일 것이다.

400 Bad Request

클라이언트가 요청을 잘못 날렸음을 의미한다.
이 때 뭘 어떻게 잘못 날렸는지 보통 HTTP 응답 바디에 담아서 알려주는 경우도 있지만 그렇지 않은 경우 백엔드 애플리케이션의 로그를 확인해야 한다.

401 Unauthorized

인증되지 않은 사용자가 인증이 필요한 리소스를 요청할 경우 인증이 필요하다고 알려주는 상태 코드이다.

👉 보통 로그인이 필요한 API를 비로그인 사용자가 호출했을 때 사용된다.

403 Forbidden

클라이언트가 접근이 금지된 리소스를 요청했음을 의미한다.

401은 인증이 되지 않은 사용자가 접근했을 때고,
403은 누구인지 신경쓰지 않고 이 리소스 요청은 금지라는 뜻이다.

👉 HTTPS 프로토콜로만 접근해야하는 리소스에
HTTP 프로토콜을 사용하여 접근했을 경우 403을 보내기도 한다.

👉 예를 들어 회원이 로그인을 한 상태이지만 아직 결제를 하지 않은 정기 구독 콘텐츠에 대해서 이용할 수 없는 경우이다. 401과 다른 점은 서버가 클라이언트가 누구인지 알고 있다.

404 Not Found

요청한 리소스가 존재하지 않는다는 뜻이다.

301 상태 코드랑 비슷하다고 생각할 수 있지만, 요청한 리소스가 없는 것은 같지만 301/302의 경우 리다이렉션되어 URL이 존재하고, 404는 리소스가 존재하지 않는 것이다.

405 Method Not Allowed

현재 리소스에 맞지 않는 메서드를 사용했음을 의미한다.

👉 클라이언트가 문서 조회만 제공하는 컬렉션에 POST, PUT, DELETE 를 전송해 컬렉션을 변경하려고 하는 경우에 해당한다.

백엔드 프레임워크의 경우 특정 컨트롤러에 해당 메서드를 사용하는 로직이 없다면 자동으로 405를 내려주기도 한다.

406 No Acceptable

서버 주도 컨텐츠 협상을 진행했음에도 불구하고 알맞은 컨텐츠 타입이 없다는 것을 의미한다.

클라이언트가 서버에 리소스를 요청할 때
HTTP의 헤더의 Accept 필드를 사용하여 어떤 컨텐츠 타입의 리소스를 원하는지 얘기한다.
이 필드를 명시하지 않을 경우 브라우저는 자동으로 text/html 을 비롯한 몇 가지 타입을 스스로 정의하여 헤더에 담는다.

GET https://blog.naver.com/pepega
Accept text/html,application/xhtml+xml,application/xml,*/*
...

서버는 클라이언트가 보낸 요청의 Accept 필드를 보고 앞에서부터 하나씩 찾아가며 요청받은 리소스와 알맞은 컨텐츠 타입이 있는지 하나씩 살펴보게 된다.
이후 알맞은 컨텐츠 타입이 있다면 HTTP 응답 헤더의 Content-type 필드에 해당 컨텐츠 타입을 명시해주게 된다.

HTTP/1.1 200 OK
Content-Type: text/html

이 과정에서 어떤 컨텐츠 타입의 리소스를 응답으로 내려줄 것인지는 전적으로 서버가 결정하게 된다.
이 과정을 "서버 주도 컨텐츠 협상"이라고 한다.

위 예시에서 클라이언트가 받기를 원했던 타입 중 첫번째 우선 순위를 가진 text/html 을 받아왔지만 text/html 리소스가 없는 경우 application/xhtml+xml 부터 차례대로 탐색하게 된다.

끝까지 없는 경우 */* 와일드 카드에 걸리기 때문에 서버는 리소스가 어떤 컨텐츠 타입인지 상관하지 않고 그대로 응답해줄 것이다.

만약 모두 탐색했는데도 알맞은 리소스가 없다면 406 상태 코드와 함께 "원하는 컨텐츠 타입의 리소스가 없다" 라는 응답을 줄 것이다.

408 Request Timeout

클라이언트와 서버의 연결은 성사되었지만 요청의 본문이 계속 서버에 도착하지 않은 상황을 의미한다. (요청 시간 초과)

HTTP 프로토콜을 활용하여 통신할 때는 반드시 클라이언트와 서버 간의 연결을 생성하고
요청 본문에 해당하는 데이터를 전송하게 되는데
408 상태 코드는 연결은 제대로 성사되었지만 서버가 아무리 기다려도 클라이언트가 보낸 요청 본문을 받지 못하는 경우가 발생하게 된다.

이 응답은 특정 몇몇 브라우저에서 빈번하게 보이는데, Chrome, Firefox 27+, 또는 IE9와 같은 웹서핑 속도를 올리기 위해 HTTP 사전 연결 메커니즘을 사용하는 브라우저들이 해당된다.
일부 서버는 이 메시지를 보내지 않고 연결을 끊어버리기도 한다.

429 Too Many Requests

클라이언트가 서버에 너무 많은 요청을 보낼 때 발생한다.

짧은 시간 안에 빠르게 요청을 마구 날려서 천천히 보내달라는 서버의 신호일 수 있고
유료 API를 사용하는 경우 돈을 더 내라는 의미로 사용되기도 한다.

서버에서는 429 상태 코드와 함께 응답 헤더의 Retry-After 라는 필드를 사용하여 "이 시간 이후 재요청 해주세요"라는 의미를 전달할 수도 있다.


500번대

클라이언트가 아닌 서버에서 문제가 생긴 경우이다.

500 Internal Server Error

백엔드 애플리케이션 내에서 알 수 없는 에러가 발생했다는 의미이다.
대부분 제대로 핸들링되지 않은 에러가 발생한 경우가 많다.

에러의 원인을 클라이언트에게 알려주지 않는다.
핸들링되지 않는 에러의 원인을 클라이언트에게 고스란히 알려주는 것은 보안 사고가 발생할 가능성이 있기 때문이다.
그래서 500 상태코드로 에러의 발생 자체만 알려주는 경우가 대부분이다.

만약 이 상태 코드를 만난다면 바로 서버로그를 보던가 Sentry, Bugsang 과 같은 에러 모니터링 솔루션을 활용하는 방법이 있다.

501

구현되지 않음. 서버에 요청을 수행할 수 있는 기능이 없다.

예를 들어 서버가 요청 메소드를 인식하지 못할 때 코드를 표시한다.

502 Bad Gateway

502를 만나는 가장 흔한 상황은 백엔드 애플리케이션이 죽은 상황이다.

일반적인 경우 클라이언트가 보낸 요청은 바로 백엔드 애플리케이션으로 가지 않는다.
그 앞단에는 apache, nginx 같은 서버 엔진이나 로드밸런서와 같은 것이 대신 요청을 받아서 백엔드 애플리케이션에 전달해주는 경우가 대부분이다.

server {
    listen 80;

    server_name evan.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Nginx는 80번 포트에서 대기하다가 HTTP 프로토콜을 사용한 요청을 받아 3000번 포트에서 대기하고 있는 백엔드 애플리케이션에게 전달해주는 역할을 한다.

백엔드 앞 단에는 아예 프록시 서버를 두어서 문지기 역할을 시키는 것이다.
이 때 프록시 서버와 백엔드 애플리케이션 간의 연결된 추상적인 통로를 "게이트웨이"라고 한다.
백엔드 애플리케이션이 죽어버린 경우 앞단의 문지기인 프록시 서버는 백엔드로부터 아무런 응답을 받지 못하게 되고 클라이언트에게 502 Bad Gateway 라는 응답을 보내주는 것이다.

503 Service Unavailable

서버가 요청을 처리할 준비가 되지 않았음을 의미한다.

502와 비슷한 느낌으로 사용되지만 503은 "일시적인 상황"을 의미하는 상태 코드이다.

👉 일반적으로 서버에 부하가 심해서 현재 요청을 핸들링 할 수 있는 여유가 없는 경우 많이 사용된다.
ex) AWS Lambda에서는 요청을 처리할 때 컨테이너의 동시 실행 갯수를 초과할 정도의 리소스가 필요하거나, 어떤 작업의 처리 시간이 Lambda에 설정된 컨테이너의 최대 수명 기간을 초과했을 경우 생기기도 한다.

503은 일시적인 상황이므로 429 Too Many Request와 동일하게 응답 헤더에 Retry-After 필드를 사용하여 "이 시간 이후에 다시 요청"이라는 의미를 클라이언트에게 줄 수 있다.

504 Gateway Timeout

504408 Request Timeout과 마찬가지로 요청에 대한 타임아웃을 의미한다.
그러나 504 상태 코드는 클라이언트에서 보낸 요청 때문에 타임아웃이 발생하는 것이 아니라
백엔드 아키텍처 내부에서 서버끼리 주고 받는 요청에서 발생한다.

백엔드의 아키텍처는 단순히 백엔드 애플리케이션 하나로 구성된 것이 아니기 때문에
클라이언트의 요청이 서버에 닿은 뒤에도 백엔드 애플리케이션끼리의 통신이 발생하게 된다.

만약 프록시 서버 역할을 맡은 Nginx가 백엔드 애플리케이션에 클라이언트의 요청을 전달했는데
백엔드 애플리케이션이 일정 시간 응답하지 않을 경우 Nginx는 클라이언트에게 504 Gateway Timeout을 내려주게 되는 것이다.


참고

profile
개발자

0개의 댓글