본문 바로가기
CS/Network

[Network] RFC에 정의된 HTTP Method

by gamxong 2025. 1. 13.

 

계기

현재 저는 웹서버를 구현해보고 있습니다.

웹서버 구현 4단계에서 기존에 GET 메서드로 처리했던 회원가입 로직을 POST를 활용하여 구현하는 요구사항이 생겼습니다.

단순히 요청을 변경하면 쉽게 구현할 수 있습니다.

 

하지만 실제 웹서버를 구현하는 만큼 HTTP 명확한 스펙을 보고 실제 웹서버와 비슷하게 구현해보고 싶었습니다.

그래서 이번 시간에는 HTTP Method 에 대해 정확한 스펙을 보고 이를 구현해보고자 합니다.

 

HTTP Method

요청 메서드(HTTP Method)는 요청의 의미로, 클라이언트가 이 요청을 만든 목적과 클라이언트가 기대하는 성공 결과를 나타냅니다.

 

HTTP Method의 의미는 요청에 특정 헤더 필드가 포함된 경우, 해당 헤더 필드의 의미에 따라 더 세부적으로 정의될 수 있습니다. 단, 이러한 추가 의미는 메서드의 기본 의미와 충돌해서는 안된다고 합니다.

 

HTTP Method 의 스펙은 아래와 같습니다.

  method = token

 

먼저 Token 에 대해 잠깐 알아본 후에 다시 HTTP Method 스펙으로 돌아와보겠습니다.


Token

여기서 token 이란?

token짧은 텍스트 식별자로서, 공백이나 구분자가 포함되면 안됩니다.

  token          = 1*tchar

  tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
                 / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
                 / DIGIT / ALPHA
                 ; any VCHAR, except delimiters
                 
  delimiters     = (),/:;<=>?@[\]{}

 

구체적으로 설명하자면, token1*tchar 로 구성되어있습니다.

여기서 1*tchar 의 의미는 최소 1개이상의 tchar 로 구성되어 있다는 의미입니다.

tchar 는 위의 스펙처럼 구분자(delimiters)를 제외한 여러 숫자 및 문자가 될 수 있습니다.

 


HTTP Method 의 자세한 스펙

이렇게 HTTP Method 는 token 형식을 지켜야 한다는 것을 알아봤습니다.

이제 더 자세한 스펙에 대해 알아보겠습니다.

 

1. HTTP Method 는 case-sensitive 하다. 무조건 대문자만 가능하다.

- 주목하면 좋을 부분은 HTTP Header 나 host는 case-insensitive 한 반면에 HTTP Method 는 case-sensitive 하다는 것입니다. 따라서 무조건 대문자만 가능합니다.

 

2. 일반적인 목적의 서버는 무조건 GET 과 HEAD 동작을 지원해야 한다.

- 다른 HTTP Method 는 Optional 이지만, GET 과 HEAD 동작에 한해서는 필수로(MUST) 지원해야 한다고 합니다.

- 스펙으로 정한 것이긴 하지만, 왜 이런 스펙을 정했는지 고민해보는 것도 재밌는 것 같습니다. 왜 일까요?

- 추론이긴 하지만, HTTP의 핵심 동작은 클라이언트가 서버로부터 리소스를 요청하고 가져오는 것입니다. 이를 정의하는 메서드 중 가장 중요한 두 가지가 GETHEAD 이기에 이를 지원하는 것을 default 로 둔 것이 아닐까 생각이 듭니다.


3. 인식 불가하거나 구현되지 않은 메서드는 501 에러를 반환해야 한다.

4. 인식 가능하고, 구현이 되어있지만 허용되지 않은 요청일 경우 405 에러를 반환해야 한다.

- 3번과 4번은 사실 제가 여태 개발하면서 잘못 알고 있었던 부분이었습니다. 만약 클라이언트가 서버에서 지원하지 않은 메서드로 요청할 경우, 405 에러를 반환해왔습니다. 서버에 지원하지 않은 요청을 했기에 클라이언트 에러(4xx)라고 생각했기 때문입니다. 

 

