벡터·그래프·시계열 데이터베이스: 문서 검색·관계 탐색·센서 집계 기준


1장. 검색 결과가 가장 비슷하다고 정답인 것은 아니다#

고객이 다음과 같이 질문했습니다.

환불 가능 기간이 며칠인가요?

벡터 검색 결과가 다음처럼 나왔다고 하겠습니다.

순위 문서 유사도
1 2025년 환불 정책 0.92
2 2026년 환불 정책 0.88
3 배송 정책 0.31

단순히 유사도만 보면 첫 번째 문서를 선택하게 됩니다.

하지만 현재 적용되는 규정이 2026년 정책이라면 실제 답변 근거로 사용해야 하는 것은 두 번째 문서입니다.

즉:

벡터상 가장 가까운 문서
≠
업무적으로 올바른 문서

입니다.

그래프 데이터베이스에서도 비슷한 문제가 생깁니다.

두 계정이 같은 IP를 사용했습니다.

계정 A
↓
IP 1
↑
계정 B

연결은 존재합니다.

그렇다고 두 계정이 같은 사람이라는 뜻은 아닙니다.

시계열에서도 마찬가지입니다.

센서의 1시간 평균이 정상 범위라고 해도 실제 측정값의 절반이 유실됐다면 정상 상태라고 판단하기 어렵습니다.

전문 데이터베이스는 질문을 빠르게 푸는 구조를 제공합니다.

하지만 결과를 업무적으로 인정하는 기준까지 자동으로 만들어 주는 것은 아닙니다.


2장. 벡터·그래프·시계열 데이터베이스는 서로 다른 질문을 푼다#

세 가지 모델을 먼저 비교해 보겠습니다.

데이터베이스 핵심 질문 대표 접근
벡터 무엇이 의미상 비슷한가? 거리·유사도
그래프 무엇이 어떻게 연결되어 있는가? 노드·관계·경로
시계열 특정 시간 구간에서 값이 어떻게 변했는가? 시간·태그·집계

같은 데이터라고 해도 질문에 따라 적합한 구조가 달라집니다.

예를 들어 고객 문의 시스템이라면:

문의와 비슷한 FAQ 찾기
→ 벡터 검색

부정 사용 탐지라면:

계정과 IP·기기의 연결 관계 찾기
→ 그래프

공장 센서 분석이라면:

지난 1시간 평균 온도 계산
→ 시계열

이 더 자연스럽습니다.


3장. 벡터 검색은 데이터를 숫자 좌표로 표현한다#

문장이나 이미지처럼 직접적인 숫자 비교가 어려운 데이터를 임베딩 모델을 이용해 벡터로 표현할 수 있습니다.

설명을 단순하게 하기 위해 2차원 벡터를 사용해 보겠습니다.

문서 의미 벡터
A 계좌 이체 (1, 0)
B 거래 내역 (0.8, 0.6)
C 여행 예약 (0, 1)

검색 질의:

계좌 송금

도 설명을 위해:

q = (1, 0)

이라고 하겠습니다.

실제 임베딩은 수백·수천 차원을 사용할 수 있으며 각 차원을 사람이 임의로 의미 해석하는 것은 일반적으로 적절하지 않습니다.


4장. 코사인 유사도는 벡터 방향의 유사성을 본다#

코사인 유사도 공식은 다음과 같습니다.

cosine(a,b)
=
(a · b)
/
(|a| × |b|)

질의 벡터:

q = (1, 0)

문서 A:

A = (1, 0)

두 벡터가 같은 방향이므로:

cos(q,A)
=
1

입니다.


5장. 문서 B의 코사인 유사도를 계산해 보자#

문서 B:

B = (0.8, 0.6)

질의 q와 내적:

1 × 0.8
+
0 × 0.6
=
0.8

두 벡터의 크기는 모두 1이라고 하면:

cos(q,B)
=
0.8

입니다.

문서 C:

C = (0, 1)

은:

cos(q,C)
=
0

입니다.

따라서 순위는:

A
↓
B
↓
C

입니다.


6장. 유클리드 거리로 계산하면 숫자의 의미가 달라진다#

같은 벡터를 유클리드 거리로 비교해 보겠습니다.

질의와 A:

sqrt(
 (1-1)^2
+
 (0-0)^2
)
=
0

질의와 B:

sqrt(
 (1-0.8)^2
+
 (0-0.6)^2
)

=
sqrt(0.4)

≈ 0.632

질의와 C:

sqrt(
 (1-0)^2
+
 (0-1)^2
)

=
sqrt(2)

≈ 1.414

