DEV

[React/React-native] Workspace

음대생개발자 2024. 11. 30. 16:06

Workspace

 

 

정의

workspace는 여러 패키지를 하나의 프로젝트에서 효율적으로 관리하기 위한 설정을 말한다. 

 

특징

  • workspace로 사용되는 패키지를 node_modules에 설치하여 관리한다. 
  • 공통되는 의존성과 설정 등이 프로젝트 Root에서부터 공유된다. 
    • Hoisting: 공통 의존성을 루트 수준에서 관리하여, 중복 설치를 줄이고 일관성을 유지한다.
    • 개별 관리: 개별 패키지에서만 가지고 있는 의존성은 패키지 내부에서만 독립적으로 관리한다.
  • 즉, 프로젝트 Root에서 npm 설치 시 공통의 모듈을 설치하며, 패키지 내부에서 독립적으로 필요한 모듈은 각 내부의 패키지에서 개별적으로 모듈을 설치한다.
// 폴더 구조
├── node_modules
│   ├── package1
│   ├── package2
│   ├── package3
├── package-lock.json
├── package.json
├── modules
   ├── package 1
   │   ├── node_modules
   │   ├── package.json
   ├── package 2
   │   ├── package.json
   ├── package 3
   │   ├── package.json
   ...
├── src
  • 서로 다른 패키지 간의 참조도 가능하다. (패키지 간의 종속성 설정 가능)
// 예시 (package.json)
{
  "dependencies": {
    "ct-library-credential": "workspace:*", // 버전을 신경 쓰지 않고 워크스페이스 내부의 패키지를 사용
    "ct-library-http-client": "workspace:1.0.0" // 워크스페이스 내부 패키지의 특정 버전을 사용 
  }
}
  • workspace 사용시 자동으로 symbolic link (npm link)가 연결된다.
    • symbolic link : node_modules 에 설치된 workspace의 패키지는 기존의 패키지가 존재하는 경로를 참조하여 node_modules에서 연결된다.
    • 기존 패키지와 연결됨에 따라 패키지의 변경사항이 실시간으로 반영된다.

 

사용 목적

1. 각 패키지의 버전 관리 : 각 패키지의 종속성 버전을 자동으로 추적, 업데이트 가능

2. 공통 의존성 관리: 중복 설치를 줄임으로써 의존성 설치 및 빌드의 효율성 증가

3. 공통 설정 관리: 린트, 테스트, 빌드 스크립트 등을 중앙화 해 통합된 개발 환경 제공

 

 

생성 방법

1. 프로젝트 Root 설정

  • 프로젝트에서 workspace로 사용하려고 하는 패키지의 경로를  Root의 package.json, workspace 속성에 추가
// package.json
{
	"name" : "YOUR_PROJECT_NAME",
    "version" : "1.0.0",
    ...
    "workspace" : ["modules/package1", "modules/package2"] // "modules/*"
}

 

2. Typescript, ESlint 등 사용시 config 설정

  • workspace 패키지 안에서 Root의 config 파일을 바라보기 때문에 ts, lint 등의 설정이 있는 경우에 충돌이 일어날 수 있다. 
  • 해당 패키지 안의 config 파일에서 추가 설정이 필요
    • extends : 기본 설정을 공유
    • 기본 설정을 공유 및 상속하면서 패키지 별 커스터마이징 가능
// typescript 
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "dist",        // 빌드 결과 경로
    "baseUrl": "./src",      // 경로 설정
    "strict": false          // 패키지별 개별 설정 덮어쓰기
  },
  "include": ["src/**/*"]    // 포함 파일
}
// eslint 설정도 동일
{
  "extends": "../../.eslintrc", // 루트 설정 상속
}

** React 추가 설정 : Babel-loader

React는 webpack에서 src 외부 경로를 기본적으로 읽지 못하므로, workspace 모듈 지원을 위한 추가 설정이 필요하다.

 

1. Webpack 설정 적용: 커스터마이징 된 설정을 덮어씌우기 위해 react-app-rewired 라이브러리 설치

npm install react-app-rewired

 

2. config-overrides.js 파일 추가

module.exports = function override(config, env) {
	...
	// src 외부 workspace 모듈 지원
  config.module.rules.push({
    test: /\.(js|jsx|ts|tsx)$/,
    include: [
      path.resolve(__dirname, "modules/package1"), // workspace 모듈 경로 (필요에 따라 수정)
       path.resolve(__dirname, "modules/package2"),
    ],
    loader: require.resolve("babel-loader"),
    options: {
      presets: ["react-app"],
      plugins: ["react-refresh/babel"],
    },
  });
  config.resolve.symlinks = true;
  return config
}

 

3. Script 수정

// package.json 
 "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
}

 

 

** React-native 추가 설정 : Metro bundler

React native가 사용하는 Metro 번들러는 심볼릭 링크를 기본적으로 지원하지 않기 때문에, 종종 workspace 모듈을 읽지 못해 추가 설정이 필요하다.

// metro.config.js
const path = require('path');
const { getDefaultConfig } = require('@react-native/metro-config');

const workspaceRoot = path.resolve(__dirname, 'module/package1');
const projectRoot = __dirname;

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */

const config = getDefaultConfig(projectRoot);
// 1. Watch all files within the monorepo
config.watchFolders = [workspaceRoot];
// 2. Let Metro know where to resolve packages, and in what order
config.resolver.nodeModulesPaths = [
    path.resolve(projectRoot, 'node_modules'),
    path.resolve(workspaceRoot, 'node_modules'),
];
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
config.resolver.disableHierarchicalLookup = true;

module.exports = config;

 

 

 

 

 

 


 

 

 

 

회사에서는 다른 레포에서 관리하는 패키지들을 서브모듈로서 관리하였는데,

그 때는 작업자마다 서브모듈 버전이 다른 경우가 생기기도 했었고 업데이트 되었는지도 잘 파악이 안되었다.

workspace를 사용하면서 버전에 종속성을 걸면, 이런 문제점들은 없어질 수 있어서 관리하기 편해질 것 같다.