Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

develog

HTTP Method 정리 본문

CS

HTTP Method 정리

LineGu 2022. 1. 29. 18:12

HTTP의 메서드들에 대해서 알아보자.

HTTP 메서드는 HTTP 동사라고도 불리며, REST한 API에서 어느걸 하고자 하는지를 담당하고 있다.

GET

URI가 가진 정보를 얻기 위해, 서버측에 URI에 해당하는 리소스를 달라고 요청하는데 사용한다.

보통의 경우, 요청에 특정 조건을 넣기 위해서 Path 파라미터나 Query 파라미터를 이용한다.

GET api/user?age=30

이런식으로 사용한다는 뜻이다.

하지만, 너무 조건이 복잡해지고 길어지게될 때, Body에 정보를 담아 보내고 싶은 욕구가 생길수도 있다.

GET에 Body를 넣어도 될까?

해도 될까..?

RFC 문서를 참고해보자.

"The GET method means retrieve whatever information (in the form of an
entity) is identified by the Request-URI.

"A message-body MUST NOT be included in a request if the specification of the request method does not allow sending an entity-body in requests. A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request."

Body를 요청에 담아 보내는 것을 허용하지 않은 메서드에는 절대 넣지 말라고 한다. 요청 메서드에 본문의 의미를 제대로 담지 않았을 때에는 서버측에서 Body를 무시하라고 권고하고 있다.

GET 메서드는 URI에 근거해서 정보가 판단되는게 맞아보인다.

하지만, 사실 이건 2014년 이전 문서이다.

2014년 이후 문서도 살펴보자.

"Request message framing is independent of method semantics, even if the method does not define any use for a message body."

2014년 이전에 있던 두 문구는 삭제되고, 위 문구가 추가되었다.

요청 메서드와 바디는 결국 독립적인 의미를 가진다는 것인데, 더 유연해진 대답이다.

이전보다, GET 요청에 Body를 추가하는 것에 더 열려진 듯하다.

그렇다면 써도 될까?

내 대답과 MDN의 대답은 "별로 좋지 않다"이다.

일반적으로 Body와 GET을 혼용하지 않기 때문에, 이에 대한 처리가 되어있지 않아 무시될 가능성이 높다.

Restful Semantic 처럼 사람들이 많이 사용하는 디자인 설계를 무시하게 된다면 설계 자체가 굉장히 꼬일 수 있다고 생각한다.

또, Spring RestTemplate나 axios 등에서, GET 메서드에 Body를 담는 것을 막고 있다.

하지만 몇몇 어플리케이션에서 실제로 GET에 Body를 담아 요청을 보내는 경우도 있긴하다..

결론은 아래와 같다.

최대한 지양하고 URI를 이용하자. 하지만 조건이 길어진다면 고려는 해볼만하다.

POST

POST 메서드는 서버에 데이터를 보낼 때 사용하는 메서드이다.

Header에 Content-Type 설정으로 Body에 담길 데이터의 타입을 지정해줄수 있다.

이 타입이 제대로 지정되지 않으면, 원치 않은 결과를 볼 수 있다. 조심하자.

application/json -> 우리가 자주 사용하는 json 형태이다.

application/x-www-form-urlencoded -> key=value&key2=value2 이런식의 데이터이다. ajax에서 사용된다.

text/plain -> 말 그대로, text이다.

image/jpeg -> JPG 이미지.

multipart/ -> 위에 타입들은 Body에 한가지 타입만을 넣을 수 있다. 다양한 타입의 데이터도 같이 담을 수 있게 등장했다.

이 외에도 엄청 많지만, 이런식으로 구성된다는 느낌만 가져가자.

DELETE

DELETE 메서드는 특정 리소스를 삭제하고 싶을 때 사용한다.

"A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request."

payload Body를 이용하면 요청이 거절될 수 있다고 한다. DELETE 메서드에서도 Body를 사용하냐 마냐가 조금 나뉘는 듯한 모습이다.

여기에 대한 대답은 GET 요청 때와 마찬가지이다.

최대한 지양하고 URI를 이용하자. 하지만 조건이 길어진다면 고려는 해볼만하다.

PUT

PUT 메서드는 리소스를 수정할 때 사용한다.

"HTTP requests have a body if they have a Content-Length or Transfer-Encoding header. If the request has neither, it has no body, and your server should treat it as such."

즉 PUT 메서드는, Body 없이 사용할 수 없다. Body를 빈상태로 보내고 싶다면, Content-Length: 0 설정을 해줘야한다.

POST 메서드랑 다른점은 무엇일까? 바로 멱등성이다.

멱등성은 특정 요청을 아무리 여러번 해도 결과가 달라지지 않는다는 것을 의미한다.

POST는 여러 요청을 할때마다 값들이 계속해서 추가되며, 서버에 상태를 변화시킬 것이다.

하지만 PUT은 항상 수정된 동일한 상태일 것이다. 이게 PUT과 POST의 가장 큰 차이다.

따라서, PUT을 사용할 땐, 자원의 모든 필드를 모두 전달해야한다. 자칫하다간 null이나 초기값이 설정될수도 있다.

예시로, {name: 'goo', age: 20}에서 나이만 수정할 때, {age: 21}이 아닌, {name: 'goo', age: 21}을 payload에 담아 요청해야한다. 잘못쓰면 위험하다.