이 예에서는 순위가 같습니다.

하지만 거리 척도를 바꾸면 항상 같은 순위가 나온다고 보장할 수는 없습니다.


7장. 내적은 벡터 크기의 영향을 받을 수 있다#

코사인 유사도는 방향을 비교하기 위해 벡터 크기를 정규화해서 보는 성격이 강합니다.

내적은 벡터 크기의 영향도 받습니다.

따라서 벡터 검색 시스템에서는 다음을 확인해야 합니다.

임베딩이 정규화되어 있는가?

어떤 거리 척도를 사용하는가?

모델이 추천한 거리 함수는 무엇인가?

단순히 유사도 숫자가 크다는 사실만 보면 부족합니다.


8장. 정확 최근접 검색은 모든 벡터와 비교할 수 있다#

문서가 1,000개라면 모든 벡터와 거리를 계산해 가장 가까운 문서를 찾을 수 있습니다.

Query
↓
1번 벡터 비교
2번 벡터 비교
3번 벡터 비교
...
1000번 벡터 비교
↓
거리순 정렬

데이터가 작으면 충분히 실용적입니다.

하지만 수억 개의 벡터를 매번 모두 비교하면 비용이 커집니다.


9장. ANN은 모든 벡터를 확인하지 않고 가까운 후보를 찾는다#

ANN은 Approximate Nearest Neighbor의 약자입니다.

근사 최근접 이웃 검색입니다.

핵심은:

모든 벡터를 정확히 비교

하는 대신:

가까울 가능성이 높은 후보만 탐색

하는 것입니다.

검색 시간을 크게 줄일 수 있지만 진짜 가까운 문서를 일부 놓칠 수 있습니다.


10장. HNSW는 벡터를 탐색용 그래프로 연결한다#

HNSW는 ANN에서 널리 사용되는 대표적인 인덱스 구조입니다.

개념적으로 여러 계층의 그래프를 구성합니다.

flowchart TD
    A["상위 계층<br/>적은 노드"] --> B["중간 계층"]
    B --> C["하위 계층<br/>많은 노드"]
    C --> D["가까운 후보"]

상위 계층에서 빠르게 영역을 좁히고 아래 계층으로 내려가며 가까운 후보를 찾습니다.


11장. HNSW는 정확도·메모리·검색 시간의 교환관계를 가진다#

더 많은 후보를 탐색하면 정확한 이웃을 찾을 가능성이 커집니다.

하지만:

탐색량 증가
→ 검색 시간 증가

가 됩니다.

인덱스 구성도 더 촘촘하게 하면 검색 품질이 좋아질 수 있지만:

인덱스 메모리 증가

구축 시간 증가

가 발생할 수 있습니다.

따라서 HNSW도 단순히:

사용하면 빠르다

로 끝나는 기술이 아닙니다.


12장. IVF는 비슷한 벡터를 여러 묶음으로 나누는 접근이다#

IVF 계열은 벡터 공간을 여러 클러스터로 나눕니다.

개념적으로:

Cluster A

Cluster B

Cluster C

Cluster D

검색 질의와 가까운 클러스터를 먼저 찾고 그 안의 벡터를 집중적으로 비교합니다.

flowchart TD
    Q["Query"] --> C["가까운 Cluster 선택"]
    C --> V["Cluster 내부 벡터 검색"]
    V --> R["Top-K"]

탐색하는 클러스터 수를 늘리면 재현율은 높아질 수 있지만 검색 비용도 커집니다.


13장. ANN에서 가장 중요한 질문은 “얼마나 빨라졌는가”만이 아니다#

기존 정확 검색:

응답 시간
500ms

ANN 적용:

응답 시간
30ms

매우 빨라졌습니다.

하지만 정답 문서 100개 가운데 ANN이 60개밖에 찾지 못한다면 업무적으로 만족스럽지 않을 수 있습니다.

성능 평가에서는:

Latency

Recall

Memory

Index build time

Update cost

를 함께 봐야 합니다.


14장. recall@k는 정답 후보를 얼마나 놓쳤는지 본다#

정확 검색에서 진짜 상위 2개가:

A
B

라고 하겠습니다.

근사 검색 결과는:

A
C

입니다.

정답 2개 중 1개를 찾았습니다.

recall@2
=
1 / 2
=
50%

입니다.

이 숫자는 문서 내용의 사실성을 평가하는 것이 아닙니다.

검색 후보를 얼마나 놓쳤는지를 평가합니다.


15장. Precision과 Recall은 서로 다른 실패를 보여준다#

정답 문서가 5개 있습니다.

