Ramble-FE / hooks / useLocalMedia.ts
useLocalMedia.ts
Raw
import { useCallback, useEffect, useRef, useState } from "react";

export const useLocalMedia = (isAuthenticated: boolean) => {
    const mediaStreamRef = useRef<MediaStream | null>(null);
    
    const [state, setState] = useState({
        isMediaReady: false,
        isMuted: false,
    });

    const initializeMedia = useCallback(async (isAuthenticatedAtCall: boolean) => {
        await navigator.mediaDevices.getUserMedia({
            audio: {
                echoCancellation: true,
                noiseSuppression: true,
                autoGainControl: true,
            } as MediaTrackConstraints,
            video: true,
        }).then(stream => {
            if (!isAuthenticatedAtCall) {
                stream.getTracks().forEach(t => t.stop());
                return;
            }

            mediaStreamRef.current = stream;
            setState((prev) => ({ ...prev, isMediaReady: true }));
        }).catch(error => {
            console.error('웹 미디어 스트림 초기화 실패:', error);
            setState((prev) => ({ ...prev, isMediaReady: false }));
            alert('카메라와 마이크 권한이 필요합니다. 브라우저에서 권한을 허용해주세요.');
        });
    }, []);

    useEffect(() => {
        if (!isAuthenticated) {
            // 인증되지 않은 경우 미디어 스트림 해제
            if (mediaStreamRef.current) {
                mediaStreamRef.current.getTracks().forEach(track => track.stop());
                mediaStreamRef.current = null;
                setState((prev) => ({ ...prev, isMediaReady: false }));
            }
            return;
        }

        initializeMedia(isAuthenticated);

        return () => {
            if (mediaStreamRef.current) {
                mediaStreamRef.current.getTracks().forEach(track => track.stop());
                mediaStreamRef.current = null;
                setState((prev) => ({ ...prev, isMediaReady: false }));
            }
        };
    }, [isAuthenticated, initializeMedia]);

    const toggleMute = useCallback(() => {
        if (!mediaStreamRef.current) return;

        const audioTrack = mediaStreamRef.current.getAudioTracks()[0];
        if (audioTrack) {
            audioTrack.enabled = !audioTrack.enabled;
            setState((prev) => ({ ...prev, isMuted: !audioTrack.enabled }));
        }
    }, []);

    return {
        // 상태
        ...state,

        // 미디어 스트림
        mediaStream: mediaStreamRef.current,

        // 미디어 액션
        toggleMute,
    };
}