☕ 카페 멤버십 포인트 적립 페이지 - 구매마다 쌓이는 리워드 시스템
cafe-membership-point-system
문제 설명
프로젝트 개요
카페 고객을 위한 멤버십 포인트 적립 페이지를 만듭니다. 고객이 구매할 때마다 포인트가 쌓이고, 일정 포인트가 모이면 무료 음료나 할인 쿠폰으로 교환할 수 있는 시스템입니다. Laravel 13.x + Blade 템플릿 + Tailwind CSS로 구현하며, SQLite 데이터베이스를 사용합니다.
필수 기능
- 회원 등록 페이지: 이름, 전화번호, 이메일 입력 폼 (간단한 회원가입)
- 포인트 적립 기록: 구매 금액 입력 시 자동으로 포인트 적립 (예: 1,000원당 1포인트)
- 포인트 내역 조회: 회원별 적립/사용 내역을 시간순으로 표시
- 리워드 교환 페이지: 보유 포인트로 교환 가능한 쿠폰 목록 표시 (예: 50포인트 = 아메리카노 무료, 100포인트 = 20% 할인)
- 포인트 사용 처리: 리워드 교환 시 포인트 차감 및 사용 내역 기록
- 회원 목록 페이지: 전체 회원과 보유 포인트를 한눈에 보는 간단한 리스트
선택 추가 기능 (보너스)
- 포인트 적립 시 애니메이션 효과 (Tailwind CSS transition 활용)
- 리워드 교환 시 확인 모달 팝업
- 회원별 포인트 누적 그래프 (간단한 막대 그래프)
- 포인트 만료 기능 (예: 1년 후 자동 소멸)
- 다크모드 지원
기술 스택
- 백엔드: Laravel 13.x (PHP 8.3+)
- 프론트엔드: Blade 템플릿 + Tailwind CSS 3.x
- 데이터베이스: SQLite (간단한 로컬 DB)
- 스타일링: Tailwind CSS CDN 또는 Laravel Mix/Vite 빌드
학습 목표
- Laravel 기본 라우팅과 컨트롤러 사용법 익히기
- Blade 템플릿 문법과 컴포넌트 재사용 이해하기
- Eloquent ORM으로 간단한 CRUD 구현하기
- 마이그레이션과 시더를 활용한 DB 초기화
- Tailwind CSS로 반응형 UI 디자인하기
이 프로젝트는 실제 카페에서 사용할 수 있는 실용적인 서비스이며, Laravel 입문자가 프레임워크의 핵심 개념을 자연스럽게 학습할 수 있도록 설계되었습니다.
제약 조건
- • Laravel 13.x 이상 사용 (최신 LTS 버전)
- • Blade 템플릿 엔진만 사용 (React/Vue 등 SPA 프레임워크 금지)
- • SQLite 데이터베이스 사용 (별도 MySQL 설치 불필요)
- • Tailwind CSS 3.x로 스타일링 (Bootstrap 금지)
- • 회원 인증 시스템은 간소화 (Laravel Breeze 등 풀스택 인증 불필요, 전화번호로 간단 조회)
- • 포인트 계산 로직은 컨트롤러에서 처리 (1,000원당 1포인트 기본 규칙)
- • 리워드 목록은 하드코딩 또는 시더로 초기화 (관리자 페이지 불필요)
- • 페이지네이션은 Laravel 기본 paginate() 메서드 사용
프롬프트 레시피
아래 프롬프트를 순서대로 AI에게 보내면 됩니다. 복사 버튼을 눌러 바로 사용하세요.
mkdir cafe-membership-point-system && cd cafe-membership-point-system
이 폴더에서 Laravel 13.x 프로젝트를 생성하고 초기 설정을 완료합니다.
# 작업 내용
1. Laravel 13.x 프로젝트 생성 (`composer create-project laravel/laravel . "^13.0"`)
2. `.env` 파일에서 데이터베이스를 SQLite로 변경:
```
DB_CONNECTION=sqlite
# DB_HOST, DB_PORT, DB_DATABASE 등 MySQL 관련 설정 주석 처리
```
3. `database/database.sqlite` 파일 생성 (빈 파일)
4. Tailwind CSS 설치 및 설정:
- `npm install -D tailwindcss postcss autoprefixer`
- `npx tailwindcss init -p`
- `tailwind.config.js`에서 content 경로 설정:
```js
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
],
```
- `resources/css/app.css`에 Tailwind 디렉티브 추가:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
- `resources/views/layouts/app.blade.php` 레이아웃 파일 생성 (기본 HTML 구조 + Tailwind CSS 로드)
5. `php artisan serve` 명령으로 서버 실행 확인
# 체크리스트
- [ ] Laravel 13.x 설치 완료
- [ ] SQLite 데이터베이스 설정
- [ ] Tailwind CSS 설치 및 빌드 설정
- [ ] 기본 레이아웃 파일 생성
- [ ] 로컬 서버 실행 확인 (http://localhost:8000)
기대 결과: Laravel 프로젝트가 생성되고, SQLite와 Tailwind CSS가 설정된 상태. 브라우저에서 http://localhost:8000 접속 시 Laravel 기본 화면이 Tailwind 스타일로 표시됨. `npm run dev` 실행 시 Tailwind가 컴파일되어 CSS가 생성됨.
회원(Member) 모델과 마이그레이션을 생성하고, 데이터베이스 구조를 설계합니다.
# 작업 내용
1. Member 모델 및 마이그레이션 생성:
```bash
php artisan make:model Member -m
```
2. 마이그레이션 파일(`database/migrations/xxxx_create_members_table.php`) 수정:
```php
Schema::create('members', function (Blueprint $table) {
$table->id();
$table->string('name'); // 회원 이름
$table->string('phone')->unique(); // 전화번호 (고유값)
$table->string('email')->nullable(); // 이메일 (선택)
$table->integer('points')->default(0); // 보유 포인트
$table->timestamps();
});
```
3. PointHistory 모델 및 마이그레이션 생성 (포인트 적립/사용 내역):
```bash
php artisan make:model PointHistory -m
```
4. PointHistory 마이그레이션 파일 수정:
```php
Schema::create('point_histories', function (Blueprint $table) {
$table->id();
$table->foreignId('member_id')->constrained()->onDelete('cascade'); // 회원 외래키
$table->enum('type', ['earn', 'use']); // 적립 또는 사용
$table->integer('amount'); // 포인트 양 (양수: 적립, 음수: 사용)
$table->integer('purchase_amount')->nullable(); // 구매 금액 (적립 시에만)
$table->string('description')->nullable(); // 설명 (예: "아메리카노 교환")
$table->timestamps();
});
```
5. 마이그레이션 실행:
```bash
php artisan migrate
```
6. Member 모델에 관계 설정 (`app/Models/Member.php`):
```php
public function pointHistories()
{
return $this->hasMany(PointHistory::class);
}
protected $fillable = ['name', 'phone', 'email', 'points'];
```
7. PointHistory 모델에 관계 설정 (`app/Models/PointHistory.php`):
```php
public function member()
{
return $this->belongsTo(Member::class);
}
protected $fillable = ['member_id', 'type', 'amount', 'purchase_amount', 'description'];
```
# 체크리스트
- [ ] Member 모델 및 마이그레이션 생성
- [ ] PointHistory 모델 및 마이그레이션 생성
- [ ] 데이터베이스 테이블 생성 완료 (`php artisan migrate` 성공)
- [ ] 모델 간 관계 설정 (hasMany, belongsTo)
기대 결과: SQLite 데이터베이스에 `members`, `point_histories` 테이블이 생성되고, 모델 간 관계가 설정된 상태. `php artisan tinker`에서 `Member::all()` 실행 시 빈 컬렉션이 반환됨.
회원 등록 페이지와 회원 목록 페이지를 만들고, 기본 CRUD 기능을 구현합니다.
# 작업 내용
1. MemberController 생성:
```bash
php artisan make:controller MemberController
```
2. 라우트 설정 (`routes/web.php`):
```php
use App\Http\Controllers\MemberController;
Route::get('/', [MemberController::class, 'index'])->name('members.index');
Route::get('/members/create', [MemberController::class, 'create'])->name('members.create');
Route::post('/members', [MemberController::class, 'store'])->name('members.store');
Route::get('/members/{member}', [MemberController::class, 'show'])->name('members.show');
```
3. MemberController 메서드 구현:
- `index()`: 전체 회원 목록 표시 (페이지네이션)
- `create()`: 회원 등록 폼 표시
- `store()`: 회원 등록 처리 (유효성 검사 포함)
- `show()`: 회원 상세 정보 및 포인트 내역 표시
4. Blade 뷰 파일 생성:
- `resources/views/members/index.blade.php`: 회원 목록 페이지
- Tailwind로 스타일링된 테이블 (이름, 전화번호, 보유 포인트, 상세보기 링크)
- "회원 등록" 버튼
- `resources/views/members/create.blade.php`: 회원 등록 폼
- 이름, 전화번호, 이메일 입력 필드
- Tailwind 폼 스타일링 (focus 효과, 에러 메시지 표시)
- `resources/views/members/show.blade.php`: 회원 상세 페이지
- 회원 정보 카드
- 보유 포인트 크게 표시
- 포인트 내역 테이블 (아직 비어있음, 다음 단계에서 구현)
5. 유효성 검사 규칙 (MemberController `store()` 메서드):
```php
$request->validate([
'name' => 'required|string|max:255',
'phone' => 'required|string|unique:members,phone|max:20',
'email' => 'nullable|email|max:255',
]);
```
6. Tailwind CSS 컴포넌트 활용:
- 버튼, 폼 입력, 테이블 등 일관된 디자인 적용
- 반응형 레이아웃 (모바일/데스크톱)
# 체크리스트
- [ ] MemberController 생성 및 메서드 구현
- [ ] 라우트 설정 완료
- [ ] 회원 목록 페이지 (index) 생성
- [ ] 회원 등록 폼 (create) 생성
- [ ] 회원 상세 페이지 (show) 생성
- [ ] 유효성 검사 및 에러 메시지 표시
- [ ] Tailwind CSS로 UI 스타일링
기대 결과: 브라우저에서 http://localhost:8000 접속 시 회원 목록 페이지가 표시되고, "회원 등록" 버튼을 클릭하면 등록 폼이 나타남. 폼 제출 시 새 회원이 데이터베이스에 저장되고 목록에 표시됨. 회원 이름 클릭 시 상세 페이지로 이동.
포인트 적립 기능을 구현하고, 구매 금액에 따라 자동으로 포인트를 계산하여 적립합니다.
# 작업 내용
1. PointController 생성:
```bash
php artisan make:controller PointController
```
2. 라우트 추가 (`routes/web.php`):
```php
use App\Http\Controllers\PointController;
Route::post('/members/{member}/earn', [PointController::class, 'earn'])->name('points.earn');
```
3. PointController `earn()` 메서드 구현:
- 구매 금액 입력 받기 (예: 5,000원)
- 포인트 계산 로직 (1,000원당 1포인트, 예: 5,000원 → 5포인트)
- Member 모델의 `points` 필드 업데이트
- PointHistory 레코드 생성 (type: 'earn', amount: 계산된 포인트, purchase_amount: 구매 금액)
- 성공 메시지와 함께 회원 상세 페이지로 리다이렉트
4. 회원 상세 페이지(`resources/views/members/show.blade.php`) 수정:
- 포인트 적립 폼 추가 (구매 금액 입력 필드 + "적립하기" 버튼)
- 적립 시 자동으로 포인트 계산 결과 미리보기 (JavaScript 또는 Alpine.js 사용)
- 포인트 내역 테이블 표시:
- 날짜, 유형(적립/사용), 포인트, 구매 금액, 설명
- 최신 내역이 위에 오도록 정렬 (`orderBy('created_at', 'desc')`)
5. Blade 컴포넌트로 폼 재사용성 높이기:
- `resources/views/components/point-earn-form.blade.php` 생성
- 회원 ID를 props로 받아서 폼 액션 동적 생성
6. 포인트 적립 시 애니메이션 효과 (선택):
- Tailwind CSS transition 클래스 활용
- 적립 성공 시 포인트 숫자가 커지는 효과
# 체크리스트
- [ ] PointController 생성 및 `earn()` 메서드 구현
- [ ] 포인트 계산 로직 (1,000원당 1포인트)
- [ ] 포인트 적립 폼 추가 (회원 상세 페이지)
- [ ] 포인트 내역 테이블 표시
- [ ] 적립 성공 시 리다이렉트 및 메시지 표시
- [ ] (선택) 적립 애니메이션 효과
기대 결과: 회원 상세 페이지에서 구매 금액을 입력하고 "적립하기" 버튼을 누르면, 자동으로 포인트가 계산되어 회원의 보유 포인트가 증가하고, 포인트 내역 테이블에 새 레코드가 추가됨. 예: 5,000원 입력 → 5포인트 적립, 총 보유 포인트 업데이트.
리워드 교환 기능을 구현하고, 보유 포인트로 쿠폰을 교환할 수 있도록 합니다.
# 작업 내용
1. 리워드 목록 정의 (하드코딩 또는 config 파일):
- `config/rewards.php` 파일 생성:
```php
return [
['name' => '아메리카노 무료', 'points' => 50, 'description' => '모든 사이즈 아메리카노 1잔 무료'],
['name' => '음료 20% 할인', 'points' => 100, 'description' => '전 메뉴 20% 할인 쿠폰'],
['name' => '디저트 세트', 'points' => 150, 'description' => '케이크 + 음료 세트 무료'],
];
```
2. 리워드 페이지 라우트 추가 (`routes/web.php`):
```php
Route::get('/members/{member}/rewards', [PointController::class, 'rewards'])->name('points.rewards');
Route::post('/members/{member}/redeem', [PointController::class, 'redeem'])->name('points.redeem');
```
3. PointController 메서드 추가:
- `rewards()`: 리워드 목록 페이지 표시 (회원 정보 + 교환 가능한 리워드 목록)
- `redeem()`: 리워드 교환 처리
- 선택한 리워드의 필요 포인트 확인
- 회원의 보유 포인트가 충분한지 검증
- 포인트 차감 (Member 모델 `points` 업데이트)
- PointHistory 레코드 생성 (type: 'use', amount: -필요포인트, description: 리워드명)
- 성공 메시지와 함께 리워드 페이지로 리다이렉트
4. Blade 뷰 파일 생성:
- `resources/views/members/rewards.blade.php`: 리워드 교환 페이지
- 회원 정보 카드 (이름, 보유 포인트)
- 리워드 목록 그리드 (Tailwind grid 레이아웃)
- 각 리워드 카드:
- 리워드명, 필요 포인트, 설명
- "교환하기" 버튼 (포인트 부족 시 비활성화)
- 교환 불가능한 리워드는 회색 처리 및 "포인트 부족" 배지 표시
5. 교환 확인 모달 (선택):
- Alpine.js 또는 Tailwind UI 모달 컴포넌트 활용
- "정말 교환하시겠습니까?" 확인 팝업
6. 회원 상세 페이지에 "리워드 교환" 버튼 추가:
- `resources/views/members/show.blade.php`에 리워드 페이지 링크 추가
# 체크리스트
- [ ] 리워드 목록 정의 (`config/rewards.php`)
- [ ] 리워드 페이지 라우트 추가
- [ ] `rewards()` 메서드 구현 (리워드 목록 표시)
- [ ] `redeem()` 메서드 구현 (교환 처리 및 포인트 차감)
- [ ] 리워드 교환 페이지 생성 (Blade 뷰)
- [ ] 포인트 부족 시 버튼 비활성화 로직
- [ ] (선택) 교환 확인 모달
- [ ] 회원 상세 페이지에 리워드 링크 추가
기대 결과: 회원 상세 페이지에서 "리워드 교환" 버튼을 클릭하면 리워드 목록 페이지로 이동. 보유 포인트가 충분한 리워드만 "교환하기" 버튼이 활성화되고, 클릭 시 포인트가 차감되며 포인트 내역에 사용 기록이 추가됨. 예: 50포인트 보유 → "아메리카노 무료" 교환 → 0포인트 남음.
제출된 작품 (0)
로그인 후 제출아직 제출된 작품이 없습니다. 첫 번째 도전자가 되어보세요!