๐ŸŽฒ ์˜ค๋Š˜์˜ ์šด์„ธ ๋ฝ‘๊ธฐ - ๋žœ๋ค ํฌ์ถ˜ ์ฟ ํ‚ค ์ƒ์„ฑ๊ธฐ - ๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ ๋ ˆ์‹œํ”ผ
์ž…๋ฌธ PHP g5se AI: Claude

๐ŸŽฒ ์˜ค๋Š˜์˜ ์šด์„ธ ๋ฝ‘๊ธฐ - ๋žœ๋ค ํฌ์ถ˜ ์ฟ ํ‚ค ์ƒ์„ฑ๊ธฐ

๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ช… fortune-cookie-generator
์กฐํšŒ์ˆ˜ 447 0๊ฑด ์ œ์ถœ

๋ฌธ์ œ ์„ค๋ช…

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

์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋žœ๋ค์œผ๋กœ ์˜ค๋Š˜์˜ ์šด์„ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ท€์—ฌ์šด ํฌ์ถ˜ ์ฟ ํ‚ค ์ƒ์„ฑ๊ธฐ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. g5se์˜ modern shell์„ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ์ดํŠธ ์ „์ฒด์™€ ์ผ๊ด€๋œ ๋””์ž์ธ์„ ์œ ์ง€ํ•˜๋ฉด์„œ, ๋‹คํฌ๋ชจ๋“œ์—์„œ๋„ ์™„๋ฒฝํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ๋‹จ์ผ ํŽ˜์ด์ง€ ์•ฑ์ž…๋‹ˆ๋‹ค.

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

  • ๋žœ๋ค ์šด์„ธ ์ƒ์„ฑ: ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋ฏธ๋ฆฌ ์ค€๋น„๋œ ์šด์„ธ ๋ฉ”์‹œ์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋žœ๋ค์œผ๋กœ ํ‘œ์‹œ
  • ์‹œ๊ฐ์  ํ”ผ๋“œ๋ฐฑ: ์šด์„ธ๋ฅผ ๋ฝ‘์„ ๋•Œ ์ฟ ํ‚ค๊ฐ€ ๊นจ์ง€๋Š” ๋“ฏํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ
  • ์šด์„ธ ์นดํ…Œ๊ณ ๋ฆฌ: ์—ฐ์• ์šด, ์žฌ๋ฌผ์šด, ๊ฑด๊ฐ•์šด, ํ•™์—…์šด ๋“ฑ ๋‹ค์–‘ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ฉ”์‹œ์ง€ (์ตœ์†Œ 20๊ฐœ ์ด์ƒ)
  • ๊ณต์œ  ๊ธฐ๋Šฅ: ๋ฝ‘์€ ์šด์„ธ๋ฅผ SNS์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋Š” ํ…์ŠคํŠธ ๋ณต์‚ฌ ๋ฒ„ํŠผ
  • ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘: modern shell์˜ ๋””์ž์ธ ํ† ํฐ์„ ํ™œ์šฉํ•˜์—ฌ ๋ผ์ดํŠธ/๋‹คํฌ ๋ชจ๋“œ ์ž๋™ ์ „ํ™˜
  • ๋ฐ˜์‘ํ˜• ๋””์ž์ธ: ๋ชจ๋ฐ”์ผ/ํƒœ๋ธ”๋ฆฟ/๋ฐ์Šคํฌํ†ฑ ๋ชจ๋“  ํ™”๋ฉด์—์„œ ์ตœ์ ํ™”๋œ ๋ ˆ์ด์•„์›ƒ

๐ŸŽ ๋ณด๋„ˆ์Šค ๊ธฐ๋Šฅ

  • ์˜ค๋Š˜ ์ด๋ฏธ ์šด์„ธ๋ฅผ ๋ฝ‘์•˜๋‹ค๋ฉด ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๊ธฐ (localStorage ํ™œ์šฉ)
  • ์šด์„ธ๋ณ„ ํ–‰์šด์˜ ์ƒ‰์ƒ/์ˆซ์ž ์ถ”๊ฐ€ ํ‘œ์‹œ
  • ๋ฝ‘์€ ์šด์„ธ ํžˆ์Šคํ† ๋ฆฌ (์ตœ๊ทผ 5๊ฐœ) ํ•˜๋‹จ์— ํ‘œ์‹œ
  • ๋ถ€๋“œ๋Ÿฌ์šด fade-in/slide-up ์• ๋‹ˆ๋ฉ”์ด์…˜
  • ๋ฐฐ๊ฒฝ์— ๋– ๋‹ค๋‹ˆ๋Š” ๋ณ„/๋ฐ˜์ง์ž„ ํšจ๊ณผ (CSS ์• ๋‹ˆ๋ฉ”์ด์…˜)

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

  • ํฌ์ถ˜ ์ฟ ํ‚ค ์•„์ด์ฝ˜/์ผ๋Ÿฌ์ŠคํŠธ (์ด๋ชจ์ง€ ๋˜๋Š” SVG)
  • ์นด๋“œ ํ˜•ํƒœ์˜ ์šด์„ธ ๋ฉ”์‹œ์ง€ ๋ฐ•์Šค (var(--m-surface) ๋ฐฐ๊ฒฝ, var(--m-shadow) ๊ทธ๋ฆผ์ž)
  • ํฐ ๋ฒ„ํŠผ (var(--m-radius-lg) ๋ผ์šด๋“œ, hover ์‹œ scale ํšจ๊ณผ)
  • ์šด์„ธ ํ…์ŠคํŠธ๋Š” ์ค‘์•™ ์ •๋ ฌ, ํฐ ํฐํŠธ ์‚ฌ์ด์ฆˆ
  • ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ ์•„์ด์ฝ˜ (๐Ÿ’• ์—ฐ์• , ๐Ÿ’ฐ ์žฌ๋ฌผ, ๐Ÿƒ ๊ฑด๊ฐ•, ๐Ÿ“š ํ•™์—…)

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

  • PHP (์ˆœ์ˆ˜ PHP, g5se ์ปจ๋ฒค์…˜)
  • HTML/CSS (modern shell ๋””์ž์ธ ํ† ํฐ)
  • Vanilla JavaScript (์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์Œ)
  • SQLite ๋ถˆํ•„์š” (์šด์„ธ ๋ฐ์ดํ„ฐ๋Š” PHP ๋ฐฐ์—ด๋กœ ํ•˜๋“œ์ฝ”๋”ฉ)

๐Ÿ“ ํ•™์Šต ํฌ์ธํŠธ

  • g5se ํด๋” ๊ธฐ๋ฐ˜ ์ž๋™ ๋ผ์šฐํŒ… ์ดํ•ด
  • modern shell ํ†ตํ•ฉ์œผ๋กœ ์ผ๊ด€๋œ UI ๊ตฌํ˜„
  • CSS ๋ณ€์ˆ˜๋ฅผ ํ™œ์šฉํ•œ ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘
  • JavaScript๋กœ ๋žœ๋ค ์„ ํƒ ๋กœ์ง ๊ตฌํ˜„
  • localStorage๋ฅผ ํ™œ์šฉํ•œ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์ƒํƒœ ๊ด€๋ฆฌ
  • CSS transition/animation์œผ๋กœ ๋ถ€๋“œ๋Ÿฌ์šด UX ๋งŒ๋“ค๊ธฐ

์ œ์•ฝ ์กฐ๊ฑด

  • โ€ข g5se ์„ค์น˜๋ณธ ์œ„์— ์ž‘์—… (์ƒˆ ํด๋” ์ƒ์„ฑ ๊ธˆ์ง€)
  • โ€ข app/modules/fortune-cookie-generator/index.php ๋‹จ์ผ ํŒŒ์ผ๋กœ ๊ตฌํ˜„
  • โ€ข modern shell (_head.inc.php, _nav.inc.php, _footer.inc.php) ํ•„์ˆ˜ ์‚ฌ์šฉ
  • โ€ข ๋””์ž์ธ ํ† ํฐ (var(--m-surface), var(--m-text), var(--m-shadow) ๋“ฑ) ํ™œ์šฉ
  • โ€ข ๋ผ์šฐํŠธ ๋“ฑ๋ก ๋ถˆํ•„์š” (ํด๋” ์ž๋™ ๋งคํ•‘)
  • โ€ข ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/CDN ์‚ฌ์šฉ ๊ธˆ์ง€ (์ˆœ์ˆ˜ HTML/CSS/JS)
  • โ€ข DB ์‚ฌ์šฉ ๊ธˆ์ง€ (์šด์„ธ ๋ฐ์ดํ„ฐ๋Š” PHP ๋ฐฐ์—ด๋กœ ๊ด€๋ฆฌ)
  • โ€ข ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ž…๋ ฅ์€ htmlspecialchars()๋กœ ์ด์Šค์ผ€์ดํ”„
  • โ€ข ๋ฐ˜์‘ํ˜• ๋””์ž์ธ (๋ชจ๋ฐ”์ผ ์šฐ์„ )
  • โ€ข ๋‹คํฌ๋ชจ๋“œ ์ž๋™ ๋Œ€์‘

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

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

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

์ด์ œ ํฌ์ถ˜ ์ฟ ํ‚ค ์ƒ์„ฑ๊ธฐ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

**1๋‹จ๊ณ„: ๊ธฐ๋ณธ ํŽ˜์ด์ง€ ๊ตฌ์กฐ + modern shell ์ ์šฉ**

`app/modules/fortune-cookie-generator/index.php` ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ๋‹ค์Œ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜์„ธ์š”:

