- 앱 디자인 README: 고르기(줄 누르기 · 바뀌는 단추 · 영구 삭제 · 읽음 뒤 끝내기 · 선택 풀기), 붙잡힌 메일, 알림 두 갈래, 서랍, 30일 줄 · [찾기] 준비 중, 새 메일 확인과 병합 규칙(웹과 다른 점), 크기 맞춤, 메일함 이름 차례 - flutter 스킬 골격 표: 메일 목록 · 앱 틀 줄(틀은 Scaffold 가 아니다 · ShellBarHidden · 알림 두 갈래 · 생명주기 안 프로바이더 · 가짜 서버의 한 프레임 응답) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ARA SYSTEM 앱 — 디자인 기준
안드로이드 앱(Flutter — flutter/)의 화면 기준이다. 보드는 웹과 같은 디자인 캔버스의 "앱 1단계 화면" 줄에 있고, 저장소 사본은 docs/design/webmail/App1*.dc.html(캔버스 사본 폴더 — canvas.json 이 모든 보드를 가리킨다)이다.
화면 글의 원본은 보드다 — 이 문서는 정한 것과 까닭만 적는다. 웹 README(docs/design/webmail/README.md)의 원칙 · 「화면 문구 — 사용자에게 말하듯」을 그대로 따르고, 다른 점만 여기에 적는다.
앱 1단계 (2026-11-05 확정 — App1Login · App1MailList · App1Reader · App1Compose · App1Shell)
첫 판은 안드로이드 먼저(Play 내부 테스트), 로그인 전체 + 메일 기본 + 새 메일 알림이다. iOS 는 맥 · Apple 개발자 계정을 준비한 뒤.
크기 · 글꼴 (웹과 다른 점)
- 누르는 곳 48(웹 44). 예외는 받는 사람 칩의 ✕ 40 하나(밀도 예외 — 사용자 확정).
- 글자: 화면 글 15 · 입력 칸 16 · 메일 본문 15(줄 간격 1.75) · 위 막대 제목 18. 글꼴은 웹과 같은 Pretendard(Regular · Medium · SemiBold · Bold — OFL, 앱 안 라이선스 화면에 싣는다).
- 색은 웹 토큰(
frontend/src/styles/tokens.css) 그대로 — 바탕 #0B3640 · 강조 #0E7C86. - 휴대폰 틀에 가짜 상태 표시줄을 그리지 않는다.
앱 틀 (App1Shell) — 모듈이 늘어나는 구조
- 아래 탭 막대(Material 3 NavigationBar · 높이 72 · 고른 탭은 청록 바탕 56×32 안의 아이콘)가 웹의 전역 앱 레일에 해당한다. 모듈 목록은 웹
frontend/src/shared/constants/app-modules.ts와 짝(메일 · 캘린더 · 파일 · 주소록 · 설정 — 같은 이름 · 차례). - 켜진 모듈만 보인다(웹은 준비 중 모듈을 꺼진 채 보이지만, 휴대폰의 누를 수 없는 탭은 어색해서 숨긴다). 첫 판은 [메일 · 설정], 캘린더 · 파일 · 주소록이 준비되면 하나씩 늘어난다.
- 탭마다 이동 기록을 따로 지킨다(메일에서 읽던 화면이 설정 탭에 다녀와도 남는다). 읽기 · 쓰기는 탭 막대 없는 전체 화면이다.
- 여러 통 고르기 중에는 탭 막대를 숨긴다(잠깐의 상태이고, 다른 탭으로 가면 고른 것을 잃는다). ✕ · 뒤로 가기로 나오면 다시 보인다.
- 화면 낭독기 이름은 "앱 메뉴".
- 설정 탭: 내 정보(이름 · 주소) · 알림(새 메일 알림 켬/끔) · 앱 정보(앱 버전 · 오픈소스 라이선스) · 문의 연락처 · [로그아웃]. 비밀번호 · 2단계 인증 같은 계정 설정은 웹에서 한다. [로그아웃]은 데이터를 지우는 일이 아니라 회색 테두리 단추이고, 누르면 확인 창(처음 초점 [취소]) — 로그아웃하면 이 휴대폰의 새 메일 알림도 오지 않는다고 알린다.
로그인 (App1Login) — 네 단계
-
단계는 웹 로그인 틀과 같다: 주소 · 비밀번호 → (2단계를 켠 직원) 인증 앱 코드 → (임시 비밀번호로 처음) 새 비밀번호 정하기 → (2단계 필수이고 아직 안 켬) 2단계 인증 켜기.
-
첫 단계만 큰 브랜드 띠, 그다음 단계는 짙은 띠(56)에 ARA 마크와 [다른 계정으로 로그인] — 웹처럼 주소 줄 안에 단추를 두면 390 폭에 들지 않는다.
-
칸 이름은 칸 위(웹과 같다 — 웹 · 앱을 함께 쓰는 직원에게 같은 모양, 오류 글도 칸 아래에 잘 보인다). 첫 단계 비밀번호 칸에 [보기].
-
2단계 켜기는 같은 휴대폰이라 QR 을 찍을 수 없다 — [인증 앱에 추가](인증 앱을 바로 연다) · 키와 [복사](키를 직접 넣는 길) · 코드 칸. 인증 앱을 찾지 못하면 키를 직접 넣으라고 알린다.
-
웹 첫 화면의 메일 프로그램(IMAP) 안내 줄은 넣지 않는다(앱이 메일 앱이다). 문의 연락처 줄은 웹과 같은 자리.
-
구현하며 정한 것(2026-11-06 — 보드에는 아직 없다)
-
실패를 보이는 곳(웹 로그인 틀과 같은 결 — 화면이 칸 · 상자에 보이는 코드만 알림을 끈다):
단계 칸 아래 위쪽 상자 그 밖 주소 · 비밀번호 VAL_001(주소 칸)AUTH_004(두 칸 빨강 · 비밀번호 비움)전역 알림( REQ_001포함 — 웹과 같다)인증 앱 코드 AUTH_006·AUTH_007·VAL_001(칸을 비움)REQ_001(코드 그대로)AUTH_004· 10분 지남은 첫 단계로(주소는 남긴다), 나머지는 전역 알림새 비밀번호 AUTH_005(임시 비밀번호) ·VAL_001(새 비밀번호) ·AUTH_006·AUTH_007(코드)REQ_001· 넘기기 실패 + [다시 시도]전역 알림 2단계 켜기 AUTH_006·AUTH_007(코드) ·AUTH_005(지금 비밀번호)AUTH_008+ 새 키 ·REQ_001서버의 VAL_001과 나머지는 전역 알림 -
칸 아래에는 안내와 오류를 함께 보인다(오류가 나도 "다음 코드가 뜨면 넣어 주세요" 같은 안내가 남는다).
-
세션이 끝나 로그인 화면으로 오면 위쪽 상자에
AUTH_002문구만 보이고 알림(스낵바)은 띄우지 않는다(웹은 대화상자). -
[다른 계정으로 로그인]은 코드 단계에서는 늘 누를 수 있고(늦은 결과는 버린다), 새 비밀번호 · 2단계 켜기를 보내거나 넘기는 동안은 막는다(서버가 이미 바꿨을 수 있다 — 웹과 같다).
-
2단계 켜기는 처음 초점을 코드 칸에 두지 않는다 — 자판이 [인증 앱에 추가]를 가리지 않게(웹은 둔다). 켠 뒤 알림은 "2단계 인증을 켰습니다. 메일 프로그램은 앱 비밀번호로 연결합니다."이고 웹의 [앱 비밀번호 만들기] 단추는 뺐다(앱에 그 화면이 없다).
-
다른 곳에서 2단계를 켜면 이 세션은 서버가 끊는다(계약 6절) — 다음 요청에서 로그인 화면 +
AUTH_002. 키를 받을 때 이미 켜져 있으면(AUTH_008뒤 확인) 이 단계를 건너뛴다. -
첫 단계 주소 칸만 자판 추천을 켠다(끄면 안드로이드 엔진이 비밀번호 보기 형식을 섞어 @ 자판이 나오지 않는다). 자동 고침은 모든 칸에서 끈다.
-
보드의 13.5 · 14.5 · 15.5 글자는 가까운 테마 역할(13 · 15 · 15)로 맞췄다. 한글은 낱말 단위로 줄을 바꾼다(
KeepAllText— 보드의word-break: keep-all). -
새 글(보드에 없던 상태): 키를 복사하지 못하면 "키를 복사하지 못했습니다. 키를 보고 인증 앱에 직접 입력해 주세요.", ③ 안내 "지금 비밀번호를 한 번 더 넣어 주세요." — 그 밖은 웹 로그인 틀의 글을 그대로 옮겼다.
-
알려진 한계: 인증 앱에 다녀오는 사이 안드로이드가 앱을 정리하면 돌아왔을 때 새 키가 나온다(인증 앱에 먼저 넣은 항목은 지우고 다시 넣어야 한다 — 옛 키의 코드는
AUTH_006, 웹의 새로고침과 같은 결). 키 화면은 최근 앱 미리 보기에 찍히고(FLAG_SECURE 없음), 복사한 키는 클립보드에 남으며 안드로이드 13 이상은 복사 미리 보기에 보인다(Flutter 클립보드는 민감 표시를 못 한다 — 네이티브 채널이 든다). iOS 의 [인증 앱에 추가]는 iOS 를 붙일 때 여는 방식을 바꾼다.
-
메일 목록 (App1MailList)
-
위 막대: 서랍 열기 · 메일함 이름 · 찾기. 서랍은 메일함만(안 읽은 수는 회색 글 — 뱃지 없음), 탭 막대 위까지 화면 전체를 덮는다.
-
줄: 동그란 사진(40) · 보낸 사람 · 시각 / 제목 · 첨부 표시 / 미리 보기 한 줄. 안 읽음은 굵게, 중요는 별. 웹 목록은 미리 보기를 넣지 않지만 휴대폰은 폭이 좁아 제목 한 줄로는 메일을 가르기 어렵다 — 앱에서만 넣는다(사용자 확정).
-
사진을 누르거나 줄을 길게 누르면 고르기 — 위 막대가 고르기 막대(읽음 표시 · 중요 표시 · 이동 · 삭제)로 바뀌고 탭 막대를 숨긴다. 삭제는 휴지통으로 옮기고 알림의 [되돌리기].
-
당겨서 새로고침. 빈 메일함 · 빈 휴지통(30일 안내 글).
-
[메일 쓰기]는 넓은 단추로 탭 막대 위(아래에서 88). 알림이 뜨면 함께 올라간다.
-
구현하며 정한 것(2026-11-06 — 보드에는 아직 없다)
- 고르기: 고르는 중에는 줄을 눌러도 고르기 · 풀기다(열지 않는다). 고른 것이 모두 읽음이면 [안 읽음 표시], 모두 중요면 [중요 해제]로 바뀐다. 휴지통에서는 빨간 [영구 삭제](확인 창 — 처음 초점 [취소]), 스팸메일함의 삭제는 휴지통으로 옮기기다. 읽음 · 중요 표시가 끝나면 보드대로 고르기를 끝낸다(웹은 남긴다) — 통째로 실패하면 고른 것을 되살린다. 다른 메일함 · 다른 탭으로 가면 고른 것을 푼다(계약 2절).
- 붙잡힌 메일(보내기 취소 · 예약)은 고를 수 없다 — 누르면 "고를 수 없습니다" 알림, 화면 낭독기는 꺼진 칸의 까닭을 읽는다. 보낼 시각 + 2초에 다시 보고 남아 있으면 5초마다 세 번 더(서버 시각으로 잰다 · 실패해도 이어 본다).
- 알림: [되돌리기]가 있는 알림은 [메일 쓰기] 바로 아래 한 줄(10초 — 화면 낭독기를 켠 동안은 저절로 닫지 않는다), 단추 없는 알림은 전역 스낵바로 띄워 [되돌리기] 줄을 바꿔 끼우지 않는다. [메일 쓰기]는 알림이 뜨면 함께 올라간다.
- 서랍은 메일함을 바꿔 끼운다(방문 기록을 쌓지 않는다 — 다른 메일함은 받은편지함 위에 하나만). 단추로만 연다(가장자리 밀기 없음). 메일함 목록을 받기 전에는 뼈대, 받지 못했으면 [다시 시도].
- 휴지통 · 스팸메일함에 메일이 있으면 맨 위에 30일 줄(웹 13단계 — 보드에는 빈 휴지통만). [찾기]는 아직 "메일 찾기는 아직 준비 중입니다. 지금은 웹메일에서 찾아 주세요."
- 새 메일 확인: 화면이 보이고(다른 탭 · 전체 화면에 가리지 않음) 앱이 앞에 있을 때만 1분마다, 다시 보이면 10초가 지났을 때 바로(웹 3단계). 가려진 목록은 바뀜을 적어 두었다가 보일 때 맞춘다. 다시 받은 쪽이 메일함 끝까지면 그 밖의 옛 메일은 다른 곳에서 지운 것으로 보고 남기지 않는다(웹은 남긴다 — 서버의 hasNext 는 끝까지 받았을 때만 거짓이다). 끝 표시는 보이는 동안 다음 쪽을 이어 부르고, 같은 커서가 되풀이되면 [다시 시도]로 멈춘다.
- 크기: 탭 막대의 고른 탭 알약은 Material 3 그대로 64×32(보드 56×32), 글자는 테마 역할로 맞췄다(12.5 → 12 · 13.5 → 13 · 14.5 → 15 · 17 → 18, 굵기 650 → 700 · 450 → 500). 탭 막대는 위 안전 영역을 빼고, 고르는 중 알림 줄은 시스템 내비게이션 위에 뜬다.
- 내 메일함 이름의 차례는 대소문자를 가리지 않는 비교다 — 영문 · 한글이 섞인 이름은 웹(
localeCompare('ko'))과 다를 수 있다.
읽기 (App1Reader)
- 위 막대: 뒤로 · 삭제 · 더 보기(안 읽음 표시 · 중요 표시 · 이동 · 스팸 신고). 아래 행동 막대: 답장 · 전체 답장 · 전달.
- 머리(제목 · 보낸 사람 · 받는 사람 펼치기 · 시각)는 앱 화면, 본문은 앱 안 WebView — 스크립트를 끄고 앱이 감싼 문서의 CSP 로 바깥에 나가지 않는다. 외부 이미지는 안내 줄의 [이미지 보기]를 누르면 앱이 받아서 넣는다. 링크는 바깥 브라우저 · mailto 는 앱의 쓰기 화면.
- 첨부 목록 — 받는 중에는 진행(%)을 보인다.
쓰기 (App1Compose)
- 위 막대: 닫기 · 첨부 · 보내기. 받는 사람 · 제목은 웹 쓰기 화면처럼 줄 왼쪽에 이름(칸 안에서 떠오르는 꼴이 아니다). 받는 사람 추천은 맞은 글자를 굵게.
- 참조 · 숨은참조는 펼쳐서. 첨부는 제목 아래(휴대폰은 본문이 길어지면 아래 첨부가 묻힌다) — 크기 · 빼기 · 올리는 중.
- 본문은 글만(서식 편집은 다음 판). 서명은 본문과 따로 된 칸에 [서명 빼기]만 — 서명 고치기는 웹에서. 답장의 원본 메일은 접혀 있고 펼쳐 볼 수 있다.
- 보낸 뒤에는 쓰기를 시작한 화면(읽기 · 목록)으로 돌아가고, 그 화면 아래에 "메일을 보냈습니다. [보내기 취소]"와 남은 시간 막대.
새 메일 알림 (푸시)
- 알림 내용은 "새 메일 N통"만 — 보낸 사람 · 제목이 Google · Apple 서버를 거치지 않게. 누르면 메일 모듈의 받은편지함으로(알림에는 모듈 이름과 id 만 싣는다).
처음 판에서 미룬 것
서식 편집 · 대용량 첨부 · 필터 · 주소록 화면 · 서명 고치기 · 계정 설정(웹에서) · 오프라인 저장 · iOS.