검색 결과는 4개입니다.

이 가운데 실제 정답은 3개였습니다.

그러면:

Precision
=
3 / 4
=
75%

입니다.

검색한 문서 중 75%가 적절했습니다.

Recall은:

Recall
=
3 / 5
=
60%

입니다.

실제 필요한 문서의 60%를 찾았습니다.


16장. 정밀도만 높고 재현율이 낮을 수도 있다#

검색 결과를 매우 엄격하게 제한한다고 하겠습니다.

실제 정답:

10개

검색:

2개

두 개가 모두 정답이면:

Precision
=
100%

입니다.

하지만:

Recall
=
2 / 10
=
20%

입니다.

틀린 문서는 거의 없지만 필요한 문서를 대부분 놓쳤습니다.


17장. 벡터 유사도는 문서의 사실성을 증명하지 않는다#

질의:

환불은 며칠 안에 가능한가?

가장 비슷한 문서가:

2025 정책
유사도 0.92

입니다.

현재 정책:

2026 정책
유사도 0.88

입니다.

유사도만 보면 오래된 정책이 앞섭니다.

따라서 실제 검색에는 다음 조건이 함께 필요할 수 있습니다.

문서 유형

유효 시작일

유효 종료일

버전

상태

18장. 메타데이터 필터는 벡터 검색만큼 중요할 수 있다#

예:

유효기간
2026-01-01 이상

status
active

language
ko

를 먼저 적용합니다.

그 안에서 벡터 검색을 수행합니다.

flowchart LR
    Q["질문"] --> F["권한·기간·유형 필터"]
    F --> V["벡터 유사도 검색"]
    V --> R["후보 문서"]

검색 후보의 품질이 크게 좋아질 수 있습니다.


19장. 권한 필터는 검색 뒤에만 두면 위험할 수 있다#

사용자 A에게 접근 권한이 없는 인사 문서가 있습니다.

벡터 검색에서 가장 높은 점수를 받았습니다.

시스템이 먼저 이 문서를 LLM에 전달한 뒤 최종 출력에서만 숨기려고 하면 이미 민감 정보가 모델 컨텍스트에 들어갔을 수 있습니다.

따라서 가능한 구조에서는 검색 단계부터 권한을 반영해야 합니다.

검색 가능 범위 결정
↓
벡터 검색
↓
허용된 후보만 사용

이 중요합니다.


20장. RAG에서도 벡터 검색 성공과 답변 성공은 다르다#

RAG 흐름을 단순화하면:

flowchart LR
    Q["질문"] --> E["Embedding"]
    E --> S["Vector Search"]
    S --> D["문서 후보"]
    D --> L["LLM"]
    L --> A["답변"]

검색 단계가 정확해도 LLM이 문서를 잘못 해석할 수 있습니다.

반대로 LLM이 좋아도 검색 단계에서 정답 문서를 놓치면 제대로 답하기 어렵습니다.

따라서 평가를 분리해야 합니다.


21장. RAG 품질은 최소 네 단계로 나눠 볼 수 있다#

검색 품질

권한 필터 품질

문서 최신성

최종 답변 근거 일치

예:

정답 문서 검색 성공
→ YES

권한 허용
→ YES

문서 최신
→ YES

답변이 문서를 잘못 해석
→ FAIL

검색 시스템 성공과 최종 답변 성공을 같은 지표로 보면 원인을 찾기 어렵습니다.


22장. 실제 평가 질문 세트를 만들어야 한다#

벡터 검색을 도입하기 전에 운영에서 자주 묻는 질문을 모읍니다.

예:

질문 정답 문서
환불 기한 POL-2026-3
기업 세금계산서 TAX-B2B-4
배송 지역 SHIP-2026-2
회원 탈퇴 MEMBER-7

각 질문에 대해 담당자가 유효한 근거 문서를 미리 정합니다.

그 뒤 인덱스와 임베딩 모델을 바꾸면서 동일한 질문으로 비교합니다.


23장. 검색 결과가 그럴듯해 보이는 것만으로 배포하면 안 된다#

다음 결과를 보면:

1위
매우 비슷한 내용

2위
비슷한 내용

3위
조금 비슷한 내용

사람이 보기에는 괜찮아 보일 수 있습니다.

하지만 정답 문서가 10위 밖에 있을 수도 있습니다.

따라서:

몇 개 샘플을 눈으로 확인

하는 것과:

정답 데이터셋을 이용해 평가

하는 것은 다릅니다.


24장. 임베딩을 바꾸면 인덱스도 다시 검토해야 한다#

기존 임베딩 모델:

