Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
ef5351d
docs: ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋‚ด์šฉ ์ถ”๊ฐ€
Huiyeongkim Mar 24, 2026
1f59cd9
feat: ์œ„์น˜ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 24, 2026
7da0ceb
feat: ์œ„์น˜ ์ƒ์„ฑ ๊ฒ€์ฆ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๊ฒ€์ฆ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 24, 2026
3f21be8
feat: ์žฅ๊ธฐํŒ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 24, 2026
8acc7d5
feat: ์ฐจ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
f254898
refactor: ๊ธฐ๋ฌผ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝ
Huiyeongkim Mar 25, 2026
f563692
feat: ๊ธฐ๋ฌผ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
cc5bd5d
feat: ๊ธฐ๋ฌผ ์ง์„  ์ด๋™ ํ…Œ์ŠคํŠธ ๊ตฌํ˜„ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
d927240
feat: ๋Œ€๊ฐ์„  ์ด๋™ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
Huiyeongkim Mar 25, 2026
d706d5b
feat: ์ง์„  ์ด๋™ ์ „๋žต ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
4c73af0
feat: ์ฐจ ์ „๋žต ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„ ๋ฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
715bc70
feat: ์ƒ ์ „๋žต ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ตฌํ˜„ ๋ฐ ๊ธฐ๋Šฅ ๊ตฌ์กฐ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
a915e9e
refactor: ์ฐจ ์ „๋žต ํŒจํ„ด ๋ฉ”์†Œ๋“œ ๋„ค์ด๋ฐ ๋ณ€๊ฒฝ
Huiyeongkim Mar 25, 2026
750232a
feat: ์ƒ ์ „๋žต ํด๋ž˜์Šค ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
Huiyeongkim Mar 25, 2026
4265ad4
feat: ์ƒ ๋ชฉ์ ์ง€ ๊ธฐ๋ฌผ๋ณ„ ์ด๋™ ํŒ์ • ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ ๋ฐ ํŒ์ • ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 25, 2026
cdf3d21
feat: ์‚ฌ ์ „๋žต ํŒจํ„ด ํ…Œ์ŠคํŠธ ๊ตฌํ˜„
Huiyeongkim Mar 25, 2026
4aaaa4d
refactor: ์ฐจ ์ด๋™์ „๋žต์„ dx,dy ํ…Œํฌ๋‹‰์œผ๋กœ ์ˆ˜์ •
Huiyeongkim Mar 26, 2026
8ded06e
refactor: ์ƒ ์ด๋™ ์ „๋žต์— dx,dy ํ…Œํฌ๋‹‰๋กœ ๋ณ€๊ฒฝ
Huiyeongkim Mar 26, 2026
6c2a330
refactor: ์ƒ ์ด๋™ ์ „๋žต์— dx,dy ํ…Œํฌ๋‹‰๋กœ ๋ณ€๊ฒฝ ๋ฐ ๊ตฌํ˜„ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
d8238df
feat: ๋งˆ์˜ ์ด๋™ ๊ทœ์น™ ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
2d5b6f6
feat: ์‚ฌ์˜ ์ด๋™ ๊ทœ์น™ ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
eaa6f00
refactor: BoardFactory์— Board ์ƒ์„ฑ ์ฑ…์ž„ ์œ„์ž„
Huiyeongkim Mar 26, 2026
4b6478f
feat: ํฌ์˜ ์ด๋™ ์ „๋žต ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
f4eeb5b
feat: ๊ถ์˜ ์ด๋™ ์ „๋žต ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
4d638e9
feat: ์กธ์˜ ์ด๋™ ๊ทœ์น™ ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
Huiyeongkim Mar 26, 2026
9c39a8c
refactor: ๋ฉ”์„œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ถˆ๋ณ€ํ™” ์ ์šฉ
Huiyeongkim Mar 26, 2026
cc703aa
refactor: ์ƒ์˜ ์ตœ์ข… ๋ชฉ์ ์ง€ ์ถ”์ถœํ•˜๋Š” ๋ฉ”์„œ๋“œ ๋‹จ์ˆœํ™”
Huiyeongkim Mar 26, 2026
a8aedbe
refactor: ํฌ์˜ ์ด๋™ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ ์กฐ๊ฑด๋ฌธ ๋ฉ”์†Œ๋“œํ™”
Huiyeongkim Mar 26, 2026
b2722cb
refactor: ํฌ์˜ ์ด๋™ ์š”๊ตฌ ๊ธฐ๋ฌผ ๊ฐฏ์ˆ˜ ๋งค์ง๋„˜๋ฒ„ ์ƒ์ˆ˜ํ™”
Huiyeongkim Mar 26, 2026
5ab2e6c
refactor: ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ถˆ๋ณ€ํ™”
Huiyeongkim Mar 27, 2026
8ee3b62
refactor: ๊ฐ™์€ ํŒ€ ๊ธฐ๋ฌผ์ธ์ง€ ๊ฒ€์ฆํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ฑ…์ž„์„ ๋ณด๋“œ์—์„œ ๊ธฐ๋ฌผ๋กœ ์ด๋™
Huiyeongkim Mar 27, 2026
6651188
refactor: isCannon ๋ฉ”์„œ๋“œ ์œ„์น˜ ๋ณ€๊ฒฝ
Huiyeongkim Mar 27, 2026
4138d89
refacotr: ๋งค์ง๋„˜๋ฒ„ ์ œ๊ฑฐ ๋ฐ ์ถœ๋ ฅ ๋กœ์ง ์ œ๊ฑฐ, if๋ฌธ ์ œ๊ฑฐ
Huiyeongkim Mar 27, 2026
3490407
test: Board ์ƒ์„ฑ ํ…Œ์ŠคํŠธ ๋ณ€๊ฒฝ
Huiyeongkim Mar 27, 2026
576bb71
feat: ๊ธฐ๋ฌผ ์ด๋™ ์‹œ ์ด์ „ ์œ„์น˜์— ์žˆ๋˜ ๊ธฐ๋ฌผ ์‚ญ์ œ
Huiyeongkim Mar 27, 2026
be6f42f
test: ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ณตํ†ต ๋กœ์ง ์ถ”์ถœ ๋ฐ ๋ฉ”์„œ๋“œ๋ช… ๋ณ€๊ฒฝ
Huiyeongkim Mar 27, 2026
9a633e4
feat: Board ์ฝ˜์†” ์ถœ๋ ฅ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Huiyeongkim Mar 28, 2026
7013f16
docs: ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋ฌธ์„œ ์ตœ์‹ ํ™”
LEEJaeHyeok97 Mar 28, 2026
57d22bd
feat: ๊ธฐ๋ฌผ ์œ„์น˜ ๋ฐ ์žฌ์‹œ๋„ ์ž…๋ ฅ ๊ฐ’ ๊ฒ€์ฆ ๋ฐ ์ž…๋ ฅ ๊ธฐ๋Šฅ ๊ตฌํ˜„
LEEJaeHyeok97 Mar 28, 2026
ca87635
feat: ๊ธฐ๋ฌผ ์ด๋™ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐ ์ด๋™ ์œ„์น˜ ์ž…๋ ฅ ๊ธฐ๋Šฅ ๊ตฌํ˜„
LEEJaeHyeok97 Mar 29, 2026
f099fba
feat: ์ฝ˜์†” ์ถœ๋ ฅ ๊ตญ๊ฐ€๋ณ„ ์ƒ‰ ๊ตฌ๋ถ„ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
LEEJaeHyeok97 Mar 29, 2026
9ab7557
docs: README.md ํŒŒ์ผ ์™„๋ฃŒ์‚ฌํ•ญ ์ฒดํฌ ๋ฐ ์ˆ˜์ •
Huiyeongkim Mar 29, 2026
5d64486
feat: ํ•œ๋‚˜๋ผ์ธ ๊ฒฝ์šฐ ์กธ ๋Œ€์‹  ๋ณ‘ ์ถœ๋ ฅํ•˜๋„๋ก ์ˆ˜์ •
Huiyeongkim Mar 29, 2026
4b0cffe
refactor: ์กธ ์˜คํƒ€ ์ˆ˜์ •
Huiyeongkim Mar 29, 2026
b354278
feat: ๋ฆฌ๋ทฐ์–ด ์š”๊ตฌ์‚ฌํ•ญ ๋ฐ˜์˜
LEEJaeHyeok97 Mar 30, 2026
14f7a2c
feat: ์œ„์น˜ ์ด๋™ ๋ฉ”์†Œ๋“œ์—์„œ turnCount๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์žฌํ• ๋‹นํ•˜๋„๋ก ์ˆ˜์ •
LEEJaeHyeok97 Apr 1, 2026
5fcf7c3
test: ์‚ฌ์˜ ์ด๋™ ํ…Œ์ŠคํŠธ ์ด๋™ ์ขŒํ‘œ๊ฐ’ ๋ณ€๊ฒฝ
LEEJaeHyeok97 Apr 1, 2026
9aabd60
feat: ์‚ฌ์˜ ๋Œ€๊ฐ์„ , ์žฅ๊ฑฐ๋ฆฌ ์ด๋™ ์ œํ•œ ์กฐ๊ฑด ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 1, 2026
707e12f
feat: ์กธ ๋Œ€๊ฐ์„  ์ด๋™ ์ œํ•œ ๋กœ์ง ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 1, 2026
7df9213
feat: ๊ฐ ๋‚˜๋ผ์˜ ์ฐจ๋ก€์— ์ž์‹ ์˜ ๋‚˜๋ผ ๊ธฐ๋ฌผ๋งŒ ์›€์ง์ผ ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋Šฅ ์ˆ˜์ •
LEEJaeHyeok97 Apr 1, 2026
a6789f0
fix: ๊ธฐ๋ฌผ์„ ์›€์ง์ผ ์œ„์น˜๋ฅผ ์ž…๋ ฅํ•˜๋‹ค ์˜ค๋ฅ˜ ์‹œ ๋‹ค์‹œ ๊ทธ ์œ„์น˜๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›๋„๋ก ์ˆ˜์ •
LEEJaeHyeok97 Apr 1, 2026
6d6c76c
fix: ๋งˆ์™€ ์ƒ์˜ ์ž˜๋ชป๋œ ์ด๋™ ๊ทœ์น™ ์ˆ˜์ •
LEEJaeHyeok97 Apr 1, 2026
5703b5d
refactor: ๊ธฐ๋ฌผ์˜ ์ด๋™ ์‹œ ์ž…๋ ฅ์„ ์žฌ๊ท€์—์„œ ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๋ณ€๊ฒฝ
LEEJaeHyeok97 Apr 1, 2026
13d9085
feat: ์ƒ์ฐจ๋ฆผ ์ž…๋ ฅ ์‹œ enum ํƒ€์ž… ๋ฌธ์ž์—ด๋กœ ์ž…๋ ฅ ํ•˜๋„๋ก ์ˆ˜์ •๋ฐ ์žฌ์ž…๋ ฅ ๋กœ์ง ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 1, 2026
21c418a
refactor: ๊ธฐ๋ฌผ์˜ ํƒ€์ž…๊ณผ ๊ธฐ๋ฌผ ์ „๋žต์„ Type enum ํด๋ž˜์Šค์— ํ•˜๋‚˜๋กœ ๋ณ€๊ฒฝ
LEEJaeHyeok97 Apr 2, 2026
30be12a
refactor: board์™€ strategy์˜ ์ฑ…์ž„์„ ๋” ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌ
LEEJaeHyeok97 Apr 2, 2026
d8f08d3
feat: ๊ธฐ๋ฌผ ์ด๋™ ์ž…๋ ฅ์ด ๋๋‚˜๋ฉด ๋งค๋ฒˆ ๋ฌป๋˜ retry ๋กœ์ง ์ œ๊ฑฐ, ํ•ญ๋ณต ์‹œ ๊ฒŒ์ž„ ์ข…๋ฃŒ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 4, 2026
92e43d7
refactor: ์‚ฌ์˜ ์ด๋™ ๊ทœ์น™์— ๋ถˆํ•„์š”ํ•œ ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ
LEEJaeHyeok97 Apr 4, 2026
e89eae0
refactor: Type(enum)์˜ ์ „๋žต ํ•„๋“œ๋ฅผ ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ ๋ฐฉ์‹์—์„œ ์‹คํ–‰ ์‹œ ์ดˆ๊ธฐํ™” ํ•˜๋„๋ก ์ˆ˜์ •
LEEJaeHyeok97 Apr 5, 2026
550fbca
docs: ์‚ฌ์ดํด2 ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋‚ด์šฉ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 6, 2026
f264ebc
feat: ์กธ์˜ ๊ถ์„ฑ ์•ˆ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
badbe55
feat: ๊ถ์˜ ๊ถ์„ฑ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
345954c
fix: ์กธ์ด ์ „์ง„ํ•˜์ง€ ๋ชปํ•˜๋˜ ๊ฒƒ ์ˆ˜์ •
LEEJaeHyeok97 Apr 7, 2026
e6def27
feat: ์กธ์˜ ๊ถ์„ฑ ์•ˆ ๋Œ€๊ฐ์„  ์ด๋™ ๊ทœ์น™ ๊ตฌํ˜„ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
bf14656
test: ๊ถ์˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋Œ€๊ฐ์„  ์ด๋™ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
0dd4bac
feat: ๊ถ์˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋Œ€๊ฐ์„  ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
90dafbf
feat: ์‚ฌ์˜ ๋ถˆ๊ฐ€๋Šฅํ•œ ๋Œ€๊ฐ์„  ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 7, 2026
8a45713
feat: ์‚ฌ์˜ ๊ถ์„ฑ ๋ฐ– ์ด๋™ ์ œํ•œ ๊ทœ์น™ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 8, 2026
dee9112
feat: ์ฐจ์˜ ๊ถ์„ฑ ์•ˆ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 8, 2026
7471b66
feat: ํฌ์˜ ๊ถ์„ฑ ์•ˆ์—์„œ ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 8, 2026
b5aaa6e
docs: ๊ถ์„ฑ ์˜์—ญ ๊ตฌํ˜„ ๊ธฐ๋Šฅ ๋‚ด์—ญ ๋ฐ˜์˜
LEEJaeHyeok97 Apr 8, 2026
a20e0fb
refacotr: JanggiGame ๊ฐ์ฒด ๋„์ž…, Controller์— ํผ์ง„ ๋ณด๋“œ ๊ฐ์ฒด ์บก์Аํ™”
LEEJaeHyeok97 Apr 8, 2026
c4286b5
test: JanggiGame ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 8, 2026
5b97409
feat: ์ ์ˆ˜ ๊ณ„์‚ฐ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 8, 2026
f2eec99
docs: ๊ธฐ๋Šฅ ๊ตฌํ˜„ ๋‚ด์—ญ ์ตœ์‹ ํ™”
LEEJaeHyeok97 Apr 8, 2026
f34dfae
feat: DB ์ ์šฉ ๋ฐ ๋ทฐ ๊ณ„์ธต ๋ถ„๋ฆฌ
LEEJaeHyeok97 Apr 9, 2026
f3f04af
Merge branch 'leejaehyeok97' into leejaehyeok97-step2
LEEJaeHyeok97 Apr 9, 2026
e24988c
feat: ๊ถ์ด 0,4 ๋˜๋Š” 9,4 ์œ„์น˜์—์„œ ๋Œ€๊ฐ์„  ์ด๋™ ๊ทœ์น™ ์ถ”๊ฐ€ ๋ฐ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 11, 2026
2cc7a3c
Merge branch 'leejaehyeok97-step2' of https://github.com/LEEJaeHyeok9โ€ฆ
LEEJaeHyeok97 Apr 12, 2026
7c2b8e0
feat: ๊ถ์„ฑ ๋ฐ–์—์„œ ์ฐจ์˜ ๋Œ€๊ฐ์„  ์ด๋™ ์ œํ•œ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 12, 2026
06a67be
feat: ์žฅ๊ธฐ๊ฒŒ์ž„์— ํ•ญ๋ณต ํ•„๋“œ ์ถ”๊ฐ€ ๋ฐ ํ–‰์œ„ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 13, 2026
6d24523
refactor: Document ๊ฐ์ฒด ๋งŒ๋“œ๋Š” ๊ณตํ†ต ์ฝ”๋“œ ๋ฉ”์†Œ๋“œํ™”
LEEJaeHyeok97 Apr 13, 2026
2d00432
refacotr: ์žฅ๊ธฐ๊ฒŒ์ž„ ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ ๋ถˆํ•„์š”ํ•œ ์ดˆ๊ธฐํ™” ์ˆ˜์ •
LEEJaeHyeok97 Apr 13, 2026
0b98381
refactor: ํ˜„์žฌ ํ„ด์„ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์†Œ๋“œ์˜ ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ
LEEJaeHyeok97 Apr 13, 2026
ae1956c
refactor: BoardDao์˜ db ์—ฐ๊ฒฐ์ฑ…์ž„ MongoConnection์œผ๋กœ ๋ถ„๋ฆฌ
LEEJaeHyeok97 Apr 13, 2026
f0cecfd
refactor: ์ปจํŠธ๋กค๋Ÿฌ์— ์žˆ๋˜ ์ƒ์ฐจ๋ฆผ ๋ถ„๊ธฐ ์ฝ”๋“œ formation enum ํด๋ž˜์Šค๋กœ ์ด๋™
LEEJaeHyeok97 Apr 13, 2026
6b73bf0
feat: ์ด๋ฏธ ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„์„ ๋ถˆ๋Ÿฌ์™”์„ ๋•Œ ์ข…๋ฃŒ๋์Œ์„ ์œ ์ €์—๊ฒŒ ์•Œ๋ฆฌ๊ณ  ์žฌ์ž…๋ ฅ ๋ฐ›๋Š” ๊ธฐ๋Šฅ ์ถ”๊ฐ€
LEEJaeHyeok97 Apr 13, 2026
22ad346
refactor: ๊ถ์„ฑ ์ด๋™ ์ „๋žต ํŒจํ„ด ๋ถ„๋ฆฌ
LEEJaeHyeok97 Apr 13, 2026
ed1155c
feat: ํ•œ๋‚˜๋ผ์˜ ์ƒ์ฐจ๋ฆผ ๋ฐฐ์น˜ ๋ฐฉ์‹ ์ˆ˜์ •
LEEJaeHyeok97 Apr 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
- ๋ชฉ์ ์ง€์— ๊ฐ™์€ ํŒ€ ๊ธฐ๋ฌผ์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์ด๋™ํ•˜์ง€ ๋ชปํ•œ๋‹ค.
- ๋ชฉ์ ์ง€์— ๋‹ค๋ฅธ ํŒ€ ๊ธฐ๋ฌผ์ด ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ๊ธฐ๋ฌผ์„ ์žก์„ ์ˆ˜ ์žˆ๋‹ค.
- ์ด๋™ํ•  ๊ธฐ๋ฌผ์ด ํฌ์ด๊ณ  ์ด๋™ ๊ฒฝ๋กœ์— ํฌ๋ฅผ ์ œ์™ธํ•œ ๋‹ค๋ฅธ ๊ธฐ๋ฌผ์ด ์žˆ๋‹ค๋ฉด ๊ธฐ๋ฌผ์„ ๋„˜์–ด์„œ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.
- [x] ๊ธฐ๋ฌผ์˜ ์ด๋™์— ๊ถ์„ฑ(ๅฎฎๅŸŽ) ์˜์—ญ์˜ ๊ทœ์น™์„ ํฌํ•จํ•œ๋‹ค.
- [x] ์™•์ด ์žกํžˆ๋Š” ๊ฒฝ์šฐ ๊ฒŒ์ž„์—์„œ ์ง„๋‹ค.
- ์™•์ด ์žกํ˜”์„ ๋•Œ ๊ฒŒ์ž„์„ ์ข…๋ฃŒํ•œ๋‹ค.
- [x] ํ˜„์žฌ ๋‚จ์•„ ์žˆ๋Š” ๊ธฐ๋ฌผ์— ๋Œ€ํ•œ ์ ์ˆ˜๋ฅผ ๊ตฌํ• ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
- [x] ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์žฌ์‹œ์ž‘ํ•˜๋”๋ผ๋„ ์ด์ „์— ํ•˜๋˜ ์žฅ๊ธฐ ๊ฒŒ์ž„์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
- DB๋ฅผ ์ ์šฉํ•  ๋•Œ ๋„๋ฉ”์ธ ๊ฐ์ฒด์˜ ๋ณ€๊ฒฝ์„ ์ตœ์†Œํ™”ํ•ด์•ผ ํ•œ๋‹ค.

