기술

AI 분석을 하나로 합치면 안 되는 이유 - 장애 분석 5가지를 각각 다르게 만들었습니다

2026.04.199분 읽기

"AI한테 분석해줘"가 하나로 안 됐습니다

지식그래프에 데이터가 쌓이고 나니까, "이 시스템 복구 플랜 만들어줘", "이거 죽으면 어디까지 영향이야?", "이 서비스 장애 원인이 뭐야?" 같은 분석 요청이 생기기 시작했거든요.

처음에는 하나의 AI 분석 기능으로 다 처리하려고 했습니다. 질문을 LLM에 넘기면 알아서 판단하고 리포트를 만들어주는 구조요. 그런데 실제로 해보니까, 같은 "분석"이라는 이름을 쓰지만 각 분석마다 Neo4j에서 가져와야 하는 데이터가 완전히 달랐어요.

단일 시스템 복구 플랜을 만들려면 그 시스템의 속성, 이웃 노드, 장애 이력, 담당자 정보가 필요합니다. 장애 전파 분석을 하려면 DEPENDS_ON 역방향 BFS 결과 + 영향받는 노드별 장애 이력이 필요하고요. 서비스 원인 추적을 하려면 역방향 의존 체인을 따라가면서 각 노드의 상태를 수집해야 합니다.

LLM한테 "알아서 필요한 데이터를 가져와라"고 맡기면 될 것 같지만, 이미 UI에서 사용자가 "장애 전파 분석을 해줘"라고 선택한 상태거든요. 어떤 분석인지 이미 확정된 건데 LLM한테 다시 판단시킬 이유가 없었습니다.


5가지 Case, 각각 컨텍스트가 다릅니다

분석을 5개로 나눈 기준은 단순합니다. 어떤 데이터를 모아서 LLM에 넣느냐가 다르면 별도 Case입니다.

Case

분석

컨텍스트 수집

LLM 역할

1

단일 복구

시스템 1개의 속성+이웃+장애이력+담당자

복구 절차 작성

2

복합 장애

여러 시스템 동시 장애, 시스템 간 관계

상관관계 분석

3

원인 추적

서비스에서 역방향 의존 체인 추적

근본 원인 추정

4

장애 전파

BFS 전파 결과 + 영향 노드별 이력

복구 우선순위

5

인프라 변경

제거 시 고립 노드 + 끊기는 관계

대체 방안 설계

Case 1은 노드 하나의 컨텍스트를 360도로 모읍니다. Case 3은 역방향 의존 체인을 따라가면서 수집하고요. Case 4는 시뮬레이션 결과 자체가 컨텍스트가 됩니다. 수집 방식이 다르니까 코드도 다르고, LLM에 넣는 프롬프트도 다릅니다.

1.jpeg


확정할 수 있는 건 코드로, LLM에는 판단만

5가지로 나눈 뒤에 각 Case의 구조를 보니까, 패턴이 하나 보였거든요. 모든 Case가 3단계로 동작합니다.

1. 어떤 Case인지 → UI가 확정 (코드)
2. 어떤 데이터를 수집할지 → 파이프라인이 확정 (코드)
3. 수집된 데이터로 리포트 작성 → LLM이 담당

LLM이 하는 일은 3번뿐이에요. 1번과 2번은 코드가 확정합니다.

이 원칙이 이전에 Schema-on-Write에서 적용한 것과 같더라고요. 그때는 "LLM이 추출한 타입을 그대로 쓰지 않고, 코드가 온톨로지 대조해서 걸러낸다"는 원칙이었거든요. 여기서도 마찬가지입니다. LLM에 판단을 넘길수록 불확실성이 커지니까, 확정할 수 있는 건 코드로 확정하고 LLM에는 진짜 판단이 필요한 것만 맡기는 거예요.

에이전트 방식으로 하나의 API에서 LLM이 "이건 장애 전파 분석이니까 BFS를 돌려야겠다"고 자율 판단하게 만들 수도 있습니다. 하지만 UI에서 이미 사용자가 "장애 전파" 버튼을 눌렀는데, LLM한테 다시 판단시키면 불확실성만 추가되는 거거든요.


7개 도구를 조립합니다

