| 서론
안녕하세요, 팡일입니다.
이전 글에서는 React + Node.js 기반의 풀스택 모노레포 환경을 구축하는 과정을 정리했고,
이번 글에서는 그 환경 위에서 실제로 데이터를 저장하고 조회할 수 있는 CRUD 기능을 구현해보겠습니다.
전체 데이터 흐름은 다음과 같습니다.
React
↓
Express API
↓
Prisma
↓
SQLite Database
간단한 Todo API를 만들어 React에서 데이터를 저장하고 조회해보겠습니다.
| 1단계 : Prisma 설치
1) Prisma ORM
Node 서버에서 데이터베이스를 사용하기 위해 Prisma ORM을 사용합니다.
Prisma는 TypeScript 환경에서 매우 사용하기 편한 ORM입니다.
- 타입 자동 생성
- DB 마이그레이션 지원
- 직관적인 API
2) 설치
: 먼저 api 패키지에 Prisma를 설치합니다.
pnpm add prisma@6 @prisma/client@6 --filter api
Prisma CLI도 설치합니다.
pnpm add -D prisma@6 --filter api
| 2단계 : Prisma 초기화
이제 Prisma 설정을 생성합니다.
cd apps/api
npx prisma init
생성 후에는 다음과 같은 구조가 생성됩니다.
apps/api
├ prisma
│ └ schema.prisma
├ .env
└ prisma.config.ts
| 3단계 : SQLite 데이터베이스 설정
이번 프로젝트에서는 로컬에서 간단히 테스트할 수 있는 SQLite를 사용합니다.
.env 파일을 수정합니다.
DATABASE_URL="file:./dev.db"
SQLite는 별도의 데이터베이스 서버를 설치하지 않아도 되기 때문에 로컬 환경에서 빠르게 CRUD 기능을 테스트할 수 있습니다.
| 4단계 : 데이터 모델 정의
schema.prisma 파일에서 Todo 모델을 정의합니다.
model Todo {
id Int @id @default(autoincrement())
title String
completed Boolean @default(false)
createdAt DateTime @default(now())
}
이 모델을 기준으로 데이터베이스 테이블이 생성됩니다.
| 5단계 : 데이터베이스 마이그레이션
모델을 정의했다면 실제 데이터베이스를 생성합니다.
npx prisma migrate dev --name init
이 명령을 실행하면 다음 작업이 수행됩니다.
- SQLite DB 생성
- migration 파일 생성
- Prisma Client 생성
실행 후 다음 파일이 생성됩니다.
apps/api/prisma/dev.db
| 6단계 : Prisma Client 생성
Prisma Client는 Node.js에서 데이터베이스를 제어하는 역할을 합니다.
1) 생성
: 아래의 명령어로 Prisma Client를 사용할 파일을 생성합니다.
npx prisma generate
2) 작성
: src/prisma.ts 파일에 아래의 내용을 작성합니다.
import { PrismaClient } from "@prisma/client";
export const prisma = new PrismaClient();
이제 Express 서버에서 Prisma를 통해 데이터베이스에 접근할 수 있습니다.
| 7단계 : Todo CRUD API 구현
이제 Express 서버에 CRUD API를 구현합니다.
1) src/index.ts
import express from "express";
import cors from "cors";
import { prisma } from "./prisma";
const app = express();
app.use(cors());
app.use(express.json());
app.get("/api/todos", async (req, res) => {
const todos = await prisma.todo.findMany();
res.json(todos);
});
app.post("/api/todos", async (req, res) => {
const { title } = req.body;
const todo = await prisma.todo.create({
data: { title },
});
res.json(todo);
});
app.patch("/api/todos/:id", async (req, res) => {
const id = Number(req.params.id);
const todo = await prisma.todo.update({
where: { id },
data: { completed: true },
});
res.json(todo);
});
app.delete("/api/todos/:id", async (req, res) => {
const id = Number(req.params.id);
await prisma.todo.delete({
where: { id },
});
res.json({ success: true });
});
app.listen(3001, () => {
console.log("server running on 3001");
});
| 8단계 : React에서 API 호출
이제 React에서 API를 호출합니다.
1) App.tsx
import { useEffect, useState } from "react";
type Todo = {
id: number;
title: string;
completed: boolean;
};
function App() {
const [todos, setTodos] = useState<Todo[]>([]);
const [title, setTitle] = useState("");
const fetchTodos = async () => {
const res = await fetch("http://localhost:3001/api/todos");
const data = await res.json();
setTodos(data);
};
const createTodo = async () => {
await fetch("http://localhost:3001/api/todos", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title }),
});
setTitle("");
fetchTodos();
};
useEffect(() => {
fetchTodos();
}, []);
return (
<div style={{ padding: 40 }}>
<h1>Todo List</h1>
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<button onClick={createTodo}>추가</button>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
);
}
export default App;
| 9단계 : 실행 및 테스트
1) 개발 서버 실행
: 프로젝트 루트에서 다음 명령어를 실행합니다.
pnpm dev
2) 접속
http://localhost:5173
Todo를 추가하면 다음 흐름으로 데이터가 저장됩니다.
React
↓
fetch API
↓
Express
↓
Prisma
↓
SQLite
그리고 API를 직접 확인할 수도 있습니다.
http://localhost:3001/api/todos
| 트러블슈팅
1) CORS 오류
React 개발 서버와 Express 서버는 서로 다른 origin이기 때문에 브라우저에서 API 요청이 차단될 수 있습니다.
이를 해결하기 위해 Express에 cors 미들웨어를 추가했습니다.
import cors from "cors";
app.use(cors());
2) Prisma Client 타입 오류
Prisma Client를 생성하지 않으면 다음 오류가 발생할 수 있습니다.
'@prisma/client' 모듈에 PrismaClient가 없습니다
이 경우 다음 명령어로 Prisma Client를 생성합니다.
npx prisma generate
| 결론
이번 글에서는 풀스택 모노레포 환경 위에서 실제 CRUD 기능을 구현하는 과정을 정리했습니다.
이를 통해 전체 스택은 다음과 같습니다.
- React + Vite
- Node.js + Express
- Prisma ORM
- SQLite
- Turborepo
- pnpm workspace
이 구조를 사용하면 프론트엔드와 백엔드를 하나의 프로젝트에서 함께 관리할 수 있고, 빠르게 풀스택 기능을 개발할 수 있습니다.
'💻 개발 > 🦕 React' 카테고리의 다른 글
| [React] React + Node.js 풀스택 모노레포 환경 세팅 (pnpm + Turborepo) (0) | 2026.03.13 |
|---|---|
| [React] API 모듈 정리하다 터진 404와 export 오류 원인 정리 (0) | 2026.02.27 |
| [React] React Router 중첩 라우트에서 index 대신 Navigate를 선택한 이유 (0) | 2026.01.19 |
| [React] React + Vite + TS + Firebase Hosting + Github Action 구축하기 (0) | 2026.01.18 |
| [React] TanStack Query(React Query) 활용하기 - useMutation으로 데이터 생성·수정·삭제 마스터하기 (0) | 2026.01.15 |
