새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.

7 분 소요

목표 D-day : 47 일 오늘 HTTP 상태코드에 대해서 학습하려고 합니다.

HTTP 응답 상태코드

특정 HTTP 요청이 성공적으로 완료되었는지 여부를 나타냅니다. 응답 코드는 다섯 가지 클래스에 그룹화됩니다.

  • 정보 응답 (100 – 199)

  • 성공 응답 (200 – 299)

  • 리디렉션 메시지 (300 – 399)

  • 클라이언트 오류 응답 (400 – 499)

  • 서버 오류 응답 (500 – 599)

1xx 정보 응답(Information response)

1xx대 응답 상태는 클라이언트와 서버 간의 요청이 진행중이며, 현재까지 문제 없이 처리되고 있다는 의미를 전달하는 코드입니다.

  • 100 Continue: 클라이언트의 초기 요청 부분이 잘 수신되었으며, 계속해서 나머지 요청을 보내도 된다는 의미입니다. 예를 들어, 큰 파일 업로드 시 유용합니다.
  • 101 Switching Protocols: 서버가 클라이언트의 요청에 따라 프로토콜을 변경하고 있음을 나타냅니다. 예를 들어, HTTP에서 WebSocket으로 프로토콜을 변경할 때 사용합니다.

클라이언트가 서버에게 요청 준비를 물어보는 경우 Expect: 100-continue라는 헤더를 보낼 때가 있습니다.

서버는 요청 준비가 될 경우 이 상태 코드를 반환하여 클라이언트가 보낸 정보를 응답할 때 사용한다고 생각하면 됩니다.

만약 클라이언트가 Expect: 100-continue없이 대용량 데이터를 보낸다면 프록시에서 요청 파일이 큰 경우 서버에 Expect: 100-continue 헤더를 보내는 경우가 있습니다. 클라이언트가 생성한 헤더 정보가 아니므로 응답 코드에 1xx 를 사용하지 않아도 됩니다.

정리해보겠습니다.

정보 응답은 회사 막내가 연말 회식하기 위한 식당을 예약할 때 식당에 전화를 합니다. “오늘 저녁 8시에 20석 예약 될까요?(대용량 데이터 전송)” 그러면 식당 매니저는 “네 가능합니다.” 라는 정보 응답을 주는 거라고 생각하면 됩니다.

2xx 성공 응답(Successful responses)

2xx대 응답 상태는 클라이언트의 요청이 성공적으로 수신되고, 이해되고, 수락되었음을 나타냅니다.

요청 방법에 따른 응답 내용

Method Response Content
GET 대상 리소스
HEAD 대상 리소스, GET과 유사하지만 표현 데이터를 전송하지 않음
POST 액션의 상태 또는 결과
PUT, DELETE 액션의 상태
OPTIONS 대상 리소스에 대한 통신 옵션
TRACE 서버가 수신한 요청 메시지

CONNECT 요청을 제외하고, 200 응답은 메세지 본문을 포함해야 합니다.

만약 Content가 필요없으면, 서버는 204(No Conetent)로 응답하는 것이 좋습니다.

GET 또는 HEAD 응답의 경우, 서버는 ETag와 Last-Modified와 같은 유효성 검증 필드를 함께 보내는 것이 좋습니다.

201 Created 리소스 생성

요청이 완료되어 새로운 리소스가 생성되었음을 나타냅니다. 생성된 리소스는 Location 헤더 필드 또는 대상 URI로 식별됩니다.

  • Location : 생성된 리소스
  • body : 생성된 리소스에 대한 설명과 링크가 포함될 수 있다.
HTTP/1.1 201 Created
Location: /new-resource/123
Content-Type: application/json

{
  "id": 123,
  "name": "새 리소스",
  "createdAt": "2024-10-19T11:45:00Z"
}

202 Accepted 요청 수락

요청이 처리되기 위해 수락되었지만, 처리가 완료되지 않았음을 나타냅니다. 요청은 처리 중에 거부될 수 있습니다.

