TypeScript 리드·아키텍트 프레임워크 면접

TypeScript 리드 · 아키텍트 (10년+) 프레임워크 5문항 조회수 8 · 2026-09-16 (수) 22:11:31
1 TypeScript 컴파일러
Hard

Q. TypeScript 컴파일러의 Program, TypeChecker, Emitter의 역할과 상호작용을 설명하고, 대규모 모노레포 환경에서 증분 컴파일(Incremental Compilation)과 Project References를 활용한 빌드 최적화 전략을 제시해주세요. 특히 tsc --build 모드의 내부 동작 원리와 캐싱 메커니즘, 그리고 조직 차원에서 빌드 시간을 단축하기 위한 프로젝트 구조 설계 원칙을 포함해주세요.

TypeScript 컴파일러의 3단계 파이프라인과 .tsbuildinfo 파일의 역할을 중심으로 생각해보세요.

A. 모범답안

TypeScript 컴파일러는 Program(파일 로드 및 의존성 그래프 구성), TypeChecker(타입 검증 및 타입 정보 생성), Emitter(JavaScript 코드 생성)의 3단계로 동작합니다. 증분 컴파일은 .tsbuildinfo 파일에 이전 빌드의 해시와 타입 정보를 저장하여 변경된 파일만 재컴파일하며, Project References는 프로젝트 간 의존성을 명시적으로 선언해 병렬 빌드와 선택적 빌드를 가능하게 합니다. 대규모 모노레포에서는 도메인별로 프로젝트를 분리하고, 공유 라이브러리는 별도 프로젝트로 구성하며, composite: true와 declarationMap을 활성화해 타입 정보만으로 의존성을 해석하도록 설계합니다. CI 환경에서는 변경된 프로젝트와 그 의존자만 빌드하는 선택적 빌드 전략을 구현하고, 빌드 캐시를 공유 스토리지에 저장해 재사용률을 높입니다. 또한 declaration 파일만 변경된 경우 하위 프로젝트의 재컴파일을 스킵하는 최적화를 적용하여 전체 빌드 시간을 최소화합니다.

핵심 포인트
  • • Program, TypeChecker, Emitter의 역할 분리와 파이프라인 동작
  • • .tsbuildinfo를 활용한 증분 컴파일 메커니즘
  • • Project References와 composite 옵션을 통한 프로젝트 간 의존성 관리
  • • 도메인 기반 프로젝트 분리 및 선택적 빌드 전략
답변에 넣으면 좋은 키워드
Program TypeChecker Emitter Project References composite tsbuildinfo 증분 컴파일 declarationMap
실무에서는

수십 개의 패키지를 가진 모노레포에서 전체 빌드 시간을 30분에서 5분으로 단축하는 프로젝트 구조 개편에 활용됩니다.

Follow-up 질문

SWC나 esbuild 같은 대체 컴파일러로 전환을 고려할 때, TypeScript 공식 컴파일러 대비 어떤 트레이드오프가 발생하며, 어떤 상황에서 전환을 권장하시겠습니까?

2 고급 타입 시스템
Hard

Q. TypeScript의 Mapped Types, Conditional Types, infer 키워드를 조합하여 함수 시그니처로부터 파라미터와 리턴 타입을 추출하고 변환하는 고급 유틸리티 타입을 설계하는 방법을 설명해주세요. 특히 Variance(공변성, 반공변성)의 개념이 함수 타입 추론에 미치는 영향과, 이를 활용한 타입 안전한 미들웨어 체이닝 시스템 설계 방안을 제시해주세요.

함수 파라미터는 반공변성(contravariance)을, 리턴 타입은 공변성(covariance)을 가진다는 점을 고려하세요.

A. 모범답안

Mapped Types는 기존 타입의 각 속성을 순회하며 변환하고, Conditional Types는 타입 조건에 따라 분기하며, infer는 조건부 타입 내에서 타입 변수를 추론합니다. 함수에서 파라미터는 반공변적이므로 더 넓은 타입을 받을 수 있고, 리턴 타입은 공변적이므로 더 좁은 타입을 반환할 수 있습니다. 미들웨어 체이닝에서는 각 미들웨어가 컨텍스트 객체를 확장하는 패턴을 구현하는데, 이전 미들웨어의 리턴 타입이 다음 미들웨어의 입력 타입으로 전파되도록 설계합니다. infer를 사용해 함수 시그니처에서 파라미터와 리턴 타입을 추출하고, Mapped Types로 컨텍스트 확장을 표현하며, 재귀적 Conditional Types로 미들웨어 배열 전체의 최종 타입을 계산합니다. 이를 통해 컴파일 타임에 미들웨어 순서 오류나 타입 불일치를 감지하고, IDE에서 각 단계의 컨텍스트 타입을 정확히 추론받을 수 있습니다.

핵심 포인트
  • • Mapped Types, Conditional Types, infer의 조합을 통한 타입 변환
  • • 함수의 공변성과 반공변성 이해 및 활용
  • • 미들웨어 체이닝에서 컨텍스트 타입 전파 메커니즘
  • • 재귀적 타입 정의를 통한 체인 전체의 타입 안정성 보장
답변에 넣으면 좋은 키워드
Mapped Types Conditional Types infer 공변성 반공변성 Variance 타입 추론 미들웨어
실무에서는

Express나 Koa 스타일의 미들웨어 프레임워크를 타입 안전하게 구현하거나, 복잡한 API 클라이언트의 타입 시스템을 설계할 때 활용됩니다.

Follow-up 질문

TypeScript 5.0 이상에서 도입된 const 타입 파라미터와 satisfies 연산자가 이러한 고급 타입 설계에 어떤 개선을 가져오는지 설명해주세요.

3 데코레이터와 메타프로그래밍
Medium

Q. TypeScript의 Decorator(실험적 기능 및 Stage 3 표준)를 활용한 메타프로그래밍 패턴과, 런타임 리플렉션을 위한 reflect-metadata 라이브러리의 동작 원리를 설명해주세요. 특히 NestJS나 TypeORM 같은 프레임워크에서 데코레이터 기반 의존성 주입과 ORM 매핑이 어떻게 구현되는지, 그리고 프로덕션 환경에서 데코레이터 사용 시 고려해야 할 성능 및 디버깅 이슈를 포함해주세요.

데코레이터는 클래스, 메서드, 속성에 메타데이터를 부착하고, reflect-metadata는 이를 런타임에 조회하는 메커니즘을 제공합니다.

A. 모범답안

TypeScript 데코레이터는 클래스, 메서드, 프로퍼티, 파라미터에 적용되는 함수로, 컴파일 시점에 메타데이터를 부착하고 런타임에 동작을 수정합니다. reflect-metadata는 Reflect.metadata API를 통해 타입 정보와 커스텀 메타데이터를 저장하고 조회하며, emitDecoratorMetadata 옵션을 활성화하면 TypeScript가 자동으로 타입 정보를 메타데이터로 생성합니다. NestJS는 @Injectable 데코레이터로 클래스를 DI 컨테이너에 등록하고, 생성자 파라미터의 타입 메타데이터를 읽어 의존성을 자동 주입하며, TypeORM은 @Entity와 @Column 데코레이터로 클래스-테이블 매핑 정보를 수집해 런타임에 쿼리를 생성합니다. 프로덕션에서는 데코레이터 실행이 모듈 로딩 시점에 발생해 초기화 시간이 증가할 수 있고, 스택 트레이스가 복잡해져 디버깅이 어려우며, 트리 쉐이킹이 제한될 수 있으므로 데코레이터 사용 범위를 최소화하고 명시적 설정 방식과 병행하는 것이 권장됩니다.

핵심 포인트
  • • 데코레이터의 실행 시점과 메타데이터 부착 메커니즘
  • • reflect-metadata를 통한 런타임 타입 정보 조회
  • • 의존성 주입과 ORM 매핑에서의 데코레이터 활용 패턴
  • • 프로덕션 환경에서의 성능 및 디버깅 고려사항
답변에 넣으면 좋은 키워드
Decorator reflect-metadata emitDecoratorMetadata 의존성 주입 메타프로그래밍 NestJS TypeORM
실무에서는

엔터프라이즈 애플리케이션에서 횡단 관심사(로깅, 인증, 트랜잭션)를 선언적으로 처리하고, 보일러플레이트 코드를 줄이는 프레임워크 설계에 활용됩니다.

Follow-up 질문

TC39 Decorator Proposal Stage 3의 새로운 데코레이터 문법이 기존 TypeScript 실험적 데코레이터와 어떻게 다르며, 마이그레이션 시 주의할 점은 무엇입니까?

4 모듈 시스템과 번들링
Hard

Q. TypeScript 프로젝트에서 CommonJS, ES Modules, UMD의 차이와 상호운용성 이슈를 설명하고, module과 moduleResolution 컴파일러 옵션이 모듈 해석에 미치는 영향을 분석해주세요. 특히 Node.js의 ESM 지원, package.json의 exports 필드, 조건부 export를 활용한 Dual Package 전략과, 라이브러리 개발 시 다양한 환경(Node.js, 브라우저, 번들러)을 지원하기 위한 빌드 구성 방안을 제시해주세요.

module 옵션은 출력 형식을, moduleResolution은 import 구문 해석 방식을 결정하며, 이 둘의 조합이 중요합니다.

A. 모범답안

CommonJS는 require/module.exports를 사용하는 동기적 모듈 시스템이고, ES Modules는 import/export를 사용하는 정적 분석 가능한 비동기 모듈 시스템이며, UMD는 두 환경을 모두 지원하는 래퍼 패턴입니다. TypeScript의 module 옵션은 출력 JavaScript의 모듈 형식을 결정하고, moduleResolution은 import 경로를 해석하는 알고리즘(node, node16, bundler 등)을 지정합니다. Node.js ESM은 .mjs 확장자나 package.json의 type: module을 요구하며, exports 필드로 진입점을 명시하고 조건부 export(import, require, types)로 환경별 파일을 제공합니다. Dual Package 전략에서는 ESM과 CJS 버전을 모두 빌드하고, exports 필드에서 import 조건에는 .mjs를, require 조건에는 .cjs를 매핑하며, types 조건으로 .d.ts 파일을 제공합니다. 라이브러리는 tsc로 타입 정의를 생성하고, esbuild나 rollup으로 다양한 형식의 번들을 생성하며, sideEffects: false를 설정해 트리 쉐이킹을 최적화하고, 브라우저 환경을 위한 폴리필 제공 여부를 결정합니다.

핵심 포인트
  • • CommonJS, ES Modules, UMD의 특성과 상호운용성
  • • module과 moduleResolution 옵션의 역할과 조합
  • • package.json exports 필드와 조건부 export를 통한 Dual Package 구성
  • • 다양한 환경을 지원하는 라이브러리 빌드 전략
답변에 넣으면 좋은 키워드
CommonJS ES Modules moduleResolution exports Dual Package 조건부 export 트리 쉐이킹
실무에서는

오픈소스 라이브러리를 배포하거나, 모노레포에서 여러 환경을 타겟으로 하는 패키지를 관리할 때 필수적인 설정입니다.

Follow-up 질문

TypeScript 5.0의 bundler moduleResolution 옵션이 기존 node16과 어떻게 다르며, 어떤 프로젝트에서 bundler 옵션을 선택해야 합니까?

5 타입 시스템 설계 원칙
Medium

Q. 대규모 TypeScript 애플리케이션에서 타입 복잡도가 증가하면서 컴파일 시간이 길어지고 IDE 반응 속도가 느려지는 문제가 발생했습니다. 타입 시스템의 성능을 개선하기 위한 설계 원칙과, 과도한 타입 추론이나 복잡한 재귀적 타입이 컴파일러에 미치는 영향을 분석해주세요. 특히 타입 단순화, 명시적 타입 어노테이션, 타입 별칭 활용 등 실무적 최적화 기법을 제시해주세요.

TypeScript 컴파일러는 타입 추론 시 재귀 깊이와 유니온 타입의 크기에 제한이 있으며, 이를 초과하면 성능이 급격히 저하됩니다.

A. 모범답안

TypeScript 컴파일러는 타입 추론 시 재귀적 타입 확장과 유니온 타입 분배를 수행하는데, 깊이가 50을 초과하거나 유니온 멤버가 수백 개에 달하면 기하급수적으로 느려집니다. 타입 복잡도를 줄이기 위해서는 재귀적 Conditional Types를 단순 Mapped Types로 대체하고, 과도한 제네릭 중첩을 피하며, 큰 유니온 타입은 타입 별칭으로 분리하여 재계산을 방지합니다. 함수 시그니처에 명시적 리턴 타입을 선언하면 함수 본문의 타입 추론 범위를 제한해 컴파일 속도가 향상되고, 외부 라이브러리의 복잡한 타입은 간단한 인터페이스로 래핑해 격리합니다. IDE 성능 개선을 위해서는 tsconfig의 skipLibCheck를 활성화해 node_modules 타입 검사를 생략하고, 프로젝트를 논리적 단위로 분리해 타입 체크 범위를 최소화하며, 타입 유틸리티 함수는 가능한 한 단순하게 유지합니다. 또한 타입 복잡도 린터(type-coverage, ts-prune)를 도입해 불필요한 타입 추론을 식별하고 지속적으로 개선합니다.

핵심 포인트
  • • 재귀적 타입과 큰 유니온 타입이 컴파일 성능에 미치는 영향
  • • 명시적 타입 어노테이션을 통한 추론 범위 제한
  • • 타입 별칭과 인터페이스를 활용한 복잡도 관리
  • • skipLibCheck, 프로젝트 분리 등 실무적 최적화 기법
답변에 넣으면 좋은 키워드
타입 복잡도 재귀적 타입 유니온 타입 타입 추론 skipLibCheck 명시적 어노테이션 컴파일 성능
실무에서는

수만 줄의 코드베이스에서 타입 체크 시간이 수 분으로 증가해 개발 생산성이 저하될 때, 타입 시스템을 리팩토링하는 프로젝트에 적용됩니다.

Follow-up 질문

any, unknown, never 타입의 차이를 설명하고, 각 타입을 사용하기 적절한 상황과 타입 안정성 측면에서의 트레이드오프를 논해주세요.

댓글 0

로그인 후 댓글을 작성할 수 있습니다.

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!