울면서개발하기
VERA ERP 개발일지

운영 화면 오류를 직접 모으기 — Sentry 대신 작은 수집기

· 커밋 2개

사용자가 프로그램 요청으로 알려 주기 전에, 운영에서 실제로 난 화면 오류를 직접 보고 싶었다. Sentry 같은 서비스를 붙이는 대신 필요한 만큼만 직접 만들었다. 데이터를 바깥 서비스로 보내지 않아도 되고, 이 정도 규모에는 표 하나와 API 하나면 충분했다.

한 일

브라우저 쪽

  • 처리되지 않은 스크립트 오류, Promise 거부, Vue 오류, console.error, Nx 의 경고(없는 넥사크로 API 등), 서버 거래 오류를 모은다
  • 10초마다 묶어서 보낸다. 같은 오류는 10분에 한 번만
  • 운영 빌드에서만 켜진다
  • 보내기 전에 개인정보로 보일 수 있는 꼴(긴 숫자 등)을 가린다

서버 쪽

  • 로그인한 사용자만 보낼 수 있고, 횟수 제한이 있다
  • 같은 오류는 한 줄로 모은다. 기준은 오류 종류 + 화면 + 숫자를 지운 메시지
  • 고쳤다고 표시한 오류가 다시 나면 다시 열린 상태가 된다

소스맵은 서버에 올리지 않는다

운영 번들은 압축돼 있어서 오류 위치가 assets/xxx-해시.js:1:23456 처럼 나온다. 원본 줄을 보려면 소스맵이 필요하지만, 소스맵에는 원본 코드가 들어 있어 서버에 올리고 싶지 않았다.

  • 빌드에서 소스맵을 hidden 으로 만든다. 파일은 만들되 번들에 소스맵 주소 주석을 적지 않는다
  • 빌드가 끝나면 소스맵 파일을 배포 폴더에서 빼내 개발 PC 의 별도 폴더에 배포본 이름별로 보관한다(최근 30개)
  • 배포본 이름(빌드 시각 + 커밋)을 빌드 결과에 넣고, 화면이 오류와 함께 보낸다
  • 작은 스크립트로 DB 에 쌓인 스택의 번들 위치를 그 배포본의 소스맵으로 풀어 원본 파일·줄을 보여 준다

넥사크로 화면 스크립트는 운영 빌드에서 주석을 지울 때 줄 수를 지켜 두었기 때문에, 스택에 나온 줄 번호가 이미 원본 줄이다.

가리기 규칙 고침

처음 규칙은 6자리 넘는 숫자를 모두 가렸다. 그랬더니 ab01_0401010_m 같은 화면 이름 안의 숫자까지 가려져 어느 화면에서 난 오류인지 알 수 없었다. 글자나 밑줄에 붙은 숫자는 두고, 따로 떨어진 긴 숫자만 가리게 바꿨다.

// 고치기 전: 화면 이름 안의 숫자까지 가린다
message.replace(/\d{6,}/g, '<num>')

// 고친 뒤: 앞뒤가 글자·숫자·밑줄이 아닌 긴 숫자만
message.replace(/(?<!\w)\d{6,}(?!\w)/g, '<num>')

기술 메모

Vite 의 build.sourcemap: 'hidden'. true 와 같이 .map 파일을 만들지만 번들 끝에 //# sourceMappingURL= 주석을 넣지 않는다. 브라우저 개발자 도구가 소스맵을 찾지 않으니, 맵 파일을 배포 폴더에서 빼 두기만 하면 원본 코드가 바깥으로 나가지 않는다. 빌드 직후 스크립트로 .map 을 옮기는 것까지 빌드 명령에 묶어 두어야 실수로 같이 올라가지 않는다.