Skip to content

[๐Ÿš€ ์‚ฌ์ดํด2 - ๋ฏธ์…˜ (๊ธฐ๋ฌผ ํ™•์žฅ + DB ์ ์šฉ)] ๋ผํ…” ๋ฏธ์…˜ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.#328

Open
bin1225 wants to merge 53 commits intowoowacourse:bin1225from
bin1225:step2

Conversation

@bin1225
Copy link
Copy Markdown

@bin1225 bin1225 commented Apr 8, 2026

์•ˆ๋…•ํ•˜์„ธ์š” ์—์ฝ”.
์‚ฌ์ดํด 2 ๋ฆฌ๋ทฐ๋„ ์ž˜ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๋ณ€๊ฒฝ ๋ฐ ์ถ”๊ฐ€ ์‚ฌํ•ญ ๊ด€๋ จํ•ด์„œ ๊ฐœ์š”์™€ ๊ฐ„๋‹จํ•œ ์ฝ”๋ฉ˜ํŠธ ๋‚จ๊น๋‹ˆ๋‹ค. ๋ฆฌ๋ทฐ ๊ณผ์ •์—์„œ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”:)

๋ณ€๊ฒฝ ๋ฐ ์ถ”๊ฐ€ ๊ฐœ์š”

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๊ตฌ์กฐ

image

โ€Žsrc/main/resources/schema.sqlโ€Ž

๊ธฐ๋ฌผ ์ด๋™ ๊ทœ์น™

๊ถ์„ฑ ๋‚ด ๋Œ€๊ฐ์„  ์ด๋™์— ๋Œ€ํ•ด์„œ "์ง์„  ์ด๋™ ๊ธฐ๋ฌผ์˜ ๊ฒฝ์šฐ ๊ฒฉ์ž์ ์— ๋Œ€๊ฐ์„ ์ด ์žˆ์œผ๋ฉด ํ•ด๋‹น ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™๊ฐ€๋Šฅํ•˜๋‹ค" ๋ผ๊ณ  ํ•ด์„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ฒฉ์ž์ ์„ ์˜๋ฏธํ•˜๋Š” Intersection ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ด๋™ ๊ฐ€๋Šฅํ•œ ๋ฐฉํ–ฅ๊ณผ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง€๋Š” Vector ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ง€๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ง์„  ์ด๋™ ๊ธฐ๋ฌผ(๊ถ,์‚ฌ,์ฐจ,ํฌ,์กธ)์ด ๊ณตํ†ต์ ์œผ๋กœ StraightRouteProvider๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๊ณ , ๊ฐ ๊ธฐ๋ฌผ์˜ ํŠน์ง•์— ์˜ํ•œ ์ถ”๊ฐ€ ๊ฒ€์ฆ์€ ๊ธฐ๋ฌผ ๋‚ด์—์„œ ์ง„ํ–‰ํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๊ฒŒ์ž„ ์ข…๋ฃŒ ๊ทœ์น™

  • ๊ฒŒ์ž„์ด ๋๋‚˜๋Š” ์‹œ์ ์€ ๋‹ค์Œ ๋‘๊ฐ€์ง€๋กœ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์–‘ํŒ€์˜ ๊ธฐ๋ฌผ ์ ์ˆ˜ ํ•ฉ์ด ๋ชจ๋‘ 30์  ์ดํ•˜์ธ ๊ฒฝ์šฐ ์ ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ŠนํŒจ ํŒ๋ณ„
    • ๊ถ์ด ์žกํžŒ ๊ฒฝ์šฐ

๊ฒŒ์ž„ ์ง„ํ–‰ ์ƒํƒœ์— ์ƒํƒœํŒจํ„ด์„ ๋„์ž…ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

  • ๊ด€๋ จ ํŒจํ‚ค์ง€ : domain/state

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

DB ์ ์šฉ

์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„์ด ์กด์žฌํ•œ๋‹ค๋ฉด ๊ฒŒ์ž„์„ ์ด์–ด์„œ ์ง„ํ–‰ํ•˜๊ฑฐ๋‚˜, ์ƒˆ๋กœ์šด ๊ฒŒ์ž„์„ ์ƒ์„ฑํ•˜๋„๋ก ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ์ž„ ์ง„ํ–‰ ๋„์ค‘ ์ข…๋ฃŒํ•˜๋Š” ๊ธฐ๋Šฅ์€ ๋”ฐ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์ง€ ์•Š์•„์„œ ๊ฐ•์ œ๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒ์‹œ์ผœ์•ผ ํ•˜๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

๋ฆฌ๋ทฐ ํฌ์ธํŠธ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

์‚ฌ์‹ค ์ด๋ฒˆ ์‚ฌ์ดํด์—์„œ ๋‹ค๋ฅธ ํฌ๋ฃจ๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ์šฉ ํŒŒํŠธ๊ฐ€ ๊ฐ€์žฅ ๋‚œํ•ดํ•˜๋‹ค๊ณ  ๋А๊ปด์กŒ์Šต๋‹ˆ๋‹ค..

๊ธฐ์กด Controller ์—ญํ• ์„ ํ•˜๋˜ JanggiFlow์—์„œ ๋‹ด๋‹นํ•ด์•ผ ํ•˜๋Š” ์—ญํ• ๊ณผ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•œ JanggiService ์—์„œ ๋‹ด๋‹นํ•ด์•ผ ํ•˜๋Š” ์—ญํ• ์— ๋Œ€ํ•œ ๊ธฐ์ค€์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์•˜์„œ ๊ทธ๋žฌ๋˜ ๊ฒƒ ๊ฐ™์•„์š”.

๋˜ ์ผ๋ฐ˜์ ์ธ ์„œ๋ฒ„๋Š” ์š”์ฒญ๋งˆ๋‹ค ์ •๋ณด๋ฅผ DB์—์„œ ์กฐํšŒํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ณ  ์ €์žฅํ•˜๋Š” ํ๋ฆ„์ด์ง€๋งŒ, ์ด๋ฒˆ ์‚ฌ์ดํด์—์„œ๋Š” ์ฒ˜์Œ์—๋งŒ Board์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๊ณ , ์ดํ›„ ์ด๋™ ์‹œ์—๋Š” ์ด๋™ ์ •๋ณด๋งŒ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ
๋ฉ”๋ชจ๋ฆฌ ์ƒ์— ์กด์žฌํ•˜๋Š” Board๋ฅผ ์—…๋ฐ์ดํŠธ ํ•œ ํ›„ ์ถ”๊ฐ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๊ตฌ์กฐ๊ฐ€ ์–ด์ƒ‰ํ•˜๋‹ค๊ณ  ๋А๊ปด์กŒ๋˜ ๊ฐ™์Šต๋‹ˆ๋‹ค.

DB ์ ์šฉ ๊ณผ์ •์—์„œ ์ถ”๊ฐ€ํ•œ Service ํด๋ž˜์Šค์™€ DAO ๊ด€๋ จ ๋กœ์ง์— ๊ฒฐํ•จ์ด ๊ฐ€์žฅ ๋งŽ์„ ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒ์ด ๋ฉ๋‹ˆ๋‹ค ใ…Žใ…Ž

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์›๋ž˜๋„ ์ฐธ ์–ด๋ ต๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ๋” ๋ณต์žกํ•ด์ง€๋Š” ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ๋А๊ปด์ง‘๋‹ˆ๋‹ค.

