Skip to content

6.10 최신화 - #378

Merged
yhi9839 merged 5 commits into
mainfrom
dev
Jun 10, 2026
Merged

yhi9839 merged 5 commits into
mainfrom
dev

Conversation

@yhi9839

@yhi9839 yhi9839 commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Enhanced error tracking and monitoring system implemented for improved app stability
    • Added global error page with recovery button for better user experience when errors occur
    • Added news upload resources section to support page

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
checkmo Ready Ready Preview, Comment Jun 10, 2026 12:53am

@coderabbitai

coderabbitai Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR integrates Sentry observability across the Next.js application with server, edge, and client-side instrumentation, error capture, and user context tracking. It adds a news upload section to the support page and removes an unused reporting hook.

Changes

Sentry Monitoring & UI Updates

Layer / File(s) Summary
Sentry SDK & Next.js Configuration
package.json, sentry.server.config.ts, sentry.edge.config.ts, next.config.ts
Adds @sentry/nextjs dependency, creates environment-specific DSN and tracing configurations for server and edge runtimes, and wraps the Next.js config with withSentryConfig for build-time integration.
Application Instrumentation Modules
instrumentation.ts, instrumentation-client.ts
instrumentation.ts exports async register() that loads the appropriate server or edge Sentry config based on NEXT_RUNTIME. instrumentation-client.ts initializes client-side Sentry with full performance tracing and session replay sampling, exporting onRouterTransitionStart for router event tracking.
Error Capture & User Context
src/components/auth/AuthProvider.tsx, src/app/global-error.tsx, src/lib/api/client.ts
AuthProvider sets Sentry user context (email/username) on successful auth profile load and clears it on failure. global-error.tsx captures uncaught exceptions and renders a fallback error UI. API client reports 5xx errors and non-timeout exceptions to Sentry.
Support Page News Upload Section
src/app/support/page.tsx
Adds a new "소식 업로드" (news upload) card with explanatory text and an external link button to the news submission URL.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • checkmo2025/FE#373: Introduces identical Sentry integration files (instrumentation-client.ts, instrumentation.ts, sentry.server.config.ts, sentry.edge.config.ts, next.config.ts wrapper), indicating overlapping or concurrent Sentry setup work.
  • checkmo2025/FE#245: Deletes legacy meeting chat service and query modules (meetingChatService 2.ts, useMeetingChatQueries 2.ts) while adding STOMP realtime chat alternatives, reflecting the same meeting subsystem refactoring visible in this PR's removals.
  • checkmo2025/FE#341: Updates API error mapping utilities (errorMapper.ts additions for block-related codes), complementing this PR's consolidation of error handling in src/lib/api/client.ts.

Suggested labels

✨ feat, ♻️ refactor

Poem

