본문 바로가기
TypeScript

[타입스크립트 프로그래밍] 10장 Namespaces.Modules

by 복숭아 우유씨 2023. 6. 9.

* 타입스크립트 프로그래밍(보리스 체르니, 프로그래밍 인사이트)를 읽고 요약 정리한 글입니다.

캡슐화 방법들

 - 함수

 - 자료구조 (객체, 리스트 등)

 - 클래스

 - 네임스페이스로 구분된 유틸리티 형태 (별도의 데이터베이스나 저장소에 보관)

   (클래스나 유틸리티가 많아지면 패키지로 묶어서 NPM으로 발행할 수도 있음)

 

자바스크립트의 모듈

 - 컴파일러의 모듈 해석, 빌드 시스템의 모듈 해석, 런타임에 모듈이 응용프로그램으로 로드되는 방법이 모두 별도의 프로그램으로 처리 

 - CommonJS, ES2015의 모듈 표준 등장으로 세 프로그램의 연동이 쉬워짐

 - 웹팩등의 번들러로 내부적으로 추상화해서 실행해 줌

 - 10장 내용: 컴파일러의 모듈 해석(타입스크립트의 모듈 해석과 컴파일 방법)

 

 

10.1 가볍게 살펴보는 자바스크립트 모듈의 역사

연도 사건
1955 자바스크립트는 모듈 시스템 지원 X
- 모든 것을 전역 네임스페이스에서 정의 
   : 응용 프로그램의 확장 어려움, 변수명 고갈, 변수명 충돌, 외부에서 사용 가능 기능 구분 어려움(각 모듈의 API를 명시적으로 노출하지 않을 경우)

  모듈 흉내내기 (위의 상황 해결을 위해 사용한 방법들)
 - 객체 이용, IIFE를 전역 window에 할당
 - 단점: 프로그램 커질수록 브라우저 느려짐
  모듈 로더 (브라우저 느려짐 해결 방안)
- 첫 페이지 로딩된 다음 자바스크립트를 lazy하고 비동기적으로 로딩
- 필수 조건
  - 모듈 캡슐화 필수 (의존성 확보하다가 페이지 망가질 수 있음)
  - 모듈간의 의존성 명시적이여 함 (어떤 모듈 필요하고, 어떤 순서로 로딩되는지 알기 위함)
  - 앱내에서 고유 식별자 가져야 함 (어떤 모듈 로딩해야 할지 안정적으로 지정하기 위함)
2008 AMD 모듈 표준이 인기(웹)
 - Dojo, RequiredJS가 추진
 - CommonJS와 같은 기능 제공 (자체 빌드 시스템 제공)
2009 NodeJS 개발, 자체 모듈 시스템 추가함 (CommonJS 모듈 표준)
 - 필수 조건 만족 가능
2011 Browserfy 출시로 CommonJS가 거의 표준으로 자리잡음
 - 프론트엔드 엔지니어도 CommonJS 사용 가능해짐
2015 ES2015에서 표준  import/export 제공함
 - CommonJS의 문제점 해결 (require 호출은 반드시 동기 방식이여야 함, 모듈 해석 알고리즘이 웹에 적합하지 않음, 정적 분석 불가능 등)

ES2015 표준에서 타입스크립트의 역할

1) 모듈 코드 소비하고 익스포트할 수 있는 여러 방식 추가

  - 필요 이유: 표준 제정 시점에는 환경에 맞는 타입으로 컴파일 필요(표준 지원하지 않는 런타임 있으므로)

  - 전역 선언, 표준 ES2015의 import/export, CommonJS의 import등

2) TSC 빌드 시스템으로 다양한 환경에 맞는 모듈 컴파일 가능

 

10.2 import, export

타입스크립트에서는 ES2015의 import, export 사용이 바람직함

 1) 자바스크립트와 비슷한 모습

  - default export 지원

  - 와일드카드 임포트(*) 이용하여 모든 것 임포트 가능

  - 일부 또는 전체 다시 익스포트 가능

 2) 타입과 인터페이스도 export 가능함

  - 타입, 값은 별개의 네임스페이스에 존재하므로 둘을 하나의 이름으로 export가능 (사용할 때 추론)

// g.ts
export let x = 3;
export type x = { y: string };

// h.ts
import { X } from './g'

let a = X + 1; // X는 값 X로 추론됨
let b: X = { y: 'z' } // X는 타입 X로 추론됨

- 모듈 경로 : 파일 시스템의 파일명 ( 모듈 경로로 파일 시스템에서의 위치와 모듈 연관 가능)

 - 모듈로더가 모듈명을 파일로 해석할 수 있도록 레이아웃 알고 있어야 함

 

