

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Terraform 함수, 표현식 및 메타 인수 이해
<a name="functions-expressions"></a>

일반적인 프로그래밍 언어보다는 선언적 구성 파일을 사용하는 IaC 도구에 대한 비판 중 하나는 사용자 지정 프로그래밍 로직을 구현하기가 더 어렵다는 것입니다. Terraform 구성에서이 문제는 함수, 표현식 및 메타 인수를 사용하여 해결됩니다.

## 함수
<a name="functions"></a>

코드를 사용하여 인프라를 프로비저닝할 때 얻을 수 있는 큰 이점 중 하나는 공통 워크플로를 저장 하고 반복해서 재사용하여 매번 다른 인수를 전달하는 것입니다. Terraform 함수는 AWS CloudFormation [내장 함수](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html)와 유사하지만 구문은 함수가 프로그래밍 언어로 호출되는 방식과 더 유사합니다. 이 가이드의 예제에서 [하위 문자열](https://developer.hashicorp.com/terraform/language/functions/substr), [concat](https://developer.hashicorp.com/terraform/language/functions/concat),[length](https://developer.hashicorp.com/terraform/language/functions/length) 및 [base64decode](https://developer.hashicorp.com/terraform/language/functions/base64decode)와 같은 일부 Terraform 함수를 이미 발견했을 수 있습니다. 내장 함수가 있는 CloudFormation과 마찬가지로 Terraform에는 구성에 사용할 수 있는 일련의 [내장 함수](https://developer.hashicorp.com/terraform/language/functions)가 있습니다. 예를 들어 특정 리소스 속성이 파일에 직접 붙여넣는 데 비효율적인 매우 큰 JSON 객체를 사용하는 경우 객체를 **.json** 파일에 넣고 Terraform 함수를 사용하여 액세스할 수 있습니다. 다음 예제에서 `file` 함수는 파일의 내용을 문자열 형식으로 반환한 다음 `jsondecode` 이를 객체 유형으로 변환합니다.

```
resource "example_resource" "example_resource_name" {
  json_object = jsondecode(file("/path/to/file.json"))
}
```

## Expressions
<a name="expressions"></a>

또한 Terraform은 보다 전통적인 [삼원 연산](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator)자 구문을 사용한다는 점을 제외하면 CloudFormation `condition` 함수와 유사한 [조건식](https://developer.hashicorp.com/terraform/language/expressions/conditionals)도 허용합니다. 다음 예제에서는 두 표현식이 정확히 동일한 결과를 반환합니다. 두 번째 예는 Terraform이 [스플랫 표현](https://developer.hashicorp.com/terraform/language/expressions/splat)식을 호출하는 것입니다. 별표로 인해 Terraform은 각 항목의 `id` 속성만 사용하여 목록을 반복하고 새 목록을 생성합니다.

```
resource "example_resource" "example_resource_name" {
  boolean_value  = var.value ? true : false
  numeric_value  = var.value > 0 ? 1 : 0
  string_value   = var.value == "change_me" ? "New value" : var.value
  string_value_2 = var.value != "change_me" ? var.value : "New value"
}
There are two ways to express for loops in a Terraform configuration:
resource "example_resource" "example_resource_name" {
  list_value   = [for object in var.ids : object.id]
  list_value_2 = var.ids[*].id
}
```

## 메타 인수
<a name="meta-arguments"></a>

이전 코드 예제에서 `list_value` 및 `list_value_2`를 *인수라고 합니다*. 이러한 메타 인수 중 일부는 이미 잘 알고 있을 수 있습니다. 또한 Terraform에는 인수처럼 작동하지만 몇 가지 추가 기능이 있는 몇 가지 *메타* 인수가 있습니다.
+ 메타 인수의 [depends\$1on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on)은 CloudFormation [DependsOn 속성](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html)과 매우 유사합니다.
+ [공급자](https://developer.hashicorp.com/terraform/language/meta-arguments#provider) 메타 인수를 사용하면 여러 공급자 구성을 한 번에 사용할 수 있습니다.
+ [수명 주기 ](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle)메타 인수를 사용하면 CloudFormation의 [제거](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk/RemovalPolicy.html) 및 [삭제](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) 정책과 마찬가지로 리소스 설정을 사용자 지정할 수 있습니다.

다른 메타 인수를 사용하면 함수 및 표현식 기능을 리소스에 직접 추가할 수 있습니다. 예를 들어 개수 [https://developer.hashicorp.com/terraform/language/meta-arguments/count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)메타 인수는 여러 유사한 리소스를 동시에 생성하는 데 유용한 메커니즘입니다. 다음 예제에서는 `count`메타 인수를 사용하지 않고 두 개의 Amazon Elastic Container Service(Amazon EKS) 클러스터를 생성하는 방법을 보여줍니다.

```
resource "aws_eks_cluster" "example_0" {
  name     = "example_0"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[0]
  }
}

resource "aws_eks_cluster" "example_1" {
  name     = "example_1"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[1]
  }
}
```

다음 예제에서는 `count`메타 인수를 사용하여 두 개의 Amazon EKS 클러스터를 생성하는 방법을 보여줍니다.

```
resource "aws_eks_cluster" "clusters" {
  count    = 2
  name     = "cluster_${count.index}"
  role_arn = aws_iam_role.cluster_role.arn
  vpc_config {
    endpoint_private_access = true
    endpoint_public_access  = true
    subnet_ids              = var.subnet_ids[count.index]
  }
}
```

각에 단위 이름을 지정하기 위해에서 리소스 블록 내의 목록 인덱스에 액세스할 수 있습니다`count.index`. 하지만 조금 더 복잡한 유사한 리소스를 여러 개 생성하려면 어떻게 해야 할까요? 여기에서 [for\$1each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each) meta-argument가 입력됩니다. `for_each` 메타 인수는 숫자 대신 목록이나 객체를 전달하는 점을 `count`제외하면와 매우 유사합니다. Terraform은 목록 또는 객체의 각 멤버에 대해 새 리소스를 생성합니다. 루프 인덱스가 아닌 목록의 내용에 액세스할 수 있다는 `count = length(list)`점을 제외하면를 설정하는 경우와 비슷합니다.

이는 항목 목록 또는 단일 객체 모두에 적용됩니다. 다음 예제에서는 ID`id-1`로 `id-0` 및가 있는 두 개의 리소스를 생성합니다 IDs.

```
variable "ids" {
  default = [
    { id = "id-0" },
    { id = "id-1" },
  ]
}

resource "example_resource" "example_resource_name" {
  # If your list fails, you might have to call "toset" on it to convert it to a set
  for_each = toset(var.ids)
  id       = each.value
}
```

다음 예제에서는 Sparky용 리소스, 푸들용 리소스, chihuahua용 리소스 등 두 개의 리소스도 생성합니다.

```
variable "dogs" {
  default = {
    poodle    = "Sparky"
    chihuahua = "Fluffy"
  }
}

resource "example_resource" "example_resource_name" {
  for_each = var.dogs
  breed    = each.key
  name     = each.value
}
```

count.index를 사용하여 개수로 루프 인덱스에 액세스할 수 있는 것처럼 각 객체를 사용하여 for\$1each 루프에 있는 각 항목의 키와 값에 액세스할 수 있습니다. for\$1each는 목록과 객체를 모두 반복하기 때문에 각 키와 값은 추적하기가 약간 혼란스러울 수 있습니다. 다음 표에는 for\$1each meta-argument를 사용할 수 있는 다양한 방법과 각 반복 시 값을 참조하는 방법이 나와 있습니다.


****  

| 예제 | `for_each` 유형 | 첫 번째 반복 | 두 번째 반복 | 
| --- | --- | --- | --- | 
| A | <pre>["poodle", "chihuahua"]</pre> | <pre>each.key = "poodle"<br /><br />each.value = null</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = null</pre> | 
| B | <pre>[<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = {<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />}<br /><br />each.value = null</pre> | <pre>each.key = {<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />each.value = null</pre> | 
| C | <pre>{<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "poodle"<br /><br />each.value = "Sparky"</pre> | <pre>each.key = "chihuahua"<br /><br />each.value = "Fluffy"</pre> | 
| D | <pre>{<br /><br />dogs = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />},<br /><br />cats = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = {<br /><br />poodle = "Sparky",<br /><br />chihuahua = "Fluffy"<br /><br />}</pre> | <pre>each.key = "cats"<br /><br />each.value = {<br /><br />persian = "Felix",<br /><br />burmese = "Morris"<br /><br />}</pre> | 
| E | <pre>{<br /><br />dogs = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />],<br /><br />cats = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]<br /><br />}</pre> | <pre>each.key = "dogs"<br /><br />each.value = [<br /><br />{<br /><br />type = "poodle",<br /><br />name = "Sparky"<br /><br />},<br /><br />{<br /><br />type = "chihuahua",<br /><br />name = "Fluffy"<br /><br />}<br /><br />]</pre> | <pre>each.key = "cats"<br /><br />each.value = [<br /><br />{<br /><br />type = "persian",<br /><br />name = "Felix"<br /><br />},<br /><br />{<br /><br />type = "burmese",<br /><br />name = "Morris"<br /><br />}<br /><br />]</pre> | 

 

따라서 `var.animals`가 E행과 같으면 다음 코드를 사용하여 동물당 하나의 리소스를 생성할 수 있습니다.

```
resource "example_resource" "example_resource_name" {
  for_each = var.animals
  type     = each.key
  breeds   = each.value[*].type
  names    = each.value[*].name
}
```

또는 다음 코드를 사용하여 동물당 두 개의 리소스를 생성할 수 있습니다.

```
resource "example_resource" "example_resource_name" {
  for_each = var.animals.dogs
  type     = "dogs"
  breeds   = each.value.type
  names    = each.value.name
}

resource "example_resource" "example_resource_name" {
  for_each = var.animals.cats
  type     = "cats"
  breeds   = each.value.type
  names    = each.value.name
}
```