React hook (useState, useEffect, useRef, useMemo....)

송연지·2024년 9월 13일
2

이 글에서는 각각의 React의 Hook이 무엇인지, 장단점, 사용 예시, 그리고 어떤 상황에서 사용하는 것이 적절한지 자세히 설명하겠습니다.

1. useState Hook

개념

useState는 함수형 컴포넌트에서 상태를 관리하는 기본적인 Hook입니다. 이 Hook을 사용하면 상태 값을 선언하고 그 값을 업데이트할 수 있는 함수를 얻을 수 있습니다.

사용법

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

useState는 두 개의 값을 반환하는데, 첫 번째는 상태 값(count), 두 번째는 그 상태를 변경할 수 있는 함수(setCount)입니다.

장점

  • 간단한 상태 관리: 간단하게 컴포넌트 내부에서 상태를 관리할 수 있습니다.
  • 함수형 컴포넌트 지원: 클래스 컴포넌트 없이도 상태를 관리할 수 있습니다.

단점

  • 관리 제한: 복잡한 상태 관리나 여러 상태를 연결하는 작업이 힘들 수 있습니다.
  • 비동기 업데이트: 상태 업데이트가 비동기로 처리되므로 업데이트 순서를 정확히 보장하기 어려울 수 있습니다.

사용 예시

  • 클릭 카운터
  • 입력 필드의 값 관리
  • UI 의 특정 상태(토글, 활성화 여부 등) 관리

언제 사용해야 하나?

  • 단순한 상태 관리가 필요한 경우
  • UI 컴포넌트 내에서 상태가 자주 변하는 상황

2. useEffect Hook

개념

useEffect는 사이드 이펙트(Side Effect)를 관리하는 Hook입니다. 사이드 이펙트는 컴포넌트가 렌더링된 후에 발생해야 하는 작업으로, 네트워크 요청, DOM 업데이트, 또는 외부 API 호출과 같은 작업이 포함됩니다.

사용법

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]);

위의 예시에서는 count 값이 변경될 때마다 document.title이 업데이트됩니다.

장점

  • 사이드 이펙트 관리: 컴포넌트가 렌더링된 이후의 작업을 손쉽게 처리할 수 있습니다.
  • 의존성 배열: 의존성 배열을 통해 언제 효과를 다시 실행할지 제어할 수 있습니다.

단점

  • 의존성 관리가 복잡할 수 있음: 의존성 배열을 적절히 관리하지 않으면 불필요한 리렌더링 또는 의도치 않은 동작을 초래할 수 있습니다.
  • 메모리 누수 가능성: 컴포넌트가 언마운트될 때 정리(clean-up)를 하지 않으면 메모리 누수가 발생할 수 있습니다.

사용 예시

  • 데이터 가져오기 (fetching data)
  • 구독 설정 (subscribing to an event)
  • 타이머 설정

언제 사용해야 하나?

컴포넌트가 마운트, 언마운트될 때 또는 특정 상태나 props가 변경될 때 발생하는 사이드 이펙트를 처리할 때
비동기 작업이나 이벤트 리스너 설정, 데이터 페칭 등

3. useRef Hook

개념

useRef는 DOM 요소 또는 어떤 값에 대해 변경을 감지하지 않으면서도 참조할 수 있는 값을 저장하는 데 사용됩니다. useRef로 만든 객체는 리렌더링 시에도 유지되며, 값이 바뀌어도 컴포넌트를 다시 렌더링하지 않습니다.

사용법


const inputRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
}, []);

위의 예시에서는 useRef를 통해 DOM 요소를 참조하여 focus 메서드를 실행하고 있습니다.

장점

  • 렌더링에 영향 없음: useRef는 값이 변경되더라도 컴포넌트가 다시 렌더링되지 않으므로 성능을 최적화할 수 있습니다.
  • 간편한 DOM 접근: 직접 DOM 요소에 접근하여 작업할 때 매우 유용합니다.

단점

  • 리액티브하지 않음: useRef는 값이 변경되어도 이를 자동으로 감지하거나 반응하지 않으므로 상태 관리에는 적합하지 않습니다.
  • 코드 가독성 저하: 과도하게 사용하면 코드가 복잡해지고, 가독성이 떨어질 수 있습니다.
    사용 예시
  • DOM 요소에 직접 접근이 필요한 경우 (ex. 포커스, 텍스트 선택, 애니메이션 제어 등)
  • 이전 값의 참조가 필요한 경우 (ex. 이전 상태 값)

