๐ŸŽฐ ์˜ค๋Š˜์˜ ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ - ๋‹น์ฒจ ํ™•๋ฅ  ์ฒดํ—˜ํ•˜๊ธฐ - ๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ ๋ ˆ์‹œํ”ผ
์ž…๋ฌธ PHP g5se AI: Claude

๐ŸŽฐ ์˜ค๋Š˜์˜ ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ - ๋‹น์ฒจ ํ™•๋ฅ  ์ฒดํ—˜ํ•˜๊ธฐ

๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ช… lottery-odds-simulator
์กฐํšŒ์ˆ˜ 177 0๊ฑด ์ œ์ถœ

๋ฌธ์ œ ์„ค๋ช…

๐ŸŽฏ ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

๋กœ๋˜, ์—ฐ๊ธˆ๋ณต๊ถŒ, ์Šคํฌ๋ž˜์น˜ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ณต๊ถŒ์˜ ๋‹น์ฒจ ํ™•๋ฅ ์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์œผ๋กœ ์ฒดํ—˜ํ•˜๋Š” ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ณต๊ถŒ ์ข…๋ฅ˜๋ฅผ ์„ ํƒํ•˜๊ณ  '๊ตฌ๋งค' ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์‹ค์ œ ํ™•๋ฅ ์— ๊ธฐ๋ฐ˜ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ฆ‰์‹œ ํ‘œ์‹œ๋˜๋ฉฐ, ๋ˆ„์  ํ†ต๊ณ„(์ด ๊ตฌ๋งค ํšŸ์ˆ˜, ๋‹น์ฒจ ํšŸ์ˆ˜, ์ˆ˜์ต๋ฅ )๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ™•๋ฅ ์˜ ์ž”์ธํ•จ์„ ์žฌ๋ฏธ์žˆ๊ฒŒ ๊ฒฝํ—˜ํ•˜๋ฉด์„œ๋„ ์‚ฌํ–‰์„ฑ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ํ•จ๊ป˜ ๋…ธ์ถœํ•˜์—ฌ ๊ต์œก์  ํšจ๊ณผ๋ฅผ ๋…ธ๋ฆฝ๋‹ˆ๋‹ค.

โœจ ํ•„์ˆ˜ ๊ธฐ๋Šฅ

  1. ๋ณต๊ถŒ ์ข…๋ฅ˜ ์„ ํƒ ์นด๋“œ

    • ๋กœ๋˜(1๋“ฑ ํ™•๋ฅ  1/8,145,060), ์—ฐ๊ธˆ๋ณต๊ถŒ(1๋“ฑ 1/5,000,000), ์Šคํฌ๋ž˜์น˜(1๋“ฑ 1/500,000) ๋“ฑ 3์ข… ์ด์ƒ
    • ๊ฐ ์นด๋“œ์— ๋ณต๊ถŒ ์ด๋ฏธ์ง€, ๊ฐ€๊ฒฉ, 1๋“ฑ ๋‹น์ฒจ๊ธˆ, ๋‹น์ฒจ ํ™•๋ฅ  ํ‘œ์‹œ
    • ์„ ํƒ ์‹œ ์นด๋“œ ๊ฐ•์กฐ ํšจ๊ณผ(border glow)
  2. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰

    • '1ํšŒ ๊ตฌ๋งค', '10ํšŒ ๊ตฌ๋งค', '100ํšŒ ๊ตฌ๋งค', '1000ํšŒ ๊ตฌ๋งค' ๋ฒ„ํŠผ
    • ํด๋ฆญ ์‹œ ์„ ํƒ๋œ ๋ณต๊ถŒ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ๋‚œ์ˆ˜ ์ƒ์„ฑ โ†’ ๋‹น์ฒจ ์—ฌ๋ถ€ ํŒ์ •
    • ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ(ํšŒ์ „ํ•˜๋Š” ๋ณต๊ถŒ ์ด๋ฏธ์ง€ โ†’ ๊ฒฐ๊ณผ ํŽ˜์ด๋“œ์ธ)
  3. ๊ฒฐ๊ณผ ํ‘œ์‹œ ์˜์—ญ

    • ๋‹น์ฒจ ์‹œ: ์ถ•ํ•˜ ๋ฉ”์‹œ์ง€ + ๋‹น์ฒจ๊ธˆ์•ก (ํฐ ํฐํŠธ, ๊ธˆ์ƒ‰ ๋ฐฐ๊ฒฝ)
    • ๋‚™์ฒจ ์‹œ: ์œ„๋กœ ๋ฉ”์‹œ์ง€ + "๋‹ค์‹œ ๋„์ „!" ๋ฒ„ํŠผ
    • ์ตœ๊ทผ 5ํšŒ ๊ฒฐ๊ณผ ํžˆ์Šคํ† ๋ฆฌ (๋‹น์ฒจ/๋‚™์ฒจ ๋ฑƒ์ง€)
  4. ๋ˆ„์  ํ†ต๊ณ„ ๋Œ€์‹œ๋ณด๋“œ

    • ์ด ๊ตฌ๋งค ํšŸ์ˆ˜, ์ด ์ง€์ถœ ๊ธˆ์•ก
    • ๋‹น์ฒจ ํšŸ์ˆ˜ (1๋“ฑ/2๋“ฑ/3๋“ฑ ๋“ฑ๊ธ‰๋ณ„)
    • ์ด ๋‹น์ฒจ๊ธˆ, ์ˆœ์ˆ˜์ต (์ง€์ถœ - ๋‹น์ฒจ๊ธˆ, ๋งˆ์ด๋„ˆ์Šค์ผ ํ™•๋ฅ  99.9%)
    • ์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„ (Chart.js ๋˜๋Š” ์ˆœ์ˆ˜ CSS ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ”)
  5. ๋ฆฌ์…‹ & ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€

    • ํ†ต๊ณ„ ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ
    • ํŽ˜์ด์ง€ ํ•˜๋‹จ์— "์ด ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” ๊ต์œก ๋ชฉ์ ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ๋ณต๊ถŒ ๊ตฌ๋งค๋Š” ์‹ ์ค‘ํžˆ ํ•˜์„ธ์š”" ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ

๐ŸŽ ์„ ํƒ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ (๋ณด๋„ˆ์Šค)

  • ์ž๋™ ๊ตฌ๋งค ๋ชจ๋“œ: 1์ดˆ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ๋ณต๊ถŒ ๊ตฌ๋งค (Start/Stop ๋ฒ„ํŠผ)
  • ๋‹น์ฒจ ์‚ฌ์šด๋“œ ํšจ๊ณผ: Web Audio API๋กœ ๋‹น์ฒจ ์‹œ ํšจ๊ณผ์Œ ์žฌ์ƒ
  • ๋ณต๊ถŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•: ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋ณต๊ถŒ ์ด๋ฆ„, ๊ฐ€๊ฒฉ, ํ™•๋ฅ  ์„ค์ • ๊ฐ€๋Šฅ (LocalStorage ์ €์žฅ)
  • ์ˆœ์œ„ํ‘œ: LocalStorage ๊ธฐ๋ฐ˜ ์ „์ฒด ์‚ฌ์šฉ์ž ์ตœ๊ณ  ์ˆ˜์ต๋ฅ  ์ˆœ์œ„ (์ต๋ช…)
  • ๋‹คํฌ๋ชจ๋“œ ์ž๋™ ๋Œ€์‘: g5se modern shell ๋””์ž์ธ ํ† ํฐ ํ™œ์šฉ
  • ๊ณต์œ  ๊ธฐ๋Šฅ: "๋‚ด ๋ณต๊ถŒ ๊ฒฐ๊ณผ ๊ณต์œ ํ•˜๊ธฐ" ๋ฒ„ํŠผ โ†’ ํด๋ฆฝ๋ณด๋“œ ๋ณต์‚ฌ (ํ…์ŠคํŠธ ํ˜•ํƒœ)

๐ŸŽจ ๋””์ž์ธ ๊ฐ€์ด๋“œ

  • ๋ณต๊ถŒ ์นด๋“œ๋Š” 3์—ด ๊ทธ๋ฆฌ๋“œ (๋ชจ๋ฐ”์ผ์—์„œ 1์—ด)
  • ๋‹น์ฒจ ์‹œ confetti ์• ๋‹ˆ๋ฉ”์ด์…˜ (CSS keyframes ๋˜๋Š” canvas-confetti CDN)
  • ํ†ต๊ณ„ ์ˆซ์ž๋Š” ์นด์šดํŒ… ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ
  • ์ƒ‰์ƒ: ๋กœ๋˜=๋ณด๋ผ, ์—ฐ๊ธˆ๋ณต๊ถŒ=์ดˆ๋ก, ์Šคํฌ๋ž˜์น˜=์ฃผํ™ฉ ๋“ฑ ๋ณต๊ถŒ๋ณ„ ๋ธŒ๋žœ๋“œ ์ปฌ๋Ÿฌ
  • modern shell์˜ --m-surface, --m-text, --m-shadow ๋ณ€์ˆ˜๋กœ ์นด๋“œ ๋ฐฐ๊ฒฝ/ํ…์ŠคํŠธ/๊ทธ๋ฆผ์ž ์ฒ˜๋ฆฌ

