클라이언트 측에서 HATEOAS의 요점은 무엇입니까?


35

현재 이해합니다 HATEOAS는 기본적으로 각 응답 링크와 함께 다음에 수행 할 작업에 대한 정보를 보내는 것입니다. 하나의 간단한 예는 인터넷에서 쉽게 찾을 수 있습니다 : 계정 시스템과 은행 시스템. 이 예는 계정 리소스에 대한 GET 요청 후이 응답을 보여줍니다.

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">100.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
    <link rel="withdraw" href="/account/12345/withdraw" /> 
    <link rel="transfer" href="/account/12345/transfer" /> 
    <link rel="close" href="/account/12345/close" /> 
</account>

데이터와 함께 다음에 수행 할 수있는 작업을 알려주는 링크가 있습니다. 잔액이 음수이면

GET /account/12345 HTTP/1.1 HTTP/1.1 200 OK 
<?xml version="1.0"?> 
<account> 
    <account_number>12345</account_number> 
    <balance currency="usd">-25.00</balance> 
    <link rel="deposit" href="/account/12345/deposit" /> 
</account>

입금 만 가능합니다. Fiddler를 사용하거나 브라우저로 요청하면 수행 할 수있는 작업을 쉽게 확인할 수 있습니다. 이런 종류의 정보는 API의 기능을 발견하고 서버가 클라이언트에서 분리되는 데 유용합니다.

그러나 요점은 우리가 Javascript를 사용하는 SPA, Android 앱 또는 다른 많은 것들과 같은 클라이언트를 구축 할 때 HATEOAS가 어떻게 계속 관련이 있는지 알 수 없다는 것입니다. 의미하는 바는 다음과 같습니다. SPA를 자바 스크립트로 코딩 할 때 코드를 작성하려면 API에서 수행 할 수있는 작업을 알아야합니다.

따라서 서버에 ajax 호출을 작성하고 심지어 UI를 빌드하기 위해 리소스, 지원되는 메소드, 수신 대상 및 반환 대상을 알아야합니다. UI를 만들 때 계정을 요청한 후 예를 들어 입금하거나 UI에서이 옵션을 제공 할 수 없다는 것을 알아야합니다. 또한 아약스 호출을 빌드하기 위해 예금을 만들기 위해 URI를 알아야합니다.

내 말은 API에 요청을 할 때 링크를 사용하면 API를 더 잘 발견하고 사용할 수 있지만 클라이언트를 만들 때 우리가 구축하는 앱은 단순히 링크를 보지 않고 자체적으로 렌더링하는 것입니다 올바른 UI와 올바른 아약스 호출을하십시오.

그렇다면 고객에게 HATEOAS가 어떻게 중요한가? 어쨌든 우리는 왜 HATEOAS를 귀찮게합니까?


1
당신 말이 맞지만 요점이 아닙니다. HATEOAS를 사용하면 클라이언트 페이지의 링크에 대한 URI를 구성하지 않아도됩니다.
James McLeod

답변:


24

우리가 구축하는 앱은 단순히 링크를 보지 않고 자체적으로 올바른 UI를 렌더링하고 올바른 아약스 호출을합니다.

사실, 이것이 바로 HATEOAS UI 제공 할 입니다. 아니 무엇 가능하지만, 경우 는 가능하다. 질문에서 알 수 있듯이 HAL 과 같은 공식 HATEOAS 는 가능한 것을 나타내는 링크를 제공합니다. 그러나 경우에 해당 링크가 표시 응용 프로그램의 상태에 따라 달라집니다. 따라서 링크는 시간이 지남에 따라 리소스에서 변경 될 수 있습니다 (이미 수행 된 작업을 기반으로 함).

이를 통해 가능한 모든 상태 가 포함 된 UI를 만들 수 있지만 해당 상태가 활성화 되는 시점 에는 신경 쓰지 않습니다 . 예를 들어,의 존재 rel="deposit"는 UI가 make deposit양식 을 렌더링해도 괜찮을 때 UI에 직접 알릴 수 있습니다 . 그러면 사용자가 값을 입력하고 링크를 사용하여 제출할 수 있습니다.


2
따라서 UI를 빌드 할 때 여전히 API가 제공하는 모든 것을 알고 있어야합니다. 그런 다음 링크를 보면 서버의 정보가 어떤 상태인지 알 수 있습니까? 예를 들어, UI는 입금, 출금, 이체 또는 마감이 가능하다는 것을 알고 (가능한 가능성을 알고 있음), 상태를 확인하기 위해 돌아온 것을 확인합니까?
user1620696

