본문 바로가기
Project: algo-analyzer/DES

[JAVA] MVC+DDD

by odaebum 2025. 5. 12.
728x90

MVC + DDD

┌─────────────────────────────┐
│ Presentation Layer (MVC)    │   ← Spring MVC의 @Controller, @RestController
│ • View / API Endpoint       │
└────────────┬────────────────┘
             │ calls
┌────────────▼────────────────┐
│ Application Layer           │   ← Use Case / Application Service
│ • 트랜잭션 경계 관리
│ • 도메인 모델 orchestration
└────────────┬────────────────┘
             │ uses
┌────────────▼────────────────┐
│ Domain Layer (DDD)          │   ← Aggregate, Entity, Value Object, Domain Service
│ • 핵심 비즈니스 로직
└────────────┬────────────────┘
             │ persists via
┌────────────▼────────────────┐
│ Infrastructure Layer        │   ← Repository 구현, 외부 API 연동
│ • DB, 메시징, 캐시, 파일 I/O
└─────────────────────────────┘


Presentation Layer (MVC)

  • 목적
    • 사용자 요청(HTTP, WebSocket 등)을 받아 Controller에서 처리 → Service 호출 → View나 JSON/XML 응답 생성
    • 화면(UI)과 서비스 로직의 분리
  • 주요 구성 요소
    • Controller (@Controller / @RestController)
      • 엔드포인트 정의 (@GetMapping, @PostMapping 등)
      • 입력 파라미터 바인딩, 예외 핸들링
    • DTO
      • Request/Response 전용 객체
      • Validation(@Valid) 적용 위치
    • View Resolver / Message Converter
      • Thymeleaf, Mustache, JSON 변환(Gson, Jackson) 등
  • 원칙
    • Thin Controller: 최대한 로직을 두지 않고 Application Layer로 위임
    • Validation: Controller 레벨에서 입력 검증 후 Service 진입
    • Exception Handling: @ControllerAdvice를 이용해 전역 예외 처리

Application Layer (Use Case)

  • 목적
    • 트랜잭션 경계 설정 및 Use Case orchestration
    • 여러 도메인 객체 협업 → 업무 흐름(시나리오) 구현
  • 주요 구성 요소
    • Application Service (@Service)
      • @Transactional 설정
      • 도메인 객체 조회/저장, 도메인 서비스 호출
      • 외부 API 호출도 여기서 어댑터(Port) 통해 수행
    • Port / Input–Output Port (Hexagonal Architecture)
      • 애플리케이션이 외부(인프라, UI)와 소통할 인터페이스 정의
      • 예: ProblemFetchPort, AnalysisResultPort
    • DTO (Use Case 요청/응답 전용)
      • Presentation DTO와 구분해 쓰거나, 동일 DTO를 재활용
  • 원칙
    • Use Case 중심: 하나의 메서드가 하나의 시나리오(Use Case)를 완결
    • Side Effect 최소화: 외부 호출·영속화는 Port 인터페이스로 추상화
    • 트랜잭션 분리: 필요한 범위에서만 @Transactional 지정

Domain Layer (DDD)

  • 목적
    • 비즈니스 규칙과 도메인 개념을 캡슐화
    • 엔티티, 값 객체, 애그리거트, 도메인 서비스로 비즈니스 로직 구현
  • 주요 구성 요소
    • Entity: 고유 식별자를 가진 객체 (Problem, User)
    • Value Object: 식별자 없이 속성으로만 구분 (Money, Coordinates)
    • Aggregate: 관련 Entity/Value Object 묶음, 불변식(Invariant) 관리
    • Domain Service: 엔티티에 두기 애매한 비즈니스 로직
    • Repository (Interface)
    • public interface ProblemRepository { Optional<Problem> findById(ProblemId id); Problem save(Problem problem); }
  • 원칙
    • 프레임워크 의존 최소화(순수 Java)
    • 유비쿼터스 언어 기반 네이밍
    • 불변식(Invariant) 보존

Infrastructure Layer

  • 목적
    • 도메인 레이어가 정의한 Repository/Port 인터페이스 구현
    • DB, 메시징, 캐시, 외부 API 등 구체 기술 담당
  • 주요 구성 요소
    • Repository 구현체 (@Repository)
    • @Repository public class JpaProblemRepository implements ProblemRepository { private final SpringDataProblemJpaRepository jpaRepo; // toDomain(), fromDomain() 매핑 로직 포함 }
    • Client/Adapter
      • REST API 클라이언트, 메시지 브로커 연동, 파일 I/O
      • DTO ↔ 도메인 모델 변환
    • Configuration
      • DataSource, MongoTemplate, RedisTemplate
      • 트랜잭션 매니저, 모니터링·보안 설정
  • 원칙
    • 오직 기술 스택에만 의존
    • 변경 시 이 레이어만 수정 (예: JPA → MyBatis)

이렇게 네 개 레이어를 분리하면, 각 책임이 명확해지고 유지보수·테스트·기술 교체가 모두 쉬워집니다.

728x90