온라인 코스 수강증 발급 플랫폼 - 학습 완료 인증서 자동 생성 - 바이브코딩 레시피
중급 PHP + JavaScript Laravel + React + Inertia.js AI: Claude

온라인 코스 수강증 발급 플랫폼 - 학습 완료 인증서 자동 생성

리포지토리명 course-certificate-generator-inertia
조회수 54 0건 제출

문제 설명

🎓 온라인 코스 수강증 발급 플랫폼

온라인 교육 플랫폼이나 소규모 강의 사업자를 위한 수강증 자동 발급 시스템을 만듭니다. 학생이 코스를 완료하면 자동으로 PDF 수강증을 생성하고, 이메일로 발송하며, 수강증 진위 여부를 확인할 수 있는 고유 인증 번호를 부여합니다.

필수 기능

  • 📚 코스 관리: 강사가 코스 제목, 설명, 수료 기준(예: 80% 이상 진도율)을 등록
  • 👤 학생 등록: 학생이 코스에 등록하고 학습 진행률을 기록
  • 📊 진도율 추적: 학생별 코스 진행률을 자동 계산 (예: 챕터별 완료 체크)
  • 🎖️ 수강증 자동 발급: 수료 조건 달성 시 PDF 수강증 자동 생성 (학생 이름, 코스명, 발급일, 고유 인증번호 포함)
  • ✉️ 이메일 발송: 수강증 PDF를 학생 이메일로 자동 전송 (Laravel Mail + Queue)
  • 🔍 수강증 검증: 인증번호로 수강증 진위 여부를 공개 페이지에서 확인 가능
  • 📜 수강증 목록: 학생이 자신의 모든 수강증을 한눈에 확인하고 재다운로드 가능

보너스 기능

  • 🎨 커스텀 디자인: 강사가 수강증 템플릿 색상/로고를 커스터마이징
  • 📈 통계 대시보드: 강사가 코스별 수료율, 발급된 수강증 수 확인
  • 🏆 배지 시스템: 특정 조건(예: 3개 코스 수료) 달성 시 특별 배지 부여
  • 🌐 소셜 공유: 학생이 수강증을 LinkedIn, Twitter에 공유 가능한 링크 생성

이 프로젝트는 Laravel 13.x + Inertia.js + React 19 모노리스 풀스택으로 구현하며, PDF 생성(DomPDF/Snappy), 이메일 큐, 파일 스토리지를 다루는 실무 기술을 학습할 수 있습니다.

제약 조건

  • • Laravel 13.x + Inertia.js + React 19 사용 (모노리스 풀스택)
  • • npx create laravel 또는 Laravel Breeze (React + Inertia) starter kit으로 프로젝트 생성
  • • Inertia.js로 Laravel 컨트롤러와 React 컴포넌트 연결 (별도 API 라우트 없음)
  • • SQLite 데이터베이스 사용 (개발 편의성)
  • • PDF 생성 라이브러리 사용 (예: barryvdh/laravel-dompdf 또는 spatie/browsershot)
  • • Laravel Mail + Queue를 사용한 이메일 비동기 발송
  • • 파일 스토리지는 Laravel Storage (local 또는 public disk)
  • • Tailwind CSS로 UI 스타일링
  • • React 컴포넌트는 함수형 컴포넌트 + Hooks (useState, useEffect) 사용
  • • 수강증 인증번호는 UUID 또는 랜덤 문자열로 생성하여 DB에 저장
  • • 수강증 검증은 인증 불필요한 공개 페이지로 제공

프롬프트 레시피

아래 프롬프트를 순서대로 AI에게 보내면 됩니다. 복사 버튼을 눌러 바로 사용하세요.

1
Step 1
mkdir course-certificate-generator-inertia && cd course-certificate-generator-inertia

이 폴더에서 Laravel 13.x + Inertia.js + React 19 프로젝트를 생성합니다.

