본문 바로가기
서버이야기/HTTP

HTTP Method 정리

by 사랑꾼이야 2022. 1. 23.
반응형

개념

HTTP는 클라이언트와 서버 사이에 이루어지는 요청/응답 프로토콜입니다. 여기서 프로토콜은 약속, 규약, 협약 을 나타냅니다. 즉, 클라이언트와 서버 사이에 이루어지는 요청과 응답의 규칙을 정의한 것입니다.

이러한 약속된 내용을 통해 HTTP Method는 주어진 리소스에 수행하길 원하는 동작을 나타냅니다.

특징

안전한 메소드(Safe Methods)

  • 안전한 메소드는 서버의 상태를 바꾸지 않는 것입니다.
  • 읽기 작업만 수행하는 메소드는 GET, HEAD, OPTION 가 있습니다.
  • 안전한 메소드는 멱등성 을 갖지만, 멱등성을 가고 있다고 모두 안전한 메소드는 아닙니다.

멱등성(Idempotent Methods)

  • 멱등성은 수학이나 전산학에서 나오는 용어로, 연산의 한 성질을 나타냅니다.
    • 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미합니다.
  • 동일한 요청을 한 번 보내느 것과 여러 번 연속으로 보내는 것이 같은 효과를 나타냅니다.
  • 올바르게 구현하였다고 가정할 경우, GET, HEAD, PUT, DELETE 메소드는 멱등성을 가지고 있습니다.
    • 여기서, 왜 DELETE 는 멱등성일까요?
      • POST를 이용해서 데이터를 생성하였다고 가정해봅시다.
      • DELETE를 이용해서 데이터를 삭제를 하였고 성공으로 Http Status 200 응답 코드를 받았습니다.
      • 삭제 요청한 것을 잊어버리고 다시 삭제를 요청하였는데, Http Status 404 응답 코드를 받았습니다.
      • 멱등성은 연산은 여러 번 적용하더라도 결과가 달라지지 않는 것이라고 하였는데, 200 → 404로 달라졌습니다.
      • 하지만 이렇게 생각해볼 수 있습니다. 처음 DELETE 요청으로 자원이 삭제가 되었습니다. 그 다음 요청에도 자원이 삭제되었기 때문에 결과가 동일하다고 볼 수 있습니다.
  • 모든 안전한 메소드는 멱등성을 갖고 있습니다.

Cacheable Methods

  • 캐시는 HTTP 응답을 나중에 검색 및 사용할 수 있도록 저장하는 것을 이야기합니다.
  • 모든 HTTP 응답을 캐시할 수 있는 것은 아닙니다.
  • 캐시 가능한 메소드는 대표적으로 GET, HEAD 입니다.
  • 캐시가 가능한 상태코드가 따로 정의되어 있습니다.
  • 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501
  • 캐시를 제어할 수 있는 HTTP 헤더 코드가 있습니다.
    • Cache-Control 은 HTTP/1.1에서 추가된 기능으로 여러 캐싱 정책을 제공하며 자세한 내용은 아래 내용 참고하면 됩니다.
    • 자세한 내용은 아래 참고 바랍니다.
    • Cahce-Controller

종류

Http Method의 종류에는 총 8가지가 있습니다. 자주 사용한 메소드 5가지와 그 외 메소드 4가지가 있습니다. 메소드는 다음과 같습니다.

GET, POST, PUT, DELETE, PATCH, HEAD, CONNECT, OPTIONS, TRACE

아래 URL은 참고용입니다.

RFC 7231, section 4: Request methods

각 HTTP Method들에 대해서 실제 구현한 예시를 통해서 알아보도록 하겠습니다.

모든 소스는 Github를 통해서 확인할 수 있습니다.

개발 환경

  • Java : 1.8
  • Spring Boot : 2.6.2
  • 그 외 JPA, Lombok, h2 사용

초기 데이터를 아래와 같이 넣어두었습니다.

INSERT INTO book(id, name) values(1, '자바의정석');
INSERT INTO book(id, name) values(2, '자바 ORM 표준 JPA 표준 프로그래밍');
INSERT INTO book(id, name) values(3, '켄트 벡의 구현 팬턴');
INSERT INTO book(id, name) values(4, '클린 코드');
INSERT INTO book(id, name) values(5, '리팩토링 2탄');

그러면, 책을 관리하는 애플리케이션을 통해서 HTTP Method 정리를 해보겠습니다.

GET

