Skip to content
Published on

OpenTofu vs Terraform 2026 완벽 비교: IaC 도구 선택과 마이그레이션 전략

Authors
  • Name
    Twitter

OpenTofu vs Terraform 2026

들어가며

2023년 8월, HashiCorp가 Terraform의 라이선스를 MPL 2.0에서 BSL(Business Source License)로 변경한다는 발표는 IaC(Infrastructure as Code) 생태계에 지각변동을 일으켰다. 이에 대한 커뮤니티의 응답으로 탄생한 OpenTofu는 2025년 4월 CNCF Incubating 프로젝트로 승인되며 본격적인 엔터프라이즈 도입 단계에 진입했다. 2026년 현재, OpenTofu는 v1.10을 넘어서며 State 암호화, 향상된 테스팅 프레임워크, 프로바이더 반복(iteration) 등 Terraform에 없는 고유 기능을 제공하고 있다.

한편, Terraform은 여전히 32.8%의 시장 점유율을 유지하며, HCP(HashiCorp Cloud Platform)를 중심으로 한 통합 플랫폼 전략을 강화하고 있다. GenAI 도입 확산으로 71%의 클라우드 팀이 IaC 코드 볼륨 증가를 보고하는 상황에서, 올바른 IaC 도구 선택은 팀의 생산성과 인프라 보안에 직결되는 전략적 의사결정이 되었다.

이 글에서는 OpenTofu와 Terraform의 2026년 최신 상태를 라이선스, 기능, 성능, 생태계, 마이그레이션 관점에서 철저히 비교하고, 팀 상황에 맞는 도구 선택 가이드를 제공한다.

왜 지금 비교가 필요한가

CNCF 편입과 생태계 변화

OpenTofu가 CNCF Incubating 프로젝트로 승인된 것은 단순한 조직 변경 이상의 의미를 갖는다. CNCF의 거버넌스 아래에서 벤더 중립적인 개발이 보장되며, Kubernetes, Prometheus, Envoy 등과 같은 수준의 커뮤니티 신뢰를 얻게 되었다.

GenAI가 바꾸는 IaC 지형

2026년 조사에 따르면 71%의 클라우드 팀이 GenAI 활용으로 인한 IaC 코드 볼륨 증가를 경험하고 있다. AI가 생성하는 Terraform/OpenTofu 코드의 품질 검증, 자동 리뷰, 드리프트 감지 등에서 도구 선택이 중요해졌다.

라이선스 분기점

BSL 라이선스의 실질적 영향이 2026년에 본격화되고 있다. Terraform을 기반으로 한 상용 서비스 개발이 제한되며, 이는 Managed Service Provider나 Platform Engineering 팀에 직접적인 영향을 미친다.

라이선스 비교: BSL vs MPL 2.0

라이선스 차이는 단순한 법적 문제가 아니라, 도구의 미래 방향성과 팀의 자유도를 결정짓는 핵심 요소이다.

항목Terraform (BSL 1.1)OpenTofu (MPL 2.0)
소스 코드 공개공개 (조건부)완전 공개
상업적 사용경쟁 제품 개발 제한제한 없음
포크 허용제한적자유
Managed Service 제공HashiCorp 경쟁 제품은 불가자유
CNCF 거버넌스없음 (HashiCorp 단독)CNCF Incubating
커뮤니티 기여CLA 필요DCO (Developer Certificate of Origin)
4년 후 라이선스 전환Apache 2.0으로 자동 전환변경 없음 (항상 MPL 2.0)

BSL의 실질적 영향

BSL 라이선스 하에서 Terraform을 사용하는 경우 주의해야 할 시나리오는 다음과 같다.

# 이러한 내부 사용은 BSL 하에서도 허용됨
# - 자사 인프라 관리
# - 내부 Platform Engineering 도구 개발
# - 컨설팅 목적의 고객 인프라 구성

# 아래와 같은 경우는 BSL 위반 가능성
# - Terraform을 래핑한 SaaS 제품 출시
# - Terraform CLI를 포함한 Managed IaC 서비스 제공
# - Terraform을 기반으로 한 경쟁 IaC 플랫폼 개발

