196 lines
6.4 KiB
Markdown
196 lines
6.4 KiB
Markdown
---
|
|
id: wiki-2026-0508-모놀리식-아키텍처-monolithic-architectur
|
|
title: 모놀리식 아키텍처 (Monolithic Architecture)
|
|
category: 10_Wiki/Topics
|
|
status: verified
|
|
canonical_id: self
|
|
aliases: [Monolith, Modular Monolith, 단일 서비스 아키텍처]
|
|
duplicate_of: none
|
|
source_trust_level: A
|
|
confidence_score: 0.9
|
|
verification_status: applied
|
|
tags: [architecture, monolith, software-design, deployment]
|
|
raw_sources: []
|
|
last_reinforced: 2026-05-10
|
|
github_commit: pending
|
|
tech_stack:
|
|
language: language-agnostic
|
|
framework: Spring/Rails/Django/Next.js
|
|
---
|
|
|
|
# 모놀리식 아키텍처 (Monolithic Architecture)
|
|
|
|
## 매 한 줄
|
|
> **"매 단일 deployable unit 으로 묶인 application"**. 1990년대 이래 표준이었으나 microservices 의 등장으로 anti-pattern 처럼 취급되다가, 2023년 Amazon Prime Video 의 monolith 회귀 사례 이후 modular monolith 가 2026년 현재 default choice 로 부활.
|
|
|
|
## 매 핵심
|
|
|
|
### 매 정의
|
|
- 매 single codebase, single build, single deployment.
|
|
- 매 모든 business capability 가 하나의 process 내 in-memory 호출.
|
|
- 매 single database 공유 (보통 RDBMS).
|
|
|
|
### 매 variant
|
|
- **Big ball of mud**: 매 module boundary X. 매 anti-pattern.
|
|
- **Layered monolith**: 매 controller / service / repo layer 분리. 매 일반적.
|
|
- **Modular monolith**: 매 internal module boundary 명확. 매 microservices 직전 단계.
|
|
- **Distributed monolith**: 매 worst case — 매 microservices 처럼 deploy 하나 coupling 은 monolith.
|
|
|
|
### 매 응용
|
|
1. Early-stage startup MVP — 매 fast iteration.
|
|
2. Internal tools — 매 traffic low, complexity low.
|
|
3. Modular monolith — 매 mid-size product (Shopify, Basecamp, GitHub).
|
|
|
|
## 💻 패턴
|
|
|
|
### Layered structure (Spring Boot)
|
|
```java
|
|
// src/main/java/com/example/app/
|
|
// ├── controller/ ── HTTP boundary
|
|
// ├── service/ ── business logic
|
|
// ├── repository/ ── data access
|
|
// └── domain/ ── entities
|
|
|
|
@RestController
|
|
@RequestMapping("/orders")
|
|
class OrderController {
|
|
private final OrderService service;
|
|
OrderController(OrderService s) { this.service = s; }
|
|
|
|
@PostMapping
|
|
Order create(@RequestBody CreateOrderReq req) {
|
|
return service.placeOrder(req);
|
|
}
|
|
}
|
|
|
|
@Service
|
|
class OrderService {
|
|
private final OrderRepository orders;
|
|
private final PaymentService payments; // 매 in-process call
|
|
|
|
@Transactional
|
|
Order placeOrder(CreateOrderReq req) {
|
|
var order = orders.save(new Order(req));
|
|
payments.charge(order); // 매 same DB transaction
|
|
return order;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Modular monolith (Rails-like, internal API)
|
|
```ruby
|
|
# app/modules/billing/
|
|
# ├── public/ # 매 외부 module 가 import 가능
|
|
# │ └── billing_api.rb
|
|
# └── internal/ # 매 module 내부에서만
|
|
# ├── invoice.rb
|
|
# └── stripe_client.rb
|
|
|
|
# 매 module boundary enforcement (packwerk gem)
|
|
module Billing
|
|
module Public
|
|
class BillingAPI
|
|
def self.charge(user_id:, amount:)
|
|
Internal::StripeClient.new.charge(user_id, amount)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# 매 Catalog module 가 Billing 호출 — 매 public API 만
|
|
class CheckoutFlow
|
|
def call(cart)
|
|
Billing::Public::BillingAPI.charge(
|
|
user_id: cart.user_id,
|
|
amount: cart.total
|
|
)
|
|
end
|
|
end
|
|
```
|
|
|
|
### Single binary deploy (Go)
|
|
```go
|
|
// main.go — 매 entire app one binary
|
|
func main() {
|
|
db := mustOpenDB()
|
|
defer db.Close()
|
|
|
|
mux := http.NewServeMux()
|
|
mux.Handle("/users/", users.NewHandler(db))
|
|
mux.Handle("/orders/", orders.NewHandler(db))
|
|
mux.Handle("/billing/", billing.NewHandler(db))
|
|
|
|
log.Fatal(http.ListenAndServe(":8080", mux))
|
|
}
|
|
|
|
// 매 deploy = scp binary + restart systemd
|
|
// 매 zero network hop, zero serialization
|
|
```
|
|
|
|
### Shared transaction (atomicity)
|
|
```python
|
|
# 매 monolith 의 핵심 이점 — 매 single ACID transaction
|
|
@transaction.atomic
|
|
def transfer_funds(from_id, to_id, amount):
|
|
src = Account.objects.select_for_update().get(id=from_id)
|
|
dst = Account.objects.select_for_update().get(id=to_id)
|
|
src.balance -= amount
|
|
dst.balance += amount
|
|
src.save(); dst.save()
|
|
AuditLog.objects.create(action="transfer", amount=amount)
|
|
# 매 all-or-nothing — 매 saga / 2PC 매 X
|
|
```
|
|
|
|
### Module 경계 violation 탐지 (TypeScript)
|
|
```ts
|
|
// .dependency-cruiser.cjs
|
|
module.exports = {
|
|
forbidden: [
|
|
{
|
|
name: 'no-cross-module-internal',
|
|
from: { path: '^src/modules/([^/]+)' },
|
|
to: { path: '^src/modules/(?!\\1)[^/]+/internal' },
|
|
},
|
|
],
|
|
};
|
|
// 매 CI 에서 검증 — 매 module boundary 매 enforce
|
|
```
|
|
|
|
## 매 결정 기준
|
|
| 상황 | Approach |
|
|
|---|---|
|
|
| 팀 < 20명, product 단일 | **Modular monolith** |
|
|
| MVP / startup early stage | **Layered monolith** |
|
|
| Independent scaling 필요 (e.g. ML inference) | **Monolith + extracted service** |
|
|
| 팀 > 50명, 매 다중 product line | Microservices |
|
|
| Compliance — 매 isolation 필수 (PCI 등) | Microservices subset |
|
|
| 매 "microservices 가 멋져 보여서" | **Monolith** (절대 X 분리) |
|
|
|
|
**기본값**: Modular monolith. 매 boundary 가 stable 해진 후 strangler-fig pattern 으로 extract.
|
|
|
|
## 🔗 Graph
|
|
- 부모: [[Software Architecture]] · [[Deployment Models]]
|
|
- 변형: [[Modular Monolith]] · [[Layered Architecture]] · [[Distributed Monolith]]
|
|
- 응용: [[Shopify Architecture]] · [[Basecamp HEY]] · [[GitHub Rails Monolith]]
|
|
- Adjacent: [[Microservices]] · [[Service-Oriented Architecture]] · [[Strangler Fig Pattern]]
|
|
|
|
## 🤖 LLM 활용
|
|
**언제**: MVP 설계, 매 small-team product, 매 strong consistency 요구, 매 deployment simplicity 우선.
|
|
**언제 X**: 팀 > 50, 매 independent scaling 필수, 매 polyglot tech stack 강제, 매 fault isolation 강제.
|
|
|
|
## ❌ 안티패턴
|
|
- **Premature microservices**: 매 100명 이하 팀이 매 microservices — 매 distributed monolith 직행.
|
|
- **Big ball of mud**: 매 module boundary 없이 grow — 매 5년 후 rewrite.
|
|
- **Shared mutable state across "modules"**: 매 module 이 서로의 internal table 직접 access — 매 boundary X.
|
|
- **God service**: 매 OrderService 가 매 모든 domain 호출 — 매 modularity X.
|
|
|
|
## 🧪 검증 / 중복
|
|
- Verified (Fowler "MonolithFirst" 2015, Amazon Prime Video case study 2023, Shopify modular monolith talk 2021).
|
|
- 신뢰도 A.
|
|
|
|
## 🕓 Changelog
|
|
| 날짜 | 변경 |
|
|
|---|---|
|
|
| 2026-05-08 | Phase 1 |
|
|
| 2026-05-10 | Manual cleanup — modular monolith 부활 perspective + 5 patterns |
|