13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] remote backend

  • [Cloud] Terraform State 파일 오류 디버깅: Lock·Drift 해결 전략

    [Cloud] Terraform State 파일 오류 디버깅: Lock·Drift 해결 전략

    Terraform State 파일 오류 디버깅: Lock·Drift 해결 전략

    Terraform State 파일 오류는 대개 Terraform이 기억하는 세계와 실제 클라우드에 존재하는 세계가 어긋날 때 시작됩니다. 에러 메시지는 lock, drift, import, backend처럼 흩어져 나오지만, 현장에서 보면 원인은 보통 세 가지입니다. 같은 state를 동시에 만졌거나, 콘솔·스크립트·다른 파이프라인이 리소스를 바꿨거나, 내가 생각한 backend가 아닌 다른 state를 보고 있는 경우입니다.

    저도 홈랩의 Proxmox VM과 AWS 테스트 계정을 Terraform으로 같이 관리하다가 state가 꼬인 적이 있습니다. plan은 말이 안 되는 삭제를 보여주고, apply는 lock에 막히고, 이미 콘솔에서 지운 인스턴스를 Terraform은 아직 관리 중이라고 믿고 있더라고요. 그때 배운 건 단순합니다. Terraform 디버깅은 명령어를 많이 아는 게임이 아니라, state, configuration, real infrastructure 중 어느 쪽이 틀렸는지 분리하는 작업입니다.

    이 글은 공식 문서 요약보다 운영 중 손을 멈춰야 할 지점, 바로 실행해도 되는 명령, 마지막까지 미뤄야 할 명령을 구분하는 실전 기준에 가깝습니다. 특히 state rm, import, state mv, force-unlock은 모두 강력하지만 잘못 쓰면 문제를 감추거나 더 키울 수 있습니다. 내부 위키에 IaC 배포 절차나 장애 복구 문서가 있다면 이 글과 함께 연결해 두면 리뷰 때 진짜 편합니다.

    Terraform State 파일 오류 이해를 위한 state 관리 흐름 다이어그램

    Terraform CLI, 원격 백엔드, 실제 클라우드 리소스, state lock이 어떻게 연결되는지 보여주는 개요 이미지입니다.

    Terraform State 파일 오류는 “지도”보다 “소유권 장부” 문제입니다

    Terraform state를 단순히 현재 인프라의 지도라고만 설명하면 절반만 맞습니다. 실무에서는 state를 Terraform이 어떤 실제 객체를 어느 리소스 주소로 관리하는지 기록한 소유권 장부로 보는 편이 더 정확합니다. 예를 들어 aws_instance.web이라는 주소가 실제 AWS 인스턴스 ID i-...에 묶여 있다면, Terraform은 그 주소를 기준으로 변경·삭제·재생성 판단을 합니다.

    문제는 이 장부가 코드와 자동으로 완벽히 동기화되지 않는다는 점입니다. Terraform은 .tf 파일, state, provider가 API로 읽어온 실제 리소스 정보를 비교해서 plan을 만듭니다. 그래서 “코드는 맞는데 plan이 이상하다”는 말은 충분히 가능합니다. 코드가 틀린 게 아니라 state가 다른 환경을 가리키거나, 실제 리소스가 콘솔에서 바뀌었거나, provider가 읽어온 값이 이전 실행과 달라졌을 수 있거든요.

    • Configuration: 우리가 원하는 선언입니다. .tf 파일, 변수, module 호출이 여기에 해당합니다.
    • State: Terraform이 이미 관리한다고 믿는 객체 목록과 속성입니다.
    • Real infrastructure: AWS, Azure, GCP, Kubernetes, vSphere 등에 실제로 존재하는 리소스입니다.
    • Provider: 실제 API를 조회하고 생성·수정·삭제를 수행하는 계층입니다. provider 버전 차이도 plan 결과를 바꿀 수 있습니다.

    제가 운영 환경에서 먼저 확인하는 건 코드가 아니라 내가 지금 올바른 backend와 workspace를 보고 있는지입니다. prod 작업이라고 믿고 있었는데 staging state를 보고 있으면, 이후의 모든 분석은 정교한 착각이 됩니다.

    흔한 Terraform State 파일 오류 유형과 근본 원인

    증상만 보고 바로 명령어를 치면 위험합니다. 같은 plan 이상이라도 원인이 drift인지, backend 오지정인지, 리팩터링 후 주소 변경인지에 따라 복구 방법이 달라집니다.

    오류 유형 대표 증상 근본 원인 먼저 볼 것 권장 대응
    State Lock Error acquiring the state lock 다른 Terraform 실행이 state 쓰기 권한을 잡았거나 이전 실행이 비정상 종료됨 CI 실행 상태, lock ID, 실행자 정보, backend lock 저장소 실행 중 작업을 확인한 뒤 고아 lock일 때만 force-unlock
    Drift 예상하지 못한 ~, -, -/+가 plan에 표시됨 콘솔 수동 변경, 외부 자동화, provider 기본값 변화 terraform plan -refresh-only, 클라우드 변경 이력 코드로 흡수할지, 실제 값을 되돌릴지 결정
    State와 실제 리소스 불일치 삭제된 리소스를 계속 추적하거나 기존 리소스를 새로 만들려 함 수동 삭제, import 누락, state rm 오남용, workspace 혼동 terraform state list, terraform state show, 실제 리소스 ID state rm, import, apply 중 선택
    Backend 설정 오류 init 실패, 전혀 다른 리소스가 plan에 표시됨 S3 key, workspace, profile, region, backend-config 불일치 .terraform/terraform.tfstate의 backend 메타정보, terraform workspace show terraform init -reconfigure 후 plan 재검증
    리팩터링 후 주소 변경 동일 리소스를 삭제 후 새로 만들려 함 resource 이름, module 경로, for_each key 변경 이전 주소와 새 주소, plan의 -/+ 여부 moved block 또는 terraform state mv

    Terraform 디버깅 루틴: apply 전에 보는 7개 체크포인트

    문제가 터졌을 때 저는 apply를 바로 다시 실행하지 않습니다. 첫 번째 실행이 실패한 이유를 모른 채 두 번째 실행을 하면 state가 더 헷갈려집니다. 아래 루틴은 로컬 backend, S3 backend, HCP Terraform/Terraform Enterprise 모두에서 큰 틀은 같습니다.

    1. Terraform 버전과 provider lock 파일을 확인합니다.
    2. 현재 workspace가 의도한 환경인지 확인합니다.
    3. backend가 어느 state 객체를 보고 있는지 확인합니다.
    4. state에 들어 있는 리소스 주소를 목록화합니다.
    5. 실제 리소스 조회와 refresh-only plan으로 drift를 분리합니다.
    6. 삭제 또는 재생성 액션이 있으면 영향 큰 리소스부터 읽습니다.
    7. state 변경 명령은 백업 또는 원격 backend 버전 복구 가능성을 확인한 뒤 실행합니다.
    # 0. 버전과 provider 잠금 파일 확인
    terraform version
    ls -la .terraform.lock.hcl
    
    # 1. 내가 보고 있는 workspace 확인
    terraform workspace show
    terraform workspace list
    
    # 2. backend 재초기화가 필요한 상황인지 확인
    terraform init -reconfigure
    
    # 3. state에 등록된 주소 확인
    terraform state list
    terraform state list 'module.network.*'
    
    # 4. 특정 리소스가 어떤 실제 ID에 연결되어 있는지 확인
    terraform state show aws_instance.web
    
    # 5. 실제 인프라를 읽어 state와의 차이만 확인
    terraform plan -refresh-only
    
    # 6. 일반 plan은 파일로 저장해서 리뷰 가능하게 남김
    terraform plan -out=tfplan
    terraform show tfplan

    terraform plan -refresh-only는 인프라를 바꾸겠다는 뜻이 아니라 실제 객체를 읽어서 state가 어떻게 갱신될지를 보여주는 모드입니다. 다만 terraform apply -refresh-only까지 실행하면 state가 실제 값에 맞게 업데이트될 수 있습니다. 운영에서는 plan과 apply의 차이를 분명히 나눠야 합니다. 조회만 하려면 plan -refresh-only에서 멈추고, state 동기화까지 의도한 경우에만 apply 단계로 갑니다.

    반대로 terraform plan -refresh=false는 실제 리소스 조회를 건너뜁니다. 빠를 수는 있지만 오래된 state를 기준으로 plan을 만들기 때문에 drift 디버깅에는 부적합합니다. 저는 대규모 환경에서 provider API 호출 비용이나 속도가 부담될 때 임시 비교용으로만 쓰고, 운영 적용 판단에는 거의 쓰지 않습니다.

    Terraform 디버깅 명령어로 state 상태를 점검하는 화면

    터미널에서 workspace, state list, refresh-only plan을 순서대로 확인하는 장면을 표현한 이미지입니다.

    IaC 상태 관리의 핵심: 원격 백엔드와 S3 key

    팀 작업에서는 로컬 state보다 원격 backend가 기본값에 가깝습니다. 로컬 파일은 간단하지만 동시 실행 제어, 접근 제어, 백업, 감사 추적이 약합니다. AWS 환경이라면 S3 backend를 많이 씁니다. 현재 Terraform S3 backend는 use_lockfile = true로 S3 기반 state locking을 사용할 수 있고, DynamoDB 기반 locking은 deprecated 상태라 신규 구성에서는 S3 lockfile을 우선 검토하는 편이 좋습니다.

    선택지 언제 적합한가 장점 주의점
    Local state 개인 실험, 폐기 가능한 샌드박스 구성이 단순하고 빠름 협업, 백업, lock, 접근 제어에 취약
    S3 backend + use_lockfile AWS에서 신규 원격 state를 단순하게 운영할 때 DynamoDB 테이블 없이 lock 구성 가능 Terraform 버전과 S3 lock 파일 권한을 함께 확인해야 함
    S3 backend + DynamoDB lock 기존 조직 표준이 이미 DynamoDB lock으로 굳어졌을 때 운영 사례가 많고 기존 자동화와 연동 쉬움 deprecated 방식이므로 마이그레이션 계획이 필요함
    HCP Terraform/Terraform Enterprise 정책, 승인, 실행 이력, 팀 권한을 한곳에서 관리할 때 협업 기능과 실행 관리가 강함 조직 계정·권한·네트워크 정책 설계가 필요
    terraform {
      backend "s3" {
        bucket       = "my-terraform-state-bucket"
        key          = "prod/network/terraform.tfstate"
        region       = "ap-northeast-2"
        encrypt      = true
        use_lockfile = true
      }
    }

    여기서 가장 자주 터지는 건 bucket보다 key입니다. 같은 bucket 안에 dev/network/terraform.tfstate, staging/network/terraform.tfstate, prod/network/terraform.tfstate를 넣는 구조는 흔합니다. 그래서 key 경로를 한 글자만 잘못 넣어도 전혀 다른 환경의 장부를 펼쳐놓고 작업하게 됩니다. 제 기준으로 prod backend는 코드 리뷰에서 bucket보다 key를 더 오래 봅니다.

    terraform init -reconfigure \
      -backend-config="bucket=my-terraform-state-bucket" \
      -backend-config="key=prod/network/terraform.tfstate" \
      -backend-config="region=ap-northeast-2" \
      -backend-config="encrypt=true" \
      -backend-config="use_lockfile=true"
    
    terraform init -reconfigure \
      -backend-config="bucket=my-terraform-state-bucket" \
      -backend-config="key=prod/network/terraform.tfstate" \
      -backend-config="region=ap-northeast-2" \
      -backend-config="dynamodb_table=terraform-locks" \
      -backend-config="encrypt=true"

    init -reconfigure는 현재 디렉터리의 backend 설정을 다시 읽게 합니다. state를 다른 위치로 옮기는 migration과는 다릅니다. Terraform이 state migration 여부를 묻는 상황에서는 메시지를 끝까지 읽어야 합니다. 운영 state를 잘못 옮기면 plan 이상보다 복구가 더 피곤해집니다.

    State Lock 해결: force-unlock은 마지막에 씁니다

    State Lock 해결을 검색하면 대부분 terraform force-unlock LOCK_ID가 먼저 보입니다. 하지만 이 명령은 lock을 푸는 도구이지, 현재 실행 중인 apply가 안전하게 끝났다는 증거가 아닙니다. 누군가 실제로 apply 중인데 강제로 풀면 두 개의 실행이 같은 state를 쓰려고 할 수 있습니다.

    ps aux | grep '[t]erraform'
    terraform workspace show
    terraform force-unlock LOCK_ID
    terraform force-unlock -force LOCK_ID

    제가 force-unlock을 허용하는 기준은 꽤 보수적입니다. 첫째, 현재 로컬·CI/CD·동료 작업 중 실행 중인 plan 또는 apply가 없어야 합니다. 둘째, lock 에러의 실행자·시간·operation 정보가 현재 살아 있는 작업과 맞지 않아야 합니다. 셋째, unlock 후 바로 apply하지 않고 plan부터 다시 봐야 합니다.

    상황 해야 할 일 하지 말아야 할 일
    CI job이 아직 실행 중 job 종료 또는 취소 결과를 기다림 lock ID가 보인다는 이유만으로 force-unlock
    노트북이 꺼져 apply가 중단됨 클라우드 리소스 생성 상태와 state 반영 여부를 확인 unlock 후 바로 apply 재시도
    오래된 고아 lock으로 확인됨 terraform force-unlock LOCK_ID 후 plan 검증 backend 저장소를 직접 수정하는 것으로 시작
    lock 저장소 권한 오류 S3 또는 DynamoDB 권한, profile, region을 확인 lock 기능을 꺼서 우회

    S3 lockfile을 쓴다면 lock 파일에 대한 s3:GetObject, s3:PutObject, s3:DeleteObject 권한을 확인해야 합니다. DynamoDB lock을 쓰는 기존 구성이라면 lock 테이블 권한과 region을 봐야 합니다. lock 문제를 Terraform 문제가 아니라 IAM 문제로 풀어야 하는 경우도 꽤 많습니다.

    State 불일치 복구: rm, import, mv를 섞어 쓰지 마세요

    Terraform State 파일 오류 중 가장 헷갈리는 구간입니다. state rm, import, state mv는 모두 state를 만지지만 목적이 다릅니다. 저는 이 셋을 “추적 끊기, 추적 시작하기, 주소 바꾸기”로 외웁니다. 이 구분만 잡아도 사고 확률이 확 줄더라고요.

    상황 사용 명령 의미 사용하면 안 되는 경우
    실제 리소스는 삭제됐는데 state에만 남음 terraform state rm Terraform의 추적만 제거 리소스를 실제로 삭제하려는 목적이면 부적합
    실제 리소스가 있는데 Terraform이 모름 terraform import 기존 객체를 state 주소에 연결 코드가 없거나 주소가 틀린 상태에서 성급히 실행
    리소스 이름·module 경로만 바뀜 terraform state mv 또는 moved block 같은 실제 객체를 새 Terraform 주소로 이동 실제 객체를 교체해야 하는 변경에는 부적합
    설정에서 더 이상 관리하지 않음 removed block 또는 state rm Terraform 관리 대상에서 제외 팀이 변경 이력을 코드로 남겨야 하는데 임시 명령만 실행
    terraform state list
    terraform state show aws_instance.web
    terraform state rm aws_instance.web
    terraform import aws_instance.web i-0123456789abcdef0
    terraform state mv aws_instance.web module.compute.aws_instance.web

    state rm은 실제 리소스를 삭제하지 않습니다. 이 사실은 단순하지만 사고를 많이 막아줍니다. 반대로 terraform destroy는 실제 리소스를 삭제할 수 있습니다. “state에서 빼고 싶다”와 “클라우드에서 없애고 싶다”는 완전히 다른 요구입니다.

    리팩터링이라면 가능하면 코드에 moved block을 남기는 방식을 선호합니다. 이유는 간단합니다. terraform state mv는 실행한 사람의 터미널 기록에만 맥락이 남지만, moved block은 저장소에 의도가 남습니다.

    moved {
      from = aws_instance.web
      to   = module.compute.aws_instance.web
    }
    Terraform State 파일 오류 복구를 위한 rm import mv 흐름도

    state에서 제거, 가져오기, 주소 이동이 각각 어떤 상황에 맞는지 정리한 흐름도 이미지입니다.

    재현 시나리오: 콘솔에서 삭제된 EC2를 다시 만들려는 경우

    가장 흔하고 교육용으로도 좋은 시나리오입니다. Terraform으로 EC2를 만들었는데 누군가 AWS 콘솔에서 직접 삭제했다고 가정하겠습니다. 이후 terraform plan을 실행하면 Terraform은 state에 남아 있는 인스턴스 ID를 기준으로 실제 객체를 조회합니다. provider는 “없다”고 답하고, Terraform은 설정 파일에 리소스가 여전히 있으니 다시 만들 계획을 세웁니다.

    1. Terraform으로 aws_instance.web를 생성합니다.
    2. AWS 콘솔 또는 외부 스크립트로 해당 인스턴스를 삭제합니다.
    3. terraform plan -refresh-only로 state와 현실의 차이를 봅니다.
    4. 그 인스턴스가 계속 필요한지, 이미 폐기한 리소스인지 결정합니다.
    5. 필요한 리소스면 terraform apply로 재생성을 검토하고, 폐기한 리소스면 코드와 state를 함께 정리합니다.
    terraform state show aws_instance.web
    terraform plan -refresh-only
    terraform plan -out=tfplan
    terraform show tfplan
    terraform apply tfplan
    terraform state rm aws_instance.web
    terraform plan

    여기서 자주 하는 실수는 state rm을 먼저 실행하는 겁니다. 설정 파일에 리소스 블록이 그대로 남아 있으면 다음 plan에서 Terraform은 “state에는 없지만 코드에는 있으니 새로 만들자”고 판단합니다. 그래서 정말 폐기하려면 코드 제거와 state 정리가 같이 가야 합니다. 필요한 리소스라면 반대로 state를 지우지 말고 Terraform이 재생성하도록 plan을 검토하는 편이 자연스럽습니다.

    plan 출력 해석: 기호보다 리소스 종류가 더 중요합니다

    Terraform plan의 기호는 기본 문법입니다. 하지만 운영 판단은 기호만으로 하지 않습니다. 같은 ~라도 태그 변경과 데이터베이스 엔진 옵션 변경은 무게가 다릅니다. 같은 -/+라도 무상태 인스턴스와 영구 디스크는 위험도가 다릅니다.

    • +: 새 리소스 생성입니다. 비용과 quota를 확인합니다.
    • ~: 기존 리소스 변경입니다. in-place 변경인지, provider가 어떤 필드를 바꾸는지 봅니다.
    • -: 리소스 삭제입니다. 운영에서는 승인 없이 진행하지 않습니다.
    • -/+: 삭제 후 재생성입니다. 네트워크, DB, 디스크, IAM, Kubernetes namespace에 보이면 멈춥니다.
    terraform plan -out=tfplan
    terraform show tfplan
    terraform show -json tfplan > tfplan.json
    jq '.resource_changes[] | select(.change.actions | index("delete")) | {address, actions: .change.actions}' tfplan.json

    저는 plan 리뷰 때 리소스를 세 그룹으로 나눕니다. 첫째, 재생성되면 장애가 될 수 있는 리소스입니다. VPC, subnet, route table, DB, disk, IAM role, cluster 같은 것들입니다. 둘째, 비용이 바로 붙는 리소스입니다. 인스턴스, NAT gateway, load balancer, managed database가 여기에 들어갑니다. 셋째, 변경되어도 영향이 제한적인 메타데이터입니다. 태그나 설명이 대표적입니다. 이 분류를 해두면 plan 리뷰가 감상이 아니라 판단이 됩니다.

    Terraform plan 결과로 State Lock 해결과 변경 위험을 해석하는 대시보드

    생성, 변경, 삭제, 재생성 항목을 색상별로 구분해 보여주는 Terraform plan 결과 해석 이미지입니다.

    성능·비용·안정성에 영향을 주는 결정 포인트

    State 디버깅은 단순 복구 작업처럼 보이지만, backend 설계와 운영 습관은 비용과 안정성에 영향을 줍니다. 숫자를 지어낼 필요는 없습니다. 어떤 결정이 어떤 방향의 비용을 만드는지만 알아도 충분히 실수를 줄일 수 있습니다.

    결정 안정성 영향 비용·성능 영향 추천 기준
    state를 환경별로 분리할지 여부 장애 범위를 줄임 state 수가 늘어 관리 포인트 증가 prod, staging, dev는 최소한 key 또는 workspace로 분리
    하나의 거대한 state 사용 한 번의 plan 영향 범위가 커짐 provider 조회가 많아져 plan이 느려질 수 있음 네트워크, 플랫폼, 앱 계층을 무리 없이 나눔
    -refresh=false 사용 drift를 놓칠 수 있음 조회가 줄어 빨라질 수 있음 운영 apply 판단에는 사용하지 않음
    state lock 비활성화 동시 apply 충돌 위험 증가 구성은 단순해짐 팀 환경에서는 lock 없는 운영을 피함
    원격 state 암호화·버전 관리 복구와 보안에 유리 스토리지 정책 관리 필요 민감 값 가능성을 전제로 암호화와 접근 제어 적용

    특히 state를 너무 크게 키우는 패턴은 나중에 발목을 잡습니다. 모든 리소스를 하나의 root module과 하나의 state에 넣으면 처음엔 편합니다. 하지만 plan이 느려지고, 작은 변경도 큰 영향 범위를 갖고, lock 대기 시간이 길어집니다. 그렇다고 너무 잘게 쪼개면 remote state 참조와 의존성 관리가 늘어납니다. 저는 “같이 생성되고 같이 롤백되어도 괜찮은 단위”를 state 분리 기준으로 잡습니다.

    자주 묻는 질문: Terraform State 파일 오류 FAQ

    Q1. terraform.tfstate 파일을 직접 수정해도 되나요?

    가능은 하지만 운영에서는 거의 마지막 수단입니다. JSON이라 열어볼 수는 있어도 Terraform 내부 구조, provider schema, 민감 값 처리, serial 값이 얽혀 있습니다. 먼저 terraform state 하위 명령을 쓰고, 원격 backend라면 버전 복구 가능성을 확인한 뒤 진행하세요.

    Q2. state 파일을 Git에 올려도 되나요?

    일반적으로 올리지 않는 편이 맞습니다. state에는 리소스 속성뿐 아니라 민감한 값이 평문에 가까운 형태로 남을 수 있습니다. 팀 환경에서는 원격 backend, 암호화, 접근 제어, 감사 가능한 실행 경로를 쓰는 쪽이 안전합니다.

    Q3. lock 오류가 나면 무조건 force-unlock 하면 되나요?

    아닙니다. lock은 귀찮은 장벽이 아니라 state 동시 수정을 막는 안전장치입니다. 실행 중인 작업이 없고 고아 lock이라고 판단될 때만 terraform force-unlock LOCK_ID를 사용하세요.

    Q4. import만 하면 코드도 자동으로 완성되나요?

    terraform import는 기존 리소스를 state에 연결하는 명령입니다. 코드 작성과 속성 정리는 별도 작업으로 보는 편이 안전합니다. import 후에는 반드시 terraform plan으로 코드와 실제 리소스 차이를 맞춰야 합니다.

    Q5. 리소스 이름만 바꿨는데 왜 삭제 후 생성이 뜨나요?

    Terraform 주소가 바뀌었기 때문입니다. aws_instance.web를 aws_instance.app으로 바꾸면 Terraform은 기본적으로 다른 리소스로 봅니다. 같은 실제 객체를 유지하려면 moved block이나 terraform state mv로 주소 이동을 알려줘야 합니다.

    운영에서 바로 쓰는 판단 기준

    Terraform State 파일 오류를 만나면 명령어보다 순서가 중요합니다. 먼저 workspace와 backend를 확인합니다. 그다음 state list, state show, plan -refresh-only로 state와 현실의 차이를 분리합니다. lock 에러라면 실행 중인 작업이 있는지 확인한 뒤 고아 lock일 때만 해제합니다.

    이럴 땐 이렇게 하시면 됩니다. 콘솔에서 지운 리소스를 Terraform이 다시 만들려 한다면, 계속 필요한 리소스인지 먼저 결정하세요. 필요하면 plan 검토 후 apply, 필요 없으면 코드 제거와 state 정리를 같이 합니다. 이름이나 module 경로만 바꿨다면 삭제·재생성을 허용하지 말고 moved block 또는 state mv를 씁니다. lock이 걸렸다면 Terraform이 나를 괴롭히는 게 아니라 state를 보호하는 중이라고 보고, 실행 중인 작업부터 찾습니다.

    제가 운영에서 절대 넘기지 않는 신호는 -와 -/+입니다. 특히 네트워크, 데이터베이스, 디스크, IAM, 클러스터 리소스에 보이면 손을 멈추고 이유를 설명할 수 있어야 합니다. 설명할 수 없는 apply는 복구 계획이 없는 변경과 비슷합니다.

    정확한 옵션과 backend 동작은 HashiCorp의 Terraform CLI 문서, S3 backend 문서, state 명령 문서를 기준으로 확인하는 습관을 권합니다. 문서는 명령 문법을 확인하는 곳이고, 운영 판단은 현재 state와 실제 인프라를 놓고 해야 합니다. 이 둘을 분리해서 보면 Terraform state 문제는 훨씬 덜 무섭습니다.