안전한 메서드

RFC 문서를 보면 "안전한 메서드(Safe Methods)"에 대한 정의가 재밌습니다. 

쉽게 생각해보면, "안전하다"는 의미는 어떤 서버의 위협이 되지 않은 메서드를 안전하다고 생각할 수 있습니다.

 

하지만 RFC 에서는 본질적으로 "read-only"인 메서드에 대해 "안전하다"고 표현합니다. 즉, 클라이언트가 원본 서버에 어떤 상태변경을 요청하거나 예상하지 않는 경우입니다.

다시말해, GET 과 같은 read-only 메서드로 서버의 부하를 줘 서버가 다운되더라도 이를 안전한 메서드(Safe Methods)라고 정의한다는 것입니다.

 

RFC 문서에서 정의한 안전한 메서드는 아래와 같습니다.

  • GET
  • HEAD
  • OPTIONS
  • TRACE

"안전하다"는 의미가 상식적인 의미와 조금 다르기에 이렇게 구분한 의도를 명확히 이해하는 것이 중요합니다.

그 이유는 아래와 같습니다.

 

1. Spiders(웹 크롤러)가 서버를 안전하게 탐색하도록 보장

  • Spiders 는 웹사이트의 콘텐츠를 수집하고, 사람들이 원하는 정보를 찾을 수 있도록 도와주는 현대 웹 생태계에서 매우 중요한 역할을 합니다.
  • 이러한 Spiders는 수백만 개의 페이지를 크롤링할 수 있기 때문에, 이러한 요청이 서버에 영향을 미친다면 예기치 못한 문제가 발생할 수 있습니다. 

 

2. 캐시 성능 최적화(pre-fetching)에 악영향을 주지않고 작동

  • Pre-fetching은 클라이언트가 사용자가 요청하기 전에 리소스를 미리 가져오는 방식입니다. 캐시나 브라우저는 미리 데이터를 가져올 때 주로 GET 요청을 사용합니다.
  • Pre-fetching은 사용자 경험을 개선하기 위해 수행되지만, 요청이 서버에 영향을 미친다면 문제가 될 수 있습니다.
  • 예를 들어, Pre-fetching이 POST 요청을 실행하면 사용자가 원하지 않는 상태 변경(예: 게시글 등록)이 발생할 수 있습니다.
  • 따라서 GET 메서드가 안전하다는 점은 캐싱 시스템이 미리 데이터를 가져와도 서버에 해를 끼치지 않도록 보장합니다.

 

뿐만 아니라, 클라이언트 신뢰할 수 없는 서버에 요청할 때 un-safe Method(안전하지 않은 메서드)의 사용에 적절한 제약을 적용할 수 있도록 합니다.

다시 말해, 클라이언트는 "안전한 메서드" 와 "안전하지 않은 메서드"을 구분해야 하며, 이를 통해 "안전하지 않은 메서드"의 경우 사용자가 인지할 수 있도록 해야합니다.

 

멱등 메서드

서버에 동일한 요청을 여러번 하더라도 단일 요청과 의도된 결과 같으면 "멱등한 메서드"라고 합니다.

 

멱등한 메서드는 아래와 같습니다.

  • Safe method 전부
  • PUT
  • DELETE

멱등한 메서드는 클라이언트가 서버의 응답을 읽기 전에 통신 실패가 발생하는 경우 요청을 자동으로 반복할 수 있기 때문에 다른 메서드와 구별됩니다.

클라이언트에서는 특별한 경우를 제외하고는 멱등하지 않은 메서드를 자동으로 재시도하는 로직을 넣어서는 안됩니다.

 

 

POST Method

POST는 클라이언트가 서버에 데이터를 전달하여 서버가 해당 데이터를 처리하도록 요청하는 HTTP 메서드입니다. 서버는 요청에 포함된 데이터를 자체적으로 정의된 방식에 따라 처리하며, 그 처리 결과에 따라 적절한 응답을 반환합니다.

 

다양한 경우에 의해, 거의 모든 상태코드를 반환할 수 있지만 아래 코드는 반환하면 안됩니다.

  • 206 Partial Content: 부분 콘텐츠 제공 (POST에 적용되지 않음).
  • 304 Not Modified: 리소스가 수정되지 않음 (POST에 적용되지 않음).
  • 416 Range Not Satisfiable: 범위 요청이 잘못됨 (POST에 적용되지 않음).

그럼 어떤 경우에 어떤 상태 코드를 반환하는게 좋을까요?

 

  1. 201(Created)
    1. 하나 이상의 리소스가 생성된 경우, 201를 반환해야(SHOULD) 합니다.
    2. Location 헤더 필드에는 새로 생성된 리소스의 식별자 (URI)를 제공합니다.
  2. 303(See Other)
    1. 만약 POST 처리 결과가 기존 리소스와 동일한 경우, 서버는 Location 헤더 필드에 기존 리소스 식별자를 포함하여 303 응답을 통해 해당 리소스로 리다이렉션 할 수 있습니다.
    2. 리다이렉션을 사용하면, 리소스가 다른 요청 방식(GET 등)으로 전달되므로, 캐시된 응답을 재사용할 수 있습니다.
    3. 클라이언트가 이미 해당 리소스를 캐시하지 않았다면 추가적인 요청이 발생할 수 있습니다.

 

GET Method

 

  • GET리소스를 읽어오는 요청으로, 서버는 리소스의 현재 상태를 응답으로 반환합니다.
  • URI는 리소스를 식별하는 방법으로 사용되며, 실제 구현은 파일 시스템이 아닐 수 있습니다. 예를 들어, 데이터베이스나 다른 정보 시스템을 통해 리소스를 제공할 수 있습니다.
  • GET 요청캐시 가능하며, Cache-Control 헤더에 의해 제어될 수 있습니다.
  • 민감한 데이터는 POST 요청을 통해 전송하는 것이 더 안전하며, GET은 URI에 데이터를 포함시키므로 주의가 필요합니다.
    • POST 요청은 데이터를 요청 본문(Body)에 포함시키기 때문에, URL에 민감한 정보가 노출되지 않습니다. 브라우저 히스토리나 서버 로그에 민감한 데이터가 기록되지 않는 장점을 가지고 있습니다.

 

HEAD Method

HEAD 방법은 GET과 동일하지만 서버는 응답에서 콘텐츠를 보내면 안 됩니다. HEAD 메서드는 메타데이터를 얻는 데 사용되며, 종종 하이퍼텍스트 링크를 테스트하거나 최근 수정 사항을 찾기 위해 사용됩니다.

 

서버는 요청 방법이 GET이었을 때 전송했을 것과 동일한 헤더 필드를 HEAD 요청에 대한 응답으로 전송 해야 합니다.

서버는 콘텐츠를 생성할 때 값이 결정되는 헤더 필드를 생략할 수 있습니다 (꼭 생략해야 하는 것은 아님). 예를 들어, Content-Length 필드의 경우 컨텐츠를 생략하기에 해당 필드를 생략할 수 있습니다.

 

 

마무리

지금까지 RFC 문서에 정의된 HTTP Method 스펙에 대해 알아봤습니다. 앞으로 Body 나 리다이렉션 같은 스펙도 구체적으로 보면서 HTTP 공부 및 HTTP 스펙을 엄격히 지킨 웹서버를 만들어보고자 합니다.

 

 

참고

https://www.rfc-editor.org/rfc/rfc9110.html#name-methods

'CS > Network' 카테고리의 다른 글

Rest, Rest API, Restful  (0) 2023.04.06
HTTP 기본적인 내용  (0) 2023.04.06

댓글