이롭게 현명하게
[React] 리액트 폴더 구조 본문

목차
리액트 기본 폴더 및 파일
src 내부 폴더 구조
[번외] package.json
[리액트 기본 폴더 및 파일]
프로젝트를 진행하다 보면 관리해야 할 파일들이 늘어난다.
파일들을 효율적으로 관리해야 하기 때문에 폴더의 구조를 잘 잡아야 한다.
24년 가지는 CRA를 사용하여 프로젝트를 구성했다.
하지만 2025년 2월 14일 리액트 공식 블로그에 CRA 사용을 중단한다는 글이 올라왔다.
그래서 vite를 사용하여 리액트 환경을 구성한다.
이 글에서는 타입스크립트를 기준으로 설명하겠습니다.
https://devyihyun.tistory.com/230
[React] vite로 리액트 설치하기
목차 create-react-app 지원 종료vite를 사용하는 이유vite 시작하기 https://devyihyun.tistory.com/168 [React] 리액트 시작하기 / 리액트 설치 / 개발환경목차 작업환경 준비하기Node.js 설치하기yarn 설치하기vscode
devyihyun.tistory.com
https://devyihyun.tistory.com/168
[React] 리액트 시작하기 / 리액트 설치 / 개발환경
목차 작업환경 준비하기Node.js 설치하기yarn 설치하기vscode 설치하기git for windows 설치하기리액트 환경설정 리액트 환경을 설치하는 CRA가 2025년 2월 14일에 종료되었습니다.npx create-react-app 대신 vite
devyihyun.tistory.com
아래는 vite로 생성한 리액트 프로젝트에서 기본적으로 설치되는 폴더 및 파일들이다.
react-project/
├── node_modules/
├── public/
├── src/
├── .gitignore
├── index.html
├── package.json
├── README.md
├── tsconfig.json
├── vite.config.ts

