본문 바로가기
React

[React] Hooks

by goblin- 2024. 9. 13.

훅(Hooks)의 개념과 필요성

 

1. 훅(Hooks)의 개념

 

**훅(Hooks)**은 리액트 16.8 버전에서 도입된 기능으로, 함수형 컴포넌트에서도 상태 관리라이프사이클 메서드와 같은 기능을 사용할 수 있도록 해주는 도구입니다. 이전에는 클래스형 컴포넌트에서만 상태 관리와 라이프사이클 메서드를 사용할 수 있었지만, 훅을 통해 이러한 기능을 함수형 컴포넌트에서도 사용할 수 있게 되었습니다.

 

훅의 주요 목표는 리액트 컴포넌트의 상태 관리와 라이프사이클 메서드를 간결하게 처리하는 것이며, 보다 직관적이고 선언적인 방식으로 리액트 애플리케이션을 개발할 수 있게 합니다.

 

2. 훅이 도입된 이유 (필요성)

 

훅이 필요한 이유는 리액트 애플리케이션에서 코드 재사용성과 상태 관리의 복잡성을 해결하기 위해서입니다. 리액트는 컴포넌트를 작은 단위로 나누어 재사용할 수 있지만, 상태와 관련된 로직을 재사용하는 것은 쉽지 않았습니다. 클래스형 컴포넌트의 한계와 복잡한 상태 관리 로직으로 인해 함수형 컴포넌트에서 더 간편하게 상태를 관리하고, 코드 재사용성을 높이기 위해 훅이 도입되었습니다.

 

훅은 다음과 같은 문제를 해결합니다:

 

1. 클래스형 컴포넌트의 복잡성: 클래스형 컴포넌트에서는 상태 관리를 위해 this 바인딩, 라이프사이클 메서드의 분리 등 복잡한 구조가 필요합니다. 훅은 이러한 복잡성을 제거하고, 함수형 컴포넌트 내에서 간단하게 상태를 관리할 수 있도록 합니다.

2. 중복된 로직: 클래스형 컴포넌트에서는 상태 관련 로직을 공유하기 어렵고, 코드 중복이 발생하는 경우가 많습니다. 훅을 사용하면 여러 컴포넌트 간에 로직을 재사용할 수 있습니다.

3. 함수형 컴포넌트의 한계: 함수형 컴포넌트는 리액트 16.8 이전에는 상태 관리라이프사이클 관리 기능이 없었고, 오직 UI 렌더링만 가능했습니다. 훅을 사용하면 함수형 컴포넌트에서도 상태라이프사이클을 관리할 수 있게 됩니다.

 

3. 기본 훅의 종류

 

리액트는 여러 종류의 기본 훅을 제공하며, 이들은 각각 다른 목적을 가집니다.

 

1. useState:

컴포넌트에서 상태를 관리하기 위한 훅입니다.

상태를 선언하고, 그 상태를 업데이트하는 함수가 반환됩니다.

const [state, setState] = useState(initialValue);

예시:

import React, { useState } from 'react';

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

 

2. useEffect:

컴포넌트의 **사이드 이펙트(side effects)**를 처리하기 위한 훅입니다.

주로 데이터 가져오기(API 호출), 구독(subscription), DOM 조작 등의 작업에 사용됩니다.

useEffect(() => {
  // 코드 실행
}, [의존성 배열]); // 의존성 배열이 비어 있으면 컴포넌트가 마운트될 때 한 번 실행

 

예시:

import React, { useState, useEffect } from 'react';

function DataFetchingComponent() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then((response) => response.json())
      .then((result) => setData(result));
  }, []);

  return <div>Data: {JSON.stringify(data)}</div>;
}

 

3. useContext:

리액트의 Context API를 사용하여 전역 상태공유된 값을 쉽게 전달할 수 있는 훅입니다.

부모 컴포넌트에서 자식 컴포넌트로 일일이 props로 값을 전달하지 않고, 컨텍스트를 통해 전역적으로 데이터를 전달할 수 있습니다.

const value = useContext(MyContext);

 

4. useReducer:

useState보다 복잡한 상태 관리가 필요한 경우에 사용됩니다.

리듀서 패턴을 사용하여 상태를 업데이트합니다. 주로 상태 전이 로직이 복잡할 때 유용합니다.

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

예시:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

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();
  }
}

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

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}

 

 

훅을 사용할 때는 몇 가지 규칙이 있습니다. 이 규칙을 지키지 않으면 리액트 컴포넌트가 예상치 못한 방식으로 동작할 수 있습니다.

 

