Skip to content

랭그래프에서 이전 (Migrating from LangGraph)

랭그래프로 에이전트를 만들었다면, StateGraph와 씨름해 봤을 거예요. 조건부 엣지를 연결하고, 새벽 2시에 상태 딕셔너리를 디버깅해 본 적도 있겠죠. 그렇게 작동은 하지만, 어느 순간 "이제 프로덕션으로 가는 더 나은 길은 없을까" 하는 생각이 들기 시작했을 거예요. 있습니다. CrewAI Flows는 그와 같은 힘 — 이벤트 기반 오케스트레이션, 조건부 라우팅, 공유 상태 — 을 훨씬 적은 보일러플레이트로, 그리고 여러분이 다단계 AI 워크플로를 실제로 생각하는 방식과 그대로 들어맞는 멘탈 모델로 제공해요. 이 글에서는 핵심 개념을 나란히 놓고 비교하고, 실제 코드 대조를 보여드리며, 왜 CrewAI Flows가 다음에 손댈 프레임워크인지를 설명할게요.


멘탈 모델의 전환

랭그래프는 그래프로 생각하라고 요구해요. 노드, 엣지, 상태 딕셔너리. 모든 워크플로는 방향 그래프라서, 계산 단계 사이의 전이를 코드로 하나하나 이어야 하죠. 강력하지만, 그 추상화에는 부담이 따라와요 — 특히 워크플로가 근본적으로 순차적이고 결정 지점이 몇 개뿐일 때요. CrewAI Flows는 이벤트로 생각하라고 해요. 무언가를 시작하는 메서드, 결과를 기다리는 메서드, 실행을 라우팅하는 메서드. 워크플로의 토폴로지는 명시적 그래프를 짜는 대신 데코레이터 어노테이션에서 드러나요. 단순한 문법 설탕이 아니라, 파이프라인을 설계·읽고·유지보수하는 방식 자체가 달라지는 거죠. 핵심 매핑은 이렇게 됩니다.

실제로 어떻게 생겼는지 볼게요.


데모 1: 단순한 순차 파이프라인

주제를 받아서 리서치하고, 요약을 쓰고, 출력을 포맷하는 파이프라인을 만든다고 상상해 보세요. 각 프레임워크는 이걸 이렇게 처리해요.

랭그래프 방식

함수를 정의하고 노드로 등록한 뒤, 모든 전이를 손으로 이어야 해요. 이런 단순한 순서조차 따라야 할 절차가 많죠.

CrewAI Flows 방식

달라진 점이 보이시나요. 그래프를 만들지 않고, 엣지를 연결하지 않고, 컴파일 단계도 없어요. 실행 순서는 로직이 살아 있는 바로 그 자리에 선언돼요. @start()가 진입점을 표시하고, @listen(method_name)이 단계를 이어 붙이죠. 상태는 타입 안전·검증·IDE 자동 완성을 갖춘 제대로 된 Pydantic 모델이에요.


데모 2: 조건부 라우팅

여기서부터 재미있어져요. 감지된 콘텐츠 유형에 따라 서로 다른 처리 경로로 라우팅하는 콘텐츠 파이프라인을 만든다고 해볼게요.

랭그래프 방식

별도의 라우팅 함수, 명시적인 조건부 엣지 매핑, 그리고 각 분기에 대한 종료 엣지가 필요해요. 라우팅 로직은 그 라우팅 결정을 만들어 내는 노드와 분리되어 있죠.

CrewAI Flows 방식

@router() 데코레이터가 메서드를 결정 지점으로 바꿔요. 리스너와 일치하는 문자열을 반환할 뿐이라, 매핑 딕셔너리도, 별도 라우팅 함수도 필요 없어요. 분기 로직이 파이썬 if 문처럼 읽히는데, 실제로 그게 if 문이거든요.


CrewAI의 진짜 힘은 여기서 드러나요. Flows는 LLM 호출을 이어 붙이는 용도만이 아니라, 자율 에이전트로 이루어진 Crew 전체를 오케스트레이션해요. 랭그래프에는 이에 해당하는 네이티브 기능이 없어요.

핵심 통찰은 이거예요. Flows가 오케스트레이션 계층을, Crews가 지능 계층을 담당한다. Flow의 각 단계는 각자의 역할·목표·도구를 가진 협업 에이전트 팀 전체를 띄울 수 있어요. 구조화되고 예측 가능한 제어 흐름과 자율 에이전트 협업, 둘 다 얻는 셈이죠 — 양쪽의 장점만 가져옵니다. 랭그래프에서 비슷한 걸 만들려면 노드 함수 안에서 에이전트 통신 프로토콜, 툴 호출 루프, 위임 로직을 수동으로 구현해야 해요. 불가능한 건 아니지만, 매번 처음부터 다시 짜야 하는 배관 작업이죠.


데모 4: 병렬 실행과 동기화

