미분류

REST ful api 란 무엇인가 ( 스크랩 )

Machine_웅 2018. 8. 21. 22:58
728x90
반응형

, ,

조대협 님께서 블로그에 개제 해주신 내용을 보고 정리하였습니다. 


출처 : http://bcho.tistory.com/953

 

http://joonyon.tistory.com/13




● API의 본질은 무엇인가 -> Decoupling, 탈 동조화


● 그렇다면 Web API의 본질은 무엇인가 -> Decoupling + Platform Agnostic


Platform Agnostic 이란? 


   플랫폼에 종속적이 않음을 뜻한다. 즉, 특정 기기나 OS에서만 돌아가는 것이 아닌 광범위하게 사용될 수 있는 것.

   ex) 데이터 파일(텍스트파일, 그래픽 파일, 음원파일)은 윈도우든 OS X 든 안드로인드든 어디에서도 잘 돌아가니까.




● REST의 역사


웹(HTTP)의 창시자 중의 한사람인 Roy Fielding의 2000년 논문에서 소개.


" 현재 아키텍쳐가 웹의 본래 설계의 우수성을 많이 사용하지 못하고 있다고 판단했기 때문에, 


웹의 장점을 최대한 활용할 수 있는 네트워크 기반의 아키텍처를 소개한 것이 Representational state transfer(REST) 이다.



● REST의 기본


REST의 요소는 크게 리소스 // 메서드 // 메세지로 구성.


예로 "이름이 Terry인 사용자를 생성한다" 라는 호출이 있다면, "사용자"는 생성되는 리소스, "생성한다"라는 행위는 메서드

그리고 "이름이 Terry인 사용자"는 메시지가 된다.


이를 REST의 형태로 표현한다면, 


HTTP POST, http://myweb/users/

{

"users":{

"name":"terry"

}

}

 


와 같은 형태로 표현.


"생성한다"라는 행위의 의미를 갖는 메서드는 HTTP Post 메서드가 되고, 


생성하고자 하는 대상이 되는 "사용자" 라는 리소스는 http://myweb/users 라는 형태의 URI로 표현이 되며,


생성하고자 하는 사용자의 디테일한 내용은 JSON 문서를 이용해서 표현된다.




● HTTP 메서드


REST에서는 앞의 언급과 같이, 행위에 대한 메서드를 "HTTP 메서드" 그대로 사용한다.


HTTP 에는 여러가지 메서드가 있지만 REST에서는 CRUD(Create Read Update Delete)에 해당하는 4가지 메서드만 사용한다.


메서드 

의미 

Idempotent 

POST 

Create 

No 

GET

Select 

Yes 

PUT

Update 

Yes 

DELETE

Delete 

Yes 



각각 POST, GET, PUT, DELETE는 각각의 CRUD 메서드에 대응된다. 


여기에 Idempotent라는 분류를 추가하였는데, Idempotent는 여러번 수행을 해도 결과가 같은 경우를 의미한다.


예를 들어 a++은 Idempotent 하지 않다고 하지만(호출시 마다 a값이 증가 되기 때문), 


a=4와 같은 명령은 반복적으로 수행해도 Idempotent하다고 한다.(a=4는 값이 고정된 명령이기 때문)


POST 메서드의 경우에는 리소스를 추가하는 연산이기 때문에 idempotent 하지 않지만 


나머지 GET, PUT, DELETE 메서드는 반복 수행해도 Idempotent 하다.


따라서 GET의 경우 게시물의 조회수 카운트를 늘려준다던가 하는 기능을 같이 수행했을 때는 


Idempotent 하지 않은 메서드로 정의해야 한다.



