다음을 통해 공유


Azure Functions의 함수 앱에 대한 리소스 배포 자동화

Bicep 파일 또는 ARM(Azure Resource Manager) 템플릿을 사용하여 함수 앱을 배포하는 프로세스를 자동화할 수 있습니다. 배포하는 동안 기존 Azure 리소스를 사용하거나 새 리소스를 만들 수 있습니다. 자동화는 다음과 같은 시나리오에서 도움이 됩니다.

  • 리소스 배포를 Azure Pipelines 및 GitHub Actions 기반 배포의 소스 코드와 통합합니다.
  • 백업에서 함수 앱 및 관련 리소스 복원
  • 앱 토폴로지 여러 번 배포

이 문서에서는 Azure Functions에 대한 리소스 만들기 및 배포를 자동화하는 방법을 보여줍니다. 함수에서 사용하는 트리거 및 바인딩에 따라 이 문서의 범위를 벗어나는 다른 리소스를 배포해야 할 수도 있습니다.

필요한 템플릿 코드는 함수 앱에 대해 원하는 호스팅 옵션에 따라 달라집니다. 이 문서에서 지원하는 호스팅 옵션은 다음과 같습니다.

호스팅 옵션 배포 유형 자세한 내용은 다음을 참조하세요...
Azure Functions 사용량 요금제 코드 전용 사용 계획
Azure Functions Flex Consumption 요금제 코드 전용 Flex 사용량 계획
Azure Functions 탄력적 프리미엄 플랜 코드 | 컨테이너 프리미엄 계획
Azure Functions 전용(App Service) 플랜 코드 | 컨테이너 전용 계획
Azure Container Apps 컨테이너만 Azure Functions의 Container Apps 호스팅
Azure Arc 코드 | 컨테이너 Azure Arc의 App Service, Functions 및 Logic Apps(미리 보기)

Important

Flex 사용량 플랜은 현재 미리 보기 버전입니다.

이 문서를 사용할 때는 다음 사항을 염두에 두어야 합니다.

  • 예제는 특정 리소스에 대한 개별 섹션으로 표시됩니다. 다양한 전체 Bicep 파일 및 ARM 템플릿 예제는 이러한 함수 앱 배포 예제를 참조하세요.
  • 예제는 특정 리소스에 대한 개별 섹션으로 표시됩니다. 전체 Bicep 파일 및 ARM 템플릿 예제의 광범위한 집합은 이러한 Flex Consumption 앱 배포 예제를 참조하세요.
  • 예제는 특정 리소스에 대한 개별 섹션으로 표시됩니다.

필요한 리소스

Azure Functions 호스팅 배포에 대해 다음 리소스를 만들거나 구성해야 합니다.

리소스 요구 사항 구문 및 속성 참조
스토리지 계정 Required Microsoft.Storage/storageAccounts
Application Insights 구성 요소 권장 Microsoft.Insights/components*
호스팅 계획 Required Microsoft.Web/serverfarms
함수 앱 Required Microsoft.Web/sites

Azure Functions 호스팅 배포에 대해 다음 리소스를 만들거나 구성해야 합니다.

리소스 요구 사항 구문 및 속성 참조
스토리지 계정 Required Microsoft.Storage/storageAccounts
Application Insights 구성 요소 권장 Microsoft.Insights/components*
함수 앱 Required Microsoft.Web/sites

Azure Container Apps 호스팅 배포를 일반적으로 구성하는 리소스는 다음과 같습니다.

리소스 요구 사항 구문 및 속성 참조
스토리지 계정 Required Microsoft.Storage/storageAccounts
Application Insights 구성 요소 권장 Microsoft.Insights/components*
관리 환경 Required Microsoft.App/managedEnvironments
함수 앱 Required Microsoft.Web/sites

Azure Arc 호스팅 배포를 일반적으로 구성하는 리소스는 다음과 같습니다.

리소스 요구 사항 구문 및 속성 참조
스토리지 계정 Required Microsoft.Storage/storageAccounts
Application Insights 구성 요소 권장 Microsoft.Insights/components1
App Service Kubernetes 환경 Required Microsoft.ExtendedLocation/customLocations
함수 앱 Required Microsoft.Web/sites

*Application Insights 인스턴스에서 사용할 수 있는 Log Analytics 작업 영역이 아직 없는 경우 이 리소스도 만들어야 합니다.

여러 리소스를 단일 Bicep 파일 또는 ARM 템플릿에 배포하는 경우 리소스를 만드는 순서가 중요합니다. 이 요구 사항은 리소스 간의 종속성으로 인한 결과입니다. 이러한 종속성의 경우 dependsOn 요소를 사용하여 종속 리소스의 종속성을 정의해야 합니다. 자세한 내용은 ARM 템플릿에서 리소스 배포 순서 정의 또는 Bicep의 리소스 종속성을 참조하세요.

필수 조건

  • 이 예제는 기존 리소스 그룹의 컨텍스트에서 실행되도록 설계되었습니다.
  • Application Insights 및 스토리지 로그 모두에 기존 Azure Log Analytics 작업 영역이 있어야 합니다. 작업 영역은 서비스 간에 공유할 수 있으며, 썸의 규칙으로 성능을 향상시키기 위해 각 지역에 작업 영역을 만들어야 합니다. Log Analytics 작업 영역을 만드는 방법의 예는 Log Analytics 작업 영역 만들기를 참조하세요. 설정>속성>리소스 ID 아래의 Azure Portal의 작업 영역 페이지에서 정규화된 작업 영역 리소스 ID를 찾을 수 있습니다.
  • 이 문서에서는 Azure Container Apps에서 이미 관리 환경을 만들었다고 가정합니다. Container Apps에서 호스트되는 함수 앱을 만들려면 관리 환경의 이름과 ID가 모두 필요합니다.

