Conversation
🚀 Preview 배포 완료!
|
Walkthrough프로젝트에 Sentry를 통합하여 빌드/런타임에 SDK 초기화, Vite 플러그인 추가, API 오류 및 렌더/로그아웃 관련 사용자 컨텍스트를 캡처/정리하도록 변경합니다. (약 50단어 이내) Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant App
participant Axios as HTTP Client
participant API
participant Sentry
Browser->>App: 사용자 가입/로그인 요청
App->>Axios: POST /api/member (credentials)
Axios->>API: HTTP 요청
API-->>Axios: 200 + auth header, body{id}
Axios-->>App: 응답 전달 (토큰 저장)
App->>Sentry: Sentry.setUser(id)
sequenceDiagram
participant Browser
participant App
participant Axios as HTTP Client
participant API
participant Sentry
Browser->>App: API 요청
App->>Axios: 요청 실행
Axios->>API: HTTP 요청
API-->>Axios: 5xx 또는 에러 응답
Axios->>App: 에러 리턴 (인터셉터)
App->>Sentry: captureClientApiError(error) -- 태그/컨텍스트 포함
Sentry-->>Sentry: 이벤트 저장/전송
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request integrates Sentry for error tracking and performance monitoring across the application. Key changes include the addition of Sentry dependencies, initialization logic in a new instrument file, and the capture of user context during authentication flows. Furthermore, an Axios interceptor was implemented to log 4xx API errors, and the global ErrorBoundary was updated to report rendering exceptions with component stacks. The review feedback suggests expanding the scope of captured API errors to include 5xx and network failures for better debugging context, and implementing a flag-based mechanism to prevent duplicate error reporting between the Axios interceptor and the ErrorBoundary.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/apis/axiosInstance.ts (1)
108-116:⚠️ Potential issue | 🟡 Minor리프레시 토큰 실패 시 Sentry 사용자 컨텍스트가 정리되지 않습니다.
useLogout.ts에서는 로그아웃 성공 시Sentry.setUser(null)을 호출하지만, 여기서 리프레시 토큰 실패로 인한 강제 로그아웃 시에는 Sentry 사용자 컨텍스트가 정리되지 않습니다. 이후 발생하는 에러에 이전 사용자 정보가 잘못 연결될 수 있습니다.🛠️ 제안하는 수정
} catch (refreshError) { console.error('Refresh Token is invalid or expired', refreshError); // 재발급도 실패하면 -> 로그인 페이지 이동 const currentLang = i18n.resolvedLanguage ?? i18n.language; const lang = isSupportedLang(currentLang) ? currentLang : DEFAULT_LANG; window.location.href = buildLangPath('/home', lang); removeAccessToken(); + Sentry.setUser(null); return Promise.reject(refreshError); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apis/axiosInstance.ts` around lines 108 - 116, In the refresh token catch block inside axiosInstance.ts (the catch handling refreshError), clear the Sentry user context before redirecting and removing tokens: call Sentry.setUser(null) (ensure Sentry is imported) right before removeAccessToken() / window.location.href so subsequent errors aren’t attributed to the old user; keep existing logic that computes lang via i18n.resolvedLanguage/i18n.language, isSupportedLang, DEFAULT_LANG and uses buildLangPath('/home', lang) and removeAccessToken().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@vite.config.ts`:
- Around line 30-32: 현재 빌드 설정은 sourcemap: 'hidden'을 isProductionBuild일 때 무조건
적용하고 있어 hasSentryAuth가 false면 .map이 dist에 남아 S3로 업로드됩니다; update the logic so
sourcemap is set to 'hidden' only when both isProductionBuild and hasSentryAuth
are true (otherwise false), and ensure the existing filesToDeleteAfterUpload
behavior is aligned with hasSentryAuth; locate and modify the sourcemap
assignment (sourcemap, isProductionBuild) and the
filesToDeleteAfterUpload/hasSentryAuth checks so they use the same hasSentryAuth
guard.
---
Outside diff comments:
In `@src/apis/axiosInstance.ts`:
- Around line 108-116: In the refresh token catch block inside axiosInstance.ts
(the catch handling refreshError), clear the Sentry user context before
redirecting and removing tokens: call Sentry.setUser(null) (ensure Sentry is
imported) right before removeAccessToken() / window.location.href so subsequent
errors aren’t attributed to the old user; keep existing logic that computes lang
via i18n.resolvedLanguage/i18n.language, isSupportedLang, DEFAULT_LANG and uses
buildLangPath('/home', lang) and removeAccessToken().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: be5b0840-5462-43f5-925e-38a9d16cbc2a
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
package.jsonsrc/apis/apis/member.tssrc/apis/axiosInstance.tssrc/components/ErrorBoundary/ErrorBoundary.tsxsrc/hooks/mutations/useLogout.tssrc/instrument.tssrc/main.tsxvite.config.ts
src/apis/axiosInstance.ts
Outdated
| baseURL: config?.baseURL, | ||
| params: config?.params, | ||
| requestData: config?.data, | ||
| responseData: response?.data, |
There was a problem hiding this comment.
[이슈 1] 민감 데이터가 Sentry에 그대로 전송될 수 있습니다
requestData: config?.data와 responseData: response?.data는 요청/응답 바디 전체를 Sentry 이벤트에 포함합니다.
지금은 무해할 수 있지만, 향후 API가 확장되면 이름, 이메일, 전화번호 등 개인정보가 포함된 바디가 Sentry 대시보드에 노출될 수 있습니다. GDPR 및 개인정보보호법 관점에서 리스크가 있습니다.
해결 방안
responseData는 제거하고, requestData는 디버깅에 필요한 필드만 선택적으로 포함하도록 변경하는 것을 권장합니다.
extra: {
url: config?.url,
method: config?.method,
baseURL: config?.baseURL,
params: config?.params,
// requestData: config?.data, ← 제거: 요청 바디에 민감 정보 포함 가능
// responseData: response?.data, ← 제거: 응답 바디에 개인정보 노출 위험
timeout: config?.timeout ?? requestTimeoutMs,
},status code와 url만으로도 4xx 에러 원인 파악에 충분한 경우가 많습니다. 만약 요청 정보가 꼭 필요하다면 민감 필드를 제외한 safe subset만 직렬화하는 별도 함수를 두는 것도 방법입니다.
There was a problem hiding this comment.
그런데 우리 프로젝트에서는 크게 문제 없을 것 같긴해요. 민감한 정보는 없을 것 같아서...
There was a problem hiding this comment.
꼼꼼하게 봐주셔서 감사합니다! 현재 민감한 정보는 없지만 그렇다고 해서 전송할 이유도 없는 것 같아서 지웠습니다! 추후 필요하다면 민감하지 않은 정도로 선택해서 포함하도록 변경하겠습니다 !!
| @@ -79,6 +115,9 @@ axiosInstance.interceptors.response.use( | |||
| return Promise.reject(refreshError); | |||
There was a problem hiding this comment.
[이슈 2] 토큰 만료로 인한 자동 로그아웃 시 Sentry user context가 정리되지 않습니다
refresh token 재발급 실패 시 removeAccessToken()은 호출되지만 Sentry.setUser(null)은 호출되지 않습니다. 이후 발생하는 에러 이벤트에 이전 사용자의 컨텍스트가 남아 잘못된 사용자에게 에러가 귀속될 수 있습니다.
useLogout.ts에서는 잘 처리하고 있지만, 세션 만료에 의한 강제 로그아웃 경로가 누락되어 있습니다.
해결 방안 (A) — 해당 위치에서 직접 처리
} catch (refreshError) {
console.error('Refresh Token is invalid or expired', refreshError);
const currentLang = i18n.resolvedLanguage ?? i18n.language;
const lang = isSupportedLang(currentLang) ? currentLang : DEFAULT_LANG;
window.location.href = buildLangPath('/home', lang);
removeAccessToken();
Sentry.setUser(null); // ← 추가: 세션 만료 시에도 user context 정리
return Promise.reject(refreshError);
}해결 방안 (B) — removeAccessToken 유틸리티에 통합
removeAccessToken() 내부에서 Sentry.setUser(null)을 함께 호출하면, 명시적 로그아웃과 세션 만료 두 경로를 한 번에 처리할 수 있어 이후 실수를 방지할 수 있습니다.
There was a problem hiding this comment.
이 부분이 빠졌었네요. 제안해 주신 방안들 중 A안으로 간단하게 작업 완료했습니다!
🚩 연관 이슈
closed #435
📝 작업 내용
이번 작업은 프론트에서 발생하는 에러를 실사용자 기준으로 수집하고, 운영에서 바로 확인하고 디버깅할 수 있는 형태로 남기기 위한 Sentry 환경 구성입니다.
이번 PR에서는 범위를 넓게 가져가기보다, 에러가 발생했을 때 누가 어떤 흐름에서 실패했는지 빠르게 파악할 수 있는 상태를 만드는 것에 우선순위를 뒀습니다. 그래서 Error Monitoring, Session Replay, Source Map 업로드를 먼저 적용했고, Logs나 Profiling, component stack 가독성 개선은 이번 범위에서 제외했습니다.
1. Sentry 초기화 및 수집 범위 구성
처음부터 모든 기능을 넓게 켜기보다는, 지금 바로 운영에서 필요한 정보만 먼저 수집하도록 구성했습니다.
2. 렌더링 에러와 API 에러 분리 수집
ErrorBoundary에서 잡힌 렌더링 에러와axiosInstance에서 잡는 API 에러를 별도로 수집하도록 구성했습니다.401과 정상/리다이렉트 응답만 제외하고,4xx / 5xx / 네트워크 실패 / 타임아웃을 수집합니다.5xx는 어떤 화면/행동에서 사용자 장애가 발생했는지 프론트 맥락으로 확인하기 위한 용도로 포함했습니다.3. 사용자 식별 기준 정리
id만 사용하고,email은 넣지 않았습니다.4. Source Map 업로드 및 검증
운영 환경에서 에러를 수집하더라도, 스택트레이스가 번들된 JS 기준으로만 보이면 실제 원인 추적이 어렵다고 판단했습니다. 그래서 이번 PR에서는 에러를 수집하는 것과 함께, 수집된 에러를 실제로 읽을 수 있게 만드는 것까지 같이 진행했습니다.
vite.config.ts에 @sentry/vite-plugin을 추가했습니다.
인증값 없이 배포 산출물에 포함되는 상황을 막기 위해 source map은 production 빌드에서, Sentry 인증값이 설정된 경우에만 생성 및 업로드되도록 정리했습니다.
업로드 후 dist/**/*.map 파일은 자동 삭제되도록 처리했습니다.
preview 환경에서 실제로 에러를 발생시켜 symbolication이 정상 동작하는 것까지 확인했습니다.
적용 전
🏞️ 스크린샷 (선택)
Sentry에게 인사해주세요 호호호 ^^
🗣️ 리뷰 요구사항 (선택)
궁금하신 점이나 설정 이런 것 추가는 어떤가요? 등등 자유롭게 달아주세요 ~ !!
Summary by CodeRabbit
새로운 기능
버그 수정 / 동작 개선