리액트 폴더 구조에 대한 고민

리액트는 특정 폴더 구조를 강제하지 않는다. 프로젝트의 규모와 복잡성에 따라 다양한 폴더 구조를 적용할 수 있다. 중요한 것은 폴더 구조의 일관성을 유지하고 팀 내에 합의된 구조를 따르는 것이다.

잘 정의된 폴더 구조는 코드의 가독성과 유지보수성의 향상, 재사용성 및 확장성을 증가시키며 팀 내에서 협업을 원활하게 한다. 이러한 이유로 프로젝트 초기 단계부터 폴더 구조에 대해 고민하고 계획하는 것이 필요하다.

폴더 구조 설계를 해보았다

여러 디자인 패턴들을 참고해보고 나름대로 폴더 구조를 잡아보았다.

React 디자인 패턴

📦 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 /> },
    ],
  },
]);

💬 프론트엔드 폴더 구조는 코드의 가독성, 유지보수성, 그리고 팀 협업의 효율성을 높이는 핵심 요소

카테고리:

업데이트:

댓글남기기