Silverlight를 설치하려면 여기를 클릭합니다.*
Korea 대한민국변경|Microsoft 전체 사이트
MSDN
|개발자 센터
MSDN Home   MSDN Home
MSDN 홈 > MSDN Magazine > 2001년 기사 > 웹 서비스: SOAP와 ASP.NET을 사용하여 재사용 가능한 웹 구성 요소 구축

웹 서비스: SOAP와 ASP.NET을 사용하여 재사용 가능한 웹 구성 요소 구축


요약? XML과 HTTP는 실행되는 플랫폼에 관계 없이 인터넷을 통해 서로 통신할 수 있는 응용 프로그램을 구축하기에 적합한 플랫폼 간 기술입니다. Microsoft .NET Framework의 웹 서비스를 사용하면 HTTP GET, HTTP POST 및 SOAP를 사용하여 통신하는 구성 요소를 쉽게 작성할 수 있습니다.

이런 응용 프로그램을 구축하려면 동기 및 비동기 작업, 보안, 상태 관리, .NET Framework에 의한 프록시 관리에 대한 지식과 함께 이러한 개념을 반드시 이해하고 있어야 합니다.

본 문서는 2000년 봄에 Microsoft Press에서 출판된 David Platt의 Microsoft .NET 플랫폼을 소개하는 서적의 내용을 발췌한 것입니다.

지금 인터넷 프로그래밍에 큰 지각 변동이 일기 시작하고 있습니다. 사람들이 작성하는 거의 모든 프로그램에서 인터넷 액세스는 곧 필수 수항이 될 것입니다. 브라우저 사용이 편리하다고 느끼는 경우를 제외하고, 일반 브라우저는 사용하지 않고 대신 특정 작업을 수행하도록 최적화된 전용 프로그램을 사용할 것입니다. 인터넷에 연결되지 않은 경우를 제외하고, 프로그램에서 인터넷에 액세스하는지를 느끼지 못할 것입니다.

이러한 프로그램의 한 종류가 Napster입니다. 이 프로그램을 사용하면 특정 기준을 만족하는 음악 파일을 찾기 위해 연결된 수천 명의 사용자 공유 하드 드라이브를 검색하여 원하는 음악을 다운로드할 수 있습니다. 멀티 플레이어 게임의 전용 사용자 인터페이스는 숨겨진 인터넷 액세스의 또 다른 예입니다. Microsoft® Money 최신 버전에서는 웹 컨텐트(예: 현재의 주식 시세, 최근 잔액)와 데스크톱 컨텐트(예: 로컬로 만든 금융 계획)를 완벽하게 통합하는 작업을 수행합니다.

이런 종류의 프로그램을 개발하려면 인터넷을 통해 다른 프로그램과 정보를 교환하는 코드를 작성하는 빠르고 간단한 방법(즉, 저렴한 방법)이 있어야 합니다. 이 개념은 전혀 새로운 것이 아닙니다. RPC, DCOM, MSMQ( Microsoft Message Queue Services) 등 여러 기술은 이런 종류의 통신을 가능하게 합니다. 각 기술 자체는 새로운 것이지만, 모두 비슷한 시스템에서만 작동한다는 치명적인 한 가지 단점이 있습니다. 즉, MSMQ는 MSMQ와, DCOM 클라이언트는 DCOM 서버와만 통신이 가능하다는 것입니다.

실제 필요한 것은 프로그램 간에 통신할 수 있도록 하는 인터넷에 대한 보편적인 프로그램 액세스 방법입니다. 이 방법은 운영 체제뿐만 아니라 프로그램의 내부 구현과 독립적이어야 합니다. 현재는 C++이나 Visual Basic, 어떤 공급업체, 어떤 버전으로도 단일 데스크톱에서 이 문제를 거의 해결할 수 없습니다. 그리고 프로그래밍하기 쉬워야 하며 누구나 구입에 부담이 없어야 합니다.


맨 위로


솔루션 아키텍처

인터넷에 있는 엄청난 수의 이기종 컴퓨터를 처리하는 유일한 방법은 일반적으로 가장 낮은 공통 분모를 사용하는 것입니다. 즉, 한 장소에서 다른 장소로 정보를 전송할 때는 인터넷에 연결된 모든 사용자를 지원하는 표준 프로세스를 사용해야 합니다. 가장 일반적인 인터넷 전송 프로토콜은 모든 웹 브라우저가 페이지를 표시할 수 있도록 요청하는 데 반드시 사용하는 HTTP입니다. HTTP를 통해 전송하는 순수한 정보를 인코드하는 플랫폼 간 표준이 XML입니다.

Microsoft는 이런 개념을 모아 웹 서비스라는 개념을 개발했습니다. 웹 서비스는 HTTP와 XML을 사용하여 서버의 개체가 클라이언트로부터 수신되는 요청을 받아들이는 완벽한 방법입니다. 웹 서비스를 만들려면 로컬 클라이언트가 직접 액세스하여 웹 클라이언트에서 사용할 작업을 지정하고 ASP.NET이 나머지를 수행하도록 하는 Microsoft .NET 서버 개체를 작성하면 됩니다. HTTP를 통해 수신되는 요청을 받아들이는 미리 작성된 인프라에 자동으로 연결하고, 그림 1에 나타난 대로 개체에 대한 호출에 매핑합니다. 웹 서비스에 롤링하여 개체가 HTTP와 XML을 사용하는 웹에 있는 모든 사용자와 작업할 수 있습니다. 여러분은 운영 체제가 제공하는? 웹 통신을 처리할 인프라를 작성할 필요가 없습니다.

Figure 1 Handling HTTP Requests
그림 1. HTTP 요청 처리

.NET은 클라이언트 측에서 그림 2처럼 HTTP 요청을 받아들이는 서버가 제공한 웹 서비스에 쉽고 기능 기반의 액세스를 하는 프록시 클래스를 제공합니다. 개발자 도구는 웹 서비스 설명을 읽고 함수가 들어 있는 프록시 서버를 클라이언트를 개발하는 데 사용하는 언어로 생성합니다. 클라이언트가 이런 함수 중 하나를 호출하면 프록시 클래스는 HTTP 요청을 생성하고 서버로 전송합니다. 서버에서 응답이 오면 프록시 클래스는 결과를 구문 분석하고 함수에서 이들을 반환합니다. 이렇게 하면 기능 기반의 클라이언트는 HTTP와 XML을 사용하는 웹 서버와 완벽하게 상호 작용할 수 있습니다.

