Skip to content

[Feat] pgvector 검색 + live check + POST /search 조립 - #57

Merged
kangcheolung merged 4 commits into
developfrom
feature/56
Jul 23, 2026
Merged

[Feat] pgvector 검색 + live check + POST /search 조립#57
kangcheolung merged 4 commits into
developfrom
feature/56

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 23, 2026

Copy link
Copy Markdown
Member

🔍 작업 내용

Closes #56

✨ 상세 설명

전체 흐름

POST /search
  → 1. 질문 임베딩 (Python 사이드카 /embed)
  → 2. search_queries PROCESSING 저장
  → 3. 권한 pre-filter → 접근 가능한 document_id 목록
  → 4. pgvector <=> Top-K 후보 추출 (F-SEARCH-05)
  → 5. 후보별 live check — 캐시 stale 방어 (F-SEARCH-06)
  → 6. search_results 저장 (F-SEARCH-07)
  → 7. search_queries SUCCESS + latency_ms 마감

신규 파일

파일 역할
VectorSearchRepository pgvector <=> 코사인 거리 네이티브 쿼리
VectorSearchRow 네이티브 쿼리 프로젝션 인터페이스
VectorSearchCandidate 검색 후보 내부 전달 record (similarityScore = 1 - distance)
VectorSearchQueryService permittedIds 빈 목록 fast-path + 쿼리 위임
SearchResultRepository search_results JpaRepository
SearchResultCommandService live check 통과 후보 rank 순서로 저장
SearchFacade 전체 흐름 조율, 예외 시 markFailed
SearchController POST /search — queryText 필수, topK 1~20 기본 5
SearchRequest / SearchResponse / SearchResultItem 요청·응답 DTO

stale 캐시 방어 시나리오 (포트폴리오 증빙)

권한 회수 직후 검색 시 pre-filter 단계에서 캐시 기반으로 문서가 포함될 수 있지만, live check(5단계 canReadDocument)에서 invalidated_at 확인 + ROLE/DEPT live 검증으로 해당 문서를 최종 제거한다.

[PERM] + [SEARCH] 타이밍 로그로 전 과정 추적 가능하다.

🛠️ 추후 리팩토링 및 고도화 계획

  • live check 탈락 후 보충 조회(fill-up) — 현재는 MVP 정책으로 그대로 반환
  • 임베딩 서버 HTTP 호출을 트랜잭션 외부로 분리 고려
  • KEYWORD / HYBRID 검색 타입 추가 (2단계 확장)
  • @DataJpaTest로 UNION 쿼리 및 pgvector 쿼리 통합 테스트 추가

📸 스크린샷 (선택)

해당 없음

💬 리뷰 요구사항

  • SearchFacade@Transactional 안에서 임베딩 서버 HTTP 호출을 포함하는 구조인데, 커넥션 점유 시간이 길어지는 트레이드오프가 있습니다. MVP 단계에서 허용 가능한 수준인지 의견 부탁드립니다.
  • VectorSearchRepositoryIN (:permittedIds) 파라미터가 매우 많아질 경우(수천 건 이상) 쿼리 성능 이슈가 생길 수 있습니다. 현재 단계에서 추가 대응이 필요한지 의견 부탁드립니다.

Summary by CodeRabbit

  • 새 기능

    • 벡터 기반 문서 검색 기능을 추가했습니다.
    • 검색어, 결과 개수, 컬렉션을 지정해 검색할 수 있습니다.
    • 문서 제목, 관련 본문, 페이지, 유사도 점수를 포함한 결과를 제공합니다.
    • 접근 권한을 검색 전후로 확인해 권한이 변경된 문서는 결과에서 제외합니다.
    • 검색 결과와 처리 상태를 저장하고, 결과가 없을 때 빈 목록을 반환합니다.
  • 문서

    • 벡터 검색 처리 흐름과 오류·권한 검증 정책을 정리한 설계 문서를 추가했습니다.

kangcheolung and others added 3 commits July 23, 2026 13:14
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ade 단위 테스트 — F-SEARCH-05/06/07

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kangcheolung, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7308dd28-cc67-40ff-a14a-7f267b48c242

