"생각의 웹"입니다.


구글에서 Open API 설계를 담당하고 있는 샘 고토의 블로그 중 소개하고 싶은 포스트가 있어 아래와 같이 번역하여 공유합니다. 이 연구의 결과가 기계와 사람 간에 스마트한 웹 세상을 만들어 내고 IoT가 꿈꾸는 스마트한 세상을 만드는 데 도움이 되리라고 생각합니다. 


의역으로 인해 오역의 가능성이 있으니 더 많은 내용이 궁금하시면 아래 원문 글을 참고하시기 바랍니다. ;-)


http://blog.sgo.to/2014/02/rows.html


리소스 지향 웹 서비스 (ROWS)

리소스 지향 웹 서비스 (ROWS)란 리소스들에 대한 프로그램적인 검색, 기술(description) 그리고 호출이 자동으로 수행 되도록 하는 일련의 기술입니다.


이는 휴먼 웹과 프로그래머블 웹을 연결해 주고 웹이 어떻게 동작하는지에  - URL들과 REST라는 일관된(Uniform) 인터페이스. 여기서 URL의 R이 핵심 영역입니다.-  보다 적합하게 설계된 서비스 지향 아키텍쳐의 대안 중 하나입니다.  


이 포스트는 연재 글 중에 하나이며 읽기 전에 이 과 이 을 읽어 보길 권합니다.


이 글은 이 기술 명세를 보다 읽기 쉽도록 하기 위해 쓰였습니다. 


우리가 다시 풀고자 하는 문제는?

우리의 목표는 "휴먼 웹"과 "프로그래머블 웹"을 연결하는 것입니다. 따라서, 현재 우리가 현재 수작업으로 하고 있는 것들을 자동화하는 것에 도전하고자 합니다.

우리는 아직까지 다음 기술들을 도출하지 못했습니다:

  1. 각각 별개의 서비스에 대한 리소스 설계, 표현(representation) 포맷 그리고 리소스 간의 링크를 클라이언트에게 알려줄 수 있는 보편적인 프레임 워크

  2. RESTful 과 하이브리드 서비스들의 다양성을 기술할 수 있는 어휘를 가진 언어. 이 언어로 작성된 문서는 보편적인(generic) 웹 서비스 클라이언트 코드를 커스텀하게 작성된 포장개체(wrapper)처럼 동작하도록 생성할 수 있습니다. 보다 자세하게 말하면 우리는 클라이언트에게 다음과 같은 것들을 알려주어야 합니다:

    • 수행 가능한 동작의 의미(semantic)가 존재하는가?

    • 어떤 HTTP 메소드(method)가 사용되는가?

    • 요청의 형식(entity-body)는 어떻게 구성되었는가?

    • 호출 후 응답되기를 기대하는 것은 무엇인가?

어떻게 시작하는지부터 살펴보자

휴먼 웹은 브라우저를 이용해 URL이라는 리소스를 GET 요청함으로써 시작됩니다. 만일 콜 택시를 요청하기 위해서 필요한 사례를 들어 설명해보죠. 
아래는 브라우저 내부에서 일어나고 있는 일을 보여 줍니다.

GET /mountain-view HTTP/1.1
Host: www.yellowcab.com 

그러면 서버가 다음과 같이 응답하도록 구현할 수 있습니다:


HTTP/1.1 200 OK
Content-Type: text/html 

  1. <html>
  2. <body>
  3.  
  4. <span>Welcome to Yellow Cab Mountain View!</span>
  5.  
  6. <a href="/moutain-view/reservations">
  7. Click here to book a cab!
  8. </a>
  9.  
  10. </body>
  11. </html>

지금 정도로도 사람에겐 충분한 정보겠지만 컴퓨터가 이 웹 페이지 내용과 개구리에 관련된 웹 페이지와의 구분할 수 없습니다.


JSON-LD, microdata와 Schema.Org 삽입하기

컴퓨터가 이 페이지를 이해하도록 만드는 첫번째 과정은 이 페이지가 무엇인지에 대해 명확히 알려 주는 겁니다.


