/** * 검색 쿼리가 "질문형"인지 판별 (규칙 기반). * true이면 검색 결과 페이지에서 /api/search/ask 병렬 호출. * * false positive: /ask가 refused=true 반환하면 카드 숨김 → 무해. * false negative: 기존 검색 결과만 표시 → 무해. */ export function isQuestion(q: string): boolean { const trimmed = q.trim(); if (trimmed.length === 0) return false; // 1. ?로 끝나면 단일 단어라도 허용 (왜?, 절차?) if (trimmed.endsWith('?')) return true; // ? 없으면 단일 단어 / 4자 미만 제외 (키워드 보호) if (trimmed.length < 4) return false; if (trimmed.split(/\s+/).length < 2) return false; // 2. 한국어 질문 어미 const KO_ENDINGS = [ '인가요', '인가', '인지', '있나요', '있나', '할까요', '할까', '될까요', '될까', '뭐야', '뭔가', '뭘까', '뭔지', '뭐지', '뭐죠', '는지', '은지', '일까', '어때', '어떤가', '됩니까', '합니까', '입니까', '나요', '까요', '주세요', '알려줘', '설명해', '비교해', ]; for (const ending of KO_ENDINGS) { if (trimmed.endsWith(ending)) return true; } // 3. 한국어 질문 시작어 const KO_STARTS = [ '어떻게', '왜', '무엇', '무슨', '뭐가', '누가', '어디', '언제', '몇', '얼마나', '어떤', '어느', ]; for (const start of KO_STARTS) { if (trimmed.startsWith(start)) return true; } // 4. 영어 질문 시작어 (대소문자 무시) const EN_STARTS = [ 'what', 'how', 'why', 'when', 'where', 'who', 'which', 'is', 'are', 'do', 'does', 'can', 'could', 'should', 'would', 'explain', 'describe', 'compare', 'tell me', ]; const lower = trimmed.toLowerCase(); for (const start of EN_STARTS) { if (lower.startsWith(start + ' ')) return true; } // 5. 의미 패턴 (끝 단어) const SEMANTIC_ENDINGS = ['차이', '비교', '설명', '요약', '정리', '방법', '절차']; const lastWord = trimmed.split(/\s+/).pop() || ''; for (const pat of SEMANTIC_ENDINGS) { if (lastWord === pat || lastWord.endsWith(pat)) return true; } return false; }