๋”๋ฏธ ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™”, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋กœ ์ธํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์ง€์ €๋ถ„ํ•ด์ง€๋Š”๋ฐ ๊ฐœ์„  ๋ฐฉํ–ฅ์„ฑ์ด ์ž˜ ๋– ์˜ค๋ฅด์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๋ฏธ์…˜์ด ๋๋‚˜๋ฉด ๊ฐœ์ธ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ด€๋ จํ•ด์„œ ์ถ”๊ฐ€ ํ•™์Šต์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์„ ๊ฒƒ ๊ฐ™์ง€๋งŒ, ์น˜๋ช…์ ์ด๋ผ๊ณ  ์ƒ๊ฐ๋˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ํ”ผ๋“œ๋ฐฑ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

ํ•™์Šต

์ด๋ฒˆ ์žฅ๊ธฐ ๋ฏธ์…˜์„ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ ˆ๋ฒจ 1์ด ๋งˆ๋ฌด๋ฆฌ ๋˜๋Š”๋ฐ, ๋งค ์‚ฌ์ดํด๋งˆ๋‹ค ๋ฌด์ง€ํ•จ์„ ์ƒˆ๋กญ๊ฒŒ ์ƒ๊ธฐํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.. ํŠนํžˆ ์ด๋ฒˆ DB ์ ์šฉ์€ ๊ฐ„๋‹จํ•  ๊ฑฐ๋ผ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ ๋ณต์žกํ•˜๋‹ค๊ณ  ๋А๊ปด์ ธ์„œ ๋” ๊ทธ๋žฌ๋˜ ๊ฒƒ ๊ฐ™์•„์š”.

์—์ฝ”๊ฐ€ ๋ฆฌ๋ทฐํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ช…ํ™•ํžˆ ๋ณด์ด๋Š” ์ œ ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด, ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉํ–ฅ์„ ์ถ”์ฒœ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋˜๋Š” ์—์ฝ”๊ฐ€ ์ƒ๊ฐํ•˜์‹œ๊ธฐ์— ์ง€๊ธˆ ์ œ ๋‹จ๊ณ„์—์„œ ์‹œ๊ฐ„์„ ํˆฌ์žํ•ด๋ณผ ๋งŒํ•œ ์š”์†Œ๋“ค์ด ์žˆ๋‹ค๋ฉด ๊ณต์œ ํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฒดํฌ ๋ฆฌ์ŠคํŠธ

  • ๋ฏธ์…˜์˜ ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋ชจ๋‘ ๊ตฌํ˜„ํ–ˆ๋‚˜์š”?
  • Gradle test๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ, ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ํ†ต๊ณผํ–ˆ๋‚˜์š”?
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋‚˜์š”?

