Minutely 구축하기: Qwen Cloud 기반의 AI 회의 에이전트
요약
Qwen Cloud를 활용하여 회의 내용을 이해하고 실행 항목을 추출하는 자율형 AI 회의 에이전트 'Minutely' 구축 과정을 소개합니다. 멀티 에이전트 오케스트레이션 파이프라인과 Next.js, Supabase, Clerk를 결합한 기술 스택 및 개발 중 직면한 보안 이슈 해결 방법을 다룹니다.
핵심 포인트
- Qwen Cloud 기반의 6단계 멀티 에이전트 오케스트레이션 설계
- 단일 프롬프트 대신 작업별 에이전트 분리를 통한 신뢰성 향상
- Next.js, Supabase, Clerk를 활용한 풀스택 에이전트 아키텍처
- Clerk와 Supabase RLS 간의 인증 불일치 문제 및 해결 방안
Qwen Cloud Global AI Hackathon (Track 4: Autopilot Agent)를 위해 자율형 회의 지능 에이전트를 구축한 나의 여정
내가 해결하고자 했던 문제
작은 팀, 교회 그룹, 또는 중소기업(SME)을 운영해 본 적이 있다면 다음과 같은 패턴을 알고 있을 것입니다: 회의가 열리고, 누군가 대충 노트를 작성하지만, 사흘 뒤에는 누가 공급업체에 후속 조치를 취하기로 했는지, 혹은 예산 항목에 대한 실제 결정이 무엇이었는지 아무도 기억하지 못합니다. 회의록은 작성되지만, 메모 앱이나 WhatsApp 스레드 속에서 방치되어 사라집니다.
나는 단순히 회의를 전사(transcribe)하는 것이 아니라, 회의를 실제로 이해하는 무언가를 만들고 싶었습니다. 즉, 결정 사항, 실행 항목(action items), 담당자를 추출하고, 스스로 후속 이메일 초안을 작성하여 루프를 완성하는 것입니다. 그것이 Minutely의 아이디어입니다.
Qwen Cloud의 해커톤에 'Track 4: Autopilot Agent' 카테고리가 있다는 것을 보았을 때 — 이는 인간 참여형(human-in-the-loop) 체크포인트를 포함하여 실제 비즈니스 워크플로우를 엔드 투 엔드(end-to-end)로 자동화하는 에이전트를 위해 설계된 것이었습니다 — 제가 이미 만들고 있던 것과 완벽하게 일치했습니다.
기술 스택
Minutely는 다음을 기반으로 실행됩니다:
- 프론트엔드 및 API 라우트: Next.js (App Router) + TypeScript
- 인터페이스: Tailwind + shadcn/ui
- 데이터 지속성: Supabase (Postgres)
- 인증: Clerk
- 추론 계층: Qwen Cloud (qwen-plus 및 qwen-turbo, qwen-max는 향후 유료 티어를 위해 예약)
시스템의 핵심은 멀티 에이전트 오케스트레이션(multi-agent orchestration) 파이프라인입니다. 이는 가공되지 않은 회의 전사본을 가져와 요약, 결정 사항, 실행 항목, 담당자, 그리고 작성된 후속 조치 초안이라는 구조화된 출력으로 점진적으로 변환하는 6개의 별도 에이전트 단계로 구성됩니다. 모든 것을 수행하려는 하나의 거대한 프롬프트 대신, 각 에이전트는 좁은 범위의 작업을 수행하며, 이를 통해 출력의 신뢰성을 훨씬 높이고 디버깅을 더 쉽게 만들었습니다.
이 모든 것을 관리하기 쉽게 유지하기 위해, 저는 모든 모델 호출을 단일 lib/ai-config.ts 파일로 중앙 집중화했습니다. 모델 선택, 토큰 제한(token limits), 프롬프트 템플릿(prompt templates)이 API 라우트 곳곳에 흩어져 있는 대신 한 곳에 모여 있습니다. Qwen Cloud의 사용 가능한 모델이나 가격 정책(pricing tiers)이 변경되더라도, 저는 단 하나의 파일만 수정하면 됩니다.
*어려웠던 점: 지속성(persistence)과 stale closure 버그
*_
두 가지 버그가 제 개발 시간의 대부분을 잡아먹었습니다. 이들은 데모 영상에서는 나타나지 않지만, 프로덕션 준비 수준(production-readiness)을 결정짓는 데 매우 중요한 요소들입니다.
행 수준 보안(Row-Level Security, RLS) vs. Clerk JWT. Supabase의 RLS는 Supabase에서 발행한 인증 토큰을 기대하지만, 저는 인증을 위해 Clerk를 사용하고 있습니다. 이러한 불일치로 인해, Clerk에서 발행한 JWT를 검증할 수 없는 RLS 정책 하에서 쓰기(write) 작업이 조용히 실패하고 있었습니다. 해결책은 서버 측 쓰기를 위해 관리자용 Supabase 클라이언트(service role)를 사용하는 방식으로 지속성 로직을 완전히 재작성하는 동시에, 클라이언트에서 직접 접근하는 모든 것에 대해서는 RLS를 그대로 유지하는 것이었습니다. 가장 아름다운 해결책은 아니지만, 서버를 신뢰하고 브라우저를 신뢰하지 않는다는 올바른 경계(boundary)를 설정한 것입니다.
AnalysisChat에서의 stale closure. 사용자들이 특정 회의 분석에 대해 Minutely와 채팅할 수 있었지만, 해당 분석 내용을 수정해도 채팅 응답에 반영되지 않았습니다. 원인은 send() 함수가 생성될 당시의 렌더링 시점에 있는 오래된(stale) 분석 prop을 캡처하고, 최신 값을 가져오지 않았기 때문입니다. 전형적인 React closure 함정(trap)이었습니다. 해결책은 send()가 한 번 캡처하는 대신, 매 호출마다 ref 또는 최신 prop으로부터 값을 읽도록 보장하는 것이었습니다.
이 중 어느 것도 화려하지는 않지만, 무대 위에서 한 번 작동하는 데모와 세션 전반에 걸쳐 실제로 신뢰할 수 있는 에이전트 사이의 차이를 만드는 요소들입니다. 그리고 이것이 바로 Track 4 심사 기준이 요구하는 핵심입니다.
인간 참여형(human-in-the-loop) 설계를 위하여
Track 4는 단순히 완전한 자동 조종(autopilot)이 아니라, 모호한 입력을 처리하고 중요한 결정 지점에서 인간의 체크포인트를 포함하는 에이전트를 명시적으로 요구합니다. Minutely의 몇 가지 설계 선택은 이를 직접적으로 반영하고 있습니다:
후속 이메일 단계는 자동 발송되지 않고 수정 가능합니다. 에이전트가 수신자, 제목, 본문을 초안 작성하지만, 실제로 내용이 전송되기 전에 인간이 검토하고 수신자를 변경할 수 있습니다. 아무런 검토 없이 이메일을 발송하는 회의 에이전트는 기능(feature)이라기보다는 위험 요소(liability)입니다.
업로드 처리 방식은 제가 FileReader.readAsText가 .docx와 같은 바이너리 형식을 조용히 손상시킨다는 것을 발견한 후, 의도적으로 .txt 및 .md 스크립트 파일로 범위를 한정했습니다. 잘못된 입력에 예측 불가능하게 실패하는 것보다 지원되는 내용에 대해 명시하는 것이 더 낫기 때문입니다.
현재 업로드 영역에서 pdfjs-dist 워커 초기화 문제를 해결하고 있습니다. PDF 스크립트는 자연스러운 다음 입력 유형이 될 것이므로, 이는 빌드 중간에도 이 트랙이 보상하는 '모호한 입력 처리'의 좋은 예시입니다.
남은 작업
7월 9일 제출 마감일까지 제가 점검해야 할 목록은 다음과 같습니다:
- 백엔드가 localhost가 아닌 실제 프로덕션 환경에서 실행됨을 증명하기 위해 Alibaba Cloud 배포(ECS) 최종화
- Qwen Cloud, Supabase, 그리고 Next.js 프론트엔드가 어떻게 연결되는지 보여주는 아키텍처 다이어그램
- 깔끔한 3분 데모 비디오
- 제출 문서 작성 마무리하기
이 트랙을 선택한 이유, 지금 이 시점의 의미
많은 'AI 에이전트' 데모는 샌드박스 환경에서는 인상적이지만, 실제의 지저분한 인간 입력(잘못된 스크립트, 모호한 실행 항목, 형식 지정의 엣지 케이스)이 나타나는 순간 무너집니다. Minutely를 구축하는 과정은 화려한 데모를 쫓기보다는, 이러한 복잡성을 우아하게 처리하는 연습에 가까웠습니다. 이것이 제가 트랙 4에서 내거는 베팅입니다: 장난감 같은 데모보다 프로덕션 준비성(production-readiness)을 보여주는 것입니다. 이는 간략한 안내서가 요구하는 바와 정확히 일치합니다.
만약 여러분도 Qwen Cloud를 기반으로 구축하고 있다면, 어떤 문제에 직면했는지 듣고 싶습니다. 특히 Postgres 백엔드를 기반으로 다중 에이전트 시스템을 구축하는 거의 모든 사람에게 발생하는 것처럼 느껴지는 오케스트레이션(orchestration) 및 지속성(persistence) 문제가 그렇습니다.
Minutely는 공개적으로 구축되었습니다. 레포지토리는 여기를 팔로우하세요: github.com/howelldevs
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기