From 1abf07559afea2e41a8d1cdf8dc277a3b7e8038b Mon Sep 17 00:00:00 2001 From: useon Date: Tue, 31 Mar 2026 03:39:00 +0900 Subject: [PATCH 01/12] =?UTF-8?q?chore:=20Sentry=20React=20SDK=20=EB=B0=8F?= =?UTF-8?q?=20Vite=20=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 413 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 + 2 files changed, 397 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88150579..3c7086da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "0.0.0", "dependencies": { + "@sentry/react": "^10.46.0", "@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/react-query": "^5.90.20", "axios": "^1.13.4", @@ -33,6 +34,7 @@ "@babel/types": "^7.28.4", "@chromatic-com/storybook": "^3.2.2", "@eslint/js": "^9.15.0", + "@sentry/vite-plugin": "^5.1.1", "@storybook/addon-essentials": "^8.6.15", "@storybook/addon-interactions": "^8.6.15", "@storybook/addon-onboarding": "^8.6.15", @@ -2316,6 +2318,358 @@ "dev": true, "license": "MIT" }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.46.0.tgz", + "integrity": "sha512-WB1gBT9G13V02ekZ6NpUhoI1aGHV2eNfjEPthkU2bGBvFpQKnstwzjg7waIRGR7cu+YSW2Q6UI6aQLgBeOPD1g==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.46.0.tgz", + "integrity": "sha512-c4pI/z9nZCQXe9GYEw/hE/YTY9AxGBp8/wgKI+T8zylrN35SGHaXv63szzE1WbI8lacBY8lBF7rstq9bQVCaHw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.46.0.tgz", + "integrity": "sha512-JBsWeXG6bRbxBFK8GzWymWGOB9QE7Kl57BeF3jzgdHTuHSWZ2mRnAmb1K05T4LU+gVygk6yW0KmdC8Py9Qzg9A==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.46.0", + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.46.0.tgz", + "integrity": "sha512-ub314MWUsekVCuoH0/HJbbimlI24SkV745UW2pj9xRbxOAEf1wjkmIzxKrMDbTgJGuEunug02XZVdJFJUzOcDw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.46.0", + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.1.1.tgz", + "integrity": "sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@sentry/browser": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.46.0.tgz", + "integrity": "sha512-80DmGlTk5Z2/OxVOzLNxwolMyouuAYKqG8KUcoyintZqHbF6kO1RulI610HmyUt3OagKeBCqt9S7w0VIfCRL+Q==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.46.0", + "@sentry-internal/feedback": "10.46.0", + "@sentry-internal/replay": "10.46.0", + "@sentry-internal/replay-canvas": "10.46.0", + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-5.1.1.tgz", + "integrity": "sha512-F+itpwR9DyQR7gEkrXd2tigREPTvtF5lC8qu6e4anxXYRTui1+dVR0fXNwjpyAZMhIesLfXRN7WY7ggdj7hi0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "5.1.1", + "@sentry/cli": "^2.58.5", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^13.0.6", + "magic-string": "~0.30.8" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@sentry/cli": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.5.tgz", + "integrity": "sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg==", + "dev": true, + "hasInstallScript": true, + "license": "FSL-1.1-MIT", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.58.5", + "@sentry/cli-linux-arm": "2.58.5", + "@sentry/cli-linux-arm64": "2.58.5", + "@sentry/cli-linux-i686": "2.58.5", + "@sentry/cli-linux-x64": "2.58.5", + "@sentry/cli-win32-arm64": "2.58.5", + "@sentry/cli-win32-i686": "2.58.5", + "@sentry/cli-win32-x64": "2.58.5" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.5.tgz", + "integrity": "sha512-lYrNzenZFJftfwSya7gwrHGxtE+Kob/e1sr9lmHMFOd4utDlmq0XFDllmdZAMf21fxcPRI1GL28ejZ3bId01fQ==", + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.5.tgz", + "integrity": "sha512-KtHweSIomYL4WVDrBrYSYJricKAAzxUgX86kc6OnlikbyOhoK6Fy8Vs6vwd52P6dvWPjgrMpUYjW2M5pYXQDUw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.5.tgz", + "integrity": "sha512-/4gywFeBqRB6tR/iGMRAJ3HRqY6Z7Yp4l8ZCbl0TDLAfHNxu7schEw4tSnm2/Hh9eNMiOVy4z58uzAWlZXAYBQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.5.tgz", + "integrity": "sha512-G7261dkmyxqlMdyvyP06b+RTIVzp1gZNgglj5UksxSouSUqRd/46W/2pQeOMPhloDYo9yLtCN2YFb3Mw4aUsWw==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.5.tgz", + "integrity": "sha512-rP04494RSmt86xChkQ+ecBNRYSPbyXc4u0IA7R7N1pSLCyO74e5w5Al+LnAq35cMfVbZgz5Sm0iGLjyiUu4I1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.5.tgz", + "integrity": "sha512-AOJ2nCXlQL1KBaCzv38m3i2VmSHNurUpm7xVKd6yAHX+ZoVBI8VT0EgvwmtJR2TY2N2hNCC7UrgRmdUsQ152bA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.5.tgz", + "integrity": "sha512-EsuboLSOnlrN7MMPJ1eFvfMDm+BnzOaSWl8eYhNo8W/BIrmNgpRUdBwnWn9Q2UOjJj5ZopukmsiMYtU/D7ml9g==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.58.5", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.5.tgz", + "integrity": "sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sentry/cli/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sentry/core": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.46.0.tgz", + "integrity": "sha512-N3fj4zqBQOhXliS1Ne9euqIKuciHCGOJfPGQLwBoW9DNz03jF+NB8+dUKtrJ79YLoftjVgf8nbgwtADK7NR+2Q==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "10.46.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.46.0.tgz", + "integrity": "sha512-Rb1S+9OuUPVwsz7GWnQ6Kgf3azbsseUymIegg3JZHNcW/fM1nPpaljzTBnuineia113DH0pgMBcdrrZDLaosFQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "10.46.0", + "@sentry/core": "10.46.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/rollup-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@sentry/rollup-plugin/-/rollup-plugin-5.1.1.tgz", + "integrity": "sha512-1d5NkdRR6aKWBP7czkY8sFFWiKnfmfRpQOj+m9bJTsyTjbMiEQJst6315w5pCVlRItPhBqpAraqAhutZFgvyVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "5.1.1", + "magic-string": "~0.30.8" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "rollup": ">=3.2.0" + } + }, + "node_modules/@sentry/vite-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-5.1.1.tgz", + "integrity": "sha512-i6NWUDi2SDikfSUeMJvJTRdwEKYSfTd+mvBO2Ja51S1YK+hnickBuDfD+RvPerIXLuyRu3GamgNPbNqgCGUg/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "5.1.1", + "@sentry/rollup-plugin": "5.1.1" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/@sinclair/typebox": { "version": "0.34.48", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", @@ -5152,6 +5506,19 @@ "dev": true, "license": "MIT" }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -6564,18 +6931,18 @@ } }, "node_modules/glob": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", - "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "minimatch": "^10.1.1", - "minipass": "^7.1.2", - "path-scurry": "^2.0.0" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -8269,11 +8636,11 @@ } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } @@ -8795,9 +9162,9 @@ "license": "MIT" }, "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -8805,16 +9172,16 @@ "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -9291,6 +9658,16 @@ "node": ">= 0.6.0" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/package.json b/package.json index da998cb2..759b361b 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "i18n:transform": "tsx scripts/i18nTransform.ts" }, "dependencies": { + "@sentry/react": "^10.46.0", "@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/react-query": "^5.90.20", "axios": "^1.13.4", @@ -44,6 +45,7 @@ "@babel/types": "^7.28.4", "@chromatic-com/storybook": "^3.2.2", "@eslint/js": "^9.15.0", + "@sentry/vite-plugin": "^5.1.1", "@storybook/addon-essentials": "^8.6.15", "@storybook/addon-interactions": "^8.6.15", "@storybook/addon-onboarding": "^8.6.15", From 751f55adbeaa8afe8e76a820b5bb6c18c2a5fc13 Mon Sep 17 00:00:00 2001 From: useon Date: Tue, 31 Mar 2026 17:14:23 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ErrorBoundary/ErrorBoundary.tsx | 9 ++++++- src/instrument.ts | 25 +++++++++++++++++++ src/main.tsx | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/instrument.ts diff --git a/src/components/ErrorBoundary/ErrorBoundary.tsx b/src/components/ErrorBoundary/ErrorBoundary.tsx index 84a8709d..e5fe407b 100644 --- a/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -1,4 +1,5 @@ import { Component, ErrorInfo, ReactNode } from 'react'; +import * as Sentry from '@sentry/react'; import ErrorPage from './ErrorPage'; interface ErrorBoundaryProps { @@ -31,7 +32,13 @@ class ErrorBoundary extends Component { } componentDidCatch(error: Error, errorInfo: ErrorInfo): void { - // You can also log the error to an error reporting service + // 렌더링 단계에서 잡힌 에러와 component stack을 함께 전송합니다. + Sentry.captureException(error, { + extra: { + componentStack: errorInfo.componentStack, + }, + }); + console.log(error, errorInfo); } diff --git a/src/instrument.ts b/src/instrument.ts new file mode 100644 index 00000000..f86fc78f --- /dev/null +++ b/src/instrument.ts @@ -0,0 +1,25 @@ +import * as Sentry from '@sentry/react'; + +const dsn = import.meta.env.VITE_SENTRY_DSN; + +if (import.meta.env.PROD && dsn) { + Sentry.init({ + dsn, + environment: import.meta.env.MODE, + integrations: [ + // 페이지 로드와 라우트 이동 등의 성능 흐름 추적 + Sentry.browserTracingIntegration(), + // 에러가 발생한 세션만 Replay로 남기고, 개인 정보 가림 + Sentry.replayIntegration({ + maskAllText: true, + blockAllMedia: true, + }), + ], + // 초기 도입 단계에서는 추적 데이터를 넉넉히 수집하고, 이후 필요 시 낮춤 + tracesSampleRate: 1.0, + // 일반 세션 Replay는 수집 X + replaysSessionSampleRate: 0, + // 에러가 발생한 세션은 모두 Replay로 남김 + replaysOnErrorSampleRate: 1.0, + }); +} diff --git a/src/main.tsx b/src/main.tsx index fdbb8fd6..548dd07c 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,3 +1,4 @@ +import './instrument'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { RouterProvider } from 'react-router-dom'; From 83f506dc20ece025ccadc90962f0b860d359e4cd Mon Sep 17 00:00:00 2001 From: useon Date: Tue, 31 Mar 2026 18:35:14 +0900 Subject: [PATCH 03/12] =?UTF-8?q?feat:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=8B=9D=EB=B3=84=20=EB=B0=8F=20?= =?UTF-8?q?API=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A7=91=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/apis/member.ts | 5 ++++ src/apis/axiosInstance.ts | 41 +++++++++++++++++++++++++++++++- src/hooks/mutations/useLogout.ts | 2 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/apis/apis/member.ts b/src/apis/apis/member.ts index 3b28e88c..fdbb21d8 100644 --- a/src/apis/apis/member.ts +++ b/src/apis/apis/member.ts @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/react'; import { setAccessToken } from '../../util/accessToken'; import { ApiUrl } from '../endpoints'; import { request } from '../primitives'; @@ -40,6 +41,10 @@ export async function postUser(code: string): Promise { throw new Error('Authorization 헤더가 존재하지 않습니다.'); } + Sentry.setUser({ + id: String(response.data.id), + }); + return response.data; } diff --git a/src/apis/axiosInstance.ts b/src/apis/axiosInstance.ts index d21d39ac..73498775 100644 --- a/src/apis/axiosInstance.ts +++ b/src/apis/axiosInstance.ts @@ -1,4 +1,5 @@ import axios from 'axios'; +import * as Sentry from '@sentry/react'; import { getAccessToken, removeAccessToken, @@ -13,12 +14,13 @@ import { // Get current mode (DEV, PROD or TEST) const currentMode = import.meta.env.MODE; +const requestTimeoutMs = 5000; // Axios instance export const axiosInstance = axios.create({ baseURL: currentMode === 'test' ? undefined : import.meta.env.VITE_API_BASE_URL, - timeout: 5000, + timeout: requestTimeoutMs, timeoutErrorMessage: '시간 초과로 인해 요청을 처리하지 못했어요... 잠시 후 다시 시도해 주세요.', headers: { @@ -38,6 +40,40 @@ axiosInstance.interceptors.request.use((config) => { return config; }); +function captureClientApiError(error: unknown) { + if (!axios.isAxiosError(error)) { + return; + } + + const { response, config, code } = error; + const status = response?.status; + + // 4xx 응답만 수집하고, 인증 재발급/서버 오류/네트워크 실패는 제외 + if (status === undefined || status === 401 || status < 400 || status >= 500) { + return; + } + + if (code === 'ECONNABORTED') { + return; + } + + Sentry.captureException(error, { + tags: { + errorType: 'api-client-error', + httpStatus: String(status), + }, + extra: { + url: config?.url, + method: config?.method, + baseURL: config?.baseURL, + params: config?.params, + requestData: config?.data, + responseData: response?.data, + timeout: config?.timeout ?? requestTimeoutMs, + }, + }); +} + // Response interceptor axiosInstance.interceptors.response.use( (response) => response, @@ -79,6 +115,9 @@ axiosInstance.interceptors.response.use( return Promise.reject(refreshError); } } + + captureClientApiError(error); + return Promise.reject(error); }, ); diff --git a/src/hooks/mutations/useLogout.ts b/src/hooks/mutations/useLogout.ts index 8ba7cc0f..cbcdfddf 100644 --- a/src/hooks/mutations/useLogout.ts +++ b/src/hooks/mutations/useLogout.ts @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/react'; import { useMutation } from '@tanstack/react-query'; import { logout } from '../../apis/apis/member'; import { removeAccessToken } from '../../util/accessToken'; @@ -10,6 +11,7 @@ export default function useLogout(onSuccess: () => void) { }, onSuccess: () => { removeAccessToken(); + Sentry.setUser(null); onSuccess(); }, }); From 85cbf15f29f9a566272a1c8029356e5df1b592d9 Mon Sep 17 00:00:00 2001 From: useon Date: Tue, 31 Mar 2026 20:46:03 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=EB=A7=B5=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/vite.config.ts b/vite.config.ts index 4489551d..c58a2ffc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,13 +1,35 @@ import { defineConfig as defineViteConfig, loadEnv, mergeConfig } from 'vite'; import { defineConfig as defineVitestConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; +import { sentryVitePlugin } from '@sentry/vite-plugin'; const viteConfig = defineViteConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ''); + const isProductionBuild = mode === 'production'; + const hasSentryAuth = + !!env.SENTRY_AUTH_TOKEN && !!env.SENTRY_ORG && !!env.SENTRY_PROJECT; + const plugins = [react()]; + + if (isProductionBuild && hasSentryAuth) { + plugins.push( + sentryVitePlugin({ + authToken: env.SENTRY_AUTH_TOKEN, + org: env.SENTRY_ORG, + project: env.SENTRY_PROJECT, + telemetry: false, + sourcemaps: { + filesToDeleteAfterUpload: 'dist/**/*.map', + }, + }), + ); + } return { base: env.VITE_BASE_PATH || '/', - plugins: [react()], + plugins, + build: { + sourcemap: isProductionBuild ? 'hidden' : false, + }, server: { proxy: { '/api': { From ef0dde51964312f2359ce2aa4459da5f508bb00f Mon Sep 17 00:00:00 2001 From: useon Date: Tue, 31 Mar 2026 21:46:11 +0900 Subject: [PATCH 05/12] =?UTF-8?q?chore:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20?= =?UTF-8?q?=ED=8A=B8=EB=A0=88=EC=9D=B4=EC=8B=B1=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/instrument.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/instrument.ts b/src/instrument.ts index f86fc78f..72579a0a 100644 --- a/src/instrument.ts +++ b/src/instrument.ts @@ -15,8 +15,8 @@ if (import.meta.env.PROD && dsn) { blockAllMedia: true, }), ], - // 초기 도입 단계에서는 추적 데이터를 넉넉히 수집하고, 이후 필요 시 낮춤 - tracesSampleRate: 1.0, + // 백엔드는 Datadog를 사용 중이므로, 프론트 단독 성능 추적만 낮은 비율로 수집 + tracesSampleRate: 0.1, // 일반 세션 Replay는 수집 X replaysSessionSampleRate: 0, // 에러가 발생한 세션은 모두 Replay로 남김 From b26c44dd64c706d3de7b89cecbc52f4cd1d07616 Mon Sep 17 00:00:00 2001 From: useon Date: Thu, 2 Apr 2026 01:34:18 +0900 Subject: [PATCH 06/12] =?UTF-8?q?refactor:=20=EC=84=BC=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=20API=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A7=91=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84=20=ED=99=95=EB=8C=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/axiosInstance.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/apis/axiosInstance.ts b/src/apis/axiosInstance.ts index 73498775..ef9c4bf5 100644 --- a/src/apis/axiosInstance.ts +++ b/src/apis/axiosInstance.ts @@ -48,19 +48,15 @@ function captureClientApiError(error: unknown) { const { response, config, code } = error; const status = response?.status; - // 4xx 응답만 수집하고, 인증 재발급/서버 오류/네트워크 실패는 제외 - if (status === undefined || status === 401 || status < 400 || status >= 500) { - return; - } - - if (code === 'ECONNABORTED') { + // 401 재발급 흐름과 정상/리다이렉트 응답만 제외하고, 4xx/5xx/네트워크 실패/타임아웃은 수집 + if (status === 401 || (status !== undefined && status < 400)) { return; } Sentry.captureException(error, { tags: { - errorType: 'api-client-error', - httpStatus: String(status), + errorType: 'api-error', + httpStatus: status ? String(status) : 'network-error', }, extra: { url: config?.url, @@ -70,6 +66,7 @@ function captureClientApiError(error: unknown) { requestData: config?.data, responseData: response?.data, timeout: config?.timeout ?? requestTimeoutMs, + errorCode: code, }, }); } @@ -106,6 +103,14 @@ axiosInstance.interceptors.response.use( originalRequest.headers.Authorization = `${newAccessToken}`; return axiosInstance(originalRequest); } catch (refreshError) { + if ( + axios.isAxiosError(refreshError) && + refreshError.response?.status !== 401 && + refreshError.response?.status !== 403 + ) { + captureClientApiError(refreshError); + } + console.error('Refresh Token is invalid or expired', refreshError); // 재발급도 실패하면 -> 로그인 페이지 이동 const currentLang = i18n.resolvedLanguage ?? i18n.language; From 7530fdb9850986b5771d0ad1725d2780571cd544 Mon Sep 17 00:00:00 2001 From: useon Date: Thu, 2 Apr 2026 04:13:10 +0900 Subject: [PATCH 07/12] =?UTF-8?q?refactor:=20=EC=84=BC=ED=8A=B8=EB=A6=AC?= =?UTF-8?q?=20API/=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=BA=A1=EC=B2=98=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=A0=84=EC=86=A1=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/axiosInstance.ts | 8 +++++++ src/apis/primitives.ts | 8 +++++++ .../ErrorBoundary/ErrorBoundary.tsx | 23 ++++++++++++++----- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/apis/axiosInstance.ts b/src/apis/axiosInstance.ts index ef9c4bf5..3425881d 100644 --- a/src/apis/axiosInstance.ts +++ b/src/apis/axiosInstance.ts @@ -16,6 +16,10 @@ import { const currentMode = import.meta.env.MODE; const requestTimeoutMs = 5000; +type SentryCapturedError = { + __sentry_captured__?: boolean; +}; + // Axios instance export const axiosInstance = axios.create({ baseURL: @@ -59,6 +63,8 @@ function captureClientApiError(error: unknown) { httpStatus: status ? String(status) : 'network-error', }, extra: { + pathname: window.location.pathname, + search: window.location.search, url: config?.url, method: config?.method, baseURL: config?.baseURL, @@ -69,6 +75,8 @@ function captureClientApiError(error: unknown) { errorCode: code, }, }); + + (error as SentryCapturedError).__sentry_captured__ = true; } // Response interceptor diff --git a/src/apis/primitives.ts b/src/apis/primitives.ts index e4bf1c13..8dc4b715 100644 --- a/src/apis/primitives.ts +++ b/src/apis/primitives.ts @@ -9,6 +9,7 @@ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; export class APIError extends Error { public readonly status: number; public readonly data: unknown; + public __sentry_captured__?: boolean; constructor(message: string, status: number, data: unknown) { super(message); @@ -18,6 +19,10 @@ export class APIError extends Error { } } +type SentryCapturedError = { + __sentry_captured__?: boolean; +}; + // Low-level http request function export async function request( method: HttpMethod, @@ -54,6 +59,9 @@ export async function request( error.response?.status || 500, responseData, ); + apiError.__sentry_captured__ = ( + error as SentryCapturedError + ).__sentry_captured__; throw apiError; } diff --git a/src/components/ErrorBoundary/ErrorBoundary.tsx b/src/components/ErrorBoundary/ErrorBoundary.tsx index e5fe407b..b3070b29 100644 --- a/src/components/ErrorBoundary/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -15,6 +15,10 @@ interface ErrorBoundaryState { const defaultError = new Error('알 수 없는 오류'); const defaultStack = '스택 정보 없음'; +type SentryCapturedError = { + __sentry_captured__?: boolean; +}; + class ErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); @@ -32,12 +36,19 @@ class ErrorBoundary extends Component { } componentDidCatch(error: Error, errorInfo: ErrorInfo): void { - // 렌더링 단계에서 잡힌 에러와 component stack을 함께 전송합니다. - Sentry.captureException(error, { - extra: { - componentStack: errorInfo.componentStack, - }, - }); + // 이미 API 인터셉터 등에서 캡처된 에러가 아니라면 전송 + if (!(error as SentryCapturedError).__sentry_captured__) { + Sentry.captureException(error, { + tags: { + errorType: 'render-error', + }, + extra: { + pathname: window.location.pathname, + search: window.location.search, + componentStack: errorInfo.componentStack, + }, + }); + } console.log(error, errorInfo); } From d4ad68bf1cd1eed0039b1909b57f1fbcf303ac30 Mon Sep 17 00:00:00 2001 From: useon Date: Thu, 2 Apr 2026 04:26:04 +0900 Subject: [PATCH 08/12] =?UTF-8?q?fix:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A1=B0=EA=B1=B4=20=EC=97=86=EC=9D=B4=20?= =?UTF-8?q?=EC=86=8C=EC=8A=A4=EB=A7=B5=20=EC=83=9D=EC=84=B1=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vite.config.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index c58a2ffc..a37f05c4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,9 +8,10 @@ const viteConfig = defineViteConfig(({ mode }) => { const isProductionBuild = mode === 'production'; const hasSentryAuth = !!env.SENTRY_AUTH_TOKEN && !!env.SENTRY_ORG && !!env.SENTRY_PROJECT; + const shouldUploadSourcemaps = isProductionBuild && hasSentryAuth; const plugins = [react()]; - if (isProductionBuild && hasSentryAuth) { + if (shouldUploadSourcemaps) { plugins.push( sentryVitePlugin({ authToken: env.SENTRY_AUTH_TOKEN, @@ -28,7 +29,7 @@ const viteConfig = defineViteConfig(({ mode }) => { base: env.VITE_BASE_PATH || '/', plugins, build: { - sourcemap: isProductionBuild ? 'hidden' : false, + sourcemap: shouldUploadSourcemaps ? 'hidden' : false, }, server: { proxy: { From a9e7356f1797999fc3540238be501245503cee12 Mon Sep 17 00:00:00 2001 From: useon Date: Thu, 2 Apr 2026 04:29:40 +0900 Subject: [PATCH 09/12] =?UTF-8?q?fix:=20=EC=84=BC=ED=8A=B8=EB=A6=AC=20API?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A7=91=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=AF=BC=EA=B0=90=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD/=EC=9D=91=EB=8B=B5=20=EB=B0=94=EB=94=94=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/axiosInstance.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apis/axiosInstance.ts b/src/apis/axiosInstance.ts index 3425881d..0e0b9e57 100644 --- a/src/apis/axiosInstance.ts +++ b/src/apis/axiosInstance.ts @@ -69,8 +69,6 @@ function captureClientApiError(error: unknown) { method: config?.method, baseURL: config?.baseURL, params: config?.params, - requestData: config?.data, - responseData: response?.data, timeout: config?.timeout ?? requestTimeoutMs, errorCode: code, }, From 0c4d0444ddfc664681d5e104482eccd795465124 Mon Sep 17 00:00:00 2001 From: useon Date: Thu, 2 Apr 2026 04:32:37 +0900 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20=EC=84=BC?= =?UTF-8?q?=ED=8A=B8=EB=A6=AC=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/axiosInstance.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apis/axiosInstance.ts b/src/apis/axiosInstance.ts index 0e0b9e57..6e052ae7 100644 --- a/src/apis/axiosInstance.ts +++ b/src/apis/axiosInstance.ts @@ -121,6 +121,7 @@ axiosInstance.interceptors.response.use( // 재발급도 실패하면 -> 로그인 페이지 이동 const currentLang = i18n.resolvedLanguage ?? i18n.language; const lang = isSupportedLang(currentLang) ? currentLang : DEFAULT_LANG; + Sentry.setUser(null); window.location.href = buildLangPath('/home', lang); removeAccessToken(); return Promise.reject(refreshError); From d787969f4ae563fc8557c7dfd391f0bab4de376e Mon Sep 17 00:00:00 2001 From: useon Date: Fri, 24 Apr 2026 10:20:20 +0900 Subject: [PATCH 11/12] =?UTF-8?q?fix:=20=EB=A6=B0=ED=8A=B8=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=A0=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/page/TableSharingPage/TableSharingPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/page/TableSharingPage/TableSharingPage.tsx b/src/page/TableSharingPage/TableSharingPage.tsx index e0642b8e..356d7b7e 100644 --- a/src/page/TableSharingPage/TableSharingPage.tsx +++ b/src/page/TableSharingPage/TableSharingPage.tsx @@ -116,7 +116,7 @@ export default function TableSharingPage() { }, ); } - }, [decodedData, navigate, openModal, closeModal, encodedData, lang]); + }, [decodedData, navigate, openModal, closeModal, encodedData, lang, t]); return ( <> From 9e31682d65fdda5bf0ab6d68e5bd5ba0e1ff318b Mon Sep 17 00:00:00 2001 From: useon Date: Fri, 24 Apr 2026 10:23:19 +0900 Subject: [PATCH 12/12] =?UTF-8?q?chore:=20sentry=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EB=B0=98=EC=98=81=20=EB=B0=8F=20lockfile=20?= =?UTF-8?q?=EB=8F=99=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 115 ++++++++++++++++++++++++++-------------------- package.json | 4 +- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/package-lock.json b/package-lock.json index 476b4311..7bbf7a21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "frontend", "version": "0.0.0", "dependencies": { + "@sentry/react": "^10.50.0", "@stomp/stompjs": "^7.3.0", "@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/react-query": "^5.90.20", @@ -35,7 +36,7 @@ "@babel/types": "^7.28.4", "@chromatic-com/storybook": "^3.2.2", "@eslint/js": "^9.15.0", - "@sentry/vite-plugin": "^5.1.1", + "@sentry/vite-plugin": "^5.2.0", "@storybook/addon-essentials": "^8.6.15", "@storybook/addon-interactions": "^8.6.15", "@storybook/addon-onboarding": "^8.6.15", @@ -2367,59 +2368,59 @@ "license": "MIT" }, "node_modules/@sentry-internal/browser-utils": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.46.0.tgz", - "integrity": "sha512-WB1gBT9G13V02ekZ6NpUhoI1aGHV2eNfjEPthkU2bGBvFpQKnstwzjg7waIRGR7cu+YSW2Q6UI6aQLgBeOPD1g==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.50.0.tgz", + "integrity": "sha512-42bxyRTxnCmYlWnvz4CxikuQNanw8UNma2WJrtxJ0f1MAJV2GhQGSHDLnA+lvFlmiz6qct3pfen/NXGyOTegTA==", "license": "MIT", "dependencies": { - "@sentry/core": "10.46.0" + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/feedback": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.46.0.tgz", - "integrity": "sha512-c4pI/z9nZCQXe9GYEw/hE/YTY9AxGBp8/wgKI+T8zylrN35SGHaXv63szzE1WbI8lacBY8lBF7rstq9bQVCaHw==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.50.0.tgz", + "integrity": "sha512-0k9XZF0wn86f77mIO2U3gNNyDZooy139CnEanRzHinrN106vVzvBZ6TUEQoHtoO1fqQxr+nWWVrqV/PXUqk47w==", "license": "MIT", "dependencies": { - "@sentry/core": "10.46.0" + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.46.0.tgz", - "integrity": "sha512-JBsWeXG6bRbxBFK8GzWymWGOB9QE7Kl57BeF3jzgdHTuHSWZ2mRnAmb1K05T4LU+gVygk6yW0KmdC8Py9Qzg9A==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.50.0.tgz", + "integrity": "sha512-51FYNfnvVLAWw1rrEWPFfwHuMRb9mkVCFGA4J9/un7SpeGBsQDziGB0Di4fsCxI7+EdSBpfLHPF0csKtCCw0oQ==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.46.0", - "@sentry/core": "10.46.0" + "@sentry-internal/browser-utils": "10.50.0", + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.46.0.tgz", - "integrity": "sha512-ub314MWUsekVCuoH0/HJbbimlI24SkV745UW2pj9xRbxOAEf1wjkmIzxKrMDbTgJGuEunug02XZVdJFJUzOcDw==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.50.0.tgz", + "integrity": "sha512-jx6RKBmcJSWdI92qDGS/sBv1w+7Cww879Z/moX7bw7ipHa/Ts3iDcB3rgZwvhmi17U+mvYsbJeL2DXkPo3TjPw==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "10.46.0", - "@sentry/core": "10.46.0" + "@sentry-internal/replay": "10.50.0", + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.1.1.tgz", - "integrity": "sha512-x2wEpBHwsTyTF2rWsLKJlzrRF1TTIGOfX+ngdE+Yd5DBkoS58HwQv824QOviPGQRla4/ypISqAXzjdDPL/zalg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.2.0.tgz", + "integrity": "sha512-8LbOI5Kzb5F0+7LVQPi2+zGz1iPiRRFhM+7uZ/ZQ33L9BmDOYNIy3xWxCfMw2JCuMXXaxF47XCjGmR22/B0WPg==", "dev": true, "license": "MIT", "engines": { @@ -2427,30 +2428,30 @@ } }, "node_modules/@sentry/browser": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.46.0.tgz", - "integrity": "sha512-80DmGlTk5Z2/OxVOzLNxwolMyouuAYKqG8KUcoyintZqHbF6kO1RulI610HmyUt3OagKeBCqt9S7w0VIfCRL+Q==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.50.0.tgz", + "integrity": "sha512-1f6rAvET6myiTaSeYqvaaBwvq1LfxqWjAPIoAW/NVC9bPMkeEcuvgDajHrnZMrBeWoJ81NMyoLkyX+iOc7MoFA==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.46.0", - "@sentry-internal/feedback": "10.46.0", - "@sentry-internal/replay": "10.46.0", - "@sentry-internal/replay-canvas": "10.46.0", - "@sentry/core": "10.46.0" + "@sentry-internal/browser-utils": "10.50.0", + "@sentry-internal/feedback": "10.50.0", + "@sentry-internal/replay": "10.50.0", + "@sentry-internal/replay-canvas": "10.50.0", + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/bundler-plugin-core": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-5.1.1.tgz", - "integrity": "sha512-F+itpwR9DyQR7gEkrXd2tigREPTvtF5lC8qu6e4anxXYRTui1+dVR0fXNwjpyAZMhIesLfXRN7WY7ggdj7hi0Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-5.2.0.tgz", + "integrity": "sha512-+C0x4gEIJRgoMwyRFGx+TFiJ1Po2BZlT1v61+PnouiaprKL5qtZG8n5PXx/5LPLDsVjSIcXjnDrTz9aSm8SJ3w==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "5.1.1", + "@sentry/babel-plugin-component-annotate": "5.2.0", "@sentry/cli": "^2.58.5", "dotenv": "^16.3.1", "find-up": "^5.0.0", @@ -2662,23 +2663,30 @@ "node": ">= 6" } }, + "node_modules/@sentry/cli/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, "node_modules/@sentry/core": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.46.0.tgz", - "integrity": "sha512-N3fj4zqBQOhXliS1Ne9euqIKuciHCGOJfPGQLwBoW9DNz03jF+NB8+dUKtrJ79YLoftjVgf8nbgwtADK7NR+2Q==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.50.0.tgz", + "integrity": "sha512-J4A+vzUO3adl0TkFCjaN1+4miamrjHiEIYuLHiuu1lmAjq5WIVw32ObvAh4yMwNtxyaEMosTrrh5M6f12XSJFg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "10.46.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.46.0.tgz", - "integrity": "sha512-Rb1S+9OuUPVwsz7GWnQ6Kgf3azbsseUymIegg3JZHNcW/fM1nPpaljzTBnuineia113DH0pgMBcdrrZDLaosFQ==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.50.0.tgz", + "integrity": "sha512-MZHYjEZAtFIa4zPrWS4oXlo+gMppRvfETqUqF920Sj2jN2U7WjboU03lDmjfDqEcH7QiwjQyl13jHd2nwAyrrw==", "license": "MIT", "dependencies": { - "@sentry/browser": "10.46.0", - "@sentry/core": "10.46.0" + "@sentry/browser": "10.50.0", + "@sentry/core": "10.50.0" }, "engines": { "node": ">=18" @@ -2688,13 +2696,13 @@ } }, "node_modules/@sentry/rollup-plugin": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@sentry/rollup-plugin/-/rollup-plugin-5.1.1.tgz", - "integrity": "sha512-1d5NkdRR6aKWBP7czkY8sFFWiKnfmfRpQOj+m9bJTsyTjbMiEQJst6315w5pCVlRItPhBqpAraqAhutZFgvyVg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@sentry/rollup-plugin/-/rollup-plugin-5.2.0.tgz", + "integrity": "sha512-a8LfpvcYMFtFSroro5MpCcOoS528LeLfUHzxWURnpofOnY+Aso9Si4y4dFlna+RKqxCXjmFbn6CLnfI+YrHysQ==", "dev": true, "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "5.1.1", + "@sentry/bundler-plugin-core": "5.2.0", "magic-string": "~0.30.8" }, "engines": { @@ -2702,17 +2710,22 @@ }, "peerDependencies": { "rollup": ">=3.2.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, "node_modules/@sentry/vite-plugin": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-5.1.1.tgz", - "integrity": "sha512-i6NWUDi2SDikfSUeMJvJTRdwEKYSfTd+mvBO2Ja51S1YK+hnickBuDfD+RvPerIXLuyRu3GamgNPbNqgCGUg/Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-5.2.0.tgz", + "integrity": "sha512-4Jo3ixBspso5HY81PDvZdRXkH9wYGVmcw/0a2IX9ejbyKBdHqkYg4IhAtNqGUAyGuHwwRS9Y1S+sCMvrXv6htw==", "dev": true, "license": "MIT", "dependencies": { - "@sentry/bundler-plugin-core": "5.1.1", - "@sentry/rollup-plugin": "5.1.1" + "@sentry/bundler-plugin-core": "5.2.0", + "@sentry/rollup-plugin": "5.2.0" }, "engines": { "node": ">= 18" diff --git a/package.json b/package.json index 0222c084..3f5d74bc 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "i18n:transform": "tsx scripts/i18nTransform.ts" }, "dependencies": { + "@sentry/react": "^10.50.0", "@stomp/stompjs": "^7.3.0", - "@sentry/react": "^10.46.0", "@tanstack/eslint-plugin-query": "^5.91.4", "@tanstack/react-query": "^5.90.20", "axios": "^1.13.4", @@ -47,7 +47,7 @@ "@babel/types": "^7.28.4", "@chromatic-com/storybook": "^3.2.2", "@eslint/js": "^9.15.0", - "@sentry/vite-plugin": "^5.1.1", + "@sentry/vite-plugin": "^5.2.0", "@storybook/addon-essentials": "^8.6.15", "@storybook/addon-interactions": "^8.6.15", "@storybook/addon-onboarding": "^8.6.15",