이 글은 Mike Kelly가 작성한 HAL - Hypertext Application Language를 번역한 글입니다.

가벼운 하이퍼미디어 타입

요약

HAL은 API 리소스 사이를 하이퍼링크 위한 쉽고 지속적인 방법을 제시해준다.

HAL을 사용하는 것은 API을 검색가능하게 만들고, API 문서가 API 내에서 쉽게 검색하게 만들어준다. 간단히 말하면 API로 일하기 쉽게 만들어서 크라이언트 개발자들에게 좀 더 매력적으로 만든다.

HAL를 사용하는 API는 대부분의 프로그래밍 언어의 오픈소스 라이브러리로 쉽게 사용된다. 또한 프로그래머가 생각한대로 JSON같이 쉽게 다룰 수 있게 만든다.

설명서

HAL은 JSON 혹은 XML 형식의 하이퍼링크를 표현하는 컨벤션을 제공한다. 나머지 HAL 문서는 단순히 순수한 JSON 혹은 XML이다. ad-hoc 구조를 사용하거나 자신만의 형식을 디자인하는데 소중한 시간을 사용하는 것 대신, HAL의 컨베년을 사용하므로서 데이터를 문서화하고 구조화하는데 더 집중 할 수 있을 것이다.

HAL은 컴퓨터에게는 좀 HTML 같다고 볼 수 있다.왜냐하면 하이퍼링크를 통해 다른 타입의 어플리케이션으로 이동할 수 있도록 디자인되었기 때문이다. 차이점은 HTML은 '인간의 행위'가 웹 어플리케이션을 통해 목표를 성취하도록 돕기 위한 특징을 가지고 있고, 반면에 HAL은 '자동화된 행위'가 웹 API를 통해 목표를 성취하도록 의도하고 있다.

하지만, HAL은 사실 굉장히 인간 친화적이기도 하다. HAL의 컨벤션은 API 도큐멘테이션을 API 메세지 그 자체로 검색이 쉽게 만들어 준다. 이것은 개발자들에게 HAL 기반의 API를 시작하는 문턱은 낮추고 API와 동떨어진 문서를 이해하려고 노력하려는 무리한 노력없이 API가 가지고 있는 능력을 탐색할 수 있게 만들어 준다.

예시

hal+json의 순서 모음을 아래처럼 표현해야 할 것이다. 찾아봐야 될 것은 :

  • self 링크로 표현되는 ('/orders')를 대표하는 메인 리소스의 URI
  • 다음 페이지의 순서를 가르키는 next 링크
  • 'ea:find'에 호출되어 아이디로 순서를 검색하는 templated 링크
  • 배열에 저장된 여러개의 'ea:admin'링크 오브젝트들
  • orders 컬렉션의 두개의 프로퍼티; 'currentlyProcessing'과 'shippedToday'
  • 프로퍼티와 그 자체 링크를 포함한 Embbeded order 리소스
  • API의 다큐멘테이션 URL로 링크로 확장하기 위한 'ea'로 명시된 압축 URI

application/hal+json

{
    "_links": {
        "self": { "href": "/orders" },
        "curies": [{ "name": "ea", "href": "http://example.com/docs/rels/{rel}", "templated": true }],
        "next": { "href": "/orders?page=2" },
        "ea:find": {
            "href": "/orders{?id}",
            "templated": true
        },
        "ea:admin": [{
            "href": "/admins/2",
            "title": "Fred"
        }, {
            "href": "/admins/5",
            "title": "Kate"
        }]
    },
    "currentlyProcessing": 14,
    "shippedToday": 20,
    "_embedded": {
        "ea:order": [{
            "_links": {
                "self": { "href": "/orders/123" },
                "ea:basket": { "href": "/baskets/98712" },
                "ea:customer": { "href": "/customers/7809" }
            },
            "total": 30.00,
            "currency": "USD",
            "status": "shipped"
        }, {
            "_links": {
                "self": { "href": "/orders/124" },
                "ea:basket": { "href": "/baskets/97213" },
                "ea:customer": { "href": "/customers/12369" }
            },
            "total": 20.00,
            "currency": "USD",
            "status": "processing"
        }]
    }
}