HTTP에는 비동기 작업의 상태 코드를 다시 전송할 수 있는 기능이 없습니다.

백엔드에서 시간이 많이 걸리는 작업(예: 배치 처리)을 처리할 때 유용하게 사용될 수 있습니다.

클라이언트는 일정 시간 간격으로 상태를확인하고, 필요한 경우 상태가 업데이트 될 때 다시 서버에 요청을 보냅니다.

클라이언트 규칙

클라이언트와 서버가 지속적으로 연결될 필요가 없습니다.

대신 클라이언트는 응답에 포함된 URL을 통해 진행 과정을 모니터링하면 됩니다.

202 응답을 받으면 작업이 완료된 것이 아님을 인지하고, 추가적인 상태 확인이 필요할 수 있습니다.

서버 규칙

처리 상태를 모니터링할 수 있는 API를 제공하는 것이 바람직하다.

HTTP/1.1 202 Accepted
Content-Type: application/json

{
  "status": "accepted",
  "monitorUrl": "http://example.com/status/123",
  "expectedCompletionTime": "2024-10-19T15:00:00Z"
}

203 Non-Authoritative Information

요청이 성공했지만, 응답의 내용이 원본 서버의 200(OK) 응답에서 변경된 것임을 나타냅니다. 이 상태 코드는 프록시가 콘텐츠를 수정했음을 알려주기 위해 사용됩니다.

  1. 클라이언트가 서버에게 회원 정보 조회 요청을 보냄.
  2. 서버가 응답에 회원 정보 V1을 포함해서 반환함.
  3. 프록시 서버가 이 응답을 변환해서 회원 정보 V1을 V2로 수정함.
  4. 이 수정된 응답을 클라이언트에게 전송할 때 203 Non-Authoritative Information 상태 코드를 사용함.

204 No Content

요청을 성공적으로 완료했으며 응답 컨텐츠를 추가로 보낼 필요가 없음을 나타냅니다.

클라이언트에게 추가적인 컨텐츠가 없음을 “명확히” 알리는 데 사용됩니다.

서버 규칙
  • 본문이 절대 포함되지 않아야합니다.
  • 본문이 포함되면 클라이언트에서 오류가 발생할 수 있습니다.

205 Reset Content

요청이 성공적으로 처리되었으며, 클라이언트에게 현재 문서 보기를 초기화하도록 요청할 때 사용됩니다. 주로 폼 입력 후 다시 초기 상태로 되돌릴 때 사용됩니다

클라이언트 규칙

원본 서버로부터 처음 받은 상태로 문서 보기를 재설정해야 함을 나타냅니다.

206 Partial Content

클라이언트가 범위 요청(Range Request)을 했을 때 서버가 요청한 부분을 응답하는 데 사용됩니다.

이 상태 코드는 주로 파일 다운로드에서 사용되며, 서버는 Content-Range 헤더를 통해 전송된 범위를 알립니다.

대용량 파일 다운로드를 효율적으로 처리하기 이해 클라이언트가 범위를 지정할 수 있습니다.

서버는 이에 맞춰 필요한 부분만 전송하므로, 클라이언트는 다운로드 중단 후 재개 기능을 쉽게 구현할 수 있습니다..

클라이언트 요청
GET /files/video.mp4 HTTP/1.1
Host: example.com
Range: bytes=0-1024
서버 응답
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1024/2048000
Content-Type: video/mp4
Content-Length: 1025

[binary data...]

3xx 리다이렉션 메세지(Redirection messages)

사용자가 요청을 완료하기 위해 추가 작업이 필요함을 나타냅니다.

  • 영구적 리다이렉션 301 (Moved Permanently), 308 (Permanent Redirect) : 요청 URI를 사용하지 않고 Location 헤더 필드에 제공된 URI로 영구적으로 바꾸라고 클라이언트에게 알리기 위한 상태코드
  • 일시적인 리다이렉션 302 (Found), 307 (Temporary Redirect),303 (See Other) : 요청 URI를 사용해도 된다, 임시적으로 Location 헤더 필드에 제공된 URI로 클라이언트에게 추가 작업을 요청하는 상태코드
  • 캐시 리다이렉션 304 (Not Modified) : 이전에 저장된 결과로 리다이렉션합니다.