<node_modules>
install을 실행할 때 자동으로 생성된다.
노드 패키지 관리자 (npm)가 리액트 프로젝트에 필요한 dependcies를 보관하는 저장 디렉터리 역할을 한다.
- 프로젝트에서 설치한 모든 패키지가 들어있는 폴더
- 용량이 크고 자동 설치 가능
- git 에는 올리지 않는다. (.gitignore로 제외)
- 이 폴더가 없거나 삭제되었다면 install 하면 된다.
<pubilc>
- 정적 파일 보관 폴더(리소스 파일)
- favicon, 이미지 등을 넣는다.
- 빌드 시 수정 없이 그대로 복사된다.
- ex) public/images/test.png 서버에서 → url로 접근 가능
- 실제 서비스 배포 시 서버에서 접근 가능한 리소스는 대부분 public 폴더에 위치한다.
<src>
- 애플리케이션의 실제 소스 코드가 위치하는 폴더
- 리액트 컴포넌트, 스타일, 훅 등
- main.tsx에서 App.tsx를 렌더링 하며 앱이 시작된다.
src/
├── components/ # 공통 UI 컴포넌트
├── pages/ # 라우팅 되는 페이지 컴포넌트
├── hooks/ # 커스텀 훅
├── assets/ # 이미지,폰트 등
├── utils/ # 공통 유틸 함수
├── App.tsx # 루트 컴포넌트
├── main.tsx # 진입점
- src
- assets
- 이미지, 글꼴 및 기타 정적 리소스가 포함되어 있다.
- main.tsx / main.jsx
- React 앱의 진입점으로 루트 컴포넌트(App.ts)를 렌더링 하고, 이를 index.html에 주입하며 React의 업격한 모드와 구성을 설정하는 역할
- app.tsx / app.jsx
- 애플리케이션의 ui 구조와 로직을 정의하는 주요 React 구성 요소
- main.js 내부에서 렌더링 되며 다른 구성 요소의 루트 구성요소로 사용된다.
- src 내의 공통 폴더
- assets
<.gitignore>
- Git에 커밋되지 않도록 무시할 파링 목록 지정
- push를 해도 .gitignore 파일에 작성된 폴더와 파일은 올라가지 않는다.
- node_modules, dist, env 등 민감하거나 용량이 큰 파일 제외
<index.html>
- 리액트 앱의 단일 HTML 템플릿
- <div id="root"> </div>가 리액트 앱이 렌더링 되는 곳
- main.tsx가 사용되는 곳
<package.json>
- 프로젝트의 메타 정보 및 의존성 리스트가 들어있다.
- Git 저장소에 올라가면 팀원들이 이 파일을 기준으로 npm install을 할 수 있다.
<README.md>
- 프로젝트 소개 및 사용 방법 등을 적는 문서
- 깃과 같은 저장소에 올릴 때 프로젝트에 대한 설명을 작성하는 곳
- 해당저장소에 진입하면 가장 먼저 띄워진다.
<tsconfig.josn>
- 타입스크립트 프로젝트 설정 파일
<vite.config.ts>
- vite의 설정 파일
- ex) 플러그인 추가, 환경 변수 관리 등
<App.tsx 또는 App.jsx>
- 앱의 루트 컴포넌트
- 전체 앱의 레이아웃, 라우터, 전역 Provider 등이 정의된다.
<main.tsx 또는 main.tsx>
- 앱의 진입점
- React.DOM.createRoot로 App.tsx를 DOM에 렌더링 한다.
- ReactRouter 사용 시 <BrowserRouter>로 App을 감싼다.
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
<index.css, App.css>
- 전역 및 컴포넌트용 CSS 파일
- 필요에 따라 테일윈드, SCSS 등으로 대체 가능
[src 내부 폴더 구조]
src/
├── assets/
├── components/
├── pages/
├── hooks/
├── utils/
├── routes/
├── layouts/
├── stores/
├── services/
├── style/
├── App.tsx
├── main.tsx
| 폴더명 | 용도 |
| assets/ | 이미지, 폰트, SVG 등 정적 리소스 |
| components/ | 재사용 가능한 작은 단위 UI 컴포넌트 |
| pages/ | 라우팅 단위 페이지 (한 화면 단위) |
| hooks/ | 로직 재사용을 위한 커스텀 훅 (useXXX) 모음 |
| utils/ | 유틸 함수, 포맷터, 헬퍼 함수 |
| routes/ | 라우터 설정 관련 파일(예 : React Router) |
| layouts/ | 페이지 공통 레이아웃 컴포넌트 |
| stores/ | 상태 관리(예 : Zustand,Recoil, Redux) |
| services/ | API 요청 로직 (axios, fetch) 등 네트워크 관련 환경 |
| style/ | css 파일들이 포함되는 폴더 |
assets
- 이미지, 폰트, 비디오, json 파일 등 미디어 파일들을 모아두어 저장하는 곳
- 컴포넌트 내부에서 사용하는 이미지 파일인 경우 assets 폴더에 위치시켜야 한다.
- public과 차이점 : 컴파일 시에 필요한지 여부
- favicon과 같이 index.html 내부에서 직접 사용하여 컴파일 단계에서 필요하지 않은 파일들은 public에
components
- 재사용 가능한 컴포넌트들이 위치하는 폴더
- 컴포넌트는 많아질 수 있기 때문에 이 폴더 내부에서 하위 폴더로 추가로 분류하는 경우가 많다.
- 공통 컴포넌트 관리(ex 헤더, 푸터, nav 등)
pages
- react router 등을 이용하여 라우팅을 적용할 때
- 페이지 단위의 컴포넌트 폴더로 구성
- 로그인 페이지 - Login.tsx, login.css
- 홈페이지 - Home.tsx, home.css
<components vs pages>
- components : 여러 페이지에 동시에 사용되는 컴포넌트의 경우
- pages : 해당 페이지 내에서만 사용하는 컴포넌트의 경우
hooks(=hocs)
- 커스텀 훅이 위치하는 폴더
- 함수형 컴포넌트를 사용하면서 커스텀 훅을 모듈화 하여 담아놓는 폴더
utils
- 정규 표현식 패턴이나 공통함수 등 공통으로 사용하는 util 파일들이 위치하는 폴더
- 상수나 공통함수, 유틸리티
layouts
- 헤더, 푸터 등 프로젝트 전체에서 사용할 수 있는 레이아웃이 포함
stores
- 상태에 저장하고 관리할 정보가 많은 대형 프로젝트에서 사용
- 전역 상태 관리 라이브러리를 사용하면서 데이터를 저장하고 모듈화 해서 관리하는 폴더
services(=api)
- api 관련 로직의 모듈 파일
- auth와 같이 인증과 관련된 파일이 포함
style
- css 파일들이 포한되는 폴더
- scss 사용 시
- react.scss → css 초기화
- common.scss → 공통으로 사용하는 css 속성 정의
- styled component 사용 시
- GlobalStyle.js → css 초기화
- theme.ts → 공통으로 사용하는 css 속성 정의 이외에 media.js 등등 다양한 css 파일을 속성에 맞게 분류하여 모듈화
- scss 사용 시
[번외] package.json
{
"name": "react-project",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.15.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.14",
"globals": "^15.12.0",
"typescript": "~5.6.2",
"typescript-eslint": "^8.15.0",
"vite": "^6.0.0"
}
}

