ConfigShip: Node.js용 제로 의존성, 보안 구성 관리자 (Raw Env 지원 포함!)

발행: (2025년 12월 26일 오후 02:32 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

ConfigShip: Node.js용 순수 의존성 없는 보안 설정 관리자 (Raw Env 지원)

소개

Node.js 애플리케이션을 운영할 때 가장 흔히 마주치는 문제 중 하나는 환경 변수구성 파일을 안전하게 관리하는 것입니다.
대부분의 기존 솔루션은 여러 외부 패키지에 의존하거나, 복잡한 설정 과정을 요구합니다.

ConfigShip은 이러한 문제를 해결하기 위해 설계되었습니다.

  • Zero Dependency: 외부 라이브러리 없이 순수 Node.js만 사용합니다.
  • Secure: 암호화된 값과 스키마 검증을 기본 제공하여 민감한 정보를 보호합니다.
  • Raw Env Support: 기존 process.env와 완벽히 호환되며, 기존 환경 변수를 그대로 사용할 수 있습니다.

주요 기능

  • 환경 변수 자동 로드: .env 파일을 자동으로 파싱하고 process.env에 주입합니다.
  • 스키마 기반 검증: zod와 같은 스키마 정의 없이도 타입과 필수 여부를 선언할 수 있습니다.
  • 암호화된 비밀 관리: AES‑256‑GCM을 사용해 비밀 값을 암호화하고 복호화합니다.
  • 플러그인 없는 경량 구현: 전체 패키지 크기가 ~2KB에 불과합니다.
  • TypeScript 지원: 타입 정의가 자동으로 생성되어 IDE 자동 완성 및 타입 체크가 가능합니다.

설치

npm i configship
# 또는
yarn add configship

기본 사용법

// config.js
const { ConfigShip } = require('configship');

// 스키마 정의 (선택 사항)
const schema = {
  PORT: { type: 'number', default: 3000 },
  DB_HOST: { type: 'string', required: true },
  DB_PASSWORD: { type: 'secret' } // 자동 암호화/복호화
};

const config = new ConfigShip({ schema });

module.exports = config;
// server.js
const config = require('./config');

console.log(`Server listening on port ${config.PORT}`);
console.log(`Database host: ${config.DB_HOST}`);

Raw Env 지원

ConfigShip은 기존 process.env와 완벽히 호환됩니다.
아래와 같이 기존 코드를 그대로 유지하면서도 ConfigShip이 제공하는 검증 및 암호화 기능을 동시에 활용할 수 있습니다.

// 기존 코드 (변경 없음)
const port = process.env.PORT || 8080;

// ConfigShip을 사용한 경우
const config = require('./config');
const port = config.PORT; // 검증 및 기본값 적용됨

비밀 값 암호화

비밀 값은 .env.secret 파일에 저장하고, 런타임에 자동 복호화됩니다.

# .env.secret
DB_PASSWORD=enc:U2FsdGVkX1+...
// config.js
const { ConfigShip } = require('configship');

const config = new ConfigShip({
  secretKey: process.env.SECRET_KEY // 암호화/복호화에 사용되는 키
});

API 레퍼런스

메서드설명
new ConfigShip(options)스키마와 옵션을 전달해 인스턴스를 생성합니다.
config.get(key)지정한 키의 값을 반환합니다. 검증 및 복호화가 자동으로 수행됩니다.
config.set(key, value)런타임에 값을 업데이트합니다. 비밀 값인 경우 자동 암호화됩니다.
config.validate()현재 로드된 모든 환경 변수를 스키마와 대조해 검증합니다.
config.loadEnv(filePath)지정한 .env 파일을 파싱하고 process.env에 주입합니다.

보안 고려 사항

  1. 비밀 키 관리: SECRET_KEY는 절대로 코드 레포에 커밋하지 말고, 별도의 비밀 관리 시스템(예: AWS Secrets Manager, HashiCorp Vault)에서 로드하세요.
  2. 파일 권한: .env.secret 파일은 최소 권한(600)으로 설정해 다른 사용자에게 노출되지 않도록 합니다.
  3. 배포 파이프라인: CI/CD 단계에서 config.validate()를 실행해 누락된 변수나 타입 오류를 사전에 차단합니다.

결론

ConfigShip은 Zero Dependency라는 가장 간단한 전제 하에, 보안편의성을 동시에 제공하는 Node.js 설정 관리 솔루션입니다.
기존 process.env 사용 방식을 그대로 유지하면서도, 스키마 검증, 비밀 값 암호화, TypeScript 타입 지원을 통해 개발 생산성을 크게 향상시킬 수 있습니다.

Tip: 프로젝트 초기 단계에서 ConfigShip을 도입하면, 환경 변수 관리에 대한 리팩터링 비용을 크게 절감할 수 있습니다.


이 글은 Dev.to에 게시된 원본 글을 한국어로 번역한 것입니다.

The Problem

  • 어디에든 흩어져 있는 하드코딩된 기본값
  • 다루기 어려운 .env 파일
  • 개발 / 스테이징 / 프로덕션용 서로 다른 설정
  • 실행 시 오버라이드가 문제를 일으킴
  • 프로토타입 오염 취약점 (정말 있습니다)

내 솔루션: ConfigShip

Zero dependencies. 진지하게 – package.json를 직접 확인해 보세요.

무엇이 다르게 만들까요?

계층형 해결 (명확한 우선순위)

runtime → env → file → defaults

원시 환경 변수 이름 (v0.1.2에서 새로 추가)

config.get("APP_NAME") // Works!
config.get("name")     // Also works! (transformed)

기본적으로 안전함

  • 프로토타입 오염으로부터 보호
  • TypeScript 엄격 모드
  • 누락된 설정으로 인한 충돌 방지

자동 파싱

APP_PORT=3000        # → number 3000
APP_ENABLED=true    # → boolean true
APP_DATA={"x":1}    # → object {x:1}

빠른 예제

import { createConfig } from "config-ship";

const config = createConfig({
  defaults: {
    db: { host: "localhost", port: 5432 }
  },
  envPrefix: "APP_",
  envFile: ".env"
});

// 어디서든 접근
config.get("db.host");
config.set("db.port", 5433);

실제 예시: Express 앱

// config/index.js
import { createConfig } from "config-ship";

export const config = createConfig({
  defaults: {
    server: { port: 3000, host: "localhost" },
    db: {
      host: "localhost",
      port: 5432,
      pool: { min: 2, max: 10 }
    },
    redis: { url: "redis://localhost:6379" },
    features: {
      rateLimiting: true,
      analytics: false
    }
  },
  envPrefix: "MYAPP_",
  envFile: ".env",               // optional auto‑loading of process.env
  rootFile: `config/${process.env.NODE_ENV}.js`
});
// app.js
import express from "express";
import { config } from "./config/index.js";

const app = express();

app.listen(
  config.get("server.port"),
  () => console.log(`Running on port ${config.get("server.port")}`)
);

프로덕션 .env

MYAPP_SERVER__PORT=8080
MYAPP_DB__HOST=prod-db.internal
MYAPP_DB__POOL__MAX=50
MYAPP_REDIS__URL=redis://prod:6379

중첩된 키를 위한 __ 를 확인하세요!

환경 변수 쉽게 사용하기

구문

  • 접두사: APP_ (단일 _가 접두사를 구분)
  • 이중 __는 중첩 경로를 생성합니다
APP_DB__HOST=localhost          # → db.host
APP_DB__PORT=5432               # → db.port (parsed to number)
APP_FEATURE__BETA=true          # → feature.beta (parsed to boolean)

사용 사례: 기능 플래그

const config = createConfig({
  defaults: {
    features: {
      darkMode: false,
      newUI: false,
      betaAccess: false
    }
  },
  envPrefix: "FEATURES_"
});

function featureEnabled(name) {
  return config.get(`features.${name}`, false);
}

// Usage
if (featureEnabled("darkMode")) {
  applyDarkTheme();
}

// Enable for beta users
if (user.isBetaTester) {
  config.set("features.betaAccess", true);
}

Use Case: NPM Package Configuration

import { createConfig } from "config-ship";

export function createClient(userOptions = {}) {
  const config = createConfig({
    defaults: {
      timeout: 5000,
      retries: 3,
      baseURL: "https://api.example.com"
    },
    envPrefix: "MY_PKG_"
  });

  // User options override everything
  Object.keys(userOptions).forEach(key => {
    config.set(key, userOptions[key]);
  });

  return {
    config,
    // your API
  };
}

Configuration sources

  • 기본값
  • 환경 변수: MY_PKG_TIMEOUT=10000
  • 런타임: createClient({ timeout: 3000 })

보안: 프로토타입 오염 방지

v0.1.2에서 중요한 수정:

// 악의적인 시도가 차단됩니다 ✅
config.set("__proto__.polluted", true);
config.set("constructor.prototype.polluted", true);

console.log({}.polluted); // undefined (안전!)

포괄적인 보안 테스트를 통해 검증되었습니다.

What’s New in v0.1.2?

  • Raw env namesconfig.get("APP_NAME") 이제 작동합니다
  • 🔒 Security – 프로토타입 오염 취약점 수정
  • 💪 TypeScript – 엄격 모드 활성화
  • 📚 Docs – 더 나은 예제와 사용 사례
  • Tests – 37개의 테스트, 모두 통과

왜 그냥 사용하지 않을까…?

LibraryDrawbacks
dotenv환경 변수만 로드; 레이어링 없음, 런타임 오버라이드 없음
config5개 이상의 의존성, 복잡한 설정, 원시 env 이름 없음
convict훌륭하지만 무겁다; 검증 오버헤드
ConfigShip의존성 제로, 간단, 보안, 배터리‑포함

설치

npm install config-ship

링크

  • 📦 NPM:
  • 🐙 GitHub:
  • 📝 Changelog:

시도해 보기

npm install config-ship

여러분의 피드백을 기다립니다! 어떤 설정 문제에 직면하고 계신가요?

Edit: 모든 피드백에 감사드립니다! env‑var 명명 및 raw‑name 지원에 대한 설명을 추가했습니다.

게시할 서브레딧

  • r/node
  • r/javascript
  • r/typescript
  • r/webdev
  • r/programming (인기가 있으면)
Back to Blog

관련 글

더 보기 »