모놀리식 CLI에서 모듈식 플러그인으로: 스트랭글러 피그 패턴 적용

발행: (2025년 12월 4일 오후 12:41 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

TL;DR – 안전한 마이그레이션 전략

  • 명령을 외부 플러그인으로 추출 (베타로 배포)
  • 플러그인을 코어에 의존성으로 추가 (v2.x – 파괴적 변경 없음)
  • 피드백을 수집하고, 반복하며, 안정화
  • v3.0.0에서 의존성 제거 (파괴적 변경, 하지만 준비됨)
  • 사용자는 필요한 것만 설치

Result: safe migration + independent plugin evolution


문제: CLI가 유지보수 불가능해지는 이유

Your CLI probably started like this:

cli/
├── commands/
   ├── deploy.js
   └── status.js
├── utils/
   └── helpers.js
└── index.js

깨끗하고. 단순하며. 모든 것이 제자리에 있습니다.

Six months later:

cli/
├── commands/      (37 files)
├── utils/         (23 files)
├── services/      (15 files)
├── integrations/  (12 files)
└── shared/        (who even knows?)

Now you’re dealing with:

  • 강한 결합 – 모든 명령이 10개 이상의 유틸리티 파일을 import
  • 공유 상태 악몽 – 모든 것이 접근하는 전역 설정
  • 위험한 릴리즈 – 하나의 변경으로 전체 CLI를 테스트해야 함
  • 느린 개발 – 기능 추가에 수주간의 조정이 필요
  • 파괴적 변경 지옥 – 한 부분을 진화시키면 전체가 깨짐

Sound familiar? You’ve built a monolith.
=> 익숙하신가요? 당신은 모놀리스를 만들었습니다.

백엔드 교훈: 모놀리스를 모듈러로 전환하기

옛 방식 (모놀리식 API)

Everything in one codebase

Tightly coupled domains

Coordinated releases

High‑risk deployments

Slow feature velocity

현대 방식 (마이크로서비스 / 모듈러)

Thin API Gateway

Isolated domain services

Independent deployments

Versioned contracts

Fast, safe iterations

핵심 인사이트: 도메인을 격리하고, 명확한 경계를 설정하며, 독립적인 진화를 가능하게 합니다. 이는 CLI에도 적용됩니다.

해결책: Core + 플러그인 아키텍처

얇은 Core

Your core should be boring and stable:

core/
├── auth/           // Auth logic
├── config/         // Config management
├── dispatcher/     // Command routing
├── utils/          // Cross‑cutting concerns
└── plugin-loader/  // Plugin discovery

The core provides infrastructure and gets out of the way.

플러그인

Each plugin is a self‑contained domain:

plugins/
├── deploy-plugin/
│   ├── commands/
│   ├── tests/
│   ├── README.md
│   └── package.json   // Independent versioning!
├── logs-plugin/
└── backup-plugin/

각 플러그인:

  • 하나의 책임만을 가짐
  • 자체 시맨틱 버전을 가짐
  • 독립적으로 설치 (npm i @cli/deploy-plugin)
  • 다른 플러그인에 영향을 주지 않고 변경 가능
  • 완전 격리된 테스트

마이그레이션 전략: 스트랭글러 피그 패턴

The Strangler Fig Pattern (Martin Fowler) lets you migrate gradually without a risky big‑bang rewrite.

단계 1 – 외부 플러그인을 베타로 배포

# Release your first plugin in beta
npm publish @my-cli/deploy-plugin@1.0.0-beta.1
npm publish @my-cli/logs-plugin@1.0.0-beta.1

왜 베타인가? 사용자는 테스트에 옵트인할 수 있고, 빠르게 반복할 수 있으며, 파괴적 변경이 예상됩니다.

// deploy-plugin/package.json
{
  "name": "@my-cli/deploy-plugin",
  "version": "1.0.0-beta.1",
  "main": "dist/index.js",
  "peerDependencies": {
    "@my-cli/core": "^2.0.0"
  }
}

단계 2 – 플러그인을 Core에 의존성으로 추가 (임시)

// core/package.json
{
  "name": "@my-cli/core",
  "version": "2.5.0",
  "dependencies": {
    "@my-cli/deploy-plugin": "^1.0.0-beta.1",
    "@my-cli/logs-plugin": "^1.0.0-beta.1"
  }
}
  • 사용자는 core를 설치하면 → 플러그인이 자동으로 함께 설치됩니다
  • 기존 사용자에게 파괴적 변경 없음
  • 플러그인은 초기 도입자에게 독립적으로 동작

단계 3 – 명령을 점진적으로 마이그레이션

v2.5.0 (Initial Beta)

deploy → Plugin (bundled as dependency)
logs   → Legacy in core
backup → Legacy in core

v2.8.0 (Beta 2)

deploy → Plugin (bundled as dependency)
logs   → Plugin (bundled as dependency)
backup → Legacy in core

각 단계는 안전하게 배포되며, 사용자는 차이를 느끼지 못하고 플러그인은 실제 환경에서 성숙합니다.

단계 4 – 대전환: 의존성 제거 (v3.0.0)

// core/package.json (v3.0.0)
{
  "name": "@my-cli/core",
  "version": "3.0.0",
  "dependencies": {
    // No more plugin dependencies!
  },
  "peerDependencies": {
    // Plugins are now optional
  }
}

사용자를 위한 마이그레이션 가이드

# Old way (v2.x) – everything bundled
npm install -g @my-cli/core

# New way (v3.x) – install what you need
npm install -g @my-cli/core
npm install -g @my-cli/deploy-plugin   # only if you need deploy
npm install -g @my-cli/logs-plugin     # only if you need logs

왜 이것이 메이저 버전인지: 파괴적 변경 – 플러그인이 더 이상 자동 설치되지 않아 사용자는 더 많은 제어권을 갖고, 설치 용량이 작아지며, 설치 속도가 빨라집니다.

단계 5 – 사용자는 필요에 따라 설치

# Minimal installation (just core utilities)
npm install -g @my-cli/core

# À la carte (only what I use)
npm install -g @my-cli/core @my-cli/deploy-plugin

# Everything (opt‑in to all plugins)
npm install -g @my-cli/all   # metapackage

장점

  • 작은 설치 용량 (예: 15 MB vs 250 MB)
  • 빠른 시작 시간
  • 각 플러그인의 독립적인 진화
  • 보다 안전하고, 제어된 릴리즈

By treating your CLI like a microservice ecosystem and applying the Strangler Fig Pattern, you can transition from a monolithic codebase to a modular, plugin‑driven architecture with minimal risk and maximum flexibility.
=> CLI를 마이크로서비스 생태계처럼 다루고 스트랭글러 피그 패턴을 적용하면, 모놀리식 코드베이스에서 모듈형 플러그인 기반 아키텍처로 최소한의 위험과 최대한의 유연성을 가지고 전환할 수 있습니다.

Back to Blog

관련 글

더 보기 »

터미널을 한 픽셀씩 아름답게 만들기

2025년 11월 13일  우리는 Gemini CLI 사용자 경험에 대한 중요한 업그레이드를 발표하게 되어 기쁩니다. 이를 통해 터미널 상호작용이 더욱 견고하고 직관적이며…