스토리지 계정 만들기

모든 함수 앱에는 Azure 스토리지 계정이 필요합니다. Blob, 테이블, 큐 및 파일을 지원하는 일반 용도의 계정이 있어야 합니다. 자세한 내용은 Azure Functions 스토리지 계정 요구 사항을 참조하세요.

Important

스토리지 계정은 중요한 앱 데이터를 저장하는 데 사용되며, 이러한 중요 앱 데이터에 애플리케이션 코드 자체가 포함되는 경우도 있습니다. 다른 앱이나 사용자가 스토리지 계정에 액세스하는 행위를 제한해야 합니다.

이 예제 섹션에서는 표준 범용 v2 스토리지 계정을 만듭니다.

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: storageAccountName
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    supportsHttpsTrafficOnly: true
    defaultToOAuthAuthentication: true
    allowBlobPublicAccess: false
  }
}

자세한 컨텍스트는 템플릿 리포지토리의 전체 main.bicep 파일을 참조하세요.

자세한 컨텍스트는 샘플 리포지토리의 전체 storage-account.bicep 파일을 참조하세요.

이 스토리지 계정의 연결 문자열을 Functions에 필요한 AzureWebJobsStorage 앱 설정으로 설정해야 합니다. 이 문서의 템플릿은 만든 스토리지 계정을 기반으로 하여 이 연결 문자열 값을 구성하는 것이 좋습니다. 자세한 내용은 애플리케이션 구성을 참조하세요.

배포 컨테이너

Flex Consumption 요금제에서 실행되는 앱에 배포하려면 배포 원본으로 Azure Blob Storage의 컨테이너가 필요합니다. 기본 스토리지 계정을 사용하거나 별도의 스토리지 계정을 지정할 수 있습니다. 자세한 내용은 배포 설정 구성을 참조하세요.

배포에 사용되는 특정 컨테이너를 포함하여 앱을 만들 때 이 배포 계정을 이미 구성했어야 합니다. 배포 구성에 대한 자세한 내용은 배포 원본을 참조하세요.

이 예제에서는 스토리지 계정에서 컨테이너를 만드는 방법을 보여 줍니다.

resource blobServices 'blobServices' = if (!empty(containers)) {
  name: 'default'
  properties: {
    deleteRetentionPolicy: deleteRetentionPolicy
  }
  resource container 'containers' = [for container in containers: {
    name: container.name
    properties: {
      publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None'
    }
  }]
}

컨텍스트의 코드 조각은 이 배포 예제를 참조하세요.

다른 배포 설정은 앱 자체로 구성됩니다.

스토리지 로그 사용

스토리지 계정은 중요한 함수 앱 데이터에 사용되므로 해당 콘텐츠를 수정하기 위해 계정을 모니터링해야 합니다. 스토리지 계정을 모니터링하려면 Azure Storage에 대한 Azure Monitor 리소스 로그를 구성해야 합니다. 이 예제 섹션에서는 myLogAnalytics라는 Log Analytics 작업 영역이 이러한 로그의 대상으로 사용됩니다.

resource blobService 'Microsoft.Storage/storageAccounts/blobServices@2021-09-01' existing = {
  name:'default'
  parent:storageAccountName
}

resource storageDataPlaneLogs 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: '${storageAccountName}-logs'
  scope: blobService
  properties: {
    workspaceId: myLogAnalytics.id
    logs: [
      {
        category: 'StorageWrite'
        enabled: true
      }
    ]
    metrics: [
      {
        category: 'Transaction'
        enabled: true
      }
    ]
  }
}

이 동일한 작업 영역은 나중에 정의되는 Application Insights 리소스에도 사용할 수 있습니다. 이러한 로그 작업 방법을 포함한 자세한 내용은 Azure Storage 모니터링을 참조하세요.

Application Insights 만들기

함수 앱 실행을 모니터링하기 위해 Application Insights를 사용해야 합니다. 이제 Application Insights에는 공유할 수 있는 Azure Log Analytics 작업 영역이 필요합니다. 이러한 예제에서는 기존 작업 영역을 사용하고 있으며 작업 영역에 대한 정규화된 리소스 ID를 가지고 있다고 가정합니다. 자세한 내용은 Azure Log Analytics 작업 영역을 참조하세요.

이 예제 섹션에서 Application Insights 리소스는 Microsoft.Insights/components 형식과 web 종류로 정의됩니다.

resource applicationInsight 'Microsoft.Insights/components@2020-02-02' = {
  name: applicationInsightsName
  location: appInsightsLocation
  tags: tags
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: '<FULLY_QUALIFIED_RESOURCE_ID>'
  }
}

자세한 컨텍스트는 템플릿 리포지토리의 전체 main.bicep 파일을 참조하세요.

APPLICATIONINSIGHTS_CONNECTION_STRING 애플리케이션 설정을 사용하여 연결을 함수 앱에 제공해야 합니다. 자세한 내용은 애플리케이션 구성을 참조하세요.

이 문서의 예제에서는 만든 인스턴스에 대한 연결 문자열 값을 가져옵니다. 이전 버전에서는 APPINSIGHTS_INSTRUMENTATIONKEY를 대신 사용하여 계측 키를 설정할 수 있었지만 이 키는 더 이상 권장되지 않습니다.

호스팅 계획 만들기

Azure Functions Flex Consumption 요금제에서 호스트된 앱, Premium 요금제 또는 전용(앱 서비스) 요금제는 호스팅 요금제에 명시적으로 정의되어야 합니다.

Flex Consumption는 사용량 서버리스 청구 모델을 사용하는 요금을 지불하는 Linux 기반 호스팅 요금제 입니다. 이 요금제는 프라이빗 네트워킹, 인스턴스 메모리 크기 선택 및 향상된 관리 ID 지원을 지원합니다.

