[네트워크/Network] REST API와 HTTP 메서드(GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH)

kindof

·

2021. 10. 28. 13:05

1. Rest API, Restful API 정의

REST는 REpresentational State Transfer라는 용어의 약자로, 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한 사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표했다고 합니다.

 

조금 더 현실적인 관점에서 REST API를 정의하자면, REST API는 웹 상에서 사용되는 여러 리소스를HTTP URI로 표현하고 해당 리소스에 대한 행위를 HTTP Method로 정의하는 방식을 말합니다. 그리고 RESTful API는 REST API 설계 가이드를 따라 API를 만드는을 말하며, REST API 설계 가이드에 따라 API를 만들어서 웹 서비스를 제공하면 해당 웹 서비스는 'RESTful하다'고 합니다.

 

REST API

 

이번 글에서는 REST API가 어떤 특징을 가지며, 어떻게 디자인되는지를 들여다보겠습니다.

 

 

2. REST의 특징

1) Uniform (유니폼 인터페이스)

Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다. 즉, 요청을 하는 Client가 플랫폼(Android, Ios, Jsp 등) 에 무관하며, 특정 언어나 기술에 종속받지 않는 특징을 의미합니다. 이러한 특징 덕분에 Rest API는 HTTP를 사용하는 모든 플랫폼에서 요청가능합니다.

2) Stateless (무상태성)

REST는 무상태성 성격을 갖습니다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않습니다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 됩니다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해집니다.

3) Cacheable (캐시 가능)

REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능합니다. 따라서 HTTP가 가진 캐싱 기능이 적용 가능합니다. HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능합니다.

4) Self-descriptiveness (자체 표현 구조)

REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것입니다.

5) Client - Server 구조

REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 됩니다.

6) 계층형 구조

REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 합니다.

 

 

3. REST 구성과 디자인 규약

REST API는 크게 자원(Resource), 행위(Verb), 표현(Representations)로 이루어져 있으며, 자원이란 URL을 의미하고 행위란 HTTP의 POST, GET, PUT, DELETE와 같은 메서드를 의미합니다.

 

POST POST를 통해 해당 URI를 요청하면 리소스를 생성합니다.
GET GET를 통해 해당 리소스를 조회합니다. 
PUT PUT를 통해 해당 리소스를 수정합니다.
DELETE DELETE를 통해 리소스를 삭제합니다.

각 메서드에 대한 자세한 설명은 좀 더 아래에서 다루겠습니다.

 

한편, REST API를 디자인할 때는 일반적으로 다음의 규칙들을 지켜야 하는데요.

  • 첫째, URL은 정보의 자원을 표현해야 합니다. 행위를 URL에 포함해서는 안됩니다.
  • 둘째, 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현합니다.
  • 셋째, 소문자를 사용합니다.
  • 넷째, URL의 마지막은 '/' 를 포함해서는 안 됩니다.
  • 다섯째, '_' 대신에 '-'를 사용합니다.

 

위 규칙을 제대로 따르지 않고 API를 설계하면, Restful하지 못하다는 뜻이겠죠? 그럼, 몇 가지 예시를 살펴보면서 위의 규칙들을 적용해보겠습니다. 

 

 

[1] 마지막에 '/' 를 포함하지 않습니다.

(1) http://api.test.com/users/ (O)
(2) http://api.test.com/users  (X)

 

[2] '_' 대신에 '-'를 사용합니다.

(1) http://api.test.com/users/post-comments  (O)
(2) http://api.test.com/users/post_comments  (X)

 

[3] 소문자를 사용합니다.

(1) http://api.test.com/users/post-comments (O)
(2) http://api.test.com/users/postComments  (X)

 

[4] 행위는 URL에 포함하지 않습니다.

(1) DELETE http://api.test.com/users/1/posts/1        (O)
(2) POST http://api.test.com/user/1/delete-post/1     (X)

 

 

 

4. HTTP Method

위에서 잠깐 HTTP의 네 가지 메서드에 대해 살펴봤는데요. REST API의 중요한 규칙 중 하나가 자원에 대한 행위를 HTTP 메서드로 정의하는 것이기 때문에 HTTP 메서드를 정확히 이해하는 것은 RESTful API를 설계하는 데 필수적인 요소가 됩니다.

 

그렇다면 HTTP Request Method에는 Post, Get, Put, Delete만 존재할까요? 그렇지 않습니다. HTTP 메서드에는 OPTIONS, HEAD, PATCH와 같은 메서드도 존재하는데요. 

 

이제 각 메서드에 대한 설명을 조금 더 깊게 해보겠습니다.

 

4-1) GET

GET은 서버로부터 정보를 조회하기 위해 설계된 메서드입니다. 위에서 말씀드렸듯이 GET은 요청을 전송할 때 필요한 데이터를 Body 대신 Header에 담고 URL의 끝에 ?와 함께 이를 값으로 하는 쿼리 파라미터를 전달하죠. Header에 데이터를 담아서 보낸다는 뜻은 데이터의 크기가 한정되어 있다는 것이고 그러면 전송 속도가 크게 느려질 일은 없겠죠?

 

또한 GET은 불필요한 요청을 제한하기 위해 캐시 기능을 적극적으로 이용합니다. html, css, js같은 정적 컨텐츠는 무거울 수 있지만 화면에서 변경될 일이 적기 때문에 동일한 요청을 계속해서 보내고 그 요청에 일일이 대답할 필요가 없죠. 있었던 그대로 보여주면 되니까요.

 

따라서 GET은 Idempotent(멱등)하다고 합니다. 즉, 동일한 연산을 여러 번 수행하더라도 동일한 결과가 나타난다는 것이죠.

 