### ์˜ˆ์™ธ ๊ธฐ๋Šฅ
- [x] ์žฅ๊ธฐํŒ์„ ๋ฒ—์–ด๋‚˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒํ•œ๋‹ค.
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ repositories {
}

dependencies {
implementation 'org.mongodb:mongodb-driver-sync:5.3.1'

testImplementation platform('org.junit:junit-bom:5.11.4')
testImplementation platform('org.assertj:assertj-bom:3.27.3')
testImplementation('org.junit.jupiter:junit-jupiter')
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import controller.JanggiController;
import dao.mongodb.BoardDao;
import dao.mongodb.MongoConnection;
import view.InputView;
import view.OutputView;

public class Application {

public static void main(String[] args) {
JanggiController janggiController = new JanggiController(new InputView(), new OutputView());
janggiController.run();
try (MongoConnection connection = new MongoConnection()) {
JanggiController janggiController = new JanggiController(new InputView(), new OutputView(), new BoardDao(connection));
janggiController.run();
}
}
}
}
118 changes: 85 additions & 33 deletions src/main/java/controller/JanggiController.java
Original file line number Diff line number Diff line change
@@ -1,43 +1,103 @@
package controller;

import dao.mongodb.BoardDao;
import domain.Board;
import domain.BoardFactory;
import domain.Formation;
import domain.JanggiGame;
import domain.Team;
import domain.vo.Position;
import dto.PieceDto;
import java.util.List;
import presentation.PositionCommand;
import view.InputView;
import view.OutputView;

