$ yh.log
[스터디] npm deep dive - 7장 직접 자바스크립트 패키지 만들기

[스터디] npm deep dive - 7장 직접 자바스크립트 패키지 만들기

npm패키지CLIChangesetscommander.js배럴파일

작성자 : 오예환 | 작성일 : 2026-03-11 | 수정일 : 2026-03-11 | 조회수 :

현재까지 학습 내용

주제설명
패키지 관리자npm, pnpm, yarn 등의 패키지 관리자
모듈 시스템CommonJS, ESM 등 모듈 시스템의 개념 이해
트랜스파일링최신 문법을 구버전으로 변환
폴리필구형 환경에서 최신 기능 지원
번들링 도구Webpack, Rollup, esbuild 등

이론적 기반을 바탕으로 직접 JS 패키지 만들기

패키지 개발은 다음과 같은 단계로 진행된다.

  1. 문제 정의 - 해결하고자 하는 문제를 명확히 정의하고 목표 설정
  2. 프로젝트 구조 설계 - 확장성과 유지보수성을 고려한 디렉토리 구조 설계
  3. 개발 환경 구성 - 생산적인 개발을 위한 도구 및 환경 준비
  4. 코드 작성 및 테스트 - 철저한 테스트를 통해 신뢰성 보장
  5. 문서화 - 협업자와 사용자가 이해할 수 있도록 문서 작성

패키지 개발을 위한 체크리스트

1. 아이디어 검증 및 기술적 타당성 검토

  • 어떤 기능을 제공할 것인가?
  • 해당 기능이 실제로 구현 가능한가?
  • 기존 솔루션과 어떤 차별점을 제공하는가?

2. 라이선스 선택

라이선스특징
MIT가장 자유로운 라이선스, 상업적 사용 가능
Apache 2.0특허권 명시, 기업 친화적
GPL파생 작업물도 오픈소스로 공개 필요
ISCMIT와 유사, npm 기본 라이선스

3. 적절한 이름 고르기

  • npm에서 이미 사용 중인지 확인 (npm search <name>)
  • 기억하기 쉽고 패키지의 목적을 반영하는 이름 선택
  • 스코프 패키지 고려 (@username/package-name)

4. 지원 환경

모든 환경에서 동작할 필요는 없다. 타겟 환경을 명확히 정의하자.

  • Node.js only: 서버 사이드 전용
  • Browser only: 클라이언트 사이드 전용
  • Universal: 양쪽 모두 지원

5. 개발 환경 및 프로젝트 구조

  • 코드 작성, 빌드, 번들링에 사용할 도구 선택
  • 어떤 기술 스택을 사용할 것인가?
  • 중요: 선택한 도구들이 서로 호환 가능한지 반드시 검토!

6. 의존성 관리 계획

유형용도예시
dependencies런타임에 필요한 패키지lodash, axios
devDependencies개발/빌드 시에만 필요typescript, jest
peerDependencies호스트 프로젝트가 제공해야 함react, vue

7. CI/CD 설정

  • 자동화된 테스트, 린팅, 타입 체크가 포함된 CI 파이프라인 구성
  • 배포를 수시로 안정적으로 진행할 수 있는 시스템 마련
  • GitHub Actions, CircleCI, Travis CI 등 활용

배럴 파일 (Barrel File)

정의

배럴 파일은 여러 모듈을 하나의 파일로 묶어서 다시 내보내는 파일이다. 모듈이 많은 대규모 프로젝트나 패키지에서 특정 모듈을 가져오는 것을 용이하게 할 목적으로 만들어졌다.

// src/index.js (배럴 파일)
export { Button } from './components/Button';
export { Input } from './components/Input';
export { Modal } from './components/Modal';
export { useForm } from './hooks/useForm';

장점과 단점

구분내용
장점어디서 만들어졌는지 몰라도 최초 진입점에서 깔끔하게 import 가능
장점API 표면을 명확하게 정의할 수 있음
단점변수명 충돌 발생 시 파일 자체 사용 불가
단점모듈의 출처 파악이 어려움
단점Tree-shaking이 제대로 작동하지 않을 수 있음

Changesets를 활용한 배포

Changesets는 모노레포 및 일반 프로젝트에서 버전 관리와 변경 로그 생성을 자동화하는 도구이다.

설정 단계

1. changeset-bot 설치

GitHub Marketplace에서 changeset-bot을 설치하여 PR에 changeset 추가 여부를 자동으로 체크한다.

2. npm 토큰 발급

npm 계정에서 Automation 타입의 토큰을 발급받는다.

