REST API를 사용하는 애플리케이션은 매우 일반적인 시나리오입니다. 일반적으로 애플리케이션에서 REST API를 호출하는 데 사용할 수 있는 클라이언트 코드를 생성해야 합니다. 이 자습서에서는 MSBuild를 사용하여 빌드 프로세스 중에 REST API 클라이언트를 자동으로 생성하는 방법을 알아봅니다. REST API에 대한 클라이언트 코드를 생성하는 도구인 NSwag사용합니다.
전체 샘플 코드는 GitHub의 .NET 샘플 리포지토리에서 REST API 클라이언트 생성 사용할 수 있습니다.
이 예제는 공용 Pet Store API를 사용하는 콘솔 앱을 보여 줍니다. 이 API는 OpenAPI 사양을 게시합니다.
이 자습서에서는 작업, 대상, 속성 또는 런타임과 같은 MSBuild 용어에 대한 기본 지식을 가정합니다. 필요한 배경은 msBuild 개념 문서 참조하세요.
빌드의 일부로 명령줄 도구를 실행하려는 경우 고려해야 할 두 가지 방법이 있습니다. 하나는 명령줄 도구를 실행하고 해당 매개 변수를 지정할 수 있는 MSBuild Exec 작업사용하는 것입니다. 다른 방법은 ToolTask에서 파생된 사용자 지정 작업을 만드는 것입니다. 이를 통해 더 큰 제어 권한을 가질 수 있습니다.
필수 구성 요소
작업, 대상 및 속성과 같은 MSBuild 개념을 이해해야 합니다. MSBuild 개념 참조하세요.
이 예제에는 Visual Studio와 함께 설치되지만 별도로 설치할 수도 있는 MSBuild가 필요합니다. Visual Studio 없이 MSBuild 다운로드참조하세요.
옵션 1: 실행 작업
MSBuild에서 NSwag 코드 생성을 사용할 수 있습니다. NSwag.MSBuild 참조하세요.
전체 코드는 PetReaderExecTaskExample 폴더에 있습니다. 다운로드하고 살펴볼 수 있습니다. 이 자습서에서는 단계별로 진행하면서 그 방법에 대한 개념을 알아봅니다.
PetReaderExecTaskExample라는 새 콘솔 애플리케이션을 만듭니다. .NET 6.0 이상을 사용합니다.동일한 솔루션인
PetShopRestClient다른 프로젝트를 만듭니다(이 솔루션은 생성된 클라이언트를 라이브러리로 포함할 예정). 이 프로젝트의 경우 .NET Standard 2.1을 사용합니다. 생성된 클라이언트는 .NET Standard 2.0에서 컴파일되지 않습니다.PetReaderExecTaskExample프로젝트에서 프로젝트 종속성을PetShopRestClient프로젝트에 추가합니다.PetShopRestClient프로젝트에 다음 NuGet 패키지를 포함합니다.- MSBuild에서 코드 생성기에 액세스할 수 있는 Nswag.MSBuild
- 생성된 클라이언트를 컴파일하는 데 필요한 Newtonsoft.Json
- 생성된 클라이언트를 컴파일하는 데 필요한 System.ComponentModel.Annotations
PetShopRestClient프로젝트에서 코드 생성을 위한 폴더(PetShopRestClient)를 추가하고 자동으로 생성된 Class1.cs 삭제합니다.프로젝트의 루트에 petshop-openapi-spec.json 텍스트 파일을 만듭니다. 여기 OpenAPI 사양을 복사하여 파일에 저장합니다. 빌드 중에 온라인으로 읽는 대신 사양의 스냅샷을 복사하는 것이 가장 좋습니다. 항상 입력에만 의존하는 일관되게 재현 가능한 빌드를 원합니다. API를 직접 사용하면 오늘 작동하는 빌드를 동일한 원본에서 내일 실패하는 빌드로 변환할 수 있습니다. petshop-openapi-spec.json 저장된 스냅샷을 사용하면 사양이 변경되더라도 빌드되는 버전을 계속 가질 수 있습니다.
다음으로, PetShopRestClient.csproj를 수정하고 빌드 프로세스 중에 클라이언트를 생성하기 위해 MSBuild 대상을 추가합니다.
먼저 클라이언트 생성에 유용한 몇 가지 속성을 추가합니다.
<PropertyGroup> <PetOpenApiSpecLocation>petshop-openapi-spec.json</PetOpenApiSpecLocation> <PetClientClassName>PetShopRestClient</PetClientClassName> <PetClientNamespace>PetShopRestClient</PetClientNamespace> <PetClientOutputDirectory>PetShopRestClient</PetClientOutputDirectory> </PropertyGroup>다음 대상을 추가합니다.
<Target Name="generatePetClient" BeforeTargets="CoreCompile" Inputs="$(PetOpenApiSpecLocation)" Outputs="$(PetClientOutputDirectory)\$(PetClientClassName).cs"> <Exec Command="$(NSwagExe) openapi2csclient /input:$(PetOpenApiSpecLocation) /classname:$(PetClientClassName) /namespace:$(PetClientNamespace) /output:$(PetClientOutputDirectory)\$(PetClientClassName).cs" ConsoleToMSBuild="true"> <Output TaskParameter="ConsoleOutput" PropertyName="OutputOfExec" /> </Exec> </Target> <Target Name="forceReGenerationOnRebuild" AfterTargets="CoreClean"> <Delete Files="$(PetClientOutputDirectory)\$(PetClientClassName).cs"></Delete> </Target>이 대상은 빌드 순서를 정의하는 방법으로 BeforeTarget 및 AfterTarget 특성을 사용합니다.
generatePetClient호출된 첫 번째 대상은 핵심 컴파일 대상 전에 실행되므로 컴파일러가 실행되기 전에 원본이 만들어집니다. 입력 및 출력 매개 변수는 증분 빌드관련이 있습니다. MSBuild는 입력 파일의 타임스탬프를 출력 파일의 타임스탬프와 비교하고 대상을 건너뛰거나 빌드하거나 부분적으로 다시 작성할지 여부를 결정할 수 있습니다.프로젝트에
NSwag.MSBuildNuGet 패키지를 설치한 후$(NSwagExe)파일의 변수.csproj사용하여 MSBuild 대상에서 NSwag 명령줄 도구를 실행할 수 있습니다. 이렇게 하면 NuGet을 통해 도구를 쉽게 업데이트할 수 있습니다. 여기서는ExecMSBuild 작업을 사용하여 클라이언트 Rest Api를 생성하는 데 필요한 매개 변수를 사용하여 NSwag 프로그램을 실행합니다. NSwag 명령 및 매개 변수참조하세요.<Exec>출력을 캡처하려면, 먼저ConsoleToMsBuild="true"태그에<Exec>을 추가하고, 그 다음에는ConsoleOutput태그의<Output>매개 변수를 사용하여 출력을 캡처할 수 있습니다.ConsoleOutput이 출력을Item로 반환합니다. 공백이 제거됩니다.ConsoleOutputtrue이면ConsoleToMSBuild활성화됩니다.forceReGenerationOnRebuild라는 두 번째 대상은 정리 중에 생성된 클래스를 삭제하여 대상을 다시 빌드하는 동안 생성된 코드를 강제로 다시 생성합니다. 이 대상은CoreCleanMSBuild 미리 정의된 대상 이후에 실행됩니다.Visual Studio Solution 다시 빌드를 실행하고
PetShopRestClient폴더에 생성된 클라이언트를 확인합니다.이제 생성된 클라이언트를 사용합니다. 클라이언트 Program.cs이동하여 다음 코드를 복사합니다.
using System; using System.Net.Http; namespace PetReaderExecTaskExample { internal class Program { private const string baseUrl = "https://petstore.swagger.io/v2"; static void Main(string[] args) { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseUrl); var petClient = new PetShopRestClient.PetShopRestClient(httpClient); var pet = petClient.GetPetByIdAsync(1).Result; Console.WriteLine($"Id: {pet.Id} Name: {pet.Name} Status: {pet.Status} CategoryName: {pet.Category.Name}"); } } }메모
이 코드는 간단하게 보여 주지만 실제 코드에는 모범 사례가 아니기 때문에
new HttpClient()사용합니다. 가장 좋은 방법은HttpClientFactory사용하여 리소스 소모 또는 부실 DNS 문제와 같은HttpClient요청의 알려진 문제를 해결하는HttpClient개체를 만드는 것입니다. 참조하세요. IHttpClientFactory를 사용하여복원력 있는 HTTP 요청을 구현합니다.
축하합니다! 이제 프로그램을 실행하여 작동 방식을 확인할 수 있습니다.
옵션 2: ToolTask에서 파생된 사용자 지정 작업
대부분의 경우 Exec 작업을 사용하면 외부 도구를 실행하여 REST API 클라이언트 코드 생성과 같은 작업을 수행하는 데 충분하지만 절대 Windows 경로를 입력으로 사용하지 않는 경우에만 REST API 클라이언트 코드 생성을 허용하려면 어떻게 해야 할까요? 또는 실행 파일이 있는 위치에서 어떤 방식으로 계산해야 하는 경우 어떻게 해야 할까요? 추가 작업을 수행하기 위해 일부 코드를 실행해야 하는 상황이 있는 경우 MSBuild 도구 태스크 가장 적합한 솔루션입니다.
ToolTask 클래스는 MSBuild Task파생된 추상 클래스입니다. 사용자 지정 MSBuild 작업을 만드는 구체적인 하위 클래스를 정의할 수 있습니다. 이 방법을 사용하면 명령 실행을 준비하는 데 필요한 모든 코드를 실행할 수 있습니다. 먼저 코드 생성 대한 사용자 지정 작업 만들기 자습서를 읽어야 합니다.
MSBuild ToolTask 파생된 사용자 지정 작업을 만들어 REST API 클라이언트를 생성하지만 http 주소를 사용하여 OpenAPI 사양을 참조하려고 하면 오류가 발생하도록 디자인됩니다. NSwag는 Http 주소를 OpenAPI 사양 입력으로 지원하지만 이 예제의 목적을 위해 이를 허용하지 않는 디자인 요구 사항이 있다고 가정해 보겠습니다.
전체 코드는 이 PetReaderToolTaskExample 폴더에 있습니다. 다운로드하고 살펴볼 수 있습니다. 이 자습서에서는 단계별로 진행하여 사용자 고유의 시나리오에 적용할 수 있는 몇 가지 개념을 알아봅니다.
사용자 지정 작업에 대한 새 Visual Studio 프로젝트를 만듭니다.
RestApiClientGenerator호출하고 .NET Standard 2.0에서 클래스 라이브러리(C#) 템플릿을 사용합니다. 솔루션 이름을PetReaderToolTaskExample로 지정하십시오.자동으로 생성된 Class1.cs삭제합니다.
Microsoft.Build.Utilities.CoreNuGet 패키지를 추가합니다.RestApiClientGenerator클래스 만들기MSBuild
ToolTask상속하고 다음 코드와 같이 추상 메서드를 구현합니다.using Microsoft.Build.Utilities; namespace RestApiClientGenerator { public class RestApiClientGenerator : ToolTask { protected override string ToolName => throw new System.NotImplementedException(); protected override string GenerateFullPathToTool() { throw new System.NotImplementedException(); } } }
다음 매개 변수를 추가합니다.
- InputOpenApiSpec, 사양이 있는 곳
- ClientClassName, 생성된 클래스의 이름
- ClientNamespaceName, 클래스가 생성되는 네임스페이스
- FolderClientClass, 클래스가 있는 폴더의 경로
- NSwagCommandFullPath, NSwag.exe 있는 디렉터리의 전체 경로
[Required] public string InputOpenApiSpec { get; set; } [Required] public string ClientClassName { get; set; } [Required] public string ClientNamespaceName { get; set; } [Required] public string FolderClientClass { get; set; } [Required] public string NSwagCommandFullPath { get; set; }NSwag 명령줄 도구설치합니다. NSwag.exe 있는 디렉터리의 전체 경로가 필요합니다.
추상 메서드를 구현합니다.
protected override string ToolName => "RestApiClientGenerator"; protected override string GenerateFullPathToTool() { return $"{NSwagCommandFullPath}\\NSwag.exe"; }당신이 재정의할 수 있는 메서드가 많이 있습니다. 현재 구현의 경우 다음 두 가지를 정의합니다.
- 명령 매개 변수를 정의합니다.
protected override string GenerateCommandLineCommands() { return $"openapi2csclient /input:{InputOpenApiSpec} /classname:{ClientClassName} /namespace:{ClientNamespaceName} /output:{FolderClientClass}\\{ClientClassName}.cs"; }- 매개 변수 유효성 검사:
protected override bool ValidateParameters() { //http address is not allowed var valid = true; if (InputOpenApiSpec.StartsWith("http:") || InputOpenApiSpec.StartsWith("https:")) { valid = false; Log.LogError("URL is not allowed"); } return valid; }메모
이 간단한 유효성 검사는 MSBuild 파일에서 다른 방법으로 수행할 수 있지만 C# 코드에서 수행하여 명령 및 논리를 캡슐화하는 것이 좋습니다.
프로젝트를 빌드합니다.
새 MSBuild 작업을 사용하는 콘솔 앱 만들기
다음 단계는 작업을 사용하는 앱을 만드는 것입니다.
콘솔 앱 프로젝트를 만들고
PetReaderToolTaskConsoleApp호출합니다. 원하는 .NET 버전을 선택합니다. 시작 프로젝트로 표시합니다.코드를 생성하기 위한
PetRestApiClient프로젝트를 만듭니다. .NET Standard를 사용합니다.PetReaderToolTaskConsoleApp프로젝트에서PetRestApiClient프로젝트 종속성을 만듭니다.PetRestApiClient프로젝트에서 폴더PetRestApiClient만듭니다. 이 폴더에는 생성된 코드가 포함됩니다.자동으로 생성된 Class1.cs삭제합니다.
PetRestApiClient에 다음 NuGet 패키지를 추가합니다.- 생성된 클라이언트를 컴파일하는 데 필요한 Newtonsoft.Json
- 생성된 클라이언트를 컴파일하는 데 필요한 System.ComponentModel.Annotations
PetRestApiClient프로젝트에서 프로젝트 폴더에 petshop-openapi-spec.json 텍스트 파일을 만듭니다. OpenAPI 사양을 추가하려면 여기서으로 내용을 파일에 복사합니다. 앞에서 설명한 대로 입력에만 의존하는 재현 가능한 빌드를 좋아합니다. 이 예제에서는 사용자가 OpenAPI 사양 입력으로 URL을 선택하는 경우 빌드 오류가 발생합니다.중요하다
일반 다시 빌드는 작동하지 않습니다. '
RestApiClientGenerator.dll복사하거나 삭제할 수 없음을 나타내는 오류가 표시됩니다. 이는 MBuild 사용자 지정 작업을 사용하는 동일한 빌드 프로세스에서 빌드하려고 하기 때문입니다.PetReaderToolTaskConsoleApp선택하고 해당 프로젝트만 다시 빌드합니다. 또 다른 솔루션은 자습서에서와 같이 완전히 독립적인 Visual Studio 솔루션에 사용자 지정 작업을 배치합니다. 사용자 지정 작업 만들기 예제입니다.다음 코드를 Program.cs복사합니다.
using System; using System.Net.Http; namespace PetReaderToolTaskConsoleApp { internal class Program { private const string baseUrl = "https://petstore.swagger.io/v2"; static void Main(string[] args) { HttpClient httpClient = new HttpClient(); httpClient.BaseAddress = new Uri(baseUrl); var petClient = new PetRestApiClient.PetRestApiClient(httpClient); var pet = petClient.GetPetByIdAsync(1).Result; Console.WriteLine($"Id: {pet.Id} Name: {pet.Name} Status: {pet.Status} CategoryName: {pet.Category.Name}"); } } }MSBuild 지침을 변경하여 작업을 호출하고 코드를 생성합니다. 다음 단계를 수행하여 PetRestApiClient.csproj 편집합니다.
MSBuild 사용자 지정 작업의 사용을 등록합니다.
<UsingTask TaskName="RestApiClientGenerator.RestApiClientGenerator" AssemblyFile="..\RestApiClientGenerator\bin\Debug\netstandard2.0\RestApiClientGenerator.dll" />작업을 실행하는 데 필요한 몇 가지 속성을 추가합니다.
<PropertyGroup> <!--The place where the OpenAPI spec is in--> <PetClientInputOpenApiSpec>petshop-openapi-spec.json</PetClientInputOpenApiSpec> <PetClientClientClassName>PetRestApiClient</PetClientClientClassName> <PetClientClientNamespaceName>PetRestApiClient</PetClientClientNamespaceName> <PetClientFolderClientClass>PetRestApiClient</PetClientFolderClientClass> <!--The directory where NSawg.exe is in--> <NSwagCommandFullPath>C:\Nsawg\Win</NSwagCommandFullPath> </PropertyGroup>중요하다
시스템의 설치 위치에 따라 적절한
NSwagCommandFullPath값을 선택합니다.빌드할 때 클라이언트를 생성하기 위해 MSBuild 대상을 추가합니다. 이 대상은 컴파일에 사용되는 코드를 생성하기
CoreCompile실행하기 전에 실행되어야 합니다.<Target Name="generatePetClient" BeforeTargets="CoreCompile" Inputs="$(PetClientInputOpenApiSpec)" Outputs="$(PetClientFolderClientClass)\$(PetClientClientClassName).cs"> <!--Calling our custom task derivated from MSBuild Tool Task--> <RestApiClientGenerator InputOpenApiSpec="$(PetClientInputOpenApiSpec)" ClientClassName="$(PetClientClientClassName)" ClientNamespaceName="$(PetClientClientNamespaceName)" FolderClientClass="$(PetClientFolderClientClass)" NSwagCommandFullPath="$(NSwagCommandFullPath)"></RestApiClientGenerator> </Target> <Target Name="forceReGenerationOnRebuild" AfterTargets="CoreClean"> <Delete Files="$(PetClientFolderClientClass)\$(PetClientClientClassName).cs"></Delete> </Target>
Input및Output증분 빌드관련되며,forceReGenerationOnRebuild대상은CoreClean후 생성된 파일을 삭제하므로 다시 빌드 작업 중에 클라이언트가 다시 생성됩니다.PetReaderToolTaskConsoleApp선택하고 해당 프로젝트만 다시 빌드합니다. 이제 클라이언트 코드가 생성되고 코드가 컴파일됩니다. 실행하여 작동 방식을 확인할 수 있습니다. 이 코드는 파일에서 코드를 생성하며 허용됩니다.이 단계에서는 매개 변수 유효성 검사를 보여 줍니다. PetRestApiClient.csproj에서 속성
$(PetClientInputOpenApiSpec)를 URL을 사용하도록 변경하세요.<PetClientInputOpenApiSpec>https://petstore.swagger.io/v2/swagger.json</PetClientInputOpenApiSpec>PetReaderToolTaskConsoleApp선택하고 해당 프로젝트만 다시 빌드합니다. 디자인 요구 사항에 따라 "URL이 허용되지 않습니다"라는 오류가 표시됩니다.
코드 다운로드
NSwag 명령줄 도구설치합니다. 그런 다음 NSwag.exe 있는 디렉터리의 전체 경로가 필요합니다. 그런 다음 PetRestApiClient.csproj 편집하고 컴퓨터의 설치 경로에 따라 적절한 $(NSwagCommandFullPath) 값을 선택합니다. 이제 RestApiClientGenerator 선택하고 해당 프로젝트만 빌드하고 마지막으로 PetReaderToolTaskConsoleApp선택하고 다시 빌드합니다.
PetReaderToolTaskConsoleApp실행할 수 있습니다. 모든 것이 예상대로 작동하는지 확인합니다.
다음 단계
사용자 지정 작업을 NuGet 패키지로 게시할 수 있습니다.
자습서: 사용자 지정 작업 만들기
또는 사용자 지정 작업을 테스트하는 방법을 알아봅니다.