몰래카메라 조용한카메라 무음카메라 닌자카메라 블랙박스카메라
© 2025 Shelled Nuts Blog. All rights reserved.
Capture your moments quietly and securely
Stripe의 혁신적인 개발자 경험과 Kinde가 이끄는 인증 시스템의 미래를 살펴보고, 개발자 친화적 솔루션 도입 인사이트를 제공합니다.
Shelled AI (한국)
복잡한 환경에서 에이전트 협업 시뮬레이션 실습을 통해 멀티 에이전트 시스템의 실제 적용과 사례를 단계별로 체험해보세요.
Shelled AI (한국)
한 번의 API 호출로 인증과 결제를 동시에 처리하는 비밀 패턴을 소개합니다. 개발 효율과 보안을 동시에 향상시키는 최신 웹 개발 팁!
Shelled AI (한국)
어, 또 만났네요! 지난번 "Vite가 Webpack을 넘어서며 드러난 숨겨진 함정과 극복법" 글, 어떠셨나요? 댓글 보니까 Vite 기반 대규모 프로젝트 세팅, 그리고 모노레포 구성에 대해 궁금해하시는 분들이 정말 많더라고요. 그래서 오늘은 이 부분, 제대로 파헤쳐보려고 합니다.
대규모 프론트엔드 프로젝트를 하다 보면, 패키지 관리, 개발 효율성, 유지보수까지 신경 쓸 게 한두 가지가 아니죠. 특히 여러 팀이 협업하거나 다양한 패키지를 한 저장소에서 관리해야 할 때 ‘모노레포’가 거의 필수처럼 느껴지기도 해요. 그런데 Vite와 모노레포를 처음 연결해보면, 어딘가에서 막히거나 예상치 못한 문제가 터지는 경우가 종종 있습니다. 저도 “이게 뭐가 그렇게 어렵겠어?” 싶었다가, 예상 밖의 삽질로 몇 시간 날린 적이 한두 번이 아니에요.
이 글에서는 Vite를 기반으로 대규모 프로젝트를 어떻게 체계적으로 세팅할 수 있는지, 그리고 모노레포 환경에서 어떤 구조와 도구, 플러그인을 활용하면 좋은지 실제 사례와 팁을 중심으로 풀어볼게요. 완벽하지 않아도 괜찮으니, 저와 함께 차근차근 모노레포 세계에 입문해보시죠. 다 읽고 나면, 여러분만의 대규모 Vite 프로젝트를 자신 있게 시작할 수 있을 거예요!
Vite 소개 및 핵심 기능
Vite가 왜 요즘 핫한지, 그리고 어떤 기능이 개발자를 사로잡는지 가볍게 살펴볼게요.
대규모 프로젝트에서 Vite 활용의 필요성
"작은 프로젝트만 쓸 수 있는 거 아냐?"라는 오해, 직접 써보니 달랐던 경험담을 공유합니다.
모노레포 개념과 Vite 기반 모노레포 구성 이해
모노레포가 뭔지, 왜 쓰는지, 그리고 Vite와 만나면 어떤 시너지가 나는지 이야기해볼게요.
Vite 기반 모노레포 초기 세팅 가이드
실제로 어떻게 폴더를 짜고, 설정을 해야 하는지 코드 예시와 함께 차근차근 설명합니다.
모노레포 환경에서 발생하는 주요 이슈와 해결법
삽질했던 경험, 그리고 그때마다 배운 노하우를 솔직하게 공유합니다.
자, 이제 Vite가 뭔지, 그리고 왜 요즘 프론트엔드 개발자들이 Vite에 열광하는지 한번 같이 알아볼까요?
처음에 Vite를 접했을 때, 저도 솔직히 “이게 Webpack이랑 뭐가 그렇게 다르지?” 싶었어요. 그런데 실제로 프로젝트에 적용해보니까, 와, 개발 경험이 완전히 달라지더라고요. 특히 개발 서버를 띄울 때 기다리는 시간이 거의 없다는 점, 그리고 코드 수정할 때마다 페이지가 번개처럼 갱신되는 ‘핫 리로딩’(HMR)이 진짜 신세계였습니다.
Vite의 가장 큰 강점은 바로 ‘빠름’이에요. 기존 번들러(Webpack, Parcel 등)들은 프로젝트가 커질수록 서버 시작 속도랑 코드 반영 속도가 점점 느려지잖아요? 그런데 Vite는 ESM(ES Modules) 기반으로 동작해서, 변경된 파일만 딱 실시간으로 갱신해줘요. 예를 들어, 사내에서 대규모 Vue 프로젝트를 작업할 때, Webpack 썼을 땐 저장하고 3~5초는 기다렸는데, Vite로 바꾸니 거의 1초도 안 걸릴 때가 많았어요. 다들 이런 답답함 느껴보셨죠?
잠깐, 여기서 정리하고 넘어갈게요. 개발 서버는 ESM으로 빠르게 돌지만, 실제로 배포할 땐 Rollup이란 번들러를 써서 코드 스플리팅, 트리 쉐이킹(필요 없는 코드 제거) 등을 자동으로 해줘요. 어? 이게 무슨 말이냐고요? 쉽게 말해, 결과물 용량을 최소화해서 배포 퍼포먼스까지 챙긴단 뜻이에요. 실제로 저희 팀에서 Vite로 마이그레이션한 뒤, 번들 사이즈가 20% 넘게 줄었어요.
그리고 또 하나! Vite는 Rollup 플러그인 다 쓸 수 있고, 자체 플러그인도 만들기 쉬워요. 예를 들어, 제가 모노레포(여러 패키지로 구성된 대규모 프로젝트) 환경에서 특정 패키지만 별도 캐싱 전략을 써야 했는데, 플러그인 몇 줄 추가해서 바로 해결했죠. 이거 진짜 신세계예요.
// vite.config.js
import myCustomPlugin from './plugins/my-custom-plugin';
export default {
plugins: [
myCustomPlugin({ cacheStrategy: 'per-package' }),
],
};
실제로 플러그인 몇 줄로 빌드 전략을 바꿨을 때, "이렇게 쉽게 확장된다고?" 싶어서 감탄했던 기억이 납니다.
TypeScript, JSX, Vue, React, Svelte... 요즘 트렌디한 웹 기술들 다 지원합니다. 예를 들어, tsconfig.json이나 babel 설정도 그냥 알아서 읽어와요. 처음엔 “설정 또 해야 하나?” 걱정했는데, 거의 손 안 대고 돌아가서 깜짝 놀랐던 기억이 나요. 혹시 여러 기술 스택 혼합된 프로젝트 관리해보신 분들, 이 부분 정말 공감하실 거예요.
아직 저도 배우는 중이지만, Vite를 쓰면서 느낀 건, 개발 속도와 경험이 완전히 달라진다는 거예요. 실수하면서 알게 된 것도 많지만, 한 번 익숙해지면 뒤로 돌아가기 힘들더라고요. 혹시 기존 번들러에서 느린 빌드 속도 때문에 힘들었던 분들, 꼭 한 번 Vite 써보시길 추천드릴게요!
대규모 프로젝트에서 왜 Vite를 선택해야 할까요? 사실 저도 처음엔 “이거 그냥 작은 프로젝트용 아니야?” 이런 생각을 했었거든요. 그런데 실제로 써보니까, 아, 이건 진짜 대규모 프론트엔드 개발에 딱이더라고요. 자, 이제 하나씩 풀어볼게요.
우선, 대규모 애플리케이션에서는 개발 환경이 느려지기 시작하면 정말 답답하잖아요. 다들 코드 한 줄 바꾸고 저장했는데, 빌드 돌고 새로고침 되기까지 몇 초씩 걸리면… 와, 이건 정말 스트레스입니다. 그런데 Vite는 ES 모듈 기반이라, 초기 번들링 없이 개발 서버를 바로 띄워줘요. 제가 이걸 써봤는데요, 작업하던 중에 소스 코드 조금만 바꿔도 바로바로 반영돼서, ‘아, 이게 진짜 핫리로드구나’ 싶더라고요.
자, 이제 모노레포 환경 얘기를 해볼까요? 요즘 대기업이나 스타트업에서 한 저장소에 여러 패키지(예: 공통 UI, 각 서비스별 프론트엔드)를 관리하는 경우 많죠. 실제로 저도 pnpm workspace랑 Vite 조합으로 여러 패키지를 동시에 작업해봤는데, 각 패키지를 독립적으로 개발 서버 돌릴 수 있으니 팀원 간 충돌도 줄고, 디버깅도 훨씬 쉬워졌어요. “이 패키지 바꿨는데 옆에 영향 주면 어떡하지?” 이런 걱정도 훨씬 줄었고요.
그리고 빌드&테스트 자동화, 이거 빼놓을 수 없죠. Nx나 Turborepo 같은 모노레포 툴과 Vite를 붙이면, 변경된 부분만 똑똑하게 다시 빌드하고 테스트하는 구조가 돼요. 제가 Nx랑 Vite 붙여본 경험을 말씀드리자면, 캐싱 기능 덕분에 빌드 속도가 진짜 확 줄었어요. 처음엔 좀 헷갈렸는데, 익숙해지니 CI/CD 파이프라인도 훨씬 깔끔해지고, 반복 작업이 줄어서 생산성도 올라가더라고요.
정리해볼게요. Vite는 빠른 개발 환경, 모노레포 지원, 빌드 자동화까지 대규모 프로젝트에 필요한 요소들을 다 갖추고 있습니다. 실수하면서 배운 건데, “크다고 무거운 게 답”이 아니라 “빠르고 유연한 게 답”이더라고요. 여러분도 한번 써보시면, 왜 Vite가 요즘 핫한지 직접 느끼실 수 있을 거예요.
여러분, 혹시 "모노레포"라는 단어 들어보셨나요? 저도 개발하면서 자주 듣긴 했는데, 처음엔 솔직히 뭔지 좀 헷갈렸어요. 그래서 오늘은 모노레포가 뭔지, 그리고 요즘 핫한 빌드 도구인 Vite와 함께 어떻게 구성하는지, 제가 직접 써보고 느낀 점까지 이야기해볼게요.
자, 이제 모노레포의 기본 개념부터 짚어볼까요?
모노레포(Monorepo)는 여러 개의 프로젝트나 패키지를 하나의 저장소(repository)에서 통합 관리하는 방식이에요. 예를 들어, 프론트엔드 UI 컴포넌트, 공통 유틸리티, 서비스 코드 등 다양한 패키지를 각각 따로 저장소를 만들지 않고, 한 번에 묶어서 관리하는 거죠. 이게 왜 좋냐고요?
저도 예전에 여러 패키지를 각각 다른 저장소로 관리하다가, 버전 꼬이고, 공유 코드가 엉키는 바람에 진땀 뺀 적 있거든요. 다들 한 번쯤 겪어보셨죠? 모노레포 쓰면 이런 스트레스가 확 줄어듭니다.
그럼, Vite는 모노레포 환경에서 어떻게 작동할까요?
Vite는 기본적으로 루트 폴더에서 여러 패키지를 인식해요. 예를 들어 apps/web
, packages/common
이런 식으로 폴더를 구성해도, Vite가 알아서 내부 의존성을 해석해줍니다. 핫 모듈 교체(HMR)도 잘 되고, 캐싱도 효율적으로 해줘서, 진짜 개발 속도가 확 빨라져요.
특히 optimizeDeps
옵션을 잘 활용하면, 내부 패키지 간 의존성을 미리 빌드해서 개발 서버가 훨씬 빨리 뜨더라고요.
그리고 저도 처음엔 "공유 코드는 어떻게 관리하지?" 싶었는데, 보통 @myorg/common
처럼 공통 패키지를 만들어서, 필요한 앱이나 라이브러리에서 의존성을 추가해주면 돼요.
여기서 중요한 게, pnpm
같은 패키지 매니저를 쓰면, 루트에서 의존성을 한 번에 관리할 수 있다는 점이에요. 저도 pnpm-workspace.yaml
로 패키지 묶어서 쓰니까, 중복 설치 없이 깔끔하게 관리됐거든요.
잠깐, 정리하고 갈게요!
아직 저도 모노레포를 100% 마스터한 건 아니지만, 실수하면서 하나씩 깨닫고 있어요. 여러분도 직접 해보시면 "아, 이래서 다들 모노레포, 모노레포 하는구나!" 하실 거예요.
자, 이제 Vite 기반 모노레포 초기 세팅에 대해 차근차근 알아볼까요?
저도 처음에 "모노레포? Vite? pnpm workspace? 이거 다 합치면 도대체 어떻게 관리하라는 거지?" 싶었는데요. 막상 한 번 해보니까 생각보다 체계적이고, 실수도 몇 번 해보니까 감이 오더라고요.
대부분 모노레포는 아래처럼 루트에 packages
폴더를 두고, 그 안에 각각의 패키지를 넣는 방식으로 시작합니다.
이 구조가 왜 중요하냐면요, 나중에 패키지 간 의존성 연결이나 유지보수할 때 정말 편하거든요.
my-monorepo/
├── package.json
├── pnpm-workspace.yaml
└── packages/
├── core/
│ └── package.json
└── web/
└── package.json
저도 처음엔 그냥 아무 데나 폴더 만들다가, 나중에 경로 꼬여서 엄청 고생했어요.
팁: packages
폴더 네이밍은 관례이긴 하지만, 회사 정책이나 팀 스타일에 맞게 바꿔도 무방합니다.
이제 패키지 매니저 설정인데요, 전 요즘 pnpm
을 주로 씁니다.
pnpm-workspace.yaml
파일을 루트에 만들고, 아래처럼 workspace 패턴을 지정해 주세요.
packages:
- 'packages/*'
그리고 루트 package.json
에 이런 식으로도 workspaces를 명시할 수 있어요:
{
"name": "my-monorepo",
"private": true,
"workspaces": [
"packages/*"
]
}
실수 경험: pnpm install
안 하고 각 패키지 폴더마다 직접 설치했다가 node_modules가 중복으로 막 생겼었죠.
정리: 항상 루트에서 의존성을 설치하는 게 핵심이에요!
자, 이제 각 패키지에 vite.config.ts
를 만들어볼까요?
가장 기본적인 예제는 이런 느낌입니다.
// packages/web/vite.config.ts
import { defineConfig } from 'vite';
import path from 'path';
export ({
: {
: {
: path.(__dirname, ),
},
},
: {
: ,
: {
: ,
: ,
},
},
});
어? 이게 무슨 말이냐고요?
@core
로 core 패키지의 소스 코드를 바로 import할 수 있게 경로를 단축한 거예요.
실제로 제가 이 부분을 빼먹어서, 나중에 import 경로를 엄청 길게 썼던 기억이...
여기서 중요한 건, 각 패키지의 package.json
에 workspace 패키지명을 의존성으로 추가하는 거예요.
// packages/web/package.json
{
"dependencies": {
"core": "workspace:*"
}
}
이렇게 하면 pnpm
이 알아서 core 패키지를 연결해줍니다.
팁: "workspace:*"
를 쓰면, 로컬에서 자동으로 최신 버전을 참조합니다.
저도 예전엔 상대 경로로 연결했다가 계속 빌드 깨지고, HMR도 안 먹히고… 다들 이런 경험 있으시죠?
server.fs.allow
옵션으로 workspace 외부 파일 접근권한 조정 가능vite.config.ts
를 두고, 각 패키지에서 import해서 확장하는 방식도 좋아요.아직 저도 배우는 중이지만, 위 구조와 설정만 잘 맞추면
대규모 프로젝트도 훨씬 깔끔하게 관리할 수 있습니다.
혹시 중간에 막히는 부분 있으시면, 저도 처음엔 다 그랬으니까 너무 걱정하지 마세요!
실수하면서 하나씩 배워나가는 게 모노레포의 묘미거든요.
자, 이제 모노레포 환경에서 자주 겪는 문제들과 실제로 써먹을 수 있는 해결법을 하나씩 풀어볼게요.
저도 처음 모노레포 환경을 도입했을 때 제일 많이 만난 게 바로 의존성 충돌이에요. 예를 들어, @core/ui
와 @feature/payment
가 각각 lodash
의 서로 다른 버전을 요구하면, 빌드할 때나 런타임에서 "Cannot find module" 같은 에러가 뜨곤 하죠. 다들 이런 경험 있으시죠?
실전 팁:
package.json
에서 주요 라이브러리 버전을 통일하세요.optimizeDeps
옵션으로 공통 의존성을 미리 번들링하면 충돌이 줄어듭니다.// pnpm-workspace.yaml 예시
packages:
- 'packages/*'
// vite.config.js에서 optimizeDeps 설정
export default {
optimizeDeps: {
include: ['lodash'], // 공통 사용 라이브러리
},
}
저도 예전에 hoisting 설정을 빼먹고, 각 패키지마다 버전이 달라서 애를 먹은 적이 있었어요. 이럴 땐 그냥 다 루트로 올려버리는 게 제일 속 편하더라고요.
그래서 말인데요, Vite는 기본적으로 싱글 패키지에 최적화돼 있어서 그냥 쓰면 바로 안 될 때가 많아요. 특히 심볼릭 링크 문제나, 다른 패키지 코드에 접근해야 할 때요.
실전 팁:
resolve.preserveSymlinks: true
로 심볼릭 링크 이슈 해결server.fs.allow
에 패키지 경로 추가build.commonjsOptions.include
로 명시 처리// vite.config.js 예시
import { join } from 'path'
export default {
resolve: { preserveSymlinks: true },
: {
: {
: [
(__dirname, ),
(__dirname, ),
],
},
},
: {
: {
: [, ],
},
},
}
제가 처음에 이 설정 빼먹고, 패키지 코드 변경이 실시간 반영이 안 돼서 "왜 이러지?" 한참 헤맸던 기억이 나네요.
모노레포에서 Vite SSR 쓰다 보면, 어떤 모듈은 번들에 넣고 어떤 건 외부화해야 하는지 머리가 아파요. 저도 ssr.noExternal
안 쓰다가 서버에서만 필요한 모듈이 클라이언트 번들에 들어가서 에러났던 적이 있어요.
실전 팁:
ssr.noExternal
로 번들에 꼭 포함할 패키지 지정// vite.config.js에서 SSR 옵션
export default {
ssr: {
noExternal: ['@core/api'], // 꼭 묶어서 번들에 넣어야 하는 패키지
},
}
어? 이게 무슨 말이냐고요? 예를 들어, 서버 전용 인증 모듈이 클라이언트에 포함되면 보안상 큰일나잖아요! 그래서 환경별로 코드를 분기하는 게 중요해요.
대규모 모노레포에서는 빌드 시간 줄이는 게 생명입니다. 저도 캐시가 꼬여서 빌드가 엄청 느려졌던 적이 있는데, 그때 알게 된 꿀팁들 공유할게요.
실전 팁:
cacheDir
을 패키지별로 따로 설정esbuild
플러그인 옵션으로 불필요한 변환 최소화optimizeDeps.exclude
로 사전 번들링이 필요 없는 모듈 제외// vite.config.js에서 패키지별 캐시 디렉터리 지정
export default {
cacheDir: 'node_modules/.vite-my-package',
optimizeDeps: {
exclude: ['moment'], // 사전 번들링 불필요
},
}
잠깐, 여기서 정리하고 넘어갈게요.
모노레포에서 Vite를 쓸 때는
솔직히 저도 아직 배우는 중이지만, 실수하면서 익힌 노하우라 꼭 한번 적용해보세요!
이제 실전에서 많이 쓰는 모노레포 도구들과 Vite의 궁합, 그리고 각 도구별 장단점까지 살펴볼 시간입니다. 사실 이 부분에서 저도 처음엔 뭘 써야 할지 한참 고민했어요. 여러분도 비슷한 고민 있으시죠?
가장 가볍고 직관적인 선택이에요.
실제로 작은 팀이나 비교적 단순한 구조의 모노레포에는 pnpm workspace만으로도 충분히 운영이 가능했습니다. 단, 빌드 파이프라인을 직접 짜야 해서, 자동화가 익숙하지 않으면 조금 번거로울 수 있어요.
대규모 프로젝트에서 진가를 발휘하는 도구입니다.
처음엔 Nx의 방대한 기능에 압도당했는데, 익숙해지니 빌드 속도와 협업 효율이 확 올라가더라고요. 특히 nx affected
명령어로 변경된 패키지만 똑똑하게 빌드할 수 있는 점이 정말 편했습니다.
Vercel에서 만든 모노레포 빌드 도구로, 최근 빠르게 인기를 얻고 있어요.
Turborepo는 설정이 간단하고, 빌드 캐시가 정말 강력해서, 대규모 프로젝트에서도 빌드 시간을 크게 줄여줍니다. 저도 Turborepo를 써보고 “이렇게까지 빨라질 수 있구나!” 하고 놀랐어요.
// nx.json
{
"projects": {
"web": {
"tags": []
// project.json (web)
{
"targets": {
"build": {
"executor": "@nx/vite:build"
},
# pnpm-workspace.yaml
packages:
- 'packages/*'
nx reset
명령어 사용휴, 복잡하죠? 천천히 다시 볼게요.
각 도구의 공식 문서와 커뮤니티도 꼭 참고해보세요. 실제로 거기서 얻은 팁들이 실무에서 큰 도움이 됐거든요.
실제 현장에서 겪은 구체적인 문제와 해결 과정을 예시로 보여드릴게요.
저도 이거 하다가 3시간 날렸어요... 여러분은 저처럼 삽질하지 마시라고!
my-monorepo/
├── apps/
│ ├── web/
│ │ ├── src/
│ │ └── vite.config.ts
│ └── admin/
│ ├── src/
│ └── vite.config.ts
├── packages/
│ ├── core/
│ │ └── src/
│ └── ui/
│ └── src/
├── pnpm-workspace.yaml
└── package.json
처음엔 apps/web
에서 packages/core
의 코드를 수정해도 HMR이 안 먹히더라고요.
알고 보니 Vite의 server.fs.allow
옵션에 core 패키지 경로를 추가하지 않아서였습니다.
// apps/web/vite.config.ts
{ defineConfig } ;
path ;
({
: {
: {
: [
path.(__dirname, ),
path.(__dirname, ),
],
},
},
: {
: {
: path.(__dirname, ),
: path.(__dirname, ),
},
},
});
core
와 ui
가 서로 다른 버전의 react
를 참조해서, 빌드가 계속 깨졌어요.
이럴 땐 루트 package.json
에서 의존성 버전을 통일하고, 각 패키지에서는 "react": "workspace:*"
로 맞춰주는 게 정답입니다.
Turborepo로 빌드 캐시를 썼는데, 변경된 코드가 반영이 안 됐어요.
이럴 땐 node_modules/.turbo
폴더를 삭제하고 다시 빌드하면 깔끔하게 해결됩니다.
Vite 기반 모노레포 세팅은 대규모 프로젝트에서도 빠른 빌드와 효율적 코드 관리를 가능하게 합니다. Webpack 대비 숨겨진 함정도 있지만, Nx, Turborepo, pnpm workspace 등과 연계하면 생산성과 안정성을 모두 잡을 수 있습니다.
이제 여러분도 소개한 가이드와 사례를 참고해 직접 Vite 모노레포 환경을 구축해 보세요. 변화의 두려움 대신, 한 발 앞선 개발 문화를 경험하는 주인공이 되시길 응원합니다!
Vite의 플러그인 시스템을 이해하면 대규모 프로젝트에서 빌드 최적화나 기능 확장이 용이해집니다.
대규모 프로젝트에서 빌드 시간과 번들 크기를 최소화하는 다양한 기법을 익혀야 합니다.
프로젝트 규모가 커질수록 다양한 환경 설정이 중요해집니다.
대규모 코드를 체계적으로 관리하려면 타입 시스템이 필수적입니다.
실제 프로젝트는 보통 프레임워크와 함께 사용합니다.
여러분, 어때요? 처음엔 복잡해 보여도, 하나씩 해보면 금방 익숙해집니다. 저도 아직 배우는 중이지만, 삽질하면서 익힌 노하우를 최대한 담아봤어요. 혹시 궁금한 점이나, “이건 왜 이렇게 해야 하죠?” 싶은 부분 있으면 댓글로 남겨주세요. 같이 성장하는 게 개발자의 특권 아니겠어요?
오늘도 즐코딩! 🚀
Nx, Turborepo, pnpm workspace와 함께하는 Vite 모노레포 최적화
실전에서 많이 쓰는 모노레포 도구들과 Vite의 궁합, 그리고 각 도구별 장단점까지!
실제 사례: Vite 기반 대규모 모노레포 프로젝트 구성 예시
실무에서 겪은 구체적인 문제와 해결 과정을 예시로 보여드릴게요.
결론 및 앞으로의 전망
앞으로 Vite와 모노레포가 어떻게 발전할지, 그리고 여러분이 어떤 준비를 하면 좋을지 정리합니다.