```php
<?php
include_once('./_common.php');

// ์šด์„ธ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด (์นดํ…Œ๊ณ ๋ฆฌ๋ณ„๋กœ ์ •๋ฆฌ)
$fortunes = [
    'love' => [
        '์˜ค๋Š˜์€ ํŠน๋ณ„ํ•œ ์ธ์—ฐ์„ ๋งŒ๋‚  ์ˆ˜ ์žˆ๋Š” ๋‚ ์ž…๋‹ˆ๋‹ค. ๐Ÿ’•',
        '๋งˆ์Œ์„ ์—ด๋ฉด ์‚ฌ๋ž‘์ด ์ฐพ์•„์˜ต๋‹ˆ๋‹ค. ์šฉ๊ธฐ๋ฅผ ๋‚ด๋ณด์„ธ์š”!',
        '์†Œ์ค‘ํ•œ ์‚ฌ๋žŒ์—๊ฒŒ ๋จผ์ € ์—ฐ๋ฝํ•ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”?',
        '์˜ค๋Š˜์˜ ๋‹น์‹ ์€ ๋งค๋ ฅ์ด ๋„˜์นฉ๋‹ˆ๋‹ค. ์ž์‹ ๊ฐ์„ ๊ฐ€์ง€์„ธ์š”!',
        '์ง„์‹ฌ์€ ์–ธ์  ๊ฐ€ ํ†ตํ•˜๊ฒŒ ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ๊ธ‰ํ•ดํ•˜์ง€ ๋งˆ์„ธ์š”.',
    ],
    'money' => [
        '์ž‘์€ ํ–‰์šด์ด ๋‹น์‹ ์„ ์ฐพ์•„์˜ฌ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ๐Ÿ’ฐ',
        '์˜ค๋Š˜์€ ์ €์ถ•๋ณด๋‹ค ์ž๊ธฐ๊ณ„๋ฐœ์— ํˆฌ์žํ•˜๋Š” ๋‚ ์ž…๋‹ˆ๋‹ค.',
        '์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ณณ์—์„œ ๊ธฐํšŒ๊ฐ€ ์ฐพ์•„์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.',
        'ํ˜„๋ช…ํ•œ ์†Œ๋น„๊ฐ€ ๋ฏธ๋ž˜์˜ ๋ถ€๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.',
        '๊ฐ์‚ฌํ•˜๋Š” ๋งˆ์Œ์ด ๋” ๋งŽ์€ ํ’์š”๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.',
    ],
    'health' => [
        '์˜ค๋Š˜์€ ๋ชธ์ด ๊ฐ€๋ฒผ์›Œ์ง€๋Š” ๋‚ ์ž…๋‹ˆ๋‹ค. ๊ฐ€๋ณ๊ฒŒ ์‚ฐ์ฑ…ํ•ด๋ณด์„ธ์š”! ๐Ÿƒ',
        '์ถฉ๋ถ„ํ•œ ํœด์‹์ด ๋‚ด์ผ์˜ ์—๋„ˆ์ง€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.',
        '๋ฌผ์„ ๋งŽ์ด ๋งˆ์‹œ๊ณ  ์ŠคํŠธ๋ ˆ์นญ์„ ํ•ด๋ณด์„ธ์š”.',
        '๊ฑด๊ฐ•ํ•œ ์‹๋‹จ์ด ํ•˜๋ฃจ๋ฅผ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.',
        '๊ทœ์น™์ ์ธ ์ƒํ™œ์ด ์ตœ๊ณ ์˜ ๋ณด์•ฝ์ž…๋‹ˆ๋‹ค.',
    ],
    'study' => [
        '์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ์ด ๋ฏธ๋ž˜์˜ ์ž์‚ฐ์ด ๋ฉ๋‹ˆ๋‹ค. ๐Ÿ“š',
        '์ž‘์€ ๋…ธ๋ ฅ์ด ๋ชจ์—ฌ ํฐ ์„ฑ๊ณผ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.',
        '์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์šฐ๊ธฐ์— ์™„๋ฒฝํ•œ ๋‚ ์ž…๋‹ˆ๋‹ค.',
        '๊พธ์ค€ํ•จ์ด ์žฌ๋Šฅ์„ ์ด๊น๋‹ˆ๋‹ค. ํฌ๊ธฐํ•˜์ง€ ๋งˆ์„ธ์š”!',
        '์˜ค๋Š˜์˜ ์‹ค์ˆ˜๋Š” ๋‚ด์ผ์˜ ์„ฑ์žฅ์ž…๋‹ˆ๋‹ค.',
    ],
];

// ๋ชจ๋“  ์šด์„ธ๋ฅผ ํ•˜๋‚˜์˜ ๋ฐฐ์—ด๋กœ ํ•ฉ์น˜๊ธฐ
$all_fortunes = [];
foreach ($fortunes as $category => $messages) {
    foreach ($messages as $message) {
        $all_fortunes[] = [
            'category' => $category,
            'message' => $message,
        ];
    }
}

require_once(G5_THEME_PATH.'/modern/_head.inc.php');
include_once('./head.sub.php');
?>
<div class="m-shell">
    <?php require G5_THEME_PATH.'/modern/_nav.inc.php'; ?>
    <main class="m-container" style="padding: 32px 20px 48px;">
        <div class="fortune-wrapper">
            <h1 class="fortune-title">๐ŸŽฒ ์˜ค๋Š˜์˜ ์šด์„ธ</h1>
            <p class="fortune-subtitle">ํฌ์ถ˜ ์ฟ ํ‚ค๋ฅผ ๊นจ์„œ ์˜ค๋Š˜์˜ ์šด์„ธ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”!</p>
            
            <div class="fortune-cookie-container">
                <div class="fortune-cookie" id="fortuneCookie">
                    <span class="cookie-icon">๐Ÿฅ </span>
                </div>
            </div>
            
            <button class="fortune-button" id="drawFortuneBtn">
                ์šด์„ธ ๋ฝ‘๊ธฐ
            </button>
            
            <div class="fortune-result" id="fortuneResult" style="display: none;">
                <div class="fortune-card">
                    <div class="fortune-category" id="fortuneCategory"></div>
                    <div class="fortune-message" id="fortuneMessage"></div>
                    <button class="copy-button" id="copyBtn">๐Ÿ“‹ ์šด์„ธ ๋ณต์‚ฌํ•˜๊ธฐ</button>
                </div>
            </div>
        </div>
    </main>
    <?php require G5_THEME_PATH.'/modern/_footer.inc.php'; ?>
</div>

<style>
.fortune-wrapper {
    max-width: 600px;
    margin: 0 auto;
    text-align: center;
}

.fortune-title {
    font-size: 2.5rem;
    font-weight: 700;
    color: var(--m-text);
    margin-bottom: 0.5rem;
}

.fortune-subtitle {
    font-size: 1.1rem;
    color: var(--m-text-muted);
    margin-bottom: 3rem;
}

.fortune-cookie-container {
    margin: 3rem 0;
    perspective: 1000px;
}

.fortune-cookie {
    display: inline-block;
    transition: transform 0.3s ease;
}

.fortune-cookie:hover {
    transform: scale(1.1) rotate(5deg);
}

.fortune-cookie.crack {
    animation: crack 0.5s ease-out;
}

@keyframes crack {
    0% { transform: scale(1) rotate(0deg); }
    25% { transform: scale(1.2) rotate(-10deg); }
    50% { transform: scale(0.9) rotate(10deg); }
    75% { transform: scale(1.1) rotate(-5deg); }
    100% { transform: scale(1) rotate(0deg); }
}

.cookie-icon {
    font-size: 8rem;
    display: block;
    cursor: pointer;
}

.fortune-button {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border: none;
    padding: 1rem 3rem;
    font-size: 1.2rem;
    font-weight: 600;
    border-radius: var(--m-radius-lg);
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}

.fortune-button:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
}

.fortune-button:active {
    transform: translateY(0);
}

.fortune-result {
    margin-top: 3rem;
    animation: fadeIn 0.5s ease-in;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.fortune-card {
    background: var(--m-surface);
    border-radius: var(--m-radius-lg);
    padding: 2rem;
    box-shadow: var(--m-shadow);
}

.fortune-category {
    font-size: 1rem;
    color: var(--m-text-muted);
    margin-bottom: 1rem;
    text-transform: uppercase;
    letter-spacing: 1px;
}

.fortune-message {
    font-size: 1.5rem;
    color: var(--m-text);
    line-height: 1.6;
    margin-bottom: 1.5rem;
    font-weight: 500;
}

.copy-button {
    background: var(--m-surface);
    color: var(--m-text);
    border: 2px solid var(--m-text-muted);
    padding: 0.75rem 1.5rem;
    border-radius: var(--m-radius-lg);
    cursor: pointer;
    font-size: 1rem;
    transition: all 0.3s ease;
}

.copy-button:hover {
    background: var(--m-text-muted);
    color: var(--m-surface);
    transform: translateY(-2px);
}

@media (max-width: 768px) {
    .fortune-title {
        font-size: 2rem;
    }
    
    .cookie-icon {
        font-size: 6rem;
    }
    
    .fortune-button {
        padding: 0.875rem 2rem;
        font-size: 1rem;
    }
    
    .fortune-message {
        font-size: 1.25rem;
    }
}
</style>

<script>
// ์šด์„ธ ๋ฐ์ดํ„ฐ๋ฅผ JavaScript๋กœ ์ „๋‹ฌ
const fortuneData = <?php echo json_encode($all_fortunes, JSON_UNESCAPED_UNICODE); ?>;

const cookieEl = document.getElementById('fortuneCookie');
const drawBtn = document.getElementById('drawFortuneBtn');
const resultEl = document.getElementById('fortuneResult');
const categoryEl = document.getElementById('fortuneCategory');
const messageEl = document.getElementById('fortuneMessage');
const copyBtn = document.getElementById('copyBtn');

// ์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€ ์ด๋ฆ„ ๋งคํ•‘
const categoryNames = {
    'love': '๐Ÿ’• ์—ฐ์• ์šด',
    'money': '๐Ÿ’ฐ ์žฌ๋ฌผ์šด',
    'health': '๐Ÿƒ ๊ฑด๊ฐ•์šด',
    'study': '๐Ÿ“š ํ•™์—…์šด'
};

// ์šด์„ธ ๋ฝ‘๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ
drawBtn.addEventListener('click', function() {
    // ์ฟ ํ‚ค ๊นจ์ง€๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜
    cookieEl.classList.add('crack');
    
    setTimeout(() => {
        cookieEl.classList.remove('crack');
        
        // ๋žœ๋ค ์šด์„ธ ์„ ํƒ
        const randomIndex = Math.floor(Math.random() * fortuneData.length);
        const fortune = fortuneData[randomIndex];
        
        // ๊ฒฐ๊ณผ ํ‘œ์‹œ
        categoryEl.textContent = categoryNames[fortune.category];
        messageEl.textContent = fortune.message;
        resultEl.style.display = 'block';
        
        // ๊ฒฐ๊ณผ ์˜์—ญ์œผ๋กœ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์Šคํฌ๋กค
        setTimeout(() => {
            resultEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        }, 100);
    }, 500);
});

// ์šด์„ธ ๋ณต์‚ฌ ๋ฒ„ํŠผ ํด๋ฆญ
copyBtn.addEventListener('click', function() {
    const text = `${categoryEl.textContent}\n${messageEl.textContent}`;
    
    navigator.clipboard.writeText(text).then(() => {
        const originalText = copyBtn.textContent;
        copyBtn.textContent = 'โœ… ๋ณต์‚ฌ ์™„๋ฃŒ!';
        
        setTimeout(() => {
            copyBtn.textContent = originalText;
        }, 2000);
    }).catch(() => {
        alert('๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.');
    });
});
</script>

<?php include_once('./tail.sub.php'); ?>
```