dependencis
- 리액트를 사용하기 위한 모든 패키지 리스트
- 실제 코드는 node_modules 폴더에 존재한다.
script
- start : 프로젝트 development mode(개발 모드) 실행을 위한 명령어 npm run start
- build : 프로젝트 production mode(배포 모드) 실행을 위한 명령어, 서비스 상용화, npm run build
<node.modules와 package.json 에서 이중으로 패키지를 관리하는 이유>
- 실제 내가 작성한 코드, 내가 설치한 패키지는 내 로컬에만 존재
- github에 올릴 때 내가 작성한 코드와 함께 package.json(추가로 설치한 패키지)를 넘긴다.
- 다른 사람이 그것을 pull 받아서 npm install만 입력하면 package.json에 기록되어 잇는 패키지의 이름과 버전 정보를 확인하여 자동으로 설치한다.
- 이때, github에 올릴 때 node_modules는 올리면 안 되는데(불필요한 용량차지) .gitignore 파일에 github에 올리고 싶지 않은 폴더와 파일을 작성할 수 있다.
<package-lock.json과 yarn.lock>
[공통점]
- 프로그래머가 관리할 필요가 없고 npm이나 yarn이 알아서 관리해 주는 파일들
- lock 파일은 해당 프로젝트에 설치한 패키지, 그 패키지와 관련된 모든 패키지의 버전 정보를 포함한다.
[package-lock.json]
- npm install을 하면 package.json을 기준으로 node_modules가 설치된다.
- package.json에서 버전 앞에 ^가 붙은 경우 최신 패치 버전이 자동으로 설치된다.
- 캐럿과 틸드
- ^ (캐럿):x.y.z 중 x 이하 하위호환성이 보장되는 범위 내에서 버전 업데이트
- 예 : ^18.4.2 → 18.4.2≤ 19.0.0
- ~(틸드) : x.y.z 중 z 범위 내에서 버전 업데이트
- 예 : ~18.4.2 → 18.4.2 ≤ 18.5.0
- 라이브러리는 계속해서버그가 수정되고 패치된다.
- 만약 npm install을 통해 내가 사용하던 버전이 아닌 최신 버전의 라이브러리가 설치된다면 라이브러리의 내용이 바뀌어 내 프로젝트에 문제가 생길 수 있다.
- 이유
- 라이브러리 A를 설치했다.
- A : ^4.18.2
- 만약 npm install을 하면 내가 사용하던 버전 그 이상의 버전으로 설치된다.
- A : ^4.18.2라는 정보가 내가 설치했을 때의 라이브러리의 내용과 다를 수 있다.
- 이것을 방지하기 위해 라이브러리를 설치했을 때의 시점에 내용이 보존되어야 한다.
- 이 문제를 방지하기 위해 사용하는 것이 package-lock.json이다.
- package-lock.json은 내가 사용했던 그 버전 그 상태 그대로 무조건 받게 끔 잠금을 해놓는 것이다.
- Github에 올릴 때는 package.json과 package-lock.json을 함께 포함시켜야 한다. → 동일한 환경 보장
[yarn.lock]
- yarn install은 yarn.lock을 기준으로 node_modules가 설치된다.
- npm과 yarn은 서로 다른 패키지 관리 시스템이다.
- 그래서 둘 다 사용하면 충돌 위험이 있다.
- package-lock.json과 yarn.lock을 동시에 사용하는 것은 금지
- 팀 프로젝트에서는 npm 또는 yarn 중 하나로 통일
[yarn을 사용하는 이유]
- yarn은 의존성 추적이 더 철저하다
- react-swiper라는 라이브러리가 있다.
- 이 라이브러리 안에는 swiper.js라는 라이브러리를 사용 중이다.
- 즉 swiper.js라는 라이브러리를 사용하여 react-swiper 라이브러리를 만든 것이다.
- react-swiper라는 라이브러리 설치
- npm은 내부에서 사용하는 swiper.js를 자동으로 설치하지 않을 수 있다. 그래서 npm install swiper.js으로 수동으로 설치해야 한다.
- yarn은 yarn add react-swiper를 하면 의존 라이브러리까지 자동으로 설치한다.
[npm에서 yarn으로 변경하고 싶을 때]
- package.json은 절대로 삭제하면 안 된다.
- node_modules와 package-lock.json 삭제
- yarn install 실행 → 자동으로 yarn.lock 생성
- 단 이때부터는 npm install 대신 yarn add로 패키지를 설치해야 한다.
잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊
댓글과 좋아요는 큰 힘이 됩니다!

[ 참고자료 ]
https://velog.io/@sisofiy626/React-리액트의-폴더-구조
[React] 리액트의 폴더 구조
프로젝트를 진행하다 보면 크기가 커질수록 관리해야할 파일은 늘어나고 이에 따라 각 파일들을 용도에 맞게 분류해야할 필요가 생깁니다.
velog.io
https://velog.io/@_seeul/React-리액트로-프로젝트를-진행할때-어떻게-폴더-구조를-잡는것이-좋을까
React | 리액트로 프로젝트를 진행할때 어떻게 폴더와 컴포넌트 구조를 설계하는 것이 좋을까?🤔
리액트 초기세팅 후 컴포넌트 구조 설계하기 🧸
velog.io
https://velog.io/@gkj8963/cra란-Create-React-App
CRA란? (+REACT 시작하기)
cra란?Set up a modern web app by running one command.손쉽게 최신의 리액트 앱을 설정할 수 있도록 하는 명령npx create-react-app '프로젝트명'(출처 : https://create-react-app.dev/
velog.io
'웹 개발 > React' 카테고리의 다른 글
| [React] 이벤트 핸들러 네이밍 on vs handle (0) | 2025.11.07 |
|---|---|
| [React] vite로 리액트 설치하기 (0) | 2025.10.22 |
| [React] EmailJS 사용방법 / 자바스크립트로 이메일 보내기 (2) | 2024.04.29 |
| [React] 리액트 useReducer (0) | 2024.01.18 |
| [React] 리액트 React.memo (0) | 2024.01.17 |
