/** * 중복 판정용 정규화. * NFKC → 소문자 → 제로폭 문자 제거 → 구두점 제거 → 공백 전부 제거. * "강남 미용실" 과 "강남미용실" 을 같은 키로 취급하기 위해 공백을 없앤다. */ const ZERO_WIDTH = /[\u200B-\u200D\uFEFF]/g; const PUNCT = /[!-\/:-@\[-`{-~·ㆍ、。「-』]/g; export function normalizeKeyword(raw: string): string { return raw .normalize('NFKC') .toLowerCase() .replace(ZERO_WIDTH, '') .replace(PUNCT, '') .replace(/\s+/g, ''); } /** 표시용 정리: 앞뒤/중복 공백만 정리하고 원문 표기는 보존 */ export function canonicalizeKeyword(raw: string): string { return raw.normalize('NFKC').replace(ZERO_WIDTH, '').replace(/\s+/g, ' ').trim(); } /** 과장광고·금칙 표현 필터 (광고심의 리스크 차단) */ const BANNED = [ '최고', '1위', '일등', '넘버원', 'no.1', '100%', '무조건', '완치', '부작용없', '영구', '평생보장', '유일한', '최저가보장', '전국최대', ]; const BANNED_NORMALIZED = BANNED.map(normalizeKeyword); export function isBanned(text: string): boolean { const n = normalizeKeyword(text); return BANNED_NORMALIZED.some((b) => b.length > 0 && n.includes(b)); }