※ Idempotent의 개념을 설명한 이유는 REST는 각 개별 API를 상태 없이 수행하게 됩니다. 

   따라서 해당 REST API를 다른 API와 함께 호출하다가 실패하였을 경우, 트렌젝션 복구를 위해서 다시 실행해야 하는 경우가 있는데, 

   Idempotent 하지 않은 메서드들의 경우는 기존 상태를 저장 했다가 다시 복원해줘야하는 문제가 있지만, Idempotent한 메서드의 경우에는 

   반복적으로 다시 메서드를 수행해주면 됩니다.

   예를 들어 게시물 조회를 하는 API가 있을때, 조회시 마다 조회수를 올리는 연산을 수행한다면 이 메서드는 Idempotent 하다고 볼 수 없고, 

   조회하다가 실패하였을 때는 올라간 조회수를 다시 -1 만큼 빼줘야 합니다. 

   즉 Idempotent 하지 않은 메서드에 대해서는 트렌젝션에 대한 처리에 특히 주의가 필요합니다.




● REST의 리소스


REST는 리소스 지향 아키텍쳐 스타일이라는 정의 답게 모든 것을 리소스, 즉 명사로 표현을 하며 각 세부 리소스에는 ID를 붙인다.


사용자라는 리소스 타입을 http://myweb/users 라고 정의 했다면, terry라는 id를 갖는 리소스는


http://myweb/users/terry 라는 형태로 정의한다.


REST의 리소스가 명사의 형태를 띄우다 보니, 명령(Operation)성의 API를 정의하는 것에서 혼동이 올 수 있다.


예를 들어 "Push 메시지를 보낸다"는 보통 기존의 RPC(Remote Procedure Call)나 함수성 접근에서는 


/myweb/sendpush 형태로 잘못 정의가 될 수 있지만, 이러한 동사형을 명사형으로 바꿔서 적용해보면


리소스 형태로 표현하기가 조금 더 수월해 진다.


"Push 메시지 요청을 생성한다."라는 형태로 정의를 변경하면, API 포맷은 POST/myweb/push 형태와 같이


명사형으로 정의가 될 수 있다. 


물론 모든 형태의 명령이 이런 형태로 정의가 가능한 것은 아니지만, 되도록이면 리소스 기반의 명사 형태로


정의를 하는게 REST 형태의 디자인이 된다.


☞ REST API의 간단한 예제


사용자 생성


다음은 http://myweb/users 라는 리소스를 이름은 terry, 주소는 seoul 이라는 내용(메시지)으로 HTTP POTS를 이용해서

생성하는 정의이다.


           HTTP POST, http://myweb/users/

          {

          "name":"terry"
          "addreses":"seoul"

          } 


- 조회 -

다음은 생성된 리소스중에서 http://myweb/users 라는 사용자 리소스 중에 id가 terry인 사용자 정보를 조회해오는 방식이다.
조회이기 때문에 HTTP GET을 사용한다.

           HTTP GET, http://myweb/users/terry



- 업데이트 -

다음은 http://myweb/users 라는 사용자 리소스중에, id가 terry인 사용자 정보에 대해서, 주소를 "suwon"으로 수정하는 방식이다.
수정은 HTTP PUT 메서드를 사용한다.

HTTP PUT, http://mtweb/users/terry
{
"name":"terry"
"address":"suwon"
}



- 삭제 -

마지막으로 http://myweb/user 라는 사용자 리소스 중에, id가 terry인 사용자 정보를 삭제하는 방법이다.

            HTTP DELETE, http://myweb/users/terry



            API의 정의를 보면 상당히 간단하다. 단순하게 리소스를 URI로 정해준 후에, 거기에 HTTP 메서드를 이용해서 
CRUD를 구현하고 메시지를 JSON으로 표현하여 HTTP Body에 실어 보내면 된다. POST URI에 리소스 id가 없다는
것을 빼면 크게 신경쓸 부분이 없다.



● REST의 특성


◎ 유니폼 인터페이스(Uniform Interface)


REST는 HTTP 표준에만 따른다면, 어떠한 기술이라던지 사용이 가능한 인터페이스 스타일이다. 


예를 들어 HTTP + JSON으로 REST API를 정의했다면, 안드로이드 플랫폼이건, IOS 플랫폼이건, 


또는 C나 Java / Python 이건 특정 언어나 기술에 종속 받지 않고 HTTP와 JSON을 사용할 수 있는


모든 플랫폼에 사용이 가능한 느슨한 결합(Loosely Coupling) 형태의 구조이다.