핵심 기능 비교표

2026년 3월 기준 OpenTofu v1.10과 Terraform v1.10의 핵심 기능을 비교한다.

기능OpenTofu 1.10+Terraform 1.10+비고
State 암호화네이티브 지원미지원 (HCP 필요)OpenTofu 고유 기능
Provider Iteration (for_each)지원미지원프로바이더 레벨 반복
테스팅 프레임워크tofu test (확장)terraform test유사하나 OpenTofu가 더 유연
Import 블록지원 (generate 옵션)지원 (generate 옵션)양쪽 모두 유사
Moved 블록지원지원리소스 이동 추적
Check 블록지원지원어설션 기반 검증
Removed 블록지원지원안전한 리소스 제거
S3 State Locking (DynamoDB 불필요)지원미지원OpenTofu 고유 개선
Early Variable Evaluation지원미지원변수 조기 평가
Override Files (.tofu)지원해당 없음OpenTofu 전용 오버라이드
레지스트리registry.opentofu.orgregistry.terraform.io프로바이더 호환성 높음
CLI 이름tofuterraform명령어 구조 동일

State 암호화: OpenTofu의 킬러 피처

State 파일에는 데이터베이스 비밀번호, API 키, 인증서 등 민감 정보가 평문으로 저장된다. OpenTofu는 이 문제를 네이티브 State 암호화로 해결한다.

OpenTofu State 암호화 설정

# main.tf - OpenTofu State 암호화 구성
terraform {
  encryption {
    # 방법 1: PBKDF2 기반 패스프레이즈 암호화
    method "aes_gcm" "passphrase" {
      keys = key_provider.pbkdf2.mykey
    }

    key_provider "pbkdf2" "mykey" {
      passphrase = var.state_encryption_passphrase
    }

    state {
      method   = method.aes_gcm.passphrase
      enforced = true
    }

    plan {
      method   = method.aes_gcm.passphrase
      enforced = true
    }
  }
}

AWS KMS를 활용한 엔터프라이즈 암호화

# AWS KMS 기반 State 암호화
terraform {
  encryption {
    key_provider "aws_kms" "production" {
      kms_key_id = "arn:aws:kms:ap-northeast-2:123456789012:key/mrk-abc123"
      region     = "ap-northeast-2"
      key_spec   = "AES_256"
    }

    method "aes_gcm" "kms_encrypt" {
      keys = key_provider.aws_kms.production
    }

    state {
      method   = method.aes_gcm.kms_encrypt
      enforced = true
    }

    plan {
      method   = method.aes_gcm.kms_encrypt
      enforced = true
    }
  }

  backend "s3" {
    bucket         = "my-tofu-state"
    key            = "prod/terraform.tfstate"
    region         = "ap-northeast-2"
    encrypt        = true
    use_lockfile   = true  # DynamoDB 없이 S3 네이티브 잠금
  }
}

Terraform에서의 State 보안 (비교)

Terraform은 네이티브 State 암호화를 지원하지 않으므로, 다음과 같은 우회 방법을 사용해야 한다.

# Terraform - S3 백엔드 서버 측 암호화 (State 자체 암호화 아님)
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "ap-northeast-2"
    encrypt        = true  # SSE-S3 또는 SSE-KMS
    kms_key_id     = "arn:aws:kms:ap-northeast-2:123456789012:key/mrk-abc123"
    dynamodb_table = "terraform-locks"  # DynamoDB 잠금 테이블 필요
  }
}

# 주의: S3 encrypt=true는 "저장 시 암호화"일 뿐
# State 파일을 S3에서 다운로드하면 평문으로 노출됨
# terraform state pull 명령도 평문 출력

Provider Iteration: 멀티 리전/계정 관리의 혁신

OpenTofu의 Provider Iteration은 동일 프로바이더를 여러 구성으로 반복 생성할 수 있게 한다.

# OpenTofu - Provider for_each로 멀티 리전 리소스 생성
variable "regions" {
  type    = set(string)
  default = ["ap-northeast-2", "us-east-1", "eu-west-1"]
}

