본문 바로가기
AI(Artificial Intelligence)

상태 기반 AI Agent를 안정적으로 설계하기 위한 Agent Orchestration Framework, LangGraph

by forward error correction Circle 2026. 6. 8.
반응형

Ⅰ. LangGraph 기술이란?

 ⅰ. 왜 필요한가?
초기 LLM 서비스는 보통 사용자의 질문을 받아 LLM에 전달하고, 응답을 화면에 출력하는 단순한 구조였습니다. 이 방식은 챗봇, 요약, 번역, Q&A처럼 한 번의 요청과 응답으로 끝나는 업무에는 충분합니다. 그러나 실제 업무 자동화로 들어가면 문제가 달라집니다.

 ⅱ. 기존 방식의 한계
   1) LLM 응답이 틀렸을 때 어느 단계에서 문제가 생겼는지 추적하기 어렵습니다.
   2) 외부 API, DB, 파일, 보안 장비를 호출하는 복잡한 작업에서 실행 흐름을 통제하기 어렵습니다.
   3) 승인, 반려, 재시도, 보류 같은 업무 절차를 자연스럽게 넣기 어렵습니다.
   4) 작업 중간에 서버가 재시작되거나 오류가 나면 처음부터 다시 실행해야 합니다.
   5) 여러 Agent가 협업하는 구조에서 상태 공유와 책임 분리가 복잡해집니다.
 ⅲ. 기술 정의
LangGraph는 LangChain 생태계에서 제공하는 상태 기반 그래프 실행 프레임워크입니다. 작업을 여러 개의 노드로 쪼개고, 노드 사이의 이동 조건을 엣지로 정의하며, 모든 단계가 하나의 공유 상태를 읽고 갱신하는 방식으로 동작합니다.

한줄 요약

LangGraph는 LLM Agent의 실행 흐름을 그래프 구조로 모델링하고, 상태 저장·분기·반복·중단·재개·사람 승인·장애 복구를 지원하는 저수준 오케스트레이션 프레임워크입니다.


 ⅳ. LangChain과 LangGraph의 차이
  1) LangChain : 모델, 프롬프트, 도구, 체인, Agent 추상화를 빠르게 조립하기 좋은 개발 프레임워크입니다. 빠른 프로토타입과 다양한 모델·도구 연동에 강합니다.
  2) LangGraph : Agent가 여러 단계를 거치며 오래 실행되고, 상태를 저장하며, 조건에 따라 되돌아가거나 사람 승인을 받아야 할 때 사용하는 실행 런타임입니다. 즉, LangChain이 재료와 도구라면 LangGraph는 업무 프로세스의 배선도와 제어판에 가깝습니다.

Ⅱ. LangGraph 기술 특징

특징 1. 상태 기반 실행
Agent의 현재 질문, 중간 결과, 검색 결과, 도구 실행 결과, 승인 상태, 오류 상태를 하나의 State로 관리합니다. 그래서 각 노드는 필요한 상태를 읽고 필요한 값만 갱신합니다.

특징 2. 노드와 엣지 기반 아키텍처
업무 단계를 노드로 나누고, 다음에 어떤 노드로 갈지 엣지로 정의합니다. 단순 순차 실행뿐 아니라 조건 분기, 반복, 검토, 재시도 흐름을 명확하게 표현할 수 있습니다.

특징 3. Checkpoint 기반 장애 복구
그래프 실행 중간 상태를 체크포인트로 저장할 수 있습니다. 특정 단계에서 실패해도 마지막 정상 상태부터 재개할 수 있어 장기 실행 업무에 유리합니다.

특징 4. Human-in-the-Loop
결재, 보안 조치, 파일 삭제, 방화벽 정책 변경, DB 업데이트처럼 위험도가 높은 작업은 중간에 실행을 멈추고 사람의 승인 후 재개할 수 있습니다.

특징 5. 멀티 Agent 구조에 적합
분석 Agent, 검색 Agent, 검증 Agent, 실행 Agent, 보고서 작성 Agent처럼 역할을 나누고, Supervisor가 전체 흐름을 제어하는 구조를 만들 수 있습니다.

