본문 바로가기

개발 서적/웹을 지탱하는 기술

[웹을 지탱하는 기술] chatper 07. HTTP 메서드

 


[목차]
chapter 01. 웹이란 무엇인가?

chapter 02. 웹의 역사
chapter 03. REST 웹의 아키텍처 스타일
chapter 04. URI의 스펙
chapter 05. URI의 설계
chapter 06. HTTP의 기본
chapter 07. HTTP 메서드

 

8개 밖에 없는 메서드

HTTP 메서드에는 클라이언트가 하고 싶은 처리를 서버에게 전달하는 중요한 임무가 있음. 그럼에도 HTTP 1.1은 8개의 메서드밖에 정의되지 않았음.

메서드 의미
GET 리소스 취득
POST 서버 리소스의 작성, 리소스 데이터의 추가, 그 밖의 처리
PUT 리소스 갱신, 리소스 작성
DELETE 리소스 삭제
HEAD 리소스의 헤더(메타 데이터) 취득
OPTION 리소스가 서포트하는 메서드의 취득
TRACE 자기 앞으로 요청 메시지 반환(루프 백) 시험
CONNECT 프록시 동작의 터널 접속으로 변경

고작 8개의 메서드로 충분할까 싶지만, 이 정도로 메서드의 수를 빠듯하게 줄여놓았기 때문에 HTTP가, 그리고 웹이 성공할 수 있었다고

 

HTTP 메서드와 CRUD

CRUD란 데이터 조작의 기본이 되는 4가지 처리를 말한다. HTTP 메서드 중 GET, POST, PUT, DELETE는 CRUD라는 성질을 충족시키고 있으므로 대표적인 메서드라고 할 수 있다.

CRUD 의미 메서드
Create 작성 POST/PUT
Read 읽기 GET
Update 갱신 PUT
Delete 삭제 DELETE

 

GET - 리소스의 취득

  • GET은 지정한 URI의 정보를 가져옴
  • 가장 이용 빈도가 높은 메서드

 

POST - 리소스의 작성, 추가

  • GET 다음으로 이용 빈도가 높은 메서드. 3가지 역할이 있음
  • 서버 리소스의 작성
  • 리소스에 데이터 추가
  • 다른 메서드로는 대응할 수 없는 처리 (GET에서 URI에 포함시킨 정보를 POST의 바디에 넣어 아무리 길더라도 사용 가능하도록 함)

 

PUT - 리소스의 갱신, 작성

  • 리소스의 갱신
  • 리소스 작성

 

POST와 PUT의 사용 구분

POST와 PUT은 둘 다 리소스를 작성할 수 있다는 공통점이 있다. 그렇다면 어떻게 구분해서 사용해야 할까?

  • POST로 리소스를 작성할 경우, 클라이언트는 리소스의 URI를 지정할 수 없다. URI의 결정권은 서버 측에 있다.
  • PUT으로 리소스를 작성할 경우, 리소스의 URI는 클라이언트가 결정한다.

클라이언트가 리소스의 URI를 결정할 수 있다는 것은 클라이언트를 만드는 프로그래머가 서버의 내부 구현(URI에 어느 문자를 허용할지, 길이의 제한은 어느 정도인지 등)을 숙지하고 있어야 한다. 특별한 이유가 없는 한, 리소스의 작성은 POST로 수행하여 URI를 서버 측에서 결정하는 설계가 바람직하다.

 

DELETE - 리소스의 삭제

  • 이름 그대로 리소스를 삭제하는 메서드
  • 일반적으로 바디를 가지지 않음.

 

HEAD - 리소스의 헤더 취득

  • GET은 리소스를 취득하는 메서드라면, HEAD는 리소스의 헤더(메타 데이터)만을 취득하는 메서드다.
  • HEAD에 대한 응답에는 바디가 포함되지 않는다. 이 성질 덕에 네트워크의 대역을 절약하면서 리소스의 크기를 조사하거나, 갱신인자를 구할 수 있음

 

OPTIONS - 리소스가 서포트하는 메서드의 취득

  • 해당 리소스가 지원하고 있는 메서드의 목록을 반환
  • 응답에 포함되는 Allow 헤더에 해당 리소스가 허용하는 메서드의 목록이 담긴다. 단, OPTIONS 자체는 포함되지 않음
  • OPTIONS를 구현하는 경우, 많은 웹 애플리케이션 프레임워크에서는 리소스마다 대응하는 메서드를 반환하도록 직접 구현하지 않으면 안됨.
 

