웹 사물(WoT) 프로파일

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-wot-profile-20251104/
최신 발행 버전:
https://www.w3.org/TR/wot-profile/
최신 편집자 초안:
https://w3c.github.io/wot-profile/
이력:
https://www.w3.org/standards/history/wot-profile/
커밋 이력
편집자:
Michael Lagally (Oracle Corp.)
Ben Francis (초빙 전문가)
Sebastian Kaebisch (Siemens AG)
Tomoaki Mizushima (Internet Research Institute, Inc.)
전 편집자:
Michael McCool (Intel Corp. 재직 당시)
Ryuichi Matsukura (Fujitsu Ltd. 재직 당시)
피드백:
GitHub w3c/wot-profile (풀 리퀘스트, 새 이슈, 열린 이슈)
public-wot-wg@w3.org로 제목 줄에 [wot-profile] … 메시지 주제 …를 포함 (아카이브)
기여자
GitHub 저장소에서 확인

초록

이 명세는 프로파일링 메커니즘프로파일 집합을 정의하며, 이는 Web Thing과 그 ConsumerWeb of Things에서 즉시 사용 가능한 상호 운용성을 갖도록 합니다.

즉시 사용 가능한 상호 운용성이란, 주어진 Profile을 준수하는 모든 Consumer가 동일한 Profile을 준수하는 모든 Thing과 추가적인 사용자 지정 없이 상호작용할 수 있음을 의미합니다.

Profile은 준수하는 ConsumerThing이 따라야 하는 일련의 단언을 제공하는 기술 명세입니다.

프로파일링 메커니즘은 주어진 Thing이 하나 이상의 Profile을 준수함을 표시하는 수단을 제공하며, 이는 해당 Profile의 식별자를 그 Thing Descriptionprofile 멤버에서 참조함으로써 이루어집니다.

이 명세는 세 가지 프로파일을 정의합니다:

이 명세에서 정의하는 Profile들은 해당 Profile의 구현도 준수해야 하는 일련의 공통 제약을 공유합니다. 여기에는 단위, 날짜 형식, 보안 메커니즘, 발견 메커니즘, 링크 관계 및 오류에 대한 제약이 포함됩니다.

이 명세의 향후 버전이나 확장 명세에서는 추가 Profile을 정의할 수 있습니다.

이 문서의 상태

이 절은 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

이 문서는 Web of Things Working Group에 의해 Recommendation 트랙을 사용하여 Working Draft로 발행되었습니다.

Working Draft로 발행되었다고 해서 W3C와 그 회원들이 이를 승인했음을 의미하지는 않습니다.

이 문서는 초안 문서이며 언제든지 업데이트되거나, 대체되거나, 다른 문서에 의해 폐기될 수 있습니다. 이 문서를 진행 중인 작업 이외의 것으로 인용하는 것은 부적절합니다.

이 문서는 W3C Patent Policy에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 해당 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지합니다. 그 페이지에는 특허를 공개하는 방법에 대한 지침도 포함되어 있습니다. 실제로 알고 있는 특허가 Essential Claim(s)을 포함한다고 믿는 개인은 W3C Patent Policy의 제6절에 따라 해당 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C Process Document의 적용을 받습니다.

1. 소개

1.1 동기

Web of Things (WoT)는 기존의 표준화된 웹 기술을 사용하고 확장함으로써 Internet of Things (IoT)의 파편화에 대응하고자 합니다.

W3C WoT Thing Description [wot-thing-description11] 명세는 연결된 장치의 기능과 해당 장치와 통신하기 위한 인터페이스를 설명하는 정보 모델과 JSON 기반 표현 형식을 정의합니다. Thing Description은 프로토콜에 구애받지 않도록 설계되었으며, 기존의 광범위한 ("브라운필드") IoT 장치를 설명할 수 있을 만큼 유연합니다.

이러한 수준의 유연성을 제공하기 위해 Thing Description 명세에는 프로토콜 바인딩, 페이로드 바인딩, 보안 메커니즘, 링크 관계 및 의미적 컨텍스트를 비롯한 여러 확장 지점이 포함되어 있습니다. 장치의 모든 기능을 Thing Description을 사용하여 설명할 수 있고, Consumer가 사용된 모든 확장을 구현하는 한, 해당 Consumer는 그 장치와 상호 운용할 수 있어야 합니다. 그러나 이러한 확장 가능한 아키텍처의 결과로, 임의의 주어진 Consumer는 가능한 Web Thing의 일부 집합과만 상호 운용할 수 있습니다.

이 명세는 "Profile"을 사용하여 임시적 상호 운용성을 가능하게 함으로써 Thing Description [wot-thing-description11] 명세를 보완하도록 설계되었습니다. Profile은 해당 profile을 구현하는 모든 Consumer와의 즉시 사용 가능한 상호 운용성을 보장하기 위해 Thing이 따라야 할 유한한 확장 및 기본값 집합을 규정합니다.

Profile은 특히 개발자가 규정적인 프로토콜 바인딩과 공통 제약 집합을 준수할 자유가 있는 새로운 ("그린필드") 구현을 위해 설계되었으며, 이를 통해 추가적인 수준의 상호 운용성에서 이점을 얻을 수 있습니다.

이 명세의 향후 버전이나 확장 명세에서는 추가 Profile을 정의할 수 있습니다.

1.2 사용 사례 및 요구사항

Web of Things Interest Group은 여러 다양한 산업을 대표하는 이해관계자들로부터 Web of Things에 대한 사용 사례를 수집했습니다. 여기에는 수직적인 도메인별 사용 사례와 여러 응용 도메인에 적용되는 수평적 사용 사례가 모두 포함됩니다 [wot-usecases].

여러 도메인별 사용 사례는 여러 공급업체의 장치를 쉽게 통합해야 할 필요성을 언급합니다. 이는 "다중 공급업체 시스템 통합"과 "즉시 사용 가능한 상호 운용성"을 요구하는 교차 도메인 사용 사례에서 특히 중요합니다.

이러한 사용 사례로부터 Profile에 대한 요구사항 집합이 도출되었습니다.

1.3 즉시 사용 가능한 상호 운용성

높은 수준에서, 즉시 사용 가능한 상호 운용성이란 Consumer가 Thing별 사용자 지정 없이 Thing의 모든 기능을 사용할 수 있음이 보장된다는 뜻입니다.

이 명세에서 사용하는 즉시 사용 가능한 상호 운용성의 전체 정의에는 여러 계층이 포함됩니다. 다음 분류는 "H2020 - CREATE-IoT Project - Recommendations for commonalities and interoperability profiles of IoT platforms" [H2020-CREATE-IoT] 보고서의 용어를 채택합니다. 아래 정의는 WoT profile의 범위를 반영하도록 조정되었습니다.

1.3.1 기술적 상호 운용성

기술적 상호 운용성은 일반적으로 통신 프로토콜 및 그 프로토콜이 동작하는 데 필요한 인프라와 관련됩니다. 이는 공통 프로토콜(예: HTTP / TCP/IP)에 합의하고, 필요한 경우 추가적인 명확화를 제공하는 것을 의미합니다.

1.3.2 구문적 상호 운용성

구문적 상호 운용성은 일반적으로 데이터 형식과 인코딩, 그리고 이를 압축하기 위한 기법과 관련됩니다. WoT에서 이러한 형식 및 인코딩의 예로는 JSON, XML, JSON-LD, UTF-8 페이로드가 있습니다.

1.3.3 의미적 상호 운용성

의미적 상호 운용성은 통신 파트너의 동작에 대한 공통 이해와 관련됩니다. profile 컨텍스트에서는 (동기 및 비동기) action 의미론에 대한 공통 해석, 공통 event 모델, 여러 property를 설정/가져오는 방법, 쓰기 가능한 property, 공통 오류 모델 및 오류 메시지를 포함합니다.

도메인별 온톨로지, 예를 들어 자동차 및 의료 장치의 의미적 상호 운용성은 이 명세의 범위를 벗어납니다.

1.3.4 조직적 상호 운용성

profile 컨텍스트에서 조직적 상호 운용성은 주어진 profile을 준수하는 모든 Consumer가 동일한 Profile을 준수하는 모든 Thing과 추가적인 사용자 지정 없이 상호작용할 수 있음을 의미합니다.

조직적 상호 운용성은 또한 보안, 신뢰 및 개인정보 보호에 대해 공통적으로 합의된 접근 방식을 요구합니다. 즉, Consumer는 이러한 공통 조건이 적용되는 경우에만 Things에 대한 접근 권한을 제공받습니다.

다양한 엔지니어, 공급업체 및 SDO가 만든 장치가 profile 명세의 요구사항을 충족하는 경우, 추가적인 사용자 지정 없이 적합한 Consumer와 통합될 수 있습니다. 이는 인프라, 지역 및 문화를 넘어서 동작합니다.

2. 적합성

비규범으로 표시된 절뿐만 아니라, 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고는 비규범입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.

이 문서에서 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, SHOULD, 및 SHOULD NOT이라는 핵심 단어는 여기에 표시된 것처럼 모두 대문자로 나타날 때, 그리고 오직 그 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석됩니다.

Thing 또는 Consumer 구현은 현재 문서의 규범적 진술을 따르는 경우 이 명세를 준수합니다.

3. 용어

Web Thing (Thing), Consumer, Thing Description, Property, Action, EventProtocol Binding과 같은 기본적인 WoT 용어는 WoT Architecture 명세 [wot-architecture11]의 3절에 정의되어 있습니다.

3.1 추가 정의

Profile
일련의 단언을 제공하는 기술 명세로, 그 단언을 준수하는 모든 Consumer는 해당 단언을 또한 준수하는 모든 Thing즉시 사용 가능한 상호 운용성을 갖습니다.

