본문 바로가기
📌 Front End/└ React

[React] 리액트 훅 - 커스텀 훅(Custom Hook)

by 쫄리_ 2024. 9. 2.
728x90
반응형

📌 사용자 정의 훅(커스텀 훅)

React에서 커스텀 훅(Custom Hook)은 상태 로직(stateful logic)을 재 사용할 수 있도록 하는 기능이다.

이는 여러 컴포넌트에서 공통적으로 사용되는 상태 로직을 추출하여 

하나의 함수로 만들어 사용할 수 있도록 한다.

커스텀 훅은 보통 use라는 접두사를 사용하여 함수의 이름을 정의하며, 

React의 기본 내장 훅(useState, useEffect 등)을 이용하여 구현된다. 

JSX 코드나 렌더링과 관련된 코드를 포함해서는 안 되며컴포넌트 내부나 외부에서 호출하여 사용한다.

커스텀 훅을 사용하면 코드의 중복을 줄이고, 컴포넌트의 재사용성과 유지보수성을 높일 수 있다.
예를 들어, API 호출, 폼 데이터 관리, 타이머/애니메이션 등의 다양한 기능을 

커스텀 훅으로 만들어 사용할 수 있다.


🔎 리액트 훅 종류

2019년 2월 16.8.0 버전에서 리액트 훅이라는 혁신적인 기능이 등장했다. 

'use'라는 접두사가 이름에 들어가는 일련의 함수이며, 반드시 함수 컴포넌트에서만 사용해야 한다.

용도 설명
컴포넌트 데이터 관리 useState 상태 관리를 위한 훅
useReducer 복잡한 상태 로직을 관리할 때 유용한 훅
useMemo 계산된 값을 메모이제이션하여 성능을 최적화
useCallback 메모이제이션된 콜백 함수를 반환하여 성능을 최적화
컴포넌트 생명 주기 대응 useEffect 컴포넌트가 렌더링된 후
사이드 이펙트를 처리할 때 사용
useLayoutEffect useEffect와 유사하지만
DOM 변경 후 동기적으로 호출
컴포넌트 메서드 호출 useRef DOM 노드나
컴포넌트 인스턴스를 참조할 때 사용
useImperativeHandle 자식 컴포넌트의 인스턴스 값과
메서드를 부모 컴포넌트에 노출할 때 사용합니다.
컴포넌트 간의 정보 공유 useContext Context API를 사용하여
컴포넌트 트리 전체에 데이터를 전달

 


🗂️ 리액트 폴더구조

리액트 프로젝트에서는 파일과 폴더를 다음과 같은 구조로 나누어 관리합니다.

src/
├── 📁components/	# UI 컴포넌트를 저장하는 폴더
│   ├── Header/
│   ├── Footer/
│   └── ...
│ 
├── 📁hooks/		# 커스텀 훅을 저장하는 폴더
│   ├── useFetch.tsx
│   └── useTimeout.tsx
│ 
├── 📁utils/		# 유틸리티 함수를 저장하는 폴더
│   ├── dateUtils.js
│   └── mathUtils.js
│ 
├── 📁pages/		# 페이지 컴포넌트를 저장하는 폴더
│   ├── HomePage/
│   └── AboutPage/
│ 
├── 📁styles/		# 스타일 파일(CSS, SCSS 등)을 저장하는 폴더
│   └── ...
├── 📁assets/		# 이미지, 폰트, 아이콘 등의 정적 자산을 저장하는 폴더
│   └── ...
│ 
├── 📁context/		# 리액트 컨텍스트를 저장하는 폴더
│   └── AuthContext.js
│ 
└── 📜App.tsx		# 메인 앱 컴포넌트

🔎 커스텀훅, 유틸함수 차이

  커스텀 훅 유틸 함수
의존성 리액트의 훅을 사용하여 
상태 관리나 사이드 이펙트 처리
리액트와 무관하게 독립적으로 동작
사용 범위 리액트 컴포넌트 내부에서 사용되며, 
컴포넌트의 상태나 라이프사이클과 
밀접관 관련이 있음
어디에서나 호출될 수 있으며, 
컴포넌트와 상관없이 다양한 로직을 처리할 수 있음
구현 방식 use로 시작하는 함수로 구현되며 
내부에서 다른 훅을 호출할 수 있음
단순한 자바스크립트 함수로 구현

 


📌 커스텀 훅 특징

기본 Hook(예: useState, useEffect, useContext 등)

상태 관리, 사이드 이펙트 처리, Context API 사용 등 

다양한 React 기능을 함수 컴포넌트 내에서 사용할 수 있도록 해줍니다.

  • 재사용성
    Custom Hook을 통해 컴포넌트 간에 공통적으로 사용되는 
    상태 관리 로직이나 사이드 이펙트 로직을 재사용할 수 있습니다.

  • 캡슐화
    관련된 로직을 하나의 Hook으로 묶어 관리할 수 있으며, 
    이를 통해 코드의 가독성과 유지보수성이 향상됩니다.

  • 모듈성
    각 Custom Hook은 독립적인 모듈로서 기능을 수행하므로, 
    필요에 따라 프로젝트의 다른 부분에서도 쉽게 재사용할 수 있습니다.

  • 구성 가능성
    기본 Hook들을 조합하고 필요에 따라 매개변수를 전달하여 
    다양한 방식으로 Custom Hook을 구성할 수 있습니다.

📌 커스텀 훅 규칙

이름 규칙

커스텀 훅의 함수 이름 앞에 "use"로 시작해야 한다.
ex. useCounter, useFetchData

 

 📁hooks 폴더 생성

대개의 경우 프로젝트 내의

hooks 디렉토리(폴더)Custom Hook을 위치시킵니다.

 

내장 훅(Hook) 사용

커스텀 훅 내에서 내장 훅(예: useState, useEffect) 사용
이렇게 하면 커스텀 훅의 로직을 더욱 강력하게 만들 수 있다.

 

상태와 함수 반환

커스텀 훅은 상태 값해당 상태를 업데이트하는 함수반환

return 하는 값은 조건부여서는 안 됩니다.

예를 들어, 카운터를 관리하는 커스텀 훅은 현재 카운트 값과 카운트를 증가시키는 함수를 반환할 수 있다.

 

로직 모듈화

커스텀 훅은 비즈니스 로직을 모듈화 하고 여러 컴포넌트에서 재 사용할 수 있는 

추상화된 API를 제공하는 데 사용된다.

예를 들어, 로그인 상태 관리, 데이터 가져오기, 테마 설정, 폼 상태 관리 등과 같은 

일반적인 로직을 커스텀 훅으로 추상화하여 코드를 더 간결하고 유지보수하기 쉽게 만들 수 있다.


📌 커스텀 훅 대표 예시

  1. useInput : 입력 필드의 값을 관리하고 유효성 검사를 수행하는 훅
  2. useTabs : 여러 탭 간의 전환을 관리하는 훅
  3. useFetch : 네트워크 요청을 보내고 응답 데이터를 관리하는 훅
  4. useToggle : boolean 상태를 토글하는 로직을 간단하게 관리하는 훅
  5. useForm : 폼 입력 및 제출 관리를 위한 훅, 유효성 검사와 폼 제출 처리를 포함
  6. useLocalStorage : Local Storage에 데이터를 저장하고 관리하는 훅
  7. useEventListener : 이벤트 리스너를 추가하고 제거하는 로직을 캡슐화한 훅
  8. useInterval/useTimeout : setIntervalsetTimeout을 React 생명주기에 맞게 관리하는 훅

📌 커스텀 훅 만들기 가이드

  • 폴더와 파일 생성 : "📁hooks 폴더"를 만들고, "📜index.tsx 파일" 을 통해 커스텀 훅을 한 곳에서 관리
  • 커스텀 훅 정의 : useToggle사용자 정의 훅을 정의하여 값 토글 기능을 제공
  • 커스텀 훅 사용 : "📜App 컴포넌트" useToggle사용자 정의 훅을 사용하여 값에 따라 UI를 변경
  • 구조 분해 할당 : 커스텀 훅이 반환하는 값들을 편리하게 사용

✅ 커스텀 훅 모아두기  ➡️ 📁"hooks" 새 폴더 생성

프로젝트 폴더 안에 📁"hooks" 라는 폴더를 만들어서 커스텀 훅들을 관리합니다.

이 폴더는 커스텀 훅 파일들을 모아두기 위한 용도로 사용됩니다.


✅ 커스텀 훅 한곳에서 내보내기  ➡️ 📜"index.tsx" 파일 생성

📁hooks 폴더 안📜"index.tsx" 파일을 생성합니다.

이 파일에서 모든 커스텀 훅을 모아 한꺼번에 내보내기(export) 합니다.

 

toggle, clamp, details라는 이름의 커스텀 훅들을

각각 useToggle, useClamp, useDetails 라는 이름으로 내보내기 하고 있습니다.

// 📁hooks/📜index.tsx
import toggle from './toggle';		// toggle 훅 가져오기
import clamp from './clamp';		// clamp 훅 가져오기
import details from './details';	// details 훅 가져오기

