๐ŸŒˆ [Section3] 6. [ Spring MVC ] Spring Data JDBC 2

ํ˜„์ฃผยท2022๋…„ 11์›” 1์ผ
1

bootcamp

๋ชฉ๋ก ๋ณด๊ธฐ
46/71

๐Ÿ“• ์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ!

  • DDD (Domain Driven Design)
  • ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ (Aggregate)
  • ํŽ˜์ด์ง€๋„ค์ด์…˜
  • n+1 ๋ฌธ์ œ

โœ๏ธ DDD (Domain Driven Design)

  • ๋” ๋‚˜์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค๊ณ„๋ฅผ ์œ„ํ•œ ๋„๋ฉ”์ธ ์œ„์ฃผ์˜ ์„ค๊ณ„ ๊ธฐ๋ฒ•

  • ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๋„๋ฉ”์ธ ๋ชจ๋ธ ์œ„์ฃผ๋กœ ๋Œ์•„๊ฐ€๊ฒŒ ์„ค๊ณ„ํ•˜๋Š” ๊ธฐ๋ฒ•

โœ”๏ธ ๋„๋ฉ”์ธ (Domain)

  • ์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ๋กœ ํ˜„์‹ค ์„ธ๊ณ„์—์„œ ์ ‘ํ•˜๋Š” ์—…๋ฌด์˜ ํ•œ ์˜์—ญ ( ๋น„์ฆˆ๋‹ˆ์Šค์ ์ธ ์–ด๋–ค ์—…๋ฌด ์˜์—ญ )
  • ๋„๋ฉ”์ธ ์ง€์‹(Domain Knoledge)๋“ค์„ ์„œ๋น„์Šค ๊ณ„์ธต์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผํ•จ
    โ €
    Ex. ๋ฐฐ๋‹ฌ ์ฃผ๋ฌธ ์•ฑ์˜ ์ƒ์œ„ ์ˆ˜์ค€ ๋„๋ฉ”์ธ - ํšŒ์› / ์ฃผ๋ฌธ / ์Œ์‹ / ๊ฒฐ์ œ / ๋ฐฐ๋‹ฌ ๋“ฑ
    โ €
    ์ด ์•ˆ์—์„œ๋„ ๋„๋ฉ”์ธ์„ ํ•˜์œ„ ์ˆ˜์ค€ ๋„๋ฉ”์ธ์œผ๋กœ ์„ธ๋ถ„ํ™”ํ•  ์ˆ˜ ์žˆ์Œ โฌ‡๏ธ
    Ex. ์ฃผ๋ฌธ - ์ฃผ๋ฌธ์ž ์ •๋ณด / ์ฃผ๋ฌธ ์ •๋ณด / ์Œ์‹ ์ •๋ณด / ์ฃผ์†Œ ์ •๋ณด ๋“ฑ

โœ”๏ธ ๋„๋ฉ”์ธ ์ง€์‹ (Domain Knoledge)

  • ๊ทธ ๋„๋ฉ”์ธ์˜ ์ „๋ฌธํ™”๋œ ๊ด€๋ จ ์ง€์‹

[์ฐธ๊ณ ] https://ko.wikipedia.org/wiki/%EB%8F%84%EB%A9%94%EC%9D%B8_%EC%A3%BC%EB%8F%84_%EC%84%A4%EA%B3%84

๋นˆ์•ฝํ•œ ๋„๋ฉ”์ธ ๋ชจ๋ธ vs ํ’๋ถ€ํ•œ ๋„๋ฉ”์ธ ๋ชจ๋ธ
๋นˆ์•ฝ - Service ํด๋ž˜์Šค์— ๊ธฐ๋Šฅ ์ง‘์ค‘ ๋˜์–ด ์žˆ๊ณ , Entity ํด๋ž˜์Šค์—๋Š” ๊ธฐ๋Šฅ์ด ์—†๊ณ  ํ•„๋“œ๋งŒ ์žˆ์Œ
ํ’๋ถ€ - Service ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์ด ์ถ•์†Œ ๋˜๊ณ , Entity ํด๋ž˜์Šค์— ๊ธฐ๋Šฅ์ด ๋งŽ์ด ๋“ค์–ด์žˆ์Œ


