Study Archives/Deep Learning

Vector DB

ns4A 2026. 3. 21. 02:35

비슷한 것을 찾는 AI 시스템의 핵심 구조 이해하기

요즘 LLM이나 멀티모달 시스템을 이야기하다 보면, 어느 순간부터 꼭 따라붙는 단어가 있습니다.
바로 Vector DB입니다.

처음 들으면 이름부터 조금 낯섭니다.
데이터베이스는 알겠는데, 벡터 데이터베이스는 또 무엇일까 싶은 것이죠.
게다가 여기에 CLIP, FAISS, 임베딩, 유사도 검색, 이상 탐지 같은 단어까지 같이 나오기 시작하면 머릿속이 금방 복잡해집니다.

그런데 조금만 천천히 뜯어보면 이 흐름은 생각보다 자연스럽습니다.
결국 이 글에서 다루는 내용은 한 문장으로 정리할 수 있습니다.

“AI가 데이터를 숫자 벡터로 바꾸고, 그 벡터들 사이의 비슷함을 빠르게 찾게 만들려면 어떻게 해야 할까?”

이번 글에서는 바로 이 질문을 중심으로, Vector DB가 왜 필요한지, CLIP은 여기서 어떤 역할을 하는지, 그리고 마지막으로 이런 구조를 이용해 텍스트-이미지 검색이나 이상 상황 감지 같은 응용이 왜 가능해지는지를 처음부터 차근차근 정리해보려고 합니다. Vector DB는 여러 벡터로 이루어진 데이터베이스이며, 다차원 벡터 연산과 검색에 특화되어 있고, LLM이나 비전 모델이 만든 feature vector를 실제 애플리케이션에 활용할 때 자주 쓰입니다. 또한 CLIP은 텍스트와 이미지를 함께 이해할 수 있는 임베딩 모델로 소개되며, 이런 임베딩을 검색에 활용하는 흐름이 함께 제시됩니다.

왜 기존 데이터베이스만으로는 부족할까

기존의 관계형 데이터베이스는 굉장히 강력합니다.
예를 들어 이름, 나이, 성별, 키 같은 속성이 정리되어 있다면 “20대 남성만 골라줘” 같은 조건 검색은 아주 잘합니다.
이런 문제에서는 SQL이 매우 익숙하고 효율적인 답이 됩니다.

그런데 문제가 조금만 달라지면 이야기가 달라집니다.

예를 들어 이런 질문을 생각해볼 수 있습니다.

“이 사람과 비슷하게 생긴 사람을 찾아줘.”
“이 문장과 의미가 비슷한 문장을 찾아줘.”
“이 이미지와 분위기가 비슷한 장면을 찾아줘.”

이때는 단순한 조건 비교로는 잘 풀리지 않습니다.
나이, 키, 단어 길이처럼 명시적인 속성만으로는 “비슷함”을 표현하기 어렵기 때문입니다.
관계형 데이터베이스가 속성값 기반의 검색에는 강하지만, 의미적 유사도나 시각적 유사도처럼 더 추상적인 비교에는 곧바로 대응하기 어렵다는 점이 바로 Vector DB가 등장하는 이유입니다. 자료에서도 전통적인 테이블 구조는 “철수와 비슷하게 생긴 사람” 같은 질의를 표현하기 어렵고, 의미적으로 비슷한 문장이나 비슷한 이미지들을 찾기 위해서는 다른 방식의 표현과 검색이 필요하다고 설명합니다.

여기서 핵심은 데이터를 그냥 문자열이나 표 형태로만 두지 않고,
비슷한 것은 가까이, 다른 것은 멀리 놓일 수 있는 숫자 공간으로 옮기는 것입니다.

그 숫자 공간이 바로 벡터 공간입니다.

벡터는 무엇이고, 왜 중요한가

벡터라는 말은 사실 수학 시간에 이미 한 번 만나본 개념입니다.
방향과 크기를 가지는 값, 혹은 다차원 공간의 한 점으로 생각할 수 있습니다.
문제는 AI에서 벡터라는 말이 나올 때, 그 의미가 단순한 좌표를 넘어선다는 점입니다.

딥러닝 모델은 텍스트, 이미지, 음성 같은 복잡한 데이터를 그대로 다루기보다,
그 안에서 중요한 특징을 뽑아 숫자 배열 형태로 바꾸는 일을 자주 합니다.
이렇게 얻어진 숫자 배열이 feature vector이고, 이 벡터가 데이터의 의미를 어느 정도 압축해서 담고 있다고 볼 수 있습니다. Vector 자체는 다차원 공간의 포인트이며, 크기와 방향을 가지고 덧셈·뺄셈 연산이 가능하다고 소개됩니다. 텍스트에서는 Word2Vec 같은 방식으로, 이미지에서는 CNN을 통과시켜 얻은 feature vector 같은 방식으로 임베딩을 만들 수 있다는 설명도 이어집니다.

이 지점이 꽤 중요합니다.

예를 들어 “고양이”라는 단어, 고양이 사진, 고양이를 설명하는 문장이 각각 다른 형태의 데이터라고 해보겠습니다.
사람은 이것들이 서로 관련 있다는 것을 직관적으로 알지만, 컴퓨터는 원래 그런 감각이 없습니다.
그래서 모델은 텍스트든 이미지든 그것을 어떤 공통된 숫자 표현으로 바꾸고, 그 숫자들 사이의 거리나 방향을 비교하면서 비슷함을 학습합니다.

조금만 더 쉽게 말해보면 이렇습니다.

  • 원래 데이터: 사람이 읽고 보는 형태
  • 임베딩 벡터: 모델이 비교하기 쉬운 형태

즉, 벡터는 AI 시스템에서 일종의 공통 언어 역할을 합니다.

벡터 간의 비슷함은 어떻게 계산할까

벡터를 만들었다고 해서 끝은 아닙니다.
이제는 이 벡터들이 서로 얼마나 비슷한지를 계산해야 합니다.

가장 대표적인 방법은 세 가지 정도로 생각할 수 있습니다.

첫째는 유클리드 거리입니다.
말 그대로 두 점 사이의 직선 거리를 계산합니다.
아주 직관적이고 기본적인 방법이지만, 차원이 커질수록 해석이나 계산에서 주의할 점이 생깁니다.

둘째는 코사인 유사도입니다.
이건 두 벡터의 길이보다 방향의 유사성에 더 주목하는 방식입니다.
실제로 임베딩 기반 검색에서는 이 방법이 굉장히 자주 쓰입니다.
길이가 조금 달라도 방향이 비슷하면 비슷한 데이터라고 보는 셈입니다. 자료에서도 코사인 유사도를 가장 널리 쓰이는 유사도 계산법으로 소개하고 있습니다.

셋째는 맨해튼 거리입니다.
각 좌표 차이의 절대값을 더하는 방식인데, 특정 상황에서는 꽤 유용합니다.
다만 입문 단계에서는 유클리드 거리와 코사인 유사도만 먼저 익혀도 큰 흐름을 이해하는 데는 충분합니다.

실무적으로는 보통 이렇게 기억하면 편합니다.

“임베딩 기반 검색에서는 코사인 유사도가 자주 등장한다.”
이 정도 감각만 먼저 잡아도 이후의 CLIP, Vector DB, 검색 구조가 훨씬 덜 낯설어집니다.

그렇다면 Vector DB는 정확히 무엇을 해주는가

이제 Vector DB의 역할이 조금 보이기 시작합니다.
데이터를 벡터로 만들었고, 벡터 간 유사도도 계산할 수 있습니다.
그런데 데이터가 몇 개 안 되면 그냥 파이썬 리스트로 비교해도 되겠지만, 데이터가 수만 개, 수십만 개, 수백만 개가 되면 이야기가 달라집니다.

그 많은 벡터들 중에서 “이 쿼리와 가까운 것 몇 개만 빨리 찾아줘”를 반복해서 해야 하기 때문입니다.

바로 이때 Vector DB가 필요합니다.
Vector DB는 고차원 벡터를 효율적으로 저장하고, 유사도 기준으로 빠르게 검색할 수 있도록 설계된 데이터 저장·검색 구조입니다. 또한 벡터 간 유사도 계산, 메타데이터 필터링, sparse/dense indexing, 중복 탐지, 분류 같은 기능도 함께 지원하는 방향으로 소개됩니다.

여기서 중요한 것은 “단순 저장”이 아니라 검색 최적화입니다.

다시 말해 Vector DB는
“벡터를 그냥 쌓아두는 창고”가 아니라
“비슷한 벡터를 빨리 찾기 위해 정리된 창고”에 가깝습니다.

모든 벡터를 일일이 비교하면 왜 비효율적일까

가장 순진한 방법은 쿼리 벡터 하나가 들어왔을 때 데이터베이스 안의 모든 벡터와 전부 비교하는 것입니다.
이 방법은 정확하지만, 데이터가 커질수록 속도가 급격히 느려집니다.

그래서 실제 시스템에서는 검색을 빠르게 하기 위한 인덱싱 구조를 씁니다.
Vector DB에서 자주 언급되는 저장·검색 방식으로는 KD-tree, LSH, HNSW 같은 구조가 있습니다. KD-tree는 공간을 재귀적으로 분할하는 방식이고, LSH는 비슷한 벡터가 비슷한 해시 버킷으로 들어가도록 설계하는 방식이며, HNSW는 여러 이웃 노드 연결을 활용해 빠르게 원하는 벡터 근처로 이동하는 그래프 기반 구조입니다.

이 부분은 처음 보면 꽤 어렵습니다.
하지만 입문자 관점에서는 너무 세부 구현까지 한 번에 들어갈 필요는 없습니다.

지금 단계에서는 이렇게 이해하면 충분합니다.

  • KD-tree: 공간을 나눠가며 찾는 느낌
  • LSH: 비슷한 것끼리 비슷한 해시칸에 넣는 느낌
  • HNSW: 가까운 이웃을 따라가며 탐색하는 느낌

결국 세 방식 모두 목표는 같습니다.
모든 벡터를 다 보지 않고도, 비슷한 후보를 빠르게 찾는 것입니다.

이미지와 텍스트를 같은 방식으로 비교할 수 있을까

이제 여기서 CLIP이 등장합니다.

텍스트끼리 비슷함을 비교하는 것은 어느 정도 상상이 됩니다.
문장을 임베딩으로 바꾸고, 문장끼리 비교하면 되니까요.

그런데 텍스트와 이미지는 원래 전혀 다른 데이터입니다.
하나는 단어의 나열이고, 다른 하나는 픽셀 덩어리입니다.
그럼에도 “고양이가 아래를 보고 있다”라는 문장과 고양이 사진이 서로 가깝다고 판단하려면, 이 둘을 같은 의미 공간으로 보내줘야 합니다.

CLIP은 바로 이 문제를 해결하려는 모델입니다.
CLIP은 Contrastive Language-Image Pre-Training의 약자로, 텍스트와 이미지를 동시에 이해할 수 있는 표현 공간을 만들기 위해 설계된 모델로 소개됩니다. 텍스트 인코더와 이미지 인코더를 각각 통과시킨 뒤, 대응되는 텍스트-이미지 쌍은 가깝게, 대응되지 않는 쌍은 멀게 학습하는 contrastive pre-training 구조를 사용합니다.

이 설명을 조금 더 쉬운 말로 바꿔보겠습니다.

CLIP은
“이 문장이 이 이미지와 잘 어울리면 벡터도 가깝게,
어울리지 않으면 멀게”
학습시키는 모델입니다.

그래서 학습이 끝나고 나면,
텍스트 임베딩과 이미지 임베딩이 어느 정도 같은 공간에서 비교 가능해집니다.

이게 왜 중요하냐면,
이제부터는 텍스트로 이미지를 검색하거나, 이미지로 텍스트를 검색하는 일이 가능해지기 때문입니다.

CLIP은 내부적으로 어떻게 동작할까

CLIP의 구조 자체는 생각보다 단순한 편입니다.
텍스트를 처리하는 인코더 하나, 이미지를 처리하는 인코더 하나가 있습니다.

텍스트 쪽은 Transformer 기반 인코더를 사용하고,
이미지 쪽은 Vision Transformer 같은 구조를 통해 이미지를 패치 단위로 나누어 처리하는 방식이 제시됩니다.
최종적으로는 텍스트와 이미지가 각각 고정된 크기의 임베딩 벡터로 변환됩니다.

여기서 중요한 것은 두 인코더가 각자 데이터를 벡터로 바꾼다는 점보다,
그 벡터들이 같은 의미 공간에서 비교 가능하도록 함께 학습된다는 점입니다.

그리고 학습은 contrastive learning 방식으로 진행됩니다.
배치 안에 있는 올바른 텍스트-이미지 쌍은 positive pair가 되고, 나머지 엇갈린 조합은 negative pair가 됩니다.
학습은 positive pair의 코사인 유사도는 크게, negative pair의 유사도는 작게 만드는 방향으로 진행되며, 자료에서는 InfoNCE loss를 사용한다고 설명합니다.

이 개념은 처음 보면 조금 어렵게 느껴질 수 있습니다.
하지만 직관은 간단합니다.

“맞는 짝은 가깝게, 틀린 짝은 멀게.”

사실 이것만 이해해도 CLIP의 핵심 아이디어는 거의 잡은 셈입니다.

그래서 CLIP으로 무엇을 할 수 있을까

가장 대표적인 응용은 zero-shot 분류입니다.
예를 들어 사전에 강아지, 고양이, 새 같은 클래스를 텍스트로 준비해두고, 입력 이미지와 가장 가까운 텍스트를 고르는 방식입니다. 자료에서도 label을 텍스트로 설정한 후, 이미지와 CLIP score가 가장 높은 label을 찾는 zero-shot 테스트 구조가 소개됩니다.

이 방식이 흥미로운 이유는,
별도의 전용 분류기를 다시 학습시키지 않아도 어느 정도 분류가 가능하다는 점입니다.
즉, “a photo of a dog” 같은 텍스트 표현만 잘 준비해도 예측이 가능해지는 것이죠.

또 하나 중요한 점은 일반화 성능입니다.
CLIP은 다양한 데이터셋에서 폭넓은 성능을 보이고, distribution-shifted dataset에서도 성능 저하가 비교적 적은 편으로 제시됩니다. 다만 객체 수 세기, 복잡한 문맥 이해, 미세한 세부 분류에서는 한계가 있을 수 있다고도 설명됩니다.

이 대목은 블로그 글에서 꼭 짚고 넘어갈 필요가 있습니다.
CLIP이 강력하다고 해서 모든 멀티모달 문제를 완벽히 해결하는 것은 아닙니다.
특히 fine-grained classification이나 복잡한 reasoning이 필요한 경우에는 성능이 기대보다 떨어질 수 있습니다.
실제로는 “무엇을 잘하고 무엇을 어려워하는지”를 알고 쓰는 태도가 더 중요해 보입니다.

Vector DB와 CLIP을 같이 쓰면 무엇이 가능해질까

이제 흐름이 연결됩니다.

  1. CLIP으로 이미지와 텍스트를 임베딩 벡터로 바꾼다.
  2. 그 벡터들을 Vector DB에 저장한다.
  3. 텍스트 쿼리가 들어오면, 그 텍스트도 벡터로 바꿔서 가까운 이미지 벡터를 찾는다.

이렇게 하면 텍스트로 이미지 검색이 가능해집니다.
실제로 자료에서도 FAISS를 사용해 다양한 인덱스 구조를 구성할 수 있고, CLIP embedding과 FAISS를 연동하여 텍스트로 이미지 검색을 수행하는 흐름이 제시됩니다. 또한 OpenAI의 텍스트 임베딩도 벡터 검색에 활용할 수 있지만, 이미지 임베딩은 CLIP 같은 구조가 더 직접적이라고 설명합니다.

여기서 FAISS는 굉장히 자주 등장하는 이름입니다.
FAISS는 Facebook AI Similarity Search의 약자로, K-nearest neighbor search, 배치 처리, GPU 연산, 범위 검색, 디스크 저장 같은 기능을 제공하는 벡터 검색 라이브러리로 소개됩니다.

입문자 입장에서는 이렇게 기억하면 됩니다.

  • CLIP: 임베딩을 만든다
  • FAISS: 그 임베딩을 빠르게 찾는다

둘이 역할이 다르지만, 함께 자주 쓰이는 이유가 바로 여기에 있습니다.

FAISS는 왜 입문 단계에서 특히 많이 쓰일까

Vector DB를 이야기할 때 Pinecone, Qdrant 같은 관리형 서비스도 자주 등장하지만,
실습 단계에서는 FAISS가 훨씬 가볍고 직접적입니다.
로컬 환경에서 바로 사용할 수 있고, 벡터 검색의 기본 구조를 이해하는 데도 좋기 때문입니다. 자료에서도 Pinecone은 완전 관리형 서비스, Qdrant는 production-ready 서비스, FAISS는 로컬에서 쓸 수 있는 오픈소스 라이브러리로 소개됩니다.

특히 FAISS의 장점은 “직접 써보면서 감을 잡기 좋다”는 점입니다.
랜덤 벡터를 넣고 최근접 이웃을 찾는 것부터 시작해서,
CLIP 임베딩을 넣고 텍스트-이미지 검색으로 이어가기까지 흐름이 자연스럽습니다.