์ด์ œ ๋ธŒ๋ผ์šฐ์ €์—์„œ `/fortune-cookie-generator`๋กœ ์ ‘์†ํ•˜๋ฉด ํฌ์ถ˜ ์ฟ ํ‚ค ์ƒ์„ฑ๊ธฐ๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: - `/fortune-cookie-generator` URL๋กœ ์ ‘์† ๊ฐ€๋Šฅ - modern shell์ด ์ ์šฉ๋œ ์ผ๊ด€๋œ ๋””์ž์ธ - ํฐ ์ฟ ํ‚ค ์ด๋ชจ์ง€(๐Ÿฅ )๊ฐ€ ์ค‘์•™์— ํ‘œ์‹œ๋จ - '์šด์„ธ ๋ฝ‘๊ธฐ' ๋ฒ„ํŠผ์ด ๋ณด๋ผ์ƒ‰ ๊ทธ๋ผ๋ฐ์ด์…˜์œผ๋กœ ํ‘œ์‹œ๋จ - ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์ฟ ํ‚ค๊ฐ€ ํ”๋“ค๋ฆฌ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ - ๋žœ๋ค ์šด์„ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์นด๋“œ ํ˜•ํƒœ๋กœ ๋‚˜ํƒ€๋‚จ - ์นดํ…Œ๊ณ ๋ฆฌ ์•„์ด์ฝ˜๊ณผ ํ•จ๊ป˜ ์šด์„ธ ํ‘œ์‹œ - '์šด์„ธ ๋ณต์‚ฌํ•˜๊ธฐ' ๋ฒ„ํŠผ ๋™์ž‘ - ๋‹คํฌ๋ชจ๋“œ ์ „ํ™˜ ์‹œ ์ž๋™์œผ๋กœ ์ƒ‰์ƒ ๋ณ€๊ฒฝ - ๋ชจ๋ฐ”์ผ์—์„œ๋„ ๋ ˆ์ด์•„์›ƒ์ด ๊นจ์ง€์ง€ ์•Š์Œ

