728x90
728x90
ESModules 방식과 Namespaces 방식
들어가며
- ESModules 방식과 Namespaces 방식의 차이에 대해 간단하게 정리해본다.

방식
① ESModules 방식
개념
- JavaScript 표준 모듈 시스템
- 파일 단위로 모듈을 분리한다.
- 각 파일이 하나의 모듈이고, 필요한 것만 @import@/@export@로 가져온다.
- Next.js, React, TypeScript, Vite, Node.js 최신 환경은 전부 이 방식을 기본으로 사용한다.
utils/
math.ts
components/
Button.tsx
app/
page.tsx
사용 예
//
// ☑️ [1] export
//
// utils/math.ts
export function add(a: number, b: number) {
return a + b;
}
export const PI = 3.14;
// app/page.tsx
import { add, PI } from "@/utils/math"; // {} 로 값 뽑기
console.log(add(1, 2));
console.log(PI);
//
// ☑️ [2] default export
//
// components/Button.tsx
export default function Button() {
return <button>Click</button>;
}
// app/page.tsx
import Button from "@/components/Button"; // 중괄호({}) 없이 가져오기
// 아래처럼 별칭 지정 가능
// components/MyComponent.tsx
export default MyComponent {}
export helloWorld = "Hello World";
export type TestType = string | number;
// app/page.tsx
import * as Test from "@/components/MyComponent"; // export default (별칭 사용)
import { helloWorld } from "@/components/MyComponent"; // export
import { helloWorld as sayHello } from "@/components/MyComponent"; // export (별칭 사용)
import { type TestType } from "@/components/MyComponent"; // 타입 불러올 때 (대부분 type 표시 필수 X)
② Namespaces 방식
개념
- TypeScript 초창기에 많이 쓰던 방식
- JavaScript의 표준 문법이 아닌 TypeScript 전용 문법
- 하나의 전역 객체처럼 코드를 묶는 방식
- 예전에는 브라우저에서 여러 TS 파일을 하나로 합치거나, 전역 스코프 충돌을 피하려고 @namespace@를 많이 썼다.
- 하지만 지금은 ESModules 방식이 표준이다.
사용 예
namespace MathUtils {
export function add(a: number, b: number) {
return a + b;
}
export const PI = 3.14;
}
console.log(MathUtils.add(1, 2));
console.log(MathUtils.PI);
- 컴파일되면 대략 다음과 같은 JavaScript 형태가 된다.
- MathUtils라는 객체 안에 함수와 값을 넣는 구조
var MathUtils;
(function (MathUtils) {
function add(a, b) {
return a + b;
}
MathUtils.add = add;
MathUtils.PI = 3.14;
})(MathUtils || (MathUtils = {}));
아직 쓰이는 경우
- Namespaces 방식이 아직 사라진 건 아니다.
- 아래의 경우 가끔 쓰인다.
(1) 타입 선언 파일 (@.d.ts@)
- 예를 들어, 전역 타입을 확장할 때 다음과 같이 사용한다.
declare namespace NodeJS {
interface ProcessEnv {
MONGO_URI: string;
NEXTAUTH_SECRET: string;
}
}
declare namespace Express {
interface Request {
userId?: string;
}
}
(2) 오래된 라이브러리 타입 정의
- 일부 오래된 JS 라이브러리의 타입 선언에서 @namespace@ 키워드를 볼 수 있다.
declare namespace SomeOldLibrary {
function init(): void;
}
(3) @enum@ 비슷하게 정적 그룹핑을 하고자 할 경우
- 가능은 하지만, 보통은 객체나 모듈 @export@ 방식이 더 낫다.
// 비추천
namespace UserRole {
export const ADMIN = "admin";
export const USER = "user";
}
// 추천
export const USER_ROLE = {
ADMIN: "admin",
USER: "user",
} as const;
export type UserRole = typeof USER_ROLE[keyof typeof USER_ROLE];
@namespace@는 현재 주로 타입 선언 파일, 전역 타입 확장, 레거시 라이브러리 타입 정의에서 사용된다.
핵심 차이 비교
| 구분 | ESModule | namespace |
| 표준 여부 | JavaScript 표준 | TypeScript 표준 |
| 사용 방식 | @import@ / @export@ | @namespace@ 블록 |
| 기준 단위 | 파일 단위 | 객체/스코프 단위 |
| Next.js 적합성 | 매우 적합 | 거의 비추천 |
| Tree-shaking | 유리함. | 불리할 수 있음. |
| 번들러 호환성 | 좋음 | 제한적 |
| 현대 TS 권장 여부 | 권장 | 특수 상황 제외 비권장 |
참고 사이트
JavaScript modules - JavaScript | MDN
developer.mozilla.org
Documentation - Namespaces
How TypeScript namespaces work
www.typescriptlang.org
728x90
728x90
'Programming > TypeScript' 카테고리의 다른 글
| [TypeScript] 코드 품질을 높여주는 tsconfig.json 설정 (0) | 2026.03.31 |
|---|---|
| [TypeScript] 환경 변수 타입 설정하기 (3) | 2024.12.09 |
| [TypeScript] 클래스(Class) (0) | 2024.10.12 |
| [TypeScript] 제네릭(Generic) (0) | 2024.10.12 |
| [TypeScript] 인터페이스(Interface) (0) | 2024.10.12 |
| [TypeScript] Zod 라이브러리 (0) | 2024.10.11 |
| [TypeScript] 타입 가드(Type Guard) (0) | 2024.10.10 |
| [TypeScript] 모듈 방식 사용하기 (0) | 2024.10.10 |