GitHub - Bellroute/TIL: Today I Learned

Today I Learned. Contribute to Bellroute/TIL development by creating an account on GitHub.

github.com

 

POST를 PUT/DELETE 대신 사용하는 방법

HTML의 form에서는 지정할 수 있는 메서드가 GET과 POST뿐이다.

 

REST - HTML Form에서 GET/POST만 지원하는 이유

연재 목록 REST - 긴 여정의 시작 REST - HTML Form에서 GET/POST만 지원하는 이유 REST - 논문(요약) 훑어보기 REST - REST 좋아하시네 REST - Roy가 입을 열다 REST - 당신이 만든 건 REST가 아니지만 괜찮아 REST -

haah.kr

이러한 HTML의 제한에 의해 웹 애플리케이션에서는 GET과 POST만을 이용하는 시대가 오랜 기간 지속되었다.

이런 제한은 Ajax의 발전(XMLHttpRequest라는 모듈을 이용해 임의의 메서드 발행)과 함께 해소되고 있지만, 여전히 GET과 POST만을 사용해야하는 상황도 존재한다. (XMLHttpRequest를 지원하지 않는 휴대전화용 브라우저의 폼)

또한 보안상의 이유로 프록시 서버에서 GET과 POST 이외의 접근을 제한하는 경우도 있다.

이런 상황에서 서버에 PUT이나 DELETE를 전달하는 방법이 2가지 있다.

_method 파라미터

  • html form의 hidden파라미터에 _method라는 파라미터를 작성하고, 원래 보내고 싶었던 메서드의 이름을 넣는다.
  • Ruby on Rails가 채용하는 방식
<form target="list/items1" action="POST">
	**<input type="hidden" id="_method" value="PUT">**
	...
</form>>
  • 요청 바디에는 폼에서 입력된 항목을 URI의 쿼리 파라미터와 같은 스펙으로 인코딩한 텍스트가 들어있음.
  • _method=PUT&body=...
  • Content-Type 헤더의 값은 application/x-www-form-urlencoded 로 이 포맷을 나타내는 미디어 타입이 들어감.
  • 웹 애플리케이션 프레임워크 등의 서버 측 구현에서는 _method 파라미터를 보고 이 요청 자체를 PUT으로 다룸

X-HTTP-Method-Override

  • _method 파라미터는 폼을 이용해 요청을 보낼 경우에는 효과적, 하지만 POST의 내용이 XML 등 application/x-www-form-urlencoded 이외의 경우에는 이용할 수 없음.
  • 이런 경우 이용할 수 있는 것이 X-HTTP-Method-Override 헤더.
  • X-HTTP-Method-Override: PUT
  • Goole의 GData가 채용하는 방식
  • 웹 애플리케이션 프레임워크 등의 서버 측 구현은 X-HTTP-Method-Override 헤더를 보고 이 요청을 PUT으로 취급함

 

조건부 요청

HTTP 메서드와 갱신일자 등으로 헤더를 구성하면 메서드의 실행 여부를 리소스의 갱신일자를 조건으로 서버가 선택할 수 있다. 이러한 요청을 가리켜 ‘조건부 요청(Conditional Request)’라고 부른다.

  • If-Modified-Since 헤더가 들어간 GET은 리소스가 이 시간 이후 갱신되어 있으면 GET한다는 의미다.
  • If-Unmodified-Since 헤더가 들어간 PUT은 이 시간 이후로 갱신되어 있지 않으면 리소스를 갱신한다는 의미다.
 

HTTP 조건부 요청 - HTTP | MDN

영향을 받는 리소스들을 검사기 값을 이용해 비교함으로써, HTTP는, 성공인 경우라도, 요청의 결과가 변경될 수 있는 조건부 요청의 컨셉을 가지고 있습니다. 그런 요청들은 캐시 컨텐츠와 쓸

developer.mozilla.org

 

멱등성과 안전성

  • 멱등성: 어떤 조작을 몇 번을 반복해도 결과가 동일한 것
  • 안전성: 조작 대상의 리소스의 상태를 변화시키지 않는 것
