1. 프로젝트 개요 및 기획 배경
1.1 기획 의도 및 페르소나 분석
본 프로젝트는 타원형 나무 물감 팔레트에 직접 유화로 그려진 빈센트 반 고흐의 명작 「별이 빛나는 밤에 by Junyeong」을 디지털 인터랙티브 웹 게임으로 재탄생시키는 작업입니다.
- 인지 및 조작 특성: 소근육 조작 능력이 발달하는 시기로, 화면 드래그가 미숙할 수 있으므로 '터치 후 배치(Tap-to-Place)' 대안이 필수적임.
- 심리적 보상: 퍼즐이 막혔을 때 좌절감을 느끼지 않도록 제한적 마법 찬스와 밑그림 가이드를 제공하여 자기주도적 성취감을 극대화함.
- 교육적 가치: 원작의 붓터치, 명도 대비, 사이프러스와 초승달의 구도를 자연스럽게 체득하여 공간 지각력 및 예술적 관찰력을 함양함.
2. 시스템 요구사항 명세 (Requirements Matrix)
| ID | 구분 | 요구사항 명칭 | 상세 명세 및 구현 검증 기준 |
|---|---|---|---|
| FR-01 | 기능 | 단계별 난이도 조절 | 4조각(2x2), 9조각(3x3), 16조각(4x4), 25조각(5x5), 36조각(6x6)의 5단계 동적 슬라이싱 지원 |
| FR-02 | 기능 | 제한적 찬스 요청 | 게임당 최대 3회의 마법 찬스 제한. 미완성 조각을 자동 탐색하여 궤적 보간 비행 후 정답 슬롯에 스냅 |
| FR-03 | 기능 | 완수 축하 애니메이션 | 마지막 조각 배치 시 퍼즐 선 투명화 페이드, Web Audio 승리 팡파르, 캔버스 물리 폭죽/별빛 파티클 3연속 폭발 |
| FR-04 | 기능 | 듀얼 컨트롤 스킴 | Pointer Events 기반 드래그 앤 드롭 + 원터치 선택 후 대상 슬롯 터치(Tap-to-Place) 동시 완벽 지원 |
| FR-05 | 기능 | 인증서 자동 생성 | 오프라인 Canvas 2D 합성 엔진을 통해 플레이어 이름, 클리어 시간, 별점이 포함된 고해상도 PNG 파일 즉시 다운로드 |
| NFR-01 | 비기능 | 무의존성 (Zero Dependency) | 외부 라이브러리(CDN, React, NPM 등) 없이 순수 Vanilla JS, HTML5, CSS3, Web Audio API만으로 구현 |
| NFR-02 | 비기능 | 크로스 플랫폼 호환성 | Windows, Linux, macOS, iOS(Safari), iPadOS, Android(Chrome) 전 기기 OS 및 뷰포트에서 완전 동일 실행 |
| NFR-03 | 비기능 | 60 FPS 렌더링 성능 | requestAnimationFrame 기반 파티클 엔진 및 Canvas 오프스크린 캐싱을 통해 60 FPS 보장 |
3. 시스템 아키텍처 및 컴포넌트 설계
본 시스템은 유지보수성과 오프라인 단일 파일 패키징의 유연성을 위해 철저한 단일 책임 원칙(SRP) 기반의 모듈형 객체 지향 구조로 설계되었습니다.
3.2 상태 머신 (State Machine) 전이도
게임 라이프사이클은 IDLE -> PLAYING -> DRAGGING / SELECTED -> SNAPPING -> VICTORY 단계로 명확히 관리됩니다.
4. 핵심 알고리즘 및 수학적 구현 상세
4.1 3차 베지에 곡선(Cubic Bézier) 기반의 유기적 직소 엣지 알고리즘
전통적인 직소 퍼즐의 볼록 탭(Tab)과 오목 홈(Blank)은 수학적으로 3차 베지에 곡선의 조합으로 정의됩니다. 시작점 \(P_0(x_0, y_0)\)와 끝점 \(P_1(x_1, y_1)\) 사이의 변위 벡터를 \(\vec{d} = P_1 - P_0\), 변의 길이를 \(L = \|\vec{d}\|\)라 할 때, 진행 방향 단위벡터 \(\vec{u}\)와 법선 단위벡터 \(\vec{n}\)은 다음과 같이 정의됩니다.
탭의 깊이를 \(D = L \times 0.24\)로 설정하고, 엣지 상의 임의의 점을 매개변수 \((s, d)\)로 표현하면: \[ P(s, d) = P_0 + s \cdot L \cdot \vec{u} + d \cdot D \cdot \vec{n} \] 곡선의 제어점은 자연스러운 직소 목(Neck)과 머리(Head)를 형성하도록 대칭적으로 배치됩니다:
// JigsawGeometry.drawEdge 3차 베지에 제어점 배치
const p1 = p(0.38, 0.0); // 기준선 직선 구간 끝
const cp1a = p(0.36, 0.15); // 목 진입 제어점 A
const cp1b = p(0.32, 0.55); // 목 진입 제어점 B
const p2 = p(0.40, 0.95); // 둥근 탭 머리 시작점
ctx.bezierCurveTo(cp1a.x, cp1a.y, cp1b.x, cp1b.y, p2.x, p2.y);
const cp2a = p(0.46, 1.20); // 탭 정점 제어점 A (돌출 깊이 120%)
const cp2b = p(0.54, 1.20); // 탭 정점 제어점 B
const p3 = p(0.60, 0.95); // 탭 머리 반대편
ctx.bezierCurveTo(cp2a.x, cp2a.y, cp2b.x, cp2b.y, p3.x, p3.y);
4.2 인접 조각 간 엣지 정합성 보장 정리
퍼즐 조각 \((r, c)\)와 오른쪽 인접 조각 \((r, c+1)\)이 완벽히 맞물리기 위해서는 다음 불변 조건(Invariant)을 반드시 만족해야 합니다.
4.3 유클리드 거리 기반 마그네틱 스냅 (Magnetic Snap) 알고리즘
사용자가 드래그 중인 조각의 패딩 보정 중심점 \((X_p, Y_p)\)와 정답 그리드 슬롯 좌표 \((X_t, Y_t)\) 사이의 유클리드 거리 \(d\)를 매 포인터 릴리즈 시점에 계산합니다.
const dist = Math.hypot(pieceInternalX - targetX, pieceInternalY - targetY);
if (dist <= this.config.snapDistance) {
// 45px 이내 진입 시 자석 흡착 및 물리 효과음 발동
this.snapPiece(piece);
} else {
this.returnPieceToTray(piece);
}
4.4 Web Audio API 기반의 무의존성 절차적 음향 합성 (Procedural Audio)
외부 MP3/WAV 오디오 다운로드 지연 및 네트워크 끊김 현상을 원천 방지하기 위해 브라우저 내장 신디사이저를 수학적으로 모델링하였습니다.
| 효과음 | 오실레이터 파형 | 주파수 변조 (Frequency Ramp) | 게인 엔벨로프 (ADSR) |
|---|---|---|---|
| 스냅 (Snap) | Triangle + Sine | 600Hz → 1200Hz → 400Hz (0.14s) + 1800Hz Click | Linear Attack (0.01s), Expo Decay (0.14s) |
| 픽 (Pick) | Triangle | 320Hz → 480Hz (0.07s) | Fast Peak (0.15), Expo Decay (0.09s) |
| 마법 찬스 (Hint) | Sine (5노트) | C5(523Hz) → E5 → G5 → C6 → E6 아르페지오 | 0.07초 간격 시차 발음, 0.35초 감쇠 |
| 승리 (Victory) | Triangle + Sine | C5, E5, G5, High C6 팡파레 화음 + 별빛 아르페지오 | 풍부한 서스테인 후 0.7초 감쇠 페이드아웃 |
5. 크로스 플랫폼 최적화 및 안정성 보장 기법
- Pointer Events API 단일화:
pointerdown,pointermove,pointerup을 통해 마우스, 애플 펜슬, 정전식 정밀 멀티터치를 단일 파이프라인으로 처리하고,setPointerCapture로 브라우저 밖으로 벗어나는 이탈을 방지. - iOS 사파리 고유 제스처 방지: 드래그 대상 요소 및 캔버스에
touch-action: none;을 지정하여 iOS 사파리의 기본 스크롤, 바운스 줌, 스와이프 뒤로가기 제스처 간섭을 원천 차단. - Retina 고밀도 디스플레이 대응:
window.devicePixelRatio를 감지하여 캔버스 백킹 버퍼 해상도를 스케일업함으로써 고해상도 모바일 화면에서도 선명하고 매끄러운 렌더링 유지. - 종횡비 잠금 반응형 레이아웃: 1200:796(약 1.5:1) 원본 캔버스 종횡비를 수식적으로 계산하여 모바일 세로/가로 모드 및 데스크톱 와이드 모드에서 여백 왜곡 없이 최적 배율 유지.
6. 클라우드 배포 및 무료 호스팅 가이드
본 게임은 완전한 정적 클라이언트 애플리케이션(SPA)이므로 무료 클라우드 플랫폼에서 서버 비용 0원으로 즉시 전 세계 배포가 가능합니다.
저장소 생성 후 본 폴더의 파일들을 푸시하고 [Settings] → [Pages]에서 Branch를 main으로 설정하면 1분 안에 HTTPS 도메인으로 서빙됩니다.
GitHub 리포지토리 연동 시 무제한 대역폭과 전 세계 CDN 엣지 캐싱이 무료 티어로 제공되어 지연 시간 10ms 이내의 쾌속 로딩을 달성합니다.
7. 자동화 검증 및 E2E 테스트 결과
Chrome DevTools Protocol(CDP) 기반의 헤드리스 엔드투엔드(E2E) 자동화 검증 스위트(tests/e2e.mjs)를 통해 전 기능 검증을 통과하였습니다.
E2E Server listening on http://127.0.0.1:9989
✔ Game initialized and image loaded!
✔ Piece count: 16 (expected 16)
✔ Sound engine active: true
✔ Initial chances: 3
✔ Chances remaining after hint: 2, Placed count: 1
✔ Switched difficulty to easy9: piece count is 9
✔ Ghost toggle: false -> true
✔ Edge filter active: true
Testing full solve flow on easy4 (4 pieces)...
✔ Game completed: true, Victory Modal Active: true
✔ Certificate Generator generated PNG: true (length: 1634190)
✔ Zero console errors detected during entire test run!
========================================
🎉 ALL AUTOMATED E2E TESTS PASSED 100%!
========================================