๐Ÿ“‹ VibePlan AI ์„ค๊ณ„ ๋ช…์„ธ์„œ – ๊ทธ๋ผ๋น„ํ‹ฐ ์บ์‹œ (Gravity Cash)

# ๐Ÿ“‹ VibePlan AI ์„ค๊ณ„ ๋ช…์„ธ์„œ – ๊ทธ๋ผ๋น„ํ‹ฐ ์บ์‹œ (Gravity Cash)

**์„œ๋น„์Šค ์š”์•ฝ**: ํ™”๋ฉด์˜ ์ค‘๋ ฅ์„ ๊ฑฐ์Šฌ๋Ÿฌ ๋– ๋‹ค๋‹ˆ๋Š” ๋™์ „๊ณผ ๋ณด์ƒ์„ ํ„ฐ์น˜ํ•˜์—ฌ ํš๋“ํ•˜๋Š” ํ”ผ์ง€์ปฌ ๊ธฐ๋ฐ˜์˜ ์•ฑํ…Œํฌ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ฐœํ•œ ๋ฌผ๋ฆฌ ํšจ๊ณผ๋ฅผ ์ฆ๊ธฐ๋ฉฐ ๊ด‘๊ณ ๋ฅผ ์‹œ์ฒญํ•˜๊ณ , ๊ฐ€๋ณ๊ฒŒ ์šฉ๋ˆ์„ ๋ฒŒ ์ˆ˜ ์žˆ๋Š” ๊ทน๊ฐ•์˜ ๋ชฐ์ž…๊ฐ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

**ํ”Œ๋žซํผ**: ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

**ํƒ€๊ฒŸ ํƒ€๊ฒŸ**: ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž

*๋ณธ ๋ฌธ์„œ๋Š” VibePlan AI์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๋งˆํฌ๋‹ค์šด ์„ค๊ณ„์„œ ์„ธํŠธ์ž…๋‹ˆ๋‹ค.*

# ๐Ÿ“‘ 1์žฅ. Vibe Check (์„œ๋น„์Šค ๊ธฐํš์„œ)

## 1. ์„œ๋น„์Šค ์ •์˜ ๋ฐ ๋ชฉ์ 

**๊ทธ๋ผ๋น„ํ‹ฐ ์บ์‹œ (Gravity Cash)**๋Š” ๊ธฐ์กด์˜ ์ง€๋ฃจํ•˜๊ณ  ๋‹จ์ˆœํ•œ ํด๋ฆญํ˜• ์•ฑํ…Œํฌ(AppTech)์—์„œ ๋ฒ—์–ด๋‚˜, ์›น ๋ธŒ๋ผ์šฐ์ € ์ƒ์—์„œ ๋ฌผ๋ฆฌ ์—”์ง„(Physics Engine) ๊ธฐ๋ฐ˜์œผ๋กœ ์ž์œ ๋กญ๊ฒŒ ํ™”๋ฉด์„ ๋– ๋‹ค๋‹ˆ๋Š” ๋™์ „๊ณผ ๋ณด์ƒ์„ ํ„ฐ์น˜ํ•˜์—ฌ ํš๋“ํ•˜๋Š” **ํ”ผ์ง€์ปฌ ๊ธฐ๋ฐ˜ ๊ฒŒ์ด๋ฐ ์•ฑํ…Œํฌ ์„œ๋น„์Šค**์ž…๋‹ˆ๋‹ค.

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

## 2. ํ•ต์‹ฌ ํƒ€๊ฒŸ ์˜ค๋””์–ธ์Šค

– **์ฃผ ํƒ€๊ฒŸ**: ๋ชจ๋ฐ”์ผ/์›น ํ™˜๊ฒฝ์—์„œ ๊ฐ€๋ณ๊ฒŒ ์Šค๋‚ต ๊ฒŒ์ž„์„ ์ฆ๊ธฐ๋ฉฐ ์†Œ์†Œํ•˜๊ฒŒ ์•ฑํ…Œํฌ๋ฅผ ํ•˜๊ณ ์ž ํ•˜๋Š” MZ์„ธ๋Œ€ ๋ฐ ์ง์žฅ์ธ.

