
1. 프로젝트 준비하기
1. 요구사항 분석하기
감정일기장: 그날의 자기 감정을 표현하는 서비스입니다. 총 4페이지로 구성되어 있습니다.
- Home페이지: 사용자가 앱에 접속하면 처음으로 만나는 페이지 (인덱스 페이지) ('/')
- new페이지: 새로운 일기를 추가하는 페이지 ('/new')
- Diary 페이지: 작성한 일기를 상세히 조회하는 페이지 ('/diary/(일기)id'
- Edit페이지: 작성한 일기를 수정하는 페이지 ('/edit/(일기)id')
2. 리액트 앱 만들기
- 작업을 할 폴더 만들기
- npx create-react-app .
- scr에서 폴터 삭제 (App.test.js, logo.svg, reportWebVitals.js, setupTest.js)
//2025-01-08
// App.js
import './App.css';
function App() {
return (
<div className="App"> </div>
);
}
export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
3. 폰트 설정하기
<구글 Fonts에 접속해 폰트 가져오기: URL>
https://fonts.google.com/ 접속 -> "Nanum Pen Scrips" or "Yeon Sung" 폰트 사용 -> 폰트 클릭 (상세페이지로 이동) -> Select Regular400 클릭 -> Use on the web dptj <Style> 태그 항목을 찾기 (css규칙이 적혀 있음) -> index.css 파일로 이동
<가져온 폰트 적용하기>
// index.css
@import url('https://fonts.googleapis.com/css2?family=Yeon+Sung&display=swap');
Body {
font-family: "Yeon Sung";
margin: 0px;
}

4. 이미지 준비하기
<감정이미지 다운로드 하기>

다운 받은 파일들은 scr폴더에 저장합니다.
//2025-01-08
// App.js
import './App.css';
import emotion1 from "./emotion/emotion1.png";
function App() {
return (
<div className="App">
<h1>감정 일기장</h1>
<img alt='감정1' src={emotion1} />
</div>
);
}
export default App;

<이미지 불러오는 함수 만들기>
//src/util.js
// 이미지 함수 불러오기
import emotion1 from "./emotion/emotion1.png";
import emotion2 from "./emotion/emotion2.png";
import emotion3 from "./emotion/emotion3.png";
import emotion4 from "./emotion/emotion4.png";
import emotion5 from "./emotion/emotion5.png";
export const getEmotionImgById = (emotion) => {
const targetEmotionId = String(emotion);
switch (targetEmotionId){
case "1":
return emotion1;
case "2":
return emotion2;
case "3":
return emotion3;
case "4":
return emotion4;
case "5":
return emotion5;
default:
return null;
}
};
//2025-01-08
// App.js
import './App.css';
import {getEmotionImgById} from "./util";
function App() {
return (
<div className="App">
<h1>감정 일기장</h1>
<img alt='감정1' src={getEmotionImgById(1)} />
<img alt='감정2' src={getEmotionImgById(2)} />
<img alt='감정3' src={getEmotionImgById(3)} />
<img alt='감정4' src={getEmotionImgById(4)} />
<img alt='감정5' src={getEmotionImgById(5)} />
</div>
);
}
export default App;

2. 페이지 라우팅
1. 라우팅의 기본 개념들
라우팅이란? 경로를 지정하는 과정으로 여러개의 라우터를 거쳐 데이터가 전송됩니다.
" 데이터 전달을 목적으로 최적의 경로를 찾아 데이터를 전송하는 과정 "
페이지 라우팅이란? 요정에 따라 적절한 페이지를 반환하는 일련의 과정입니다.
" URL 요청 경로에 맞게 적절한 페이지를 보여주는 과정 "

2. 리액트의 페이지 라우팅
웹페이지를 어디서 만드냐에 따라 서버사이드 렌더링과 클라이언트 사이드 렌더링으로 구분된다.
서버사이드 렌더링
- 웹브라우저에 URL로 서비스 요청 -> 웹서버는 URL경로 확인하고 html생성후 반환-> 웹브라우저에서 웹서버에 반환된 html을 보여줍니다. (사용자 버튼 또는 링크 클릭시) 웹서버에 반환된 html을 보여주면서 페이지가 교체되기 때문에 새로고침이 발생.
- 장: 검색엔진에 최적화하며, 퍼음 접속할 때 속도가 빠릅니다.
- 단: 서버가 새로운 페이지를 생성해 제공하려면 많은 연산을 수행하게 됩니다. 때문에 동시여청이 많아지만 부하가 걸릴 수 있습니다. 또한 브라우저가 서버가 제공하는 페이지를 기다려야 하기 때문에 속도가 느립니다.
클라이언트 사이드 렌더링
- 리액트는 단일 html파일이기 때문에 클라이언트 사이드 렌더링 방식으로 페이지 렌더링합니다.
- 웹브라우저 서비스 요청 -> index.html, 리액트 앱 반환 -> 페이지를 할당하고 리액트 실행 -> 경로에 맞는 페이지 실행 (사용자가 페이지 이동하면 웹브라우저는 서버에서 받은 리액트 앱을 실행해 페이지 교체)
- 사용자가 보는 페이지를 웹 서버가 아닌 브라우저가 완성합니다. 브러우저는 처음접속할 때만 서버에게 데이터를 요펑하며, 페이지를 이동할 때는 별도로 요청을 하지 않습니다.
- 처음 접속은 서버사이드 렌더링 보다 느리지만, 페이지 이동할 때는 브라우저 페이지를 직접 교체하므로 속도가 훨씬 빠릅니다. (페이지를 빠르게 교체한다)


3. 리액트 라우터로 페이지 라우팅하기
1. 리액트 라우터란?
리액트 라우터는 오픈소스 라이브럴리로 단 몇줄의 코드로 여러 페이지로 구성된 리액트 앱을 단단히 구축할 수 있습니다.
2. 리액트 라우터 설치하기
- npm을 이용해여 리액트 라우터를 [감정일기장]프로젝트를 설치합니다.
npm i react-router-dom
/*
웹용: npm i react-router-dom
애플리케이션용: npm i react-router-native
*/

//package.json
(...)
{
"name": "week_01_18",
"version": "0.1.0",
"private": true,
"dependencies": {
"cra-template": "1.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.28.1", // x,y,z로 x가 5 이하이면 삭제후 재설치
"react-scripts": "^5.0.1"
},
/*
npm uninstall react-router-dom: 제거
npm i react-router-dom@6: 최신버전 설치
*/
3. 프로젝트에 라우터 적용하기
- BrowserRouter에는 브라우저의 주소 변경을 감지하는 기능이 있습니다. 이 라우터는 컴포넌트가 페이지를 구성하고 이동하는 데 필요한 기능을 다양하게 제공합니다.
(...)
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
4. 페이지 컴포넌트 만들기
src/pages/
- Home: 인덱스 페이지
- New: 새 일기 작성 페이지
- Diary: 일기 상세 조회 페이지
- Edit: 작성한 일기를 수정하거나 삭제하는 페이지
const Home = () => {
return <div> Home 페이지 입니다. </div>
};
export default Home;
const New = () => {
return <div> New 페이지 입니다. </div>
};
export default New;
const Edit = () => {
return <div> Edit 페이지 입니다. </div>
};
export default Edit;
const Diary = () => {
return <div> Diary 페이지 입니다. </div>
};
export default Diary;
5. 페이지 라우팅 구현하기
4개의 컴포넌트에 URL경로에 따라 브라우저에 적절한 페이지를 렌더링하도록 페이지 라우팅 구현합니다.
- Routes문은 Switch문으로, Route를 case로 생각하면 이해하기 쉽습니다.
- Routes는 자신이 감싸는 route컴포넌트 중에서 URL 경로와 일피하는 요소를 찾아 페이지에 렌더링 합니다.
//2025-01-13
// App.js
// 3.5.1. 페이지 라우딩 하기
import { Routes, Route } from "react-router-dom";
import './App.css';
import Home from "./pages/Home";
import New from "./pages/New";
import Diary from "./pages/Diary";
import Edit from "./pages/Edit";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary" element={<Diary />} />
<Route path="/edit" element={<Edit />} />
</Routes>
</div>
);
}
export default App;

