본문 바로가기

리액트 공식 문서 읽기

10화: State: A Component's Memory

이 글은 단순히 리액트 공식 문서를 읽고 베꼈을 뿐이다!! 학습 목적이라면 공식 문서를 보는 걸 추천한다.

 

Unsplash 의 Artem Makarov 님 사진

공식 문서

https://react.dev/learn/state-a-components-memory

 

State: A Component's Memory – React

The library for web and native user interfaces

react.dev

State의 등장

컴포넌트가 사용자의 클릭 횟수에 따라 다른 정보를 보여주고 싶어 이 횟수를 기억하는 지역 변수를 선언했다고 치자.
여기에는 두 가지 문제가 있다.

  1. 지역 변수는 렌더링 시 유지되지 않음: 함수형 컴포넌트에서 렌더링이란 해당 함수를 실행하는 것이다. 당연히 이전에 실행했던 함수의 지역 변수는 없어지고 다시 새로운 지역 변수가 생길 것이다.
  2. 지역 변수를 바꾼다고 해도 렌더링을 유발하지 않음: 리액트는 지역변수의 값이 바뀌었을 때 리렌더링을 해야 한다고 생각하지 않는다.

즉 새로운 정보를 가지고 컴포넌트를 업데이트하고 싶다면 다음 두 가지 기능이 있어야 한다는 말이다.

  1. 렌더링 사이에 정보를 잃어버리지 말고 유지하기
  2. 리액트가 새로운 정보를 가지고 렌더링하게 시키기

useState 훅은 이 두 가지를 지원한다.

  1. state variable: 다시 렌더링하더라도 유지되는 정보
  2. state setter function: 정보를 바꾸고 리액트의 컴포넌트 리렌더링 유도

상태 변수 사용하기

  1. import { useState } from 'react';
  2. const [myState, setMyState] = useState(0); 로 상태값과 해당 상태값을 조작하는 함수 받아오기
  3. 조작이 필요하면 setMyState(myState + 1); 이런 식으로 호출해서 쓰기

  • useState 처럼 리액트에서 use 가 붙은 친구들은 '훅' 이라고 부름
  • 리액트 렌더링 과정에서만 사용할 수 있음
  • 리액트의 여러 기능을 사용할 수 있게 도와줌
  • 컴포넌트나 내가 만든 커스텀 훅의 최상단에서만 사용할 수 있음..

useState의 구조

  • useState를 쓴다는 건 리액트에게 이 컴포넌트가 뭔가를 기억했으면 한다고 요청하는 것
  • 컨벤션: const [something, setSomething]
  • useState의 argument는 initial value 혹은 initializer function
  • 컴포넌트가 렌더링될 때마다 useState는 상태값과 상태 변경 함수를 전달해줌
  • 컴포넌트가 리렌더링되면 useState는 argument에 있는 초기값을 보지만 이미 기억하고 있는 값이 있다는 걸 알고 초기값이 아닌 기억하고 있는 값을 돌려줌

컴포넌트 안에서 여러 개의 state 사용 가능

  • 그냥 useState 여러 번 쓰면 됨
  • 서로 무관하다면 서로 다른 상태로 두어도 되지만 form처럼 비슷한 게 여러 개 필요하다면 하나의 상태로 관리하는 걸 고려해봄직 함

리액트는 각 useState가 어떤 상태인지 어떻게 알지?

우리가 useState를 쓸 때 '저는 어떤 이름을 가진 상태입니다' 라고 리액트에게 알려주지 않는다. const [something, setSomething] 이거도 우리가 알아보기 좋으라고 쓰는 컨벤션일 뿐, 사실 const [a, b] 이따구로 쓰더라도 돌아는 갈 것이다. 그렇다면 리액트는 어떻게 어떤 상태인지를 알고 있는 것일까?

컴포넌트 내부의 리액트 훅은 렌더링 단계에서 안정적인 '호출 순서' 에 따라 값을 기억한다. 함수형 컴포넌트의 렌더링이 함수를 실행한다는 점을 생각해 보면 컴포넌트 내부의 여러 useState들은 항상 우리가 적은 순서대로, 위에서부터 아래로 읽힐 것이다. 이를 이용해서 기억하는 것이다. 같은 이유로 훅은 컴포넌트나 내가 만든 커스텀 훅의 최상단에서만 사용할 수 있다. 만약 조건문이나 반복문 안에서 훅을 사용한다면 경우에 따라 훅이 실행될 수도 있고 아닐 수도 있어서 순서가 꼬일 수 있기 때문이다.

내 상태는 사생활이에요!

  • 상태는 화면에 있는 하나의 컴포넌트 인스턴스만을 위한 것
  • 같은 컴포넌트를 다른 위치에 두 개 렌더링하면 각 컴포넌트의 상태는 완전히 독립되어 있음 (옆집 상태를 보거나 건드릴 수 없음)
  • 부모 컴포넌트 역시 자식의 상태를 볼 수 없음
  • 이런 점들이 모듈 상단에 선언하는 변수들과 상태의 차이임
  • 물론 상태를 공유하고 싶다면 여러 방법들이 있지만 그건 이 문서가 아닌 나중 문서에 자세히 나옴

읽고 나서

공식 문서에서는 useState가 일종의 배열을 이용해서 상태 순서와 '어떤' 상태인지를 기억한다고 설명한다. 실제로 내가 아는 그 배열을 쓰는지 너무나도 궁금하다.
하지만 실제 리액트 코드에서는 너무 추상화가 잘 되어 있었다. 조금만 들어가도 대륙 사면을 타고 심해로 들어가 헤어나오지 못할 것 같다는 예감이 들어 더 이상 파고들지는 않았다.
대체가 될 지는 모르겠지만 react-debug-tools의 useState는 이해할 수 있었다. 여기에서는 연결 리스트를 활용하여 각각 어떤 상태인지 기억한다. 아쉽게도 이 패키지는 실험적이고 불안정하다고 쓰여 있어서 실제 리액트의 작동과는 얼마나 차이가 나는지는 알 수 없었다.

'리액트 공식 문서 읽기' 카테고리의 다른 글

12화: State as a Snapshot  (0) 2023.06.15
11화: Render and Commit  (0) 2023.06.15
9화: Responding to Events  (0) 2023.06.14
8화: Keeping Components Pure  (0) 2023.06.13
7화: Rendering Lists  (0) 2023.06.13