– **์„œ๋ธŒ ํƒ€๊ฒŸ**: ์ง๊ด€์ ์ธ ์กฐ์ž‘๊ณผ ํ™”๋ คํ•œ ํ”ผ๋“œ๋ฐฑ์„ ์„ ํ˜ธํ•˜๋ฉฐ ๋ฐฉ์น˜ํ˜•/ํ„ฐ์น˜ํ˜• ๊ฒŒ์ž„์„ ์ข‹์•„ํ•˜๋Š” ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž.

## 3. ์„œ๋น„์Šค ํ•ต์‹ฌ ๊ฐ€์น˜ ๋ฐ ์ฐจ๋ณ„์ 

– **๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ธฐ๋ฐ˜ ์†๋ง›**: ์ •ํ˜•ํ™”๋œ ๋ฆฌ์ŠคํŠธ UI ๋Œ€์‹  HTML5 Canvas์™€ ๋ฌผ๋ฆฌ ์—”์ง„(Matter.js)์„ ํ™œ์šฉํ•˜์—ฌ ์ค‘๋ ฅ, ๋ฐ˜๋ฐœ๋ ฅ, ๋งˆ์ฐฐ๋ ฅ์ด ์ ์šฉ๋œ ๊ฐ€์ƒ ๋™์ „๋“ค์„ ํ„ฐ์น˜ํ•˜๋Š” ์—ญ๋™์ ์ธ UX๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

– **๋ชฐ์ž…ํ˜• ๋ฆฌ์›Œ๋“œ ๋ฃจํ”„**: ํ™”๋ฉด์— ๋– ๋‹ค๋‹ˆ๋Š” ์ŠคํŽ˜์…œ ‘ํ™ฉ๊ธˆ ๋™์ „’์ด๋‚˜ ‘๋ณด๋ฌผ์ƒ์ž’๋ฅผ ํ„ฐ์น˜ํ•˜๋ฉด ๋ฆฌ์›Œ๋“œ ๊ด‘๊ณ ํ˜• ๋ชจ๋‹ฌ์ด ํ™œ์„ฑํ™”๋˜๊ณ , ๊ด‘๊ณ  ์‹œ์ฒญ ์™„๋ฃŒ ์‹œ ์ฆ‰์‹œ ๋Œ€๋Ÿ‰์˜ ์บ์‹œ๋ฅผ ์ ๋ฆฝํ•ฉ๋‹ˆ๋‹ค.

– **ํˆฌ๋ช…ํ•œ ์ •์‚ฐ**: ์Œ“์ธ ์บ์‹œ๋ฅผ ๊ธฐํ”„ํ‹ฐ์ฝ˜ ๊ตํ™˜ ๋ฐ ์ฆ‰์‹œ ์ถœ๊ธˆ ์‹ ์ฒญ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ์ง๊ด€์ ์ด๊ณ  ๋น ๋ฅธ ์ •์‚ฐ ํ๋ฆ„์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

# โš™๏ธ 2์žฅ. Blueprint (๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ์‹œ์Šคํ…œ ์„ค๊ณ„)

## 1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ” ์Šคํ‚ค๋งˆ ์ •์˜

### `users` (์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”)

| ์ปฌ๋Ÿผ๋ช… | ํƒ€์ž… | ์ œ์•ฝ์กฐ๊ฑด | ์„ค๋ช… |

| :— | :— | :— | :— |

| `id` | UUID | PRIMARY KEY, DEFAULT gen_random_uuid() | ๊ณ ์œ  ์‚ฌ์šฉ์ž ID |

| `email` | VARCHAR(255) | UNIQUE, NOT NULL | ์ด๋ฉ”์ผ ์ฃผ์†Œ |