특징 6. 관측성과 디버깅
각 노드의 입력, 출력, 상태 변화, 도구 호출 결과를 추적하면 Agent가 왜 그런 판단을 했는지 분석하기 쉽습니다. 운영 환경에서는 LangSmith나 별도 로그 시스템과 함께 쓰는 것이 좋습니다.

Ⅲ. LangGraph 기술 동작방식

 ⅰ. 구성 요소

구성 설명
State 그래프 전체가 공유하는 데이터 구조입니다. 질문, 검색 결과, 도구 결과, 오류, 승인 상태, 최종 응답 등을 담습니다.
Node 실제 작업을 수행하는 함수입니다. LLM 호출, RAG 검색, 로그 분석, API 호출, 검증, 보고서 작성 등이 노드가 됩니다.
Edge 노드 사이의 이동 경로입니다. 고정 경로뿐 아니라 조건에 따라 다른 노드로 보내는 조건부 엣지를 만들 수 있습니다.
Checkpointer 실행 상태를 저장하고 복원하는 계층입니다. 장기 실행, 장애 복구, 사람 승인, 대화 메모리에 핵심입니다.
Interrupt 실행을 의도적으로 멈추고 외부 입력을 기다리는 기능입니다. 사람이 승인하면 저장된 상태에서 다시 이어서 실행합니다.


 ⅱ. 데이터 흐름
   1) 사용자의 요청이 State에 들어갑니다.
   2) START 지점에서 첫 번째 노드가 실행됩니다.
   3) 노드는 State를 읽고, 필요한 작업을 수행한 뒤 State의 일부 값을 갱신합니다.
   4) Edge 또는 Conditional Edge가 다음 실행 노드를 결정합니다.
   5) 중요한 단계마다 Checkpoint가 저장됩니다.
   6) 사람 검토가 필요한 경우 Interrupt로 멈춘 뒤 승인 결과를 받아 재개합니다.
   7) END에 도달하면 최종 응답 또는 실행 결과를 반환합니다.

Ⅳ. LangGraph 기술 구성 및 흐름도

ⅰ. LangGraph Agent 아키텍처를 기준으로 구성한 흐름도(보안 로그 감사, 장애 대응, 보고서 자동화 같은 실무형 )

 ⅱ. 단계별 처리 흐름
   1) 입력 수집: 사용자 요청, 이벤트, 로그, 알림을 State에 기록합니다.
   2) 분류: 단순 답변, 문서 검색, 외부 조치, 사람 승인 필요 여부를 판단합니다.
   3) 근거 수집: RAG, DB, API, 로그 시스템, 보안 장비에서 데이터를 가져옵니다.
   4) 추론: LLM이 수집된 근거를 바탕으로 분석, 초안, 조치안을 만듭니다.
   5) 검증: 정책 위반, 근거 부족, 위험 조치 여부를 확인합니다.
   6) 승인: 위험 조치라면 사람에게 승인 또는 수정을 요청합니다.
   7) 실행: 승인된 작업만 실제 시스템에 반영합니다.
   8) 기록: 상태, 도구 호출, 최종 결과를 로그와 체크포인트에 남깁니다.

Ⅴ. LangGraph 기술 설치 방법

Python 환경 기준 설치 예시는 다음과 같습니다. 실제 운영에서는 Python 버전, 패키지 버전, LLM Provider SDK, 체크포인터 DB 드라이버를 함께 고정하는 것이 좋습니다.

# 기본 설치
pip install -U langgraph

# LangChain과 함께 사용할 경우
pip install -U langchain langgraph

# 로컬 체크포인트 저장용 SQLite
pip install -U langgraph-checkpoint-sqlite

# 운영 환경 체크포인트 저장용 PostgreSQL
pip install -U langgraph-checkpoint-postgres

# LangSmith 추적을 사용할 경우
pip install -U langsmith

※ 운영 설치 팁
 1) 개발 환경에서는 InMemory 또는 SQLite Checkpointer로 시작해도 됩니다.
 2) 운영 환경에서는 재시작, 장애 복구, 승인 대기, 이력 조회가 필요하므로 PostgreSQL 같은 영속 저장소를 권장합니다.
 3) 패키지는 requirements.txt 또는 pyproject.toml에 버전을 고정합니다.
 4) API Key는 코드에 직접 넣지 말고 환경 변수 또는 Secret Manager로 관리합니다.

