Skip to content

[๐ŸŒฑ JPA ๋ฐฉํƒˆ์ถœ ์˜ˆ์•ฝ ๋Œ€๊ธฐ] ํ”ผ์˜จ(์ž„ํ˜„์ˆ˜) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.#575

Open
everypine wants to merge 11 commits into
woowacourse:everypinefrom
everypine:jpa
Open

[๐ŸŒฑ JPA ๋ฐฉํƒˆ์ถœ ์˜ˆ์•ฝ ๋Œ€๊ธฐ] ํ”ผ์˜จ(์ž„ํ˜„์ˆ˜) ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.#575
everypine wants to merge 11 commits into
woowacourse:everypinefrom
everypine:jpa

Conversation

@everypine

@everypine everypine commented Jun 18, 2026

Copy link
Copy Markdown

๋‹จ๊ณ„๋ณ„ ๋„๋‹ฌ ์ง€์ 

  • 0๋‹จ๊ณ„: everypine -> jpa๋กœ ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ ๋ฐ ์ฒดํฌ์•„์›ƒ, ๋ฐฉํƒˆ์ถœ ๋ฏธ์…˜ ๋™์ž‘ ํ™•์ธ
  • 1๋‹จ๊ณ„: JdbcTemplate -> JPA ์ „ํ™˜, ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๊ด€์ฐฐ ๋ฐ ์‹ ํ˜ธ ํ™•์ธ
  • 2๋‹จ๊ณ„: ๋ณธ์ธ ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ API๋ฅผ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์ˆ˜์ • (๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์ฟผ๋ฆฌ ์‚ฌ์šฉ)
  • 3๋‹จ๊ณ„: ์˜ˆ์•ฝ ๋Œ€๊ธฐ ์š”์ฒญ(์˜ˆ์•ฝ ๊ธฐ๋Šฅ์— ํฌํ•จ) ๋ฐ ์ทจ์†Œ (soft delete), ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ์— ๋Œ€๊ธฐ ์˜ˆ์•ฝ๋„ ํฌํ•จ, ์˜ˆ์•ฝ ์ˆœ๋ฒˆ ํ‘œ์‹œ ์ถ”๊ฐ€
  • 4๋‹จ๊ณ„: ๊ด€๋ฆฌ์ž ๋Œ€๊ธฐ ๋ชฉ๋ก ์กฐํšŒ, ์ทจ์†Œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€, ์ž๋™ ๋ฐฉ์‹์˜ ์˜ˆ์•ฝ ๋Œ€๊ธฐ ์Šน์ธ ๊ธฐ๋Šฅ ์ถ”๊ฐ€

๋ฐœํ–‰ SQL ๋ฐœ์ทŒ

1. IDENTITY strategy๋กœ ์ƒ์„ฑํ•˜๋Š” @GeneratedValue

insert 
    into
        reservation
        (date_id, name, status, theme_id, time_id, waiting_order, id) 
    values
        (?, ?, ?, ?, ?, ?, default)
  • JdbcTemplate: id๊ฐ€ ๋‹ด๊ธฐ์ง€ ์•Š๋Š” ์•”๋ฌต์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‚ฝ์ž…
  • JPA: IDENTITY strategy์—์„œ๋Š” id ์ƒ์„ฑ์„ DB์— ์œ„์ž„, default๋Š” Hibernate์˜ DB dialect์— ๋”ฐ๋ผ ๋ช…์‹œ๋œ ํ‘œํ˜„

2. ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ์กฐํšŒ

๋‹ค์Œ์€ findById(reservationId).getTime().getStartAt()๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ ๋ฐœํ–‰๋˜๋Š” SQL์ด๋‹ค

select 
	r1_0.id, 
	r1_0.date_id, 
	r1_0.name, 
	r1_0.status, 
	r1_0.theme_id, 
	r1_0.time_id, 
	r1_0.waiting_order 
from 
	reservation r1_0 
where 
	r1_0.id=? 

select 
	rt1_0.id, 
	rt1_0.is_active, 
	rt1_0.start_at 
from 
	reservation_time rt1_0 
where 
	rt1_0.id=?

findById(...)๊นŒ์ง€๋Š” ์™ธ๋ž˜ํ‚ค ์ปฌ๋Ÿผ์ธ time_id๋งŒ ์กฐํšŒํ•˜๊ณ , ์ดํ›„ LAZY ์—ฐ๊ด€ ๊ด€๊ณ„์˜ ์‹ค์ œ ํ•„๋“œ์— ์ ‘๊ทผํ•˜๋ฉด ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

3. fetch join ์ฟผ๋ฆฌ

select
        r1_0.id, r1_0.date_id,
        d1_0.id, d1_0.date, d1_0.is_active,
        r1_0.member_id, r1_0.status, r1_0.theme_id,
        t1_0.id, t1_0.description, t1_0.is_active, t1_0.name, t1_0.thumbnail_url,
        r1_0.time_id,
        t2_0.id, t2_0.is_active, t2_0.start_at,
        r1_0.waiting_order 
    from
        reservation r1_0 
    left join
        member m1_0 
            on m1_0.id=r1_0.member_id 
    join
        reservation_date d1_0 
            on d1_0.id=r1_0.date_id 
    join
        theme t1_0 
            on t1_0.id=r1_0.theme_id 
    join
        reservation_time t2_0 
            on t2_0.id=r1_0.time_id 
    where
        m1_0.id=? 
    order by
        r1_0.id desc