Figure 2 Proxy Classes
그림 2. 프록시 클래스

맨 위로


웹 서비스 작성

새 기술을 설명할 때 항상 그랬듯이, 웹 서비스를 보여줄 수 있는 가장 간단한 프로그램을 작성했습니다. 이 예제 웹 서비스는 두 번째 자리가 있는 문자열이나 없는 문자열 형식으로 시스템의 현재 시간을 제공합니다. 이 문서 맨 위에 있는 링크에서 이 서비스에 대한 예제 코드를 다운로드하면 이 설명을 보다 자세하게 따라 할 수 있습니다. 실행하려면 Microsoft .NET SDK를 다운로드하고 설치해야 합니다.

다른 소프트웨어 패키지를 사용할 필요가 없도록 .asmx 페이지의 형태로 이 웹 서비스를 작성했습니다. 먼저, .NET SDK를 설치한 다음, Microsoft Internet Information Service(IIS)의 관리 도구를 사용하여 서비스 파일을 개발할 폴더를 가리키는 가상 디렉터리를 설정했습니다. 그런 다음 서버에서 TimeService.asmx라는 파일에 ASP.NET 코드를 작성했습니다.

웹 서비스는 아주 쉽게 작성했습니다. 메모장에서 작성했습니다( 그림 3 참조). 매우 간단하지만 여러분에게는 아마 새로운 구조가 있을 것입니다. 따라서 부분별로 검토해 보겠습니다. 이 문서의 코드는 베타 1 이전의 버전을 기반으로 하며, 호출은 최종 버전이 릴리스되기 전에 다소 변경될 수 있습니다. 프로그램은 표준 ASP.NET 인사말 <%@...%>로 시작합니다. 여기에서 WebService 지시어는 ASP.NET이 페이지의 코드를 웹 서비스로 나타내도록 합니다. 언어 특성은 해당 페이지의 코드를 컴파일할 언어를 ASP에게 알려줍니다. 여기서는 대부분의 개발자에게 익숙한 Visual Basic을 선택했습니다. ASP.NET은 Visual Basic.NET을 사용하여 코드를 컴파일합니다. .NET SDK에 동봉된 모든 언어 컴파일러인 Visual Studio®를 설치해야 합니다. 클래스 특성은 이 서비스를 요청하는 수신 요청을 활성화하기 위해 개체 클래스의 이름을 ASP.NET에 알립니다.

이 페이지의 나머지 부분에서는 클래스를 구현하는 코드가 포함되어 있습니다. 먼저, Visual Basic.NET의 새 기능인 Imports 지시어를 사용하여 컴파일러에게 이름 공간을 가져옵니다. "이름 공간"이란 용어는 미리 작성된 기능에 대한 설명을 나타내는 방법으로, 개념적으로 Visual Basic 6.0 프로젝트의 참조와 동일합니다. ASP.NET은 클라이언트에서 요청이 도착하면 이 예제 코드를 컴파일하기 때문에 이런 참조를 설정하는 프로젝트가 없으며 따라서 코드에 명시적으로 추가해야 합니다. Imports 다음에 나오는 이름은 참조를 포함할 기능을 설정하는 컴파일러에 알립니다. 이 경우 시스템과 System.Web.Services에는 웹 서비스를 작성하는 데 필요한 미리 작성된 기능이 포함되어 있습니다.

다음 줄은 클래스 이름을 정의합니다. Visual Basic의 이 클래스는 여러분이 작성하는 것과 비슷합니다. 줄 끝에 새로운 키워드인 Inherits WebService가 나타납니다. 이것은 Visual Basic.NET의 주요 향상된 기능 중 하나를 나타내는 것으로 상속이라는 개체 지향 개념을 지원합니다. 새 TimeService 클래스가 WebService 클래스에서 상속되면 시스템에서 제공하는 클래스 이름인 WebService(기본 클래스라고 함)에서 모든 코드를 가져오고, 새 TimeService 클래스(파생 클래스라고 함)에 포함시키도록 컴파일러에 지정합니다. 그리고 상속된 클래스의 코드를 재사용하고 새로운 부류에서 해당 클래스의 기능을 무시합니다. 실제로 아무것도 이동하지 않고 잘라내어 붙여넣는 것으로 상속을 생각하십시오. 사실 상당히 복잡한 C++와 Java 언어에서 물리적으로 잘라내어 붙여넣는 것을 편집기 상속이라고 합니다.

Visual Basic 6.0에 사용된 여러 개체가 운영 체제에 제공되는 것처럼 WebService 클래스는 새로운 .NET 런타임 라이브러리에 의해 제공됩니다. WebService는 수신 HTTP 요청을 처리하는 데 필요한 모든 작성된 단순 작업을 포함하고 개체에 적절한 방법을 라우트합니다.

이름 공간을 가져오고 상속을 선언하는 것의 차이가 무엇인지에 대한 질문을 가끔 받습니다. 즉, 키워드를 가져오고 상속하는 것의 차이점은 무엇입니까? Imports 문은 기능 집합의 설명에만 적용하고 실제 사용하지는 않습니다. 전에 말했듯이 참조를 설정하는 것과 같습니다. Inherits 키워드는 설명에서 언급한 코드를 가져와서 사용합니다. 스테로이드에 있는 Dim과 같습니다.

클래스를 정의했으므로 이제 클래스의 메서드와 함수를 정의해야 합니다. Visual Basic 6.0에 사용되는 방법과 아주 비슷하지만 새로운 것이 한 가지 있습니다. 즉, 새 특성인 <WebMethod()>를 웹 클라이언트에 나타내려는 모든 메서드에 추가해야 합니다. 이렇게 하면 나타나는 메서드를 클라이언트에 웹 서비스로 나타내도록 ASP.NET에 알립니다. Visual Basic 6.0에서 public, private, const와 같은 여러 가지 특성을 보았습니다. .NET Framework와 Visual Basic.NET에는 이 중 많은 부분을 사용하여 이들을 지정하는 새 구문이 많습니다. 클래스에 public과 private 메서드를 포함할 수 있는 것과 마찬가지로 웹 클라이언트에 나타낸 메서드와 그렇지 않은 메서드를 포함할 수 있습니다.
마지막으로, 클래스 메서드의 내부로 들어가 보겠습니다. 코드에서 날짜와 시간 변수를 처리하는 것이 약간 이상해 보일 수 있습니다. 저도 그랬습니다. 하지만 걱정하지 마십시오. 단지 Visual Basic.NET이 날짜와 시간을 처리하는 방식 때문입니다.