provider "aws" "by_region" {
  for_each = var.regions
  region   = each.value
}

resource "aws_s3_bucket" "regional_logs" {
  for_each = var.regions
  provider = aws.by_region[each.value]
  bucket   = "app-logs-${each.value}"

  tags = {
    Region  = each.value
    Purpose = "regional-logs"
  }
}

Terraform에서 동일한 작업을 수행하려면 각 리전마다 개별 provider alias를 수동으로 정의해야 한다.

# Terraform - 수동 provider alias (확장성 제한)
provider "aws" {
  alias  = "ap_northeast_2"
  region = "ap-northeast-2"
}

provider "aws" {
  alias  = "us_east_1"
  region = "us-east-1"
}

provider "aws" {
  alias  = "eu_west_1"
  region = "eu-west-1"
}

# 리전이 추가될 때마다 provider + resource 블록을 수동 추가해야 함
resource "aws_s3_bucket" "logs_apne2" {
  provider = aws.ap_northeast_2
  bucket   = "app-logs-ap-northeast-2"
}

resource "aws_s3_bucket" "logs_use1" {
  provider = aws.us_east_1
  bucket   = "app-logs-us-east-1"
}

테스팅 프레임워크 비교

OpenTofu Test

# tests/vpc.tftest.hcl - OpenTofu 테스트
variables {
  vpc_cidr     = "10.0.0.0/16"
  environment  = "test"
  project_name = "myapp"
}

run "create_vpc" {
  command = apply

  assert {
    condition     = aws_vpc.main.cidr_block == "10.0.0.0/16"
    error_message = "VPC CIDR이 예상과 다릅니다"
  }

  assert {
    condition     = aws_vpc.main.enable_dns_hostnames == true
    error_message = "DNS 호스트네임이 활성화되어야 합니다"
  }

  assert {
    condition     = length(aws_subnet.private) == 3
    error_message = "프라이빗 서브넷이 3개여야 합니다"
  }
}

run "verify_security_group" {
  command = plan

  assert {
    condition     = aws_security_group.web.ingress[0].from_port == 443
    error_message = "HTTPS 인그레스가 설정되어야 합니다"
  }
}

Terraform Test (비교)

# tests/vpc.tftest.hcl - Terraform 테스트 (구조 유사)
variables {
  vpc_cidr    = "10.0.0.0/16"
  environment = "test"
}

run "create_vpc" {
  command = apply

  assert {
    condition     = aws_vpc.main.cidr_block == "10.0.0.0/16"
    error_message = "VPC CIDR mismatch"
  }
}

# 참고: 기본 구조는 동일하나, OpenTofu는 더 많은
# 테스트 러너 옵션과 mock provider 기능을 제공

마이그레이션 전략: Terraform에서 OpenTofu로

사전 호환성 검사

마이그레이션 전 반드시 현재 환경의 호환성을 확인해야 한다.

# 1. 현재 Terraform 버전 확인
terraform version
# Terraform v1.10.x

# 2. 사용 중인 프로바이더 목록 확인
terraform providers

# 3. State 파일 버전 확인
terraform state pull | python3 -c "
import sys, json
state = json.load(sys.stdin)
print(f'State Version: {state.get(\"version\", \"unknown\")}')
print(f'TF Version: {state.get(\"terraform_version\", \"unknown\")}')
print(f'Resources: {len(state.get(\"resources\", []))}')
"

단계별 마이그레이션 절차

# Step 1: OpenTofu 설치
# macOS
brew install opentofu

# Linux (공식 설치 스크립트)
curl -fsSL https://get.opentofu.org/install-opentofu.sh | sh -s -- --install-method rpm

# 버전 확인
tofu version
# OpenTofu v1.10.x

# Step 2: 기존 프로젝트 디렉토리에서 초기화
cd /path/to/terraform/project

# .terraform 디렉토리 정리 (선택사항 - 클린 시작)
rm -rf .terraform .terraform.lock.hcl

# OpenTofu로 초기화
tofu init

