feat(S15P11A705-339): 단어형 질의의 본문 문자열 검색과 RRF 병합 (검증 게이트 통과) - #206
Merged
Conversation
검색 고도화 트랙(ai 레포 P49 §6)의 작업 PR은 base가 dev가 아니라 통합 브랜치라서, 트리거가 dev 한정이면 그 PR들이 CI 없이 병합된다. ai-ci가 같은 이유로 같은 트리거를 추가한 선례(ai cf07b15)를 따른다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Spring 테스트 컨텍스트 캐시는 컨텍스트를 닫지 않고 쌓고, 컨텍스트마다 HikariPool(기본 10)이 공유 컨테이너 하나에 연결을 잡는다. 합이 postgres 기본 한도(100)를 넘으면 늦게 뜨는 컨텍스트가 "FATAL: sorry, too many clients already"로 죽는다 — 검색 쪽 컨텍스트가 하나 늘면서 실제로 넘었다 (clean check에서 OpenApi·Security·Flyway 계열 4클래스 기동 실패로 관측). 캐시 상한 축소는 기각한다: evict된 컨텍스트의 재기동 비용을 뒤 클래스가 갚고, 어느 클래스가 느려지는지가 실행 순서에 좌우된다. 이 값은 테스트 전용 컨테이너 설정이라 운영과 무관하다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
검색 고도화 트랙 P49 작업 5(티켓 미발급 — 발급 시 병합 커밋에 키를 싣는다). 본문에 질의 문자열이 그대로 있는데 임베딩 유사도가 낮아 검색되지 않는 실패 사례(신한)를 회복한다. 규칙은 ai 파트 오프라인 실측(I54)의 확정안 그대로다: 단어형 한정·부분일치 게이트 + RRF(k=60) 병합 + similarity 원 코사인 유지 + 실패 시 벡터만. - LexicalContextRepository: core.context 본인 소유·활성 본문의 부분일치 매치. DISTINCT ON으로 Record당 대표 Context(최신 교체본) 하나. LIKE 특수문자 이스케이프 - LexicalSearchProperties: pinlog.search.lexical.enabled(기본 false — 꺼진 상태가 현행과 동일하다는 계약을 기본값 컨텍스트 테스트로 고정) · word-query-max-chars(ai와 같은 값 5) - RecordSearchService: distinctByRecord 직후 병합 단계. 단어형 판정은 ai와 등가(유니코드 공백 전체·코드 포인트 길이). 문자열 후보도 기존 Core 재검증에 그대로 합류. 조회 실패는 벡터 결과로 조용히 복귀. size 절단은 RRF 하위부터 한 번만 - 실측과 다르게 간 지점 셋(문자열 목록 순위 기준·문자열 단독 후보의 점수 항·similarity 0.0)은 컷 탈락 후보의 코사인이 FastAPI 밖으로 나오지 않는 제약에서 나왔다 — 근거와 트레이드오프는 구현 리포트(BI-42, 별도 커밋 예정)에 있다 검증: 신규 12건 RED(병합 요구 6건 실패 확인) → 구현 후 GREEN, 기본값 꺼짐 계약 1건 추가, clean check 전체 통과. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
구현 커밋(b909227)이 예고한 기록이다. 실측(ai 레포 I54)의 계산을 런타임에 그대로 옮길 수 없던 세 지점(문자열 목록 순위 기준·문자열 단독 후보의 점수 항·similarity 대체값)의 판단과 근거, TDD 검증 경과, 실서버 E2E가 검증 게이트 몫으로 남는다는 경계를 담는다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
P49 §6 규칙의 정기 동기화다. dev 신규 커밋(f9d521f)은 AI 구역 문서 가독성 재구성으로, 이 트랙의 변경 파일과 교집합이 없음을 병합 전 확인했다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dev에 먼저 머지된 PR #202가 BI-42를 `BI-42-2026-08-07-map-keyword-chips.md`로 확정했다. 이 브랜치의 `BI-42-2026-08-06-search-lexical-merge.md`와 번호가 겹치므로 뒤에 오는 이쪽을 BI-43으로 옮긴다. dev에 BI-43은 아직 없다. 두 파일은 날짜와 주제가 달라 파일명이 서로 다르다. git은 경로가 다른 파일을 같은 자원으로 보지 않으므로 병합할 때 충돌로 잡지 않고 둘 다 조용히 남긴다. 번호 중복은 사람이 읽을 때만 드러난다. dev의 직전 커밋 39cbc7f가 같은 사고를 BD-46에서 수습한 커밋이고, 이번에는 병합 전에 처리한다. implements 구역은 목록 표를 두지 않으므로(`docs/backend/implements/README.md`) 파일명과 H1, 작업 로그의 링크만 고치면 참조가 모두 맞는다. 브랜치 전체에서 옛 번호를 참조하는 곳이 남지 않았음을 확인했다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
P49 §6 규칙의 정기 동기화다. dev 신규 커밋은 세 건이다. 733787d는 최근 7일 기록 목록 조회 API, f66b324는 지도 bbox 안 상위 키워드 조회 API, 39cbc7f는 겹친 BD-46 두 개 중 나중 것을 BD-50으로 옮긴 문서 정리다. 변경 파일 경로에 교집합이 없음을 병합 전에 확인했다. 문서 번호는 교집합이 있었으나 앞선 커밋 a5e7673에서 이쪽 BI-42를 BI-43으로 옮겨 미리 풀었다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
병합 직전 dev 가 전진했다(#204 이미지 업로드 용량 상향). dev 브랜치 보호가 strict 라 병합 시점에 dev 최신 상태여야 한다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
병합 직전 dev 가 또 전진했다(#203 컬렉션 목록 조회 API). 파일 교집합이 없음을 확인하고 반영한다. dev 브랜치 보호가 strict 라 병합 시점에 dev 최신이어야 한다. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dev 가 계속 전진해 strict 요건을 다시 맞춘다. 파일 교집합 없음. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
검색 고도화 트랙의 back 몫을 dev 에 반영한다. 본문에 질의 문자열이 그대로 있는 기록을 찾아 벡터 결과와 합치는 경로를 추가했다. 기본 꺼짐 플래그 뒤에 있어 이 병합으로 검색 동작은 바뀌지 않는다.
3레포(
docs·back·ai)를 같은 이름의 통합 브랜치에서 함께 준비해 한 번에 릴리스한다.docs계약 개정(3c28c01)은 병합 완료,ai는 ai#118 로 함께 올라가 있다.Jira
변경 사항
LexicalContextRepository(신설) —core.context에서 요청자 소유·삭제되지 않은 본문의 부분일치를 찾는다. 기록당 대표 Context 하나를 고르고, LIKE 문법 글자(%·_·\)는 이스케이프해 글자로 취급한다.LexicalSearchProperties(신설) —pinlog.search.lexical.enabled(기본 false) ·word-query-max-chars(기본 5, ai 의 같은 뜻 설정과 일치해야 한다).RecordSearchService— FastAPI 응답을 기록 단위로 정리한 직후 병합 단계를 넣었다. 단어형 질의에서만 문자열 매치를 조회해 RRF(k=60)로 재정렬하고,size절단은 재정렬 뒤 한 번만 한다. 문자열 후보도 기존 Core 재검증을 그대로 지난다.backend-ci.yml— 통합 브랜치를 트리거에 추가(검색 고도화 작업 PR 의 base 가 dev 가 아니었다).IntegrationContainerSupport— 테스트 컨테이너 postgres 연결 한도 상향. 컨텍스트가 늘며 기본 한도(100)를 넘겨 기동이 실패했다.검증
./gradlew clean check --no-daemon통과.RecordSearchApiTests에 「기본값 꺼짐 = 현행 동일」 계약 1건 추가신한회복은 이 문자열 경로의 몫이며 전체 경로에서 실증했다. 증거는 ai 레포.search/gate_*.json리뷰 포인트
similarity는 0.0 이다. 벡터 컷을 통과하지 못해 실을 코사인이 없다. 응답 계약상 숫자가 필수이고(front 스키마), 0.0 은 실제 코사인이 만들 수 없는 값이라 구분 표지도 된다. 벡터 후보의 값은 원 코사인 그대로다.similarity대체값)의 판단과 근거는 BI-43 에 적었다. 전부 「컷 탈락 후보의 코사인이 FastAPI 밖으로 나오지 않는다」에서 나온 제약이다.미결 / 후속
🤖 Generated with Claude Code