※ 흔히들 근래에 REST를 이야기하면, HTTP + JSON을 쉽게 떠올리는데, JSON은 하나의 옵션일뿐, 메시지 포맷을 

   꼭 JSON으로 적용해야할 필요는 없다. 자바스크립트가 유행하기전에만 해도 XML 형태를 많이 사용했으며, 근래에

   들어서 사용의 편리성 때문에 JSON을 많이 사용하고 있지만, XML을 사용할 경우, XPath, XSL 등 다양한 XML 프레임웍을

   사용할 수 있을뿐만 아니라 메시지 구조를 명시적으로 정의할 수 있는 XML Scheme나 DTD등을 사용할 수 있기 때문에,

   복잡도는 올라가더라도, 메시지 정의의 명확성을 더할 수 있다.



◎ 무상태성/스테이트리스(Stateless)


REST는 Representational State Transfer의 약어로 Stateless(상태를 유지하지 않음)이 특징 중의 하나이다.

상태가 있다, 없다의 의미는 사용자나 클라이언트의 컨택스트를 서버쪽에 유지 하지 않는다는 의미로,

쉽게 표현하면 HTTP Session과 같은 컨텍스트 저장소에 상태 정보를 저장하지 않는 형태를 의미한다.

상태 정보를 저장하지 않으면 각 API 서버는 들어오는 요청만을 들어오는 메시지로만 처리하면 되며, 

세션과 같은 컨텍스트 정보를 신경쓸 필요가 없기 떄문에 구현이 단순해 진다.


◎ 캐싱 가능(Cacheable)


REST의 큰 특징 중의 하나는 HTTP라는 기존의 웹 표준을 그대로 사용하기 때문에, 


웹에서 사용하는 기존의 인프라를 그대로 활용이 가능하다.


HTTP 프로토콜 기반의 로드 밸러서나 SSL은 물론이고, HTTP가 가진 가장 강력한 특징중에 하나인 


캐싱 기능을 적용할 수 있다. 일반적인 서비스 시스템에서 60%에서 많게는 80% 가량의 트랜잭션이 Select와 같은 


조회성 트랜잭션인 것을 감안하면, HTTP의 리소스들을 웹캐시 서버등에 캐싱하는 것은 


용량이나 성능 면에서 많은 장점을 가지고 올 수 있다. 구현은 HTTP 프로토콜 표준에서 사용하는


"Last-Modified" 태그나 E-Tag를 이용하면 캐싱을 구현할 수 있다.


아래와 같이 Client가 HTTP GET을 "Last-Modified" 값과 함께 보냈을 때, 컨텐츠가 변화가 없으면 REST 컴포넌트는


"304 Not Modified"를 리턴하면 Client는 자체 캐쉬에 저장된 값을 사용하게 된다.


그림 1. Last-Modified 필드를 이용한 캐싱 처리 방식



이렇게 캐시를 사용하게 되면 네트워크 응답시간 뿐만 아니라, REST 컴포넌트가 위치한 서버에 트랜잭션을 


발생시키지 않기 때문에, 전체 응답시간과 성능 그리고 서버의 자원 사용률을 비약적으로 향상시킬 수 있다.




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


REST의 가장 큰 특징 중의 하나는 REST API 자체가 매우 쉬워서 API 메시지 자체만 보고도 API를 이해할 수 있는 


Self-descriptiveness 구조를 갖는 다는 것이다. 리소스와 메서드를 이용해서 어떤 메서드에 무슨 행위를 하는지를 알 수 있으며,


또한 메시지 포맷 역시 JSON을 이용해서 직관적으로 이해가 가능한 구조이다.


대부분의 REST 기반의 OPEN API 들이 API 문서를 별도로 제공하고 있지만, 디자인 사상은 최소한의 문서의 도움만으로도 


API 자체를 이해할 수 있어야 한다.




◎ 클라이언트 서버 구조(Client-Server 구조)


근래에 들면서 재 정립되고 있는 특징 중의 하나는 REST가 클라이언트 서버 구조라는 것이다.