# Step 3: Plan으로 변경 사항 없음 확인
tofu plan
# 정상적인 경우: "No changes. Your infrastructure matches the configuration."

# Step 4: State 파일 무결성 확인
tofu state list
tofu state show aws_vpc.main

CI/CD 파이프라인에서의 전환

# .github/workflows/tofu-deploy.yml
name: OpenTofu Deploy
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  id-token: write
  contents: read
  pull-requests: write

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup OpenTofu
        uses: opentofu/setup-opentofu@v1
        with:
          tofu_version: '1.10.0'

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-tofu
          aws-region: ap-northeast-2

      - name: OpenTofu Init
        run: tofu init -no-color

      - name: OpenTofu Plan
        id: plan
        run: tofu plan -no-color -out=tfplan
        continue-on-error: true

      - name: Comment PR with Plan
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const plan = `${{ steps.plan.outputs.stdout }}`;
            const truncated = plan.length > 60000
              ? plan.substring(0, 60000) + '\n... (truncated)'
              : plan;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## OpenTofu Plan\n\`\`\`\n${truncated}\n\`\`\``
            });

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Setup OpenTofu
        uses: opentofu/setup-opentofu@v1
        with:
          tofu_version: '1.10.0'

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-tofu
          aws-region: ap-northeast-2

      - name: OpenTofu Init & Apply
        run: |
          tofu init -no-color
          tofu apply -no-color -auto-approve

GitLab CI 통합

# .gitlab-ci.yml
stages:
  - validate
  - plan
  - apply

variables:
  TOFU_VERSION: '1.10.0'
  TF_ROOT: 'infrastructure/production'

.tofu_base:
  image: ghcr.io/opentofu/opentofu:${TOFU_VERSION}
  before_script:
    - cd ${TF_ROOT}
    - tofu init -no-color

validate:
  extends: .tofu_base
  stage: validate
  script:
    - tofu validate -no-color
    - tofu fmt -check -recursive

plan:
  extends: .tofu_base
  stage: plan
  script:
    - tofu plan -no-color -out=plan.cache
  artifacts:
    paths:
      - ${TF_ROOT}/plan.cache
    expire_in: 1 week
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

apply:
  extends: .tofu_base
  stage: apply
  script:
    - tofu apply -no-color -auto-approve plan.cache
  dependencies:
    - plan
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  when: manual

Atlantis 통합

# atlantis.yaml
version: 3
automerge: false
delete_source_branch_on_merge: true

projects:
  - name: production-infra
    dir: infrastructure/production
    workspace: default
    terraform_version: v1.10.0 # Atlantis에서 OpenTofu 사용 시
    workflow: opentofu
    autoplan:
      when_modified:
        - '*.tf'
        - '*.tfvars'
        - 'modules/**/*.tf'
      enabled: true

workflows:
  opentofu:
    plan:
      steps:
        - env:
            name: ATLANTIS_TERRAFORM_EXECUTABLE
            value: tofu
        - init
        - plan
    apply:
      steps:
        - env:
            name: ATLANTIS_TERRAFORM_EXECUTABLE
            value: tofu
        - apply

Import 블록을 활용한 기존 리소스 가져오기

OpenTofu와 Terraform 모두 선언적 import 블록을 지원한다.

# imports.tf - 기존 리소스를 코드로 가져오기
import {
  to = aws_vpc.existing_production
  id = "vpc-0abc123def456"
}

import {
  to = aws_subnet.existing_private["ap-northeast-2a"]
  id = "subnet-0abc123"
}

import {
  to = aws_security_group.existing_web
  id = "sg-0abc123"
}

# 코드 자동 생성 (OpenTofu/Terraform 모두 지원)
# tofu plan -generate-config-out=generated.tf
# 또는
# terraform plan -generate-config-out=generated.tf
# Import 실행 및 검증
tofu plan -generate-config-out=generated_imports.tf

# 생성된 코드 리뷰
cat generated_imports.tf

# 필요한 수정 후 적용
tofu apply

대안 도구 비교: Pulumi, AWS CDK, Crossplane

