콘텐츠로 이동

PixiJS 웹 게임 에러 수집과 AI 진단·티켓 자동화 도구 만들기

모바일 앱에는 Firebase Crashlytics가, PC·콘솔에는 사내 크래시 수집 도구가 있었지만 PixiJS 웹 게임(TypeScript, Vite, H5 프레임워크)에는 에러 리포팅 도구가 없었다. 에러 하나를 처리하는 흐름은 전부 사람 손을 거쳤다.

  1. 인지: 유저 CS 인입
  2. 재현: 받은 정보로 재현 시도
  3. 정보 확보: 재현한 상태에서 브라우저 콘솔과 로그 수집
  4. 위치 파악: 압축된 스택트레이스로 원본 위치를 수동 추정
  5. 원인 분석: 관련 코드와 최근 커밋을 뒤져 원인 추정
  6. 공유: 팀 채팅에 공유
  7. 티켓화: Jira 티켓 수기 작성
  8. 해결: 담당자가 코드 수정·배포

이 흐름의 페인 포인트는 네 가지였다.

  • 인지 지연: 자동 수집·감지 체계가 없어 유저 제보에 의존한다. JS 에러는 네이티브 크래시와 달리 게임 화면을 멈추지 않기도 한다. 겉보기엔 정상인 채 일부 기능만 동작하지 않아 유저 이탈 지점이 된다.
  • 원인 파악 비용: 배포 코드가 minify되어 있어 콘솔에는 main-xxxx.js:1 같은 위치만 찍히고 변수·함수명도 mangle되어 있다. sourcemap 자동 복원이 없으면 pretty-print, 문자열 grep, 로컬 dev 빌드 재현으로 원본 위치를 추정해야 하고, 건마다 이 수작업을 반복한다.
  • 반복 수작업: 같거나 비슷한 유형의 에러(예: 특정 npm 패키지 이슈)를 매번 처음부터 분석하고, 티켓도 매번 손으로 쓴다.
  • 지식 쏠림: 해당 프로덕트를 만든 개발자가 아니면 원인 파악이 오래 걸려 특정 담당자에게 병목이 생긴다.

같은 게임을 여러 납품처에 공급하는 구조라, 출시한 프로젝트와 납품처가 늘수록 유지보수 비용도 함께 커진다.

Sentry에도 AI 원인 분석과 Jira 연동이 있지만, 쓰려면 원본 코드가 담긴 소스맵을 Sentry에 올려야 한다. 원본 코드를 회사 밖에 두지 않고 진단과 티켓까지 잇는 도구는 없었다.

8단계 중 1~7단계(인지부터 티켓화까지)를 자동화하고, 8단계(코드 수정·배포)는 개발자에게 남긴다. 웹 게임에서 난 런타임 에러를 자동으로 모아 원본 위치 복원, AI 진단, Google Chat 알림, Jira 티켓 생성까지 사람 손을 거치지 않고 처리한다.

  • Sentry는 수집기로 쓰고, 그 위에 복원된 원본 위치를 바탕으로 한 AI 원인 진단·처방과 티켓 자동화를 얹어 End-to-End로 잇는다.
  • 소스맵은 원본 코드를 담고 있으므로 Sentry나 CDN에 올리지 않고 회사 호스트에서 직접 복원한다.
  • 수용 조건은 다음과 같이 정했다.
    • 에러 위치가 원본 파일·라인으로 표시된다.
    • 개발자들이 일정 기간 모니터링하며 진단 리포트를 평가하고, 「도움됨」 비율이 목표치를 넘는다.
    • Chat·대시보드·Jira가 동작하고, 티켓이 중복되지 않는다.
    • 소스맵이 없거나 원인이 클라이언트 밖이면 「원인 불명」으로 표기한다.
    • 다른 팀의 요구(Jira 위치·담당자 지정)를 충족하고 다른 프로젝트에 이식할 수 있다.
  • 감지: Sentry가 모은 에러를 웹훅으로 받아 저장하고, 오래 걸리는 작업은 대기열에서 처리한다. breadcrumbs와 환경 정보(브라우저, OS, 릴리즈)를 함께 받아 재현 없이 맥락을 확보한다.
  • 위치 복원: 회사 호스트에만 둔 소스맵으로 압축된 위치를 원본 파일·라인으로 되돌린다. 복원된 파일·라인에는 Git 저장소의 blame 링크를 붙여 변경 이력을 바로 볼 수 있게 한다.
  • AI 진단: 원본 코드, 에러 직전의 사용자 행동, 환경, 실패한 요청을 모아 사내 AI 게이트웨이로 진단한다.
  • 알림·티켓: Chat과 Jira에 「분석 대기」를 먼저 보내고, 진단이 끝나면 갱신한다. 이슈 하나에 티켓은 한 장이며, 재발은 코멘트로 남긴다.
  • 대시보드: 여러 게임의 이슈를 한 화면에서 보고, 개발자가 진단을 「도움됨 / 보통 / 틀림」으로 평가한다. 이슈마다 원인 유형, 확인 상태, 담당자, Jira 티켓이 보인다.
  • 이식: 게임 저장소에서 설치 스킬로 설정하고, 배포 후 검증 스킬로 확인한다.

