해당글은 실제 현업에서 개발하면서 느낀 부분을 gpt랑 질문하며 정리한 글입니다. 할루시네이션이 있을수 있음을 인지 부탁드립니다.

 

 

리액트 방식의 문제점이라고 생각하는 부분

ReAct 방식의 검증된 한계점

  • 반복 횟수 제한과 불완전한 종료
    반복 횟수(max_iterations)를 설정해도 모델이 작업 완료를 인식하지 못하면 의미 없는 중간 결과가 반환되거나, "iteration limit" 오류로 조기에 멈추는 경우가 많다. LLM이 언제 결과를 최종화해야 할지 인지하지 못한 채 계속 추가 도구를 호출하는 현상 역시 대표적 위험이다.
  • 무한 루프 및 환각(Hallucination)
    에이전트가 이미 수행된 도구 결과를 무시하고 반복하거나, 실제로 존재하지 않는 도구를 호출해 자기 내부 대화만 이어가는 현상이 발생한다. 특히 경량 또는 로컬 모델에서 이러한 루프와 환각이 심화되고, 프롬프트 해석 과정의 오류도 흔하다.
  • 토큰 비용 폭증
    Reasoning → Acting → Observation 사이클마다 전체 컨텍스트를 반복적으로 LLM에 입력해야 하므로, 단순 질의 대비 3~5배 이상 토큰을 소모한다. 서비스 환경에서는 이 비용이 빠르게 증폭된다.

슈퍼바이저 패턴의 실전 문제점

  • 컨텍스트 전파의 딜레마
    모든 메시지를 하위 에이전트에 전달하면 정보량과 비용이 급증하고, 요약하면 중요한 문맥이 손실될 뿐 아니라 추가적인 LLM 호출 비용이 발생한다. 병렬로 작동하는 에이전트들 사이에서 컨텍스트 불일치로 인해 중복 작업 또는 모순된 결과가 생길 수 있다.
  • 라우팅 정확도 저하
    에이전트가 늘어날수록 “다음에 어떤 에이전트에게 태스크를 배분”해야 할지 결정 오류가 자주 발생한다. 컨텍스트가 복잡할수록 분배와 추적 관리가 어려워지고, 계층형 슈퍼바이저 도입 시에도 복잡성과 비용이 올라간다.
  • 종료 조건의 불확실성
    슈퍼바이저가 각 작업의 완료 시점을 확실히 판단하기 어렵고, 일부 하위 에이전트의 부분 성공이나 모호한 반환이 전체 플로우의 불안정성을 유발한다.

추가로 알려진 한계

  • 도구 선택 비효율성
    활용 가능한 도구가 많아지면 최적 도구 선택 오류로 불필요한 호출이 늘어나고, 실제 서비스 단위에서 큰 비용 이슈가 된다.
  • LLM 예측 불가능성
    규칙 기반이 아니라 실시간 응답 생성으로, 결과의 정확성과 일관성을 보장하기 어렵고, 특히 자유 입력 환경에서는 이 문제가 심화된다.
  • 관찰성과 디버깅 한계
    이상 결과나 오작동 원인을 효과적으로 추적하거나 복구하는 기능이 부족하다. 버전·상태 관리도 별도 설계가 필요하다.
  • API 불안정성 대응 부족
    외부 시스템 오류, 대기 시간 지연 등 발생 시 자동 복구·재시도 로직이 부족해 운영 설계가 복잡해질 수 있다.
  • 병렬 실행 관리의 어려움
    여러 도구를 동시 호출할 때 결과 동기화, 오류 처리 복잡도가 높고, 순차 실행 기반 구조에서는 병렬화 최적화가 제한적이다.

현실적인 완화 전략

  • 프롬프트 간결화, 프롬프트 캐싱, 컨텍스트 축소 등으로 토큰 비용 절감
  • 단순 작업과 고난이도 작업을 각각 경량/고성능 모델로 분리하는 모델 캐스케이딩
  • 컨텍스트 구조화로 직전 결정만 전달하고 전체 기록은 별도 저장소로 분리하는 방식
  • 각 에이전트의 단일 책임 설계로 혼란 방지 및 효율화
  • 반복 횟수 이외 목표 달성 여부 확인, 특정 도구 호출 후 바로 종료 등 루프 방지 로직 추가
  • 세션 체크포인팅과 재개 기능을 활용해 장기 작업의 운영성과 UX 향상

도메인/예시 없이, 위와 같은 형태로 ReAct 방식 및 슈퍼바이저 에이전트 패턴의 기술적 한계와 실전 대응 전략을 정리할 수 있다.아래는 ReAct 방식 및 멀티에이전트/슈퍼바이저 패턴의 구조적 한계와 실전 이슈를 특정 분야, 제품 이름 없이 정리한 글이다.


ReAct 방식의 검증된 한계점

  • 반복 횟수를 지정해도 모델이 작업 완료를 인지하지 못하면 "중간 결과"나 "iteration limit" 오류가 발생한다. LLM이 최종 결과를 언제 생성해야 하는지 판단하지 못한 채 여러 번 도구 호출을 반복하는 경우도 흔하다.
  • 에이전트가 같은 작업을 반복하거나, 실제로 없는 도구를 호출해서 내부 루프/환각(hallucination)이 발생한다. 경량 모델이나 로컬 모델을 쓸 때 이런 현상이 더 자주 나타난다.
  • Reasoning → Acting → Observation의 반복에서 전체 컨텍스트가 계속 LLM에 전달되어 토큰 비용이 기하급수적으로 커진다. 실제 서비스 환경에서는 단순 질의 대비 3~5배까지 토큰이 발생할 수 있다.

슈퍼바이저 패턴의 실전 문제점

  • 컨텍스트 전파 딜레마로, 에이전트 간에 전체 메시지를 공유할수록 노이즈와 운영 비용이 늘고, 요약하면 중요한 정보가 누락되고 추가 LLM 호출이 필요해진다. 병렬 에이전트 간 컨텍스트 불일치 때문에 중복 작업이나 논리 충돌도 생긴다.
  • 슈퍼바이저가 관리하는 에이전트 수가 많아질수록 다음에 어떤 에이전트를 호출해야 할지 불확실성이 증가한다. 복잡한 컨텍스트에서는 분배/관리의 정확도가 급격히 저하되는 케이스가 많다.
  • 언제 작업이 완료되는지, 어떤 조건에서 플로우를 끝내야 하는지 명확히 판단하기 어렵다. 하위 에이전트가 모호한 결과를 내면 추가 결정이 불안정해진다.

추가로 널리 보고되는 문제점

  • 도구가 늘어나면 최적 선택 오류, 중복 호출 등 운영 비효율성이 심각해진다.
  • LLM은 규칙 기반 소프트웨어와 달리 결과 예측 불가능성이 높으며, 자유 입력과 동적 환경에서는 그 영향이 더욱 커진다.
  • 에이전트의 잘못된 행동이나 결정을 추적/디버깅하는 과정이 부족하다. 상태와 버전 관리 등은 별도 설계가 필요하다.
  • 외부 API가 실패하거나 지연될 때, 재시도/fallback 로직이 부족하며 전체 설계 복잡도가 늘어난다.
  • 여러 도구를 동시에 호출할 때 동기화나 실패 처리가 어려워지고, 순차 실행 기반 구조에서는 병렬 처리에 제한이 많다.

현실적 완화 전략

  • 프롬프트 간결화, 캐싱, RAG 기반 컨텍스트 관리로 토큰 비용을 절감
  • 간단 작업과 복잡 작업을 경량/고성능 모델로 분리하는 모델 캐스케이딩 적용
  • 슈퍼바이저와 하위 에이전트 간에는 이전 결정만 구조화해 전달하고, 전체 기록은 별도 저장소에 집중
  • 각 에이전트에 단일 책임만 부여하여 혼란과 비효율을 방지
  • 반복 횟수·목표 확인·특정 도구 호출 후 즉시 종료 등 명시적 루프 방지 로직 마련
  • 체크포인트 기능과 세션 복원으로 장기 작업·이탈 후 재개를 지원하고 운영성을 높임
 
 
 

 
사실 그래서 rewoo가 프로덕션에는 좀 더 낫지 않나 싶다
 
 

요구사항과 외부 API가 명확히 정의된 도메인 특화 서비스에서는 ReWOO/Plan-and-Execute 방식이 훨씬 합리적이다.

워크플로우 접근이 적합한 이유

도메인 특화성은 범용 챗봇과 달리 명확한 태스크 흐름이 존재하는 서비스의 핵심 장점이다. Anthropic의 공식 가이드도 "tasks with clearly defined workflows should use structured approaches, not open-ended agent loops"라고 명시한다.

토큰 효율성은 서비스 경제성의 생명줄로, ReWOO가 ReAct 대비 64~80% 토큰 절감과 4.4% 정확도 향상을 달성했다는 연구 결과가 있다. HotpotQA 벤치마크에서 ReWOO는 2,000 토큰으로 42.4% 정확도를 달성한 반면, ReAct는 9,795 토큰으로 40.8% 정확도를 기록했다.

