순수 바닐라 JS로 1500단계 퍼즐 게임을 만들었습니다 (그리고 AI가 가장 어려운 부분을 해결하는 데 어떻게 도움을 줬는지)

발행: (2026년 4월 2일 PM 06:35 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

Source Code:
Play Ziply Live:

오늘 새로운 웹 프로젝트를 시작하면 가장 먼저 떠오르는 반응은 npx create-react-app을 실행하거나 Next.js 보일러플레이트를 띄우는 것입니다. 하지만 저사양 모바일 기기에서도 완벽히 동작해야 하는 1500레벨의 고도로 인터랙티브한 논리 퍼즐 게임을 만들고 싶다면 어떻게 해야 할까요?
프레임워크를 버리고 기본으로 돌아갑니다.

저는 최근 Ziply라는 라인 드로잉 논리 퍼즐 게임을 출시했습니다. Unity 같은 무거운 게임 엔진이나 React 같은 웹 프레임워크를 사용하지 않고, 순수 JavaScript, HTML, CSS만으로 처음부터 직접 만들었습니다. 아래는 아키텍처, 성능 선택 사항, 그리고 AI가 가장 어려운 부분을 해결하는 데 어떻게 도움을 주었는지에 대한 상세 분석입니다.

왜 Vanilla JS인가? (Performance & Control)

사용자가 그리드 위에서 손가락을 빠르게 끌어 파이프를 그리는 게임에서는 프레임 레이트가 모든 것이다.

  • React를 사용하면 각 타일 터치마다 상태 변화가 발생해 전체 8×8 그리드가 무거운 재렌더링을 일으킬 수 있다.
  • Vanilla JS를 사용하면 이벤트 루프와 메모리 관리에 절대적인 제어권을 가질 수 있다. touchstarttouchmove를 컨테이너에 직접 바인딩하고, 정확한 손가락 좌표를 추적하며, 게임 상태를 밀리초 단위의 일부분만에 업데이트할 수 있다—프레임워크 오버헤드가 없다.

Source:

아키텍처: DOM + Canvas 하이브리드

가장 큰 시각적 과제는 사용자가 스와이프할 때 빛나는 “파이프”를 렌더링하는 것이었습니다. 전체 게임을 캔버스로만 만들면 커스텀 히트박스, 이벤트 리스너, UI 스케일링 로직을 처음부터 모두 작성해야 하고, 순수 HTML/CSS 라인 그리기는 절대 위치 지정 때문에 곧 악몽이 됩니다.

내 해결책

  • CSS Grid는 표준 <div> 요소들을 사용해 게임 보드를 생성하고, 내장된 반응형 기능과 document.elementFromPoint()를 통한 간단한 히트 감지를 제공합니다.
  • 완전히 투명한 <canvas> 요소를 그리드 바로 위에 겹쳐 놓아, 빛나는 파이프를 시각적으로 표시하는 전용 레이어로 활용합니다.

  
// Canvas는 순수히 시각적 표현 레이어 역할만 합니다.
const canvas = document.querySelector('.overlay');
const ctx = canvas.getContext('2d');

// 예시: 파이프 구간 그리기
function drawPipe(x1, y1, x2, y2) {
  ctx.strokeStyle = 'rgba(0, 200, 255, 0.8)';
  ctx.lineWidth = 8;
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(x2, y2);
  ctx.stroke();
}

힌트 시스템 및 나의 AI 페어 프로그래머

가장 만들기 어려웠던 기능은 힌트 시스템이었습니다. Ziply의 핵심 규칙은 숫자를 순서대로 연결하고 보드의 모든 빈 블록을 채우는 것입니다.

초기 시도: BFS

간단한 너비 우선 탐색(BFS)으로 최단 경로를 찾을 수 있었지만, 종종 코너를 잘라내고 빈 타일을 차단해 버려서 레벨을 클리어할 수 없는 힌트를 만들었습니다.

DFS와 백트래킹으로 전환

보이지 않는 상태에서 게임을 시뮬레이션하고, 수천 개의 경로를 탐색하며, 막히면 되돌아갈 수 있는 깊이 우선 탐색(DFS)이 필요했습니다—검증된 100 % 승리 경로를 찾을 때까지 멈추지 않는 것이 목표였습니다.

고급 경로 탐색은 제 강점이 아니었기 때문에 Gemini를 페어 프로그래머로 활용했습니다. 게임 규칙을 AI에 입력하고 BFS가 왜 실패했는지 설명한 뒤, 백트래킹 DFS 솔버를 생성하고 다듬는 데 도움을 받았습니다.

// PERFECT WIN CONDITION: Path fills all tiles AND ends on highest number
if (currentPath.length === targetLen && cellVal === maxNum) {
  bestSolution = [...currentPath];
  return;
}

const neighbors = [
  `${cx + 1}-${cy}`,
  `${cx - 1}-${cy}`,
  `${cx}-${cy + 1}`,
  `${cx}-${cy - 1}`
];

for (const n of neighbors) {
  if (isValidMove(n)) {
    currentPath.push(n);
    solve(currentPath, nextExpected); // Recursive dig
    currentPath.pop(); // Backtrack if it's a dead end
  }
}

AI가 생성한 알고리즘을 기존 게임 루프에 통합하고, UI 애니메이션에 연결하며, 엣지 케이스를 디버깅하는 과정은 놀라운 학습 경험이었습니다. 이는 개인적인 지식의 격차를 메우는 데 AI가 얼마나 강력하게 활용될 수 있는지를 보여주었습니다.

직접 해보세요!

DEV 커뮤니티가 직접 사용해 보길 바랍니다. 6×6 마스터 모드에서 레벨 10을 깰 수 있는지 확인해 보세요!

🎮 Play Ziply Live:

댓글에 UI, 터치 컨트롤, 혹은 코드 구조에 대한 피드백을 자유롭게 남겨 주세요!

0 조회
Back to Blog

관련 글

더 보기 »

Time Spender v1

제가 만든 Time Spender v1은 궁극적인 생산성 anti‑tool입니다. 이는 정확히… 낭비하도록 설계된 단 하나의, 고도로 최적화된 목적을 가진 web application입니다.