[React] React Hooks

SungWoo·2024년 12월 21일
1

React

목록 보기
12/16
post-thumbnail

React Hook은 컴포넌트에서 상태 관리, 사이드 이펙트(부수 효과) 처리, 참조 관리 등 다양한 기능을 간단하고 효율적으로 구현할 수 있게 해주는 도구다.

Hook이 등장하기 전에는 클래스 컴포넌트를 사용해야만 상태와 라이프사이클 관련 기능을 구현할 수 있었다. 하지만 Hook의 도입으로 함수형 컴포넌트에서도 이러한 기능을 사용할 수 있게 되었고, React 개발 패러다임이 크게 변화했다.

Hook을 사용하면 코드를 더 간결하게 작성할 수 있고, 유지보수도 한결 쉬워진다. 또한, 코드 재사용성을 극대화할 수 있어 효율적인 개발이 가능하다.

이번 포스팅을 통해 React의 주요 Built-in Hook들에 대해 가볍게 정리해보자.


State Hook(상태 관리)

State Hook은 컴포넌트가 사용자 입력, UI 상태 등의 정보를 기억할 수 있도록 돕는다.

  • useState : 상태 변수를 선언하고 직접 업데이트 할 수 있다.
// 버튼 클릭 시 카운트가 1씩 증가하는 예제
import { useState } from 'react';

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

  return (
    <button onClick={() => setCount(count + 1)}>
      Count: {count}
    </button>
  );
}
  • useReducer : 상태와 업데이트 로직을 별도의 리듀서 함수로 관리할 수 있다.

Context Hook (컨텍스트 관리)

Context Hook은 컴포넌트 트리 깊은 곳에 있는 자식 컴포넌트에 데이터를 전달할 때 props drilling을 피할 수 있게 도와준다.

Props drilling: React에서 상위 컴포넌트의 데이터를 하위 컴포넌트에 전달하기 위해 중간 컴포넌트를 거쳐 props를 계속 전달하는 과정

  • useContext : Context 값을 읽고 변경 사항을 구독한다.
// ThemeContext에서 값을 가져와 버튼의 배경 색상을 설정하는 예제
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function Button() {
  const theme = useContext(ThemeContext);

  return <button style={{ background: theme.background }}>Click me</button>;
}

Ref Hook (참조 관리)

Ref Hook은 렌더링에 영향을 주지 않는 정보를 저장하거나 DOM 요소를 직접 조작하는 데 사용된다.

  • useRef : 값이나 DOM 노드를 저장할 수 있는 참조를 생성한다.
// 버튼 클릭 시 입력 필드에 포커스를 주는 예제
import { useRef } from 'react';

function TextInput() {
  const inputRef = useRef();

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </>
  );
}
  • useInperativeHandle : 컴포넌트가 노출하는 ref를 사용자 정의한다.

Effect Hook (사이드 이펙트 처리)

Effect Hook은 컴포넌트가 외부 시스템과 연결하거나 동기화할 때 사용된다.

  • useEffect : 데이터 fetch, DOM 업데이트 등 외부 시스템과의 연결을 처리한다.
// roomId가 변경될 때마다 새로운 연결을 생성하고 연결 종료 시 이전 연결을 끊는 예제
import { useEffect } from 'react';

function ChatRoom({ roomId }) {
  useEffect(() => {
    const connection = createConnection(roomId);
    connection.connect();

    return () => connection.disconnect();
  }, [roomId]);

  return <p>Welcome to the room!</p>;
}
  • useLayoutEffect : 브라우저가 화면을 다시 그리기 전에 실행된다.
  • useInsertionEffect : React가 DOM에 변경을 반영하기 전에 실행된다.

Performance Hook (성능 최적화)

재랜더링 성능을 최적화 하는 일반적인 방법은 불필요한 작업을 건너뛰는 것이다.

예를 들어, 캐시된 계산을 재사용하거나 이전 렌더링 이후 데이터가 변경되지 않은 경우 재렌더링을 건너뛰도록 React에 지시할 수 있다.

Performance Hook은 불필요한 계산을 건너뛰거나 렌더링 성능을 최적화할 때 사용된다.

  • useMemo : 계산된 값을 메모이제이션하여 불필요한 재계산을 방지하고 성능을 최적화하는 데 사용된다.
// 주어진 filter에 따라 todos를 필터링하고 렌더링하는 예제
import { useMemo } from 'react';

function TodoList({ todos, filter }) {
  const filteredTodos = useMemo(() => {
    return todos.filter(todo => todo.type === filter);
  }, [todos, filter]);

  return <ul>{filteredTodos.map(todo => <li key={todo.id}>{todo.text}</li>)}</ul>;
}
  • useCallback : 함수를 메모이제이션하여 불필요한 재생성을 막고 성능을 최적화 하는데 사용된다.
// 버튼 클릭 시 항목을 추가하는 함수의 불필요한 재생성을 막는 예제
import { useState, useCallback } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  // useCallback을 사용하여 addTodo 함수의 재생성을 방지
  const addTodo = useCallback(() => {
    setTodos(prevTodos => [...prevTodos, { text: input, id: Date.now() }]);
    setInput('');
  }, [input]);

  return (
    <div>
      <input value={input} onChange={e => setInput(e.target.value)} />
      <button onClick={addTodo}>Add Todo</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>{todo.text}</li>
        ))}
      </ul>
    </div>
  );
}

하지만 때로는 화면이 실제로 업데이트되어야 하기 때문에 렌더링을 건너뛸 수 없는 경우도 있다.

이 경우, 사용자가 입력란에 텍스트를 입력하는 것 처럼 동기적으로 처리해야 하는 차단 업데이트(Blocking Update)와 차트 업데이트와 같이 사용자 인터페이스를 차단할 필요가 없는 비차단 업데이트(Non-Blocking Update)를 분리하여 성능을 개선할 수 있다.

즉, 어떤 업데이트가 우선적으로 처리되고, 어떤 업데이트가 나중에 처리될지에 대한 렌더링 우선순위를 설정하려면, 다음 훅들을 사용하면 된다.

  • useTransition : 상태 전환을 비차단으로 표시하고 다른 업데이트가 이를 중단할 수 있도록 한다.
  • useDeferredValue : 중요하지 않은 UI 부분의 업데이트를 지연시켜 다른 부분이 먼저 업데이트 되도록 한다.

이 두 훅은 처음 접해보는데 굉장히 흥미롭다. 추후에 직접 Hook을 사용해보면서 성능 최적화에 대한 내용을 정리해보면 좋을 것 같다.


Other Hook

  • useId : 접근성 구현 시 고유 ID 생성
  • useSyncExternalStore : 외부 상태 관리 라이브러리와의 동기화
  • useDebugValue : React DevTools에서 사용자 정의 Hook에 대한 디버깅 정보 제공

마무리

React의 Built-in Hook은 다양한 기능을 간단하게 구현할 수 있게 해준다. 이 Hook들을 잘 활용하면 코드의 가독성과 유지보수성이 크게 향상된다. React 개발자로서 Hook은 필수적인 도구이므로, 이를 완전히 이해하고 활용할 수 있도록 꾸준히 연습해보자.


Reference

profile
어제보다 더 나은

0개의 댓글