๐Ÿ›  ๊ธฐ์ˆ  ์Šคํƒ

  • ํ”„๋ ˆ์ž„์›Œํฌ: g5se (๊ทธ๋ˆ„๋ณด๋“œ5 SE) โ€” PHP ๊ธฐ๋ฐ˜ CMS
  • DB: SQLite (์„ ํƒ ์‚ฌํ•ญ, ํ†ต๊ณ„ ์˜์†ํ™” ์‹œ ์‚ฌ์šฉ. ๊ธฐ๋ณธ์€ LocalStorage๋กœ ์ถฉ๋ถ„)
  • ํ”„๋ก ํŠธ: ์ˆœ์ˆ˜ HTML/CSS/JavaScript (Vanilla JS)
  • ์Šคํƒ€์ผ: g5se modern shell ๋””์ž์ธ ํ† ํฐ + ์ปค์Šคํ…€ CSS
  • ์• ๋‹ˆ๋ฉ”์ด์…˜: CSS transitions + keyframes

์ œ์•ฝ ์กฐ๊ฑด

  • โ€ข g5se๊ฐ€ ์„ค์น˜๋œ ํ™˜๊ฒฝ์—์„œ ์ž‘์—… (https://github.com/gnuboard/g5se main ๋ธŒ๋žœ์น˜)
  • โ€ข Laravel/Composer/npm/Vite/React/Vue ๋“ฑ ์™ธ๋ถ€ ๋นŒ๋“œ ๋„๊ตฌ ์ ˆ๋Œ€ ์‚ฌ์šฉ ๊ธˆ์ง€
  • โ€ข ์ˆœ์ˆ˜ PHP + g5se ์ปจ๋ฒค์…˜๋งŒ ์‚ฌ์šฉ
  • โ€ข ํด๋” ๊ธฐ๋ฐ˜ ์ž๋™ ๋ผ์šฐํŒ…: app/modules/lottery-odds-simulator/index.php ์ƒ์„ฑ โ†’ URL์€ /lottery-odds-simulator
  • โ€ข modern shell ํ•„์ˆ˜ ์ ์šฉ (_head.inc.php + m-shell + _nav.inc.php + m-container + _footer.inc.php)
  • โ€ข ๋””์ž์ธ ํ† ํฐ ์‚ฌ์šฉ: var(--m-surface), var(--m-text), var(--m-shadow) ๋“ฑ์œผ๋กœ ๋‹คํฌ๋ชจ๋“œ ์ž๋™ ๋Œ€์‘
  • โ€ข DB ์‚ฌ์šฉ ์‹œ ์ž์ฒด SQLite ํŒŒ์ผ (G5_DATA_PATH.'/modules/lottery-odds-simulator.sqlite') โ€” g5se ๋ฉ”์ธ DB ํ…Œ์ด๋ธ” ์ƒ์„ฑ ๊ธˆ์ง€
  • โ€ข ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋Š” htmlspecialchars()๋กœ ์ด์Šค์ผ€์ดํ”„
  • โ€ข ์™ธ๋ถ€ CDN ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ตœ์†Œํ™” (confetti๋Š” ์„ ํƒ ์‚ฌํ•ญ)
  • โ€ข ํ†ต๊ณ„ ์ €์žฅ์€ LocalStorage ์šฐ์„  (SQLite๋Š” ๋ณด๋„ˆ์Šค)

ํ”„๋กฌํ”„ํŠธ ๋ ˆ์‹œํ”ผ

์•„๋ž˜ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ˆœ์„œ๋Œ€๋กœ AI์—๊ฒŒ ๋ณด๋‚ด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋ณต์‚ฌ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”.

1
Step 1
g5se๊ฐ€ ์„ค์น˜๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ(๋ฃจํŠธ์— `index.php`ยท`app/`์ด ์žˆ๋Š” ๊ณณ)์—์„œ ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. (g5se ์„ค์น˜๋Š” https://github.com/gnuboard/g5se ์ฐธ๊ณ )

์ด ๋‹จ๊ณ„์—์„œ๋Š” ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ํŽ˜์ด์ง€์˜ ๊ธฐ๋ณธ ๊ณจ๊ฒฉ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

**์ž‘์—… ๋‚ด์šฉ:**

1. `app/modules/lottery-odds-simulator/index.php` ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
2. modern shell ๊ณจ๊ฒฉ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค:
   - `_common.php` ์ธํด๋ฃจ๋“œ (g5se ์ง„์ž… ์ปจํ…์ŠคํŠธ)
   - `G5_THEME_PATH.'/modern/_head.inc.php'` ์ธํด๋ฃจ๋“œ (HTML head + ๋””์ž์ธ ํ† ํฐ ๋กœ๋“œ)
   - `./head.sub.php` ์ธํด๋ฃจ๋“œ (g5se ๊ณตํ†ต ํ—ค๋”)
   - `<div class="m-shell">` ๋ž˜ํผ
   - `G5_THEME_PATH.'/modern/_nav.inc.php'` ์ธํด๋ฃจ๋“œ (์ƒ๋‹จ ๋„ค๋น„๊ฒŒ์ด์…˜)
   - `<main class="m-container" style="padding: 32px 20px 48px;">`๋กœ ๋ณธ๋ฌธ ์˜์—ญ
   - `G5_THEME_PATH.'/modern/_footer.inc.php'` ์ธํด๋ฃจ๋“œ (ํ•˜๋‹จ ํ‘ธํ„ฐ)
   - `./tail.sub.php` ์ธํด๋ฃจ๋“œ (g5se ๊ณตํ†ต ๊ผฌ๋ฆฌ)
3. ํŽ˜์ด์ง€ ์ œ๋ชฉ์„ `<h1 style="font-size: 2rem; font-weight: 700; margin-bottom: 1rem; color: var(--m-text);">๐ŸŽฐ ์˜ค๋Š˜์˜ ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ</h1>`๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
4. ํ•˜๋‹จ์— ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค: `<p style="margin-top: 2rem; padding: 16px; background: var(--m-surface); border-left: 4px solid #f59e0b; color: var(--m-text-muted); font-size: 0.9rem;">โš ๏ธ ์ด ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” ๊ต์œก ๋ชฉ์ ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ ๋ณต๊ถŒ ๊ตฌ๋งค๋Š” ์‹ ์ค‘ํžˆ ํ•˜์„ธ์š”.</p>`

**์ฐธ๊ณ :**
- ๋ผ์šฐํŠธ ๋“ฑ๋ก ๋ถˆํ•„์š” (ํด๋” ๊ธฐ๋ฐ˜ ์ž๋™ ๋ผ์šฐํŒ…)
- ์ƒ๋Œ€๊ฒฝ๋กœ `./_common.php`, `./head.sub.php`, `./tail.sub.php`๋Š” g5se ์ง„์ž…์ด cwd๋ฅผ `app/`๋กœ ์žก์•„์ฃผ๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ
- `G5_THEME_PATH`๋Š” `_common.php` ์ธํด๋ฃจ๋“œ ํ›„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (ํ˜„์žฌ ํ…Œ๋งˆ ๊ฒฝ๋กœ)

**์˜ˆ์ƒ ์ถœ๋ ฅ:**
๋ธŒ๋ผ์šฐ์ €์—์„œ `/lottery-odds-simulator` ์ ‘์† ์‹œ g5se ์‚ฌ์ดํŠธ ๋„ค๋น„๊ฒŒ์ด์…˜/ํ‘ธํ„ฐ์™€ ํ•จ๊ป˜ "๐ŸŽฐ ์˜ค๋Š˜์˜ ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ" ์ œ๋ชฉ๊ณผ ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: app/modules/lottery-odds-simulator/index.php ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜๊ณ , /lottery-odds-simulator URL๋กœ ์ ‘์†ํ•˜๋ฉด g5se modern shell(๋„ค๋น„๊ฒŒ์ด์…˜/ํ‘ธํ„ฐ ํฌํ•จ)๊ณผ ํ•จ๊ป˜ ํŽ˜์ด์ง€ ์ œ๋ชฉ '๐ŸŽฐ ์˜ค๋Š˜์˜ ๋ณต๊ถŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ'๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ํ•˜๋‹จ์— ๊ฒฝ๊ณ  ๋ฌธ๊ตฌ๊ฐ€ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

2
Step 2
๋ณต๊ถŒ ์ข…๋ฅ˜ ์„ ํƒ ์นด๋“œ UI๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

**์ž‘์—… ๋‚ด์šฉ:**

1. `<main>` ์•ˆ์— ๋ณต๊ถŒ ์„ ํƒ ์„น์…˜์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:
```html
<section style="margin-bottom: 2rem;">
    <h2 style="font-size: 1.5rem; font-weight: 600; margin-bottom: 1rem; color: var(--m-text);">๋ณต๊ถŒ ์ข…๋ฅ˜ ์„ ํƒ</h2>
    <div id="lotteryCards" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem;">
        <!-- ์นด๋“œ๋Š” JavaScript๋กœ ๋™์  ์ƒ์„ฑ -->
    </div>
</section>
```

2. `<main>` ๋๋‚˜๊ธฐ ์ „์— `<script>` ๋ธ”๋ก์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณต๊ถŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ •์˜ํ•˜๊ณ  ์นด๋“œ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค:
```javascript
const lotteries = [
    { id: 'lotto', name: '๋กœ๋˜ 6/45', price: 1000, jackpot: '20์–ต์›', odds: 8145060, color: '#8b5cf6', emoji: '๐ŸŽฑ' },
    { id: 'pension', name: '์—ฐ๊ธˆ๋ณต๊ถŒ', price: 1000, jackpot: '์›” 700๋งŒ์› (20๋…„)', odds: 5000000, color: '#10b981', emoji: '๐Ÿ’ฐ' },
    { id: 'scratch', name: '์Šคํฌ๋ž˜์น˜', price: 2000, jackpot: '1์–ต์›', odds: 500000, color: '#f97316', emoji: '๐ŸŽซ' }
];

let selectedLottery = null;

function renderCards() {
    const container = document.getElementById('lotteryCards');
    container.innerHTML = lotteries.map(lot => `
        <div class="lottery-card" data-id="${lot.id}" style="
            background: var(--m-surface);
            border: 2px solid transparent;
            border-radius: var(--m-radius-lg);
            padding: 1.5rem;
            cursor: pointer;
            transition: all 0.3s;
            box-shadow: var(--m-shadow);
        ">
            <div style="font-size: 3rem; text-align: center; margin-bottom: 0.5rem;">${lot.emoji}</div>
            <h3 style="font-size: 1.25rem; font-weight: 600; margin-bottom: 0.5rem; color: var(--m-text);">${lot.name}</h3>
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">๊ฐ€๊ฒฉ: ${lot.price.toLocaleString()}์›</p>
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">1๋“ฑ: ${lot.jackpot}</p>
            <p style="color: var(--m-text-muted); font-size: 0.85rem;">ํ™•๋ฅ : 1/${lot.odds.toLocaleString()}</p>
        </div>
    `).join('');

    // ์นด๋“œ ํด๋ฆญ ์ด๋ฒคํŠธ
    document.querySelectorAll('.lottery-card').forEach(card => {
        card.addEventListener('click', () => {
            selectedLottery = card.dataset.id;
            document.querySelectorAll('.lottery-card').forEach(c => c.style.borderColor = 'transparent');
            const lot = lotteries.find(l => l.id === selectedLottery);
            card.style.borderColor = lot.color;
            card.style.boxShadow = `0 0 20px ${lot.color}80`;
        });
    });
}

renderCards();
```

**์˜ˆ์ƒ ์ถœ๋ ฅ:**
ํŽ˜์ด์ง€์— 3๊ฐœ์˜ ๋ณต๊ถŒ ์นด๋“œ(๋กœ๋˜, ์—ฐ๊ธˆ๋ณต๊ถŒ, ์Šคํฌ๋ž˜์น˜)๊ฐ€ ๊ทธ๋ฆฌ๋“œ๋กœ ํ‘œ์‹œ๋˜๊ณ , ํด๋ฆญ ์‹œ ์„ ํƒ๋œ ์นด๋“œ์— ์ƒ‰์ƒ ํ…Œ๋‘๋ฆฌ glow ํšจ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: ๋ณต๊ถŒ ์„ ํƒ ์„น์…˜์ด ์ถ”๊ฐ€๋˜๊ณ , ๋กœ๋˜/์—ฐ๊ธˆ๋ณต๊ถŒ/์Šคํฌ๋ž˜์น˜ 3์ข…์˜ ์นด๋“œ๊ฐ€ ๊ทธ๋ฆฌ๋“œ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์นด๋“œ ํด๋ฆญ ์‹œ ์„ ํƒ๋œ ์นด๋“œ์— ์ƒ‰์ƒ ํ…Œ๋‘๋ฆฌ์™€ ๊ทธ๋ฆผ์ž ํšจ๊ณผ๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

3
Step 3
์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰ ๋ฒ„ํŠผ๊ณผ ๊ฒฐ๊ณผ ํ‘œ์‹œ ์˜์—ญ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

**์ž‘์—… ๋‚ด์šฉ:**

1. ๋ณต๊ถŒ ์„ ํƒ ์„น์…˜ ์•„๋ž˜์— ๊ตฌ๋งค ๋ฒ„ํŠผ ์„น์…˜์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:
```html
<section style="margin-bottom: 2rem;">
    <h2 style="font-size: 1.5rem; font-weight: 600; margin-bottom: 1rem; color: var(--m-text);">์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰</h2>
    <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
        <button onclick="buySim(1)" style="padding: 12px 24px; background: var(--m-primary); color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer; font-weight: 600;">1ํšŒ ๊ตฌ๋งค</button>
        <button onclick="buySim(10)" style="padding: 12px 24px; background: var(--m-primary); color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer; font-weight: 600;">10ํšŒ ๊ตฌ๋งค</button>
        <button onclick="buySim(100)" style="padding: 12px 24px; background: var(--m-primary); color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer; font-weight: 600;">100ํšŒ ๊ตฌ๋งค</button>
        <button onclick="buySim(1000)" style="padding: 12px 24px; background: var(--m-primary); color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer; font-weight: 600;">1000ํšŒ ๊ตฌ๋งค</button>
    </div>
</section>

<section style="margin-bottom: 2rem;">
    <h2 style="font-size: 1.5rem; font-weight: 600; margin-bottom: 1rem; color: var(--m-text);">๊ฒฐ๊ณผ</h2>
    <div id="resultArea" style="background: var(--m-surface); padding: 2rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); min-height: 150px; text-align: center; color: var(--m-text-muted);">
        ๋ณต๊ถŒ์„ ์„ ํƒํ•˜๊ณ  ๊ตฌ๋งค ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.
    </div>
</section>
```

2. `<script>` ๋ธ”๋ก์— ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:
```javascript
let stats = {
    totalBuys: 0,
    totalSpent: 0,
    wins: 0,
    totalWinnings: 0,
    history: []
};

function buySim(count) {
    if (!selectedLottery) {
        alert('๋ณต๊ถŒ ์ข…๋ฅ˜๋ฅผ ๋จผ์ € ์„ ํƒํ•ด์ฃผ์„ธ์š”!');
        return;
    }

    const lot = lotteries.find(l => l.id === selectedLottery);
    const resultArea = document.getElementById('resultArea');
    resultArea.innerHTML = '<div style="font-size: 3rem;">๐ŸŽฐ</div><p>์ถ”์ฒจ ์ค‘...</p>';

    setTimeout(() => {
        let winCount = 0;
        let winnings = 0;

        for (let i = 0; i < count; i++) {
            const rand = Math.random();
            if (rand < 1 / lot.odds) {
                winCount++;
                // ๊ฐ„๋‹จํžˆ 1๋“ฑ๋งŒ ์ฒ˜๋ฆฌ (์‹ค์ œ๋กœ๋Š” 2๋“ฑ/3๋“ฑ ํ™•๋ฅ ๋„ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ)
                const prize = lot.id === 'lotto' ? 2000000000 : lot.id === 'pension' ? 168000000 : 100000000;
                winnings += prize;
            }
        }

        stats.totalBuys += count;
        stats.totalSpent += lot.price * count;
        stats.wins += winCount;
        stats.totalWinnings += winnings;

        const profit = stats.totalWinnings - stats.totalSpent;
        const message = winCount > 0
            ? `<div style="font-size: 3rem;">๐ŸŽ‰</div><h3 style="color: #f59e0b; font-size: 1.5rem; margin: 1rem 0;">์ถ•ํ•˜ํ•ฉ๋‹ˆ๋‹ค! ${winCount}ํšŒ ๋‹น์ฒจ!</h3><p style="font-size: 1.25rem; font-weight: 600;">๋‹น์ฒจ๊ธˆ: ${winnings.toLocaleString()}์›</p>`
            : `<div style="font-size: 3rem;">๐Ÿ˜ข</div><p style="font-size: 1.25rem;">์•„์‰ฝ๊ฒŒ๋„ ${count}ํšŒ ๋ชจ๋‘ ๋‚™์ฒจ์ž…๋‹ˆ๋‹ค.</p><button onclick="buySim(1)" style="margin-top: 1rem; padding: 8px 16px; background: var(--m-primary); color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer;">๋‹ค์‹œ ๋„์ „!</button>`;

        resultArea.innerHTML = message + `<p style="margin-top: 1rem; color: var(--m-text-muted); font-size: 0.9rem;">์ˆœ์ˆ˜์ต: ${profit >= 0 ? '+' : ''}${profit.toLocaleString()}์›</p>`;

        // ํžˆ์Šคํ† ๋ฆฌ ์ถ”๊ฐ€ (์ตœ๊ทผ 5๊ฐœ๋งŒ)
        stats.history.unshift({ count, winCount, winnings, profit });
        if (stats.history.length > 5) stats.history.pop();

        updateStats();
    }, 1000);
}

function updateStats() {
    // ๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ตฌํ˜„
}
```

**์˜ˆ์ƒ ์ถœ๋ ฅ:**
๊ตฌ๋งค ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ 1์ดˆ ํ›„ ๊ฒฐ๊ณผ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋‹น์ฒจ ์‹œ ์ถ•ํ•˜ ๋ฉ”์‹œ์ง€์™€ ๋‹น์ฒจ๊ธˆ, ๋‚™์ฒจ ์‹œ ์œ„๋กœ ๋ฉ”์‹œ์ง€์™€ ๋‹ค์‹œ ๋„์ „ ๋ฒ„ํŠผ์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์‹คํ–‰ ๋ฒ„ํŠผ(1ํšŒ/10ํšŒ/100ํšŒ/1000ํšŒ)๊ณผ ๊ฒฐ๊ณผ ํ‘œ์‹œ ์˜์—ญ์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์„ ํƒ๋œ ๋ณต๊ถŒ์˜ ํ™•๋ฅ ์— ๋”ฐ๋ผ ๋‹น์ฒจ/๋‚™์ฒจ ๊ฒฐ๊ณผ๊ฐ€ ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ํ•จ๊ป˜ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

4
Step 4
๋ˆ„์  ํ†ต๊ณ„ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฆฌ์…‹ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

**์ž‘์—… ๋‚ด์šฉ:**

1. ๊ฒฐ๊ณผ ์„น์…˜ ์•„๋ž˜์— ํ†ต๊ณ„ ์„น์…˜์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:
```html
<section style="margin-bottom: 2rem;">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
        <h2 style="font-size: 1.5rem; font-weight: 600; color: var(--m-text);">๋ˆ„์  ํ†ต๊ณ„</h2>
        <button onclick="resetStats()" style="padding: 8px 16px; background: #ef4444; color: white; border: none; border-radius: var(--m-radius-lg); cursor: pointer; font-size: 0.9rem;">๋ฆฌ์…‹</button>
    </div>
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem;">
        <div style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); text-align: center;">
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">์ด ๊ตฌ๋งค ํšŸ์ˆ˜</p>
            <p id="statBuys" style="font-size: 2rem; font-weight: 700; color: var(--m-text);">0</p>
        </div>
        <div style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); text-align: center;">
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">์ด ์ง€์ถœ</p>
            <p id="statSpent" style="font-size: 2rem; font-weight: 700; color: var(--m-text);">0์›</p>
        </div>
        <div style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); text-align: center;">
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">๋‹น์ฒจ ํšŸ์ˆ˜</p>
            <p id="statWins" style="font-size: 2rem; font-weight: 700; color: #10b981;">0</p>
        </div>
        <div style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); text-align: center;">
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">์ด ๋‹น์ฒจ๊ธˆ</p>
            <p id="statWinnings" style="font-size: 2rem; font-weight: 700; color: #f59e0b;">0์›</p>
        </div>
        <div style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); text-align: center; grid-column: span 2;">
            <p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 0.5rem;">์ˆœ์ˆ˜์ต</p>
            <p id="statProfit" style="font-size: 2rem; font-weight: 700;">0์›</p>
        </div>
    </div>
</section>

<section>
    <h2 style="font-size: 1.5rem; font-weight: 600; margin-bottom: 1rem; color: var(--m-text);">์ตœ๊ทผ ๊ธฐ๋ก</h2>
    <div id="historyArea" style="background: var(--m-surface); padding: 1.5rem; border-radius: var(--m-radius-lg); box-shadow: var(--m-shadow); color: var(--m-text-muted);">
        ์•„์ง ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค.
    </div>
</section>
```

2. `<script>` ๋ธ”๋ก์— ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ ๋ฐ ๋ฆฌ์…‹ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค:
```javascript
function updateStats() {
    document.getElementById('statBuys').textContent = stats.totalBuys.toLocaleString();
    document.getElementById('statSpent').textContent = stats.totalSpent.toLocaleString() + '์›';
    document.getElementById('statWins').textContent = stats.wins.toLocaleString();
    document.getElementById('statWinnings').textContent = stats.totalWinnings.toLocaleString() + '์›';

    const profit = stats.totalWinnings - stats.totalSpent;
    const profitEl = document.getElementById('statProfit');
    profitEl.textContent = (profit >= 0 ? '+' : '') + profit.toLocaleString() + '์›';
    profitEl.style.color = profit >= 0 ? '#10b981' : '#ef4444';

    // ํžˆ์Šคํ† ๋ฆฌ ๋ Œ๋”๋ง
    const historyArea = document.getElementById('historyArea');
    if (stats.history.length === 0) {
        historyArea.innerHTML = '<p style="color: var(--m-text-muted);">์•„์ง ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค.</p>';
    } else {
        historyArea.innerHTML = stats.history.map((h, i) => `
            <div style="padding: 12px; background: ${i % 2 === 0 ? 'var(--m-surface)' : 'transparent'}; border-radius: 8px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center;">
                <span style="color: var(--m-text);">${h.count}ํšŒ ๊ตฌ๋งค</span>
                <span style="color: ${h.winCount > 0 ? '#10b981' : '#ef4444'}; font-weight: 600;">${h.winCount > 0 ? '๋‹น์ฒจ ' + h.winCount + 'ํšŒ' : '๋‚™์ฒจ'}</span>
                <span style="color: var(--m-text-muted);">${(h.profit >= 0 ? '+' : '') + h.profit.toLocaleString()}์›</span>
            </div>
        `).join('');
    }

    // LocalStorage ์ €์žฅ
    localStorage.setItem('lotteryStats', JSON.stringify(stats));
}

function resetStats() {
    if (!confirm('ํ†ต๊ณ„๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?')) return;
    stats = { totalBuys: 0, totalSpent: 0, wins: 0, totalWinnings: 0, history: [] };
    updateStats();
    document.getElementById('resultArea').innerHTML = '<p style="color: var(--m-text-muted);">๋ณต๊ถŒ์„ ์„ ํƒํ•˜๊ณ  ๊ตฌ๋งค ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”.</p>';
}

// ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ ์ €์žฅ๋œ ํ†ต๊ณ„ ๋ณต์›
window.addEventListener('DOMContentLoaded', () => {
    const saved = localStorage.getItem('lotteryStats');
    if (saved) {
        stats = JSON.parse(saved);
        updateStats();
    }
});
```

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

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

์ œ์ถœ๋œ ์ž‘ํ’ˆ (0)

๋กœ๊ทธ์ธ ํ›„ ์ œ์ถœ

์•„์ง ์ œ์ถœ๋œ ์ž‘ํ’ˆ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋„์ „์ž๊ฐ€ ๋˜์–ด๋ณด์„ธ์š”!

๋Œ“๊ธ€ (0)

๋กœ๊ทธ์ธ ํ›„ ๋Œ“๊ธ€์„ ๋‚จ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋Œ“๊ธ€์„ ๋‚จ๊ฒจ๋ณด์„ธ์š”!