프로젝트 설정에서는 게임마다 저장소, 담당자, Jira 부모 이슈, Chat 방을 지정한다. Jira에서는 게임마다 담당 개발자의 상위 태스크를 두고, 그 아래에 이슈 하나당 티켓 한 장을 자동으로 만든다. 도구의 「확인 / 미확인」은 담당자가 에러를 봤는지를, Jira 상태는 수정·배포까지의 해결 여부를 관리한다.

공통 npm 패키지나 공용 프레임워크 같은 공유 의존성에 버그가 있으면 여러 프로젝트와 유저에서 에러가 한꺼번에 터진다. 그룹핑으로 같은 원인을 한 건으로 모아 분석과 티켓 발급을 한 번만 한다.

가장 어려운 지점은 JS 콜스택, breadcrumbs, 소스·커밋 이력처럼 여러 컨텍스트 중에서 해당 이슈와 관련된 것만 골라 조합하는 일이다. 그러면서 환각을 억제하고 구조화된 JSON을 안정적으로 출력해, 개발자가 “도움이 된다”고 느낄 만한 진단 품질을 내야 한다.

  • 호출 단위: 에러 한 건에 AI 게이트웨이를 한 번 호출한다.
  • 출력 형식: 원인, 확신도, 심각도, 수정 제안, 한계를 정해진 JSON으로만 받고, 형식이 틀리면 다시 요청한다.
  • 단정하지 않기: 확신도가 낮거나 원인이 클라이언트 밖이면 「원인 불명」으로 표시한다. 이때도 AI 추정과 환경, 실패한 요청을 참고로 붙인다.
  • 개인정보와 비용: 토큰·이메일·사용자 ID는 가려서 보내고, 같은 입력은 다시 호출하지 않는다.
  • 소스맵이 빌드 때 정상 등록되어야 원본 기준으로 복원된다. 등록되지 않으면 위치 식별이 제한된다.
  • 애드블록이나 네트워크 유실로 일부 에러는 수집되지 않을 수 있다.
  • 스택만 있고 breadcrumbs가 없는 식으로 맥락이 빈약하면 AI 진단 정확도가 떨어진다.
  • 서버·네트워크처럼 프론트엔드 밖에서 생긴 에러는 진단에 한계가 있다.
  • AI 진단은 검수가 필요하다. 개발자가 진단을 확인한 뒤 실제 코드를 고친다.
  • 게임마다 구조가 달라 SDK 패키지 대신 설치 스킬로 이식한다.
  • Jira가 담당자 칸에 이메일을 받지 않아, 이메일을 Jira 계정으로 바꿔 넣는다.
  • AI 진단이 언제 끝날지 보장할 수 없어 「분석 대기」 알림을 먼저 보낸다.
  • Chat 알림은 운영 서버 에러만 보내고, 알림 방은 프로젝트마다 고른다.
  • 소스맵 보안: 배포본에서 소스맵을 숨기고 회사 호스트에만 올렸다. 소스맵 없이 나간 배포는 「맵 없음」으로 표시된다.
  • 알림 지연: 웹훅은 저장만 하고 바로 응답한다. 알림은 「분석 대기」와 진단 후 갱신으로 나눠 보낸다.
  • 티켓 중복: 같은 요청이 다시 오거나 동시에 들어와도 이슈 하나에 티켓은 한 장이 되게 했다.
  • 부분 실패: 소스맵이 없거나 AI가 실패해도 나머지 단계는 진행하고, 실패한 작업은 간격을 늘려 다시 시도한다.
