WCF(Windows Communication Foundation) 웹 서비스 사용
WCF는 서비스 지향 애플리케이션을 빌드하기 위한 Microsoft의 통합 프레임워크입니다. 이를 통해 개발자는 안전하고 안정적이며 거래되고 상호 운용 가능한 분산 애플리케이션을 빌드할 수 있습니다. 이 문서에서는 애플리케이션에서 Xamarin.Forms WCF SOAP(Simple Object Access Protocol) 서비스를 사용하는 방법을 보여 줍니다.
WCF는 다음을 비롯한 다양한 계약을 포함하는 서비스를 설명합니다.
- 데이터 계약 – 메시지 내의 콘텐츠에 대한 기초를 형성하는 데이터 구조를 정의합니다.
- 메시지 계약 – 기존 데이터 계약의 메시지를 작성합니다.
- 오류 계약 – 사용자 지정 SOAP 오류를 지정할 수 있습니다.
- 서비스 계약 – 서비스에서 지원하는 작업 및 각 작업과 상호 작용하는 데 필요한 메시지를 지정합니다. 또한 각 서비스의 작업과 연결할 수 있는 사용자 지정 오류 동작도 지정합니다.
ASMX(ASP.NET Web Services)와 WCF 간에는 차이가 있지만 WCF는 ASMX가 제공하는 것과 동일한 기능인 HTTP를 통한 SOAP 메시지를 지원합니다. ASMX 서비스 사용에 대한 자세한 내용은 ASMX(ASP.NET 웹 서비스 사용)를 참조하세요.
Important
WCF에 대한 Xamarin 플랫폼 지원은 클래스를 사용하여 BasicHttpBinding
HTTP/HTTPS를 통해 텍스트로 인코딩된 SOAP 메시지로 제한됩니다.
WCF 지원을 사용하려면 Windows 환경에서만 사용할 수 있는 도구를 사용하여 프록시를 생성하고 TodoWCFService를 호스트해야 합니다. iOS 앱을 빌드하고 테스트하려면 Windows 컴퓨터 또는 Azure 웹 서비스로 TodoWCFService를 배포해야 합니다.
Xamarin Forms 네이티브 앱은 일반적으로 .NET Standard 클래스 라이브러리와 코드를 공유합니다. 그러나 .NET Core는 현재 WCF를 지원하지 않으므로 공유 프로젝트는 레거시 이식 가능한 클래스 라이브러리여야 합니다. .NET Core의 WCF 지원에 대한 자세한 내용은 서버 앱에 대한 .NET Core와 .NET Framework 중에서 선택 항목을 참조 하세요.
샘플 애플리케이션 솔루션에는 로컬로 실행할 수 있는 WCF 서비스가 포함되어 있으며 다음 스크린샷에 표시됩니다.
참고 항목
iOS 9 이상에서 ATS(App Transport Security)는 인터넷 리소스(예: 앱의 백 엔드 서버)와 앱 간에 보안 연결을 적용하여 중요한 정보의 우발적인 공개를 방지합니다. ATS는 iOS 9용으로 빌드된 앱에서 기본적으로 사용하도록 설정되므로 모든 연결에는 ATS 보안 요구 사항이 적용됩니다. 연결이 이러한 요구 사항을 충족하지 않으면 예외로 실패합니다.
인터넷 리소스에 대한 프로토콜 및 보안 통신을 사용할 HTTPS
수 없는 경우 ATS를 옵트아웃할 수 있습니다. 이 작업은 앱의 Info.plist 파일을 업데이트하여 수행할 수 있습니다. 자세한 내용은 App Transport Security를 참조 하세요.
웹 서비스 사용
WCF 서비스는 다음 작업을 제공합니다.
연산 | 설명 | 매개 변수 |
---|---|---|
GetTodoItems | 할 일 항목의 목록 가져오기 | |
CreateTodoItem | 새 할 일 항목 만들기 | 직렬화된 XML TodoItem |
EditTodoItem | 할 일 항목 업데이트 | 직렬화된 XML TodoItem |
DeleteTodoItem | 할 일 항목 삭제 | 직렬화된 XML TodoItem |
애플리케이션에서 사용되는 데이터 모델에 대한 자세한 내용은 데이터 모델링을 참조하세요.
애플리케이션이 서비스에 연결할 수 있도록 하는 WCF 서비스를 사용하려면 프록시를 생성해야 합니다. 프록시는 메서드 및 연결된 서비스 구성을 정의하는 서비스 메타데이터를 사용하여 생성됩니다. 이 메타데이터는 웹 서비스에서 생성되는 WSDL(웹 서비스 설명 언어) 문서의 형태로 노출됩니다. Visual Studio 2017에서 Microsoft WCF 웹 서비스 참조 공급자를 사용하여 .NET Standard 라이브러리에 웹 서비스에 대한 서비스 참조를 추가하여 프록시를 빌드할 수 있습니다. Visual Studio 2017에서 Microsoft WCF 웹 서비스 참조 공급자를 사용하여 프록시를 만드는 대신 ServiceModel 메타데이터 유틸리티 도구(svcutil.exe)를 사용하는 것이 좋습니다. 자세한 내용은 ServiceModel 메타데이터 유틸리티 도구(Svcutil.exe)를 참조하세요.
생성된 프록시 클래스는 APM(비동기 프로그래밍 모델) 디자인 패턴을 사용하는 웹 서비스를 사용하는 메서드를 제공합니다. 이 패턴에서 비동기 작업은 비동기 작업을 시작하고 종료하는 BeginOperationName 및 EndOperationName이라는 두 가지 메서드로 구현됩니다.
BeginOperationName 메서드는 비동기 작업을 시작하고 인터페이스를 구현하는 개체를 IAsyncResult
반환합니다. BeginOperationName을 호출한 후 애플리케이션은 스레드 풀 스레드에서 비동기 작업이 수행되는 동안 호출 스레드에 대한 명령을 계속 실행할 수 있습니다.
BeginOperationName에 대한 각 호출에 대해 애플리케이션은 EndOperationName을 호출하여 작업 결과를 가져와야 합니다. EndOperationName의 반환 값은 동기 웹 서비스 메서드에서 반환하는 형식과 동일합니다. 예를 들어 메서드는 EndGetTodoItems
인스턴스 컬렉션을 TodoItem
반환합니다. EndOperationName 메서드에는 BeginOperationName 메서드에 대한 해당 호출에서 반환되는 인스턴스로 설정해야 하는 매개 변수도 포함되어 IAsyncResult
있습니다.
TPL(작업 병렬 라이브러리)은 동일한 Task
개체에서 비동기 작업을 캡슐화하여 APM 시작/끝 메서드 쌍을 사용하는 프로세스를 간소화할 수 있습니다. 이 캡슐화는 메서드의 TaskFactory.FromAsync
여러 오버로드에서 제공됩니다.
APM 에 대한 자세한 내용은 MSDN의 비동기 프로그래밍 모델 및 TPL 및 기존 .NET Framework 비동기 프로그래밍을 참조하세요.
TodoServiceClient 개체 만들기
생성된 프록시 클래스는 HTTP를 TodoServiceClient
통해 WCF 서비스와 통신하는 데 사용되는 클래스를 제공합니다. URI 식별 서비스 인스턴스에서 비동기 작업으로 웹 서비스 메서드를 호출하는 기능을 제공합니다. 비동기 작업에 대한 자세한 내용은 비동기 지원 개요를 참조 하세요.
인스턴스는 TodoServiceClient
다음 코드 예제와 같이 애플리케이션이 WCF 서비스를 사용하는 데 필요한 한 개체가 유지되도록 클래스 수준에서 선언됩니다.
public class SoapService : ISoapService
{
ITodoService todoService;
...
public SoapService ()
{
todoService = new TodoServiceClient (
new BasicHttpBinding (),
new EndpointAddress (Constants.SoapUrl));
}
...
}
인스턴스는 TodoServiceClient
바인딩 정보 및 엔드포인트 주소로 구성됩니다. 바인딩은 애플리케이션 및 서비스가 서로 통신하는 데 필요한 전송, 인코딩 및 프로토콜 세부 정보를 지정하는 데 사용됩니다. 텍스트 BasicHttpBinding
로 인코딩된 SOAP 메시지가 HTTP 전송 프로토콜을 통해 전송되도록 지정합니다. 엔드포인트 주소를 지정하면 게시된 인스턴스가 여러 개인 경우 애플리케이션이 WCF 서비스의 다른 인스턴스에 연결할 수 있습니다.
서비스 참조를 구성하는 방법에 대한 자세한 내용은 서비스 참조 구성을 참조하세요.
데이터 전송 개체 만들기
샘플 애플리케이션은 클래스를 TodoItem
사용하여 데이터를 모델링합니다. 웹 서비스에 항목을 저장 TodoItem
하려면 먼저 프록시 생성 TodoItem
형식으로 변환해야 합니다. 이 작업은 다음 코드 예제와 같이 메서드에 의해 ToWCFServiceTodoItem
수행됩니다.
TodoWCFService.TodoItem ToWCFServiceTodoItem (TodoItem item)
{
return new TodoWCFService.TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
이 메서드는 단순히 새 TodoWCFService.TodoItem
인스턴스를 만들고 인스턴스에서 TodoItem
동일한 속성으로 각 속성을 설정합니다.
마찬가지로 웹 서비스에서 데이터를 검색할 때 프록시 생성 TodoItem
형식에서 인스턴스로 TodoItem
변환해야 합니다. 이 작업은 다음 코드 예제와 같이 메서드를 사용하여 수행 FromWCFServiceTodoItem
됩니다.
static TodoItem FromWCFServiceTodoItem (TodoWCFService.TodoItem item)
{
return new TodoItem
{
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
이 메서드는 프록시 생성 TodoItem
형식에서 데이터를 검색하고 새로 만든 TodoItem
인스턴스에서 설정합니다.
데이터 검색
및 메서드는 TodoServiceClient.BeginGetTodoItems
웹 서비스에서 제공하는 작업을 호출 GetTodoItems
하는 데 TodoServiceClient.EndGetTodoItems
사용됩니다. 이러한 비동기 메서드는 다음 코드 예제와 Task
같이 개체에 캡슐화됩니다.
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
foreach (var item in todoItems)
{
Items.Add (FromWCFServiceTodoItem (item));
}
...
}
메서드가 Task.Factory.FromAsync
완료되면 메서드를 실행하는 TodoServiceClient.EndGetTodoItems
메서드 TodoServiceClient.BeginGetTodoItems
를 만듭니 Task
다. null
매개 변수는 대리자로 데이터가 전달되지 않음을 BeginGetTodoItems
나타냅니다. 마지막으로 열거형 값 TaskCreationOptions
은 태스크 만들기 및 실행에 대한 기본 동작을 사용해야 하므로 지정합니다.
메서드는 TodoServiceClient.EndGetTodoItems
인스턴스를 ObservableCollection
TodoWCFService.TodoItem
반환한 다음 표시할 List
인스턴스로 TodoItem
변환됩니다.
데이터 만들기
및 메서드는 TodoServiceClient.BeginCreateTodoItem
웹 서비스에서 제공하는 작업을 호출 CreateTodoItem
하는 데 TodoServiceClient.EndCreateTodoItem
사용됩니다. 이러한 비동기 메서드는 다음 코드 예제와 Task
같이 개체에 캡슐화됩니다.
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginCreateTodoItem,
todoService.EndCreateTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
메서드는 Task.Factory.FromAsync
메서드가 완료되면 메서드 TodoServiceClient.BeginCreateTodoItem
를 실행하는 TodoServiceClient.EndCreateTodoItem
메서드를 만들고Task
, todoItem
매개 변수는 웹 서비스에서 만들 데이터를 지정 TodoItem
하기 위해 대리자로 BeginCreateTodoItem
전달되는 데이터입니다. 마지막으로 열거형 값 TaskCreationOptions
은 태스크 만들기 및 실행에 대한 기본 동작을 사용해야 하므로 지정합니다.
웹 서비스는 애플리케이션에서 FaultException
처리하는 웹 서비스를 만들지 TodoItem
못한 경우 throw합니다.
데이터 업데이트
및 메서드는 TodoServiceClient.BeginEditTodoItem
웹 서비스에서 제공하는 작업을 호출 EditTodoItem
하는 데 TodoServiceClient.EndEditTodoItem
사용됩니다. 이러한 비동기 메서드는 다음 코드 예제와 Task
같이 개체에 캡슐화됩니다.
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
var todoItem = ToWCFServiceTodoItem (item);
...
await Task.Factory.FromAsync (
todoService.BeginEditTodoItem,
todoService.EndEditTodoItem,
todoItem,
TaskCreationOptions.None);
...
}
메서드가 Task.Factory.FromAsync
완료되면 메서드를 실행하는 TodoServiceClient.EndEditTodoItem
메서드 TodoServiceClient.BeginCreateTodoItem
를 만듭니다Task
. todoItem
매개 변수는 웹 서비스에서 업데이트할 대상을 지정 TodoItem
하기 위해 대리자로 BeginEditTodoItem
전달되는 데이터입니다. 마지막으로 열거형 값 TaskCreationOptions
은 태스크 만들기 및 실행에 대한 기본 동작을 사용해야 하므로 지정합니다.
웹 서비스는 애플리케이션에서 FaultException
처리하는 을 찾거나 업데이트 TodoItem
하지 못하는 경우 throw합니다.
데이터 삭제
및 메서드는 TodoServiceClient.BeginDeleteTodoItem
웹 서비스에서 제공하는 작업을 호출 DeleteTodoItem
하는 데 TodoServiceClient.EndDeleteTodoItem
사용됩니다. 이러한 비동기 메서드는 다음 코드 예제와 Task
같이 개체에 캡슐화됩니다.
public async Task DeleteTodoItemAsync (string id)
{
...
await Task.Factory.FromAsync (
todoService.BeginDeleteTodoItem,
todoService.EndDeleteTodoItem,
id,
TaskCreationOptions.None);
...
}
메서드가 Task.Factory.FromAsync
완료되면 메서드 TodoServiceClient.BeginDeleteTodoItem
를 TodoServiceClient.EndDeleteTodoItem
실행하는 메서드를 만듭니다Task
. id
매개 변수는 웹 서비스에서 삭제할 데이터를 지정 TodoItem
하기 위해 대리자로 BeginDeleteTodoItem
전달되는 데이터입니다. 마지막으로 열거형 값 TaskCreationOptions
은 태스크 만들기 및 실행에 대한 기본 동작을 사용해야 하므로 지정합니다.
웹 서비스는 애플리케이션에서 FaultException
처리하는 위치를 찾거나 삭제 TodoItem
하지 못하는 경우 throw합니다.
IIS Express에 대한 원격 액세스 구성
Visual Studio 2017 또는 Visual Studio 2019에서는 추가 구성 없이 PC에서 UWP 애플리케이션을 테스트할 수 있어야 합니다. Android 및 iOS 클라이언트를 테스트하려면 이 섹션의 추가 단계가 필요할 수 있습니다. 자세한 내용은 iOS 시뮬레이터 및 Android 에뮬레이터에서 로컬 웹 서비스에 대한 커넥트 참조하세요.
기본적으로 IIS Express는 .에 대한 요청에만 응답합니다 localhost
. 원격 디바이스(예: Android 디바이스, i전화 또는 시뮬레이터)는 로컬 WCF 서비스에 액세스할 수 없습니다. 로컬 네트워크에서 Windows 10 워크스테이션 IP 주소를 알아야 합니다. 이 예제에서는 워크스테이션에 IP 주소 192.168.1.143
가 있다고 가정합니다. 다음 단계에서는 원격 연결을 허용하고 물리적 또는 가상 디바이스에서 서비스에 연결하도록 Windows 10 및 IIS Express를 구성하는 방법을 설명합니다.
Windows 방화벽에 예외를 추가합니다. 서브넷의 애플리케이션이 WCF 서비스와 통신하는 데 사용할 수 있는 Windows 방화벽을 통해 포트를 열어야 합니다. 방화벽에서 포트 49393을 여는 인바운드 규칙을 만듭니다. 관리 명령 프롬프트에서 다음 명령을 실행합니다.
netsh advfirewall firewall add rule name="TodoWCFService" dir=in protocol=tcp localport=49393 profile=private remoteip=localsubnet action=allow
원격 연결을 허용하도록 IIS Express를 구성합니다. [솔루션 디렉터리].vs\config\applicationhost.config에서 IIS Express에 대한 구성 파일을 편집하여 IIS Express를 구성할 수 있습니다. 이름을
TodoWCFService
가진site
요소를 찾습니다. 다음 XML과 유사하게 표시됩니다.<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> </bindings> </site>
외부 트래픽 및 Android 에뮬레이터에 포트 49393을 열려면 두
binding
요소를 추가해야 합니다. 바인딩은 IIS Express가 요청에 응답하는 방법을 지정하는 형식을 사용합니다[IP address]:[port]:[hostname]
. 외부 요청에는 .로binding
지정해야 하는 호스트 이름이 있습니다. 요소에 다음 XML을bindings
추가하여 IP 주소를 사용자 고유의 IP 주소로 바꿉니다.<binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" />
변경 후
bindings
요소는 다음과 같이 표시됩니다.<site name="TodoWCFService" id="2"> <application path="/" applicationPool="Clr4IntegratedAppPool"> <virtualDirectory path="/" physicalPath="C:\Users\tom\TodoWCF\TodoWCFService\TodoWCFService" /> </application> <bindings> <binding protocol="http" bindingInformation="*:49393:localhost" /> <binding protocol="http" bindingInformation="*:49393:192.168.1.143" /> <binding protocol="http" bindingInformation="*:49393:127.0.0.1" /> </bindings> </site>
Important
기본적으로 IIS Express는 보안상의 이유로 외부 원본의 연결을 허용하지 않습니다. 원격 디바이스에서 연결을 사용하도록 설정하려면 관리 사용 권한으로 IIS Express를 실행해야 합니다. 이 작업을 수행하는 가장 쉬운 방법은 관리 권한을 사용하여 Visual Studio 2017을 실행하는 것입니다. 그러면 TodoWCFService를 실행할 때 관리시제 권한으로 IIS Express가 시작됩니다.
이러한 단계가 완료되면 TodoWCFService를 실행하고 서브넷의 다른 디바이스에서 연결할 수 있어야 합니다. 애플리케이션을 실행하고 방문하여 테스트할 수 있습니다
http://localhost:49393/TodoService.svc
. 해당 URLbindings
을 방문할 때 잘못된 요청 오류가 발생하는 경우 IIS Express 구성에서 잘못된 것일 수 있습니다(요청이 IIS Express에 도달하지만 거부됨). 다른 오류가 발생하면 애플리케이션이 실행되고 있지 않거나 방화벽이 잘못 구성되었을 수 있습니다.IIS Express가 서비스를 계속 실행하고 서비스할 수 있도록 하려면 프로젝트 속성 > 웹 > 디버거에서 편집 및 계속 옵션을 끕니다.
서비스에 액세스하는 데 사용하는 엔드포인트 디바이스를 사용자 지정합니다. 이 단계에서는 물리적 또는 에뮬레이트된 디바이스에서 실행되는 클라이언트 애플리케이션을 구성하여 WCF 서비스에 액세스합니다.
Android 에뮬레이터는 에뮬레이터가 호스트 컴퓨터의
localhost
주소에 직접 액세스하지 못하도록 하는 내부 프록시를 활용합니다. 대신 에뮬레이터의 주소10.0.2.2
는 내부 프록시를localhost
통해 호스트 컴퓨터로 라우팅됩니다. 이러한 프록시된 요청은 요청 헤더에 호스트 이름으로 포함되므로127.0.0.1
위의 단계에서 이 호스트 이름에 대한 IIS Express 바인딩을 만들었습니다.Windows용 원격 iOS 시뮬레이터를 사용하는 경우에도 iOS 시뮬레이터는 Mac 빌드 호스트에서 실행됩니다. 시뮬레이터의 네트워크 요청에는 로컬 네트워크의 워크스테이션 IP가 호스트 이름으로 포함됩니다(이 예제
192.168.1.143
에서는 그렇지만 실제 IP 주소는 다를 수 있습니다). 이 때문에 위의 단계에서 이 호스트 이름에 대한 IIS Express 바인딩을 만들었습니다.SoapUrl
TodoWCF(이식 가능) 프로젝트의 Constants.cs 파일에 있는 속성에 네트워크에 올바른 값이 있는지 확인합니다.public static string SoapUrl { get { var defaultUrl = "http://localhost:49393/TodoService.svc"; if (Device.RuntimePlatform == Device.Android) { defaultUrl = "http://10.0.2.2:49393/TodoService.svc"; } else if (Device.RuntimePlatform == Device.iOS) { defaultUrl = "http://192.168.1.143:49393/TodoService.svc"; } return defaultUrl; } }
적절한 엔드포인트를 사용하여 Constants.cs 구성한 후에는 실제 또는 가상 디바이스에서 Windows 10 워크스테이션에서 실행되는 TodoWCFService에 연결할 수 있어야 합니다.