โœ๏ธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ (Aggregate)

  • ๋น„์Šทํ•œ ๋ฒ”์ฃผ์˜ ์—ฐ๊ด€๋œ ์—…๋ฌด๋“ค์„ ํ•˜๋‚˜๋กœ ๊ทธ๋ฃนํ™” ํ•ด๋†“์€ ๋ฌถ์Œ
    (๋น„์Šทํ•œ ์—…๋ฌด ๋„๋ฉ”์ธ๋“ค์˜ ๋ฌถ์Œ)

  • DDD(Domain-Driven Design)์˜ ํŒจํ„ด
    โ €
    Ex. ๋ฐฐ๋‹ฌ ์ฃผ๋ฌธ ์•ฑ์—์„œ - ํšŒ์› ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ / ์ฃผ๋ฌธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ / ์Œ์‹ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ / ๊ฒฐ์ œ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋“ฑ
    ( ํ•œ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ์•ˆ์—๋Š” 1๊ฐœ ์ด์ƒ์˜ ๋„๋ฉ”์ธ(ํ•˜์œ„ ์ˆ˜์ค€ ๋„๋ฉ”์ธ)๋“ค์ด ์กด์žฌ )

[์ฐธ๊ณ ] https://www.alibabacloud.com/blog/an-in-depth-understanding-of-aggregation-in-domain-driven-design_598034

โœ๏ธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ (Aggregate Root)

  • ๋ฃจํŠธ ์—”ํ‹ฐํ‹ฐ(Root Entity)๋ผ๊ณ ๋„ ํ•จ

  • ํ•˜๋‚˜์˜ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ๋ฅผ ๋Œ€ํ‘œํ•˜๋Š” ๋„๋ฉ”์ธ
    ( ํ•œ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ์•ˆ์˜ 1๊ฐœ ์ด์ƒ์˜ ๋„๋ฉ”์ธ๋“ค ์ค‘์— ๊ทธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ๋ฅผ ๋Œ€ํ‘œํ•  ์ˆ˜ ์žˆ๋Š” ๋„๋ฉ”์ธ )
    โ €
    Ex. ์•„ํŒŒํŠธ(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ)์˜ 1,2,3๋™์˜ ๋™๋Œ€ํ‘œ๋“ค (์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ)

  • ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋‚ด์˜ ๋„๋ฉ”์ธ๋“ค ์ค‘, ๋‹ค๋ฅธ ๋ชจ๋“  ๋„๋ฉ”์ธ๋“ค๊ณผ ์ง๊ฐ„์ ‘์ ์œผ๋กœ ์—ฐ๊ด€์ด ๋˜์–ด ์žˆ๋Š” ๋„๋ฉ”์ธ๋“ค

    Ex.

    • ํšŒ์› ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ
      โžœ ํšŒ์› ์ •๋ณด๊ฐ€ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ
      ( ํšŒ์› ์ •๋ณด๋ฅผ ์•Œ์•„์•ผ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๋“ค(ํšŒ์› ํฌ์ธํŠธ, ํšŒ์› ๋“ฑ๊ธ‰ ๋“ฑ)์„ ์•Œ ์ˆ˜ ์žˆ์Œ )
      โ €
    • ์ฃผ๋ฌธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ
      โžœ ์ฃผ๋ฌธ ์ •๋ณด๊ฐ€ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ
      ( ์ฃผ๋ฌธ ์ •๋ณผ๋ฅด ์•Œ์•„์•ผ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๋“ค(์ฃผ๋ฌธ์ž, ์ฃผ๋ฌธ ์Œ์‹ ๋“ฑ)์„ ์•Œ ์ˆ˜ ์žˆ์Œ )
      โ €
      โ— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ๊ด€๊ณ„๋กœ ๋ณด๋ฉด,
      ํ•œ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ์•ˆ์— ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ - ๋ถ€๋ชจ ํ…Œ์ด๋ธ” / ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๋“ค - ์ž์‹ ํ…Œ์ด๋ธ”
  • ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ(Aggregate Root)์˜ ๊ธฐ๋ณธํ‚ค ์ •๋ณด๋ฅผ ๋‹ค๋ฅธ ๋„๋ฉ”์ธ๋“ค์ด ์™ธ๋ž˜ํ‚ค ํ˜•ํƒœ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์Œ
    ( ๊ทธ๋ž˜์•ผ ์ง๊ฐ„์ ‘์ ์œผ๋กœ ์ •๋ณด๋ฅผ ๋นผ์™€ ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ์œผ๋‹ˆ๊นŒ )

    Ex. ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ A ํ…Œ์ด๋ธ” / B ํ…Œ์ด๋ธ”์ด ์žˆ์„ ๋•Œ,
    A ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธํ‚ค๋ฅผ B ํ…Œ์ด๋ธ”์ด ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด,
    A = ๋ถ€๋ชจ ํ…Œ์ด๋ธ” / B = ์ž์‹ ํ…Œ์ด๋ธ”
    โ— ์—ฌ๊ธฐ์„œ ์ž์‹ ํ…Œ์ด๋ธ”(B)์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” A ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธํ‚ค = ์™ธ๋ž˜ํ‚ค


