# ๊ฐ•์ขŒ ์†Œ๊ฐœ

# ๊ฐ•์ขŒ ์†Œ๊ฐœ

# ์ˆ˜์—… ์ž๋ฃŒ

# ๊ฐ•์˜ ์†Œ์Šค ์ฝ”๋“œ

# 2ํŽธ ์ถ”๊ฐ€ ์ž๋ฃŒ

# API ๊ฐœ๋ฐœ ๊ธฐ๋ณธ

# ํšŒ์› ๋“ฑ๋ก API

// ๊ฐœ๋ฐœ ์‹œ Request, Response์— ํ•ด๋‹นํ•˜๋Š” class๋Š” ๋”ฐ๋กœ ์ƒ์„ฑ
@PostMapping("/api/v1/members")
public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) {
    Long id = memberService.join(member);
    return new CreateMemberResponse(id);
}

@PostMapping("/api/v2/members")
public CreateMemberResponse saveMemberV2(@RequestBody @Valid CreateMemberRequest request) {

    Member member = new Member();
    member.setName(request.getName());

    Long id = memberService.join(member);
    return new CreateMemberResponse(id);
}

# ํšŒ์› ์ˆ˜์ • API

// ENtity์ˆ˜์ •์€ ๋ณ€๊ฒฝ๊ฐ์ง€๋ฅผ ํ™œ์šฉ
// Update๋Š” ๋ฐ˜ํ™˜๊ฐ’์ด ์—†๋Š”๊ฒŒ ์ข‹์Œ(์ปค๋งจ๋“œ์™€ ์ฟผ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌ)
@PutMapping("/api/v2/members/{id}")
public UpdateMemberResponse updateMemberV2(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request) {
    memberService.update(id, request.getName());
    Member findMember = memberService.findOne(id);
    return new UpdateMemberResponse(findMember.getId(), findMember.getName());
}

# ํšŒ์› ์กฐํšŒ API

// Entity๋ฅผ @JSonIgnore๋ฅผ ํ•˜๋Š” ํ˜•ํƒœ๋กœ๋„ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ ˆ๋Œ€ํ•˜์ง€ ์•Š๊ธฐ
// Entity์˜ ๊ฐ’์„ ๋ณ€๊ฒฝ์‹œ api์˜ Spec์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์•ˆ๋จ
// Spec ํ™•์žฅ์„ ๊ณ ๋ คํ•ด์„œ data์— Array๋ฅผ ๋„ฃ๋Š” ํ˜•ํƒœ๋กœ ์ง„ํ–‰
@GetMapping("/api/v2/members")
public Result membersV2() {

    List<Member> findMembers = memberService.findMembers();
    //์—”ํ‹ฐํ‹ฐ -> DTO ๋ณ€ํ™˜
    List<MemberDto> collect = findMembers.stream()
            .map(m -> new MemberDto(m.getName()))
            .collect(Collectors.toList());
    return new Result(collect);
}

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ - ์ค€๋น„

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ ์†Œ๊ฐœ

์กฐํšŒ์šฉ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ
์ง€์—ฐ ๋กœ๋”ฉ๊ณผ ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”
์ปฌ๋ ‰์…˜ ์กฐํšŒ ์ตœ์ ํ™”
ํŽ˜์ด์ง•๊ณผ ํ•œ๊ณ„ ๋ŒํŒŒ
OSIV์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”

# ์กฐํšŒ์šฉ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ

userA
-JPA1 BOOK
-JPA2 BOOK

userB
-SPRING1 BOOK
-SPRING2 BOOK


initService.dbInit1();
initService.dbInit2();

  jpa:
    hibernate:
      ddl-auto: create

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ - ์ง€์—ฐ ๋กœ๋”ฉ๊ณผ ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”

# ๊ฐ„๋‹จํ•œ ์ฃผ๋ฌธ ์กฐํšŒ V1: ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ง์ ‘ ๋…ธ์ถœ

์ฃผ๋ฌธ + ๋ฐฐ์†ก์ •๋ณด + ํšŒ์›์„ ์กฐํšŒํ•˜๋Š” API๋ฅผ ๋งŒ๋“ค์ž
์ง€์—ฐ ๋กœ๋”ฉ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ๋‹จ๊ณ„์ ์œผ๋กœ ํ•ด๊ฒฐํ•ด๋ณด์ž.

