spring

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด vs ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด

devJK93 2024. 11. 25.

๐Ÿ”ฅ ๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์ด๋ž€?

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด(Domain Model Pattern)์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋„๋ฉ”์ธ ๊ฐ์ฒด(์—”ํ‹ฐํ‹ฐ) ๋‚ด๋ถ€์— ํฌํ•จ์‹œํ‚ค๋Š” ์„ค๊ณ„ ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™, ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ, ๋ฐ์ดํ„ฐ ๊ฒ€์ฆ ๋“ฑ์„ ๋„๋ฉ”์ธ ๊ฐ์ฒด๊ฐ€ ์ง์ ‘ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŒจํ„ด์€ DDD(Domain-Driven Design)์˜ ํ•ต์‹ฌ ๊ฐœ๋… ์ค‘ ํ•˜๋‚˜์ด๋ฉฐ, ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์žฅ์ ์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ง•

  1. ๋„๋ฉ”์ธ ๊ฐ์ฒด์— ์ฑ…์ž„ ๋ถ€์—ฌ:๊ฐ์ฒด๊ฐ€ ์ž์‹ ์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ๊ด€๋ จ๋œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  2. ์˜ˆ: Order ๊ฐ์ฒด๊ฐ€ ์ฃผ๋ฌธ ์ƒ์„ฑ, ์ฃผ๋ฌธ ์ทจ์†Œ ๋“ฑ์„ ์ˆ˜ํ–‰.
  3. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์บก์Šํ™”:๋ฐ์ดํ„ฐ์™€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์ด ํ•œ ๊ฐ์ฒด ๋‚ด๋ถ€์— ์บก์Šํ™”๋ฉ๋‹ˆ๋‹ค.
  4. ์—”ํ‹ฐํ‹ฐ ์ค‘์‹ฌ ์„ค๊ณ„:์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๊ฐ€ ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์—ญํ• ๋งŒ ํ•˜์ง€ ์•Š๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์˜ ๊ตฌ์กฐ

1. ์—”ํ‹ฐํ‹ฐ(Entity)

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ: Order, Member, Product ๋“ฑ.

2. ๋ฐธ๋ฅ˜(Value Object)

ํŠน์ • ๊ฐ’์„ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ์ฒด๋กœ, ๊ฐ’ ์ž์ฒด๊ฐ€ ์ค‘์š”ํ•˜๋ฉฐ ๋ถˆ๋ณ€์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

์˜ˆ: Address, Money ๋“ฑ.

3. ์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ(Aggregate)

์—”ํ‹ฐํ‹ฐ์™€ ๋ฐธ๋ฅ˜ ๊ฐ์ฒด๊ฐ€ ํ•˜๋‚˜๋กœ ๋ฌถ์ธ ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.

์• ๊ทธ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฃจํŠธ(์ฃผ๋กœ ์—”ํ‹ฐํ‹ฐ)๊ฐ€ ์™ธ๋ถ€์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋‹ด๋‹นํ•˜๋ฉฐ, ๋‚ด๋ถ€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์˜ ์žฅ์ 

  • ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์žฅ์  ํ™œ์šฉ: ๋ฐ์ดํ„ฐ์™€ ํ–‰์œ„๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ฌถ์–ด ๊ฐ์ฒด์ง€ํ–ฅ์  ์„ค๊ณ„๋ฅผ ์ด‰์ง„ํ•ฉ๋‹ˆ๋‹ค.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ง‘์ค‘ํ™”: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๊ฐ์ฒด์— ์ง‘์ค‘๋˜์–ด ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.
  • ์‘์ง‘๋„ ํ–ฅ์ƒ: ๊ด€๋ จ๋œ ๋กœ์ง๊ณผ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•œ ๊ณณ์— ๋ชจ์—ฌ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง‘๋‹ˆ๋‹ค.
  • ์ค‘๋ณต ์ฝ”๋“œ ๊ฐ์†Œ: ๊ฐ์ฒด๊ฐ€ ์ƒํƒœ๋ฅผ ์Šค์Šค๋กœ ๊ด€๋ฆฌํ•˜๋ฏ€๋กœ, ์„œ๋น„์Šค ๊ณ„์ธต์˜ ๋กœ์ง ์ค‘๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์˜ ๋‹จ์ 

  • ์ดˆ๊ธฐ ์„ค๊ณ„ ๋น„์šฉ: ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ์„ค๊ณ„ํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณต์žก์„ฑ ์ฆ๊ฐ€: ๊ฐ์ฒด ๊ฐ„ ๊ด€๊ณ„์™€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋ณต์žกํ•  ๊ฒฝ์šฐ, ๊ด€๋ฆฌ๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ˆ™๋ จ๋œ ๊ฐœ๋ฐœ์ž ํ•„์š”: ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์™€ ๋„๋ฉ”์ธ ์ฃผ๋„ ์„ค๊ณ„(DDD)์— ๋Œ€ํ•œ ๊นŠ์€ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ: Order ํด๋ž˜์Šค

