diff --git a/src/components/sns/SnsKakaoBt.jsx b/src/components/sns/SnsKakaoBt.jsx
index 5738feb..c55edd4 100644
--- a/src/components/sns/SnsKakaoBt.jsx
+++ b/src/components/sns/SnsKakaoBt.jsx
@@ -1,10 +1,17 @@
+import { issueState } from "@/utils/oauthState";
+
const SnsKakaoBt = () => {
- const KAKAO_CLIENT_ID = import.meta.env.VITE_APP_KAKAO_CLIENTID; // 발급받은 클라이언트 아이디
- const REDIRECT_URI = import.meta.env.VITE_APP_KAKAO_CALLBACKURL; // Callback URL
- const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${KAKAO_CLIENT_ID}&redirect_uri=${REDIRECT_URI}`;
+ const KAKAO_CLIENT_ID = import.meta.env.VITE_APP_KAKAO_CLIENTID;
+ const REDIRECT_URI = import.meta.env.VITE_APP_KAKAO_CALLBACKURL;
const KakaoLogin = () => {
- window.location.href = KAKAO_AUTH_URL;
+ const state = issueState("kakao");
+ const url =
+ "https://kauth.kakao.com/oauth/authorize?response_type=code" +
+ `&client_id=${encodeURIComponent(KAKAO_CLIENT_ID)}` +
+ `&state=${encodeURIComponent(state)}` +
+ `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;
+ window.location.href = url;
};
return (
diff --git a/src/components/sns/SnsKakaoCallback.jsx b/src/components/sns/SnsKakaoCallback.jsx
index 23d5b3d..c0f6fef 100644
--- a/src/components/sns/SnsKakaoCallback.jsx
+++ b/src/components/sns/SnsKakaoCallback.jsx
@@ -1,15 +1,32 @@
-import { useEffect } from "react";
+import { useEffect, useRef } from "react";
import * as EgovNet from "@/api/egovFetch";
import CODE from "@/constants/code";
import { setSessionItem } from "@/utils/storage";
+import { consumeState } from "@/utils/oauthState";
+import { useAuth } from "@/contexts/AuthContext";
const SnsKakaoCallback = () => {
- //백엔드 호출
+ const { refresh } = useAuth();
+ // dev StrictMode 의 useEffect 이중 실행으로 consumeState 가 두 번째 호출에서 실패해
+ // false-positive 알럿이 뜨는 것을 막기 위한 1회 실행 가드
+ const didRunRef = useRef(false);
const callBackEnd = () => {
- // 백엔드로 코드값을 넘겨주는 로직
- let code = new URL(window.location.href).searchParams.get("code");
- let state = new URL(window.location.href).searchParams.get("state");
- console.log("code, state=====>", code, state);
+ const params = new URLSearchParams(window.location.search);
+ let code = params.get("code");
+ let state = params.get("state");
+
+ if (!code || !state) {
+ window.location.replace("/");
+ return;
+ }
+
+ // state 1회용 검증 — CSRF 방어
+ if (!consumeState("kakao", state)) {
+ alert("인증 요청이 유효하지 않습니다. 다시 시도해 주세요.");
+ window.location.replace("/");
+ return;
+ }
+
// 요청이 성공하면
if (code) {
const kakaoLoginUrl = `/login/kakao/callback?code=${code}&state=${state}`;
@@ -20,12 +37,10 @@ const SnsKakaoCallback = () => {
},
};
EgovNet.requestFetch(kakaoLoginUrl, requestOptions, (resp) => {
- let resultVO = resp.resultVO;
- let jToken = resp?.jToken || null;
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
- setSessionItem("jToken", jToken);
- //setLoginVO(resultVO);
- setSessionItem("loginUser", resultVO);
+ const { id, name, userSe, uniqId } = resp.resultVO || {};
+ setSessionItem("loginUser", { id, name, userSe, uniqId });
+ refresh(); // AuthContext 갱신
//props.onChangeLogin(resultVO);
// PC와 Mobile 열린메뉴 닫기
document.querySelector(".all_menu.WEB").classList.add("closed");
@@ -33,14 +48,18 @@ const SnsKakaoCallback = () => {
document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
document.querySelector(".all_menu.Mobile").classList.add("closed");
alert("Sns 간편 로그인 중..."); //공통 alert 사용대신해서
+ window.location.replace("/");
} else {
- //React.StrictMode 에서 fetch가 자동으로 2번 실행할 때 아래 메인화면으로 이동된다.
window.location.replace("/");
}
});
}
};
- useEffect(callBackEnd, []);
+ useEffect(() => {
+ if (didRunRef.current) return;
+ didRunRef.current = true;
+ callBackEnd();
+ }, []);
return (
<>
diff --git a/src/components/sns/SnsNaverBt.jsx b/src/components/sns/SnsNaverBt.jsx
index 396aa96..da99b99 100644
--- a/src/components/sns/SnsNaverBt.jsx
+++ b/src/components/sns/SnsNaverBt.jsx
@@ -1,11 +1,17 @@
+import { issueState } from "@/utils/oauthState";
+
const SnsNaverBt = () => {
- const NAVER_CLIENT_ID = import.meta.env.VITE_APP_NAVER_CLIENTID; // 발급받은 클라이언트 아이디
- const REDIRECT_URI = import.meta.env.VITE_APP_NAVER_CALLBACKURL; // Callback URL
- const STATE = import.meta.env.VITE_APP_STATE; //다른 서버와 통신 시 암호화문자
- const NAVER_AUTH_URL = `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${NAVER_CLIENT_ID}&state=${STATE}&redirect_uri=${REDIRECT_URI}`;
+ const NAVER_CLIENT_ID = import.meta.env.VITE_APP_NAVER_CLIENTID;
+ const REDIRECT_URI = import.meta.env.VITE_APP_NAVER_CALLBACKURL;
const NaverLogin = () => {
- window.location.href = NAVER_AUTH_URL;
+ const state = issueState("naver");
+ const url =
+ "https://nid.naver.com/oauth2.0/authorize?response_type=code" +
+ `&client_id=${encodeURIComponent(NAVER_CLIENT_ID)}` +
+ `&state=${encodeURIComponent(state)}` +
+ `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;
+ window.location.href = url;
};
return (
diff --git a/src/components/sns/SnsNaverCallback.jsx b/src/components/sns/SnsNaverCallback.jsx
index 6f037ed..9ff2b43 100644
--- a/src/components/sns/SnsNaverCallback.jsx
+++ b/src/components/sns/SnsNaverCallback.jsx
@@ -1,15 +1,32 @@
-import { useEffect } from "react";
+import { useEffect, useRef } from "react";
import * as EgovNet from "@/api/egovFetch";
import CODE from "@/constants/code";
import { setSessionItem } from "@/utils/storage";
+import { consumeState } from "@/utils/oauthState";
+import { useAuth } from "@/contexts/AuthContext";
const SnsNaverCallback = () => {
- //백엔드 호출
+ const { refresh } = useAuth();
+ // dev StrictMode 의 useEffect 이중 실행으로 consumeState 가 두 번째 호출에서 실패해
+ // false-positive 알럿이 뜨는 것을 막기 위한 1회 실행 가드
+ const didRunRef = useRef(false);
const callBackEnd = () => {
- // 백엔드로 코드값을 넘겨주는 로직
- let code = new URL(window.location.href).searchParams.get("code");
- let state = new URL(window.location.href).searchParams.get("state");
- console.log("code, state=====>", code, state);
+ const params = new URLSearchParams(window.location.search);
+ let code = params.get("code");
+ let state = params.get("state");
+
+ if (!code || !state) {
+ window.location.replace("/");
+ return;
+ }
+
+ // state 1회용 검증 — CSRF 방어
+ if (!consumeState("naver", state)) {
+ alert("인증 요청이 유효하지 않습니다. 다시 시도해 주세요.");
+ window.location.replace("/");
+ return;
+ }
+
// 요청이 성공하면
if (code) {
const naverLoginUrl = `/login/naver/callback?code=${code}&state=${state}`;
@@ -20,12 +37,10 @@ const SnsNaverCallback = () => {
},
};
EgovNet.requestFetch(naverLoginUrl, requestOptions, (resp) => {
- let resultVO = resp.resultVO;
- let jToken = resp?.jToken || null;
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
- setSessionItem("jToken", jToken);
- //setLoginVO(resultVO);
- setSessionItem("loginUser", resultVO);
+ const { id, name, userSe, uniqId } = resp.resultVO || {};
+ setSessionItem("loginUser", { id, name, userSe, uniqId });
+ refresh(); // AuthContext 갱신
//props.onChangeLogin(resultVO);
// PC와 Mobile 열린메뉴 닫기
document.querySelector(".all_menu.WEB").classList.add("closed");
@@ -33,14 +48,18 @@ const SnsNaverCallback = () => {
document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
document.querySelector(".all_menu.Mobile").classList.add("closed");
alert("Sns 간편 로그인 중..."); //공통 alert 사용대신해서
+ window.location.replace("/");
} else {
- //React.StrictMode 에서 fetch가 자동으로 2번 실행할 때 아래 메인화면으로 이동된다.
window.location.replace("/");
}
});
}
};
- useEffect(callBackEnd, []);
+ useEffect(() => {
+ if (didRunRef.current) return;
+ didRunRef.current = true;
+ callBackEnd();
+ }, []);
return (
<>
diff --git a/src/config/index.jsx b/src/config/index.jsx
deleted file mode 100644
index 837c5a9..0000000
--- a/src/config/index.jsx
+++ /dev/null
@@ -1,4 +0,0 @@
-export const SERVER_URL = "http://" + import.meta.env.VITE_APP_EGOV_CONTEXT_URL; // REST API 서버 Domain URL
-export const DEFAULT_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // default = 공지사항 게시판 아이디
-export const NOTICE_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // 공지사항 게시판 아이디
-export const GALLERY_BBS_ID = "BBSMSTR_BBBBBBBBBBBB"; // 갤러리 게시판 아이디
diff --git a/src/constants/code.jsx b/src/constants/code.jsx
deleted file mode 100644
index 91ca24b..0000000
--- a/src/constants/code.jsx
+++ /dev/null
@@ -1,22 +0,0 @@
-const CODE = {
- RCV_SUCCESS : "200", // 성공
-
- RCV_ERROR_AUTH : "403", // 인증 오류
- RCV_ERROR_DELETE : "700", // 삭제 오류
- RCV_ERROR_SAVE : "800", // 저장 오류
- RCV_ERROR_VALIDATION : "900", // 입력 오류
-
- MODE_CREATE : "create", // 등록 모드
- MODE_MODIFY : "modify", // 수정 모드
- MODE_READ : "read", // 읽기 모드
- MODE_REPLY : "reply", // 답글 모드
-
- DATE_YEAR : "year",
- DATE_MONTH : "month",
- DATE_DATE : "date",
- DATE_WEEK : "week",
- DATE_DAY : "day",
-}
-
-
-export default CODE;
\ No newline at end of file
diff --git a/src/constants/url.jsx b/src/constants/url.jsx
deleted file mode 100644
index 9c28bf2..0000000
--- a/src/constants/url.jsx
+++ /dev/null
@@ -1,89 +0,0 @@
-const URL = {
- //COMMON
- MAIN: "/", //메인페이지
-
- LOGIN: "/login", //로그인
- SNS_NAVER_CB: "/login/naver/callback", //Sns Naver Callback
- SNS_KAKAO_CB: "/login/kakao/callback", //Sns Kakao Callback
- ERROR: "/error", //로그인
-
- //ABOUT
- ABOUT: "/about", //사이트소개
- ABOUT_SITE: "/about/site", // 사이트소개/소개
- ABOUT_HISTORY: "/about/history", // 사이트소개/연혁
- ABOUT_ORGANIZATION: "/about/organization", // 사이트소개/조직소개
- ABOUT_LOCATION: "/about/location", // 사이트소개/찾아오시는길
-
- //INTRO
- INTRO: "/intro", //정보마당
- INTRO_WORKS: "/intro/works", // 정보마당/주요사업소개
- INTRO_SERVICE: "/intro/service", // 정보마당/주요서비스소개
-
- //SUPPORT
- SUPPORT: "/support", // 고객지원
- SUPPORT_DOWNLOAD: "/support/download", // 고객지원/자료실
- SUPPORT_DOWNLOAD_DETAIL: "/support/download/detail", // 고객지원/자료실/상세
- SUPPORT_DOWNLOAD_CREATE: "/support/download/create", // 고객지원/자료실/등록
- SUPPORT_QNA: "/support/qna", // 고객지원/묻고답하기
- SUPPORT_QNA_DETAIL: "/support/qna/detail", // 고객지원/묻고답하기/상세
- SUPPORT_APPLY: "/support/apply", // 고객지원/서비스신청
-
- //INFORM
- INFORM: "/inform", // 알림마당
- INFORM_DAILY: "/inform/daily", // 알림마당/오늘의행사
- INFORM_DAILY_DETAIL: "/inform/daily/detail", // 알림마당/오늘의행사상세
- INFORM_WEEKLY: "/inform/weekly", // 알림마당/금주의행사
- INFORM_WEEKLY_DETAIL: "/inform/weekly/detail", // 알림마당/금주의행사상세
- INFORM_NOTICE: "/inform/notice", // 알림마당/공지사항
- INFORM_NOTICE_DETAIL: "/inform/notice/detail", // 알림마당/공지사항상세
- INFORM_NOTICE_CREATE: "/inform/notice/create", // 알림마당/공지사항등록
- INFORM_NOTICE_MODIFY: "/inform/notice/modify", // 알림마당/공지사항수정
- INFORM_NOTICE_REPLY: "/inform/notice/reply", // 알림마당/공지사항답글
- INFORM_GALLERY: "/inform/gallery", // 알림마당/사이트갤러리
- INFORM_GALLERY_DETAIL: "/inform/gallery/detail", // 알림마당/사이트갤러리상세
- INFORM_GALLERY_CREATE: "/inform/gallery/create", // 알림마당/사이트갤러리등록
- INFORM_GALLERY_MODIFY: "/inform/gallery/modify", // 알림마당/사이트갤러리수정
- INFORM_GALLERY_REPLY: "/inform/gallery/reply", // 알림마당/사이트갤러리답글
-
- //ADMIN
- ADMIN: "/admin", // 사이트관리
- ADMIN_SCHEDULE: "/admin/schedule", // 사이트관리/일정관리
- ADMIN_SCHEDULE_DETAIL: "/admin/schedule/detail", // 사이트관리/일정관리상세
- ADMIN_SCHEDULE_CREATE: "/admin/schedule/create", // 사이트관리/일정관리생성
- ADMIN_SCHEDULE_MODIFY: "/admin/schedule/modify", // 사이트관리/일정관리수정
-
- ADMIN_BOARD: "/admin/board", // 사이트관리/게시판생성관리 목록
- ADMIN_BOARD_DETAIL: "/admin/board/detail", // 사이트관리/게시판생성관리 상세
- ADMIN_BOARD_CREATE: "/admin/board/create", // 사이트관리/게시판생성관리 등록
- ADMIN_BOARD_MODIFY: "/admin/board/modify", // 사이트관리/게시판생성관리 상세/수정
-
- ADMIN_USAGE: "/admin/usage", // 사이트관리/게시판사용관리 목록
- ADMIN_USAGE_DETAIL: "/admin/usage/detail", // 사이트관리/게시판사용관리 상세
- ADMIN_USAGE_CREATE: "/admin/usage/create", // 사이트관리/게시판사용관리 등록
- ADMIN_USAGE_MODIFY: "/admin/usage/modify", // 사이트관리/게시판사용관리 상세/수정
-
- ADMIN_NOTICE: "/admin/notice", // 사이트관리/공지사항관리 목록
- ADMIN_NOTICE_DETAIL: "/admin/notice/detail", // 사이트관리/공지사항관리 상세
- ADMIN_NOTICE_CREATE: "/admin/notice/create", // 사이트관리/공지사항관리 등록
- ADMIN_NOTICE_MODIFY: "/admin/notice/modify", // 사이트관리/공지사항관리 수정
- ADMIN_NOTICE_REPLY: "/admin/notice/reply", // 사이트관리/공지사항관리 답글 등록
-
- ADMIN_GALLERY: "/admin/gallery", // 사이트관리/사이트갤러리관리
- ADMIN_GALLERY_DETAIL: "/admin/gallery/detail", // 사이트관리/사이트갤러리관리 상세
- ADMIN_GALLERY_CREATE: "/admin/gallery/create", // 사이트관리/사이트갤러리관리 등록
- ADMIN_GALLERY_MODIFY: "/admin/gallery/modify", // 사이트관리/사이트갤러리관리 수정
- ADMIN_GALLERY_REPLY: "/admin/gallery/reply", // 사이트관리/사이트갤러리관리 답글 등록
-
- ADMIN_MANAGER: "/admin/manager", // 사이트관리/사이트관리자 암호변경 기능
- ADMIN_MEMBERS: "/admin/members", // 사이트관리/회원관리 목록기능
- ADMIN_MEMBERS_DETAIL: "/admin/members/detail", // 사이트관리/회원관리 상세
- ADMIN_MEMBERS_CREATE: "/admin/members/create", // 사이트관리/회원관리 등록
- ADMIN_MEMBERS_MODIFY: "/admin/members/modify", // 사이트관리/회원관리 상세/수정
-
- //MYPAGE
- MYPAGE_MODIFY: "/mypage/modify", // 고객지원/마이페이지/회원 수정
- MYPAGE_CREATE: "/mypage/create", // 고객지원/마이페이지/회원 등록
-};
-
-
-export default URL;
diff --git a/src/contexts/AuthContext.jsx b/src/contexts/AuthContext.jsx
new file mode 100644
index 0000000..1256a97
--- /dev/null
+++ b/src/contexts/AuthContext.jsx
@@ -0,0 +1,58 @@
+import { createContext, useContext, useEffect, useState, useCallback } from "react";
+import * as EgovNet from "@/api/egovFetch";
+import CODE from "@/constants/code";
+
+/**
+ * 백엔드 /auth/me 호출 결과를 전역 인증 상태로 보관.
+ * 라우트 가드·메뉴 분기는 이 컨텍스트의 roles 를 기준으로 판단한다.
+ * sessionStorage 의 loginUser 는 표시용 보조 캐시로만 사용.
+ */
+const AuthContext = createContext({
+ user: null,
+ roles: [],
+ loading: true,
+ refresh: () => {},
+ clear: () => {},
+});
+
+export function AuthProvider({ children }) {
+ const [state, setState] = useState({ user: null, roles: [], loading: true });
+
+ const refresh = useCallback(() => {
+ EgovNet.requestFetch(
+ "/auth/me",
+ { method: "GET", headers: { "Content-type": "application/json" } },
+ (resp) => {
+ if (resp && Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
+ const vo = resp.resultVO || {};
+ setState({
+ user: { id: vo.id, name: vo.name, userSe: vo.userSe, uniqId: vo.uniqId },
+ roles: Array.isArray(vo.roles) ? vo.roles : [],
+ loading: false,
+ });
+ } else {
+ setState({ user: null, roles: [], loading: false });
+ }
+ },
+ () => {
+ setState({ user: null, roles: [], loading: false });
+ }
+ );
+ }, []);
+
+ const clear = useCallback(() => {
+ setState({ user: null, roles: [], loading: false });
+ }, []);
+
+ useEffect(() => {
+ refresh();
+ }, [refresh]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export const useAuth = () => useContext(AuthContext);
diff --git a/src/main.jsx b/src/main.jsx
index 569fdf2..0d1758a 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,6 +1,6 @@
import React from "react";
import ReactDOM from "react-dom/client";
-import App from "./App.jsx";
+import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
diff --git a/src/pages/about/EgovAboutLocation.jsx b/src/pages/about/EgovAboutLocation.jsx
index 1edc676..d82e41c 100644
--- a/src/pages/about/EgovAboutLocation.jsx
+++ b/src/pages/about/EgovAboutLocation.jsx
@@ -46,7 +46,7 @@ function EgovAboutLocation() {
diff --git a/src/pages/admin/board/EgovAdminBoardEdit.jsx b/src/pages/admin/board/EgovAdminBoardEdit.jsx
index 7b3f459..a1a1a31 100644
--- a/src/pages/admin/board/EgovAdminBoardEdit.jsx
+++ b/src/pages/admin/board/EgovAdminBoardEdit.jsx
@@ -10,15 +10,11 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
import EgovRadioButtonGroup from "@/components/EgovRadioButtonGroup";
function EgovAdminBoardEdit(props) {
- console.group("EgovAdminBoardEdit");
- console.log("[Start] EgovAdminBoardEdit ------------------------------");
- console.log("EgovAdminBoardEdit [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
const checkRef = useRef([]);
- console.log("EgovAdminBoardEdit [location] : ", location);
const replyPosblAtRadioGroup = [
{ value: "Y", label: "가능" },
@@ -163,7 +159,6 @@ function EgovAdminBoardEdit(props) {
for (let key in boardDetail) {
formData.append(key, boardDetail[key]);
- //console.log("boardDetail [%s] ", key, boardDetail[key]);
}
if (formValidator(formData)) {
@@ -219,7 +214,6 @@ function EgovAdminBoardEdit(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> board delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.ADMIN_BOARD, { replace: true });
@@ -239,8 +233,6 @@ function EgovAdminBoardEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminBoardEdit [End]");
- console.groupEnd("EgovAdminBoardEdit");
return (
diff --git a/src/pages/admin/board/EgovAdminBoardList.jsx b/src/pages/admin/board/EgovAdminBoardList.jsx
index 88c400f..ca166c3 100644
--- a/src/pages/admin/board/EgovAdminBoardList.jsx
+++ b/src/pages/admin/board/EgovAdminBoardList.jsx
@@ -10,12 +10,8 @@ import EgovPaging from "@/components/EgovPaging";
import { itemIdxByPage } from "@/utils/calc";
function EgovAdminBoardList(props) {
- console.group("EgovAdminBoardList");
- console.log("[Start] EgovAdminBoardList ------------------------------");
- console.log("EgovAdminBoardList [props] : ", props);
const location = useLocation();
- console.log("EgovAdminBoardList [location] : ", location);
// eslint-disable-next-line no-unused-vars
const [searchCondition, setSearchCondition] = useState(
@@ -34,7 +30,6 @@ function EgovAdminBoardList(props) {
const retrieveList = useCallback(
(srchCnd) => {
- console.groupCollapsed("EgovAdminBoardList.retrieveList()");
const retrieveListURL = "/bbsMaster" + EgovNet.getQueryString(srchCnd);
@@ -95,10 +90,8 @@ function EgovAdminBoardList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminBoardList.retrieveList()");
},
[listTag, searchCondition]
);
@@ -108,8 +101,6 @@ function EgovAdminBoardList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminBoardList [End]");
- console.groupEnd("EgovAdminBoardList");
return (
diff --git a/src/pages/admin/gallery/EgovAdminGalleryDetail.jsx b/src/pages/admin/gallery/EgovAdminGalleryDetail.jsx
index 5725643..371ca59 100644
--- a/src/pages/admin/gallery/EgovAdminGalleryDetail.jsx
+++ b/src/pages/admin/gallery/EgovAdminGalleryDetail.jsx
@@ -13,13 +13,9 @@ import EgovAttachFile from "@/components/EgovAttachFile";
import EgovImageGallery from "@/components/EgovImageGallery";
function EgovAdminGalleryDetail(props) {
- console.group("EgovAdminGalleryDetail");
- console.log("------------------------------");
- console.log("EgovAdminGalleryDetail [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminGalleryDetail [location] : ", location);
// 직접 URL 접근 시 location.state가 null일 수 있음
const bbsId = location.state?.bbsId || GALLERY_BBS_ID;
@@ -60,7 +56,6 @@ function EgovAdminGalleryDetail(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> board delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.ADMIN_GALLERY, { replace: true });
@@ -85,7 +80,6 @@ function EgovAdminGalleryDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovAdminGalleryDetail");
return (
diff --git a/src/pages/admin/gallery/EgovAdminGalleryEdit.jsx b/src/pages/admin/gallery/EgovAdminGalleryEdit.jsx
index b0b6e9c..dfc18c6 100644
--- a/src/pages/admin/gallery/EgovAdminGalleryEdit.jsx
+++ b/src/pages/admin/gallery/EgovAdminGalleryEdit.jsx
@@ -13,13 +13,9 @@ import bbsFormVaildator from "@/utils/bbsFormVaildator";
import { useDebouncedInput } from "@/hooks/useDebounce";
function EgovAdminGalleryEdit(props) {
- console.group("EgovAdminGalleryEdit");
- console.log("------------------------------");
- console.log("EgovAdminGalleryEdit [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminGalleryEdit [location] : ", location);
const bbsId = location.state?.bbsId || GALLERY_BBS_ID;
const nttId = location.state?.nttId || "";
@@ -113,7 +109,6 @@ function EgovAdminGalleryEdit(props) {
const formData = new FormData();
for (let key in boardDetail) {
formData.append(key, boardDetail[key]);
- //console.log("boardDetail [%s] ", key, boardDetail[key]);
}
if (bbsFormVaildator(formData)) {
@@ -159,7 +154,6 @@ function EgovAdminGalleryEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovAdminGalleryEdit");
return (
@@ -229,10 +223,6 @@ function EgovAdminGalleryEdit(props) {
masterBoard.fileAtchPosblAt === "Y" && (
{
- console.log(
- "====>>> Changed attachfile file = ",
- attachfile
- );
const arrayConcat = { ...boardDetail }; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
for (let i = 0; i < attachfile.length; i++) {
arrayConcat[`file_${i}`] = attachfile[i];
@@ -240,7 +230,6 @@ function EgovAdminGalleryEdit(props) {
setBoardDetail(arrayConcat);
}}
fnDeleteFile={(deletedFile) => {
- console.log("====>>> Delete deletedFile = ", deletedFile);
setBoardAttachFiles(deletedFile);
}}
boardFiles={boardAttachFiles}
diff --git a/src/pages/admin/gallery/EgovAdminGalleryList.jsx b/src/pages/admin/gallery/EgovAdminGalleryList.jsx
index d323c2f..21d0cb5 100644
--- a/src/pages/admin/gallery/EgovAdminGalleryList.jsx
+++ b/src/pages/admin/gallery/EgovAdminGalleryList.jsx
@@ -12,9 +12,6 @@ import EgovPaging from "@/components/EgovPaging";
import { itemIdxByPage } from "@/utils/calc";
function EgovAdminGalleryList(props) {
- console.group("EgovAdminGalleryList");
- console.log("[Start] EgovAdminGalleryList ------------------------------");
- console.log("EgovAdminGalleryList [props] : ", props);
const cndRef = useRef();
const wrdRef = useRef();
@@ -29,7 +26,6 @@ function EgovAdminGalleryList(props) {
const [listTag, setListTag] = useState([]);
const retrieveList = useCallback((searchCondition) => {
- console.groupCollapsed("EgovAdminGalleryList.retrieveList()");
const retrieveListURL = "/board" + EgovNet.getQueryString(searchCondition);
const requestOptions = {
@@ -98,10 +94,8 @@ function EgovAdminGalleryList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminGalleryList.retrieveList()");
}, []);
//======================================================
@@ -110,8 +104,6 @@ function EgovAdminGalleryList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminGalleryList [End]");
- console.groupEnd("EgovAdminGalleryList");
return (
diff --git a/src/pages/admin/manager/EgovAdminPasswordUpdate.jsx b/src/pages/admin/manager/EgovAdminPasswordUpdate.jsx
index 7b1e236..a31f5f5 100644
--- a/src/pages/admin/manager/EgovAdminPasswordUpdate.jsx
+++ b/src/pages/admin/manager/EgovAdminPasswordUpdate.jsx
@@ -6,9 +6,6 @@ import CODE from "@/constants/code";
import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
function EgovAdminPasswordUpdate(props) {
- console.group("EgovAdminPasswordUpdate");
- console.log("[Start] EgovAdminPasswordUpdate ------------------------------");
- console.log("EgovAdminPasswordUpdate [props] : ", props);
const navigate = useNavigate();
const [oldPassword, setOldPassword] = useState("");
@@ -77,9 +74,6 @@ function EgovAdminPasswordUpdate(props) {
}, []);
- console.log("------------------------------EgovAdminPasswordUpdate [End]");
- console.groupEnd("EgovAdminPasswordUpdate");
-
return (
diff --git a/src/pages/admin/members/EgovAdminMemberEdit.jsx b/src/pages/admin/members/EgovAdminMemberEdit.jsx
index 28aa4ad..fe26e07 100644
--- a/src/pages/admin/members/EgovAdminMemberEdit.jsx
+++ b/src/pages/admin/members/EgovAdminMemberEdit.jsx
@@ -9,15 +9,9 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
import EgovRadioButtonGroup from "@/components/EgovRadioButtonGroup";
function EgovAdminMemberEdit(props) {
- console.group("EgovAdminMemberEdit");
- console.log("[Start] EgovAdminMemberEdit ------------------------------");
- console.log("EgovAdminMemberEdit [props] : ", props);
-
const navigate = useNavigate();
const location = useLocation();
const checkRef = useRef([]);
-
- console.log("EgovAdminMemberEdit [location] : ", location);
const uniqId = location.state?.uniqId || "";
const mberSttusRadioGroup = [
{ value: "P", label: "가능" },
@@ -250,7 +244,6 @@ function EgovAdminMemberEdit(props) {
};
EgovNet.requestFetch(deleteMemberURL, requestOptions, (resp) => {
- console.log("====>>> member delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("회원이 삭제되었습니다.");
navigate(URL.ADMIN_MEMBERS, { replace: true });
@@ -265,9 +258,6 @@ function EgovAdminMemberEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminMemberEdit [End]");
- console.groupEnd("EgovAdminMemberEdit");
-
return (
diff --git a/src/pages/admin/members/EgovAdminMemberList.jsx b/src/pages/admin/members/EgovAdminMemberList.jsx
index 2ca7381..f96356d 100644
--- a/src/pages/admin/members/EgovAdminMemberList.jsx
+++ b/src/pages/admin/members/EgovAdminMemberList.jsx
@@ -10,14 +10,7 @@ import EgovPaging from "@/components/EgovPaging";
import { itemIdxByPage } from "@/utils/calc";
function EgovAdminMemberList(props) {
- console.group("EgovAdminMemberList");
- console.log(
- "[Start] EgovAdminMemberMemberList ------------------------------"
- );
- console.log("EgovAdminMemberList [props] : ", props);
-
const location = useLocation();
- console.log("EgovAdminMemberList [location] : ", location);
// eslint-disable-next-line no-unused-vars
const [searchCondition, setSearchCondition] = useState(
@@ -36,7 +29,6 @@ function EgovAdminMemberList(props) {
const retrieveList = useCallback(
(srchCnd) => {
- console.groupCollapsed("EgovAdminMemberList.retrieveList()");
const retrieveListURL = "/members" + EgovNet.getQueryString(srchCnd);
@@ -105,10 +97,8 @@ function EgovAdminMemberList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminMemberList.retrieveList()");
},
[listTag, searchCondition]
);
@@ -118,8 +108,6 @@ function EgovAdminMemberList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminMemberList [End]");
- console.groupEnd("EgovAdminMemberList");
return (
diff --git a/src/pages/admin/notice/EgovAdminNoticeDetail.jsx b/src/pages/admin/notice/EgovAdminNoticeDetail.jsx
index a1cbc6d..6fa5f06 100644
--- a/src/pages/admin/notice/EgovAdminNoticeDetail.jsx
+++ b/src/pages/admin/notice/EgovAdminNoticeDetail.jsx
@@ -12,13 +12,9 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
import EgovAttachFile from "@/components/EgovAttachFile";
function EgovAdminNoticeDetail(props) {
- console.group("EgovAdminNoticeDetail");
- console.log("------------------------------");
- console.log("EgovAdminNoticeDetail [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminNoticeDetail [location] : ", location);
// 직접 URL 접근 시 location.state가 null일 수 있음
const bbsId = location.state?.bbsId || NOTICE_BBS_ID;
@@ -59,7 +55,6 @@ function EgovAdminNoticeDetail(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> board delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.ADMIN_NOTICE, { replace: true });
@@ -83,7 +78,6 @@ function EgovAdminNoticeDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovAdminNoticeDetail");
return (
diff --git a/src/pages/admin/notice/EgovAdminNoticeEdit.jsx b/src/pages/admin/notice/EgovAdminNoticeEdit.jsx
index e7bb526..f97b296 100644
--- a/src/pages/admin/notice/EgovAdminNoticeEdit.jsx
+++ b/src/pages/admin/notice/EgovAdminNoticeEdit.jsx
@@ -14,13 +14,9 @@ import bbsFormVaildator from "@/utils/bbsFormVaildator";
import { useDebouncedInput } from "@/hooks/useDebounce";
function EgovAdminNoticeEdit(props) {
- console.group("EgovAdminNoticeEdit");
- console.log("------------------------------");
- console.log("EgovAdminNoticeEdit [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminNoticeEdit [location] : ", location);
const bbsId = location.state?.bbsId || NOTICE_BBS_ID;
const nttId = location.state?.nttId || "";
@@ -114,7 +110,6 @@ function EgovAdminNoticeEdit(props) {
const formData = new FormData();
for (let key in boardDetail) {
formData.append(key, boardDetail[key]);
- //console.log("boardDetail [%s] ", key, boardDetail[key]);
}
if (bbsFormVaildator(formData)) {
@@ -160,7 +155,6 @@ function EgovAdminNoticeEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovAdminNoticeEdit");
return (
@@ -230,10 +224,6 @@ function EgovAdminNoticeEdit(props) {
masterBoard.fileAtchPosblAt === "Y" && (
{
- console.log(
- "====>>> Changed attachfile file = ",
- attachfile
- );
const arrayConcat = { ...boardDetail }; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
for (let i = 0; i < attachfile.length; i++) {
arrayConcat[`file_${i}`] = attachfile[i];
@@ -241,7 +231,6 @@ function EgovAdminNoticeEdit(props) {
setBoardDetail(arrayConcat);
}}
fnDeleteFile={(deletedFile) => {
- console.log("====>>> Delete deletedFile = ", deletedFile);
setBoardAttachFiles(deletedFile);
}}
boardFiles={boardAttachFiles}
diff --git a/src/pages/admin/notice/EgovAdminNoticeList.jsx b/src/pages/admin/notice/EgovAdminNoticeList.jsx
index 41e59ec..8b9e089 100644
--- a/src/pages/admin/notice/EgovAdminNoticeList.jsx
+++ b/src/pages/admin/notice/EgovAdminNoticeList.jsx
@@ -12,9 +12,6 @@ import EgovPaging from "@/components/EgovPaging";
import { itemIdxByPage } from "@/utils/calc";
function EgovAdminNoticeList(props) {
- console.group("EgovAdminNoticeList");
- console.log("[Start] EgovAdminNoticeList ------------------------------");
- console.log("EgovAdminNoticeList [props] : ", props);
const cndRef = useRef();
const wrdRef = useRef();
@@ -29,7 +26,6 @@ function EgovAdminNoticeList(props) {
const [listTag, setListTag] = useState([]);
const retrieveList = useCallback((searchCondition) => {
- console.groupCollapsed("EgovAdminNoticeList.retrieveList()");
const retrieveListURL = "/board" + EgovNet.getQueryString(searchCondition);
const requestOptions = {
@@ -99,10 +95,8 @@ function EgovAdminNoticeList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminNoticeList.retrieveList()");
}, []);
useEffect(() => {
@@ -110,8 +104,6 @@ function EgovAdminNoticeList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminNoticeList [End]");
- console.groupEnd("EgovAdminNoticeList");
return (
diff --git a/src/pages/admin/schedule/EgovAdminScheduleDetail.jsx b/src/pages/admin/schedule/EgovAdminScheduleDetail.jsx
index 778176b..8aae436 100644
--- a/src/pages/admin/schedule/EgovAdminScheduleDetail.jsx
+++ b/src/pages/admin/schedule/EgovAdminScheduleDetail.jsx
@@ -9,13 +9,9 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
import EgovAttachFile from "@/components/EgovAttachFile";
function EgovAdminScheduleDetail(props) {
- console.group("EgovAdminScheduleDetail");
- console.log("[Start] EgovAdminScheduleDetail ------------------------------");
- console.log("EgovAdminScheduleDetail [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminScheduleDetail [location] : ", location);
const [scheduleDetail, setScheduleDetail] = useState({});
const [boardAttachFiles, setBoardAttachFiles] = useState();
@@ -99,7 +95,6 @@ function EgovAdminScheduleDetail(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> Schdule delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.ADMIN_SCHEDULE, { replace: true });
@@ -124,8 +119,6 @@ function EgovAdminScheduleDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminScheduleDetail [End]");
- console.groupEnd("EgovAdminScheduleDetail");
return (
diff --git a/src/pages/admin/schedule/EgovAdminScheduleEdit.jsx b/src/pages/admin/schedule/EgovAdminScheduleEdit.jsx
index 7930baa..9f2ef89 100644
--- a/src/pages/admin/schedule/EgovAdminScheduleEdit.jsx
+++ b/src/pages/admin/schedule/EgovAdminScheduleEdit.jsx
@@ -14,13 +14,9 @@ import { useDebouncedInput } from "@/hooks/useDebounce";
import "react-datepicker/dist/react-datepicker.css";
function EgovAdminScheduleEdit(props) {
- console.group("EgovAdminScheduleEdit");
- console.log("[Start] EgovAdminScheduleEdit ------------------------------");
- console.log("EgovAdminScheduleEdit [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminScheduleEdit [location] : ", location);
const reptitSeCodeRadioGroup = [
{ value: "1", label: "당일" },
@@ -118,7 +114,6 @@ function EgovAdminScheduleEdit(props) {
for (let key in scheduleDetail) {
formData.append(key, scheduleDetail[key]);
- console.log("scheduleDetail [%s] ", key, scheduleDetail[key]);
}
if (formValidator(formData)) {
@@ -201,8 +196,6 @@ function EgovAdminScheduleEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminScheduleEdit [End]");
- console.groupEnd("EgovAdminScheduleEdit");
return (
@@ -378,7 +371,6 @@ function EgovAdminScheduleEdit(props) {
dateFormat="yyyy-MM-dd HH:mm"
showTimeInput
onChange={(date) => {
- console.log("setStartDate : ", date);
setScheduleDetail({
...scheduleDetail,
schdulBgnde: getDateFourteenDigit(date),
@@ -414,7 +406,6 @@ function EgovAdminScheduleEdit(props) {
showTimeInput
minDate={scheduleDetail.startDate}
onChange={(date) => {
- console.log("setEndDate: ", date);
setScheduleDetail({
...scheduleDetail,
schdulEndde: getDateFourteenDigit(date),
@@ -460,7 +451,6 @@ function EgovAdminScheduleEdit(props) {
{
- console.log("====>>> Changed attachfile file = ", attachfile);
const arrayConcat = { ...scheduleDetail }; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
for (let i = 0; i < attachfile.length; i++) {
arrayConcat[`file_${i}`] = attachfile[i];
@@ -468,7 +458,6 @@ function EgovAdminScheduleEdit(props) {
setScheduleDetail(arrayConcat);
}}
fnDeleteFile={(deletedFile) => {
- console.log("====>>> Delete deletedFile = ", deletedFile);
setBoardAttachFiles(deletedFile);
}}
boardFiles={boardAttachFiles}
diff --git a/src/pages/admin/schedule/EgovAdminScheduleList.jsx b/src/pages/admin/schedule/EgovAdminScheduleList.jsx
index b806c61..70f1a1a 100644
--- a/src/pages/admin/schedule/EgovAdminScheduleList.jsx
+++ b/src/pages/admin/schedule/EgovAdminScheduleList.jsx
@@ -8,12 +8,8 @@ import CODE from "@/constants/code";
import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
function EgovAdminScheduleList(props) {
- console.group("EgovAdminScheduleList");
- console.log("[Start] EgovAdminScheduleList ------------------------------");
- console.log("EgovAdminScheduleList [props] : ", props);
const location = useLocation();
- console.log("EgovAdminScheduleList [location] : ", location);
const DATE = new Date();
const TODAY = new Date(DATE.getFullYear(), DATE.getMonth(), DATE.getDate());
@@ -31,7 +27,6 @@ function EgovAdminScheduleList(props) {
const [scheduleList, setScheduleList] = useState([]);
const innerConsole = (...args) => {
- console.log(...args);
};
const getLastDateOfMonth = (year, month) => {
@@ -69,7 +64,6 @@ function EgovAdminScheduleList(props) {
};
const retrieveList = useCallback((srchcnd) => {
- console.groupCollapsed("EgovAdminScheduleList.retrieveList()");
const retrieveListURL = "/schedule/month" + EgovNet.getQueryString(srchcnd);
@@ -87,14 +81,11 @@ function EgovAdminScheduleList(props) {
setScheduleList(resp.result.resultList);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminScheduleList.retrieveList()");
}, []);
const drawCalendar = () => {
- console.groupCollapsed("EgovAdminScheduleList.drawCalendar()");
const PREV_MONTH_ADDITION = -1;
let lastOfLastMonth = getLastDateOfMonth(
@@ -110,27 +101,8 @@ function EgovAdminScheduleList(props) {
searchCondition.month
);
- console.log(
- "lastOfLastMonth : ",
- lastOfLastMonth,
- lastOfLastMonth.getDay()
- );
- console.log(
- "firstOfThisMonth :",
- firstOfThisMonth,
- firstOfThisMonth.getDay()
- );
- console.log("lastOfThisMonth :", lastOfThisMonth, lastOfThisMonth.getDay());
- console.log("scheduleList : ", scheduleList);
-
let firstDayOfThisMonth = firstOfThisMonth.getDay();
let lastDateOfThisMonth = lastOfThisMonth.getDate();
- console.log(
- "firstDayOfThisMonth",
- firstDayOfThisMonth,
- "lastDateOfThisMonth",
- lastDateOfThisMonth
- );
let monthArr = [];
let weekArr = [];
@@ -147,7 +119,6 @@ function EgovAdminScheduleList(props) {
}
}
monthArr.push(weekArr);
- console.log("FirstWeek monthArr : ", monthArr);
// firstWeek Date Set END
// otherWeek Date Set START
@@ -175,21 +146,18 @@ function EgovAdminScheduleList(props) {
monthArr.push(weekArr);
}
// lastWeek Date Set END
- console.log("OtherWeek monthArr : ", monthArr);
let mutsUseYearMonth =
searchCondition.year.toString() +
((searchCondition.month + 1).toString().length === 1
? "0" + (searchCondition.month + 1).toString()
: (searchCondition.month + 1).toString());
- console.log("mutsUseYearMonth : ", mutsUseYearMonth);
let mutCalendarTagList = [];
let keyIdx = 0;
//draw Calendar
monthArr.forEach((week) => {
- console.log();
mutCalendarTagList.push(
{week.map((day) => {
@@ -271,9 +239,7 @@ function EgovAdminScheduleList(props) {
);
});
- console.log("mutCalendarTagList : ", mutCalendarTagList);
setCalendarTag(mutCalendarTagList);
- console.groupEnd("EgovAdminScheduleList.drawCalendar()");
};
const Location = React.memo(function Location() {
@@ -304,8 +270,6 @@ function EgovAdminScheduleList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scheduleList]);
- console.log("------------------------------EgovAdminScheduleList [End]");
- console.groupEnd("EgovAdminScheduleList");
return (
diff --git a/src/pages/admin/usage/EgovAdminUsageEdit.jsx b/src/pages/admin/usage/EgovAdminUsageEdit.jsx
index 5fb41d4..39c30b0 100644
--- a/src/pages/admin/usage/EgovAdminUsageEdit.jsx
+++ b/src/pages/admin/usage/EgovAdminUsageEdit.jsx
@@ -9,13 +9,9 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
import EgovRadioButtonGroup from "@/components/EgovRadioButtonGroup";
function EgovAdminUsageEdit(props) {
- console.group("EgovAdminUsageEdit");
- console.log("[Start] EgovAdminUsageEdit ------------------------------");
- console.log("EgovAdminUsageEdit [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovAdminUsageEdit [location] : ", location);
const bbsId = location.state?.bbsId || "";
const trgetId = location.state?.trgetId || "SYSTEM_DEFAULT_BOARD";
@@ -109,7 +105,6 @@ function EgovAdminUsageEdit(props) {
if (modeStr === "POST") {
for (let key in boardDetail) {
formData.append(key, boardDetail[key]);
- //console.log("boardDetail [%s] ", key, boardDetail[key]);
}
requestOptions = {
@@ -170,8 +165,6 @@ function EgovAdminUsageEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminUsageEdit [End]");
- console.groupEnd("EgovAdminUsageEdit");
return (
@@ -223,7 +216,6 @@ function EgovAdminUsageEdit(props) {
onChange={(e) => {
let index = e.nativeEvent.target.selectedIndex;
let label = e.nativeEvent.target[index].text;
- console.log("bbsId onChange : ", e.nativeEvent);
setBoardDetail({
...boardDetail,
bbsId: e.target.value,
@@ -234,7 +226,6 @@ function EgovAdminUsageEdit(props) {
>
선택하세요
{notUsedBdMstrList.map((option) => {
- console.log("notUsedBdMstrList option : ", option);
return (
{option.bbsNm}
diff --git a/src/pages/admin/usage/EgovAdminUsageList.jsx b/src/pages/admin/usage/EgovAdminUsageList.jsx
index 7481e97..21e08b9 100644
--- a/src/pages/admin/usage/EgovAdminUsageList.jsx
+++ b/src/pages/admin/usage/EgovAdminUsageList.jsx
@@ -10,12 +10,8 @@ import EgovPaging from "@/components/EgovPaging";
import { itemIdxByPage } from "@/utils/calc";
function EgovAdminUsageList(props) {
- console.group("EgovAdminUsageList");
- console.log("[Start] EgovAdminUsageList ------------------------------");
- console.log("EgovAdminUsageList [props] : ", props);
const location = useLocation();
- console.log("EgovAdminUsageList [location] : ", location);
const cndRef = useRef();
const wrdRef = useRef();
@@ -34,7 +30,6 @@ function EgovAdminUsageList(props) {
const retrieveList = useCallback(
(srchCnd) => {
- console.groupCollapsed("EgovAdminUsageList.retrieveList()");
const retrieveListURL = "/bbsUseInf" + EgovNet.getQueryString(srchCnd);
@@ -95,10 +90,8 @@ function EgovAdminUsageList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovAdminUsageList.retrieveList()");
},
[listTag]
);
@@ -108,8 +101,6 @@ function EgovAdminUsageList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovAdminUsageList [End]");
- console.groupEnd("EgovAdminUsageList");
return (
diff --git a/src/pages/inform/daily/EgovDailyDetail.jsx b/src/pages/inform/daily/EgovDailyDetail.jsx
index c48c313..45dbc7b 100644
--- a/src/pages/inform/daily/EgovDailyDetail.jsx
+++ b/src/pages/inform/daily/EgovDailyDetail.jsx
@@ -8,12 +8,8 @@ import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavInform"
import EgovAttachFile from "@/components/EgovAttachFile";
function EgovDailyDetail(props) {
- console.group("EgovDailyDetail");
- console.log("[Start] EgovDailyDetail ------------------------------");
- console.log("EgovDailyDetail [props] : ", props);
const location = useLocation();
- console.log("EgovDailyDetail [location] : ", location);
const [scheduleDetail, setScheduleDetail] = useState({});
const [boardAttachFiles, setBoardAttachFiles] = useState();
@@ -94,8 +90,6 @@ function EgovDailyDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovDailyDetail [End]");
- console.groupEnd("EgovDailyDetail");
return (
diff --git a/src/pages/inform/daily/EgovDailyList.jsx b/src/pages/inform/daily/EgovDailyList.jsx
index db61e12..110f269 100644
--- a/src/pages/inform/daily/EgovDailyList.jsx
+++ b/src/pages/inform/daily/EgovDailyList.jsx
@@ -8,12 +8,8 @@ import CODE from "@/constants/code";
import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavInform";
function EgovDailyList(props) {
- console.group("EgovDailyDetail");
- console.log("[Start] EgovDailyDetail ------------------------------");
- console.log("EgovDailyDetail [props] : ", props);
const location = useLocation();
- console.log("EgovDailyDetail [location] : ", location);
const DATE = new Date();
const TODAY = new Date(DATE.getFullYear(), DATE.getMonth(), DATE.getDate());
@@ -101,7 +97,6 @@ function EgovDailyList(props) {
const retrieveList = useCallback(
(srchcnd) => {
- console.groupCollapsed("EgovDailyDetail.retrieveList()");
const retrieveListURL =
"/schedule/daily" + EgovNet.getQueryString(srchcnd);
@@ -120,11 +115,9 @@ function EgovDailyList(props) {
drawList();
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovDailyDetail.retrieveList()");
},
[drawList]
);
@@ -163,8 +156,6 @@ function EgovDailyList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scheduleList]);
- console.log("------------------------------EgovDailyDetail [End]");
- console.groupEnd("EgovDailyDetail");
return (
diff --git a/src/pages/inform/gallery/EgovGalleryDetail.jsx b/src/pages/inform/gallery/EgovGalleryDetail.jsx
index a9c3a25..74d00b3 100644
--- a/src/pages/inform/gallery/EgovGalleryDetail.jsx
+++ b/src/pages/inform/gallery/EgovGalleryDetail.jsx
@@ -14,13 +14,9 @@ import EgovImageGallery from "@/components/EgovImageGallery";
import { getSessionItem } from "@/utils/storage";
function EgovGalleryDetail(props) {
- console.groupEnd("EgovGalleryDetail");
- console.log("------------------------------");
- console.log("EgovGalleryDetail [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovGalleryDetail [location] : ", location);
//관리자 권한 체크때문에 추가(아래)
const sessionUser = getSessionItem("loginUser");
@@ -66,7 +62,6 @@ function EgovGalleryDetail(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> board delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.INFORM_GALLERY, { replace: true });
@@ -90,7 +85,6 @@ function EgovGalleryDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovGalleryDetail");
return (
diff --git a/src/pages/inform/gallery/EgovGalleryEdit.jsx b/src/pages/inform/gallery/EgovGalleryEdit.jsx
index d64c6ab..b616bbc 100644
--- a/src/pages/inform/gallery/EgovGalleryEdit.jsx
+++ b/src/pages/inform/gallery/EgovGalleryEdit.jsx
@@ -14,16 +14,13 @@ import { getSessionItem } from "@/utils/storage";
import { useDebouncedInput } from "@/hooks/useDebounce";
function EgovGalleryEdit(props) {
- console.group("EgovGalleryEdit");
- console.log("------------------------------");
- console.log("EgovGalleryEdit [props] : ", props);
//관리자 권한 체크때문에 추가(아래)
const sessionUser = getSessionItem("loginUser");
const sessionUniqId = sessionUser?.uniqId;
+ const sessionId = sessionUser?.id;
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovGalleryEdit [location] : ", location);
const bbsId = location.state?.bbsId || GALLERY_BBS_ID;
const nttId = location.state?.nttId || "";
@@ -117,7 +114,6 @@ function EgovGalleryEdit(props) {
const formData = new FormData();
for (let key in boardDetail) {
formData.append(key, boardDetail[key]);
- //console.log("boardDetail [%s] ", key, boardDetail[key]);
}
if (bbsFormVaildator(formData)) {
@@ -163,7 +159,6 @@ function EgovGalleryEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovGalleryEdit");
return (
@@ -233,10 +228,6 @@ function EgovGalleryEdit(props) {
masterBoard.fileAtchPosblAt === "Y" && (
{
- console.log(
- "====>>> Changed attachfile file = ",
- attachfile
- );
const arrayConcat = { ...boardDetail }; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
for (let i = 0; i < attachfile.length; i++) {
arrayConcat[`file_${i}`] = attachfile[i];
@@ -244,7 +235,6 @@ function EgovGalleryEdit(props) {
setBoardDetail(arrayConcat);
}}
fnDeleteFile={(deletedFile) => {
- console.log("====>>> Delete deletedFile = ", deletedFile);
setBoardAttachFiles(deletedFile);
}}
boardFiles={boardAttachFiles}
@@ -254,7 +244,7 @@ function EgovGalleryEdit(props) {
)}
{/* */}
- {sessionUniqId && (
+ {sessionId && (
{
- console.groupCollapsed("EgovGalleryList.retrieveList()");
const retrieveListURL = "/board" + EgovNet.getQueryString(searchCondition);
const requestOptions = {
@@ -100,10 +96,8 @@ function EgovGalleryList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovGalleryList.retrieveList()");
}, []);
//======================================================
@@ -112,8 +106,6 @@ function EgovGalleryList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovGalleryList [End]");
- console.groupEnd("EgovGalleryList");
return (
diff --git a/src/pages/inform/notice/EgovNoticeDetail.jsx b/src/pages/inform/notice/EgovNoticeDetail.jsx
index fe5694d..baf428f 100644
--- a/src/pages/inform/notice/EgovNoticeDetail.jsx
+++ b/src/pages/inform/notice/EgovNoticeDetail.jsx
@@ -10,19 +10,15 @@ import { NOTICE_BBS_ID } from "@/config";
import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavInform";
import EgovAttachFile from "@/components/EgovAttachFile";
-import { getSessionItem } from "@/utils/storage";
+import { useAuth } from "@/contexts/AuthContext";
function EgovNoticeDetail(props) {
- console.group("EgovNoticeDetail");
- console.log("------------------------------");
- console.log("EgovNoticeDetail [props] : ", props);
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovNoticeDetail [location] : ", location);
- //관리자 권한 체크때문에 추가(아래)
- const sessionUser = getSessionItem("loginUser");
- const sessionUserSe = sessionUser?.userSe;
+ // 관리자 권한 체크: 백엔드 /auth/me 결과 사용
+ const { roles } = useAuth();
+ const isAdmin = roles.includes("ROLE_ADMIN");
// 직접 URL 접근 시 location.state가 null일 수 있음
const bbsId = location.state?.bbsId || NOTICE_BBS_ID;
@@ -65,7 +61,6 @@ function EgovNoticeDetail(props) {
};
EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
- console.log("====>>> board delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
alert("게시글이 삭제되었습니다.");
navigate(URL.INFORM_NOTICE, { replace: true });
@@ -89,7 +84,6 @@ function EgovNoticeDetail(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.groupEnd("EgovNoticeDetail");
return (
@@ -163,7 +157,7 @@ function EgovNoticeDetail(props) {
{user &&
- sessionUserSe === "ADM" &&
+ isAdmin &&
masterBoard.bbsUseFlag === "Y" && (
@@ -233,10 +227,6 @@ function EgovNoticeEdit(props) {
masterBoard.fileAtchPosblAt === "Y" && (
{
- console.log(
- "====>>> Changed attachfile file = ",
- attachfile
- );
const arrayConcat = { ...boardDetail }; // 기존 단일 파일 업로드에서 다중파일 객체 추가로 변환(아래 for문으로)
for (let i = 0; i < attachfile.length; i++) {
arrayConcat[`file_${i}`] = attachfile[i];
@@ -244,7 +234,6 @@ function EgovNoticeEdit(props) {
setBoardDetail(arrayConcat);
}}
fnDeleteFile={(deletedFile) => {
- console.log("====>>> Delete deletedFile = ", deletedFile);
setBoardAttachFiles(deletedFile);
}}
boardFiles={boardAttachFiles}
@@ -254,7 +243,7 @@ function EgovNoticeEdit(props) {
)}
{/* */}
- {sessionUserSe === "ADM" && (
+ {isAdmin && (
{
- console.groupCollapsed("EgovNoticeList.retrieveList()");
const retrieveListURL = "/board" + EgovNet.getQueryString(searchCondition);
const requestOptions = {
@@ -101,10 +97,8 @@ function EgovNoticeList(props) {
setListTag(mutListTag);
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovNoticeList.retrieveList()");
}, []);
useEffect(() => {
@@ -112,8 +106,6 @@ function EgovNoticeList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovNoticeList [End]");
- console.groupEnd("EgovNoticeList");
return (
@@ -191,7 +183,7 @@ function EgovNoticeList(props) {
{/* user.id 대신 권한그룹 세션값 사용 */}
{user &&
- sessionUserSe === "ADM" &&
+ isAdmin &&
masterBoard.bbsUseFlag === "Y" && (
{
let adjustedDate = date.getDate() + date.getDay();
- console.log(
- "getWeekOfMonth : ",
- date,
- date.getDate(),
- date.getDay(),
- adjustedDate,
- adjustedDate / 7,
- 0 | (adjustedDate / 7)
- );
let weeksOrder = [0, 1, 2, 3, 4, 5];
let returnVal = parseInt(weeksOrder[0 | (adjustedDate / 7)]);
- console.log("returnVal:", returnVal);
return returnVal;
};
@@ -81,7 +67,6 @@ function EgovWeeklyList(props) {
searchCondition.date + addtionOfDays
); //다음주의 첫날
}
- console.log("changedDate : ", changedDate);
setSearchCondition({
...searchCondition,
year: changedDate.getFullYear(),
@@ -208,7 +193,6 @@ function EgovWeeklyList(props) {
const retrieveList = useCallback(
(srchcnd) => {
- console.groupCollapsed("EgovWeeklyList.retrieveList()");
const retrieveListURL =
"/schedule/week" + EgovNet.getQueryString(srchcnd);
@@ -227,11 +211,9 @@ function EgovWeeklyList(props) {
drawList();
},
function (resp) {
- console.log("err response : ", resp);
}
);
- console.groupEnd("EgovWeeklyList.retrieveList()");
},
[drawList]
);
@@ -270,8 +252,6 @@ function EgovWeeklyList(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scheduleList]);
- console.log("------------------------------EgovWeeklyList [End]");
- console.groupEnd("EgovWeeklyList");
return (
diff --git a/src/pages/login/EgovLogin.jsx b/src/pages/login/EgovLogin.jsx
index d6d55c1..2ea7072 100644
--- a/src/pages/login/EgovLogin.jsx
+++ b/src/pages/login/EgovLogin.jsx
@@ -5,17 +5,10 @@ import EgovLoginContent from "@/pages/login/EgovLoginContent";
import URL from "@/constants/url";
function EgovLogin(props) {
- console.group("EgovLogin");
- console.log("[Start] EgovLogin ------------------------------");
- console.log("EgovLogin [props] : ", props);
-
const onChangeLogin = (user) => {
props.onChangeLogin(user);
};
- console.log("------------------------------EgovLogin [End]");
- console.groupEnd("EgovLogin");
-
return (
diff --git a/src/pages/login/EgovLoginContent.jsx b/src/pages/login/EgovLoginContent.jsx
index 3520ad7..ea5749d 100644
--- a/src/pages/login/EgovLoginContent.jsx
+++ b/src/pages/login/EgovLoginContent.jsx
@@ -5,21 +5,19 @@ import * as EgovNet from "@/api/egovFetch";
import URL from "@/constants/url";
import CODE from "@/constants/code";
import { getLocalItem, setLocalItem, setSessionItem } from "@/utils/storage";
+import { hashPassword } from "@/utils/passwordHash";
import SnsNaverBt from "@/components/sns/SnsNaverBt";
import SnsKakaoBt from "@/components/sns/SnsKakaoBt";
+import { useAuth } from "@/contexts/AuthContext";
function EgovLoginContent(props) {
- console.group("EgovLoginContent");
- console.log("[Start] EgovLoginContent ------------------------------");
- console.log("EgovLoginContent [props] : ", props);
-
const navigate = useNavigate();
const location = useLocation();
- console.log("EgovLoginContent [location] : ", location);
+ const { refresh } = useAuth();
const [userInfo, setUserInfo] = useState({
id: "",
- password: "default",
+ password: "",
userSe: "USR",
});
// eslint-disable-next-line no-unused-vars
@@ -57,9 +55,9 @@ function EgovLoginContent(props) {
}, []);
useEffect(() => {
- let data = getLocalItem(KEY_ID);
- if (data !== null) {
- setUserInfo({ id: data, password: "default", userSe: "USR" });
+ const savedId = getLocalItem(KEY_ID);
+ if (savedId) {
+ setUserInfo((prev) => ({ ...prev, id: savedId }));
}
}, []);
@@ -75,8 +73,25 @@ function EgovLoginContent(props) {
}
}
};
- const submitFormHandler = () => {
- console.log("EgovLoginContent submitFormHandler()");
+ const submitFormHandler = async () => {
+ if (!userInfo.id?.trim()) {
+ alert("아이디를 입력해 주세요.");
+ idRef.current.focus();
+ return;
+ }
+ if (!userInfo.password) {
+ alert("비밀번호를 입력해 주세요.");
+ passwordRef.current.focus();
+ return;
+ }
+ if (userInfo.password.length < 6) {
+ alert("비밀번호는 6자 이상이어야 합니다.");
+ passwordRef.current.focus();
+ return;
+ }
+
+ // R-07: 비밀번호를 1차 SHA-256 해시로 변환해 전송 — DevTools/네트워크에 평문 노출 차단.
+ const hashedPassword = await hashPassword(userInfo.id, userInfo.password);
const loginUrl = "/auth/login-jwt";
@@ -85,19 +100,18 @@ function EgovLoginContent(props) {
headers: {
"Content-type": "application/json",
},
- body: JSON.stringify(userInfo),
+ body: JSON.stringify({ ...userInfo, password: hashedPassword }),
};
EgovNet.requestFetch(loginUrl, requestOptions, (resp) => {
- let resultVO = resp.resultVO;
- let jToken = resp?.jToken || null;
-
- setSessionItem("jToken", jToken);
-
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
- //setLoginVO(resultVO);
+ // JWT는 httpOnly 쿠키로 수신 — sessionStorage에 토큰 저장하지 않음
+ // uniqId는 게시물 작성자 본인 확인 UI에 필요 (비밀 정보 아님)
+ const { id, name, userSe, uniqId } = resp.resultVO || {};
+ const resultVO = { id, name, userSe, uniqId };
setSessionItem("loginUser", resultVO);
props.onChangeLogin(resultVO);
+ refresh(); // AuthContext 갱신 — /auth/me 재호출로 권한 정보 동기화
if (saveIDFlag) setLocalItem(KEY_ID, resultVO?.id);
navigate(URL.MAIN);
// PC와 Mobile 열린메뉴 닫기
@@ -111,9 +125,6 @@ function EgovLoginContent(props) {
});
};
- console.log("------------------------------EgovLoginContent [End]");
- console.groupEnd("EgovLoginContent");
-
return (
{/* */}
diff --git a/src/pages/main/EgovMain.jsx b/src/pages/main/EgovMain.jsx
index 04bd14a..9bd48ee 100644
--- a/src/pages/main/EgovMain.jsx
+++ b/src/pages/main/EgovMain.jsx
@@ -8,26 +8,19 @@ import initPage from "@/js/ui";
import { fetchMainPage } from "@/api/services/mainPage";
import BoardList from "./fragments/BoardList";
function EgovMain(props) {
- console.group("EgovMain");
- console.log("[Start] EgovMain ------------------------------");
- console.log("EgovMain [props] : ", props);
-
const location = useLocation();
- console.log("EgovMain [location] : ", location);
const [noticeBoardList, setNoticeBoardList] = useState([]);
const [gallaryBoardList, setGallaryBoardList] = useState([]);
const retrieveList = async () => {
- console.groupCollapsed("EgovMain.retrieveList()");
try {
const resp = await fetchMainPage();
setNoticeBoardList(resp.result.notiList);
setGallaryBoardList(resp.result.galList);
} catch (err) {
- console.error("err response : ", err);
+ // 오류는 사용자 알림 없이 조용히 처리
}
- console.groupEnd("EgovMain.retrieveList()");
};
useEffect(() => {
@@ -35,9 +28,6 @@ function EgovMain(props) {
retrieveList();
}, []);
- console.log("------------------------------EgovMain [End]");
- console.groupEnd("EgovMain");
-
return (
diff --git a/src/pages/mypage/EgovMypageEdit.jsx b/src/pages/mypage/EgovMypageEdit.jsx
index 706b1f2..110da93 100644
--- a/src/pages/mypage/EgovMypageEdit.jsx
+++ b/src/pages/mypage/EgovMypageEdit.jsx
@@ -8,15 +8,9 @@ import CODE from "@/constants/code";
import { getSessionItem, setSessionItem } from "@/utils/storage";
function EgovMypageEdit(props) {
- console.group("EgovMypageEdit");
- console.log("[Start] EgovMypageEdit ------------------------------");
- console.log("EgovMypageEdit [props] : ", props);
-
const navigate = useNavigate();
const location = useLocation();
const checkRef = useRef([]);
-
- console.log("EgovMypageEdit [location] : ", location);
//const uniqId = location.state?.uniqId || "";
const [modeInfo, setModeInfo] = useState({ mode: props.mode });
const [memberDetail, setMemberDetail] = useState({});
@@ -66,17 +60,10 @@ function EgovMypageEdit(props) {
};
EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
- console.log("mypage retrieveDetail response:", resp);
- console.log("resp.result:", resp?.result);
- console.log("resp.result.mberManageVO:", resp?.result?.mberManageVO);
-
- // 수정모드일 경우 조회값 세팅
if (modeInfo.mode === CODE.MODE_MODIFY) {
if (resp && resp.result && resp.result.mberManageVO) {
- console.log("Setting member detail:", resp.result.mberManageVO);
setMemberDetail(resp.result.mberManageVO);
} else if (resp && resp.resultCode === "403") {
- console.error("Permission denied for mypage:", resp);
// 백엔드에서 반환한 에러 메시지가 있으면 사용
const errorMessage =
resp && resp.resultMessage
@@ -85,15 +72,12 @@ function EgovMypageEdit(props) {
alert(errorMessage);
window.location.href = URL.LOGIN;
} else if (resp && resp.resultCode === "401") {
- console.error("Authentication required for mypage:", resp);
alert("로그인이 필요합니다.");
window.location.href = URL.LOGIN;
} else if (resp && resp.resultCode === "900") {
- console.error("Data error for mypage:", resp);
alert(resp.resultMessage || "회원 정보를 불러올 수 없습니다.");
window.location.href = URL.LOGIN;
} else {
- console.error("mberManageVO not found in response:", resp);
// 백엔드에서 반환한 에러 메시지가 있으면 사용
const errorMessage =
resp && resp.resultMessage
@@ -258,10 +242,9 @@ function EgovMypageEdit(props) {
};
EgovNet.requestFetch(deleteMypageURL, requestOptions, (resp) => {
- console.log("====>>> member delete= ", resp);
if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
setSessionItem("loginUser", { id: "" });
- setSessionItem("jToken", null);
+ // ACCESS_TOKEN 쿠키는 백엔드가 관리 — 별도 삭제 불필요
// PC와 Mobile 열린메뉴 닫기
document.querySelector(".all_menu.WEB").classList.add("closed");
document.querySelector(".btnAllMenu").classList.remove("active");
@@ -281,9 +264,6 @@ function EgovMypageEdit(props) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- console.log("------------------------------EgovMypageEdit [End]");
- console.groupEnd("EgovMypageEdit");
-
return (
diff --git a/src/routes/index.jsx b/src/routes/index.jsx
index ac31901..3d60253 100644
--- a/src/routes/index.jsx
+++ b/src/routes/index.jsx
@@ -3,6 +3,7 @@ import { Navigate, Routes, Route, useLocation } from "react-router-dom";
import URL from "@/constants/url";
import CODE from "@/constants/code";
+import { useAuth } from "@/contexts/AuthContext";
//COMMON
import EgovHeader from "@/components/EgovHeader";
@@ -76,113 +77,52 @@ import EgovMypageEdit from "@/pages/mypage/EgovMypageEdit";
import initPage from "@/js/ui";
const RootRoutes = () => {
- //useLocation객체를 이용하여 정규표현식을 사용한 /admin/~ 으로 시작하는 경로와 비교에 사용(아래 1줄) */}
const location = useLocation();
+ // 인증 상태는 백엔드 /auth/me 결과(AuthContext)를 진실 소스로 사용.
+ // sessionStorage 변조로 우회 불가.
+ const { user, roles, loading } = useAuth();
- // JWT 토큰 정보 가져오기 함수 추가
- // eslint-disable-next-line no-unused-vars
- const [userRole, setUserRole] = useState(""); // 사용자 권한 저장
-
- // JWT 토큰에서 사용자 권한 정보 확인
- const getUserRoleFromToken = useCallback(() => {
- console.group("getUserRoleFromToken");
- console.log("[Start] getUserRoleFromToken ------------------------------");
-
- // 세션에서 JWT 토큰 가져오기
- const token = sessionStorage.getItem("jToken");
-
- if (token) {
- try {
- // JWT 토큰 파싱 (간단한 방식으로 처리)
- const tokenParts = token.split(".");
- if (tokenParts.length === 3) {
- const payload = JSON.parse(atob(tokenParts[1]));
- const role = payload.groupNm || "";
- console.log("User role from token:", role);
- setUserRole(role);
- return role;
- }
- } catch (error) {
- console.error("JWT 토큰 파싱 중 오류:", error);
- }
- }
-
- console.log("JWT 토큰에서 권한 정보를 찾을 수 없음");
- setUserRole("");
- return "";
- }, []);
-
- // 경로에 따른 인증 처리를 위한 함수 추가
const checkPathAccess = useCallback(() => {
- console.group("checkPathAccess");
- console.log("[Start] checkPathAccess ------------------------------");
- console.log("Current path:", location.pathname);
+ // 인증 상태 로딩 중에는 라우트 가드 보류
+ if (loading) return;
- // 현재 경로 가져오기
const currentPath = location.pathname;
const adminRegex = /^\/admin(\/.*)?$/;
const mypageRegex = /^\/mypage(\/.*)?$/;
- // JWT 토큰에서 사용자 로그인 정보 확인
- const token = sessionStorage.getItem("jToken");
-
- if (!token) {
- console.log("로그인 정보가 없습니다.");
+ const isLoggedIn = !!user?.id;
+ const isAdmin = roles.includes("ROLE_ADMIN");
- // 로그인이 필요한 경로인 경우 처리
+ if (!isLoggedIn) {
if (adminRegex.test(currentPath) || mypageRegex.test(currentPath)) {
- console.log("로그인이 필요한 경로입니다.");
setMounted(false);
alert("로그인이 필요한 경로입니다.");
window.location.href = URL.LOGIN;
return false;
}
-
- // 로그인이 필요하지 않은 경로인 경우
setMounted(true);
return true;
}
- // 사용자 권한 확인
- const role = getUserRoleFromToken();
- console.log("User role:", role);
-
- // 관리자 페이지 접근 처리
if (adminRegex.test(currentPath)) {
- if (role !== "ROLE_ADMIN") {
- console.log("관리자 권한이 없어 접근이 불가합니다.");
+ if (!isAdmin) {
setMounted(false);
alert("관리자 권한이 필요한 페이지입니다.");
window.location.href = URL.MAIN;
return false;
- } else {
- console.log("관리자 권한 확인 성공.");
- setMounted(true);
- return true;
}
+ setMounted(true);
+ return true;
}
- // 마이페이지 접근 처리 - 로그인한 유저라면 접근 가능
if (mypageRegex.test(currentPath)) {
- if (!token) {
- console.log("로그인이 필요한 경로입니다.");
- setMounted(false);
- alert("로그인이 필요한 페이지입니다.");
- window.location.href = URL.LOGIN;
- return false;
- } else {
- console.log("로그인 사용자 확인 성공.");
- setMounted(true);
- return true;
- }
+ setMounted(true);
+ return true;
}
- // 기본적으로 모든 다른 경로는 접근 가능
setMounted(true);
- console.log("------------------------------checkPathAccess [End]");
- console.groupEnd("checkPathAccess");
return true;
- }, [getUserRoleFromToken, location.pathname]);
+ }, [loading, user, roles, location.pathname]);
//시스템관리 메뉴인 /admin/으로 시작하는 URL은 모두 로그인이 필요하도록 코드추가(아래)
const isMounted = useRef(false); // 아래 로그인 이동 부분이 2번 실행되지 않도록 즉, 마운트 될 때만 실행되도록 변수 생성
diff --git a/src/utils/bbsFormVaildator.jsx b/src/utils/bbsFormVaildator.jsx
deleted file mode 100644
index 63e5daa..0000000
--- a/src/utils/bbsFormVaildator.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-const bbsFormVaildator = (formData) => {
- if (formData.get("nttSj") === null || formData.get("nttSj") === "") {
- alert("제목은 필수 값입니다.");
- return false;
- }
- if (formData.get("nttCn") === null || formData.get("nttCn") === "") {
- alert("내용은 필수 값입니다.");
- return false;
- }
- return true;
-};
-
-export default bbsFormVaildator;
diff --git a/src/utils/calc.jsx b/src/utils/calc.jsx
deleted file mode 100644
index 753e282..0000000
--- a/src/utils/calc.jsx
+++ /dev/null
@@ -1 +0,0 @@
-export const itemIdxByPage = (resultCnt, currentPageNo, pageSize, index) => resultCnt + 1 - ((currentPageNo - 1) * pageSize + index + 1);
\ No newline at end of file
diff --git a/src/utils/logger.js b/src/utils/logger.js
new file mode 100644
index 0000000..825b9a8
--- /dev/null
+++ b/src/utils/logger.js
@@ -0,0 +1,44 @@
+const SENSITIVE_KEYS = /(password|jToken|authorization|access_token|refresh_token|ihidnum|secret)/i;
+
+function mask(value, seen = new WeakSet()) {
+ if (value == null) return value;
+ // 문자열·숫자 등 원시값은 그대로 통과. 마스킹은 "객체 내부에서 SENSITIVE_KEYS 와 매칭되는 키의 값" 에만 적용된다 (의도: 일반 메시지는 보존, 민감 정보만 차단).
+ if (typeof value !== "object") return value;
+
+ // 특수 객체는 spread 시 internal slot 정보가 손실되므로(Date → {}, Error → {} 등)
+ // 원본 그대로 콘솔에 위임. 콘솔이 자체적으로 적절히 표시한다.
+ if (
+ value instanceof Date ||
+ value instanceof Error ||
+ value instanceof RegExp ||
+ value instanceof Map ||
+ value instanceof Set ||
+ (typeof Blob !== "undefined" && value instanceof Blob) ||
+ (typeof FormData !== "undefined" && value instanceof FormData) ||
+ value instanceof ArrayBuffer ||
+ ArrayBuffer.isView(value)
+ ) {
+ return value;
+ }
+
+ // 순환 참조 가드 — `obj.self = obj` 같은 입력에서 무한 재귀 방지
+ if (seen.has(value)) return "[Circular]";
+ seen.add(value);
+
+ const cloned = Array.isArray(value) ? [...value] : { ...value };
+ for (const k of Object.keys(cloned)) {
+ if (SENSITIVE_KEYS.test(k)) cloned[k] = "***";
+ else if (typeof cloned[k] === "object") cloned[k] = mask(cloned[k], seen);
+ }
+ return cloned;
+}
+
+const noop = () => {};
+const isProd = import.meta.env.PROD;
+
+export const logger = {
+ log: isProd ? noop : (...args) => console.log(...args.map(mask)),
+ info: isProd ? noop : (...args) => console.info(...args.map(mask)),
+ warn: (...args) => console.warn(...args.map(mask)),
+ error: (...args) => console.error(...args.map(mask)),
+};
diff --git a/src/utils/oauthState.js b/src/utils/oauthState.js
new file mode 100644
index 0000000..20dd77d
--- /dev/null
+++ b/src/utils/oauthState.js
@@ -0,0 +1,15 @@
+const stateKey = (provider) => `oauth_state_${provider}`;
+
+export function issueState(provider) {
+ const buf = new Uint8Array(16);
+ crypto.getRandomValues(buf);
+ const state = Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join("");
+ sessionStorage.setItem(stateKey(provider), state);
+ return state;
+}
+
+export function consumeState(provider, received) {
+ const saved = sessionStorage.getItem(stateKey(provider));
+ sessionStorage.removeItem(stateKey(provider));
+ return saved != null && saved === received;
+}
diff --git a/src/utils/passwordHash.js b/src/utils/passwordHash.js
new file mode 100644
index 0000000..cd6267a
--- /dev/null
+++ b/src/utils/passwordHash.js
@@ -0,0 +1,17 @@
+/**
+ * 로그인 비밀번호 클라이언트 측 1차 해싱.
+ *
+ * 백엔드 EgovFileScrty.encryptPassword(password, id) 와 동일 형식의
+ * Base64(SHA-256(id_bytes ++ password_bytes)) 을 만든다.
+ *
+ * 서버는 받은 1차 해시에 한 번 더 SHA-256 을 적용해 이중해시로 저장값과 비교한다.
+ * 클라이언트가 보내는 값과 DB 저장값이 다르므로 DB 유출 시 그 값으로 직접 로그인할 수 없다.
+ */
+export async function hashPassword(id, password) {
+ const data = new TextEncoder().encode(id + password);
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
+ const bytes = new Uint8Array(hashBuffer);
+ let binary = "";
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
+ return btoa(binary);
+}
diff --git a/vite.config.js b/vite.config.js
index bac6adb..a1432a7 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -40,11 +40,14 @@ export default defineConfig(({ mode }) => ({
},
build: {
chunkSizeWarningLimit: 100000000,
+ sourcemap: false,
},
esbuild: {
loader: "jsx",
include: /\.[jt]sx?$/,
exclude: [],
+ drop: mode === "production" ? ["console", "debugger"] : [],
+ pure: mode === "production" ? ["console.log", "console.info", "console.debug", "console.trace"] : [],
},
optimizeDeps: {
esbuildOptions: {