๐ ํผ์ ํ ํ ์กฐํฉ ์ถ์ฒ๊ธฐ - ๋๋ง์ ์๋ฒฝํ ํผ์ ๋ง๋ค๊ธฐ
pizza-topping-recommender
๋ฌธ์ ์ค๋ช
๐ ํผ์ ํ ํ ์กฐํฉ ์ถ์ฒ๊ธฐ
์ฌ์ฉ์๊ฐ ์ ํธํ๋ ์ฌ๋ฃ๋ฅผ ์ ํํ๋ฉด ์ด์ธ๋ฆฌ๋ ํผ์ ํ ํ ์กฐํฉ์ ์ถ์ฒํด์ฃผ๋ ์ฌ๋ฏธ์๋ ์น ์๋น์ค์ ๋๋ค. Laravel 13.x + Blade ํ ํ๋ฆฟ์ผ๋ก ๋ง๋๋ ์ ๋ฌธ์์ฉ ํ๋ก์ ํธ๋ก, ๊ธฐ๋ณธ์ ์ธ ํผ ์ฒ๋ฆฌ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค CRUD๋ฅผ ํ์ตํ ์ ์์ต๋๋ค.
ํ์ ๊ธฐ๋ฅ
- ํ ํ ์นดํ ๊ณ ๋ฆฌ๋ณ ์ ํ UI (์น์ฆ, ๊ณ ๊ธฐ, ์ผ์ฑ, ์์ค ๋ฑ)
- ์ ํํ ํ ํ ์กฐํฉ ์ ์ฅ ๊ธฐ๋ฅ
- ์ธ๊ธฐ ์๋ ์กฐํฉ ์์ ํ์ (์ข์์ ์ ๊ธฐ์ค)
- ์ ์ฅ๋ ๋๋ง์ ์กฐํฉ ๋ชฉ๋ก ๋ณด๊ธฐ
- ๊ฐ ์กฐํฉ์ ์ด๋ฆ๊ณผ ์ค๋ช ์ถ๊ฐ ๊ฐ๋ฅ
- ์กฐํฉ๋ณ ์ข์์ ๋ฒํผ (์ค๋ณต ๋ฐฉ์ง)
์ ํ ์ถ๊ฐ ๊ธฐ๋ฅ (๋ณด๋์ค)
- ํ ํ๋ณ ์นผ๋ก๋ฆฌ/๊ฐ๊ฒฉ ์ ๋ณด ํ์
- ์กฐํฉ ๊ณต์ ๊ธฐ๋ฅ (๊ณ ์ URL ์์ฑ)
- ๋๋ค ์กฐํฉ ์ถ์ฒ ๋ฒํผ
- ํ ํ ์ด๋ฏธ์ง ์์ด์ฝ ํ์
- ์์๋ณ ํ๊ทธ ์์คํ (๋งค์ด๋ง, ๊ณ ๋จ๋ฐฑ, ์ฑ์ ๋ฑ)
๊ธฐ์ ์คํ
- Laravel 13.x
- Blade ํ ํ๋ฆฟ
- SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค
- Tailwind CSS
ํ์ต ๋ชฉํ
- Laravel ๋ผ์ฐํ ๊ณผ ์ปจํธ๋กค๋ฌ ๊ธฐ๋ณธ
- Blade ์ปดํฌ๋ํธ์ ๋ฐ๋ณต๋ฌธ ํ์ฉ
- ํผ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ
- Eloquent ORM ๊ธฐ๋ณธ CRUD
- ๊ด๊ณํ ๋ฐ์ดํฐ ๋ชจ๋ธ๋ง (๋ค๋๋ค ๊ด๊ณ)
- Session์ ํ์ฉํ ์ข์์ ๊ธฐ๋ฅ
์ ์ฝ ์กฐ๊ฑด
- โข Laravel 13.x ์ต์ ๋ฒ์ ์ฌ์ฉ ํ์
- โข Blade ํ ํ๋ฆฟ ์์ง๋ง ์ฌ์ฉ (React/Vue ๊ธ์ง)
- โข SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ
- โข Tailwind CSS๋ก ์คํ์ผ๋ง
- โข ํ ํ๊ณผ ์กฐํฉ์ ๋ค๋๋ค(many-to-many) ๊ด๊ณ๋ก ์ค๊ณ
- โข ์ข์์๋ ์ธ์ ๊ธฐ๋ฐ์ผ๋ก ์ค๋ณต ๋ฐฉ์ง (๋ก๊ทธ์ธ ๋ถํ์)
- โข ๋ฐ์ํ ๋์์ธ ์ ์ฉ (๋ชจ๋ฐ์ผ ์นํ์ )
- โข ์ต์ 10๊ฐ ์ด์์ ํ ํ ๋ฐ์ดํฐ ์๋ฉ
ํ๋กฌํํธ ๋ ์ํผ
์๋ ํ๋กฌํํธ๋ฅผ ์์๋๋ก AI์๊ฒ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค. ๋ณต์ฌ ๋ฒํผ์ ๋๋ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์.
mkdir pizza-topping-recommender && cd pizza-topping-recommender ์ด ํด๋์์ Laravel 13.x ํ๋ก์ ํธ๋ฅผ ์์ํฉ๋๋ค. Laravel 13.x ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ ๊ธฐ๋ณธ ์ค์ ์ ํด์ฃผ์ธ์. ์๊ตฌ์ฌํญ: 1. Laravel ์ต์ ๋ฒ์ (13.x) ์ค์น 2. .env ํ์ผ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ SQLite๋ก ์ค์ 3. database/database.sqlite ํ์ผ ์์ฑ 4. Tailwind CSS ์ค์น ๋ฐ ์ค์ (Laravel Mix ๋๋ Vite ์ฌ์ฉ) 5. ๊ธฐ๋ณธ welcome ํ์ด์ง๋ฅผ ํผ์ ํ ํ ์ถ์ฒ๊ธฐ ๋ฉ์ธ ํ์ด์ง๋ก ๋ณ๊ฒฝ ๋ฉ์ธ ํ์ด์ง(welcome.blade.php)์๋: - ๐ ํผ์ ํ ํ ์กฐํฉ ์ถ์ฒ๊ธฐ ํ์ดํ - "์ ์กฐํฉ ๋ง๋ค๊ธฐ" ๋ฒํผ - "์ธ๊ธฐ ์กฐํฉ ๋ณด๊ธฐ" ๋ฒํผ - ๊ฐ๋จํ ์ค๋ช ํ ์คํธ - Tailwind CSS๋ก ์ค์ ์ ๋ ฌ๋๊ณ ๊น๋ํ ๋ ์ด์์ ๋ฒํผ๋ค์ ์์ง ๋งํฌ ์์ด UI๋ง ๊ตฌํํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: Laravel 13.x ํ๋ก์ ํธ๊ฐ ์์ฑ๋๊ณ , Tailwind CSS๊ฐ ์ค์ ๋๋ฉฐ, SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ค๋น๋ฉ๋๋ค. ๋ฉ์ธ ํ์ด์ง์ ํผ์ ํ ๋ง์ ๊น๋ํ ๋๋ฉ UI๊ฐ ํ์๋ฉ๋๋ค.
ํ ํ๊ณผ ์กฐํฉ์ ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง๋ฅผ ์ค๊ณํ๊ณ ๋ง์ด๊ทธ๋ ์ด์ ์ ์์ฑํด์ฃผ์ธ์. ํ์ํ ํ ์ด๋ธ: 1. `toppings` ํ ์ด๋ธ: - id (primary key) - name (ํ ํ ์ด๋ฆ, ์: 'ํํผ๋ก๋', '์ฌ๋ฆฌ๋ธ', '๋ชจ์ง๋ ๋ผ') - category (์นดํ ๊ณ ๋ฆฌ, ์: '๊ณ ๊ธฐ', '์ผ์ฑ', '์น์ฆ', '์์ค') - icon (์ด๋ชจ์ง ๋๋ ์์ด์ฝ ์ด๋ฆ, ์: '๐ฅ', '๐ง') - calories (์นผ๋ก๋ฆฌ, nullable) - price (๊ฐ๊ฒฉ, nullable) - timestamps 2. `combinations` ํ ์ด๋ธ: - id (primary key) - name (์กฐํฉ ์ด๋ฆ, ์: '๋งค์ฝค ํํผ๋ก๋ ์ฝค๋ณด') - description (์ค๋ช , nullable) - likes_count (์ข์์ ์, ๊ธฐ๋ณธ๊ฐ 0) - timestamps 3. `combination_topping` ํผ๋ฒ ํ ์ด๋ธ (๋ค๋๋ค ๊ด๊ณ): - id (primary key) - combination_id (foreign key) - topping_id (foreign key) - timestamps ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ์์ฑํ๊ณ `php artisan migrate` ์คํ๊น์ง ํด์ฃผ์ธ์. ๊ทธ๋ฆฌ๊ณ Topping, Combination ๋ชจ๋ธ๋ ์์ฑํด์ฃผ์ธ์. Combination ๋ชจ๋ธ์๋ toppings ๊ด๊ณ ๋ฉ์๋๋ฅผ ์ ์ํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: 3๊ฐ์ ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ด ์์ฑ๋๊ณ ์คํ๋์ด SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ด ์์ฑ๋ฉ๋๋ค. Topping๊ณผ Combination ๋ชจ๋ธ์ด ์์ฑ๋๊ณ , ๋ค๋๋ค ๊ด๊ณ๊ฐ ์ค์ ๋ฉ๋๋ค.
ํ ํ ๋ฐ์ดํฐ๋ฅผ ์๋ฉ(seeding)ํด์ฃผ์ธ์. ToppingSeeder๋ฅผ ๋ง๋ค์ด์ ์ต์ 15๊ฐ ์ด์์ ๋ค์ํ ํ ํ์ ์ถ๊ฐํด์ฃผ์ธ์. ์นดํ ๊ณ ๋ฆฌ๋ณ ์์: - ์น์ฆ: ๋ชจ์ง๋ ๋ผ(๐ง), ์ฒด๋ค, ๊ณ ๋ฅด๊ณค์กธ๋ผ, ํ๋ง์ฐ - ๊ณ ๊ธฐ: ํํผ๋ก๋(๐ฅ), ์์์ง, ๋ฒ ์ด์ปจ, ํ, ๋ถ๊ณ ๊ธฐ - ์ผ์ฑ: ์ํ(๐ง ), ํผ๋ง, ์ฌ๋ฆฌ๋ธ, ํ ๋งํ , ๋ฒ์ฏ(๐), ํ์ธ์ ํ(๐) - ์์ค: ํ ๋งํ ์์ค(๐ ), ํฌ๋ฆผ ์์ค, ๋ฐ๋ฒ ํ ์์ค, ํซ์์ค(๐ถ๏ธ) ๊ฐ ํ ํ์ ์ ์ ํ ์ด๋ชจ์ง ์์ด์ฝ์ ์ถ๊ฐํ๊ณ , ์ ํ์ ์ผ๋ก ์นผ๋ก๋ฆฌ์ ๊ฐ๊ฒฉ๋ ๋ฃ์ด์ฃผ์ธ์. `php artisan db:seed --class=ToppingSeeder` ์คํ๊น์ง ํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ToppingSeeder๊ฐ ์์ฑ๋๊ณ ์คํ๋์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ค์ํ ํ ํ ๋ฐ์ดํฐ๊ฐ ์ถ๊ฐ๋ฉ๋๋ค. ๊ฐ ํ ํ์ ์ด๋ชจ์ง ์์ด์ฝ๊ณผ ์นดํ ๊ณ ๋ฆฌ ์ ๋ณด๋ฅผ ํฌํจํฉ๋๋ค.
์ ์กฐํฉ ๋ง๋ค๊ธฐ ํ์ด์ง๋ฅผ ๊ตฌํํด์ฃผ์ธ์. ๋ผ์ฐํธ: - GET /combinations/create - ์กฐํฉ ์์ฑ ํผ ํ์ - POST /combinations - ์กฐํฉ ์ ์ฅ CombinationController๋ฅผ ์์ฑํ๊ณ create, store ๋ฉ์๋๋ฅผ ๊ตฌํํด์ฃผ์ธ์. create.blade.php ๋ทฐ: - ์กฐํฉ ์ด๋ฆ ์ ๋ ฅ ํ๋ - ์กฐํฉ ์ค๋ช ํ ์คํธ ์์ญ (์ ํ์ฌํญ) - ํ ํ ์ ํ UI: ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ๊ทธ๋ฃนํ๋ ์ฒดํฌ๋ฐ์ค ๋ชฉ๋ก - ๊ฐ ์นดํ ๊ณ ๋ฆฌ(์น์ฆ, ๊ณ ๊ธฐ, ์ผ์ฑ, ์์ค)๋ฅผ ์น์ ์ผ๋ก ๋๋ - ๊ฐ ํ ํ์ ์ด๋ชจ์ง ์์ด์ฝ๊ณผ ํจ๊ป ํ์ - ์ฒดํฌ๋ฐ์ค๋ก ๋ค์ค ์ ํ ๊ฐ๋ฅ - "์กฐํฉ ์ ์ฅ" ๋ฒํผ - Tailwind CSS๋ก ๊น๋ํ๊ณ ์ง๊ด์ ์ธ UI store ๋ฉ์๋: - ํผ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ (์กฐํฉ ์ด๋ฆ ํ์, ์ต์ 1๊ฐ ํ ํ ์ ํ ํ์) - Combination ๋ ์ฝ๋ ์์ฑ - ์ ํ๋ ํ ํ๋ค๊ณผ ๊ด๊ณ ์ฐ๊ฒฐ (attach ์ฌ์ฉ) - ์ฑ๊ณต ๋ฉ์์ง์ ํจ๊ป ์กฐํฉ ์์ธ ํ์ด์ง๋ก ๋ฆฌ๋๋ ํธ ๋ฉ์ธ ํ์ด์ง์ "์ ์กฐํฉ ๋ง๋ค๊ธฐ" ๋ฒํผ์ ์ด ๋ผ์ฐํธ ๋งํฌ๋ฅผ ์ฐ๊ฒฐํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: CombinationController๊ฐ ์์ฑ๋๊ณ , ํ ํ์ ์ ํํ์ฌ ์๋ก์ด ํผ์ ์กฐํฉ์ ๋ง๋ค ์ ์๋ ํผ ํ์ด์ง๊ฐ ์์ฑ๋ฉ๋๋ค. ํผ ์ ์ถ ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์กฐํฉ์ด ์ ์ฅ๋๊ณ ํ ํ๊ณผ์ ๊ด๊ณ๊ฐ ์ฐ๊ฒฐ๋ฉ๋๋ค.
์กฐํฉ ์์ธ ํ์ด์ง์ ์ธ๊ธฐ ์กฐํฉ ๋ชฉ๋ก ํ์ด์ง๋ฅผ ๊ตฌํํด์ฃผ์ธ์.
๋ผ์ฐํธ:
- GET /combinations/{id} - ์กฐํฉ ์์ธ ๋ณด๊ธฐ
- GET /combinations - ์ธ๊ธฐ ์กฐํฉ ๋ชฉ๋ก
- POST /combinations/{id}/like - ์ข์์ ์ถ๊ฐ
CombinationController์ show, index, like ๋ฉ์๋ ์ถ๊ฐ:
show ๋ฉ์๋:
- ์กฐํฉ ์ ๋ณด์ ์ฐ๊ฒฐ๋ ํ ํ ๋ชฉ๋ก ํ์
- ์ข์์ ์ ํ์
- ์ข์์ ๋ฒํผ (์ด๋ฏธ ์ข์์ ํ์ผ๋ฉด ๋นํ์ฑํ)
show.blade.php ๋ทฐ:
- ์กฐํฉ ์ด๋ฆ๊ณผ ์ค๋ช
- ์ ํ๋ ํ ํ ๋ชฉ๋ก (์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ๊ทธ๋ฃนํ, ์ด๋ชจ์ง ์์ด์ฝ ํฌํจ)
- ์ข์์ ์์ ํํธ ๋ฒํผ
- "๋ชฉ๋ก์ผ๋ก" ๋ฒํผ
index ๋ฉ์๋:
- ๋ชจ๋ ์กฐํฉ์ ์ข์์ ์ ๊ธฐ์ค ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
- ํ์ด์ง๋ค์ด์
(10๊ฐ์ฉ)
index.blade.php ๋ทฐ:
- ์กฐํฉ ์นด๋ ๊ทธ๋ฆฌ๋ ๋ ์ด์์
- ๊ฐ ์นด๋: ์กฐํฉ ์ด๋ฆ, ํ ํ ์์ด์ฝ ๋ชฉ๋ก, ์ข์์ ์
- ์นด๋ ํด๋ฆญ ์ ์์ธ ํ์ด์ง๋ก ์ด๋
like ๋ฉ์๋:
- ์ธ์
์ ์ข์์ํ ์กฐํฉ ID ๋ฐฐ์ด ์ ์ฅ
- ์ด๋ฏธ ์ข์์ ํ์ผ๋ฉด ์ค๋ณต ๋ฐฉ์ง
- likes_count ์ฆ๊ฐ
- ์์ธ ํ์ด์ง๋ก ๋ฆฌ๋๋ ํธ
๋ฉ์ธ ํ์ด์ง์ "์ธ๊ธฐ ์กฐํฉ ๋ณด๊ธฐ" ๋ฒํผ์ /combinations ๋งํฌ ์ฐ๊ฒฐํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ์กฐํฉ ๋ชฉ๋ก ํ์ด์ง์ ์์ธ ํ์ด์ง๊ฐ ์์ฑ๋๊ณ , ์ข์์ ๊ธฐ๋ฅ์ด ์๋ํฉ๋๋ค. ์ธ์ ์ ํ์ฉํ์ฌ ์ค๋ณต ์ข์์๊ฐ ๋ฐฉ์ง๋๋ฉฐ, ์ธ๊ธฐ ์กฐํฉ์ด ์ข์์ ์ ์์ผ๋ก ์ ๋ ฌ๋์ด ํ์๋ฉ๋๋ค.
์ ์ฒด UI/UX๋ฅผ ๊ฐ์ ํ๊ณ ๋ณด๋์ค ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ฃผ์ธ์.
๊ฐ์ ์ฌํญ:
1. ๋ฐ์ํ ๋์์ธ:
- ๋ชจ๋ฐ์ผ์์๋ ๋ณด๊ธฐ ์ข๊ฒ ๊ทธ๋ฆฌ๋ ๋ ์ด์์ ์กฐ์
- ํฐ์น ์นํ์ ์ธ ๋ฒํผ ํฌ๊ธฐ
2. ์๊ฐ์ ํผ๋๋ฐฑ:
- ์ข์์ ๋ฒํผ ํด๋ฆญ ์ ์ ๋๋ฉ์ด์
ํจ๊ณผ
- ์กฐํฉ ์ ์ฅ ์ฑ๊ณต ์ ํ ์คํธ ๋ฉ์์ง
- ํ ํ ์ ํ ์ ์ฒดํฌ๋ฐ์ค ์คํ์ผ ๊ฐ์
3. ๋ณด๋์ค ๊ธฐ๋ฅ ์ถ๊ฐ:
- ์กฐํฉ ์์ฑ ํ์ด์ง์ "๋๋ค ์กฐํฉ ์ถ์ฒ" ๋ฒํผ
- ํด๋ฆญ ์ ๊ฐ ์นดํ
๊ณ ๋ฆฌ์์ ๋๋ค์ผ๋ก 1๊ฐ์ฉ ํ ํ ์ ํ
- ์กฐํฉ ๋ชฉ๋ก์ ํํฐ ๊ธฐ๋ฅ
- ํน์ ํ ํ์ ํฌํจํ๋ ์กฐํฉ๋ง ๋ณด๊ธฐ
- ๊ฐ ์กฐํฉ ์นด๋์ ์ด ์นผ๋ก๋ฆฌ ํ์ (ํ ํ ์นผ๋ก๋ฆฌ ํฉ์ฐ)
4. ๋ค๋น๊ฒ์ด์
๊ฐ์ :
- ๋ชจ๋ ํ์ด์ง ์๋จ์ ๊ณตํต ๋ค๋น๊ฒ์ด์
๋ฐ ์ถ๊ฐ
- ํ, ์ ์กฐํฉ ๋ง๋ค๊ธฐ, ์ธ๊ธฐ ์กฐํฉ ๋งํฌ ํฌํจ
5. ๋น ์ํ ์ฒ๋ฆฌ:
- ์กฐํฉ์ด ์์ ๋ "์ฒซ ์กฐํฉ์ ๋ง๋ค์ด๋ณด์ธ์!" ๋ฉ์์ง
- ์ ์ ํ ์ผ๋ฌ์คํธ ๋๋ ์ด๋ชจ์ง ์ถ๊ฐ
Tailwind CSS ์ ํธ๋ฆฌํฐ ํด๋์ค๋ฅผ ์ต๋ํ ํ์ฉํ์ฌ ๊น๋ํ๊ณ ๋ชจ๋ํ ๋์์ธ์ ์์ฑํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ UI/UX๊ฐ ํฌ๊ฒ ๊ฐ์ ๋๊ณ , ๋๋ค ์ถ์ฒ, ํํฐ๋ง ๋ฑ ๋ณด๋์ค ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋ฉ๋๋ค. ๋ฐ์ํ ๋์์ธ์ด ์ ์ฉ๋์ด ๋ชจ๋ฐ์ผ์์๋ ์๋ฒฝํ๊ฒ ์๋ํ๋ฉฐ, ์ฌ์ฉ์ ๊ฒฝํ์ด ํฅ์๋ฉ๋๋ค.
์ ์ถ๋ ์ํ (0)
๋ก๊ทธ์ธ ํ ์ ์ถ์์ง ์ ์ถ๋ ์ํ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋์ ์๊ฐ ๋์ด๋ณด์ธ์!