1. 훅은 컴포넌트의 최상위 레벨에서만 호출해야 합니다:

훅은 조건문이나 반복문 안에서 호출해서는 안 됩니다. 항상 컴포넌트의 최상위에서 호출되어야 합니다. 그래야 리액트가 훅 호출 순서를 올바르게 추적할 수 있습니다.

2. 훅은 리액트 함수형 컴포넌트 또는 커스텀 훅에서만 호출해야 합니다:

훅은 일반 함수나 클래스형 컴포넌트에서 호출할 수 없습니다. 훅은 리액트 함수형 컴포넌트커스텀 훅 내에서만 사용할 수 있습니다.

 

5. 커스텀 훅(Custom Hook)

 

커스텀 훅은 리액트의 기본 훅들을 조합하여 재사용 가능한 상태 관련 로직을 만들 수 있는 방법입니다. 훅은 함수이기 때문에, 함수처럼 로직을 캡슐화하고 재사용할 수 있습니다.

 

예시: 커스텀 훅 만들기

import React, { useState, useEffect } from 'react';

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return width;
}

function WindowWidthComponent() {
  const width = useWindowWidth();

  return <p>Window width: {width}px</p>;
}

설명:

 

**useWindowWidth**는 창의 너비를 추적하는 커스텀 훅입니다.

이 훅은 리액트 컴포넌트에서 창 크기를 쉽게 추적할 수 있도록 도와줍니다.

useEffect를 통해 창 크기가 변경될 때마다 상태를 업데이트하고, 컴포넌트가 언마운트될 때 이벤트 리스너를 제거합니다.

 

 

6. 훅의 필요성 정리

 

훅은 다음과 같은 이유로 리액트 개발에서 필수적인 기능입니다:

 

1. 함수형 컴포넌트의 상태 관리:

훅은 함수형 컴포넌트에서도 상태 관리를 가능하게 합니다. 이를 통해 리액트 개발자들은 간결한 코드를 작성할 수 있으며, 상태나 라이프사이클 메서드 때문에 굳이 클래스형 컴포넌트를 사용할 필요가 없게 됩니다.

2. 코드 재사용성 향상:

훅을 사용하면 커스텀 훅을 통해 로직을 재사용할 수 있습니다. 상태 관리나 비즈니스 로직을 다양한 컴포넌트에 걸쳐 재사용할 수 있기 때문에, 코드를 모듈화하고 중복을 줄일 수 있습니다.

3. 클래스형 컴포넌트의 복잡성 해결:

클래스형 컴포넌트에서 this 바인딩, 상태 관리 로직의 분리 문제, 라이프사이클 메서드의 중복 등으로 인해 복잡성이 증가할 수 있었습니다. 훅은 이러한 문제를 해결하고, 더 단순하고 직관적인 코드 작성을 가능하게 합니다.

4. 리액트 컴포넌트의 선언적 접근:

훅을 사용하면 리액트 컴포넌트에서 발생하는 모든 로직을 하나의 선언적 흐름으로 작성할 수 있습니다. 상태 업데이트, 사이드 이펙트 처리 등을 컴포넌트의 로직 안에서 명확하게 처리할 수 있습니다.

5. 컴포넌트 기반의 로직 캡슐화:

훅은 특정 컴포넌트에서만 사용되는 로직을 간단히 캡슐화하고, 필요한 부분에서만 호출할 수 있게 합니다. 이를 통해 상태나 사이드 이펙트를 더 직관적이고, 컴포넌트에 맞게 관리할 수 있습니다.

 

7. 결론

 

훅(Hooks)은 리액트에서 함수형 컴포넌트의 한계를 극복하고, 상태 관리와 라이프사이클 처리를 가능하게 하기 위해 도입된 기능입니다. 훅은 리액트 애플리케이션을 개발할 때 코드를 간결하고 모듈화할 수 있게 도와주며, 로직의 재사용성컴포넌트 구조의 일관성을 크게 향상시킵니다.

 

리액트의 주요 훅인 useState, useEffect, useContext 등의 훅을 사용해 상태 관리, 라이프사이클 관리, 전역 상태 공유 등을 함수형 컴포넌트에서 손쉽게 할 수 있습니다. 또한, 커스텀 훅을 통해 특정 로직을 재사용할 수 있어 컴포넌트 기반 개발을 더욱 효율적으로 수행할 수 있습니다.

 

결론적으로, 훅은 리액트에서 복잡한 클래스형 컴포넌트를 대체하면서도 상태와 라이프사이클을 관리할 수 있게 해주는 필수 도구로, 리액트 개발에서 매우 중요한 개념입니다.