🎁 지금 가입하면 온라인 AI를 최대 30분 무료로 사용할 수 있습니다. 신용카드는 필요하지 않습니다.

TypeScript 면접 질문과 답변 (2026): 타입, 제네릭, 내로잉

October 9, 2026
엄격 모드에서 테스트된 20개의 TypeScript 면접 질문과 답변: type vs interface, any vs unknown, 유니온, 제네릭, 유틸리티 타입, 구조적 타이핑.
TypeScript 면접 질문과 답변 (2026): 타입, 제네릭, 내로잉
typescript interview questions
typescript interview
type vs interface
any vs unknown typescript
typescript generics interview

TypeScript 면접은 문법을 넘어 타입 시스템을 이해하고 있는지를 확인합니다. 아래에는 기초부터 TypeScript를 "사용하는" 사람과 "왜 그렇게 동작하는지 아는" 사람을 가르는 질문까지, 답변과 함께 20개의 질문을 정리했습니다. 코드는 게시 전에 strict 모드의 TypeScript 컴파일러로 컴파일했으며, 인용한 오류 메시지는 실제로 출력된 것입니다.

기초

1. TypeScript는 JavaScript에 무엇을 더하나요?

컴파일 시점에 검사된 뒤 제거되는 정적 타입 시스템입니다. 결과물은 순수한 JavaScript이므로 타입은 런타임 비용도, 런타임 존재감도 없습니다. 이 마지막 점이 중요합니다. 직접 검사를 작성하지 않는 한 런타임에 typeof로 타입을 확인할 수 없습니다.

2. type과 interface의 차이는 무엇인가요?

둘 다 객체의 형태를 기술하며 대개 서로 바꿔 쓸 수 있습니다. 실질적인 차이는 다음과 같습니다.

interfacetype
선언 병합가능, 두 선언이 병합됨불가, 이름이 중복되면 오류
유니언과 원시 타입표현할 수 없음표현할 수 있음, 예를 들어 number와 string의 유니언
확장extends&를 사용한 교차
매핑 및 조건부 타입불가가능

interface A를 두 번 선언하면 필드가 병합됩니다. type B를 두 번 선언하면 error TS2300: Duplicate identifier 'B'가 발생합니다. 흔히 쓰는 기준은 이렇습니다. 다른 사람이 확장할 수 있는 공개 객체 형태에는 interface를, 나머지에는 type을 사용하세요.

3. any, unknown, never의 차이는 무엇인가요?

  • any는 검사를 꺼버립니다. 무엇이든 허용되고 오류는 숨습니다.
  • unknown은 안전한 버전입니다. 무엇이든 대입할 수 있지만 사용 전에 좁혀야 합니다. unknown에 x.toFixed()를 호출하면 error TS18046: 'x' is of type 'unknown'으로 실패합니다.
  • never는 존재할 수 없는 값의 타입입니다. 예를 들어 항상 throw하는 함수가 그렇습니다. 완전성 검사에 유용합니다.

파싱한 JSON처럼 타입을 통제할 수 없는 값에는 any보다 unknown을 선호하세요.

4. strict 모드는 무엇을 하나요?

여러 검사를 켭니다. 가장 중요한 것은 strictNullChecks(null과 undefined가 별도 타입이 됨)와 noImplicitAny입니다. 이 모드에서 옵셔널 값을 확인 없이 사용하면 error TS18048: 'x' is possibly 'undefined'가 발생합니다. 새 프로젝트는 strict를 켜고 시작해야 합니다.

5. readonly와 const의 차이는 무엇인가요?

const는 변수를 재할당하지 못하게 막습니다. readonly는 프로퍼티에 대입하지 못하게 막습니다. readonly 프로퍼티에 쓰면 error TS2540: Cannot assign to 'n' because it is a read-only property가 발생합니다. 둘 다 기반 객체를 깊은 수준까지 불변으로 만들지는 않습니다.

실전에서의 타입

6. 유니언 타입이란 무엇이고 어떻게 좁히나요?

