Skip to content
MCP ThesaurusMCP Thesaurus

BoxTier Basketball Receipt

CommunityIncomplete39/100Claim

streamable-httpupdated 17d ago

์นœ๊ตฌ๋ผ๋ฆฌ ํ•˜๋Š” ๋†๊ตฌ ๊ฒฝ๊ธฐ๋ฅผ ์˜ค๋Š˜์˜ ํŒ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ๊ฒฝ๊ธฐ ํ›„ ์–‘ํŒ€ ์Šน์ธ์œผ๋กœ ์ „์ ๊ณผ ํ‹ฐ์–ด๋ฅผ ๋‚จ๊ธฐ๋Š” React + Vite MVP์ž…๋‹ˆ๋‹ค.

SourceWebsite

What can you do with BoxTier Basketball Receipt?

RankBall

์นœ๊ตฌ๋ผ๋ฆฌ ํ•˜๋Š” ๋†๊ตฌ ๊ฒฝ๊ธฐ๋ฅผ ์˜ค๋Š˜์˜ ํŒ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ , ๊ฒฝ๊ธฐ ํ›„ ์–‘ํŒ€ ์Šน์ธ์œผ๋กœ ์ „์ ๊ณผ ํ‹ฐ์–ด๋ฅผ ๋‚จ๊ธฐ๋Š” React + Vite MVP์ž…๋‹ˆ๋‹ค.

์‹คํ–‰

npm install
npm run dev

.env๊ฐ€ ์—†์–ด๋„ localStorage demo mode๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

Supabase

Vite์—์„œ๋„ Vercel/Next ์Šคํƒ€์ผ์˜ NEXT_PUBLIC_* ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ฝ๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=...

Supabase ์˜์† ์ €์žฅ์€ supabase/migrations๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. Supabase ํ™˜๊ฒฝ์ด ์„ค์ •๋œ ๋’ค ์›๊ฒฉ ๋กœ๋“œ๊ฐ€ ์‹คํŒจํ•˜๋ฉด localStorage demo state๋กœ ํ›„ํ‡ดํ•˜์ง€ ์•Š๊ณ  ์›๊ฒฉ shell/error ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

Supabase CLI migration

Production DB migration์€ ๊ฐ€๋Šฅํ•˜๋ฉด Supabase CLI๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

supabase --version
$env:SUPABASE_ACCESS_TOKEN="..."
$env:SUPABASE_DB_PASSWORD="..."
supabase link --project-ref olzxextphxpniwiiwwda --password $env:SUPABASE_DB_PASSWORD
supabase db push --linked --dry-run
supabase db push --linked

DATABASE_URL์ด ์žˆ์œผ๋ฉด link ์—†์ด๋„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

supabase db push --db-url "$env:DATABASE_URL" --dry-run
supabase db push --db-url "$env:DATABASE_URL"

Production ์ ์šฉ ๋’ค schema health๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

Invoke-RestMethod -Method Post -Uri "https://boxtier.kr/api/system/schema-health" -Headers @{ Authorization = "Bearer $env:CRON_SECRET" }

๋ฐฐํฌ ์ „ ๊ฒ€์ฆ์€ ํ•œ ๋ช…๋ น์œผ๋กœ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

npm run verify:release -- --confirm-production=olzxextphxpniwiiwwda

verify:release๋Š” production build ํ›„ ์›๊ฒฉ Supabase/Auth ๊ธฐ๋ฐ˜ ์ „์ฒด backend simulation๊ณผ schema health๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. production ref์™€ ์ •ํ™•ํžˆ ๊ฐ™์€ --confirm-production=<project-ref> CLI flag๊ฐ€ ์—†์œผ๋ฉด API/Auth ํ˜ธ์ถœ ์ „์— ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค. SUPABASE_SERVICE_ROLE_KEY, ํ…Œ์ŠคํŠธ Auth ํ™˜๊ฒฝ๋ณ€์ˆ˜, CRON_SECRET์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ข…๋ฃŒ ์ฝ”๋“œ๊ฐ€ 0์ด ์•„๋‹ˆ๋ฉด ๋ฐฐํฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

