제네릭(Generic)은 TypeScript의 핵심 기능 중 하나로, “타입을 파라미터로 받아 재사용성을 극대화하는 문법”입니다. 배열, 함수, 클래스, API 응답 타입 등 어디에서든 사용되며 규모가 있는 프로젝트에서 제네릭을 이해하면 코드 품질이 눈에 띄게 올라갑니다.
제네릭이란?
제네릭은 타입을 변수처럼 받아서 사용하는 기능입니다. 다시 말해, “값을 입력받는 함수”처럼 “타입을 입력받는 함수”라고 보면 이해하기 쉽습니다.
function identity<T>(value: T): T {
return value;
}
identity(10); // T = number
identity("hello"); // T = string
이 함수는 어떤 타입이 들어오든 동일한 타입을 반환하므로, 중복 선언 없이 다양한 타입을 처리할 수 있습니다.
배열(Array)의 제네릭 표기
TypeScript의 배열 타입도 이미 제네릭 기반입니다.
let numbers: Array<number> = [1, 2, 3];
let strings: Array<string> = ["a", "b"];
동일 문법을 간단히 줄인 것이 number[], string[]입니다.
제네릭 함수
제네릭 함수는 “입력값 타입”과 “반환 타입”이 서로 연결된 경우 가장 유용합니다.
function wrap<T>(value: T) {
return { value };
}
const result = wrap("hello");
// result: { value: string }
입력값에 따라 자동으로 타입이 변하기 때문에 타입 선언 중복을 완전히 없앨 수 있습니다.
제네릭 인터페이스
인터페이스에서도 제네릭을 쓰면 재사용성이 매우 높아집니다.
interface ApiResponse<T> {
success: boolean;
data: T;
}
const userRes: ApiResponse<{ id: number; name: string }> = {
success: true,
data: { id: 1, name: "Alice" },
};
API 응답 모델링에서 가장 흔하게 보는 패턴입니다.
제네릭 클래스
클래스에서도 제네릭을 사용하면 다양한 타입을 처리하는 자료구조나 서비스 클래스를 만들 수 있습니다.
class Box<T> {
constructor(private value: T) {}
getValue() {
return this.value;
}
}
const box = new Box(123); // T = number
클래스 기반의 라이브러리나 유틸리티에서 자주 사용되는 패턴입니다.
제네릭 제약 조건(extends)
제네릭을 사용할 때 “T는 반드시 특정 조건을 만족해야 한다”는 제약을 걸 수 있습니다.
function getLength<T extends { length: number }>(value: T) {
return value.length;
}
getLength("hello"); // OK
getLength([1, 2, 3]); // OK
getLength(10); // 오류 (number는 length 없음)
이 패턴을 통해 제네릭 타입의 기능을 강화할 수 있습니다.
기본값(Default Type) 지정
제네릭에도 기본 타입을 지정할 수 있습니다.
interface ApiResponse<T = string> {
success: boolean;
data: T;
}
const res: ApiResponse = {
success: true,
data: "OK",
}; // T는 자동으로 string
기본값을 주면 타입을 지정하지 않아도 안전하게 사용할 수 있습니다.
여러 타입 파라미터 사용
제네릭은 필요하다면 여러 개의 타입을 동시에 받을 수도 있습니다.
function map<T, U>(items: T[], mapper: (item: T) => U): U[] {
return items.map(mapper);
}
const result = map([1, 2, 3], x => x.toString());
// result: string[]
매핑, 변환, 필터링 등 데이터 처리 함수에서 많이 사용되는 패턴입니다.
제네릭이 필요한 이유 (실무 기준)
- 중복 타입 선언 제거
- 함수/클래스의 재사용성 증가
- 구체적 타입을 유지하면서 유연성 확보
- API 모델링 및 데이터 변환 로직에 최적
- 도메인 모델 확장 및 타입 안정성 향상
특히 데이터 처리, API 응답, 유틸리티 함수, 폼 검증 라이브러리 등을 만들 때 제네릭이 필수입니다.
실무에서 가장 많이 사용하는 제네릭 패턴
1. 값 래핑(wrap) 패턴
type Wrap<T> = { value: T };
2. API 응답 모델링
type ApiResponse<T> = { success: boolean; data: T };
3. 배열 전용 유틸리티
type ItemType<T extends any[]> = T[number];
4. Partial, Pick, Omit 같은 유틸리티 타입 기반 확장
모두 제네릭 기반으로 동작합니다.
제네릭은 TypeScript에서 가장 강력한 기능 중 하나이며, 특히 대규모 프로젝트에서 타입 중복을 제거하고 안전하고 재사용 가능한 코드를 작성하데 사용할 수 있습니다.
- 제네릭 = 타입을 인자로 받는 함수/클래스
- 타입 유연성과 타입 안정성을 동시에 확보
- API, 데이터 처리, 유틸리티 함수에서 필수
'개발 > Typescript' 카테고리의 다른 글
| [TYSCRIPT] 제네릭 제약조건(extends) 사용법 — 타입 안정성을 높이는 핵심 기법 (0) | 2025.12.10 |
|---|---|
| [TYPESCRIPT] 제네릭 함수와 클래스 활용하기 - 재사용성과 타입 안정성을 모두 잡는 방법 (0) | 2025.12.09 |
| [TYPESCRIPT] 컴파일러 옵션 정리 — strict, noImplicitAny 등 꼭 알아야 할 핵심 옵션 (0) | 2025.12.07 |
| [TYPESCRIPT] 타입 확장과 중복 방지 패턴 - 유지보수성을 극대화하는 TypeScript 실무 전략 (0) | 2025.12.06 |
| [TYPESCRIPT] keyof와 typeof 활용하기 - 객체 기반 타입 설계를 정교하게 만드는 핵심 문법 (0) | 2025.12.05 |
