Skip to content

seoyoonyi/dopaminetto

Repository files navigation

Dopaminetto

๐Ÿ“„ ๊ฐœ์š”

๊ฒŒ๋”ํƒ€์šด์ด ์ข…๋ฃŒ๋œ๋‹ค๋Š” ๋ง์— ๊ดœํžˆ ์•„์‰ฌ์šด ๋งˆ์Œ์ด ๋“ค๋”๋ผ๊ณ ์š”. ๊ทธ๋ž˜์„œ โ€œ์ด์™• ์ด๋ ‡๊ฒŒ ๋œ ๊ฑฐ, ์šฐ๋ฆฌ(๊ธ€๋˜)์˜ ์ž‘์€ ์Œ์„ฑยทํ…์ŠคํŠธ ์ฑ„ํŒ… MVP๋ผ๋„ ๋งŒ๋“ค์–ด๋ณผ๊นŒ?โ€ ์‹ถ์–ด์„œ ๊ฐ€๋ณ๊ฒŒ ์‹œ์ž‘ํ•ด๋ณธ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค!


๐Ÿš€ ์‹œ์ž‘ํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ๋ฅผ ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ํ•˜๋ ค๋ฉด ์•„๋ž˜ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

์˜์กด์„ฑ ์„ค์น˜

npm install

ํ•„์ˆ˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜

ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .env.local.ex ํŒŒ์ผ์„ .env.local๋กœ ๋ณต์‚ฌํ•˜๊ณ  ๋‹ค์Œ ๊ฐ’๋“ค์„ ์„ค์ •ํ•˜์„ธ์š”:

# Supabase Configuration (ํ•„์ˆ˜)
NEXT_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

# Cloudflare Configuration (์Œ์„ฑ ์ฑ„ํŒ…์šฉ)
CLOUDFLARE_API_TOKEN=your-cloudflare-api-token
CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_CALLS_APP_ID=your-calls-app-id

# Development Configuration
NODE_ENV=development

๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰

npm run dev

์ด์ œ ๋ธŒ๋ผ์šฐ์ €์—์„œ http://localhost:3000์œผ๋กœ ์ ‘์†ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ

WebRTC ์†”๋ฃจ์…˜ ์„ ํƒ ์ด์œ 

  • P2P ๋ฐฉ์‹ ๋ถˆ๊ฐ€: 40~50๋ช… ๋™์‹œ ์ ‘์† ์‹œ ๊ฐ์ž 49๊ฐœ ์—ฐ๊ฒฐ ํ•„์š” (์ด 1,225๊ฐœ ์—ฐ๊ฒฐ)
  • SFU ํ•„์ˆ˜: ์„œ๋ฒ„ ์ค‘๊ณ„ ๋ฐฉ์‹์œผ๋กœ ํ™•์žฅ์„ฑ ํ™•๋ณด
  • Cloudflare Realtime ์„ ํƒ: ๋น„์šฉ๊ณผ ํŽธ์˜์„ฑ ๊ณ ๋ ค

์ต๋ช… ์ ‘์† ๊ตฌํ˜„

  • ํšŒ์›๊ฐ€์ž… ์—†์ด UUID ๊ธฐ๋ฐ˜ ์‚ฌ์šฉ์ž ์‹๋ณ„
  • ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ํ†ตํ•œ ์„ธ์…˜ ์œ ์ง€
  • ์ž„์‹œ ๋‹‰๋„ค์ž„ ์œ ์ €๊ฐ€ ์ƒ์„ฑ
  • Supabase user.id๋ฅผ ์šฐ์„  ์‚ฌ์šฉํ•˜๋˜, ์•„์ง ๊ฐ’์ด ์—†์„ ๋•Œ๋Š” ํด๋ผ์ด์–ธํŠธ(user-storage ์Šคํ† ์–ด)๊ฐ€ uuid๋กœ ์ž„์‹œ userId๋ฅผ ์ƒ์„ฑํ•ด ๋™์ผ ๋ธŒ๋ผ์šฐ์ €/ํƒญ์—์„œ ์ผ๊ด€๋œ ์‹๋ณ„์ž๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