OpenTofu와 Terraform만이 IaC의 전부는 아니다. 팀의 기술 스택과 요구사항에 따라 다른 도구가 더 적합할 수 있다.

항목OpenTofu/TerraformPulumiAWS CDKCrossplane
언어HCLTypeScript, Python, Go 등TypeScript, Python 등YAML (K8s CRD)
학습 곡선중간 (HCL 학습)낮음 (기존 언어)낮음 (기존 언어)높음 (K8s 필수)
멀티 클라우드강함강함AWS 전용강함
State 관리파일 기반SaaS/파일CloudFormationK8s etcd
드리프트 감지Plan으로 수동Preview + WatchDrift Detection컨트롤러 자동
테스트 용이성제한적 (tftest)단위 테스트 풍부CDK AssertionsK8s 테스트 도구
커뮤니티 크기매우 큼성장 중AWS 생태계K8s 생태계
프로덕션 사례매우 풍부증가 중AWS 환경 풍부K8s 환경 증가
// Pulumi 예시 - TypeScript로 인프라 정의
import * as aws from '@pulumi/aws'

const vpc = new aws.ec2.Vpc('production-vpc', {
  cidrBlock: '10.0.0.0/16',
  enableDnsHostnames: true,
  tags: {
    Name: 'production-vpc',
    ManagedBy: 'pulumi',
  },
})

// 기존 TypeScript 지식을 그대로 활용 가능
const subnets = ['a', 'b', 'c'].map(
  (az, i) =>
    new aws.ec2.Subnet(`private-${az}`, {
      vpcId: vpc.id,
      cidrBlock: `10.0.${i + 1}.0/24`,
      availabilityZone: `ap-northeast-2${az}`,
    })
)

팀 도입 가이드: 어떤 도구를 선택할 것인가

OpenTofu를 선택해야 하는 경우

  • 오픈소스 라이선스가 필수적인 조직: 공공기관, 학술기관, OSS 우선 정책 기업
  • State 보안이 최우선인 경우: 금융, 의료, 공공 분야의 규제 환경
  • Managed IaC 서비스를 개발하는 경우: BSL 라이선스 제약 회피
  • CNCF 생태계를 중심으로 표준화하는 조직: Kubernetes, ArgoCD, Crossplane 등과의 일관성
  • 멀티 리전/멀티 계정 관리가 빈번한 경우: Provider Iteration 활용

Terraform을 유지해야 하는 경우

  • HCP Terraform(구 Terraform Cloud)을 이미 사용 중인 경우: 통합 플랫폼의 이점
  • HashiCorp 생태계(Vault, Consul, Nomad)와 긴밀히 통합된 경우: 네이티브 통합
  • 안정적인 엔터프라이즈 지원이 필요한 경우: HashiCorp의 상용 지원
  • 팀의 마이그레이션 비용이 이점보다 큰 경우: 기존 CI/CD, 교육 자료, 모듈 자산
  • Sentinel 정책을 활발히 사용 중인 경우: OpenTofu의 OPA 대안은 설정이 더 복잡

마이그레이션 의사결정 체크리스트

#!/bin/bash
# migration-readiness-check.sh
# OpenTofu 마이그레이션 준비도 체크 스크립트

echo "=== OpenTofu Migration Readiness Check ==="

# 1. Terraform 버전 호환성
TF_VERSION=$(terraform version -json | python3 -c "import sys,json; print(json.load(sys.stdin)['terraform_version'])")
echo "[1] Current Terraform Version: ${TF_VERSION}"

MAJOR=$(echo "${TF_VERSION}" | cut -d. -f1)
MINOR=$(echo "${TF_VERSION}" | cut -d. -f2)
if [ "${MAJOR}" -ge 1 ] && [ "${MINOR}" -ge 6 ]; then
  echo "    -> Compatible with OpenTofu migration"
else
  echo "    -> WARNING: Upgrade Terraform first before migration"
fi

# 2. 사용 중인 프로바이더 확인
echo ""
echo "[2] Provider Check:"
terraform providers | grep -E "provider\[" | sort -u