메서드 성질
GET, HEAD 멱등이고 안전하다
PUT, DELETE 멱등이지만 안전하지 않다
POST 멱등이지도 안전하지도 않다

 

HTTP 메소드 차이점 비교

GET vs POST

GET은 요청 메시지에 body를 포함하지 않는다. 또한 요청에 필요한 파라미터를 쿼리 스트링의 형태로 URL 뒤에 이어 붙인다. 반면, POST는 body에 데이터를 담아서 요청을 보낸다. 외부에 노출되면 안되는 정보라면 POST를 사용하여 body에 데이터를 담는 것이 좋다. 멱등성 측면에서 비교를 한다면, GET은 서버에 동일한 요청을 여러 번 전송하더라도 동일한 응답이 돌아오지만 POST는 같은 요청을 여러 번 하더라도 응답이 다를 수 있다.

POST vs PUT

POST는 Create, PUT은 update의 의미로 사용하지만 PUT도 POST와 마찬가지로 자원을 생성 가능하다. 가장 큰 차이는 멱등성이라고 할 수 있다. POST의 경우 같은 요청을 여러 번 수행하면 수행한만큼 자원이 생성되기 때문에 멱등하지 않다. 반면 PUT은 여러 번 요청을 수행해도 하나의 자원이 생성&수정되기 때문에 멱등하다.

PUT vs PATCH

PUT은 Resource의 모든 필드를 교체한다. 요청 시에 일부만 전달할 경우 전달한 필드 외 모두 null or 초기값 처리될 수 있다. 반면 PATCH는 자원의 부분만 교체한다. 요청 시에 일부만 전달할 경우 해당 필드만 수정된다.

 

메서드의 오용

HTTP 스펙으로 GET과 HEAD는 멱등이고 안전, PUT과 DELETE는 멱등이라고 정해져 있음. 그러나 웹 서비스와 웹 API의 설계를 잘못하면 이들 메서드가 안전하지 않게 되거나 멱등이 아니게 될 가능성도 있음.

GET이 안전하지 않게 되는 예

GET의 목적은 리소스의 취득이다. GET으로 리소스를 변경하거나 리소스를 삭제하는 것은 GET의 잘못된 사용방법으로, 리소스의 멱등과 안전을 보장하지 않는다.

→ GET을 바르게 이용하고 있는지 판단하는 기준은 GET의 실행 전후에 리소스에 변경이 가해져 있는지 여부다.

다른 메서드로 할 수 있는데 POST를 오용한 예

다른 메서드로 대응할 수 없는 처리를 하는 POST를 지나치게 사용하면 오용으로 이어진다. 오용이란 적절한 메서드가 마련되어 있는데도 불구하고, POST로 그 기능을 실현해 버린 것이다.

POST 오용의 예로는 XML-RPC와 SOAP이다. 둘 다 RPC를 구현하기 위한 프로토콜이지만, 모든 함수 호출을 POST로 구현하도록 설계되어 있음.

→ 리소스의 취득, 갱신, 삭제를 POST로 구현하면 GET, PUT, DELETE의 멱등성과 안전성을 이용할 수 없게 됨.

PUT이 멱등이 아니게 되는 예

PUT으로 리소스 내용의 상대적인 차분을 전송하면 PUT은 멱등이 아니게 된다. PUT으로는 그 리소스의 완전한 표현을 전송하도록 한다. (토마토의 가격을 변경하는 요청은 가격의 차(+50)로 표현하는 것이 아니라, 변경 후 의 값(150)으로 표현해야 한다.

DELETE가 멱등이 아니게 되는 예

특정 리소스를 영구적으로 나타내는 것이 아니라, 시간이나 상황에 따라 지시하는 리소스가 변화하는 리소스는 특별한 이유가 없는 한, 갱신과 삭제 등의 조작을 할 수 없도록 설계해야 한다. (최신 버전을 나타내는 리소스가 있다고 할 때 delete요청을 보낼때마다 최신의 버전의 리소스들이 순차적으로 제거됨. 즉, 멱등하지 않게 됨)

 

웹의 성공 이유는 HTTP 메서드에 있다

HTTP에서는 아주 적은 수의 메서드 밖에 정의하고 있지 않지만, 이것이야말로 REST의 통일 인터페이스 제약이다. 메서드를 한정하여 고정시켰기 때문에 결국 프로토콜이 심플하게 유지되었고 웹은 성공했다.

반응형