simulation์€ ์‹คํ–‰ ์ „์— environment, ์ง์ ‘ Supabase project ref, ์›๊ฒฉ API host/ref๋ฅผ stderr์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. process๋‹น ์ „์ฒด flow ๋ฐ˜๋ณต ์ƒํ•œ์€ 1ํšŒ์ด๊ณ  ์ž๋™ ์žฌ์‹œ๋„๋Š” cleanup ์‹คํŒจ ์‹œ ์ตœ๋Œ€ 1ํšŒ์ž…๋‹ˆ๋‹ค. ๋ณ„๋„ process๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋Š” ์™ธ๋ถ€ runner๋„ ํ˜ธ์ถœ ํšŸ์ˆ˜๋ฅผ 1ํšŒ๋กœ ์ œํ•œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. --safety-check-only๋Š” target guard๋งŒ ๊ฒ€์ฆํ•˜๊ณ  DB/API๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ „์šฉ Supabase๋Š” test URL, publishable key, service-role key๋ฅผ ํ•จ๊ป˜ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์›๊ฒฉ test API๋ฅผ ์“ฐ๋ฉด ์‹ค์ œ ๋ฐฐํฌ ๋Œ€์ƒ๊ณผ ๊ฐ™์€ ref๋ฅผ --remote-project-ref=<test-ref>๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ง์ ‘ ref์™€ ์›๊ฒฉ ref๊ฐ€ ๋‹ค๋ฅด๋ฉด ์‹คํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์›๊ฒฉ DB์—๋Š” supabase db reset --linked, DROP TABLE, TRUNCATE, ๋Œ€๋Ÿ‰ DELETE๋ฅผ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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

