어쩌다 보니 회사에서 현재 진행중인 프로젝트를 처음부터 더 깔끔하게 마이그레이션을 하기로 결정이났다.
일반적인 웹사이트가 아니라 소프트웨어 앱에 가까운 프로젝트이다 보니,
해물짬뽕 스파게티코드
가 탄생하기도 해서, 리팩토링보다는 처음부터 구조를 완벽하게 짜는게 나을 것 같다는 판단이었다. ( 기존 배포 유지 마이그레이션 버전의 수준이 올라오면 갈아끼울 예정 )
오랜만에 폴더구조부터 만드려고 하니 오히려 재밌다라는 생각을 했다. 매일 빽빽한 코드만 보다가 내가 폴더구조부터 내가 설계할 수 있다보니까 설레는 마음으로 검색을 시작했다.
가장 중요한포인트로 생각한 것은 우리 프로젝트 코드에서 가장 유지보수 효율이 좋을 것 같은 폴더구조를 고민하게 되었다.
여러 폴더구조 아키텍쳐를 찾아봤지만 여기서 장단점을 나열할 필요는 없을 것 같아서 결론부터 적자면, FSD기반 으로 도메인 단위로 폴더를 구분하기로 결정했다.
- 각 도메인마다 페이지, 상태, API, UI 컴포넌트가 긴밀히 묶여 있음
- React Query / Zustand / Custom Hook 등 상태 관리를 도메인 별로 스코핑 가능
- Electron 같은 멀티 플랫폼 확장도 고려 시 유리 → React Native 또는 Electron에서는 features/XXX만 선택적으로 마운트할 수 있어 확장성 뛰어남
그렇다면 이제 본론으로 들어가서
lazy import + suspense와 react-router 을 이용하여 번들링 크기 줄이고 브라우저 성능 향상시키기 에 대해 설명을 할 차례이다.
우선 프로젝트 전체를
FSD + 코드 스플리팅
으로 다시 짜겠다는 것은 결국 도메인 별로 잘린 작은 번들들이, 필요한 순간에만 브라우저에 내려오게 해서 초기 번들링 크기를 줄이는 것이다.
이렇게 구현을 하면 초기 렌더가 오래걸린다는SPA의 단점
을 어느정도 상쇄시킬 수 있는 전략이라고 생각이 들었다.
import { lazy } from "react";
export const AuthPage = lazy(() => import("./AuthPage"));
import 시점을 애플리케이션 로드
→ 해당 라우트 진입
으로 미룸.
그리고 라우트 레벨에서 Suspense
경계로 감싸주면 끝.
import { createBrowserRouter, RouterProvider } from "react-router";
import { Suspense } from "react";
import LoadingSkeleton from "@/shared/components/LoadingSkeleton";
import { AuthPage } from "@/features/group/pages/AuthPage.lazy";
const router = createBrowserRouter([
{
path: "/groups/:id",
element: (
<Suspense fallback={<LoadingSkeleton />}>
<AuthPage />
</Suspense>
),
},
]);
export default function AppRouter() {
return <RouterProvider router={router} />;
우선 미리 알아둬야 하는 것이 아직 제대로 나눈 것이 아니라 기존 버전의 코드에서 더 효율적인 코드 스플릿 없이 대충 lazyLoading 만 사용해서 스플리팅한 무거운 빌드 파일을 나눈 상황이라 그닥 좋은 빌드 파일이라고는 말을 못하겠다.
하지만 사진으로 볼 수 있듯이 초기 렌더가 3379.43kb → 1423.54kb까지 약 58 % 감소했고, 대략 2.4 배 가까이 빠른 초기 로드를 체감할 수 있다. 그만큼 네트워크 전송량·파싱·실행 시간이 가벼워 진다는 것이다.
💡 하지만 다시 한번 말하지만 현재 예시는 실용적인 스플리팅 없이 그냥 꽝 나눈 코드기 때문에 만일 dist/assets/Canvas-BXSx-WT0.js 청크
를 로드할떄 또 그만큼의 속도가 걸린 다는 것이기 때문에 더 효율적으로 코드스플리팅
을 할 필요가 있다.
SSR, 서버 컴포넌트도 생각을 해봤지만 우리는 에디터툴을 개발중인 상태라서 SEO가 필요없다고 판단됐고, 추후에 Electron 확장 가능성도 있어서 CSR + 코드 스플리팅이 더 맞는 상태라고 판단했다.