| `nickname` | VARCHAR(50) | NOT NULL | ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ |

| `points` | INT | DEFAULT 0, CHECK (points >= 0) | ํ˜„์žฌ ๋ณด์œ  ์ค‘์ธ ์บ์‹œ ํฌ์ธํŠธ |

| `created_at` | TIMESTAMP | DEFAULT NOW() | ํšŒ์› ๊ฐ€์ž…์ผ |

### `point_transactions` (ํฌ์ธํŠธ ์ ๋ฆฝ/์ฐจ๊ฐ ์ด๋ ฅ)

| ์ปฌ๋Ÿผ๋ช… | ํƒ€์ž… | ์ œ์•ฝ์กฐ๊ฑด | ์„ค๋ช… |

| :— | :— | :— | :— |

| `id` | UUID | PRIMARY KEY, DEFAULT gen_random_uuid() | ํŠธ๋žœ์žญ์…˜ ๊ณ ์œ  ID |

| `user_id` | UUID | FOREIGN KEY REFERENCES users(id) ON DELETE CASCADE | ์ ๋ฆฝ/์ฐจ๊ฐ ๋Œ€์ƒ ์œ ์ € ID |

| `amount` | INT | NOT NULL | ๋ณ€๋™ ํฌ์ธํŠธ์•ก (์–‘์ˆ˜: ์ ๋ฆฝ, ์Œ์ˆ˜: ์ฐจ๊ฐ) |

| `type` | VARCHAR(50) | NOT NULL | ๊ตฌ๋ถ„ (`TAP` / `AD_REWARD` / `WITHDRAWAL` / `EVENT`) |

| `description` | TEXT | | ์ƒ์„ธ ์„ค๋ช… |

| `created_at` | TIMESTAMP | DEFAULT NOW() | ์ƒ์„ฑ ์‹œ๊ฐ |

### `withdrawals` (์ถœ๊ธˆ ์‹ ์ฒญ ํ…Œ์ด๋ธ”)

| ์ปฌ๋Ÿผ๋ช… | ํƒ€์ž… | ์ œ์•ฝ์กฐ๊ฑด | ์„ค๋ช… |

| :— | :— | :— | :— |

| `id` | UUID | PRIMARY KEY, DEFAULT gen_random_uuid() | ์ถœ๊ธˆ ์‹ ์ฒญ ๊ณ ์œ  ID |

| `user_id` | UUID | FOREIGN KEY REFERENCES users(id) ON DELETE CASCADE | ์ถœ๊ธˆ ์‹ ์ฒญ ์œ ์ € ID |

| `amount` | INT | NOT NULL | ์ถœ๊ธˆ ์‹ ์ฒญ ํฌ์ธํŠธ์•ก |

| `bank_name` | VARCHAR(50) | NOT NULL | ์€ํ–‰๋ช… |

| `account_number` | VARCHAR(100) | NOT NULL | ๊ณ„์ขŒ๋ฒˆํ˜ธ |

| `status` | VARCHAR(20) | DEFAULT ‘PENDING’ | ์ƒํƒœ (`PENDING`, `APPROVED`, `REJECTED`) |

| `created_at` | TIMESTAMP | DEFAULT NOW() | ์‹ ์ฒญ์ผ์‹œ |

## 2. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ ๋ฐ ๋ฐ์ดํ„ฐ ํ๋ฆ„

– **Frontend**: Next.js (App Router), Tailwind CSS, Framer Motion

– **Physics Engine**: Matter.js (React integration via canvas ref)

– **Backend & Database**: Supabase (PostgreSQL, Auth, Realtime)

– **Data Flow**:

ย  1. **๋™์ „ ์ƒ์„ฑ ๋ฐ ํ„ฐ์น˜**: ์‚ฌ์šฉ์ž๊ฐ€ Gravity Canvas ์ƒ์—์„œ ํŠ•๊ฒจ ๋‹ค๋‹ˆ๋Š” ๋™์ „์„ ํ„ฐ์น˜ํ•˜๋ฉด ํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์ฆ‰๊ฐ ๋ฐ˜์‘ํ•˜์—ฌ ์ ์ˆ˜๋ฅผ ์นด์šดํŠธํ•ฉ๋‹ˆ๋‹ค.