dimension = 768

새 모델:

dimension = 1536

이라고 하겠습니다.

차원이 다르면 기존 벡터를 그대로 사용할 수 없습니다.

같은 차원이어도 모델의 벡터 공간 자체가 달라질 수 있습니다.

따라서 일반적으로:

문서 재임베딩

벡터 인덱스 재구축

평가 재실행

이 필요할 수 있습니다.


25장. 문서 내용이 바뀌었는데 임베딩이 그대로면 검색도 오래된 상태다#

문서 본문:

환불 기간 7일

에서:

환불 기간 14일

로 바뀌었습니다.

하지만 벡터 인덱스에는 이전 내용으로 만든 임베딩이 남아 있습니다.

그렇다면 검색 결과와 실제 문서 내용이 어긋날 수 있습니다.

따라서 벡터 시스템에서도:

document_id

version

embedding_version

updated_at

같은 메타데이터가 중요합니다.


26장. 그래프 데이터베이스는 연결 경로가 주요 질문일 때 강하다#

이제 계정 관계를 보겠습니다.

다음 데이터가 있습니다.

u1
→ IP ip1

u2
→ IP ip1

u2
→ Device phone7

u3
→ Device phone7

이를 그래프로 표현하면:

flowchart LR
    U1["u1"] --> IP["ip1"]
    U2["u2"] --> IP
    U2 --> D["phone7"]
    U3["u3"] --> D

u1과 u3는 직접 관계가 없습니다.

하지만 u2를 거치면 연결됩니다.


27장. 관계형 테이블에서도 표현 가능하지만 질문의 중심이 다르다#

관계형 DB에서도 다음 테이블로 저장할 수 있습니다.

USER_IP

USER_DEVICE

그래프 DB가 필요한 이유는 단순히 관계형 DB에서 관계를 표현할 수 없어서가 아닙니다.

질문이 반복적으로:

몇 단계 떨어져 있는가?

어떤 경로로 연결되는가?

공통 이웃은 누구인가?

어떤 관계를 따라 연결되는가?

처럼 경로 자체에 집중될 때 그래프 모델이 자연스럽습니다.


28장. 그래프의 기본 구성은 노드와 관계다#

예:

노드
User

노드
IP

관계
USED_IP

또는:

User
-[:USED_DEVICE]->
Device

처럼 표현할 수 있습니다.

관계에도 속성을 넣을 수 있습니다.

예:

first_seen

last_seen

login_count

29장. 같은 IP를 사용하는 사용자 쌍을 찾는 예#

Neo4j Cypher 형태로 다음과 같이 표현할 수 있습니다.

MATCH
    (u:User)-[:USED_IP]->(ip:IP)<-[:USED_IP]-(v:User)
WHERE u.user_id < v.user_id
RETURN
    u.user_id AS first_user,
    v.user_id AS second_user,
    ip.address AS shared_ip;

u.user_id < v.user_id 조건은:

u1, u2

u2, u1

처럼 같은 쌍이 반대로 두 번 나오는 것을 줄이기 위한 조건입니다.


30장. RETURN DISTINCT가 잘못된 관계 모델을 고쳐주지는 않는다#

쿼리 결과가 중복된다고 무조건:

RETURN DISTINCT

를 붙이면 안 됩니다.

중복 원인이:

같은 사용자들이 여러 IP를 공유

하기 때문일 수 있습니다.

질문이:

공유한 IP의 개수

인지:

공유 관계가 있는 사용자 쌍

인지에 따라 결과가 달라집니다.

DISTINCT는 의미를 먼저 정의한 뒤 사용해야 합니다.


31장. 그래프에서 가장 위험한 오해는 “연결=증거”다#

u1과 u2가 같은 IP를 사용했습니다.

그렇다고:

같은 사람

이라고 단정할 수 없습니다.

가능한 정상 상황:

회사 네트워크

학교 와이파이

가족 공유기

공공 와이파이

통신사 NAT

가 있습니다.

그래프는 관계를 발견하는 도구입니다.

업무 판단 기준은 따로 필요합니다.


32장. 관계의 시간 범위도 중요하다#

다음 두 경우를 비교하겠습니다.

경우 A#

u1
2023년 ip1 사용

u2
2026년 ip1 사용

경우 B#

u1
2026-10-01 10:00 ip1 사용

u2
2026-10-01 10:03 ip1 사용

둘 다 동일 IP 연결이지만 업무 의미는 다를 수 있습니다.

관계에 시점을 저장해야 하는 이유입니다.


33장. 그래프 탐색에서는 최대 홉 수를 정해야 한다#

