- 개요, 조사(BGA·한국 인기 보드게임·UI/UX), 아키텍처, 실시간 프로토콜,
안정성·보안, 계정, 로비·방, UI/UX, 데이터 모델, 게임 엔진, 테스트,
배포·운영, 로드맵(M0~M9), 사용자 결정 항목
- 게임별 규칙·엔진 설계·UI·테스트 체크리스트 26종
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
마일스톤: M2 · 인원: 최소 2 ~ 최대 2명 · 예상 시간: 블리츠 약 10분, 래피드 약 2040분 · 난이도: 보통어려움
1. 개요
백과 흑이 16개씩의 기물로 상대 킹을 체크메이트하면 이기는 서양 장기. 한국에서는 학교 방과후 수업과 온라인(chess.com, lichess)으로 어린이·청소년층 인지도가 높다.
인원 근거: 원작이 2인 게임. 최소 2, 최대 2.
규칙 기준: FIDE 체스 규칙(Laws of Chess, 2023년 1월 시행판). 온라인 환경에 맞춘 차이는 7장과 6장에 명시.
완전 정보 게임. view에서 제외할 것은 RNG 상태뿐.
2. 모드와 옵션
옵션 키
설명
선택지
기본값
variant
변형
standard / chess960
standard
timeControl
시간 방식(피셔: 기본 시간 + 수당 추가)
프리셋: 블리츠 3+2, 5+0, 5+3 / 래피드 10+0, 10+5, 15+10 / 클래식 30+0 / none / 사용자 지정(190분, 060초)
10+5
drawMode
반복·50수 무승부 처리
auto(3회 반복·50수 즉시 자동 무승부) / fide(3회 반복·50수는 클레임, 5회 반복·75수는 자동)
auto
colorAssignment
백흑 결정
random / hostWhite / hostBlack / alternate
random
autoQueen
승진 시 퀸 자동 선택(설정 끄면 선택 창)
true / false
false (선택 창, 퀸이 첫 번째 큰 버튼)
undo
무르기 허용 횟수(1인당, 상대 동의)
off / 1 / 3 / unlimited
1
drawOffer
무승부 제안
true / false
true
firstMoveSec
첫 수 제한(넘기면 대국 취소)
15 / 30 / 60
30
idleLimitSec
timeControl=none일 때 무응답 한도
300 / 600
600
hints
초보 도움말(이동 가능 칸 표시, 공격받는 기물 경고)
off / moves / movesAndThreats
moves
disconnectGraceSec
연결 끊김 유예
30 / 60 / 120
60
3. 구성물
8×8 칸(64칸), a1이 흑색 칸(백 기준 왼쪽 아래가 어두운 칸).
각 색: 킹 1, 퀸 1, 룩 2, 비숍 2, 나이트 2, 폰 8.
좌표: 열 ah(백 기준 왼→오), 행 18(백 쪽부터). 기보는 SAN(예: Nf3, exd5, O-O, e8=Q+) 저장, 내부 처리는 UCI(e2e4, e7e8q).
4. 준비(셋업)
standard: 백 1행 a~h: R N B Q K B N R, 2행 폰. 흑은 8행·7행에 대칭(퀸은 자기 색 칸: 백 Q d1, 흑 Q d8). FEN rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1.
chess960: 시드 RNG로 0~959 중 번호 n을 뽑아 백 1행 배치를 만들고 흑은 같은 열에 대칭 배치. 폰 배치는 동일. 번호 → 배치(Scharnagl 방식):
b1 = n % 4; n = floor(n/4) → 밝은 칸 비숍을 열 2*b1 + 1(b, d, f, h)에.
b2 = n % 4; n = floor(n/4) → 어두운 칸 비숍을 열 2*b2(a, c, e, g)에.
q = n % 6; n = floor(n/6) → 남은 6칸 중 왼쪽부터 q번째(0부터)에 퀸.
n(0~9)로 남은 5칸 중 나이트 두 자리: 0:(0,1) 1:(0,2) 2:(0,3) 3:(0,4) 4:(1,2) 5:(1,3) 6:(1,4) 7:(2,3) 8:(2,4) 9:(3,4).
남은 3칸에 왼쪽부터 R, K, R.
검증: n = 518 → RNBQKBNR(표준 배치).
백이 먼저 둔다. 시계: 양쪽 baseSec. 첫 수 규칙은 8.5 참고.
5. 진행 규칙
5.1 기물 이동
킹: 8방향 1칸. 공격받는 칸으로는 못 간다.
퀸: 가로·세로·대각 어느 거리든(가로막히면 정지).
룩: 가로·세로 어느 거리든. 비숍: 대각 어느 거리든. 나이트: L자(2+1), 다른 기물을 뛰어넘음.
폰: 앞으로 1칸(빈칸), 처음 위치에서는 2칸(두 칸 모두 빈칸). 대각 앞 1칸으로만 잡는다.
잡기: 상대 기물이 있는 칸으로 이동하면 그 기물을 제거. 자기 기물 칸으로는 못 간다.
5.2 특수 규칙
앙파상(en passant): 상대 폰이 직전 수에 처음 위치에서 2칸 전진해 내 폰 바로 옆에 섰을 때, 바로 다음 수에 한해 그 폰이 1칸만 전진한 것처럼 대각선으로 잡을 수 있다.
승진(promotion): 폰이 마지막 행에 도달하면 같은 색 퀸·룩·비숍·나이트 중 하나로 반드시 바꾼다(기존 기물 수와 무관).
캐슬링(standard): 킹과 룩이 모두 한 번도 움직이지 않았고, 사이 칸이 모두 비었으며, 킹이 현재 체크 상태가 아니고, 킹이 지나가는 칸과 도착 칸이 공격받지 않을 때. 킹이 룩 쪽으로 2칸 이동하고 룩이 킹이 넘어간 칸으로 이동. 킹사이드: Ke1→g1, Rh1→f1. 퀸사이드: Ke1→c1, Ra1→d1(b1은 비어야 하지만 공격받아도 무관).
캐슬링(chess960): 결과 위치는 표준과 동일(킹사이드: 킹 g, 룩 f / 퀸사이드: 킹 c, 룩 d). 조건: 해당 킹·룩 미이동, 킹의 현재 칸도착 칸 사이 모든 칸(양 끝 포함)과 룩의 현재 칸도착 칸 사이 모든 칸이 그 킹과 룩을 제외하고 비어 있음, 킹이 현재 체크 아님, 킹이 지나가는 칸·도착 칸이 공격받지 않음. 킹이나 룩이 이미 도착 칸에 있을 수 있다(이동 0칸).
체크: 킹이 공격받는 상태. 자기 킹을 공격받게 두는 수(핀 된 기물 이동, 공격받는 칸으로 킹 이동 포함)는 불법.
5.3 턴 구조
차례인 플레이어는 합법 수 하나를 둔다. 패스 없음.
합법 수가 없으면: 체크 상태면 체크메이트(패배), 아니면 스테일메이트(무승부).
6. 승패와 점수 계산
승리: 체크메이트, 상대 기권, 상대 시간패(단 아래 예외), 상대 연결 끊김 시간 초과.
무승부:
스테일메이트.
기물 부족(데드 포지션의 결정적 부분집합, 자동): 킹 대 킹 / 킹+비숍 대 킹 / 킹+나이트 대 킹 / 킹+비숍(들) 대 킹+비숍(들)에서 모든 비숍이 같은 색 칸.
3회 반복: 같은 국면(같은 차례, 같은 기물 배치, 같은 캐슬링 권리, 같은 앙파상 가능 여부 — 앙파상 칸은 실제로 합법적 앙파상 잡기가 가능할 때만 국면에 포함)이 3번째 나옴. auto면 즉시 무승부, fide면 차례인 플레이어가 클레임 가능, 5번째는 자동 무승부.
50수 규칙: 양쪽 모두 50수(100 플라이) 동안 폰 이동·잡기 없음. auto면 즉시 무승부, fide면 클레임 가능, 75수(150 플라이)는 자동. 단 그 수가 체크메이트면 체크메이트 우선.
무승부 합의.
시간패 예외(FIDE 6.9): 시간이 다 된 쪽의 상대가 어떤 합법 수순으로도 체크메이트할 수 없으면 무승부. 판정 함수 cannotMate(side): side가 킹만 있음 / 킹+나이트 1개만 있고 상대가 킹만 / 킹+비숍 1개만 있고 상대가 킹만 / side가 킹+같은 색 칸 비숍들만 있고 상대도 킹+같은 색 칸 비숍들만(또는 킹만). 이 외에는 메이트 가능으로 보수적으로 판단(→ 시간 초과한 쪽 패배). 예: 백이 시간 초과, 흑이 킹+나이트, 백이 킹+퀸이면 흑이 이론상 헬프메이트 가능하므로 흑 승.
점수 개념 없음. 결과 요약: "백 승 (체크메이트, 34수)".
대국 취소(aborted): 백 또는 흑이 첫 수를 firstMoveSec 안에 두지 않으면 결과 없이 취소(승패 기록 없음).
7. 지역 룰 / 하우스 룰 (옵션으로 켜고 끄기)
drawMode=auto(기본): chess.com처럼 3회 반복과 50수를 클레임 없이 자동 무승부. 어린이·어르신이 "클레임" 개념을 몰라 무한 반복하는 일을 막기 위함.
drawMode=fide: FIDE 9.2/9.3/9.6 그대로(클레임 버튼 제공 + 5회 반복·75수 자동).
Chess960: 무작위 첫 배치. 오프닝 암기 부담을 없앤 변형.
터치 무브(손 댄 기물은 움직여야 함), 불법 수 둔 사람 패배 등 오프라인 규칙은 온라인에서 적용하지 않는다(불법 수는 서버가 거부).
8. 엔진 설계
8.0 라이브러리 vs 자체 구현 평가
후보
장점
단점
chess.js (BSD-2-Clause, TypeScript)
오래 쓰인 검증된 수 생성, FEN/PGN/SAN, isCheckmate/isStalemate/isInsufficientMaterial/isThreefoldRepetition/isDrawByFiftyMoves 제공, 서버·클라이언트 공용, 라이선스 자유로움
Chess960 캐슬링 미지원(이슈 #67, #441 등 장기 미해결). 3회 반복 판정의 국면 동일성 기준, 기물 부족 기준을 우리 규칙과 맞춰 확인 필요
chessops (TypeScript, lichess 개발자 제작)
Chess960 포함 각종 변형 지원, lichess에서 실사용
GPL-3.0 이상. 클라이언트 번들에 포함하면 클라이언트 코드 공개 의무 발생 가능. 서버 전용으로 쓰면 배포가 아니므로 일반적으로 문제 없으나 법적 판단 필요
자체 구현
의존성·라이선스 없음, 960 포함 완전 통제
수 생성 버그 위험. perft 테스트로 검증 필수, 개발 시간 증가
권장: v1(standard)은 chess.js를 서버에서만 사용해 판정하고, 클라이언트는 서버 view의 legalMoves로 하이라이트(클라이언트 라이브러리 불필요 → 번들 경량화, 판정 이중화 불일치 방지). 대신 아래를 어댑터에서 우리 규칙으로 직접 판정한다: 반복 국면 키(앙파상 정규화), 50/75수, 기물 부족 목록, 시간패 예외 cannotMate.
Chess960(후속 마일스톤): (a) chessops를 서버 전용으로 도입(GPL 적용 범위를 사용자/법률 검토 후) 또는 (b) 자체 구현 + perft 검증. 사용자가 오픈소스 공개를 원치 않고 법률 검토도 부담이면 (b). 이 문서의 상태·액션 정의는 두 방식 모두에 맞도록 FEN(960은 Shredder-FEN: 캐슬링 권리를 룩의 열 문자로 표기, 예 HAha)을 기준으로 한다.
어느 쪽이든 perft로 검증: 초기 국면 깊이 15 = 20 / 400 / 8,902 / 197,281 / 4,865,609, "Kiwipete" 국면(r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1) 깊이 14 = 48 / 2,039 / 97,862 / 4,085,603. 960은 공개된 chess960 perft 세트 사용.
8.1 상태(State)
typeColor='white'|'black';interfaceChessState{options: ChessOptions;players: Record<Color,PlayerId>;startFen: string;// 960 배치 포함
chess960Index: number|null;fen: string;// 현재 국면 (권위 있는 단일 진실)
moves:{uci: string;san: string;color: Color;at: number;fenAfter: string}[];repetition: Record<string,number>;// 국면 키 -> 등장 횟수
phase:'playing'|'finished';clock:{remainingMs: Record<Color,number>;turnStartedAt: number;started: Record<Color,boolean>};undo:{usedBy: Record<Color,number>;pending:{by: Color;plies: 1|2}|null};draw:{pendingBy: Color|null;lastOfferPly: Record<Color,number>};claimable:'threefold'|'fiftyMove'|null;// drawMode=fide에서 차례인 쪽이 클레임 가능한 사유
result: ChessResult|null;rng: RngState;}// 국면 키 = FEN의 앞 4필드(배치, 차례, 캐슬링 권리, 앙파상 칸).
// 단 앙파상 칸은 합법적인 앙파상 잡기가 실제로 있을 때만 남기고 아니면 '-'로 정규화.
8.2 액션
type
payload
누가 / 언제
검증 조건
move
{ from: 'e2', to: 'e4', promotion?: 'q'|'r'|'b'|'n' }
차례인 플레이어, playing
합법 수 목록에 존재. 승진 수인데 promotion 없으면 거부("승진할 기물을 골라 주세요"). 승진 수가 아닌데 있으면 무시. 실패 사유 예: "그 기물은 그렇게 움직일 수 없어요", "킹이 공격받게 되어 둘 수 없어요", "지금은 상대 차례예요"
castle
{ side: 'king' | 'queen' }
차례인 플레이어
5.2 조건. 960에서 킹 이동과 혼동되는 경우(킹이 1칸 옆 룩 칸 등) 명시적으로 사용. standard에서는 move e1g1도 캐슬링으로 인정
claimDraw
{}
차례인 플레이어, drawMode=fide
claimable != null (FIDE: 클레임하는 수를 두기 직전 또는 직후 국면). 수락 없이 즉시 무승부
requestUndo
{}
플레이어
undo != off, 횟수 남음, 대기 없음, 본인 수 존재. 1 또는 2 플라이
respondUndo
{ accept }
상대
수락 시 moves 끝에서 제거하고 startFen에서 재생해 fen·repetition 재구성. 시계는 되돌리지 않음
offerDraw
{}
플레이어
drawOffer=true, 대기 없음, 거절 후 본인 3수 이상
respondDraw
{ accept }
상대
수락 → 무승부
cancelOffer
{}
요청자
resign
{}
플레이어
언제든(첫 수 전이면 aborted로 처리)
timeout
{}
시스템
8.5
수 처리 순서: 시계 차감(0 이하면 시간패 처리, 6장 예외 포함) → 합법성 → 적용 → 증가분 가산 → 종료 판정 순서: 체크메이트 > 스테일메이트 > 기물 부족 > (75수/5회 반복 자동) > (auto면 50수/3회 반복) → claimable 갱신.