이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • 자주 일어나지는 않지만 반드시 알아야 하는 AI 장애는 무엇인가?
  • embedding 모델 변경, index 잔존 chunk, prompt cache 붕괴는 왜 위험한가?
  • agent와 tool calling에서 드물지만 큰 사고가 나는 지점은 무엇인가?
  • 이런 문제를 설계 체크리스트에 어떻게 반영하는가?

개요

실무자는 흔한 장애뿐 아니라 드물지만 피해가 큰 장애를 알아야 한다. AI 시스템은 모델, context, 검색, tool, provider, 로그, 비용이 연결되어 있어 낮은 확률의 문제가 큰 사고로 이어질 수 있다.

이 문서는 그런 문제를 미리 체크리스트에 넣기 위한 플레이북이다.

Embedding 모델 변경 후 검색 품질 붕괴

embedding 모델을 바꾸면 vector가 놓이는 의미 공간이 달라질 수 있다. 기존 index에 새 embedding을 섞거나 query만 새 모델로 만들면 유사도 점수가 무의미해질 수 있다.

대응:

  • embedding model version을 index metadata에 저장한다.
  • 모델 변경 시 전체 재색인 계획을 세운다.
  • dual index로 비교 eval을 돌린다.
  • old/new index를 섞지 않는다.

삭제된 문서 Chunk 잔존

원본 문서를 삭제했는데 vector index에 chunk가 남으면 오래된 정보나 개인정보가 계속 검색될 수 있다.

대응:

  • 문서 삭제 이벤트가 index 삭제로 이어지게 한다.
  • source id 기준 delete API를 둔다.
  • 정기적으로 원본 DB와 index를 reconcile한다.
  • 답변 trace에 source id를 남긴다.

Retry로 인한 Tool 중복 실행

모델 호출이나 host가 실패했다고 판단해 retry했지만, 실제 write tool은 이미 성공했을 수 있다. 이때 메일, 결제, 티켓 생성, DB 변경이 중복된다.

대응:

  • write tool은 idempotency key 필수
  • 실행 결과를 audit log에 남김
  • timeout 후 상태 조회 먼저 수행
  • retry 금지 tool 목록 관리

JSON Schema 강제에도 Parsing 실패

structured output을 써도 refusal, content policy, max token, provider error, streaming partial 때문에 파싱 실패가 난다.

대응:

  • validation failure를 정상 실패 경로로 둔다.
  • refusal을 별도 타입으로 처리한다.
  • output token limit을 모니터링한다.
  • fallback model도 schema eval을 통과시킨다.

Prompt Cache 붕괴

prompt caching은 고정 prefix가 반복될 때 유리하다. 앞부분에 timestamp, user id, 요청별 context를 넣으면 cache hit rate가 떨어질 수 있다.

대응:

  • 고정 instruction과 schema를 앞에 둔다.
  • 동적 값은 뒤쪽에 배치한다.
  • cached token 지표를 본다.
  • prompt version 변경 후 cache hit rate를 확인한다.

Observability 고카디널리티 비용 폭증

trace tag에 user input, prompt hash가 아닌 원문, source id 수천 개, document title을 넣으면 관측성 비용이 커질 수 있다.

대응:

  • tag에는 낮은 cardinality 값을 둔다.
  • 원문은 별도 저장소와 샘플링을 쓴다.
  • source id 목록은 길이 제한을 둔다.
  • prompt 전문 로그는 기본 비활성화한다.

Metadata Filter와 DB 권한 불일치

vector DB의 metadata filter가 실제 DB 권한 모델과 다르면 권한 없는 문서가 검색될 수 있다.

대응:

  • 권한 모델의 source of truth를 정한다.
  • index metadata 생성과 권한 변경 이벤트를 연결한다.
  • 검색 후 서버에서 한 번 더 권한을 확인한다.
  • 권한 경계 eval을 만든다.

최신 문서보다 오래된 Chunk가 더 높은 점수

벡터 유사도는 최신성을 자동으로 보장하지 않는다. 오래된 문서가 질문과 더 비슷하면 더 높은 점수를 받을 수 있다.

대응:

  • updated_at과 document version을 ranking에 반영한다.
  • 폐기된 문서를 index에서 제외한다.
  • 답변에 문서 버전을 표시한다.
  • 최신성 관련 eval case를 둔다.

Streaming Partial Output 저장

streaming 중 연결이 끊겼는데 부분 응답을 성공 결과로 저장하면 사용자는 깨진 답변을 보게 된다.

대응:

  • stream 상태를 in_progress, completed, aborted로 분리한다.
  • 완료 marker를 받은 뒤에만 최종 저장한다.
  • partial은 별도 임시 저장소에 둔다.
  • 사용자 취소와 네트워크 실패를 구분한다.

Agent Loop 무한 반복

agent가 목표를 달성하지 못하고 같은 tool을 계속 호출할 수 있다.

대응:

  • max steps
  • max tool calls
  • max cost
  • 반복 tool call 감지
  • human handoff

외부 Tool 결과의 Prompt Injection

tool이 가져온 웹 문서, 티켓, 사용자 입력 안에 악성 지시가 들어 있을 수 있다.

대응:

  • tool result를 데이터로 감싼다.
  • system instruction보다 tool result가 우선하지 않게 한다.
  • 민감 tool 호출 전에 서버 검증을 둔다.
  • prompt injection eval을 만든다.

실전 팁

  • 드문 사고는 장애 후에야 찾으면 늦다. 설계 리뷰 체크리스트에 넣는다.
  • RAG는 삭제와 권한 변경 테스트가 꼭 필요하다.
  • agent는 write tool을 연결하기 전 read-only로 충분히 관찰한다.
  • 로그 비용도 장애로 취급한다.

위험 신호!

  • embedding model version을 저장하지 않는다.
  • vector index 삭제 절차가 없다.
  • write tool retry가 공통 retry 정책을 그대로 탄다.
  • agent loop 제한이 없다.
  • observability tag에 원문 텍스트가 들어간다.

확인 질문

확인 질문

  • embedding 모델 변경 시 왜 재색인이 필요한가?
    • 새 embedding과 기존 embedding이 같은 의미 공간에 있다고 보장할 수 없기 때문이다.
  • vector index에 삭제된 chunk가 남으면 어떤 사고가 나는가?
    • 오래된 정보와 개인정보, 권한 없는 문서가 계속 검색될 수 있다.
  • agent loop에 max step이 필요한 이유는 무엇인가?
    • 반복 tool 호출로 비용과 side effect가 계속 증가하는 것을 막기 위해서다.

참고 문서