타입스크립트 - 모듈

모듈(modules)은 독립 가능한 기능의 단위 입니다. 프로그램은 여러 모듈로 구성돼 있고 모듈을 결합해 하나의 프로그램을 만듭니다.
모듈을 사용하면 다음과 같은 장점이 있습니다.

  • 유지보수의 용이성
  • 전역 스코프 오염을 방지
  • 재사용성 향상

첫 번째 장점은 모듈을 사용하면 유지보수가 쉬워집니다. 공통기능을 모듈로 정의해 사용하면 애플리케이션의 전체적인 수정 없 모듈의 수정이나
교체만으로도 코드를 효과적으로 수정할 수 있습니다.

두 번째 장점은 모듈은 전역 스코프 오염(global scope pollution)을 방지합니다. 전역 스코프틑 전역 이름 공간을 가지므로 변수의 이름이나
함수 이름을 중복해 선언 할 수 없습니다. 그런데 변수나 함수등을 파일 내부에 한정해 모듈로 선언하면 이름 공간이 파일 단위로 제한되며 전역 이름 공간을 침범하지 않습니다.

세 번째 장점은 모듈을 사용하면 재사용성이 향상 됩니다. 모듈화를 잘 해두면 현재의 프로젝트뿐 아니라 다른 프로젝트에도 공유해 재사용할 수 있습니다.

모듈러 프로그래밍을 위한 접근

모듈러 프로그래밍은 프로그램의 설계 기술로 모듈의 분리와 모듈의 손쉬운 교체에 관심이 있습니다. 상호 교환 가능한 모듈을 정의할 수 있어야 합니다.
모듈러 프로그래밍의 첫 번째 과정은 모듈을 식별, 두번째는 모듈을 분리, 세번째 과정을 모듈을 공개 하는 것입니다.
모듈을 외부로 공개함으로써 프로젝트 내에 존재하는 특정 파일에서 호출해 사용할 수 있게 됩니다.

내부 모듈과 외부 모듈

내부 모듈의 네임스페이스는 여러 파일에 걸쳐 하나의 이름 공간을 공유하지만, 외부 모듈은 파일 모듈 파일마다 이름 공간이 정해집니다.

내부 모듈

내부 모듈인 네임스페이스는 전역 이름 공간과 분리된 네임스페이스 단위의 이름 공간입니다. 참조할 때는 별도의 참조문을 선언하지 않아도 됩니다.
네임스페이스는 전역 스코프에 속하지만 전역 스코프와 독립된 이름공간이라는 점.

외부 모듈

export로 선언한 모듈을 외부 모듈이라 합니다. 흔희 말하는 모듈은 외부 모듈을 가리킵니다.
외부 모듈의 이름 공간은 파일 내로 제한되므로 파일이 다르다면 외부 모듈의 이름이 같아도 괜찮지만 export를 생략해 외부 모듈로 선언하지
않으면 전역 스코프의 이름 공간을 공유해 이름 충돌이 발생합니다.

네임스페이스

네임스페이스는 하나의 독립된 이름 공간을 만들고 여러 파일에 걸쳐 하나의 이름 공간을 공유 할 수 있습니다.
namespace와 module은 키워드는 다르지만, 역할과 기능상 차이가 없습니다.

  • 타입스크립트 1.5 버전 이후에 내부 모듈을 선언 할 때는 module 대신에 namespace로 선언해야 합니다.

내부 모듈은 자바스크립트로 컴파일 될때 즉시 실행 함수로 변환됩니다.

.js
1
2
3
(function (hello) {
/* 내부 모듈의 이름 공간 */
})(Hello || (Hello = {}));

즉시 실행 함수에서 hello 매개변수는 함수 외부에서 함수 내부의 이름 공간에 접근 할수 있게 하는 역할을 합니다.

프로젝트 단위 컴파일을 수행하지 않고 특정 파일만을 컴파일할 때는 같은 네임스페이스라도 외부에 선언된 네임스페이스를 인식할 수 없습니다.
그럴땐 명시적으로 참조 경로를 선언해 줘야 합니다.

네임스페이스 모듈

네임스페이스는 export를 이용해 모듈로 선언할 수 있습니다. 모듈로 선언되 네임스페이스는 import 문을 이용해 JS로 컴파일된 뒤에도 명시적으로
모듈 호출(import문, require 함수 등)을 할 수 있습니다.

네임스페이스의 이름 확장

네임스페이스 이름은 알파벳의 소문자와 대문자를 사용해 다음처럼 선언합니다.

1
namespace Animal{...}

네임스페이스 이름은 예외로 점(.)을 허용합니다. 점을 이용하면 네임스페이스 간의 이름 계층을 만드는 효과가 있습니다.
논리적인 이름 순서상 상위 이름은 앞에 선언돼야 하고 하위 이름은 상대적으로 뒤에 선언돼야 합니다.

브라우저에서 네임스페이스의 모듈 호출

여러 타입스크립트 파일을 컴파일할 때 런타임시에 타입스크립트 파일을 인식하려면 가장 단순한 방법으로 out옵션으로 타입스크립트 파일을 컴파일하며 됩니다.
그런데 브라우저 상황은 다소 다릅니다. 파일을 하나로 합치지 않고 타입스크립트 파일을 개별적으로 컴파일하고 import문을 사용하지 않더라고 브라우저가
호출된 것처럼 인식합니다.

