개요

REST는 6가지 제약 조건이 존재하고 이를 잘 지킨다면 RESTful한 시스템이라고 할 수 있음.

6가지 제약조건

  • Client-Server
  • Stateless
  • Cacheable
  • Uniform Interface
    • identification of resources
    • manipuation of resources through representations
    • self-descriptive messages
    • hypermeia as the engine of application state(HATEOAS)
  • Layered System
  • Code on demand(Optional)

Bold 처리 해둔 부분이 잘 충족시키지 못하는 부분.

(client-server, stateless, cache, layered system은 HTTP만 잘 따라도 충족시킬 수 있다.)

→ RESTful한 시스템 설계를 위해선 HATEOAS를 알아야 함.


REST API 성숙도 모델

성숙도 모델은 총 4단계로 나누어져 각 단계의 조건에 만족할 수록 REST API에 가까워짐.

Richardson이 제시한 REST 성숙도 모델
Richardson이 제시한 REST 성숙도 모델
(출처 : https://grapeup.com/blog/how-to-build-hypermedia-api-with-spring-hateoas#)

Lvl0

API 구현은 HTTP 프로토콜을 사용하지만 전체 기능을 활용하지 않음.

또한 리소스에 대한 고유 주소 제공 X

Lvl1

리소스에 대한 고유 식별자가 있지만 리소스에 대한 각 작업에는 고유한 URL이 있음

Lvl2

동작을 설명하는 동사 대신 HTTP 메서드 사용.

ex) URL 대신 Delete 메서드 사용

Lvl3

HATEOAS 용어 도입 → 리소스에 하이퍼미디어 도입

이를 통해 가능한 작업에 대해 알려주는 응답에 링크를 배치할 수 있으므로 API를 통해 탐색할 수 있는 가능성이 추가됨.

HATEOAS

애플리케이션의 상태는 Hyperlink를 이용해 전이 되어야 한다.

하이퍼미디어는 각기 독립된 다양한 매체를 하나의 통합된 매체를 통해 각종의 자료와 정보를 요구자의 필요에 따라 비선형적으로 선택할 수 있게 하는 것을 말합니다.


// HATEOAS 예시 URI (GET /api/accounts/3) 요청 응답
{
    ~~~ 데이터 영역 ~~~
	"id": 3,
	"accountNumber": "20191575",
	"weight": 30,
    ~~~ 데이터 영역 ~~~
    
    ~~~ 링크 영역 ~~~
	"_links": {
		"self": {
			"href": "http://localhost:8080/api/accounts/3"
		},
		"collection": {
			"href": "http://localhost:8080/api/accounts"
		},
		"talls": {
			"href": "http://localhost:8080/api/accounts/3/tall"
		}
	}
    ~~~ 링크 영역 ~~~
}

HAL

Hypertext Application Language, JSON, XML 코드 내의 외부 리소스에 대한 링크를 추가하기 위한 특별한 데이터 타입.

HAL 타입 2가지

  • application/hal+json
  • application/hal+xml

HAL 특징 2가지

  • 리소스 : 일반적인 data 필드에 해당됨
  • 링크 : 하이퍼미디어로 보통 _self 필드가 링크 필드가 됨

예시

{
  "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 주소
    }
  }
}

애플리케이션 상태 전이

메인 → 글 목록(GET /articles) → 글 쓰기( GET/new-form) → 글 저장(POST /articles) → 생성된 글 보기 (GET /articles/10) → 글 목록 (GET /articles)

항상 해당 페이지에 있던 링크를 따라가면서 전이가 되었기 때문에 HATEOAS가 된 것임.

HTTP/1.1 200 OK
Content-Type: application/json
Link: </articles/1>; rel="previous",
			</articles/3>; rel="next";
{
	"title" : "The second article",
	"contents" : "article contents"
}

Uniform Interface를 충족시키는 이유

REST가 목적 하는 바인 독립적 진화를 달성하기 위해.

독립적 진화

  • 서버와 클라이언트가 각각 독립적으로 진화한다.
  • 서버의 기능이 변경되어도 클라이언트를 업데이트할 필요가 없다.

REST를 잘 적용한 사례

  • 웹 페이지를 변경했다고 웹 브라우저를 업데이트할 필요는 없다.
  • 웹 브라우저를 업데이트했다고 웹 페이지를 변경할 필요도 없다.
  • HTTP 명세가 변경되어도 웹은 잘 작동한다.
  • HTML 명세가 변경되어도 웹은 잘 작동한다.

결론

Q : REST API도 저 제약조건들을 다 지켜야 하는건가?

A (RoyFielding) : 그렇다.

Q2 : 원격 API가 꼭 REST API여야 하는건가?

A2 (RoyFielding) : 시스템 전체를 통제할 수 있다고 생각하거나, 진화에 관심이 없다면 REST에 대해 따지느라 시간을 낭비하지 마라


마치며

REST로 간단하게 실습을 진행해보던 중 예전에 이론 공부를 하던 부분을 다시 짚어보다가 HATEOAS에 대해 공부하게 되었습니다..

오늘날 스스로 REST API라고 하는 API들의 대부분이 REST 아키텍쳐 스타일을 따르지 않는다고 하고, 실무 프로젝트는 보통 성숙도 모델 레벨2 정도로 진행한다고 합니다. 하지만 HATEOAS에 관한 내용을 알아두어서 나쁠건 없다고 생각합니다.

공부하면서 참고했던 사이트

수정할 사항이나 추가해야 할 사항이 있다면 댓글이나 이메일로 연락 남겨주세요.

profile
일단 부딪혀보자

0개의 댓글