State: 컴포넌트의 기억
State: 컴포넌트의 기억
컴포넌트는 보통 어떤 값을 '기억'해야 해요 — 입력 중인 텍스트, 현재 보고 있는 이미지, 장바구니에 담긴 목록까지. 그런데 함수는 실행이 끝나면 지역 변수가 사라지니까, 렌더링 사이에 값을 보관하려면 남들과 구분되는 저장소가 필요해요. React에서는 이렇게 컴포넌트 고유의 기억 공간을 state라고 불러요.
일반 변수로는 왜 부족할까요
props처럼 이미 받은 값은 그대로 보여주면 되지만, 사용자 입력에 따라 바뀌는 값은 얘기가 달라요. 일반 지역 변수는 렌더링이 끝나면 휘발되기 때문에, 렌더링 사이에 값을 보존하려면 두 가지가 필요해요.
- 렌더링 사이 데이터를 품고 있는 state 변수
- 값을 바꾸면서 React에게 다시 그리라고 알려주는 setter 함수
useState가 이 두 개를 배열로 돌려준답니다.
첫 번째 Hook, useState
useState는 React의 훅 중 하나예요. 훅은 함수지만, 컴포넌트의 '필요 사항을 선언'한다고 보는 게 이해에 도움이 돼요. 파일 위에서 모듈을 import 하듯, 컴포넌트 함수의 최상단에서 기능을 '사용'한다고 생각하면 돼요.
const [index, setIndex] = useState(0);
useState에 넘기는 유일한 인자는 state 변수의 초깃값이에요. 위 코드는 초깃값 0을 넣어 [0, setIndex]을 받는 셈이죠. 값이 바뀌는 흐름을 따라가 보면 이래요.
- 컴포넌트가 처음 렌더링될 때,
useState(0)은index가0인 배열을 돌려줘요. React는 최신 값이0임을 기억해요. - 사용자가 버튼을 눌러
setIndex(1)을 호출하면, React는index를1로 기억하고 다시 렌더링을 예약해요. - 두 번째 렌더링에서도 코드는 여전히
useState(0)이지만, React가 값을 바꿔놨으므로[1, setIndex]을 돌려줘요. 초깃값은 첫 렌더링에서만 의미가 있는 거예요.
state는 여러 개 둘 수 있어요
컴포넌트 하나에 useState를 여러 번 부르면 여러 state 변수를 가질 수 있어요. 다만 form처럼 필드가 많은 경우엔 필드마다 변수를 두기보다 객체 하나를 state로 두는 편이 다루기 쉬울 때가 많아요. React는 컴포넌트마다 state 쌍 배열을 들고 있고, useState를 호출할 때마다 다음 순서의 state를 돌려줘요. 그래서 훅의 순서가 바뀌면 안 되는 거예요.
state는 격리되고 비공개예요
state는 특정 함수 호출이나 코드 위치가 아니라, 화면에 있는 컴포넌트 인스턴스에 묶인 값이에요. 같은 컴포넌트를 두 번 렌더링하면 두 인스턴스는 완전히 독립된 state를 가져서, 하나를 바꿔도 다른 쪽은 영향받지 않아요. 또 props와 달리 state는 선언한 컴포넌트만 접근할 수 있고 부모가 건드릴 수 없어요.
만약 두 화면의 state를 동기화하고 싶다면, 각 자식이 state를 갖게 하는 대신 가장 가까운 공통 부모로 state를 올려서 내려주는 게 React의 정석이에요. 그리고 렌더링 사이에 보관할 필요가 없는 값은 굳이 state로 만들지 않아요 — 이벤트 핸들러 안에서만 쓰이는 값은 일반 변수로 충분해요.
더 알아보기
- useState 레퍼런스 — 확정된 API 시그니처를 보고 싶을 때 읽어요
- state 구조 선택하기 — state를 어떻게 묶을지 고민할 때 봐요
- 컴포넌트에 props 전달하기 — state를 부모로 올리는 동기화 방식의 기초예요