REST 서버는 API를 제공하고, 제공된 API를 이용해서 비즈니스 로직 처리 및 저장을 책임진다.


클라이언트의 경우 사용자 인증이나 컨택스트(세션, 로그인 정보)등을 직접 관리하고 책임 지는 구조로 역할이 나뉘어 지고 있다.


이렇게 역할이 각각 확실하게 구분되면서, 개발 관점에서 클라이언트와 서버에서 개발해야 할 내용들이 명확하게 되고 


서로의 개발에 있어서 의존성이 줄어들게 된다.




◎ 계층형 구조(Layered System)


계층형 아키텍쳐 구조 역시 근래에 들어서 주목받기 시작하는 구조인데, 클라이언트 입장에서는 REST API 서버만 호출한다.


그러나 서버는 다중 계층으로 구성될 수 있다. 순수 비즈니스 로직을 수행하는 API 서버와 그 앞단에 사용자 인증(Authentication),


암호화(SSL), 로드밸런싱 등을 하는 계층을 추가해서 구조상의 유연성을 둘 수 있는데, 


이는 근래에 들어서 앞에서 언급한 마이크로 서비스 아키텍쳐의 API Gateway나 간단한 기능의 경우에는 HA Proxy나


Apache와 같은 Reverse Proxy를 이용해서 구현하는 경우가 많다.





● REST 안티 패턴


REST 디자인시 하지 말아야 할 안티 패턴에 대한 내용이다.



◎ GET/POST를 이용한 터널링


가장 나쁜 디자인 중 하나가 GET이나 POST를 이용한 터널링이다.


http://myweb/users?method=update&id=terry 이 경우가 전형적인 GET을 이용한 터널링이다.


메서드의 실제 동작은 리소르르 업데이트 하는 내용인데, HTTP PUT을 사용하지 않고, 


GET에 쿼리 파라미터로 method=update라고 넘겨서, 이 메서드가 수정 메서드임을 명시했다.


대단히 안좋은 디자인인데, HTTP 메서드 사상을 따르지 않았기 때문에, REST라고 부를 수 도 없고,


또한 웹 캐시 인프라 등도 사용이 불가능하다.


또 많이 사용하는 안좋은 예는 POST를 이용한 터널링이다. Insert(Create)성 오퍼레이션이 아닌데도 불구하고,


JSON 바디에 오퍼레이션 명을 넘기는 형태인데 예를 들어 사용자 정보를 가지고 오는 API를 아래와 같이 


POST를 이용해서 만든 경우이다. 


HTTP POST, http://myweb/users/
{

"getuser":{

"id":"terry",

}

}



◎ Self-descriptiveness 속성을 사용하지 않음


앞서 특징에서 설명한 바와 같이 REST의 특성 중 하나는 자기 서술성(Self-descriptiveness) 속성으로 REST URI와


메서드 그리고 쉽게 정의된 메시지 포맷에 의해서 쉽게 API를 이해할 수 있는 기능이 되어야 한다.


특히나 자기 서술성을 깨먹는 대표적인 사례가 위에서 언급한 GET이나 POST를 이용한 터널링을 이용한 구조가 된다.



◎ HTTP Response code를 사용하지 않음


다음으로 많이 하는 실수 중의 하나가 HTTP Response code를 충실하게 따르지 않고, 성공은 200, 실패는 500과 같이 


1~2개의 HTTP Response code만을 사용하는 경우이다. 심한 경우에는 에러도 HTTP Response code 200으로 정의한 후


별도의 에러 메시지를 200 response code와 함께 보내는 경우인데, 이는 REST 디자인 사상에도 어긋남은 물론이고


자기 서술성에도 어긋난다.

728x90
반응형

'미분류' 카테고리의 다른 글

오픈 소스 모음  (0) 2019.04.24
UI vs UX  (0) 2018.10.15
aws mysql 연동  (0) 2018.07.13
(스크랩)윈도우에서 Atom 에디터(Editor)로 아마존(AWS) 리눅스 서버에 연결(접속)하기  (0) 2018.07.04
NDK VS Cmake??  (0) 2018.06.27