들어가면서
React 컴포넌트를 만들 때 가장 기본이자 중요한 부분은 Props를 제대로 타입 지정하는 것이다.
이전 포스팅에 이어지는 내용으로,
이번 포스팅에서는 실무에서도 자주 쓰이는 패턴을 중심으로, children, optional, default 값 처리까지 깔끔하게 정리해보겠다.
✅ 1. 기본적인 Props 타입 지정
type ButtonProps = {
label: string;
onClick: () => void;
};
function Button({ label, onClick }: ButtonProps) {
return <button onClick={onClick}>{label}</button>;
}
- type 또는 interface로 Props 정의 가능
- 함수형 컴포넌트에 인자로 구조분해하여 사용
✅ 2. Optional Props (선택적으로 받을 수 있는 경우)
type CardProps = {
title: string;
subtitle?: string; // optional
};
function Card({ title, subtitle }: CardProps) {
return (
<div>
<h2>{title}</h2>
{subtitle && <p>{subtitle}</p>}
</div>
);
}
- ?로 표시하면 필수 prop 아님
- 렌더링 조건 분기 시 && 연산자 자주 사용
✅ 3. Default Props (기본값 지정)
type BadgeProps = {
text: string;
color?: string;
};
function Badge({ text, color = 'gray' }: BadgeProps) {
return <span style={{ backgroundColor: color }}>{text}</span>;
}
- 기본값은 구조분해 시 지정하는 것이 가장 깔끔
- 기존 방식인 Component.defaultProps는 함수형 컴포넌트에선 비권장
✅ 4. children Props 타입 지정
type LayoutProps = {
children: React.ReactNode;
};
function Layout({ children }: LayoutProps) {
return <div className="layout">{children}</div>;
}
- children은 명시적으로 React.ReactNode 또는 JSX.Element로 선언
- 여러 개의 JSX를 자식으로 받을 수 있어야 하므로 대부분 React.ReactNode를 사용
✅ 5. Props 타입 정의 방법: type vs interface
// interface 버전
interface ModalProps {
open: boolean;
onClose: () => void;
}
// type 버전
type ModalProps = {
open: boolean;
onClose: () => void;
};
- 대부분의 경우 type과 interface는 동일하게 사용 가능
- 확장성이 필요하거나 상속 받을 경우엔 interface
- 유니언/인터섹션 타입 조합이 필요하면 type 추천
✅ 6. 유니언 타입으로 prop 제한하기 (리터럴 타입)
type AlertProps = {
type: 'success' | 'error' | 'info';
};
function Alert({ type }: AlertProps) {
return <div className={`alert ${type}`}>{type} 메시지입니다.</div>;
}
- 잘못된 문자열 입력 방지
- setType('loading') → 에러 발생! 👍
✅ 7. HTML 기본 태그 속성과 병행 (extends 활용)
type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
label: string;
};
function Input({ label, ...props }: InputProps) {
return (
<label>
{label}
<input {...props} />
</label>
);
}
- 기본 HTML 속성도 그대로 쓸 수 있게 만들기
- 실무에서는 Button, Input, Textarea 등의 공통 컴포넌트 제작에 자주 사용
✅ 8. 컴포넌트 재사용을 위한 Generic Props
type SelectProps<T> = {
options: T[];
getLabel: (item: T) => string;
};
function Select<T>({ options, getLabel }: SelectProps<T>) {
return (
<select>
{options.map((item, i) => (
<option key={i}>{getLabel(item)}</option>
))}
</select>
);
}
- 고급 패턴이지만 매우 강력함!
- 어떤 데이터든 label만 뽑을 수 있다면 재사용 가능
💬 마무리하며
- Props는 컴포넌트 설계의 핵심
- 명확한 타입 선언은 협업/리팩토링/오류 방지에 큰 도움
- 기본 타입에서 시작해서 점점 유연하게 확장하는 방식이 안전하고 실무에 적합
'TypeScript' 카테고리의 다른 글
| 🔗 API 통신 타입, 이렇게 정의하면 실무에서 편해진다 (React + TypeScript + Axios) (0) | 2025.06.17 |
|---|---|
| 🧠 useState에 타입 주는 가장 깔끔한 패턴 정리 (React + TypeScript) (0) | 2025.06.16 |