← 홈페이지 5강 목록으로
🧩
EPISODE 01
단일 책임 · children · render prop · 합성 vs 상속

컴포넌트 심화

컴포넌트 설계의 핵심 원칙(단일 책임), children/render prop 패턴, 조건부 렌더링 3가지 방법, 그리고 React가 권장하는 합성 vs 상속을 다룹니다.

React컴포넌트합성
소요 시간
45~60분
난이도
📊 중급
선수 조건
🎯 ts-06
결과물
역할이 분리되고 합성 가능한 컴포넌트 설계

이 강의에서 배우는 것

  • 1컴포넌트는 한 가지 역할만 한다는 단일 책임을 적용한다
  • 2children과 render prop으로 유연한 컴포넌트를 만든다
  • 3&&, 삼항, 컴포넌트 분리 — 조건부 렌더링 3가지를 구분한다
  • 4상속 대신 합성으로 컴포넌트를 확장한다

1. 단일 책임 원칙

jsx
// ❌ 나쁜 예 — 하나의 컴포넌트가 너무 많은 일
function UserCard() {
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetch('/api/user').then(r => r.json()).then(setUser);
  }, []);
  return (
    <div>
      <img src={user?.avatar} />
      <h2>{user?.name}</h2>
      <button onClick={() => alert('팔로우!')}>팔로우</button>
    </div>
  );
}

// ✅ 좋은 예 — 역할 분리
function UserAvatar({ src, alt }) { return <img src={src} alt={alt} />; }
function FollowButton({ onFollow }) { return <button onClick={onFollow}>팔로우</button>; }

function UserCard({ user, onFollow }) {
  return (
    <div>
      <UserAvatar src={user.avatar} alt={user.name} />
      <h2>{user.name}</h2>
      <FollowButton onFollow={onFollow} />
    </div>
  );
}

2. children props

jsx
function Card({ children }) {
  return (
    <div style={{ border: '1px solid #ddd', padding: 16, borderRadius: 8 }}>
      {children}
    </div>
  );
}

<Card>
  <h2>제목</h2>
  <p>내용이 여기에 들어갑니다.</p>
</Card>

레이아웃·래퍼 컴포넌트에 자주 사용.

3. render prop 패턴

jsx
function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData);
  }, [url]);
  return render(data);
}

<DataFetcher url="/api/users" render={(users) => (
  <ul>{users?.map(u => <li key={u.id}>{u.name}</li>)}</ul>
)} />

4. 조건부 렌더링

&& 연산자 (단순)

jsx
{hasMessage && <p>{message}</p>}
// 주의: hasMessage가 0이면 "0"이 출력됨 → Boolean(hasMessage) 권장

삼항 (둘 중 하나)

jsx
{isLoggedIn ? <button>로그아웃</button> : <button>로그인</button>}

컴포넌트 분리 (복잡)

jsx
function UserProfile({ isLoading, error, user }) {
  if (isLoading) return <LoadingSpinner />;
  if (error)     return <ErrorMessage message={error} />;
  return <div>{user.name}</div>;
}

5. 합성 vs 상속

구분합성상속
방법children, props로 조합class extends
유연성높음낮음
React 권장
jsx
function Dialog({ title, message, children }) {
  return (
    <div className="dialog">
      <h1>{title}</h1>
      <p>{message}</p>
      {children}
    </div>
  );
}

function WelcomeDialog() {
  return (
    <Dialog title="환영합니다!" message="React 심화 과정에 오신 것을 환영합니다.">
      <button>시작하기</button>
    </Dialog>
  );
}
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