진행 중 · 2026년 6월 10일
Ki Clash
한국 학교 운동장 손게임 '기싸움'을 실시간 1v1 PvP로 옮긴 게임 — 상대 수를 읽고, 기를 모으고, 타이밍에 친다. Python(FastAPI)과 Go 두 런타임이 같은 Redis 게임 상태를 공유. Next.js 16 PWA, 방 기반 PvP, 6 캐릭터 필살기, AI 생성 스프라이트.
Python + Go 듀얼 런타임 · Redis 상태 공유 · 164 테스트 · 136 커밋 · 필살기 6 · 스프라이트 36
- 역할
- Solo (Claude Code 페어 프로그래밍)
- 스택
- Python 3.11 · FastAPI · Go 1.23 · Next.js 16 · React 19 · PostgreSQL · asyncpg · Redis · Caddy · Tailwind v4

학교 운동장 손게임 기싸움을 실시간 1v1로 옮긴 게임. 제품은 작은 게임이고, 핵심은 엔지니어링 — 두 서버 런타임(Python·Go)이 같은 Redis 게임 상태를 공유, 방 기반 PvP, AI 스프라이트 파이프라인.
무엇을 하나
- 실시간 1v1: 두 플레이어가 기 모으기 / 막기 / 펀치 / 기 폭발 / 텔레포트를 동시에 고른다. 같은 순간에 공개되고, 결과 매트릭스가 누가 데미지를 입고 누가 기를 모았고 누가 피했는지를 정한다. 3판 2선승.
- 두 가지 진입: Quick Match(전역 큐 자동 매칭) 또는 방 만들기 / 참여 — 호스트가 4글자 코드를 받고, 친구가 들어오고, 둘 다 캐릭터를 고르고 ready. "면접관이 30초 만에 같이 플레이"하는 경로.
- 캐릭터 6명, 각자 결정타에 터지는 시그니처 필살기.
짚을 만한 엔지니어링
- 병렬 서버 런타임 2개, 하나의 진실. Python(FastAPI)과 Go가 같은 Redis JSON blob(
ki_clash:game:{id})을 읽고 쓴다. 핵심 변경 — load →WATCH/MULTI/EXEC→ 플레이어별 Redis 채널로 publish — 이 두 런타임에 바이트 단위로 포팅됨. End-to-end 검증: Python REST로 방을 띄우고, 두 플레이어가 Go의 WebSocket으로 붙고, 둘 다charge를 보내고, 각자 올바르게 개인화된turn_result를 받는다(go-server/test_e2e.py). Go는 Caddy 라우트 한 줄 교체로 핫패스를 넘겨받게 배선돼 있고, 그 전까진 Python이 authoritative. - 분산 상태 하드닝, 버그는 기록. 인프로세스 PvP 시뮬레이터가 실제 동시성 버그 4개를 드러냈다 — 첫 연결 시 잘못된
opponent_reconnected, 중복waiting_for_action, 메시지 순서, 빠진turn_number— 각각 symptom/cause/commit 항목과 회귀 테스트로 고정. - 투명도·저작권 검수를 통과하는 AI 스프라이트 파이프라인. 파이터 PNG 36장(캐릭터 6 × 포즈 6)을 Pollinations/flux로 생성한 뒤 rembg(U2Net)로 생성기가 남긴 흰 배경을 제거. 렌더러가 포즈별 PNG를 고르고, 이미 누워 있는
ko.png가 이중 회전되지 않도록 포즈 PNG일 땐 CSS 회전을 스케일만으로 낮춘다. 특정 라이선스 캐릭터에 너무 가까웠던 스프라이트 1개는 이미 리젠 1패스 완료. - 글로 남긴 판단 흔적. 설계 결정 기록 15개(DR-1 ~ DR-15)와 2,512줄 엔지니어링 로그 — 백엔드 언어 선택(Python vs Spring vs Go), 에셋 파이프라인 형태, stateless 워커 + Redis-as-truth, 턴 제출의 낙관적 동시성 — 각각 고려한 대안과 받아들인 트레이드오프를 적어둠.
아직 안 되는 것
- 프런트엔드 자동 테스트 없음. 엔진·매치메이킹·게임 스토어·AI 상대·pub/sub은 Python 테스트 함수 151개, Go 엔진은 13개 — 하지만 React UI는 수동 검증.
- Go 런타임은 end-to-end 검증됐지만 아직 authoritative 아님. 켜는 건 Caddy 한 줄 주석 해제 + 재배포.
- 단일 왕복 Lua 원자적 submit을 작성했다가 Redis
cjson의 빈 배열 인코딩 한계로 되돌림. 현재 경합(하루 한 자릿수)에선WATCH/MULTI/EXEC로 충분. - 모바일(Expo)은 React 19 / Reanimated peer-dep 충돌로 보류 중 — 당분간 모바일 브라우저에서 PWA로 동작.
프로젝트 로그
이 프로젝트를 만들면서 남긴 트러블슈팅 · 회고 · 업데이트의 시간순 기록.
2026년 6월 1일 주14 개 · 3 업데이트 · 3 트러블슈팅 · 3 기술 회고 · 5 사용성 회고
Go-live night — real AWS deploy + the bugs only prod surfaced
트러블슈팅2026년 6월 7일 · 4 분
Go-live on AWS EC2 (t3.micro) exposed bugs no local run had: a single-player 'Game not found' from 2 uvicorn workers over in-memory state, a broken disconnect/reconnect + forfeit-stats + /health HEAD path, a pubsub listener that crashed on idle, and OOM during builds — fixed with --workers 1, a session repair, get_message polling, and 2GB swap baked into user_data.
Viewport-locked single-screen mobile + installable PWA
사용성 회고2026년 6월 7일 · 5 분
Locks every gameplay phase to one no-scroll viewport (100svh, capped arena, compact spacing) on a single stable skeleton that never reflows, removes the growing in-match turn history, makes the web client an installable home-screen PWA, and cuts the AI reveal/round hold from 5.1s/4.5s to 3s.
PixiJS v8 WebGL effects (DR-17) and the additive-overlay lesson (DR-18)
기술 회고2026년 6월 7일 · 5 분
A PixiJS v8 WebGL effect engine and /pixi-test harness wired into both PvP and vs-AI matches — plus the day's hard lesson: the first integration replaced the dynamic KiAuraArena and silently deleted its character motion, so it was reverted and re-done as an additive transparent overlay (DR-18: enhance = compose, not replace).
AWS infra as Terraform IaC — VPC + EC2 + separated EBS + EIP
기술 회고2026년 6월 4일 · 4 분
One Terraform module stands up the JJAN! backend on AWS — a /16 VPC, a single t3.micro EC2 host, a lifecycle-protected EBS data volume that outlives instance replacement, and an Elastic IP — followed by four deploy fixes the first real build surfaced (Go base bump, distroless self-healthcheck, Caddy domain, Vercel build env).
DR-16 — client-ready handshake + 8-dimension live verification
트러블슈팅2026년 6월 4일 · 5 분
Gated turn 1 behind a two-player presence check so the 5s turn clock never starts against a ghost opponent, split the room start-guard from the handoff-guard to fix a 'Match starting' hang, made CharacterAvatar render the real fighter PNG, then ran an 8-dimension live verification that surfaced 4 bugs.
Vercel monorepo routing + canonical-domain redirects
트러블슈팅2026년 6월 3일 · 2 분
Added a root-level vercel.json so Vercel builds the web/ subdirectory in this monorepo instead of failing on a missing root package.json, then layered 301 redirects so www and the old kiclash alias both funnel to the canonical jjan.daeseon.ai.
Rebrand to JJAN! · 짠 + recruiter-ready bilingual README
업데이트2026년 6월 2일 · 3 분
Renamed the user-visible product from "Ki Clash" to "JJAN! · 짠" across the web surfaces (metadata, lobby, shop, share-sheet) while keeping the internal ki-clash code slug untouched, and shipped a grounded bilingual EN/KO recruiter README plus a problem-indexed troubleshooting reference.
Character-specific ultimate finishers + real fighter PNGs on select
사용성 회고2026년 6월 2일 · 3 분
Replaced the one generic match-end beam with six per-character signature ultimates, swapped the emoji placeholders on character-select for the real fighter PNGs under global-friendly names, and closed the 6×6 fighter sprite matrix with seokjin + yuri's pose sets.
Phase 11 — in-house FX overhaul (Lottie-quality, no external assets)
사용성 회고2026년 6월 2일 · 4 분
Phase 11 rebuilds all six arena effects in-house with framer-motion + canvas-confetti + multi-layer SVG (zero external dependency), fixes white-box fighter backgrounds with local AI bg removal + pose-aware sprite transforms, and splits the Attack (POW punch) and Energy Wave (energy-beam) moves into visually disjoint FX.
Deploy-night checkpoint — Phase 7G/8/10 done, Phase 9 (live deploy) pending Jason
업데이트2026년 6월 1일 · 3 분
Deploy-night checkpoint: Phases 1-4, 7, 8, and 10 are done and the backend is production-ready; Phase 9 (the actual AWS EC2 + Vercel deploy) is the only outstanding work and is waiting on Jason — nothing is live yet.
Phases 7D-F — fighter sprites, hit/KO reactions, image-first pipeline + 6 AI idle sprites
사용성 회고2026년 6월 1일 · 1 분
Phases 7D-F replaced placeholder fighters with humanoid then shōnen-knockoff sprites, added hit/KO reactions and a match-end final-blow KO sequence, and moved to an image-first pipeline backed by 6 AI-generated idle sprites.
Phase 10 — standalone Go WebSocket game server (scaffold → game loop → hardening)
기술 회고2026년 6월 1일 · 3 분
Three commits stood up the Go game-server tier from DR-1's hybrid 2-tier design: a WebSocket scaffold, a full game-loop port wired for prod, and a hardening pass adding cross-instance reconnect, metrics, Sentry, unit tests, and a load harness.
Phase 7 — cinematic match-end finale + anime ki-aura arena
사용성 회고2026년 6월 1일 · 2 분
Phase 7 ships a cinematic match-end finale and an anime ki-aura arena in the web client, realizing decision DR-2's move from pixel art to a high-impact arcade anime aesthetic.
Phase 8 — Tekken-style room PvP (create code, share, character select, ready up)
업데이트2026년 6월 1일 · 1 분
Phase 8 adds Tekken-style room PvP — create a room code, share it, pick a character, and ready up — with a backend rooms API plus the frontend /pvp flow, followed by a chore to auto-derive the WebSocket URL from the API URL in production.
2026년 5월 25일 주9 개 · 2 업데이트 · 2 트러블슈팅 · 5 기술 회고
RESUME-HERE checkpoint added to the engineering log
업데이트2026년 5월 28일 · 1 분
Added a Part 0 'RESUME HERE' checkpoint to docs/engineering-log.md so the next session opens with a single where-are-we / what's-next handoff snapshot.
Phase 6 — production stack scaffold (AWS EC2 + Vercel hybrid)
업데이트2026년 5월 27일 · 2 분
Scaffolded the production deployment stack as an AWS EC2 + Vercel hybrid — a single docker-compose stack (db + redis + api + caddy) on EC2 with Caddy terminating TLS and reverse-proxying the FastAPI backend, and the Next.js frontend on Vercel.
Wrote the Engineering Decision Reference (DR-1..11)
기술 회고2026년 5월 26일 · 2 분
Added a 'Part 2 — Engineering Decision Reference' section to docs/engineering-log.md with 11 deep trade-off analyses (DR-1..DR-11), each documenting the decision, options, trade-off table, reasoning chain, meta-pattern, and interview framing.
Multiplayer networking reference (Ki Clash vs LoL / Valorant)
기술 회고2026년 5월 26일 · 1 분
Created a standalone Korean networking reference doc that maps Ki Clash code onto real-time multiplayer concepts, doubling as Toronto game/systems interview prep.
Phase 2 — test coverage + observability (JWT auto-recovery, JSON logs, Sentry, Prometheus)
기술 회고2026년 5월 26일 · 4 분
Phase 2 added 52 new tests (game engine, matchmaking) and the observability backbone — structured JSON logging, Sentry, and Prometheus /metrics — plus a client-side JWT 401 auto-recovery fix. Suite grew from 52 to 99 tests.
Phase 3 — fixed the 4 PvP concurrency bugs
트러블슈팅2026년 5월 26일 · 2 분
Phase 3 fixed the 4 PvP concurrency bugs documented as xfail during Phase 2.1; the integration suite went from 6 passed / 4 xfailed to 10 passed, and the full suite to 126 passed.
Phase 4 — Redis-backed stateless PvP (game store, cross-worker pub/sub, 149 tests)
기술 회고2026년 5월 26일 · 4 분
Phase 4 externalized all in-memory PvP state to Redis, added per-player pub/sub for cross-worker routing, and used optimistic concurrency for atomic two-player turns — landing the full suite at 149 tests passing in ~23s.
PvP simulator surfaces 4 concurrency bugs (captured as xfail tests)
트러블슈팅2026년 5월 26일 · 3 분
Driving a real Bo3 match through a PvP simulator against the live docker stack surfaced 4 concurrency/protocol bugs, which were then locked into a permanent pytest integration harness as xfail tests.
Asset pipeline + fallback components; pixel-art moved to deprecated/
기술 회고2026년 5월 25일 · 2 분
Scaffolded a drop-in asset pipeline with graceful emoji fallback components on web and mobile, and moved the pixel-art code into a deprecated/ folder via git mv since 12+ active screens still import it.
2026년 2월 16일 주6 개 · 3 업데이트 · 3 사용성 회고
6 original Korean fighters, character select, selection timer, AI trash talk + tutorial
사용성 회고2026년 2월 22일 · 2 분
Added a roster of 6 original Korean fighters with a dedicated character select screen, converted the countdown into a selection timer, layered in AI trash talk and an interactive tutorial, and ported the whole set to mobile.
Core game built in a day — engine, backend API, web frontend
업데이트2026년 2월 22일 · 1 분
Single milestone commit shipped the product-agnostic game engine, an AI opponent with difficulty tiers, a versioned FastAPI backend, and a Next.js web frontend — plus dev-workflow slash commands.
Game feel — Web Audio SFX, card-flip reveal, screen shake, countdown rhythm
사용성 회고2026년 2월 22일 · 1 분
A game-feel pass on the web client: a 3-beat countdown between action confirm and reveal, procedural Web Audio sound effects with a mute toggle, a card-flip reveal with screen shake on outcomes, and an animated AI thinking indicator.
Pixel-art fighter system (web + mobile)
사용성 회고2026년 2월 22일 · 2 분
Built a dedicated pixel-art rendering layer plus per-fighter frame data for 6 fighters, wired it into the live web game UI, and ported the whole system to the React Native mobile client.
PvP realtime backend — WS manager, Redis matchmaking, session loop
업데이트2026년 2월 22일 · 1 분
Built the realtime PvP backbone for Ki Clash: a room-based WebSocket manager, a Redis-backed FIFO matchmaking service, and a WebSocket-driven game session, plus a PvP frontend with matchmaking and game UI.
React Native (Expo) mobile app + full game flow
업데이트2026년 2월 22일 · 1 분
Scaffolded a React Native (Expo) mobile app with TypeScript and expo-router, then built the full game UI, AI/PvP flow, and ported the web 'game feel' features to native.