Repository navigation
[REFACTOR] 그래프 조회를 영속 참조 기반 읽기 경로로 전환 - #212
Conversation
기수 문서의 contents를 읽어 요청마다 참조를 파싱하지 않고, 저장된 node와 reference 조회 결과로 응답을 조립한다. 읽기 경로에서 CrewDocumentReferenceExtractor 의존을 제거한다. DB에는 방향성 참조를 그대로 두고 API는 기존처럼 UUID가 작은 문서를 source로 둔 무방향 edge 하나만 반환한다. 자기참조 방어 제외와 중복 제거, 안정 정렬을 유지한다. 기존 테스트 fixture를 contents 링크에서 실제 참조 row로 바꾼다.
저장 방향과 무관하게 UUID 순서로 정규화한 간선이 정렬되는지 검증한다. StatementInspector로 실제 실행 SQL을 기록해 조직 미선택 조회가 node와 reference query 2개만 실행하고 select list에 contents가 없음을, 조직 선택 조회가 4개를 넘지 않음을 검증한다.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
| List<CrewGraphNodeReadModel> nodeReadModels = crewGraphQueryRepository | ||
| .findAllGraphNodesByGenerationTitle(generation); | ||
| List<DocumentReferenceReadModel> referenceReadModels = documentReferenceRepository | ||
| .findAllReadModelsByGenerationTitle(generation); |
There was a problem hiding this comment.
develop 머지 시 dev CD가 즉시 배포되는데, 현재부터는 document_reference만 조회합니다. backfill 실행 진입점이 없어 기존 데이터의 간선이 edges: []로 누락될 수 있습니다. 머지 전에 backfill을 강제하는 배포 단계나, 완료 전 legacy 경로를 유지하는 feature flag를 마련해주세요.
DocumentReferenceBackfillService는 production 호출자가 없어 배포 후에도 기존 문서의 document_reference를 채울 수단이 없었다. POST /admin/graph/document-references/backfill로 실행 진입점을 연다. /admin/** 이므로 LoginCheckInterceptor의 인증을 그대로 적용받는다. 서비스 결과는 AdminDocumentReferenceBackfillResponse로 변환해 반환한다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
develop·main 머지가 곧 배포이므로, 영속 참조 읽기 경로가 backfill보다 먼저 배포되면 그래프 API가 예외 없이 edges: []를 반환한다. graph.read.source로 읽기 경로를 고르게 해 코드 배포와 동작 전환을 분리한다. legacy는 요청 시 본문을 파싱하는 기존 경로이고 기본값이다. persisted는 저장된 document_reference를 조회하며 backfill 완주 후에만 켠다. 설정이 없으면 legacy가 선택되므로 머지와 배포만으로는 동작이 바뀌지 않는다. 두 경로가 같은 응답을 만들도록 무방향화와 자기참조 제외, 중복 제거, 안정 정렬을 CrewGraphEdgeNormalizer 하나로 공유한다. CrewGraphReader가 node와 edge를 함께 반환해 legacy가 contents를 두 번 조회하지 않게 한다. CrewGraphQueryService는 reader에 위임하고 조직 그래프 합성만 담당한다. CrewGraphReaderParityTest로 backfill 이후 두 경로의 node·edge가 같음과 backfill 이전에 영속 경로만 간선을 잃음을 고정한다. CrewGraphQueryServiceDefaultReadSourceTest로 기본값이 legacy임을 검증한다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
관련 이슈
Closes #211
변경 배경
그래프 읽기 경로가 계속
contents를 조회하고 요청마다 extractor를 실행하면 참조 영속화의 읽기 성능 이득을 얻을 수 없습니다. 저장된 node/reference 조회 결과로 기존CrewGraphResponse를 조립하도록 전환했습니다.변경 내용
findAllGraphNodesByGenerationTitle로 전환findAllReadModelsByGenerationTitle로 전환contents와CrewDocumentReferenceExtractor의존 제거읽기 경로는
CrewGraphReader전략으로 분리했고,CrewGraphQueryService는 reader에 위임하며 조직 그래프 합성만 담당합니다.이전 구현은
nodeDocumentUuids(현재 기수 노드 집합)로 target을 필터했는데,findAllReadModelsByGenerationTitle이 source·target 양쪽을 같은 기수 크루로 제한하고TYPE(target) = CrewDocument까지 거르므로 그 필터를 쿼리에 위임했습니다.리뷰 반영
배포 즉시 전환되어 기존 데이터의 간선이 누락될 수 있다는 리뷰를 반영해, feature flag와 backfill 실행 진입점을 둘 다 추가했습니다.
두 방안은 택일 관계가 아닙니다. flag는 "배포 시점 = 전환 시점"이라는 결합만 끊어줄 뿐이고, 기존 문서의
document_reference를 채우려면 backfill을 실행할 수단이 별도로 필요합니다.DocumentReferenceBackfillService는 production 호출자가 0건이었습니다.feature flag
graph.read.source로 읽기 경로를 고릅니다. 기본값은legacy입니다.legacy(기본)persisteddocument_reference조회. backfill 완주 후에만 켭니다.@ConditionalOnProperty(matchIfMissing = true)이므로 설정이 없으면 legacy가 선택됩니다. 머지와 배포만으로는 동작이 바뀌지 않습니다.두 경로가 같은 응답을 만들도록 무방향화·자기참조 제외·중복 제거·안정 정렬을
CrewGraphEdgeNormalizer하나로 공유합니다. edge 규칙이 갈라질 여지가 구조적으로 없습니다.CrewGraphReader가 node와 edge를 함께 반환하므로 legacy 경로가contents를 두 번 조회하지도 않습니다.CrewGraphReaderParityTest가 이를 고정합니다.backfill 엔드포인트
/admin/**이므로LoginCheckInterceptor인증을 그대로 적용받습니다. 응답은AdminDocumentReferenceBackfillResponse로 변환해 서비스 DTO를 노출하지 않습니다.추가·변경 파일
CrewGraphReaderContentsParsingCrewGraphReaderPersistedCrewGraphReaderCrewGraphEdgeNormalizerCrewGraphElementsAdminDocumentReferenceBackfillControllerapplication.ymlgraph.read.source: ${GRAPH_READ_SOURCE:legacy}dev-cd.yml/prod-cd.yml.envheredoc에GRAPH_READ_SOURCE추가검증
CrewGraphQueryServiceTest: 통과 (정규화·정렬 회귀 테스트 1건 추가)CrewGraphControllerTest: 통과 (JSON field, node/edge 순서 유지 확인)CrewGraphQueryRepositoryTest: 통과DocumentReferenceRepositoryTest: 통과CrewGraphQueryServiceQueryCountTest: 통과 (신규)CrewGraphReaderParityTest: 통과 (신규, 두 읽기 경로 동치성)CrewGraphQueryServiceDefaultReadSourceTest: 통과 (신규, flag 기본값)AdminDocumentReferenceBackfillControllerTest: 통과 (신규)./gradlew clean testBUILD SUCCESSFUL, tests=149 failures=0 errors=0 skipped=0git diff --check: 통과contents없음 확인: 조직 미선택 경로에서 실행된 SQL 전체에contents미포함query 수와 SQL 증거는 Hibernate
StatementInspector를 구현한 테스트 전용RecordingStatementInspector로 실제 실행 SQL을 기록해 검증했습니다. 새 dependency는 추가하지 않았고spring.jpa.properties.hibernate.session_factory.statement_inspector만 테스트 프로퍼티로 설정했습니다.영향 및 참고사항
배포 순서
flag 기본값이
legacy이므로 이 PR을 머지하고 배포해도 동작은 그대로입니다. 전환은 아래 순서로 진행합니다.POST /admin/graph/document-references/backfill실행addedCount와removedCount가 모두 0인지 확인GRAPH_READ_SOURCE=persisted설정 후 재기동운영
.env는 CD 워크플로의 heredoc에서 생성되므로GRAPH_READ_SOURCE줄을 함께 추가했습니다. Secret(PROD_GRAPH_READ_SOURCE/DEV_GRAPH_READ_SOURCE)을 만들지 않으면legacy입니다. prod는workflow_dispatch의redeploy모드로 이미지 재빌드 없이 전환과 롤백이 가능합니다.그 외
CrewGraphReadModel과 contents projection(findAllCrewDocumentsByGenerationTitle)은ContentsParsingCrewGraphReader가 계속 사용합니다. 영속 참조로 완전히 전환해 안정화 판정이 끝나면 flag와 함께 제거합니다.CrewDocumentReferenceExtractor는 쓰기 동기화에서 계속 사용하므로 삭제하지 않았습니다.findOrganizationDocument가OrganizationDocument엔티티를 통째로 로드해 select list에contents가 포함됩니다. 기존 동작이고 조직 선택 로직 유지가 요구사항이라 손대지 않았습니다. 핵심 크루 그래프 읽기 경로에는contents가 없습니다.uk_document_reference_source_target은source == target을 막지 않습니다.uk_document_reference_source_target덕에 데이터가 깨지지는 않지만 한쪽이 실패로 집계될 수 있으므로 한 번에 하나만 호출해 주세요.🤖 Generated with Claude Code