유니언은 "이 타입들 중 하나"를 뜻합니다. 좁히기는 컴파일러가 이해하는 검사를 사용합니다.

type Id = number | string;
function describe(id: Id): string {
  if (typeof id === "string") return id.toUpperCase();
  return id.toFixed(1);
}

if 안에서 id는 string입니다. 그 뒤에서 컴파일러는 이것이 number임을 압니다. 다른 좁히기 도구로는 instanceof, in 연산자, 동등 비교, 사용자 정의 타입 가드가 있습니다.

7. 판별 유니언이란 무엇인가요?

각 멤버가 서로를 구별해 주는 공통 리터럴 필드, 즉 판별자를 가진 유니언입니다.

type Shape =
  | { kind: "circle"; r: number }
  | { kind: "sq"; s: number };

function assertNever(x: never): never {
  throw new Error("unexpected " + x);
}

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.r ** 2;
    case "sq": return s.s ** 2;
    default: return assertNever(s);
  }
}

나중에 새 형태를 추가하고 case를 빠뜨리면 default 분기가 컴파일되지 않습니다. s가 더 이상 never가 아니기 때문입니다. 이것이 완전성 검사입니다.

8. 제네릭이란 무엇이고 왜 사용하나요?

여러 타입에 걸쳐 동작하면서도 타입들 사이의 관계를 유지할 수 있게 해줍니다.

function first<T>(xs: T[]): T | undefined { return xs[0]; }
function pick<T, K extends keyof T>(o: T, k: K): T[K] { return o[k]; }

first([1, 2])는 any가 아니라 number | undefined를 반환합니다. pick(user, "name")은 name의 타입을 반환합니다. extends keyof T 제약은 존재하지 않는 키를 전달하지 못하게 막습니다.

9. 자주 쓰이는 유틸리티 타입은 무엇인가요?

유틸리티하는 일
Partial<T>모든 프로퍼티를 옵셔널로 만듦
Required<T>모든 프로퍼티를 필수로 만듦
Readonly<T>모든 프로퍼티를 readonly로 만듦
Pick<T, K>나열한 키만 남김
Omit<T, K>나열한 키를 제거함
Record<K, V>키가 K이고 값이 V인 객체 타입
ReturnType<F>함수 타입의 반환 타입

10. 매핑 타입이란 무엇인가요?

다른 타입의 키를 순회하며 새 타입을 만듭니다. Partial 자체도 { [K in keyof T]?: T[K] }로 작성됩니다. 이걸 알면 유틸리티 타입을 외우는 게 아니라 이해하고 있다는 뜻입니다.

11. as const란 무엇인가요?

컴파일러에게 가장 좁은 타입을 추론하고 모든 것을 readonly로 표시하라고 지시합니다. const arr = [1, 2, 3] as const의 타입은 readonly [1, 2, 3]이며, arr.push(4)는 error TS2339: Property 'push' does not exist on type 'readonly [1, 2, 3]'로 실패합니다. 허용되는 값의 목록이나 설정 객체에 유용합니다.

12. 타입 단언이란 무엇이고 언제 위험한가요?

value as Type은 컴파일러에게 자신을 믿으라고 말합니다. 런타임에는 아무 검사도 하지 않습니다. 틀렸다면 오류는 나중에 크래시로 나타납니다. 단언하기보다는 검사나 타입 가드 함수로 좁히는 편이 좋습니다.

언어 동작 방식

13. null과 undefined의 차이는 무엇인가요?

undefined는 값이 한 번도 할당되지 않았다는 뜻이고, null은 "값이 없음"을 의도적으로 설정한 것입니다. strictNullChecks를 켜면 둘은 서로 다른 타입이 됩니다. 이들을 다룰 때는 옵셔널 체이닝(a?.b)과 null 병합 연산자(a ?? b)를 사용하세요. ||와 달리 ??는 null과 undefined일 때만 대체값을 사용하므로 0이나 빈 문자열은 그대로 유지됩니다.

14. Non-null 단언 연산자 !는 무엇인가요?