์ด๋ฆ„ ์œ„์น˜ ์šฉ๋„
VITE_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_URL ๋ธŒ๋ผ์šฐ์ €/์„œ๋ฒ„ Supabase project URL
VITE_SUPABASE_PUBLISHABLE_KEY / NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY / VITE_SUPABASE_ANON_KEY ๋ธŒ๋ผ์šฐ์ € Supabase anon/publishable key
SUPABASE_SERVICE_ROLE_KEY ์„œ๋ฒ„/์Šคํฌ๋ฆฝํŠธ ์ „์šฉ server action, seed, simulation
VITE_ENABLE_SERVER_ACTIONS ๋ธŒ๋ผ์šฐ์ € server action ํ™œ์„ฑํ™”
VITE_DEMO_LOGIN ๋ธŒ๋ผ์šฐ์ € localhost ํ…Œ์ŠคํŠธ ๋กœ๊ทธ์ธ UI ํ—ˆ์šฉ
RANKBALL_SEED_REAL_TEST_AUTH / RANKBALL_SEED_AUTH_ONLY ์Šคํฌ๋ฆฝํŠธ ํ…Œ์ŠคํŠธ ๊ณ„์ •์„ Supabase Auth user๋กœ ๋งŒ๋“ค๊ณ  ๊ธฐ์กด profile์— ์—ฐ๊ฒฐ
RANKBALL_TEST_PASSWORD / VITE_TEST_AUTH_PASSWORD ์Šคํฌ๋ฆฝํŠธ/๋ธŒ๋ผ์šฐ์ € ํ…Œ์ŠคํŠธ ๊ณ„์ • password Auth์šฉ ๋น„๋ฐ€๋ฒˆํ˜ธ
RANKBALL_TEST_AUTH_EMAIL_DOMAIN / VITE_TEST_AUTH_EMAIL_DOMAIN ์Šคํฌ๋ฆฝํŠธ/๋ธŒ๋ผ์šฐ์ € ํ…Œ์ŠคํŠธ ๊ณ„์ • email domain. ๊ธฐ๋ณธ๊ฐ’ rankball.test
VITE_ASSET_BASE_URL / VITE_PUBLIC_ASSET_BASE_URL ๋ธŒ๋ผ์šฐ์ € ์›๊ฒฉ asset base URL
VITE_NAVER_MAP_CLIENT_ID / VITE_NAVER_MAP_NCP_KEY_ID ๋ธŒ๋ผ์šฐ์ €/์„œ๋ฒ„ fallback Naver map/geocode client id
NAVER_MAP_CLIENT_SECRET / NAVER_MAP_NCP_KEY / NAVER_MAP_NCP_CLIENT_SECRET ์„œ๋ฒ„ ์ „์šฉ Naver geocode fallback secret
DISCORD_CLIENT_ID / DISCORD_CLIENT_SECRET / DISCORD_REDIRECT_URI ์„œ๋ฒ„ ์ „์šฉ Discord OAuth
DISCORD_BOT_TOKEN / DISCORD_GUILD_ID / DISCORD_GUILD_IDS ์„œ๋ฒ„ ์ „์šฉ Discord DM worker
DISCORD_PUBLIC_KEY ์„œ๋ฒ„ ์ „์šฉ Discord interaction signature ๊ฒ€์ฆ
DISCORD_CHAT_BRIDGE_SECRET / DISCORD_CHAT_BRIDGE_URL bridge worker Discord ๋ฐฉ ์ฑ„ํŒ…์„ ์›น API๋กœ ์ „๋‹ฌ
DISCORD_CHAT_BRIDGE_REQUEST_TIMEOUT_MS / DISCORD_CHAT_BRIDGE_MAX_DELIVERY_ATTEMPTS bridge worker ์ „๋‹ฌ timeout๊ณผ ์žฌ์‹œ๋„ ํšŸ์ˆ˜. ๊ธฐ๋ณธ 10000, 4
CRON_SECRET ์„œ๋ฒ„/์Šคํฌ๋ฆฝํŠธ ์ „์šฉ worker, maintenance, schema-health
SUPABASE_ACCESS_TOKEN CLI ์ „์šฉ Supabase Management API ์ธ์ฆ
SUPABASE_DB_PASSWORD CLI ์ „์šฉ supabase link, supabase db push --linked ์›๊ฒฉ DB ๋น„๋ฐ€๋ฒˆํ˜ธ
SUPABASE_PROJECT_ID CLI/CI ์ „์šฉ Supabase project ref. ํ˜„์žฌ production ref: olzxextphxpniwiiwwda
DATABASE_URL CLI/์„œ๋ฒ„ ์ „์šฉ supabase db push --db-url ๋˜๋Š” ์ง์ ‘ Postgres ์ ‘์†
RANKBALL_SIM_BASE_URL / RANKBALL_SIM_SECRET / RANKBALL_SIM_TIMEOUT_MS / RANKBALL_SIM_CLEANUP_TIMEOUT_MS ์Šคํฌ๋ฆฝํŠธ backend simulation
RANKBALL_SIM_REMOTE_PROJECT_REF ์Šคํฌ๋ฆฝํŠธ ์›๊ฒฉ test API๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” Supabase project ref. --remote-project-ref๊ฐ€ ์šฐ์„ 
RANKBALL_SIM_REPEAT / RANKBALL_SIM_MAX_RETRIES ์Šคํฌ๋ฆฝํŠธ ์ „์ฒด flow ๋ฐ˜๋ณต ์ƒํ•œ 1, cleanup ์žฌ์‹œ๋„ ์ƒํ•œ 1

Discord ๋ฐฉ ์ฑ„ํŒ… bridge

์ƒ์‹œ ์‹คํ–‰ ํ™˜๊ฒฝ์—์„œ ์•„๋ž˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. Gateway worker๋Š” heartbeat ACK ๋ˆ„๋ฝ ์‹œ ์žฌ์—ฐ๊ฒฐํ•˜๊ณ , ๊ฐ€๋Šฅํ•œ ์„ธ์…˜์€ resumeํ•˜๋ฉฐ, ์›น API์˜ timeoutยท429ยท5xx๋ฅผ ์ œํ•œ ํšŸ์ˆ˜๋งŒํผ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.

npm run discord:room-chat-bridge

์šด์˜์—์„œ๋Š” DISCORD_CHAT_BRIDGE_SECRET์„ ๋ณ„๋„๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. CRON_SECRET fallback์€ ๊ธฐ์กด ๋ฐฐํฌ ํ˜ธํ™˜์šฉ์ž…๋‹ˆ๋‹ค.

Vercel

Framework preset์€ Vite, build command๋Š” npm run build, output directory๋Š” dist์ž…๋‹ˆ๋‹ค.