본문 바로가기

FE Dev./React

📚 React + Next.js + TypeScript 폴더 구조 완벽 가이드

리액트 로고

App Router / Pages Router / 환경별 구조 차이까지 정리

1. 들어가며

기본적으로 React의 폴더 구조가 어떻게 되는지 정리해본다.

 

리액트는 환경(설정)에 따라 폴더구조가 다르다. 그래서 같은 리액트를 사용한다고 해도 어떻게 초반에 설정을 했느냐에 구조가 다를 수 밖에 없다.

 

필자는 리액트를 시작한지 얼마안되었지만 개인 프로젝트 및 회사에서의 프로젝트를 고려했을 때 아래와 같이 고민을 했었다.

“폴더 구조를 어떻게 잡아야 하지?”

 

예제를 보거나 강의를 몇개를 찾아보면 조금씩 다르기 때문이다. 물론 리액트와 Next.js 버전, TypeScript 따라 달라질 수 있는에 정확하게 어떻게 달라지는지 기록을 해보려고 한다.

 

특히 Next.js를 사용할 때는 App RouterPages Router라는 두 가지 라우팅 방식이 있고, 여기에 TypeScript, 상태 관리, API 연동, 스타일 전략까지 더해지면 폴더 구조가 제각각 달라진다.

 

2. React + TypeScript 기본 구조

(Vite, CRA 등 Next.js 없이 단독 React 프로젝트)

my-react-app/
├─ public/                  # 정적 파일
├─ src/
│  ├─ app/                  # 엔트리와 전역 설정
│  ├─ pages/                # react-router 페이지
│  ├─ features/             # 도메인 단위(회원, 글, 결제 등)
│  ├─ components/           # 공용 UI
│  ├─ hooks/                 # 전역 커스텀 훅
│  ├─ store/                # Zustand, Redux 전역 상태
│  ├─ services/             # API 클라이언트, Firebase/Supabase 연동
│  ├─ lib/                   # 유틸, 헬퍼 함수
│  ├─ styles/               # 전역 스타일
│  ├─ types/                # 전역 타입 정의
│  └─ config/               # 환경 설정, 상수
└─ vite.config.ts

 

💡 포인트

 

  • pages → URL 매핑되는 화면
  • features → 관련 로직, API, UI, 타입을 한 기능 단위로 모음
  • services → 외부 서비스 연동

 

3. Next.js + TypeScript (App Router 기준)

Next.js 13+에서 기본 라우팅 방식이다.

my-next-app/
├─ public/
├─ app/
│  ├─ layout.tsx              # 루트 레이아웃
│  ├─ page.tsx                # /
│  ├─ dashboard/
│  │  ├─ layout.tsx
│  │  ├─ page.tsx
│  │  └─ settings/page.tsx
│  ├─ api/                    # Route Handlers (간단 API)
│  │  └─ auth/route.ts
│  └─ actions/                # 서버 액션
├─ components/                # 공용 UI
├─ features/                  # 도메인 단위 모듈
├─ lib/                        # DB, 인증, 유틸
├─ providers/                 # 전역 Provider
├─ styles/                    # 전역 CSS, Tailwind
├─ types/
└─ config/

 

 

💡 App Router 특징

  • 페이지·레이아웃이 폴더 구조로 매핑
  • 서버 컴포넌트 기본, "use client"로 클라이언트 전환
  • 서버 액션(Server Action)을 페이지 근처에 둘 수 있음

4. Next.js + TypeScript (Pages Router 기준)

Next.js 12 또는 App Router를 쓰지 않는 경우

my-next-pages-app/
├─ public/
├─ pages/
│  ├─ _app.tsx               # 전역 레이아웃/Provider
│  ├─ _document.tsx          # HTML 문서 커스터마이즈
│  ├─ index.tsx              # /
│  ├─ about.tsx              # /about
│  ├─ blog/[slug].tsx        # 동적 라우트
│  └─ api/                   # API 라우트
│     └─ auth.ts
├─ components/               # 공용 UI
├─ features/                 # 도메인 단위 모듈
├─ lib/                       # 유틸, API 클라이언트
├─ hooks/
├─ styles/
├─ types/
└─ config/

 

 

💡 Pages Router 특징

  • pages/ 폴더 안에 라우트 정의
  • getStaticProps, getServerSideProps 등 페이지에서 직접 데이터 패칭
  • API 라우트는 pages/api/ 안에 위치

5.  App Router vs Pages Router 비교

