비용 문제가 시작이었다

3편에서 만든 영어 레이어는 꽤 만족스러웠다. 실제로 매일 사용할 정도로 잘 동작했다.

하지만 오래 사용하다 보니 문제가 보였다. Claude API는 생각보다 훨씬 비쌌다.

같은 Claude를 사용하더라도 구독과 API는 비용 구조가 완전히 달랐다. 조금만 대화를 오래 이어가도 토큰이 빠르게 소모됐고, 여러 모델을 함께 호출하는 구조는 비용 부담을 더 키웠다.

그때 처음으로 이런 생각을 했다.

"비싼 모델 하나를 계속 쓰는 대신, 저렴한 모델 여러 개를 잘 조합하면 비슷한 결과를 만들 수 있지 않을까?"

그 질문이 LangGraph를 공부하게 된 계기였다.

처음에는 그냥 워크플로 도구처럼 보였다

처음 LangGraph를 봤을 때는 별 감흥이 없었다.

START가 있고 END가 있다. 중간에 노드를 연결하고, 조건에 따라 다른 노드로 분기한다. 그냥 함수를 순서대로 실행하는 워크플로 정도로 보였다.

'굳이 이걸 왜 그래프라고 부를까? if문과 함수 호출로도 충분히 만들 수 있는 것 같은데.'

LangChain과 LangGraph의 차이도 크게 와닿지 않았다. 그냥 다음 버전 정도인가 싶었다.

그런데 State라는 개념이 계속 눈에 들어왔다

공부를 계속하면서 가장 많이 보인 단어는 State였다.

처음에는 단순한 전역 변수 정도로 생각했다.

그런데 조금씩 느낌이 달랐다. LangGraph에서는 노드끼리 데이터를 직접 주고받지 않는다. 모든 노드가 하나의 State를 함께 읽고 수정한다.

지금까지의 대화, 검색 결과, 메모리, 중간 추론 결과 같은 정보가 모두 하나의 State 안에 들어간다. Planner도, Search도, Memory도, 전부 같은 State를 바라본다.

그 순간 조금 이해가 됐다. LangGraph는 함수를 연결하는 프레임워크가 아니라, State를 중심으로 실행 흐름을 설계하는 프레임워크였다.

LangGraph: everything flows through State

Reducer는 왜 필요한 걸까?

그다음 궁금했던 것은 Reducer였다. State를 여러 노드가 동시에 수정하면 어떻게 될까?

Reducer가 각각의 변경 사항을 합쳐 새로운 State를 만든다. React의 reducer와 비슷한 개념이라 이해는 어렵지 않았다.

하지만 여기서 한 가지 흥미로운 점이 있었다. LangGraph에서 중요한 것은 노드가 아니라, 결국 State를 어떻게 설계하느냐였다. 노드들은 State를 읽고, 수정하고, 다음 노드에게 넘기다. 생각보다 실행 흐름보다 데이터 구조가 더 중요하게 느껴졌다.

그제야 Graph라는 이름이 이해됐다

처음에는 그냥 순서대로 실행하는 도구처럼 보였다. 하지만 Conditional Edge와 루프를 보면서 생각이 바뀌었다.

질문에 따라 검색을 하기도 하고, 검색 결과가 부족하면 다시 Planner로 돌아가기도 한다. 같은 노드를 여러 번 방문하는 것도 가능했다.

Planner → Executor → Planner → Executor → END.

그제야 이름이 이해됐다. Tree가 아니라 정말 Graph였다. 복잡한 실행 흐름을 자연스럽게 표현하기 위한 구조.

여러 Agent도 결국 같은 패턴이었다

ReAct, Plan-and-Execute, Reflection, Supervisor, Multi-Agent 같은 예제도 많이 따라 만들어 봤다. 처음에는 전부 새로운 기술처럼 보였다.

하지만 하나씩 뜯어보니 결국은 같은 구조였다. Planner가 계획을 세우고, 다른 Agent가 실행하고, 필요하면 Tool을 호출하고, 다시 Planner가 판단한다. 노드 구성만 조금씩 다를 뿐, 전부 State를 공유하면서 협력하는 Graph였다.

그 과정을 따라가면서 AI 에이전트가 어떻게 동작하는지 훨씬 깊게 이해할 수 있었다.

