게임 백엔드와 라이브 서비스
게임 밖에서 플레이를 받쳐 주는 서비스들이다. 계정, 매치메이킹, 로비와 친구, 순위표, 인벤토리와 재화, 상점이 여기에 든다.
목차 (10)
게임 밖의 서버들
경기를 돌리는 전용 서버(멀티플레이어 서버 설계 노트)는 게임 서비스의 일부일 뿐이다. 로그인하고, 친구를 초대해 파티를 짜고, 실력이 비슷한 상대를 찾고, 경기가 끝나면 순위와 보상을 받고, 상점에서 스킨을 사는 일은 모두 경기 밖의 서비스가 맡는다. 이것을 묶어 게임 백엔드라고 부른다. 구조로 보면 평범한 웹 서비스(설계 부품 노트의 API 서버, 캐시, 큐, DB)와 같지만, 게임이라 생기는 특이점이 있다.
- 몰림이 극단적이다: 출시일, 시즌 시작, 대형 업데이트 직후에 평소의 몇십 배가 한꺼번에 로그인한다. 로그인 대기열(입장 순번을 주고 차례로 들이기)을 두고, 로그인 직후 부르는 API 수를 줄이는 것이 기본이다. 몰림을 버티는 일반 기법은 규모 확장 노트에 있다.
- 클라이언트를 믿지 않는다: 게임 클라이언트는 사용자의 기기에서 돌기 때문에 언제든 조작된다. 재화·아이템·순위처럼 값어치가 있는 것은 모두 서버가 정하고, 클라이언트는 요청만 한다.
- 경기 서버와 백엔드는 따로 늘어난다: 경기 서버는 지역마다 흩어져 동시 경기 수에 따라 늘고, 백엔드는 한두 곳에서 요청 수에 따라 는다. 둘 사이 호출은 경기 시작(참가자 확인)과 끝(결과 보고)에 몰아서 한다.
계정과 플랫폼 로그인
PC·콘솔 게임은 대개 자체 아이디·비밀번호 대신 플랫폼 계정(Steam, PlayStation Network, Xbox, Epic)으로 로그인한다. 플레이어는 이미 로그인해 있고, 게임은 그 플랫폼이 "이 사람이 맞다"고 보증한 증표를 백엔드에 내기만 하면 된다. Steamworks의 사용자 인증과 소유권 문서는 클라이언트가 세션 티켓을 받아 서버에 넘기고, 서버가 그 티켓을 확인하는 흐름을 설명한다. 백엔드가 웹 서버라면 ISteamUserAuth Web API의 AuthenticateUserTicket으로 확인한다.
클라이언트가 Steam 클라이언트에게 웹 API용 인증 티켓을 달라고 한다. 이 티켓을 누구에게 낼지(우리 백엔드의 이름)를 함께 적는다.
- 플랫폼 id를 내 계정에 잇는다: 백엔드는 자기 계정 id를 만들고, SteamID·PSN 계정 id·Xbox 계정 id를 거기에 연결해 둔다. 이렇게 해야 한 사람이 PC와 콘솔에서 같은 진행을 이어 가는 크로스 프로그레션이 된다. 연결을 바꾸거나 끊는 일은 계정 탈취의 통로가 되니 재인증을 요구한다.
- 게스트 계정: 모바일은 기기에서 바로 시작하는 익명 계정을 흔히 쓰고, 나중에 플랫폼 계정에 연결하게 한다. 기기를 잃으면 진행도 잃으니 연결을 유도한다.
- 세션 토큰: 확인이 끝나면 백엔드는 자기 토큰(서명된 짧은 수명 토큰과 갱신 토큰)을 준다. 매 요청마다 플랫폼에 다시 묻지 않는다. 토큰과 서명 키 관리는 보안 노트의 인증 절과 같다.
- 제재: 치트나 결제 사기로 막은 계정은 백엔드가 로그인 단계에서 거른다. 플랫폼 id 단위로 막아야 새 게스트 계정으로 돌아오는 것을 줄인다.
실력 점수: Elo, Glicko-2, TrueSkill
매치메이킹의 재료는 "이 사람이 얼마나 잘하나"를 나타내는 숫자다. 가장 오래된 방식은 체스의 Elo다. 두 사람의 점수 차로 기대 승률을 계산하고, 결과가 기대와 다른 만큼 점수를 옮긴다. 점수 차가 400점이면 기대 승률이 10배(약 91% 대 9%)가 되도록 정해져 있다. 100점 높은 사람의 기대 승률은 약 64%라서, K가 32일 때 그가 이기면 12점만 얻지만 낮은 쪽이 이기면 20점을 얻는다. 두 사람이 주고받는 점수의 합은 늘 0이다.
- Glicko-2: Elo는 점수가 얼마나 확실한지를 모른다. 처음 온 사람의 1500과 천 판을 한 사람의 1500을 똑같이 다룬다. Mark Glickman의 Glicko-2 설명 문서는 점수에 불확실성(RD)과 변동성을 함께 둔다. 판수가 적거나 오래 쉬었던 사람은 RD가 커서 점수가 크게 움직이고, 많이 할수록 RD가 줄어 안정된다.
- TrueSkill: Microsoft Research가 Xbox Live를 위해 만든 방식이다(TrueSkill 프로젝트 페이지). 실력을 평균과 표준편차를 가진 정규분포로 보고, 2명보다 많은 팀 대 팀이나 여러 명이 순위를 다투는 경기에서 결과를 개인 점수로 나눠 갱신한다. 이후 나온 TrueSkill 2는 킬 수, 탈주, 파티 여부 같은 정보도 쓴다.
- 보이는 등급과 숨은 점수: 많은 게임이 매칭에 쓰는 숨은 점수(MMR)와 화면에 보이는 등급(브론즈~마스터)을 따로 둔다. 등급은 동기 부여를 위해 시즌마다 초기화하거나 지는 판에 덜 깎이게 만들 수 있지만, 매칭은 숨은 점수로 정확하게 한다.
- 새로 온 사람과 부계정: 첫 몇 판(배치 경기)은 불확실성을 크게 두어 빨리 제자리를 찾게 한다. 잘하는 사람이 새 계정으로 초보를 상대하는 문제(smurf)는 첫 경기들의 성적으로 점수를 빠르게 올리는 식으로 줄인다.
매치메이킹 대기열: 품질과 대기 맞바꾸기
매치메이커는 대기열에 들어온 표(ticket: 사람 또는 파티, 점수, 지역별 핑, 고른 모드)를 모아 조건에 맞는 묶음을 만든다. 조건을 빡빡하게 잡으면 경기 품질은 좋지만 사람이 적은 시간·높은 등급에서는 끝없이 기다린다. 그래서 거의 모든 매치메이커가 기다린 시간에 따라 조건을 넓힌다. AWS의 FlexMatch 규칙 넓히기 문서도 "점수 차 5 이내"를 15초 뒤 10, 더 지나 20으로 늘리는 예를 든다.
처음에는 점수가 ±50 이내인 사람만 찾는다. 창 ±50 안에 1명이라 아직 모자란다.
- 넓히는 축: 점수 창만이 아니라 핑 한도, 팀 인원 균형, 파티 크기 맞추기도 시간에 따라 푼다. 무엇을 먼저 푸는지가 게임의 성격을 정한다. 경쟁전은 점수를 늦게, 일반전은 빨리 푼다.
- 파티: 친구끼리 들어온 파티는 한 표로 다룬다. 파티의 점수는 평균보다 높은 쪽으로 잡는 경우가 많다(같이 하는 사람들은 소통이 좋아 더 강하다). 혼자 온 사람들만의 팀이 5인 파티를 만나지 않게 따로 다루기도 한다.
- 모으는 주기: 표가 올 때마다 바로 짝을 찾으면 먼저 온 사람이 나중에 올 더 좋은 상대를 놓친다. 몇 초마다 대기열 전체를 보고 한꺼번에 묶으면 품질이 오르지만 그만큼 기다린다.
- 되채우기(backfill): 경기 중에 누가 나가면 매치메이커가 그 자리에 맞는 사람을 넣는다. 대기열의 표와 진행 중인 경기의 빈자리를 같은 규칙으로 다룬다.
- 경기를 만든 뒤: 묶음이 정해지면 매치메이커가 핑 정보로 지역을 고르고 서버를 할당받아(서버 설계 노트의 할당) 모두에게 주소와 접속 토큰을 보낸다. 누군가 수락하지 않으면 나머지는 대기열 앞쪽으로 돌려보낸다.
로비, 파티, 프레즌스, 친구와 채팅
경기 전에 모이는 곳이 로비와 파티다. 로비는 방장, 참가자 목록, 준비 상태, 고른 맵 같은 작은 공유 상태이고, 참가자 모두에게 바뀐 내용을 실시간으로 밀어 줘야 한다. 그래서 백엔드는 클라이언트와 WebSocket 같은 오래 유지되는 연결을 두고, 그 연결을 잡고 있는 연결 서버(gateway)들 사이를 발행·구독(pub/sub)으로 잇는다. 실시간 연결을 수백만 개 유지하는 방법은 실시간과 위치 사례 노트의 채팅 설계와 같다.
- 프레즌스(presence): 친구 목록의 "온라인 · 경기 중 · 로비에서 대기" 표시다. 상태가 자주 바뀌고 친구가 많으면 알릴 곳도 많아, 온라인인 친구에게만 밀고 나머지는 읽을 때 가져간다. 상태에 만료 시간(TTL)을 붙이면 클라이언트가 강제 종료돼도 저절로 오프라인이 된다.
- 친구: 플랫폼 친구(Steam 친구, PSN 친구)를 가져와 쓰고, 크로스플레이 게임은 플랫폼을 넘는 자체 친구 목록을 따로 둔다. 차단 목록은 매치메이킹과 채팅 양쪽에서 존중해야 한다.
- 채팅: 파티·로비·길드 채널로 나누고, 메시지는 순서와 기록이 필요한 만큼만 저장한다. 욕설 필터와 신고는 출시 전에 있어야 하고, 콘솔 플랫폼은 차단·신고 기능과 부모 통제를 요구한다. 음성 채팅은 대개 전문 서비스(Vivox, EOS 음성 등)를 쓴다.
- 초대: 친구에게 초대를 보내면 플랫폼의 초대 기능(오버레이의 "참가")과 백엔드의 파티가 함께 움직여야 한다. 플랫폼마다 초대를 받는 경로가 달라 크로스플레이 게임에서 손이 많이 가는 부분이다.
순위표: 정렬 집합 하나면 된다
순위표에 필요한 질문은 셋이다: 점수를 넣는다, 내 순위는 몇 위인가, 상위 몇 명과 내 위아래 몇 명은 누구인가. 관계형 DB로 "나보다 점수가 높은 사람 수"를 세면 사람이 많을수록 느려진다. Redis의 정렬 집합(sorted set) 문서는 이 셋을 모두 로그 시간에 하는 자료구조를 설명하고, 예로 바로 게임 순위표를 든다. Redis가 메모리 안에서 자료구조를 다루는 방식은 키-값 노트에 있다.
- 시즌과 기간: 시즌마다, 주마다 키를 따로 만든다(lb:s12, lb:week:41). 기간이 끝나면 키를 닫아 보상을 정산하고 DB에 영구 기록한 뒤 만료시킨다.
- 같은 점수: 동점이면 먼저 도달한 사람을 위로 두고 싶을 때가 많다. 점수에 시각을 섞은 값(점수 × 큰 수 + (최대 시각 − 도달 시각))을 점수로 쓰는 식으로 해결한다.
- 친구 순위: 전체 순위표에서 친구만 골라 점수를 가져와 정렬한다. 친구가 수백 명이면 충분히 빠르다.
- 원본은 따로: Redis는 순위를 빨리 읽는 사본이고, 점수의 원본(경기 결과)은 DB에 둔다. Redis가 날아가도 다시 채울 수 있게 해 둔다. 경기 서버가 보고한 결과만 점수에 반영하고, 클라이언트가 보낸 점수는 받지 않는다.
- 관리형: 직접 만들지 않아도 된다. Steamworks의 순위표 기능처럼 플랫폼과 백엔드 서비스 대부분이 순위표를 준다. 다만 점수를 클라이언트가 직접 올리는 방식이면 조작을 막기 어렵다.
인벤토리와 재화: 원장과 멱등 키
게임 속 재화(골드, 젬)와 아이템은 현금으로 산 것이 섞여 있어 사실상 돈이다. 잘못 늘어나면(복제 버그) 경제가 무너지고, 잘못 사라지면 환불과 민원이 온다. 그래서 설계는 정확성이 중요한 시스템 노트의 결제·원장 설계를 그대로 따른다.
- 서버만 바꾼다: 클라이언트는 "이 상자를 열겠다", "이 퀘스트를 끝냈다"고 요청만 한다. 상자에서 무엇이 나오는지(확률 뽑기)도 서버가 정한다. 확률형 아이템은 여러 나라에서 확률 공개 의무가 있어, 서버의 확률표가 공개한 값과 같은지 검증할 수 있게 둔다.
- 원장(ledger): 잔액을 덮어쓰지 않고 "+50 퀘스트 보상", "−300 스킨 구매"를 줄로 덧붙인다. 잔액은 합계이고, 빠르게 읽으려고 따로 들고 있더라도 원장에서 언제든 다시 계산할 수 있어야 한다. 무엇이 언제 왜 바뀌었는지가 남아 고객 문의와 버그 추적이 된다.
- 멱등 키: 퀘스트 보상 요청이 타임아웃으로 재시도되면 두 번 지급될 수 있다. 요청마다 고유한 키를 달고 DB에 키 유일 제약을 걸어, 같은 키는 한 번만 기록하고 두 번째에는 처음 결과를 그대로 돌려준다.
- 거래와 교환: 두 플레이어가 아이템을 주고받는 거래는 양쪽 변경이 한 트랜잭션이어야 한다. 한쪽만 반영되면 복제가 된다. 경매장처럼 거래가 많으면 별도 서비스로 떼고 같은 원장 원칙을 지킨다.
상점과 결제: 영수증은 서버가 확인한다
게임 안에서 현금으로 사는 것(인앱 구매)은 플랫폼 스토어의 결제를 거쳐야 한다. 모바일은 App Store와 Google Play, PC는 Steam·Epic, 콘솔은 각 스토어다. 결제가 끝나면 스토어는 서명된 거래 정보(영수증)를 클라이언트에 준다. 이것을 클라이언트에서 확인하고 아이템을 주면, 조작된 클라이언트가 가짜 영수증으로 공짜 아이템을 받는다. 반드시 백엔드가 스토어에 직접 묻는다.
플레이어가 게임 안 상점에서 젬 묶음을 고르고, 결제는 플랫폼 스토어(App Store, Google Play, Steam 등)의 화면에서 한다.
- Apple: 예전의 verifyReceipt 엔드포인트는 폐기 예정(deprecated) 상태이고, 지금은 App Store Server API로 거래 정보를 조회하며 환불·구독 변경은 App Store Server Notifications로 받는다.
- Google Play: 백엔드가 Google Play Developer API의 purchases.products.get으로 구매 토큰을 확인하고, 지급 뒤 확인(acknowledge) 처리를 한다. 사흘 안에 확인하지 않으면 구매가 자동 환불된다.
- Steam: 흐름이 조금 다르다. Steam 마이크로트랜잭션 문서처럼 백엔드가 Web API로 주문을 먼저 만들고(InitTxn), 사용자가 Steam 오버레이에서 승인하면 백엔드가 확정(FinalizeTxn)한 뒤 지급한다. 처음부터 서버가 주도한다.
- 환불과 차지백: 스토어가 환불을 알려 오면 지급한 재화를 회수하거나, 이미 썼으면 잔액을 음수로 두고 다음 충전에서 메우는 식의 정책이 필요하다. 환불 후 재화를 써 버리는 악용을 막으려면 알림을 반드시 받는다.
- 가격과 지역: 스토어마다 지역 가격표, 세금, 수수료가 다르다. 게임 안 상점에 표시하는 가격은 스토어가 돌려준 현지 가격을 그대로 쓴다.
라이브 이벤트와 텔레메트리
라이브 서비스 게임은 출시 뒤에 운영으로 산다. 주말 경험치 두 배, 한정 모드, 시즌 패스, 기념 이벤트를 클라이언트 업데이트 없이 켜고 끄려면 일정과 수치를 서버 설정으로 빼 둬야 한다. 그리고 무엇을 바꿀지는 숫자를 보고 정한다. 그 숫자를 모으는 것이 텔레메트리다.
- 이벤트 설계: "경기 시작", "상점 열기", "구매", "튜토리얼 3단계 통과"처럼 이름과 필드를 정한 이벤트를 보낸다. 스키마에 버전을 달고, 클라이언트 버전·플랫폼·지역을 공통 필드로 넣는다. 나중에 분석할 수 없는 이벤트는 처음부터 잘못 설계된 것이다.
- 수집: 클라이언트는 이벤트를 모아 묶음으로 보내고, 끊기면 기기에 쌓았다가 다시 보낸다. 같은 이벤트가 두 번 올 수 있으니 이벤트 id로 중복을 없앤다. 뒤의 스트림·배치 처리는 데이터 파이프라인 사례 노트와 같다.
- 보는 숫자: 동시 접속자(CCU), 일·월 활성 사용자(DAU·MAU), 재방문율(1일·7일·30일 리텐션), 유료 전환율, 사용자당 매출(ARPDAU), 매칭 대기 시간, 경기 서버 크래시율. 출시·패치 직후에는 실시간 갈래로 몇 분 단위로 본다.
- 라이브 설정: 이벤트 일정, 드롭률, 가격, A/B 그룹 배정을 서버 설정으로 내려보낸다. 설정 변경도 배포처럼 단계적으로 하고, 되돌릴 수 있게 버전을 남긴다(배포와 서빙 노트의 라이브 옵스 절).
- 개인 정보: 텔레메트리에는 개인을 식별할 수 있는 값이 섞이기 쉽다. 필요한 것만 모으고, 플랫폼 정책과 GDPR 같은 법의 삭제 요청에 응할 수 있게 사용자 id로 지울 수 있게 둔다.
백엔드 서비스 지형 (2026년)
위의 것을 다 직접 만들 필요는 없다. 플랫폼이 주는 것, 클라우드 회사가 파는 것, 오픈 소스가 있다. 고를 때는 기능 목록보다 "크로스플레이를 하나", "서버 호스팅까지 맡길 건가", "업체가 사라지면 어떻게 되나"를 먼저 묻는다.
- Steamworks: Steam에 게임을 내면 쓸 수 있는 Valve의 SDK와 Web API다. 인증, 로비 검색 기반의 기본 매치메이킹, 친구·초대, 순위표, 업적, 클라우드 저장, 인벤토리, 마이크로트랜잭션, Steam Datagram Relay를 준다. Steam 사용자에게만 해당한다.
- Epic Online Services(EOS): Epic이 무료로 제공하는 크로스플랫폼 서비스다(EOS 개발자 문서). 어느 스토어에 낸 게임이든 쓸 수 있고, 계정 연결, 로비·세션, 친구, 순위표·통계, 음성 채팅, Easy Anti-Cheat를 준다. 전용 서버 호스팅은 없다.
- PlayFab: Microsoft가 Azure 위에서 운영하는 라이브 게임 백엔드다(PlayFab 문서). 계정, 매치메이킹, 로비, 순위표, 경제(재화·카탈로그), 라이브 설정과 분석, 전용 서버 호스팅(Multiplayer Servers)까지 한 묶음이다. 2026년에는 일부 분석 API를 정리하는 등 구성이 바뀌고 있어 쓰려는 기능의 현재 상태를 확인해야 한다.
- Amazon GameLift Servers: AWS의 전용 서버 호스팅과 FlexMatch 매치메이킹이다(FlexMatch 소개). 계정·순위표 같은 나머지는 다른 AWS 서비스나 다른 백엔드와 묶는다. 2025년에 Amazon GameLift에서 이름이 바뀌었고, 같은 때 클라우드 스트리밍용 GameLift Streams가 따로 나왔다.
- Unity Gaming Services(UGS): Unity의 서비스 묶음이다(Unity 서비스 문서). 인증, Lobby, Friends, Leaderboards, Economy, Matchmaker, Relay, Cloud Save, Remote Config, Analytics가 있고 Unity가 아닌 엔진에서도 쓸 수 있다. 전용 서버 호스팅(Multiplay)은 2026년 3월 31일로 Unity의 직접 지원이 끝나 Rocket Science Group 쪽으로 넘어갔다.
- Nakama: Heroic Labs가 만든 Go 언어 오픈 소스 게임 서버다(GitHub 저장소, Apache 2.0). 계정, 친구·그룹·채팅, 매치메이커, 순위표, 지갑과 인앱 구매 검증, 서버 권한 실시간 경기 처리기를 한 서버에 담고 PostgreSQL 호환 DB(CockroachDB 포함)를 쓴다. 직접 운영할 수 있어 업체가 사라질 위험이 적고, 회사가 관리형 호스팅도 판다.
흔한 조합은 "플랫폼 SDK(인증·친구·초대) + 크로스플랫폼 백엔드 하나(계정 연결·재화·순위표) + 서버 호스팅 하나"다. 2026년에 Unity Multiplay와 Hathora가 잇달아 손을 뗀 것처럼 업체는 바뀐다. 백엔드 호출을 게임 코드 곳곳에 흩지 말고 얇은 어댑터 뒤에 모아 두면 옮기는 비용이 준다.
- Steamworks Documentation — Valve
- User Authentication and Ownership — Steamworks Documentation
- ISteamUserAuth Interface — Steamworks Documentation
- Example of the Glicko-2 system — Mark Glickman
- TrueSkill Ranking System — Microsoft Research
- Allow requirements to relax over time — Amazon GameLift Servers FlexMatch
- What is Amazon GameLift Servers FlexMatch? — AWS
- Redis sorted sets — Redis Docs
- Leaderboards — Steamworks Documentation
- App Store Server API — Apple Developer
- purchases.products.get — Google Play Developer API
- Microtransactions Implementation Guide — Steamworks Documentation
- Epic Online Services Documentation — Epic Games
- PlayFab Documentation — Microsoft
- Unity Services Documentation — Unity
- Nakama — Heroic Labs (GitHub)