네트워크/네트워크 정리
REST API의 이해와 설계
100win10
2020. 9. 7. 18:17
REST란?
- REST는 웹의 창시자 중 한 사람인 Roy Fielding의 2000년 논문에 의해 소개되었다.
- 현재의 아키텍처가 웹의 본래 설계의 우수성을 많이 사용하지 못하고 있다고 판단하였고
- 웹의 강점을 최대한 활용 가능한 네트워크 기반의 아키텍처를 소개했는데
- 그것이 바로 Representational safe transfer ( REST )이다.
REST의 기본
- REST 요소로는 크게 리소스, 메서드, 메시지 3가지 요소로 구성된다.
이름이 "Terry"인 사용자를 생성한다 라는 호출
HTTP POST http://myweb/users/ |
{ "users" : { "name" : "terry" } } |
- "사용자"는 생성되는 리소스
- "생성한다"라는 행위는 메서드
- "이름은 Terry인 사용자"라는 메시지가 된다.
- 이때 생성한다는 의미를 갖는 메서드는 HTTP POST 메서드가 되고
- 생성하고자 하는 대상이 되는 사용자라는 리소스는 http://myweb/users라는 URL로 표현이 되며
- 생성하고자 하는 사용자의 디테일한 내용은 JSON 문서를 이용하여 표현된다.
HTTP Method와 Idempotent
Method | 의미 | Idempotent |
POST | Create | No |
GET | Select | Yes |
PUT | Update | Yes |
DELETE | Delete | Yes |
HTTP Method는 Post, Put, Get, Delete로 각각의 CRUD 메서드에 대응된다.
여기에 Idempotent라는 분류를 추가할 수 있는데 이는 여러 번 수행해도 결과가 같은 경우를 의미한다.
Idempotent? a++는 Idempotent 하지 않다. 호출시 마다 값이 증가되기 때문이다. a = 4 와 같은 명령은 반복적으로 수행해도 Idempotent 하다. 값이 같기 때문이다. |
- POST 연산의 경우 리소스를 추가하는 연산이기에 Idempotent하지 않지만
- GET, PUT, DELETE는 대부분 반복 수행해도 Idempotent 하다.
- ex ) 물론 GET의 경우도 게시물의 카운트를 늘려주는 기능은 Idempotent하지 않다.
- Idempotent 개념이 중요한 이유는 REEST는 각 개별 API를 상태 없이 수행하게 된다.
- 따라서 해당 REST API가 다른 API와 함께 호출하다가 충돌되었을 경우 트랜잭션 복구를 위해 다시 실행돼야 한다.
- 이때 Idempotent하지 않다면 기존 상태를 저장했다가 다시 원복해야 하는 문제가 있지만
- Idempotent 한 메서드의 경우 반복적으로 다시 메서드를 수행해주면 된다.
REST의 리소스
- 기존의 Web Application이 서버 중심이었다면 REST는 리소스 중심이다.
- 리소스를 중심으로 설계하며 CRUD시 해당하는 HTTP 4가지 메서드(POST, GET, PUT, DELETE)를 이용한다.
-
추가적으로 Patch 메서드도 있다.
- REST는 리소스 지향 아키텍처 스타일이라는 정의답게 모든 것을 리소스 즉 명사로 표현하며 각 세부 리소스에는 Id를 붙인다.
- 즉 사용자는 리소스 타입을 http://myweb/users라고 정의했다면 terry라는 id를 갖는 리소스는 http://myweb/users/terry라는 형태로 정의한다.
REST의 특성
- 유니폼 인터페이스 ( Uniform Interface )
- REST는 HTTP 표준에만 따른다면, 어떤 기술이라던지 사용이 가능한 인터페이스 스타일이다.
- 가령 HTTP + JSON 형태로 REST API를 정의했다면, 안드로이드, IOS, C/JAVA/Python 등 특정 언어나 기술에 종속받지 않고
- HTTP와 JSON을 사용할 수 있는 모든 플랫폼에 사용이 가능한 느슨한 결합 형태의 구조이다.
- 무상 태성 ( 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는 자체 캐시에 저장된 값을 사용하게 된다.
- 자체 표현 구조 ( Self - Descriptiveness )
- REST의 가장 큰 특징 중 하나는 REST API 자체가 매우 쉬워 API 메시지만 보고 API를 이해할 수 있는 Self-Descriptiveness 구조를 갖는다는 것이다. '
- 리소스와 메서드를 이용하여 어떤 메서드에 무슨 행위를 하는지를 알 수 있으며, 메세지 포맷 역시 JSON을 통한 직관적인 이해가 가능한 구조이다.
- 대부분의 REST 기반 OPEN API 들이 API 문서를 별도로 제공하지만, 디자인 사상은 최소한의 문서의 도움만으로도 API 자체를 이해할 수 있어야 한다.
- 클라이언트 서버 구조 ( Clinet-Server 구조 )
- REST 서버는 API 를 제공하고, 제공된 API를 이용해서 비즈니스 로직 처리 및 저장을 책임진다.
- 클라이언트의 경우 사용자 인증이나 콘텍스트(세션, 로그인) 등을 직접 관리하고 책임지는 구조로 역할이 나누어지고 있다.
- 계층형 구조 ( Layered System ) 란 클라이언트 입장에서는 REST API 서버만 호출하지만 서버는 다중 계층으로 구성이 될 수 있다. 순수 비즈니스 로직을 수행하는 API 서버와 그 앞단에 사용자 인증 ( Authentication ) , 암호화 (SSL), 로드 밸런싱 등을 하는 계층을 추가해서 구조상의 유연성을 두는 것이다.
- 이는 근래에 들어 언급되는 마이크로 서비스 아키텍처의 api gateway나, 간단한 기능의 경우 HA Proxy나 Apache 같은 Reverse Proxy를 통해 구현하는 경우가 많다.
REST 안티 패턴
REST 디자인 시 하지 말아야 할 안티 패턴에 대해서 알아보자.
- GET/POST를 이용한 터널링
- http://myweb/users? method=update&id=terry 전형적인 GET을 이용한 터널링이다.
- 메서드의 실제 동작은 리소스를 업데이트하는 내용인데 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를 이해할 수 있는 기능이 되어야 한다.
- HTTP Response Code를 사용하지 않음
- Http Response Code를 충실하게 따르지 않고, 성공은 200, 실패는 500과 같이 1~2개의 Http Response code 만 사용하는 경우이다.
- 심한 경우 에러도 200으로 정의 후 메시지를 200 response code와 함께 보내는 경우인데, 이는 REST 디자인 사상에도 어긋나고 자기 서술성에도 어긋나게 된다.
참고