6. 페이지 이동 구현하기
- HTML은 <a>태그를 이용하지만, react는 <Link>태그를 이용합니다.
<Limk to = "이동할 경로">링크 이름 </Link>
- 링크를 클릭하면 클릭한 페이지로 이동합니다. 클라이언트 사이트 렌더링으로 페이지를 이동하면, 브라우저에서 컴포넌트만 교체하는 식으로 렌더링하므로 이동 속도가 매우 빠릅니다.
//2025-01-13
// App.js
// 3.6.1. 페이지 이동 구현하기
import { Routes, Route, Link } from "react-router-dom";
import './App.css';
import Home from "./pages/Home";
import New from "./pages/New";
import Diary from "./pages/Diary";
import Edit from "./pages/Edit";
function App() {
return (
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/diary" element={<Diary />} />
<Route path="/edit" element={<Edit />} />
</Routes>
<div>
<Link to={"/"}>Home</Link>
<Link to={"/new"}>New</Link>
<Link to={"/diary"}>Diary</Link>
<Link to={"/edit"}>Edit</Link>
</div>
</div>
);
}
export default App;

4. 리액트 라우터로 동적 경로 라우팅하기
동적경로란? 특정 아이템을 나타내는 id처럼 값이 변하는 요소를 URL에 포함하는 경우를 만합니다.
1. 동적경로의 종류
URL 파라미터
- URL파라미터는 URL에 유동적인 값을 넢는 방법입니다.
- http://localhost:3000/diary/{id}
쿼리 스트링
- 쿼리 스트링은 물음표(?) 뒤에 key=value 문법으로 URL에 유동적인 값을 포함하는 방법입니다.
- http://localhost:3000?sort=latest
2. 동적경로에 대응하기
프로젝트애서 리액트 라우터로 동적 경로가 포함된 페이지를 렌더링하는 페이지 라우팅을 구현하겠습니다.
URL 파라미터로 경로 설정하기
- 동적 경로가 포함된 페이지를 라우팅하려면, Route컴포넌트에서 URL 파라미터 방식으로 전달해야 합니다.
// App.js
// 4.2.1 URL 파라미터로 경로 설정하기
<Route path="/diary/:id" element={<Diary />} />