구분 App Router Pages Router
라우트 정의 app/ 폴더 구조 기반 pages/ 폴더 파일명 기반
전역 레이아웃 app/layout.tsx pages/_app.tsx
데이터 패칭 서버 컴포넌ㅌ, 서버 액션, fetch API getStaticProps, getServerSideProps
API 라우트  app/api/**/route.ts pages/api/**
기본 컴포넌트 서버 컴포넌트 클라이언트 컴포넌트

 

 

6. 왜 환경(설정)에 따라 폴더 구조가 달라질까? 

 

  • 라우팅 방식
    • App Router는 서버 액션과 서버 컴포넌트 중심 → 도메인별 로직 근접 배치
    • Pages Router는 페이지 중심 → 페이지는 얇게, 기능 폴더에서 로직 처리
  • 배포 대상
    • Serverless/Edge: 환경별 DB, 캐시 유틸 분리 필요
    • Node 서버: 서버 전용 코드와 클라이언트 코드를 명확히 구분
  • 데이터 패칭 전략
    • 클라이언트 패칭(SWR, React Query) vs SSR/SSG 여부에 따라 fetch 로직 위치가 달라짐
  • 인증/세션 방식
    • NextAuth, JWT, OAuth에 따라 API 라우트나 미들웨어가 추가됨
  • 스타일 방식
    • Tailwind, CSS-in-JS, CSS Modules 중 무엇을 쓰느냐에 따라 styles/ 구조가 달라짐
  • 모노레포 여부
    • Turborepo/PNPM 환경이면 공용 패키지를 packages/로 분리

 

7. 폴더별 자세히 설명

  1. app/
    • Next.js 13 이상에서의 페이지 라우트 관리 폴더이다.
    • 경로에 따라 폴더를 쪼개서 파일 시스템 기반 라우팅을 한다.
    • 각 폴더 아래에 page.tsx, layout.tsx 등 파일이 들어간다.
    • (Next.js 12 이하에서는 pages/ 폴더 사용)
  2. components/
    • 버튼, 카드, 모달, 폼 등 UI 단위의 재사용 가능한 컴포넌트들을 넣는 곳
    • 서브 폴더를 만들어 도메인별, 기능별로 구분할 수도 있다
  3. lib/
    • 외부 라이브러리 래퍼, API 인스턴스(axios 등), 공통 유틸 함수, 인증 처리 등
    • 비즈니스 로직에 가까운 재사용 코드를 넣습니다.
      ex) lib/tmdb.ts, lib/firebase.ts, lib/auth.ts 등
  4. styles/
    • 전역 스타일, reset, theme, CSS 변수, styled-components의 글로벌 스타일 등
    • scss, css, tailwind 등 어떤 스타일링 방법이든 여기에 모아둡니다.
  5. hook/
    • 커스텀 React Hook(useSomething.ts)들을 모아둡니다.
      ex) useAuth.ts, useModal.ts, useFetch.ts 등
  6. types/
    • TypeScript의 타입, 인터페이스, enum 등을 정의합니다.
    • 타입 재사용이 쉽고, 코드 자동완성에도 도움이 됩니다.
  7. public/
    • 웹 서버에서 직접 접근 가능한 정적 파일(이미지, 폰트, favicon 등)
  8. assets/
    • 디자인 리소스(아이콘, 일러스트, mock 데이터 등)를 분리해서 관리한다.
    • public/과 비슷하지만, 코드에서 import해서 사용하는 리소스라면 assets/를 쓴다.
  9. constansts/
    • 여러 곳에서 쓰는 문자열, 숫자, 환경설정 값 등
      ex) API_URL, PAGE_SIZE, ROUTE_PATHS 등
  10. services/
    • 외부 API 요청, 비즈니스 로직 처리 함수 등
    • lib/와 비슷하지만, 더 비즈니스 중심적인 코드에 집중
  11. utils/
    • 날짜 포맷팅, 숫자 변환 등 작고 단순한 함수 모음
  12. contents/
    • React Context API 관련 코드(Provider, Context 정의 등)
  13. store/
    • 상태관리 라이브러리(Redux, Zustand 등) 관련 코드
  14. test
    • 단위/통합 테스트 코드(jest, react-testing-library 등)

 

8. TypeScript 설정 팁 (경로 별칭)

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@components/*": ["./src/components/*"],
      "@features/*": ["./src/features/*"],
      "@lib/*": ["./src/lib/*"]
    }
  }
}

 

 

9. 마무리

프로젝트의 폴더 구조에 정답은 없는거 같다.
다만, 환경(라우팅 방식, 배포, 데이터 패칭, 인증 방식 등)에 따라 응집도와 확장성을 고려한 구조를 잡는 것이 중요하다고 한다.

핵심 원칙: 페이지는 얇게, 기능은 두껍게!
그리고 관련 파일은 가깝게(co-location) 두기.

 

 

 

반응형
LIST