--- id: devops-terraform-patterns title: Terraform — 모듈 / 워크스페이스 / state category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [devops, terraform, iac, vibe-coding] tech_stack: { language: "HCL / Terraform", applicable_to: ["DevOps"] } applied_in: [] aliases: [terraform, IaC, state file, workspace, module, OpenTofu] --- # Terraform > Infra 를 코드로. **Module = 재사용 단위, State = 진실 source, Workspace = 환경 분리**. 1.x 부터 OpenTofu 로 fork — 둘 다 호환. State 는 항상 remote backend. ## 📖 핵심 개념 - HCL: 선언형. resource / data / module / variable / output. - State: `terraform.tfstate` — 무엇이 만들어졌는지. - Plan / Apply: dry-run / 실행. - Module: 재사용 가능한 폴더 묶음. - Workspace: 같은 코드 다른 state. ## 💻 코드 패턴 ### 폴더 구조 ``` infra/ modules/ rds/ main.tf variables.tf outputs.tf envs/ dev/ main.tf backend.tf terraform.tfvars prod/ main.tf backend.tf terraform.tfvars ``` ### Module ```hcl # modules/rds/main.tf variable "name" { type = string } variable "instance_class" { type = string; default = "db.t4g.micro" } variable "vpc_security_group_ids" { type = list(string) } variable "subnet_ids" { type = list(string) } resource "aws_db_subnet_group" "this" { name = "${var.name}-subnets" subnet_ids = var.subnet_ids } resource "aws_db_instance" "this" { identifier = var.name engine = "postgres" engine_version = "16" instance_class = var.instance_class allocated_storage = 20 storage_encrypted = true vpc_security_group_ids = var.vpc_security_group_ids db_subnet_group_name = aws_db_subnet_group.this.name backup_retention_period = 7 deletion_protection = true skip_final_snapshot = false username = "app" manage_master_user_password = true } output "endpoint" { value = aws_db_instance.this.endpoint } ``` ### Env 호출 ```hcl # envs/prod/main.tf module "rds_main" { source = "../../modules/rds" name = "app-prod" instance_class = "db.r7g.large" vpc_security_group_ids = [aws_security_group.db.id] subnet_ids = data.aws_subnets.private.ids } output "rds_endpoint" { value = module.rds_main.endpoint } ``` ### Backend (remote state) ```hcl # envs/prod/backend.tf terraform { required_version = ">= 1.6" backend "s3" { bucket = "tf-state-myco-prod" key = "main.tfstate" region = "us-east-1" dynamodb_table = "tf-locks" encrypt = true } } ``` ### Provider lock ```hcl terraform { required_providers { aws = { source = "hashicorp/aws"; version = "~> 5.0" } } } ``` `.terraform.lock.hcl` 은 commit. ### Variables / tfvars ```hcl # variables.tf variable "env" { type = string } variable "region" { type = string; default = "us-east-1" } # terraform.tfvars (NOT committed if secrets) env = "prod" ``` ### Workflow ```bash terraform init terraform fmt -recursive terraform validate terraform plan -out=tfplan terraform apply tfplan ``` ### Secrets ```hcl # ❌ tfvars 안 secret db_password = "..." # ✅ env or AWS Secrets Manager data "aws_secretsmanager_secret_version" "db" { secret_id = "app/db" } resource "aws_db_instance" "this" { password = jsondecode(data.aws_secretsmanager_secret_version.db.secret_string)["password"] } ``` ### tfsec / checkov (보안 검사) ```bash tfsec . checkov -d . ``` CI 에서 plan + tfsec 자동. ### Drift detection ```bash terraform plan -detailed-exitcode # exit 0 = no change, 2 = drift ``` ## 🤔 의사결정 기준 | 환경 | 분리 | |---|---| | 작은 팀, 1 env | workspace 또는 단일 폴더 | | Multi-env | 폴더 분리 (envs/dev, envs/prod) | | 큰 조직 / 격리 | 별도 state file + IAM 분리 | | Shared infra (VPC) | 별도 module + remote state read | | Pulumi vs Terraform | Pulumi = TS/Python, Terraform = HCL | | OpenTofu | 라이센스 자유 — 같이 호환 | ## ❌ 안티패턴 - **State 로컬 파일**: 잃으면 인프라 분실. 항상 remote. - **State lock 없음**: 동시 apply 시 깨짐. dynamodb 또는 S3 locking. - **Secret tfvars 에 commit**: leak. - **수동 console 변경 + apply**: drift, 다음 apply 가 덮음. - **Module 거대 (1000줄)**: 작게 단위. - **Resource 직접 dev/prod 혼용**: 분리. - **Provider version unlock**: 무작위 brake. - **`terraform destroy` 실수**: prod 보호 — `prevent_destroy` lifecycle. ## 🤖 LLM 활용 힌트 - modules/ + envs/ + remote state. - secret = AWS Secrets Manager / Vault. - CI = init + fmt + validate + plan + tfsec. ## 🔗 관련 문서 - [[DevOps_IaC_Drift_Detection]] - [[DevOps_Secrets_Rotation_Automation]] - [[DevOps_Kubernetes_Basics]]