언제 사용해야 하나?

  • 컴포넌트가 리렌더링될 필요 없이 특정 값을 참조해야 할 때
  • DOM에 직접 접근해야 할 때

4. useMemo Hook

개념

useMemo는 메모이제이션(Memoization)된 값을 반환하는 Hook입니다. 이 값은 컴포넌트가 리렌더링될 때 특정 의존성 배열(Dependency Array)이 변경되지 않는 한 다시 계산되지 않습니다. 이를 통해 불필요한 계산을 피하고 성능을 최적화할 수 있습니다.

사용법

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

위의 코드는 a와 b가 변경될 때만 computeExpensiveValue 함수를 호출하여 그 결과를 다시 계산합니다. 만약 a와 b가 변경되지 않았다면, 이전에 계산된 값을 그대로 사용합니다.

장점

  • 성능 최적화: 계산 비용이 많이 드는 연산을 최적화할 수 있습니다.
  • 불필요한 연산 방지: 의존성 배열의 값이 변경되지 않았다면 이전에 계산된 값을 재사용하므로 불필요한 계산을 방지합니다.

단점

  • 불필요한 사용: 메모이제이션 오버헤드가 있어 매번 새로운 값을 계산하는 것이 더 효율적인 경우도 있습니다.
  • 복잡성 증가: 너무 많은 메모이제이션은 코드의 가독성을 저하시킬 수 있습니다.

사용 예시

  • 복잡한 계산을 여러 번 수행하는 컴포넌트
  • 정렬된 배열을 기반으로 데이터를 렌더링하는 경우

언제 사용해야 하나?

  • 값이 변경될 가능성이 낮지만, 계산 비용이 매우 높은 경우
  • 동일한 계산을 여러 번 반복하는 경우

5. useReducer Hook

개념

useReducer는 상태 업데이트 로직이 복잡하거나 여러 상태가 상호작용하는 경우에 유용한 Hook입니다. 상태와 이를 업데이트하는 로직을 컴포넌트 외부에서 분리하여 재사용할 수 있습니다.

사용법


const [state, dispatch] = useReducer(reducer, initialState);

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

장점

  • 복잡한 상태 관리에 적합: 상태 업데이트 로직을 하나의 함수로 관리하므로 복잡한 상태나 상태 간 상호작용이 필요한 경우 적합합니다.
  • 코드 분리: 상태와 업데이트 로직을 분리하여 코드 가독성을 높일 수 있습니다.

단점

  • 복잡성 증가: 간단한 상태 관리에는 오히려 복잡성을 높일 수 있습니다.
  • 초기 설정: reducer 함수와 상태 구조를 정의하는 초기 설정이 다소 복잡할 수 있습니다.

사용 예시

  • 복잡한 폼 상태 관리
  • 여러 상태를 동시에 관리해야 하는 UI (ex. 쇼핑카트)

언제 사용해야 하나?

  • 상태가 복잡하고 여러 액션에 의해 관리되는 경우
  • 여러 상태 간의 상호작용이 중요한 경우

6. useContext Hook

개념

useContext는 부모 컴포넌트에서 자식 컴포넌트로 Props를 전달하는 대신, 전역적으로 상태를 관리하고 전달할 수 있는 Hook입니다. 이를 통해 컴포넌트 트리 전반에 걸쳐 데이터를 공유할 수 있습니다.

사용법

const value = useContext(MyContext);

장점

  • 전역 상태 관리: 여러 컴포넌트에서 동일한 데이터를 손쉽게 공유할 수 있습니다.
  • Props Drilling 방지: 여러 컴포넌트를 거쳐 Props를 전달하는 문제를 해결할 수 있습니다.

단점

  • 리렌더링 최적화 어려움: Context가 업데이트되면 하위 컴포넌트들이 불필요하게 리렌더링될 수 있습니다.
  • 구조적 복잡성: 잘못 사용할 경우, Context 구조가 복잡해질 수 있습니다.

사용 예시

  • 테마 설정(라이트/다크 모드)
  • 사용자 인증 상태 관리

언제 사용해야 하나?

  • 전역 상태를 여러 컴포넌트에서 공유해야 할 때
  • 복잡한 Props Drilling을 피하고 싶을 때

7. useLayoutEffect Hook

개념

useLayoutEffect는 useEffect와 유사하지만, 차이점은 렌더링 이후 화면이 그려지기 전에 실행된다는 점입니다. 이 Hook은 DOM이 업데이트된 직후에 실행되므로 화면에 표시되는 것에 즉각적으로 영향을 미치는 작업을 수행할 때 유용합니다.