10.2.1 동적 임포트

 

첫 렌더링 지연 문제

 - 응용 프로그램 커지면서 시간 점점 길어짐, 네트워크 병목 생기기 쉬운 프론트엔드 응용 프로그램에서 많이 발생

 - 해결

   1) 코드 분할(splitting) 

    - 자바스크립트 파일을 여러개 생성하여 나누어 저장하는 방법

    - 병렬 로딩 가능

   2) lazy loading

    - 코드가 필요할 때 로딩하는 방법

    - 동적 임포트라는 개념으로 공식화

// 동적 임포트 사용 예
let locale = await import('locale_us-en')

 

동적임포트 안전하게 하기 (둘중 하나 사용)

 1) 문자열: 변수 할당X, import에 문자열 리털로 직접 제공

 2) import 에 표현식 전달하고 모듈 시그니처 직접 명시 - 모듈 정적 임포트하지만 타입위치에만 사용 -> 타입 안전성/동적 임포트 가능

 

10.2.2 CommonJS와 AMD 코드 사용하기

- 단순히 이름으로 import 가능

- default export 불가 -> 필요시 와일드카드 임포트 사용 

// 와일드카드 사용 예
import * as fs from 'fs'
fs.readFile('some/file.txt')

// tsconfig.json esModuleInterop 설정을 true로 설정할 경우, 더 자연스러운 사용 가능
import fs from 'fs'
fs.readFile('some/file.txt')

 

10.2.3 모듈 모드 vs. 스크립트 모드

타입스크립트 파일 파싱

  모듈 모드 스크립트 모드
결정기준: import나 export 포함하는가? O X
다른 파일 코드 가져올 때 import 혹은 import()  
다른 파일에 코드 제공할 때 export  
서드파티 UMD 모듈
(CommonJS, RequiredJS, 브라우저 전역 중 환경이 지원하는 기능을 선택한다)
먼저 import 해야함 먼저 명시적 임포트 필요 없음
바로 사용 가능
사용 사례 대부분의 상황 - 모듈 시스템이 전혀 없고, HTML파일에 <script />태그로 직접 포함시킬 브라우저 코드를 빠르게 프로토타이핑 해보는 상황
- 타입 선언을 만드는 상황
 

 

10.3 네임스페이스

namespace

- 코드를 캡슐화할 수 있는 수단인 키워드

- 타입스크립트 지원 O

- 파일시스템내 파일 구성 방식 등의 세부사항 추상화

- 짧고 간편한 네임스페이스로 접근하게 해줌

- 코드 캡슐화 수단으로 권장되진 않음 (모듈 사용을 권장함)

 

사용시 유의사항 및 특징

// Get.ts
namespace Network {
  export function get<T>(url: string): Promise<T> {
    // ...
  }
  export namespace TCP { // 중첩된 구조, 호출시 Network.TCP.listenOn 형태로 호출 가능
  	listenOn(port: number): Collection {
    	// ...
    }
  }
  // ...
}

// App.ts
namespace App {
  Network.get<GitRepo>("https://api.github.com/repos/Microsoft/typescript");
}

- 반드시 이름이 있어야 한다.

- 함수, 변수, 타입, 인터페이스, 다른 네임스페이스를 익스포트할 수 있다.

- namespace 블록안의 모든 코드는 명시적으로 익스포트하지 않는 한 외부에서 볼 수 없다.

- 중첩된 구조도 쉽게 만들 수 있다. (모듈이 점점 커져서 서브 모듈로 쪼개야 할 때 활용 가능)

- 네임스페이스도 merge가능하므로 파일 분리하여 관리 가능

- 별칭(alias) 적용 가능하나 별칭에서는 구조분해할당 지원 하지 않음

 

10.3.1 충돌

- 같은 이름 익스포트하면 충돌 발생

- 단, 오버로드된 앰비언트 함수 선언(overloaded ambient function declaration)에는 이름 충돌 금지 규칙 적용되지 않음

 

10.3.2 컴파일된 출력

- tsconfig.json의 module 설정에 영향 받지 않음

- 항상 전역 변수로 컴파일됨

 

10.4 선언합치기

타입스크립트가 제공하는 merge 기능

 1)  값과 타입 (컴패니언 객체 패턴 참고)

 2) 여러 네임스페이스를 하나로

 3) 여러 인터페이스를 하나로

 

- 타입스크립트는 다른 종류의 이름을 합치는 다양한 동작을 제공 -> 온갖 종류의 패턴 표현 가능

 


Reference

1) 타입스크립트 프로그래밍, 보리스 체르니, 프로그래밍 인사이트

댓글