사용자 u1에서 모든 연결을 무제한으로 따라간다고 하겠습니다.

u1
↓
IP
↓
다른 사용자
↓
기기
↓
다른 사용자
↓
다른 IP
...

데이터가 많으면 탐색 공간이 빠르게 커집니다.

따라서 실무에서는:

1홉

2홉

최대 3홉

처럼 제한을 두는 경우가 많습니다.


34장. 관계 종류도 제한해야 한다#

부정 사용 분석에서 필요한 관계가:

USED_IP

USED_DEVICE

라고 하겠습니다.

그런데 그래프에:

VIEWED_PRODUCT

LIKED

FOLLOWED

까지 모두 포함해 무제한 탐색하면 관계 의미가 흐려집니다.

질문에 필요한 관계 타입만 선택해야 합니다.


35장. 그래프의 경로 수와 고유 사용자 수는 다르다#

u1과 u2가 상품 A와 B를 모두 샀다고 하겠습니다.

연결 경로:

u1 → A ← u2

u1 → B ← u2

경로는 2개입니다.

하지만 연결된 상대 사용자는:

u2 한 명

입니다.

따라서:

COUNT(path)

와:

COUNT(DISTINCT user)

는 다른 질문입니다.


36장. 시계열 데이터베이스에서는 시간 자체가 핵심 인덱스 축이다#

센서 A가 온도를 기록합니다.

시각 온도
12:00 20
12:20 22
12:40 24
13:00 30

대표 질문은 다음과 같습니다.

12시부터 13시 직전까지 평균 온도는?

시간 창을:

[12:00, 13:00)

으로 정의합니다.

13:00은 포함하지 않습니다.


37장. 반개방 구간을 사용하면 시간 경계 중복을 줄일 수 있다#

첫 창:

[12:00, 13:00)

두 번째 창:

[13:00, 14:00)

이면 정확히 13:00인 측정값은 두 번째 창에만 들어갑니다.

반면 양쪽 모두 끝점을 포함하면:

[12:00, 13:00]

[13:00, 14:00]

13:00 값이 두 번 포함될 가능성이 있습니다.


38장. 12시 구간의 관측값 평균을 계산해 보자#

포함되는 값:

20

22

24

입니다.

평균:

(20 + 22 + 24) / 3
=
22

입니다.

따라서:

시간 창 건수 평균
[12:00, 13:00) 3 22
[13:00, 14:00) 1 30

입니다.


39장. 이 평균을 “1시간 평균 온도”라고 부르기 전에 수집 간격을 확인해야 한다#

센서가 원래 20분마다 한 번 측정하도록 설계되어 있다면:

12:00

12:20

12:40

세 건이 정상일 수 있습니다.

하지만 원래 1분마다 측정해야 하는 센서였다면 예정값은 60개입니다.

실제값은 3개뿐입니다.

수집률
=
3 / 60
=
5%

평균 22도만 보여주면 심각한 수집 장애를 놓칠 수 있습니다.


40장. 집계값 옆에 실제 건수를 함께 저장하면 좋다#

예:

평균
22°C

실제 관측
3

예정 관측
60

으로 저장하면:

정상 온도

와:

대량 결측

을 구분할 수 있습니다.

시계열에서는 값의 통계뿐 아니라 데이터 품질도 중요합니다.


41장. 결측을 0으로 채우면 실제 의미를 바꿀 수 있다#

관측값:

20
22
24

나머지 57개가 없습니다.

이를 모두 0으로 채우면:

0°C

라는 실제 측정이 있었던 것처럼 계산됩니다.

결측과 0은 다른 의미입니다.

따라서:

missing
≠
0

을 지켜야 합니다.


42장. 단순 평균과 시간 가중 평균도 다르다#

측정 시점이 불규칙하다고 하겠습니다.

12:00
20°C

12:05
30°C

12:55
10°C

단순 평균:

(20 + 30 + 10) / 3
=
20°C

입니다.

하지만 각 값이 얼마 동안 유지됐다고 가정할지에 따라 시간 가중 평균은 크게 달라질 수 있습니다.

따라서 센서 의미와 샘플링 방식에 따라 어떤 평균을 쓸지 정해야 합니다.


43장. 이벤트 시간과 수신 시간은 서로 다를 수 있다#

센서가 실제 측정한 시각:

12:40

네트워크 문제로 서버가 데이터를 받은 시각:

13:05

입니다.

두 시간이 있습니다.

Event Time
→ 실제 발생 시각

Ingestion Time
→ 시스템 수신 시각