ย  2. **์บ์‹œ ์ ๋ฆฝ ์ฒ˜๋ฆฌ**: API Route๋ฅผ ํ†ตํ•ด Supabase DB์˜ `point_transactions`์— ์›์žฅ ๊ธฐ์ž…์„ ์ˆ˜ํ–‰ํ•˜๊ณ , `users` ํ…Œ์ด๋ธ”์˜ `points` ๊ฐ’์„ ์›์ž์ (Atomic) ์—ฐ์‚ฐ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ๋ถ€์ • ํ–‰์œ„๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

ย  3. **๊ด‘๊ณ  ์—ฐ๋™**: ํŠน์ • ์ˆ˜ ์ด์ƒ ํ„ฐ์น˜ํ•˜๊ฑฐ๋‚˜ ๊ณจ๋“œ ๋ฐ•์Šค ํด๋ฆญ ์‹œ ๋น„๋””์˜ค ๊ด‘๊ณ  API๊ฐ€ ๋กœ๋”ฉ๋˜๊ณ , ์™„๋ฃŒ ์ฝœ๋ฐฑ์„ ๋ฐ›์•„ DB ํŠธ๋žœ์žญ์…˜์„ ํ†ตํ•ด ๋ฆฌ์›Œ๋“œ๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ์ ๋ฆฝ๋ฉ๋‹ˆ๋‹ค.

# ๐Ÿ—บ๏ธ 3์žฅ. User Flow (ํ™”๋ฉด ์„ค๊ณ„)

## 1. ์ฃผ์š” ํŽ˜์ด์ง€ ๋ชฉ๋ก

– **`/` (์˜จ๋ณด๋”ฉ ๋ฐ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€)**: ๊ทธ๋ผ๋น„ํ‹ฐ ์บ์‹œ ์†Œ๊ฐœ ๋ฐ ๊ฐ„ํŽธ ์†Œ์…œ ๋กœ๊ทธ์ธ ํ™”๋ฉด.

– **`/dashboard` (๋ฉ”์ธ ๊ทธ๋ผ๋น„ํ‹ฐ ํ™”๋ฉด)**: ์ค‘๋ ฅ ์—”์ง„์ด ์ ์šฉ๋œ ๋ฉ”์ธ ์บ”๋ฒ„์Šค ์˜์—ญ. ์ขŒ์šฐ๋กœ ํ”๋“ค๊ฑฐ๋‚˜ ๋ชจ๋ฐ”์ผ์„ ๊ธฐ์šธ์ด๋ฉด ๋™์ „๋“ค์ด ์š”๋™์น˜๋ฉฐ ๋–จ์–ด์ง. ์ƒ๋‹จ์— ์บ์‹œ ๋ณด๋“œ ์‹ค์‹œ๊ฐ„ ํ‘œ์‹œ.

– **`/store` (์บ์‹œ ์ƒ์  ๋ฐ ์ถœ๊ธˆ)**: ์Œ“์€ ํฌ์ธํŠธ๋กœ ๊ธฐํ”„ํ‹ฐ์ฝ˜์„ ๊ตฌ๋งคํ•˜๊ฑฐ๋‚˜, ํ˜„๊ธˆ ์ถœ๊ธˆ์„ ์‹ ์ฒญํ•˜๋Š” ํผ ์ œ๊ณต.

– **`/history` (์ ๋ฆฝ ์ด๋ ฅ ๋ฐ ๋‚ด์—ญ)**: ์ถœ๊ธˆ ์ง„ํ–‰ ์ƒํ™ฉ ๋ฐ ํฌ์ธํŠธ ์ ๋ฆฝ ๋กœ๊ทธ๋ฅผ ํƒ€์ž„๋ผ์ธ ํ˜•ํƒœ๋กœ ์ œ๊ณต.