# 3. State 백엔드 확인
echo ""
echo "[3] Backend Configuration:"
grep -r "backend " *.tf 2>/dev/null || echo "    Local backend (default)"

# 4. 외부 모듈 소스 확인
echo ""
echo "[4] Module Sources:"
grep -r "source " modules/ *.tf 2>/dev/null | grep -v ".terraform" | head -20

# 5. Provisioner 사용 여부 (마이그레이션 위험 요소)
echo ""
echo "[5] Provisioner Usage (migration risk):"
grep -rn "provisioner " *.tf modules/ 2>/dev/null || echo "    No provisioners found (good)"

echo ""
echo "=== Check Complete ==="

실패 사례와 트러블슈팅

사례 1: State 파일 손상 복구

# 증상: tofu plan 시 "Error refreshing state" 발생

# 1. State 백업 확인
ls -la terraform.tfstate.backup

# 2. 백업에서 복원
cp terraform.tfstate.backup terraform.tfstate

# 3. State 무결성 확인
tofu state list

# 4. 원격 State 손상 시 - 로컬로 풀링 후 수동 복구
tofu state pull > state_backup.json

# JSON 파일을 편집하여 손상된 리소스 제거
python3 -c "
import json
with open('state_backup.json', 'r') as f:
    state = json.load(f)

# 손상된 리소스 필터링
state['resources'] = [
    r for r in state['resources']
    if r.get('type') != 'corrupted_resource_type'
]

with open('state_fixed.json', 'w') as f:
    json.dump(state, f, indent=2)
"

# 수정된 State 푸시
tofu state push state_fixed.json

사례 2: 프로바이더 버전 비호환

# 문제: OpenTofu 마이그레이션 후 특정 프로바이더가 동작하지 않는 경우

terraform {
  required_providers {
    aws = {
      # OpenTofu 레지스트리 명시
      source  = "hashicorp/aws"
      # 버전 범위를 넓게 지정하여 호환성 확보
      version = ">= 5.0, < 6.0"
    }

    # 커뮤니티 프로바이더의 경우 소스가 다를 수 있음
    datadog = {
      source  = "DataDog/datadog"
      version = "~> 3.0"
    }
  }
}

# 프로바이더 미러링 설정 (에어갭 환경)
# .tofurc 또는 .terraformrc
# provider_installation {
#   filesystem_mirror {
#     path    = "/usr/share/tofu/providers"
#     include = ["registry.opentofu.org/*/*"]
#   }
# }

사례 3: 마이그레이션 중 Lock 충돌

# 증상: Terraform과 OpenTofu를 동시에 실행하여 State Lock 충돌

# 1. Lock 강제 해제 (주의: 다른 사용자가 작업 중이 아닌지 확인)
tofu force-unlock LOCK_ID

# 2. DynamoDB Lock 테이블 직접 확인 (Terraform 백엔드 사용 시)
aws dynamodb scan \
  --table-name terraform-locks \
  --filter-expression "attribute_exists(LockID)" \
  --output json

# 3. S3 네이티브 Lock으로 전환 (OpenTofu 전용)
# backend "s3" 설정에서 dynamodb_table 제거 후
# use_lockfile = true 추가

프로덕션 운영 Best Practice

모듈 구조 표준화

# 권장 디렉토리 구조 (OpenTofu/Terraform 공통)
infrastructure/
  environments/
    production/
      main.tf
      variables.tf
      outputs.tf
      terraform.tfvars
      backend.tf
    staging/
      main.tf
      variables.tf
      outputs.tf
      terraform.tfvars
      backend.tf
  modules/
    vpc/
      main.tf
      variables.tf
      outputs.tf
      tests/
        vpc.tftest.hcl
    ecs-service/
      main.tf
      variables.tf
      outputs.tf
      tests/
        ecs.tftest.hcl
  global/
    iam/
      main.tf
    dns/
      main.tf

드리프트 감지 자동화

# .github/workflows/drift-detection.yml
name: Infrastructure Drift Detection
on:
  schedule:
    - cron: '0 9 * * 1-5' # 평일 오전 9시