통제 가능성은 지적한 대로 핵심 차별점으로, LangGraph의 명시적 그래프 구조는 "even if your LLM tries to go rogue, the graph won't allow it"라는 강제력을 제공한다. 워크플로우는 각 노드의 입출력을 테스트하고 로깅할 수 있어 프로덕션 신뢰성이 훨씬 높다.

병렬 실행은 계획된 작업의 최대 강점으로, 의존성 없는 작업들을 동시에 수행할 수 있다. ReAct는 순차 실행만 가능하지만, ReWOO는 플레이스홀더로 병렬 처리를 구현한다.

Orchestrator-Worker 패턴의 검증된 효과

슈퍼바이저 기반 아키텍처는 실제로 "separate concerns by role"이 프로덕션 안정성의 핵심이라는 Azure와 LangChain의 공식 권장사항이다. 각 전문 에이전트가 단일 책임만 수행하면 디버깅과 최적화가 명확해진다.

컨텍스트 최소화 전략은 하위 에이전트에게 전체 대화가 아닌 구조화된 상태만 전달하는 방식이다. LangGraph의 TypedDict State는 이런 구조를 강제해 "노이즈 없는 컨텍스트"를 보장한다.

계획 취합 노드는 Plan-and-Execute의 Solver 단계에 해당하며, 각 하위 에이전트의 결과를 종합해 최종 응답을 생성한다. 이 단계만 고성능 LLM을 사용하고 나머지는 경량 모델이나 확정적 함수를 쓰면 비용과 품질을 동시에 확보한다.

웰노운 워크플로우 패턴

Orchestrator-Worker Pattern은 중앙 오케스트레이터가 작업을 분해하고 전문 워커에게 배분한 뒤 결과를 취합하는 방식으로, "most useful for tasks requiring structured approach and careful planning"에 해당한다.

Prompt Chaining with Parallelization은 LangChain이 공식 제시한 첫 번째 워크플로우 패턴으로, 단계별 프롬프트를 체인으로 연결하되 독립 작업은 병렬 실행한다.

Evaluator-Optimizer Loop는 생성된 결과를 평가하고 기준 미달 시 재시도하는 패턴으로, 결과물이 제약조건을 만족하지 못하면 다시 검색하는 로직에 적용할 수 있다.

현실적인 한계 인정의 중요성

**"완벽한 답은 못 만들어도 통제 가능"**이라는 표현이 프로덕션의 본질을 정확히 짚었다. 워크플로우는 "보장된 실행 순서"를 제공하지만 각 단계의 LLM 출력 품질은 여전히 확률적이므로, 출력 검증과 fallback 로직이 필수다.

Structured Output Enforcement는 각 노드의 출력을 Pydantic 스키마로 강제해 다음 노드가 항상 예측 가능한 입력을 받도록 하는 기법으로, Anthropic과 OpenAI 공식 가이드에서 강력히 권장한다.

Explicit Planning Transparency는 사용자가 진행 상황을 볼 수 있도록 하는 것으로, 신뢰도와 UX를 동시에 향상시킨다.

구현 시 핵심 권장사항

노드별 책임 명확화는 각 노드가 하나의 도구나 하나의 판단만 수행하도록 설계하는 것으로, 각각 독립적으로 테스트하고 교체할 수 있다.

조건부 라우팅은 LangGraph의 conditional_edges로 구현하며, 상황에 맞는 경로를 선택한다. ReAct의 무한 루프 위험 없이 명확한 분기를 제공한다.

체크포인팅과 재개는 LangGraph의 핵심 기능으로, 사용자가 이탈했다가 나중에 재개할 수 있도록 지원한다.

도구 실패 처리는 ReWOO가 ReAct보다 우수한 영역으로, 계획 단계에서 이미 모든 도구 호출을 명시했으므로 실패 시 재시도나 대체 도구 선택을 체계적으로 수행할 수 있다.

제안한 아키텍처는 "명확한 요구사항 + 정의된 툴 + 전문 에이전트 + 병렬 실행 + 중앙 취합"이라는 Plan-and-Execute의 이상적 사용 케이스이며, 실제 프로덕션 배포 시 토큰 비용과 신뢰성 측면에서 ReAct보다 압도적으로 유리하다.

 
 

 

그래서 정말 리콰이어먼트가 없는 그런 에이전틱한 ai를 만들때에는 리액트 방식이 조금 나을수도 있겠으나...에이전틱ai는 리액트 방식을 넘어서 정말 ai가 발전해야하며, 대부분의 프로덕션에서 목적성이 있는 서비스는 rewoo가 낫지 않을까 싶다.

 
 

이 글은 개인적으로 공부하기 위함이여 gpt를 기반으로 작성하였으니 할루시네이션은 감안하시고 보시기 바랍니다.

 

 

사내 문서를 봇으로 만든다는 가정

 

벡터 데이터베이스 선택

사내 문서(100장, 예상 5만 벡터) 규모에 최적화된 선택입니다.

벡터DBHNSW 지원하이브리드 검색평균 레이턴시 (1M 벡터)QPS (처리량)설치 난이도추천도
Qdrant ✅ (Native) 3.5ms 1,238 쉬움 (Docker) ⭐⭐⭐⭐⭐
Milvus ✅ (Built-in) 8-12ms 890 보통 (K8s) ⭐⭐⭐⭐
pgvector ❌ (외부 구현) 7ms 280 (but 동시 처리 4.4배) 쉬움 (PostgreSQL) ⭐⭐⭐⭐
OpenSearch ✅ (Plugin) 10-15ms 500 어려움 ⭐⭐⭐
Weaviate ✅ (Alpha) 5-8ms 750 보통 ⭐⭐⭐⭐

벡터디비 검색 성능 평가 지표

 

지표 의미 병원 진단 예시 검색시스템 예시 언제 중요한가
Precision (정밀도) 내가 찾았다고 한 것 중 진짜 정답 비율 암이라고 진단한 100명 중 실제 암 환자 90명 = 90% 검색 결과 10개 중 실제 관련 문서 8개 = 80% 잘못된 결과를 보여주면 안 될 때 (의료, 법률)
Recall (재현율) 전체 정답 중 내가 찾아낸 비율 병원에 있는 실제 암 환자 50명 중 40명 발견 = 80% 데이터베이스에 있는 관련 문서 20개 중 12개 검색 = 60% 놓치면 안 되는 정보가 있을 때 (보안, 법규 준수)
F1 Score Precision과 Recall의 조화평균 두 값이 모두 높아야 높은 점수 균형 잡힌 검색 성능 둘 다 중요할 때 (일반적인 검색)
Recall@K 상위 K개 결과에서의 재현율 처음 본 환자 10명 중 발견률 첫 페이지(상위 10개)에 답이 몇 개? 사용자는 첫 페이지만 본다
NDCG@10 순위까지 고려한 품질 중요한 환자를 먼저 진단했는가 가장 관련 높은 문서가 1등인가 순위가 중요할 때

실무 팁: 사내 문서 Q&A 봇은 Recall@10이 가장 중요합니다. 개발자가 질문했을 때 상위 10개 안에 답이 없으면 신뢰를 잃기 때문입니다. Precision은 80% 이상, Recall@10은 90% 이상을 목표로 설정하세요.

Precision vs Recall 트레이드오프

이 둘은 시소 관계입니다. 검색 결과를 많이 보여주면 Recall은 올라가지만(놓치는 게 없음) Precision은 떨어집니다(쓸데없는 것도 섞임). 반대로 확실한 것만 보여주면 Precision은 올라가지만 Recall이 떨어집니다.

text
예시: "Spring Boot 설정 방법" 검색
   - 엄격한 기준 (similarity > 0.9): 2개 반환, 2개 정답 → Precision 100%, Recall 20%
   - 느슨한 기준 (similarity > 0.7): 15개 반환, 10개 정답 → Precision 67%, Recall 100%
   - 적절한 기준 (similarity > 0.8): 8개 반환, 8개 정답 → Precision 100%, Recall 80% ✅

 

 

문맥 vs 단어: 검색 방식 선택

검색 방식은 크게 두 가지로 나뉩니다. 실무에서는 **둘 다 사용(하이브리드)**하는 것이 정답입니다.

구분Lexical Search (단어 기반)Semantic Search (문맥 기반)Hybrid Search (하이브리드)
원리 단어가 정확히 일치하는지 검색 의미가 비슷한지 검색 둘 다 사용해서 결합
알고리즘 BM25, TF-IDF Dense Vector Embedding BM25 + Vector + RRF
장점 빠름 (ms 단위), 정확한 용어 검색 동의어/유의어 이해, 자연어 쿼리 처리 둘의 장점 결합
단점 "로그인"과 "사용자 인증" 못 찾음 "getUserInfo"같은 정확한 함수명 약함 구현 복잡도 증가
속도 매우 빠름 (1-5ms) 보통 (10-30ms) 보통 (15-40ms)
사용 예시 getUserById() 함수 찾기 "사용자 정보 조회하는 방법" 둘 다 커버
개발 문서 적합도 ⭐⭐⭐ (코드 검색) ⭐⭐⭐⭐ (설명 검색) ⭐⭐⭐⭐⭐ (최적)
 

