학습 목표
레이어드 아키텍처(Layered Architecture) 의 전형적인 3계층을 설명할 수 있다.
계층 간 의존 방향(위에서 아래로)과 닫힌 계층(closed layer) 개념을 설명할 수 있다.
레이어드 구조의 장단점과 언제 적합한지 판단할 수 있다.
계층 누수(layer violation)·빈약한 도메인 같은 흔한 실패 패턴을 짚을 수 있다.
문제 상황
- Controller에서 JPA Entity를 그대로 JSON으로 내려준다
- DB 스키마 변경이 API 스펙까지 번진다
- Service 없이 Controller가 SQL을 직접 호출한다
- 비즈니스 규칙이 UI 계층에 흩어진다
- "레이어 나눴는데" 패키지는
controller/service/repository인데 순환 참조가 난다- 폴더만 나눴지 의존 규칙이 없다
- 작은 CRUD 앱에 MSA를 검토한다
- 팀·트래픽 대비 구조 복잡도만 올라간다
품질 속성을 봤다. 이번 편은 가장 흔한 모놀리스 스타일—계층으로 관심사를 나누는 방법부터 잡는다.
1. 레이어드 아키텍처란
레이어드 아키텍처는 시스템을 수평 계층으로 나누고, 각 계층이 명확한 역할만 담당하게 하는 스타일이다.
- Richards/Ford 기준으로 가장 널리 쓰이는 아키텍처 스타일
- 전형적으로 모놀리스 배포 단위 안에서 계층이 공존
- 목표: 변경 영향 범위를 줄이고, 역할 분리로 이해·테스트를 쉽게

| 계층 | 역할 | 예 (Spring) |
|---|---|---|
| Presentation | 외부와 입출력, 프로토콜 변환 | Controller, REST handler, DTO |
| Business | 도메인 규칙·유스케이스 | Service, Domain model |
| Persistence | 저장·조회 구현 | Repository, DAO, ORM mapper |
- 4계층으로 API / Application / Domain / Infrastructure 를 쓰는 팀도 많다
- 핵심은 "위가 아래를 호출하고, 아래는 위를 모른다"는 단방향 의존
2. 요청이 흐르는 방식
HTTP 요청은 보통 위 계층에서 아래로 내려가고, 응답은 다시 위로 올라온다.

Client
→ Presentation (validate input, map DTO)
→ Business (apply rules, orchestrate)
→ Persistence (load/save)
→ Database
← entity / record
← domain result
← response DTO / JSON
| 단계 | 할 일 | 하지 말 것 |
|---|---|---|
| Presentation | 인증 토큰 파싱, 입력 검증, HTTP 상태 매핑 | SQL, 가격 계산 규칙 |
| Business | 주문 취소 가능 여부, 재고 차감 순서 | JSON 직렬화, 커넥션 풀 |
| Persistence | 쿼리·트랜잭션 경계 | HTTP 헤더 해석 |
- 트랜잭션 경계는 보통 Business 또는 Persistence에서 시작
- "한 유스케이스 = 한 트랜잭션"이 흔한 규칙
3. 닫힌 계층과 열린 계층
Closed layer — 계층은 바로 아래 계층만 호출할 수 있다.
- Presentation → Business → Persistence (O)
- Presentation → Persistence 직접 (X, 계층 건너뛰기)
Open layer — 특정 계층을 공유 유틸처럼 여러 곳에서 호출 허용
- 예: 공통
logging·securitycross-cutting layer - 편하지만 의존이 퍼지면 유지보수성이 떨어진다
| 모드 | 장점 | 위험 |
|---|---|---|
| Closed | 경계 명확, 변경 영향 예측 가능 | 보일러플레이트 증가 |
| Open | 중복 감소, 빠른 개발 | 계층 규칙 붕괴 |
- 팀 규칙으로 ArchUnit·모듈 경계 테스트로 강제하는 경우가 많다
4. 장단점

장점
| 항목 | 설명 |
|---|---|
| 익숙함 | Spring MVC, Rails, Django 등 기본 템플릿 |
| 역할 분리 | 신입도 "컨트롤러는 여기"로 진입 가능 |
| 점진적 변경 | 한 계층만 교체·테스트하기 상대적으로 쉬움 |
| 단일 배포 | 운영·디버깅이 MSA보다 단순한 경우 많음 |
단점
| 항목 | 설명 |
|---|---|
| 성능 | 계층 통과마다 매핑·호출 오버헤드 |
| 확장 한계 | 전체를 scale out — 특정 기능만 키우기 어려움 |
| 빈약한 도메인 | Business가 CRUD 전달만 하면 계층이 형식적 |
| 데이터 모델 지배 | DB 테이블 구조가 도메인을 끌고 가기 쉬움 |
- 품질 속성 관점: 유지보수성·테스트 용이성에는 유리한 편, 독립 확장성에는 불리
- 트래픽·팀 규모가 커지면 MSA·모듈러 모놀리스 검토로 이어진다
5. 흔한 실패 패턴
| 패턴 | 증상 | 대응 |
|---|---|---|
| Layer violation | Controller가 Repository 직접 주입 | closed layer 규칙, 린트·ArchUnit |
| Anemic domain | Service가 getter/setter만 호출 | 도메인 행동을 Entity에 모으기 |
| Leaky persistence | Entity가 API로 노출 | Response DTO 분리 |
| God service | 한 Service에 모든 유스케이스 | 유스케이스·도메인별 분할 |
| 순환 의존 | Service ↔ Service 상호 참조 | 이벤트, 인터페이스, 패키지 경계 |
// violation: presentation skips business layer
@RestController
class OrderController {
private final OrderRepository repo; // persistence directly
}
- 패키지 이름이
layer여도 import 방향이 규칙을 깨면 효과 없다
6. 언제 쓰고 언제 넘어갈까
| 적합 | 재검토 신호 |
|---|---|
| 중소 규모 CRUD·백오피스 | 팀별 독립 배포 요구 |
| 단일 제품 모놀리스 | 특정 기능만 10x 트래픽 |
| 레거시 정리 1단계 | 다른 스택으로 서비스를 나눠야 할 때 |
| 품질 우선순위가 유지보수·출시 속도 | 조직이 Conway 법칙으로 서비스 경계가 갈림 |
- 레이어드는 "최종 답"이 아니라 출발점인 경우가 많다
- 헥사고날·클린 아키텍처는 의존 방향을 더 엄격히 뒤집는 다음 단계
7. 정리
- 레이어드 아키텍처는 Presentation / Business / Persistence로 관심사를 수평 분리한다
- 의존은 위에서 아래로, 닫힌 계층이 규칙을 지킨다
- 익숙하고 운영이 단순하지만, 확장·도메인 풍부함에서는 한계가 있다
- 폴더 분리만으로 끝내지 말고 import·테스트로 경계를 지킨다
다음에 다룰 것
- 헥사고날과 클린 아키텍처
- 포트·어댑터, 의존성 역전, 도메인 중심
해당 내용은 Fundamentals of Software Architecture (Mark Richards, Neal Ford) 의 내용을 기반으로 합니다.
'소프트웨어 아키텍처' 카테고리의 다른 글
| 마이크로서비스 아키텍처 (0) | 2026.06.24 |
|---|---|
| 헥사고날과 클린 아키텍처 (3) | 2026.06.23 |
| 아키텍처 품질 속성 (0) | 2026.06.21 |
| 이해관계자와 Concern (0) | 2026.06.20 |
| 아키텍처란 무엇인가 (0) | 2026.06.19 |