1. 시작점: 왜 코드로 인프라를 관리하는가
AWS 콘솔에서 VPC를 클릭으로 만들면 어떤 일이 벌어지는가:
문제 1: "이 VPC 누가 만들었어? 설정이 왜 이래?" → 추적 불가
문제 2: "dev 환경이랑 똑같이 prod 만들어줘" → 수동 반복, 실수 발생
문제 3: "3개월 전 상태로 롤백해줘" → 불가능
문제 4: "인프라 변경 사항 코드리뷰 해줘" → 리뷰할 코드가 없음
문제 5: "이 인프라 전부 삭제해줘" → 뭘 만들었는지 기억 못함
이 5가지 문제를 해결하는 것이 IaC (Infrastructure as Code) — 인프라를 코드로 선언하고,
Git으로 버전 관리하고, 자동으로 생성/변경/삭제하는 방식이다.
CGV 프로젝트의 실제 예:
# 콘솔 클릭 대신 이 코드 한 줄이면 VPC가 생긴다
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
}
terraform plan # "VPC 1개 만들 예정입니다" (미리보기)
terraform apply # 실제로 AWS API를 호출해서 VPC 생성
terraform destroy # VPC 삭제
2. IaC란 무엇인가
2.1 핵심 원칙
IaC에는 두 가지 접근 방식이 있다:
| 접근 방식 | 설명 | 도구 |
|---|---|---|
| 선언형 (Declarative) | "이런 상태여야 한다" 선언 → 도구가 알아서 맞춤 | Terraform, CloudFormation |
| 명령형 (Imperative) | "이 순서대로 실행하라" 명령 | Ansible, Shell Script |
Terraform은 선언형이다. "VPC가 있어야 한다"고 선언하면:
- 없으면 → 생성
- 이미 있으면 → 변경 사항만 적용
- 코드에서 삭제하면 → 실제 리소스도 삭제
# "이 상태여야 한다" — 선언형
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16" # CIDR이 이것이어야 한다
enable_dns_hostnames = true # DNS가 켜져 있어야 한다
}
# Terraform이 현재 상태와 비교해서:
# - VPC 없음 → 생성
# - VPC 있는데 DNS가 꺼져있음 → 수정
# - VPC 있고 설정도 같음 → 아무것도 안 함
2.2 IaC의 이점
| 이점 | 설명 | CGV 예시 |
|---|---|---|
| 버전 관리 | Git으로 인프라 변경 이력 추적 | VPC CIDR 변경 → PR 리뷰 가능 |
| 재현성 | 같은 코드 = 같은 인프라 | dev/prod 환경 일관성 |
| 자동화 | CI/CD에서 인프라 배포 | terraform apply 한 줄 |
| 문서화 | 코드 자체가 인프라 명세서 | "SG 규칙이 뭐야?" → 코드 보면 됨 |
| 삭제 | 만든 것을 정확히 역순으로 삭제 | terraform destroy → 비용 $0 |
3. Terraform 핵심 구조
3.1 Provider — "어떤 클라우드?"
Provider는 Terraform이 통신할 대상 (AWS, GCP, Azure 등)을 정의한다.
# "AWS를 쓸 것이고, 서울 리전이다"
provider "aws" {
region = "ap-northeast-2"
}
terraform init 실행 시 해당 Provider 플러그인이 .terraform/ 디렉토리에 다운로드된다.
Provider가 AWS API 호출 방법을 알고 있으므로, 우리는 HCL로 선언만 하면 된다.
우리가 쓰는 코드 (HCL)
↓
Terraform Core (plan/apply 엔진)
↓
AWS Provider Plugin (API 호출 변환)
↓
AWS API (실제 리소스 생성)
3.2 Resource — "무엇을 만들 것인가"
Resource는 실제로 만들/변경/삭제할 인프라 리소스다.
resource "aws_vpc" "main" {
# ^^^^^^^^ ^^^^
# 리소스 타입 로컬 이름
cidr_block = "10.0.0.0/16"
}
- 리소스 타입 (
aws_vpc): Provider가 제공하는 리소스 종류.aws_접두사 = AWS Provider. - 로컬 이름 (
main): 이 Terraform 코드 안에서 참조할 이름. AWS에는 보이지 않음. - 속성: CIDR, 이름, 태그 등 설정값.
3.3 Data Source — "이미 있는 것을 조회"
Resource가 "만드는 것"이라면, Data Source는 "이미 존재하는 것을 읽어오는 것"이다.
# 이미 존재하는 다른 스택의 State를 읽어오기
data "terraform_remote_state" "vpc" {
backend = "s3"
config = {
bucket = "cgv-terraform-state"
key = "cgv-vpc/terraform.tfstate"
region = "ap-northeast-2"
}
}
# 읽어온 값 사용
resource "aws_security_group" "alb" {
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
# ^^^^ Data Source 참조
}
CGV에서 cgv-security 스택이 cgv-vpc 스택의 VPC ID를 참조할 때 이 패턴을 쓴다.
3.4 Variable — "외부에서 값 주입"
하드코딩 대신 변수로 만들면 재사용 가능:
variable "cluster_name" {
description = "EKS 클러스터 이름"
type = string
default = "cgv-cluster"
}
resource "aws_eks_cluster" "main" {
name = var.cluster_name # 변수 참조
}
변수 값 전달 방법 (우선순위 순):
terraform apply -var="cluster_name=my-cluster"(CLI)terraform.tfvars파일TF_VAR_cluster_name환경변수default값
sensitive = true로 표시하면 Plan/Apply 출력에서 값이 마스킹된다:
variable "db_password" {
type = string
sensitive = true # Plan 출력에서 (sensitive value) 표시
}
3.5 Output — "만든 결과를 외부에 노출"
Resource를 만들고 나면 ID, 엔드포인트 등이 생긴다. Output으로 노출하면 다른 스택에서 참조 가능:
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id # 생성 후 자동 부여되는 ID
}
$ terraform output vpc_id
"vpc-0a1b2c3d4e5f6"
3.6 Local — "코드 내부 계산값"
반복되는 표현식을 로컬 변수로 정리:
locals {
oidc_provider_url = replace(aws_iam_openid_connect_provider.eks.url, "https://", "")
oidc_provider_arn = aws_iam_openid_connect_provider.eks.arn
}
# IRSA Role 5개에서 반복 사용
"${local.oidc_provider_url}:sub" = "system:serviceaccount:monitoring:monitoring-sa"
"${local.oidc_provider_url}:sub" = "system:serviceaccount:kube-system:karpenter"
4. Terraform 동작 원리: init → plan → apply
4.1 terraform init
$ terraform init
초기화 단계. 세 가지를 수행한다:
- Provider 플러그인 다운로드 →
.terraform/providers/에 저장 - Backend 설정 → State 파일 저장 위치 연결 (S3 등)
- Module 다운로드 → 외부 모듈 사용 시
infra/cgv-vpc/
├── main.tf
├── backend.tf
├── .terraform/ ← init이 생성하는 디렉토리
│ ├── providers/ ← AWS Provider 바이너리
│ └── terraform.tfstate ← Backend 설정 메타데이터
└── .terraform.lock.hcl ← Provider 버전 Lock 파일 (Git 커밋 대상)
4.2 terraform plan — "무엇이 변할 것인가"
$ terraform plan
현재 State(=지금 AWS에 있는 것)와 코드(=원하는 상태)를 비교해서 차이를 보여준다.
# Plan 출력 예시
+ aws_vpc.main # 초록 + : 새로 생성
~ aws_subnet.app_private_a # 노랑 ~ : 속성 변경 (in-place)
- aws_eip.old # 빨강 - : 삭제
-/+ aws_db_instance.mysql # 삭제 후 재생성 (파괴적 변경)
내부적으로 Terraform은 DAG (Directed Acyclic Graph) 를 만든다:
aws_vpc.main
├── aws_subnet.public_a
│ └── aws_nat_gateway.nat_a
│ └── aws_route_table.app_private_a
├── aws_subnet.app_private_a
└── aws_internet_gateway.main
└── aws_route_table.public
- VPC가 먼저 만들어져야 Subnet을 만들 수 있다 → 의존성 자동 추론
- 서로 의존성 없는 리소스는 병렬로 생성한다 (예: Subnet A와 Subnet C)
depends_on으로 명시적 의존성 추가도 가능
4.3 terraform apply — "실제로 적용"
$ terraform apply
Plan 결과를 보여주고 yes 입력 시 실제 AWS API를 호출한다.-auto-approve 플래그로 확인 없이 즉시 적용 가능 (CI/CD에서 사용).
실행 순서:
- Plan 계산 (DAG 생성)
- DAG 순서대로 AWS API 호출
- 각 리소스 생성/수정/삭제 결과를 State 파일에 기록
- 완료 후 요약 출력
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
Outputs:
vpc_id = "vpc-0a1b2c3d4e5f6"
4.4 terraform destroy — "전부 삭제"
$ terraform destroy
State에 기록된 모든 리소스를 역순으로 삭제한다.
CGV 프로젝트에서 실습 후 비용 발생을 막기 위해 반드시 실행해야 하는 명령.
4.5 전체 흐름 요약
코드 작성 (.tf 파일)
↓
terraform init ← Provider 다운로드, Backend 연결
↓
terraform plan ← 코드 vs State 비교 → 변경 사항 출력
↓
terraform apply ← AWS API 호출 → 리소스 생성 → State 업데이트
↓
terraform destroy ← State 기반으로 역순 삭제
5. State — Terraform의 핵심이자 가장 중요한 개념
5.1 State란?
State는 "Terraform이 지금까지 만든 것의 목록" 을 기록한 JSON 파일이다.
// terraform.tfstate (실제 파일 구조 요약)
{
"resources": [
{
"type": "aws_vpc",
"name": "main",
"instances": [{
"attributes": {
"id": "vpc-0a1b2c3d4e5f6",
"cidr_block": "10.0.0.0/16"
}
}]
}
]
}
왜 필요한가? Terraform은 AWS를 전수 조사하지 않는다.
"내가 만든 VPC가 vpc-0a1b2c3d라는 것"을 State에 기록해두고,
다음 plan 때 이 VPC의 현재 상태를 API로 조회해서 코드와 비교한다.
terraform plan의 실제 동작:
1. State 파일 읽기 → "내가 만든 VPC는 vpc-0a1b2c3d"
2. AWS API 호출 → "vpc-0a1b2c3d의 현재 CIDR은 10.0.0.0/16"
3. 코드 읽기 → "코드에서 원하는 CIDR은 10.0.0.0/16"
4. 비교 → "같음 → 변경 없음" or "다름 → 수정 필요"
5.2 State가 없으면 벌어지는 일
State 파일을 삭제하면:
- Terraform은 "내가 만든 리소스가 없다"고 판단
- terraform plan → "12개 리소스를 새로 만들겠습니다"
- terraform apply → 이미 있는데 또 만들려고 시도 → 이름 충돌 에러
- terraform destroy → "삭제할 것이 없습니다" → AWS에 리소스가 남아있는데 삭제 불가
→ State = Terraform의 기억. 잃어버리면 인프라를 관리할 수 없다.
5.3 Local State vs Remote State
| 항목 | Local State | Remote State (S3) |
|---|---|---|
| 저장 위치 | 로컬 파일 (terraform.tfstate) | S3 버킷 |
| 팀 협업 | 불가 (내 PC에만 있음) | 가능 (S3에서 공유) |
| 동시 실행 방지 | 없음 | DynamoDB Lock |
| 백업 | 없음 | S3 버전 관리 |
| 보안 | 로컬에 평문 저장 | S3 암호화 (AES256) |
CGV 프로젝트는 s3-dynamodb 스택만 Local Backend, 나머지 5개 스택(db, ecr,eks,sg,vpc)은 S3 Backend:
# s3-dynamodb: Local Backend (S3 버킷이 아직 없으니까)
terraform {
# backend 설정 없음 = Local
}
# cgv-vpc ~ cgv-ecr: S3 Backend
terraform {
backend "s3" {
bucket = "cgv-terraform-state" # State 저장 버킷
key = "cgv-vpc/terraform.tfstate" # 스택별 고유 경로
region = "ap-northeast-2"
dynamodb_table = "cgv-terraform-lock" # 동시 실행 방지
encrypt = true # 암호화
}
}
5.4 State Locking — 동시 실행 방지
동시에 두 명이 terraform apply를 실행하면:
시간 개발자 A 개발자 B
t=0 plan (VPC 생성) plan (VPC 생성)
t=1 apply 시작 apply 시작
t=2 VPC 생성 성공 VPC 생성 → 이름 충돌 에러
t=3 State 업데이트 State 업데이트 → 꼬임!
DynamoDB 테이블로 Lock을 걸면:
시간 개발자 A 개발자 B
t=0 Lock 획득 (DynamoDB에 기록)
t=1 plan + apply Lock 획득 시도 → 실패
t=2 State 업데이트 "State is locked" 에러 출력
t=3 Lock 해제 Lock 획득 → plan + apply
5.5 terraform import — 기존 리소스를 State에 등록
콘솔에서 수동으로 만든 리소스를 Terraform 관리로 가져오기:
# AWS 콘솔에서 만든 VPC를 Terraform State에 등록
terraform import aws_vpc.main vpc-0a1b2c3d4e5f6
import 후에도 .tf 코드는 직접 작성해야 한다. import는 State만 업데이트하고 코드를 생성하지 않는다.
6. HCL 문법 Deep Dive
6.1 Block 구조
HCL(HashiCorp Configuration Language)의 모든 것은 Block이다:
block_type "label_1" "label_2" {
attribute = "value"
nested_block {
attribute = "value"
}
}
| Block 종류 | 라벨 수 | 예시 |
|---|---|---|
terraform |
0 | terraform { required_version = ">= 1.5.0" } |
provider |
1 | provider "aws" { region = "ap-northeast-2" } |
resource |
2 | resource "aws_vpc" "main" { ... } |
data |
2 | data "terraform_remote_state" "vpc" { ... } |
variable |
1 | variable "cluster_name" { ... } |
output |
1 | output "vpc_id" { ... } |
locals |
0 | locals { ... } |
6.2 타입 시스템
# 기본 타입
variable "name" { type = string } # "cgv-cluster"
variable "port" { type = number } # 6379
variable "enabled" { type = bool } # true
# 컬렉션 타입
variable "subnet_ids" { type = list(string) } # ["subnet-a", "subnet-c"]
variable "tags" { type = map(string) } # { Name = "cgv", Env = "prod" }
# 구조체 타입
variable "scaling" {
type = object({
min = number
max = number
desired = number
})
default = { min = 1, max = 1, desired = 1 }
}
6.3 리소스 참조 (Reference)
# 같은 파일/디렉토리 안에서 다른 리소스의 속성 참조
resource "aws_subnet" "public_a" {
vpc_id = aws_vpc.main.id
# ^^^^^^^^^^^^^^^^^
# resource_type.name.attribute
}
# Data Source 참조
vpc_id = data.terraform_remote_state.vpc.outputs.vpc_id
# Variable 참조
name = var.cluster_name
# Local 참조
arn = local.oidc_provider_arn
6.4 문자열 보간 (String Interpolation)
tags = {
Name = "cgv-${var.environment}-mysql" # → "cgv-dev-mysql" or "cgv-prod-mysql"
}
# 멀티라인 문자열
description = <<-EOT
CGV Queue System
Environment: ${var.environment}
EOT
6.5 조건 표현식
# 조건 ? 참값 : 거짓값
multi_az = var.environment == "prod" ? true : false
# count와 함께 사용 → 리소스 조건부 생성
resource "aws_elasticache_replication_group" "redis" {
count = var.create_elasticache ? 1 : 0 # false면 아예 안 만듦
# ...
}
6.6 내장 함수
# 자주 쓰는 함수들
replace("https://oidc.eks...", "https://", "") # 문자열 치환
file("${path.module}/policy.json") # 파일 읽기
jsonencode({ key = "value" }) # Map → JSON 문자열
formatdate("YYYY-MM-DD", timestamp()) # 날짜 포맷
try(expression, fallback) # 에러 시 대체값
contains(["dev", "prod"], var.env) # 리스트에 포함 여부
7. Meta-arguments — 리소스 제어의 핵심
7.1 depends_on — 명시적 의존성
Terraform은 참조 관계에서 의존성을 자동 추론하지만, 참조가 없는 암묵적 의존성은 수동 지정:
resource "aws_eks_addon" "coredns" {
cluster_name = aws_eks_cluster.main.name
addon_name = "coredns"
# CoreDNS는 Deployment → 노드가 있어야 스케줄링됨
# cluster_name 참조만으로는 노드 그룹 의존성이 잡히지 않음
depends_on = [aws_eks_node_group.system]
}
7.2 count — 조건부 생성 / 다중 생성
# 조건부: Prod만 ElastiCache 생성
resource "aws_elasticache_replication_group" "redis" {
count = var.create_elasticache ? 1 : 0
# ...
}
# 참조 시 인덱스 필요
subnet_group_name = aws_elasticache_subnet_group.redis[0].name
7.3 for_each — Map/Set 기반 다중 생성
# 여러 S3 버킷을 한 번에 생성
resource "aws_s3_bucket" "buckets" {
for_each = toset(["logs", "cache", "backup"])
bucket = "cgv-${each.key}-${data.aws_caller_identity.current.account_id}"
}
count vs for_each:
count: 인덱스 기반 → 중간 삭제 시 나머지 재생성 위험for_each: 키 기반 → 특정 항목만 추가/삭제 가능 (권장)
7.4 lifecycle — 리소스 생명주기 제어
resource "aws_s3_bucket" "terraform_state" {
bucket = "cgv-terraform-state"
lifecycle {
prevent_destroy = true # terraform destroy 시 이 리소스 삭제 거부
}
}
| 속성 | 설명 | 사용 예시 |
|---|---|---|
prevent_destroy |
삭제 시도 시 에러 | State 버킷, RDS |
create_before_destroy |
교체 시 신규 먼저 생성 | 무중단 교체 |
ignore_changes |
특정 속성 변경 무시 | 외부에서 수정되는 태그 |
8. Micro-stacks 패턴과 Remote State
8.1 모놀리식 vs Micro-stacks
모놀리식 — 모든 리소스가 하나의 State:
infra/
└── main.tf ← VPC + SG + RDS + EKS + ECR 전부 한 파일
└── terraform.tfstate (하나)
문제점:
terraform plan이 모든 리소스를 검사 → 느림- VPC 수정이 EKS에 영향 → blast radius가 큼
- State 하나 꼬이면 전체 인프라 관리 불가
Micro-stacks — 관심사 별로 State 분리:
infra/
├── s3-dynamodb/ → terraform.tfstate (독립)
├── cgv-vpc/ → terraform.tfstate (독립)
├── cgv-security/ → terraform.tfstate (독립)
├── cgv-database/ → terraform.tfstate (독립)
├── cgv-eks/ → terraform.tfstate (독립)
└── cgv-ecr/ → terraform.tfstate (독립)
장점:
- 각 스택 독립적으로 plan/apply → 빠름
- VPC 변경이 EKS State에 영향 없음 → blast radius 최소화
- 팀원이 동시에 다른 스택 작업 가능
8.2 스택 간 통신: terraform_remote_state
스택이 분리되면 "cgv-security가 cgv-vpc의 VPC ID를 어떻게 알지?" 문제가 생긴다.
해결: Output으로 노출 → Data Source로 참조
┌─ cgv-vpc ──────────────┐ ┌─ cgv-security ──────────────┐
│ │ │ │
│ resource "aws_vpc" ... │ │ data "terraform_remote_state" │
│ │ │ "vpc" { │
│ output "vpc_id" { │────▶│ config = { │
│ value = aws_vpc...id │ │ key = "cgv-vpc/..." │
│ } │ │ } │
│ │ │ } │
│ State: cgv-vpc/*.tfstate│ │ │
└────────────────────────┘ │ vpc_id = data...vpc.outputs │
│ .vpc_id │
└──────────────────────────────┘
8.3 CGV 6-Stack 의존성 맵
s3-dynamodb (부트스트랩, 의존성 없음)
↓
cgv-vpc (네트워크)
↓ ↘
cgv-security cgv-database ← vpc + security 참조
↓ ↓
cgv-eks ← vpc 참조 │
↓ │
cgv-ecr (독립) │
배포 순서: 1→2→3→4→5→6 (의존성 체인)
삭제 순서: 6→5→4→3→2→1 (역순)
8.4 Backend Key 규칙
각 스택의 State 파일이 S3에 저장되는 경로:
s3://cgv-terraform-state/
├── cgv-vpc/terraform.tfstate
├── cgv-security/terraform.tfstate
├── cgv-database/terraform.tfstate
├── cgv-eks/terraform.tfstate
└── cgv-ecr/terraform.tfstate
key 값이 스택 간 겹치면 안 된다 — 서로의 State를 덮어쓰게 됨.
9. IaC 도구 비교
| 항목 | Terraform | CloudFormation | Pulumi | Ansible |
|---|---|---|---|---|
| 제작사 | HashiCorp | AWS | Pulumi | Red Hat |
| 언어 | HCL | JSON/YAML | Python/TS/Go | YAML |
| 클라우드 | 멀티 (AWS/GCP/Azure) | AWS 전용 | 멀티 | 멀티 |
| 접근 방식 | 선언형 | 선언형 | 명령형+선언형 | 명령형 |
| State | 자체 관리 (S3 등) | AWS가 관리 | 자체/클라우드 | 없음 |
| 장점 | 멀티클라우드, 커뮤니티 | AWS 네이티브 통합 | 기존 언어 사용 | 설정 관리 강점 |
| 단점 | State 관리 필요 | AWS 종속 | 상대적으로 적은 커뮤니티 | Provisioning 약함 |
CGV가 Terraform을 선택한 이유:
- AWS 외 클라우드 전환 가능성 (멀티클라우드)
- HCL이 JSON/YAML보다 읽기 쉬움
- 커뮤니티와 모듈 생태계가 가장 큼
- DevOps 현업에서 사실상 표준
Terraform vs Ansible 차이:
- Terraform: Provisioning (인프라 생성) → "VPC, EKS, RDS를 만들어라"
- Ansible: Configuration Management (설정 관리) → "서버에 Nginx를 설치하고 설정해라"
- CGV에서는 Terraform으로 인프라 만들고, Helm으로 K8s 위에 앱 배포
10. 면접 대비 Q&A
Q1. "Terraform의 State가 뭐고 왜 중요한가요?"
State는 Terraform이 관리하는 리소스의 현재 상태를 기록한 JSON 파일입니다.
terraform plan이 코드(원하는 상태)와 State(현재 상태)를 비교해서 차이를 계산하므로,
State가 없으면 어떤 리소스가 존재하는지 알 수 없어 인프라 관리가 불가능합니다.팀 협업을 위해 S3에 저장하고, DynamoDB로 동시 실행을 방지합니다.
Q2. "Terraform plan과 apply의 차이는?"
plan은 Dry-run입니다. 코드와 State를 비교해서 "무엇이 변할 것인지" 미리보기만 합니다.
실제 AWS API를 호출하지 않습니다.apply는 plan 결과를 실제로 실행해서 리소스를 생성/수정/삭제하고 State를 업데이트합니다.plan을 먼저 확인하고 apply하는 것이 안전한 워크플로우입니다.
Q3. "모놀리식 Terraform 대신 Micro-stacks를 쓴 이유는?"
blast radius를 줄이기 위해서입니다. 하나의 State에 모든 리소스가 있으면
VPC 변경이 EKS까지 영향을 줄 수 있습니다. 6개 스택으로 분리하면
각 스택이 독립적으로 plan/apply되고, State 하나가 꼬여도 다른 스택은 영향받지 않습니다.대신 스택 간 통신은
terraform_remote_stateData Source로 Output을 참조합니다.
Q4. "선언형과 명령형의 차이는?"
선언형은 "최종 상태"를 선언합니다. "VPC가 있어야 한다" → 이미 있으면 아무것도 안 합니다.
명령형은 "실행 절차"를 지시합니다. "VPC를 만들어라" → 이미 있어도 또 만들려고 시도합니다.Terraform은 선언형이라 멱등성(idempotent)이 보장됩니다.
같은 코드를 10번 apply해도 결과는 동일합니다.
Q5. "Terraform State가 꼬이면 어떻게 복구하나요?"
- S3 버전 관리로 이전 State 복구 (가장 안전)
terraform state rm+terraform import로 수동 재등록terraform state pull/push로 State 직접 편집 (최후의 수단)예방이 중요합니다: DynamoDB Lock으로 동시 실행 방지, S3 Versioning으로 백업,
CI/CD에서만 apply 실행하는 것이 Best Practice입니다.
Q6. "Terraform에서 민감 정보(DB 비밀번호 등)는 어떻게 관리하나요?"
코드에 하드코딩하면 안 됩니다. 세 가지 방법이 있습니다:
variable "db_password" { sensitive = true }+ 환경변수TF_VAR_db_password- AWS Secrets Manager에서 Data Source로 조회
- Terraform Cloud/Vault를 사용한 시크릿 관리
CGV에서는 1번 방식을 사용하고, State 파일이 S3에 암호화 저장되어 있습니다.
Q7. "lifecycle의 prevent_destroy는 언제 쓰나요?"
State 버킷, RDS 등 실수로 삭제하면 복구가 어려운 리소스에 사용합니다.
terraform destroy를 실행해도 이 리소스만 건너뛰고 에러를 발생시킵니다.
CGV에서는cgv-terraform-stateS3 버킷에 적용되어 있습니다.
Q8. "count와 for_each의 차이와 언제 어떤 것을 쓰나요?"
count는 인덱스 기반 ([0],[1])이라 중간 요소를 삭제하면 뒤의 모든 리소스가
인덱스가 바뀌면서 재생성됩니다. 단순 조건부 생성(0 or 1)에 적합합니다.
for_each는 키 기반이라 특정 항목만 추가/삭제해도 나머지에 영향이 없습니다.
여러 개를 만들 때는for_each가 안전합니다.CGV에서는 ElastiCache 조건부 생성에
count를, 다중 리소스에는for_each를 사용합니다.
'Cloudwave > cgv-project' 카테고리의 다른 글
| CI/CD (0) | 2026.02.18 |
|---|---|
| 메시징 시스템 (0) | 2026.02.16 |
| WebSocket (0) | 2026.02.12 |
| 3. CI/CD 파이프라인 구축과 자동화 (0) | 2026.02.02 |
| 2. CGV 대기열 시스템 (0) | 2026.02.01 |