사용법

코드 복사
useLayoutEffect(() => {
  // DOM 조작 및 레이아웃 관련 작업
}, []);

장점

  • 화면 그리기 전에 작업 실행: DOM 변경이 화면에 반영되기 전에 실행되므로 UI의 일관성을 보장할 수 있습니다.
  • 성능 최적화: DOM이 변경되기 전에 필요한 조작을 함으로써 렌더링 성능을 개선할 수 있습니다.

단점

  • 렌더링 지연: 복잡한 작업이 들어가면 렌더링 속도를 저하시킬 수 있습니다.
  • 자주 사용하면 성능에 악영향: 필요하지 않은 경우에는 useEffect를 사용하는 것이 더 적절할 수 있습니다.

사용 예시

  • DOM 조작과 레이아웃 관련 작업
  • 요소 크기나 위치를 기반으로 계산해야 하는 작업

언제 사용해야 하나?

  • 렌더링 직후 DOM 조작이 필요한 경우
  • 화면에 표시되는 동안 사용자에게 깜빡임을 방지하기 위한 작업이 필요한 경우

7. useCallback Hook

개념

useCallback은 함수의 메모이제이션을 제공하는 Hook입니다. 이 Hook은 특정 의존성이 변경되지 않는 한 동일한 함수 객체를 반환하여, 불필요한 함수 재생성을 방지합니다.

사용법

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

장점

  • 성능 최적화: 불필요한 함수 재생성을 방지하여 자식 컴포넌트에 전달되는 함수를 안정적으로 유지할 수 있습니다.
  • 의존성 제어: 함수의 의존성을 명시적으로 제어하여 업데이트 시점을 명확하게 할 수 있습니다.

단점

  • 과도한 사용: 메모이제이션 자체의 오버헤드가 있을 수 있으므로, 단순한 함수에는 오히려 성능 저하가 발생할 수 있습니다.
  • 코드 복잡성 증가: 지나친 사용은 코드 가독성을 떨어뜨릴 수 있습니다.

사용 예시

  • 자식 컴포넌트에 props로 함수를 전달할 때
  • 이벤트 핸들러 함수가 자주 변경될 필요가 없을 때

언제 사용해야 하나?

  • 함수 객체가 자주 생성되어 불필요한 리렌더링을 방지하고 싶을 때
  • 동일한 함수 객체를 메모이제이션하여 성능을 최적화하고자 할 때

마무리 및 정리

React의 Hook은 모두 서로 다른 목적으로 컴포넌트 성능과 동작을 최적화하는 데 중요한 역할을 합니다. 각각의 Hook은 적절한 상황에서 사용할 때 매우 유용하며, 사용 목적과 상황에 맞게 선택하는 것이 중요합니다.

Hook목적장점단점사용 예시
useState간단한 상태 관리간단한 상태 관리 가능상태 관리가 복잡해지면 적합하지 않음클릭 카운터, 입력 필드 관리
useEffect사이드 이펙트 처리 (렌더 후 동작)컴포넌트의 라이프사이클 동안 다양한 작업 처리 가능의존성 관리가 복잡할 수 있으며, 메모리 누수 가능성 있음데이터 페칭, 이벤트 리스너, 타이머 설정 등
useRef참조 값 관리 (렌더링에 영향 없음)렌더링에 영향을 주지 않고 값 참조 가능값 변경에 리액티브하지 않음DOM 요소 접근, 이전 값 저장 등
useMemo계산된 값 메모이제이션불필요한 계산을 방지하고 성능 최적화지나친 사용은 오히려 복잡성을 증가시킬 수 있음복잡한 계산, 정렬된 리스트 등
useReducer복잡한 상태와 액션 관리복잡한 상태 관리에 적합, 상태 로직 분리 가능초기 설정이 복잡할 수 있음복잡한 폼, 쇼핑 카트 관리
useContext전역 상태 관리전역 상태를 쉽게 공유 가능리렌더링 최적화 어려움테마 설정, 사용자 인증 상태
useLayoutEffectDOM이 그려지기 전 작업 수행화면 그리기 전에 작업을 실행할 수 있음렌더링 지연 가능레이아웃 관련 작업, DOM 조작
useCallback함수의 메모이제이션불필요한 함수 재생성을 방지하여 성능 최적화과도한 사용은 성능 저하로 이어질 수 있음이벤트 핸들러, 자식 컴포넌트에 props로 전달하는 함수
profile
프론트엔드 개발쟈!!

0개의 댓글