다음 명령으로 Laravel 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 build
```

데이터베이스는 SQLite를 사용합니다. `.env` 파일을 다음과 같이 수정하세요:

```
DB_CONNECTION=sqlite
# DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD 주석 처리
```

`database/database.sqlite` 파일을 생성하고 마이그레이션을 실행하세요:

```bash
touch database/database.sqlite
php artisan migrate
```

이제 기본 인증 시스템(회원가입/로그인)이 포함된 Laravel + Inertia + React 프로젝트가 준비되었습니다. `php artisan serve`로 서버를 실행하고 `http://localhost:8000`에 접속하여 확인하세요.

기대 결과: Laravel Breeze (React + Inertia) 프로젝트가 생성되고, 기본 인증 시스템이 작동합니다. 회원가입/로그인 페이지가 정상적으로 렌더링되고, SQLite 데이터베이스가 연결됩니다.

2
Step 2
코스(Course)와 수강 등록(Enrollment), 수강증(Certificate) 모델을 생성하고 마이그레이션을 작성하세요.

### 요구사항:

1. **Course 모델**: 강사가 생성한 코스 정보를 저장
   - 필드: `id`, `user_id` (강사, users 테이블 FK), `title`, `description`, `completion_threshold` (수료 기준 진도율, 기본값 80), `created_at`, `updated_at`

2. **Enrollment 모델**: 학생이 코스에 등록한 정보
   - 필드: `id`, `user_id` (학생, users 테이블 FK), `course_id` (courses 테이블 FK), `progress` (진도율, 0~100, 기본값 0), `completed_at` (수료 일시, nullable), `created_at`, `updated_at`
   - 인덱스: `user_id`, `course_id` 복합 유니크 인덱스 (중복 등록 방지)

3. **Certificate 모델**: 발급된 수강증 정보
   - 필드: `id`, `enrollment_id` (enrollments 테이블 FK), `certificate_number` (고유 인증번호, UUID), `issued_at`, `pdf_path` (PDF 파일 경로), `created_at`, `updated_at`
   - 인덱스: `certificate_number` 유니크 인덱스

다음 명령으로 모델과 마이그레이션을 생성하세요:

```bash
php artisan make:model Course -m
php artisan make:model Enrollment -m
php artisan make:model Certificate -m
```

각 마이그레이션 파일을 위 스키마대로 작성하고, 모델에 관계(relationship)를 정의하세요:

- `User` 모델: `hasMany(Course)`, `hasMany(Enrollment)`
- `Course` 모델: `belongsTo(User)`, `hasMany(Enrollment)`, `hasManyThrough(Certificate, Enrollment)`
- `Enrollment` 모델: `belongsTo(User)`, `belongsTo(Course)`, `hasOne(Certificate)`
- `Certificate` 모델: `belongsTo(Enrollment)`

마이그레이션을 실행하세요:

```bash
php artisan migrate
```

기대 결과: Course, Enrollment, Certificate 모델과 마이그레이션이 생성되고, 데이터베이스 테이블이 생성됩니다. 모델 간 관계가 정의되어 Eloquent로 연관 데이터를 쉽게 조회할 수 있습니다.

3
Step 3
강사가 코스를 생성/조회/수정/삭제할 수 있는 CRUD 기능을 구현하세요.

### 요구사항:

1. **CourseController 생성**:
   ```bash
   php artisan make:controller CourseController
   ```

2. **라우트 정의** (`routes/web.php`):
   - `GET /courses` → `CourseController@index` (코스 목록)
   - `GET /courses/create` → `CourseController@create` (코스 생성 폼)
   - `POST /courses` → `CourseController@store` (코스 저장)
   - `GET /courses/{id}/edit` → `CourseController@edit` (코스 수정 폼)
   - `PUT /courses/{id}` → `CourseController@update` (코스 업데이트)
   - `DELETE /courses/{id}` → `CourseController@destroy` (코스 삭제)
   - 모든 라우트는 `auth` 미들웨어로 보호