Ⅵ. LangGraph 기술 사용 방법

 ⅰ. 가장 단순한 그래프 예시

from langgraph.graph import StateGraph, MessagesState, START, END

def mock_llm(state: MessagesState):
    return {"messages": [{"role": "ai", "content": "hello world"}]}

builder = StateGraph(MessagesState)
builder.add_node("mock_llm", mock_llm)
builder.add_edge(START, "mock_llm")
builder.add_edge("mock_llm", END)

graph = builder.compile()

result = graph.invoke({"messages": [{"role": "user", "content": "hi!"}]})
print(result)

 ⅱ. 실무형 구조 예시: 분류 → 검색 → 분석 → 검토

from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import InMemorySaver

class AgentState(TypedDict):
    question: str
    route: str
    context: str
    answer: str
    risk: str

def classify(state: AgentState):
    question = state["question"]
    if "삭제" in question or "정책 변경" in question:
        return {"route": "human_review", "risk": "high"}
    return {"route": "rag", "risk": "normal"}

def retrieve_context(state: AgentState):
    # 실제로는 문서 DB, Vector DB, 로그 시스템, API 등을 호출합니다.
    return {"context": "관련 운영 문서와 최근 로그를 조회한 결과"}

def reason(state: AgentState):
    # 실제로는 LLM 호출을 통해 근거 기반 답변을 생성합니다.
    return {"answer": f"분석 결과: {state['context']}를 근거로 조치안을 작성했습니다."}

def human_review(state: AgentState):
    return {"answer": "위험도가 높은 요청입니다. 관리자 승인 후 실행해야 합니다."}

def route_after_classify(state: AgentState) -> Literal["rag", "human_review"]:
    return state["route"]

builder = StateGraph(AgentState)
builder.add_node("classify", classify)
builder.add_node("retrieve_context", retrieve_context)
builder.add_node("reason", reason)
builder.add_node("human_review", human_review)

builder.add_edge(START, "classify")
builder.add_conditional_edges(
    "classify",
    route_after_classify,
    {
        "rag": "retrieve_context",
        "human_review": "human_review",
    },
)
builder.add_edge("retrieve_context", "reason")
builder.add_edge("reason", END)
builder.add_edge("human_review", END)

checkpointer = InMemorySaver()
graph = builder.compile(checkpointer=checkpointer)

config = {"configurable": {"thread_id": "incident-2026-0001"}}

result = graph.invoke(
    {
        "question": "최근 보안 로그를 분석해서 조치안을 만들어줘",
        "route": "",
        "context": "",
        "answer": "",
        "risk": "",
    },
    config=config,
)

print(result["answer"])


 ⅲ. 운영 시 고려사항
  1) State 설계: State가 너무 크면 디버깅과 저장 비용이 증가합니다. 필요한 값만 구조화해서 저장합니다.
  2) 노드 책임 분리: 하나의 노드가 분류, 검색, 판단, 실행을 모두 하면 장애 분석이 어렵습니다.
  3) 외부 조치 통제: 방화벽 변경, 계정 잠금, DB 업데이트 같은 조치는 반드시 승인 노드를 둡니다.
  4) 재시도 정책: LLM 호출 실패, API Timeout, Rate Limit에 대한 재시도와 중단 기준을 정합니다.
  5) 관측성: 노드별 입력, 출력, 실행 시간, 오류, 토큰 사용량을 남깁니다.

Ⅶ. LangGraph 자주 쓰는 명령어와 사례

명령어 설명
pip install -U langgraph 패키지 설치
pip freeze > requirements.txt 운영용 의존성 저장
LangSmith 추적 환경 변수 export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY="your_api_key"
그래프 실행 시 thread_id 지정 config = {"configurable": {"thread_id": "user-or-task-id"}}
graph.invoke(input_state, config=config)

Ⅷ. LangGraph 활용방안

 ⅰ. 실제 적용 사례

1) 보안 로그 감사 Agent
Windows Event Log, Linux auth.log, 방화벽 로그, WAF 로그를 수집해 이상 징후를 분류하고, 위험도가 높은 이벤트는 보안 담당자 승인 후 차단 정책 초안을 생성합니다.