A rabbit hops through logs so bright,
Sentries guard each day and night,
Errors captured, users seen,
News uploads keep things keen! 🐰📊✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "6.10 최신화" is vague and generic, using only a date and the Korean word for "update" without describing what was actually changed. Replace with a specific title that describes the main change, e.g., "Add Sentry instrumentation for error tracking and monitoring" or "Refactor API client and integrate Sentry error reporting."
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request integrates Sentry for error tracking and performance monitoring in a Next.js application, configures user context tracking, and cleans up several unused API hooks and services. The review feedback highlights a critical issue in the API client where parsing custom error codes (e.g., COMMON500) fails to report 5xx errors to Sentry. Additionally, the reviewer recommends dynamically configuring Sentry's tracesSampleRate based on the environment to protect quotas, correcting a potential typo in the support page link, and using a unique database ID instead of an email address for Sentry user identification to safeguard PII.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/lib/api/client.ts
Comment on lines +91 to +98
if (error instanceof ApiError) {
// 5xx 서버 에러만 Sentry에 보고 (4xx, 401은 제외)
const statusCode = parseInt(error.code.replace("HTTP", ""), 10);
if (!isNaN(statusCode) && statusCode >= 500) {
Sentry.captureException(error, {
extra: { code: error.code, url: requestUrl, method: options.method },
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

error.code가 COMMON500이나 BLOCK_400과 같이 숫자가 포함된 커스텀 에러 코드일 경우, error.code.replace("HTTP", "") 결과는 여전히 숫자가 아닌 문자로 시작하는 문자열(예: COMMON500)이 됩니다. 이로 인해 parseInt 결과가 NaN이 되어 5xx 서버 에러임에도 불구하고 Sentry에 보고되지 않는 문제가 발생할 수 있습니다.\n\n정규식을 사용하여 에러 코드 문자열에서 숫자 부분만 안전하게 추출하여 판별하는 것을 권장합니다.

    if (error instanceof ApiError) {
      // 5xx 서버 에러만 Sentry에 보고 (4xx, 401은 제외)
      const match = error.code.match(/\d+/);
      const statusCode = match ? parseInt(match[0], 10) : NaN;
      if (!isNaN(statusCode) && statusCode >= 500) {
        Sentry.captureException(error, {
          extra: { code: error.code, url: requestUrl, method: options.method },
        });
      }
    }

Comment thread instrumentation-client.ts
Comment on lines +7 to +9
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
tracesSampleRate: 1.0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

현재 tracesSampleRate가 1.0으로 고정되어 있습니다. 주석에 언급된 것처럼 운영(production) 환경에서는 1020%(0.10.2)로 낮추는 것이 권장되는데, 이를 수동으로 변경하기보다 환경 변수(process.env.NODE_ENV)에 따라 자동으로 설정되도록 분기 처리하는 것이 안전합니다.

Suggested change
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
tracesSampleRate: 1.0,
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,

Comment thread sentry.edge.config.ts
Comment on lines +5 to +6
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

운영(production) 환경에서 Sentry 할당량이 급격히 소모되는 것을 방지하기 위해 tracesSampleRate를 환경 변수에 따라 동적으로 설정하는 것을 권장합니다.

Suggested change
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,

Comment thread sentry.server.config.ts
Comment on lines +5 to +6
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

운영(production) 환경에서 Sentry 할당량이 급격히 소모되는 것을 방지하기 위해 tracesSampleRate를 환경 변수에 따라 동적으로 설정하는 것을 권장합니다.

Suggested change
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
environment: process.env.NODE_ENV,
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,

Comment thread src/app/support/page.tsx
Comment on lines +78 to +80
<a
href={EXTERNAL_LINKS.NEWS_FROM_URL}
target="_blank"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

EXTERNAL_LINKS.NEWS_FROM_URL 변수명에 오타가 있는 것으로 보입니다. "소식 업로드"를 위한 설문지(Form) 링크이므로 NEWS_FROM_URL 대신 NEWS_FORM_URL이 더 적절합니다.\n\n정의된 상수 파일(EXTERNAL_LINKS가 선언된 곳)과 함께 이 부분의 변수명을 NEWS_FORM_URL로 변경하는 것을 검토해 주세요.

Suggested change
<a
href={EXTERNAL_LINKS.NEWS_FROM_URL}
target="_blank"
<a
href={EXTERNAL_LINKS.NEWS_FORM_URL}
target="_blank"

Comment on lines +21 to +25
Sentry.setUser({
id: response.result.email || "unknown",
email: response.result.email || undefined,
username: response.result.nickname,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Sentry의 setUser에서 id 필드에 이메일(email)을 사용하고 있습니다. 이메일은 변경될 수 있는 값이며 개인정보(PII)에 해당하므로, Sentry의 권장사항에 따라 데이터베이스의 고유 식별자(예: id 또는 userId)를 id 필드에 사용하고 이메일은 email 필드에만 할당하는 것이 보안 및 데이터 정합성 측면에서 더 좋습니다.\n\nresponse.result에 고유 ID 필드가 존재한다면 이를 활용해 주세요.

Suggested change
Sentry.setUser({
id: response.result.email || "unknown",
email: response.result.email || undefined,
username: response.result.nickname,
});
Sentry.setUser({
id: String(response.result.id || "unknown"),
email: response.result.email || undefined,
username: response.result.nickname,
});

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/components/auth/AuthProvider.tsx (1)

21-25: ⚡ Quick win

Consider using non-PII identifier as Sentry user ID.

The implementation uses email as the Sentry user id (line 22). Email is personally identifiable information (PII). Sentry's best practice recommends using a non-PII identifier (such as a user UUID or database ID) as the primary id, while keeping email as a separate field for filtering.

This reduces privacy/compliance risk and makes it easier to anonymize or delete user data when needed.

🔒 Proposed fix if user profile includes an ID field
           Sentry.setUser({
-            id: response.result.email || "unknown",
+            id: response.result.id?.toString() || "unknown",
             email: response.result.email || undefined,
             username: response.result.nickname,
           });

If the profile doesn't include a unique ID, consider adding one or using a hashed/anonymized version of the email.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/auth/AuthProvider.tsx` around lines 21 - 25, The
Sentry.setUser call is currently using PII (response.result.email) as the user
id; update the Sentry.setUser invocation in AuthProvider (the Sentry.setUser
call) to use a non-PII identifier such as response.result.id or
response.result.userId if available, falling back to an anonymized/hash of
response.result.email only if no unique id exists, and keep
response.result.email assigned to the email field (not the id) while preserving
username: response.result.nickname so Sentry receives id (non-PII), email (PII)
separately, and username unchanged.
instrumentation.ts (1)

4-9: ⚡ Quick win

Use else if for mutually exclusive runtime checks.

The sequential if statements could theoretically load both configs if NEXT_RUNTIME contained both values. While unlikely, using else if makes the mutual exclusion explicit and prevents potential double-initialization.

♻️ Proposed fix
 export async function register() {
   if (process.env.NEXT_RUNTIME === "nodejs") {
     await import("./sentry.server.config");
-  }
-  if (process.env.NEXT_RUNTIME === "edge") {
+  } else if (process.env.NEXT_RUNTIME === "edge") {
     await import("./sentry.edge.config");
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@instrumentation.ts` around lines 4 - 9, The two runtime checks using
process.env.NEXT_RUNTIME should be mutually exclusive; replace the second
standalone if with an else if so only one config is imported: change the block
that currently awaits import("./sentry.server.config") and
import("./sentry.edge.config") to use if (process.env.NEXT_RUNTIME === "nodejs")
{ await import("./sentry.server.config"); } else if (process.env.NEXT_RUNTIME
=== "edge") { await import("./sentry.edge.config"); } to prevent potential
double-initialization.
sentry.edge.config.ts (1)

4-4: ⚖️ Poor tradeoff

Hardcoded Sentry DSN spans three configuration files.

The same Sentry DSN is hardcoded in sentry.edge.config.ts, sentry.server.config.ts, and instrumentation-client.ts. While Sentry DSNs are technically public (used client-side), hardcoding prevents:

  • Environment-specific projects (dev/staging/production)
  • Easy rotation if needed
  • Centralized configuration management

Move to a shared environment variable (NEXT_PUBLIC_SENTRY_DSN) that all three configs can reference.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sentry.edge.config.ts` at line 4, Replace the hardcoded DSN value assigned to
the dsn property in the Sentry configuration with a shared environment variable
NEXT_PUBLIC_SENTRY_DSN; update the dsn assignment (the dsn field in
sentry.edge.config.ts and the equivalent dsn usages in sentry.server.config.ts
and instrumentation-client.ts) to read from process.env.NEXT_PUBLIC_SENTRY_DSN
(or the appropriate runtime env accessor) and add a clear fallback/error
handling if the variable is missing so builds fail fast or log a helpful
message.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@instrumentation-client.ts`:
- Around line 7-9: The tracesSampleRate is hardcoded to 1.0; change it to read
from an environment-driven value and set a lower default for production (e.g.,
use process.env.SENTRY_TRACES_SAMPLE_RATE or compute based on NODE_ENV so
production uses 0.1–0.2 while development can remain 1.0). Update the
tracesSampleRate assignment in instrumentation-client.ts (the variable named
tracesSampleRate) to parse the env value (fallback to 0.1–0.2 in production and
1.0 in non-production) so production sampling is reduced without altering
behavior in dev.

In `@sentry.edge.config.ts`:
- Line 6: All configs currently hardcode tracesSampleRate: 1.0; change them to
compute the sampling from environment (e.g. read
process.env.SENTRY_TRACES_SAMPLE_RATE or NODE_ENV) by adding a small helper
(name it getTracesSampleRate or computeTracesSampleRate) that returns a float:
if SENTRY_TRACES_SAMPLE_RATE is set use parseFloat(value), else if NODE_ENV ===
'production' return 0.1 (or 0.2) otherwise return 1.0 for dev; then replace
tracesSampleRate: 1.0 in sentry.edge.config.ts, sentry.server.config.ts and
instrumentation-client.ts with tracesSampleRate: getTracesSampleRate() so
production uses the lower default and you can override via env.

In `@src/app/global-error.tsx`:
- Around line 17-26: The <html> element returned by the global error component
is missing a lang attribute; update the returned <html> tag in the component
(the JSX that currently returns <html> ... ) to include an appropriate lang
value (e.g., lang="ko" for the Korean message) so screen readers and tools can
detect the page language.

In `@src/lib/api/client.ts`:
- Around line 91-98: The current Sentry-reporting in the client.ts ApiError
branch assumes error.code is prefixed with "HTTP" and thus misses custom backend
codes; update the ApiError class (ApiError constructor / properties) to include
a numeric status field (e.g., status?: number) and ensure the code that
constructs ApiError in the HTTP response path sets that status from
response.status; then change the Sentry reporting logic in client.ts (the block
that computes statusCode from error.code and calls Sentry.captureException) to
prefer error.status if present, otherwise only parse error.code when it
startsWith("HTTP"), and report to Sentry for status >= 500 using the resolved
numeric status.

---

Nitpick comments:
In `@instrumentation.ts`:
- Around line 4-9: The two runtime checks using process.env.NEXT_RUNTIME should
be mutually exclusive; replace the second standalone if with an else if so only
one config is imported: change the block that currently awaits
import("./sentry.server.config") and import("./sentry.edge.config") to use if
(process.env.NEXT_RUNTIME === "nodejs") { await
import("./sentry.server.config"); } else if (process.env.NEXT_RUNTIME ===
"edge") { await import("./sentry.edge.config"); } to prevent potential
double-initialization.

In `@sentry.edge.config.ts`:
- Line 4: Replace the hardcoded DSN value assigned to the dsn property in the
Sentry configuration with a shared environment variable NEXT_PUBLIC_SENTRY_DSN;
update the dsn assignment (the dsn field in sentry.edge.config.ts and the
equivalent dsn usages in sentry.server.config.ts and instrumentation-client.ts)
to read from process.env.NEXT_PUBLIC_SENTRY_DSN (or the appropriate runtime env
accessor) and add a clear fallback/error handling if the variable is missing so
builds fail fast or log a helpful message.

In `@src/components/auth/AuthProvider.tsx`:
- Around line 21-25: The Sentry.setUser call is currently using PII
(response.result.email) as the user id; update the Sentry.setUser invocation in
AuthProvider (the Sentry.setUser call) to use a non-PII identifier such as
response.result.id or response.result.userId if available, falling back to an
anonymized/hash of response.result.email only if no unique id exists, and keep
response.result.email assigned to the email field (not the id) while preserving
username: response.result.nickname so Sentry receives id (non-PII), email (PII)
separately, and username unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 481b6f60-bda2-43e4-8db3-7b5e16bb9d99

📥 Commits

Reviewing files that changed from the base of the PR and between 8cd8687 and 8d97e2e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • instrumentation-client.ts
  • instrumentation.ts
  • next.config.ts
  • package.json
  • sentry.edge.config.ts
  • sentry.server.config.ts
  • src/app/global-error.tsx
  • src/app/support/page.tsx
  • src/components/auth/AuthProvider.tsx
  • src/hooks/mutations/useReportMemberMutations 2.ts
  • src/hooks/queries/useMeetingChatQueries 2.ts
  • src/hooks/queries/useMeetingTopicQueries 2.ts
  • src/hooks/useReportBlockFlow 2.ts
  • src/lib/api/ApiError.ts
  • src/lib/api/client.ts
  • src/lib/api/client/index.ts
  • src/lib/api/errorMapper.ts
  • src/services/meetingChatService 2.ts
  • src/services/reportService 2.ts
💤 Files with no reviewable changes (9)
  • src/services/reportService 2.ts
  • src/hooks/queries/useMeetingChatQueries 2.ts
  • src/lib/api/ApiError.ts
  • src/services/meetingChatService 2.ts
  • src/hooks/queries/useMeetingTopicQueries 2.ts
  • src/lib/api/client/index.ts
  • src/hooks/mutations/useReportMemberMutations 2.ts
  • src/lib/api/errorMapper.ts
  • src/hooks/useReportBlockFlow 2.ts

Comment thread instrumentation-client.ts
Comment on lines +7 to +9
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
tracesSampleRate: 1.0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Implement the acknowledged sampling rate adjustment.

The comment correctly notes that tracesSampleRate: 1.0 should be lowered to 0.1-0.2 for production, but the code doesn't implement this. This can lead to high Sentry costs and rate-limit issues in production.

⚡ Proposed fix
   // 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
-  // production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
-  tracesSampleRate: 1.0,
+  // production 배포 시 0.1~0.2 (10~20%)로 낮춤
+  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮추는 것을 권장
tracesSampleRate: 1.0,
// 성능 모니터링: 페이지 로딩, API 응답 시간 등 100% 수집
// production 배포 시 0.1~0.2 (10~20%)로 낮춤
tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@instrumentation-client.ts` around lines 7 - 9, The tracesSampleRate is
hardcoded to 1.0; change it to read from an environment-driven value and set a
lower default for production (e.g., use process.env.SENTRY_TRACES_SAMPLE_RATE or
compute based on NODE_ENV so production uses 0.1–0.2 while development can
remain 1.0). Update the tracesSampleRate assignment in instrumentation-client.ts
(the variable named tracesSampleRate) to parse the env value (fallback to
0.1–0.2 in production and 1.0 in non-production) so production sampling is
reduced without altering behavior in dev.

Comment thread sentry.edge.config.ts
Sentry.init({
dsn: "https://415293b2a74c82af51a4d9b6f9436fbb@o4511437350436864.ingest.us.sentry.io/4511518360141824",
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

100% trace sampling rate across all Sentry configs.

All three Sentry configurations (sentry.edge.config.ts, sentry.server.config.ts, instrumentation-client.ts) use tracesSampleRate: 1.0. In production, this captures 100% of all performance traces, which can:

  • Generate high Sentry costs
  • Hit rate limits
  • Create unnecessary noise

The comment in instrumentation-client.ts acknowledges this should be 0.1-0.2 for production. Implement environment-based sampling across all configs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sentry.edge.config.ts` at line 6, All configs currently hardcode
tracesSampleRate: 1.0; change them to compute the sampling from environment
(e.g. read process.env.SENTRY_TRACES_SAMPLE_RATE or NODE_ENV) by adding a small
helper (name it getTracesSampleRate or computeTracesSampleRate) that returns a
float: if SENTRY_TRACES_SAMPLE_RATE is set use parseFloat(value), else if
NODE_ENV === 'production' return 0.1 (or 0.2) otherwise return 1.0 for dev; then
replace tracesSampleRate: 1.0 in sentry.edge.config.ts, sentry.server.config.ts
and instrumentation-client.ts with tracesSampleRate: getTracesSampleRate() so
production uses the lower default and you can override via env.

Comment thread src/app/global-error.tsx
Comment on lines +17 to +26
return (
<html>
<body>
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", gap: "16px" }}>
<h2>예기치 못한 문제가 발생했습니다.</h2>
<button onClick={() => reset()}>다시 시도하기</button>
</div>
</body>
</html>
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add lang attribute to <html> tag for accessibility.

The <html> tag is missing the lang attribute (line 18). This attribute helps screen readers, translation tools, and search engines understand the page language.

♿ Proposed fix
   return (
-    <html>
+    <html lang="ko">
       <body>
         <div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", gap: "16px" }}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return (
<html>
<body>
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", gap: "16px" }}>
<h2>예기치 못한 문제가 발생했습니다.</h2>
<button onClick={() => reset()}>다시 시도하기</button>
</div>
</body>
</html>
);
return (
<html lang="ko">
<body>
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", gap: "16px" }}>
<h2>예기치 못한 문제가 발생했습니다.</h2>
<button onClick={() => reset()}>다시 시도하기</button>
</div>
</body>
</html>
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/global-error.tsx` around lines 17 - 26, The <html> element returned
by the global error component is missing a lang attribute; update the returned
<html> tag in the component (the JSX that currently returns <html> ... ) to
include an appropriate lang value (e.g., lang="ko" for the Korean message) so
screen readers and tools can detect the page language.

Comment thread src/lib/api/client.ts
Comment on lines +91 to +98
if (error instanceof ApiError) {
// 5xx 서버 에러만 Sentry에 보고 (4xx, 401은 제외)
const statusCode = parseInt(error.code.replace("HTTP", ""), 10);
if (!isNaN(statusCode) && statusCode >= 500) {
Sentry.captureException(error, {
extra: { code: error.code, url: requestUrl, method: options.method },
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Error code parsing may miss custom 5xx error codes.

Line 93 assumes error.code has an "HTTP" prefix, but looking at line 77, error.code can be either from data?.code (custom error codes) or HTTP${response.status}. If the backend returns a custom error code (e.g., "SERVER_ERROR") for a 5xx response, parsing will produce NaN and the error won't be reported to Sentry, even though it's a server error.

Consider either:

  1. Storing the original HTTP status separately in ApiError
  2. Attempting to parse but falling back to reporting all ApiErrors
  3. Checking if error.code starts with "HTTP" before parsing
🐛 Proposed fix option 1: Store HTTP status in ApiError

Modify ApiError class to include HTTP status:

// In src/lib/api/errors/ApiError.ts
export class ApiError extends Error {
    code: string;
    response?: any;
    status?: number; // Add this

    constructor(message: string, code: string = "UNKNOWN_ERROR", response?: any, status?: number) {
        super(message);
        this.name = "ApiError";
        this.code = code;
        this.response = response;
        this.status = status; // Store it
    }
}

Then in client.ts line 83:

-      throw new ApiError(errorMessage, errorCode, data);
+      throw new ApiError(errorMessage, errorCode, data, response.status);

And update the Sentry reporting:

     if (error instanceof ApiError) {
-      // 5xx 서버 에러만 Sentry에 보고 (4xx, 401은 제외)
-      const statusCode = parseInt(error.code.replace("HTTP", ""), 10);
-      if (!isNaN(statusCode) && statusCode >= 500) {
+      if (error.status && error.status >= 500) {
         Sentry.captureException(error, {
-          extra: { code: error.code, url: requestUrl, method: options.method },
+          extra: { code: error.code, status: error.status, url: requestUrl, method: options.method },
         });
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/api/client.ts` around lines 91 - 98, The current Sentry-reporting in
the client.ts ApiError branch assumes error.code is prefixed with "HTTP" and
thus misses custom backend codes; update the ApiError class (ApiError
constructor / properties) to include a numeric status field (e.g., status?:
number) and ensure the code that constructs ApiError in the HTTP response path
sets that status from response.status; then change the Sentry reporting logic in
client.ts (the block that computes statusCode from error.code and calls
Sentry.captureException) to prefer error.status if present, otherwise only parse
error.code when it startsWith("HTTP"), and report to Sentry for status >= 500
using the resolved numeric status.

@yhi9839
yhi9839 merged commit a54647e into main Jun 10, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — 8d97e2e8 Deployed Jun 10, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants