260706_1_계정, 로그인, 보안 초안 작성

This commit is contained in:
2026-07-07 19:17:13 +09:00
parent 404941c47a
commit f8633bb1fe
4696 changed files with 6110 additions and 642171 deletions
+3 -3
View File
@@ -1,8 +1,8 @@
{
"hash": "43705b0a",
"configHash": "f5412da4",
"hash": "cd9a5c4a",
"configHash": "6176f0ef",
"lockfileHash": "0cc0e656",
"browserHash": "ae6c1db5",
"browserHash": "dd3791f4",
"optimized": {},
"chunks": {}
}
+1 -1
View File
@@ -105,7 +105,7 @@ function buildHeader(): HTMLElement {
});
actions.append(langBtn, themeBtn);
if (isAuthenticated()) {
if (isAuthenticated() as any) {
actions.append(
createButton({
label: L("Nav_MyAccount"),
+10 -12
View File
@@ -7,13 +7,7 @@
* - PROTECTED_ROUTES는 토큰 없으면 A06_Login으로 리다이렉트.
* ========================================================================== */
import {
ROUTES,
DEFAULT_ROUTE,
PROTECTED_ROUTES,
AUTH_TOKEN_KEY,
type RoutePath,
} from "@config/config_frontend";
import { ROUTES, DEFAULT_ROUTE, PROTECTED_ROUTES, type RoutePath } from "@config/config_frontend";
/** 페이지 렌더 함수 시그니처. root(마운트 대상)를 받아 내용을 채운다. */
export type PageRenderer = (root: HTMLElement) => void | Promise<void>;
@@ -30,11 +24,14 @@ const routeTable: Partial<Record<RoutePath, () => Promise<PageRenderer>>> = {
(await import("../A04_NewsHistory/A04_NewsHistory_UI_Page")).renderA04NewsHistory,
[ROUTES.A05_EDU_DETAIL]: async () =>
(await import("../A05_EduDetail/A05_EduDetail_UI_Page")).renderA05EduDetail,
[ROUTES.A06_LOGIN]: async () => (await import("../A06_Login/A06_Login_UI_Page")).renderA06Login,
[ROUTES.A06_LOGIN]: async () =>
(await import("../A06_Login/A06_Login_UI_Auth_Page")).renderA06Login,
[ROUTES.A07_REGISTER]: async () =>
(await import("../A07_Register/A07_Register_UI_Page")).renderA07Register,
(await import("../A07_Register/A07_Register_UI_Auth_Page")).renderA07Register,
[ROUTES.A08_SUPPORT]: async () =>
(await import("../A08_Support/A08_Support_UI_Page")).renderA08Support,
[ROUTES.A09_SECURITY]: async () =>
(await import("../A09_Security/A09_Security_UI_Page")).renderA09Security,
// 로그인 후 (B 그룹)
[ROUTES.B01_ACCOUNT]: async () =>
(await import("../B01_AccountDetail/B01_AccountDetail_UI_Page")).renderB01AccountDetail,
@@ -61,8 +58,9 @@ const routeTable: Partial<Record<RoutePath, () => Promise<PageRenderer>>> = {
};
/** 로그인 여부 (토큰 존재 확인) */
export function isAuthenticated(): boolean {
return localStorage.getItem(AUTH_TOKEN_KEY) !== null;
export async function isAuthenticated(): Promise<boolean> {
const { fetchSession } = await import("../A06_Login/A06_Login_Api_Fetch");
return fetchSession();
}
/** 현재 해시에서 라우트 경로 추출 (#/a01-home → a01-home) */
@@ -98,7 +96,7 @@ function renderPlaceholder(root: HTMLElement, route: RoutePath): void {
export async function renderCurrentRoute(outlet: HTMLElement): Promise<void> {
const route = currentRoute();
if (PROTECTED_ROUTES.includes(route) && !isAuthenticated()) {
if (PROTECTED_ROUTES.includes(route) && !(await isAuthenticated())) {
navigateTo(ROUTES.A06_LOGIN);
return;
}