4. 프로파일링 메커니즘

Profile을 준수하려면, Web ThingProfile 명세의 모든 규범적 진술을 준수해야 MUST 합니다.

주어진 Web Thing이 하나 이상의 Profile을 준수함을 표시하려면, 그 Thing Description profile 멤버를 포함해야 MUST 합니다 [wot-thing-description11]. profile 멤버의 값은 단일 Profile을 식별하는 유효한 URI [RFC3986]이거나, 여러 Profile을 식별하는 유효한 URI의 배열로 설정되어야 MUST 합니다.

Thing Description에서 profile 멤버를 사용하려면, @context 멤버는 해당 문서가 Thing Description 명세 버전 1.1을 사용하고 있음을 표시하기 위해 anyURI https://www.w3.org/2022/wot/td/v1.1을 포함해야 MUST 합니다. [wot-thing-description11].

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "urn:dev:ops:32473-WoTLamp-1234",
  "profile": "https://www.w3.org/2022/wot/profile/http-basic/v1",
  "title": "My Lamp",
  "description": "A web connected lamp",
  ...
}
{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "urn:dev:ops:32473-WoTLamp-1234",
  "profile": [
    "https://www.w3.org/2022/wot/profile/http-basic/v1",
    "https://www.w3.org/2022/wot/profile/http-sse/v1"
  ],
  "title": "My Lamp",
  "description": "A web connected lamp",
  ...
}

Profile을 준수하는 모든 ThingConsumer는 WoT Thing Description 1.1 명세 [wot-thing-description11]에 명시된 단언을 충족해야 MUST 하며, 단, "TD 1.1 consumers MUST accept TDs satisfying the W3C WoT Thing Description 1.0 [wot-thing-description] specification."라는 텍스트의 단언은 제외합니다.

Profile은 프로토콜 바인딩 템플릿 [wot-binding-templates]의 기본값을 재정의해서는 안 됩니다 SHOULD NOT. 예를 들어 profile이 HTTP 프로토콜 바인딩을 사용하고 HTTP Binding Template이 HTTP 프로토콜 바인딩에서 readproperty 작업의 htv:methodName 기본값이 GET이라고 명시하는 경우, profile은 해당 값을 POST로 재정의해서는 안 됩니다.

Profile은 해당 Profile을 구현하지 않은 Consumer에게 예상 밖일 수 있는 방식으로 Thing이 응답하도록 요구해서는 안 됩니다 SHOULD NOT. 예를 들어 Profilequeryaction 작업에 대한 프로토콜 바인딩의 세부사항을 정의할 수 있으며, 이는 (WoT Thing Description 1.1 명세의 현재 제한으로 인해) 현재 Thing Description의 프로토콜 바인딩 템플릿을 사용해서는 완전히 설명할 수 없지만, 적합한 Consumer가 소비할 수 있습니다. 그러나 Thing Description에 노출된 다른 action 관련 작업은 해당 Profile을 구현하지 않은 Consumer가 예상하는 방식으로 여전히 응답해야 합니다.

참고

Profile을 준수한다고 해서 Web Thing이 그 Thing Description에서 Profile에 설명된 것 이상의 추가 기능 및 프로토콜 바인딩을 설명하는 것이 금지되지는 않습니다. 단, 해당 Profile의 모든 규범적 단언을 준수해야 합니다.

참고

Thing Description이 자신이 설명하는 Thing이 주어진 Profile을 준수한다고 주장한다고 해서, Consumer가 실제로도 준수한다고 가정해서는 안 됩니다. 예를 들어 ConsumerThing이 주어진 작업에 대해 명시된 대로 응답하지 않더라도 정상적으로 복구할 수 있어야 합니다.

5. 공통 제약

다음 절은 이 문서에서 정의하는 profiles에 적용됩니다.

5.1 단위

Thing Description 작성자는 자신의 지리적 지역에서 일반적인 단위가 전 세계적으로 적용될 수 있는 것은 아니며, 심각한 결과를 초래하는 오해로 이어질 수 있음을 인식해야 합니다.

값이 물리량을 갖는 경우 unit을 제공하는 것이 매우 RECOMMENDED됩니다.

전 세계 배포에 사용되는 장치에는 미터법(SI 단위)을 사용하는 것이 매우 RECOMMENDED됩니다.

5.2 날짜 형식

달리 명시되지 않는 한, 모든 날짜 및 시간 값은 [RFC3339]에 정의된 date-time 형식을 사용해야 MUST 합니다.

2022-09-21T23:20:50.52Z
참고

모호성을 줄이기 위해 RFC 3339는 00부터 23까지(24가 아님)의 값을 갖는 시(hour)만 허용하며, 시간대는 UTC에 대한 수치 오프셋으로 표현됩니다. 시간에 적용된 접미사 "Z"는 UTC 오프셋 00:00을 나타냅니다.

5.3 보안

적합한 Web Thing은 다음 보안 스킴 [wot-thing-description11] 중 하나 이상을 사용해야 MUST 합니다:

  • NoSecurityScheme
  • BasicSecurityScheme
  • code 또는 client flow를 사용하는 OAuth2SecurityScheme

적합한 Consumer는 다음 보안 스킴 [wot-thing-description11]을 모두 지원해야 MUST 합니다:

  • NoSecurityScheme
  • BasicSecurityScheme
  • code 또는 client flow를 사용하는 OAuth2SecurityScheme
  • 위 스킴 중 하나 이상을 포함하는 oneOf 멤버를 갖는 ComboSecurityScheme

Thing은 여러 보안 스킴을 구현할 수 MAY 있습니다.

Thing이 여러 보안 스킴을 지원하는 경우, 한 번에 하나의 보안 스킴만 사용하면 되도록 해당 스킴들을 oneOf 멤버로 열거하기 위해 ComboSecurityScheme을 사용해야 MUST 합니다.

BasicSecurityScheme의 경우 "in" 필드는 생략되거나, [wot-thing-description11]에 정의된 기본값 "header"가 주어져야 MUST 합니다. BasicSecurityScheme의 경우 "proxy" 엔드포인트가 주어지지 않으면 "name" 필드는 "Authorization" 값을 사용하여 제공되어야 MUST 합니다. BasicSecurityScheme의 경우 "proxy" 엔드포인트가 주어지면 "name" 필드는 "Proxy-Authorization" 값을 사용하여 제공되어야 MUST 합니다.

적합한 Consumer는 WoT Discovery [wot-discovery] 명세의 Security Bootstrapping에 정의된 대로, 구현된 모든 보안 스킴에 대한 보안 부트스트래핑을 지원해야 MUST 합니다.

ThingThing Description을 가져오기 위해 인증을 요구하는 적합한 Things는 WoT Discovery [wot-discovery] 명세의 Security Bootstrapping에 정의된 대로 보안 부트스트래핑을 구현해야 MUST 합니다.

5.4 발견

Web ThingThing Description [wot-thing-description11]은 Direct Introduction Mechanism [wot-discovery]이 제공하는 HTTP URL [RFC9110]을 사용하여 Thing Description Server [wot-architecture11]에서 검색 가능해야 MUST 합니다.

5.6 오류

HTTP profiles의 프로토콜 바인딩에서 정의된 작업 중 하나라도 성공하지 못하면 Web Thing은 실패 이유를 설명하는 HTTP 오류 코드가 포함된 HTTP 응답을 보내야 MUST 합니다.

오류 응답은 다음 HTTP 오류 코드 중 하나를 사용하는 것이 RECOMMENDED됩니다:

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 500 Internal Server Error
  • 503 Service Unavailable

Web Thing은 리디렉션, 캐싱 또는 인증 목적으로 3xx 상태 코드로 응답할 수 MAY 있습니다. Web Thing300 Multiple Choices 상태 코드로 응답해서는 안 됩니다 MUST NOT.

Web Thing은 다른 유효한 HTTP 오류 코드 (예: 418 I'm a teapot)로 응답할 수 MAY 있습니다. Consumer는 다른 유효한 HTTP 오류 코드를 특별히 정의된 동작이 없는 일반적인 4xx 또는 5xx 오류로 해석할 수 MAY 있습니다.

HTTP 오류 응답에 본문이 포함되어 있는 경우, 그 본문의 내용은 Problem Details 형식 [RFC7807]을 준수해야 MUST 합니다.

6. HTTP Basic Profile

이 절은 HTTP Basic Profile을 정의하며, 여기에는 속성을 읽고 쓰며, 액션을 호출, 질의 및 취소하기 위한 Protocol Binding이 포함됩니다.

이 profile은 속성을 관찰하고 이벤트를 수신하기 위한 작업을 제공하기 위해 HTTP SSE Profile 또는 HTTP Webhook Profile과 함께 사용할 수 있습니다.

HTTP Basic Profile을 준수하려면 Web Things와 ConsumerCommon Constraints 절의 모든 단언도 준수해야 MUST 합니다.

6.1 식별자

주어진 Web Thing이 HTTP Basic Profile을 준수함을 표시하려면, 그 Thing Descriptionhttps://www.w3.org/2022/wot/profile/http-basic/v1 값을 갖는 profile 멤버 [wot-thing-description11]를 가져야 MUST 합니다.

6.2 프로토콜 바인딩

이 절은 Consumer가 HTTP 프로토콜 [RFC9112]을 통해 JSON [JSON] 페이로드를 사용하여 Web Thing [wot-architecture11]과 통신하는 방식을 설명하는 Protocol Binding을 정의합니다.

HTTP Basic Profile을 준수하는 Consumer 또는 Web Thing은 이 프로토콜 바인딩을 구현해야 MUST 합니다.

이 절 전체에서 제공되는 예제는 다음 Thing Description을 생성하는 Web ThingConsumer가 어떻게 통신하는지를 설명합니다:

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": "https://www.w3.org/2022/wot/profile/http-basic/v1",
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [{"href": "properties/on"}]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [{"href": "properties/level"}]
    }
  },
  "actions": {
    "fade": {
      "title": "Fade",
      "description": "Fade the lamp to a given level",
      "synchronous": false,
      "input": {
        "type": "object",
        "properties": {
          "level": {
            "title": "Brightness",
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "unit": "percent"
          },
          "duration": {
            "title": "Duration",
            "type": "integer",
            "minimum": 0,
            "unit": "milliseconds"
          }
        }
      },
      "forms": [{"href": "actions/fade"}]
    }
  },
  "forms": [
    {
      "op": ["readallproperties", "writemultipleproperties"],
      "href": "properties"
    },
    {
      "op": "queryallactions",
      "href": "actions"
    }
  ]
}

