π[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οΈβ£ μμ½.
- βλλ©μΈ κ³μΈ΅μ λΉμ¦λμ€ λ‘μ§μ΄ λ€μ΄κ°λ€βλ μλ―Έλ μ ν리μΌμ΄μ
μ λΉμ¦λμ€ λ‘μ§μ΄ μλΉμ€ κ³μΈ΅μ΄λ λ³λμ μ νΈλ¦¬ν° ν΄λμ€κ° μλλΌ λλ©μΈ κ°μ²΄ λ΄λΆμ μμΉνμ¬ κ°μ²΄κ° μ€μ€λ‘ λΉμ¦λμ€ κ·μΉμ κ΄λ¦¬νκ³ μννλ€λ κ²μ μλ―Έν©λλ€.
- μ΄λ μμ§μ±κ³Ό μ¬μ¬μ©μ±μ λμ΄λ©°, κ°μ²΄ μ§ν₯μ μΈ μ€κ³ μμΉμ λ°λΌ μμ€ν μ μ€κ³νλ λ°©μμ λλ€.