React 쇼핑몰 구조 이해하기 1편 - 프로젝트 구조와 앱의 시작점
쇼핑몰 코드를 처음 보면 복잡해 보이죠? 상품 목록, 상세 페이지, 장바구니, 게시판까지… 이 코드들이 어떻게 연결되어 있는지 파악하기 어려울 수 있어요.
이 시리즈에서는 이미 완성된 과일 쇼핑몰 예제코드를 함께 분석하면서 React 쇼핑몰의 전체 구조를 이해해볼 거예요. 오늘 1편에서는 프로젝트의 기본 구조를 파악하고, 앱이 어떻게 시작되는지 알아봅니다.
이번 편에서 알아볼 내용
- ✅ 쇼핑몰 예제코드에서 사용하는 기술 스택
- ✅ React 앱의 전체 폴더 구조
- ✅ index.js - React 앱의 시작점
- ✅ Provider와 BrowserRouter의 역할
- ✅ App.js - 메인 컴포넌트 구조
이 쇼핑몰에서 사용하는 기술 스택
분석할 쇼핑몰에서는 다음 기술들을 사용해요:
graph LR
A["React 19"] --> B["React Router v6"]
A --> C["Redux Toolkit"]
A --> D["Bootstrap 5"]
A --> E["Axios"]
style A fill:#61DAFB,color:#000
style B fill:#CA4245,color:#fff
style C fill:#764ABC,color:#fff
style D fill:#7952B3,color:#fff
style E fill:#5A29E4,color:#fff
| 기술 | 용도 |
|---|---|
| React 19 | UI 컴포넌트 개발 |
| React Router v6 | 페이지 간 이동 |
| Redux Toolkit | 전역 상태 관리 (장바구니) |
| Bootstrap 5 | 빠른 UI 스타일링 |
| Axios | 외부 데이터 요청 |
프로젝트 생성하기
이 프로젝트를 직접 만들어보려면 다음 순서로 진행하세요:
# 1. 프로젝트 생성
npx create-react-app shop
# 2. 폴더 이동
cd shop
# 3. 필요한 라이브러리 설치
npm install react-router-dom @reduxjs/toolkit react-redux bootstrap react-bootstrap axios
# 4. 개발 서버 실행
npm start
프로젝트 폴더 구조
쇼핑몰 프로젝트를 열면 이런 구조가 보여요:
shop/
├── public/
│ ├── img/ # 상품 이미지들
│ │ ├── fruit1.jpg ~ fruit9.jpg
│ │ └── veggie/
│ │ └── veggie1.jpg ~ veggie3.jpg
│ └── index.html
├── src/
│ ├── components/ # 화면을 구성하는 컴포넌트들
│ │ ├── Products.js # 상품 카드
│ │ ├── Detail.js # 상품 상세
│ │ ├── Cart.js # 장바구니
│ │ ├── BoardList.js # 게시판 목록
│ │ └── ...
│ ├── db/ # 상품 데이터
│ │ ├── fruit.js # 과일 데이터
│ │ └── veggie.js # 채소 데이터
│ ├── App.js # ⭐ 메인 컴포넌트
│ ├── store.js # ⭐ Redux 상태 저장소
│ └── index.js # ⭐ 앱 시작점
└── package.json
⭐ 표시된 파일이 가장 중요한 핵심 파일들이에요!
앱의 시작 흐름 이해하기
React 앱이 브라우저에서 어떻게 실행되는지 순서대로 살펴볼게요:
graph TD
A["index.html<br/>(빈 HTML 파일)"] --> B["index.js<br/>(React 진입점)"]
B --> C["Provider 감싸기<br/>(Redux 연결)"]
C --> D["BrowserRouter 감싸기<br/>(라우팅 활성화)"]
D --> E["App.js<br/>(실제 화면 렌더링)"]
style A fill:#e1f5ff
style B fill:#ffe1e1
style C fill:#e1d5ff
style D fill:#fff4e1
style E fill:#e1ffe1
하나씩 자세히 볼게요!
index.js - 앱의 시작점
src/index.js 파일은 이렇게 생겼어요:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import {BrowserRouter} from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
코드를 하나씩 뜯어볼게요:
1. Import 부분
import {BrowserRouter} from 'react-router-dom'; // 라우팅
import { Provider } from 'react-redux'; // Redux 연결
import store from './store'; // 우리가 만든 store
2. Provider - Redux 연결하기
<Provider store={store}>
...
</Provider>
Provider는 Redux 상태를 앱 전체에서 사용할 수 있게 해줘요. 마치 전기 콘센트에 플러그를 꽂는 것처럼, 앱에 Redux를 “꽂아주는” 역할이에요.
store는 장바구니 같은 전역 데이터를 저장하는 곳이에요. 4편에서 자세히 알아볼 거예요!
3. BrowserRouter - 라우팅 활성화
<BrowserRouter>
<App />
</BrowserRouter>
BrowserRouter로 감싸야 URL에 따라 다른 페이지를 보여줄 수 있어요:
/→ 홈 (상품 목록)/detail/1→ 1번 상품 상세/cart→ 장바구니/board→ 게시판
왜 이렇게 감싸는 걸까?
graph TB
subgraph "감싸는 순서 (바깥 → 안쪽)"
P["Provider<br/>(Redux 상태 전달)"]
B["BrowserRouter<br/>(URL 라우팅)"]
A["App<br/>(실제 화면)"]
P --> B --> A
end
style P fill:#e1d5ff
style B fill:#fff4e1
style A fill:#e1ffe1
비유로 설명하면:
Provider= 전기 콘센트 (상태라는 전기를 공급)BrowserRouter= 건물 복도 (어느 방으로 갈지 안내)App= 실제 방 (화면에 보이는 내용)
App.js - 메인 컴포넌트 구조
이제 src/App.js를 볼게요. 이 파일이 쇼핑몰의 실제 화면을 담당해요.
전체 구조 미리보기
graph TD
subgraph App["App.js"]
N["Navbar<br/>(상단 메뉴)"]
R["Routes<br/>(페이지 라우팅)"]
end
R --> Home["/ (홈)<br/>상품 목록"]
R --> Detail["/detail/:id<br/>상품 상세"]
R --> Cart["/cart<br/>장바구니"]
R --> About["/about<br/>회사소개"]
R --> Board["/board<br/>게시판"]
style App fill:#f8f9fa
style N fill:#343a40,color:#fff
style Home fill:#e1ffe1
style Detail fill:#e1f5ff
style Cart fill:#ffe1e1
style About fill:#fff4e1
style Board fill:#e1d5ff
Import 부분
import { useState } from "react";
import "./App.css";
import { Navbar, Container, Nav, Button } from "react-bootstrap";
import data from "./db/fruit";
import Products from "./components/Products";
import { Routes, Route, useNavigate } from "react-router-dom";
import Detail from "./components/Detail";
import Cart from "./components/Cart";
// ... 더 많은 import
여기서 중요한 것들:
useState- 상태를 관리하는 React Hookreact-bootstrap- 이쁜 UI 컴포넌트들data from "./db/fruit"- 과일 상품 데이터Routes, Route, useNavigate- 페이지 이동 도구
상태(State) 정의
App.js에서 관리하는 상태들을 살펴볼게요:
function App() {
// 과일 상품 데이터
const [fruit, setFruit] = useState(data);
// 채소 상품 데이터
let [veggie, setVeggie] = useState(data2);
// 더 보기 버튼 클릭 횟수
let [count, setCount] = useState(1);
// 검색어 입력값
let [input, setInput] = useState("");
// 게시판 글 목록
const [posts, setPosts] = useState([
{
id: 1,
title: "사과는 언제 배송이 되나요?",
content: "어제부터 기다렸는데 아직 배송이 안됐어요.",
author: "김과일",
date: new Date().getTime(),
views: 1,
},
// ...
]);
const navigate = useNavigate();
// ...
}
Navbar - 상단 메뉴
<Navbar bg="dark" variant="dark">
<Container>
<Navbar.Brand onClick={() => navigate("/")}>
과일농장
</Navbar.Brand>
<Nav className="me-auto">
<Nav.Link onClick={() => navigate("/")}>홈으로</Nav.Link>
<Nav.Link onClick={() => navigate("/detail/1")}>상세페이지</Nav.Link>
<Nav.Link onClick={() => navigate("/cart")}>장바구니</Nav.Link>
<Nav.Link onClick={() => navigate("/about")}>회사소개</Nav.Link>
<Nav.Link onClick={() => navigate("/board")}>게시판</Nav.Link>
</Nav>
</Container>
</Navbar>
useNavigate를 사용하면 클릭했을 때 다른 페이지로 이동할 수 있어요.
Routes - 페이지 라우팅
<Routes>
{/* 홈 페이지 */}
<Route path="/" element={<div>... 상품 목록 ...</div>} />
{/* 상품 상세 */}
<Route path="/detail/:paramId" element={<Detail fruit={fruit} veggie={veggie} />} />
{/* 장바구니 */}
<Route path="/cart" element={<Cart />} />
{/* 회사소개 (중첩 라우팅) */}
<Route path="/about" element={<About />}>
<Route path="member" element={<Member />} />
<Route path="location" element={<Location />} />
</Route>
{/* 게시판 */}
<Route path="/board" element={<BoardList posts={posts} ... />} />
<Route path="/board/write" element={<BoardWrite onAdd={handleAddPost} />} />
<Route path="/board/:id" element={<BoardDetail posts={posts} ... />} />
<Route path="/board/edit/:id" element={<BoardEdit posts={posts} ... />} />
{/* 404 페이지 */}
<Route path="/*" element={<NotFound />} />
</Routes>
여기서 핵심 포인트:
path="/"- URL이/이면 이 컴포넌트를 보여줘:paramId- 동적 파라미터 (1, 2, 3 등 어떤 값이든 받음)element={<컴포넌트 />}- 해당 URL에서 보여줄 컴포넌트
정리
오늘 1편에서 살펴본 내용을 정리하면:
graph LR
A["index.js"] --> B["Provider<br/>(Redux 연결)"]
B --> C["BrowserRouter<br/>(라우팅)"]
C --> D["App.js<br/>(Navbar + Routes)"]
style A fill:#ffe1e1
style B fill:#e1d5ff
style C fill:#fff4e1
style D fill:#e1ffe1
핵심 포인트:
- 📦 index.js는 앱의 시작점이고, Provider와 BrowserRouter로 App을 감싼다
- 🔌 Provider는 Redux 상태를 앱 전체에 공급한다
- 🛣️ BrowserRouter는 URL에 따라 다른 화면을 보여준다
- 📱 App.js는 Navbar(상단메뉴)와 Routes(페이지들)로 구성된다
다음 편에서는 상품 목록이 화면에 어떻게 표시되는지, 검색과 정렬은 어떻게 동작하는지 알아볼게요!