첫 release APK(1.0.0)는 기기 종류 셋(ABI)이 한 파일에 들어 64.4MB 였다 —
문서의 "판마다 30MB 남짓"을 고친다. 개발 PC 에 java 가 PATH 에 없으면
apksigner 가 결과 없이 끝나 서명 확인을 놓치므로 Android Studio 의 Java 를
먼저 잡는 줄을 flutter/README 사내 배포에 더한다.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
계약 1절 "휴대폰 앱 받기"와 6절 운영 도구 명령, 서버 B 에 APK 올리는 차례와 직원 안내(링크 없이),
앱의 서명 키 · release 빌드 · 올리기 전 확인, 웹 화면 절, 스킬 표, App1Shell 보드의 앱 정보 줄.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
firebase-messaging 26.0.1(firebase_core 5.1.0 의 BoM 35.1.0)의 register() · unregister() 는
매니페스트에 firebase_messaging_installation_id_enabled = true 가 없으면 곧바로 "API disabled" 로 거절한다
(2026-11-08 실기기에서 [알림 켜기]가 누르자마자 SYS_001 — SDK 바이트코드로 확인, 플러그인 문서에는 없다).
표시를 켜고, FID 길은 Google Play 서비스 26.12 이상에서만 탄다는 한계를 앱 README 에 적었다.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱 디자인 README 에 "새 메일 알림 · 업데이트 · 앱 아이콘" 절(허락 묻기 · 설정 줄 상태 · 받기 · 누르기 · 로그아웃 차례 ·
"알림이 멈췄습니다"를 보내는 때)을, flutter README 에 Firebase 설정 파일 · 아이콘 만들기 · Play 데이터 보안 신고를,
flutter 스킬에 새 행을, 계약 2절 "새 메일 확인"에 앱이 알림을 받았을 때 한 번 묻는 줄을 더했다.
보드 App1Push 의 ⑧ 칸 설명은 "알림이 멈췄습니다"를 넓힌 결정대로 고쳤다(캔버스 v66).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
머리는 앱 화면, 본문은 스크립트를 끈 WebView 에 앱이 감싼 CSP 문서로
보인다. 받은 HTML 은 서버 정화 뒤 앱이 한 번 더 허용 목록으로 다시 쓰고,
외부 이미지는 [이미지 보기] 뒤 앱이 Dio 로 받아 data: 로 넣는다(토큰이
WebView 에 가지 않는다).
- 읽음 · 중요 · 이동 · 스팸 · 삭제 · 영구 삭제, 붙잡힌 메일의 보내기 취소 ·
예약 취소는 목록과 같은 규칙. 응답은 그 요청이 바꾼 칸만 지금 값에 덮는다
- 첨부는 앱 임시 폴더(cacheDir/downloads)에 받아 FileProvider + ACTION_VIEW
로 연다(파일 여는 플러그인 없이). 열 형식은 확장자 먼저, 웹 문서 · svg ·
설치 파일 · 인증서는 받지 않는다
- 응답 인터셉터가 바이트 · 스트림 실패 본문(64KB 까지)에서 코드를 읽고,
뜻밖의 실패에도 handler.next 로 끝낸다
- 리뷰 H1: 같은 그림을 수백 번 쓴 메일이 문서를 GB 단위로 키우던 것 —
문서에 싣는 그림 글을 나온 횟수까지 세어 10M 자에서 멈춘다
- 리뷰 M1: 짧고 깊은 본문을 화면 isolate 에서 정화하던 것 — 길이와 중첩
비용으로 고르고(6,144자 · 비용 5,000), 그 밖은 Isolate.run
- 새 의존성: webview_flutter 4.14.1 · webview_flutter_android 4.12.0 ·
html 0.15.7(+ csslib 1.0.2) — 배포 2주 넘음. path_provider · mime 은
lock 에 있던 판을 직접 의존으로
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱 1단계의 바탕이다(계약 1절 "앱 로그인" — 서버는 다음 차례, 지금은 가짜 서버로 시험한다).
- 토큰: 리프레시 토큰은 보안 저장소에만, 액세스 토큰은 메모리에만. 첫 실행 표시가 없으면 남은 토큰을
지우고, 안드로이드 백업을 끈다. 보안 저장소 일은 차례로 한다
- 인터셉터: 401 이면 갱신 한 번(동시 401 묶음) 뒤 다시 보내기, AUTH_010 은 me 를 다시 받아 그 단계로,
미리 갱신 30초 전 · 만료는 응답 Date 로, 세션 세대가 바뀐 뒤의 응답은 조용히 버린다,
비밀이 든 요청의 실패 예외는 본문 · Bearer 를 지운다
- 세션: 로그인 · 코드 · 새 비밀번호 · 2단계 켜기 단계의 상태와 늦은 결과 버리기(버린 로그인의 토큰은
조용히 logout), 로그아웃은 메모리부터 비운다, 유예 응답이면 세션 끝 + 조용한 logout
- 모듈 틀: go_router StatefulShellRoute 와 아래 탭 막대 — 모듈 목록은 웹 app-modules.ts 와 짝,
첫 판은 [메일 · 설정]. 모듈끼리 import 하지 않는다
- Riverpod 자동 다시 하기를 끈다, Pretendard 1.3.9(OFL), 확정 글자 크기, 시험 126건
- 판은 Flutter 3.41.9(Dart 3.11.5) — pubspec 의 sdk 하한과 lock 을 함께
리뷰 세 번 반영(AUTH_010 다시 보내기 · 늦은 응답 · 저장 실패 · 로그아웃 차례 · 비밀이 실린 객체 등).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>