REST 아키텍쳐 스타일에 부합하는 API
다시말해, 하이퍼텍스트를 포함한 self-descriptive한 메시지의 uniform interface를 통해 리소스에 접근하는 API
* (참고) API란?
애플리케이션 프로그래밍 인터페이스
애플리케이션이나 디바이스가 서로 간에 연결하여 통신할 수 있는 방법을 정의하는 규칙 세트
자원(Resource): URI
모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.
자원을 구별하는 ID는 ‘/groups/:group_id’와 같은 HTTP URI 다.
Client는 URI를 이용해서 자원을 지정하고 해당 자원의 상태(정보)에 대한 조작을 Server에 요청한다.
행위(Verb): HTTP Method
HTTP 프로토콜의 Method를 사용한다.
HTTP 프로토콜은 GET, POST, PUT, DELETE 와 같은 메서드를 제공한다.
표현(Representation of Resource)
Client가 자원의 상태(정보)에 대한 조작을 요청하면 Server는 이에 적절한 응답을 보낸다.
REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation(표현)으로 나타내어 질 수 있다.
Uniform Interface (일관된 인터페이스)
요청이 어디에서 오는지와 무관하게, 동일한 리소스에 대한 모든 API 요청은 동일하게 보여야 한다. URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말한다.
Stateless (무상태성)
REST는 무상태성 성격을 갖는다. 다시 말해 API 서버는 작업을 위한 상태정보를 따로 저장하고 관리하지 않고, 들어오는 요청만을 단순히 처리하면 된다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.
Cacheable (캐시 가능)
REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 따라서 HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.
Client - Server 구조
REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 각자 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 된다.
계층형 구조
REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.
code-on-demand 코드 온 디맨드(옵션)
REST API는 일반적으로 정적 리소스를 전송하지만, 특정한 경우에는 응답에 실행 코드(예: Java 애플릿, 자바스크립트)를 포함할 수도 있다. 이 경우에 코드는 요청 시에만 실행되어야 한다.
❓왜 Uniform Interface를 지켜야 할까?
자원은 객체이다
자원의 상태는 변화가 가능하기 때문에 상태로 식별할 수 없다
→ 변하지 않는 식별자 필요! ex) /members/1
⇒ “URI를 통해 자원을 식별해야 한다”
리소스를 요청할 때 서버는 리소스를 표현하여 응답한다.
서버가 자원의 표현을 보내기 때문에 클라이언트는 자신이 이해하고 조작할 수 있는 특정 표현(형식)을 요청할 수 있다.
예를 들어 클라이언트는 리소스의 JSON 표현을 요청할 수 있다.
서버는 그렇게 할 수 있는 경우 이 표현을 제공할 수 있다.
이 개념을 콘텐츠 협상이라고 한다.
⇒ API에서 콘텐츠 협상을 사용하여 여러 클라이언트가 동일한 URL에서 다른 리소스 표현에 엑세스할 수 있도록 할 수 있다.
ex) Accept: text/plain
→ plain text로 response
Accept: application/json
→ JSON으로 response
메시지는 스스로에 대해 설명해야 한다.
클라이언트와 서버 사이의 컴포넌트들은 메시지의 내용을 참고하여 적절한 작업을 수행한다.
ex)
GET / HTTP/1.1
→ Non Self-descriptive
GET / HTTP/1.1 HOST: [www.example.org](<http://www.example.org>)
→ Self-descriptive
“하이퍼미디어(링크)를 통한 앱 상태 변경”
어플리케이션의 상태가 하이퍼링크를 통해서 전이가 되어야한다.
예를 들어,
게시 글을 조회하는 URI가 있다고 가정 해보자 GET https:*//my-server.com/article*
그럼 여기서 해당 글을 조회한 사용자는 다음 행동으로 어떤 행동을 할까?
이러한 행동(상태)의 전이를 하이퍼미디어를 통해 해야한다.
HTML(프론트) 상에서는 <a>
태그를 통해 이를 만족한다.
ex) <a href=”/test”>Test</a>
🤔서버에서도 이를 만족하려면?
서버는 현재 이용 가능한 다른 작업에 대한 하이퍼링크를 포함하여 응답해야한다.
- HTTP Link 헤더
: HTML 태그와 같은 용도로서, Content-Type이 text/html이 아닐 때도 태그에 담기는 내용들을 메타데이터로 전송할 수 있게 해준다
HTTP/1.1 200 OK
Link: <http://example.com/objects/?from=...>; rel=next
Content-Type: application/json
[...]
- HATEOAS를 위한 HAL JSON 타입
: Hypertext Application Language 으로 JSON, XMl 코드 내의 외부 리소스에 대한 링크를 추가하기 위한 특별한 데이터 타입이다.
{
"data": { // HAL JSON의 리소스 필드
"id": 1000,
"name": "게시글 1",
"content": "HAL JSON을 이용한 예시 JSON"
},
"_links": { // HAL JSON의 링크 필드
"self": {
"href": "http://localhost:8080/api/article/1000" // 현재 api 주소
},
"profile": {
"href": "http://localhost:8080/docs#query-article" // 해당 api의 문서
},
"next": {
"href": "http://localhost:8080/api/article/1001" // article 의 다음 api 주소
},
"prev": {
"href": "http://localhost:8080/api/article/999" // article의 이전 api 주소
}
}
}
Reference
그런 REST API로 괜찮은가
[10분 테코톡] 정의 REST API
진짜 RESTful API란 무엇인가? Rest API uniform interface
REST API 제대로 알고 사용하기
HATEOAS를 모르면 당신이 알고 있는 REST API는 REST API가 아니라고 장담할게요.