[ 요약 ]
- Sentry.init 을 설정하고 npm run build 하면 빌드 결과물이 Sentry에 업로드된다.
- webpack-dev-server로 로컬에서 개발 서버 열고 에러를 던진다.
- Sentry를 열어 에러를 확인하고 Unminify Code를 클릭하면 Debug ID가 매칭되지 않는다는 오류가 발생했다고 하며 번들링된 파일을 제공한다.
- ❌ 문제점 : source map을 설정한 npm run build 한 빌드 결과물과 webpack-dev-server로 돌렸을 때 실행한 빌드 결과물이 달라 오류가 발생한다. (mismatch Debug ID)
- ✅ 해결 : 그냥 source map 설정하고 빌드 결과물을 배포하면 문제없이 동작한다.
Sentry로 어떤 에러가 자주 발생했는지, 어떤 행동을 했을 때 에러가 발생하는지 등을 트래킹할 수 있다.
가이드대로 Sentry.init 으로 설정 후 배포하기 전에 로컬에서 테스트하고 싶었다. 그래서 일부로 에러를 던져봤는데, 어떤 코드에서 에러가 났는지 화면 상에서 알기 어려웠다.
공식문서를 찾아보니 source map을 업로드하면 Sentry 에서 스택 트레이스를 확인할 수 있다고 한다.
똑같이 실행하고 로컬에서 돌려보면 안된다. (또 나만 안돼)
공식문서와 블로그를 다 뒤져봤는데 해당 문제를 해결해주지 않았다. 아래와 같이 bundle.js 만 보여주고 에러가 발생하는 곳을 알려주지는 않았다. 아래 목록은 물구나무서서봐도 번들링된 파일이였다.
우측에 Unminify Code
를 클릭해보면 안되는 이유를 알려주는데 Debug ID와 매칭되는 source file이 없다고 하네요 하하 (웨않됌만 14시간째…)
알고보니 그냥 webpack config에 source map 설정하고 빌드 결과물을 배포하면 문제없이 동작한다.
어제 밤부터 하다가 오후까지 안되서 배포된 사이트에서만 되면 되지 하고 배포해봤는데 왜 돼 ?!??
생각해보니 npm run build를 하고 npm start로 webpack-dev-server를 열어서 테스트했었다. 그 과정을 다시 살펴보니 npm run build 단계에서 Sentry에 빌드 결과물을 업로드하고, webpack-dev-server로 개발 서버를 열 때 새로 빌드한다. 그래서 빌드 결과물이 다르니 debug id가 다르다는 에러가 발생한 것이였다.
알고보면 당연한 부분이였지만 Sentry라는 낯선 도구를 처음 적용해보니 어디서 에러가 발생할지 예측할 수 없었다. 사실 Sentry로 확인하는데 source map이 적용됐는지 안됐는지도 몰랐다. 그래서 source map에 따라 스택 트레이스가 어떻게 달라지는지 좀더 알아보았다.
devtool을 source-map으로 설정할 경우 에러 메세지에서 소스코드 원본이 그대로 보인다. production 환경에서 이런식으로 코드가 다 보인다면 코드가 유출될 수 있다. 회사 프로덕트일 경우 더더욱 보안을 신경써야하기 때문에 이와 같은 방식은 권장되지 않는다.
devtool을 hidden-source-map으로 설정하면 난독화된 파일에서 에러 메세지를 보여준다. 하지만 source 탭에 .js.map 파일은 존재하므로 악의적인 사용자가 이를 이용할 수 있다.
하지만 Sentry에서 가독성 좋은 스택 트레이스를 보여주려면 source map이 필요하다.
Sentry는 source map을 갖고, 배포 사이트에선 source map을 확인 못하게 할 수 없을까?
공식문서 webpack 설정에 따르면 sourcemaps.filesToDeleteAfterUpload
를 활용하여 Sentry에 업로드 후 map 파일만 제거할 수 있다. 실제로 배포 사이트에서 확인해보면 map 파일이 없어 번들링된 파일로 트래킹되는 것을 확인할 수 있다.
// webpack.config.js
...
devtool: 'hidden-source-map',
plugins: [
sentryWebpackPlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: 'ddangkong',
project: 'ddangkong-front',
sourcemaps: {
filesToDeleteAfterUpload: '**/*.js.map',
},
}),
],