본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 26. 08:10

장애 진단을 위한 유사도 검색 (Similarity Search)

요약

pgvector를 활용하여 과거 장애 사례를 검색하고, RAG 기술을 통해 OperationsAgent가 현재 장애를 진단하는 과정을 설명합니다. 검색 결과의 품질을 결정하는 매개변수 설정과 프롬프트 구성 전략을 다룹니다.

핵심 포인트

  • pgvector를 이용한 유사도 검색으로 과거 인시던트 데이터 활용
  • maxResults(3)와 minScore(0.75)를 통한 최적의 컨텍스트 제어
  • SAGA HISTORY와 SIMILAR INCIDENTS를 구분한 프롬프트 구조화
  • 구조화된 출력 형식을 통한 진단 결과의 데이터베이스 저장 및 파싱

장애 진단을 위한 유사도 검색 (Similarity Search)

이전 포스트에서는 모든 saga 이벤트가 pgvector로 어떻게 벡터화(vectorized)되는지 보여드렸습니다. 이제 그 데이터를 사용해 보겠습니다. saga가 실패하면, OperationsAgent는 유사한 과거의 인시던트(incidents)를 검색하여 현재의 장애를 진단하는 데 사용합니다.

검색 (The Search)

검색은 현재 장애의 텍스트 표현을 가져와 임베딩(embed)하고, pgvector에서 가장 유사한 일치 항목을 찾습니다:

private String findSimilarIncidents(String historyText) {
    var queryEmbedding = embeddingModel.embed(historyText).content();
    var results = embeddingStore.search(
...

세 가지 매개변수가 결과의 품질을 제어합니다.

maxResults(3)는 컨텍스트(context) 크기를 제한합니다. 저는 1, 3, 5, 10으로 테스트했습니다. 3개가 진단에 가장 좋은 결과를 제공했습니다. 1의 경우, LLM이 패턴을 파악할 만큼 충분한 컨텍스트를 갖지 못합니다. 5 이상의 경우, 프롬프트(prompt)가 길어져서 LLM이 분석 대신 요약을 시작하게 됩니다.

minScore(0.75)는 약한 일치 항목을 필터링합니다. pgvector에서 코사인 유사도(Cosine similarity)는 0에서 1 사이의 범위를 가집니다. 테스트를 통해 발견한 내용은 다음과 같습니다:

점수 범위의미조치
0.90+거의 동일한 장애매우 강력한 일치, 동일한 근본 원인
...

0.75가 제 데이터에서 가장 적절한 지점(sweet spot)이었습니다. 이보다 낮으면 관련 없는 장애들이 검색되어 진단을 혼란스럽게 만듭니다.

진단 프롬프트 구축 (Building the Diagnosis Prompt)

검색 결과는 현재의 장애와 함께 프롬프트에 주입됩니다:

private void diagnose(Event event, String historyText) {
    String ragContext = findSimilarIncidents(historyText);
    String prompt = """
...

프롬프트는 LLM이 작업할 수 있는 두 개의 섹션으로 구성됩니다. SAGA HISTORY는 현재의 장애이며, SIMILAR INCIDENTS는 RAG 컨텍스트입니다. LLM은 이 둘을 비교하여 패턴을 식별합니다.

RAG를 사용하는 에이전트 (The Agent That Uses RAG)

OperationsAgent는 MCP 도구를 사용하지 않습니다. 어떤 서비스에 쿼리(query)할 필요도 없습니다. 모든 데이터는 프롬프트에 미리 조립되어 전달됩니다. 에이전트의 유일한 임무는 추론(reasoning)하는 것입니다:

public interface OperationsAgent {

    @SystemMessage("""
...

구조화된 출력 형식 (Structured output format)은 매우 중요합니다. 진단 결과는 데이터베이스 테이블에 저장되고 API 엔드포인트(API endpoint)를 통해 표시됩니다. 일관된 형식은 파싱(parseable)을 가능하게 합니다.

실제 진단 사례

다음은 RAG 컨텍스트 (RAG context)가 있을 때와 없을 때 에이전트가 생성하는 결과물입니다.

RAG 미사용 시 (해당 유형의 첫 번째 장애 발생)

ROOT CAUSE: PAYMENT_SERVICE: New customer limit exceeded (R$450.00 > R$500.00)
AFFECTED SERVICES: PAYMENT_SERVICE, PRODUCT_VALIDATION_SERVICE (rolled back)
FINANCIAL IMPACT: R$450.00: payment was never processed, no financial loss
...

유용하지만 일반적입니다. 에이전트는 눈앞에 있는 정보만을 분석할 수 있습니다.

RAG 사용 시 (50회 이상의 유사 장애 발생 후)

ROOT CAUSE: PAYMENT_SERVICE: New customer limit exceeded (R$450.00 > R$500.00)
AFFECTED SERVICES: PAYMENT_SERVICE, PRODUCT_VALIDATION_SERVICE (rolled back)
FINANCIAL IMPACT: R$450.00: payment was never processed, no financial loss
...

RAG 컨텍스트는 진단 내용을 변화시킵니다. 에이전트는 패턴(저녁 시간대, 특정 금액 범위, 특정 프로필)을 식별하고 타겟팅된 권장 사항을 제공합니다.

진단 결과 저장

모든 진단 결과는 관계형 테이블 (relational table)에 저장됩니다:

diagnosticRepository.save(SagaDiagnostic.builder()
    .orderId(event.getOrderId())
    .transactionId(event.getTransactionId())
...

해당 테이블은 REST 엔드포인트 (REST endpoint)를 통해 쿼리할 수 있습니다:

@GetMapping("/diagnostics")
public List<SagaDiagnostic> getAllDiagnostics() {
    return diagnosticRepository.findAllByOrderByCreatedAtDesc();
...

이를 통해 운영 팀은 자동으로 생성된 장애 분석 피드 (feed)를 받아볼 수 있습니다. 운영 팀은 로그를 살펴보거나 여러 서비스에 걸친 이벤트를 수동으로 상관 분석 (correlate)할 필요가 없습니다.

유사도 임계값 튜닝

minScore 임계값은 가장 중요한 튜닝 파라미터 (tuning parameter)입니다. 너무 높으면 관련 컨텍스트를 놓치게 되고, 너무 낮으면 프롬프트 (prompt)가 노이즈 (noise)로 오염됩니다.

저는 0.80에서 시작했으나, 관련 장애가 존재함에도 불구하고 에이전트가 자주 "유사한 장애 사례를 찾을 수 없습니다 (No similar incidents found)"라는 결과를 내놓는 것을 발견했습니다. 이를 0.75로 낮추자 문제가 해결되었습니다. 0.75~0.79 사이의 매칭은 다소 느슨하지만, 진단을 개선하기에 충분할 만큼 관련성이 있습니다.

만약 데이터가 매우 균질하다면 (작은 변동만 있는 유사한 이벤트들), 0.85와 같이 더 높은 임계값 (threshold)이 필요할 수 있습니다. 반대로 데이터가 다양하다면 (서로 다른 장애 유형, 서로 다른 서비스), 0.70이 더 효과적일 수 있습니다.

정답은 정해져 있지 않습니다. 10~20개의 장애 사례를 시스템에 통과시켜 보고, 매칭 결과를 수동으로 확인하며, RAG 컨텍스트 (context)가 일관되게 도움이 될 때까지 조정하십시오.

다음 단계

이 시스템은 특정 시점의 진단 (point-in-time diagnosis)을 위해 작동합니다. 하지만 진정한 가치는 시간이 흐르면서 나타납니다. 다음 포스트에서는 플라이휠 효과 (flywheel effect)를 다룰 예정입니다. 즉, 각각의 새로운 Saga 이벤트가 어떻게 향후 진단을 개선하는지, SagaComposerAgent가 어떻게 동일한 벡터 스토어 (vector store)를 사용하여 Saga 실행 순서를 최적화하는지, 그리고 수천 개의 과거 장애 사례가 쌓였을 때 어떤 일이 발생하는지에 대해 설명하겠습니다.

리포지토리 (repo): github.com/pedrop3/saga-orchestration

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0