Azure Logic Apps의 표준 워크플로에서 .NET Framework 코드 만들기 및 실행

적용 대상: Azure Logic Apps(표준)

표준 논리 앱 워크플로에서 .NET Framework 코드를 작성하고 실행해야 하는 통합 솔루션의 경우 Azure Logic Apps(표준) 확장과 함께 Visual Studio Code를 사용할 수 있습니다. 이 확장은 다음과 같은 기능과 이점을 제공합니다.

  • 가장 어려운 통합 문제를 해결하기 위해 유연성과 제어가 가능한 함수를 만들어 사용자 고유의 코드를 작성합니다.
  • Visual Studio Code에서 로컬로 코드를 디버그합니다. 동일한 디버깅 세션에서 코드 및 워크플로를 단계별로 실행합니다.
  • 워크플로와 함께 코드를 배포합니다. 다른 서비스 계획은 필요하지 않습니다.
  • 온-프레미스에서 클라우드로 사용자 지정 .NET Framework 투자를 리프트 앤 시프트할 수 있도록 BizTalk Server 마이그레이션 시나리오를 지원합니다.

사용자 고유의 코드를 작성하는 기능을 사용하여 다음과 같은 시나리오를 수행할 수 있습니다.

  • 사용자 지정 비즈니스 논리 구현
  • 인바운드 메시지에서 정보를 추출하는 사용자 지정 구문 분석
  • 데이터 유효성 검사 및 간단한 변환
  • API와 같은 다른 시스템에 대한 아웃바운드 메시지의 메시지 셰이핑
  • 계산

이 기능은 다음과 같은 시나리오에 적합하지 않습니다.

  • 실행하는 데 10분 이상 걸리는 프로세스
  • 큰 메시지 및 데이터 변환
  • 복잡한 일괄 처리 및 분리 시나리오
  • 스트리밍을 구현하는 BizTalk Server 파이프라인 구성 요소

Azure Logic Apps의 제한 사항에 대한 자세한 내용은 제한 및 구성 - Azure Logic Apps를 참조 하세요.

필수 조건

제한 사항

사용자 지정 함수 작성은 현재 Azure Portal에서 사용할 수 없습니다. 그러나 Visual Studio Code에서 Azure로 함수를 배포한 후 Azure Portal에 대한 워크플로 에서 코드 호출의 단계를 따릅니다. 이 논리 앱에서 로컬 함수 호출이라는 기본 제공 작업을 사용하여 배포된 사용자 지정 함수에서 선택하고 코드를 실행할 수 있습니다. 워크플로의 후속 작업은 다른 워크플로와 마찬가지로 이러한 함수의 출력을 참조할 수 있습니다. 기본 제공 작업의 실행 기록, 입력 및 출력을 볼 수 있습니다.

코드 프로젝트 만들기

Visual Studio Code용 최신 Azure Logic Apps(표준) 확장에는 워크플로를 사용하여 사용자 고유의 코드를 작성, 디버깅 및 배포하기 위한 간소화된 환경을 제공하는 코드 프로젝트 템플릿이 포함되어 있습니다. 이 프로젝트 템플릿은 작업 영역 파일과 두 개의 샘플 프로젝트를 만듭니다. 하나는 코드를 작성할 프로젝트이고 다른 프로젝트는 워크플로를 만듭니다.

참고 항목

코드와 워크플로 모두에 동일한 프로젝트 폴더를 사용할 수 없습니다.

  1. Visual Studio Code를 엽니다. 활동 모음에서 Azure 아이콘을 선택합니다. (키보드: Shift+Alt+A)

  2. 열리는 Azure 창의 작업 영역 섹션 도구 모음에 있는 Azure Logic Apps 메뉴에서 새 논리 앱 작업 영역 만들기를 선택합니다.

    Screenshot shows Visual Studio Code, Azure window, Workspace section toolbar, and selected option for Create new logic app workspace.

  3. 폴더 선택 상자에서 프로젝트에 대해 만든 로컬 폴더를 찾아 선택합니다.

  4. 새 논리 앱 작업 영역 만들기 프롬프트 상자가 나타나면 작업 영역의 이름을 입력합니다.

    Screenshot shows Visual Studio Code with prompt to enter workspace name.

    이 예제에서는 MyLogicAppWorkspace를 계속 진행합니다.

  5. 논리 앱 작업 영역 프롬프트에 대한 프로젝트 템플릿 선택 프롬프트 상자가 나타나면 사용자 지정 코드 프로젝트가 있는 논리 앱을 선택합니다.

    Screenshot shows Visual Studio Code with prompt to select project template for logic app workspace.

  6. 다음 프롬프트에 따라 다음 예제 값을 제공합니다.

    Item 예제 값
    함수 프로젝트의 함수 이름 WeatherForecast
    함수 프로젝트의 네임스페이스 이름 Contoso.Enterprise
    워크플로 템플릿:
    - 상태 저장 워크플로
    - 상태 비지정 워크플로
    상태 저장 워크플로
    워크플로 이름 MyWorkflow
  7. 현재 창에서 열기를 선택합니다.

    이 단계를 완료한 후 Visual Studio Code는 기본적으로 함수 프로젝트와 논리 앱 프로젝트를 포함하는 작업 영역을 만듭니다. 예를 들면 다음과 같습니다.

    Screenshot shows Visual Studio Code with created workspace.

    노드 설명
    <workspace-name> 함수 프로젝트와 논리 앱 워크플로 프로젝트를 모두 포함합니다.
    함수 함수 프로젝트에 대한 아티팩트가 들어 있습니다. 예를 들어 <함수 이름>.cs 파일은 코드를 작성할 수 있는 코드 파일입니다.
    LogicApp 빈 워크플로를 포함하여 논리 앱 프로젝트에 대한 아티팩트를 포함합니다.