5가지 Case를 만들면서 코드가 반복되기 시작했거든요. Case 1에서 노드 컨텍스트를 수집하는 코드가 Case 4에서도 쓰이고, BFS 장애 전파 계산은 시뮬레이션 시각화에서도 쓰입니다.

그래서 반복되는 로직을 도구(Tool)로 분리했습니다.

도구

역할

gather_node_context

노드의 속성, 이웃, 장애이력, 담당자, 문서를 한꺼번에 수집

format_context_sections

수집된 컨텍스트를 마크다운으로 변환

gather_inter_relations

노드 간 직접/간접 관계 조회

gather_trace_context

역방향 의존 체인 수집 (원인 추적용)

cascade_simulation

DEPENDS_ON 역방향 BFS 장애 전파 계산

removal_simulation

노드 제거 시 고립 노드 + 끊기는 관계 탐지

generate_report

LLM에 프롬프트 + 컨텍스트 넣어서 리포트 생성

각 Case는 이 도구들을 다른 조합으로 호출합니다. Case 1은 gather_node_context → format_context_sections → generate_report. Case 4는 cascade_simulation → gather_node_context(영향 노드별) → generate_report. 도구는 같은데 조합이 다른 거예요.

도구로 분리해둔 이유가 하나 더 있어요. 지금은 API가 도구를 고정 순서로 호출하는 파이프라인이지만, 나중에 LangGraph 에이전트로 전환하면 에이전트가 도구를 자율 선택해서 호출하게 됩니다. 도구의 인터페이스(name, description, parameters, returns)가 동일하니까, 호출자만 바뀌고 도구는 그대로 가져갈 수 있거든요.


시뮬레이션은 LLM을 위한 컨텍스트 엔진입니다

Case 4와 5에서 재미있는 구조가 보였거든요. 시뮬레이션과 AI 분석이 연결되는 방식이에요.

그래프 페이지에서 시뮬레이션을 실행하면, 장애 전파 경로나 고립 노드가 시각적으로 보입니다. 여기까지는 Neo4j 그래프 연산이에요. 그런데 시뮬레이션 결과 패널에서 "AI 분석 요청" 버튼을 누르면, 시뮬레이션 결과가 그대로 LLM의 컨텍스트가 됩니다.

시뮬레이션 (그래프 연산)
  → 전파 결과 23개 노드, 깊이별 분포
  → 영향 노드별 장애 이력, 담당자
      ↓ 이 전체가 컨텍스트
  LLM (리포트 생성)
  → 복구 우선순위, 리스크 등급, 권장 조치

시뮬레이션이 "데이터를 구조화해서 LLM에 넘겨주는 엔진" 역할을 하는 거예요. LLM 혼자서는 Neo4j를 탐색할 수 없지만, 시뮬레이션이 탐색 결과를 정리해서 넘겨주면 LLM은 거기서 판단과 작문에 집중할 수 있습니다.

팔란티어도 같은 흐름이더라고요. 온톨로지로 데이터 구조화 → 그래프로 시각화 → 시뮬레이션으로 미래 예측 → AI 분석으로 액션 제시 → Action으로 실행. "데이터 → 시각화 → 시뮬레이션 → 분석 → 실행" 이 흐름 자체가 핵심이었습니다.

2.jpeg


정리하면, 파이프라인은 코드로 짜고 판단만 LLM에 맡깁니다

5가지 분석을 만들면서 정리된 원칙은 결국 하나예요. 확정할 수 있는 건 코드로 확정하고, LLM에는 진짜 판단이 필요한 것만 맡긴다. Case 분기도 코드, 컨텍스트 수집도 코드, 도구 호출 순서도 코드. LLM은 정리된 컨텍스트를 받아서 리포트를 쓰는 역할만 합니다.

이 원칙을 지키면 두 가지가 좋거든요. 디버깅이 쉽습니다. LLM이 이상한 리포트를 만들면, 컨텍스트가 잘못 수집된 건지 프롬프트가 잘못된 건지를 분리해서 확인할 수 있어요. 그리고 나중에 에이전트로 전환할 때 도구를 그대로 가져갈 수 있습니다.

#AI분석#LLM#지식그래프#Neo4j#시뮬레이션#장애분석#AI전환기