← back to services

live · service

듀오아레나

둘이서 짧게 즐기는 실시간 2인 미니게임 모음. 12종의 게임을 한 앱에서, 친구와 코드 한 줄로 매칭. 랭크전과 캐주얼, 친구 초대 모드까지 — 한 판 길이는 짧지만 결과는 분명한 게임을 모아두었습니다.

Flutter Node.js TypeScript Socket.IO PostgreSQL Express AdMob

서비스 소개

듀오아레나는 "지금 옆에 있는 친구와 한 판" 같은 가벼운 게임을 모은 1대1 멀티플레이 앱입니다. 한 판이 1~2분 안에 끝나야 한다는 제약을 두고, 그 안에서 결과가 명확하게 나오는 게임만 추렸습니다.

Flutter 한 코드베이스로 iOS · Android 동시 빌드, 서버는 Node.js + TypeScript + Socket.IO 위에서 실시간 매치를 굴립니다. 출시 후로는 한 릴리즈마다 게임을 한두 개씩 더해왔고, 지금은 12종이 한 앱 안에 들어있습니다.

Architecture

클라이언트는 Socket.IO 클라이언트로 서버에 직접 연결, 서버는 매치메이킹과 게임 상태를 메모리에서 관리하고 결과만 PostgreSQL 에 저장합니다.

/ client iOS app Flutter · Provider Android app Flutter · Provider socket.io · wss://duo.jiny.shop / edge Nginx · reverse proxy TLS · WS upgrade / app Express + Socket.IO 게임 서버 매치메이킹 · 게임 상태 (in-memory) · JWT 인증 / data & ext PostgreSQL 전적 · 랭킹 · 사용자 · 코인샵 한국어 사전 API 네이버 국어사전 (훈민정음 게임) single VPS · Docker

Behind the scenes

12종의 게임을 한 사람이 굴리면서 가장 오래 붙들고 있던 두 가지 이야기.

  1. 01

    사전 API 와의 술래잡기

    훈민정음 게임은 사용자가 입력한 단어가 실제 한국어인지 검증해야 합니다. 처음엔 한국어기초사전(krdict)을 썼는데 User-Agent 가 까다롭게 굴면서 요청이 막히기 시작했습니다. 브라우저 헤더 통째로 흉내 내봤지만 곧 다시 막히고, 우리말샘(opendict)으로 옮겼다가 거기서도 안정성에 의문이 생겨 결국 네이버 국어사전으로 정착했습니다. 외부 API 에 게임 핵심 로직을 의존할 때 — 한 줄 짜리 호출도 운영 단계에서는 결코 한 줄이 아니라는 걸 배웠습니다.

  2. 02

    친구 초대는 한 번에 만들 수 없다

    "친구창에서 친구를 눌러 게임으로" 같은 단순한 흐름이, 막상 실시간 멀티플레이 위에 얹히니 끝없이 엣지 케이스가 튀어나왔습니다 — 중복 초대, match_found 이벤트 두 번 처리, 초대 후 stale 상태로 새 게임 진입, 네트워크 끊김 직후 잘못된 룸으로 진입, invitor 쪽만 게임 화면으로 못 넘어가는 문제 등. v1.0.0 이후 한 달에 가까운 버그 수정의 절반이 이 영역이었고, 결국 SocketService 가 다중 리스너를 안전하게 관리하도록 다시 짜고서야 잠잠해졌습니다.

Screenshots

카드를 누르면 큰 이미지로 볼 수 있습니다.

More

지나온 버전과 앞으로 들어갈 항목을 별도 페이지에서 확인할 수 있습니다.