- Published on
4단계: 상태와 생명주기 이해
4-1. 상태(state)의 개념
컴포넌트 내부에서 변경 가능한 데이터를 의미합니다. useState 훅을 통해 선언합니다.
const [count, setCount] = useState(0);
4-2. 상태의 변경과 리렌더링
setState 함수 호출 시 해당 컴포넌트는 다시 렌더링됩니다. 변경된 state를 기반으로 UI가 자동으로 갱신됩니다.
4-3. 상태 끌어올리기
형제 컴포넌트가 공유하는 상태는 공통 부모 컴포넌트로 끌어올려야 합니다.
function Parent() {
const [value, setValue] = useState("");
return (
<>
<Input value={value} setValue={setValue} />
<Display value={value} />
</>
);
}
4-4. useEffect 기초
useEffect(() => {
console.log("마운트됨");
return () => {
console.log("언마운트됨");
};
}, []);
- 빈 배열이면 처음 1회만 실행
- 특정 값을 넣으면 그 값이 바뀔 때마다 실행
4-5. 의존성 배열의 의미
[ ]
: mount 시 1회 실행[a]
: a가 바뀔 때마다 실행- 생략 시: 렌더링마다 실행 (주의)
4-6. 생명주기 흐름과 대응
클래스형에서는 다음과 같은 생명주기 메서드가 있습니다:
- componentDidMount → useEffect(() => , [])
- componentDidUpdate → useEffect(() => , [state])
- componentWillUnmount → useEffect cleanup return
4-7. 상태 공유 전략 비교
- useState + props: 가장 기본
- Context API: 중간 규모 앱
- Redux, Zustand 등 외부 상태 관리: 대규모
4-8. 상태 성능 최적화
- 불필요한 렌더링 방지
React.memo
,useMemo
,useCallback
등 활용- 상태 분리로 재렌더링 범위 최소화
요약
- useState로 상태를 선언하고 변경 시 리렌더링 발생
- 상태 공유는 상태 끌어올리기로 처리하며 복잡해질 경우 Context나 Redux 도입
- useEffect는 생명주기 역할을 함수형에서 대신함
- 성능 최적화를 위한 리렌더링 제어 기법도 필수
심화학습
Q1. useEffect에서 의존성 배열을 생략하면 어떤 문제가 발생하는가?
A1. 생략하면 렌더링마다 useEffect가 실행되기 때문에 성능 문제가 발생하거나 무한 루프에 빠질 수 있습니다.
Q2. 상태 공유가 많아질수록 컴포넌트 구조가 복잡해지는 이유는?
A2. 끌어올린 상태가 여러 계층으로 전달되면 props drilling이 발생하고 유지보수가 어려워집니다. 이럴 땐 Context나 전역 상태 관리 도구가 필요합니다.
Q3. React에서 상태 관리를 잘못했을 때 성능 이슈가 나는 대표적인 예는?
A3. 한 state 변경이 너무 넓은 범위에 영향을 주면 모든 하위 컴포넌트가 불필요하게 리렌더링됩니다. 상태는 가능한 작게 쪼개고 컴포넌트에 맞게 분리해야 합니다.