Terraform이 인프라 자동화의 기준선이 된 구조적 이유
클라우드 리소스를 콘솔에서 손으로 만들면 어제 만든 것과 오늘 만든 것이 같다는 보장이 없다. IaC(Infrastructure as Code)는 이 문제를 코드와 버전 관리로 옮기는 접근이고, Terraform은 그중 특정 클라우드에 묶이지 않은 선언형 도구로 자리를 잡았다. 여기서는 공식 문서에 기재된 동작과 제약을 기준으로 구성 요소와 절차를 정리한다.
선언형 구성과 상태 파일
Terraform 구성 파일(HCL)은 "무엇을 만들라"가 아니라 "최종 상태가 무엇이어야 하는가"를 기술한다. 도구는 구성 파일에 적힌 목표 상태, 상태 파일(terraform.tfstate)에 기록된 마지막 관리 상태, 그리고 프로바이더 API로 조회한 실제 상태 세 가지를 비교해 차이만큼의 작업을 계산한다. 상태 파일은 단순 캐시가 아니라 "이 리소스는 Terraform이 관리한다"는 소유권 대장이기 때문에, 이 파일을 잃어버리면 도구 입장에서는 관리 대상 자체가 사라진 것이 된다.
프로바이더 플러그인 구조
Terraform 코어는 클라우드 API를 직접 알지 못한다. AWS 인프라를 다루는 것은 AWS 프로바이더 플러그인이고, 같은 방식으로 Kubernetes, GitHub, 데이터독 등의 프로바이더가 레지스트리에 공개되어 있다. 하나의 워크플로로 여러 공급자를 함께 다룰 수 있다는 점이 단일 클라우드 전용 도구와 갈리는 지점이다. 반대로 말하면 특정 기능이 프로바이더에 아직 구현되지 않았다면 그 기능은 코드로 관리할 수 없다.
실행 계획이 만드는 안전 여백
terraform plan은 실제로 적용하기 전에 생성·수정·삭제될 리소스 목록을 보여준다. 특히 "교체(replace)"로 표시되는 항목은 기존 리소스를 지우고 새로 만든다는 뜻이라 데이터베이스나 EBS 볼륨에서는 곧바로 사고로 이어질 수 있다. plan 결과를 파일로 저장했다가 그 파일을 apply에 넘기면, 검토한 계획과 실제 적용 대상이 어긋나는 상황을 막을 수 있다.
AWS 인프라를 코드로 세우는 표준 절차
버전을 먼저 고정한다
구성 최상단의 terraform 블록에 required_version과 required_providers를 명시하는 것이 공식 문서가 권고하는 출발점이다. 프로바이더 버전을 열어두면 어제까지 통과하던 코드가 오늘 새 메이저 버전이 나오면서 깨진다. init 시 생성되는 종속성 잠금 파일(.terraform.lock.hcl)은 팀원과 CI가 동일한 프로바이더 바이너리를 쓰도록 보장하므로 반드시 저장소에 커밋해야 한다.
init에서 apply까지
순서는 init(백엔드 초기화와 플러그인 내려받기), validate(문법·타입 검증), plan(변경 계획 산출), apply(적용), destroy(회수)로 정리된다. CI에서 자동화할 때는 fmt로 서식을 검사하고 plan을 저장한 뒤, 사람의 승인 단계를 거쳐 apply를 실행하는 구성이 일반적이다. 실무 파이프라인에서 승인 단계를 생략하면 plan이 제공하는 안전장치를 스스로 버리는 셈이 된다.
원격 상태와 잠금
상태 파일을 로컬에 두면 협업이 불가능하다. AWS 인프라라면 S3 백엔드가 표준적인 선택이고, 버전 관리와 서버 측 암호화를 함께 켜는 것이 권장된다. 동시에 두 사람이 apply를 돌리면 상태 파일이 깨지므로 잠금이 필요한데, 과거에는 DynamoDB 테이블을 별도로 두는 방식이 정석이었고 최근 버전에서는 S3 자체의 잠금 파일 기능이 추가되어 별도 테이블 없이도 잠금이 가능하다. 사용 중인 Terraform 버전의 백엔드 문서에서 어느 방식이 지원되는지 확인한 뒤 선택해야 한다.
도구 비교와 선택 기준
주요 IaC 도구 비교
| 항목 | Terraform | AWS CloudFormation | AWS CDK | Pulumi |
|---|---|---|---|---|
| 대상 범위 | 멀티 클라우드·SaaS(프로바이더 기반) | AWS 전용 | AWS 전용(합성 후 CFN 실행) | 멀티 클라우드 |
| 작성 방식 | HCL 선언형 | YAML/JSON 선언형 | TypeScript·Python 등 범용 언어 | 범용 언어 |
| 상태 보관 | 사용자가 백엔드 선택(S3 등) | AWS가 스택으로 관리 | AWS가 스택으로 관리 | Pulumi 서비스 또는 자체 백엔드 |
| 변경 미리보기 | plan | 변경 세트(Change Set) | diff | preview |
| 라이선스 | 1.6 이후 BUSL-1.1 | AWS 서비스 약관 | Apache-2.0 | Apache-2.0 |
선택 전에 반드시 확인할 세 가지
- 라이선스 조건 — HashiCorp는 2023년에 Terraform 라이선스를 MPL 2.0에서 BUSL-1.1로 변경했다. 1.5.x까지는 기존 라이선스가 유지되고 1.6 이후 버전에 새 조건이 적용된다. 일반적인 사내 인프라 운영은 문제가 없지만, Terraform을 감싸 상용 서비스로 재판매하는 형태라면 조항을 먼저 검토해야 한다. 같은 배경에서 리눅스 재단 산하 포크인 OpenTofu가 갈라져 나왔고, 초기 버전은 명령 체계와 구성 문법이 호환되도록 설계되었다.
- 상태 파일에 담기는 민감 정보 — 공식 문서는 상태 파일이 리소스 속성값을 평문으로 담을 수 있다고 명시한다. RDS 초기 비밀번호처럼 민감한 값이 상태에 그대로 남을 수 있으므로, 상태 저장소는 버킷 정책과 암호화로 접근을 좁히고 저장소를 일반 소스 저장소와 분리해야 한다. sensitive 표시는 CLI 출력만 가리는 것이지 상태 파일 내용을 암호화하지 않는다.
- 프로바이더 지원 범위와 시차 — 신규 AWS 서비스나 신규 옵션은 프로바이더에 반영된 뒤에야 코드로 관리할 수 있다. 도입 예정 서비스가 있다면 해당 리소스 타입이 프로바이더 문서에 이미 존재하는지 확인하는 것이 순서다. 없으면 콘솔로 만든 뒤 나중에 import하는 이중 작업이 생긴다.
- 팀의 언어 역량 — 범용 언어 기반 도구는 반복문과 추상화가 자유롭지만, 그만큼 인프라 코드가 애플리케이션 코드처럼 복잡해질 여지도 크다. 선언형 문법의 제약을 장점으로 볼지 단점으로 볼지는 팀 구성에 따라 갈린다.
운영 단계에서 반복적으로 걸리는 제약
드리프트와 기존 리소스 편입
콘솔에서 누군가 보안 그룹 규칙을 손으로 고치면 코드와 실제가 어긋난다. plan은 이 차이를 감지해 원래 정의대로 되돌리려 하는데, 그 되돌림이 장애 대응 중 넣은 임시 조치를 지우는 경우가 있다. 이미 존재하는 AWS 인프라를 편입할 때는 import 기능을 쓴다. 최신 버전에서는 구성 파일에 import 블록을 선언해 plan 단계에서 편입 결과를 미리 확인하는 방식이 지원되므로, CLI 명령으로 즉시 편입하던 방식보다 검토 여지가 크다.
리팩터링과 리소스 주소
Terraform은 리소스를 주소로 추적한다. 모듈 이름을 바꾸거나 리소스를 다른 모듈로 옮기면 주소가 달라지고, 도구는 이를 "기존 것 삭제 후 새로 생성"으로 해석한다. moved 블록으로 주소 이동을 선언하면 실제 리소스를 건드리지 않고 상태만 갱신할 수 있다. 또한 count는 목록 중간 항목이 빠지면 뒤 인덱스가 밀리면서 무관한 리소스가 재생성되므로, 키가 명확한 대상에는 for_each를 쓰는 편이 안전하다.
블라스트 반경 나누기
네트워크, 데이터 계층, 애플리케이션을 하나의 상태 파일에 넣으면 작은 변경에도 전체 plan을 돌려야 하고 실수의 파급 범위가 커진다. 수명 주기가 다른 자원은 별도 상태로 분리하고, 필요한 값은 원격 상태 참조나 데이터 소스로 읽어오는 구성이 일반적이다. 환경 분리에 workspace를 쓰는 방식은 상태만 나뉠 뿐 코드와 백엔드 설정은 공유되므로, 운영과 개발의 구성 자체가 다르다면 디렉터리 분리가 더 맞는다.
어떤 경우에 Terraform이 적합한가
도입이 유리한 조건
- AWS 외에 다른 클라우드나 SaaS 설정까지 하나의 워크플로로 묶어야 하는 경우. 프로바이더 생태계의 폭이 가장 직접적인 이점이 된다.
- 동일한 구성의 환경을 반복해서 찍어내야 하는 경우. 모듈과 변수로 개발·스테이징·운영을 같은 코드에서 파생시킬 수 있다.
- 변경 이력과 승인 절차가 필요한 조직. 코드 리뷰와 plan 산출물이 그대로 변경 근거 자료가 된다.
- 인프라 담당 인원이 여럿이라 동시 변경 충돌을 통제해야 하는 경우. 원격 백엔드와 잠금이 이 문제를 다룬다.
다른 선택이 나은 조건
- 단일 AWS 계정에서 소수 리소스만 쓰고 앞으로도 AWS만 쓸 계획이라면, 상태 파일을 직접 관리할 필요가 없는 CloudFormation 계열이 운영 부담이 작다.
- 인프라 정의에 복잡한 조건 분기와 계산이 필요하고 팀이 특정 언어에 익숙하다면, 범용 언어 기반 도구가 표현력에서 유리하다.
- 변경 빈도가 극히 낮은 일회성 환경이라면, IaC 학습과 파이프라인 구축 비용이 회수되지 않을 수 있다.
- 라이선스 조건이 사업 모델과 충돌한다면 OpenTofu 같은 대안을 함께 검토한다.
정리하면, Terraform은 "여러 공급자에 걸친 인프라를 여러 사람이 반복해서 바꾸는" 상황에서 값을 한다. 도입을 결정했다면 버전 고정, 원격 상태와 잠금, 상태 파일 접근 통제 세 가지를 첫날에 세팅하는 것이 이후의 복구 비용을 가장 크게 줄인다. 세부 옵션은 버전에 따라 달라지므로 사용 중인 버전의 공식 문서에서 백엔드와 lifecycle 항목을 확인한 뒤 적용하는 것이 안전하다.