## 2. ๊ฐ ํ™”๋ฉด๋ณ„ ๊ตฌ์„ฑ ์ปดํฌ๋„ŒํŠธ

– **Dashboard ํ™”๋ฉด**:

ย  – `GravityCanvas`: Matter.js๋ฅผ ํƒ‘์žฌํ•˜์—ฌ ์ค‘๋ ฅ ํ•˜์— ๋™์ „ ๊ฐ์ฒด๋“ค์ด ์ถฉ๋Œํ•˜๊ณ  ๋ฆฌ๋ฐ”์šด๋“œํ•˜๋Š” ํ’€์Šคํฌ๋ฆฐ ์บ”๋ฒ„์Šค ์ปดํฌ๋„ŒํŠธ.

ย  – `CashIndicator`: ํ˜„์žฌ ํš๋“ํ•œ ์บ์‹œ์™€ ํ„ฐ์น˜ ํšŸ์ˆ˜๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋…ธ์ถœํ•˜๋Š” ์ƒ๋‹จ ๊ณ ์ • ํ—ค๋”.

ย  – `AdTriggerModal`: ๋ฆฌ์›Œ๋“œ ๊ด‘๊ณ  ๋ณด๊ธฐ๋ฅผ ์œ ๋„ํ•˜๊ณ  ๊ด‘๊ณ ๊ฐ€ ์—ฐ๋™๋˜๋Š” ๋ฐ˜์‘ํ˜• ์˜ค๋ฒ„๋ ˆ์ด.

– **Store ํ™”๋ฉด**:

ย  – `WithdrawalForm`: ์€ํ–‰, ๊ณ„์ขŒ, ์ถœ๊ธˆ์•ก์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ž…๋ ฅ๋ฐ›๊ณ  ์‹ค์‹œ๊ฐ„ ์ž”์•ก ๋Œ€์กฐ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž…๋ ฅ ํผ.

## 3. ํ•ต์‹ฌ ์‚ฌ์šฉ์ž ์ด๋™ ๊ฒฝ๋กœ

1. **๋กœ๊ทธ์ธ**: ์†Œ์…œ ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ํ›„ ๋Œ€์‹œ๋ณด๋“œ๋กœ ์ง„์ž….

2. **๋ฌผ๋ฆฌ ํŒŒ๋ฐ ํ”Œ๋ ˆ์ด**: ํ™”๋ฉด ๋‚ด ๊ฐ€์ƒ์˜ ์ค‘๋ ฅ ํ•˜์— ๋‚™ํ•˜ํ•˜๋Š” ๋™์ „์„ ๋‚œ์‚ฌํ•˜๋“ฏ ํ„ฐ์น˜. ๋™์ „์ด ํŠ•๊ธธ ๋•Œ ๋งˆ๋‹ค ์‚ฌ์šด๋“œ ๋ฐ ํŒŒํ‹ฐํด ์ดํŽ™ํŠธ ๋ฐœ์ƒ. `+1 Cash` ๋ˆ„์ .

3. **ํฌ๋ฆฌํ‹ฐ์ปฌ ๋ฆฌ์›Œ๋“œ ๋ฐœ๋™**: ๋žœ๋คํ•˜๊ฒŒ ๋‚˜ํƒ€๋‚˜๋Š” ํ™ฉ๊ธˆ ๋ณด๋ฌผ์ƒ์ž๋ฅผ ์žก์œผ๋ฉด ๋ฆฌ์›Œ๋“œ ๋น„๋””์˜ค ๊ด‘๊ณ ๊ฐ€ ํŒ์—… ํ˜•ํƒœ๋กœ ์žฌ์ƒ.

