# 명명 규칙

## 일반적인 규칙 <a href="#general-conventions" id="general-conventions"></a>

{% hint style="info" %}
이 규칙을 따르지 않을 이유가 없죠 :)
{% endhint %}

{% hint style="info" %}
실제 클라우드 리소스에는 허용되는 이름에 제한이 있는 경우가 많습니다. 예를 들어 일부 리소스에는 대시를 포함할 수 없으며 일부 리소스는 낙타 표기법(CamelCase)으로 표기해야 합니다. 이 책의 규칙은 Terraform 이름 자체를 나타냅니다.
{% endhint %}

1. 리소스 이름, 데이터 소스 이름, 변수 이름, 출력 등 모든 곳에서 `-`(대시, dash) 대신 `_`(밑줄)을 사용합니다.
2. (UTF-8이 지원되더라도) 소문자와 숫자를 사용하는 것이 좋습니다.

## 리소스 및 데이터 소스 인수 <a href="#undefined" id="undefined"></a>

1. (이름 일부 또는 전체를 포함해) 리소스 이름에 리소스 유형을 반복하지 마세요.

{% hint style="success" %}

```
`resource "aws_route_table" "public" {}`
```

{% endhint %}

{% hint style="danger" %}

```
`resource "aws_route_table" "public_route_table" {}`
```

{% endhint %}

{% hint style="danger" %}

```
`resource "aws_route_table" "public_aws_route_table" {}`
```

{% endhint %}

