프론트 개발자를 위한 여정

모든 영역을 안내하는 개발자

Frontend/디자인패턴

[Custom Hook 패턴] Custom Hook 구조 및 작성 방법(MobX 클래스를 Custom Hook처럼 사용하면?)

ji-frontdev 2025. 4. 6. 10:00
728x90
반응형

1️⃣ Custom Hook 기본 구조

Custom Hook은 기본적으로 함수형 컴포넌트 내부에서 재사용할 로직을 분리하는 패턴.


📌 구성 요소

  • 반드시 use 접두사를 붙여야 함 → 예: useFetch, useAuth
  • 내부에서 React Hook(useState, useEffect, useContext 등)을 사용할 수 있음
  • UI와 독립적이어야 하며 JSX를 반환하지 않음
const useCustomHook = () => {
  // 상태 관리
  const [state, setState] = useState(null);

  // 부수 효과 실행
  useEffect(() => {
    // 로직 실행
    setState('Hello Custom Hook!');
  }, []);

  return state;
};​

이제 이를 활용해보자.

const Component = () => {
  const message = useCustomHook();
  return <div>{message}</div>;
};
 

이점
✔️ useCustomHook을 여러 컴포넌트에서 재사용 가능
✔️ 관심사 분리 → 컴포넌트에서는 로직을 신경 쓰지 않고 UI만 처리


2️⃣ Custom Hook 예제: API Fetching

API 호출을 처리하는 Custom Hook을 만들어 보자.

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

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
};
 

📌 사용 예시

const UserProfile = () => {
  const { data, loading, error } = useFetch('/api/user');

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return <div>{data.name}</div>;
};​

 

이점
✔️ API 호출 로직을 재사용 가능
✔️ 상태 관리와 UI를 분리하여 유지보수성 향상
✔️ loading, error 등 UI에서 필요한 상태를 직접 관리할 필요 없음


📌 Custom Hook vs MobX 클래스

질문: MobX 클래스에서 API 메서드를 정의하고 useEffect에서 호출하는 것도 Custom Hook이라고 볼 수 있을까?

정확히 말하면 Custom Hook은 아니지만, Custom Hook처럼 사용할 수도 있음.

✅ MobX 방식

// MobX Store
import { makeAutoObservable } from 'mobx';

class UserStore {
  user = null;

  constructor() {
    makeAutoObservable(this);
  }

  async fetchUser() {
    const response = await fetch('/api/user');
    this.user = await response.json();
  }
}

export const userStore = new UserStore();
 

📌 컴포넌트에서 사용

import { useEffect } from 'react';
import { observer } from 'mobx-react-lite';
import { userStore } from './UserStore';

const UserProfile = observer(() => {
  useEffect(() => {
    userStore.fetchUser();
  }, []);

  return <div>{userStore.user?.name}</div>;
});
 

이점
✔️ MobX는 @observable 상태를 활용해 리액티브한 상태 관리가 가능
✔️ fetchUser()를 어디서든 호출하면 자동으로 상태가 업데이트됨
✔️ Custom Hook 없이도 userStore의 상태를 직접 참조하여 사용할 수 있음


✅ Custom Hook 방식으로 변환

MobX를 Custom Hook처럼 활용하려면 다음과 같이 감싸줄 수 있어.

const useUserStore = () => {
  useEffect(() => {
    userStore.fetchUser();
  }, []);

  return userStore.user;
};
 

📌 사용 예시

const UserProfile = observer(() => {
  const user = useUserStore();
  return <div>{user?.name}</div>;
});

 

💡 이렇게 하면 MobX의 상태를 Custom Hook처럼 감싸서 사용 가능!


📌 결론

🚀 MobX 방식과 Custom Hook의 차이점


 

  Custom Hook 방식 MobX 방식
상태 관리 useState, useEffect로 상태 관리 @observable 상태를 활용
API 호출 useEffect 내부에서 API 호출 Store 클래스의 메서드에서 API 호출
상태 변경 방식 setState로 직접 변경 MobX의 @observable이 자동 반응
사용 방식 함수(useFetch())로 로직을 감쌈 observer로 감싼 후 상태를 직접 참조

✅ MobX 방식도 Custom Hook처럼 사용할 수 있지만, 일반적으로는 Custom Hook이라고 부르지 않는다.

✔️ MobX는 전역 상태 관리를 목표로 하고 있음
✔️ Custom Hook은 컴포넌트 내부의 로직을 재사용하는 것이 목적

그래서 "MobX Store를 Custom Hook처럼 사용할 수 있다" 정도로 이해하면 됨.

728x90
반응형