1. 패키지와 모듈 시스템
Node.js는 확장성 있는 네트워크 애플리케이션을 구축하기 위한 JavaScript 런타임 환경이다.
Node.js의 강점 중 하나는 넓은 패키지 생태계로, 수많은 라이브러리를 쉽게 활용할 수 있다.
1.1. 패키지와 모듈의 차이점
패키지(Package)란 package.json 파일과 이 파일에 정의된 파일 또는 디렉터리의 집합이다.
패키지는 재사용 가능한 코드의 단위로, 다른 프로젝트에서 사용할 수 있도록 설계되었다.
모듈(Module)은 node_modules 디렉터리 아래에 있는 파일 또는 디렉터리로, require() 또는 import 구문을 통해 로드할 수 있는 코드 단위이다.
모든 패키지는 모듈이 될 수 있지만, 모든 모듈이 패키지인 것은 아니다.
패키지 ⊂ 모듈
1.2. Node.js의 모듈 시스템
Node.js는 CommonJS 모듈 시스템을 기반으로 하며, ES 모듈 시스템도 지원한다.
1) CommonJS 방식:
// math.js (모듈 정의)
function add(a, b) {
return a + b;
}
module.exports = { add };
// app.js (모듈 사용)
const math = require('./math');
console.log(math.add(2, 3)); // 5
2) ES 모듈 방식:
// math.js (모듈 정의)
export function add(a, b) {
return a + b;
}
// app.js (모듈 사용)
import { add } from './math';
console.log(add(2, 3)); // 5
ES 모듈을 사용하려면 package.json에 "type": "module" 필드를 추가하거나 파일 확장자를 .mjs로 지정해야 한다.
2. NPM(Node Package Manager)
2.1. NPM이란?
NPM은 자바스크립트 프로그래밍 언어를 위한 패키지 관리자이다.
Node.js 설치 시 함께 제공되며, 자바스크립트 패키지를 설치, 공유, 배포하는 데 사용된다.
1) 웹사이트(npmjs.com): 패키지 검색 및 정보 제공
2) CLI(Command Line Interface): 터미널에서 패키지 관리
3) 레지스트리: 패키지 메타데이터와 배포 파일 저장소
2.2. 주요 NPM 명령어
1) 패키지 초기화:
npm init
2) 패키지 설치:
npm install [패키지명] # 로컬 설치
npm install -g [패키지명] # 전역 설치
npm install [패키지명] --save-dev # 개발 의존성으로 설치
3) 패키지 제거:
npm uninstall [패키지명]
4) 패키지 업데이트:
npm update [패키지명]
5) 스크립트 실행:
npm run [스크립트명]
2.3. package.json
package.json은 Node.js 프로젝트의 메타데이터를 담고 있는 파일이다.
프로젝트 구성, 의존성, 스크립트 등 다양한 정보를 JSON 형식으로 정의한다.
ex)
{
"name": "my-project", // 프로젝트 이름
"version": "1.0.0", // 버전 (semver 형식)
"description": "", // 프로젝트 설명
"main": "index.js", // 진입점 파일
"scripts": { // 실행 스크립트
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"dependencies": { // 프로덕션 의존성
"express": "^4.18.2"
},
"devDependencies": { // 개발 의존성
"nodemon": "^2.0.22"
},
"keywords": [], // 검색 키워드
"author": "", // 작성자
"license": "ISC" // 라이선스
}
3. 패키지 잠금과 의존성 관리
3.1. package-lock.json
package-lock.json은 설치된 패키지의 정확한 버전과 의존성 트리를 기록하는 파일이다.
목적:
1) 정확한 의존성 트리 유지
2) 일관된 설치 보장
3) 종속성 충돌 예방
npm install 명령을 실행하면 자동으로 생성 또는 업데이트된다.
ex)
{
"name": "my-project",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "my-project",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.2"
}
},
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-3OHGXZ...",
"dependencies": {
"accepts": "~1.3.8",
"body-parser": "1.20.1",
// ... 더 많은 의존성
}
}
// ... 전체 의존성 트리
}
}
3.2. 의존성 버전 관리
NPM은 Semantic Versioning(SemVer)을 사용하여 패키지 버전을 관리한다.
SemVer는 주(Major).부(Minor).수(Patch) 형식으로 구성된다.
- 주 버전: 호환되지 않는 API 변경
- 부 버전: 하위 호환되는 기능 추가
- 수 버전: 하위 호환되는 버그 수정
버전 범위 지정 기호:
- ^: 호환되는 최신 버전(주 버전 고정)
- 예: ^1.2.3 → 1.x.x (1.2.3 이상, 2.0.0 미만)
- ~: 근사한 버전(주.부 버전 고정)
- 예: ~1.2.3 → 1.2.x (1.2.3 이상, 1.3.0 미만)
- >, >=, <, <=: 특정 버전 이상/이하
- * 또는 x: 모든 버전
- 1.2.3 - 2.3.4: 범위 지정
다만, 이 버전을 엄격하게 지키지 않는 패키지도 있다는 것을 유의해야한다.
3.3. peerDependencies
peerDependencies는 해당 패키지가 호스트 패키지의 특정 의존성에 의존하는 것을 명시한다.
주로 플러그인이나 확장 모듈에서 사용되며, 호환성을 보장하기 위해 필요하다.
{
"name": "my-plugin",
"version": "1.0.0",
"peerDependencies": {
"react": "^18.0.0"
}
}
4. 간이 패키지 만들기
개인적으로 간단한 패키지를 만들어 보는 것이 전체적인 구조를 이해하는데에 도움이 됐다.
여기서는 덧셈 기능만 있는 간단한 패키지를 만들어 보겠다.
4.1. 프로젝트 초기화
먼저 새 디렉터리를 만들고 프로젝트를 초기화한다
mkdir sample-package
cd sample-package
npm init -y
4.2. 패키지 구조 설계
sample-package/
├── index.js # 메인 진입점
├── src/ # 소스 코드
│ └── operations.js
├── README.md # 문서
├── package.json # 패키지 메타데이터
└── .gitignore # Git 무시 파일
4.3. 구현
src/operations.js:
/**
* 두 수의 합을 반환한다.
* @param {number} a 첫 번째 숫자
* @param {number} b 두 번째 숫자
* @returns {number} 두 수의 합
*/
function add(a, b) {
return a + b;
}
module.exports = {
add,
};
index.js:
const operations = require('./src/operations');
// 직접 내보내기
module.exports = operations;
// 또는 다음과 같이 개별적으로 내보낼 수도 있음:
// module.exports = {
// add: operations.add,
// };
package.json:
{
"name": "sample-package",
"version": "1.0.0",
"description": "간단한 패키지",
"main": "index.js",
"scripts": {
"test": "node test/test.js"
},
"keywords": ["math", "calculator", "operations"],
"author": "Mumu",
"license": "MIT"
}
4.4. 문서 작성
README.md:
# Sample Package
간단한 덧셈 연산을 제공하는 JavaScript 패키지입니다.
## 설치
```bash
npm install sample-package
사용 예시:
const sample = require('sample-package');
// 덧셈
console.log(sample.add(2, 3)); // 5
4.5. 로컬에서 패키지 사용
패키지를 로컬에서 테스트하기 위해 npm link를 사용할 수 있다.
# 패키지 디렉터리에서
npm link
# 다른 프로젝트에서
npm link sample-package
또는 로컬 경로를 직접 지정하여 설치할 수도 있다.
# 다른 프로젝트에서
npm install /path/to/sample-package
4.6. npm 레지스트리 배포
1) npm 계정 생성 및 로그인
2) npm adduser # 계정이 없는 경우 npm login # 이미 계정이 있는 경우
3) 배포
4) npm publish
비공개 패키지로 배포하려면 패키지 이름을 스코프로 지정한다.
{
"name": "@username/sample-package",
"version": "1.0.0",
...
}