2 분 소요

개요

Props(Properties)는 부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달하는 방법입니다. Props는 읽기 전용(Read-Only)으로, 자식 컴포넌트는 전달받은 props를 변경할 수 없습니다.


기본 사용법

Props 전달 (부모)

function App() {
  return (
    <div>
      {/* 속성처럼 값을 전달 */}
      <UserCard name="Alice" age={30} job="개발자" />
      <UserCard name="Bob" age={25} job="디자이너" />
    </div>
  );
}

Props 받기 (자식)

// TypeScript: interface로 타입 정의
interface UserCardProps {
  name: string;
  age: number;
  job: string;
}

// 구조분해(destructuring)로 받기 (권장)
function UserCard({ name, age, job }: UserCardProps) {
  return (
    <div>
      <h2>{name}</h2>
      <p>나이: {age}</p>
      <p>직업: {job}</p>
    </div>
  );
}


Optional Props와 기본값

interface ButtonProps {
  label: string;
  color?: string;       // ? = 선택사항 (optional)
  disabled?: boolean;
}

// 기본값은 = 으로 지정
function Button({ label, color = "blue", disabled = false }: ButtonProps) {
  return (
    <button
      style=
      disabled={disabled}
    >
      {label}
    </button>
  );
}

// 사용
<Button label="확인" />                    // color="blue", disabled=false
<Button label="취소" color="gray" />       // disabled=false
<Button label="삭제" color="red" disabled />  // disabled=true


children Props

컴포넌트 태그 사이에 넣은 내용을 children으로 받습니다.

import { ReactNode } from "react";

interface CardProps {
  title: string;
  children: ReactNode;   // ReactNode = JSX, 문자열, 숫자 등 모든 렌더링 가능한 값
}

function Card({ title, children }: CardProps) {
  return (
    <div style=>
      <h3>{title}</h3>
      {children}          {/* 태그 사이 내용이 여기에 렌더링됨 */}
    </div>
  );
}

// 사용
<Card title="사용자 정보">
  <p>이름: Alice</p>
  <p>이메일: alice@example.com</p>
</Card>


함수 Props (콜백)

부모의 함수를 자식에게 전달해, 자식이 이벤트를 발생시킬 때 부모에게 알립니다.

interface ConfirmDialogProps {
  message: string;
  onConfirm: () => void;   // 인자 없는 함수
  onCancel: () => void;
}

function ConfirmDialog({ message, onConfirm, onCancel }: ConfirmDialogProps) {
  return (
    <div>
      <p>{message}</p>
      <button onClick={onConfirm}>확인</button>
      <button onClick={onCancel}>취소</button>
    </div>
  );
}

// 사용
function App() {
  const handleConfirm = () => {
    console.log("확인 클릭");
  };

  return (
    <ConfirmDialog
      message="정말 삭제하시겠습니까?"
      onConfirm={handleConfirm}
      onCancel={() => console.log("취소")}
    />
  );
}


Props 전개(Spread)

객체의 모든 속성을 한 번에 전달할 때 사용합니다.

interface UserCardProps {
  name: string;
  age: number;
  job: string;
}

const user: UserCardProps = { name: "Alice", age: 30, job: "개발자" };

// 개별 전달
<UserCard name={user.name} age={user.age} job={user.job} />

// 전개 연산자로 한 번에 전달
<UserCard {...user} />


Props 주의사항

단방향 데이터 흐름

App (부모)
 └──> UserCard (자식)   Props는 이 방향으로만!

자식은 props를 읽을 수만 있고 변경할 수 없습니다.

function UserCard({ name }: { name: string }) {
  // ❌ props 직접 변경 불가
  // name = "Bob";  // 오류

  return <p>{name}</p>;
}

Props Drilling 문제

props를 여러 단계를 거쳐 깊이 전달하면 코드가 복잡해집니다.

App → Page → Section → Article → Content → Button
(Button에서 필요한 데이터를 5단계 거쳐 전달)

이 문제는 Context API 또는 Zustand 같은 상태 관리 라이브러리로 해결합니다.


관련 링크