flatten 함수
flatten 함수
flatten은 리스트를 받아서, 그 요소 중 리스트인 것들을 해당 리스트 내용의 평평한(flattened) 순서로 바꿔주는 함수예요.
출처: 문서
본문
예제
> flatten([["a", "b"], [], ["c"]])
["a", "b", "c"]
중첩된 리스트 안에 또 직접 중첩된 리스트가 있다면, 그 역시 재귀적으로 평평하게 만들어져요.
> flatten([["a", "b"], [], ["c"]])
["a", "b", "c"]
맵 안처럼 간접적으로 중첩된 리스트는 평평하게 만들어지지 않아요.
for_each를 위한 중첩 구조 평평하게 만들기
리소스 for_each와 dynamic 블록 언어 기능은 모두 반복마다 요소 하나씩을 담은 컬렉션 값이 필요해요.
때로는 입력 데이터 구조가 for_each 인자에 쓰기에 자연스럽지 않은 형태일 수 있는데, 이때 중첩 데이터 구조를 평평한 구조로 줄일 때 flatten이 유용한 도우미 함수가 돼요.
예를 들어, 다음과 같은 변수를 선언하는 모듈을 생각해 보세요.
variable "networks" {
type = map(object({
cidr_block = string
subnets = map(object({ cidr_block = string }))
}))
default = {
"private" = {
cidr_block = "10.1.0.0/16"
subnets = {
"db1" = {
cidr_block = "10.1.0.0/24"
}
"db2" = {
cidr_block = "10.1.1.0/24"
}
}
},
"public" = {
cidr_block = "10.2.0.0/16"
subnets = {
"webserver" = {
cidr_block = "10.2.1.0/24"
}
"email_server" = {
cidr_block = "10.2.2.0/24"
}
}
}
"dmz" = {
cidr_block = "10.3.0.0/16"
subnets = {
"firewall" = {
cidr_block = "10.3.1.0/24"
}
}
}
}
}
위는 네트워크와 그 서브넷처럼 자연스럽게 트리를 이루는 객체를 모델링하는 합리적인 방법이에요. 최상위 네트워크의 반복은 결과 인스턴스가 맵 요소와 일대일로 일치하는 형태이므로 이 변수를 직접 사용할 수 있어요.
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 = tomap({
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
}
위 결과는 서브넷과 그 서브넷이 속한 네트워크 사이의 연결 관계를 유지하면서, 서브넷 객체 하나당 서브넷 인스턴스 하나씩을 만들게 돼요.
더 알아보기 (Learn more)
setproduct— 여러 리스트나 집합 값의 모든 조합을 찾아주며,for_each구문에 쓸 컬렉션을 준비할 때도 유용해요.