본문 바로가기
C.W.K.
Stream
Lesson 01 of 07 · published

React 19와 TypeScript: 컴포넌트 경계에 타입 놓기

~10 min · frameworks, react, react-19, components

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"컴포넌트는 JSX를 돌려주는 함수이고, props 타입은 그 함수의 공개 입구야."

props에서 시작하기

ButtonPropslabel과 선택적 onPress를 선언해. 컴포넌트 매개변수에 이 타입을 붙이면 호출하는 JSX까지 계약이 이어져. 필수 props 누락과 이름 오타, 잘못된 콜백 시그니처를 렌더링 전에 찾을 수 있지.

반환 타입은 JSX에서 잘 추론되므로 모든 컴포넌트에 억지로 적을 필요는 없어. 공개 경계를 문서화하거나 잘못된 반환을 함수 안에서 막고 싶을 때 React.ReactNode 등 프로젝트의 React 타입 버전에 맞는 타입을 명시해.

React.FC는 선택이지 금지가 아니다

React.FC<Props>를 쓸 수도 있고 함수 매개변수에 Props를 직접 붙일 수도 있어. 현대 React 타입에서 예전의 children 동작에 대한 조언을 그대로 외우면 안 돼. 팀의 일관성과 제네릭 표현, 반환 타입 요구를 보고 고르되 두 스타일을 근거 없이 섞지 마.

children을 받는 컴포넌트라면 children: React.ReactNode를 props에 명시해. 특정 엘리먼트나 렌더 함수만 허용해야 한다면 더 좁은 타입으로 실제 사용 계약을 표현해야 해.

이벤트 타입은 문맥에서 얻기

JSX 안의 인라인 핸들러는 대상 요소에서 이벤트 타입을 추론해. 별도 함수로 빼면서 타입이 필요하면 React.MouseEvent<HTMLButtonElement>처럼 요소를 포함한 이벤트 타입을 쓸 수 있어.

DOM 이벤트와 React 이벤트 타입을 무심코 섞지 말고, 핸들러가 어느 경계에서 호출되는지 확인해. 대개 이벤트 객체 전체보다 컴포넌트가 실제로 필요한 값만 상위 콜백에 전달하는 편이 결합을 줄여.

React 타입의 중심은 컴포넌트 입구와 출구의 관계야. props를 정확히 만들고 문맥 추론을 살리면 나머지는 평범한 TypeScript처럼 흐른다.

Code

Props, children, event handler 가진 component·tsx
import { useState } from 'react';

interface ButtonProps {
  label: string;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
  children?: React.ReactNode;
}

export function Button({ label, onClick, variant = 'primary', disabled, children }: ButtonProps) {
  return (
    <button onClick={onClick} disabled={disabled} className={`btn btn-${variant}`}>
      {label}
      {children}
    </button>
  );
}

// Event handler — inline 추론.
function Form() {
  const [value, setValue] = useState('');
  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}    // e: React.ChangeEvent<HTMLInputElement>
    />
  );
}

External links

Exercise

제목은 필수, 설명과 액션 영역은 선택인 Card 컴포넌트를 작성해. 액션 영역은 React가 렌더할 수 있는 노드를 받아.
Hint
interface CardProps { title: string; description?: string; actions?: React.ReactNode }. 그다음 <Card title="..." actions={<Button ... />} />.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.