// ▶ 각 훅을 다른 이름으로 내보내기 (export)
export {
    toggle as useToggle,
    clamp as useClamp,
    details as useDetails
};


커스텀 훅 정의  ➡️  📜"toggle.tsx" 파일 (useToggle 만들기)

📜"toggle.tsx" 파일에서 useToggle이라는 이름의 커스텀 훅을 정의합니다.

useToggl훅 value 상태값 세 가지 함수(toggle, setOn, setOff)반환합니다.

  • toggle : 값을 반전시킵니다. (예: true → false, false → true)
  • setOn : 값을 항상 true로 설정합니다.
  • setOff : 값을 항상 false로 설정합니다.
// 📁hooks/📜toggle.tsx
import React, { useState, useCallback } from 'react';

// ▶ useToggle 커스텀 훅 정의(토글 훅)
export default function useToggle(initialValue: boolean = false) {
    const [value, setValue] = useState(initialValue);

    const toggle = () => setValue((prev) => !prev);		// 현재 값을 반전

    const setOn = useCallback(() => setValue(true), []); 	// 값을 항상 true로 설정
    const setOff = useCallback(() => setValue(false), []);	// 값을 항상 false로 설정

    // ▶ 훅이 반환하는 값들
    return { value, toggle, setOn, setOff };
}

커스텀 훅 사용  ➡️ 📜"app.tsx" (App 컴포넌트에서 사용)

사용자 정의 훅을 가져오려면,

"📁hooks/📜index.tsx" 파일에서 export한 커스텀 훅의 이름을 사용하여 import 합니다.

import { 커스텀훅이름 } from '../hooks폴더명';
  • useToggle(true)를 호출하여 초기값을 true로 설정합니다.
  • 버튼을 클릭할 때마다 toggle 함수가 호출되어 value의 값이 바뀝니다.
  • value가 true일 때는 빨간색 사각형(div)이 화면에 나타나고, false일 때는 사라집니다.
// 📜app.tsx
import React from 'react';
import { useToggle } from '../hooks';			// ▶ 우리가 만든 커스텀 훅을 가져오기

// ▶ 커스텀 훅 사용
export default function App() {
    const { value, toggle, setOn } = useToggle(true);	// 필요한 값과 함수를 가져오기

    return (
        <div>
            <button onClick={toggle}>버튼</button>	{/* 버튼을 클릭하면 toggle 함수 실행 */}
            <div
                style={{
                    display: value ? 'block' : 'none',	// value 값에 따라 보이거나 숨기기
                    width: '200px',
                    height: '200px',
                    backgroundColor: 'red',
                    textAlign: 'center',
                }}
            >
                화면
            </div>
        </div>
    );
}

 


➕ 커스텀 훅의 반환값 구조 분해 할당

리액트 훅은 일반적으로 배열 또는 객체반환합니다.

이를 구조 분해 할당을 통해 각 값을 편리하게 사용할 수 있습니다.

  • 배열 형태 반환 : [a, b, c]와 같은 방식으로 순서대로 값들을 가져옴
  • 객체 형태 반환 : { a, b, c }와 같은 방식으로 프로퍼티 이름을 기준으로 값을 가져옴
  • 이름 변경하여 사용 : { a: x, b: y }와 같이 기존 이름을 다른 이름으로 변경하여 사용할 수 있음

🔎 배열 형태 반환값

useCustomHook이라는 훅이 배열을 반환하는 경우,

대괄호 []를 사용하여 반환된 값을 순서대로 할당받습니다.

  • 배열에서 구조 분해 할당을 할 때는 인덱스 번호가 중요합니다.
  • export된 이름 그대로 사용할 필요는 없습니다. 대신, 값의 순서(인덱스)가 유지되어야 합니다.
// useCustomHook의 첫 번째 값을 a에, 두 번째 값을 b에, 세 번째 값을 c에 할당
const [a, b, c] = useCustomHook();

 

🔎 객체 형태 반환값

useCustomHook이라는 훅이 객체를 반환하는 경우,

중괄호 {}를 사용해 구조 분해 할당을 통해 값을 가져올 수 있습니다.

  • 객체에서 구조 분해 할당을 할 때는 export된 이름 그대로 사용해야 합니다.
  • { export한이름: 새이름 } 형태로 이름을 변경하여 사용할 수도 있습니다.
// useCustomHook의 반환 객체에서 a, b, c 값을 구조 분해 할당으로 가져옴
const { a, b, c } = useCustomHook();

// 반환된 객체의 a는 x로, b는 y로, c는 z로 사용할 수 있음
const { a: x, b: y, c: z } = useCustomHook();

 


728x90
반응형