타입스크립트
Microsoft가 개발한 JavaScript의 상위 집합(Superset) 언어로, JavaScript에 정적 타입 시스템을 추가하여 컴파일 시점에 오류를 잡을 수 있게 한 프로그래밍 언어입니다.
핵심 특징
| 항목 | 내용 |
| 개발사 | Microsoft (2012년 공개) |
| 관계 | JavaScript ⊂ TypeScript (JS의 상위 집합) |
| 실행 방식 | TypeScript → 컴파일(tsc) → JavaScript → 브라우저/Node.js 실행 |
| 타입 시스템 | 정적 타입 (컴파일 시점에 타입 검사) |
| 확장자 | .ts, .tsx (React JSX 포함 시) |
TypeScript 코드 (.ts)
│
▼ tsc (TypeScript Compiler)
│
JavaScript 코드 (.js)
│
▼ 브라우저 또는 Node.js
│
실행
JavaScript vs TypeScript
// JavaScript — 런타임에 오류 발생
function add(a, b) {
return a + b;
}
add(1, "2"); // "12" — 의도치 않은 문자열 결합
add(1); // NaN — 오류 없이 실행됨
// TypeScript — 컴파일 시점에 오류 감지
function add(a: number, b: number): number {
return a + b;
}
add(1, "2"); // X 컴파일 에러: string은 number에 할당 불가
add(1); // X 컴파일 에러: 2개의 인수가 필요한데 1개만 전달
add(1, 2); // O 정상: 3
주요 타입 시스템
기본 타입
// 원시 타입
let name: string = "홍길동";
let age: number = 25;
let isActive: boolean = true;
let data: null = null;
let value: undefined = undefined;
// 배열
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["a", "b", "c"];
// 튜플
let pair: [string, number] = ["age", 25];
// 열거형
enum Direction {
UP, DOWN, LEFT, RIGHT
}
let dir: Direction = Direction.UP;
인터페이스와 타입
// 인터페이스 — 객체 구조 정의
interface User {
id: number;
name: string;
email: string;
age?: number; // 선택적 속성 (Optional)
readonly createdAt: Date; // 읽기 전용
}
const user: User = {
id: 1,
name: "홍길동",
email: "hong@example.com",
createdAt: new Date()
};
user.name = "김철수"; // O 변경 가능
user.createdAt = new Date(); // X readonly이므로 변경 불가
// 타입 별칭
type ID = number | string; // 유니온 타입
let userId: ID = 1;
userId = "abc"; // O number 또는 string 허용
제네릭
// 제네릭 — 타입을 매개변수화
function getFirst<T>(arr: T[]): T {
return arr[0];
}
getFirst<number>([1, 2, 3]); // 반환 타입: number
getFirst<string>(["a", "b"]); // 반환 타입: string
// 제네릭 인터페이스
interface ApiResponse<T> {
status: number;
data: T;
message: string;
}
const response: ApiResponse<User> = {
status: 200,
data: { id: 1, name: "홍길동", email: "hong@example.com", createdAt: new Date() },
message: "성공"
};
유니온과 내로잉
// 유니온 타입
function printId(id: number | string) {
// 타입 내로잉 (Narrowing)
if (typeof id === "string") {
console.log(id.toUpperCase()); // string 메서드 사용 가능
} else {
console.log(id.toFixed(2)); // number 메서드 사용 가능
}
}
printId(101); // "101.00"
printId("abc"); // "ABC"
TypeScript를 쓰는 이유
| 이유 | 설명 |
| 컴파일 시점 오류 감지 | 런타임 전에 타입 관련 버그를 잡음 |
| IDE 지원 강화 | 자동완성, 리팩토링, 타입 추론 등 |
| 코드 가독성 | 타입이 곧 문서 역할 |
| 대규모 프로젝트 | 팀 협업 시 계약(인터페이스)으로 소통 |
| 리팩토링 안전성 | 타입 변경 시 영향 범위를 컴파일러가 알려줌 |
[JavaScript 대규모 프로젝트]
함수 수정 → 어디서 쓰이는지 모름 → 런타임에 장애 발생
[TypeScript 대규모 프로젝트]
함수 시그니처 변경 → 컴파일러가 영향 받는 곳을 모두 표시
→ 수정 누락 방지
Java와 TypeScript 비교
| 항목 | Java | TypeScript |
| 타입 시스템 | 정적 타입 (강타입) | 정적 타입 (구조적 타입) |
| 타입 검사 방식 | 명목적 (이름 기반) | 구조적 (모양 기반) |
| 실행 환경 | JVM | 브라우저 / Node.js |
| 컴파일 결과 | 바이트코드 (.class) | JavaScript (.js) |
| Null 처리 | NullPointerException | strict null checks 옵션 |
// TypeScript: 구조적 타입 — 모양이 같으면 호환
interface Point {
x: number;
y: number;
}
const p = { x: 10, y: 20, z: 30 }; // z가 추가로 있어도
const point: Point = p; // O x, y가 있으므로 호환됨
// Java: 명목적 타입 — 이름이 같아야 호환
class Point {
int x;
int y;
}
class Coordinate {
int x;
int y;
}
Point p = new Coordinate(); // X 이름이 다르므로 호환 안 됨
주요 사용처
| 프레임워크 / 환경 | 설명 |
| React | .tsx로 컴포넌트 타입 안전하게 작성 |
| Next.js | TypeScript 기본 지원 |
| Angular | TypeScript 필수 |
| Node.js (NestJS) | 백엔드에서도 TypeScript 사용 |
| React Native | 모바일 앱 개발 |