온라인 클래스 수강평 플랫폼 - 별점 & 상세 리뷰 작성
online-course-review-platform
문제 설명
프로젝트 개요
온라인 강의 플랫폼에서 수강생들이 수강한 클래스에 대한 솔직한 리뷰를 남기고 다른 사람들의 후기를 확인할 수 있는 리뷰 플랫폼을 만듭니다. 실제 수강생들의 생생한 경험을 공유하여 예비 수강생들이 현명한 선택을 할 수 있도록 돕는 서비스입니다.
필수 기능
- 클래스 목록 페이지: 카테고리별(프로그래밍, 디자인, 마케팅, 언어 등) 클래스 목록 표시
- 클래스 상세 페이지: 클래스 정보, 평균 별점, 리뷰 목록 표시
- 리뷰 작성 기능: 별점(1~5점), 제목, 상세 내용, 장단점 입력
- 리뷰 정렬: 최신순, 별점 높은순, 별점 낮은순, 도움이 된 순
- 리뷰 도움됨 기능: 다른 사용자가 리뷰에 '도움이 됐어요' 버튼 클릭
- 필터링: 별점별 필터(5점만, 4점 이상 등), 카테고리 필터
- 검색 기능: 클래스명, 강사명으로 검색
- 반응형 디자인: 모바일/태블릿/데스크톱 대응
보너스 기능
- 리뷰 수정/삭제 기능
- 강사 프로필 페이지 (해당 강사의 모든 클래스 & 평균 평점)
- 내가 작성한 리뷰 모아보기 (마이페이지)
- 리뷰 신고 기능
- 클래스 찜하기 기능
- 최근 본 클래스 히스토리
기술 스택
- 백엔드: Laravel 13.x (Eloquent ORM, Migration, Seeder)
- 프론트엔드: React 19 + Inertia.js
- 스타일링: Tailwind CSS
- 데이터베이스: SQLite (개발용) 또는 MySQL
- 인증: Laravel Breeze (선택사항)
이 프로젝트를 통해 Laravel의 관계형 데이터베이스 설계(클래스, 리뷰, 카테고리 관계), Inertia.js를 통한 SPA 경험, React의 상태 관리와 컴포넌트 분리, 그리고 실제 서비스 수준의 필터링/정렬/검색 기능 구현을 학습할 수 있습니다.
제약 조건
- • Laravel 13.x + Inertia.js + React 19 모노리스 풀스택 구조 사용
- • 별도 REST API 라우트 없이 Inertia::render()로 데이터 전달
- • Laravel Breeze (React + Inertia) starter kit으로 프로젝트 초기화
- • Tailwind CSS로 스타일링 (CDN 또는 npm 설치)
- • 데이터베이스는 SQLite 또는 MySQL 사용
- • 리뷰 작성 시 별점은 1~5점 범위로 제한
- • 평균 별점은 소수점 첫째 자리까지 표시
- • 페이지네이션은 Laravel의 paginate() 메서드 활용
- • Inertia.js의 Link 컴포넌트로 페이지 이동 (새로고침 없이)
- • 폼 검증은 Laravel의 FormRequest 또는 validate() 메서드 사용
프롬프트 레시피
아래 프롬프트를 순서대로 AI에게 보내면 됩니다. 복사 버튼을 눌러 바로 사용하세요.
mkdir online-course-review-platform && cd online-course-review-platform 이 폴더에서 Laravel + Inertia.js + React 프로젝트를 시작합니다. # Laravel Breeze (React + Inertia) 프로젝트 생성 다음 명령어로 Laravel 13 프로젝트를 생성하고 Breeze (React + Inertia) starter kit을 설치해주세요: ```bash composer create-project laravel/laravel . composer require laravel/breeze --dev php artisan breeze:install react npm install npm run dev ``` 설치 후 `.env` 파일을 열어 데이터베이스 설정을 SQLite로 변경해주세요: ```env DB_CONNECTION=sqlite # DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD 주석 처리 ``` 그리고 `database/database.sqlite` 파일을 생성해주세요: ```bash touch database/database.sqlite ``` 마이그레이션 실행: ```bash php artisan migrate ``` 서버 실행 확인: ```bash php artisan serve ``` 브라우저에서 http://localhost:8000 접속 시 Laravel 초기 화면이 보이면 성공입니다.
기대 결과: Laravel 13 + Breeze + React + Inertia.js 프로젝트가 생성되고, 기본 인증 화면(로그인/회원가입)이 동작하는 것을 확인할 수 있습니다. npm run dev로 Vite 개발 서버가 실행되고, Tailwind CSS가 적용된 UI를 볼 수 있습니다.
# 데이터베이스 설계 및 마이그레이션 생성 온라인 클래스 리뷰 플랫폼에 필요한 테이블들을 설계하고 마이그레이션을 생성해주세요: ## 필요한 테이블: 1. **categories** (카테고리) - id (PK) - name (카테고리명, 예: 프로그래밍, 디자인, 마케팅) - slug (URL용) - timestamps 2. **courses** (클래스) - id (PK) - category_id (FK) - title (클래스명) - instructor (강사명) - description (클래스 설명) - thumbnail_url (썸네일 이미지 URL, nullable) - price (가격) - duration_hours (수강 시간, 예: 10시간) - timestamps 3. **reviews** (리뷰) - id (PK) - course_id (FK) - user_id (FK) - rating (별점, 1~5) - title (리뷰 제목) - content (상세 내용) - pros (장점, nullable) - cons (단점, nullable) - helpful_count (도움됨 수, default 0) - timestamps 4. **review_helpfuls** (리뷰 도움됨 기록) - id (PK) - review_id (FK) - user_id (FK) - timestamps - unique(review_id, user_id) - 한 사용자가 같은 리뷰에 중복 도움됨 방지 다음 명령어로 마이그레이션 파일을 생성하고 작성해주세요: ```bash php artisan make:migration create_categories_table php artisan make:migration create_courses_table php artisan make:migration create_reviews_table php artisan make:migration create_review_helpfuls_table ``` 각 마이그레이션 파일에 위 스키마를 반영하여 작성해주세요. 외래 키 제약 조건과 인덱스도 추가해주세요. 마이그레이션 실행: ```bash php artisan migrate ```
기대 결과: 4개의 마이그레이션 파일이 생성되고, 각 테이블의 컬럼과 관계가 정의됩니다. php artisan migrate 실행 시 데이터베이스에 테이블이 생성되며, 외래 키 제약 조건이 올바르게 설정됩니다.
# Eloquent 모델 생성 및 관계 설정
각 테이블에 대응하는 Eloquent 모델을 생성하고 관계를 설정해주세요:
```bash
php artisan make:model Category
php artisan make:model Course
php artisan make:model Review
php artisan make:model ReviewHelpful
```
## 모델별 관계 설정:
### Category 모델:
- `courses()`: hasMany 관계 (한 카테고리는 여러 클래스를 가짐)
### Course 모델:
- `category()`: belongsTo 관계
- `reviews()`: hasMany 관계
- `averageRating()`: 평균 별점을 계산하는 accessor 또는 메서드 추가
- `reviewCount()`: 리뷰 개수를 반환하는 메서드
### Review 모델:
- `course()`: belongsTo 관계
- `user()`: belongsTo 관계
- `helpfuls()`: hasMany 관계 (ReviewHelpful)
- `isHelpfulBy($userId)`: 특정 사용자가 도움됨을 눌렀는지 확인하는 메서드
### ReviewHelpful 모델:
- `review()`: belongsTo 관계
- `user()`: belongsTo 관계
각 모델 파일에 관계 메서드를 정의하고, `$fillable` 속성도 설정해주세요.
Course 모델에 평균 별점을 계산하는 메서드 예시:
```php
public function averageRating()
{
return $this->reviews()->avg('rating') ?? 0;
}
```
기대 결과: 4개의 Eloquent 모델이 생성되고, 각 모델 간의 관계(hasMany, belongsTo)가 올바르게 정의됩니다. Course 모델에서 평균 별점과 리뷰 개수를 조회할 수 있는 메서드가 추가됩니다.
# 시더(Seeder) 생성 및 더미 데이터 삽입
개발 및 테스트를 위해 더미 데이터를 생성하는 시더를 작성해주세요:
```bash
php artisan make:seeder CategorySeeder
php artisan make:seeder CourseSeeder
php artisan make:seeder ReviewSeeder
```
## 시더 내용:
### CategorySeeder:
- 프로그래밍, 디자인, 마케팅, 비즈니스, 언어, 음악, 요리 등 7~10개 카테고리 생성
### CourseSeeder:
- 각 카테고리마다 3~5개씩 클래스 생성 (총 30~50개)
- 클래스명, 강사명, 설명, 가격, 수강 시간 등 현실적인 데이터로 작성
- 썸네일은 placeholder 이미지 URL 사용 (예: https://via.placeholder.com/400x300)
### ReviewSeeder:
- 각 클래스마다 3~10개의 리뷰 생성
- 별점은 1~5점 랜덤
- 리뷰 제목, 내용, 장점, 단점을 현실적으로 작성
- user_id는 1~10 범위로 랜덤 (실제 사용자는 없어도 됨, 테스트용)
- helpful_count는 0~20 랜덤
`DatabaseSeeder.php`에서 위 시더들을 호출하도록 설정해주세요:
```php
public function run()
{
$this->call([
CategorySeeder::class,
CourseSeeder::class,
ReviewSeeder::class,
]);
}
```
시더 실행:
```bash
php artisan db:seed
```
기대 결과: 데이터베이스에 카테고리, 클래스, 리뷰 더미 데이터가 삽입됩니다. 각 클래스는 카테고리에 속하고, 각 클래스는 여러 리뷰를 가지며, 리뷰는 별점과 상세 내용을 포함합니다.
# 클래스 목록 페이지 구현 (컨트롤러 + React 컴포넌트)
## 1. CourseController 생성:
```bash
php artisan make:controller CourseController
```
`CourseController.php`에 `index` 메서드를 작성해주세요:
- 모든 클래스를 카테고리와 함께 조회 (eager loading)
- 각 클래스의 평균 별점과 리뷰 개수를 계산하여 전달
- 카테고리 필터, 검색어, 정렬 옵션을 쿼리 파라미터로 받아 처리
- 페이지네이션 적용 (한 페이지당 12개)
- Inertia::render('Courses/Index', [...])로 React 컴포넌트에 데이터 전달
## 2. 라우트 설정:
`routes/web.php`에 다음 라우트 추가:
```php
Route::get('/courses', [CourseController::class, 'index'])->name('courses.index');
```
## 3. React 컴포넌트 생성:
`resources/js/Pages/Courses/Index.jsx` 파일을 생성하고 다음 기능을 구현해주세요:
- props로 courses (페이지네이션 객체), categories, filters (현재 필터 상태) 받기
- 상단에 카테고리 필터 버튼 (전체, 프로그래밍, 디자인 등)
- 검색 입력창 (클래스명/강사명 검색)
- 정렬 드롭다운 (최신순, 평점 높은순, 리뷰 많은순)
- 클래스 카드 그리드 (썸네일, 제목, 강사명, 평균 별점, 리뷰 수, 가격 표시)
- 각 카드 클릭 시 클래스 상세 페이지로 이동 (Inertia Link 사용)
- 페이지네이션 컴포넌트
Tailwind CSS로 반응형 그리드 레이아웃 (모바일 1열, 태블릿 2열, 데스크톱 3~4열) 구성해주세요.
필터/검색/정렬 변경 시 Inertia.get()을 사용하여 쿼리 파라미터를 업데이트하고 페이지를 다시 로드해주세요.
기대 결과: 클래스 목록 페이지가 구현되어 http://localhost:8000/courses 접속 시 모든 클래스가 카드 형태로 표시됩니다. 카테고리 필터, 검색, 정렬 기능이 동작하며, 페이지네이션으로 다음 페이지를 볼 수 있습니다. 각 클래스 카드에는 평균 별점과 리뷰 수가 표시됩니다.
# 클래스 상세 페이지 구현 (리뷰 목록 포함)
## 1. CourseController에 show 메서드 추가:
`CourseController.php`에 `show` 메서드를 작성해주세요:
- URL 파라미터로 클래스 ID를 받아 해당 클래스 조회
- 클래스 정보와 함께 카테고리, 평균 별점, 리뷰 개수 조회
- 해당 클래스의 리뷰 목록을 조회 (작성자 정보 포함, eager loading)
- 리뷰 정렬 옵션 (최신순, 별점 높은순, 별점 낮은순, 도움됨 많은순) 처리
- 별점 필터 (5점만, 4점 이상, 3점 이상 등) 처리
- 리뷰 페이지네이션 (한 페이지당 10개)
- Inertia::render('Courses/Show', [...])로 데이터 전달
## 2. 라우트 추가:
```php
Route::get('/courses/{course}', [CourseController::class, 'show'])->name('courses.show');
```
## 3. React 컴포넌트 생성:
`resources/js/Pages/Courses/Show.jsx` 파일을 생성하고 다음 기능을 구현해주세요:
- 상단에 클래스 정보 섹션 (썸네일, 제목, 강사명, 카테고리, 가격, 수강 시간, 설명)
- 평균 별점 및 리뷰 개수 표시 (별 아이콘으로 시각화)
- 별점 분포 그래프 (5점, 4점, 3점, 2점, 1점 각각 몇 개인지 막대 그래프)
- 리뷰 작성 버튼 (로그인 사용자만, 클릭 시 리뷰 작성 페이지로 이동)
- 리뷰 정렬 드롭다운 (최신순, 별점 높은순, 별점 낮은순, 도움됨 순)
- 별점 필터 버튼 (전체, 5점, 4점 이상, 3점 이상, 2점 이하)
- 리뷰 목록 (각 리뷰: 작성자명, 별점, 제목, 내용, 장점/단점, 작성일, 도움됨 수, 도움됨 버튼)
- 리뷰 페이지네이션
Tailwind CSS로 깔끔한 레이아웃 구성해주세요. 별점은 별 아이콘(★)으로 표시하고, 도움됨 버튼은 👍 아이콘 사용.
정렬/필터 변경 시 Inertia.get()으로 쿼리 파라미터 업데이트.
기대 결과: 클래스 상세 페이지가 구현되어 특정 클래스의 모든 정보와 리뷰 목록이 표시됩니다. 평균 별점과 별점 분포가 시각적으로 표시되고, 리뷰 정렬/필터 기능이 동작합니다. 리뷰 작성 버튼이 보입니다.
# 리뷰 작성 기능 구현
## 1. ReviewController 생성:
```bash
php artisan make:controller ReviewController
```
`ReviewController.php`에 다음 메서드를 작성해주세요:
### create 메서드:
- URL 파라미터로 클래스 ID를 받아 해당 클래스 정보 조회
- Inertia::render('Reviews/Create', [...])로 리뷰 작성 폼 페이지 전달
### store 메서드:
- 폼 데이터 검증 (rating: 1~5 필수, title: 필수, content: 필수, pros/cons: 선택)
- 현재 로그인한 사용자의 user_id와 함께 리뷰 저장
- 저장 후 해당 클래스 상세 페이지로 리다이렉트
- 성공 메시지 플래시
## 2. 라우트 추가:
```php
Route::middleware('auth')->group(function () {
Route::get('/courses/{course}/reviews/create', [ReviewController::class, 'create'])->name('reviews.create');
Route::post('/courses/{course}/reviews', [ReviewController::class, 'store'])->name('reviews.store');
});
```
## 3. React 컴포넌트 생성:
`resources/js/Pages/Reviews/Create.jsx` 파일을 생성하고 다음 기능을 구현해주세요:
- 상단에 리뷰 작성 중인 클래스 정보 표시 (제목, 강사명)
- 별점 선택 UI (1~5점, 클릭 가능한 별 아이콘)
- 리뷰 제목 입력창 (텍스트 필드)
- 상세 내용 입력창 (textarea, 최소 50자)
- 장점 입력창 (textarea, 선택사항)
- 단점 입력창 (textarea, 선택사항)
- 제출 버튼
- 취소 버튼 (클래스 상세 페이지로 돌아가기)
React의 useState로 폼 상태 관리하고, Inertia의 useForm 훅 사용하여 폼 제출 처리.
별점 선택 UI는 interactive하게 구현 (마우스 오버 시 미리보기, 클릭 시 확정).
Tailwind CSS로 깔끔한 폼 레이아웃 구성.
기대 결과: 리뷰 작성 페이지가 구현되어 로그인한 사용자가 클래스에 대한 리뷰를 작성할 수 있습니다. 별점 선택 UI가 interactive하게 동작하고, 폼 검증이 올바르게 작동하며, 리뷰 저장 후 클래스 상세 페이지로 리다이렉트됩니다.
# 리뷰 도움됨 기능 구현
## 1. ReviewController에 toggleHelpful 메서드 추가:
`ReviewController.php`에 `toggleHelpful` 메서드를 작성해주세요:
- URL 파라미터로 리뷰 ID를 받음
- 현재 로그인한 사용자가 해당 리뷰에 이미 도움됨을 눌렀는지 확인
- 눌렀다면 ReviewHelpful 레코드 삭제 & Review의 helpful_count 감소
- 누르지 않았다면 ReviewHelpful 레코드 생성 & Review의 helpful_count 증가
- JSON 응답으로 업데이트된 helpful_count와 현재 사용자의 도움됨 상태 반환
## 2. 라우트 추가:
```php
Route::middleware('auth')->group(function () {
Route::post('/reviews/{review}/helpful', [ReviewController::class, 'toggleHelpful'])->name('reviews.helpful');
});
```
## 3. Courses/Show.jsx 컴포넌트 수정:
리뷰 목록의 각 리뷰에 도움됨 버튼 추가:
- 버튼 텍스트: "👍 도움이 됐어요 (숫자)"
- 현재 사용자가 이미 눌렀다면 버튼 스타일 변경 (활성화 상태)
- 버튼 클릭 시 Inertia.post()로 toggleHelpful 라우트 호출
- 응답 받아서 해당 리뷰의 helpful_count와 활성화 상태 업데이트
- 로그인하지 않은 사용자는 버튼 클릭 시 로그인 페이지로 리다이렉트
React의 useState로 각 리뷰의 도움됨 상태를 관리하고, 버튼 클릭 시 낙관적 업데이트(optimistic update) 적용.
Tailwind CSS로 버튼 스타일링 (기본 상태와 활성화 상태 구분).
기대 결과: 클래스 상세 페이지의 각 리뷰에 도움됨 버튼이 추가되고, 버튼 클릭 시 도움됨 수가 증가/감소합니다. 현재 사용자가 이미 눌렀는지 여부가 시각적으로 표시되며, 로그인하지 않은 사용자는 버튼 클릭 시 로그인 페이지로 이동합니다.
# 메인 페이지 및 네비게이션 개선
## 1. HomeController 생성 및 메인 페이지 구현:
```bash
php artisan make:controller HomeController
```
`HomeController.php`에 `index` 메서드 작성:
- 평균 별점이 높은 인기 클래스 6개 조회
- 최근 등록된 신규 클래스 6개 조회
- 리뷰가 많은 클래스 6개 조회
- Inertia::render('Home', [...])로 데이터 전달
라우트 설정:
```php
Route::get('/', [HomeController::class, 'index'])->name('home');
```
## 2. React 컴포넌트 생성:
`resources/js/Pages/Home.jsx` 파일을 생성하고 다음 기능을 구현해주세요:
- 히어로 섹션 (큰 제목, 설명, "클래스 둘러보기" CTA 버튼)
- "인기 클래스" 섹션 (6개 카드 그리드)
- "신규 클래스" 섹션 (6개 카드 그리드)
- "리뷰가 많은 클래스" 섹션 (6개 카드 그리드)
- 각 섹션마다 "더보기" 버튼 (클래스 목록 페이지로 이동)
Tailwind CSS로 매력적인 랜딩 페이지 디자인 구성.
## 3. 공통 레이아웃 네비게이션 개선:
`resources/js/Layouts/AuthenticatedLayout.jsx` (또는 GuestLayout.jsx)를 수정하여 네비게이션 바 추가:
- 로고 (홈으로 링크)
- "클래스 둘러보기" 메뉴 (courses.index로 링크)
- 검색창 (클래스명 검색, 엔터 시 courses.index로 이동)
- 로그인/회원가입 버튼 (로그인 전) 또는 프로필 드롭다운 (로그인 후)
Inertia의 Link 컴포넌트로 페이지 전환.
Tailwind CSS로 반응형 네비게이션 바 구성 (모바일에서는 햄버거 메뉴).
기대 결과: 메인 페이지가 구현되어 인기 클래스, 신규 클래스, 리뷰 많은 클래스가 섹션별로 표시됩니다. 네비게이션 바가 모든 페이지에 공통으로 표시되며, 로고 클릭 시 홈으로, 클래스 둘러보기 클릭 시 목록 페이지로 이동합니다. 검색 기능이 네비게이션에 통합됩니다.
# 최종 마무리 및 UX 개선 ## 1. 로딩 상태 및 에러 처리: - Inertia의 progress bar 활성화 (nprogress 라이브러리 설치 및 설정) - 각 페이지에서 데이터 로딩 중일 때 스켈레톤 UI 표시 - 폼 제출 중일 때 버튼 비활성화 및 로딩 스피너 표시 - 에러 메시지 표시 (폼 검증 실패 시 각 필드 아래에 에러 메시지) ## 2. 반응형 디자인 최종 점검: - 모든 페이지가 모바일, 태블릿, 데스크톱에서 올바르게 표시되는지 확인 - 네비게이션 바 모바일 햔버거 메뉴 동작 확인 - 클래스 카드 그리드 반응형 레이아웃 확인 - 리뷰 작성 폼 모바일에서 사용성 확인 ## 3. 접근성 개선: - 별점 아이콘에 aria-label 추가 - 버튼에 명확한 텍스트 또는 aria-label 추가 - 폼 필드에 label 연결 - 키보드 내비게이션 지원 확인 ## 4. 성능 최적화: - Eloquent 쿼리에서 N+1 문제 해결 (eager loading 확인) - 불필요한 리렌더링 방지 (React.memo, useMemo 활용) - 이미지 lazy loading 적용 ## 5. README.md 작성: 프로젝트 루트에 `README.md` 파일을 작성하여 다음 내용 포함: - 프로젝트 소개 - 주요 기능 목록 - 기술 스택 - 설치 및 실행 방법 - 스크린샷 (선택사항) - 라이선스 ## 6. 최종 테스트: - 회원가입 → 로그인 → 클래스 둘러보기 → 클래스 상세 → 리뷰 작성 → 도움됨 버튼 클릭 전체 플로우 테스트 - 필터/정렬/검색 기능 동작 확인 - 페이지네이션 동작 확인 - 로그아웃 후 비로그인 상태에서의 동작 확인 (리뷰 작성 버튼 클릭 시 로그인 페이지로 이동) 모든 기능이 정상 동작하면 프로젝트 완성입니다! 🎉
기대 결과: 모든 페이지가 반응형으로 동작하고, 로딩 상태와 에러 처리가 올바르게 구현되어 사용자 경험이 개선됩니다. 접근성과 성능이 최적화되고, README.md가 작성되어 프로젝트를 다른 사람에게 공유할 수 있습니다. 전체 플로우가 원활하게 동작하여 실제 서비스 수준의 온라인 클래스 리뷰 플랫폼이 완성됩니다.
제출된 작품 (0)
로그인 후 제출아직 제출된 작품이 없습니다. 첫 번째 도전자가 되어보세요!