본문으로 건너뛰기

Search 서비스

개요​

Search 서비스는 OpenSearch를 활용한 상품 검색 기능을 제공합니다. Kafka를 통해 Product Catalog의 변경 이벤트를 수신하여 검색 인덱스를 자동으로 동기화하며, Secondary 리전에서는 DocumentDB 변경 스트림을 통해 데이터를 동기화합니다.

항목내용
언어Go 1.21+
프레임워크Gin
데이터베이스OpenSearch, DocumentDB (Change Stream)
캐시ElastiCache (Valkey)
네임스페이스core-services
포트8080
헬스체크/healthz, /readyz

아키텍처​

주요 기능​

1. 상품 검색​

  • 멀티 필드 검색 (이름, 설명, SKU)
  • 카테고리 필터링
  • 가격 범위 필터링
  • 페이지네이션

2. 검색 결과 캐싱​

  • Valkey를 통한 검색 결과 캐싱 (5분 TTL)
  • 캐시 키 기반 중복 쿼리 방지

3. 실시간 인덱스 동기화​

  • Kafka 이벤트를 통한 인덱스 업데이트
  • DocumentDB Change Stream을 통한 Secondary 리전 동기화

API 엔드포인트​

상품 검색​

메서드경로설명
GET/api/v1/search상품 검색

요청 파라미터​

파라미터타입필수설명기본값
qstringN검색 키워드-
categorystringN카테고리 ID-
min_pricefloatN최소 가격-
max_pricefloatN최대 가격-
pageintN페이지 번호1
sizeintN페이지 크기 (최대 100)20

요청 예시​

GET /api/v1/search?q=노트북&category=electronics&min_price=500000&max_price=2000000&page=1&size=20

응답 예시​

{
"products": [
{
"id": "prod-001",
"name": "삼성 갤럭시북 프로",
"description": "15.6인치 AMOLED 디스플레이 노트북",
"sku": "SGB-PRO-15",
"price": 1590000,
"currency": "KRW",
"category_id": "electronics",
"images": [
"https://cdn.example.com/products/sgb-pro-1.jpg"
],
"attributes": {
"brand": "Samsung",
"display_size": "15.6",
"memory": "16GB"
},
"is_active": true
}
],
"total": 42,
"page": 1,
"size": 20
}

데이터 모델​

Product (검색 인덱스)​

type Product struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
SKU string `json:"sku"`
Price float64 `json:"price"`
Currency string `json:"currency"`
CategoryID string `json:"category_id"`
Images []string `json:"images"`
Attributes map[string]string `json:"attributes"`
IsActive bool `json:"is_active"`
}

SearchParams​

type SearchParams struct {
Query string // 검색 키워드
Category string // 카테고리 필터
MinPrice *float64 // 최소 가격
MaxPrice *float64 // 최대 가격
Page int // 페이지 번호
Size int // 페이지 크기
}

SearchResult​

type SearchResult struct {
Products []Product `json:"products"`
Total int64 `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}

OpenSearch 인덱스 매핑​

{
"mappings": {
"properties": {
"id": {"type": "keyword"},
"name": {"type": "text", "analyzer": "standard"},
"description": {"type": "text", "analyzer": "standard"},
"sku": {"type": "keyword"},
"price": {"type": "float"},
"currency": {"type": "keyword"},
"category_id": {"type": "keyword"},
"is_active": {"type": "boolean"}
}
}
}

이벤트 (Kafka)​

구독하는 토픽​

토픽설명Consumer Group
catalog.product.created상품 생성 이벤트search-indexer
catalog.product.updated상품 수정 이벤트search-indexer
catalog.product.deleted상품 삭제 이벤트search-indexer

이벤트 페이로드 예시​

product.created / product.updated​

{
"event": "product.created",
"product": {
"id": "prod-001",
"name": "삼성 갤럭시북 프로",
"description": "15.6인치 AMOLED 디스플레이 노트북",
"sku": "SGB-PRO-15",
"price": 1590000,
"currency": "KRW",
"category_id": "electronics",
"images": ["https://cdn.example.com/products/sgb-pro-1.jpg"],
"attributes": {"brand": "Samsung"},
"is_active": true
}
}

product.deleted​

{
"event": "product.deleted",
"product_id": "prod-001"
}

환경 변수​

변수명설명기본값
PORT서버 포트8080
AWS_REGIONAWS 리전us-east-1
REGION_ROLE리전 역할 (PRIMARY/SECONDARY)PRIMARY
OPENSEARCH_ENDPOINTOpenSearch 엔드포인트http://localhost:9200
CACHE_HOSTElastiCache 호스트localhost
CACHE_PORTElastiCache 포트6379
KAFKA_BROKERSKafka 브로커 주소localhost:9092
DOCUMENTDB_HOSTDocumentDB 호스트 (Secondary)localhost
DOCUMENTDB_PORTDocumentDB 포트27017
LOG_LEVEL로그 레벨info

서비스 의존성​

의존하는 서비스​

서비스용도
OpenSearch검색 인덱스 저장 및 쿼리
ElastiCache (Valkey)검색 결과 캐싱
MSK (Kafka)상품 변경 이벤트 수신
DocumentDBChange Stream (Secondary 리전)

이 서비스에 의존하는 컴포넌트​

컴포넌트용도
API Gateway검색 API 라우팅
웹/모바일 클라이언트상품 검색

멀티 리전 동작​

Primary 리전 (us-east-1)​

  • Kafka 이벤트를 통해 Product Catalog 변경사항 수신
  • OpenSearch 인덱스 업데이트

Secondary 리전 (us-west-2)​

  • Kafka 이벤트 + DocumentDB Change Stream 이중 동기화
  • DocumentDB Global Cluster의 복제 데이터를 Change Stream으로 감지
  • 로컬 OpenSearch 인덱스 업데이트

캐싱 전략​

검색 결과는 Valkey에 5분간 캐싱됩니다.

캐시 키 형식​

search:{query}:{category}:{page}:{size}[:min{price}][:max{price}]

예시:

search:노트북:electronics:1:20:min500000:max2000000