상황에 맞는 메소드를 사용하여 리소스를 요청할 수 있어야 한다.
■ GET (조회)
전송 형태 :
GET [request-uri]?query_string HTTP/1.1
Host:[Hostname] 혹은 [IP]
요청받은 URI의 정보를 검색하여 응답한다.
■ HEAD
전송 형태 :
HEAD [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
GET방식과 동일하지만, 응답에 BODY가 없고 응답코드와 HEAD만 응답한다.
웹서버 정보확인, 헬스체크, 버전확인, 최종 수정일자 확인등의 용도로 사용된다.
■ POST (추가)
전송 형태 :
POST [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
Content-Lenght:[Length in Bytes]
Content-Type:[Content Type]
[데이터]
요청된 자원을 생성(CREATE)한다.
새로 작성된 리소스인 경우 HTTP헤더 항목 Location : URI주소를 포함하여 응답.
■ PUT (생성 혹은 갱신)
전송 형태 :
PUT [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
Content-Lenght:[Length in Bytes]
Content-Type:[Content Type]
[데이터]
요청된 자원을 수정(UPDATE)한다.
내용 갱신을 위주로 Location : URI를 보내지 않아도 된다.
클라이언트측은 요청된 URI를 그대로 사용하는 것으로 간주함.
■ PATCH (갱신)
전송 형태 :
PATCH [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
Content-Lenght:[Length in Bytes]
Content-Type:[Content Type]
[데이터]
PUT과 유사하게 요청된 자원을 수정(UPDATE)할 때 사용한다.
PUT의 경우 자원 전체를 갱신하는 의미지만, PATCH는 해당 자원의 일부를 교체하는 의미로 사용.
■ DELETE (삭제)
전송 형태 :
DELETE [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
요청된 자원을 삭제할 것을 요청함.
(안전성 문제로 대부분의 서버에서 비활성)
■ CONNECT
전송 형태 :
CONNECT [request-uri] HTTP/1.1
Host:[Hostname] 혹은 [IP]
동적으로 터널 모드를 교환, 프락시 기능을 요청시 사용.
■ TRACE
전송 형태 :
TRACE [request-uri] HTTP/ 1.1
Host: [Hostname] 혹은 [IP]
원격지 서버에 루프백 메시지 호출하기 위해 테스트용으로 사용.
■ OPTIONS
전송 형태 :
OPTIONS [request-uri] HTTP/ 1.1
Host: [Hostname] 혹은 [IP]
웹서버에서 지원되는 메소드의 종류를 확인할 경우 사용.
공통점 : 클라이언트에서 서버로 어떤 정보를 제출한다는 점
차이점 :
기본적인 개념으로 POST는 ‘생성’에 관여하고 PUT은 ‘수정’에 관여한다.
**POST**를 통해 “11월 28일부터 진행한다.”는 정보를 가진
“CodeStates DevOps 3기” Class를 생성해달라고 서버에 요청한 후 서버가 성공적으로 해당 요청을 수행했을시 “CodeStates DevOps 3기”라는 Class가 생성된다.
**PUT**을 통해 “CodeStates DevOps 3기”의 정보에서 “11월 28일부터 진행한다.”라는 정보를 “11월 29일부터 진행한다.”로 변경할 수 있다.
그리고 서버에 POST된 “CodeStates DevOps 3기”가 없이 PUT을 사용하였다면 PUT을 통한 “생성”을 진행할 수도 있다.
이렇게 보면 둘은 같은 역할이고 PUT이 조금 더 발전된 영역 같아 보일 수 있지만 이러한 작업이 반복될 때 둘의 차이점이 발생한다.
POST는 “CodeStates DevOps 3기”라는 Class 생성을 반복적으로 수행했을 때 “id”값이 다른 수행 횟수만큼의
같은 이름을 가진 “CodeStates DevOps 3기”라는 Class가 생성된다.
반면 PUT을 사용해 “CodeStates DevOps 3기”를 “CodeStates DevOps 4기”로 변경해달라는 요청을 반복적으로 수행 했을때는
“CodeStates DevOps 4기”로 변경된 결과값을 응답해준 후 추가적인 “수정” 이나 “생성”이 반복되지 않는다.
이 반복적인 요청에 대한 서버의 응답이 중복(변질)되지 않는 것을 “멱등성”을 지녔다고 이야기 하고
우리는 이 예제를 통해서 POST는 멱등성을 가지지 않지만 PUT은 멱등성을 가진다고 둘의 차이점을 이해할 수 있다.
■ POST와 PUT의 차이에 대해 알아보면서 느낀 내 생각
어제 수업에서 이러한 문제들에 대해 “왜”라는 기준점으로 접근하라는 엔지니어님의 말에 따라
“왜” 우리는 멱등성을 이해해야 할까에 대해 찾아봤다.
그 해답은 매소드의 안정성과 연관이 있었다. 부트캠프 첫 시간에 개발에서 문제는 ‘상수’이고 그 문제를 해결할 줄 아는 개발자가 되어야 한다.
라고 말씀해 주셨는데 멱등성은 이러한 오류로부터 훨씬 안전한 웹서비스를 구성할 수 있게 도와주는 중요한 역할을 한다.
리소스를 조회하기 위해 GET 요청을 했을 때 작업이 실패하게 되면 우리는 다시 GET 요청을 반복해야 한다.
왜냐하면 해당 리소스를 조회해야 하기 때문이다. 이때 멱등하지 않는다면 해당 리소스는 몇 번이고 계속해서 조회 될 것이다.
PUT, DELETE 역시 마찬가지다. 웹 서비스에서 리소스를 업데이트 하거나 삭제하는 요청을 오류가 발생하더라도 몇 번이고 반복적으로 수행이 가능하다.
이는 서버의 자동 복구나 타임아웃등 서버가 정상적인 응답을 하지 못하였을 때 클라이언트가 요청을 반복해도 괜찮은지에 대한 판단 근거가 된다.
공통점 : 클라이언트가 리소스를 전달하고 해당 리소스를 업데이트하길 요청한다는 공통점이 있다.
차이점 :
먼저 기본적인 차이는 PUT은 생성 및 수정인 반면 PATCH는 수정이라는 점이다.
따라서 서버에 생성된 정보가 없다면 PUT은 리소스를 생성하지만 PATCH는 작동하지 않는다.
또한 리소스에 대해 PUT은 전체를 업데이트하지만 PATCH는 리소스의 일부를 업데이트하기 때문에
PATCH는 멱등하지 않다고 할 수 있다. 멱등성을 가지기 위해서는 동일 리소스에 대해서 동일한 결과가 응답되어야 하는데.
PATCH의 경우 리소스의 일부만을 업데이트 하기 때문에 멱등성을 보장할 수 없다.
동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니고,
서버의 상태도 동일하게 남을 때, 해당 HTTP 메서드가 멱등성을 가졌다고 말합니다.
다른 말로는, 멱등성 메서드에는 통계 기록 등을 제외하면 어떠한 부수 효과(side effect)도 존재해서는 안됩니다.
올바르게 구현한 경우 GET, HEAD, PUT, DELETE 메서드는 멱등성을 가지며,
POST 메서드는 그렇지 않습니다. 모든 안전한 메서드는 멱등성도 가집니다.
멱등성을 따질 땐 실제 서버의 백엔드 상태만 보면 되며, 각 요청에서 반환하는 응답 코드는 다를 수 있습니다.
첫 번째 DELETE 요청이 200을 반환한다면, 그 이후는 아마 404를 반환할 것입니다.
DELETE가 멱등성을 가진다는 것은,
REST API에서 개발자는 DELETE 메서드를 사용해 "목록의 마지막 항목 제거" 기능을 구현해서는 안된다는 것입니다.
다만, 서버는 멱등성을 보장하지 않으며, 일부 애플리케이션은 잘못된 구현으로 멱등성 제약을 어길 수도 있습니다.
GET /pageX HTTP/1.1는 멱등성을 가집니다. 여러 번 연속해서 호출해도 클라이언트가 받는 응답은 동일합니다.
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
POST /add_row HTTP/1.1는 멱등성을 갖지 않습니다. 여러 번 호출할 경우, 여러 열을 추가합니다.
POST /add_row HTTP/1.1
POST /add_row HTTP/1.1 -> Adds a 2nd row
POST /add_row HTTP/1.1 -> Adds a 3rd row
DELETE /idX/delete HTTP/1.1의 상태 코드는 응답마다 달라질 수 있지만, 그럼에도 멱등성을 가집니다.
DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists
DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted
DELETE /idX/delete HTTP/1.1 -> Returns 404
코드로 표현을 한다면 아래와 같다. (여기에서 “data”에 해당하는 부분이 페이로드이다. 그 외는 모두 프로토콜 오버헤드이다.)
{
"status" : "OK"
"from": "localhost",
"to": "https://hanamon.kr/users/1",
"method": "GET",
<"data":{ "username" : "하나몬" }>
REST는 Representational State Transfer의 약자이다. 자원을 URI로 표시하고 해당 자원의 상태를 주고 받는 것을 의미한다.
따라서, REST는 URI를 통해 자원을 표시하고 HTTP METHOD를 이용하여 해당 자원의 행위를 정해주며
그 결과를 받는 것을 말한다.
REST를 REST답게 쓰기 위한 방법으로 공식적이지 않은 개발자들이 비공식적으로 제시한 것이다.
이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것이 목적이다.
ex) /users
Endpoint | Method | Action |
---|---|---|
/users | GET | 유저 목록 |
/users | POST | 유저 생성 |
/users/:id | GET | 유저 조회 |
/users/:id | PUT | 유저 수정 |
/users/:id | DELETE | 유저 삭제 |
ex) /posts
Endpoint | Method | Action |
---|---|---|
/posts | GET | 포스트 목록 |
/posts?userId={id} | GET | 유저별 포스트 목록 |
/posts | POST | 포스트 생성 |
/posts/:id | GET | 포스트 조회 |
/posts/:id | PUT | 포스트 수정 |
/posts/:id | DELETE | 포스트 삭제 |
ex) /todos
Endpoint | Method | Action |
---|---|---|
/todos | GET | 할 일 목록 |
/todos?userId={id} | GET | 유저별 할 일 목록 |
/todos | POST | 할 일 생성 |
/todos/:id | GET | 할 일 조회 |
/todos/:id | PUT | 할 일 수정 |
/todos/:id | DELETE | 할 일 삭제 |
ex) /comments
Endpoint | Method | Action |
---|---|---|
/comments | GET | 댓글 목록 |
/comments?userId={id} | GET | 유저별 댓글 목록 |
/comments?postId={id} | GET | 포스트별 댓글 목록 |
/comments/:id | GET | 댓글 조회 |
/comments/:id | PUT | 댓글 수정 |
/comments/:id | DELETE | 댓글 삭제 |