๐ฏ g5se ๋๋ค ํฌ์ถ ์ฟ ํค ๋ฉ์์ง ์์ฑ๊ธฐ - ์ค๋์ ํ์ด ๋ฉ์์ง & ๊ณต์ ํ๊ธฐ
g5se-fortune-cookie-message-generator
๋ฌธ์ ์ค๋ช
๐ฅ ํ๋ก์ ํธ ๊ฐ์
์ค๊ตญ์ง์์ ๋ฐ๋ ํฌ์ถ ์ฟ ํค์ฒ๋ผ, ๋๋คํ ํ์ด ๋ฉ์์ง๋ฅผ ์์ฑํ๊ณ ๊ณต์ ํ ์ ์๋ ์ฌ๋ฏธ์๋ ์น ํ์ด์ง๋ฅผ ๋ง๋ญ๋๋ค. ์ฌ์ฉ์๊ฐ "์ฟ ํค ๊นจ๊ธฐ" ๋ฒํผ์ ๋๋ฅด๋ฉด ์ฌ๋ฏธ์๋ ์ ๋๋ฉ์ด์ ๊ณผ ํจ๊ป ํ์ด์ ๋ฉ์์ง๊ฐ ๋ํ๋๊ณ , ๋ง์์ ๋๋ ๋ฉ์์ง๋ ํ์คํ ๋ฆฌ์ ์ ์ฅํ ์ ์์ต๋๋ค.
โจ ํ์ ๊ธฐ๋ฅ
-
๋๋ค ๋ฉ์์ง ์์ฑ
- "์ฟ ํค ๊นจ๊ธฐ" ๋ฒํผ ํด๋ฆญ ์ ๋๋ค ๋ฉ์์ง ํ์
- ๋ค์ํ ์นดํ ๊ณ ๋ฆฌ์ ๋ฉ์์ง ํ (ํ์ด, ์ฌ๋, ์ฑ๊ณต, ์ฌ๋ฏธ, ์งํ ๋ฑ)
- ๊ฐ ๋ฉ์์ง๋ง๋ค ๊ณ ์ ํ "ํ์ด ๋ฒํธ" (1~99) ์๋ ์์ฑ
-
์๊ฐ์ ์ธํฐ๋์
- ์ฟ ํค ์ด๋ฏธ์ง ํด๋ฆญ ์ ๊นจ์ง๋ ์ ๋๋ฉ์ด์ ํจ๊ณผ
- ๋ฉ์์ง ์นด๋๊ฐ ๋ถ๋๋ฝ๊ฒ ๋ํ๋๋ fade-in ํจ๊ณผ
- ์นดํ ๊ณ ๋ฆฌ๋ณ ์์ ๊ตฌ๋ถ (ํ์ด=๊ธ์, ์ฌ๋=๋ถํ, ์ฑ๊ณต=ํ๋ ๋ฑ)
-
๋ฉ์์ง ํ์คํ ๋ฆฌ
- SQLite DB์ ๋ฐ์ ๋ฉ์์ง ์๋ ์ ์ฅ (ํ์์คํฌํ ํฌํจ)
- ์ต๊ทผ ๋ฐ์ ๋ฉ์์ง 10๊ฐ ๋ชฉ๋ก ํ์
- ๊ฐ ๋ฉ์์ง ์์ ๋ฐ์ ๋ ์ง/์๊ฐ ํ์
-
๊ณต์ ๊ธฐ๋ฅ
- ํ์ฌ ๋ฉ์์ง๋ฅผ ํ ์คํธ๋ก ๋ณต์ฌํ๋ ๋ฒํผ
- "์ค๋์ ํ์ด: [๋ฉ์์ง] #ํ์ด๋ฒํธXX" ํ์์ผ๋ก ๋ณต์ฌ
๐ ๋ณด๋์ค ๊ธฐ๋ฅ
- ๋ฉ์์ง ์นดํ ๊ณ ๋ฆฌ ํํฐ (ํน์ ์ฃผ์ ๋ง ๋ณด๊ธฐ)
- ์ฆ๊ฒจ์ฐพ๊ธฐ ๊ธฐ๋ฅ (๋ง์์ ๋๋ ๋ฉ์์ง ๋ณํ ํ์)
- ํ๋ฃจ์ ๋ฐ์ ์ ์๋ ๋ฉ์์ง ๊ฐ์ ์ ํ (์: 3๊ฐ) ๋ฐ ์นด์ดํธ๋ค์ด ํ์ด๋จธ
- ๋ฉ์์ง์ ์ด์ธ๋ฆฌ๋ ์ด๋ชจ์ง ์๋ ์ถ๊ฐ
- ๋คํฌ๋ชจ๋์์ ์ฟ ํค ์ด๋ฏธ์ง ์์ ๋ฐ์
๐จ ๋์์ธ ์๊ตฌ์ฌํญ
- modern shell ์ ์ฉ์ผ๋ก ์ฌ์ดํธ ๋ค๋น๊ฒ์ด์ ํต์ผ
- ๋์์ธ ํ ํฐ(
--m-surface,--m-text๋ฑ) ์ฌ์ฉ์ผ๋ก ๋คํฌ๋ชจ๋ ์๋ ๋์ - ์ฟ ํค ์ด๋ฏธ์ง๋ ์ค์ ๋ฐฐ์น, ํด๋ฆญ ์ ๋ ์ ๋๋ฉ์ด์ (์ด์ง ํ๋ค๋ฆผ)
- ๋ฉ์์ง ์นด๋๋ ๊ทธ๋ฆผ์ ํจ๊ณผ๋ก ์ ์ฒด๊ฐ ํํ
- ๋ชจ๋ฐ์ผ์์๋ ํฐ์นํ๊ธฐ ํธํ ํฐ ๋ฒํผ ํฌ๊ธฐ
๐ ๊ธฐ์ ์คํ
- ๋ฐฑ์๋: ์์ PHP (g5se ์ปจ๋ฒค์ )
- ๋ฐ์ดํฐ๋ฒ ์ด์ค: SQLite (
G5_DATA_PATH/modules/fortune-cookie.sqlite) - ํ๋ก ํธ์๋: HTML/CSS/JavaScript (CDN ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด ์์ ๊ตฌํ)
- UI ํ๋ ์์ํฌ: g5se modern shell + ๋์์ธ ํ ํฐ
๐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง
CREATE TABLE messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT NOT NULL,
content TEXT NOT NULL,
lucky_number INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
is_favorite INTEGER DEFAULT 0
);
๐ฏ ํ์ต ๋ชฉํ
- g5se ํด๋ ๊ธฐ๋ฐ ์๋ ๋ผ์ฐํ ์ดํด
- modern shell์ ํ์ฉํ ์ผ๊ด๋ UI ๊ตฌ์ฑ
- SQLite๋ฅผ ์ด์ฉํ ๊ฐ๋จํ CRUD ๊ตฌํ
- CSS ์ ๋๋ฉ์ด์ ์ผ๋ก ์ฌ์ฉ์ ๊ฒฝํ ํฅ์
- JavaScript๋ก ๋์ ์ธํฐ๋์ ๊ตฌํ (AJAX ์์ด ํ์ด์ง ์๋ก๊ณ ์นจ ๋ฐฉ์)
์ ์ฝ ์กฐ๊ฑด
- โข g5se๊ฐ ์ค์น๋ ํ๊ฒฝ์์ ์์ (https://github.com/gnuboard/g5se main ๋ธ๋์น)
- โข ํด๋ ๊ธฐ๋ฐ ์๋ ๋ผ์ฐํ ์ฌ์ฉ (app/router.php์ ๋ผ์ฐํธ ๋ฑ๋ก ๊ธ์ง)
- โข modern shell (_head.inc.php + m-shell + _nav.inc.php + m-container + _footer.inc.php) ํ์ ์ ์ฉ
- โข ๋์์ธ ํ ํฐ (--m-surface, --m-text, --m-shadow ๋ฑ) ์ฌ์ฉ์ผ๋ก ๋คํฌ๋ชจ๋ ์๋ ๋์
- โข SQLite ํ์ผ ์์น: G5_DATA_PATH/modules/fortune-cookie.sqlite
- โข ์ฒซ ์ ๊ทผ ์ ํ ์ด๋ธ ์๋ ์์ฑ (CREATE TABLE IF NOT EXISTS)
- โข prepared statement๋ก SQL ์ธ์ ์ ๋ฐฉ์ง
- โข ์ฌ์ฉ์ ์ ๋ ฅ ์ถ๋ ฅ ์ htmlspecialchars() ์ด์ค์ผ์ดํ ํ์
- โข ์ธ๋ถ ๋น๋ ๋๊ตฌ(npm/vite) ์ฌ์ฉ ๊ธ์ง
- โข CDN ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ๊ธ์ง (์์ HTML/CSS/JS๋ง)
- โข Laravel/Composer/React/Vue/SPA ํ๋ ์์ํฌ ์ ๋ ์ฌ์ฉ ๊ธ์ง
ํ๋กฌํํธ ๋ ์ํผ
์๋ ํ๋กฌํํธ๋ฅผ ์์๋๋ก AI์๊ฒ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค. ๋ณต์ฌ ๋ฒํผ์ ๋๋ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์.
g5se๊ฐ ์ค์น๋ ๋๋ ํฐ๋ฆฌ(๋ฃจํธ์ `index.php`ยท`app/`์ด ์๋ ๊ณณ)์์ ์์
์ ์์ํฉ๋๋ค. (g5se ์ค์น๋ https://github.com/gnuboard/g5se ์ฐธ๊ณ )
**Step 1: ํ๋ก์ ํธ ํด๋ ์์ฑ ๋ฐ ๊ธฐ๋ณธ ํ์ด์ง ๊ตฌ์กฐ ๋ง๋ค๊ธฐ**
1. `app/modules/fortune-cookie/index.php` ํ์ผ์ ์์ฑํ์ธ์.
2. ํ์ผ ๋งจ ์์ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํ์ธ์:
```php
<?php
include_once('./_common.php');
// ํ์ด์ง ์ ๋ชฉ
$g5['title'] = 'ํฌ์ถ ์ฟ ํค ๋ฉ์์ง ์์ฑ๊ธฐ';
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 style="max-width: 600px; margin: 0 auto; text-align: center;">
<h1 style="font-size: 2rem; margin-bottom: 1rem; color: var(--m-text);">๐ฅ ํฌ์ถ ์ฟ ํค</h1>
<p style="color: var(--m-text-muted); margin-bottom: 2rem;">์ฟ ํค๋ฅผ ๊นจ์ ์ค๋์ ํ์ด ๋ฉ์์ง๋ฅผ ๋ฐ์๋ณด์ธ์!</p>
<div style="margin: 3rem 0;">
<div style="font-size: 8rem; cursor: pointer; user-select: none;">๐ฅ </div>
<button type="button" style="
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 1rem 2rem;
font-size: 1.1rem;
border-radius: var(--m-radius-lg);
cursor: pointer;
margin-top: 1rem;
box-shadow: var(--m-shadow);
">์ฟ ํค ๊นจ๊ธฐ</button>
</div>
<div style="
background: var(--m-surface);
border-radius: var(--m-radius-lg);
padding: 2rem;
margin-top: 2rem;
box-shadow: var(--m-shadow);
display: none;
">
<p style="font-size: 1.2rem; color: var(--m-text); margin-bottom: 1rem;">ํ์ด ๋ฉ์์ง๊ฐ ์ฌ๊ธฐ์ ํ์๋ฉ๋๋ค</p>
<p style="color: var(--m-text-muted); font-size: 0.9rem;">ํ์ด ๋ฒํธ: #00</p>
</div>
</div>
</main>
<?php require G5_THEME_PATH.'/modern/_footer.inc.php'; ?>
</div>
<?php include_once('./tail.sub.php'); ?>
```
3. ๋ธ๋ผ์ฐ์ ์์ `/fortune-cookie`๋ก ์ ์ํ์ฌ ๊ธฐ๋ณธ ๋ ์ด์์์ด ํ์๋๋์ง ํ์ธํ์ธ์.
**ํ์ธ ์ฌํญ:**
- modern shell์ ๋ค๋น๊ฒ์ด์
๊ณผ ํธํฐ๊ฐ ์๋์ผ๋ก ํ์๋๋๊ฐ?
- ๋คํฌ๋ชจ๋ ํ ๊ธ ์ ๋ฐฐ๊ฒฝ์๊ณผ ํ
์คํธ ์์์ด ์๋์ผ๋ก ๋ณ๊ฒฝ๋๋๊ฐ?
- ์ฟ ํค ์ด๋ชจ์ง์ "์ฟ ํค ๊นจ๊ธฐ" ๋ฒํผ์ด ์ค์์ ๋ฐฐ์น๋์ด ์๋๊ฐ?
๊ธฐ๋ ๊ฒฐ๊ณผ: - `/fortune-cookie` ๊ฒฝ๋ก๋ก ์ ๊ทผ ๊ฐ๋ฅํ ํ์ด์ง ์์ฑ ์๋ฃ - modern shell์ด ์ ์ฉ๋์ด ์ฌ์ดํธ ๋ค๋น๊ฒ์ด์ /ํธํฐ ํ์ - ์ฟ ํค ์ด๋ชจ์ง์ ๋ฒํผ์ด ์ค์ ์ ๋ ฌ๋ ๊ธฐ๋ณธ UI - ๋ฉ์์ง ์นด๋ ์์ญ์ ์จ๊ฒจ์ง ์ํ (display: none) - ๋คํฌ๋ชจ๋ ์ ํ ์ ๋ฐฐ๊ฒฝ/ํ ์คํธ ์์ ์๋ ๋ณ๊ฒฝ
**Step 2: SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ ๋ฐ ๋ฉ์์ง ๋ฐ์ดํฐ ์ค๋น**
1. `app/modules/fortune-cookie/index.php` ํ์ผ์ `include_once('./_common.php');` ๋ฐ๋ก ์๋์ ๋ค์ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ธ์:
```php
// SQLite DB ์ฐ๊ฒฐ ๋ฐ ํ
์ด๋ธ ์์ฑ
@mkdir(G5_DATA_PATH.'/modules', 0707, true);
$db_path = G5_DATA_PATH.'/modules/fortune-cookie.sqlite';
$db = new PDO('sqlite:'.$db_path);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// ํ
์ด๋ธ ์์ฑ (์ฒซ ์ ๊ทผ ์)
$db->exec("
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT NOT NULL,
content TEXT NOT NULL,
lucky_number INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
is_favorite INTEGER DEFAULT 0
)
");
// ๋ฉ์์ง ํ (์นดํ
๊ณ ๋ฆฌ๋ณ)
$message_pool = [
'fortune' => [
'์ค๋์ ์์์น ๋ชปํ ํ์ด์ด ์ฐพ์์ฌ ๊ฒ์
๋๋ค.',
'์์ ๊ธฐํ๊ฐ ํฐ ์ฑ๊ณต์ผ๋ก ์ด์ด์ง ๊ฒ์
๋๋ค.',
'๋น์ ์ ๊ธ์ ์ ์ธ ์๋์ง๊ฐ ์ฃผ๋ณ์ ๋ฐ๊ฒ ๋ง๋ญ๋๋ค.',
'๊ณง ์ข์ ์์์ด ๋ค๋ ค์ฌ ๊ฒ์
๋๋ค.',
'์ค๋ ๋ง๋๋ ์ฌ๋์ด ๋น์ ์๊ฒ ํ์ด์ ๊ฐ์ ธ๋ค์ค ๊ฒ์
๋๋ค.'
],
'love' => [
'์ง์ฌ์ ์ธ์ ๋ ํตํฉ๋๋ค. ์ฉ๊ธฐ๋ฅผ ๋ด๋ณด์ธ์.',
'์ค๋์ ์์คํ ์ฌ๋์๊ฒ ๊ฐ์ฌ๋ฅผ ํํํ๊ธฐ ์ข์ ๋ ์
๋๋ค.',
'๋น์ ์ ๋ฏธ์๊ฐ ๋๊ตฐ๊ฐ์ ํ๋ฃจ๋ฅผ ๋ฐ๊ฒ ๋ง๋ค ๊ฒ์
๋๋ค.',
'์ฌ๋์ ๊ฐ๊น์ด ๊ณณ์ ์์ต๋๋ค. ์ฃผ๋ณ์ ๋๋ฌ๋ณด์ธ์.',
'๋ฐ๋ปํ ๋ง ํ๋ง๋๊ฐ ํฐ ๋ณํ๋ฅผ ๋ง๋ญ๋๋ค.'
],
'success' => [
'๋
ธ๋ ฅ์ ์ ๋ ๋ฐฐ์ ํ์ง ์์ต๋๋ค. ๊ณ์ ๋์๊ฐ์ธ์.',
'์ค๋ ์์ํ ์ผ์ด ํฐ ์ฑ๊ณผ๋ก ์ด์ด์ง ๊ฒ์
๋๋ค.',
'๋น์ ์ ์ฌ๋ฅ์ด ๋น์ ๋ฐํ ์๊ฐ์ด ๋ค๊ฐ์ต๋๋ค.',
'์์ ์ฑ๊ณต๋ค์ด ๋ชจ์ฌ ํฐ ๊ฟ์ ์ด๋ฃน๋๋ค.',
'๋์ ์ ๋๋ ค์ํ์ง ๋ง์ธ์. ๋น์ ์ ํด๋ผ ์ ์์ต๋๋ค.'
],
'wisdom' => [
'๋๋ก๋ ์ฒ์ฒํ ๊ฐ๋ ๊ฒ์ด ๋ ๋น ๋ฅธ ๊ธธ์
๋๋ค.',
'์คํจ๋ ์ฑ๊ณต์ ์ด๋จธ๋์
๋๋ค. ํฌ๊ธฐํ์ง ๋ง์ธ์.',
'์ค๋ ๋ฐฐ์ด ์์ ๊ตํ์ด ๋ด์ผ์ ํฐ ์งํ๊ฐ ๋ฉ๋๋ค.',
'๊ฒฝ์ฒญ์ ์ต๊ณ ์ ๋ํ ๊ธฐ์ ์
๋๋ค.',
'๋ณํ๋ ๋ถํธํ์ง๋ง, ์ฑ์ฅ์ ์์์
๋๋ค.'
],
'fun' => [
'์ค๋์ ์ข์ํ๋ ์์์ ๋ง์๊ป ์ฆ๊ฒจ๋ณด์ธ์!',
'๊ฐ๋์ ์๋ฌด ์ด์ ์์ด ์ถค์ถฐ๋ ๊ด์ฐฎ์ต๋๋ค.',
'์์์ ์ต๊ณ ์ ๋ช
์ฝ์
๋๋ค. ์ค๋ ๋ง์ด ์์ผ์ธ์.',
'์ค๋ ํ๋ฃจ๋ ๋น์ ์ด ์ฃผ์ธ๊ณต์
๋๋ค!',
'์์ ํ๋ณต์ ์ฐพ๋ ๊ฒ์ด ์ง์ง ํ๋ณต์ ๋น๊ฒฐ์
๋๋ค.'
]
];
// ์ฟ ํค ๊นจ๊ธฐ ๋ฒํผ ํด๋ฆญ ์ ์ฒ๋ฆฌ
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['break_cookie'])) {
// ๋๋ค ์นดํ
๊ณ ๋ฆฌ ์ ํ
$categories = array_keys($message_pool);
$random_category = $categories[array_rand($categories)];
// ํด๋น ์นดํ
๊ณ ๋ฆฌ์์ ๋๋ค ๋ฉ์์ง ์ ํ
$messages = $message_pool[$random_category];
$random_message = $messages[array_rand($messages)];
// ํ์ด ๋ฒํธ ์์ฑ (1~99)
$lucky_number = rand(1, 99);
// DB์ ์ ์ฅ
$stmt = $db->prepare("INSERT INTO messages (category, content, lucky_number) VALUES (?, ?, ?)");
$stmt->execute([$random_category, $random_message, $lucky_number]);
// ๋ฐฉ๊ธ ์์ฑ๋ ๋ฉ์์ง ๊ฐ์ ธ์ค๊ธฐ
$current_message = [
'category' => $random_category,
'content' => $random_message,
'lucky_number' => $lucky_number
];
}
// ์ต๊ทผ ๋ฉ์์ง 10๊ฐ ๊ฐ์ ธ์ค๊ธฐ
$stmt = $db->query("SELECT * FROM messages ORDER BY created_at DESC LIMIT 10");
$recent_messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
```
2. ์ฝ๋๊ฐ ์ ์์ ์ผ๋ก ๋์ํ๋์ง ํ์ธํ์ธ์. ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํด๋ ์๋ฌ๊ฐ ์์ด์ผ ํฉ๋๋ค.
**ํ์ธ ์ฌํญ:**
- `data/modules/fortune-cookie.sqlite` ํ์ผ์ด ์๋์ผ๋ก ์์ฑ๋์๋๊ฐ?
- ํ์ด์ง ๋ก๋ฉ ์ ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์๋๊ฐ?
๊ธฐ๋ ๊ฒฐ๊ณผ: - SQLite DB ์ฐ๊ฒฐ ์ฑ๊ณต - messages ํ ์ด๋ธ ์๋ ์์ฑ - 5๊ฐ ์นดํ ๊ณ ๋ฆฌ(fortune, love, success, wisdom, fun)์ ๊ฐ 5๊ฐ์ฉ ์ด 25๊ฐ ๋ฉ์์ง ์ค๋น - POST ์์ฒญ ์ฒ๋ฆฌ ๋ก์ง ๊ตฌํ (์์ง ๋ฒํผ๊ณผ ์ฐ๊ฒฐ ์ ๋จ) - ์ต๊ทผ ๋ฉ์์ง 10๊ฐ ๊ฐ์ ธ์ค๋ ์ฟผ๋ฆฌ ์ค๋น
**Step 3: ์ฟ ํค ๊นจ๊ธฐ ๊ธฐ๋ฅ ๊ตฌํ ๋ฐ ๋ฉ์์ง ์นด๋ ํ์**
1. `app/modules/fortune-cookie/index.php`์์ ๊ธฐ์กด ๋ฒํผ ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ธ์:
```php
<div style="margin: 3rem 0;">
<div id="cookie" style="font-size: 8rem; cursor: pointer; user-select: none; transition: transform 0.3s;">๐ฅ </div>
<form method="POST" id="cookieForm">
<button type="submit" name="break_cookie" value="1" style="
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 1rem 2rem;
font-size: 1.1rem;
border-radius: var(--m-radius-lg);
cursor: pointer;
margin-top: 1rem;
box-shadow: var(--m-shadow);
transition: transform 0.2s;
" onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">์ฟ ํค ๊นจ๊ธฐ</button>
</form>
</div>
<?php if (isset($current_message)): ?>
<div id="messageCard" style="
background: var(--m-surface);
border-radius: var(--m-radius-lg);
padding: 2rem;
margin-top: 2rem;
box-shadow: var(--m-shadow);
border-left: 4px solid <?php
$colors = [
'fortune' => '#FFD700',
'love' => '#FF69B4',
'success' => '#4169E1',
'wisdom' => '#9370DB',
'fun' => '#FF6347'
];
echo $colors[$current_message['category']];
?>;
animation: fadeIn 0.5s;
">
<div style="display: inline-block; background: <?php echo $colors[$current_message['category']]; ?>; color: white; padding: 0.3rem 0.8rem; border-radius: 1rem; font-size: 0.85rem; margin-bottom: 1rem;">
<?php
$category_names = [
'fortune' => '๐ ํ์ด',
'love' => '๐ ์ฌ๋',
'success' => '๐ฏ ์ฑ๊ณต',
'wisdom' => '๐ง ์งํ',
'fun' => '๐ ์ฌ๋ฏธ'
];
echo $category_names[$current_message['category']];
?>
</div>
<p style="font-size: 1.2rem; color: var(--m-text); margin-bottom: 1rem; line-height: 1.6;">
<?php echo htmlspecialchars($current_message['content']); ?>
</p>
<p style="color: var(--m-text-muted); font-size: 0.9rem; margin-bottom: 1rem;">
ํ์ด ๋ฒํธ: #<?php echo str_pad($current_message['lucky_number'], 2, '0', STR_PAD_LEFT); ?>
</p>
<button type="button" onclick="copyMessage()" style="
background: var(--m-surface);
border: 1px solid var(--m-text-muted);
color: var(--m-text);
padding: 0.6rem 1.2rem;
border-radius: var(--m-radius-lg);
cursor: pointer;
font-size: 0.9rem;
">๐ ๋ฉ์์ง ๋ณต์ฌ</button>
</div>
<style>
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<script>
function copyMessage() {
const message = `<?php echo htmlspecialchars($current_message['content']); ?>`;
const luckyNumber = '<?php echo str_pad($current_message['lucky_number'], 2, '0', STR_PAD_LEFT); ?>';
const text = `์ค๋์ ํ์ด: ${message} #ํ์ด๋ฒํธ${luckyNumber}`;
navigator.clipboard.writeText(text).then(() => {
alert('๋ฉ์์ง๊ฐ ๋ณต์ฌ๋์์ต๋๋ค!');
});
}
// ์ฟ ํค ํด๋ฆญ ์ ํ๋ค๋ฆผ ํจ๊ณผ
document.getElementById('cookie').addEventListener('click', function() {
this.style.animation = 'shake 0.5s';
setTimeout(() => {
this.style.animation = '';
}, 500);
});
</script>
<style>
@keyframes shake {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(-10deg); }
75% { transform: rotate(10deg); }
}
</style>
<?php endif; ?>
```
2. ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๊ณ "์ฟ ํค ๊นจ๊ธฐ" ๋ฒํผ์ ํด๋ฆญํ์ฌ ๋ฉ์์ง๊ฐ ํ์๋๋์ง ํ์ธํ์ธ์.
3. ์ฟ ํค ์ด๋ชจ์ง๋ฅผ ํด๋ฆญํ๋ฉด ํ๋ค๋ฆฌ๋ ์ ๋๋ฉ์ด์
์ด ๋์ํ๋์ง ํ์ธํ์ธ์.
4. "๋ฉ์์ง ๋ณต์ฌ" ๋ฒํผ์ ํด๋ฆญํ์ฌ ํด๋ฆฝ๋ณด๋์ ๋ณต์ฌ๋๋์ง ํ์ธํ์ธ์.
**ํ์ธ ์ฌํญ:**
- ๋ฒํผ ํด๋ฆญ ์ ๋๋ค ๋ฉ์์ง๊ฐ ํ์๋๋๊ฐ?
- ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ๋ค๋ฅธ ์์์ ํ
๋๋ฆฌ๊ฐ ํ์๋๋๊ฐ?
- ๋ฉ์์ง ์นด๋๊ฐ fade-in ์ ๋๋ฉ์ด์
์ผ๋ก ๋ํ๋๋๊ฐ?
- ์ฟ ํค ์ด๋ชจ์ง ํด๋ฆญ ์ ํ๋ค๋ฆผ ํจ๊ณผ๊ฐ ๋์ํ๋๊ฐ?
- ๋ฉ์์ง ๋ณต์ฌ ๊ธฐ๋ฅ์ด ์ ์ ์๋ํ๋๊ฐ?
๊ธฐ๋ ๊ฒฐ๊ณผ: - POST ์์ฒญ์ผ๋ก ์ฟ ํค ๊นจ๊ธฐ ๊ธฐ๋ฅ ๊ตฌํ - ๋๋ค ์นดํ ๊ณ ๋ฆฌ ๋ฐ ๋ฉ์์ง ์ ํ ๋ก์ง ๋์ - SQLite์ ๋ฉ์์ง ์๋ ์ ์ฅ - ๋ฉ์์ง ์นด๋๊ฐ ์นดํ ๊ณ ๋ฆฌ๋ณ ์์์ผ๋ก ํ์ - fade-in ์ ๋๋ฉ์ด์ ์ ์ฉ - ์ฟ ํค ํ๋ค๋ฆผ ํจ๊ณผ ๋ฐ ๋ฉ์์ง ๋ณต์ฌ ๊ธฐ๋ฅ ๊ตฌํ
**Step 4: ์ต๊ทผ ๋ฉ์์ง ํ์คํ ๋ฆฌ ํ์**
1. `app/modules/fortune-cookie/index.php`์ ๋ฉ์์ง ์นด๋ ์๋์ ๋ค์ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ธ์:
```php
<?php if (count($recent_messages) > 0): ?>
<div style="margin-top: 4rem;">
<h2 style="font-size: 1.5rem; color: var(--m-text); margin-bottom: 1.5rem; text-align: center;">๐ ์ต๊ทผ ๋ฐ์ ๋ฉ์์ง</h2>
<div style="display: grid; gap: 1rem;">
<?php
$colors = [
'fortune' => '#FFD700',
'love' => '#FF69B4',
'success' => '#4169E1',
'wisdom' => '#9370DB',
'fun' => '#FF6347'
];
$category_names = [
'fortune' => '๐ ํ์ด',
'love' => '๐ ์ฌ๋',
'success' => '๐ฏ ์ฑ๊ณต',
'wisdom' => '๐ง ์งํ',
'fun' => '๐ ์ฌ๋ฏธ'
];
foreach ($recent_messages as $msg):
?>
<div style="
background: var(--m-surface);
border-radius: var(--m-radius-lg);
padding: 1.2rem;
box-shadow: var(--m-shadow);
border-left: 3px solid <?php echo $colors[$msg['category']]; ?>;
">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
<span style="background: <?php echo $colors[$msg['category']]; ?>; color: white; padding: 0.2rem 0.6rem; border-radius: 0.8rem; font-size: 0.75rem;">
<?php echo $category_names[$msg['category']]; ?>
</span>
<span style="color: var(--m-text-muted); font-size: 0.8rem;">
<?php
$date = new DateTime($msg['created_at']);
echo $date->format('m/d H:i');
?>
</span>
</div>
<p style="color: var(--m-text); font-size: 0.95rem; line-height: 1.5; margin-bottom: 0.5rem;">
<?php echo htmlspecialchars($msg['content']); ?>
</p>
<p style="color: var(--m-text-muted); font-size: 0.8rem;">
ํ์ด ๋ฒํธ: #<?php echo str_pad($msg['lucky_number'], 2, '0', STR_PAD_LEFT); ?>
</p>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
```
2. ์ฌ๋ฌ ๋ฒ "์ฟ ํค ๊นจ๊ธฐ" ๋ฒํผ์ ํด๋ฆญํ์ฌ ํ์คํ ๋ฆฌ๊ฐ ์์ด๋์ง ํ์ธํ์ธ์.
3. ์ต๊ทผ 10๊ฐ๊น์ง๋ง ํ์๋๋์ง ํ์ธํ์ธ์.
**ํ์ธ ์ฌํญ:**
- ์ต๊ทผ ๋ฉ์์ง๊ฐ ์ต์ ์์ผ๋ก ์ ๋ ฌ๋์ด ํ์๋๋๊ฐ?
- ๊ฐ ๋ฉ์์ง์ ์นดํ
๊ณ ๋ฆฌ ๋ฐฐ์ง์ ๋ ์ง/์๊ฐ์ด ํ์๋๋๊ฐ?
- ์นดํ
๊ณ ๋ฆฌ๋ณ ์์์ด ์ผ๊ด๋๊ฒ ์ ์ฉ๋๋๊ฐ?
- 10๊ฐ ์ด์ ์์ฑํด๋ ์ต๊ทผ 10๊ฐ๋ง ํ์๋๋๊ฐ?
๊ธฐ๋ ๊ฒฐ๊ณผ: - ์ต๊ทผ ๋ฉ์์ง 10๊ฐ๋ฅผ ์๊ฐ์์ผ๋ก ํ์ - ๊ฐ ๋ฉ์์ง ์นด๋์ ์นดํ ๊ณ ๋ฆฌ ๋ฐฐ์ง, ๋ด์ฉ, ํ์ด ๋ฒํธ, ๋ ์ง/์๊ฐ ํ์ - ์นดํ ๊ณ ๋ฆฌ๋ณ ์์ ์ผ๊ด์ฑ ์ ์ง - ํ์คํ ๋ฆฌ ์น์ ์ด ๋ฉ์์ง๊ฐ ์์ ๋๋ง ํ์ - ๋ชจ๋ฐ์ผ์์๋ ์ฝ๊ธฐ ํธํ ๋ ์ด์์
์ ์ถ๋ ์ํ (0)
๋ก๊ทธ์ธ ํ ์ ์ถ์์ง ์ ์ถ๋ ์ํ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋์ ์๊ฐ ๋์ด๋ณด์ธ์!