지출 관리자에 AI 채팅 기능 추가하기
요약
React와 Express로 구축한 지출 추적기에 사용자가 자연어로 질문하여 데이터를 얻는 AI 채팅 기능을 추가하는 과정을 다룹니다. 이 기능은 단순 요약이나 분류를 넘어, 실제 데이터 기반의 대화형 분석을 가능하게 합니다. 개발 과정에서 환경 변수 이름 오류, 비동기 처리 누락(await), 모델 버전 문제, 그리고 할당량 초과(429) 등 다양한 기술적 문제를 해결한 경험을 공유합니다.
핵심 포인트
- AI 채팅 기능으로 데이터 기반의 대화형 분석 구현 가능
- 백엔드 라우트 테스트 시 curl 사용이 효과적임
- 비동기 함수 호출 시 반드시 await 처리 필요 (Promise 객체 주의)
- API 키 환경 변수 이름 및 모델 버전 관리에 유의해야 함
저는 이미 React, Express 및 SQLite로 작동하는 지출 추적기를 구축했습니다. 이 작업을 위해 저는 단순히 기능을 덧붙이는 것이 아니라 실제로 의미가 있는 AI 기능을 선택해야 했습니다. 그래서 사용자가 자신의 지출에 대해 일반 영어로 질문할 수 있는 채팅 기능을 선택했습니다. 예를 들어, "이번 달 식비로 얼마를 썼나요?" 또는 "제 가장 큰 카테고리는 무엇인가요?"와 같이 질문하면 실제 데이터를 기반으로 답변을 받습니다.
이 기능이 필요한 이유
앱에는 이미 총액과 카테고리별 분류가 표시되는 요약 섹션이 있었지만, 그것만으로는 충분하지 않습니다. 두 카테고리를 비교하거나 특정 기간을 확인하는 등 더 구체적인 것이 필요하다면, 목록을 스크롤하여 직접 계산해야 합니다. 채팅 기능은 이를 해결합니다. 질문만 하면 답변을 얻습니다. 이는 제가 이미 데이터베이스에 가지고 있던 데이터를 가장 자연스럽게 확장한 느낌이었으며, 또한 단순히 API를 한 번 호출하고 결과를 출력하는 대신 프롬프트와 스트리밍에 대해 깊이 생각하도록 강제한 기능이기도 합니다.
처음에는 다른 두 가지 옵션도 고려했습니다. 타이핑할 때 지출을 자동 분류하는 것은 너무 사소하게 느껴졌고, AI 기능이라기보다는 분류기에 가까웠습니다. 일회성 지출 요약은 괜찮았지만 정적이었습니다. 한 번 생성하면 끝입니다. 채팅이 실제로 AI SDK가 의도된 방식으로 사용되는 느낌을 주었습니다.
기술적 결정
기술적 결정
Provider 및 모델. API 키를 위해 무료이고 카드 정보가 필요 없는 Google AI Studio를 사용했습니다. 대부분의 튜토리얼에서 사용하는 gemini-2.5-flash로 시작했지만, 이 모델이 더 이상 새로운 API 키에 대해 제공되지 않는다는 것을 알게 되어 대신 현재 Google의 기본 플래시 모델을 가리키는 gemini-flash-latest로 변경했습니다. 테스트하는 도중에 503
저는 먼저 API 키를 얻고 ai와 @ai-sdk/google 패키지를 설치한 다음, 프론트엔드 코드를 건드리기 전에 백엔드 라우트를 작성하는 것부터 시작했습니다. 제 계획은 UI를 구축하기 전에 curl로 테스트하는 것이었는데, 이것이 정말 좋은 결정이었음이 밝혀졌습니다. 왜냐하면 작동하기까지 네 가지의 별도 버그에 직면했기 때문입니다.
첫 번째는 .env 파일에서 환경 변수 이름을 잘못 지정한 것입니다. 저는 SDK가 예상하는 정확한 이름인 GOOGLE_GENERATIVE_AI_API_KEY 대신 APIKEY와 같은 것을 사용해서, 제공자(provider)가 키를 전혀 찾지 못했습니다.
두 번째는 convertToModelMessages(messages)를 기다리지 않고(await) streamText에 바로 전달한 것입니다. 알고 보니 이 함수가 SDK의 이번 버전에서 비동기(async)가 되었기 때문에, 저는 메시지 배열 대신 Promise 객체를 messages 필드에 전달했고, 이는 messages.some이 함수가 아니라는 이상한 오류를 발생시켰습니다. 스택 트레이스(stack trace)를 좀 파헤쳐 본 후에야 수정 방법이 단순히 await을 추가하는 것임을 깨달았습니다.
세 번째는 위에서 언급했던 모델 버전 문제, 즉 gemini-2.5-flash가 더 이상 신규 사용자에게 사용할 수 없다는 404 오류를 반환한 것입니다.
네 번째는 모델을 전환한 후 높은 수요로 인해 503 오류에 직면했습니다. 저는 코드를 그대로 두고 몇 시간 후에 다시 시도했고 정상적으로 작동했으므로, 이것은 제가 해결할 필요가 없는 Google 서버의 일시적인 과부하였음이 분명했습니다.
언급할 가치가 있는 또 다른 점은, 실제로 앱을 배포하고 라이브로 테스트했을 때 503과는 다른 오류인 429에 직면했다는 것입니다. 이는 제가 할당량(quota)을 초과했음을 의미했으며, 구체적으로 무료 등급의 분당 20개 요청 제한이었습니다. 이것은 Google 서버가 과부하된 것이 아니라, 모든 것이 작동하는지 확인하기 위해 저 자신이 너무 많은 테스트 질문을 연속으로 보낸 결과였습니다. 실패 모드는 달랐지만 해결책은 같았고, 잠시 기다리면 사라졌습니다.
백엔드가 실제로 작동하자, useChat을 사용해 프론트엔드를 연결하는 것은 비교적 순조로웠습니다. 또한 개발 서버가 제가 아직 설정하지 않은 Express 서버에 도달할 수 없는 프록시 문제에 직면하여, /api 요청을 localhost:5000으로 가리키는 프록시를 vite.config.js에 추가했습니다.
테스트하는 동안 발견한 또 다른 점은,
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기