4. **์บ์‹œ ํš๋“ ๋ฐ ์ถœ๊ธˆ**: ์ผ์ • ๊ธˆ์•ก ์ด์ƒ ๋„๋‹ฌ ์‹œ ์ƒ์ ์œผ๋กœ ์ด๋™ํ•˜์—ฌ ํ˜„๊ธˆ ์ถœ๊ธˆ์„ ์‹ ์ฒญ.

# ๐Ÿค– AI ๊ฐœ๋ฐœ ์ง€์‹œ์„œ ํ”„๋กฌํ”„ํŠธ ๊ฐ€์ด๋“œ

## 1๋‹จ๊ณ„: ํ”„๋กœ์ ํŠธ ๊ธฐ์ดˆ ๋ผˆ๋Œ€ ๊ตฌ์ถ• ๋ฐ ๋ ˆ์ด์•„์›ƒ ์„ค์ •

“`text

Next.js (App Router), Tailwind CSS, Lucide React๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ‘๊ทธ๋ผ๋น„ํ‹ฐ ์บ์‹œ(Gravity Cash)’ ์›น ์•ฑ์˜ ๋ผˆ๋Œ€๋ฅผ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

1. `package.json`์— ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๋„๋ก ๊ฐ€์ด๋“œ ๋˜๋Š” ๋ผˆ๋Œ€๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.

ย  ย – `matter-js` (๋ฌผ๋ฆฌ ์—”์ง„)

ย  ย – `framer-motion` (UI ์• ๋‹ˆ๋ฉ”์ด์…˜)

ย  ย – `lucide-react` (์•„์ด์ฝ˜)

2. ๊ณตํ†ต ๋ ˆ์ด์•„์›ƒ์„ ์ •์˜ํ•ด ์ฃผ์„ธ์š”.

ย  ย – ์ƒ๋‹จ ํ—ค๋”: ์„œ๋น„์Šค ๋กœ๊ณ  ‘Gravity Cash’, ํ˜„์žฌ ๋ณด์œ  ํฌ์ธํŠธ ํ‘œ์‹œ๋ถ€, ๋ฉ”๋‰ด ๋งํฌ(ํ™ˆ, ์ƒ์ , ์ ๋ฆฝ์ด๋ ฅ)

ย  ย – ๋ชจ๋ฐ”์ผ ํผ์ŠคํŠธ ๋ฐ˜์‘ํ˜• ์ปจํ…Œ์ด๋„ˆ ๋ ˆ์ด์•„์›ƒ (์ตœ๋Œ€ ๋„ˆ๋น„ 480px์˜ ์•ฑ ๋А๋‚Œ์˜ ํ™”๋ฉด ๊ตฌ์„ฑ ์ถ”์ฒœ)

3. ๊ธฐ๋ณธ ๋žœ๋”ฉ ๋ฐ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€(`/app/page.tsx`)์™€ ๋Œ€์‹œ๋ณด๋“œ ๊ตฌ์กฐ(`/app/dashboard/page.tsx`)์˜ ๊ฐ„๋‹จํ•œ ๋ชฉ์—… ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•ด์ฃผ์„ธ์š”.

“`

## 2๋‹จ๊ณ„: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ ์ •์˜ ๋ฐ ์—ฐ๋™

“`text

Supabase ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™ ๋ฐ SQL ์„ค์ •์„ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.

1. ๋‹ค์Œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋Š” PostgreSQL DDL ์ฟผ๋ฆฌ๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”:

ย  ย – `users` (id: uuid, email: text, nickname: text, points: int, created_at)

ย  ย – `point_transactions` (id: uuid, user_id, amount: int, type: text, description: text, created_at)

ย  ย – `withdrawals` (id: uuid, user_id, amount, bank_name, account_number, status, created_at)

2. `supabase/client.ts`๋ฅผ ์ •์˜ํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ์™€ Supabase ๊ฐ„ ์—ฐ๋™ ์„ค์ •์„ ๋งŒ๋“œ์„ธ์š”.

3. ํฌ์ธํŠธ๋ฅผ ์›์ž์ ์œผ๋กœ ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ ์œ„ํ•œ Postgres ํ•จ์ˆ˜(RPC) `increment_points`๋ฅผ ์ •์˜ํ•˜๋Š” SQL์„ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”:

ย  ย – ์ž…๋ ฅ: `target_user_id` (UUID), `amount` (INT)

ย  ย – ๋กœ์ง: `users` ํ…Œ์ด๋ธ”์˜ `points`๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ๋™์‹œ์— `point_transactions` ํ…Œ์ด๋ธ”์— ์ ๋ฆฝ ๋กœ๊ทธ๋ฅผ ์›์žฅ์œผ๋กœ ํ•œ ๋ฒˆ์— ์‚ฝ์ž…ํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ ์ •์˜.

“`