@Entity
public class Order {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List orderItems = new ArrayList<>();

    @OneToOne(cascade = CascadeType.ALL)
    private Delivery delivery;

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status; // ์˜ˆ: ORDERED, CANCELED

    //== ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ==//

    // ์ฃผ๋ฌธ ์ƒ์„ฑ
    public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) {
        Order order = new Order();
        order.setMember(member);
        order.setDelivery(delivery);
        for (OrderItem orderItem : orderItems) {
            order.addOrderItem(orderItem);
        }
        order.setOrderDate(LocalDateTime.now());
        order.setStatus(OrderStatus.ORDERED);
        return order;
    }

    // ์ฃผ๋ฌธ ์ทจ์†Œ
    public void cancel() {
        if (delivery.getStatus() == DeliveryStatus.COMPLETE) {
            throw new IllegalStateException("์ด๋ฏธ ๋ฐฐ์†ก ์™„๋ฃŒ๋œ ์ฃผ๋ฌธ์€ ์ทจ์†Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }
        this.setStatus(OrderStatus.CANCELED);
        for (OrderItem orderItem : orderItems) {
            orderItem.cancel(); // ์ฃผ๋ฌธ์ƒํ’ˆ๋„ ์ทจ์†Œ
        }
    }

    // ์ด ์ฃผ๋ฌธ ๊ฐ€๊ฒฉ ๊ณ„์‚ฐ
    public int getTotalPrice() {
        return orderItems.stream()
                .mapToInt(OrderItem::getTotalPrice)
                .sum();
    }
}

๋ถ„์„

1. createOrder ๋ฉ”์„œ๋“œ

์ •์  ๋ฉ”์„œ๋“œ๋กœ ์ฃผ๋ฌธ์„ ์ƒ์„ฑํ•˜๋ฉฐ, Member, Delivery, OrderItem์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ๋ฌธ ์ƒ์„ฑ ๊ณผ์ •์—์„œ์˜ ๋ณต์žกํ•œ ๋กœ์ง์„ ์บก์Šํ™”ํ•˜์—ฌ ์„œ๋น„์Šค ๊ณ„์ธต์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค.

2. cancel ๋ฉ”์„œ๋“œ

์ฃผ๋ฌธ ์ƒํƒœ๋ฅผ ์ทจ์†Œ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉฐ, ์—ฐ๊ด€๋œ OrderItem๋„ ์ทจ์†Œํ•ฉ๋‹ˆ๋‹ค.

๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™(์˜ˆ: ๋ฐฐ์†ก ์™„๋ฃŒ ํ›„ ์ทจ์†Œ ๋ถˆ๊ฐ€)์„ ์บก์Šํ™”ํ•ฉ๋‹ˆ๋‹ค.

3. getTotalPrice ๋ฉ”์„œ๋“œ

์ฃผ๋ฌธ์ƒํ’ˆ์˜ ์ด ๊ฐ€๊ฒฉ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ณ„์‚ฐ ๋กœ์ง์ด Order ๋‚ด๋ถ€์— ์žˆ์œผ๋ฏ€๋กœ, ์™ธ๋ถ€์—์„œ ๊ณ„์‚ฐ ๋กœ์ง์„ ์•Œ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์„œ๋น„์Šค ๊ณ„์ธต์˜ ๋‹จ์ˆœํ™”

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋น„์Šค ๊ณ„์ธต์˜ ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง‘๋‹ˆ๋‹ค.

// ์„œ๋น„์Šค ๊ณ„์ธต
@Transactional
public Long order(Member member, Delivery delivery, OrderItem... orderItems) {
    Order order = Order.createOrder(member, delivery, orderItems);
    orderRepository.save(order);
    return order.getId();
}

์„œ๋น„์Šค ๊ณ„์ธต์—์„œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋Œ€์‹ , ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ์กฐํ•ฉํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด๊ณผ JPA

JPA๋Š” ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด๊ณผ ์ž˜ ๋งž์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ JPA์˜ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ™œ์šฉํ•˜๋ฉด, ๋„๋ฉ”์ธ ๊ฐ์ฒด๊ฐ€ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ JPA๊ฐ€ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์ž๋™์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์˜ ํ™œ์šฉ

1. ์ ํ•ฉํ•œ ๊ฒฝ์šฐ

  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋ณต์žกํ•˜๊ณ , ๊ฐ์ฒด ๊ฐ„ ๊ด€๊ณ„๊ฐ€ ๋งŽ์€ ๋„๋ฉ”์ธ.
  • ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์‘์ง‘๋„๊ฐ€ ์ค‘์š”ํ•œ ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜.

2. ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

  • ๊ฐ„๋‹จํ•œ CRUD ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ, ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด์ด ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ”ฅ ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด ์˜ˆ์‹œ

ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์•„๋‹Œ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์ด ํŒจํ„ด์€ ๋‹จ์ˆœํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ CRUD ์ž‘์—…์— ์ ํ•ฉํ•˜๋ฉฐ, ๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด๋ณด๋‹ค ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

1. ์—”ํ‹ฐํ‹ฐ ๊ฐ„์†Œํ™”

์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฐ€์ ธ์˜ค๋Š” ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•˜๋ฉฐ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์—†์Šต๋‹ˆ๋‹ค.

@Entity
public class Order {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List orderItems = new ArrayList<>();

    @OneToOne(cascade = CascadeType.ALL)
    private Delivery delivery;

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status; // ์˜ˆ: ORDERED, CANCELED

    // Getter, Setter๋งŒ ์กด์žฌ
    public void addOrderItem(OrderItem orderItem) {
        this.orderItems.add(orderItem);
        orderItem.setOrder(this);
    }
}

2. ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ๋ชจ๋“  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ

@Service
@Transactional
public class OrderService {

    private final OrderRepository orderRepository;
    private final MemberRepository memberRepository;

    public OrderService(OrderRepository orderRepository, MemberRepository memberRepository) {
        this.orderRepository = orderRepository;
        this.memberRepository = memberRepository;
    }

    // ์ฃผ๋ฌธ ์ƒ์„ฑ
    public Long createOrder(Long memberId, Delivery delivery, List orderItems) {
        // ํšŒ์› ์กฐํšŒ
        Member member = memberRepository.findById(memberId)
                .orElseThrow(() -> new IllegalArgumentException("ํšŒ์›์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."));

        // ์ฃผ๋ฌธ ์ƒ์„ฑ
        Order order = new Order();
        order.setMember(member);
        order.setDelivery(delivery);
        for (OrderItem orderItem : orderItems) {
            order.addOrderItem(orderItem);
        }
        order.setOrderDate(LocalDateTime.now());
        order.setStatus(OrderStatus.ORDERED);

        // ์ฃผ๋ฌธ ์ €์žฅ
        orderRepository.save(order);
        return order.getId();
    }

    // ์ฃผ๋ฌธ ์ทจ์†Œ
    public void cancelOrder(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new IllegalArgumentException("์ฃผ๋ฌธ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."));

        if (order.getDelivery().getStatus() == DeliveryStatus.COMPLETE) {
            throw new IllegalStateException("์ด๋ฏธ ๋ฐฐ์†ก ์™„๋ฃŒ๋œ ์ฃผ๋ฌธ์€ ์ทจ์†Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }

        // ์ƒํƒœ ๋ณ€๊ฒฝ
        order.setStatus(OrderStatus.CANCELED);

        // ์ฃผ๋ฌธ์ƒํ’ˆ ์ทจ์†Œ
        for (OrderItem orderItem : order.getOrderItems()) {
            orderItem.cancel(); // ์ฃผ๋ฌธ์ƒํ’ˆ ์ทจ์†Œ ๋กœ์ง ํ˜ธ์ถœ
        }
    }

    // ์ด ์ฃผ๋ฌธ ๊ฐ€๊ฒฉ ๊ณ„์‚ฐ
    public int getTotalPrice(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new IllegalArgumentException("์ฃผ๋ฌธ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."));
        return order.getOrderItems().stream()
                .mapToInt(OrderItem::getTotalPrice)
                .sum();
    }
}

ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด์˜ ํŠน์ง•

  • ์—”ํ‹ฐํ‹ฐ๋Š” ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ์™€ ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์—ญํ• ๋งŒ ์ˆ˜ํ–‰.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋ชจ๋‘ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ์ฒ˜๋ฆฌ.
  • ๋ฐ์ดํ„ฐ ํ๋ฆ„์ด ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ํšจ๊ณผ์ .

๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด๊ณผ ๋น„๊ต

ํŠน์ง• ๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด
๋กœ์ง ์œ„์น˜ ์—”ํ‹ฐํ‹ฐ ๋‚ด๋ถ€ (๋„๋ฉ”์ธ ๊ฐ์ฒด) ์„œ๋น„์Šค ๊ณ„์ธต
๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ณต์žก๋„ ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ ํ•ฉ ๊ฐ„๋‹จํ•œ CRUD ๋ฐ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ ํ•ฉ
์œ ์ง€๋ณด์ˆ˜ ๊ฐ์ฒด์ง€ํ–ฅ์  ์„ค๊ณ„๋กœ ์‘์ง‘๋„๊ฐ€ ๋†’์Œ ๊ตฌ์กฐ๊ฐ€ ๋‹จ์ˆœํ•˜์ง€๋งŒ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋ถ„์‚ฐ๋  ์ˆ˜ ์žˆ์Œ
์žฌ์‚ฌ์šฉ์„ฑ ์—”ํ‹ฐํ‹ฐ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์šฉ์ด ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ๊ฐ™์€ ๋กœ์ง์ด ๋ฐ˜๋ณต๋  ๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ
์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„ ์ดˆ๊ธฐ ์„ค๊ณ„ ๋น„์šฉ์ด ํผ ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜๊ณ  ๋น ๋ฆ„

๊ฒฐ๋ก 

ํŠธ๋žœ์žญ์…˜ ์Šคํฌ๋ฆฝํŠธ ํŒจํ„ด์€ ๋‹จ์ˆœํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•˜๋ฉฐ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ๋ณต์žกํ•˜์ง€ ์•Š์„ ๋•Œ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ์„ ํƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋กœ์ง์ด ๋ณต์žกํ•ด์ง€๊ฑฐ๋‚˜ ์žฌ์‚ฌ์šฉ์„ฑ์ด ์ค‘์š”ํ•ด์ง„๋‹ค๋ฉด ๋„๋ฉ”์ธ ๋ชจ๋ธ ํŒจํ„ด์œผ๋กœ ์ „ํ™˜์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋Œ“๊ธ€