· Interview  · 9 min read

Terraform 면접 질문 20선 — IaC 설계부터 상태 관리까지

Terraform으로 멀티 환경 인프라를 관리하는 DevOps 엔지니어를 위한 면접 질문. State 관리, 모듈화, Workspace, 트러블슈팅 핵심 정리.

Terraform으로 멀티 환경 인프라를 관리하는 DevOps 엔지니어를 위한 면접 질문. State 관리, 모듈화, Workspace, 트러블슈팅 핵심 정리.

기초 개념

1. Terraform의 동작 원리를 설명해주세요.

  1. Init: Provider 플러그인 다운로드, Backend 초기화
  2. Plan: 현재 State와 코드 비교 → 변경 계획 생성
  3. Apply: Plan 기반으로 실제 리소스 생성/수정/삭제
  4. Destroy: 관리 중인 모든 리소스 삭제

핵심: Terraform은 선언적(Declarative) 도구. “어떻게”가 아닌 “무엇을” 정의합니다.

2. Terraform State의 역할과 중요성은?

State 파일(terraform.tfstate)은:

  • 실제 인프라와 코드의 매핑 정보 저장
  • Plan 시 변경사항 계산의 기준점
  • 리소스 간 의존성 추적
  • 메타데이터 (리소스 ID, 속성) 저장

State 없이는 Terraform이 기존 인프라를 인식할 수 없습니다.

3. Local State vs Remote State 차이와 선택 기준은?

구분LocalRemote (S3 + DynamoDB)
저장 위치로컬 파일S3 버킷
팀 협업불가가능 (잠금 지원)
보안파일 관리암호화 + IAM
잠금없음DynamoDB Lock

프로덕션에서는 항상 Remote State를 사용합니다.

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "ap-northeast-2"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

4. State Locking이 필요한 이유는?

동시에 여러 사용자/파이프라인이 terraform apply를 실행하면 State 충돌이 발생합니다.

DynamoDB Lock으로:

  • apply 시작 시 Lock 획득
  • 다른 사용자는 Lock 해제까지 대기
  • apply 완료/실패 시 Lock 해제

5. terraform import는 어떤 경우에 사용하나요?

수동으로 생성된 기존 리소스를 Terraform 관리 하에 두고 싶을 때:

terraform import aws_instance.example i-1234567890abcdef0

주의: import는 State에만 추가합니다. 코드(.tf)는 직접 작성해야 합니다.


모듈화

6. Terraform Module 설계 원칙은?

modules/
├── vpc/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   └── README.md
├── eks/
└── rds/

원칙:

  • 단일 책임: 하나의 모듈은 하나의 관심사만 처리
  • 재사용성: 환경별 변수로 동작 제어
  • 캡슐화: 내부 구현 숨기고 인터페이스(variables/outputs)만 노출
  • 버전 관리: Git 태그로 모듈 버전 고정

7. 공통 Module과 환경별 코드는 어떻게 분리하나요?

infra/
├── modules/          # 공통 모듈
│   ├── vpc/
│   ├── eks/
│   └── rds/
├── environments/
│   ├── dev/
│   │   ├── main.tf   # module 호출 + dev 변수
│   │   └── terraform.tfvars
│   ├── stg/
│   └── prd/

환경별 terraform.tfvars로 인스턴스 크기, 개수 등만 다르게 설정합니다.

8. Module 버전 관리와 Registry 활용은?

module "vpc" {
  source  = "git::https://gitlab.com/team/modules.git//vpc?ref=v1.2.0"
  # 또는 Terraform Registry
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
}
  • Git 태그로 버전 고정 (ref=v1.2.0)
  • ~> 연산자로 호환 버전 범위 지정
  • 내부 Module Registry 구축으로 팀 표준화

멀티 환경 관리

9. Workspace vs 디렉토리 분리, 어떤 방식을 선호하나요?

구분Workspace디렉토리 분리
State같은 Backend, 다른 State완전 분리
코드동일 코드환경별 다를 수 있음
격리 수준낮음높음
실수 위험workspace 전환 실수 가능디렉토리 명확

실무 권장: 디렉토리 분리. DEV와 PRD의 리소스 구성이 다를 수 있고, 실수 방지에 유리합니다.

10. Multi-Account 인프라 관리 방법은?

# Provider alias로 여러 Account 관리
provider "aws" {
  alias   = "network"
  region  = "ap-northeast-2"
  assume_role {
    role_arn = "arn:aws:iam::NETWORK_ACCOUNT:role/terraform"
  }
}

resource "aws_transit_gateway" "main" {
  provider = aws.network
  # ...
}

