누구나 로고
Online CoursesFor BusinessLibraryTrend InsightsFree coursesNoticesContactCareers
모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.
로그인무료 회원가입
강좌리액트 입문 — 컴포넌트로 만드는 웹13강

13강 / 전체 28강

상태 끌어올리기

5분 읽기 조회 0

상태 끌어올리기 패턴으로 형제 컴포넌트 간 상태를 공유하는 방법과 컴포넌트 합성(Composition) 패턴의 실전 활용을 배웁니다.

🤝 왜 상태를 끌어올려야 하는가

두 컴포넌트가 동일한 데이터를 공유해야 할 때 어떻게 해야 할까요? 리액트에서 데이터는 항상 위에서 아래로(부모 → 자식) 흐릅니다. 형제 컴포넌트끼리 직접 데이터를 주고받을 수 없습니다. 이 문제를 해결하는 패턴이 상태 끌어올리기(Lifting State Up)입니다.

핵심 아이디어: 두 컴포넌트가 공유해야 하는 상태를 가장 가까운 공통 부모로 이동시킵니다.

📌 문제 상황 — 온도 변환기

섭씨와 화씨 입력창이 있고, 하나를 바꾸면 다른 것도 자동으로 업데이트됩니다:

// ❌ 각자 state를 가지면 동기화 불가
function CelsiusInput() {
  const [value, setValue] = useState('')
  return <input value={value} onChange={(e) => setValue(e.target.value)} />
}

function FahrenheitInput() {
  const [value, setValue] = useState('')  // 완전히 별개의 상태!
  return <input value={value} onChange={(e) => setValue(e.target.value)} />
}

이렇게 만들면 두 입력창의 값이 서로 연동되지 않습니다. 해결책은 상태를 부모로 끌어올리는 것입니다.

✅ 해결 — 상태를 공통 부모로 이동

// 자식 컴포넌트들: 값과 콜백을 Props로 받음
function TemperatureInput({
  label,
  value,
  onChange,
}: {
  label: string
  value: string
  onChange: (val: string) => void
}) {
  return (
    <label className="block">
      <span className="text-sm font-medium">{label}</span>
      <input
        type="number"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className="mt-1 block w-full border rounded px-3 py-2"
      />
    </label>
  )
}

// 부모: 상태를 가지고 두 자식에 내려줌
function TemperatureConverter() {
  const [celsius, setCelsius] = useState('')

  const fahrenheit = celsius !== ''
    ? String(Math.round(parseFloat(celsius) * 9 / 5 + 32))
    : ''

  function handleCelsiusChange(val: string) {
    setCelsius(val)
  }

  function handleFahrenheitChange(val: string) {
    const f = parseFloat(val)
    if (!isNaN(f)) {
      setCelsius(String(Math.round((f - 32) * 5 / 9)))
    } else {
      setCelsius('')
    }
  }

  return (
    <div className="space-y-4 p-6 max-w-sm">
      <h2 className="text-xl font-bold">온도 변환기</h2>
      <TemperatureInput label="섭씨 (°C)" value={celsius} onChange={handleCelsiusChange} />
      <TemperatureInput label="화씨 (°F)" value={fahrenheit} onChange={handleFahrenheitChange} />
    </div>
  )
}

이제 섭씨 입력창을 바꾸면 부모의 celsius state가 업데이트되고, fahrenheit 값이 자동으로 계산되어 두 번째 입력창에 반영됩니다.

🧩 컴포넌트 합성 (Composition)

상태 끌어올리기와 함께 중요한 패턴이 합성(Composition)입니다. children이나 render props를 활용해 컴포넌트를 유연하게 조합합니다.

// 레이아웃 컴포넌트 — children으로 내용을 유연하게 받음
function Panel({
  title,
  children,
  action,
}: {
  title: string
  children: React.ReactNode
  action?: React.ReactNode  // 헤더 오른쪽에 올 요소 (선택)
}) {
  return (
    <div className="rounded-2xl border border-gray-100 overflow-hidden">
      <div className="flex items-center justify-between px-6 py-4 border-b bg-gray-50">
        <h3 className="font-bold text-gray-900">{title}</h3>
        {action}
      </div>
      <div className="p-6">{children}</div>
    </div>
  )
}

// 사용: 완전히 다른 내용을 같은 Panel에 담을 수 있음
function Dashboard() {
  return (
    <div className="space-y-4">
      <Panel title="최근 주문" action={<button className="text-sm text-indigo-600">전체 보기</button>}>
        <OrderList />
      </Panel>

      <Panel title="알림" action={<span className="text-xs bg-red-100 text-red-600 px-2 py-0.5 rounded-full">3개 미읽음</span>}>
        <NotificationList />
      </Panel>
    </div>
  )
}

🗂️ 언제 상태를 끌어올릴까

항상 가장 가까운 공통 부모까지만 올립니다. 불필요하게 높이 올리면 prop drilling(깊은 곳까지 props를 전달하는 것)이 생깁니다. 규칙:

  • 형제 컴포넌트가 같은 데이터를 필요로 할 때 → 부모로 끌어올리기
  • 한 컴포넌트만 사용하는 상태 → 그 컴포넌트 안에 유지
  • 많은 컴포넌트가 공유해야 할 때 → Context(뒤에서 다룸)

✅ 정리

  • 리액트 데이터는 위→아래 단방향. 형제 컴포넌트는 직접 통신 불가.
  • 공유 상태는 가장 가까운 공통 부모로 끌어올립니다.
  • 자식은 값(Props)과 콜백(함수 Props)을 받아 표시하고 변경 요청만 합니다.
  • children과 선택적 Props(action?)로 유연한 합성 컴포넌트를 만듭니다.

관련 주제

  • lifting state up
  • 공통 부모 컴포넌트
  • 콜백으로 상태 변경 전달
  • 형제 컴포넌트 상태 공유
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 리액트 입문 — 컴포넌트로 만드는 웹
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나
이전 12강데이터 가져오기(fetch)다음 14강 컴포넌트 합성과 재사용

댓글

0/1000

불러오는 중...

목차

  1. 1.리액트란 무엇인가
  2. 2.개발 환경 만들기 — Vite
  3. 3.JSX 기초
  4. 4.컴포넌트 만들기
  5. 5.Props로 데이터 전달
  6. 6.State와 useState
  7. 7.이벤트 처리
  8. 8.조건부 렌더링
  9. 9.리스트 렌더링과 key
  10. 10.폼 다루기
  11. 11.useEffect 기초
  12. 12.데이터 가져오기(fetch)
  13. 13.상태 끌어올리기
  14. 14.컴포넌트 합성과 재사용
  15. 15.useRef와 DOM 접근
  16. 16.커스텀 훅 만들기
  17. 17.Context API
  18. 18.useReducer
  19. 19.리스트 앱 실전 ①
  20. 20.리스트 앱 실전 ②
  21. 21.라우팅 — React Router
  22. 22.스타일링 방법들
  23. 23.리스트·상세 페이지 연결
  24. 24.비동기 상태 관리 패턴
  25. 25.성능 기초 — memo
  26. 26.에러 처리와 경계
  27. 27.환경변수와 빌드
  28. 28.배포하기

Support

  • Notices
  • FAQ
  • Contact Us
  • Community

Help & Info

  • Terms of Service
  • Privacy Policy
  • Refund Policy

Services

  • About Us
  • Sign up
  • New courses
  • Free courses
누구나 로고
Terms of ServicePrivacy PolicyRefund Policy

상호명: NUGUNA  |  대표자: 정우진  |  사업자등록번호: 392-32-01817  |  통신판매업신고: 제 2026-서울양천-0564 호

주소: 서울특별시 양천구 목동서로 100  |  이메일: nugunapass@gmail.com  |  전화: 010-6395-3043

© 2026 NUGUNA. All rights reserved.

KB예금주인증관리자
HomeCoursesLibraryContactMY