talklog 전용 앱 설계 — 카톡 접근성 화면 스크랩 수집기
PoC 통과(2026-06-11) 후 전용 안드로이드 앱 설계 단일 출처. handoff.md NOW와 한 묶음. 검증 완료: 접근성 권한 켜도 카톡 정상 + 화면 말풍선 텍스트 추출 가능 + 내 발화(오른쪽)도 추출 = 양방향.
목표·범위
- 페페 폰 1대에서 카톡 대화(1:1·단톡, 내 발화 포함)를 접근성 화면 스크랩으로 텍스트 수집 → PC 전송 → Claude 요약 → 저장처(노션/로컬).
- 읽기 전용. 발신 동작 절대 금지(자동 답장·메시지 전송 없음).
검증된 전제 (PoC)
- 접근성 서비스 ON 상태에서 카톡 경고·차단 없음.
- 외부 접근성 앱이 카톡 대화방 화면의 말풍선 텍스트 읽음(FLAG_SECURE 차단 없음).
- 내 말풍선(오른쪽)도 읽힘 → 양방향 수집 가능.
- 매크로 앱(MacroDroid)은 검사(true/false)만 → 전용 앱은 "전체 텍스트 변수 추출" 구현 필요(접근 가능 입증됨 → 추출 거의 확실).
앱 구성 요소
- AccessibilityService - 카톡 대화방 화면의 말풍선 노드 텍스트 추출(발화자 좌/우 구분 → 나/상대, 가능하면 타임스탬프·날짜 구분선도). - 위로 스와이프(가상 제스처)로 과거 메시지 로드 → 한 페이지(스와이프 1회분)씩 누적. - 증분 수집: 방별 마지막 수집 지점(마지막 메시지 타임스탬프 또는 내용 해시)을 체크포인트로 저장 → 다음 실행/재개 시 그 지점 이후만. - 사람 유사 동작: 스와이프·탭 사이 랜덤 지연, 빠른 연속 동작 금지(탐지·차단 완화).
- 오버레이 안내화면 (SYSTEM_ALERT_WINDOW) - 수집 중 풀스크린/상단 오버레이: "📥 수집 중 · 현재 [방이름] · 진행 N/M방" + [⏸ 작업 중단] 버튼. - 오버레이만 pointer-events 받고 그 아래서 접근성이 카톡 조작.
- 중단/재개 (상태머신) - 상태: 대기 → 수집중 → (중단 누름) 안전중단점까지 진행 → 중단됨(체크포인트 저장) → (재개) 체크포인트 다음부터 → 수집중. - 안전중단점 = 페이지(스와이프 1회분) 단위 — 진행 중 페이지 마무리·저장 후 정지(데이터 안 잘림). - 중단 = 자동화가 화면에서 완전히 손 뗌(오버레이 닫힘·접근성 동작 정지) → 페페 폰 100% 정상 사용.
- 전송: 수집 텍스트 → PC 지정 폴더(예:
C:\dev\kakao-inbox) 또는 서버. (방식 미정: 로컬망 HTTP·파일동기 등 Phase2에서.)
처리부 (수집 방식 무관 공통)
PC 폴더감시(신규 파일) → 파싱(날짜·화자) → Claude API 요약(현장명·상대·액션아이템)
→ 저장처: 노션 3-DB(현장/연락처/기록, GS건설 dedup 패턴) 또는 user_brief 로컬
빌드·설치
- 사이드로딩: 구글 심사·허가 불필요(본인 폰 직접 설치). "알 수 없는 출처 허용" + 접근성/오버레이 권한 수동 토글(안드 13+ "제한된 설정" 1단계 해제).
- PC에서 APK 빌드(Android SDK/Gradle 또는 Android Studio) → 폰 설치. 페페 PC 개발환경 유무 확인 선결(없으면 Phase0).
정책 리스크 (감수 결정)
- 서버 패킷 빈도 탐지엔 안 걸림(읽기 전용·발신 없음 → 평범한 사용자와 동일).
- 클라이언트측 "접근성 자동화 존재" 인지 가능성 있음(특정 앱 지목은 패키지명·서명 변경 시 어려움).
- 완화: 읽기만·사람 속도·저빈도·유휴 배치. 본계정 정지 시 카카오 전 서비스 상실 = 리스크 감수 전제.
결정 대기 (3건)
- ① 트리거: 반자동([지금 수집] 버튼, 권장 — 충돌·리스크 통제) vs 완전자동(유휴 감지).
- ② 저장처: 노션 3-DB vs user_brief 로컬 vs 둘 다.
- ③ 페페 PC 안드로이드 개발환경 유무.
단계 분할 (권장)
- Phase 1 최소 수집기: 접근성 추출 + 오버레이 + 중단/재개 → 한 방 텍스트 파일 저장. (UI·정책·추출 실동작 실증)
- Phase 2 증분·다중 방 순회·PC 전송.
- Phase 3 처리부: 폴더감시 → Claude 요약 → 저장처.
보류·병행 후보
- 통화 채널: 제미나이 1단계(갤럭시 자동녹음+텍스트변환→AI)를 별도 병행 가치(카톡과 무관).
PC 일회성 수집기 — 공식 내보내기 자동화 (역공학 완료 2026-06-13)
상시 모바일 앱(위)과 별개 분기. 페페 지시: 상시 모바일은 추후(S25 엣지), 지금은 현재 PC에서 최근 2주 대화 일회성 수집(방별 텍스트+사진 원본, 동영상 제외, AI요약 없음, 대화방 목록 작성, 추후 업무외 방 사용자 지정). 방식 결정 = 공식 "대화 내보내기" 자동화(1:1+단톡 전부·오픈채팅/채널/나와의채팅 제외·1방 시범 후 확대). 코워크(카카오워크)=별 플랫폼이라 기존 카톡 반출 불가 → 폐기.
환경: 카톡 PC v26.4.0.5128, Win11, Python 3.9.13. 의존성=uiautomation·pywinauto·pywin32·comtypes·Pillow·psutil(python -m pip install). 코드=C:\dev\kakao-collector\, 산출물=C:\dev\kakao-inbox\. 로그인 사용자 폴더=%LOCALAPPDATA%\Kakao\KakaoTalk\users\13fa090e…(1.7GB, 로컬은 암호화 .edb — 복호화는 정책위반이라 안 씀).
핵심 제약: 카톡은 목록·말풍선을 자체 GDI 렌더(EVA_ 클래스) → 메시지 본문 UIA 직접추출 불가. 그래서 공식 내보내기(.txt)가 정답. 좌표/화면 기반 → 카톡이 전면(foreground)이어야 동작 = 자동화 중 PC 카톡 점유. 방 열기는 읽음 처리* 부수효과(모든 방식 공통, 본인계정이라 수용).
창 구조(이 PC 실측):
- 메인 창: class=EVA_Window_Dblclk, .Name="카카오톡"(우측 도킹 1528,0 392x1032). 목록=ChatRoomListCtrl(EVA_VH_ListControl_Dblclk) 최근순. 항목 UIA 비노출 → 좌표 클릭. 헤더+필터칩 ~137px, 행높이 ~85px, 행1중심≈(목록좌상단+170,+180).
- 방 열기 = 행 더블클릭(단일=선택만). 방은 별도 top-level 창, class=EVA_Window_Dblclk, window title=방이름(식별 확실). ⚠ win32 GetWindowText는 ANSI(한글 mojibake) → uiautomation .Name으로 매칭.
- 방 창: 메시지영역 EVA_VH_ListControl_Dblclk(UIA 비노출), 입력창 RICHEDIT50W(절대 클릭금지), ≡메뉴=창우측-18,+57.
내보내기 경로(확정):
- 방 창 포커스 → Ctrl+S = "대화 내보내기" 단축키. (메뉴경로 ≡→"대화 내용"→하위[톡클라우드 대화 복원 / 대화 내보내기 Ctrl+S / 채팅방 저장소에 저장 / ⚠️대화 내용 모두 삭제]. 삭제가 인접 → Ctrl+S만 쓰고 메뉴 좌표클릭 회피.)
- Ctrl+S → 표준 "다른 이름으로 저장" 대화상자(class=#32770, .Name="다른 이름으로 저장", UIA 완전제어). 기본 파일명=방이름+날짜, 형식 Text(.txt).
- 제어: 파일명 Edit(ComboBox AutomationId "1148"→Edit, 또는 Edit AutomationId "1001")에 전체경로 SetValue → 저장 버튼 Button AutomationId "1" Invoke. 덮어쓰기창=AutomationId "6"(예).
- 결과: 전체 이력 .txt(UTF-8, BOM 없음*). 예 신동승 185KB·1,396메시지(2019~2026).
내보내기 형식(파싱 규약):
<방이름> 님과 카카오톡 대화
저장한 날짜 : YYYY-MM-DD HH:MM:SS
--------------- YYYY년 M월 D일 요일 ---------------
[화자] [오전|오후 H:MM] 내용 (연속 멀티라인은 접두어 없이 다음 줄)
사진="사진"/"사진 N장", 동영상="동영상", 파일="파일: name", 이모티콘/음성도 placeholder. 원본 미디어 미포함(텍스트 표시만) → 사진 원본은 별도 수집.
PoC 검증 완료(2026-06-13): 신동승 1방 = 열기→Ctrl+S→#32770 UIA저장→신동승.txt(185KB)→parse_kakao_export.py 2주필터 9건(file1·photo3·text5, 2026-06-05~06-13) 정상. 텍스트 체인 전구간 실증. 산출물=C:\dev\kakao-inbox\poc\. 코드 파일: inspect_kakao·activate_shot·discover2~5·reopen_ctrls_test·poc_save·parse_kakao_export.
사진 원본 수집 — 채팅방 서랍 역공학 완료 (2026-06-14)
- 경로: 방창 → ≡(right-18, top+57) → 메뉴 1번 '채팅방 서랍'(▶서브메뉴) 호버 → 서브 '사진/동영상' 클릭 → 서랍 창(EVA_Window_Dblclk, .Name="채팅방 서랍"; 좌=방선택 사이드바, 우=월별 사진 그리드, GDI라 썸네일 UIA 비노출 → 좌표).
- 저장: 썸네일 우클릭 → 컨텍스트(공유/저장) → '저장' = 앨범 통째 저장. 저장처(고정) =
C:\Users\delix\OneDrive\문서\카카오톡 받은 파일\, 파일명KakaoTalk_YYYYMMDD_id[_NN].jpg(날짜 파싱가능 → 2주필터 가능). 저장 후 "저장 결과" 모달(~300x200, 이름없는 EVA_Window) 뜨고 WM_CLOSE로 닫아야 다음 우클릭이 안 막힘 — 핵심 함정(내보내기 완료 모달 ~300x227도 동일). - 그리드: 콘텐츠 x542~1517, 썸네일 pitch~125(열 603·728·…·1353), 행0 y≈327. 썸네일=메시지/앨범 1개. 더블클릭=뷰어(.Name에 날짜 有, 앨범범위만 내비). 단일클릭=무동작. ESC=서랍 닫힘(금지).
- ⚠ 라이브 수집 중 발견·수정한 함정 2건(이거 없으면 사진 전부 실패): ① ≡ 메뉴 구성이 방마다 다름(1:1은 '대화상대 초대하기'가 1번 → 채팅방 서랍이 2번) → 항목을 위→아래 호버하며 첫 ▶서브메뉴 항목=채팅방 서랍 자동 탐지(상단 절반만). ② 방/서랍 창이 보조 모니터·소형으로 열릴 수 있음 →
MoveWindow로 방창(0,0,960,1032)·서랍창(258,0,1260,1373) 고정 정규화 후 좌표 적용.
구현·검증 완료 (코드=C:\dev\kakao-collector\, 산출물=C:\dev\kakao-inbox)
collect_photos.py— 서랍 사진탭 → col1 프로브로 행 탐지(우클릭→메뉴 뜨면 썸네일) → 7열 저장 → 저장폴더 diff → 파일명 날짜로 2주필터 →photos/<방>/이동(해시 dedup), 컷오프밖은_discarded/로 빼 사용자 폴더 원상복구. 신동승 7장 보관/4장 컷오프밖 검증.collect_all.py— 오케스트레이터. 메인목록 행 위→아래 열기(방명=창제목 .Name, 행0 y158·pitch77) → 텍스트 Ctrl+S export(+#32770 제어, 완료모달 닫기) + 2주필터 + 사진수집 + 대화방목록.csv(순번·방이름·유형추정·최근활동·2주내메시지수·사진수·수집여부(사용자지정)·비고). 최신순+핀 대비 연속 N개 컷오프밖이면 종료,--resume(중단 재개), 채널은 서랍없어 graceful skip. 2방 검증 통과.- ✅ 전체 수집 실행 완료(2026-06-14): 55방 텍스트 · 42방 사진 · 사진 189장 · 제외 7방. 컷오프(05-31) 연속 3방 초과 시 자동 종료(COMPLETE). 순차 청크(
--resume --max-new N)로 분할(라이브 UI 병렬 불가). CSV는 디스크 스캔으로 재생성(--build-csv; 실행중 CSV는 목록 스크롤로 누락 가능 → text/·photos/ 디스크가 진실). - 사용자 후처리: CSV
수집여부에서 업무외/개인방 제외 표시(개인방 일부 수집됨 예외갓집 남조카방46장·아빠). 재실행/추가=--resume(기수집 건너뜀). 영구 제외는 collect_all.pyEXCLUDE에 추가(제외 방도 식별 위해 잠깐 열려 읽음 처리됨). - 안전: RICHEDIT 입력창 클릭금지 / 내보내기 Ctrl+S만("모두 삭제" 회피) / 방열림=읽음(수용) / 저장·내보내기 모달 WM_CLOSE / 사람속도 지연.