3. npm 토큰을 저장소에 저장

Settings → Secrets and variables → Actions → New repository secret

NPM_TOKEN이라는 이름으로 토큰을 저장한다.

4. 저장소에 changesets 설정

# @changesets/cli 설치
pnpm add -D @changesets/cli
 
# 초기화
pnpm changeset init

5. GitHub Actions 권한 설정

Settings → Actions → General → Workflow permissions

Read and write permissions로 설정한다.

Changeset 작성 시 입력 내용

PR에서 "Click here if you're a maintainer who wants to add another changeset to this PR"을 클릭하면 마크다운 파일을 작성할 수 있다.

항목설명
버전업 유형patch (기본값), minor (기능 추가), major (Breaking Change)
변경 내용CHANGELOG.md에 추가될 내용이므로 자세하게 작성

CLI를 만드는 데 유용한 패키지

인자/명령어 파싱

commander.js

가장 널리 사용되는 CLI 프레임워크. 명령어, 옵션, 인자를 쉽게 정의할 수 있다.

import { program } from 'commander';
 
program
  .name('my-cli')
  .version('1.0.0')
  .description('My awesome CLI tool');
 
program
  .command('init <name>')
  .description('Initialize a new project')
  .option('-t, --template <type>', 'Template type', 'default')
  .action((name, options) => {
    console.log(`Creating project: ${name} with template: ${options.template}`);
  });
 
program.parse();

meow

Sindre Sorhus가 만든 경량 CLI 헬퍼. 간단한 CLI를 빠르게 만들 때 유용하다.

import meow from 'meow';
 
const cli = meow(`
  Usage
    $ my-cli <input>
 
  Options
    --rainbow, -r  Include a rainbow
 
  Examples
    $ my-cli unicorns --rainbow
`, {
  importMeta: import.meta,
  flags: {
    rainbow: {
      type: 'boolean',
      shortFlag: 'r'
    }
  }
});
 
console.log(cli.input);  // ['unicorns']
console.log(cli.flags);  // { rainbow: true }

대화형 프롬프트

Inquirer.js

사용자와 대화형으로 입력을 받을 수 있는 라이브러리. 다양한 질문 유형을 지원한다.

import inquirer from 'inquirer';
 
const answers = await inquirer.prompt([
  {
    type: 'input',
    name: 'projectName',
    message: 'What is your project name?',
    default: 'my-project'
  },
  {
    type: 'list',
    name: 'language',
    message: 'Which language do you want to use?',
    choices: ['JavaScript', 'TypeScript']
  },
  {
    type: 'confirm',
    name: 'useEslint',
    message: 'Do you want to use ESLint?',
    default: true
  }
]);
 
console.log(answers);
// { projectName: 'my-app', language: 'TypeScript', useEslint: true }

터미널 스타일링

chalk

터미널 출력에 색상과 스타일을 적용하는 라이브러리.

import chalk from 'chalk';
 
console.log(chalk.blue('Info: ') + 'Processing files...');
console.log(chalk.green('Success: ') + 'Build completed!');
console.log(chalk.red('Error: ') + 'Something went wrong');
console.log(chalk.yellow.bold('Warning: ') + 'Deprecated API used');
 
// 중첩 스타일
console.log(chalk.blue.bgWhite.bold(' INFO ') + ' Starting server...');

ora

우아한 터미널 스피너(로딩 표시)를 제공하는 라이브러리.

import ora from 'ora';
 
const spinner = ora('Loading dependencies...').start();
 
// 작업 수행
await installDependencies();
 
spinner.succeed('Dependencies installed');
// 또는
spinner.fail('Failed to install dependencies');
// 또는
spinner.warn('Some dependencies have vulnerabilities');

패키지 비교 요약

패키지용도특징
commander.js명령어 파싱기능이 풍부, 서브커맨드 지원
meow명령어 파싱경량, 간단한 CLI에 적합
Inquirer.js대화형 프롬프트다양한 입력 유형 지원
chalk텍스트 스타일링색상, 굵기 등 터미널 꾸미기
ora로딩 스피너비동기 작업 진행 표시

추가로 유용한 CLI 패키지

패키지용도
yargscommander.js 대안, 강력한 인자 파싱
promptsInquirer.js 대안, 더 가볍고 현대적
boxen터미널에 박스 UI 생성
cli-table3터미널에 표 출력
figures터미널 유니코드 심볼 (체크마크, X 등)
listr2멀티 태스크 진행률 표시
update-notifierCLI 업데이트 알림