ASP.NET Web API 2.1의 BSON 지원
이 항목에서는 Web API 컨트롤러(서버 쪽) 및 .NET 클라이언트 앱에서 BSON을 사용하는 방법을 보여 줍니다. Web API 2.1은 BSON에 대한 지원을 도입합니다.
BSON이란?
BSON 은 이진 serialization 형식입니다. "BSON"은 "Binary JSON"을 의미하지만 BSON과 JSON은 매우 다르게 직렬화됩니다. 개체는 JSON과 유사한 이름-값 쌍으로 표현되기 때문에 BSON은 "JSON과 유사"입니다. JSON과 달리 숫자 데이터 형식은 문자열이 아닌 바이트로 저장됩니다.
BSON은 가볍고, 스캔하기 쉽고, 인코딩/디코딩이 빨라지도록 설계되었습니다.
- BSON의 크기는 JSON과 비슷합니다. 데이터에 따라, BSON 페이로드는 JSON 페이로드보다 작거나 클 수 있습니다. 이미지 파일과 같은 이진 데이터를 직렬화하는 경우 이진 데이터가 base64로 인코딩되지 않으므로 BSON은 JSON보다 작습니다.
- BSON 문서는 요소 앞에 길이 필드가 있으므로 쉽게 검색할 수 있으므로 파서는 요소를 디코딩하지 않고 건너뛸 수 있습니다.
- 숫자 데이터 형식은 문자열이 아닌 숫자로 저장되므로 인코딩 및 디코딩이 효율적입니다.
.NET 클라이언트 앱과 같은 네이티브 클라이언트는 JSON 또는 XML과 같은 텍스트 기반 형식 대신 BSON을 사용하면 이점을 얻을 수 있습니다. 브라우저 클라이언트의 경우 JavaScript가 JSON 페이로드를 직접 변환할 수 있으므로 JSON을 고수할 수 있습니다.
다행히 Web API는 콘텐츠 협상을 사용하므로 API는 두 형식을 모두 지원하고 클라이언트가 선택할 수 있도록 할 수 있습니다.
서버에서 BSON 사용
Web API 구성에서 BsonMediaTypeFormatter 를 포맷터 컬렉션에 추가합니다.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Formatters.Add(new BsonMediaTypeFormatter());
// Other Web API configuration not shown...
}
}
이제 클라이언트가 "application/bson"을 요청하는 경우 Web API는 BSON 포맷터를 사용합니다.
BSON을 다른 미디어 형식과 연결하려면 SupportedMediaTypes 컬렉션에 추가합니다. 다음 코드는 지원되는 미디어 형식에 "application/vnd.contoso"를 추가합니다.
var bson = new BsonMediaTypeFormatter();
bson.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.contoso"));
config.Formatters.Add(bson);
예제 HTTP 세션
이 예제에서는 다음 모델 클래스와 간단한 Web API 컨트롤러를 사용합니다.
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public decimal Price { get; set; }
public DateTime PublicationDate { get; set; }
}
public class BooksController : ApiController
{
public IHttpActionResult GetBook(int id)
{
var book = new Book()
{
Id = id,
Author = "Charles Dickens",
Title = "Great Expectations",
Price = 9.95M,
PublicationDate = new DateTime(2014, 1, 20)
};
return Ok(book);
}
}
클라이언트는 다음 HTTP 요청을 보낼 수 있습니다.
GET http://localhost:15192/api/books/1 HTTP/1.1
User-Agent: Fiddler
Host: localhost:15192
Accept: application/bson
응답은 다음과 같습니다.
HTTP/1.1 200 OK
Content-Type: application/bson; charset=utf-8
Date: Fri, 17 Jan 2014 01:05:40 GMT
Content-Length: 111
.....Id......Title.....Great Expectations..Author.....Charles Dickens..Price..........PublicationDate.........
여기서는 이진 데이터를 "." 문자로 대체했습니다. Fiddler의 다음 스크린샷은 원시 16진수 값을 보여줍니다.
HttpClient에서 BSON 사용
.NET 클라이언트 앱은 HttpClient와 함께 BSON 포맷터를 사용할 수 있습니다. HttpClient에 대한 자세한 내용은 .NET 클라이언트에서 Web API 호출을 참조하세요.
다음 코드는 BSON을 수락하는 GET 요청을 보낸 다음 응답에서 BSON 페이로드를 역직렬화합니다.
static async Task RunAsync()
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost");
// Set the Accept header for BSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));
// Send GET request.
result = await client.GetAsync("api/books/1");
result.EnsureSuccessStatusCode();
// Use BSON formatter to deserialize the result.
MediaTypeFormatter[] formatters = new MediaTypeFormatter[] {
new BsonMediaTypeFormatter()
};
var book = await result.Content.ReadAsAsync<Book>(formatters);
}
}
서버에서 BSON을 요청하려면 Accept 헤더를 "application/bson"으로 설정합니다.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/bson"));
응답 본문을 역직렬화하려면 BsonMediaTypeFormatter를 사용합니다. 이 포맷터는 기본 포맷터 컬렉션에 없으므로 응답 본문을 읽을 때 지정해야 합니다.
MediaTypeFormatter[] formatters = new MediaTypeFormatter[] {
new BsonMediaTypeFormatter()
};
var book = await result.Content.ReadAsAsync<Book>(formatters);
다음 예제에서는 BSON이 포함된 POST 요청을 보내는 방법을 보여 줍니다.
static async Task RunAsync()
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:15192");
// Set the Accept header for BSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/bson"));
var book = new Book()
{
Author = "Jane Austen",
Title = "Emma",
Price = 9.95M,
PublicationDate = new DateTime(1815, 1, 1)
};
// POST using the BSON formatter.
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/books", book, bsonFormatter);
result.EnsureSuccessStatusCode();
}
}
이 코드의 대부분은 이전 예제와 동일합니다. 그러나 PostAsync 메서드에서 BsonMediaTypeFormatter 를 포맷터로 지정합니다.
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var result = await client.PostAsync("api/books", book, bsonFormatter);
Top-Level 기본 형식 직렬화
모든 BSON 문서는 키/값 쌍의 목록입니다. BSON 사양은 정수 또는 문자열과 같은 단일 원시 값을 직렬화하기 위한 구문을 정의하지 않습니다.
이 제한을 해결하기 위해 BsonMediaTypeFormatter 는 기본 형식을 특수한 사례로 처리합니다. 직렬화하기 전에 값을 "Value" 키가 있는 키/값 쌍으로 변환합니다. 예를 들어 API 컨트롤러가 정수()를 반환한다고 가정합니다.
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return Ok(42);
}
}
직렬화하기 전에 BSON 포맷터는 이를 다음 키/값 쌍으로 변환합니다.
{ "Value": 42 }
역직렬화하면 포맷터가 데이터를 원래 값으로 다시 변환합니다. 그러나 웹 API가 원시 값을 반환하는 경우 다른 BSON 파서를 사용하는 클라이언트는 이 사례를 처리해야 합니다. 일반적으로 원시 값이 아닌 구조화된 데이터를 반환하는 것이 좋습니다.