자체-호스트(Self-Host) Web API (C#)

등록일시: 2013-10-09 15:59,  수정일시: 2013-12-16 13:28
조회수: 8,094
이 문서는 ASP.NET Web API 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.

반드시 IIS에서만 ASP.NET Web API를 사용할 수 있는 것은 아니며, 필요하다면 직접 작성한 호스트 프로세스에서 Web API를 자체 호스트 할 수도 있습니다.

본 자습서에서는 콘솔 응용 프로그램 상에서 Web API를 자체 호스트하는 방법을 살펴봅니다.

콘솔 응용 프로그램 프로젝트 생성하기

먼저, Visual Studio를 시작하고 시작 (Start) 페이지에서 새 프로젝트 (New Project) 링크를 클릭합니다. 또는, 파일 (File) 메뉴에서 새 프로젝트 (New Project)를 선택해도 됩니다.

템플릿 (Templates) 패인에서 설치됨 (Installed) 노드 하위의 템플릿 (Templates) 노드를 선택하고, 그 하위의 Visual C# 노드를 확장합니다. 그리고, Visual C# 노드 하위의 Windows 노드를 선택한 다음, 프로젝트 템플릿 목록에서 콘솔 응용 프로그램 (Console Application)을 선택하고, 프로젝트 이름을 "SelfHost"로 지정한 다음, 확인 (OK) 버튼을 클릭합니다.

타겟 프레임워크 설정 (Visual Studio 2010)

만약, Visual Studio 2010을 사용중이라면 대상 프레임워크를 .NET 프레임워크 4.0으로 변경해야 합니다. (프로젝트 템플릿의 기본 대상은 .Net Framework Client Profile 입니다.)

대상 프레임워크를 변경하려면 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 버튼으로 클릭한 다음, 속성 (Properties)을 선택합니다. 그리고, 대상 프레임워크 (Target framework) 드롭다운 목록에서 대상 프레임워크를 .NET Framework 4.0으로 변경합니다. 변경 적용 여부를 묻는 프롬프트가 나타나면 예 (Yes)를 클릭합니다.

NuGet 패키지 관리자 설치하기

비-ASP.NET 프로젝트에 Web API 어셈블리들을 추가하는 가장 손쉬운 방법은 NuGet 패키지 관리자를 사용하는 것입니다.

NuGet 패키지 관리자가 설치되어 있는지 확인하려면, 먼저 Visual Studio의 도구 (Tools) 메뉴를 클릭합니다. 만약, 그 하위에 라이브러리 패키지 관리자 (Library Package Manager) 항목이 존재하면 NuGet 패키지 관리자가 설치되어 있는 것입니다.

새로 NuGet 패키지 관리자를 설치하려면:

  1. Visual Studio를 시작합니다.
  2. 도구 (Tools) 메뉴에서 확장 및 업데이트 (Extensions and Updates)를 선택합니다.
  3. 확장 및 업데이트 (Extensions and Updates) 대화 상자에서 온라인 (Online)을 선택합니다.
  4. 만약, "NuGet Package Manager"를 찾을 수 없다면 검색 상자에 "nuget package manager"를 입력합니다.
  5. 목록에서 NuGet Package Manager를 선택한 다음, 다운로드 (Download) 버튼을 클릭합니다.
  6. 다운로드가 완료되면 설치를 위한 프롬프트가 나타날 것입니다.
  7. 설치가 완료되고 나면 Visual Studio를 재시작한다는 프롬프트가 나타납니다.

Web API NuGet 패키지 설치하기

프로젝트에 NuGet 패키지 관리자를 설치한 다음에는 Web API 자체-호스트 패키지를 설치해야 합니다.

  1. 도구 (Tools) 메뉴에서 라이브러리 패키지 관리자를 선택합니다.
    노트: 이 메뉴 항목이 나타나지 않는다면 NuGet 패키지 관리자가 정상적으로 설치되었는지 먼저 확인하시기 바랍니다.
  2. 솔루션용 NuGet 패키지 관리 (Manage NuGet Packages for Solution...)를 선택합니다.
  3. NugGet 패키지 관리 (Manage NugGet Packages) 대화 상자에서 온라인 (Online)을 선택합니다.
  4. 검색 상자에 "Microsoft.AspNet.WebApi.SelfHost"를 입력합니다.

    노트: 설치해야 할 패키지의 이름이 AspNetWebApi.SelfHost가 아닌 Microsoft.AspNet.WebApi.SelfHost라는 점에 주의하십시요.

  5. "ASP.NET Web API Self Host package"를 선택하고 설치 (Install) 버튼을 클릭합니다..
  6. 패키지 설치를 마쳤으면 대화 상자의 닫기 (Close) 버튼을 클릭합니다.

모델 및 컨트롤러 생성하기

본 자습서에서는 여러분의 첫 번째 ASP.NET Web API (C#) 자습서의 모델 및 컨트롤러 클래스들과 동일한 클래스들을 사용합니다.

먼저, Product라는 이름으로 public 클래스를 추가합니다.

namespace SelfHost
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

그리고, ProductsController라는 이름으로 public 클래스를 하나 더 추가합니다. 이 클래스는 System.Web.Http.ApiController 클래스를 상속받아야 합니다.

namespace SelfHost
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web.Http;
        
    public class ProductsController : ApiController
    {
        Product[] products = new Product[]
        {
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };
    
        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }
    
        public Product GetProductById(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return product;
        }
    
        public IEnumerable<Product> GetProductsByCategory(string category)
        {
            return products.Where(p => string.Equals(p.Category, category,
                    StringComparison.OrdinalIgnoreCase));
        }
    }
}

