Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m45s

This commit is contained in:
2026-07-31 18:00:11 +09:00
5 changed files with 50 additions and 123 deletions
@@ -1,59 +0,0 @@
import { useEffect, useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { getSiteInfo } from "../api/site";
import { getIpList } from "../api/ip";
import { ENDPOINT } from "../config";
import { getCookie } from "../lib";
const siteId = getCookie("site-id-key") ?? "";
const ClientIpGuard = ({
currentPath,
children,
}: {
currentPath?: string;
children: React.ReactNode;
}) => {
const queryClient = useQueryClient();
const [clientIp, setClientIp] = useState("");
const [isAllowed, setIsAllowed] = useState(true);
useEffect(() => {
(async () => {
const response = await fetch("https://api.ipify.org?format=json");
const data = await response.json();
if (!data?.ip) return;
setClientIp(data.ip);
})();
}, []);
useEffect(() => {
(async () => {
if (!siteId || !clientIp) return;
const siteInfo = await queryClient.ensureQueryData({
queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId],
queryFn: () => getSiteInfo(siteId),
});
if (siteInfo.siteKndCd === "O") return;
const { content: ipList } = await getIpList({
siteId,
prmYn: "Y",
});
const allowedClientIp = ipList.some((ip) => ip.ipAddr === clientIp);
setIsAllowed(allowedClientIp);
})();
}, [queryClient, clientIp, currentPath]);
if (!isAllowed) {
alert("허용되지 않은 IP로 접근하였습니다.");
return <></>;
}
return <>{children}</>;
};
export { ClientIpGuard };
@@ -3,7 +3,6 @@ import type { QueryClient } from "@tanstack/react-query";
import { QueryProvider } from "../../provider/query-provider";
import { PopupProvider } from "../../provider/popup-provider";
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";
@@ -29,30 +28,28 @@ export function BaseLayout({
}) {
return (
<QueryProvider queryClient={queryClient}>
<ClientIpGuard currentPath={currentPath}>
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header
authService={authService}
tokenManager={authService ? undefined : tokenManager}
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header
authService={authService}
tokenManager={authService ? undefined : tokenManager}
/>
<div className="flex">
<LNB
currentPath={currentPath}
handleMenuClick={handleMenuClick}
/>
<div className="flex">
<LNB
currentPath={currentPath}
handleMenuClick={handleMenuClick}
/>
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col">
<div className="flex-1">{children}</div>
<Footer />
</div>
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col">
<div className="flex-1">{children}</div>
<Footer />
</div>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</ClientIpGuard>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</QueryProvider>
);
}
@@ -2,7 +2,6 @@ import type { QueryClient } from "@tanstack/react-query";
import { QueryProvider } from "../../provider/query-provider";
import { PopupProvider } from "../../provider/popup-provider";
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";
@@ -25,26 +24,24 @@ export function NoFooterLayout({
}) {
return (
<QueryProvider queryClient={queryClient}>
<ClientIpGuard currentPath={currentPath}>
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header authService={authService} />
<div className="flex">
<LNB
currentPath={currentPath}
handleMenuClick={handleMenuClick}
/>
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col overflow-auto">
<div className="flex-1">{children}</div>
</div>
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header authService={authService} />
<div className="flex">
<LNB
currentPath={currentPath}
handleMenuClick={handleMenuClick}
/>
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col overflow-auto">
<div className="flex-1">{children}</div>
</div>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</ClientIpGuard>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</QueryProvider>
);
}
@@ -3,7 +3,6 @@ import type { QueryClient } from "@tanstack/react-query";
import { QueryProvider } from "../../provider/query-provider";
import { PopupProvider } from "../../provider/popup-provider";
import { HelpDialogProvider } from "../../provider/help-dialog-context";
import { ClientIpGuard } from "../../lib/client-ip-guard";
import type { MenuItem } from "../../api";
import { SidebarProvider } from "../sidebar";
import { Header } from "../header";
@@ -14,7 +13,6 @@ export function NoLNBLayout({
children,
queryClient,
authService,
currentPath,
}: {
children: React.ReactNode;
queryClient?: QueryClient;
@@ -24,23 +22,21 @@ export function NoLNBLayout({
}) {
return (
<QueryProvider queryClient={queryClient}>
<ClientIpGuard currentPath={currentPath}>
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header authService={authService} />
<div className="flex">
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col overflow-auto">
<div className="flex-1">{children}</div>
<Footer />
</div>
<PopupProvider>
<HelpDialogProvider>
<SidebarProvider>
<div className="flex-1">
<Header authService={authService} />
<div className="flex">
<div className="flex min-h-[calc(100vh-50px)] flex-1 flex-col overflow-auto">
<div className="flex-1">{children}</div>
<Footer />
</div>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</ClientIpGuard>
</div>
</SidebarProvider>
</HelpDialogProvider>
</PopupProvider>
</QueryProvider>
);
}
+2 -6
View File
@@ -3,13 +3,9 @@
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"types": ["node"]
},
"include": ["."],
"exclude": [
"node_modules",
"dist",
"coverage",
"storybook-static"
]
"exclude": ["node_modules", "dist", "coverage", "storybook-static"]
}