Flex Comsuption 사용량은 특별한 유형의 serverfarm 리소스입니다. FlexConsumptiontier 값을 가진 sku 속성의 Name 속성 값에 FC1(을)를 사용하여 지정할 수 있습니다.

이 예제 섹션에서는 Flex Consumption 요금제를 만듭니다.

resource flexFuncPlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: planName
  location: location
  tags: tags
  kind: 'functionapp'
  sku: {
    tier: 'FlexConsumption'
    name: 'FC1'
  }
  properties: {
    reserved: true
  }
}

자세한 컨텍스트는 Flex Consumption 요금제 샘플 리포지토리의 전체 function.bicep 파일을 참조하세요.

Flex Consumption 요금제는 현재 Linux만 지원하므로 reserved 속성도 true(으)로 설정해야 합니다.

프리미엄 계획은 소비 계획과 동일한 크기 조정을 제공하지만 전용 리소스 및 추가 기능을 포함합니다. 자세한 정보는 Azure Functions 프리미엄 계획을 참조하세요.

프리미엄 계획은 특수한 유형의 serverfarm 리소스입니다. 이는 sku 속성의 Name 속성 값에 대해 EP1, EP2 또는 EP3을 사용하여 지정할 수 있습니다. Functions 호스팅 계획을 정의하는 방법은 함수 앱이 Windows에서 실행되는지 아니면 Linux에서 실행되는지에 따라 달라집니다. 이 예제 섹션에서는 EP1 플랜을 만듭니다.

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: hostingPlanName
  location: location
  sku: {
    name: 'EP1'
    tier: 'ElasticPremium'
    family: 'EP'
  }
  kind: 'elastic'
  properties: {
    maximumElasticWorkerCount: 20
  }
}

자세한 컨텍스트는 템플릿 리포지토리의 전체 main.bicep 파일을 참조하세요.

sku 개체에 대한 자세한 내용은 SkuDefinition을 참조하거나 예제 템플릿을 검토하세요.

전용(App Service) 플랜에서 함수 앱은 웹앱과 비슷하게 App Service 요금제의 기본, 표준 및 프리미엄 SKU의 전용 VM에서 실행됩니다. 자세한 내용은 전용 플랜을 참조하세요.

샘플 Bicep 파일/Azure Resource Manager 템플릿은 Azure App Service 요금제의 함수 앱을 참조하세요.

Functions에서 전용 계획은 serverfarm 리소스로 정의되는 일반 App Service 계획일 뿐입니다. 최소한 name 값을 제공해야 합니다. 지원되는 플랜 이름 목록은 전용 플랜에 지원되는 현재 값 목록에 대한 az appservice plan create--sku 설정을 참조하세요.

호스팅 계획을 정의하는 방법은 함수 앱이 Windows에서 실행되는지 아니면 Linux에서 실행되는지에 따라 달라집니다.

resource hostingPlanName 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: hostingPlanName
  location: location
  sku: {
    tier: 'Standard'
    name: 'S1'
    size: 'S1'
    family: 'S'
    capacity: 1
  }
}

자세한 컨텍스트는 템플릿 리포지토리의 전체 main.bicep 파일을 참조하세요.

호스팅 계획 만들기

사용량 호스팅 계획 리소스는 명시적으로 정의할 필요가 없습니다. 이 리소스 정의를 건너뛰면 함수 앱 리소스 자체를 만들 때 지역별로 플랜이 자동으로 만들어지거나 선택됩니다.

사용량 플랜을 computeModesku 속성에 대해 Dynamic 값을 사용하여 지정하는 특수 형식의 serverfarm 리소스로 명시적으로 정의할 수 있습니다. 이 예제 섹션에서는 사용량 플랜을 명시적으로 정의하는 방법을 보여줍니다. 호스팅 계획을 정의하는 방법은 함수 앱이 Windows에서 실행되는지 아니면 Linux에서 실행되는지에 따라 달라집니다.

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: hostingPlanName
  location: location
  sku: {
    name: 'Y1'
    tier: 'Dynamic'
    size: 'Y1'
    family: 'Y'
    capacity: 0
  }
  properties: {
    computeMode: 'Dynamic'
  }
}

자세한 컨텍스트는 템플릿 리포지토리의 전체 main.bicep 파일을 참조하세요.

Kubernetes 환경

Azure Functions는 코드 프로젝트 또는 컨테이너화된 함수 앱으로 Azure Arc 지원 Kubernetes에 배포할 수 있습니다.

앱 및 계획 리소스를 만들려면 Azure Arc 지원 Kubernetes 클러스터에 대해 이미 App Service Kubernetes 환경이 만들어져 있어야 합니다. 이 문서의 예제에서는 배포할 사용자 지정 위치(customLocationId) 및 App Service Kubernetes 환경(kubeEnvironmentId)의 리소스 ID가 있다고 가정합니다. 다음 예제와 같이 설정됩니다.

param kubeEnvironmentId string
param customLocationId string

사이트와 계획 둘 다 extendedLocation 필드를 통해 사용자 지정 위치를 참조해야 합니다. 이 잘린 예제와 같이 extendedLocationkindlocation에 대한 피어로 properties 외부에 있습니다.

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  ...
  {
    extendedLocation: {
      name: customLocationId
    }
  }
}

플랜 리소스는 Linux 배포이므로 Kubernetes(K1) 값을 SKU에 사용하고, kind 필드는 linux,kubernetes이고, reserved 속성은 true이어야 합니다. 또한 extendedLocationkubeEnvironmentProfile.id를 각각 사용자 지정 위치 ID와 Kubernetes 환경 ID로 설정해야 합니다. 다음 예제 섹션과 같습니다.

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: hostingPlanName
  location: location
  kind: 'linux,kubernetes'
  sku: {
    name: 'K1'
    tier: 'Kubernetes'
  }
  extendedLocation: {
    name: customLocationId
  }
  properties: {
    kubeEnvironmentProfile: {
      id: kubeEnvironmentId
    }
    reserved: true
  }
}

