| 서론
안녕하세요, 팡일입니다.
보통 웹 개발을 하면 프론트엔드 프로젝트와 백엔드 프로젝트를 각각 관리해왔었는데요? 혹시 모노레포라고 들어보셨나요?
모노레포란?
: 두 개 이상의 프로젝트, 애플리케이션 또는 라이브러리 코드를 하나의 버전 관리 저장소(Repository)에서 통합하여 관리하는 개발 전략
프론트엔드와 백엔드를 각각 관리할 수도 있지만, 최근에는 모노레포(monorepo) 구조를 사용하는 경우가 많다는 점을 알고만 있었고, 실제로 세팅을 해본 경험은 없었습니다.
그러나, 드디어 환경 세팅에 성공하였고, 보다 쉽게 세팅하는 과정을 공유하고자 포스팅을 작성하게 되었습니다.
1) 모노레포의 장점
본격적으로 시작하기에 앞서, 모노레포를 사용하면 다음과 같은 장점을 한 번 살펴보고 싶은데요?
- 프론트엔드와 백엔드를 하나의 저장소에서 관리할 수 있다
- 공통 타입과 유틸을 쉽게 공유할 수 있다
- 개발 환경을 한 번에 실행할 수 있다
- 협업 시 코드 관리가 단순해진다
이러한 장점이 있는 모노레포를 이번 글에서는 다음 스택을 기반으로 풀스택 개발 환경을 세팅하는 과정을 정리합니다.
2) 사용 기술
이번 포스팅에서 사용되는 기술 스택은 아래와 같습니다.
- React + TypeScript
- Node.js + Express
- pnpm workspace
- Turborepo
- Vite
최종적으로는 다음 명령어 하나로 프론트와 백엔드가 동시에 실행되는 환경을 목표로 합니다.
pnpm dev
| 1단계 : 프로젝트 생성
1) 프로젝트 루트 디렉토리 생성
: 먼저 풀스택 프로젝트를 위한 루트 디렉토리를 생성합니다.
mkdir full-stack
cd full-stack
-> 이 폴더는 앞으로 프론트엔드, 백엔드, 공통 패키지 등을 모두 포함하는 모노레포의 루트 디렉토리가 됩니다.
2) pnpm 설치
: 이번 프로젝트에서는 패키지 매니저로 pnpm을 사용합니다.
pnpm은 다음과 같은 장점이 있습니다.
- 빠른 패키지 설치 속도
- 효율적인 디스크 사용
- workspace 기반 모노레포 관리 지원
아직 pnpm이 설치되어 있지 않다면 다음 명령어로 설치합니다.
npm install -g pnpm
설치가 완료되면 다음 명령어로 정상 설치 여부를 확인할 수 있습니다.
pnpm -v
3) 루트 package.json 생성
: 이제 프로젝트 루트에 package.json 파일을 생성합니다.
pnpm init
-> 이 파일은 모노레포 전체를 관리하는 루트 설정 파일이 됩니다.
| 2단계 모노레포 폴더 구조 만들기
1) 모노레포 구조 이해
: 모노레포에서는 보통 다음 구조를 사용합니다.
full-stack
│
├ apps
│ ├ web
│ └ api
│
├ packages
│
├ package.json
└ pnpm-workspace.yaml
- apps/web → 프론트엔드 (React)
- apps/api → 백엔드 (Node.js)
- packages → 공통 코드 (타입, UI 등)
2) 폴더 생성
: 먼저 폴더를 생성합니다.
mkdir apps
mkdir apps/web
mkdir apps/api
mkdir packages
| 3단계 : pnpm workspace 설정
1) pnpm-workspace.yaml 파일 생성
: 루트에 pnpm-workspace.yaml 파일을 생성합니다.
packages:
- "apps/*"
- "packages/*"
이 설정을 통해 pnpm이 다음 폴더를 워크스페이스로 인식합니다.
apps/web
apps/api
packages/*
| 4단계 : Turborepo 설치
1) turbo 설치
: 모노레포 환경에서 여러 프로젝트를 동시에 실행하기 위해 Turborepo를 사용합니다.
pnpm add -D turbo -w
여기서 -w 옵션은 workspace root에 설치한다는 의미입니다.
2) 유의할점
: 이렇게 설치를 한 뒤에는 프로젝트 루트 경로에 'node_modules' 폴더가 생성되는데요?
.gitignore 파일을 만들어준 뒤에, node_modules를 추가해주시면 좋습니다.
| 5단계 : turbo.json 설정
: 루트에 turbo.json 파일을 생성합니다.
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"dev": {
"cache": false,
"persistent": true
}
}
}
여기서 중요한 설정이 하나 있습니다.
"persistent": true
이 옵션은 dev server가 계속 실행되도록 하는 설정입니다.
예를 들어, vite, next dev, node server와 같이 같은 dev 서버는 계속 살아있는 프로세스이기 때문에 이 옵션이 필요합니다.
| 6단계 : React 프로젝트 생성 (Vite)

1) 프로젝트 생성 명령어 입력
: 프론트엔드는 Vite 기반 React 프로젝트로 생성합니다.
pnpm create vite apps/web
2) 옵션 선택
Framework: React
Variant: TypeScript
3) 설치
cd apps/web
pnpm install
4) 개발 서버 실행
: 이제 프론트엔드 개발 서버를 실행할 수 있습니다.
pnpm dev
기본적으로 다음 주소에서 실행됩니다.
http://localhost:5173
| 7단계 : Node.js 백엔드 생성
1) 백엔드 서버 생성
: 이제 백엔드 서버를 생성합니다.
cd ../../apps/api
pnpm init
2) 패키지 설치
: Express와 TypeScript를 설치합니다.
pnpm add express
pnpm add -D typescript ts-node-dev @types/node @types/express
| 8단계 : TypeScript 설정
1) 파일 생성
: tsconfig를 생성합니다.
npx tsc --init
2) 파일 수정
: Node 환경에서 안정적으로 동작하도록 다음처럼 수정합니다.
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src"]
}
| 9단계 : Express 서버 코드 작성
백엔드 API 서버를 구성하기 위해 Express 기반의 간단한 서버 코드를 작성합니다.
먼저 서버의 진입점이 될 src 폴더와 index.ts 파일을 생성합니다.
1) 폴더 생성
apps/api/src
2) src/index.ts 파일 생성
import express from "express";
const app = express();
app.use(express.json());
app.get("/", (req, res) => {
res.json({ message: "API running" });
});
app.listen(3001, () => {
console.log("server running on 3001");
});
위 코드는 Express 서버를 생성하고 기본 API 엔드포인트를 하나 구성하는 간단한 예제입니다.
서버가 실행되면 http://localhost:3001 주소로 요청을 보낼 수 있으며, 정상적으로 동작하는지 빠르게 확인할 수 있습니다.
| 10단계 : 백엔드 실행 스크립트

1) apps/api/package.json 수정
{
"scripts": {
"dev": "ts-node-dev --respawn src/index.ts"
}
}
| 11단계 : 프론트 실행 스크립트
1) apps/web/package.json 수정
{
"scripts": {
"dev": "vite"
}
}
| 12단계 : 루트 실행 스크립트

1) 루트 package.json 수정
{
"scripts": {
"dev": "turbo run dev"
}
}
2) 명령어 실행
이제 루트에서 다음 명령어를 실행하면 됩니다.
pnpm dev
그러면 다음 두 서버가 동시에 실행됩니다.
Frontend → http://localhost:5173
Backend → http://localhost:3001
| 마지막 : 실행 결과
web:dev: VITE v7 ready
Local: http://localhost:5173/
api:dev: server running on 3001
이 상태라면 풀스택 개발 환경이 정상적으로 구성된 것입니다.
| 추가 공유 : 개발 중 겪었던 문제들
1) Turborepo dev 서버가 실행되지 않는 문제
초기 설정에서는 다음 문제가 발생했습니다.
vite ready
하지만 localhost 접속 안됨
원인은 turbo dev task가 persistent가 아니었기 때문입니다.
turbo.json에서 아래의 문구로 수정한 결과 해결되었습니다.
"persistent": true
2) TypeScript import 에러
다음 에러가 발생했습니다.
ECMAScript imports cannot be written in a CommonJS file
원인은 tsconfig module 설정 문제였습니다.
apps/api/tsconfig.json에서 아래의 문구로 수정한 결과 해결되었습니다.
"module": "CommonJS",
"esModuleInterop": true
3) pnpm workspace root 설치 경고
다음 오류가 발생했습니다.
ERR_PNPM_ADDING_TO_ROOT
아래의 명령어로 해결되었습니다.
pnpm add -D turbo -w
-w 옵션을 사용해 workspace root에 설치합니다.
4) turbo.json 스키마 경고(Location ... is untrusted) 해결
모노레포를 세팅하면서 turbo.json에 $schema를 넣었는데, VS Code에서 아래 경고가 발생할 수 있습니다.
'https://turbo.build/schema.json'에서 스키마를 로드할 수 없습니다. Location ... is untrusted.
이건 Turbo 동작 오류가 아니라, VS Code JSON Language Server가 원격 스키마를 신뢰하지 못해 생기는 에디터 경고였습니다.
즉 turbo run dev 같은 실행 자체보다, JSON 자동완성/검증 기능에 영향을 주는 이슈라고 볼 수 있습니다.
이 문제의 경우, 워크스페이스 설정으로 고정해서 해결했습니다.
// .vscode/settings.json
{
"json.schemaDownload.enable": true,
"json.schemas": [
{
"fileMatch": ["/turbo.json"],
"url": "https://turbo.build/schema.json"
}
]
}
Developer: Reload Window를 실행하면 경고가 사라졌고, turbo.json에 대한 스키마 기반 검증/자동완성도 정상 동작했습니다.
만약 동일 경고가 남아 있으면 JSON: Clear Schema Cache를 한 번 실행한 뒤 다시 확인하면 됩니다.
| 현재 프로젝트 구조
.
├── .gitignore
├── .turbo
│ └── cache
├── apps
│ ├── api
│ │ ├── package.json
│ │ ├── src
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── web
│ ├── .gitignore
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── public
│ │ └── vite.svg
│ ├── src
│ │ ├── App.css
│ │ ├── App.tsx
│ │ ├── assets
│ │ │ └── react.svg
│ │ ├── index.css
│ │ └── main.tsx
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── package.json
├── packages
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── turbo.json
이 과정을 통해 설치된 파일과 폴더의 구조는 다음과 같습니다.
| 결론
이번 글에서는 React와 Node.js를 하나의 모노레포 환경에서 함께 개발할 수 있는 풀스택 개발 환경을 구성해보았습니다.
구체적으로 다음과 같은 기술 스택을 기반으로 초기 개발 구조를 만들었습니다.
- React + TypeScript : 프론트엔드 UI 개발
- Node.js + Express : API 서버 구축
- Vite : 빠른 프론트엔드 개발 서버
- pnpm workspace : 모노레포 패키지 관리
- Turborepo : 여러 앱을 동시에 실행하고 관리하는 빌드 시스템
이 환경을 구성하면 pnpm dev 명령어 하나로 프론트엔드와 백엔드 서버를 동시에 실행할 수 있고, 앞으로 프로젝트 규모가 커지더라도 구조적으로 확장하기 쉬운 기반을 마련할 수 있습니다.
이후에는 다음과 같은 단계로 자연스럽게 확장할 수 있습니다.
- React ↔ Node API 연결
- 공통 타입(shared types) 관리
- Zod 기반 API validation
- Prisma를 활용한 데이터베이스 연동
- JWT / OAuth 기반 인증 시스템 구축
이러한 구조는 단순한 실습 프로젝트뿐만 아니라, 토이 프로젝트나 실제 서비스 개발을 시작할 때 기본 템플릿으로 활용하기 좋은 풀스택 모노레포 구조라고 생각합니다.
처음에는 설정 과정이 다소 길게 느껴질 수 있지만, 한 번만 환경을 잘 구성해두면 이후에는 같은 구조를 재사용하면서 훨씬 빠르게 프로젝트를 시작할 수 있습니다.
'💻 개발 > 🦕 React' 카테고리의 다른 글
| [React] React + Node.js 풀스택 CRUD 만들기 (Prisma + SQLite) (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 |
