Day 10— Terraform 조건식, 동적 블록 및 스플랫 표현식
Source: Dev.to
조건식
조건식은 조건을 평가하고, 해당 조건이 참인지 거짓인지에 따라 두 값 중 하나를 반환합니다.
구문
condition ? true_value : false_value
사용 사례
- 환경(
devvsprod)에 따라 인스턴스 유형 선택 - 설정에 따라 모니터링 활성화/비활성화
- 지역에 따라 서로 다른 AMI 선택
- 환경별 리소스 개수 설정
- 환경‑특화 태그 적용
장점
- 여러 환경에 대해 하나의 구성만 필요
- 코드 중복 감소
- 환경 차이를 명시적으로 표현
- 구성 관리가 간편
- 이해와 유지보수가 쉬움
사용 시점
- 환경‑별 구성
- 기능 플래그(기능 활성화/비활성화)
- 조건부 리소스 생성
- 지역‑별 설정
- 비용 최적화(개발 환경에서는 작은 리소스 사용)
사용하지 말아야 할 경우
- 조건이 많아 복잡한 로직(이때는
locals사용) - 별도의 환경 파일이 더 명확할 때
- 모든 환경이 동일해야 할 때
예시
resource "aws_instance" "conditional_example" {
ami = "ami-28765345876"
instance_type = var.environment == "prod" ? "t3.large" : "t2.micro"
tags = {
Name = "conditional-instance-${var.environment}"
}
}
terraform plan을 실행하면 environment 변수에 따라 선택된 인스턴스 유형이 표시됩니다:
terraform plan
data.aws_ami.amazon_linux: Reading...
data.aws_ami.amazon_linux: Read complete after 1s [id=ami-02610f36df0c59544]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
+ create
# aws_instance.conditional_example will be created
+ resource "aws_instance" "conditional_example" {
+ ami = "ami-02610f36df0c59544"
+ instance_type = "t2.micro"
# ... other attributes omitted for brevity
}
이 예시에서 var.environment가 "prod"이면 인스턴스 유형이 t3.large가 되고, 그 외에는 기본값인 t2.micro가 사용됩니다.
동적 블록
동적 블록은 컬렉션(리스트 또는 맵)을 기반으로 리소스 내에 여러 중첩 블록을 자동으로 생성하여, 유사한 블록 구성을 반복할 필요를 없애줍니다.
구문
dynamic "block_name" {
for_each = var.collection
content {
# each.key와 each.value를 사용한 블록 구성
}
}
for_each는 리스트 또는 맵을 순회합니다.content는 생성되는 각 블록이 포함할 내용을 정의합니다.- 값은
each.key와each.value로 접근합니다.
사용 사례
- 보안 그룹 인그레스/이그레스 규칙
- EC2 인스턴스에 여러 EBS 볼륨 연결
- IAM 정책 문(statement)
- 로드 밸런서 리스너
- 라우트 테이블 라우트
- 반복되는 중첩 블록 구조 전반
장점
- 반복적인 코드 제거
- 항목 추가·삭제가 쉬움
- 변수에 의해 구성이 구동됨
- 코드가 더 깔끔하고 유지보수 용이
- 복잡한 데이터 구조 지원
사용 시점
- 유사한 중첩 블록이 다수 존재할 때
- 구성 개수가 가변적일 때
- 보안 그룹 규칙
- 인라인 정책
- 모든 반복 블록 패턴
사용하지 말아야 할 경우
- 하나 혹은 몇 개의 정적 블록만 필요할 때(오버헤드가 불필요)
- 코드 가독성을 떨어뜨릴 때
- 최상위 리소스에는(
count또는for_each사용)
예시
resource "aws_security_group" "dynamic_sg" {
name = "dynamic-sg-${var.environment}"
description = "Security group with dynamic rules"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
description = ingress.value.description
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "dynamic-sg-${var.environment}"
}
}
variable "ingress_rules" {
description = "List of ingress rules for security group"
type = list(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
description = string
}))
default = [
{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTP"
},
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS"
}
]
}
terraform plan을 실행하면 동적으로 생성된 인그레스 규칙이 표시됩니다:
# aws_security_group.dynamic_sg will be created
+ resource "aws_security_group" "dynamic_sg" {
+ arn = (known after apply)
+ description = "Security group with dynamic rules"
+ egress = [
{
+ cidr_blocks = ["0.0.0.0/0"]
+ from_port = 0
+ protocol = "-1"
+ to_port = 0
}
]
+ ingress = [
{
+ from_port = 80
+ to_port = 80
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ description = "HTTP"
},
{
+ from_port = 443
+ to_port = 443
+ protocol = "tcp"
+ cidr_blocks = ["0.0.0.0/0"]
+ description = "HTTPS"
}
]
# ... other attributes omitted for brevity
}
동적 블록은 var.ingress_rules를 순회하면서 각 규칙마다 ingress 블록을 자동으로 생성하므로, 수동으로 복제할 필요가 없습니다.
