1. REST API의 탄생
REST는 'REpresentational State Transfer'라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한 사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표했다고 한다.
2. REST API란?
HTTP 통신에서 어떤 자원에 대한 CRUD 요청을 Resource와 Method로 표현하여 특정한 형태로 전달하는 방식
즉, REST란 '어떤 자원에 대해 CRUD(Create, Read, Update, Delete) 연산을 수행하기 위해 URI(Resource)로 요청을 보내는 것'으로 GET, POST 등의 방식(Method)을 사용하여 요청을 보내며, 요청을 위한 자원은 특정한 형태(Representation of Resource)로 표현된다.
[Resource, 자원]
서버는 Unique한 Resource를 가지고 있으며, 클라이언트는 이러한 Resource에 요청을 보낸다. 이러한 Resource는 URI에 해당한다.
[Method, 행위]
서버에 요청을 보내기 위한 방식으로 GET, POST, PUT, PATCH, DELETE가 있다. CRUD 연산 중 처리를 위한 연산에 맞는 Method를 사용해서 서버에 요청을 보내야 한다.
[Representation of Resource, 표현]
클라이언트와 서버가 데이터를 주고받는 형태로 json, xml, text, rss 등이 있다. 이 중 Key, Value를 활용하는 json을 주로 사용한다.
3. RESTful API
앞서 언급한 Resource, Method, Representation of Resource의 3가지 구성 요소를 만족해야만 REST API를 충족한다.
예를 들어, 게시글을 작성하기 위해 'http://localhost:5000/board' URI에 POST 방식을 사용하여 JSON 형태의 데이터를 전달할 수 있다. 이와 같이 CRUD 연산에 대한 요청을 할 때, 요청을 위한 Resource(자원, URI)와 이에 대한 Method(행위, POST) 그리고 Representation of Resource(자원의 형태, JSON)을 사용하면 표현이 명확해지므로 이를 REST라고 하며, 이러한 REST 기반의 API를 웹으로 구현한 것이 RESTful한 API라고 한다.
4. REST(REpresentational State Transfer)의 특징
REST 아키텍쳐에 적용되는 6가지 특징
4-1. Client-Server
- API를 제공하는 서버와 사용자 인증이나 컨텍스트(세션, 로그인 정보 등)을 관리하는 클라이언트를 분리함으로써 서버와 클라이언트를 사용자 인터페이스와 데이터 저장 문제를 각각의 역할로 나눌 수 있다.
- 서버와 클라이언트의 역할이 명확하게 나뉘어지기 때문에 서버와 클라이언트는 각각의 구성요소들을 독립적으로 진화할 수 있고 확장할 수 있다.
- 이로써 서버와 클라이언트 사이의 의존성이 낮아지게 되고 각 필드에서 개발해야 할 사항들이 명확해진다.
4-2. Stateless
- REST의 Stateless(무상태성)은 CSS(Client-Stateless-Server) 스타일과 마찬가지로 기본적으로 상태 비저장 상태이어야 한다.
- 클라이언트에서 서버로 보내는 요청에 이해하는데 필요한 모든 정보를 포함해야 하며, 서버에서는 컨텍스트를 사용할 수 없다. 즉, 클라이언트에서 전적으로 세션 상태를 관리한다. 또한 서버에서는 요청 사이에 상태를 저장하지 않아도 되므로 확장성이 향상된다.
- 서버에서는 요청에 대한 전체적은 특성을 확인하기 위해서 단일 요청 데이터 이상을 검토할 필요가 없으며, 들어오는 요청만을 단순히 처리하기만 하면 되기 때문에 가시성이 향상된다.
- 따라서, 서버의 구성 요소는 자원(Resource)을 신속하게 확보할 수 있고, 서버가 요청 전반에서 자원 사용을 관리할 필요가 없으므로 구현을 더욱 단순화 시킬 수 있다.
- 단점은 서버와 클라이언트에서 공유하는 컨텍스트 정보를 서버에 남겨둘 수 없기 때문에, 일련의 요청에서 전송되는 반복 데이터를 증가시켜 네트워크 성능을 저하시킬 수 있다.
4-3. Cacheable
- REST의 특징 중 하나는 REST를 구성하기 위한 조건을 충족하면 HTTP라는 기존 웹 표준을 그대로 사용할 수 있기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용 가능하다. 따라서 HTTP가 가진 캐싱 기능을 적용할 수 있다.
- 네트워크 효율성을 개선하기 위해서 캐시 제약 조건을 추가한 'client-cache-stateless-server' 스타일을 형성한다.
- 캐시 제약 조건을 사용하기 위해서 클라이언트의 요청에 대한 응답에 데이터가 '캐시 가능' 또는 '캐시 불가능'인 레이블을 암시적 또는 명시적으로 지정해줘야 한다.
- 캐시 제약 조건을 추가하면 일련의 상호작용의 평균 대기 시간을 줄여 효율성, 확장성 또는 사용자 인식 성능을 개선할 수 있다는 장점이 있다.
- 단점은 캐시 내의 오래된 데이터가 서버에 직접 요청을 전송했을 때, 얻었을 데이터와 크게 다르다면 캐시의 안정성이 저하될 수 있다.
- REST 아키텍처 스타일을 다른 네트워크 기반 스타일과 구별하는 가장 큰 특징이다.
- Resource(URI)에 대한 요청을 통일되고, 한정적으로 수행하는 아키텍처 스타일이다. 이는 요청을 하는 Client가 플랫폼(Android, iOS 등)에 무관하며, 특정 언어나 기술에 종속받지 않는 특징이다.
- 여기서 말하는 한정적이라는 뜻은 동일하게 구성된 URL 주소에 요청할 자원의 방법(Methods)을 달리하여 나타낼 수 있다는 뜻이다. 즉, 하나의 URL을 이용하여 많은 representation을 할 수 있다.
- REST 인터페이스는 대량의 하이퍼미디어 데이터 전송에 효율적이도록 설계되어 웹의 일반적인 사례에는 최적화되지만 다른 형태의 아키텍처 상호작용에는 최적화되지 않는 인터페이스를 제공한다.
4-5. Layered System
- REST API의 서버는 다중 계층으로 구성될 수 있으며, 로드 밸런싱, 암호화 등을 위한 계층을 추가하여 구조를 변경할 수 있다.
- 또한 Proxy, Gateway와 같은 네트워크 기반의 중간매체를 사용할 수 있게 해준다.
- 클라이언트는 서버와 직접 통신하는지, 중간 서버와 통신하는지 알 수 없다.
4-6. Self-Descriptiveness
- REST API는 요청 메세지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어있다.
5. REST API 디자인 가이드
- URI는 정보의 자원을 표현해야 한다.
- 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.
6. REST API 중심 규칙
6-1. URI는 정보의 자원을 표현해야 한다. - 리소스명은 동사보다는 명사를 사용
GET /members/delete/1 (x)
- delete는 행위에 대한 표현이므로 적절하지 않다.
- URI는 자원을 표현하는데 중점을 두어야 한다.
DELETE /members/1 (o)
- 행위에 대한 표현은 HTTP Method로 표현하여, URI에는 자원을 표현하는데 중점을 두도록 수정
위의 예시처럼 URI는 자원을 표현하는 데 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 REST한 API를 설계하는 중심 규칙이다.
6-2. URI 설계 시 주의할 점
1) 슬래시 구분자(/)는 계층 관계를 나타내는데 사용한다.
http://restapi.example.com/houses/apartments
http://restapi.example.com/animals/mammals/whales
2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다.
URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이다. REST API는 분명한 URI를 만들어서 통신을 해야하므로 혼동을 주지 않도록 URI 경로의 마지막에는 슬래시(/)를 사용하지 않는다.
http://restapi.example.com/houses/apartments/ (x)
3) 하이픈(-)은 URI 가독성을 높이는데 사용
URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI 경로를 사용하게 된다면 하이픈을 사용하여 가독성을 높일 수 있다.
4) 밑줄(_)은 URI에 사용하지 않는다.
밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 한다. 가독성을 위해 하이픈(-)을 사용하는 것이 좋다.
5) URI 경로에는 소문자가 적합하다.
대소문자에 따라 다른 리소스로 인식하게 되기 때문에 URI 경로에 대문자 사용은 피하도록 해야 한다.
RFC 3986 is the URI (Unified Resource Identifier) Syntax document
→ RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정한다.
6) 파일 확장자는 URI에 포함시키지 않는다.
REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다.
Accept header를 사용하여 파일 확장자를 표현한다.
http://restapi.example.com/members/soccer/345/photo.jpg (x)
GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg (o)
6-3. 리소스 간의 관계를 표현하는 방법
REST 리소스 간에는 연관 관계가 있을 수 있고, 이런 경우에 다음과 같은 표현 방법을 사용한다.
/리소스명/리소스 ID/관계가 있는 다른 리소스명
ex) GET : /user/{userid}/devices (일반적으로 소유 'has'의 관계를 표현)
만약 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있다.
GET : /user/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)
6-4. 자원을 표현하는 Collection과 Document
-
Collection과 Document에 대해 알면 URI 설계가 한 층 더 쉬워진다.
-
Collection: 문서들의 집합, 객체들의 집합
-
Document: 문서 또는 객체
-
Collection과 Document는 모두 리소스로 표현할 수 있으며, URI에 표현된다.
-
sports라는 컬렉션과 soccer라는 도큐먼트로 표현되어 있다.
http:// restapi.example.com/sports/soccer
- sports, players 컬렉션과 soccer, 13을 의미하는 도큐먼트로 URI가 이루어진다.
http:// restapi.example.com/sports/soccer/players/13
- 여기서 중요한 점은 컬렉션은 복수로 사용하고 도큐먼트는 단수를 사용한다.
- 직관적인 REST API를 위해서는 컬렉션과 도큐먼트를 사용할 때, 단수와 복수를 지키면 좀 더 이해하기 쉬운 URI를 설계할 수 있다.
7. HTTP 응답 상태 코드
- 잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것까지 포함되어야 한다.
- 200 : 클라이언트의 요청을 정상적으로 수행함
- 201 : 클라이언트가 어떠한 리소스 생성을 요청, 해당 리소스가 성공적으로 생성됨 (POST를 통한 리소스 생성 작업 시)
- 400 : 클라이언트의 요청이 부적절 할 경우 사용하는 응답 코드
- 401 : 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용하는 응답 코드
- 403 : 유저 인증상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용하는 응답 코드 (403 보다는 400이나 404를 사용할 것을 권고, 403 자체가 리소스가 존재한다는 뜻이기 때문에)
- 405 : 클라이언트가 요청한 리소스에는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드
- 301 : 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을 때 사용하는 응답 코드 (응답 시 Location header에 변경된 URI를 적어줘야 한다.)
- 500 : 서버에 문제가 있을 경우 사용하는 응답 코드
Reference