하루에 한 문제

REST, REST API, RESTful 본문

카테고리 없음

REST, REST API, RESTful

dkwjdi 2021. 5. 27. 22:49

REST란?

웹은 명확하게 클라이언트 서버로 구분되어 있습니다. 클라이언트에서 서버로 요청을 보내고, 서버는 클라이언트에 응답을 보내줍니다. REST API를 사용하는 웹앱은 URI(주소)를 통하여 서버에 요청을 보냅니다. 서버는 html, xml, json 등으로 응답합니다.

  • Representational State Ttansfer의 약자로 웹의 장점을 최대한 활용할 수 있는 Clien, Server 간 통신 방식중 하나이다.
  • 설계 기본 규칙으로 HTTP URL를 통해 자원을 명시하고 HTTP method(GET,POST,PUT,DELETE)를 통해 자원을 처리하도록 설계된 아키텍쳐이다.
  • RESTful은 REST라는 아키텍쳐를 구현하는 웹 서비스를 나타내는 것으로 REST 원리를 따르는 시스템을 RESTful이라는 용어로 지칭한다.

Idempotent

HTTP 메소드에는 idempotent라는 개념이 있습니다. 반복해도 결과가 같은 경우 idempotent 하다고 표현합니다. POST를 제외한 나머지 메소드는 idempotent합니다. 100번을 조회해도 결과는 항상 같고, 100번을 수정하고 삭제해도 결과는 마지막 한 번 한 것과 결과는 같습니다. 다만 POST 요청을 할 때는 계속 새로운 문서가 생기기 때문에 결과가 다릅니다. POST 100번을 하면 100개의 문서가 생기죠. 

 

Idempotent 개념이 왜 중요하냐면, 에러가 발생해서 실행이 되지 않거나, 복구가 필요한 경우 때문입니다. Idempotent한 메소드들은 실행이 되지 않을 경우에는 한 번 더 실행하면 되고, 복구가 필요한 경우에는 해당 요청만 취소하면 되지만, 그렇지 않은 POST 메소드는 복구할 때 더 각별한 주의가 필요합니다.

 

REST 구성요소

