프로젝트 시작점
react에서는 주로 react-router-dom을 이용해서 라우팅을 처리하고, next.js에서는 내장된 파일/폴더 기반 라우팅을 이용합니다
저는 주로 next.js를 사용해서 파일/폴더 기반 라우팅이 더 익숙하였고, 이를 react-router-dom에서도 사용하고싶은 마음에 시작하였습니다.
프로젝트 아이디어
기본적인 아이디어는 next.js의 폴더 기반 라우팅을 그대로 구현하는거였습니다.
즉 [폴더명]/page.tsx 구조로 제한을 걸고 폴더명이 path가 되는 방식입니다
이를 위해서는 내부적으로 폴더/파일 구조를 탐색하고 이 특정 패턴의 폴더/파일 경로를 가져와서 react-router object로 바꾸는 방법이 있다고 생각하였습니다
실제 구현
`import.meta.glob()`를 활용하는게 핵심이였습니다
이를 통해 `/src/pages/**/page.{jsx,tsx}` 패턴의 파일/폴더 경로를 모두 가져옵니다
const modules = import.meta.glob('/src/pages/**/page.{jsx,tsx}');
이러면 아래와 같은 결과가 나오게될것입니다
{
'/src/pages/home/page.tsx': () => import('/src/pages/home/page.tsx'),
'/src/pages/about/page.tsx': () => import('/src/pages/about/page.tsx'),
...
}
이제 이 객체를 돌면서 key와 value를 적절하게 포멧해줍니다
예를들어 "/src/pages/**/page.{jsx,tsx}" 에서 앞의 "/src/pages"는 삭제되어야하고,
뒤에 존재하는 "page.{jsx,tsx}"도 경로에 들어가면 안됩니다
export function formatPath(filePath: string): string {
/** 윈도우 경로 구분자 처리 */
const normalizedPath = filePath.replace(/\\/g, '/');
let path = normalizedPath
.replace(/^\/src\/pages/, '') // 폴더 경로에서 `path`에 포함되지 않을 부분 제거
.replace(/\/page\.(jsx|tsx)$/, '') // 폴더 경로에서 page.tsx or page.jsx 제거
.replace(/\[([^\]]+)\]/g, ':$1'); // [id] -> :id 로 변환
if (path === '') {
path = '/';
}
return path;
}
또한 react-router Object에는 `path`와 `element`가 필요합니다
위의 `modules`의 결과를 보시면 알겠지만 dynamic 임포트를 통해 가져오므로 React.lazy를 통해 처리해주어야합니다
const element = React.lazy(modules[filePath] as any);
이제 이렇게 구성된 object를 라우터에 적용해야하므로 아래와 같이 처리할수있습니다
const element = useRoutes(routes);
이러면 "/src/pages/home/page.tsx"가 /home에 접근시 렌더링되는 것을 확인할 수 있습니다
자세한 내용은 아래 깃허브를 참고해주세요
[깃허브 - react-router-file-routing]
GitHub - joseph0926/react-router-file-routing: A library to support folder-based routing of next.js to react-router-dom
A library to support folder-based routing of next.js to react-router-dom - joseph0926/react-router-file-routing
github.com
한계점
아직 시작단계라 너무 많은 한계점이 존재하지만 일단 가장 큰 한계는 `vite`외 환경에서는 사용 불가능한 점입니다.
하지만 아직 시작단계이므로 우선 `vite` 환경에서 최대한 잘 동작하게 한 후 확장해보려합니다
다음 단계
동적 라우트를 처리하려합니다
`/src/pages/[id]/page.tsx` -> /:id
최종 목표
next.js의 폴더/파일 기반 시스템을 완전히 카피하는게 목표입니다
(loading.tsx, error.tsx ... 등)
'기타' 카테고리의 다른 글
[radix-ui] radix-ui 깃허브에 올라온 버그 이슈 수정해보기 (0) | 2024.09.19 |
---|---|
[shadcn-ui] shadcn-ui 깃허브에 올라온 버그 이슈 수정해보기 (5) | 2024.09.06 |
[기타] 네이버 카페 페이지 이동 시 url에 반영하기 (0) | 2024.08.24 |
[Frontend] 요구사항에 따른 디자인 시스템 설계하기 (0) | 2023.07.15 |