#320 본문에 후속 과제로 적어둔 "자동완성 대상 확장"을 독립 이슈로 분리한다.
지금 자동완성이 아는 아티스트는 artistAlias 사전에 손으로 적은 71명뿐이고,
artists 테이블에는 13,869명이 있다.
전제 — 교체가 아니라 합치기
사전을 DB로 갈아끼우는 그림이 아니다. 사전이 자동완성 말고 두 가지를 더 하고 있어서,
걷어내면 기능이 후퇴한다.
| 사전이 하는 일 |
DB가 대신할 수 있나 |
| 후보 제시 |
✅ 커버리지 200배 |
별칭 → 공식명 치환 ("원오크" → ONE OK ROCK) |
❌ artists 에 별칭 컬럼이 없다 |
| 초성 검색 ("ㅁㅅㅅ" → 미세스 그린 애플) |
❌ 초성 컬럼도 인덱스도 없다 |
따라서 목표는 로컬 사전을 그대로 두고 DB 후보를 뒤에 이어 붙이는 하이브리드다.
사전은 치환·초성·오프라인 폴백을 맡고, DB 는 나머지 13,798명의 커버리지를 맡는다.
서버는 이미 있지만 메인 검색창을 받을 준비는 안 됐다
/api/artists/search 는 투표 화면(저트래픽) 기준으로 만들어졌다.
// apps/web/src/app/api/artists/search/route.ts:19
const pattern = `%${query}%`; // 선행 와일드카드 → B-tree 인덱스를 못 탄다
const [byName, byNameKo] = await Promise.all([...]); // 13,869행 × 2 쿼리
여기에 디바운스가 없다. useArtistSearchQuery(apps/web/src/queries/artistsQuery.ts:15)는
query 가 바뀌는 즉시 요청하고, 투표 화면은 타이핑마다 setQuery 를 호출한다.
지금은 쓰는 사람이 적어 드러나지 않을 뿐이다. 메인 검색창은 이 앱에서 트래픽이 가장 많은
입력창이라, 붙이기 전에 이 둘을 먼저 손봐야 한다.
1단계 — 서버 부담 정리 (선행 필수)
2단계 — 검색 화면에 결합
3단계 — 검증
착수 전 정해야 할 것 3가지
1. 초성 검색의 범위
사전 71명에만 남길지, artists 에 name_choseong 컬럼을 추가하고 배치로 백필해 전체로 넓힐지.
후자가 제대로 된 방법이지만 마이그레이션 + packages/crawling 배치 작업이 붙는다.
2. 매칭 규칙의 불일치
사전은 접두 일치(getArtistAlias.ts:60), DB 는 중간 포함(ilike '%q%')이라
같은 입력에 두 규칙이 섞인 목록이 나온다. 사전 쪽 동작은 현행 유지가 결정된 상태이므로,
DB 쪽을 접두 일치(q%)로 맞출지를 정해야 한다. 접두로 맞추면 인덱스도 잘 탄다.
3. 후보를 골랐을 때 입력창에 넣을 값
DB 후보는 name(원어)과 name_ko(한국어)가 둘 다 있다. 곡 검색은 양쪽을 다 훑으므로
결과는 같고, 순전히 표시 문제다.
참고
#320 본문에 후속 과제로 적어둔 "자동완성 대상 확장"을 독립 이슈로 분리한다.
지금 자동완성이 아는 아티스트는
artistAlias사전에 손으로 적은 71명뿐이고,artists테이블에는 13,869명이 있다.전제 — 교체가 아니라 합치기
사전을 DB로 갈아끼우는 그림이 아니다. 사전이 자동완성 말고 두 가지를 더 하고 있어서,
걷어내면 기능이 후퇴한다.
ONE OK ROCK)artists에 별칭 컬럼이 없다따라서 목표는 로컬 사전을 그대로 두고 DB 후보를 뒤에 이어 붙이는 하이브리드다.
사전은 치환·초성·오프라인 폴백을 맡고, DB 는 나머지 13,798명의 커버리지를 맡는다.
서버는 이미 있지만 메인 검색창을 받을 준비는 안 됐다
/api/artists/search는 투표 화면(저트래픽) 기준으로 만들어졌다.여기에 디바운스가 없다.
useArtistSearchQuery(apps/web/src/queries/artistsQuery.ts:15)는query가 바뀌는 즉시 요청하고, 투표 화면은 타이핑마다setQuery를 호출한다.지금은 쓰는 사람이 적어 드러나지 않을 뿐이다. 메인 검색창은 이 앱에서 트래픽이 가장 많은
입력창이라, 붙이기 전에 이 둘을 먼저 손봐야 한다.
1단계 — 서버 부담 정리 (선행 필수)
artists.name/name_ko에pg_trgmGIN 인덱스 추가 (현재 인덱스 유무는 Supabase 대시보드 확인 필요 — 코드로는 알 수 없다)ilike두 쿼리를 하나로 합칠지 검토 (or필터 또는 RPC)2단계 — 검색 화면에 결합
useSearchSong의autoCompleteList(apps/web/src/hooks/useSearchSong.ts:64)를[로컬 사전 후보, ...DB 후보]병합 결과로 교체value기준 중복 제거 — 사전과 DB 가 같은 아티스트를 각각 내놓는다 (사전 "요아소비" / DBYOASOBI). 검색 자동완성 후속 — 제목 탭 오작동·클릭 미검색·중복 후보 #321 ③ 과 별개로, 확장이 새로 만드는 중복이라 이건 처리해야 한다canUseArtistAlias(useSearchSong.ts:58) 게이트를 DB 후보에도 적용 — 제목·번호 탭에서는 아티스트 후보를 띄우지 않는다 (검색 자동완성 후속 — 제목 탭 오작동·클릭 미검색·중복 후보 #321 ①)3단계 — 검증
/api/search가artist·artist_ko를 부분 일치로 훑으므로(apps/web/src/app/api/search/route.ts:24),artists.name이extractPrimaryArtist로 괄호가 제거된 값이어도 곡은 잡힐 것으로 보인다artists에 없다 (packages/crawling의backfillArtists.ts). 자동완성에 안 뜨는 아티스트가 남는다는 뜻이라, 허용 범위인지 판단착수 전 정해야 할 것 3가지
1. 초성 검색의 범위
사전 71명에만 남길지,
artists에name_choseong컬럼을 추가하고 배치로 백필해 전체로 넓힐지.후자가 제대로 된 방법이지만 마이그레이션 +
packages/crawling배치 작업이 붙는다.2. 매칭 규칙의 불일치
사전은 접두 일치(
getArtistAlias.ts:60), DB 는 중간 포함(ilike '%q%')이라같은 입력에 두 규칙이 섞인 목록이 나온다. 사전 쪽 동작은 현행 유지가 결정된 상태이므로,
DB 쪽을 접두 일치(
q%)로 맞출지를 정해야 한다. 접두로 맞추면 인덱스도 잘 탄다.3. 후보를 골랐을 때 입력창에 넣을 값
DB 후보는
name(원어)과name_ko(한국어)가 둘 다 있다. 곡 검색은 양쪽을 다 훑으므로결과는 같고, 순전히 표시 문제다.
참고
route.ts:7)이라 페이로드는 문제가 아니다. 실제 비용은 타이핑마다 나가는 DB 왕복이고, 그래서 1단계 없이 2단계를 올리면 안 된다.