멘탈 케어 앱을 개발하면서 사용자의 식사, 수면, 신체, 정신 건강 데이터를 분석하고 조언해 줄 RAG(검색 증강 생성) 시스템을 구축하고 있습니다. 처음에는 단순히 단계별로 기능을 붙여 나가면 성능이 좋아질 것이라 생각했습니다. 하지만 구현을 위해 깊이 공부할수록, 우리가 흔히 사용하는 벡터 데이터베이스 구조에 치명적인 함정이 있다는 것을 알게 되었습니다.
오늘 포스팅에서는 제가 처음에 구상했던 1차 고도화 전략과, 그 과정에서 발견한 문제를 해결하기 위해 진행한 2차 심화 학습(벡터 DB 필터링 이슈)의 과정을 위한 공부 및 정리를 하나로 정리해 봅니다.
1. 첫 번째 설계: RAG 성능 고도화 5단계 전략
처음 시스템을 기획할 때는 RAG의 품질을 단계적으로 높이는 로드맵을 그렸습니다. 사용자의 질문 의도를 정확히 파악하기 위해, 가장 단순한 검색부터 복잡한 추론까지 5가지 케이스로 나누어 설계했습니다.
- 'Case 1: Basic Vector Search (Baseline)' 메타데이터 필터링 없이, 사용자의 질문을 벡터로 변환하여 가장 유사한 문서를 찾는 기본 방식입니다. 성능 비교의 기준점이 됩니다.
- 'Case 2: Metadata Pre-filtering + Vector Search' 가장 핵심이라고 생각했던 단계입니다. "수면 카테고리에서만 검색해줘"처럼 SQL의 WHERE 절을 이용해 데이터를 먼저 좁히고 검색하는 방식입니다. 정확도와 속도를 모두 잡을 수 있는 정석적인 방법이라 생각했습니다.
- 'Case 3: Hybrid Search (BM25 + Vector)' 벡터 검색이 약한 고유명사나 전문 용어를 잡기 위해, 전통적인 키워드 검색(BM25)을 결합하는 방식입니다.
- 'Case 4: Re-ranking' 1차로 검색된 결과들을 Cross-Encoder 모델을 사용해 다시 정밀하게 줄 세우는 과정입니다. 정확도는 높아지지만 연산 비용이 듭니다.
- 'Case 5: Graph RAG' 단순 검색을 넘어, "스트레스가 수면 장애를 일으키고, 이것이 식욕 변화로 이어진다"는 식의 인과관계를 지식 그래프로 추론하는 최종 단계입니다.
이 설계대로라면 'Case 2'의 메타데이터 필터링이 효율성의 핵심 열쇠였습니다. 하지만 이 방식에 대해 더 깊이 파고들면서, 벡터 DB의 구조적인 문제점에 부딪히게 되었습니다.
2. 문제의 발견: "필터링을 했더니 길을 잃었다"
우리가 흔히 사용하는 대부분의 벡터 DB(PostgreSQL의 pgvector 포함)는 검색 속도를 높이기 위해 'HNSW(Hierarchical Navigable Small World)'라는 인덱스 알고리즘을 사용합니다. 이것은 데이터들이 서로 비슷한 녀석들끼리 이웃처럼 연결된 '거미줄(그래프)' 같은 구조를 하고 있습니다.
여기서 문제가 발생합니다. "SQL로 필요 없는 데이터를 먼저 다 걸러내고(Pre-filtering), 남은 것 중에서 벡터 검색을 하면 빠르고 정확하겠지?"라고 생각하기 쉽지만, HNSW 구조에서 무작정 데이터를 걸러내면 '그래프 분절(Graph Disconnection)' 현상이 일어납니다.
HNSW 분절 문제: 데이터 관점에서의 기술적 분석
① 데이터 상황 설정 사용자가 "커피를 많이 마셔서 잠이 안 와"라는 질문을 던졌다고 가정해 봅시다. 이 질문은 임베딩 모델을 통해 벡터값(숫자 배열)으로 변환되어 공간상에 위치합니다.
- '문서 A (정답)': "수면의 질을 높이려면 카페인 섭취를 줄여야 합니다." (Category: 수면)
- '문서 B (연결고리)': "커피에 든 카페인은 각성 효과가 있어 뇌를 깨웁니다." (Category: 식사/영양)
- '문서 C (오답)': "베개 높이는 경추 지지에 중요합니다." (Category: 수면)
② HNSW 그래프의 연결 구조 (필터링 전) HNSW 인덱스는 의미적으로 유사한(거리가 가까운) 벡터끼리 선(Edge)으로 연결합니다.
- 사용자의 질문("커피... 잠이 안 와")은 의미적으로 '문서 B("커피... 각성 효과")'와 가장 가깝습니다. 둘 다 '커피'와 '각성'이라는 문맥을 공유하기 때문입니다.
- '문서 B'는 다시 '문서 A("카페인 줄이기... 수면")'와 연결되어 있습니다. '카페인'이라는 공통 주제가 있기 때문입니다.
- 즉, 검색 알고리즘은 [질문] -> [문서 B] -> [문서 A] 순서로 타고 넘어가서 정답을 찾게 됩니다. 여기서 '문서 B'는 질문과 정답을 이어주는 중요한 '의미적 허브(Hub)' 역할을 합니다.
③ 필터링 적용 시 발생하는 문제 (Pre-filtering) 여기서 사용자가 "수면 카테고리에서만 찾아줘"라며 SQL 필터링(WHERE category = '수면')을 걸었다고 합시다.
- '연결고리 차단': 검색 대상에서 '식사/영양' 카테고리인 '문서 B'가 제외되어 투명 인간 취급을 받습니다.
- '그래프 단절': HNSW 알고리즘은 질문과 가장 가까운 이웃인 '문서 B'로 넘어가려 하지만, 필터 조건 때문에 접근이 불가능합니다.
- '고립': 이제 질문 벡터 주변에 남은 것은 같은 수면 카테고리인 '문서 C(베개)'뿐입니다. 하지만 '문서 C'는 질문(커피)과 의미적 거리가 너무 멉니다.
- '탐색 실패': 알고리즘은 '문서 B'라는 다리를 건너지 못했기 때문에, 그 너머에 있는 진짜 정답인 '문서 A'의 존재를 파악하지 못하고 검색을 종료하거나, 엉뚱한 '문서 C'를 결과로 내놓게 됩니다.
이처럼 벡터 공간에서는 의미적으로 긴밀하게 연결되어 있어도, 메타데이터(카테고리)가 다르면 필터링 과정에서 '중간 연결 노드'가 사라지게 됩니다. 이것이 바로 HNSW 그래프가 끊어져 정답(Recall)을 놓치게 되는 데이터적 원리입니다.
이때 데이터베이스에는 다음과 같은 3개의 문서 청크(Chunk)가 저장되어 있습니다.
이 문제를 정확히 이해하려면, 텍스트가 벡터 공간(Vector Space)에 어떻게 배치되고 HNSW가 이들을 어떻게 연결하는지 살펴봐야 합니다.
실제로 필터링 후 남은 데이터가 전체의 1% 미만일 때, 일반적인 방식은 길이 끊어져서 정답을 찾지 못할 확률이 매우 높습니다. 재현율(Recall)이 20% 이하로 급락한다는 연구 결과도 있습니다. 즉, 10개의 정답 중 8개는 길이 끊겨서 못 찾게 되는 셈입니다.
기술적 예시
'차이값(거리)이 제거된다'는 표현은 '거리를 계산할 중간 다리가 끊어진다'는 의미로 이해하시면 아주 정확합니다.
HNSW와 같은 벡터 검색 알고리즘은 '모든 데이터와의 거리를 다 계산하는 것(전수 조사)'이 아닙니다. 그랬다간 데이터가 많을 때 너무 느리니까요. 대신, '내 친구(이웃)와의 거리만 계산해서 야금야금 이동하는' 방식을 씁니다.
이 과정에서 메타데이터 필터링이 어떻게 문제를 일으키는지, [MindBudget]의 실제 상황을 예로 들어 수학적인 거리 개념을 섞어 설명해 드릴게요.
실제 사례: "스트레스와 단 음식" 검색
사용자가 "스트레스 받으면 왜 초콜릿이 당길까?"라고 검색했고, 필터 조건으로 '카테고리: 정신(Mental)'만 걸었다고 가정해 봅시다.
1. 벡터 공간의 데이터 배치 (좌표로 상상해 보세요)
설명을 돕기 위해 복잡한 1024차원 벡터를 단순한 (x, y) 좌표로 표현해 보겠습니다. 거리가 가까울수록 내용이 비슷한 겁니다.
- [Q] 질문: "스트레스 받으면 초콜릿 당김" (좌표: 10, 10)
- [A] 연결고리 문서 (Body): "코르티솔 호르몬은 식욕을 자극함" (좌표: 11, 11)
- 질문과 아주 비슷함 (거리: 1.4)
- *하지만 카테고리가 '신체(Body)'임
- [B] 정답 문서 (Mental): "정신적 불안은 당분 섭취 욕구를 높임" (좌표: 12, 12)
- 연결고리 문서와 아주 비슷함 (거리: 1.4)
- *카테고리는 '정신(Mental)'임
- [C] 엉뚱한 문서 (Mental): "정신 건강을 위한 명상법" (좌표: 50, 50)
- 질문과 전혀 다름 (거리: 56.5)
- *카테고리는 '정신(Mental)'임
2. 필터링 없을 때의 정상적인 검색 (계산 과정)
HNSW 알고리즘은 [Q] 질문 위치인 (10, 10)에 떨어집니다. 그리고 "내 근처에 누구 있어?"라고 주변을 살핍니다.
- 1단계 점프: 주변을 보니 [A] 연결고리 문서(Body)가 (11, 11)에 있습니다.
- 계산: "오, 거리가 1.4밖에 안 되네? 이쪽으로 가보자." -> [A]로 이동
- 2단계 점프: 이제 [A] 위치인 (11, 11)에서 다시 주변을 살핍니다.
- 계산: "옆에 [B] 정답 문서(Mental)가 (12, 12)에 있네? 거리 1.4로 아주 가깝군." -> [B]로 이동
- 결과: [B] 정답 문서를 찾아냈습니다!
핵심: '신체' 카테고리인 [A]가 징검다리 역할을 해서 [B]로 안내해 준 것입니다.
3. 'Pre-filtering(선 필터링)' 적용 시 발생하는 문제
이제 사용자가 "정신(Mental) 카테고리에서만 찾아줘"라고 명령했습니다. SQL이 먼저 작동해서 '신체' 카테고리인 [A] 연결고리 문서를 투명하게(검색 대상 제외) 만들어 버립니다.
- 1단계 시도: 알고리즘이 [Q] 질문 위치 (10, 10)에 떨어집니다. "내 근처에 '정신' 카테고리인 친구 있어?"라고 묻습니다.
- 계산 실패:
- 원래 가장 가까웠던 [A] (11, 11)는 필터링되어 보이지 않습니다.
- 진짜 정답인 [B] (12, 12)는 **[A]**를 거쳐야만 보이는(연결된) 위치에 있어서, [Q] 자리에서는 직접 보이지 않거나 연결선이 없습니다.
- 엉뚱한 연결: HNSW는 억지로라도 '정신' 카테고리인 이웃을 찾습니다. 그나마 멀리 희미하게 연결된 [C] 엉뚱한 문서 (50, 50)가 보입니다.
- 계산: "거리가 56.5나 되지만... 얘 말고는 갈 곳이 없네."
- 결과: 엉뚱한 [C]를 정답으로 내놓거나, "결과 없음"을 반환합니다.
4. [A] 가 없어지면 왜 [B]가 아닌 [C]가 결과로 나올까?
HNSW의 치명적 맹점: "나는 내 친구밖에 모릅니다"
많은 분들이 "벡터 DB는 모든 데이터와의 거리를 계산해서 가장 가까운 것을 찾아준다"고 오해하곤 합니다. 만약 전수 조사(Flat Index) 방식이라면 그 말이 맞습니다. 하지만 우리가 사용하는 HNSW는 속도를 위해 '전체 지도'를 보지 않는, 마치 장님 코끼리 만지기와 같은 방식을 사용합니다.
왜 바로 옆에 있는 정답을 찾지 못하고 엉뚱한 곳으로 가게 되는지, 친구 연락처에 빗대어 그 내부 메커니즘을 들여다보겠습니다.
1. 인덱스(친구 관계)가 만들어진 상황
HNSW는 데이터를 저장할 때, 효율성을 위해 모든 관계를 다 저장하지 않습니다. 나랑 가장 친한 친구 몇 명만 연락처에 저장해 두는 식입니다.
데이터가 입력될 때, HNSW는 효율을 위해 다음과 같이 관계를 연결해 두었다고 가정해 봅시다.
- [Q] 질문(좌표 10, 10): "제 연락처엔 [A]만 저장되어 있습니다. 걔가 저랑 제일 비슷하거든요." (참고: B도 가깝지만, 이미 A와 연결해 두었으므로 굳이 중복해서 B까지 저장하지 않습니다. 이것이 HNSW의 효율적인 압축 방식입니다.)
- [A] 연결고리(좌표 11, 11): "제 연락처엔 [B]가 저장되어 있습니다."
- [C] 엉뚱한 데이터(좌표 50, 50): "전 왕따인데, 어쩌다 보니 Q랑 연결된 '먼 친구' 하나입니다." (참고: HNSW는 탐색 도중 멀리 점프하기 위해, 가끔 이렇게 거리가 먼 데이터도 연결해 둡니다.)
2. 필터링 발생 (Pre-filtering)
사용자가 "수면 카테고리만 찾아줘(A는 제외해 줘)!"라고 필터 조건을 걸었습니다. 이 순간, 질문 [Q]와 가장 가까웠던 **[A]**가 필터링에 걸려 투명 인간이 되어 버립니다.
3. 검색 시작 (비극의 시작)
이제 알고리즘이 [Q] 위치에서 출발하여 탐색을 시작합니다.
- [Q]의 탐색: "자, 내 연락처(이웃 목록)를 한번 볼까?"
- 원래 목록: [A, C]
- 필터 적용 후 목록: [C] (A는 제외되어 보이지 않음)
- 알고리즘의 판단: "어라? A는 조건에 안 맞아서 갈 수가 없네. 목록에 남은 건 C뿐이야."
- 이동: 알고리즘은 울며 겨자 먹기로 아주 멀리 있는 [C]로 점프하여 이동합니다.
- [B]의 운명: 진짜 정답인 [B]는 좌표 (12, 12)라는 아주 가까운 곳에 서 있습니다. 하지만 [Q]의 연락처에는 [B]가 없습니다. [Q]는 오직 [A]를 통해서만 [B]를 소개받을 수 있었는데, 유일한 소개팅 주선자인 A가 사라져 버린 것입니다.
결론: "보이지 않으면(연결되지 않으면) 거리를 잴 기회조차 없다"
우리가 흔히 생각하는 "B가 좌표상 더 가까우니까 당연히 B가 나와야지"라는 논리는 "알고리즘이 B의 존재를 알고 있다"는 전제하에만 성립합니다.
하지만 HNSW에서는 연결된 선(Edge)이 끊어지면, 바로 옆에 정답이 있어도 그 존재 자체를 모르게 됩니다. 아예 거리 계산 후보군에 B를 올리지도 못하고 탐색이 끝나버리는 것입니다.
이것이 바로 그래프 분절의 무서움입니다. 그래서 Qdrant와 같은 최신 벡터 DB들이 필터 조건별로 "[Q]랑 [B]를 직접 연결해 주는 비상 연락망"을 미리 만들어두는 기술(Filterable HNSW)을 개발한 것입니다.
2.1 기존 방식의 딜레마: 먼저 거를까, 나중에 거를까?
벡터 DB에서 필터링을 수행하는 전통적인 방식은 크게 두 가지가 있는데, 징검다리 문제와 연결해 보면 둘 다 명확한 한계가 존재합니다.
① Pre-filtering (선 필터링, 후 검색) SQL의 WHERE 절처럼 조건을 먼저 적용해 데이터를 걸러낸 뒤, 남은 데이터 안에서 벡터 검색을 하는 방식입니다.
- '작동 방식': "수면 데이터만 남기고 다 지워!"라고 명령한 뒤, 남은 데이터끼리 유사도를 비교합니다.
- '문제점': 앞서 설명한 징검다리 문제가 바로 여기서 발생합니다. 필터링으로 인해 중간 연결 노드들이 사라지면서 HNSW 그래프가 섬처럼 조각나 버립니다. 결국 검색 알고리즘이 건너갈 다리가 끊어져 정답에 도달하지 못하게 됩니다.
② Post-filtering (선 검색, 후 필터링) 일단 벡터 유사도로 상위 N개를 뽑은 뒤, 그중에서 조건에 안 맞는 것을 버리는 방식입니다.
- '작동 방식': 일단 질문과 가장 비슷한 데이터 100개를 가져옵니다. 그 후 "여기서 수면 데이터가 아닌 건 다 빼!"라고 필터링합니다.
- '문제점': 만약 상위 100개가 전부 '식사'나 '운동' 데이터라면 어떨까요? 필터링을 거치고 나면 결과가 0개가 되어버립니다. 사용자는 분명 데이터가 있는데도 "검색 결과 없음"을 보게 되는 셈입니다.
결국 기존의 두 방식 모두 정확도(Recall) 측면에서 치명적인 약점을 가지고 있었고, 이를 해결하기 위해 2026년의 벡터 DB들은 새로운 길을 모색하게 된 것입니다.
3. 해결책: 2026년 벡터 DB 트렌드와 5가지 대안의 장단점
HNSW의 구조적 한계인 '그래프 분절'을 해결하기 위해, 각 데이터베이스는 저마다의 독창적인 방식으로 길을 연결하고 있습니다. 각 기술의 원리와 효과, 그리고 고려해야 할 단점까지 가감 없이 비교해 보겠습니다.
① Qdrant: 'Filterable HNSW' (비상 연락망 구축)
- '원리': HNSW 인덱스를 구축하는 시점부터 메타데이터를 고려합니다. 벡터의 유사성뿐만 아니라, 필터 조건별로 이동할 수 있는 '추가적인 연결 고리(Edge)'를 미리 생성해 둡니다.
- '예시 상황': [Q]의 연락처에 원래는 [A]만 있었지만, Qdrant는 "혹시 A가 차단당할 경우를 대비해, B 직통 번호도 적어두자"라며 미리 추가 연결선을 만들어 둡니다.
- '효과': 필터링으로 [A]가 사라져도, 미리 준비해 둔 [B] 직통 번호를 통해 탐색을 이어갈 수 있습니다. 필터 조건이 매우 까다로워 남은 데이터가 1% 미만이어도 95% 이상의 높은 재현율(Recall)을 유지합니다.
- '단점': 모든 필터 조건에 대해 연결 고리를 추가로 만들어야 하므로, 인덱스 용량이 커지고 메모리를 더 많이 사용합니다.
② Weaviate: 'ACORN' 알고리즘 (징검다리 허용)
- '원리': 검색 도중 필터 조건에 맞지 않는 노드를 만나면, 이를 결과 목록에는 포함시키지 않지만 다음 노드로 넘어가기 위한 '징검다리'로는 활용합니다.
- '예시 상황': 탐색 도중 조건에 안 맞는 [A]를 만났습니다. 기존 방식은 "에이, 길이 막혔네" 하고 포기하지만, ACORN은 "A는 답이 아니니까 챙기진 말자. 대신 A를 밟고 건너가서 그 뒤에 있는 B를 확인하자"라고 판단합니다.
- '효과': 필터된 노드를 단순히 삭제하는 것이 아니라 탐색 경로로 활용하기 때문에 유연성이 높습니다. 하이브리드 검색(BM25+Vector)에도 유리합니다.
- '단점': 필터 조건이 너무 강력해서 대부분의 노드가 정답이 아닌 경우(예: 100만 개 중 5개만 정답), 정답을 찾기 위해 너무 많은 징검다리를 건너뛰어야 해서 검색 속도가 느려질 수 있습니다.
③ MyScale: 'Single-stage Filtering' (MSTG 알고리즘)
- '원리': 벡터 검색과 필터링을 분리하지 않고, 하나의 수식으로 합쳐서 계산합니다. 트리를 탐색할 때 벡터 유사도 점수와 필터 일치 여부를 실시간으로 통합하여 판단합니다.
- '예시 상황': 스마트 내비게이션이 길을 찾을 때 "유료도로를 다 지우고 시작해(Pre)"라고 하지 않습니다. 대신 "이 길은 빠르지만(+100점) 유료니까 페널티(-50점)"와 같이 점수를 매겨, **"속도와 비용을 합산했을 때 가장 이득인 길"**을 한 번에 계산하며 나아갑니다.
- '효과': 그래프가 끊어질 걱정이 아예 없습니다. 특히 복잡한 SQL 조건(JOIN 등)이 섞여 있을 때도 속도 저하 없이 정확한 결과를 찾아냅니다.
- '단점': 실시간으로 필터 조건을 함께 연산해야 하므로, 검색 시 CPU 연산량이 많아져 리소스 소모가 클 수 있습니다.
④ Milvus: 'Partition Key' (방 나누기)
- '원리': 물리적인 데이터를 '파티션(Partition)' 단위로 나누어 관리합니다. 검색 시 필터 조건에 맞는 파티션만 지정해서 그래프를 탐색합니다.
- '예시 상황': 친구들을 아예 '수면 반', '식사 반'처럼 다른 교실(파티션)에 배정합니다. "수면 데이터 찾아줘" 하면 '수면 반' 교실 문만 열고 들어가서 그 안에서 짜인 친구 관계도만 봅니다. 옆 반 친구가 사라지든 말든 상관없습니다.
- '효과': 특정 카테고리 내에서만 검색할 때 그래프 분절 문제가 원천적으로 발생하지 않습니다. 대용량 데이터를 다룰 때 매우 효율적입니다.
- '단점': 여러 파티션을 넘나들며 검색해야 하는 경우(예: '수면'과 '식사' 동시 검색)에는 성능이 떨어지거나 관리가 복잡해집니다. 파티션별 데이터 불균형이 심하면 효율이 저하됩니다.
⑤ 전략적 대안: 'Flat Index' (전수 조사)
- '원리': HNSW 같은 근사 알고리즘(ANN)을 쓰지 않고, 무식하지만 확실하게 모든 데이터와 일일이 거리를 계산하는 방식입니다.
- '예시 상황': 친구 연락처를 타고 넘어가는 게 아니라, 전화번호부 책을 펴고 1번부터 끝번까지 모든 사람에게 전화를 걸어 확인합니다. "너 나랑 얼마나 친해?"
- '효과': 길 찾기 자체가 아니므로 '길이 끊어질' 일이 없습니다. 무조건 재현율(Recall) 100%를 보장합니다. 데이터가 적거나(수십만 건 이하), 필터링 후 남는 데이터가 극소수일 때 가장 빠르고 정확합니다.
- '단점': 데이터가 많아질수록 계산량이 기하급수적으로 늘어나 속도가 매우 느려집니다. 빠른 속도를 유지하려면 고가의 GPU 장비가 필요할 수 있습니다
4. 아키텍처 조합별 비교 분석
단순한 기능 구현을 넘어, 실제 운영 시의 복잡도와 비용 효율성을 따져보기 위해 총 5가지의 아키텍처 조합을 비교 분석했습니다.
조합 A: 일반 RAG (Qdrant + PostgreSQL) 가장 표준적이고 강력한 조합입니다. 관계형 데이터는 PostgreSQL이, 벡터 검색과 필터링은 Qdrant가 전담합니다.
- '구성': PostgreSQL(메타데이터, 원본) + Qdrant(벡터 저장, 필터링) + KURE v1(임베딩)
- '평가': 필터링 성능과 확장성에서 별 5점을 줄 만큼 우수합니다. 오픈소스라 비용 효율도 좋지만, 두 개의 시스템을 운영해야 하므로 복잡도는 중간 정도입니다.
조합 B: 하이브리드 검색 (Weaviate + PostgreSQL) 키워드 검색(BM25)이 중요할 때 선택하는 조합입니다.
- '구성': PostgreSQL(관계형) + Weaviate(벡터+BM25) + KURE v1(임베딩)
- '평가': 필터링과 하이브리드 검색 성능은 최상이지만, GraphQL을 익혀야 하는 러닝커브가 존재합니다.
조합 C: 단순 통합 (PostgreSQL + pgvector) 관리 포인트가 하나라는 점이 최대 강점인 조합입니다.
- '구성': PostgreSQL + pgvector(모든 기능 통합) + KURE v1(임베딩)
- '평가': 운영 복잡도가 가장 낮고 관리형 옵션이 다양해 시작하기 좋습니다. 다만 필터링 성능은 조건이 느슨할 때만 유효하며(별 3점), 확장성 면에서는 전용 DB보다 부족합니다.
조합 D: Graph RAG (Neo4j 단일) 데이터 간의 관계가 핵심일 때 사용하는 조합입니다.
- '구성': Neo4j(지식 그래프 + 벡터 통합) + PostgreSQL(선택) + KURE v1(임베딩)
- '평가': 관계 탐색과 다중 홉 추론 능력은 독보적입니다. 다만 운영 복잡도와 비용이 다소 높은 편입니다.
조합 E: 풀 하이브리드 (Qdrant + Neo4j + PostgreSQL) 모든 장점을 다 취하는 끝판왕 조합입니다.
- '구성': PostgreSQL + Qdrant(벡터) + Neo4j(그래프) + KURE v1(임베딩)
- '평가': 기능과 유연성은 최고지만, 세 개의 시스템을 동시에 운영해야 하므로 복잡도가 매우 높고 비용 부담이 큽니다.
💡 오늘의 교훈:
"RAG 한다고 무지성으로 벡터 DB 아무거나 쓰지 말자. '필터링'이 어떻게 동작하는지 모르면, 사용자는 영원히 답변을 못 받을 수도 있다."
오늘의 삽질과 공부 끝에 내린 결론은 다음과 같다.
공부한 내용을 바탕으로 'MindBudget'을 위한 DB 후보를 추렸다.
다행히 2026년 현재, 이 문제를 해결한 똑똑한 알고리즘들이 나와 있었다. 오늘 비교해 본 핵심 기술들이다.
'파이썬 및 ai 관련 지식 공부' 카테고리의 다른 글
| [비동기] 비동기 프로그래밍 완벽 가이드: 개념부터 실전 패턴까지 (Asyncio) (0) | 2026.01.14 |
|---|---|
| [LangGraph] 기초부터 멀티 에이전트까지: 실전 개발 로드맵 총정리 (3) | 2026.01.14 |
| [AI/RAG] Graph RAG 완벽 가이드: 개념부터 구현(LlamaIndex vs Custom)까지 (2) | 2026.01.06 |
| [RAG] PostgreSQL 하나로 끝내는 AI 검색: pgvector와 메타데이터 필터링 (0) | 2026.01.05 |