2
Step 2
**2๋‹จ๊ณ„: localStorage๋กœ ์˜ค๋Š˜์˜ ์šด์„ธ ์ €์žฅ + ํžˆ์Šคํ† ๋ฆฌ ๊ธฐ๋Šฅ ์ถ”๊ฐ€**

๊ฐ™์€ ๋‚  ์—ฌ๋Ÿฌ ๋ฒˆ ์ ‘์†ํ•ด๋„ ๊ฐ™์€ ์šด์„ธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , ์ตœ๊ทผ 5๊ฐœ์˜ ์šด์„ธ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ํ•˜๋‹จ์— ํ‘œ์‹œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด๋ด…์‹œ๋‹ค.

`app/modules/fortune-cookie-generator/index.php` ํŒŒ์ผ์—์„œ `<script>` ๋ธ”๋ก์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜์„ธ์š”:

```javascript
<script>
// ์šด์„ธ ๋ฐ์ดํ„ฐ๋ฅผ JavaScript๋กœ ์ „๋‹ฌ
const fortuneData = <?php echo json_encode($all_fortunes, JSON_UNESCAPED_UNICODE); ?>;

const cookieEl = document.getElementById('fortuneCookie');
const drawBtn = document.getElementById('drawFortuneBtn');
const resultEl = document.getElementById('fortuneResult');
const categoryEl = document.getElementById('fortuneCategory');
const messageEl = document.getElementById('fortuneMessage');
const copyBtn = document.getElementById('copyBtn');

// ์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€ ์ด๋ฆ„ ๋งคํ•‘
const categoryNames = {
    'love': '๐Ÿ’• ์—ฐ์• ์šด',
    'money': '๐Ÿ’ฐ ์žฌ๋ฌผ์šด',
    'health': '๐Ÿƒ ๊ฑด๊ฐ•์šด',
    'study': '๐Ÿ“š ํ•™์—…์šด'
};

// ์˜ค๋Š˜ ๋‚ ์งœ ๊ตฌํ•˜๊ธฐ (YYYY-MM-DD ํ˜•์‹)
function getTodayDate() {
    const today = new Date();
    return today.toISOString().split('T')[0];
}

// ์˜ค๋Š˜์˜ ์šด์„ธ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
function getTodayFortune() {
    const saved = localStorage.getItem('todayFortune');
    if (saved) {
        const data = JSON.parse(saved);
        if (data.date === getTodayDate()) {
            return data.fortune;
        }
    }
    return null;
}

// ์˜ค๋Š˜์˜ ์šด์„ธ ์ €์žฅํ•˜๊ธฐ
function saveTodayFortune(fortune) {
    const data = {
        date: getTodayDate(),
        fortune: fortune,
        timestamp: new Date().getTime()
    };
    localStorage.setItem('todayFortune', JSON.stringify(data));
    
    // ํžˆ์Šคํ† ๋ฆฌ์—๋„ ์ถ”๊ฐ€
    addToHistory(fortune);
}

// ํžˆ์Šคํ† ๋ฆฌ์— ์ถ”๊ฐ€
function addToHistory(fortune) {
    let history = JSON.parse(localStorage.getItem('fortuneHistory') || '[]');
    
    // ์ค‘๋ณต ๋ฐฉ์ง€ (๊ฐ™์€ ๋‚ ์งœ์˜ ์šด์„ธ๋Š” ํ•˜๋‚˜๋งŒ)
    history = history.filter(item => item.date !== getTodayDate());
    
    // ์ƒˆ ์šด์„ธ๋ฅผ ๋งจ ์•ž์— ์ถ”๊ฐ€
    history.unshift({
        date: getTodayDate(),
        ...fortune
    });
    
    // ์ตœ๋Œ€ 5๊ฐœ๊นŒ์ง€๋งŒ ์œ ์ง€
    if (history.length > 5) {
        history = history.slice(0, 5);
    }
    
    localStorage.setItem('fortuneHistory', JSON.stringify(history));
    displayHistory();
}

// ํžˆ์Šคํ† ๋ฆฌ ํ‘œ์‹œ
function displayHistory() {
    const history = JSON.parse(localStorage.getItem('fortuneHistory') || '[]');
    const historyEl = document.getElementById('fortuneHistory');
    
    if (history.length === 0) {
        historyEl.style.display = 'none';
        return;
    }
    
    historyEl.style.display = 'block';
    const listEl = document.getElementById('historyList');
    listEl.innerHTML = '';
    
    history.forEach(item => {
        const li = document.createElement('div');
        li.className = 'history-item';
        li.innerHTML = `
            <div class="history-date">${item.date}</div>
            <div class="history-category">${categoryNames[item.category]}</div>
            <div class="history-message">${item.message}</div>
        `;
        listEl.appendChild(li);
    });
}

// ์šด์„ธ ํ‘œ์‹œ ํ•จ์ˆ˜
function displayFortune(fortune) {
    categoryEl.textContent = categoryNames[fortune.category];
    messageEl.textContent = fortune.message;
    resultEl.style.display = 'block';
    
    setTimeout(() => {
        resultEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }, 100);
}

// ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ ์˜ค๋Š˜์˜ ์šด์„ธ๊ฐ€ ์žˆ์œผ๋ฉด ๋ฐ”๋กœ ํ‘œ์‹œ
window.addEventListener('DOMContentLoaded', function() {
    const todayFortune = getTodayFortune();
    if (todayFortune) {
        displayFortune(todayFortune);
        drawBtn.textContent = '๋‹ค์‹œ ๋ณด๊ธฐ';
    }
    
    // ํžˆ์Šคํ† ๋ฆฌ ํ‘œ์‹œ
    displayHistory();
});

// ์šด์„ธ ๋ฝ‘๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ
drawBtn.addEventListener('click', function() {
    // ์ด๋ฏธ ์˜ค๋Š˜์˜ ์šด์„ธ๊ฐ€ ์žˆ์œผ๋ฉด ๋‹ค์‹œ ํ‘œ์‹œ๋งŒ
    const existingFortune = getTodayFortune();
    if (existingFortune) {
        displayFortune(existingFortune);
        return;
    }
    
    // ์ฟ ํ‚ค ๊นจ์ง€๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜
    cookieEl.classList.add('crack');
    
    setTimeout(() => {
        cookieEl.classList.remove('crack');
        
        // ๋žœ๋ค ์šด์„ธ ์„ ํƒ
        const randomIndex = Math.floor(Math.random() * fortuneData.length);
        const fortune = fortuneData[randomIndex];
        
        // ์˜ค๋Š˜์˜ ์šด์„ธ๋กœ ์ €์žฅ
        saveTodayFortune(fortune);
        
        // ๊ฒฐ๊ณผ ํ‘œ์‹œ
        displayFortune(fortune);
        
        // ๋ฒ„ํŠผ ํ…์ŠคํŠธ ๋ณ€๊ฒฝ
        drawBtn.textContent = '๋‹ค์‹œ ๋ณด๊ธฐ';
    }, 500);
});

// ์šด์„ธ ๋ณต์‚ฌ ๋ฒ„ํŠผ ํด๋ฆญ
copyBtn.addEventListener('click', function() {
    const text = `${categoryEl.textContent}\n${messageEl.textContent}`;
    
    navigator.clipboard.writeText(text).then(() => {
        const originalText = copyBtn.textContent;
        copyBtn.textContent = 'โœ… ๋ณต์‚ฌ ์™„๋ฃŒ!';
        
        setTimeout(() => {
            copyBtn.textContent = originalText;
        }, 2000);
    }).catch(() => {
        alert('๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.');
    });
});
</script>
```

