- 💡해당 게시글은 최범균님의 ‘주니어 백엔드 개발자가 반드시 알아야 할 실무 지식’을 개인 공부목적으로 메모하였습니다.
11장에서 다루는 내용
- MVC 패턴 (Model-View-Controller)
- 계층형 아키텍처 (Layered Architecture)
- DDD와 전술 패턴 (Domain-Driven Design)
- 마이크로서비스 아키텍처 (Microservices Architecture)
- 이벤트 기반 아키텍처 (Event-Driven Architecture)
- CQRS 패턴 (Command Query Responsibility Segregation)
MVC 패턴 (Model-View-Controller)
개념
- 서버 애플리케이션을 Model, View, Controller 3가지 구조로 분리하는 패턴
- Node.js의 Express.js, Spring MVC 등이 대표적인 MVC 패턴 사용 예
구조 및 역할

- 모델(Model)
- 데이터 관리, 비즈니스 로직 처리
- 뷰(View)
- 사용자에게 보여질 결과물 생성, 사용자 요청 응답
- 컨트롤러(Controller)
- 사용자 입력 처리 및 모델 제어
특징
- 컨트롤러는 사용자의 요청을 해석하여 모델을 실행하고 결과를 컨트롤러에 리턴
- 모델은 처리된 결과를 컨트롤러에 전달
- 사용자가 요청한 기능을 처리하기 위한 요청을 받아 모델이 제공하는 기능을 실행하고, 그 결과를 뷰를 통해 응답함
계층형 아키텍처 (Layered Architecture)
개념
- 오래된 패턴으로 많은 곳에서 사용됨
- 각 계층마다 특정 역할을 수행하고, 하위에 위치한 계층에만 의존하는 특징
구조

특징
- 계층형 아키텍처에서 하위 계층은 상위 계층에 대한 의존을 갖지 않음
- 모든 계층이 단방향으로 의존하도록 강제하는 경우도 있음
- 계층 1이 계층 2에만 의존하고 계층 3에는 의존하지 못함
- 비슷하게 계층 3은 계층 2와 계층 1에 의존하지 않음
웹 애플리케이션의 계층형 구조 예시

- 표현/UI 계층
- 사용자의 요청 처리 담당
- 응용 계층
- 사용 케이스 정의
- 도메인/모델 계층
- 도메인 로직 구현 (주문 취소, 사용자 비밀번호 변경, 결제 상태 변경 등)
- 인프라/영속 계층
- DB 연동이나 문자 발송 같은 구현 기술을 지원
DDD와 전술 패턴 (Domain-Driven Design)
개념
- 복잡성이 높은 도메인을 구현할 때 사용하는 설계 패턴
- DDD에서 소개하는 전술 패턴을 사용하면 도메인 영역에 도메인 로직을 집중시키는 데 도움이 됨
DDD의 도메인 모델 구성 요소
- 엔티티 (Entity)
- 고유의 식별자를 갖는 객체
- 내부 상태가 바뀌어도 식별자는 유지됨 (예: 주문번호가 다른 주문 엔티티)
- 밸류 (Value)
- 식별자 없이 개념적인 값으로 표현
- 금액, 배송 주소 등 (Value Object 권장)
- 애그리거트 (Aggregate)
- 연관된 객체들을 묶은 개념적 단위
- 도메인 모델의 관리 단위
- 리포지토리 (Repository)
- 도메인 객체 저장 및 조회 인터페이스
- 애그리거트 단위로 관리
- 도메인 서비스 (Domain Service)
- 특정 애그리거트에 속하지 않는 로직 구현
- 외부 연동 로직 등 처리
- 도메인 이벤트 (Domain Event)
- 도메인 상태 변경 시 발생하는 이벤트
- 다른 구성요소에 변경 전파 용도
DDD 활용의 장점
- 복잡한 도메인을 애그리거트 단위로 분산 관리 가능
- 관련 로직을 모아 응집도를 높임
- 복잡한 도메인의 유지보수 용이
DAO 중심 구현의 한계
- 요구사항 및 쿼리
- status가 ‘ACTIVE’인 경우에만 ‘BLOCKED’로 변경해야 함
1 2
// MemberDao.updateStatus(id)의 쿼리 update member set status = 'BLOCKED' where member_id = ? and status = 'ACTIVE'
- 일반적인 구현 방식 (DAO 중심)
- 단순히 쿼리 실행 결과(변경 행 개수)만 확인하여 성공 여부 판단
1 2 3 4 5
int cnt = mdao.updateMemberStatus(id); if (cnt == 0) { // 변경 건이 없으므로 변경 실패 처리 // 예외를 던지거나 함 }
- 문제점 (도메인 로직 부재)
- 비즈니스 규칙이 SQL(쿼리)에 숨어있음
- 코드는 단순히 데이터베이스 처리 결과만 확인할 뿐 도메인 의도를 드러내지 못함
마이크로서비스 아키텍처
개념
- 서비스를 작은 단위로 분리하고 각 서비스가 연동되는 구조
- 기존 모놀리식(Monolithic)은 하나의 애플리케이션에 모든 기능 구현
구조

모놀리식과 마이크로서비스 장단점 비교
| 구분 | 모놀리식 | 마이크로서비스 |
|---|---|---|
| 장점 | • 배포 단순 • 코드 관리 용이 • 구조 비교적 단순 • 테스트/디버깅 쉬움 |
• 독립적/지속적 배포 용이 • 성능 확장 유리 • 기술 선택 유연성 • 개발자 만족도 높음 |
| 단점 | • 규모 증가 시 개발 속도 저하 • 부분 장애가 전체 영향 • 기술 스택 변경 어려움 • 작은 변경에도 전체 재배포 필요 |
• 테스트/디버깅 어려움 • 인프라 복잡도 증가 • 커뮤니케이션 비용 증가 • 분산 모놀리식 위험 |
마이크로서비스 아키텍처 구축의 주요 개념
- 독립적 배포
- 개별 서비스의 변경, 배포, 출시가 독립적으로 가능해야 함
- 도메인을 중심으로 모델링
- 도메인 기준으로 서비스 구분
- 기능 분산 시 응집도 저하 발생
- 자신의 상태를 가짐
- DB 공유 금지
- 타 서비스 데이터는 API 등을 통해 접근
- 크기
- 정해진 기준 없음
- 조직이 감당 가능한 수준과 경계 정의에 집중
- 유연함
- 비용 투입 대비 유연성(기술, 확장, 견고함) 확보 필요
- 아키텍처 조율을 맞춤
- 조직 구조가 아키텍처에 영향을 줌
- 비즈니스 도메인이 주도하는 아키텍처 지향
- MSA가 무조건 정답은 아니며, 모놀리식이 잘못된 아키텍처도 아님
- 코드 품질이 낮은 상태에서 무리하게 MSA로 분리하면 오히려 복잡도만 증가할 수 있음
- 모놀리식도 모듈 간 결합도를 낮추고 컴포넌트를 잘 나누면 충분히 확장 가능함
이벤트 기반 아키텍처 (Event-Driven Architecture)
개념
- 시스템 간 통신에 이벤트를 사용
- 이벤트
- 과거에 발생한 사실
- ex) ‘주문 수행함’, ‘인증 실패함’
구조 및 구성 요소

