grep

SRE 업무에 AI 녹여내기 — 2편: Alert Adviser로 장애 원인 분석 자동화

여기어때

2026년 8월 24일

원문에서 보기 ↗

SRE 업무에 AI 녹여내기 --- 2편: Alert Adviser로 장애 원인 분석 자동화

글. 구혜준(Hazel) / SRE팀 이 글은 2부작입니다.

(1/2) AI는 읽고, 코드는 계산합니다 --- Smart RI Calc (2/2) 틀린 걸 없애기보다, 틀린 게 보이게 --- Alert Adviser (현재 글)

안녕하세요, 여기어때컴퍼니 SRE팀에서 클라우드 엔지니어링 업무를 담당하고 있는 헤이즐입니다.

1편(Smart RI Calc)에 이어, 이번 글에서는 Grafana 알림을 AI가 분석해 원인과 영향 범위를 추적하고 조치 가이드를 제시하는 Alert Adviser 구축 과정을 공유합니다.

1. 왜 필요했을까?

기존에는 알림이 울리면 해당 개발팀 온콜 담당자가 태그되고, 담당자가 손으로 대시보드와 로그를 뒤져 원인을 파악한 뒤 Resolved로 바뀌면 상황이 정리되곤 했습니다.

하지만 알림이 왔을 때 상황을 알아야 하는 사람은 온콜 담당자만이 아닙니다. QA, 타 연관 서비스 개발팀, SRE팀 모두가 에러의 원인과 영향 범위를 빠르게 알아야 각자의 위치에서 대응할 수 있습니다.

원인을 파악하는 속도도 문제였습니다. 장애 지점이 여러 서비스에 걸쳐 특정하기 어렵거나, 담당자가 인프라 맥락에 익숙하지 않으면 장애 해결 시간(MTTR)은 그만큼 늘어났습니다.

그래서 알림이 오는 순간 AI가 1차 관측 데이터를 먼저 추적·조사하고, 사람은 검증된 리포트 위에서 바로 대응을 시작하도록 분석 봇을 만들었습니다.

2. 어떻게 동작하나

가장 접근하기 쉬운 Slack을 1차 인터페이스로 잡고 분석 봇을 구성했습니다. Alert Adviser 서비스 플로우

  1. 수신 및 분류--- 봇을 모니터링 채널에 초대해 Slack Socket Mode로 Grafana 알림을 실시간으로 받고, 전용 분석 채널로 복제해 올립니다. 원본 채널에는 알림만 남고 분석 메시지는 복제본의 스레드에 쌓입니다. 기존 온콜 대응 흐름을 방해하지 않으면서 분석만 덧붙이려는 구조입니다. 알림 서식 16종 중 분석할 수 있는 12종을 골라 Namespace, Pod, Job 등 메타데이터를 뽑습니다.

(※ 본문의 모든 캡처 화면은 보안을 고려해 Mock 데이터를 적용했습니다.) 분석 채널로 복제된 알림과 분석 진행 상태

2. 노이즈 필터링 --- 테스트 알림은 걸러내고, 같은 문제(Pod + 알림 타입, 1시간 이내)는 기존 스레드로 묶습니다. 3회 이상 반복 수신 시 AI 분석을 생략하고 카운트만 올립니다.

3. 데이터 조회 --- AI가 알림 텍스트만 보고 추측하지 않도록, Grafana MCP로 Mimir, Loki, Tempo, 배포 어노테이션 지표를 직접 조회해 원인을 분석합니다.

4. 리포트 게시 & 상세 분리 --- 심각도, 1순위 추정 원인, 요약을 스레드에 올리고 나머지는 네 개의 버튼으로 나눴습니다. [상세 분석]은 원인 후보와 근거를, [더 파보기]는 확인 명령어와 추적 가이드를 보여줍니다. [쉬운설명]은 비개발 직군도 읽을 수 있게 풀어 쓴 요약이고, [도움말]은 봇 사용법 안내입니다. 한 화면에 다 쏟아붓지 않고 필요한 사람이 필요한 깊이만 열어보게 했습니다. 스레드에 게시된 기본 분석 카드