3. **컨트롤러 메서드 구현**:
   - `index`: 로그인한 사용자가 생성한 코스 목록을 `Inertia::render('Courses/Index')`로 전달
   - `create`: 빈 폼을 `Inertia::render('Courses/Create')`로 렌더링
   - `store`: 폼 데이터를 검증(title 필수, completion_threshold 0~100)하고 코스 생성 후 `/courses`로 리다이렉트
   - `edit`: 특정 코스를 조회하여 `Inertia::render('Courses/Edit')`로 전달
   - `update`: 코스 정보 업데이트 후 `/courses`로 리다이렉트
   - `destroy`: 코스 삭제 후 `/courses`로 리다이렉트

4. **React 페이지 컴포넌트 생성**:
   - `resources/js/Pages/Courses/Index.jsx`: 코스 목록 테이블, 생성/수정/삭제 버튼
   - `resources/js/Pages/Courses/Create.jsx`: 코스 생성 폼 (title, description, completion_threshold 입력)
   - `resources/js/Pages/Courses/Edit.jsx`: 코스 수정 폼
   - Inertia `useForm` 훅을 사용하여 폼 제출 처리
   - Tailwind CSS로 스타일링 (카드 레이아웃, 버튼, 입력 필드)

5. **네비게이션 추가**: `resources/js/Layouts/AuthenticatedLayout.jsx`에 "내 코스" 메뉴 추가

구현 후 브라우저에서 코스를 생성/수정/삭제할 수 있는지 테스트하세요.

기대 결과: 강사가 로그인 후 코스를 생성하고, 목록을 확인하며, 수정/삭제할 수 있습니다. React 컴포넌트가 Inertia.js를 통해 Laravel 컨트롤러와 원활하게 통신하고, 데이터가 DB에 저장됩니다.

4
Step 4
학생이 코스에 등록하고 진도율을 업데이트하는 기능을 구현하세요.

### 요구사항:

1. **EnrollmentController 생성**:
   ```bash
   php artisan make:controller EnrollmentController
   ```

2. **라우트 정의** (`routes/web.php`):
   - `GET /courses/{id}` → `CourseController@show` (코스 상세 페이지, 학생이 등록 가능)
   - `POST /enrollments` → `EnrollmentController@store` (코스 등록)
   - `PUT /enrollments/{id}/progress` → `EnrollmentController@updateProgress` (진도율 업데이트)
   - `GET /my-courses` → `EnrollmentController@myCourses` (내가 등록한 코스 목록)

3. **CourseController@show 구현**:
   - 코스 정보와 현재 사용자의 등록 여부(enrollment)를 조회
   - `Inertia::render('Courses/Show', ['course' => $course, 'enrollment' => $enrollment])`로 전달

4. **EnrollmentController 구현**:
   - `store`: 로그인한 사용자를 코스에 등록 (중복 등록 방지)
   - `updateProgress`: 진도율(progress)을 0~100 범위로 업데이트. 진도율이 `completion_threshold` 이상이면 `completed_at`을 현재 시각으로 설정하고, 수강증 발급 로직 호출 (다음 단계에서 구현)
   - `myCourses`: 로그인한 사용자가 등록한 코스 목록을 `Inertia::render('Enrollments/MyCourses')`로 전달

5. **React 페이지 컴포넌트 생성**:
   - `resources/js/Pages/Courses/Show.jsx`: 코스 상세 정보, "등록하기" 버튼 (미등록 시), 진도율 슬라이더 (등록 시)
   - `resources/js/Pages/Enrollments/MyCourses.jsx`: 내가 등록한 코스 목록, 진도율 표시, 수료 여부 표시
   - 진도율 슬라이더는 `<input type="range" min="0" max="100" />` 사용, 변경 시 `PUT /enrollments/{id}/progress`로 업데이트

6. **네비게이션 추가**: AuthenticatedLayout에 "내 수강 코스" 메� 추가

구현 후 학생이 코스에 등록하고 진도율을 조정할 수 있는지 테스트하세요.

기대 결과: 학생이 코스 상세 페이지에서 등록 버튼을 클릭하여 코스에 등록할 수 있고, 진도율 슬라이더로 학습 진행률을 업데이트할 수 있습니다. 진도율이 수료 기준에 도달하면 completed_at이 자동으로 설정됩니다.

5
Step 5
수강증 자동 발급 기능을 구현하세요. 학생이 코스를 수료하면 PDF 수강증을 자동 생성하고 DB에 저장합니다.

### 요구사항:

1. **PDF 생성 라이브러리 설치**:
   ```bash
   composer require barryvdh/laravel-dompdf
   ```

2. **CertificateService 생성**: 수강증 발급 로직을 서비스 클래스로 분리
   - `app/Services/CertificateService.php` 파일 생성
   - `generateCertificate(Enrollment $enrollment)` 메서드 구현:
     - UUID로 고유 인증번호 생성 (`Str::uuid()`)
     - PDF 뷰 템플릿 렌더링 (학생 이름, 코스명, 발급일, 인증번호 포함)
     - PDF 파일을 `storage/app/public/certificates/{certificate_number}.pdf`에 저장
     - Certificate 모델 레코드 생성 (enrollment_id, certificate_number, issued_at, pdf_path)

3. **PDF 뷰 템플릿 생성**:
   - `resources/views/certificates/template.blade.php` 생성
   - HTML/CSS로 수강증 디자인 (A4 크기, 중앙 정렬, 학생 이름, 코스명, 발급일, 인증번호 표시)
   - 예시:
     ```blade
     <!DOCTYPE html>
     <html>
     <head>
         <style>
             body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
             .certificate { border: 5px solid #4F46E5; padding: 40px; }
             .title { font-size: 36px; font-weight: bold; color: #4F46E5; }
             .name { font-size: 28px; margin: 20px 0; }
             .course { font-size: 20px; margin: 10px 0; }
             .number { font-size: 14px; color: #666; margin-top: 30px; }
         </style>
     </head>
     <body>
         <div class="certificate">
             <div class="title">수강증</div>
             <div class="name">{{ $studentName }}</div>
             <div class="course">{{ $courseName }}</div>
             <p>위 과정을 성실히 이수하였음을 증명합니다.</p>
             <div>발급일: {{ $issuedAt }}</div>
             <div class="number">인증번호: {{ $certificateNumber }}</div>
         </div>
     </body>
     </html>
     ```

4. **EnrollmentController@updateProgress 수정**:
   - 진도율이 수료 기준에 도달하고 `completed_at`이 null일 때 `CertificateService@generateCertificate` 호출

5. **Storage 심볼릭 링크 생성**:
   ```bash
   php artisan storage:link
   ```

구현 후 학생이 진도율을 100%로 올렸을 때 PDF 수강증이 자동 생성되고 DB에 저장되는지 확인하세요.

기대 결과: 학생이 코스를 수료하면 자동으로 PDF 수강증이 생성되어 storage/app/public/certificates 폴더에 저장되고, certificates 테이블에 레코드가 추가됩니다. PDF 파일은 브라우저에서 다운로드 가능합니다.

6
Step 6
수강증 이메일 자동 발송 기능을 구현하세요. 수강증 발급 시 학생에게 PDF 파일을 첨부한 이메일을 비동기로 발송합니다.

### 요구사항:

1. **메일 설정** (`.env`):
   - 개발 환경에서는 `MAIL_MAILER=log`로 설정하여 이메일을 로그 파일에 기록
   - 실제 서비스에서는 SMTP 또는 Mailgun 등 사용

2. **Mailable 클래스 생성**:
   ```bash
   php artisan make:mail CertificateIssued
   ```
   - `app/Mail/CertificateIssued.php`에서 생성자로 `Certificate` 모델 주입
   - `build()` 메서드에서 이메일 제목, 본문 뷰, PDF 첨부 구현:
     ```php
     public function build()
     {
         return $this->subject('수강증이 발급되었습니다!')
                     ->view('emails.certificate-issued')
                     ->attach(storage_path('app/public/' . $this->certificate->pdf_path));
     }
     ```

