HTTP 상태코드 소개
상태코드란? 클라이언트가 보낸 요청의 처리 상태를 서버가 응답할 때 숫자 코드로 알려주는 기능
- 1xx (Informational): 요청이 수신되어 처리되고 있음을 알려줌 → 실무에서 거의 사용되지 않음! (생략)
- 2xx (Successful): 요청이 정상적으로 처리됨을 알려줌
- 3xx (Redirection): 요청을 완료하려면 추가 행동이 필요한 상황임을 알려줌
- 4xx (Client Error): 클라이언트 딴에서의 오류, 잘못된 문법 등으로 서버가 요청을 수행할 수 없다고 알려줌
- 5xx (Server Error): 서버 딴에서의 오류, 서버 장애 등으로 서버가 정상 요청을 처리하지 못한다고 알려줌
서버에서 클라이언트가 인식할 수 없는 상태코드를 반환하더라도, 상위 상태코드(백의 자리 수)로 해석해서 처리하면 된다. ex) 299 → 2xx니까 요청 처리 성공
2xx - 성공
200대 상태코드는 서버가 클라이언트의 요청을 성공적으로 처리했다는 뜻이다. 자주 사용하는 코드를 살펴보자.
- 200 OK: 요청 성공!
- 201 Created: 요청 성공해서 새로운 리소스가 생성되었다고 알려주며, 생성된 리소스가 응답 메세지 헤더 Location 필드에 작성되어 있겠구나 생각할 수 있음 ex) POST로 회원을 등록하고자 할 때
- 202 Accepted: 요청이 접수는 되었으나 처리가 완료되지 않은 상태 → 잘 사용하진 않음... ex) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리할 때
- 204 No Content: 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문(메세지 바디)에 보낼 데이터가 없는 상태 ex) 웹 문서 편집기에서 save 버튼 누를 때 그 결과로 아무 내용이 없어도 되며, 같은 화면을 유지해야 함
3xx - 리다이렉션
300대 상태코드는 서버가 요청을 완료하기 위해서 유저 에이전트의 추가 조치가 필요하다는 뜻이다. 여기서 유저 에이전트는 웹 브라우저라고 봐도 무방하다. 자주 사용하는 코드를 살펴보기전에 리다이렉션 개념에 대해 이해해야 한다.
리다이렉션
300대 응답의 결과 헤더에 Location 필드가 존재하면, 웹 브라우저는 Location 위치로 자동 이동한다. = 자동 리다이렉트

- 영구 리다이렉션: 특정 리소스의 URI가 영구적으로 이동 ex) 이벤트 페이지를 새로 만들어서 사용자가 기존 페이지 URI를 입력해도 새로운 페이지로 이동할 수 있도록 할 때
- 일시 리다이렉션: 일시적인 변경 ex) 주문을 완료하고 나서 주문 내역 화면으로 잠시 이동할 때
- 특수 리다이렉션: 결과 대신 캐시를 사용 ex) 이미지가 변경되지 않아서 기존 이미지를 그대로 사용해도 될 때
각 리다이렉션에 해당하는 코드 중, 자주 사용하는 것들을 살펴보자.
먼저, 영구 리다이렉션. 앞서 말했듯이 기존의 URL을 사용하지 않는다. 검색 엔진 등에서도 변경을 인지한다.
- 301 Moved Permanently: 리다이렉트시 요청 메서드가 GET으로 변할 수 있고, 본문(메세지 바디)이 제거될 수 있음

- 308 Permanent Redirect: 301과 기능은 같으나, 리다이렉트시 요청 메서드와 본문(메세지 바디)이 유지됨