6.2.1 속성

6.2.1.1 readproperty

Property 값을 읽을 때 사용할 property 리소스의 URL은 Thing Description에서 해당 PropertyAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • 기본값이 적용된 후, 그 op 멤버가 readproperty 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 property 리소스의 URL로 사용되어야 MUST 합니다.

Property 값을 읽으려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 GET으로 설정
  • URL은 property 리소스의 URL로 설정
  • Accept 헤더는 application/json으로 설정
GET /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com
Accept: application/json

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, Consumer가 해당 Property를 읽을 권한이 있으면, Property 값을 성공적으로 읽은 후 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 application/json으로 설정
  • JSON으로 직렬화된 property 값을 포함하는 본문
HTTP/1.1 200 OK
Content-Type: application/json
false
6.2.1.2 writeproperty

Property 값을 쓸 때 사용할 property 리소스의 URL은 Thing Description에서 해당 PropertyAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • 기본값이 적용된 후, 그 op 멤버가 writeproperty 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 property 리소스의 URL로 사용되어야 MUST 합니다.

Property 값을 쓰려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 PUT으로 설정
  • URL은 property 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • JSON으로 직렬화된 property의 요청된 새 값을 포함하는 본문
PUT /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
true

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, Consumer가 해당 Property를 쓸 권한이 있으면, property 값을 성공적으로 쓴 후 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204로 설정
HTTP/1.1 204 No Content
6.2.1.3 readallproperties

모든 Properties 값을 한 번에 읽을 때 사용할 properties 리소스의 URL은 Thing Description에서 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 readallproperties 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 properties 리소스의 URL로 사용되어야 MUST 합니다.

모든 Properties 값을 읽으려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 GET으로 설정
  • URL은 properties 리소스의 URL로 설정
  • Accept 헤더는 application/json으로 설정
GET /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Accept: application/json

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면, Consumer가 접근 권한을 가진 모든 읽기 가능한 Properties 값을 성공적으로 읽은 후, 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 모든 읽기 가능한 properties의 값을 property 이름을 키로 하는 객체로 JSON 직렬화한 본문
HTTP/1.1 200 OK
Content-Type: application/json
{
  "on": false,
  "level": 100
}
6.2.1.4 writemultipleproperties

여러 Properties 값을 한 번에 쓸 때 사용할 properties 리소스의 URL은 Thing Description에서 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 writemultipleproperties 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 properties 리소스의 URL로 사용되어야 MUST 합니다.

여러 properties 값을 한 번에 쓰려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 PUT으로 설정
  • URL은 Properties 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 쓰기 가능한 Properties의 요청된 새 값을 property 이름을 키로 하는 객체로 JSON 직렬화한 본문
PUT /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  "on": true,
  "level": 50
}

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면, 요청된 쓰기 가능한 Properties 값을 성공적으로 쓴 후 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204로 설정
HTTP/1.1 204 No Content
참고

readmultipleproperties 작업은 요청 페이로드 형식의 복잡성 때문에, 그리고 readpropertyreadallproperties에 비해 많은 기능을 추가하지 않기 때문에 제외됩니다. writeallpropertieswritemultipleproperties의 특수한 경우일 뿐이므로 제외됩니다.

6.2.2 액션

6.2.2.1 invokeaction

Action을 호출할 때 사용할 action 리소스의 URL은 Thing Description에서 해당 ActionAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • 기본값이 적용된 후, 그 op 멤버의 값이 invokeaction입니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 action 리소스의 URL로 사용되어야 MUST 합니다.

Web Thing에서 Action을 호출하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 action 리소스의 URL로 설정
  • Accept 헤더는 application/json으로 설정
  • Content-Type 헤더는 application/json으로 설정(action에 입력이 있는 경우에만)
  • 있는 경우 action에 대한 입력을 JSON으로 직렬화한 본문
POST /things/lamp/actions/fade HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
Accept: application/json
{
  "level": 100,
  "duration": 5
}

action에 입력이 없으면 요청의 Content-type 헤더는 설정해서는 SHOULD NOT 안 되며, 본문은 비어 있어야 합니다.

참고

null, 빈 따옴표 ("") 또는 빈 중괄호({})와 같은 유효한 JSON 값은 유효한 action 입력일 수 있으며, "빈" 본문으로 간주되지 않습니다.

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면 세 가지 응답 형식 중 하나로 응답해야 MUST 합니다:

  1. 동기식 액션 응답
  2. 비동기식 액션 응답
  3. 오류 응답

ActionAffordancesynchronous 멤버는 true 또는 false로 설정되어야 MUST 합니다.

ActionAffordance [wot-thing-description11]의 synchronous 멤버가 true로 설정되어 있으면 Web Thing은 동기식 액션 응답으로 응답해야 MUST 합니다.

ActionAffordance [wot-thing-description11]의 synchronous 멤버가 false로 설정되어 있으면 Web Thing비동기식 액션 응답으로 응답해야 MUST 합니다.

HTTP 요청의 제한 시간 기간(예: 30초에서 120초) 내에 실행이 완료될 것으로 예상되지 않는 장기 실행 actions의 경우, 초기 invokeaction 응답 후 Consumer가 동적으로 생성된 ActionStatus 리소스에 대한 queryaction 작업으로 action 요청의 상태를 계속 모니터링할 수 있도록, Web Thing은 비동기식 액션 응답으로 응답하는 것이 RECOMMENDED됩니다.

HTTP 요청의 제한 시간 기간 내에 실행이 완료될 것으로 예상되는 단기 actions의 경우, Web Thing은 action이 완료될 때까지 기다렸다가 동기식 액션 응답을 보낼 수 MAY 있습니다.

Web Thinginvokeaction 요청에 응답하기 전에 action 실행을 시도하는 중 오류를 만나면, 오류 응답을 보내야 MUST 합니다.

적합한 Consumers는 초기 invokeaction 요청에 대한 세 가지 응답 유형을 모두 지원해야 MUST 합니다. 초기 요청 이후, ActionStatus 리소스에 대한 후속 작업 지원은 OPTIONAL입니다.

6.2.2.1.1 ActionStatus 객체

비동기식 action 호출 요청의 상태는 다음 멤버를 포함하는 ActionStatus 객체로 표현됩니다:

멤버 설명 할당 유형
status action 요청의 상태입니다. 필수 string ( pending, running, completed 또는 failed 중 하나)
output 완료된 action의 출력 데이터(있는 경우)로, 해당 ActionAffordanceoutput 데이터 스키마를 준수해야 MUST 합니다. 선택 사항 임의 유형
error 실패한 action과 관련된 오류 메시지(있는 경우)로, Problem Details 형식 [RFC7807]의 JSON 직렬화를 사용해야 MUST 합니다( queryaction 작업에 대한 응답에서만 필요). 선택 사항 object
href queryactioncancelaction 작업에서 사용할 수 있는 ActionStatus 리소스의 [URL]로, 그 URI scheme [RFC3986]은 http 또는 https로 확인되어야 MUST 합니다( 비동기식 액션 응답에만 필요). 선택 사항 string
timeRequested Thing이 action 실행 요청을 수신한 시간을 나타내는 타임스탬프입니다. (날짜 형식 제약은 날짜 형식을 참조하십시오). 선택 사항 string
timeEnded Thing이 action 실행을 성공적으로 완료했거나, action 실행에 실패한 시간을 나타내는 타임스탬프입니다. (날짜 형식 제약은 날짜 형식을 참조하십시오). 선택 사항 string
참고

Thing의 시계가 올바른 시간으로 설정되어 있지 않을 수 있습니다. 시간이 중요하다면 Consumer는 따라서 ActionStatus 객체의 timeEnded 멤버를 timeRequested 멤버에 상대적인 것으로 처리하도록 선택할 수 있지만, 반드시 자신의 내부 시계나 다른 Things의 시계에 상대적인 것으로 처리할 필요는 없습니다.

6.2.2.1.2 동기식 액션 응답

출력이 있는 action에 대해 동기식 액션 응답을 제공하는 경우, Web Thing은 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 application/json으로 설정
  • action의 출력을 JSON으로 직렬화하여 포함하는 본문
예제 14: 출력이 있는 동기식 action 응답
HTTP/1.1 200 OK
Content-Type: application/json
20

출력이 없는 action에 대해 동기식 액션 응답을 제공하는 경우, Web Thing은 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204로 설정
  • Content-Type 헤더는 설정하지 않음
  • 빈 본문
예제 15: 출력이 없는 동기식 action 응답
HTTP/1.1 204 No Content
참고

null, 빈 따옴표 ("") 또는 빈 중괄호({})와 같은 유효한 JSON 값은 유효한 action 출력일 수 있으며, "빈" 본문으로 간주되지 않습니다.

6.2.2.1.3 비동기식 액션 응답

