icon
7장 : 모듈과 네임스페이스

ES 모듈 시스템


현대의 자바스크립트 및 타입스크립트 개발에서 코드를 조직하고 재사용하는 핵심적인 방법은 바로 모듈(Modules) 을 사용하는 것입니다. 모듈은 코드를 여러 개의 독립적인 파일로 분리하고, 각 파일이 자신만의 스코프(Scope)를 가지도록 하여 전역 스코프 오염을 방지하며, 필요한 부분만 명시적으로 가져다 쓸 수 있게 해줍니다.

타입스크립트는 자바스크립트의 표준 모듈 시스템인 ES 모듈(ECMAScript Modules) 을 완벽하게 지원합니다. ES 모듈은 importexport 키워드를 사용하여 모듈 간의 의존성을 관리합니다.


export로 모듈 내보내기

모듈에서 다른 파일에서 사용될 수 있는 변수, 함수, 클래스, 인터페이스, 타입 별칭 등을 공개하려면 export 키워드를 사용합니다.

개별 내보내기 (Named Exports)

각 선언 앞에 export 키워드를 붙여 개별적으로 내보냅니다. 여러 개를 내보낼 수 있으며, 가져올 때도 해당 이름을 그대로 사용해야 합니다.

mathUtils.ts
export const PI = 3.14159; // 변수 내보내기

export function add(a: number, b: number): number { // 함수 내보내기
  return a + b;
}

export class Calculator { // 클래스 내보내기
  constructor(public value: number) {}
  multiply(factor: number): number {
    return this.value * factor;
  }
}

export interface Point { // 인터페이스 내보내기
  x: number;
  y: number;
}

export type ID = string | number; // 타입 별칭 내보내기

한꺼번에 내보내기

모듈의 끝에서 중괄호 {} 안에 내보낼 모든 것들을 나열하여 한꺼번에 내보낼 수도 있습니다.

validation.ts
function isValidEmail(email: string): boolean {
  return email.includes('@') && email.includes('.');
}

function isValidPassword(password: string): boolean {
  return password.length >= 8;
}

export { isValidEmail, isValidPassword };

기본 내보내기 (Default Exports)

모듈에서 단 하나의 주된 값을 내보낼 때는 export default를 사용합니다. export default는 모듈당 하나만 존재할 수 있으며, 가져올 때는 임의의 이름을 붙일 수 있습니다.

userService.ts
interface User {
  id: number;
  name: string;
}

class UserService {
  private users: User[] = [];

  addUser(user: User): void {
    this.users.push(user);
    console.log(`User ${user.name} added.`);
  }

  getUsers(): User[] {
    return this.users;
  }
}

export default UserService; // UserService 클래스를 기본 내보내기

기본 내보내기는 주로 한 모듈이 특정 클래스나 함수 하나를 대표할 때 사용됩니다.


import로 모듈 가져오기

다른 모듈에서 내보낸 값을 사용하려면 import 키워드를 사용합니다.

개별 가져오기 (Named Imports)

중괄호 {} 안에 내보낸 이름을 그대로 사용하여 가져옵니다. 필요하다면 as 키워드를 사용하여 별칭을 지정할 수 있습니다.

app.ts
import { PI, add, Calculator } from './mathUtils'; // 개별 내보내기 가져오기
import { isValidEmail as checkEmail } from './validation'; // 별칭 사용하여 가져오기

console.log(PI); // 3.14159
console.log(add(5, 3)); // 8

const calc = new Calculator(10);
console.log(calc.multiply(4)); // 40

console.log(checkEmail("test@example.com")); // true

기본 가져오기 (Default Imports)

기본 내보내기로 내보낸 값을 가져올 때는 중괄호 없이 임의의 이름을 사용하여 가져옵니다.

main.ts
import MyUserService from './userService'; // 기본 내보내기 가져오기 (임의의 이름 MyUserService)

const service = new MyUserService(); // MyUserService는 실제 UserService 클래스를 참조
service.addUser({ id: 1, name: "Alice" });
console.log(service.getUsers());

전체 가져오기 (Namespace Imports)

모듈 내의 모든 내보내진 멤버들을 하나의 객체로 묶어서 가져올 수 있습니다. 이는 주로 모듈의 멤버가 많거나, 이름 충돌을 피하고 싶을 때 사용됩니다.

app.ts
import * as Math from './mathUtils'; // mathUtils.ts의 모든 멤버를 Math 객체로 가져오기

console.log(Math.PI);
console.log(Math.add(10, 20));

const newCalc = new Math.Calculator(20);
console.log(newCalc.multiply(5));

사이드 이펙트를 위한 가져오기

특정 모듈이 내보내는 값은 없지만, 모듈을 가져오는 것만으로 전역 스코프에 영향을 주거나 특정 초기화 코드를 실행하는 경우에 사용됩니다.

polyfills.ts (예시)
// 이 파일은 직접 내보내는 것은 없지만, import만으로 특정 기능을 활성화할 수 있습니다.
// String.prototype.startsWith 폴리필 등...
console.log("Polyfills loaded!");
main.ts
import './polyfills'; // polyfills.ts 모듈을 가져와서 실행만 합니다.
console.log("Application started.");
// 출력:
// Polyfills loaded!
// Application started.

모듈 경로 지정

import 문에서 모듈의 경로는 다음과 같이 지정됩니다.

  • 상대 경로: 현재 파일 위치를 기준으로 다른 모듈의 경로를 지정합니다. (./, ../ 사용)
    import { someFunc } from './myFile';
    import { anotherFunc } from '../components/AnotherComponent';
  • 절대 경로 (별칭 경로): tsconfig.jsonpaths 설정을 통해 특정 경로에 별칭을 부여하여 사용할 수 있습니다. 이는 프로젝트 규모가 커질 때 긴 상대 경로를 피하고 모듈 위치를 명확히 하는 데 도움이 됩니다.
    tsconfig.json
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@utils/*": ["src/utils/*"],
          "@models/*": ["src/models/*"]
        }
      }
    }
    app.ts
    // app.ts
    import { formatMoney } from '@utils/formatter'; // src/utils/formatter.ts 파일을 참조
    import { User } from '@models/user';             // src/models/user.ts 파일을 참조
  • 패키지 이름: node_modules 폴더에 설치된 npm 패키지를 가져올 때 사용합니다.
    import React from 'react';
    import { useEffect } from 'react';
    import axios from 'axios';

타입스크립트와 ES 모듈

타입스크립트는 .ts 파일에서 ES 모듈 문법을 사용하면, 컴파일 시 tsconfig.jsonmodule 설정에 따라 해당 모듈 코드를 자바스크립트의 ES 모듈(ESNext), CommonJS, AMD, UMD 등 다양한 모듈 형식으로 변환합니다.

대부분의 현대 웹 개발 환경(React, Angular, Vue 등)에서는 번들러(Webpack, Vite, Rollup 등)와 함께 ES 모듈을 사용하는 것이 표준입니다. 타입스크립트는 이러한 환경에 맞춰 모듈 시스템을 유연하게 지원합니다.


ES 모듈 시스템은 코드의 모듈화와 재사용성을 극대화하고, 전역 스코프 오염을 방지하여 대규모 애플리케이션을 효율적으로 개발할 수 있게 해줍니다. exportimport 키워드를 적절히 사용하여 코드를 기능별로 분리하고, 명확한 의존성 관계를 설정하는 것은 잘 조직된 타입스크립트 프로젝트의 기본입니다.