다음으로, 일시적인 리다이렉션. 리소스의 URI가 일시적으로 변경되기 때문에 검색 엔진 등에서는 URL을 변경하면 안된다.
- 302 Found: 리다이렉트시 요청 메서드가 GET으로 변할 수 있고, 본문(메세지 바디)이 제거될 수 있음
- 307 Temporary Redirect: 302와 기능은 같으나, 리다이렉트시 요청 메서드와 본문(메세지 바디)이 유지됨
- 303 See Other: 302와 기능은 같으나, 리다이렉트시 요청 메서드가 GET으로 변경됨
PRG: POST / Redirect / GET
예를 들어서, 사용자가 주문을 하기 위해 주문정보를 입력하고 주문하기 버튼을 클릭했다. 그러면 주문정보를 POST로 서버에게 보내면 서버는 그 주문정보를 DB에 저장하고, 클라이언트에게 주문이 완료되었다며 요청 성공 메세지를 보낼 것이다.
그런데 여기서 사용자가 새로고침을 누르면 어떻게 될까?
새로고침을 누르면 가장 마지막 요청이 다시 실행되는 거기 때문에 앞서 말한 과정이 또 한번 진행된다. 그러면 중복 주문이 되는 것이다. 사용자가 계속 새로고침을 누르면 누를 때 마다 주문이 1개씩 더 들어가게 된다.
이런 상황을 막기 위해서 PRG가 필요한 것이다!!!

POST로 주문 후에 주문 결과 화면을 GET 메서드로 리다이렉트하기 때문에, 새로고침을 하면 GET으로 결과 화면을 조회하게 된다. 따라서, 아무리 새로고침을 눌러도 결과 화면이 GET으로 다시 요청되어 중복 주문이 일어나지 않게 된다.
마지막으로 특수 리다이렉션.
- 300 Multiple Choices: 안씀
- 304 Not Modified: 캐시를 목적으로 사용함 → 캐시로 리다이렉트 함
- 캐시 기간이 만료된 것 같아서 서버한테 리소스를 다시 보내달라고 요청한다. 그럼 서버는 클라이언트한테 리소스가 수정되지 않았으니, 기존 리소스를 다시 써도 된다고 알려준다. 그 응답을 받은 클라이언트는 로컬에 저장된 캐시를 재사용한다.
- 304 응답은 응답에 메세지 바디를 포함하면 안된다. → why? 로컬 캐시를 사용해야하니까
- 조건부 GET, HEAD 요청시 사용한다.
4xx - 클라이언트 오류
400대 상태코드는 클라이언트의 요청에 잘못된 문법 등으로 서버가 요청을 수행할 수 없을 때를 뜻한다. 즉, 오류의 원인이 클라이언트한테 있다는 것이다. 이때, 같은 요청을 계속 재시도해도 이미 클라이언트 단에서 잘못된 요청과 데이터를 보내고 있기 때문에 요청에 실패한다.
- 400 Bad Request: 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없다. 클라이언트는 요청 내용을 검토하고 다시 보내야한다. ex) 요청 파라미터가 숫잔데 문자로 보낸다거나, API 스펙이 맞지 않는다거나 ...
- 401 Unauthorized: 클라이언트가 해당 리소스에 대한 인증이 필요하다. 여기서 인증은 로그인을 의미하며, 서버는 응답에 WWW-Authenticate 헤더와 함께 인증 방법 설명을 보내준다.
- 403 Forbidden: 서버가 요청을 이해했지만 승인을 거부한다. 로그인은 했으나, 접근 권한이 불충분한 경우이다. ex) 관리자가 아닌 사용자가 로그인은 했으나, 관리자 페이지에 접근할 경우
- 404 Not Found: 요청 리소스를 찾을 수 없다. 클라이언트가 요청하는 리소스가 서버에 없다는 것이다. 또는 클라이언트가 권한이 부족한 리소스에 접근할 때, 서버는 해당 리소스에 대한 권한이 부족하다고 알려주기 싫어서 아예 없는 것처럼 숨기고 싶은 경우에도 해당 상태코드를 보낸다.
5xx - 서버 오류
500대 상태코드는 서버 문제로 발생하는 오류를 뜻한다. 완전한 서버 문제이기에, 서버가 복구되는 등 서버의 문제가 해결되고나서 재시도를 하면 요청을 성공할 수 있다.
- 500 Internal Server Error: 서버 내부 문제로 오류 발생, 애매한 경우에 500 오류를 내림
- 503 Service Unavailable: 서비스 이용 불가 → 서버가 일시적인 과부하 또는 예정된 서버 작업으로 잠시 요청을 처리할 수 없음
- Retry-After 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있음