비동기식 액션 응답을 제공하는 경우, Web ThingActionStatus 리소스의 URL을 포함하는 HTTP 응답을 보내야 MUST 하며, 그 URI scheme [RFC3986]은 http 또는 https로 확인되어야 MUST 합니다. 응답은 다음을 가져야 MUST 합니다:

  • 상태 코드는 201로 설정
  • Content-Type 헤더는 application/json으로 설정
  • Location 헤더는 ActionStatus 리소스의 URL로 설정
  • href 멤버가 ActionStatus 리소스의 URL로 설정된 JSON 직렬화된 ActionStatus 객체를 포함하는 본문
HTTP/1.1 201 CREATED
Content-Type: application/json
Location: /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
{
  "status": "pending",
  "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655",
  "timeRequested": "2021-11-10T11:43:19.135Z"
}

리소스가 제한된 환경에서는 오래된 완료/실패 actions의 ActionStatus 객체를 삭제하여 새로 호출된 actions를 위한 공간을 만들 수 MAY 있습니다.

예를 들어 Thing이 과부하 상태이기 때문에 action을 사용할 수 없어 호출을 수락할 수 없는 경우, Web Thing503 오류 응답을 반환해야 SHOULD 합니다.

6.2.2.2 queryaction

queryaction 작업은 진행 중인 action 요청의 현재 상태를 질의하는 데 사용됩니다.

Action에 대한 invokeaction 작업에 대해 비동기식 액션 응답을 제공하는 Web Thing은 그 동일한 Action에 대한 queryaction 작업도 지원해야 MUST 합니다. Action에 대한 invokeaction 작업에 대해 동기식 액션 응답만 제공하는 Web Thing은 그 동일한 Action에 대한 queryaction 작업을 지원해서는 SHOULD NOT 안 됩니다.

queryaction 작업에 사용할 ActionStatus 리소스의 URL은 비동기식 액션 응답Location 헤더 또는 그 본문 안의 ActionStatus 객체의 href 멤버에서 얻어야 MUST 합니다.

action 요청의 상태를 질의하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 GET으로 설정
  • URL은 ActionStatus 리소스의 URL로 설정
  • Accept 헤더는 application/json으로 설정
GET /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
Host: mythingserver.com
Accept: application/json

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, Consumer가 해당 ActionStatus 리소스를 질의할 권한이 있으면, action 요청의 상태를 성공적으로 읽은 후 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 application/json으로 설정
  • action 요청의 현재 상태를 나타내는 ActionStatus 객체를 JSON 직렬화하여 포함하는 본문
HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "running",
  "timeRequested": "2021-11-10T11:43:19.135Z"
}

질의된 action이 실행에 실패한 경우, ActionStatus 객체의 status 멤버는 "failed"로 설정되어야 MUST 합니다. 질의된 action이 실행에 실패한 경우, error 멤버는 Problem Details 형식 [RFC7807]을 준수하는 추가 오류 정보를 제공할 수 MAY 있습니다.

HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": "failed",
  "error": {
    "type": "https://mythingserver.com/docs/errors/invalid-level",
    "title": "Invalid value for level provided",
    "invalid-params": [
      {
        "name": "level",
        "reason": "Must be a valid number between 0 and 100"
      }
    ]
  },
  "timeRequested": "2021-11-10T11:43:19.135Z",
  "timeEnded": "2021-11-10T11:43:20.513Z"
}
6.2.2.3 cancelaction

cancelaction 작업은 진행 중인 action 요청을 취소하는 데 사용됩니다.

Action에 대한 invokeaction 작업에 대해 비동기식 액션 응답을 제공하는 Web Thing은 그 동일한 Action에 대한 cancelaction 작업도 지원할 수 MAY 있습니다. Action에 대한 invokeaction 작업에 대해 동기식 액션 응답만 제공하는 Web Thing은 그 동일한 Action에 대한 cancelaction 작업을 지원해서는 SHOULD NOT 안 됩니다.

cancelaction 작업에 사용할 ActionStatus 리소스의 URL은 비동기식 액션 응답Location 헤더 또는 그 본문 안의 ActionStatus 객체의 href 멤버에서 얻어야 MUST 합니다.

action 요청을 취소하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 DELETE로 설정
  • URL은 ActionStatus 리소스의 URL로 설정
DELETE /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655 HTTP/1.1
Host: mythingserver.com

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, Consumer가 해당 action 요청을 취소할 권한이 있으면, action을 성공적으로 취소한 후 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204로 설정
HTTP/1.1 204 No Content
6.2.2.4 queryallactions

진행 중인 모든 action 요청의 상태를 질의할 때 사용할 actions 리소스의 URL은 Thing Description에서 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 queryallactions 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 actions 리소스의 URL로 사용되어야 MUST 합니다.

진행 중인 모든 action 요청의 상태를 질의하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 GET으로 설정
  • URL은 actions 리소스의 URL로 설정
  • Accept 헤더는 application/json으로 설정
GET /things/lamp/actions HTTP/1.1
Host: mythingserver.com
Accept: application/json

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면, Consumer가 접근 권한을 가진 진행 중인 모든 action 요청의 상태를 성공적으로 검색한 후, 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 application/json으로 설정
  • Action 이름을 키로 하는 객체를 포함하는 본문으로, 각 객체 멤버의 값은 action 요청을 나타내는 ActionStatus 객체들의 배열이며, JSON으로 직렬화됩니다.

결과 객체의 각 배열은 가장 최근의 action 요청이 먼저 나타나도록 역시간순으로 정렬되어야 MUST 합니다.

HTTP/1.1 200 OK
Content-Type: application/json
{
  "fade": [
    {
      "status": "completed",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655",
      "timeRequested": "2021-11-10T11:43:19.135Z",
      "timeEnded": "2021-11-10T11:43:20.513Z"
    },
    {
      "status": "failed",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-558329",
      "timeRequested": "2021-11-10T11:42:15.133Z",
      "timeEnded": "2021-11-10T11:42:22.524Z"
    },
    {
      "status": "running",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-434656",
      "timeRequested": "2021-11-10T11:41:53.351Z"
    },
    {
      "status": "pending",
      "href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-ea9519",
      "timeRequested": "2021-11-10T11:39:53.651Z"
    }
  ]
}
참고: ActionStatus 객체의 보존
action 요청이 cancelaction 작업으로 취소되면, 그 ActionStatus 객체는 삭제되며 보존할 필요가 없습니다. 그 밖의 모든 action 요청에 대해서는 Web Thing이 나중에 queryaction 또는 queryallactions 작업으로 그 상태를 질의할 수 있도록 ActionStatus 객체를 저장한다고 가정합니다. ActionStatus 객체를 무기한 보존할 것으로 기대되지는 않으며, 휘발성 메모리에 저장되거나 주기적으로 정리될 수 있습니다. ActionStatus 객체를 보존할 시간의 길이는 구현별로 달라질 것으로 예상되며, 애플리케이션별 요구사항이나 리소스 제약에 따라 달라질 수 있습니다.

7. HTTP SSE Profile

이 절은 Server-Sent Events [EVENTSOURCE]를 사용하여 Properties를 관찰하고 Events를 수신하기 위한 Protocol Binding을 포함하는 HTTP SSE Profile을 정의합니다.

이 profile은 속성을 읽고 쓰며, action을 호출, 질의 및 취소하는 작업을 제공하기 위해 HTTP Basic Profile과 함께 사용할 수 있습니다.

HTTP SSE Profile을 준수하려면 Web ThingsConsumersCommon Constraints 절의 모든 단언도 준수해야 MUST 합니다.

7.1 식별자

주어진 Web Thing이 HTTP SSE Profile을 준수함을 표시하려면, 그 Thing Descriptionhttps://www.w3.org/2022/wot/profile/http-sse/v1 값을 갖는 profile 멤버 [wot-thing-description11]를 가져야 MUST 합니다.

7.2 프로토콜 바인딩

이 절은 Server-Sent Events [EVENTSOURCE]를 사용하여 ConsumerWeb Thing [wot-architecture11]과 통신하는 방식을 설명하는 Protocol Binding을 정의합니다.

HTTP SSE Profile을 준수하는 Consumer 또는 Web Thing은 이 프로토콜 바인딩을 구현해야 MUST 합니다.

이 절 전체에서 제공되는 예제는 다음 Thing Description을 생성하는 Web ThingConsumer가 어떻게 통신하는지를 설명합니다:

{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": "https://www.w3.org/2022/wot/profile/http-sse/v1",
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [
        {
          "href": "properties/on",
          "op": ["observeproperty", "unobserveproperty"],
          "subprotocol": "sse"
        }
      ]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [
        {
          "href": "properties/level",
          "op": ["observeproperty", "unobserveproperty"],
          "subprotocol": "sse"
        }
      ]
    }
  },
  "events": {
    "overheated": {
      "title": "Overheated",
      "data": {
        "type": "number",
        "unit": "degree celsius"
      },
      "description": "The lamp has exceeded its safe operating temperature",
      "forms": [{
        "href": "events/overheated",
        "subprotocol": "sse"
      }]
    }
  },
  "forms": [
    {
      "op": ["observeallproperties", "unobserveallproperties"],
      "href": "properties",
      "subprotocol": "sse"
    },
    {
      "op": ["subscribeallevents", "unsubscribeallevents"],
      "href": "events",
      "subprotocol": "sse"
    }
  ]
}

7.2.1 속성

7.2.1.1 observeproperty

property 값을 관찰할 때 사용할 Property 리소스의 URL은 Thing Description에서 해당 PropertyAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 observeproperty 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • subprotocol 멤버의 값이 sse입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 property 리소스의 URL로 사용되어야 MUST 합니다.

Property를 관찰하려면, Consumer는 Server-Sent Events [EVENTSOURCE] 명세를 따라 property 리소스의 URL에서 Web Thing과의 연결을 열어야 MUST 합니다.

이는 Consumer가 다음과 같은 HTTP 요청을 Web Thing에 보내는 것을 포함합니다:

  • 메서드는 GET으로 설정
  • URL은 property 리소스의 URL로 설정
  • Accept 헤더는 text/event-stream으로 설정
  • Connection 헤더는 keep-alive로 설정
GET /things/lamp/properties/level HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection: keep-alive
참고: JavaScript를 사용한 연결 열기

JavaScript [ECMASCRIPT]로 구현되고 EventSource 인터페이스를 노출하는 런타임에서 실행되는 Consumers의 경우, Server-Sent Events 연결은 EventSource 생성자를 사용하여 시작할 수 있습니다.

const levelSource = new EventSource('/things/lamp/properties/level');

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 Consumer가 해당 property를 관찰할 권한이 있으면, Server-Sent Events [EVENTSOURCE] 명세를 따라 Consumer와 열린 연결을 유지하고, 지정된 Property 값이 변경될 때마다 property 값을 Consumer에 푸시해야 MUST 합니다.

이는 Web Thing이 처음에 Consumer에게 다음과 같은 HTTP 응답을 보내는 것을 포함합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 text/event-stream으로 설정
HTTP/1.1 200 OK
Content-Type: text/event-stream

Web ThingConsumer와 열린 연결을 가진 동안 지정된 Property의 값이 변경될 때마다, Web Thing은 Server-Sent Events [EVENTSOURCE] 명세의 event stream 형식을 사용하여 property 값을 Consumer에 보내야 MUST 합니다. 보내는 각 메시지에 대해, Web Thingevent 필드를 PropertyAffordance의 이름으로 설정하고, data 필드를 JSON으로 직렬화되고 PropertyAffordance에 지정된 데이터 스키마를 따르는 property 값으로 채워야 MUST 합니다. id 필드는 끊어진 연결을 다시 설정할 때 사용하기 위해 property 변경에 대한 고유 식별자로 설정하는 것이 SHOULD 좋습니다(아래 참조). 식별자는 property가 변경된 시각을 나타내는 타임스탬프인 것이 RECOMMENDED됩니다 (날짜 형식 제약은 Date Format 참조).

event: level\n
data: 42\n
id: 2021-11-17T15:33:20.827Z\n\n

ConsumerWeb Thing 사이의 연결이 끊어지면(아래에 정의된 unobserve 작업의 결과인 경우는 제외), Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 설명된 단계를 따라 연결을 다시 설정해야 MUST 합니다. 연결이 다시 설정되면, Web Thing은 가능하다면 ConsumerLast-Event-ID 헤더에 지정한 마지막 변경 이후에 발생한 누락된 property 변경을 보내는 것이 SHOULD 좋습니다.

참고: text/event-stream으로 감싼 application/json

Property 값은 JSON으로 직렬화되어 text/event-stream 형식으로 직렬화된 Server-Sent Event의 data 필드에 제공됩니다. HTTP 헤더에 사용되는 text/event-stream 콘텐츠 타입은 sse 하위 프로토콜에 의해 암시되는 것으로 간주되며, 내장된 application/json 콘텐츠 타입은 (기본값이 적용된) Form의 contentType 멤버에 표시됩니다.

7.2.1.2 unobserveproperty

Property 관찰을 중지하려면, Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 지정된 대로 Web Thing과의 해당 Server-Sent Events 연결을 종료해야 MUST 합니다.

참고: JavaScript를 사용한 연결 종료

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource [EVENTSOURCE] 객체의 close() 메서드를 사용하여 종료할 수 있습니다.

levelSource.close();
7.2.1.3 observeallproperties

Web Thing의 모든 properties 변경을 관찰할 때 사용할 properties 리소스의 URL은 Thing Description에서 Thing Description의 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 observeallproperties 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • subprotocol 멤버의 값이 sse입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 properties 리소스의 URL로 사용되어야 MUST 합니다.

Web Thing의 모든 Properties 변경을 관찰하려면, Consumer는 Server-Sent Events [EVENTSOURCE] 명세를 따라 properties 리소스의 URL에서 Web Thing과의 연결을 열어야 MUST 합니다.

이는 Consumer가 다음과 같은 HTTP 요청을 Web Thing에 보내는 것을 포함합니다:

  • 메서드는 GET으로 설정
  • URL은 properties 리소스의 URL로 설정
  • Accept 헤더는 text/event-stream으로 설정
  • Connection 헤더는 keep-alive로 설정
GET /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection: keep-alive
참고: JavaScript를 사용한 연결 열기

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource 생성자를 사용하여 시작할 수 있습니다.

const lampPropertiesSource = new EventSource('/things/lamp/properties');

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면 Server-Sent Events [EVENTSOURCE] 명세를 따라 Consumer와 열린 연결을 유지하고, 관찰할 권한이 있는 모든 Properties에 대해 새 property 값을 Consumer에 푸시해야 MUST 합니다.

이는 Web Thing이 처음에 Consumer에게 다음과 같은 HTTP 응답을 보내는 것을 포함합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 text/event-stream으로 설정
HTTP/1.1 200 OK
Content-Type: text/event-stream

Web Thing이 Consumer와 열린 연결을 가진 동안 Property가 변경될 때마다, Web Thing은 Server-Sent Events [EVENTSOURCE] 명세의 event stream 형식을 사용하여 새 property 값을 Consumer에 보내야 MUST 합니다. 보내는 각 메시지에 대해, Web Thingevent 필드를 PropertyAffordance의 이름으로 설정하고, data 필드를 새 property 값으로 채워야 MUST 합니다. property 데이터는 PropertyAffordance에 지정된 데이터 스키마를 따라야 MUST 하며 JSON으로 직렬화되어야 MUST 합니다. id 필드는 끊어진 연결을 다시 설정할 때 사용하기 위해 event에 대한 고유 식별자로 설정하는 것이 SHOULD 좋습니다(아래 참조). 식별자는 Property가 변경된 시각을 나타내는 타임스탬프인 것이 RECOMMENDED됩니다 (날짜 형식 제약은 Date Format 참조).

event: level\n
data: 42\n
id: 2021-11-17T15:33:20.827Z\n\n

ConsumerWeb Thing 사이의 연결이 끊어지면(아래에 정의된 unobserveallproperties 작업의 결과인 경우는 제외), Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 설명된 단계를 따라 연결을 다시 설정해야 MUST 합니다. 연결이 다시 설정되면 Web Thing은 가능하다면 ConsumerLast-Event-ID 헤더에 지정한 마지막 변경 이후에 발생한 누락된 property 변경을 보내는 것이 SHOULD 좋습니다.

참고: text/event-stream으로 감싼 application/json

Property 값은 JSON으로 직렬화되어 text/event-stream 형식으로 직렬화된 Server-Sent Event의 data 필드에 제공됩니다. HTTP 헤더에 사용되는 text/event-stream 콘텐츠 타입은 sse 하위 프로토콜에 의해 암시되는 것으로 간주되며, 내장된 application/json 콘텐츠 타입은 (기본값이 적용된) Form의 contentType 멤버에 표시됩니다.

7.2.1.4 unobserveallproperties

모든 properties의 관찰을 해제하려면, Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 지정된 단계를 따라, Web Thing의 properties endpoint와의 해당 Server-Sent Events 연결을 종료해야 MUST 합니다.

참고: JavaScript를 사용한 연결 종료

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource [EVENTSOURCE] 객체의 close() 메서드를 사용하여 종료할 수 있습니다.

lampPropertiesSource.close();

7.2.2 이벤트

HTTP SSE Profile은 ConsumersWeb Thing이 내보내는 events를 구독하기 위한 메커니즘으로 Server-Sent Events [EVENTSOURCE]를 사용합니다.

참고

Consumers는 이 profile을 준수하기 위해 Server-Sent Events 명세의 EventSource JavaScript API를 구현할 필요가 없습니다. event stream을 소비하는 데는 어떤 프로그래밍 언어든 사용할 수 있습니다.

7.2.2.1 subscribeevent

Event를 구독할 때 사용할 event 리소스의 URL은 Thing Description에서 해당 EventAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • 기본값이 적용된 후, 그 op 멤버가 subscribeevent 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • subprotocol 멤버의 값이 sse입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 event 리소스의 URL로 사용되어야 MUST 합니다.

Event를 구독하려면, Consumer는 Server-Sent Events [EVENTSOURCE] 명세를 따라 event 리소스의 URL에서 Web Thing과의 연결을 열어야 MUST 합니다.

이는 Consumer가 다음과 같은 HTTP 요청을 Web Thing에 보내는 것을 포함합니다:

  • 메서드는 GET으로 설정
  • URL은 event 리소스의 URL로 설정
  • Accept 헤더는 text/event-stream으로 설정
  • Connection 헤더는 keep-alive로 설정
GET /things/lamp/events/overheated HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection: keep-alive
참고: JavaScript를 사용한 연결 열기

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource 생성자를 사용하여 시작할 수 있습니다.

const overheatedEventSource = new EventSource('/things/lamp/events/overheated');

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 Consumer가 해당 Event를 구독할 권한이 있으면, Server-Sent Events [EVENTSOURCE] 명세를 따라 Consumer와 열린 연결을 유지하고, 지정된 유형의 events가 발생할 때 event 데이터를 Consumer에 푸시해야 MUST 합니다.

이는 Web Thing이 처음에 Consumer에게 다음과 같은 HTTP 응답을 보내는 것을 포함합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 text/event-stream으로 설정
HTTP/1.1 200 OK
Content-Type: text/event-stream

