16장. 콘솔에서 코드로 — Infrastructure as Code (Terraform)
15장에서 앱 배포를 자동화했습니다. 그런데 그 앱이 올라가는 무대 — VPC, RDS, ECS, ALB — 는 어떤가요? 2부 내내 콘솔에서 손으로 클릭해 만들었습니다. 이번 장에서는 이 인프라 자체를 코드로 옮깁니다. 실무에서 "IaC"라고 부르는, 오늘날 인프라 관리의 표준 방식입니다.
[지금 여기]
우리는 22단계를 거쳐 "라이브 투표 서비스"를 만들고, 컨테이너에 담아, AWS에 배포하는 여정을 걷고 있습니다. 지금은 16단계, 인프라를 코드로 옮기는 자리입니다.
- 1장개발 환경 준비
- 2장Claude Code 사용법 익히기
- 3장무엇을 만들지 기획 (라이브 투표 서비스)
- 4장로컬에서 서비스 만들기 (React + Express + PostgreSQL)
- 5장Docker 개념
- 6장Dockerfile 작성
- 7장컨테이너 빌드·실행
- 8장AWS 시작 (계정 / IAM / 리전 / 비용)
- 9장이미지 태깅
- 10장ECR에 이미지 올리기
- 11장VPC 네트워크 구성
- 12장RDS 데이터베이스 생성
- 13장SSM 터널로 RDS 초기화
- 14장ECS Fargate + ALB로 배포 (기본 완성)
- 15장CI/CD (GitHub Actions)
- 16장IaC (Terraform)
- 17장배포 자동화 연결
- 18장현업 운영 구조 이해
- 19장무중단 배포
- 20장신규 버전 배포 & 롤백
- 21장(심화) 프론트를 Vercel로 분리 배포
- 22장마무리 (회고 + 리소스 삭제)
- 방금 끝낸 것: 15장에서 GitHub Actions로 앱 배포를 자동화했습니다. 코드를 GitHub에 올리면 이미지가 빌드되어 ECS에 자동으로 배포됩니다.
- 이번 장에서 하는 것: 앱이 아니라 인프라 자체(VPC·RDS·ECS·ALB)를
Terraform 코드로 표현하고,
terraform plan으로 그 코드가 우리 인프라를 정확히 그려 내는지 검증합니다.
이번 장에서 완성되는 것
한 문장으로: 2부에 콘솔 클릭으로 만든 인프라를 Terraform 코드
(.tf 파일들)로 옮겨 적고, terraform plan으로 "이 코드를 실행하면
우리 인프라가 그대로 만들어진다"는 것을 확인합니다.
이렇게 되면 성공입니다: VS Code 터미널에서 terraform plan을 실행했을
때 오류 없이 계획이 출력되고, 그 목록에 VPC·서브넷·RDS·ALB·ECS 등
2부에서 만든 리소스가 전부 "새로 만들 것"으로 잡혀 있습니다.
이 장은 plan까지만 하고 apply는 하지 않습니다.
지금 AWS에는 콘솔로 만든 인프라가 이미 살아서 돌아가고 있습니다.
여기에 apply를 하면 똑같은 인프라가 한 벌 더 만들어져 요금이
이중으로 나갑니다. 그래서 이번 장은 코드 작성과 plan 검증까지만
합니다. 실제로 코드에서 인프라를 세워 보는 것(=apply 재현)은 22장에서
리소스를 모두 지운 뒤에 해 보길 권합니다. 지웠던 인프라가 명령 몇 번에
되살아나는 경험이 IaC의 힘을 가장 잘 느끼게 해 줍니다.
사전 조건
이 장은 1~15장을 마친 상태에서 시작합니다. 아래가 갖춰져 있어야 합니다.
- 2부에서 콘솔로 만든 인프라가 AWS에 살아 있다 — VPC(
vote-vpc), RDS(vote-db), ECS 클러스터/서비스, ALB(vote-alb)가 서울 리전 (ap-northeast-2)에 만들어져 있고, 14장에서 ALB 주소로 앱이 뜨는 걸 확인했다. - 문서(Documents) 폴더 안에
vote-app폴더가 있고, VS Code로 그 폴더를 열 수 있다. (1장에서 만든 그 폴더입니다.) - AWS CLI에 내 계정 자격 증명이 설정돼 있다 — 13장에서 SSM 터널로
RDS를 초기화할 때 이미
aws configure로 설정해 두었습니다. 터미널에서aws sts get-caller-identity를 쳤을 때 내 계정 번호가 나오면 준비된 것입니다. Terraform은 이 자격 증명을 그대로 빌려 AWS와 통신합니다.
준비 확인부터 하겠습니다. VS Code로 vote-app 폴더를 열고
(File → Open Folder → 문서 → vote-app), Terminal → New Terminal로
터미널을 연 뒤 아래를 입력하세요.
aws sts get-caller-identity # 내 AWS 계정 자격 증명이 설정돼 있는지 확인
Account, Arn 같은 항목과 함께 내 계정 번호가 한 덩이 출력되면
준비된 것입니다.
Unable to locate credentials 또는 command not found: aws가
나오면 아직 AWS CLI 설정이 안 된 것입니다. 13장의 AWS CLI 설정
(aws configure) 부분을 먼저 마치고 돌아오세요. 이게 돼 있어야 이 장
뒤쪽의 terraform plan이 동작합니다.
16.1 왜 콘솔 클릭이 아니라 코드여야 하는가
콘솔 클릭 방식(손 구성)의 문제를 상상해 봅시다.
상황 1. "이거 다시 만들어 주세요." 회사에서 우리 서비스와 똑같은 환경을 하나 더(예: 테스트용) 만들어야 합니다. 2부의 그 수십 번의 클릭을 기억을 더듬어 그대로 반복할 수 있을까요? 화면 순서, 입력값, 체크박스 하나까지? 사람의 기억은 그걸 못 합니다. 어딘가 미묘하게 다른 환경이 만들어지고, "테스트에선 됐는데 운영에선 안 되는" 문제가 생깁니다.
상황 2. "이거 누가 바꿨어요?" 어느 날 보안 그룹 규칙이 하나 바뀌어 있습니다. 누가, 언제, 왜 바꿨는지 아무 기록이 없습니다. 콘솔 클릭은 이력이 남지 않습니다.
상황 3. "실수로 지웠어요." 리소스를 실수로 삭제했습니다. 복구하려면? 또 기억을 더듬어 클릭해야 합니다.
이 문제들의 공통 원인은 인프라의 "정답"이 사람 머릿속에만 있다는 것입니다. 해결책은 앱 코드에서 이미 봤습니다. 코드로 적어 두면 됩니다.
IaC(Infrastructure as Code, 코드형 인프라) 서버·네트워크·DB 같은 인프라를 콘솔 클릭이 아니라 코드(텍스트 파일)로 정의하고, 도구가 그 코드를 읽어 실제 인프라를 만들게 하는 방식입니다. 인프라의 정답이 코드에 있으므로: 몇 번이든 똑같이 재현할 수 있고(재현성), Git으로 변경 이력이 남고(추적), 동료와 리뷰할 수 있습니다(협업).
비유하면, 콘솔 클릭은 요리사가 감으로 만드는 요리이고, IaC는 레시피를 문서로 만들어 둔 요리입니다. 레시피가 있으면 누가 언제 만들어도 같은 맛이 나고, 레시피를 고칠 때도 "이렇게 바꾸자"고 검토할 수 있습니다. 1부의 Dockerfile("이미지의 레시피")과 정확히 같은 발상을, 인프라 전체로 넓힌 것입니다.
16.2 [활용 사례] IaC는 실무에서 어디에 쓰이나
IaC(코드형 인프라)가 우리 실습에만 쓰이는 특별한 기법이라고 오해하지 않도록, 현업에서 실제로 쓰이는 장면 몇 가지를 봅시다.
-
환경을 통째로 복제한다(개발·스테이징·운영). 회사는 보통 같은 구조의 환경을 여러 벌 굴립니다. 개발용, 테스트(스테이징)용, 실제 서비스(운영)용. 코드가 한 벌 있으면 변수(이름·크기)만 바꿔 같은 인프라를 세 벌 찍어 낼 수 있습니다. 손 클릭으로는 세 번 다 똑같이 만드는 게 사실상 불가능합니다.
-
변경을 코드 리뷰로 검토한다. "보안 그룹에 포트를 하나 연다" 같은 위험한 변경도, 코드로 하면 동료가 Pull Request로 미리 보고 승인할 수 있습니다. 콘솔에서 몰래 클릭 한 번으로 바뀌는 것과는 안전성이 다릅니다. 누가 왜 바꿨는지도 Git 이력에 남습니다.
-
재해 복구(DR). 한 리전(예: 서울)이 통째로 장애가 나도, 같은 코드를 다른 리전에
apply하면 인프라를 몇 분 만에 다시 세울 수 있습니다. "정답이 코드에 있으니" 복구가 곧 코드 실행입니다. -
인프라를 문서 대신 코드로 공유한다. 신입이 들어와도 "우리 인프라가 어떻게 생겼는지"를 별도 문서가 아니라
.tf파일을 읽어 파악합니다. 코드가 곧 최신 설계도라, 문서처럼 낡지 않습니다.
이래서 오늘날 클라우드를 다루는 거의 모든 팀이 인프라를 코드로 관리합니다. 우리도 그 방식을 지금 맛봅니다.
16.3 도구 선택 — 왜 Terraform인가
IaC 도구는 여러 가지가 있습니다. 대표 셋만 가볍게 비교합니다.
| 도구 | 특징 |
|---|---|
| Terraform | 업계에서 가장 널리 쓰임. AWS뿐 아니라 다른 클라우드에도 같은 방식으로 사용 가능. 자료가 압도적으로 많음 |
| CloudFormation | AWS 전용. AWS에 내장되어 있으나 문법이 장황한 편 |
| CDK | 프로그래밍 언어(TypeScript 등)로 인프라를 작성. 개발자 친화적이나 AWS 전용 |
우리는 Terraform을 씁니다. 이유는 단순합니다. 실무에서 가장 많이 쓰이고, 자료가 많아 막혔을 때 답을 찾기 쉽고, 여기서 배운 방식이 다른 클라우드에도 그대로 통하기 때문입니다.
Terraform(테라폼)
HashiCorp사가 만든 IaC 도구입니다. .tf 확장자의 텍스트 파일에
"이런 인프라가 있어야 한다"를 선언해 두면, Terraform이 클라우드에
실제로 그 인프라를 만들고 관리해 줍니다.
16.4 Terraform 기초 — 네 가지 개념
Terraform 코드를 읽으려면 네 단어만 알면 됩니다.
프로바이더(Provider) "어느 클라우드와 대화할 것인가"를 정하는 연결 장치입니다. 우리는 AWS 프로바이더를 씁니다. Terraform에게 AWS와 통신하는 방법을 가르쳐 주는 부품이라고 보면 됩니다.
리소스(Resource) 만들고 싶은 인프라 하나하나의 선언입니다. "VPC 하나", "RDS 하나", "보안 그룹 하나"가 각각 리소스 블록 하나로 적힙니다.
변수(Variable) 코드에서 반복되거나 환경마다 달라지는 값(리전, 이름, 크기 등)을 한곳에 모아 두는 것입니다. 앱의 환경변수와 같은 발상입니다.
스테이트(State, 장부) Terraform이 "지금까지 실제로 만들어 둔 것"을 기록하는 장부 파일입니다. Terraform은 코드(원하는 상태)와 장부(현재 상태)를 비교해서, 그 차이만 만들거나 고치거나 지웁니다. 이 장부가 Terraform의 심장입니다.
맛보기로, VPC 하나를 선언한 Terraform 코드는 이렇게 생겼습니다.
provider "aws" { # AWS와 대화하겠다
region = "ap-northeast-2" # 서울 리전에서
}
resource "aws_vpc" "vote" { # "aws_vpc 리소스를 만들어라, 코드 안에서는 vote라고 부르겠다"
cidr_block = "10.0.0.0/16" # 주소 범위 (11장 콘솔에서 입력했던 그 값)
tags = { Name = "vote-vpc" } # 이름표
}
콘솔에서 클릭으로 입력했던 값들이 텍스트로 적혀 있을 뿐이라는 것이 느껴지나요? 어렵게 생각할 필요 없습니다. 콘솔 화면의 입력 항목들을 파일에 적어 둔 것이 Terraform 코드입니다.
선언형이라는 것 Terraform 코드에는 "만드는 순서"가 아니라 "최종 모습"을 적습니다. "VPC가 있어야 한다"라고 선언하면, 없으면 만들고 이미 있으면 그대로 두는 식입니다. 순서와 방법은 Terraform이 알아서 정합니다.
16.5 Terraform 설치
맛보기와 실습을 하려면 먼저 Terraform 프로그램을 내 컴퓨터에 깔아야 합니다. 설치가 낯설면 Claude Code에게 아래처럼 시켜도 되지만, 아래에 운영체제별 정확한 방법을 적어 두었으니 직접 따라 해도 됩니다. 명령은 모두 VS Code 터미널에서 실행합니다.
macOS — 아래 두 줄이면 됩니다. VS Code 터미널에 한 줄씩 붙여넣고
각 줄마다 Enter를 누르세요. (Terraform은 Homebrew 기본 저장소에서
빠져 있어서, 제조사인 HashiCorp의 공식 저장소(tap)를 먼저 등록해야
합니다. 곧바로 brew install terraform만 치면 "없다"고 나오니 주의하세요.)
brew tap hashicorp/tap # HashiCorp 공식 저장소 등록
brew install hashicorp/tap/terraform # Terraform 설치
macOS인데 brew: command not found가 나오면 Homebrew가 아직
없는 것입니다. 웹브라우저에서 https://brew.sh에 접속해 안내된 설치
명령을 VS Code 터미널에 붙여넣어 Homebrew부터 설치한 뒤 위 두 줄을
실행하세요. (또는 Claude Code에게 "Homebrew를 설치해 줘"라고 시켜도
됩니다.)
Windows — 공식 다운로드 방식이 가장 확실합니다.
- 웹브라우저에서 공식 다운로드 페이지
https://developer.hashicorp.com/terraform/install에 접속해 Windows / AMD64 용 zip 파일을 내려받습니다. - 압축을 풀면
terraform.exe파일 하나가 나옵니다. 이 파일을 새로 만든 폴더C:\terraform안에 둡니다. - 그 폴더(
C:\terraform)를 환경 변수 PATH에 등록합니다.- [용어] PATH 등록: "이 폴더 안의 프로그램은 어디서든 이름만 치면
실행되게 해 달라"고 Windows에 알려 주는 설정입니다. 시작 메뉴에서
"환경 변수"를 검색 → 시스템 환경 변수 편집 → 환경 변수(N) 버튼
→ 아래
Path를 골라 편집 → 새로 만들기로C:\terraform을 추가 → 모든 창에서 확인을 누릅니다. - 이 과정이 낯설면 Claude Code에게 "
C:\terraform에 둔 terraform.exe를 PATH에 등록하는 방법을 스크린샷 없이 단계별로 알려 줘"라고 물어보면 됩니다.
- [용어] PATH 등록: "이 폴더 안의 프로그램은 어디서든 이름만 치면
실행되게 해 달라"고 Windows에 알려 주는 설정입니다. 시작 메뉴에서
"환경 변수"를 검색 → 시스템 환경 변수 편집 → 환경 변수(N) 버튼
→ 아래
- 등록 후에는 VS Code 터미널을 새로 열어야 인식됩니다. 터미널 영역 오른쪽 위 휴지통 아이콘으로 지금 터미널을 닫고, Terminal → New Terminal로 다시 여세요.
Windows에서 Chocolatey라는 패키지 관리자를 이미 쓰고 있다면
choco install terraform 한 줄로도 설치됩니다. (이 패키지는 HashiCorp가
직접 관리하는 것은 아닙니다.)
설치 확인은 macOS·Windows 공통입니다. VS Code 터미널에 입력하세요.
terraform -version # 버전이 나오면 설치 성공
Terraform v1.x.x 처럼 버전이 한 줄 나오면 설치된 것입니다.
command not found: terraform이 나오면 터미널이 아직 새로
설치된 명령을 인식하지 못한 경우가 많습니다. 터미널 오른쪽 위 휴지통
아이콘으로 터미널을 닫고 Terminal → New Terminal로 새로 연 뒤 다시
terraform -version을 입력하세요.
Terraform 프로젝트에서 앞으로 계속 쓰는 명령은 세 개뿐입니다. 역할만 먼저 눈에 익히고, 바로 다음 절 맛보기에서 셋 다 직접 실행해 봅니다.
terraform init— 작업 폴더 준비. 코드에 적힌 프로바이더(클라우드 연결 부품)를 내려받습니다. 프로젝트 폴더마다 처음 한 번 실행합니다.terraform plan— 실행 계획 미리보기. 코드와 장부(state)를 비교해 "이걸 실행하면 무엇이 만들어지고/바뀌고/지워지는지" 보여 주기만 합니다. 실제로는 아무것도 건드리지 않습니다.terraform apply— 계획을 실제로 실행. 이때 비로소 리소스가 만들어집니다. 마지막에yes를 입력해야 진행됩니다.
plan과 apply를 나눠 둔 이유 인프라는 실수의 대가가 큽니다(DB를 지운다든가). 그래서 "실행하면 무슨 일이 벌어지는지"를 먼저 보고(plan), 확인한 뒤에 실행(apply)하는 2단계가 기본기입니다.
16.6 [맛보기] AWS 없이 Terraform 한 바퀴 돌려 보기
우리 인프라(AWS)로 곧장 가기 전에, 아주 작고 무해한 예제로
init → plan → apply를 손으로 한 번 돌려 봅시다. AWS를 전혀 건드리지
않고, 내 컴퓨터에 텍스트 파일 하나를 만들었다 지우는 예제라 요금도,
위험도 전혀 없습니다. 이 한 바퀴를 돌려 보면 다음의 진짜 실습이 안
무섭습니다.
1단계. 맛보기용 폴더 만들기
우리 인프라 코드와 섞이지 않도록, vote-app 안에 맛보기 전용 폴더를
따로 만듭니다. VS Code 터미널(지금 vote-app에 열려 있음)에 입력하세요.
mkdir tf-hello # vote-app 안에 tf-hello 폴더를 만든다
cd tf-hello # 그 폴더 안으로 들어간다
pwd를 치면 경로 끝이 /vote-app/tf-hello로 끝나야 합니다.
앞으로 이 절의 명령은 모두 이 tf-hello 폴더 안에서 실행합니다.
2단계. 맛보기 코드 파일 만들기
VS Code 왼쪽 파일 목록에서 tf-hello 폴더 위에 마우스를 올리면 나오는
아이콘 중 새 파일(New File) 을 눌러, 파일 이름을 main.tf로 만듭니다.
그리고 아래 내용을 그대로 붙여넣고 저장(Ctrl/Cmd + S)합니다.
terraform {
required_providers {
local = { # AWS가 아니라, 내 컴퓨터 파일을 다루는 무해한 프로바이더
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
resource "local_file" "hello" { # "로컬 파일 하나를 만들어라"
filename = "hello.txt" # 이 폴더에 hello.txt 라는 파일을
content = "Terraform이 만든 파일입니다.\n" # 이 내용으로 만든다
}
이 코드는 AWS와 무관합니다. hashicorp/local 프로바이더는 "내 컴퓨터에
파일을 만든다"만 할 줄 아는 아주 단순한 부품입니다.
3단계. init — 준비
VS Code 터미널(tf-hello 폴더)에서:
terraform init # 코드에 적힌 local 프로바이더를 내려받아 폴더를 준비
Terraform has been successfully initialized!가 나오면 성공입니다.
(이때 .terraform 폴더와 .terraform.lock.hcl 파일이 생깁니다. 정상입니다.)
4단계. plan — 미리보기
terraform plan # 실행하면 무엇이 만들어질지 미리 보여 준다 (아직 안 만듦)
출력 끝에 이런 요약이 보입니다.
Plan: 1 to add, 0 to change, 0 to destroy.
"실행하면 1개(파일 하나)가 새로 만들어진다"는 뜻입니다. 아직 실제로는 아무것도 안 만들어졌습니다. plan은 미리보기일 뿐입니다.
5단계. apply — 실제 실행 (이건 무해하니 해 봅니다)
terraform apply # 계획을 실제로 실행 (내 컴퓨터에 파일을 만든다)
중간에 Do you want to perform these actions?라고 물으면 yes를
입력하고 Enter를 누릅니다. Apply complete! Resources: 1 added.가
나오면 성공입니다.
이제 VS Code 왼쪽 tf-hello 폴더를 보면 hello.txt 파일이 실제로
생겨 있습니다. 그리고 terraform.tfstate 파일도 보일 텐데, 이게
바로 앞에서 배운 장부(state) 입니다. 열어 보면 "방금 hello.txt를
만들었다"는 기록이 들어 있습니다.
6단계. destroy — 정리
맛보기가 끝났으니 만든 것을 도로 지웁니다.
terraform destroy # Terraform이 만든 것을 지운다
yes를 입력하면 hello.txt가 사라집니다. 방금 여러분은 Terraform의
전체 흐름(init → plan → apply → destroy)을 손으로 한 바퀴 돌려 봤습니다.
AWS 실습도 원리는 똑같고, 다루는 대상이 파일 하나에서 VPC·RDS로
커질 뿐입니다.
7단계. 맛보기 폴더에서 나오기
다음 실습은 다른 폴더에서 하므로, 상위 폴더로 돌아갑니다.
cd .. # vote-app 폴더로 돌아간다
pwd의 끝이 다시 /vote-app이면 됩니다.
16.7 스테이트를 어디에 둘까 — 원격 state (개념)
방금 맛보기에서 terraform.tfstate(장부)가 내 컴퓨터에 파일로 생기는 걸
봤습니다. 혼자 실습할 때는 그걸로 충분하지만, 실무에서는 문제가 됩니다.
- 장부가 내 노트북에만 있으면, 동료가 인프라를 관리할 수 없습니다. 노트북이 고장 나면 장부가 통째로 사라집니다.
- 두 사람이 동시에 apply하면 장부가 꼬입니다.
그래서 실무에서는 장부를 팀이 함께 접근하는 원격 저장소에 둡니다. AWS에서는 S3를 씁니다.
S3(Simple Storage Service) AWS의 파일 보관 서비스입니다. 어떤 파일이든 안전하게 저장해 주는 클라우드 저장소로, Terraform 장부를 두는 표준 위치이기도 합니다.
백엔드(Backend)와 잠금(Locking) - 백엔드: Terraform에게 "장부를 어디에 저장하라"고 지정하는 설정입니다. S3 백엔드를 설정하면 장부가 내 컴퓨터가 아니라 S3에 저장되어 팀 전체가 공유합니다. - 잠금: 두 사람이 동시에 apply하지 못하게, 작업 중에는 장부를 잠그는 기능입니다.
S3 백엔드를 설정하는 코드는 이렇게 생겼습니다(개념만 보고 넘어갑니다).
terraform {
backend "s3" {
bucket = "vote-tfstate-버킷이름" # 장부를 저장할 S3 버킷
key = "infra/terraform.tfstate" # 버킷 안에서의 파일 경로
region = "ap-northeast-2" # 서울 리전
use_lockfile = true # S3 자체 잠금 기능 켜기 (한 줄이면 끝)
}
}
핵심은 마지막 줄 use_lockfile = true 입니다. 이 한 줄이면 S3가 스스로
잠금을 처리합니다.
DynamoDB 방식은 이제 구식입니다
예전 자료에는 잠금을 위해 DynamoDB라는 별도 서비스를 함께 만들어
쓰는 방법이 나옵니다. 지금은 그럴 필요가 없습니다. S3 백엔드에
use_lockfile = true 한 줄만 넣으면 S3 자체 잠금이 동작합니다.
DynamoDB를 쓰는 방식은 구식이니, 최신 자료를 볼 때 참고만 하세요.
이 실습에서는 혼자 진행하므로 로컬 state(내 컴퓨터의
terraform.tfstate)로 충분합니다. "실무에서는 장부를 S3에 두고
use_lockfile = true로 잠금을 켠다"는 개념만 가져가면 됩니다.
16.8 우리 인프라를 코드로 — VPC부터
이제 실전입니다. 2부에 콘솔로 만든 인프라를 Terraform 코드로 다시 표현합니다. 직접 타이핑하지 않고, Claude Code에게 시키고 읽으며 이해합니다.
시작 전에 앞의 [주의]를 다시 못 박습니다. 지금 AWS에는 콘솔로 만든
리소스가 이미 살아 있습니다. 그래서 이번 장은 코드 작성 → plan
검증까지만 하고 apply는 하지 않습니다. apply하면 같은 인프라가 한
벌 더 생겨 요금이 이중으로 나갑니다.
먼저 우리 인프라 코드를 담을 폴더를 만듭니다. VS Code 터미널(vote-app)에서
Claude Code를 실행하겠습니다.
claude # vote-app 폴더에서 Claude Code 실행
[실습] VPC 코드 작성
Claude Code 입력창에 아래 프롬프트를 넣습니다.
Claude Code가 infra 폴더 안에 파일들을 만들어 줍니다. VS Code 왼쪽
파일 목록에서 infra/vpc.tf를 열어 보세요. 11장에서 콘솔 마법사가 만들어
준 것들이 전부 리소스 블록으로 적혀 있습니다. aws_vpc, aws_subnet(4개),
aws_internet_gateway, aws_nat_gateway, aws_route_table… 코드를 쭉
읽으면서, 콘솔에서 봤던 이름·값들과 하나씩 짝지어 보세요. 이것이 이
장의 진짜 공부입니다. 콘솔에서 이해한 것을 코드에서 다시 알아보는 것.
16.9 코드로 짜기 — RDS
이어서 Claude Code(계속 켜 둔 상태)에 다음 프롬프트를 넣습니다.
만들어진 infra/rds.tf를 열고, 여기서 눈여겨볼 것 두 가지를 확인하세요.
- 비밀번호를 변수로: 코드는 GitHub에 올라가므로, 비밀번호를 코드에
적으면 안 됩니다(1부부터 이어지는 원칙입니다). Terraform은 변수를 실행
시점에 입력받거나 별도 파일(
.tfvars, Git 제외)로 관리합니다.rds.tf안에 비밀번호가 직접 적혀 있지 않고var.db_password처럼 변수로만 참조되는지 확인해 보세요. - 보안 그룹 관계가 코드에 보입니다: "ECS 보안 그룹에서 오는 5432만 허용" 같은 관계가 리소스 참조로 명시됩니다. 12장에서 그림으로 설계했던 사슬이 코드에서 그대로 읽힙니다.
16.10 코드로 짜기 — ECS · Fargate · ALB
마지막으로 배포 층입니다.
코드가 꽤 길어질 겁니다. 전부 이해하려 하지 말고, 콘솔에서 만졌던 설정들 — 타깃 그룹의 IP 유형, 원하는 태스크 수 2, 프라이빗 서브넷 배치, 보안 그룹 사슬 — 이 코드 어디에 적혀 있는지 찾아보는 정도면 충분합니다.
이 코드 묶음의 의미
방금 우리는 2부에서 클릭한 것 전부를 텍스트 파일 몇 개(provider.tf,
vpc.tf, rds.tf, ecs.tf, alb.tf, variables.tf)로 압축했습니다.
이 파일들만 있으면, 누구든 명령 두 번(init, apply)으로 같은 인프라를
그대로 세울 수 있습니다. 이것이 "인프라의 정답이 코드에 있다"는 말의
실체입니다.
16.11 plan으로 검증하기
이제 코드가 제대로 됐는지 확인합니다. plan은 아무것도 만들지 않고
"만든다면 이렇게 된다"만 보여 주므로, 콘솔 리소스가 살아 있는 지금
실행해도 안전합니다.
Claude Code에게 시켜도 되고, 직접 터미널에서 쳐도 됩니다. 직접 할 경우,
지금 터미널에 Claude Code가 켜져 있다면 입력창에 /exit를 입력해
빠져나온 뒤(또는 Terminal → New Terminal로 새 터미널을 열어), infra
폴더로 들어가 실행합니다.
cd infra # vote-app 안의 infra 폴더로 이동
terraform init # 코드에 적힌 AWS 프로바이더를 내려받아 준비 (이 폴더 첫 실행)
terraform plan # 실행 계획 미리보기 (실제로는 아무것도 안 만듦)
plan 출력의 끝에는 이런 요약이 나옵니다.
Plan: 23 to add, 0 to change, 0 to destroy.
"실행하면 23개 리소스가 새로 만들어진다"는 뜻입니다. (개수는 구성에 따라 다릅니다.) 이 숫자가 크게 나오는 게 정상입니다 — 우리 코드의 장부(state)는 지금 비어 있으니, Terraform은 "코드에 적힌 걸 전부 새로 만들어야 한다"고 계획하는 겁니다. 콘솔 리소스가 살아 있는 지금은 여기서 멈추고 apply하지 않습니다.
plan 목록을 훑으며 "VPC, 서브넷 4개, IGW, NAT, RDS, ALB, 클러스터, 서비스…"가 다 있는지 — 즉 코드가 우리 인프라의 완전한 설계도가 되었는지 확인하는 것으로 이 절은 완성입니다.
plan이 오류 없이 실행되고, 생성 목록에 2부에 만든 리소스
종류가 모두 보이면 성공입니다. 이 코드도 GitHub에 커밋해 두세요
(비밀번호가 담긴 .tfvars 파일과 .terraform 폴더, *.tfstate는
.gitignore로 제외). 이제 인프라의 이력도 Git에 남습니다.
작업이 끝나면 상위 폴더로 돌아옵니다.
cd .. # vote-app 폴더로 복귀
16.12 (심화) 이미 있는 리소스는? — import vs 재생성
"콘솔로 만든 기존 리소스를 지우지 않고, Terraform 장부에 그대로 등록할 수는 없나요?" — 좋은 질문이고, 방법이 있습니다.
임포트(Import) 이미 존재하는 실제 리소스를 Terraform의 장부(state)에 편입시키는 기능입니다. "이 VPC는 앞으로 네가 관리해"라고 Terraform에게 인계하는 것입니다.
두 접근의 비교입니다.
- 임포트: 기존 리소스를 그대로 살리면서 코드 관리로 전환. 운영 중인 서비스를 중단 없이 IaC로 옮길 때 실무에서 쓰는 방법입니다. 다만 리소스 하나하나를 코드와 정확히 맞춰야 해서 손이 많이 갑니다.
- 재생성: 지우고 코드로 새로 만들기. 깔끔하지만 서비스가 잠시 중단됩니다. 학습 환경이나 새 프로젝트에 적합합니다.
우리 실습은 학습 환경이므로 재생성 쪽(22장에서 삭제 → 원하면 코드로 재현)이 알맞습니다. 실무에서 "운영 중인 인프라를 IaC로 전환"하는 날이 오면, 그때 임포트를 떠올리면 됩니다.
막히면
이 장에서 자주 나는 오류와 대처법입니다.
-
command not found: terraform. 설치 직후 터미널이 아직 인식하지 못한 경우가 많습니다. 터미널 오른쪽 위 휴지통 아이콘으로 터미널을 닫고 Terminal → New Terminal로 새로 연 뒤terraform -version을 다시 치세요. 그래도 안 되면 16.5절 설치를 다시 진행합니다. (macOS는brew, Windows는 PATH 등록이 됐는지 확인.) -
terraform init에서 프로바이더 다운로드 실패. 인터넷 연결을 확인하고 다시terraform init을 실행하세요. 회사 네트워크의 방화벽이 원인일 수도 있습니다. -
terraform plan에서 자격 증명 오류(No valid credential sources,Unable to locate credentials등). Terraform이 AWS와 통신할 자격 증명을 못 찾은 것입니다. 사전 조건에서 확인한aws sts get-caller-identity가 잘 되는지 먼저 확인하고, 안 되면 13장의aws configure를 마친 뒤 다시 하세요. -
plan 숫자가 너무 커서 놀랐다(예: 23 to add). 정상입니다. 우리 코드의 장부가 비어 있어 "전부 새로 만든다"고 계획한 것뿐입니다. 여기서 apply만 하지 않으면 AWS에는 아무 변화도 없습니다.
-
실수로
apply를 눌렀다. 아직yes를 입력하지 않았다면Ctrl + C로 중단하면 됩니다. 이미yes까지 눌러 리소스가 생겼다면, 그infra폴더에서terraform destroy를 실행해 방금 Terraform이 만든 것만 도로 지우세요(콘솔로 만든 원래 리소스는 Terraform 장부에 없으므로 건드리지 않습니다). 그런 뒤 이중 리소스가 없는지 콘솔에서 확인합니다.
[확인] 16장 체크리스트
- □ 손 구성의 세 가지 문제(재현 불가·무기록·복구 곤란)를 말할 수 있다
- □ IaC가 무엇이고, Dockerfile과 어떤 발상이 같은지 설명할 수 있다
- □ IaC의 실무 활용 사례(환경 복제·코드 리뷰·재해 복구)를 한둘 댈 수 있다
- □ 프로바이더 / 리소스 / 변수 / state 네 개념을 안다
- □ Terraform을 설치하고
terraform -version으로 확인했다 - □ 맛보기에서
init → plan → apply → destroy를 손으로 한 바퀴 돌려 봤다 - □ init / plan / apply의 역할 차이, 특히 plan을 먼저 보는 이유를 안다
- □ 원격 state(S3 백엔드 +
use_lockfile = true잠금)가 왜 필요한지 안다 - □ 우리 인프라(VPC·RDS·ECS·ALB)가
infra폴더에 Terraform 코드로 작성돼 있다 - □
terraform plan이 오류 없이 실행되고, 인프라 전체가 코드로 표현됐음을 확인했다 (apply는 하지 않음)
앱 배포도 자동, 인프라도 코드가 됐습니다.