์ฐธ๊ณ : ์ง€๊ธˆ๋ถ€ํ„ฐ ์„ค๋ช…ํ•˜๋Š” ๋‚ด์šฉ์€ ์ •๋ง ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด 100% ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ManyToOne, OneToOne ์„ฑ๋Šฅ์ตœ์ ํ™”


localhost:8080/api/v1/simple-orders

์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ @JsonIgnore

fetch =LAZY ์ง€์—ฐ๋กœ๋”ฉ ์‹œ.. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ Hibernate5Module
Configure๋ฅผ ์ˆ˜์ •ํ•ด์„œ ๊ฐ•์ œ Lazy๋กœ๋”ฉ์„ ํ•˜๊ฒŒํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํ•˜๋ฉด์•ˆ๋จ..
hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);

์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ•์ œ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Œ
for (Order order : all) {
    order.getMember().getName(); //Lazy ๊ฐ•์ œ ์ดˆ๊ธฐํ™”
    order.getDelivery().getAddress(); //Lazy ๊ฐ•์ œ ์ดˆ๊ธฐํ™”
}

์ง€์—ฐ ๋กœ๋”ฉ(LAZY)๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์ฆ‰์‹œ ๋กœ๋”ฉ(EARER)์œผ๋กœ ์„ค์ •ํ•˜๋ฉด ์•ˆ๋จ. ์ฆ‰์‹œ๋กœ๋”ฉ์€ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ํ•„์š”์—†์„๋•Œ๋„ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ญ์ƒ์กฐํšŒํ•ด์„œ ์„ฑ๋Šฅ๋ฌธ์ œ๋ฅผ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ
์ฆ‰์‹œ ๋กœ๋”ฉ์œผ๋กœ ์„ค์ • ์‹œ ์„ฑ๋Šฅ ํŠœ๋‹์ด ์–ด๋ ค์›Œ์ง
ํ•ญ์ƒ ์ง€์—ฐ๋กœ๋”ฉ์„ ๊ธฐ๋ณธ์œผ๋กœํ•˜๊ณ , ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํŽ˜์น˜์กฐ์ธ(fetch join)์„ ์‚ฌ์šฉ



# ๊ฐ„๋‹จํ•œ ์ฃผ๋ฌธ ์กฐํšŒ V2: ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜

#  org.hibernate.type: trace

@ManyToOne(fetch = EAGER) ํ•˜๋ฉด ์•ˆ๋˜๋Š” ์ด์œ  
@ManyToOne(fetch = LAZY)๋ฅผ ์‚ฌ์šฉ

์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•
์ฟผ๋ฆฌ๊ฐ€ ์ด 1 + N + N๋ฒˆ ์‹คํ–‰๋œ๋‹ค. (v1๊ณผ ์ฟผ๋ฆฌ์ˆ˜ ๊ฒฐ๊ณผ๋Š” ๊ฐ™๋‹ค.)

@GetMapping("/api/v2/simple-orders")
public List<SimpleOrderDto> ordersV2() {
    // ORDER 2๊ฐœ
    // N + 1 -> 1 + ํšŒ์› N + ๋ฐฐ์†ก N
    List<Order> orders = orderRepository.findAll();
    List<SimpleOrderDto> result = orders.stream()
            .map(o -> new SimpleOrderDto(o))
            .collect(toList());

    return result;
}

# ๊ฐ„๋‹จํ•œ ์ฃผ๋ฌธ ์กฐํšŒ V3: ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜ - ํŽ˜์น˜ ์กฐ์ธ ์ตœ์ ํ™”

# ๊ฐ„๋‹จํ•œ ์ฃผ๋ฌธ ์กฐํšŒ V4: JPA์—์„œ DTO๋กœ ๋ฐ”๋กœ ์กฐํšŒ

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ - ์ปฌ๋ ‰์…˜ ์กฐํšŒ ์ตœ์ ํ™”

# ์ฃผ๋ฌธ ์กฐํšŒ V1: ์—”ํ‹ฐํ‹ฐ ์ง์ ‘ ๋…ธ์ถœ

