Case Study · Webview Game

게임형 리워드 '펭귄 구하기'

앱 웹뷰에서 동작하는 광고 기반 출석·보상 게임입니다.
프론트엔드 구현을 전담해 개발 3일 + QA 2일, 5일 만에 출시했습니다.

5일개발 3일 + QA 2일, FE 전담git 히스토리 기준
62,000+명출시 3주 누적 사용자Amplitude 실측
590,000+건게임 보상 수령 (3주)Amplitude 실측
4,300 → 0일별 익명 적재 기기1년 묵은 문제 종결
01 · Playable Demo

실제 게임과 같은 규칙으로 플레이해보세요

아래 보드는 실제 게임과 같은 슬라이딩 규칙으로 동작합니다.
펭귄은 민 방향으로 벽에 부딪힐 때까지 미끄러지고, 중간에 멈출 수 없습니다.

Stage
이동 0/4 ⏱ 0s ★★★
아기 펭귄에게 도착하면 클리어
최적 이동수 안에 도착해야 합니다.
초과하면 즉시 실패 (실제 정책)
키보드 방향키·화면 버튼·스와이프로 조작합니다. 벽에 붙어 못 미는 입력은 이동수를 차감하지 않고, 제한 시간이 지나면 시간 초과로 실패합니다.
플레이 중 다른 탭에 다녀와보세요. 타이머가 멈췄다 이어집니다.
02 · Architecture

역할을 세 층으로 나눠 따로 만들고 조립했습니다

펭귄을 한 번 미는 흐름을 기준으로 역할을 나눴습니다. 층끼리 서로를 모르게 해서, 각각 따로 만들고 마지막에 조립할 수 있었습니다.

물리 함수벽에 부딪히기 직전 칸만 계산하는 순수 함수. React도 게임 규칙도 모릅니다. 위 데모도 같은 함수로 동작합니다
export const slideFrom = (pos: Position, dir: Direction, board: CollisionBoard): Position => {
  let current = pos
  while (true) {
    const next = step(current, dir)
    if (isBlocked(next, board)) return current  // 벽이나 경계 직전 칸에서 멈춘다
    current = next
  }
}
게임 상태미끄러지는 동안 입력을 막고, 도착하면 판정해서 결과만 넘깁니다
ready→playing→ cleared failed · overstep failed · timeout
서버 상태출석, 보상, 스테이지(React Query). 넘겨받은 결과를 서버에 제출합니다
03 · Troubleshooting

타이머는 플레이한 시간만 세도록 했습니다

처음엔 setInterval이 실행될 때마다 0.25초씩 더했는데, 웹뷰가 백그라운드로 가면 실행이 늦춰지거나 멈춰서 시간이 덜 흘렀습니다. 그래서 실행 횟수 대신 시작 시각과의 차이로 계산하도록 바꿨습니다.

백그라운드 정지화면이 숨겨지면 멈추고, 돌아오면 그만큼 시작 시각을 미뤄 플레이한 시간만 셉니다
판정 유예제한 시간 직전에 민 슬라이드는 끝날 때까지 시간 초과 판정을 미뤄서, 성공과 시간 초과가 동시에 나지 않습니다
04 · Observability

1년 넘게 이어지던 익명 User ID 적재를 0으로

하루 수천 대의 기기에서 User ID 없이 이벤트가 쌓이는 문제가, 1년 넘게 이어지고 있었습니다.

1

측정 — 고치기 전에 먼저 쟀습니다

문제 브릿지가 응답하지 않으면 에러도 나지 않아 에러 캡처 코드가 실행되지 않았고, 그래서 월 18건으로 실제보다 훨씬 적게 집계되고 있었습니다.

해결 5초 타임아웃으로 '응답 없음'을 실패로 바꿔 셀 수 있게 하고, 원인별로 태깅했습니다
(timeout · missing_user_id · bridge_error. 자체 호스팅 Sentry 부하는 10% 샘플링 후 집계 때 10배 역산)

2

원인 — 대부분은 SDK 초기화 타이밍 문제

재보니 처음 원인으로 의심한 앱-웹 브릿지 무응답은 일 ~350대로 일부였습니다.
대부분은 SDK가 초기화되기 전에 넣은 User ID(setUserId)가 내부 큐에서 사라지는 경우였고, 이 경로만 일 ~4,300대였습니다.

3

해결 — 이벤트를 보내는 시점을 웹에서 직접 정함

인증 게이트 — 앱에서 User ID를 받을 때까지 하위 화면을 렌더하지 않아서, User ID 없이 이벤트가 나갈 수 없습니다.

자체 버퍼링 — SDK 초기화는 렌더와 별개로 진행되고, 그사이 발생한 이벤트는 웹 버퍼에 모아뒀다가 초기화가 끝나고 User ID를 다시 넣은 뒤에 내보냅니다.

일별 익명 적재 기기 — 인증 게이트 + 버퍼링 완전 적용 첫날 4,000+ → 0 (커밋 기록 기준)

05 · Usage

출시 후 3주, 사용 규모가 유지되고 있습니다

주간 게임 보상 수령 건수입니다. 첫 주 이후에도 줄지 않아,
일회성 이벤트가 아니라 매일 돌아오는 사용 패턴으로 자리 잡았습니다.

1주차
170,000건
2주차
210,000건
3주차
220,000건

주간 보상 수령 이벤트 (Amplitude 실측) · 누적 사용자 62,000+명 · 누적 수령 590,000+건