[설계가이드] Terraform 모듈 설계, 원칙 없이 만들면 반드시 무너진다

Tech Story/etc.

[설계가이드] Terraform 모듈 설계, 원칙 없이 만들면 반드시 무너진다

 

 
[ kt cloud Azure전환팀 변세림 님 ]

📋 요약

이 글에서는 Terraform 모듈 설계 원칙과 표준 구조, 실무 적용 기준을 다룹니다.

안정적인 인프라 운영을 위해 모듈 복잡도와 변경 위험을 줄이는 방향을 정리합니다.

#Terraform #IaC #Terraform모듈 #HashiCorp #인프라자동화


[설계가이드] Terraform 모듈 설계, 원칙 없이 만들면 반드시 무너진다

안녕하세요. 🙋

1부에서 IaC의 본질을 살펴봤는데요, 이번에는 조금 더 실전적인 이야기를 해볼게요.

Terraform을 쓰다 보면 어느 순간 꼭 이런 상황이 생겨요.

"처음엔 그냥 리소스 파일을 하나씩 만들었는데, 어느 순간 코드가 뒤엉켜서 뭐가 뭔지 모르게 됐다."
"모듈을 만들긴 했는데... 팀원이 어떻게 쓰는지 모른다."
"모듈 하나 고쳤더니 왜 다른 환경이 망가졌지?"

 

이런 문제들은 Terraform을 잘못 쓴 게 아니에요. 모듈 설계 원칙 없이 만들어진 코드가 쌓인 거예요. 🎯

본격적인 모듈 설계 이야기 전에, 먼저 "왜 IaC 도구 중에서 Terraform인가?"를 짚고 넘어갈게요.


1. 왜 Terraform인가?

IaC 도구는 Terraform 외에도 다양해요. AWS CloudFormation, Azure Bicep, Ansible, Pulumi 등 선택지가 많죠. 그런데 왜 많은 팀들이 Terraform을 선택할까요?

① 클라우드에 종속되지 않는다 (Cloud-Agnostic)

CloudFormation은 AWS 전용, Bicep은 Azure 전용이에요. 반면 Terraform은 AWS, Azure, GCP, Kubernetes 등 1,000개 이상의 Provider를 지원하는 클라우드 중립적인 도구예요.

 

멀티 클라우드 환경이 보편화된 지금, 하나의 도구로 여러 클라우드를 동일한 워크플로우로 관리할 수 있다는 건 큰 장점이에요.

💡 실무 관점
오늘은 Azure만 쓰더라도, 내일 다른 클라우드가 추가될 가능성은 항상 있어요. Terraform을 쓰면 도구를 바꾸지 않고 Provider만 추가하면 돼요.

② 선언형 언어로 직관적이다 (Declarative)

Terraform은 HCL(HashiCorp Configuration Language)이라는 선언형 언어를 써요. "어떻게 만들지"가 아니라 "어떤 상태가 되어야 하는지"만 기술하면, Terraform이 알아서 현재 상태와 비교해서 필요한 작업을 수행해요.

 

예를 들어 VM 하나를 만들 때 "이 VM은 이런 스펙으로 존재해야 한다"고 선언만 하면, Terraform이 현재 상태와 비교해서 필요한 작업을 알아서 수행해줘요. 절차를 일일이 쓸 필요가 없는 거죠.

③ 거대한 커뮤니티와 생태계

Terraform은 전 세계 수만 개의 조직에서 사용하는 사실상의 IaC 표준이에요. 공식 문서, 커뮤니티 모듈, 레퍼런스 아키텍처가 풍부해서 막히는 상황에서 해결책을 찾기가 쉬워요.

도구 클라우드 지원 언어 특징
Terraform
멀티 클라우드
HCL (선언형)
클라우드 중립, 대규모 커뮤니티
CloudFormation
AWS 전용
YAML/JSON
AWS 네이티브 통합
Bicep
Azure 전용
DSL
ARM 템플릿 대체
Ansible
멀티 클라우드
YAML (절차형)
설정 관리에 강점
Pulumi
멀티 클라우드
범용 언어(Python 등)
개발자 친화적

 


2. 좋은 모듈의 3가지 설계 원칙

이제 본론으로 들어가볼게요. HashiCorp 공식 가이드는 모듈을 설계할 때 반드시 고려해야 할 세 가지 축을 제시해요.

① 캡슐화 (Encapsulation): 항상 함께 배포되는 것만 묶어라

모듈에 너무 많은 리소스를 넣으면 쓰기는 편하지만, 모듈의 목적과 요구사항이 무엇인지 이해하기 어려워져요.

💡 기준은 이거예요

"이 리소스들은 항상 함께 배포되는가?" → Yes면 같은 모듈, No면 분리

 

예를 들어 네트워크 모듈이 VNet, 서브넷, NSG를 함께 만드는 건 자연스러워요. 이것들은 항상 같이 필요하거든요. 하지만 같은 모듈이 애플리케이션 서버까지 만들기 시작하면, 모듈의 목적이 흐려지고 나중에 분리하기가 굉장히 힘들어지죠.

② 권한 경계 (Privileges): 권한이 다른 리소스는 분리하라

모듈 안에 서로 다른 팀이 관리하는 리소스가 섞이면 권한 분리 원칙이 깨질 수 있어요.

💡 실무 예시

네트워크 팀이 관리하는 VNet 설정과 개발팀이 관리하는 VM을 같은 모듈에 넣으면, 개발팀이 의도치 않게 네트워크 설정을 건드릴 수 있어요. 권한 경계에 맞게 모듈을 나누면 이런 사고를 구조적으로 막을 수 있어요.

③ 변동성 (Volatility): 자주 바뀌는 것과 안 바뀌는 것을 분리하라

수명이 긴 인프라와 짧은 인프라를 같은 모듈에 묶으면 안 돼요.

낮은 변동성 (분리 권장) 높은 변동성 (분리 권장)
VNet, 서브넷 등 네트워크 애플리케이션 서버
데이터베이스 오토스케일링 설정
Key Vault, IAM 정책 배포 관련 설정

💡 왜 분리해야 할까요?

애플리케이션 서버는 하루에도 수십 번 배포될 수 있어요. 이걸 DB와 같은 모듈에 넣으면, 서버 배포할 때마다 DB 설정에 불필요한 변경 위험이 생기거든요. 안 바뀌어도 될 인프라를 괜히 건드리는 셈이죠.


3. 표준 모듈 구조 (Standard Module Structure)

HashiCorp가 권장하는 모듈의 표준 파일/디렉토리 구조예요. 이 구조를 따르면 Terraform 툴링이 자동으로 문서를 생성하고 모듈 레지스트리에 인덱싱하는 등 여러 기능을 활용할 수 있어요.

 

terraform-module-name/
├── main.tf          # 핵심 리소스 정의 (필수)
├── variables.tf     # 입력 변수 정의
├── outputs.tf       # 출력값 정의
├── README.md        # 모듈 설명 문서
├── modules/         # 중첩 모듈 (선택)
│   └── sub-module/
└── examples/        # 사용 예시 (선택)
    └── basic/

유일한 필수 요소는 루트 디렉토리의 .tf 파일이에요. 나머지는 모듈이 성숙해지면서 점진적으로 추가하면 돼요.

🔍 [한 단계 더 들어가 보기] README는 왜 중요한가요?

HashiCorp 공식 가이드는 루트 모듈과 모든 중첩 모듈에 README를 작성할 것을 권장해요.

변수나 출력값 목록은 terraform-docs 같은 툴이 .tf 파일을 읽어서 자동으로 생성해줘요. README에 꼭 담아야 할 것은 "이 모듈이 무엇을 만드는가", "언제 써야 하는가", 그리고 "실제 사용 예시"예요. 이것만 있어도 팀원이 물어보는 횟수가 확 줄어들어요.


4. MVP 원칙: 처음엔 작게 시작하라

HashiCorp는 모듈을 처음 만들 때 MVP(Minimum Viable Product) 접근을 강조해요. 처음부터 완벽한 모듈을 만들려다가 결국 아무것도 못 만드는 것보다, 작게 시작해서 점진적으로 발전시키는 게 낫거든요.

 