# ์ฃผ๋ฌธ ์กฐํšŒ V2: ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜

# ์ฃผ๋ฌธ ์กฐํšŒ V3: ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜ - ํŽ˜์น˜ ์กฐ์ธ ์ตœ์ ํ™”

# ์ฃผ๋ฌธ ์กฐํšŒ V3.1: ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜ - ํŽ˜์ด์ง•๊ณผ ํ•œ๊ณ„ ๋ŒํŒŒ

# ์ฃผ๋ฌธ ์กฐํšŒ V4: JPA์—์„œ DTO ์ง์ ‘ ์กฐํšŒ

# ์ฃผ๋ฌธ ์กฐํšŒ V5: JPA์—์„œ DTO ์ง์ ‘ ์กฐํšŒ - ์ปฌ๋ ‰์…˜ ์กฐํšŒ ์ตœ์ ํ™”

# ์ฃผ๋ฌธ ์กฐํšŒ V6: JPA์—์„œ DTO๋กœ ์ง์ ‘ ์กฐํšŒ, ํ”Œ๋žซ ๋ฐ์ดํ„ฐ ์ตœ์ ํ™”

ํ•œ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ์‹คํ–‰์ด ๊ฐ€๋Šฅ

// OrderQueryRepository
public List<OrderFlatDto> findAllByDto_flat() {
    return em.createQuery(
            "select new jpabook.jpashop.repository.order.query.OrderFlatDto(o.id, m.name, o.orderDate, o.status, d.address, i.name, oi.orderPrice, oi.count)" +
                    " from Order o" +
                    " join o.member m" +
                    " join o.delivery d" +
                    " join o.orderItems oi" +
                    " join oi.item i", OrderFlatDto.class)
            .getResultList();
}

// OrderApiController
@GetMapping("/api/v6/orders")
public List<OrderQueryDto> ordersV6() {
    List<OrderFlatDto> flats = orderQueryRepository.findAllByDto_flat();

    return flats.stream()
            .collect(groupingBy(o -> new OrderQueryDto(o.getOrderId(), o.getName(), o.getOrderDate(), o.getOrderStatus(), o.getAddress()),
                    mapping(o -> new OrderItemQueryDto(o.getOrderId(), o.getItemName(), o.getOrderPrice(), o.getCount()), toList())
            )).entrySet().stream()
            .map(e -> new OrderQueryDto(e.getKey().getOrderId(), e.getKey().getName(), e.getKey().getOrderDate(), e.getKey().getOrderStatus(), e.getKey().getAddress(), e.getValue()))
            .collect(toList());
}

// OrderQueryDto
@EqualsAndHashCode(of = "orderId")

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ ์ •๋ฆฌ

*์—”ํ‹ฐํ‹ฐ ์กฐํšŒ
- ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•ด์„œ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜: V1
- ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ ํ›„ DTO๋กœ ๋ณ€ํ™˜: V2
- ํŽ˜์น˜ ์กฐ์ธ์œผ๋กœ ์ฟผ๋ฆฌ ์ˆ˜ ์ตœ์ ํ™”: V3
- ์ปฌ๋ ‰์…˜ ํŽ˜์ด์ง•๊ณผ ํ•œ๊ณ„ ๋ŒํŒŒ: V3.1
    - ์ปฌ๋ ‰์…˜์€ ํŽ˜์น˜ ์กฐ์ธ์‹œ ํŽ˜์ด์ง•์ด ๋ถˆ๊ฐ€๋Šฅ
    - ToOne ๊ด€๊ณ„๋Š” ํŽ˜์น˜ ์กฐ์ธ์œผ๋กœ ์ฟผ๋ฆฌ ์ˆ˜ ์ตœ์ ํ™”
    - ์ปฌ๋ ‰์…˜์€ ํŽ˜์น˜ ์กฐ์ธ ๋Œ€์‹ ์— ์ง€์—ฐ ๋กœ๋”ฉ์„ ์œ ์ง€ํ•˜๊ณ , hibernate.default_batch_fetch_size,
      @BatchSize๋กœ ์ตœ์ ํ™”

