---
id: typescript-module-augmentation
title: TypeScript Module Augmentation — 외부 타입 확장
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [typescript, declaration, augmentation, vibe-coding]
tech_stack: { language: "TypeScript 5+", applicable_to: ["Library", "App"] }
applied_in: []
aliases: [d.ts, declare module, global augmentation, ambient]
---

# TypeScript Module Augmentation

> 외부 라이브러리 / 전역 / 자체 모듈에 **타입을 추가하거나 덮어쓰기**. plugin 시스템, env 타입, custom matcher 등에서 필수.

## 📖 핵심 개념
- `declare module 'pkg'`: 패키지 타입 확장.
- `declare global`: 전역 namespace 추가.
- `interface` 는 같은 이름이면 자동 merge.
- 별도 `.d.ts` 파일 또는 `.ts` 파일 내 inline.

## 💻 코드 패턴

### 1. Express Request 확장
```ts
// types/express.d.ts
import 'express';
declare module 'express-serve-static-core' {
  interface Request {
    user?: { id: string; email: string };
    requestId: string;
  }
}

// app.ts
app.use((req, res, next) => {
  req.requestId = crypto.randomUUID(); // ✅ 타입 됨
  next();
});
```

### 2. Vite env vars
```ts
// src/vite-env.d.ts
/// <reference types="vite/client" />
interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_FEATURE_X: 'on' | 'off';
}
interface ImportMeta { readonly env: ImportMetaEnv; }

// 사용
const url = import.meta.env.VITE_API_URL; // string 타입
```

### 3. Process.env 보강 (Node)
```ts
// global.d.ts
declare global {
  namespace NodeJS {
    interface ProcessEnv {
      DATABASE_URL: string;
      JWT_SECRET: string;
      NODE_ENV: 'development' | 'production' | 'test';
    }
  }
}
export {};
```

### 4. Window 전역
```ts
// global.d.ts
declare global {
  interface Window {
    dataLayer: any[];
    gtag: (...args: any[]) => void;
  }
}
export {};

// 사용
window.dataLayer = window.dataLayer || [];
```

### 5. CSS Modules 타입
```ts
// styles.d.ts
declare module '*.module.css' {
  const classes: { readonly [key: string]: string };
  export default classes;
}
declare module '*.svg' {
  const url: string;
  export default url;
}
```

### 6. 자체 라이브러리 plugin 확장점
```ts
// MyLib core
export interface PluginRegistry {} // 빈 인터페이스 — 플러그인이 augment

// 플러그인 패키지
declare module 'mylib' {
  interface PluginRegistry {
    'analytics': { trackingId: string };
  }
}
```

## 🤔 의사결정 기준
| 상황 | 위치 |
|---|---|
| 외부 라이브러리 필드 추가 | `declare module 'pkg'` |
| Window / globalThis | `declare global` + `export {}` |
| Env vars | ImportMetaEnv / NodeJS.ProcessEnv |
| 비-JS asset (png, svg, css) | `declare module '*.png'` |
| Plugin 확장점 | 빈 interface + augmentation |

## ❌ 안티패턴
- **`.d.ts` 가 `tsconfig.include` 에 안 들어감**: 무시됨. 경로 확인.
- **module augmentation 파일이 `import` 없음**: ambient module 처럼 처리되어 의도와 다름. `export {}` 또는 다른 import.
- **interface vs type 혼용**: type 은 merge 안 됨. augmentation 은 interface 만.
- **거대 .d.ts 파일에 모든 augmentation**: 분리 권장 (express.d.ts, env.d.ts, etc).
- **타입만 export 했는데 런타임 값으로 사용**: 컴파일 후 사라짐. 별도 const.
- **컴파일 시 사라지는 import side-effect**: `import 'pkg'` 만 (런타임 effect 위해) 했는데 타입은 안 보강. 명시적 reference.

## 🤖 LLM 활용 힌트
- "Express / Next / Vite / Node 확장은 별도 .d.ts 파일에 declare module" 명시.
- 새 d.ts 추가 시 tsconfig include 확인.

## 🔗 관련 문서
- [[TypeScript_Branded_Types]]
- [[JS_Module_System_ESM_CJS]]
