diff --git a/src/App.tsx b/src/App.tsx
index 7f3a6b92..1b4f138f 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -3,7 +3,7 @@ import { sessionReplayPlugin } from '@amplitude/plugin-session-replay-browser';
import { MutationCache, QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { AxiosError } from 'axios';
-import { useEffect, useRef, useState } from 'react';
+import { lazy, Suspense, useEffect, useRef, useState } from 'react';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';
import Layout from '@components/Layout';
@@ -11,16 +11,20 @@ import DeviceTypeProvider from 'contexts/DeviceTypeProvider';
import RecruitingInfoProvider from 'contexts/RecruitingInfoProvider';
import ThemeProvider, { useTheme } from 'contexts/ThemeProvider';
import { dark, light } from 'styles/theme.css';
-import { SessionExpiredDialog } from 'views/dialogs';
-import ErrorPage from 'views/ErrorPage';
-import MainPage from 'views/MainPage';
-import PasswordPage from 'views/PasswordPage';
-import ResultPage from 'views/ResultPage';
-import ReviewPage from 'views/ReviewPage';
-import SignupPage from 'views/SignupPage';
+import BigLoading from 'views/loadings/BigLoding';
import 'styles/reset.css';
+const SessionExpiredDialog = lazy(() =>
+ import('views/dialogs').then(({ SessionExpiredDialog }) => ({ default: SessionExpiredDialog })),
+);
+const MainPage = lazy(() => import('views/MainPage'));
+const PasswordPage = lazy(() => import('views/PasswordPage'));
+const ResultPage = lazy(() => import('views/ResultPage'));
+const ReviewPage = lazy(() => import('views/ReviewPage'));
+const SignupPage = lazy(() => import('views/SignupPage'));
+const ErrorPage = lazy(() => import('views/ErrorPage'));
+
const router = createBrowserRouter([
{
path: '/',
@@ -113,7 +117,9 @@ const App = () => {
-
+ }>
+
+
diff --git a/src/views/ApplyPage/index.tsx b/src/views/ApplyPage/index.tsx
index fca7b4e9..45add81a 100644
--- a/src/views/ApplyPage/index.tsx
+++ b/src/views/ApplyPage/index.tsx
@@ -1,5 +1,5 @@
import { track } from '@amplitude/analytics-browser';
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { lazy, useCallback, useEffect, useRef, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
@@ -9,8 +9,6 @@ import useCheckBrowser from '@hooks/useCheckBrowser';
import useDate from '@hooks/useDate';
import useScrollToHash from '@hooks/useScrollToHash';
import { useDeviceType } from 'contexts/DeviceTypeProvider';
-import { DraftDialog, PreventApplyDialog, SubmitDialog } from 'views/dialogs';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import ApplyCategory from './components/ApplyCategory';
@@ -29,6 +27,13 @@ import { buttonWrapper, container, formContainerVar } from './style.css';
import type { ApplyRequest } from './types';
+const DraftDialog = lazy(() => import('views/dialogs').then(({ DraftDialog }) => ({ default: DraftDialog })));
+const PreventApplyDialog = lazy(() =>
+ import('views/dialogs').then(({ PreventApplyDialog }) => ({ default: PreventApplyDialog })),
+);
+const SubmitDialog = lazy(() => import('views/dialogs').then(({ SubmitDialog }) => ({ default: SubmitDialog })));
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
interface ApplyPageProps {
onSetComplete?: () => void;
}
diff --git a/src/views/MyPage/index.tsx b/src/views/MyPage/index.tsx
index 9c3831de..3d1a8399 100644
--- a/src/views/MyPage/index.tsx
+++ b/src/views/MyPage/index.tsx
@@ -1,4 +1,5 @@
import { track } from '@amplitude/analytics-browser';
+import { lazy } from 'react';
import Button from '@components/Button';
import Callout from '@components/Callout';
@@ -6,7 +7,6 @@ import Title from '@components/Title';
import useDate from '@hooks/useDate';
import { useDeviceType } from 'contexts/DeviceTypeProvider';
import { useRecruitingInfo } from 'contexts/RecruitingInfoProvider';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import {
@@ -19,6 +19,8 @@ import {
buttonWidthVar,
} from './style.css';
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const MyInfoItem = ({ label, value }: { label: string; value?: string | number | boolean }) => {
const { deviceType } = useDeviceType();
const isMasking = label !== '지원서';
diff --git a/src/views/PasswordPage/components/PasswordForm/index.tsx b/src/views/PasswordPage/components/PasswordForm/index.tsx
index 95578add..4b45499e 100644
--- a/src/views/PasswordPage/components/PasswordForm/index.tsx
+++ b/src/views/PasswordPage/components/PasswordForm/index.tsx
@@ -1,5 +1,5 @@
import { track } from '@amplitude/analytics-browser';
-import { useRef } from 'react';
+import { lazy, useRef } from 'react';
import { FormProvider, useForm, type FieldValues } from 'react-hook-form';
import Button from '@components/Button';
@@ -7,11 +7,12 @@ import { TextBox비밀번호, TextBox이름, TextBox이메일 } from '@component
import { VALIDATION_CHECK } from '@constants/validationCheck';
import useVerificationStatus from '@hooks/useVerificationStatus';
import { useRecruitingInfo } from 'contexts/RecruitingInfoProvider';
-import { CompleteDialog } from 'views/dialogs';
import useMutateChangePassword from 'views/PasswordPage/hooks/useMutateChangePassword';
import { formWrapper } from './style.css';
+const CompleteDialog = lazy(() => import('views/dialogs').then(({ CompleteDialog }) => ({ default: CompleteDialog })));
+
const PasswordForm = () => {
const completeDialog = useRef(null);
const {
diff --git a/src/views/PasswordPage/index.tsx b/src/views/PasswordPage/index.tsx
index 7c34ad82..8959e0d8 100644
--- a/src/views/PasswordPage/index.tsx
+++ b/src/views/PasswordPage/index.tsx
@@ -1,12 +1,15 @@
+import { lazy } from 'react';
+
import Title from '@components/Title';
import useDate from '@hooks/useDate';
import { useDeviceType } from 'contexts/DeviceTypeProvider';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import PasswordForm from './components/PasswordForm';
import { containerVar } from './style.css';
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const PasswordPage = () => {
const { deviceType } = useDeviceType();
const { NoMoreRecruit, isLoading, isMakers } = useDate();
diff --git a/src/views/ResultPage/index.tsx b/src/views/ResultPage/index.tsx
index e36211ce..3d5db6db 100644
--- a/src/views/ResultPage/index.tsx
+++ b/src/views/ResultPage/index.tsx
@@ -1,14 +1,15 @@
-import { useEffect } from 'react';
+import { useEffect, lazy } from 'react';
import useDate from '@hooks/useDate';
import { useTheme } from 'contexts/ThemeProvider';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import useGetMyInfo from 'views/SignedInPage/hooks/useGetMyInfo';
import FinalResult from './components/FinalResult';
import ScreeningResult from './components/ScreeningResult';
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const ResultPage = () => {
const { handleChangeMode } = useTheme();
const { myInfoData, myInfoIsLoading } = useGetMyInfo();
diff --git a/src/views/ReviewPage/index.tsx b/src/views/ReviewPage/index.tsx
index 4a794713..87e4a406 100644
--- a/src/views/ReviewPage/index.tsx
+++ b/src/views/ReviewPage/index.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { lazy, useCallback, useEffect, useRef, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import useDate from '@hooks/useDate';
@@ -15,10 +15,13 @@ import PartSection from 'views/ApplyPage/components/PartSection';
import useGetDraft from 'views/ApplyPage/hooks/useGetDraft';
import useGetQuestions from 'views/ApplyPage/hooks/useGetQuestions';
import { container, formContainerVar } from 'views/ApplyPage/style.css';
-import { PreventReviewDialog } from 'views/dialogs';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
+const PreventReviewDialog = lazy(() =>
+ import('views/dialogs').then(({ PreventReviewDialog }) => ({ default: PreventReviewDialog })),
+);
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const ReviewPage = () => {
const { deviceType } = useDeviceType();
const preventReviewDialog = useRef(null);
diff --git a/src/views/SignInPage/index.tsx b/src/views/SignInPage/index.tsx
index 95058526..dae11867 100644
--- a/src/views/SignInPage/index.tsx
+++ b/src/views/SignInPage/index.tsx
@@ -1,12 +1,15 @@
+import { lazy } from 'react';
+
import useDate from '@hooks/useDate';
import { useDeviceType } from 'contexts/DeviceTypeProvider';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import SignInForm from './components/SignInForm';
import SignInInfo from './components/SignInInfo';
import { containerVar } from './style.css';
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const SignInPage = () => {
const { deviceType } = useDeviceType();
const { isLoading, NoMoreRecruit, isMakers } = useDate();
diff --git a/src/views/SignupPage/components/SignupForm/index.tsx b/src/views/SignupPage/components/SignupForm/index.tsx
index 8ee7d6b3..89d9d78e 100644
--- a/src/views/SignupPage/components/SignupForm/index.tsx
+++ b/src/views/SignupPage/components/SignupForm/index.tsx
@@ -1,5 +1,5 @@
import { track } from '@amplitude/analytics-browser';
-import { useEffect, useRef } from 'react';
+import { lazy, useEffect, useRef } from 'react';
import { type FieldValues, FormProvider, useForm } from 'react-hook-form';
import Button from '@components/Button';
@@ -11,11 +11,14 @@ import { PRIVACY_POLICY } from '@constants/policy';
import { VALIDATION_CHECK } from '@constants/validationCheck';
import useVerificationStatus from '@hooks/useVerificationStatus';
import { useRecruitingInfo } from 'contexts/RecruitingInfoProvider';
-import { ExistingApplicantDialog } from 'views/dialogs';
import useMutateSignUp from 'views/SignupPage/hooks/useMutateSignUp';
import { formWrapper } from './style.css';
+const ExistingApplicantDialog = lazy(() =>
+ import('views/dialogs').then(({ ExistingApplicantDialog }) => ({ default: ExistingApplicantDialog })),
+);
+
const SignupForm = () => {
const {
recruitingInfo: { season, group },
diff --git a/src/views/SignupPage/index.tsx b/src/views/SignupPage/index.tsx
index 18c271de..b7098b2f 100644
--- a/src/views/SignupPage/index.tsx
+++ b/src/views/SignupPage/index.tsx
@@ -1,12 +1,15 @@
+import { lazy } from 'react';
+
import Title from '@components/Title';
import useDate from '@hooks/useDate';
import { useDeviceType } from 'contexts/DeviceTypeProvider';
-import NoMore from 'views/ErrorPage/components/NoMore';
import BigLoading from 'views/loadings/BigLoding';
import SignupForm from './components/SignupForm';
import { containerVar } from './style.css';
+const NoMore = lazy(() => import('views/ErrorPage/components/NoMore'));
+
const SignupPage = () => {
const { deviceType } = useDeviceType();
const { NoMoreRecruit, NoMoreApply, isLoading, isMakers } = useDate();
diff --git a/vite.config.ts b/vite.config.ts
index 9b97e8c2..5ceda280 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -12,11 +12,19 @@ export default defineConfig({
vanillaExtractPlugin(),
visualizer({
filename: './dist/report.html',
- open: true,
gzipSize: true,
brotliSize: true,
}) as PluginOption,
],
+ build: {
+ rollupOptions: {
+ output: {
+ manualChunks: (id) => {
+ if (id.includes('firebase')) return 'firebase';
+ },
+ },
+ },
+ },
resolve: {
alias: [
{ find: '@apis', replacement: path.resolve(__dirname, 'src/common/apis') },