리다이렉트 처리 주의사항

메서드 변경 유무
암묵적 변경

301 (Moved Permanently), 302 (Found) : 1차 요청 POST → 2차 요청 GET

클라이언트가 서버에 POST 요청시 서버 응답은 Location: newUrl으로 전달됩니다. 클라이언트는 GET newUrl으로 다시 추가 작업을 해야합니다.

기존 원칙은 메서드 유지였지만 관행적으로 GET으로 변경하여 요청합니다.

명시적 변경

303 (See Other) : 1차 요청 POST → 2차 요청 GET

302와 기능은 같지만 요청 메서드가 GET 으로 추가 작업하라는 명시적인 응답 코드입니다.

메서드 변경 없음

308 (Permanent Redirect), 307 (Temporary Redirect) : 1차 요청 POST → 2차 요청 POST

클라이언트가 요청한 메서드를 유지한채 리다이렉트 URL로 추가작업합니다.

본문도 유지해야합니다.

보안 고려

자동 리다이렉션이 발생할 경우, 인증 관련 헤더나 중요한 데이터를 전송하지 않도록 주의해야합니다.

특히 Authorization 또는 Cookie와 같은 헤더는 자동으로 리디렉션된 요청에 포함되지 않도록 관리해야 합니다.

제 3자 서버로 전달될 수 있는 상황이 있기 때문에 몇 가지 설정으로 방지할 수 있습니다.

  • 클라이언트에서 인증 정보를 방지한다.
  • 쿠키 설정 (SecureHttpOnlySameSite 옵션) 을 사용합니다.
무한 루프 주의

클라이언트와 서버 간의 협업에서 잘못 설정된 리디렉션이 무한 루프를 발생할 수 있습니다. 이런 상황을 감지하고 주기를 방지하는 로직이 필요합니다.

프록시 서버나 로드 밸런서가 있는 경우, 리디렉션 처리를 신중하게 관리해야합니다.

예를 들어, 프록시 서버가 리디렉션을 제대로 처리하지 않는다면 무한 리디렉션이 발생할 수 있습니다.

POST-Redirect-GET 패턴

사용자가 POST 요청을 하고 결과를 그대로 유지한다면 사용자가 중복으로 요청할 수 있습니다.

서버는 이런 문제를 줄이기 위해 3xx 응답 코드와 함께 처리 결과 URL을 Location 헤더에 추가하여 리다이렉션을 수행할 수 있습니다. 이 과정으로 클라이언트가 중복 요청을 방지하도록 합니다.

클라이언트 측에서는 POST 요청 후 서버의 리다이렉션 응답을 받아 GET 요청으로 변환하여 사용자에게 안전한 응답 결과를 제공합니다.

장점

중복 요청 방지: POST 요청이 중복으로 전송되는 것을 막아 서버에서 과부하가 걸리지 않게 할 수 있습니다.

사용자 경험 개선: 사용자가 POST 요청 이후 브라우저 새로고침을 해도 같은 요청이 반복되지 않고, 안전한 GET 요청 결과를 확인할 수 있게 합니다.

300 Multiple Choices

사용자가 요청한 리소스에 대해 서버는 여러 개의 구체적인 리소스가 있다는 것을 알려주는 상태 코드입니다.

서버가 선호하는 구체적인 리소스를 헤더 필드 Location에 추가할 수 있습니다.

서버 규칙

서버는 300 응답에서 메타데이터와 URI 참조 목록을 포함하는 콘텐츠를 포함합니다.

REQUEST

GET /example-resource HTTP/1.1
Host: www.example.com
Accept: text/html

RESPONSE

HTTP/1.1 300 Multiple Choices
Content-Type: application/json
Location: http://www.example.com/english-version // 서버가 선호하는 Location 추가

