RummiArena — 멀티 LLM 전략 실험 플랫폼 프로젝트 소개
1. 프로젝트의 탄생 배경
1.1 루미큐브라는 게임
루미큐브(Rummikub)는 1940년대 루마니아 태생의 이스라엘인 에프라임 헤르차노(Ephraim Hertzano)가 마작, 러미 카드게임, 도미노 등의 규칙을 착안하여 발명한 타일 기반 보드게임이다. 그는 가족과 함께 첫 세트를 손수 제작했고, 방문판매와 위탁판매로 이 게임을 퍼뜨리기 시작했다. 1970년대에 미국으로 전해지면서 폭발적인 인기를 얻었고, 1977년에는 미국 베스트셀러 게임에 올랐다. 1980년에는 세계적 권위를 가진 독일 올해의 게임상(Spiel des Jahres)을 수상하며 명실상부한 세계적 보드게임으로 자리매김했다. 오늘날 루미큐브는 체스, 모노폴리와 함께 세계에서 세 번째로 많이 판매된 보드게임으로 알려져 있다.
루미큐브의 가장 큰 매력은 전략적 사고와 운, 그리고 상대방에 대한 심리전이 절묘하게 결합된다는 점에 있다. 플레이어는 총 106개의 타일(4가지 색상의 숫자 타일 104장과 조커 2장)을 사용하여 경쟁하며, 자신의 타일을 가장 먼저 모두 내려놓는 사람이 승리한다. 단순히 타일을 나열하는 것에 그치지 않고, 이미 테이블에 놓인 타일들을 재배치하여 새로운 조합을 만들어내는 “재조합” 전략이 핵심이다. 이 재조합 능력이야말로 초보자와 고수를 구분하는 가장 중요한 요소이며, 컴퓨터 과학적 관점에서 보면 상당히 복잡한 조합 최적화 문제를 실시간으로 풀어야 하는 도전적인 과제이기도 하다.
1.2 LLM과 게임 플레이의 만남
2025년을 전후로 대규모 언어모델(LLM)을 활용한 게임 에이전트 연구가 활발하게 진행되고 있다. IBM Research와 A*STAR가 공동 개발한 TextArena는 LLM 에이전트끼리 수십 가지 텍스트 기반 게임에서 대결하는 오픈소스 플랫폼이고, ICLR 2026에서 발표된 GamingAgent(lmgame-Bench)는 다양한 게임 환경에서 LLM/VLM 기반 에이전트의 성능을 표준화된 방식으로 벤치마킹한다. 2025년 10월에는 주요 LLM들이 온라인 포커 대회에서 격돌하여 OpenAI가 우승하고 Meta의 LLAMA가 가장 부진한 성적을 거두기도 했다. 외교(Diplomacy) 게임에서는 Gemini, o3, Claude 등이 협상과 배신을 오가며 경쟁하는 실험이 이루어졌는데, 이 실험은 LLM의 사회적 지능과 전략적 행동을 평가하는 중요한 벤치마크로 주목받았다.
이처럼 LLM이 단순한 텍스트 생성을 넘어서 규칙 이해, 전략 수립, 상대 분석, 심리전까지 수행할 수 있는지를 검증하려는 시도가 학계와 산업계 전반에서 활발히 이루어지고 있다. RummiArena 프로젝트는 바로 이러한 흐름의 연장선에서, 루미큐브라는 전략적으로 풍부한 보드게임을 매개로 다양한 LLM 모델의 게임 전략 능력을 비교 분석하는 실험 플랫폼을 구축하고자 탄생했다.
1.3 프로젝트의 목적
RummiArena는 단순히 AI가 게임을 플레이하는 것을 구경하는 시스템이 아니다. 이 프로젝트는 크게 네 가지 핵심 목표를 추구한다.
첫째, 멀티 LLM 전략 비교이다. OpenAI의 GPT-4o, Anthropic의 Claude, DeepSeek, 그리고 Ollama를 통해 실행되는 로컬 LLaMA 모델 등 다양한 LLM이 동일한 게임 환경에서 대결한다. 각 모델에 동일한 캐릭터와 난이도를 부여하거나, 서로 다른 조합을 적용하여 모델별 강점과 약점을 실험적으로 비교할 수 있다.
둘째, Human과 AI의 혼합 대전이다. 2~4인의 인간 플레이어와 AI 플레이어가 한 테이블에서 실시간으로 경쟁한다. 인간은 AI의 전략을 관찰하고 학습할 수 있고, AI는 인간의 비정형적 플레이 패턴에 대응해야 한다. 이를 통해 AI의 실전 적응 능력도 간접적으로 측정할 수 있다.
셋째, 풀스택 플랫폼 엔지니어링 실습이다. Kubernetes, GitOps(ArgoCD + Helm), DevSecOps(SonarQube + Trivy), 서비스 메시(Istio) 등 현대적인 클라우드 네이티브 기술 스택의 전체 사이클을 1인 개발 환경에서 직접 경험하는 것을 목표로 한다.
넷째, 외부 공개 가능한 아키텍처 수준의 설계이다. 내부 실험 프로젝트이지만, SaaS 서비스를 운영하는 것과 같은 수준의 아키텍처 설계를 적용하여 향후 확장이나 공개에 대비한다.
2. 시스템 아키텍처
2.1 전체 구조
RummiArena의 아키텍처는 마이크로서비스 지향적인 폴리글랏(Polyglot) 구조를 채택하고 있다. 시스템은 크게 프론트엔드 레이어, 백엔드 레이어, 데이터 레이어, 그리고 외부 API 레이어로 나뉜다.
프론트엔드 레이어에는 게임 UI를 담당하는 Next.js 기반 프론트엔드 애플리케이션과, 관리자 대시보드 역할을 하는 별도의 Next.js 관리자 패널이 있다. 이 두 애플리케이션은 각각 포트 3000과 3001에서 동작하며, TailwindCSS로 스타일링하고 Framer Motion으로 애니메이션을 처리한다. 특히 게임 UI에서는 타일을 끌어다 놓는 드래그 앤 드롭 인터랙션이 핵심이므로 dnd-kit 라이브러리를 활용한다.
백엔드 레이어가 이 프로젝트의 가장 흥미로운 설계 지점이다. Game Server와 AI Adapter라는 두 개의 독립된 서비스로 구성되어 있으며, 각각 서로 다른 언어와 프레임워크를 사용한다. Game Server는 Go 언어로 작성되어 포트 8080에서 동작하고, AI Adapter는 NestJS(TypeScript)로 작성되어 포트 8081에서 동작한다. 이 폴리글랏 구성을 채택한 이유는 뒤에서 자세히 설명한다.
데이터 레이어에서는 PostgreSQL 16이 사용자 정보, 게임 전적, AI 호출 로그, 시스템 설정 등 영속적인 데이터를 관리하고, Redis 7이 게임 진행 중의 상태, 세션 정보, 턴 타이머 등 휘발성이지만 고속 접근이 필요한 데이터를 관리한다.
외부 API 레이어에서는 OpenAI, Claude, DeepSeek의 클라우드 API와, 로컬에서 실행되는 Ollama(LLaMA)가 AI 플레이어의 두뇌 역할을 한다. 또한 Google OAuth 2.0이 인증을, 카카오톡 API가 알림을 담당한다.
2.2 폴리글랏 아키텍처: Go와 NestJS의 공존
RummiArena의 백엔드가 두 가지 언어를 사용하는 이유는 각 서비스의 특성에 최적화된 기술을 선택하기 위함이다.
Game Server에 Go를 선택한 이유는 명확하다. 첫째, goroutine 기반의 동시성 모델이 WebSocket 연결을 매우 효율적으로 처리할 수 있다. 연결 하나당 스레드를 할당하는 방식보다 메모리 사용이 훨씬 적다. 둘째, 게임 엔진의 규칙 검증 로직은 CPU를 집중적으로 사용하는 연산이므로 컴파일 언어인 Go의 성능이 유리하다. 셋째, 멀티스테이지 Docker 빌드를 통해 scratch 이미지 기반으로 약 15MB의 극도로 가벼운 컨테이너 이미지를 만들 수 있어 Kubernetes Pod의 시작 시간을 최소화할 수 있다. 넷째, Go는 Kubernetes 생태계의 네이티브 언어이므로 플랫폼 엔지니어링 학습 목적에도 부합한다.
AI Adapter에 NestJS(TypeScript)를 선택한 이유도 합리적이다. LLM API 호출은 I/O 바운드 작업이므로 Node.js의 비동기 이벤트 루프 모델이 충분히 효율적이다. JSON 형태의 LLM 응답을 파싱하고 프롬프트 템플릿을 관리하는 데에는 TypeScript의 풍부한 타입 시스템이 편리하다. 또한 프론트엔드(Next.js)와 DTO나 타입 정의를 공유할 수 있는 잠재력도 있다.
물론 폴리글랏 구성에는 추가 비용이 있다. 빌드 파이프라인을 두 벌 관리해야 하고, 개발자(이 경우 1인)가 두 언어 모두에 숙달해야 한다. 그러나 이 프로젝트는 Go 실전 경험 확보라는 학습 목표와, 서비스별 최적 기술을 선택한다는 마이크로서비스 원칙을 동시에 달성하기 위해 이 비용을 감수하고 있다. GitLab CI의 멀티스테이지 파이프라인으로 두 서비스의 빌드를 체계적으로 관리할 수 있으므로 운영상의 복잡성은 통제 가능하다.
2.3 핵심 설계 원칙
RummiArena의 아키텍처를 관통하는 몇 가지 핵심 원칙이 있다.
LLM 신뢰 금지 원칙은 이 프로젝트에서 가장 중요한 설계 철학이다. LLM은 게임에서의 행동을 “제안”할 뿐이며, 그 제안이 실제로 유효한지는 반드시 Game Engine이 검증한다. LLM이 잘못된 수를 제안하면 에러 메시지와 함께 최대 3회까지 재요청하고, 3회 모두 실패하면 강제로 드로우 처리한다. 이 원칙 덕분에 어떤 LLM 모델이 아무리 엉뚱한 응답을 내놓더라도 게임 자체의 무결성은 항상 보장된다.
Stateless 서버 설계는 Kubernetes 환경에서의 안정성을 위해 채택되었다. 모든 게임 상태는 Redis에, 영속적 데이터는 PostgreSQL에 저장되므로, Game Server Pod이 재시작되더라도 30초 이내에 게임을 복구할 수 있다. 현재는 단일 인스턴스(replicas: 1)로 운영하지만, 향후 수평 확장 시에는 Redis Pub/Sub를 도입하여 인스턴스 간 WebSocket 이벤트를 동기화하는 구조로 확장할 수 있도록 설계되어 있다.
AI Adapter 분리 원칙은 Game Engine이 특정 LLM에 의존하지 않도록 보장한다. 모든 LLM은 동일한 MoveRequest/MoveResponse 인터페이스를 통해 통신하므로, 새로운 모델을 추가할 때 Adapter 하나만 구현하면 된다. 이 구조 덕분에 Phase 5에서 Istio Service Mesh를 도입하면 VirtualService를 통해 모델별 트래픽 가중치 라우팅까지 가능해진다.
3. 게임 엔진과 규칙 체계
3.1 타일 시스템
RummiArena의 게임 엔진은 루미큐브의 공식 규칙을 충실하게 구현한다. 총 106장의 타일은 4가지 색상(빨강, 파랑, 노랑, 검정) × 13개 숫자(1~13) × 2세트(a, b) = 104장의 숫자 타일과 2장의 조커(JK1, JK2)로 구성된다.
타일을 프로그래밍적으로 표현하기 위해 {Color}{Number}{Set} 형식의 인코딩 규칙을 사용한다. 예를 들어 R7a는 빨강 7의 세트 a를, B13b는 파랑 13의 세트 b를, JK1은 첫 번째 조커를 의미한다. 이 인코딩은 시스템의 모든 구성요소(Game Engine, AI Adapter, 프론트엔드, Redis 저장소)에서 통일적으로 사용되어 데이터의 일관성을 보장한다.
3.2 세트의 유효성 검증
테이블에 놓인 타일들은 반드시 “그룹” 또는 “런” 중 하나의 유효한 세트에 속해야 한다.
그룹(Group)은 같은 숫자이면서 서로 다른 색상의 타일 3~4장으로 구성된다. 예를 들어 [R7a, B7a, K7b]는 유효한 그룹이다. 같은 색상이 중복되거나(예: [R7a, R7b, B7a]), 숫자가 불일치하거나(예: [R7a, B8a, K7b]), 2장 이하이면 무효이다.
런(Run)은 같은 색상이면서 연속된 숫자의 타일 3장 이상으로 구성된다. 예를 들어 [Y3a, Y4a, Y5a]는 유효한 런이다. 숫자가 연속하지 않거나, 색상이 다르거나, 13에서 1로의 순환(wrap-around)은 허용되지 않는다.
조커는 그룹이나 런에서 어떤 타일이든 대체할 수 있으며, 테이블 위의 조커를 해당 타일로 교체하고 회수할 수도 있다. 단, 회수한 조커는 같은 턴 내에 반드시 다른 세트에 사용해야 한다.
3.3 게임 진행 흐름
게임은 106장의 타일을 생성하여 Fisher-Yates 알고리즘으로 균등하게 셔플한 뒤, 각 플레이어에게 14장씩 분배하고, 나머지를 드로우 파일로 남겨두는 것으로 시작한다. 2인 게임이라면 78장, 3인이라면 64장, 4인이라면 50장이 드로우 파일에 남게 된다.
각 플레이어의 턴에는 타일 배치(Place)와 타일 뽑기(Draw) 중 하나를 선택할 수 있다. 배치를 선택하면 자신의 랙에서 타일을 꺼내 테이블 위의 유효한 세트를 구성해야 하며, 최초 등록을 완료한 이후에는 테이블에 이미 있는 타일들을 자유롭게 재배치할 수도 있다. 턴이 확정되면 Game Engine은 테이블 위의 모든 세트가 유효한지, 랙에서 최소 1장 이상의 타일이 추가되었는지, 테이블에서 타일이 유실되지 않았는지 등 총 15가지 검증 규칙을 철저하게 점검한다.
최초 등록(Initial Meld)은 게임에서 처음으로 타일을 테이블에 내려놓을 때 적용되는 특별 규칙이다. 반드시 자신의 랙 타일만으로 합계 30점 이상의 세트를 구성해야 하며, 이 조건을 충족하기 전에는 테이블 재배치가 불가능하다. 이 규칙은 게임 초반의 전략적 긴장감을 높이는 중요한 장치이다.
3.4 승리 조건과 교착 상태
자신의 랙에 있는 타일을 모두 유효한 세트로 내려놓은 플레이어가 승리한다. 교착 상태는 드로우 파일이 소진된 후 전체 플레이어가 한 라운드(인원 수만큼의 턴) 동안 아무도 배치하지 못할 때 발생하며, 이 경우 남은 타일의 숫자 합산이 가장 적은 플레이어가 승리한다. 동점이면 타일 수가 적은 쪽이 우선하고, 그것도 동점이면 무승부로 처리한다. 점수 계산에서 조커는 30점으로 매우 무겁게 책정되므로, 조커를 끝까지 보유하는 전략에는 상당한 리스크가 따른다.
3.5 테이블 재배치: 루미큐브의 꽃
테이블 재배치(Rearrangement)는 루미큐브를 다른 보드게임과 차별화하는 핵심 메커니즘이다. 최초 등록을 완료한 플레이어는 기존 테이블 위의 세트에서 타일을 분리하여 다른 세트로 이동하거나, 세트를 합치거나, 조커를 교체하는 등 다양한 형태의 재배치를 수행할 수 있다. 단, 반드시 자신의 랙에서 최소 1장 이상을 추가해야 하며, 턴 종료 시 테이블의 모든 세트가 유효한 상태여야 한다. 재배치에 실패하면 테이블은 턴 시작 시의 스냅샷으로 롤백되고, 패널티로 3장을 추가로 뽑아야 한다.
이 재배치 메커니즘은 AI에게도 매우 도전적인 과제이다. 고수 AI는 복잡한 체인 재배치를 수행하여 한 턴에 다수의 타일을 소진할 수 있어야 하는 반면, 하수 AI는 재배치를 시도하지 않는 단순한 플레이를 하도록 설계된다.
4. AI 캐릭터 시스템
4.1 설계 철학
RummiArena의 AI 캐릭터 시스템은 이 프로젝트를 단순한 “AI가 루미큐브를 하는 프로그램”에서 “LLM 전략 실험 플랫폼”으로 격상시키는 핵심 기능이다. AI 플레이어는 캐릭터(성격), 난이도, 심리전 수준이라는 세 가지 축의 조합으로 구성되며, 이 조합에 따라 프롬프트가 동적으로 생성되어 LLM의 행동 양식이 결정된다.
4.2 6가지 캐릭터
각 캐릭터는 고유한 전략 성향과 플레이 스타일을 가진다.
루키(Rookie) 는 이름 그대로 초보자처럼 플레이한다. 단순한 그룹과 런만 만들고 테이블 재배치는 시도하지 않는다. 의도적으로 10~20% 확률로 최적 수 대신 차선의 수를 선택하여 “실수”를 시뮬레이션한다.
칼큘레이터(Calculator) 는 감정 없이 논리적으로 플레이하는 캐릭터이다. 남은 타일의 확률을 계산하고, 기대값을 최대화하는 수를 선택하며, 조커를 아껴두는 효율적인 스타일을 보여준다.
샤크(Shark) 는 공격적인 압박형 캐릭터이다. 가능한 한 많은 타일을 빠르게 내려놓고, 상대가 필요로 할 것으로 추정되는 타일을 선점하여 견제한다. 블러핑도 활용한다.
폭스(Fox) 는 교활한 전략가이다. 낼 수 있는 타일도 전략적으로 보류하다가 한 턴에 대량으로 배치하는 “폭탄 전략”을 구사한다. 페이크 드로우와 역심리를 마스터한 캐릭터이다.
월(Wall) 은 수비적이고 끈질긴 캐릭터이다. 최소한의 타일만 내려놓으며 상대를 방해하고 장기전으로 유도한다. 절대 서두르지 않는 스타일이다.
와일드카드(Wildcard) 는 예측 불가능한 캐릭터이다. 매 턴마다 다른 전략을 혼합하여 상대를 혼란에 빠뜨리며, 일관성 없는 플레이가 오히려 이 캐릭터의 정체성이다.
4.3 3단계 난이도
난이도는 AI에게 제공되는 정보의 양과 사용하는 LLM 모델의 수준, 그리고 허용되는 전략의 복잡도를 결정한다.
하수(Beginner) 난이도에서는 경량 모델(gpt-4o-mini, llama3.2:1b)을 사용하고, 자신의 타일과 테이블 상태만 볼 수 있으며, 재배치는 사용하지 않는다. 심리전도 적용되지 않는다.
중수(Intermediate) 난이도에서는 중급 모델(gpt-4o-mini, deepseek-chat)을 사용하고, 상대 플레이어의 남은 타일 수까지 고려할 수 있다. 기본적인 재배치를 활용하며, 심리전 Level 1~2가 적용된다.
고수(Expert) 난이도에서는 최상위 모델(gpt-4o, claude-sonnet, deepseek-r1)을 사용하고, 전체 행동 히스토리와 미출현 타일 목록까지 분석한다. 적극적인 체인 재배치를 수행하며, 심리전 Level 2~3의 고도화된 심리 전략을 구사한다.
4.4 심리전 시뮬레이션
실제 루미큐브에서 숙련된 인간 플레이어는 다양한 심리전을 활용한다. RummiArena는 이를 4단계(Level 0~3)의 심리전 시스템으로 모델링한다.
Level 0은 심리전 없이 순수하게 최적의 수만 계산하는 단계이다. Level 1에서는 기본적인 블러핑(의도적 지연, 페이크 무브)이 도입된다. Level 2에서는 상대의 행동 패턴을 분석하여 역이용하는 전략이 추가된다. Level 3에서는 타일 홀딩, 역블러핑, 상대 유인, 템포 제어까지 포함하는 고급 심리전이 시뮬레이션된다.
이러한 심리전 전략은 프롬프트를 통해 LLM에 지시되며, AI Adapter의 PromptBuilder가 캐릭터, 난이도, 심리전 수준을 조합하여 최종 프롬프트를 동적으로 생성한다. 이 시스템 덕분에 동일한 LLM 모델이라도 부여된 캐릭터와 심리전 수준에 따라 전혀 다른 플레이 스타일을 보여줄 수 있다.
4.5 실험적 가치
캐릭터 시스템의 진정한 가치는 AI 실험 플랫폼으로서의 분석 능력에 있다. GPT-4o에 Shark 캐릭터를 부여한 것과 Claude에 Fox 캐릭터를 부여한 것의 대결 결과를 통계적으로 분석할 수 있고, 동일 모델에 심리전 유무를 달리하여 승률 차이를 측정할 수도 있다. 어떤 캐릭터-난이도 조합이 가장 높은 승률을 기록하는지, 인간 플레이어는 어떤 AI 스타일에 가장 취약한지 등 다양한 실험 시나리오가 가능하다.
5. AI Adapter 서비스
5.1 공통 인터페이스
AI Adapter는 Game Server와 다양한 LLM 사이의 중간 계층으로서, 모델에 무관한 공통 인터페이스를 제공한다. Game Server는 POST /api/ai/move 엔드포인트로 MoveRequest를 보내기만 하면 되고, AI Adapter가 내부적으로 적절한 LLM을 호출하여 MoveResponse를 반환한다.
MoveRequest에는 게임 ID, 현재 게임 상태, 캐릭터(persona), 난이도(difficulty), 심리전 수준(psychologyLevel), 최대 재시도 횟수, 타임아웃 시간이 포함된다. MoveResponse에는 수행할 행동(place 또는 draw), 배치할 타일 그룹, 사용할 랙 타일 목록, AI의 사고 과정(reasoning), 그리고 모델 유형, 지연시간, 토큰 사용량 등의 메타데이터가 포함된다.
5.2 프롬프트 설계
PromptBuilder는 시스템 프롬프트, 캐릭터 지시, 현재 게임 상태, 플레이어 타일 정보, 상대 정보, 게임 히스토리를 조합하여 최종 프롬프트를 구성한다. 전체 프롬프트의 토큰 예산은 약 2,000토큰 이내로 관리되며, 히스토리가 이 한도를 초과하면 오래된 항목부터 제거한다. 난이도에 따라 제공되는 히스토리의 깊이도 달라지는데, 하수는 0턴, 중수는 3턴, 고수는 5턴의 히스토리를 참조한다.
5.3 재시도 및 Fallback 로직
LLM의 응답이 실패하거나 파싱에 실패하거나 Game Engine의 유효성 검증을 통과하지 못하면 재시도가 이루어진다. 재시도 시에는 이전 실패의 에러 메시지를 프롬프트에 포함하여 LLM이 같은 실수를 반복하지 않도록 유도한다. 3회 모두 실패하면 해당 턴은 강제 드로우로 처리되며, 5턴 연속 강제 드로우가 발생하면 해당 AI를 비활성화하고 관리자에게 알림을 보낸다.
5.4 비용 제어
LLM API 호출에는 비용이 발생하므로 Quota 시스템이 설계되어 있다. 사용자당 일일 AI 호출 횟수는 500회, 게임당 AI 호출 횟수는 200회로 제한되며, 전체 시스템의 일일 API 비용 한도는 $10으로 설정된다. 비용 추적은 Redis Hash를 통해 모델별로 실시간 집계되며, 한도 초과 시 외부 API 모델이 비활성화되고 Ollama(로컬) 모델만 허용된다.
5.5 LangChain/LangGraph 도입 검토
Sprint 4에서는 AI 호출 방식을 직접 API 호출로 할 것인지, LangChain/LangGraph를 도입할 것인지를 PoC를 통해 결정할 예정이다. 단순한 프롬프트에서 JSON 응답을 받는 수준이라면 직접 구현이 충분하지만, 타일 재배치 탐색을 다단계 그래프로 모델링하거나 “분석 → 후보 생성 → 평가 → 선택”이라는 복잡한 파이프라인이 필요하다면 LangGraph가 적합할 수 있다.
6. 데이터 설계
6.1 이중 저장소 전략
RummiArena는 데이터의 특성에 따라 PostgreSQL과 Redis를 이중으로 활용한다.
PostgreSQL은 사용자 계정(users), 게임 기록(games), 게임 참가자(game_players), AI 호출 로그(ai_call_logs), 게임 이벤트 로그(game_events), 시스템 설정(system_config), ELO 레이팅 변경 이력(elo_history), 연습 세션(practice_sessions), 게임 복기용 턴 스냅샷(game_snapshots) 등 9개의 핵심 테이블로 구성된다. UUID를 기본 키로 사용하며, JSONB 타입을 적극 활용하여 유연한 데이터 구조를 지원한다.
Redis는 게임 상태(Hash), 플레이어별 타일(List), 드로우 파일(List), 세션(Hash), 교착 상태 판정 데이터(Hash), 턴 타이머(String), 비용 추적(Hash) 등을 관리한다. 모든 게임 관련 키는 game:{gameId}:* 패턴을 따르며, 게임 진행 중에는 7,200초(2시간) TTL로, 게임 종료 후에는 600초(10분)로 TTL이 단축되어 자원을 회수한다.
6.2 게임 복기 시스템
game_snapshots 테이블은 매 턴 완료 시 비동기로 스냅샷을 저장한다. 각 스냅샷에는 해당 턴의 모든 플레이어 패, 테이블 상태, 수행된 액션, 드로우 파일 잔량, AI의 판단 근거 등이 기록된다. 게임 종료 후에는 이 스냅샷들을 기반으로 4분할 복기 뷰에서 모든 플레이어의 패를 공개하며 턴별로 재생할 수 있다. 이 복기 기능은 LLM 전략을 비교 분석하는 데 있어 핵심적인 도구이다. 게임당 평균 30~80행의 스냅샷이 생성되며, 90일 후 자동 아카이브 정책이 적용된다.
7. 인프라와 배포
7.1 Kubernetes 배포 아키텍처
모든 서비스는 Docker Desktop Kubernetes 위에 배포된다. rummikub 네임스페이스에 frontend, game-server, ai-adapter, admin, ollama가 Deployment로, redis와 postgres가 StatefulSet으로 배포된다. 각 서비스는 ClusterIP Service를 통해 내부 통신하며, NGINX Ingress Controller가 외부 요청을 라우팅한다. /는 frontend로, /api는 game-server로, /ws는 WebSocket 업그레이드를 통해 game-server로, /admin은 admin으로 연결된다. TLS 종단은 self-signed 인증서로 처리한다.
Phase 5에서는 Istio Service Mesh가 도입되어 VirtualService(트래픽 라우팅), DestinationRule(Circuit Breaker, Timeout), PeerAuthentication(mTLS) 등 서비스 메시 기능이 추가될 예정이다.
7.2 CI/CD 파이프라인
CI/CD 파이프라인은 GitOps 원칙에 따라 소스 저장소와 배포 저장소가 분리되어 있다. 코드가 Push되면 GitLab CI가 Lint, 단위 테스트, SonarQube 정적 분석(Quality Gate), Docker 빌드, Trivy 이미지 스캔을 순차적으로 수행한다. Go 서비스와 Node.js 서비스가 각각 독립된 파이프라인을 가지되, 병렬로 실행된다.
모든 게이트를 통과한 이미지는 Container Registry에 Push되고, GitOps 저장소의 Helm values에 이미지 태그가 업데이트된다. ArgoCD가 이 변경을 감지하여 자동으로 Kubernetes에 Rolling Update 방식의 무중단 배포를 수행한다. 배포 완료 후에는 카카오톡으로 결과 알림이 발송된다.
7.3 DevSecOps 보안 체계
보안은 CI 파이프라인에 통합된 DevSecOps 방식으로 관리된다. SonarQube는 코드의 버그, 취약점, 코드 스멜을 정적 분석하며, 신규 코드 기준으로 버그 0건, 취약점 0건, 코드 스멜 A등급, 커버리지 80% 이상의 Quality Gate를 통과해야 빌드가 진행된다. Trivy는 Docker 이미지의 CVE 취약점을 스캔하여 Critical 또는 High 등급의 취약점이 발견되면 파이프라인을 중단한다. Phase 5에서는 OWASP ZAP을 통한 동적 보안 테스트(DAST)도 추가될 예정이다.
7.4 리소스 제약과 교대 실행 전략
이 프로젝트는 LG 그램 15Z90R (Intel i7-1360P, RAM 16GB, 내장 GPU)이라는 제한된 하드웨어 위에서 동작한다. 16GB RAM으로는 모든 서비스를 동시에 실행할 수 없으므로, 개발 모드(앱 + DB, ~6GB), CI/CD 모드(ArgoCD + GitLab Runner, ~6GB), 품질 모드(SonarQube 단독, ~4GB), AI 실험 모드(Ollama + 1B~3B 모델, ~5GB)로 나누어 교대 실행하는 전략을 적용한다. Ollama로 7B 이상의 모델은 Kubernetes와 동시 실행이 불가능하므로, 3B 이하 모델 또는 클라우드 API 모델을 사용하도록 권장된다.
8. 기능 구성
8.1 1인 연습 모드
루미큐브에 익숙하지 않은 플레이어를 위해 6단계의 연습 모드가 제공된다. Stage 1에서는 최초 등록(30점 이상 세트 배치) 연습을, Stage 2에서는 런 만들기를, Stage 3에서는 그룹 만들기를, Stage 4에서는 테이블 재배치를, Stage 5에서는 조커 활용을 단계별로 학습한다. Stage 6에서는 AI 1명과의 종합 실전 대전을 경험할 수 있다. 연습 모드는 로그인 없이도 플레이 가능하며, 턴 타임아웃이 없고 ELO 레이팅에 반영되지 않는다.
8.2 실시간 멀티플레이
WebSocket 기반으로 2~4인의 실시간 대전을 지원한다. Room을 생성하고 참가하는 방식이며, 인간 플레이어와 AI 플레이어를 자유롭게 조합할 수 있다. 연결 끊김 시 30초 이내에 재연결하면 게임 상태가 재동기화되고, 3턴 연속 부재 시 게임에서 제외된다. 남은 인원이 2명 미만이 되면 게임이 자동 취소된다.
8.3 ELO 랭킹 시스템
인간 플레이어와 AI 플레이어 모두에게 ELO 레이팅이 적용된다. 초기 레이팅은 1,000이며, K-factor 32를 기본으로 한다. 게임 결과에 따라 레이팅이 자동 업데이트되며, 전체/AI별/기간별 리더보드와 모델별 ELO 비교 차트가 제공된다.
8.4 관리자 대시보드
관리자 대시보드에서는 활성 게임 Room 목록 조회, 게임 강제 종료, 사용자 목록 및 차단 관리, AI 모델별 호출 통계(횟수, 응답시간, 토큰 사용량), 게임 결과 기록 및 AI 승률 통계를 확인할 수 있다. 향후에는 AI vs AI 토너먼트 실행 기능도 추가될 예정이다.
8.5 게임 복기
게임 종료 후 4분할 뷰로 모든 플레이어의 패를 공개하며 턴별로 복기할 수 있다. 자동 재생, 턴별 스텝 이동, 특정 턴 점프 기능을 지원하며, AI 플레이어의 경우 판단 근거 요약을 오버레이로 확인할 수 있다. 이 복기 기능은 LLM 전략을 분석하고 비교하는 데 있어 핵심적인 도구이다.
8.6 알림 시스템
카카오톡 메시지 API를 통해 게임 초대, 게임 결과, 시스템 이상(AI 장애 등), 빌드/배포 결과 등의 알림을 발송한다. 알림에는 우선순위가 부여되어, 일일 발송 한도에 근접하면 저우선 알림이 억제된다.
9. 프로젝트 일정과 진행 현황
9.1 전체 일정
프로젝트는 2026년 3월 8일에 시작하여 2026년 8월 15일 완료를 목표로 하며, 2주 단위의 스프린트로 운영된다. 전체 6개 Phase, 10개 Sprint(Sprint 0~9)로 구성된다.
Phase 1(Sprint 0, ~3월 28일)은 기획과 환경 구축 단계로, 기획/설계 문서 작성과 Kubernetes, ArgoCD, SonarQube 등 인프라 환경을 구축한다. Phase 2(Sprint 1~3, ~5월 9일)에서는 Game Engine, 백엔드 API, 프론트엔드 기본 기능의 MVP를 개발한다. Phase 3(Sprint 4~5, ~6월 6일)에서는 4종의 AI Adapter를 연동하고 실시간 멀티플레이를 완성한다. Phase 4(Sprint 6, ~6월 20일)에서는 관리자 대시보드, ELO 랭킹, 카카오톡 알림, 게임 복기 등 플랫폼 기능을 확장한다. Phase 5(Sprint 7~9, ~8월 1일)에서는 Observability, 보안 고도화, Istio Service Mesh 등 DevSecOps를 고도화한다. Phase 6(~8월 15일)에서는 AI 토너먼트를 실행하고 모델별 전략 비교 분석 리포트를 산출한다.
9.2 현재 진행 현황
2026년 3월 11일 현재, Phase 1이 진행 중이다. 기획 문서 5개(프로젝트 헌장, 요구사항 정의서, 리스크 관리 계획, 도구체인, WBS)와 설계 문서 6개(시스템 아키텍처, DB 설계, API 설계, AI Adapter 설계, 게임 세션 관리, 게임 규칙 설계)가 완료되었다. 백엔드 기술 결정(Go + NestJS 폴리글랏 구성)이 확정되었고, PostgreSQL 컨테이너와 WSL2 환경 최적화가 완료되었으며, GitHub 저장소에 코드가 Push되었다.
기획/설계 문서에 대한 종합 검토를 통해 17개의 이슈가 식별되고 해소되었으며, 전체 문서의 도식이 Mermaid로 표준화되었다. HTML 시뮬레이션 3종(관전 뷰, 4분할 뷰, 1인칭 뷰)도 프로토타입으로 제작되었다.
다음 단계로는 UI 와이어프레임 작성, GitHub Projects 보드 구성, Docker Desktop Kubernetes 활성화, ArgoCD 설치, GitLab Runner 등록 등이 예정되어 있다.
10. 리스크 관리
프로젝트에서 식별된 주요 리스크는 크게 기술, 환경, 외부 API, 비용, 일정의 5가지 범주로 분류된다.
기술 리스크 중 가장 심각한 것은 LLM 응답 지연/타임아웃(TR-01)과 Docker Desktop Kubernetes 리소스 부족(TR-05)이다. LLM 응답 지연에 대해서는 10초 타임아웃과 3회 재요청, 강제 드로우 fallback이 설계되어 있으며, 리소스 부족에 대해서는 앞서 언급한 교대 실행 전략이 적용된다.
환경 리스크로는 WSL2 네트워킹 불안정(ER-01)과 Hyper-V 메모리 과점유(ER-03)가 있다. .wslconfig 파일로 메모리 상한을 10GB로 제한하고, 프로젝트별 프로파일을 전환하는 스크립트로 관리한다.
비용 리스크로는 LLM API 비용 폭증(CR-01)이 있으며, Quota 시스템과 일일 비용 한도로 통제한다.
일정 리스크로는 1인 개발로 인한 병목(SR-01)이 가장 크며, Agile 스프린트 기반의 우선순위 관리와 MVP 우선 전략으로 대응한다.
11. 기술 스택 요약
RummiArena에서 사용되는 전체 기술 스택을 영역별로 정리하면 다음과 같다.
프론트엔드 영역에서는 Next.js를 기반으로 TailwindCSS, Framer Motion, dnd-kit을 사용한다. 백엔드의 Game Server는 Go 언어 기반으로 gin(HTTP 프레임워크), gorilla/websocket(WebSocket), GORM(ORM), go-redis(Redis 클라이언트), golang-jwt(JWT), zap(구조화 로그), viper(설정 관리)를 활용한다. AI Adapter는 NestJS(TypeScript) 기반으로 axios(HTTP 클라이언트), class-validator(DTO 검증), jest(테스트)를 사용한다.
데이터베이스는 PostgreSQL 16과 Redis 7을 사용하며, AI 모델로는 OpenAI API, Claude API, DeepSeek API, Ollama(LLaMA)를 지원한다. 인프라는 Docker Desktop Kubernetes, Helm 3, ArgoCD로 구성되고, CI는 GitLab CI + GitLab Runner, 코드 품질은 SonarQube, 보안은 Trivy와 OWASP ZAP으로 관리된다. 인증은 Google OAuth 2.0, 알림은 카카오톡 API를 사용하며, Phase 5에서 Istio Service Mesh가 추가될 예정이다.
12. 성공 기준
프로젝트의 성공은 기능 기준과 품질/인프라 기준으로 나뉘어 평가된다.
기능 면에서는 Human + AI 혼합 게임의 완주율 95% 이상, 최소 3개 이상 LLM 모델의 동시 참가, AI vs AI 대전 100판 이상 완료, 1인 연습 모드 Stage 1~6 전체 플레이 가능, 6캐릭터 × 3난이도 조합 전체 동작 확인이 목표이다.
품질/인프라 면에서는 CI 파이프라인 소요 시간 평균 5분 이내, ArgoCD Sync 성공률 99% 이상, SonarQube Quality Gate 통과(Coverage 60% 이상, Bug 0), Trivy Critical/High 취약점 0건, Pod 재시작 시 게임 복구 30초 이내, AI 턴 응답 시간 10초 이내(95 percentile), 모델별 승률/전략 분석 리포트 산출이 목표이다.
13. 맺음말
RummiArena는 겉으로 보면 보드게임 웹 애플리케이션이지만, 그 안에는 멀티 LLM 전략 실험, 폴리글랏 마이크로서비스 아키텍처, 풀스택 DevSecOps 파이프라인, 그리고 Kubernetes 기반 클라우드 네이티브 인프라라는 다층적 기술 과제가 담겨 있다. 1인 개발이라는 제약 속에서도 SaaS 수준의 설계를 추구하며, 제한된 하드웨어 자원을 교대 실행 전략으로 극복하고, AI의 불확실한 응답을 LLM 신뢰 금지 원칙으로 통제하는 이 프로젝트는 현대적 소프트웨어 엔지니어링의 다양한 측면을 하나의 플랫폼에 녹여낸 의욕적인 실험이라 할 수 있다.
작성일: 2026-03-11