본문 바로가기

코딩

React Hook, 왜 이렇게 복잡한 걸까요?

공부하는 아이 일러스트 이미지

 

 

 React 개발을 하다 보면, 어느 순간부터 함수형 컴포넌트가 대세라는 사실을 깨닫게 돼요. 그런데 클래스형 컴포넌트에서 this.setState 잘 쓰고 있었는데, 갑자기 useState, useEffect, useMemo 같은 이상한 녀석들이 튀어나옵니다. 😵‍🚫

 

"이걸 왜 써야 하죠?" 🤷‍♂️라고 묻는 분들도 많아요. 답은 간단합니다. 코드가 간결해지고, 성능이 좋아지고, 유지보수가 쉬워지거든요. 하지만, "간결한 코드"를 위해 더 많은 개념을 배워야 한다는 함정이 숨어있죠. 😂 그래서 React Hook을 마스터하는 게 중요합니다!

 

🏆 필수 Hook 정리

Hook 역할
useState 상태 관리 (기본)
useEffect 사이드 이펙트 처리 (비동기, API 요청 등)
useRef DOM 요소 접근 & 값 유지
useMemo 값 메모이제이션 (성능 최적화)
useCallback 함수 메모이제이션 (불필요한 리렌더 방지)
useContext 전역 상태 관리 (Redux 없이 간단하게)
useReducer 복잡한 상태 관리 (Redux 대체 가능)
useLayoutEffect 렌더링 전에 동작 (UI 깜빡임 방지)

 

🔥 useState, 그거 그냥 변수 아닌가요?

useState는 컴포넌트의 상태를 관리하는 Hook이에요. 단순한 값부터 객체까지 다룰 수 있어요. 클래스형 컴포넌트에서는 this.state로 관리하던 걸 이제 useState 하나로 해결할 수 있죠.

const [count, setCount] = useState(0);

👆 이렇게 하면 count라는 상태 변수가 생기고, setCount로 값을 변경할 수 있어요.

 

하지만 함정이 있습니다. useState로 값을 변경해도 즉시 반영되지 않는다는 점이죠. 😨 그래서 이전 값을 기반으로 업데이트할 땐 이렇게 써야 해요.

setCount(prev => prev + 1);

👉 이걸 안 지키면 예상치 못한 버그가 생길 수 있어요. 🐛

 

🎯 useEffect, 언제 실행되는 거죠?

useEffect는 컴포넌트가 렌더링될 때 부수 효과(side effect)를 처리하는 역할을 해요. 예를 들면 API 호출, 이벤트 리스너 등록, 타이머 설정 같은 것들이죠.

useEffect(() => {
  console.log("컴포넌트가 마운트됨!");
  return () => console.log("컴포넌트가 언마운트됨!");
}, []);

👉 빈 배열([])을 넣으면 한 번만 실행되고, 특정 변수를 넣으면 그 값이 변경될 때마다 실행됩니다. 💡

🚨 주의: useEffect 안에서 상태를 변경하면 무한 루프에 빠질 수도 있어요! 😱

 

🚀 useMemo & useCallback, 성능 최적화 필수템

React에서 불필요한 리렌더링을 막는 게 중요해요. 여기서 등장하는 게 useMemouseCallback입니다.

const memoizedValue = useMemo(() => 계산_값, [의존성]);
const memoizedFunction = useCallback(() => 함수_정의, [의존성]);

useMemo을 저장해서 불필요한 계산을 줄이고, useCallback함수를 저장해서 렌더링 때마다 새로운 함수가 생성되는 걸 막아요.

 

언제 써야 할까?

  • 연산량이 많은 작업을 할 때 (useMemo)
  • 특정 함수를 계속 재사용해야 할 때 (useCallback)
  • props로 함수를 넘길 때 (useCallback)

이걸 안 쓰면? 불필요한 렌더링 지옥 🔥을 경험할 수도 있어요! 😱

 

🎮 useReducer, 복잡한 상태 관리를 쉽게!

useReduceruseState보다 강력한 상태 관리 Hook이에요. 상태 변화가 많을 때 쓰면 좋아요.

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    default:
      return state;
  }
};

const [state, dispatch] = useReducer(reducer, { count: 0 });

👉 이렇게 dispatch({ type: "INCREMENT" })로 상태를 변경할 수 있어요.

Redux를 써야 하나 고민될 때, 간단한 건 useReducer로 해결할 수 있어요!

 

🏁 Hook을 왜 써야 할까요?

React Hook은 처음엔 헷갈리지만, 익숙해지면 더 강력한 기능과 성능 개선을 제공합니다.

 

요약하면:

  • useState: 기본 상태 관리
  • useEffect: 부수 효과 처리
  • useMemo & useCallback: 성능 최적화
  • useContext: 전역 상태 관리
  • useReducer: 복잡한 상태 관리

🚀 도전 과제:

기존에 클래스형 컴포넌트로 만든 프로젝트가 있다면, 함수형 컴포넌트 + Hook으로 변환해보세요!

처음엔 어렵겠지만, 몇 번 써보면 "이걸 왜 안 썼지?" 할 거예요. 😉