Genkit Agents API 적용법: 대화형 AI 앱에서 세션·도구·스트리밍을 한 번에 설계하기
Google이 Genkit Agents API를 preview로 공개했다. Genkit은 TypeScript, Go, Dart, Python을 지원하는 오픈소스 AI 앱 프레임워크다. 이번 Agents API의 핵심은 대화형 AI 기능을 만들 때 반복해서 구현하던 세션, 메시지 히스토리, tool loop, 스트리밍, 저장소, 프론트엔드 프로토콜을 하나의 에이전트 인터페이스로 묶는 것이다.
대화형 AI 앱을 만들어 본 팀이라면 알 것이다. 처음에는 generate() 한 번이면 충분해 보인다. 하지만 실제 제품으로 가면 바로 복잡해진다. 사용자는 이전 대화를 기억하길 원하고, 모델은 도구를 호출해야 하며, 도구 결과는 다시 모델 입력으로 들어가고, 응답은 스트리밍되어야 한다. 중간에 사용자가 취소할 수도 있고, 세션을 이어받거나 특정 시점에서 분기해야 할 수도 있다.
단일 generate 호출이 무너지는 시점
FAQ 챗봇은 단순하다. 질문을 받고 답한다. 하지만 지원 상담, 개발 도우미, 여행 계획, 리포트 작성, 데이터 분석처럼 여러 턴을 다루는 기능은 구조가 다르다. 모델은 사용자의 목표를 기억하고, 중간 상태를 저장하고, 필요한 도구를 호출하고, 결과를 반영해 다음 질문을 해야 한다.
이때 팀들이 자주 만드는 임시 구조는 다음과 같다.
- messages 배열을 클라이언트에 계속 들고 다닌다.
- 도구 호출은 별도 if문으로 처리한다.
- 세션 저장은 DB 테이블 하나로 급하게 만든다.
- 스트리밍 이벤트 형식은 프론트와 백엔드가 따로 약속한다.
- 취소, 재시도, 분기 처리는 나중으로 미룬다.
PoC에서는 된다. 운영에서는 장애 원인이 된다. 모바일 앱이 백그라운드로 내려가거나, 서버 인스턴스가 바뀌거나, 도구 호출 중 네트워크가 끊기면 대화 상태가 꼬인다.
Genkit Agents API가 제공하는 기본 추상화
Google 설명에 따르면 Genkit Agents API는 서버에서 agent를 정의하고 같은 chat() API로 in-process 실행이나 HTTP endpoint 실행을 다룰 수 있게 한다. Agent는 이름, 시스템 프롬프트, 모델, 도구, 상태, 세션 저장소를 가진다. 처음에는 간단한 RunText로 시작하고, 기능이 커지면 같은 객체에 store와 tools를 붙인다.
실무적으로 좋은 점은 추상화가 기능 성장 경로를 막지 않는다는 것이다. 처음부터 “챗봇용 코드”와 “에이전트용 코드”를 따로 만들 필요가 줄어든다. 한 번 정의한 agent가 one-shot 응답, 스트리밍 턴, 일시 중지된 도구 호출, 멀티턴 대화를 모두 처리할 수 있다면 제품 코드가 단순해진다.
물론 preview라는 점은 주의해야 한다. TypeScript와 Go에서 preview이고 minor version에서 breaking change가 생길 수 있다고 명시돼 있다. 따라서 핵심 운영 기능에 바로 깊게 묶기보다는 새 기능이나 내부 도구부터 적용하는 편이 안전하다.
세션 저장은 서버 관리와 클라이언트 관리 중 선택해야 한다
Genkit 문서에서 중요한 설계 지점은 session store다. store를 붙이면 서버 관리 세션이 된다. 서버가 메시지, custom state, artifacts를 snapshot으로 저장하고, 클라이언트는 sessionId로 이어간다. Firestore 같은 managed store를 쓰면 여러 서버 인스턴스가 같은 세션을 공유할 수 있다.
store를 붙이지 않으면 클라이언트 관리 방식이다. 서버가 전체 state를 반환하고 클라이언트가 다음 턴에 다시 보낸다. stateless 서버를 유지하고 싶거나 이미 앱이 자체 persistence를 갖고 있다면 이 방식이 맞다.
선택 기준은 명확하다.
- 고객지원, 협업, 장기 작업: 서버 관리 세션
- 짧은 개인 도구, 임시 채팅, 로컬 앱: 클라이언트 관리 세션
- 민감 데이터 포함: 서버 관리 + 접근 제어 + 감사 로그
- 서버 비용 최소화: 클라이언트 관리 + state 크기 제한
잘못 선택하면 나중에 비용이 커진다. 예를 들어 B2B 고객지원 AI가 클라이언트 관리 세션만 쓰면 사용자가 기기를 바꿨을 때 이어받기 어렵고, 감사 로그도 약해진다. 반대로 가벼운 개인 앱에서 모든 턴을 서버 저장하면 인프라 비용과 개인정보 부담이 커진다.
Snapshot과 branching은 제품 기능으로 바로 이어진다
Genkit Agents API는 최신 상태를 sessionId로 이어가거나 특정 snapshotId에서 분기할 수 있다고 설명한다. 이 기능은 단순 개발 편의가 아니라 UX 기능이다.
예를 들어 여행 계획 AI에서 사용자가 “예산을 줄인 버전도 보여줘”라고 하면 기존 계획을 망가뜨리지 않고 특정 시점에서 branch를 만들 수 있다. 코드 리뷰 AI라면 “보수적인 패치”와 “리팩터링 포함 패치”를 같은 분석 지점에서 나눌 수 있다. 리포트 작성 AI라면 승인된 초안 snapshot을 보존하고, 마케팅용 버전과 기술 문서 버전을 따로 만들 수 있다.
이런 기능을 처음부터 염두에 두면 DB 설계가 달라진다. 단순히 conversations 테이블 하나에 messages를 append하는 구조보다 sessions, snapshots, artifacts를 분리하는 편이 낫다.
도구와 상태를 UI 이벤트로 연결해야 한다
대화형 에이전트 앱에서 사용자는 모델이 “생각 중”인지, 도구를 호출 중인지, 파일을 만들었는지, 중간 결과를 저장했는지 알고 싶어 한다. Genkit은 custom state와 artifacts를 agent가 들고 다니며 tool이 업데이트할 수 있고, 변경 사항을 클라이언트로 스트리밍할 수 있다고 설명한다.
제품 관점에서는 다음 이벤트를 UI에 보여줘야 한다.
- 메시지 토큰 스트리밍
- 도구 호출 시작과 종료
- 생성된 artifact 목록
- 현재 workflow 상태
- 취소 가능 여부
- 오류와 재시도 버튼
이걸 빼면 사용자는 긴 작업을 기다리는 동안 불안해한다. 특히 30초 이상 걸리는 AI 작업은 빈 spinner 하나로 버티기 어렵다. 어떤 단계가 진행 중인지 보여주는 것이 체감 성능을 크게 바꾼다.
바로 적용할 체크리스트
Genkit Agents API를 검토하는 팀은 다음 순서로 접근하면 된다.
- 현재 AI 기능이 one-shot인지 multi-turn인지 구분한다.
- 대화 상태를 클라이언트가 들지 서버가 들지 먼저 결정한다.
- 장기 작업에는 sessions, snapshots, artifacts 모델을 분리한다.
- 도구 호출 이벤트를 UI에 노출할 스트리밍 형식을 정한다.
- 취소, 재시도, 분기, 이어받기를 첫 설계에 포함한다.
- preview API는 내부 도구나 신규 기능부터 적용한다.
- 특정 프레임워크에 묶이기 전에 세션 데이터 export 경로를 확보한다.
Genkit Agents API의 가치는 “Google이 또 AI 프레임워크를 냈다”가 아니다. 대화형 AI 앱에서 반복되는 운영 배관을 제품 코드와 분리하려는 시도다. 팀이 지금 세션과 도구 호출을 임시 코드로 처리하고 있다면, 이번 기회에 에이전트 런타임 구조를 다시 정리할 만하다.