Static Chess 구현
- 평범하고, 필수적인 기능만 있는 체스 구현
- 모든 페이지는 오직 HTML과 CSS로만 구성됨
- 모든 체스 이동은 링크를 클릭해서 이뤄짐
- 친구에게 링크를 보내면 상대방이 이동하고 다시 링크를 보내주는 방식으로 진행
- 불필요한 애니메이션이나 화려한 인터랙티브 요소가 게임플레이를 방해하지 않음
- 구글이 이 사이트를 인덱싱할 때 모든 가능한 체스 이동을 계산할 수 있을지 궁금함
기능 제한 및 버그
- 기능이 매우 제한적이고 동작하지 않을 수 있음
- 버그를 발견하면 제보 부탁
영감을 준 아이디어
- 틱택토 게임의 모든 가능한 상태를 보여주는 사이트에 대한 Hacker News 토론에서 영감을 얻음
향후 계획
- 실제 게임플레이를 지원하도록 확장할 계획
- 친구들과 장기전을 할 수 있는 심플한 인터페이스가 될 수 있을 것 같음
- 정적 AI와 대결하는 기능을 추가하는 것도 재미있을 것 같음
- 추가되었으면 하는 기능이 있다면 PR 환영
주요 코드
class StaticChess {
// 생략...
async fetch(req: Request): Promise<Response> {
const gameInfo = parseURL(req.url);
if (gameInfo === undefined) {
return new Response("Not Found", { status: 404, headers: { "cache-control": "max-age=86400, public" } });
}
const game = new Game(gameInfo.game, gameInfo.selected);
return new Response(
renderToString(
<html>
{/* 생략... */}
<div className="board">
{this.rows.map(row => (
<div key={row} className="row">{this.squares.map(square => game.squareContent(row, square))}</div>
))}
</div>
{/* 생략... */}
</html>
),
{ headers: { "content-type": "text/html", "cache-control": "max-age=86400, public" } },
);
}
}
class Game {
// 생략...
squareContent(row: number, square: number) {
// 생략...
const squareContent = (() => {
if (this.selectable.includes(pos)) {
return <a href={`/${this.fen}/${pos}`}>{pieces[this.board[row][square]?.type]}</a>;
}
const nextMove = this.nextMoves[pos];
if (nextMove !== undefined) {
return (
<a href={`/${nextMove.after.replaceAll(" ", "_")}/`}>
{pieces[this.board[row][square]?.type]}
</a>
);
}
return <span>{pieces[this.board[row][square]?.type]}</span>;
})();
// 생략...
}
}
GN⁺의 의견
- 웹 체스 게임을 HTML/CSS만으로 구현하는 것은 흥미로운 시도임. 하지만 모든 상태를 정적 페이지로 만드는 것은 실용성 면에서는 의문임.
- 현실적인 사용성을 고려하면 결국 백엔드에서 상태를 관리하고 프론트엔드에서 API를 호출하는 형태가 되어야할 것 같음.
- 정적 페이지로 모든 상태를 미리 계산해두는 것은 아이디어로서는 재미있지만, 실제 사용자에게는 큰 의미가 없어보임.
- React로 SSR하는 것은 괜찮은 접근이지만, 캐싱이나 프리페칭 등 성능을 개선할 여지가 많아보임.
- 비슷한 오픈소스 프로젝트로는 lichess가 있음. 풍부한 기능과 멋진 UI를 제공하므로 참고해볼만함.
- 체스 엔진과 연동해서 AI 모드를 지원하려면 WASM을 활용하는 것도 고려해볼 수 있겠음.