public class JanggiController {

private static final String RESUME_GAME_NUMBER = "2";
private static final String SURRENDER = "ํ•ญ๋ณต";

private final InputView inputView;
private final OutputView outputView;
private final BoardDao boardDao;

public JanggiController(InputView inputView, OutputView outputView) {
public JanggiController(InputView inputView, OutputView outputView, BoardDao boardDao) {
this.inputView = inputView;
this.outputView = outputView;
this.boardDao = boardDao;
}

public void run() {
String command = inputView.readCommand();

if (command.equals(RESUME_GAME_NUMBER)) {
resumeGame();
return;
}

startNewGame();
}

private void startNewGame() {
Board board = BoardFactory.setUp();
board = readHanFormation(board);
board = readChuFormation(board);

outputView.printBoard(board.getBoard());
JanggiGame janggiGame = JanggiGame.of(board);
Comment thread
her0807 marked this conversation as resolved.
String gameId = boardDao.save(PieceDto.fromBoard(board.getBoard()), janggiGame.getTurnCount());

playGame(gameId, janggiGame);
}

private void resumeGame() {
while (true) {
try {
String gameId = inputView.readGameId();
List<PieceDto> pieceDtos = boardDao.findPiecesByGameId(gameId);

int turnCount = boardDao.findTurnCountByGameId(gameId);
Board board = PieceDto.toBoard(pieceDtos);
JanggiGame janggiGame = JanggiGame.of(board, turnCount);

playGame(gameId, janggiGame);
return;
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
System.out.println();
}
}
}

private void playGame(String gameId, JanggiGame janggiGame) {
outputView.printCurrentGameId(gameId);
outputView.printBoard(janggiGame.getBoardStatus());

int turnCount = 0;
turnCount = movePosition(board, turnCount);
while (true) {
movePosition(janggiGame);
boardDao.update(gameId, PieceDto.fromBoard(janggiGame.getBoardStatus()), janggiGame.getTurnCount());

if (janggiGame.isFinished()) {
boardDao.finish(gameId);
outputView.printGameFinishMessage();
outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU));
break;
}

while (inputView.readRetryCommand()) {
turnCount = movePosition(board, turnCount);
if (janggiGame.isSurrendered()) {
boardDao.finish(gameId);
outputView.printGameSurrenderMessage();
outputView.printScore(janggiGame.calculateScore(Team.HAN), janggiGame.calculateScore(Team.CHU));
break;
}
}
Comment thread
her0807 marked this conversation as resolved.
}

private Board readChuFormation(Board board) {
while (true) {
try {
String chuArrangement = inputView.readArrangement(Team.CHU);
board = applyArrangement(chuArrangement, board, Team.CHU);
board = Formation.from(chuArrangement, board, Team.CHU);
return board;
} catch (Exception e) {
System.out.println(e.getMessage());
Expand All @@ -50,7 +110,7 @@ private Board readHanFormation(Board board) {
while (true) {
try {
String hanArrangement = inputView.readArrangement(Team.HAN);
board = applyArrangement(hanArrangement, board, Team.HAN);
board = Formation.from(hanArrangement, board, Team.HAN);

return board;
} catch (Exception e) {
Expand All @@ -60,35 +120,27 @@ private Board readHanFormation(Board board) {
}
}

private static Board applyArrangement(String arrangement, Board board, Team team) {
if (Formation.from(arrangement) == Formation.SANG_MA_SANG_MA) {
return BoardFactory.setUpLeftElephantFormation(board.getBoard(), team);
}
if (Formation.from(arrangement) == Formation.MA_SANG_MA_SANG) {
return BoardFactory.setUpRightElephantFormation(board.getBoard(), team);
}
if (Formation.from(arrangement) == Formation.MA_SANG_SANG_MA) {
return BoardFactory.setUpInnerElephantFormation(board.getBoard(), team);
}
if (Formation.from(arrangement) == Formation.SANG_MA_MA_SANG) {
return BoardFactory.setUpOuterElephantFormation(board.getBoard(), team);
}

return board;
}

private int movePosition(Board board, int turnCount) {
private void movePosition(JanggiGame janggiGame) {
while (true) {
try {
outputView.printCurrentTurn(turnCount);
outputView.printCurrentTurn(janggiGame.currentTurn());

String input = inputView.readPosition();
if (input.equals(SURRENDER)) {
janggiGame.surrender();
return;
}
Comment thread
her0807 marked this conversation as resolved.

String targetInput = inputView.readTargetPosition();

Position position = PositionCommand.from(input).toPosition();
Position targetPosition = PositionCommand.from(targetInput).toPosition();

Position position = inputView.readPosition();
Position targetPosition = inputView.readTargetPosition();
janggiGame.move(position, targetPosition);
outputView.printBoard(janggiGame.getBoardStatus());
janggiGame.passTheTurn();

Team currentTeam = Team.from(turnCount);
board.move(position, targetPosition, currentTeam);
outputView.printBoard(board.getBoard());
return turnCount += 1;
return;
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println();
Expand Down
111 changes: 111 additions & 0 deletions src/main/java/dao/mongodb/BoardDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package dao.mongodb;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import dto.PieceDto;
import java.util.ArrayList;
import java.util.List;
import org.bson.Document;
import org.bson.types.ObjectId;

public class BoardDao {

private final MongoCollection<Document> collection;

public BoardDao(MongoConnection connection) {
this.collection = connection.getCollection("board");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

MongoClient๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Connection Pool์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฌด๊ฑฐ์šด ๊ฐ์ฒด์ธ๋ฐ์š”, ํ˜„์žฌ ์ฝ˜์†” ์•ฑ์ด๋ผ JVM ์ข…๋ฃŒ ์‹œ ์ •๋ฆฌ๋˜๊ธด ํ•˜์ง€๋งŒ close()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”,, MongoClient๋ฅผ ํ•„๋“œ๋กœ ์ €์žฅํ•˜๊ณ  close() ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜, try-with-resources๋กœ ๊ฐ์‹ธ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ํ˜„์žฌ BoardDao ์ƒ์„ฑ์ž์—์„œ MongoDB ์—ฐ๊ฒฐ ์ƒ์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์ด๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ์ฑ…์ž„์„ ๋™์‹œ์— ๊ฐ–๊ณ  ์žˆ๋Š”๋ฐ์š”. ์—ฐ๊ฒฐ ์„ค์ •(URL, ์ธ์ฆ์ •๋ณด, DB๋ช…)์€ ์ธํ”„๋ผ ๊ด€์‹ฌ์‚ฌ์ด๊ณ , CRUD ์ˆ˜ํ–‰์€ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ด€์‹ฌ์‚ฌ์ธ๋ฐ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์— ์„ž์—ฌ ์žˆ์–ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ๋‹ค๋ฅธ DB์— ์—ฐ๊ฒฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด BoardDao ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๊ฑฐ๋“ ์š”. ์—ฐ๊ฒฐ ์„ค์ •์„ ๋ณ„๋„ Config ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•ด๋ณด๋ฉด ์–ด๋–จ๊นŒ์š”?

Copy link
Copy Markdown
Author

@LEEJaeHyeok97 LEEJaeHyeok97 Apr 13, 2026

Choose a reason for hiding this comment

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

try-with-resource ์ ์šฉ ๋ฐ BoardDao์˜ ์ฑ…์ž„์ด ๋‘๊ฐ€์ง€๋˜ ๊ฒƒ์„ db ์—ฐ๊ฒฐ์šฉ ํด๋ž˜์Šค(MongoConnection)๊ณผ ์ˆœ์ˆ˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ํด๋ž˜์Šค์ธ BoardDao๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

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.

MongoClient๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ Connection Pool์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฌด๊ฑฐ์šด ๊ฐ์ฒด์ธ๋ฐ์š”, ํ˜„์žฌ ์ฝ˜์†” ์•ฑ์ด๋ผ JVM ์ข…๋ฃŒ ์‹œ ์ •๋ฆฌ๋˜๊ธด ํ•˜์ง€๋งŒ close()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฆฌ์†Œ์Šค ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”,, MongoClient๋ฅผ ํ•„๋“œ๋กœ ์ €์žฅํ•˜๊ณ  close() ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜, try-with-resources๋กœ ๊ฐ์‹ธ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”!

์ปค๋„ฅ์…˜ ํ’€ ์ด์•ผ๊ธฐ๊ฐ€ ๋‚˜์™€์„œ ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค>.! ์ปค๋„ฅ์…˜ ํ’€์ด ์œ ์ €์˜ ์—ฐ๊ฒฐ์„ ๋•๋Š”๋ฐ ์žฌ์‚ฌ์šฉ์ด๋ผ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋Š” ๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค! ์š”์ฒญ ์‹œ ๋งˆ๋‹ค ์ปค๋„ฅ์…˜์„ ์ƒ์„ฑํ•˜๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ๋งŒ๋“ค์–ด๋’€๋‹ค๊ฐ€ ๋‹ค์‹œ ํ’€์–ด ์ง‘์–ด ๋„ฃ๊ณ  ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ตœ์ ํ™”๋ฅผ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•„๋Š”๋ฐ, 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.

์™„์ „ ์ข‹์€ ์งˆ๋ฌธ์ด์—์š”! ์ด ๋ถ€๋ถ„์ด ํ—ท๊ฐˆ๋ฆฌ๋Š” ๊ฐ€์žฅ ํฐ ์ด์œ ๋Š” close()๋ผ๋Š” ๊ฐ™์€ ์ด๋ฆ„์ด ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๋™์ž‘์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด์—์š”.

ํ’€์—์„œ ๋นŒ๋ฆฐ Connection์˜ close()๋Š” ์ง„์งœ ๋‹ซ๋Š” ๊ฒŒ ์•„๋‹ˆ์—์š”

// ํ’€ ์—†์ด ์ง์ ‘ ๋งŒ๋“  ๊ฒฝ์šฐ
Connection conn = DriverManager.getConnection(url);
conn.close();  // ์ง„์งœ TCP ์—ฐ๊ฒฐ ๋Š๊น€

// ํ’€์—์„œ ๋นŒ๋ฆฐ ๊ฒฝ์šฐ
Connection conn = dataSource.getConnection();  // ํ’€์—์„œ ๊บผ๋ƒ„
conn.close();  // ํ’€์— ๋Œ๋ ค๋†“๊ธฐ๋งŒ ํ•จ! TCP ์—ฐ๊ฒฐ์€ ์‚ด์•„์žˆ์Œ

DataSource.getConnection()์ด ๋ฐ˜ํ™˜ํ•˜๋Š” Connection์€ **์‹ค์ œ Connection์„ ๊ฐ์‹ผ Wrapper(ํ”„๋ก์‹œ)**์˜ˆ์š”. ์ด Wrapper์˜ close()๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ด Connection์„ ํ’€์— ๋ฐ˜ํ™˜ํ•œ๋‹ค๋กœ ๋™์ž‘ํ•˜๋„๋ก ์˜ค๋ฒ„๋ผ์ด๋“œ๋˜์–ด ์žˆ์–ด์š”. ๊ทธ๋ž˜์„œ ๋งค๋ฒˆ close()ํ•ด๋„ ์žฌ์‚ฌ์šฉ์„ฑ์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ผ์š”!

๊ทธ๋Ÿผ ๋ˆ„๋ˆ„ํ•œํ…Œ ์•Œ๋ ค๋“œ๋ฆฐ close()๋Š” ๋ญ์˜€๋‚˜์š”?

์ €๋Š” ๋‘ ๊ฐ€์ง€๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ๋ง์”€๋“œ๋ฆฐ ๊ฑฐ์˜ˆ์š”

  • ๋งค ์š”์ฒญ ํ›„ connection.close(): ํ’€์— ๋ฐ˜ํ™˜ โ†’ ์žฌ์‚ฌ์šฉ์„ฑ ์‚ด์•„์žˆ์Œ
  • ์•ฑ ์ข…๋ฃŒ ์‹œ mongoClient.close(): ํ’€ ์ž์ฒด ์ •๋ฆฌ โ†’ ๋ฆฌ์†Œ์Šค ์™„์ „ ํ•ด์ œ

์‹ค๋ฌด์—์„œ ์ปค๋„ฅ์…˜ ํ’€ ์šด์˜ํ•˜๋‹ค ๋ณด๋ฉด ์ด๊ฑธ ์ •ํ™•ํžˆ ๋ชจ๋ฅด๊ณ  mongoClient.close()๋ฅผ ๋งค๋ฒˆ ํ˜ธ์ถœํ•ด์„œ ํ’€์ด ๋ง๊ฐ€์ง€๋Š” ์‚ฌ๊ณ ๊ฐ€ ์ข…์ข… ๋‚˜๊ฑฐ๋“ ์š”. ๊ทธ๋ž˜์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์„ ์•Œ๊ณ  ๋„˜์–ด๊ฐ€๋‹ˆ ์ข‹๋„ค์š”

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.

JDBC๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ getConnection() -> close()๋กœ ํ’€ ๋ฐ˜ํ™˜์„ ๊ด€๋ฆฌํ•˜์ง€๋งŒ, MongoDB ๋“œ๋ผ์ด๋ฒ„๋Š” ๊ฐ ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ ๋‚ด๋ถ€์ ์œผ๋กœ ํ’€์—์„œ ๊บผ๋‚ด๊ณ  ์ž๋™ ๋ฐ˜ํ™˜๊นŒ์ง€ ํ•ฉ๋‹ˆ๋‹ค! ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฐœ์ž…ํ•  ๊ตฌ๊ฐ„์ด ์—†์Šต๋‹ˆ๋‹ค.

JDBC ์„ค๋ช…๊ณผ MongoDB ์„ค๋ช…์ด ์„ž์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค
JDBC ๊ธฐ์ค€ ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ๊บผ๋‚ด๋Š” ๊ฒƒ์€ dataSource.getConnection()
ํ’€์— ๋ฐ˜ํ™˜ ํ•˜๋Š” ๊ฒƒ์€ connection.close();
ํ’€ ์ž์ฒด๋ฅผ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์€ datasource.close();

MongoDB ๊ธฐ์ค€ ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ๊บผ๋‚ด๊ฑฐ๋‚˜ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ๋“œ๋ผ์ด๋ฒ„๊ฐ€ ์ž๋™์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
mongoClient.close(): ํ’€ ์ž์ฒด ์ •๋ฆฌ O

public String save(List<PieceDto> pieces, int turnCount) {
ArrayList<Document> pieceDocuments = new ArrayList<>();

for (PieceDto pieceDto : pieces) {
pieceDocuments.add(toDocument(pieceDto));
}

Document gameDocument = getDocument(turnCount, pieceDocuments);

collection.insertOne(gameDocument);
return gameDocument.getObjectId("_id").toString();
}

public List<PieceDto> findPiecesByGameId(String gameId) {
Document gameDocument = findGameDocument(gameId);

if (gameDocument.getBoolean("isFinished")) {
throw new IllegalArgumentException("[ERROR] ์ด๋ฏธ ์ข…๋ฃŒ๋œ ๊ฒŒ์ž„์ž…๋‹ˆ๋‹ค: " + gameId);
}

List<Document> pieces = gameDocument.getList("pieces", Document.class);
List<PieceDto> pieceDtos = new ArrayList<>();

for (Document doc : pieces) {
pieceDtos.add(toPieceDto(doc));
}

return pieceDtos;
}

public int findTurnCountByGameId(String gameId) {
Document gameDocument = findGameDocument(gameId);
return gameDocument.getInteger("turnCount");
}

public void update(String gameId, List<PieceDto> pieces, int turnCount) {
ArrayList<Document> pieceDocuments = new ArrayList<>();

for (PieceDto pieceDto : pieces) {
pieceDocuments.add(toDocument(pieceDto));
}

Document updateFields = new Document("$set", new Document()
.append("pieces", pieceDocuments)
.append("turnCount", turnCount));

collection.updateOne(
Filters.eq("_id", new ObjectId(gameId)),
updateFields
);
}
Comment on lines +64 to +69
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

๋ˆ„๋ˆ„๊ฐ€ ์ •๋ฆฌํ•œ MongoDB ์žฅ์  ์ค‘ ์Šคํ‚ค๋งˆ ์œ ์—ฐ์„ฑ: pieces ๋ฐฐ์—ด๋กœ ํ•˜๋‚˜์˜ Document์— ๋‹ด์„ ์ˆ˜ ์žˆ์–ด JOIN์ด ๋ถˆํ•„์š”๋ผ๋Š” ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋Š”๋ฐ์š”, ํ•œ ๊ฐ€์ง€ ๋” ๊นŠ์ด ์ƒ๊ฐํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”.

ํ˜„์žฌ ๊ตฌ์กฐ์—์„œ๋Š” ๋งค ํ„ด๋งˆ๋‹ค ์ „์ฒด ๊ธฐ๋ฌผ ๋ฐฐ์—ด์„ ํ†ต์งธ๋กœ ๊ต์ฒดํ•˜๊ณ  ์žˆ์–ด์š”.

RDBMS์˜€๋‹ค๋ฉด ์ด๋™ํ•œ ๊ธฐ๋ฌผ 1~2๊ฐœ๋งŒ UPDATEํ•˜๋ฉด ๋˜๋Š”๋ฐ, MongoDB Document ๊ตฌ์กฐ์—์„œ๋Š” ๊ธฐ๋ฌผ 32๊ฐœ๋ฅผ ๋งค๋ฒˆ ์ „๋ถ€ ์ง๋ ฌํ™”ํ•ด์„œ ์ €์žฅํ•˜๊ณ  ์žˆ๊ฑฐ๋“ ์š”. ์ด trade-off๋ฅผ ์ธ์ง€ํ•˜๊ณ  ์žˆ์—ˆ๋‚˜์š”? ํ˜„์žฌ ๊ทœ๋ชจ์—์„œ๋Š” ๋ฌธ์ œ ์—†์ง€๋งŒ, Document๋กœ ํ•œ ๋ฒˆ์— ๋‹ด๋Š” ๊ฒŒ ํ•ญ์ƒ ์ข‹์€ ๊ฑด์ง€ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PR ์„ค๋ช…์—์„œ ์ด๋ ‡๊ฒŒ ์ ์–ด์ฃผ์…จ๋Š”๋ฐ์š”!

ํŠธ๋žœ์žญ์…˜ ๋ฏธ์ง€์›(๋‹จ์ผ ๋…ธ๋“œ): ํ˜„์žฌ ๊ตฌ์กฐ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ๊ฒŒ์ž„ ์ƒํƒœ ์ €์žฅ์ด ์—ฌ๋Ÿฌ ์ปฌ๋ ‰์…˜์— ๊ฑธ์น˜๊ฒŒ ๋œ๋‹ค๋ฉด ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๊ฐ€ RDBMS๋ณด๋‹ค ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ธ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๋ถ€๋ถ„์€ ์‚ฌ์‹ค ์ •ํ™•ํ•˜์ง€ ์•Š์•„์š”! MongoDB๋Š” 4.0(2018๋…„)๋ถ€ํ„ฐ ๋ฉ€ํ‹ฐ ๋„ํ๋จผํŠธ ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„๋ˆ„๊ฐ€ ์‚ฌ์šฉ ์ค‘์ธ ๋“œ๋ผ์ด๋ฒ„(mongodb-driver-sync:5.3.1)๋„ ๋‹น์—ฐํžˆ ์ง€์›ํ•˜๊ณ ์š”.

// MongoDB์—์„œ๋„ ํŠธ๋žœ์žญ์…˜์ด ๊ฐ€๋Šฅํ•ด์š”
try (ClientSession session = client.startSession()) {
    session.startTransaction();
    collection1.insertOne(session, doc1);
    collection2.insertOne(session, doc2);
    session.commitTransaction();
}

๋‹ค๋งŒ ๋ˆ„๋ˆ„์˜ ํ˜„์žฌ ๊ตฌ์กฐ์—์„œ๋Š” ๊ฒŒ์ž„ ์ƒํƒœ๊ฐ€ ๋‹จ์ผ Document ํ•˜๋‚˜์— ์ „๋ถ€ ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ํŠธ๋žœ์žญ์…˜์ด ํ•„์š” ์—†๋Š” ๊ตฌ์กฐ์ด๊ธด ํ•ด์š”. MongoDB๋Š” ๋‹จ์ผ Document์— ๋Œ€ํ•œ ์›์ž์  ์“ฐ๊ธฐ๋ฅผ ๊ธฐ๋ณธ ๋ณด์žฅํ•˜๊ฑฐ๋“ ์š”. ๊ทธ๋ž˜์„œ replaceOne()์ด ์ค‘๊ฐ„์— ์‹คํŒจํ•ด๋„ ๋ฐ˜์ฏค ์ €์žฅ๋˜๋Š” ์ผ์€ ์—†์–ด์š”.

์ •๋ฆฌํ•˜๋ฉด, ํŠธ๋žœ์žญ์…˜์ด ์•ˆ ๋ผ์„œ ๊นŒ๋‹ค๋กญ๋‹ค๊ฐ€ ์•„๋‹ˆ๋ผ ๋‹จ์ผ Document ๊ตฌ์กฐ๋ผ์„œ ํŠธ๋žœ์žญ์…˜์ด ์• ์ดˆ์— ํ•„์š” ์—†๋‹ค๊ฐ€ ๋” ์ •ํ™•ํ•œ ํ‘œํ˜„์ด์—์š”!

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

์žฅ๊ธฐ ๋„๋ฉ”์ธ์— MongoDB๊ฐ€ ์ •๋ง ์ ํ•ฉํ•œ ์„ ํƒ์ผ๊นŒ? ๐Ÿค”

๋ˆ„๋ˆ„๊ฐ€ MongoDB๋ฅผ ์„ ํƒํ•œ ๋„์ „ ์ •์‹ ์€ ์ •๋ง ์ข‹์•˜์–ด์š”! ๋‹ค๋งŒ ์†”์งํ•˜๊ฒŒ ์ด์•ผ๊ธฐํ•˜๋ฉด, ์žฅ๊ธฐ๋Š” RDBMS๊ฐ€ ๋” ์ž์—ฐ์Šค๋Ÿฌ์šด ๋„๋ฉ”์ธ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”. ์ด์œ ๋ฅผ ๋ช‡ ๊ฐ€์ง€ ์ •๋ฆฌํ•ด๋ณผ๊ฒŒ์š”.

์žฅ๊ธฐ๊ฐ€ RDBMS์— ๋” ๋งž๋Š” ์ด์œ 

  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ๋งค์šฐ ๊ณ ์ •์ ์ด์—์š”. 9x10 ๋ณด๋“œ, ๊ณ ์ •๋œ ๊ธฐ๋ฌผ ํƒ€์ž…, ๊ณ ์ •๋œ ํŒ€ โ€” ์Šคํ‚ค๋งˆ๊ฐ€ ๋ณ€ํ•  ์ผ์ด ์—†์–ด์š”, ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ชฝ๊ณ ๋””๋น„์˜ ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์ด์ ์„ ๋ชป๋ˆ„๋ฆฌ๋Š” ์ƒํ™ฉ์ด์—์š”.
  • ๊ธฐ๋ฌผ ์ด๋™์€ 1~2๊ฐœ ํ–‰๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๋Š”๋ฐ, Document ๊ตฌ์กฐ๋Š” ๋งค๋ฒˆ 32๊ฐœ ๊ธฐ๋ฌผ์„ ์ „๋ถ€ ์ง๋ ฌํ™”ํ•ด์•ผ ํ•ด์š”
  • "์ง„ํ–‰ ์ค‘์ธ ๊ฒŒ์ž„ ๋ชฉ๋ก", "ํŠน์ • ํ”Œ๋ ˆ์ด์–ด์˜ ์ „์ " ๊ฐ™์€ ์ฟผ๋ฆฌ๋Š” RDBMS๊ฐ€ ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฌ์›Œ์š”
  • ์Šคํ‚ค๋งˆ ๊ฐ•์ œ๊ฐ€ ์˜คํžˆ๋ ค ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ์„ ๋ฐฉ์ง€ํ•ด์ค˜์š” ์˜ˆ๋ฅผ๋“ค๋ฉด piece_type์— ์˜คํƒ€๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์ œ์•ฝ ์กฐ๊ฑด์—์„œ ์žกํžˆ๋‹ˆ๊นŒ์š”. ์ง€๊ธˆ์€ ์ž˜๋ชป ์ €์žฅ๋˜๋ฉด ๋‚˜์ค‘์— enum ์ด๋‚˜ ๋‹ค๋ฅธ๊ฑธ๋กœ ์กฐํšŒํ•  ๋•Œ ์บ์ŠคํŒ…ํ•˜๋Š” ๊ณผ์ •์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๊ฒ ์ฃ ?

MongoDB๊ฐ€ ๋น›๋‚˜๋Š” ๋„๋ฉ”์ธ์€

  • ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ์œ ๋™์ ์ธ ๊ฒฝ์šฐ (์˜ˆ: ์‚ฌ์šฉ์ž๋ณ„ ์„ค์ •, ๋กœ๊ทธ, CMS ์ฝ˜ํ…์ธ )
  • ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ
  • ์ˆ˜ํ‰ ํ™•์žฅ์ด ํ•„์š”ํ•œ ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ

๋ฌผ๋ก  ํ˜„์žฌ ๋ฏธ์…˜ ๋ฒ”์œ„์—์„œ๋Š” ๋‘˜ ๋‹ค ์ถฉ๋ถ„ํžˆ ๋™์ž‘ํ•˜๊ณ , MongoDB๋ฅผ ์ง์ ‘ ์จ๋ณธ ๊ฒฝํ—˜ ์ž์ฒด๊ฐ€ ๊ท€ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š”. ํ•™์Šต๋ชฉ์ ์œผ๋กœ ์„ ํƒํ•œ๊ฒƒ๋„ ์ด์œ ๊ฐ€ ๋˜๋‹ˆ๊นŒ์š”!

Copy link
Copy Markdown
Author

@LEEJaeHyeok97 LEEJaeHyeok97 Apr 13, 2026

Choose a reason for hiding this comment

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

MongoDB ์— ๋Œ€ํ•ด ์ฐพ์•„๋ณด๋‹ˆ RDB ์ฒ˜๋Ÿผ ํŠน์ • ํ•„๋“œ๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค.

//ํ•ต์‹ฌ ์ฐจ์ด๋Š” replaceOne์€ _id๋ฅผ ์ œ์™ธํ•œ ๋ฌธ์„œ ์ „์ฒด๋ฅผ ์ƒˆ ๋ฌธ์„œ๋กœ ๋ฎ์–ด์“ฐ์ง€๋งŒ,
// updateOne + $set์€ ์ง€์ •ํ•œ ํ•„๋“œ๋งŒ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€ ํ•„๋“œ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

public void update(String gameId, List<PieceDto> pieces, int turnCount) {
        ArrayList<Document> pieceDocuments = new ArrayList<>();

        for (PieceDto pieceDto : pieces) {
            pieceDocuments.add(toDocument(pieceDto));
        }

        Document updateFields = new Document("$set", new Document()
                .append("pieces", pieceDocuments)
                .append("turnCount", turnCount));

        collection.updateOne(
                Filters.eq("_id", new ObjectId(gameId)),
                updateFields
        );
    }

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ „์ฒด ๋ฌธ์„œ๋ฅผ ๋ฎ์–ด์“ฐ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ํŠน์ • ํ•„๋“œ๋งŒ ๋ฐ”๊พธ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์šฐ์„ , NoSQL์— ๊ด€ํ•œ ์ œ ์ƒ๊ฐ์„ ๋ง์”€๋“œ๋ฆฌ๊ณ  ์‹ถ์–ด์š”.

NoSQL์€ ๋‹จ์ˆœํžˆ "๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ์šฉ"์ด๋ผ๋Š” ํ”„๋ ˆ์ž„์— ๊ฐ€๋‘๊ธฐ์—” ๊ทธ ์ฒ ํ•™์ด ๋” ๋„“๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
์›๊ธ€์—์„œ "Document ๊ตฌ์กฐ๋Š” ๋งค๋ฒˆ 32๊ฐœ ๊ธฐ๋ฌผ์„ ์ „๋ถ€ ์ง๋ ฌํ™”ํ•ด์•ผ ํ•œ๋‹ค"๊ณ  ํ•˜์…จ๋Š”๋ฐ, ์ด๋Š” MongoDB๋ฅผ replaceOne์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.(์ €์˜ ์ž˜๋ชป๋œ ๊ตฌํ˜„ใ… ใ… ) ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ updateOne + $set ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ํ•„๋“œ๋งŒ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค! ํ•ต์‹ฌ ์ฐจ์ด๋Š” replaceOne์€ _id๋ฅผ ์ œ์™ธํ•œ ๋ฌธ์„œ ์ „์ฒด๋ฅผ ๋ฎ์–ด์“ฐ์ง€๋งŒ, updateOne + $set์€ ์ง€์ •ํ•œ ํ•„๋“œ๋งŒ ๊ฐฑ์‹ ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ œ๊ฐ€ ์ž˜๋ชป ๊ตฌํ˜„ํ•ด์„œ ์˜คํ•ด๋ฅผ ๋“œ๋ฆฐ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. "๋งค๋ฒˆ ์ „๋ถ€ ์ง๋ ฌํ™”ํ•ด์•ผ ํ•œ๋‹ค"๋Š” MongoDB์˜ ๋ณธ์งˆ์  ํ•œ๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ ๋ฐฉ์‹์˜ ๋ฌธ์ œ์˜€์Šต๋‹ˆ๋‹ค.

์ตœ๊ทผ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Redis๋ผ๋Š” ์ฑ…์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ณณ์—์„œ NoSQL์€ ๊ธฐ์กด RDB์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋Š” ๋ฌธ๊ตฌ๋ฅผ ์ฝ์€ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ € ๋˜ํ•œ RDB๊ฐ€ ACID๋ฅผ ์ง€์ผœ์„œ ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ์—„๊ฒฉํžˆ ์ง€ํ‚จ๋‹ค๋Š” ์ ์—์„œ ์žฅ์ ์ด ๋งŽ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ NoSQL์€ ๊ทธ ์—„๊ฒฉํ•จ์„ ์˜๋„์ ์œผ๋กœ ์™„ํ™”ํ•˜๋Š” ๋Œ€์‹ , ์œ ์—ฐ์„ฑ๊ณผ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์ด๋ผ๋Š” ๋‹ค๋ฅธ ๊ฐ€์น˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์žฅ๊ธฐ ๋„๋ฉ”์ธ์ฒ˜๋Ÿผ ์Šคํ‚ค๋งˆ๊ฐ€ ๊ณ ์ •์ ์ด๋ผ ํ•ด๋„, ๊ทธ ๊ณ ์ •๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๋ฌธ์„œ๋กœ ์‘์ง‘๋ ฅ ์žˆ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ MongoDB์˜ ์žฅ์ ์ž…๋‹ˆ๋‹ค.

"๊ณ ์ •๋œ ์Šคํ‚ค๋งˆ = RDBMS"๋ผ๋Š” ๋“ฑ์‹์— ๋Œ€ํ•ด์„œ๋„ ์ƒ๊ฐํ•ด๋ณผ ์—ฌ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์žฅ๊ธฐ ๊ฒŒ์ž„ ํ•˜๋‚˜๋ฅผ RDBMS๋กœ ๋ชจ๋ธ๋งํ•˜๋ฉด games ํ…Œ์ด๋ธ”, pieces ํ…Œ์ด๋ธ”, moves ํ…Œ์ด๋ธ” ๋“ฑ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ„์‚ฐ๋˜๊ณ , ๊ฒŒ์ž„ ์ƒํƒœ๋ฅผ ์กฐํšŒํ•  ๋•Œ๋งˆ๋‹ค JOIN์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด MongoDB๋Š” ํ•˜๋‚˜์˜ Document ์•ˆ์— ๊ฒŒ์ž„์˜ ์ „์ฒด ์ƒํƒœ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” "๊ฒŒ์ž„ ํ•˜๋‚˜๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค"๋Š” ๊ฐ€์žฅ ๋นˆ๋ฒˆํ•œ ์—ฐ์‚ฐ์—์„œ ์˜คํžˆ๋ ค ๋” ์ง๊ด€์ ์ด๊ณ  ํšจ์œจ์ ์ธ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณ ์ •์ ์ด๋ผ๋Š” ๊ฒƒ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ค ๋‹จ์œ„๋กœ ๋ฌถ์–ด์„œ ๋‹ค๋ฃจ๋А๋ƒ๋Š” ๋ณ„๊ฐœ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์— ๋Œ€ํ•ด์„œ๋„ MongoDB๋Š” ๋Œ€์•ˆ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
MongoDB๋Š” Schema Validation ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. piece_type์— ์˜คํƒ€๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๋ฌธ์ œ๋Š” RDBMS์˜ ์ œ์•ฝ ์กฐ๊ฑด๋งŒ์œผ๋กœ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, MongoDB์˜ JSON Schema Validation์ด๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์˜ enum ๊ฒ€์ฆ์œผ๋กœ๋„ ์ถฉ๋ถ„ํžˆ ๋Œ€์‘ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์—์„œ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ์ด DB ์ข…๋ฅ˜์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋” ๊ฒฌ๊ณ ํ•œ ๋ฐฉ์–ด์„ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ชฝ๊ณ ๋””๋น„ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๋„ฃ๊ธฐ
https://velog.io/@lemix777/MongoDB-%EC%8A%A4%ED%82%A4%EB%A7%88-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC

Copy link
Copy Markdown

@her0807 her0807 Apr 13, 2026

Choose a reason for hiding this comment

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

๋ˆ„๋ˆ„๊ฐ€ ์ด๋ ‡๊ฒŒ ๊นŠ์ด ๊ณ ๋ฏผํ•˜๊ณ  ๋‹ต๋ณ€ํ•ด์ฃผ์…”์„œ ๋„ˆ๋ฌด ์ข‹์•„์š”! ์ฑ…๊นŒ์ง€ ์ฝ์–ด๋ณด์…จ๋‹ค๋‹ˆ ์ •๋ง ๋ฉ‹์ ธ์š”. ๋‹ค๋งŒ ๋ช‡ ๊ฐ€์ง€ ์งš์–ด๋ณด๊ณ  ์‹ถ์€ ๋ถ€๋ถ„์ด ์žˆ์–ด์„œ ๋‹ค์‹œ ์˜๊ฒฌ ๋‚จ๊ฒจ์š”.

MongoDB๋„ ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋œ๋‹ค๋Š” ๋‹ต๋ณ€์— ๋Œ€ํ•ด

updateOne + $set์„ ์•Œ๋ ค์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ด์š”! ์ œ๊ฐ€ replaceOne ๊ธฐ์ค€์œผ๋กœ๋งŒ ์ด์•ผ๊ธฐํ•œ ๊ฑด ๋งž์•„์š”. ๋‹ค๋งŒ ์ด ๋‹ต๋ณ€์„ ์ฝ์œผ๋ฉด์„œ ํ•œ ๊ฐ€์ง€ ์ƒ๊ฐ์ด ๋“ค์—ˆ์–ด์š”.

MongoDB๋„ RDBMS์ฒ˜๋Ÿผ ํŠน์ • ํ•„๋“œ๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”
MongoDB๋„ RDBMS์ฒ˜๋Ÿผ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์„ ํ•  ์ˆ˜ ์žˆ์–ด์š”

์ด ๋‹ต๋ณ€๋“ค์˜ ๊ณตํ†ต์ ์€ MongoDB๋„ RDBMS์ฒ˜๋Ÿผ ~ํ•  ์ˆ˜ ์žˆ๋‹ค์˜ˆ์š”. ๊ทธ๋Ÿฐ๋ฐ RDBMS์ฒ˜๋Ÿผ ์“ธ ๊ฑฐ๋ฉด RDBMS๋ฅผ ์“ฐ๋ฉด ๋˜์ง€ ์•Š์„๊นŒ์š”?

๋„๊ตฌ๋ฅผ ์„ ํƒํ•  ๋•Œ ์ด ๋„๊ตฌ๋กœ๋„ X๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ฐ€ ๊ทผ๊ฑฐ๊ฐ€ ๋˜๋ฉด ์ข€ ์œ„ํ—˜ํ•ด์š”. ๊ทธ๋Ÿผ ๋ชจ๋“  ๋„๊ตฌ๊ฐ€ ๋‹ค ๊ฐ™์•„์ง€๊ฑฐ๋“ ์š”. ์ง„์งœ ์ƒ๊ฐํ•ด๋ณผ ์ง€์ ์€ ์ด ๋„๋ฉ”์ธ์—์„œ MongoDB๊ฐ€ RDBMS๋ณด๋‹ค ๋” ์ž˜ํ•˜๋Š” ๊ฒŒ ๋ญ”๊ฐ€?์˜ˆ์š”.

MongoDB์˜ ์ง„์งœ ๊ฐ•์ ์€ ์–ด๋””์„œ ๋น›๋‚˜๋‚˜์š”?

MongoDB๊ฐ€ ์ •๋ง ๋น›๋‚˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์ด์ „์— ๋งํ–ˆ๋“ฏ ์•„๋ž˜์™€ ๊ฐ™์•„์š”.

  • ์Šคํ‚ค๋งˆ๊ฐ€ ์ž์ฃผ ๋ณ€ํ•˜๋Š” ๊ฒฝ์šฐ (CMS, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ๋กœ๊ทธ)
  • ์ฝ๊ธฐ/์“ฐ๊ธฐ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  eventual consistency๋ฅผ ๋ฐ›์•„๋“ค์ด๋Š” ๊ฒฝ์šฐ (์†Œ์…œ ํ”ผ๋“œ, ์•Œ๋ฆผ)
  • ๊ณ„์ธต์  ๋ฐ์ดํ„ฐ๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ํ‘œํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ (ํŠธ๋ฆฌ, ์ค‘์ฒฉ ๋Œ“๊ธ€)

์žฅ๊ธฐ ๊ฒŒ์ž„์€ ์ด ์ค‘ ์–ด๋””์—๋„ ํ•ด๋‹นํ•˜์ง€ ์•Š์•„์š”. ๋ˆ„๋ˆ„๊ฐ€ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ณ ์ •์ ์ด๋ผ๋Š” ๊ฒƒ๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ค ๋‹จ์œ„๋กœ ๋ฌถ๋А๋ƒ๋Š” ๋ณ„๊ฐœ๋ผ๊ณ  ํ•˜์…จ๋Š”๋ฐ, ๊ทธ ๋ง์€ ๋งž์•„์š”. ๋‹ค๋งŒ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ๋ฌถ๊ณ  ์‹ถ๋‹ค๊ฐ€ MongoDB๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒฐ์ •์  ์ด์œ ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š”๊ฐ€?๋Š” ๋‹ค๋ฅธ ๋ฌธ์ œ์˜ˆ์š”.

ํ•˜๋‚˜์˜ Document๋กœ ์‘์ง‘์ด ์ง„์งœ MongoDB๋งŒ์˜ ๊ฐ•์ ์ธ๊ฐ€์š”?

PostgreSQL์˜ JSONB, MySQL์˜ JSON ์ปฌ๋Ÿผ์„ ๋ณด๋ฉด, ์‚ฌ์‹ค ํ˜„๋Œ€ RDBMS๋„ ํ•˜๋‚˜์˜ row์— ๋ณต์žกํ•œ JSON ๊ตฌ์กฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ์–ด์š”. PostgreSQL JSONB๋Š” ์ธ๋ฑ์‹ฑ๋„ ๋˜๊ณ  ๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋„ ๋ผ์š”.

MySql ์—์„œ ํ•„๋“œ ์ž์ฒด๋ฅผ json ์œผ๋กœ ์ €์žฅํ•ด์„œ ๊บผ๋‚ด ์“ธ ์ˆ˜๋„ ์žˆ์–ด์š”.

-- PostgreSQL์—์„œ ๊ฒŒ์ž„ ํ•˜๋‚˜๋ฅผ ํ•œ row์— ๋‹ด๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅ
CREATE TABLE games (
    id BIGSERIAL PRIMARY KEY,
    pieces JSONB NOT NULL,
    turn_count INT NOT NULL
);

UPDATE games SET pieces = jsonb_set(pieces, '{0}', '...') WHERE id = 1;

๊ทธ๋ž˜์„œ Document๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” MongoDB์˜ ๊ณ ์œ ํ•œ ๊ฐ•์ ์ด๋ผ๊ธฐ๋ณด๋‹ค๋Š”, ๋ชจ๋˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ณตํ†ต ๊ธฐ๋Šฅ์— ๊ฐ€๊นŒ์›Œ์š”.

Schema Validation ์ถ”๊ฐ€๋Š” MongoDB์˜ ์–‘๋ณด๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”.

์ด๊ฑด ์ข€ ๋„๋ฐœ์ ์ธ ํ‘œํ˜„์ด๊ธด ํ•œ๋ฐ์š”, MongoDB๊ฐ€ Schema Validation์„ ๋„์ž…ํ•œ ๊ฑด ์Šคํ‚ค๋งˆ ์—†๋Š” ์ž์œ ๋กœ์›€์ด ์‹ค๋ฌด์—์„œ ๋„ˆ๋ฌด ๋งŽ์€ ๋ฐ์ดํ„ฐ ์˜ค์—ผ์„ ์ผ์œผ์ผฐ๊ธฐ ๋•Œ๋ฌธ์ด์—์š”. NoSQL์˜ ์ดˆ๊ธฐ ์ฒ ํ•™("์Šคํ‚ค๋งˆ๋Š” ์ž์œ ๋‹ค!")์ด ์‹ค์ œ ์šด์˜์—์„œ ํ•œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋‹ค๋Š” ๊ฑธ ์ธ์ •ํ•œ ๊ฑฐ์ฃ .

๊ทธ๋ž˜์„œ ๋ˆ„๋ˆ„๊ฐ€ MongoDB๋„ Schema Validation์œผ๋กœ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜์‹  ๊ฑด ๋งž์ง€๋งŒ, ๊ทธ ๊ธฐ๋Šฅ์„ ์“ฐ๋Š” ์ˆœ๊ฐ„ RDBMS์˜ ์žฅ์ ์„ ํ‰๋‚ด๋‚ด๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๊ฑฐ๋“ ์š”. ์ฒ˜์Œ๋ถ€ํ„ฐ RDBMS๋ฅผ ์“ฐ๋ฉด ๊ทธ ๊ฒ€์ฆ์ด ๊ทธ๋ƒฅ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋”ฐ๋ผ์™€์š”.

๋‹ค์‹œ ๋Œ์•„์™€์„œ NoSQL์˜ ์ฒ ํ•™์ด ์ •ํ™•ํžˆ ๋ญ˜๊นŒ์š”?

๋ˆ„๋ˆ„๊ฐ€ NoSQL์€ ๋น„์ •ํ˜• ๋ฐ์ดํ„ฐ์šฉ์ด๋ผ๋Š” ํ”„๋ ˆ์ž„์— ๊ฐ€๋‘๊ธฐ์—” ๊ทธ ์ฒ ํ•™์ด ๋” ๋„“๋‹ค ํ•˜์…จ๋Š”๋ฐ, ๊ทธ ๋” ๋„“์€ ์ฒ ํ•™์ด ๊ตฌ์ฒด์ ์œผ๋กœ ๋ญ˜๊นŒ์š”?

์ œ ์ƒ๊ฐ์—๋Š” NoSQL์˜ ๋ณธ์งˆ์  trade-off๋Š” CAP ์ •๋ฆฌ์—์„œ ๋‚˜์˜จ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š”.

  • ์ผ๊ด€์„ฑ(Consistency)์„ ์–‘๋ณดํ•˜๊ณ  ๊ฐ€์šฉ์„ฑ(Availability)๊ณผ ๋ถ„ํ•  ๋‚ด์„ฑ(Partition tolerance)์„ ์–ป๋Š”๋‹ค
  • ACID ๋Œ€์‹  BASE๋ฅผ ๋ฐ›์•„๋“ค์ธ๋‹ค

์žฅ๊ธฐ ๊ฒŒ์ž„์—์„œ ์ด trade-off๋ฅผ ๋ฐ›์•„๋“ค์˜€๋‚˜์š”?

  • ๊ฐ€์šฉ์„ฑ์ด ๊ทธ๋ ‡๊ฒŒ ์ค‘์š”ํ•œ๊ฐ€? (ํ•œ ์‚ฌ๋žŒ์ด ํ•˜๋Š” ๊ฒŒ์ž„)
  • ๋ถ„ํ•  ๋‚ด์„ฑ์ด ํ•„์š”ํ•œ๊ฐ€? (์—ฌ๋Ÿฌ ๋…ธ๋“œ์— ๊ฑธ์นœ ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ?)
  • eventual consistency๊ฐ€ ๊ฒŒ์ž„์— ์ ํ•ฉํ•œ๊ฐ€? (ํ„ด์ด ์‚ด์ง ๋Šฆ๊ฒŒ ๋ฐ˜์˜๋ผ๋„ ๊ดœ์ฐฎ์€๊ฐ€?)

์•„๋‹ˆ๋ผ๋ฉด, NoSQL์˜ ๋ณธ์งˆ์  ๊ฐ•์ ์„ ํ™œ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹จ์ง€ Document ํ˜•ํƒœ๊ฐ€ ์ง๊ด€์ ์ด๋‹ค๋ผ๋Š” ๋ถ€์ˆ˜์  ์ด์œ ๋กœ ์„ ํƒํ•œ ๊ฑฐ์˜ˆ์š”. ๊ทธ๋Ÿผ ๊ทธ๊ฑด NoSQL์˜ ์ฒ ํ•™์„ ๋”ฐ๋ฅธ๋‹ค๊ธฐ๋ณด๋‹ค๋Š” JSON ์ €์žฅ์†Œ๋กœ ์“ฐ๋Š” ๊ฒƒ์— ๊ฐ€๊นŒ์›Œ์š”.

์ €๋Š” ๋ˆ„๋ˆ„์˜ ๋„์ „ ์ •์‹ ๊ณผ MongoDB๋ฅผ ๊นŠ์ด ๊ณต๋ถ€ํ•œ ์ ์€ ์ •๋ง ๋†’์ด ํ‰๊ฐ€ํ•ด์š”.

๋‹ค๋งŒ ๊ฐ ๋„๊ตฌ๋Š” ์ž๊ธฐ๊ฐ€ ์ž˜ํ•˜๋Š” ์˜์—ญ์ด ์žˆ๊ณ , ๊ทธ ์˜์—ญ์— ๋งž์ถฐ ์“ธ ๋•Œ ์ง„์งœ ๊ฐ€์น˜๊ฐ€ ๋‚˜์˜จ๋‹ค๋Š” ๊ฒŒ ์ œ ์ƒ๊ฐ์ด์—์š”. ๋ˆ„๋ˆ„๊ฐ€ MongoDB๋ฅผ ์ง์ ‘ ์จ๋ณด๊ณ  ๊ทธ trade-off๋ฅผ ์ฒด๊ฐํ•œ ๊ฒƒ ์ž์ฒด๊ฐ€ ๊ฐ€์žฅ ํฐ ํ•™์Šต์ด๊ณ , ๊ทธ ๊ฒฝํ—˜์ด ๋‚˜์ค‘์— ์ด ํ”„๋กœ์ ํŠธ์—” ์–ด๋–ค DB๋ฅผ ์จ์•ผ ํ• ๊นŒ? ๊ฒฐ์ •ํ•  ๋•Œ ์ง„์งœ ์ž์‚ฐ์ด ๋  ๊ฑฐ์˜ˆ์š”!

๋‹ค์‹œ ํ•œ๋ฒˆ, ์ฑ…๊นŒ์ง€ ์ฐพ์•„๋ณด๋ฉด์„œ ๋‹ต๋ณ€ํ•ด์ฃผ์…”์„œ ์ •๋ง ๊ฐ์‚ฌํ•ด์š”! ์ด๋Ÿฐ ๊นŠ์ด ์žˆ๋Š” ํ† ๋ก ์ด ์ง„์งœ ์„ฑ์žฅ์„ ๋งŒ๋“ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์š” ใ…Žใ…Ž


public void finish(String gameId) {
Document updateFields = new Document("$set", new Document("isFinished", true));

collection.updateOne(
Filters.eq("_id", new ObjectId(gameId)),
updateFields
);
}

private Document findGameDocument(String gameId) {
Document gameDocument = collection.find(Filters.eq("_id", new ObjectId(gameId))).first();
if (gameDocument == null) {
throw new IllegalArgumentException("[ERROR] ํ•ด๋‹น ๊ฒŒ์ž„์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: " + gameId);
}
return gameDocument;
}

private Document getDocument(int turnCount, ArrayList<Document> pieceDocuments) {
return new Document()
.append("pieces", pieceDocuments)
.append("turnCount", turnCount)
.append("isFinished", false);
}

private Document toDocument(PieceDto pieceDto) {
return new Document()
.append("row", pieceDto.row())
.append("col", pieceDto.col())
.append("team", pieceDto.team())
.append("type", pieceDto.type());
}

private PieceDto toPieceDto(Document doc) {
return new PieceDto(
doc.getInteger("row"),
doc.getInteger("col"),
doc.getString("team"),
doc.getString("type")
);
}
}
30 changes: 30 additions & 0 deletions src/main/java/dao/mongodb/MongoConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dao.mongodb;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

public class MongoConnection implements AutoCloseable {

private static final String CONNECTION_STRING = "mongodb://admin:password123@localhost:27017";
private static final String DATABASE_NAME = "janggi";

private final MongoClient client;
private final MongoDatabase database;

public MongoConnection() {
this.client = MongoClients.create(CONNECTION_STRING);
this.database = client.getDatabase(DATABASE_NAME);
}

public MongoCollection<Document> getCollection(String name) {
return database.getCollection(name);
}

@Override
public void close() {
client.close();
}
}
Loading