임베딩 프로세스 설계와 Postgres 벡터 저장 구조
사용자가 장소(Spot)를 저장할 때,
그 장소의 설명(description) 을 OpenAI 모델로 분석하고,
핵심 키워드를 추출한 뒤 이를 벡터 임베딩(Embedding) 으로 변환하여
PostgreSQL DB에 저장하는 전체 프로세스를 설계한다.
“사용자가 저장한 장소를 시스템이 ‘이해’하는 과정”
[User Action]
↓
(1) Spot 저장 요청
↓
(2) description 텍스트 분석 (LLM)
↓
(3) 키워드 추출
↓
(4) Embedding API 호출
↓
(5) 임베딩 벡터 생성
↓
(6) PostgreSQL에 벡터 저장
gpt-4o-mini (텍스트 분석 전용)spot.description["자연", "한적함", "호수뷰", "산책", "가족여행"]
예시 프롬프트:
당신은 텍스트 요약 전문가입니다.
다음 관광지 설명에서 핵심적인 의미를 대표하는 키워드 3~8개를 추출하세요.
출력은 JSON 배열 형식으로만 반환하세요.
설명:
"맑은 호수와 산책로가 매력적인 도심 속 자연 명소입니다.
가족 단위로 방문이 많으며, 조용한 분위기 속 힐링이 가능합니다."
text-embedding-3-small예시:
{
"embedding": [0.0123, -0.0045, 0.0098, ...]
}
FLIK에서는 MariaDB가 주요 트랜잭션 DB이지만, 벡터 검색 최적화를 위해 PostgreSQL (pgvector 확장) 을 별도 구성한다.
💡 PostgreSQL의
pgvector는 OpenAI 임베딩 모델과 완벽 호환된다.
CREATE TABLE spot_embeddings (
id BIGSERIAL PRIMARY KEY,
spot_id BIGINT NOT NULL,
keywords TEXT[],
embedding VECTOR(1536),
created_at TIMESTAMP DEFAULT NOW(),
FOREIGN KEY (spot_id) REFERENCES spots(id)
);
[1] UserSavedSpotEventListener
└── spot 저장 이벤트 수신
└── LLMKeywordExtractor.extractKeywords(description)
└── ["자연", "산책", "가족여행"]
└── EmbeddingService.createEmbedding(keywords)
└── [0.0123, -0.0045, ...]
└── SpotEmbeddingRepository.save(spot_id, keywords, embedding)
@Service
@RequiredArgsConstructor
public class SpotEmbeddingService {
private final LLMKeywordExtractor llmKeywordExtractor;
private final EmbeddingClient embeddingClient;
private final SpotEmbeddingRepository spotEmbeddingRepository;
@Async
public void processEmbedding(Spot spot) {
// 1. 키워드 추출
List<String> keywords = llmKeywordExtractor.extractKeywords(spot.getDescription());
// 2. 벡터 임베딩 생성
List<Double> vector = embeddingClient.embed(String.join(" ", keywords));
// 3. PostgreSQL 저장
spotEmbeddingRepository.save(spot.getId(), keywords, vector);
}
}
@Repository
@RequiredArgsConstructor
public class SpotEmbeddingRepository {
private final JdbcTemplate jdbcTemplate;
public void save(Long spotId, List<String> keywords, List<Double> embedding) {
String sql = "INSERT INTO spot_embeddings (spot_id, keywords, embedding) VALUES (?, ?, ?)";
jdbcTemplate.update(sql, spotId, keywords.toArray(new String[0]), embedding.toArray(new Double[0]));
}
}
| 기준 | MariaDB | PostgreSQL (pgvector) |
|---|---|---|
| 트랜잭션 처리 | ✔ 우수 | ✔ 우수 |
| 벡터 유사도 검색 | ✘ 미지원 | ✔ 지원 |
| OpenAI 임베딩 호환성 | 낮음 | 매우 높음 |
| 확장성 | 높음 | 높음 |
| 운영 편의성 | 익숙함 | 다소 복잡 |
결론: 트랜잭션 로직은 MariaDB, 임베딩 및 추천 관련 연산은 PostgreSQL로 역할 분리 (CQRS-like 구조)
🔜 6편 예고: “나와 비슷한 여행자는 누구일까 — 사용자 임베딩과 추천 매칭 로직”