반디북
리액트 훅을 활용한 마이크로 상태 관리
Ch2
준영

02. 지역 상태와 전역 상태 사용하기

언제 지역 상태를 사용할까?

순수 함수

  • 오직 인수에만 의존하며 동일한 인수가 들어오면 항상 동일한 값을 반환한다.

✅ “리액트 컴포넌트는 순수할 수 있지만, 컴포넌트 내에서 지역 상태를 사용할 경우 순수하지 않게 된다.”
위의 문구는 컴포넌트 내 상태의 값의 변화에 따라 반환되는 JSX가 달라지기 때문에 이렇게 표현하지 않았을까?
하지만 이는 좀더 큰 개념에서 바라보았을때, 다른 외부 컴포넌트에 영향을 끼치지 않으므로 상대적으로 순수하다.
책에서는 이것을 억제됨(contained) 이라고 표현하는 것 같다.

🍪 Cookie!

자바스크립트의 전역 변수의 경우,
한번 생성되고 나면 window 객체에 등록되어 이후 참조시 window 객체에 등록된 값을 반환한다.

리액트는 개념적으로 상태를 사용자 인터페이스를 변환하는 함수이다.
즉, 리액트 컴포넌트는 화면에 값을 표시하는 JSX 요소를 반환한다.

const AddBase = ({ number }) => {
	const [base, changeBase] = useState(1);
	return <div>{number + base}</div>
}

위의 코드는 책에서 억제된 컴포넌트로 설명하는 예시이다.
base라는 상태를 변경하기 위해서는 changeBase 함수에 접근해야 하는데, 이는 AddBase 함수 범위 내에서만 사용 가능하므로 외부에서 접근이 불가능하다.
따라서 이는 지역 상태를 사용하고 있으며 억제되어있다.
또한 외부 컴포넌트에 어떠한 영향도 미치지 않기 때문에 지역성을 보장한다.

그럼 어떨 때 지역 상태를 사용하면 안될까?
컴포넌트 외부에서 상태를 변경해야 할 때는 전역 상태를 사용해야 한다.
하지만, 전역 상태는 컴포넌트의 동작을 예측하기 어렵다는 단점이 있다.

꼭 필요할 때 "보조 수단"으로 사용하자!

지역 상태를 효과적으로 사용하는 방법

상태 끌어올리기 (Lifting State Up)

공통으로 사용할 상태를 부모 컴포넌트에서 정의하고 이를 자식 컴포넌트에 props로 내려준다.
이 패턴은 일부 상황에서 부모 컴포넌트의 상태 변경에 의해 모든 자식 컴포넌트의 리렌더링이 발생하는 성능 문제가 존재할 수 있다.

const Child1 = ({ count, setCount }) => {
	return ~~~~;
}
const Child2 = ({ count, setCount }) => {
	return ~~~~;
}
 
const Parent = () => {
  const [count, setCount] = useState(0);
 
  return (
    <>
      <Child1 count={count} setCount={setCount} />
      <Child2 count={count} setCount={setCount} />
    </>
  );
};

내용 끌어올리기 (Lifting Content Up)

자식 컴포넌트에는 상위 컴포넌트에 의존하지 않는 컴포넌트가 존재할 수 있다.
따라서 성능 문제를 방지하기 위해 JSX 요소를 상위 컴포넌트로 끌어올려 이런 불필요한 리렌더링을 줄일 수 있다.
컴포넌트 자체를 props로 전달하거나 children prop을 활용하여 사용할 수 있다.

전역 상태 사용하기

전역 상태

  • 하나의 컴포넌트에만 속하지 않고, 여러 컴포넌트에서 사용할 수 있는 상태이다.

리액트에서는 다음 두 상황에서 전역 상태를 사용한다.

  • Prop을 전달하는 것이 적절하지 않을 때
  • 이미 리액트 외부에 상태가 있을 때

✅ 먼저, 첫번째 상황은 props drilling을 말하는 것 같다.
상위 컴포넌트에서 특정 상태를 하위 컴포넌트에 전달하기 위해 props로 전달하는데, 이 전달을 위한 뎁스가 깊어지면 이는 굉장히 불필요하며, 가독성을 해칠 수 있다.
또한 해당 상태가 변경되었을 때, 모든 중간 컴포넌트가 리렌더링되며 성능 문제가 발생할 수도 있다.
따라서 이러한 경우 전역 상태를 사용하는 것이 좋다.

그리고 두번째 상황은 사용자 인증 정보를 예시로 설명한다.
즉, Access Token이나 Refresh Token과 같은 인증 정보를 전역 상태에 저장한다.

도은

언제 지역 상태를 사용할까?

💡 리액트는 개념적으로 상태를 사용자 인터페이스(UI)로 변환하는 함수다.
const Component = ({ number }) => {
  return <div>{number}</div>;
};

👆 number라는 인수를 받아 값을 표시하는 JSX(JavaScript syntax extension) 요소를 반환

혼자 정리해보기..

리액트의 컴포넌트 = 값을 표시하는 JSX 요소를 반환하는 함수

🤔 JSX 요소

  • 리액트 요소를 생성하기 위한 구문
  • 리액트 요소 = UI의 일부를 나타내는 자료구조

🤔 억제되어 있는 함수

const AddBase = ({ number }) => {
  const [base, changeBase] = useState(1);
  return <div>{number + base}</div>;
};
  • changeBase를 함수 선언 내에서만 사용 가능 → 억제된 것
  • 이렇게 useState를 사용하는 것 → 지역 상태
  • 컴포넌트는 억제, 외부에 그 어떤 것에도 영향X → 지역성 보장

🤔 지역 상태의 한계

🤔 지역 상태를 언제 사용해서는 안 될까?
  • 컴포넌트 외부에서 상태를 변경해야 한다면, 전역 상태 필요
  • 과하게 사용하면, 컴포넌트 동작 예측이 어려워진다.

지역 상태를 효과적으로 사용하는 방법

지역 상태를 효과적으로 사용하기 위해 알아야 하는 패턴을 알아보자.

1. 상태 끌어올리기(Lifting State Up)

  • 두 컴포넌트가 상태를 공유하고 싶다면, 부모 컴포넌트를 만들고 전달받으면 된다.
const Parent = () => {
  const [count, setCount] = useState(0);
 
  return (
    <>
      <Component1 count={count} setCount={setCount} />
      <Component2 count={count} setCount={setCount} />
    </>
  );
};

2. 내용 끌어올리기(Lifting Content Up)

  • 상위 컴포넌트의 상태에 의존하지 않는 컴포넌트가 있을 수 있다.
  • 불필요한 렌더링을 방지하기 위해서는 JSX 요소를 상위 컴포넌트로 끌어올릴 수도 있다.

전역 상태 사용하기

💡 하나의 컴포넌트에만 속하지 않고 여러 컴포넌트에서 사용할 수 있다면 전역상태라고 한다.

🤔 언제 전역 상태를 사용할까?

  • prop을 전달하는 것이 적절하지 않을 때
    • props drilling
  • 이미 리액트 외부에 상태가 있을 때
    • 예를 들면, accessToken