개요
모노레포에서 여러 모듈들의 의존성을 연결할 때, Symlink를 활용하게 됩니다. 이번 블로그 포스트에서는 모노레포를 이해하기 위한 기본 지식인 Symlink(Symbolic Link)에 대해서 알아보도록 하겠습니다.
블로그 시리즈
이 블로그는 시리즈로 제작되었습니다. 다음 링크를 통해 다른 블로그 포스트도 확인해 보시기 바랍니다.
- [프로젝트 관리] 리포지토리 전략
- [JavaScript] 모노레포(Monorepo)를 위한 도구들
- [Monorepo] NodeJS의 모듈 불러오기
- [Monorepo] Symlink
- [Monorepo] Yarn Workspaces
- [Monorepo] Yarn Workspaces의 Hoisting
- [Monorepo] Yarn Workspaces의 명령어
- [Monorepo] pnpm을 사용하여 모노레포 만들기
Symlink
Symlink는 Symbolic Link의 줄임말로, 파일 또는 디렉토리에 대한 바로가기(System shortcut)라고 생각하시면 됩니다.
Symlink는 주요 OS(macOS, Windows, Linux)에서 지원하는 기본 기능입니다. 또한 NodeJS의 패키지 매니저인 npm과 yarn에서도 지원하고 있습니다.
예제
npm과 yarn이 제공하는 Symlink 기능을 확인하기 위한 예제를 만들어 봅시다. 우선, 다음과 같이 폴더와 파일 구조를 생성합니다.
.
└── src/
├── module-a/
│ ├── index.js
│ └── package.json
└── module-b/
├── index.js
└── package.json
module-a의 package.json은 다음과 같습니다.
// src/module-a/package.json
{
"name": "module-a",
"version": "1.0.0",
"main": "index.js"
}
module-b의 package.json은 다음과 같습니다.
// src/module-b/package.json
{
"name": "module-b",
"version": "1.0.0",
"main": "index.js"
}
그리고 module-b의 index.js는 다음과 같습니다.
// src/module-b/index.js
console.log('module-b');
마지막으로 module-a의 index.js는 다음과 같습니다.
// src/module-a/index.js
console.log('module-a');
require('module-b');
이렇게 파일을 구성한 후, 다음 명령어를 실행하여 모듈을 잘 불러오는지 확인합니다.
node src/module-a/index.js
그럼 다음과 같이 에러가 발생하는 것을 확인할 수 있습니다.
module-a
node:internal/modules/cjs/loader:1073
throw err;
^
Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
at Module._load (node:internal/modules/cjs/loader:923:27)
at Module.require (node:internal/modules/cjs/loader:1137:19)
at require (node:internal/modules/helpers:121:18)
at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
at Module._compile (node:internal/modules/cjs/loader:1255:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
at Module.load (node:internal/modules/cjs/loader:1113:32)
at Module._load (node:internal/modules/cjs/loader:960:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}
Symlink 생성
Symlink 기능을 확인하기 위해 module-b 폴더로 이동합니다.
cd src/module-b
이동한 후, 다음 명령어를 실행하여 Symlink를 사용할 준비를 합니다.
npm link
# yarn link
이후, module-b를 사용하는 module-a 폴더로 이동합니다.
cd ..
cd module-a
module-a 폴더로 이동하였다면, 다음 명령어를 사용하여 module-b에 대한 Symlink를 생성합니다.
npm link module-b
이렇게 link 명령어를 실행하면 다음과 같이 module-a 폴더의 node_modules 폴더가 생성되고 modules-b의 Symlink가 생성된 것을 확인할 수 있습니다.
.
├── index.js
├── node_modules
│ └── module-b -> ../../module-b
└── package.json
이 Symlink 폴더는 module-b를 복사한 것이 아니라 module-b 자체와 연동이 되어 있습니다. 따라서 src/module-b/index.js 파일을 수정하면 src/module-a/node_modules/module-b/index.js 파일도 같이 수정이 되며, 반대로 src/module-a/node_modules/module-b/index.js 파일을 수정하면 src/module-b/index.js 파일도 같이 수정이 됩니다.
Symlink 확인
이제 프로젝트의 루트 폴더(/)로 이동한 후, 다음 명령어를 실행하여 모듈을 잘 불러오는지 확인합니다.
# cd ../..
node src/module-a/index.js
그럼 다음과 같이 문제없이 잘 실행되는 것을 확인할 수 있습니다.
module-a
module-b
이제 src/module-b/index.js 파일 내용을 다음과 같이 수정합니다.
console.log('module-b!!!!');
수정후, src/module-a/node_modules/module-b/index.js 파일을 열어보면 위에서 수정한 내용이 반영되어 있는 것을 확인할 수 있습니다. 물론, 다음 명령어를 실행하면, 변경된 내용이 잘 출력되는 것을 확인할 수 있습니다.
node src/module-a/index.js
module-a
module-b!!!!
완료
이것으로 모노레포를 사용하기 위한 기초 지식인 Symlink에 대해서 알아보았습니다. 모노레포에서 여러 모듈들의 의존성을 연결할 때, Symlink를 활용하므로 이번 블로그 포스트를 통해 Symlink를 이해해 두면 모노레포를 사용하는데 도움이 될 것입니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku가 개발한 앱을 한번 사용해보세요.Deku가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.














![[심통]현장에서 바로 써먹는 리액트 with 타입스크립트 : 리액트와 스토리북으로 배우는 컴포넌트 주도 개발, 심통](https://img1c.coupangcdn.com/image/affiliate/banner/7cba8cb0601eebaf88a17a0c3cf65a63@2x.jpg)