Files
arasystem/docs/design/app
ttipo 4e779dedd2 docs: 앱 로그인 네 단계의 구현하며 정한 것을 앱 디자인 README · flutter 스킬에 적는다
- 앱 디자인 README: 단계마다 실패를 보이는 곳(표), 안내와 오류 함께, 세션 끝은 상자만,
  [다른 계정으로 로그인]을 막는 때, 2단계 켜기의 처음 초점 · 켠 뒤 알림, 다른 곳에서 켠 경우,
  주소 칸 자판, 글자 크기 맞춤, 새 글, 알려진 한계(인증 앱에 다녀오는 사이 앱이 정리되면 새 키 ·
  최근 앱 미리 보기 · 클립보드 · iOS)
- flutter 스킬 골격 표에 로그인 화면 줄(노티파이어 제한 단계 API · 알림 끄는 묶음 · url_launcher
  쓰는 규칙 · KeepAllText)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 15:57:39 +09:00
..

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). 알림이 뜨면 함께 올라간다.

읽기 (App1Reader)

  • 위 막대: 뒤로 · 삭제 · 더 보기(안 읽음 표시 · 중요 표시 · 이동 · 스팸 신고). 아래 행동 막대: 답장 · 전체 답장 · 전달.
  • 머리(제목 · 보낸 사람 · 받는 사람 펼치기 · 시각)는 앱 화면, 본문은 앱 안 WebView — 스크립트를 끄고 앱이 감싼 문서의 CSP 로 바깥에 나가지 않는다. 외부 이미지는 안내 줄의 [이미지 보기]를 누르면 앱이 받아서 넣는다. 링크는 바깥 브라우저 · mailto 는 앱의 쓰기 화면.
  • 첨부 목록 — 받는 중에는 진행(%)을 보인다.

쓰기 (App1Compose)

  • 위 막대: 닫기 · 첨부 · 보내기. 받는 사람 · 제목은 웹 쓰기 화면처럼 줄 왼쪽에 이름(칸 안에서 떠오르는 꼴이 아니다). 받는 사람 추천은 맞은 글자를 굵게.
  • 참조 · 숨은참조는 펼쳐서. 첨부는 제목 아래(휴대폰은 본문이 길어지면 아래 첨부가 묻힌다) — 크기 · 빼기 · 올리는 중.
  • 본문은 글만(서식 편집은 다음 판). 서명은 본문과 따로 된 칸에 [서명 빼기]만 — 서명 고치기는 웹에서. 답장의 원본 메일은 접혀 있고 펼쳐 볼 수 있다.
  • 보낸 뒤에는 쓰기를 시작한 화면(읽기 · 목록)으로 돌아가고, 그 화면 아래에 "메일을 보냈습니다. [보내기 취소]"와 남은 시간 막대.

새 메일 알림 (푸시)

  • 알림 내용은 "새 메일 N통"만 — 보낸 사람 · 제목이 Google · Apple 서버를 거치지 않게. 누르면 메일 모듈의 받은편지함으로(알림에는 모듈 이름과 id 만 싣는다).

처음 판에서 미룬 것

서식 편집 · 대용량 첨부 · 필터 · 주소록 화면 · 서명 고치기 · 계정 설정(웹에서) · 오프라인 저장 · iOS.