지난 글에서는 크롬 익스텐션에서 소셜 로그인을 하는 방법에 대해 알아보았다.
이번에는 모노레포의 종류 중 하나인 Turborepo에 대해서 알아보고, 왜 졸업 작품에서 모노레포 방식을 사용하게 되었는지 이야기를 해보고자 한다.
우리 팀은 졸업 작품으로 크롬 익스텐션과 웹 애플리케이션 총 2개를 만든다.
처음에는 레포지토리를 2개를 생성하여 멀티 레포 구조를 가져가려 했다.
하지만 개발을 하다 보면 익스텐션의 UI와 웹의 UI에서 중복으로 사용되는 컴포넌트가 나올 것이고, DTO 및 기타 타입 등이 겹치게 될 것이다.
이를 2개의 레포지토리에서 따로 관리를 하게 된다면 컴포넌트 혹은 타입의 수정이 필요할 때 2개 모두 일일이 수정해야 한다는 번거로움이 있다.
따라서 모노레포를 도입하여 진행하기로 했다.
모노레포란 하나의 레포지토리에서 여러 개의 프로젝트를 관리할 수 있는 방식을 의미한다.
그렇다면 모노레포를 사용하면서 얻을 수 있는 이점으로는 뭐가 있을까?
위에서도 언급했듯이 공통으로 사용되는 util, hook 등을 효율적으로 관리할 수 있게 된다.
Typescript, eslint 등을 동일한 버전으로 사용함으로써 동일한 개발 환경을 유지할 수 있다.
하나의 레포지토리에서 관리가 되기 때문에 코드 컨벤션 및 테스트를 일관되게 유지할 수 있다.
특히 1, 2번의 이점으로 멀티레포가 아닌 모노레포를 선택하게 되었다.
모노레포도 종류가 여러 가지 있는데 이 중에서 Turborepo를 선택한 이유에 대해 이야기해보겠다.
다른 모노레포인 Nx에 비해 설정 및 사용이 간단하고 공식 문서에 다양한 examples가 있어서 필요에 맞게 갖다 쓰거나 참고해서 쓰기 좋았다.
Turborepo는 Vercel에서 제작했기 때문에 원격 캐싱 혹은 Vercel에서 제공하는 다양한 기능들을 쉽게 사용할 수 있다.
🚨 문제 상황
처음 폴더 구조는 아래와 같았다.
apps
|_extension
|_www
packages
|_types
|__example.ts
|__index.ts
|__package.json
// example.ts
export interface Example {
name: string;
age: number;
}
// index.ts
export type * from "./example";
// package.json
{
"name": "@repo/types",
"exports": {
"types": "./index.ts"
}
}
www와 extension의 devDependencies에 “@repo/types”: “workspace:*”를 명시하고 pnpm install을 하여 Example 타입을 가져오려 했는데, 자동 완성에 나오지 않았다.

직접 import하려 해도 아래와 같은 에러가 나왔다.

🔍 해결 과정
tsconfig.json의 compilerOptions 옵션에 types 필드를 추가하여 @repo/types를 컴파일 목록에 추가하였다.
{
"compilerOptions": {
"types": ["@repo/types"]
},
}
types 필드에 대해 간단하게 알아보겠다.
컴파일 목록에 포함되게 되면 전역 스코프로 들어가게 되어 자동 완성 추천에 나오게 된다.
이후 폴더 구조와 package.json의 내용을 아래와 같이 바꿨다.
apps
|_extension
|_www
packages
|_types
|__dist
|__src
|___example
|____index.ts
|___index.ts
|___package.json
// package.json
{
"name": "@repo/types",
"scripts": {
"build": "tsc"
},
"exports": {
"types": "./dist/index.d.ts"
}
}
pnpm build를 이용하여 dist/index.d.ts를 생성 후 apps 패키지에서 Example 타입을 입력하니 자동 완성 추천이 정상적으로 되었다.

🚨 문제 상황
types 패키지에서 새롭게 추가하거나 수정한 내용들이 개발 시 실시간으로 반영되지 않는 것을 확인했다.
🔍 해결 과정
watch라는 옵션을 달아주어 type에 변경이 생기면 바로 반영이 되도록 수정했다.
또한 개발 서버와 tsc —watch를 같이 실행시키기 위해 root의 package.json에 스크립트를 추가해 주었다.
// package.json
{
"scripts": {
"dev": "turbo dev", // www, extension, tsc 모두 실행
"dev:extension": "turbo dev --filter=extension --filter=@repo/types", // extension, tsc 실행
"dev:www": "turbo dev --filter=www --filter=@repo/types", // www, tsc 실행
},
}
// packages/types/package.json
{
"name": "@repo/types",
"scripts": {
"dev": "tsc --watch"
},
"exports": {
"types": "./dist/index.d.ts"
}
}
모노레포 세팅을 처음부터 끝까지 해보는 것이 처음이라 많이 어려웠다.
tsconfig.json의 동작 방식, package.json의 필드에 대한 개념이 부족하다고 느끼게 된 계기가 되었다. 하지만 그만큼 얻어 가는 것도 많았던 것 같다.