Figure 4 TimeService.asmx in a Browser
그림 4. 브라우저에서 TimeService.asmx

이제 클라이언트에서 웹 서비스에 액세스할 수 있습니다. ASP.NET에는 또한 이를 위해 미리 잘 작성된 지원 기능이 포함되어 있습니다. Microsoft Internet Explorer 5.5를 실행하고 제가 작성한 ASP.NET 페이지를 요청하면 그림 4에 표시된 페이지가 나타납니다. ASP.NET은 웹 서비스 페이지 자체에 대한 액세스를 감지하고(서비스 내의 메서드 중 하나와 반대) 서비스에 대한 정보 페이지로 응답합니다. 이 페이지는 ASP.NET이 대상 클래스(이 경우에는 GetTime만 해당)에서 발견한 모든 메서드를 보여주고 각 메서드에 대한 테스트 기능을 제공합니다. 두 번째 자리 표시 여부를 지정하려면 True나 False를 입력하고, Invoke를 누릅니다. 그러면 테스트 페이지는 지정된 메서드를 호출하고 그림 5에 나타난 대로 결과를 반환합니다(TRUE를 입력한 경우). 매개 변수가 URL에 전달되고 결과는 GET 프로토콜을 통해 XML로 반환됩니다. 또한 http://localhost/your virtual directory name/timeservice.asmx와 같은 정식 UTL을 입력하여 IIS를 통과하는 방식으로 페이지를 열어야 합니다. 하드 디스크의 탐색기 보기에서 페이지를 두 번 누르면 IIS와 ASP.NET을 생략하고 원하지 않는 .asmx 페이지의 텍스트만 표시됩니다.

Figure 5 Show Seconds
그림 5. 초 표시

이것이 웹 서비스를 작성하기 위해 해야 하는 모든 것입니다. else와 endif를 포함하여 13줄뿐입니다. 얼마나 쉽습니까?

맨 위로


웹 서비스의 자체 설명: SDL 파일

프로그래머가 웹 서비스를 사용하는 클라이언트 응용 프로그램을 개발할 수 있도록 저는 디자인과 프로그래밍 과정 동안 필요한 정보를 제공해야 합니다. 예를 들어, 웹 서비스의 클라이언트는 웹 서비스가 나타내는 메서드, 필요한 매개 변수, 지원되는 프로토콜, 표준 COM 구성 요소가 수행할 유형 라이브러리와 개념적으로 비슷합니다. 그러나, 유형 라이브러리의 문제는 Microsoft COM과 관련된 것이며, 비 Microsoft 시스템이 웹 서비스를 이용할 수 있습니다. 또한 Microsoft 내장 클라이언트 응용 프로그램이 이러한 서비스를 사용할 수 있도록 비 Microsoft 시스템을 실행하는 비 Microsoft 서비스의 설명을 작성할 수도 있습니다. 필요한 것은 서비스를 설명하는 보편적인 메서드입니다. 그리고 자동 개발 환경에서 사용할 수 있게 시스템이 읽을 수 있도록 해야 합니다.

ASP.NET은 이런 설명 서비스를 제공합니다. 웹 서비스를 컴파일하면 ASP.NET은 이 서비스에서 지원하는 프로토콜과 제공 메서드 및 해당 서비스에서 필요로 하는 매개 변수를 나열하는 파일을 생성할 수 있습니다. 이 파일은 XML로 인코드되며 SDL(Service Descriptor Language)이라고 하는 용어를 사용합니다. 웹 서비스의 SDL 파일은 서비스가 수행할 수 있는 작업을 나열하고 이 작업에 대해 질문하는 방법을 알려주기 때문에 연락처라고도 합니다.

URL에 '?SDL' 문자를 첨부한 .asmx 파일을 요청하여 ASP.NET에서 SDL 파일을 얻습니다. 예를 들어, 로컬 시스템에서 URL http://localhost/AspxTimeDemo/TimeService.asmx?SDL을 요청하여 예제 웹 서비스에 대한 SDL을 얻었습니다. 실제 실행되는 서버에서 예제 서비스를 나타내지 않았기 때문에 예제 코드에 이 파일을 제공했습니다.

Visual Basic 6.0과 Visual C++® 6.0에서 COM 구성 요소를 작성할 때는 먼저 구성 요소를 작성한 다음, 이것을 설명하는 유형 라이브러리를 작성했습니다. 인터페이스를 설명하는 유형 라이브러리로 시작했을 때는 이를 구현한 코드를 작성하면 SDL은 둘 모두 이런 방법으로 동작할 수 있습니다. ASP.NET은 관심 있는 클라이언트에 대해 SDL 파일을 생성할 경우 이 예제에서 수행한 것과 같이 먼저 코드를 작성할 수 있습니다. 또한, 유틸리티 프로그램 WebServiceUtil을 사용하여 이 프로그램이 설명하는 서비스를 구현하는 템플릿 파일을 생성할 수 있습니다(Visual Basic 6.0에서 키워드를 구현하는 것과 비슷함).

SDL 파일은 다소 복잡하기 때문에 원칙를 설명하기 위해 일부를 추출했습니다( 그림 6 참조). serviceDescription 요소는 파일의 루트입니다. 이 내부에 있는 모든 것은 이 웹 서비스 설명의 일부입니다. 여기에는 웹 서비스의 이름을 부여하는 특성, 이 경우 TimeService이 들어 있습니다.

루트에는 두 가지 흥미로운 하위 요소 유형이 포함되어 있습니다. 첫 번째는 서비스가 지원하는 프로토콜, 요청을 인코드하는 방법, 해당 프로토콜에 대한 응답 데이터를 관심 있는 클라이언트 개발자에 알리는 프로토콜 설명입니다. HTTP GET 작업은 가장 간단하게 표시할 수 있으므로 하나를 예로 들어 보았습니다. SDL 사용자나 개발 도구는 서비스 이름 TimeService가 이 프로토콜을 통해 액세스할 수 있다는 것을 알 것입니다. 완전한 SDL 파일에는 HTTP POST 작업을 통해서 액세스할 수 있고 HTTP/XML 하이브리드인 SOAP(Simple Object Access Protocol)를 통해서도 액세스할 수 있는 항목이 들어 있습니다. 이 문서의 다음 단원에서 HTTP POST와 SOAP를 설명합니다. 프로토콜 설명 내부에는 지정된 URL에 있는 GetTime이라는 메서드가 서비스에 있습니다. 요청하는 데 ShowSeconds라는 단일 매개 변수가 필요합니다. 이 매개 변수가 HTTP GET 작업에 사용된다는 것은 문자열 형식으로 전달된다는 것을 암시합니다. 응답은 XML에 다시 문자열 형식으로 반환됩니다.

