Laravel 11 + Vue 3 SPA 기프트카드 플랫폼 · 최종 업데이트: 2026-05-13 · S0–S5 완료 (100%) ✅ MVP 완료
Laravel 11 + Vue 3 + MariaDB 개발 기반 구축. Sanctum SPA 쿠키 인증, 품질 도구(Pint·PHPStan·ESLint·vue-tsc), Idempotency 미들웨어, AppendOnly 감사 로그 가드까지 모든 공통 인프라 완성.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T001 | Laravel 11 신규 설치 /home/giftcard/public_html · .env · .gitignore 설정 |
Infra | ✓ |
| T002 | Vue 3 SPA + Vite 5 셋업 frontend/ 디렉터리 · TypeScript strict · 백엔드 프록시(/api, /sanctum) |
FE | ✓ |
| T003 | MariaDB 연결 + 기본 마이그레이션 DB_CONNECTION=mariadb · users, sessions, cache, jobs 테이블 |
Infra | ✓ |
| T004 | Laravel Sanctum SPA 모드 EnsureFrontendRequestsAreStateful · CSRF 쿠키 · stateful domains |
BE | ✓ |
| T005 | shadcn-vue + Tailwind CSS 셋업 Button, Card, Input, Label, Dialog 컴포넌트 추가 · 디자인 토큰 |
FE | ✓ |
| T006 | Vue Router 4 + Pinia 셋업 requiresAuth · requiresAdmin 가드 · authStore 골격 |
FE | ✓ |
| T007 | 코드 품질 도구 설정 Laravel Pint · PHPStan Level 8 · ESLint · vue-tsc · lint 스크립트 |
Infra | ✓ |
| T008 | 공통 도메인 인프라 EnsureIdempotency 미들웨어 · IdempotencyKey 모델 · AppendOnly 트레이트 |
BE | ✓ |
회원가입·로그인·로그아웃·마이페이지 + 기프트카드 상품 CRUD(관리자) + 공개 목록·상세 페이지 완성. UserRole enum(user/admin), GiftCardStatus enum, PIN 3-컬럼(hash·encrypted·last_four) 도입. 백엔드 37개 Feature 테스트 통과.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T101 | User 모델 + Sanctum 인증 API register · login · logout · me · reauth · UserRole enum · ULID PK · AuthApiTest(12개) |
BE+FE | ✓ |
| T102 | 로그인·회원가입 UI LoginView · RegisterView · useAuth composable · shadcn-vue Form/Input |
FE | ✓ |
| T103 | 마이페이지 (F011) MyPageView · 이름·이메일·계정유형 표시 · 로그아웃 버튼 |
FE | ✓ |
| T104 | GiftCard 도메인 + 관리자 CRUD API (F020) GiftCard 모델 · GiftCardService(AES-256-GCM) · GiftCardController · GiftCardResource(pin 미노출) · GiftCardApiTest(8개) |
BE | ✓ |
| T105 | 관리자 상품 관리 UI (F020) AdminGiftCardListView · AdminGiftCardFormView · adminGiftCardStore(Pinia) |
FE | ✓ |
| T106 | 공개 상품 목록 API + 페이지 (F001) GET /api/gift-cards · 커서 페이지네이션 · GiftCardListView · HomeView |
BE+FE | ✓ |
| T107 | 공개 상품 상세 API + 페이지 (F002) GET /api/gift-cards/{id} · GiftCardDetailView · 환불 법령 고지 문구 |
BE+FE | ✓ |
PG Mock 결제(pending→paid) → GiftCard 자동 발급(owner_id 부여) → 보관함 → 재인증 후 PIN 노출(30초 타이머) → 사용 완료(used). OrderStatus 재설계(Pending/Paid/Failed/Refunded), 낙관적 잠금(version 컬럼), 멱등성(Idempotency-Key), RequireRecentReauth 미들웨어, GiftCardTransaction AppendOnly 감사 로그 완성.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T201 | Order/OrderItem 도메인 + 멱등성 (F003) OrderStatus enum 재설계 · OrderItem · pg_provider/pg_payload/external_id · OrderApiTest |
BE | ✓ |
| T202 | PG 어댑터 인터페이스 + Mock + Webhook PaymentGatewayInterface · MockPaymentGateway · config/payment.php · PaymentWebhookController · OrderController@confirm |
BE | ✓ |
| T203 | GiftCard 발급 로직 + PIN 보안 3-컬럼 (F003) GiftCardIssuanceService · owner_id/expires_at/used_at · GiftCardStatusLog(AppendOnly) · GiftCardTransaction · GiftCardStatus 재설계(Sold 제거) |
BE | ✓ |
| T204 | 보관함 목록/상세 API + UI (F005) GET /api/vault · owner_id 기준 필터 · MyVaultView · 만료 임박 배지 · 상태 레이블 |
BE+FE | ✓ |
| T205 | PIN 노출 재인증 + reveal-pin API (F006, F012) RequireRecentReauth 미들웨어(5분) · throttle:3,1 · ReauthDialog · 30초 자동 마스킹 타이머 · RevealPinTest(5개) |
BE+FE | ✓ |
| T206 | 사용 완료 처리 + 낙관적 잠금 (F006) GiftCardUsageService · version 컬럼 비교 → ConflictException(409) · GiftCardUsageTest(6개) |
BE | ✓ |
| T207 | GiftCardTransaction 도메인 + 관리자 거래 내역 (F022) TransactionType enum · AppendOnly · Admin TransactionController · 커서 페이지네이션 · TransactionApiTest(4개) |
BE | ✓ |
| T208 | 결제 페이지 + 결제 완료 UI (F003) CheckoutView(약관동의·Idempotency-Key 인터셉터) · CheckoutSuccessView · GiftCardUseView · 라우터 4개 경로 추가 |
FE | ✓ |
선물 발송(회원 자동 적립 / 비회원 클레임 URL) + 클레임 페이지 + 사용자 거래 내역 + 관리자 발급 내역 + PIN reveal(관리자). GiftIssuanceService 회원/비회원 분기, GiftClaimMail 큐 발송, ClaimController 1회용 토큰 검증 완성.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T301 | OrderItem 선물 처리 + 회원/비회원 분기 발급 GiftIssuanceService · claim_token · gift_send/gift_receive 트랜잭션 2건 | BE | ✓ |
| T302 | 선물하기 UI (F004) GiftFormView · 수신자 이메일·이름·메시지(200자) | FE | ✓ |
| T303 | 클레임 API + 페이지 (F009) GET/POST /api/claim/{token} · 서명 검증 · 1회용 토큰 · ClaimView | BE+FE | ✓ |
| T304 | 사용자 거래 내역 API + 페이지 (F007) GET /api/transactions · 유형/날짜 필터 · TransactionListView | BE+FE | ✓ |
| T305 | 관리자 발급 내역 + PIN reveal (F021) 관리자 GiftCard 목록 · 마스킹 · reveal 사유 필수 · 감사 로그 | BE+FE | ✓ |
| T306 | 관리자 대시보드 + 거래 내역 UI (F021/F022) AdminDashboardView · AdminTransactionListView · 집계 카운트 | FE | ✓ |
| T307 | 선물 발송/수신 메일 검증 Mail::fake() · GiftClaimMail · Mailpit 로컬 검증 | Test | ✓ |
사용자 환불 신청 → 관리자 승인(PG 부분취소 mock) → 카드 refunded 전이. 일일 스케줄러로 만료 카드 expired 전이. 전 생명주기 감사 로그 100% 적재. 법령 고지 문구 전 흐름 점검 완료.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T401 | Refund 도메인 + 사용자 환불 신청 (F008) Refund 모델 · RefundStatus enum · RefundService(100%/90% 계산) · RefundFormView | BE+FE | ✓ |
| T402 | 관리자 환불 처리 + PG 부분취소 (F023) Admin RefundController · approve/reject · PG refund mock · AdminRefundListView | BE+FE | ✓ |
| T403 | 만료 처리 배치 (F024) ExpireGiftCardsCommand · daily schedule · actor_type=system 감사 로그 | BE | ✓ |
| T404 | 감사 로그 전 흐름 검증 + 관리자 로그 페이지 GiftCardAuditController · AdminGiftCardAuditView · 발급→사용→환불→만료 시나리오 테스트 | BE+FE | ✓ |
| T405 | 법령 고지 문구·약관 동의 정합성 점검 결제·환불 흐름 약관 동의 체크박스 · 이용약관·환불정책·개인정보처리방침 분리 | FE | ✓ |
| T406 | Idempotency 키 정리 배치 CleanExpiredIdempotencyKeysCommand · TTL 24시간 · daily schedule | BE | ✓ |
Playwright E2E 골든 패스 전체 통과. 보안 체크리스트 9항목 PASS(docs/security-checklist.md 산출). SensitiveDataProcessor 로그 마스킹, pg·audit·idempotency 채널 분리. Nginx vhost·PHP-FPM·운영 cron·deploy.md·runbook.md 완성.
| Task | 작업 내용 | 구분 | 상태 |
|---|---|---|---|
| T501 | Playwright E2E 골든 패스 시나리오 auth · purchase · gift · refund · admin 스펙 5종 · Playwright MCP 시각 회귀 | Test | ✓ |
| T502 | 보안 점검 체크리스트 PIN 평문 응답 미포함 · localStorage 저장 금지 · Rate Limit · CSRF 419 · Admin RBAC 우회 403 | Test | ✓ |
| T503 | 로깅·모니터링 설정 일자별 로테이션 · pg.log · audit.log · idempotency.log · SensitiveDataProcessor 마스킹 | Infra | ✓ |
| T504 | 배포 환경 구성 + 운영 문서 Nginx vhost · PHP-FPM · .env.production.example · docs/deploy.md · docs/runbook.md | Infra | ✓ |
pin_hash(HMAC-SHA256, 유일성 검증) · pin_encrypted(AES-256-GCM, 복호화용) · pin_last_four(마스킹 표시).
GET /api/gift-cards/{id} 응답에는 pin_hash · pin_encrypted 절대 미포함.
클라이언트는 평문 PIN을 메모리 외 저장 금지(localStorage · sessionStorage 금지).
owner_id IS NULL AND status = active.
구매 완료 시 owner_id = 구매자 user_id로 설정.
status = sold 값 제거 — 상태와 소유권을 분리하여 선물/클레임 흐름도 자연스럽게 처리.
version 값 불일치로 감지 → ConflictException(409 Conflict) 반환.
DB 레벨 lockForUpdate()와 병행하여 이중 방어.
src/api/http.ts)가 POST/PUT/PATCH/DELETE 요청에 Idempotency-Key 헤더를 자동 생성.
백엔드 EnsureIdempotency 미들웨어가 동일 키 재요청 시 저장된 응답 반환, 다른 본문이면 409.
->withHeader('Origin', 'http://localhost') 헤더가 필수.
RequireRecentReauth 테스트는 ->withSession(['auth.confirmed_at' => time()])->withHeader('Origin', 'http://localhost') 패턴 사용.
owner_id/version API 응답 제거 → is_available 추가.
Admin LIKE 인젝션 이스케이프, RequireRecentReauth 토큰 기반 요청 즉시 401,
VerifyWebhookSignature HMAC-SHA256 서명 검증,
app.key base64 접두사 제거 후 PIN HMAC 적용.
crypto.randomUUID() Idempotency-Key 생성.
MockPaymentGateway는 결제를 즉시 성공으로 처리. 실제 PG(Toss/Nice/KG이니시스) 연동 시
PaymentGatewayInterface를 구현한 어댑터 추가 후 PAYMENT_DRIVER 환경변수 변경만으로 전환 가능.