---
title: "네이버 블로그 매일 자동 포스팅 시스템 설계 v1 (Sonnet 1M + 액션테스트 계획)"
from: claude-code
to: ["jadong"]
project: "naver-blog"
date: 2026-05-07T18:19:07.169431+09:00
status: sent
type: report
---

# 네이버 블로그 매일 자동 포스팅 시스템 설계 v1

> **작성일**: 2026-05-07
> **환경**: vhagar (kontology, BOSGAME M4 Plus) + Galaxy S23+ (USB ADB, serial R3CW60BHSAT)
> **계정**: 분유타는대표 (tidtyd222) — 1계정 MVP, 안정화 후 민지(wngmlxx12) 추가
> **LLM**: Claude Sonnet 1M (OpenClaw 채널콘솔 계정토큰)
> **폰 자동화**: droidrun/mobilerun (8.3K stars)
> **문서 버전**: v1 (액션테스트 전). 테스트 후 v2로 업데이트 예정.

---

## 0. 진행 순서

| 단계 | 내용 | 상태 |
|------|------|------|
| **v1 문서화** | 이 문서. 설계 전체를 문서로 확정 | 현재 |
| **Phase 0: S23 액션테스트** | mobilerun 설치 → S23 실물 테스트 → 동작 검증 | 다음 |
| **v2 문서화** | 액션테스트 결과 반영하여 스펙 수정 | Phase 0 후 |
| **코딩** | v2 스펙 기반으로 구현 | v2 확정 후 |

**코딩은 v2 스펙 확정 전까지 하지 않는다.**

---

## 1. 전체 아키텍처

