"매 application 을 horizontal layer (presentation / business / persistence / data) 의 stack 으로 조직". 매 가장 흔한 default architecture — 매 simple, 매 onboarding 쉬움. 매 large-scale 에서 coupling/performance 한계 발생 → microservice/hexagonal 로 진화.
매 핵심
매 표준 layer
Presentation: UI / REST controller / GraphQL resolver. 매 input 의 validation + serialization.
Business / Service: domain logic, transaction boundary, orchestration.
Persistence / Repository: ORM, query, cache.
Data: DB, file, message broker.
매 strict vs relaxed
Strict layering: 매 layer N 은 layer N-1 만 호출 가능. 매 testability 좋음.
Relaxed: layer skip 가능 (e.g. controller → repository 직접). 매 anti-pattern 으로 간주.
매 응용
Spring Boot 의 @Controller / @Service / @Repository.
// 매 controller 는 DTO 만, service 는 domain entity 만 다룬다.publicrecordCreateOrderReq(Stringsku,intqty){}publicrecordOrderDto(Longid,Stringsku,intqty,Stringstatus){publicstaticOrderDtofrom(Ordero){returnnewOrderDto(o.getId(),o.getSku(),o.getQty(),o.getStatus().name());}}
Repository abstraction (testability)
publicinterfaceOrderRepo{Ordersave(Ordero);Optional<Order>findById(Longid);}// 매 unit test 의 Stub repository 의 inject:classStubOrderRepoimplementsOrderRepo{/* in-memory */}
매 cross-cutting (logging / tx / auth) 의 AOP
@Aspect@ComponentclassAuditAspect{@Around("@annotation(Audited)")publicObjectaudit(ProceedingJoinPointpjp)throwsThrowable{longt0=System.nanoTime();Objectresult=pjp.proceed();log.info("{} took {}ns",pjp.getSignature(),System.nanoTime()-t0);returnresult;}}
Layer 의 dependency rule (안티: upward call)
// ❌ Service 가 Controller 호출 X// ❌ Repository 가 Service 호출 X// ✅ 매 한 방향: presentation → service → persistence
매 결정 기준
상황
Approach
CRUD-heavy MVP
매 layered (default 선택)
매 complex domain logic
hexagonal / clean architecture
매 high decoupling 필요
event-driven / CQRS
매 large team / bounded context
microservice
매 simple script
매 layer X — single file
기본값: 매 small/medium app 은 3-layer (controller / service / repository) + DI + DTO boundary.