5. 스레드 조치 & MTTR 집계 --- 스레드 댓글로 질문하면 AI가 MCP로 추가 조사해 답변합니다. 문제가 해결되면 체크 리액션으로 해결 상태를 표시하고, MTTR은 Grafana의 Firing → Resolved 시각을 기준으로 자동 집계됩니다.

구성

봇은 단일 EC2 위에서 동작합니다. 백엔드는 Go로 작성해 Slack Socket Mode로 알림을 받고, 전용 대시보드는 React로 만들어 같은 서버에서 서빙합니다. 기존 알림 인프라는 그대로 둔 채 Slack에 봇 하나만 붙이려던 구조이기에 별도 인프라를 늘리지 않았습니다.

MCP(Model Context Protocol)란?

AI가 외부 도구를 표준화된 방식으로 호출하도록 정의한 규약입니다.
기존에는 개발자가 도구마다 호출 코드를 짜고 무엇을 조회할지도 정해줘야 했다면,
MCP는 설정 파일에 서버만 등록하면 AI가 도구 목록을 읽고 필요한 것을 직접 고릅니다.
연동 코드가 필요 없는 대신, 어떤 도구를 노출할지는 목록으로 통제해야 합니다.

핵심은 MCP입니다. Grafana를 연결하는 데 든 건 설정 파일 한 줄이었습니다. 다만 AI에게 모든 도구를 열어주지는 않았습니다. 호출 가능한 도구를 화이트리스트로 제한해 조회 전용 27종 만 등록했고, 클러스터에 직접 접근하거나 상태를 바꾸는 도구는 목록에 아예 없습니다. 권한을 프롬프트로 부탁하는 대신 구조적으로 차단한 것입니다. Alert adviser 아키텍처 다이어그램

3. AI가 틀리는 상황을 어떻게 통제할 것인가?

실제로 개발 과정에서 이런 일이 있었습니다. 한 지연 장애에서 AI가 "DB UPDATE 쿼리 68초"를 원인으로 지목했으나, 실제 원인은 외부 검색 엔진에 수십 건의 요청을 순차 호출하던 백엔드 로직이었습니다. 수치는 진짜 데이터였지만 인과관계가 완전히 틀린 오답이었죠.

장애 대응에서 그럴듯하게 틀린 분석은 없는 것보다 나쁩니다. 대응 방향을 엉뚱한 곳으로 끌고 가 해결 시간을 오히려 늘리기 때문입니다. 이런 오판을 막기 위해 AI 분석 결과를 어디까지 믿을지 정하는 세 가지 통제 장치를 넣었습니다.

① 근거 등급과 출처의 코드 강제

AI가 지목한 원인에는 근거의 강도와 출처가 함께 붙습니다. 로그에서 직접 확인되면 로그·확정, 메트릭 추이로 뒷받침되면 메트릭·유력, 맥락 추정이면 추측입니다.

중요한 점은 AI가 붙인 등급을 그대로 쓰지 않고, 백엔드 코드가 한 번 더 검증한다는 것입니다. 근거 문장에 단위가 붙은 실측 수치가 들어 있는지, 추정 어투가 섞이지는 않았는지를 정규식으로 확인합니다.

// 단위가 붙은 실측 수치가 있는가
var dataEvidenceRe = regexp.MustCompile(
    `\d+(\.\d+)?\s*(%|ms|m|Mi|Gi|MB|GB|개|건|초|회|pods?|replicas?|bytes?)`)

// 추정 어투가 섞여 있는가
var speculativePatterns = regexp.MustCompile(
    `(?:추정|추측|가능성|것으로 보[임인]|시사|의심|수 있[음다]|으로 보[임인])`)