함수 앱 만들기

함수 앱 리소스는 최소한 functionapp을 포함하는 Microsoft.Web/siteskind 형식의 리소스에서 정의됩니다.

함수 앱 리소스를 정의하는 방법은 Linux에서 호스트하는지 아니면 Windows에서 호스트하는지에 따라 달라집니다.

Windows에서 실행할 때 필요한 애플리케이션 설정 목록은 애플리케이션 구성을 참조하세요. 샘플 Bicep 파일/Azure Resource Manager 템플릿은 사용량 플랜에서 Windows에 호스트되는 함수 앱 템플릿을 참조하세요.

Windows에서 실행할 때 필요한 애플리케이션 설정 목록은 애플리케이션 구성을 참조하세요.

Flex Consumption는 Bicep 및 ARM 템플릿 배포에 사용되는 많은 표준 애플리케이션 설정 및 사이트 구성 속성을 대체합니다. 자세한 내용은 애플리케이션 구성을 참조하세요.

resource flexFuncApp 'Microsoft.Web/sites@2023-12-01' = {
  name: appName
  location: location
  tags: tags
  kind: 'functionapp,linux'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    serverFarmId: flexFuncPlan.id
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage__accountName'
          value: storage.name
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsights.properties.ConnectionString
        }
      ]
    }
    functionAppConfig: {
      deployment: {
        storage: {
          type: 'blobContainer'
          value: '${storage.properties.primaryEndpoints.blob}${deploymentStorageContainerName}'
          authentication: {
            type: 'SystemAssignedIdentity'
          }
        }
      }
      scaleAndConcurrency: {
        maximumInstanceCount: maximumInstanceCount
        instanceMemoryMB: instanceMemoryMB
      }
      runtime: { 
        name: functionAppRuntime
        version: functionAppRuntimeVersion
      }
    }
  }
}

자세한 컨텍스트는 Flex Consumption 요금제 샘플 리포지토리의 전체 function.bicep 파일을 참조하세요.

참고 항목

필요에 따라 사용량 플랜을 정의하도록 선택하는 경우 플랜의 리소스 ID를 가리키도록 앱에서 serverFarmId 속성을 설정해야 합니다. 함수 앱에 계획도 참조하는 dependsOn 설정이 있는지 확인합니다. 플랜을 명시적으로 정의하지 않은 경우 플랜을 만듭니다.

플랜의 리소스 ID를 가리키도록 앱에서 serverFarmId 속성을 설정합니다. 함수 앱에 계획도 참조하는 dependsOn 설정이 있는지 확인합니다.

resource functionAppName_resource 'Microsoft.Web/sites@2022-03-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    serverFarmId: hostingPlanName.id
    siteConfig: {
      appSettings: [
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: applicationInsightsName.properties.ConnectionString
        }
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'WEBSITE_CONTENTSHARE'
          value: toLower(functionAppName)
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'node'
        }
        {
          name: 'WEBSITE_NODE_DEFAULT_VERSION'
          value: '~14'
        }
      ]
    }
  }
}

전체 엔드투엔드 예제는 이 main.bicep 파일을 참조하세요.

resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    serverFarmId: hostingPlan.id
    siteConfig: {
      alwaysOn: true
      appSettings: [
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: applicationInsightsName.properties.ConnectionString
        }
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'node'
        }
        {
          name: 'WEBSITE_NODE_DEFAULT_VERSION'
          value: '~14'
        }
      ]
    }
  }
}

전체 엔드투엔드 예제는 이 main.bicep 파일을 참조하세요.

배포 원본

Bicep 파일 또는 ARM 템플릿은 필요에 따라 함수 코드에 대한 배포를 정의할 수도 있습니다. 여기에는 다음 메서드가 포함될 수 있습니다.

배포 원본

Flex Consumption 요금제에서 프로젝트 코드는 Blob Storage 컨테이너에 게시된 압축 패키지에서 배포됩니다. 자세한 내용은 배포를 참조하세요. 배포, 인증 방법 및 자격 증명에 사용되는 특정 스토리지 계정 및 컨테이너는 사이트에 대한 functionAppConfig.deployment.storageproperties 요소에서 설정됩니다. 컨테이너 및 애플리케이션 설정은 앱을 만들 때 존재해야 합니다. 스토리지 컨테이너를 만드는 방법의 예는 배포 컨테이너를 참조하세요.

이 예제에서는 시스템 할당 관리 ID를 사용하여 지정된 Blob Storage 컨테이너에 액세스합니다. 이 컨테이너는 배포의 다른 위치에서 만들어집니다.

deployment: {
  storage: {
    type: 'blobContainer'
    value: '${storage.properties.primaryEndpoints.blob}${deploymentStorageContainerName}'
    authentication: {
      type: 'SystemAssignedIdentity'
    }
  }
}

관리 ID를 사용하는 경우 다음 예제와 같이 함수 앱에서 ID를 사용하여 스토리지 계정에 액세스할 수 있도록 설정해야 합니다.

// Allow access from function app to storage account using a managed identity
resource storageRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
  name: guid(storage.id, storageRoleDefinitionId)
  scope: storage
  properties: {
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', storageRoleDefinitionId)
    principalId: flexFuncApp.identity.principalId
    principalType: 'ServicePrincipal'
  }
}

전체 참조 예제는 이 Bicep 파일을 참조하세요.

관리 ID 대신 연결 문자열을 사용하는 경우 대신 authentication.type(을)를 StorageAccountConnectionString(으)로 설정하고 authentication.storageAccountConnectionStringName(을)를 배포 스토리지 계정 연결 문자열이 포함된 애플리케이션 설정의 이름으로 설정해야 합니다.

