diff --git a/index.html b/index.html index fa36f87..80a0702 100644 --- a/index.html +++ b/index.html @@ -11,8 +11,14 @@ rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Icons" /> - - + +
diff --git a/package-lock.json b/package-lock.json index 0cdf5a6..e958d7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "react-router-dom": "^7.1.5", "react-spinners": "^0.15.0", "recoil": "^0.7.7", + "rollup-plugin-visualizer": "^5.14.0", "styled-components": "^6.1.15", "text-encoding": "^0.7.0", "unsplash-js": "^7.0.19", @@ -51,7 +52,6 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^26.0.0", - "rollup-plugin-visualizer": "^5.14.0", "vite": "^6.0.5", "vitest": "^3.0.7" } @@ -3822,6 +3822,16 @@ "node": ">=10" } }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -4532,7 +4542,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/graceful-fs": { @@ -5616,9 +5626,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001704", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001704.tgz", - "integrity": "sha512-+L2IgBbV6gXB4ETf0keSvLr7JUrRVbIaB/lrQ1+z8mRcQiisG5k+lG6O4n6Y5q6f5EuNfaYXKgymucphlEXQew==", + "version": "1.0.30001705", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001705.tgz", + "integrity": "sha512-S0uyMMiYvA7CxNgomYBwwwPUnWzFD83f3B1ce5jHUfHTH//QL6hHsreI8RVC5606R4ssqravelYO5TU6t8sEyg==", "dev": true, "funding": [ { @@ -6078,7 +6088,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6521,6 +6530,17 @@ "source-map": "~0.6.1" } }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/eslint": { "version": "9.22.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", @@ -7815,7 +7835,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" @@ -8110,7 +8129,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^2.0.0" @@ -9870,9 +9888,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", - "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", + "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", "funding": [ { "type": "github", @@ -10118,7 +10136,6 @@ "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, "license": "MIT", "dependencies": { "define-lazy-prop": "^2.0.0", @@ -10970,7 +10987,7 @@ "version": "4.35.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz", "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.6" @@ -11009,7 +11026,6 @@ "version": "5.14.0", "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.14.0.tgz", "integrity": "sha512-VlDXneTDaKsHIw8yzJAFWtrzguoJ/LnQ+lMpoVfYJ3jJF4Ihe5oYLAqLklIK/35lgUY+1yEzCkHyZ1j4A5w5fA==", - "dev": true, "license": "MIT", "dependencies": { "open": "^8.4.0", @@ -11040,7 +11056,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -11049,16 +11064,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/rollup-plugin-visualizer/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/rrweb-cssom": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", @@ -11376,13 +11381,12 @@ } }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { @@ -11405,6 +11409,16 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index ea6b3b6..5b1c142 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "react-router-dom": "^7.1.5", "react-spinners": "^0.15.0", "recoil": "^0.7.7", + "rollup-plugin-visualizer": "^5.14.0", "styled-components": "^6.1.15", "text-encoding": "^0.7.0", "unsplash-js": "^7.0.19", @@ -56,7 +57,6 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^26.0.0", - "rollup-plugin-visualizer": "^5.14.0", "vite": "^6.0.5", "vitest": "^3.0.7" } diff --git a/src/api/auth/PostLogin.js b/src/api/auth/PostLogin.js index 65f4147..92a9989 100644 --- a/src/api/auth/PostLogin.js +++ b/src/api/auth/PostLogin.js @@ -3,7 +3,7 @@ const BASE_URL = import.meta.env.VITE_BASE_URL; const PostLogin = async (authCode) => { try { - const response = await axios.post(`http://10.0.133.177:8080/login`, { + const response = await axios.post(`${BASE_URL}/api/login`, { authCode, }); diff --git a/src/api/auth/PostLogout.js b/src/api/auth/PostLogout.js index ac4bade..6099f2c 100644 --- a/src/api/auth/PostLogout.js +++ b/src/api/auth/PostLogout.js @@ -4,7 +4,7 @@ const BASE_URL = import.meta.env.VITE_BASE_URL; const PostLogout = async (refreshToken) => { try { - const response = await axios.post(`${BASE_URL}/logout`, null, { + const response = await axios.post(`${BASE_URL}/api/logout`, null, { headers: { refresh: refreshToken, }, diff --git a/src/api/requestHandler.js b/src/api/requestHandler.js index 7b461e8..e25454c 100644 --- a/src/api/requestHandler.js +++ b/src/api/requestHandler.js @@ -16,7 +16,7 @@ const refreshAccessToken = async () => { throw new Error('Refresh token not found'); } - const response = await axios.post(`${BASE_URL}/token/reissue`, { + const response = await axios.post(`${BASE_URL}/api/token/reissue`, { refresh: refreshToken, }); @@ -64,7 +64,7 @@ const requestHandler = async ({ // 요청 보내기 const response = await axios({ method, - url: `http://10.0.133.177:8080/api${endpoint}`, + url: `${BASE_URL}/api${endpoint}`, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, @@ -82,10 +82,10 @@ const requestHandler = async ({ } catch (error) { console.log(error); if (error.response?.status === 401) { - //window.location.href = '/login'; - //localStorage.clear(); + window.location.href = '/login'; + localStorage.clear(); - // const originalRequest = error.config; + /* // const originalRequest = error.config; // originalRequest._retry = true; // if (isRefreshing) { @@ -111,7 +111,7 @@ const requestHandler = async ({ // isRefreshing = false; // processQueue(refreshError, null); // throw refreshError; - // } + // }*/ } if (errorMessage) { diff --git a/src/components/banner/Banner.jsx b/src/components/banner/Banner.jsx index 32781d5..eaa29da 100644 --- a/src/components/banner/Banner.jsx +++ b/src/components/banner/Banner.jsx @@ -1,42 +1,53 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, memo, Suspense } from "react"; import * as style from "./style/Banner.js"; -import banner1 from "../../assets/img/banner1.webp"; -import banner2 from "../../assets/img/banner2.webp"; -import banner3 from "../../assets/img/banner3.webp"; -import banner4 from "../../assets/img/banner4.webp"; -import banner5 from "../../assets/img/banner5.webp"; -import banner6 from "../../assets/img/banner6.webp"; -import banner7 from "../../assets/img/banner7.webp"; +import banner1 from "../../assets/img/banner1.webp"; // 기본 이미지 -const banners = [ - banner1, - banner2, - banner3, - banner4, - banner5, - banner6, - banner7 +const bannerImports = [ + () => import("../../assets/img/banner2.webp"), + () => import("../../assets/img/banner3.webp"), + () => import("../../assets/img/banner4.webp"), + () => import("../../assets/img/banner5.webp"), + () => import("../../assets/img/banner6.webp"), + () => import("../../assets/img/banner7.webp"), + () => import("../../assets/img/banner8.webp"), ]; -const Banner = () => { +const Banner = memo(() => { const [currentIndex, setCurrentIndex] = useState(0); + const [loadedBanners, setLoadedBanners] = useState([banner1]); + // ✅ Lazy Loading 적용 useEffect(() => { + const loadNextImage = async () => { + if (loadedBanners.length < bannerImports.length + 1) { + try { + const nextImage = await bannerImports[loadedBanners.length - 1](); + setLoadedBanners((prevBanners) => [...prevBanners, nextImage.default]); + } catch (error) { + console.error("Failed to load image", error); + } + } + }; + const interval = setInterval(() => { - setCurrentIndex((prevIndex) => (prevIndex + 1) % banners.length); + setCurrentIndex((prevIndex) => (prevIndex + 1) % (loadedBanners.length)); + loadNextImage(); // ✅ 다음 배너 이미지를 필요할 때만 로드 }, 4000); + return () => clearInterval(interval); - }, [currentIndex]); // ✅ `currentIndex` 변경될 때만 실행 + }, [currentIndex, loadedBanners]); return (