React 독학 가이드 5 - Props 완벽 가이드

learning by Seven Fingers Studio 17분
ReactProps컴포넌트데이터전달웹개발

저번에 컴포넌트를 배웠잖아요. 근데 한 가지 문제가 있었어요. 같은 컴포넌트인데 다른 데이터를 보여주고 싶으면 어떡하죠?

예를 들어 프로필 카드 컴포넌트가 있는데, 홍길동, 김철수, 이영희 세 명의 정보를 각각 보여주고 싶다면요?

이때 쓰는 게 Props입니다.

Props가 뭔가요?

Props는 Properties의 줄임말이에요. 부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달하는 방법이죠.

함수의 매개변수라고 생각하면 됩니다.

// 일반 함수
function greet(name) {
  return `안녕하세요, ${name}님!`;
}
greet("홍길동");

// React 컴포넌트
function Greeting({ name }) {
  return <h1>안녕하세요, {name}님!</h1>;
}
<Greeting name="홍길동" />

거의 똑같죠?

Props 기본 사용법

Props 전달하기

부모 컴포넌트에서 HTML 속성처럼 넘겨요:

function App() {
  return (
    <div>
      <Greeting name="홍길동" />
      <Greeting name="김철수" />
      <Greeting name="이영희" />
    </div>
  );
}

실행 결과:

안녕하세요, 홍길동님!

안녕하세요, 김철수님!

안녕하세요, 이영희님!

Props로 다른 데이터를 전달하여 각각 다르게 렌더링되었습니다

Props 받기

자식 컴포넌트에서는 매개변수로 받아요:

// 방법 1: props 객체로 받기
function Greeting(props) {
  return <h1>안녕하세요, {props.name}님!</h1>;
}

// 방법 2: 구조분해 할당 (더 많이 씀)
function Greeting({ name }) {
  return <h1>안녕하세요, {name}님!</h1>;
}

구조분해 할당이 훨씬 깔끔해서 이 방법을 주로 씁니다.

여러 개의 Props 전달

Props는 여러 개 넘길 수 있어요:

function UserCard({ name, age, job, email }) {
  return (
    <div className="user-card">
      <h2>{name}</h2>
      <p>나이: {age}세</p>
      <p>직업: {job}</p>
      <p>이메일: {email}</p>
    </div>
  );
}

function App() {
  return (
    <UserCard
      name="홍길동"
      age={25}
      job="개발자"
      email="hong@example.com"
    />
  );
}

주의: 문자열은 따옴표로, 숫자/변수/객체는 중괄호로 전달해요.

// 문자열
<Component title="제목" />

// 숫자
<Component count={10} />

// 불린
<Component isActive={true} />
<Component isActive />  // true의 축약형

// 배열
<Component items={[1, 2, 3]} />// 객체
<Component user={{ name: "홍길동", age: 25 }} />

// 변수
<Component data={myData} />

객체로 Props 전달하기

데이터가 많으면 객체로 전달하는 게 편해요:

function App() {
  const user = {
    name: "홍길동",
    age: 25,
    job: "개발자",
    email: "hong@example.com"
  };

  return <UserCard user={user} />;
}

function UserCard({ user }) {
  return (
    <div>
      <h2>{user.name}</h2>
      <p>나이: {user.age}세</p>
      <p>직업: {user.job}</p>
    </div>
  );
}

Spread 연산자로 더 깔끔하게

function App() {
  const user = {
    name: "홍길동",
    age: 25,
    job: "개발자"
  };

  // spread 연산자로 펼치기
  return <UserCard {...user} />;
}

// 이렇게 받으면 됨
function UserCard({ name, age, job }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>나이: {age}세</p>
      <p>직업: {job}</p>
    </div>
  );
}

{...user}name="홍길동" age={25} job="개발자"와 같아요.

기본값 설정하기 (Default Props)

Props가 안 넘어올 때를 대비해서 기본값을 설정할 수 있어요:

function Button({ text = "클릭", color = "blue", size = "medium" }) {
  return (
    <button
      style={{
        backgroundColor: color,
        padding: size === "large" ? "15px 30px" : "10px 20px"
      }}
    >
      {text}
    </button>
  );
}

// 사용
<Button />                    // 기본값 사용
<Button text="저장" />        // text만 변경
<Button color="red" size="large" />  // 여러 개 변경

실행 결과:

기본값과 커스텀 Props로 다양한 버튼을 생성했습니다

Children Props

컴포넌트 태그 사이에 넣은 내용은 children으로 받아요:

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

function App() {
  return (
    <Card>
      <h2>제목입니다</h2>
      <p>내용입니다. 뭐든 들어갈 수 있어요.</p>
      <button>버튼도 가능!</button>
    </Card>
  );
}