Account 분리 패턴:

  • NTW: 네트워크 중앙 관리 (TGW, VPN)
  • SEC: 보안 (GuardDuty, Config)
  • DEV/STG/PRD: 워크로드

고급 기능

11. data source와 resource의 차이는?

  • resource: Terraform이 생성/관리하는 리소스
  • data source: 이미 존재하는 리소스의 정보를 읽어오기만 함
# 기존 VPC 정보 조회
data "aws_vpc" "existing" {
  filter {
    name   = "tag:Name"
    values = ["production-vpc"]
  }
}

# 조회한 VPC에 서브넷 생성
resource "aws_subnet" "new" {
  vpc_id = data.aws_vpc.existing.id
  # ...
}

12. depends_on은 언제 사용하나요?

Terraform이 자동으로 의존성을 추론하지 못하는 경우:

resource "aws_iam_role_policy" "example" {
  # ...
}

resource "aws_instance" "example" {
  # IAM Policy가 완전히 적용된 후 인스턴스 생성
  depends_on = [aws_iam_role_policy.example]
}

주의: 가능하면 참조를 통한 암시적 의존성을 사용하고, depends_on은 최소화합니다.

13. for_each와 count의 차이, 선택 기준은?

# count: 인덱스 기반 (순서 변경 시 재생성 위험)
resource "aws_subnet" "example" {
  count = 3
  cidr_block = var.subnet_cidrs[count.index]
}

# for_each: 키 기반 (안정적, 권장)
resource "aws_subnet" "example" {
  for_each   = toset(var.subnet_names)
  cidr_block = var.subnet_config[each.key].cidr
}

for_each 권장: 중간 항목 삭제 시 다른 리소스에 영향 없음.

14. Dynamic Block은 어떤 경우에 사용하나요?

반복적인 중첩 블록을 동적으로 생성할 때:

resource "aws_security_group" "example" {
  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      from_port   = ingress.value.port
      to_port     = ingress.value.port
      protocol    = "tcp"
      cidr_blocks = ingress.value.cidrs
    }
  }
}

15. Lifecycle 블록 옵션을 설명해주세요.

resource "aws_instance" "example" {
  lifecycle {
    create_before_destroy = true   # 삭제 전 새 리소스 생성
    prevent_destroy       = true   # 실수로 삭제 방지
    ignore_changes        = [tags] # 특정 속성 변경 무시
    replace_triggered_by  = [...]  # 특정 변경 시 교체
  }
}

상태 관리 & 트러블슈팅

16. State가 꼬였을 때 대응 방법은?

  1. state rm: State에서 리소스 제거 (실제 삭제 안함)

    terraform state rm aws_instance.old
  2. state mv: State 내 리소스 이동/이름 변경

    terraform state mv aws_instance.old aws_instance.new
  3. state pull/push: State 파일 직접 수정 (최후의 수단)

  4. import: 실제 리소스를 State에 다시 연결

17. Plan에서는 정상인데 Apply에서 실패하는 경우는?

원인:

  • 권한 부족: Plan은 읽기만, Apply는 쓰기 권한 필요
  • 리소스 제약: 쿼터 초과, 리전 제한
  • 동시성 충돌: 다른 프로세스가 같은 리소스 변경
  • API 일시 오류: AWS API Rate Limiting

대응: 에러 메시지 확인 → 해당 리소스만 targeted apply

terraform apply -target=aws_instance.example

18. terraform plan 결과에 예상치 못한 변경이 있을 때?

  1. terraform state show <resource>로 현재 State 확인
  2. 실제 리소스와 비교 (콘솔/CLI)
  3. 원인 분석:
    • 수동 변경이 있었는지 (Drift)
    • Provider 업그레이드로 스키마 변경
    • ignore_changes 누락

19. 대규모 인프라에서 Plan/Apply 속도 개선 방법은?

  • State 분리: 도메인별로 State 파일 분리 (VPC, EKS, App 별도)
  • Targeted Apply: -target 옵션으로 범위 제한
  • Parallelism: -parallelism=N 옵션 (기본 10)
  • Provider 캐시: plugin_cache_dir 설정

20. Terraform과 다른 IaC 도구 비교

구분TerraformPulumiCDKCloudFormation
언어HCLPython/TS/GoPython/TSYAML/JSON
멀티 클라우드강점강점AWS 전용AWS 전용
State외부 관리Pulumi CloudCloudFormationCloudFormation
학습 곡선중간낮음 (기존 언어)낮음높음
커뮤니티최대성장 중성장 중AWS 공식

Terraform 선택 이유: 멀티 클라우드 지원, 성숙한 생태계, 풍부한 Provider/Module.

Back to Blog

Related Posts

View All Posts »