개인 프로젝트 | Linkeeper - 2
리액트 폴더 구조에 대한 고민
리액트는 특정 폴더 구조를 강제하지 않는다. 프로젝트의 규모와 복잡성에 따라 다양한 폴더 구조를 적용할 수 있다. 중요한 것은 폴더 구조의 일관성을 유지하고 팀 내에 합의된 구조를 따르는 것이다.
잘 정의된 폴더 구조는 코드의 가독성과 유지보수성의 향상, 재사용성 및 확장성을 증가시키며 팀 내에서 협업을 원활하게 한다. 이러한 이유로 프로젝트 초기 단계부터 폴더 구조에 대해 고민하고 계획하는 것이 필요하다.
폴더 구조 설계를 해보았다
여러 디자인 패턴들을 참고해보고 나름대로 폴더 구조를 잡아보았다.
📦 linkeeper
┣ 📂public
┣ 📂src
┃ ┣ 📂api
┃ ┣ 📂assets
┃ ┣ 📂components
┃ ┃ ┣ 📂auth
┃ ┃ ┣ 📂common
┃ ┃ ( ... )
┃ ┃ ┣ 📂sidebar
┃ ┣ 📂hooks
┃ ┣ 📂layouts
┃ ┣ 📂pages
┃ ┣ 📂shared
┃ ┣ 📂styles
┃ ┗ 📂typings
api
: 서버와의 통신을 위한 API 호출 함수들assets
: 이미지, 폰트, 아이콘 등과 같은 정적 자원components
: 재사용 가능한 UI 컴포넌트들hooks
: 커스텀 훅layouts
: 헤더, 푸터, 사이드바 등의 공통 레이아웃 요소pages
: 각 페이지를 구성하는 컴포넌트shared
: 여러 컴포넌트나 페이지에서 공유하여 사용할 수 있는 공통 요소나 유틸리티 함수들styles
: 전역 스타일, 테마, 변수 등 CSS 관련 파일typings
: 타입 정의와 인터페이스 관리
리액트는 SPA이지만 페이지가 있다. React Router를 사용해 페이지를 만들기 때문에 pages
폴더 내의 컴포넌트를 페이지 진입점으로 사용한다. 또한 라우터 구조를 설정할 때 pages/index.ts
파일에서 내보낸 모듈들을 가져와 import 코드를 줄일 수 있다.
// src/pages/index.ts
import Home from './Home';
import MajorTopic from './MajorTopic';
import SubTopic from './SubTopic';
import Profile from './Profile';
import SearchResults from './SearchResults';
import NotFound from './NotFound';
import Bookmark from './Bookmark';
export { Home, MajorTopic, SubTopic, Profile, SearchResults, NotFound, Bookmark };
// BEFORE
import Home from './pages/Home';
import MajorTopic from './pages/MajorTopic';
import SubTopic from './pages/SubTopic';
import Profile from './pages/Profile';
import SearchResults from './pages/SearchResults';
import NotFound from './pages/NotFound';
import Bookmark from './pages/Bookmark';
// AFTER
import { Home, MajorTopic, SubTopic, Profile, SearchResults, NotFound, Bookmark } from './pages';
공통되거나 페이지에서 사용되는 컴포넌트는 components
폴더에, 페이지들 간 공통 레이아웃은 layouts
폴더에 저장한다.
components
폴더 내부에는 각 도메인별로 폴더를 만들어 해당 도메인에 사용되는 컴포넌트끼리 그룹화한다. 컴포넌트들을 도메인별로 나누었을 때 컴포넌트를 찾거나 추가할 때 편리하다.
Router.tsx
파일과 pages
폴더의 예시로 살펴보기
pages
폴더는 각각의 페이지를 나타내는 컴포넌트들을 모아두었다. 따라서 pages
폴더를 보면 각 페이지 컴포넌트의 역할과 위치를 쉽게 파악할 수 있다.
📦linkeeper
┣ 📂public
┃ ┗ 📜logo.svg
┣ 📂src
┃ ┣ 📂pages
┃ ┃ ┣ 📜Bookmark.tsx
┃ ┃ ┣ 📜Home.tsx
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜MajorTopic.tsx
┃ ┃ ┣ 📜NotFound.tsx
┃ ┃ ┣ 📜Profile.tsx
┃ ┃ ┣ 📜SearchResults.tsx
┃ ┃ ┗ 📜SubTopic.tsx
┃ ┣ ( ... )
┃ ┣ 📜App.tsx
┃ ┣ 📜main.tsx
┃ ┣ 📜Router.tsx
┣ ( ... )
이처럼 폴더 구조가 잘 정리되어 있으면 다른 팀원이 보기에도 코드를 더 빠르게 이해할 수 있어 협업하기가 쉬워진다. 게다가 잘 정의된 폴더 구조는 새로운 컴포넌트나 기능을 보다 쉽게 추가할 수 있어 확장성이 높다.
// Router.tsx
import { createBrowserRouter } from 'react-router-dom';
import App from './App';
import {
Home,
NotFound,
MajorTopic,
SubTopic,
Bookmark,
SearchResults,
Profile,
} from './pages';
export const router = createBrowserRouter([
{
path: '/',
element: <App />,
errorElement: <NotFound />,
children: [
{ path: '/', element: <Home />, index: true },
{
path: '/topics/:major',
element: <MajorTopic />,
},
{
path: '/topics/:major/:sub',
element: <SubTopic />,
},
{ path: '/bookmark', element: <Bookmark /> },
{ path: '/search/:query', element: <SearchResults /> },
{ path: '/profile/:id', element: <Profile /> },
],
},
]);
💬 프론트엔드 폴더 구조는 코드의 가독성, 유지보수성, 그리고 팀 협업의 효율성을 높이는 핵심 요소
댓글남기기