import { useCallback, useEffect, useRef, useState } from "react"; export const useLocalMedia = (isAuthenticated: boolean) => { const mediaStreamRef = useRef(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, }; }