*DTO ์ง์ ‘์กฐํšŒ
- JPA์—์„œ DTO๋ฅผ ์ง์ ‘ ์กฐํšŒ: V4
- ์ปฌ๋ ‰์…˜ ์กฐํšŒ ์ตœ์ ํ™”- ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์ธ ์ปฌ๋ ‰์…˜์€ IN ์ ˆ์„ ํ™œ์šฉํ•ด์„œ ๋ฉ”๋ชจ๋ฆฌ์— ๋ฏธ๋ฆฌ ์กฐํšŒํ•ด์„œ ์ตœ์ ํ™”: V5
- ํ”Œ๋žซ ๋ฐ์ดํ„ฐ ์ตœ์ ํ™” - JOIN ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋Œ€๋กœ ์กฐํšŒ ํ›„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์›ํ•˜๋Š” ๋ชจ์–‘์œผ๋กœ ์ง์ ‘ ๋ณ€ํ™˜: V6

*๊ถŒ์žฅ์ˆœ์„œ
1. ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฐฉ์‹์œผ๋กœ ์šฐ์„  ์ ‘๊ทผ
    1.ํŽ˜์น˜์กฐ์ธ์œผ๋กœ ์ฟผ๋ฆฌ ์ˆ˜๋ฅผ ์ตœ์ ํ™”
    2.์ปฌ๋ ‰์…˜ ์ตœ์ ํ™”
        1.ํŽ˜์ด์ง• ํ•„์š” -> hibernate.default_batch_fetch_size, @BatchSize๋กœ ์ตœ์ ํ™”
        2. ํŽ˜์ด์ง• ํ•„์š”x -> ํŽ˜์น˜ ์กฐ์ธ ์‚ฌ์šฉ
2. ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐ์ด ์•ˆ๋˜๋ฉด DTO ์กฐํšŒ ๋ฐฉ์‹ ์‚ฌ์šฉ
3. DTO ์กฐํšŒ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐ์ด ์•ˆ๋˜๋ฉด NativeSQL or Spring JdbcTemplate

์ฐธ๊ณ : ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ ๋ฐฉ์‹์€ ํŽ˜์น˜ ์กฐ์ธ์ด๋‚˜, hibernate.default_batch_fetch_size, @BatchSize ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ๊ฑฐ์˜ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ , ์˜ต์…˜๋งŒ ์•ฝ๊ฐ„ ๋ณ€๊ฒฝํ•ด์„œ, ๋‹ค์–‘ํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด์— DTO๋ฅผ ์ง์ ‘ ์กฐํšŒํ•˜๋Š” ๋ฐฉ์‹์€ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•˜๊ฑฐ๋‚˜ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•  ๋•Œ ๋งŽ์€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค.

์ฐธ๊ณ : ๊ฐœ๋ฐœ์ž๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ์ฝ”๋“œ ๋ณต์žก๋„ ์‚ฌ์ด์—์„œ ์ค„ํƒ€๊ธฐ๋ฅผ ํ•ด์•ผํ•œ๋‹ค. ํ•ญ์ƒ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ณดํ†ต ์„ฑ๋Šฅ ์ตœ์ ํ™”๋Š” ๋‹จ์ˆœํ•œ ์ฝ”๋“œ๋ฅผ ๋ณต์žกํ•œ ์ฝ”๋“œ๋กœ ๋ชฐ๊ณ ๊ฐ„๋‹ค.
์—”ํ‹ฐํ‹ฐ ์กฐํšŒ๋ฐฉ์‹์€ JPA๊ฐ€ ๋งŽ์€ ๋ถ€๋ถ„์„ ์ตœ์ ํ™” ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์—, ๋‹จ์ˆœํ•œ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ, ์„ฑ๋Šฅ์„ ์ตœ์ ํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ฐ˜๋ฉด์— DTO ์กฐํšŒ ๋ฐฉ์‹์€ SQL์„ ์ง์ ‘ ๋‹ค๋ฃจ๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‘˜ ์‚ฌ์ด์— ์ค„ํƒ€๊ธฐ๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค.


