Ramble-FE / hooks / useStompClient.ts
useStompClient.ts
Raw
import { stompClient } from "@/lib";
import { Client } from "@stomp/stompjs";
import { useCallback, useEffect, useRef, useState } from "react";

export const useStompClient = (isAuthenticated: boolean) => {
    const clientRef = useRef<Client | null>(null);
    const [state, setState] = useState({
        isConnected: false,
        isConnecting: false,
    });
    
    const initializeClient = useCallback(async () => {
        if (clientRef.current?.connected || clientRef.current?.active) {
            return;
        }

        try {
            clientRef.current = await stompClient();
            setState((prev) => ({ ...prev, isConnecting: true }));

            clientRef.current.onConnect = (frame) => {
                console.log("STOMP 연결 성공:", frame);
                setState((prev) => ({ ...prev, isConnected: true, isConnecting: false }));
            };

            clientRef.current.onDisconnect = () => {
                console.log("STOMP 연결 종료");
                setState((prev) => ({ ...prev, isConnected: false, isConnecting: false }));
            };

            clientRef.current.onStompError = (frame) => {
                console.error("STOMP 에러:", frame);
                setState((prev) => ({ ...prev, isConnected: false, isConnecting: false }));
            };

            clientRef.current.onWebSocketClose = () => {
                console.warn("STOMP 소켓 종료됨 - 재연결 대기");
                setState((prev) => ({ ...prev, isConnected: false, isConnecting: true }));
            };

            clientRef.current.activate();
        } catch (error) {
            console.error("STOMP 클라이언트 초기화 실패:", error);
            setState((prev) => ({ ...prev, isConnected: false, isConnecting: false }));
        }
    }, []);

    useEffect(() => {
        if (!isAuthenticated) {
            if (clientRef.current) {
                setState({ isConnected: false, isConnecting: false });
                const toDeactivate = clientRef.current;
                clientRef.current = null;
                void toDeactivate.deactivate();
            }
            return;
        }

        initializeClient();

        return () => {
            if (clientRef.current) {
                setState({ isConnected: false, isConnecting: false });
                const toDeactivate = clientRef.current;
                clientRef.current = null;
                void toDeactivate.deactivate();
            }
        };
    }, [isAuthenticated, initializeClient]);

    return {
        ...state,
        client: clientRef.current,
    };
};