[Test/Fix/Docs] POST /search 수동 테스트 + EmbedServerResponse 버그 수정 + 설계 문서 상세 - #60
Conversation
…DING_DIMENSION_MISMATCH 버그 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… 필드 제거 대응) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 50 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthrough임베딩 서버와 pgvector 인프라 문서를 확장하고, 벡터 검색의 권한 필터·임베딩 검증·요청 상태 기록·live check·결과 저장 흐름을 구체화했다. 임베딩 응답에서 Changes벡터 검색 기능
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🧹 Nitpick comments (2)
src/main/java/com/opensource/docgrid/domain/embedding/dto/response/EmbedServerResponse.java (1)
3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
float[]를 방어적으로 복사해 DTO 불변성을 보장하세요.Java record는 얕은 불변성만 제공하므로
vector()가 mutable 배열을 그대로 반환합니다. 이 배열은EmbedResult와 검색 저장 흐름으로 전달되므로 downstream mutation이 같은 버퍼를 변경할 수 있습니다. compact constructor와 accessor에서 복사하거나 immutable value representation을 사용하세요.As per path instructions: DTO는 Getter/Setter 남용을 피하고 고정된 데이터 구조로 설계해야 하므로 배열 내부의 가변성도 차단해야 합니다.
🤖 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/embedding/dto/response/EmbedServerResponse.java` at line 3, Update the EmbedServerResponse record to defensively copy the vector array both when storing it in the compact constructor and when returning it from vector(), preserving the fixed DTO structure while preventing downstream mutations from affecting the record’s internal data.Source: Path instructions
src/test/java/com/opensource/docgrid/domain/embedding/service/query/QueryEmbeddingServiceTest.java (1)
46-73: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win실제 Python JSON 역직렬화를 검증하는 테스트를 추가하세요.
현재 테스트는
new EmbedServerResponse(vector)를 직접 생성하고body()결과를 mock하므로, 실제 응답{"vector":[...]}가dimension없이 정상 역직렬화되는지 검증하지 않습니다. 이번 변경의 핵심 회귀를 방지하려면 프로젝트 ObjectMapper 또는 HTTP mock을 사용해 wire contract를 테스트해야 합니다.As per path instructions:
src/test/**/*.java는 변경된 계약과 핵심 분기에 대한 테스트 커버리지를 확인해야 합니다.🤖 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/embedding/service/query/QueryEmbeddingServiceTest.java` around lines 46 - 73, Update QueryEmbeddingServiceTest around embed_success to deserialize the actual JSON contract {"vector":[...]} using the project ObjectMapper or HTTP mock instead of constructing EmbedServerResponse directly and mocking body(). Verify that a response without the dimension field is successfully deserialized and processed into the expected EmbedResult, while preserving the existing dimension-mismatch coverage.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-`#35-embedding-server.md:
- Around line 312-317: Update the embedding-server startup instructions to use
the /health endpoint as the sole readiness check: remove the Uvicorn startup-log
criterion and instruct users to poll /health until it returns HTTP 200,
accounting for the initial 503 responses while the model loads.
- Around line 55-60: 문서의 모든 해당 코드 펜스에 언어 식별자를 추가하세요. 디렉터리 트리처럼 문법 강조가 필요 없는 블록은
text를 사용하고, 언급된 모든 적용 위치에서 일관되게 지정하여 MD040 lint를 통과하게 하세요.
- Around line 264-296: Update the pg_hba.conf rule in the documented
initialization flow to restrict access to the intended Docker bridge CIDR or
explicitly allowed host/IP addresses instead of 0.0.0.0/0. Keep SCRAM
authentication enabled and update the nearby troubleshooting and trade-off text
to describe the narrower allowed range without implying unrestricted IPv4
access.
In `@docs/design/kangcheolung-`#41-vector-search-db-infrastructure.md:
- Around line 153-156: Update the first troubleshooting subsection heading
immediately under “## 6. 트러블슈팅” from level four to level three, preserving its
existing title and content.
- Around line 22-35: V32 migration must be protected for production databases:
add a preflight or explicit fresh-database-only guard before changing
embeddings.vector, and preserve existing embedding data through backup or a
validated migration path instead of unconditional DROP/ADD. Before casting
search_queries.query_vector, validate that non-NULL values are valid vectors
with exactly 1024 dimensions and either correct/repair or fail with a clear
controlled message; ensure Flyway does not proceed on incompatible data.
In `@docs/design/kangcheolung-`#44-search-embedding-query-logging.md:
- Around line 233-245: Update the REQUIRES_NEW method markFailed so it reloads
the SearchQuery by identifier within the new transaction before applying
updateToFailed(errorMessage), rather than mutating the detached argument
directly. Use the repository’s findById flow (or an equivalent explicit update
query) and preserve the FAILED status persistence when the outer transaction
rolls back.
In `@docs/design/kangcheolung-`#54-search-permission-pre-filter.md:
- Line 126: 문서의 UNION 방식 설명에서 PostgreSQL의 병렬 처리나 Java Set 합집합과 동일하다는 보장성 표현을
제거하세요. 해당 문장을 단일 SQL로 접근 경로를 결합하고 결과 중복을 제거하는 방식으로만 수정하고,
existsRoleReadPermission 등 반복 호출 비교는 유지하세요.
In `@docs/design/kangcheolung-`#56-vector-search-live-check-api.md:
- Around line 461-463: 지정된 두 fenced code block에 언어 식별자를 추가하세요:
docs/design/kangcheolung-#56-vector-search-live-check-api.md의 similarityScore 수식
블록(461-463)은 text 등 적절한 언어를 사용하고,
docs/test-results/kangcheolung-#56-vector-search-live-check-api.md의 Gradle 출력
블록(474-477)은 text를 지정하세요.
- Around line 25-32: 검색 실패 기록 시점을 문서 전체에서 실제 흐름과 일치하도록 수정하세요.
docs/design/kangcheolung-#56-vector-search-live-check-api.md 25-32에서는 임베딩 실패 시
search_queries row가 없다는 점은 유지하되 로그 부재와 markFailed 적용 여부를 구분하고, 296-308에서는
createProcessing() 이후 try/catch가 실패 상태 계약의 근거임을 명시하세요. 같은 문서 476-484에서는 조기 실패에
대한 markFailed 표기를 제거하거나 실제 구현과 일치하게 수정하고,
docs/test-results/kangcheolung-#56-vector-search-live-check-api.md 466-468에서는 전체
요청이 아닌 실제 기록된 요청만 SUCCESS였다고 정정하세요.
In `@docs/test-results/kangcheolung-`#56-vector-search-live-check-api.md:
- Around line 20-24: Update every design-document Markdown link in the
referenced list so the filename’s # character is URL-encoded as %23, preserving
the existing relative paths and link targets otherwise.
- Around line 507-508: Update the final results table entries for the live check
failure and dimension mismatch scenarios to distinguish that Swagger manual
testing was not performed while automated unit tests passed. Do not mark these
scenarios as fully verified, so the table accurately reflects that fewer than
all 10 manual scenarios were completed.
---
Nitpick comments:
In
`@src/main/java/com/opensource/docgrid/domain/embedding/dto/response/EmbedServerResponse.java`:
- Line 3: Update the EmbedServerResponse record to defensively copy the vector
array both when storing it in the compact constructor and when returning it from
vector(), preserving the fixed DTO structure while preventing downstream
mutations from affecting the record’s internal data.
In
`@src/test/java/com/opensource/docgrid/domain/embedding/service/query/QueryEmbeddingServiceTest.java`:
- Around line 46-73: Update QueryEmbeddingServiceTest around embed_success to
deserialize the actual JSON contract {"vector":[...]} using the project
ObjectMapper or HTTP mock instead of constructing EmbedServerResponse directly
and mocking body(). Verify that a response without the dimension field is
successfully deserialized and processed into the expected EmbedResult, while
preserving the existing dimension-mismatch coverage.
🪄 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: 4bb30e15-8c5d-4182-a760-8fce8d7080bd
📒 Files selected for processing (10)
docs/design/kangcheolung-#35-embedding-server.mddocs/design/kangcheolung-#41-vector-search-db-infrastructure.mddocs/design/kangcheolung-#44-search-embedding-query-logging.mddocs/design/kangcheolung-#54-search-permission-pre-filter.mddocs/design/kangcheolung-#56-vector-search-live-check-api.mddocs/test-results/kangcheolung-#56-vector-search-live-check-api.mdsrc/main/java/com/opensource/docgrid/domain/embedding/dto/response/EmbedServerResponse.javasrc/main/java/com/opensource/docgrid/domain/embedding/service/query/QueryEmbeddingService.javasrc/main/java/com/opensource/docgrid/domain/search/service/SearchFacade.javasrc/test/java/com/opensource/docgrid/domain/embedding/service/query/QueryEmbeddingServiceTest.java
| grep -qxF "host all all 0.0.0.0/0 scram-sha-256" "$PGDATA/pg_hba.conf" \ | ||
| || echo "host all all 0.0.0.0/0 scram-sha-256" >> "$PGDATA/pg_hba.conf" | ||
|
|
||
| pg_ctl stop -D "$PGDATA" -m fast -w | ||
| exec postgres # PID 1을 postgres 프로세스로 교체 — exec 없으면 스크립트 종료 시 컨테이너도 종료됨 | ||
| ``` | ||
|
|
||
| ### 로컬 실행 방법 | ||
| - `pg_ctl start ... -o "-h ''"`: 초기화 작업 중엔 TCP를 안 열고 로컬 소켓으로만 안전하게 작업. | ||
| - `exec postgres`: Docker가 컨테이너를 "살아있음"으로 인식하려면 PID 1이 postgres여야 함. | ||
| - `scram-sha-256`: 초기 버전은 `trust`(비밀번호 없이 누구나 접속 가능)였다가, 비밀번호 해시 인증으로 보안 강화. | ||
|
|
||
| ### 2.5 트러블슈팅 | ||
|
|
||
| #### 재시작 시 컨테이너 크래시 | ||
|
|
||
| 증상: `su: user docgrid does not exist` 에러. | ||
| 원인: `.env`(DB_USER=docgrid)와 `vars.yml`(pg_owner: app)의 유저명 불일치. | ||
| 해결: `vars.yml`을 `.env`에 맞춰 통일. | ||
|
|
||
| #### docgrid DB 자동 생성 안 됨 | ||
|
|
||
| 원인: `vars.yml`의 `pg_databases` 목록 설정이 OpenSQL ansible 롤에서 인식 안 됨 (Docker 컨텍스트에서 해당 태스크가 스킵되는 것으로 추정). | ||
| 해결: `init-and-start.sh`에서 ansible 완료 후 직접 `CREATE DATABASE` 실행. | ||
|
|
||
| #### Spring Boot → DB 연결 실패 | ||
|
|
||
| 증상: `no pg_hba.conf entry for host "192.168.65.1"...` | ||
| 원인: Docker Desktop 브리지 게이트웨이 IP에서 오는 TCP 연결 허용 규칙 없음. | ||
| 해결: `pg_hba.conf`에 `host all all 0.0.0.0/0 scram-sha-256` 추가. | ||
|
|
||
| ### 2.6 트레이드오프 — pg_hba.conf IP 대역 | ||
|
|
||
| 현재 `0.0.0.0/0`으로 설정되어 있어 IP 대역이 넓음. 인증 방식은 `trust`에서 `scram-sha-256`으로 개선됐으나, 포트가 외부 네트워크에 노출되는 상황(공용 와이파이, 시연 환경 등)에서는 주의 필요. 시연 전에는 Docker 브리지 대역으로 좁히는 것 권장. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate docs/design filenames =="
fd '.*\.md$' docs/design 2>/dev/null | sort || true
echo
echo "== target excerpt =="
sed -n '230,310p' docs/design/kangcheolung-#35-embedding-server.md 2>/dev/null || true
echo
echo "== pg_hba occurrences =="
rg -n --hidden --glob '!build/**' --glob '!dist/**' --glob '!node_modules/**' 'pg_hba|0\.0\.0\.0/0|scram-sha-256|postgres' docs src . 2>/dev/null | head -n 200 || trueRepository: DocGrid/backend
Length of output: 21010
🌐 Web query:
PostgreSQL pg_hba.conf host 0.0.0.0/0 scram-sha-256 default match
💡 Result:
The configuration line host all all 0.0.0.0/0 scram-sha-256 in the pg_hba.conf file is a valid directive used to allow TCP/IP connections from any IPv4 address to any database as any user, requiring SCRAM-SHA-256 password authentication [1][2]. Key details regarding this configuration include: - Functionality: The 0.0.0.0/0 CIDR notation represents all IPv4 addresses [1][3]. In a pg_hba.conf entry, this tells PostgreSQL to permit connection attempts from any IPv4 client [1][2]. - Not a Default Match: There is no inherent default match in pg_hba.conf [4]. PostgreSQL processes entries in the order they appear in the file; the first record that matches the connection's type, database, user, and client address is used [2][4]. If no rule matches a connection attempt, the default behavior is to reject the connection [4]. - Security Considerations: Using 0.0.0.0/0 is highly permissive [5]. It is generally recommended to restrict access to specific IP addresses or subnets whenever possible [6][2]. - PostgreSQL Listening: Simply adding this line to pg_hba.conf is not sufficient to enable remote connectivity [5]. You must also ensure that the PostgreSQL server is configured to listen on the appropriate network interfaces (e.g., set listen_addresses = '*' in postgresql.conf) [5]. - SCRAM-SHA-256: This is a secure password-based authentication method, which is the current recommended standard for PostgreSQL [6][7]. When configuring pg_hba.conf, always remember that rule ordering is critical [2]. Specific rules (e.g., allowing a single host) should be placed before broader rules (e.g., allowing a subnet or 0.0.0.0/0) [2].
Citations:
- 1: https://www.postgresql.org/docs/current/auth-pg-hba-conf.html
- 2: https://www.stanza.dev/courses/postgresql-security/authentication/postgresql-security-pg-hba-conf
- 3: https://www.postgresql.org/docs/16/auth-pg-hba-conf.html
- 4: https://www.postgresql.org/message-id/16668.1141254061%40sss.pgh.pa.us
- 5: https://stackoverflow.com/questions/79372173/pg-hba-conf-host-all-all-0-0-0-0-0-md5-does-not-work
- 6: https://oneuptime.com/blog/post/2026-01-21-postgresql-pg-hba-authentication/view
- 7: https://github.com/postgres/postgres/blob/207cb2ab/src/backend/libpq/pg_hba.conf.sample
pg_hba.conf의 기본 허용 범위를 좁혀 주세요.
host all all 0.0.0.0/0 scram-sha-256은 SCRAM 인증을 요구하지만 모든 IPv4 연결을 허용하는 규칙입니다. 이 파일을 그대로 배포하거나 시연 환경에서 공개 네트워크에 노출되면 원치 않는 인증 시도를 그대로 받습니다. Docker 브리지 CIDR, 명시적 호스트/IP 목록, 또는 로컬 전용 설정임을 강제하는 별도 설정으로 제한해 주세요.
🤖 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-`#35-embedding-server.md around lines 264 - 296,
Update the pg_hba.conf rule in the documented initialization flow to restrict
access to the intended Docker bridge CIDR or explicitly allowed host/IP
addresses instead of 0.0.0.0/0. Keep SCRAM authentication enabled and update the
nearby troubleshooting and trade-off text to describe the narrower allowed range
without implying unrestricted IPv4 access.
| ```sql | ||
| ALTER TABLE embeddings DROP COLUMN vector; | ||
| ALTER TABLE embeddings ADD COLUMN vector vector(1024) NOT NULL; | ||
| ALTER TABLE search_queries ALTER COLUMN query_vector TYPE vector(1024) USING query_vector::vector; | ||
|
|
||
| ALTER TABLE search_queries ALTER COLUMN query_vector TYPE vector(1024) | ||
| USING query_vector::vector; | ||
|
|
||
| CREATE INDEX ON embeddings USING hnsw (vector vector_cosine_ops); | ||
| ``` | ||
|
|
||
| - `embeddings.vector`: TEXT → vector(1024) | ||
| - `search_queries.query_vector`: TEXT → vector(1024) | ||
| - HNSW 인덱스: 코사인 거리 기반 ANN 검색 가속 | ||
| 결정 사항: | ||
| - `embeddings.vector`는 개발 환경에 실 데이터 없음을 전제로 DROP/ADD 방식 사용. (`ALTER COLUMN TYPE USING`은 기존 값이 vector로 캐스팅 가능해야 하는데, TEXT 상태로는 불가) | ||
| - `search_queries.query_vector`는 nullable이라 USING 캐스팅으로 안전하게 타입만 변환. | ||
| - HNSW 인덱스: IVFFlat 대비 구축 속도 빠르고 실시간 insert에 강해서 선택. `vector_cosine_ops`는 코사인 거리(`<=>`) 연산에 최적화된 인덱스 옵션. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
fd -a '^(kangcheolung-#41-vector-search-db-infrastructure|v32|.*migration|.*flyway)' . | sed 's#^\./##' | head -200
echo "== design file excerpt =="
if [ -f docs/design/kangcheolung-#41-vector-search-db-infrastructure.md ]; then
nl -ba docs/design/kangcheolung-#41-vector-search-db-infrastructure.md | sed -n '1,180p'
fi
echo "== sql migration references to embeddings/query/vector/hnsw =="
rg -n "embeddings|query_vector|vector_cosine_ops|hnsw|V32|DROP COLUMN vector|ADD COLUMN vector|ALTER COLUMN TYPE USING" -S .Repository: DocGrid/backend
Length of output: 471
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== file sizes =="
wc -l docs/design/kangcheolung-#41-vector-search-db-infrastructure.md src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql
echo "== design file excerpt =="
cat -n docs/design/kangcheolung-#41-vector-search-db-infrastructure.md | sed -n '1,220p'
echo "== V32 migration =="
cat -n src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql
echo "== related schema/migration references =="
rg -n "Embeddings|SearchQuery|QUERY_VECTOR|QUERY_VECTOR|vector|embeddings|hnsw|vector_cosine_ops|DROP COLUMN vector|ADD COLUMN vector|ALTER COLUMN TYPE USING" src/main resources docs -S || true
echo "== deterministic pgvector-like parse simulation =="
python3 - <<'PY'
import re
samples = [
"NULL",
"[1,2,3]",
"[1.0,2.0,3.0]",
"[1,2,3]",
"[1,2,3]",
"[1,2,3]",
"[1,2,3]",
"[1,2,3]",
"[1]",
"[1,2,3,4,5,6,7,8,9,10,11,12]",
]
def dimension(s):
if s is None or s == "":
return None
m = re.search(r"^\[", s)
return bool(m)
for s in samples:
print(f"{s!r}: dimension_or_null={dimension(s)}")
PYRepository: DocGrid/backend
Length of output: 45587
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== V32 migration =="
cat -n src/main/resources/db/migration/V32__convert_vector_columns_to_pgvector.sql
echo "== deterministic behavior probe: rows affected by V32 under possible existing TEXT shapes =="
python3 - <<'PY'
import csv, io
embeddings = [
("row1", None, 1024, 'NULL'),
("row2", 1024, 1024, '[1,-2,3]'),
("row3", 768, 1024, '[1,-2,3]'),
("row4", 1024, 1024, 'invalid ['),
]
actions = []
for row in embeddings:
if row[1] is None and row[2] is None:
actions.append(row[0] + ': DROP COLUMN vector removes row 3 value')
elif row[1] is not None:
try:
value = row[3]
if not (value.startswith('[') and value.endswith(']')):
actions.append(row[0] + ': query_vector::vector raises invalid literal for ' + repr(value))
elif value == '[1,-2,3]':
actions.append(row[0] + ': CAST succeeds but vector dimension is 3, not 1024')
except Exception as e:
actions.append(row[0] + ': ' + str(e))
for a in actions:
print(a)
searchrows = sum(1 for row in embeddings if row[1] is not None)
print("search_queries affected =", searchrows)
PYRepository: DocGrid/backend
Length of output: 1013
V32 마이그레이션은 실데이터 DB에서도 실행 가능하도록 보호하세요.
embeddings.vector의 DROP/ADD는 기존 임베딩 값을 영구 삭제합니다. search_queries.query_vector::vector는 NULL이 아니라도 1024차원이 아니거나 잘못된 TEXT 형식일 때 실패해 Flyway가 중단될 수 있습니다. 환경 가정을 문서화하는 것 외에도 preflight 확인/백업·보정 또는 fresh DB 전용 실행 조건을 추가해 주세요.
🤖 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-`#41-vector-search-db-infrastructure.md around lines
22 - 35, V32 migration must be protected for production databases: add a
preflight or explicit fresh-database-only guard before changing
embeddings.vector, and preserve existing embedding data through backup or a
validated migration path instead of unconditional DROP/ADD. Before casting
search_queries.query_vector, validate that non-NULL values are valid vectors
with exactly 1024 dimensions and either correct/repair or fail with a clear
controlled message; ensure Flyway does not proceed on incompatible data.
Source: Coding guidelines
| ├─ 1. QueryEmbeddingService.embed() | ||
| │ 질문 텍스트 → 1024차원 벡터 (Python 사이드카 /embed 호출) | ||
| │ └─ 실패 시 → 로그조차 안 남고 즉시 503 (아직 search_queries row 없음) | ||
| │ | ||
| ├─ 2. User / Collection 엔티티 조회 (FK 준비) | ||
| │ | ||
| ├─ 2. SearchQueryCommandService.createProcessing() | ||
| │ search_queries INSERT (status = PROCESSING) | ||
| ├─ 3. SearchQueryCommandService.createProcessing() | ||
| │ search_queries INSERT (status = PROCESSING) ← 이때부터 로그 남기 시작 |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
검색 실패 상태의 기록 시점을 문서 전체에서 일치시켜 주세요.
createProcessing() 이전에 발생한 임베딩·사용자·컬렉션 조회 실패는 markFailed() 대상이 아니므로, 아래 설명을 실제 흐름에 맞춰 정정해야 합니다.
docs/design/kangcheolung-#56-vector-search-live-check-api.md#L25-L32: 임베딩 실패 시search_queriesrow가 없다는 점을 유지하되 “로그조차 없음”과markFailed설명을 구분해 주세요.docs/design/kangcheolung-#56-vector-search-live-check-api.md#L296-L308: PROCESSING 생성 및try/catch순서를 실패 상태 계약의 근거로 명시해 주세요.docs/design/kangcheolung-#56-vector-search-live-check-api.md#L476-L484: 조기 실패 케이스의markFailed표기를 제거하거나 구현을 변경해 주세요.docs/test-results/kangcheolung-#56-vector-search-live-check-api.md#L466-L468: 전체 요청이 아니라 실제 기록된 요청만 SUCCESS였다고 수정해 주세요.
📍 Affects 2 files
docs/design/kangcheolung-#56-vector-search-live-check-api.md#L25-L32(this comment)docs/design/kangcheolung-#56-vector-search-live-check-api.md#L296-L308docs/design/kangcheolung-#56-vector-search-live-check-api.md#L476-L484docs/test-results/kangcheolung-#56-vector-search-live-check-api.md#L466-L468
🤖 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 25
- 32, 검색 실패 기록 시점을 문서 전체에서 실제 흐름과 일치하도록 수정하세요.
docs/design/kangcheolung-#56-vector-search-live-check-api.md 25-32에서는 임베딩 실패 시
search_queries row가 없다는 점은 유지하되 로그 부재와 markFailed 적용 여부를 구분하고, 296-308에서는
createProcessing() 이후 try/catch가 실패 상태 계약의 근거임을 명시하세요. 같은 문서 476-484에서는 조기 실패에
대한 markFailed 표기를 제거하거나 실제 구현과 일치하게 수정하고,
docs/test-results/kangcheolung-#56-vector-search-live-check-api.md 466-468에서는 전체
요청이 아닌 실제 기록된 요청만 SUCCESS였다고 정정하세요.
| ``` | ||
| domain/search/service/SearchFacade.java | ||
| similarityScore = max(0, 1 - distance) | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
모든 fenced code block에 언어를 지정해 주세요.
docs/design/kangcheolung-#56-vector-search-live-check-api.md#L461-L463: 수식 블록에text등 적절한 언어를 지정해 주세요.docs/test-results/kangcheolung-#56-vector-search-live-check-api.md#L474-L477: Gradle 출력 블록에text를 지정해 주세요.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)
[warning] 461-461: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
📍 Affects 2 files
docs/design/kangcheolung-#56-vector-search-live-check-api.md#L461-L463(this comment)docs/test-results/kangcheolung-#56-vector-search-live-check-api.md#L474-L477
🤖 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
461 - 463, 지정된 두 fenced code block에 언어 식별자를 추가하세요:
docs/design/kangcheolung-#56-vector-search-live-check-api.md의 similarityScore 수식
블록(461-463)은 text 등 적절한 언어를 사용하고,
docs/test-results/kangcheolung-#56-vector-search-live-check-api.md의 Gradle 출력
블록(474-477)은 text를 지정하세요.
Source: Linters/SAST tools
…UNION 표현 수정, markFailed 정확도, 링크 URL 인코딩, 시나리오 9/10 상태 표기 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🔍️ 작업 내용
Closes #59
✨ 상세 설명
fix: EmbedServerResponse dimension 필드 제거
/embed서버 응답은{"vector": [...]}형태만 반환하는데, Java 측EmbedServerResponse에int dimension필드가 선언되어 있어 역직렬화 시 기본값0으로 채워짐0 != 1024조건이 항상 참이 되어 모든/search요청이EMBEDDING_DIMENSION_MISMATCH(500)로 실패하는 버그dimension필드 제거 후vector().length로만 차원 검증 단순화QueryEmbeddingServiceTest) 생성자 호출부 동시 수정docs: POST /search 수동 테스트 결과 문서 작성
docs/test-results/kangcheolung-#56-vector-search-live-check-api.md신규 작성./gradlew testBUILD SUCCESSFUL 결과 포함docs: 검색 블록 설계 문서 5종 상세 보강
#35— 임베딩 모델 선택 근거(기각 대안 포함), 트러블슈팅 3건, Dockerfile/main.py 코드 상세#41— VectorType 전체 코드 + equals/deepCopy 이유, 트러블슈팅 4건, seed 정비 배경#44— REQUIRES_NEW 필요 이유 상세, dimension 버그 수정 이력, 에러 케이스 테이블#54— 7-branch UNION 구조 테이블, 각 조건 의미, 성능 재검토 포인트#56— 전체 클래스 코드 + 각 줄 의미, 코사인 거리 개념, live check 시나리오, TODO🛠️ 추후 리팩토링 및 고도화 계획
SearchQueryCommandService.markFailed()REQUIRES_NEW와 미커밋 row 간 트랜잭션 상호작용 통합 테스트 검증@Transactional밖으로 분리 (DB 커넥션 점유 시간 단축)📸 스크린샷 (선택)
💬 리뷰 요구사항
EmbedServerResponse버그 수정 방향 확인 (dimension 필드 완전 제거 vs Python 서버 응답에 dimension 추가)Summary by CodeRabbit
새 기능
문서화
버그 수정