코드 작성

  1. 작업 영역에서 아직 확장 되지 않은 경우 Functions 노드를 확장합니다.

  2. 이 예제에서 <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);
    
        <...>
    
    }
    
  3. 샘플 함수 코드를 사용자 고유의 코드로 바꾸고 사용자 고유의 시나리오에 대한 기본 Run 메서드를 편집합니다. 또는 선언을 포함하여 함수를 복사한 [FunctionName("<*function-name*>")] 다음 고유한 이름으로 함수의 이름을 바꿀 수 있습니다. 그런 다음, 필요에 맞게 이름이 바뀐 함수를 편집할 수 있습니다.

이 예제에서는 변경하지 않고 샘플 코드를 계속 사용합니다.

코드 컴파일 및 빌드

코드 작성을 완료한 후 컴파일하여 빌드 오류가 없는지 확인합니다. 함수 프로젝트에는 워크플로가 실행할 사용자 지정 함수를 찾는 논리 앱 프로젝트의 lib\custom 폴더에 코드를 컴파일한 다음 추가하는 빌드 작업이 자동으로 포함됩니다. 이러한 작업은 라이브러리\custom\net472 폴더에 어셈블리를 배치합니다.

  1. Visual Studio Code의 터미널 메뉴에서 새 터미널을 선택합니다.

  2. 표시되는 작업 디렉터리 목록에서 새 터미널의 현재 작업 디렉터리로 Functions를 선택합니다.

    Screenshot shows Visual Studio Code, prompt for current working directory, and selected Functions directory.

    Visual Studio Code는 명령 프롬프트가 있는 터미널 창을 엽니다.

  3. 터미널 창의 명령 프롬프트에서 dotnet restore를 입력합니다.

    Visual Studio Code는 프로젝트를 분석하고 프로젝트가 최신 상태인지 여부를 결정합니다.

    Screenshot shows Visual Studio Code, Terminal window, and completed dotnet restore command.

  4. 명령 프롬프트가 다시 나타나면 dotnet build를 입력합니다. 또는 터미널 메뉴에서 작업 실행을 선택합니다. 작업 목록에서 빌드(함수)를 선택합니다.

    빌드가 성공하면 터미널 창에서 빌드가 성공했다고 보고합니다.

  5. 논리 앱 프로젝트에 다음 항목이 있는지 확인합니다.

    • 작업 영역에서 LogicApp>lib\custom>net472 폴더를 확장합니다. net472라는 하위 폴더에 function-name>이라는< 파일을 포함하여 코드를 실행하는 데 필요한 여러 DLL(어셈블리) 파일이 포함되어 있음을 확인합니다.dll.

    • 작업 영역에서 LogicApp>lib\custom<>function-name> 폴더를 확장합니다. 함수 이름>이라는< 하위 폴더에 작성한 함수 코드에 대한 메타데이터를 포함하는 function.json 파일이 포함되어 있는지 확인합니다. 워크플로 디자이너는 이 파일을 사용하여 코드를 호출할 때 필요한 입력 및 출력을 결정합니다.

    다음 예제에서는 논리 앱 프로젝트에서 생성된 샘플 어셈블리 및 기타 파일을 보여줍니다.

    Screenshot shows Visual Studio Code and logic app workspace with function project and logic app project, now with the generated assemblies and other required files.

워크플로에서 코드 호출

코드가 컴파일되고 논리 앱 프로젝트에 코드 실행에 필요한 파일이 포함되어 있는지 확인한 후 논리 앱 프로젝트에 포함된 기본 워크플로를 엽니다.

  1. 작업 영역의 LogicApp에서 워크플로 이름> 노드를< 확장하고 workflow.json 바로 가기 메뉴를 열고 디자이너 열기를 선택합니다.

    열리는 워크플로 디자이너에서 논리 앱 프로젝트에 포함된 기본 워크플로는 다음 트리거 및 작업과 함께 표시됩니다.

  2. 이 논리 앱에서 로컬 함수 호출이라는 작업을 선택합니다.

    작업의 정보 창이 오른쪽에 열립니다.

    Screenshot shows Visual Studio Code, workflow designer, and default workflow with trigger and actions.

  3. 함수 이름 매개 변수 값이 실행하려는 함수로 설정되어 있는지 검토하고 확인합니다. 함수에서 사용하는 다른 매개 변수 값을 검토하거나 변경합니다.