📥 Commits

Reviewing files that changed from the base of the PR and between bb32559 and 396d935.

📒 Files selected for processing (5)
  • src/main/java/com/opensource/docgrid/domain/search/dto/VectorSearchCandidate.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java
  • src/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.java
  • src/main/java/com/opensource/docgrid/domain/search/service/command/SearchQueryCommandService.java
📝 Walkthrough

Walkthrough

pgvector 기반 Top-K 검색, 후보별 live 권한 검증, 검색 결과 저장 및 POST /search 응답 조립 흐름을 추가했습니다. 요청 검증, 검색 상태 마감, 빈 결과와 실패 처리, 관련 단위 테스트도 포함합니다.

Changes

벡터 검색 및 API 흐름

Layer / File(s) Summary
pgvector 후보 검색
src/main/java/com/opensource/docgrid/domain/search/repository/*, src/main/java/com/opensource/docgrid/domain/search/service/query/*, src/main/java/com/opensource/docgrid/domain/search/dto/VectorSearchCandidate.java, src/test/java/com/opensource/docgrid/domain/search/service/query/*
권한 허용 문서 ID와 활성 임베딩 모델을 조건으로 pgvector Top-K 후보를 조회하고, cosine distance를 similarityScore로 변환합니다.
검색 오케스트레이션 및 live check
src/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.java, src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java, docs/design/...
SearchFacade가 임베딩, 검색 쿼리 생성, 권한 pre-filter, 후보별 canReadDocument() 재검증, 성공·실패 마감을 순차 처리합니다.
결과 저장 및 HTTP 응답
src/main/java/com/opensource/docgrid/domain/search/controller/*, src/main/java/com/opensource/docgrid/domain/search/dto/*, src/main/java/com/opensource/docgrid/domain/search/service/command/*, src/test/java/com/opensource/docgrid/domain/search/service/command/*
POST /search 요청 검증과 응답 DTO를 추가하고, live check 통과 후보를 rank 순서로 search_results에 저장합니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  actor Client
  participant SearchController
  participant SearchFacade
  participant VectorSearchQueryService
  participant PermissionQueryService
  participant SearchResultCommandService

  Client->>SearchController: POST /search
  SearchController->>SearchFacade: search(userId, request)
  SearchFacade->>VectorSearchQueryService: Top-K 후보 검색
  VectorSearchQueryService-->>SearchFacade: VectorSearchCandidate 목록
  SearchFacade->>PermissionQueryService: 후보별 canReadDocument()
  PermissionQueryService-->>SearchFacade: 권한 판정
  SearchFacade->>SearchResultCommandService: 검증된 후보 저장
  SearchResultCommandService-->>SearchFacade: 저장 완료
  SearchFacade-->>SearchController: SearchResponse
  SearchController-->>Client: ApiResponse<SearchResponse>
Loading

Possibly related PRs

  • DocGrid/backend#23: live check에서 사용하는 PermissionQueryService.canReadDocument() 구현과 직접 연결됩니다.
  • DocGrid/backend#45: search_queries 생성 및 SUCCESS/FAILED 상태 처리 흐름과 연결됩니다.
  • DocGrid/backend#55: 벡터 검색 전 권한 허용 문서 ID를 조회하는 pre-filter 흐름과 연결됩니다.

Suggested labels: ✨ Feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 pgvector 검색, live check, POST /search 조립이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 템플릿의 작업 내용, 상세 설명, 추후 계획, 스크린샷, 리뷰 요구사항 섹션이 모두 포함되어 있고 내용도 충분합니다.
Linked Issues check ✅ Passed 핵심 흐름과 DTO·저장·검증이 구현되어 #56의 pgvector 검색, live check, 저장, POST /search 요구와 부합합니다.
Out of Scope Changes check ✅ Passed 추가된 문서, 서비스, DTO, 테스트는 모두 검색 API 구현 범위에 속해 보이며 불필요한 변경은 보이지 않습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/56

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (4)
src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java (1)

60-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

저장 계약의 나머지 필드도 검증하세요.

이 테스트는 rank와 similarityScore만 확인합니다. matchedTextfinalScore도 저장 계약의 일부이므로, capture한 엔티티에서 두 필드를 함께 assert해야 해당 매핑 회귀를 탐지할 수 있습니다.

As per path instructions, "src/test/**/*.java: 테스트 커버리지, 스프링 테스트 어노테이션, mock 사용법, 네이밍 규칙을 확인한다."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java`
around lines 60 - 65, Update the assertions in SearchResultCommandServiceTest to
also verify matchedText and finalScore on the captured SearchResult entities in
saved. Use the expected values for each entity and preserve the existing rank
and similarityScore assertions.

