[AWS 인프라 구축기] Terraform과 Packer로 인프라 자동화 구축하기

2026. 4. 1. 07:04·Cloud & DevOps/AWS Infrastructure

토이 프로젝트를 활용해 Terraform과 Packer를 이용한 인프라 자동화를 구축하며 겪은 시행착오와 '비싼' 배움의 기록을 정리했다. 단순히 기술을 나열하는 것이 아니라, 이 과정이 얼마나 정교한 설계와 책임감을 요하는지 깨달은 시간이었다. 


1. Packer와 Terraform, 이 둘은 뭐가 다를까?

가장 먼저 두 도구의 역할을 명확히 이해하는 게 중요했다.

  • Packer (The Baker): 서버의 '원형'인 AMI(Amazon Machine Image)를 만드는 도구다. 운영체제 위에 필요한 소프트웨어(Java)를 설치하고, 애플리케이션(app.jar)을 미리 담아 언제든 바로 실행 가능한 '밀키트' 상태로 포장하는 역할을 한다.
  • Terraform (The Architect): Packer가 만든 이미지를 어디에, 몇 대나 배치할지 설계하는 인프라 구성 도구다. VPC, 보안 그룹, 데이터베이스(RDS) 등 클라우드의 모든 자원을 코드로 정의하고 생성한다.

요약하면 Packer가 재료를 준비하고, Terraform이 그 재료로 집을 짓는 느낌이다.

2. 48달러의 교훈: 인프라 관리의 무게

테라폼의 편리함을 체감하기도 전에, 인프라 관리의 무서움을 먼저 맛보았다.

인강을 보며 실습하던 중 terraform destroy가 제대로 동작하지 않아 수동으로 AWS 리소스를 삭제한 적이 있었다. 나름 꼼꼼하게 지웠다고 생각했는데, IAM 테스트 계정으로만 확인하고 Root 계정의 비용 현황을 확인하지 않은 게 문제였다. 뒤늦게 확인한 청구서에는 48달러가 찍혀 있었다.

알고 보니 수동 삭제 과정에서 WAF(Web Application Firewall)를 놓쳤고, SQS 등 몇몇 리소스가 매일 비용을 발생시키고 있었다. 이 사건 이후 두 가지 철칙을 세웠다.

  1. 예산 알림 설정: 일정 금액 이상 발생 시 즉시 알림이 오도록 설정했다.
  2. 매일의 Destroy: 아직은 인스턴스 중지(Stop)보다 삭제(Destroy)가 더 안전하다고 판단하여, 매일 테스트 종료 후 인프라를 완전히 허문다. 아침마다 Root 계정으로 들어가 비용을 확인하는 습관도 생겼다. 비싼 수업료였지만, 직접 겪어보니 인프라 관리의 정교함이 왜 필요한지 뼈저리게 느꼈다.

비싼 수업료였지만, 직접 겪어보니 인프라 관리의 정교함이 왜 필요한지 뼈저리게 느꼈다. 그리고 오기도 생겼다. 무조건 프리티어 안에서, 최소한의 비용으로 구축하겠다!

3. 인프라 설계: 역할에 따른 파일 분리

인프라의 성격에 따라 파일을 분리하여 관리 효율성을 높였다.

  • main.tf (기반 공사): VPC, 서브넷, 인터넷 게이트웨이 등 한 번 구축하면 변하지 않는 네트워크의 뼈대를 설정했다.
  • infra.tf (고정형 시설): Redis, Kafka와 같이 상시 가동되어야 하는 고정형 서버들을 정의했다.
    → 이부분은 현재 Redis, Kafka를 Avien에서 쓰고 있으며, 내 목표는 프리티어 내에서 혹은 최소한의 비용으로 해결하는게 목표이기 때문에 Paas를 이용하기로 하였고, 초기 구성에서 추후 제외하였다.(현재 주석처리)
  • app.tf (유동형 공장): 트래픽에 따라 서버가 늘어나는 Auto Scaling Group(ASG)과 그 거푸집인 Launch Template을 설정했다.
    → Launch Template(시작템플릿)란? EC2 인스턴스를 띄울 때 필요한 모든 설정(AMI ID, 인스턴스 유형, 보안 그룹 등)을 미리 저장해둔 '설계도'
  • terraform.tfstate (상태 기록): GitHub Actions와의 협업을 위해 S3와 DynamoDB를 활용한 Remote Backend를 구축하여 인프라의 현재 상태를 동기화했다.

4. Packer의 설계도

상세 코드를 나열하기보다, 이미지 빌드를 위해 구성한 파일들의 역할을 정의했다.

  • aws-ami.pkr.hcl: 어떤 기반 이미지(AMI)를 사용하고, 어떤 인스턴스 타입으로 빌드할지 정의하는 핵심 설계도다.
  • variables.pkr.hcl: 리전 정보나 JAR 파일 경로 등 가변적인 설정을 변수로 분리하여 관리했다.
  • setup.sh & configure-service.sh: 인스턴스 내부에 Java를 설치하고, 앱을 systemd 서비스로 등록하는 실질적인 설치 스크립트다.
  • moa-backend.service: 앱의 실행 명령어와 재시작 정책 등을 담은 서비스 설정 파일이다.

5. 처음이기에 겪었던 시행착오와 해결 (Troubleshooting)

단순히 소스 코드를 업로드하는 수준을 넘어, 초기 환경 구성을 '무(無)'에서 '유(有)'로 만드는 과정은 생각보다 복잡했다.

① "단순 업로드"가 아닌 "환경 구축"의 어려움

처음에는 파일을 올리면 끝날 줄 알았으나, 실제로는 Key Pair 관리, IAM 권한 설정, 보안 그룹(Security Group) 간의 연동 등 고려할 것이 너무 많았다. 특히 DB나 Redis가 실행되지 않았던 이유는 대부분 보안 그룹에서 포트가 막혀 있거나, 환경 변수가 제대로 주입되지 않았기 때문이었다.

② JAR 이름 통일과 경로의 지옥

빌드할 때마다 달라지는 JAR 파일 이름과 Packer/Terraform 간 경로 불일치로 서버가 앱을 찾지 못하는 현상이 발생했다. 빌드 결과물 이름을 app.jar로 고정하고, Packer에서 임시로 올리는 경로(/tmp)와 최종 실행 경로(/opt/moa/backend/)를 명확히 구분해서 해결했다.

③ 비밀값 관리 (Secrets & Variables)

DB 비밀번호나 AWS 키를 코드에 노출할 수 없으니, variables.tf에 변수를 선언하고 실제 값은 GitHub Actions의 Secrets에 저장했다. Terraform 실행 시 TF_VAR_ 접두어를 사용해 안전하게 값을 주입하는 방식을 이번에 제대로 익혔다.

④ "닭이 먼저냐, 달걀이 먼저냐" - 생성 순서(Dependency) 이슈

아마 이게 가장 많이 겪은 에러였던 것 같다. app.tf에서 보안 그룹이나 RDS를 생성할 때, A 리소스가 B 리소스의 ID를 참조해야 하는데 B가 아직 생성되지 않아 터지는 문제다. depends_on으로 명시적으로 순서를 지정하거나, 보안 그룹 규칙을 별도 리소스(aws_security_group_rule)로 분리해서 의존성 스파게티를 풀어냈다.


이번 작업을 돌아보면, 기술 자체보다 인프라를 다루는 태도를 배웠다는 게 더 크다.

코드 몇 줄로 수십 개의 리소스가 생겨나는 건 분명 편리하다. 그런데 그만큼 잘못됐을 때의 파급력도 크다. 48달러짜리 실수가 준 교훈이 바로 그것이었다. 자동화는 편의를 위한 도구이지, 책임을 대신해주는 도구가 아니라는 것.

앞으로는 지금 구축한 기반 위에 GitHub Actions와의 CI/CD 파이프라인을 좀 더 단단하게 연결하고, 모니터링과 로깅 쪽도 손볼 계획이다. 여전히 프리티어 안에서. 😄

 

 

 

'Cloud & DevOps > AWS Infrastructure' 카테고리의 다른 글

[AWS 인프라 구축기] 극한의 비용 최적화로 완성한 대용량 예매 시스템 배포 아키텍처  (0) 2026.03.26
2026 AWS SAA(Solutions Architect - Associate) 합격(2026 덤프 PDF, 시험문제 PDF, 실전 팁)  (1) 2026.02.27
'Cloud & DevOps/AWS Infrastructure' 카테고리의 다른 글
  • [AWS 인프라 구축기] 극한의 비용 최적화로 완성한 대용량 예매 시스템 배포 아키텍처
  • 2026 AWS SAA(Solutions Architect - Associate) 합격(2026 덤프 PDF, 시험문제 PDF, 실전 팁)
Dev히다
Dev히다
Java 백엔드 개발자입니다. 안정적인 서비스 운영과 효율적인 인프라 구축에 몰입합니다. 코드가 돌아가는 환경까지 이해하는 엔지니어를 지향합니다. Architecture, TroubleShooting, Tech Log.
  • Dev히다
    Java to Cloud : Dev Note
    Dev히다
  • 전체
    오늘
    어제
    • 분류 전체보기 (186)
      • AI & Future Tech (2)
        • AI Workspace (0)
        • AI Weekly News (0)
        • AI Agent & Automation (0)
        • LLM & RAG (2)
      • Backend Engineering (20)
        • Java & Spring (15)
        • JPA & QueryDSL (5)
      • Data Engineering (4)
        • DBMS & Tuning (3)
        • Redis & Cache (1)
      • Cloud & DevOps (5)
        • AWS Infrastructure (3)
        • Docker & CI CD (2)
      • Algorithm & CS (6)
        • CodingTest (5)
        • Computer Science (1)
      • Projects (12)
        • Side Project (10)
        • Work Experience (2)
      • Troubleshooting (9)
        • Error Log (0)
        • Review (9)
      • Log (0)
        • 내 맘대로 (0)
        • 여행 (0)
        • 요즘 (0)
      • Archive (125)
        • 기술면접 (33)
        • Project (9)
        • Spring (29)
        • Spring_Boot (2)
        • JAVA (5)
        • Servlet_JSP (12)
        • SQL (6)
        • JavaScript (1)
        • HTML_CSS (6)
        • Jquery (3)
        • Mybatis (1)
        • Vue.js (3)
        • 기타 (3)
        • 기타2 (2)
        • 코테대비 (10)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    뉴렉처
    @Controller
    자바
    폐쇄망
    기술 대비
    인텔리제이
    코테
    MVC2
    CORS
    JSP
    인프런
    Join
    docker
    Terraform
    김영한
    redis
    @RestController
    코딩테스트
    thread
    프로그래머스
    MVC
    프레임워크
    공부기록
    스프링
    select
    aws
    대용량 트래픽
    SQL
    AOP
    토이프로젝트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
Dev히다
[AWS 인프라 구축기] Terraform과 Packer로 인프라 자동화 구축하기
상단으로

티스토리툴바