SDL 파일에서 두 번째 관심 있는 부분은 W3C 표준 <스키마> 요소입니다. 여기에는 특정 프로토콜에서 액세스되는 방법이나 있는 위치에 관계 없이 서비스의 추상적인 정의가 포함되어 있습니다. 이 정의는 유형 라이브러리의 인터페이스 정의로 생각하십시오. 이 정의는 메서드 집합을 설명하지만 이들을 구현하는 것은 아닙니다. 여기의 예제 SDL 파일은 ShowSeconds라는 부울 매개 변수를 요구하는 GetTime이라는 함수를 설명합니다. 문자열로 반환되는 GetTime 메서드 결과에 대한 별도 설명이 들어 있는 것을 볼 수도 있습니다.

맨 위로


웹 서비스 클라이언트 작성

이제 이 서비스에 액세스하는 클라이언트를 작성하는 데 필요한 사항에 대해 살펴 보겠습니다. 클라이언트를 작성하는 것이 서비스 자체를 작성하는 것보다 쉽다는 것을 알았습니다. ASP.NET 수신기는 수신 요청을 HTTP: HTTP GET, HTTP POST 및 SOAP로 구성하는 세 가지 다른 방법을 받아들입니다. 이것은 미국식 영어, 영국식 영어, 호주식 영어 등 영어의 세 가지 방언으로 교신하는 항공 관제탑의 경우와 개념적으로 비슷합니다. 이런 방법을 사용하는 클라이언트를 작성하는 방법을 모두 검토해 보겠습니다.

맨 위로


사례? 1: HTTP GET

웹 서비스는 URL 문자열에서 ShowSeconds 매개 변수를 사용하여 간단한 HTTP GET 요청을 통해 요청을 받습니다. 앞 단원에서 이 프로토콜에 대한 웹 서비스 지원을 설명하는 SDL 파일을 살펴 보았습니다. 이 요청에 액세스를 제공하는 예제 웹 페이지는 그림 7과 같으며 이 문서의 예제 코드에서 GetTimeThroughHttpGet.htm 파일로 제공됩니다. 요청이 서버에 도달하면 ASP.NET은 URL 문자열에서 매개 변수를 분석하고 TimeService 개체를 만들어 GetTime 메서드를 호출합니다.

Figure 7 Sample Web Page
그림 7. 예제 웹 페이지

맨 위로


사례 2: HTTP POST

웹 서비스는 입력 컨트롤의 ShowSeconds 매개 변수를 사용하여 HTTP POST 요청을 통해 요청을 받아들입니다. HTTP POST 작업에 대한 웹 서비스 지원을 설명하는 SDL 파일의 부분은 그림 8과 같습니다. 별도의 <request> 및 <response> 요소는 서비스 요청 즉, 양식을 게시하는 것이 응답을 수신하는 것과는 별도의 작업임을 나타냅니다. 이것은 HTTP POST 작업이 일반적으로 작동하는 방식이므로 걱정하지 마십시오. <form> 요소는 이 매개 변수를 전달하는 ShowSeconds라는 입력 컨트롤이 들어 있는 양식이 POST 작업에 필요하다는 것을 나타냅니다. Microsoft FrontPage® 2000을 사용하여 이를 수행하는 양식을 작성했습니다. 그림 9는 스크린샷이며? 그림 10은 HTML 코드입니다. 파일은 GetTimeThroughHttpPost.htm으로 제공됩니다. 요청이 서버에 도달하면 ASP.NET은 TimeService 개체를 만들고 양식 컨트롤에서 매개 변수를 풀링하고 GetTime 메서드를 호출합니다.

Figure 9 Sending a Request via HTTP POST
그림 9. HTTP POST를 통해 요청 보내기

맨 위로


사례 3: SOAP



HTTP POST 작업에 대한 웹 서비스 지원을 설명하는 SDL 파일 일부가 그림 11에 나와 있습니다. SOAP를 사용하여 웹 서비스의 GetTime 메서드를 호출하는 그림 12의 예제 프로그램을 작성했습니다. Microsoft 인터넷 전송 컨트롤을 사용하여 실제 HTTP 통신을 수행합니다. URL이 서비스 내의 메서드를 가리키는 앞의 두 예와 달리 SOAP 인코딩은 웹 서비스의 모든 메서드가 들어 있는 .asmx 페이지로 지정됩니다. 서버로 전송된 SOAP 패킷은 상위 편집 컨트롤에서 볼 수 있듯이 합의된 스키마에 따라 XML로 인코드된 기능 이름과 해당 매개 변수를 포함합니다. SOAP 패킷이 서버에 도달하면 ASP.NET이 이를 인식하고 패킷에서 메서드 이름과 해당 매개 변수를 구문 분석하고 개체를 만들고 호출을 합니다.

Figure 12 Soap Client
그림 12. Soap 클라이언트

요청 패킷의 XML 인코딩은 2000년 8월 기사에서 설명한 SOAP Toolkit Rob Caron과 동봉된 예제에서 사용한 것과 약간 다릅니다. SOAP와 .NET은 현재 개발 중이므로 이런 종류의 일탈은 예상할 수 밖에 없습니다.

맨 위로


사례 4: 자동 SOAP 프록시, 동기 작업

앞 단원의 SOAP 예제는 사실 작성 작업이 지루합니다. 반복되는 많은 양의 패키지를 반드시 수정해야 하지만 방법마다 다르다는 점에서 COM에 IDispatch 클라이언트를 수동으로 작성해야 합니다. 자동화 개체 액세스(Visual Basic을 사용하는 대다수의 프로그래머는 C++이 지루하다는 것을 전혀 느끼지 못했으며, 나머지 프로그래머는 개의치 않거나 적극적으로 수용함)를 가까스로 처리하는 C++과 Visual Basic 제공 래퍼 클래스처럼 .NET SDK는 웹 서비스에 대한 SOAP 클라이언트 작성을 쉽게 만들어 주는 래퍼 클래스 생성 기능을 제공합니다.

이런 작업을 수행하는 도구는 .NET SDK에 포함된 WebServiceUtil이라는 명령줄 유틸리티입니다. 이 유틸리티는MSDN Magazine의 2000년 9월호에서 설명한 Visual Studio에도 제공됩니다(" Visual Studio.NET: Build Web Apps Faster and Easier Using Web Services and XML" 참조). 이 문제는 SDL 파일에서 웹 서비스 설명을 읽고 사용자가 지정한 언어에서 액세스하기 위한 프록시를 생성합니다. 현재 Visual Basic.NET, C#, JavaScript를 지원하지만 C++은 지원하지 않습니다. SDL 파일을 로컬 디렉터리에 복사하고 다음 명령줄을 사용하여 WebServiceUtil을 실행했습니다.

webserviceutil /command:proxy /language:vb /path:timeservice.sdl
Visual Basic 기반 프록시 코드는 그림 13과 같습니다. 여기에는 웹 서비스에서 시간을 가져오는 기능의 동기 및 비동기 버전이 모두 포함되어 있습니다. 동기 버전은 여기에서 설명하고 비동기 버전은 다음 단원에서 설명합니다. 프록시 클래스는 실제 코드가 들어 있는 기본 클래스 System.Web.Services.Protocols.SoapClientProtocol(이런 긴 이름을 사용할 것이므로 익숙해지기 바랍니다.)에서 상속합니다. 프록시 클래스에는 프록시가 기본 클래스에서 상속하는 Path라는 속성이 있습니다. 이 속성은 호출이 지정된 서버의 URL을 지정합니다. 여기에는 원본 SDL 파일에서 얻은 기본값이 들어 있지만 예제 프로그램은 런타임 시 이를 변경하는 방법을 보여줍니다. 클라이언트는 기본 클래스에서 상속한 메서드 Invoke를 호출하여 프록시에 있는 명명된 메서드를 호출합니다. 이 메서드는 앞 단원에서 본 것처럼 메서드 이름과 매개 변수가 들어 있는 SOAP 패킷을 만들고 HTTP를 통해 서버로 전송합니다. SOAP 응답 패킷이 서버에서 반환되면 기본 클래스는 반환 값을 구문 분석하여 프록시에 반환한 다음 클라이언트로 반환합니다.

함수 이름(괄호 사이의 문자)에 있는 특성 블록에는 메서드 및 매개 변수 이름과 같은 호출을 구성하는 방법을 기본 클래스에게 알리는 정보가 들어 있습니다. Visual Studio.NET은 정보를 시스템 코드의 미리 작성된 기능으로 전달하는 수단으로 특성을 많이 사용합니다. 처음에는 이것이 변경할 수 없는 런타임 특성을 프로그램 실행 동안 변경할 수 있는 특성과 구분하기 어려웠던 기본 클래스의 구성 변수를 통해 수행되었습니다.?

클라이언트의 실제 Visual Basic 기반 코드는 그림 14와 같으며 예제 클라이언트 응용 프로그램은 그림 15와 같습니다. 그리 어렵지 않다는 것을 알 수 있습니다. 어려운 문제는 프록시 클래스가 대신해 줍니다.

Figure 15 Client App
그림 15. 클라이언트 응용 프로그램

맨 위로


사례 5: 자동 SOAP 프록시, 비동기 작업

인터넷은 단일 데스크톱보다 훨씬 비정형적이며 비결정적입니다. 디즈니랜드처럼 많은 재미가 있지만 끝이 없는 줄서기를 감내할 수 있는 치밀한 전략이 없다면 즐길 수 있는 희망이 없을 정도로 거의 항상 혼잡합니다. 웹 서비스에 대한 가장 간단한 호출조차도 순풍이 불어주는 좋은 날에도 5초~10초 정도 걸리며 어떤 곳이라도 갈 수 있습니다. 여러분은 1, 2초 이상 움직임이 없는 인터페이스에 사용자를 묶어 둘 수 없습니다.

프로그램의 사용자 인터페이스를 처리하는 스레드에서 웹 서비스에 대한 호출을 차단할 수 없습니다. 예제에서와 마찬가지로 유명 응용 프로그램도 양식 단추의 응답 기능에서 동기 프록시 메서드를 호출할 수 없습니다. 사용자 인터페이스를 중단하지 않고 응답을 기다렸다가 잠시 후에 해당 스레드에서 결과를 검색하여 사용자에게 표시할 수 있는 다른 스레드를 호출해야 합니다.

지금까지 대부분의 프로그래머들은 이런 상황을 처리하기 위해 자신의 인프라 코드를 작성해야 했습니다. 대개 이런 종류의 코드는 작성하기가 매우 까다로우며 시간도 오래 걸려 비용이 많이 들었습니다. 그러나, 이제 이 상황은 거의 보편화되었으므로 WebServiceUtil가 생성한 자동 프록시 클래스가 미리 작성된 코드에 통합되어 이를 처리합니다. 호출하고 완료될 때까지 차단하지 않고 프로그램은 요청 데이터를 서버에 전송한 다음 즉시 반환하는 한 메서드를 호출할 수 있습니다. 나중에 편리한 때에 프로그램이 서버에서 반환된 결과를 가져오는 다른 메서드를 호출할 수 있습니다. 이렇게 하면 예약 코드를 작성할 필요가 없기 때문에 작업이 상당히 쉬워집니다. 그리고 비동기 액세스를 지원하도록 작성된 서버뿐만 아니라 모든 서버에도 작동합니다.

그림 13은 시간 서비스 호출의 동기 및 비동기 버전을 모두 보여 주었습니다. 프록시에는 Beginmethodname이라는 이름(이 경우 BeginGetTime)의 메서드가 들어 있습니다. 이 매개 변수 목록은 동기 메서드의 매개 변수(이 경우 ShowSeconds 부울 변수)로 시작합니다. 이 문서의 범위를 벗어나는 콜백 사례에 사용된 매개 변수가 두 개 이상 있습니다. 그림 14의 클라이언트 코드에서 둘 모두에 Visual Basic에서 널과 비슷한 Nothing을 전달합니다. 이것은 통신 연결을 시작하여 요청을 전달하고 즉시 반환합니다. 반환 값은 나중에 결과를 얻는 데 사용할 유형 IAsyncResult의 개체입니다. 이제 원하는 작업을 할 수 있습니다. 랩에서 이 작업을 수행할 때는 긴 작업을 시뮬레이션하기 위해 1에서 10억까지 계산하는 길고 반복적인 루프를 .asmx 페이지에 삽입했습니다. 여러분이 직접 테스트하려면 스스로 이 작업을 수행해야 합니다.