Source: Path instructions

docs/design/kangcheolung-#56-vector-search-live-check-api.md (1)

18-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

모든 fenced code block에 언어 식별자를 지정하세요.

  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L18-L47: 흐름도 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L57-L60: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L110-L112: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L132-L134: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L157-L166: 시나리오 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L176-L178: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L186-L189: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L210-L212: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L222-L224: 경로 블록에 text를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L226-L232: HTTP 예시에 http를 지정하세요.
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md#L236-L238: 경로 블록에 text를 지정하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design/kangcheolung-`#56-vector-search-live-check-api.md around lines 18
- 47, Specify language identifiers for every fenced code block in
docs/design/kangcheolung-#56-vector-search-live-check-api.md: use text for the
flow, path, and scenario blocks at lines 18-47, 57-60, 110-112, 132-134,
157-166, 176-178, 186-189, 210-212, 222-224, and 236-238; use http for the HTTP
example at lines 226-232.

Source: Linters/SAST tools

src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java (1)

51-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

리포지토리 호출 인자 계약도 검증하세요.

현재 any*() stub은 modelId, permittedIds, topK, 벡터 직렬화 값이 잘못 전달돼도 테스트를 통과시킵니다. ArgumentCaptor 또는 정확한 matcher로 이 값들을 검증해 pre-filter와 Top-K 계약 회귀를 막으세요.

