1. REST 구성
REST API는 다음과 같은 3가지 부분으로 구성된다.
- 자원(Resource) : 자원은 Data, Meta Data, HATEOAS로 나뉜다.
- 행위(Verb) : HTTP Method로 표현된다.
- 표현(Representations)
2. REST의 특징
- 구성 요소(클라이언트, 서버 등) 사이의 인터페이스는 균일(uniform)해야한다.
- 인터페이스를 일반화함으로써, 전체 시스템 아키텍처가 단순해지고, 상호 작용의 가시성이 개선되며, 구현과 서비스가 분리되므로 독립적인 진화가 가능해질 수 있다.
2) Stateless (무상태성)
- 클라이언트와 서버의 통신에는 상태가 없어야한다. 모든 요청은 필요한 모든 정보를 담고 있어야한다.
- 요청 하나만 봐도 바로 뭔지 알 수 있으므로 가시성이 개선되고, task 실패시 복원이 쉬우므로 신뢰성이 개선되며, 상태를 저장할 필요가 없으므로 규모 확장성이 개선될 수 있다.
3) Cacheable (캐시 가능)
- 캐시가 가능해야한다. 즉, 모든 서버 응답은 캐시가 가능한지 그렇지 아닌지 알 수 있어야한다.
- 효율, 규모 확장성, 사용자 입장에서의 성능이 개선된다.
4) Self-descriptiveness (자체 표현 구조)
- REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것이다.
5) Client - Server 구조
- 클라이언트-서버 스타일은 사용자 인터페이스에 대한 관심(concern)을 데이터 저장에 대한 관심으로부터 분리함으로써 클라이언트의 이식성과 서버의 규모확장성을 개선할 수 있다.
6) Layered System(계층형 구조)
- REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.
3. REST API 설계 가이드
1) URI는 정보의 자원을 표현해야 한다.
- resource는 동사보다는 명사를, 대문자보다는 소문자를 사용한다.
- resource의 도큐먼트 이름으로는 단수 명사를 사용해야 한다.
- resource의 컬렉션 이름으로는 복수 명사를 사용해야 한다.
- resource의 스토어 이름으로는 복수 명사를 사용해야 한다.
- 예) GET /members : 맴버의 모든 정보를 달라는 요청
- 예) DELETE /members/1 : HTTP Method 중의 하나인 DELETE를 이용하여 삭제를 표현
2) 자원에 대한 행위는 HTTP Method (GET, POST, PUT, DELETE)로 표현한다.
URI | 올바른 표현인가 ? |
---|
GET /members/1 | O |
GET /members/get/1 | X |
GET /members/add | X |
POST /members | O |
GET /members/update/1 | X |
PUT /members/1 | O |
GET /members/del/1 | X |
DELETE /members/1 | O |
3) URI에 HTTP Method가 들어가면 안된다.
- 예) GET /books/delete/1 -> DELETE /books/1
4) URI에 행위에 대한 동사 표현이 들어가면 안된다.
- 즉, CRUD 기능을 나타내는 것은 URI에 사용하지 않는다.
- 예) GET /books/show/1 -> GET /books/1
- 예) GET /books/insert/2 -> POST /books/2
5) 경로 부분 중 변하는 부분은 유일한 값으로 대체한다.
- 즉, id는 하나의 특정 resource를 나타내는 고유값을 의미한다.
- 예) book을 생성하는 URI: POST /students
- 예) id=10 인 book을 삭제하는 URI: DELETE /students/10
6) 슬래시 구분자( / )는 계층 관계를 나타내는데 사용한다.
7) URI 마지막 문자로 슬래시( / )를 포함하지 않는다.
8) URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라져야 한다.
9) 하이픈( - )은 URI 가독성을 높이는데 사용할 수 있다.
10) 밑줄( _ )은 URI에 사용하지 않는다.
11) URI 경로에는 소문자가 적합하다.
- URI 경로에 대문자 사용은 피하도록 한다.
- RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하기 때문이다.
13) 리소스 간에 연관 관계가 있는 경우 다음과 같은 방법으로 표현한다.
- /리소스명/리소스 ID/관계가 있는 다른 리소스명
- 예) GET : /books/{bookid}/viewers (일반적으로 소유 ‘has’의 관계를 표현할 때)
14) 자원을 표현하는 컬렉션(Collection)과 도큐먼트(Document)
- 컬렉션은 객체의 집합, 도큐먼트는 객체라고 생각하면 된다. 컬렉션과 도큐먼트 모두 리소스로 표현할 수 있으며 URI로 표현할 수 있다.
- 예) http://edwith.org/courses/1
- courses는 컬렉션을 나타낸다. 복수로 표현해야 한다.
- courses/1 은 courses 중에서 id가 1인 도큐먼트를 의미한다.
4. HTTP 응답 상태 코드
- 잘 설계된 REST API는 URI만 잘 설계되는 것이 아니라 그 리소스에 대한 응답도 잘 표현되야 한다.
- 정확한 응답의 상태 코드만으로도 많은 정보를 전달할 수 있기 때문이다.
- 자주 사용되는 HTTP 상태 코드는 다음과 같다.
5. HATEOAS
- 웹 게시판을 이용한다고 생각해보자. 게시판 목록보기 화면에서 제목을 누르면 상세 보기 화면으로 이동한다. 상세 보기 화면에서 글쓰기 버튼을 클릭하면 글쓰기 화면으로 이동한다. 이렇게 웹이란 하이퍼 링크를 통해 관계된 URL로 이동할 수 있다.
- REST API를 요청할 경우, 그 결과를 전달 받게 된다. 그 결과는 보통 JSON형태로 받게 된다.
- 예를 들어, 다음과 같은 요청을 보냈다고 생각해보자.
- GET /books/1
- 결과는 다음과 같다.
{
"id" : 1,
"title" : "hello spring",
"author" : "carami"
"price" : 5000
}
- 이렇게 요청에 해당하는 결과를 보내줄 수 있다. 이 결과에 관련된 REST API에 대한 정보를 HATEOAS라고 말한다.
- HATEOAS란 ‘Hypermedia As The Engine Of Application State’ 의 약자이다.
- 아래의 JSON문서를 보면 ‘_links’ 부분이 보일 것이다. 이 부분이 HATEOAS부분이다.
- 자기 자신의 URL, book 컬렉션과 관련된 URL, book저장을 위한 URL 등이 표현되어 있는 것을 알 수 있다.
{
"id" : 1,
"title" : "hello spring",
"author" : "carami"
"price" : 5000,
"_links":{
"self":{
"href":"http://localhost:8080/books/1"
},
"query-books":{
"href":"http://localhost/books"
},
"write-books":{
"href":"http://localhost/books"
}
}
}
- 이렇게, DATA와 함께 관련된 URL정보를 제공하는 것을 HATEOAS라고 말한다.
6. REST와 관련된 논란
- REST API에 대한 명확한 표준은 없다. 그런 문제로 REST API와 관련되서 많은 논쟁이 벌어진다.
- REST API를 구현하는 개발자들은 아키텍처 스타일을 모두 지키는 것이 힘들게 생각하는 경우가 있다.
- 그러다보니, 모든 아키텍처 스타일을 지키지 않고 개발하게 된다.
- 특히 REST의 HATEOAS와 자체 표현 구조(self-descriptiveness)를 만족 못하도록 개발되는 경우가 많다.
- 이렇게 REST API를 완벽하게 구현하지 못할 경우를 Web API라고 한다.(완벽하지 않아도 REST API라고 부르는 경우도 많다.)
reference
https://www.youtube.com/watch?v=RP_f5dMoHFc
https://meetup.toast.com/posts/92