REST 서비스 템플릿

WCF 2011. 5. 2. 09:00 Posted by 알 수 없는 사용자

이번 포스트에선 REST 서비스를 만들 수 있는 간단한 방법~ REST 서비스 템플릿에 대해 얘기를 해볼까 합니다.
이 주제로 세미나(Your Smarter Visual Studio 2010)를 한번 했었는데, 그 때 시간이 짧아 많은 얘기를 전달하지 못한 것 같아 그 때 차마 하지 못했던 얘기들을 이번 포스팅에서 한번 주절거려 보겠습니다. 
세미나를 한 지가 꽤 오래됐는데 이제서야 포스팅을 하네요~ ^^;;;


그럼 시작합니다~ ^^

REST 서비스에 대한 자세한 설명은 과감하게 생략하도록 하겠습니다. 최근엔 REST에 대한 정보가 많아서 글 솜씨가 부족한 제가 굳이 설명하지 않아도 REST에 대해 알기 쉽게 설명한 글들을 큰 힘 들이지 않아도 찾을 수 있으실 겁니다 ㅎ

그래서, 이번 포스팅의 시작은 REST 서비스 템플릿을 다운받는 것부터 시작하겠습니다.

Visual Studio 프로젝트 템플릿을 다운 받는 방법은 크게 두 가지가 있습니다. 첫째는 Visual Studio를 통해서 다운 받는 것이고, 둘째는 직접 템플릿 다운 사이트(Visual Studio 갤러리 사이트)를 방문하여 다운 받는 것입니다.
두 방법 모두 절대 어렵지 않습니다. 여기선 Visual Studio를 사용하는 방법에 대해 알아보겠습니다.

우선,Visual Studio를 열고, 새 프로젝트를 만들기 위한 창을 띄웁니다. 그리고 좌측 메뉴에서 "온라인 템플릿"을 선택합니다. 그러면 잠깐 동안의 검색 이미지가 나타났다가, 아래 그림과 같은 화면이 나타나는데, 우측 리스트에 보면 "WCF REST Service Template 40(CS)" 아이템이 보입니다. 

 
이 아이템을 선택하고 프로젝트를 생성할 이름과 위치를 지정한 후에 확인 버튼을 클릭하면, 해당하는 템플릿을 다운받고, 바로 새로운 프로젝트를 생성해줍니다. 너무 쉽습니다~ 그죠? ㅎ 

REST 서비스 프로젝트가 생성되면 기본 파일들이 함께 생성되는데, 이 파일 중에 Service1.cs 파일이 실제 REST 서비스를 구현하기 위한 파일입니다. 이 파일을 보면 Service1 이라는 이름의 클래스 밑에 다음과 같은 메서드들이 정의되어 있는 것을 보실 수 있으실 겁니다. 

[WebGet(UriTemplate = "")]
public List<SampleItem> GetCollection() { … }

[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance) { … }

[WebGet(UriTemplate = "{id}")]
public SampleItem Get(string id) {… }

[WebInvoke(UriTemplate = "{id}", Method = "PUT")]
public SampleItem Update(string id, SampleItem instance) { … } 

[WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
 
public void Delete(string id) { … }

 
REST 서비스에서 각 작업과의 상호 작용은 고유한 URI와 HTTP 표준 동사(GET, POST, PUT, DELETE) 를 통해 이루어 집니다. 기본적으로 만들어지는 위와 같은 메서드는 각 HTTP 표준 동사에 대한 메서드 특성 설정에 대한 예시를 보여줍니다.

WebGetAttribute 와 WebInvokeAttribute

WCF REST 서비스는 위와 같이 정의 된 메서드에 접근하기 위해 URI와 HTTP 동사를 메서드에 매핑해 주는데 이때 필요한 것이 WebGetAttribute 와 WebInvokeAttribute 입니다.

WebGetAttribute는 메서드가 HTTP GET 요청에 대해 응답한다는 것을 알려줍니다. WebInvokeAttribute는 기본적으로POST 요청에 응답하지만, PUT 과 DELETE 요청에 대한 응답도 지원합니다. PUT 및 DELETE 요청에 대해 응답하는 메서드를 정의하기 위해서는 WebInvokeAttribute.Method 속성을 설정해주면 됩니다. 설명이 좀 어려워 보이지만 위 코드를 보면 쉽게 이해할 수 있으실 겁니다. ^^


REST 서비스 구현

기본적인 부분은 모두 언급이 된 것 같습니다. 이제는 이를 이용하여 간단한 REST 서비스를 만들어보겠습니다.
만들려는 서비스는 회원 관리에 대한 것으로 새로운 회원의 입력, 회원 정보 조회, 회원 정보 수정 및 삭제를 할 수 있는 서비스를 구현해보도록 하겠습니다.

우선, 서비스에서 사용할 Member 클래스를 다음과 같이 정의하였습니다.

[DataContract]
public class Member
{
    [
DataMember(Order=0)]
    
public string Id { getset; }
    [
DataMember(Order=1)]
    
public string Name { getset; }
    [
DataMember(Order=2)]
    
public string Job { getset; }
    [
DataMember(Name="PhoneNumber", Order=3)]
    
public string Phone { getset; }
    [
DataMember(Order=4)]
    
public string Address { getset; }
}

 
그리고, 실제 서비스의 구현은 다음과 같습니다.

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MemberService
{
    [WebGet(UriTemplate = "GetAll")]
    public MemberList GetCollection()
    {
        BizMember bizMember = new BizMember();
        return bizMember.GetAll();
    }

 
    [WebInvoke(UriTemplate = "Add", Method = "POST")]
    public void Create(Member instance)
    {
        BizMember bizMember = new BizMember();
        bizMember.Add(instance);
    }

 

    [WebGet(UriTemplate = "{id}", ResponseFormat=WebMessageFormat.Json)]
 
   public Member Get(string id)
    {
        BizMember bizMember = new BizMember();
        return bizMember.Get(id);
    }

 

    [WebInvoke(UriTemplate = "{id}", Method = "PUT")]
 
   public void Update(string id, Member instance)
    {
        BizMember bizMember = new BizMember();
        bizMember.Update(id, instance);
    }
 

    [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
    public void Delete(string id)
    {
        BizMember bizMember = new BizMember();
        bizMember.Delete(id);
    }
}


코드는 보시면 아시겠지만 그리 어렵지 않습니다. BizMember 라는 클래스에서 여러가지 작업이 이루어지는데 이 클래스 역시 그렇게 어려운 내용이 없기에 자세한 설명은 생략하겠습니다. 대신에 소스를 첨부시켜 놓을 테니 잠깐만 살펴보시면 알 수 있으실 겁니다. ^^;; BizMember 클래스에 대한 설명까지 하려면 내용이 너무 길어질 것 같아 그러니 양해 부탁드립니다~ 흠흠;;; 

앞에서 설명을 하지 않았는데 위 코드를 보면 WebGetAttribute와 WebInvokeAttribute에 UriTemplate 이라는 속성이 보이실겁니다. 이 속성은 서비스로 들어온 요청의 URI와 매핑을 시키는 속성이라고 생각하시면 됩니다.
예를 들어, 위의 코드에서 Create 메서드의 경우 UriTemplate 속성의 값이 "Add" 로 되어 있는데, 만약 이 서비스의 기본 주소가 "http://localhost:2853/MemberService"이라고 할 때, 요청 들어온 URI가 "http://localhost:2853/MemberService/Add" 일 때 Create 메서드를 호출 한다는 것입니다. 물론, Create 메소드의 WebInvokeAttribute에 정의되어 있듯이 "POST" 방식의 요청이어야 하겠죠~?

또한, 위 코드의 Get 메서드처럼 UriTemplate 속성의 값이 "{id}"인 경우가 있는데, 이는 메서드의 파라미터인 id의 값이 URI에 들어가는 형태가 되는 것입니다. 예를 들면, HTTP "GET" 방식으로 "http://localhost:2853/MemberService/ruaa" 의 주소로 요청이 들어오면, 위 코드에서의 Get 메서드가 호출되면서 Get 메서드의 id 파라미터 값으로 ruaa가 입력되는 것입니다.
 
그럼, 서비스의 기본 주소는 어떻게 설정할 수 있을까요? 궁금하지 않으신가요? ㅎ
기존 WCF 서비스에서는 web.config 파일을 사용했었는데, REST 서비스 템플릿은 조금 다릅니다. 
global.asax 파일을 열어보시면 그 답을 찾을 수 있으실 겁니다.

private void RegisterRoutes()
{
    // Edit the base address of Service1 by replacing the "Service1" string below
    RouteTable.Routes.Add(new ServiceRoute("MemberService"new WebServiceHostFactory(),
                                            typeof(MemberService)));
}

 
위 코드를 보니 어디서 많이 봤다~ 싶으네요~ ㅎ
ASP.NET 4.0과 ASP.NET MVC 프로젝트를 한 번이라도 구현해보신 분들이라면 저랑 같은 생각을 하셨을겁니다. ASP.NET MVC 때 부터 사용한 라우팅 방법과 같은 방식을 사용하고 있네요~

아무튼, 위 코드 처럼 구현을 할 경우 서비스의 기본 주소는 "http://{서비스가 배포된 기본 주소}/MemberService"가 됩니다.


Help 페이지

이렇게 REST 서비스 템플릿을 이용하여 서비스를 구현하고, 빌드를 하면 기본적으로 서비스에 대한 help 페이지를 만날 수 있습니다. help 페이지의 주소는 서비스의 기본주소에 "/help" 가 붙는 형식입니다.
저 같은 경우, Visual Studio 개발 서버로 돌렸기 때문에 다음 그림에서 보듯이 help 페이지의 경로는 "http://localhost:2853/MemberService/Help" 가 되는 것입니다.


위 그림을 보시면 알겠지만, 각 서비스 끝점에 대한 간단한 설명을 볼 수 있고, 각 서비스 끝점의 메서드를 클릭하면 자세한 내용을 확인할 수 있습니다. 이는 WCF 서비스의 헬프 페이지와 아주 유사하죠~? 

자~ 이제 슬 마무리 지어 볼까요? ^^

이번 포스팅을 통해 REST 서비스의 많은 부분에 대해 알려드리진 못했지만 기본적인 부분은 모두 설명이 된 듯 합니다. 그리고 REST 서비스 템플릿을 이용하면 정말 쉽게 WCF를 이용한 RESTful 서비스를 구현할 수 있다는 것도 알게 되었습니다. 

혹시나 추가적인 설명이 필요한 부분이나 질문이 있으신 분들은 댓글 남겨주시면 성심성의껏(?) 답변 해드리겠습니다.
그리고, 첨부한 소스 코드를 참조하시어 테스트 해보시면 이번 포스팅에서 설명한 많은 부분이 이해가 되실 것 같습니다.