3. **이메일 뷰 템플릿 생성**:
   - `resources/views/emails/certificate-issued.blade.php`
   - 간단한 축하 메시지와 수강증 다운로드 안내

4. **Queue 설정**:
   - `.env`에서 `QUEUE_CONNECTION=database` 설정
   - 마이그레이션 생성 및 실행:
     ```bash
     php artisan queue:table
     php artisan migrate
     ```

5. **CertificateService 수정**:
   - `generateCertificate` 메서드 끝에 이메일 발송 로직 추가:
     ```php
     Mail::to($enrollment->user->email)->queue(new CertificateIssued($certificate));
     ```

6. **Queue Worker 실행**:
   ```bash
   php artisan queue:work
   ```
   - 개발 중에는 별도 터미널에서 실행하여 큐 작업 처리

구현 후 학생이 코스를 수료했을 때 이메일이 큐에 추가되고, `storage/logs/laravel.log`에 이메일 내용이 기록되는지 확인하세요.

기대 결과: 수강증 발급 시 이메일이 큐에 추가되고, Queue Worker가 실행 중이면 비동기로 이메일이 발송됩니다. 개발 환경에서는 로그 파일에 이메일 내용이 기록되어 확인할 수 있습니다.

7
Step 7
학생이 자신의 수강증 목록을 확인하고 재다운로드할 수 있는 페이지를 구현하세요. 또한 수강증 인증번호로 진위 여부를 확인할 수 있는 공개 페이지를 만드세요.

### 요구사항:

1. **CertificateController 생성**:
   ```bash
   php artisan make:controller CertificateController
   ```

2. **라우트 정의** (`routes/web.php`):
   - `GET /my-certificates` → `CertificateController@index` (내 수강증 목록, 인증 필요)
   - `GET /certificates/{id}/download` → `CertificateController@download` (PDF 다운로드, 인증 필요)
   - `GET /verify-certificate` → `CertificateController@verify` (수강증 검증 페이지, 공개)
   - `GET /verify-certificate/{number}` → `CertificateController@show` (특정 수강증 정보 조회, 공개)

3. **CertificateController 구현**:
   - `index`: 로그인한 사용자의 모든 수강증을 조회 (enrollments → certificates 관계 활용), `Inertia::render('Certificates/Index')`로 전달
   - `download`: 특정 수강증의 PDF 파일을 다운로드 응답으로 반환 (`Storage::download()`)
   - `verify`: 수강증 검증 폼을 `Inertia::render('Certificates/Verify')`로 렌더링
   - `show`: 인증번호로 수강증을 조회하여 정보(학생명, 코스명, 발급일) 반환. 존재하지 않으면 404 에러

4. **React 페이지 컴포넌트 생성**:
   - `resources/js/Pages/Certificates/Index.jsx`: 수강증 목록 (코스명, 발급일, 인증번호, 다운로드 버튼)
   - `resources/js/Pages/Certificates/Verify.jsx`: 인증번호 입력 폼, 검증 결과 표시 (학생명, 코스명, 발급일, "유효한 수강증입니다" 메시지)
   - Tailwind CSS로 카드 레이아웃, 배지, 버튼 스타일링

5. **네비게이션 추가**: AuthenticatedLayout에 "내 수강증" 메뉴, 공개 헤더에 "수강증 검증" 링크 추가

구현 후 학생이 수강증 목록을 확인하고 PDF를 다운로드할 수 있는지, 공개 페이지에서 인증번호로 수강증을 검증할 수 있는지 테스트하세요.

기대 결과: 학생이 로그인 후 자신의 수강증 목록을 확인하고 PDF 파일을 다운로드할 수 있습니다. 공개 검증 페이지에서 인증번호를 입력하면 수강증 진위 여부와 상세 정보가 표시됩니다.

제출된 작품 (0)

로그인 후 제출

아직 제출된 작품이 없습니다. 첫 번째 도전자가 되어보세요!

댓글 (0)

로그인 후 댓글을 남길 수 있습니다.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!