HTML 내에서 연결 데이터(linked-data)를 전송하기 위한 몇 가지 방안이 있는데 제가 선호하는 방식은 JSON-LD와 microdata*입니다.


* 제 생각엔 JSON-LD가 대용량의 복잡한 사례들에 대응하기 위한 보다 확장성 있는 방식이라고 보는 반면 microdata는 예제가 쉬워 쉽게 이해할 수 있습니다. 그래서 전 여기에서는 microdata를 사용할거지만 실제로는 JSON-LD를 훨씬 선호한다는 사실을 알아주셨으면 합니다.


안타깝게도 microdata나 JSON-LD 만으로는 충분치 않습니다. 택시 정거장에 대한 컴퓨터 처리가 가능한 기술이 필요하기 때문이죠.  이것을 schema.org에서 가져올 수 있습니다: shema.org는 세상에서 컴퓨터가 이해할 수 있는 방식으로 사물을 기술하는 어휘들을 제공하는 사이트입니다.


아래는 이 웹 페이지의 모습을 보여줍니다:


HTTP/1.1 200 OK
Content-Type: text/html
  1. <html>
  2. <body itemscope
  3. itemid="/mountain-view"
  4. itemtype="http://schema.org/TaxiStand" >
  5.  
  6. <span itemprop="description">
  7. Welcome to Yellow Cab Mountain View!
  8. </span>
  9.  
  10. <a itemprop="reservations"
  11. href="/mountain-view/reservations"
  12. itemscope itemtype="http://schema.org/ItemList">
  13. Click here to book a cab!
  14. </a>
  15.  
  16. </body>
  17. </html>

이제 제가 서두에서 필요로 하다고 제시한 기술들을 리마인드 해보죠. 이 JSON-LD / micro-data + schema.org 를 통해 컴퓨터가 이해할 수 있는 방식으로 사물을 기술하기 위한 보편적인 프레임워크를 제공할 수 있습니다. 


그 결과 컴퓨터는 이제 다음을 이해할 수 있습니다:

  • 이 리소스는 TaxiStand (택시 승차장) 입니다.
  • 이 택시 승차장은 기술(description)을 가지고 있습니다.
  • 이 택시 승차장은 예약 아이템 리스트 (ItemList of reservations)를 가지고 있습니다.
그러나 이것으로 할 수 있는 것을 이해하기에는 턱없이 부족합니다.

프로그래머블 웹으로의 연결

API에 존재하는 프로그래머블 웹을 컴퓨터가 발견하도록 하기 어렵습니다. 그래서 이 특정 택시 승차장을 택시 (yellow cab) API에서 찾을 수 있도록 링크를 추가해 보겠습니다:

  1. <body itemscope
  2. itemid="/mountain-view"
  3. itemtype="http://schema.org/TaxiStand" >
  4. <meta itemprop="alternate" itemscope
  5. itemtype="http://schema.org/ApiUrl"
  6. content="http://api.yellowcab.com/moutain-view"/>


이로서 이 택시 서비스가 특정 API에 연결되어 있음을 컴퓨터가 알 수 있게 되었습니다.
만일 저 URL에 GET 요청을 하게 되면 다음과 같은 일이 일어나게 됩니다:

GET /mountain-view HTTP/1.1
Host: api.yellowcab.com

그리고 서버는 다음과 같이 응답합니다:


HTTP/1.1 200 OK
Content-Type: application/json+ld
  1. {
  2. "@context": "http://schema.org",
  3. "@type": "TaxiStand",
  4. "@id": "/mountain-view",
  5. "description": "Welcome to Yellow Cab!",
  6. "reservations": {
  7. "@type": "ItemList",
  8. "@id": "/mountain-view/reservations",
  9. }
  10. }

이 응답은 컴퓨터가 이해할 수 있는 형식에 훨씬 가깝습니다. 