1. 보다 더 설명적이고 일반적인 이름을 사용할 수 없거나 리소스 모듈이 해당 유형에 대해 단 한 개의 리소스를 생성하는 경우(예: [AWS VPC module](https://github.com/terraform-aws-modules/terraform-aws-vpc)에는 `aws_nat_gateway` 유형의 리소스 한 개와 `aws_route_table` 유형의 리소스가 여러 개 있는 경우에 `aws_nat_gateway`는 `this`로, `aws_route_table`은 `private`, `public`, `database`와 같이 더 설명적인 이름을 지어줘야 합니다.
2. 이름에는 항상 단수 명사를 사용하세요.
3. 인수 값 내부와 값이 사람에게 노출되는 곳(예: RDS 인스턴스의 DNS 이름 내부)에는 `-`를 사용합니다.
4. 리소스 또는 데이터 소스 블록 내부에 인수 `count` / `for_each`를 맨 위의 첫 번째 인수로 포함하고 그 뒤는 줄바꿈으로 구분합니다.
5. 리소스에서 지원하는 경우 인수 `tags`를 마지막 실제 인수로 포함하고 필요한 경우 `depends_on` 및 `lifecycle`을 포함합니다. 이들 모두는 하나의 빈 줄로 구분되어야 합니다.&#x20;
6. 인수 `count` / `for_each`에 조건을 사용할 때는 `length`나 다른 표현식을 사용하는 대신 불(bool) 값을 쓰는 것이 좋습니다.

## `resource` 코드 예제

### `count` / `for_each`의 사용

{% hint style="success" %}
{% code title="main.tf" %}

```hcl
resource "aws_route_table" "public" {
  count = 2

  vpc_id = "vpc-12345678"
  # ... remaining arguments omitted
}

resource "aws_route_table" "private" {
  for_each = toset(["one", "two"])

  vpc_id = "vpc-12345678"
  # ... remaining arguments omitted
}
```

{% endcode %}
{% endhint %}

{% hint style="danger" %}
{% code title="main.tf" %}

```hcl
resource "aws_route_table" "public" {
  vpc_id = "vpc-12345678"
  count  = 2

  # ... remaining arguments omitted
}
```

{% endcode %}
{% endhint %}

### `tags`의 배치

{% hint style="success" %}
{% code title="main.tf" %}

```hcl
resource "aws_nat_gateway" "this" {
  count = 2

  allocation_id = "..."
  subnet_id     = "..."

  tags = {
    Name = "..."
  }

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }
}   
```

{% endcode %}
{% endhint %}

{% hint style="danger" %}
{% code title="main.tf" %}

```hcl
resource "aws_nat_gateway" "this" {
  count = 2

  tags = "..."

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }

  allocation_id = "..."
  subnet_id     = "..."
}
```

{% endcode %}
{% endhint %}

### `count`의 조건

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
resource "aws_nat_gateway" "that" {    # Best
  count = var.create_public_subnets ? 1 : 0
}

resource "aws_nat_gateway" "this" {    # Good
  count = length(var.public_subnets) > 0 ? 1 : 0
}
```

{% endcode %}
{% endhint %}

## 변수

1. 리소스 모듈의 바퀴를 다시 만들지 마세요(역주: Don't reinvent the wheel! 이미 만들어져서 잘 쓰이고 있는 것을 두고 굳이 비슷한 수준의 것을 새로 만드는 데 에너지를 쏟는 것을 피하라는 말). 작업 중인 리소스에 대한 "인수 참조" 섹션에 정의된 대로 변수에 대한 `name`, `description`, 및 `default`값을 사용하세요.
2. 변수의 유효성 검사에 대한 지원은 다소 제한적입니다(예: 다른 변수에 액세스하거나 조회를 수행할 수 없음). 대부분의 경우 이 기능은 쓸모가 없으므로 상황에 맞춰 계획하세요.
3. &#x20;유형이 `list(...)` 또는 `map(...)`인 경우 변수 이름에 복수형을 사용합니다.
4. 변수 블록의 키 순서를 다음과 같이 지정하세요: `description` , `type`, `default`, `validation`
5. 분명하다고 생각되더라도 항상 모든 변수에 대한 `description`(설명)을 포함하세요(향후 필요할 것입니다).
6. 각 키에 엄격한 제약을 적용할 필요가 없는 한 `object()`와 같은 특정 유형보다는 간단한 유형 (`number`, `string`, `list(...)`, `map(...)`, `any`)을 사용하는 것이 좋습니다.
7. 지도의 모든 요소가 동일한 유형(예: `string`문자열)이거나 해당 유형으로 변환될 수 있는 경우(예: `number` 숫자 유형을 `string` 문자열로 변환할 수 있는 경우) `map(map(string))`과 같은 특정 유형을 사용합니다.
8. 특정 깊이에서 시작하거나 여러 유형을 지원해야 하는 경우에 유형 유효성 검사를 비활성화하려면 `any` 유형을 사용하세요.
9. 값 `{}`은 지도일 때도 있고 객체일 때도 있습니다. 객체를 만들 수 있는 방법이 없기 때문에 지도를 만들려면 `tomap(...)`을 사용하세요.

## 출력(outputs)

모듈의 범위 밖에서도 출력을 일관되고 이해하기 쉽게 만드세요(사용자가 모듈을 사용할 때 반환되는 값의 유형과 속성이 무엇인지 명확해야 합니다).

1. 출력 이름은 자신이 포함하는 속성을 설명해야 하며 일반적으로 우리가원하는 것보다는 형식이 덜 자유롭습니다.
2. 출력 이름에 적합한 구조는 `{name}_{type}_{attribute}`이며 다음을 참고하세요.
   1. `{name}`은 프로바이더 접두사가 없는 리소스 또는 데이터 소스 이름입니다. `aws_subnet`의 `{name}`은 `subnet`이고, `aws_vpc`의 경우 `vpc`입니다.
   2. `{type}`은 리소스 소스의 유형입니다.
   3. `{attribute}`는 출력이 반환하는 속성입니다.
   4. [예제 보기](#code-examples-of-output).
3. 출력이 보간 함수 및 여러 리소스가 포함된 값을 반환하는 경우 `{name}` 및 `{type}`은 가능한 한 일반적이어야 합니다(접두사로 `this`는 생략해야 함). [예를 참조하세요](#code-examples-of-output).&#x20;
4. 반환된 값이 리스트인 경우 복수형 이름을 가져야 합니다. [예를 참조하세요](#.).&#x20;
5. 분명하다고 생각되더라도 항상 모든 변수에 대한 `description`(설명)을 포함하세요.
6. 모든 모듈의 모든 위치에서 이 출력의 사용을 완전히 제어할 수 있는 게 아니라면 `sensitive` 인수를 설정하지 마세요.
7. `element(concat(...))`(0.13 이전 버전의 레거시 접근 방식)보다 `try()`(Terraform 0.13부터 사용 가능)를 쓰는 것이 좋습니다.

### `output`  코드 예제 <a href="#code-examples-of-output" id="code-examples-of-output"></a>

보안 그룹의 ID를 최대 1개 반환합니다

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
output "security_group_id" {
  description = "The ID of the security group"
  value       = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0].id, "")
}
```

{% endcode %}
{% endhint %}

동일한 유형의 리소스가 여러 개 있는 경우 출력 이름에서 `this`를 생략해야 합니다.

{% hint style="danger" %}
{% code title="outputs.tf" %}

```hcl
output "this_security_group_id" {
  description = "The ID of the security group"
  value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
}
```

{% endcode %}
{% endhint %}

### 반환 값이 리스트인 경우 복수형 이름을 사용하세요.

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
output "rds_cluster_instance_endpoints" {
  description = "A list of all cluster instance endpoints"
  value       = aws_rds_cluster_instance.this.*.endpoint
}
```

{% endcode %}
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.terraform-best-practices.com/ko/naming.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