## 3๋‹จ๊ณ„: ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋ฐ API ๊ตฌํ˜„

“`text

Next.js App Router API Route ๋ฐ API ์—ฐ๋™ ๋กœ์ง์„ ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”.

1. `/api/points/route.ts` API ์—”๋“œํฌ์ธํŠธ ๊ตฌํ˜„:

ย  ย – ์‚ฌ์šฉ์ž๊ฐ€ ์ผ๋ฐ˜ ๋™์ „ ํ˜น์€ ํ™ฉ๊ธˆ ์ƒ์ž๋ฅผ ํ„ฐ์น˜ํ•ด ํš๋“ํ•œ ํฌ์ธํŠธ๋ฅผ ์„œ๋ฒ„์— ๋™๊ธฐํ™” ์š”์ฒญํ•˜๋Š” API.

ย  ย – ์š”์ฒญ ๋ณธ๋ฌธ(body): `{ amount: number, type: string, description: string }`

ย  ย – ๋ณด์•ˆ ์ฒ˜๋ฆฌ: Supabase Auth ์„ธ์…˜ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ•ด์•ผ ํ•˜๋ฉฐ, 1์ดˆ ๋‚ด์— ๋น„์ •์ƒ์ ์œผ๋กœ ๋‹ค๋Ÿ‰์˜ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š” ๊ธฐ์ดˆ์ ์ธ ์•ˆํ‹ฐ ์น˜ํŠธ(Anti-Cheat) ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ์„ธ์…˜ ์ฒดํฌ๋ฅผ ๋ฐ˜์˜ํ•ด ์ฃผ์„ธ์š”.

2. `/api/withdraw/route.ts` API ์—”๋“œํฌ์ธํŠธ ๊ตฌํ˜„:

ย  ย – ์ถœ๊ธˆ ์‹ ์ฒญ API.

ย  ย – ์œ ์ €์˜ ํ˜„์žฌ ํฌ์ธํŠธ๋ฅผ ๊ฒ€์ฆํ•˜์—ฌ ์ถœ๊ธˆ ์š”์ฒญ์•ก(`amount`)์ด ํฌ์ธํŠธ ์ž”์•ก๋ณด๋‹ค ํฐ์ง€ ํ™•์ธํ•˜๊ณ , ํ†ต๊ณผํ•˜๋ฉด `points` ์ฐจ๊ฐ ๋ฐ `withdrawals`์— ํ–‰์„ ์‚ฝ์ž…ํ•˜๋Š” ํŠธ๋žœ์žญ์…˜ API๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.

“`

## 4๋‹จ๊ณ„: UI ์™„์„ฑ ๋ฐ ํ”„๋ก ํŠธ์—”๋“œ ์—ฐ๋™