어느 시간을 기준으로 집계할지 정해야 합니다.


44장. 늦게 도착한 데이터는 이미 끝난 시간 창을 바꿀 수 있다#

12시 창을 13시에 마감했다고 하겠습니다.

당시 수집값:

20
22

평균:

21

입니다.

13:05에 12:40 값 24가 늦게 도착했습니다.

새 평균은:

(20 + 22 + 24) / 3
=
22

가 됩니다.

이미 발표한 결과를 수정할지 결정해야 합니다.


45장. 지연 허용 시간을 둘 수 있다#

예를 들어:

12시 창 종료
13:00

지연 허용
10분

이라고 하겠습니다.

13:05에 도착한 12:40 데이터는 허용 범위 안입니다.

따라서 12시 집계에 포함합니다.

13:15에 도착한 데이터는 정책에 따라 별도 처리할 수 있습니다.

스트림 처리에서는 이런 개념을 워터마크와 연결해 다루기도 합니다.


46장. 늦은 데이터를 항상 수정하는 것도 정답은 아니다#

실시간 경보 시스템이 있다고 하겠습니다.

12시 평균을 이미 외부 기관에 보고했습니다.

2시간 뒤 늦은 데이터가 들어왔습니다.

과거 보고서를 자동으로 수정하면 운영상 문제가 될 수도 있습니다.

따라서 업무별로:

정정 허용

정정 금지

별도 보정 기록

정책을 정해야 합니다.


47장. 시계열의 태그는 검색에 유용하지만 너무 많으면 문제가 된다#

측정값:

temperature = 22

태그:

sensor_id = S1

region = Seoul

factory = F1

와 같이 두면:

서울 공장 F1의 센서

범위를 빠르게 찾는 데 도움이 됩니다.


48장. 요청 ID 같은 고유값을 태그로 넣으면 카디널리티가 폭증할 수 있다#

모든 HTTP 요청에:

request_id

가 각각 다릅니다.

이 값을 시계열 태그로 사용하면:

요청 1
→ 새로운 시계열

요청 2
→ 새로운 시계열

요청 3
→ 새로운 시계열
...

처럼 고유 시계열 수가 급증할 수 있습니다.

이를 높은 카디널리티 문제라고 합니다.


49장. 태그와 일반 필드의 역할을 구분해야 한다#

다음 질문을 자주 사용한다고 하겠습니다.

region=Seoul이고 service=checkout인 지난 1시간 CPU.

그렇다면:

region

service

는 필터 차원으로 적합할 수 있습니다.

반면 매번 다른:

request_id

는 별도 로그나 추적 시스템에서 관리하는 것이 더 적절할 수 있습니다.

제품 특성에 따라 설계는 달라집니다.


50장. 시계열 데이터는 오래될수록 해상도를 낮출 수 있다#

원시 센서 데이터를 1초마다 저장한다고 하겠습니다.

하루:

86,400건

센서 10,000개라면 하루 약:

864,000,000건

입니다.

장기간 그대로 보관하면 비용이 매우 커집니다.

그래서:

최근 30일
→ 원시 데이터

30일 이후
→ 1분 집계

1년 이후
→ 1시간 집계

같은 정책을 사용할 수 있습니다.


51장. 이것이 다운샘플링이다#

예를 들어 1분 동안 60개의 온도 값을:

평균
최솟값
최댓값
건수

로 압축합니다.

원본 60개 대신 집계 레코드 하나를 보관합니다.

저장 공간은 크게 줄어듭니다.

하지만 원본 한 건 단위의 세부 값은 잃을 수 있습니다.


52장. 평균만 저장하면 나중에 평균을 다시 합칠 때 오류가 생길 수 있다#

첫 번째 구간:

20
22

평균:

21

건수:

2

두 번째 구간:

30

평균:

30

건수:

1

두 평균을 단순 평균하면:

(21 + 30) / 2
=
25.5

입니다.


53장. 하지만 실제 전체 평균은 24다#

원래 세 값:

20
22
30

합:

72

건수:

3

평균:

72 / 3
=
24

입니다.

따라서 다운샘플링에서는 평균만 저장하지 말고:

sum

count

를 함께 저장하면 상위 집계를 정확하게 만들기 쉽습니다.


54장. 평균의 평균은 각 그룹 크기가 같을 때만 단순하게 계산할 수 있다#

첫 그룹 100개 평균:

10

두 번째 그룹 1개 평균:

100

단순 평균:

55

입니다.

실제 전체 평균은:

(100×10 + 1×100)
/
101

≈ 10.89

입니다.

그룹 크기가 다르면 가중치가 필요합니다.


