Homebrew로 Node.js CLI 패키지를 직접 관리하는 방법

Homebrew Formula를 직접 만들어서 Node.js CLI 도구를 관리하면 npm이나 yarn과는 다른 방식으로 패키지를 제어할 수 있어요. 특히 시스템 전역 설치가 필요한 CLI 도구를 깔끔하게 관리하고 싶을 때 유용해요.


Node.js 로고와 터미널 아이콘이 나란히 배치된 CLI 개발 환경 표현


기본 Node.js 설치와 nvm 설치 중 선택하기


macOS에서 Homebrew로 Node.js를 설치하는 방법은 크게 두 가지예요. 단일 버전만 필요하면 직접 설치하고, 여러 버전을 관리해야 하면 nvm을 사용해요.

# 방법 1: Node.js 직접 설치
brew install node

# 설치 확인
node -v  # v20.11.0 같은 버전 출력
npm -v   # 10.2.4 같은 버전 출력


프로젝트마다 다른 Node.js 버전이 필요하다면 nvm이 더 적합해요. 설치 과정이 조금 복잡하지만 버전 전환이 자유로워요.

# 방법 2: nvm 설치 및 설정
brew install nvm
mkdir ~/.nvm

# ~/.zshrc 파일에 추가
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
echo '[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh"' >> ~/.zshrc

# 쉘 재시작 후 Node.js 설치
source ~/.zshrc
nvm install --lts  # 최신 LTS 버전 설치
nvm use --lts      # 설치한 버전 사용


커스텀 Formula 작성의 핵심 구조


Node.js CLI 패키지를 Homebrew Formula로 만들 때는 Ruby 클래스를 작성해요. npm 레지스트리의 tarball URL을 직접 참조하는 방식이 가장 안정적이에요.

class MyNodeCli < Formula
  desc "나만의 Node.js CLI 도구"  # 패키지 설명
  homepage "https://github.com/username/my-cli"
  url "https://registry.npmjs.org/my-cli/-/my-cli-1.0.0.tgz"
  sha256 "abc123..."  # shasum 명령으로 계산한 해시값
  
  depends_on "node"  # Node.js 의존성 명시
  
  def install
    # npm 패키지를 libexec에 설치 (전역 오염 방지)
    system "npm", "install", *std_npm_args
    
    # 실행 파일을 bin 디렉토리에 심볼릭 링크
    bin.install_symlink Dir["#{libexec}/bin/*"]
  end
  
  test do
    # 버전 확인으로 설치 검증
    assert_match version.to_s, shell_output("#{bin}/my-cli --version")
  end
end


std_npm_args 헬퍼 메서드가 자동으로 적절한 npm 설치 옵션을 설정해줘요. 이 방식으로 전역 node_modules를 건드리지 않고 독립적인 환경을 구성할 수 있어요.


실제 Formula 작성 시 겪는 기술적 문제들


공식 문서대로 따라 해도 실제로는 여러 문제가 발생해요. 가장 흔한 문제와 해결 방법을 정리해봤어요.

# 문제 1: 심볼릭 링크 충돌 해결
def install
  system "npm", "install", *std_npm_args
  
  # 기존 방식 (충돌 가능성 있음)
  # bin.install_symlink Dir["#{libexec}/bin/*"]
  
  # 개선된 방식: 환경 변수 스크립트 사용
  (bin/"my-cli").write_env_script "#{libexec}/bin/my-cli",
    :NODE_PATH => "#{libexec}/lib/node_modules"
end


네이티브 애드온이 포함된 패키지는 빌드 의존성 추가가 필요해요.

# 문제 2: 네이티브 빌드 의존성 처리
depends_on "node"
depends_on "python@3.11" => :build  # node-gyp용 Python

def install
  # node-gyp rebuild 포함된 패키지 설치
  system "npm", "install", "--build-from-source", *std_npm_args
  bin.install_symlink Dir["#{libexec}/bin/*"]
end


SHA256 해시값 자동 계산과 버전 관리


Formula를 업데이트할 때마다 해시값을 수동으로 계산하는 건 번거로워요. 자동화 스크립트를 만들어두면 편해요.

#!/bin/bash
# update_formula.sh - Formula 자동 업데이트 스크립트

PACKAGE_NAME="my-cli"
VERSION="1.0.1"

# npm 레지스트리에서 tarball 다운로드
curl -L "https://registry.npmjs.org/${PACKAGE_NAME}/-/${PACKAGE_NAME}-${VERSION}.tgz" \
  -o "/tmp/${PACKAGE_NAME}.tgz"

# SHA256 계산
SHA256=$(shasum -a 256 "/tmp/${PACKAGE_NAME}.tgz" | cut -d' ' -f1)

echo "url: https://registry.npmjs.org/${PACKAGE_NAME}/-/${PACKAGE_NAME}-${VERSION}.tgz"
echo "sha256: ${SHA256}"

# Formula 파일 자동 업데이트 (sed 사용)
sed -i '' "s/url .*/url \"https:\/\/registry.npmjs.org\/${PACKAGE_NAME}\/-\/${PACKAGE_NAME}-${VERSION}.tgz\"/" Formula/${PACKAGE_NAME}.rb
sed -i '' "s/sha256 .*/sha256 \"${SHA256}\"/" Formula/${PACKAGE_NAME}.rb


플랫폼별 호환성 처리 방법


macOS와 Linux에서 모두 동작하는 Formula를 만들려면 OS별 조건 처리가 필요해요.

class CrossPlatformCli < Formula
  desc "크로스 플랫폼 Node.js CLI"
  homepage "https://example.com"
  url "https://registry.npmjs.org/cross-cli/-/cross-cli-1.0.0.tgz"
  sha256 "xyz789..."
  
  depends_on "node"
  
  def install
    system "npm", "install", *std_npm_args
    
    # OS별 경로 처리
    if OS.mac?
      # macOS 전용 설정
      bin.install_symlink Dir["#{libexec}/bin/*"]
      
      # macOS의 경우 추가 권한 설정
      chmod 0755, Dir["#{libexec}/bin/*"]
    else
      # Linux 전용 설정
      bin.install_symlink Dir["#{libexec}/bin/*"]
      
      # Linux에서는 다른 경로 사용
      (share/"man/man1").install Dir["#{libexec}/share/man/man1/*"]
    end
  end
end


Formula 검증과 배포 전 체크리스트


작성한 Formula가 Homebrew 정책에 맞는지 확인하는 과정이 중요해요. brew 명령어로 자동 검사할 수 있어요.

# Formula 스타일 검사
brew style --fix Formula/my-cli.rb

# Formula 정책 준수 검사
brew audit --strict Formula/my-cli.rb

# 실제 설치 테스트
brew install --build-from-source Formula/my-cli.rb

# 설치된 패키지 동작 확인
brew test my-cli


로컬 Formula 저장소 관리하기


공식 homebrew-core에 등록하지 않고도 개인 저장소로 Formula를 관리할 수 있어요. 이게 진짜 DIY 패키지 매니저의 시작이에요.

# 개인 Formula 저장소 생성
mkdir -p ~/homebrew-formulae
cd ~/homebrew-formulae
git init

# Formula 파일 추가
cp my-cli.rb Formula/

# Homebrew에 탭으로 등록
brew tap-new username/tools
brew tap username/tools ~/homebrew-formulae

# 이제 설치 가능
brew install username/tools/my-cli


자체 Formula 저장소를 GitHub에 올려두면 팀원들과 쉽게 공유할 수 있어요. brew tap username/repo 명령 하나로 모든 커스텀 Formula를 사용할 수 있게 돼요.


전역 npm 설치의 문제점을 해결하면서도 버전 관리와 의존성 격리가 가능한 DIY 패키지 매니저는 특히 여러 프로젝트를 동시에 진행하는 개발 환경에서 큰 도움이 돼요. 초기 설정이 번거롭긴 하지만 한번 구축해두면 npm과 Homebrew의 장점을 모두 활용할 수 있어요.


맥북 교체 시 Brewfile로 개발환경 한 번에 복원하는 방법