[251030] fix: WebSpeech SilenceDetection disable

🕐 커밋 시간: 2025. 10. 30. 07:12:09

📊 변경 통계:
  • 총 파일: 3개
  • 추가: +72줄
  • 삭제: -54줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/.gitignore
  ~ com.twin.app.shoptime/src/hooks/useReviews/useReviews.js
  ~ com.twin.app.shoptime/src/views/SearchPanel/VoiceInputOverlay/VoiceInputOverlay.jsx

🔧 주요 변경 내용:
  • 핵심 비즈니스 로직 개선
  • 소규모 기능 개선
  • 코드 정리 및 최적화
This commit is contained in:
2025-10-30 07:12:09 +09:00
parent bc35007955
commit f569558a14
3 changed files with 72 additions and 54 deletions

View File

@@ -15,6 +15,10 @@ npm-debug.log
# ipk file # ipk file
srcBackup srcBackup
# com.lgshop.app_*.ipk # com.lgshop.app_*.ipk
.doc
.docs .docs
nul nul
.txt .txt
.optimal
OPTIMAL.md

View File

@@ -28,27 +28,27 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
// Redux 상태에서 리뷰 데이터 가져오기 - reviewVersion에 따라 선택 // Redux 상태에서 리뷰 데이터 가져오기 - reviewVersion에 따라 선택
const reviewData = useSelector((state) => { const reviewData = useSelector((state) => {
// v2 디버깅: 전체 product state 확인 // v2 디버깅: 전체 product state 확인
if (reviewVersion === 2) { // if (reviewVersion === 2) {
console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', { // console.log('[useReviews_useReviewList] 📥 전체 Redux state.product 상태:', {
keys: Object.keys(state.product), // keys: Object.keys(state.product),
reviewData: state.product.reviewData, // reviewData: state.product.reviewData,
reviewListData: state.product.reviewListData, // reviewListData: state.product.reviewListData,
loadedPrdtId: state.product.loadedPrdtId, // loadedPrdtId: state.product.loadedPrdtId,
loadedListPrdtId: state.product.loadedListPrdtId // loadedListPrdtId: state.product.loadedListPrdtId
}); // });
} // }
const data = reviewVersion === 1 const data = reviewVersion === 1
? state.product.reviewData ? state.product.reviewData
: state.product.reviewListData; : state.product.reviewListData;
console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', { // console.log('[useReviews_useReviewList] 📥 Redux reviewData 선택:', {
reviewVersion, // reviewVersion,
selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData', // selectedState: reviewVersion === 1 ? 'reviewData' : 'reviewListData',
dataExists: !!data, // dataExists: !!data,
dataKeys: data ? Object.keys(data) : 'null', // dataKeys: data ? Object.keys(data) : 'null',
reviewListLength: data?.reviewList?.length || 0 // reviewListLength: data?.reviewList?.length || 0
}); // });
return data; return data;
}); });
@@ -58,11 +58,11 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
? state.product.loadedPrdtId ? state.product.loadedPrdtId
: state.product.loadedListPrdtId; : state.product.loadedListPrdtId;
console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', { // console.log('[useReviews_useReviewList] 🔑 Redux loadedPrdtId 선택:', {
reviewVersion, // reviewVersion,
selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId', // selectedState: reviewVersion === 1 ? 'loadedPrdtId' : 'loadedListPrdtId',
loadedPrdtId: id // loadedPrdtId: id
}); // });
return id; return id;
}); });
@@ -647,17 +647,17 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
totalRatingCount: actualReviewCount, // 실제로 받은 리뷰 개수 사용 totalRatingCount: actualReviewCount, // 실제로 받은 리뷰 개수 사용
}; };
console.log('[useReviews_useReviewList] 📊 stats 계산:', { // console.log('[useReviews_useReviewList] 📊 stats 계산:', {
actualReviewCount, // actualReviewCount,
apiTotalCount, // apiTotalCount,
allReviewsLength: allReviews.length, // allReviewsLength: allReviews.length,
hasLoadedData, // hasLoadedData,
isLoading, // isLoading,
isCurrentProductLoaded, // isCurrentProductLoaded,
reviewVersion, // reviewVersion,
loadedPrdtId, // loadedPrdtId,
prdtId // prdtId
}); // });
return result; return result;
}, [allReviews.length, filteredReviews.length, displayReviews.length, reviewDetail, hasLoadedData, isLoading, isCurrentProductLoaded, reviewVersion, loadedPrdtId, prdtId]); }, [allReviews.length, filteredReviews.length, displayReviews.length, reviewDetail, hasLoadedData, isLoading, isCurrentProductLoaded, reviewVersion, loadedPrdtId, prdtId]);
@@ -675,18 +675,18 @@ const useReviews = (prdtId, patnrId, _deprecatedReviewVersion) => {
const hasReviews = allReviews.length > 0 && hasLoadedData && !isLoading && isCurrentProductLoaded; const hasReviews = allReviews.length > 0 && hasLoadedData && !isLoading && isCurrentProductLoaded;
// hasReviews 계산 로그 // hasReviews 계산 로그
useEffect(() => { // useEffect(() => {
console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', { // console.log('[useReviews_useReviewList] 🔴 hasReviews 계산:', {
allReviewsLength: allReviews.length, // allReviewsLength: allReviews.length,
hasLoadedData, // hasLoadedData,
isLoading, // isLoading,
isCurrentProductLoaded, // isCurrentProductLoaded,
loadedPrdtId, // loadedPrdtId,
prdtId, // prdtId,
resultHasReviews: hasReviews, // resultHasReviews: hasReviews,
reviewVersion // reviewVersion
}); // });
}, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]); // }, [hasReviews, allReviews.length, hasLoadedData, isLoading, isCurrentProductLoaded, loadedPrdtId, prdtId, reviewVersion]);
return { return {
// 🔥 핵심 API 함수 - useReviews가 모든 API 호출 담당 // 🔥 핵심 API 함수 - useReviews가 모든 API 호출 담당

View File

@@ -95,6 +95,11 @@ const DEFAULT_SUGGESTIONS = [
// false로 설정하면 이 기능은 완전히 비활성화됩니다 // false로 설정하면 이 기능은 완전히 비활성화됩니다
const ENABLE_WAKE_WORD = false; const ENABLE_WAKE_WORD = false;
// 🔧 Silence Detection 활성화 여부
// continuous: true에서 노이즈를 interim으로 감지할 수 있어
// 사용자가 준비 단계에서 조기 종료될 수 있으므로 false로 설정
const IS_SILENCE_CHECK_ENABLED = false;
// Utility function to clear a single timer ref (timeout) // Utility function to clear a single timer ref (timeout)
const clearTimerRef = (timerRef) => { const clearTimerRef = (timerRef) => {
if (timerRef.current) { if (timerRef.current) {
@@ -852,29 +857,38 @@ const VoiceInputOverlay = ({
// } // }
// }, [voiceInputMode, currentMode, isListening, startListening, stopListening]); // }, [voiceInputMode, currentMode, isListening, startListening, stopListening]);
// 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트 + 3초 silence detection // 🎤 Interim 텍스트 실시간 표시 및 ref 업데이트
// Silence Detection은 IS_SILENCE_CHECK_ENABLED에 따라 제어
useEffect(() => { useEffect(() => {
if (currentMode !== VOICE_MODES.LISTENING) { if (currentMode !== VOICE_MODES.LISTENING) {
// ✅ LISTENING 모드가 아니면 타이머 정리 // ✅ LISTENING 모드가 아니면 타이머 정리
if (IS_SILENCE_CHECK_ENABLED) {
clearTimerRef(silenceDetectionTimerRef); clearTimerRef(silenceDetectionTimerRef);
silenceDetectionTimerRef.current = null; silenceDetectionTimerRef.current = null;
}
return; return;
} }
// ✅ Ref 업데이트 (15초 타이머에서 최신 값을 읽을 수 있도록) // ✅ Ref 업데이트 (15초 타이머에서 최신 값을 읽을 수 있도록)
interimTextRef.current = interimText || ''; interimTextRef.current = interimText || '';
// ✨ TInput에 실시간으로 텍스트 표시
if (onSearchChange && interimText) {
onSearchChange({ value: interimText });
}
// ✅ Silence Detection (IS_SILENCE_CHECK_ENABLED === true일 때만)
if (!IS_SILENCE_CHECK_ENABLED) {
// Silence Detection 비활성화 - 15초 타이머에만 의존
return;
}
if (!interimText) { if (!interimText) {
// 입력이 없으면 silence detection 시작하지 않음 // 입력이 없으면 silence detection 시작하지 않음
return; return;
} }
// ✨ TInput에 실시간으로 텍스트 표시 // 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
if (onSearchChange) {
onSearchChange({ value: interimText });
}
// ✅ 3초 silence detection: 마지막 입력 후 3초 동안 추가 입력이 없으면 자동 종료
clearTimerRef(silenceDetectionTimerRef); clearTimerRef(silenceDetectionTimerRef);
silenceDetectionTimerRef.current = setTimeout(() => { silenceDetectionTimerRef.current = setTimeout(() => {
console.log('[VoiceInput] 🔇 3초 동안 입력 없음 - 자동 종료'); console.log('[VoiceInput] 🔇 3초 동안 입력 없음 - 자동 종료');
@@ -887,7 +901,7 @@ const VoiceInputOverlay = ({
clearTimerRef(silenceDetectionTimerRef); clearTimerRef(silenceDetectionTimerRef);
silenceDetectionTimerRef.current = null; silenceDetectionTimerRef.current = null;
}; };
}, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog]); }, [interimText, currentMode, onSearchChange, processFinalVoiceInput, addWebSpeechEventLog, IS_SILENCE_CHECK_ENABLED]);
// 🎉 Wake Word Detection: PROMPT 모드에서 백그라운드 리스닝 시작 // 🎉 Wake Word Detection: PROMPT 모드에서 백그라운드 리스닝 시작
useEffect(() => { useEffect(() => {