โœ๏ธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๊ฐ„ ๊ด€๊ณ„ ์˜ˆ์‹œ

ํ”„๋กœ์ ํŠธ ์‹ค์Šต์—์„œ ํšŒ์› / ์ฃผ๋ฌธ / ์ปคํ”ผ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ๊ฐ€ ์žˆ๊ณ , ๊ทธ ๊ฐ๊ฐ์— ํšŒ์› ์ •๋ณด(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ), ์ฃผ๋ฌธ ์ •๋ณด(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ) / ์ฃผ๋ฌธ ์ปคํ”ผ ์ •๋ณด, ์ปคํ”ผ ์ •๋ณด(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ)๊ฐ€ ์žˆ๋‹ค.

์ด๋ฅผ ์˜ˆ์‹œ๋กœ ์ƒ๊ฐํ•ด๋ณด๋ฉด,

โœ”๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์—์„œ ๊ฐ๊ฐ์˜ ๊ด€๊ณ„ ( ์™ธ๋ž˜ํ‚ค๋ฅผ ํ†ตํ•ด )

( ์œ„์—์„œ ํ‘œ์‹œํ•œ ๊ฒƒ์ด ์™ธ๋ž˜ํ‚ค(Foreign Key)๊ฐ€ ๋˜๋Š” ๊ฒƒ )

โ— ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ๋Œ€๋ฌธ์ž๋กœ ํ•  ๊ฒฝ์šฐ, ORDER๋Š” ์‚ฌ์šฉ ๋ถˆ๊ฐ€
( ์ฟผ๋ฆฌ๋ฌธ์˜ ORDER BY ์˜ˆ์•ฝ์–ด์— ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— )
โžœ ORDERS ์‚ฌ์šฉํ•ด์•ผํ•จ

  • ํšŒ์› ์ •๋ณด (Member) - ์ฃผ๋ฌธ ์ •๋ณด (Orders)์˜ ๊ด€๊ณ„ ๐Ÿ‘‰ 1 ๋Œ€ N
    ( ํ•œ ๋ช…์˜ ํšŒ์›์€ ์—ฌ๋Ÿฌ ๋ฒˆ ์ฃผ๋ฌธ ๊ฐ€๋Šฅ )

  • ์ฃผ๋ฌธ ์ •๋ณด (Orders) - ์ปคํ”ผ ์ •๋ณด (Coffee)์˜ ๊ด€๊ณ„ ๐Ÿ‘‰ N ๋Œ€ N
    โžœ ํ•œ๋ช…์ด ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ปคํ”ผ ์‹œํ‚ค๊ธฐ ๊ฐ€๋Šฅ
    ( ํ•˜๋‚˜์˜ ์ฃผ๋ฌธ์ด ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ปคํ”ผ ํฌํ•จ ๊ฐ€๋Šฅ )
    โžœ ํ•œ ์ปคํ”ผ๋ฅผ ์—ฌ๋Ÿฌ๋ช…์ด ์‹œํ‚ค๊ธฐ ๊ฐ€๋Šฅ
    ( ํ•˜๋‚˜์˜ ์ปคํ”ผ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฑด์˜ ์ฃผ๋ฌธ์— ํฌํ•จ ๊ฐ€๋Šฅ )

โ— ์œ„์˜ N ๋Œ€ N ๊ด€๊ณ„๋Š” ์กฐ์ธํ…Œ์ด๋ธ”(์ฃผ๋ฌธ ์ปคํ”ผ ์ •๋ณด)์„ ๋„ฃ์–ด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ ! โฌ‡๏ธ

  • ์ฃผ๋ฌธ ์ •๋ณด (Orders) - ์ฃผ๋ฌธ ์ปคํ”ผ ์ •๋ณด (Order_Coffee) ๐Ÿ‘‰ 1 ๋Œ€ N
  • ์ฃผ๋ฌธ ์ปคํ”ผ ์ •๋ณด (Order_Coffee) - ์ปคํ”ผ ์ •๋ณด (Coffee) ๐Ÿ‘‰ N ๋Œ€ 1
    ( ์ฃผ๋ฌธ ์ •๋ณด(1) - ์ฃผ๋ฌธ ์ปคํ”ผ ์ •๋ณด(N) - ์ปคํ”ผ ์ •๋ณด(1) )

