네임스페이스 사용법
타입스크립트의 네임스페이스는 관련된 기능을 그룹화하고 전역 스코프의 오염을 방지하기 위한 메커니즘입니다.
모듈 시스템과 달리, 네임스페이스는 논리적 그룹화에 중점을 둡니다.
네임스페이스 기본 개념
네임스페이스의 기본 문법
namespace MyNamespace {
export interface MyInterface {
myProperty: string;
}
export class MyClass implements MyInterface {
constructor(public myProperty: string) {}
}
export function myFunction() {
console.log("Hello from MyNamespace");
}
}
// 사용
const instance = new MyNamespace.MyClass("Hello");
MyNamespace.myFunction();
네임스페이스는 export
키워드로 외부에 노출할 요소를 지정합니다.
네임스페이스 vs 모듈
주요 차이점
- 스코프 : 네임스페이스는 전역 스코프, 모듈은 파일 스코프
- 로딩 : 네임스페이스는 런타임에 전역으로 사용 가능, 모듈은 명시적 임포트 필요
- 의존성 관리 : 모듈이 더 명시적이고 관리하기 쉬움
중첩 네임스페이스
네임스페이스는 중첩하여 사용할 수 있습니다.
namespace Outer {
export namespace Inner {
export class InnerClass {}
}
export class OuterClass {}
}
// 사용
const inner = new Outer.Inner.InnerClass();
const outer = new Outer.OuterClass();
이 방식은 복잡한 라이브러리의 구조를 표현할 때 유용합니다.
네임스페이스 분할과 의존성 관리
여러 파일에 걸쳐 네임스페이스를 분할할 수 있습니다.
// file1.ts
namespace MyNamespace {
export function func1() {}
}
// file2.ts
/// <reference path="file1.ts" />
namespace MyNamespace {
export function func2() {
func1(); // 같은 네임스페이스 내에서 직접 접근 가능
}
}
/// <reference>
지시문은 컴파일러에게 의존성을 알려줍니다.
네임스페이스와 모듈의 하이브리드 사용
네임스페이스와 모듈을 함께 사용할 수 있지만, 주의가 필요합니다.
// myModule.ts
export namespace MyNamespace {
export function myFunction() {}
}
// main.ts
import { MyNamespace } from './myModule';
MyNamespace.myFunction();
이 접근 방식은 레거시 코드와의 호환성을 유지할 때 유용할 수 있지만, 일반적으로 권장되지 않습니다.
네임스페이스 별칭
긴 네임스페이스 경로를 단축할 수 있습니다.
namespace VeryLong.Nested.Namespace {
export function myFunction() {}
}
import VNN = VeryLong.Nested.Namespace;
VNN.myFunction();
라이브러리 구조화
네임스페이스를 사용한 라이브러리 구조화 예
namespace MyLibrary {
export namespace Utils {
export function helperFunction() {}
}
export namespace Models {
export interface User {}
}
export namespace Services {
export class UserService {
getUser(): Models.User {
Utils.helperFunction();
return {} as Models.User;
}
}
}
}
이 방식의 장점은 관련 기능을 논리적으로 그룹화할 수 있다는 것입니다.
다만 모듈 시스템에 비해 의존성 관리가 어렵다는 점이 단점으로 작용합니다.
네임스페이스와 ES 모듈 상호 운용성
네임스페이스와 ES 모듈을 함께 사용할 때는 주의가 필요합니다.
// namespace.ts
namespace MyNamespace {
export const myConst = 42;
}
// module.ts
export { MyNamespace } from './namespace';
// main.ts
import { MyNamespace } from './module';
console.log(MyNamespace.myConst); // 42
이 방식은 작동하지만, 모듈 시스템만 사용하는 것이 더 명확하고 관리하기 쉽습니다.
컴파일러 옵션
네임스페이스 관련 주요 컴파일러 옵션
--outFile
: 여러 네임스페이스 파일을 하나의 파일로 컴파일--module
: 모듈 시스템 지정 (네임스페이스 사용 시 'none' 또는 'amd' 권장)
{
"compilerOptions": {
"outFile": "./dist/bundle.js",
"module": "none"
}
}
현대적 개발 환경에서의 대안
현대 타입스크립트 개발에서는 네임스페이스 대신 ES 모듈을 사용하는 것이 권장됩니다.
export function helperFunction() {}
export interface User {}
import { helperFunction } from './utils';
import { User } from './models';
export class UserService {
getUser(): User {
helperFunction();
return {} as User;
}
}
이 접근 방식은 더 나은 의존성 관리와 트리 쉐이킹을 가능하게 합니다.
Best Practices와 주의사항
- 모듈 선호 : 가능한 한 네임스페이스 대신 ES 모듈 사용
- 일관성 유지 : 프로젝트 내에서 네임스페이스와 모듈을 혼용하지 않기
- 얕은 중첩 : 네임스페이스를 사용할 경우, 중첩을 최소화
- 명확한 이름 : 충돌을 피하기 위해 명확하고 고유한 네임스페이스 이름 사용
- 레거시 고려 : 레거시 시스템과의 통합 시에만 제한적으로 사용
- 문서화 : 네임스페이스 사용 시 그 이유와 구조를 명확히 문서화
- 점진적 마이그레이션 : 기존 네임스페이스 기반 코드는 점진적으로 모듈 시스템으로 전환
네임스페이스의 현재 위치
네임스페이스는 타입스크립트의 초기 버전에서 중요한 역할을 했지만, 현재는 그 사용이 권장되지 않습니다.
주요 이유는 다음과 같습니다.
- 모듈 시스템의 발전 : ES 모듈이 표준화되고 널리 지원됨
- 번들러의 발전 : Webpack, Rollup 등이 모듈 기반 코드를 효율적으로 처리
- 의존성 관리 : 모듈 시스템이 더 명시적이고 관리하기 쉬움
- 생태계 지원 : 대부분의 현대 도구와 라이브러리가 모듈 시스템을 기반으로 함
그럼에도 불구하고 네임스페이스는 여전히 다음과 같은 상황에서 사용될 수 있습니다.
- 레거시 시스템과의 통합
- 전역 라이브러리 API 설계 (드문 경우)
- 특정 런타임 환경에서의 제약 사항
새로운 타입스크립트 프로젝트를 시작할 때는 ES 모듈 시스템을 사용하는 것이 가장 좋은 선택입니다.
네임스페이스는 역사적인 이유로 여전히 지원되지만, 현대적인 웹 개발 실무에서는 점점 그 자리를 모듈 시스템에 내주고 있습니다.
기존의 네임스페이스 기반 코드베이스를 유지보수하거나 마이그레이션해야 하는 경우가 아니라면 네임스페이스 사용을 피하고 모듈 시스템을 채택하는 것이 장기적으로 더 나은 선택일 것입니다.