💡프로젝트 구조
React 프로젝트를 구성할 때 효율적이고 유지보수가 용이한 폴더 구조를 만드는 것은 매우 중요하다.
이를 위해서는 기능적으로 연관된 파일들을 그룹화하고, 각 파일이 어디에 속하는지 명확하게 파악할 수 있도록 구조를 설계해야 한다.
프로젝트 구조를 적용할 때는 팀원들과의 커뮤니케이션을 통해 일관된 방식으로 파일을 구성하도록 한다.
1. src/ 디렉터리
index.js 살펴보기
프로젝트의 구조에서 가장 중요한 것은 src 폴더이다. src는 source의 약자로, 프로젝트의 모든 소스 코드가 포함된 최상위 디렉터리이다.
src 폴더에는 입구 파일이라고 할 수 있는 index.js 파일이 있다. npm start 명령어로 create-react-app을 구동시키면 index.js를 찾아서 적혀 있는 코드에 따라 동작하게 된다.
index.js에는 여러 전역적인 설정들이 들어가며, 이후 App.js에서 내용을 편집하며 UI를 변경하면 된다.
2. public/ 디렉터리
public 디렉터리는 src처럼 초기에 생성되는 폴더 중 하나로, 정적 자원이 위치하는 디렉터리이다.
주로 웹 애플리케이션의 진입점인 index.html 파일과 해당 웹 애플리케이션의 아이콘 파일인 favicon.ico 등이 위치한다.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
위 코드는 index.js 코드의 일부이다. <App />이라는 태그가 Id값이 root인 태그로 rendering 되도록 하고 있으며, 이와 관련한 설정 파일은 public 폴더 안에 위치한다.
index.html 살펴보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
index.html 파일의 <body> 태그 내부에 id가 root인 <div> 태그를 확인할 수 있다.
<div id="root" style="border: 10px solid cornflowerblue"></div>
root 태그인 것을 확인하기 위해 css로 border를 적용해 보면 디자인이 변경되는 것을 확인할 수 있다.
3. assets/ 디렉터리
public과 마찬가지로 이미지나 글꼴과 같은 정적 자원을 저장하는 디렉터리이다.
컴파일 시 필요한 파일들은 이 디렉터리에 위치시키고, 컴포넌트 내부에서만 사용되는 파일은 public/ 디렉터리에 위치시킬 수 있다.
4. app/ 디렉터리
프로젝트의 핵심 기능과 관련된 파일을 담는 디렉터리이다.
예를 들어 API 호출이나 상태 관리와 관련된 코드를 여기에 위치시킬 수 있다.
5. components/ 디렉터리
재사용 가능한 UI 컴포넌트를 담는 디렉터리이다.
컴포넌트마다 별도의 폴더를 만들고, 해당 컴포넌트의 JavaScript 파일과 CSS 파일을 함께 두는 방식으로 구성할 수 있다.
6. features/ 디렉터리
프로젝트의 기능을 기반으로 파일을 구성하는 디렉터리이다.
각 기능에 대한 파일들을 그룹화하여 정리하고, API 호출이나 상태 관리와 관련된 코드를 포함할 수 있다.
7. hooks/ 디렉터리
커스텀 훅을 담는 디렉터리이다.
재사용 가능한 훅들을 여기에 위치시킴으로써 코드의 재사용성을 높일 수 있다.
8. layout/ 디렉터리
레이아웃 파일을 담는 디렉터리이다.
애플리케이션의 전반적인 레이아웃을 정의하는 파일들을 여기에 위치시킬 수 있다.
9. pages/ 디렉터리
라우팅에 사용되는 페이지 컴포넌트를 담는 디렉터리이다.
각 페이지의 컴포넌트를 그룹화하여 정리하고, 하위 폴더를 만들어 연관된 컴포넌트들을 함께 묶을 수 있다.
10. styles/ 디렉터리
CSS 파일들을 담는 디렉터리이다.
프로젝트에서 사용되는 모든 스타일 시트들을 여기에 위치시킬 수 있다.
11. types/ 디렉터리
타입 정의 파일을 담는 디렉터리이다.
프로젝트에서 사용되는 모든 타입들을 여기에 위치시킴으로써 코드의 타입 안정성을 높일 수 있다.
12. utils/ 디렉터리
공통 함수나 상수들을 담는 디렉터리이다.
유틸리티 함수들을 여기에 위치시킴으로써 코드의 재사용성을 높일 수 있다.
💡index.js 파일 동작
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
위 화면에서 돌아가는 React 로고는 <App />로 인해서 동작되고 있는 상태이다. 즉, <App />는 이 UI 전체를 의미한다.
이 <App />은 상단의 import App를 통해서 왔으며, 이때 App은 from './App'에서 왔다.
'.'이라는 기호는 현재 디렉터리를 의미하며, 여기서 App의 뒤에는 확장자명이 생략되어 있는 상태이다.
App.js
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
App이 어디서 왔는지를 더 자세히 알기 위해 App.js 파일을 확인해 보도록 하자.
소스 코드를 살펴보면, App()이라는 함수 안에 UI를 구성하고 있는 것을 확인할 수 있다.
App.js 수정하기
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
Hello React!
</div>
);
}
export default App;
그래서 만약 App.js를 위와 같이 수정하면 화면도 바뀌게 된다.
App.css
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
글자가 가운데에 위치해 있는 것은 App.css에서 디자인이 적용되고 있기 때문이다.
text-align: center 속성으로 인해서 글자가 가운데 정렬되고 있다. 이와 같이 UI의 디자인을 수정할 때에는 App.css 파일을 수정하면 된다.
또한, index.js 파일에도 index.css 파일이 있다. 이 파일을 통해 기본적으로 sample에 대해서 사용하고 있는 css를 수정할 수 있다.
💡프로젝트 배포
npm start를 통해 실행시킨 현재의 애플리케이션은 개발을 위한 애플리케이션이다. 하지만, 서비스하기에는 용량이 크고, 여러 가지 불필요한 메시지를 표시하고 있기 때문에 실제로 서비스하기에는 적합하지 않은 상태이다. 따라서 어떻게 하면 서비스에 최적화되어 있는 효율적인 배포본을 만들 수 있는가에 대해 알아보도록 하자.
build 명령어
npm run build
터미널에서 기존의 개발 환경을 Ctrl + C 단축키로 꺼준 뒤, 위의 빌드 명령어를 실행한다.
build 폴더 생성
그러면 이와 같이 build라는 폴더가 생성된다.
이 폴더 안에는 index.html을 비롯한 파일들이 생성되며, 배포할 때에는 공백이 필요 없기 때문에 공백이 사라진다.
serve 명령어
build한 결과를 서비스할 때, serve를 사용하는 것을 추천하고 있다. serve에서 -s라는 옵션을 사용하게 되면 사용자가 어떤 경로에서 들어오더라도 index.html 파일을 서비스한다. 그리고 build 폴더를 지정하면 build 폴더 내의 index.html 파일을 서비스한다는 의미가 된다.
npx serve -s build
serve는 Node.js로 만들어진 애플리케이션이므로, npx를 사용하여 실행한다.
serve 명령어를 실행하면 build 폴더에 있는 index.html을 서비스하는 웹 서버가 실행되며, 접속할 수 있는 주소를 만들어준다.
이 경로의 주소로 들어가면 실제로 서비스 할 수 있는 버전의 파일이 만들어진 것을 확인할 수 있다.
참고자료
React 2022년 개정판 - 3. 소스코드수정방법, 생활코딩, 2022.03.17.
React 프로젝트 폴더구조 리팩토링, 지금부터가 반전, 2023.10.16.