Content-Type 헤더가 있어 컴퓨터가 어떻게 이것을 분석(parse)할 수 있는지 알려주고 또한 내부의 하이퍼미디어가 이 리소스를 컴퓨터가 이해할 수 있는 정보 (machine-readable information)를 제공하기 때문입니다.


하지만, 컴퓨터가 이 리소스들로 무엇을 할 수 있을지 알려 줄수도 있을까요?


만일 예약을 하고 싶다면 HTTP로 어떻게 해야 하지?

HTTP에서 API 검색 기법에 가장 가까운 방식은 OPTIONS 요청을 보내는 것입니다.


OPTIONS /mountain-view/reservations HTTP/1.1
Host: api.yellowcab.com

그러면 다음과 같이 응답할 수 있겠죠:

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST

POST 요청은 많은 일들을 할 수 있도록 설계되었기에 "RESTful Web API"의 저자들 (리처드슨, 샘 그리고 마이크, 이후 LSM으로 명기)이 앞서 지적했던 것처럼 이로써는 충분하지 않습니다. 어떻게 이런 것들을 알 수 있을까요:

  1. POST 요청의 내용(entity-body)은 무엇을 채워야 하는가?
  2. POST 요청이 중첩된 POST 요청(예를 들어 RPC-형태의 POST)인지을 어떻게 구분할 수 있을까?

액션 (Actions)를 추가하기

액션은 리소스로 무엇을 할 수 있는지 알려주는 어휘입니다. 이것은 추가 요청을 하는 것이 아닌 리소스에 추가 삽입(attached inline)하는 형태입니다.

이것은 중요한 세 가지의 기법으로 구성됩니다:
  1. 사물에 액션을 연결하는 기법

  2. 액션을 분류하고 요청을 강제하기 위한 잘 정의된 의미(semantics)

  3. 매개 변수가 어떻게 생겼는지를 기술하는 어휘
JSON-LD 응답이 어떻게 생겼는지 보시죠:


HTTP/1.1 200 OK
Content-Type: application/json+ld
  1. {
  2. "@context": "http://schema.org",
  3. "@type": "TaxiStand",
  4. "@id": "/mountain-view",
  5. "description": "Welcome to Yellow Cab!",
  6. "reservations": {
  7. "@type": "ItemList",
  8. "@id": "/mountain-view/reservations",
  9. "operation": {
  10. "@type": "CreateAction",
  11. "expects": {
  12. "@type": "SupportedClass",
  13. "subClassOf": "http://schema.org/TaxiReservation",
  14. }
  15. }
  16. }
  17. }

이 정보와 동일한 정보를 HTML 마크업에서도 찾을 수 있습니다:

  1. <a itemprop="reservations"
  2. href="/mountain-view/reservations"
  3. itemscope itemtype="http://schema.org/ItemList">
  4. <meta itemprop="alternate" itemscope
  5. itemtype="http://schema.org/ApiAppUrl"
  6. content="http://api.yellowcab.com/moutain-view/reservations" />
  7. <div itemprop="operation" itemscope
  8. itemtype="http://schema.org/CreateAction"/>
  9. <meta itemprop="expects" itemscope
  10. itemtype="http://schema.org/SupportedClass"
  11. content="http://schema.org/TaxiReservation"/>
  12. </div>
  13. </div>
  14. Click here to book a cab!
  15. </a>
* 이 형태가 꽤나 복잡해 보인다는 점 인정합니다만 이후에 이걸 더 요약하는 법 또한 소개하도록 하겠습니다. 힌트는 링크드 데이터와 연관되어 있습니다.

이제 컴퓨터가 이해하는 데 필요한 *모든 것*을 알려줄 수 있습니다:

  • 이것은 택시 승차장입니다.
  • 여기에 API 시작 위치가 있습니다. http://api.yellowcab.com/moutain-view/
  • 이 택시 승차장은 예약 아이템 리스트를 가지고 있습니다.
  • 이 예약 아이템 리스트에는 *매우* 상세한 의미(semantics)를 갖는 - 이 요청이 갖는 의미 뿐 아니라 세부 상세 내용까지 포함된 - 액션 생성(CreateAction)이라는 동작을 갖습니다. 예를 들어 이렇게 정의된 동작은 엄격한 POST 요청이 되겠지요.
  • 예약을 하기 위해서는 택시 예약 객체(TaxiReservation)를 전달합니다.