Card 태그 사이의 모든 내용이 children으로 들어가요. 레이아웃 컴포넌트 만들 때 정말 유용해요.

children 활용 예시: 레이아웃

function PageLayout({ children }) {
  return (
    <div className="page">
      <header>My Website</header>
      <main>{children}</main>
      <footer>© 2025</footer>
    </div>
  );
}

function HomePage() {
  return (
    <PageLayout>
      <h1>홈페이지에 오신 것을 환영합니다!</h1>
      <p>여기는 메인 페이지입니다.</p>
    </PageLayout>
  );
}

function AboutPage() {
  return (
    <PageLayout>
      <h1>소개</h1>
      <p>저희 서비스를 소개합니다.</p>
    </PageLayout>
  );
}

header와 footer는 공통이고, 중간 내용만 페이지마다 달라지죠.

Props는 읽기 전용!

아주 중요한 규칙이 있어요. Props는 수정하면 안 돼요.

// ❌ 절대 하면 안 됨!
function UserCard({ name }) {
  name = "변경된 이름";  // 에러!
  return <h2>{name}</h2>;
}

Props는 부모가 준 데이터예요. 자식이 마음대로 바꾸면 안 됩니다. 이건 React의 핵심 규칙이에요.

데이터를 바꾸고 싶으면 State를 써야 해요. 다음 글에서 배울 거예요.

실전 예제: 상품 목록 만들기

지금까지 배운 걸로 상품 목록을 만들어볼게요.

ProductCard 컴포넌트

function ProductCard({ name, price, discount = 0, image, inStock = true }) {
  const discountedPrice = price * (1 - discount / 100);

  return (
    <div style={{
      border: '1px solid #ddd',
      borderRadius: '12px',
      padding: '15px',
      width: '200px'
    }}>
      <img
        src={image}
        alt={name}
        style={{ width: '100%', borderRadius: '8px' }}
      />
      <h3 style={{ margin: '10px 0 5px' }}>{name}</h3>

      {discount > 0 ? (
        <div>
          <span style={{
            textDecoration: 'line-through',
            color: '#999',
            fontSize: '14px'
          }}>
            {price.toLocaleString()}원
          </span>
          <span style={{ color: 'red', marginLeft: '5px' }}>
            {discount}%
          </span>
          <p style={{
            fontSize: '18px',
            fontWeight: 'bold',
            margin: '5px 0'
          }}>
            {Math.floor(discountedPrice).toLocaleString()}원
          </p>
        </div>
      ) : (
        <p style={{ fontSize: '18px', fontWeight: 'bold' }}>
          {price.toLocaleString()}원
        </p>
      )}

      <p style={{ color: inStock ? 'green' : 'red', fontSize: '14px' }}>
        {inStock ? '구매 가능' : '품절'}
      </p>
    </div>
  );
}

상품 목록

function ProductList() {
  const products = [
    {
      id: 1,
      name: "에어팟 프로",
      price: 359000,
      discount: 15,
      image: "https://via.placeholder.com/200",
      inStock: true
    },
    {
      id: 2,
      name: "아이패드 미니",
      price: 769000,
      discount: 0,
      image: "https://via.placeholder.com/200",
      inStock: true
    },
    {
      id: 3,
      name: "맥북 에어",
      price: 1590000,
      discount: 10,
      image: "https://via.placeholder.com/200",
      inStock: false
    }
  ];

  return (
    <div style={{ display: 'flex', gap: '20px', flexWrap: 'wrap' }}>
      {products.map((product) => (
        <ProductCard
          key={product.id}
          name={product.name}
          price={product.price}
          discount={product.discount}
          image={product.image}
          inStock={product.inStock}
        />
      ))}
    </div>
  );
}

이렇게 하면 상품 데이터만 바꾸면 자동으로 UI가 바뀌어요!

Props vs State 미리보기

헷갈릴 수 있어서 미리 정리해드릴게요:

PropsState
부모가 전달컴포넌트 내부에서 관리
읽기 전용변경 가능
외부에서 받는 데이터내부에서 만드는 데이터

다음 글에서 State를 자세히 다룰 거예요!

다음 단계

Props를 배웠으니, 이제 이벤트 처리를 배울 차례예요. 버튼을 클릭하면 뭔가 하고, 입력창에 뭔가 쓰면 반응하고… 이런 것들이요.

Props 개념이 익숙해지면 React가 훨씬 재밌어져요. 컴포넌트 간에 데이터를 주고받으면서 앱을 만드는 게 레고 조립하는 것 같거든요!


React 시리즈 탐색:

← 블로그 목록으로