โœ”๏ธ ํด๋ž˜์Šค์—์„œ ๊ฐ๊ฐ์˜ ๊ด€๊ณ„ ( ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด )

  • ํšŒ์›(Member) ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค
    โžœ 1์— ํ•ด๋‹น๋˜๋Š” Member ํด๋ž˜์Šค๋Š” N์— ํ•ด๋‹น๋˜๋Š” Order ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋„๋ก List<Order>๋ฅผ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€

    ๐Ÿ’ก ์™œ List๋ฅผ ์ถ”๊ฐ€ํ• ๊นŒ?
    ์นดํŽ˜์—์„œ ์ปคํ”ผ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋“ฏ์ด, Member ํด๋ž˜์Šค ์—ญ์‹œ๋„ ์—ฌ๋Ÿฌ๊ฐœ์˜ Order ํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ !

  • ์ฃผ๋ฌธ(Order) ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค
    โžœ Order ๊ณผ Coffee ํด๋ž˜์Šค์˜ N:N ๊ด€๊ณ„๋ฅผ ๊ฐ๊ฐ 1:N ์œผ๋กœ ๋งŒ๋“ค์ฃผ์–ด,
    1์— ํ•ด๋‹น๋˜๋Š” Order ํด๋ž˜์Šค๋Š” N์— ํ•ด๋‹น๋˜๋Š” OrderCoffee ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋„๋ก List<OrderCoffee>๋ฅผ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€

  • ์ปคํ”ผ(Coffee) ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค
    โžœ Coffee ์™€ Order ํด๋ž˜์Šค์˜ N:N ๊ด€๊ณ„๋ฅผ ๊ฐ๊ฐ 1:N ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ์–ด,
    1์— ํ•ด๋‹น๋˜๋Š” Coffee ํด๋ž˜์Šค๋Š” N์— ํ•ด๋‹น๋˜๋Š” OrderCoffee ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋„๋ก List<OrderCoffee>๋ฅผ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์ถ”๊ฐ€

  • ์ฃผ๋ฌธ_์ปคํ”ผ(OrderCofee) ํด๋ž˜์Šค
    โžœ Order ๊ณผ Coffee ํด๋ž˜์Šค์˜ N:N ๊ด€๊ณ„๋ฅผ ๊ฐ๊ฐ 1:N ์œผ๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” OrderCoffee ํด๋ž˜์Šค ์ถ”๊ฐ€
    โžœ ์ฃผ๋ฌธํ•˜๋Š” ์ปคํ”ผ๊ฐ€ 1์ž” ์ด์ƒ์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— quantity(์ฃผ๋ฌธ ์ˆ˜๋Ÿ‰) ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์ถ”๊ฐ€

โ— Spring Data JDBC๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์œ„์— ์„ค๊ณ„ํ•œ ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์˜ ๊ด€๊ณ„๋ฅผ DDD(Domain Driven Design)์˜ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ(Aggregate) ๋งคํ•‘ ๊ทœ์น™์— ๋งž๊ฒŒ ํ•œ๋ฒˆ ๋” ๋ณ€๊ฒฝํ•ด์•ผํ•จ


โœ๏ธ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๊ฐ์ฒด ๋งคํ•‘ ๊ทœ์น™

โœ”๏ธ 1. ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด์˜ ์ƒํƒœ๋Š” ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋ณ€๊ฒฝ ( ํ•ต์‹ฌ ๊ทœ์น™ )
โ €
Ex. ํšŒ์› ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ์•ˆ์— ํšŒ์› ์ •๋ณด(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ)์™€ ํšŒ์› ํฌ์ธํŠธ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•  ๋•Œ,
ํšŒ์› ํฌ์ธํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ํšŒ์› ์ •๋ณด๋ผ๋Š” ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๋ฅผ ํ†ตํ•ด ํšŒ์› ํฌ์ธํŠธ์— ์ ‘๊ทผํ•œ ๋’ค, ๊ทธ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•จ

๐Ÿ’ก ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๋ฅผ ํ†ตํ•ด์„œ ๋‚˜๋จธ์ง€ ์—”ํ‹ฐํ‹ฐ์— ์ ‘๊ทผํ•œ๋‹ค
โžœ ์–ด๋–ค ์‹์œผ๋กœ๋“  ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๊ฐ€ ๋‚˜๋จธ์ง€ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ์— ๋Œ€ํ•œ ๊ฐ์ฒด๋ฅผ ์ง๊ฐ„์ ‘์ ์œผ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ

๐Ÿ’ก โ— ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋‚˜๋จธ์ง€ ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•˜๋Š” ์ด์œ 

  • ์—”ํ‹ฐํ‹ฐ์— ์ง์ ‘ ์ ‘๊ทผํ•ด์„œ ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝํ•  ๊ฒฝ์šฐ,
    ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ๋ง์•„์•ผํ•˜๋Š” ์ƒํƒœ์—์„œ๋„ ๋ฌด์‹œํ•˜๊ณ  ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋จ
    โžœ ๋„๋ฉ”์ธ ๊ทœ์น™์— ๋Œ€ํ•œ ์ผ๊ด€์„ฑ์ด ๊นจ์ง
    โ €
  • ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ๋ฅผ ๋จผ์ € ๊ฑฐ์ณ์„œ ๋ณ€๊ฒฝ๋  ์กฐ๊ฑด(๊ทœ์น™)์„ ๊ฒ€์ฆํ•œ ํ›„,
    ๊ทธ ๊ฒ€์ฆ์— ํ†ต๊ณผํ•˜๋ฉด ์—”ํ‹ฐํ‹ฐ์˜ ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ
    โžœ ๋„๋ฉ”์ธ ๊ทœ์น™์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋„๋ก
    โ €
    Ex. ์ฃผ๋ฌธ์ด๋ผ๋Š” ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•˜๋ฉด ์ฃผ๋ฌธ ์ •๋ณด(์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ), ๋ฐฐ๋‹ฌ ์ฃผ์†Œ ์ •๋ณด ๋“ฑ์ด ์žˆ์„ ๊ฒƒ์ž„
    ๋ฐฐ๋‹ฌ ์ค‘์ด๋ผ๊ณ  ํ•  ๋•Œ, ๋ฐฐ๋‹ฌ ์ฃผ์†Œ ์ •๋ณด๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์ง€๊ธˆ์ด ์กฐ๋ฆฌ ์ค‘์ธ์ง€ / ๋ฐฐ๋‹ฌ ์ค‘์ธ์ง€ ๊ฒ€์ฆํ•œ ํ›„,
    ์กฐ๋ฆฌ ์ค‘์ด๋ฉด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ณ , ๋ฐฐ๋‹ฌ ์ค‘์ด๋ฉด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ์ด๋Ÿฐ ๊ทœ์น™์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋„๋ก ํ•ด์•ผํ•จ!

โœ”๏ธ 2. ๋™์ผํ•œ ํ•˜๋‚˜์˜ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋‚ด์—์„œ๋Š” ์—”ํ‹ฐํ‹ฐ ๊ฐ„์— ๊ฐ์ฒด๋กœ ์ฐธ์กฐ
( ๋™์ผํ•œ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋‚ด์˜ ์—”ํ‹ฐํ‹ฐ๋ผ๋ฆฌ ์ฐธ์กฐํ•  ๊ฒฝ์šฐ๋งŒ ์ ์šฉ )

โœ”๏ธ 3. ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ ๋Œ€ ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ ๊ฐ„์˜ ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์ฐธ์กฐ

  • ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ ๊ฐ„์˜ ์ฐธ์กฐ๋Š” (๊ฐ์ฒด ์ฐธ์กฐ ๋Œ€์‹ ์—) ์™ธ๋ž˜ํ‚ค ๋ฐฉ์‹์ฒ˜๋Ÿผ ID๋กœ ์ฐธ์กฐ
    ( ์ฐธ์กฐํ•˜๊ณ ์ž ํ•˜๋Š” ์• ๊ทธ๋ฆฌ๊ฑฐํŠธ ๋ฃจํŠธ์˜ ID๋ฅผ ์ฐธ์กฐ๊ฐ’์œผ๋กœ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ )

  • 1๋Œ€1 / 1๋Œ€N ๊ด€๊ณ„์ผ ๋•Œ๋Š” ํ…Œ์ด๋ธ” ๊ฐ„์˜ ์™ธ๋ž˜ํ‚ค ๋ฐฉ์‹๊ณผ ๋™์ผ

  • N๋Œ€N ๊ด€๊ณ„์ผ ๋•Œ๋Š” ์™ธ๋ž˜ํ‚ค ๋ฐฉ์‹์ธ ID ์ฐธ์กฐ / ๊ฐ์ฒด ์ฐธ์กฐ ๋ฐฉ์‹์ด ํ•จ๊ป˜ ์‚ฌ์šฉ

