๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ
๊ฐ์
์ํํธ์จ์ด ์ํคํ ์ฒ์์ ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ ์ค์ํ ์ค๊ณ ์์น ์ค ํ๋์ด๋ค. ์ด ์์น์ ํด๋ฆฐ ์ํคํ ์ฒ์ ํต์ฌ ๊ฐ๋ ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฉฐ, ๋๋ฉ์ธ ๋ก์ง๊ณผ ์์์ฑ ๊ณ์ธต ๊ฐ์ ์์กด์ฑ์ ์ต์ํํ์ฌ ์์คํ ์ ์ ์ง ๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์ด๋ ๋ฐ ๋ชฉ์ ์ด ์๋ค.
์ด๋ฒ ๊ฒ์๊ธ์์๋ ์ด๋ฌํ ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ์ ์ฐจ์ด์ ์ ๋ํด ์์๋ณด๊ณ , ์ด ๋์ ๋ถ๋ฆฌํจ์ผ๋ก์จ ์ป์ ์ ์๋ ์ด์ ๊ณผ ์ฃผ์ํด์ผ ํ ์ ๊ทธ๋ฆฌ๊ณ ์ธ์ ๋ถ๋ฆฌํ๋ฉด ์ข์์ง์ ๋ํด ์ ๋ฆฌํ๋ค.
๋๋ฉ์ธ ์ํฐํฐ
๋จผ์ ๋๋ฉ์ธ ์ํฐํฐ์ ๊ฐ๋ ๋ถํฐ ์ดํด๋ณด๋ฉด ๋๋ฉ์ธ ์ํฐํฐ๋ ๋น์ฆ๋์ค ๋๋ฉ์ธ ๋ด์ ๊ฐ๋ ์ ๋ํ๋ด๋ ๊ฐ์ฒด๋ก, ์ ์์๊ฑฐ๋ ์์คํ ์์๋ 'Order', 'Customer', 'Product'๋ฑ์ด ๋๋ฉ์ธ ์ํฐํฐ๊ฐ ๋ ์ ์๋ค. ๋ค์์ ๊ฐ๋จํ ์์ ์ฝ๋์ด๋ค.
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Order {
private String orderId;
private Address shippingAddress;
private List<OrderItem> items;
private OrderStatus status;
public Order(String orderId, Address shippingAddress, List<OrderItem> items) {
this.orderId = orderId;
this.shippingAddress = shippingAddress;
this.items = new ArrayList<>(items);
this.status = OrderStatus.PENDING;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order order = (Order) o;
return orderId.equals(order.orderId);
}
@Override
public int hashCode() {
return Objects.hash(orderId);
}
}
import java.util.Objects;
public class Address {
private final String street;
private final String city;
private final String zipcode;
public Address(String street, String city, String zipcode) {
this.street = street;
this.city = city;
this.zipcode = zipcode;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return Objects.equals(street, address.street) && Objects.equals(city, address.city) && Objects.equals(zipcode, address.zipcode);
}
@Override
public int hashCode() {
return Objects.hash(street, city, zipcode);
}
}
์ ์ฝ๋์์ Address๋ Value Object๋ก, ์ํฐํฐ์ ๋ฌ๋ฆฌ ๊ณ ์ ์๋ณ์๊ฐ ์์ผ๋ฉฐ ์์ฑ๋ง์ผ๋ก ๋์ผ์ฑ์ ํ๋จํ๋ค. ์ด๋ ๋ถ๋ณ(immutable) ๊ฐ์ฒด๋ก ์ฃผ๋ก ๊ฐ ํ์ ์ ํํํ๋ ๋ฐ ์ฌ์ฉ๋๋ค. ๋ฐ๋ฉด Order๋ ๊ณ ์ ํ ์๋ณ์์ธ orderId๋ฅผ ๊ฐ์ง๋ฉฐ, ์ด ์๋ณ์๋ฅผ ํตํด ์ํฐํฐ ๊ฐ์ ๋์ผ์ฑ์ ๋ณด์ฅํ๋ค. ์ด๋ฅผ ์ ๋ณด์ฌ์ฃผ๋ ๋ถ๋ถ์ด equals์ hashCode ๋ฉ์๋์ ๊ตฌํ ๋ถ๋ถ์ธ๋ฐ, ์ํฐํฐ๋ ID๋ง ๋น๊ตํ๊ณ , VO๋ ๋ชจ๋ ์์ฑ์ ๋น๊ตํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ import ๋ถ๋ถ์ ๋ณด๋ฉด ์์ POJO๋ก ๊ตฌ์ฑ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์์์ฑ ์ํฐํฐ
๊ทธ๋ ๋ค๋ฉด ์์์ฑ ์ํฐํฐ๋ ์ด๋จ๊น? ์์์ฑ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๊ณ ORM์ ํตํด ๊ด๋ฆฌ๋๋ ๊ฐ์ฒด์ด๋ค. ์์์ฑ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ๊ณผ 1:1๋ก ๋งคํ๋๋ฉฐ ์ฃผ๋ก JPA ๊ฐ์ ORM ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ๋ค. ๋ค์์ ๊ฐ๋จํ ์์์ฑ ์ํฐํฐ ์์์ด๋ค.
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import jakarta.persistence.*;
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderId;
@Embedded
private Address shippingAddress;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "order_id")
private List<OrderItem> items;
@Enumerated(EnumType.STRING)
private OrderStatus status;
protected Order(){
}
public Order(Address shippingAddress, List<OrderItem> items) {
this.shippingAddress = shippingAddress;
this.items = new ArrayList<>(items);
this.status = OrderStatus.PENDING;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order order = (Order) o;
return orderId.equals(order.orderId);
}
@Override
public int hashCode() {
return Objects.hash(orderId);
}
}
// ์ดํ Address ๋ฑ ์๋ต
์์์ฑ ์ํฐํฐ๋ ์์์ฑ์ ์ํ ์ด๋ ธํ ์ด์ ๋ค์ด ๋ถ์ด ์๋ค๋ ์ ์์ ๋๋ฉ์ธ ์ํฐํฐ์ ๋ค๋ฅด๋ค. Order ์ํฐํฐ๋ @Entity ์ด๋ ธํ ์ด์ ์ผ๋ก ์ง์ ๋์ด ์์ผ๋ฉฐ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ๊ณผ ๋งคํ๋๋ค. Address๋ @Embeddable ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ๋ด์ฅ ํ์ ์ผ๋ก ์ ์๋์๊ณ , OrderItem์ Order์ @OneToMany ๊ด๊ณ๋ฅผ ๊ฐ๋๋ค.
๋๋ฉ์ธ ์ํฐํฐ๋ ์ฃผ๋ก ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํ๊ณ ์์ด ๋น์ฆ๋์ค ๊ท์น๊ณผ ๋๋ฉ์ธ ๊ฐ๋ ์ ํํํ๋ ๋ฐ ์ค์ ์ ๋๋ค. ๋ฐ๋ฉด ์์์ฑ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํธ์์ฉ์ ์ํด ์ค๊ณ๋๋ฉฐ, ๋ฐ์ดํฐ ์ ์ฅ๊ณผ ์กฐํ์ ์ค์ ์ ๋๋ค. ํ์ฌ ์์์์๋ ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ์ ํ๋๋ฅผ ์ ๋ถ ๋์ผํ๊ฒ ์์ฑํ์ง๋ง, ๋ณดํต์ ๊ฒฝ์ฐ ๋๋ฉ์ธ ์ํฐํฐ๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๊ณ ์์ด ํ๋์ ๋ฉ์๋๊ฐ ๋ ๋ณต์กํด์ง ์ ์๋ค.
์๋ฅผ ๋ค์ด ๋๋ฉ์ธ ์ํฐํฐ์์๋ ์ฃผ๋ฌธ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๋น์ฆ๋์ค ๋ก์ง์ด ํฌํจ๋ ์ ์๋ค.
public void completeOrder() {
if (this.status != OrderStatus.PENDING) {
throw new IllegalStateException("Order cannot be completed");
}
this.status = OrderStatus.COMPLETED;
}
๊ทธ๋ฌ๋ ์์์ฑ ์ํฐํฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ ๊ตฌ์กฐ์ ์ผ์นํ๋ ํ๋์ ๋จ์ํ CRUD ์์ ์ ํ์ํ ๋ฉ์๋๋ง์ ๊ฐ์ง๋ฏ๋ก, ๋น์ฆ๋์ค ๋ก์ง๋ณด๋ค๋ ๋ฐ์ดํฐ ์ ์ฅ๊ณผ ์กฐํ์ ๋ ์ง์คํ๋ค. ๋ฌผ๋ก , ๋๋ฉ์ธ ์ํฐํฐ๋ฅผ ์ฌ์ฉํ์ง ์๋ ๊ฒฝ์ฐ์๋ ์ด๋ฌํ ๋น์ฆ๋์ค ๋ก์ง์ด ์์์ฑ ์ํฐํฐ์ ์์ฑ๋ ์ ์๋ค.
์ ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ๋ฅผ ๋ถ๋ฆฌํ๋๊ฐ?
์์ ์์ ์ฝ๋์์ ๋ดค๋ฏ์ด ๊ตณ์ด ์ด ๋์ ๋ถ๋ฆฌํ์ง ์๊ณ ์์์ฑ ์ํฐํฐ๋ฅผ ๋๋ฉ์ธ ์ํฐํฐ๋ก ์ฌ์ฉํด๋ ๋๋ค. ๊ทธ๋ฐ๋ฐ๋ ์ ๊ตณ์ด ์ด ๋์ ๋ถ๋ฆฌํ๋ ๊ฒ์ผ๊น?
๋จผ์ , ํด๋ฆฐ ์ํคํ ์ฒ์ ์์น์ ์ดํด๋ณด์. ํด๋ฆฐ ์ํคํ ์ฒ์์๋ ๋ชจ๋ ์์กด์ฑ์ด ๋๋ฉ์ธ ๋ก์ง์ ํฅํด ์์ชฝ ๋ฐฉํฅ์ผ๋ก ํฅํ๋ค. ์ด ์ํคํ ์ฒ๋ ๋์ฌ์ ๊ตฌ์กฐ๋ก ๊ณ์ธต๋ค์ด ๋๋ฌ์ธ์ฌ ์์ผ๋ฉฐ, ๊ฐ์ฅ ์ค์ํ ๊ท์น์ ๊ณ์ธต ๊ฐ์ ๋ชจ๋ ์์กด์ฑ์ด ์์ชฝ์ผ๋ก ํฅํด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
ํด๋ฆฐ ์ํคํ ์ฒ์ ํต์ฌ์๋ ๋๋ฉ์ธ ์ํฐํฐ๊ฐ ์๋ค. ์ ์ค์ผ์ด์ค๋ ๋จ์ผ ์ฑ ์์ ๊ฐ๊ธฐ ์ํด ๋ ์ธ๋ถํ๋ ํํ์ ์๋น์ค๋ก ๊ตฌ์ฑ๋๋ฉฐ, ์ด ์ฝ์ด๋ฅผ ์ค์ฌ์ผ๋ก ๋น์ฆ๋์ค ๊ท์น์ ๊ตฌํํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค๋ฅธ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ด ์กด์ฌํ๋ค. ์ด ์ปดํฌ๋ํธ๋ค์ ์์์ฑ์ ์ ๊ณตํ๊ฑฐ๋ UI๋ฅผ ์ ๊ณตํ๋ ์ญํ ์ ํ๋ฉฐ, ๋ฐ๊นฅ์ชฝ ๊ณ์ธต๋ค์ ์๋ํํฐ ์ปดํฌ๋ํธ์ ๋ํ ์ด๋ํฐ ์ญํ ์ ํ ์๋ ์๋ค.
๋๋ฉ์ธ ์ฝ๋์์๋ ์ด๋ค ์์์ฑ ํ๋ ์์ํฌ๋ UI ํ๋ ์์ํฌ๊ฐ ์ฌ์ฉ๋๋์ง ์ ์ ์๊ธฐ ๋๋ฌธ์ ํน์ ํ๋ ์์ํฌ์ ํนํ๋ ์ฝ๋๋ฅผ ๊ฐ์ง ์ ์๋ค. ์ด ๋๋ถ์ ์ค์ง ๋น์ฆ๋์ค ๊ท์น์ ์ง์คํ ์ ์๊ณ , ๋๋ฉ์ธ ์ฝ๋๋ฅผ ์์ ๋กญ๊ฒ ๋ชจ๋ธ๋งํ ์ ์๊ฒ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ ๊ณง ๋๋ฉ์ธ ์ฃผ๋ ์ค๊ณ(DDD)๋ฅผ ๊ฐ์ฅ ์์ํ ํํ๋ก ์ ์ฉํ ์ ์๊ฒ ๋๋ค.
๊ฐ๋ น, ์์์ฑ ๊ณ์ธต์์ ORM ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด๋ณด์. ์ผ๋ฐ์ ์ผ๋ก ORM ํ๋ ์์ํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ์ ๊ฐ์ฒด ํ๋ ๋ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์นผ๋ผ ๊ฐ์ ๋งคํ์ ์์ ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์๋ ์ํฐํฐ ํด๋์ค๋ฅผ ํ์๋ก ํ๋ค. ๋๋ฉ์ธ ๊ณ์ธต์ ์์์ฑ ๊ณ์ธต์ ์์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋๋ฉ์ธ ๊ณ์ธต์์ ์ฌ์ฉํ ์ํฐํฐ ํด๋์ค๋ฅผ ์์์ฑ ๊ณ์ธต์์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค. ๋ฐ๋ผ์ ๋ ๊ณ์ธต์์ ๊ฐ๊ฐ ์ํฐํฐ๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค. ๋๋ฉ์ธ ๊ณ์ธต๊ณผ ์์์ฑ ๊ณ์ธต์ด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋, ๋ ์ํฐํฐ๋ฅผ ์๋ก ๋ณํํด์ผ ํ๋ค. ์ด๋ ๋๋ฉ์ธ ๊ณ์ธต๊ณผ ๋ค๋ฅธ ๊ณ์ธต๋ค ์ฌ์ด์์๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
์ฆ, ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ๋ฅผ ๋ถ๋ฆฌํ๋ ์ด์ ๋ ํด๋ฆฐ ์ํคํ ์ฒ์ ์์น์ ๋ฐ๋ผ ๊ณ์ธต ๊ฐ์ ์์กด์ฑ์ ์ต์ํํ๊ณ , ๋๋ฉ์ธ ๋ก์ง์ด ํน์ ํ๋ ์์ํฌ๋ ๊ธฐ์ ์ ์ข ์๋์ง ์๋๋ก ํ๊ธฐ ์ํจ์ด๋ค.
๊ผญ ๋ถ๋ฆฌํด์ผ ํ๋๊ฐ?
๋๋ฉ์ธ ๋ชจ๋ธ์ ์์์ฑ๊ณผ ๋ฌด๊ดํ๊ฒ ์์ํด์ผ ํ๋ฉฐ, ์ค๊ณ์์ ๋๋ฉ์ธ์ด ๊ฐ์ฅ ๋์ ์ฐ์ ์์๋ฅผ ๊ฐ์ง๋ฉฐ ์ค์ฌ์ด ๋๋ค. ORM์ ์ฌ์ฉํ๋ค๊ฐ ๋จ์ ์ฟผ๋ฆฌ ์คํ๊ธฐ(e.g., JDBC, MyBatis)๋ก ๋ณ๊ฒฝํด๋ ๋๋ฉ์ธ ์ค๊ณ๋ ๋ณ๊ฒฝ๋์ง ์์์ผ ํ๋ค. ์ฆ ์์์ฑ ํ๋ ์์ํฌ์ ์ฌ์ฉ ์ฌ๋ถ๊ฐ ๋๋ฉ์ธ ์์ญ์ ์ํฅ์ ์ฃผ์ด์๋ ์ ๋๋ค.
ํ์ง๋ง ์ ์๊ฐํด ๋ณด์ ์ค์ ํ๋ก์ ํธ์์ ํ ๋ฒ ๋์ ๋ ๊ธฐ์ ๋ค์ด ๋ณ๊ฒฝ๋ ์ ์ด ์๋๊ฐ? ๋ถ๋ฆฌํ๊ธฐ ์ํด์๋ ์ด๋ค ์ ๋ค์ ๊ณ ๋ คํ๋ฉด ์ข์๊น?
- ์ผ๋ฐ์ ์ธ ๊ท๋ชจ์ ํ๋ก์ ํธ์์ ORM์ ์ฌ์ฉํ๋ค๊ฐ ๊ฑท์ด๋ธ ์ ์ด ์๋๊ฐ?
- ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ORM @Entitiy๋ฅผ ๋์ผํ๊ฒ ์ฌ์ฉํ๊ณ ์์ง๋ ์๋๊ฐ?
- JPA๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์ํฐํฐ ํด๋์ค์ jakarta.persistence(java 17 ๋ฏธ๋ง์๋ javax)๋ง ์ถ๊ฐ๋ก import ํ๊ณ ์๋๋ฐ, ์ด๊ฒ๋ ์์ POJO๋ก ๊ฐ์ฃผํ ์ ์์ง ์์๊น?
- ํ๋ก์ ํธ ์ด๊ธฐ์ ๊ธฐ์ ์ ํ์ ์๋ชปํ ๊ฒฝ์ฐ, ๋์ค์ ์ด๋ฅผ ์์ ํ๊ธฐ ์ํด ๋ค์ฌ์ผ ํ ๋น์ฉ๊ณผ ๋ ธ๋ ฅ์ด ์ด๋ ์ ๋์ธ๊ฐ?
- ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ด ๋ถ๋ฆฌ๋จ์ผ๋ก์จ ํ์ ๊ฐ๋ฐ ์๋์ ์ฝ๋ ํ์ง์ ๋ฏธ์น๋ ์ํฅ์ ๋ฌด์์ธ๊ฐ?
- ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฆฌ๋ฅผ ํตํด ์ป์ ์ ์๋ ํ ์คํธ์ ์ฉ์ด์ฑ์ ์ด๋ ์ ๋์ธ๊ฐ?
- ๋๋ฉ์ธ ๋ชจ๋ธ์ ์ฌ์ฉํ์ง ์๋ ํ์์ด๋ ํ์ ๊ฐ๋ฐ์๊ฐ ํ๋ก์ ํธ์ ์ฐธ์ฌํ ๊ฒฝ์ฐ, ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฆฌ๋ก ์ธํ ํ์ต ๊ณก์ ์ ์ด๋ป๊ฒ ๋๋๊ฐ?
์ ์ง๋ฌธ๋ค์ ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ๊ธฐ ์ ์ ํ ๋ฒ ๊ณ ๋ฏผํด ๋ณด๋ฉด ์ข์ ๋ฆฌ์คํธ๋ค์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ ์ง๋ฌธ๋ค์ ํตํด ๋๋ฉ์ธ ์ํฐํฐ์ ์์์ฑ ์ํฐํฐ๋ก ๋๋๋ ๊ฒ์ ๊ฒฐ์ฌํ๋๋ผ๋ ์ค์ ์์ ์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ ํธ๋ ์ด๋์คํ๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ค.
1. ์ปจ๋ฒํ ์ ์ํ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ ์ฝ๋ ์์ฑ
์์ ๋๋ฉ์ธ ๊ฐ์ฒด์ ์์์ฑ ๊ฐ์ฒด๋ ๋ถ๋ฆฌ๋์ด์ผ ํ๋ค. ์ฆ, ์๋น์ค์ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ์ ๋ฐํ ๊ฐ์ ์ธ๋ถ์ ์์กดํ์ง ์๋๋ก ์ปจ๋ฒํ ์์ ์ด ํ์ํ๋ค. ๋ง์ฝ ํ๋์ ์ ๊ทธ๋ฆฌ๊ฑฐํธ์ ๋งค์ฐ ๋ง์ ์ค์ฒฉ ๊ฐ์ฒด๊ฐ ์กด์ฌํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
์ผ๋ฐ์ ์ผ๋ก DDD์์๋ ํ๋์ ์ ๊ทธ๋ฆฌ๊ฑฐํธ(๊ฐ์ ๋ผ์ดํ ์ฌ์ดํด์ ๊ฐ์ง๋ ๊ด๋ จ๋ ๊ฐ์ฒด๋ค์ ๋ชจ์ ํ๋์ ๋จ์๋ก ์ทจ๊ธํ๋ ๊ฐ๋ )๋ฅผ repository์ ๋์ ์ํฐํฐ๋ก ์ผ๋๋ค. ์๋ฅผ ๋ค์ด Order๋ผ๋ ์ ๊ทธ๋ฆฌ๊ฑฐํธ๊ฐ ์กด์ฌํ ๋, ํด๋น ์ ๊ทธ๋ฆฌ๊ฑฐํธ๋ฅผ ์ ์ฅํ๊ณ ๋ก๋ํ๋ OrderRepository๋ง ์กด์ฌํด์ผ ํ๋ค. ๊ฒฐ๊ตญ, ํด๋น ์ ๊ทธ๋ฆฌ๊ฑฐํธ์ ํฌํจ๋๋ ๋ชจ๋ ์ํฐํฐ์ ๋ฐธ๋ฅ ๊ฐ์ฒด๋ค์ ๋ํด ํธ๋์ญ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํด์ผ ํ๋ฉฐ, ์ปจ๋ฒํ ์์ ์ ๋ง์ ์๊ฐ์ ์๋ชจํ๊ฒ ๋๋ค.
๋ํ ์ฝ๋์ ์์ ์ค์ด๊ธฐ ์ํด ๋งคํ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๋๋ผ๋, ๋ ๋ชจ๋ธ ๊ฐ ๋งคํ์ ๊ตฌํํ๋ ๋ฐ๋ ์๋นํ ์๊ฐ์ด ์์๋๋ค. ํนํ ๋งคํ ํ๋ ์์ํฌ๊ฐ ๋ด๋ถ ๋์ ๋ฐฉ์์ ์ ๋ค๋ฆญ ์ฝ๋์ ๋ฆฌํ๋ ์ ๋ค๋ก ์จ๊ธธ ๊ฒฝ์ฐ, ๋งคํ ๋ก์ง์ ๋๋ฒ๊น ํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ต๊ณ ๋ณต์กํ๋ค.
์ด๋ฌํ ์ด์ ๋ก ์ธํด, ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฆฌ๋ ๋ง์ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋ง๋ค๊ณ , ๊ฐ๋ฐ์๋ค์ด ์ปจ๋ฒํ ๋ก์ง์ ๋ง์ ์๊ฐ์ ํ ์ ํ๊ฒ ๋๋ค. ์ด๋ก ์ธํด ๊ฐ๋ฐ ์๋๊ฐ ์ ํ๋๊ณ (์ค์ ๋ก ๊ฝค ์ฒด๊ฐ๋๋ค.), ๋๋ฒ๊น ๊ณผ์ ์์์ ์ด๋ ค์์ด ์ฆ๊ฐํ์ฌ ์ ์ฒด์ ์ธ ์์ฐ์ฑ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ์ ์๋ค.
2. ํด๋จผ ์๋ฌ
์ปจ๋ฒํ ๋ฌธ์ ์ ์ง๊ฒฐ๋ ๋ฌธ์ ๋ก, ์ค์๋ก ์ธํด ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
public class Customer {
private Long id;
private String name;
private String email;
private String phoneNumber; // New field added
private Address address;
public Customer(Long id, String name, String email, String phoneNumber, Address address) {
this.id = id;
this.name = name;
this.email = email;
this.phoneNumber = phoneNumber; // Initialization of new field
this.address = address;
}
// Other methods..
}
@Entity
public class CustomerEntity {
@Id
private Long id;
private String name;
private String email;
// Missing phoneNumber field
private Address address;
public CustomerEntity(Long id, String name, String email, Address address) {
this.id = id;
this.name = name;
this.email = email;
this.address = address;
}
// Other methods..
}
์ ์ฝ๋์์ Customer ๊ฐ์ฒด์๋ phoneNumber ํ๋๊ฐ ์ถ๊ฐ๋์์ง๋ง, ์ค์๋ก CustomerEntity์๋ ์ถ๊ฐ๋์ง ์์๋ค(๋ฐ๋์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ค). ์ด๋ ์ปดํ์ผ ๋จ๊ณ์์ ํ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ ์์ ์ฑ์ด ๋จ์ด์ง ์ ์๋ค. ๋ฌผ๋ก ์ฒ ์ ํ๊ฒ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋ณํ ๊ณผ์ ์์ ๋ฐ์ํ ์ ์๋ ์ค๋ฅ๋ฅผ ์ฌ์ ์ ๋ฐ๊ฒฌํ ์ ์์ง๋ง, ํญ์ ์๋ฒฝํ์ง๋ ์๋ค.
์ด๋ฌํ ์ค์๋ ๋ณ๋ก ์ผ์ด๋์ง ์์ ๊ฒ ๊ฐ์ง๋ง, ์๊ฐ๋ณด๋ค ๊ฐ๋ฐํ๋ ๋์ ๊ฝค๋ ์์ฃผ ๋ฐ์ํ๋๋ฐ ์๋ก์ด ํ๋๋ฅผ ์ถ๊ฐํ๋ ๋์ค ๋ง์ ๊ฑธ๊ฑฐ๋ ์ปคํผํ์์ผ๋ก ์ธํด ์ ๊น ์ฃผ์๋ฅผ ๋๋ฆฐ ํ ๋ค์ ์์ ์ ์ฌ๊ฐํ ๋, ํ๋ ์ถ๊ฐ๋ฅผ ๊น๋จน๋ ๊ฒฝ์ฐ๊ฐ ์์ฃผ ์๋ค.
3. ๊ตฌํ ๊ธฐ์ ์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ฌ์ฉ ๋ถ๊ฐ
์ปจ๋ฒํ ์ ์ฐ์ฅ์ ์ผ๋ก, Lazy Loading์ด๋ Dirty Checking ๊ฐ์ JPA์์ ์ง์ํ๋ ๊ธฐ๋ฅ์ ์์์ฑ ๊ณ์ธต์ ์์กดํ๋ ๊ธฐ๋ฅ์ด๋ค. ๋ฐ๋ผ์ ์ปจ๋ฒํ ์ดํ์๋ ์ด๋ฌํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค. ์ด๋ ์ฑ๋ฅ ์ต์ ํ ๋ฐ ๋ฆฌ์์ค ๊ด๋ฆฌ ์ธก๋ฉด์์ ๋ถ๋ฆฌํ ์ ์๋ค.
๋ค๋ง ์ด ๋ถ๋ถ์ ์ ๊ทธ๋ฆฌ๊ฑฐํธ์ ๋ํด Lazy Loading์ด ํ์ํ์ง ์๋ค๊ณ ๋ณด๋ ์๊ฒฌ๋ ๋ง๋ค. ์ ๊ทธ๋ฆฌ๊ฑฐํธ์ ํ์ํ ๊ฐ์ ํ ๋ฒ์ ๋ก๋๋์ด์ผ ํ๊ณ , ํ์ํ์ง ์์ผ๋ฉด ๋ก๋๋์ง ์์์ผ ํ๋ค. Lazy Loading์ด ํ์ํ๋ค๋ ๊ฒ์ ์ ๊ทธ๋ฆฌ๊ฑฐํธ์ ์ค๊ณ๊ฐ ์๋ชป๋์์ ๊ฐ๋ฅ์ฑ์ ์๋ฏธํ๋ค.
๊ทธ๋ฌ๋ ์ ์คํ ๊ณ ๋ คํ ๋ค ๋ถ๋ฆฌํ์
๊ฒฐ๋ก ์ ์ผ๋ก, ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ถ๋ฆฌ๋ ์ ์คํ๊ฒ ๊ฒฐ์ ํด์ผ ํ๋ฉฐ, ํ๋ก์ ํธ์ ํน์ฑ, ํ์ ์ญ๋, ์ฅ๊ธฐ์ ์ธ ์ ์ง๋ณด์์ ํ์ฅ์ฑ์ ๊ณ ๋ คํ ์ ๋ต์ ์ธ ์ ๊ทผ์ด ํ์ํ๋ค. ์ด๋ฌํ ๋ถ๋ฆฌ๊ฐ ํญ์ ์ต์ ์ ์ ํ์ ์๋๋ฉฐ, ์ค์ ํ๋ก์ ํธ ์ํฉ์ ๋ง๋ ์ต์ ์ ๊ฒฐ์ ์ ๋ด๋ฆฌ๋ ๊ฒ์ด ์ค์ํ๋ค.
์ค์ ๋ก '๋ง๋ค๋ฉด์ ๋ฐฐ์ฐ๋ ํด๋ฆฐ ์ํคํ ์ฒ' ์ฑ ์์๋ 8์ฅ์์ ์ด ๋์ ๋๋ฉ์ธ์ ๋๋์ง ์๋ '๋งคํํ์ง ์๊ธฐ' ์ ๋ต์ ๋ํด ๋ค๋ฃจ๊ณ ์๋๋ฐ, ์ด๋ฅผ ํตํด ๋๋ฉ์ธ๊ณผ ์์์ฑ ๋ชจ๋ธ์ ๋ฐ๋์ ๋ถ๋ฆฌํด์ผ ํ๋ ๊ฒ์ด ์ ๋ต์ด ์๋๋ผ๋ ๊ฒ์ ์ ์ ์๋ค.
์ต๋ฒ๊ท ๋์ DDD์ฑ 4์ฅ 171ํ์ด์ง์๋ ์๋์ ๊ฐ์ ๋ด์ฉ์ด ์ธ๊ธ๋๋ค.
"ํน์ ๊ธฐ์ ์ ์์กดํ์ง ์๋ ์์ํ ๋๋ฉ์ธ ๋ชจ๋ธ์ ์ถ๊ตฌํ๋ ๊ฐ๋ฐ์๋ ์ ์ด๋ฏธ์ง์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๊ตฌํํ๋ค. ์ด ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋ฉด ๊ตฌํ ๊ธฐ์ ์ ๋ณ๊ฒฝํ๋๋ผ๋ ๋๋ฉ์ธ์ด ๋ฐ๋ ์ํฅ์ ์ต์ํํ ์ ์๋ค. DIP๋ฅผ ์ ์ฉํ๋ ์ฃผ๋ ์ด์ ๋ ์ ์์ค ๊ตฌํ์ด ๋ณ๊ฒฝ๋๋๋ผ๋ ๊ณ ์์ค์ด ์ํฅ์ ๋ฐ์ง ์๋๋ก ํ๊ธฐ ์ํจ์ด๋ค. ํ์ง๋ง ๋ฆฌํฌ์งํฐ๋ฆฌ์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๊ตฌํ ๊ธฐ์ ์ ๊ฑฐ์ ๋ฐ๋์ง ์๋๋ค. ํ์๋ JPA๋ก ๊ตฌํํ ๋ฆฌํฌ์งํฐ๋ฆฌ ๊ตฌํ ๊ธฐ์ ์ ๋ง์ด๋ฐํฐ์ค๋ ๋ค๋ฅธ ๊ธฐ์ ๋ก ๋ณ๊ฒฝํ ์ ์ด ์๊ณ , RDBMS๋ฅผ ์ฌ์ฉํ๋ค ๋ชฝ๊ณ DB๋ก ๋ณ๊ฒฝํ ์ ๋ ์๋ค. ์ด๋ ๊ฒ ๋ณ๊ฒฝ์ด ๊ฑฐ์ ์๋ ์ํฉ์์ ๋ณ๊ฒฝ์ ๋ฏธ๋ฆฌ ๋๋นํ๋ ๊ฒ์ ๊ณผํ๋ค๊ณ ์๊ฐํ๋ค."
๊ทธ๋ผ์๋ ์ธ์ ๋ถ๋ฆฌํ๋ฉด ์ข์๊น?
๊ทธ๋ ๋ค๋ฉด ์ธ์ ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข์๊น? ๊ฐ์ฅ ์ค์ํ ๊ฒ์ [persistence layer → domain layer] ๋ฐฉํฅ์ผ๋ก ๋ณ๊ฒฝ ์๋ ฅ์ด ๊ฐํด์ ธ์๋ ์ ๋๋ค๋ ์ ์ด๋ค. ์ด๋ฅผ ์ํด ๋ถ๋ฆฌ๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ ๋ช ๊ฐ์ง ์ํฉ์ด ์๋ค.
๋นํจ์จ์ ์ด๊ณ ์๋ชป ์ค๊ณ๋ ํ ์ด๋ธ ์คํค๋ง์ ๊ฒฝ์ฐ
์๋ชป ์ค๊ณ๋ ํ ์ด๋ธ ์คํค๋ง๊ฐ ๊ทธ๋๋ก ๋๋ฉ์ธ ๊ณ์ธต์ ๋ ธ์ถ๋๋ฉด ๋ฌธ์ ๊ฐ ๋ ์ ์๋ค. ORM @Entity๋ฅผ ๋๋ฉ์ธ ๋ชจ๋ธ๋ก ์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์ด๋ฌํ ์๋ชป๋ ํ ์ด๋ธ ๊ตฌ์กฐ๊ฐ ๊ทธ๋๋ก ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ฐ์๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ด๋ค.
// ์๋ชป ์ค๊ณ๋ ํ
์ด๋ธ ์คํค๋ง
@Entity
public class UserEntity {
@Id
private Long id;
private String fullName; // fullName ๋์ firstName๊ณผ lastName์ ๋ถ๋ฆฌํ์ด์ผ ํจ
private String address1; // Address๊ฐ ํ๋์ ํ๋๋ก ์ ์ฅ๋จ
private String address2;
private String address3;
}
// ๋๋ฉ์ธ ๋ชจ๋ธ
public class User {
private Long id;
private String firstName;
private String lastName;
private Address address; // Address ๊ฐ์ฒด๋ก ๋ถ๋ฆฌ
}
public class Address {
private String street;
private String city;
private String state;
private String zipCode;
}
ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ์ฌ, ์๋ชป ์ค๊ณ๋ ํ ์ด๋ธ์ ์คํค๋ง๊ฐ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ฐ์๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์๋ค. ์ด๋ฅผ ํตํด ๋๋ฉ์ธ ๋ชจ๋ธ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ฌธ์ ์ ์ ๊ทธ๋๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ง์ ์ ์๋ค.
๊ฐฑ์ ์ด์์ ํผํ๊ธฐ ์ํด ์ปฌ๋ผ์ด ๋๋ฝ๋ ๊ฒฝ์ฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ ์ ๊ฐฑ์ ์ด์์ ํผํ๊ธฐ ์ํด ์ค๋ณต์ ์ต์ํํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ค. ๋ค๋ง ์ด๋ก ์ธํด ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ ๊ฐ์ ๋ถ์ผ์น๊ฐ ๋ฐ์ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, @Entity๋ ํ ์ด๋ธ ์ปฌ๋ผ๊ณผ ๋์ผํ ํ๋๋ฅผ ๊ฐ์ง์ง๋ง, ๋๋ฉ์ธ ๋ชจ๋ธ์๋ ๋น์ฆ๋์ค ๋ก์ง์ ํ์ํ ์ถ๊ฐ ํ๋๊ฐ ์กด์ฌํ ์ ์๋ค.
@Entity
public class OrderEntity {
@Id
private Long id;
private BigDecimal amount;
private Long customerId; // ๊ณ ๊ฐ ์ ๋ณด๊ฐ ๋ถ๋ฆฌ๋์ด ์์
// ๋ค๋ฅธ ํ์ํ ํ๋๋ค...
}
public class Order {
private Long id;
private BigDecimal amount;
private BigDecimal tax; // ๋น์ฆ๋์ค ๋ก์ง์ ํ์ํ ์ถ๊ฐ ํ๋
private Customer customer; // ๊ณ ๊ฐ ์ ๋ณด ํฌํจ
public BigDecimal getTotalAmount() {
return amount.add(tax);
}
}
public class Customer {
private Long id;
private String name;
private String email;
}
๋ฌผ๋ก @Transient ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ํ ์ด๋ธ์๋ ์์ง๋ง ๋น์ฆ๋์ค์์ ํ์ํ ํ๋๋ฅผ ๋๋ฉ์ธ ๋ชจ๋ธ์ ์ถ๊ฐํ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฐฉ๋ฒ์ ๋๋ฉ์ธ ๋ชจ๋ธ์ด ์์์ฑ ๊ณ์ธต์ ์ธ๋ถ์ฌํญ์ ์ข ์๋๊ฒ ํ์ฌ ํผ๋์ ์ด๋ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, ๋น์ฆ๋์ค ๋ก์ง์์๋ ํ์ํ์ง๋ง ๋ฐ์ดํฐ๋ฒ ์ด์ค์๋ ์กด์ฌํ์ง ์๋ ํ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์์ ๋ถ๋ช ํํ ๋์์ด ๋ฐ์ํ ์ ์๋ค.
์ด๋ฌํ ํผ๋์ด ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถํ์ํ ๋ณ๊ฒฝ ์๋ ฅ์ผ๋ก ์์ฉํ์ง ์๋๋ก, ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค. ์ด๋ฅผ ํตํด ๋๋ฉ์ธ ๋ชจ๋ธ์ด ๋น์ฆ๋์ค ๋ก์ง์ ์ ๋๋ก ๋ฐ์ํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ ์ง๋ ์ ์๋ค.
์์์ฑ ์ ์ฉ ์ ๋ํ ์ด์ ์ ๊ณผ๋ํ ์ฌ์ฉ์ผ๋ก ์ธํด ๋๋ฉ์ธ ๋ชจ๋ธ ์ค์ผ๋ ๊ฒฝ์ฐ
๋๋ฉ์ธ ๋ชจ๋ธ์ ์์น์ ์ผ๋ก ์์ํด์ผ ํ๋ฏ๋ก, ORM @Entity๋ฅผ ๋ถ์ด๋ ๊ฒ์ ์ ํ์ ์ผ๋ก ํ์ฉ๋๋ค. ํ์ง๋ง ๋ค์ํ ORM ์ ๋ํ ์ด์ ์ด ๊ณผ๋ํ๊ฒ ์ฌ์ฉ๋๋ฉด ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ณธ์ง์ ํด์น ์ ์๋ค. ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ๋ค.
@Entity
@BatchSize(size = 10)
public class ProductEntity {
@Id
private Long id;
private String name;
@Version
private int version; // ๋ฒ์ ๊ด๋ฆฌ ํ๋
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdated; // ๋ง์ง๋ง ์
๋ฐ์ดํธ ์๊ฐ
}
public class Product {
private Long id;
private String name;
private LocalDateTime lastUpdated; // ๋๋ฉ์ธ ๋ชจ๋ธ์์๋ LocalDateTime ์ฌ์ฉ
}
์ ๋ํ ์ด์ ์ด ๊ณผ๋ํ๊ฒ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ, ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ํ์ํ ์ ์๋ค. ์ด๋ ๋๋ฉ์ธ ๋ชจ๋ธ์ ์์์ฑ์ ์ ์งํ๊ณ , ํน์ ์์์ฑ ํ๋ ์์ํฌ๋ ๊ธฐ์ ์ ์ข ์๋์ง ์๋๋ก ํ๊ธฐ ์ํจ์ด๋ค.
์ด๋ฌํ ์ ํธ๋ค์ด ๋ณด์ธ๋ค๋ฉด, ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ORM @Entity๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ค๊ณ์ ์์์ฑ์ ์ ์งํ๊ณ , ๋๋ฉ์ธ ๊ณ์ธต์ด ํน์ ์์์ฑ ํ๋ ์์ํฌ๋ ๊ธฐ์ ์ ์ข ์๋์ง ์๋๋ก ํ๋ ๊ฒ์ด ์ข๋ค. ์ด๋ฅผ ํตํด ์์คํ ์ ์ ์ง๋ณด์์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์ผ ์ ์์ผ๋ฉฐ, ๋น์ฆ๋์ค ๋ก์ง์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ด๋ฆฌ๋ ์ ์๋ค.
์ ๋ฆฌ
๊ฒฐ๊ตญ, ์ํฐํฐ๋ฅผ ๋ถ๋ฆฌํ๋ ์ด์ ๋ ๋๋ฉ์ธ ์ค์ฌ ์ค๊ณ๋ฅผ ๊ตฌํํ๊ธฐ ์ํจ์ด๋ค. ์ ํต์ ์ธ ๊ณ์ธตํ ์ํคํ ์ฒ์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ํ ๋๊ฐ ๋๋ค. ์น ๊ณ์ธต์ ๋๋ฉ์ธ ๊ณ์ธต์ ์์กดํ๊ณ , ๋๋ฉ์ธ ๊ณ์ธต์ ์์์ฑ ๊ณ์ธต์ ์์กดํ๋ฏ๋ก ์์ฐ์ค๋ฝ๊ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์กดํ๊ฒ ๋๋ค. ์ด๋ก ์ธํด ๋ชจ๋ ๊ฒ์ด ์์์ฑ ๊ณ์ธต์ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ง๋ค.
์ฐ๋ฆฌ์ ์ ํ๋ฆฌ์ผ์ด์ ๋๋ถ๋ถ์ ๋ชฉ์ ์ด ๋ฌด์์ธ์ง ์๊ฐํด ๋ณด์. ์ฐ๋ฆฌ๋ ๋น์ฆ๋์ค๋ฅผ ๊ด์ฅํ๋ ๊ท์น์ด๋ ์ ์ฑ ์ ๋ฐ์ํ ๋ชจ๋ธ์ ๋ง๋ค์ด, ์ฌ์ฉ์๊ฐ ์ด๋ฅผ ํธ๋ฆฌํ๊ฒ ํ์ฉํ ์ ์๋๋ก ํ๋ค. ์ด๋ ์ฐ๋ฆฌ๋ ์ํ(state)๊ฐ ์๋๋ผ ํ๋(behavior)์ ์ค์ฌ์ผ๋ก ๋ชจ๋ธ๋งํ๋ค. ์ด๋ค ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ ์ํ๊ฐ ์ค์ํ ์์์ด๊ธด ํ์ง๋ง, ํ๋์ด ์ํ๋ฅผ ๋ณํ์ํค๋ ์ฃผ์ฒด์ด๊ธฐ ๋๋ฌธ์ ํ๋์ด ๋น์ฆ๋์ค๋ฅผ ์ด๋์ด๊ฐ๋ค.
๋ฐ๋ผ์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ์ด๋ฌํ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ํ๋์ ์ค์ฌ์ผ๋ก ์ค๊ณ๋๋ฉด ์ข๋ค. ์์์ฑ ๊ณ์ธต์ ์ ์ฝ์ด๋ ์ธ๋ถ์ฌํญ์ ์ํด ๋๋ฉ์ธ ๋ชจ๋ธ์ด ์๊ณก๋์ง ์๋๋ก ORM @Entity์ ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ค์ํ๋ค. ์ด๋ ๊ฒ ํจ์ผ๋ก์จ, ๋๋ฉ์ธ ๋ชจ๋ธ์ ๋น์ฆ๋์ค ๋ก์ง์ ์ ๋๋ก ๋ฐ์ํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ ์ง๋ ์ ์๋ค.
+ ๋ง๋ถ์..
๋ค๋ง, ํ์ ์์ ๊ณ์ธตํ ์ํคํ ์ฒ์ ํด๋ฆฐ ์ํคํ ์ฒ๋ฅผ ๋ชจ๋ ์ ํด๋ณธ ์ ์ฅ์์ ๋๋ ์์ฆ ์ค๋ฒ์์ง๋์ด๋ง์ ๋ํด ๋งค์ฐ ๊ฒฝ๊ณํ๊ณ ์๋ค. ๋ชจ๋ ๊ฒ์๋ ์ ๋ต์ด ์์ง๋ง, ํด๋ฆฐ ์ํคํ ์ฒ๋ ํฅ์ฌ๊ณ ๋ ์ํคํ ์ฒ๋ฅผ ์ฌ์ฉํ๋ค๊ณ ํด์ ์ํ๋ ๊ฐ๋ฐ์์ด๊ณ , ๊ณ์ธตํ ์ํคํ ์ฒ๋ก ๊ฐ๋ฐํ๋ค๊ณ ํด์ ๋ชปํ๋ ๊ฐ๋ฐ์๋ ์๋๋ผ๊ณ ์๊ฐํ๋ค. ๊ตฌํ์ฒด๊ฐ ํ๋๋ฟ์ธ๋ฐ๋ ์๋จ์ ์ธํฐํ์ด์ค๋ฅผ ๋์ง ์์์ผ๋ DIP๋ฅผ ์ด๊ฒผ๊ธฐ์ ๋์ ์ฝ๋์ธ๊ฐ? ํ์ ๋ฆฌํฉํฐ๋ง์ ํ๋ฉด ์ ๋๋ ๊ฑธ๊น? ๋น์ฅ 3๋ ์์ ์ ์ฅ์๊ฐ ๋ณ๊ฒฝ๋ ์ผ์ด ์๊ณ ํธ๋ํฝ๋ ์ ์ ์๋น์ค์์ MSA๋ CQRS๋ฅผ ์ ์ฉํ๋ ๊ฒ์ด ์ ๋ง ํ์ํ ๊ฑธ๊น? ํ์๋ค์ ํ์ต ๊ณก์ ์ ๊ณ ๋ คํ์ง ์์ ํ์ ๊ฐ๋ฐ ์๋๊ฐ ๋ฆ์ถฐ์ง๋ ๊ฒ์ ๊ด์ฐฎ์ ์ผ์ผ๊น? RDD(์ด๋ ฅ์ ์ฃผ๋ ๊ฐ๋ฐ)์ด ๋๋ฉด ์ ๋๋ค๊ณ ์๊ฐํ๋ค.
์ฐ๋ฆฌ๋ ๊ฐ๋ฐ์์ด๊ธฐ ์ด์ ์ ํ ํ์ฌ์์ ๋์ ๋ฐ๋ ์ง์์ด๊ณ , ์ ํ์ ๋น ๋ฅด๊ณ ๊ฒฝ์๋ ฅ ์๊ฒ ๋ง๋ค์ด ๊ณ ๊ฐ์ ๋ง์กฑ์ ๋์ด๋ ์ผ์ ํด์ผ ํ๋ค. ๊ทธ๋ ๊ธฐ์ ์ค์ํ ๊ฒ์ ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ์ถฉ์กฑ์ํค๊ณ ํ์ ์์ฐ์ฑ์ ์ ์งํ๋ฉด์ ์ ์ ํ ์ํคํ ์ฒ๋ฅผ ์ ํํ๋ ๊ฒ์ด๋ค. '์์ด์์ ์๋ค(No Silver Bullet)'๋ผ๋ ๋ง์ด ์๋ฏ์ด ๋ชจ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๋ง๋ฅ์ ์ํคํ ์ฒ๋ ์ค๊ณ๋ ์กด์ฌํ์ง ์๋๋ค.
์ฐธ๊ณ
- https://umbum.dev/2005/
- https://dev-coco.tistory.com/190
- ๋ง๋ค๋ฉด์ ๋ฐฐ์ฐ๋ ํด๋ฆฐ ์ํคํ ์ฒ
- ๋๋ฉ์ธ ์ฃผ๋ ๊ฐ๋ฐ ์์ํ๊ธฐ: DDD ํต์ฌ ๊ฐ๋ ์ ๋ฆฌ๋ถํฐ ๊ตฌํ๊น์ง
- ํฅ์ฌ๊ณ ๋ ๋ฐฐ์ฐ์ง ๋ง์ feat. ๊ตฌํ First
- ๋๊ธฐ์ ๋ค์ด ์์ฅ์ MSA๋ผ๋ ๋ ์ ํ์๋ค
- ์ง์ ์ฑ์ฅ ๊ฐ๋ฅํ ์ํํธ์จ์ด๋ฅผ ๋ง๋ค์ด ๊ฐ๋ ๋ฐฉ๋ฒ
- DDD์ Entity์ JPA์ Entity๋ ๊ฐ์ ๊ฑธ๊น?