C4 모델
고친 사람 github-actions[bot]
C4 모델은 소프트웨어의 구조를 여러 배율로 나눠 그리게 해 줍니다. 가장 먼 배율에서는 시스템 하나와 그것을 쓰는 사람만 보입니다. 한 단계씩 확대할수록 시스템 안의 실행 단위와 그 속의 부품이 드러납니다. 듣는 사람에 맞는 배율의 그림을 골라 보여 줄 수 있습니다.
쉽고 빠른 이해
무슨 일을 하나 — 시스템 구조 그림을 네 장으로 나눠 그립니다. 온라인 서점이라면 「고객과 서점과 결제 회사」를 그린 한 장, 「웹 화면과 서버와 데이터베이스」를 그린 한 장이 따로 있습니다.
왜 하나 — 한 장에 다 그리면 사장님에게는 너무 복잡합니다. 개발자에게는 너무 흐립니다. 상자 하나가 서버인지 코드 묶음인지도 그린 사람만 압니다.
어떻게 도나
- 시스템 바깥을 먼저 그립니다. 누가 쓰는지와 무엇과 주고받는지를 그립니다
- 시스템 하나를 열어 따로 돌아가는 프로그램과 데이터베이스를 그립니다
- 그중 하나를 다시 열어 안의 부품을 그립니다
- 부품 하나를 다시 열어 클래스와 함수를 그립니다. 이 장은 흔히 건너뜁니다
대가 — 손으로 그린 그림은 코드가 바뀌어도 저절로 안 바뀝니다. 장수가 늘수록 낡은 그림도 늘어납니다.
언제 쓰나 — 처음 오는 사람에게 시스템을 설명할 때 씁니다. 작은 시스템이면 앞의 두 장이면 됩니다.
상세
이 절은 온라인 서점 하나를 예로 삼습니다. 고객이 책을 주문하고 결제하는 시스템입니다. 같은 시스템을 네 배율로 차례로 그려 보며 C4 모델이 무엇을 정해 두는지 봅니다.
한 장에 다 그리면 생기는 일
소프트웨어 아키텍처는 시스템을 어떤 부품으로 나누고 그 부품들을 어떻게 잇는지에 대한 큰 그림입니다. 팀은 이 그림을 화이트보드나 문서에 상자와 화살표로 그려 나눕니다. 그런데 그 그림을 처음 보는 사람은 자주 멈춥니다.
흔한 그림 하나를 봅시다. 「주문」 상자와 「결제」 상자가 화살표로 이어져 있습니다. 「주문」이 서버 한 대인지, 서버 안의 코드 묶음인지 그림만으로는 알 수 없습니다. 화살표가 HTTP(HyperText Transfer Protocol, 웹에서 요청과 응답을 주고받는 규약) 요청인지, 함수 호출인지도 안 적혀 있습니다.
더 큰 문제는 듣는 사람마다 필요한 크기가 다르다는 것입니다. 기획자는 서점이 어떤 바깥 서비스에 기대는지만 알면 됩니다. 새로 온 백엔드 개발자는 주문 서버 안에서 어느 코드가 결제를 부르는지 알아야 합니다. 둘을 한 장에 담으면 어느 쪽에도 맞지 않습니다.
C4 모델은 이 문제를 배율로 풉니다. 지도 앱을 떠올리면 됩니다. 나라 전체를 볼 때는 도시 이름만 보입니다. 확대하면 거리와 건물이 보입니다. 한 화면에 나라와 건물을 같이 그리지 않습니다.
네 단계와 이름
C4 모델은 그림을 네 단계로 나눕니다. 네 단계의 영어 이름 Context·Container·Component·Code 가 모두 C 로 시작해서 C4 라는 이름이 붙었습니다. 한국어로는 시스템 컨텍스트·컨테이너·컴포넌트·코드라고 부릅니다.
단계가 내려갈수록 앞 단계의 상자 하나를 열어서 그 안을 그립니다. 그래서 네 장의 그림은 따로 노는 것이 아니라 서로 이어져 있습니다.
| 단계 | 그리는 것 | 주로 보는 사람 |
|---|---|---|
| 시스템 컨텍스트 | 시스템 하나와 그 바깥의 사람·시스템 | 개발자가 아닌 사람까지 전부 |
| 컨테이너 | 시스템 안에서 따로 돌아가는 프로그램과 데이터 저장소 | 개발자 · 운영 담당 |
| 컴포넌트 | 컨테이너 하나 안의 큰 부품 | 그 컨테이너를 만드는 개발자 |
| 코드 | 컴포넌트 하나 안의 클래스와 함수 | 그 코드를 고치는 개발자 |
아래 그림은 확대가 어떻게 이어지는지 보입니다. 위 단계의 상자 하나가 아래 단계 그림 한 장이 됩니다. 그림 속 상자 이름은 뒤의 소절에서 하나씩 풉니다.
flowchart TD
A["시스템 컨텍스트 · 서점 시스템이 상자 하나"] -->|"서점 시스템을 연다"| B["컨테이너 · 웹 화면 · 주문 API 서버 · 데이터베이스"]
B -->|"주문 API 서버를 연다"| C["컴포넌트 · 주문 처리 · 결제 연동 · 재고 조회"]
C -->|"결제 연동을 연다"| D["코드 · 클래스와 함수"]
시스템 컨텍스트 다이어그램
첫 단계는 가장 멀리서 본 그림입니다. 우리 시스템은 상자 하나로만 그립니다. 그 둘레에 이 시스템을 쓰는 사람과, 이 시스템이 주고받는 바깥 시스템을 놓습니다.
서점이라면 상자는 넷입니다. 고객, 서점 시스템, 카드 결제를 대신 처리해 주는 결제 대행사, 주문 확인 메일을 보내 주는 메일 발송 서비스입니다. 화살표에는 「책을 주문한다」 「결제를 요청한다」처럼 무엇을 하는지를 적습니다.
이 그림에는 서버나 데이터베이스가 안 나옵니다. 기술 낱말을 모르는 사람도 읽을 수 있어야 하기 때문입니다. 대신 「이 시스템이 무엇에 기대는가」가 한눈에 보입니다. 결제 대행사가 멈추면 서점도 멈춘다는 것을 회의를 시작하자마자 모두가 압니다.
컨테이너 다이어그램
둘째 단계는 서점 시스템 상자를 열어서 그립니다. 이 단계의 상자 하나하나를 컨테이너라고 부릅니다.
C4 모델에서 컨테이너는 따로 실행되거나 따로 데이터를 담는 단위입니다. 웹 애플리케이션 하나, API(Application Programming Interface, 프로그램끼리 서로 부르는 창구) 서버 하나, 데이터베이스 하나, 휴대폰에 깔리는 앱 하나가 각각 컨테이너입니다.
도커의 컨테이너와는 이름만 같습니다. 도커에 담아 돌리든 안 담든, 따로 실행되거나 따로 데이터를 담으면 C4 의 컨테이너입니다.
서점 시스템을 열면 아래 모양이 나옵니다. 고객이 직접 만나는 것은 웹 화면뿐입니다. 결제 대행사와 메일 발송 서비스는 주문 API 서버가 부릅니다.
flowchart TD
고객["고객 · 사람 · 책을 고르고 산다"]
subgraph 서점시스템["서점 시스템"]
웹["웹 화면 · 브라우저에서 도는 앱 · 책을 보여 주고 주문을 받는다"]
서버["주문 API 서버 · 자바 웹 서버 · 주문을 받고 결제를 요청한다"]
DB[("주문 데이터베이스 · 데이터베이스 · 주문과 재고를 담는다")]
end
결제["결제 대행사 · 바깥 시스템 · 카드 결제를 대신 처리한다"]
메일["메일 발송 서비스 · 바깥 시스템 · 주문 확인 메일을 보낸다"]
고객 -->|"책을 고르고 주문한다"| 웹
웹 -->|"주문을 보낸다 · HTTP"| 서버
서버 -->|"주문을 적는다 · SQL"| DB
서버 -->|"결제를 요청한다 · HTTP"| 결제
서버 -->|"확인 메일을 부탁한다 · HTTP"| 메일
이 그림부터 기술 이름이 화살표와 상자에 붙습니다. 주문 API 서버가 데이터베이스와 SQL(Structured Query Language, 데이터베이스에 묻고 쓰는 언어) 로 이야기한다는 것이 보입니다. 운영 담당은 이 그림을 보고 무엇을 몇 개 띄워야 하는지 가늠합니다.
컴포넌트 다이어그램
셋째 단계는 컨테이너 하나를 열어서 그립니다. 주문 API 서버를 열면 그 안의 큰 부품들이 보입니다.
컴포넌트는 관련된 기능을 한데 모은 코드 묶음입니다. 바깥에서는 그 묶음이 내놓은 인터페이스(바깥에서 부를 수 있는 함수들의 목록)로만 부릅니다. 그래서 안쪽 코드를 바꿔도 부르는 쪽은 그대로 둘 수 있습니다.
컴포넌트는 컨테이너와 달리 혼자 실행되지 않습니다. 컨테이너 하나 안에서 함께 돌아갑니다.
주문 API 서버라면 주문 처리, 결제 연동, 재고 조회 같은 컴포넌트가 나옵니다. 화살표는 「주문 처리가 결제 연동을 부른다」처럼 어느 부품이 어느 부품에 기대는지를 보입니다. 새로 온 개발자가 결제 버그를 고치러 어느 코드부터 열어야 할지 여기서 알게 됩니다.
코드 다이어그램
넷째 단계는 컴포넌트 하나를 열어서 그 안의 클래스와 함수를 그립니다. UML(Unified Modeling Language, 통합 모델링 언어)은 소프트웨어 설계를 그리는 표준 기호 모음입니다. 객체 지향 언어라면 그중 클래스 다이어그램이 흔히 쓰입니다. 클래스를 상자로, 클래스끼리의 관계를 선으로 그린 그림입니다.
이 단계는 사람이 손으로 잘 안 그립니다. 코드가 바뀔 때마다 그림이 낡기 때문입니다. 필요하면 개발 도구가 코드를 읽어 자동으로 그려 주는 그림을 씁니다. 세 단계만 그리고 코드 단계는 건너뛰는 팀도 많습니다.
그림 하나를 그리는 약속
C4 모델은 상자 모양이나 색을 정하지 않습니다. 네모를 쓰든 원통을 쓰든 자유입니다. 대신 다른 사람이 그린 그림도 설명 없이 읽히도록 몇 가지 약속을 둡니다.
상자마다 세 가지를 적습니다. 이름, 종류, 한 줄 설명입니다. 「주문 API 서버 · 자바 웹 서버 · 주문을 받고 결제를 요청한다」처럼 씁니다. 종류가 적혀 있으면 상자가 사람인지 서버인지 코드 묶음인지 묻지 않아도 됩니다.
화살표는 한쪽 방향으로 긋습니다. 방향이 없는 선은 누가 누구를 부르는지 알려 주지 않기 때문입니다.
화살표 위에는 무엇을 하는지를 적습니다. 선만 있으면 무엇이 오가는지 모릅니다. 컨테이너 단계부터는 어떤 방식으로 주고받는지도 붙입니다. 「주문을 보낸다 · HTTP」 같은 식입니다.
그림마다 제목을 답니다. 모양과 색이 무엇을 뜻하는지 밝히는 범례도 둡니다. 범례가 있으면 다른 팀이 그린 그림도 읽을 수 있습니다.
보조 다이어그램
네 단계는 모두 가만히 있는 구조를 보입니다. 시간에 따라 무엇이 오가는지나, 어느 서버에 무엇이 깔리는지는 따로 그립니다. C4 모델은 이를 위한 보조 다이어그램 셋을 함께 듭니다.
| 보조 다이어그램 | 보이는 것 |
|---|---|
| 시스템 랜드스케이프 | 회사 안의 여러 시스템과 그 사이의 연결. 컨텍스트 다이어그램을 시스템 여럿으로 넓힌 그림 |
| 다이내믹 | 주문 하나가 들어왔을 때 상자들 사이로 요청이 오가는 순서 |
| 배포 | 컨테이너들이 어느 서버나 클라우드 환경에 깔리는지 |
언제 쓰고 언제 덜 쓰나
C4 모델은 처음 오는 사람에게 시스템을 설명할 때 힘을 냅니다. 새 팀원 온보딩, 다른 팀과의 설계 검토, 시스템 문서가 그렇습니다. 컨텍스트 그림 한 장과 컨테이너 그림 한 장이면 대개 첫 대화가 됩니다.
작은 시스템에서는 네 장이 다 필요하지 않습니다. 서버 하나와 데이터베이스 하나뿐이라면 컨텍스트와 컨테이너 두 장으로 충분합니다. 몇 장을 그릴지는 그림을 볼 사람이 정합니다.
손으로 그린 그림은 코드를 따라 저절로 바뀌지 않습니다. 컴포넌트와 코드 단계처럼 자주 바뀌는 그림일수록 빨리 낡습니다. 그래서 그림을 텍스트로 적어 코드 저장소(소스 코드를 담아 두는 곳)에 코드와 함께 두는 팀도 있습니다. Structurizr나 PlantUML 같은 도구가 그 텍스트를 읽어 그림을 그립니다.
C4 모델은 구조가 지금 어떻게 생겼는지를 보입니다. 왜 그렇게 나눴는지는 보이지 않습니다. 그 이유는 아키텍처 결정 기록처럼 결정을 글로 남기는 문서가 맡습니다.
UML 과 4+1 뷰
UML 은 기호의 약속입니다. 상자와 화살표가 무엇을 뜻하는지를 정합니다. C4 모델은 무엇을 어느 배율로 그릴지에 대한 약속입니다. 그래서 C4 의 네 단계는 UML 기호로 그려도 됩니다. 아무 상자로 그려도 됩니다.
4+1 뷰는 같은 시스템을 관점 넷으로 나눠 그립니다. 기능을 어떻게 나눴나, 실행 중에 무엇이 동시에 도나, 코드를 어떻게 묶나, 어느 기계에 무엇이 깔리나가 그 넷입니다. 「+1」인 시나리오는 사용자가 하는 일 몇 가지를 골라 네 관점이 그 일을 제대로 받쳐 주는지 맞춰 봅니다. C4 모델은 관점을 바꾸기보다 한 구조를 확대해 들어갑니다.
관련 항목
C4 모델이 그리는 구조의 상위 분류
소프트웨어 아키텍처 · 아키텍처 양식 · 아키텍처 기술 · 모놀리스 · 마이크로서비스 · 레이어드
C4 모델과 같은 일을 두고 겨루는 표기법
UML · 4+1 뷰 · 클래스 다이어그램 · 시퀀스 다이어그램 · 배포 다이어그램 · 아키텍처 다이어그램
C4 모델의 네 단계를 이루는 구성 요소
컨텍스트 다이어그램 · 웹 애플리케이션 · API · 데이터베이스 · 인터페이스 · 프로세스
C4 다이어그램을 텍스트로 그리는 도구
Structurizr · PlantUML · Mermaid · docs as code · 다이어그램 as code
C4 모델과 함께 남기는 설계 문서
아키텍처 결정 기록 · 설계 문서 · 온보딩 · 기술 문서화
다른 이름: C4 · C4 model · C4 Model · C4 다이어그램 · C4 모델 다이어그램