TypeScript의 가장 강력한 기능 중 하나는 바로 객체(Object) 타입 정의입니다. JavaScript에서 객체는 자유롭게 속성을 추가하거나 제거할 수 있지만, 이는 예기치 않은 런타임 오류를 만들어내는 주요 원인이 됩니다. TypeScript는 객체의 구조를 명확히 정의하고 타입 검사를 수행함으로써, 안정성과 유지보수성을 크게 향상시킵니다.
기본 객체 타입 선언
가장 단순한 형태의 객체 타입은 속성과 그 타입을 지정하는 방식입니다.
let user: {
name: string;
age: number;
isAdmin: boolean;
};
user = {
name: "Alice",
age: 30,
isAdmin: true,
};
TypeScript는 필수 속성 누락, 타입 불일치를 모두 체크해 줍니다.
user = { name: "Bob" };
// ❌ 오류: age, isAdmin 속성이 없어서 오류 발생
선택적(Optional) 속성
특정 속성이 필수는 아닐 때 ? 를 사용해 선택적 속성을 만들 수 있습니다.
let product: {
title: string;
price: number;
description?: string; // 선택적 속성
};
product = { title: "Keyboard", price: 49000 };
product = { title: "Mouse", price: 29000, description: "Wireless" };
선택적 속성이 존재하지 않아도 오류가 발생하지 않으며, 사용시 undefined 여부 체크가 필요할 수 있습니다.
읽기 전용(Readonly) 속성
객체 내 특정 속성을 변경할 수 없도록 강제하려면 readonly를 사용합니다.
let config: {
readonly appName: string;
version: string;
};
config.appName = "New Name";
// ❌ 오류: 읽기 전용 속성은 수정할 수 없음
정적 설정값, 환경 변수, 고정 ID 등에 매우 유용합니다.
객체 타입 재사용: Type Alias
여러 곳에서 반복되는 객체 구조는 Type Alias로 정의할 수 있습니다.
type User = {
id: number;
name: string;
email?: string;
};
let u1: User = { id: 1, name: "Alice" };
let u2: User = { id: 2, name: "Bob", email: "bob@test.com" };
Type Alias는 데이터를 구조적으로 재사용할 때 필수적인 기능입니다.
인터페이스(Interface) - 객체 타입의 확장
interface는 객체 타입 정의를 위한 또 다른 방식이며, 특히 OOP 스타일의 확장(extends)에 강력한 기능을 제공합니다.
1. 기본 인터페이스
interface User {
id: number;
name: string;
isAdmin: boolean;
}
const admin: User = {
id: 1,
name: "Root",
isAdmin: true
};
2. 인터페이스 확장
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
const myDog: Dog = {
name: "Buddy",
breed: "Golden Retriever"
};
상속 기반 구조에서 인터페이스가 특히 유리합니다.
타입(alias) vs 인터페이스(interface) 차이
| 구분 | type | interface |
|---|---|---|
| 확장성 | 일반적으로 확장 불가(교차 타입으로 가능) | extends로 확장에 최적화 |
| 유연성 | union, tuple 등 다양한 타입 표현 | 객체 타입 정의 중심 |
| 중복 선언 | 오류 | 자동 병합 |
실무에서는 아래 기준으로 선택하면 됩니다:
- 객체 중심 상황 → interface
- 유연한 타입 조합 필요 → type
객체 타입과 인덱스 시그니처
객체의 key/value 구조가 동적일 때 인덱스 시그니처를 활용합니다.
interface StringMap {
[key: string]: string;
}
const headers: StringMap = {
"Content-Type": "application/json",
Authorization: "Bearer token"
};
실무에서 API 요청 헤더, 다국어(i18n) 번역 데이터에 자주 사용됩니다.
객체 타입의 readonly + optional 조합
둘을 함께 사용하면 “수정은 금지, 존재 여부는 선택적”인 속성을 정의할 수 있습니다.
interface Profile {
readonly id: number;
nickname?: string;
}
const p: Profile = { id: 1 };
p.nickname = "KakaoVX"; // 가능
p.id = 2; // ❌ 오류
실무에서 자주 사용되는 객체 타입 패턴
1. API 응답폼
interface ApiResponse {
success: boolean;
data: T;
message?: string;
}
2. DB 모델
interface UserEntity {
id: number;
email: string;
createdAt: string;
updatedAt: string;
}
3. 상태 관리(Store) 구조
type AuthState = {
token: string | null;
user?: User;
};
이처럼 객체 타입은 실제 애플리케이션에서 가장 많이 사용되는 구조입니다.
TypeScript의 객체 타입 정의는 단순히 “타입을 붙이기”가 아니라, 코드의 의도를 명확히 하고 유지보수성을 극대화하는 설계 도구입니다. 객체의 구조가 복잡해질수록 인터페이스와 타입 alias를 적절히 조합해 관리하는 것이 중요합니다.
'개발 > Typescript' 카테고리의 다른 글
| [TYPESCRIPT] 배열과 튜플 다루기 - TypeScript에서 컬렉션을 안전하게 사용하는 방법 (0) | 2025.11.22 |
|---|---|
| [TYPESCRIPT] 기본 타입 소개 - string, number, boolean 완벽 이해하기 (0) | 2025.11.21 |
| [TYPESCRIPT] tsconfig.json 완벽 가이드 - TypeScript 프로젝트 설정의 모든 것 (0) | 2025.11.20 |
| [TYPESCRIPT] 개발 환경 세팅: Node.js, npm, pnpm, ts-node 설치하기 - TypeScript 프로젝트를 위한 필수 준비 (0) | 2025.11.19 |
| [TYPESCRIPT] TypeScript란 무엇인가? - JavaScript와의 차이점 완전 정리 (0) | 2025.11.18 |
