on
HTTP 상태코드
김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식을 공부하고 정리하는 포스트입니다.
HTTP 상태코드
HTTP 상태코드에 대해서 알아보겠습니다. 상태코드는 클라이언트가 서버에 요청을 보냈을 때, 요청이 잘 처리되었는지 응답이 올 때(Response) 알려주는 코드입니다.
- 1xx (Informational): 요청이 수신되어 처리중
- 2xx (Successful): 요청 정상 처리
- 3xx (Redirection): 요청을 완료하려면 추가 행동이 필요
- 4xx (Client Error): 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음
- 5xx (Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못함
만약 미래에 추가적인 코드가 추가되어서 모르는 상태의 코드가 나타난다면 어떻게 해야할까요? 클라이언트가 인식할 수 없는 코드가 오더라도 위에 정의가 된 것처럼 맨 앞자리를 보고 판단하면 됩니다.
2xx - 성공
2xx 시리즈는 성공을 했다고 생각하면 됩니다.
- 200 OK
- 201 Created
- 202 Accepted
- 204 No Content
하나씩 살펴보겠습니다.
200 OK
200 OK는 가장 많이 보는 것입니다. 리소스를 요청하면 서버에서 결과가 정상적으로 잘 처리해서 응답하면 200 OK가 나옵니다.
201 Created
간혹 사용되는 것으로 요청에 성공하면 새로운 리소스가 생성됩니다. 클라이언트가 POST로 요청을 하면 서버에서 자원을 생성하고 URI를 관리해줍니다.
따라서 201이 넘어오면 요청이 성공했고 Location Header가 있을 수 있겠다고 판단할 수 있습니다.
202 Accepted
요청이 접수는 되었지만 처리가 되지 않은 경우 나타납니다. 예를 들어 1시간 뒤에 배치 프로세스가 요청을 처리하는 경우가 있습니다.
204 No Content
서버가 요청을 성공적으로 수행했지만, 응답으로 보낼 데이터가 없는 경우 발생합니다. 예를 들어 게시글을 저장할 때 사용할 수 있습니다. 본문을 작성하고 저장을 누른 다음 같은 화면을 유지하면 되기 때문에 사용할 수 있습니다.
결과 내용이 없어도 204 메시지로 성공을 인식할 수 있습니다.
3xx - 리다이렉션
조금 더 복잡한 3xx 시리즈인 리다이렉션에 대해서 알아보겠습니다. 리다이렉션은 요청을 완료하기 위해 유저 에이전트(클라이언트 프로그램, 주로 웹브라우저)의 추가적인 작업이 필요하다고 다시 보내는 것입니다.
- 300 Multiple Choices
- 301 Moved Permanently
- 302 Found
- 303 See Other
- 304 Not Modified
- 307 Temporary Redirect
- 308 Permanent Redirect
3xx 시리즈는 300번 Multiple Choices는 거의 사용되지 않고, 301 부터 308 까지가 중요합니다.
가장 중요한 리다이렉션에 대해서 이해해야 합니다. 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동으로 이동합니다. 이것을 리다이렉트 라고 이야기합니다. 아래 그림은 자동 리다이렉션의 흐름을 나타낸 것입니다.
리다이렉션 종류
리다이렉션에는 3가지 종류가 있습니다.
- 영구 리다이렉션 : 특정 리소스의 URI가 영구적으로 이동
- 예) /members -> /users
- 일시 리다이렉션 : 일시적인 변경
- 주문 완료 후 주문 내역 화면으로 이동
- PRG: POST / Redirect / Get
- 특수 리다이렉션
- 결과 대신 캐시를 사용
영구 리다이렉션
301과 308이 영구 리다이렉션에 해당합니다. 리소스의 URI가 영구적으로 이동했다는 것을 알려주는데 원래 URL을 더 이상 사용해서는 안된다고 알려줘야 합니다. 이러한 변화에 대해서 검색 엔진 등에서도 인지 할 수 있습니다.
301과 308 둘 다 경로가 변경되었음을 알려주는데 차이점이 무엇일까요? 301의 경우 리다이렉트 시 요청 메서드가 GET으로 변하고, 본문이 제거될 수도 있습니다. 308은 301과 기능이 동일하지만, 리다이렉트 시 요청 메서드와 본문을 유지합니다. 처음 POST를 보내면 리다이렉트도 POST를 유지합니다.
등록을 위해 POST로 보냈지만 결과적으로 GET으로 전송되고 메시지 바디 부분이 사라질 수 있습니다. 이러한 부분을 308로 해결할 수 있습니다.
일시적 리다이렉션
일시적 리다이렉션은 리소스의 URI가 일시적으로 바뀌는 것입니다. 안 바뀔수도 있고, A로 갔다가 B로 갈수도 있습니다. 따라서 영구적인 리다이렉션과 달리 검색 엔진 등에서 URL을 변경하면 안됩니다.
302, 307, 303이 있고 3가지 모두 기능은 동일하지만 일부분이 다릅니다.
- 302 Found
- 리다이렉트 시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음
- 307 Temporary Redirect
- 302와 동일한 기능
- 리다이렉트 시 요청 메서드와 본문 유지(요청 메서드를 변경하면 안됨)
- 303 See Other
- 302와 동일한 기능
- 리다이렉트 시 요청 메서드가 GET으로 변경
사실 302는 거의 바뀐다고 볼 수 있습니다. 그래서 302는 명확하지 않습니다. 무조건 GET으로 변경하고 싶어서 만들어 진 것이 303입니다.
대부분의 프레임워크나 기술 레벨에서 302를 사용합니다.
PRG : Post / Redirect / Get
일시적 리다이렉트가 언제 사용될까요? 일시적 리다이렉트가 반드시 필요한 경우가 있는데 바로 PRG라고 불리는 것입니다. POST로 상품을 주문하고 나서 웹 브라우저를 새로고침하면 어떻게 될까요? POST의 데이터가 다시 전송되서 중복이 될 수가 있습니다.
물론 이러한 경우는 서버에서 상품 ID나 그런 것을 통해서 중복 주문을 막도록 처리를 해야합니다.
POST로 주문 후 새로고침 시 중복 주문이 발생할 수 있기 때문에 주문 후 주문 결과 화면을 GET으로 리다이렉트 합니다. 이렇게 하면 결과 화면이 GET이기 때문에 새로고침을 해도 결과 화면만 계속 요청하게 됩니다.
그림에서 응답 시 302를 사용했는데 303을 사용해도 됩니다. 이렇게 PRG 이후에는 URL이 GET로 변경되었기 때문에 중복 주문을 막고 사용성이 좋아집니다.
정리
- 302 Found -> GET으로 변할 수 있음
- 307 Temporary Redirect -> 메서드가 변하면 안됨
- 303 See Other -> 메서드가 GET으로 변경
처음 302 스펙의 의도는 HTTP 메서드를 유지하는 것이였습니다. 그런데 일부는 다르게 동작하지만 대부분의 웹 브라우저들이 GET으로 바꾸어 버렸습니다. 그래서 모호한 302를 대신하는 명확한 307, 303이 등장하게 되었습니다.
물론 307, 303을 권장하지만 현실적으로 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용하고 자동 리다이렉션시에 GET으로 변해도 되면 그냥 302를 사용해도 큰 문제가 없습니다.
기타 리다이렉션
- 300 Multiple Choices
- 사용하지 않음
- 304 Not Modified
- 캐시를 목적으로 사용
- 클라이언트에게 리소스가 수정되지 않았음을 알려줌. 따라서 클라이언트는 로컬 PC에 저장된 캐시를 재사용함(캐시로 리다이렉트)
- 304 응답은 응답에 메시지 바디를 포함하면 안됨 (로컬 캐시를 사용해야 하므로)
- 조건부 GET, HEAD 요청시 사용
4xx - Client Error
오류의 원인이 클라이언트에게 있는 경우 4xx 에러가 발생합니다. 이 때 중요한 것이 있습니다. 클라이언트가 잘못된 요청, 데이터를 보내고 있기 때문에 똑같이 재시도 할 경우 실패하게 됩니다.
400 Bad Request
클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없을 때 발생합니다. 요청 구문, 메시지 등등을 잘못 보낸 경우에 발생하며, 클라이언트는 요청 내용을 재검토해서 다시 보내야 합니다. 백엔드 개발자는 이러한 부분을 철저히 검증해서 입구에서 차단해야합니다. 클라이언트의 잘못임을 명확히 보내줘야 클라이언트가 요청을 다시 살펴볼 수 있기 때문입니다.
401 Unauthorized
401은 인증이 되지 않았을 때 발생합니다. 클라이언트가 해당 리소스에 대한 인증이 필요하다는 뜻으로 401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명해주어야 합니다.
- 참고
- 인증(Authentication) : 본인이 누구인지 확인 (로그인)
- 인가(Authorization) : 권한 부여 (Admin 권한처럼 특정 리소스에 접근할 수 있는 권한, 인증이 있어야 인가가 있음)
오류 메시지가 Unauthorized로 인가가 되지 않은 것 같지만 실제로는 로그인되지 않은 것, 즉 인증에 대한 부분입니다.
403 Forbidden
Forbidden은 서버가 클라이언트의 요청을 이해했지만 승인을 거부하는 것입니다. 주로 인증 자격은 증명했지만, 접근 권한이 불충분한 경우에 발생합니다. 즉 관리자가 아닌 사용자가 관리자 권한이 필요한 리소스에 접근할 때 발생합니다.
404 Not Found
우리가 흔히 볼 수 있는 것으로 요청한 리소스가 서버에 없을 때 발생합니다. 또는 클라이언트가 권한이 없는 리소스에 접근할 때, 해당 리소스를 완전히 숨기고 싶을 때 사용하기도 합니다.
5xx - Server Error
4xx가 클라이언트 문제라면 5xx는 서버의 문제입니다. 서버에 문제가 있기 때문에 재시도했을 때 서버가 복구되서 성공하는 경우도 있습니다.
500 Internal Server Error
이름 그대로 서버 내부 문제로 오류가 발생한 것을 나타냅니다. 서버 측에서 오류가 발생했을 때 애매하다 싶으면 500 오류를 사용하면 됩니다.
503 Service Unavailable
서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없을 때 사용할 수 있습니다. Retry - After 헤더 필드로 얼마 뒤에 복구되는지 보낼 수 있습니다. 물론 에러는 예측할 수 없기 때문에 503을 보는 경우는 거의 없고, 대부분 500 에러가 떨어지게 됩니다.
한 가지 조심해야 할 것이 있습니다. 정말 서버의 문제가 터졌을 때를 제외하고는 5xx 에러를 서버에서 만들어서는 안됩니다.
예를 들어 비즈니스 로직 상 API도 완벽하고 고객의 요청도 서버까지 들어왔을 때, 고객의 잔고가 부족하다고 해봅시다. 이런 경우 정상적인 프로세스인데 비즈니스 로직 상 예외 케이스이기 때문에 5xx 에러를 발생시켜서는 안됩니다.
Comments
CS 의 다른 글
-
HTTP 헤더 - 캐시와 조건부 요청 03 Jan 2022
-
HTTP 헤더 - 일반 헤더 26 Dec 2021
-
HTTP 상태코드 20 Dec 2021
-
HTTP 메서드 활용 17 Dec 2021
-
HTTP 메서드 12 Dec 2021
-
HTTP 기본 09 Dec 2021
-
URI와 웹 브라우저 요청 흐름 08 Dec 2021
-
인터넷 네트워크 06 Dec 2021
-
Single LinkedList 01 Oct 2021
-
ArrayList 24 Sep 2021
-
List Interface(리스트 인터페이스) 23 Sep 2021
-
자바 컬렉션 프레임워크 20 Sep 2021
-
면접 기초 질문 리스트 31 Aug 2021
-
인프라 기초 총정리 14 Aug 2021
-
하드웨어와 네트워크 기초 지식 03 Aug 2021
-
오버레이 네트워크(Overlay Network) 02 Aug 2021
-
이건 꼭 알고 가자! 면접 출제 빈도가 높은 질문들 19 May 2021
-
1분 자기소개 19 May 2021
-
백엔드 개발자 면접 / 학습내용 15 Feb 2021
-
너비 우선 탐색(breadth-first search, BFS) 22 Oct 2020
-
깊이 우선 탐색(depth-first search, DFS) 10 Oct 2020
-
크리티컬 섹션(Critical Section) 10 Sep 2020
-
삽입 정렬(Insertion Sort) 04 Sep 2020
-
선택 정렬(Selection Sort) 04 Sep 2020
-
거품 정렬(Bubble Sort) 04 Sep 2020
-
LRU 알고리즘 31 Aug 2020
-
Stack, Queue 29 Aug 2020
-
awk 명령어 사용법 24 Aug 2020
-
grep 명령어 사용법 23 Aug 2020
-
DNS의 이해 14 Aug 2020
-
대칭키와 공개키 10 Aug 2020
-
HTTP & HTTPS 10 Aug 2020