Home > Spring > πŸƒ[Spring] μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λž€ λ¬΄μ—‡μΌκΉŒμš”?

πŸƒ[Spring] μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λž€ λ¬΄μ—‡μΌκΉŒμš”?
Spring Framework

πŸƒ[Spring] μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λž€ λ¬΄μ—‡μΌκΉŒμš”?

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λŠ” 도메인 주도 섀계(Domain-Driven Design, DDD)μ—μ„œ μ‚¬μš©ν•˜λŠ” κ°œλ…μœΌλ‘œ, λ°€μ ‘ν•˜κ²Œ μ—°κ΄€λœ 객체듀을 ν•˜λ‚˜μ˜ 일관성 μžˆλŠ” λ³€κ²½ λ‹¨μœ„λ‘œ λ¬Άμ–΄ κ΄€λ¦¬ν•˜λŠ” 그룹을 μ˜λ―Έν•©λ‹ˆλ‹€.
  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λŠ” ν•˜λ‚˜μ˜ 도메인 κ°œλ…μ„ ν‘œν˜„ν•˜κ³ , 객체 κ°„μ˜ 관계λ₯Ό μΊ‘μŠν™”ν•˜μ—¬ μΌκ΄€λœ μƒνƒœλ₯Ό μœ μ§€ν•  수 있게 ν•΄μ€λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ μΊ‘μŠν™”(Encapsulation)

객체 μ§€ν–‰ ν”„λ‘œκ·Έλž˜λ°μ˜ μ€‘μš”ν•œ κ°œλ… 쀑 ν•˜λ‚˜λ‘œ, 객체의 데이터와 이λ₯Ό μ‘°μž‘ν•˜λŠ” λ©”μ„œλ“œλ₯Ό ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ λ¬Άμ–΄ μ™ΈλΆ€μ—μ„œ 직접 μ ‘κ·Όν•˜μ§€ λͺ»ν•˜λ„둝 μˆ¨κΈ°λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
μΊ‘μŠν™”(Encapsulation)λŠ” 객체 λ‚΄λΆ€μ˜ μ„ΈλΆ€ κ΅¬ν˜„μ„ 감좔고, μ™ΈλΆ€μ—λŠ” ν•„μš”ν•œ λΆ€λΆ„λ§Œ κ³΅κ°œν•˜μ—¬ 객체의 일관성을 μœ μ§€ν•˜κ³  μ½”λ“œμ˜ λ³΅μž‘μ„±μ„ μ€„μ΄λŠ” 데 도움이 λ©λ‹ˆλ‹€.

1️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)의 ꡬ성 μš”μ†Œ.

1️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트(Aggregate Root)

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)의 μ§„μž…μ μ΄ λ˜λŠ” 객체둜, μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate) μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•  수 μžˆλŠ” μœ μΌν•œ μ—”ν‹°ν‹°μž…λ‹ˆλ‹€.
    • μ™ΈλΆ€μ—μ„œλŠ” 루트 μ—”ν‹°ν‹°λ₯Ό ν†΅ν•΄μ„œλ§Œ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate) 내뢀에 μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2️⃣ λ‚΄λΆ€ 엔티티와 κ°’ 객체듀.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ λ£¨λ“œ(Aggregate Root)와 ν•¨κ»˜ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λ₯Ό κ΅¬μ„±ν•˜λŠ” 객체듀 μž…λ‹ˆλ‹€.
    • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트(Aggregate Root)κ°€ 이듀을 ν¬ν•¨ν•˜κ±°λ‚˜ μ°Έμ‘°ν•˜λ©°, μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)의 일관성을 μ±…μž„μ§‘λ‹ˆλ‹€.

2️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)의 μ˜ˆμ‹œ: μ£Όλ¬Έ μ‹œμŠ€ν…œ.

  • μ£Όλ¬Έ μ‹œμŠ€ν…œμ—μ„œ μ£Όλ¬Έ(Order)μ΄λΌλŠ” κ°œλ…μ„ μ—κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)둜 μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
    • OrderλŠ” μ£Όλ¬Έ ν•­λͺ©λ“€(OrderItem)을 ν¬ν•¨ν•˜λ©°, 이듀을 ν•œ λ‹¨μœ„λ‘œ λ¬Άμ–΄ μ£Όλ¬Έκ³Ό κ΄€λ ¨λœ λͺ¨λ“  λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.
      ```java
      @Entity
      public class Order {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;

    private LocalDateTime orderDate;
    private OrderStatus status;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List = items = new ArrayList<>();

    public void addItem(OrderItem item) {
    items.add(item);
    item.setOrder(this);
    }

    public BigDecimal calculateTotalPrice() {
    return items.stream()
    .map(OrderItem::getTotalPrice)
    .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public void completeOrder() {
    if (items.isEmpty()) {
    throw new IllegalStateException(β€œμ£Όλ¬Έ ν•­λͺ©μ΄ λΉ„μ–΄ μžˆμŠ΅λ‹ˆλ‹€.”);
    }
    this.status = OrderStatus.COMPLETED;
    }
    // getter, setter
    }
    ```

3️⃣ μ„€λͺ….

  • OrderλŠ” μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트(Aggregate Root)둜, μ£Όλ¬Έκ³Ό κ΄€λ ¨λœ λͺ¨λ“  μƒνƒœμ™€ λ™μž‘μ„ μ±…μž„μ§‘λ‹ˆλ‹€.
  • OrderItem κ°μ²΄λŠ” Order μ• κ·Έλ¦¬κ²Œμ΄νŠΈμ˜ λ‚΄λΆ€ ꡬ성 μš”μ†Œλ‘œ, μ™ΈλΆ€μ—μ„œλŠ” OrderItem에 직접 μ ‘κ·Όν•  수 μ—†μŠ΅λ‹ˆλ‹€.
  • OrderλŠ” μ£Όλ¬Έ ν•­λͺ©μ„ μΆ”κ°€ν•˜κ³  총 가격을 κ³„μ‚°ν•˜λ©°, μ£Όλ¬Έ μ™„λ£Œ μ—¬λΆ€λ₯Ό κ²°μ •ν•˜λŠ” λ‘œμ§μ„ ν¬ν•¨ν•©λ‹ˆλ‹€.

4️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)의 νŠΉμ§•κ³Ό 원칙.

1️⃣ 일관성 μœ μ§€.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λŠ” ν•˜λ‚˜μ˜ νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ μ²˜λ¦¬λ˜μ–΄, μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate) λ‚΄λΆ€μ˜ μƒνƒœμ™€ 데이터가 항상 일관성을 μœ μ§€ν•©λ‹ˆλ‹€.

2️⃣ 단일 μ§„μž…μ .

  • μ™ΈλΆ€μ—μ„œλŠ” μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트(Aggregate Root)λ₯Ό ν†΅ν•΄μ„œλ§Œ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ λ‚΄λΆ€ 객체에 μ ‘κ·Όν•  수 있으며, 루트 μ—”ν‹°ν‹°κ°€ λ‚΄λΆ€ 객체듀에 λŒ€ν•œ 관리 κΆŒν•œμ„ κ°€μ§‘λ‹ˆλ‹€.

3️⃣ 단일 μ‹λ³„μž.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate) 전체λ₯Ό κ³ μœ ν•˜κ²Œ 식별할 수 μžˆλŠ” μ‹λ³„μžλŠ” μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트(Aggregate Root)μ—λ§Œ μ‘΄μž¬ν•˜λ©°, μ‹œμŠ€ν…œ μ „μ²΄μ—μ„œ ν•΄λ‹Ή μ‹λ³„μžλ‘œ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λ₯Ό κ΅¬λΆ„ν•©λ‹ˆλ‹€.

5️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate) μ‚¬μš©μ˜ μž₯점.

1️⃣ 응집성.

  • μ—°κ΄€λœ 데이터와 둜직이 ν•œ 곳에 λͺ¨μ—¬ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λͺ…ν™•ν•˜κ²Œ μ •μ˜λ˜λ©°, μœ μ§€λ³΄μˆ˜κ°€ μš©μ΄ν•΄μ§‘λ‹ˆλ‹€.

2️⃣ 일관성 보μž₯.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ λ‹¨μœ„λ‘œ νŠΈλžœμž­μ…˜μ΄ μ²˜λ¦¬λ˜λ―€λ‘œ 데이터 일관성을 보μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3️⃣ μΊ‘μŠν™”.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ μ™ΈλΆ€μ—μ„œλŠ” λ‚΄λΆ€ 객체에 직접 μ ‘κ·Όν•  수 μ—†κ³ , μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트λ₯Ό ν†΅ν•΄μ„œλ§Œ 접근이 κ°€λŠ₯ν•˜λ―€λ‘œ 데이터와 둜직이 μ•ˆμ „ν•˜κ²Œ μΊ‘μŠν™”λ©λ‹ˆλ‹€.

5️⃣ μ• κ·Έλ¦¬κ²Œμ΄νŠΈμ˜ 예제 상황.

  • μ£Όλ¬Έ(Order) μ• κ·Έλ¦¬κ²Œμ΄νŠΈ : μ£Όλ¬Έ ν•­λͺ©(OrderItem)κ³Ό 결제 정보(PaymentInfor) 등을 ν¬ν•¨ν•˜μ—¬, ν•˜λ‚˜μ˜ μ£Όλ¬Έ λ‹¨μœ„λ‘œ 묢음.
  • μ‚¬μš©μž(User) μ• κ·Έλ¦¬κ²Œμ΄νŠΈ : μ‚¬μš©μž 정보와 μ‚¬μš©μž ν”„λ‘œν•„(Profile), μ—°λ½μ²˜(Contact) 등을 ν¬ν•¨ν•˜μ—¬ μ‚¬μš©μžμ™€ κ΄€λ ¨λœ λͺ¨λ“  정보λ₯Ό ν•˜λ‚˜λ‘œ 묢음.

6️⃣ μš”μ•½.

  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈλŠ” λ°€μ ‘ν•˜κ²Œ μ—°κ΄€λœ 객체듀을 ν•˜λ‚˜μ˜ 일관성 μžˆλŠ” λ³€κ²½ λ‹¨μœ„λ‘œ λ¬Άμ–΄ κ΄€λ¦¬ν•˜λŠ” κ°œλ…μž…λ‹ˆλ‹€.
  • μ• κ·Έλ¦¬κ²Œμ΄νŠΈ 루트λ₯Ό ν†΅ν•΄μ„œλ§Œ 접근이 κ°€λŠ₯ν•˜λ„λ‘ μΊ‘μŠν™”ν•˜μ—¬ 데이터와 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직의 응집성과 일관성을 μœ μ§€ν•˜λ©°, 객체 μ§€ν–₯적인 λ°©μ‹μœΌλ‘œ μ‹œμŠ€ν…œμ„ λͺ¨λΈλ§ν•  수 있게 ν•©λ‹ˆλ‹€.