실제로 이런 과정을 밟아보면
벡터 검색이 단순히 이론이 아니라
“정말 데이터 공간에서 가까운 점을 찾는 일”이라는 감각이 생깁니다.

그리고 마지막 응용, 이상 상황 감지는 왜 가능할까

여기까지 오면 한 가지 재미있는 응용이 등장합니다.
바로 anomaly detection입니다.

아이디어는 의외로 단순합니다.
정상 데이터들이 어떤 공간에 모여 있다고 해보겠습니다.
그러면 그 근처의 벡터들은 서로 이웃이 가깝겠죠.
반대로 이상한 데이터는 정상 데이터 무리에서 떨어져 있을 가능성이 큽니다.

그래서 각 벡터마다 k개의 최근접 이웃을 찾고,
그 평균 거리가 유난히 크다면 그 벡터를 이상치로 볼 수 있습니다.
자료에서도 FAISS를 이용한 anomaly detection 아이디어로 “각 벡터와 가까운 kNN 간의 평균 거리를 계산하고, 그 값이 크다면 이웃 샘플들이 멀리 떨어져 있는 경우이므로 anomaly로 볼 수 있다”고 설명합니다. 또한 random vector, CLIP 기반 이미지 임베딩, OpenAI text embedding 기반 실험 흐름이 함께 제시됩니다.

이 아이디어가 좋은 이유는,
분류기처럼 정답 라벨을 많이 요구하지 않아도
데이터 분포만으로 이상한 샘플을 어느 정도 걸러볼 수 있다는 점입니다.

예를 들어 개 사진이 대부분인 데이터셋에 사람 사진 몇 장이 섞여 있다면,
CLIP 임베딩 공간에서 사람 사진은 개 사진 무리와 멀리 떨어질 가능성이 있습니다.
그러면 평균 최근접 거리 기준으로 이상치를 탐지할 수 있게 됩니다. 텍스트 임베딩에 대해서도 비슷한 시도가 가능하지만, 자료에서는 텍스트 anomaly detection의 경우 기대만큼 깔끔하게 분리되지 않는 한계도 함께 언급합니다.

이 부분은 꽤 실무적인 시사점을 줍니다.

벡터 기반 이상 탐지는 분명 유용하지만,
임베딩 품질이 좋지 않거나 데이터 자체가 애매하면 결과도 흔들릴 수 있습니다.
다시 말해, Vector DB가 마법처럼 정답을 주는 것이 아니라
좋은 임베딩과 적절한 기준 설정이 함께 필요하다는 뜻입니다.

이미지 삽입 제안 3

결국 이 구조는 어디에 쓰일까

이제 전체 흐름을 다시 정리해보겠습니다.

Vector DB는 유사한 벡터를 빠르게 찾기 위한 저장·검색 구조입니다.
CLIP은 텍스트와 이미지를 같은 의미 공간에서 비교할 수 있는 임베딩 모델입니다.
FAISS 같은 도구는 그 임베딩 공간에서 최근접 이웃을 빠르게 검색하게 해줍니다.
그리고 이런 조합은 텍스트-이미지 검색, 멀티모달 검색, 추천, 중복 탐지, 이상 상황 감지 같은 응용으로 이어질 수 있습니다.

조금만 더 현실적으로 말하면,
이 구조는 “무언가를 이해하는 AI”라기보다
“비슷한 것을 잘 찾아주는 AI 시스템”의 핵심이라고 보는 편이 더 정확합니다.

그리고 바로 이 능력이
검색, 추천, RAG, 멀티모달 질의응답, 모니터링 같은 시스템 전반에 매우 넓게 퍼져 있습니다.

마무리하며

처음에는 Vector DB, CLIP, FAISS 같은 단어가 서로 따로 노는 개념처럼 보일 수 있습니다.
하지만 조금만 연결해서 보면 흐름은 의외로 단순합니다.

데이터를 임베딩 벡터로 바꾸고,
그 벡터들 사이의 비슷함을 계산하고,
그 비슷함을 빠르게 검색 가능한 구조 위에 올리는 것.
이것이 이번 글의 핵심이었습니다.

결국 중요한 것은 모델 이름을 많이 외우는 일이 아니라,
“내가 해결하려는 문제가 조건 검색인지, 유사도 검색인지”를 먼저 구분하는 일 같습니다.
그 차이를 이해하기 시작하면, 왜 Vector DB가 필요하고 왜 CLIP 같은 모델이 강력한지 훨씬 자연스럽게 보일 것입니다.