조건부 표현식

조건부 표현식 (Conditional Expressions)

조건부 표현식은 불리언 표현식의 값을 사용해 두 값 중 하나를 선택해요.

출처: 문서

본문

문법 (Syntax)

조건부 표현식의 문법은 다음과 같아요:

condition ? true_val : false_val

conditiontrue면 결과는 true_val이에요. conditionfalse면 결과는 false_val이에요.

조건부 표현식의 일반적인 용법은 잘못된 값을 대체할 기본값을 정의하는 것이에요:

var.a == "" ? "default-a" : var.a

var.a가 빈 문자열이면 결과는 "default-a"이고, 그렇지 않으면 var.a의 실제 값이에요.

조건 (Conditions)

조건은 불리언 값으로 평가되는 어떤 표현식이든 될 수 있어요. 보통 동등, 비교, 논리 연산자를 사용하는 표현식이에요.

사용자 지정 조건 검사 (Custom Condition Checks)

구성의 여러 유형의 객체에 대해 사용자 지정 오류 메시지를 생성하는 조건을 만들 수 있어요. 예를 들어 입력 변수에 들어오는 이미지 ID가 제대로 형식화됐는지 확인하는 조건을 추가할 수 있어요.

사용자 지정 조건은 가정을 포착하는 데 도움이 되며, 미래의 유지 관리자가 구성 설계와 의도를 이해하는 데 도움을 줘요. 또한 오류에 대해 더 일찍, 더 문맥에 맞는 유용한 정보를 반환해 소비자가 구성의 문제를 더 쉽게 진단할 수 있게 해줘요.

자세한 내용은 구성 검증을 참고하세요.

결과 타입 (Result Types)

두 결과 값은 어떤 타입이든 될 수 있지만, 조건 값을 모른 채 전체 조건부 표현식이 반환할 타입을 Terraform이 결정할 수 있도록 둘 다 같은 타입이어야 해요.

두 결과 표현식이 같은 타입을 생성하지 않으면 Terraform은 둘 다 변환될 수 있는 타입을 찾으려고 시도하고, 가능하다면 자동으로 변환해요.

예를 들어 다음 표현식은 유효하며 항상 문자열을 반환해요. Terraform에서 모든 숫자는 십진수로 문자열에 자동 변환될 수 있기 때문이에요:

var.example ? 12 : "hello"

이 자동 변환 동작에 의존하는 것은 Terraform의 변환 규칙에 익숙하지 않은 사람들에게는 혼란스러울 수 있으므로, 기대 결과 타입에 대해 불확실성이 있는 상황에서는 타입 변환 함수를 사용해 명시적으로 작성하는 것을 권장해요.

다음 예제는 이 경우 타입 변환 대신 상수 "12"를 쓰는 것이 더 쉬우므로 인위적이지만, tostring을 사용해 숫자를 문자열로 명시적으로 변환하는 방법을 보여줘요.

var.example ? tostring(12) : "hello"

예제 (Examples)

조건이 유효하고 불리언 결과를 반환하기만 하면 조건에서 Terraform의 내장 함수나 언어 연산자를 사용할 수 있어요. 다음 예제는 조건 표현식 작성에 도움이 되는 언어 기능을 보여줘요.

논리 연산자 예제

논리 연산자 &&(AND), ||(OR), !(NOT)를 사용해 여러 조건을 결합해요.

  condition = var.name != "" && lower(var.name) == var.name

a + b 같은 산술 연산자, a == b 같은 동등 연산자, a < b 같은 비교 연산자도 사용할 수 있어요. 자세한 내용은 산술 및 논리 연산자를 참고하세요.

contains 함수

contains 함수를 사용해 주어진 값이 미리 정의된 유효한 값 집합 중 하나인지 테스트해요.

  condition = contains(["STAGE", "PROD"], var.environment)

length 함수

length 함수를 사용해 컬렉션의 길이를 테스트하고 비어 있지 않은 리스트나 맵을 요구해요.

  condition = length(var.items) != 0

두 피연산자가 잠재적으로 정확히 같은 타입을 가질 때 ==!=를 사용하는 것보다 length 함수를 사용하는 것이 더 적절하며, 빈 컬렉션에서는 종종 모호해요.

for 표현식

함수 alltrueanytrue와 함께 for 표현식을 사용해 조건이 컬렉션의 모든 요소 또는 어떤 요소에 대해 성립하는지 테스트해요.

  condition = alltrue([
    for v in var.instances : contains(["t2.micro", "m3.medium"], v.type)
  ])

can 함수

can 함수를 사용해 표현식의 유효성을 조건으로 간결하게 사용해요. 주어진 표현식이 성공적으로 평가되면 true를, 오류를 반환하면 false를 반환하므로, 보통 오류를 반환하는 다양한 다른 함수를 조건 표현식의 일부로 사용할 수 있어요.

예를 들어 regex는 일치하지 않는 문자열이 주어지면 오류를 반환하므로 canregex와 함께 사용해 문자열이 특정 패턴과 일치하는지 테스트할 수 있어요.

  condition = can(regex("^[a-z]+$", var.name))

타입 변환 함수와 함께 can을 사용해 값이 타입 또는 타입 제약으로 변환될 수 있는지 테스트할 수도 있어요.

  # This remote output value must have a value that can
  # be used as a string, which includes strings themselves
  # but also allows numbers and boolean values.
  condition = can(tostring(data.terraform_remote_state.example.outputs["name"]))
  # This remote output value must be convertible to a list
  # type of with element type.
  condition = can(tolist(data.terraform_remote_state.example.outputs["items"]))

속성 접근이나 인덱스 연산자와 함께 can을 사용해 컬렉션이나 구조적 값이 특정 요소나 인덱스를 갖는지 테스트할 수도 있어요.

  # var.example must have an attribute named "foo"
  condition = can(var.example.foo)
  # var.example must be a sequence with at least one element
  condition = can(var.example[0])
  # (although it would typically be clearer to write this as a
  # test like length(var.example) > 0 to better represent the
  # intent of the condition.)

self 객체

postcondition 블록에서 self 객체를 사용해 평가 중인 인스턴스의 속성을 참조해요.

resource "aws_instance" "example" {
  instance_type = "t2.micro"
  ami           = "ami-abc123"

  lifecycle {
    postcondition {
      condition     = self.instance_state == "running"
      error_message = "EC2 instance must be running."
    }
  }
}

eachcount 객체

for_each 또는 count가 설정된 블록에서 eachcount 객체를 사용해 체인으로 확장된 다른 리소스를 참조해요.

variable "vpc_cidrs" {
  type = set(string)
}

data "aws_vpc" "example" {
  for_each = var.vpc_cidrs

  filter {
    name   = "cidr"
    values = [each.key]
  }
}

resource "aws_internet_gateway" "example" {
  for_each = data.aws_vpc.example
  vpc_id = each.value.id

  lifecycle {
    precondition {
      condition     = data.aws_vpc.example[each.key].state == "available"
      error_message = "VPC ${each.key} must be available."
    }
  }
}

더 알아보기 (Learn more)