배포 원본

Bicep 파일 또는 ARM 템플릿은 필요에 따라 zip 배포 패키지를 사용하여 함수 코드에 대한 배포를 정의할 수도 있습니다.

Azure Resource Manager를 사용하여 애플리케이션을 성공적으로 배포하려면 Azure에서 리소스가 배포되는 방식을 이해하는 것이 중요합니다. 대부분의 예제에서 최상위 구성은 siteConfig를 사용하여 적용됩니다. Functions 런타임 및 배포 엔진에 정보를 전달하기 때문에 최상위 수준에서 이러한 구성을 설정하는 것이 중요합니다. 자식 sourcecontrols/web 리소스가 적용되기 전에 최상위 정보가 필요합니다. 이러한 설정은 자식 수준 config/appSettings 리소스에서 구성할 수 있지만 경우에 따라 config/appSettings가 적용되기 전에 함수 앱을 배포해야 합니다.

Zip 배포 패키지

Zip 배포는 함수 앱 코드를 배포하는 데 권장되는 방법입니다. 기본적으로 zip 배포를 사용하는 함수는 배포 패키지 자체에서 실행됩니다. 배포 패키지 요구 사항을 포함한 자세한 내용은 Azure Functions에 대한 Zip 배포를 참조하세요. 리소스 배포 자동화를 사용하는 경우 Bicep 또는 ARM 템플릿에서 .zip 배포 패키지를 참조할 수 있습니다.

템플릿에서 zip 배포를 사용하려면 앱의 WEBSITE_RUN_FROM_PACKAGE 설정을 1로 설정하고 /zipDeploy 리소스 정의를 포함합니다.

Linux의 사용량 플랜의 경우 이 예제 템플릿과 같이 WEBSITE_RUN_FROM_PACKAGE 설정에서 직접 배포 패키지의 URI를 대신 설정합니다.

다음 예제에서는 zip 배포 원본을 기존 앱에 추가합니다.

@description('The name of the function app.')
param functionAppName string

@description('The location into which the resources should be deployed.')
param location string = resourceGroup().location

@description('The zip content url.')
param packageUri string

resource functionAppName_ZipDeploy 'Microsoft.Web/sites/extensions@2021-02-01' = {
  name: '${functionAppName}/ZipDeploy'
  location: location
  properties: {
    packageUri: packageUri
  }
}

zip 배포 리소스를 템플릿에 포함하는 경우 다음 사항에 유의하세요.

  • packageUri는 Functions에서 액세스할 수 있는 위치여야 합니다. SAS(공유 액세스 서명)를 통해 Azure Blob Storage를 사용하는 것이 좋습니다. SAS가 만료되면 배포를 위해 Functions에서 더 이상 공유에 액세스할 수 없습니다. SAS를 다시 생성하는 경우 WEBSITE_RUN_FROM_PACKAGE 설정을 새 URI 값으로 업데이트해야 합니다.

  • WEBSITE_RUN_FROM_PACKAGE을(를) URI로 설정할 때는 트리거를 수동으로 동기화해야 합니다.

  • 설정을 추가하거나 업데이트하는 경우 항상 필요한 모든 애플리케이션 설정을 appSettings 컬렉션에 지정해야 합니다. 명시적으로 설정되지 않은 기존 설정은 업데이트에서 제거됩니다. 자세한 내용은 애플리케이션 구성을 참조하세요.

  • Functions는 패키지 배포에 대한 웹 배포(msdeploy)를 지원하지 않습니다. 대신 배포 파이프라인 및 자동화에서 zip 배포를 사용해야 합니다. 자세한 내용은 Azure Functions에 대한 Zip 배포를 참조하세요.

원격 빌드

배포 프로세스에서는 사용하는 .zip 파일 또는 zip 배포에 실행 준비 앱이 포함되어 있다고 가정합니다. 즉, 기본적으로 사용자 지정이 실행되지 않습니다.

앱을 원격으로 다시 빌드해야 하는 시나리오가 있습니다. 이러한 예 중 하나는 Windows 컴퓨터에서 개발한 Python 또는 Node.js 앱에 Linux 관련 패키지를 포함해야 하는 경우입니다. 이 경우 zip 배포 후 코드에서 원격 빌드를 수행하도록 Functions를 구성할 수 있습니다.

원격 빌드를 요청하는 방법은 배포하는 운영 체제에 따라 달라집니다.

앱이 Windows에 배포되면 언어별 명령(예: C# 앱의 경우 dotnet restore, Node.js 앱의 경우 npm install)이 실행됩니다.

연속 통합을 통해 가져오는 것과 동일한 빌드 프로세스를 사용하도록 설정하려면 배포 코드의 애플리케이션 설정에서 SCM_DO_BUILD_DURING_DEPLOYMENT=true를 추가하고 WEBSITE_RUN_FROM_PACKAGE를 완전히 제거합니다.

Linux 컨테이너

컨테이너화된 함수 앱을 Azure Functions 프리미엄 또는 전용 플랜에 배포하는 경우 다음을 수행해야 합니다.

자세한 내용은 애플리케이션 구성을 참조하세요.

resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    serverFarmId: hostingPlan.id
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'node'
        }
        {
          name: 'WEBSITE_NODE_DEFAULT_VERSION'
          value: '~14'
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'DOCKER_REGISTRY_SERVER_URL'
          value: dockerRegistryUrl
        }
        {
          name: 'DOCKER_REGISTRY_SERVER_USERNAME'
          value: dockerRegistryUsername
        }
        {
          name: 'DOCKER_REGISTRY_SERVER_PASSWORD'
          value: dockerRegistryPassword
        }
        {
          name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE'
          value: 'false'
        }
      ]
      linuxFxVersion: 'DOCKER|myacr.azurecr.io/myimage:mytag'
    }
  }
  dependsOn: [
    storageAccount
  ]
}

컨테이너화된 함수를 Azure Container Apps에를 배포하는 경우 템플릿에서 다음을 수행해야 합니다.

  • kind 필드를 functionapp,linux,container,azurecontainerapps 값으로 설정합니다.
  • managedEnvironmentId 사이트 속성을 Container Apps 환경의 정규화된 URI로 설정합니다.
  • 사이트와 동시에 Microsoft.App/managedEnvironments 리소스를 만들 때 리소스 링크를 사이트의 dependsOn 컬렉션에 추가합니다.

프라이빗 컨테이너 레지스트리에서 기존 Container Apps 환경으로 배포된 컨테이너화된 함수 앱의 정의는 다음 예제와 같습니다.

resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: functionAppName
  kind: 'functionapp,linux,container,azurecontainerapps'
  location: location
  properties: {
    serverFarmId: hostingPlanName
    siteConfig: {
      linuxFxVersion: 'DOCKER|myacr.azurecr.io/myimage:mytag'
      appSettings: [
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: applicationInsightsName.properties.ConnectionString
        }
      ]
    }
    managedEnvironmentId: managedEnvironmentId
  }
  dependsOn: [
    storageAccount
    hostingPlan
  ]
}

함수를 Azure Arc에 배포하는 경우 함수 앱 리소스의 kind 필드에 설정하는 값은 배포 유형에 따라 달라집니다.

배포 유형 kind 필드 값
코드만 배포 functionapp,linux,kubernetes
컨테이너 배포 functionapp,linux,kubernetes,container

호스팅 계획 리소스에서와 마찬가지로 customLocationId도 설정해야 합니다.

.NET 6 빠른 시작 이미지를 사용하는 컨테이너화된 함수 앱의 정의는 다음 예제와 같습니다.

resource functionApp 'Microsoft.Web/sites@2022-03-01' = {
  name: functionAppName
  kind: 'kubernetes,functionapp,linux,container'
  location: location
  extendedLocation: {
    name: customLocationId
  }
  properties: {
    serverFarmId: hostingPlanName
    siteConfig: {
      linuxFxVersion: 'DOCKER|mcr.microsoft.com/azure-functions/4-dotnet-isolated6.0-appservice-quickstart'
      appSettings: [
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value}'
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: applicationInsightsName.properties.ConnectionString
        }
      ]
      alwaysOn: true
    }
  }
  dependsOn: [
    storageAccount
    hostingPlan
  ]
}

애플리케이션 구성

Flex 소비 계획에서는 다음 두 가지 유형의 속성을 사용하여 Azure에서 함수 앱을 구성합니다.

구성 Microsoft.Web/sites 속성
애플리케이션 구성 functionAppConfig
애플리케이션 설정 siteConfig.appSettings 컬렉션

이러한 구성은 functionAppConfig에서 유지 관리됩니다.

동작 functionAppConfig에서 설정
언어 런타임 runtime.name
언어 버전 runtime.version
최대 인스턴스 수 scaleAndConcurrency.maximumInstanceCount
인스턴스 메모리 크기 scaleAndConcurrency.instanceMemoryMB
배포 원본 deployment

Flex Consumption 요금제는 다음과 같은 애플리케이션 설정도 지원합니다.

애플리케이션 구성

Functions는 Azure에서 함수 앱을 구성하기 위한 다음 옵션을 제공합니다.

구성 Microsoft.Web/sites 속성
사이트 설정 siteConfig
애플리케이션 설정 siteConfig.appSettings 컬렉션

이러한 사이트 설정은 siteConfig 속성에 필요합니다.

다음 애플리케이션 설정은 특정 운영 체제 및 호스팅 옵션에 필요하거나 권장됩니다.

다음 애플리케이션 설정은 컨테이너 배포에 필요합니다.

다음 설정은 프라이빗 컨테이너 레지스트리에서 배포하는 경우에만 필요합니다.

Bicep 파일 또는 ARM 템플릿을 사용하여 사이트 및 애플리케이션 설정 작업을 사용하는 경우 다음 고려 사항에 유의하세요.

  • 자동화된 배포에서 WEBSITE_CONTENTSHARE를 설정해야 하는 경우에 대한 중요한 고려 사항이 있습니다. 자세한 지침은 WEBSITE_CONTENTSHARE 참조를 참조하세요.
  • 이 문서의 예제에서와 같이 항상 애플리케이션 설정을 만드는 Microsoft.Web/sites 리소스의 siteConfig/appSettings 컬렉션으로 정의해야 합니다. 이 정의는 함수 앱을 실행하는 데 필요한 설정을 초기 시작 시 사용할 수 있도록 보장합니다.

  • 템플릿을 사용하여 애플리케이션 설정을 추가하거나 업데이트하는 경우 모든 기존 설정을 업데이트에 포함해야 합니다. 기본 업데이트 REST API 호출에서 전체 /config/appsettings 리소스를 대체하므로 이 작업을 수행해야 합니다. 기존 설정을 제거하면 함수 앱이 실행되지 않습니다. 개별 애플리케이션 설정을 프로그래밍 방식으로 업데이트하려면 Azure CLI, Azure PowerShell 또는 Azure Portal을 대신 사용하여 이러한 변경을 수행할 수 있습니다. 자세한 내용은 애플리케이션 설정 작업을 참조하세요.

슬롯 배포

Functions를 사용하면 다양한 버전의 코드를 함수 앱의 고유한 엔드포인트에 배포할 수 있습니다. 이 옵션을 사용하면 프로덕션에서 실행되는 함수에 영향을 주지 않고 함수 업데이트를 더 쉽게 개발하고, 유효성 검사를 하고 및 배포할 수 있습니다. 배포 슬롯은 Azure App Service의 기능입니다. 사용 가능한 슬롯 수는 호스팅 계획에 따라 달라집니다. 자세한 내용은 Azure Functions 배포 슬롯 기능을 참조하세요.

