DevOps

Azure Bicep ์„ค๋ช…

๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ์˜ ์ตœ๊ณ  ์ˆ˜์ค€ IaC (Infrastructure as Code)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Azure ํด๋ผ์šฐ๋“œ ๋ฆฌ์†Œ์Šค ํ”„๋กœ๋น„์ €๋‹

  • #cloud
  • #iac
  • #infra

Bicep์€ Azure ๋„ค์ดํ‹ฐ๋ธŒ IaC(Infrastructure as Code) ์†”๋ฃจ์…˜์œผ๋กœ, ARM ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ํ”„๋กœ๋น„์ €๋‹์„ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ฝ๊ณ  ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์šด ์„ ์–ธ์  ๋„๋ฉ”์ธ ํŠน์ • ์–ธ์–ด(DSL)์ž…๋‹ˆ๋‹ค.

๋ถ€์ธ ์„ฑ๋ช…

ํ•œ๊ตญ์–ด ์‹ค๋ ฅ์ด ๋ถ€์ ํ•˜์—ฌ ์ด ๊ธ€์ด ๊ตฌ๊ธ€ ๋ฒˆ์—ญ๊ธฐ๋ฅผ ์ฃผ๋กœ ํ™œ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€์ •ํ™•ํ•œ ๋ฌธ๋ฒ•๊ณผ ์–ดํœ˜๊ฐ€ ์žˆ์„์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์  ์–‘ํ•ด ๋ถ€ํƒ๋“œ๋ฆฌ๋ฉฐ, ์ถ”ํ›„์— ๋‹ค์‹œ ๊ฒ€ํ† ํ•˜์—ฌ ์ˆ˜์ •ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์„ค์น˜

Bicep ๊ด€๋ จ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Azure CLI๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด az version ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ์„ค์น˜๋œ Azure CLI ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ JSON ํ˜•์‹์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

{
  "azure-cli": "2.77.0",
  "azure-cli-core": "2.77.0",
  "azure-cli-telemetry": "1.1.0",
  "extensions": {}
}

๊ทธ ํ›„, bicep install ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Bicep ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

az bicep install

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

Installing Bicep CLI v0.37.4...
The configuration value of bicep.use_binary_from_path has been set to 'false'.
Successfully installed Bicep CLI to "C:\Users\User\.azure\bin\bicep.exe".

์„ค์น˜๋œ ๋ฒ„์ „์„ ํ™•์ธํ•˜๋ ค๋ฉด bicep version ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

az bicep version

์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•˜์„ธ์š”.

az bicep upgrade

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

Bicep์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ตฌ๋ฌธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. resource ํ‚ค์›Œ๋“œ๋Š” ๋’ค๋”ฐ๋ฅด๋Š” ๋‚ด์šฉ์ด ๋ฆฌ์†Œ์Šค ์„ ์–ธ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. <Variable>์€ ํ”„๋กœ๋น„์ €๋‹๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ €์žฅํ•˜๋ฉฐ, ์Šคํฌ๋ฆฝํŠธ์—์„œ ์ดํ›„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <ResourceType>๋Š” ์œ ํšจํ•œ Azure ๋ฆฌ์†Œ์Šค ์œ ํ˜•์œผ๋กœ, ํ…œํ”Œ๋ฆฟ ํŽ˜์ด์ง€์˜ ์ฐธ์กฐ ์„น์…˜์—์„œ ํ•ด๋‹น ๋ฒ”์ฃผ๋ณ„๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <DateVersion>์€ ๋ฆฌ์†Œ์Šค ํ”„๋กœ๋น„์ €๋‹์— ์‚ฌ์šฉํ•  API ๋ฒ„์ „์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฐ ์„ ์–ธ ๋ธ”๋ก ๋‚ด์—์„œ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํ•ด๋‹น ๊ฐ’์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

resource <Variable> '<ResourceType>@<DateVersion>' = {
  parameter: value
  parameter2: value2
  ...
}

๋‹ค์Œ์€ ์Šคํ† ๋ฆฌ์ง€ ๊ณ„์ •์„ ์„ ์–ธํ•˜๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

main.bicep
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: 'mydemostorage'
  location: 'eastus'
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}

์ด ํŒŒ์ผ์€ deployment group create ๋ช…๋ น์„ ์‹คํ–‰ํ•˜์—ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <existing-resource-group>์€ ๊ธฐ์กด ๋ฆฌ์†Œ์Šค ๊ทธ๋ฃน์˜ ์ด๋ฆ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

az deployment group create \
  --template-file main.bicep \
  --resource-group <existing-resource-group>

์œ„ ๋ช…๋ น์–ด๋Š” main.bicep ํŒŒ์ผ์„ ๋ฆฌ์†Œ์Šค ๊ทธ๋ฃน ์ˆ˜์ค€์—์„œ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— ์•„๋ž˜ ๋ช…๋ น์–ด๋Š” main.bicep ํŒŒ์ผ์„ ๊ตฌ๋… ์ˆ˜์ค€์—์„œ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.

az deployment sub create --location eastus --template-file main.bicep

๊ธฐ๋ณธ ๊ตฌ๋ฌธ

ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Bicep์€ ๋ณ€์ˆ˜, ๋ฐ˜๋ณต๋ฌธ, ๋ชจ๋“ˆ ๋ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ํšจ์œจ์ ์ด๊ณ  ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Bicep์—์„œ๋Š” ์„ธ๋ฏธ์ฝœ๋ก ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ณ€์ˆ˜

๋ณ€์ˆ˜๋Š” var ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ€์ˆ˜ ์„ ์–ธ ์‹œ ๋ฌธ์ž์—ด ๋ณด๊ฐ„์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ๋Š” ์Šคํ† ๋ฆฌ์ง€ ๊ณ„์ •์˜ ์œ„์น˜ ๋ณ€์ˆ˜๋ฅผ ์ด๋ฆ„ ์„ ์–ธ์˜ ์ผ๋ถ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

main.bicep
var storageAccountLocation = 'eastus'
var storageAccountName = 'mydemostorage${storageAccountLocation}'

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}

๋ณ€์ˆ˜์—๋Š” ์ง€์›๋˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋ณต๋ฌธ

๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๊ณ ๋„ ๋ฐฐ์—ด์„ ํ™œ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฐ์—ด์— ์ง€์ •๋œ ์—ฌ๋Ÿฌ ์œ„์น˜์— ๊ฐ๊ฐ ๋‹ค๋ฅธ ์Šคํ† ๋ฆฌ์ง€ ๊ณ„์ •์„ ์ƒ์„ฑํ•  ๋•Œ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด์˜ ์š”์†Œ๋Š” ์ค„ ๋ฐ”๊ฟˆ ๋ฌธ์ž(\n) ๋˜๋Š” ์‰ผํ‘œ(,)๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var regions1 = ['eastus', 'northeurope', 'uksouth']
var regions2 = [
  'southeastasia'
  'westeurope'
]

์•„๋ž˜๋Š” regions1 ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ eastus, northeurope, uksouth ์ง€์—ญ์— ์Šคํ† ๋ฆฌ์ง€ ๊ณ„์ •์„ ๋ฐฐํฌํ•˜๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์€ Azure ์ „์ฒด์—์„œ ๊ณ ์œ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ธ๋ฑ์Šค ๋˜๋Š” ์ง€์—ญ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฆ„์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = [for (region, index) in regions1: {
  name: 'mystorage${region}${index}'
  location: region
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}]

ํ•จ์ˆ˜

Bicep์€ ์ง€์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ๋‚ด์žฅ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ฌธ์ž์—ด ๋ฐ ๋ฐฐ์—ด ์œ ํ˜•์— ์‚ฌ์šฉ๋˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ•จ์ˆ˜์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค. ์ „์ฒด ํ•จ์ˆ˜ ๋ชฉ๋ก์€ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ž์—ด์€ concat ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, toUpper ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var hello string = 'hello'
var helloWorld string = concat(toUpper(hello), ', world!') // HELLO, world!

๋ฐฐ์—ด์€ union ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘๋ณต ์—†์ด ๋ณ‘ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var array1 = [1, 2, 3]
var array2 = [2, 3, 4]

var result = union(array1, array2) // [1, 2, 3, 4]

๋ชจ๋“ˆ

๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ด€๋ จ ๋ฆฌ์†Œ์Šค๋ฅผ ๋…ผ๋ฆฌ์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ ๋ฆฌ์†Œ์Šค ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์€ ๋งค๊ฐœ๋ณ€์ˆ˜, ๋ฆฌ์†Œ์Šค ๋ฐ ์ถœ๋ ฅ์ด๋ผ๋Š” ์„ธ ๊ฐ€์ง€ ์ฃผ์š” ๋ถ€๋ถ„์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ˜ธ์ถœ์ž๊ฐ€ ์ „๋‹ฌํ•˜๋Š” ๋ฐ์ดํ„ฐ์ด๋ฉฐ, param ํ‚ค์›Œ๋“œ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค๋Š” ๋ชจ๋“ˆ์— ์˜ํ•ด ์‹ค์ œ๋กœ ์ƒ์„ฑ๋  ๋ฆฌ์†Œ์Šค์ด๋ฉฐ, ์ถœ๋ ฅ์€ ํ˜ธ์ถœ์ž๊ฐ€ ํ•„์š”๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ์„ฑ๋œ ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ์ค‘์š”ํ•œ ์ •๋ณด(์˜ˆ: ๋ฆฌ์†Œ์Šค ID)์ž…๋‹ˆ๋‹ค.

์•„๋ž˜ ์˜ˆ์‹œ๋Š” App Service ๋˜๋Š” ์›น ์•ฑ์„ ๋ฐฐํฌํ•˜๋Š” ๋ชจ๋“ˆ์ž…๋‹ˆ๋‹ค. App Service๋Š” App Service ํ”Œ๋žœ์ด ํ•„์š”ํ•˜๋ฏ€๋กœ, ์ด ๋ชจ๋“ˆ์€ ํ•ด๋‹น ํ”Œ๋žœ๋„ ํ•จ๊ป˜ ํ”„๋กœ๋น„์ €๋‹ํ•ฉ๋‹ˆ๋‹ค.

appService.bicep
@description('๋ชจ๋“  ๋ฆฌ์†Œ์Šค์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค.')
param location string

@description('์•ฑ ์„œ๋น„์Šค ํ”Œ๋žœ์˜ ์ด๋ฆ„.')
param appServicePlanName string

@description('์›น ์•ฑ์˜ ์ด๋ฆ„.')
param webAppName string

@description('๋ฐฐํฌ ํ™˜๊ฒฝ.')
@allowed([ 'dev', 'prod' ])
param environmentType string

@description('๋ชจ๋“  ๋ฆฌ์†Œ์Šค์— ์ ์šฉํ•  ํƒœ๊ทธ.')
param tags object = {}

var appServicePlanSkuName = (environmentType == 'prod') ? 'P2V3' : 'F1'

resource appServicePlan 'Microsoft.Web/serverfarms@2024-11-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: appServicePlanSkuName
  }
  tags: tags
}

resource webApp 'Microsoft.Web/sites@2024-11-01' = {
  name: webAppName
  location: location
  properties:{
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
  tags: tags
}

@description('์›น ์•ฑ์˜ ๊ธฐ๋ณธ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„')
output webAppHostName string = webApp.properties.defaultHostName

์ฒซ ๋‘ ์ค„์€ ์ด ๋ชจ๋“ˆ์ด location์ด๋ผ๋Š” ์ด๋ฆ„์˜ ๋ฌธ์ž์—ด ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์œผ๋ฉฐ, @description ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

๋˜ํ•œ appServicePlanSkuName์—์„œ๋Š” ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ environmentType ํ™˜๊ฒฝ ์œ ํ˜•์— ๋”ฐ๋ผ ํ•„์š”ํ•œ SKU๋ฅผ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ์ปดํ“จํŒ… ์„ฑ๋Šฅ์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ, ์ œ๊ณต๋œ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ appServicePlan์ด๋ผ๋Š” ์ƒ์ง•์ ์ธ ์ด๋ฆ„์œผ๋กœ App Service Plan์„ ํ”„๋กœ๋น„์ €๋‹ํ•˜๊ณ , serverFarmId: appServicePlan.id ์ค„์—์„œ ํ•ด๋‹น App Service Plan ์•„๋ž˜์— ์›น ์•ฑ์„ ํ”„๋กœ๋น„์ €๋‹ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ์›น ์•ฑ์˜ webAppHostName์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋ชจ๋“ˆ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

main.bicep
module appService 'modules/appService.bicep' = {
  name: 'appService'
  params: {
    location: location
    appServicePlanName: appServicePlanName
    webAppName: webAppName
    environmentType: environmentType
    tags: tags
  }
}

๋ฐ˜ํ™˜๋œ ๊ฐ’์€ outputs ์†์„ฑ์„ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

main.bicep
// ์ด ๋ณ€์ˆ˜๋Š” ์›ํ•˜๋Š” ๊ณณ ์–ด๋””๋“  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
var appName = appService.outputs.webAppHostName

์ „์ฒด ์ฝ”๋“œ๋Š” ์ œ GitHub ์ €์žฅ์†Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์ธ ํŒŒ์ผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”

๋ฉ”์ธ ํŒŒ์ผ๋„ param ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

main.bicep
@allowed([
  'dev'
  'prod'
])
param environment string

module appService 'modules/appService.bicep' = {
  name: 'appService'
  params: {
    location: location
    appServicePlanName: appServicePlanName
    webAppName: webAppName
    environmentType: environment // ์—ฌ๊ธฐ์—๋Š” ์‚ฌ์šฉ ๋˜์š”
    tags: tags
  }
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฐฐํฌ ๋ช…๋ น์—์„œ --parameters ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ๋ณ„ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

az deployment group create \
  --resource-group my-rg \
  --template-file main.bicep \
  --parameters environment=dev

์ฃผ์š” ๋ฐฐํฌ ํŒŒ์ผ์— ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ, ๋ช…๋ น์ค„์—์„œ ํ•˜๋‚˜์”ฉ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  .bicepparam ํ™•์žฅ์ž๋กœ ๋๋‚˜๋Š” Bicep ๋งค๊ฐœ๋ณ€์ˆ˜ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ฝ”๋“œ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์€ Docker์—์„œ docker-compose.yml ํŒŒ์ผ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋งค์šฐ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ ์˜ˆ์‹œ๋Š” main.dev.bicepparam ํŒŒ์ผ์—์„œ main.bicep ๋ชจ๋“ˆ์— ๋Œ€ํ•œ ํ™˜๊ฒฝ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

main.dev.bicepparam
use 'main.bicep'

param environment = 'dev'

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฐฐํฌ ์‹œ์—๋Š” parameter ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋งค๊ฐœ๋ณ€์ˆ˜ ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

az deployment group create \
  --resource-group my-rg \
  --parameters main.dev.bicepparam

๋„๊ตฌ

VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ

Bicep์€ ๊ตฌ๋ฌธ ๊ฐ•์กฐ ํ‘œ์‹œ, ์ธํ…”๋ฆฌ์„ผ์Šค, ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ฐ ๋ฐฐํฌ ๊ตฌ์„ฑ์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•œ ๋ฆฌ์†Œ์Šค ์‹œ๊ฐํ™” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•˜๋Š” VS Code ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํฌ๋งทํŒ…

Bicep ํŒŒ์ผ์€ format ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์ž๋ฆฌ์—์„œ ํ˜•์‹์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

az bicep format --file <your-bicep-file>

What-If

what-if ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ ์šฉํ•˜๊ธฐ ์ „์— ํ™˜๊ฒฝ์˜ ๋ฆฌ์†Œ์Šค์— ์–ด๋–ค ๋ณ€ํ™”๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ๋ฏธ๋ฆฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐฐํฌ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜๋„์น˜ ์•Š์€ ๋ฐ์ดํ„ฐ ์†์‹ค์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

az deployment group what-if --resource-group my-rg --template-file main.bicep

์ฐธ๊ณ 

Rathnayake, K. Azure Bicep Crash Course | Step by Step | All in One.https://www.youtube.com/watch?v=mKG5d9rnaYg
Microsoft. Fundamentals of Bicep. Retrieved 2025, October 12 from https://learn.microsoft.com/en-us/training/paths/fundamentals-bicep/