책 정보를 조회하려고 합니다. 원하는 책 하나를 조회 요청할 수 도 있고 책 전체 목록을 조회 요청할 수 도 있습니다. 여기서는 책 하나를 조회 요청해보겠습니다.

정보를 조회할 때는 URL path와 query 파라미터를 사용합니다. 두 개를 같이 사용할 수도, 따로 사용할 수도 있습니다.

URL Path

  • 리소스의 경로를 나타내며, 계층적 구조를 표현합니다.

다음을 호출해보겠습니다.

GET http://localhost:8080/book/1

결과는 다음과 같습니다.

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 14:35:01 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "id": 1,
  "name": "자바의정석"
}

Response code: 200; Time: 298ms; Content length: 23 bytes

GET은 안전한 메소드입니다. 그렇다면 멱등성일까요? 몇 번은 요청해도 응답값은 동일하기 때문에 멱등성을 갖고 있습니다.

URL Query 파라미터

  • key=value 형태를 나타내며, ?로 시작, &로 추가 가능합니다.
    • ex) ?keyA=value&keyB=valueB
  • query parameter, query string 등으로 불리며, 문자 형태로 전송됩니다.

다음을 호출해보겠습니다.

GET http://localhost:8080/book?id=1&name=자바의정석

결과는 위와 동일합니다.

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 14:51:58 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "id": 1,
  "name": "자바의정석"
}

Response code: 200; Time: 228ms; Content length: 23 bytes

정리

  • GET은 읽기 작업을 수행하기 때문에 안전한 메소드입니다.
  • GET은 안전한 메소드라서 멱등성을 만족합니다. 한 번 요청을 보내는 것과 동일한 요청을 보내는 것의 대한 응답값이 동일합니다.
  • GET은 요청 Body가 없습니다.
  • GET은 응답 데이터가 존재합니다.
  • GET은 URL 패스와 쿼리 파라미터를 자원 조회를 요청할 수 있습니다.
  • URL에 길이 제한이 있으며 2,048 자까지 제한합니다.
  • GET은 캐시 대상입니다.
  • GET은 안전한 메소드입니다.
  • GET은 멱등성을 보장합니다.
  • GET는 HTML Form을 허용합니다.

POST

새로운 책을 등록하려고 합니다. 그러려면 책 정보를 작성해서 작성된 정보를 넘겨줘야 합니다.

다음과 같이 작성하여 요청해보도록 하겠습니다.

POST http://localhost:8080/book
Content-Type: application/json

{
  "name": "함께자라기"
}

결과는 다음과 같습니다.

HTTP/1.1 201 
Location: /book/6
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 15:11:05 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "id": 6,
  "name": "함께자라기"
}

Response code: 201; Time: 503ms; Content length: 23 bytes

POST는 안전한 메소드가 아닙니다. 그래서 같은 내용으로 시도하였을 경우 동일한 결과가 나타나면 안됩니다. 같은 내용으로 다시 시도해보면 다음과 같은 2가지 결과를 얻을 수 있습니다.

첫번째

  • 이름이 중복되어도 등록은 가능하며 id가 변경됩니다.
HTTP/1.1 201 
Location: /book/6
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 15:11:05 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "id": 7,
  "name": "함께자라기"
}

Response code: 201; Time: 503ms; Content length: 23 bytes

두번째

  • 이름이 중복된 경우 등록 불가 처리를 하였습니다.
HTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 15:20:59 GMT
Connection: close

{
  "timestamp": "2022-01-14T15:20:59.262+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "message": "이미 등록된 책입니다.",
  "path": "/book"
}

Response code: 500; Time: 155ms; Content length: 130 bytes

정리

  • POST는 새로운 자원 등록을 요청할 수 있습니다.
  • PUT은 요청 Body가 존재합니다.
  • PUT은 응답 Body가 존재합니다.
  • POST는 안전한 메소드는 아닙니다.
  • POST는 안전한 메소드가 아니기 때문에 멱등이 아닙니다.
  • POST는 응답 데이터기 존재합니다.
  • POST는 캐시가 가능하지만 사용하기는 어렵습니다.
  • POST는 GET과는 다르게 요청 Body의 데이터를 보낼 수 있습니다.
  • 요청 Body의 데이터를 보낼 수 있기 때문에 전송양에 길이 제한이 없으며 대용량 데이터를 보낼 수 있습니다.
  • POST는 HTML Form을 허용합니다.

PUT