DTO ์กฐํšŒ ๋ฐฉ์‹์˜ ์„ ํƒ์ง€
- DTO๋กœ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ๊ฐ๊ฐ ์žฅ๋‹จ์ด ์žˆ๋‹ค. V4, V5, V6์—์„œ ๋‹จ์ˆœํ•˜๊ฒŒ ์ฟผ๋ฆฌ๊ฐ€ 1๋ฒˆ ์‹คํ–‰๋œ๋‹ค๊ณ  V6์ด ํ•ญ์ƒ ์ข‹์€ ๋ฐฉ๋ฒ•์ธ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.
-V4๋Š” ์ฝ”๋“œ๊ฐ€ ๋‹จ์ˆœํ•˜๊ฐ€. ํŠน์ • ์ฃผ๋ฌธ ํ•œ๊ฑด๋งŒ ์กฐํšŒํ•˜๋ฉด ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด๋„ ์„ฑ๋Šฅ์ด ์ž˜ ๋‚˜์˜จ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ ์กฐํšŒํ•œ Order๋ฐ์ดํ„ฐ๊ฐ€ 1๊ฑด์ด๋ฉด OrderItem์„ ์ฐพ๊ธฐ ์œ„ํ•œ ์ฟผ๋ฆฌ๋„ 1๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.
-V5๋Š” ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•˜๋‹ค. ์—ฌ๋Ÿฌ ์ฃผ๋ฌธ์„ ํ•œ๊บผ๋ฒˆ์— ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” V4 ๋Œ€์‹ ์— ์ด๊ฒƒ์„ ์ตœ์ ํ™”ํ•œ V5 ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ ์กฐํšŒํ•œ Order๋ฐ์ดํ„ฐ๊ฐ€ 1000๊ฑด์ธ๋ฐ, V4 ๋ฐฉ์‹์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด, ์ฟผ๋ฆฌ๊ฐ€ ์ด 1 + 1000๋ฒˆ ์‹คํ–‰๋œ๋‹ค. ์—ฌ๊ธฐ์„œ 1์€ Order๋ฅผ ์กฐํšŒํ•œ ์ฟผ๋ฆฌ๊ณ , 1000์€ ์กฐํšŒ๋œ Order์˜ row ์ˆ˜๋‹ค. V5 ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™” ํ•˜๋ฉด ์ฟผ๋ฆฌ๊ฐ€ ์ด 1 + 1๋ฒˆ๋งŒ ์‹คํ–‰๋œ๋‹ค. ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒ ์ง€๋งŒ ์šด์˜ ํ™˜๊ฒฝ์—์„œ 100๋ฐฐ ์ด์ƒ์˜ ์„ฑ๋Šฅ ์ฐจ์ด๊ฐ€ ๋‚  ์ˆ˜ ์žˆ๋‹ค.
-V6๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ ‘๊ทผ๋ฐฉ์‹์ด๋‹ค. ์ฟผ๋ฆฌ ํ•œ๋ฒˆ์œผ๋กœ ์ตœ์ ํ™” ๋˜์–ด์„œ ์ƒ๋‹นํžˆ ์ข‹์•„๋ณด์ด์ง€๋งŒ, Order๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํŽ˜์ด์ง•์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์‹ค๋ฌด์—์„œ๋Š” ์ด์ •๋„ ๋ฐ์ดํ„ฐ๋ฉด ์ˆ˜๋ฐฑ์ด๋‚˜, ์ˆ˜์ฒœ๊ฑด ๋‹จ์œ„๋กœ ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๊ฐ€ ๊ผญ ํ•„์š”ํ•˜๋ฏ€๋กœ, ์ด ๊ฒฝ์šฐ ์„ ํƒํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฐฉ๋ฒ•์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์œผ๋ฉด ์ค‘๋ณต ์ „์†ก์ด ์ฆ๊ฐ€ํ•ด์„œ V5์™€ ๋น„๊ตํ•ด์„œ ์„ฑ๋Šฅ ์ฐจ์ด๋„ ๋ฏธ๋น„ํ•˜๋‹ค.

# API ๊ฐœ๋ฐœ ๊ณ ๊ธ‰ - ์‹ค๋ฌด ํ•„์ˆ˜ ์ตœ์ ํ™”

# OSIV์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”

# ๋‹ค์Œ์œผ๋กœ

# ์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA ์†Œ๊ฐœ

# QueryDSL ์†Œ๊ฐœ

Last Updated: 4/13/2025, 11:14:44 PM