Supabase ์ต๋ช… ์ธ์ฆ ํ™œ์„ฑํ™”

  • ์ด ํ”„๋กœ์ ํŠธ๋Š” ํšŒ์›๊ฐ€์ž… ์—†์ด ์ต๋ช…์œผ๋กœ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ”„๋กœ์ ํŠธ์—์„œ ์ต๋ช… ์ธ์ฆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.
    1. Supabase ๋Œ€์‹œ๋ณด๋“œ์— ๋กœ๊ทธ์ธํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    2. ์™ผ์ชฝ ์‚ฌ์ด๋“œ๋ฐ”์—์„œ Authentication ๋ฉ”๋‰ด๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
    3. Sign In / Providers ์„น์…˜์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    4. Anonymous ์˜ต์…˜์„ ํ™œ์„ฑํ™”(enable)ํ•˜๊ณ  ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

Supabase Anonymous ํ™œ์„ฑํ™” ์Šคํฌ๋ฆฐ์ƒท

์ค‘์š”: ์ต๋ช… ์‚ฌ์šฉ์ž๋Š” authenticated ์—ญํ• ์„ ๋ถ€์—ฌ๋ฐ›์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘๊ทผ ์ œ์–ด๋ฅผ ์œ„ํ•ด RLS(Row-Level Security) ์ •์ฑ…์„ ๋ฐ˜๋“œ์‹œ ๊ฒ€ํ† ํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ is_anonymous ํ•„๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ์ต๋ช… ์‚ฌ์šฉ์ž์™€ ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ์ •์ฑ…์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ—๏ธ ๊ธฐ์ˆ  ์Šคํƒ

Frontend

  • Framework: Next.js 15.5.3 with Turbopack
  • Language: TypeScript
  • Styling: Tailwind CSS v4
  • UI Components: shadcn/ui
  • Icons: Lucide React

Backend & Database

  • Database: Supabase (PostgreSQL)
  • Real-time: Supabase Realtime (์ฑ„ํŒ…, ์‹œ๊ทธ๋„๋ง)
  • Authentication: ์ต๋ช… ์ ‘์† (ํšŒ์›๊ฐ€์ž… ๋ถˆํ•„์š”)

WebRTC & Voice Chat

  • SFU Solution: Cloudflare Realtime + SFU
  • User Identification: UUID ๊ธฐ๋ฐ˜ ์ต๋ช… ์‚ฌ์šฉ์ž

Game Engine

  • 2D Game Engine: Phaser 3
  • Canvas Rendering: WebGL/Canvas API

State Management

  • Global State: Zustand
  • Server State: TanStack React Query

๐Ÿงฑ ์„ค๊ณ„ ์›์น™

  • ๋ชจ๋“  ๊ตฌํ˜„์€ SOLID ์›์น™์„ ๋”ฐ๋ฅด๋ฉฐ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ฆฐ ์ฝ”๋“œ ๊ทœ์น™์„ ์ง€์ผœ ๋ช…ํ™•ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ UI๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ํ…Œ์ŠคํŠธ์™€ ํ™•์žฅ์„ฑ์„ ํ™•๋ณดํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ FSD ํด๋” ๊ตฌ์กฐ

  • ๊ธฐ๋Šฅ๋ณ„๋กœ FSD ๋ ˆ์ด์–ด(entities, features, widgets, shared)๋กœ ๋‚˜๋ˆ„์–ด ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • ์„ค๊ณ„ ์›์น™์— ๋”ฐ๋ผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ UI๋ฅผ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ฐฐ๋Ÿด(index.ts)์„ ํ™œ์šฉํ•ด ๊ณต์šฉ ์ง„์ž…์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ“‚ ํ”„๋กœ์ ํŠธ ํด๋” ๊ตฌ์กฐ ๋ณด๊ธฐ
๐Ÿ“ฆsrc
 โ”ฃ ๐Ÿ“‚app              # Next.js App Router (ํŽ˜์ด์ง€ ๋ผ์šฐํŒ… ๋ฐ ์ง„์ž…์ )
 โ”ƒ โ”ฃ ๐Ÿ“‚api            # ์„œ๋ฒ„ ์‚ฌ์ด๋“œ API ๋ผ์šฐํŠธ (์˜ˆ์ •)
 โ”ƒ โ”ฃ ๐Ÿ“‚providers      # ์ „์—ญ ์ปจํ…์ŠคํŠธ ํ”„๋กœ๋ฐ”์ด๋”
 โ”ƒ โ”— ๐Ÿ“‚town           # ๋ฉ”์ธ ๊ฒŒ์ž„ ํƒ€์šด ํŽ˜์ด์ง€ ๊ฒฝ๋กœ
 โ”ฃ ๐Ÿ“‚entities         # ๋น„์ฆˆ๋‹ˆ์Šค ์—”ํ‹ฐํ‹ฐ (์˜ˆ์ •)
 โ”ƒ โ”ฃ ๐Ÿ“‚player         # ํ”Œ๋ ˆ์ด์–ด ๋ชจ๋ธ
 โ”ƒ โ”— ๐Ÿ“‚room           # ๋ฐฉ(Room) ๋ชจ๋ธ
 โ”ฃ ๐Ÿ“‚features         # ๊ธฐ๋Šฅ ๋‹จ์œ„ (๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง)
 โ”ƒ โ”ฃ ๐Ÿ“‚auth           # ์ธ์ฆ ๊ด€๋ จ
 โ”ƒ โ”ฃ ๐Ÿ“‚chat           # ์ฑ„ํŒ… ๊ธฐ๋Šฅ
 โ”ƒ โ”ฃ ๐Ÿ“‚movement       # ์ด๋™ ๋กœ์ง (์˜ˆ์ •)
 โ”ƒ โ”ฃ ๐Ÿ“‚panelToggle    # ํŒจ๋„ ํ† ๊ธ€
 โ”ƒ โ”ฃ ๐Ÿ“‚presence       # ์ ‘์† ์ƒํƒœ
 โ”ƒ โ”ฃ ๐Ÿ“‚room-switch    # ๋ฐฉ ์ด๋™ (์˜ˆ์ •)
 โ”ƒ โ”— ๐Ÿ“‚voice          # ์Œ์„ฑ ์ฑ„ํŒ… (์˜ˆ์ •)
 โ”ฃ ๐Ÿ“‚widgets          # ๋…๋ฆฝ์ ์ธ UI ๋ธ”๋ก
 โ”ƒ โ”ฃ ๐Ÿ“‚chatPanel      # ์ฑ„ํŒ… ํŒจ๋„
 โ”ƒ โ”ฃ ๐Ÿ“‚gameCanvas     # ๊ฒŒ์ž„ ์บ”๋ฒ„์Šค (์˜ˆ์ •)
 โ”ƒ โ”ฃ ๐Ÿ“‚roomLayout     # ๋ฐฉ ๋ ˆ์ด์•„์›ƒ (์˜ˆ์ •)
 โ”ƒ โ”ฃ ๐Ÿ“‚townToolbar    # ํ•˜๋‹จ ํˆด๋ฐ”
 โ”ƒ โ”— ๐Ÿ“‚usersPanel     # ์ ‘์†์ž ํŒจ๋„
 โ”— ๐Ÿ“‚shared           # ๊ณต์šฉ ๋ชจ๋“ˆ
   โ”ฃ ๐Ÿ“‚config         # ํ™˜๊ฒฝ ์„ค์ •
   โ”ฃ ๐Ÿ“‚hooks          # ๊ณต์šฉ ํ›…
   โ”ฃ ๐Ÿ“‚lib            # ์œ ํ‹ธ๋ฆฌํ‹ฐ
   โ”ฃ ๐Ÿ“‚store          # ์ „์—ญ ์ƒํƒœ
   โ”ฃ ๐Ÿ“‚types          # ๊ณต์šฉ ํƒ€์ž…
   โ”— ๐Ÿ“‚ui             # ๊ณต์šฉ UI ์ปดํฌ๋„ŒํŠธ

โš™๏ธ ๊ธฐ๋ณธ ์„ค์ • ์š”์•ฝ

  • .env.local.example์„ ๋ณต์‚ฌํ•ด .env.local์„ ์ƒ์„ฑํ•˜๊ณ  ์‹ค ์„œ๋น„์Šค ํ‚ค๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
  • Supabase ์ต๋ช… ์ ‘์†, Cloudflare Realtime, Cloudflare Calls ์„ค์ •์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • React Query DevTools, Supabase Provider, Zustand ์Šคํ† ์–ด, Phaser ์—”์ง„ ๋“ฑ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” Provider ๊ณ„์ธต์„ src/app/providers/์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ƒํƒœ ๊ด€๋ฆฌ๋Š” React Query(@tanstack/react-query)๋กœ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ, Zustand๋กœ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”ง Providers ๊ตฌ์กฐ

