해당 글은 아래의 자료들을 바탕으로 작성하였습니다.자세한 내용은 아래의 글을 확인해주세요.내용, 저작권등의 문제가 있는 경우 댓글이나 메일 부탁드립니다.
- Deview 2017 - 그런 Rest API로 괜찮은가?
- REST의 representation이란 무엇인가
- 바쁜 개발자들을 위한 REST 논문 요약
- REST API 이해와 설계 - #2 API 설계 가이드
- 위키백과 REST
- [Network] REST란? REST API란? RESTful이란?
- REST API 관점에서 바라보는 HTTP 상태 코드(HTTP status code)
- 5분만에 제대로 설계하는 ⭐️ REST API
- 논문을 통한 REST에 대한 고찰
- What is REST
- 책 : 조대협의 서버 사이드 : 대용량 아키텍처와 성능 튜닝 4장 Rest API
- 강의 : 인프런 백기선의 스프링기반 Rest api 개발
- 강의 : 인프런 Spring Boot를 이용한 RESTful Web Services 개발
"How do I improve HTTP without breaking the Web?"
웹을 깨뜨리지 않고 어떻게 HTTP를 향상 시킬 수 있을까?
Representational State Transfer: An Architectural Style for Distributed Hypermedia interaction
REST : 분산 하이퍼미디어 시스템을 위한 아키텍처 스타일
Architectural Styles and the Design of Network-based Software Architectures
아래는 로이필딩의 박사학위 논문인 “Architectural Styles and the Design of Network-based Software Architectures”에 나온 REST의 스타일이다.
identification of resources
manipulation of resources through representation
self-descriptive messages
hypermedia as the engine of application state
이 스타일(Uniform Interface)에 따르면, REST API는 기본 URI와 Media-Type만으로 이용 할 수 있어야한다.
위의 제약조건은 아래에서 더 자세히 알아보겠습니다.
REST가 대세가 되었고 CMIS와 같은 표준이 나왔지만, 로이필딩은 REST가 아니라 지적하였다.
로이필딩은 위의 REST의 스타일 중 'Code-On-Demand'를 제외한 모든 스타일을 지켜야 REST라 부를수 있다고 하였다. (REST하지 않은 API도 괜찮음. 다만 REST API라 부르면 안됨.)
샘플을 통해서 보는 구성요소
Method
REST에서 행위(CRUD)가 되는 부분으로 HTTP Method를 사용하여 나타낸다
Microsoft REST API Guidelines(2016)
- GET, PUT, DELETE, POST, HEAD, PATCH, OPTIONS를 지원해야함.
Resource
서버에서 명명 할 수 있는 모든 정보는 자원이 될 수 있다. (문서, 이미지, 다른 리소스의 모음 등..)
Microsoft REST API Guidelines(2016)
- URI는 https://{serviceRoot}/{collection}/{id} 형식이어야 함.
Representation
Representation은 어떤 리소스의 특정 시점의 상태를 반영하고 있는 정보이며,
Json, XML, plain-text 등의 여러 형태로 표현할 수 있다.
“representation”은 무엇인가? 어떤 리소스의 특정 시점의 상태를 반영하고 있는 정보이다. 하나의 representation은 representation data와 representation metadata로 구성된다. 위의 예에서는 “hello”가 representation data이고, “Content-Type: text/plain”과 “Content-Language: en”이 representation metadata이다.
PUT /repos/{owner}/{repo}/topics
{
"owner": "octocat",
"repo": "hello-world",
"names": [
"names"
]
}
HTTP/1.1 200 OK
{
"names": [
"octocat",
"atom",
"electron",
"api"
]
}
단, Representation은 단순히 서버에서 반환해주는 리소스의 정보만이 아닌
Representation metadata는 특정 URI로 자원을 요청하였을 때 서버와 클라이언트 간의 내용 협상(Content Negotiation) 에 사용된다.
Content-Type: text/html; charset=UTF-8
Content-Language: ko
<html><body>안녕하세요</body></html>
HTTP/2 422
Content-Length: 149
{
"message": "Validation Failed",
"errors": [
{
"resource": "Issue",
"field": "title",
"code": "missing_field"
}
]
}
이는 Unidentified Representation으로 불리는 URI를 모르는 어떤 리소스에 대한 Representation이다.
이론적으로 정확한 정답은 “Content-Location 헤더에 들어있는 uri가 가리키는 리소스”이다. 그러나 보통 Content-Location 헤더는 비어 있을 것이므로 현실적인 정답은 “uri를 모르는 어떤 리소스”이다.
HTTP 메시지의 PayLoad로 전달되는 모든 것은 하나의 Representation이거나 적어도 그의 일부이다.
Re: Is a payload always a representation?
Yes, but not necessarily a representation of the resource identified by the request-target.
- Roy T. Fielding [https://lists.w3.org/Archives/Public/ietf-http-wg/2017JanMar/0523.html]
URI(Uniform Resource Identifier)로 리소스가 식별되어야 한다.
http://{serviceRoot}/movie
http://{serviceRoot}/movies
http://{serviceRoot}/movies/inception
http://{serviceRoot}/movies/inception/actors/2
Representaion 전송을 통해서 리소스를 조작해야한다.
GET /todos HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/vnd.todos+json
[
{"id": 1, "title": "회사 가기"},
{"id": 2, "title": "집에 가기"}
]
GET /todos HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Content-Type: application/json
Link: <https://exmaple.org/docs/todos>; rel="profile
[
{"id": 1, "title": "회사 가기"},
{"id": 2, "title": "집에 가기"}
]
{
"id" : 31,
"free" : false,
"location" : "my home",
...
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/events/31"
},
"query-events" : {
"href" : "http://localhost:8080/api/events"
},
"profile" : {
"href" : "/docs/index-kr.html#resources-events-create"
},
"update-event" : {
"href" : "http://localhost:8080/api/events/31"
}
}
}
링크를 통한 애플리케이션 상태 변이
이로인해 API에 Versioning을 할 필요가 없어진다.
"REST API must be hypertext-driven"
"REST API를 위한 최고의 버저닝 전략은 API 버저닝을 안하는 것"
- Roy T. Fielding
POST /todos HTTP/1.1
Content-Type: application/json
{
"title": "점심 약속"
}
HTTP/1.1 204 No Content
Location: /todos/1
Link: </todos/>, rel="collection"
{
"id" : 31,
"free" : false,
"location" : "my home",
...
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/events/31"
},
"query-events" : {
"href" : "http://localhost:8080/api/events"
},
"profile" : {
"href" : "/docs/index-kr.html#resources-events-create"
},
"update-event" : {
"href" : "http://localhost:8080/api/events/31"
}
}
}
REST의 경우 명확한 표준이 정해지지 않아 지금까지 완전히 REST하지 않은 API를 REST API라고 하면서 개발하고 있었습니다.
제대로된 REST API를 개발하기 위해 REST의 의미와 스타일에 대해 정리해보았습니다.
다음에는 잘 짜여진 REST API의 예시와 Springboot, RestDocs를 이용한 실제 REST API 작성하는 법을 정리해보겠습니다.
감사합니다 :)