diff --git a/apps/as/app/api/proxy/[...url]/route.ts b/apps/as/app/api/proxy/[...url]/route.ts index b32008942..d54f08656 100644 --- a/apps/as/app/api/proxy/[...url]/route.ts +++ b/apps/as/app/api/proxy/[...url]/route.ts @@ -68,7 +68,7 @@ async function handler( cookieStore.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, sameSite: "strict", - domain: getCookieDomain(), + domain: COOKIE_DOMAIN, path: "/", }); } @@ -92,14 +92,3 @@ export async function PUT(request: Request, props: { params: Promise<{ url: stri const params = await props.params; return handler(request, params, "PUT"); } - -function getCookieDomain(): string | undefined { - if (typeof window === "undefined") return undefined; - - if (COOKIE_DOMAIN) return COOKIE_DOMAIN; - - const { hostname } = window.location; - if (hostname === "localhost" || hostname === "127.0.0.1") return undefined; - - return hostname; -} diff --git a/apps/as/next.config.ts b/apps/as/next.config.ts index 8864de0e7..d3afd4d70 100644 --- a/apps/as/next.config.ts +++ b/apps/as/next.config.ts @@ -1,6 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { + output: "standalone", reactStrictMode: true, transpilePackages: ["@common/assets"], }; diff --git a/apps/cm/app/api/proxy/[...url]/route.ts b/apps/cm/app/api/proxy/[...url]/route.ts index c0f646cd2..57cfc86e8 100644 --- a/apps/cm/app/api/proxy/[...url]/route.ts +++ b/apps/cm/app/api/proxy/[...url]/route.ts @@ -2,6 +2,7 @@ import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, + COOKIE_DOMAIN, REFRESH_TOKEN, SERVER_API_URL, SITE_ID, @@ -135,6 +136,7 @@ async function handler( cookieStore.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, sameSite: "lax", + domain: COOKIE_DOMAIN, path: "/", }); } diff --git a/apps/cs/app/api/proxy/[...url]/route.ts b/apps/cs/app/api/proxy/[...url]/route.ts index 4385956d3..16185ba1d 100644 --- a/apps/cs/app/api/proxy/[...url]/route.ts +++ b/apps/cs/app/api/proxy/[...url]/route.ts @@ -70,7 +70,7 @@ async function handler( response.cookies.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, sameSite: "strict", - domain: getCookieDomain(), + domain: COOKIE_DOMAIN, path: "/", }); } @@ -105,14 +105,3 @@ export async function PUT( const params = await props.params; return handler(request, params, "PUT"); } - -function getCookieDomain(): string | undefined { - if (typeof window === "undefined") return undefined; - - if (COOKIE_DOMAIN) return COOKIE_DOMAIN; - - const { hostname } = window.location; - if (hostname === "localhost" || hostname === "127.0.0.1") return undefined; - - return hostname; -} diff --git a/apps/cs/middleware.ts b/apps/cs/middleware.ts index 98b741325..adc6077b9 100644 --- a/apps/cs/middleware.ts +++ b/apps/cs/middleware.ts @@ -41,7 +41,7 @@ export function middleware(req: NextRequest) { logMessages.push(` Rewritten URL: ${newUrl}`); logMessages.push("\n--------------------------------\n"); - // console.log(logMessages.join("\n")); + console.log(logMessages.join("\n")); const response = NextResponse.rewrite(new URL(newUrl)); return addSecurityHeaders(response); @@ -58,7 +58,7 @@ export function middleware(req: NextRequest) { logMessages.push(` Rewritten URL: ${newUrl}`); logMessages.push("\n--------------------------------\n"); - // console.log(logMessages.join("\n")); + console.log(logMessages.join("\n")); const response = NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, @@ -83,7 +83,7 @@ export function middleware(req: NextRequest) { logMessages.push(` Link API Rewritten URL: ${newUrl}`); logMessages.push("\n--------------------------------\n"); - // console.log(logMessages.join("\n")); + console.log(logMessages.join("\n")); const response = NextResponse.rewrite(new URL(newUrl), { headers: requestHeaders, @@ -97,7 +97,7 @@ export function middleware(req: NextRequest) { } logMessages.push("\n--------------------------------\n"); - // console.log(logMessages.join("\n")); + console.log(logMessages.join("\n")); const response = NextResponse.next(); return addSecurityHeaders(response); diff --git a/apps/cs/next.config.ts b/apps/cs/next.config.ts index 61d7f72cc..827d37753 100644 --- a/apps/cs/next.config.ts +++ b/apps/cs/next.config.ts @@ -18,7 +18,7 @@ const nextConfig: NextConfig = { fetches: { fullUrl: true, }, - }, + }, async headers() { return [ { diff --git a/apps/st/app/api/proxy/[...url]/route.ts b/apps/st/app/api/proxy/[...url]/route.ts index 261d6b259..8d2ce62dc 100644 --- a/apps/st/app/api/proxy/[...url]/route.ts +++ b/apps/st/app/api/proxy/[...url]/route.ts @@ -5,6 +5,7 @@ import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, + COOKIE_DOMAIN, REFRESH_TOKEN, SERVER_API_URL, SITE_ID, @@ -75,6 +76,7 @@ async function handler( cookieStore.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, sameSite: "lax", + domain: COOKIE_DOMAIN, path: "/", }); } diff --git a/apps/st/next.config.ts b/apps/st/next.config.ts index a0adf6946..743a29bdd 100644 --- a/apps/st/next.config.ts +++ b/apps/st/next.config.ts @@ -1,47 +1,47 @@ import type { NextConfig } from "next"; const subDomain = - process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000"; + process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000"; const nextConfig: NextConfig = { - // output: "standalone", - async headers() { - return [ - { - source: "/(.*)", - headers: [ - { - key: "Content-Security-Policy", - value: "img-src 'self' data: https: blob:;", - }, - ], - }, - ]; - }, - async rewrites() { - return { - beforeFiles: [ - { - source: "/_next/static/:path*", - destination: `${subDomain}/_next/static/:path*`, - has: [ + output: "standalone", + async headers() { + return [ { - type: "header", - key: "referer", - value: "(.*)/cms(.*)", + source: "/(.*)", + headers: [ + { + key: "Content-Security-Policy", + value: "img-src 'self' data: https: blob:;", + }, + ], }, - ], - }, - ], - afterFiles: [ - { - source: "/cms/:path*", - destination: `${subDomain}/cms/:path*`, - }, - ], - fallback: [], - }; - }, + ]; + }, + async rewrites() { + return { + beforeFiles: [ + { + source: "/_next/static/:path*", + destination: `${subDomain}/_next/static/:path*`, + has: [ + { + type: "header", + key: "referer", + value: "(.*)/cms(.*)", + }, + ], + }, + ], + afterFiles: [ + { + source: "/cms/:path*", + destination: `${subDomain}/cms/:path*`, + }, + ], + fallback: [], + }; + }, }; export default nextConfig; diff --git a/apps/st/src/pages/statistics/ui/panels/schedule-info-panel.tsx b/apps/st/src/pages/statistics/ui/panels/schedule-info-panel.tsx index 6a5e3602d..b678099d3 100644 --- a/apps/st/src/pages/statistics/ui/panels/schedule-info-panel.tsx +++ b/apps/st/src/pages/statistics/ui/panels/schedule-info-panel.tsx @@ -84,7 +84,7 @@ export function ScheduleInfoPanel({ params }: ScheduleInfoPanelProps) {
- {data.inptSeCd}차 입력기간 + 입력기간

{dayjs(data.inptBgngYmd).format( @@ -102,7 +102,7 @@ export function ScheduleInfoPanel({ params }: ScheduleInfoPanelProps) { color="gray" className="font-semibold" > - {data.vrfcSeCd}차 검증기간 + 검증기간

{dayjs(data.vrfcBgngYmd).format( diff --git a/packages/common/components/src/api/banner.ts b/packages/common/components/src/api/banner.ts index 8d9962529..330431c39 100644 --- a/packages/common/components/src/api/banner.ts +++ b/packages/common/components/src/api/banner.ts @@ -1,35 +1,31 @@ -import { getApiClient } from "./client"; import { getConfig } from "@common/config"; import { ENDPOINT } from "../config"; +import { getAuthHeaders } from "../lib/auth-header"; export interface Banner { - bnrSn: number; - bnrTypeCd: string; - bnrTypeNm: string; - bnrTtl: string; - lnkgUrlAddr: string; - useYn: string; - atflCd: string; - mdfcnDt: string; - mdfr: string; - mdfrNm: string; - } + bnrSn: number; + bnrTypeCd: string; + bnrTypeNm: string; + bnrTtl: string; + lnkgUrlAddr: string; + useYn: string; + atflCd: string; + mdfcnDt: string; + mdfr: string; + mdfrNm: string; +} +const { PROXY_HOST } = getConfig(); +const BASE_URL = `${PROXY_HOST}/server`; - const { PROXY_HOST } = getConfig(); - const BASE_URL = `${PROXY_HOST}/server`; - -const client = getApiClient(); - -export const getBannerList = async (siteId: string) => { - const response = await client.get( +export const getBannerList = async (siteId: string): Promise => { + const response = await fetch( `${BASE_URL}${ENDPOINT.CMS_SERVICE.BANNERS}/${siteId}`, { method: "GET", - headers: { - "Content-Type": "application/json", - }, + headers: getAuthHeaders(), + credentials: "include", }, ); - return response.data; + return response.json(); }; diff --git a/packages/common/components/src/api/menu.ts b/packages/common/components/src/api/menu.ts index b4d84c95e..ee9e74357 100644 --- a/packages/common/components/src/api/menu.ts +++ b/packages/common/components/src/api/menu.ts @@ -1,4 +1,4 @@ -import { getApiClient } from "./client"; +import { getAuthHeaders } from "../lib/auth-header"; import { ENDPOINT } from "../config"; import { getConfig } from "@common/config"; @@ -27,22 +27,33 @@ export interface TreeMenu extends MenuItem { menuHlpCn: string; } -const client = getApiClient(); const { PROXY_HOST } = getConfig(); const BASE_URL = `${PROXY_HOST}/server`; -export const getMenuList = async (siteId: string) => { - const response = await client.get( - `${ENDPOINT.CMS_SERVICE.MENU_ROLES}/${siteId}`, +export const getMenuList = async (siteId: string): Promise => { + const response = await fetch( + `${BASE_URL}${ENDPOINT.CMS_SERVICE.MENU_ROLES}/${siteId}`, + { + method: "GET", + headers: getAuthHeaders(), + credentials: "include", + }, ); - return response.data; + return response.json(); }; -export const getPreviewTreeMenuList = async (siteId: string) => { - const response = await client.get( - `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree/preview`, +export const getPreviewTreeMenuList = async ( + siteId: string, +): Promise => { + const response = await fetch( + `${BASE_URL}${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree/preview`, + { + method: "GET", + headers: getAuthHeaders(), + credentials: "include", + }, ); - return response.data; + return response.json(); }; export const getAnonymouseMenuList = async ( @@ -52,9 +63,8 @@ export const getAnonymouseMenuList = async ( `${BASE_URL}${ENDPOINT.CMS_SERVICE.MENU_ANONYMOUS}/user/${siteId}`, { method: "GET", - headers: { - "Content-Type": "application/json", - }, + headers: getAuthHeaders(), + credentials: "include", }, ); return response.json(); diff --git a/packages/common/components/src/api/site.ts b/packages/common/components/src/api/site.ts index bfe0f3275..56f8a7c30 100644 --- a/packages/common/components/src/api/site.ts +++ b/packages/common/components/src/api/site.ts @@ -1,6 +1,6 @@ -import { getApiClient } from "./client"; import { getConfig } from "@common/config"; import { ENDPOINT } from "../config"; +import { getAuthHeaders } from "../lib/auth-header"; export interface SiteInfo { siteId: string; @@ -62,25 +62,18 @@ export const getSiteInfo = async (siteId: string) => { `${BASE_URL}${ENDPOINT.CMS_SERVICE.SITES}/${siteId}`, { method: "GET", - headers: { - "Content-Type": "application/json", - }, + headers: getAuthHeaders(), + credentials: "include", }, ); return response.json() as Promise; }; -const client = getApiClient(); - -export const getSiteList = async () => { - const response = await client.get( - `${BASE_URL}${ENDPOINT.CMS_SERVICE.SITE_LIST}`, - { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }, - ); - return response.data; +export const getSiteList = async (): Promise => { + const response = await fetch(`${BASE_URL}${ENDPOINT.CMS_SERVICE.SITE_LIST}`, { + method: "GET", + headers: getAuthHeaders(), + credentials: "include", + }); + return response.json(); }; diff --git a/packages/common/components/src/lib/auth-header.ts b/packages/common/components/src/lib/auth-header.ts new file mode 100644 index 000000000..962688504 --- /dev/null +++ b/packages/common/components/src/lib/auth-header.ts @@ -0,0 +1,22 @@ +import Cookies from "js-cookie"; +import { getConfig } from "@common/config"; + +export function getAuthHeaders(): HeadersInit { + const { CLAIM_NAME, AUTH_USER_ID } = getConfig(); + + if (!CLAIM_NAME || !AUTH_USER_ID) { + throw new Error("Required environment variables are not set"); + } + + const headers: Record = { + "Content-Type": "application/json", + }; + + const token = Cookies.get(CLAIM_NAME); + const userId = Cookies.get(AUTH_USER_ID); + + if (token) headers[CLAIM_NAME] = token; + if (userId) headers[AUTH_USER_ID] = userId; + + return headers; +} diff --git a/packages/common/components/src/ui/footer/index.tsx b/packages/common/components/src/ui/footer/index.tsx index 2430820ff..4df6e170b 100644 --- a/packages/common/components/src/ui/footer/index.tsx +++ b/packages/common/components/src/ui/footer/index.tsx @@ -12,8 +12,6 @@ import { CarouselPrevious, } from "../carousel"; -const siteId = getCookie("site-id-key") ?? ""; - type BannerImageProps = { atflCd: string; bnrSn: number; @@ -64,6 +62,8 @@ const BannerImage = ({ atflCd, lnkgUrlAddr }: BannerImageProps) => { }; export function Footer() { + const siteId = getCookie("site-id-key") ?? ""; + const { data: siteInfo } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId], queryFn: () => getSiteInfo(siteId), diff --git a/packages/common/components/src/ui/header/index.tsx b/packages/common/components/src/ui/header/index.tsx index 99b7977cd..7d01f09f0 100644 --- a/packages/common/components/src/ui/header/index.tsx +++ b/packages/common/components/src/ui/header/index.tsx @@ -29,7 +29,6 @@ import { ScrollArea, ScrollBar } from "../scroll-area"; const appConfig = getConfig(); const userId = getCookie(appConfig.AUTH_USER_ID ?? ""); -const siteId = getCookie("site-id-key") ?? ""; const isLoggedIn = !!userId; function getRootDomain(hostname: string): string { @@ -144,6 +143,7 @@ export function Header({ const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const logoRef = useRef(null); const remainingMs = useTokenRemainingMs(mounted && isLoggedIn && !viewOnly); + const siteId = getCookie("site-id-key") ?? ""; useSessionExtendConfirm({ enabled: diff --git a/packages/common/components/src/ui/layout/nofooter.tsx b/packages/common/components/src/ui/layout/nofooter.tsx index 12f14ceea..29b5cddf6 100644 --- a/packages/common/components/src/ui/layout/nofooter.tsx +++ b/packages/common/components/src/ui/layout/nofooter.tsx @@ -8,15 +8,18 @@ import { SidebarProvider } from "../sidebar"; import { LNB } from "../lnb"; import { Header } from "../header"; import "./common.css"; +import type { AuthService } from "@common/auth"; export function NoFooterLayout({ children, queryClient, + authService, currentPath, handleMenuClick, }: { children: React.ReactNode; queryClient?: QueryClient; + authService?: AuthService; currentPath?: string; handleMenuClick?: (item: MenuItem) => void; }) { @@ -26,19 +29,19 @@ export function NoFooterLayout({ -

-
-
- -
-
{children}
+
+
+
+ +
+
{children}
+
-
- + diff --git a/packages/common/components/src/ui/layout/nolnb.tsx b/packages/common/components/src/ui/layout/nolnb.tsx index 47717c99b..abc436e23 100644 --- a/packages/common/components/src/ui/layout/nolnb.tsx +++ b/packages/common/components/src/ui/layout/nolnb.tsx @@ -6,7 +6,6 @@ import { HelpDialogProvider } from "../../provider/help-dialog-context"; import { ClientIpGuard } from "../../lib/client-ip-guard"; import type { MenuItem } from "../../api"; import { SidebarProvider } from "../sidebar"; -import { LNB } from "../lnb"; import { Header } from "../header"; import { Footer } from "../footer"; import "./common.css"; @@ -17,7 +16,6 @@ export function NoLNBLayout({ authService, tokenManager, currentPath, - handleMenuClick, }: { children: React.ReactNode; queryClient?: QueryClient; @@ -33,19 +31,19 @@ export function NoLNBLayout({ -
-
-
-
-
{children}
-
- + diff --git a/packages/common/components/src/ui/lnb/index.tsx b/packages/common/components/src/ui/lnb/index.tsx index 1c7722a36..35d2f121d 100644 --- a/packages/common/components/src/ui/lnb/index.tsx +++ b/packages/common/components/src/ui/lnb/index.tsx @@ -42,7 +42,6 @@ import { const appConfig = getConfig(); const userId = getCookie(appConfig.AUTH_USER_ID ?? ""); -const appSiteId = getCookie("site-id-key") ?? ""; const isLoggedIn = !!userId; export function LNB({ @@ -74,6 +73,7 @@ export function LNB({ helpContent, } = useHelpDialog(); + const appSiteId = getCookie("site-id-key") ?? ""; const siteId = propSiteId ?? appSiteId; const { data: menuListData } = useQuery({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd99062b0..214b99a21 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -247,9 +247,9 @@ importers: '@common/components': specifier: workspace:* version: link:../../packages/common/components - '@common/config': + '@common/network': specifier: workspace:* - version: link:../../packages/common/config + version: link:../../packages/common/network '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -1042,6 +1042,9 @@ importers: js-cookie: specifier: ^3.0.5 version: 3.0.5 + lucide-react: + specifier: ^0.474.0 + version: 0.474.0(react@19.2.4) moment: specifier: ^2.30.1 version: 2.30.1