talklog — PC 카톡 상시 수집 설계 (폰 리스너 트리거 + 로그인 호스트 탐지)
2026-08-04 페페 결정. 폰 화면 순회(접근성)를 주 수집 경로에서 내리고, 수집은 카톡 PC가 한다. 폰은 "새 메시지가 왔다"는 신호만 준다. 상태·이력 =
handoff.md/ 규칙 =rules.md.
왜 바꾸나 (결정 근거)
| 기존 경로 | 막힌 지점 |
|---|---|
| 폰 접근성 순회(야간 03:00) | ①S25 보안잠금 — PIN 지우면 지문이 삭제돼 은행앱·삼성패스·Secure Folder가 무너진다(페페 확인). PIN 유지 = deviceLocked=1로 3am 생략 ②카톡 26.6.1 UI 변경으로 행 선택자 chat_room_list_item 소멸 → 순회 0방(2026-08-04 실측) |
| PC 카톡 수집 | 잠금·배터리·연결 전부 무관. 파이프라인은 이미 구현·실증(collect_all.py·collect_full.py, 967방 전량 이력) |
페페 요구 3가지 1. 수집은 PC 카톡에서 한다(상시 수집으로 전환). 2. 신규 메시지 감지를 "빨간 미읽음 배지"에 의존하면 안 된다 — 페페가 오는 즉시 읽어 배지가 안 남는다. 3. S25에 리스너를 깔아 도착을 감지하고, 카톡PC가 지금 어느 PC에 로그인돼 있는지 판별해 그 PC에서 수집한다.
구성 (4블록)
[S25 talklog 앱] [미니PC 100.108.234.45:8792] [수집 실행 호스트]
NotificationListener ──POST──▶ /kakao-event → dirty 방 큐 사무실PC POINIMOS01
(카톡 알림 도착 신호) │ 또는 미니PC
├── 실행 게이트(로그인·idle·시간대)
각 PC 프로브 ────POST /kakao-host──────────▶ │ │
(카톡 실행·로그인·idle 하트비트) └──────── 수집 명령 ────────────────▶ collect(방 지정)
│
기존 파이프라인 ◀────────────┘
(parse → ingest → worklog/PFS)
P1 — 폰 리스너 = 도착 신호 (앱)
- 새 앱 만들지 않는다. S25에 이미 있는
com.poin.talklog에NotificationListenerService하나를 추가한다(서버 통신·토큰·주소해석 배관 재사용 =TelemetryClient/Config.resolveServer). - 전송 =
POST /kakao-event {room, sender, ts, preview_hash}. 본문은 기본 미전송(미결 A). - 권한은 adb로 부여 가능 —
settings put secure enabled_notification_listeners <pkg>/<svc>+enabled_notification_listener재적용. 폰 UI 안 건드림. - 폰 카톡 순회 코드는 비활성(알람은 통화 수집만 남긴다). 선택자 재RE 작업이 통째로 사라진다.
- 한계 = 알림 끈 방·요약 알림은 못 잡음 → P4가 메운다.
P2 — 카톡PC 로그인 호스트 탐지 (각 PC 프로브)
- 각 PC(미니PC·사무실PC)에서 5분마다
POST /kakao-host {host, running, logged_in, session, idle_sec, ver}. - 로그인 판정 후보(P0에서 택1 실측 확정):
1.
HKCU\Software\Kakao\KakaoTalk\UserAccounts값 유무 — 미니PC 현재 로그아웃 상태에서 비어 있음 확인(2026-08-04). 로그인 PC와 대조 필요. 2. UIA 최상위창.Name="카카오톡"존재(로그아웃이면 로그인창). 3.KakaoTalk.exe프로세스 + 데이터 폴더 mtime. - 사무실PC 실행 경로 = SSH(22, 열림)로 배포, GUI는 Session 0에서 안 보이므로 프로브·수집 모두
schtasks /it /ru poinpc로 Session 1 실행(기존 레시피rules/remote.md). - 전제 확인 필요 = 카톡 PC가 동시에 한 대만 로그인되는지(P0-2).
P3 — 오케스트레이션 (미니PC)
- dirty 큐:
/kakao-event수신 → 방 단위 dirty 표시 + 디바운스(기본 10분). - 실행 게이트(전부 충족해야 수집):
- 대상 호스트가 로그인 중
- 사람이 안 쓰는 중 —
GetLastInputInfoidle ≥ 10분 (카톡 GUI 자동화는 화면을 뺏는다) - 시간대 정책 — 사무실PC는 퇴근 후 우선, 낮에는 idle 조건일 때만(미결 B)
- 수집 = 기존 수집기에 방 이름 지정 모드를 추가해 dirty 방만 연다(현재는 목록 위→아래 순회 + 컷오프).
- 산출은 기존 경로 그대로(
parse_kakao_export.py→ingest.py→ worklog/PFS).
P4 — 안전망 (배지 비의존 이중화)
- PC 목록 행 시그니처 폴링 — 카톡 메인 목록에서 (방이름│마지막 미리보기│시각)을 UIA로 읽기만 해서 변화 감지. 읽음/안읽음과 무관해 배지 문제를 우회한다. 폰 앱이 쓰던
sweepRowSig와 같은 원리, 클릭 없음. - 주 1회 전량 스윕 —
collect_full.py(정식 내보내기, 실증됨)로 누락 회수. - 무이벤트 경보 — 리스너 이벤트가 N시간(기본 12) 없으면 텔레그램. 조용한 실패를 다시 만들지 않는다.
단계 계획
| 단계 | 내용 | 산출/검증 |
|---|---|---|
| > 진행 = P1 완료(2026-08-04 18:32, APK v0.28 설치·리스너 바인딩 확인). P0는 로그인 판정식·500자 실측 완료, 수집기 회귀만 남음. |
| P0 실측(0.5일) | ①로그인 판정 방식 택1(레지스트리 vs UIA) ②카톡PC 동시 로그인 가능 여부 ③사무실PC에서 Session 1 작업 실행 재확인 ④카톡 PC 26.6.0에서 기존 수집기 좌표·단축키 회귀(6/14 기준 v26.4에서 올라감) | 판정 스크립트 + 회귀 결과표 |
| P1 리스너 | talklog 앱에 NotificationListener 추가·재빌드·재설치(uninstall→install), adb 권한 부여, 서버 /kakao-event | 실제 카톡 메시지 1건 도착 → 미니PC 이벤트 수신 로그 |
| P2 프로브 | 두 PC에 하트비트 프로브 배치(미니PC=pythonw 상주, 사무실PC=schtasks) | 로그인 위치를 옮겨가며 판정 정확도 확인 |
| P3 수집 | 방 지정 수집 모드 + 게이트 + 큐 | dirty 방 1개가 신호→수집→적재까지 종단 |
| P4 안전망 | 행 시그니처 폴링·주1회 스윕·무이벤트 경보 | 리스너 끄고도 누락분이 메워지는지 |
알려진 함정 (기지식 재사용)
- 카톡 PC 수집은 Session 1 GUI 자동화다. Bash 백그라운드(Session 0)에서는 창이 안 보인다.
- 내보내기 후 "내보내기 완료" 모달을 WM_CLOSE로 닫지 않으면 다음 동작이 전부 막힌다(
collector/STATUS.md). - 방/서랍 창이 보조 모니터에 열리면 좌표가 깨진다 →
MoveWindow정규화 선행. - 카톡 PC 버전이 v26.4→26.6.0.5208로 올랐다 → 좌표·메뉴 구성 회귀 필요(P0-4).
- 폰 앱 재설치는 서명 불일치로
-r불가 → uninstall→install + adb 재프로비저닝(rules.md). am start로 카톡을 못 띄운다(not exported) →monkey -p com.kakao.talk -c android.intent.category.LAUNCHER 1.
확정 결정 (페페 2026-08-04)
- A. 리스너는 신호만 보낸다 — 방·발신자·시각. 본문 미전송. ⚠단서 = 500자 이상 본문 함정 주의(아래 실측 절).
- B. 사무실PC 낮 수집 허용 — idle 게이트 하에 낮에도 돈다.
- C. 폰 카톡 순회 코드 폐기 — 접근성 순회는 걷어낸다. 통화 녹음 수집(MediaStore)은 유지.
P0 실측 결과 (2026-08-04, 미니PC에서)
로그인 호스트 판정식 = KakaoTalk PID의 비-루프백 ESTABLISHED 연결 ✅확정
| 대상 | 프로세스 | 레지스트리 UserAccounts |
netstat | 판정 |
|---|---|---|---|---|
| 미니PC(poin-mini) | 실행 중(6212, 창 없음·트레이) | 비어 있음 | 211.249.222.161:443 + 211.242.13.235:**995** ESTABLISHED |
로그인 중 |
| 사무실PC(POINIMOS01) | 실행 중(39504, Session 1) | 4220339@naver.com·delix0731@gmail.com 2건 |
루프백 10151↔10152뿐 | 로그아웃(로그인 창) |
- 🔑레지스트리
UserAccounts는 로그인 이력이지 현재 상태가 아니다 — 오히려 반대로 나온다(로그인된 미니PC가 비어 있고 로그아웃된 사무실PC에 2건). 판정에 쓰면 안 된다. - 판정은
netstat -ano의 외부 ESTABLISHED(특히:995=LOCO). GUI 접근 불필요 → SSH(Session 0)로도 판정 가능 = 사무실PC 원격 판정이 그대로 성립. - 부수 확인 = 같은 계정은 PC 한 대만 로그인된다는 전제와 일치(미니PC 로그인 중 사무실PC는 로그인 창).
- 현재 로그인 위치 = 미니PC. PC 카톡 버전 = 미니
26.6.0.5208/ 사무실26.5.0.5163.
500자 이상 본문 — PC 내보내기 경로엔 함정 없음 ✅실측
text_full/_chunks 105파일 258,825줄(967방 전량 내보내기 산출) 분석:
- 최장 3,439자 한 줄, 500자↑ 552줄, 1,000자↑ 16줄, 2,000자↑ 4줄이 온전히 들어 있다.
- 잘림 마커(전체보기·긴 메시지) 0건. → 카톡 PC 정식 내보내기는 장문을 자르지 않는다.
- 줄바꿈 포함 장문도 안전 — parse_kakao_export.py가 타임스탬프로 시작하지 않는 줄을 직전 메시지의 extra로 이어붙이고 render()가 그대로 다시 쓴다.
- 🔴함정의 실제 위치는 두 곳뿐:
1. 폰 화면 스크랩(접근성) — 말풍선이 접혀 전문을 못 읽었다(구 조사의 readlong 항목). 결정 C로 이 경로가 사라지면서 함께 소멸.
2. 알림 미리보기 — 알림 텍스트는 잘린다. 본문을 안 쓰니 손실은 무관하나, preview_hash를 중복판정에 쓰면 앞부분이 같은 장문끼리 충돌한다 → 해시는 방+발신자+ts(초)+미리보기를 함께 넣어 만든다(설계 반영).