HAL 모델

HAL 컨벤션은 두가지의 심플한 컨셉을 가진다 : Resource와 Links

Resource

Resource는 다음과 같은 것들은 가진다. :

  • Links (to URIs)
  • Embedded Resource (다른 리소스들은 임베디드 Resource에 포함된다)
  • State (정제되지 않은 JSON 혹은 XML 데이터)

Links는 다음과 같은 것들을 가진다. :

  • Target (a URI)
  • 'rel'이라고 불리는 relation (링크의 이름)
  • 같은 URL의 다른 버전의 URL을 가능하게 하는 HTTP 기술(content negotiation)이나 더 이상 사용불가한 것들(deprecation)을 도와주는 다른 부가적인 프로퍼티들

아래는 어떻게 HAL의 구조도를 대략적으로 그려놓은 이미지이다.

스크린샷 2019-09-06 오전 9.19.01.png

HAL은 API에서 어떻게 사용되었는가

HAL은 클라이언트가 API 따라오는 링크들로 리소스를 탐색할 수 있는 API를 제작하기 위해 디자인 되었다.

Links는 link relations에 의해 식별된다. Link relation은 하이퍼미디어 API의 활력소와 같은 것들이다. : 클라이언트 개발자들에게어떤 리소스가 사용가능하고 어떻게 상호작용하는지, 어떻게 코드가 어떤 링크로 이동할 것인지 알려준다.

그렇지만 Link relation은 HAL에서 일반적인 식별문자는 아니다. Link relation은 사실 개발자들이 주어진 링크의 도큐멘테이션을 읽을 수있게 만든 URLs이다. 이것이 흔히 알려진 "탐색가능성(discoverability)"이다. 이는 개발자가 다른 사람이 만든 API로 유입되고, 가능한 링크들의 문서들을 읽은 뒤 API에 빠져들도록 만들어준다.

HAL은 link relation를 다음과 같이 사용하도록 독려한다.

  • link와 representation내의 embedded resources를 식별한다.
  • 예상 구조와 타겟 resoure의 의미를 추정한다.
  • 어떤 request와 representation이 타겟 resource로 보내졌는지 시그널을 준다.

어떻게 HAL을 보내는가

HAL은 각각applicatoin/hal+jsonapplication/hal+xml이라는 이름의 JSON, XML 미디어타입을 가진다.
HAL이 HTTP에 보낼 때, 응답 Content-Type은 관련된 미디어타입 이름을 포함해야 한다.

HAL 문서 구조

문서의 최소 요구사항

HAL 문서는 최소한 빈 리소소라도 가지고 있어야 한다.
빈 JSON 객체

{}

리소스

대부분의 경우에, 리소스는 self URI를 가져야 한다.

self 링크로 나타내는 것

{
    "_links" : {
        "self": { "href" : "/example_reousrces" }
    }
}

links는 반드시 리소스에 직접 포함되어야 한다. links는 반드시 리소스 객체의 프로퍼티가 되어야 하는 _Links 해시를 포함하는 JSON 객체로 나타낸다.

{
    "_links": {
        "next": { "href": "/page=2" }
    }
}

Links는 'rel'이라고 불리는 relation을 가진다. 이는 특정 링크의 의미를 나타낸다.
Link rel은 리소스들의 링크들을 구분을 하는 주된 방법이다.
간단히 말해 기본적으로 _links 해쉬 내의 키값이다. 주로 실제 'href'값과 같은 데이터를 포함한 링크 객체와 함께 링크의 의미와 연관되어있다.

{
    "_links": {
        "next": { "href": "/page=2" }
    }
}