그런데 구현할수록 이상한 기분이 들었다

공부는 재미있었다. 실제로 영어 레이어도 여러 모델로 분리해서 실험했고, 저렴한 모델에게 단순한 작업을 맡기는 구조도 만들어 봤다.

그런데 구현을 계속할수록 이상한 기분이 들었다.

내가 만들고 있는 게 무엇일까?

채팅 UI, 도구 실행, Google Calendar 연결, 파일 읽기, 웹 검색, 자동 실행, 메모리 레이어, LangGraph 실행 엔진.

결국 Claude가 제공하는 기능을 하나씩 다시 구현하고 있었다. 원하는 방식으로 자유롭게 만들 수 있다는 장점은 있었다. 하지만 새로운 기능이 나올 때마다 내가 직접 구현해야 했고, Claude가 발전할수록 내가 따라가야 하는 범위도 계속 커졌다.

What I was actually replicating

정말 이길 수 있는 싸움일까?

더 근본적인 질문도 생겼다. LangGraph를 잘 설계하면, 저렴한 모델 여러 개를 조합해서 비싼 모델 하나보다 더 좋은 결과를 만들 수 있을까?

처음에는 가능할 거라고 생각했다.

하지만 계속 공부하고 여러 사례와 연구를 찾아볼수록 생각이 바뀌었다. 복잡한 에이전트 구조가 항상 더 좋은 결과를 만드는 것은 아니었다. 오히려 충분히 학습된 단일 모델이 더 좋은 성능을 보여주는 경우도 많았다.

나는 Anthropic이 가장 잘하는 영역에서 Anthropic과 경쟁하고 있었다. 거기에서 벗어나는 것이 더 현명한 선택이라고 판단했다.

그래서 방향을 완전히 바꿨다

직접 만든 챗봇 UI는 더 이상 만들지 않기로 했다. LangGraph 기반 실행 엔진도 접었다. 영어 레이어도 아쉬웠지만 별도의 시스템으로 유지하지 않기로 했다. 대신 단순하더라도 프롬프트를 통해 해결하기로 했다.

내가 잘할 수 있는 것과, AI 회사가 훨씬 잘할 수 있는 것을 분리하기 시작한 것이다.

질문이 완전히 달라졌다

그때부터 질문이 바뀌었다.

"Claude보다 더 좋은 AI를 만들 수 있을까?"

"Claude가 절대 가질 수 없는 것은 무엇일까?"

답은 하나였다. 내 맥락이었다.

내 프로젝트. 내 의사결정. 내가 실패했던 이유. 오래된 메모. 학습 기록. 취향.

이런 것들은 모델이 아무리 좋아져도 자동으로 생기지 않는다.

그래서 전략을 완전히 바꿨다. AI는 Claude를 그대로 사용한다. 내일 ChatGPT로 바꾸더라도 마찬가지다. 대신 모든 AI가 공통으로 사용하는 메모리와 지식 계층을 직접 만들기로 했다.

The pivot: from replace to extend

ATLAS는 다른 것이 됐다

ATLAS는 더 이상 채팅 앱이 아니다. Claude나 ChatGPT를 대체하는 프로젝트도 아니다.

ATLAS는 하나의 지식 엔진이자 개인 인프라다.

MCP를 통해 Claude가 연결되고, ChatGPT도 같은 MCP를 통해 연결된다. 어떤 AI를 사용하든, 같은 메모리를 읽고, 같은 메모리에 기록한다.

모델은 언제든 바뀔 수 있다. 하지만 내 지식과 맥락은 하나의 인프라 위에 계속 남는다.

그것이 내가 직접 만들어야 할 영역이라고 생각했다.

ATLAS as shared infrastructure

Atlas Knowledge Graph Dashboard

다음 문제

방향을 바꾸고 나니 새로운 문제가 보였다.

메모리는 단순히 저장만 하면 되는 걸까?

처음에는 나도 그렇게 생각했다. 하지만 직접 만들어 보니, 기억은 많이 저장할수록 오히려 더 엉망이 되기 시작했다.

그래서 다음에는 실행 구조가 아니라, 기억 자체의 구조를 설계하기 시작했다. 어떻게 해야 시간이 지나도 유용한 지식을 만들 수 있을까. 그게 다음 질문이었다.