즉, 이 정보를 통해 컴퓨터는 다음과 같은 요청을 보낼 수 있게 됩니다:

POST /mountain-view/reservations HTTP/1.1
Host: api.yellowcab.com
Content-Type:application/json+d;charset=utf-8
Content-Length:207
  1. {
  2. "@context": "http://schema.org/",
  3. "@type": "TaxiReservation",
  4. "pickUpLocation":
  5. "1600 Amphitheatre Parkway, Mountain View, CA",
  6. "pickUpTime": "2pm",
  7. "numberOfPassengers": "1"
  8. }

그러면 서버는 다음과 같이 응답을 하게 되겠지요:

HTTP/1.1 201 Created
Location:
http://api.yellowcab.com/moutain-view/reservations/32523325225


이렇게 다시 하이퍼 미디어가 도래합니다.

하이퍼미디어는 정말 엄청나게 위력있는 개념입니다. 이 개념을 통해 하나의 리소스에서 다음 리소스 링크로 이동할 수 있게 됩니다. 정말 대단한 거죠.

방금 하나의 리소스를 생성했다면 이걸로 해볼 수 있는 최선을 한번 고려해 봅시다:

OPTIONS /mountain-view/reservations/32523325225 HTTP/1.1
Host: api.yellowcab.com


그럼 서버는 이렇게 응답할 수 있겠죠:

HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, PATCH
Accept-Patch: application/json+ld

이 응답의 PATCH HTTP 메소드로 인해 이 리소소는 변경되기 쉬운 (mutable) 리소스라는 걸 알 수 있다는 것이 꽤 흥미로운 점이죠. 또한 이 리소스는 추가로 JSON-LD 패치 문서를 가지고 있다고 알려 주기때문에 이 역시 꽤 유익한 정보가 될 겁니다.


그러나, POST 요청이 그렇듯 PATCH 동작의 어플리케이션 의미(semantics)가 무엇인지
 충분히 알 수는 없습니다. 예를 들어 "패치"가 pick up 시간을 업데이트하는 것인지 아니면
location을 전달(drop off) 하는지 말이죠.


액션으로 되돌아 가보죠. 이 리소스를 GET 요청합시다:


GET /mountain-view/reservations/32523325225 HTTP/1.1
Host: api.yellowcab.com

그러면 서버는 이렇게 응답해 줄 수 있습니다:

HTTP/1.1 200 OK
Content-Type: application/json+ld
Accept: application/json+ld
  1. {
  2. "@context": "http://schema.org",
  3. "@type": "TaxiReservation",
  4. "@id": "/mountain-view/reservations/32523325225",
  5. "reservationStatus": "CONFIRMED",
  6. "operation": {
  7. "@type": "CancelAction"
  8. }
  9. }

여기에 취소(CancelAction) - "미래의 사건이나 행위가 더 이상 일어나지 않도록 하는 행위" - 라는 매우 명확한 어플리케이션 의미를 가지고 있고 이 리소스를 "취소" 하는 의미가 매우 명확히 정의(HTTP 용어에서는 "취소"의 정의에 관련된 것은 PATCH 요청입니다.)되어 있으며 따라서 컴퓨터는 다음과 같이 PATCH 요청을 보낼 수 있기 때문입니다:

PATCH /mountain-view/reservations/32523325225 HTTP/1.1
Host: api.yellowcab.com
Content-Type:application/json+d;charset=utf-8
Content-Length:100
Accept: application/json+ld

  1. {
  2. "@context": "http://schema.org/",
  3. "@type": "CancelAction"
  4. }

이제 취소된 예약 상태를 알 수 있습니다:


