Terraform vs Pulumi — IaC 도구 비교 2026
HCL vs 프로그래밍 언어, 상태 관리, 모듈 시스템 비교와 코드 예시.
한 줄 요약: Terraform은 HCL 언어와 대규모 프로바이더 생태계로 IaC의 표준 위치에 있고, Pulumi는 Python/TypeScript 등 범용 언어로 인프라를 코드처럼 다룰 수 있어 개발자 친화적이다. 2026년 기준 둘 다 성숙한 도구이며, 팀의 언어 배경이 선택 기준이 된다.
- IaC 도구를 처음 도입하거나 기존 Terraform에서 대안을 검토 중인 팀
- HCL 대신 Python / TypeScript로 인프라를 관리하고 싶은 개발자
- 상태 파일 관리, 모듈 시스템, 멀티 클라우드 지원을 실무 기준으로 비교하려는 경우
- 같은 AWS 리소스를 두 도구로 구현하는 코드를 직접 보고 싶은 경우
※ Terraform 1.9.x 및 Pulumi 3.x 기준으로 작성됐습니다. OpenTofu(Terraform 포크)는 Terraform과 문법이 동일하므로 HCL 예시는 동일하게 적용됩니다.
핵심 비교표 — Terraform vs Pulumi
| 항목 | Terraform | Pulumi |
|---|---|---|
| 언어 | HCL (HashiCorp Configuration Language) | Python, TypeScript, Go, C#, Java, YAML |
| 상태 관리 | tfstate 파일 (로컬 / S3 / Terraform Cloud) | Pulumi Cloud / S3 / Azure Blob 등 |
| 프로바이더 수 | 3,000+ | 150+ (Terraform 프로바이더 브리지 포함) |
| 모듈 시스템 | Terraform Registry 모듈 | 언어 패키지 매니저 (pip, npm 등) |
| 로직 / 반복문 | count, for_each, dynamic 블록 (제한적) | 언어 기본 루프 / 조건문 (자연스러움) |
| 테스트 | terraform test (1.6+), Terratest | 언어 기본 테스트 프레임워크 |
| 커뮤니티 / 에코시스템 | 압도적으로 넓음 | 성장 중 |
| 라이선스 | BUSL 1.1 (2023년 변경) | Apache 2.0 |
| 오픈소스 대안 | OpenTofu (MPL 2.0) | 해당 없음 (자체 OSS) |
HCL vs 범용 언어 — 실질적 차이
HCL은 선언형 언어다. 인프라의 원하는 상태를 기술하고, 로직이나 반복문은 제한된 문법(count, for_each)으로 표현한다. 단순한 인프라에서는 가독성이 높고 표준화가 쉽다. 그러나 조건부 리소스 생성, 동적 정책 생성 등 복잡한 로직이 필요할 때 HCL의 표현력은 한계에 부딪힌다.
Pulumi는 Python, TypeScript 등 팀이 이미 쓰는 언어로 인프라를 작성한다. 반복문, 조건문, 함수 추상화, 테스트가 언어 수준에서 자연스럽게 지원된다.
같은 인프라 — Terraform vs Pulumi 코드 비교
AWS S3 버킷 + 버전 관리 활성화 + 태그 설정을 두 도구로 구현한다.
Terraform HCL — S3 버킷 + 버전 관리# main.tf provider "aws" { region = "ap-northeast-2" } resource "aws_s3_bucket" "app_assets" { bucket = "my-app-assets-2026" tags = { Environment = "production" Team = "frontend" } } resource "aws_s3_bucket_versioning" "app_assets" { bucket = aws_s3_bucket.app_assets.id versioning_configuration { status = "Enabled" } } output "bucket_name" { value = aws_s3_bucket.app_assets.id }
Pulumi TypeScript — 같은 S3 버킷 + 버전 관리import * as aws from '@pulumi/aws'; const appAssets = new aws.s3.BucketV2('app-assets', { bucket: 'my-app-assets-2026', tags: { Environment: 'production', Team: 'frontend', }, }); const versioning = new aws.s3.BucketVersioningV2('app-assets-versioning', { bucket: appAssets.id, versioningConfiguration: { status: 'Enabled', }, }); export const bucketName = appAssets.id;
기본 리소스 선언은 코드 량이 비슷하다. 차이는 복잡한 로직이 필요할 때 나타난다.
Pulumi 장점 — 조건부 환경별 버킷 생성 (TypeScript 루프)import * as aws from '@pulumi/aws'; import * as pulumi from '@pulumi/pulumi'; const config = new pulumi.Config(); const envs = ['dev', 'staging', 'production']; const buckets = envs.map(env => new aws.s3.BucketV2(`app-assets-${env}`, { bucket: `my-app-assets-${env}-2026`, tags: { Environment: env }, }) ); export const bucketNames = buckets.map(b => b.id);
Terraform — 같은 다중 버킷 (for_each 문법)# main.tf locals { envs = toset(["dev", "staging", "production"]) } resource "aws_s3_bucket" "app_assets" { for_each = local.envs bucket = "my-app-assets-${each.key}-2026" tags = { Environment = each.key } } output "bucket_names" { value = { for env, b in aws_s3_bucket.app_assets : env => b.id } }
상태 파일 관리 — 협업 시 주의 사항
Terraform 상태 관리: tfstate 파일은 민감한 데이터(암호, 토큰)를 평문으로 포함할 수 있다. 로컬 tfstate는 협업에 부적합하다. S3 + DynamoDB(잠금)를 원격 백엔드로 사용하는 것이 표준이다.
Pulumi 상태 관리: Pulumi Cloud(SaaS)를 기본으로 제공하며 상태 잠금, 히스토리, 암호화를 기본 포함한다. 자체 호스팅은 S3, Azure Blob, GCS를 지원한다.
| 항목 | Terraform | Pulumi |
|---|---|---|
| 원격 상태 기본값 | 없음 (직접 설정 필요) | Pulumi Cloud 기본 제공 |
| 상태 잠금 (동시 실행 방지) | DynamoDB 설정 필요 | 자동 (Pulumi Cloud) |
| 상태 파일 암호화 | 별도 설정 필요 | Pulumi Cloud 기본 암호화 |
에코시스템과 마이그레이션
Terraform 에코시스템: Terraform Registry에 3,000개 이상의 프로바이더가 있다. AWS, GCP, Azure, Kubernetes, Datadog, GitHub 등 주요 서비스는 모두 공식 프로바이더가 존재한다. 채용 시장에서 Terraform 경험자가 Pulumi보다 압도적으로 많다.
Pulumi Terraform 브리지: Pulumi는 Terraform 프로바이더를 자동으로 래핑해 사용할 수 있다. 150+ 공식 지원 외에, Terraform 프로바이더 대부분을 Pulumi에서 사용할 수 있다는 의미다.
기존 Terraform에서 Pulumi로 마이그레이션: pulumi convert --from terraform 명령으로 HCL을 Pulumi 코드로 자동 변환할 수 있다. 완전 자동은 아니지만 초기 변환 작업을 크게 줄인다.
프로젝트별 선택 기준
Terraform (또는 OpenTofu)을 선택할 때:
- 팀에 HCL이나 Terraform 경험자가 있는 경우
- Terraform Registry의 방대한 프로바이더 생태계를 활용해야 하는 경우
- 커뮤니티 모듈(VPC, EKS 등)을 그대로 가져다 쓰고 싶은 경우
- 인프라가 비교적 단순하고 선언형 구성으로 충분한 경우
Pulumi를 선택할 때:
- 팀이 Python / TypeScript에 익숙하고 HCL을 새로 배우는 비용을 피하고 싶은 경우
- 인프라 로직이 복잡하고 루프, 조건문, 함수 추상화가 자주 필요한 경우
- 인프라 코드에 일반 언어 테스트 프레임워크를 적용하고 싶은 경우
- Pulumi Cloud로 상태 관리를 간단히 해결하고 싶은 경우
요약 및 참고 자료
- Terraform: 프로바이더 생태계 최대, 채용 인력 풍부, HCL 학습 필요
- Pulumi: 범용 언어 사용, 복잡한 로직에 강함, 생태계는 상대적으로 작음
- BUSL 라이선스가 걱정되면 OpenTofu (HCL 동일, MPL 2.0)
- 기존 Terraform → Pulumi 전환은
pulumi convert로 보조 가능