AI가 "확정"이라고 답해도 근거 문장이 이 검사를 통과하지 못하면 코드가 등급을 내립니다. 수치와 추정 어투가 한 문장에 같이 있으면 추정 쪽이 이깁니다. "500MB 증가한 것으로 보임"은 수치가 있어도 추측으로 내려갑니다. 트레이스를 조회하지 않은 프론트엔드 레이어 등은 unknown으로 남고, 화면에는 "미확인"으로 표시됩니다. [상세 분석] --- 원인 후보마다 근거 등급과 출처가 붙습니다

② 변경성 권한 차단

kubectl delete, scale 같은 변경성 명령어는 분석 응답에서 통째로 뺍니다. 롤백 판단, 장애 등급 확정, 에스컬레이션 문구도 자동으로 걸러 [판단 제외 --- 담당 조직 영역]으로 바꿉니다.

아래 [더 파보기] 화면에서 조회 명령어만 남고 변경 명령어 자리에 "없음(읽기 전용)"이 뜨는 게 그 결과입니다. 다만 값을 제안하는 것과 그 값을 적용하는 것은 다릅니다. AI는 근거와 함께 리소스 조정안까지 내놓되, 반영 여부는 담당 조직이 판단합니다. [더 파보기] --- 조회 명령어는 남고 변경성 명령어는 제거된 상태

③ 오판 패턴을 검증 규칙으로

운영하면서 AI가 틀린 분석을 내놓을 때마다 원인을 되짚어 프롬프트에 검증 규칙을 하나씩 추가했습니다. 어디서 틀렸는지는 분석 카드의 "부족함" 피드백과 개발자가 남긴 실제 해결 댓글에서 확인했습니다.

4. 왜 사내 문서 검색을 걷어냈나

관측 데이터만으로 메워지지 않는 추측이 있습니다. "이 서비스는 배치 시간에 인프라 지표가 튄다", "저 알림은 임계치가 낮아 원래 자주 울린다"처럼 메트릭에는 남지 않고 사람만 아는 조직 지식입니다. 이런 맥락을 넣어주면 추측이 줄어들 것이라 보고, 처음에는 사내 Confluence 문서를 벡터 스토어에 임베딩하는 자체 RAG를 구상했습니다.

첫 번째 벽은 데이터였습니다. 대상 문서 400여 건을 살펴보니 팀마다 서식이 제각각이었고, 표와 이미지에 정보가 들어간 경우도 많았습니다. 검색할 수 있는 형태로 만들려면 파싱과 정제부터 손봐야 했는데, 그 작업량이 알림 분석 봇 본체보다 커 보였습니다. 봇을 만들려다 검색 인프라를 만들게 되는 상황이라 자체 구축은 접었습니다.

대신 사내 공통플랫폼 조직에서 이미 만들어둔 RAG 도구가 MCP로 열려 있어 이를 활용했습니다. 정제와 인덱싱 부담 없이 검색만 가져다 쓸 수 있었습니다. 그런데 문제는 그다음이었습니다. 검색해 온 문서를 넣을수록 분석 품질이 오히려 나빠졌습니다.

서비스명으로 검색하면 이름만 같은 다른 팀 문서가 딸려오고, 증상 키워드로 검색하면 구축 가이드나 네이밍 정책 같은 범용 문서가 상위로 올라왔습니다. 그래서 필터를 세 겹으로 붙였습니다. 제목에 "구축 가이드", "네이밍 정책" 같은 범용 문서 패턴이 있으면 제외하고, 서비스명이 제목·경로·본문에 있거나 증상 키워드와 장애성 제목이 함께 걸릴 때만 통과시킨 뒤, 남은 다섯 건은 AI에게 다시 관련성을 검토하게 했습니다.

그런데도 무관한 문서는 계속 섞였습니다. 필터가 확인하는 건 문서에 서비스명이 들어 있는지였는데, 정작 필요한 건 그 문서가 이 장애의 근거가 되는지였습니다. 다른 팀 문서에 우리 서비스명이 한 번만 나와도 통과했습니다. 제외 패턴도 겪어본 유형을 하나씩 추가하는 식이라 새로운 유형은 매번 뚫렸고, 조건을 조이면 이번엔 필요한 문서까지 떨어졌습니다.