- 이벤트 생산자
- 이벤트를 생성하여 브로커에 전달
- 이벤트 소비자
- 이벤트를 받아 적절히 반응
- 이벤트 브로커(또는 라우터)
- 변경된 데이터를 다른 시스템에 전달하는 중개자 역할
이벤트 브로커와 단일 전달 공급원
-
이벤트 브로커를 단일 전달 공급원으로 사용 가능
- 카프카의 메시지 영구 저장 특징 활용
- 이벤트 기록만으로 시스템 상태 변화 추적 가능 (이벤트 소싱 패턴)
특징
- 이벤트는 메시지의 한 형태
- 대표적인 브로커 기술은 Kafka, RabbitMQ
- 생산자와 소비자 간 결합도 감소함
CQRS 패턴 (Command Query Responsibility Segregation)
개념
- 명령(Command) 모델과 조회(Query) 모델을 분리
- 각 기능에 최적화된 모델 구현 가능
- 상호 영향 최소화
CQRS 구조

주요 특징
- 조회와 명령의 분리
- 복잡한 시스템에서는 상태 변경과 조회의 모델이 달라짐
- 단일 모델로는 복잡도 증가 및 유지보수 어려움
- ex) 주문 생성 시 여러 참조 데이터 필요
- 모델의 차이
- 독립적인 조회 성능 향상 가능
- 조회 전용 캐시나 DB 활용 용이
- 단점
- 구현해야 할 코드량 증가
- 단순 모델 적용 시 이점보다 작업량이 클 수 있음
- 모델이 복잡할수록 효과적
- 적용 시기
- 구현 기술 복잡도 증가 고려
- 조회 전용 DB 도입 시 데이터 동기화 이슈 해결 필요
배운 점
- MVC 패턴
- Model-View-Controller로 책임을 분리하여 유지보수성 향상
- 계층형 아키텍처
- 각 계층이 특정 역할을 수행하며 하위 계층에만 의존하여 결합도 감소
- DDD와 전술 패턴
- 도메인 로직을 체계적으로 구현하여 비즈니스 복잡성 관리
- 마이크로서비스 아키텍처
- 서비스를 작은 단위로 분리하여 독립적인 배포와 확장 가능
- 이벤트 기반 아키텍처
- 이벤트를 통한 시스템 간 비동기 통신으로 결합도 최소화
- CQRS 패턴
- 명령과 조회 모델을 분리하여 각각의 성능과 확장성 최적화
적용 방안
- 아키텍처 선택 기준
- 프로젝트 규모, 팀 구성, 비즈니스 요구사항에 따라 적절한 패턴 선택해야함
- 초기에는 모놀리식으로 시작하고 필요시 마이크로서비스로 전환 고려하는 것도 괜찮음
- 도메인 로직 강화
- 비즈니스 로직은 도메인 계층에 집중시켜 응집도 높임
- 서비스 계층은 도메인 객체 간의 흐름만 제어하도록 설계
- 이벤트 활용
- 시스템 간 강결합을 피하기 위해 이벤트 기반 통신 도입 고려
- Kafka 등의 메시지 브로커를 활용하여 안정적인 메시지 처리
- 성능 최적화
- 조회 성능이 중요한 경우 CQRS 도입 검토
- 캐싱 전략과 읽기 전용 DB 활용