인프라 코드: Terraform

인프라를 코드로 정의하고 버전 관리하는 Terraform의 기본과 고급 사용법


인프라를 코드로 정의하고 버전 관리하는 Terraform의 기본과 고급 사용법

목표: 클라우드 인프라를 코드로 프로비저닝하고 관리할 수 있는 수준 [!warning] 실습 주의 terraform applyterraform destroy는 실제 클라우드 리소스와 비용을 바꾼다. 실습 계정, 별도 워크스페이스, plan 확인을 기본으로 둔다.


🎯 Terraform 개요

개념

인프라를 코드로 정의하고 관리.

graph LR
    TF["🔧 Terraform"] -->|"HCL"| CODE["📄 main.tf"]
    CODE -->|"plan"| PLAN["📋 실행 계획"]
    PLAN -->|"apply"| INFRA["☁️ 인프라"]
    INFRA -->|"state"| STATE["🗄️ 상태 파일"]

핵심 개념:

  • Provider: 클라우드 플랫폼 (AWS, Azure, GCP)
  • Resource: 생성할 인프라 (VM, DB, 네트워크)
  • Module: 재사용 가능한 코드 묶음
  • State: 인프라 상태 추적
  • Plan: 변경 사항 미리보기

🛠️ 설치

# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Linux
wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
unzip terraform_1.6.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/

# Windows (Chocolatey)
choco install terraform

# 버전 확인
terraform version

📝 기본 사용법

프로젝트 구조

terraform-project/
├── main.tf          # 메인 설정
├── variables.tf     # 변수 정의
├── outputs.tf       # 출력 정의
├── providers.tf     # 프로바이더 설정
├── terraform.tfvars # 변수 값
└── modules/         # 모듈
    └── vpc/

기본 설정

# providers.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "project/terraform.tfstate"
    region = "ap-northeast-2"
  }
}

provider "aws" {
  region = var.aws_region
}

리소스 생성

# main.tf
# VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "${var.project_name}-vpc"
  }
}

# 서브넷
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-2a"
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.project_name}-public-subnet"
  }
}

# EC2 인스턴스
resource "aws_instance" "web" {
  ami           = "ami-0c9c942bd7bf113a2"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "${var.project_name}-web"
  }
}

📊 변수와 출력

변수

# variables.tf
variable "aws_region" {
  description = "AWS 리전"
  type        = string
  default     = "ap-northeast-2"
}

variable "project_name" {
  description = "프로젝트 이름"
  type        = string
}

variable "instance_count" {
  description = "인스턴스 수"
  type        = number
  default     = 1
}

variable "enable_monitoring" {
  description = "모니터링 활성화"
  type        = bool
  default     = true
}
# terraform.tfvars
aws_region     = "ap-northeast-2"
project_name   = "my-project"
instance_count = 2

출력

# outputs.tf
output "vpc_id" {
  description = "VPC ID"
  value       = aws_vpc.main.id
}

output "instance_ips" {
  description = "인스턴스 IP 목록"
  value       = aws_instance.web[*].public_ip
}

🚀 명령어

기본

# 초기화
terraform init

# 포맷
terraform fmt

# 검증
terraform validate

# 계획
terraform plan
terraform plan -out=tfplan

# 적용
terraform apply
terraform apply tfplan
terraform apply -auto-approve

# 파괴
terraform destroy
terraform destroy -target=aws_instance.web

상태 관리

# 상태 확인
terraform show

# 상태 목록
terraform state list

# 상태 이동
terraform state mv aws_instance.web aws_instance.new_web

# 상태 가져오기
terraform import aws_instance.web i-1234567890abcdef0

# 상태 잠금 해제
terraform force-unlock LOCK_ID

📦 모듈

모듈 사용

# main.tf
module "vpc" {
  source = "./modules/vpc"

  vpc_cidr     = "10.0.0.0/16"
  project_name = var.project_name
}

module "ec2" {
  source = "./modules/ec2"

  instance_count = var.instance_count
  subnet_id      = module.vpc.public_subnet_id
  project_name   = var.project_name
}

모듈 작성

# modules/vpc/main.tf
resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr
  
  tags = {
    Name = "${var.project_name}-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, 1)
  availability_zone = "${var.aws_region}a"

  tags = {
    Name = "${var.project_name}-public-subnet"
  }
}
# modules/vpc/variables.tf
variable "vpc_cidr" {
  type = string
}

variable "project_name" {
  type = string
}

variable "aws_region" {
  type    = string
  default = "ap-northeast-2"
}
# modules/vpc/outputs.tf
output "vpc_id" {
  value = aws_vpc.main.id
}

output "public_subnet_id" {
  value = aws_subnet.public.id
}

🔄 워크스페이스

사용

# 워크스페이스 목록
terraform workspace list

# 워크스페이스 생성
terraform workspace new staging
terraform workspace new production

# 전환
terraform workspace select staging

# 현재 워크스페이스 확인
terraform workspace show

설정

# main.tf
locals {
  env = terraform.workspace
  
  instance_config = {
    default = {
      instance_type = "t3.micro"
      count         = 1
    }
    staging = {
      instance_type = "t3.small"
      count         = 2
    }
    production = {
      instance_type = "t3.medium"
      count         = 3
    }
  }
}

resource "aws_instance" "web" {
  count         = local.instance_config[local.env].count
  instance_type = local.instance_config[local.env].instance_type
  # ...
}

📋 체크리스트

  • Terraform 설치
  • 프로젝트 구조
  • Provider 설정
  • 리소스 생성
  • 변수 사용
  • 출력 정의
  • 상태 관리
  • 모듈 작성/사용
  • 워크스페이스
  • 원격 상태
  • plan/apply/destroy

🔗 관련 노트

  • 01-03-도커-기본 — 컨테이너화
  • 02-03-Ansible-자동화 — 설정 관리
  • 03-02-플랫폼엔지니어링 — 플랫폼 구축

마지막 업데이트: 2026-06-01