Claude Fable 5가 서비스 중단되기 전 나의 인디 다이어리 앱을 리뷰하게 했다 — 발견된 버그들
요약
Claude Fable 5를 활용하여 Flutter 기반 인디 다이어리 앱의 코드를 리뷰하고 실제 버그를 수정한 사례를 기록합니다. 비동기 작업 중 BuildContext 사용 문제와 테스트 코드 부재 등 실질적인 수정 사항을 다룹니다.
핵심 포인트
- Claude Fable 5를 통한 Flutter 앱 코드 리뷰 및 버그 수정
- 비동기 간극(async gaps)에서 mounted 체크 누락으로 인한 크래시 방지
- 실제 커밋 히스토리에 기반한 실질적인 코드 개선 사례 공유
- Anthropic의 서비스 중단 이슈와 관련된 배경 설명
서론 (Intro)
저는 사이드 프로젝트로 작은 다이어리 앱인 Daily Diary (Flutter 기반, Google Play 출시됨)를 운영하고 있습니다. 배포 전에 제대로 된 품질 검토를 거치고 싶어서, Claude Fable 5에게 코드를 리뷰하고 수정하도록 했습니다. 이것은 그 기록입니다.
Fable 5는 2026년 6월 9일에 출시되었습니다. 사흘 뒤인 6월 12일 저녁, 미국 상무부(US Commerce Department)가 수출 통제 지침을 발행하면서 전 세계적으로 접속이 중단되었습니다. 해당 지침은 Anthropic의 외국인 직원들을 포함하여, 미국 내외를 불문하고 모든 외국 국적자의 Fable 5 및 Mythos 5 접속을 금지합니다. Anthropic이 실시간으로 미국 사용자과 외국 국적자를 구분할 수 없기 때문에, 모든 사용자에 대해 모델을 폐쇄한 것입니다. 인용된 이유는 국가 안보(서신에 구체적인 내용은 없음)이며, 보도에 따르면 Fable 5의 안전장치(safeguards)를 우회하는 기술이 촉발제가 된 것으로 보입니다. 이 글을 쓰는 시점(6월 15일)에도 서비스는 복구 날짜 없이 중단된 상태입니다. Anthropic은 이를 오해라고 부르며 사용자들을 Opus 4.8로 안내하고 있습니다. 짧은 기간이었지만, 서비스가 중단되기 전에 한 번의 검토를 마칠 수 있었기에 실제로 무엇을 했는지 기록해 두려 합니다.
저는 일반적인 "다른 모델들이 놓친 버그를 찾아냈다"라는 식의 주장이 아니라, 제 리포지토리(repo)의 커밋 히스토리에 남아 있는 **실제 수정 사항(real fixes)**만을 나열하겠습니다.
앱: Daily Diary
단순한 오프라인 다이어리 앱입니다.
- 오프라인 우선 (Offline-first): 데이터는 기기에만 저장되며 클라우드를 사용하지 않음
- 5개 언어 지원: 일본어 / 영어 / 중국어 / 한국어 / 스페인어
- 다크 모드, 기분 표시 기능이 있는 캘린더, 통계 (연속 기록, 기분 트렌드), 전체 텍스트 검색, 과거 기록 무작위 보기, JSON 내보내기/가져오기
Google Play: https://play.google.com/store/apps/details?id=com.diary.daily
기술 스택 (Stack): Flutter 3.x / Dart, Provider, Hive (로컬 NoSQL), Flutter intl.
요청 사항
"모든 것을 다시 작성하라"가 아니라, _"품질 측면에서 의심스러운 부분을 찾아 수정하라"_에 가까웠습니다. 즉, flutter analyze 경고를 해결하고, 테스트를 설정하며, CI(지속적 통합)를 추가하는 작업이었습니다.
발견된 버그들
1. mounted 체크 없이 비동기 간극(async gaps)에서 BuildContext 사용
여러 곳에서 await 이후에 setState / BuildContext (로컬라이제이션 (localization), Navigator)를 호출했습니다. 만약 비동기 호출 중에 위젯이 폐기(disposed)되면 크래시가 발생하는데, 이는 내보내기/가져오기 (export/import) 흐름에서 나타날 수 있는 문제입니다.
// 이전 (예시): await 동안 위젯이 폐기되었더라도 위젯에 접근함
await databaseService.importData(file);
setState(() { /* ... */ }); // 폐기된 경우 예외 발생
...
일반적인 사용 중에는 거의 발생하지 않기 때문에, 직접 테스트할 때도 놓치기 쉽습니다.
2. 아무것도 테스트하지 않은 테스트
남겨져 있던 템플릿 widget_test.dart는 존재하지 않는 MyApp을 참조하고 있었으며, 컴파일조차 되지 않았습니다 (= 사실상 테스트가 0개인 상태). 이를 모델과 Hive 지속성 (persistence)을 위한 12개의 실제 테스트로 교체하였고, 푸시(push) 또는 PR 시에 분석(analyze)과 테스트를 실행하는 CI를 추가했습니다.
3. 47개의 analyzer 경고를 0개로
withOpacity 지원 중단(deprecation) -> withValues로 변경 (27곳), 지원 중단된 ColorScheme API, RadioListTile -> RadioGroup 마이그레이션 작업을 수행했습니다. 주요 의존성(dependencies)들도 업데이트했습니다.
1인 개발자로서 느낀 점
솔직히 Fable이 잡아낸 것은 화려한 기능이 아니었습니다. 제가 스스로는 체계적으로 확인하지 않는 부류의 버그들이었습니다:
- 비동기 간극 (async-gap) mounted -> 특정 타이밍에서만 크래시 발생
- 깨진 테스트 -> 테스트가 있다고 생각하지만, 실제로는 없음
- 쌓여있는 지원 중단 (deprecations) -> 지금은 작동하지만, 나중에 깨짐
기능 자체는 제가 직접 작성할 수 있지만, "특정 조건에서만 실패하는 문제", "테스트가 실제로 무언가를 테스트하고 있는가", "지원 중단된 API 정리" 등은 전담 리뷰어가 없으면 놓치기 쉽습니다. 이에 대해 철저한 검토를 한 번 거친 것은 사이드 프로젝트로서 정말 유용했습니다.
한계도 있습니다. 기기 UI에 의존적인 동작(광고, 내보내기/가져오기 공유)은 CI에서 검증할 수 없으므로, 이 부분은 여전히 제가 실제 기기에서 직접 테스트합니다. 컨셉, 디자인, 기기 테스트, 스토어 제출, 그리고 최종 코드 리뷰는 여전히 저의 몫입니다.
3일 만에 서비스가 중단된 것은 아쉽지만, 중단되기 전에 이 검토를 받을 수 있어서 다행이라고 생각합니다.
Daily Diary는 Google Play에서 확인하실 수 있습니다 — 한 번 사용해 보세요:
📱 https://play.google.com/store/apps/details?id=com.diary.daily
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기