55장. 벡터·그래프·시계열을 하나의 서비스에서 함께 사용할 수도 있다#

예를 들어 제조 서비스가 있다고 하겠습니다.

벡터#

장애 보고서와 비슷한 과거 사례 검색

그래프#

장비·부품·공급업체 관계 탐색

시계열#

센서 온도·진동·전류 분석

flowchart TD
    A["장애 분석 서비스"] --> V["Vector<br/>유사 사례"]
    A --> G["Graph<br/>부품 관계"]
    A --> T["Time Series<br/>센서 변화"]

각각 다른 질문을 해결합니다.


56장. 전문 데이터베이스를 사용한다고 원본 데이터가 없어지는 것은 아니다#

벡터 인덱스가 있다고 원본 문서를 삭제하면 곤란할 수 있습니다.

벡터는 문서 의미를 검색하기 위한 표현입니다.

최종 답변에는 원문이 필요합니다.

그래프도 관계 원천 이벤트가 있을 수 있습니다.

시계열 집계도 원본 이벤트나 일정 기간의 원시 데이터가 필요할 수 있습니다.

따라서:

원본

검색·관계·집계용 파생 데이터

를 구분하는 것이 좋습니다.


57장. 벡터 인덱스를 재구축할 수 있는지도 중요하다#

문서가 1천만 개 있다고 하겠습니다.

임베딩 모델을 교체해야 합니다.

모든 문서를 다시 임베딩하는 데:

20시간

이 걸린다고 하겠습니다.

그동안 어떤 인덱스를 서비스할지 결정해야 합니다.

기존 인덱스 유지

새 인덱스 병렬 구축

완료 후 전환

같은 배포 전략이 필요합니다.


58장. 그래프 관계도 원본에서 재구축할 수 있어야 한다#

그래프 DB의 관계가 잘못 생성됐다고 하겠습니다.

예:

u1 → phone7

가 실제로는 잘못된 관계였습니다.

관계 원천 로그나 기준 데이터가 있다면 그래프를 다시 만들 수 있습니다.

그래프 자체만 유일한 사실 저장소로 두면 오류 수정이 어려울 수 있습니다.


59장. 시계열 집계도 원시 데이터 보존 기간을 고려해야 한다#

원시 데이터 보관 기간:

30일

시간별 집계:

2년

이라고 하겠습니다.

60일 전 시간별 평균이 잘못 계산됐음을 발견했습니다.

원시 데이터가 이미 삭제됐다면 정확한 재계산이 어려울 수 있습니다.

따라서 원시 보관 기간과 재처리 요구를 함께 결정해야 합니다.


60장. 세 데이터베이스의 대표 실패를 비교하면#

유형 잘못된 결과 예 먼저 확인할 것
벡터 오래된 정책이 1위 버전·유효기간·recall
그래프 공유 IP만으로 부정 사용자 판정 관계 의미·시간·홉
시계열 평균은 정상인데 95% 데이터 누락 실제 건수·결측률
벡터 정답 문서 누락 ANN 설정·임베딩
그래프 연결 탐색 폭증 팬아웃·관계 종류·깊이
시계열 늦은 이벤트가 빠짐 이벤트 시간·지연 허용

61장. 성능만 빠르게 만드는 것이 목표가 아니다#

벡터 검색:

500ms → 30ms

그래프 탐색:

3초 → 100ms

시계열 조회:

10초 → 300ms

모두 좋아 보입니다.

하지만 결과가 잘못됐다면 의미가 없습니다.

전문 데이터베이스에서는 항상:

속도

+

결과 품질

을 함께 측정해야 합니다.


62장. 벡터 검색 체크리스트#

  1. 어떤 임베딩 모델을 사용하는가?
  2. 벡터 차원은 얼마인가?
  3. 코사인·내적·유클리드 중 무엇을 사용하는가?
  4. 임베딩을 정규화했는가?
  5. 정확 검색과 ANN 결과 차이는 어느 정도인가?
  6. recall@k를 측정했는가?
  7. 응답 시간은 얼마인가?
  8. 인덱스 메모리는 얼마인가?
  9. 문서 변경 시 임베딩도 갱신되는가?
  10. 문서 버전과 유효기간을 관리하는가?
  11. 검색 전에 권한 필터가 적용되는가?
  12. 검색 결과와 최종 생성 답변을 별도로 평가하는가?

