TypeScript의 진정한 힘은 타입을 조합하는 능력에 있습니다. 그중에서도 가장 중요한 개념이 바로 유니온 타입(Union)과 교차 타입(Intersection)입니다. 이 두 개념을 제대로 이해하면, 데이터 모델링부터 API 설계까지 훨씬 더 유연하고 견고한 타입을 구성할 수 있습니다.
유니온 타입(Union)이란?
유니온 타입은 둘 이상의 타입 중 하나를 허용하는 타입입니다. 쉽게 말해 “A 또는 B” 타입의 값을 담을 수 있습니다.
let value: string | number;
value = "hello";
value = 100;
// 둘 다 가능
유니온 타입은 서로 다른 타입이 들어올 수 있는 “여러 가능성”을 표현할 때 매우 유용합니다.
✔ 실무 예제 — API 응답
type ApiResponse =
| { success: true; data: any }
| { success: false; error: string };
API 결과가 성공/실패 두 형태로 구분되므로 유니온 타입이 자연스럽게 사용됩니다.
✔ 타입 좁히기(Narrowing)와 함께 사용
유니온 타입은 조건문을 통해 좁혀서 안전하게 사용할 수 있습니다.
function printId(id: string | number) {
if (typeof id === "string") {
console.log(id.toUpperCase());
} else {
console.log(id.toFixed(2));
}
}
유니온 타입이 강력한 이유는 바로 이 조건부 분기(타입 가드) 덕분입니다.
교차 타입(Intersection)이란?
교차 타입은 두 타입을 모두 만족하는 타입입니다. 즉 "A 그리고 B" 형태의 타입이며, 유니온과 상반된 개념입니다.
type A = { name: string };
type B = { age: number };
type C = A & B;
const person: C = {
name: "Alice",
age: 20
};
교차 타입은 객체 구조를 결합해야 하는 상황에서 매우 유용합니다.
✔ 실무 예제 — 사용자 + 권한 결합
type User = { id: number; name: string };
type Admin = { role: "admin" };
type AdminUser = User & Admin;
유저 정보와 관리자 권한을 합쳐 새로운 타입을 만들 때 자연스럽게 사용됩니다.
유니온 vs 교차 — 가장 중요한 차이
| 개념 | 유니온( | ) | 교차( & ) |
|---|---|---|
| 의미 | A 또는 B (하나만 만족) | A 그리고 B (둘 다 만족) |
| 형태 | 선택 가능한 타입 집합 | 모든 속성을 병합한 타입 |
| 사용 예 | API 성공/실패 | 객체 구조 병합 |
| 타입 가드 필요 여부 | 필요 (가능성 여러 개) | 필요 없음 |
유니온 + 태그(Discriminated Union) — 실무 최강 조합
복잡한 상태나 이벤트 구조를 설계할 때 가장 많이 쓰는 고급 패턴입니다.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; size: number };
function area(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.size ** 2;
}
}
각 구조에 “kind”라는 태그를 붙여서 타입 좁히기를 단순화하는 패턴입니다. Redux, React Query, GraphQL 에서 매우 자주 사용됩니다.
교차 타입 주의사항 — 속성 충돌
교차 타입을 사용할 때 하나 주의해야 할 점은, 같은 속성이 서로 다른 타입을 갖고 있으면 충돌이 발생한다는 것입니다.
type A = { value: string };
type B = { value: number };
type C = A & B;
// C의 value는 string & number → never 타입
충돌하는 속성은 교집합이 존재하지 않기 때문에 never가 되며, 사실상 사용 불가능한 타입이 됩니다.
실무에서의 선택 기준
✔ 다음 경우에는 유니온을 사용
- 서로 다른 타입 중 하나만 올 수 있는 상황
- API 응답 구조 정의
- 이벤트 타입 설계
- 여러 상태 값 처리 (loading | success | error)
✔ 다음 경우에는 교차 타입을 사용
- 객체 구조를 합칠 때
- 여러 개의 설정/옵션을 함께 적용할 때
- 기존 타입에 속성을 확장할 때
- MVC, OOP 스타일에서 역할 결합
예제 — 유니온 + 교차 조합
두 개념은 단독으로도 강력하지만, 함께 사용하면 훨씬 더 유연한 타입 설계가 가능합니다.
type User = { id: number; name: string };
type Admin = { role: "admin" };
type Guest = { role: "guest" };
type Person = User & (Admin | Guest);
// Admin 사용자 또는 Guest 사용자
이 패턴은 RBAC(Role Based Access Control) 설계에서 많이 사용됩니다.
유니온 타입과 교차 타입은 TypeScript를 “타입 시스템이 강력한 언어”로 만들어주는 핵심 도구입니다. 이 두 개념을 정확히 이해하면, 객체 디자인부터 상태 관리, API 모델링까지 복잡한 구조를 안정적이고 명확하게 표현할 수 있습니다.
- 유니온( | ) → 여러 가능성 중 하나
- 교차( & ) → 모든 속성을 가진 결합 타입
- 유니온 + 태그 조합 → 실무 최강 패턴
