[Code] 자바스크립트(JS) 테트리스(Tetris) 만들기: 워드프레스 WPCode 적용부터 핵심 로직 리뷰까지

안녕하세요! studyformyself입니다. 오늘은 HTML5 Canvas와 순수 자바스크립트(Vanilla JS)를 활용하여 직접 구현한 ‘네온 테마 테트리스(Tetris)’ 웹 게임의 코드 리뷰를 진행해 보겠습니다.

실제로 게임이 어떻게 작동하는지 궁금하시다면 아래 링크에서 바로 플레이해 보실 수 있습니다.

👉 테트리스 게임 플레이하러 가기

이번 포스팅에서는 프론트엔드 개발 관점에서의 테트리스 핵심 알고리즘(충돌 판정, 행렬 회전 등)뿐만 아니라, 워드프레스 환경에서 자바스크립트 게임을 배포할 때 겪는 문법 오류를 WPCode 플러그인으로 해결하는 방법까지 상세히 다뤄보겠습니다.

1. 워드프레스 JS 오류 해결: WPCode로 완벽하게 분리하기

워드프레스 ‘사용자 정의 HTML’ 블록에 자바스크립트 코드를 직접 넣고 발행(Publish)하면, 미리보기에서는 잘 되던 코드가 먹통이 되는 현상을 자주 겪게 됩니다.

이는 워드프레스의 내장 필터(wpautop, wptexturize)가 코드 내부의 줄바꿈을 <p><br> 태그로 변환하거나, 일반 따옴표(")를 스마트 따옴표()로 임의 변경하여 **Uncaught SyntaxError**를 발생시키기 때문입니다. 이 문제를 가장 깔끔하게 해결하는 방법은 디자인(HTML)과 로직(JS)을 물리적으로 분리하는 것입니다.

WPCode 플러그인 적용 방법

  1. 플러그인 설치: 워드프레스 관리자에서 무료 플러그인인 WPCode를 설치 및 활성화합니다.
  2. HTML 뼈대 작성: 글 편집기의 ‘사용자 정의 HTML’에는 <canvas> 요소와 버튼 등 CSS 디자인 뼈대만 작성합니다.
  3. JS 스니펫 생성: WPCode의 ‘Add Snippet’에서 코드 유형을 **’JavaScript Snippet’**으로 설정한 뒤, 테트리스의 메인 로직 코드만 단독으로 붙여넣습니다.
  4. 쇼트코드 삽입: 생성된 쇼트코드(예: )를 HTML 블록 바로 아래에 넣어주면, 워드프레스의 간섭 없이 코드가 안전하게 렌더링됩니다.

2. 테트리스 게임의 핵심 자바스크립트 로직 리뷰

테트리스는 화려한 그래픽보다는 2차원 배열(Matrix) 데이터를 어떻게 수학적으로 다루느냐가 관건인 게임입니다. 주요 로직을 3가지로 나누어 살펴보겠습니다.

A. 보드와 2차원 배열 (2D Array) 초기화

테트리스 보드는 눈에 보이는 픽셀이 아니라, 20행 12열의 거대한 표(배열)로 관리됩니다.

const ROW = 20;
const COL = 12;
const EMPTY = "#111111"; // 빈 칸 색상
let board = [];

// 20x12 2차원 배열 생성
function initBoard() {
  for (let r = 0; r < ROW; r++) {
    board[r] = [];
    for (let c = 0; c < COL; c++) {
      board[r][c] = EMPTY;
    }
  }
}

board[y][x]의 형태로 각 칸의 색상 데이터를 저장하며, 값이 EMPTY가 아니면 해당 칸에 블록이 쌓여있다고 판단합니다.

B. 충돌 판정 알고리즘 (Collision Detection)

가장 중요한 로직입니다. 블록이 아래로 내려가거나 양옆으로 움직일 때, 이동하려는 좌표가 1) 보드 바깥인지, 2) 이미 다른 블록이 있는지 검사합니다.

collision(x, y, piece) {
  for (let r = 0; r < piece.length; r++) {
    for (let c = 0; c < piece[r].length; c++) {
      if (!piece[r][c]) continue; // 빈 공간(0)은 무시
      
      let newX = this.x + c + x;
      let newY = this.y + r + y;
      
      // 외벽 충돌 및 기존 블록 충돌 확인
      if (newX < 0 || newX >= COL || newY >= ROW) return true; 
      if (newY < 0) continue; 
      if (board[newY][newX] !== EMPTY) return true; 
    }
  }
  return false;
}

이 함수가 true를 반환하면 이동이나 회전을 취소하고, 블록이 바닥에 닿았다면 해당 위치의 배열 값을 색상 문자로 고정(lock)시킵니다.

C. 행렬 90도 회전 (Rotation)

배열로 이루어진 테트리미노 블록을 위쪽 방향키로 회전시키는 것은, 프로그래밍의 고전적인 N x N 행렬 90도 회전 알고리즘과 동일합니다.

rotate() {
  // 행과 열을 뒤집고(Transpose), 각 행을 역순(Reverse)으로 배치
  let nextPattern = this.activeTetromino[0].map((val, index) => 
    this.activeTetromino.map(row => row[index]).reverse()
  );
  
  // 벽 차기 (Wall Kick) 보정
  let kick = 0;
  if (this.collision(0, 0, nextPattern)) {
    if (this.x > COL / 2) kick = -1; // 우측 벽에 붙었으면 좌측으로 밀기
    else kick = 1;
  }
  // ... (후략)
}

이 프로젝트에서는 자바스크립트의 고차 함수인 map()reverse()를 체이닝하여 매우 간결하게 회전을 구현했습니다. 또한 회전 시 벽에 끼이는 버그를 막기 위해 간단한 ‘Wall Kick(벽 차기)’ 보정 로직을 추가한 것이 특징입니다.


더 많은 캐주얼 웹 게임을 즐기고 싶으시거나, 직접 프론트엔드 지식을 쌓아 이 게임이 어떻게 만들어졌는지 코드를 뜯어보고 싶으시다면 아래 링크를 방문해 보세요!

👉 더 많은 무료 웹 게임 즐기러 가기

👉 프론트엔드 학습자를 위한 자바스크립트 코드 분석 보기

Leave a Comment