63장. 그래프 데이터베이스 체크리스트#

  1. 노드 유형은 무엇인가?
  2. 관계 유형은 무엇인가?
  3. 방향이 중요한가?
  4. 관계 발생 시각을 저장하는가?
  5. 최대 탐색 홉 수는 얼마인가?
  6. 특정 노드의 연결 수가 지나치게 큰가?
  7. 경로 개수와 고유 대상 수를 구분하는가?
  8. 정상적인 공유 관계를 오탐하지 않는가?
  9. 관계가 곧 업무 판정이라는 잘못된 가정을 하지 않는가?
  10. 그래프를 원본 데이터에서 재생성할 수 있는가?

64장. 시계열 데이터베이스 체크리스트#

  1. 이벤트 시각과 수신 시각을 구분하는가?
  2. 시간대를 어떻게 저장하는가?
  3. 구간 경계를 [start,end) 형태로 정의했는가?
  4. 예상 수집 주기는 무엇인가?
  5. 결측률을 계산하는가?
  6. 결측을 0으로 잘못 취급하지 않는가?
  7. 지연 데이터를 얼마나 오래 기다리는가?
  8. 집계 결과를 수정할 수 있는가?
  9. 태그 카디널리티가 지나치게 크지 않은가?
  10. 원시 데이터 보존 기간은 얼마인가?
  11. 다운샘플링 해상도는 업무에 충분한가?
  12. 평균뿐 아니라 sum·count를 보존해야 하는가?

65장. 어떤 데이터베이스를 쓸지 결정하는 가장 쉬운 질문#

데이터 이름보다 질문을 먼저 적습니다.

벡터#

이 문서와 의미가 가까운 자료는 무엇인가?

그래프#

이 계정은 어떤 경로로 다른 계정과 연결되는가?

시계열#

이 장비의 지난 1시간 값은 어떻게 변했는가?

질문의 모양이 다르면 자연스러운 데이터 구조도 달라집니다.


66장. 핵심 정리#

벡터·그래프·시계열 데이터베이스는 모두 특정 질문을 빠르게 해결하기 위한 전문적인 저장·검색 구조입니다.

벡터 데이터베이스의 핵심은:

의미를 벡터로 표현
↓
거리·유사도 계산
↓
가까운 후보 검색

입니다.

하지만:

가까움
≠
사실성

가까움
≠
현재 유효한 문서

가까움
≠
접근 가능한 문서

입니다.

따라서 유사도뿐 아니라 문서 버전·유효기간·권한을 함께 관리해야 합니다.

ANN과 HNSW 같은 근사 검색은 속도를 크게 높일 수 있지만 관련 후보를 놓칠 수 있습니다.

그래서:

Latency
+
Recall@k

를 함께 평가해야 합니다.

그래프 데이터베이스에서는:

노드
+
관계
+
경로

가 핵심입니다.

같은 IP나 기기를 공유하는 사용자를 여러 단계로 탐색할 수 있지만:

연결 발견
≠
업무상 유죄·부정 판정

입니다.

관계의 종류·발생 시각·방향·탐색 깊이를 함께 봐야 합니다.

시계열 데이터베이스에서는:

시간

측정값

태그

가 중심입니다.

시간 집계에서는 단순 평균보다:

시간 창 경계

실제 관측 건수

결측

늦게 도착한 데이터

보존 기간

다운샘플링

을 함께 고려해야 합니다.

특히 평균을 다시 집계해야 한다면 평균만 저장하지 말고 합계와 건수를 보존해야 정확한 가중 평균을 계산할 수 있습니다.

세 데이터베이스 모두 공통된 원칙이 있습니다.

검색 엔진이 찾아낸 결과와 업무적으로 인정할 결과는 같은 것이 아니다.

벡터에서는 유사한 문서를 찾습니다.

그래프에서는 연결된 대상을 찾습니다.

시계열에서는 특정 시간 구간의 값을 집계합니다.

그 뒤에는 각각:

이 문서는 현재 유효한가?

이 관계는 실제 업무에서 의미가 있는가?

이 집계는 충분한 관측값을 기반으로 하는가?

라는 검증이 필요합니다.

전문 데이터베이스를 선택할 때 가장 중요한 질문은 결국 하나입니다.

내가 빠르게 답하고 싶은 질문은 정확히 어떤 형태인가?

그리고 그 뒤에는 반드시 한 가지를 더 확인해야 합니다.

빠르게 찾은 결과가 실제 업무에서도 올바른 결과라는 것을 어떻게 검증할 것인가?

이 두 질문을 함께 설계해야 벡터·그래프·시계열 데이터베이스가 단순한 최신 기술이 아니라 실제 서비스의 검색과 분석 품질을 높이는 도구가 됩니다.

이 페이지의 목차