GET은 서버에게 동일한 요청을 백 번, 천 번 보내도 동일한 응답이 돌아와야 합니다. 이에 따라 GET은 설계원칙에 따라 서버의 데이터나 상태를 변경시키지 않는 조회 기능에 많이 이용됩니다.

 

4-2) POST

POST는 리소스를 생성/변경하기 위해 설계된 메서드입니다. HTTP 메시지의 Body는 길이의 제한없이 데이터를 전송할 수 있기 때문에 POST 요청은 GET과 달리 대용량 데이터를 전송할 수 있죠. 하지만 이 말을 반대로 해석하면, 데이터가 커지면 커질수록 GET보다는 요청 속도가 느려질 수 있겠죠?

 

한편, POST는 Non-idempotent합니다. 즉, 서버에게 동일한 요청을 여러 번 전송해도 응답은 항상 다를 수 있기 때문에 멱등하지 않다는 것이죠.

 

예를 들어, POST 요청으로 유저 한명을 생성한다고 해보겠습니다.

Http 요청
POST /user
{
  “name”: “Sunghyeon”,
  “grade”: 1
}


Http 응답
HTTP/1.1 200 OK
{
  “id”: 1,
  “name”: “뽀로로”,
  “grade”: 1
}

 

그런데 POST 요청을 두 번 보내면 어떻게 될까요?

POST /user
{
   “name”: “sunghyeon”,
   “grade”: 1
}

POST /user
{
   “name”: “sunghyeon”,
   “grade”: 1
}

POST를 두 번 보내면 서로 다른 두 응답이 돌아옵니다. 즉, 'sunghyeon'이라는 이름을 가진 자원 두 개가 생성되는 것이죠. 이것이 바로 위에서 말한 멱등하지 않은 상황을 의미합니다.

HTTP/1.1 200 OK
{ “id”: 1, “name”: “sunghyeon”, “grade”: 1 }

HTTP/1.1 200 OK
{ “id”: 2, “name”: “sunghyeon”, “grade”: 1}

 

4-3) PUT

PUT 메서드는 기본적으로 자원의 업데이트(수정)을 담당하는 메서드입니다. 위에서 생성한 유저의 이름을 "Ryan"으로 바꾸려면 아래와 같이 PUT 요청을 보낼 수 있습니다.

Http 요청
PUT /user/1
{
  “name”: 'Ryan'
}

Http 응답
HTTP/1.1 200 OK
{
  “id”: 1,
  “name”: “Ryan”,
  “grade”: 1
}

 

그런데 위의 동일한 PUT 요청을 두 번 보내게 되면 어떻게 될까요?

PUT /user/3
{
  “name”: ”Ryan”
  “grade”: 2
}

PUT /user/3
{
  “name”: ”Ryan”
  “grade”: 2
}

PUT 요청은 요청을 보낸 횟수와 관계없이 아래처럼 동일한 응답을 리턴합니다. 즉, PUT 메서드는 멱등하다는 것이죠.

HTTP/1.1 200 OK
{ “id”: ”3”, “name”: “Ryan”, “grade”: 2 }

 

 

4-4. OPTIONS

OPTIONS는 현재 End-point가 제공 가능한 API Method를 응답합니다. 아래와 같이 curl 형태의 요청을 서버에 보내면, 서버에서 사용할 수 있는 메서드를 확인할 수 있는 것이죠.

 

curl -X OPTIONS http://example.org -i

요청을 보내면 아래와 같이 'Allow' 헤더가 응답에 포함되어서 오고, 이 예제에서는 OPTIONS, GET, HEAD, POST가 사용가능한 메서드임을 알 수 있습니다.

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Expires: Thu, 20 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
x-ec-custom-error: 1
Content-Length: 0

 

4-5. HEAD

HEAD는 GET 요청과 동일한 역할을 하지만 요청에 대한 헤더 정보만 응답하는 메서드로 Body가 존재하지 않습니다. 다시 말해, HEAD 메서드는 특정 리소스를 GET메서드로 요청했을 때 돌아올 헤더를 요청하는 것이죠.

 

그래서 HEAD 메서드는 일반적으로 웹 서버의 다운 여부 점검이나 서버 정보 등을 얻기 위해 사용됩니다.

 

4-6. PATCH

PUT 메서드가 자원의 전체를 수정하는 데 반해, PATCH는 자원의 일부를 수정할 때 사용합니다. 만약 유저의 이름을 수정해야 하는 상황에서 PUT을 쓰게 되면 이름 이외의 값은 Default로 수정이 됩니다. 그래서 일반적으로 PUT을 사용할 때는 바뀌지 않는 속성의 값도 원래 값으로 입력해서 보내줘야 하죠. 

 

예를 들어 유저의 정보가 현재 {'age': 30, 'name': 'sunghyeon', 'vip':'true'}라면, name을 수정하기 위해서는 age, vip에 대한 내용도 함께 넣어주는 것이 안전하다는 것입니다.

 

반면, PATCH를 이용하게 되면 위와 같은 의무가 사라집니다. PATCH는 요청에 수정을 원하는 자원의 부분 데이터만 넣어도 되기 때문이죠. 즉, 위 예시에서 name을 수정하고 싶을 때 age, vip에 대한 고려는 하지 않아도 됩니다.

 


 

이렇게 이번 포스팅에서는 REST API가 무엇인지 알아보고, RESTful한 디자인 규약에 대해 공부했습니다. 그리고 이를 위해 반드시 알아야 하는 HTTP의 7가지 메서드(GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH)도 살펴봤습니다.

 

감사합니다.