실제 파이프라인은 일을 여러 갈래로 나누고(fan out) 결과를 다시 모아야(fan in) 하는 경우가 많아요. CrewAI Flows는 and_or_ 연산자로 이걸 우아하게 처리해요.

여러 개의 @start() 데코레이터가 병렬로 실행돼요. @listen 데코레이터의 and_() 콤비네이터는 세 업스트림 메서드가 모두 끝난 뒤에만 synthesize_report가 실행되도록 보장해 주죠. 업스트림 작업 아무거나 하나라도 끝나면 진행하고 싶을 때 쓸 수 있는 or_()도 있어요. 랭그래프에서는 병렬 분기를 만들고, 동기화 노드를 두고, 상태 병합을 신경 쓰는 fan-out/fan-in 패턴을 — 전부 엣지로 명시해 — 직접 구축해야 해요.


왜 프로덕션에는 CrewAI Flows인가

문법이 깔끔한 것 외에도, Flows는 프로덕션에서 중요한 여러 장점을 주는데요. 내장 상태 지속성. Flow 상태는 LanceDB에 백업되어, 워크플로가 크래시를 견디고 재개되며 여러 번 실행에 걸쳐 지식을 쌓아요. 랭그래프는 별도의 체크포인터를 설정해야 하죠. 타입 안전 상태 관리. Pydantic 모델이 검증·직렬화·IDE 지원을 기본 제공해요. 랭그래프의 TypedDict 상태는 런타임에 검증하지 않아요. 일급 에이전트 오케스트레이션. Crew는 네이티브 프리미티브예요. 에이전트를 역할·목표·백스토리·도구와 함께 정의하면, Flow라는 구조적 틀 안에서 자율적으로 협업해요. 다중 에이전트 조정을 새로 발명할 필요가 없어요. 더 단순한 멘탈 모델. 데코레이터가 의도를 선언해요. @start는 "여기서 시작해", @listen(x)는 "x 다음에 실행해", @router(x)는 "x 다음에 어디로 갈지 정해". 코드가 그 코드가 묘사하는 워크플로처럼 읽히죠. CLI 통합. crewai run으로 Flow를 실행해요. 별도 컴파일 단계도, 그래프 직렬화도 없어요. Flow는 파이썬 클래스이고, 그냥 파이썬 클래스처럼 돌아갑니다.


이전 치트 시트

랭그래프 코드베이스를 갖고 CrewAI Flows로 옮기려 한다면, 실용적인 변환 가이드가 여기 있어요.

  1. 상태를 매핑하세요. TypedDict를 Pydantic BaseModel로 바꾸고, 모든 필드에 기본값을 추가하세요.
  2. 노드를 메서드로 바꾸세요.add_node 함수가 Flow 서브클래스의 메서드가 됩니다. state["field"] 읽기는 self.state.field로 바꾸세요.
  3. 엣지를 데코레이터로 바꾸세요. add_edge(START, "first_node")는 첫 번째 메서드 위의 @start()가 되어요. 순차 add_edge("a", "b")는 메서드 b 위의 @listen(a)가 되죠.
  4. 조건부 엣지를 @router로 바꾸세요. 라우팅 함수와 add_conditional_edges() 매핑은 라우트 문자열을 반환하는 @router() 메서드 하나로 합쳐져요.
  5. 컴파일 + 인보크를 킥오프로 바꾸세요. graph.compile()을 버리고 flow.kickoff()를 호출하세요.
  6. Crew가 들어갈 자리를 고려하세요. 복잡한 다단계 에이전트 로직이 있는 노드는 Crew로 추출하기 좋은 후보예요. 여기서 가장 큰 품질 개선을 보게 될 거예요.

시작하기

CrewAI를 설치하고 새 Flow 프로젝트를 스캐폴딩하세요.

이렇게 하면 편집할 준비가 된 Flow 클래스, 설정 파일, 그리고 type = "flow"가 이미 설정된 pyproject.toml이 있는 프로젝트 구조가 생성돼요. 다음과 같이 실행하세요.

여기서부터 에이전트를 추가하고, 리스너를 연결하고, 배포하면 됩니다.


마무리

랭그래프는 AI 워크플로에 구조가 필요하다는 걸 생태계에 가르쳐 줬어요. 중요한 교훈이었죠. 그런데 CrewAI Flows는 그 교훈을 가져다가 더 빨리 쓰고, 더 읽기 쉽고, 프로덕션에서 — 특히 여러 협업 에이전트가 얽힌 워크플로에서 — 더 강력한 형태로 전달해요. 단일 에이전트 체인을 넘어서는 무언가를 만든다면, Flows를 진지하게 살펴볼 만해요. 데코레이터 중심 모델, 네이티브 Crew 통합, 내장 상태 관리는 배관에 쓰는 시간을 줄이고 문제 그 자체에 쓰는 시간을 늘려 주죠. crewai create flow에서 시작해 보세요. 후회하지 않을 거예요.