무관한 문서가 프롬프트에 들어가면 AI는 그걸 근거로 삼아 답을 만듭니다. 그래서 문서 검색은 걷어냈습니다. 지금은 관측 데이터만으로 분석합니다.

확실성이 담보되지 않은 정보는 추측을 줄이는 게 아니라, 추측을 사실처럼 보이게 만드는 재료가 됩니다.

5. 실전 원인 분석 정확도는 얼마나 나왔을까?

알림 스레드에 달린 실제 해결 댓글과 AI 분석 결과를 건별로 수동 대조해 판정했습니다. 판정 기준은 세 단계입니다. 일치 는 개발자가 내린 결론과 원인이 같은 경우, 부분 일치는 현상과 영역은 맞았지만 근본 원인까지 도달하지 못한 경우, 불일치는 다른 원인을 1순위로 지목한 경우입니다.

분석 결과가 남은 20건 중 일치 14건, 부분 일치 4건, 불일치 2건이었습니다. 표본이 크지 않아 비율보다는 어떤 유형에서 맞고 틀렸는지가 더 의미 있었습니다.

잘 맞힌 14건은 공통점이 뚜렷했습니다. 관측 데이터에 흔적이 남는 유형이라는 점입니다. 외부 API 타임아웃은 트레이스에 예외 스택트레이스가 그대로 남아 있었고, 시크릿 값이 치환되지 않은 설정 오류는 로그에 리터럴 문자열이 그대로 찍혀 있어 AI가 정확히 짚어냈습니다.

못 맞힌 6건은 반대였습니다. 한 건은 AI가 "타임아웃이 아닌 애플리케이션 내부 예외"까지는 정확히 판정했지만, 실제 원인인 날짜 비교 로직의 NPE(Null Pointer Exception)까지는 도달하지 못했습니다. AI는 코드를 조회하지 않으니 예상했던 한계입니다. 불일치 2건은 둘 다 API Gateway 타임아웃이었는데, AI가 클러스터 안에서 원인을 찾는 동안 실제 범인은 밖에 있었습니다. 한 건은 노드 교체를 지목했지만 개발자는 외부 파트너 API 지연을, 다른 한 건은 DB 풀스캔을 지목했지만 실제로는 취소 수수료 조회 타임아웃이었습니다. 정리하면 메트릭·로그·트레이스에 증거가 남는 장애는 잘 맞히고, 코드 내부나 조회 불가 영역으로 갈수록 약해집니다.

이 경계를 아는 것이 정확도 숫자보다 중요했습니다. 어디까지 믿고 어디부터 사람이 봐야 하는지가 여기서 정해지기 때문입니다.

그래서 인상적이었던 건 틀린 케이스보다 "모른다"고 답한 케이스였습니다. 레거시 Grafana가 모니터링하는 EC2 인스턴스의 디스크 알림에서, AI는 조회 가능한 EKS 노드가 모두 정상(최대 49.5%)임을 확인한 뒤 "해당 데이터소스에 접근할 수 없어 90% 초과 인스턴스를 특정하지 못했다"고 그대로 보고했습니다. 실제로 그 인스턴스에서는 오래된 로그 파일이 쌓여 있었고 담당자가 정리해 88%로 낮췄습니다. AI가 닿을 수 없는 영역이었지만, 닿을 수 없다는 사실 자체를 정확히 말해준 덕분에 사람이 바로 그쪽을 확인할 수 있었습니다.

6. 어떤 알림까지 분석할 것인가

분석 대상 알림은 "Grafana MCP로 데이터를 정상 조회할 수 있는가"를 기준으로 EKS 4종과 애플리케이션·인프라 8종, 총 12종을 골랐습니다. RDS CPU나 Redis Engine CPU처럼 Grafana MCP가 접근할 수 있는 데이터소스에 연동돼 있지 않은 알림은 제외했습니다. 데이터 없는 조사는 추측으로 이어지기 때문에, 지원하지 못하는 영역을 분명히 그어두는 것도 시스템 신뢰성의 일부입니다.

이렇게 선별한 알림의 분석 결과는 Slack 스레드에 쌓입니다. 다만 Slack은 실시간 수신에는 좋아도 이력 추적과 통계 확인에는 한계가 있어 별도 대시보드를 구축했습니다. 전체 통계와 분석 실패 건수, 24시간 내 5회 이상 발생한 만성 알림, 동시 발생 알림 연관성을 보여주며, 특히 인프라 ➔ DB ➔ 백엔드 ➔ API ➔ 프론트엔드 ➔ 사용자로 이어지는 영향 경로 시각화를 통해 에러 지점과 영향 범위를 한눈에 파악할 수 있습니다. 조회하지 않은 구간은 "미확인"으로 구분됩니다. 대시보드 통계 (Mock 데이터 기준)장애 영향 경로 --- 조회하지 않은 구간은 "미확인"으로 구분됩니다

7. 원인이 아니라 영향에서 출발하기 --- Alert Bridge

"이 장애, 사용자한테는 어떻게 보이는 거예요?"

Alert Adviser를 개발하던 중 QA팀과 협업하며 서로의 고충을 접했습니다. QA는 사용자 화면 에러의 백엔드 원인을 몰라 여러 팀을 오가며 확인해야 했고, 인프라와 DB 담당자는 백엔드 장애가 사용자 화면에 어떤 영향을 주는지 가늠하기 힘들었습니다.

Alert Adviser가 알림을 받아 "왜 났는가"를 파고든다면, Alert Bridge는 "어느 화면까지 번지는가"에서 출발합니다. 그래서 알림 자체를 새로 정의했습니다.

QA팀에게서 에러가 나면 사용자 화면에 영향이 큰 백엔드 API 목록과, 각 API가 어느 화면에 쓰이는지 정리한 매핑 문서를 받았습니다. 이를 기준으로 에러율·응답 지연 SLO Alert Rule을 다듬고 분석을 연동했습니다(주요 라우트 13개, 룰 3종). Alert Adviser 와 Alert Bridge

Alert Bridge 상세분석

아직 도입 초기라 MTTR 개선 같은 정량 효과를 말하기에는 이릅니다. 다만 알림을 보는 기준이 인프라 지표에서 사용자 화면으로 옮겨졌고, 하나의 알림을 QA·인프라·DBA가 각자의 할 일로 나눠 읽게 됐습니다. 효과는 알림이 충분히 쌓인 뒤 Alert Adviser와 같은 방식으로 건별 대조해 판정할 계획입니다.

마치며

이번 프로젝트를 진행하며 얻은 가장 큰 결론은 이것입니다.

"AI 분석 시스템의 신뢰성은 AI의 성능보다, 불확실한 데이터와 권한을 어떻게 통제하느냐에 달려 있다."

추측에는 추측 등급을 강제하고, 변경성 조치는 막으며, 분석 불가능한 영역은 unknown으로 명시하는 통제 장치가 있었기에 실무에서 엔지니어들이 믿고 쓸 수 있는 시스템이 되었습니다.

20건을 대조하며 얻은 것도 정확도 숫자 자체가 아니라 이 시스템을 어디까지 믿어야 하는지에 대한 경계선이었습니다. 정확도를 올리는 일보다 틀렸을 때 그것이 드러나게 만드는 일이 먼저였습니다.

FinOps(Smart RI Calc)부터 Monitoring(Alert Adviser), 그리고 직군을 넘는 협업(Alert Bridge)까지, AI를 명확한 원칙 아래 적용하는 SRE 엔지니어링 실험은 앞으로도 계속됩니다. 읽어주셔서 감사합니다.