From b65c50c5f9982f0d3d230b3a2192e6a65c294a0b Mon Sep 17 00:00:00 2001 From: jangwoong Date: Wed, 8 Jul 2026 16:41:08 +0900 Subject: [PATCH] =?UTF-8?q?[cs=20frontend]=20sentry=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/instrumentation-client.ts | 13 ++++++++++++ apps/cs/instrumentation.ts | 13 ++++++++++++ apps/cs/next.config.ts | 15 +++++++++++++- apps/cs/package.json | 1 + apps/cs/sentry.edge.config.ts | 8 ++++++++ apps/cs/sentry.server.config.ts | 8 ++++++++ .../cs/src/entities/menu/lib/menu-wrapper.tsx | 20 +++++++++++-------- 7 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 apps/cs/instrumentation-client.ts create mode 100644 apps/cs/instrumentation.ts create mode 100644 apps/cs/sentry.edge.config.ts create mode 100644 apps/cs/sentry.server.config.ts diff --git a/apps/cs/instrumentation-client.ts b/apps/cs/instrumentation-client.ts new file mode 100644 index 000000000..07509aaa4 --- /dev/null +++ b/apps/cs/instrumentation-client.ts @@ -0,0 +1,13 @@ +import * as Sentry from "@sentry/nextjs"; + +export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? "local", + tracesSampleRate: 1.0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 1.0, + integrations: [Sentry.replayIntegration()], + debug: process.env.NEXT_PUBLIC_SENTRY_DEBUG === "true", +}); diff --git a/apps/cs/instrumentation.ts b/apps/cs/instrumentation.ts new file mode 100644 index 000000000..7cbe93c13 --- /dev/null +++ b/apps/cs/instrumentation.ts @@ -0,0 +1,13 @@ +import * as Sentry from "@sentry/nextjs"; + +export async function register() { + if (process.env.NEXT_RUNTIME === "nodejs") { + await import("./sentry.server.config"); + } + + if (process.env.NEXT_RUNTIME === "edge") { + await import("./sentry.edge.config"); + } +} + +export const onRequestError = Sentry.captureRequestError; diff --git a/apps/cs/next.config.ts b/apps/cs/next.config.ts index 61d7f72cc..11d8237c7 100644 --- a/apps/cs/next.config.ts +++ b/apps/cs/next.config.ts @@ -1,4 +1,5 @@ import type { NextConfig } from "next"; +import { withSentryConfig } from "@sentry/nextjs"; const subDomain = process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000"; @@ -58,4 +59,16 @@ const nextConfig: NextConfig = { }, }; -export default nextConfig; +export default withSentryConfig(nextConfig, { + org: process.env.SENTRY_ORG, + project: process.env.SENTRY_PROJECT, + silent: true, + widenClientFileUpload: true, + tunnelRoute: "/monitoring", + webpack: { + treeshake: { + removeDebugLogging: process.env.NEXT_PUBLIC_SENTRY_DEBUG === "true" ? false : true, + }, + automaticVercelMonitors: false, + }, +}); diff --git a/apps/cs/package.json b/apps/cs/package.json index 9d128263a..5bc498b88 100644 --- a/apps/cs/package.json +++ b/apps/cs/package.json @@ -27,6 +27,7 @@ "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.8", + "@sentry/nextjs": "^10.57.0", "@tanstack/react-query": "^5.75.5", "@tanstack/react-query-devtools": "^5.75.5", "@tanstack/react-table": "^8.21.2", diff --git a/apps/cs/sentry.edge.config.ts b/apps/cs/sentry.edge.config.ts new file mode 100644 index 000000000..436630178 --- /dev/null +++ b/apps/cs/sentry.edge.config.ts @@ -0,0 +1,8 @@ +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? "local", + tracesSampleRate: 1.0, + debug: process.env.NEXT_PUBLIC_SENTRY_DEBUG === "true", +}); diff --git a/apps/cs/sentry.server.config.ts b/apps/cs/sentry.server.config.ts new file mode 100644 index 000000000..436630178 --- /dev/null +++ b/apps/cs/sentry.server.config.ts @@ -0,0 +1,8 @@ +import * as Sentry from "@sentry/nextjs"; + +Sentry.init({ + dsn: process.env.NEXT_PUBLIC_SENTRY_DSN, + environment: process.env.NEXT_PUBLIC_SENTRY_ENVIRONMENT ?? "local", + tracesSampleRate: 1.0, + debug: process.env.NEXT_PUBLIC_SENTRY_DEBUG === "true", +}); diff --git a/apps/cs/src/entities/menu/lib/menu-wrapper.tsx b/apps/cs/src/entities/menu/lib/menu-wrapper.tsx index 1f1080cac..d09801dac 100644 --- a/apps/cs/src/entities/menu/lib/menu-wrapper.tsx +++ b/apps/cs/src/entities/menu/lib/menu-wrapper.tsx @@ -2,9 +2,10 @@ import { useEffect } from "react"; import { usePathname, useRouter } from "next/navigation"; +import { useQuery } from "@tanstack/react-query"; import { MenuAuthorityApi } from "@/entities/menu-authority/@x/menu"; import { getCookie, useAlertStore, useMenuStore } from "@/shared/lib"; -import { SITE_ID } from "@/shared/config"; +import { SITE_ID, ENDPOINT } from "@/shared/config"; import { MenuApi } from "../api/menu-service"; import { getCurrentMenu } from "./utils"; @@ -16,11 +17,10 @@ const MenuWrapper = ({ children }: { children: React.ReactNode }) => { const { pageMenuAuthority, setCurrentMenuInfo, setPageMenuAuthority } = useMenuStore((state) => state); - const getCurrentMenuInfo = async () => { - const menuRoles = await MenuApi.getMenuRoles(SITE_ID); - if (!menuRoles) return; - return getCurrentMenu(menuRoles, pathname ?? ""); - }; + const { data: menuRoles } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES], + queryFn: () => MenuApi.getMenuRoles(SITE_ID), + }); const getPageMenuAuthority = async () => { const menuCd = getCookie("menu-code-key"); @@ -36,10 +36,14 @@ const MenuWrapper = ({ children }: { children: React.ReactNode }) => { }; useEffect(() => { - (async () => { - const currentMenu = await getCurrentMenuInfo(); + if (menuRoles) { + const currentMenu = getCurrentMenu(menuRoles, pathname ?? ""); if (currentMenu) setCurrentMenuInfo(currentMenu); + } + }, [menuRoles, pathname]); + useEffect(() => { + (async () => { const response = await getPageMenuAuthority(); if (response?.length) setPageMenuAuthority(response[0]!); })();