Home > Spring > πŸƒ[Spring] '도메인 계측에 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°”λ‹€'의 μ˜λ―ΈλŠ” λ¬΄μ—‡μΈκ°€μš”?

πŸƒ[Spring] '도메인 계측에 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°”λ‹€'의 μ˜λ―ΈλŠ” λ¬΄μ—‡μΈκ°€μš”?
Spring Framework

πŸƒ[Spring] β€˜λ„λ©”μΈ 계측에 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°”λ‹€β€™μ˜ μ˜λ―ΈλŠ” λ¬΄μ—‡μΈκ°€μš”?

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심적인 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ 도메인 객체(주둜 μ—”ν‹°ν‹°λ‚˜ κ°’ 객체)에 ν¬ν•¨μ‹œμΌ°λ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
    • 도메인 객체에 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°€λ©΄, 객체 지ν–₯ μ„€κ³„μ—μ„œ 객체 슀슀둜 μžμ‹ μ˜ μƒνƒœμ™€ 행동을 κ΄€λ¦¬ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ‹œμŠ€ν…œμ„ 섀계할 수 μžˆμŠ΅λ‹ˆλ‹€.

1️⃣ 도메인 κ³„μΈ΅μ΄λž€?

  • 도메인 계측은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ ν‘œν˜„ν•˜λŠ” κ³„μΈ΅μž…λ‹ˆλ‹€.
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직과 κ·œμΉ™μ„ ν¬ν•¨ν•˜λ©°, 보톡 μ—”ν‹°ν‹°, κ°’ 객체, μ—κ·Έλ¦¬κ²Œμ΄νŠΈ λ“±μ˜ 도메인 객체둜 κ΅¬μ„±λ©λ‹ˆλ‹€.

πŸ™‹β€β™‚οΈ μ—κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)

도메인 주도 섀계(Domain-Driven Design, DDD)μ—μ„œ μ‚¬μš©ν•˜λŠ” κ°œλ…μœΌλ‘œ, λ°€μ ‘ν•˜κ²Œ μ—°κ΄€λœ 객체듀을 ν•˜λ‚˜μ˜ λ‹¨μœ„λ‘œ λ¬Άμ–΄ κ΄€λ¦¬ν•˜λŠ” κ·Έλ£Ήμž…λ‹ˆλ‹€.
μ—κ·Έλ¦¬κ²Œμ΄νŠΈ(Aggregate)λŠ” ν•˜λ‚˜μ˜ 일관성 μžˆλŠ” λ³€κ²½ λ‹¨μœ„λ‘œ 닀뀄지며, κ°μ²΄λ“€μ˜ 집합이 λ‹¨μΌν•œ 도메인 κ°œλ…μ„ ν‘œν˜„ν•  λ•Œ μ‚¬μš©λ©λ‹ˆλ‹€.

2️⃣ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 도메인 계측에 μœ„μΉ˜ν•˜λŠ” 이유.

  • λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ 도메인 계측에 λ„£λŠ” 것은 객체 지ν–₯ 원칙에 λ§žλŠ” 섀계 λ°©μ‹μž…λ‹ˆλ‹€.
    • 객체가 μžμ‹ μ˜ μƒνƒœλ₯Ό 슀슀둜 κ΄€λ¦¬ν•˜κ³ , ν•„μš”ν•œ μž‘μ—…λ„ 슀슀둜 μˆ˜ν–‰ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ„€κ³„ν•˜λ©΄ 높은 응집λ ₯을 μœ μ§€ν•  수 있으며, μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±κ³Ό μœ μ§€λ³΄μˆ˜μ„±λ„ ν–₯μƒλ©λ‹ˆλ‹€.
      • 예λ₯Ό λ“€μ–΄, OrderλΌλŠ” μ£Όλ¬Έ μ—”ν‹°ν‹°κ°€ μžˆλ‹€κ³  κ°€μ •ν•  λ•Œ, 이 엔티티에 μ£Όλ¬Έ μΆ”κ°€, 총앑 계산과 같은 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ ν¬ν•¨μ‹œν‚€λ©΄, μ„œλΉ„μŠ€ κ³„μΈ΅μ—μ„œ λ‹¨μˆœνžˆ 데이터λ₯Ό μ²˜λ¦¬ν•˜κΈ°λ³΄λ‹€ Order 객체가 μžμ‹ μ˜ 역할에 맞게 슀슀둜 행동할 수 있게 λ©λ‹ˆλ‹€.

3️⃣ 예제: λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 도메인 계측에 ν¬ν•¨λœ 경우.

  • μ•„λž˜ μ˜ˆμ œμ—μ„œλŠ” Order μ—”ν‹°ν‹°κ°€ μ£Όλ¬Έκ³Ό κ΄€λ ¨λœ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ 슀슀둜 μˆ˜ν–‰ν•˜λ„λ‘ κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
    @Entity
    public class Order {
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      private Long id;
        
      @OneToMany(mappedBy = "order", cascade = Cascade = CascadeType.ALL, orphanRemoval = true)
      private List<OrderItem> items = new ArrayList<>();
        
      private LocalDateTime orderDate;
        
      public void addItem(OrderItem item) {
          items.add(item);
          item.setOrder(this);
      }
        
      public void removeItem(OrderItem item) {
          item.remove(item);
          item.setOrder(null);
      }
        
      public BigDecimal calculateTotalPrice() {
          return items.stream()
                      .map(OrderItem::getTotalPrice)
                      .reduce(BigDecimal.ZERO, BigDecimal::add);
      }
        
      public void completeOrder() {
          if (items.isEmpty()) {
              throw new IllegalStateException("μ£Όλ¬Έ ν•­λͺ©μ΄ λΉ„μ–΄ μžˆμŠ΅λ‹ˆλ‹€.");
          }
          this.orderDate = LocalDateTime.now();
      }
      // getter, setter
    }
    

4️⃣ μ„€λͺ….

  • addItem λ©”μ„œλ“œ : Order 객체가 슀슀둜 μ£Όλ¬Έ ν•­λͺ©μ„ μΆ”κ°€ν•˜λŠ” λ‘œμ§μ„ κ°–κ³  μžˆμŠ΅λ‹ˆλ‹€.
  • calculateTotalPrice λ©”μ„œλ“œ : μ£Όλ¬Έ ν•­λͺ©λ“€μ˜ 총합을 κ³„μ‚°ν•˜λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 Order 객체에 ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  • completeOrder λ©”μ„œλ“œ : 주문을 μ™„λ£Œν•  λ•Œμ˜ λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™(예: μ£Όλ¬Έ ν•­λͺ©μ΄ μ—†μœΌλ©΄ 였λ₯˜)을 Order 객체가 슀슀둜 μ²˜λ¦¬ν•©λ‹ˆλ‹€.
    • μœ„μ™€ 같이 도메인 객체에 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ ν¬ν•¨ν•˜λ©΄, μ„œλΉ„μŠ€ κ³„μΈ΅μ—μ„œλŠ” Order 객체의 μƒνƒœλ₯Ό 직접 λ³€κ²½ν•˜κ±°λ‚˜ μ²˜λ¦¬ν•˜λŠ” λŒ€μ‹ , Order 객체에 ν•„μš”ν•œ 행동을 μš”μ²­ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

5️⃣ 도메인 계측에 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ λ„£λŠ” μž₯점.

1️⃣ 응집성 κ°•ν™”.

  • 데이터와 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 도메인 객체 내뢀에 함꼐 μœ„μΉ˜ν•˜μ—¬ μ„œλ‘œ λ°€μ ‘ν•˜κ²Œ κ΄€λ¦¬λ©λ‹ˆλ‹€.

2️⃣ μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±.

  • λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 도메인 계측에 있으면, λ‹€λ₯Έ μ„œλΉ„μŠ€μ—λ„ ν•΄λ‹Ή 객체의 κΈ°λŠ₯을 μž¬μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

3️⃣ μœ μ§€λ³΄μˆ˜ μš©μ΄μ„±.

  • λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 ν•œ 곳에 μ§‘μ€‘λ˜λ―€λ‘œ, μ½”λ“œμ˜ μœ μ§€λ³΄μˆ˜κ°€ 더 μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

4️⃣ ν’λΆ€ν•œ 도메인 λͺ¨λΈ.

  • 객체가 데이터λ₯Ό λ‹¨μˆœνžˆ λ‹΄λŠ” 것에 κ·ΈμΉ˜μ§€ μ•Šκ³  슀슀둜 의미 μžˆλŠ” 역할을 ν•˜λ©°, λͺ¨λΈ μžμ²΄κ°€ 더 직관적이고 μ΄ν•΄ν•˜κΈ° μ‰¬μ›Œμ§‘λ‹ˆλ‹€.

5️⃣ μš”μ•½.

  • β€œλ„λ©”μΈ 계측에 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 λ“€μ–΄κ°”λ‹€β€λŠ” μ˜λ―ΈλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직이 μ„œλΉ„μŠ€ κ³„μΈ΅μ΄λ‚˜ λ³„λ„μ˜ μœ ν‹Έλ¦¬ν‹° ν΄λž˜μŠ€κ°€ μ•„λ‹ˆλΌ 도메인 객체 내뢀에 μœ„μΉ˜ν•˜μ—¬ 객체가 슀슀둜 λΉ„μ¦ˆλ‹ˆμŠ€ κ·œμΉ™μ„ κ΄€λ¦¬ν•˜κ³  μˆ˜ν–‰ν•œλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
    • μ΄λŠ” 응집성과 μž¬μ‚¬μš©μ„±μ„ 높이며, 객체 지ν–₯적인 섀계 원칙에 따라 μ‹œμŠ€ν…œμ„ μ„€κ³„ν•˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€.