· Interview · 9 min read
Terraform 면접 질문 20선 — IaC 설계부터 상태 관리까지
Terraform으로 멀티 환경 인프라를 관리하는 DevOps 엔지니어를 위한 면접 질문. State 관리, 모듈화, Workspace, 트러블슈팅 핵심 정리.
기초 개념
1. Terraform의 동작 원리를 설명해주세요.
- Init: Provider 플러그인 다운로드, Backend 초기화
- Plan: 현재 State와 코드 비교 → 변경 계획 생성
- Apply: Plan 기반으로 실제 리소스 생성/수정/삭제
- Destroy: 관리 중인 모든 리소스 삭제
핵심: Terraform은 선언적(Declarative) 도구. “어떻게”가 아닌 “무엇을” 정의합니다.
2. Terraform State의 역할과 중요성은?
State 파일(terraform.tfstate)은:
- 실제 인프라와 코드의 매핑 정보 저장
- Plan 시 변경사항 계산의 기준점
- 리소스 간 의존성 추적
- 메타데이터 (리소스 ID, 속성) 저장
State 없이는 Terraform이 기존 인프라를 인식할 수 없습니다.
3. Local State vs Remote State 차이와 선택 기준은?
| 구분 | Local | Remote (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가 꼬였을 때 대응 방법은?
state rm: State에서 리소스 제거 (실제 삭제 안함)
terraform state rm aws_instance.oldstate mv: State 내 리소스 이동/이름 변경
terraform state mv aws_instance.old aws_instance.newstate pull/push: State 파일 직접 수정 (최후의 수단)
import: 실제 리소스를 State에 다시 연결
17. Plan에서는 정상인데 Apply에서 실패하는 경우는?
원인:
- 권한 부족: Plan은 읽기만, Apply는 쓰기 권한 필요
- 리소스 제약: 쿼터 초과, 리전 제한
- 동시성 충돌: 다른 프로세스가 같은 리소스 변경
- API 일시 오류: AWS API Rate Limiting
대응: 에러 메시지 확인 → 해당 리소스만 targeted apply
terraform apply -target=aws_instance.example18. terraform plan 결과에 예상치 못한 변경이 있을 때?
terraform state show <resource>로 현재 State 확인- 실제 리소스와 비교 (콘솔/CLI)
- 원인 분석:
- 수동 변경이 있었는지 (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 도구 비교
| 구분 | Terraform | Pulumi | CDK | CloudFormation |
|---|---|---|---|---|
| 언어 | HCL | Python/TS/Go | Python/TS | YAML/JSON |
| 멀티 클라우드 | 강점 | 강점 | AWS 전용 | AWS 전용 |
| State | 외부 관리 | Pulumi Cloud | CloudFormation | CloudFormation |
| 학습 곡선 | 중간 | 낮음 (기존 언어) | 낮음 | 높음 |
| 커뮤니티 | 최대 | 성장 중 | 성장 중 | AWS 공식 |
Terraform 선택 이유: 멀티 클라우드 지원, 성숙한 생태계, 풍부한 Provider/Module.