배경 및 목적: 여러 사람과 함께 해야 하는 추론 게임을, 다른 사람으로 인한 부담이나 압박 없이 누구나 혼자서 AI 참가자들과 편하게 즐길 수 있게 하고자 개발하였습니다.
핵심 목표: 독립된 페르소나를 지닌 AI 참가자와의 1인 추론 게임 경험 제공, 게임 규칙 엔진과 플랫폼을 모노레포 내 별도 패키지로 분리하여 다양한 게임으로 확장이 가능한 체계 구축.
2. 담당 역할 및 핵심 기능
담당 역할: 아키텍처 설계/구현을 포함한 프론트엔드 개발 및 에이전트를 활용한 개발 체계 구축 1인 전담
핵심 기능 목록:
반응형 1인 마피아 게임: 낮(자유 토론·시간 조절·투표·변론)과 밤(타겟 선정) 등 실시간 페이즈별 상태에 최적화된 모바일 친화적 입력 컨트롤 제공
실시간 타임라인 및 상태 동기화: HTTP 명령과 SSE 단방향 스트리밍을 결합한 실시간 대화 및 상태 수신
3. LLM 활용 방향 및 범위
프론트엔드/백엔드 모두 기능 구현 시 먼저 LLM과의 질의응답을 통해 세부 기획과 스펙을 엄밀하게 구체화한 후 이를 그대로 코드로 작성하도록 에이전트를 제어하며 생산성 있게 작업하였습니다.
프론트엔드는 에이전트의 초기 작성 후 생성된 모든 코드를 읽고 검토한 후 아키텍처 등 전체적인 설계와 코드를 직접 개선 및 재작성하며 진행하였습니다. 백엔드는 주력인 프론트엔드 아키텍처 및 사용자 경험에 집중하기 위해 스펙 설계 후 빠르게 작성하도록 효율화하였습니다.
사용하는 기술 스택에 관한 에이전트 스킬을 설치하여 에이전트의 구현 능력을 향상시켰으며, 특히 접근성이나 SEO 등 웹 퀄리티를 최적화하기 위해 관련 스킬을 통한 리뷰를 반복하였습니다.
단순 프롬프트 지시 시 컴포넌트가 비대해 지는 등 생성되는 코드 퀄리티에서 반복적으로 나타나는 문제 해결을 위해, 평소 중요하게 생각해왔던 개발 철학과 설계 기준을 규격화해 선언적 타입스크립트 함수형 패턴, 커스텀 훅 기반의 리액트 뷰-로직 분리, UI 트리 아키텍처 리뷰 등의 에이전트 스킬을 작성하여, 에이전트가 고품질 코드를 작성하고 교정할 수 있는 제어 체계를 구축하였습니다.
#
4. 핵심 의사결정 및 문제 해결
1) 비용 최적화와 자연스러운 대화 흐름을 위한 AI 참가자 발화 오케스트레이션 설계
상황 및 과제: 게임 스냅샷이 갱신될 때마다 모든 AI가 발화 결정을 위해 동시에 LLM을 호출하면 API 비용이 과도하게 소모되고, 여러 참가자들이 한 번에 발언을 쏟아내는 등 대화 흐름이 부자연스러운 문제가 발생하였습니다.
기술적 의사결정: 시행착오 끝에 전체 참가자의 API 동시 호출 대신 임의 참가자의 LLM 요청 후 침묵 결정 시 참가자가 다음 호출 후보를 결정하게 하는 라우팅을 적용하기로 결정했습니다.
구현 및 해결: AI 참가자 중 한 명을 무작위로 선택하여 LLM API를 호출하고, LLM 응답에서 발화를 결정하면 즉시 루프를 종료하고 응답 내용으로 스냅샷에 대화를 추가하는 반면 침묵을 결정할 시엔 응답에서 다음 발화 후보를 추천하여 같이 반환하도록 한 후 이 후보로 다음 API 호출을 반복하는 오케스트레이터를 구현하였습니다.
결과 및 영향: 모든 AI 참가자가 API를 호출하던 방식 대비 LLM 요청 횟수를 8인 게임 기준 약 70% 절감해 운영 비용을 최적화하였으며, 실제 사람들이 턴을 주고받으며 토론하듯 자연스러운 타이밍과 밸런스를 갖춘 AI 대화 경험을 달성할 수 있었습니다.
2) UI 트리 아키텍처 리뷰와 뷰-로직 분리를 통한 복잡한 게임 컴포넌트 구조 개선
상황 및 과제: 실시간 게임 특성상 페이즈(토론·지목·변론·투표·밤), 역할, 생존 여부에 따른 수많은 상태와 조건부 분기 로직이 컴포넌트 내부에 직접 뒤섞여 코드 복잡도가 치솟고 유지보수가 어려운 문제를 체감하였습니다.
기술적 의사결정: 직접 제작한 에이전트 스킬(뷰-로직 분리 및 UI 트리 리뷰)을 적용하여, UI 렌더링 계층에서 상호작용 로직을 순수 함수로 분리하는 구조를 도입하기로 결정하였습니다.
구현 및 해결: ts-pattern 기반으로 게임 스냅샷과 상태를 페이즈별 유니온으로 변환하는 함수를 작성하고, 하위 패널 및 선택 컴포넌트들이 이를 참조해 선언적으로 사용하도록 컴포넌트 계층을 전면 재구조화하는 방향으로 코드를 개선하였습니다.
결과 및 영향: 컴포넌트 내 난잡했던 명령형 분기 코드를 완전히 걷어내어 UI 구조를 직관적으로 개선하였으며, 리액트 렌더링과 독립된 단위 테스트 환경에서 모든 페이즈별 상호작용을 안전하게 검증할 수 있게 되었습니다.
3) 사용자 의도 예측형 프리페치와 컴포넌트 지연 로딩을 통한 진입 UX 최적화
상황 및 과제: 메인 페이지 로딩 시 번들 크기를 줄이기 위해 게임 시작 다이얼로그 컴포넌트를 코드 스플리팅 및 지연 로딩하였으나, 사용자가 '게임 시작' 버튼을 누르는 순간 JS 청크 다운로드와 잔여 플레이 가능 횟수 API 조회가 발생하여 모달 오픈에 체감 지연이 생기는 것을 발견하였습니다.
기술적 의사결정: 단순 React.lazy 분할에 그치지 않고, 사용자 마우스 이동 궤적을 감지하여 클릭 의도를 사전에 예측하는 ForesightJS 기반의 예측형 프리페칭과 전용 스켈레톤 UI를 결합하기로 결정했습니다.
구현 및 해결: 버튼 접근 시 다이얼로그 컴포넌트 청크와 TanStack Query 게스트 권한 데이터를 병렬로 사전 로딩하고, Suspense 폴백으로 모달 스켈레톤을 배치하였습니다.
결과 및 영향: 메인 페이지의 JS 번들 크기를 10%(19KB) 경량화하여 LCP를 1.15s에서 0.95s로, 버튼 클릭 시의 다이얼로그 오픈 INP를 112ms에서 64ms로 단축해 보다 쾌적한 진입 경험을 완성하였습니다.
5. 주요 성과
실시간 스트리밍(SSE), 페이즈 전환, 타이머, 유저 입력이 공존하는 복잡한 상태를 뷰-로직 분리로 구조화하여, 매끄러운 1인 추론 게임을 완성
폰트 레이아웃 시프트 방지, 프리페치를 활용한 다이얼로그 지연 로딩, 접근성 및 반응형 UI 최적화 등을 통해 다양한 기기의 웹 브라우저에서도 쾌적한 사용자 경험 제공