8.9 KiB
8.9 KiB
Friendly Map — Claude 작업 지침 (인수인계)
0. 가장 먼저 (이 지시가 모든 것보다 최우선)
- 모든 가이드·문서·결정·진행 기록·화면 점검은 프로젝트의
wiki/Obsidian 보관함에 저장하고 관리한다. 새 내용은 wiki 에 먼저 쓰고, 다른 문서(README 등)는 wiki 를 가리키기만 한다. - 세션을 시작하면
wiki/홈.md와wiki/00 최우선 규칙.md부터 읽는다. 일할 때마다wiki/진행 로그/<날짜>.md,wiki/02 결정 기록.md를 갱신한다.
이 파일은 이전 대화(claude.ai 프로젝트 "Frindly Map")에서 정한 것을 새 세션에 넘기는 문서다. 세션을 시작하면 먼저 이 파일, wiki/홈.md, tool/check_modules.py 를 읽고, 작업 전에 아래 원칙을 한 번 읊고 시작한다.
최우선 규칙 (모든 규칙보다 위)
- 질문은 반드시 최종 화면이 담긴 설치 가능한 APK 를 먼저 건넨 뒤(사용자가 설치해 써 보며 답할 수 있게), 캡처도 함께 보여 주고, 그 화면을 기준으로 "이렇게 하면 / 저렇게 하면" 비교로만 묻는다. 화면 없는 질문 금지.
- 암호 비트 수·키 구조·함수 설계 같은 내부 기술 질문은 하지 않는다. 내가 정하고 결과에 적는다. 책임 회피성 질문 금지.
- 방법론: 화면 먼저 → 화면 보고 사용자가 답 → 그 답에 따라 내부 아키텍처를 바꾼다.
- 모든 기록(결정·진행 로그·로드맵·화면 점검)은 프로젝트의
wiki/Obsidian 보관함에 남긴다. 일할 때마다 갱신. - 화면 캡처:
flutter test test_ux/shots_test.dart --update-goldens→test_ux/shots/*.png(한글 글꼴build/ux/kr.ttf필요, 맥의 /Library/Fonts/Arial Unicode.ttf 복사).
사용자와 일하는 규칙 (1순위, 어기지 말 것)
- 모든 답변은 한글. 고친 파일은 일부 발췌가 아니라 처음부터 끝까지 완본으로 보여 준다.
- "목업"이라는 말은 쓰지 않는다 ("화면 설계"라고 한다).
- 나는 솔루션 개발자다: 구조가 기능보다 먼저다. 화면과 내부를 분리한다.
- 모듈화 필수. 모듈은 다른 모듈을 고치지 않고 빼고 끼울 수 있어야 한다.
tool/check_modules.py가 의존 방향을 검사한다(새 모듈은 ALLOW 표에 등록). - 소스 파일은 300~400줄, 최대 700줄.
- 모듈별로 시험한다(
tool/test_module.sh <모듈>). 시험이 끝난 모듈은 다시 만들지 않고 그 위에 쌓는다. - 한 번에 한 플랫폼. 지금은 안드로이드만. 다른 플랫폼은 사용자가 지정할 때
platform_<이름>모듈만 새로 붙인다. - 단계마다 되묻지 말고 합리적으로 정해 진행하고, 결정한 내용은 결과에 적는다. 멈춰 서서 "대기"하지 않는다. (단, 되돌릴 수 없는 파괴적 작업은 먼저 묻는다.)
제품
Android 다크모드 인맥 앱(Flutter/Dart). 옛 "Family MAP" + 카카오톡식 대화. 목적별 명함(개인/회사/학교/그룹·여행/가족) 교환, "어디서 봤지?" 유추, 가계도, 연결 고리, 검색, 자동 연동 추천, 내 정보 숨기기, 가족 모임(촌수·통화 요약·생일/기일 알림).
이미 정한 기술 결정 (바꾸지 말 것)
- 모든 데이터는 기기에 암호화 저장(안드로이드 SQLCipher). 전화번호는 식별자일 뿐 키 재료가 아니다.
- 모든 기기가 서버 겸 클라이언트(P2P). 외부 DB(server/)는 암호화된 임시 우편함 + 기준 시각 제공뿐.
- (2026-10-26 사용자 결정으로 바뀜) 복구 코드·조각·보관 키 없음. 처음 시작은 이름·번호만, 키는 조용히 만든다. 폰을 잃으면 데이터는 끝. 새 폰에서 다시 시작하면 관계를 유지하는 사용자 각자가 승인(다시 연결) 또는 제명(그 번호 영구 차단). 탈퇴 후 재가입 없음. 사람 식별은 전화번호 1순위·이름 2순위.
- 대화는 영구 보관, 1MB/기기 사용률 80% 초과 시 별도 저장(조절 가능). 시각은 1/100초, 충돌 시 먼저 쓴 변경이 앞선다. 고친 명함은 "다시 보내기"에서만 보낸다. 그룹 대화 키는 돌리지 않는다.
- 가족 모임 데이터(가계도, 생일, 기일, 통화 주제)는 기기 안에만 저장하고 어디로도 보내지 않는다. 전화번호 없는 친척은
local:<id>번호의 기기 안 전용 사람이다.
구조
lib/modules/<이름>/<이름>.dart가 모듈의 공개 입구(예외: platform_ui.dart, storage_sqlite.dart). 다른 모듈은 입구 파일만 import.- 모듈: core, platform, platform_android, storage, keys, sharing, sync, transport, discovery, inference, layout, visibility, kinship, events, groups, work, app, ui.
- 조립은 모듈 밖:
lib/main.dart,lib/composition/android_bootstrap.dart. - 안드로이드 전용 플러그인은 platform_android 에서만 import (PLATFORM_ONLY 목록).
- 화면은
AppScope.of(context).app(FriendlyApp)의 서비스만 쓴다.
상태 (2026-10-26 기준)
- 맥 podman Flutter(stable) 컨테이너에서
flutter analyze문제 없음,flutter test307개 통과(widget_test.dart 포함), 서버(Python) 18개 통과, check_modules.py 통과. - 2026-10-26 추가: groups 모듈(그룹 정의·비밀번호 잠금), 주소록 가져오기(flutter_contacts), 설정의 "그룹 · 주소록". 관계망 로드맵 1단계(그룹 계층: 학교 › 초등~대학원, 가족 › 친가·외가·처가·시가·촌수 모름, 회사 › 회사 › 팀) 끝. 2단계(채팅·사람 화면의 "관계 정하기": RelateService, 촌수 맞춰 친가·외가·처가, 촌수 모름 모음, 연결 고리) 끝. 3단계(work 모듈, WorkService: 팀 대화방, 📌 업무 맡기기·정리, 🚨 긴급 호출 즉시 알림) 끝. 4단계(CareerService: 받은 회사 명함 비교로 이직 알림, 확인하면 이전 회사 그룹에 이전 구성원으로 흐리게·새 회사 그룹으로 이동, 지우기·무시) 끝. 로드맵 1~4단계 완료.
flutter build apk --debug성공(app-debug.apk 약 190MB). 컨테이너마다 SDK 34·35, CMake 를 다시 내려받아 15분 넘게 걸린다. 빌드할 때는 시험을 같이 돌리지 않는다(podman 머신 8GB 에서 Gradle 데몬이 메모리 부족으로 꺼진 적 있음).- 빌드 경고(아직 빌드를 막지는 않음):
nsd_android,flutter_contacts가 Kotlin Gradle Plugin 을 직접 적용한다. 앞으로 Flutter 판에서 빌드가 실패할 수 있으니, 지원 판이 나오면 nsd 버전을 올린다. geolocator_android 는 deprecated API 를 쓴다는 Note 만 나온다. - 확인 안 된 곳: 실제 기기에서 화면 실행과 플러그인 동작(geolocator, call_log, url_launcher, flutter_local_notifications, timezone, sqflite_sqlcipher, nsd, mobile_scanner, sensors_plus, flutter_secure_storage).
- pubspec.lock 은 이 컨테이너(Flutter stable)에서 풀린 판을 기준으로 올린다(2026-10-26 flutter_contacts 추가 때부터).
- 빌드 캐시:
-v fm-gradle:/root/.gradle -v fm-pub:/root/.pub-cache를 붙이면 두 번째 빌드부터 빨라진다. - 알려진 한계: 윤달 생일 미지원(기일만 지원), 음력 변환 1951~2049년, 통화 기록 읽기(READ_CALL_LOG)는 Play 스토어 제한, WebRTC·앱 잠금·복구 단어 재확인 알림·공유 이미지/PDF 저장·우편함 요청 서명은 미구현. 문자 인증은 서버에
--sms-webhook연결이 필요.
빌드·시험 방법 (Mac Pro 2013, podman)
Flutter 는 직접 설치하지 않고 컨테이너로 쓴다 (프로젝트는 홈 폴더 안에 있어야 podman machine 이 공유한다):
podman machine start
podman run --rm -it -v "$PWD":/app -w /app ghcr.io/cirruslabs/flutter:stable bash
flutter create --platforms=android --org com.friendlymap --project-name friendly_map .
python3 tool/android_patch.py # 권한·수신기·desugaring·minSdk 패치 (여러 번 돌려도 같은 결과)
flutter pub get && flutter analyze && flutter test
flutter build apk --debug # build/app/outputs/flutter-apk/app-debug.apk
build/,.dart_tool/는 만들어지는 폴더라 저장소에 올리지 않는다(.gitignore).android/는 Gitea 에는 올라가 있다.- 서버 시험:
cd server && python3 -m unittest test_mailbox test_verify. - 모듈 경계 검사:
python3 tool/check_modules.py. - 저장소: http://192.168.88.15:3180/diadmin/frindlymap (Gitea, remote origin). 고친 뒤 커밋해서 Gitea 에 푸시한다.
- GitLab 에는 올리지 않는다. 단, 하루 한 번 메이저 업그레이드 때만 GitLab 에 올린다(원격은 아직 등록되지 않음).
작업 방식
- 고치면 해당 모듈 시험을 다시 돌리고, 마지막에 전체 시험과 check_modules.py 를 돌린다.
- 새 기능은 (1) 순수 모듈 또는 서비스 + 시험 → (2) 화면 순서로, 기존 시험이 끝난 모듈은 고치지 않는다.
- 끝낼 때 한글로: 무엇이 바뀌었나, 무엇을 돌려 확인했나, 확인 못 한 것은 무엇인가.