React – 상태 관리와 Hooks – State와 Props – 3 – 상태 끌어올리기 패턴

React – 상태 관리와 Hooks – State와 Props – 3 – 상태 끌어올리기 패턴

React – 상태 관리와 Hooks – State와 Props – 3 – 상태 끌어올리기 패턴

안녕하세요, 리액트를 함께 배우고 있는 여러분! 😊
오늘은 React 개발에서 공통적으로 데이터를 관리해야 할 때 자주 등장하는 핵심 개념, 바로 “상태 끌어올리기(Lifting State Up)” 패턴에 대해 자세히 설명드릴게요.

이 개념은 마치 가족끼리 쓰는 리모컨을 하나로 정리하는 것과 비슷해요.
각 방마다 다른 리모컨이 있으면 헷갈리잖아요? 상태도 마찬가지예요. 여러 자식 컴포넌트에서 같은 데이터를 쓰고 바꿔야 한다면, 중앙에 하나로 묶어서 관리하는 게 깔끔하고 효율적이랍니다!


1. 상태 끌어올리기가 필요한 상황

자식 컴포넌트 여러 개가 같은 데이터를 참조하거나 수정할 필요가 있을 때,
각 자식에서 따로 상태를 관리하면 동기화가 깨지고 버그가 발생할 수 있어요.

그래서 이럴 땐 부모 컴포넌트로 상태를 끌어올려서 한 곳에서 관리하고,
각 자식은 props로 상태와 변경 함수를 받아서 사용하게 됩니다.


2. 예시 상황: 두 입력값을 비교해야 할 때

❌ 상태를 자식이 각각 가질 경우

function TemperatureInput() {
  const [temp, setTemp] = useState('');
  return <input value={temp} onChange={e => setTemp(e.target.value)} />;
}

function Calculator() {
  return (
    <>
      <TemperatureInput />
      <TemperatureInput />
    </>
  );
}
  • 두 컴포넌트는 각각 다른 state를 갖고 있어서 서로 연동되지 않아요.
  • 이때는 상태를 부모 Calculator로 끌어올려야 합니다.

3. ✅ 상태 끌어올리기 적용 예시

function TemperatureInput({ label, temperature, onTemperatureChange }) {
  return (
    <div>
      <label>{label}</label>
      <input
        value={temperature}
        onChange={e => onTemperatureChange(e.target.value)}
      />
    </div>
  );
}

function Calculator() {
  const [temperature, setTemperature] = useState('');

  return (
    <>
      <TemperatureInput
        label="섭씨"
        temperature={temperature}
        onTemperatureChange={setTemperature}
      />
      <TemperatureInput
        label="화씨"
        temperature={temperature}
        onTemperatureChange={setTemperature}
      />
    </>
  );
}

👉 흐름 정리

  • Calculator상태의 소유자
  • 두 자식 컴포넌트는 같은 값을 props로 받고,
  • 입력을 변경하면 부모의 상태(setTemperature)가 갱신됨
  • 결국 두 입력창이 동일한 값을 공유하게 됨

4. 상태 끌어올리기의 일반적인 절차

  1. 공통으로 필요한 데이터를 찾는다.
  2. 그 데이터를 부모 컴포넌트로 끌어올려서 useState로 선언한다.
  3. 그 값을 자식 컴포넌트에 props로 전달한다.
  4. 자식 컴포넌트가 데이터를 바꿔야 한다면, 변경 함수도 props로 전달한다.

5. 또 다른 예시: 체크박스 동기화

function ChildCheckbox({ label, checked, onToggle }) {
  return (
    <label>
      <input type="checkbox" checked={checked} onChange={onToggle} />
      {label}
    </label>
  );
}

function Parent() {
  const [isChecked, setIsChecked] = useState(false);

  return (
    <>
      <ChildCheckbox
        label="옵션 A"
        checked={isChecked}
        onToggle={() => setIsChecked(prev => !prev)}
      />
      <ChildCheckbox
        label="옵션 B"
        checked={isChecked}
        onToggle={() => setIsChecked(prev => !prev)}
      />
    </>
  );
}

➡️ 이처럼 하나의 상태를 공유해서 두 체크박스가 동시에 체크/해제되도록 만들 수 있어요.


6. 상태 끌어올리기의 장점

장점 설명
데이터 일관성 유지 여러 자식이 같은 상태를 사용할 때 버그 방지
유지보수 용이 상태 위치를 한눈에 파악 가능
테스트 용이성 ↑ 상태 추적과 흐름 분석이 쉬움
재사용성 향상 Dumb 컴포넌트화하여 다양한 상황에 활용 가능

7. 상태 끌어올릴 때 주의할 점

항목 설명
상태 위치 과도하게 끌어올리지 않기 너무 상위로 올리면 컴포넌트 간 결합도 증가
props 전달이 복잡해질 수 있음 중첩이 깊을 경우 Context 사용 고려
자식 컴포넌트는 상태를 변경하지 말고 반드시 props로 받은 콜백 함수만 사용해야 함

8. 실전에서 자주 쓰이는 상황 예

  • 입력 폼에서 여러 필드 상태를 한 부모에서 관리할 때
  • 검색 필터처럼 여러 컴포넌트가 동일한 필터 기준을 공유할 때
  • 다중 선택 UI에서 모든 선택 항목을 부모에서 제어할 때
  • 동기화된 UI (예: 슬라이더와 숫자 입력창)

9. 비슷한 개념: Controlled vs Uncontrolled

구분 설명
Controlled 상태를 부모에서 제어 (React 권장 방식)
Uncontrolled 상태를 DOM에서 직접 관리 (ref 사용)

➡️ 상태 끌어올리기는 Controlled 컴포넌트 전략의 연장선이에요!


10. 마무리하며

상태 끌어올리기는 React에서 복잡한 UI를 유기적으로 구성할 수 있는 핵심 패턴입니다.
각 자식이 제각각 데이터를 관리하기보단, 공통의 상위 부모가 중심을 잡고 흐름을 컨트롤하는 구조를 만드는 게 훨씬 안정적이에요.

이 구조를 잘 익혀두면 다음 단계에서 배우게 될 Context API전역 상태 관리 도구(Redux, Recoil 등) 도 더욱 쉽게 이해할 수 있답니다!

📌 한 문장으로 정리하면:

“여러 자식이 같은 데이터를 사용한다면, 상태는 그들의 공통 부모에 있어야 한다!”

다음 글에서는 이 흐름 위에서 효율적인 데이터 처리와 최적화 방법을 다뤄보겠습니다. 함께 꾸준히 배워가요! 🚀

답글 남기기