실무 시나리오 비교:

text
사용자 질문: "API 호출 시 401 에러가 나요"
 
Lexical Search (BM25):
   ✅ "401", "API", "에러" 키워드 정확히 매칭
   ❌ "인증 실패", "토큰 만료" 같은 관련 문서 놓침
 
Semantic Search (Vector):
   ✅ "인증 실패", "권한 오류" 같은 의미적으로 유사한 문서 검색
   ❌ "error code 401" 같은 정확한 코드 검색 약함
 
Hybrid Search:
   ✅ 둘 다 찾아서 RRF로 결합 → 최고 성능

언제 어떤 방식을 선택할까?

상황권장 방식이유
API 함수명, 클래스명 검색 Lexical (BM25) UserRepository.findById() 같은 정확한 매칭 필요
개념 설명, 방법 질문 Semantic (Vector) "어떻게 캐시를 구현하나요?" 같은 자연어
에러 코드, 로그 메시지 Lexical (BM25) NullPointerException 같은 정확한 문자열
복합 질문 (코드 + 설명) Hybrid 사내 문서는 대부분 이 케이스
사내 전문 용어 많음 Hybrid + Custom Dictionary "DPMS", "GSMS" 같은 내부 약어
 

핵심 권장사항: 사내 개발 문서는 반드시 하이브리드 검색을 사용하세요. 코드와 설명이 섞여 있어 단일 방식으로는 한계가 있습니다.

 

 

임베딩 모델 비교: 실전 벤치마크

실제 성능 데이터를 기반으로 모델을 비교했습니다.

주요 임베딩 모델 성능 비교표

모델차원MTEB 평균한국어 성능 (F1)문맥 강점단어 강점코드 지원비용추천도
BGE-m3-ko 1024 66.8 0.7456 🥇 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ 무료 ⭐⭐⭐⭐⭐
KU-HIAI-ONTHEIT-large-v1.1 1024 65.2 0.7193 🥈 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ 무료 ⭐⭐⭐⭐
text-embedding-3-large (OpenAI) 3072→768 64.6 0.6053 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ $$ ⭐⭐⭐⭐
gemini-embedding-001 (Google) 3072→768 66.3 0.65 (추정) ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ $ ⭐⭐⭐⭐⭐
text-embedding-3-small (OpenAI) 1536→512 62.3 0.55 (추정) ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ $ ⭐⭐⭐⭐
KoE5 1024 64.1 0.7018 🥉 ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ 무료 ⭐⭐⭐⭐
Cohere embed-multilingual-v3 1024 62.0 0.3596 ⭐⭐⭐ ⭐⭐ ⭐⭐⭐ $$ ⭐⭐
all-MiniLM-L6-v2 384 56.3 0.40 (추정) ⭐⭐ ⭐⭐⭐ ⭐⭐ 무료 ⭐⭐
 

성능 지표 설명:

  • MTEB 평균: 전세계 표준 벤치마크 (높을수록 좋음)
  • 한국어 성능: AutoRAG 벤치마크 F1 스코어 (1.0이 만점)
  • 비용: 무료 (오픈소스), $ (저렴), $$ (보통)

문맥 강점 vs 단어 강점 모델

분류모델특징사용 시나리오
문맥 특화 BGE-m3-ko, gemini-embedding-001, KU-HIAI-ONTHEIT Long Context (8192 토큰) 지원, 의미 이해 탁월 "이 기능 어떻게 구현하나요?" 같은 자연어 질문
단어 특화 BM25 (sparse), all-MiniLM-L6-v2 정확한 키워드 매칭 "NullPointerException 해결" 같은 정확한 용어
코드 특화 text-embedding-3-large, gemini-embedding-001 코드 블록 학습, 함수 시그니처 이해 getUserById() 함수 검색, 코드 스니펫
균형형 BGE-m3-ko, text-embedding-3-small 문맥과 키워드 모두 준수 일반적인 사내 문서 (텍스트+코드 혼재)
 

실전 예시:

python
# 문맥 강점 모델 (BGE-m3-ko, Gemini)
 
질문: "사용자 정보를 데이터베이스에서 어떻게 가져오나요?"
"UserRepository의 findById() 메서드 사용" 문서 검색 ✅
→ 의미적으로 관련된 "DAO 패턴 설명" 문서도 검색 ✅
 
# 단어 강점 모델 (BM25, MiniLM)
질문: "getUserById 함수"
→ 정확히 "getUserById" 포함된 코드 스니펫 검색 ✅
"사용자 조회 방법" 같은 유사 의미는 놓침 ❌
 
# 하이브리드 (BGE-m3-ko + BM25)
→ 둘 다 찾아서 결합 → 최고 정확도 ⭐⭐⭐⭐⭐

 

 

벡터 차원 크기: 성능 vs 비용 트레이드오프

차원 수는 검색 시스템의 성능, 속도, 비용을 모두 결정합니다.

차원별 장단점 비교

차원 범위대표 모델장점단점메모리 (5만 벡터)검색 속도추천 용도
384 all-MiniLM-L6-v2 매우 빠름, 저비용 의미 표현력 낮음 75MB 3-5ms 테스트, PoC
512-768 text-embedding-3-small (768), gemini-embedding-001 (768) 균형 잡힌 성능, 적절한 비용 - 150MB 5-10ms 사내 문서 최적 
1024 BGE-m3-ko, KoE5, Cohere 높은 정확도, 복잡한 관계 포착 저장/계산 비용 증가 200MB 10-15ms 고품질 검색 필요 시
1536 text-embedding-3-large 매우 높은 정확도 비용/속도 부담 300MB 15-20ms 고급 검색, 대규모 데이터
3072 gemini-embedding-001 (full) 최고 정확도 매우 높은 비용 600MB 30-40ms 연구, 특수 목적

 

차원 축소 (Matryoshka Embeddings)

최신 모델들은 낮은 차원으로 축소해도 성능을 유지합니다.

원본 차원축소 차원성능 유지율저장 비용 절감속도 향상
3072 (gemini) 768 95-98% 75% ↓ 3-4배 ↑
1536 (OpenAI large) 512 93-96% 67% ↓ 2-3배 ↑
1024 (BGE-m3-ko) 768 97-99% 25% ↓ 1.3배 ↑

 

 

인덱스 알고리즘 비교

인덱스원리속도정확도 (Recall)메모리사용 시나리오
HNSW 계층적 그래프 탐색 ⭐⭐⭐⭐⭐ (1-5ms) ⭐⭐⭐⭐⭐ (99%+) 높음 (RAM 필요) 5만 벡터 최적 
IVFFlat 클러스터 기반 검색 ⭐⭐⭐ (10-20ms) ⭐⭐⭐ (90-95%) 보통 100만+ 벡터
IVF-PQ 클러스터 + 압축 ⭐⭐⭐ (10-30ms) ⭐⭐ (85-90%) 낮음 (압축) 대용량 (10M+)
Flat 전체 검색 (brute force) ⭐ (100ms+) ⭐⭐⭐⭐⭐ (100%) 낮음 1만 이하 소량

 


 

벡터 인덱스 알고리즘 상세

벡터 검색의 핵심은 수백만 개 벡터 중에서 가장 유사한 것을 빠르게 찾는 것입니다. 전체 벡터를 하나씩 비교하면 정확하지만 너무 느리므로, 근사 검색(ANN, Approximate Nearest Neighbor) 알고리즘이 필요합니다.

 

HNSW (Hierarchical Navigable Small World)

작동 원리:

HNSW는 고속도로 시스템처럼 작동합니다. 서울에서 부산 가는 길을 찾을 때, 먼저 고속도로(상위 레이어)로 대략적인 방향을 잡고, 목적지 근처에서 국도(중간 레이어), 마지막에 골목길(하위 레이어)로 정확한 위치를 찾는 것과 같습니다.

text
[Layer 2 - 최상위층] 노드 5개 (전체의 1%) - 장거리 연결, 빠른 탐색
[Layer 1 - 중간층] 노드 50개 (전체의 10%) - 중거리 연결
[Layer 0 - 기저층] 노드 500개 (전체 100%) - 단거리 연결, 정밀 검색

구축 과정:

  1. 계층 배정: 새 벡터가 추가될 때 확률적으로 레이어를 결정합니다. 상위 레이어로 갈수록 선택 확률이 낮습니다 (exponential decay).
  2. 연결 생성: 각 레이어에서 가장 가까운 M개의 이웃과 양방향 링크를 만듭니다. M=16이면 각 노드는 최대 16개 이웃과 연결됩니다.
  3. Greedy Search: 새 벡터를 삽입할 때, 상위 레이어에서 시작해 현재 레이어에서 가장 가까운 노드로 이동하고, 더 가까운 노드가 없으면 한 레이어 내려갑니다.

성능 특성:

특성값설명
시간 복잡도 O(log N) 100만 벡터에서도 20번 이하 비교로 검색
공간 복잡도 O(N × M) 각 노드가 M개 링크 저장, 메모리 많이 필요
구축 시간 O(N × log N × M) 실시간 추가 가능, 재구축 불필요
Recall@10 95-99% 거의 정확함
평균 레이턴시 1-5ms 매우 빠름
 

핵심 파라미터:

python
# HNSW 파라미터 설정 가이드
{
    "M": 16-48,              # 각 노드의 연결 수
                             # M=16: 빠르지만 정확도 낮음
                             # M=32: 균형점 (권장)
                             # M=48: 느리지만 정확도 높음
    
    "ef_construction": 100-500,  # 인덱스 구축 시 탐색 깊이
                                 # 높을수록 구축 느리지만 그래프 품질 좋음
                                 # 200-400 권장
    
    "ef_search": 32-128,    # 검색 시 탐색 깊이
                            # 높을수록 정확하지만 느림
                            # 64-128이 실무 최적
}

# 예시: 5만 벡터, 768차원
# M=32, ef_construction=256, ef_search=64
# → Recall@10: 97%, 레이턴시: 3-5ms, 메모리: 500MB

장점과 단점:

장점단점
✅ 가장 빠른 검색 속도 (1-5ms) ❌ 메모리 사용량 높음 (벡터 크기의 2-3배)
✅ 높은 정확도 (Recall 95%+) ❌ 초기 메모리 로딩 시간 필요
✅ 실시간 업데이트 가능 ❌ 대용량(1억+ 벡터)에서 메모리 부족 가능
✅ 하이퍼파라미터 튜닝 간단  
 

실전 사용 시나리오: 사내 문서 5만 벡터는 HNSW의 최적 범위입니다. 16GB RAM으로 충분하며, 100명 동시 접속도 여유롭게 처리합니다.

IVF (Inverted File Index)

작동 원리:

IVF는 도서관의 주제별 서가와 같습니다. 전체 벡터를 K개 클러스터(Voronoi cell)로 나누고, 검색 시 가장 가까운 몇 개 클러스터만 조사합니다.

text
1. 학습 단계 (K-Means 클러스터링):
   100만 벡터 → 1,000개 클러스터로 분할
   각 클러스터에 평균 1,000개 벡터 포함

2. 검색 단계:
   Query 벡터 → 가장 가까운 nprobe=10개 클러스터만 조사
   → 1만 개 벡터만 비교 (100만 개의 1%)

변형: IVF-PQ (Product Quantization):

IVF에 벡터 압축을 추가한 버전입니다. 768차원 벡터를 96개 서브벡터(각 8차원)로 쪼개고, 각 서브벡터를 256개 코드북 중 하나로 대체합니다.

text
원본 벡터: 768차원 × 4바이트 (float32) = 3,072바이트
IVF-PQ 압축: 96 서브벡터 × 1바이트 (uint8) = 96바이트
→ 32배 압축, 메모리 97% 절감!

성능 비교:

인덱스검색 속도정확도 (Recall)메모리구축 시간
HNSW ⭐⭐⭐⭐⭐ 1-5ms ⭐⭐⭐⭐⭐ 99% 높음 (200%) 빠름
IVFFlat ⭐⭐⭐ 10-20ms ⭐⭐⭐ 90-95% 보통 (100%) 매우 빠름
IVF-PQ ⭐⭐⭐ 15-30ms ⭐⭐ 85-90% 낮음 (3-5%) 느림
Flat ⭐ 100ms+ ⭐⭐⭐⭐⭐ 100% 낮음 (100%) 없음
 

핵심 파라미터:

python
# IVFFlat 설정
{
    "nlist": sqrt(N),        # 클러스터 수 (N=벡터 수)
                             # 100만 벡터 → nlist=1,000
                             # 클수록 정확하지만 구축 느림
    
    "nprobe": 10-100,        # 검색 시 조사할 클러스터 수
                             # nprobe=10: 빠르지만 정확도 낮음
                             # nprobe=50: 균형점
                             # nprobe=100: 느리지만 정확
}

# IVF-PQ 추가 설정
{
    "m": 8, 16, 32,          # 서브벡터 수 (768차원이면 m=96)
    "nbits": 8,              # 각 서브벡터를 몇 비트로 표현 (8bit=256 코드북)
}

실전 사용 시나리오: 100만 벡터 이상 대규모이거나, 메모리가 제한적일 때 IVF-PQ를 사용합니다. 5만 벡터 규모에서는 HNSW가 더 효율적입니다.

알고리즘 선택 가이드

데이터 규모메모리 제약정확도 요구추천 인덱스이유
< 1만 무관 100% Flat 전체 검색해도 빠름
1만 ~ 100만 충분 95%+ HNSW 속도와 정확도 최고
1만 ~ 100만 부족 85%+ IVF-PQ 메모리 97% 절감
100만 ~ 1억 충분 90%+ HNSW 분산 구성 필요
100만 ~ 1억 부족 85%+ IVF-PQ 압축으로 RAM 절약
1억+ 충분 90%+ HNSW (분산) 샤딩 필수
1억+ 부족 80%+ IVF-PQ + SQ 극한 압축

 

 

유사도 측정 방식

벡터 간 "가까움"을 측정하는 방법입니다. 어떤 방식을 선택하느냐에 따라 검색 결과가 완전히 달라집니다.

코사인 유사도 (Cosine Similarity)

의미: 두 벡터 사이의 각도를 측정합니다. 값의 크기(magnitude)는 무시하고 방향만 봅니다.

 

범위 -1 ~ +1 (1에 가까울수록 유사)
정규화 자동 정규화 (벡터 크기 무관)
장점 문서 길이에 영향받지 않음
단점 절대적 차이 무시
적합 케이스 텍스트 임베딩, 추천 시스템

 

유클리드 거리 (Euclidean Distance)

 

의미: 두 점 사이의 직선 거리를 측정합니다. 일상생활에서 쓰는 거리 개념과 동일합니다.


범위 0 ~ ∞ (0에 가까울수록 유사)
정규화 정규화 필요 (벡터 크기 영향)
장점 직관적, 절대적 거리 표현
단점 큰 벡터가 거리 지배 (스케일 민감)
적합 케이스 정규화된 벡터, 이미지 임베딩

 

검색 결합 알고리즘 (RRF)

하이브리드 검색에서 여러 검색 결과를 하나로 합치는 방법입니다.

RRF (Reciprocal Rank Fusion) 상세

핵심 아이디어:

"여러 검색 방식에서 모두 상위권에 나온 문서는 진짜 정답일 가능성이 높다"

 


개인적인 궁금증 : 실무에서는 잘모르는 사용자가 질문을 할수도 있음, 그렇게 되면 되게 모호한 단어들이나 표현들을 쓰는데 찰떡같이 알아듣고 서칭하도록 만들어야함

 

모호한 질문 처리 기술

개발자가 "컨테이너가 안 떠요", "클러스터가 이상해요"처럼 모호하게 질문할 때 대응하는 고급 기술들입니다.

1. Query Rewriting (쿼리 재작성)

핵심 아이디어: 사용자의 모호한 질문을 LLM이 명확하고 구체적인 검색 쿼리로 변환합니다. 또한 프롬프트에 이 문서의 범위나 주요 단어들을 명시해줘야함. 그래야 llm이 범위안에서 추측을 할수있음

4가지 핵심 속성:

속성의미예시
Correctness (정확성) 원래 의도 보존 "그거" → "EKS Pod"
Clarity (명확성) 맥락 독립적 "또 안돼" → "EKS Pod가 다시 재시작됨"
Informativeness (정보성) 관련 정보 추가 "에러남" → "EKS Pod CrashLoopBackOff 에러 발생"
Non-redundancy (비중복성) 중복 질문 제거 이전 질문과 겹치지 않게

2. HyDE (Hypothetical Document Embeddings)

핵심 아이디어: 질문을 직접 검색하지 말고, LLM이 가상의 답변을 생성하고, 그 답변으로 검색합니다.

작동 과정:

text
1. 사용자 질문: "컨테이너가 안 떠요"

2. LLM이 가상 답변 생성 (사실 여부 무관):
   "EKS Pod가 시작되지 않는 경우, 다음을 확인하세요:
    1. kubectl describe pod로 이벤트 확인
    2. 이미지 이름과 태그가 올바른지 확인
    3. ImagePullSecrets 설정 확인
    4. 노드의 리소스(CPU/메모리) 충분한지 확인
    5. SecurityContext 권한 문제 확인"

3. 이 가상 답변을 임베딩 → 벡터 검색
   (실제 문서와 어조/구조가 유사함)

4. 검색 결과: "EKS Pod 트러블슈팅 가이드" (정확히 매칭!)

왜 효과적인가?:

방식임베딩 대상특징검색 품질
일반 검색 "컨테이너가 안 떠요" 짧고 모호 ⭐⭐
HyDE "EKS Pod가 시작되지 않는 경우..." (200단어) 길고 구체적, 문서와 유사한 문체 ⭐⭐⭐⭐⭐

언제 HyDE를 사용할까?:

상황HyDE 효과이유
매우 모호한 질문 ("안돼요", "이상해요") ⭐⭐⭐⭐⭐ LLM이 맥락 추론해서 구체화
전문 용어 모르는 질문 ("그 로드밸런서 같은거") ⭐⭐⭐⭐⭐ LLM이 정확한 용어(ALB) 사용
구체적 질문 ("ALB Ingress Controller 설치 방법") ⭐⭐ 오히려 역효과 (원래 질문이 더 정확)
최신 정보 필요 (2025년 신기능) LLM이 구버전 지식으로 생성

3. Multi-Query Retrieval

핵심 아이디어: 하나의 질문을 여러 관점으로 다시 써서, 각각 검색한 후 결합합니다.

즉, 앙상블 기법으로 생각해라

 

 

 

모호한 질문 처리 파이프라인

python
# 통합 파이프라인
def handle_ambiguous_query(user_query, conversation_history):
    # Step 1: 대화 맥락 기반 Query Rewriting
    rewritten = query_rewriter(user_query, conversation_history)
    # "안돼요" → "EKS Pod ImagePullBackOff 에러"
    
    # Step 2: Multi-Query 생성 (3가지 관점)
    multi_queries = generate_multi_queries(rewritten)
    # [증상, 원인, 해결책] 3개 쿼리
    
    # Step 3: HyDE 추가 (모호한 경우만)
    if is_vague(rewritten):
        hyde_doc = generate_hypothetical_doc(rewritten)
        multi_queries.append(hyde_doc)
    
    # Step 4: 각 쿼리로 하이브리드 검색
    all_results = []
    for query in multi_queries:
        # Dense + Sparse 하이브리드
        dense_results = vector_search(query)
        sparse_results = bm25_search(query)
        hybrid_results = rrf_combine(dense_results, sparse_results)
        all_results.append(hybrid_results)
    
    # Step 5: 전체 결과 RRF 결합
    final_results = rrf_combine(all_results)
    
    # Step 6: Reranker로 최종 정렬 (optional)
    reranked = reranker.rerank(rewritten, final_results)
    
    return reranked[:5]  # 상위 5개 문서

 

최종 권장 아키텍처

text
[사용자] "컨테이너가 안떠요"
    ↓
[대화 맥락 분석] 이전 질문 참조
    ↓
[Query Rewriting] "EKS Pod ImagePullBackOff 에러"
    ↓
[Multi-Query 생성]
    ├─ "EKS Pod 이미지 다운로드 실패 증상"
    ├─ "ImagePullBackOff 발생 원인"
    └─ "ECR 인증 및 이미지 Pull 설정 방법"
    ↓
[HyDE] (필요시) 가상 트러블슈팅 가이드 생성
    ↓
[하이브리드 검색 × 4]
    ├─ Dense (gemini-768) + Sparse (BM25) → RRF
    ├─ Dense (gemini-768) + Sparse (BM25) → RRF
    ├─ Dense (gemini-768) + Sparse (BM25) → RRF
    └─ Dense (gemini-768) + Sparse (BM25) → RRF
    ↓
[RRF 전체 결합] 상위 20개
    ↓
[Reranker] (optional) 최종 5개
    ↓
[LLM 답변 생성] Gemini 1.5 Pro
    ↓
[답변 + 출처]

실제 현업에서 개발하는 API는 단순히 GET요청도 있지만 인증 등이 들어가고 복잡한 데이터를 POST로 요청하는 경우가 많은데

과연 LLM을 이용해서 대화형으로 사용자가 부하테스트를 할 수 있게 구현이 가능한지 궁금증이 들어 시작을 했다.

 

문제는 크게 3가지같다.

1. 다양한 데이터를 어떻게 활용하게 할지 ( 예를들어 로그인 api테스트면 여러 ID를 만드는 가입절차까지 스스로 만들게 하는건 어려워보이기 때문에 이미 만들어진 계정을 넘겨줘야 하는데, 어떻게 넘겨줄지)

 

2. 스크립트를 어떻게 전달할 것인가

    - 스크립트 생성까지 llm이 한다면 검증이 필요한데, 검증은 무조건 스모크테스트처럼 부하를 조금이라도 쏴봐야 한다.

    - 기본적인 스크립트를 줄것인가 ( 그럼 왜 이 llm을 이용하는지에 대한 강점을 확실하게 줘야함 )

 

3. API을 알려주면 어떻게 llm이 이해를 하고 스크립트를 짤것인가, 또는 만들어진 스크립트를 활용할 것인가

    - 스웨거 json을 이용해야하나?

 

 

--개인 메모 -----------

FLOW:  사용자 요청 → LLM 스크립트 생성 → 검증 단계 → 실행 → 결과 보고

 

검증 단계에서는:

  • 문법 검사: k6 스크립트의 문법적 오류 확인
  • 안전성 검사: 위험한 코드나 무한 루프 등 확인
  • 테스트 실행 가능성 검사: 필수 파라미터 누락 여부 확인

점진적 실행 접근법

  • 스모크 테스트 먼저 실행: 생성된 스크립트를 먼저 최소한의 VU(1~2개)로 짧은 시간(5-10초) 실행
  • 결과 확인 후 전체 테스트: 스모크 테스트가 성공하면 전체 테스트 실행

템플릿 기반 접근법

  • 완전히 자유로운 스크립트 생성 대신, 검증된 템플릿을 사용하고 LLM은 파라미터만 채우는 방식

피드백 루프 구현 ( 이건 랭그래프로 복잡한 구조가 될 듯 )

  • 사용자 피드백을 통해 스크립트를 개선하는 메커니즘

 

실용적인 구현 방안

위 접근법들을 종합하여 다음과 같은 실용적인 구현을 제안합니다:

  1. 단계적 접근:
    • 1단계: 템플릿 기반 + 파라미터 추출 (안전하게 시작)
    • 2단계: 제한된 자유도의 스크립트 생성 + 검증
    • 3단계: 완전 자유도의 스크립트 생성 + 강력한 검증
  2. 하이브리드 접근법:
    • 핵심 구조는 템플릿 기반으로 유지
    • 동적 부분(페이로드, 검증 로직 등)은 LLM이 생성
    • 생성된 코드는 샌드박스에서 검증 후 통합
  3. 사용자 지식 활용:
    • "이 API는 JWT 인증이 필요해" 같은 사용자 힌트 활용
    • 이전에 성공한 테스트 패턴 재활용
  4. 점진적 학습:
    • 성공한 스크립트를 데이터베이스에 저장
    • 새로운 스크립트 생성 시 유사한 성공 사례 참조

 

 

---결과----

결론적으로 랭그래프 기반으로 웹까지 연결은 했따

다만 로키와 템포 등 어떠한 분석을 계속 이어나가는것에 리액트 에이전트 방식은 좋지 않은것 같음

리액트 에이전트의 단점은, 개인적으로는 다음과 같다. 

1. 통제 불가능 (반복횟수 통제는 가능하지만, 퀄리티 보장 불가)

2. 위와 같은 맥락으로 토큰 비효율

3. 슈퍼바이저 에이전트의 비효율성 ( 서브에이전트들과의 오케스트레이션시 대화 맥락 전달 등 비효율 부분 발생 )

 

차라리 리우방식이 나은듯

이 내용은 저의 경험을 통해 개인적으로 정리한 부분입니다. 

다른 사람의 의견과는 다를 수 있습니다.

 

회사마다 또는 서비스의 규모마다 다를 수 있지만 대고객 서비스를 운영할때 가장 유용하게 본 지표는 서비스의 응답속도입니다.

이러한 응답속도는 tempo를 이용해서 구축할 수 있고, 또는 와탭과 같은 상용 APM을 이용해도 됩니다.

아래와 같은 형태로 제공됩니다.