HTTP/1.1 200 OK
Content-Type: application/json+ld

  1. {
  2. "@context": "http://schema.org",
  3. "@type": "TaxiReservation",
  4. "@id": "/mountain-view/reservations/32523325225",
  5. "reservationStatus": "CANCELLED",
  6. }

마지막으로 덧붙이면 취소를 완료하게 되면 취소된 예약에는 적용되지 않기 때문에 "취소" 요청의 내용은 사라지게 됩니다.


남은 숙제들...

"악마는 디테일에 있다"는 말처럼 아직 모음(collections), 인증(authentication), 상이한 전송 기법 - 예를 들면 모바일 앱, 이메일 메세지 - 등이 어떻게 되어야 하는지는 숙제로 남겨져 있습니다. 이 하나 하나 모두 풀기에 매우 까다로운 것들이기 때문이죠.


추후 올릴 포스팅에도 계속적으로 관심 가져 주시기를 바랍니다. 감사합니다.

웹 서비스가 스스로 새로운 웹서비스를 만들어가는 스마트한 IoT 세상을 꿈꾸는 "생각의 웹"입니다.


웹 세상에서 REST API가 Open API의 대세로 자리 매김한지도 꽤 시간이 지났음에도

진정 RESTful API를 설계하는 일이 여전히 쉽지 않습니다.

따라서 이전에 포스트에서 REST API의 성숙도를 표현하는 리처드슨의 성숙도 모델이 있다는 것 소개드린 바 있습니다.


http://webofthink.tistory.com/2


이번 포스트에서는 REST API의 대가인 리처드슨, 아문센 그리고 샘 루비가 오레일리 출판사를 통해 작년 말에 내 놓은 RESTful Web API에서 발췌한 REST API를 설계하는 절차를 소개하려 합니다.


먼저, 발췌한 해당 내용의 스크린 샷을 이미지 슬라이드로 보여 드리죠.


012345678910111213


책에서는 API를 설계하는 서로다른 두 가지 절차를 소개합니다. 첫번째는 두 단계로 이뤄진 요약이고 두 번째는 일곱 단계로 이뤄진 상세한 내용이라고 할 수 있습니다.


전자에 대해 정리하면 다음과 같습니다.


  1.  HTTP 요청에 대한 응답 body에 표현 (representation)으로 사용할 미디어 형태 (media type)을 선택한다. 이 선택으로 말미암아 프로토콜 의미 (protocol semantics) - HTTP 프로토콜 하에서 API의 동작 - 와 어플리케이션 의미 (application semantics) - 표현으로 참조할 수 있는 실제 세계의 사물 -  에 제약을 받게 된다.

  2. 나머지 모든 것을 대응할 수 있는 프로파일 (profile)을 작성한다.

REST API에 대해 설계한 경험이 없다면 이 두 단계로 함축한 것으로는 이해하기가 어려울 것으로 사료됩니다. 이 책을 읽고 포스트를 작성하는 저 스스로도 잘 와닿지 않기 때문입니다. ^^;