URL 파라미터 값 불러오기
// src/pages/Diary.js
// 4.2.2 URL 파라미터 값 불러오기
import { useParams } from "react-router-dom";
const Diary = () => {
const {id} = useParams();
return (
<div>
<div> {id}번 일기 </div>
<div> Diary 페이지 입니다. </div>
</div>
);
};
export default Diary;
쿼리 스트링으로 값 불러오기
- searchParams: 쿼리스트링 편하게 이용할 수 있는 리액트의 훅
// src/pages/Home.js
// 4.2.3 쿼리 스트링으로 값 불러오기
import { useSearchParams } from "react-router-dom";
const Home = () => {
const [searchParams, setSearchParams] = useSearchParams();
console.log(searchParams.get("sort"));
return <div> Home 페이지 입니다. </div>
};
export default Home;

출처 : 이정환, 『한 입 크기로 잘라먹는 리액트』, 프로그래밍인사이트(2023).
'DEVELOPMENT > react' 카테고리의 다른 글
| [React Native] Aglie, Scrum, User Story, TDD 알아보기 (0) | 2025.05.06 |
|---|---|
| [React Native] 리액트 네이티브 개발하기 - 개발환경 세팅 ( 시작하기 ) (0) | 2025.05.06 |
| 13. 컴포넌트 트리에 데이터 공급하기 (0) | 2025.01.08 |
| 12. 최적화 (0) | 2025.01.06 |
| 11장 useReducer와 상태 관리 (0) | 2025.01.06 |