๐จ ์จ๋ผ์ธ ๊ฐค๋ฌ๋ฆฌ ์ ์ & ์ํ ํ๋งค ํ๋ซํผ
online-art-exhibition-platform
๋ฌธ์ ์ค๋ช
๐จ ์จ๋ผ์ธ ๊ฐค๋ฌ๋ฆฌ ์ ์ & ์ํ ํ๋งค ํ๋ซํผ
์ํฐ์คํธ๊ฐ ์์ ์ ์ํ์ ์ ์ํ๊ณ ํ๋งคํ ์ ์๋ ์จ๋ผ์ธ ๊ฐค๋ฌ๋ฆฌ ํ๋ซํผ์ ๋ง๋ญ๋๋ค. Laravel 13.x + Inertia.js + React 19 ๋ชจ๋ ธ๋ฆฌ์ค ํ์คํ ๊ตฌ์กฐ๋ก, ์ํ ๊ฐค๋ฌ๋ฆฌ, ์นดํ ๊ณ ๋ฆฌ๋ณ ํํฐ๋ง, ์ํ ์์ธ ํ์ด์ง, ๊ตฌ๋งค ๋ฌธ์ ํผ์ ๊ตฌํํฉ๋๋ค.
ํ์ ๊ธฐ๋ฅ
- ์ํ ๊ฐค๋ฌ๋ฆฌ: ๊ทธ๋ฆฌ๋ ๋ ์ด์์์ผ๋ก ์ํ ๋ชฉ๋ก ํ์ (์ด๋ฏธ์ง, ์ ๋ชฉ, ์๊ฐ๋ช , ๊ฐ๊ฒฉ)
- ์นดํ ๊ณ ๋ฆฌ ํํฐ๋ง: ํํ/์กฐ๊ฐ/์ฌ์ง/๋์งํธ์ํธ ๋ฑ ์นดํ ๊ณ ๋ฆฌ๋ณ ์ํ ํํฐ๋ง
- ์ํ ์์ธ ํ์ด์ง: ํฐ ์ด๋ฏธ์ง, ์ํ ์ค๋ช , ํฌ๊ธฐ, ์ฌ๋ฃ, ๊ฐ๊ฒฉ ์ ๋ณด ํ์
- ๊ตฌ๋งค ๋ฌธ์ ํผ: ์ํ๋ณ ๊ตฌ๋งค ์์ฌ ์ ๋ฌ (์ด๋ฆ, ์ด๋ฉ์ผ, ๋ฉ์์ง)
- ๊ฒ์ ๊ธฐ๋ฅ: ์ํ๋ช ๋๋ ์๊ฐ๋ช ์ผ๋ก ๊ฒ์
- ์ข์์ ๊ธฐ๋ฅ: ๊ด์ฌ ์๋ ์ํ์ ํํธ ํ์ (๋ก์ปฌ ์คํ ๋ฆฌ์ง ํ์ฉ)
- ๋ฐ์ํ ๋์์ธ: ๋ชจ๋ฐ์ผ/ํ๋ธ๋ฆฟ/๋ฐ์คํฌํฑ ์ต์ ํ
์ ํ ์ถ๊ฐ ๊ธฐ๋ฅ (๋ณด๋์ค)
- ์ด๋ฏธ์ง ํ๋ ๋ชจ๋ฌ: ์ํ ์ด๋ฏธ์ง ํด๋ฆญ ์ ๋ผ์ดํธ๋ฐ์ค ํจ๊ณผ
- ์ํ ์ ๋ ฌ: ์ต์ ์/๊ฐ๊ฒฉ์/์ธ๊ธฐ์ ์ ๋ ฌ ์ต์
- ์๊ฐ ํ๋กํ ํ์ด์ง: ์๊ฐ๋ณ ์ํ ๋ชจ์ & ์๊ฐ
- ํ์ด์ง๋ค์ด์ : ์ํ ๋ชฉ๋ก ํ์ด์ง๋ค์ด์ ๋๋ ๋ฌดํ ์คํฌ๋กค
- ์ด๋ฉ์ผ ์๋ฆผ: ๊ตฌ๋งค ๋ฌธ์ ์ ์๊ฐ์๊ฒ ์๋ ์ด๋ฉ์ผ ๋ฐ์ก
- ์ํ ๊ณต์ ๊ธฐ๋ฅ: SNS ๊ณต์ ๋ฒํผ (์นด์นด์คํก, ํ์ด์ค๋ถ, ํธ์ํฐ)
๊ธฐ์ ์คํ
- ๋ฐฑ์๋: Laravel 13.x (Eloquent ORM, SQLite)
- ํ๋ก ํธ์๋: React 19 + Inertia.js
- ์คํ์ผ๋ง: Tailwind CSS
- ์์ด์ฝ: Heroicons ๋๋ React Icons
- ์ด๋ฏธ์ง ์ฒ๋ฆฌ: Laravel Storage (public disk)
์ค์ ๊ฐค๋ฌ๋ฆฌ ์ด์์๋ ์ํฐ์คํธ๊ฐ ์ฌ์ฉํ ์ ์๋ ์์ค์ ํ๋ซํผ์ ๋ชฉํ๋ก ํ๋ฉฐ, ์ํ ์ด๋ฏธ์ง๊ฐ ๋๋ณด์ด๋ ์ธ๋ จ๋ UI/UX๋ฅผ ๊ตฌํํฉ๋๋ค.
์ ์ฝ ์กฐ๊ฑด
- โข Laravel 13.x + Inertia.js + React 19 ๋ชจ๋ ธ๋ฆฌ์ค ํ์คํ ๊ตฌ์กฐ
- โข ๋ณ๋ API ๋ผ์ฐํธ ์์ด Inertia::render()๋ก ๋ฐ์ดํฐ ์ ๋ฌ
- โข SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ (๊ฐ๋จํ ์ค์ )
- โข Tailwind CSS๋ก ์คํ์ผ๋ง
- โข ์ด๋ฏธ์ง ์ ๋ก๋๋ Laravel Storage ํ์ฉ (public disk)
- โข ์ค์๊ฐ ์ฑํ ๊ธ์ง (๊ตฌ๋งค ๋ฌธ์๋ ํผ ์ ์ถ ๋ฐฉ์)
- โข ๊ด๋ฆฌ์ ๋์๋ณด๋ ์์ด ์ฌ์ฉ์ ์ค์ฌ ๊ฐค๋ฌ๋ฆฌ ๋ทฐ ๊ตฌํ
- โข ๋ฐ์ํ ๋์์ธ ํ์ (๋ชจ๋ฐ์ผ ์ฐ์ )
ํ๋กฌํํธ ๋ ์ํผ
์๋ ํ๋กฌํํธ๋ฅผ ์์๋๋ก AI์๊ฒ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค. ๋ณต์ฌ ๋ฒํผ์ ๋๋ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์.
mkdir online-art-exhibition-platform && cd online-art-exhibition-platform ์ด ํด๋์์ Laravel 13.x + Inertia.js + React 19 ํ๋ก์ ํธ๋ฅผ ์์ํฉ๋๋ค. `npx create laravel` ๋ช ๋ น์ผ๋ก Laravel 13.x ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ , Laravel Breeze์ React + Inertia.js starter kit์ ์ค์นํด์ฃผ์ธ์. ์ค์น ํ ๋ค์ ์์ ์ ์ํํด์ฃผ์ธ์: 1. SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ (.env ํ์ผ์์ DB_CONNECTION=sqlite ์ค์ , database/database.sqlite ํ์ผ ์์ฑ) 2. Tailwind CSS ์ค์ ํ์ธ (Breeze๊ฐ ์๋์ผ๋ก ์ค์ ) 3. `php artisan migrate` ์คํํ์ฌ ๊ธฐ๋ณธ ํ ์ด๋ธ ์์ฑ 4. `npm install && npm run dev` ์คํํ์ฌ ํ๋ก ํธ์๋ ๋น๋ ์์ 5. `php artisan serve` ์คํํ์ฌ ๊ฐ๋ฐ ์๋ฒ ์์ ํ๋ก์ ํธ ๊ตฌ์กฐ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ๋์๋์ง ํ์ธํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: Laravel 13.x + Inertia.js + React 19 ํ๋ก์ ํธ๊ฐ ์์ฑ๋๊ณ , SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ค์ ๋๋ฉฐ, ๊ฐ๋ฐ ์๋ฒ๊ฐ ์คํ๋ฉ๋๋ค. http://localhost:8000์ ์ ์ํ๋ฉด Laravel Breeze ๊ธฐ๋ณธ ํ๋ฉด์ด ๋ณด์ ๋๋ค.
์ํ(Artwork) ๋ชจ๋ธ๊ณผ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ง์ด๊ทธ๋ ์ด์ ์ ์์ฑํด์ฃผ์ธ์. `php artisan make:model Artwork -m` ๋ช ๋ น์ผ๋ก ๋ชจ๋ธ๊ณผ ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ์์ฑํ๊ณ , ๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ๋ค์ ์ปฌ๋ผ์ ์ถ๊ฐํด์ฃผ์ธ์: - id (์๋ ์์ฑ) - title (string, ์ํ ์ ๋ชฉ) - artist_name (string, ์๊ฐ๋ช ) - category (string, ์นดํ ๊ณ ๋ฆฌ: painting/sculpture/photography/digital) - description (text, ์ํ ์ค๋ช ) - size (string, ์ํ ํฌ๊ธฐ, ์: 50x70cm) - material (string, ์ฌ๋ฃ, ์: Oil on canvas) - price (decimal, ๊ฐ๊ฒฉ) - image_path (string, ์ด๋ฏธ์ง ๊ฒฝ๋ก) - is_sold (boolean, ํ๋งค ์ฌ๋ถ, ๊ธฐ๋ณธ๊ฐ false) - created_at, updated_at (ํ์์คํฌํ) ๋ง์ด๊ทธ๋ ์ด์ ์คํ: `php artisan migrate` ๊ทธ๋ฆฌ๊ณ Artwork ๋ชจ๋ธ์ $fillable ์์ฑ์ ์ถ๊ฐํ์ฌ ๋๋ ํ ๋น ๊ฐ๋ฅํ๋๋ก ์ค์ ํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: Artwork ๋ชจ๋ธ๊ณผ artworks ํ ์ด๋ธ์ด ์์ฑ๋ฉ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ค๋น๊ฐ ์๋ฃ๋ฉ๋๋ค.
์๋(Seeder)๋ฅผ ์์ฑํ์ฌ ์ํ ์ํ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์. `php artisan make:seeder ArtworkSeeder` ๋ช ๋ น์ผ๋ก ์๋๋ฅผ ์์ฑํ๊ณ , ์ต์ 12๊ฐ ์ด์์ ์ํ ์ํ์ ์ถ๊ฐํด์ฃผ์ธ์. ์นดํ ๊ณ ๋ฆฌ๋ painting, sculpture, photography, digital์ ๊ณจ๊ณ ๋ฃจ ์์ด์ฃผ์ธ์. ์ํ ๋ฐ์ดํฐ ์์: - ์ ๋ชฉ: "Sunset over the Ocean" - ์๊ฐ๋ช : "Jane Doe" - ์นดํ ๊ณ ๋ฆฌ: painting - ์ค๋ช : "A vibrant sunset painting capturing the beauty of nature." - ํฌ๊ธฐ: "60x80cm" - ์ฌ๋ฃ: "Oil on canvas" - ๊ฐ๊ฒฉ: 350000 (์ ๋จ์) - ์ด๋ฏธ์ง ๊ฒฝ๋ก: "artworks/sample1.jpg" (์ค์ ์ด๋ฏธ์ง๋ ๋์ค์ ์ ๋ก๋) - ํ๋งค ์ฌ๋ถ: false DatabaseSeeder.php์์ ArtworkSeeder๋ฅผ ํธ์ถํ๋๋ก ์ค์ ํ๊ณ , `php artisan db:seed` ๋ช ๋ น์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํด์ฃผ์ธ์. ์ด๋ฏธ์ง๋ public/storage/artworks ํด๋์ ์ํ ์ด๋ฏธ์ง(placeholder)๋ฅผ ๋ฃ๊ฑฐ๋, https://picsum.photos ๊ฐ์ ๋ฌด๋ฃ ์ด๋ฏธ์ง ์๋น์ค๋ฅผ ํ์ฉํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ ์ํ 12๊ฐ ์ด์์ด ์ฝ์ ๋๊ณ , ๊ฐค๋ฌ๋ฆฌ์ ํ์ํ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋ฉ๋๋ค.
์ํ ๊ฐค๋ฌ๋ฆฌ ํ์ด์ง๋ฅผ ๊ตฌํํด์ฃผ์ธ์.
1. **๋ผ์ฐํธ ์ค์ **: routes/web.php์ ๊ฐค๋ฌ๋ฆฌ ๋ฉ์ธ ํ์ด์ง ๋ผ์ฐํธ ์ถ๊ฐ
- GET '/' โ ArtworkController@index
2. **์ปจํธ๋กค๋ฌ ์์ฑ**: `php artisan make:controller ArtworkController`
- index() ๋ฉ์๋์์ Artwork::all()๋ก ๋ชจ๋ ์ํ์ ๊ฐ์ ธ์ Inertia::render('Gallery/Index', ['artworks' => $artworks])๋ก ์ ๋ฌ
3. **React ์ปดํฌ๋ํธ ์์ฑ**: resources/js/Pages/Gallery/Index.jsx
- props๋ก artworks ๋ฐ๊ธฐ
- ๊ทธ๋ฆฌ๋ ๋ ์ด์์(grid-cols-1 md:grid-cols-3 lg:grid-cols-4)์ผ๋ก ์ํ ์นด๋ ํ์
- ๊ฐ ์นด๋์ ์ด๋ฏธ์ง, ์ ๋ชฉ, ์๊ฐ๋ช
, ๊ฐ๊ฒฉ ํ์
- Tailwind CSS๋ก ์ธ๋ จ๋ ์นด๋ ๋์์ธ (hover ํจ๊ณผ, ๊ทธ๋ฆผ์ ๋ฑ)
- ์นด๋ ํด๋ฆญ ์ ์ํ ์์ธ ํ์ด์ง๋ก ์ด๋ (Inertia Link ์ฌ์ฉ)
4. **๋ ์ด์์**: AuthenticatedLayout ๋์ GuestLayout ๋๋ ์ปค์คํ
๋ ์ด์์ ์ฌ์ฉ (๊ฐค๋ฌ๋ฆฌ๋ ๋๊ตฌ๋ ๋ณผ ์ ์๋๋ก)
์ด๋ฏธ์ง ํ์๋ `/storage/artworks/{image_path}` ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ๊ณ , `php artisan storage:link` ๋ช
๋ น์ผ๋ก ์ฌ๋ณผ๋ฆญ ๋งํฌ๋ฅผ ์์ฑํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: http://localhost:8000์ ์ ์ํ๋ฉด ์ํ ๊ฐค๋ฌ๋ฆฌ ๊ทธ๋ฆฌ๋๊ฐ ํ์๋ฉ๋๋ค. 12๊ฐ ์ด์์ ์ํ ์นด๋๊ฐ ๋ณด์ด๋ฉฐ, ๊ฐ ์นด๋๋ ์ด๋ฏธ์ง, ์ ๋ชฉ, ์๊ฐ๋ช , ๊ฐ๊ฒฉ์ ํฌํจํฉ๋๋ค. ์นด๋์ ํธ๋ฒํ๋ฉด ์๊ฐ์ ํจ๊ณผ๊ฐ ๋ํ๋ฉ๋๋ค.
์นดํ ๊ณ ๋ฆฌ ํํฐ๋ง ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ฃผ์ธ์. 1. **Gallery/Index.jsx ์์ **: - ์๋จ์ ์นดํ ๊ณ ๋ฆฌ ๋ฒํผ ์ถ๊ฐ (All, Painting, Sculpture, Photography, Digital) - useState๋ก selectedCategory ์ํ ๊ด๋ฆฌ - ๋ฒํผ ํด๋ฆญ ์ selectedCategory ์ ๋ฐ์ดํธ - artworks๋ฅผ ํํฐ๋งํ์ฌ ์ ํ๋ ์นดํ ๊ณ ๋ฆฌ๋ง ํ์ (All์ด๋ฉด ์ ์ฒด ํ์) - ์ ํ๋ ๋ฒํผ์ ๋ค๋ฅธ ์์์ผ๋ก ๊ฐ์กฐ (Tailwind์ bg-blue-500 ๋ฑ) 2. **๊ฒ์ ๊ธฐ๋ฅ ์ถ๊ฐ**: - ์ ๋ ฅ ํ๋ ์ถ๊ฐ (์ํ๋ช ๋๋ ์๊ฐ๋ช ๊ฒ์) - useState๋ก searchQuery ์ํ ๊ด๋ฆฌ - artworks๋ฅผ ํํฐ๋งํ์ฌ ๊ฒ์์ด์ ๋งค์นญ๋๋ ์ํ๋ง ํ์ - ์นดํ ๊ณ ๋ฆฌ ํํฐ์ ๊ฒ์ ํํฐ๋ฅผ ๋์์ ์ ์ฉ 3. **UI ๊ฐ์ **: - ํํฐ/๊ฒ์ ์น์ ์ ์๋จ์ ๊ณ ์ ํ๊ฑฐ๋ sticky๋ก ์ค์ - ํํฐ ๊ฒฐ๊ณผ๊ฐ ์์ ๋ "No artworks found" ๋ฉ์์ง ํ์ - ์ ๋๋ฉ์ด์ ํจ๊ณผ ์ถ๊ฐ (์นด๋ fade-in ๋ฑ) Tailwind CSS์ transition๊ณผ transform์ ํ์ฉํ์ฌ ๋ถ๋๋ฌ์ด UX๋ฅผ ๊ตฌํํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ๊ฐค๋ฌ๋ฆฌ ์๋จ์ ์นดํ ๊ณ ๋ฆฌ ๋ฒํผ๊ณผ ๊ฒ์์ฐฝ์ด ํ์๋ฉ๋๋ค. ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ ํํ๊ฑฐ๋ ๊ฒ์์ด๋ฅผ ์ ๋ ฅํ๋ฉด ์ํ ๋ชฉ๋ก์ด ์ค์๊ฐ์ผ๋ก ํํฐ๋ง๋ฉ๋๋ค. ์ ํ๋ ์นดํ ๊ณ ๋ฆฌ ๋ฒํผ์ ํ์ด๋ผ์ดํธ ๋๊ณ , ํํฐ ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ์๋ด ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค.
์ํ ์์ธ ํ์ด์ง๋ฅผ ๊ตฌํํด์ฃผ์ธ์.
1. **๋ผ์ฐํธ ์ถ๊ฐ**: routes/web.php
- GET '/artworks/{id}' โ ArtworkController@show
2. **์ปจํธ๋กค๋ฌ ๋ฉ์๋**: ArtworkController@show
- Artwork::findOrFail($id)๋ก ์ํ ์กฐํ
- Inertia::render('Gallery/Show', ['artwork' => $artwork])๋ก ์ ๋ฌ
3. **React ์ปดํฌ๋ํธ**: resources/js/Pages/Gallery/Show.jsx
- ํฐ ์ํ ์ด๋ฏธ์ง ํ์ (์ด๋ฏธ์ง ํด๋ฆญ ์ ๋ชจ๋ฌ๋ก ํ๋ - ์ ํ ์ฌํญ)
- ์ํ ์ ๋ณด ํ์: ์ ๋ชฉ, ์๊ฐ๋ช
, ์นดํ
๊ณ ๋ฆฌ, ์ค๋ช
, ํฌ๊ธฐ, ์ฌ๋ฃ, ๊ฐ๊ฒฉ
- ํ๋งค ์ฌ๋ถ ๋ฐฐ์ง (Available / Sold Out)
- "๊ตฌ๋งค ๋ฌธ์" ๋ฒํผ (ํด๋ฆญ ์ ๋ฌธ์ ํผ์ผ๋ก ์คํฌ๋กค)
- ์ข์์ ๋ฒํผ (ํํธ ์์ด์ฝ, ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ์ ์ฅ)
- ๋ค๋ก ๊ฐ๊ธฐ ๋ฒํผ (๊ฐค๋ฌ๋ฆฌ๋ก ๋์๊ฐ๊ธฐ)
4. **๋ ์ด์์**: 2์ปฌ๋ผ ๋ ์ด์์ (์ผ์ชฝ: ์ด๋ฏธ์ง, ์ค๋ฅธ์ชฝ: ์ ๋ณด)
- ๋ชจ๋ฐ์ผ์์๋ 1์ปฌ๋ผ์ผ๋ก ์ ํ
- Tailwind CSS๋ก ๊น๋ํ ๋์์ธ
์ข์์ ๊ธฐ๋ฅ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ํ์ฉํ์ฌ ํด๋ผ์ด์ธํธ ์ธก์์๋ง ์ฒ๋ฆฌํฉ๋๋ค (๋ฐฑ์๋ ์ ์ฅ ์ ํ ์ฌํญ).
๊ธฐ๋ ๊ฒฐ๊ณผ: ๊ฐค๋ฌ๋ฆฌ์์ ์ํ ์นด๋๋ฅผ ํด๋ฆญํ๋ฉด ์์ธ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค. ํฐ ์ด๋ฏธ์ง์ ํจ๊ป ์ํ์ ๋ชจ๋ ์ ๋ณด๊ฐ ํ์๋๊ณ , ์ข์์ ๋ฒํผ๊ณผ ๊ตฌ๋งค ๋ฌธ์ ๋ฒํผ์ด ๋ณด์ ๋๋ค. ๋ฐ์ํ์ผ๋ก ๋ชจ๋ฐ์ผ์์๋ ์ ๋ณด์ ๋๋ค.
๊ตฌ๋งค ๋ฌธ์ ํผ์ ๊ตฌํํด์ฃผ์ธ์.
1. **๋ฌธ์ ๋ชจ๋ธ ์์ฑ**: `php artisan make:model Inquiry -m`
- ๋ง์ด๊ทธ๋ ์ด์
์ปฌ๋ผ: id, artwork_id, name, email, message, created_at, updated_at
- Artwork์ ๊ด๊ณ ์ค์ (belongsTo)
- ๋ง์ด๊ทธ๋ ์ด์
์คํ
2. **Gallery/Show.jsx์ ๋ฌธ์ ํผ ์ถ๊ฐ**:
- ์ํ ์ ๋ณด ์๋์ ๋ฌธ์ ํผ ์น์
์ถ๊ฐ
- ์
๋ ฅ ํ๋: ์ด๋ฆ, ์ด๋ฉ์ผ, ๋ฉ์์ง
- useForm (Inertia.js์ form helper) ์ฌ์ฉํ์ฌ ํผ ์ํ ๊ด๋ฆฌ
- ์ ์ถ ๋ฒํผ ํด๋ฆญ ์ POST /artworks/{id}/inquiries๋ก ์ ์ก
- ํผ ์ ์ถ ํ ์ฑ๊ณต ๋ฉ์์ง ํ์ (Inertia flash message ํ์ฉ)
3. **๋ผ์ฐํธ ์ถ๊ฐ**: routes/web.php
- POST '/artworks/{id}/inquiries' โ ArtworkController@storeInquiry
4. **์ปจํธ๋กค๋ฌ ๋ฉ์๋**: ArtworkController@storeInquiry
- Request validation (name, email, message ํ์)
- Inquiry::create()๋ก ๋ฐ์ดํฐ ์ ์ฅ
- redirect()->back()->with('success', '๋ฌธ์๊ฐ ์ ์ก๋์์ต๋๋ค.')
5. **์ด๋ฉ์ผ ์๋ฆผ (์ ํ ์ฌํญ)**:
- `php artisan make:mail InquiryReceived --markdown=emails.inquiry`
- ๋ฌธ์ ์ ์ฅ ํ Mail::to('gallery@example.com')->send(new InquiryReceived($inquiry))
- .env์ ๋ฉ์ผ ์ค์ (๊ฐ๋ฐ ์ mailtrap ๋๋ log ๋๋ผ์ด๋ฒ ์ฌ์ฉ)
ํผ ๋์์ธ์ Tailwind CSS๋ก ๊น๋ํ๊ฒ ๋ง๋ค๊ณ , ์ ํจ์ฑ ๊ฒ์ฌ ์๋ฌ ๋ฉ์์ง๋ ํ์ํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ์ํ ์์ธ ํ์ด์ง ํ๋จ์ ๊ตฌ๋งค ๋ฌธ์ ํผ์ด ํ์๋ฉ๋๋ค. ์ด๋ฆ, ์ด๋ฉ์ผ, ๋ฉ์์ง๋ฅผ ์ ๋ ฅํ๊ณ ์ ์ถํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๊ณ , ์ฑ๊ณต ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค. ์ ํจ์ฑ ๊ฒ์ฌ ์๋ฌ ์ ์๋ฌ ๋ฉ์์ง๊ฐ ๋ํ๋ฉ๋๋ค.
๊ฐค๋ฌ๋ฆฌ UI/UX๋ฅผ ๊ฐ์ ํ๊ณ ๋ง๋ฌด๋ฆฌ ์์ ์ ํด์ฃผ์ธ์. 1. **๋ค๋น๊ฒ์ด์ ๋ฐ ์ถ๊ฐ**: - ์๋จ์ ๋ก๊ณ /์ฌ์ดํธ๋ช ๊ณผ "Gallery", "About" ๋งํฌ ์ถ๊ฐ - ๋ชจ๋ฐ์ผ์์๋ ํ๋ฒ๊ฑฐ ๋ฉ๋ด๋ก ์ ํ 2. **์ ๋ ฌ ๊ธฐ๋ฅ ์ถ๊ฐ** (Gallery/Index.jsx): - ๋๋กญ๋ค์ด ๋ฉ๋ด๋ก ์ ๋ ฌ ์ต์ ์ ๊ณต (์ต์ ์, ๊ฐ๊ฒฉ ๋ฎ์์, ๊ฐ๊ฒฉ ๋์์) - useState๋ก sortBy ์ํ ๊ด๋ฆฌ - artworks ๋ฐฐ์ด์ ์ ๋ ฌํ์ฌ ํ์ 3. **ํ์ด์ง๋ค์ด์ ๋๋ ๋ฌดํ ์คํฌ๋กค**: - Laravel์ paginate() ์ฌ์ฉํ์ฌ ์ํ ๋ชฉ๋ก ํ์ด์ง๋ค์ด์ - Inertia.js์ Link ์ปดํฌ๋ํธ๋ก ํ์ด์ง ์ด๋ - ๋๋ React Infinite Scroll ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ฉ 4. **๋ก๋ฉ ์ํ ํ์**: - Inertia.js์ progress indicator ํ์ฉ - ์ํ ์นด๋ ๋ก๋ฉ ์ ์ค์ผ๋ ํค UI ํ์ 5. **์ด๋ฏธ์ง ์ต์ ํ**: - Lazy loading ์ ์ฉ (loading="lazy" ์์ฑ) - ์ด๋ฏธ์ง ๋น์จ ์ ์ง (aspect-ratio ์ค์ ) 6. **์ ๊ทผ์ฑ ๊ฐ์ **: - alt ํ ์คํธ ์ถ๊ฐ - ํค๋ณด๋ ๋ค๋น๊ฒ์ด์ ์ง์ - ARIA ๋ผ๋ฒจ ์ถ๊ฐ 7. **๋ฐ์ํ ํ ์คํธ**: - ๋ชจ๋ฐ์ผ, ํ๋ธ๋ฆฟ, ๋ฐ์คํฌํฑ์์ ๋ ์ด์์ ํ์ธ - Chrome DevTools๋ก ๋ค์ํ ํ๋ฉด ํฌ๊ธฐ ํ ์คํธ 8. **README ์์ฑ**: - ํ๋ก์ ํธ ์ค๋ช , ์ค์น ๋ฐฉ๋ฒ, ์คํ ๋ฐฉ๋ฒ ์์ฑ - ์คํฌ๋ฆฐ์ท ์ถ๊ฐ ๋ชจ๋ ๊ธฐ๋ฅ์ด ์ ์ ์๋ํ๋์ง ์ต์ข ํ ์คํธ๋ฅผ ์งํํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: ๊ฐค๋ฌ๋ฆฌ ํ๋ซํผ์ด ์์ฑ๋ฉ๋๋ค. ๋ค๋น๊ฒ์ด์ , ์ ๋ ฌ, ํ์ด์ง๋ค์ด์ ์ด ์ถ๊ฐ๋๊ณ , ๋ก๋ฉ ์ํ์ ์ค์ผ๋ ํค UI๊ฐ ํ์๋ฉ๋๋ค. ๋ชจ๋ ํ๋ฉด ํฌ๊ธฐ์์ ๋ฐ์ํ์ผ๋ก ์ ์๋ํ๋ฉฐ, ์ ๊ทผ์ฑ์ด ๊ฐ์ ๋์์ต๋๋ค. README ํ์ผ์ด ์์ฑ๋์ด ํ๋ก์ ํธ๋ฅผ ์ฝ๊ฒ ์ดํดํ๊ณ ์คํํ ์ ์์ต๋๋ค.
์ ์ถ๋ ์ํ (0)
๋ก๊ทธ์ธ ํ ์ ์ถ์์ง ์ ์ถ๋ ์ํ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋์ ์๊ฐ ๋์ด๋ณด์ธ์!