“`text

Matter.js ๋ฌผ๋ฆฌ ์—”์ง„์„ ํ™œ์šฉํ•œ ํ”ผ์ง€์ปฌ ๊ฒŒ์ž„ ํ™”๋ฉด๊ณผ ์ตœ์ข… UI ์—ฐ๋™์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.

1. `/app/dashboard/components/GravityCanvas.tsx` ์ปดํฌ๋„ŒํŠธ๋ฅผ ์„ค๊ณ„ํ•˜์„ธ์š”:

ย  ย – HTML5 ``๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Matter.js ๋ฌผ๋ฆฌ ์›”๋“œ(Engine, World, Render, Runner, Bodies)๋ฅผ ๋งˆ์šดํŠธํ•ฉ๋‹ˆ๋‹ค.

ย  ย – ๋ชจ๋ฐ”์ผ/๋ฐ์Šคํฌํ†ฑ ํ„ฐ์น˜/ํด๋ฆญ ๊ฐ์ง€: ์‚ฌ์šฉ์ž๊ฐ€ ์บ”๋ฒ„์Šค์˜ ํŠน์ • ์œ„์น˜๋ฅผ ํ„ฐ์น˜/ํด๋ฆญํ•˜๋ฉด Matter.js ์›”๋“œ ์•ˆ์— ๋ฌผ๋ฆฌ ์†์„ฑ(์›, ๋ณต์›๋ ฅ, ํƒ„์„ฑ)์„ ๊ฐ€์ง„ ์›ํ˜• ‘๋™์ „(Coin)’๊ณผ ‘๊ธˆ ์ƒ์ž(Chest)’๊ฐ€ ํ•˜๋Š˜์—์„œ ๋–จ์–ด์ง€๊ณ  ๋ฐ”๋‹ฅ์—์„œ ํŠ•๊ธฐ๊ฒŒ ์ฒ˜๋ฆฌํ•˜์„ธ์š”.

ย  ย – ์บ”๋ฒ„์Šค ๋‚ด ์ƒ์„ฑ๋œ ๋™์ „์„ ํด๋ฆญํ•˜๋ฉด ํ„ฐ์น˜ํ•œ ๊ฐ์ฒด๊ฐ€ ํŒŒ๊ดด(World์—์„œ ์ œ๊ฑฐ)๋˜๋ฉด์„œ ํญ์ฃฝ ํŒŒํ‹ฐํด ํšจ๊ณผ๊ฐ€ ํผ์ง€๊ณ , ํด๋ผ์ด์–ธํŠธ ์ธก ํฌ์ธํŠธ ์ƒํƒœ๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋„๋ก ํ•˜์„ธ์š”.

ย  ย – ๋””๋ฐ”์ด์Šค ์ž์ด๋กœ์Šค์ฝ”ํ”„ ๋˜๋Š” ๋“œ๋ž˜๊ทธ๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ค‘๋ ฅ ๋ฐฉํ–ฅ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๊พธ์–ด ๋™์ „๋“ค์ด ๋ฏธ๋„๋Ÿฌ์ ธ ํŠ•๊ธฐ๊ฒŒ ๊ตฌํ˜„ํ•˜์„ธ์š” (์ž์ด๋กœ ์—†๋Š” ํ™˜๊ฒฝ์„ ์œ„ํ•ด ๋“œ๋ž˜๊ทธ ์Šฌ๋ผ์ด๋”๋‚˜ ํด๋ฆญ์œผ๋กœ ์ค‘๋ ฅ ๋ฐ˜์ „ ๋ณด์™„).

2. ์ƒ์ (`/app/store/page.tsx`) ํ™”๋ฉด์—์„œ ์ถœ๊ธˆ ํผ์„ ์ž‘๋™ ๊ฐ€๋Šฅํ•˜๋„๋ก 3๋‹จ๊ณ„์˜ `/api/withdraw`์™€ ์—ฐ๊ฒฐํ•˜๊ณ  ์ƒํƒœ ๋ฉ”์‹œ์ง€๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ํ‘œํ˜„ํ•˜๋Š” ํ† ์ŠคํŠธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜์„ธ์š”.

“`

๋Œ“๊ธ€ ๋‹ฌ๊ธฐ

์ด๋ฉ”์ผ ์ฃผ์†Œ๋Š” ๊ณต๊ฐœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•„์ˆ˜ ํ•„๋“œ๋Š” *๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค