# Pulumi vs Terraform 2026: TypeScript 기반 Infrastructure as Code와 면접 질문 > 2026년 Pulumi와 Terraform 비교 가이드입니다. TypeScript 지원, 상태 관리, 프로바이더 에코시스템, 마이그레이션 전략, DevOps 면접 질문을 다룹니다. - Published: 2026-09-21 - Updated: 2026-09-21 - Author: Anthony Fillion-Maillet - Reading time: 5 min --- Pulumi와 Terraform은 2026년 DevOps 팀에게 Infrastructure as Code(IaC) 영역에서 핵심적인 선택지입니다. 두 도구 모두 클라우드 리소스를 선언적으로 프로비저닝하지만, 언어 지원, 상태 관리, 에코시스템 성숙도에서 상당한 차이가 있습니다. 본 문서에서는 기술적 트레이드오프, TypeScript와 HCL 코드 예제, IaC 선택과 관련된 면접 질문을 상세히 다룹니다. > **버전 정보: 2026년 9월 기준** > > 본 비교는 Pulumi v3.263.0(2026년 9월 15일 릴리스)과 Terraform 1.16.3(2026년 8월 26일 릴리스)을 기반으로 합니다. HashiCorp의 TypeScript 레이어인 CDKTF는 2025년 12월에 지원 중단되어 아카이브되었습니다. ## 핵심 아키텍처: Pulumi 엔진 vs Terraform Plan-Apply 사이클 Terraform은 도메인 특화 언어(HCL)와 2단계 워크플로우를 사용합니다. `terraform plan`이 실행 계획을 생성하고, `terraform apply`가 이를 실행합니다. 상태 파일은 리소스 메타데이터를 추적하며, 로컬 또는 S3나 Terraform Cloud 같은 원격 백엔드에 저장됩니다. Pulumi는 범용 런타임에 엔진을 내장합니다. TypeScript, Python, Go, C#으로 작성된 프로그램이 Pulumi 프로바이더를 통해 클라우드 API에 직접 접근합니다. 상태는 기본적으로 Pulumi Cloud에 저장되며, S3, Azure Blob Storage, 로컬 파일 등 자체 관리 백엔드 옵션도 제공됩니다. 아키텍처 차이는 루프, 조건문, 추상화 처리 방식에서 즉각적으로 드러납니다. Terraform의 `for_each`와 `count`는 HCL의 제약 내에서 동작합니다. Pulumi 프로그램은 네이티브 언어 구문을 사용합니다: TypeScript의 `for...of`, Python의 리스트 컴프리헨션, Go의 `range` 등입니다. ```typescript // infra/index.ts - Pulumi TypeScript 예제 import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; // 네이티브 TypeScript 배열 메서드 직접 사용 가능 const environments = ["dev", "staging", "prod"]; const buckets = environments.map(env => new aws.s3.BucketV2(`data-${env}`, { bucket: `myapp-data-${env}-${pulumi.getStack()}`, tags: { Environment: env, ManagedBy: "pulumi", }, }) ); // 버킷 ARN을 스택 출력으로 내보내기 export const bucketArns = buckets.map(b => b.arn); ``` 동등한 Terraform 구성은 반복을 위해 HCL 문법이 필요합니다: ```hcl # main.tf - Terraform HCL 예제 variable "environments" { type = list(string) default = ["dev", "staging", "prod"] } resource "aws_s3_bucket" "data" { for_each = toset(var.environments) bucket = "myapp-data-${each.key}-${terraform.workspace}" tags = { Environment = each.key ManagedBy = "terraform" } } output "bucket_arns" { value = [for b in aws_s3_bucket.data : b.arn] } ``` 두 스니펫 모두 S3 버킷 3개를 생성합니다. Terraform 버전은 HCL에 익숙한 사람에게 간결하고 가독성이 좋습니다. Pulumi 버전은 표준 TypeScript를 사용하므로 IDE 자동완성, 타입 체크, 기존 코드베이스와의 통합이 가능하며, 새로운 언어를 배울 필요가 없습니다. ## TypeScript 지원: 네이티브 언어 vs CDKTF(지원 중단) Pulumi는 첫 번째 공개 릴리스부터 TypeScript를 지원합니다. SDK는 타입이 지정된 리소스 클래스를 제공하고, `pulumi.Output`는 배포 중 해결되는 비동기 값을 래핑합니다. TypeScript 에코시스템의 리팩토링 도구, 린터, 테스트 프레임워크가 직접 적용 가능합니다. Terraform의 범용 언어 지원에 대한 답변은 [CDKTF(Cloud Development Kit for Terraform)](https://developer.hashicorp.com/terraform/cdktf)였습니다. CDKTF는 Terraform JSON으로 컴파일되는 TypeScript 또는 Python 코드 작성을 가능하게 했습니다. HashiCorp는 2025년 12월에 CDKTF를 지원 중단하고 리포지토리를 아카이브했습니다. 기존 CDKTF 프로젝트는 계속 실행되지만, 새로운 Terraform 버전이나 프로바이더 변경에 대한 업데이트는 제공되지 않습니다. 2026년에 TypeScript IaC를 원하는 팀에게 Pulumi가 적극적으로 유지보수되는 옵션입니다. CDKTF에 이미 투자한 팀은 기존 스택을 계속 운영할 수 있지만, 신규 개발에서는 HCL 또는 Pulumi로의 마이그레이션이 앞으로 나아가는 길입니다. ```typescript // infra/vpc.ts - 재사용 가능한 VPC 추상화를 위한 Pulumi 컴포넌트 import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; // VPC, 서브넷, 라우팅을 캡슐화하는 커스텀 컴포넌트 export class StandardVpc extends pulumi.ComponentResource { public readonly vpcId: pulumi.Output; public readonly publicSubnetIds: pulumi.Output[]; constructor(name: string, args: { cidr: string; azCount: number }, opts?: pulumi.ComponentResourceOptions) { super("mycompany:network:StandardVpc", name, {}, opts); const vpc = new aws.ec2.Vpc(`${name}-vpc`, { cidrBlock: args.cidr, enableDnsHostnames: true, tags: { Name: name }, }, { parent: this }); this.vpcId = vpc.id; // 가용 영역 전체에 퍼블릭 서브넷 생성 const azs = aws.getAvailabilityZones({ state: "available" }); this.publicSubnetIds = []; for (let i = 0; i < args.azCount; i++) { const subnet = new aws.ec2.Subnet(`${name}-public-${i}`, { vpcId: vpc.id, cidrBlock: `10.0.${i}.0/24`, availabilityZone: azs.then(az => az.names[i]), mapPublicIpOnLaunch: true, tags: { Name: `${name}-public-${i}` }, }, { parent: this }); this.publicSubnetIds.push(subnet.id); } this.registerOutputs({ vpcId: this.vpcId }); } } ``` 이 Pulumi 컴포넌트는 재사용 가능한 VPC 추상화를 생성합니다. 사용자는 `new StandardVpc("prod", { cidr: "10.0.0.0/16", azCount: 3 })`로 인스턴스화합니다. Terraform에서 동등한 구현은 변수, 출력, HCL 파일이 포함된 모듈 디렉터리입니다. 두 접근 방식 모두 재사용을 가능하게 하지만, Pulumi 버전은 문서화, 테스트, 버전 관리를 위한 TypeScript 도구를 상속받습니다. ## 상태 관리 및 백엔드 옵션 상태 관리는 운영상의 차이가 나타나는 영역입니다. Terraform 상태에는 리소스 ID, 프로바이더 메타데이터, 민감한 값이 포함됩니다. 팀은 협업을 위해 원격 백엔드를 구성하고, 동시 수정을 방지하기 위해 잠금을 구현해야 합니다. [Terraform 백엔드 구성](https://developer.hashicorp.com/terraform/language/settings/backends/configuration)은 S3, Azure Blob, Google Cloud Storage, Terraform Cloud 등을 지원합니다. 각 백엔드는 자체 인증 설정이 필요합니다. 상태 잠금은 S3 백엔드에서 DynamoDB, Azure에서 Blob 리스, Terraform Cloud에서 네이티브 잠금을 사용합니다. Pulumi Cloud는 기본적으로 상태 저장소, 잠금, 이력을 처리합니다. 팀은 무료 계정을 만들고 `pulumi login`을 실행하면 상태 관리가 구성됩니다. 자체 관리 상태가 필요한 팀을 위해 Pulumi는 `pulumi login` 명령으로 S3, Azure Blob, GCS, 로컬 파일 백엔드를 지원합니다. ```bash # Pulumi: 자체 관리 S3 백엔드에 로그인 pulumi login s3://my-pulumi-state-bucket # Terraform: HCL에서 S3 백엔드 구성 # backend.tf terraform { backend "s3" { bucket = "my-terraform-state" key = "prod/terraform.tfstate" region = "us-east-1" dynamodb_table = "terraform-locks" encrypt = true } } ``` Pulumi Cloud는 스택 이력, 리소스 시각화, 팀 권한을 위한 웹 UI를 제공합니다. Terraform Cloud는 Sentinel을 통한 정책 적용과 유사한 기능을 제공합니다. 두 도구 모두 자체 호스팅 옵션이 있습니다: Pulumi의 자체 호스팅 백엔드와 Terraform Enterprise입니다. ## 프로바이더 에코시스템 및 멀티클라우드 지원 Terraform의 프로바이더 에코시스템은 IaC에서 가장 큽니다. [Terraform Registry](https://registry.terraform.io/)에는 AWS, Azure, GCP, Kubernetes 및 수백 개의 SaaS 플랫폼을 다루는 4,000개 이상의 프로바이더가 등록되어 있습니다. 프로바이더 품질은 다양합니다: HashiCorp 공식 및 클라우드 벤더 프로바이더는 정기적으로 업데이트되지만, 커뮤니티 프로바이더는 API 변경에 뒤처질 수 있습니다. Pulumi 프로바이더는 타입이 지정된 SDK를 생성하는 브릿지를 사용하여 Terraform 프로바이더를 래핑합니다. [Pulumi Registry](https://www.pulumi.com/registry/)는 주요 클라우드, Kubernetes, 데이터베이스, 모니터링 서비스용 프로바이더를 제공합니다. Pulumi가 Terraform 프로바이더를 브릿지하기 때문에 에코시스템 커버리지는 비슷하지만, 새로운 Terraform 프로바이더 버전은 Pulumi SDK에 반영되기 전에 브릿지 업데이트가 필요합니다. Pulumi는 클라우드 API에 직접 작성된 네이티브 프로바이더도 제공합니다. AWS, Azure, Kubernetes용 네이티브 프로바이더는 새로운 API 기능을 당일 지원합니다. 트레이드오프로, 네이티브 프로바이더는 주요 클라우드에만 존재하며, 덜 일반적인 서비스는 브릿지 프로바이더를 사용합니다. ```typescript // Pulumi 네이티브 AWS 프로바이더를 사용한 Lambda import * as aws from "@pulumi/aws"; import * as pulumi from "@pulumi/pulumi"; const role = new aws.iam.Role("lambda-role", { assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({ Service: "lambda.amazonaws.com", }), }); const lambdaFunction = new aws.lambda.Function("api-handler", { runtime: aws.lambda.Runtime.NodeJS20dX, handler: "index.handler", role: role.arn, code: new pulumi.asset.AssetArchive({ "index.js": new pulumi.asset.StringAsset( `exports.handler = async () => ({ statusCode: 200, body: "OK" });` ), }), }); export const functionArn = lambdaFunction.arn; ``` ## 인프라 코드 테스트 테스트는 언어 선택에 따라 분기가 생기는 영역입니다. Pulumi 프로그램은 표준 코드이므로 유닛 테스트는 익숙한 프레임워크를 사용합니다. `@pulumi/pulumi/runtime` 모듈은 리소스 생성을 위한 모킹을 제공하여 리소스를 배포하지 않고 구성을 검증할 수 있습니다. ```typescript // __tests__/infra.test.ts - Vitest로 Pulumi 리소스 유닛 테스트 import { describe, it, expect, beforeAll } from "vitest"; import * as pulumi from "@pulumi/pulumi"; // Pulumi 런타임 모킹 pulumi.runtime.setMocks({ newResource: (args: pulumi.runtime.MockResourceArgs) => { return { id: `${args.name}-id`, state: args.inputs }; }, call: (args: pulumi.runtime.MockCallArgs) => { return args.inputs; }, }); describe("S3 버킷 구성", () => { let bucketTags: Record; beforeAll(async () => { // 모킹 설정 후 Pulumi 프로그램 임포트 const infra = await import("../infra/index"); // 테스트용 출력 추출 bucketTags = await new Promise(resolve => { infra.buckets[0].tags.apply(tags => resolve(tags as Record)); }); }); it("버킷에 Environment 태그가 설정되어야 함", () => { expect(bucketTags).toHaveProperty("Environment"); }); it("버킷에 ManagedBy 태그가 설정되어야 함", () => { expect(bucketTags.ManagedBy).toBe("pulumi"); }); }); ``` Terraform 테스트는 `terraform test`(Terraform 1.6에서 도입) 또는 Terratest 같은 외부 도구를 사용합니다. `terraform test`는 격리된 구성에서 실제 리소스를 생성하는 HCL 테스트 파일을 실행합니다. Terratest는 Terraform 명령을 래핑하고 어설션을 제공하는 Go 라이브러리입니다. ```hcl # tests/bucket.tftest.hcl - Terraform 네이티브 테스트 run "bucket_tags" { command = plan assert { condition = aws_s3_bucket.data["dev"].tags["Environment"] == "dev" error_message = "버킷에 Environment 태그가 필요합니다" } assert { condition = aws_s3_bucket.data["dev"].tags["ManagedBy"] == "terraform" error_message = "버킷에 ManagedBy 태그가 필요합니다" } } ``` 두 접근 방식 모두 인프라 구성을 검증합니다. Pulumi의 장점은 TypeScript 테스트 러너 및 커버리지 도구와의 통합입니다. Terraform 네이티브 테스트는 외부 의존성 없이 실행되지만 HCL 문법이 필요합니다. ## 면접 질문: Pulumi vs Terraform 2026년 DevOps 면접에는 IaC 도구 비교가 자주 포함됩니다. 다음은 프로덕션 환경에서 두 도구를 사용한 후보자를 구분하는 질문입니다. **"Terraform 상태가 실제 인프라와 드리프트되면 어떤 일이 발생합니까?"** 예상 답변: `terraform plan`은 상태와 실제 인프라를 비교하여 드리프트를 감지합니다. 계획은 업데이트, 생성, 삭제할 리소스를 보여줍니다. 드리프트는 Terraform 외부에서 변경이 이루어질 때(콘솔, CLI, 다른 도구) 발생합니다. 옵션으로는 상태를 업데이트하는 `terraform refresh`, 리소스를 관리 대상으로 가져오는 `terraform import`, 또는 원하는 상태를 복원하기 위해 계획을 수락하는 것이 있습니다. **"Pulumi는 Terraform과 비교하여 시크릿을 어떻게 다르게 처리합니까?"** 예상 답변: Pulumi는 패스프레이즈 또는 클라우드 KMS를 사용하여 기본적으로 상태의 시크릿을 암호화합니다. `pulumi.secret()` 함수는 값을 민감한 것으로 표시하며, 저장 시 암호화된 상태로 유지됩니다. Terraform은 상태 파일에 시크릿을 평문으로 저장하며, 팀은 백엔드 암호화(S3 서버 측 암호화)와 액세스 제어에 의존합니다. Terraform 1.4에서 `sensitive` 변수 마킹이 추가되었지만, 값은 여전히 상태에서 암호화되지 않은 상태로 나타납니다. **"HashiCorp가 CDKTF를 지원 중단한 이유와 마이그레이션 옵션은 무엇입니까?"** 예상 답변: CDKTF는 Terraform의 업데이트 주기에 맞추지 못하면서 유지보수 오버헤드를 추가했습니다. 새로운 프로바이더 버전과 Terraform 기능은 CDK 바인딩에 대한 수동 업데이트가 필요했습니다. HashiCorp는 HCL과 Terraform Cloud에 집중하기로 결정했습니다. 마이그레이션 옵션은: `cdktf convert`를 사용하여 HCL로 변환, TypeScript가 필요한 경우 Pulumi로 재작성, 또는 업데이트 없이 기존 CDKTF 스택을 계속 운영하는 것입니다. **"새 프로젝트에서 Terraform 대신 Pulumi를 선택하는 경우는 언제입니까?"** 예상 답변: 팀이 이미 TypeScript/Python/Go를 사용하고 있고 애플리케이션 코드와 동일한 언어로 IaC를 작성하려는 경우, 복잡한 추상화에 실제 프로그래밍 구문(제네릭, 인터페이스, 테스트 프레임워크)이 필요한 경우, 또는 내장 시크릿 암호화가 요구사항인 경우 Pulumi를 선택합니다. 팀이 HCL을 알고 있는 경우, 프로바이더 에코시스템에 틈새 또는 커뮤니티 프로바이더가 필요한 경우, 또는 조직 도구(Atlantis, Spacelift)가 Terraform과 통합되는 경우 Terraform을 선택합니다. Infrastructure as Code 면접 준비에 대한 자세한 내용은 [Terraform 면접 질문: Infrastructure as Code 완전 가이드](/blog/devops/terraform-interview-questions-infrastructure-as-code) 및 [Terraform 고급 모듈](/technologies/devops/interview-questions/terraform-advanced)을 참조하십시오. ## 마이그레이션 전략: Terraform에서 Pulumi로 Pulumi는 `pulumi import`를 제공하여 기존 클라우드 리소스를 재생성하지 않고 관리 대상으로 가져올 수 있습니다. Terraform 상태를 가진 팀을 위해 `pulumi convert`는 HCL을 Pulumi 프로그램으로 변환합니다. 변환은 완벽하지 않으며, 복잡한 모듈과 동적 블록은 수동 조정이 필요합니다. ```bash # Terraform HCL을 Pulumi TypeScript로 변환 pulumi convert --from terraform --language typescript # 기존 AWS 리소스를 Pulumi 상태로 임포트 pulumi import aws:s3/bucketV2:BucketV2 my-bucket my-existing-bucket-name ``` 단계적 마이그레이션을 통해 팀은 전환 기간 동안 두 도구를 모두 운영할 수 있습니다. Terraform이 기존 스택을 관리하고 Pulumi가 새로운 인프라를 프로비저닝합니다. 팀이 Pulumi 경험을 쌓은 후 Terraform 스택을 점진적으로 변환합니다. 상태는 도구 간에 공유되지 않으므로 충돌을 피하기 위해 리소스 관리를 명확하게 분리해야 합니다. ## 2026년 의사결정 프레임워크 | 요소 | Terraform | Pulumi | |------|-----------|--------| | 언어 | HCL(DSL) | TypeScript, Python, Go, C#, Java, YAML | | 상태 관리 | 자체 관리 또는 Terraform Cloud | Pulumi Cloud(기본) 또는 자체 관리 | | 시크릿 처리 | 상태에 평문, 백엔드 암호화 | 기본 암호화 | | 테스트 | `terraform test`, Terratest | 네이티브 언어 테스트 프레임워크 | | 프로바이더 커버리지 | 레지스트리에 4,000개 이상 | Terraform 프로바이더 브릿지 + 네이티브 SDK | | TypeScript 지원 | CDKTF(2025년 12월 지원 중단) | 퍼스트 클래스, 적극적 유지보수 | | 학습 곡선 | HCL은 전용 설계, IaC에 빠름 | 기존 언어 지식 필요 | | 엔터프라이즈 기능 | Terraform Cloud/Enterprise | Pulumi Cloud/자체 호스팅 | > **면접 팁** > > Pulumi vs Terraform에 대해 질문받을 때 한쪽이 "더 좋다"고 말하는 것을 피합니다. 트레이드오프를 명확히 합니다: Terraform은 더 큰 에코시스템을 가지고 있고 HCL의 제약이 런타임 오류를 방지합니다. Pulumi는 실제 언어 기능과 타입이 지정된 SDK를 제공합니다. 선택이 팀 스킬, 기존 도구, 프로젝트 요구사항에 따라 달라진다는 것을 보여줍니다. ## 2026년 Infrastructure as Code 핵심 사항 - Terraform 1.16은 최대 프로바이더 에코시스템과 성숙한 도구(Atlantis, Spacelift, env0)를 갖춘 HCL 기반 IaC의 안정적인 선택입니다. - Pulumi v3.263은 네이티브 언어 테스트, IDE 통합, 내장 시크릿 암호화와 함께 TypeScript, Python, Go, C#을 제공합니다. - CDKTF는 2025년 12월부터 지원 중단되었습니다. TypeScript IaC를 원하는 팀은 새로운 CDKTF 프로젝트를 시작하기보다 Pulumi를 평가해야 합니다. - 두 도구 모두 멀티클라우드 배포, 원격 상태 백엔드, 팀 협업을 지원합니다. 선택은 언어 선호도와 기존 팀 전문성에 따라 달라집니다. - 면접 토론에서는 상태 관리, 드리프트 감지, 프로바이더 에코시스템, DSL 단순성과 범용 언어 파워 간의 트레이드오프에 대한 이해를 보여야 합니다. - Terraform에서 Pulumi로의 마이그레이션은 `pulumi convert`와 `pulumi import`를 사용하여 가능하지만 신중한 계획과 단계적 롤아웃이 필요합니다. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/ko/blog/devops/pulumi-vs-terraform-2026-infrastructure-as-code-typescript-interview-questions