모듈 선언과 모듈 임포트

타입스크립트 1.5부터는 ES2015 모듈 시스템을 지원합니다.
ES2015 모듈 시스템은 export나 import 제한자를 통해 모듈을 선언하고 호출 할 수 있습니다. 모듈은 export로 선언해야 외부로 노출됩니다.
export 키워드와 모듈 이름을 함께 선언해 모듈을 노출하는 방식을 명명된 내보내기(named exports)라고 합니다. 외부로 노출된 모듈은 import 키워드를 이용해 가져올 수 있습니다.

1
2
3
4
5
export interface Information {...}
export function add(a: number, b: number) {...}

import * as m from './module';
import { add, sub } from './calc';

여러 모듈을 함께 export하기

변수나 배열 등도 모듈로 선언할 수 있습니다. 모듈을 개벌적으로 선언해도 되지만 모듈을 선언할 때마다 export 키워드를 붙이는건 불편합니다.
이러한 점을 개선하기 위해 여러 모듈을 함께 export 해주면 편리합니다.
만약 모듈로 선언할 대상이 인터페이스를 사용하는 함수일 때는 함수가 인터페이스와 의존관계가 있으므로 함수와 인터페이스를 함께 export해야 합니다.

1
2
3
4
5
6
let ver = '1.0';
let author: string = 'happy';
let extension = ['jpg', 'bmp', 'png'];
let display = () => 'hello world';

export { ver, author, extension, display };

가져온 모든 모듈을 재노출

재노출할 모듈이 많아 구체적인 이름을 열거하기가 불편할 때는 “export * from …”문법을 이용합니다. *은 모든 모듈을 의미합니다.
모듈 파일을 재노출할 때 모든 외부 모듈을 의미하는 *에 대한 별칭이 없으므로 임포트 할 때는 as 키워드를 이용해 별칭을 추가해야 합니다.

1
2
3
4
export * from  './module1';
export * from './module2';

import * as m from './module';

모듈 파일에서 재노출한 전체 모듈을 참조할 수 있도록 m이라는 별칭을 추가 별칭 m은 재노출된 모듈에 접근할 수 있는 식별자로 이용됩니다.

네임스페이스로 감싸서 재노출

네임스페이스는 독립된 이름 공간이며 export를 이용해 모듈로 선언할 수 있습니다.

1
export namespace CarInfo{...}

export로 선언하며 다른 파일에서 임포트할 수 있는 모듈이 됩니다. 네임스페이스는 이름공간을 정의해 하위에 여러 모듈을 포함할 수 있는 특성이 있습니다.
이 때문에 네임스페이스를 기존에 흩어졌던 모듈을 다시 용도에 맞게 감싸서 재노출할 용도로 사용할 수 있습니다.

디폴트 모듈

타입스크립트 1.5가 발표되기 전에는 모듈을 선언할 때 export-equals 문으로 할당 했고, 모듈을 호출 할 때는 import-equals 문으로 임포트했습니다.

1
2
export = validator
import Validator = require("validator");

타입스크립트1.5에서는 import-equals 문과 export-equals 문 대신 다른 형태의 키워드를 이용합니다.

1
2
export default {...}
import Validator from './module';

이외에도 모듈을 선언하는 방법은 여럿 있습니다. 익명 함수의 디폴트 모듈선언, 기명함수의 디폴트 함수선언, 클래스 선언

1
2
3
export default function(x: number) {...}
export default function add(x: number) {...}
export default class Hello {...}

디폴트 모듈은 default 키워드를 사용해서 선언합니다. 디폴트 모듈의 특성은 모듈파일에 최대 1개 까지만 선언할 수 있습니다.
default 키워드를 두 번 사용하면 컴파일 에러가 발생합니다.
임포트할 디폴트 모듈은 {}에 선언하면 안 되고 {}가 없이 선언해야 합니다.

1
import p, {hello} from './defaul';

이처럼 디폴트 모듈과 일반 모듈을 함께 임포트할 때는 디폴트 모듈은 이름만 선언하고 일반 모듈은 {} 내부에 모듈 이름을 선언해야 합니다.

모듈 시스템

모듈 로더는 모듈 파일에 선언된 모듈을 실행할수 있습니다. 브라우저에서 동작하는 모듈로더는 느린로딩의 방식으로 모듈 파일을 가져와 모듈을 실행합니다.
타입스크립트에서는 모듈을 정의하거나 호출할 때 ES2015 모듈을 이용합니다. 타입스크립트는 자바스트립트로 컴파일돼 실행 합니다.
이때 ES2015 모듈이 표준이지만 더 많은 브라우저에서 지원하게 하고자 ES5 표준으로 컴파일 하되 ES2015 모듈은 모듈 로더를 통해 호출 할 수 있습니다.

모듈 로더마다 지원하는 명세가 다소 다릅니다. 최근 나오는 모듈 로더는 대체로 CommonJS 와 AMD 모듈 형식을 기본으로 지원합니다.

댓글

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×