1. 자원(Resource): URL

  • 모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다
  • 자원을 구별하는 ID는 '/groups/:group_id' 와 같은 HTTP URL이다.
  • 클라이언트는  URL를 이용해서 자원을 지정하고 해당 자원의 상태(정보(에 대한 조작을 Server에 요청한다

2. 행위(Verb): HTTP Method

  • HTTP프로토콜의 Method를 사용한다
  • GET, POST, PUT, DELETE와 같은 메서드를 제공한다

3. 표현(Representation of Resource)

  • 클라이언트가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답을 보낸다
  • REST에서 하나의 자원은 JSON,XML,TEXT,RSS등 여러 형태의 Representation으로 나타내어 질 수 있다.
  • JSON 혹은 XML를 통해 데이터를 주고 받는 것이 일반적이다.

 

REST API 장점

  • 체계적이라 관리하기가 쉽다.
  • 주소만 봐도 무슨 내용인지 이해할 수 있다.
  • 서버를 REST API로 만들어 놓으면 언어에 상관없이 HTTP를 사용하는 다양한 플랫폼에서 동시에 사용할 수 있다.
  • 캐싱이 가능하다 (GET 요청 같은 경우 응답 시 캐싱으로 더 빨리 로딩)

REST API 주의점

REST API는 무조건 따라해야 하는것이 아니라 하나의 구조입니다.

다만 사용하기로 했다면 몇가지를 주의해서 사용해야 합니다.

1. 잘 이해가지 않는 주소 사용

/Zero/Nero 와 같은 주소는 봤을 때 뭘 하라는 요청인지 알 수가 없습니다.

최대한 주소는 명사 단위로 이해할 수 있게 만들어야 합니다.

2.HTTP 메소드 잘못 사용

GET메소드를 사용해 티스토리 포스트를 불러오면서 동시에 조회수를 1 올린다면 이는 REST에 어긋난 것입니다.

PUT을 통해 조회수를 관리하는 메소드를 한번, GET을 통해 포스트를 요청하는 메소드를 한번 요청 하는것이 올바른 사용법입니다.

 

 

 

자 이까지가 우리가 흔히 알고있는 REST이다. 이제 조금 다른 얘기를 해보자.

 

REST API란 REST아키텍쳐 스타일을 따르는 API라는 의미다

그렇다면 REST는 뭘까

REST는 분산 하이퍼미디어 시스템(예:웹)을 위한 아키텍쳐 스타일이다.

그렇다면 또 아키텍쳐 스타일은 뭔가???

아키텍쳐 스타일은 제약조건의 집합이다.

그렇다면 이 제약조건에는 뭐가 있을까?

1.client-server

2.stateless

3.cache

4.uniform interface

5.layerd system

6.code-ondemand(optional)

 

사실 1,2,3,5번은 HTTP만 잘따라도 지킬 수 있다.

6번의 의미는 서버에서 코드를 클라이언트로 보내서 실행할 수 있어야 된다는 의미인데 이는 자바스크립트를 의미한다.

 

그런데 이중에 uniform interface라는 제약조건을 잘 지키지 못한다.

uniform interface는 4가지 제약조건으로 이루어져 있다.

1.identification of resources -> 리소스가 URI로 식별되면 된다.

2.manipulation of resources through representations -> 리소스를 만들거나 삭제하거나 업데이트할때 메세지에다 표현을 담아서 전송한다.

3. self-descriptive messages -> 메세지는 스스로를 설명해야 한다(메세지만 보고도 해석이 가능해야 한다.)

4. hypermedia as the engine of application state(HATEOAS) (어플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다)

 

이중 3,4번은 자칭 REST API라고 불리는 모든 사이트에서 지켜지지 않고 있다.

 

self-descriptive messages

GET / HTTP/1.1

위으 코드는 루트를 얻어오는 단순한 GET메서드이다.

그런데 이 HTTP요청 메세지에는 무엇인가 빠져있기 때문에 self-descriptive하지 못하다 

GET / HTTP/1.1
Host: www.example.org

그렇다 어디로 간다는 목적지가 없다. Host를 추가해줌으로써 self-descriptive를 만족시킬 수 있다.

 

하나의 예를 더 보자

HTTP/1.1 200 OK
[ { "op" : "remove", "path" : "a/b/c" } ]

위의 HTTP응답 메세지 또한  self-descriptive하지 않다. 왜일까?

클라이언트입장에서 보자 이런 응답메세지를 받았을 때 어떤 문법인지 알 수 없기 떄문에 해석할 수가 없다.

HTTP/1.1 200 OK
Content-Type: application/json
[ { "op" : "remove", "path" : "a/b/c" } ]

자 위의 문제를 해결해주기 위해 Content-Type을 통해 명시를 해주었다.

그렇다면 self-descriptive을 만족하게 된걸까?? 아니다.. 왜 또 아닐까

자 저 문법이 json이란걸 알고 파싱까지 했다. 하지만 op가 무얼 뜻하는지, path가 무얼 뜻하는지 알수가 없다.

HTTP/1.1 200 OK
Content-Type: application/json-patch+json
[ { "op" : "remove", "path" : "a/b/c" } ]

위으 코드처럼 해주어야 self-descriptive하다가 할 수 있다. json-patch라는 명세를 찾아가서 이를 이해하고 메세지를 해석하면 올바른 내용을 알 수 있다.

 

HATEOAS

HTTP/1.1 200 OK
Content-Type : text/html

<html>
<head></head>
<body><a href="/test">test</a></body>
</html>

위의 코드 처럼 하이퍼링크를 통해서 다음 상태로 전이가 된다면 HATEOAS를 만족하고 있는것이다. 

 

HTTP/1.1 200 OK
Content-Type : application/json
Link: </articles/1>; rel="previous",
      </articles/3>; rel="next";
{
	"title": "The Second Article",
    "contents" : "blah blah..."
}

json으로 표현해도 만족할 수 있는 방법이 있다. link라는 헤더가 있는데 메세지의 리소스와 연결되어 있는 다른리소스를 가르킬 수 있는 헤더이다.

이전 게시물의 url가 /articles/1 이고 이 다음 게시물의 url이 /articles/3 이라고 알려주었다.

link헤더는 표준이기 때문에 이것을 해석하는 사람이 해석가능하다.

따라서 HATEOAS를 만족한다!

 

 

근데 도대체 왜 uniform interface가 필요할까

바로 독립적 진화를 하기 위함이다.

서버와 클라이언트가 각각 독립적으로 진화한다.

서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.

 

 

 

우리가 사용하는 "웹"은 REST가 아주 잘 지켜지고 있다.

웹 페이지를 변경했다고 해서 웹 브라우저를 업데이트할 필요 없다.

웹 브라우저를 업데이트했다고 웹 페이지를 변경할 필요도 없다.

HTTP 명세가 변경되어도 웹은 잘 동작한다.

HTML 명세가 변경되어도 웹은 잘 동작한다.

 

 

그런데 "앱"은 REST가 잘 지켜지지 않고 있다.

구글플레이스토어나 앱스토어에서 리뷰를 살펴보면 업데이트를 너무 많이 한다 라는 글을 본 적이 있을것이다.

이는 다시 말하자면 모바일 앱은 클라이언트와 서버간의 통신이 REST로 이루어지지 않고 있다는 뜻이다. 

 

그렇다면 REST가 웹의 독립적 진화에 도움을 주었을까???

답은 그렇다

HTTP에 지속적으로 영향을 주었다. -> Host헤더 추가

 

이어서...

참고

github.com/WooVictory/Ready-For-Tech-Interview/blob/master/Network/REST%20%26%20RESTful.md

gmlwjd9405.github.io/2018/09/21/rest-and-restful.html

www.zerocho.com/category/NodeJS/post/579b3fc4062e76a002648af6

Comments