슬롯 리소스는 함수 앱 리소스(Microsoft.Web/sites)와 동일한 방식으로 정의되지만 대신 Microsoft.Web/sites/slots 리소스 식별자를 사용합니다. 프리미엄 플랜에서 프로덕션 슬롯과 스테이징 슬롯을 모두 만드는 배포 예제(Bicep 및 ARM 템플릿 모두에서)는 배포 슬롯이 있는 Azure Function 앱을 참조하세요.

템플릿을 사용하여 슬롯을 교환하는 방법에 대한 자세한 내용은 Resource Manager 템플릿을 사용하여 자동화를 참조하세요.

슬롯 배포 작업을 사용하는 경우 다음 고려 사항에 유의하세요.

  • 배포 슬롯 정의에서 WEBSITE_CONTENTSHARE 설정을 명시적으로 설정하지 않습니다. 이 설정은 앱이 배포 슬롯에 만들어질 때 만들어집니다.

  • 슬롯을 교환하는 경우 일부 애플리케이션 설정은 교환되는 코드가 아니라 슬롯에 유지된다는 점에서 "고정"된 설정으로 간주됩니다. 이러한 슬롯 설정"slotSetting":true를 템플릿의 특정 애플리케이션 설정 정의에 포함하여 정의할 수 있습니다. 자세한 내용은 설정 관리를 참조하세요.

보안 배포

가상 네트워크와 통합하여 하나 이상의 리소스가 보호되는 배포에서 함수 앱을 만들 수 있습니다. 함수 앱에 대한 가상 네트워크 통합은 Microsoft.Web/sites/networkConfig 리소스에서 정의됩니다. 이 통합은 참조되는 함수 앱과 가상 네트워크 리소스에 따라 달라집니다. 함수 앱은 프라이빗 엔드포인트 및 경로와 같은 다른 프라이빗 네트워킹 리소스를 사용할 수도 있습니다. 자세한 내용은 Azure Functions 네트워킹 옵션을 참조하세요.

이러한 프로젝트는 네트워크 액세스 제한을 포함하여 가상 네트워크에 함수 앱을 배포하는 방법에 대한 Bicep 기반 예제를 제공합니다.

보안 스토리지 계정을 사용하는 배포를 만드는 경우 WEBSITE_CONTENTSHARE 설정을 명시적으로 설정하고 이 설정에 명명된 파일 공유 리소스를 만들어야 합니다. 이 예제(ARM 템플릿|Bicep 파일)와 같이 WEBSITE_CONTENTSHARE 값을 사용하여 Microsoft.Storage/storageAccounts/fileServices/shares 리소스를 만들어야 합니다. 또한 vnetContentShareEnabled 사이트 속성을 true로 설정해야 합니다.

참고 항목

이러한 설정이 보안 스토리지 계정을 사용하는 배포의 일부가 아닌 경우 배포 유효성 검사 중에 Could not access storage account using provided connection string 오류가 표시됩니다.

다음 프로젝트에서는 네트워크 액세스 제한을 포함하여 함수 앱을 가상 네트워크에 배포하는 방법에 대한 Bicep 및 ARM 템플릿 예제를 모두 제공합니다.

제한된 시나리오 설명
가상 네트워크 통합을 사용하는 함수 앱 만들기 함수 앱은 해당 네트워크의 리소스에 대한 모든 권한이 있는 가상 네트워크에 만들어집니다. 함수 앱에 대한 인바운드 및 아웃바운드 액세스는 제한되지 않습니다. 자세한 내용은 가상 네트워크 통합을 참조하세요.
보안 스토리지 계정에 액세스하는 함수 앱 만들기 만든 함수 앱은 Functions에서 프라이빗 엔드포인트를 사용하여 액세스하는 보안 스토리지 계정을 사용합니다. 자세한 내용은 스토리지 계정을 가상 네트워크로 제한을 참조하세요.
프라이빗 엔드포인트를 모두 사용하는 함수 앱 및 스토리지 계정 만들기 만든 함수 앱은 프라이빗 엔드포인트를 통해서만 액세스할 수 있으며, 프라이빗 엔드포인트를 사용하여 스토리지 리소스에 액세스합니다. 자세한 내용은 프라이빗 엔드포인트를 참조하세요.

제한된 네트워크 설정

함수 앱에 네트워크 제한이 있는 경우 다음 설정을 사용해야 할 수도 있습니다.

설정 설명
WEBSITE_CONTENTOVERVNET 1 스토리지 계정이 가상 네트워크로 제한되면 함수 앱의 크기를 조정할 수 있도록 하는 애플리케이션 설정입니다. 자세한 내용은 스토리지 계정을 가상 네트워크로 제한을 참조하세요.
vnetrouteallenabled 1 함수 앱의 모든 트래픽에서 가상 네트워크를 사용하도록 강제하는 사이트 설정입니다. 자세한 내용은 지역 가상 네트워크 통합을 참조하세요. 이 사이트 설정은 WEBSITE_VNET_ROUTE_ALL 애플리케이션 설정을 대체합니다.

네트워크 제한에 대한 고려 사항

프라이빗 엔드포인트를 통한 스토리지 계정 액세스를 제한하는 경우 포털 또는 가상 네트워크 외부의 디바이스를 통해 스토리지 계정에 액세스할 수 없습니다. 기본 네트워크 액세스 규칙을 관리하여 스토리지 계정의 보안 IP 주소 또는 가상 네트워크에 대한 액세스 권한을 부여할 수 있습니다.

함수 액세스 키