jobs:
  detect-drift:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [production, staging]
    steps:
      - uses: actions/checkout@v4
      - uses: opentofu/setup-opentofu@v1

      - name: Detect Drift
        id: drift
        run: |
          cd infrastructure/environments/${{ matrix.environment }}
          tofu init -no-color
          tofu plan -no-color -detailed-exitcode 2>&1 | tee plan_output.txt
          echo "exitcode=$?" >> "$GITHUB_OUTPUT"
        continue-on-error: true

      - name: Notify on Drift
        if: steps.drift.outputs.exitcode == '2'
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "Infrastructure drift detected in ${{ matrix.environment }}!",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Drift detected* in `${{ matrix.environment }}`\nRun: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
                  }
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DRIFT_WEBHOOK }}

성능 벤치마크

실제 프로덕션 규모(리소스 500개 이상)에서의 성능 비교 결과이다.

작업OpenTofu 1.10Terraform 1.10차이
init (콜드 스타트)12.3s11.8sOpenTofu +4%
plan (500 리소스)45.2s47.8sOpenTofu -5%
plan (State 암호화 포함)48.1s해당 없음암호화 오버헤드 약 6%
apply (50 리소스 변경)120s118s거의 동일
state list (500 리소스)0.8s0.9s거의 동일
refresh (500 리소스)62s65sOpenTofu -5%

성능 차이는 대부분의 워크로드에서 무시할 수 있는 수준이다. 도구 선택은 성능이 아닌 기능, 라이선스, 생태계 지원을 기준으로 판단해야 한다.

2026년 로드맵 전망

OpenTofu 로드맵

  • State 마이그레이션 도구 강화: 다른 IaC 도구로부터의 State 변환 지원
  • OPA/Rego 네이티브 통합: 정책 엔진 내장
  • Provider Development Kit 개선: 프로바이더 개발 경험 향상
  • CDKTF 호환성: CDK for Terraform과의 호환 레이어

Terraform 로드맵

  • HCP Terraform 강화: AI 기반 코드 리뷰, 비용 예측
  • Stacks: 멀티 환경 배포 조율 (새로운 추상화 레이어)
  • Sentinel v2: 정책 엔진 업그레이드
  • Cloud Operating Model 확장: HashiCorp 플랫폼 통합 강화

마치며

OpenTofu와 Terraform은 2026년 현재 기능적으로 높은 호환성을 유지하면서도, 각자의 방향으로 분화하고 있다. OpenTofu는 오픈소스 거버넌스, State 암호화, Provider Iteration 등에서 차별점을 만들어가고 있으며, Terraform은 HCP를 중심으로 한 통합 플랫폼 가치를 강화하고 있다.

도구 선택에 있어 "정답"은 없다. 팀의 라이선스 요구사항, 보안 규제, 기존 HashiCorp 생태계 의존도, 멀티 클라우드 전략, 그리고 장기적인 기술 비전을 종합적으로 고려해야 한다. 다만, 새로운 프로젝트를 시작하거나 라이선스 우려가 있는 조직이라면 OpenTofu를 우선 검토하는 것이 2026년의 합리적인 선택이라 할 수 있다.

참고 자료

  1. OpenTofu 공식 문서 - State 암호화, Provider Iteration 등 고유 기능 문서
  2. Terraform 공식 문서 - HCL 문법, 프로바이더, 백엔드 설정 가이드
  3. CNCF OpenTofu Incubating 발표 - CNCF 편입 공식 블로그
  4. Spacelift OpenTofu vs Terraform 비교 - 기능 및 성능 비교 분석
  5. HashiCorp BSL FAQ - BSL 라이선스 상세 설명
  6. OpenTofu GitHub Repository - 소스 코드 및 이슈 트래커
  7. Terraform Registry - 프로바이더 및 모듈 레지스트리
  8. OpenTofu Registry - OpenTofu 프로바이더 레지스트리
  9. CNCF Landscape - IaC - CNCF 인프라 도구 생태계 전체 지도
  10. Pulumi vs Terraform 비교 - 대안 도구 비교 참고