tempo로 구축한 api 응답속도 heatmap대시보드
와탭 (https://docs.whatap.io/)

 

서비스 운용시 마이크로 서비스가 너무 많으면 데브옵스 엔지니어는 서비스 지연 또는 장애를 어떤 기준으로 딱 봐야할지 기준을 잡기 힘듭니다. 그래서 대고객 서비스라면 우리 서비스를 이루는 모든 마이크로서비스들의 응답속도를 시각화한 대시보드를 보는게 가장 좋습니다.

 

운영을 하다보면 장애는 항상 패턴을 보입니다. 가장 많이 겪었던 장애포인트는 DB지연 또는 장애, 네트워크 지연, pod 이상, 배포로 인한 장애 정도의 순서였습니다. 

 

히트맵의 패턴을 몇개 말씀드리면 세로줄, 가로줄 , 무분별한 지연 정도로 볼 수 있었습니다.

장애를 재연할 수 없으니 와탭 홈페이지 도큐먼트의 사진을 예로 설명하겠습니다.

 

세로줄은 아래와 같이 지속적이지는 않지만 단발성으로 그어지는 패턴이 있고, 어느정도 그림을 그려나가며 세로줄이 그어지기도 합니다.

저는 보통 두번째의 경우가 많았던것 같지만 첫번째는 주로 특정 시간에 어떠한 병목구간이 해결이 되거나 락이 해소되면서 풀리는 상황이며 두번째는 점점 지연이 발생하다가 장애 서비스의 배포등으로 해결되는 상황 등에서 발생했었습니다.

 

가로줄은 아래와 같이 나타납니다. 이는 보통 타임아웃처럼 무언가에 걸리는 상황이며 이 상황도 지속되는 상황이기에 해당 서비스의 자원(우리쪽이든 외부 서비스쪽이든)에 대해 살펴봐야 합니다. 또는 타임아웃 시간이 적절히 설정되었는지 확인합니다.

아래와 같은 대환장 케이스는 서비스 전반적으로 장애가 전파된 상황이라고 생각이 됩니다. DB모니터링이나 restart pod나 cpu,mem사용률이나 네트워크 장애, 배포이력을 모두 보면서 해결해야 합니다.

위에서 말한것처럼 외부서비스 연동도 많이 되어있는 서비스라면 장애시 내부서비스의 문제인지 외부서비스의 문제인지 파악해야 하며, 외부 서비스들을 전용 ALB등으로 통신하도록 되어있다면 클라우드와치등을 이용하여 그라파나로 시각화한 대시보드도 모니터링 해야 합니다.

 

모니터링 및 장애 추적은 위와같이 응답속도로 부터 찾아가는게 가장 빠른 방법이라고 생각합니다.

그래서 루틴을 적어보자면.

1. 히트맵 모니터링

2. 응답지연이 발생하는 서비스 찾기 ( 상용 APM들은 히트맵을 클릭하면 해당 API이력들이 연결되도록 지원할 것이며, TEMPO를 이용한다면 복잡하긴 하지만 Data link등을 이용하여 구축이 가능합니다)

3. 서비스를 파악했으면 POD모니터링, 로그 모니터링, 트레이징 모니터링

4. 클라우드 서비스 모니터링 (ALB, WAF등)

 

POD를 모니터링 하는 경우 보통 CPU, MEMORY, NETWORK, running pod 추이, restart 수 추적,  HPA작동 여부 정도를 모니터링 할 것이며 개인적으로는 cicd연동도 필요하다고 생각합니다. 깃헙 액션을 이용하여 배포를 하는 시스템이면 실제 배포가 이루어 지는 시점을 그라파나 어노테이션으로 대시보드에 표시를 남기고, argocd를 사용한다면 argocd noti기능을 통해 마찬가지로 그라파나로 어노테이션을 보낼 수 있습니다.

 

이러한 이유는 장애는 배포시점에 나타날 수도 있기 때문에 배포이력을 파악해야 하며, 이상적인 마이크로 서비스는 서비스간 디펜던시가 없는 것이지만 현실적으로 어려운 부분이 많습니다. 우리 서비스를 호출하거나 우리 서비스에서 호출을 하는 마이크로 서비스가 배포되었는지도 우리 서비스의 장애로 연결 될 수 있기 때문에 이러한 배포이력을 시각화하는것도 매우 중요하다고 생각을 합니다.

 

또한 배포이력을 마이크로 서비스 POD모니터링 대시보드에 표시하지 않는다면 블루그린을 배포하는 서비스의 경우 배포시 POD의 수가 증가하는데 배포이력이 시각화되어있지 않으면 POD가 왜 수가 증가했는지 추가적인 해석이 필요하기 때문에 마이크로 서비스가 많아질수록 모니터링시 직관적인 해석이 아니라 노력이 들어가는 해석이 필요합니다.

 

로그모니터링은 에러로그 또는 개발자라면 개발자가 남긴 중요한 로그를 검색하도록 쿼리를 구성하고 이 카운팅을 시각화해놓는 것이 좋습니다. 또한 알람도 설정을 해야 합니다. 트레이싱 또한 매우 중요합니다. 마이크로 서비스간 호출 실패 또는 성공을 시각화 하는것은 장애를 고치는 것에 있어 효과적이며, 더불어 네트워크 장애가 있었는지 시스템을 추적해 나가는것에도 많은 도움이 됩니다.

 tempo를 이용하여 서비스 그래프를 구축하면 아래와 같이 서비스간 호출을 시각화 할 수 있습니다. 이는 상용 APM에서는 더욱 많은 기능을 제공하며 토폴로지 맵 등의 이름으로 불리기도 합니다.

 

 

사실 이정도만 구축이 되었다면 어느정도 모니터링은 다 된다고 생각합니다. 인프라 운영자의 입장에서는 추가적으로 하나 더 좋은 대시보드가 있습니다. AWS를 사용한다면 클라우드 와치를 이용하여 우리 서비스의 진입점부터 각 단계의 ALB등의 호출건수 등도 모니터링하며 우리 서비스가 Top-down으로 통신하는 구간에서 어느 구간이 이상한지 한눈에 파악할 수 있기 때문에 굉장히 효과적으로 서비스 가시성을 확보할 수 있습니다.

 

그리고 블루그린 배포를 하면 POD가 일시적으로 증가합니다. 이때 장애가 날 수 있는 포인트는 데이터베이스 입니다. 커넥션 관리가 중요하며 커넥션 관련 장애가 날 수 있기 때문에 블루 그린 배포를 하더라고 로직상 데이터베이스 커넥션관리를 잘 해줘야 하며, AWS RDS proxy같은 서비스를 적극 활용해야 합니다. 이러한 커넥션 모니터링도 당연히 운영해야 합니다.

 

그리고 비용최적화의 한 부분으로 호출구조를 변경하여 네트워크사용으로 인한 비용절감이 있습니다. 또는 API 캐싱전략을 사용하여 DB호출을 줄이는 방법도 있습니다. 이러한 개선을 해나갈때 도움이 되는 부분중 하나는 호출되는 API리스트를 시각화하며, API별 호출건수, 지연시간 등도 시각화를 하여 어떠한 개선을 해나가야 할 지 정하는것이 좋습니다.

 

이러한 전체적인 흐름을 통해 각자 서비스에 맞게 대시보드를 구축하면 됩니다. 어떻게 시각화를 하고 어떻게 대시보드 티어늘 나누고 등은 노하우의 영역입니다.

마이크로서비스 모니터링 가이드

모니터링 전략 구성 요소

기본 성능 지표 설정

  • 각 서비스별 핵심 성능 지표(KPI) 식별 및 추적
  • 정상 동작 이해를 위한 기준 데이터 수집
  • 비즈니스 요구사항에 맞는 현실적인 성능 목표 설정
  • 서비스 응답 시간, 오류율, 처리량 등 핵심 지표 모니터링

알림 및 통지 시스템 구축

  • 중요 지표에 대한 임계값 정의
  • 단계별 알림 시스템 구현:
    • 잠재적 문제에 대한 경고 알림
    • 즉각적인 조치가 필요한 중요 알림
  • PagerDuty 또는 OpsGenie와 같은 도구를 사용한 온콜 관리

분산 추적 구현

  • 추적 솔루션 선택 (예: SigNoz, Zipkin, Tempo)
  • 서비스 계측을 통한 추적 데이터 생성
  • 로그 및 지표와 추적 데이터 연계
  • 고유 요청 ID를 사용하여 서비스 간 요청 추적

도구별 활용 방안

Prometheus와 Loki 통합 활용

  • Prometheus: 실시간 모니터링, 애플리케이션 계측, 시계열 데이터 분석
  • Loki: 비용 효율적인 로그 저장, 텍스트 기반 디버깅 정보, 사고 후 분석
  • Grafana: Prometheus 지표와 Loki 로그를 통합 시각화

쿠버네티스 모니터링

  • Kubernetes Monitoring Helm 차트 활용
  • 클러스터 이름을 정적 레이블로 지정하여 모든 로그에 첨부
  • 클러스터 이벤트 및 Pod 로그 수집 활성화
  • 서비스 메시(Istio, Linkerd)와 통합하여 서비스 간 통신에 대한 상세 정보 확보

로그 관리

  • 서비스 전반에 걸친 로그 형식 표준화
  • 중앙 집중식 로깅 시스템 구현 (LGTM 스택, ELK 스택)
  • 스토리지 비용 관리를 위한 로그 보존 정책 구현

그라파나를 이용한 쿠버네티스 모니터링 지표

클러스터 수준 지표

  • 클러스터 CPU 사용량: 사용 vs 총량
  • 클러스터 메모리 사용량: 사용 vs 총량
  • 클러스터 파일 시스템 사용량: 사용 vs 총량
  • 클러스터 네트워크 I/O 압력
  • 클러스터 상태 (파드 상태, 파드 재시작, 파드 스로틀링)
  • 노드, 파드, 컨테이너 개요

노드 수준 지표

  • 마스터 노드 상태 확인 - API 서버, 스케줄러, 컨트롤러 등
  • 마스터 노드 성능 저하
  • 파드 서비스를 위한 가용 노드 수
  • 노드 CPU 사용률 (node_cpu_usage_seconds_total)
  • 노드 메모리 사용량 (node_memory_working_set_bytes)
  • 파드 배치를 위한 노드 디스크 공간
  • 노드 디스크 I/O 사용량
  • 노드 네트워크 트래픽 (송수신)
  • 노드 네트워크 트래픽 오류
  • 노드 네트워크 트래픽 드롭
  • 준비되지 않은 노드 수 (node_collector_unhealthy_nodes_in_zone)

파드/컨테이너 수준 지표

  • 파드 리소스 할당
  • 과소 또는 과대 프로비저닝된 파드
  • 클러스터 내 실행 중인 파드 수
  • 클러스터 내 정상 vs 비정상 파드
  • 스로틀된 컨테이너 비율
  • 컨테이너 재시작 횟수
  • 실패 또는 대기 상태의 영구 볼륨 수
  • 컨테이너 CPU 및 메모리 사용률
  • 파드 CPU 사용률 (pod_cpu_usage_seconds_total)
  • 파드 메모리 사용량 (pod_memory_working_set_bytes)
  • 대기 중인 파드 (scheduler_pending_pods)
  • 스케줄링 시도 (scheduler_pod_scheduling_attempts)
  • 프로브 카운트 (prober_probe_total)

애플리케이션 성능 지표

  • 요청 속도: 초당 처리된 요청 수
  • 오류 율: 실패한 요청의 비율
  • 지연 시간: 요청 처리에 소요된 시간
  • API 서버 요청 지연 시간 (apiserver_request_duration_seconds)
  • 메트릭 스크래핑 오류 (resource_scrape_error)

모니터링 모범 사례

자동화된 모니터링 솔루션

  • 인프라 확장에 맞춰 모니터링 솔루션 자동화
  • 명확한 인시던트 대응 프로토콜 수립 및 팀 교육 제공
  • 자동 계측 라이브러리 및 에이전트 사용

메트릭, 로그, 트레이스 상관관계 분석

  • 시스템 동작에 대한 다양한 관점 제공
  • 더 빠른 디버깅 및 근본 원인 분석 가능
  • 로그, 트레이스, 메트릭 간 쉬운 상관관계 분석을 위한 컨텍스트 로깅 구현

증상 기반 알림 설정

  • 단순 임계값이 아닌 증상에 기반한 알림 설정
  • 지연 시간 증가, 오류율 급증, 포화도 등 모니터링

컨테이너 내부 모니터링

  • 컨테이너가 실행 중인지 뿐만 아니라 내부 프로세스 상태 확인
  • 프로세스 상태, 메모리 누수, 문제를 나타내는 로그 등 고려
  • 상태 확인 및 준비 프로브 구현 (/health 및 /ready 엔드포인트)

개발 단계부터 모니터링 통합

  • 초기 단계에서 계측 추가
  • 개발 중 알림 임계값 정의
  • 배포 전 관찰 가능성 테스트
  • 서비스 설계에 관찰 가능성 요구사항 포함

'혼자 공부하는 내용 ( 잡다한 것들 )' 카테고리의 다른 글

TCP 핸드쉐이크 주요 플래그  (0) 2025.04.19
osi 7계층  (0) 2025.04.19
servlet , JSP  (0) 2020.06.27
Web , Was와 관련 지식에 대한 이해  (0) 2020.06.27
yaml 기본 문법  (0) 2020.05.28

최우선 조건 : 사용자의 복잡한 질문,여러 툴을 이용해야해도 완성도 있게 대답해야 한다.

  1. 오케스트레이터 노드: 사용자 입력을 최초로 받아 처리 방향을 결정하는 중앙 제어 장치
  2. 플래닝 노드: 복잡한 작업을 여러 단계로 분해하여 실행 계획을 수립
  3. 전문 에이전트 노드들: 각각 특정 도구나 서비스에 특화된 8개의 에이전트 (그라파나, 로키, 템포, 아르고시디 등)
  4. 밸리데이션 노드: 결과의 완성도와 정확성을 검증
  5. 응답 노드: 최종 결과를 사용자 친화적으로 요약하여 제공

 

보완하면 좋을 만한 부분들:

  • 컨텍스트 관리: 사용자와의 대화가 이어질 때 이전 대화 컨텍스트를 어떻게 유지할지 고려가 필요함. 예를 들어 "그 중에서 메모리 사용량이 가장 높은 것만 보여줘"와 같은 후속 질문에 대응할 수 있어야 함 -> 메모리세이버 등 이용
  • 에이전트 선택 메커니즘: 오케스트레이터가 어떤 에이전트를 호출할지 결정하는 로직이 중요. -> 프롬프트 강화
  • 실패 처리 메커니즘: 특정 에이전트가 실패하거나 정보를 가져오지 못할 경우에 대한 대처 방안이 필요.-> 고민 필요
  • 사용자 피드백 루: 사용자가 결과에 만족하지 못할 경우 시스템이 어떻게 개선 방향을 찾을지에 대한 고려가 필요 -> 고민 필요
  • 병렬 처리: 여러 에이전트를 동시에 실행하여 응답 시간을 단축하는 방법을 고려해 볼 수 있음 -> 멀티 처리 적용
  • 간 결과 제공: 복잡한 질문의 경우 최종 답변까지 시간이 오래 걸릴 수 있으므로, 중간 진행 상황이나 부분 결과를 제공하는 기능이 유용할 수 있음 -> add 메세지를 구현하고 st.session_state를 이용하여 화면에 실시간 출력
  • 에이전트 확장성: 새로운 에이전트를 쉽게 추가할 수 있는 구조인지 확인. 향후 새로운 도구나 서비스를 통합할 필요가 있을 수 있음 -> 고민필요

 

 

 

코드 구현은 차차 할 예정, 랭그래프, 랭체인, 제미나이 예정

MCP서버를 만들기전 시나리오를 수립해보자.

 

k6 Tool 사용 시나리오

  • 특정 API endpoint에 대해 지정된 부하(초당 요청 수, 가상 유저 수, 지속 시간)로 테스트 실행 및 결과 요약
  • 동일 endpoint에 대한 과거 테스트 결과 비교(성능 트렌드, 최대 TPS, 에러율 등)
  • 다양한 HTTP 메소드(GET, POST, PUT, DELETE)별 부하 테스트.
  • 인증이 필요한 API에 대해 토큰 발급 및 헤더 자동 세팅
  • Swagger/OpenAPI 문서를 파싱하여 자동으로 k6 스크립트 생성.
  • 여러 API endpoint를 조합한 시나리오 테스트(사용자 플로우 시뮬레이션).
  • 테스트 실패(에러율 급증, 응답 지연) 시 자동 알림/이슈 생성.

cli나 스크립트 사용

 

 

 

argocd Tool 사용 시나리오

 

  • 배포 실패시 자동으로 로그도 가져와주기. ( 해결 방안 추천도 해주면 좋을것 같음)
  • 배포 자동화
  • 현재 out-of-sync인 app 요청
  • 배포 히스토리 물어보기
  • 전체 pod진단
  • project생성
  • project리스트 검색
  • project기반 검색
  • app생성
  • app검색
/api/v1/applications (GET) 전체 애플리케이션 목록 및 상태 조회
/api/v1/applications/{appName} (GET) 특정 앱의 상세 정보 및 sync 상태 확인
/api/v1/applications?syncStatus=OutOfSync Out-of-sync 상태인 앱 목록 필터링
/api/v1/applications/{appName}/sync (POST) 특정 앱 강제 동기화 트리거
/api/v1/applications/{appName}/operation 앱에 대한 롤백, 중단 등 연산 실행
/api/v1/projects (GET) 프로젝트 단위로 앱 관리
/api/v1/session (POST) 인증 토큰 발급
 

 

 

챗봇에서 가능한 시나리오:

  • "my-app 어플리케이션 지금 sync상태 어때?" → /api/v1/applications/my-app 호출 후 status.sync.status 반환.
  • "지금 out-of-sync인 서비스들 쭉 알려줘" → /api/v1/applications?syncStatus=OutOfSync로 조회.
  • "my-app을 강제로 동기화해줘" → /api/v1/applications/my-app/sync POST.
  • "오늘 배포된 앱 목록 알려줘" → /api/v1/applications?createdAfter=YYYY-MM-DD 등(필터링 지원 시).
  • "특정 앱의 리소스 트리 보여줘" → /api/v1/applications/{appName}/resource-tree.
  • 특정 프로젝트 내 앱의 동기화 상태 집계 및 리포트.

Agentic AI라는게 정말로 가능한 것인가라는 생각이 든다. 

아직까지 챗봇형태로 할루시네이션이 어느정도 발생하여도 용인이 되는 서비스는 충분히 가능해 보인다. 마누스와 같은...

 

하지만 기업이 서비스를 연동하려면 많은 부분들이 필요해 보인다.

가전제품처럼 오작동이 있어서는 안되는 서비스에서는 re-check과정이 타이트하게 들어가야 하는데 LLM 자체가 생성형이기때문에 항상 우리가 생각하는 일관된 답변을 주지 않아서 re-plan과정이 들어갈수밖에 없다. 이럴수록 시간이 늘어나기 때문에 고객 경험 측면에서 좋지 않음. 근데 이 시간을 줄이기 위해서는 단계를 줄이거나 프롬프트를 엄청나게 잘 짜거나, json형식으로 잘 관리해서  LLM으로 검증하는게 아닌 코드기반으로 빠르게 검증을 해야한다.

 

또한 LLM 호출을 타이트하게 제어해야한다. 돈을 무한정 낼 수 없다.

 

멀티 에이전트간 흐름제어가 굉장히 어렵다. 프롬프트만으로는 불가능해 보이며 결국에는 검증코드들이 많이 들어가야 한다. 

 

에이전틱 ai는 결국에 사람처럼 생각하는 사고방식을 가져야한다. 사람이 과거를 기억하고, 할일의 우선순위를 정하고, 할일을 기억하는 등 이러한 과정을 시스템에 녹여내야 하는데,,,,굉장히 어렵다. 

 

또한 단일 워크플로우만 잘 처리하도록 에이전트를 개발하면 안된다. 아쉬운 점은 현재 대부분의 강의들이 이러한 형태뿐이다. 당연히 그럴수밖에 없는게..아직 국내에서 에이전틱 시스템을 해본사람도 극소수일 것이기에...

 

앞으로는 집중할 부분은 "사람처럼 생각하게하기" , "output검증", "보안이나 오작동을 최소화 하기위한 가드레일 기능" 이다.

TCP 핸드셰이크 주요 플래그

약어전체 명칭설명트러블슈팅 활용 예시
SYN Synchronize 연결 시작 시 시퀀스 번호 동기화 tcp.flags.syn==1로 초기 패킷 필터링
ACK Acknowledgment 데이터 수신 확인 tcp.analysis.ack_rtt로 지연 분석
FIN Finish 정상 연결 종료 요청 비정상 FIN 패킷은 연결 리셋 의심
RST Reset 긴급 연결 종료/재설정 tcp.flags.reset==1로 이상 종료 감지
PSH Push 수신 측에 즉시 데이터 전달 요청 스트리밍 서비스에서 빈번히 사용
URG Urgent 긴급 데이터 표시(현대 프로토콜에서 거의 사용 안 함) tcp.urgent_pointer 값 확인

플래그(약어)의미많이 보일 때 위험 징후 및 설명

RST Reset 연결이 비정상적으로 즉시 종료될 때 사용. 대량의 RST 패킷이 보이면 네트워크 장애, 방화벽 차단, 서비스 거부 공격(DDoS) 등 의심
ALL ALL TCP Flags 모든 플래그가 동시에 켜진 패킷(예: Xmas Flood). 정상적이지 않은 패킷으로, DDoS 공격이나 방화벽 우회 시도일 수 있음
ACK Acknowledgment 단독 ACK(특히 SYN/ACK 없이 ACK만 오는 경우)은 비정상적인 핸드셰이크 흐름, 방화벽/보안장비의 세션 차단, 도중 연결 끊김 등 문제 신호
FIN Finish 정상 연결 종료 플래그이나, FIN과 RST가 반복적으로 섞여 나오거나 비정상적으로 많이 보이면 연결 불안정, 세션 문제 가능성

 

와이어샤크에서 많이 보이면 위험한 패턴

  • RST 플래그 다수:
    • 서버 또는 클라이언트가 강제로 연결을 자주 끊는 경우, 서비스 장애, 방화벽 차단, 포트 스캔 등 공격 징후일 수 있음
  • ALL TCP Flags(0x3F):
    • 정상적인 상황에서는 거의 나타나지 않음. 대량 출현 시 DDoS(Xmas Flood) 공격, 방화벽/IPS 우회 시도 가능성
  • ACK만 반복:
    • SYN/ACK 없이 ACK만 계속 보이면 정상적인 3-way handshake가 이루어지지 않는 상태. 방화벽, NAT, 세션 테이블 문제, 비정상 트래픽 의심
  • FIN, RST 혼합 다수:
    • 정상 종료(FIN)와 강제 종료(RST)가 반복적으로 섞여 나오면, 세션 불안정, 네트워크 장비의 세션 관리 문제, 또는 애플리케이션 오류 가능성
  • Bad TCP, Out-of-Order, Retransmission:
    • 와이어샤크에서 빨간색으로 표시되는 Bad TCP, 재전송, 순서 뒤바뀜 패킷이 많으면 패킷 손실, 네트워크 혼잡, MTU 불일치 등 네트워크 품질 저하 신호

계층별 핵심 기능과 실무 적용

7계층(Application) - 애플리케이션 서비스

  • 실무 포커스: HTTP/3(QUIC), gRPC, WebSocket 등 모던 프로토콜 지원 여부 확인
  • 트러블슈팅:
  •  
    bash
    curl -v http://target.com # HTTP 헤더 검증 tcpdump -i eth0 port 443 -w capture.pcap # TLS 핸드셰이크 캡처
  • 보안: WAF(Web Application Firewall)를 통한 SQLi/XSS 탐지

6계층(Presentation) - 데이터 표현

  • 암호화: TLS 1.3 협상 과정에서의 cipher suite 선택 전략
    openssl s_client -connect target.com:443 -tls1_3
  • 이슈 사례:
    • JSON vs Protobuf 직렬화 오버헤드 비교
    • 압축 알고리즘(Zstd vs Brotli)에 따른 CPU/대역폭 트레이드오프

5계층(Session) - 세션 관리

  • 실무 적용:
    • 양방향 세션 추적을 위한 NetFlow/IPFIX 활용
    • QUIC의 Connection ID를 이용한 멀티패스 핸드오버
  • 장애 사례:
    • 방화벽의 세션 타임아웃(기본 30분)으로 인한 장기 연결 끊김

4계층(Transport) - 전송 제어

  • TCP 심화:
  •  
    bash
    ss -tin # CWND/BBR 모니터링 sysctl net.ipv4.tcp_available_congestion_control
  • UDP 최적화:
    • QUIC의 0-RTT 핸드셰이크 구현
    • MTU Discovery 실패 시 PMTUD 블랙홀 현상

3계층(Network) - 라우팅

  • BGP 운영:
  •  
    bash
    vtysh -c "show ip bgp summary" # BGP 피어링 상태 확인
  • SDN 연계: VXLAN을 이용한 L3 오버레이 구성
  • 트래픽 엔지니어링:
    • MPLS-TE에서의 명시적 경로 지정(ERSPAN)
    • ECMP 로드 밸런싱 비대칭 문제

2계층(Data Link) - 프레임 전달

  • 스패닝 트리:
  •  
    bash
    show spanning-tree detail # Root 포트/블로킹 포트 확인
  • 이더넀 최적화:
    • LACP의 hash-policy(src-dst-ip vs src-dst-mac)
    • Jumbo Frame(9000 byte) 적용 시 end-to-end 일관성 검증

1계층(Physical) - 물리적 신호

  • 케이블 진단:
     
    bash
    ethtool -p eth0 # 링크 LED 점등 확인 cabletest start interface=eth0 # TDR 테스트
  • DWDM 장비:
    • Chromatic Dispersion 보상 계수 계산
    • QSFP28 모듈의 BER(Bit Error Rate) 모니터링

계층별 패킷 처리 심화 분석

 
text
송신 측: Application → Presentation → Session → Transport → Network → Data Link → Physical 수신 측: Physical → Data Link → Network → Transport → Session → Presentation → Application
  • 헤더 추가 과정:
  •  
    python
    # TCP 세그먼트 생성 예시 class TCPHeader: def __init__(self, src_port, dst_port): self.src_port = src_port # 16비트 self.dst_port = dst_port # 16비트 self.seq_num = 0 # 32비트 self.ack_num = 0 # 32비트 # ... 기타 플래그 필드
  • MTU 파편화:
    wireshark-filter: tcp.flags.fragment_offset > 0

실무 트러블슈팅 방법론

  1. Bottom-Up 접근법:
    • 물리층(1) → 애플리케이션층(7) 순으로 검증
    • 예시: ping(3층) → tcping(4층) → curl(7층)
  2. Protocol Analyzer 활용:
    tshark -i eth0 -Y "http.request" -T json
  3. Latency 진단:
    mtr --report-wide --tcp --port 443 target.com
  4. 대규모 클러스터:
    • eBPF를 이용한 커널 수준 트레이싱
    • P4 프로그래밍 가능 스위치에서의 인라인 측정

클라우드 네이티브 환경의 진화

  • 서비스 메시: Istio에서의 L7 프로토콜 인식
  • 가상화 네트워킹:
    • SR-IOV의 VF/PF 아키텍처
    • CNI 플러그인의 다중 네트워크 지원(Calico BGP, Cilium eBPF)
  • Observability:
    prometheus-query: rate(node_network_transmit_bytes_total[5m])

 

https://github.com/nicolaka/netshoot

 

GitHub - nicolaka/netshoot: a Docker + Kubernetes network trouble-shooting swiss-army container

a Docker + Kubernetes network trouble-shooting swiss-army container - nicolaka/netshoot

github.com

 

위 내용에 대해서 공부할것.

'쿠버네티스' 카테고리의 다른 글

HPA  (0) 2022.09.26
인그레스  (0) 2022.09.13
스테이트 풀셋  (0) 2022.08.28
스토리지  (0) 2022.08.28
잡, 크론잡  (0) 2022.08.28

+ Recent posts