등록된 책의 정보를 수정하려고 합니다. 여기서 책의 가격 정보를 나타내는 필드를 추가하여서 진행해보겠습니다.

다음과 같이 작성하여 요청하겠습니다.

PUT http://localhost:8080/book/6
Content-Type: application/json

{
  "name" : "스프링 부트와 AWS로 혼자 구현하는 웹 서비스",
  "price": 18000
}

응답 결과는 다음과 같습니다. PUT은 조회 대상 자원이 있고 요청한 정보가 성공적으로 수정이 된다면 200 (OK) 또는 204(No Content) 응답을 보내 성공을 알려줘야 합니다. 여기서는 새로 생성되었기 때문에 200 을 사용하였습니다.

HTTP/1.1 200 
Content-Length: 0
Date: Fri, 14 Jan 2022 16:11:19 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

Response code: 200; Time: 203ms; Content length: 0 bytes

PUT은 안전한 메소드는 아니지만 멱등성을 가지고 있습니다. 한 번을 보내도, 여러 번을 연속으로 보내도 응답 결과는 같습니다.

7번의 책 정보를 등록을 하려고 합니다. 다음과 같이 작성하여 요청하겠습니다. 7번은 현재 등록된 정보가 없습니다.

PUT http://localhost:8080/book/7
Content-Type: application/json

{
  "name" : "스프링 부트와 AWS로 혼자 구현하는 웹 서비스",
  "price": 18000
}

응답은 다음과 같습니다.

HTTP/1.1 201 
Location: /book/6
Content-Length: 0
Date: Fri, 14 Jan 2022 17:02:10 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

Response code: 201; Time: 391ms; Content length: 0 bytes

PUT은 대상 자원이 존재하지 않고 요청한 정보가 성공적으로 생성을 한 경우, 201 (Created) 응답을 보내야 합니다.

정리

  • PUT은 요청 Body가 존재합니다.
  • PUT은 응답 Body가 존재할수도 있고 존재하지 않을수도 있습니다.
  • PUT은 요청한 대상 자원이 존재한다면 정보를 수정할 수 있습니다.
  • PUT은 요청한 대상 정보가 완전히 대체됩니다.
    • 파일이 존재할때 덮어쓰는것과 파일이 존재하지 않을 때 새롭게 생성하는 것과 비슷한 원리입니다.
  • PUT은 요청한 대상 자원이 존재하지 않는다면 새로운 정보를 생성할 수 있습니다.
  • PUT은 안전한 메소드가 아닙니다.
  • PUT은 멱등성을 보장받습니다.
  • 요청 Body의 데이터를 보낼 수 있기 때문에 전송양에 길이 제한이 없으며 대용량 데이터를 보낼 수 있습니다.
  • PUT은 캐시 대상이 아닙니다.
  • PUT은 클라이언트가 리소스 위치를 알고 URI를 지정합니다.
  • PUT은 HTML Form을 허용하지 않습니다.

PATCH

등록된 책의 가격이 변동되어서 가격만 수정하려고 합니다. 다음과 같이 작성하여 요청하겠습니다.

PATCH http://localhost:8080/book/6
Content-Type: application/json

{
  "price" : "40000"
}

응답은 다음과 같습니다.

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 17:24:17 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "id": 5,
  "name": "리팩토링 2탄",
  "price": 40000
}

Response code: 200; Time: 185ms; Content length: 39 bytes

PATCH의 응답 상태는 2xx 상태 코드를 통해서 확인할 수 있습니다.

PATCH은 API를 구현하는 방식의 따라서 PUT처럼 멱등성을 보장받을 수 있고 보장받지 않을 수도 있습니다.

실제 현업에서 어떤 부분까지 사용하는지 궁금합니다. 댓글로 알려주신다면 감사하겠습니다.

정리

  • PATCH는 요청 Body가 존재합니다.
  • PATCH는 응답 Body가 존재합니다.
  • PATCH는 안전하지 않은 메소드입니다.
  • PATCH는 멱등성이 아닙니다.
    • 구현 방식의 따라서 멱등성을 보장받을 수 있습니다.
  • PATCH는 캐시 대상이 아닙니다.
  • PATCH는 HTML Form을 허용하지 않습니다.

DELETE

등록된 책 중 저자의 요청으로 인하여 삭제(?)를 해보도록 하겠습니다. 다음과 같이 작성하여 요청하겠습니다.

DELETE http://localhost:8080/book/5

응답은 다음과 같습니다.

