inblog logo
|
LifeLog, DevLog
    Tech

    도메인 모델링

    의미, 구성 요소, 예시
    KYJTHEYJ's avatar
    KYJTHEYJ
    Jan 08, 2026
    도메인 모델링
    Contents
    도메인 모델도메인 모델의 구성 요소유의할 사항들

    도메인 모델

    비즈니스 이해를 위한 특정 비즈니스 영역의 개념, 규칙, 정의를 객체 모델로 표현한 것

    도메인 모델의 구성 요소

    Ubiquitous Language

    기획자, 개발자, 도메인 전문가가 공용으로 사용하는 언어

    Entity

    식별자를 지닌 도메인 객체

    // 엔티티
    public class Event { // 도메인 객체
    	// 식별자
    	private Long eventId; // 이벤트 마다 배정된 구별 아이디
    	private String title;
    	private EventPeriod period;
    
    	@OneToMany
    	private EventPrize prize;
    	...
    }
    
    // 엔티티
    public class EventPrize { // 도메인 객체
    	// 식별자
    	private Long eventPrizeId; // 이벤트 상품마다 배정된 구별 아이디
    	private String name;
    	...
    }
    
    // 엔티티
    public class Participate { // 도메인 객체
    	// 식별자
    	private Long participateId; // 참석 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	private LocalDateTime participateDt; // 참석 일자
    	...
    }
    
    // 엔티티
    public class Winner { // 도메인 객체
    	// 식별자
    	private Long winnerId; // 당첨 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	...
    }

    Value Object

    식별자 없이 속성으로 구별되는 불변의 객체, 엔티티의 일부로 포함된다
    @Embeddable → 이 클래스는 다른 클래스 내에 필드로 포함될 수 있다
    @Embedded → 포함 되었다

    // 엔티티
    public class Event {
    	// 식별자
    	private Long eventId; // 이벤트 마다 배정된 구별 아이디
    	private String title; // 이벤트 제목 (그냥 값)
    	
    	@OneToMany
    	private EventPrize prize;
    
    	@Embedded
    	private EventPeriod period; // 이벤트의 기간
    }
    
    // 엔티티
    public class EventPrize { // 도메인 객체
    	// 식별자
    	private Long eventPrizeId; // 이벤트 상품마다 배정된 구별 아이디
    	private String name;
    	...
    }
    
    // 엔티티
    public class Participate { // 도메인 객체
    	// 식별자
    	private Long participateId; // 참석 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	private LocalDateTime participateDt; // 참석 일자
    	...
    }
    
    // 엔티티
    public class Winner { // 도메인 객체
    	// 식별자
    	private Long winnerId; // 당첨 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	...
    }
    
    // 값 객체
    @Embeddable
    public class EventPeriod {
    	// 불변
    	private LocalDateTime StartDt;
    	private LocalDateTime EndDt;
    }

    Aggregate

    관련 객체를 하나의 단위로 묶은 것
    외부에서는 Aggregate 의 Root 로 접근 (트랜잭션을 지녀야 한다)

    public class Event { // 도메인 객체
    	// 식별자
    	private Long eventId; // 이벤트 마다 배정된 구별 아이디
    	private String title;
    
    	@OneToMany
    	private EventPrize prize;
    
    	@Embedded
    	private EventPeriod period;
    	...
    }
    
    // 엔티티
    public class EventPrize { // 도메인 객체
    	// 식별자
    	private Long eventPrizeId; // 이벤트 상품마다 배정된 구별 아이디
    	private String name;
    	...
    }
    
    @Embeddable
    public class EventPeriod {
    	// 불변
    	private LocalDateTime StartDt;
    	private LocalDateTime EndDt;
    }
    
    // 이 전체가 하나의 Event 애그리거트
    // 루트는 Event
    
    // EventPrzie 는 Event 를 통해서 접근한다
    // EventPeriod 는 Event 를 통해서 접근한다

    Bounded Context

    어떠한 하위 개념이 어떤 도메인과 의미가 충돌하지 않도록 정하는 경계

    // "참여" 라는 행위가 이벤트에서 참여한다 라는 의미로 쓰이나
    // 다른 도메인 에서 다른 의미로 사용될 수 있으니 경계를 지어 구분해야함
    
    // 결제의 "상품", 재고의 "상품", 주문의 "상품"은 다른 의미 일수도 있음
    
    // 이럴 경우 유비쿼터스 언어는 일관되게 한 상태로 도메인과의 경계를 지어야하는데
    // 여기서 이 경계를 Bounded Context 라고 한다

    Domain Service

    특정 엔티티에 속하지 않는 비즈니스 로직

    // 엔티티
    public class Event { // 도메인 객체
    	// 식별자
    	private Long eventId; // 이벤트 마다 배정된 구별 아이디
    	private String title;
    	private EventPeriod period;
    	...
    }
    
    // 엔티티
    public class Participate { // 도메인 객체
    	// 식별자
    	private Long participateId; // 참석 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	private LocalDateTime participateDt; // 참석 일자
    	...
    }
    
    // 엔티티
    public class Winner { // 도메인 객체
    	// 식별자
    	private Long winnerId; // 당첨 번호
    	private Long userId; // 회원 식별자
    	private Long eventId; // 이벤트 식별자
    	...
    }
    
    // 이벤트 추첨 로직을 만들어야 한다고 하면 
    // Event 에 종속되어야 할지
    // Participate 에 종속되어야 할지
    // Winner 에 종속되어야 할지 모든 것에 연관이 있으니 
    // 따로 서비스에 비즈니스 로직을 만들어야함

    Repository

    Aggregate를 저장하고 조회하는 인터페이스

    public interface EventRepository { // 도메인 객체
    	Event saveEvent(Event event);
    
    	Event getEvent(Long eventId);
    
    	List<Event> getAllEvent();
    
    	void deleteEvent(Long eventId);
    }

    유의할 사항들

    • 애그리거트와 엔티티의 구별

    public class Event { // 도메인 객체
    	// 식별자
    	private Long eventId; // 이벤트 마다 배정된 구별 아이디
    	private String title;
    
    	@OneToMany
    	private EventPrize prize;
    
    	@Embedded
    	private EventPeriod period;
    	...
    }
    
    // 엔티티
    public class EventPrize { // 도메인 객체
    	// 식별자
    	private Long eventPrizeId; // 이벤트 상품마다 배정된 구별 아이디
    	private String name;
    	...
    }
    
    // 값 객체
    @Embeddable
    public class EventPeriod {
    	// 불변
    	private LocalDateTime StartDt;
    	private LocalDateTime EndDt;
    }
    
    // Event, EventPrzie -> 엔티티
    // Event + EventPrzie + EventPeriod -> 애그리거트
    // EventPeriod -> 값 객체

    • 도메인 모델링에서 표현하는 것의 정의

      • 연관 관계를 어떻게 생각해야하는 것이 좋을까?

        • 1:N 관계로 생각하면 폭 넓게 도메인 객체를 생각할 수 있을 것
          하지만 구현점이 너무 어렵지 않을까

        • N:1 관계로 생각하면 구현점을 작게 나눌 수 있지만
          구현할 것들이 많아 지게 될 것

    Share article
    Contents
    도메인 모델도메인 모델의 구성 요소유의할 사항들

    LifeLog, DevLog - https://github.com/KYJTHEYJ

    RSS·Powered by Inblog