1
그렇습니다. 다시 말하지만 그것은 당신이 그것을 원하는 동적입니다. 다른 사람들이 언급했듯이 서버의 링크를 변경하고 클라이언트를 중단시키지 않는 기능은 또 다른 장점입니다. 그리고 API에 모두 사용하는 iPhone, Android, Windows Phone, 모바일 웹 및 웹 클라이언트가 있으면 API가 매우 흥미로워집니다 (다른 사용자가 클라이언트를 구축 할 수 있도록 API가 게시 된 경우는 말할 것도 없습니다).
Davin Tryon

@ user1620696 어쨌든 클라이언트와 서버를 통해 컨텐츠 유형을 설명하는이 모든 것을 알고 있어야합니다. 콘텐츠 유형은 멍청한 xml 또는 Json 이상입니다. 고객이 작업하는 방법을 이해하는 "은행 예금"컨텐츠 유형이 있어야합니다.
Cormac Mulhall

1
@Nik 은 응답에서 링크가 제공되는 방법에 대한 예를 보려면 HAL 을 살펴보십시오 .
Davin Tryon

1
예, 여전히 이전 버전과의 호환성 문제가 있습니다. URL에 버전 헤더 또는 버전을 포함 시켜서 해결할 수 있습니다. 그러나 나는 당신이 올바르게 이해하고 있다고 말할 것입니다.
Davin Tryon

3

현재 이해합니다 HATEOAS는 기본적으로 각 응답 링크와 함께 다음에 수행 할 작업에 대한 정보를 보내는 것입니다.

증오는 단순한 링크 그 이상입니다. 응용 프로그램 상태의 엔진으로서 "하이퍼 미디어"입니다.

설명에서 빠진 것은 클라이언트와 서버간에 전달되는 하이퍼 미디어의 공식적인 정의 인 컨텐츠 유형입니다.

HTML은 하이퍼 미디어의 예이며 HATEOS가 작동하는 이유의 예입니다. HTML 페이지 자체는 클라이언트 (예 : 사용자)가 사이트를 이동할 수 있도록하는 엔진입니다. HTML을 사용자에게 완전히 탐색 가능한 웹 사이트로 표시 할 수있는 기능을 갖춘 브라우저입니다. 단순히 다른 페이지에 대한 링크를 전달하는 것이 아니라 링크에 컨텍스트를 제공하고 브라우저가 탐색 가능한 사이트를 구성 할 수있는 방식으로 의미있는 방식으로 링크를 전달합니다.

그리고 가장 중요한 것은 브라우저가 웹 사이트 자체에 대한 ZERO의 사전 이해를 통해이를 수행 할 수 있다는 것입니다. 브라우저는 HTTP 및 HTML 만 알고 있습니다. 이러한 간단한 이해를 바탕으로 뉴욕 타임즈를 사용자에게 제시하여 탐색 할 수 있습니다.

"사용자"가 다른 컴퓨터 프로그램 인 경우에도 마찬가지입니다. 하이퍼 미디어 자체는 탐색 컨텍스트를 정의해야합니다.


1
브라우저처럼 복잡하고 버그가 발생하기 쉬운 클라이언트를 구축해야한다는 의미가 아닙니까? 유연성은 종종 비용으로 복잡성을 초래합니다.
Andres F.

@AndresF. 당신이 것을 의미하지 않는다 있어야 또는 한다 그래서, 그것은 단지 당신이 원하는 또는 필요한 경우 동적으로 그것을 할 수있는 옵션을 제공 할 수.
Peteris

2
@nik 물론입니다. 내 머리 꼭대기에는 편안한 API를 통해 조상 정보를 제공하는 서비스가 있다고 상상해보십시오. 다양한 유형의 정보가있는 '개인'자원의 형식을 정의하지만 '형제'또는 '자매'또는 '어머니'와 같은 관계의 형태를 정의하는 컨텐츠 유형이 있습니다. 다른 Person 리소스에 대한 URI가 있어야합니다. HTTP 동사를 사용하고이 '개인'컨텐츠 유형을 이해하는 상당히 간단한 클라이언트는이 API를 탐색 할 수 있습니다. 특정 인물의 직계 후손을 모두 찾고 싶다고 가정 해 봅시다.
Cormac Mulhall

