๋ธ๋ก๊ทธ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ์ฌ๋ฌ ๋ฒ ์ธํ ์ ์๋ํ๊ณ , ๊ทธ ๊ณผ์ ์์ ํฌ๊ธฐ๋ ์ฌ๋ฌ ๋ฒ ํ์ต๋๋ค. ๋ค์ํ ์๋ ๋์ monorepo ๊ตฌ์กฐ๋ก ๊ตฌ์ฑํ๋ ๋ฐฉ์์ด ๊ฐ์ฅ ๊น๋ํ๊ฒ ํ๋ก์ ํธ๋ฅผ ๋๋๊ณ ์ฌ์ฉํ๊ธฐ์๋ ํธํ๋ค๋ ๊ฒฐ๋ก ์ ๋๋ฌํ์ต๋๋ค. ๋จ์ํ ํด๋ ๊ตฌ์กฐ๋ง์ผ๋ก ๊ธฐ๋ฅ์ ๊ตฌ๋ถํ๋ ค ํ์ ๋๋ ํด๋๊ฐ ์ง๋์น๊ฒ ์ธ๋ถํ๋์๊ณ , ๊ทธ๋ ๋ค๊ณ ํจํค์ง๋ค์ repo๋ฅผ ๋๋๋ ค ํ๋ฉด ๊ด๋ฆฌํ๊ณ ๋ค๋ฅธ ์ฑ์ ์ ์ฉํ๊ธฐ ์ง์ฆ๋ฉ๋๋ค. ํนํ ์๋ํฐ ๊ธฐ๋ฅ์ ํฌํจํ๋ ค๋ค ๋ณด๋ ์ฝ๋ ์์ด ๋ง์์ง๋ฉด์ ๋๋ฉ์ธ๊ณผ ์ฝ๋๊ฐ ์์ด๊ธฐ ์ฌ์ ์ต๋๋ค. ๋ฐ๋ฉด, ํ๋์ ๋ ํฌ์์ ๋ชจ๋๋ณ๋ก ๋ถ๋ฆฌํ๋ ๋ฐฉ์์ ์์ฐ์ค๋ฝ๊ฒ ๋๋ฉ์ธ๊ณผ ์ฝ๋๊ฐ ๋ถ๋ฆฌ๋๋ฉฐ, ์ฌ์ฌ์ฉ์ฑ ๋ฐ ์ฌ์ฉ์ฑ(๊ฐ๋ฐ์ ๊ฒฝํ)๊น์ง ํ๋ณดํ ์ ์๋ค๋ ์ ์์ ํ์คํ ์ฅ์ ์ด ์๋ค๊ณ ๋๊ผ์ต๋๋ค.
์๋๋ ๋ธ๋ก๊ทธ ๋ง๋ค ๋ ์ฌ์ฉํ Monorepo ๊ตฌ์กฐ์ ๋๋ค.

