๐ญ ์ฐ๊ทน ๊ณต์ฐ ํ๊ธฐ & ์ฌ์ง ๊ฐค๋ฌ๋ฆฌ - ๊ด๊ฐ์ด ๋ง๋๋ ๊ณต์ฐ ์์นด์ด๋ธ
theater-audience-review-gallery
๋ฌธ์ ์ค๋ช
๐ญ ์ฐ๊ทน ๊ณต์ฐ ํ๊ธฐ & ์ฌ์ง ๊ฐค๋ฌ๋ฆฌ
๊ด๊ฐ๋ค์ด ์ง์ ๊ด๋ํ ์ฐ๊ทน ๊ณต์ฐ์ ํ๊ธฐ์ ์ฌ์ง์ ์ ๋ก๋ํ์ฌ ๊ณต์ ํ๋ ํ๋ซํผ์ ๋๋ค. Laravel 13.x + Blade ํ ํ๋ฆฟ์ผ๋ก ๊ตฌํํ๋ฉฐ, ๊ณต์ฐ๋ณ๋ก ๊ด๊ฐ๋ค์ ์์ํ ๋ฐ์์ ๋ชจ์๋ณผ ์ ์์ต๋๋ค.
๐ฏ ํต์ฌ ๊ธฐ๋ฅ
- ๊ณต์ฐ ์ ๋ณด ๋ฑ๋ก (์ ๋ชฉ, ๊ทน๋จ๋ช , ๊ณต์ฐ ๊ธฐ๊ฐ, ์ฅ์, ํฌ์คํฐ ์ด๋ฏธ์ง)
- ๊ณต์ฐ๋ณ ํ๊ธฐ ์์ฑ (๋ณ์ , ๊ด๋ ๋ ์ง, ๊ฐ์ํ, ์ฌ์ง ์ ๋ก๋)
- ๊ณต์ฐ ๋ชฉ๋ก ํ์ด์ง (์นด๋ ๋ ์ด์์ with ํ๊ท ๋ณ์ )
- ๊ณต์ฐ ์์ธ ํ์ด์ง (ํ๊ธฐ ๋ชฉ๋ก & ์ฌ์ง ๊ฐค๋ฌ๋ฆฌ)
- ํ๊ธฐ ์ข์์ ๊ธฐ๋ฅ (๊ณต๊ฐ ํ์)
- ๋ณ์ ํํฐ๋ง (5์ ๋ง, 4์ ์ด์ ๋ฑ)
- ๋ฐ์ํ ๋์์ธ (Tailwind CSS)
๐ ๋ณด๋์ค ๊ธฐ๋ฅ
- ํ๊ธฐ ์ ๋ ฌ (์ต์ ์, ์ข์์์, ๋ณ์ ์)
- ์ฌ์ง ํด๋ฆญ ์ ๋ชจ๋ฌ๋ก ํฌ๊ฒ ๋ณด๊ธฐ
- ๊ณต์ฐ ๊ฒ์ ๊ธฐ๋ฅ (์ ๋ชฉ, ๊ทน๋จ๋ช )
- ๋ฒ ์คํธ ํ๊ธฐ ๋ฐฐ์ง (์ข์์ 10๊ฐ ์ด์)
- ๊ด๋ ์ธ์ฆ ์คํฐ์ปค (๋ ์ง ๋์ฅ)
๐จ ๋์์ธ ํฌ์ธํธ
- ๊ทน์ฅ ๋ถ์๊ธฐ์ ๋คํฌ ํ ๋ง UI
- ๋ณ์ ์ ๋๋ฉ์ด์ ํจ๊ณผ
- ์ฌ์ง ๊ทธ๋ฆฌ๋ ๋ ์ด์์ (Pinterest ์คํ์ผ)
- ํธ๋ฒ ์ ์นด๋ ๋ฆฌํํธ ํจ๊ณผ
์ ์ฝ ์กฐ๊ฑด
- โข Laravel 13.x ํ์ ์ฌ์ฉ
- โข Blade ํ ํ๋ฆฟ ์์ง ์ฌ์ฉ (React/Vue ๊ธ์ง)
- โข SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฌ์ฉ
- โข Tailwind CSS๋ก ์คํ์ผ๋ง
- โข ์ด๋ฏธ์ง ์ ๋ก๋๋ public/storage ์ฌ์ฉ
- โข ๋ผ์ฐํธ๋ web.php์ ์ ์
- โข ๋ชจ๋ธ๋ช : Performance, Review
- โข ๋ง์ด๊ทธ๋ ์ด์ ์ผ๋ก ํ ์ด๋ธ ์คํค๋ง ๊ด๋ฆฌ
- โข Blade ์ปดํฌ๋ํธ ํ์ฉ (๋ณ์ ํ์, ์นด๋ ๋ฑ)
- โข ํ์ผ ์ ๋ก๋ validation (์ด๋ฏธ์ง๋ง, ์ต๋ 2MB)
ํ๋กฌํํธ ๋ ์ํผ
์๋ ํ๋กฌํํธ๋ฅผ ์์๋๋ก AI์๊ฒ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค. ๋ณต์ฌ ๋ฒํผ์ ๋๋ฌ ๋ฐ๋ก ์ฌ์ฉํ์ธ์.
mkdir theater-audience-review-gallery && cd theater-audience-review-gallery ์ด ํด๋์์ Laravel 13.x ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ ๊ธฐ๋ณธ ์ค์ ์ ์๋ฃํฉ๋๋ค. # ์๊ตฌ์ฌํญ 1. Laravel 13.x ํ๋ก์ ํธ ์์ฑ 2. SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์ (.env ํ์ผ์์ DB_CONNECTION=sqlite) 3. database/database.sqlite ํ์ผ ์์ฑ 4. Tailwind CSS ์ค์น ๋ฐ ์ค์ (Laravel Breeze ์์ด ์์ Tailwind) 5. public/storage ์ฌ๋ณผ๋ฆญ ๋งํฌ ์์ฑ (php artisan storage:link) # ๋ง์ด๊ทธ๋ ์ด์ ์์ฑ - performances ํ ์ด๋ธ: id, title, company_name, poster_image, venue, start_date, end_date, description, created_at, updated_at - reviews ํ ์ด๋ธ: id, performance_id, rating(1-5), review_date, content, photo_path(nullable), likes_count(default 0), created_at, updated_at # ๋ชจ๋ธ ์์ฑ - Performance ๋ชจ๋ธ: hasMany reviews ๊ด๊ณ ์ ์ - Review ๋ชจ๋ธ: belongsTo performance ๊ด๊ณ ์ ์ # ๊ธฐ๋ณธ ๋ ์ด์์ ์์ฑ - resources/views/layouts/app.blade.php ์์ฑ - ๋คํฌ ํ ๋ง ๊ทน์ฅ ๋ถ์๊ธฐ (๋ฐฐ๊ฒฝ์ #1a1a2e, ์ก์ผํธ #e94560) - ๋ค๋น๊ฒ์ด์ ๋ฐ ํฌํจ (๋ก๊ณ , ๊ณต์ฐ ๋ชฉ๋ก ๋งํฌ) php artisan migrate ์คํ๊น์ง ์๋ฃํด์ฃผ์ธ์.
๊ธฐ๋ ๊ฒฐ๊ณผ: Laravel ํ๋ก์ ํธ๊ฐ ์์ฑ๋๊ณ , SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค์ performances์ reviews ํ ์ด๋ธ์ด ๋ง์ด๊ทธ๋ ์ด์ ๋ฉ๋๋ค. Performance์ Review ๋ชจ๋ธ์ด ๊ด๊ณ ์ค์ ๊ณผ ํจ๊ป ์์ฑ๋๋ฉฐ, Tailwind CSS๊ฐ ์ค์ ๋ ๊ธฐ๋ณธ ๋ ์ด์์ ํ์ผ์ด ์ค๋น๋ฉ๋๋ค.
๊ณต์ฐ ๋ชฉ๋ก ํ์ด์ง์ ๊ณต์ฐ ๋ฑ๋ก ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
# ๋ผ์ฐํธ (routes/web.php)
- GET / โ ๊ณต์ฐ ๋ชฉ๋ก ํ์ด์ง
- GET /performances/create โ ๊ณต์ฐ ๋ฑ๋ก ํผ
- POST /performances โ ๊ณต์ฐ ์ ์ฅ
- GET /performances/{id} โ ๊ณต์ฐ ์์ธ ํ์ด์ง
# ์ปจํธ๋กค๋ฌ (PerformanceController)
- index(): ๋ชจ๋ ๊ณต์ฐ์ ํ๊ท ๋ณ์ ๊ณผ ํจ๊ป ์กฐํ (์นด๋ ๊ทธ๋ฆฌ๋ ๋ ์ด์์)
- create(): ๊ณต์ฐ ๋ฑ๋ก ํผ ํ์
- store(): ๊ณต์ฐ ์ ์ฅ (ํฌ์คํฐ ์ด๋ฏธ์ง ์
๋ก๋ ํฌํจ, validation)
- show($id): ๊ณต์ฐ ์์ธ ์ ๋ณด + ํ๊ธฐ ๋ชฉ๋ก ํ์
# ๋ทฐ ํ์ผ
- resources/views/performances/index.blade.php: ๊ณต์ฐ ์นด๋ ๊ทธ๋ฆฌ๋ (ํฌ์คํฐ, ์ ๋ชฉ, ๊ทน๋จ๋ช
, ํ๊ท ๋ณ์ ํ์)
- resources/views/performances/create.blade.php: ๊ณต์ฐ ๋ฑ๋ก ํผ (ํ์ผ ์
๋ก๋ ํฌํจ)
- Blade ์ปดํฌ๋ํธ resources/views/components/star-rating.blade.php ์์ฑ (๋ณ์ ํ์์ฉ, 1-5์ )
# Tailwind CSS ์คํ์ผ๋ง
- ์นด๋ ํธ๋ฒ ์ transform scale-105 ํจ๊ณผ
- ํฌ์คํฐ ์ด๋ฏธ์ง aspect-ratio-3/4
- ๊ทธ๋ฆฌ๋ ๋ ์ด์์ (lg:grid-cols-3 md:grid-cols-2)
# Validation
- title: required, max:255
- poster_image: required, image, max:2048
- start_date, end_date: required, date
๊ธฐ๋ ๊ฒฐ๊ณผ: ๊ณต์ฐ ๋ชฉ๋ก ํ์ด์ง์์ ๋ฑ๋ก๋ ๊ณต์ฐ๋ค์ด ์นด๋ ํํ๋ก ํ์๋๋ฉฐ, ๊ณต์ฐ ๋ฑ๋ก ํผ์ ํตํด ์ ๊ณต์ฐ์ ์ถ๊ฐํ ์ ์์ต๋๋ค. ํฌ์คํฐ ์ด๋ฏธ์ง ์ ๋ก๋๊ฐ ์ ์ ์๋ํ๊ณ , ํ๊ท ๋ณ์ ์ด ๊ณ์ฐ๋์ด ํ์๋ฉ๋๋ค.
๊ณต์ฐ ์์ธ ํ์ด์ง์ ํ๊ธฐ ์์ฑ ๊ธฐ๋ฅ๊ณผ ํ๊ธฐ ๋ชฉ๋ก์ ๊ตฌํํฉ๋๋ค.
# ๋ผ์ฐํธ ์ถ๊ฐ
- POST /performances/{id}/reviews โ ํ๊ธฐ ์ ์ฅ
- POST /reviews/{id}/like โ ํ๊ธฐ ์ข์์
# ์ปจํธ๋กค๋ฌ (ReviewController)
- store($performanceId): ํ๊ธฐ ์ ์ฅ (๋ณ์ , ๊ด๋ ๋ ์ง, ๊ฐ์ํ, ์ฌ์ง ์
๋ก๋)
- like($id): ํ๊ธฐ ์ข์์ ์ฆ๊ฐ (likes_count++)
# ๋ทฐ ์์ (performances/show.blade.php)
- ๊ณต์ฐ ์ ๋ณด ์๋จ ํ์ (ํฌ์คํฐ, ์ ๋ชฉ, ๊ทน๋จ๋ช
, ๊ณต์ฐ ๊ธฐ๊ฐ, ํ๊ท ๋ณ์ )
- ํ๊ธฐ ์์ฑ ํผ (๋ณ์ ์ ํ ๋ผ๋์ค ๋ฒํผ with ๋ณ ์์ด์ฝ, ๊ด๋ ๋ ์ง, ๊ฐ์ํ textarea, ์ฌ์ง ์
๋ก๋)
- ํ๊ธฐ ๋ชฉ๋ก ํ์ (์นด๋ ํํ, ๋ณ์ , ๊ด๋ ๋ ์ง, ๊ฐ์ํ, ์ฌ์ง, ์ข์์ ์)
- ํ๊ธฐ ์ฌ์ง ํด๋ฆญ ์ ์ ํญ์์ ํฌ๊ฒ ๋ณด๊ธฐ (target="_blank")
# Blade ์ปดํฌ๋ํธ
- resources/views/components/review-card.blade.php ์์ฑ (ํ๊ธฐ ์นด๋ UI)
- ์ข์์ ๋ฒํผ (ํํธ ์์ด์ฝ, ํด๋ฆญ ์ POST ์์ฒญ)
# Validation
- rating: required, integer, between:1,5
- review_date: required, date
- content: required, min:10
- photo: nullable, image, max:2048
# ์คํ์ผ๋ง
- ํ๊ธฐ ์นด๋ border-l-4 border-pink-500 (์ก์ผํธ)
- ๋ณ์ ์ ํ ์ ๋
ธ๋์ ๋ณ ์ฑ์ฐ๊ธฐ ํจ๊ณผ
- ์ฌ์ง rounded-lg shadow-md
๊ธฐ๋ ๊ฒฐ๊ณผ: ๊ณต์ฐ ์์ธ ํ์ด์ง์์ ํ๊ธฐ๋ฅผ ์์ฑํ ์ ์์ผ๋ฉฐ, ์์ฑ๋ ํ๊ธฐ๋ค์ด ๋ชฉ๋ก์ผ๋ก ํ์๋ฉ๋๋ค. ๋ณ์ , ๊ด๋ ๋ ์ง, ๊ฐ์ํ, ์ฌ์ง์ด ๋ชจ๋ ์ ์ฅ๋๊ณ , ์ข์์ ๊ธฐ๋ฅ์ด ์๋ํฉ๋๋ค. ์ฌ์ง์ ํด๋ฆญํ๋ฉด ํฌ๊ฒ ๋ณผ ์ ์์ต๋๋ค.
์ ์ถ๋ ์ํ (0)
๋ก๊ทธ์ธ ํ ์ ์ถ์์ง ์ ์ถ๋ ์ํ์ด ์์ต๋๋ค. ์ฒซ ๋ฒ์งธ ๋์ ์๊ฐ ๋์ด๋ณด์ธ์!