🧑🏻💻 Ep.32 | AI 장애는 어떻게 복구할까
금요일 저녁 7시 42분, “같은 쿠폰이 두 장 왔다”는 문의가 들어왔습니다. 처음에는 상담원 실수라고 생각했어요. 4분 뒤 비슷한 문의가 세 건 더 생겼고, 대시보드에서는 AI의 도구 호출 재시도가 평소의 여섯 배로 뛰었습니다.
검색 시스템이 느려지자 답변 생성이 타임아웃 났고, AI는 쿠폰 발급까지 실패한 것으로 판단해 전체 작업을 다시 시도하고 있었습니다. 첫 발급은 이미 성공했는데 응답만 잃어버린 요청들이었어요.
팀 채널에는 원인 가설이 쏟아졌습니다. 그때 필요한 질문은 따로 있었습니다.
“설명은 조금 뒤에 해도 됩니다. 지금 무엇부터 멈출까요?”
장애 대응의 첫 번째 결과물은 근사한 원인 분석이 아니라, 더 이상 피해가 늘지 않는 상태입니다.
※ 이 글의 시각·건수·재시도 수치는 장애 대응 패턴을 설명하기 위해 재구성한 가상 시나리오입니다.
1. 첫 5분: 가장 위험한 손부터 묶는다
오후 7시 47분, 팀은 AI 전체를 내리는 대신 쿠폰 발급 도구만 막았습니다. 상담 답변 초안과 주문 조회는 유지했어요. 고객센터에는 “쿠폰 자동 발급 일시 중지, 수동 확인 필요”라는 공지를 보냈습니다.
전체 기능을 끄면 단순 문의까지 멈추고 상담량이 폭증합니다. 반대로 답변만 막고 실행 도구를 열어두면 피해는 계속됩니다. 그래서 기능을 위험 단위로 끌 수 있어야 합니다.
✔️ 외부 상태를 바꾸는 도구
✔️ 사용자에게 바로 전송하는 답변
✔️ 특정 모델이나 프롬프트 버전
✔️ 검색·기억 같은 컨텍스트 기능
평소에는 하나의 AI 기능처럼 보여도 장애 때는 따로 멈출 수 있어야 합니다. “FAQ 링크만 제공”, “초안만 생성”, “사람 확인 후 실행” 같은 축소 모드도 미리 평가해둡니다. 사고 중에 처음 만드는 대체 흐름은 또 다른 사고가 되기 쉽습니다.
2. 다음 5분: 장애의 층을 분리한다
AI 장애라는 말은 너무 큽니다. 같은 ‘잘못된 답변’도 원인이 다릅니다.
근거 문서를 못 찾았는지, 모델이 찾은 근거를 잘못 읽었는지, JSON 출력이 깨졌는지, 도구가 같은 요청을 두 번 실행했는지 나눠 봅니다. 지연과 비용 폭증도 별도 층이고요.
이번 사고에서는 모델이 쿠폰을 두 번 제안한 게 아니었습니다. 실행 API의 응답을 받지 못한 오케스트레이터가 작업 전체를 새 ID로 다시 시작한 것이 원인이었습니다. 모델 답변만 살폈다면 한참 엉뚱한 곳을 봤을 겁니다.
요청 하나를 따라갈 수 있는 공통 ID가 중요합니다. 사용자 질문, 검색 결과, 모델·프롬프트 버전, 도구 호출, 외부 시스템의 처리 결과가 이어져야 합니다. 그래야 “모델이 틀렸다”는 큰 문장을 실제 실패 지점으로 좁힐 수 있습니다.
3. 10분 뒤: 재현에 필요한 것만 보존한다
오후 7시 53분부터 문제 요청의 실행 묶음을 따로 보존했습니다. 당시 모델과 프롬프트, 검색 버전, 도구 입력, 작업 ID, 타임아웃 시각이 대상이었습니다.
여기서 당황한 팀이 흔히 하는 실수가 있습니다. “일단 전부 저장하자”는 겁니다. 고객 대화와 개인정보를 제한 없이 복사하면 장애 조사 저장소가 새로운 보안 위험이 됩니다.
재현에 필요한 필드와 기간을 정하고 민감 정보는 가립니다. 접근 권한도 사고 대응자에게만 좁힙니다. 원본 기록을 임의로 고치지 않고, 분석용 복사본에는 생성 시각과 출처를 남깁니다.
정확한 실행 묶음이 있으면 정상 요청과 비교할 수 있습니다. 무엇이 달랐는지 찾고, 수정한 뒤 같은 조건에서 실패가 사라졌는지 확인할 수 있고요. 데이터가 많아서가 아니라 연결돼 있어서 쓸모 있는 증거입니다.
4. 재현과 재실행은 전혀 다른 일이다
팀은 타임아웃 상황을 재현하기 위해 당시 요청을 테스트 환경에서 다시 돌렸습니다. 답변 생성과 도구 선택까지만 재생했고 실제 쿠폰 API는 가짜 구현으로 바꿨어요.
이 구분이 중요합니다. AI의 판단을 다시 계산하는 재현과 외부 부작용을 다시 만드는 재실행은 다릅니다. 운영 요청을 통째로 재생하면 쿠폰·메일·환불이 한 번 더 일어날 수 있습니다.
미처리 요청을 복구할 때도 먼저 외부 시스템의 현재 상태를 확인합니다. 응답을 잃었다고 실행이 실패한 것은 아니기 때문입니다. 고유 작업 키로 이미 처리된 요청은 결과만 읽고, 실제로 미처리된 요청만 별도 승인을 거쳐 실행합니다.
💡 타임아웃은 “실패”가 아니라 “결과를 아직 모름”일 수 있습니다. 모르는 상태에서 같은 부작용을 다시 만들지 않아야 합니다.
5. 복구와 보상은 나눠서 생각한다
오후 8시 02분, 중복 발급은 멈췄습니다. 그렇다고 장애가 끝난 건 아니었습니다. 이미 쿠폰을 두 장 받은 고객, 쿠폰 발급을 기다리던 고객, 잘못된 상태를 본 상담원이 남아 있었어요.
시스템을 정상으로 돌리는 일과 영향을 받은 사용자를 바로잡는 일은 별도 작업입니다. 누가 몇 장을 받았는지 범위를 확정하고, 회수할지 그대로 인정할지 정책 담당자와 결정합니다. 회수 자체가 또 다른 사용자 피해를 만들 수 있으니 기술팀이 임의로 정하지 않습니다.
고객센터에는 영향 범위와 임시 안내를 계속 갱신합니다. 내부 대시보드가 초록색이 됐다는 사실보다 현장에서 무엇을 말해야 하는지가 중요합니다.
장애 기록에는 기술 원인뿐 아니라 사용자에게 어떤 결과가 갔고 어떻게 바로잡았는지를 남깁니다. 시스템 복구 시각과 사용자 영향 종료 시각은 다를 수 있습니다.
6. 다시 켜는 기준은 미리 검증한다
수정은 단순했습니다. 쿠폰 요청에 같은 작업 키를 유지하고, 결과를 모르는 타임아웃은 외부 상태를 조회한 뒤 처리하도록 바꿨습니다. 단순하다고 바로 전부 켜지는 않았습니다.
타임아웃 재현 테스트에서 중복이 없는지, 쿠폰 도구를 끈 축소 모드가 정상인지, 미처리 요청 목록이 정확한지 확인했습니다. 내부 계정과 소량 트래픽부터 열고 중복률·타임아웃·이관률을 관찰한 뒤 범위를 넓혔고요.
재개 조건에는 기술 지표와 운영 준비가 함께 들어갑니다. 고객센터가 바뀐 동작을 알고 있는지, 피해 사용자 처리 방침이 정해졌는지, 다시 이상해지면 즉시 끌 담당자가 있는지도 확인합니다.
7. 사고를 다음 제품의 기준으로 돌려보낸다
사고 뒤에는 처음 제품의 약속으로 돌아갑니다. “같은 승인 작업은 한 번만 외부 효과를 만든다”는 조건을 평가셋과 운영 경보, 도구 계약에 모두 넣습니다. 포스트모템이 문서에서 끝나지 않고 다음 실패를 막는 시스템으로 들어가야 합니다.
✅ AI 장애가 특별해 보여도 복구의 중심은 익숙합니다. 피해를 먼저 제한하고, 정확한 실행을 재현하며, 부작용은 함부로 재생하지 않고, 검증된 작은 범위부터 다시 여는 것입니다.
오후 8시를 넘겨서야 팀은 원인을 한 문장으로 설명할 수 있었습니다. 다행히 그보다 먼저 쿠폰 발급은 멈춰 있었습니다. 장애 대응에서는 그 순서가 맞습니다.
🌱 장애의 처음과 끝을 함께 보는 개발자들이 모인 곳, 루퍼스
교과서의 복구와 실제 금요일 저녁의 복구는 다릅니다. 현업에서 겪은 장애와 운영의 판단을 함께 나누고 싶다면 루퍼스에서 시작해보세요 🙌
AI 시대에도 결국 중요한 건 생각하는 힘과 성장하는 환경이라고 믿습니다.
루퍼스에는 성장에 진심인 800+명의 크루가 함께하고 있습니다. 현업에서 부딪히는 고민과 경험을 나누며 함께 성장하는 크루들의 이야기. 전액 기부 강의 그리고 다양한 오프라인 네트워킹까지! 루퍼스는 개발자를 위한 지속 가능한 성장을 만들어 갑니다.
📢 LOOPERS의 소식이 궁금하다면?
Share article