Terraform, 작은 데이터팀이 살아남는 법

작은 데이터팀에서 Terraform을 도입하며 겪은 시행착오와 구조 설계 경험을 공유합니다. Terraform Cloud 환경에서 실수를 줄이고 유지보수성을 높이기 위한 선택 기준도 담았습니다.

도입 계기

보통 Terraform(테라폼)은 SRE팀이나 DevOps팀에서 많이 사용한다고 알고 있지만 사실 데이터팀에서도 많이 사용된다. 그 이유는 간단하다. 데이터팀도 수많은 플랫폼을 직접 구축 및 운영하기 때문이다. 우리 회사도 마찬가지였다. 다만 다른 팀과 다르게 2명이서 이 모든 인프라를 어깨에 매고 운영해야 한다는 점만 달랐다.

이전에는 AWS 웹 콘솔에서 모든 리소스를 생성 및 유지보수를 했는데 이는 많은 문제들을 야기했다.

  • 팀원이 2명밖에 없고 담당자 교체 시 인수인계가 어려움
  • 특정 리소스가 어떤 서비스에서 사용되는지 파악이 어려움
  • 인프라 구조 자체를 누가 어떻게 만들었는지 기억이 안 남
  • 장애 시 빠르게 재현하거나 복구하는 데 어려움
  • 사용 중인 리소스 vs 미사용 리소스 구분 불가
  • 전체 구성 현황이 흩어져 있고 가시성이 없음

위 문제들을 해결하고자 2023년 테라폼 도입을 추진했다.

기존 구조의 문제점

2023년 도입 이후 2024년 한 해동안 로드밸런서, 배포서버, spark 클러스터 등 큰 리소스들은 테라폼으로 구성 및 유지보수를 진행했다. 그 과정을 통해 몇 가지 중요한 깨달음을 얻었다.

  • 공통 리소스를 한데 묶는 것이 좋은 것은 아니었다.

공통 리소스를 elb라는 폴더 안에 ALB, NLB 등 여러 개 정의해두었더니, 일부 설정만 바꿔도 전체 리소스가 plan에 잡혀버리는 문제가 있었다. 이는 변경 범위를 좁히기 어렵게 만들고, 의도치 않은 리소스까지 apply에 포함되어 운영 리스크가 되었다. 작은 팀에서는 리소스의 기술적 종류보다 서비스 단위로 코드를 나누는 것이 더 안전하고 실용적이라는 걸 깨달았다.

  • 재사용성을 고려하다 보니 모듈이 덩치만 커졌다.

처음에는 재사용성을 높이겠다는 의도로 여러 리소스를 조합한 복합적인 모듈을 만들었다. 예를 들어 EC2 인스턴스와 EBS 볼륨, IAM Role까지 한 번에 생성하는 ec2_bundle 모듈을 만들어 두었는데, 이후 다른 환경에서 EC2만 단독으로 사용하고 싶을 때 해당 모듈을 재사용할 수 없었다. 결국 재사용을 목표로 만든 모듈이 다른 사용 시나리오에서는 발목을 잡는 구조가 되어버린 것이다. 모듈은 처음부터 최소 단위로 분리해놓고 조합은 사용하는 쪽에서 하는 게 확장성과 유지보수 측면에서 더 낫다는 교훈을 얻었다.

  • 과도한 추상화는 코드 이해도와 예측 가능성을 낮춘다.

for_each, merge, dynamic 등 고급 기능으로 여러 리소스를 하나의 모듈로 다루는 방식은 처음엔 코드가 짧고 DRY하다는 장점이 있었지만, 조건 분기나 키 누락으로 인한 type mismatch, null 참조 오류가 자주 발생했다. 코드는 짧고 모듈화되어 있어 보였지만, 결과적으로 구조 파악도 어렵고 plan 실패도 자주 나는 블랙박스 코드가 되었다. 작은 팀에선 오히려 반복되더라도 명시적으로 작성된 코드가 훨씬 안전했다.

테라폼도 결국은 사람을 위한 도구이다. 사람이 이해하지 못하는 코드는 곧 장애가 되고, 또 다른 유지보수 대상이 된다.

설계 시 가장 중요했던 점

위 문제점들을 바탕으로 꼭 가져가야겠다 싶었던 가치는 아래 3가지였다.

  • 사용성과 직관성: 누구나 보고 바로 이해할 수 있어야 한다.
  • 유지보수 용이성: 장애 시 빠르게 원인 파악 및 수정이 가능해야 한다.
  • Terraform Cloud 활용: 환경 별 디렉토리/구조가 충돌 없이 작동해야 한다.

결국 테라폼은 사람코드인프라를 관리하는 것이기 때문에 중복코드 제거나 자동화에 집착하기 보다는 안정성에 무게를 두어야 한다는 교훈을 얻은 것이다.

고민했던 부분들

작은 팀이기 때문에 더욱 구조를 명확히 하고, 실수를 줄일 수 있는 방법을 선택해야 했다. 실제로 아래와 같은 고민을 했고 각 항목마다 선택지를 비교한 후 기준을 세워나갔다.

환경 분리 전략

  • 문제: dev/prd 환경을 어떻게 나눌 것인가?
  • 후보:
    • .tfvars 기반 분리: 변수만 다르게 관리하되 디렉토리는 공유
    • 브랜치 기반 분리: Git 브랜치에 따라 분기
    • 폴더 기반 분리: dev/, prd/ 디렉토리 분리
  • 선택: 폴더 기반 분리
  • 이유: Terraform Cloud에서 .tfvars, 브랜치 기반은 환경이 명확하지 않았고 실수 위험이 컸다. 폴더 구조는 가독성과 명확성이 더 좋아 실수를 방지할 수 있다고 판단했다.

디렉토리 구조 설계

  • 문제: 리소스를 어떻게 구조화할 것인가?
  • 후보:
    • module과 env 모두 리소스 단위로 분리
    • module은 리소스, env는 block 단위로 분리
    • module은 리소스, env는 service/shared 형태로 구분
  • 선택: modules/는 리소스 단위, 환경 디렉토리는 service/, shared/로 나누는 구조
  • 이유: 서비스별 리소스를 관리하면서도 공통 리소스(ALB, S3 등)는 shared/에 두어 재사용 가능하게 구성할 수 있었다. 또한 CI/CD 흐름에서도 서비스 단위로 나뉘는 구조가 명확했다.

모듈 재사용 전략

  • 문제: 복합 모듈로 구성할 것인가?
  • 후보:
    • 여러 리소스를 하나의 모듈로 묶은 복합 모듈
    • 기능 단위로 모듈을 나누고 조합은 사용하는 쪽에서 처리
  • 선택: 기능 단위로 모듈 분리
  • 이유: 복합 모듈은 예외 상황에 대응이 어렵고 다른 서비스에서 재활용하기 힘들었다. 기능 단위로 분리한 뒤 조합하는 방식이 훨씬 유연했다.

네이밍 컨벤션

  • 문제: 리소스마다 어떤 이름 규칙을 따를 것인가?
  • 후보:
    • 자유롭게 작성, tag만 통일
    • 기본 컨벤션 + 예외는 자유롭게
    • 예외 없이 일관된 네이밍 컨벤션 적용
  • 선택: 예외 없이 일관된 네이밍 컨벤션 적용
  • 이유: 일관된 네이밍은 시각적으로 리소스를 빠르게 식별할 수 있게 해준다. 또한 tag로만 구분하는 방식보다 AWS 콘솔, CloudWatch, Billing 등에서 리소스 필터링이 훨씬 용이했다.

추상화 기준

  • 문제: 반복되는 코드를 얼마나 추상화할 것인가?
  • 후보:
    • for_each, dynamic 적극 활용해 반복 최소화
    • 명시적으로 나열해서 가독성과 디버깅 우선
  • 선택: 명시적 작성 + 최소한의 반복만 허용
  • 이유: 추상화된 코드는 코드 길이는 줄였지만 plan 오류와 디버깅 난이도를 높였다. 명시적으로 작성한 쪽이 안정성과 예측 가능성이 훨씬 높았다.

Terraform Cloud 워크플로우 설계

  • 문제: 변경 범위를 어떻게 명확하게 제어할 것인가?
  • 후보:
    • 하나의 workspace에서 모든 리소스를 관리
    • 서비스 단위로 workspace 분리
  • 선택: 서비스 단위 workspace 분리
  • 이유: Git 기반 CI/CD 환경에서 서비스별 workspace 분리는 변경 범위를 명확히 구분하고, 자동 plan을 통해 영향도를 사전에 검토할 수 있어 실수 방지에 효과적이었다.

결론: 작은 팀이라 더 중요했던 선택들

지금까지 이야기 했던 내용을 정리하면 아래와 같다.

  • 작은 팀일수록 구조의 단순함과 명확성이 생존 조건이다.
  • Terraform은 너무 추상화하거나 DRY에 집착하면 되려 복잡해지고 디버깅이 어려워진다.
  • 브랜치 기반보다 폴더 기반 환경 분리가 실무에서 훨씬 안정적이었다.
  • Terraform Cloud는 편리하지만 그만큼 코드 구조가 명확하지 않으면 큰 리스크가 된다.

결국 테라폼 실전에서 중요한 건 가독성, 직관성, 복구 가능성이었다. 작은 규모의 팀에게는 멋진 테라폼 코드보다는 이해하기 쉬운 구조가 필요하다.


Terraform, 작은 데이터팀이 살아남는 법
https://dev-bearabbit.github.io/ko/Terraform/terraform-0/
Author
Jess
Posted on
2025년 4월 20일
Licensed under