๋‹ค์Œ SQL์€ ์•„๋ž˜ ์ฝ”๋“œ๊ฐ€ ๋ฐœํ–‰ํ•œ SQL๋ฌธ์ด๋‹ค.

@EntityGraph(attributePaths = {"date", "time", "theme"})  
List<Reservation> findAllByMemberIdOrderByIdDesc(Long id);
  • date, time, theme๋Š” ์กฐํšŒ ์‹œ์ ์— ํ•จ๊ป˜ ๋กœ๋”ฉ๋˜๊ฒŒ๋” ์„ค์ •๋˜์—ˆ๋‹ค.
  • member๋Š” attributePaths์— ๋“ฑ๋ก๋˜์ง€ ์•Š์•„ ์ง€์—ฐ ๋กœ๋”ฉ ๋Œ€์ƒ์ด์ง€๋งŒ where ์กฐ๊ฑด์ ˆ์„ ์œ„ํ•ด join ์—ฐ์‚ฐ์ด ์‹คํ–‰๋˜์—ˆ๋‹ค.

๋ง์„ค์ธ ๊ฒฐ์ •

1. ๋ณธ์ธ ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ(GET /reservations-mine) ์ฟผ๋ฆฌ ๊ตฌ์„ฑ

  • ์„ ํƒ์ง€ A: ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์ฟผ๋ฆฌ ๋ฐฉ์‹ ์‚ฌ์šฉ
  • ์„ ํƒ์ง€ B: JPQL ๋ฐฉ์‹ ์‚ฌ์šฉ
  • ๋‚˜์˜ ์„ ํƒ: B
  • ์ด์œ : ๋‹จ์ˆœ ์˜ˆ์•ฝ ๋ชฉ๋ก๋งŒ ์กฐํšŒํ•œ๋‹ค๋ฉด findByMemberId๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ–ˆ์„ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ํ˜„์žฌ ๊ตฌ์กฐ์—์„œ๋Š” ์˜ˆ์•ฝ์ด ๋Œ€๊ธฐ ์ƒํƒœ์ด๋ฉด ์ˆœ๋ฒˆ ์ •๋ณด๋„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์ฟผ๋ฆฌ ๋ฐฉ์‹๋งŒ์œผ๋กœ๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ JPQL๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

2. ์ˆœ๋ฒˆ ์ •๋ณด๊ฐ€ ์—†๋Š” ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ์—์„œ์˜ ์—ฐ๊ด€ ์—”ํ‹ฐํ‹ฐ ์กฐํšŒ ๋ฐฉ์‹

  • ์„ ํƒ์ง€ A: JPQL์— fetch join ๋ช…์‹œ
  • ์„ ํƒ์ง€ B: @EntityGraph ์‚ฌ์šฉ
  • ๋‚˜์˜ ์„ ํƒ: B
  • ์ด์œ : ์„ ํƒ์ง€ A๋Š” JPQL์„ ์‚ฌ์šฉํ•˜๋Š” ์ „์ œ๊ฐ€ ์žˆ๋Š”๋ฐ ์ˆœ๋ฒˆ ์ •๋ณด๊ฐ€ ์—†๋Š” ์˜ˆ์•ฝ ๋ชฉ๋ก ์กฐํšŒ๋Š” ๋ณต์žกํ•œ ์กฐ๊ฑด์ด ์—†์–ด ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ์ฟผ๋ฆฌ๋กœ๋„ ์ถฉ๋ถ„ํ•˜๊ธฐ์— ๊ณ ๋ ค๋ฅผ ํ•˜์ง€ ์•Š์•˜๋‹ค. ๋˜ํ•œ, ์„ ํƒ์ง€ B์˜ ๊ฒฝ์šฐ์—๋Š” ์–ด๋–ค ์—ฐ๊ด€ ์ •๋ณด๋ฅผ ๋กœ๋”ฉํ• ์ง€ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ๋Š” ์žฅ์ ๋„ ์žˆ์—ˆ๋‹ค.

ํ”๋“ค๋ฆฐ ํ•œ ์žฅ๋ฉด

๋Œ€๊ธฐ ์˜ˆ์•ฝ ์Šน์ธ ๋กœ์ง์€ ๊ธฐ์กด์— ์ด๋ฏธ ๋™์‹œ์„ฑ์„ ์ถฉ๋ถ„ํžˆ ๊ณ ๋ คํ•˜์—ฌ ์ž‘์„ฑํ•˜์˜€๊ธฐ์— Jdbc -> JPA ์ „ํ™˜ ๊ณผ์ •์—์„œ๋„ ํฌ๊ฒŒ ๊ฑด๋“ค์ง€ ์•Š์•„๋„ ๋˜๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ JPA์—์„œ๋Š” ๊ฐ™์€ id๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ์˜ ์žฌ์กฐํšŒ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด db์—์„œ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  1์ฐจ ์บ์‹œ์—์„œ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ฐ„๊ณผํ–ˆ๋‹ค. ์ฆ‰, ํŠธ๋žœ์žญ์…˜ ์ค‘๊ฐ„์— DB ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋กœ์ง์ด JPA ํ™˜๊ฒฝ์—์„œ๋Š” ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ฒ˜์Œ์— ์กฐํšŒํ•œ ์ปจํ…์ŠคํŠธ ๋‚ด reservation์„ refreshํ•˜๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์žฌํ™•์ธ์ด ์•ˆ๋˜๋˜ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.

everypine added 11 commits June 15, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant