게임 링크 : https://reversechess.perfect.ai.kr/
리버스 체스
reversechess.perfect.ai.kr
리버스 체스 기록 처음부터 보기 : https://helloworld.ai.kr/29
개발 시간이 이미 45시간을 넘어선 시점이었다.
이 단계에서는 이상적인 해결보다 빠른 완성에 초점을 맞췄다.
문제 : Zobrist Hash 값과 보드 상태 불일치
초기에는 말 이동, 캡처, 턴 전환마다 Zobrist Hash를 증분 업데이트 방식으로 관리하고 있었다. 하지만 증분 업데이트된 해시 값과 보드를 통째로 다시 계산한 해시 값이 일치하지 않는 문제가 발생했다.
정확히 어디서 어긋나는지 끝내 특정하지 못해, 매번 보드 전체를 다시 계산하도록 수정했다.
계산 비용은 대략 다음과 같다.
기물 개수만큼 XOR + 턴 상태 XOR
→ 한 번의 보드 변경당 최대 33회 XOR
성능 영향이 크지 않다고 판단해, 증분 업데이트를 고집하기보다는 빠른 안정화를 선택했다.
문제 : 여전한 Invalid Move
Zobrist Hash를 수정한 이후에도, 한 판에 한 번 정도 AI가 불가능한 수를 두는 문제가 남아 있었다. 어딘가에서 보드 상태가 꼬이는 것으로 추정되지만 정확한 원인은 찾지 못했다.
그래서 재시도 방식으로 일단 틀어막았다.
- Invalid Move 1회 발생
→ AI 플레이어와 TT 초기화 후 재탐색 (대부분 여기서 해결) - 2회 연속 발생
→ 합법 수 중 하나를 랜덤 선택
완벽한 해결은 아니지만, 최소한 게임이 터지는 상황은 막을 수 있었다.

문제 : Out of Memory
TT 엔트리 수가 초당 약 5천 개씩 증가하는 것을 확인하고, 처음에는 다음과 같이 제한을 걸었다.
- 최대 30만 엔트리
- 초과 시 가장 오래된 엔트리 1개 삭제
하지만 게임 후반에 브라우저 메모리가 1GB를 넘어가며 out of memory가 발생했다.
그래서 정책을 다음과 같이 수정했다.
- 최대 5만 엔트리
- 각 엔트리에 최근 사용 시점 기록
- 초과 시 LRU 방식으로 1만 개 일괄 삭제
이후 브라우저 메모리는 약 300MB 수준에서 안정적으로 유지되었고, out of memory도 발생하지 않았다.
1인 플레이 구현 완료
이것으로 PvE 구현이 마무리되었다.
앞서 문제로 꼽았던 세 가지 중
- 혼자 플레이할 콘텐츠 부족
- 설명/튜토리얼 부재
- 모바일 UI 깨짐
이 중 1번과 2번은 해결했고, 이제 마지막 3번을 손보기로 했다.
모바일 UI 기초
모바일에서 접속하면 체스판이 좌우로 늘어나거나 찌그러지면서 칸 사이가 벌어지거나 겹치는 문제가 발생했다.
이를 해결하기 위해 다음 작업을 진행했다.
- 상단 컴포넌트 3개 → 2줄 구조로 재배치
- 체스판 크기에 맞춰 레이아웃 너비가 결정되도록 수정
- 칸 크기를 clamp 기반으로 조정
h-[clamp(32px,9vw,48px)]
w-[clamp(32px,9vw,48px)]
모바일 UI 원칙
고정 픽셀 대신 비율 또는 반응형 값을 사용한다.
특히 많이 활용한 CSS는 두 가지다.
1. Tailwind Breakpoint
px-6 py-4 text-lg
sm:px-10 sm:py-6 sm:text-2xl
기본 스타일이 적용되다가, 화면 너비가 640px 이상이면 sm 스타일로 전환된다.
2. clamp()
w-[clamp(32px,9vw,48px)]
- 기본: 화면 너비의 9%
- 최소: 32px
- 최대: 48px
모든 화면을 직접 늘렸다 줄였다 하며 확인했고, 실제 모바일에서도 테스트했다.
화면 수가 많지 않아 그나마 수월했다.
해결하지 못한 문제 : 다크모드
모바일 크롬 다크모드에서 다음 문제가 발생했다.
- 흑/백 말 색상 반전
- 턴 표시 색상 왜곡
CSS만으로 해결을 시도했지만 실패했다.
가장 단순한 해결책은 기물과 턴 표시 UI를 이미지 리소스로 고정하는 것이지만, 시간 관계상 적용하지 못했다.
구글 애널리틱스 쪼아요
이 프로젝트는 백엔드가 없어서,
누가 들어와서 얼마나 플레이했는지 파악할 방법이 없었다.
이를 보완하기 위해 Google Analytics를 도입했다.
프로젝트에 추가하는 과정도 간단했고, 원하는 이벤트를 정의해 수집할 수 있다는 점이 특히 인상적이었다.
다음 이벤트들을 정의했다.
- 게임 종료 시 승자
- 게임 종료 후 ‘다시 하기’ 클릭 여부
- 튜토리얼 완료 여부
- 기타 사용자 행동
초기 데이터 기준으로 22명의 사용자가 확인되었다.
잘 활용하면 가설 검증과 UX 개선에 꽤 유용할 것 같다.
리버스 체스 완
시간이 예상보다 많이 들었고 몇 가지 아쉬운 점도 남았지만, 이번 프로젝트는 전반적으로 꽤 만족스러운 결과다.
'개발로그' 카테고리의 다른 글
| 아무 앱 플레이스토어 출시 ( 2 ) - 등록 완료 (0) | 2026.03.07 |
|---|---|
| 아무 앱 플레이스토어 출시 ( 1 ) - 「마법의 고민해결 책」 (0) | 2026.02.17 |
| 리버스 체스 ( 3 ) - '그 긴 거' (0) | 2026.02.17 |
| 리버스 체스 ( 2 ) - 익숙한 부분 (0) | 2026.02.17 |
| 리버스 체스 ( 1 ) - 회고 (0) | 2026.02.17 |