HTTP 상태 코드 정리
- CS/네트워크
- 2021. 12. 4.
HTTP 상태 코드
클라이언트가 서버에 보낸 요청이 어떻게 처리 되었는지를 보여주는 코드.
- 1xx (Informational) : 요청이 수신되어 처리 중
- 2xx (Sucessful) : 요청 정상 처리
- 3xx (Redirection) : 요청을 완료하려면 추가 행동이 필요
- 4xx (Client Error) : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음.
- 5xx (Server Error) : 서버 오류, 서버가 정상 요청을 처리하지 못함.
만약 모르는 상태 코드가 나타나면?
- 클라이언트가 인식할 수 없는 상태코드를 서버가 반환하면, 클라이언트는 상위 상태 코드로 해석해서 처리한다.
- 상위 상태 코드를 보고 필요한 일을 처리하면 되고, 이 덕분에 미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 됨
- 예시
1) 299 ??? -> 2xx (Successful)
2) 451 ??? -> 4xx (Client Error)
3) 599 ??? -> 5xx (Server Error)
HTTP 상태코드 2xx - 성공(요청 처리 성공)
클라이언트의 요청이 성공적으로 처리되었음.
- 200 OK
- 201 Created (뭔가 서버에서 새로 생성되서 저장됨)
- 202 Accepeted
- 204 No Contented
200 OK
- GET members/100이라는 요청이 갔을 때, 서버에서 결과를 정상적으로 잘 전달해주면 200 OK를 Return 해줌
201 Created
- 클라이언트 요청이 성공해서 새로운 리소스가 생성되었을 때 돌아오는 응답코드다. POST /members로 신규 리소스 등록 요청을 보냄. POST는 서버에서 리소스 생성한다. 이 때, 201 Created를 보내준다. 이 때, HTTP Header에 Location을 도 같이 넣어준 HTTP 응답 메세지를 만들어서 응답한다.
202 Accepted
- 요청이 접수되었으나 처리가 완료되지 않았음.
- 배치 처리 같은 곳에서 사용(요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함)
204 No Content
- 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없음.
- 티스토리의 일시저장 버튼. 일시저장 버튼 누르고 편집을 계속한다. 이런 경우, 데이터는 DB에 저장하되 이 행위의 결과가 필요가 없음. 왜냐하면 같은 화면을 유지해야하기 때문임.
HTTP 상태코드 3xx - 리다이렉션
클라이언트가 서버에 요청을 했는데, 리다이렉션은 클라이언트의 요청을 완료하기 위해서는 클라이언트의 추가적인 조치가 필요하다는 것을 응답으로 알려준다. 이 때, 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동을 한다(Redirect)
위의 그림으로 Redirect의 개념을 이해할 수 있다.
- 예전에 /event라는 페이지를 배포했음. 그렇지만 더 이상 사용하지 않고 /new-event 페이지를 사용중
- 웹 브라우저에서 GET /event로 접근함.
- 요청을 받은 서버는 /event를 더 안 쓰니 경로가 바뀐 것을 클라이언트게 알려줌. 이 때 영구적으로 바뀌었기 때문에 "301 moved Permanently"라고 응답 + Location Header로 /new-event로 응답 메세지를 작성해서 응답함
- 클라이언트의 웹 브라우저는 301 코드 + Location 헤더를 확인한 후, URI를 new-event로 바꾸어 다시 한번 GET 요청을 보낸다.
- 서버는 정상적으로 접근된 것을 확인 후, 200 OK 응답 메세지를 보냄.
리다이렉션의 이해
영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동
- /members → /users
- /event → /new-event
- URI가 위의 경우처럼 영구적으로 변경됨.
일시 리다이렉션 - 일시적인 변경 (잠깐 이동 시킬 때 쓴다)
- 주문 완료 후 주문 내역 화면으로 이동 (사용자 편의성 증가)
- PRG : Post/Redirect/Get → 굉장히 자주 쓰는 일시 리다이렉션 패턴
특수 리다이렉션
- 클라이언트에 캐시가 있는데, 이 캐시 결과가 만료된 것 같다. 클라이언트가 서버에 캐시가 만료된 거 같은데, 만료된거 맞냐고 물어봄. 서버가 보고 캐시 그대로 써도 돼라고 응답을 주는 것이 특수 리다이렉션이다. 결론은 응답 결과 대신 캐시를 사용한다.
영구 리다이렉션 (301, 308)
- 리소스의 URI이 영구적으로 변경된 것을 알려주는 코드
- 원래의 URL를 사용하면 안됨→ 검색 엔진 등에서도 변경을 인지하고, 추후에는 저쪽으로 들어감
- 301 Moved Permanetly
리다이렉트시 요청 메서드가 Get으로 변하고, 본문이 제거될 수 있음(변경 + 제거 둘다 MAY임). 가령 POST로 요청했다고 하더라도, 리다이렉션 시 GET으로 변하고 본문이 제거될 수도 있음. - 308 Permanent Redirect
1) 301과 기능은 같음.
2) 리다이렉트 시 요청 메서드 + 본문 유지됨.
301 살펴보기
- 클라이언트에서 POST로 /event를 보낸다.
- 서버에서는 페이지를 안 쓰는 것을 알고 있기 때문에 301로 응답함.
- 클라이언트는 URI의 경로를 바꾸고 요청할 때 'GET'을 쓰고 본문이 제거됨(name = hello&age=20)
- 이렇게 되면, 새로운 이벤트 폼이 나오고 새로 처음부터 입력해야한다
308 살펴보기
- 클라이언트가 POST /event 요청 메세지 보낸다.
- 서버가 308로 메세지 보낸다.
- 클라이언트가 POST /new-event 요청 메세지 보낸다.
- 서버에는 처음에 등록했던 데이터가 등록이 되고, 200 OK를 받음.
일시적인 리다이렉션(302, 307, 303)
- 리소스의 URI가 일시적으로 변경(나중에 안 바뀔 수도 있음)
따라서 검색 엔진 등에서 URL을 변경하면 안됨. 다음에 들어왔을 때는 어떻게 되어있을지 모르기 때문임. - 302 Found
리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY, 대부분다 GET으로 바뀜) - 307 Temporary Redirect
302와 기능은 같음
리다이렉트 시 요청 메서드와 본문을 유지(요청 메서드를 변경하면 안된다. MUST NOT) - 303 See Other
302와 기능은 같음.
리다이렉트 시 요청 메서드가 GET으로 변경됨. (100% 명확하게 변경)
PRG : Post/Redirect/Get 패턴 (일시적인 리다이렉션)
- POST로 주문 후에 웹 브라우저를 새로고침하면?
- 새로고침은 마지막 요청을 다시 반복하는 것이다.
- 만약 결과가 남아있는 상태에서 새로고침하면, 다시 요청이 되는 것이니 중복 주문이 될 수 있음.
- POST로 마우스 하나 산다고 클라이언트가 요청을 보냄.
- 서버는 DB에 마우스 하나 샀다고 저장함.
- 서버는 클라이언트에게 200 OK + 주문완료 HTML을 보내준다.
- 이 상태에서 클라이언트가 새로고침을 누르면, 마지막에 들어갔던 POST 요청이 다시 들어감. (구매 요청)
- POST 요청을 클라이언트에서 서버로 다시 한번 보낸다.
- 서버는 DB에 마우스 하나를 샀다고 저장함.
- 클라이언트에게 주문완료를 리턴해줌. → 중복 주문이 됨
PRG 패턴으로 일시적인 리다이렉션 이용하기
- POST로 주문 후에 새로 고침으로 인한 중복 주문 방지
- POST로 주문 후, 주문 결과 페이지로 리다이렉트 + GET 메서드를 보내줌.
- 클라이언트는 결과 화면을 자동으로 GET 하기 때문에 마지막 요청은 주문 결과 페이지 요청 메세지임.
- 새로 고침을 하면 주문 결과 화면을 다시 요청함(중복 주문 제거)
- 요청 POST를 보낸다.
- DB에 마우스 하나가 쌓인다.
- 응답을 302 Found + Location으로 리다이렉트를 보낸다. 이 때 Location 헤더를 응답해줌
- 클라이언트는 300 시리즈를 보고 리다이렉트를 한다.
- GET을 사용해서 다시 조회 요청함.
- 주문완료 HTML을 만들어 응답하면서, 상태 코드를 200 OK로 보냄.
- 결과 화면에서 새로고침을 해도 마지막 요청은 GET이기 때문에 결과 페이지 다시 조회됨.
일시적인 리다이렉트, 뭘 써야함?
- 302 → GET 으로 변할 수 있음
- 307 → 메서드가 변하면 안됨
- 303 → 메서드가 GET으로 변경
현실적으로는 307, 303을 권장하지만 이미 많은 서버에서는 302가 기본값이다. 따라서 리다이렉션 시, GET으로 메서드가 변해도 되면 302를 사용해도 큰 문제가 없음.
기타 리다이렉션 (304, Not Modified)
- 304 Not Modified는 자주 사용한다.
- 캐시를 목적으로 사용한다
- 클라이언트에게 리소스가 수정되지 않았다는 것을 알려줌. 따라서 클라이언트는 로컬 PC에 저장된 캐시를 재사용한다.
- 3xx이니 리다이렉트를 하게 하고, 304는 리다이렉트 대상이 캐시임
- 304 응답은 Body를 포함하면 안된다(로컬 캐시를 사용하기 때문)
- 조건부 GET, HEAD 요청 시 사용한다.
HTTP 상태 코드, 4xx (Client Error)
- 클라이언트의 요청이 잘못된 문법등으로 구성된다면, 서버가 요청을 수행할 수가 없다.
- 오류의 원인이 클라이언트에 있음.
- 중요! 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에 똑같은 재시도를 하면 실패한다. (5xx를 나누는 중요한 기준)
400 bad request
- 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없음
- 요청 구문, 메시지 등등 오류.
- 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때.
401 Unauthorized
- 클라이언트가 해당 리소스를 쓰기 위해서는 인증이 필요함
- 인증(Authentication) 되지 않음.
- 401 오류 발생 시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명해줘야함
인증 관련 참고
- 인증(Authentication) : 본인이 누구인지 확인해줌.(로그인 할 수 있다 없다 정도만)
- 인가(Authorization) : 권한 부여(ADMIN 권한처럼 특정 리소스에 접근할 수 있는 권한, 인증이 있어야 인가가 있음)(이 리소스에 접근할 수 있는지 없는지를 결정)
- 오류 메시지가 Unauthorized 이지만 인증 되지 않음(이름이 아쉬움). 로그인 자체가 안된건데.. 살짝 애매하네.
403 Forbidden
- 서버가 사용자의 요청을 이해했지만, 승인을 거부함
- 주로 인증 자격 증명(로그인은 되었음)은 있지만, 접근 권한이 불충분한 경우.
- 어드민 등급이 아닌 사용자가 로그인은 했지만, 어드민 등급의 리소스에 접근하는 경우.
404 Not Found
- 요청 리소스를 찾을 수 없음. 요청 리소스가 서버에 없음. (클라이언트가 없는 걸 요청했으니, 잘못된 요청임)
- 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을 때.
HTTP 상태 코드, 5xx (Server Error)
- 서버 문제로 오류가 발생한다.
- 서버에 문제가 있기 때문에 재시도 하면 성공할 수도 있음(복구가 되거나 등등등)
500 Internal Server Error
- 서버 내부에 문제가 발생해서 오류가 발생함. 애매하면 죄다 500 오류로 알려주면 됨.
503 Service Unavailable
- 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음(서비스 이용 불가)
- Retry-After 헤더 필드로 얼마 뒤에 복구되는지도 예상 시간을 보내줄 수도 있음.
5xx 에러는 진짜 서버에 문제가 생겼을 때만 만들어야 한다. 예를 들어 비지니스 로직상, API 요청도 다 맞고 서버까지 들어왔는데, 고객의 잔고가 부족하다고 하자. 이런 경우에는 5xx 에러가 아니다. 또 다른 예로는 20살 넘어야 주문이 가능한데, 15살이 주문한 경우다. 이런 경우는 4xx로 보내야한다.
5xx로 보내야 할 내용들은 DB가 내려가거나, 서버가 먹통이 된 경우만 보내야한다.
'CS > 네트워크' 카테고리의 다른 글
HTTP API 설계 예시 (0) | 2021.12.07 |
---|---|
HTTP 메서드 활용 (0) | 2021.12.06 |
HTTP 메서드 관련 정리 (0) | 2021.12.04 |
HTTP의 Stateless, 비연결성 (0) | 2021.12.04 |
URI와 웹 브라우저 요청 흐름 (0) | 2021.12.04 |