๊ณตํต๋๋ ์ค์ ๋ค์ eslint.base.js, tsconfig.base.json์ ๋ด๊ฒจ์ ธ ์์ด ๊ฐ ์ฑ๊ณผ ํจํค์ง์์ ์ด๋ฅผ extendsํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ์ต๋๋ค. ์ต์ ํ๋ฅผ ์ํด์ references ์์ฑ์ ์ด์ฉํด ์์กด์ฑ์ ๋ง๋ค์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ต์ ๋ฒ์ (eslint v9.16)์ผ๋ก ์ค์ ์ ํ๋ค๋ณด๋ ๋ ํผ๋ฐ์ค๊ฐ ๋ถ์กฑํ์ฌ ์ผ๋ถ๋ถ ๋ค์ฃฝ๋ฐ์ฃฝ ์ค์ ํ ๋ถ๋ถ๋ ์์ต๋๋ค.
โโโ apps/โ โโโ storyBook/ # storybookโ โโโ carrotBlogFront/ # Next.js ์ฑ (๋ฉ์ธ ํ๋ก ํธ์๋)โ โโโ carrotMobileApp/ # React Native ์ฑ โโโ packages/โ โโโ designSystem/ # tailwind ๊ธฐ๋ฐ ๋์์ธ ์์คํ
โ โโโ editor/ # ์๋ํฐโ โโโ domain/ # ๋๋ฉ์ธ [Entity, FetchApi, Util]โ โโโ utils/ # ๊ณตํต ์ ํธโโโ preinstall.js # preinstall ์คํฌ๋ฆฝํธโโโ pnpm-workspace.yaml # pnpm์ ๋ณ๋ ํ์ผ๋ก ์ํฌ์คํ์ด์ค ์ ์โโโ package.json โโโ turbo.json # ๋น๋ ํ์ดํ๋ผ์ธ, task ์ค์ โโโ eslint.config.js # root eslintโโโ tsconfig.json # root tsconfigโโโ eslint.config.base.js # ๊ณตํต eslintโโโ tsconfig.base.json # ๊ณตํต tsconfigtsconfig์ eslint ์ค์ ์ ๊ณตํต๋ ๋ถ๋ถ์ ๊ฐ๊ฐ ํจํค์ง๋ก ๋ ์ง๊ด์ ์ผ๋ก ์ฐพ์์ ๊ด๋ฆฌํ ์ ์๋๋ก ๋ง๋ค์์ต๋๋ค.
๋ค์ผ๋ก ๊ธฐ์กด์ tsconfig๋ฅผ references ํ๋๋ฅผ ํ์ฉํ์ฌ ์ต์ ํ ํ๋๋ฐ ํผ์ ๊ฐ๋ฐํ๋ ๋งํผ ์์ฒญ ํฐ ํ๋ก์ ํธ๋ ๋๊ธฐ ํ๋ค๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์ฑ ์ธก๋ฉด์์ ๋ ์ข์ just in time packages ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ์ต๋๋ค. (references๋ฅผ ์ญ์ )
์ ๊ฐ ์ฒ์ eslint๋ฅผ ์ค์ ํ์๋, ์ต์ ๋ฒ์ ์ eslint๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ๋ฒ์ ์ฐพ์๋ณด๊ณ ์ ์ฉํ๋๋ผ ๋ค์ฃฝ๋ฐ์ฃฝ ์งํํ ์ ์ด ์์ต๋๋ค. ๊ทธ๋์ turboRepo dlx์ ์์ฑ๋๋ ๊ธฐ๋ณธ ์ค์ ์ผ๋ก ์๋น๋ถ๋ถ ๋ณ๊ฒฝํ์์ต๋๋ค.
โโโ apps/โ โโโ storyBook/ # storybookโ โโโ carrotBlogFront/ # Next.js ์ฑ (๋ฉ์ธ ํ๋ก ํธ์๋)โ โโโ carrotMobileApp/ # React Native ์ฑ โโโ packages/โ โโโ designSystem/ # tailwind ๊ธฐ๋ฐ ๋์์ธ ์์คํ
โ โโโ editor/ # ์๋ํฐโ โโโ domain/ # ๋๋ฉ์ธ [Entity, FetchApi, Util]โ โโโ utils/ # ๊ณตํต ์ ํธโ โโโ eslintConfig/ # eslint ์ค์ โ โโโ tsConfig/ # ํ์
์คํฌ๋ฆฝํธ ์ค์ โโโ preinstall.js # preinstall ์คํฌ๋ฆฝํธโโโ pnpm-workspace.yaml # pnpm์ ๋ณ๋ ํ์ผ๋ก ์ํฌ์คํ์ด์ค ์ ์โโโ package.json โโโ turbo.json # ๋น๋ ํ์ดํ๋ผ์ธ, task ์ค์ // apps/*/package.json// pacckages/*/package.json{ "devDependencies": { "@yooncarrot/eslint-config": "workspace:*", "@yooncarrot/ts-config": "workspace:*", "eslint": "9.16.0" }}// packages/typescript-config/tsconfig.base.json{ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "declaration": true, "declarationMap": true, "esModuleInterop": true, "isolatedModules": true, "composite": true, "lib": ["es2022", "DOM", "DOM.Iterable"], "module": "NodeNext", "moduleDetection": "force", "moduleResolution": "nodenext", "noUncheckedIndexedAccess": false, // index๋ก ์ ๊ทผํด๋ undefined์๋์ค๊ฒ "resolveJsonModule": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "allowImportingTsExtensions": true, "emitDeclarationOnly": true, "target": "ES2022" }}// packages/exlint-config/base.jsimport js from "@eslint/js";import eslintConfigPrettier from "eslint-config-prettier";import turboPlugin from "eslint-plugin-turbo";import tseslint from "typescript-eslint";import onlyWarn from "eslint-plugin-only-warn";/** * A shared ESLint configuration for the repository. * * @type {import("eslint").Linter.Config[]} * */export const config = [ js.configs.recommended, eslintConfigPrettier, ...tseslint.configs.recommended, { plugins: { turbo: turboPlugin, }, rules: { "turbo/no-undeclared-env-vars": "off", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": [ // ์ฌ์ฉํ์ง ์๋ ๋ณ์ underbar prefix ๋ถ์ด๋ฉด ์๋ฌ์๋๊ฒ ์ค์ "error", { args: "all", argsIgnorePattern: "^_", caughtErrors: "all", caughtErrorsIgnorePattern: "^_", destructuredArrayIgnorePattern: "^_", varsIgnorePattern: "^_", ignoreRestSiblings: true, }, ], }, }, { plugins: { onlyWarn, }, }, { ignores: ["dist/**"], },];๋ธ๋ก๊ทธ ํ๋ก์ ํธ์์ App์ ์คํ ๋ฆฌ๋ถ, React Web, React Native 3๊ฐ ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํจํค์ง๋ Design System, Editor, Domain, Utils 4๊ฐ์ ts์ esLint ์ค์ ์ ์ํ tsConfig, eslintConfig 2๊ฐ๋ก ๊ตฌ์ฑํ์ต๋๋ค.
App
React Web
React Native
Storybook
Package
DesignSystem
Editor
Domain
Utils
tsConfig
esLintConfig
์ฌ๊ธฐ์ Domain์ ๋ณ๋๋ก ๋ถ๋ฆฌํ ๋ชฉ์ ์ ์ข๋ API๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํจ์ ๋๋ค.(๋๋ฉ์ธ ์ฃผ๋ ๊ฐ๋ฐ ๋๋์ผ๋ก ์๊ฐํ ๊ฒ์ ์๋๋๋ค.) ๊ทธ๋ฆฌ๊ณ Domain ํจํค์ง์ ์ญํ ์ 3๊ฐ์ง ์ ๋๋ค.
ํ๋ก ํธ์์ ์ฌ์ฉํ Article์ด๋ Category๊ฐ์ Entity๋ฅผ ์ ์ํ๊ณ , ๋ฐฑ์๋์์ ๋ฐ๋ DTO๋ฅผ ์ ์ํ์ฌ DTO๋ฅผ Entity๋ก ๊ฐ๊ณตํ์ฌ App์์๋ ๋ฐ๋ก Entity๋ก ์ฌ์ฉํ ์ ์๋ ์ญํ ์ ํฉ๋๋ค.
๋ํ Restfulํ API๋ก ์ค๊ณํ์๋๋ฐ(์ฑ์๋ 2๋ ๋ฒจ ์ ๋), [Get, /articles]๊ฐ์ api๋ฅผ ์ฌ์ฉํ ๋ ์ข๋ ์ฒด๊ณ์ ์ผ๋ก ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ํ์ฉํ ์ ์๋๋ก App๊ณผ ๋ถ๋ฆฌํ์ต๋๋ค. ๊ทธ๋์ ๊ณตํต์ ์ธ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ค์ QueryStringFactory๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๊ท์น์ ์ด๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
ex) [Get, /articles?q=๋ธ๋ก๊ทธ&sort=+createdAt-likes&category=Typescript&page=0&size=9] ์ด api๋ "๋ธ๋ก๊ทธ"๋ฅผ ๊ฒ์ํ๋๋ฐ ์์ฑ์ผ ์ค๋ฆ์ฐจ, ์ข์์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ๋ ๋ฐ์ดํฐ์ด๊ณ , ์นดํ
๊ณ ๋ฆฌ๋ Typescript์ธ ๊ฒ๋ค๋ง ๊ฐ์ ธ์ค๋ api์
๋๋ค. ์ด๋ ๊ฒ ์ฟผ๋ฆฌ ์คํธ๋ง์ด ๋ง๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ api์์ ๊ณตํต์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค๋ฉด ๋ ์ข๋ค๊ณ ์๊ฐํ์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก๋ React Native๋ก ์ฑ์ผ๋ก๋ ๊ฐ๋ฐํด์ผ ํ๋๋ฐ, API ์ฌ์ฌ์ฉ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค.
Monorepo์์ ๋ชจ๋๊ฐ tsconfig๋ฅผ ๊ณต์ ํ๋ ๋ฐฉ๋ฒ๋ค์ ๋ํด์ ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค. ์๋ ์์๋ค์ ์ค์ ๋ก๋ Nx๋ฅผ ์ฌ์ฉํ์ ๋ ์์๋ค์ ๊ฐ์ ธ์จ ๊ฒ์ ๋๋ค. ํ์ง๋ง turboRepo๋ฅผ ์ฌ์ฉํด๋ ๋๊ฐ์ด ์ค์ ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ๊ฐ์ ์์๋ก ์ฌ์ฉํ์ต๋๋ค. tsconfig ๊ณต์ ๋ฐฉ๋ฒ๋ณ๋ก ์ฐจ์ด์ ๋ค ์ ๋ฆฌํ์ต๋๋ค. Monorepo ์ธํ ์ ํ์ค ๋ ํฐ ๋์์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
๊ตฌ๋ถ | ์ค๋ช | ํ์ ์ถ๋ก ์๋ | ๋น๋ ๋ฐฉ์ | ํ์ ํ์ผ | ๋ฐฐํฌ |
|---|---|---|---|---|---|
Project Reference | ts๊ฐ ํจํค์ง ๊ฐ ์์กด์ฑ/๋น๋ ์์๋ฅผ ์ถ์ | ๐ก ๋ณดํต (.tsbuildInfo ์ฌ์ฉ) | tsc --build tsc --watch (์ค์๊ฐ) | .d.ts .tsbuildinfo | โ |
Internal Package | ๋น๋ ์์ด ๊ทธ๋๋ก .ts ํ์ผ์ ์๋น | ๐ก ๋ณดํต | consumer ๋น๋ ์ฌ์ฉ | .ts | โ |
Compiled Package | ์์ค ์ฝ๋๋ฅผ ๋น๋ํด์ .js + .d.ts ์ถ๋ ฅ | ๐ข ๋น ๋ฆ | ๋น๋ ์ฌ์ฉ | .d.ts, .js | โ |
Publish Package | ์ธ๋ถ ๊ณต๊ฐ์ฉ์ผ๋ก ๋น๋๋ ํจํค์ง | ๐ข ๋น ๋ฆ | ๋น๋ ์ฌ์ฉ | .d.ts, .js | โ |
โโ . โโ apps โ โโ exampleApp โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ packages โ โโ exampleLib โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ tsconfig.base.json// apps/exampleApp/src/index.tsimport { add } from '../../../packages/exampleLib/src/index.ts';console.log(add(1,3));// tsconfig.base.json{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "strict": true, "moduleResolution": "NodeNext", "baseUrl": ".", "rootDir": "." }}// apps/exampleApp/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "../../dist", "declaration": true }, "include": ["src/**/*"]}// packages/exampleLib/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "../../dist", "declaration": true }, "include": ["src/**/*"]}์์กด์ฑ ํด๊ฒฐ
์๋ ๊ฒฝ๋ก๋ฅผ ์ด์ฉํ์ฌ ํจํค์ง ๊ฐ ์ฐ๊ฒฐ์ ๊ฐ์ฅ ๊ฐ๋จํ๊ฒ ํ ์ ์๋ ๋ฐฉ๋ฒ์
๋๋ค.
ํ์ง๋ง ์ฝ๋๋ฒ ์ด์ค ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ๋ฉด, extends ๊ฒฝ๋ก๋ฅผ ์ผ์ผ์ด ์์ ํด์ผ ํฉ๋๋ค. ํฐ ์ํฌ์คํ์ด์ค์์ ์ด ๋จ์ ์ด ๋ ๋ถ๊ฐ๋ ์ ์์ต๋๋ค.
๋ชจ๋ํ
์ฑ๊ณผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๊ฐ๊ฐ์ ํด๋๋ก ๋ถ๋ฆฌํ์ฌ ๋ชจ๋ํ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ค๋๋ค. ๋ฐ๋ผ์ ์ ์ง ๋ณด์์ฑ๋ ์ข์์ง๊ณ ์ํฌ์คํ์ด์ค๋ ์ฝ๊ฒ ํ์ํ ์ ์์ต๋๋ค.
ํ์ง๋ง Typescript ๊ด์ ์์๋ ์ ์ฒด๊ฐ ํ๋์ ํตํฉ๋ ํ๋ก์ ํธ๊ฐ ๋์ด, ํ์
๊ฒ์ฌ์์ ํจํค์ง ๊ฐ์ ๊ฒฝ๊ณ๊ฐ ์กด์ฌํ์ง ์๊ฒ๋ฉ๋๋ค.
์ฑ๋ฅ
Typescript ๊ด์ ์์ ์ ์ฒด๊ฐ ํ๋์ ํตํฉ๋ ํ๋ก์ ํธ๊ฐ ๋์ด ์ํฌ์คํ์ด์ค๊ฐ ํฌ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ต๋๋ค. ํ์ ๊ฒ์ฌ์ ์ปดํ์ผ์ ์ ์ฒด ๋ชจ๋์ ๋์์ผ๋ก ์ด๋ฃจ์ด์ง๊ธฐ ๋๋ฌธ์, ๋น๋ ์๋๊ฐ ๋๋ ค์ง๊ณ ์๋ํฐ ๋ฐ์์ฑ๋ ์ ํ๋ ์ ์์ต๋๋ค.
tsconfig.base.json
paths ํ๋ ์ถ๊ฐ
๊ฒฐ๋ก
import path ์ถ์ฝํ์ฌ ๊ฐ๋ ์ฑ ํฅ์
โโ . โโ apps โ โโ exampleApp โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ packages โ โโ exampleLib โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ tsconfig.base.json// tsconfig.base.json{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "strict": true, "moduleResolution": "NodeNext", "baseUrl": ".", "rootDir": "." "paths": { "@text-package/exampleLib": ["packages/exampleLib/src/index.ts"] } }}// apps/exampleApp/src/index.tsimport { add } from '@test-package/exampleLib';console.log(add(1,3));์์กด์ฑ ํด๊ฒฐ
Path alias๋ฅผ ์ฌ์ฉํ์ฌ ์๋ ๊ฒฝ๋ก๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ด์ ธ์ ์ฝ๋๋ฒ ์ด์ค ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋์ด๋ tsconfig.base.json์ paths๋ง ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋ฉ๋๋ค.
๋ชจ๋ํ์ ์ฑ๋ฅ์ ๋ฌ๋ผ์ง์ง ์์ต๋๋ค.
์๊ตฌ ์ฌํญ : typescript v3.0 ์ด์
root - package.json
scripts์ tsc --build๋ก
tsconfig.base.json
rootUrl ์ ๊ฑฐ
compilerOptions์์ composite:true ์ค์ => incremental์ด true๊ฐ ๋๊ณ ๋น๋ ์ .tsbuildinfo ์์ฑํจ
declaration ๊ด๋ จ ์ค์ ๋ค ์ถ๊ฐ
root - tsconfig.json
ํ์ผ ์ถ๊ฐ
references ํ๋ ์ถ๊ฐ
app - tsconfig.json
declaration, outDir ํ๋ ์ ๊ฑฐ
references ํ๋ ์ถ๊ฐ
packages - tsconfig.json
declaration, outDir ํ๋ ์ ๊ฑฐ
๊ฒฐ๋ก
ํ์ ์คํฌ๋ฆฝํธ๊ฐ ๋ชจ๋๋ณ๋ก ๋ณ๋ ๊ด๋ฆฌ
์ฑ๋ฅ ํฅ์
ํ์ ์์กด์ฑ ์์ฑ (๋น๋ ์์กด์ฑ ์๊ธฐ๋ฉฐ ts๊ฐ ์์์ ๊ณ์ฐ)
โโ . โโ apps โ โโ exampleApp โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ packages โ โโ exampleLib โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ tsconfig.json โโ tsconfig.base.json// apps/exampleApp/src/index.tsimport { add } from '@test-package/exampleLib';console.log(add(1,3));// tsconfig.base.json// ํต์ฌ์ rootUrl ์ญ์ .{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "strict": true, "moduleResolution": "NodeNext", "composite": true, "declaration": true, "declarationMap": true, "sourceMap": true, "baseUrl": ".", "paths": { "@text-package/exampleLib": ["packages/exampleLib/src/index.ts"] } }}// tsconfig.json{ "files": [], "references": [{ "path": "./packages/exampleLib" }, { "path": "./apps/exampleApp" }]}// apps/exampleApp/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "rootDir": "src", }, "references": [{ "path": "../../packages/exampleLib" }], "include": ["src/**/*"]}// packages/exampleLib/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "rootDir": "src", }, "include": ["src/**/*"]}// packages/exampleLib/package.json{ "name": "test-package", ... "scripts": { "dev": "tsx --tsconfig tsconfig.base.json apps/exampleApp/src/index.ts", "build": "tsc --build", "clean": "tsc --build --clean", "typecheck": "tsc --build --emitDeclarationOnly" }}๋ชจ๋ํ
ํ๋ก์ ํธ ๋ ํผ๋ฐ์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ ๋ชจ๋์ ๋ ๋ฆฝ์ ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค. ์ปดํฌ๋ํธ ์ฌ์ด์ ๋ ผ๋ฆฌ์ ์ธ ๋ถ๋ฆฌ๋ฅผ ๊ฐ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ํจํค์ง ๊ฐ์ ๊ฒฉ๋ฆฌ ์์ค์ด ํฅ์๋๊ณ , ์์กด์ฑ์ ํจํค์ง ๋จ์๋ก ํ์ ๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
์ฑ๋ฅ
์ฆ๋ถ ๋น๋(incremental build)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ณ๊ฒฝ๋ ํจํค์ง๋ง ๋ค์ ์ปดํ์ผํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ๋น๋๋ฅผ ๋ฐ๋ณตํ ํ์๊ฐ ์์ต๋๋ค. ํ์ ์คํฌ๋ฆฝํธ๋ .tsbuildinfo ํ์ผ์ ์์ฑํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํ๊ณ ์ด๋ฅผ ํตํด ํ์ ๊ฒ์ฌ์ ์ปดํ์ผ ์๋๋ฅผ ํฅ์์ํต๋๋ค. ๊ท๋ชจ๊ฐ ํฐ ์ํฌ์คํ์ด์ค๋ CI ํ์ดํ๋ผ์ธ์์ ์ ์ฉํฉ๋๋ค. (๊ฐ๋ฐ ํธ์์ฑ์ผ๋ก --watch ์ต์ ์ฌ์ฉํ์ฌ ์ค์๊ฐ ์ ๋ฐ์ดํธ)
์๊ตฌ์ฌํญ : Node.js v13.2.0 ์ด์
์ด ๋ฐฉ์์ app(consumer)์์ package์ tsํ์ผ์ ์ง์ ์ฐธ์กฐํ๋ ๋ฐฉ์์ ๋๋ค. ๊ทธ๋์ transpiling์ ์ฑ ์์ด consumer์๊ฒ ์์ต๋๋ค. ๋ง์ฝ consumer๊ฐ Typescript๋ฅผ ์ปดํ์ผํ์ฌ ์ฌ์ฉํ ์ ์์ผ๋ฉด package๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
tsconfig.base.json
baseUrl ์ญ์
paths ์ญ์
app - package.json
private ํ๋ ์ถ๊ฐ
package๋ฅผ dependency์ ์ถ๊ฐ
app - tsconfig.json
baseUrl ํ๋ ์ถ๊ฐ
package - package.json
private ํ๋ ์ถ๊ฐ (๋จ๋ ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅ)
exports ํ๋ ์ถ๊ฐ
package - tsconfig.json
composite ํ๋ ์ถ๊ฐ
declaration ํ๋ ์ถ๊ฐ
main, type ์ถ๊ฐ
workspace ์ถ๊ฐ
pnpm์ pnpm-workspace.yaml ํ์ผ
npm, yarn์ root - package.json์ workspaces ํ๋ ์ถ๊ฐ.
๊ฒฐ๋ก
typescript path alias๊ฐ ์๋ package manager๋ก app๊ณผ ํจํค์ง๊ฐ ์ฐ๊ฒฐ๋จ
๋ชจ๋๋ค์ ๋ณ๋๋ก ํจํค์ง ๊ด๋ฆฌ
๋ ์๊ฒฉํ ํ๊ฒฝ ๋ถ๋ฆฌ
app์ ๋ณ๋ ํธ๋์คํ์ผ + ๋ฒ๋ค๋ง (app ๋น๋์ packages๊น์ง ํด์ค์ผํจ)
โโ . โโ apps โ โโ exampleApp โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ packages โ โโ exampleLib โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ pnpm-workspace.yaml โโ tsconfig.json โโ tsconfig.base.json// pnpm-workspace.yamlpackages: - 'apps/*' - 'packages/*'// apps/exampleApp/tsconfig.json{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "strict": true, "moduleResolution": "NodeNext", "composite": true, "declaration": true, "declarationMap": true, "sourceMap": true, }}// apps/exampleApp/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "dist", "rootDir": "src", "baseUrl": ".", "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo" }, "references": [{ "path": "../../packages/exampleLib" }], "include": ["src/**/*"]}// packages/exampleLib/tsconfig.json{ "extends": "../../tsconfig.base.json", "compilerOptions": { "baseUrl": ".", "rootDir": "src", "outDir": "dist", "tsBuildInfoFile": "dist/tsconfig.tsbuildinfo" }, "include": ["src/**/*"]}// packages/exampleLib/package.json{ "name": "@text-package/exampleLib", ... "type": "module", "exports": { ".": { "types": "./src/index.ts", "import": "./src/index.ts", "default": "./src/index.ts" }, "./package.json": "./package.json" }, "main": "./src/index.ts", "types": "./src/index.ts", "module": "./src/index.ts"}// apps/exampleApp/package.json{ "name": "@yooncarrot/exampleApp", ... "dependencies": { "@test-package/exampleLib": "workspace:*" // NPM์ ์ฐ๋ฉด ์ ํ์ฌํญ ์ด์ง๋ง, pnpm์์๋ ๋ฐ๋์ ๋ช
์ํด์ค์ผํฉ๋๋ค. }}์์กด์ฑ ํด๊ฒฐ
ํจํค์ง ๋งค๋์ ์ workspace๋ฅผ ์ฌ์ฉํ์ฌ ํจํค์ง ํด์์ ํจํค์ง ๋งค๋์ ์๊ฒ ์์ํ์ฌ typescript์ ๋ ๋ฆฝ์ ์ผ๋ก ๋์ํฉ๋๋ค.
๋ชจ๋ํ
๊ฐ ํจํค์ง์ ์์กด์ฑ์ด package.json์ ์ํด ๋ช ํํ๊ฒ ์ ์๋์ด ์ง๊ด์ ์ด๊ณ ์ดํดํ๊ธฐ ์ฌ์์ง๋๋ค. ๊ทธ๋ฆฌ๊ณ exportํ ํ์ผ์ ๋ช ์ํ๊ธฐ ๋๋ฌธ์ ํด๋น ํ์ผ์ importํ๋ ํจํค์ง์์ ํธ๋์คํ์ผํ๊ณ ๋ฒ๋ค๋งํ๋ ์ฑ ์์ ์ง๊ฒ ๋์ด ๋ ํ์คํ ๋ชจ๋ํ๊ฐ ๋ฉ๋๋ค.
์ฑ๋ฅ์ ์ด์ Reference๋ฐฉ์๊ณผ ๊ฐ์ต๋๋ค.
package - package.json
exports ๊ฒฝ๋ก๋ค์ ๋น๋ ๊ฒฝ๋ก๋ก ์์ (src/index.ts => dist/index.d.js..)
package.jsonํน์ exampleLib์ package.json ๋น๋ ์คํฌ๋ฆฝํธ ์ ์ ํ ์์ .
nx๋ turboRepo์ฐ๋ฉด ํด๋น monorepo ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ง๊ฒ ํ์ดํ๋ผ์ธ ์์ .
๊ฒฐ๋ก
๋ฒ๋ค๋ง ์ฑ ์์ด ๊ฐ ๋ชจ๋๋ณ๋ก ๊ฐ์ง ์ ์์. (๋ฏธ๋ฆฌ ๋น๋ํ๊ณ ์ ๊ณตํ๊ธฐ ๋๋ฌธ)
Compiled Packages๋ ๋น๋๋ฅผ ํด์ผ ํ์ ์ ๋ฐ์ดํธ๊ฐ ๋๊ธฐ ๋๋ฌธ์ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์.(๊ฐ๋ฐ ํธ์์ฑ ์ ํ ๊ฐ๋ฅ์ฑ)
๋๊ท๋ชจ ํ๋ก์ ํธ์์๋ pre-compile ๋ฐฉ์์ด ๊ฐ๋ฐ ํธ์์ฑ์ด ์ข์ ์ ์์ (IDE ํ์ ์ถ๋ก ๋๋ ์ด ์ ์ด์ง)
โโ . โโ apps โ โโ exampleApp โ โโ ... โ โโ package.json โ โโ tsconfig.json โโ package.json โโ packages โ โโ exampleLib โ โโ dist โ โ โโ index.d.ts โ โ โโ index.d.ts.map โ โ โโ index.js โ โ โโ index.js.map โ โ โโ tsconfig.tsbuildinfo โ โโ package.json โ โโ src โ โ โโ index.ts โ โโ tsconfig.json โโ pnpm-workspace.yaml โโ tsconfig.base.json โโ tsconfig.json// packages/exampleApp/package.json{ "name": "@test-package/exampleLib", "version": "0.0.0", // ์ถ๊ฐ๋ ํ๋ "private": true, // ์ถ๊ฐ๋ ํ๋ "type": "module", "exports": { ".": { "types": "./dist/index.d.ts", // ๋ชจ๋ ./src/* => ./dist/*๋ก ๋ณ๊ฒฝ(๋น๋๋ ํ์ผ) "import": "./dist/index.js", "default": "./dist/index.js" }, "./package.json": "./package.json" }, "main": "./dist/index.js", "types": "./dist/index.d.ts", "module": "./dist/index.js"}์์กด์ฑ ํด๊ฒฐ
์์กด์ฑ ํจํค์ง๋ค์ ๋ฏธ๋ฆฌ ์ปดํ์ผํ์ฌ, app ๋ฒ๋ค๋ฌ๊ฐ ๋ฏธ๋ฆฌ ๋น๋๋ ์ถ๋ ฅ๋ฌผ์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค. ๋ํ ์ ํ๋ฆฌ์ผ์ด์ ๋ฒ๋ค๋ง ์ค์ ํจํค์ง ์์กด์ฑ์ ์ปดํ์ผํ ํ์๋ ์์ด์ง๋๋ค. ์์ ํ์ดํ๋ผ์ธ ์์ฑ์ ํจํค์ง๋ค์ด ๋ฏธ๋ฆฌ ์ปดํ์ผ ๋๋๋ก ๋ณด์ฅํ์ฌ ์ํฌํ๋ก์ฐ๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค.
๋ชจ๋ํ
ํ์ ์คํฌ๋ฆฝํธ ์์ค ํ์ผ์ ์ง์ ์ฐธ์กฐํ๋ ์ด์ ๋ฐฉ์์ ๋นํด ๋ชจ๋์ฑ์ด ํฅ์๋ฉ๋๋ค. ํจํค์ง๋ฅผ ๋ฏธ๋ฆฌ ์ปดํ์ผํ๊ณ ํจํค์งํ๋ฉด, ๋ชจ๋ ธ๋ ํฌ ์ธ๋ถ์ ๋ฐฐํฌ๋ ๊ฐ๋ฅํฉ๋๋ค.
์ฑ๋ฅ
ํ์ ๊ฒ์ฌ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. ๋ฏธ๋ฆฌ ์ปดํ์ผ๋ .d.ts ํ์ผ์ ํตํด ํ์ ์ ๋ณด๊ฐ ๋ฏธ๋ฆฌ ์์ฑ๋์ด ํ๋ก์ ํธ ์ฐธ์กฐ๋ฅผ ํตํ ํ์ ์คํฌ๋ฆฝํธ ์์ค ํ์ผ์ ์ฒ๋ฆฌํ๋ ๋์ ์ด ํ์ ์ ๋ณด ํ์ผ์ ์ง์ ํ์ฉํ ์ ์์ต๋๋ค.
์๊ตฌ ์ฌํญ : typescript 5.4 ์ด์, NodeJs 14.6 ์ด์
package(ํจํค์ง)์ tsconfig ์ต์
์ค์ compilerOptions.paths๊ฐ consumer์๊ฒ๋ ์ ์ฉ๋์ง ์์ต๋๋ค. ์๋ํ๋ฉด app์ ํ์
์คํฌ๋ฆฝํธ๋ก ํธ๋์คํ์ผ ๋ ๊ฒ์ผ๋ก ์์ํ๊ณ ์๋๋๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋์ ํจํค์ง์์ path alias๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฌธ์ ๊ฐ ์๊ธฐ๋๋ฐ, ํ์
์คํฌ๋ฆฝํธ 5.0๋ถํฐ๋ nodejs์ 14.6๋ฒ์ ์ ์ถ๊ฐ๋ subPath ๊ธฐ๋ฅ์ผ๋ก ์ด๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
monorepo์์ Just-in-Time ํจํค์ง๋ app์์ ํจํค์ง์ ts ํ์ผ์ ์ง์ ์ฐธ์กฐํ๋ ๋ฐฉ์์ ๋๋ค. ์ฆ, ํ์ ์ ์ ํ์ผ(.d.ts)๋ .tsbuildInfoํ์ผ์ ์ฐธ์กฐํ์ง ์๋ ๋ฐฉ์์ ๋๋ค. ์ฅ์ ์ผ๋ก๋ ์ง์์ ์ธ build๊ฐ ํ์ ์์ด ์ค์๊ฐ์ผ๋ก ๋ฐ์๋๋ค๋ ์ ์ ๋๋ค.
โโ . โโ apps โ โโ exampleApp โ โโ ... โ โโ package.json โ โโ tsconfig.json โโ package.json โโ packages โ โโ exampleLib โ โโ package.json โ โโ src โ โ โโ add.ts โ โ โโ sub.ts โ โ โโ index.ts โ โโ tsconfig.json โโ pnpm-workspace.yaml โโ tsconfig.base.json โโ tsconfig.json// packages/exampleLib/package.json{ "name": "@test-package/exampleLib", "version": "0.0.0", // ์ถ๊ฐ๋ ํ๋ "type": "module", "imports": { // ์ถ๊ฐ๋ ํ๋ "#*": "./src/*" // package ๋ด๋ถ์์ path alias ์ฌ์ฉ์.(node ์ค์ ์์๋ @ ๋ถ๊ฐ) }, "exports": { // ์ถ๊ฐ๋ ํ๋ ".": "./src/index.ts", "./add": "./src/add.ts", "./sub": "./src/sub.ts", }, ...}// packages/exampleLib/tsconfig.json{ "extends": ["../../tsconfig.base.json"], "compilerOptions": { "baseUrl": ".", "paths": { "#*": ["./src/*"] // packge ๋ด๋ถ์์ path alias ์ฌ์ฉ์ Just-in-Time ํจํค์ง์์๋ @๋ถ๊ฐ. } }, "include": ["src/**/*"] ...}์์กด์ฑ ํด๊ฒฐ
Package ๋ชจ๋๋ค๋ path alias๋ฅผ ์ฌ์ฉํ์ฌ๋ ํ์ ์ฐธ์กฐ๊ฐ ๊ฐ๋ฅํ๊ฒ ๋ฉ๋๋ค. (path alias๋ก ์ธํ ์์กด์ฑ ๋ฌธ์ ๊ฐ ํด๊ฒฐ)
์ฑ๋ฅ
compiled packages๋ก ํจํค์ง๋ฅผ app์์ ์ฌ์ฉํ๋ ๊ฒ ๋ณด๋ค ์ฑ๋ฅ์ ์ข์ง ์์ต๋๋ค. ํ์ง๋ง ide์ ํ์ ์ ๋ณด์ฌ์ฃผ๋ ๊ธฐ๋ฅ์ ๋ง์ ๋ฆฌ์์ค๊ฐ ํ์ํ ๋๊ท๋ชจ ํ๋ก์ ํธ๊ฐ ์๋๋ฆฌ๋ฉด ๊ฐ๋ฐ์์ ๊ฐ๋ฐ ๊ฒฝํ์ ๋ ์ข์์ง ์ ์์ต๋๋ค.
EsLint ์ค์ ์ tsConfig์ค์ ๋ณด๋ค๋ ํจ์ฌ ๊ด๋ฆฌํ๊ธฐ ์ฝ์ต๋๋ค. ์ปดํ์ผ์ด๋ ๋ฒ๋ค๋ง๊ณผ ํฐ ์ฐ๊ด์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋จ์ํ eslintConfig ํจํค์ง์์ ๊ณตํต๋ eslint์ค์ ์ ๋ง๋ค๊ณ , App๊ณผ Package์์ importํด์ ์ฌ์ฉํ์ต๋๋ค.
// NextJs App์ eslint.config.jsimport {nextJsConfig} from "@yooncarrot/eslintConfig/next";/** @type {import("eslint").Linter.Config} */export default nextJsConfig;// esLintPackage ํจํค์ง์ base.jsexport const config = [ js.configs.recommended, eslintConfigPrettier, ...tseslint.configs.recommended, { plugins: { turbo: turboPlugin, }, rules: { "turbo/no-undeclared-env-vars": "off", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": [ "error", { args: "all", argsIgnorePattern: "^_", caughtErrors: "all", caughtErrorsIgnorePattern: "^_", destructuredArrayIgnorePattern: "^_", varsIgnorePattern: "^_", ignoreRestSiblings: true, }, ], }, }, { plugins: { onlyWarn, }, }, { ignores: ["dist/**"], },];// esLintConfig ํจํค์ง์ nextjs.eslint.jsexport const nextJsConfig = [ ...baseConfig, js.configs.recommended, eslintConfigPrettier, ...tseslint.configs.recommended, { ...pluginReact.configs.flat.recommended, languageOptions: { ...pluginReact.configs.flat.recommended.languageOptions, globals: { ...globals.serviceworker, }, }, }, { plugins: { "@next/next": pluginNext, }, rules: { ...pluginNext.configs.recommended.rules, ...pluginNext.configs["core-web-vitals"].rules, // ์ปค์คํ
ํฐํธ ํ์ฉ "@next/next/no-page-custom-font": "off", }, }, { plugins: { "react-hooks": pluginReactHooks, }, settings: {react: {version: "detect"}}, rules: { ...pluginReactHooks.configs.recommended.rules, // React scope no longer necessary with new JSX transform. "react/react-in-jsx-scope": "off", }, },];turborepo์์๋ internal packages์ ์ปดํ์ผ ์ ๋ต์ ํฌ๊ฒ 3๊ฐ์ง๋ก ๋๋ด์ต๋๋ค. ์ปดํ์ผํ์ง์๋ Just-in-Time Packages์, ts compileํ๋ Compiled Packages, NPM์ ์ฌ๋ฆฌ๋ Publishable Packages์ ๋๋ค.
Just-in-Time ํจํค์ง๋ ์ต์ํ์ ์ค์ ๋ง ํ์ํ ๋ฐฉ์์ ๋๋ค. ์๋ํ๋ฉด ํจํค์ง์์ ๋ฐ๋ก ๋น๋๋ฅผ ํ์ง ์๊ณ App์ ์ปดํ์ผ๋ฌ์ ๋ฒ๋ค๋ฌ๋ก ํจ๊ป ๋น๋๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฆ ์ปดํ์ผ๊ณผ ๋ฒ๋ค๋ง ์ค์ ์ด App ์ค์ ์ ์ํฅ์ ๋ฐ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฐ๋ก ์ปดํ์ผ ํ์ง ์์๋, ts ํ์ผ์ ๋ณด๊ณ ๋ฐ๋ก ํ์ ์ถ๋ก ์ด ๋ฉ๋๋ค.
์ฅ์
๋ฐ๋ก Typescript๋ฅผ exportํ์ฌ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, app์์๋ ํจํค์ง์ tsํ์ผ์ ๋ฐ๋ก ์ฐธ์กฐํ์ฌ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋์ ํจํค์ง ํ์ผ์ ์์ ํ๋ฉด ๋ณ๊ฒฝ ์ฌํญ์ด ๋ฐ๋ก ๋ฐ์๋์ด ํ์ ์ถ๋ก ์ด ๋ฉ๋๋ค.
app์์ ํจํค์ง๋ฅผ ๋ฐ๋ก ์ง์ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ๋ณ๋์ build ์คํฌ๋ฆฝํธ๋ ์ค์ ์ด ํ์์์ต๋๋ค.
๋จ์ /ํ๊ณ
tsํ์ผ ์ง์ ์ฐธ์กฐ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ consumer(์ฃผ๋ก app)๊ฐ ts๋ฅผ ์ดํดํ ์ ์์ด์ผ ํ๊ณ , ๋น๋ํ ์ ์์ด์ผ ํฉ๋๋ค. ๋ง์ฝ app์ด js๋ง ์ฌ์ฉํ ์ ์๋ค๋ฉด, complied packages ๋ฐฉ์์ผ๋ก ๋ฐ๊ฟ์ผํฉ๋๋ค.
ํจํค์ง๋ tsconfig์์ path alias๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ํ๋ฉด typescript๋ ์ฝ๋๋ฅผ ์์ฑํ ํจํค์ง ์์์ ํธ๋์คํ์ผํ ๊ฒ์ผ๋ก ์๊ฐํ๊ธฐ ๋๋ฌธ์ path alias๋ฅผ ๋ณ๋๋ก ์ธ์ํ ์ ์์ต๋๋ค. ๊ทธ๋์ path alias๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด nodeJs์ subPath ๊ธฐ๋ฅ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
turborepo์์ package์ ๋น๋ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ์ง ๋ชปํ๋ ๋จ์ ์ด ์์ต๋๋ค. ์๋ํ๋ฉด package๋ฅผ ๋ฐ๋ก ๋น๋๋ฅผ ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ๋์ package๊ฐ ๋ฐ๋๋ฉด, app๋ ๋ค์ ๋น๋ํด์ผ ํฉ๋๋ค.
ํจํค์ง๋ฅผ ts ๊ทธ๋๋ก ์ฐ๊ธฐ ๋๋ฌธ์ ํ์ ์๋ฌ๊ฐ ์์ผ๋ฉด, app์์๋ ๊ตณ์ด ๋ชฐ๋ผ๋ ๋ ํ์ ์๋ฌ๋ฅผ ์์์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ธธ ์ ์์ต๋๋ค.
Compiled ํจํค์ง๋ tsํ์ผ์ js์ d.ts ํ์ผ๋ก ์ปดํ์ผํ์ฌ ์ฌ์ฉํ๋ ํจํค์ง์ ๋๋ค. ๋ณดํต /dist ํด๋์ ์ปดํ์ผ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ์ฌ, ์ง์ ์ (entry point)๋ก ์ค์ ํ์ฌ ์ฌ์ฉํฉ๋๋ค. ์ปดํ์ผํ๊ธฐ ๋๋ฌธ์ turborepo์ ๋น๋ ์บ์ฑ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์์ต๋๋ค. ๊ทธ๋์ app์ด๋ package ๋ชจ๋ ๋น๋ ์ ๋ ๋น ๋ฅด๊ฒ ๋น๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ฅ์
turborepo์ ๋น๋ ์บ์ฑ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์์ต๋๋ค.
๋จ์ /ํ๊ณ
๋ณดํต tsc๋ก ์ปดํ์ผ ์ฒ๋ฆฌ๋ง ํฉ๋๋ค. ์๋ํ๋ฉด app์ bundler๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ์ง๋ง ๊ฐ๋ ์ ์ ํ์ผ์ package์์ ์ฌ์ฉํ๋ค๋ฉด ๋ณ๋์ ๋ฒ๋ค๋ง ์์ ์ด ํ์ํ ์ ์์ต๋๋ค.
Just-in-Time ํจํค์ง๋ณด๋ค ์ค์ ์ด ๋ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค๋ฉด ํด๋ฆฌํ ์์ ์ด ํ์ํ ํจํค์ง๋ผ๋ฉด package.json์ sideEffect ์์ฑ์ ์ถ๊ฐํด์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
Publishable ํจํค์ง๋ NPM ์ ์ฅ์์ ์ฌ๋ ค์ ์ฌ์ฉํ๋ ํจํค์ง ์ ๋๋ค. ๊ทธ๋์ ๋ณ๋์ builder๋ก ๋น๋ํ ์ ์์ด์ผ ํฉ๋๋ค. ๊ทธ๋์ compile๊ณผ bundle์ ์ฑ ์์ด ํจํค์ง์๊ฒ ์์ต๋๋ค. ๊ฐ์ฅ ๊ฒฌ๊ณ ํ๊ฒ ํจํค์ง๋ฅผ ๋ง๋๋ ๋ฐฉ์์ ๋๋ค. app์ npm registry๋ฅผ ํตํด ํจํค์ง๋ฅผ ๋ค์ด๋ฐ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ๋ฉ๋๋ค.
ํด๋๊ตฌ์กฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉํ๋ ๊ตฌ์กฐ(Layered Architecture)๋ฅผ ์ฌ์ฉํ์ต๋๋ค. NextJS ์ฑ์ FSD์๋ ์ด์ธ๋ฆด ๊ฒ ๊ฐ์ FSD ์ํคํ ์ฒ๋ฅผ ์๊ฐํด ๋ดค๋๋ฐ ์๋ก ๋์ ํ๋ ๊ฒ์ด ๋๋ฌด ๋ง์์ ๊ณ ์ด ์ ์ด๋์ต๋๋ค. ์ผ๋ถ ์ฑ๊ณผ ํจํค์ง์ ํด๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด ๋ดค์ต๋๋ค.
โโ blog โโ src โ โโ app โ โ ... โ โ โโ layout.ts โ โ โโ page.ts โ โ โโ action.ts โ โ โโ error.ts โ โ โโ loading.ts โ โ โโ robots.ts โ โ โโ sitemap.ts โ โโ components โ โ โโ client โ โ โโ server โ โโ provider โโ after_build.js โโ eslint.config.js โโ tsconfig.json โโ postcss.config.js โโ next.config.ts โโ package.jsonโโ design-system โโ src โ โโ globals.css โ โโ palette.css โ โโ components โ โ ... โ โ โโ Backdrop โ โ โโ BentoCard โ โโ motion โโ eslint.config.js โโ tsconfig.json โโ postcss.config.js โโ vite.config.ts โโ package.jsonโโ editor โโ src โ โโ extensions โ โโ hooks โ โโ plugins โ โโ utils โโ eslint.config.js โโ tsconfig.json โโ vite.config.ts โโ package.jsonhttps://turbo.build/blog/you-might-not-need-typescript-project-references