App Layer Providers (src/app/providers/)

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๋ฐ”์ด๋”๋“ค์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ํ”„๋กœ๋ฐ”์ด๋”๋“ค

ํ”„๋กœ๋ฐ”์ด๋” ์šฉ๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠน์ง•
QueryProvider ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐ ์บ์‹ฑ @tanstack/react-query DevTools ํฌํ•จ
SupabaseProvider ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ์‹ค์‹œ๊ฐ„ ๊ธฐ๋Šฅ @supabase/ssr ์ต๋ช… ์ ‘์†, SSR ์ง€์›
AppProviders ๋ชจ๋“  ํ”„๋กœ๋ฐ”์ด๋” ํ†ตํ•ฉ - ๊ณ„์ธต์  ๊ตฌ์กฐ

๐Ÿ”ง ์ฃผ์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ญํ• 

ํŒจํ‚ค์ง€ ์šฉ๋„
@supabase/ssr Supabase SSR ์ง€์›
@supabase/supabase-js Supabase ํด๋ผ์ด์–ธํŠธ SDK
zustand ๊ฒฝ๋Ÿ‰ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
@tanstack/react-query ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐ ์บ์‹ฑ
@tanstack/react-query-devtools React Query ๊ฐœ๋ฐœ ๋„๊ตฌ (DevDependency)
phaser 2D ๊ฒŒ์ž„ ์—”์ง„ (WebGL/Canvas ๋ Œ๋”๋ง)
uuid ์ต๋ช… ์‚ฌ์šฉ์ž ๊ณ ์œ  ์‹๋ณ„์ž ์ƒ์„ฑ
tailwind-merge Tailwind CSS ํด๋ž˜์Šค ๋ณ‘ํ•ฉ ์œ ํ‹ธ๋ฆฌํ‹ฐ
@slick-carousel ๋ฐ˜์‘ํ˜• ์บ๋Ÿฌ์…€ ์ปดํฌ๋„ŒํŠธ
lucide-react ์•„์ด์ฝ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

๐Ÿ”Œ ํ™˜๊ฒฝ ๋ฐ ํ”„๋กœ๋ฐ”์ด๋” ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • .env.local.ex๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ .env.local์„ ๋งŒ๋“ค๊ณ  Supabase, Cloudflare Realtime/Calls, NODE_ENV ๊ฐ’์„ ์‹ค์ œ ํ‚ค๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • React Query(@tanstack/react-query), Supabase(@supabase/supabase-js, @supabase/ssr), Zustand, Phaser ๋“ฑ ์ฃผ์š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ src/app/providers/ ๋‚ด๋ถ€์—์„œ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
  • ํ•„์š”ํ•œ ํ”„๋กœ๋ฐ”์ด๋”๋Š” QueryProvider, SupabaseProvider, AppProviders์ด๋ฉฐ, Supabase๋Š” ์ต๋ช… ์ ‘์†ยทSSRยทRealtime์„ ์ง€์›ํ•˜๊ณ  AppProviders๊ฐ€ ์ „์ฒด ๊ณ„์ธต์„ ๊ฐ์Œ‰๋‹ˆ๋‹ค.
  • ์ƒํƒœ ๊ด€๋ฆฌ๋Š” React Query๊ฐ€ ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ, Zustand๊ฐ€ ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๋ฅผ ๋‹ด๋‹นํ•˜๋ฉฐ, ๊ด€๋ จ ์Šคํ† ์–ด๋Š” FSD ๋ ˆ์ด์–ด๋ณ„ model/store์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.
  • Cloudflare Realtime + SFU, Phaser ๊ฒŒ์ž„ ์—”์ง„ ์„ค์ •, Supabase Realtime ์„ค์ • ๋“ฑ์€ ์œ„ ๊ตฌ์„ฑ์ด ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ™˜๊ฒฝ๋ณ€์ˆ˜, provider hooks, AppProviders ๊ณ„์ธต์—์„œ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ์ฐธ๊ณ  ์ž๋ฃŒ

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors