TypeScript 미드레벨 기술면접

TypeScript 미드레벨 (3~7년) 코딩 · 알고리즘 5문항 조회수 103 · 2026-06-12 (금) 11:10:48
1 TypeScript 타입 시스템
Medium

Q. TypeScript의 never 타입과 void 타입의 차이를 설명하고, never 타입이 실무에서 유용하게 사용되는 구체적인 시나리오(예: exhaustive check, 타입 좁히기)를 설명해주세요.

A. 모범답안

void는 함수가 명시적으로 아무것도 반환하지 않음을 나타내며 undefined를 할당할 수 있지만, never는 절대 발생하지 않는 값의 타입으로 어떤 값도 할당할 수 없습니다. never는 switch-case문에서 모든 케이스를 처리했는지 컴파일 타임에 검증하는 exhaustive check에 활용되며, 타입 가드를 통한 타입 좁히기에서 도달 불가능한 코드 경로를 표현할 때 사용됩니다. 또한 유니온 타입에서 특정 타입을 제거하거나, 조건부 타입에서 불가능한 경우를 표현하는 데 활용됩니다.

핵심 포인트
  • • void는 반환값이 없음을 나타내고 never는 절대 발생하지 않는 타입
  • • exhaustive check로 모든 케이스 처리 여부를 컴파일 타임에 검증
  • • 타입 가드와 조건부 타입에서 불가능한 경로 표현
Follow-up 질문

유니온 타입에서 never를 사용하여 특정 타입을 제거하는 Exclude 유틸리티 타입의 동작 원리를 설명해주세요.

2 비동기 프로그래밍
Hard

Q. JavaScript의 async/await에서 병렬 처리와 순차 처리의 성능 차이를 설명하고, N개의 API 호출을 동시성 제한(예: 최대 3개씩만 동시 실행)하면서 처리해야 할 때 어떤 방식으로 구현할 수 있는지 설명해주세요.

A. 모범답안

순차 처리는 각 await가 이전 작업이 완료될 때까지 기다리므로 총 실행 시간이 모든 작업 시간의 합이 되지만, 병렬 처리는 Promise.all을 사용하여 동시에 실행되므로 가장 긴 작업 시간만큼만 소요됩니다. 동시성 제한이 필요한 경우 세마포어 패턴이나 Promise 풀을 구현하여 실행 중인 작업 수를 추적하고, 작업이 완료될 때마다 대기 중인 다음 작업을 시작하는 방식으로 처리합니다. p-limit 같은 라이브러리를 사용하거나, async 큐를 직접 구현하여 동시 실행 개수를 제어할 수 있습니다.

핵심 포인트
  • • 순차 처리는 작업 시간의 합, 병렬 처리는 최대 작업 시간
  • • 동시성 제한은 세마포어 패턴이나 Promise 풀로 구현
  • • 실행 중인 작업 수를 추적하고 완료 시 다음 작업 시작
Follow-up 질문

동시성 제한 구현 시 메모리 사용량과 처리 속도 간의 트레이드오프를 어떻게 고려해야 하나요?

3 알고리즘 최적화
Medium

Q. 재귀 함수로 구현된 피보나치 수열의 시간 복잡도가 O(2^n)인 이유를 설명하고, 메모이제이션과 동적 프로그래밍을 사용하여 O(n)으로 최적화하는 방법의 차이점을 TypeScript 관점에서 설명해주세요.

A. 모범답안

재귀 피보나치는 각 호출이 2개의 하위 호출을 생성하고 동일한 값을 중복 계산하여 O(2^n)의 시간 복잡도를 가집니다. 메모이제이션은 Map이나 객체를 사용해 계산된 값을 캐싱하여 top-down 방식으로 중복 계산을 제거하며, 동적 프로그래밍은 배열을 사용해 bottom-up 방식으로 작은 문제부터 순차적으로 해결합니다. TypeScript에서는 메모이제이션 시 제네릭 데코레이터나 고차 함수로 재사용 가능한 캐싱 로직을 구현할 수 있으며, 타입 안정성을 유지하면서 최적화할 수 있습니다.

핵심 포인트
  • • 재귀는 중복 계산으로 O(2^n), 최적화 시 O(n)
  • • 메모이제이션은 top-down 캐싱, DP는 bottom-up 순차 계산
  • • TypeScript에서 제네릭과 고차 함수로 재사용 가능한 최적화 구현
Follow-up 질문

메모이제이션 캐시가 무한정 증가하는 것을 방지하기 위한 LRU 캐시 전략을 어떻게 구현할 수 있나요?

4 디자인 패턴
Hard

Q. TypeScript에서 Singleton 패턴을 구현할 때 클래스 기반 방식과 모듈 기반 방식의 차이를 설명하고, 각각의 장단점과 멀티 스레드 환경(Worker Threads)에서의 동작 차이를 설명해주세요.

A. 모범답안

클래스 기반 Singleton은 private 생성자와 static 인스턴스를 사용하여 명시적으로 단일 인스턴스를 보장하며, 모듈 기반은 ES6 모듈 시스템의 캐싱 특성을 활용하여 암묵적으로 싱글톤을 구현합니다. 클래스 방식은 lazy initialization과 명시적 제어가 가능하지만 코드가 복잡하고, 모듈 방식은 간결하지만 초기화 시점 제어가 어렵습니다. Node.js의 Worker Threads 환경에서는 각 워커가 독립적인 모듈 캐시를 가지므로 두 방식 모두 워커마다 별도의 인스턴스가 생성되며, 진정한 전역 싱글톤이 필요하면 SharedArrayBuffer나 메시지 패싱을 활용해야 합니다.

핵심 포인트
  • • 클래스 방식은 명시적 제어, 모듈 방식은 ES6 캐싱 활용
  • • 클래스는 lazy init 가능, 모듈은 간결하지만 초기화 제어 어려움
  • • Worker Threads에서는 각 워커마다 독립적 인스턴스 생성
Follow-up 질문

Singleton 패턴이 테스트 가능성을 해치는 이유와 Dependency Injection으로 이를 개선하는 방법을 설명해주세요.

5 메모리 관리
Medium

Q. JavaScript의 클로저가 메모리 누수를 발생시킬 수 있는 구체적인 시나리오를 설명하고, 이벤트 리스너나 타이머 함수에서 클로저 관련 메모리 누수를 방지하기 위한 베스트 프랙티스를 설명해주세요.

A. 모범답안

클로저는 외부 함수의 변수를 참조하여 해당 스코프 전체를 메모리에 유지시키므로, 이벤트 리스너나 setInterval 콜백에서 DOM 요소나 큰 객체를 참조하면 해당 요소가 제거되어도 가비지 컬렉션되지 않습니다. 메모리 누수를 방지하려면 removeEventListener나 clearInterval로 명시적으로 정리하고, WeakMap을 사용하여 약한 참조를 유지하거나, 필요한 값만 추출하여 클로저에 캡처해야 합니다. TypeScript에서는 컴포넌트 언마운트나 cleanup 함수에서 리스너 제거를 강제하는 타입 안전한 패턴을 구현할 수 있습니다.

핵심 포인트
  • • 클로저는 외부 스코프 전체를 메모리에 유지
  • • 이벤트 리스너와 타이머는 명시적으로 정리 필요
  • • WeakMap 사용 또는 필요한 값만 캡처하여 누수 방지
Follow-up 질문

React의 useEffect 훅에서 클로저와 관련된 stale closure 문제가 발생하는 원리와 해결 방법을 설명해주세요.

댓글 0

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

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