피드로 돌아가기
Building Voice Conversations Without Usage Limits: A Flutter Developer's Guide
Dev.toDev.to
Frontend

Flutter 개발팀이 Sealed Event 기반 스트림 아키텍처를 도입해 음성 인터페이스를 사용량 제한 없이 확장 가능하도록 구현

Building Voice Conversations Without Usage Limits: A Flutter Developer's Guide

Alexander Phaiboon2026년 3월 28일9intermediate

Context

기존 음성 기능 구현은 버튼 누르기→음성 전송→응답 수신의 단순 API 호출 패턴이었으나, 이는 대화 상태 관리 부재, UI 차단 패턴, 네트워크 오류 시 전체 대화 중단이라는 문제를 야기했다. Notion이 사용자당 20회 lifetime AI 상호작용으로 제한한 것처럼 기존 아키텍처는 대규모 음성 상호작용에 부적합했다.

Technical Solution

  • Sealed 클래스 기반 음성 이벤트 계층 구조 정의: VoiceStarted, VoiceRecording, VoicePaused, VoiceCompleted, VoiceError 5개 이벤트로 모든 음성 상태를 표현
  • StreamController를 통한 이벤트 스트림 브로드캐스트: 여러 위젯이 동일 스트림을 구독하는 비블로킹 패턴으로 전환
  • VoiceProvider에서 대화 상태를 Map<String, VoiceConversation>로 관리: 활성 대화 ID를 추적하며 상태 변경 시마다 이벤트 발행
  • VoiceError 이벤트에 recoveryAction 필드 추가: 네트워크 오류 발생 시 "재시도" 또는 "로컬 저장" 옵션 제공 가능하도록 설계
  • Sealed 클래스 패턴으로 모든 가능한 상태를 명시적으로 처리: 컴파일 시점에 빠진 케이스 감지 가능

Impact

20개 이상의 위젯이 동일 스트림을 청취해도 성능 저하 없음. Sealed 클래스 기반 테스트로 음성 흐름의 통합 테스트 제거 가능.

Key Takeaway

음성이나 실시간 협업 같은 상태 기반 기능은 블로킹 API 호출 대신 이벤트 스트림 아키텍처로 설계하면, 사용량 제한 없이 상태 관리와 오류 복구를 자동화할 수 있다. Sealed 클래스를 UI 코드 작성 전에 먼저 정의하는 것이 복잡한 상호작용 흐름의 디버깅을 크게 단순화한다.


Flutter에서 음성 또는 실시간 협업 기능을 구축하는 팀이 StreamController 기반 Sealed Event 계층 구조를 도입하면, UI 블로킹 없이 여러 위젯에서 동시에 상태 변화를 추적할 수 있으며, 네트워크 오류 시 자동 복구 옵션을 제공할 수 있다.

원문 읽기