한 줄 정의
함께 정의되고 변경되는 인프라 리소스를 스택 이라는 단위로 묶어 코드로 프로비저닝·업데이트하며, 이 스택의 크기와 경계를 어떻게 정하느냐가 인프라 설계의 핵심 결정입니다.
쉽게 말하면
이사할 때 짐을 상자에 나눠 담는 문제입니다. 상자 하나가 곧 스택입니다.
집 전체 짐을 거대한 상자 하나에 담으면(모놀리식) 뭘 하나 꺼내려 해도 상자 전체를 들어야 하고, 떨어뜨리면 안의 짐이 전부 깨집니다. 이 “떨어뜨렸을 때 깨지는 범위”가 폭발 반경 입니다.
반대로 숟가락 하나마다 상자를 따로 쓰면(마이크로) 상자 하나하나는 가볍지만, 상자가 수십 개라 짝을 맞추고 조립하는 일이 새로운 일거리가 됩니다.
그래서 이사의 요령은 “같이 쓰는 물건끼리, 같은 방 물건끼리” 담는 것입니다. 스택도 같습니다 — 함께 변경되는 리소스끼리 한 스택에 담고, 변경 주기가 다른 것(자주 갈아치우는 서버 vs 계속 보관할 데이터)은 상자를 나눕니다. 이 장의 패턴들은 결국 상자 크기에 대한 선택지입니다.
왜 중요한가?
인프라 스택은 자동화된 인프라의 기본 구성 요소 입니다. 인프라 플랫폼이 제공하는 리소스를 코드로 정의한다고 할 때, 실제로 프로비저닝·변경이 일어나는 단위가 바로 스택입니다.
문제는 인프라 설계에서 정말 어려운 지점이 스택의 크기와 구조를 정하는 것 이라는 점입니다. 스택 하나로 전체 시스템을 관리할 수도 있지만, 시스템이 커질수록 변경이 느리고 위험해집니다. 변경이 무서워지면 변경 빈도를 줄이고 한 번에 몰아서 바꾸게 되는데, 이것이 더 높은 수준의 기술 부채로 이어집니다.
핵심 내용
스택 = 코드 + 도구 + 인스턴스
스택 도구는 스택 소스 코드를 읽고, 클라우드 플랫폼 API를 호출해 코드에 정의된 구성 요소를 조합하여 스택 인스턴스를 프로비저닝합니다.
flowchart LR code["스택 코드<br/>(.tf 파일, 템플릿)"] --> tool["스택 도구<br/>(Terraform 등)"] tool -->|"플랫폼 API 호출"| instance["스택 인스턴스<br/>(VM·볼륨·서브넷 모음)"]
| 구성 요소 | 내용 |
|---|---|
| 스택 코드 | 인프라 구성 요소를 선언하는 소스 코드. Terraform .tf 파일, CloudFormation 템플릿 |
| 스택 도구 | Terraform, CloudFormation, Azure Resource Manager, Google Cloud Deployment Manager, OpenStack Heat, Pulumi, Bosh |
| 스택 인스턴스 | 코드로부터 실제 프로비저닝된 리소스 모음. 프로젝트 하나로 여러 인스턴스를 만들 수 있음 |
스택 도구를 실행하면 플랫폼 API로 인스턴스 상태를 확인하고 코드와 비교합니다. 이 과정을 코드를 인스턴스에 적용(applying) 한다고 표현합니다.
| 인스턴스 상태 | 도구의 동작 |
|---|---|
| 없음 | 새로 생성 |
| 코드와 불일치 | 일치하도록 수정 |
| 코드와 일치 | 그대로 유지 |
'스택'이라는 용어
대부분의 도구는 자신을 스택 관리 도구라고 부르지 않고 저마다 다른 용어를 씁니다. 이 개념에 대한 업계 합의가 아직 없어, 책에서는 스택이라는 단어로 통칭합니다.
스택 코드와 서버 코드는 분리한다
완전한 컨테이너 기반이나 서버리스가 아닌 시스템의 인프라 코드베이스에는 서버 프로비저닝·구성 코드가 많고, 컨테이너 기반 시스템조차 호스트 서버는 필요합니다.
이때 스택을 빌드하는 코드와 서버를 빌드하는 코드를 분리해야 코드를 이해하기 쉽고, 변경이 단순해지고, 서버 코드를 재사용·테스트할 수 있습니다. 스택 코드는 서버 구성 도구를 호출 하여 생성할 서버와 실행 환경 정보만 전달합니다.
virtual_machine:
name: appserver-waterworks-${environment}
source_image: shopspinner-base-appserver
memory: 4GB
provision:
tool: servermaker
parameters:
maker_server: maker.shopspinner.xyz
role: appserver
environment: ${environment}스택 코드는 서버 이미지와 스펙만 선언하고, 구성의 실제 내용은 role 파라미터로 서버 구성 도구(Servermaker)에 위임합니다.
하위 레벨 vs 상위 레벨 인프라 언어
많이 쓰이는 스택 도구 언어는 대부분 하위 레벨 인프라 언어 로, 플랫폼이 제공하는 리소스를 코드에 직접 노출합니다. 주소 블록, VLAN, 게이트웨이, 라우팅까지 전부 손으로 연결해야 합니다.
address_block:
name: application_network_tier
address_range: 10.1.0.0/24
vlans:
- appserver_vlan_A:
address_range: 10.1.0.0/16
virtual_machine:
name: shopspinner_appserver_A
vlan: application_network_tier.appserver_vlan_A
gateway:
name: public_internet_gateway
address_block: application_network_tier
inbound_route:
gateway: public_internet_gateway
public_ip: 192.168.99.99
incoming_port: 443
destination:
virtual_machine: shopspinner_appserver_A
port: 8443상위 레벨 인프라 언어 는 플랫폼 리소스에 직접 매핑되지 않는 항목을 정의합니다. 위와 같은 인프라가 단 두 줄로 선언됩니다.
application_server:
public_ip: 192.168.99.99이 코드를 적용하면 네트워크·서버 리소스가 프로비저닝되거나 기존 리소스가 검색되고, 포트·VLAN 값과 서버 구축 방법은 도구와 라이브러리가 결정합니다. PaaS의 배포 디스크립터가 이 수준의 추상화이며, 직접 라이브러리·모듈을 작성해 고유한 추상화 계층을 만들 수도 있습니다.
폭발 반경 — 스택 크기를 정하는 기준
큰 스택 변경이 작은 스택 변경보다 위험한 이유는 폭발 반경(blast radius), 즉 변경이 영향을 미치는 범위가 크기 때문입니다.
폭발 반경
폭발 반경은 변경이 적용되는 명령에 포함되는 코드 범위입니다.
terraform apply를 실행하면 프로젝트의 모든 코드가 직접 폭발 반경에 들어갑니다. 그 리소스에 의존하는 시스템 요소들은 간접 폭발 반경으로, 직접 반경의 리소스 파괴에 영향을 받을 수 있습니다.
스택이 클수록 프로비저닝·변경에 시간이 오래 걸리고, 실패 시 문제가 커집니다. 그래서 사람들이 변경을 기피하게 되고, 이것이 기술 부채를 키웁니다.
스택 구조화 패턴
스택 경계를 어디에 긋느냐에 따라 하나의 스펙트럼이 만들어집니다.
flowchart LR mono["모놀리식 스택<br/>시스템 전체 = 스택 1개"] --> group["애플리케이션 그룹 스택<br/>여러 서비스 = 스택 1개"] --> service["서비스 스택<br/>서비스 1개 = 스택 1개"] --> micro["마이크로 스택<br/>서비스 1개 = 스택 여러 개"]
안티패턴 — 모놀리식 스택
매우 많은 구성 요소가 하나의 스택에 들어간 형태입니다. 새 구성 요소를 기존 프로젝트에 추가하는 것이 가장 간단하기 때문에 자연스럽게 만들어집니다. 새 스택을 만들면 오케스트레이션·통합·테스트가 늘어나니까요.
시스템이 작고 단순할 때는 적합할 수 있지만, 확장되면 프로비저닝·변경 속도가 느려지고 폭발 반경이 최대가 됩니다.
내 스택은 모놀리식일까?
판단 축은 “주어진 시간에 몇 명이 이 스택을 바꾸는가”입니다. 다음 신호들이 잦으면 의심합니다.
- 스택 조각들이 어떻게 맞물리는지 이해하기 어렵고, 신규 팀원 온보딩과 디버깅이 느리다
- 변경·배포할 때마다 실패와 충돌이 잦다
- 기능 브랜치를 습관적으로 쓴다
- CI 빌드 시간이 길어지고 빌드 규율 유지가 어렵다
여러 팀이 한 스택을 공유하고 있다면 분할할 때입니다.
패턴 — 애플리케이션 그룹 스택
여러 애플리케이션·서비스의 인프라를 하나의 스택으로 묶습니다. 예를 들어 ShopSpinner의 제품 스택에는 제품 브라우징, 제품 검색, 장바구니 서비스가 함께 들어가고, 단일 명령으로 전체를 프로비저닝·제거할 수 있습니다.
하나의 팀이 모든 애플리케이션의 인프라와 배포 권한을 소유할 때 잘 작동하며, 모놀리식에서 서비스 스택으로 발전하는 중간 단계로 유용합니다. 대가는 시간·위험·변경 속도의 결합입니다 — 한 부분만 변경해도 전체 스택의 위험을 관리해야 하므로, 특정 부분만 자주 변경된다면 비효율적입니다.
패턴 — 서비스 스택
배포 가능한 애플리케이션 컴포넌트 단위로 스택을 분리합니다. 인프라의 경계를 그 위에서 실행되는 소프트웨어에 맞추는 것입니다.
폭발 반경이 서비스 하나로 제한되어 변경 프로세스가 단순해지고, 서비스 팀이 자기 소프트웨어의 인프라를 소유할 수 있습니다. 마이크로서비스 아키텍처, 자율적인 팀 조직과 잘 맞습니다.
대가는 스택 간 코드 중복 입니다. 각 스택에 앱 서버 프로비저닝 코드가 반복되면 OS 버전·네트워크 구성이 조금씩 어긋나 일관성이 깨집니다. 모듈로 코드를 공유해 해결합니다.
패턴 — 마이크로 스택
단일 서비스의 인프라를 다시 여러 스택으로 나눕니다. 네트워크·서버·데이터베이스 각각 별도의 스택 프로젝트를 두는 식입니다.
핵심 동기는 수명주기의 분리 입니다. 서버 인스턴스는 자주 삭제하고 리빌드하지만, 데이터베이스나 디스크 볼륨의 데이터는 영속적입니다. 서버와 데이터를 다른 스택에서 관리하면 서버 스택만 훨씬 자주 리빌드할 수 있습니다.
대가는 통합 복잡도입니다. 작은 스택 자체는 간단하지만, 리빌드되는 부분이 많아지면 스택 사이를 연결하는 일이 복잡해집니다.
비교 / 트레이드오프
| 패턴 | 스택 단위 | 잘 맞는 상황 | 대가 |
|---|---|---|---|
| 모놀리식 (안티패턴) | 시스템 전체 | 작고 단순한 시스템 | 폭발 반경 최대, 변경이 느리고 위험 → 기술 부채 |
| 애플리케이션 그룹 | 여러 서비스 묶음 | 한 팀이 전체 소유, 서비스 스택으로 가는 과도기 | 일부만 바꿔도 전체 스택의 위험 관리 |
| 서비스 스택 | 배포 가능한 서비스 1개 | 마이크로서비스, 자율적 서비스 팀 | 스택 간 코드 중복 (모듈로 해결) |
| 마이크로 스택 | 서비스 내 수명주기 단위 | 부분별 변경 주기·특성이 다를 때 (서버 vs 데이터) | 스택 통합 복잡도 |
결국 경계의 기준은 세 가지 질문입니다: 함께 변경되는가, 누가 소유하는가, 수명주기가 같은가.
내 생각
- 폭발 반경의 실무 정의는 “
terraform apply한 번에 걸리는 코드 범위”입니다. plan 결과가 수백 줄씩 나오거나 state 잠금 경합이 잦다면 스택 분리 신호로 읽으면 됩니다. - 스택 경계는 결국 팀 경계를 따라갑니다. 서비스 스택이 마이크로서비스와 잘 맞는 이유는 기술 문제가 아니라 “여러 팀이 한 스택을 공유하면 조정 비용이 폭증한다”는 조직 문제 때문입니다.
- 서버/데이터 스택 분리는 stateless/stateful 분리와 같은 원리입니다. 자주 갈아치우는 것과 지켜야 하는 것을 같은 수명주기로 묶지 않는다는 감각은 애플리케이션 설계와 동일합니다.
관련 개념
- Ch03 인프라 플랫폼 — 스택이 조합하는 리소스(VM·볼륨·서브넷)를 제공하는 계층
- Ch04 모든 것을 코드로 정의한다 — “코드를 인스턴스에 적용”하는 멱등 동작과 선언형 언어의 배경