RV Badminton App

#spring-boot#flutter#fastapi#duckdb#system-design

์ œ๊ฐ€ ์‹ค์ œ๋กœ ๋‹ค๋‹ˆ๋Š” ๋ฐฐ๋“œ๋ฏผํ„ด ๋ชจ์ž„์„ ์œ„ํ•ด ๋งŒ๋“  ์šด์˜ ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค. ํšŒ์›์€ Flutter ์•ฑ์œผ๋กœ ๊ฒฝ๊ธฐ๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ์‹ค์‹œ๊ฐ„ ๋ฆฌ๋”๋ณด๋“œ์™€ ๊ฐœ์ธ ๊ธฐ๋ก์„ ํ™•์ธํ•˜๋ฉฐ, Spring Boot ๋ฐฑ์—”๋“œยท์šด์˜์ง„ ๋Œ€์‹œ๋ณด๋“œยทPython ํฌ์ธํŠธ ๊ณ„์‚ฐ ์„œ๋น„์Šค๊ฐ€ ์ด๋ฅผ ๋’ท๋ฐ›์นจํ•ฉ๋‹ˆ๋‹ค. App Store์™€ Google Play์— ์ถœ์‹œํ•ด ๋ชจ์ž„์ด ๋งค์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

App Store์™€ Google Play์— ์˜ฌ๋ผ๊ฐ„ RV ๋ฐฐ๋“œ๋ฏผํ„ด ์•ฑ ํŽ˜์ด์ง€

๋ฌธ์ œ

๋ชจ์ž„์€ ๋‹จํ†ก๋ฐฉ 100๋ช… ์ด์ƒ, ์ •๋ชจ๋งˆ๋‹ค 30โ€“40๋ช…์ด ๋ชจ์ด๋Š” ๊ทœ๋ชจ๋กœ ์ปค์กŒ๊ณ , ๋ชจ๋“  ๊ฒฝ๊ธฐ ์ ์ˆ˜๋ฅผ ๊ฐœ์ธ ํฌ์ธํŠธ๋กœ ํ™˜์‚ฐํ•ด ์‹œ์ฆŒ๋งˆ๋‹ค ์‹œ์ƒํ•˜๋Š” ๊ฒƒ์ด ๋ชจ์ž„์˜ ํ•ต์‹ฌ ๋ฌธํ™”์˜€์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ๊ธฐ๋ก๊ณผ ์ •์‚ฐ์€ 2๋…„ ๋™์•ˆ ์‚ฌ๋žŒ ์†์— ์˜์กดํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ์ˆ˜์ž‘์—… ์ •์‚ฐ. ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ๋Š” โ€œ์ด๋ฆ„ ๋„ค ๊ฐœ์™€ ์ ์ˆ˜ ๋‘ ๊ฐœโ€ ํ•œ ์ค„๋กœ ๋‹จํ†ก๋ฐฉ์— ์˜ฌ๋ผ๊ฐ”๊ณ , ๋ชจ์ž„์žฅ์ด ๋งค์ฃผ ๋ช‡ ์‹œ๊ฐ„์”ฉ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณต์‚ฌํ•˜๊ณ  ์˜คํƒ€๋ฅผ ๊ณ ์ณ ๊ฐœ์ธ C# ํ”„๋กœ๊ทธ๋žจ์— ๋ถ™์—ฌ ๋„ฃ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ํ”„๋กœ๊ทธ๋žจ์€ ๋งค๋ฒˆ ์ฒซ ๊ฒฝ๊ธฐ๋ถ€ํ„ฐ ์ „๋ถ€ ๋‹ค์‹œ ๊ณ„์‚ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋Šฆ์€ ๋ฆฌ๋”๋ณด๋“œ. ์ •๋ชจ ์ค‘์—๋Š” ๋ˆ„๊ตฌ๋„ ์ž๊ธฐ ์ˆœ์œ„๋ฅผ ๋ชฐ๋ž๊ณ , ๊ฒฐ๊ณผ๋Š” ์ž์ • ๋ฌด๋ ต์—์•ผ ๊ณต์ง€๋์Šต๋‹ˆ๋‹ค.
  • ์•Œ๋ฆผ ๊ณตํ•ด. ๊ฒฝ๊ธฐํ•˜์ง€ ์•Š์€ ํšŒ์›๊นŒ์ง€ ๊ฒฝ๊ธฐ๋งˆ๋‹ค ์•Œ๋ฆผ์„ ๋ฐ›์•„, ๊ฒฐ๊ตญ ๋‹จํ†ก๋ฐฉ์„ ์Œ์†Œ๊ฑฐํ•˜๊ณ  ์ค‘์š”ํ•œ ๊ณต์ง€๋ฅผ ๋†“์ณค์Šต๋‹ˆ๋‹ค.
  • ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋ฐ์ดํ„ฐ. โ€œ์˜ค๋Š˜ ๋ช‡ ๊ฒŒ์ž„ ์ณค์ง€?โ€, โ€œ์„ ๋‹ฌ ์ „๋ณด๋‹ค ๋‚˜์•„์กŒ๋‚˜?โ€์— ๋‹ตํ•˜๋ ค๋ฉด ์ฑ„ํŒ…์„ ๊ฑฐ์Šฌ๋Ÿฌ ์˜ฌ๋ผ๊ฐ€์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ

๋ชจ์ž„์žฅ์—๊ฒŒ โ€œ๊ทœ์น™์€ ์ •ํ•ด ์ฃผ์„ธ์š”. ๊ธฐ๋กํ•˜๊ณ  ๊ณ„์‚ฐํ•˜๊ณ  ๋ณด์—ฌ์ฃผ๋Š” ์ผ์€ ์•ฑ์œผ๋กœ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹คโ€ ๋ผ๊ณ  ์ œ์•ˆํ–ˆ๊ณ , ํ•œ ๋‹ฌ์งœ๋ฆฌ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ๋กœ ์‹œ์ž‘ํ•œ ์ผ์ด 18๊ฐœ์›”์˜ ๊ฐœ๋ฐœ๋กœ ์ด์–ด์กŒ์Šต๋‹ˆ๋‹ค.

  • ๊ฒฝ๊ธฐ ๊ธฐ๋ก๊ณผ ์•Œ๋ฆผ์˜ ๋ถ„๋ฆฌ. ํšŒ์›์ด ์•ฑ์—์„œ ๊ฒฝ๊ธฐ๋ฅผ ๋ฐ”๋กœ ๊ธฐ๋กํ•˜๋ฉด ์ ์ˆ˜๊ฐ€ ์ž๋™ ๊ณ„์‚ฐ๋˜๊ณ , ์•Œ๋ฆผ์€ ๊ฒฝ๊ธฐ์— ์ฐธ์—ฌํ•œ ์‚ฌ๋žŒ์—๊ฒŒ๋งŒ ๊ฐ‘๋‹ˆ๋‹ค. ๊ณต์ง€ยท์‚ฌ์ง„ยท๊ฑด์˜๋Š” ์•ฑ์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๋กœ ์˜ฎ๊ฒผ์Šต๋‹ˆ๋‹ค.
  • ํฌ์ธํŠธ ๊ณ„์‚ฐ ์—”์ง„ ๋ถ„๋ฆฌ. ์ ์ˆ˜ ๊ทœ์น™์€ ๊ฑฐ์˜ ๋งค๋‹ฌ ๋ฐ”๋€Œ๋Š”, ์‹œ์Šคํ…œ์—์„œ ๊ฐ€์žฅ ๋ถˆ์•ˆ์ •ํ•œ ๋ถ€๋ถ„์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ Spring Boot์—์„œ ๋–ผ์–ด๋‚ด Python/FastAPI ์„œ๋น„์Šค๋กœ ๋งŒ๋“ค๊ณ  ๋ฐฐํฌ ๋‹จ์œ„๋ฅผ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅ์†Œ ์†Œ์œ ๊ถŒ๋„ ๋‚˜๋ˆด์Šต๋‹ˆ๋‹ค โ€” ์›๋ณธ ๊ธฐ๋ก์€ PostgreSQL, ์žฌ์—ฐ ์บ์‹œ๋Š” DuckDB, ๋ฆฌ๋”๋ณด๋“œ๋Š” Redis. Java ์ชฝ์€ Redis ๊ณ„์•ฝ๋งŒ ์ง€ํ‚ค๋ฉด ๊ทœ์น™์ด ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ๋“  ์˜ํ–ฅ์ด ์—†์Šต๋‹ˆ๋‹ค.
  • ํ•„์š”ํ•œ ๋งŒํผ๋งŒ ์žฌ์—ฐ. ๋ฆฌ๊ทธํฌ์ธํŠธ๋Š” ์ด์ „ ๊ฒฝ๊ธฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ค์Œ ๊ณ„์‚ฐ์˜ ์ž…๋ ฅ์ด ๋˜๋Š” ์ˆœ์ฐจ ์ฒด์ธ์ด๋ผ, ์ง€๋‚œ ๊ฒฝ๊ธฐ ํ•˜๋‚˜๋ฅผ ๊ณ ์น˜๋ฉด ๊ทธ ๋’ค ์ „๋ถ€๋ฅผ ๋‹ค์‹œ ๊ตด๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งค๋ฒˆ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ณ„์‚ฐํ•˜๋Š” ๋Œ€์‹  ์ง์ „ ์Šค๋ƒ…์ƒท๋ถ€ํ„ฐ ์žฌ์—ฐํ•˜๊ณ , ์žฌ์‹œ์ž‘ ์‹œ ์›๋ณธ๊ณผ ์บ์‹œ๋ฅผ ๋Œ€์กฐํ•ด ์Šค์Šค๋กœ ๋งž์ถ”๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทœ์น™ ๊ฐœํŽธ์„ ๊ณ„๊ธฐ๋กœ ๊ตฌ์กฐ ์žฌ์„ค๊ณ„. ์„ธ ๊ฐœ์˜ ๋ฆฌ๊ทธํฌ์ธํŠธ๊ฐ€ ํšŒ์›๋‹น MMR ํ•˜๋‚˜๋กœ, ๋‹ค์„ฏ ๋‹จ๊ณ„ ๊ณต์‹์ด ์„ธ ๋ฌธ์žฅ์งœ๋ฆฌ ์ œ๋กœ์„ฌ ์ •์‚ฐ์œผ๋กœ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ MMR์„ ์ปฌ๋Ÿผ์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๋ธํƒ€๋ฅผ append-only ์›์žฅ์— ์Œ“์•„ ํ•ฉ์œผ๋กœ ๊ตฌํ•˜๋„๋ก ๋ฐ”๊ฟจ์Šต๋‹ˆ๋‹ค. ์ถœ์„ ๋ณด์ •์ด ๋‹ค์Œ ์ •๋ชจ์˜ ์‹œ์ž‘ MMR์ด ๋˜๋ฉด์„œ ์žฌ์—ฐ ๋‹จ์œ„๋„ ๊ฒฝ๊ธฐ ์ˆœ์—์„œ ํ•˜๋ฃจ ์ˆœ์œผ๋กœ ์˜ฎ๊ฒผ๊ณ , ์žฌ๊ณ„์‚ฐ ์š”์ฒญ์€ 1.5์ดˆ ์ฐฝ์œผ๋กœ ๋ชจ์•„ ๊ฐ€์žฅ ์ด๋ฅธ ๋‚ ์งœ ํ•˜๋‚˜๋กœ ํ•ฉ์นฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

  • ์ •๋ชจ ์ค‘ ์‹ค์‹œ๊ฐ„ ๋ฆฌ๋”๋ณด๋“œ, ์ฐธ๊ฐ€์ž ๋Œ€์ƒ ์•Œ๋ฆผ, ํšŒ์›๋ณ„ ๊ฒฝ๊ธฐยท์Šน๋ฅ ยทํฌ์ธํŠธ ์ด๋ ฅ์„ ์ œ๊ณตํ•ด ๋ชจ์ž„์žฅ์˜ ๋งค์ฃผ ์ˆ˜์ž‘์—… ์ •์‚ฐ์„ ์—†์•ด์Šต๋‹ˆ๋‹ค.
  • ์•ฝ 1,000๊ฐœ์˜ ์ปค๋ฐ‹, 3๊ฐœ ์–ธ์–ด๋กœ ๋งŒ๋“  4๊ฐœ ์„œ๋น„์Šค๋ฅผ App StoreยทGoogle Play๋กœ ์ถœ์‹œํ•ด ํ”„๋กœ๋•์…˜์—์„œ ์šด์˜ ์ค‘์ž…๋‹ˆ๋‹ค.
  • ๋งค์ผ ์ƒˆ๋ฒฝ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ „์ฒด ์žฌ์—ฐ์„ ๋Œ๋ ค ๋žญํ‚น๊ณผ ๋Œ€์กฐํ•˜๋Š” ๊ฒ€์ฆ์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด DuckDB Postgres ์Šค์บ๋„ˆ์˜ N+1์„ ๊ฑท์–ด๋‚ด 1๋งŒ 2์ฒœ์—ฌ ๊ฒฝ๊ธฐ ์ „์ฒด ์žฌ์—ฐ์„ ์•ฝ 20๋ถ„์—์„œ 80์ดˆ ๋ฏธ๋งŒ์œผ๋กœ ์ค„์˜€์Šต๋‹ˆ๋‹ค.
  • ์›์žฅ ๊ตฌ์กฐ ๋•๋ถ„์— โ€œ๊ฒฝ๊ณ„์ผ๋ถ€ํ„ฐ ๋ถ€๋ถ„ ์žฌ์—ฐํ•œ ๊ฒฐ๊ณผ == ์ฒ˜์Œ๋ถ€ํ„ฐ ์ „์ฒด ์žฌ์—ฐํ•œ ๊ฒฐ๊ณผโ€๋ฅผ ๋ฌด์ž‘์œ„ ๊ฒฝ๊ณ„์ผ 5๊ฐœ์— ๋Œ€ํ•ด ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ๊ฒ€์ฆํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.
  • ๊ฒฝ๊ธฐ๋ณ„ ์ •์‚ฐ ๋‚ด์—ญ API๋Š” ์ €์žฅ๊ฐ’์ด ์•„๋‹ˆ๋ผ ์›์žฅ์—์„œ ๊ทธ ์‹œ์  ์ƒํƒœ๋ฅผ ๋ณต์›ํ•ด ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๊ณ , ์›์žฅ๊ณผ์˜ ์ผ์น˜ ์—ฌ๋ถ€๋ฅผ ํ•จ๊ป˜ ๋Œ๋ ค์ค๋‹ˆ๋‹ค. ์ •๋ชจ ๋‹จ์œ„ ๊ฒŒ์ž„ํฌ์ธํŠธ ์‚ฌ์ „ ์ง‘๊ณ„๋กœ ๋ฆฌ๋”๋ณด๋“œ ์ฝ๊ธฐ๋ฅผ 31โ€“33๋ฐฐ ๋น ๋ฅด๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœํŽธ์€ Python ์„œ๋น„์Šค ์•ˆ์—์„œ ๋๋‚ฌ๊ณ , Java ๋ฐฑ์—”๋“œ์—์„œ ๋ฐ”๋€ ๊ฒƒ์€ ํ ์‹œ๊ทธ๋‹ˆ์ฒ˜์™€ ์บ์‹œ ํ‚ค ๋ช‡ ๊ฐœ๋ฟ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์—”์ง„์„ ๋ถ„๋ฆฌํ•œ ๊ฒฐ์ •์ด ์—ฌ๊ธฐ์„œ ๊ฐ’์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐ์šด ๊ฒƒ

  • ๊ฐ€์žฅ ์ž์ฃผ ๋ฐ”๋€Œ๋Š” ๋ถ€๋ถ„์„ ๋…๋ฆฝ๋œ ๋ฐฐํฌ ๋‹จ์œ„๋กœ. ์„œ๋น„์Šค ๋ถ„๋ฆฌ์˜ ์ด์œ ๋Š” ๊ธฐ์ˆ  ์Šคํƒ์ด ์•„๋‹ˆ๋ผ ๋ณ€๊ฒฝ ๋นˆ๋„์˜€๊ณ , ๊ทธ ํŒ๋‹จ์€ ๊ทœ์น™ ๊ฐœํŽธ ๋•Œ ๊ทธ๋Œ€๋กœ ํšŒ์ˆ˜๋์Šต๋‹ˆ๋‹ค.
  • ํŒŒ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์€ ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฎ์–ด์“ฐ๋Š” ์ง€์ ์ด ์—†์œผ๋ฉด ๋‚ก์•„์งˆ ๊ฐ’๋„ ์—†๊ณ , ์žฌ์—ฐ์ด ์ˆœ์ˆ˜ ํ•จ์ˆ˜๊ฐ€ ๋˜์–ด ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํŒŒ์ƒ ์ €์žฅ์†Œ๋Š” ์–ธ์ œ ์ง€์›Œ๋„ ๋˜๋Š” ์บ์‹œ๋กœ ๋‘ก๋‹ˆ๋‹ค.
  • ๊ทœ์น™์€ ์ฝ”ํŠธ์—์„œ ๋ง๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์„ฏ ๋‹จ๊ณ„ ๊ณต์‹์€ ์ •ํ™•ํ–ˆ์ง€๋งŒ โ€œ์™œ 5์ ๋ฐ–์— ์•ˆ ์˜ฌ๋ž๋ƒโ€์— ๋‹ตํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ทœ์น™์ด ์‹œ์Šคํ…œ์˜ ์š”๊ตฌ์‚ฌํ•ญ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์‹ค์‚ฌ์šฉ์ž์—๊ฒŒ ๋จผ์ € ๋ฐฐํฌํ•˜๋ฉด ๋ถ€์ฑ„๋„ ํ•จ๊ป˜ ์˜ต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๋Š” ๊ณ ๋ฅด์ง€ ์•Š๊ณ  CI/CD์™€ API ๋ฌธ์„œ๋Š” ๋‚จ์€ ๊ณผ์ œ์ž…๋‹ˆ๋‹ค. ๋Œ€์‹  ์˜ค๋ฅ˜๋ฅผ ๋ฐ”๋กœ ์•Œ๋ ค ์ฃผ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ์—ˆ๊ณ , ๊ทธ๊ฒŒ 18๊ฐœ์›”์„ ์ด์–ด ๊ฐ„ ์ด์œ ์˜€์Šต๋‹ˆ๋‹ค.

๋” ์ฝ๊ธฐ

์„ค๊ณ„ ๊ฒฐ์ •์˜ ๊ทผ๊ฑฐ์™€ ๊ตฌํ˜„ ๊ณผ์ •์€ ๊ฐœ๋ฐœ ์ผ์ง€์— ์ฑ•ํ„ฐ๋ณ„๋กœ ๊ธฐ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.

Flutter ยท Spring Boot ยท Java ยท Python ยท FastAPI ยท PostgreSQL ยท DuckDB ยท Redis