컴퓨팅에서 오픈 데이터 프로토콜(Open Data Protocol, OData)은 표준적인 방식으로 쿼리 가능하고 상호 운용 가능한 웹 서비스 API를 생성하고 소비할 수 있게 하는 공개 프로토콜이다. 마이크로소프트는 2007년에 OData를 시작했다. 버전 1.0, 2.0, 3.0은 마이크로소프트 오픈 스펙 약속 하에 릴리스되었다. 버전 4.0은 OASIS에서 표준화되었으며, 2014년 3월에 출시되었다. 2015년 4월 OASIS는 OData v4와 OData JSON Format v4를 ISO/IEC JTC 1에 국제 표준으로 승인해달라고 제출했다. 2016년 12월, ISO/IEC는 OData 4.0 Core를 ISO/IEC 20802-1:2016으로, OData JSON Format을 ISO/IEC 20802-2:2016으로 출판했다.
이 프로토콜은 HTTP 기반의 웹 API 생성 및 소비를 가능하게 하며, 웹 클라이언트가 URL을 사용하여 식별되고 데이터 모델에서 정의된 리소스를 간단한 HTTP 메시지를 사용하여 게시하고 편집할 수 있게 한다. OData는 JDBC 및 ODBC와 유사한 점을 공유하며, ODBC와 마찬가지로 OData는 관계형 데이터베이스에만 국한되지 않는다.
마이크로소프트의 초기 개발 이후, OData는 OASIS OData 기술 위원회(TC)의 표준화된 프로토콜이 되었다.
"OASIS OData TC는 기업, 클라우드, 모바일 기기에서 재사용을 위해 서로 다른 애플리케이션 및 여러 이해관계자 간에 데이터를 쿼리하고 공유하는 것을 단순화하기 위해 노력한다. REST 기반 프로토콜인 OData는 HTTP, AtomPub, JSON을 기반으로 구축되었으며 URI를 사용하여 데이터 피드 리소스에 접근한다. 이 프로토콜은 관계형 데이터베이스, 파일 시스템, 콘텐츠 관리 시스템, 전통적인 웹 사이트를 포함한(이에 국한되지 않음) 다양한 소스에서 정보에 접근할 수 있게 한다. OData는 데이터 사일로를 허물고 데이터의 공유 가치를 높이는 방법을 제공하며, 데이터 소비자가 데이터 생산자와 현재 가능한 것보다 훨씬 강력한 방식으로 상호 운용할 수 있는 생태계를 조성하여 더 많은 애플리케이션이 더 넓은 범위의 데이터를 이해할 수 있도록 한다. 이 생태계에 참여하는 모든 데이터 생산자와 소비자는 그 전체 가치를 증가시킨다."
TC 참가자로는 CA 테크놀로지스, 시트릭스 시스템즈, IBM, 마이크로소프트, 프로그레스 소프트웨어, 레드햇, SAP SE 및 SDL이 있다.
OData는 웹 API 생성 및 소비를 위한 프로토콜이다. 따라서 OData는 URI를 사용하여 데이터 피드 리소스에 접근하는 HTTP, AtomPub 및 JSON을 기반으로 한다.
OData는 URI를 사용하여 리소스를 식별한다. 서비스 루트가 http://host/service/로 약칭되는 모든 OData 서비스에 대해 다음의 고정 리소스를 찾을 수 있다.
서비스 문서는 검색할 수 있는 엔티티 집합, 함수 및 싱글턴을 나열한다. 클라이언트는 서비스 문서를 사용하여 하이퍼미디어 기반 방식으로 모델을 탐색할 수 있다.
서비스 문서는 http://host/service/에서 이용할 수 있다.
메타데이터 문서는 OData 서비스가 이해하는 형식, 집합, 함수 및 작업을 설명한다. 클라이언트는 메타데이터 문서를 사용하여 서비스의 엔티티를 쿼리하고 상호 작용하는 방법을 이해할 수 있다.
메타데이터 문서는 http://host/service/$metadata에서 이용할 수 있다.
동적 리소스의 URI는 서비스 문서 및 메타데이터 문서의 하이퍼미디어 정보로부터 계산될 수 있다.
OData는 HTTP 동사를 사용하여 리소스에 대한 작업을 나타낸다.
OData 엔드포인트에 요청된 URL에는 쿼리 옵션이 포함될 수 있다. OData 프로토콜은 엔드포인트가 수락해야 하는 다양한 '시스템 쿼리 옵션'을 지정하며, 이는 데이터를 필터링, 정렬, 매핑 또는 페이지 매김하는 데 사용할 수 있다.
쿼리 옵션은 ? 문자 뒤에 URL에 추가할 수 있으며 & 문자로 구분된다. 각 옵션은 $ 부호가 접두사로 붙은 이름과 그 값으로 구성되며 = 부호로 구분된다. 예를 들어 OData/Products?$top=2&$orderby=Name과 같다. 데이터를 필터링할 때 사용할 수 있도록 여러 논리 연산자와 함수가 정의되어 있다. 예를 들어 OData/Products?$filter=Price lt 10.00 and startswith(Name,'M')은 가격이 10보다 작고 이름이 'M'으로 시작하는 제품을 요청한다.
OData는 데이터 및 데이터 모델을 표현하기 위해 다양한 형식을 사용한다. OData 프로토콜 버전 4.0에서는 JSON 형식이 데이터 표현의 표준이며, Atom 형식은 여전히 위원회 사양 단계에 있다. 데이터 모델을 표현하기 위해서는 OData 서비스가 노출하는 엔티티 데이터 모델의 XML 표현을 정의하는 CSDL(Common Schema Definition Language)이 사용된다.
제품 컬렉션:
{
"@odata.context": "http://services.odata.org/V4/OData/OData.svc/$metadata#Products",
"value": [
{
"ID": 0,
"Name": "Meat",
"Description": "Red Meat",
"ReleaseDate": "1992-01-01T00:00:00Z",
"DiscontinuedDate": null,
"Rating": 14,
"Price": 2.5
},
{
"ID": 1,
"Name": "Milk",
"Description": "Low fat milk",
"ReleaseDate": "1995-10-01T00:00:00Z",
"DiscontinuedDate": null,
"Rating": 3,
"Price": 3.5
},
...
]
}
제품 컬렉션:
<feed xml:base="http://services.odata.org/V4/OData/OData.svc/" m:context="http://services.odata.org/V4/OData/OData.svc/$metadata#Products" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://docs.oasis-open.org/odata/ns/data" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
<id>http://services.odata.org/v4/odata/odata.svc/Products</id>
<title type="text">Products</title>
<updated>2015-05-19T03:38:50Z</updated>
<link rel="self" title="Products" href="Products"/>
<entry>
<id>http://services.odata.org/V4/OData/OData.svc/Products(0)</id>
<category term="#ODataDemo.Product" scheme="http://docs.oasis-open.org/odata/ns/scheme"/>
<link rel="edit" title="Product" href="Products(0)"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/Categories" type="application/xml" title="Categories" href="Products(0)/Categories/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/Categories" type="application/atom+xml;type=feed" title="Categories" href="Products(0)/Categories"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/Supplier" type="application/xml" title="Supplier" href="Products(0)/Supplier/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(0)/Supplier"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/ProductDetail" type="application/xml" title="ProductDetail" href="Products(0)/ProductDetail/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/ProductDetail" type="application/atom+xml;type=entry" title="ProductDetail" href="Products(0)/ProductDetail"/>
<title/>
<updated>2015-05-19T03:38:50Z</updated>
<author>
<name/>
</author>
<content type="application/xml">
<m:properties>
<d:ID m:type="Int32">0</d:ID>
<d:Name>Bread</d:Name>
<d:Description>Whole grain bread</d:Description>
<d:ReleaseDate m:type="DateTimeOffset">1992-01-01T00:00:00Z</d:ReleaseDate>
<d:DiscontinuedDate m:null="true"/>
<d:Rating m:type="Int16">4</d:Rating>
<d:Price m:type="Double">2.5</d:Price>
</m:properties>
</entry>
<entry>
<id>http://services.odata.org/V4/OData/OData.svc/Products(1)</id>
<category term="#ODataDemo.Product" scheme="http://docs.oasis-open.org/odata/ns/scheme"/>
<link rel="edit" title="Product" href="Products(1)"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/Categories" type="application/xml" title="Categories" href="Products(1)/Categories/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/Categories" type="application/atom+xml;type=feed" title="Categories" href="Products(1)/Categories"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/Supplier" type="application/xml" title="Supplier" href="Products(1)/Supplier/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/Supplier" type="application/atom+xml;type=entry" title="Supplier" href="Products(1)/Supplier"/>
<link rel="http://docs.oasis-open.org/odata/ns/relatedlinks/ProductDetail" type="application/xml" title="ProductDetail" href="Products(1)/ProductDetail/$ref"/>
<link rel="http://docs.oasis-open.org/odata/ns/related/ProductDetail" type="application/atom+xml;type=entry" title="ProductDetail" href="Products(1)/ProductDetail"/>
<title/>
<updated>2015-05-19T03:38:50Z</updated>
<author>
<name/>
</author>
<content type="application/xml">
<m:properties>
<d:ID m:type="Int32">1</d:ID>
<d:Name>Milk</d:Name>
<d:Description>Low fat milk</d:Description>
<d:ReleaseDate m:type="DateTimeOffset">1995-10-01T00:00:00Z</d:ReleaseDate>
<d:DiscontinuedDate m:null="true"/>
<d:Rating m:type="Int16">3</d:Rating>
<d:Price m:type="Double">3.5</d:Price>
</m:properties>
</entry>
...
</feed>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="ODataDemo" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<EntityType Name="Product">
<Key>
<PropertyRef Name="ID"/>
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false"/>
<Property Name="Name" Type="Edm.String"/>
<Property Name="Description" Type="Edm.String"/>
<Property Name="ReleaseDate" Type="Edm.DateTimeOffset" Nullable="false"/>
<Property Name="DiscontinuedDate" Type="Edm.DateTimeOffset"/>
<Property Name="Rating" Type="Edm.Int16" Nullable="false"/>
<Property Name="Price" Type="Edm.Double" Nullable="false"/>
</EntityType>
<ComplexType Name="Address">
<Property Name="Street" Type="Edm.String"/>
<Property Name="City" Type="Edm.String"/>
<Property Name="State" Type="Edm.String"/>
<Property Name="ZipCode" Type="Edm.String"/>
<Property Name="Country" Type="Edm.String"/>
</ComplexType>
<EntityContainer Name="DemoService">
<EntitySet Name="Products" EntityType="ODataDemo.Product"></EntitySet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
응용 프로그램에는 다음이 포함된다.