MVP 모듈 설계 원칙 4가지

  1. 80% 룰 — 80%의 사용 사례에서 작동하는 모듈을 목표로 해요. 모든 케이스를 커버하려다가 복잡해지는 게 더 나빠요.
  2. 엣지 케이스 금지 — 드물게 일어나는 예외 상황은 모듈에 넣지 마세요. 모듈은 재사용 가능한 블록이어야 해요.
  3. 조건문 최소화 — MVP 단계에서 복잡한 조건 분기는 모듈의 범위를 흐리게 해요.
  4. 변수는 꼭 필요한 것만 — 자주 바꿀 것 같은 변수만 노출하고, 나머지는 기본값으로 숨겨두세요.

💡 실무 팁

"이 변수, 나중에 누군가 바꾸고 싶어할까?"를 기준으로 변수를 정해요. 그렇지 않다면 locals로 처리하는 게 모듈을 훨씬 깔끔하게 유지시켜 줘요.


5. Output은 아낌없이 내보내라

HashiCorp 가이드에서 특히 강조하는 내용이에요. 지금 당장 쓸 곳이 없더라도, 모듈에서 나올 수 있는 정보는 최대한 output으로 내보내야 해요.

 

실무에서 모듈은 혼자 쓰이지 않거든요. 네트워크 모듈의 output이 컴퓨팅 모듈의 input이 되고, 컴퓨팅 모듈의 output이 보안 모듈의 input이 되는 식으로 연결돼요.

 

예를 들어 네트워크 모듈을 만들 때 network ID 하나만 output으로 내보내면, 나중에 다른 모듈에서 network 이름이나 subnet ID가 필요할 때 참조할 방법이 없어요. ID뿐 아니라 name, subnet ID, CIDR 등 해당 리소스에서 나올 수 있는 정보는 최대한 함께 내보내두는 게 좋아요.


6. 모듈 설계 원칙 요약

원칙 핵심 질문 잘못된 예 올바른 예
캡슐화
항상 함께 배포되는가?
네트워크 + 앱 서버를 한 모듈에
네트워크 모듈 / 앱 모듈 분리
권한 경계
같은 팀이 관리하는가?
네트워크팀 + 개발팀 리소스 혼재
담당 팀별로 모듈 분리
변동성
변경 빈도가 같은가?
DB + 앱 서버를 한 모듈에
정적 인프라 / 동적 인프라 분리
MVP
80%의 케이스를 커버하는가?
처음부터 모든 옵션 변수화
꼭 필요한 변수만 노출
Output
충분히 내보내고 있는가?
ID만 output
이름, ID, 속성 모두 output

마무리

[설계가이드] Terraform 모듈 설계, 원칙 없이 만들면 반드시 무너진다

지금까지 살펴본 Terraform 모듈 설계 원칙, kt cloud 환경에서 직접 적용해보고 싶으신가요? 3부에서는 kt cloud 인프라의 기반이 되는 OpenStack Provider를 활용한 구성 방법과 함께, 팀이 함께 안전하게 모듈을 관리하는 버전 관리 전략까지 소개해 드릴게요. 기대해 주세요! ✨

kt cloud 플랫폼 바로가기

❓ 자주 묻는 질문 (FAQ)

Q. Terraform 말고 Azure Bicep을 써도 되지 않나요?
A. Azure 환경만 사용한다면 Bicep도 충분히 좋은 선택이에요. Azure 네이티브 기능과의 통합이 더 빠르고 긴밀하거든요. 다만 멀티 클라우드 환경이거나 팀이 이미 Terraform 경험이 있다면, 하나의 도구로 통일하는 것이 운영 효율 면에서 유리해요.
Q. 모듈 하나가 너무 작아지는 것 같아요. 어느 정도 크기가 적당한가요?
A. HashiCorp는 "모듈의 기능이나 목적을 설명하기 어렵다면 너무 복잡한 것"이라고 말해요. 딱 한 문장으로 "이 모듈은 ○○을 만든다"고 설명할 수 있는 크기가 적당해요.
Q. 변수를 얼마나 많이 노출해야 할까요?
A. MVP 단계에서는 "자주 바꿔야 할 것 같은 값"만 변수로 노출하는 걸 권장해요. 나머지는 locals나 기본값으로 처리하세요. 변수가 많을수록 모듈을 쓰는 사람의 부담도 커지거든요.

📚 관련/출처