이 컨트롤러의 코드에 대한 보다 자세한 정보는 여러분의 첫 번째 ASP.NET Web API (C#) 자습서를 참고하시기 바랍니다. 이 컨트롤러에는 세 개의 GET 액션이 정의되어 있습니다:

URI 설명
/api/products 모든 제품들의 목록을 가져옵니다.
/api/products/id ID를 기준으로 제품을 가져옵니다.
/api/products/?category=category 카테고리를 기준으로 제품들의 목록을 가져옵니다.

Web API 호스트하기

Program.cs 파일을 열고 다음의 using 문들을 추가합니다:

using System.Web.Http;
using System.Web.Http.SelfHost;

그리고, 다음의 코드를 Program 클래스에 추가합니다.

var config = new HttpSelfHostConfiguration("http://localhost:8080");
    
config.Routes.MapHttpRoute("API Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
    
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
    server.OpenAsync().Wait();
    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
}

(선택사항) HTTP URL 네임스페이스 예약 추가하기

이 응용 프로그램은 http://localhost:8080/을 수신합니다. 그러나, 특정 HTTP 주소를 수신하려면 기본적으로관리자 권한이 필요합니다. 그렇기 때문에, 본 자습서의 응용 프로그램을 실행시켜보면 환경에 따라 "HTTP could not register URL http://+:8080/"라는 오류를 만날 수도 있습니다. 이 오류를 피할 수 있는 방법이 두 가지 있습니다:

  1. Visual Studio를 관리자 권한으로 상승하여 실행시키거나,
  2. Netsh.exe를 사용해서 여러분의 계정에 권한을 부여하여 해당 URL을 예약합니다.

Netsh.exe를 사용하려면 관리자 권한으로 명령 프롬프트를 연 다음, 다음의 명령을 입력합니다:

netsh http add urlacl url=http://+:8080/ user=machine\username

이 때, machine\username 자리에는 여러분의 계정을 입력합니다.

자체-호스팅을 마친 뒤에는 이 예약을 삭제해줍니다:

netsh http delete urlacl url=http://+:8080/

클라이언트 응용 프로그램(C#)에서 Web API 호출하기

Web API를 호출하는 간단한 콘솔 응용 프로그램을 작성해보겠습니다.

먼저, 솔루션에 새로운 콘솔 응용 프로그램 프로젝트를 추가합니다.:

  1. 솔루션 탐색기에서 솔루션을 마우스 오른쪽으로 클릭한 다음, 추가 (Add), 새 프로젝트 (New Project)를 선택합니다.
  2. "ClientApp"라는 이름으로 새로운 콘솔 응용 프로그램을 생성합니다.

NuGet 패키지 관리자를 사용해서 Web API 클라이언트 라이브러리 패키지를 설치합니다:

  1. 도구 (Tools) 메뉴에서 라이브러리 패키지 관리자를 선택합니다.
  2. 솔루션용 NuGet 패키지 관리 (Manage NuGet Packages for Solution...)를 선택합니다.
  3. NugGet 패키지 관리 (Manage NugGet Packages) 대화 상자에서 온라인 (Online)을 선택합니다.
  4. 검색 상자에 "Microsoft.AspNet.WebApi.Client"를 입력합니다.
  5. "Microsoft ASP.NET Web API Client Libraries" 패키지를 선택하고, 설치 (Install) 버튼을 클릭합니다.

ClientApp 프로젝트에 SelfHost 프로젝트에 대한 참조를 추가합니다:

  1. 솔루션 탐색기에서 ClientApp 프로젝트를 마우스 오른쪽 버튼으로 클릭합니다.
  2. 참조 추가 (Add Reference)를 선택합니다.
  3. 참조 관리자 (Reference Manager) 대화 상자에서, 솔루션 (Solution) 하위의 프로젝트 (Projects)를 선택합니다.
  4. SelfHost 프로젝트를 선택합니다.
  5. 확인 (OK) 버튼을 클릭합니다.

Client/Program.cs 파일을 열고, 다음의 using 문을 추가합니다:

using System.Net.Http;

그리고, 정적 HttpClient 인스턴스를 추가합니다:

namespace ClientApp
{
    class Program
    {
        static HttpClient client = new HttpClient();
    }
}

다음의 메서드들을 추가합니다. 이 메서드들은 각각 모든 제품들의 목록을 가져오거나, ID를 기준으로 제품을 조회하고, 카테고리를 기준으로 제품들의 목록을 조회하는 메서드입니다.

static void ListAllProducts()
{
    HttpResponseMessage resp = client.GetAsync("api/products").Result;
    resp.EnsureSuccessStatusCode();
    
    var products = resp.Content.ReadAsAsync<IEnumerable<SelfHost.Product>>().Result;
    foreach (var p in products)
    {
        Console.WriteLine("{0} {1} {2} ({3})", p.Id, p.Name, p.Price, p.Category);
    }
}
    
static void ListProduct(int id)
{
    var resp = client.GetAsync(string.Format("api/products/{0}", id)).Result;
    resp.EnsureSuccessStatusCode();
    
    var product = resp.Content.ReadAsAsync<SelfHost.Product>().Result;
    Console.WriteLine("ID {0}: {1}", id, product.Name);
}
    
static void ListProducts(string category)
{
    Console.WriteLine("Products in '{0}':", category);
    
    string query = string.Format("api/products?category={0}", category);
    
    var resp = client.GetAsync(query).Result;
    resp.EnsureSuccessStatusCode();
    
    var products = resp.Content.ReadAsAsync<IEnumerable<SelfHost.Product>>().Result;
    foreach (var product in products)
    {
        Console.WriteLine(product.Name);
    }
}

이 메서드들은 모두 다음과 같은 동일한 패턴을 따르고 있습니다:

  1. HttpClient.GetAsync 메서드를 호출하여 GET 요청을 적절한 URI에 전송합니다.
  2. 그런 다음, HttpResponseMessage.EnsureSuccessStatusCode 메서드를 호출합니다. 이 메서드는 HTTP 응답 상태가 오류 코드인 경우, 예외를 던집니다.
  3. ReadAsAsync<T> 메서드를 호출하여 HTTP 응답을 CLR 형식으로 역직렬화합니다. 이 메서드는 System.Net.Http.HttpContentExtensions 클래스에 정의되어 있는 확장 메서드입니다.

GetAsync 메서드와 ReadAsAsync 메서드는 모두 비동기 메서드입니다. 그리고, 두 메서드는 비동기 작업 자체를 나타내는 Task 개체를 반환합니다. Result 속성을 읽는 작업은 작업이 완료될 때까지 쓰레드를 블록킹합니다.

논-블록킹 호출을 작성하는 방법 등을 비롯한, HttpClient에 대한 보다 자세한 정보는 .NET 클라이언트에서 Web API 호출하기 (C#)를 참고하시기 바랍니다.

이 메서드들을 호출하기 전에 HttpClient 인스턴스의 BaseAddress 속성을 "http://localhost:8080"으로 설정합니다. 가령 다음과 같습니다:

static void Main(string[] args)
{
    client.BaseAddress = new Uri("http://localhost:8080");
    
    ListAllProducts();
    ListProduct(1);
    ListProducts("toys");
    
    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
}

이제 응용 프로그램을 실행하면 다음과 같이 출력될 것입니다. (SelfHost 응용 프로그램을 먼저 실행시켜야 한다는 점을 잊지 마십시요.)

1 Tomato Soup 1.0 (Groceries)
2 Yo-yo 3.75 (Toys)
3 Hammer 16.99 (Hardware)
ID 1: Tomato Soup
Products in 'toys':
Yo-yo
Press Enter to quit.