1. 실습

1. 모노레포 구축

  1. 루트의 package.json 생성

    1. yarn init -y

      {
        "name": "gloddy",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "private": true,
        "workspaces": {
          "packages": [
            "packages/*"
          ],
          "nohoist": [
            "/packages/app/**"
          ]
        },
        "packageManager": "[email protected]",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1",
          "web": "yarn workspace @gloddy/web",
          "app": "yarn workspace @gloddy/app"
        },
        "devDependencies": {
          "husky": "^9.0.7"
        }
      }
      

      루트의 package.json은 workspace에서 공통으로 사용할 모듈을 관리한다. 현재, husky만 설치되어 있으며, prettier, typescript같은 공통으로 사용할 모듈을 추가할 것이다.

  2. .gitignore 추가

2. Next.js 패키지

  1. packages/web으로 폴더 묶기

  2. package.json의 name 수정

    {
    	"name":"@gloddy/web"
    }
    

    여기서 name은 모노레포의 다른 패키지에서 접근할 때 사용할 이름이다.

3. React Native 패키지

  1. packages/app으로 폴더 묶기

  2. package.json 수정

    {
    	"name":"@gloddy/app"
    }
    
  3. no-hoist 설정

    모듈을 hoist할 경우, 루트에 모듈이 설치된다. 그래서 ios, android의 네이티브 코드에서 직접 경로를수정해야 한다. 이러한 과정을 하지 않기 위해서는 no-hoist설정을 통해 루트가 아닌, react-native 폴더에 모듈을 설치하도록 할 수 있다.

    // packages/app/package.json
    {
    	// ..
    	"nohoist":[
    		"/packages/app/**"
    	]
    }
    
  4. yarn berry가 아닌, yarn classic 설정

    기존 React Native에서 사용하던 패키지 관리자는 npm이었다. yarn berry의 PNP로 마이그레이션을 할 경우 의존성 문제를 마주할 것을 생각해, 우선 yarn으로 마이그레이션만 하기로 결정했다. 나중에 순차적으로 yarn berry의 pnp로 마이그레이션을 할 예정이다.

    모노레포의 전체적인 패키지 매니저는 yarn berry이므로, react-native패키지에 한해서 yarn classic으로 설정할 것이다.

    // packages/app/package.json
    {
    	// ..
    	"packgeManager" : "[email protected]",
    }
    
    // packages/app/.yarnrc.yml
    nodeLinker:node-modules
    
    // .yarnignore
    packages/app/**
    

4. typescript, eslint, prettier 설정

1. typescript 설정

tsconfig는 루트에서 base를 설정하고, 각 패키지에서 상속받아 설정한다.

  1. typescript는 루트와 각 패키지에서 설치한다. 루트의 tsconfig에서 공통된 tsconfig를 설정하고, 각 패키지에서 루트의 tsconfig를 상속받아 설정할 수 있다.

    // tsconfig.json
    {
      "compilerOptions": {
        "allowSyntheticDefaultImports": true,
        "moduleResolution": "Node",
        "resolveJsonModule": true,
        "esModuleInterop": true,
        "strict": true,
        "target": "es5",
        "lib": ["ES5", "ES6", "ESNext", "DOM"],
        "skipLibCheck": true,
        "baseUrl": ".",
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "isolatedModules": true
      },
      "exclude": ["packages/**/dist/**"]
    }
    
    // packages/web/tsconfig.json, packages/app/tsconfig.json
    {
    	"extends":"../../tsconfig.json",
      // ..
    }