소프트웨어 시스템은 여러 **정책(Policy)**의 집합이다. 정책들은 서로 다른 **수준(Level)**에 존재하며, 의존성은 수준의 방향으로 흘러야 한다.
정책(Policy)이란?
정책은 시스템의 행동을 기술하는 것이다.
flowchart LR
subgraph Policies [정책의 예]
P1[입력을 읽는 방법]
P2[데이터를 변환하는 방법]
P3[출력을 쓰는 방법]
end
정책의 예시
| 정책 유형 | 예시 |
|---|---|
| 입력 정책 | 키보드 읽기, 파일 읽기, HTTP 요청 수신 |
| 변환 정책 | 암호화, 포맷 변환, 비즈니스 규칙 적용 |
| 출력 정책 | 화면 출력, 파일 저장, HTTP 응답 전송 |
| |
수준(Level)이란?
입력과 출력으로부터의 거리가 수준을 결정한다.
flowchart LR
INPUT[입력 장치
저수준]
LOW1[입력 처리
저수준]
MID[비즈니스 로직
중간]
HIGH[핵심 규칙
고수준]
MID2[출력 처리
중간]
LOW2[출력 장치
저수준]
OUTPUT[화면/파일
저수준]
INPUT --> LOW1 --> MID --> HIGH
HIGH --> MID2 --> LOW2 --> OUTPUT
수준의 정의
| 수준 | 특징 | 예시 |
|---|---|---|
| 고수준 | 입출력에서 멀리 떨어짐 | 핵심 비즈니스 규칙 |
| 중간 수준 | 변환과 처리 | 유스케이스 |
| 저수준 | 입출력에 가까움 | UI, DB, 외부 API |
왜 거리가 중요한가?
“입력과 출력에 가까울수록 변경 가능성이 높다. 멀수록 안정적이다.”
flowchart TB
subgraph ChangeFrequency [변경 빈도]
UI[UI - 자주 변경]
UC[유스케이스 - 가끔 변경]
BR[비즈니스 규칙 - 드물게 변경]
end
UI -->|더 안정| UC -->|더 안정| BR
의존성 방향
의존성은 수준이 낮은 곳에서 수준이 높은 곳으로 흘러야 한다.
flowchart TB
subgraph Good [올바른 의존성 방향]
direction TB
L1[저수준: Console Reader]
L2[저수준: Console Writer]
H[고수준: Encrypter]
L1 --> H
L2 --> H
end
잘못된 의존성
flowchart TB
subgraph Bad [잘못된 의존성 방향]
direction TB
H2[고수준: Encrypter]
L3[저수준: Console Reader]
L4[저수준: Console Writer]
H2 --> L3
H2 --> L4
end
고수준 정책이 저수준 정책을 모르게 해야 한다.
예시: 암호화 프로그램
마틴은 간단한 암호화 프로그램을 예로 들어 설명한다.
요구사항
- 문자를 읽어서
- 암호화하고
- 암호화된 문자를 출력
잘못된 설계
| |
올바른 설계
| |
조립 (의존성 주입)
| |
수준과 변경
flowchart TB
subgraph Levels [수준별 변경 특성]
HIGH[고수준
비즈니스 규칙
변경 적음]
MID[중간 수준
유스케이스
가끔 변경]
LOW[저수준
입출력
자주 변경]
end
LOW -->|의존| MID
MID -->|의존| HIGH
| 수준 | 변경 빈도 | 변경 이유 |
|---|---|---|
| 고수준 | 드물게 | 비즈니스 요구사항 변경 |
| 중간 수준 | 가끔 | 새로운 기능 추가 |
| 저수준 | 자주 | 기술 변경, UI 개선 |
왜 고수준으로 의존해야 하는가?
| |
아키텍처에 적용
flowchart TB
subgraph Architecture [클린 아키텍처의 수준]
ENT[Entities
가장 고수준]
UC[Use Cases
고수준]
CTRL[Controllers
중간]
GW[Gateways
저수준]
DB[(DB)
가장 저수준]
end
DB --> GW --> CTRL --> UC --> ENT
핵심 요약
| 원칙 | 설명 |
|---|---|
| 수준의 정의 | 입출력으로부터의 거리 |
| 의존성 방향 | 저수준 → 고수준 |
| 고수준의 특징 | 안정적, 변경 적음 |
| 저수준의 특징 | 불안정, 변경 많음 |
“수준이 높을수록 변경이 적고, 수준이 낮을수록 변경이 많다. 따라서 의존성은 고수준을 향해야 한다.” — Robert C. Martin
flowchart LR
CHANGE[변경] --> LOW[저수준]
LOW -->|의존| HIGH[고수준]
HIGH -.->|영향 없음| CHANGE
안정적인 고수준 정책이 불안정한 저수준 정책을 모르게 하면, 저수준의 변경이 고수준에 영향을 주지 않는다.
![Featured image of post [Clean Architecture] 29. 정책과 수준](/post/cleanarchitecture/29-policy-and-level-high-level-dependency/wordcloud_hu_4f680f4db281ae35.png)
![[Clean Architecture] 27. 경계: 선 긋기와 플러그인 아키텍처](/post/cleanarchitecture/27-boundaries-drawing-lines-plugin-architecture/wordcloud_hu_fc36676e3ba6ff35.png)
![[Clean Architecture] 28. 경계 해부학: 모놀리스에서 서비스까지](/post/cleanarchitecture/28-boundary-anatomy-monolith-to-services/wordcloud_hu_cbdfd79295eecd4.png)
![[Clean Architecture] 29. 정책과 수준](/post/cleanarchitecture/29-policy-and-level-high-level-dependency/wordcloud_hu_e48501593aac0e11.png)
![[Clean Architecture] 30. 업무 규칙: 엔티티와 유스케이스](/post/cleanarchitecture/30-business-rules-entities-usecases/wordcloud_hu_9cdcde1a7829faa5.png)
![[Clean Architecture] 31. 소리치는 아키텍처](/post/cleanarchitecture/31-screaming-architecture-intent-driven-structure/wordcloud_hu_dc3a91882497fd3e.png)
![[Clean Architecture] 19. DIP: 의존성 역전 원칙](/post/cleanarchitecture/19-dip-dependency-inversion-principle/wordcloud_hu_5f6ac41d048e618a.png)
![[Clean Architecture] 23. 컴포넌트 결합: ADP, SDP, SAP](/post/cleanarchitecture/23-component-coupling-adp-sdp-sap/wordcloud_hu_c4603e13dc344ade.png)
![[Clean Architecture] 25. 아키텍처란?](/post/cleanarchitecture/25-what-is-architecture-system-lifecycle/wordcloud_hu_e36846752c8a10ed.png)
![[Clean Architecture] 40. 세부사항 서론](/post/cleanarchitecture/40-details-introduction-interchangeable-parts/wordcloud_hu_6d3c7574feb4b30a.png)