HTTP/1.1 204 
Date: Fri, 14 Jan 2022 17:42:25 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

Response code: 204; Time: 304ms; Content length: 0 bytes

DELETE은 요청한 자원을 삭제하고 No Content 를 응답으로 전달합니다.

정리

  • DELETE는 요청 Body가 존재할 수 있습니다.
  • DELETE는 응답 Body가 존재할 수 있습니다.
  • DELETE는 안전하지 않은 메소드입니다.
  • DELETE는 멱등성을 보장합니다.
  • DELETE는 캐시 가능하지 않습니다.
  • DELETE는 HTML Form을 허용하지 않습니다.

CONNECT

요청한 자원에 대해 양방향 연결을 시작하는 메소드입니다.

정리

  • CONNECT는 요청 Body가 존재하지 않습니다.
  • CONNECT는 응답 Body가 존재합니다.
  • CONNECT는 안전하지 않은 메소드입니다.
  • CONNECT는 멱등성을 보장하지 않습니다.
  • CONNECT는 캐시 가능하지 않습니다.
  • CONNECT는 홉바이홉(hop by hop)입니다.
    • 데이터 통신망에서 각 패킷이 노드(또는 라우터)를 통해 전송되는 것을 비유적으로 표현한 것입니다.
  • CONNECT는 HTML Form을 허용하지 않습니다.

HEAD

특정 HTTP Method에 대해서 응답받을 헤더를 요청합니다.

다음과 같이 요청할 수 있습니다.

 HEAD http://localhost:8080/book/1

응답은 다음과 같습니다.

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 14 Jan 2022 17:51:54 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

Response code: 200; Time: 176ms; Content length: 0 bytes

응답 Body는 비어 있으며 응답 Header 정보가 담고 있습니다.

정리

  • HEAD는 요청 Body가 존재하지 않습니다.
  • HEAD는 응답 Body가 존재하지 않습니다.
  • HEAD는 안전한 메소드입니다.
  • HEAD는 멱등성을 보장합니다.
  • HEAD는 캐시 가능합니다.
  • HEAD는 HTML Form을 허용하지 않습니다.

OPTIONS

  • 자원의 대한 통신 옵션 정보를 확인하기 위해 사용됩니다.

다음과 같이 요청할 수 있습니다.

OPTIONS http://localhost:8080/book/1

응답은 다음과 같습니다.

HTTP/1.1 200 
Allow: DELETE,GET,HEAD,PUT,PATCH,OPTIONS
Accept-Patch: 
Content-Length: 0
Date: Fri, 14 Jan 2022 17:54:12 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

Response code: 200; Time: 191ms; Content length: 0 bytes

Allow 헤더를 통해서 허용되는 Method를 확인할 수 있습니다.

정리

  • OPTIONS는 요청 Body가 존재하지 않습니다.
  • OPTIONS는 응답 Body가 존재합니다.
  • OPTIONS는 안전한 메소드입니다.
  • OPTIONS는 멱등성을 보장합니다.
  • OPTIONS는 캐시 가능하지 않습니다.
  • OPTIONS는 HTML Form을 허용하지 않습니다.

TRACE

  • 목적 리소스의 경로를 따라 메시지 loop-back 테스트를 합니다.

정리

  • TRACE 요청 Body가 존재하지 않습니다.
  • TRACE 응답 Body가 존재하지 않습니다.
  • TRACE 안전한 메소드입니다.
  • TRACE 멱등성을 보장합니다.
  • TRACE 캐시 가능하지 않습니다.
  • TRACE는 HTML Form을 허용하지 않습니다.

마무리

  • HTTP는 클라이언트와 서버 간의 약속된 규칙을 말합니다.
  • HTTP Methods는 3가지 특성을 갖고 있습니다.
    • 안전한 메소드
    • 멱등성
    • 캐시 가능
  • HTTP Methods의 종류는 9개이며 자주 사용하는 5개(GET, POST, PUT, PATCH, DELETE)와 자주 사용하지 않는 4개(HEAD, OPTIONS, CONNECT, TRACE)로 나눌 수 있습니다.
  • 다음과 같이 표로 정리해보겠습니다.
  안전한 메소드 멱등성 캐시 가능 요청 Body 응답 Body
GET O O O X O
POST X X X O O
PUT X O X O X
PATCH X X X O O
DELETE X O X O X
HEAD O O O X X
OPTIONS O O X X O
CONNECT X X X X O
TRACE          
반응형

댓글