As per path instructions, "src/test/**/*.java: 테스트 커버리지, 스프링 테스트 어노테이션, mock 사용법, 네이밍 규칙을 확인한다."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java`
around lines 51 - 62, Update the test around vectorSearchRepository.findTopK and
vectorSearchQueryService.search to capture or precisely match every repository
argument: the expected modelId, permittedIds, topK value, and serialized VECTOR
input. Assert those values explicitly so incorrect pre-filter or Top-K arguments
cannot satisfy the stub.

Source: Path instructions

src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java (1)

42-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

전역 LENIENT 설정을 제거하고 기본 strict stubbing을 유지하세요.

현재 테스트의 stubbing은 각 시나리오에서 사용되므로 전역 완화는 불필요한 mock 설정을 숨길 수 있습니다. 필요한 경우에만 개별 stubbing에 한정해 완화하세요.

수정 예시
-import org.mockito.junit.jupiter.MockitoSettings;
-import org.mockito.quality.Strictness;
...
-@MockitoSettings(strictness = Strictness.LENIENT)

As per path instructions, src/test/**/*.java의 “mock 사용법” 확인 규칙을 적용했습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java`
around lines 42 - 44, SearchFacadeTest의 클래스 수준 `@MockitoSettings`(strictness =
Strictness.LENIENT)를 제거하고 Mockito 기본 strict stubbing을 사용하세요. 각 테스트 시나리오에서 실제로
불필요한 stubbing이 있는 경우에만 해당 개별 stubbing에 한정해 완화 설정을 적용하세요.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/kangcheolung-`#56-vector-search-live-check-api.md:
- Around line 249-257: Clarify the FAILED-history policy in the live-check API
design: either persist failure status through an independent transaction that
survives rethrown exceptions, including embedding, user, and collection lookup
failures before createProcessing(), or revise the documented behavior to state
that those pre-history failures do not create SearchQuery records. Align the
failure table and the “markFailed() then rethrow remains FAILED” section with
the chosen implementation.

In
`@src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java`:
- Around line 7-11: 각 신규 타입에 역할·책임·경계를 설명하는 클래스 수준 주석을 추가하세요. SearchRequest는
HTTP 검색 요청 DTO와 기본값·검증 경계를, SearchController는 HTTP API 진입점과 facade 위임을,
SearchResponse는 검색 응답 조립과 API 응답 경계를, SearchResultItem은 개별 결과 표현과 후보 모델 변환을,
SearchFacadeTest는 테스트 대상과 mock 경계를 설명해야 합니다. 변경 대상은
src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java
7-11,
src/main/java/com/opensource/docgrid/domain/search/controller/SearchController.java
22-26,
src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java
9-12,
src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java
9-15,
src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java
42-45입니다.
- Line 10: Update the collectionId field in SearchRequest to accept null for
whole-collection searches but validate any provided value as strictly positive,
using the project’s existing DTO validation annotations and conventions.

In
`@src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java`:
- Around line 13-18: Update SearchResponse.of to wrap the constructed items list
in a copied unmodifiable list when creating the response, ensuring
SearchResponse.results cannot be modified by callers and matches the immutable
contract used by empty().

In
`@src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java`:
- Line 14: Update the similarityScore contract consistently: either document and
implement the existing 1 - distance calculation for its actual -1~1 range, or
transform/clamp the value so it genuinely remains within 0~1 and update the
`@Schema` description accordingly. Ensure the implementation producing
similarityScore and the SearchResultItem schema describe the same returned
range.

In
`@src/main/java/com/opensource/docgrid/domain/search/repository/SearchResultRepository.java`:
- Around line 7-8: 添加类级 JavaDoc:在 SearchResultRepository 中说明其作为 SearchResult
持久化边界的职责;在 VectorSearchQueryServiceTest 中说明其验证 fast-path 与候选转换;在
SearchResultCommandServiceTest 中说明其验证搜索结果保存映射。为这三个新增类型分别补充职责、责任范围和边界描述。

In
`@src/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.java`:
- Around line 29-42: Update the class-level flow documentation in SearchFacade
to include the User/Collection FK entity lookup and PROCESSING persistence
before the live check, renumber live check as step 6, shift search_results
saving to step 7, and SUCCESS/latency completion to step 8. Keep the documented
sequence aligned with the actual implementation.
- Around line 111-113: Update the exception path in SearchFacade so the failure
state recorded by SearchQueryCommandService.markFailed is committed
independently before the original exception is rethrown. Use a separate
REQUIRES_NEW transaction boundary for the failure update, or otherwise adjust
exception handling to prevent updateToFailed from rolling back while preserving
exception propagation.

---

Nitpick comments:
In `@docs/design/kangcheolung-`#56-vector-search-live-check-api.md:
- Around line 18-47: Specify language identifiers for every fenced code block in
docs/design/kangcheolung-#56-vector-search-live-check-api.md: use text for the
flow, path, and scenario blocks at lines 18-47, 57-60, 110-112, 132-134,
157-166, 176-178, 186-189, 210-212, 222-224, and 236-238; use http for the HTTP
example at lines 226-232.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java`:
- Around line 60-65: Update the assertions in SearchResultCommandServiceTest to
also verify matchedText and finalScore on the captured SearchResult entities in
saved. Use the expected values for each entity and preserve the existing rank
and similarityScore assertions.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java`:
- Around line 51-62: Update the test around vectorSearchRepository.findTopK and
vectorSearchQueryService.search to capture or precisely match every repository
argument: the expected modelId, permittedIds, topK value, and serialized VECTOR
input. Assert those values explicitly so incorrect pre-filter or Top-K arguments
cannot satisfy the stub.

In
`@src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java`:
- Around line 42-44: SearchFacadeTest의 클래스 수준 `@MockitoSettings`(strictness =
Strictness.LENIENT)를 제거하고 Mockito 기본 strict stubbing을 사용하세요. 각 테스트 시나리오에서 실제로
불필요한 stubbing이 있는 경우에만 해당 개별 stubbing에 한정해 완화 설정을 적용하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 95eb3b3d-7a97-45c1-83c1-89d49c283504

📥 Commits

Reviewing files that changed from the base of the PR and between a0982d4 and bb32559.

📒 Files selected for processing (15)
  • docs/design/kangcheolung-#56-vector-search-live-check-api.md
  • src/main/java/com/opensource/docgrid/domain/search/controller/SearchController.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/VectorSearchCandidate.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java
  • src/main/java/com/opensource/docgrid/domain/search/repository/SearchResultRepository.java
  • src/main/java/com/opensource/docgrid/domain/search/repository/VectorSearchRepository.java
  • src/main/java/com/opensource/docgrid/domain/search/repository/VectorSearchRow.java
  • src/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.java
  • src/main/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandService.java
  • src/main/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryService.java
  • src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java
  • src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java
  • src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java

Comment thread docs/design/kangcheolung-#56-vector-search-live-check-api.md
Comment on lines +7 to +11
public record SearchRequest(
@NotBlank String queryText,
@Min(1) @Max(20) Integer topK,
Long collectionId
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

새 Java 타입에 역할·책임·경계를 설명하는 클래스 주석을 추가하세요.

  • src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java#L7-L11: HTTP 검색 요청 DTO와 기본값·검증 경계를 설명하세요.
  • src/main/java/com/opensource/docgrid/domain/search/controller/SearchController.java#L22-L26: HTTP API 진입점과 facade 위임 경계를 설명하세요.
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java#L9-L12: 검색 응답 조립 DTO와 API 응답 경계를 설명하세요.
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java#L9-L15: 개별 검색 결과 표현과 후보 모델 변환 경계를 설명하세요.
  • src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java#L42-L45: SearchFacade 단위 테스트의 대상과 mock 경계를 설명하세요.

As per coding guidelines, “Every newly created class, interface, or record must have a class-level comment describing its role, responsibility, and boundary.”

📍 Affects 5 files
  • src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java#L7-L11 (this comment)
  • src/main/java/com/opensource/docgrid/domain/search/controller/SearchController.java#L22-L26
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java#L9-L12
  • src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java#L9-L15
  • src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java#L42-L45
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java`
around lines 7 - 11, 각 신규 타입에 역할·책임·경계를 설명하는 클래스 수준 주석을 추가하세요. SearchRequest는
HTTP 검색 요청 DTO와 기본값·검증 경계를, SearchController는 HTTP API 진입점과 facade 위임을,
SearchResponse는 검색 응답 조립과 API 응답 경계를, SearchResultItem은 개별 결과 표현과 후보 모델 변환을,
SearchFacadeTest는 테스트 대상과 mock 경계를 설명해야 합니다. 변경 대상은
src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java
7-11,
src/main/java/com/opensource/docgrid/domain/search/controller/SearchController.java
22-26,
src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResponse.java
9-12,
src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java
9-15,
src/test/java/com/opensource/docgrid/domain/search/service/SearchFacadeTest.java
42-45입니다.

Source: Coding guidelines

Comment thread src/main/java/com/opensource/docgrid/domain/search/dto/request/SearchRequest.java Outdated
@Schema(description = "문서 제목") String documentTitle,
@Schema(description = "매칭된 청크 텍스트") String chunkText,
@Schema(description = "원본 문서 페이지 번호, 페이지 개념이 없는 형식은 null") Integer pageNo,
@Schema(description = "코사인 유사도 (0~1, 높을수록 유사)") BigDecimal similarityScore

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Locate SearchResultItem"
fd -a 'SearchResultItem\.java$' . || true

echo "## Git status/stat"
git status --short
git diff --stat || true

echo "## Search for similarity/cosine transforms in Java"
rg -n "similarityScore|similarity|cosine|vector|Similarity|cosine\(" src/main/java || true

echo "## Candidate file"
file="$(fd 'SearchResultItem\.java$' . | head -n1 || true)"
if [ -n "${file:-}" ]; then
  echo "FILE=$file"
  wc -l "$file"
  cat -n "$file"
fi

Repository: DocGrid/backend

Length of output: 9933


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## VectorSearchCandidate"
file="$(fd 'VectorSearchCandidate\.java$' . | head -n1 || true)"
echo "FILE=$file"
wc -l "$file"
cat -n "$file"