Web ThingConsumer와 열린 연결을 가진 동안 지정된 유형의 event가 발생할 때마다, Web Thing은 Server-Sent Events [EVENTSOURCE] 명세의 event stream 형식을 사용하여 event 데이터를 Consumer에 보내야 MUST 합니다. 보내는 각 메시지에 대해, Web Thingevent 필드를 EventAffordance의 이름으로 설정하고 data 필드를 event 데이터(있는 경우)로 채워야 MUST 합니다. event 데이터는 EventAffordance에 지정된 데이터 스키마를 따라야 MUST 하며 JSON으로 직렬화되어야 합니다. id 필드는 끊어진 연결을 다시 설정할 때 사용하기 위해 event에 대한 고유 식별자로 설정하는 것이 SHOULD 좋습니다(아래 참조). 식별자는 event가 발생한 시각을 나타내는 타임스탬프인 것이 RECOMMENDED됩니다 (날짜 형식 제약은 Date Format 참조).

event: overheated\n
data: 90\n
id: 2021-11-16T16:53:50.817Z\n\n

ConsumerWeb Thing 사이의 연결이 끊어지면(아래에 정의된 unsubscribeevent 작업의 결과인 경우는 제외), Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 설명된 단계를 따라 연결을 다시 설정해야 MUST 합니다. 연결이 다시 설정되면 Web Thing은 가능하다면 ConsumerLast-Event-ID 헤더에 지정한 마지막 event 이후에 발생한 누락된 events를 보내는 것이 SHOULD 좋습니다.

참고: text/event-stream으로 감싼 application/json

Event payload는 JSON으로 직렬화되어 text/event-stream 형식으로 직렬화된 Server-Sent Event의 data 필드에 제공됩니다. HTTP 헤더에 사용되는 text/event-stream 콘텐츠 타입은 sse 하위 프로토콜에 의해 암시되는 것으로 간주되며, 내장된 application/json 콘텐츠 타입은 (기본값이 적용된) Form의 contentType 멤버에 표시됩니다.

7.2.2.2 unsubscribeevent

Event 구독을 해제하려면, Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 지정된 대로 Web Thing과의 해당 Server-Sent Events 연결을 종료해야 MUST 합니다.

참고: JavaScript를 사용한 연결 종료

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource [EVENTSOURCE] 객체의 close() 메서드를 사용하여 종료할 수 있습니다.

overheatedEventSource.close();
7.2.2.3 subscribeallevents

Web Thing이 내보내는 모든 Events를 구독할 때 사용할 events 리소스의 URL은 Thing Description에서 Thing Description의 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 subscribeallevents 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • subprotocol 멤버의 값이 sse입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다

그런 다음 href 멤버의 확인된 값은 events 리소스의 URL로 사용되어야 MUST 합니다.

Web Thing이 내보내는 모든 Events를 구독하려면, Consumer는 Server-Sent Events [EVENTSOURCE] 명세를 따라 events 리소스의 URL에서 Web Thing과의 연결을 열어야 MUST 합니다.

이는 Consumer가 다음과 같은 HTTP 요청을 Web Thing에 보내는 것을 포함합니다:

  • 메서드는 GET으로 설정
  • URL은 events 리소스의 URL로 설정
  • Accept 헤더는 text/event-stream으로 설정
  • Connection 헤더는 keep-alive로 설정
GET /things/lamp/events HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection: keep-alive
참고: JavaScript를 사용한 연결 열기

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource 생성자를 사용하여 시작할 수 있습니다.

const lampEventsSource = new EventSource('/things/lamp/events');

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하면 Server-Sent Events [EVENTSOURCE] 명세를 따라 Consumer와 열린 연결을 유지하고, 구독할 권한이 있는 모든 event 유형에 대해 event 데이터를 Consumer에 푸시해야 MUST 합니다.

이는 Web Thing이 처음에 Consumer에게 다음과 같은 HTTP 응답을 보내는 것을 포함합니다:

  • 상태 코드는 200으로 설정
  • Content-Type 헤더는 text/event-stream으로 설정
HTTP/1.1 200 OK
Content-Type: text/event-stream

Web ThingConsumer와 열린 연결을 가진 동안 event가 발생할 때마다, Web Thing은 Server-Sent Events [EVENTSOURCE] 명세의 event stream 형식을 사용하여 event 데이터를 Consumer에 보내야 MUST 합니다. 보내는 각 메시지에 대해, Web Thingevent 필드를 EventAffordance의 이름으로 설정하고 data 필드를 event 데이터(있는 경우)로 채워야 MUST 합니다. event 데이터는 EventAffordance에 지정된 데이터 스키마를 따라야 MUST 하며 JSON으로 직렬화되어야 합니다. id 필드는 끊어진 연결을 다시 설정할 때 사용하기 위해 event에 대한 고유 식별자로 설정하는 것이 SHOULD 좋습니다(아래 참조). 식별자는 event가 발생한 시각을 나타내는 타임스탬프인 것이 RECOMMENDED됩니다 (날짜 형식 제약은 Date Format 참조).

event: overheated\n
data: 90\n
id: 2021-11-16T16:53:50.817Z\n\n

ConsumerWeb Thing 사이의 연결이 끊어지면(아래에 정의된 unsubscribeallevents 작업의 결과인 경우는 제외), Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 설명된 단계를 따라 연결을 다시 설정해야 MUST 합니다. 연결이 다시 설정되면 Web Thing은 가능하다면 ConsumerLast-Event-ID 헤더에 지정한 마지막 event 이후에 발생한 누락된 events를 보내는 것이 SHOULD 좋습니다.

참고: text/event-stream으로 감싼 application/json

Event payload는 JSON으로 직렬화되어 text/event-stream 형식으로 직렬화된 Server-Sent Event의 data 필드에 제공됩니다. HTTP 헤더에 사용되는 text/event-stream 콘텐츠 타입은 sse 하위 프로토콜에 의해 암시되는 것으로 간주되며, 내장된 application/json 콘텐츠 타입은 (기본값이 적용된) Form의 contentType 멤버에 표시됩니다.

7.2.2.4 unsubscribeallevents

모든 Events의 구독을 해제하려면, Consumer는 Server-Sent Events 명세 [EVENTSOURCE]에 지정된 단계를 따라 Web Thing의 events endpoint와의 해당 Server-Sent Events 연결을 종료해야 MUST 합니다.

참고: JavaScript를 사용한 연결 종료

JavaScript [ECMASCRIPT]로 구현되고 Consumers EventSource 인터페이스를 노출하는 런타임에서 실행되는 경우, Server-Sent Events 연결은 EventSource [EVENTSOURCE] 객체의 close() 메서드를 사용하여 종료할 수 있습니다.

lampEventsSource.close();

8. HTTP Webhook Profile

이 절은 Webhooks를 사용하여 Properties를 관찰하고 Events를 수신하기 위한 Protocol Binding을 포함하는 HTTP Webhook Profile을 정의합니다.

HTTP Webhook profile은 속성을 읽고 쓰며, action을 호출, 질의 및 취소하는 작업을 제공하기 위해 HTTP Basic Profile과 함께 사용할 수 MAY 있습니다.

HTTP Webhook profile은 HTTP SSE Profile의 대체 event 메커니즘으로 사용할 수 MAY 있습니다.

HTTP Webhook Profile을 준수하려면, Web ThingsConsumersCommon Constraints 절의 모든 단언도 준수해야 MUST 합니다.

참고: HTTP client 및 server 역할

HTTP Webhook profile을 구현하려면 ThingConsumer 모두가 HTTP client와 HTTP server로 동작할 수 있어야 하며, 네트워크를 통해 서로 접근 가능해야 합니다. 모든 배포 시나리오에서 이것이 가능하지는 않을 수 있습니다.

8.1 식별자

주어진 Web Thing이 HTTP Webhook Profile을 준수함을 표시하려면, 그 Thing Descriptionhttps://www.w3.org/2022/wot/profile/http-webhook/v1 값을 갖는 profile 멤버 [wot-thing-description11]를 가져야 MUST 합니다.

참고

profile 멤버는 여러 profile 항목을 포함할 수 있는 배열이며, 이는 Web Thing이 해당 배열의 모든 Profiles를 준수함을 나타낸다는 점에 유의하십시오.

8.2 프로토콜 바인딩

이 절은 Webhooks를 사용하여 ConsumerWeb Thing이 통신하는 방식을 설명하는 Protocol Binding을 정의합니다.

HTTP Webhook Profile을 준수하는 Consumer 또는 Web Thing은 이 프로토콜 바인딩을 구현해야 MUST 합니다.

이 절 전체에서 제공되는 예제는 다음 Thing Description [wot-thing-description11]을 생성하는 Web ThingConsumer가 어떻게 통신하는지를 설명합니다:

