REST
REST라는 단어는 비교적 최근에 나온 단어로 로이 필딩(Roy Fielding)의 2000년 박사학위 논문에서 소개되었습니다 (자세한 사항은 Chapter 5, p.94를 보면 됩니다).
1990년대에는 웹이 폭발적으로 성장중이었지만 웹의 최신 구조를 제대로 설명하는 문서가 없었고 캐시나 프록시 같은 기술이 존재했지만 이에 대한 표준은 존재하지 않았습니다.
때문에 W3C나 IETF 같은 곳에서 웹의 표준화 작업에 착수했고 로이 필딩은 HTTP 1.1의 초기 설계를 담당하면서 HTTP 1.0과 HTTP 1.1의 개념을 설명하기 위해 REST 개념을 개발하였다고 합니다.
로이 필딩이 REST를 개발하게 된 동기는 웹이 어떻게 동작해야 하는지에 대한 구조적 모델을 만들어서 웹 프로토콜 표준을 위한 guiding framework 역할을 하기 위함이었다고 합니다. 웹 환경에는 수많은 프로토콜이 존재하는데 이에 대한 표준이 존재하지 않아 인터페이스나 인터페이스 사양이 천차만별이 될 수 있어 REST가 웹 프로토콜의 표준이 되어 가이드라인을 제공해주길 원했다고 합니다.
REST의 의미
REST는 REpresentational State Transfer의 약자로 분산 하이퍼미디어 시스템 설계를 위한 아키텍처의 한 종류입니다.
REST는 HTTP 1.1의 개발과 병행되어 설계되었기 때문에 처음부터 웹에 특화된, 웹의 장점을 최대한으로 활용하는 아키텍처라고 할 수 있습니다.
Representational State Transfer를 구글 번역기를 돌려보면 "대표 상태 이전", ChatGPT로 설명해달라고 하면 "표현 상태 전이"라고 해석해줍니다. 단어만 나열해놓으니 어떤 뜻인지 모르겠는데, 정확히 이해하기 위해서는 Representational과 State Transfer를 따로 두고 해석해야 합니다.
Representational은 "대표"라는 뜻이 아닌 "표현"의 뜻으로 해석해야 합니다. 하나의 데이터를 TEXT, JSON, XML, 이미지 등의 다양한 형식으로 표현할 수 있듯이 로이 필딩은 자원을 정보와 이에 대한 표현(representation)으로 분리했습니다.
웹은 정보를 전송하는 것이 아니라 자원의 표현을 전송해서 소통하는 것으로 해석해야 하고, REST 구조의 프로그램은 정보를 전송하는 것이 아니라 자원의 특정 상태를 특정한 표현으로서 전송하는 것입니다. 이러한 특성을 생각하면 Representational은 자원의 표현을 의미하게 됩니다.
State Transfer는 "상태의 전이"라는 뜻인데 로이 필딩은 예시로 웹 페이지 하나를 하나의 State로 보고 유저가 링크를 클릭하면 State Transfer가 발생해서 새로운 State로 이동한다고 보았습니다. 즉, State Transfer는 링크를 통한 자원의 이동(상태의 전이)를 의미합니다.
위의 설명을 통해 REST를 조금 더 말이 되게 해석해보면 (아닐 수도 있고요) "다양하게 표현되는(Representational) 자원(Resource)과 이러한 자원의 상태의 전달(State Transfer)"이라고 해석할 수 있겠습니다.
다른 일반적인 블로그에서는 자원의 표현에 의한 상태 전달이라고도 해석하며, 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미한다고도 합니다.
REST의 구성 요소
REST는 자원(Resource), 행위(Verb) 그리고 표현(Representation)으로 구성됩니다.
- 자원: URI, 모든 자원은 고유한 ID를 가져야 합니다
예) /students/:id, /students/grades/:id - 행위: HTTP 프로토콜의 메소드 (GET, POST, PUT, DELETE)
GET: 정보의 요청
POST: 정보의 입력
PUT: 정보의 갱신
DELETE: 정보의 삭제 - 표현: JSON, XML, HTML, TEXT 등 다양한 자원의 표현 방식을 말합니다
REST의 6가지 규칙
REST는 다음의 6가지 제한 조건을 가지고 있습니다.
- Client/Server 구조: 사용자 인터페이스와 데이터 저장소가 분리되어 있어 독립적으로 개발할 수 있습니다
- Stateless(무상태): 각 요청은 모든 필요한 정보를 가지며, 클라이언트의 컨텍스트가 서버에 저장되어서는 안 됩니다
- Cacheable(캐시 가능): 클라이언트는 응답을 캐시해 성능을 향상시킬 수 있습니다
- Layered System(계층적 시스템): 클라이언트는 서버에 직접 연결되었는지 미들웨어에 연결되었는지 알 필요가 없어야하며, 이를 통해 유연성을 높입니다
- Code on Demand(Optional): 서버는 자바스크립트, 애플릿과 같은 클라이언트가 실행 가능한 코드를 제공하여 기능을 확장시킬 수 있습니다
- Uniform Interface: URI로 지정한 Resource에 대한 조작을 통일되고 한정적인 인터페이스로 수행해야 합니다
일반적으로 WEB 프로그램을 개발하면서 HTTP 프로토콜을 사용할경우 5번째 규칙까지는 큰 신경을 쓰지 않아도 알아서 지켜지게 됩니다(HTTP 1.1을 개발하면서 같이 만들었으니 가능하겠죠?).
우리가 신경써야 하는 부분은 6번의 Uniform Interface입니다. REST is defined by four interface constraints: identification of resources; manipulation of resources through representations; self-descriptive messages; and, hypermedia as the engine of application state라고 설명되고 있으며 wikipedia에 따로 가이드 설명을 확인할 수 있습니다.
identification of resources (자원의 식별)
요청 내에 기술된 개별 자원을 식별할 수 있어야 합니다. 웹에서는 URI의 사용이 그 예시입니다.
manipulation of resources through representations (메시지를 통한 리소스의 조작)
클라이언트가 어떤 자원을 지칭하는 메시지와 특정 메타데이터만 가지고 있다면 이것만으로도 서버 상의 해당 자원을 변경/삭제할 수 있는 충분한 정보를 가지고 있는 것입니다.
self-descriptive messages (자기서술적 메시지)
각 메시지는 자신을 어떻게 처리해야 하는지에 대한 충분한 정보를 포함해야 합니다. 예를 들어 MIME type 같은 인터넷 미디어 타입을 전송하면 어떤 파서를 이용해야 하는지에 대한 정보까지 포함되어 있어야 합니다.
메시지를 이해하기 위해 그 내용까지 살펴봐야 한다면 그 메시지는 자기서술적이지 못한 메시지입니다.
단순한 application/xml 타입은 실제로 다운받지 않으면 해당 메시지만 가지고 무엇을 해야할 지 알 수 없으므로 자기서술적이지 못한 메시지입니다.
자기서술적이지 못한 메시지
GET / HTTP/1.1
자기서술적인 메시지
GET / HTTP/1.1
Host: https://www.google.com
자기서술적이지 못한 메시지
HTTP/1.1 200 OK
[{ "path": "a/b/c", "op": "delete" }]
자기서술적인 메시지
HTTP/1.1 200 OK
Content-Type: application/json
[{ "path": "a/b/c", "op": "delete" }]
hypermedia as the engine of application state (HATEOAS, 어플리케이션의 상태에 대한 엔진으로서의 하이퍼미디어)
만약에 클라이언트가 관련된 리소스에 접근하기를 원한다면 리턴되는 지시자에서 구별될 수 있어야 합니다. 충분한 컨텍스트 속에서 URI를 제공해주는 하이퍼텍스트 링크가 그 예시입니다.
간단하게 설명하면 하이퍼미디어를 어플리케이션의 상태를 관리하기 위한 매커니즘으로 사용한다는 것으로, 한 정보에서 이와 연관된 정보로 넘어가기 위한 하이퍼링크를 명시하라는 얘기입니다.
계좌정보 12345에 접근할경우 일반적으로는 아래와 같이 응답합니다
{
"application_id": 12345,
"balance": 350000
}
HATEOAS를 적용하면 다음처럼 응답합니다
{
"account_id": 12345,
"balance": 350000,
"links": [
{
"rel": "self",
"href": "https://.../accounts/12345"
},
{
"rel": "withdraw",
"href": "https://.../accounts/12345/withdraw"
}
]
}
이상으로 REST란 무엇인지, REST의 특징은 무엇인지 알아보았습니다.
다음번에는 RESTful API가 무엇인지 알아보겠습니다.