# Claude Code 개발 기록: Opus5 | 항목 | 값 | | --- | --- | | Model | Claude Opus5 | | 도구 | Claude Code | | 플랜 | Pro | | 프로젝트 | [claude_opus5](../../claude_opus5/) | | Usage | 5시간 사용량 윈도우의 약 65% 소진 | | Time | 미기록 | | Steps | 미기록 | | Files | 69개 | | Lines | 10,259줄 (텍스트 전체, 빈 줄 포함) | | 코드 비공백 LOC | 5,716줄 | | 규모 측정일 | 2026-09-06 | ## 해석 및 측정 기준 - 사용량은 사용자가 제공한 근사 관측값이다. 5시간은 사용 한도의 집계 윈도우이며 실제 개발 소요 시간이 아니다. - 소진율을 개발 시간·토큰·실제 청구액·GitHub Copilot 크레딧으로 환산하지 않는다. 월 $20·30일·하루 2개 윈도우를 가정한 [구독료 배분 추정](cost-estimates.md)은 약 $0.217이다. - 제공된 로그에 전체 소요 시간과 Steps의 확정값이 없어 미기록으로 남긴다. 파일시스템 시각도 복사로 평탄화되어 개발 시간의 근거로 사용할 수 없다. - 파일·라인 수는 [공통 집계 기준](README.md#측정-기준)에 따른 현재 폴더 실측값이며, 개발 당시 생성량이나 편집량이 아니다. ## 기록 출처 - 사용량: 사용자 제공 정보 (Pro 플랜, 5시간 윈도우 약 65%). - 규모: 저장소의 기존 프로젝트 집계기를 이용한 2026-09-06 재측정. - 상세 개발 로그: 아래 사용자 제공 원문 보존. 구현·테스트 통과 여부를 새로 검증한 문서가 아니다.
원문 펼치기 ~~~~text I'll build the Janggi game following the P0→P9 + P12 phases. Let me start by exploring the working directory. 실행됨 명령 2개 빈 폴더입니다. P0 → P9 + P12 순서로 구현하겠습니다 (P10 AI, P11 온라인 제외). 먼저 프로젝트 골격과 헌법 문서부터 고정합니다. P0-P1: 헌법과 규칙 명세 실행됨 명령 3개 Now the build scaffolding. 실행됨 명령 3개 의존성 설치 완료. P2 — 좌표계와 데이터 모델을 만듭니다. P2: 데이터 모델과 초기 배치 실행됨 명령 2개 (1개 실패) Heredoc quoting broke on that size; I'll use the file tools for the larger sources. 생성됨 board.ts +381 -0 P3 — 기물별 이동 생성기. 규칙 로직이므로 테스트를 먼저 작성합니다. P3: 기물 이동 생성기 생성됨 파일 7개 +437 -0 Tests are in place. Now the implementations. 생성됨 파일 8개, 실행됨 명령 1개 +413 -0 두 실패는 테스트 쪽 오류입니다 — 상의 이동 벡터를 (2,3)/(3,2)가 아닌 값으로 잘못 적었습니다. 테스트를 규칙에 맞게 고칩니다. 편집됨 sang.test.ts, 실행됨 명령 1개 +9 -8 P4 — 합법수 필터와 장군 판정. P4-P5: 합법수·장군·승패 판정 생성됨 파일 8개, 편집됨 파일 1개, 실행됨 명령 1개 +1059 -12 테스트 전제가 틀렸습니다 — 궁성 귀퉁이의 차가 대각선으로 중앙을 지나 반대 귀퉁이까지 공격하므로 그 자리도 봉쇄됩니다. 엔진이 맞습니다. 테스트를 고치고 이 상호작용을 별도 테스트로 고정합니다. 편집됨 result.test.ts, 실행됨 명령 1개 +24 -2 P5 검증 — 콘솔 랜덤 대국과 P6 불변식 검사를 한 모듈에 담습니다. 생성됨 파일 2개, 실행됨 명령 2개 +266 -0 엔진이 콘솔에서 완주합니다 (148수, 빅장, 위반 0건). 이제 P6 검증 — perft 기준값과 대량 랜덤 대국. P6: perft + 랜덤 대국 검증 생성됨 perft.ts, 실행됨 명령 1개 +24 -0 Perft 기준값이 나왔습니다. 초기 국면 31수는 손으로도 검산됩니다. 이제 회귀 테스트로 고정하고 대량 검증을 돌립니다. 생성됨 soak.ts, 실행됨 명령 3개 (1개 실패) +52 -0 빅장을 끄면 외통·반복·수제한으로 분산되고 위반은 0건입니다. 검증 테스트로 고정합니다. 실행됨 명령 2개, 생성됨 파일 2개 +112 -0 엔진이 완성되었습니다 (97 테스트, 랜덤 1000판 위반 0). 이제 기보 직렬화/리플레이(P9의 엔진 부분)를 추가하고 UI로 넘어갑니다. 생성됨 record.ts, 실행됨 명령 1개 +154 -0 P7 — SVG 보드. 먼저 기하 계산과 스타일. P7: SVG 보드와 상호작용 생성됨 파일 5개 +1213 -0 P8 — 게임 흐름. 상태는 useReducer로만 관리하고, 액션은 엔진 함수만 호출합니다. P8-P9: 화면 흐름과 기보 생성됨 파일 11개, 실행됨 명령 3개 +1418 -0 타입 체크 통과. PWA 자산과 아이콘을 생성합니다. P12: 접근성·PWA·배포 생성됨 파일 2개, 실행됨 명령 2개 +141 -0 빌드 성공. 브라우저에서 실제 동작을 확인합니다. janggi-dev 브라우저 탭이 닫혔습니다 실행됨 명령 1개, 사용함 도구 6개 (1개 실패) 보드는 정상 렌더링됩니다. 좌표 라벨이 가장자리 기물에 가려지는 문제가 보입니다 — SVG 여백이 기물 반지름보다 작기 때문입니다. 여백을 늘리면 터치 타깃이 좁아지므로, 라벨을 SVG 밖 오버레이로 옮깁니다. 편집됨 파일 2개, 실행됨 명령 1개, 사용함 도구 9개 +72 -23 마·상·포·졸 이동이 모두 규칙대로 표시됩니다. 시각/접근성 세부를 다듬습니다. 편집됨 파일 2개, 사용함 도구 1개 +5 -4 드래그로 21마33이 성사되었지만 (4,2) 부근에 정체 불명의 원이 보입니다. DOM으로 확인합니다. Ran page script 좌표 프레임 혼동이 있었습니다 — 방금 것은 드래그가 아니라 클릭 이동이었습니다. 뷰포트를 팬 크기에 맞추고 실제 드래그를 다시 테스트합니다. 먼저 마우스 사용 시 키보드 커서가 뜨는 문제를 고칩니다. 편집됨 Board.tsx, 사용함 도구 3개 (1개 실패) +3 -1 좁고 낮은 창에서 보드가 거의 0폭으로 붕괴합니다 — 세로 맞춤 계산에 하한이 없었습니다. 고칩니다. 편집됨 app.css, 사용함 도구 1개 +2 -1 자동 저장 복구 배너가 동작합니다. 이어두기로 복원 후 보드를 확인합니다. 사용함 도구 4개 드래그가 성사되지 않았습니다. 포인터 이벤트가 실제로 오는지 계측합니다. 사용함 도구 3개 좌표 프레임을 확정했습니다 (도구 좌표 = 클라이언트 좌표 / 1.6). 다시 드래그합니다. Ran page script, dragged 드래그 앤 드롭 확인 완료. 이제 키보드 조작을 검증합니다. 사용함 도구 2개 키보드 선택도 동작합니다 (해당 마는 (3,4) 아군 병에 다리가 막혀 합법수가 (2,1) 하나뿐 — 엔진이 맞습니다). 한 수 쉬기·무르기·리플레이를 확인합니다. 사용함 도구 7개 (1개 실패) 기권·종료 다이얼로그 정상. 조사(助詞) 표현을 다듬습니다. Fixed Korean particle wording in UI strings 모바일 세로 화면과 터치 타깃 크기를 확인합니다. 사용함 도구 3개 (1개 실패) 모바일 레이아웃은 좋지만 교차점 간격이 35.4px입니다. 여백을 줄여 최대한 확보합니다. 편집됨 파일 1개, 생성됨 파일 4개, 실행됨 명령 2개, 사용함 도구 2개 +486 -0 테스트에 남긴 잘못된 단언 하나와, 궁의 낭독 명칭("한(漢) 한")을 고칩니다. 편집됨 파일 2개, 실행됨 명령 3개 +17 -8 Now the README (P12 배포 준비). 생성됨 README.md +197 -0 최종 검증: 아키텍처 경계, 전체 테스트, 프로덕션 빌드. 실행됨 명령 3개, 사용함 도구 2개 드래그 준비 중 setPointerCapture가 던지면 클릭 선택까지 함께 죽는 문제가 드러났습니다. 방어적으로 고칩니다. 편집됨 Board.tsx, 사용함 도구 2개 +8 -1 진짜 버그를 찾았습니다: pointerdown/up이 같은 React 배치에서 처리되면 drag 상태가 낡은 채 남아 다음 클릭이 엉뚱한 지점으로 라우팅됩니다. 상태 대신 ref를 진실 원본으로 바꿉니다. 편집됨 Board.tsx, 실행됨 명령 1개, 사용함 도구 2개 +42 -16 장군 판정, 멍군 강제(한 수 쉬기 비활성), 점수 차감까지 모두 정상입니다. 라이트 테마를 확인합니다. 실행됨 명령 3개, 사용함 도구 4개 claude_opus5 폴더에 웹 장기 게임을 완성했습니다. P0~P9 + P12 구현, P10(AI)·P11(온라인)은 제외. 검증 결과 npm test 143개 테스트 전부 통과 — 그중 핵심은: 검사 결과 랜덤 대국 1000판 완주 규칙 위반 0건 (궁 잡힘·보드 이탈·궁성 이탈·포 규칙·졸 후진·undo 불일치) perft depth 1~3, 배치 4종 기준값 고정 (31 / 961 / 30,506) 기물 7종 이동 규칙 다리 막힘·경로 차단·궁성 대각선 등 개별 테스트 초기 국면 31수는 손으로도 검산했습니다: 차2+2, 마2+1, 상0+1, 사2+2, 궁6, 포0+0, 졸13. 샹치와 헷갈리기 쉬운 부분 — 실제로 확인함 브라우저에서 직접 둬 보며 확인했습니다: 포는 초기 국면에서 한 수도 못 둡니다 (세로는 상대 포, 가로는 아군 포가 첫 기물 → 넘을 수 없음). 샹치처럼 차같이 움직이면 오답 졸은 처음부터 좌우 3방향, 뒤로는 불가 상은 1직진+2대각, 강(河) 없음 차는 궁성 귀퉁이에서 중앙을 지나 반대 귀퉁이까지 공격 — 이게 외통 판정에 실제로 영향을 줍니다 (테스트로 고정) 장군 상태에서 「한 수 쉬기」 버튼이 비활성됩니다 브라우저 테스트 중 찾아 고친 실제 버그 2건 클릭 라우팅 경합 — pointerdown/pointerup이 같은 React 배치에서 처리되면(빠른 탭·터치) 낡은 드래그 상태가 남아 다음 클릭이 엉뚱한 지점으로 착수됐습니다. 드래그 상태의 진실 원본을 state → ref로 바꿔 해결. 좁고 낮은 창에서 보드 붕괴 — 세로 맞춤 계산에 하한이 없어 보드 폭이 거의 0이 됐습니다. 하한 300px 추가. 좌표 라벨도 가장자리 기물에 가려져 SVG 밖 오버레이로 옮겼습니다 — SVG 여백을 키우면 교차점 간격(=터치 타깃)이 줄기 때문입니다. 알아두실 한계 하나 P12의 "터치 타깃 최소 44px"는 9열 보드에서 폭 400px 미만 화면이면 기하학적으로 불가능합니다(8×44=352px에 기물 지름까지 필요). 주변 여백을 최대한 줄여 375px 뷰포트에서 39px를 확보했고, 가로 스크롤은 없습니다. README에 근거를 적어 뒀습니다. 실행 cd C:\Work\Azure\janggi\claude_opus5 && npm install && npm run dev UI 없이 엔진만 돌려 볼 수도 있습니다: npm run play -- 7 README.md에 아키텍처·규칙 출처·perft 기준값·접근성을, RULES.md에 규칙 명세를 그대로 고정해 뒀습니다. src/engine/에는 React/DOM 참조가 한 줄도 없고, src/ui/에서 이동 생성기를 직접 호출하는 곳도 없습니다 — 경계를 grep으로 확인했습니다. ~~~~