코드 및 워크플로 디버그

  1. 다음 단계를 반복하여 Azurite 스토리지 에뮬레이터 를 세 번 시작합니다. 다음 Azure Storage 서비스에 대해 각각 한 번:

    • Azure Blob Service
    • Azure 큐 서비스
    • Azure Table Service
    1. Visual Studio Code 보기 메뉴에서 명령 팔레트를 선택합니다.

    2. 표시되는 프롬프트에서 Azurite: Blob Service를 찾아 선택합니다.

    3. 표시되는 작업 디렉터리 목록에서 LogicApp을 선택합니다.

    4. Azurite: Start Queue Service and Azurite: Start Table Service에 대해 다음 단계를 반복합니다.

    화면 맨 아래에 있는 Visual Studio Code 작업 표시줄에 실행 중인 세 가지 스토리지 서비스가 표시됩니다. 예를 들면 다음과 같습니다.

    Screenshot shows Visual Studio Code taskbar with Azure Blob Service, Azure Queue Service, and Azure Table Service running.

  2. Visual Studio Code 작업 모음에서 실행 및 디버그를 선택합니다. (키보드: Ctrl+Shift+D)

    Screenshot shows Visual Studio Code Activity Bar with Run and Debug selected.

  3. 실행 및 디버그 목록에서 논리 앱에 연결(LogicApp)을 선택하고 아직 선택하지 않은 경우 재생(녹색 화살표)을 선택합니다.

    Screenshot shows Run and Debug list with Attach to logic app selected and Play button selected.

    터미널 창이 열리고 시작된 디버깅 프로세스가 표시됩니다. 그러면 디버그 콘솔 창이 나타나고 디버깅 상태 표시됩니다. Visual Studio Code 아래쪽의 작업 표시줄은 .NET 디버거가 로드되었음을 나타내는 주황색으로 바뀝니다.

  4. 실행 및 디버그 목록에서 .NET 함수에 연결(함수)을 선택한 다음 재생(녹색 화살표)을 선택합니다.

    Screenshot shows Run and Debug list with Attach to NET Functions selected and Play button selected.

  5. 중단점을 설정하려면 함수 정의(<함수 이름>.cs) 또는 워크플로 정의(workflow.json)에서 중단점을 원하는 줄 번호를 찾고 왼쪽 열을 선택합니다. 예를 들면 다음과 같습니다.

    Screenshot shows Visual Studio Code and the open function code file with a breakpoint set for a line in code.

  6. 워크플로에서 요청 트리거를 수동으로 실행하려면 워크플로의 개요 페이지를 엽니다.

    1. 논리 앱 프로젝트에서 workflow.json 파일의 바로 가기 메뉴를 열고 개요를 선택합니다.

      워크플로의 개요 페이지에서 워크플로를 수동으로 시작하려는 경우 실행 트리거 단추를 사용할 수 있습니다. 워크플로 속성에서 콜백 URL 값은 워크플로의 요청 트리거에 의해 생성된 호출 가능한 엔드포인트의 URL입니다. 다른 논리 앱 워크플로를 포함하여 다른 앱에서 워크플로를 트리거하기 위해 이 URL에 요청을 보낼 수 있습니다.

      Screenshot shows Visual Studio Code and workflow's Overview page opened.

  7. 개요 페이지 도구 모음에서 실행 트리거를 선택합니다.

    워크플로가 실행하기 시작하면 디버거가 첫 번째 중단점을 활성화합니다.

  8. 실행 메뉴 또는 디버거 도구 모음에서 디버그 작업을 선택합니다.

    워크플로 실행이 완료되면 개요 페이지에 완료된 실행과 해당 실행에 대한 기본 세부 정보가 표시됩니다.

  9. 워크플로 실행에 대한 자세한 내용을 검토하려면 완료된 실행을 선택합니다. 또는 기간 열 옆의 목록에서 실행 표시를 선택합니다.

    Screenshot shows Visual Studio Code and finished workflow run.

코드 배포

논리 앱 프로젝트를 배포하는 것과 동일한 방식으로 사용자 지정 함수를 배포할 수 있습니다. Visual Studio Code에서 배포하든 CI/CD DevOps 프로세스를 사용하든, 배포하기 전에 코드를 빌드하고 모든 종속 어셈블리가 논리 앱 프로젝트의 lib/custom/net472 폴더에 있는지 확인합니다. 자세한 내용은 Visual Studio Code에서 Azure로 표준 워크플로 배포를 참조하세요.

문제 해결

작업 정보 창 오류

워크플로 디자이너에서 이 논리 앱에서 로컬 함수 호출이라는 기본 제공 작업을 선택하면 작업의 정보 창에 다음 메시지가 표시됩니다.

Failed to retrieve dynamic inputs. Error details:

이 시나리오에서는 논리 앱 프로젝트를 검사하여 LogicApp\lib\custom 폴더가 비어 있는지 검사. 비어 있는 경우 터미널 메뉴에서 작업>빌드 함수 실행을 선택합니다.

지정된 이름의 프로세스가 현재 실행 중이 아닙니다.

워크플로를 실행할 때 이 오류 메시지가 표시되면 논리 앱이 아닌 .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)

다음 단계

Visual Studio Code를 사용하여 표준 워크플로 만들기