flatten 함수
flatten 함수
flatten은 리스트를 받아서, 그 안에 들어 있는 리스트 요소들을 그 내용물로 펼쳐서 평평한(1차원) 시퀀스로 바꿔줘요. 중첩 구조를 한 단계로 정리하고 싶을 때 쓰는 함수죠.
출처: Packer 공식 문서
본문
flatten takes a list and replaces any elements that are lists with a flattened sequence of the list contents.
예시 (Examples)
> flatten([["a", "b"], [], ["c"]])
["a", "b", "c"]
중첩된 리스트 안에 또 바로 중첩된 리스트가 들어 있어도, 이 역시 재귀적으로 평평하게 만들어져요:
> flatten([[[ "a", "b" ], []], [ "c" ]])
["a", "b", "c"]
다만 맵(map) 안에 담긴 것처럼 간접적으로 중첩된 리스트는 펼쳐지지 않아요.
for_each를 위한 중첩 구조 평탄화 (Flattening nested structures for for_each)
리소스 for_each와 dynamic 블록 언어 기능은 반복 횟수만큼 요소를 가진 컬렉션 값이 필요해요.
때로는 입력 데이터 구조가 for_each 인자에 쓰기 좋은 형태가 아닐 수 있는데, 그런 중첩 구조를 평평한 구조로 줄일 때 flatten이 유용한 도우미 함수가 돼요.
예를 들어 아래처럼 변수를 선언하는 폴더를 생각해 볼게요:
variable "networks" {
type = map(object({
cidr_block = string
subnets = map(object({
cidr_block = string
})
})
}
이런 구조는 최상위 네트워크와 그 서브넷처럼 자연스럽게 트리를 이루는 객체들을 모델링하는 합리적인 방법이에요. 최상위 네트워크의 반복은 이 변수를 그대로 쓸 수 있는데, 이미 결과 인스턴스가 맵 요소와 일대일로 대응되는 형태거든요:
resource "aws_vpc" "example" {
for_each = var.networks
cidr_block = each.value.cidr_block
}
하지만 모든 서브넷 을 단일 resource 블록으로 선언하려면, 먼저 구조를 평탄화해서 각 최상위 요소가 서브넷 하나를 나타내는 컬렉션을 만들어야 해요:
locals {
# flatten ensures that this local value is a flat list of objects, rather
# than a list of lists of objects.
network_subnets = flatten([
for network_key, network in var.networks : [
for subnet_key, subnet in network.subnets : {
network_key = network_key
subnet_key = subnet_key
network_id = aws_vpc.example[network_key].id
cidr_block = subnet.cidr_block
}
]
])
}
resource "aws_subnet" "example" {
# local.network_subnets is a list, so we must now project it into a map
# where each key is unique. We'll combine the network and subnet keys to
# produce a single unique key per instance.
for_each = {
for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
}
vpc_id = each.value.network_id
availability_zone = each.value.subnet_key
cidr_block = each.value_cidr_block
}
이렇게 하면 서브넷 객체 하나마다 서브넷 인스턴스 하나가 생기면서도, 서브넷과 이를 담은 네트워크 사이의 연결 관계는 그대로 유지돼요.
관련 함수 (Related Functions)
setproduct는 여러 리스트나 값 집합의 모든 조합을 찾아주는데,for_each구문에 쓸 컬렉션을 준비할 때도 유용해요.