โœ” ์‚ฌ์šฉํ•œ ์• ๋„ˆํ…Œ์ด์…˜ / ์ธํ„ฐํŽ˜์ด์Šค๋“ค

  • โœ”๏ธ @Id
    โžœ ์‹๋ณ„์ž๋กœ ์ง€์ •

    Ex. Member ํด๋ž˜์Šค์˜ memberId ๋ณ€์ˆ˜์— ์ด ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด,
    Member ํด๋ž˜์Šค์˜ ์‹๋ณ„์ž(Primary Key)๋กœ ์ง€์ •๋˜๊ณ ,
    schema.sql์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์—์„œ MEMBER ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋จ

  • โœ”๏ธ @Table
    โžœ ํด๋ž˜์Šค๋ช…๊ณผ ๋ณ„๊ฐœ์˜ ๋งคํ•‘๋  ํ…Œ์ด๋ธ”๋ช…์„ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

    Ex. Order ํด๋ž˜์Šค์—์„œ @Id ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด ์ด ํด๋ž˜์Šค๋Š” ORDER ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋จ
    But, ์ด ๊ฒฝ์šฐ ์ฟผ๋ฆฌ๋ฌธ์˜ ORDER BY ์˜ˆ์•ฝ์–ด๊ฐ€ ์žˆ๊ธฐ์— ๊ฒน์น˜์ง€ ์•Š๊ฒŒ @Table("ORDERS")๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด ORDER๊ฐ€ ์•„๋‹Œ ORDERS๋ผ๋Š” ํ…Œ์ด๋ธ”๋ช…๊ณผ ๋งคํ•‘๋จ

  • โœ”๏ธ AggregateReference<T,ID>
    โžœ 1:N ๊ด€๊ณ„์ผ ๋•Œ,
    Id๋ฅผ ์ด ํด๋ž˜์Šค๋กœ ๊ฐ์‹ธ์„œ ๊ฐ์ฒด ์ฐธ์กฐ๊ฐ€ ์•„๋‹Œ ID ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ฐ์‹ธ์ค„ ์ˆ˜ ์žˆ์Œ
    ( N:N ๊ด€๊ณ„์—์„œ๋Š” ์‚ฌ์šฉ X )
    โ €
    โžœ T - ์ฐธ์กฐ๋œ ์ง‘๊ณ„ ๋ฃจํŠธ์˜ ์œ ํ˜•
    โžœ ID - ์ฐธ์กฐ๋œ ์ง‘๊ณ„ ๋ฃจํŠธ์˜ ID ์œ ํ˜•
    ( ์ฐธ์กฐ๋œ ์ง‘๊ณ„ ๋ฃจํŠธ์˜ ID๋งŒ ๋ณด์œ  )
    โ €
    [์ฐธ๊ณ ] https://docs.spring.io/spring-data/jdbc/docs/current/api/org/springframework/data/jdbc/core/mapping/AggregateReference.html

  • โœ”๏ธ @MappedCollection(idCloumn = "", keyColumn = "")
    โžœ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ๊ฐ„์— ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด์ฃผ๋Š” ์ •๋ณด
    ( ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์˜ List, Set๋˜๋Š” ์†์„ฑ์— ๋Œ€ํ•œ ๋งคํ•‘์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์„ )
    โžœ idColumn - ์ž์‹ ํ…Œ์ด๋ธ”์— ์ถ”๊ฐ€๋˜๋Š” ์™ธ๋ž˜ํ‚ค์— ํ•ด๋‹น๋˜๋Š” ์ปฌ๋Ÿผ๋ช… ์ง€์ •
    โžœ keyColumn - ์™ธ๋ž˜ํ‚ค๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธํ‚ค ์ปฌ๋Ÿผ๋ช… ์ง€์ •
    โ €
    โ— List์˜ ๊ฒฝ์šฐ ๋‘ ์• ํŠธ๋ฆฌ๋ทฐํŠธ ๋ชจ๋‘ ์ ์–ด์•ผํ•˜๊ณ , Set์˜ ๊ฒฝ์šฐ idColumn๋งŒ ์ ์œผ๋ฉด ๋จ !

  • โœ”๏ธ CrudRepository<Member, Long>
    โžœ ๋ฐ์ดํ„ฐ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ…Œ์ด๋ธ”์— ์ €์žฅ, ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค

โœ” ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ (Query Method)

  • find + By + SQL ์ฟผ๋ฆฌ๋ฌธ์—์„œ WHERE ์ ˆ์˜ ์ปฌ๋Ÿผ๋ช… + (WHERE ์ ˆ ์ปฌ๋Ÿผ์˜ ์กฐ๊ฑด์ด ๋˜๋Š” ๋ฐ์ดํ„ฐ) ํ˜•์‹

    โ— findByxxxx์—์„œ ์ปฌ๋Ÿผ๋ช…์€ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์ง€๋งŒ,
    Spring JDBC ์ž…์žฅ์—์„œ๋Š” ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ๋ฐ”๋ผ๋ณด๊ณ  ์ž‘์—…์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—
    ๋ฐ˜๋“œ์‹œ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋ช…์„ ์ ์–ด์ฃผ์–ด์•ผ ํ•จ

  • ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ…Œ์ด๋ธ”์—์„œ ์กฐํšŒํ•˜์—ฌ ๋ฆฌํ„ด๋œ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ์ง€์ •

    Ex. Optional< Member > findByEmail(String email); ๋ผ๋Š” ์ฟผ๋ฆฌ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด,
    ๋‚ด๋ถ€์ ์œผ๋กœ ์•„๋ž˜์˜ SQL ์ฟผ๋ฆฌ๋ฌธ์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ MEMBER ํ…Œ์ด๋ธ”์— ์งˆ์˜ ๋ณด๋ƒ„
    SELECT "MEMBER"."NAME" AS "NAME", "MEMBER"."PHONE" AS "PHONE", "MEMBER"."EMAIL" AS "EMAIL", "MEMBER"."MEMBER_ID" AS "MEMBER_ID" FROM "MEMBER" WHERE "MEMBER"."EMAIL" = ?
    โžœ ์ด๋ฏธ ํ…Œ์ด๋ธ”์— ๋“ฑ๋ก๋œ ์ด๋ฉ”์ผ ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„

โœ”๏ธ @Query

  • ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์ฟผ๋ฆฌ๋ฌธ์„ ์ž‘์„ฑํ•ด์„œ ์งˆ์˜๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์คŒ
    ( ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋ช…์„ ๊ธฐ์ค€์œผ๋กœ SQL ์ฟผ๋ฆฌ๋ฌธ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ X )

  • ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฌธ์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ
    Ex. @Query("SELECT * FROM COFFEE WHERE COFFEE_ID = :coffeeId")

[์ฐธ๊ณ ] https://www.javaguides.net/2021/10/spring-boot-pagination-and-sorting-rest-api.html


โœ๏ธ ํŽ˜์ด์ง€๋„ค์ด์…˜

  • โœ”๏ธ PagingAndSortingRepository < T, ID >
    โžœ Spring ์ง€์› pagination API
    โžœ extends CrudRepository < T, ID > ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค

์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Repository์— extends ํ•˜์—ฌ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ตฌํ˜„ ๊ฐ€๋Šฅ !

โœ” ํŽ˜์ด์ง€๋„ค์ด์…˜ ์ฒ˜๋ฆฌ ๋ฐฉ์‹

1. ์˜คํ”„์…‹ ๋ฐฉ์‹

  • ์Šคํ”„๋ง์—์„œ ์ง€์›ํ•˜๋Š” ๋ฐฉ์‹

  • ํ–‰์„ ์ฐพ์„ ๊ฐœ์ˆ˜๋งŒํผ ์œ„์—์„œ๋ถ€ํ„ฐ ์นด์šดํŒ…ํ•˜์—ฌ ์ฐพ์•„๊ฐ€๋Š” ๋ฐฉ์‹
    Ex. 10๋งŒ ๊ฑด์˜ ๋ฐ์ดํ„ฐ์—์„œ 10๋งŒ ๋ฒˆ์งธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์œผ๋ ค๋ฉด 1๋ฒˆ๋ถ€ํ„ฐ ์ญ‰ ์ฐพ์•„๊ฐ€์•ผํ•จ

  • ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ 100๋งŒ๊ฑด - 200๋งŒ๊ฑด์œผ๋กœ ๊ทธ๋ ‡๊ฒŒ ๋Š๋ ค์ง€์ง€๋Š” ์•Š์Œ

  • ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ๋Š” ๋ฐฉ์‹

