한국어

커스텀 훅으로 React 애플리케이션의 재사용 가능한 로직의 힘을 발휘해 보세요. 더 깔끔하고 유지보수하기 쉬운 코드를 위해 커스텀 훅을 만들고 활용하는 방법을 알아보세요.

커스텀 훅: React의 재사용 가능한 로직 패턴

React 훅은 함수형 컴포넌트에 상태 및 생명주기 기능을 도입하여 우리가 React 컴포넌트를 작성하는 방식에 혁명을 일으켰습니다. 훅이 제공하는 많은 이점 중에서, 커스텀 훅은 여러 컴포넌트에 걸쳐 로직을 추출하고 재사용하는 강력한 메커니즘으로 두드러집니다. 이 블로그 게시물에서는 커스텀 훅의 세계를 깊이 파고들어 그 이점, 생성 및 실제 예제를 통한 사용법을 탐구할 것입니다.

커스텀 훅이란 무엇인가?

본질적으로 커스텀 훅은 'use'라는 단어로 시작하고 다른 훅을 호출할 수 있는 JavaScript 함수입니다. 이를 통해 컴포넌트 로직을 재사용 가능한 함수로 추출할 수 있습니다. 이는 렌더 프롭(render props), 고차 컴포넌트(higher-order components) 또는 다른 복잡한 패턴에 의존하지 않고 컴포넌트 간에 상태 저장 로직, 부수 효과 또는 기타 복잡한 동작을 공유하는 강력한 방법입니다.

커스텀 훅의 주요 특징:

커스텀 훅 사용의 이점

커스텀 훅은 React 개발에서 여러 가지 중요한 이점을 제공합니다:

나만의 첫 커스텀 훅 만들기

창 크기를 추적하는 훅이라는 실제 예제를 통해 커스텀 훅의 생성을 설명해 보겠습니다.

예제: useWindowSize

이 훅은 브라우저 창의 현재 너비와 높이를 반환합니다. 또한 창 크기가 조절될 때 이 값들을 업데이트합니다.

import { useState, useEffect } from 'react';

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    window.addEventListener('resize', handleResize);

    // 정리 시 이벤트 리스너 제거
    return () => window.removeEventListener('resize', handleResize);
  }, []); // 빈 배열은 마운트 시에만 이펙트가 실행되도록 보장합니다

  return windowSize;
}

export default useWindowSize;

설명:

  1. 필요한 훅 가져오기: React에서 useStateuseEffect를 가져옵니다.
  2. 훅 정의하기: 이름 규칙에 따라 useWindowSize라는 함수를 만듭니다.
  3. 상태 초기화하기: useState를 사용하여 windowSize 상태를 창의 초기 너비와 높이로 초기화합니다.
  4. 이벤트 리스너 설정하기: useEffect를 사용하여 창에 resize 이벤트 리스너를 추가합니다. 창 크기가 조절되면 handleResize 함수가 windowSize 상태를 업데이트합니다.
  5. 정리(Cleanup): 컴포넌트가 마운트 해제될 때 이벤트 리스너를 제거하기 위해 useEffect에서 정리 함수를 반환합니다. 이는 메모리 누수를 방지합니다.
  6. 값 반환하기: 훅은 창의 현재 너비와 높이를 포함하는 windowSize 객체를 반환합니다.

컴포넌트에서 커스텀 훅 사용하기

이제 커스텀 훅을 만들었으니 React 컴포넌트에서 어떻게 사용하는지 알아봅시다.

import React from 'react';
import useWindowSize from './useWindowSize';

function MyComponent() {
  const { width, height } = useWindowSize();

  return (
    

창 너비: {width}px

창 높이: {height}px

); } export default MyComponent;

설명:

  1. 훅 가져오기: useWindowSize 커스텀 훅을 가져옵니다.
  2. 훅 호출하기: 컴포넌트 내에서 useWindowSize 훅을 호출합니다.
  3. 값에 접근하기: 반환된 객체를 구조 분해하여 widthheight 값을 얻습니다.
  4. 값 렌더링하기: 컴포넌트의 UI에 너비와 높이 값을 렌더링합니다.

useWindowSize를 사용하는 모든 컴포넌트는 창 크기가 변경될 때 자동으로 업데이트됩니다.

더 복잡한 예제

커스텀 훅의 더 고급 사용 사례를 살펴보겠습니다.

예제: useLocalStorage

이 훅을 사용하면 로컬 스토리지에서 데이터를 쉽게 저장하고 검색할 수 있습니다.

import { useState, useEffect } from 'react';

function useLocalStorage(key, initialValue) {
  // 값을 저장할 상태
  // 로직이 한 번만 실행되도록 초기 값을 useState에 전달
  const [storedValue, setStoredValue] = useState(() => {
    try {
      // 키로 로컬 스토리지에서 가져오기
      const item = window.localStorage.getItem(key);
      // 저장된 json을 파싱하거나, 없으면 초기 값을 반환
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // 오류 발생 시에도 초기 값을 반환
      console.log(error);
      return initialValue;
    }
  });

  // useState의 setter 함수를 래핑하여...
  // ...새 값을 localStorage에 유지하는 버전을 반환합니다.
  const setValue = (value) => {
    try {
      // 값이 함수일 수 있도록 하여 useState와 동일한 API를 가짐
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      // 로컬 스토리지에 저장
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
      // 상태 저장
      setStoredValue(valueToStore);
    } catch (error) {
      // 더 고급 구현에서는 오류 사례를 처리할 것입니다
      console.log(error);
    }
  };

  useEffect(() => {
    try {
      const item = window.localStorage.getItem(key);
      setStoredValue(item ? JSON.parse(item) : initialValue);
    } catch (error) {
      console.log(error);
    }
  }, [key, initialValue]);

  return [storedValue, setValue];
}

export default useLocalStorage;

사용법:

import React from 'react';
import useLocalStorage from './useLocalStorage';

function MyComponent() {
  const [name, setName] = useLocalStorage('name', 'Guest');

  return (
    

안녕하세요, {name}님!

setName(e.target.value)} />
); } export default MyComponent;

예제: useFetch

이 훅은 API에서 데이터를 가져오는 로직을 캡슐화합니다.

import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP 오류! 상태: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (error) {
        setError(error);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

사용법:

import React from 'react';
import useFetch from './useFetch';

function MyComponent() {
  const { data, loading, error } = useFetch('https://jsonplaceholder.typicode.com/todos/1');

  if (loading) return 

로딩 중...

; if (error) return

오류: {error.message}

; return (

제목: {data.title}

완료 여부: {data.completed ? '예' : '아니오'}

); } export default MyComponent;

커스텀 훅을 위한 모범 사례

커스텀 훅이 효과적이고 유지보수 가능하도록 하려면 다음 모범 사례를 따르십시오:

피해야 할 일반적인 함정

고급 패턴

커스텀 훅 조합하기

커스텀 훅을 함께 조합하여 더 복잡한 로직을 만들 수 있습니다. 예를 들어, useLocalStorage 훅과 useFetch 훅을 결합하여 가져온 데이터를 로컬 스토리지에 자동으로 유지할 수 있습니다.

훅 간의 로직 공유

여러 커스텀 훅이 공통 로직을 공유하는 경우, 해당 로직을 별도의 유틸리티 함수로 추출하여 두 훅 모두에서 재사용할 수 있습니다.

커스텀 훅과 Context 함께 사용하기

커스텀 훅은 React Context와 함께 사용하여 전역 상태에 접근하고 업데이트할 수 있습니다. 이를 통해 애플리케이션의 전역 상태를 인식하고 상호 작용할 수 있는 재사용 가능한 컴포넌트를 만들 수 있습니다.

실제 사례

다음은 실제 애플리케이션에서 커스텀 훅을 사용할 수 있는 몇 가지 예입니다:

예제 : 지도 또는 배달 서비스와 같은 다문화 애플리케이션을 위한 useGeolocation 훅

import { useState, useEffect } from 'react';

function useGeolocation() {
  const [location, setLocation] = useState({
    latitude: null,
    longitude: null,
    error: null,
  });

  useEffect(() => {
    if (!navigator.geolocation) {
      setLocation({
        latitude: null,
        longitude: null,
        error: '이 브라우저에서는 Geolocation이 지원되지 않습니다.',
      });
      return;
    }

    const watchId = navigator.geolocation.watchPosition(
      (position) => {
        setLocation({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
          error: null,
        });
      },
      (error) => {
        setLocation({
          latitude: null,
          longitude: null,
          error: error.message,
        });
      }
    );

    return () => navigator.geolocation.clearWatch(watchId);
  }, []);

  return location;
}

export default useGeolocation;

결론

커스텀 훅은 더 깔끔하고, 재사용 가능하며, 유지보수하기 쉬운 React 코드를 작성하기 위한 강력한 도구입니다. 복잡한 로직을 커스텀 훅에 캡슐화함으로써 컴포넌트를 단순화하고, 코드 중복을 줄이며, 애플리케이션의 전체 구조를 개선할 수 있습니다. 커스텀 훅을 받아들이고 그 잠재력을 발휘하여 더 견고하고 확장 가능한 React 애플리케이션을 구축하십시오.

기존 코드베이스에서 여러 컴포넌트에 걸쳐 로직이 반복되는 영역을 식별하는 것부터 시작하십시오. 그런 다음 해당 로직을 커스텀 훅으로 리팩터링하십시오. 시간이 지남에 따라 개발 프로세스를 가속화하고 코드 품질을 향상시킬 재사용 가능한 훅 라이브러리를 구축하게 될 것입니다.

모범 사례를 따르고, 일반적인 함정을 피하며, 고급 패턴을 탐색하여 커스텀 훅을 최대한 활용하는 것을 기억하십시오. 연습과 경험을 통해 당신은 커스텀 훅의 달인이자 더 효과적인 React 개발자가 될 것입니다.