HTTP 상태코드란?
클라이언트가 서버에 요청을 보내면 그 요청이 잘 처리 됐는지 혹은 문제가 있는지를 응답에서 알려주는 기능이다.
1xx
2xx
3xx
(redirection)
4xx
- 클라이언트 오류, 잘못된 문법 등으로 서버가 요청을 수행할 수 없음
5xx
- 서버 오류, 서버가 정상 요청을 처리하지 못함
만약 모르는 상태 코드가 나타난다면?
=> 클라이언트 입장에서는 200대는 정상처리구나~로 큰 범위로 알면 된다.
클라이언트를 바꾸지는 않아도 된다.
2xx (Successful) 성공
클라이언트의 요청은 성공적으로 처리
- 200 ok
- 201 created
- 요청 성공해서 새로운 리소스가 생성됨
- 생성된 리소스는 응답의 Location 헤더 필드로 식별
- 202 Accepted
- 204 No Content
- 서버가 요청을 하면 보통 응답값을 주는데 응답 페이로드 본문에 보낼 데이터가 없을 때 사용
- 결과 내용이 없어도 204 메시지만으로 성공을 인식할 수 있다.
- 삭제 했을 때 사용하기도 함
3xx (Redirection) 리다이렉션
요청을 완료하기 위해 유저 에이전트(클라이언트 프로그램, 웹 브라우저)의 추가 조치 필요
리다이렉션
- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면 Location 위치로 자동으로 이동한다.
자동 리다이렉트 흐름
- 요청 GET /event
- 응답 301 Moved Permanently
- Location: /new-event
- 자동 리다이렉트
- 요청 GET/new-event
- 응답 200 OK 새로운 이벤트페이지
리다이렉션 종류
- 영구 리다이렉션 (301, 308)
- 특정 리소스의 URI가 영구적으로 이동
- 일시 리다이렉션 - 일시적인 변경
- 주문 완료 후 주문 내역 화면으로 이동
- PRG: Post/Redirect/Get
- 특수 리다이렉션
- 결과 대신 캐시를 사용
1. 영구 리다이렉션
301, 308
- 리소스의 URI가 영구적으로 이동
- 원래 url을 사용하면 안된다.
- 검색엔진등에서도 변경을 인지할 수 있다.
- 301 Moved Permanently
- 리다이렉트 시 요청 메서드가 GET으로 변한다.
- 본문이 제거될 수 있다
- 처음 스펙을 정의할 당시에는 메서드를 바꿀거라고는 생각을 못해서 본문이 제거될 수 있다는 스펙이 없었는데 나중에 스펙이 바뀜
- post로 보내도 get으로 보내진다
- 308 Permanent Redirect
- 리다이렉트 시 요청 메서드와 본문 유지
- 클라이언트에서 서버로 보낼 때 post로 보내도 리다이렉트 된 후 post로 보내진다
- 하지만 실무에서는 이렇게 쓰지 않는다
- 내부적으로 전달해야하는 데이터 자체가 다 바껴버리기 때문!
- get으로 다시 돌리는게 맞다
2. 일시적인 리다이렉션
302, 307, 303
- 리소스의 uri가 일시적으로 변경
- 처음에는 a 나중에는 b로 갈 수 있다는 뜻
- 그러므로 검색엔진등에서 url을 변경하면 안된다
- 실무에서 정말 많이 씀
- 302, 307, 303 기능이 비슷
- 302 Found
- 리다이렉트 시 요청 메서드가 get으로 변하고, 본문이 제거될 수 있음(MAY)
- 메서드 유지, 대부분 바꿈, 하지만 명확하지 않음
- 처음 302 스펙의 의도는 http 메서드를 유지하는 것이었다
- (사람이 대부분 정리하는 거라서 생각하는 바를 스펙으로 정리하기는 너무 어렵기 때문에 스펙은 개정이 일어나게 된다)
- 웹 브라우저들이 대부분 get으로 바꾸어 버리지만 일부는 다르게 동작하기도 한다
- 그래서 모호한 302 대신 명확한 303과 307이 등장하게 된다
- 307, 303을 권장하지만 현실적으로 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용하고 있다
- 자동 리다이렉션시에 get으로 변해도 되면 그냥 302를 사용해도 큰 문제가 없다
- 307 Temporary Redirect
- 리다이렉트시 요청 메서드와 본문 유지
- 요청 메서드를 변경하면 안된다! (MUST NOT)
- 303 See Other
- 처음부터 조회를 다시 해야될 때 사용
- 리다이렉트 시 요청 메서드가 무조건 get으로 변경
PRG: Post/Redirect/Get
일시적인 리다이렉션
post로 주문 후에 웹 브라우저를 새로고침 한다면?
prg 사용 전
- POST /order로 주문 요청 ⇒ 데이터 저장 ⇒ 응답 200 ⇒ 새로고침 한다면 ⇒ 또 POST 요청 ⇒ 또 데이터 저장 ⇒ 응답 200
서버에서 같은 주문번호면 주문안되도록 막더라도 클라이언트에서 한번 더 막아주는 것이 좋다.
prg 사용 후
- post로 주문 후에 주문 결과 화면을 get으로 리다이렉트
- POST /order로 주문 요청 ⇒ 데이터 저장 ⇒ 응답 302 Found / 303 see other Location: /order-result/19 ⇒ 자동 리다이렉트 ⇒ get 사용해서 요청 GET/order-result/19 ⇒ 주문데이터 조회, 19번 주문했다 ⇒ 응답 200, 주문완료 화면 보여줌 ⇒ 새로고침 한다면 ⇒ GET/order-result/19 결과 화면만 다시 요청함 (GET/order-result/19)
- 실수로 새로고침 했을 때 중복주문 문제가 해결된다.
그럼 302, 307, 303 중 뭘 써야하는가?
302
⇒ get으로 변할 수 있음
307
⇒ 메서드가 변하면 안될 때
303
⇒ get으로 변경되야 할 때
3. 기타 리다이렉션
300, 304
304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다
- 로컬pc에 저장된 캐시로 리다이렉트 한다, 클라이언트는 로컬 pc에 저장된 캐시를 재사용한다.
- 클라이언트 : 캐시가 만료된거 같으니까 서버 니가 다시 내려줘
- 서버 : 아냐 더 그대로 써도돼 데이터 안줄거야 니가 그냥 캐시에 있는거 갖다 그냥 써
- 네트워크 다운로드 용량이 줄어듬
- 304 응답은 메시지 바디를 포함하면 안된다 ⇒ 로컬 캐시를 사용해야 하므로
- 조건부 get, head 요청시에 사용
- e태그도 사용가능
4xx (Client Error) 클라이언트 오류
- 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없을 때
- 오류의 원인이 클라이언트에 있음
- 중요!
- 400대 오류는 복구 불가능이다
- 클라이언트가 이미 잘못된 요청을 한 것이기 때문에 똑같이 재시도를 해도 실패한다
- 그러나 500대 오류는 복구 가능하다
- 서버에 요청을 보냈을 때 똑같이 재시도 해도 성공할 가능성이 있다는 것
400 Bad Request
클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음
- 클라이언트가 요청을 다시 수정해서 보내야함
- 요청 구문, 메시지 등등 스펙이 안맞을 때
- 요청 파라미터 안맞을 때, api 스펙이 안맞을때
401 Unauthorized
클라이언트가 해당 리소스에 대한 인증이 필요함
- 인증되지 않음
- 인증 - 본인이 누구인지 확인
- 인가 - 권한부여
- 응답에 WWW-Authenticate 헤더와 함께 인증방법을 설명해줘야 한다
- Unauthorized는 인증이 되지 않다는 뜻이다.
인증과 인가
인증 Authentication
인가 Authorization
- 권한 부여
- admin 처럼 특정 리소스에 접근할 수 있는 권한
- 인증이 있어야 인가가 있다
403 Forbidden
- 서버가 요청을 이해했지만 승인을 거부함
- 주로 인증 자격증명은 있지만 접근 권한이 불충분한 경우
- 어드민 등급이 아닌 유저가 로그인 후에 어드민 리소스에 접근하는 경우
404 Not found
요청 리소스를 찾을 수 없음
- 리소스를 제공할 수 없을 때
- 권한이 부족한 리소스에 접근할 때 리소스를 숨기고 싶을 때도 사용함
5xx (Server Error) 서버 오류
서버 오류
- 서버 내부 문제로 오류 발생
- 재시도 하면 성공할 수도 있음
- 애매하면 500 오류
- 서버는 최대한 500오류는 내지 않아야 함
503 Service Unavailable
서비스 이용 불가
- 서버가 일시적인 과부하/예정된 작업으로 잠시 요청을 처리할 수 없을 때
- Retry-After 헤더에 얼마 뒤에 복구되는지 보낼 수도 있음
- 예측 불가일 경우가 많아서 잘 안쓰고 500을 보내는 경우가 많음
Reference.