나중에 작업 결과를 가져오고 싶으면 서버가 결과를 반환했을 때 실제 시간을 확인하십시오. 프록시에서 Endmethodname 메서드(이 경우 EndGetTime)를 호출하고 Begin 메서드에서 가져온 IAsyncResult를 전달하여 이 작업을 수행합니다. 클라이언트는 동시에 여러 요청을 가지기 때문에 바로 이 방법으로 인프라 코드가 여러분에게 결과를 제공합니다. 마지막 메서드는 결과를 가져와 사용자에게 반환합니다.

그러나 작업이 언제 완료되었으며 결과를 가져올 준비가 되었는지 어떻게 알 수 있을까요? IAsyncResult 개체는 True 또는 False를 반환하는 IsCompleted라고 하는 이런 목적으로 사용되는 메서드를 포함하고 있습니다. 사용자 인터페이스 스레드는 완료되었는지 확인하기 위해 주기적으로 폴링할 수 있습니다. 작업이 완료되기 전에 EndGetTime을 호출하면 작업이 사실상 완료되기 전에 차단됩니다. 주 사용자 인터페이스 스레드에서 이 작업을 수행하지 않으면 웹 서비스 호출 결과가 있어야 진행할 수 있는 처리의 한 지점에 도달한 작업 스레드에서 호출을 감지합니다.

맨 위로


Visual Studio.NET에서 웹 서비스 지원

앞에서 본 웹 서비스 예제는 웹 서비스 작성이 프로그래밍 환경에 의존하지 않는다는 것을 보여주었습니다. 그러나 소프트웨어 개발에서 개발 시간이 가장 중요한 것이 아니기 때문에 진행을 빠르게 하는 도구를 사용하여 웹 서비스를 작성하는 것이 좋습니다. 메모장은 통합 디버거와 같은 유용한 기능이 부족하기 때문에 Visual Studio.NET은 웹 서비스를 작성하는 좋은 도구입니다. Visual Studio.NET의 2000년 7월 PDC 릴리스를 사용하여 서비스를 작성하는 방법을 보여 주겠습니다.

Visual Studio.NET 주 메뉴에서 File | New | Project를 선택하면 그림 16의 대화 상자가 나타납니다.

Figure 16 New Web Service
그림 16. 새 웹 서비스

왼쪽 창에서 Visual Basic Projects를 선택하고, 오른쪽 창에서 Web Service 아이콘을 선택하고, 편집 컨트롤에 프로젝트 이름을 입력한 다음 OK를 눌렀습니다. Visual Studio.NET은 그림 17에 표시된 파일이 들어 있는 새로운 솔루션이 생성했습니다. 어쨌든 "솔루션"은 하나 이상의 프로젝트를 보유하고 있으므로 프로젝트 그룹은 훨씬 설명하기 어려운 용어라고 생각됩니다.

Figure 17 Solution Explorer
그림 17. 솔루션 탐색기

흥미 있는 프로그래밍 작업은 WebService1.vb에서 수행합니다. 여기에는 웹 서비스를 실제로 구현하는 코드가 있습니다. 이 예제 웹 서비스에 대한 코드는 그림 18에 있습니다. 웹 서비스 환경의 흥미 있는 기능을 보여주기 위해 이 코드에 약간의 코드를 더 추가했습니다. 메모장보다 Visual Studio.NET에서 수행하기가 훨씬 쉬웠습니다. 다운로드한 예제를 보면 그림에는 Visual Basic.NET을 내부에서 사용하기 위해 많은 양의 관리 코드를 생략한 것을 알 수 있습니다. Visual J++® 6.0 사용자는 여기에 익숙할 것입니다. 코드에 있는 주석은 읽는 데 방해가 되기 때문에 최종판에서는 나타나지 않을 것입니다.

마법사는 그림 17에서 본 여러 가지 다른 파일을 생성합니다. 파일 Config.Web은 런타임에 웹 서비스를 처리하는 방법을 ASP.NET에 알리는 다양한 구성 옵션이 들어 있는 XML 데이터 파일입니다. 예를 들면, ASP.NET 세션 시간 초과 간격이 들어 있습니다.

.disco 파일은 SDL과 스키마를 함께 모아 클라이언트의 웹 서비스 동적 검색을 제어하기 위해 사용하는 XML 파일입니다. 다운로드한 코드에서 볼 수 있는 기본 구성에는 생성하는 SDL 파일에서 특정 하위 디렉터리(게시 과정에서 생성)를 제외하도록 ASP.NET에게 알리는 항목이 포함되어 있습니다.
.asmx 파일은 클라이언트 요청 대상입니다. 코드를 이 파일에서 사용했던 앞의 예제와 달리, 이 예제에는 다음과 같이 어디서나 사용되는?설명선이 포함되어 있습니다.

<%@ WebService Language="vb"
Codebehind="WebService1.vb"
Class="VS7DemoTimeService.WebService1" %>
Codebehind 특성은 서비스를 백업하는 코드를 찾는 장소를 알려줍니다.

globals.vb 파일에서 이벤트 처리기는 ApplicationStart와 ApplicationEnd 같은 프로젝트 범위의 이벤트를 처리합니다. 이 기능에 자신이 작성한 코드를 두면 ASP.NET은 지정된 이벤트가 발생할 때 호출합니다. globals.asax 파일은 이들 파일과 ASP.NET을 서로 연결합니다.

프로젝트를 구축할 때 Visual Studio.NET은 사용자가 지정한 웹 서버에 이를 자동으로 게시합니다(이 경우 시스템 기본값). 웹 서비스를 테스트하려면 Visual Studio.NET 주 메뉴에서 디버거를 테스트하면 됩니다. 작업을 순조롭게 처리하는 그림 4와 비슷한 테스트 페이지가 열립니다. 웹 서비스에 중단점을 설정하고 아무 것이나 디버깅할 수 있습니다. 테스트하면서 발견된 유일한 문제는 사용자 입력이 잘못된 경우 제대로 처리하지 못한다는 점입니다. 예를 들어, False를 잘못 입력하는 것처럼 사용자가 값을 잘못 입력하면 ASP.NET은 웹 서비스를 처리하기 전에 수신 요청을 거부하고 그림 19와 같은 오류를 표시합니다.

