Putting It All Together — 실전 예시와 템플릿
예시: Academic Life System 아키텍처 결정 과정
의사결정 워크스루
1단계: 도메인 복잡도 평가
| 기능 | 복잡도 | 근거 | | ---------- | ----- | ----------------------------- | | 학생 정보 CRUD | 낮음 | 단순 읽기/쓰기 | | 수강 신청 | 중간 | 선수과목 체크, 학점 한도 검증 | | 과목 추천 | 높음 | 커리큘럼 분석, 선수과목 그래프 탐색, 우선순위 계산 | | LLM 상담 | 높음 | 외부 API 연동, 응답 파싱, 컨텍스트 구성 | | 졸업요건 확인 | 중간~높음 | 복잡한 규칙 조합 (필수/선택, 학점 합계, GPA) |
판정: 복잡한 기능이 핵심이므로 → Domain Model
2단계: 데이터 소스 패턴 선택
DCD 클래스와 테이블 매핑 상태:
- Student ↔ students: 1:1 ✅
- Course ↔ courses: 1:1 ✅
- Enrollment ↔ enrollments: 1:1 ✅
- Curriculum + Requirement: 약간의 불일치 있지만 관리 가능
- LLMCounselorService: 테이블 없음 (외부 API)
판정: 대부분 1:1이고, 상속 구조가 아직 없음 → Active Record로 시작. LLM 연동은 Gateway 패턴으로 분리.
3단계: 프레젠테이션 선택
- 웹 기반 → MVC (Drogon 기본 제공)
- 단순한 페이지 구조 → Page Controller로 충분
- View: Drogon CSP (Template View)
4단계: 결과 아키텍처
향후 진화 시나리오
"Active Record가 한계에 부딪히는 순간":
- Curriculum에 상속 구조가 필요해짐 (학과별 다른 졸업요건 타입)
- RecommendationService가 Student, Course, Enrollment를 복잡하게 조합
- 테스트할 때 DB 없이 도메인 로직만 테스트하고 싶어짐
→ 이때 Data Mapper로 전환. Student에서 SQL을 빼고 StudentMapper를 만든다.
템플릿
아키텍처 의사결정 기록 (ADR)
# Architecture Decision Record: [결정 제목]
## 상태
[제안됨 / 승인됨 / 폐기됨 / 대체됨]
## 맥락
[이 결정이 필요한 배경. 어떤 문제를 해결하려는가?]
## 결정
[무엇을 선택했는가?]
## 고려한 대안들
### 대안 1: [이름]
- 장점:
- 단점:
- 적합 조건:
### 대안 2: [이름]
- 장점:
- 단점:
- 적합 조건:
## 선택 근거
[왜 이 대안을 선택했는가? Fowler의 어떤 기준을 적용했는가?]
## 결과
[이 결정으로 인해 예상되는 영향]
## 전환 트리거
[어떤 상황이 되면 이 결정을 재검토해야 하는가?]
전체 아키텍처 결정 워크시트
## [프로젝트명] 아키텍처 결정
### Step 1: 도메인 복잡도 평가
| 핵심 기능 | 복잡도 (Low/Mid/High) | 근거 |
|----------|---------------------|------|
| ________ | | |
| ________ | | |
| ________ | | |
전체 판정: ___ → 도메인 로직 패턴: ___________
### Step 2: 데이터 소스 패턴 선택
| DCD 클래스 | DB 테이블 | 1:1? | 상속? | 복잡한 연관? |
|-----------|----------|------|------|-----------|
| _________ | _________ | Y/N | Y/N | Y/N |
| _________ | _________ | Y/N | Y/N | Y/N |
판정: ___________
전환 트리거: ___________
### Step 3: 프레젠테이션 선택
- 인터페이스: Web / Rich Client / API / CLI
- Controller: Page Controller / Front Controller
- View: Template View / Transform View / Two Step View
- Application Controller 필요: Yes / No
### Step 4: 인프라 결정
- 분산 필요: Yes / No
- Yes → Remote Facade + DTO 도입
- No → 단일 프로세스 (권장)
- 세션 상태: Server / Client / DB
- 동시성: Optimistic / Pessimistic
### Step 5: 결과 요약
| 계층 | 패턴 | 구체적 기술/프레임워크 |
|------|------|---------------------|
| Presentation | __________ | __________ |
| Domain | __________ | __________ |
| Data Source | __________ | __________ |
| 기타 | __________ | __________ |
기술 스택 매핑 템플릿
## [프로젝트명] 패턴 → 기술 매핑
| Fowler 패턴 | 우리 프로젝트의 구현 | 파일/클래스 위치 |
|------------|-------------------|---------------|
| Domain Model | __________ | src/domain/ |
| Active Record / Data Mapper | __________ | src/mapper/ |
| Service Layer | __________ | src/service/ |
| Page/Front Controller | __________ | src/controller/ |
| Template View | __________ | views/ |
| Gateway (외부 시스템) | __________ | src/gateway/ |
| Unit of Work | 자체구현 / 프레임워크 제공 | |
| Identity Map | 자체구현 / 프레임워크 제공 | |
Iteration별 아키텍처 진화 계획
## [프로젝트명] 아키텍처 진화 로드맵
### Iteration 1: [범위]
- 도메인: [패턴] — [핵심 클래스들]
- 데이터: [패턴] — [핵심 테이블들]
- 프레젠테이션: [패턴]
- 검증할 가설: "___________"
### Iteration 2: [범위]
- 변경/추가: ___________
- 검증할 가설: "___________"
### 전환 체크포인트
- [ ] Active Record에서 도메인-DB 불일치가 3곳 이상 → Data Mapper 검토
- [ ] Transaction Script에서 코드 중복 3회 이상 → Domain Model 전환
- [ ] 외부 시스템 연동이 도메인에 침투 → Gateway 도입
마스터 의사결정 플로우
템플릿: 전체 아키텍처 결정 기록서 (Full ADR)
프로젝트마다 이 문서를 하나 만들고, 결정을 내릴 때마다 빈칸을 채운다.
# [프로젝트명] 아키텍처 결정 기록
## 프로젝트 개요
- **이름**:
- **도메인**:
- **핵심 Use Case**:
- **예상 사용자 수**:
- **동시 접속자 수**:
---
## 결정 1: 도메인 로직 패턴
**선택**: Transaction Script / Table Module / Domain Model (단순/복잡)
| 평가 항목 | 이 프로젝트에서 |
|----------|--------------|
| 비즈니스 규칙 복잡도 | 낮 / 중 / 고 |
| 규칙 변경 빈도 | 낮 / 중 / 고 |
| 조건 분기 수준 | 단순 if-else / Strategy 필요 / 상속 필요 |
| 팀 OO 경험 | 초급 / 중급 / 고급 |
**근거**:
**참고**: [[02-organizing-domain-logic]], [[04-domain-logic-patterns]]
---
## 결정 2: 데이터 소스 패턴
**선택**: Table Data Gateway / Row Data Gateway / Active Record / Data Mapper
| 평가 항목 | 이 프로젝트에서 |
|----------|--------------|
| 클래스-테이블 1:1 매칭 | Yes / 대체로 / No |
| 상속 매핑 필요 | Yes / No |
| 도메인-DB 독립 진화 필요 | Yes / No |
| ORM 도구 사용 가능 | Yes / No |
**근거**:
**참고**: [[05-data-source-patterns]]
---
## 결정 3: DB 스키마
**ER Diagram**: (Mermaid erDiagram)
**클래스 ↔ 테이블 매핑**:
| 도메인 클래스 | DB 테이블 | 매핑 방식 | 특수 패턴 |
|---|---|---|---|
| | | 1:1 / 상속 / 연결테이블 | |
**참고**: [[03-mapping-to-relational-databases]]
---
## 결정 4: O-R Behavioral 패턴
| 패턴 | 사용 여부 | 구현 방식 |
|---|---|---|
| Unit of Work | Yes / No | Caller / Object / Controller Registration |
| Identity Map | Yes / No | 테이블당 / 세션당 |
| Lazy Load | Yes / No | Initialization / Proxy / Holder / Ghost |
**참고**: [[06-or-behavioral-patterns]]
---
## 결정 5: Web Presentation
| 항목 | 선택 |
|---|---|
| 프레임워크 | |
| MVC 스타일 | Page Controller / Front Controller |
| View 기술 | Template View / Transform View / Two Step View |
| Application Controller | 필요 / 불필요 |
| API 스타일 | REST / GraphQL / gRPC |
**참고**: [[08-web-presentation-patterns]]
---
## 결정 6: 동시성 전략
| 항목 | 선택 |
|---|---|
| 비즈니스 트랜잭션이 여러 요청에 걸치는가? | Yes / No |
| 충돌 가능성 | 낮음 / 높음 |
| Offline Lock 방식 | Optimistic / Pessimistic / 불필요 |
| 트랜잭션 격리 수준 | Read Committed / Repeatable Read / Serializable |
**참고**: [[11-concurrency-and-transactions]]
---
## 결정 7: 세션 상태
| 항목 | 선택 |
|---|---|
| 세션 상태가 있는가? | Yes / No |
| 저장 방식 | Client / Server / Database Session State |
| 세션 데이터 크기 | 작음 / 중간 / 큼 |
| 클러스터링 필요 | Yes / No |
---
## 결정 8: 분산
**Fowler 제1법칙: "객체를 분산하지 마라"**
| 항목 | 답변 |
|---|---|
| 단일 프로세스로 가능한가? | Yes → 분산 불필요 |
| 분리가 필요한 경계는? | 클라이언트-서버 / 앱-DB / 웹서버-앱서버 |
| Remote Facade 필요 | Yes / No |
| DTO 필요 | Yes / No |
**참고**: [[09-distribution-and-base-patterns]]