Flutter에서 Gemini, OpenAI, Claude 직접 연동하기 — 멀티 AI 프로바이더 패턴 구현

시작 — 하드코딩된 API 키 문제 Flutter 앱에서 AI 기능(영수증 OCR, 이미지 번역, 블로그 자동 생성)을 넣을 때, 처음에는 BizRouter라는 AI 프록시 서비스를 썼다. 모든 요청을 하나의 엔드포인트로 보내면 내부에서 Gemini, GPT, Claude 등으로 라우팅해주는 구조였다. 문제는 API 키가 소스 코드에 하드코딩되어 있다는 것이었다. class BizRouterService { static const _apiKey = 'sk-br-v1-d6872ae8e164...'; // 이게 코드에 그대로 static const _baseUrl = 'https://api.bizrouter.ai/v1'; 지인들에게 배포하는 MVP라 처음에는 괜찮았지만, 사용자가 자기 키를 입력해서 쓸 수 있게 만들어야 했다. Gemini 키가 있는 사람은 Gemini로, OpenAI 키가 있는 사람은 GPT로, Claude 키가 있는 사람은 Claude로 — 각자 가진 키를 쓸 수 있어야 했다. ...

2026-03-26 · 9분 소요 · Seunghan
Flutter Ios Build Dark Mode Logout Debugging

TestFlight 올리려다 터진 Flutter iOS 빌드 오류 5종 — 다크모드·로그아웃 버그까지 한 번에

빌드를 올리려는데 한꺼번에 여러 문제가 터졌다. 코드 생성기가 실패하고, 없어진 파일이 있고, 빌드 번호 규칙을 몰라서 거절당하고, UI는 다크모드가 하드코딩되어 있고, 로그아웃은 토큰을 안 지웠다. 하나씩 정리한다. 1. Retrofit 옵션 파라미터 문법 오류 → .g.dart 생성 실패 증상 dart run build_runner build 실행 시 일부 API 서비스 파일에서: Expected to find ')' 원인 Retrofit의 추상 메서드에서 옵션 파라미터({}) 위치를 잘못 씀. // ❌ 잘못된 문법 — 닫는 중괄호 뒤에 쉼표 Future<Response> getItems( @Path('id') String id, {@Query('type') String? type}, // ← 이렇게 쓰면 안 됨 ); // ✅ 올바른 문법 — 포지셔널 파라미터 뒤에 { 바로 열기 Future<Response> getItems( @Path('id') String id, { @Query('type') String? type, }); Dart 문법에서 옵션 파라미터는 마지막 포지셔널 파라미터 바로 뒤에 {를 열어야 한다. },로 닫은 뒤 쉼표를 찍으면 파서가 다음 인자로 인식하려다 실패한다. ...

2025-11-01 · 5분 소요 · Seunghan
Flutter Deprecated Api Mass Fix

Flutter Deprecated API 대규모 수정 - withOpacity, DropdownButtonFormField, Switch 등

Flutter 프로젝트를 오래 유지하다 보면 flutter analyze가 수백 개의 deprecated 경고를 뱉는 시점이 온다. 기능은 잘 돌아가지만 Warning이 쌓이면 진짜 문제가 묻힌다. 이번에 한 번에 200개 넘는 deprecated 경고를 정리하면서 나온 패턴들을 정리한다. deprecated 경고를 방치하면 결국 세 가지 문제로 이어진다. 첫째, 다음 Flutter 메이저 업그레이드 때 deprecated가 removal로 전환되어 컴파일 에러가 터진다. 둘째, 실제 버그나 타입 에러가 경고 노이즈에 묻혀 코드 리뷰에서 놓치기 쉽다. 셋째, 팀 합류 시 “왜 경고가 이렇게 많아요?“라는 질문이 나오는 순간 기술 부채를 설명해야 하는 부담이 생긴다. 한 번 정리해두면 이후 유지 비용이 훨씬 줄어든다. ...

2025-07-20 · 6분 소요 · Seunghan
Dart Api Integration

DART Open API 연동 삽질기 (Rails + Flutter)

DART Open API를 Rails 백엔드에 연동하면서 겪은 과정을 정리한다. 공시 모니터링, 감사의견, 지배구조, 재무지표, 지분공시 5개 영역을 구현했고 각 단계마다 삽질이 있었다. 구현 구조 각 데이터 유형마다 모델과 ActiveJob을 하나씩 만들었다. Job은 DART API를 호출해서 upsert_all로 DB에 넣는 단순한 구조다. DartCorpCodeSyncJob → dart_companies (기업 마스터) DartDisclosureSyncJob → dart_disclosures (공시 목록) DartMajorEventSyncJob → dart_major_events (상장폐지 트리거 이벤트 — DS001) DartAuditOpinionSyncJob → dart_audit_opinions (감사의견 — DS002/DS003) DartGovernanceSyncJob → dart_executives / dart_major_shareholders (DS004/DS005) DartFinancialIndexSyncJob → dart_financial_indexes (fnlttSinglAcntAll) DartEquityReportSyncJob → dart_equity_reports (지분공시) 삽질 1: upsert_all + update_only + updated_at 중복 가장 먼저 터진 오류. ...

2025-06-01 · 5분 소요 · Seunghan
개인정보처리방침 이용약관 면책조항 문의