Namespace & ES Module

김동현·2022년 6월 11일
0

TypeScript

목록 보기
17/18
post-thumbnail

타입스크립트 모듈 시스템

타입스크립트 파일은 분리가 되어 있더라도 모든 파일들을 하나의 전역 스코프로 취급합니다.

위 그림처럼 index.ts 파일에서 전역 변수 a를 선언하고, app.ts 파일에서도 전역 변수 a를 선언한 경우 중복된 선언으로 에러가 표시되는 것을 확인할 수 있습니다.

이는 파일들이 분리되어 있더라도 모두 하나의 전역 스코프를 공유하기 때문입니다.

이를 방지하기 위해서는 파일을 모듈로서 인식하도록 만들기 위해 export 구문을 작성하여 모듈 파일로 인식하도록 할 수 있습니다.

위 그림에서 index.ts 파일 내 export {};를 작성하여 모듈 파일로 인식되도록 하였습니다.

모듈 파일은 자체적인 파일 스코프를 갖기 때문에 더이상 전역 스코프를 공유하지 않게 됩니다.

타입스크립트 파일 내 importexport 구문이 존재한다면 해당 파일은 모듈 파일로 인식됩니다.

내부 모듈과 내부 모듈

타입스크립트에서 모듈은 내부 모듈과 외부 모듈이 존재합니다.

외부 모듈

외부 모듈이란 파일 내 export 문을 갖는 파일을 의미하며, 외부 모듈은 import 문을 사용하여 모듈을 불러옵니다.

exportimport 문이 존재하는 타입스크립트 파일은 외부 모듈로 인식되며, 각 파일마다 자체적인 전역 스코프를 생성하기 때문에 전역 스코프에 영향을 주지 않습니다.

내부 모듈

내부 모듈은 타입스크립트의 Namespace를 말합니다. Namespace는 외부 모듈과 달리 파일마다 자체적인 스코프를 생성하지 않고, 하나의 전역 스코프를 사용합니다.

이때 하나의 전역 스코프 내에서 스코프 역할을 하는 그룹을 Namespace라고 합니다. 즉, 하나의 파일 내 Namespace들로 스코프를 구분하도록 합니다.

위 그림에서 index.ts와 app.ts에서 선언한 변수 a가 중복되어있다고 에러가 표시되는 것을 보아 전역 스코프는 여전히 공유된다는 점을 알 수 있습니다.

그리고 Index 네임스페이스에서 선언한 변수 a는 더이상 전역 스코프의 변수가 아니게되며, App 네임스페이스의 변수 a 또한 전역 스코프의 변수가 아닌 것을 확인할 수 있습니다.

네임스페이스 자체를 하나의 독립된 스코프로 볼 수 있습니다. 그러므로 동일한 이름의 네임스페이스 내에서는 중복된 식별자 선언같은 것들 또한 불가능합니다.

Namespace

namespace 생성

네임스페이스를 사용하기 위해서는 tsconfig.json 파일에서 "outFile"옵션을 사용해야 하며 "outFile" 옵션을 사용하기 위해서는 "module" 옵션의 값이 "amd"또는 "system"일 때 사용할 수 있습니다.

네임스페이스는 namespace 이름 {,,,}으로 사용합니다. 즉, {,,,}에 작성된 것들은 같은 이름의 네임스페이스에서 공유가 됩니다.

그리고 공유할 데이터 앞에 export 키워드를 작성해주어야 합니다.

위 그림처럼 App 이라는 네임스페이스 이름을 갖는다면 export된 Draggable, DragTarget 인터페이스를 공유할 수 있습니다.

namspace import 하기

다른 파일, 분리된 파일에서 import하고자 한다면 /// <reference path="파일경로" />을 작성하여 import할 namespace가 선언된 파일을 경로를 작성해줍니다.

그리고 동일한 이름의 namespace를 선언하고 내부에서는 export된 데이터에 접근할 수 있습니다.

위 그림처럼 index.ts의 Index 네임스페이스를 app.ts 파일에서 import하여 식별자를 참조할 수 있습니다.

ES6 Module

자바스크립트의 ES6 Module을 이용하는 방법도 존재합니다.
즉, importexport를 사용하여 모듈 시스템을 사용할 수 있습니다.

이때 주의해야 할 점으로 import 할 때 파일의 확장자가 ".js"이어야 합니다. 이는 컴파일 결과물인 자바스크립트 파일을 import해야하기 때문입니다.

위 코드처럼 다른 파일에서 사용될 것들을에 export 작성해줍니다.

그리고 export한 것을 사용할 파일에서는 위 코드처럼 import 구문을 작성하여 export된 것을 선택적으로 가져올 수 있습니다.


tsconfig.json에서는 "module" 옵션 값을 "ES2015"이상 버전을 작성합니다. 즉, ES6 Module을 지원하는 버전을 작성해주어야 합니다.

또한 "outFile" 옵션을 사용중이라면 해당 옵션을 사용하지 않도록 주석처리를 해주어야 합니다. outFile 옵션의 경우 module 옵션값이 amd나 system일 때 사용되는 옵션입니다.

declare

"declare" 키워드는 타입스크립트 컴파일러에게 해당 변수나 함수가 이미 존재하다고 알려주는 키워드입니다.

위 코드는 다른 파일에 선언된 전역 변수인 GLOBAL_VALUE 변수에 대해서 타입스크립트가 찾을 수 없다는 에러를 표시하고 있습니다.

이때 "declare" 키워드를 사용하여 컴파일러에게 해당 변수가 존재한다고 알려줌으로써 발생하는 에러를 해결할 수 있습니다.

@types Library

선언 파일(*.d.ts)

타입스크립트 파일 내 자바스크립트 외부 라이브러리를 import하여 사용하는 경우 컴파일 에러가 발생하며 자동 완성이나 정적 검사도 해주지 않습니다.

컴파일 에러가 발생하는 이유는 타입스크립트 컴파일러가 해당 자바스크립트 라이브러리의 선언(declaration) 파일을 찾을 수 없기 때문입니다.

타입스크립트는 자바스크립트 파일을 이해하지 못하므로 자바스크립트 파일을 타입스크립트로 변환해주는 "선언 파일"이 존재해야 합니다.

선언 파일은 "*.d.ts" 확장자를 갖고 있으며 실제 로직이 아니라 "타입스크립트 컴파일러에게 지시할 내용"을 담고 있는 파일입니다.
결국 기존 자바스크립트 파일을 타입스크립트로 변환하기 위해 타입만 따로 작성된 파일입니다.

@types 라이브러리

타입스크립트로 변환해주는 선언 파일을 갖고 있지 않는 자바스크립트 라이브러리로 작업을 한다면 "@types/패키지이름" 패키지를 설치하여 해결할 수 있습니다.

대부분 외부 라이브러리들은 @types 패키지가 존재합니다. DefinitelyTypes에 공개된 타입 선언을 확인할 수 있습니다.

@types 라이브러리는 타입 정보만을 포함하고 있으며 구현체는 포함하지 않습니다. 타입 정보는 런타임에 존재하지 않으며 사용하지도 않기 때문에 일반적으로는 devDependencies에 의존성을 포함시킵니다.

실제 구현체는 자바스크립트 라이브러리에 존재하며 이는 dependencies에 포함되어 있습니다.

devDependencies는 현재 프로젝트를 개발하고 테스트 하는 데 사용되지만 런타임에는 필요 없는 라이브러리들이 포함됩니다.

profile
Frontend Dev

0개의 댓글