turborepo 로 monorepo 구성하기(with pnpm)
1) turbo 테일윈드 템플릿으로 monorepo 생성하기
pnpm dlx create-turbo@latest --example with-tailwind
2) apps/storybook 에 storybook 설치하기
cd apps
mkdir storybook
cd storybook
pnpm dlx storybook@latest init
3) packages/ui > packages/shared 로 변경
- 이때 package.json 의 "name" 도 꼭 수정해주어야 함
- 각 app 폴더의 next.config.js 도 수정해주어야 함
- 검색에서 /ui 검색후 나오는 것 모두 /shared 로 변경
4) apps 폴더 원하는대로 바꾸고, lock파일 삭제후 다시 pnpm install
rm pnpm-lock.yaml
pnpm install
5) apps 폴더 하위의 각 app 폴더의 package.json 수정
"scripts": {
"dev": "next dev --port 3000" // 포트는 3000으로 통일
//....
6) 각 apps 의 필요한 곳에서 의존성 설치
pnpm add @tanstack/react-query @tanstack/react-query-devtools react-hook-form react-icons tailwind-merge
7) .vscode/settings.json 수정
{
"eslint.workingDirectories": [
{
"mode": "auto"
}
],
"editor.codeActionsOnSave": {
"source.organizeImports": "always",
"source.fixAll.eslint": "always"
},
"editor.formatOnSave": true
}
8) .prettierrc.json 파일 설정
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 108,
"tabWidth": 2,
"endOfLine": "auto",
"arrowParens": "always",
"bracketSpacing": true,
"useTabs": false
}
9) env 는 각 app 폴더에 각각 넣기
에러 수정일지
1) @repo 모듈 못찾는 문제 해결을 위해 .vscode 에 아래 내용 추가
{
"eslint.workingDirectories": [
{
"mode": "auto"
}
],
}
3) pnpm install 실행 후, pnpm-lock.yaml 파일 수정 됨
4) packages/shared 매번 컴파일 없이 사용할 수 있도록 각 tailwind.config.ts 수정
// apps/ 하위 storybook 제외 모든 app의 tailwind.config.ts 파일에서 본 내용 적용
import sharedConfig from '@repo/tailwind-config';
import type { Config } from 'tailwindcss';
const config: Pick<Config, 'content' | 'presets'> = {
content: [
// app content
`src/**/*.{js,ts,jsx,tsx}`,
// 아래 부분을 추가!
'../../packages/shared/*.{js,ts,jsx,tsx}',
],
presets: [sharedConfig],
};
export default config;
5) packages/shared/package.json 에서 "main" 삭제 및 "exports"추가
{
"name": "@repo/shared",
"version": "0.0.0",
"sideEffects": [
"**/*.css"
],
"files": [
"dist"
],
// 아래 exports 부분 추가됨
"exports": {
"./styles.css": "./src/styles.css",
"./components": "./src/components/index.ts"
},
"license": "MIT",
"scripts": {
"build": "tailwindcss -i ./src/styles.css -o ./dist/index.css",
"lint": "eslint src/",
"dev": "tailwindcss -i ./src/styles.css -o ./dist/index.css --watch",
"type-check": "tsc --noEmit"
},
"peerDependencies": {
"react": "^18.2.0"
},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
"@repo/tailwind-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@types/react": "^18.2.61",
"autoprefixer": "^10.4.18",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"typescript": "^5.3.3"
}
}
6) shared/index 삭제 후, shared/src/components 에 index.ts 추가
// packages/shared/src/components/index.ts
export { Card } from './card';
// 이런 식으로 공통 컴포넌트들 생길 때 마다 계속 익스포트를 추가해줘야 함
7) 각 app 의 컴포넌트에서 정상적으로 임포트 되는 것을 확인!
8) .vscode eslint 설정 사용 하지 않고 참조 문제 해결하기
.vscode/settings.json 에 eslint.workingDirectories > mode : auto 옵션으로 임포트 에러를 잡고 있었는데,
만약 vscode를 사용하지 않는 팀원이 있다면 어떡하지!??
그럴때를 위해서 구조를 수정할 필요가 있다고 느꼈습니다.
여러가지 삽질결과 해결한 방법은 다음과 같습니다.
- .vscode에 옵션을 추가하지 않으면 다시 에러가 발생하는데, 테스트 결과 원인은 packages/config-eslint 하위 파일들에 있었습니다.
- const project = resolve(process.cwd(), 'tsconfig.json'); 이 구문에서 path 가 최상위 루트 디렉토리로 잡혀서 tsconfig.json을 찾지 못하는 문제가 발생하는 것이었습니다.
- 이를 해결하기 위해 다양한 방법을 써봤지만 잘 되지 않아서 packages/config-eslint 하위 설정 파일들에서 parserOptions 와 settings 옵션을 주석처리해버리고,
- apps 하위의 각 디렉토리(www, invitation, admin)내의 .eslintrc.js 파일에 tsconfig의 위치를 아래와 같이 직접 설정함으로서 해결했습니다.
const { resolve } = require('node:path');
const project = resolve(__dirname, 'tsconfig.json');
module.exports = {
extends: ['@repo/eslint-config/next.js'],
parserOptions: {
project,
},
settings: {
'import/resolver': {
typescript: {
project,
},
node: {
extensions: ['.mjs', '.js', '.jsx', '.ts', '.tsx'],
},
},
},
};
추신) shared 폴더 사용 관련 gpt 질의응답 내역 첨부
>> turborepo readme 해석 좀 부탁해요<<
이 리드미는 TurboRepo Tailwind CSS Starter Pack에서 packages/ui
패키지를 설정하고, 이 패키지를 Next.js 앱과 어떻게 연결할지에 대한 설명입니다. 특히 Tailwind CSS 설정과 컴포넌트 스타일링 관련 내용을 다루고 있습니다. 각 항목을 자세히 해석해 보겠습니다.
주요 내용 해석
- "Building packages/ui":
packages/ui
폴더는 UI 컴포넌트가 포함된 패키지입니다. 이 패키지의 스타일은 컴파일된 형태로dist
디렉토리에 저장됩니다.- Next.js 앱들은
packages/ui
에서 컴파일된.tsx
파일을 직접 사용하며, 이를 위해next.config.js
파일에서transpilePackages
설정을 사용합니다.
- "Make sharing one tailwind.config.js to apps and packages as easy as possible":
- 이 구조에서는 단일
tailwind.config.js
파일을 여러 앱과 패키지에서 공유할 수 있도록 설계되어 있습니다. 즉, 각 앱과 패키지에서 하나의 Tailwind 설정을 사용하여 일관성을 유지할 수 있습니다.
- 이 구조에서는 단일
- "Make package compilation simple by only depending on the Next.js Compiler and tailwindcss":
- 이 설정은 Next.js 컴파일러와 Tailwind CSS에 의존하여 컴파일 과정을 간소화합니다. 추가적인 복잡한 컴파일러나 설정을 추가할 필요 없이 Next.js와 Tailwind CSS로 스타일 컴파일을 처리합니다.
- "Ensure Tailwind classes do not overwrite each other. The ui package uses a ui- prefix for its classes":
- 클래스 이름 충돌을 방지하기 위해
packages/ui
에서 사용하는 Tailwind 클래스에는ui-
접두사를 붙입니다. 예를 들어,text-center
대신ui-text-center
를 사용합니다. 이렇게 하면 다른 앱이나 패키지에서 동일한 클래스 이름을 사용하더라도 충돌을 피할 수 있습니다.
- 클래스 이름 충돌을 방지하기 위해
- "Maintain clear package export boundaries":
packages/ui
는 명확한 패키지 경계를 유지하여, 다른 앱이나 패키지에서 이 패키지를 사용할 때 구조를 명확히 유지합니다. 즉,packages/ui
는 다른 앱에 명확한 인터페이스(컴포넌트와 스타일)를 제공하며, 이 경계를 통해 패키지 간 혼선을 방지합니다.
대안: 직접 소스에서 packages/ui
를 사용하는 방법 (컴파일 없이)
- "Another option is to consume packages/ui directly from source without building":
- 컴파일된 패키지를 사용하지 않고,
packages/ui
에서 소스 코드를 직접 사용할 수도 있습니다. 이 경우 컴파일 과정이 필요하지 않으며, Next.js 앱이 소스 코드를 직접 참조하게 됩니다.
- 컴파일된 패키지를 사용하지 않고,
- "If using this option, you will need to update the tailwind.config.js in your apps to be aware of your package locations":
- 소스 코드를 직접 참조하려면, 각 앱의
tailwind.config.js
파일에서 Tailwind가packages/ui
폴더를 인식할 수 있도록 경로 설정을 해야 합니다. - Tailwind CSS는 CSS를 사용할 파일 경로를 알아야 CSS를 생성할 수 있습니다. 이 경로에
packages/ui
의 파일들도 포함시켜야 합니다.
- 소스 코드를 직접 참조하려면, 각 앱의
tailwind.config.js
의content
설정:tailwind.config.js
파일에서content
설정은 Tailwind가 CSS를 생성할 파일들을 정의합니다. 만약 소스에서 직접 사용하려면packages/ui
내의 파일 경로도 이content
설정에 포함해야 합니다.
content: [ // 앱의 컴포넌트 파일 경로 `src/**/*.{js,ts,jsx,tsx}`, // packages/ui 경로도 포함 "../../packages/ui/*.{js,ts,jsx,tsx}", ],
- "If you choose this strategy, you can remove the tailwindcss and autoprefixer dependencies from the ui package":
- 만약
packages/ui
를 소스 코드에서 직접 참조하는 방식을 선택한다면,packages/ui
패키지 자체에서tailwindcss
와autoprefixer
의존성을 제거할 수 있습니다. 왜냐하면tailwindcss
와autoprefixer
는 각 앱에서 이미 적용되고 있기 때문입니다.
- 만약
요약
- 컴파일된
packages/ui
:packages/ui
의 스타일을 컴파일하여dist
디렉토리에서 사용하고, Next.js 앱에서 컴파일된 결과물을 사용합니다.- 클래스 충돌을 방지하기 위해
ui-
접두사를 사용하며, 패키지 경계도 명확히 유지됩니다.
- 소스에서 직접 사용:
- 컴파일 없이 소스 코드를 직접 참조하려면, 각 앱의
tailwind.config.js
에packages/ui
의 파일 경로를 추가해야 합니다. - 이 방법을 선택하면
packages/ui
의tailwindcss
와autoprefixer
의존성을 제거할 수 있습니다.
- 컴파일 없이 소스 코드를 직접 참조하려면, 각 앱의
>> 1번은 그러면 pnpm build 를 해야지만 쓸수 있는 것이고 2번은 안해도 쓸 수 있는 것인가요? <<
이 두 가지 옵션 중에서 프로젝트 구조에 맞는 방식으로 packages/ui
를 사용할 수 있습니다.
네, 맞습니다. 1번과 2번 방법의 차이는 pnpm build
를 해야 하는지 여부와 관련이 있습니다.
1번: 컴파일된 packages/ui
사용 (pnpm build 필요)
- 이 방법에서는
packages/ui
의 스타일 및 컴포넌트를 먼저 컴파일한 후, Next.js 앱에서 컴파일된 결과물을 사용합니다. - 즉,
pnpm build
명령어를 실행하여 컴포넌트를 빌드하고,dist
폴더에 컴파일된 파일을 생성한 후에야 Next.js 앱에서 이를 사용할 수 있습니다. - 빌드 과정:
packages/ui
에서pnpm build
를 실행합니다.- 컴파일된 파일들이
dist
디렉토리에 생성됩니다. - Next.js 앱은
dist
디렉토리의 컴파일된 결과물을 참조합니다.
- 요약*:
pnpm build
를 실행해야packages/ui
의 스타일과 컴포넌트를 사용할 수 있습니다.
2번: 소스에서 직접 packages/ui
사용 (pnpm build 불필요)
- 이 방법에서는 컴파일 과정 없이,
packages/ui
의 소스 코드(.tsx 파일)를 직접 참조합니다. - 컴포넌트와 스타일 파일들을 빌드하지 않고도 Next.js 앱에서 바로 사용 가능합니다.
- 단, 이 방법을 사용하려면 Next.js 앱의
tailwind.config.js
파일에서packages/ui
의 파일 경로를content
설정에 추가해야 합니다. - 이 설정을 통해 Tailwind CSS가
packages/ui
내부의 Tailwind 클래스를 인식하고, 해당 스타일을 적용할 수 있게 됩니다. - 요약*:
pnpm build
없이packages/ui
의 소스 코드를 직접 참조하여 사용할 수 있습니다. Tailwind 설정만 올바르게 추가하면 됩니다.
결론
- 1번 방법:
pnpm build
가 필수입니다. 컴파일된 결과물을 Next.js 앱에서 사용합니다. - 2번 방법:
pnpm build
불필요. 소스 코드를 바로 사용하고, Tailwind 설정만 추가하면 됩니다.
두 방법 중 프로젝트 요구사항에 맞는 방식을 선택하시면 됩니다!
'TIL' 카테고리의 다른 글
[240919 TIL] revalidatePath, on-demand ISR (1) | 2024.09.19 |
---|---|
[240908 TIL] zod 사용 관련 (1) | 2024.09.08 |
[240906 TIL] Monorepo 구성하기 (0) | 2024.09.06 |
[240821 TIL] 컬쳐핏 (0) | 2024.08.21 |
[240814 TIL] openai 이미지생성 (0) | 2024.08.15 |