LearningTypeScript 전환 가이드
타입 시스템 기초: 타입은 계산 규칙이다
TypeScript 타입을 문법 표기로 보지 않고, JS로 변환되는 컴파일 산출물을 통제하는 타입 시스템으로 이해한다.
이 문서의 목표
TypeScript를 배우는 핵심은 type/interface 문법 암기가 아니라,
값이 아니라 타입 규칙이 설계 의도를 전달한다는 점을 이해하는 것입니다.
이 문서는 백엔드 개발자 관점에서 보면 가장 익숙한 3가지를 중심으로 설명합니다.
- 합타입(Union)으로 상태의 분기를 나타내는 법
- 곱타입(Intersection/Object)으로 값의 성분을 조합하는 법
- 컴파일 단계에서 타입이 사라지고, JS는 언제나 런타임 규칙으로 남는다는 점
1) TypeScript는 “컴파일 타임 타입 체크 언어”다
TypeScript 코드:
type Money = { amount: number };
type ApiStatus<T> = { ok: true; data: T } | { ok: false; error: string };
const getMoney = (): ApiStatus<Money> => ({ ok: true, data: { amount: 1000 } });실제 JS 출력(요약):
const getMoney = () => ({ ok: true, data: { amount: 1000 } });- 타입 표기(
type,: number,Money,ApiStatus<T>)는 모두 지워짐 - 타입은 컴파일러에게 계약을 전달하고, 런타임으로는 실행 규칙이 들어가지 않음
그래서 타입 = 런타임 동작이 아니라 타입 = 정적 안전성 규칙입니다.
2) 합타입(Union): 가능한 상태의 목록
A | B는 “A 또는 B 중 하나”를 뜻합니다.
type ApiResult =
| { status: "success"; data: string }
| { status: "error"; message: string };장점:
- 실패/성공 상태를 명시적으로 분기
if (result.status === "success")같은 분기점에서 안전하게 데이터 접근
백엔드 관점에서 보면 API 응답의 200/400/500을 프론트 상태로 모델링한 것과 유사합니다.
3) 곱타입(Intersection): 성분의 결합
A & B는 A의 성분과 B의 성분을 동시에 만족합니다.
type BaseUser = { id: string };
type VipTag = { isVip: boolean };
type VipUser = BaseUser & VipTag;실무 해석:
- 객체 계약을 작게 쪼개고 조합해서 재사용
- 공통 스키마(
BaseUser) + 기능별 첨부(VipTag)를 누적 가능
4) 타입 합성의 사고법: “곱(필수 성분) / 합(분기)” 분리
- UI 상태는 대개 합타입이 먼저 적합:
idle | loading | success | error - 공통 도메인 데이터는 곱타입이 먼저 적합:
id + createdAt + name
이 분리를 먼저 잡으면, “이 값은 무엇이냐?”보다 “이 값의 상태 조합이 어떤 의미냐?”를 먼저 설계하게 됩니다.
5) 제네릭과 타입 분기(컴파일 타임)
type Data<T> = T extends string
? { kind: "text"; value: T; length: number }
: { kind: "other"; value: T };
type A = Data<"ok">; // { kind: "text"; value: "ok"; length: number }
type B = Data<{ id: string }>; // { kind: "other"; value: { id: string } }Data<T>의 결과 타입은 T에 따라 타입 검사 시점(컴파일 타임)에서 결정됩니다.
트랜스파일된 런타임 JavaScript에는 T나 extends 분기 정보가 남지 않습니다.
비교:
- TypeScript의 조건부 타입은 타입 검사기에서 계산되는 규칙이고, JavaScript로 내려가면 타입은 소거됩니다.
- Java/C#/Rust 등은 제네릭과 타입 제약을 제공하지만, TypeScript의 T extends U ? X : Y처럼 타입을 조건식으로 평가해 새로운 타입을 계산하는 조건부 타입 문법은 제공하지 않습니다.
6) 실무에서 자주 생기는 함정
- 타입을
runtime으로 착각하고typeof로T를 가려보려 함 - 합타입에서 상태 태그(
status) 없이 분기 - 실패/빈값을 하나로
null에 묶어 버리고 화면에서 예측 불가 버그 발생
체크리스트
- “이 값은 합타입인지 곱타입인지” 판단해 설계할 수 있는가?
- 태그 기반 합타입(예:
kind,status)으로 분기 누락이 컴파일 타임에 걸리도록 설계할 수 있는가? - 제네릭을 “컴파일 타임 규칙”으로 설명할 수 있는가?
- 타입은 JS 출력에서 사라진다는 점을 팀원에게 설명할 수 있는가?