bin1225 added 30 commits April 8, 2026 15:34
- isSame() ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€
- PoCollisionDetector ๋‚ด ๊ธฐ๋ฌผ์ด ํฌ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๋กœ์ง์—์„œ isSame์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
- ๋ณด๋“œ์—์„œ Piece๋ฅผ Intersection ์œผ๋กœ ๊ฐ์‹ธ๊ณ , ๊ฐ ์œ„์น˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€
- Vector : ๋ฐฉํ–ฅ ๋ฐ ๊ฑฐ๋ฆฌ
- isPalace ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ถ์„ฑ ์—ฌ๋ถ€ ์ €์žฅ
- PalaceIntersectionInitializer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ๊ธฐํŒ ์ดˆ๊ธฐํ™” ์‹œ ๊ฐ Location์— ๋Œ€ํ•œ Intersection ์ •๋ณด๋ฅผ ์ดˆ๊ธฐํ™”
- ์ง์„  ์ด๋™ ๊ธฐ๋ฌผ (๊ถ,์‚ฌ,์ฐจ,ํฌ,๋ณ‘) ์ด Intersection ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘๋™ํ•˜๋Š” StraightRouteProvider๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
- ๊ธฐ์กด GungSeongRouteProvider ๊ตฌํ˜„์ฒด ์‚ญ์ œ
- ๋ณ‘์˜ ๊ฒฝ์šฐ ๊ฒฝ๋กœ๊ฐ€ ๋’ค๋กœ ์ด๋™ํ•˜๋Š”์ง€ ๊ฒ€์ฆ
- ๊ฐ ๊ธฐ๋ฌผ์ด ์ตœ๋Œ€ ์ด๋™ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง€๊ณ , ๊ฒฝ๋กœ ๊ธธ์ด์™€ ๋น„๊ตํ•˜์—ฌ ์ด๋™๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ
- ํ˜ธ์ถœ๋ถ€์—์„œ !isEmpty()๋กœ ๋น„์–ด์žˆ์ง€ ์•Š์Œ์„ ํ™•์ธํ•˜๋˜ ๋ถ€๋ถ„์„ isNotEmpty() ๋ฉ”์„œ๋“œ๋กœ ๋Œ€์ฒด
- Intersection ์ดˆ๊ธฐํ™” ์ธ๋ฑ์Šค๊ฐ€ view ์ถœ๋ ฅ ๋ฒˆํ˜ธ ๊ธฐ์ค€์œผ๋กœ ๋˜์–ด ์žˆ๋˜ ๋ถ€๋ถ„์„ ์ž๋ฃŒ๊ตฌ์กฐ ๊ธฐ์ค€์œผ๋กœ ๋ณ€๊ฒฝ
- Board.move ํ˜ธ์ถœ ์‹œ ๋„์ฐฉ์ง€์— ์žˆ๋˜ ๊ธฐ๋ฌผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
- ๋ฐ˜ํ™˜๋ฐ›์€ ๊ธฐ๋ฌผ์„ GameContext.update ๋ฉ”์„œ๋“œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
- PieceType์— ๊ธฐ๋ฌผ๋ณ„ ์ ์ˆ˜ ์†์„ฑ ๋ฐ ์กฐํšŒ ๋กœ์ง ๊ตฌํ˜„
- ์ง„์˜๋ณ„ ์ตœ์ข… ์ ์ˆ˜(๊ธฐ๋ณธ ์ ์ˆ˜ + ๋‚จ์€ ๊ธฐ๋ฌผ ์ ์ˆ˜) ํ•ฉ์‚ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
- ์–‘ ์ง„์˜ ์ ์ˆ˜๊ฐ€ ๊ธฐ์ค€์น˜(30์ ) ์ดํ•˜์ผ ๋•Œ, ๊ณ ๋“์  ์ง„์˜ ์Šน๋ฆฌ ์ฒ˜๋ฆฌ
- ConnectionProvider ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ DB ์ปค๋„ฅ์…˜์„ ์–ป๊ณ  ์‚ฌ์šฉ
- Board, Piece ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒ์„ฑ
- TransactionManager ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜์„ ๊ด€๋ฆฌํ•œ๋‹ค.
- being() : ์ž‘์—… ์‹คํ–‰ ์ „ ์‹คํ–‰
- getConnection() : ์ž‘์—… ์ง„ํ–‰ ๊ณผ์ •์—์„œ ๋™์ผ ์ปค๋„ฅ์…˜ ์กฐํšŒ
- commit() : ์ž‘์—… ์™„๋ฃŒ ํ›„ ์‹คํ–‰
- close() : ์ปค๋„ฅ์…˜ ์ •๋ฆฌ
- ์‹ ๊ทœ ๊ฒŒ์ž„ ์ •๋ณด ์ €์žฅ ๋กœ์ง ์ถ”๊ฐ€
- ์ง„ํ–‰ ์ค‘์ธ ๊ฒŒ์ž„(isActive=true) ๋ชฉ๋ก ์กฐํšŒ ๋กœ์ง ์ถ”๊ฐ€
- ํŠน์ • ๊ฒŒ์ž„์˜ ์ง„ํ–‰ ์ƒํƒœ(isActive) ๊ฐฑ์‹  ๋กœ์ง ์ถ”๊ฐ€
- ๊ธฐ๋ฌผ ์ €์žฅ ๋กœ์ง ์ถ”๊ฐ€
- ๊ฒŒ์ž„ id ๋ฅผ ํ†ตํ•œ ๊ธฐ๋ฌผ ๋ชฉ๋ก ์กฐํšŒ ๋กœ์ง ์ถ”๊ฐ€
- ๊ธฐ๋ฌผ ์œ„์น˜(row_idx, col_idx) ๋ณ€๊ฒฝ ๋กœ์ง ์ถ”๊ฐ€
- ๊ธฐ๋ฌผ ์‚ญ์ œ ๋กœ์ง ์ถ”๊ฐ€
- Piece ๋„๋ฉ”์ธ ์ด๋ฆ„๊ณผ ์ค‘๋ณต๋˜๋Š” ๊ฒƒ์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด PieceEntity๋กœ ๋ณ€๊ฒฝ
- ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„์ด ์žˆ๋Š” ๊ฒฝ์šฐ ๊ฒŒ์ž„ ์ •๋ณด๋ฅผ DB์—์„œ ์กฐํšŒ ํ›„ ์ง„ํ–‰
- ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„์ด ์—†๋Š” ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ๊ฒŒ์ž„ ์ƒ์„ฑ ํ›„ ์ €์žฅ
- PieceEntityMapper ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ Entity ๋ฅผ ๋„๋ฉ”์ธ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€
- GameInformation DTO ์ถ”๊ฐ€
- DB ์กฐํšŒ ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณด๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ DBArrangementStrategy ๋ฐฐ์น˜ ์ „๋žต ํด๋ž˜์Šค ์ถ”๊ฐ€
Comment on lines +5 to +8
public record Vector(
Direction direction,
int distance
) {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ˜„์žฌ๋Š” ์ฐจ, ํฌ ๊ฐ™์€ ์ง์„  ์ด๋™ ๊ธฐ๋ฌผ์ด ๋Œ€๊ฐ์„  ์ด๋™ ์‹œ ๊ถ์„ฑ์„ ๋ฒ—์–ด๋‚  ์ˆ˜ ์—†๋Š” ์ƒํƒœ์ด์ง€๋งŒ, ๋งŒ์•ฝ ๋ฒ—์–ด๋‚  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•ด์„œ ํ˜„์žฌ์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๊ถ์„ฑ ๋‚ด์—์„œ ์ด๋™ํ•˜๋Š” ๊ทœ์น™์„ ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ํ˜„์žฌ ์œ„์น˜๊ฐ€ ๊ถ์„ฑ์ผ ๋•Œ ํ•ด๋‹น ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค ์ง€๊ธˆ์ฒ˜๋Ÿผ ๊ฒฉ์ž์ ์ด ๋ฐฉํ–ฅ๊ณผ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์ด ๋ณ€ํ™”์— ์œ ์—ฐํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

public class Board {

private final Map<Location, Piece> boardState;
private final Map<Location, Intersection> boardState;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Board์—์„œ Map์˜ value๊ฐ’์œผ๋กœ Piece ๋ฅผ ๊ฐ€์ง€๋˜ ๊ฒƒ์„ Intersection์œผ๋กœ ๊ฐ์‹ธ์„œ ๊ฐ€์ง€๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋‹ˆ ๊ฒฐ๊ตญ Intersection ์— ์žˆ๋Š” Piece, Location์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ชจ๋‘ getter๋ฅผ ์ •์˜ํ•˜๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

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

ํ˜น์‹œ ์—์ฝ”์˜ ์˜๊ฒฌ์ด ์žˆ๋‹ค๋ฉด ๊ณต์œ ํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

import java.util.List;
import java.util.Map;

public class InProgress implements GameState {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ˜„์žฌ ์ง„ํ–‰์ค‘์ธ ๊ฒŒ์ž„์˜ ์ ์ˆ˜์™€ ์ฐจ๋ก€๋ฅผ ๊ฐ€์ง€๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
๊ธฐ๋ฌผ ์ด๋™์‹œ ๋„์ฐฉ์ง€์— ์žˆ๋˜ ๊ธฐ๋ฌผ์„ board.move()๋ฉ”์„œ๋“œ์—์„œ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•˜์˜€๊ณ , ํ•ด๋‹น ๋ฐ˜ํ™˜๊ฐ’์„ GameState.update()์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์‚ญ์ œ๋œ ๊ธฐ๋ฌผ์„ ๊ธฐ์ค€์œผ๋กœ ๊ฒŒ์ž„ ์ ์ˆ˜๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ , ๊ถ์ด ์žกํ˜”๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋“ฑ ๊ฒŒ์ž„ ์ข…๋ฃŒ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

Comment on lines +6 to +11
public record GameInformation(
Long gameId,
Board board,
Side currentSide
) {
}
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ปจํŠธ๋กค๋Ÿฌ์™€ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ธฐ ์œ„ํ•œ DTO์ž…๋‹ˆ๋‹ค.


public class TransactionManager {

private final ThreadLocal<Connection> connectionHolder = new ThreadLocal<>();
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Service ๊ณ„์ธต์—์„œ ํŠธ๋žœ์žญ์…˜์„ ์‹œ์ž‘ํ•˜๊ณ , ํ•ด๋‹น ์ปค๋„ฅ์…˜์„ DAO์— ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ TreadLocal์„ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.


public class Gung extends ActivePiece {

private static final int MAX_MOVE_DISTANCE = 1;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ฐ ์ง์„  ์ด๋™ ๊ธฐ๋ฌผ์ด ์ž์‹ ์ด ์ด๋™ ๊ฐ€๋Šฅํ•œ ์ตœ๋Œ€ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ€์ง€๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
RouteProvider๋ฅผ ํ†ตํ•ด ๋ฐ›์€ ๊ฒฝ๋กœ๊ฐ€ ์ด๋™ ๊ฐ€๋Šฅ ๊ฑฐ๋ฆฌ๋ณด๋‹ค ๊ธธ๋‹ค๋ฉด, ์ด๋™ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.

import janggi.domain.piece.Piece;
import java.util.Map;

public class DBArrangementStrategy implements ArrangementStrategy {
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ธฐ์กด ๋ณด๋“œ ์ƒ์„ฑ ๋กœ์ง์„ ๊ทธ๋Œ€๋กœ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด DB์—์„œ ์กฐํšŒํ•œ ๋ฐ์ดํ„ฐ๋ฅผ Map<Location, Piece> ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , DBArrangementStrategy ์‚ฌ์šฉํ•˜์—ฌ Board๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

@echo724 echo724 self-requested a review April 8, 2026 12:59
bin1225 added 6 commits April 9, 2026 15:49
- ๋ถˆํ•„์š”ํ•œ ์ฃผ์„ ์‚ญ์ œ
- PieceViewResolver ์—์„œ List<piece> ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ์œ ํ‹ธ ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€
- process ๋‚ด๋ถ€ ๋กœ์ง์„ ๋ฉ”์„œ๋“œ๋กœ ๋ถ„๋ฆฌ
- ResultSet์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์ •๋ณด๋ฅผ ์—”ํ‹ฐํ‹ฐ์— ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•ด RowMapper ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€
- ์กฐํšŒ, ์ˆ˜์ •, ์ถ”๊ฐ€ ์— ๋Œ€ํ•ด์„œ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜์—ฌ Dao์—์„œ ์‚ฌ์šฉ
- ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ•„์š”ํ•œ ๊ฐ’๋“ค์€ Object ๋ฐฐ์—ด์— ์ˆœ์„œ๋Œ€๋กœ ๋‹ด์•„์„œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ
Copy link
Copy Markdown

@echo724 echo724 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์•ˆ๋…•ํ•˜์„ธ์š” ๋ผํ…”!
์ด๋ฒˆ ์‚ฌ์ดํด๋„ ๊น”๋”ํ•˜๊ฒŒ ์ž˜ ํ•ด์ฃผ์…จ๋„ค์š”! DB ์‚ฌ์šฉ์ด ์–ด๋ ต๋‹ค๊ณ  ํ•˜์‹  ๊ฒƒ์— ๋น„ํ•ด์„œ ์ƒ๊ฐ๋ณด๋‹ค ํŠธ๋žœ์ ์…˜๋„ ๊น”๋”ํ•˜๊ฒŒ ์ž˜ ์ฒ˜๋ฆฌํ•ด์ฃผ์…จ๊ณ  ๊ณต์„ฑ ๋ถ€๋ถ„๋„ Intersection ํ™œ์šฉํ•˜์…”์„œ ์ž˜ ํ•ด๊ฒฐ ํ•˜์‹  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋„ ๋ณด๋‹ˆ ๊ฒฉ์ž์ ์„ ์œ„ํ•œ ๋ณ€๊ฒฝ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ํฌ๊ฒŒ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€ ๊ฒƒ ๊ฐ™์ง€์•Š๊ตฌ์š”! ๋”ฑ๋ด๋„ ๋ฏธ์…˜ ์ž์ฒด๊ฐ€ ์–ด๋ ค์› ์„ ๊ฒƒ ๊ฐ™์€๋ฐ ๊ณ ์ƒ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค! ใ… 

์ผ๋‹จ ๋ฏธ์…˜ ๊น”๋”ํ•˜๊ฒŒ ์ž˜ ์งœ์‹  ๊ฒƒ ๊ฐ™์•„์„œ ํฌ๋ฆฌํ‹ฐ์ปฌํ•œ ํ”ผ๋“œ๋ฐฑ์€ ๋”ฐ๋กœ ์—†์„ ๊ฒƒ ๊ฐ™๊ตฌ์š”, ๋‹ค๋งŒ ๊ณ ๋ฏผํ•ด๋ณผ๋งŒํ•œ ๋ถ€๋ถ„, ์ถ”๊ฐ€๋กœ ํ•™์Šตํ•ด๋ณด๋ฉด ์ข‹์€ ๋ถ€๋ถ„๋“ค ์ปค๋ฉ˜ํŠธ๋กœ ๋‚จ๊ฒผ์Šต๋‹ˆ๋‹ค ํ™•์ธํ•ด๋ณด์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”. ์ถ”๊ฐ€๋กœ PR ์„ค๋ช…์— ๋‚จ๊ธฐ์‹  ์งˆ๋ฌธ ๋‹ต ๋“œ๋ฆฌ๋ฉด:

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—…๋ฐ์ดํŠธ ๊ตฌ์กฐ
  • ์ผ๋‹จ ๋ผํ…”์ด ์ด๋ฏธ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ณ ๋ฏผ์ฒ˜๋Ÿผ ํ˜„์žฌ ์ œ๊ฐ€ ๋А๋ผ๊ธฐ๋กœ๋Š” ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋‹นํ•˜๋Š” ๋„๋ฉ”์ธ๊ณผ ์˜์†ํ™”๋ฅผ ์œ„ํ•œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋„ˆ๋ฌด ๋”ฐ๋กœ ๋…ธ๋Š” ๋А๋‚Œ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ธ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ๋กœ ์›€์ง์ž„์„ ํ™•์ธ ํ•œ ๋‹ค์Œ์— ์›€์ง์ž„์ด ์„ฑ๊ณตํ•˜๋ฉด ๊ฒŒ์ž„ ์ƒํƒœ์™€ ์ปค๋ฐ‹์„ ํ•˜๋”๋ผ๊ตฌ์š”. ํ•ด๋‹น ๊ตฌ์กฐ๊ฐ€ ์•„๋ฌด๋ž˜๋„ DB์ถ”๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ์„œ ์„ค๊ณ„๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ์ง„ํ–‰๋œ ๊ฒƒ ๊ฐ™์•„์š”. ๋ง์”€ํ•˜์‹  ๋Œ€๋กœ ํ•ด๋‹น ๋กœ์ง์ด ๋‚˜์œ ๊ฒƒ?์€ ์•„๋‹ˆ์ง€๋งŒ ๊ทธ๋ž˜๋„ ์žฅ์•  ์ฒ˜๋ฆฌ ๋ถ€๋ถ„๊ณผ ๋„๋ฉ”์ธ ๊ฒฐํ•ฉ๋„๋กœ ๋ดค์„๋•Œ๋Š” ๋งŽ์ด ๋–จ์–ด์ง€๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์ •๋ณด๊ฐ€ ์ง„์‹ค์›์ธ์ง€ (DB์— ์žˆ๋Š” ํ”ผ์Šค ์ •๋ณด๊ฐ€ ์ง„์‹ค์ธ์ง€, ์•„๋‹ˆ๋ฉด ์ธ๋ฉ”๋ชจ๋ฆฌ์ƒ์˜ ์ •๋ณด๊ฐ€ ์ง„์‹ค์ธ์ง€), ์žฅ์•  ๋‚ฌ์„ ๊ฒฝ์šฐ์— DB์™€ ์ธ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ ์ฐจ์ด๋Š” ์–ด๋–ป๊ฒŒ ๋‚  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„์ง€ ๋“ฑ ํ˜„์žฌ ๊ตฌ์กฐ๋กœ ๋ถ€ํ„ฐ ์˜ค๋Š” ๋ฌธ์ œ์ ๋“ค์€ ํ•œ ๋ฒˆ ๊ณ ๋ฏผํ•ด๋ณด์‹œ๋ฉด ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.|
  1. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ
    ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ˜„์žฌ DB๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด์„œ ํ…Œ์ŠคํŠธ ๋ฒ”์œ„๋‚˜ ๋ฐฉ์‹์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ์ข€ ์ƒ๊ธฐ์…จ์„ ๊ฒƒ ๊ฐ™์•„์š”. ๋‘ ๊ฐ€์ง€ ํ‚ค์›Œ๋“œ๋กœ ์ถ”๊ฐ€ ํ•™์Šต ํ•ด๋ณด์‹œ๋ฉด ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™์€๋ฐ 1. ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ: TransactionManager์ฒ˜๋Ÿผ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง๊ณผ ์ธํ”„๋ผ๋‚˜ ํŠธ๋žœ์ ์…˜์„ ์œ„ํ•œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด๋‘์…จ๋Š”๋ฐ, ํ…Œ์ŠคํŠธ๋„ ๊ทธ์— ๋”ฐ๋ผ ๊ฐ๊ฐ์˜ ๊ด€์‹ฌ์‚ฌ๋ฅผ ์ œ๋Œ€๋กœ ํ…Œ์ŠคํŠธ ํ•ด์ฃผ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (์ด๋ฏธ ์ž˜ ํ•ด๋‘์‹  ๊ฒƒ ๊ฐ™์ง€๋งŒ์š”) 2. ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๋ถ„๋ฆฌ: ํ˜„์žฌ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์ด ๋”ฐ๋กœ ์—†๊ธฐ ๋•Œ๋ฌธ์— In-memory db๋กœ๋งŒ ํ…Œ์ŠคํŠธ์™€ ์‹ค์ œ ํ”„๋กœ๊ทธ๋žจ ํ™˜๊ฒฝ ๋ชจ๋‘ ๋™์ผํ•˜๊ฒŒ ํ•ด๋‘์…จ๋”๋ผ๊ตฌ์š”. ์ด ๋ถ€๋ถ„ ๋ฏธ์…˜์—์„œ ์‚ด์ง ๋ฒ—์–ด๋‚  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ๊ณผ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์„๊นŒ ๊ณ ๋ฏผํ•ด๋ณด์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”.

์ด์ •๋„๊ฐ€ ๋‹ต์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ์ปค๋ฉ˜ํŠธ ๊ณ ๋ฏผํ•ด๋ณด์‹œ๊ณ  ๋ฆฌ๋ทฐ ์š”์ฒญ ๋‹ค์‹œ ์ฃผ์„ธ์š”. ํ™”์ดํŒ…์ž…๋‹ˆ๋‹ค!

Comment on lines +104 to +125
private <T> T executeInTransaction(Supplier<T> action) {
boolean isNewTransaction = transactionManager.isNotActive();
if (isNewTransaction) {
transactionManager.begin();
}
try {
T result = action.get();
if (isNewTransaction) {
transactionManager.commit();
}
return result;
} catch (RuntimeException e) {
if (isNewTransaction) {
transactionManager.rollback();
}
throw e;
} finally {
if (isNewTransaction) {
transactionManager.close();
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB ์‚ฌ์šฉ์ด ์–ด๋ ต๋‹ค ํ•˜์‹  ๊ฒƒ ์น˜๊ณ ๋Š” ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ(ํŠธ๋žœ์ ์…˜์€ ํŠธ๋žœ์ ์…˜ ๋งค๋‹ˆ์ €๊ฐ€ ๋น„์ง€๋‹ˆ์Šค/๋„๋ฉ”์ธ ๋กœ์ง์€ ๋„๋ฉ”์ธ์ด๋‚˜ ์„œ๋น„์Šค๊ฐ€)๋ฅผ ๋งค์šฐ ๊น”๋”ํ•˜๊ฒŒ ์ž˜ ํ•˜์…จ์Šต๋‹ˆ๋‹ค?! ํ˜น์‹œ ์ „์— ์‚ฌ์šฉํ•˜์…จ๊ฑฐ๋‚˜ ๋”ฐ๋กœ ๊ฒฝํ—˜์ด ์žˆ์œผ์‹ ๊ฐ€์š”?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋‹ค๋งŒ, ํ™•์ธํ•ด๋ณด๋‹ˆ executeInTransaction ๋ฉ”์„œ๋“œ๋“ค ๋ชจ๋‘ transactionManager์— public ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค๊ณ  ๋‚˜๋จธ์ง€ isNotActive, commit, rollback, close ๋ฉ”์„œ๋“œ๋“ค ๋‚ด๋ถ€ ์ ‘๊ทผ์ž๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”? ๋”ฑํžˆ ๋ฉ”์„œ๋“œ์—์„œ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์˜์กดํ•˜์ง€ ์•Š์•„์„œ transactionManager๋กœ ๋„ฃ์–ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜๋ฏธ์ƒ์œผ๋กœ๋„ DefaultJanggiService๋ณด๋‹จ transactionManager๊ฐ€ ๋‹ด๋‹นํ•˜๋Š”๊ฒŒ ๋‚˜์„ ๊ฒƒ ๊ฐ™์•„์„œ์š”!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DB ์‚ฌ์šฉ์ด ์–ด๋ ต๋‹ค ํ•˜์‹  ๊ฒƒ ์น˜๊ณ ๋Š” ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ(ํŠธ๋žœ์ ์…˜์€ ํŠธ๋žœ์ ์…˜ ๋งค๋‹ˆ์ €๊ฐ€ ๋น„์ง€๋‹ˆ์Šค/๋„๋ฉ”์ธ ๋กœ์ง์€ ๋„๋ฉ”์ธ์ด๋‚˜ ์„œ๋น„์Šค๊ฐ€)๋ฅผ ๋งค์šฐ ๊น”๋”ํ•˜๊ฒŒ ์ž˜ ํ•˜์…จ์Šต๋‹ˆ๋‹ค?! ํ˜น์‹œ ์ „์— ์‚ฌ์šฉํ•˜์…จ๊ฑฐ๋‚˜ ๋”ฐ๋กœ ๊ฒฝํ—˜์ด ์žˆ์œผ์‹ ๊ฐ€์š”?

๋„ˆ๊ทธ๋Ÿฝ๊ฒŒ ํ‰๊ฐ€ํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ใ…Žใ…Ž
์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ @Transactional ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์„œ๋น„์Šค ๋ ˆ์ด์–ด์—์„œ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์—ˆ๊ณ , ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ฑ…์ž„ ๋ถ„๋ฆฌ ๊ด€์ ์—์„œ ์˜ณ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ตฌํ˜„์€ ai๋ฅผ ๋งŽ์ด ์ฐธ๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค..

๋‹ค๋งŒ, ํ™•์ธํ•ด๋ณด๋‹ˆ executeInTransaction ๋ฉ”์„œ๋“œ๋“ค ๋ชจ๋‘ transactionManager์— public ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค๊ณ  ๋‚˜๋จธ์ง€ isNotActive, commit, rollback, close ๋ฉ”์„œ๋“œ๋“ค ๋‚ด๋ถ€ ์ ‘๊ทผ์ž๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์„ธ์š”?

์—์ฝ” ์˜๊ฒฌ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.
ํŠธ๋žœ์žญ์…˜์˜ ์‹คํ–‰ ํ๋ฆ„ ๊ด€๋ฆฌ๋„ transactionManager์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์˜ณ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ Service ๊ณ„์ธต ๊ตฌํ˜„์ฒด๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋ฉด์—์„œ๋„ ์ด๋™ ์‹œํ‚ค๋Š” ๊ฒƒ์ด ์ •๋‹ต์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”.

commit, rollback ๊ณผ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋„ ๋…ธ์ถœ์‹œ์ผœ๋‘๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•ด๋ณด์ด์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋™์‹œ์— ์—ฌ๋Ÿฌ ๋กœ์ง์ด ์‹คํ–‰๋  ๋•Œ (์ด๋ฏธ ์ด๋Ÿฐ ๋ถ€๋ถ„์—์„œ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ์ง€์ ์ด 100๊ฐ€์ง€ ์ •๋„ ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ์š”), ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋“ค์ด ํ˜ธ์ถœ๋˜๋Š” ๊ฒฝ์šฐ ์˜ˆ์ƒํ•˜์ง€ ๋ชปํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

  • TransactionManager ๋‚ด๋ถ€๋กœ executeInTransaction() ๋ฉ”์„œ๋“œ๋ฅผ ์ด๋™ ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ํ…Œ์ŠคํŠธ๊ฐ„ ์ข…์†์„ฑ์„ ์—†์• ๊ธฐ ์œ„ํ•ด begin, rollback, close ๋ฉ”์„œ๋“œ๋ฅผ @BeforeEach, @AfterEach ์—์„œ ํ˜ธ์ถœํ–ˆ๋Š”๋ฐ, ์ด ๋กœ์ง์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ TransactionManger ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šคํ™” ํ•˜๊ณ , ํ…Œ์ŠคํŠธ์—์„œ๋Š” TestTransactionManager ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•œ ๊ฒŒ ์ ์ ˆํ•œ์ง€ ํ™•์‹ ์ด ์„œ์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™๋„ค์š”..

Comment on lines +83 to +95
Long gameId = gameInformation.gameId();
Board board = gameInformation.board();
Piece removedPiece = board.move(from, to);

Optional<PieceEntity> fromPiece = pieceDao.findByGameIdAndLocation(gameId, from);
Optional<PieceEntity> toPiece = pieceDao.findByGameIdAndLocation(gameId, to);
fromPiece.ifPresent(pieceEntity -> pieceDao.updatePosition(pieceEntity.getId(), to));
toPiece.ifPresent(pieceEntity -> pieceDao.deleteById(pieceEntity.getId()));

gameContext.update(removedPiece);
if(gameContext.isInProgress()) {
gameDao.updateTurn(gameId, gameContext.getCurrentSide().name());
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์žฅ๊ธฐ๋ง ์˜ฎ๊ธฐ๊ธฐ -> ์˜ฎ๊ธด ์žฅ๊ธฐ๋ง ์—…๋ฐ์ดํŠธ -> ๊ฐœ์ž„์ƒํƒœ ์—…๋ฐ์ดํŠธ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๋Š” ๊ฑธ๋กœ ๋ณด์ด๋„ค์š”? ์ผ๋‹จ์€ ๊น”๋”ํ•˜๊ฒŒ ๋กœ์ง์ด ์ž˜ ๋ณด์ด๊ธด ํ•˜๋Š”๋ฐ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๋ฏผํ•˜์‹ค ๋ถ€๋ถ„์ด ์žˆ์–ด ๋ณด์ด๋„ค์š”! ๋งŒ์•ฝ ์ธ๋ฉ”๋ชจ๋ฆฌ ์ƒ(์˜์†ํ™” ์ œ์™ธํ•œ ๋ถ€๋ถ„)์—์„œ๋Š” ์„ฑ๊ณต์ ์œผ๋กœ ์ง„ํ–‰์ด ๋๋Š”๋ฐ, pieceDao์—์„œ ํ”ผ์Šค๋ฅผ ์ฐพ๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? Timeout์ด ๋ฐœ์ƒํ•  ์ˆ˜ ๋„ ์žˆ๊ณ , ์ปค๋„ฅ์…˜์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ์ˆ˜ ๋„ ์žˆ๊ตฌ์š”. ๋‹ค์–‘ํ•œ ์ด์œ ๋กœ ๋น„์ง€๋‹ˆ์Šค ๋กœ์ง์ด ์˜์†ํ™”๊ฐ€ ์•ˆ๋  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Ÿฐ ์žฅ์•  ์ƒํ™ฉ ๋“ฑ์„ ์–ด๋–ป๊ฒŒ ๋Œ€๋น„ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋˜ํ•œ ๋งŒ์•ฝ ์ธ๋ฉ”๋ชจ๋ฆฌ ์ƒ์—์„œ๋Š” ๋ณด๋“œ(๊ต์ฐจ์ )์— ํ•ด๋‹น ํ”ผ์Šค๊ฐ€ ์žˆ๋Š”๋ฐ, pieceDao์—์„œ๋Š” ๋ชป์ฐพ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์„๊นŒ์š”? ์ด๋ ‡๊ฒŒ ์—”ํ‹ฐํ‹ฐ์™€ ๋„๋ฉ”์ธ ๊ฐ์ฒด๊ฐ€ ๋ถ„๋ฆฌ๋˜์—ˆ์„ ๊ฒฝ์šฐ์—๋Š” ๊ฒ€์ฆํ•ด์ค˜์•ผํ•  ๋ถ€๋ถ„๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„ 1. ํ˜„์žฌ ๊ตฌ์กฐ๊ฐ€ ์žฅ์•  ์ƒํ™ฉ ํ˜น์€ ์ƒํƒœ ๋ถˆ์ผ์น˜ ์ƒํ™ฉ์— ๊ดœ์ฐฎ์€์ง€ 2. ์•„๋‹ˆ๋ผ๋ฉด ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„์ง€ -> ๋„๋ฉ”์ธ ์—”ํ‹ฐํ‹ฐ๋กœ ์„ค๊ณ„ ๋ณ€๊ฒฝ? ํ˜น์€ ์žฌ์‹œ๋„? ๋“ฑ๋“ฑ ๊ณ ๋ฏผํ•ด๋ณด์‹œ๊ณ  ์ ์šฉํ•ด๋ณด์‹œ๊ฑฐ๋‚˜ ์ปค๋ฉ˜ํŠธ๋กœ ์•Œ๋ ค์ฃผ์‹œ๋ฉด ์ข‹๊ฒ ๋„ค์š”!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋จผ์ € ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ จ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋„ ์žฌ์‹œ๋„ ๋กœ์ง์— ํฌํ•จ๋˜๋„๋ก JanggiException์„ ์ƒ์†๋ฐ›์€ ์ปค์Šคํ…€ ์˜ˆ์™ธ๋ฅผ ์ •์˜ํ•˜๊ณ  ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

  1. ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๊ด€๋ จ ๋ฌธ์ œ๋„ ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒ์‹œํ‚ค๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆฌ๊ณ , ๋‹ค์‹œ ์žฌ์‹œ๋„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

  2. ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ์ฆ‰ ์‹œ์ž‘ ์‹œ์ ์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋”ฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๋Š” ๋”ฐ๋กœ ์žฌ์‹œ๋„ ๋กœ์ง ์—†์ด ์‹คํ–‰์ด ์‹คํŒจํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋‹ˆ ์—์ฝ”๊ฐ€ ๋ง์”€ํ•˜์‹ ๋Œ€๋กœ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ๋Š” ๋ณด๋“œ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•œ ํ›„ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ๋กค๋ฐฑ์ด ๋˜์ง€๋งŒ, ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ๋Š” ๋กค๋ฐฑ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ์™€ DB ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์ง‘๋‹ˆ๋‹ค.

        transactionManager.executeInTransaction(() -> {
            Long gameId = gameInformation.getGameId();
            Board board = gameInformation.getBoard();
            Piece removedPiece = board.move(from, to);

            Optional<PieceEntity> fromPiece = pieceDao.findByGameIdAndLocation(gameId, from);
            Optional<PieceEntity> toPiece = pieceDao.findByGameIdAndLocation(gameId, to);
            fromPiece.ifPresent(pieceEntity -> pieceDao.updatePosition(pieceEntity.getId(), to));
            toPiece.ifPresent(pieceEntity -> pieceDao.deleteById(pieceEntity.getId()));

            gameInformation.update(removedPiece);

            if (gameInformation.isInProgress()) {
                gameDao.updateTurn(gameId, gameInformation.getCurrentSide().name());
                throw new JanggiException("์ž„์˜๋กœ ์˜ˆ์™ธ ๋ฐœ์ƒ!");
            }
        });

๋˜ ์ด ๊ฒฝ์šฐ ์žฌ์‹œ๋„ ๋กœ์ง์ด ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์— view ๋ ˆ๋ฒจ์—์„œ ์บ์‹ฑํ•ด๋‘” ๋ณด๋“œ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

public class ApplicationView {

    private final Output outputWriter;
    private final Input inputReader;

    private List<List<String>> lastBoard;
    private String lastSide;

๊ฒฐ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๊ฒฝํ—˜ํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.


ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด๋ดค์„ ๋•Œ,

  1. DB ๋จผ์ € ์—…๋ฐ์ดํŠธ ํ›„ ์„ฑ๊ณต ์‹œ ๋ฉ”๋ชจ๋ฆฌ ์—…๋ฐ์ดํŠธ
  2. ๋ณด๋“œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์œ ์ง€ํ•˜์ง€ ์•Š๊ณ  ํ•ญ์ƒ DB์—์„œ ์กฐํšŒ

์ง€๊ธˆ ์ƒํ™ฉ์—์„œ๋Š” 1๋ฒˆ ๋ฐฉ์‹์ด ๊ฐ€์žฅ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋ถ€๋ถ„์€ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋งค๋ฒˆ ์‹ ๊ฒฝ์จ์•ผ ํ•œ๋‹ค๋Š” ์ ์—์„œ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ ๋กœ์ง์ด ๋ณต์žกํ•ด์ง€๋Š” ๊ฒฝ์šฐ ์™„๋ฒฝํ•œ ํ†ต์ œ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋„ค์š”.

2๋ฒˆ ๋ฐฉ์‹์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šคํ‚ค๋งˆ, DAO ๋กœ์ง์— ๋งŽ์€ ์ˆ˜์ •์ด ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๊ฒฐ๋ก 

DB ๊ด€๋ จ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ, ์ดˆ๊ธฐ ๋กœ๋”ฉ ์‹œ์ ์ด ์•„๋‹ˆ๋ผ๋ฉด ์žฌ์‹œ๋„ ๋กœ์ง์ด ์ ์šฉ๋˜๋„๋ก ์ปค์Šคํ…€ ์˜ˆ์™ธ ๋„์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์žฅ์•  ๋ฐœ์ƒ ์‹œ ๋ฉ”๋ชจ๋ฆฌ์™€ DB์˜ ๋™๊ธฐํ™”๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด, DB ๊ด€๋ จ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์™„๋ฒฝํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ด๊ณ  ๋ฉ”๋ชจ๋ฆฌ ์ƒ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•จ์œผ๋กœ์จ ์–ป๋Š” ์กฐํšŒ ๋น„์šฉ ๊ฐ์†Œ์˜ ์ด์ ๋ณด๋‹ค ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™” ๊ด€๋ จํ•ด์„œ ์•ˆ์ •์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๊ฒƒ์ด ๋” ํฌ๋‹ค๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.
๋˜ ํ˜„์žฌ GameInformation DTO๊ฐ€ ๊ฐ์ฒด๋ฅผ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  controller์™€ service ๊ณ„์ธต์„ ์™”๋‹ค ๊ฐ”๋‹ค ํ•˜๋Š” ๊ฒƒ๋„ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด๋ถ€์—์„œ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ์ƒ๊ฐ๋ฉ๋‹ˆ๋‹ค.

์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋งค ๋กœ์ง๋งˆ๋‹ค ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐ ๋ณ€๊ฒฝ์ด ๋งŽ์ด ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์•„์„œ ์กฐ๊ธˆ ๋” ๊ณ ๋ฏผํ•ด๋ณผ ์‹œ๊ฐ„์ด ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋„ˆ๋ฌด ์ข‹์€ ๋ฆฌ๋ทฐ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

);
}

private enum PalaceConfiguration {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์บฌ ๊ณต์„ฑ ์งœ๊ธฐ ์‰ฝ์ง€ ์•Š์€๋ฐ ๊ทธ๋ž˜๋„ ์ž˜ ํ‘œํ˜„ํ•ด๋‚ด์…จ๋„ค์š” ๐Ÿ‘

Comment on lines +36 to +45
GameInformation gameInformation = initializeGameInformation();
Board board = gameInformation.board();

GameContext gameContext = GameContext.createInProgress(board.getAlivePieces(), gameInformation.currentSide());
while (gameContext.isInProgress()) {
printBoard(board);
view.respondCurrentSide(SideViewResolver.toDisplayName(gameContext.getCurrentSide()));
retryAction(() -> playTurn(gameInformation, gameContext));
}
finish(gameContext, gameInformation);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ œ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค๋งŒ, ํ˜„์žฌ GameInformation, GameContext ์ƒ์„ฑ ์‹œ์ , ์‚ฌ์šฉ๋˜๋Š” ์œ„์น˜ ์ „๋ถ€ ๋น„์Šทํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š”๋ฐ ์ด ๋ถ€๋ถ„ ํ•ฉ์น˜๋Š”๊ฑฐ ๊ณ ๋ คํ•ด๋ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”. ํ•œ์ชฝ์ด DTO์ด๊ธด ํ•˜์ง€๋งŒ ๊ฒฐ๊ตญ์— ๋‘˜์ด ๊ฐ™์€ ๋ผ์ดํ”„์‚ฌ์ดํด๋กœ ๊ฐ™์ด ์›€์ง์ธ๋‹ค๋ฉด ์ถฉ๋ถ„ํžˆ ๊ฐ™์€ ๊ฐ์ฒด์— ๋‘ฌ๋„ ๋˜์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์—์ฝ”๊ฐ€ ๋งํ•˜์‹ ๋Œ€๋กœ ์ƒ์„ฑ ์‹œ์ ๋„ ๋™์ผํ•˜๊ณ , Service ๊ณ„์ธต ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ์—๋„ GameContext์™€ GameInformation์ด ํ•จ๊ป˜ ์ „๋‹ฌ๋˜๋Š” ๊ตฌ์กฐ์ธ ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ GameInformation์— GameContext ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ˆ˜์ •ํ•˜๋‹ˆ ์ƒˆ๋กœ์šด ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.
GameInformation์„ DTO ๋ชฉ์ ์œผ๋กœ ์ •์˜ํ–ˆ๋Š”๋ฐ, ๋‚ด๋ถ€์— GameContext, Board ์™€ ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋˜๋‹ˆ, DTO์ธ์ง€ ๋„๋ฉ”์ธ์ธ์ง€ ๊ฒฝ๊ณ„๊ฐ€ ๋ชจํ˜ธํ•ด์ง„๋‹ค๊ณ  ๋А๋‚๋‹ˆ๋‹ค.

๋‹จ์ˆœ getter๋กœ ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๊ณ  DTO๋กœ์จ ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ํ•˜๋ฉด ๋””๋ฏธํ„ฐ์˜ ๋ฒ•์น™์„ ์œ„๋ฐ˜ํ•˜๊ณ  ํ˜ธ์ถœ๋ถ€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

gameInformation.getGameContext().update();

๊ทธ๋ž˜์„œ ํ˜„์žฌ๋Š” GameInformation ๋‚ด๋ถ€์— gameContext๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋Š” ์„œ๋น™ ๋ฉ”์„œ๋“œ๋ฅผ ๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

public void update(Piece removedPiece) {
    gameContext.update(removedPiece);
}

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

๊ฒฐ๋ก 
์ž‘๋™ ๊ตฌ์กฐ ์„ค๊ณ„๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‚˜ ์ƒ๊ฐ์ด ๋“œ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.
๋งค ํ„ด๋งˆ๋‹ค ๋ณด๋“œ ์ •๋ณด๋ฅผ ์กฐํšŒํ•˜๋Š” ๋น„์šฉ์„ ์•„๋ผ๊ณ ์ž ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ณด๋“œ, ๊ฒŒ์ž„ ํ„ด ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ ์ฟผ๋ฆฌ๋งŒ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ตฌ์กฐ๋•Œ๋ฌธ์— Controller์™€ Service๊ฐ€ ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ์ฃผ๊ณ  ๋ฐ›๊ฒŒ๋˜๊ณ , ๊ทธ๋ž˜์„œ DTO์— ๊ฐ์ฒด๊ฐ€ ๊ทธ๋Œ€๋กœ ๋“ค์–ด๊ฐ€๋ฉฐ ์—ญํ• ์ด ๋ชจํ˜ธํ•ด์ง€๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์ง€๊ธˆ ๋– ์˜ค๋ฅด๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ ๋‘๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  1. ์กฐํšŒ ๋น„์šฉ์„ ์•„๋ผ๊ธฐ ์œ„ํ•ด์„œ Service ๊ณ„์ธต์—์„œ ๋ณด๋“œ ๋ฐ ํ„ด ์ •๋ณด๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง€๊ณ  ์บ์‹ฑํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ๋งค ์‹คํ–‰ ์‹œ๋งˆ๋‹ค DB์—์„œ ๋ณด๋“œ ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.

๋‹จ์ผ ํ˜ธ์ŠคํŠธ์—์„œ ์‹คํ–‰๋˜๋Š” ์ง€๊ธˆ ๊ตฌ์กฐ๋ผ๋ฉด 1๋ฒˆ๋„ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์€๋ฐ,
์—์ฝ”๊ฐ€ ๋ณด์‹œ๊ธฐ์—๋Š” ์–ด๋–ค ๋ฐฉํ–ฅ์ด ๋” ์ ์ ˆํ•ด๋ณด์ด์‹œ๋‚˜์š”?

@Override
public List<Location> calculateRoute(Location from, Location to) {

protected List<Location> resolveRoute(Intersection from, Intersection to) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveRoute๋ผ๋Š” ์ด๋ฆ„์ด ์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๋˜๋Š”๋ฐ์š”, calculate์—์„œ ๋ณ€๊ฒฝํ•˜์‹  ์ด์œ ๊ฐ€ ๋”ฐ๋กœ ์žˆ์„๊นŒ์š”?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๊ธฐ๋ฌผ ๊ฒฝ๋กœ ๊ณ„์‚ฐ์—์„œ ์ค‘๋ณต๋˜๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค!


๊ธฐ์กด์—๋Š” ๊ธฐ๋ฌผ์˜ ์ด๋™ ๊ฒฝ๋กœ ๊ณ„์‚ฐ ๊ณผ์ •์—์„œ ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๊ธฐ๋ฌผ์ด ๋ฌด์—‡์ธ์ง€ ์ •๋ณด๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด ๊ธฐ์กด ์ฝ”๋“œ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ˆ์™ธ๋ฅผ ์žก์•„์„œ ๊ตฌ์ฒดํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

    @Override
    public List<Location> calculateRoute(Location from, Location to) {
        try {
            return ROUTE_PROVIDER.calculateRoute(from, to);
        } catch (RouteResolveException e) {
            throw new RouteResolveException(pieceType, from, to);
        }
    }

์ด๋ ‡๊ฒŒ try-catch๋กœ ๊ฐ์‹ธ๋Š” ๋กœ์ง์ด ๋ชจ๋“  ๊ธฐ๋ฌผ์— ์ค‘๋ณต๋œ๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด์„œ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ ์šฉํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์‹ค์ œ ์ด๋™ ๊ฐ€๋Šฅํ•œ ๊ธฐ๋ฌผ์˜ ๋ถ€๋ชจ์ธ ActivePiece ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜ํ•˜์—ฌ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๊ณตํ†ต ์ฒ˜๋ฆฌํ•˜๊ณ , ์ž์‹ ํด๋ž˜์Šค์—์„œ resolveRoute() ๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์ œํ–ˆ์Šต๋‹ˆ๋‹ค.

    @Override
    public final List<Location> calculateRoute(Intersection from, Intersection to) {
        try {
            return resolveRoute(from, to);
        } catch (RouteResolveException e) {
            throw new RouteResolveException(pieceType, from.getLocation(), to.getLocation());
        }
    }

    protected abstract List<Location> resolveRoute(Intersection from, Intersection to);

์‚ฌ์‹ค ์ด ๋ถ€๋ถ„ ๊ด€๋ จํ•ด์„œ๋„ ์ ์ ˆํ•œ ์ฝ”๋“œ์ธ์ง€ ํ™•์‹ ์ด ์„œ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ฝ”๋“œ๋ฅผ ๋ณด๋Š” ์ž…์žฅ์—์„œ Piece ์ธํ„ฐํŽ˜์ด์Šค์˜ calculateRoute๊ฐ€ ์ž์‹ ํด๋ž˜์Šค์— ๊ตฌํ˜„์ด ๋˜์–ด ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ํ™•์ธํ•˜๋ฉด์„œ ์ž‘๋™์„ ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋Š” ์ ์ด ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋Œ€๋กœ ๋ถ€๋ชจ ํด๋ž˜์Šค์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ…œํ”Œ๋ฆฟ ๋ฉ”์„œ๋“œ๋ฅผ protected๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ๊ฒฝ์šฐ์—๋Š” ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด์„œ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ๊ตฌํ˜„์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

// ๋ถ€๋ชจ ํด๋ž˜์Šค (ActivePiece)
    protected List<Location> calculateWithExceptionHandling(Intersection from, Intersection to, Supplier<List<Location>> routeSupplier) {
        try {
            return routeSupplier.get(); // ์ž์‹ ํด๋ž˜์Šค์—์„œ ์ „๋‹ฌํ•œ ๋žŒ๋‹ค(์‹ค์ œ ๊ณ„์‚ฐ ๋กœ์ง) ์‹คํ–‰
        } catch (RouteResolveException e) {
            // ๊ณตํ†ต ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐ ๊ตฌ์ฒดํ™”
            throw new RouteResolveException(pieceType, from.getLocation(), to.getLocation());
        }
    }

    // ์ž์‹ ํด๋ž˜์Šค (์˜ˆ: Cha, Sang ๋“ฑ)
    @Override
    public List<Location> calculateRoute(Intersection from, Intersection to) {
        // ๋ถ€๋ชจ์˜ protected ๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉฐ ๋žŒ๋‹ค๋กœ ์‹ค์ œ ๋กœ์ง ์ „๋‹ฌ
        return calculateWithExceptionHandling(from, to, () -> {
            return ROUTE_PROVIDER.calculateRoute(from, to); 
        });
    }

ํ˜น์‹œ ์—์ฝ”๊ฐ€ ๋ณด์‹œ๊ธฐ์— ์ ์ ˆํ•˜์ง€ ์•Š๋‹ค๊ณ  ํŒ๋‹จ๋˜์‹œ๋ฉด ์˜๊ฒฌ ๊ณต์œ  ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค :)

bin1225 added 6 commits April 10, 2026 09:56
- ๋ผ์ดํ”„ ์‚ฌ์ดํด์ด ๊ฐ™์€ ๋‘ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ๊ฐ€๋…์„ฑ ๋ฐ ์‚ฌ์šฉ์„ฑ ๊ฐœ์„ 
- begin, commit, rollback ๋ฉ”์„œ๋“œ ์ ‘๊ทผ์ œ์–ด์ž๋ฅผ private๋กœ ์ˆ˜์ •
- TransactionManager ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•˜๊ณ , Test์ „์šฉ TransactionManger๋Š” begin, rollback, close๋ฅผ ํ…Œ์ŠคํŠธ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋”ฐ๋ผ ํ˜ธ์ถœํ•˜๋„๋ก ๊ตฌํ˜„
- transaction, connection ํŒจํ‚ค์ง€ ์ถ”๊ฐ€
โ€ฆnsaction ํ™•์ธ ๋กœ์ง ์ œ๊ฑฐ

- ํ…Œ์ŠคํŠธ์šฉ TransactionManager๋ฅผ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉํ•จ์— ๋”ฐ๋ผ ํ”„๋กœ๋•์…˜ ์šฉ TransactionManger ์—์„œ ๋ถˆํ•„์š”ํ•œ ๋กœ์ง ์ œ๊ฑฐ
@bin1225
Copy link
Copy Markdown
Author

bin1225 commented Apr 10, 2026

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

@echo724 echo724 self-requested a review April 10, 2026 14:17
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.

2 participants