Figure 19 Error Report
그림 19. 오류 보고서

맨 위로


고유 개체

ASP 원본 버전에는 실행 중인 ASP 스크립트와 이를 실행하는 서버 간의 연결을 나타내는 고유 개체라고 하는 개체 집합이 포함되어 있습니다. 이 집합에는 Server, Application, Session, Request 및 Response 개체가 포함되어 있습니다. ASP 스크립트는 직접 액세스할 수 있습니다. ASP 스크립트가 사용하는 COM 개체는 여기에 도달하기 위해 몇 번의 절차를 이동해야 했지만 큰 문제 없이 사용할 수 있었습니다.

ASP.NET은 일반적으로 업데이트되고 향상된 유사한 개체를 포함하여, 이들 개체는 쉽게 사용할 수 있도록 재구성되었습니다. 고유 개체는 이제 System.Web.Services.WebService 기본 개체의 일부입니다. 해당 클래스에서 서비스를 추출하면 무조건 상속합니다.

Server, Application 및 Session 개체는 웹 서비스 클래스 부분입니다. 이들 개체는 조금씩 업데이트되고 향상되었습니다. 예를 들어, Server 개체는 이전에는 HtmlDecode였으며, 이제는 HtmlEncode 메서드를 갖습니다. 보안 인증을 수행할 때 사용할 User라고 하는 새로운 개체가 있습니다(보안 단원 참조). Request 및 Response 개체는 Context라는 새로운 고유 개체로 이동했습니다. 이 개체를 트랜잭션을 시작하고 취소하는 데 사용하는 ObjectContext와 혼동하지 마십시오. 용어가 너무 많은 것이 탈입니다. 일반적으로 이 기능(게시된 양식의 속성에 액세스)들은 웹 서비스 인프라와는 달리 너무 추상적이므로 자주 사용하지 않습니다. 다음 단원에서 이 중 몇 가지를 사용하는 방법에 대해 설명합니다.


맨 위로


상태 관리

많은 트리가 상태가 많거나 상태 구분이 없는 개체에 대해 계속되는 논쟁의 무의미한 희생물이 되었습니다. 여기에서 이 문제의 해결책을 제사할 의도는 없습니다. 웹 서비스에서 상태 관리에 사용할 수 있는 옵션을 보여줄 것입니다. 이를 사용자가 원하는 상태 동작을 구현하는 데 사용할 수 있습니다.

원래 상태의 웹 서비스 개체는 상태 구분이 없습니다. 즉, ASP.NET이 각 수신 호출에 대한 개체의 새 인스턴스를 구성하고 호출이 끝나면 삭제한다는 뜻입니다. 한 호출 결과는 빠져 나갔다가 다시 들어오지 않는 한 다음 호출에 사용할 수 없습니다.

이러한 것이 필요할 때도 있고 그렇지 않을 때도 있을 것입니다. 이 문서에서 설명하는 시간 서비스의 경우는 가능합니다. 클라이언트가 두 번째 자리 표시를 원하거나 원하지 않거나 다음 클라이언트에는 상관이 없습니다. 각 기능 호출은 그 자체로 충분합니다. 호출 상태를 유지할 이유는 없습니다. 데이터와 데이터에 사용하는 코드의 조합으로 개체를 보는 고전적인 의미에서는 개체가 없다고 주장할 수 있습니다. 클라이언트는 아무 관련이 없고 개체가 아닌 함수를 호출을 합니다. .NET 개체 서비스를 사용하기 때문에 이를 개체라고 하겠습니다.

이 동작을 원하지 않으면 개체는 호출 간의 상태를 유지할 수 있습니다. 개체는 원할 때 만들거나 삭제할 수 있지만 ASP.NET을 사용하면 하위 항목에 대해 적용했던 것처럼 이전에 사용했던 데이터를 유지할 수 있습니다. ASP.NET은 웹 서비스에서 응용 프로그램 상태와 세션 상태 등 두 상태를 유지할 수 있습니다. 응용 프로그램 상태는 인터넷 응용 프로그램 어디에나 즉, 솔루션에 내장된 해당 개체에서 모든 사용자와 모든 세션이 사용할 수 있습니다. 솔루션이 얼마나 설득력이 없습니까? 프로젝트 그룹으로 바꿔 보십시오. 더 나은가요? 그렇지 않나요? 후자는 개별 사용자가 현재 연결된 세션에만 사용할 수 있습니다. 세션은 대화 단위의 동작을 쉽게 프로그램할 수 있도록 ASP.NET이 관리하는 시간이 제한된 개념적인 연결입니다. 특정 사용자의 장바구니에 들어 있는 품목을 기억하는 것과 같은 세션 상태를 사용하므로 응용 프로그램 수준 상태보다 훨씬 많이 사용할 것입니다.

웹 서비스가 기반으로 하는 ASP.NET 시스템은 상태 변수를 관리하고 추적하는 방법을 제공합니다. 웹 서비스가 추출하는 기본 클래스 WebService에는 Application과 Session이라고 하는 상태를 가진 두 컬렉션이 포함되어 있습니다. 항목의 문자열 이름을 통해 액세스하면 이곳에 데이터를 저장하고 데이터를 꺼낼 수 있습니다. 그림 18의 예제 서비스는 두 종류의 상태를 사용하는 코드를 포함합니다. Application에 요청 수를 보관하고 Session 수준 상태에 특정 사용자에 대한 요청 수를 보관합니다.

맨 위로


웹 서비스 보안

보안은 배포된 모든 프로그래밍 종류에 필수적이며, 그 설명은 종종 감정에 좌우됩니다. 이 영역에 발생하는 문제를 설명하고 ASP.NET이 큰 문제 없이 사용자가 필요한 보안 수준을 가능하게 하는 미리 작성된 기능을 웹 서비스에 어떻게 제공하는지 설명합니다. 그러나 보안에 대해 완벽하게 알려면 2~3 기사에 걸쳐 다루어야 합니다.