๊ทธ๋ฆฌ๊ณ  `</main>` ํƒœ๊ทธ ๋ฐ”๋กœ ์œ„์— ํžˆ์Šคํ† ๋ฆฌ ์„น์…˜์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

```php
            <div class="fortune-history" id="fortuneHistory" style="display: none;">
                <h2 class="history-title">๐Ÿ“œ ์ตœ๊ทผ ์šด์„ธ ๊ธฐ๋ก</h2>
                <div id="historyList" class="history-list"></div>
            </div>
        </div>
    </main>
```

๋งˆ์ง€๋ง‰์œผ๋กœ `<style>` ๋ธ”๋ก์— ํžˆ์Šคํ† ๋ฆฌ ์Šคํƒ€์ผ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

```css
.fortune-history {
    margin-top: 4rem;
    padding-top: 3rem;
    border-top: 1px solid var(--m-text-muted);
}

.history-title {
    font-size: 1.5rem;
    color: var(--m-text);
    margin-bottom: 1.5rem;
}

.history-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.history-item {
    background: var(--m-surface);
    border-radius: var(--m-radius-lg);
    padding: 1rem 1.5rem;
    box-shadow: var(--m-shadow);
    text-align: left;
    transition: transform 0.2s ease;
}

.history-item:hover {
    transform: translateX(5px);
}

.history-date {
    font-size: 0.875rem;
    color: var(--m-text-muted);
    margin-bottom: 0.5rem;
}

.history-category {
    font-size: 0.875rem;
    color: var(--m-text-muted);
    margin-bottom: 0.5rem;
}

.history-message {
    font-size: 1rem;
    color: var(--m-text);
    line-height: 1.5;
}
```

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: - ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ๊ณ ์นจํ•ด๋„ ์˜ค๋Š˜ ๋ฝ‘์€ ์šด์„ธ๊ฐ€ ๊ทธ๋Œ€๋กœ ํ‘œ์‹œ๋จ - ๊ฐ™์€ ๋‚  ์—ฌ๋Ÿฌ ๋ฒˆ '์šด์„ธ ๋ฝ‘๊ธฐ'๋ฅผ ๋ˆŒ๋Ÿฌ๋„ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ด - ๋ฒ„ํŠผ ํ…์ŠคํŠธ๊ฐ€ '๋‹ค์‹œ ๋ณด๊ธฐ'๋กœ ๋ณ€๊ฒฝ๋จ - ํ•˜๋‹จ์— '์ตœ๊ทผ ์šด์„ธ ๊ธฐ๋ก' ์„น์…˜์ด ๋‚˜ํƒ€๋‚จ - ์ตœ๊ทผ 5๊ฐœ์˜ ์šด์„ธ๊ฐ€ ๋‚ ์งœ์™€ ํ•จ๊ป˜ ํ‘œ์‹œ๋จ - ๋‹ค์Œ ๋‚  ์ ‘์†ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์šด์„ธ๋ฅผ ๋ฝ‘์„ ์ˆ˜ ์žˆ์Œ - ํžˆ์Šคํ† ๋ฆฌ ํ•ญ๋ชฉ์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ์‚ด์ง ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™ํ•˜๋Š” ํšจ๊ณผ

