목표
업무 후에 Vite + React + FastAPI를 사용하면서 실질적으로 궁금한 것들을 테스트 해보는 용도로 환경을 만들어 두려한다.
기본 환경 설정
frontend/폴더에 Vite 기반 React + TypeScript 템플릿 생성.- 아래 커맨드를 실행해준다.
cd <원하는 폴더>
npm create vite@latest frontend -- --template react-ts
cd frontend
npm install
npm run dev
그럼 이렇게 기본 5173 포트로 React Template이 담긴 페이지가 뜬다.

프론트-백엔드 연동 환경설정
- frontend/ 폴더에 Vite 기반 React + TypeScript 템플릿이 있고, backend/ 폴더에 파이썬으로 된 기본적인 백엔드가 있으며, docker-compose.yml 이용하여 간단하게 빌드하는 환경 만들기
파일
오늘 해보는 실습의 코드는 아래 레포에 있다.
코드에서 알 수 있는 주요한 특징만 글로 정리하고자 한다.
https://github.com/i-zro/react-250701/tree/gh-pages/250923-base
react-250701/250923-base at gh-pages · i-zro/react-250701
Contribute to i-zro/react-250701 development by creating an account on GitHub.
github.com
Docker로 빌드 구성
먼저 docker로 기본 빌드 구성을 만들어줬으며, 아래는 각각 프론트/백엔드 Dockerfile이다.
# 프론트엔드 Dockerfile
FROM node:20-alpine
# 작업 디렉토리 설정
WORKDIR /app
# package.json과 package-lock.json 복사
COPY package*.json ./
# 의존성 설치
RUN npm install
# 소스 코드 복사
COPY . .
# 포트 노출
EXPOSE 5173
# 개발 서버 실행
CMD ["npm", "run", "dev", "--", "--host"]
# 백엔드 Dockerfile
FROM python:3.11-slim
# 작업 디렉토리 설정
WORKDIR /app
# 의존성 파일 복사
COPY requirements.txt .
# 의존성 설치
RUN pip install --no-cache-dir -r requirements.txt
# 소스 코드 복사
COPY . .
# 포트 노출
EXPOSE 8000
# FastAPI 서버 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
docker-compose.yml은 아래와 같다.
version: '3.8'
services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
volumes:
- ./backend:/app
environment:
- PYTHONPATH=/app
networks:
- app-network
restart: unless-stopped
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "5173:5173"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- VITE_API_URL=http://localhost:8000
networks:
- app-network
depends_on:
- backend
restart: unless-stopped
networks:
app-network:
driver: bridge
프론트 톺아보기
가장 먼저 진입하는 파일은 index.html 파일이다.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
react 화면 자체는 tsx 속 function의 return으로 반환
다시, 이 index.html 파일은 /src/main.tsx를 본다. 다시 main.tsx를 가보면 App.tsx를 반환함을 알 수 있다.
App.tsx에서 먼저 return을 보자.
알 수 있는 점은, return을 통해 우리가 보는 화면을 렌더해준다는 것이다.
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React + FastAPI</h1>
<div className="card">
{error && <p style={{ color: 'red' }}>{error}</p>}
<p>현재 카운트: <strong>{count}</strong></p>
<div style={{ display: 'flex', gap: '10px', justifyContent: 'center' }}>
<button onClick={incrementCount} disabled={loading}>
{loading ? '로딩...' : '카운트 증가'}
</button>
<button onClick={resetCount} disabled={loading}>
{loading ? '로딩...' : '리셋'}
</button>
<button onClick={fetchCount} disabled={loading}>
{loading ? '로딩...' : '새로고침'}
</button>
</div>
<p>
백엔드 API와 연동된 카운터입니다
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
다음으로, count라는 변수를 쓴 게 보일 것이다.
const [현재 state, state 를 변경하기 위한 함수] = useState()
const [count, setCount] = useState(0)
주로 이런 식으로 쓰는데, [현재 state, state 를 변경하기 위한 함수]
이며 변수값을 셋팅해 주는 역할을 한다.
백엔드 통신함수는 아래와 같다.
const fetchCount = async () => {
try {
setLoading(true)
const response = await fetch(`${API_URL}/api/count`)
if (!response.ok) throw new Error('Failed to fetch count')
const data = await response.json()
setCount(data.count)
setError(null)
} catch (err) {
setError('백엔드 연결에 실패했습니다')
console.error('Error fetching count:', err)
} finally {
setLoading(false)
}
}
- setLoading(true): 버튼을 비활성화하고 “로딩…” 문구를 보이게 함(사용자 연타 방지).
- fetch(url): 브라우저의 표준 HTTP 요청 함수.
- response.ok: 상태코드 200~299면 true. 아니면 throw로 에러 처리 진입.
- await response.json(): JSON 본문 파싱.
- 성공 시 setCount(data.count)로 UI 업데이트, setError(null)로 에러 문구 제거.
- 실패 시 사용자에게 보여줄 한글 에러 메시지를 setError(...)에 저장하고, 상세 원인은 console.error에 남김.
- finally: 성공/실패와 무관하게 항상 loading을 false로 돌려놓음.
즉, 백엔드에 현재 count 변수를 주면, 백엔드에서는 해당 변수를 기반으로 돌려주는 식으로 초기 실습을 구성하였다.

'Web > 🖥 React.js' 카테고리의 다른 글
| [react native] 01. 내 아이폰 화면에 글자 띄워보기 (mac OS, iOS) (1) | 2025.01.19 |
|---|---|
| 리액트 기초 / Boiler-Plate ( 따라하며 배우는 리액트 노드 ) (0) | 2021.09.04 |
| React Native 챗봇 만들기 (윈도우) (0) | 2021.04.11 |