Azure Logic Apps의 표준 워크플로에서 .NET 코드 만들기 및 실행
적용 대상: Azure Logic Apps(표준)
표준 논리 앱 워크플로에서 .NET 코드를 작성하고 실행해야 하는 통합 솔루션의 경우 Azure Logic Apps(표준) 확장과 함께 Visual Studio Code를 사용할 수 있습니다. 이 확장은 다음과 같은 기능과 이점을 제공합니다.
- 가장 어려운 통합 문제를 해결하기 위해 유연성과 제어가 가능한 함수를 만들어 사용자 고유의 코드를 작성합니다.
- Visual Studio Code에서 로컬로 코드를 디버그합니다. 동일한 디버깅 세션에서 코드 및 워크플로를 단계별로 실행합니다.
- 워크플로와 함께 코드를 배포합니다. 다른 서비스 계획은 필요하지 않습니다.
- 사용자 지정 .NET 투자를 온-프레미스에서 클라우드로 리프트 앤 시프트할 수 있도록 BizTalk Server 마이그레이션 시나리오를 지원합니다.
고유한 코드를 작성하는 기능을 사용하여 다음과 같은 시나리오를 수행할 수 있습니다.
- 사용자 지정 비즈니스 논리 구현
- 인바운드 메시지에서 정보를 추출하는 사용자 지정 구문 분석
- 데이터 유효성 검사 및 간단한 변환
- API와 같은 다른 시스템에 대한 아웃바운드 메시지에 대한 메시지 셰이핑
- 계산
이 기능은 다음과 같은 시나리오에 적합하지 않습니다.
- 실행하는 데 10분 이상 걸리는 프로세스
- 대용량 메시지 및 데이터 변환
- 복잡한 일괄 처리 및 분리 시나리오
- 스트리밍을 구현하는 파이프라인 구성 요소 BizTalk Server
Azure Logic Apps의 제한 사항에 대한 자세한 내용은 제한 사항 및 구성 - Azure Logic Apps를 참조하세요.
필수 조건
Azure 계정 및 구독 구독이 없는 경우 Azure 체험 계정에 등록합니다.
Azure Logic Apps(표준) 확장을 사용하는 최신 Visual Studio Code. 이러한 요구 사항을 충족하려면 Visual Studio Code를 사용하여 단일 테넌트 Azure Logic Apps에서 표준 워크플로 만들기의 필수 조건을 참조하세요.
사용자 지정 함수 기능은 현재 Windows 운영 체제에서 실행되는 Visual Studio Code에서만 사용할 수 있습니다.
사용자 지정 함수 기능은 현재 Azure 호스팅 논리 앱 워크플로에 대해 .NET Framework 및 .NET 8 호출을 지원합니다.
코드 프로젝트를 만드는 데 사용할 로컬 폴더
제한 사항
사용자 지정 함수 작성은 현재 Azure Portal에서 사용할 수 없습니다. 그러나 Visual Studio Code에서 Azure로 함수를 배포한 후 Azure Portal에 대해 워크플로에서 코드 호출의 단계를 따릅니다. 이 논리 앱에서 로컬 함수 호출이라는 기본 제공 작업을 사용하여 배포된 사용자 지정 함수에서 선택하고 코드를 실행할 수 있습니다. 워크플로의 후속 작업은 다른 워크플로와 마찬가지로 이러한 함수의 출력을 참조할 수 있습니다. 기본 제공 작업의 실행 기록, 입력 및 출력을 볼 수 있습니다.
사용자 지정 함수는 격리된 작업자를 사용하여 논리 앱 워크플로의 코드를 호출합니다. 고유의 함수 코드와 작업자 간의 패키지 참조 충돌을 방지하려면 작업자가 참조하는 것과 동일한 패키지 버전을 사용합니다. 작업자가 참조하는 전체 패키지 목록과 버전은 작업자 및 패키지 종속성을 참조하세요.
코드 프로젝트 만들기
Visual Studio Code에 대한 최신 Azure Logic Apps(표준) 확장에는 워크플로를 사용하여 사용자 고유의 코드를 작성, 디버깅 및 배포하기 위한 간소화된 환경을 제공하는 코드 프로젝트 템플릿이 포함되어 있습니다. 이 프로젝트 템플릿은 작업 영역 파일과 두 개의 샘플 프로젝트를 만듭니다. 하나는 코드를 작성하는 프로젝트이고 다른 하나는 워크플로를 만드는 프로젝트입니다.
참고 항목
코드와 워크플로 모두에 동일한 프로젝트 폴더를 사용할 수 없습니다.
Visual Studio Code를 엽니다. 활동 막대에서 Azure 아이콘을 선택합니다. (키보드: Shift+Alt+A)
열리는 Azure 창의 작업 영역 섹션 도구 모음의 Azure Logic Apps 메뉴에서 새 논리 앱 작업 영역 만들기를 선택합니다.
폴더 선택 상자에서 프로젝트에 대해 만든 로컬 폴더를 찾아 선택합니다.
새 논리 앱 작업 영역 만들기 프롬프트 상자가 나타나면 작업 영역의 이름을 입력합니다.
이 예제에서는 MyLogicAppWorkspace를 계속 진행합니다.
논리 앱 작업 영역에 대한 프로젝트 템플릿 선택 프롬프트 상자가 나타나면 사용자 지정 코드 프로젝트가 있는 논리 앱을 선택합니다.
Azure 호스팅 표준 논리 앱 워크플로의 경우 프롬프트에 따라 .NET Framework 또는 .NET 8을 선택합니다.
다음 프롬프트에 따라 다음 예제 값을 제공합니다.
Item 예제 값 .NET 함수 프로젝트의 함수 이름 WeatherForecast .NET 함수 프로젝트의 네임스페이스 이름 Contoso.Enterprise 워크플로 템플릿:
- 상태 저장 워크플로
- 상태 비저장 워크플로상태 저장 워크플로 워크플로 이름 MyWorkflow 현재 창에서 열기를 선택합니다.
이 단계를 완료한 후 Visual Studio Code는 기본적으로 .NET 함수 프로젝트와 논리 앱 프로젝트를 포함하는 작업 영역을 만듭니다. 예를 들면 다음과 같습니다.
노드 설명 <workspace-name> .NET 함수 프로젝트와 논리 앱 워크플로 프로젝트를 모두 포함합니다. 함수 .NET 함수 프로젝트에 대한 아티팩트를 포함합니다. 예를 들어 <function-name.cs> 파일은 코드를 작성할 수 있는 코드 파일입니다. LogicApp 빈 워크플로를 포함하여 논리 앱 프로젝트에 대한 아티팩트를 포함합니다.
코드 작성
아직 확장되지 않은 경우 작업 영역에서 Functions 노드를 확장합니다.
이 예제에서 WeatherForecast.cs라는 <function-name>.cs 파일을 엽니다.
기본적으로 이 파일에는 다음과 같은 코드 요소가 포함된 샘플 코드와 이전에 제공된 예제 값이 포함됩니다( 해당하는 경우).
- 네임스페이스 이름
- 클래스 이름
- 함수 이름
- 함수 매개 변수
- 반환 형식
- 복합 형식
다음 예제에서는 전체 샘플 코드를 보여줍니다.
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace Contoso.Enterprise { using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.Functions.Extensions.Workflows; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; /// <summary> /// Represents the WeatherForecast flow invoked function. /// </summary> public class WeatherForecast { private readonly ILogger<WeatherForecast> logger; public WeatherForecast(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<WeatherForecast>(); } /// <summary> /// Executes the logic app workflow. /// </summary> /// <param name="zipCode">The zip code.</param> /// <param name="temperatureScale">The temperature scale (e.g., Celsius or Fahrenheit).</param> [FunctionName("WeatherForecast")] public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale) { this.logger.LogInformation("Starting WeatherForecast with Zip Code: " + zipCode + " and Scale: " + temperatureScale); // Generate random temperature within a range based on the temperature scale Random rnd = new Random(); var currentTemp = temperatureScale == "Celsius" ? rnd.Next(1, 30) : rnd.Next(40, 90); var lowTemp = currentTemp - 10; var highTemp = currentTemp + 10; // Create a Weather object with the temperature information var weather = new Weather() { ZipCode = zipCode, CurrentWeather = $"The current weather is {currentTemp} {temperatureScale}", DayLow = $"The low for the day is {lowTemp} {temperatureScale}", DayHigh = $"The high for the day is {highTemp} {temperatureScale}" }; return Task.FromResult(weather); } /// <summary> /// Represents the weather information for WeatherForecast. /// </summary> public class Weather { /// <summary> /// Gets or sets the zip code. /// </summary> public int ZipCode { get; set; } /// <summary> /// Gets or sets the current weather. /// </summary> public string CurrentWeather { get; set; } /// <summary> /// Gets or sets the low temperature for the day. /// </summary> public string DayLow { get; set; } /// <summary> /// Gets or sets the high temperature for the day. /// </summary> public string DayHigh { get; set; } } } }
함수 정의에는 시작하는 데 사용할 수 있는 기본
Run
메서드가 포함되어 있습니다. 이 샘플Run
메서드는 복잡한 .NET 형식을 포함하여 다양한 입력 및 출력 전달과 같은 사용자 지정 함수 기능에서 사용할 수 있는 몇 가지 기능을 보여줍니다.<function-name>.cs 파일에는 Application Insights 리소스에 이벤트 로깅을 지원하는
ILogger
인터페이스도 포함되어 있습니다. Application Insights에 추적 정보를 보내고 워크플로의 추적 정보와 함께 해당 정보를 저장할 수 있습니다. 예를 들면 다음과 같습니다.private readonly ILogger<WeatherForecast> logger; public WeatherForecast(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<WeatherForecast>(); } [FunctionName("WeatherForecast")] public Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale) { this.logger.LogInformation("Starting WeatherForecast with Zip Code: " + zipCode + " and Scale: " + temperatureScale); <...> }
샘플 함수 코드를 사용자 고유의 코드로 바꾸고 사용자 고유의 시나리오에 대한 기본
Run
메서드를 편집합니다. 또는[FunctionName("<*function-name*>")]
선언을 포함하여 함수를 복사한 다음 고유한 이름으로 함수의 이름을 바꿀 수 있습니다. 그런 다음, 필요에 맞게 이름이 바뀐 함수를 편집할 수 있습니다.
이 예제에서는 샘플 코드를 변경하지 않고 계속 진행합니다.
코드 컴파일 및 빌드
코드 작성을 완료한 후 컴파일하여 빌드 오류가 없는지 확인합니다. .NET 함수 프로젝트에는 워크플로가 실행할 사용자 지정 함수를 찾는 논리 앱 프로젝트의 lib\custom 폴더에 코드를 컴파일한 다음 추가하는 빌드 작업이 자동으로 포함됩니다. 이러한 작업은 .NET 버전에 따라 lib\custom\net472 또는 lib\custom\net8 폴더에 어셈블리를 배치합니다.
Visual Studio Code의 터미널 메뉴에서 새 터미널을 선택합니다.
표시되는 작업 디렉터리 목록에서 함수를 새 터미널의 현재 작업 디렉터리로 선택합니다.
Visual Studio Code가 명령 프롬프트가 있는 터미널 창을 엽니다.
터미널 창의 명령 프롬프트에서 dotnet restore를 입력합니다.
Visual Studio Code가 프로젝트를 분석하고 프로젝트가 최신 상태인지 여부를 결정합니다.
명령 프롬프트가 다시 나타나면 dotnet build를 입력합니다. 또는 터미널 메뉴에서 작업 실행을 선택합니다. 작업 목록에서 빌드(Functions)를 선택합니다.
빌드가 성공하면 터미널 창에서 빌드가 성공했다고 보고합니다.
논리 앱 프로젝트에 다음 항목이 있는지 확인합니다.
작업 영역에서 .NET 버전에 따라 LogicApp>lib\custom>net472 또는 net8 폴더를 확장합니다. net472 또는 net8이라는 하위 폴더에 각각 <function-name>.dll이라는 파일을 포함하여 코드를 실행하는 데 필요한 어셈블리(DLL) 파일이 포함되어 있음을 확인합니다.
작업 영역에서 LogicApp>lib\custom><function-name> 폴더를 확장합니다. <function-name>이라는 하위 폴더에 작성한 함수 코드에 대한 메타데이터가 포함된 function.json 파일이 포함되어 있는지 확인합니다. 워크플로 디자이너는 이 파일을 사용하여 코드를 호출할 때 필요한 입력 및 출력을 결정합니다.
다음 예제에서는 논리 앱 프로젝트에서 생성된 샘플 어셈블리 및 기타 파일을 보여줍니다.
워크플로에서 코드 호출
코드가 컴파일되고 논리 앱 프로젝트에 코드를 실행하는 데 필요한 파일이 포함되어 있는지 확인한 후 논리 앱 프로젝트에 포함된 기본 워크플로를 엽니다.
작업 영역의 LogicApp에서 <workflow-name> 노드를 확장하고 workflow.json에 대한 바로 가기 메뉴를 열고 디자이너 열기를 선택합니다.
열리는 워크플로 디자이너에서 논리 앱 프로젝트에 포함된 기본 워크플로가 다음 트리거 및 작업과 함께 표시됩니다.
- HTTP 요청을 수신할 때라는 기본 제공 요청 트리거
- 이 논리 앱에서 로컬 함수 호출이라는 기본 제공 작업
- 요청 트리거를 사용하는 경우에만 호출자에게 회신하는 데 사용하는 응답이라는 기본 제공 응답 작업
이 논리 앱에서 로컬 함수 호출이라는 작업을 선택합니다.
작업의 정보 창이 오른쪽으로 열립니다.
함수 이름 매개 변수 값이 실행하려는 함수로 설정되어 있는지 검토하고 확인합니다. 함수에서 사용하는 다른 매개 변수 값을 검토하거나 변경합니다.
코드 및 워크플로 디버그
다음 단계를 반복하여 다음 Azure Storage 서비스에 대해 각각 한 번씩, Azurite 스토리지 에뮬레이터를 세 번 시작합니다.
- Azure Blob Service
- Azure 큐 서비스
- Azure Table Service
Visual Studio Code 보기 메뉴에서 명령 팔레트를 선택합니다.
표시되는 프롬프트에서 Azurite: Blob 서비스 시작을 찾아 선택합니다.
표시되는 작업 디렉터리 목록에서 LogicApp을 선택합니다.
Azurite: 큐 서비스 시작 및 Azurite: 테이블 서비스 시작에 대해 다음 단계를 반복합니다.
화면 아래쪽의 Visual Studio Code 작업 표시줄에 실행 중인 세 가지 스토리지 서비스가 표시되면 성공합니다. 예를 들면 다음과 같습니다.
다음 단계를 수행하여 논리 앱 프로젝트에 디버거를 연결합니다.
Visual Studio Code 활동 막대에서 실행 및 디버그를 선택합니다. (키보드: Ctrl+Shift+D)
실행 및 디버그 목록에서 논리 앱(LogicApp)에 연결을 선택하고 아직 선택하지 않은 경우 재생(녹색 화살표)을 선택합니다.
터미널 창이 열리고 시작된 디버깅 프로세스가 표시됩니다. 그러면 디버그 콘솔 창이 나타나고 디버깅 상태가 표시됩니다. Visual Studio Code 아래쪽에서 작업 표시줄이 주황색으로 바뀌어 .NET 디버거가 로드되었음을 나타냅니다.
코드에 따라 다음 단계를 수행하여 .NET 함수 프로젝트에 디버거를 연결합니다.
.NET 8 프로젝트
Visual Studio Code 보기 메뉴에서 명령 팔레트를 선택합니다.
명령 팔레트에서 디버그: .NET 5 이상 또는 .NET Core 프로세스에 연결을 찾아 선택합니다.
목록에서 dotnet.exe 프로세스를 찾아 선택합니다. 여러 dotnet.exe 프로세스가 있는 경우 다음 경로가 있는 프로세스를 선택합니다.
<드라이브 이름>:\Users<user-name>.azure-functions-core-tools\Functions\ExtensionBundles\Microsoft.Azure.Functions.ExtensionBundle.Workflows<extension-bundle-version>\CustomCodeNetFxWorker\net8\Microsoft.Azure.Workflows.Functions.CustomCodeNetFxWorker.dll
.NET Framework 프로젝트
실행 및 디버그 목록에서 .NET 함수(Functions)에 연결을 선택하고 아직 선택하지 않은 경우 재생(녹색 화살표)을 선택합니다.
중단점을 설정하려면 함수 정의(<function-name.cs>) 또는 워크플로 정의(workflow.json)에서 중단점을 두려는 줄 번호를 찾고 왼쪽 열을 선택합니다. 예를 들면 다음과 같습니다.
워크플로에서 요청 트리거를 수동으로 실행하려면 워크플로의 개요 페이지를 엽니다.
논리 앱 프로젝트에서 workflow.json 파일의 바로 가기 메뉴를 열고 개요를 선택합니다.
워크플로의 개요 페이지에서 워크플로를 수동으로 시작하려는 경우 트리거 실행 단추를 사용할 수 있습니다. 워크플로 속성에서 콜백 URL 값은 워크플로의 요청 트리거에 의해 생성된 호출 가능한 엔드포인트의 URL입니다. 다른 논리 앱 워크플로를 포함하여 다른 앱에서 워크플로를 트리거하기 위해 이 URL에 요청을 보낼 수 있습니다.
개요 페이지 도구 모음에서 트리거 실행을 선택합니다.
워크플로가 실행하기 시작하면 디버거가 첫 번째 중단점을 활성화합니다.
실행 메뉴 또는 디버거 도구 모음에서 디버그 작업을 선택합니다.
워크플로 실행이 완료되면 개요 페이지에 완료된 실행과 해당 실행에 대한 기본 세부 정보가 표시됩니다.
워크플로 실행에 대한 자세한 내용을 검토하려면 완료된 실행을 선택합니다. 또는 기간 열 옆의 목록에서 실행 표시를 선택합니다.
코드 배포
논리 앱 프로젝트를 배포하는 것과 동일한 방식으로 사용자 지정 함수를 배포할 수 있습니다. Visual Studio Code에서 배포하든 CI/CD DevOps 프로세스를 사용하든 관계없이 코드를 빌드하고 모든 종속 어셈블리가 배포하기 전에 다음 논리 앱 프로젝트 폴더에 있는지 확인합니다.
.NET 4.7.2: lib/custom/net472 폴더
.NET 8: lib/custom/net8 폴더
자세한 내용은 Visual Studio Code에서 Azure로 표준 워크플로 배포를 참조하세요.
문제 해결
작업 정보 창 오류
워크플로 디자이너에서 이 논리 앱에서 로컬 함수 호출이라는 기본 제공 작업을 선택하면 작업의 정보 창에 다음 메시지가 표시됩니다.
Failed to retrieve dynamic inputs. Error details:
이 시나리오에서는 논리 앱 프로젝트를 검사하여 LogicApp\lib\custom 폴더가 비어 있는지 검사합니다. 비어 있는 경우 터미널 메뉴에서 작업 실행>Functions 빌드을 선택합니다.
현재 실행 중인 지정된 이름의 프로세스가 없습니다.
워크플로를 실행할 때 이 오류 메시지가 표시되면 논리 앱이 아닌 .NET Functions에 연결된 디버거 프로세스가 있는 것일 수 있습니다.
이 문제를 해결하려면 실행 및 디버그 목록에서 논리 앱(LogicApp)에 연결을 선택한 다음 재생(녹색 삼각형)을 선택합니다.
패키지를 올바르게 가져오지 않음
출력 창에 다음 메시지와 유사한 오류가 표시되면 .NET 6.0 이상이 설치되어 있는지 확인합니다. 이 버전을 설치한 경우 제거한 다음 다시 설치해 보세요.
C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.targets(83,5): warning : The ExtensionsMetadataGenerator package was not imported correctly. Are you missing 'C:\Users\yourUserName\.nuget\packages\microsoft.azure.webjobs.script.extensionsmetadatagenerator\4.0.1\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.targets' or 'C:\Users\yourUserName\.nuget\packages\microsoft.azure.webjobs.script.extensionsmetadatagenerator\4.0.1\build\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.props'? [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] WeatherForecast -> C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\\bin\Debug\net472\WeatherForecast.dll C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : It was not possible to find any compatible framework version [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : The specified framework 'Microsoft.NETCore.App', version '6.0.0' was not found. [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj] C:\Users\yourUserName\.nuget\packages\microsoft.net.sdk.functions\4.2.0\build\Microsoft.NET.Sdk.Functions.Build.targets(32,5): error : - Check application dependencies and target a framework version installed at: [C:\Desktop\...\custom-code-project\MyLogicAppWorkspace\Function\WeatherForecast.csproj]
빌드 실패
함수에 변수가 포함되어 있지 않고 코드를 빌드하는 경우 출력 창에 다음 오류 메시지가 표시될 수 있습니다.
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1031: Type expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1001: Identifier expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
Build FAILED.
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1031: Type expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
C:\Users\yourUserName\...\custom-code-project\Function\func.cs (24,64): error CS1001: Identifier expected [C:\Users\yourUserName\...\custom-code-project\Function\func.csproj]
0 Warning(s)
2 Error(s)
이 문제를 해결하려면 코드의 Run
메서드에 다음 매개 변수를 추가합니다.
string parameter1 = null
다음 예제에서는 Run
메서드 서명이 표시되는 방법을 보여줍니다.
public static Task<Weather> Run([WorkflowActionTrigger] int zipCode, string temperatureScale, string parameter1 = null)