이번에는 좀 더 상세한 단계를 설명해 주고 있는 후자에 대해서 살펴 보시죠.

  1.  클라이언트(client) - REST API를 호출할 웹 앱 - 이 알아야 하거나 API에 담고자 하는 모든 정보를 나열한다. 이 정보가 추후 의미 기술 (semantic descriptors)이 되며 계층적 구조를 갖게 됩니다. 예를 들어 '사람'과 같은 오브젝트는 보다 추상적인 '성'과 같은 상세 정보를 갖게 되는데 이런 정보 간 계층이 직관적으로 묶일 수 있도록 합니다. 

  2. API를 위한 상태 전이도 (state diagram)를 그립니다. 이 도식에서 칸은 하나의 표현 - 의미 기술의 일부를 함께 묶은 문서 - 을 나타냅니다. 클라이언트가 이런 표현들을 자연스럽게 찾을 수 있도록 화살표를 이용해 표시합니다. 이 화살표는 HTTP 요청에 따른 상태 전이 (state transitions)이 됩니다.

  3. 의미 기술에 사용한 임의의 용어 (magic strings)를 기존 프로파일(profile)에 존재하는 용어로 대체합니다. 이때 사용한 모든 단어와 두번째 단계에서 그린 상태 전이도에 모두 적용될 때까지 반복합니다.

  4. 프로토콜 의미와 어플리케이션 의미에 부합하는 (compatible) 미디어 형식 (media type)을 선정하거나 필요할 경우 새로 만듭니다. 운이 좋다면 기 정의된 미디어 형식으로 어플리케이션 의미의 상당 부분을 대응할 수 있으며 이때 세 번째 단계로 되돌아 가서 미디어 형식의 용어가 대응하는지 다시 살펴봅니다.

  5. 어플리케이션 의미를 기술하는 프로파일을 작성합니다. 이 프로파일에는 당신만의 용어 (magic string), IANA에 등록된 링크 관계가 아닌 링크 관계들과 미디어 형식에 의해 기술된 용어를 담고 있어야 합니다.

  6.  세번째 단계에서 도출한 상태 전이도를 HTTP 서버로 구현하기 위한 코드를 작성합니다. 클라이언트는 특정 HTTP 요청으로 상태를 전이시키게 되고 그 결과로 응답을 전송받게 됩니다. 이 응답의 표현에는 4번째 단계에서 정의한 미디어 형식과 5번째 단계에서 정의한 프로파일에 대한 링크가 포함되어야 합니다. 

  7.  API를 사용하기 위한 접속 주소가 되는 빌보드 URL를 제공합니다. 또한 개발자를 위한 API 문서, 튜토리얼 및 예제 클라이언트 코드를 제공할 수도 있습니다.

API를 설계하는 일은 사용자를 고려한 UX를 설계하는 일처럼 어려운 일입니다. 특히, API를 사용하는 주체가 사람 뿐 아니라 기계일 경우는 더욱 그렇습니다.

프로그래머블 웹이 현실이 되고 인터넷에 연결된 IoT 기기가 시장에 본격적으로 등장하면서 진정 스마트한 기기를 만들기 위해서는 스마트한 API를 만들 수 있는 기술이 필요합니다.

이 설계 방법이 스마트한 웹 세계를 만들 것이라 기대해 봅니다.
감사합니다. 


안녕하세요. '생각의 웹'입니다.


한국의 테크 샵인 대디스랩 지원에 힘입어 빠르게 프로토타이핑한 '홈 센서 프레임워크'을 소개합니다.

'홈 센서 프로임워크'는 스마트 홈 환경에서 사용자에게 필요한 서비스를 발굴하기 위해 데이터를 모으고 데이터를 분석해 컨텍스트를 발굴하기 위한 JavaScript 개발 환경입니다. 


 상세한 내용은 아래 슬라이드를 참고하시기 바랍니다.



덧붙여 제가 생각하는 이 프레임워크가 가지는 장점은 다음과 같습니다.

    • 오픈 소스 하드웨어를 이용해 스마트 홈 관련 아이디어를 손쉽게 DIY 
    • 웹 월드의 일등 시민인 JavaScript 만으로 서비스 개발 가능
    • Open API (RESTful Web API)와 연동한 서비스 개발 가능
    • 사생활 침해의 우려가 있는 민감한 컨텍스트 정보를 클라우드가 아닌 댁 내에 저장
    • HTML5 기반 멀티 스크린 (N-Screen) 서비스 ready   

개발 관련해서 궁금한 점이나 아이디어 있으시면 댓글로 남겨주세요.


감사합니다.


덧글1. 

라즈베리 파이에서 MySQL 설치가 제대로 되지 않을 경우, 아래 링크를 참고하시기 바랍니다.

http://likeplex.com/Blog/Archives/92


덧글2. 

'밸브의 신' 덕분에 의도치 않게 이 슬라이드가 관심을 많이 받게 되었네요.

슬라이드를 보고 진행하시다가 막히는 부분을 댓글로 연락처와 함께 남겨주시면 A/S 해드리도록 하겠습니다. 







+ Recent posts