```
┌─────────────────────────────────────────────────────────────────┐
│  systemd timer (매일 19:00 ± 랜덤 10분)                          │
│                                                                 │
│  ① keyword_engine      오늘의 키워드 선정                        │
│        ↓                                                        │
│  ② content_generator   Sonnet 1M 원고 생성 (OpenClaw 채널콘솔)   │
│        ↓                                                        │
│  ③ seo_formatter       SE 호환 HTML 변환                         │
│        ↓                                                        │
│  ④ phone_poster        mobilerun → S23 Chrome → SE → 발행       │
│        ↓                                                        │
│  ⑤ result_logger       Supabase 로깅 + Telegram 알림            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### 1.1 왜 Sonnet 1M인가

| 항목 | DeepSeek V4 (이전안) | Sonnet 1M (현재안) |
|------|---------------------|-------------------|
| 한국어 품질 | 중상 | 최상 |
| 컨텍스트 | 128K | **1M** — 전체 키워드 DB + 전략문서 + 기발행 히스토리 한번에 로드 |
| 비용 | $0.01~0.02/포스트 | **$0 (구독 내 계정토큰)** |
| 페르소나 일관성 | few-shot 필요 | 1M 윈도우에 기존 발행글 전부 넣어서 톤 학습 |
| Vision | 없음 | 있음 (mobilerun에서도 사용) |

**핵심 변경**: 앤트로픽이 OpenClaw 채널콘솔(계정로그인토큰)을 다시 허용. 구독 기반 auth로 Sonnet 1M 호출 가능 → API 과금 없음.

### 1.2 왜 mobilerun + S23인가

네이버 블로그에는 공개 포스팅 API가 없다. 모든 자동화 도구(AutoPanda, Gazet 등)가 브라우저 자동화로 SmartEditor를 조작한다.

mobilerun이 다른 방식보다 나은 이유:
- **IP/핑거프린트**: 실제 폰의 LTE/WiFi IP + 실제 디바이스 핑거프린트. 서버발 Selenium보다 안전
- **네이버 봇 탐지 회피**: 실제 Chrome on Android. WebDriver 감지 없음
- **세션 관리**: 폰 Chrome에 로그인 유지. 쿠키/세션 자연스럽게 유지
- **vision + 접근성 트리**: WebView 내부도 조작 가능
- **LLM reasoning**: UI 변경에 적응 가능 (하드코딩된 좌표 아님)

### 1.3 파일 구조

```
~/projects/naver-blog/
├── automation/
│   ├── __init__.py
│   ├── pipeline.py                  # 메인 오케스트레이터
│   ├── keyword_engine.py            # 키워드 선정
│   ├── content_generator.py         # 원고 생성 (Sonnet 1M)
│   ├── seo_formatter.py             # SE 호환 HTML 변환
│   ├── phone_poster.py              # mobilerun S23 포스팅
│   └── result_logger.py             # Supabase 로깅
├── templates/
│   ├── info_post.jinja2             # 정보성 글 프롬프트
│   └── daily_post.jinja2            # 일상 글 프롬프트
├── config/
│   ├── accounts.yaml                # 계정별 설정 (페르소나/시간대/키워드풀)
│   ├── keywords_used.json           # 사용된 키워드 이력 (날짜, 카테고리)
│   └── .env                         # API 키 (gitignore)
├── account_01_분유타는대표/
│   ├── drafts/                      # 생성된 원고 (.md)
│   ├── published/                   # 발행 완료 (날짜_키워드.md + .html)
│   ├── queue/                       # 발행 대기 / needs_review
│   └── images/                      # Phase 2: 이미지 자산
├── research/                        # 기존 키워드 분석 데이터
│   └── keyword-analysis/            # 1,638개 키워드 DB
├── docs/
│   └── specs/                       # 이 문서
├── tests/                           # Phase 0 액션테스트 스크립트
│   ├── test_mobilerun_basic.py      # mobilerun 기본 동작
│   ├── test_naver_se_paste.py       # SE 에디터 HTML paste
│   └── test_e2e_post.py             # 전체 플로우 E2E
└── .venv/                           # Python 가상환경
```

---

## 2. LLM 연동: OpenClaw 채널콘솔

### 2.1 채널콘솔이란

- **OpenClaw MCP Server** (Lightsail 43.203.12.112:8765)가 Claude API를 호출할 때 사용하는 인증 경로
- **계정로그인토큰**: Claude 구독 계정의 세션 토큰. API 키와 달리 별도 과금 없음
- 앤트로픽이 2026-05-07 기준 다시 허용

### 2.2 Sonnet 1M 호출 경로

```
automation/content_generator.py
  → OpenClaw Gateway (ws://127.0.0.1:18789 또는 Tailscale)
  → Anthropic API (account auth)
  → Sonnet 1M response
```

**또는** 직접 호출:
```
automation/content_generator.py
  → Anthropic SDK (python)
  → ANTHROPIC_API_KEY (채널콘솔 토큰)
  → Sonnet 1M response
```

**액션테스트에서 확인할 것**: 채널콘솔 토큰으로 Sonnet 1M 직접 호출이 되는지, 아니면 OpenClaw 게이트웨이 경유가 필요한지. 호출 방법에 따라 content_generator.py 구현이 달라짐.

### 2.3 mobilerun LLM provider

mobilerun도 LLM이 필요하다 (폰 UI 이해 + 액션 계획). 옵션:

| 방식 | 설명 | 비용 |
|------|------|------|
| Anthropic provider (채널콘솔) | `mobilerun[anthropic]` + 채널콘솔 토큰 | $0 |
| OpenAI-compatible proxy | OpenClaw를 OpenAI 호환 엔드포인트로 노출 | $0 |
| DeepSeek fallback | 채널콘솔이 mobilerun에서 안 되면 | ~$0.05/세션 |

**액션테스트에서 확인할 것**: mobilerun이 채널콘솔 토큰을 ANTHROPIC_API_KEY로 받아들이는지.

---

## 3. 콘텐츠 생성 파이프라인

### 3.1 키워드 선정 (keyword_engine.py)

**데이터 소스 (3중)**:
1. 기존 `research/keyword-analysis/` — 1,638개 키워드, 검색량/경쟁도 데이터
2. Naver SearchAd API — [naver-search-mcp](https://github.com/isnow890/naver-search-mcp) 오픈소스. 실시간 검색량 조회
3. `published/` 히스토리 + `keywords_used.json` — 중복 방지

**선정 로직**:

```
1. 카테고리 결정 (라운드로빈 + 비율 가중)
   육아 40% / 자영업 25% / 보안IT 20% / 운동 15%
   → 최근 발행 이력 기반으로 부족한 카테고리 우선

2. 후보 필터링
   - 해당 카테고리 키워드 풀에서
   - 30일 내 미사용
   - 경쟁도 "낮음" 또는 "중간" 우선 (블루오션 전략)
   - 월간 검색량 100+ (너무 적으면 의미 없음)

3. 최종 선택
   score = 검색량 × (1 / 경쟁도 가중치) × 전환가치
   상위 1개 선택

4. 기록
   keywords_used.json에 {날짜, 키워드, 카테고리} append
```

**SaaS 리버싱으로 고도화할 부분** (Phase 4):
- **Blai 패턴**: 블로그 현재 지수(DIA 점수) 대비 이길 수 있는 키워드만 선택
- **BlogTalk 패턴**: 블로그 레벨 매칭 — 신규 블로그가 빅키워드 가면 저품질 위험
- **Gazet 패턴**: SmartBlock 키워드 → 네이버가 원하는 소제목 구조 파악

### 3.2 원고 생성 (content_generator.py)

**모델**: Sonnet 1M (채널콘솔)

**1M 컨텍스트 활용 전략**:
Sonnet 1M의 핵심 장점은 방대한 컨텍스트 윈도우. 한 번의 호출에 아래 전부를 로드:

```
[System Prompt]
  ├── 페르소나 정의 (POSTING_STRATEGY.md §분유타는대표)
  ├── marketer-system 규칙
  │   ├── 다변수 임팩트 공식 v2 (V1~V10)
  │   ├── 카피 파워 5피처 (MR, DA, ET, UC, GG)
  │   └── 바디 핸들링 규칙 5 + 안티패턴 5
  ├── 네이버 SEO 규칙
  │   ├── C-Rank 알고리즘 핵심
  │   ├── 저품질 방지 가이드라인
  │   └── SmartBlock 최적화 (리버싱 후 추가)
  └── 출력 형식 지정 (마크다운 → HTML 변환 규칙)

[Few-shot Examples]
  ├── 기발행 글 3~5개 전문 (published/ 에서 로드)
  │   → 톤, 구조, 분량의 실제 레퍼런스
  └── 각 글의 키워드, 카테고리, 검색 성과 (있으면)

[User Prompt]
  ├── 오늘의 키워드: {keyword}
  ├── 카테고리: {category}
  ├── 템플릿: {info_post 또는 daily_post}
  ├── SmartBlock 소제목 가이드 (있으면)
  └── 특별 지시 (시즌 이슈, 연결할 내부 글 등)
```

이렇게 하면 매 포스트가 기존 발행글과 톤이 일관되고, marketer-system 규칙을 자연스럽게 따른다.

**템플릿 2종**:

| 템플릿 | 용도 | 분량 | 구조 |
|--------|------|------|------|
| info_post | 검색 유입용 | 1500~2500자 | 도입 3줄 → H2 3~4개(각 300~500자) → 관련글 → 결론 → 해시태그 → 서이추 |
| daily_post | 서이추/공감용 | 800~1200자 | 사진 → 에피소드 본문 → 사진 2~3장 → 질문 마무리 → 해시태그 |

**카테고리→템플릿 매핑**:
- 육아: daily_post 70% / info_post 30%
- 자영업: info_post 60% / daily_post 40%
- 보안IT: info_post 90% / daily_post 10%
- 운동: daily_post 80% / info_post 20%

**품질 검증 (자동, 생성 직후)**:

| 항목 | 기준 | 실패 시 |
|------|------|---------|
| 자수 | info: 1500~2500 / daily: 800~1200 | 재생성 |
| 키워드 밀도 | 2~4% (키워드 등장/총 자수) | 재생성 |
| H2 소제목 | info: 3~4개, daily: 0~2개 | 재생성 |
| 이미지 슬롯 | 최소 3개 `[IMAGE_SLOT_N]` | 경고 (Phase 1은 텍스트만) |
| 해시태그 | 5~7개 | 자동 보정 |
| 서이추 문구 | 하단에 존재 | 자동 append |
| 500자 미만 | 절대 차단 | 재생성 |

재생성은 1회만. 2회째도 실패 → `queue/needs_review/` 저장 + Telegram 알림.

### 3.3 SEO 포매팅 (seo_formatter.py)

**검증된 CDP SE 메서드** (2026-05-02, 프레데터 Chrome에서 확인):

clipboard에 inline style HTML을 넣고 Ctrl+V → SE 에디터가 자동으로 `se-fs{N}` 클래스로 매핑.
bold, color, center align, 표 모두 보존. 발행본 #224266857023 수준 polished output.

**변환 규칙**:

| 마크다운 요소 | SE HTML 출력 |
|-------------|-------------|
| `## 소제목` | `<p style="font-size:24px"><b>소제목</b></p>` |
| 본문 단락 | `<p style="font-size:16px">내용</p>` |
| `**강조**` | `<b>텍스트</b>` |
| 색상 강조 | `<span style="color:#00b4b4">텍스트</span>` |
| 가운데 정렬 | `<p style="text-align:center">...</p>` |
| 구분선 | `<hr>` |
| 이미지 슬롯 | `[IMAGE_SLOT_N]` → Phase 1: 제거, Phase 2: Unsplash URL |
| 해시태그 | 별도 메타데이터로 분리 (mobilerun이 태그 필드에 입력) |
| 서이추 문구 | 마지막 `<p>` 블록 |

**출력 형태**:
```python
{
    "title": "신생아 홈캠 추천 — 업계 사람 기준 TOP 3",
    "html_body": "<p style='font-size:16px'>도입부...</p>...",
    "tags": ["신생아홈캠", "홈캠추천", "아기모니터", "육아필수템", "분유타는대표"],
    "category": "보안IT",
    "template": "info_post",
    "word_count": 1850,
    "keyword": "신생아 홈캠 추천"
}
```

**액션테스트에서 확인할 것**:
- S23 Chrome 모바일 SE 에디터에서 clipboard HTML paste가 동일하게 작동하는지
- PC Chrome과 모바일 Chrome에서 SE 동작 차이가 있는지
- 긴 HTML(2000자+)의 clipboard 전달 한계

---

## 4. 폰 포스팅 자동화 (mobilerun + S23)

### 4.1 mobilerun 아키텍처 이해

```
┌─────────────────────────────────────────────┐
│  vhagar (kontology)                         │
│                                             │
│  phone_poster.py                            │
│    → MobileAgent(goal="...", config=...)    │
│    → mobilerun SDK                          │
│       ├── LLM (Sonnet 1M vision)           │
│       ├── ADB 명령 실행                     │
│       └── Portal APK 통신 (TCP 8080)        │
│                                             │
│  ┌─── USB ADB ───┐                         │
│  │                │                         │
│  │  S23+          │                         │
│  │  ├── Portal APK (접근성 트리 제공)       │
│  │  ├── Chrome (m.blog.naver.com)          │
│  │  └── 네이버 계정 로그인 상태 유지        │
│  │                │                         │
│  └────────────────┘                         │
└─────────────────────────────────────────────┘
```

**Portal APK**:
- mobilerun이 `mobilerun setup --device R3CW60BHSAT`으로 자동 설치
- 안드로이드 접근성 서비스 활성화 → UI 트리를 TCP 8080으로 노출
- 커스텀 키보드 IME 제공 → 한글 입력 지원

**두 가지 인식 모드**:
1. **접근성 트리**: 네이티브 앱 UI에 적합. 빠르고 정확
2. **Vision (스크린샷)**: WebView/복잡한 UI에 필수. SE 에디터는 이것이 필요

### 4.2 mobilerun 설치 계획

```bash
# 1. vhagar에 설치
cd ~/projects/naver-blog
python3 -m venv .venv
source .venv/bin/activate
pip install uv
uv pip install 'mobilerun[anthropic]'

# 2. 채널콘솔 토큰 설정 (테스트에서 확인 후 확정)
# 방법 A: 직접 Anthropic SDK
export ANTHROPIC_API_KEY=<채널콘솔 토큰>
# 방법 B: OpenClaw 경유 (OpenAI compatible)
export OPENAI_API_KEY=<openclaw 토큰>
export OPENAI_BASE_URL=http://127.0.0.1:18789/v1

# 3. S23 Portal 설치
mobilerun setup --device R3CW60BHSAT

# 4. 연결 검증
mobilerun ping --device R3CW60BHSAT

# 5. provider 설정
mobilerun configure
# → provider: Anthropic (또는 OpenAI compatible)
# → model: claude-sonnet-4-6 (1M)
```

### 4.3 포스팅 흐름 상세

```
사전 조건:
  - S23 Chrome에 tidtyd222 로그인 상태
  - S23 화면 켜짐 (adb shell input keyevent KEYCODE_WAKEUP)
  - Portal APK 접근성 서비스 활성화

Step 1: 화면 준비
  adb -s R3CW60BHSAT shell input keyevent KEYCODE_WAKEUP
  adb -s R3CW60BHSAT shell input keyevent KEYCODE_MENU  (잠금 해제 필요 시)

Step 2: HTML → S23 클립보드
  방법 A: adb shell am broadcast
    adb -s R3CW60BHSAT shell am broadcast -a clipper.set -e text "<html>"
    (Clipper 앱 필요. 없으면 방법 B)
  
  방법 B: 파일 push → 폰에서 읽기
    adb -s R3CW60BHSAT push /tmp/post.html /data/local/tmp/post.html
    adb -s R3CW60BHSAT shell "cat /data/local/tmp/post.html | am broadcast ..."
  
  방법 C: mobilerun의 type 명령으로 직접 입력
    (긴 텍스트는 느리지만, 클립보드 방식이 안 되면 대안)

  → 액션테스트에서 가장 안정적인 방법 결정

Step 3: mobilerun agent 실행
  goal:
    1. Chrome 앱 열기
    2. 주소창에 m.blog.naver.com 입력 후 이동
    3. 글쓰기(연필 아이콘) 버튼 탭
    4. SmartEditor 로딩 대기 (2~3초)
    5. 제목 입력 필드 탭 → 제목 텍스트 입력
    6. 본문 영역 탭
    7. 롱프레스 → 컨텍스트 메뉴에서 "붙여넣기" 탭
    8. 붙여넣기 완료 대기 (1~2초)
    9. 하단으로 스크롤
    10. 태그/해시태그 입력 필드 찾아서 탭
    11. 태그 하나씩 입력 + 엔터 (5~7개)
    12. "발행" 또는 "완료" 버튼 탭
    13. 발행 확인 다이얼로그가 나오면 확인 탭
    14. 발행 완료 화면 확인

  config:
    max_steps: 40
    reasoning: True (단계별 계획 수립)
    vision: True (SE 에디터 WebView 인식)
    timeout: 300초

Step 4: 결과 확인
  - mobilerun result.success 체크
  - 스크린샷 캡처 (선택적)
  - 발행 URL 추출 시도 (Chrome 주소창에서)
```

### 4.4 네이버 로그인 세션 관리

| 시나리오 | 감지 방법 | 대응 |
|---------|----------|------|
| 정상 로그인 | 글쓰기 버튼 존재 | 정상 진행 |
| 세션 만료 | "로그인" 텍스트 감지 | Telegram 알림 → 수동 재로그인 |
| Chrome 업데이트 팝업 | "업데이트" 다이얼로그 감지 | 닫기 → 정상 진행 |
| 네이버 점검 | 에러 페이지 감지 | 30분 후 재시도 |

**Phase 1에서는 자동 재로그인을 구현하지 않는다.** 보안 이슈 + 2FA 가능성. 세션 만료는 Telegram 알림으로 대응.

### 4.5 mobilerun 주요 제약 & 대응

| 제약 | 심각도 | 대응 | 테스트 항목 |
|------|--------|------|-----------|
| SE WebView 접근성 트리 불완전 | 높음 | vision 모드 필수 | AT0-3 |
| 클립보드 HTML 길이 제한 | 중간 | 파일 push fallback | AT0-4 |
| Portal APK 접근성 서비스 중지 | 중간 | 사전 체크 + 자동 재활성화 | AT0-2 |
| 한글 IME 입력 깨짐 | 중간 | mobilerun Portal IME 사용 | AT0-5 |
| vision 토큰 비용 | 낮음 | 채널콘솔 = $0 | - |
| 폰 화면 꺼짐 | 낮음 | KEYCODE_WAKEUP 사전 전송 | AT0-1 |

---

## 5. Phase 0: S23 액션테스트 계획

**목적**: 코딩 전에 mobilerun + S23 + 네이버 블로그 SE 에디터의 실제 동작을 검증. 결과를 v2 스펙에 반영.

### 5.1 테스트 환경 준비

```bash
# 0. venv 생성 + mobilerun 설치
cd ~/projects/naver-blog
python3 -m venv .venv && source .venv/bin/activate
pip install uv && uv pip install 'mobilerun[anthropic]'

# 1. S23 Portal APK 설치
mobilerun setup --device R3CW60BHSAT

# 2. 접근성 서비스 활성화 확인
mobilerun ping --device R3CW60BHSAT

# 3. LLM provider 설정
mobilerun configure
# provider → 채널콘솔 토큰 테스트 (안 되면 DeepSeek fallback)
```

### 5.2 테스트 항목

| ID | 테스트 | 방법 | 성공 기준 | 기록할 것 |
|----|--------|------|----------|----------|
| **AT0-1** | 폰 화면 제어 | `mobilerun run "turn on screen, unlock phone" --device R3CW60BHSAT` | 화면 켜짐 | 잠금 해제 필요 여부, PIN 필요 여부 |
| **AT0-2** | Chrome 열기 + 네비게이션 | `mobilerun run "open Chrome, go to m.blog.naver.com" --vision` | 블로그 메인 표시 | 소요 시간, step 수, 에러 |
| **AT0-3** | SE 에디터 진입 | 블로그 메인 → 글쓰기 버튼 → SE 에디터 로딩 | SE 에디터 표시 | vision으로 인식 가능 여부, 접근성 트리 상태 |
| **AT0-4** | 클립보드 HTML paste | `adb push post.html` → SE 에디터에서 paste | HTML 서식 보존 | paste 방법(broadcast/file/type), 서식 보존 여부, 길이 한계 |
| **AT0-5** | 한글 제목 입력 | SE 제목 필드에 한글 텍스트 입력 | 한글 정상 표시 | IME 방식, 글자 깨짐 여부 |
| **AT0-6** | 해시태그 입력 | 태그 필드에 5개 태그 입력 | 태그 5개 등록 | 태그 구분자(엔터/쉼표), 입력 속도 |
| **AT0-7** | 임시저장 | 발행 대신 임시저장 | 임시저장 성공 | 임시저장 버튼 위치, 확인 다이얼로그 |
| **AT0-8** | E2E 테스트 발행 | 전체 플로우: Chrome → SE → 제목+본문+태그 → 발행 | 글 발행 확인 | 총 소요 시간, 총 step 수, 실패 지점 |
| **AT0-9** | LLM provider 테스트 | 채널콘솔 토큰으로 mobilerun 실행 | 정상 동작 | 토큰 형식, env 변수, 에러 메시지 |
| **AT0-10** | 세션 만료 감지 | 로그아웃 상태에서 글쓰기 시도 | "로그인" 감지 | mobilerun이 로그인 화면을 인식하는지 |

### 5.3 테스트용 더미 원고

```html
<p style="font-size:24px"><b>테스트 포스팅 — 자동화 시스템 검증용</b></p>
<p style="font-size:16px">이 글은 블로그 자동 포스팅 시스템의 E2E 테스트를 위한 더미 원고입니다.</p>
<p style="font-size:16px">서식이 정상적으로 적용되는지 확인합니다.</p>
<p style="font-size:24px"><b>소제목 테스트</b></p>
<p style="font-size:16px">본문 <b>볼드</b> 테스트. <span style="color:#00b4b4">색상</span> 테스트.</p>
<hr>
<p style="font-size:16px">구분선 위아래 텍스트.</p>
<p style="font-size:14px" style="color:#888">서이추 환영합니다 💕 소통해요!</p>
```

태그: `테스트`, `자동화검증`, `삭제예정`

**테스트 후 해당 글은 즉시 삭제 또는 비공개 처리.**

### 5.4 테스트 결과 기록 양식

각 테스트 항목에 대해 `tests/results/AT0-{N}.md`에 기록:

```markdown
# AT0-{N}: {테스트명}
- 일시: 2026-05-XX HH:MM
- 결과: PASS / FAIL / PARTIAL
- 소요시간: X초
- mobilerun steps: N
- 에러: (있으면)
- 스크린 기록: (텍스트 설명, 스크린샷 금지 — 세션 날림)
- 발견사항: (v2 스펙에 반영할 내용)
- 결론: (이 방식 유지 / 대안 필요)
```

### 5.5 테스트 순서

```
AT0-9 (LLM provider) → AT0-1 (화면) → AT0-2 (Chrome) → AT0-5 (한글)
→ AT0-3 (SE 에디터) → AT0-4 (HTML paste) → AT0-6 (태그)
→ AT0-7 (임시저장) → AT0-10 (세션만료) → AT0-8 (E2E)
```

LLM provider부터 테스트. 채널콘솔이 안 되면 나머지 테스트를 DeepSeek fallback으로 진행.

---

## 6. 스케줄링 & 모니터링

### 6.1 systemd timer

```ini
# ~/.config/systemd/user/naver-blog-post.timer
[Unit]
Description=Daily Naver Blog Post (분유타는대표)

[Timer]
OnCalendar=*-*-* 19:00:00
Persistent=true
RandomizedDelaySec=600

[Install]
WantedBy=timers.target
```

```ini
# ~/.config/systemd/user/naver-blog-post.service
[Unit]
Description=Naver Blog Posting Pipeline

[Service]
Type=oneshot
WorkingDirectory=/home/tlswk/projects/naver-blog
ExecStart=/home/tlswk/projects/naver-blog/.venv/bin/python -m automation.pipeline --account 분유타는대표
EnvironmentFile=/home/tlswk/projects/naver-blog/config/.env
TimeoutStartSec=600
```

**설계 근거**:
- `RandomizedDelaySec=600`: 매일 정확히 같은 시각 방지 → 네이버 봇 탐지 회피
- `Persistent=true`: vhagar 꺼져있다가 켜지면 놓친 실행 보상 실행
- `TimeoutStartSec=600`: mobilerun vision + Sonnet 응답 시간 감안 (10분)
- user-level systemd: root 불필요, ADB 권한 유지

### 6.2 모니터링 & 알림

```
pipeline.py 실행 결과:

성공:
  → published/ 에 {날짜}_{키워드}.md + .html 저장
  → Supabase daily_log에 append
  → Telegram "✅ 블로그 발행 완료: {제목}" 알림

실패:
  ├─ 키워드 선정 실패
  │   → 수동 키워드 풀에서 랜덤 선택 (fallback)
  │   → Telegram "⚠️ 키워드 선정 실패, fallback 사용" 알림
  │
  ├─ 원고 생성 실패
  │   → 1회 재시도 (5초 대기)
  │   → 여전히 실패 → queue/needs_review/ 저장
  │   → Telegram "❌ 원고 생성 실패, 수동 검토 필요" 알림
  │
  ├─ 폰 포스팅 실패
  │   → 3회 재시도 (60초 간격)
  │   → 여전히 실패 → Telegram "❌ 포스팅 실패" + 마지막 에러
  │   → 원고는 queue/에 보관 → 다음날 재시도 또는 수동 발행
  │
  └─ 세션 만료
      → Telegram "🔐 네이버 로그인 필요 — S23 Chrome에서 수동 로그인 해주세요"
```

Telegram 알림: 기존 BalerionBot (@BalrerionBot, id: 8620124076) 활용.

### 6.3 Supabase 로깅

`daily_log`에 블로그 포스팅 결과 append.
**⚠️ CONTEXT_BRIDGE_GUARD 준수**: summary SET 교체 금지, jsonb 배열 교체 금지.

```json
{
  "type": "blog_post",
  "account": "분유타는대표",
  "keyword": "신생아 홈캠 추천",
  "category": "보안IT",
  "template": "info_post",
  "title": "신생아 홈캠 추천 — 업계 사람 기준 TOP 3",
  "status": "published",
  "url": "https://blog.naver.com/tidtyd222/...",
  "word_count": 1850,
  "mobilerun_steps": 23,
  "mobilerun_duration_sec": 45,
  "timestamp": "2026-05-07T19:03:22+09:00"
}
```

---

## 7. 에러 핸들링 & 네이버 보호

### 7.1 재시도 정책

| 단계 | 재시도 | 간격 | 최종 실패 시 |
|------|--------|------|-------------|
| 키워드 선정 | 2회 | 즉시 | 수동 키워드 풀 랜덤 |
| 원고 생성 | 1회 | 5초 | queue/needs_review |
| SEO 포매팅 | 0회 | - | plain text 포스팅 |
| 폰 포스팅 | 3회 | 60초 | Telegram 알림, queue 보관 |

### 7.2 네이버 저품질 방지 가드레일

기존 POSTING_STRATEGY.md 규칙을 코드로 **하드 강제**:

| 규칙 | 구현 | 위반 시 |
|------|------|---------|
| 하루 최대 1개 발행 | pipeline.py에서 오늘 published/ 체크 | 실행 중단 |
| 500자 미만 차단 | content_generator.py 검증 | 재생성 |
| 동일 키워드 30일 재사용 금지 | keywords_used.json 체크 | 다른 키워드 선택 |
| 발행 시간대 고정 | systemd timer 19:00±10분 | timer가 강제 |
| 계정간 30분 간격 | 민지 추가 시 timer 시간 분리 | timer가 강제 |
| 연속 포스팅 금지 | published/ 최근 기록 체크 | 최소 20시간 간격 |

### 7.3 디바이스 핑거프린트 보호

기존 POSTING_STRATEGY.md §리스크관리 준수:
- Chrome 프로필: tidtyd222 전용 (S23 기본 Chrome)
- NNB 쿠키: 자연 갱신 (강제 삭제 안 함)
- Canvas/WebGL 핑거프린트: S23 실제 디바이스 = 고유하고 일관됨 (문제없음)
- User-Agent: 실제 Chrome on Android (조작 없음)

---

## 8. SaaS 리버싱 대상 (Phase 4)

콘텐츠 생성 로직 고도화를 위한 리버싱 우선순위:

| 순위 | 서비스 | URL | RE 목표 | 방법 |
|------|--------|-----|---------|------|
| 1 | **Gazet AI** | gazet.ai | SmartBlock 키워드 → 소제목 구조 | 웹 네트워크 탭 감청 |
| 2 | **Blai** | blai.co.kr | C-Rank/DIA 스코어링 모델 | API 엔드포인트 분석 |
| 3 | **BlogTalk** | blogtalk.io | 블로그 레벨 매칭 키워드 추천 | 크롬 확장 분석 |
| 4 | **AutoPanda** | autopanda.co.kr | SE 에디터 자동화 플로우 | 데스크탑 앱 디컴파일 |
| 5 | **naver-search-mcp** | github/isnow890 | SearchAd API 호출 패턴 | 오픈소스 직접 활용 |

**리버싱에서 가져올 것**:
- Gazet: "키워드를 넣으면 네이버가 원하는 소제목 구조가 나온다" — 이 파이프라인
- Blai: "이 블로그의 현재 DIA 점수는 X이고, 이 키워드는 이길 수 있다/없다" — 이 판단 로직
- BlogTalk: "신규 블로그인데 이 키워드는 가지 마라" — 레벨 매칭

---

## 9. 구현 로드맵

### Phase 0: 액션테스트 (이 문서 확정 직후)
- mobilerun 설치 + S23 셋업
- AT0-1 ~ AT0-10 전수 테스트
- 결과 기록 → v2 스펙 반영

### Phase 1: MVP 코딩 (v2 스펙 후, 2~3일)
- phone_poster.py: 검증된 방법으로 SE 포스팅
- seo_formatter.py: 마크다운 → SE HTML
- 수동 원고 1개 → 자동 포스팅 E2E

### Phase 2: 콘텐츠 자동화 (2~3일)
- keyword_engine.py: 키워드 DB 기반 선정
- content_generator.py: Sonnet 1M 원고 생성
- pipeline.py: 전체 오케스트레이션
- 3일간 매일 1건 수동 모니터링

### Phase 3: 스케줄링 + 모니터링 (1일)
- systemd timer 설정 (user-level)
- Supabase 로깅 연동
- Telegram 알림 연동
- 1주간 무인 운영 모니터링

### Phase 4: 고도화 (지속)
- SaaS 리버싱 (Gazet, Blai) → 콘텐츠 품질 향상
- SearchAd API 연동 → 실시간 키워드 데이터
- 이미지 자동 삽입 (Unsplash API → AI 이미지 생성)
- 민지 계정 추가 (timer 분리, 시간대 오전 10:00)
- 성과 대시보드 (발행 이력 + 방문자 + 검색유입 추적)

---

## 10. 비용 추정 (월간)

| 항목 | 이전안 (DeepSeek) | 현재안 (Sonnet 1M 채널콘솔) |
|------|-------------------|---------------------------|
| 원고 생성 (30회) | ~$0.30~0.60 | **$0** (구독 내) |
| mobilerun vision (30회) | ~$1.50~3.00 | **$0** (채널콘솔) |
| SearchAd API | 무료 | 무료 |
| Supabase | 기존 인프라 | 기존 인프라 |
| **합계** | **~$2~4/월** | **~$0/월** |

채널콘솔이 mobilerun에서 안 되면 mobilerun만 DeepSeek fallback → ~$1.50~3.00/월.

---

## 11. 의존성 정리

| 패키지 | 용도 | 설치 |
|--------|------|------|
| mobilerun[anthropic] | 폰 자동화 | `uv pip install` |
| anthropic | Sonnet 1M 호출 | `pip install anthropic` |
| jinja2 | 프롬프트 템플릿 | `pip install jinja2` |
| pyyaml | 설정 파일 | `pip install pyyaml` |
| supabase | 로깅 | `pip install supabase` |
| requests | HTTP 호출 | 내장 |

---

## 12. 미결 사항 (액션테스트에서 확인)

| ID | 질문 | 영향 범위 |
|----|------|----------|
| Q1 | 채널콘솔 토큰이 Anthropic SDK에서 직접 작동하는가? | content_generator.py 구현 |
| Q2 | 채널콘솔 토큰이 mobilerun ANTHROPIC_API_KEY로 작동하는가? | phone_poster.py LLM provider |
| Q3 | S23 모바일 Chrome SE 에디터에서 HTML clipboard paste가 되는가? | clipboard 전달 방식 |
| Q4 | 긴 HTML (2000자+)의 ADB 클립보드 전달 한계는? | seo_formatter.py 출력 길이 |
| Q5 | mobilerun vision이 SE 에디터 WebView를 인식하는가? | phone_poster.py goal 작성 |
| Q6 | 한글 입력이 mobilerun Portal IME로 정상 동작하는가? | 제목/태그 입력 방식 |
| Q7 | S23 잠금화면 자동 해제가 필요한가? (PIN/패턴) | 사전 준비 스크립트 |
| Q8 | Portal APK 접근성 서비스가 재부팅 후에도 유지되는가? | 안정성 |