예제 45: HTTP Webhook Profile 예제 Thing Description
{
  "@context": "https://www.w3.org/2022/wot/td/v1.1",
  "id": "https://mywebthingserver.com/things/lamp",
  "profile": [
    "https://www.w3.org/2022/wot/profile/http-webhook/v1",
  ],
  "base": "https://mywebthingserver.com/things/lamp/",
  "title": "My Lamp",
  "description": "A web connected lamp",
  "securityDefinitions": {
    "oauth2": {
      "scheme": "oauth2",
      "flow": "code",
      "authorization": "https://mywebthingserver.com/oauth/authorize",
      "token": "https://mywebthingserver.com/oauth/token"
    }
  },
  "security": "oauth2",
  "properties": {
    "on": {
      "type": "boolean",
      "title": "On/Off",
      "description": "Whether the lamp is turned on",
      "forms": [
        {
          "op": "observeproperty",
          "href": "properties/on",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unobserveproperty",
          "href": "properties/on/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    },
    "level" : {
      "type": "integer",
      "title": "Brightness",
      "description": "The level of light from 0-100",
      "unit": "percent",
      "minimum" : 0,
      "maximum" : 100,
      "forms": [
        {
          "op": "observeproperty",
          "href": "properties/level",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unobserveproperty",
          "href": "properties/level/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    },
  },
  "events": {
    "overheated": {
      "title": "Overheated",
      "data": {
        "type": "number",
        "unit": "degree celsius"
      },
      "description": "The lamp has exceeded its safe operating temperature",
      "subscription": {
        "type": "object",
        "properties": {
          "callbackURL": {
            "type": "string",
            "format": "uri",
            "description": "Callback URL provided by subscriber for Webhook notifications."
          }
        }
      }
      "forms": [
        {
          "op": "subscribeevent",
          "href": "events/overheated",
          "subprotocol": "webhook",
          "contentType": "application/json",
          "htv:methodName": "POST"
        },
        {
          "op": "unsubscribeevent",
          "href": "events/overheated/{subscriptionID}",
          "subprotocol": "webhook",
          "htv:methodName": "DELETE"
        }
      ]
    }
  },
  "forms": [
    {
      "op": "observeallproperties",
      "href": "properties",
      "subprotocol": "webhook",
      "htv:methodName": "POST"
    },
    {
      "op": "unobserveallproperties",
      "href": "properties/{subscriptionID}",
      "suprotocol": "webhook",
      "htv:methodName": "DELETE"
    },
    {
      "op": "subscribeallevents",
      "href": "events",
      "subprotocol": "webhook",
      "htv:methodName": "POST"
    },
    {
      "op": "unsubscribeallevents",
      "href": "events/{subscriptionID}",
      "suprotocol": "webhook",
      "htv:methodName": "DELETE"
    }
  ]
}

8.2.1 속성

8.2.1.1 observeproperty

Property 값을 관찰할 때 사용할 property 리소스의 URL은 Thing Description [wot-thing-description11]에서 해당 PropertyAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 observeproperty 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다
  • subprotocol 멤버의 값이 webhook입니다

그런 다음 href 멤버의 확인된 값은 property 리소스의 URL로 사용되어야 MUST 합니다.

Property를 관찰하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 property 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 다음 멤버를 포함하는 JSON 객체가 들어 있는 본문:
    • callbackURL 멤버는 Thing이 property 변경 알림을 Consumer에 보내는 데 사용해야 하는 callback URL로 설정됩니다.
예제 46: Observe property 요청
POST /things/lamp/properties/level HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/d629c54e-a919-463b-8680-602a21f91fe9"
}

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 Consumer가 해당 Property를 관찰할 권한이 있으면, callback URL을 성공적으로 등록한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 201 Created로 설정
  • Location 헤더는 개별 property 관찰 구독을 나타내는 고유 URL로 설정되며, 나중에 ConsumerProperty 관찰을 취소할 때 사용합니다.
예제 47: Observe property 응답
HTTP/1.1 201 Created
Location: /things/properties/level/74353483-3997-437a-a4f5-84d03784e517

property 관찰 구독이 등록되어 있는 동안, 관찰 중인 Property 값이 변경될 때마다, Web Thing은 관찰 중인 Consumer에게 다음과 같은 HTTP 요청을 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 관찰을 등록할 때 Consumer가 제공한 callback URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • Link 헤더는 URL을 해당 property 리소스의 URL로 설정하고, relself로 설정
  • Date 헤더는 user agent에 의해 property 변경 시각으로 자동 설정되며, [rfc9110]의 HTTP Date 형식을 사용합니다
  • Property의 새 값을 포함하는 본문으로, JSON으로 직렬화되고 Property Affordance의 데이터 스키마를 준수합니다
예제 48: Property 변경 알림 요청
POST /listeners/d629c54e-a919-463b-8680-602a21f91fe9 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 12:48:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/properties/level>; rel="self"
90

Consumer가 유효한 callback URL로 위 형식을 따르는 HTTP 요청을 수신하면, Web Thing에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200 OK로 설정
예제 49: Property 변경 알림 응답
HTTP/1.1 200 OK
8.2.1.2 unobserveproperty

property의 관찰 구독을 취소하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 DELETE로 설정
  • URL은 observeproperty 작업 중 HTTP 응답의 Location 헤더에 제공된 subscription URL로 설정
예제 50: Unobserve property 요청
DELETE /things/properties/level/74353483-3997-437a-a4f5-84d03784e517 HTTP/1.1 
Host: mythingserver.com

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, 제공된 URL을 가진 property 관찰 구독이 존재하면, 구독을 성공적으로 취소한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204 No Content로 설정
예제 51: Unobserve property 응답
HTTP/1.1 204 No Content
8.2.1.3 observeallproperties

Web Thing의 모든 Properties 값을 관찰할 때 사용할 properties 리소스의 URL은 Thing Description [wot-thing-description11]에서 Thing Description의 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 observeallproperties 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다
  • subprotocol 멤버의 값이 webhook입니다

그런 다음 href 멤버의 확인된 값은 properties 리소스의 URL로 사용되어야 MUST 합니다.

Web Thing의 모든 Properties 변경을 관찰하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 properties 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 다음 멤버를 포함하는 JSON 객체가 들어 있는 본문:
    • callbackURL 멤버는 Thing이 property 변경 알림을 Consumer에 보내는 데 사용해야 하는 callback URL로 설정됩니다.
예제 52: Observe all properties 요청
POST /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/aa2d8e1f-dc6a-4fe0-a5c0-a42d9f532699"
}

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 ConsumerThingProperties를 관찰할 권한이 있으면, callback URL을 성공적으로 등록한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 201 Created로 설정
  • Location 헤더는 개별 관찰 구독을 나타내는 고유 URL로 설정되며, 나중에 Consumer가 모든 Properties의 관찰을 취소할 때 사용합니다.
예제 53: Observe all properties 응답
HTTP/1.1 201 Created
Location: /things/properties/a84fc5df-2667-4db2-a767-feb4640f2cf7

properties 관찰 구독이 등록되어 있는 동안, 관찰 가능한 Property 값이 변경될 때마다, Web Thing은 관찰 중인 Consumer에게 다음과 같은 HTTP 요청을 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 관찰 구독을 등록할 때 Consumer가 제공한 callback URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • Link 헤더는 URL을 해당 PropertyAffordance의 URL로 설정하고, relself로 설정
  • Date 헤더는 user agent에 의해 property 변경 시각으로 자동 설정되며, [rfc9110]의 HTTP Date 형식을 사용합니다
  • Property의 새 값을 포함하는 본문으로, JSON으로 직렬화되고 PropertyAffordance의 데이터 스키마를 준수합니다
예제 54: Property 변경 알림 요청
POST /listeners/aa2d8e1f-dc6a-4fe0-a5c0-a42d9f532699 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 12:56:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/properties/level>; rel="self"
86

Consumer가 유효한 callback URL로 위 형식을 따르는 HTTP 요청을 수신하면, Web Thing에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200 OK로 설정
예제 55: Property 변경 알림 응답
HTTP/1.1 200 OK
8.2.1.4 unobserveallproperties

모든 Properties의 관찰을 취소하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 DELETE로 설정
  • URL은 observeallproperties 작업 중 HTTP 응답의 Location 헤더에 제공된 subscription URL로 설정
예제 56: Unobserve all properties 요청
DELETE /things/properties/a84fc5df-2667-4db2-a767-feb4640f2cf7 HTTP/1.1 
Host: mythingserver.com

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, 제공된 URL을 가진 properties 관찰 구독이 존재하면, 관찰 구독을 성공적으로 취소한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204 No Content로 설정
예제 57: Unobserve all properties 응답
HTTP/1.1 204 No Content

8.2.2 이벤트

8.2.2.1 subscribeevent

Event를 구독할 때 사용할 event 리소스의 URL은 Thing Description [wot-thing-description11]에서 해당 EventAffordance 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 subscribeevent 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다
  • subprotocol 멤버의 값이 webhook입니다

그런 다음 href 멤버의 확인된 값은 event 리소스의 URL로 사용되어야 MUST 합니다.

Event를 구독하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 event 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 다음 멤버를 포함하는 JSON 객체가 들어 있는 본문:
    • callbackURL 멤버는 Thing이 event 알림을 Consumer에 보내는 데 사용해야 하는 callback URL로 설정됩니다.
예제 58: Subscribe event 요청
POST /things/lamp/events/overheated HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/e79dd0a5-4537-4ded-a10f-bb4eb2aca28d"
}

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 Consumer가 해당 Event를 구독할 권한이 있으면, callback URL을 성공적으로 등록한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 201 Created로 설정
  • Location 헤더는 개별 event 구독을 나타내는 고유 URL로 설정되며, 나중에 Consumer가 구독을 취소할 때 사용합니다.
예제 59: Subscribe event 응답
HTTP/1.1 201 Created
Location: /things/events/overheated/ce527faa-a5ab-4f03-8f85-e4411d13edb5

event 구독이 등록되어 있는 동안, 모니터링되는 Event의 인스턴스가 발생할 때마다, Web Thing은 구독한 Consumer에게 다음과 같은 HTTP 요청을 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 Event를 구독할 때 Consumer가 제공한 callback URL로 설정
  • Content-Type 헤더는 application/json으로 설정(event에 data payload가 있는 경우에만)
  • Link 헤더는 URL을 해당 event 리소스의 URL로 설정하고, relself로 설정
  • Date 헤더는 user agent에 의해 event 발생 시각으로 자동 설정되며, [rfc9110]의 HTTP Date 형식을 사용합니다
  • event의 data payload가 있는 경우 이를 포함하는 본문으로, JSON으로 직렬화되고 EventAffordance의 데이터 스키마를 준수합니다

event에 data payload가 포함되어 있지 않으면 요청의 Content-Type 헤더는 설정해서는 SHOULD NOT 안 되며, 본문은 비어 있어야 합니다.

참고

null, 빈 따옴표 ("") 또는 빈 중괄호({})와 같은 유효한 JSON 값은 유효한 data payload일 수 있으며, "빈" 본문으로 간주되지 않습니다.

예제 60: Event 알림 요청
POST /listeners/e79dd0a5-4537-4ded-a10f-bb4eb2aca28d HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 16:46:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/events/overheated>; rel="self"
90

Consumer가 유효한 callback URL로 위 형식을 따르는 HTTP 요청을 수신하면, Web Thing에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200 OK로 설정
예제 61: Event 알림 응답
HTTP/1.1 200 OK
8.2.2.2 unsubscribeevent

Event 구독을 취소하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 DELETE로 설정
  • URL은 subscribeevent 작업 중 HTTP 응답의 Location 헤더에 제공된 subscription URL로 설정
예제 62: Unsubscribe event 요청
DELETE /things/events/overheated/ce527faa-a5ab-4f03-8f85-e4411d13edb5 HTTP/1.1 
Host: mythingserver.com

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, 제공된 URL을 가진 event 구독이 존재하면, 구독을 성공적으로 취소한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204 No Content로 설정
예제 63: Unsubscribe event 응답
HTTP/1.1 204 No Content
8.2.2.3 subscribeallevents

Web Thing의 모든 Events를 구독할 때 사용할 events 리소스의 URL은 Thing Description [wot-thing-description11]에서 Thing Description의 최상위 forms 멤버 내부의 다음 조건을 만족하는 Form을 찾아 얻어야 MUST 합니다:

  • op 멤버가 subscribeallevents 값을 포함합니다
  • 해당되는 경우 base URL을 기준으로 확인된 후, 그 href 멤버 값의 URI scheme [RFC3986]이 http 또는 https입니다
  • 기본값이 적용된 후, 그 contentType 멤버의 값이 application/json입니다
  • subprotocol 멤버의 값이 webhook입니다

그런 다음 href 멤버의 확인된 값은 events 리소스의 URL로 사용되어야 MUST 합니다.

Web Thing의 모든 Events를 구독하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 events 리소스의 URL로 설정
  • Content-Type 헤더는 application/json으로 설정
  • 다음 멤버를 포함하는 JSON 객체가 들어 있는 본문:
    • callbackURL 멤버는 Thing이 event 알림을 Consumer에 보내는 데 사용해야 하는 callback URL로 설정됩니다.
예제 64: Subscribe all events 요청
POST /things/lamp/events HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
  callbackURL: "https://myconsumer.com/listeners/bdd2aa13-387b-4c97-9725-52294a9fa5a9"
}

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고 ConsumerThingEvents를 구독할 권한이 있으면, callback URL을 성공적으로 등록한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 201 Created로 설정
  • Location 헤더는 개별 event 구독을 나타내는 고유 URL로 설정되며, 나중에 Consumer가 구독을 취소할 때 사용합니다.
예제 65: Subscribe all events 응답
HTTP/1.1 201 Created
Location: /things/events/929dbb69-eb66-46df-a0fe-93701d82e7ea

events 구독이 등록되어 있는 동안, event가 발생할 때마다 Web Thing은 구독한 Consumer에게 다음과 같은 HTTP 요청을 보내야 MUST 합니다:

  • 메서드는 POST로 설정
  • URL은 구독을 등록할 때 Consumer가 제공한 callback URL로 설정
  • Content-Type 헤더는 application/json으로 설정(event에 data payload가 포함된 경우에만)
  • Link 헤더는 URL을 해당 event 리소스의 URL로 설정하고, relself로 설정
  • Date 헤더는 user agent에 의해 event 발생 시각으로 자동 설정되며, [rfc9110]의 HTTP Date 형식을 사용합니다
  • event data payload가 있는 경우 이를 포함하는 본문으로, JSON으로 직렬화되고 EventAffordance의 데이터 스키마를 준수합니다

event에 data payload가 포함되어 있지 않으면 요청의 Content-type 헤더는 설정해서는 SHOULD NOT 안 되며, 본문은 비어 있어야 합니다.

참고

null, 빈 따옴표 ("") 또는 빈 중괄호({})와 같은 유효한 JSON 값은 유효한 data payload일 수 있으며, "빈" 본문으로 간주되지 않습니다.

예제 66: Event 알림 요청
POST /listeners/bdd2aa13-387b-4c97-9725-52294a9fa5a9 HTTP/1.1
Host: myconsumer.com
Date: Fri, 4 Jul 2025 17:04:00 GMT
Content-type: application/json
Link: <https://mythingserver.com/things/mylamp1/events/overheated>; rel="self"
86

Consumer가 유효한 callback URL로 위 형식을 따르는 HTTP 요청을 수신하면, Web Thing에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 200 OK로 설정
예제 67: Event 알림 응답
HTTP/1.1 200 OK
8.2.2.4 unsubscribeallevents

모든 Events에 대한 구독을 취소하려면, Consumer는 다음과 같은 HTTP 요청을 Web Thing에 보내야 MUST 합니다:

  • 메서드는 DELETE로 설정
  • URL은 subscribeallevents 작업 중 HTTP 응답의 Location 헤더에 제공된 subscription URL로 설정
예제 68: Unsubscribe all events 요청
DELETE /things/events/929dbb69-eb66-46df-a0fe-93701d82e7ea HTTP/1.1 
Host: mythingserver.com

Web Thing이 위 형식을 따르는 HTTP 요청을 수신하고, 제공된 URL을 가진 events 구독이 존재하면, events 구독을 성공적으로 취소한 후 Consumer에게 다음과 같은 HTTP 응답을 보내야 MUST 합니다:

  • 상태 코드는 204 No Content로 설정
예제 69: Unsubscribe all events 응답
HTTP/1.1 204 No Content

9. 개인정보 보호 고려사항

WoT Architecture [wot-architecture11] 및 WoT Thing Description [wot-thing-description11] 명세의 개인정보 보호 고려사항을 고려해야 SHOULD 합니다.

참고

구현 조언은 WoT Security and Privacy Guidelines [wot-security]도 참조하십시오.

10. 보안 고려사항

WoT Architecture [wot-architecture11] 및 WoT Thing Description [wot-thing-description11] 명세의 보안 고려사항을 고려해야 SHOULD 합니다.

참고

구현 조언은 WoT Security and Privacy Guidelines [wot-security]도 참조하십시오.

11. 접근성 고려사항

Thing Description의 모든 수준에서 titledescription 멤버의 값은 사용자 인터페이스를 생성하는 데 사용될 수 있으므로, 필요한 경우 보조 기술로도 렌더링할 수 있는 사람이 읽을 수 있는 문자열이어야 SHOULD 합니다.

A. 최근 명세 변경 사항

A.1 2023년 1월 18일에 발행된 WD 이후 변경 사항

A.2 2020년 11월 24일에 발행된 FPWD 이후 변경 사항

B. 참고문헌

B.1 규범적 참고문헌

[EVENTSOURCE]
Server-Sent Events. Ian Hickson. W3C. 2021년 1월 28일. W3C 권고안. URL: https://www.w3.org/TR/eventsource/
[JSON]
The JavaScript Object Notation (JSON) Data Interchange Format. T. Bray, Ed. IETF. 2017년 12월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc8259
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3339]
Date and Time on the Internet: Timestamps. G. Klyne; C. Newman. IETF. 2002년 7월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc3339
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. 2005년 1월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc3986
[RFC7807]
Problem Details for HTTP APIs. M. Nottingham; E. Wilde. IETF. 2016년 3월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7807
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC9110]
HTTP Semantics. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9110.html
[RFC9112]
HTTP/1.1. R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed. IETF. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9112.html
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[wot-architecture11]
Web of Things (WoT) Architecture 1.1. Michael Lagally; Ryuichi Matsukura; Kunihiko Toumura; Michael McCool. W3C. 2023년 12월 5일. W3C 권고안. URL: https://www.w3.org/TR/wot-architecture11/
[wot-binding-templates]
Web of Things (WoT) Binding Templates. Michael Koster; Ege Korkan. W3C. 2024년 5월 28일. W3C Working Group Note. URL: https://www.w3.org/TR/wot-binding-templates/
[wot-discovery]
Web of Things (WoT) Discovery. Kunihiko Toumura; Michael McCool; Andrea Cimmino; Farshid Tavakolizadeh. W3C. 2023년 12월 5일. W3C 권고안. URL: https://www.w3.org/TR/wot-discovery/
[wot-thing-description11]
Web of Things (WoT) Thing Description 1.1. Sebastian Käbisch; Michael McCool; Ege Korkan. W3C. 2023년 12월 5일. W3C 권고안. URL: https://www.w3.org/TR/wot-thing-description11/
[wot-usecases]
Web of Things (WoT): Use Cases and Requirements. Michael Lagally; Michael McCool; Ryuichi Matsukura; Tomoaki Mizushima. W3C. 2022년 3월 7일. W3C Working Group Note. URL: https://www.w3.org/TR/wot-usecases/

B.2 참고 정보 참고문헌

[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[H2020-CREATE-IoT]
H2020 - CREATE-IoT Project - Recommendations for commonalities and interoperability profiles of IoT platforms. IoT European Large-Scale Pilots Programme. 2018-11. Published. URL: https://european-iot-pilots.eu/wp-content/uploads/2018/11/D06_02_WP06_H2020_CREATE-IoT_Final.pdf
[wot-security]
Web of Things (WoT) Security and Privacy Guidelines. Elena Reshetova; Michael McCool. W3C. 2019년 11월 6일. W3C Working Group Note. URL: https://www.w3.org/TR/wot-security/