S3 벡터가 작동하는 방식: AWS의 새로운 Vector Store에 대한 친절한 가이드

발행: (2025년 12월 7일 오후 07:24 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

왜 벡터인가?

우리는 모두 AWS S3가 무엇인지 알고 있죠? 수십 년 동안 사용되어 온 잘 알려진, 저렴하고 내구성 높은 객체 스토어입니다. S3 벡터에 대해 처음 들었을 때 떠오르는 질문 몇 가지:

  • 벡터란 무엇인가?
  • 수학자만 쓰는 건가?
  • AI와는 어떤 관계가 있는가?
  • 왜 S3라는 접두사가 붙어 있는가?

아래에서 이 질문들에 답하고 S3 벡터가 어떻게 동작하는지 보여드리겠습니다.

벡터 스토어란 무엇이며 AI에 왜 필요한가?

벡터는 크기(크기)와 방향을 모두 갖는 수학적 객체로, 보통 순서가 있는 숫자 리스트로 표현됩니다. 예: ["tell"] = [0, 2, 1, 10, …, 3].
이 숫자들은 무작위가 아니라 의미를 담고 있습니다. 예를 들어 EspressoLatte는 비슷한 종류의 커피를 가리키므로 매우 유사한 벡터를 가집니다.

벡터 데이터베이스

벡터 데이터베이스(벡터 DB)는 특수한 근사 최근접 이웃(ANN) 알고리즘을 사용해 유사도 검색을 수행하도록 설계되었습니다. 관계형 데이터베이스도 유사도 검색을 할 수는 있지만, 대규모에서는 효율적이지 않습니다.

일반적인 흐름:

  1. 애플리케이션이 벡터 스토어에 질의합니다.
  2. 스토어가 가장 가까운 벡터(청크)를 찾아 반환합니다.
  3. 그 청크들을 대형 언어 모델(LLM)에 컨텍스트로 제공합니다.

예시: 챗봇 LLM이 “학생에게 적용되는 할인 혜택이 있나요?”라는 질문을 받았을 때, 벡터 DB에 관련 정보가 있으면 LLM이 해당 정보를 검색·보강·답변에 활용할 수 있습니다.

벡터 스토어는 증강 지식 베이스 역할을 하여, 비용이 많이 드는 모델 학습 없이도 임의의 정보를 주입할 수 있게 해줍니다. 이 접근법을 **검색‑증강 생성(Retrieval‑Augmented Generation, RAG)**이라고 합니다. 벡터는 텍스트, 이미지, 음악 등 임베딩 가능한 모든 것을 표현할 수 있습니다.

S3 벡터 스토어 구조

구조는 기존 S3와 유사합니다:

  • 버킷 – 리전 내에서 고유한 이름.
  • 인덱스 – 버킷 안에서 고유한 이름; 필요에 따라 구성 가능.

인덱스 구성 옵션

설정설명
Dimension각 벡터가 포함하는 숫자의 개수를 나타내는 정수값(1–4096). 예: 차원이 5이면 [1, 2, 1, 4, 5]와 같은 벡터가 생성됩니다.
Distance Metric쿼리 시 유사도를 정의하기 위해 Cosine(코사인 유사도) 또는 Euclidean(유클리드 거리) 중 선택합니다.
Encryption버킷 수준 암호화를 사용하거나 인덱스에 대해 별도로 지정할 수 있습니다. 옵션:
• SSE‑KMS (AWS KMS 키를 이용한 서버 측 암호화)
• SSE‑S3 (Amazon S3 관리 키를 이용한 서버 측 암호화)
Tagging각 벡터에 임의의 태그(예: region, category, audience)를 붙일 수 있습니다. 태그는 메타데이터 역할을 하여 순수 벡터 유사도 외에 필터링 검색을 가능하게 합니다. AWS가 자동으로 태그를 생성하거나 사용자가 직접 설정할 수 있습니다.

예시: 벡터 생성 및 조회

아래는 전체 Python 예시로,

  1. Amazon Titan embed‑text‑v2 모델을 사용해 임베딩을 생성하고,
  2. S3 벡터 인덱스에 저장하며,
  3. 태그로 필터링할 수 있는 의미 검색을 수행합니다.
import boto3
import json

region = "us-west-2"
bucket = "my-sales-bucket"
index = "my-sales-index"

bedrock = boto3.client("bedrock-runtime", region_name=region)
s3vectors = boto3.client("s3vectors", region_name=region)

# --- 1. Populate the vector index with sample sales data ---
items = [
    {
        "key": "laptop-general-sale",
        "text": "10% off all laptops this weekend in our electronics section.",
        "metadata": {"category": "laptop", "audience": "all", "discount": "10%"}
    },
    {
        "key": "laptop-student-sale",
        "text": "15% discount on lightweight laptops for students and university use.",
        "metadata": {"category": "laptop", "audience": "students", "discount": "15%"}
    },
    {
        "key": "phone-sale",
        "text": "20% off latest smartphones with long‑lasting battery.",
        "metadata": {"category": "phone", "audience": "all", "discount": "20%"}
    }
]

vectors = []
for item in items:
    resp = bedrock.invoke_model(
        modelId="amazon.titan-embed-text-v2:0",
        body=json.dumps({"inputText": item["text"]})
    )
    embedding = json.loads(resp["body"].read())["embedding"]

    vectors.append({
        "key": item["key"],
        "data": {"float32": embedding},
        "metadata": {
            "source_text": item["text"],
            **item["metadata"]
        }
    })

s3vectors.put_vectors(
    vectorBucketName=bucket,
    indexName=index,
    vectors=vectors
)

# --- 2. Query the index for "laptops for students" ---
query_text = "Do you have any sales on laptops for students?"

resp = bedrock.invoke_model(
    modelId="amazon.titan-embed-text-v2:0",
    body=json.dumps({"inputText": query_text})
)
query_embedding = json.loads(resp["body"].read())["embedding"]

# Plain semantic search
response = s3vectors.query_vectors(
    vectorBucketName=bucket,
    indexName=index,
    queryVector={"float32": query_embedding},
    topK=3,
    returnDistance=True,
    returnMetadata=True
)
print("Top matches:")
print(json.dumps(response["vectors"], indent=2))

# Optional: restrict to laptop category only
response_filtered = s3vectors.query_vectors(
    vectorBucketName=bucket,
    indexName=index,
    queryVector={"float32": query_embedding},
    topK=3,
    filter={"category": "laptop"},
    returnDistance=True,
    returnMetadata=True
)
print("Laptop‑only matches:")
print(json.dumps(response_filtered["vectors"], indent=2))

사용된 질의: “Do you have any sales on laptops for students?”

Note: Prices shown in the example are approximate. For detailed pricing, refer to the official AWS documentation.


이 가이드가 도움이 되었길 바랍니다! 직접 데이터를 가지고 실험해 보시고, 벡터 스토어가 여러분의 애플리케이션에 어떤 마법을 부릴 수 있는지 확인해 보세요. 질문이 있으면 아래 댓글에 남겨 주세요.

Back to Blog

관련 글

더 보기 »