2) 장애 대응 Agent
Zabbix, Prometheus, Grafana Alert를 입력으로 받아 원인 후보를 분류하고, 최근 변경 이력과 로그를 조회한 뒤 조치 순서를 제안합니다.

3) ISMS 운영 자동화 Agent
정책 문서, 증적, 점검 결과를 기반으로 통제 항목별 미흡 사항을 분류하고 보완 조치 보고서를 생성합니다.

4) 보고서 자동 작성 Agent
자료 수집, 근거 요약, 목차 생성, 초안 작성, 검토, 최종 HTML 변환까지 단계별로 자동화합니다.


 ⅱ. 대안 기술 비교

구분 주요 장점 적합한 경우
LangGraph 상태 기반 흐름 제어, 체크포인트, 사람 승인, 복잡한 분기와 반복 처리에 강합니다. 운영 자동화, 보안 조치, 장기 실행 Agent, Multi-Agent 제어에 적합합니다.
LangChain Agent 빠른 개발, 모델·도구 연동 편의성, 범용 생태계가 강합니다. 간단한 Tool Calling, 챗봇, RAG 기반 질의응답에 적합합니다.
CrewAI 역할 기반 Multi-Agent를 빠르게 구성하기 좋습니다. 조사 Agent, 작성 Agent, 검토 Agent처럼 역할 분담이 명확한 업무에 적합합니다.
AutoGen 계열 여러 Agent의 대화형 협업과 연구·실험형 Multi-Agent 패턴에 강합니다. Agent 간 토론, 코드 생성, 시뮬레이션, 실험적 자동화에 적합합니다.
n8n·Dify 같은 Low-code 도구 화면 기반으로 빠르게 워크플로우를 만들고 외부 SaaS와 연결하기 쉽습니다. 비개발자 중심 자동화, 단순 업무 연결, 빠른 PoC에 적합합니다.

 ⅲ. 언제 쓰면 안 되는가?
   1) 단순 Q&A, 요약, 번역처럼 한 번의 LLM 호출로 충분한 경우.
   2) 모든 흐름이 완전히 결정적이고 LLM 판단이 필요 없는 경우.
   3) 초저지연 응답이 중요한데 여러 노드와 도구 호출이 지연을 크게 늘리는 경우.
   4) 상태 저장, 로그, 권한 통제 없이 Agent에게 실제 시스템 변경 권한을 주려는 경우.
   5) 운영팀이 Agent의 실패 시나리오를 감당할 준비가 안 된 경우.

Ⅸ.  주의해야 할 점

ⅰ. 설계 단계 주의사항
1) LLM에게 흐름 제어를 전부 맡기지 않습니다. LLM은 판단을 보조하고, 실제 흐름 제어는 그래프와 정책 코드가 담당해야 합니다.
2) 노드는 작고 명확해야 합니다. 노드 하나가 너무 많은 일을 하면 재시도, 장애 분석, 비용 측정이 어렵습니다.
3) State는 계약서처럼 설계합니다. 어떤 키가 있고, 어떤 노드가 어떤 값을 갱신하는지 명확해야 합니다.
4) 조건 분기는 코드로 검증합니다. “LLM이 알아서 판단하겠지”라는 구조는 운영에서 사고로 이어지기 쉽습니다.
5) 승인 노드를 아끼지 않습니다. 보안, 비용, 데이터 변경, 외부 발송은 사람 승인 또는 정책 승인 단계를 둡니다.

 

ⅱ. 운영 단계 주의사항
1) 외부 시스템 호출은 멱등성을 고려합니다. 재시도 시 같은 계정 잠금, 같은 티켓 생성, 같은 방화벽 정책 추가가 중복으로 발생할 수 있습니다.
2) 도구 권한은 최소 권한으로 제한합니다. 읽기 전용 도구와 쓰기 도구를 분리하고, 쓰기 도구는 승인 후 실행합니다.
프롬프트 인젝션을 전제로 설계합니다. 이메일, 문서, 웹 페이지, 로그 안의 문장을 시스템 지시로 신뢰하지 않습니다.
3) 비용 제한을 둡니다. 반복 루프, 대량 RAG, 긴 컨텍스트는 토큰 비용을 급격히 증가시킵니다.
4) 관측성 없이는 운영하지 않습니다. 노드별 실행 시간, 입력, 출력, 오류, 재시도 횟수, 사용 모델, 토큰량을 추적합니다.

Ⅹ. 트러블슈팅 포인트

LangGraph 자체 문법보다 운영에서 더 자주 문제가 되는 부분은 상태 설계, 체크포인트, 재시도, 외부 도구 호출, 승인 흐름입니다.

문제 원인 해결 방안
State 값이 예상과 다르게 사라짐 노드가 반환한 값이 기존 State를 덮어쓰거나, 리스트 누적을 위한 reducer를 정의하지 않은 경우가 많습니다. State Schema를 명확히 정의하고, 메시지나 로그처럼 누적되는 값은 reducer를 사용합니다. 노드 반환값은 전체 State가 아니라 변경할 필드만 반환하는 습관을 들입니다.
재시작 후 대화나 작업이 이어지지 않음 checkpointer를 compile에 연결하지 않았거나, 실행 시 thread_id를 넘기지 않은 경우입니다. 운영에서는 checkpointer를 반드시 연결하고, 사용자 ID·업무 ID·티켓 번호 등으로 thread_id를 일관되게 지정합니다.
그래프가 무한 반복됨 조건부 엣지에서 종료 조건이 불명확하거나, LLM 판단에만 루프 탈출을 맡긴 경우입니다. retry_count, max_steps, confidence, approved 같은 명시적 상태 값을 두고, 일정 횟수 이상이면 사람 검토 또는 END로 보내야 합니다.
외부 API가 중복 실행됨 Timeout 이후 재시도하면서 이미 성공한 API를 다시 호출하는 경우입니다. idempotency key를 사용하고, 외부 조치 전후 상태를 기록합니다. 티켓 생성, 계정 잠금, 방화벽 정책 변경은 실행 이력 테이블을 따로 두는 것이 안전합니다.
Human-in-the-Loop가 운영에서 멈춘 것처럼 보임 Interrupt는 의도적으로 실행을 멈추고 외부 입력을 기다리는 구조입니다. 승인 UI, 알림, 재개 API가 없으면 장애처럼 보입니다. 승인 대기 상태를 별도 상태값으로 기록하고, 승인자에게 알림을 보내며, 재개 요청이 들어왔을 때 같은 thread_id로 resume하도록 설계합니다.
답변은 그럴듯하지만 근거가 약함 RAG 검색 결과가 부족하거나, LLM이 검색 실패를 인정하지 않고 추정으로 답한 경우입니다. 근거 개수, 문서 신뢰도, 최신성, 출처를 State에 넣고, 근거가 부족하면 답변 생성 노드가 아니라 보완 검색 또는 사람 검토 노드로 보내야 합니다.
로그가 많아질수록 비용과 지연이 증가함 모든 원본 로그를 LLM 컨텍스트에 그대로 넣으면 토큰 비용과 지연이 커집니다. 사전 필터링, 정규화, 요약 노드, Top-K 검색, 시간 범위 제한을 둡니다. LLM에는 원본 전체가 아니라 판단에 필요한 근거만 전달합니다.
보안상 위험한 도구 호출이 발생함 Agent에게 너무 넓은 권한을 주었거나, 도구 호출 전 정책 검증이 없는 경우입니다. 읽기 도구와 쓰기 도구를 분리하고, 쓰기 도구는 정책 검증 노드와 승인 노드를 반드시 거치게 합니다. 계정, 네트워크, DB 작업은 최소 권한 계정으로만 실행합니다.
디버깅이 어려움 노드별 입력과 출력, 라우팅 결정 이유, 도구 호출 결과를 남기지 않은 경우입니다. node_name, run_id, thread_id, input_summary, output_summary, latency, error를 구조화 로그로 남깁니다. 가능하면 LangSmith 같은 추적 도구와 연동합니다.
PoC는 잘 되는데 운영 전환이 어려움 PoC에서는 InMemory, 단일 사용자, 단일 모델, 낮은 트래픽만 가정했기 때문입니다. 운영 전환 전에는 영속 Checkpointer, Secret 관리, 모델 장애 시 fallback, Rate Limit, 비용 제한, 승인 UI, 감사 로그, 재처리 정책을 반드시 설계해야 합니다

 

반응형