Terraform 실전 가이드 | IaC·AWS·State·Module·Workspace·Best Practices

Terraform 실전 가이드 | IaC·AWS·State·Module·Workspace·Best Practices

이 글의 핵심

Terraform으로 인프라를 코드로 관리하는 실전 가이드입니다. 기본 문법, AWS 리소스, State 관리, Module, Workspace, Best Practices까지 실무 예제로 정리했습니다.

실무 경험 공유: 수동 인프라 관리를 Terraform으로 자동화하면서, 배포 시간을 2시간에서 10분으로 단축하고 인프라 오류를 90% 줄인 경험을 공유합니다.

들어가며: “인프라 관리가 복잡해요”

실무 문제 시나리오

시나리오 1: 콘솔에서 수동으로 클릭해요
AWS 콘솔에서 리소스를 생성합니다. 실수가 많고 재현이 어렵습니다.

시나리오 2: 환경마다 다르게 설정해요
개발/스테이징/프로덕션 설정이 달라 혼란스럽습니다. Terraform으로 일관성을 유지합니다.

시나리오 3: 인프라 변경 이력이 없어요
누가 언제 무엇을 바꿨는지 모릅니다. Terraform은 Git으로 관리합니다.


1. Terraform이란?

핵심 특징

Terraform은 인프라를 코드로 관리하는 IaC 도구입니다.

주요 장점:

  • 선언적: 원하는 상태를 정의
  • 멀티 클라우드: AWS, GCP, Azure 지원
  • State 관리: 현재 상태 추적
  • Plan: 변경 사항 미리 확인
  • 모듈: 재사용 가능한 구성

2. 설치

설치

# Windows (Chocolatey)
choco install terraform

# macOS
brew install terraform

# 확인
terraform version

3. 기본 문법

첫 번째 리소스

# main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-terraform-bucket-12345"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

명령어

# 초기화
terraform init

# Plan (변경 사항 확인)
terraform plan

# Apply (적용)
terraform apply

# Destroy (삭제)
terraform destroy

4. 변수

변수 정의

# variables.tf
variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-east-1"
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t3.micro"
}

variable "tags" {
  description = "Common tags"
  type        = map(string)
  default     = {
    Environment = "Dev"
    Project     = "MyApp"
  }
}

변수 사용

# main.tf
provider "aws" {
  region = var.region
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_type

  tags = var.tags
}

변수 값 전달

# CLI
terraform apply -var="region=ap-northeast-2"

# 파일
# terraform.tfvars
region = "ap-northeast-2"
instance_type = "t3.small"

5. Output

# outputs.tf
output "instance_id" {
  description = "EC2 instance ID"
  value       = aws_instance.web.id
}

output "instance_public_ip" {
  description = "Public IP"
  value       = aws_instance.web.public_ip
}

output "s3_bucket_name" {
  description = "S3 bucket name"
  value       = aws_s3_bucket.example.id
}
# Output 확인
terraform output
terraform output instance_public_ip

6. 실전 예제: VPC + EC2

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

  tags = {
    Name = "main-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "us-east-1a"
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "public-rt"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# ec2.tf
resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group for web server"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = [0.0.0.0/0]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [0.0.0.0/0]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = [0.0.0.0/0]
  }
}

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id

  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
              #!/bin/bash
              yum update -y
              yum install -y httpd
              systemctl start httpd
              systemctl enable httpd
              echo "Hello from Terraform" > /var/www/html/index.html
              EOF

  tags = {
    Name = "web-server"
  }
}

7. State 관리

Remote State (S3)

# backend.tf
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}

State 명령어

# State 확인
terraform state list

# 특정 리소스 확인
terraform state show aws_instance.web

# State 이동
terraform state mv aws_instance.old aws_instance.new

# State에서 제거
terraform state rm aws_instance.web

8. Module

Module 정의

# modules/vpc/main.tf
variable "cidr_block" {
  type = string
}

variable "name" {
  type = string
}

resource "aws_vpc" "main" {
  cidr_block = var.cidr_block

  tags = {
    Name = var.name
  }
}

output "vpc_id" {
  value = aws_vpc.main.id
}

Module 사용

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

  cidr_block = "10.0.0.0/16"
  name       = "production-vpc"
}

resource "aws_subnet" "public" {
  vpc_id     = module.vpc.vpc_id
  cidr_block = "10.0.1.0/24"
}

9. Workspace

# Workspace 생성
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# Workspace 전환
terraform workspace select dev

# 현재 Workspace
terraform workspace show

# Workspace 목록
terraform workspace list

Workspace별 설정

locals {
  env = terraform.workspace

  instance_type = {
    dev     = "t3.micro"
    staging = "t3.small"
    prod    = "t3.medium"
  }
}

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

정리 및 체크리스트

핵심 요약

  • Terraform: 인프라를 코드로 관리
  • 선언적: 원하는 상태를 정의
  • State: 현재 상태 추적
  • Module: 재사용 가능한 구성
  • Workspace: 환경별 관리
  • 멀티 클라우드: AWS, GCP, Azure

프로덕션 체크리스트

  • Remote State 설정 (S3 + DynamoDB)
  • Module 구조화
  • Workspace 분리
  • 변수 파일 관리
  • CI/CD 통합
  • 문서화

같이 보면 좋은 글

  • Kubernetes 실전 가이드
  • GitHub Actions CI/CD 가이드
  • AWS 완벽 가이드

이 글에서 다루는 키워드

Terraform, IaC, AWS, DevOps, Infrastructure, Cloud, Automation

자주 묻는 질문 (FAQ)

Q. Terraform vs CloudFormation, 어떤 게 나은가요?

A. Terraform은 멀티 클라우드를 지원합니다. CloudFormation은 AWS 전용입니다. 멀티 클라우드는 Terraform, AWS만 사용하면 둘 다 괜찮습니다.

Q. State 파일을 Git에 커밋해도 되나요?

A. 아니요, 절대 안 됩니다. 민감한 정보가 포함될 수 있습니다. S3 같은 Remote Backend를 사용하세요.

Q. 학습 곡선이 가파른가요?

A. 기본 문법은 간단합니다. 하지만 클라우드 지식이 필요합니다.

Q. 프로덕션에서 사용해도 되나요?

A. 네, 많은 기업에서 프로덕션 인프라를 Terraform으로 관리합니다.

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3