번역도 참조하십시오.
Copyright © 2017-2023 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
W3C 웹 사물(WoT)은 IoT 플랫폼과 애플리케이션 도메인 전반의 상호운용성을 가능하게 하기 위한 것이다. 이 목표를 달성하기 위한 핵심 메커니즘 중 하나는 IoT 장치나 서비스가 적절한 추상화 수준에서 네트워크를 통해 제공하는 상호작용을 설명하는 메타데이터를 정의하고 사용하는 것이다. WoT 사물 설명 명세는 이 목표를 충족한다.
그러나 사물을 사용하려면 먼저 그 사물 설명을 얻어야 한다. 이 문서에서 설명하는 WoT 디스커버리 프로세스는 이 문제를 다룬다. WoT 디스커버리는 다양한 사용 사례에서 WoT 사물 설명의 배포를 지원해야 한다. 여기에는 임시 시스템과 설계된 시스템, 개발 중과 런타임, 그리고 로컬 네트워크와 전역 네트워크 모두가 포함된다. 또한 이 프로세스는 기존 디스커버리 메커니즘과 함께 동작하고, 보안을 갖추며, 개인정보를 보호하고, WoT 사물 설명에 대한 업데이트와 IoT 생태계의 동적이고 다양한 특성을 효율적으로 처리할 수 있어야 한다.
WoT 디스커버리 프로세스는 두 단계, 즉 도입(Introduction)과 탐색(Exploration)으로 나뉜다. 도입 단계는 기존 디스커버리 메커니즘을 활용하지만 메타데이터를 직접 노출하지 않는다. 이 단계는 단순히 탐색 서비스를 발견하는 데 사용되며, 탐색 서비스는 안전한 인증과 권한 부여 이후에만 메타데이터를 제공한다. 이 문서는 두 가지 탐색 서비스를 규범적으로 정의한다. 하나는 정규 웹 서비스에서 단일 WoT 사물 설명을 배포하는 서비스로, 자기 설명을 특별한 경우로 포함한다. 다른 하나는 사물 설명 컬렉션을 위한 검색 가능한 WoT 사물 설명 디렉터리 서비스이다. 또한 다양한 도입 서비스도 설명되며, 필요한 경우 이를 지원하기 위한 규범적 정의가 제공된다.
이 섹션은 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 https://www.w3.org/TR/의 W3C 기술 보고서 색인에서 확인할 수 있다.
이 명세의 향후 업데이트에는 새로운 기능이 포함될 수 있다.
이 문서는 웹 사물 워킹 그룹이 권고안 트랙을 사용하여 권고안으로 발행했다.
W3C는 웹 표준으로서 이 명세의 광범위한 배포를 권장한다.
W3C 권고안은 광범위한 합의 형성을 거친 후 W3C와 그 회원이 승인하고, 구현에 대해 워킹 그룹 구성원으로부터 로열티 없는 라이선스 약속을 받은 명세이다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었다. W3C는 이 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허를 공개하기 위한 지침도 포함되어 있다. 실제로 해당 개인이 필수 청구항을 포함한다고 믿는 특허에 대해 알고 있는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.
이 문서는 2023년 11월 03일 W3C 프로세스 문서의 적용을 받는다.
웹 사물(WoT)은 웹 기술을 IoT 장치와 통합하고 사용하는 것을 지원하는 아키텍처를 정의한다. WoT 아키텍처 [wot-architecture11] 문서는 지원되는 기본 개념과 사용 패턴을 정의한다. 그러나 WoT 사물 설명 [wot-thing-description11]은 WoT 디스커버리의 목적이 WoT 사물 설명을 사용 가능하게 하는 것이므로 WoT 디스커버리의 핵심 명세이다. 구체적으로, WoT 디스커버리는 인증되고 권한이 부여된 엔터티(그리고 오직 그러한 엔터티)만이 특정 의미 체계를 갖거나 특정 상호작용을 포함하는 등 일련의 기준을 만족하는 WoT 사물 설명을 찾을 수 있도록 해야 한다. 반대로, 보안 및 개인정보 보호 목표를 지원하기 위해 WoT 디스커버리 프로세스는 권한이 없는 엔터티에 정보를 누설해서는 안 된다. 여기에는 사물 설명 자체에 배포된 정보뿐 아니라 특정 엔터티가 특정 정보를 요청하고 있다는 정보의 누설도 포함된다.
이미 여러 디스커버리 메커니즘이 정의되어 있으므로 [Discovery-Categorization-IoT], 우리가 새 메커니즘을 제안하는 이유를 명확히 해야 한다. 첫째, 많은 기존 디스커버리 메커니즘은 보안 및 개인정보 보호가 비교적 약하다. 우리의 목표 중 하나는 메타데이터를 보호하기 위해 모범 사례를 사용할 뿐 아니라 필요에 따라 미래의 모범 사례를 지원하도록 업그레이드할 수 있는 메커니즘을 수립하는 것이다. 둘째, 우리는 디스커버리를 로컬 및 비로컬 메커니즘을 모두 포함하는 넓은 의미로 사용한다. 로컬 메커니즘은 브로드캐스트 프로토콜을 사용할 수 있지만, 비로컬 메커니즘은 브로드캐스트가 확장 가능하지 않은 현재 네트워크 세그먼트를 넘어설 수 있으므로 검색 서비스와 같은 다른 접근 방식이 필요하다. 우리의 접근 방식은 필요에 따라 기존 메커니즘을 사용하여 더 일반적이고 안전한 메타데이터 배포 시스템으로 부트스트랩하는 것이다. 셋째, 우리가 배포하는 메타데이터인 WoT 사물 설명은 매우 구조화되어 있으며 데이터 스키마와 의미 주석 같은 풍부한 데이터를 포함한다. 단순한 키-값 쌍 목록에 기반한 기존 디스커버리 메커니즘은 적절하지 않다. 동시에 SPARQL [SPARQL11-OVERVIEW]과 같은 의미 데이터 질의를 위한 기존 표준의 사용은 일부 고급 사용 사례에는 적합할 수 있지만, 예상되는 많은 IoT 애플리케이션에는 너무 많은 노력이 필요할 수 있다. 따라서 더 기본적인 애플리케이션을 다루기 위해 더 단순한 질의 메커니즘도 정의한다.
몇 가지 기본 용어를 정의한 뒤, WoT 디스커버리의 기본 사용 사례와 요구사항을 요약한다. 이들은 WoT 사용 사례 [wot-usecases] 및 WoT 아키텍처 [wot-architecture11] 문서에 제시된 더 상세하고 포괄적인 사용 사례 및 요구사항의 하위 집합이다. 그런 다음 2단계 도입/탐색 접근 방식을 사용하는 WoT 디스커버리 프로세스의 기본 아키텍처를 설명한다. 이 아키텍처의 기본 목표는 기존 디스커버리 표준을 사용하여 보호된 디스커버리 서비스에 대한 접근을 부트스트랩하되, 상세한 메타데이터는 권한이 있는 사용자에게만 배포하고 질의를 수행하는 사용자를 도청자로부터 가능한 한 보호하는 것이다. 이어서 특정 도입 및 탐색 메커니즘의 세부사항을 설명한다. 특히, 사물 또는 그 대리 엔터티가 동적으로 등록할 수 있는 WoT 사물 설명 컬렉션에 대한 검색 메커니즘을 제공하는 WoT 사물 설명 디렉터리(WoT TDD) 서비스를 위한 규범적 API를 상세히 정의한다. 그러나 WoT 디스커버리 메커니즘은 정규 웹 서비스에서 단일 TD를 배포하는 것도 지원하며, 이의 특별한 경우가 자기 설명이다. 마지막으로, 잠재적 위험과 완화 방안의 집합을 포함하여 보안 및 개인정보 보호 고려 사항을 논의한다.
비규범으로 표시된 섹션뿐 아니라, 이 명세의 모든 작성 지침, 도표, 예제 및 참고는 비규범이다. 이 명세의 그 밖의 모든 내용은 규범이다.
이 문서의 핵심 단어 MAY, MUST, OPTIONAL, RECOMMENDED, SHOULD, 및 SHOULD NOT은 여기에 표시된 것처럼 모두 대문자로 나타나는 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석되어야 한다.
이 섹션은 비규범이다.
사물, 사물 설명 (TD), 사물 모델 (TM), 속성, 액션, 이벤트, 익명 TD, 디스커버러, 디스커버리, 탐색, 도입, 사물 설명 서버 (TD 서버), 사물 설명 디렉터리 (TDD), 부분 TD, 보강된 TD와 같은 기본 WoT 용어는 WoT 아키텍처 1.1 명세의 섹션 3 [wot-architecture11]에 정의되어 있다.
이 섹션은 비규범이다.
그림 1은 WoT 디스커버리 프로세스의 개요를 보여준다. 디스커버리는 개방적이면서도 메타데이터에 대한 접근을 권한 있는 엔터티로 제한해야 하는 상충되는 요구사항을 해결하기 위해 2단계 아키텍처를 사용한다. 첫 번째 단계에서는 비교적 개방적인 "도입" 메커니즘 집합 중 하나 이상을 사용하여 후보 URL 집합을 생성할 수 있다. 이러한 URL 자체에는 메타데이터가 포함되지 않지만, 두 번째 단계에서 인증 후 실제로 사물 설명의 형태로 메타데이터를 제공할 수 있는 "탐색" 서비스를 참조하는 데 사용된다.
의도는 도입 메커니즘이 디스커버리 프로세스의 나머지 부분을 위한 시작점을 제공하는 비교적 개방적인 "첫 접촉" 메커니즘이 되는 것이다. 이 문서에서는 로컬 및 비로컬 시나리오를 포함하여 서로 다른 사용 사례에 적합한 여러 도입 메커니즘의 세부사항을 명시하지만, 도입은 실제로 URL을 반환할 수 있는 어떤 메커니즘으로도 제공될 수 있다. 그러나 도입은 보안 또는 개인정보 보호 제어를 포함하지 않으므로 메타데이터를 직접 제공해서는 안 된다. 대신, 도입 메커니즘이 제공하는 URL은 "탐색" 서비스를 참조한다. 탐색 서비스는 실제로 메타데이터를 제공하지만, 적절한 인증과 접근 제어가 적용된 후에만 제공한다.
디스커버리 프로세스는 하나의 도입 메커니즘만 사용하더라도 도입 단계의 출력으로 URL의 집합을 생성할 수 있다(일부 도입 메커니즘 자체가 여러 URL을 반환할 수 있다). 탐색 단계 이후의 최종 출력도 사물 설명의 집합일 수 있다.
도입 단계에서 제공되는 각 URL은 항상 단일 사물 설명을 반환하는 탐색 서비스 엔드포인트를 가리킨다. 가장 단순한 경우, 이 URL은 IoT 엔드포인트 장치를 설명하는 사물의 사물 설명을 제공하는 웹 서버의 일반 리소스를 참조한다. 이의 특별한 경우로, 자기 설명 사물의 경우 도입 URL이 자체 사물 설명을 제공하는 사물이 제공하는 엔드포인트를 직접 가리킬 수 있다.
일반적으로 사물 설명은 다양한 방식으로 제공될 수 있으며, 특히 자기 설명 방식이 아닐 수 있다. 예를 들어,
그러한 사물의 사물 설명은 별도의 서비스에서 제공되어야 한다.
이 문서는 더 큰 유연성을 허용하는 두 가지 특별한 경우를 명시한다:
디스커버리 프로세스가 사물 설명 디렉터리의 내용을 검색하여 결과의 일부로 반환하는 것은 필수 사항이 아니다. 일반적으로 이는 엄청난 결과 집합을 초래할 수 있기 때문이다. 대신 애플리케이션은 결과에서 사물 설명 디렉터리 TD를 찾아 이들로부터 TD를 검색할지, 가능하다면 선택적으로 검색할지를 결정해야 한다. 마찬가지로 사물 링크를 자동으로 따라가는 것도 요구되지 않는다. 대신 애플리케이션은 이를 선택적으로 따라갈 수 있다.
이 섹션에서는 클라이언트의 관점에서 WoT 디스커버리 프로세스를 설명하고, 클라이언트가 WoT 디스커버리를 지원한다고 말하는 것이 무엇을 의미하는지 설명한다. WoT 디스커버리 프로세스의 클라이언트인 엔터티를 가리키기 위해 디스커버러라는 용어를 사용한다. 디스커버러는 완전한 컨슈머일 수도 있고 아닐 수도 있다. 그러나 디스커버러는 디렉터리 및 사물 링크를 위한 특수 TD를 읽고 정보를 추출하며, 그 안에 제공된 특정 어포던스와 링크를 사용해야 한다. 반대로 컨슈머는 디스커버리를 지원하지 않을 수 있지만, 이는 권장된다 [wot-architecture11].
WoT 디스커버리 프로세스는 단일 URI가 주어졌을 때 단일 TD를 가져올 수 있는 거의 모든 클라이언트가 WoT 디스커버리를 지원한다고 할 수 있도록 설계되어 있다. 물론 디스커버러는 더 강력한 디스커버리 메커니즘을 지원할 수 있지만, 이들 중 일부는 추가 요구사항이 있다. 일부 도입 메커니즘은 여러 URL을 반환할 수 있으며, 각 URL은 차례로 적어도 하나의 TD를 가져오는 데 사용될 수 있다. 따라서 TDD가 없더라도 여러 TD를 발견할 수 있다.
다음 단언은 디스커버러의 구체적인 책임을 설명한다:
@type 필드를 확인하고 이 구분을
수행할 수 있어야 함을 의미한다. 디스커버러는 링크를
따라갈지 또는 TDD 내용을 가져올지를 결정할 수 있다. 예를
들어 외부 리소스를 가리키는 링크나 TDD에 많은 TD가 포함되어
이를 모두 가져오면 컨슈머의 메모리 처리 능력을 초과하는
경우처럼, 컨슈머가 특정 URL을 확장하지 않을 수 있는 사용
사례가 있다.위 프로세스는 디렉터리가 자신의 TD를 복제하지 않고 다른 디렉터리를 참조할 수 있게 하는 방법을 지원한다. 다른 디렉터리를 참조하려는 디렉터리는 다른 디렉터리 서비스의 TD에 대한 "describedby" 관계를 가진 사물 링크를 포함해야 한다. 그러면 위 프로세스는 사물 링크를 확장하여 디렉터리의 실제 TD를 얻고, 그런 다음 (선택적으로) 적절한 디렉터리 어포던스를 사용하여 연결된 디렉터리의 내용에 접근한다. 이러한 사물 링크는 디렉터리 자체가 아니라 디렉터리의 TD를 가리킨다는 점에 유의한다. 이들은 같은 위치에 호스팅될 수도 있고 그렇지 않을 수도 있다.
그러한 연결된 디렉터리의 내용을 재귀적으로 가져오는 것, 특히 특정 질의나 필터 없이 그렇게 하는 것은 쉽게 많은 양의 데이터를 다운로드하는 결과를 낳을 수 있다. 이러한 재귀 확장은 인벤토리, 감사 또는 색인 작성처럼 이를 요구하는 사용 사례로 제한되어야 한다.
디렉터리 서비스의 URL은 아래에 언급된 SPARQL 질의의 페더레이션 기능과 함께 사용할 수도 있으며, 대부분의 경우 이는 분산된 디렉터리 서비스 집합에서 특정 정보를 수집하는 더 효율적인 방법이 될 것이다. 그러나 SPARQL은 이러한 페더레이션을 위해 SPARQL 엔드포인트의 URL을 필요로 하며, 이는 SPARQL 질의를 지원하는 디렉터리의 TD에서 찾을 수 있다. 이는 디렉터리의 TD를 가리키는 URL과 동일하지 않다.
이 장은 사물 또는 사물 설명 디렉터리와의 초기 접촉을 위한 메커니즘을 설명한다. 다음 메커니즘 중 어느 것이든 사물 또는 사물 설명 디렉터리가 컨슈머에게 제공할 수 있다. 도입 메커니즘의 결과는 항상 적절한 인증 이후 상세한 메타데이터(TD)를 얻는 데 사용할 수 있는 탐색 서비스의 URL(주소)이다. 여러 도입 메커니즘을 사용하고 그 결과를 병합하는 것도 가능하다. 적어도 하나의 탐색 서비스 URL을 어떤 방식으로든 얻는 한, 특정 도입 메커니즘은 필수가 아니다.
탐색 서비스의 URL을 얻기 위해, 단일 URL을 생성하는 어떤 메커니즘도 사용할 수 MAY 있다. 여기에는 블루투스 비콘, QR 코드, 사용자가 입력할 서면 URL이 포함된다. 그러한 모든 URL에 대한 요청은 7. 탐색 메커니즘에 규정된 대로 TD를 결과로 반환해야 MUST 한다. 자기 설명 사물의 경우, 이는 사물 자체의 TD일 수 있다. URL이 사물 설명 디렉터리를 참조하는 경우, 이는 사물 설명 디렉터리의 사물 설명이어야 MUST 한다.
사물 또는 사물
설명 디렉터리는 자신의 존재를 알리기 위해
잘 알려진 통일 자원 식별자 [RFC8615]를
사용할 수 MAY 있다. 사물 또는 사물
설명 디렉터리가 자신의 존재를 알리기 위해 잘 알려진 통일 자원
식별자 [RFC8615]를
사용하는 경우, 다음 경로에 자신의 사물 설명을 등록해야
MUST 한다:
/.well-known/wot.
위의 잘 알려진 URI에 요청이 이루어지면, 서버는 7. 탐색 메커니즘에 규정된 대로 사물 설명을 반환해야 MUST 한다.
사물 또는 사물 설명 디렉터리는 DNS 기반 서비스 디스커버리(DNS-SD)[RFC6763]를 사용할 수 MAY 있다. 이는 멀티캐스트 DNS(mDNS)[RFC6762]와 함께 동일한 로컬 네트워크에서도 사용할 수 있다.
다음 표는 존재를 광고하기 위한 서비스 이름과 프로토콜을 나열한다. 각각이 기존 탐색 메커니즘과 함께 유효한 사용을 가지므로 이는 규범적이다:
| 서비스 이름 | 사물 또는 TDD | 프로토콜 |
|---|---|---|
_wot._tcp |
사물 | TCP 위의 HTTP, TLS/TCP 위의 HTTP, TCP 위의 CoAP, 또는 TLS/TCP 위의 CoAP |
_directory._sub._wot._tcp |
TDD | TCP 위의 HTTP, TLS/TCP 위의 HTTP, TCP 위의 CoAP, 또는 TLS/TCP 위의 CoAP |
_wot._udp |
사물 | UDP 위의 CoAP 또는 DTLS/UDP 위의 CoAP |
다음 추가 서비스 이름은 향후 사용을 위해 정의되었다. 그러나 현재 UDP 위의 CoAP를 사용하는 정의된 디렉터리 서비스가 없으므로 이 정의는 정보 제공용이다:
| 서비스 이름 | 사물 또는 TDD | 프로토콜 |
|---|---|---|
_directory._sub._wot._udp |
TDD | UDP 위의 CoAP 또는 DTLS/UDP 위의 CoAP |
TCP 기반 서비스의 경우, 서비스 인스턴스 이름이 가리키는
TXT 레코드에 다음 정보가 포함되어야
MUST 한다:
tdtypeThing 또는 Directory. 생략되면,
유형은 Thing으로 간주된다.
schemehttp (TCP 위의 HTTP), https
(TLS/TCP 위의 HTTP), coap+tcp (TCP 위의
CoAP), 또는 coaps+tcp (TLS/TCP 위의 CoAP). 생략되면,
스킴은
http로 간주된다.
UDP 기반 서비스의 경우, 서비스 인스턴스 이름이 가리키는
TXT 레코드에 다음 정보가 포함되어야
MUST 한다:
tdtypeThing 또는 Directory. 생략되면,
유형은 Thing으로 간주된다.
schemecoap (UDP 위의 CoAP) 또는 coaps
(DTLS/UDP 위의 CoAP). 생략되면 스킴은
coap로 간주된다.
그림 2 및 그림 3은 DNS-SD와 mDNS를 사용하여 사물 또는 사물 설명 디렉터리의 디스커버리를 지원하는 예시 시퀀스를 보여준다.
사물 또는 사물 설명 디렉터리는 Constrained RESTful Environment(CoRE) 링크 형식 [RFC6690]을 사용하여 자신의 존재를 광고할 수 MAY 있다. 사물 또는 사물 설명 디렉터리는 CoRE 리소스 디렉터리 [RFC9176]를 사용하여 해당 사물 설명에 대한 링크를 등록할 수 MAY 있다.
사물의 사물 설명을 대상으로 하는 링크의
리소스 유형(rt)은
wot.thing이어야 MUST 한다. 사물
설명 디렉터리의 사물 설명을 대상으로 하는 링크의
리소스 유형은
wot.directory이어야 MUST 한다.
분산 식별자
(DID) [DID-CORE]를 사용하는
사물 또는
사물
설명 디렉터리는 TD의 식별자가 해석되는 DID 문서에
각각 WotThing 또는
WotDirectory 유형의 DID 서비스
엔드포인트를 포함하여 자신의
TD 위치를
광고할 수 MAY 있다.
WoT 디스커버리를 위한 서비스
엔드포인트를 정의하기 위해,
사물 또는 사물
설명 디렉터리의 DID를 해석하여 얻은 DID 문서는
자신의 @context [did-spec-registries]에
URL
https://www.w3.org/2022/wot/discovery-did를
포함해야 MUST 한다.
사물 또는 사물
설명 디렉터리의 DID를 해석하여 얻은 DID 문서가 각각
WotThing 또는 WotDirectory 유형의 서비스
엔드포인트를 포함하는 경우, 이 서비스 엔드포인트는
각각 그 사물을 설명하는 TD
(WotThing 서비스 이름을 사용할 때) 또는 해당
사물
설명 디렉터리를 설명하는 TD (WotDirectory 서비스 이름을 사용할 때)를
참조해야 MUST 한다
[did-spec-registries].
그림 4는 TD 서버(자기 설명을 위한 것을 포함해 단일 TD를 제공함)와 사물 설명 디렉터리 서비스를 위한 고수준 정보 모델을 보여준다. 사물 설명 디렉터리는 TD를 포함할 수 있으며 동시에 사물이기도 하다. 이는 자체 TD를 가진다는 의미이다. 또한 디렉터리는 다른 사물의 개별 TD를 가져오기 위한 웹 서비스 엔드포인트를 호스팅하며, 이들 각각은 TD 서버로 사용될 수 있다. 일반적으로 사물은 자체 TD를 호스팅할 수 있으며, 이 경우 자기 설명 사물이다. 디렉터리에 대해 자기 설명은 필수가 아니지만, 사물 설명 디렉터리이면서 자기 설명 사물인 자기 설명 사물 설명 디렉터리는 가능하다.
두 가지 기본 탐색 메커니즘은 7.2 사물 설명 서버와 7.3 사물 설명 디렉터리에 설명되어 있다.
그림 5는 사물 온톨로지의 확장으로 디스커버리 온톨로지를 보여준다.
이 온톨로지는 디렉터리에 저장된 TD와 연결된
메타데이터를 위한 클래스를 포함한다. 이 클래스는
RegistrationInformation이라고 하며,
7.3.1.1 등록
정보에서 디렉터리 명세의 일부로 설명된다.
디스커버리 온톨로지는 또한 다음 섹션에서 설명하는 두 개의 새로운 사물 설명 클래스를 정의하며, 이들은 특수한 탐색 메타데이터를 모델링하는 데 사용될 수 있다: ThingDirectory 및 ThingLink.
ThingDirectory 유형 또는 URI
https://www.w3.org/2022/wot/discovery#ThingDirectory를
사용해야 MUST 한다.
이 클래스의 TD는 디렉터리의 사물 모델에서 파생될 수 있다. 7.3.2.4 API 명세(사물 모델)를 참조하라.
ThingLink 유형 또는 URI
https://www.w3.org/2022/wot/discovery#ThingLink를
사용해야 MUST 한다.
사물 링크는 참조되는 TD를
describedby 링크 관계 유형,
application/td+json 미디어 유형 및
대상 URL로 설정된 href를 가진 링크로
정의해야 MUST 한다.
예제 3은 사물 링크의 예이다.
사물 링크는 다양한 시나리오에서 사용될 수 있다. 예를 들면 다음과 같다:
탐색 서비스의 목적은 TD를 제공하는 것이지만, 적절한 인증 이후에만, 그리고 권한이 있는 당사자에게만 제공하는 것이다. 그러나 일부 경우, 특히 임시 시나리오에서 디스커버러는 탐색 서비스를 통해 TD에 접근하는 데 어떤 보안 자격 증명이 필요한지 알지 못할 수 있다. 탐색 서비스에 처음 접근할 때 적절한 인증 자격 증명이 제공되지 않으면 디스커버러는 아직 TD에 접근할 수 없으므로, 어떤 종류의 인증 및 권한 부여 정보가 필요한지 알기 위해 TD에 포함된 보안 메타데이터에 의존할 수 없다. 디스커버러에게 사전 지식이 없다면, 적어도 TD 자체에 접근하기 위해 기존 보안 협상 지원에 의존하여 접근을 부트스트랩해야 한다.
우리는 보안 협상 프로세스가 이미 존재하는 HTTP 프로토콜에 대해 다음을 정의한다. 그러나 대부분의 HTTP 협상 프로세스는 사람이 루프 안에 있다고 가정하지만, 이는 WoT 디스커버리에도 적절하다. 이 문제는 일반적으로 사용자가 공개 WoT 서비스에 접근하려 하거나 새 장치의 통합을 수행하려 할 때 발생하기 때문이다. 이 경우 협상의 목적은 시스템에 접근하기 위해 어떤 자격 증명이 필요한지에 대한 안내를 제공하는 것이다.
탐색 서비스가 시스템 관리를 자동화하는 데 사용되는 경우에는 관련 탐색 서비스에 접근하는 데 필요한 자격 증명 (및 인증 메커니즘)을 미리 수립하는 것이 가장 좋으며, 보안 부트스트래핑은 필요하지 않다. 이러한 이유로 보안 부트스트래핑은 필수 기능이 아니며, 미리 수립된 보안 메커니즘과 함께 사용될 장치에서는 생략하거나 비활성화할 수 있다.
보안 부트스트래핑은 TD에 대한 첫 번째 접근에서만 필요할 수도 있다. 디스커버러가 특정 탐색 서비스에 접근하는 데 필요한 자격 증명과 인증 메커니즘을 결정하면, 이 정보를 보관하고 향후 접근에 사용하려고 시도할 수 있다. 그러나 사용되는 보안 체계에 따라 자격 증명 자체가 만료될 수 있으며 주기적으로 다시 수립해야 할 수도 있다는 점에 유의한다.
보안 부트스트래핑은 TD를
제공하는 모든 HTTP 엔드포인트에서 제공될 수
MAY 있다. 위에서 언급했듯이,
보안 메커니즘이 이전에 수립되어 있다면 보안 부트스트래핑을
비활성화하거나 생략하는 것이 허용된다. 예를 들어, 어떤
설치가 OAuth2 client 흐름을 사용하고 잠재적
클라이언트에게 사용할 인증 서버의 주소를 미리 제공하려는
경우, 보안 부트스트래핑을 비활성화할 수 있다. 대안은
다른(그리고 잠재적으로 더 약한) 인증 형식을 포함하는 것이기
때문이다.
HTTP 프로토콜에서 사용할 인증 및 권한 부여
메커니즘은 일반적으로 HTTP 서버가 필요한 정보를 지정하는
WWW-Authenticate 헤더와 함께 "401
(Unauthorized)" 응답 코드를 반환함으로써 협상될 수 있다.
접근 권한을 얻기 위해 클라이언트는 필요한 정보를 포함하여
또 다른 요청을 해야 한다.
IANA에 등록된 여러 인증 체계가 있다. 그러나 이들
모두가 널리 사용되는 것은 아니며, 일부는 실험적이고,
TD가 지원하는 체계와는 부분적으로만 겹친다. 또한 IANA
등록의 oauth 체계는 폐기된 OAuth1을 가리키므로
사용해서는 안 된다는 점에 유의한다. 관련 OAuth2 흐름인
code 흐름은 401 응답 대신 인증 서버로의
리디렉션으로 시작하며, 최종적으로 접근에 사용할 수 있는
자격 증명(WoT의 경우 bearer 토큰)을 생성한다.
이러한 고려 사항을 바탕으로, 다양한 장치와 브라우저에서 보안 부트스트래핑을 가능하게 하려면 다음 제약 조건을 준수해야 한다:
WWW-Authenticate 헤더와
필요한 권한 부여를 설명하는 기타 헤더를 포함해야 한다.
요구사항의 세부사항은 위 인증 체계 각각에 대해 IANA
레지스트리를 참조해야 한다. 마찬가지로 OAuth2 명세에
따라, 보안 부트스트래핑 중 OAuth2 code
흐름이 사용되는 경우 인증 서버로 리디렉션하기 위해
"302 (Found)" 또는 "303 (See Other)" 응답 코드를
사용해야 하며, 접근 자격 증명은 최종적으로 bearer
토큰으로 표현된다. WoT 사물 설명 1.1에서 지원되는 다른
OAuth2 흐름인 client는 초기 접근이 최종
엔드포인트가 아니라 인증 서버로 이루어질 것을 기대하므로
보안 부트스트래핑을 통해 사용할 수 없다는 점에 유의한다.
이러한 요구사항은 보안 부트스트래핑을 지원해야 할 수도
있는 탐색 서비스의 엔드포인트, 즉 TD를 제공하는
엔드포인트에만 적용되며, 동일한 탐색 서비스가 제공할 수
있는 다른 엔드포인트에는 적용되지 않는다. 특히 이러한
요구사항은 도입 메커니즘이 참조할 수 있는 URL에만
적용되며, 예를 들어 이벤트 구독 엔드포인트에는 적용되지
않는다.
[wot-architecture11] 및 [wot-thing-description11]에는 TD 접근에 인증이 필요한 경우와 보안 전송의 사용에 관한 관련 보안 및 개인정보 보호 고려 사항이 있다. 9. 개인정보 보호 고려 사항도 참조하라. 요약하면, 보안 전송(예: TLS)은 공개 서비스에 필요하며, 사설 네트워크에서도 (인증 요구사항이 없더라도 질의의 기밀성을 보호하기 위해) 강력히 권장된다. 또한 인증과 권한 부여 없이 요청을 제공하는 것은 개인 식별 정보가 존재하지 않거나 추론될 수 없는 제한된 상황에서만 고려해야 한다.
URL로 참조될 수 있고 적절한 인증과 접근 제어를 통해 TD를 반환할 수 있는 모든 웹 서비스는 탐색 메커니즘으로 사용될 수 있다. 이를 사물 설명 서버 또는 TD 서버라고 부른다. TD 서버는 사물일 필요가 없다. 특히 TD는 일반 웹 서버에 호스팅되고 그 URL로 참조될 수 있다.
TD 서버는 자기 설명을 지원하는 데 사용될 수 있다. 자기 설명의 경우, 사물은 자신의 TD를 호스팅하고 URL로 식별되는 웹 리소스를 통해 사용할 수 있게 한다. 그러나 이러한 웹 리소스는 TD 자체의 어포던스에는 포함되지 않는다. 이 웹 리소스는 6.2 잘 알려진 URI에 정의된 도입 메커니즘으로 사용되는 잘 알려진 URL과 같을 수도 있고 다를 수도 있다.
보안 전송의 사용은 [wot-architecture11] 및 [wot-thing-description11] 명세의 보안 고려 사항 및 개인정보 보호 고려 사항 섹션에 제시된 단언의 적용을 받는다. 이들 명세는 보안 전송이 권장되거나 필수인 시나리오와 상호 인증이 권장되는 시나리오를 정의한다.
다음 프로토콜을 사용하여 TD를 배포하는 TD 서버는 다음 제약 조건의 적용을 받는다:
HTTP 기반 TD 서버가
TD를
제공하는 경우
그 리소스를 GET 메서드로 제공해야
MUST 한다. HTTP 기반 TD 서버가
TD를
제공하는 경우 성공 응답은
200 (OK) 상태와 본문 안의 TD를
가져야 MUST 한다.
JSON 직렬화를 포함한 성공
응답은 Content-Type 헤더에
application/json 또는
application/td+json 중 하나를 포함해야
MUST 한다. 여기서
application/td+json은 더 구체적이고
application/json을 함의하므로 선호된다.
성공 응답 본문의 기본
직렬화 형식은 JSON-LD 1.1
[JSON-LD11] 구문을 사용하는 JSON이어야
MUST 한다. JSON-LD 구문은 의미
확장과 처리를 허용한다.
HTTP 기반 TD 서버가
TD를
제공하는 경우, 서버 주도
콘텐츠 협상, 즉 요청의 Accept 및 Accept-Encoding
헤더를 존중하고 지원되는 TD 직렬화 및 이에 상응하는
Content-Type과 Content-Encoding 헤더로 응답함으로써
대체 표현을 제공할 수 MAY 있다. 또한
WoT 사물 설명 1.1 명세
[wot-thing-description11]에서
규범적으로 정의된 절차에 따라, HTTP 기반 TD 서버가
TD를 제공하는
경우 서버 주도 콘텐츠 협상,
즉 요청의 Accept-Language 헤더를 존중함으로써 다른 기본
언어를 사용한 수정된 TD 또는 오류 응답을 제공할 수
있다.
HTTP 기반 TD 서버가
TD를
제공하는 경우,
동일한 엔드포인트에 대한 GET 요청에서
반환되는 것과 동등한 헤더만 반환하여
HEAD 요청에 응답해야
MUST 한다. 이를 통해 클라이언트는
Content-Length 같은 HTTP 헤더를 미리 가져와
TD의 크기(바이트
단위)를 알고
효율적인 질의 전략을 결정할 수 있다.
제약된 환경에서는 단일 TD가 서버나 클라이언트가 처리하기에 너무 클 수 있다. 요청된 페이로드의 점진적 전송에 대한 프로토콜별 권장 사항은 10.1 점진적 전송을 참조하라.
오류 응답:
CoAP 기반 TD 서버가
TD를
제공하는 경우
그 리소스를 GET 메서드로 제공해야
MUST 한다. CoAP 기반 TD 서버가
TD를
제공하는 경우 성공 응답은 2.05 (Content) 상태를 가져야
MUST 하며, 값 50
(application/json) 또는 432
(application/td+json)의 Content-Format 옵션과 페이로드 안의
TD를
포함해야 한다.
Content-Format 432는 더 구체적이고 Content-Format 50을
함의하므로 선호된다. 페이로드는 블록 단위 전송
[RFC7959]을
사용하여 여러 메시지 교환으로 분할될 수 있음에 유의한다.
CoAP 기반 TD 서버가
TD를
제공하는 경우, 서버 주도
콘텐츠 협상, 즉 요청의 Accept 옵션을 존중하고
지원되는 TD 직렬화 및 이에 상응하는
Content-Format 옵션으로 응답함으로써 대체 표현을
제공할 수 MAY 있다.
CoAP 기반 TD 서버가 TD를 제공하는 경우, Size2 옵션을 포함하는 요청에 대해 다음 응답에 TD의 크기 추정치를 포함하여 응답하는 것이 좋다 SHOULD. 이는 블록 단위 전송을 사용하여 TD를 얻을 때 관련이 있으며, 전체 페이로드 크기가 클라이언트가 처리하기에 너무 클 경우 클라이언트가 검색을 중단할 수 있게 한다.
제약된 환경에서는 단일 TD가 서버나 클라이언트가 처리하기에 너무 클 수 있다. 요청된 페이로드의 점진적 전송에 대한 프로토콜별 권장 사항은 10.1 점진적 전송을 참조하라.
오류 응답:
사물 설명 디렉터리(줄여서 TDD 또는 디렉터리)는 다른 사물을 설명하는 TD 집합을 관리하는 서비스를 제공하는 사물이다.
그림 4에 표시된 것처럼, 사물 설명 디렉터리는 0개 이상의 TD를 포함할 수 있다. 각 TD에 대해 디렉터리는 장부 관리 및 검색 목적을 위한 추가 메타데이터를 유지한다. 이는 7.3.1.1 등록 정보 및 7.3.1.3 익명 TD 식별자에서 설명된다. 디렉터리와의 상호작용 일부로 그러한 추가 메타데이터를 포함하는 TD를 보강된 TD라고 한다.
디스커버리 컨텍스트에서의 TD 온톨로지는
그림 5에서 소개되었다.
RegistrationInformation 클래스는
디렉터리에 저장된 TD와
연결된다. 다음 표는 디스커버리 컨텍스트를 포함하거나
참조하는 TD
내에서
사용할 등록 정보 속성을 나열한다. 등록 정보를 포함하는
것은 보강된
TD뿐이라는 점에 유의한다. 보강된
TD는 자신의 @context에 URI
https://www.w3.org/2022/wot/discovery를
포함해야 MUST 한다.
이 표에서 클라이언트는 TD의
생산자 또는 소비자를 가리키며,
서버는 사물
설명 디렉터리를 가리킨다.
절대 시간이 dateTime을 사용하여 표현될 때마다, 이는 [RFC3339]에 명시된 date-time으로 해석되어야 MUST 한다. 구체적으로, 시간대 오프셋은 선택 사항이 아니다.
온톨로지를 업데이트하여 date-time과 RFC3339만 사용하고 dateTime과 date-time의 이상한 조합은 사용하지 않도록 해야 하지만, 이는 TD 명세에서도 해결되어야 한다. 그러나 이 추가 제한을 가진 새로운 SHACL shape가 필요할 것이다.
| 어휘 용어 | 설명 | 클라이언트 할당 | 서버 할당 | 유형 |
|---|---|---|---|---|
created |
TD 인스턴스가 디렉터리 내부에서 생성된 절대
시간을 제공한다.
이는 디렉터리가 설정하고 소비자에게 반환할 수 MAY 있다. |
읽기 전용 | 선택 사항 |
dateTime
|
modified |
TD 인스턴스가 디렉터리 내부에서 마지막으로
수정된 절대 시간을 제공한다.
이는 디렉터리가 설정하고 소비자에게 반환할 수 MAY 있다. |
읽기 전용 | 선택 사항 |
dateTime
|
expires |
TD 인스턴스 등록이 만료되는 절대 시간을
제공한다.
생산자는 등록 중 절대 만료 시간을 나타내기 위해 이를 설정할 수 MAY 있다. 만료 가능한 TD를 지원하는 서버의 경우:
|
선택 사항 | 선택 사항 |
dateTime
|
ttl |
Time-to-live: 등록 시간부터 TD 인스턴스 등록이
만료될 때까지의 상대 시간(초 단위).
생산자는 등록 중 상대 만료 시간을 나타내기 위해 이를 설정할 수 MAY 있다. 만료 가능한 TD를 지원하는 서버의 경우:
서버는 |
선택 사항 | 읽기 전용 | number |
retrieved |
TD가 서버에서 검색된 절대 시간.
이는 다른 절대 타임스탬프를 처리하려 하지만 내부 시계나 현재 시간을 획득할 다른 수단이 없는 클라이언트에게 유용하다. |
읽기 전용 | 선택 사항 |
dateTime
|
생산자는 만료 시간을 설정하여 디렉터리와 다른 소비자에게 TD 등록의 유효성을 알릴 수 있다. 만료는 동적 TD의 만료를 소비자에게 알리는 데에도 유용한 지표이다. 예를 들어 지리적 위치나 속성 같은 메타데이터 변경 사항이 제한된 기간 동안 유효할 것으로 예상되는 경우가 이에 해당한다. 소비자는 만료 시간에 의존하여 검색한 TD가 얼마나 오래 유효할지, 그리고 언제 더 최신의 TD를 요청해야 하는지를 알 수 있다. 만료된 TD를 검색한 소비자는 이를 비활성 클라이언트의 메타데이터로 간주할 수 있다.
서버의 경우, 만료 시간은 오래되었거나 우발적인 등록의 자동 제거를 구현하는 데 유용하다. 서버는 만료 시간이 지난 TD를 주기적으로 제거하는 것이 좋다 SHOULD. 만료 시간에 대해 전역적인 의무사항이나 상한을 규정하는 것은 애플리케이션별 사항이며 이 명세의 범위를 벗어난다. 서버는 만료 시간에 대한 구성 가능한 상한을 의무화하거나 설정할 수 있으며, 준수하지 않는 요청을 거부할 수 있다. 서버에 의한 제거는 자신의 TD를 명시적으로 등록 해제할 수 없는 클라이언트(예: IoT 장치)와 상호작용할 때 특히 유익하다. 이는 프로토콜별 제한, 장애, 파손 또는 비정상적인 폐기 때문일 수 있다. 그러한 클라이언트는 합리적으로 짧은 만료 시간을 설정하고 정상 동작 중에 이를 주기적으로 연장해야 한다. 만료는 TD에 변경을 가하지 않는 업데이트를 포함하여, 등록을 전체적으로 또는 부분적으로 업데이트함으로써 연장할 수 있다. 7.3.2.1.3 업데이트를 참조하라. 클라이언트가 동작을 중단하면, 제거 기능을 가진 디렉터리가 그 등록을 자동으로 제거한다.
id로
로컬 식별자를 추가해야 MUST 한다.
로컬 식별자는
URN [RFC4122]으로
표현된 UUID 버전 4인 것이 좋다
SHOULD.
UUID 버전 4는 호스트나 리소스에 대한 의도하지 않은 정보를
포함하지 않는 난수 또는 의사 난수이다.
디렉터리 서비스는 시스템 사용자 데이터에 대한 접근을 제공하므로 적절한 보안 및 개인정보 보호를 제공해야 한다. WoT 디렉터리 서비스 API 구현에서 진정성과 기밀성을 위한 보안 전송 프로토콜 및 접근 제어의 사용은 [wot-architecture11]에 제시된 보안 고려 사항 및 개인정보 보호 고려 사항의 적용을 받는다.
HTTP API 응답은 이 섹션에서 성공 및 오류 응답에 대해
설명한 적절한 상태 코드를 사용해야 한다.
HTTP API는 HTTP 클라이언트 오류(4xx) 및
서버 오류(5xx) 응답에서 오류 세부 정보를 전달하기 위해
Problem Details
[RFC7807] 형식을
사용해야 MUST 한다. 이를 통해 기계와
사람이 모두 고수준 오류 클래스와 세부 정보를 알 수 있다.
Problem Details를 사용하여
설명되는 모든 HTTP API 오류 응답은 UTF-8로 인코딩되어야
MUST 한다.
HTTP API 오류 응답은 HTTP 요청에서
Accept-Language 헤더 필드가 설정된 경우,
사전 협상을 사용하여 다른 언어로 세부 정보를 보고할 수
MAY 있다 [RFC7231].
API는 [RFC7231]의 섹션 6에 정의된 HTTP 상태 코드를 설정한다. 사용되는 오류 코드 목록에는 다음이 포함된다(이에 국한되지는 않음):
WWW-Authenticate 헤더에 포함된다.
GET
메서드에 응답하는 각 HTTP 엔드포인트에 대해, 서버는
HEAD 요청을 수락하고 헤더만 반환해야
MUST 한다. 이를 통해 클라이언트는 본문을
수신하지 않고 Content-Length 같은 헤더를 검색하고
정보를 질의하기 위한 적절한 전략을 결정할 수 있다. 예를
들어 제약된 클라이언트는 객체의 필요한 부분만 요청하거나
(적절한 검색 질의를 사용하여) 항목 목록을 작은 하위 집합으로
검색할 수 있다.
제약된 환경에서는 단일 TD가 서버나 클라이언트가 처리하기에 너무 클 수 있다. 이는 읽기(즉, 하나 이상의 TD 또는 TD 조각 검색) 작업과 쓰기(즉, TD 또는 부분 TD 제출) 작업 모두에 영향을 준다. 페이로드의 점진적 전송에 대한 프로토콜별 권장 사항은 10.1 점진적 전송을 참조하라.
URL을 통한 안전한 데이터 전송을 보장하기 위해, 클라이언트와 서버 모두 URL의 나머지 부분에서 구분자와 충돌하는 문자를 퍼센트 인코딩/디코딩할 것으로 기대된다. 이러한 문자는 [RFC1738]의 섹션 2.2에서 안전하지 않은 문자로 정의된다. 안전하지 않은 문자가 URL에 나타나면, 예를 들어 경로에 포함된 리소스 ID가 그 자체로 URL이거나 검색 질의 문자열에 포함되는 경우, 예상치 못한 동작이 발생할 수 있다.
디렉터리 API에는 필수, 권장 및 선택 기능이 포함된다. 디렉터리가 지원하지 않는 권장 또는 선택 기능 때문에 요청에 응답할 수 없는 경우, 적절한 HTTP 오류를 반환하여 해당 기능이 없음을 클라이언트에게 알려야 SHOULD 한다. 다음 예제는 구현을 위한 지침으로 사용할 수 있다:
/search/sparql 엔드포인트), 404 (Not
Found)를 사용한다.
/things 엔드포인트의
PATCH), 405 (Method Not
Allowed)를 사용한다.
TD에 이미 제공된 번역을 사용하여 TD의 기본 언어를 수정하는 절차는 WoT 사물 설명 1.1 명세 [wot-thing-description11]에서 규범적으로 설명된다. 이 절차를 사용하면, 디렉터리 서버는 서버 주도 콘텐츠 협상, 즉 요청의 Accept-Language 헤더를 존중함으로써 다른 기본 언어를 사용한 수정된 TD 또는 자신의 TD를 제공할 수 있다.
사물 API는 /things 엔드포인트에서 제공되는
RESTful HTTP API로, TD를 생성, 조회, 업데이트, 삭제 및
목록화(CRUDL)하기 위한 인터페이스를 제공한다. 이
API의 설계는 [RFC7231]
및 [REST-IOT]에 따른다.
HTTP API는 다음 일반 규칙을 따른다:
CRUDL 작업은 다음 섹션에서 설명된다:
생성은 디렉터리 내부에 새로운 TD를 등록하는 것을 의미한다.
TD 객체는 7.3.2.1.6 유효성 검사에 따라 검증된다. TD는 그것이 설명하는 사물에 의해 생성될 수도 있고 그렇지 않을 수도 있음에 유의한다. 특히 브라운필드 장치의 경우, 해당 장치를 대신하여 사물에 대한 TD를 생성하고 등록하는 별도의 디스커버러 프로세스 또는 서비스가 필요할 수 있다.
id
속성으로
식별되는 TD는 식별자가 없는 TD(익명
TD)와 다르게 처리되어야 MUST 한다.
생성 작업은 아래에서 자세히 설명된다:
id를 가진 TD는
HTTP PUT 요청의 본문으로
/things/{id} 엔드포인트에 제출되어야
MUST 하며, 여기서
id는 TD 객체 내부에 존재하는 고유 TD
식별자이다. 익명
TD는 다르게 처리된다. 아래를 참조하라.
요청은 TD의 JSON
직렬화를 위해
application/td+json Content-Type
헤더를 포함하는 것이 좋다 SHOULD. TD
객체는 7.3.2.1.6
유효성 검사에 따라 검증된다. 성공적으로 처리되면,
서버는 201 (Created) 상태로 응답해야
MUST 한다.
참고: 대상 위치가 기존 TD에 해당하는 경우, 요청은 대신 업데이트 작업으로 진행되고 적절한 상태 코드로 응답해야 한다(업데이트 섹션 참조).
식별자를 가진 TD의 생성 작업은
7.3.2.4 API
명세(사물 모델)의 createThing
액션으로 지정된다.
POST 요청의 본문으로
/things 엔드포인트에 제출되어야
MUST 한다. 요청은 TD의 JSON 직렬화를 위해
application/td+json Content-Type
헤더를 포함하는 것이 좋다 SHOULD. TD
객체는 7.3.2.1.6
유효성 검사에 따라 검증된다. 디렉터리는 디렉터리에서 로컬 관리와 검색을
가능하게 하기 위해 모든 익명
TD에 로컬 식별자를 할당해야
MUST 한다. 시스템 생성 ID의
체계는 7.3.1.3
익명 TD 식별자에 설명되어 있다. 성공적으로 처리되면,
서버는 201 (Created) 상태와 생성된 TD 리소스의
시스템 생성 URI를 포함하는 Location 헤더로 응답해야
MUST 한다.
시스템 생성 URI에는 TD의 시스템 생성 식별자가
포함되며, 이후 디렉터리에서 TD를 질의하는 데 사용할 수
있다.
익명
TD의 생성 작업은
7.3.2.4 API
명세(사물 모델)의
createAnonymousThing 액션으로 지정된다.
만료 가능한 TD를 지원하는 서버는
7.3.1.2
등록 만료에 설명된 대로 이러한 기능을 실현한다.
특히 생성 중에 ttl(상대 만료)이 주어지면,
그러한 서버는 expires 값을 계산하고 저장한다.
기존 TD의 조회는 HTTP
GET 요청을 사용하여
/things/{id} 엔드포인트에서 수행되어야
MUST 하며, 여기서 id는 고유 TD
식별자이다. 성공 응답은
200 (OK) 상태와 본문의 요청된 TD를 가져야
MUST 한다. JSON 직렬화를 포함한 성공 응답은
Content-Type 헤더에 application/json 또는
application/td+json 중 하나를 포함해야
MUST 한다. 여기서
application/td+json은 더 구체적이고
application/json을 함의하므로 선호된다.
기본 직렬화는 JSON-LD 구문을 사용하는 JSON이며,
대체 직렬화는 협상할 수 있음에 유의한다.
7.3.2.1 사물
API를 참조하라.
조회 작업은 7.3.2.4 API 명세(사물
모델)의 retrieveThing 액션으로 지정된다.
다음은 조회된 TD의 예이다:
이는 디렉터리 내 TD의 생성 및 수정 시간과 같은 등록 정보를 포함하는 보강된 TD이다.
아래 예제는 익명
TD가 보강된
TD 형식으로 조회되었고 로컬 식별자
urn:uuid:48951ff3-4019-4e67-b217-dbbf011873dc를
가진 경우를 보여준다.
다음은 3600초(1시간)의 상대 만료 시간으로 등록된 조회 TD의 예이다. 서버는 수정 시간으로부터 1시간 뒤를 절대 만료 시간으로 계산했다.
가독성을 위해 이 예제의 시간 값은 정확한 숫자로 설정되어 있다. 실제 설정에서는 시간 값에 소수부가 포함될 수 있다.
업데이트 작업은 기존 TD를 대체하거나 부분적으로 수정하는 것이다.
업데이트 작업은 아래에 설명되어 있다:
id가 있는
/things/{id} 엔드포인트에 HTTP
PUT 요청으로 제출될 때 기존 TD를
대체해야 MUST 한다.
요청은 TD의 JSON 직렬화를 위해
application/td+json Content-Type
헤더를 포함하는 것이 좋다
SHOULD. TD 객체는
7.3.2.1.6
유효성 검사에 따라 검증된다.
성공 시 서버는
204 (No Content) 상태로 응답해야
MUST 한다.
이 작업은 7.3.2.4 API
명세(사물 모델)의 updateThing
속성으로 지정된다.
만료 가능한 TD를 지원하는 서버는
7.3.1.2
등록 만료에 설명된 대로 이러한 기능을
실현한다. 업데이트 작업 중 ttl
(상대 만료)이 설정된 경우, 서버는
expires(절대 만료) 값을 계산하고 설정한다.
참고: 대상 위치가 기존 TD에 해당하지 않는
경우, 요청은 대신 생성 작업으로 진행되고
적절한 상태 코드로 응답해야 한다(생성 섹션
참조). 즉, HTTP PUT 요청은 생성 또는
업데이트 작업으로 동작한다.
id가 있는
/things/{id} 엔드포인트에 HTTP
PATCH 요청으로 제출될 때 기존 TD는
부분적으로 수정되어야 MUST 한다.
부분 업데이트는
[RFC7396]에 설명된 JSON merge patch
형식을 사용하여 처리되어야 MUST 한다.
요청은 merge
patch 문서의
JSON 직렬화를 위해
application/merge-patch+json
Content-Type 헤더를 포함해야
MUST 한다. 입력은
부분
TD 형식이어야 MUST 하며 원래 TD
구조를 준수해야 한다. 입력에 원래 TD에
나타나는 멤버가 포함된 경우, 해당 값은 대체된다.
멤버가 원래 TD에 나타나지 않으면 그 멤버가
추가된다. 멤버가 null로 설정되어 있고
원래 TD에 나타나는 경우, 해당 멤버는 제거된다.
객체 값을 가진 멤버는 재귀적으로 처리된다.
수정을 적용한 후 TD 객체는
7.3.2.1.6
유효성 검사에 따라 검증된다.
성공 시 서버는
204 (No Content) 상태로 응답해야
MUST 한다.
이 작업은
7.3.2.4 API
명세(사물 모델)의
partiallyUpdateThing 속성으로 지정된다.
만료 가능한 TD를 지원하는 서버는
7.3.1.2
등록 만료에 설명된 대로 이러한 기능을
실현한다. 부분 업데이트 작업 중 결과 TD에 ttl
(상대 만료)이 있는 경우, 서버는 새
expires(절대 만료) 값을 계산하고
설정한다.
패치 작업은 ttl(상대 만료) 값을
사용하는 등록의 만료를 효율적으로 연장하는 데
특히 유용하다. 이는 일반적으로 빈 merge patch
문서, 즉 빈 JSON 객체를 제출함으로써 수행된다.
이는 사실상 아무것도 업데이트하지 않지만
expires(절대 만료) 값의 재계산을
트리거하는 부분 업데이트 작업을 수행하는 것으로
해석된다. 이 만료 기능은 서버가
7.3.1.2
등록 만료에 정의된 대로 이를 지원하는
경우에만 동작한다.
다음 예제는 TD의 base 및
등록 expires 필드만 업데이트하기 위한
merge patch 문서이다:
삭제 작업은 기존 TD의 식별자인
id가 있는
/things/{id}에서 HTTP
DELETE 요청을 사용하여 수행되어야
MUST 한다. 성공 응답은
204 (No Content) 상태를 가져야
MUST 한다. 조회 작업은
7.3.2.4 API 명세(사물
모델)의 deleteThing 속성으로 지정된다.
목록화 엔드포인트는 디렉터리에서 전체 TD 객체 컬렉션을 질의하는 여러 방법을 제공한다.
많은 시나리오에서는 전체 TD 객체 대신 일부를 검색하는
것이 선호된다. 필요한 요소가 일부뿐이기 때문이며
(예: 모든 TD에 대한 속성의 id 및
href), 네트워크 자원을 절약하기 위해서이기도
하다. 검색 API는 TD 객체의 일부를 질의할 수 있게 한다.
7.3.2.3 검색
API를 참조하라.
디렉터리는 /things
엔드포인트에서 HTTP GET 요청을 사용하여
기존 TD를 검색할 수 있게 해야
MUST 한다. 성공 응답은
200 (OK) 상태와 본문의 TD 배열을 가져야
MUST 한다.
JSON 직렬화를 포함한 성공
응답은 Content-Type 헤더에
application/json 또는
application/ld+json 중 하나를 포함해야
MUST 한다. 여기서
application/ld+json은 더 구체적이고
application/json을 함의하므로 선호된다.
기본 직렬화는 JSON-LD 구문을 사용하는 JSON이며,
대체 직렬화는 협상할 수 있음에 유의한다.
7.3.2.1 사물
API를 참조하라.
클라이언트가 TD의 작은 하위 집합으로 컬렉션을 검색해야 하는 시나리오가 있을 수 있다. 검색 API (7.3.2.3 검색 API)는 특정 범위를 질의하는 기능을 제공하지만, 이것이 최적이거나 개발자 친화적이지는 않을 수 있다. 서버는 컬렉션을 작은 하위 집합으로 반환하기 위해 페이지네이션을 지원할 수 MAY 있다. 페이지네이션은 다음 규칙을 기반으로 해야 한다:
limit
질의 매개변수가 양의 정수로 설정된 경우,
서버는 요청된 수 이하의 TD로 이루어진 하위 집합으로
응답할 수 MAY 있다.next Link
헤더 [RFC8288]를 포함해야
MUST 한다. next
링크는 동일한 데이터 집합과 그 순서를 생성하는 데
필요한 모든 인수를 포함해야 MUST 하며,
특히 초기 요청에서 주어진 동일한
limit 인수와 다음 하위 집합의 시작에
고정된 0 기반 offset 인수를 포함해야
한다. 링크는 절대 URL이거나
디렉터리 API의 기본 URL에 상대적이어야
MUST 한다.
또한 정렬 또는 세션 관리에 필요한 추가 인수를
포함할 수 있다.etag 매개변수를 포함한
canonical Link 헤더 [RFC8288]를 포함해야
MUST 한다. 링크는 절대 URL이거나
디렉터리 API의 기본 URL에 상대적일 수 있다.
etag 값은 TD 컬렉션이 TD의 순서에 영향을
주는 방식으로 변경될 때마다 설정되는 개정 번호,
타임스탬프 또는 UUID 버전 4일 수 있다. 클라이언트는
컬렉션의 페이지별 검색 중 컬렉션이 일관된 상태를
유지하는지 알기 위해 etag 값에 의존할 수
있다. 예를 들어 TD의 생성 또는 삭제, 또는 정렬에
사용되는 TD 필드의 업데이트는 계산된 페이징 창을
이동시킬 수 있다.
위 명세는 JSON-LD 배열의 선택적 페이지네이션을 허용하기 위해 Linked Data Paging [LDP-Paging]의 하위 집합을 따른다. Linked Data Paging의 추가 부분은 예를 들어 클라이언트의 질의 선호를 존중하거나 의미 주석 및 대체 탐색 링크를 위한 다른 링크 관계를 추가하기 위해 구현될 수 있다.
다음 예제는 TD의 페이지별 검색 절차를 보여준다:
응답 본문의 TD 배열 대신, 서버는 실제 데이터 외에도 페이지네이션 정보와 같은 서버 측 정보를 포함할 수 있는 더 자세한 페이로드를 보낼 수 MAY 있다.
대체 페이지네이션 형식은 Hydra Advanced Concepts, 더 구체적으로 Partial Collection View에서 영감을 받은 것이다. 우리의 목적에 맞게 조정하고 TD 배열을 수용하기 위해 members 필드를 사용하면, 목록화 엔드포인트의 경우 다음과 같다:
서버에 어떤 형식을 보낼지 알리기 위해, 추가 질의
매개변수
?format=array|collection을 요청에 추가할 수
있다. ?format=array는 기본 매개변수이며,
명시적으로 제공할 필요가 없고, 서버 응답으로 순수 TD
배열을 산출한다.
?format=collection은
예제
9에 설명된 형식의 서버 응답을 산출해야
한다.
목록화 작업은 7.3.2.4 API 명세(사물
모델)의 things 속성으로 지정된다.
저장 전에 TD 객체의 구문적
유효성 검사를 수행하는 것은 흔한 잘못된 제출을
방지하기 위해 권장된다 RECOMMENDED.
서버는 TD를 검증하기 위해
[wot-thing-description11]에 정의된
최소 유효성 검사를 적어도 사용하고, 필요에 따라
WoT 사물 설명(1.0) JSON Schema 또는
WoT 사물 설명 1.1 JSON Schema와
A. WoT 디스커버리 TD 확장을 위한
JSON Schema에 정의된 JSON 스키마를
보강된
TD에 대해 @context 값에 적절하게
사용해야 SHOULD 한다.
다양한 사용 사례를 지원하기 위해 추가적인 형태의
유효성 검사를 더할 수 있다. 예를 들어, 어떤 사용 사례는
version 값이 사전 정의된 규칙에 따라 초기화되고
업데이트되는지 보장하기 위해 입력 TD의 상태 기반 유효성
검사를 요구할 수 있다.
서버가 TD 객체의 유효성 검사에
실패한 경우, 오류를 식별하고 해결하는 데 필요한
세부 정보를 클라이언트에게 알려야
MUST 한다. 유효성 검사 오류는
validationErrors라는 확장 필드를 가진
Problem Details [RFC7807]로
설명되어야 MUST 하며, 이 필드는
field 및
description 필드를 가진 객체 배열로
설정된다. 이는 오류를 기계가 읽을 수 있는 방식으로
표현하기 위해 필요하다. Problem
Details를 사용하여
설명되는 모든 유효성 검사 오류 응답은 UTF-8로
인코딩되어야 MUST 한다. 오류 보고에 대해
일반적으로 이미 언급했듯이, HTTP 요청에서
Accept-Language 헤더 필드가 설정된 경우
유효성 검사 오류 응답은 사전 협상을 사용하여 다른
언어로 세부 정보를 보고할 수 있다 [RFC7231].
예제 10은 두 개의 유효성 검사 오류를 포함한 오류 응답의 예이다.
알림 API는 디렉터리 내에서 유지되는 TD의 변경 사항을 클라이언트에게 알리기 위한 것이다. 디렉터리는 알림 API를 구현할 수 MAY 있다.
알림 API는
/events 엔드포인트에서 클라이언트에게 이벤트를
제공하기 위해 Server-Sent Events(SSE)
[HTML] 명세를 따라야
MUST 한다. 특히 서버는 성공 요청에 대해
200 (OK) 상태와 text/event-stream Content Type으로
응답한다. 다시 연결하는 클라이언트는 마지막 이벤트 ID를
Last-Event-ID 헤더 값으로 제공하여 마지막
이벤트부터 계속할 수 있다. 서버는 각 이벤트의
id 필드로 이벤트 ID를 제공하고, 다시
연결하는 클라이언트에게 누락된 모든 이벤트를 전달하는
것이 좋다 SHOULD.
이 섹션의 나머지 부분은 SSE 프로토콜 위에서의 구현 세부사항을 설명한다. MQTT와 같은 다른 프로토콜을 사용해 알림 기능을 실현하는 것도 가능하며, 이 명세의 향후 버전에서 공식화될 수 있다.
thing_created,
thing_updated, 및
thing_deleted 이벤트 유형을 사용하여
생성해야 MUST 한다.서버는 구독 시 클라이언트가 제공한 이벤트 유형을 기반으로 이벤트 필터링을 지원해야 MUST 한다.
예를 들어 URI Template
/events{/type}가 주어진 경우:
/events/thing_created는
thing_created 유형의 이벤트만
전달하도록 서버에 지시한다
/events는 모든 이벤트를
전달하도록 서버에 지시한다클라이언트는 서버에서 이벤트의 하위 집합(예:
thing_created 및
thing_deleted만)을 받기 위해 별도로
구독해야 한다. HTTP/2를 사용할 때, 동일한
도메인의 여러 구독(HTTP 스트림)은 하나의 연결에서
다중화된다.
이벤트 데이터는 이벤트 객체의 JSON 직렬화를 포함해야 MUST 한다. 이벤트 데이터 객체는 요청에 따라 부분 TD 또는 전체 TD 객체이다:
diff
질의 매개변수가 true로 설정되고
이벤트가 thing_created 유형인 경우,
서버는 전체 TD 객체를 이벤트 데이터로 반환할 수
MAY 있다.
diff
질의 매개변수가 true로 설정되고
이벤트가 thing_updated 유형인 경우,
서버는 JSON Merge Patch [RFC7396]
형식에 따라 업데이트된 부분을 클라이언트에게
알릴 수 MAY 있다. JSON Merge Patch
[RFC7396]에 기반한
thing_updated 이벤트 데이터는 변경
여부와 관계없이 항상 TD의 식별자를 포함해야
MUST 한다.
다음 예제는 예제 12의 TD 업데이트 시 트리거된 이벤트를 보여준다:
diff
질의 매개변수는 thing_deleted 이벤트에
대해 무시되어야 MUST 한다. 즉,
diff가 true로 설정된 경우에도
서버는 thing_deleted 이벤트의 페이로드에
추가 속성을 포함하지 않아야 한다.
diff 질의 매개변수를 지원하지 않는
서버가 그러한 질의 매개변수로 요청을 받은 경우,
요청을 거부해야 한다. 이는 연결 시점에 클라이언트에게
그러한 기능이 없음을 알리고, 이벤트 데이터 속성
누락으로 인한 런타임 예외를 피하기 위한 것이다.
알림 API는 7.3.2.4 API
명세(사물 모델)에서 세 가지 이벤트 어포던스로
지정된다. 즉:
thingCreated, thingUpdated, 및
thingDeleted.
일부 초기 SSE 구현(HTML5 EventSource 포함)은 초기 HTTP 요청에서 사용자 지정 헤더 설정을 허용하지 않는다. Authorization 헤더는 일부 OAuth2 흐름에서 필요하며, 이를 질의 매개변수로 전달하는 것은 권장되지 않는다. 브라우저용 폴리필과 Authorization 헤더 설정을 허용하는 현대적인 라이브러리가 있다.
디렉터리를 검색하기 위한 하위 API, 예를 들어
질의를 실행하는 API이다. 가능한 질의에는 다양한
형식과 수준이 있다. 예를 들어 구문적(JSONPath, XPath) 질의와
의미적(SPARQL) 질의가 있으며, 더 고급 질의 유형은 모든
디렉터리에서 지원되지 않을 수 있다. 따라서 이 API에는
추가 하위 섹션이 있으며, 그중 일부는 선택 사항이 될
것이다. 검색에는 질의에서 반환된 것과 같은 콘텐츠의
목록화를 관리하고 페이지네이션 등을 처리하기 위한
하위 API도 포함된다. 한 가지 특별한 질의 형식은 모든
것을 반환할 수 있음에 유의한다. 결과는 요청자의
권한 부여 대상이 될 수 있다.
추가 논의: 다른 TDD에 대한 페더레이션 질의,
공간 및 네트워크 제한 질의, 링크
디렉터리는 클라이언트별 질의를 기반으로 TD를 효율적으로 제공하기 위해 검색 API를 구현하는 것이 권장된다 RECOMMENDED.
이 섹션은 비규범이다.
JSONPath 검색 API 지원은 선택 사항이다. 구현된 경우, JSONPath API는query가 JSONPath 표현식인
/search/jsonpath?query={query} 엔드포인트에서
HTTP GET 요청을 사용하여 TD를 검색할 수 있게
해야 한다. 요청은 검색 매개변수로 유효한 JSONPath
[JSONPATH]를
포함해야 한다. 성공 응답은 200 (OK) 상태를 가져야 하며,
Content-Type 헤더에 application/json을 포함하고,
본문에 완전한 TD 집합 또는 TD 조각 집합을 포함해야
한다. JSONPath를 사용한 구문 검색은
7.3.2.4 API 명세(사물
모델)의 searchJSONPath 액션으로 지정된다.
이 섹션은 비규범이다.
XPath 검색 API 지원은 선택 사항이다. 구현된 경우, XPath 질의 API는query가 XPath 표현식인
/search/xpath?query={query} 엔드포인트에서
HTTP GET 요청을 사용하여 TD를 검색할 수 있게
해야 한다. 요청은 검색 매개변수로 유효한 XPath 3.1
[xpath-31]을
포함해야 한다. 성공 응답은 200 (OK) 상태를 가져야 하며,
Content-Type 헤더에 application/json을 포함하고,
본문에 JSON 직렬화된 질의 응답을 포함해야 한다. 응답을
위한 데이터 스키마는 질의와 XPath 명세에 의해 암묵적으로
정의된다. XPath를 사용한 구문 검색은
7.3.2.4 API 명세(사물
모델)의 searchXPath 액션으로 지정된다.
query가 SPARQL 표현식인
/search/sparql?query={query} 엔드포인트에서
HTTP GET 요청을 사용한 질의를 수락해야
MUST 한다.
/search/sparql 엔드포인트에서 HTTP
POST 메서드를 사용한 SPARQL 검색 지원은
OPTIONAL이다.
SELECT 또는 ASK 질의를 포함한
성공 요청은 200 (OK) 상태 응답을 반환하고 기본적으로
Content-Type 헤더에 application/json을
포함해야 MUST 한다.
CONSTRUCT 및 DESCRIBE 질의를 포함한
성공 요청은 200 (OK) 상태 응답을 반환하고 기본적으로
Content-Type 헤더에 application/ld+json을
포함해야 MUST 한다.
SELECT, ASK,
CONSTRUCT 또는 DESCRIBE가 아닌
모든 질의를 포함한 요청은 400 (Bad Request) 응답을
반환해야 MUST 한다. SPARQL을 사용한 의미 검색은
7.3.2.4 API 명세(사물
모델)의 searchSPARQL 액션으로 지정된다.
WoT 사물 설명
디렉터리는 자신의 SPARQL 질의 API에서 페더레이션을
구현할 수 MAY 있다. 구현된 경우,
SPARQL API는 SPARQL 1.1 Federated Query 표준
[sparql11-overview]을
구현해야 MUST 한다.
사물 설명 디렉터리의 API 템플릿은 여기에서 사물 모델로 제공된다. 사물 모델은 (명시된 경우를 제외하고) 규범적이지만, 사물 설명 디렉터리를 구현하거나 상호작용하기 위한 유일한 참조로 간주되어서는 안 된다. 또한 7.3.2 디렉터리 서비스 API에 제시된 명세도 참조하라.
이 사물 모델에 제공된 searchJSONPath 및
searchXPath 어포던스는 규범적이지 않으며
정보 제공용으로만 제공된다.
HTTP 응답의 본문이 비어 있어야 하는 경우에도
ExpectedResponse 클래스의 인스턴스(즉, form의
response 키에 해당하는 JSON 객체)에 대해
WoT TD 1.1 명세 [wot-thing-description11]가
contentType을 요구한다는 점에 유의한다.
이 경우 아래 TM에서 생성된 TD가 유효하도록
application/x-empty를 사용할 수 있다.
{
"@context": [
"https://www.w3.org/2022/wot/td/v1.1",
"https://www.w3.org/2022/wot/discovery"
],
"@type": [
"tm:ThingModel",
"ThingDirectory"
],
"title": "Thing Description Directory (TDD) Thing Model",
"version": {
"model": "1.0.0"
},
"base": "{{DIRECTORY_BASE_URL}}",
"tm:optional": [
"/actions/createThing",
"/actions/createAnonymousThing",
"/actions/retrieveThing",
"/actions/updateThing",
"/actions/partiallyUpdateThing",
"/actions/deleteThing",
"/actions/searchJSONPath",
"/actions/searchXPath",
"/actions/searchSPARQL",
"/events/thingCreated",
"/events/thingUpdated",
"/events/thingDeleted"
],
"properties": {
"things": {
"description": "Retrieve all Thing Descriptions",
"uriVariables": {
"offset": {
"title": "Number of TDs to skip before the page",
"type": "number",
"default": 0
},
"limit": {
"title": "Number of TDs in a page",
"type": "number"
},
"format": {
"title": "Payload format",
"type": "string",
"enum": [
"array",
"collection"
],
"default": "array"
}
},
"forms": [
{
"href": "/things{?offset,limit,format}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"htv:statusCodeValue": 200,
"contentType": "application/ld+json",
"htv:headers": [
{
"htv:fieldName": "Link"
}
]
},
"additionalResponses": [
{
"description": "Invalid query arguments",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
}
},
"actions": {
"createThing": {
"description": "Create a Thing Description",
"uriVariables": {
"id": {
"@type": "ThingID",
"title": "Thing Description ID",
"type": "string",
"format": "iri-reference"
}
},
"input": {
"description": "The schema is implied by the content type",
"type": "object"
},
"forms": [
{
"href": "/things/{id}",
"htv:methodName": "PUT",
"contentType": "application/td+json",
"response": {
"description": "Success response",
"htv:statusCodeValue": 201
},
"additionalResponses": [
{
"description": "Invalid serialization or TD",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
},
"createAnonymousThing": {
"description": "Create an anonymous Thing Description",
"input": {
"description": "The schema is implied by the content type",
"type": "object"
},
"forms": [
{
"href": "/things",
"htv:methodName": "POST",
"contentType": "application/td+json",
"response": {
"description": "Success response including the system-generated URI",
"htv:headers": [
{
"description": "System-generated URI",
"htv:fieldName": "Location"
}
],
"htv:statusCodeValue": 201
},
"additionalResponses": [
{
"description": "Invalid serialization or TD",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
},
"retrieveThing": {
"description": "Retrieve a Thing Description",
"uriVariables": {
"id": {
"@type": "ThingID",
"title": "Thing Description ID",
"type": "string",
"format": "iri-reference"
}
},
"output": {
"description": "The schema is implied by the content type",
"type": "object"
},
"safe": true,
"idempotent": true,
"forms": [
{
"href": "/things/{id}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"htv:statusCodeValue": 200,
"contentType": "application/td+json"
},
"additionalResponses": [
{
"description": "TD with the given id not found",
"contentType": "application/problem+json",
"htv:statusCodeValue": 404
}
]
}
]
},
"updateThing": {
"description": "Update a Thing Description",
"uriVariables": {
"id": {
"@type": "ThingID",
"title": "Thing Description ID",
"type": "string",
"format": "iri-reference"
}
},
"input": {
"description": "The schema is implied by the content type",
"type": "object"
},
"forms": [
{
"href": "/things/{id}",
"htv:methodName": "PUT",
"contentType": "application/td+json",
"response": {
"description": "Success response",
"htv:statusCodeValue": 204
},
"additionalResponses": [
{
"description": "Invalid serialization or TD",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
},
"partiallyUpdateThing": {
"description": "Partially update a Thing Description",
"uriVariables": {
"id": {
"@type": "ThingID",
"title": "Thing Description ID",
"type": "string",
"format": "iri-reference"
}
},
"input": {
"description": "The schema is implied by the content type",
"type": "object"
},
"forms": [
{
"href": "/things/{id}",
"htv:methodName": "PATCH",
"contentType": "application/merge-patch+json",
"response": {
"description": "Success response",
"htv:statusCodeValue": 204
},
"additionalResponses": [
{
"description": "Invalid serialization or TD",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
},
{
"description": "TD with the given id not found",
"contentType": "application/problem+json",
"htv:statusCodeValue": 404
}
]
}
]
},
"deleteThing": {
"description": "Delete a Thing Description",
"uriVariables": {
"id": {
"@type": "ThingID",
"title": "Thing Description ID",
"type": "string",
"format": "iri-reference"
}
},
"forms": [
{
"href": "/things/{id}",
"htv:methodName": "DELETE",
"response": {
"description": "Success response",
"htv:statusCodeValue": 204
},
"additionalResponses": [
{
"description": "TD with the given id not found",
"contentType": "application/problem+json",
"htv:statusCodeValue": 404
}
]
}
]
},
"searchJSONPath": {
"description": "JSONPath syntactic search. This affordance is not normative and is provided for information only.",
"uriVariables": {
"query": {
"title": "A valid JSONPath expression",
"type": "string"
}
},
"output": {
"description": "The schema depends on the given query",
"type": "object"
},
"safe": true,
"idempotent": true,
"forms": [
{
"href": "/search/jsonpath?query={query}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"contentType": "application/json",
"htv:statusCodeValue": 200
},
"additionalResponses": [
{
"description": "JSONPath expression not provided or contains syntax errors",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
},
"searchXPath": {
"description": "XPath syntactic search. This affordance is not normative and is provided for information only.",
"uriVariables": {
"query": {
"title": "A valid XPath expression",
"type": "string"
}
},
"output": {
"description": "The schema depends on the given query",
"type": "object"
},
"safe": true,
"idempotent": true,
"forms": [
{
"href": "/search/xpath?query={query}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"contentType": "application/json",
"htv:statusCodeValue": 200
},
"additionalResponses": [
{
"description": "XPath expression not provided or contains syntax errors",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
},
"searchSPARQL": {
"description": "SPARQL semantic search",
"uriVariables": {
"query": {
"title": "A valid SPARQL 1.1. query",
"type": "string"
}
},
"output": {
"description": "The schema depends on the given query",
"type": "object"
},
"safe": true,
"idempotent": true,
"forms": [
{
"href": "/search/sparql?query={query}",
"htv:methodName": "GET",
"response": {
"description": "Success response",
"contentType": "application/json",
"htv:statusCodeValue": 200
},
"additionalResponses": [
{
"description": "SPARQL query not provided or contains syntax errors",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
},
{
"href": "/search/sparql",
"htv:methodName": "POST",
"response": {
"description": "Success response",
"contentType": "application/json",
"htv:statusCodeValue": 200
},
"additionalResponses": [
{
"description": "SPARQL query not provided or contains syntax errors",
"contentType": "application/problem+json",
"htv:statusCodeValue": 400
}
]
}
]
}
},
"events": {
"thingCreated": {
"description": "Registration of Thing Descriptions inside the directory",
"uriVariables": {
"diff": {
"description": "Receive the full created TD as event data",
"type": "boolean"
}
},
"data": {
"title": "Partial/Full TD",
"type": "object"
},
"forms": [
{
"op": "subscribeevent",
"href": "/events/thing_created{?diff}",
"subprotocol": "sse",
"htv:headers": [
{
"description": "ID of the last event for reconnection",
"htv:fieldName": "Last-Event-ID"
}
],
"response": {
"contentType": "text/event-stream"
}
}
]
},
"thingUpdated": {
"description": "Updates to Thing Descriptions within the directory",
"uriVariables": {
"diff": {
"description": "Include TD changes inside event data",
"type": "boolean"
}
},
"data": {
"title": "Partial TD",
"type": "object",
"contentMediaType": "application/merge-patch+json"
},
"forms": [
{
"op": "subscribeevent",
"href": "/events/thing_updated{?diff}",
"subprotocol": "sse",
"htv:headers": [
{
"description": "ID of the last event for reconnection",
"htv:fieldName": "Last-Event-ID"
}
],
"response": {
"contentType": "text/event-stream"
}
}
]
},
"thingDeleted": {
"description": "Deletion of Thing Descriptions from the directory",
"data": {
"title": "Partial TD",
"type": "object"
},
"forms": [
{
"op": "subscribeevent",
"href": "/events/thing_deleted",
"subprotocol": "sse",
"htv:headers": [
{
"description": "ID of the last event for reconnection",
"htv:fieldName": "Last-Event-ID"
}
],
"response": {
"contentType": "text/event-stream"
}
}
]
}
}
}
보안은 모든 WoT 빌딩 블록과 WoT 구현에서 고려해야 하는 교차 영역 문제이다. 이 장은 구체적인 WoT 디스커버리 구현의 보안을 보존하는 데 도움이 되는 몇 가지 일반적인 문제와 지침을 요약한다. 보안 및 개인정보 보호 문제 모두에 대한 더 상세하고 완전한 분석은 WoT 보안 및 개인정보 보호 지침 명세 [WOT-SECURITY]를 참조하라. WoT 사물과 WoT TDD도 웹 서비스이므로 웹 서비스의 모범 사례를 사용하여 구현해야 한다. 아래의 특정 보안 고려 사항에 더하여, OWASP Top 10 [OWASP-Top-10] 같은 지침에서 논의되는 보안 위험과 완화책을 평가하고, 해당되는 경우 이를 처리해야 한다.
디렉터리 서비스의 특정 기능, 특히 검색 질의는 실행하는 데 상당한 자원이 필요할 수 있으며, 이 사실은 WoT 사물 설명 디렉터리 서비스에 대한 서비스 거부(DoS) 공격을 시작하는 데 사용될 수 있다. 이러한 공격에서 WoT 디렉터리는 공격자의 요청으로 과부하되어 다른 요청을 처리할 수 없게 된다.
WoT 디스커버리 메커니즘의 요소를 사용하여 다른 대상을 향한 분산 서비스 거부(DDoS) 공격을 시작하는 것도 가능할 수 있다. 이러한 공격에서 WoT 디스커버리 서비스 자체가 대상은 아니다. 대신 WoT 디스커버리 서비스의 어떤 측면이 악용되어 실제 대상인 제3자를 과부하시키는 증폭된 네트워크 트래픽을 생성한다. 이러한 공격에는 두 가지 요구사항이 있다. 첫째, 트래픽을 제3자로 리디렉션할 수 있는 능력이고, 둘째, 공격자의 네트워크 트래픽을 증폭하는 데 악용될 수 있는 중개 서비스이다. 안전하지 않은 CoAP와 같은 일부 프로토콜에서는 헤더의 출처 정보를 수정함으로써 네트워크 트래픽의 리디렉션이 가능하다. 증폭은 세 가지 곱셈 요인, 즉 요청 대 응답 페이로드 크기의 비율, CoAP 같은 프로토콜에서의 "observe" 사용(하나의 요청에 대해 여러 결과를 줄 수 있음), 그리고 멀티캐스트 사용 (하나의 요청에 대해 여러 서버가 응답할 수 있음)을 이용하여 가능하다. 인증을 지원하지 않는 서비스는 이러한 간접 공격에 이상적인 중개자이다. 불행히도 WoT 디스커버리의 도입 메커니즘은 디스커버리를 시작하기 위한 개방형 접근 메커니즘을 제공하도록 의도되어 있으며, 이 목적에 악용될 수 있다.
LAN에서는 브라우저가 공개적으로 보이는 URL을 가리키는 인증서를 기대하기 때문에, 인증서와 브라우저가 HTTPS용 TLS를 제대로 설정하지 못할 수 있다. LAN 내부에서 HTTP를 사용하는 것은 일반적인 관행이지만, 자기 설명과 결합되면 WoT 사물이 사설 LAN에 접근할 수 있는 모든 사람에게 TD를 본질적으로 노출하게 된다는 뜻이다. HTTP 비밀번호 같은 보안 메커니즘을 사용하더라도 전송 보안 없이는 효과적이지 않다(트래픽 분석기로 쉽게 발견될 수 있기 때문이다).
LAN에서는 가능하다면 PSK(사전 공유 키)를 사용해야 하며 SHOULD, 이는 [RFC4279]의 암호군 중 하나를 의미한다. 이는 사물이 공통 보안 도메인에서 PSK를 할당받아야 함을 요구하며, 일반적으로 온보딩 프로세스를 따라 수행된다. 불행히도 구체적인 온보딩 프로세스는 현재 WoT 명세의 범위를 벗어난다.
대안은 로컬 네트워크 보안(즉, WEP)에 의존하는 것이다. 이는 보안 또는 개인정보 보호 관점에서 최선의 해결책은 아니지만 일부 맥락에서는 허용될 수 있다. 그러나 네트워크에 접근할 수 있는 모든 사용자가 자기 설명을 통해 모든 TD에 접근할 수 있다는 점에 유의한다. 사물을 전송 보안 및 인증과 권한 부여로 개별적으로 보호할 수 없다면, 별도의 네트워크, 즉 대체 SSID를 갖는 네트워크를 설정하고 IoT 장치에만 사용하는 것이 좋다 SHOULD. 분할된 네트워크를 사용하면 이 네트워크에 연결된 IoT 장치 집합에 접근해야 하는 사람에게 이 네트워크의 비밀번호를 배포해야 할 필요가 줄어든다.
또 다른 대안은 클라우드 기반 리버스 프록시 서비스를 사용하는 것이다. IoT 장치가 클라우드에 접근할 수 있다면, 프록시 서버는 공개 URL을 가질 수 있고 초기 연결은 HTTPS를 사용할 수 있으며, 이후 websocket을 통해 보안 터널을 열 수 있으므로 안전한 설정을 달성할 수 있다. 프록시는 다시 보안 엔드포인트를 노출할 수 있으며, 인증을 추가할 수도 있다. 이 접근법의 단점에는 외부 클라우드 서비스에 의존한다는 점과 외부 접근 지점을 노출해야 한다는 점 (그 자체가 보안 위험임)이 포함된다. 첫 번째 단점은 로컬 서버가 ISP를 통해 연결되어 있는 경우, 프록시 서비스를 로컬에 호스팅하고 예를 들어 동적 DNS를 사용하여 공개 URL을 노출함으로써 해결할 수 있다. 사물을 전송 보안 및 인증과 권한 부여로 개별적으로 보호할 수 없다면, 적절한 접근 제어를 제공할 수 있는 프록시를 통해 일반 접근이 가능하도록 만들 수 있다.
개인정보 보호는 모든 WoT 빌딩 블록과 WoT 구현에서 고려해야 하는 교차 영역 문제이다. 이 장은 구체적인 WoT 디스커버리 구현의 개인정보 보호를 보존하는 데 도움이 되는 몇 가지 일반적인 문제와 지침을 요약한다. 보안 및 개인정보 보호 문제 모두에 대한 더 상세하고 완전한 분석은 WoT 보안 및 개인정보 보호 지침 명세 [WOT-SECURITY]를 참조하라.
WoT 디스커버리 아키텍처는 2단계 접근 방식을 사용하고 메타데이터 공개 전에 권한 부여를 강제할 수 있도록 함으로써 기존 디스커버리 체계의 개인정보 보호에 대한 의존을 피하도록 설계되었다. 그러나 여러 개인정보 보호 위험은 여전히 존재한다. 아래에는 이러한 위험과 가능한 완화책이 나열되어 있다. 개인정보 보호에 대한 위험 수준은 특히 사용 사례와 사람과 관련된 정보가 그 사람의 개인정보 보호 의사와 일치하지 않는 방식으로 배포될 위험이 있는지에 달려 있다. 개인정보 보호를 위해 우리는 다음과 같은 넓은 사용 사례 시나리오 클래스를 구분한다:
실제로 이 모든 경우에는 개인정보 보호 위험이 있다. 공장 자동화의 경우에도 직원 성과에 대한 데이터가 수집되어 적절히 관리되어야 할 가능성이 있다.
다음에서는 "추적"을 자주 언급한다. 이 용어는 위치 추적과 행동 프로파일링을 포함한 여러 개인정보 보호 위험을 포괄한다. 일반적으로 GDPR [GDPR-Defs] 제4조에 주어진 "프로파일링"의 정의는 이 문서에서 사용되는 "추적"과 동등한 것으로 간주해야 한다.
이러한 정의와 범주를 수립했으므로, 이제 몇 가지 특정 개인정보 보호 위험과 잠재적 완화책을 논의한다.
디스커버리 서비스는 잠재적으로 사람의 동의 없이 그 사람의 대략적인 위치를 확인할 수 있게 할 수 있다. 이 위험은 피하거나 완화할 수 있는 몇 가지 특정 상황에서 발생한다. 이는 DHCP 및 DNS 같은 다른 네트워크 서비스가 야기하는 위험과도 유사하다.
이 위험이 발생하려면 먼저 필수 의료 장치나 차량처럼 사람의 위치와 신뢰성 있게 연결될 수 있는 IoT 장치가 있어야 한다. 이 위험은 기관 사용 사례가 아니라 개인 사용 사례에만 적용된다는 점에 유의한다. 둘째, 장치가 가장 가까운 디렉터리 서비스에 자동으로 등록하도록 구성되어 있어야 한다. 이 경우, 디렉터리 서비스의 네트워크 범위에서 장치의 위치를 추론할 수 있고, 장치의 위치에서 사람의 위치를 추론할 수 있다.
여기에는 몇 가지 변형이 있다:
위치 추적만이 유일한 프로파일링 위험은 아니다. 일반적으로 "프로파일링"에는 경제적 상태, 건강, 선호, 관심사, 신뢰성 및 행동을 포함하여 사람에 관한 정보를 평가하는 데 사용되는 모든 메커니즘이 포함된다. TD의 일부 메타데이터는 설명된 사물이 사람과 연결될 수 있는 경우 이러한 종류의 정보를 추론하는 데 사용될 수 있다. 아래 완화책 중 일부는 이 더 일반적인 프로파일링 정의에도 적용 가능하다.
이러한 위험 중 일부는 유사한 서비스와 공유된다. 예를 들어 DCHP는 로컬 네트워크에서 IP 주소 요청에 자동으로 응답하며, 장치는 일반적으로 이 과정의 일부로 식별자(MAC 주소)를 제공하고 DHCP 서버는 레지스트리를 유지한다. 이론적으로 카페의 DHCP 서버에 접근할 수 있는 사람은 이 정보를 사용하여 누군가의 휴대폰을 추적하고 그 위치를 추론할 수 있다.
디렉터리 서비스는 개인이 제공한 인증된 신원을 통해 그 개인을 식별하면서, 개인의 질의를 기록하고 추적할 수 있다. 그러면 개인과 연결된 질의 집합은 그 개인을 프로파일링하는 데 사용될 수 있으며, 특정 질의는 개인에 대한 개인정보를 드러낼 수도 있다.
공개 디렉터리에 접근할 때, 다른 공개 웹 서비스와 마찬가지로 사용자와 구현은 익명 신원 제공자를 사용해야 한다. 특히 OAuth2는 특정 개인을 식별하지 않고 다른 곳에서 증명된 접근 권한만 단언하는 토큰을 제공할 수 있다.
이 섹션은 비규범이다.
TD 객체는 크기에 제한이 없다. 개별적으로 또는 집합적으로 처리하고 전송하는 데 비용이 많이 들 수 있다. 단일 TD 또는 TD 목록은 자신의 TD를 컨슈머에게 제공하거나, 이를 디렉터리에 제출하거나, 다른 TD를 소비하는 제약된 장치에 너무 클 수 있다. 이러한 요구사항을 충족하기 위해 서버는 프로토콜별 메커니즘을 사용하여 페이로드의 점진적 전송을 지원해야 한다:
chunked
Transfer-Encoding [RFC7230]을
지원해야 한다.
대부분의 HTTP 서버와 클라이언트는 청크로 전송되는 데이터를 자동으로 처리한다. 메모리 제약이 있는 클라이언트는 전체 객체를 메모리에 로드하여 역직렬화하려고 하기보다, 수신한 데이터를 점진적으로 소비하는 것을 고려해야 한다.
IANA는 [RFC8615]에 정의된 잘 알려진 URI에 다음 값을 할당하도록 요청받을 것이다.
wotIANA는 [RFC6335]에 정의된 서비스 이름 및 전송 프로토콜 포트 번호 레지스트리에 다음 값을 할당하도록 요청받을 것이다.
wot_directory
하위 유형을 사용한다.IANA는 [RFC6690]에 정의된
Constrained Restful Environments(CoRE) 매개변수 레지스트리의
Resource Type(rt=) Link Target Attribute Values
하위 레지스트리에 다음 값을 할당하도록 요청받을 것이다.
| 값 | 설명 | 참조 |
|---|---|---|
wot.thing |
사물의 사물 설명 | 6.4 CoRE 링크 형식 및 CoRE 리소스 디렉터리 |
wot.directory |
사물 설명 디렉터리의 사물 설명 | 6.4 CoRE 링크 형식 및 CoRE 리소스 디렉터리 |
다음 값은 DID 문서에서 사용되는 서비스 유형에 할당될 것이다.
| 값 | 설명 | 참조 |
|---|---|---|
WotThing |
사물의 사물 설명 | 6.5 DID 문서 |
WotDirectory |
사물 설명 디렉터리의 사물 설명 | 6.5 DID 문서 |
{
"title": "WoT Discovery TD-extensions Schema - 21 May 2021",
"description": "JSON Schema for validating TD instances with WoT Discovery extensions",
"$schema ": "https://json-schema.org/draft/2019-09/schema#",
"type": "object",
"properties": {
"registration": {
"type": "object",
"properties": {
"created": {
"type": "string",
"format": "date-time"
},
"expires": {
"type": "string",
"format": "date-time"
},
"retrieved": {
"type": "string",
"format": "date-time"
},
"modified": {
"type": "string",
"format": "date-time"
},
"ttl": {
"type": "number"
}
}
}
}
}
wot 사용.DirectoryDescription 유형을 포함하여 디렉터리의
TD를 식별하는 TDD용 온톨로지와, 페더레이션을 지원하기 위해
원격 디렉터리를 참조하는 데 유용한 다른 TD에 대한 링크일
뿐인 TD를 식별하는 LinkDescription 유형 추가.
IoT의 기존 디스커버리 메커니즘에 대한 조사 작업을 해 준 Arne Broering, Soumya Kanti Datta, Christian Bonnet에게 특별한 감사를 전한다. 이 문서에 기여해 준 Philipp Blum, Victor Charpeney, Ben Francis, Christian Glomb, Daniel Peintner, Christine Perey, Jan Romann, Elodie Thieblin에게 특별한 감사를 전한다.
W3C 스태프, 특히 Kazuyuki Ashimura와 Dominique Hazael-Massieux, 그리고 이 문서의 개선으로 이어진 지원, 기술적 의견 및 제안을 제공한 W3C 웹 사물 관심 그룹(WoT IG) 및 워킹 그룹(WoT WG)의 모든 활동적인 참여자에게 깊이 감사한다.
Referenced in:
Referenced in:
Referenced in:
Referenced in: