count, for_eachfor 표현식(list/map 컴프리헨션)dynamic 블록count와 for_each는 같은 블록에서 동시에 못 씀count — “N개 찍어내기”(인덱스 기반)# N개 퍼블릭 서브넷 (AZ 개수만큼)
variable "az_count" { default = 2 }
resource "aws_subnet" "public" {
count = var.az_count
vpc_id = aws_vpc.main.id
availability_zone = local.azs[count.index] # 0,1,...
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
map_public_ip_on_launch = true
}
# 참조: aws_subnet.public[0].id, aws_subnet.public[1].id
조건부 생성(0 또는 1):
count = var.enabled ? 1 : 0
for_each — “키 기반 반복”(맵/셋 권장)# AZ별 CIDR을 키로 관리 → 변경에 강함
locals {
public_subnets = {
"ap-northeast-2a" = "10.0.1.0/24"
"ap-northeast-2c" = "10.0.2.0/24"
}
}
resource "aws_subnet" "public" {
for_each = local.public_subnets
vpc_id = aws_vpc.main.id
availability_zone = each.key
cidr_block = each.value
map_public_ip_on_launch = true
}
# 참조: aws_subnet.public["ap-northeast-2a"].id
map(...) 또는 set(string) 권장 (list는 toset(list)로 변환해 사용)모듈/데이터소스에도 동일하게 사용 가능:
module "svc" { for_each = var.services name = each.key spec = each.value } data "aws_ami" "sel" { for_each = toset(var.names) # ... }
for 표현식 — 값 가공/필터링(컴프리헨션)# 리소스 목록 → ID만 추출 (count 케이스)
output "public_ids" {
value = [for s in aws_subnet.public : s.id]
}
# for_each(맵) 케이스: values()로 값만 뽑아 다시 for
output "public_cidrs" {
value = [for s in values(aws_subnet.public) : s.cidr_block]
}
# 필터 포함(for ... if ...)
locals {
public_http_cidrs = [
for r in var.rules : r.cidr
if r.public && r.port == 80
]
}
if 절로 필터링 가능dynamic 블록 — 중첩 블록 반복 생성중첩 블록(예: SG의 ingress)을 데이터로부터 반복 생성.
locals {
ingress_rules = {
ssh = { port = 22, cidr = "0.0.0.0/0" }
http = { port = 80, cidr = "0.0.0.0/0" }
}
}
resource "aws_security_group" "web" {
name = "web-sg"
vpc_id = aws_vpc.main.id
dynamic "ingress" {
for_each = local.ingress_rules
content {
from_port = ingress.value.port
to_port = ingress.value.port
protocol = "tcp"
cidr_blocks = [ingress.value.cidr]
}
}
}
aws_security_group_rule) 그걸 for_each로 돌리는 편이 더 명확할 때도 있음locals로 룩업 테이블 만들고 for_eachlocals {
itype_by_env = { dev = "t3.micro", prod = "t3.medium" }
itype = local.itype_by_env[var.env]
}
resource "aws_instance" "web" {
instance_type = local.itype
# ...
}
resource "aws_instance" "web" {
# ...
user_data = var.enable_user_data ? file("${path.module}/init.sh") : null
# null → 해당 인자 미설정으로 간주
}
output "subnet_ids" {
value = [for s in aws_subnet.public : s.id]
}
output "subnet_by_az" {
value = { for az, s in aws_subnet.public : az => s.id } # for_each 맵 그대로 재구성
}
count와 for_each를 같은 블록에 동시 사용 → 불가count 인덱스 변경으로 재생성 → ✅ for_each + 안정된 키(맵/셋) 사용toset(list) 또는 맵으로 변환for 표현식이 더 명확locals에 데이터 구조를 먼저 정리(가독성↑, 재사용↑)| 목적 | 방법 | 포인트 |
|---|---|---|
| N개 리소스 | count = N | count.index, 인덱스 변경 주의 |
| 키 기반 여러 개 | for_each = map/set | each.key, each.value, 변경 안정 |
| 값 변환/필터 | [for x in xs : ... if ...] / {for k,v in m : ...} | 컴프리헨션 |
| 중첩 블록 반복 | dynamic "<block>" { for_each = ... } | SG ingress 등 |
| 조건부 생성 | count = cond ? 1 : 0 | 0/1 토글 |
| 조건부 속성 | attr = cond ? val : null | null이면 미설정 |
“여러 개 만들 땐
for_each(키 안정), 단순 개수면count,
가공/필터링은for표현식, 중첩 블록은dynamic으로!”