2
@nik이 클라이언트는 액세스 한 리소스의 콘텐츠 유형과 HTTP 동사 (GET, PUT, DELETE 등)를 이해해야하며이 API 가져 오기 및 업데이트 리소스를 탐색 할 수 있습니다. 그리고 더 중요한 것은 컨텐츠 유형을 이해하는 모든 클라이언트가 URI를 통해 다른 서버로 완전히 이동하여 그대로 유지할 수 있다는 것입니다. 그들은 어떤 서버와 통신하든 상관없이 리소스의 컨텐츠 유형에만 관심이 있고 이해하거나 이해하지 못합니다.
Cormac Mulhall

1
@Nik 따라서 이러한 상황에서는 원본 컨텐츠 유형 (Person v1)과 새로운 컨텐츠 유형 (Person v2)을 이해하는 서버가 있습니다. 클라이언트는 Person v1 만 이해합니다. 클라이언트는 서버에서 HTTP의 Accept 헤더를 통해 이해하는 컨텐츠 유형을 알려줍니다. 서버는 컨텐츠 협상을 사용하여 클라이언트가 지원하는 것을 전송할지 여부를 판별하며,이 경우 컨텐츠 유형 Person v1을 사용하여 자원을 리턴합니다. 이제이 오래된 컨텐츠 유형 지원을 중단하고 클라이언트에 406 오류를 보낼 수 있습니다. 최대한 노력하고 지원하는 것이 좋습니다.
Cormac Mulhall

2

동적으로 생성 된 인터페이스를 구축 할 필요가 없습니다. 좋을 수도 있지만 필요하지는 않습니다. 동적 인터페이스를 구축 할 수없는 경우 링크를 사용하면됩니다. 단점은 다시 백엔드에 하드 링크되어 있으며 변경 사항이 있으면 충돌한다는 것입니다.

동적 레이아웃을 사용하는 것은 매우 간단합니다.

links.forEach(function(link) {

  switch(link.rel) {

    case 'deposit':
      showDepositButton();
      break;

    case 'withdraw':
      loadWithdrawForm(link.href);
      showWithdrawButton();
      break;
  }

});

다음과 같이 클라이언트 코드에 저장됩니다.

if (balance <= 0 && negativeBalanceAllowed === false) {
  showWithdrawButton();
}

클라이언트를 변경하지 않고 허용 된 부정적 위치 (예 : 돈을 빌림)를 구현할 수 있습니다.


좀 더 강력한 예를 들어, 은행은 고객 측에 각 계정에 대한 한도가 무엇인지 알려주지 않고도 자신의 계정에 대해 변동 인출 한도를 제공 할 수 있습니다.
Bart van Ingen Schenau

맞습니다. 잔액 한도 결정을 원하는만큼 복잡하게 만들 수 있지만 여전히 클라이언트를 변경할 필요는 없습니다. 컨텐츠 유형과 같은 REST 파트를 사용하여이를 더 수행하면 다른보기를 표시 할 수 있습니다. 예를 들어 계정은 거래와 다릅니다. 주문형 코드도 흥미 롭습니다 (구현되지는 않았지만). 예를 들어 차용 견적서에 사용될 수 있습니다. 인터페이스에 간단한 계산기 기능을 제공 할 수 있으므로 클라이언트는 계산을위한 입력 만 구현하면됩니다. 백엔드부터 최신 상태로 유지됩니다.
Luc Franken

2
그러나 일반적으로 고객은 인출 할 수없는 이유를 알아야하므로 별도의 필드에있는 ENUM 또는 문자열을로 고객에게 보내야합니다 reason. 그리고 우리가 여전히 이것을 필요로한다면, 단순히 canWithdraw액션에 대한 링크 대신 다른 부울 필드 를 보내면 어떨까요? 또 다른 장점은 클라이언트를 건드리지 않고 액션의 URL을 변경할 수 있다는 것입니다. 그러나 .. URL을 변경해야하는 이유는 무엇입니까? 대부분의 경우 의미 또는 매개 변수 또는 요청 / 응답 형태 등이 약간 변경되므로 클라이언트를 변경해야합니다. 그래서, 나는 아직도 그것을 얻지 못했습니다-HATEOAS의 요점.
Ruslan Stelmachenko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.