[Architecture] DDD

황성현·2025년 9월 19일

Architecture

목록 보기
2/3

기존 개발 방식의 문제점

  • 해당 부분은 현재 회사에서도 지독하게 느끼는 부분이다

  • DB 스키마를 먼저 기준으로 설계하여 여기에 맞춘 MVC 패턴 구축하여 "DB에 종속적임"
    (말이 MVC이지 구조만 있고 Controller에서 대부분 로직 처리 + Service로직은 join,파이프라인,비즈니스로직 붙여놓은 Query만 왔다갔다만 함.. 이외는 또 화면에서 로직 처리...)

  • 프로젝트 규모가 크고, 도메인이 복잡한 상태에서 도메인 규칙 반영이 어렵고, 중복된 코드/어디서 일어나는지 알기 어려운 버그 쉽게 발생
    ex: 비즈니스 로직이 Service 레이어에 로직 몰림


데이터 저장소에 종속적이란??

  • 기존 방식(특히 DB 주도 설계) 흐름 + JPA
  1. DB 스키마 먼저 설계 (테이블, 컬럼, PK, FK 등)
  2. 그걸 기반으로 Entity 클래스 자동 생성 (ORM 매핑)
  3. Service, Controller 코드에서 Entity = 데이터 구조체처럼 사용
  4. 비즈니스 로직도 DB 테이블의 구조에 맞춰 작성

즉, 비즈니스 로직이 DB 스키마 형태에 묶여서 설계됨.

// Account 테이블: id, user_id, balance
@Entity
@Table(name = "account")
public class AccountEntity {
    @Id Long id;
    Long userId;
    BigDecimal balance;
}

// Service 레이어
public void transfer(Long fromId, Long toId, BigDecimal amount) {
    AccountEntity from = accountRepository.findById(fromId);
    AccountEntity to = accountRepository.findById(toId);

    if (from.getBalance().compareTo(amount) < 0) { 
        throw new RuntimeException("잔액 부족");
    }

    from.setBalance(from.getBalance().subtract(amount)); // 여기
    to.setBalance(to.getBalance().add(amount));

    accountRepository.save(from);
    accountRepository.save(to);
}

※ 상태 변경(balance 감소)이 서비스에서 이뤄짐 → 여러 서비스에서 중복될 가능성 큼
※ Account라는 비즈니스 개념이 단순 데이터 컨테이너로 전락
※ 서비스 로직에서 BigDecimal 직접 다룸 (도메인 개념 없음)


  • 그럼 DDD면 어떤데??
public class Account {
    private Money balance;

    public void withdraw(Money amount) {
        if (balance.isLessThan(amount)) throw new InsufficientException();
        balance = balance.minus(amount);
    }
}

public class TransferService {
    public void transfer(Account from, Account to, Money amount) {
        from.withdraw(amount);
        to.deposit(amount);
    }
}
  1. withdraw() 안에서 도메인 규칙 캡슐화

  2. 서비스에서는 단순히 account.withdraw(amount)만 호출 → 중복 방지

  3. Money라는 값 객체를 써서 통화/단위 같은 도메인 개념까지 표현 가능

  4. JPA 말고도 다른 저장소로 바꿀 때 (예: NoSQL, 외부 API) 도메인 로직은 그대로 재사용 가능


정리 : DDD 방식은? (도메인 중심 설계)

  • 데이터 저장보다 도메인 "규칙/행위" 를 코드로 표현하는 데 집중
    ex: 커뮤니티라는 도메인 => 질문, 답변, 좋아요 등등 해야하는 규칙/행위 정의 후에 각각의 도메인 모델 구성하여 각각을 책임질 모듈 구성(Controller, Service, Domain, Repository ,FacadeSerive ,infra 등..)으로 나누어 처리
  • 도메인 로직은 Entity, Value Object, Domain Service로 분산 => Service Layer 책임 ↓
    ※ Entity에는 해당 로직이 도메인과 밀접하게 관련된 경우(상태 변경 등) / Domain Service에 여러 엔티티/VO가 함께 참여하는 로직을 작성한다
  • 인프라(DB, 메시징, UI)는 도메인에 종속되지 않고 바꿀 수 있음 => 이전 Mysql에 종속된 SQL이였는데 Oracle로 바꾸래.. => 이전 구조였으면 끔찍..
  • DB 없이 도메인 모델 자체로 유닛 테스트 구성해서 안정성 ↑

0개의 댓글