단계 도구 없이 도구로
인지 iOS Safari 유저의 로딩 실패. 제보가 없으면 모름 수신 직후 Chat 알림, Jira 티켓 자동 생성
위치 압축된 framework-*.js:2만 보임 H5 프레임워크 원본 resources.js:56 fetch로 복원
원인 재현·로그 수집부터 시작 manifest.json 요청이 응답 없이 실패. 코드 결함보다 네트워크 실패
조치 담당자가 직접 정리 담당 개발자가 네트워크 이슈로 결론 내고 확인 완료, 평가자 모두 「도움됨」

이슈 상세 화면에는 복원된 원본 위치, AI 진단, 처리 단계, 개발자 평가가 한 화면에 모인다.

출시 전 빌드(공개 주소에 올린 빌드와 QA 빌드)에 연동해 운영했다.

  • 원본 위치: 운영 서버의 실제 에러 상당수를 원본 파일·라인으로 복원했다. 복원하지 못한 것은 소스맵 없이 나간 배포와 위치 정보가 없는 에러였다.
  • 인지: 유저 제보를 기다리지 않고 에러가 나면 바로 알림이 나간다.
  • 티켓: 자동으로 생성되고, 사람이 티켓을 쓰는 일은 없어졌다. 이슈 수와 티켓 수가 같아 중복이 없었다.
  • 진단 리포트 평가: 「도움됨」 비율이 목표치를 넘었고 「틀림」은 없었다. 평가 대상은 AI 문장에 환경, 실패한 요청, 원본 위치를 묶은 리포트 전체다. 「원인 불명」 리포트도 대부분 「도움됨」을 받았다.
  • 에러 성격: 들어온 실제 에러는 대부분 리소스 로드 실패였고 나머지는 기기·환경 문제였다. 코드 결함은 없었다.
  • 이식: 다른 팀 규칙대로 Jira·Chat을 지정한 테스트 프로젝트에 설치 스킬로 적용해 로컬에서 복원과 알림을 확인했다.

정성적으로는 다음이 달라졌다.

  • 제보가 없었다면 몰랐을 에러, 화면은 멀쩡한데 기능만 멈춘 에러도 잡힌다.
  • 모든 에러가 원인·처방·심각도라는 같은 구조로 남아, 담당자별 분석 편차가 줄고 나중에도 당시 맥락을 다시 볼 수 있다.
  • 에러가 쏟아져도 이슈당 티켓은 한 장이다.
  • 납품처가 알려 오기 전에 먼저 알 수 있다.

티켓 작성 시간은 없어졌다. 건당 원인 파악 시간이 줄었다는 것은 개발자 경험에 따른 판단이고 측정값은 아니다. 연동한 게임이 모두 출시 전이라 에러 빈도는 아직 실측할 수 없다.

설계부터 백엔드, 대시보드, 배포 문서, 이식 스킬까지 AI 코딩 에이전트(Cursor, Claude Code)와 함께 만들었고, 본업과 병행했다. 요구사항과 보안 원칙, 실제 배포 검증은 사람이 정하고 확인했다. 운영 서버에서 에러를 받기 시작한 뒤에도 운영하며 보강했다.

  • 「도움됨」 비율을 계속 보고, 출시 후 에러 빈도를 실측한다.
  • 실패한 작업과 밀린 작업은 운영자 Chat 방과 /health로 확인한다.
  • Sentry metric으로 로딩 시간과 리소스 로드 실패율 같은 유저 텔레메트리를 측정한다.
  • 다른 웹 게임 프로젝트로 설치 스킬 적용을 넓힌다.