echo "## VectorSearchRepository"
file="$(fd 'VectorSearchRepository\.java$' . | head -n1 || true)"
echo "FILE=$file"
wc -l "$file"
sed -n '1,120p' "$file" | cat -n

echo "## SearchResultCommandService"
file="$(fd 'SearchResultCommandService\.java$' . | head -n1 || true)"
echo "FILE=$file"
wc -l "$file"
cat -n "$file"

echo "## Relevant SQL/native query text"
rg -n "similarity_score|cosine|<=>|similarityScore|vectorStr|FindQuery|`@Query`|`@SqlResultSetMapping`|`@ConstructorResult`" src/main/java -S

Repository: DocGrid/backend

Length of output: 13000


유사도 범위 표시를 실제 반환 값과 맞게 변경하세요.

현재 similarityScore1 - e.vector <=> queryVector로 계산되어 코사인 거리 범위가 0~2라면 결과도 -1~1에 열 수 있어 0~1 문서가 실제 응답 계약과 맞지 않습니다. 1 - distance의 계약을 유지하려면 문서와 구현에서 0~2라고 맞추고, 실제 유사도로 맞추려면 clamp 또는 1/2 * (1 - distance) 같은 변환을 일관되게 적용하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/opensource/docgrid/domain/search/dto/response/SearchResultItem.java`
at line 14, Update the similarityScore contract consistently: either document
and implement the existing 1 - distance calculation for its actual -1~1 range,
or transform/clamp the value so it genuinely remains within 0~1 and update the
`@Schema` description accordingly. Ensure the implementation producing
similarityScore and the SearchResultItem schema describe the same returned
range.

Source: Coding guidelines

Comment on lines +7 to +8
public interface SearchResultRepository extends JpaRepository<SearchResult, Long> {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

신규 타입에 역할과 경계를 설명하는 클래스 레벨 주석을 추가하세요.

  • src/main/java/com/opensource/docgrid/domain/search/repository/SearchResultRepository.java#L7-L8: SearchResult 영속화 경계를 설명하는 JavaDoc을 추가하세요.
  • src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java#L25-L27: fast-path 및 후보 변환을 검증하는 테스트 클래스임을 설명하세요.
  • src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java#L31-L33: 검색 결과 저장 매핑을 검증하는 테스트 클래스임을 설명하세요.

As per coding guidelines, "Every newly created class, interface, or record must have a class-level comment describing its role, responsibility, and boundary."

📍 Affects 3 files
  • src/main/java/com/opensource/docgrid/domain/search/repository/SearchResultRepository.java#L7-L8 (this comment)
  • src/test/java/com/opensource/docgrid/domain/search/service/query/VectorSearchQueryServiceTest.java#L25-L27
  • src/test/java/com/opensource/docgrid/domain/search/service/command/SearchResultCommandServiceTest.java#L31-L33
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/opensource/docgrid/domain/search/repository/SearchResultRepository.java`
around lines 7 - 8, 添加类级 JavaDoc:在 SearchResultRepository 中说明其作为 SearchResult
持久化边界的职责;在 VectorSearchQueryServiceTest 中说明其验证 fast-path 与候选转换;在
SearchResultCommandServiceTest 中说明其验证搜索结果保存映射。为这三个新增类型分别补充职责、责任范围和边界描述。

Source: Coding guidelines

Comment thread src/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.java Outdated
, 불변 리스트, 유사도 clamp, 주석 번호

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@kangcheolung
kangcheolung merged commit 12fe815 into develop Jul 23, 2026
1 check passed
@kangcheolung kangcheolung mentioned this pull request Jul 25, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] pgvector 검색 + live check + POST /search 조립

1 participant