JavaScript에서 TypeScript로의 마이그레이션은 한 번에 전환하지 않고 점진적으로 진행하는 것이 안전합니다. 기존 JS 코드와 새 TS 코드를 함께 운영하면서 단계적으로 전환합니다.

전환 전략 개요

PLAINTEXT
1단계: TypeScript 설치 + allowJs
2단계: JSDoc으로 타입 추가
3단계: .js → .ts 파일 변환 (느슨한 설정)
4단계: strict 모드 점진적 활성화
5단계: any 제거 + 완전한 타입 커버리지

1단계: TypeScript 설치와 기본 설정

BASH
npm install --save-dev typescript
npx tsc --init
JSON
// tsconfig.json — 가장 느슨한 설정으로 시작
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "allowJs": true,          // JS 파일 허용
    "checkJs": false,         // JS 파일 타입 체크 안 함 (처음에는)
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": false,          // 처음에는 느슨하게
    "esModuleInterop": true,
    "skipLibCheck": true,
    "noEmit": true            // 번들러가 있다면
  },
  "include": ["src/**/*"]
}

이 설정만으로도 TypeScript 컴파일러가 프로젝트를 인식합니다. 기존 JS 코드는 전혀 수정하지 않아도 됩니다.

2단계: JSDoc으로 타입 추가

파일 확장자를 바꾸지 않고도 JSDoc으로 타입 정보를 추가할 수 있습니다.

JAVASCRIPT
// utils.js — JSDoc으로 타입 추가

/**
 * @param {string} name
 * @param {number} age
 * @returns {{ name: string, age: number }}
 */
function createUser(name, age) {
  return { name, age };
}

/** @type {string[]} */
const tags = ['javascript', 'typescript'];

/**
 * @typedef {Object} Config
 * @property {string} host
 * @property {number} port
 * @property {boolean} [ssl]
 */

/** @type {Config} */
const config = { host: 'localhost', port: 3000 };
JSON
// tsconfig.json — checkJs 활성화
{
  "compilerOptions": {
    "checkJs": true  // JS 파일도 타입 체크
  }
}

checkJs를 켜면 JSDoc 타입 정보를 기반으로 JS 파일도 타입 체크됩니다.

3단계: .js → .ts 변환

가장 중요한 파일부터 하나씩 .ts로 변환합니다.

변환 우선순위

  1. 유틸리티 함수 — 의존성이 적고 독립적
  2. ** 타입/인터페이스 정의** — 다른 파일에서 사용
  3. ** 핵심 비즈니스 로직** — 타입 안전성이 가장 중요한 곳
  4. ** 컴포넌트** — 점진적으로

변환 시 주의점

TYPESCRIPT
// JS에서 변환할 때 흔한 패턴

// ❌ JS 패턴 — 동적 속성 추가
const user = {};
user.name = '홍길동'; // Error: Property 'name' does not exist

// ✅ TS로 변환
const user: { name: string } = { name: '홍길동' };
// 또는
interface User { name: string; }
const user: User = { name: '홍길동' };
TYPESCRIPT
// 일단 any로 변환 후 나중에 개선
function processData(data: any): any {
  // TODO: 타입 추가
  return data.map((item: any) => item.value);
}

4단계: strict 옵션 점진적 활성화

한꺼번에 strict: true를 켜면 에러가 폭발할 수 있습니다. 하나씩 켜는 것이 좋습니다.

JSON
// 활성화 순서 (추천)
{
  "compilerOptions": {
    "strict": false,

    // 1단계: 가장 영향이 적은 것부터
    "noImplicitAny": true,           // any 추론 금지

    // 2단계
    "strictNullChecks": true,        // null/undefined 분리

    // 3단계
    "strictFunctionTypes": true,     // 함수 매개변수 반공변

    // 4단계
    "strictPropertyInitialization": true, // 클래스 속성 초기화

    // 최종: 모든 것을 strict: true로
    // "strict": true
  }
}

noImplicitAny 대응

TYPESCRIPT
// 에러 발생 위치에 타입을 추가
// ❌ Parameter 'data' implicitly has an 'any' type
function process(data) { /* ... */ }

// ✅ 타입 추가
function process(data: unknown) { /* ... */ }
// 또는 일단 any를 명시 (나중에 개선)
function process(data: any) { /* ... */ }

strictNullChecks 대응

TYPESCRIPT
// ❌ Object is possibly 'null'
const element = document.getElementById('app');
element.textContent = 'hello'; // Error

// ✅ null 체크 추가
const element = document.getElementById('app');
if (element) {
  element.textContent = 'hello';
}

5단계: any 제거

프로젝트 전체에서 any를 점진적으로 제거합니다.

BASH
# any 사용 현황 확인
npx tsc --noEmit | grep 'any'
TYPESCRIPT
// ESLint로 any 사용을 경고
{
  "rules": {
    "@typescript-eslint/no-explicit-any": "warn" // 처음에는 warn, 나중에 error
  }
}

유용한 도구

ts-migrate

BASH
# Airbnb의 자동 마이그레이션 도구
npx ts-migrate-full <project-dir>

ts-migrate는 JS 파일을 TS로 자동 변환하고, 타입 에러가 나는 곳에 any를 자동으로 추가합니다. 나중에 any를 하나씩 개선하면 됩니다.

마이그레이션 체크리스트

단계작업확인
1TypeScript 설치, allowJs 설정
2@types 패키지 설치
3핵심 파일 .ts 변환
4noImplicitAny 활성화
5strictNullChecks 활성화
6strict: true 전체 적용
7any 제거 (95% 이상)
8ESLint typescript-eslint 적용

정리

  • 마이그레이션은 한 번에 하지 않고 점진적으로 진행한다
  • allowJs로 JS와 TS를 혼합 운영하면서 하나씩 전환한다
  • JSDoc으로 파일 확장자 변경 없이도 타입을 추가할 수 있다
  • strict 옵션은 하나씩 켜면서 에러를 관리한다
  • ts-migrate 같은 자동화 도구를 활용하면 초기 작업이 빨라진다
댓글 로딩 중...