PATCH

PATCH 메서드는 리소스의 부분만 수정할 때 사용한다.

PUT과 다른 점은, 부분만을 수정할 수 있다는 것이다. 위 예시를 다시 들어보자면, {name: 'goo', age: 20}에서 나이만 수정할 때, {age: 21} 만을 요청에 담아도 된다.

이런 특징 때문에, 사용방식에 따라 PUT과 완전히 동일하게 작동하게 할 수 있다.

그렇게 되면 PATCH 메서드도 멱등성을 가지게 된다.

OPTIONS

OPTIONS 메서드는 목적 리소스의 통신을 설정하기 위해 사용한다.

말이 좀 어렵다. 단순히, 우리가 평소에 자주 사용하는 GET, POST 이런 요청 전에 브라우저에서 서버한테 이런 요청들이 허락된 요청들인지 물어보는 거라고 생각하면 된다.

순서대로 보면 아래와 같다.

  1. 브라우저에서 method를 OPTIONS로 요청 전송 (서버야 이거 요청 해도 되는거냐?)
  2. OPTIONS를 받은 서버가 응답헤더에 허용하는 옵션(Access-Control-Allow-*)을 포함해 전송 (응 이런것만 가능해)
  3. 브라우저는 응답헤더의 옵션을 확인해 허용되지 않은 요청은 504에러 발생, 허용하는 경우 요청 전송 (나 되네 or 나 안되네;)

이런 과정을 preflight(프리플라이트)라고 한다. 이 과정은 브라우저에서 자동으로 해주기 때문에 우리도 모르는 사이에 이루어지고 있었다. 네트워크 탭을 까보면 실제로 일어난다는걸 확인할 수 있다.

이 과정 때문에, 우리를 평소에 그토록 괴롭히던 CORS(Cross-Origin Resource Sharing)가 발생한 것이다.

OPTIONS 요청을 막아버릴 방법

웹 서버와 서버를 같은 출처(도메인, 프로토콜, 포트) 내에서 굴리면 된다. 하지만 이는 API 서버를 분리하여 설계하는 현재 방식에는 적용하기 어렵다. 이 땐, 웹 서버와 동일한 서버에 프록시 서버를 두어서 해결할 수 있긴하다.

한가지 또 다른 방법은, preflight가 일어나지 않는 조건을 모두 만족하는 것이다.

preflight는 매번 일어나는게 아니라 다음 조건을 모두 만족시키면 일어나지 않는다.

  1. GET, HEAD, POST 요청 중 하나
  2. user agent에 의해 자동으로 설정되는 헤더외에 CORS-safelisted request-header로 명시된 헤더들만 포함된 경우(Accept, Accept-Language, Content-Language, Content-Type 등)
  3. Content-Type은 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용

하지만 경험상 이것도 쉽지 않긴하다..

아무튼 결론은 OPTIONS 메서드는 보안상의 이유로 일어나는 메서드다!

CONNECT

CONNECT 서버에게 연결을 맺자고 날리는 메서드이다.

보통 HTTPS를 사용하고 있는 웹사이트에 접속할 때 쓰이게 된다.

HTTPS 서버는 항상 HTTP 프록시 서버를 두고 있는데, 애한테 "어이 서버한테 TCP 연결좀 맺자고 전해줘" 라는 메세지를 주는 셈이다.

이 때 연결에 성공하면, 대칭키가 생성되고 이를 이용해 통신을 암호화 하게된다.

만약 프록시카 키를 알게되면 보안적으로 매우 치명적이 된다. 따라서 프록시는 그냥 데이터를 전달해주는 가운데 비둘기 역할만 한다.

이렇게 프록시가 데이터를 전혀 알 길이 없기 때문에, end-to-end 보안이 보장된다.

HEAD

HEAD 메서드는 GET 메서드의 요청하고 비슷한데, 헤더 정보만 보내준다.

또, GET과는 다르게 절대로 Body를 가져서는 안된다. 만약 있더라도 서버측에서 무시해야한다.

"Responses to the HEAD request method never include a message body because the associated response header fields if present, indicate only what their values would have been if the request method had been GET"

응답 시에도 Body를 포함하지 말라고 명시하고 있다.

Health Check 처럼 웹서버 상태를 점검할 때나, 웹 서버 버전 정보를 확인하고자 할때 사용될 수 있다.

TRACE (en-US)

TRACE 메서드는 loop-back 테스트를 하는데 사용한다.

아래 그림을 보면 더 이해가 쉽다.

하지만 이는 XST(Cross-site Tracing) 공격에 취약하다.

사용자의 쿠키가 노출될 수 있기 때문이다.

따라서 Trace 메서드를 비활성화 하는 것을 권장하고 있다.


HTTP의 메서드들을 알아보았다.

많은 메서드가 있지만 잘 알아둔다면, 분명 도움이 될 것이다.

'CS' 카테고리의 다른 글

HTTPS 를 적용하기 위한 과정과 필요한 도구들  (0) 2022.02.01
HTTPS 란?  (0) 2022.02.01
HTTP/0.9부터 HTTP/3까지. QUIC란?  (0) 2022.01.28
Stateful vs Stateless (HTTP) 에 대해서 알아보자  (2) 2022.01.22
HTTP란?  (0) 2022.01.22
Comments