{
  "choices": [
    {
      "description": "English version",
      "uri": "http://www.example.com/english-version"
    },
    {
      "description": "French version",
      "uri": "http://www.example.com/french-version"
    },
    {
      "description": "German version",
      "uri": "http://www.example.com/german-version"
    }
  ]
}

301 Moved Permanently

영구

  • 사용 목적 : 클라이언트가 요청한 리소스 URL은 이제 사용하지 않고, 새로운 리소스 URL로 변경할 것을 응답합니다.
  • 캐시 적용이 가능하다.
  • 클라이언트는 새 리소스 URL로 변경해야합니다.
주의사항

301 응답은 캐시가 가능하므로, 캐시된 상태에서 클라이언트가 계속해서 잘못된 URI를 사용할 수 있습니다.

서버는 Cache-Control,Expries 헤더를 사용하여 캐시 만료로 관리해야합니다ㅣ.

예를 들어

  1. old-url -> 301 리다이렉트 -> change-url
  2. change-url -> 301 리다이렉트 -> current-url

change-url로 리다이렉션 하는 로직에 캐시를 관리하지 않으면 current-url이 아니라 캐시 버전 change-url이 남아 있을 수 있습니다.

HTTP/1.1 301 Moved Permanently
Location: http://example.com/current-url
Cache-Control: no-store

이런 방식으로 캐시 만료를 설정하여 최신 변경된 URL을 사용할 수 있도록 합니다.

304 Not Modified

  • 사용목적: 클라이언트가 제공한 메타데이터를 보고 기존 데이터와 동일 여부를 반환할 때 사용한다.
  • 304 상태를 반환하는 경우 바디는 없습니다.

조건부 GET 또는 HEAD 요청이 수신되었으며 조건이 거짓으로 평가되지 않았다면 200 (OK) 응답이 되었을 것임을 나타냅니다.

조건부 GET과 HEAD 란?

조건부 GET은 클라이언트가 기존 리소스 정보와 새 리소스를 요청할 때 서버 측에서 기존 리소스 정보를 보고 새 리소스를 줄지 캐시를 사용할지 결정하게 하는 작업을 말합니다.

HEAD는 리소스의 메타데이터( 예 : 크기, 수정 날짜 등)를 확인하는데 사용하며, HEAD 요청으로 리소스가 존재하는지, 또는 변경되었는지 확인할 때 사용합니다.

즉, 클라이언트가 이미 유효한 표현을 가지고 있으므로 서버는 해당 저장된 표현을 사용하도록 클라이언트를 리디렉션합니다.

주의사항: 서버는 304 응답을 생성할 때 Content-Location, Date, ETag 및 Vary 헤더 필드를 반드시 생성해야 합니다. 304 응답은 헤더 섹션의 끝으로 종료되며 콘텐츠나 트레일러를 포함할 수 없습니다.

예시
  1. 클라이언트 요청 : 클라이언트가 조건부 GET 요청을 합니다.

    GET /example-resource HTTP/1.1
    Host: www.example.com
    If-None-Match: "abc123"
    
  2. 서버 응답: 클라이언트가 전송한 Etag: abc123과 현재 Etag를 비교해서 동일하여 같은 리소스라면 수정되지 않았으므로 기존 데이터를 사용하라는 응답을 전송합니다.

    HTTP/1.1 304 Not Modified
    Content-Location: /example-resource // 클라이언트가 요청한 리소스
    Date: Sat, 19 Oct 2024 03:08:11 GMT // 응답이 생성된 날짜
    ETag: "abc123" // 현재 리소스 고유 식별자
    Vary: Accept-Encoding // 요청 헤더
    

305 Use Proxy

305 (Use Proxy) 상태 코드는 이전 버전의 사양에서 정의되었으며 이제는 사용되지 않습니다.

306 (Unused)

306 상태 코드는 이전 버전의 사양에서 정의되었으며 더 이상 사용되지 않으며 코드가 예약되어 있습니다.

출처

댓글남기기