* 타입스크립트 프로그래밍(보리스 체르니, 프로그래밍 인사이트)를 읽고 요약 정리한 글입니다.
캡슐화 방법들
- 함수
- 자료구조 (객체, 리스트 등)
- 클래스
- 네임스페이스로 구분된 유틸리티 형태 (별도의 데이터베이스나 저장소에 보관)
(클래스나 유틸리티가 많아지면 패키지로 묶어서 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) 타입스크립트 프로그래밍, 보리스 체르니, 프로그래밍 인사이트
'TypeScript' 카테고리의 다른 글
[타입스크립트 프로그래밍] 9장 프론트엔드 프레임워크와 백엔드 프레임워크 (0) | 2023.06.09 |
---|---|
[타입스크립트 프로그래밍] 7장 에러처리 (2) | 2023.06.07 |
[타입스크립트 프로그래밍] 5장 클래스와 인터페이스 (2) | 2023.05.31 |
댓글