3
Step 3
**3๋‹จ๊ณ„: ํ–‰์šด์˜ ์ˆซ์ž/์ƒ‰์ƒ ์ถ”๊ฐ€ + ๋ฐฐ๊ฒฝ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ**

์šด์„ธ์™€ ํ•จ๊ป˜ ํ–‰์šด์˜ ์ˆซ์ž์™€ ์ƒ‰์ƒ์„ ๋ณด์—ฌ์ฃผ๊ณ , ๋ฐฐ๊ฒฝ์— ๋– ๋‹ค๋‹ˆ๋Š” ๋ณ„ ํšจ๊ณผ๋ฅผ ์ถ”๊ฐ€ํ•ด๋ด…์‹œ๋‹ค.

๋จผ์ € PHP ๋ถ€๋ถ„์—์„œ ์šด์„ธ ๋ฐ์ดํ„ฐ์— ํ–‰์šด์˜ ์ˆซ์ž์™€ ์ƒ‰์ƒ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. `$all_fortunes` ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •:

```php
// ๋ชจ๋“  ์šด์„ธ๋ฅผ ํ•˜๋‚˜์˜ ๋ฐฐ์—ด๋กœ ํ•ฉ์น˜๊ธฐ (ํ–‰์šด์˜ ์ˆซ์ž/์ƒ‰์ƒ ์ถ”๊ฐ€)
$all_fortunes = [];
$lucky_colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E2'];

foreach ($fortunes as $category => $messages) {
    foreach ($messages as $message) {
        $all_fortunes[] = [
            'category' => $category,
            'message' => $message,
            'luckyNumber' => rand(1, 99),
            'luckyColor' => $lucky_colors[array_rand($lucky_colors)],
        ];
    }
}
```

๊ทธ๋ฆฌ๊ณ  ์šด์„ธ ์นด๋“œ HTML์— ํ–‰์šด์˜ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•  ์˜์—ญ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”. `fortune-card` ์•ˆ์ชฝ์„ ์ˆ˜์ •:

```php
            <div class="fortune-result" id="fortuneResult" style="display: none;">
                <div class="fortune-card">
                    <div class="fortune-category" id="fortuneCategory"></div>
                    <div class="fortune-message" id="fortuneMessage"></div>
                    
                    <div class="lucky-info">
                        <div class="lucky-item">
                            <span class="lucky-label">๐Ÿ€ ํ–‰์šด์˜ ์ˆซ์ž</span>
                            <span class="lucky-value" id="luckyNumber"></span>
                        </div>
                        <div class="lucky-item">
                            <span class="lucky-label">๐ŸŽจ ํ–‰์šด์˜ ์ƒ‰์ƒ</span>
                            <span class="lucky-color-box" id="luckyColorBox"></span>
                        </div>
                    </div>
                    
                    <button class="copy-button" id="copyBtn">๐Ÿ“‹ ์šด์„ธ ๋ณต์‚ฌํ•˜๊ธฐ</button>
                </div>
            </div>
```

์Šคํƒ€์ผ์— ํ–‰์šด์˜ ์ •๋ณด์™€ ๋ฐฐ๊ฒฝ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”:

```css
/* ๋ฐฐ๊ฒฝ ๋ณ„ ์• ๋‹ˆ๋ฉ”์ด์…˜ */
.fortune-wrapper {
    max-width: 600px;
    margin: 0 auto;
    text-align: center;
    position: relative;
}

.fortune-wrapper::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: 
        radial-gradient(2px 2px at 20% 30%, white, transparent),
        radial-gradient(2px 2px at 60% 70%, white, transparent),
        radial-gradient(1px 1px at 50% 50%, white, transparent),
        radial-gradient(1px 1px at 80% 10%, white, transparent),
        radial-gradient(2px 2px at 90% 60%, white, transparent),
        radial-gradient(1px 1px at 33% 90%, white, transparent);
    background-size: 200% 200%;
    animation: stars 20s ease-in-out infinite;
    opacity: 0.3;
    pointer-events: none;
    z-index: -1;
}

@keyframes stars {
    0%, 100% { background-position: 0% 0%; }
    50% { background-position: 100% 100%; }
}

/* ํ–‰์šด์˜ ์ •๋ณด ์Šคํƒ€์ผ */
.lucky-info {
    display: flex;
    gap: 1rem;
    justify-content: center;
    margin: 1.5rem 0;
    padding: 1rem;
    background: rgba(102, 126, 234, 0.1);
    border-radius: var(--m-radius-lg);
}

.lucky-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
}

.lucky-label {
    font-size: 0.875rem;
    color: var(--m-text-muted);
}

.lucky-value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--m-text);
}

.lucky-color-box {
    width: 40px;
    height: 40px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.2);
    border: 2px solid var(--m-surface);
}

@media (max-width: 768px) {
    .lucky-info {
        flex-direction: column;
        gap: 1rem;
    }
}
```

JavaScript์—์„œ ํ–‰์šด์˜ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•˜๋„๋ก ์ˆ˜์ •ํ•˜์„ธ์š”. `displayFortune` ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •:

```javascript
// ์šด์„ธ ํ‘œ์‹œ ํ•จ์ˆ˜
function displayFortune(fortune) {
    categoryEl.textContent = categoryNames[fortune.category];
    messageEl.textContent = fortune.message;
    
    // ํ–‰์šด์˜ ์ˆซ์ž์™€ ์ƒ‰์ƒ ํ‘œ์‹œ
    document.getElementById('luckyNumber').textContent = fortune.luckyNumber;
    const colorBox = document.getElementById('luckyColorBox');
    colorBox.style.backgroundColor = fortune.luckyColor;
    
    resultEl.style.display = 'block';
    
    setTimeout(() => {
        resultEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }, 100);
}
```

๋ณต์‚ฌ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ–‰์šด์˜ ์ •๋ณด๋„ ํ•จ๊ป˜ ๋ณต์‚ฌ๋˜๋„๋ก ์ˆ˜์ •:

```javascript
// ์šด์„ธ ๋ณต์‚ฌ ๋ฒ„ํŠผ ํด๋ฆญ
copyBtn.addEventListener('click', function() {
    const luckyNumber = document.getElementById('luckyNumber').textContent;
    const text = `${categoryEl.textContent}\n${messageEl.textContent}\n\n๐Ÿ€ ํ–‰์šด์˜ ์ˆซ์ž: ${luckyNumber}`;
    
    navigator.clipboard.writeText(text).then(() => {
        const originalText = copyBtn.textContent;
        copyBtn.textContent = 'โœ… ๋ณต์‚ฌ ์™„๋ฃŒ!';
        
        setTimeout(() => {
            copyBtn.textContent = originalText;
        }, 2000);
    }).catch(() => {
        alert('๋ณต์‚ฌ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์‹œ๋„ํ•ด์ฃผ์„ธ์š”.');
    });
});
```

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ: - ์šด์„ธ ๊ฒฐ๊ณผ์— ํ–‰์šด์˜ ์ˆซ์ž๊ฐ€ ํฐ ๊ธ€์”จ๋กœ ํ‘œ์‹œ๋จ - ํ–‰์šด์˜ ์ƒ‰์ƒ์ด ์ปฌ๋Ÿฌ ๋ฐ•์Šค๋กœ ์‹œ๊ฐ์ ์œผ๋กœ ํ‘œ์‹œ๋จ - ๋ฐฐ๊ฒฝ์— ์€์€ํ•˜๊ฒŒ ๋– ๋‹ค๋‹ˆ๋Š” ๋ณ„ ํšจ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚จ - ๋ณ„๋“ค์ด ์ฒœ์ฒœํžˆ ์›€์ง์ด๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ - ์šด์„ธ ๋ณต์‚ฌ ์‹œ ํ–‰์šด์˜ ์ˆซ์ž๋„ ํ•จ๊ป˜ ๋ณต์‚ฌ๋จ - ๋ชจ๋ฐ”์ผ์—์„œ๋Š” ํ–‰์šด์˜ ์ •๋ณด๊ฐ€ ์„ธ๋กœ๋กœ ๋ฐฐ์น˜๋จ - ๋‹คํฌ๋ชจ๋“œ์—์„œ๋„ ๋ณ„ ํšจ๊ณผ๊ฐ€ ๋ณด์ž„ (ํˆฌ๋ช…๋„๋กœ ์กฐ์ ˆ) - ์ „์ฒด์ ์œผ๋กœ ๋” ํ’์„ฑํ•˜๊ณ  ์žฌ๋ฏธ์žˆ๋Š” UI ์™„์„ฑ

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

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

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

๋Œ“๊ธ€ (0)

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