value!는 컴파일러에게 이 값이 null이나 undefined가 아니라고 알려줍니다. as와 마찬가지로 검사되지 않습니다. 컴파일러보다 더 잘 아는 몇몇 상황에서는 괜찮지만, 보통은 런타임 검사를 하는 편이 더 안전합니다.

15. keyof는 무엇을 하며, 타입 위치에서의 typeof는 무엇인가요?

keyof T는 T의 프로퍼티 이름들의 유니온을 만들어냅니다. 타입 위치에서 typeof x는 값의 타입을 가져오므로 타입을 반복해서 쓰지 않아도 됩니다. 둘을 함께 쓰면 keyof typeof obj는 값으로 정의한 객체의 키들을 얻을 수 있습니다.

16. enum과 유니온 타입은 어떻게 다른가요?

enum은 런타임 객체와 값을 만듭니다. "idle" | "loading" 같은 문자열 리터럴 유니온은 컴파일 시점에 사라지고 추가 코드가 필요 없습니다. 많은 팀이 단순함 때문에 문자열 리터럴 유니온을 선호하고, 런타임 객체가 필요할 때만 enum을 사용합니다.

도구와 실제 프로젝트

17. tsconfig.json은 무엇을 하며, 어떤 옵션이 중요한가요?

컴파일러에게 어떤 파일을 포함하고 어떻게 검사할지 알려줍니다. 면접관이 자주 묻는 옵션은 strict, target(출력할 JavaScript 버전), module과 moduleResolution, noEmit(검사만 하고, 다른 도구가 빌드할 때 흔히 사용), esModuleInterop, skipLibCheck입니다.

18. API 응답처럼 외부에서 들어오는 것은 어떻게 타입을 지정하나요?

타입은 런타임에 사라지므로 컴파일러는 네트워크가 무엇을 반환하는지 검증할 수 없습니다. 데이터를 unknown으로 취급한 뒤, 스키마 라이브러리나 직접 작성한 타입 가드로 검증한 다음 사용하세요. 파싱된 JSON에 타입을 단언하는 것은 버그를 숨깁니다.

19. JavaScript 프로젝트를 TypeScript로 어떻게 마이그레이션하나요?

점진적으로 하세요. allowJs를 켠 tsconfig.json을 추가하고, 파일을 하나씩 이름을 바꾸고, 시간이 지나면서 더 엄격한 옵션을 켜고, API 클라이언트나 공용 유틸리티처럼 경계 부분에 먼저 타입을 붙이세요. 한 번에 전부 바꾸는 방식은 피하세요.

20. 구조적 타이핑이란 무엇인가요?

TypeScript는 타입을 이름이 아니라 형태로 비교합니다. 객체가 어떤 타입이 요구하는 필드를 가지고 있으면, 그 타입으로 선언된 적이 없어도 허용됩니다. 선언된 이름이 중요한 명목적 타이핑을 쓰는 언어와는 다릅니다.

준비 방법

  1. 플레이그라운드나 작은 프로젝트를 strict 모드로 열고, 실패해야 하는 예제를 포함해 위의 모든 예제를 직접 시도해 보세요.
  2. 제네릭 함수와 판별 유니온을 외워서 바로 작성할 수 있도록 준비하세요.
  3. any 대신 unknown을 선택하는 이유를 알아두세요.
  4. 실제 프로젝트에서 까다로운 부분에 타입을 붙였던 경험 한 가지를 준비하세요.

관련 연습이 필요하다면 Node.js 면접 질문, Angular 면접 질문, Python 면접 질문 가이드를 참고하세요.

소리 내어 자신의 말로 연습하세요. 이후에 녹취록을 보면 어디서 횡설수설했는지, 핵심을 놓쳤는지 알 수 있습니다. 실시간 면접이나 평가에서는 AI 도구에 관한 고용주의 규칙을 따르세요.

YesToTheOffer와 함께 답변을 연습하세요

소리 내어 리허설하고, 자신의 이력서에서 생성된 답변을 받고, 이후에 녹취록을 검토하세요. 30분 무료, 구독 없음.

iOS & Android — 출시 예정
요금 보기