모든 웹 서비스는 여러분이 인식하건 하지 못하건 보안을 고려합니다. 저는 타이머를 누가 보든지 상관하지 않기 때문에 이 예제 시간 서비스에는 보안을 고려하지 않았습니다. 누군가 코드를 삭제하거나 해킹하여 현재 시간에서 10분을 늦춰 모든 호출자의 약속을 늦게 만드는 것을 원하지 않습니다. 따라서 사용자의 사용 권한을 읽고 선택된 사용자에게만 쓰기 권한을 부여하려 합니다. IIS는 이런 기본적인 수준의 보안을 제공합니다.

웹 서비스의 보안 요구 사항은 시청의 보안 요구 사항과 유사합니다. 많은 사람들이 시청을 오고 가면서 지도를 나눠주는 안내소와 같은 장소를 방문할 수 있습니다. 그러나 시청 내에서도 시장 집무실이 있는 층과 같이 다른 곳은 신원을 증명(인증)하지 못하고 해당 층에 용무가 없는 사람(권한)은 출입할 수 없습니다.

보안 상 첫 번째 문제는 사용자가 누구이며 어떻게 확인하는가 하는 인증입니다. 이 사람이 누구인지 확인될 때까지 일부 리소스에 대한 액세스를 허용할 것인지 알 수 없습니다. ASP.NET은 기본 IIS 층에서 인증 서비스를 받습니다. 기존의 IIS 도구를 사용하여 그림 20에 나타난 대로 Anonymous access 상자의 확인 표시를 지워 특정 페이지를 인증이 필요한 것으로 표시할 수 있습니다. 그러면 IIS는 지정된 페이지를 표시하기 전에 사용자 ID/암호를 요구합니다. 이렇게 하려면 사용자가 서버에 액세스할 수 있는 계정이 있어야 합니다. 인증에 성공하면 ASP.NET 스크립트는 인증된 사용자의 ID를 사용하여 실행됩니다.

Figure 20 Authentication Methods
그림 20. 인증 방법

앞에 나타난 .NET 프록시 기반의 클라이언트 응용 프로그램을 작성하면 프록시 기본 클래스에는 Username, Password, Domain이라는 등록 정보가 포함됩니다. 두 문자열에 이 등록 정보를 설정하면 클라이언트는 이들을 요청하는 서버에 쉽게 전달할 수 있습니다.

명백히 인증은 추가 네트워크 트래픽을 요청하므로 필요할 때만 사용해야 합니다. 지도를 얻는 데 ID와 몸 수색을 요구한다면 시청 여행자 사무소를 많이 사용하지 않을 것입니다. 이 예제는 페이지를 읽는 데는 인증을 요구하지 않고 쓰는 데만 인증을 요구합니다. 이 경우, 관리자는 Anonymous access 상자에 확인 표시하고, 익명의 클라이언트는 서버에 대한 액세스 확인에 사용할 계정 ID를 지정합니다. 일반적으로 이 계정은 낮은 권한 수준을 갖습니다.

사용자가 누구인지 결정한 후에는 민감한 작업을 수행하기 전에 이 사람의 작업 허용 여부를 확인해야 합니다. 때때로 이 작업은 백 엔드 운영 체제에 의해 처리됩니다. 예를 들어, NTFS에서는 관리자가 파일에 대한 액세스 권한을 설정할 수 있으며 관리자는 익명의 사용자가 시스템 구성 파일에 액세스를 허용하지 않기를 희망합니다. Microsoft SQL Server™와 같은 다른 프로그램은 비슷한 작업을 수행합니다.

실패할 경우 최소한의 처리 시간을 소비하게 되므로 가능하면 액세스 과정 초반부에 인증을 확인하는 것이 가장 좋습니다. 웹 서비스 개체는 User라고 하는 고유 개체를 통해 자신의 인증을 수행할 수 있습니다. 여기에는 사용자가 설정한 관리 그룹의 구성원인지 알려주는 IsCallerInRole이라는 메서드가 포함되어 있습니다. COM+에서 본 유사한 메서드와 개념적으로 동일합니다. 자세한 내용을 알고 싶으면 User 개체의 Identity 속성을 사용하십시오. 이 속성은 사용자 이름과, 해당 사용자 이름을 확인하는 데 사용하는 인증 메커니즘을 알리는 IIdentity 인터페이스를 반환합니다. 사용자가 어떤 작업을 수행하는 것이 허용되었는지 결정하기 위해 해당 정보를 사용하는 코드를 직접 작성할 수 있습니다.

향후 웹 서비스는 많은 사람들이 쉽게 사용할 수 있는 Passport 인증과 쿠키 기반 인증을 지원할 것입니다. 이 내용은 이 문서에서는 다루지 않습니다.

맨 위로


결론

모든 프로그래머는 실행되는 시스템 종류에 관계 없이 인터넷을 통해 서로 통신하는 프로그램을 작성하고 싶어 합니다. 가장 보편적인 XML과 HTTP를 설정하여 이 작업을 수행할 수 있습니다. Microsoft .NET 기술의 웹 서비스 부분은 .NET 구성 요소의 양식으로 비즈니스 논리를 쉽게 작성하고 HTTP GET, HTTP POST 또는 SOAP를 사용하는 모든 웹 클라이언트에 이들을 나타낼 수 있도록 합니다. 웹 서비스 인프라에 의해 생성되는 SDL 파일은 웹 서비스를 통해 사용할 수 있는 기능에 대해 시스템이 읽을 수 있는 설명을 제공합니다. 프록시 생성기는 웹 서비스에 대한 기능 기반 액세스를 제공하여 클라이언트 프로그램을 쉽게 개발하도록 합니다. Visual Studio.NET은 웹 서비스 개발을 위한 생산적인 환경을 제공합니다. 웹 서비스 인프라는 웹 응용 프로그램이 요구하는 보안을 설정할 수 있는 여러 가지 옵션을 제공합니다. 이 도구를 사용하면 훨씬 빠르게 보다 나은 인터넷 응용 프로그램을 작성할 수 있습니다.


David S. Platt은 Rolling Thunder Computing Inc의 사장이며 설립자입니다. 그는 하버드 대학과 전세계 기업에서 COM과 COM+를 가르치며 COM+에 대한 무료 전자 메일 소식지를 http://www.rollthunder.com/에 게시하고 있습니다. David는 Understanding COM+(Microsoft Press)의 저자이며 2001년 봄 Microsoft .NET 플랫폼을 소개하는 서적(Microsoft Press)을 출간할 예정입니다.

? 최종수정일: 2001년 2월 19일

Top of Page Top of Page


Microsoft