2. ์ปค์„œ ๋ฐฉ์‹

  • ์œ„์—์„œ ์Šคํฌ๋กค ์ญ‰ ํ•ด์„œ ํŽ˜์ด์ง€์˜ ๋งˆ์ง€๋ง‰ ๋˜๋ฉด ๋ฐ‘์— ํŽ˜์ด์ง€๊ฐ€ ์ƒˆ๋กœ ๋‚˜ํƒ€๋‚˜์„œ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ

  • ๋งˆ์ง€๋ง‰ ์กฐํšŒํ•œ ์œ„์น˜๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•จ

  • ์Šคํฌ๋กค ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹


โœ๏ธ n+1 ๋ฌธ์ œ

  • ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ SQL์„ ํ•œ ๋ฒˆ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ n ๊ฑด ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ๊ทธ ๊ฒฐ๊ณผ ์ˆ˜ ๋งŒํผ SQL์„ ์ถ”๊ฐ€๋กœ ๋” ์‹คํ–‰(N)ํ•˜๋Š” ๋ฌธ์ œ
    Ex. N๊ฑด์˜ ์ฃผ๋ฌธ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปคํ”ผ ์ •๋ณด

โžœ JOIN๋ฌธ์„ ํ™œ์šฉํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ์‹คํ–‰ ํšŸ์ˆ˜๋ฅผ ์ค„์ž„

โžœ SQL IN ์—ฐ์‚ฐ์ž ์—ญํ• ์„ ํ•˜๋Š” findAllById(Iterable ids)๋ฅผ ์ด์šฉํ•ด ์ฟผ๋ฆฌ ์ˆ˜ํ–‰ ํšŸ์ˆ˜๋ฅผ ์ค„์ž„


๐Ÿ˜œ ์‹ค์Šต

  • projects ๋‚ด์˜ be-template-jdbc 2

๐Ÿ’ฌ ๊ถ๊ธˆํ–ˆ๋˜ ์  !
๋ฉค๋ฒ„-์˜ค๋”์™€ ์˜ค๋”-์˜ค๋”์ปคํ”ผ๋Š” ๋˜‘๊ฐ™์ด 1:N ๊ด€๊ณ„์ธ๋ฐ
๋ฉค๋ฒ„-์˜ค๋” ๊ด€๊ณ„์—์„œ๋Š” ์˜ค๋”์—์„œ ๋ฉค๋ฒ„๋ฅผ ์ฐธ์กฐํ•˜๋Š”๋ฐ
์™œ ์˜ค๋”-์˜ค๋”์ปคํ”ผ์—์„œ๋Š” ์˜ค๋”์ปคํ”ผ์—์„œ ์˜ค๋”๋ฅผ ์ฐธ์กฐํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ
์˜ค๋”์—์„œ ์˜ค๋”์ปคํ”ผ๋ฅผ ์ฐธ์กฐํ• ๊นŒ??


๐Ÿ’ฌ Answer )
JPA๊ฐ™์€ ๊ฒฝ์šฐ ๋‘˜ ๋‹ค ์ฐธ์กฐํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, Spring Data JDBC ์—์„œ๋Š” DDD ์ถ”๊ตฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ์ค‘ ์›์น™์ธ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„ ์ถ”๊ตฌ

[GroupingBy ์ด์šฉ ์ฐธ๊ณ ]
https://gem1n1.tistory.com/159

[Java 8 Comparator Comparing Reverse Order ์ฐธ๊ณ ]
https://www.javaprogramto.com/2021/12/java-8-comparator-comparing-reverse.html


๐ŸŒˆ ๋Š๋‚€์ 

์‹ค์Šต ์ฝ”๋“œ ์–‘์ด ์•„์ฃผ ๋งŽ์•„์„œ ํ•˜๋ฃจํ•˜๋ฃจ ๋” ๋ฐ”์œ ์š”์ฆ˜ ใ… 
๋ญ”๊ฐ€ ํ•™์Šต ์‹œ๊ฐ„์— ์ฝ”๋“œ ์น˜๊ณ  ์ดํ•ดํ•˜๊ธฐ๋„ ๋น ๋“ฏํ•œ๋ฐ
์ฝ”๋“œ์— ์—๋Ÿฌ๊ฐ€ ๋‚˜์„œ ๊ทธ๊ฑฐ์— ์‹œ๊ฐ„์„ ์Ÿ์œผ๋ฉด ์ ์  ๋ฐ€๋ ค์„œ ๊ผฌ์ด๋Š” ๋Š๋‚Œ์ด๋‹ค ๐Ÿ˜ฅ
ํ•˜์ง€๋งŒ ๊ดœ์ฐฎ์•„.. ํŒŒ์ดํŒ…์ด๋‹ค !!

0๊ฐœ์˜ ๋Œ“๊ธ€