소프트웨어 아키텍처 종류 — 전체 지도
how-to-design-a-program-from-scratch|설계 프로세스에서 아키텍처를 선택할 때 알아야 할 주요 패턴들. 모든 아키텍처의 차이는 결국 세 가지 질문에 대한 답이다: 누가 누구를 호출하는가(제어 흐름), 데이터가 어디에 살고 이동하는가(데이터 흐름), 변경이 생기면 어디까지 퍼지는가(결합도).
1계열: 계층으로 나누기
Layered Architecture
코드를 수평 층으로 나누고 위에서 아래로만 호출한다.
핵심 규칙: 아래 층은 위 층을 모른다.
적합 여부: 소~중규모, 팀이 작을 때. 한계: 층이 많아지면 단순한 변경도 여러 층을 관통.
Clean Architecture (Hexagonal / Ports & Adapters)
Layered의 진화형. 의존성 방향을 반전시킨다. 핵심 도메인이 "Repository 인터페이스"만 알고, 실제 DB 구현은 바깥에 있다. DB를 교체해도 핵심 로직을 안 건드린다.
적합: DB/프레임워크 교체 가능성, 장기 유지보수. 한계: 보일러플레이트가 많아 소규모에서는 과함.
2계열: 역할로 나누기
MVC (Model-View-Controller)
UI 앱에서 역할을 셋으로 분리.
Model이 View에 직접 알림을 보낼 수 있다 (Observer 패턴). 전통적 서버 렌더링 웹앱에 적합 (Rails, Django, Spring MVC).
MVVM (Model-View-ViewModel)
MVC 변형. Controller 대신 ViewModel이 화면 상태를 관리하고 View와 양방향 바인딩된다. Svelte의 reactive 변수, React의 useState가 ViewModel 역할.
MVC에서 Controller가 "입력을 해석"하는 역할이었다면, ViewModel은 "화면 상태를 관리" 하는 역할이야. Svelte의 reactive 변수, React의 useState가 ViewModel의 역할을 하는 거야.
MVC: 사용자 클릭 → Controller 해석 → Model 업데이트 → View 갱신
MVVM: 사용자 클릭 → ViewModel 상태 변경 → 자동으로 View 반영
적합: 프론트엔드 SPA (Svelte, React, Vue).
3계열: 이벤트로 나누기
Event-Driven Architecture
모듈이 서로를 직접 호출하지 않고 이벤트를 발행/구독한다. 각 모듈이 서로를 모르기 때문에 새 기능 추가 시 기존 코드를 안 건드린다.
적합: 기능이 많고 독립적이어야 할 때, 플러그인 시스템. 한계: 흐름 추적과 디버깅이 어려움.
Pub/Sub (Publisher-Subscriber)
Event-Driven의 네트워크 확장.
메시지 브로커(Redis, RabbitMQ, Kafka)를 통해 서로 다른 서버 간 이벤트를 주고받는다. 대규모 분산 시스템에서 사용.
4계열: 서비스로 나누기
Monolith
하나의 앱에 모든 기능. Layered, MVC 등은 대부분 모놀리스 안에서의 구조다.
단순하고 배포 한 번이면 끝. 커지면 한 기능 수정이 전체에 영향.
Microservices
기능별로 완전히 독립된 서비스.
각 서비스가 자기만의 DB를 가지고, 독립 배포 가능. 언어도 서비스마다 다를 수 있다.
적합: 대규모 팀, 서비스별 배포 주기가 다를 때 (Netflix, 쿠팡). 한계: 복잡도 폭발 (네트워크 통신, 데이터 일관성, 장애 전파). 소규모에서는 절대 쓰면 안 된다.
5계열: 데이터 흐름으로 나누기
Pipe and Filter
데이터가 파이프라인을 따라 한 방향으로 흐르면서 변환된다.
Unix의 cat file | grep "algo" | sort가 정확히 이 구조야. 그리고 네가 관심 있을 만한 곳: 데이터 전처리 파이프라인, 크롤링 파이프라인, ML 학습 파이프라인이 이 패턴이야.
크롤링: 웹페이지 → HTML 파싱 → 데이터 추출 → 정제 → DB 저장
ML: 원본 데이터 → 전처리 → 특성 추출 → 학습 → 평가
Unix: cat file | grep "algo" | sort
적합: 데이터 처리, ETL, ML 파이프라인, 컴파일러.
전체 선택 지도
중요한 원칙
아키텍처는 섞어 쓸 수 있다. 앱 전체는 Layered인데 UI는 MVVM이고, 알림만 Event-Driven으로 동작할 수 있다. "하나만 골라야 한다"가 아니라 "어떤 부분에 어떤 패턴이 맞는가"로 생각한다.