호스트 수준 함수 액세스 키는 Azure 리소스로 정의됩니다. 즉, ARM 템플릿 및 Bicep 파일에서 호스트 키를 만들고 관리할 수 있습니다. 호스트 키는 Microsoft.Web/sites/host/functionKeys 형식의 리소스로 정의됩니다. 이 예제에서는 함수 앱을 만들 때 my_custom_key 이라는 호스트 수준 액세스 키를 만듭니다.

resource functionKey 'Microsoft.Web/sites/host/functionKeys@2022-09-01' = {
  name: '${parameters('name')}/default/my_custom_key'
  properties: {
    name: 'my_custom_key'
  }
  dependsOn: [
    resourceId('Microsoft.Web/Sites', parameters('name'))
  ]
}

이 예제에서 name 매개 변수는 새 함수 앱의 이름입니다. 새 함수 앱을 사용하여 키가 생성되도록 하려면 dependsOn 설정을 포함해야 합니다. 마지막으로 호스트 키의 properties 개체에는 특정 키를 설정하는 데 사용할 수 있는 value 속성도 포함될 수 있습니다.

value 속성을 설정하지 않으면 리소스를 만들 때 함수가 자동으로 새 키를 생성하는 것이 좋습니다. 액세스 키 작업에 대한 보안 모범 사례를 비롯한 액세스 키에 대한 자세한 내용은 Azure Functions에서 액세스 키 작업을 참조하세요.

템플릿 만들기

Bicep 또는 ARM 템플릿을 사용하는 전문가는 간단한 텍스트 편집기를 사용하여 배포를 수동으로 코딩할 수 있습니다. 나머지 사용자에게는 개발 프로세스를 더 쉽게 만드는 몇 가지 방법이 있습니다.

  • Visual Studio Code: Bicep 파일ARM 템플릿 작업을 사용하는 데 도움이 되는 확장이 있습니다. 이러한 도구를 사용하여 코드가 올바른지 확인하고 몇 가지 기본 유효성 검사를 제공할 수 있습니다.

  • Azure Portal: 포털에서 함수 앱 및 관련 리소스를 만들면 최종 검토 + 만들기 화면에 자동화 템플릿 다운로드 링크가 있습니다.

    Azure Portal의 Azure Functions 만들기 프로세스에서 템플릿 링크를 다운로드합니다.

    이 링크는 포털에서 선택한 옵션에 따라 생성된 ARM 템플릿을 보여줍니다. 이 템플릿은 많은 새 리소스가 있는 함수 앱을 만들 때 약간 복잡해 보일 수 있습니다. 그러나 ARM 템플릿의 모양에 대한 좋은 참조를 제공할 수 있습니다.

템플릿 유효성 검사

배포 템플릿 파일을 수동으로 만드는 경우 배포하기 전에 템플릿의 유효성을 검사해야 합니다. 모든 배포 메서드는 템플릿 구문의 유효성을 검사하고, 다음 JSON 형식 예제와 같이 validation failed 오류 메시지를 발생시킵니다.

{"error":{"code":"InvalidTemplate","message":"Deployment template validation failed: 'The resource 'Microsoft.Web/sites/func-xyz' is not defined in the template. Please see https://aka.ms/arm-template for usage details.'.","additionalInfo":[{"type":"TemplateViolation","info":{"lineNumber":0,"linePosition":0,"path":""}}]}}

다음 메서드는 배포하기 전에 템플릿의 유효성을 검사하는 데 사용할 수 있습니다.

deploymentMode: 'Validation'를 사용하는 다음 Azure 리소스 그룹 배포 v2 작업에서는 템플릿의 유효성을 검사하도록 Azure Pipelines에 지시합니다.

- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    deploymentScope: 'Resource Group'
    subscriptionId: # Required subscription ID
    action: 'Create Or Update Resource Group'
    resourceGroupName: # Required resource group name
    location: # Required when action == Create Or Update Resource Group
    templateLocation: 'Linked artifact'
    csmFile: # Required when  TemplateLocation == Linked Artifact
    csmParametersFile: # Optional
    deploymentMode: 'Validation'

테스트 리소스 그룹을 만들어 실행 전배포 오류를 확인할 수도 있습니다.

템플릿 배포

다음 방법 중 하나를 사용하여 Bicep 파일 및 템플릿을 배포할 수 있습니다.

Azure에 배포 단추

참고 항목

이 방법은 현재 Bicep 파일 배포를 지원하지 않습니다.

<url-encoded-path-to-azuredeploy-json>을 GitHub에 있는 azuredeploy.json 파일의 원시 경로에 대한 URL 인코딩 버전으로 바꿉니다.

markdown을 사용하는 예는 다음과 같습니다.

[![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>)

HTML을 사용하는 예는 다음과 같습니다.

<a href="https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>" target="_blank"><img src="https://azuredeploy.net/deploybutton.png"></a>

PowerShell을 사용하여 배포

다음 PowerShell 명령은 리소스 그룹을 만들고 필요한 리소스를 사용하여 함수 앱을 만드는 Bicep 파일 또는 ARM 템플릿을 배포합니다. 로컬에서 실행하려면 Azure PowerShell이 설치되어 있어야 합니다. 로그인하려면 Connect-AzAccount를 실행합니다.

# Register Resource Providers if they're not already registered
Register-AzResourceProvider -ProviderNamespace "microsoft.web"
Register-AzResourceProvider -ProviderNamespace "microsoft.storage"

# Create a resource group for the function app
New-AzResourceGroup -Name "MyResourceGroup" -Location 'West Europe'

# Deploy the template
New-AzResourceGroupDeployment -ResourceGroupName "MyResourceGroup" -TemplateFile main.bicep  -Verbose

이 배포를 테스트하려면 Windows에서 소비 계획에 함수 앱을 만드는 이와 같은 템플릿을 사용하면 됩니다.

다음 단계

Azure Functions를 개발하고 구성하는 방법에 대해 자세히 알아봅니다.