본문 바로가기
C.W.K.
Stream
Lesson 01 of 05 · published

검색과 자동완성은 다른 일

~11 min · two-regimes, search-vs-complete, latency, api-design

Level 0꺼진 심지
0 XP0/33 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"둘 다 텍스트를 받아 코퍼스의 텍스트를 돌려주지만 같은 기능은 아냐. 허용되는 시간이 완전히 다르거든."

닮은 입력이 같은 일을 뜻하지 않아

검색은 '장기 투자에 관한 구절을 찾아줘'처럼 관련된 내용을 묻고, 자동완성은 '장기 투자자가 물어야 할 유일한 질문…' 다음에 아빠가 실제로 쓴 말을 묻는 기능이야. 둘 다 문자열을 받아 같은 코퍼스에서 문자열을 내놓지만, 하나는 관련성을 찾고 다른 하나는 정확한 연속을 찾지.

기다릴 수 있는 시간이 다르게 흐른다

검색은 사람이 문장을 입력하고 엔터를 누른 뒤 결과를 기다려. 수백 밀리초 동안 키워드와 벡터를 함께 찾고 두 순위를 합친 뒤 선택적으로 rerank할 여유가 있어. 자동완성은 글자 하나를 칠 때마다 실행돼. 수십 밀리초 안에 답하지 못하면 손가락보다 늦게 따라와 오히려 방해가 되지. 네트워크 왕복 한 번조차 예산을 써버릴 수 있어.

사서와 메아리는 다른 일을 해

검색은 코퍼스 어디에 있든 질문과 가장 관련 있는 구절을 순위로 보여주는 사서야. 자동완성은 현재 문구가 과거 글에서 실제로 어떻게 이어졌는지 들려주는 메아리고. 한 구현으로 둘을 해결하려 하면 자동완성에는 너무 무겁고 검색에는 너무 얕은 타협이 생겨.

입출력이 비슷해도 시간 예산이 다르면 경로를 나눠. 하나는 눈 깜짝할 사이에 끝나야 하고 다른 하나는 더 깊이 찾을 수 있다면, 각자 자기 제약을 지키는 API 둘이 어설픈 만능 API 하나보다 나아.

아래는 공유하고 계약은 나눠

두 경로는 같은 코퍼스와 chunk, 로컬 인덱스를 함께 써. 하지만 /api/search는 벡터와 rerank를 위해 원격 서비스에 닿을 수 있고 부족한 기능을 응답에 표시해. /api/complete는 로컬 기계를 떠나지 않아. 코드가 일부 겹쳐도 두 계약을 나눈 것은 중복이 아니라, 검색 한 번과 키 입력 한 번이 같은 사건이 아니라는 사실을 정직하게 반영한 설계야.

저장소를 공유한다고 실행 경로까지 하나여야 하는 것은 아니야. 같은 chunk와 FTS 인덱스를 밑에서 함께 쓰면서도 검색은 품질을, 자동완성은 즉시성을 우선할 수 있어. 공통 기반은 재사용하고 사용자에게 약속하는 시간과 실패 방식은 따로 두는 것이 이 분리의 핵심이야.

Code

키 입력과 검색 쿼리는 다른 사건이라 엔드포인트도 둘이야·python
# Same corpus underneath, two endpoints with two very different contracts.

@app.post("/api/search")
def search(query: str, mode: str = "hybrid", k: int = 8, rerank: bool = False):
    # Budget: ~100s of ms. May use vectors + fusion + optional rerank.
    # Announces degradation. This is the interactive 'find relevant passages' path.
    ...

@app.post("/api/complete")
def complete(prefix: str, k: int = 5):
    # Budget: tens of ms, on EVERY keystroke. No embeddings. No network. No model.
    # This is the 'finish my sentence from the corpus' path. Local index only.
    ...

# Merging these into one endpoint would force completion to carry search's
# machinery — and the keystroke path can't afford a single network hop.

External links

Exercise

네가 쓰는 앱에서 인터페이스는 공유하되 속도가 다르게 느껴지는 두 기능을 떠올려 — 가령 검색창 대 그 자동완성 드롭다운. 각각의 지연 시간 예산을 추정해. 한 코드 경로로 구현할래 두 개로? 빠른 기능이 느린 기능과 구현을 공유하면 뭘 포기하게 될지 나열해.
Hint
신호는 지연 시간의 절벽이야. 한 기능은 눈에 보이는 한 박자를 쓸 수 있지만 다른 기능은 즉각 반응해야 한다면, 구현을 하나로 묶을수록 빠른 쪽이 느린 쪽의 비용을 떠안아. 각자 자기 시간 예산을 지키는 두 경로가 거의 항상 나아.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.