제목 없는 아티클
[ Villion 작업 분담 계획 ]
1. 인도인 개발자 (Sai, Himanshu)
업무 (1주차): 워드프레스 → Villion 콘텐츠 이전 플러그인 제작
목적:
고객이 자기 WordPress 웹사이트에 플러그인 하나만 설치하면,
블로그 포스트·페이지가 Villion Publish로 자동 이전되는 툴.
Inblog가 네이버 블로그·티스토리에서 콘텐츠 끌어오는 것과 동일한
마이그레이션 모델.
고객 관점 플로우:
1) wp-admin에서 "Villion Migrate" 플러그인 설치
2) Settings에서 Villion API Key 입력 → 연결 확인
3) Migrate 페이지에서 이전 범위 선택 (전체 / 카테고리 / 날짜 범위)
4) Start 클릭 → 진행 상태 실시간 추적
5) 완료 후:
- Villion Publish에 이전된 콘텐츠 확인
- 301 Redirect 맵(CSV) 다운로드 — 기존 SEO 자산 보존용
내가 전달해야 할 것 (24일 금요일까지):
- Villion 백엔드 API 계약 (request/response shape) 확정
POST /api/v1/blog/import/wordpress/register
POST /api/v1/blog/import/wordpress/execute
GET /api/v1/blog/import/wordpress/jobs/{id}
→ backend_beta/docs/api-reference.md에 고정
- Mockoon config (실서버 배포 전까지 로컬 스텁)
- Repo write 권한 (github.com/Villion-inc/villion-wordpress)
- Slack 채널 #wp-migrate + 두 명 초대
- Day 1 로컬 세팅 가이드 (wp-env 기반 WordPress)
두 사람의 업무는 완전 독립. 서로 기다릴 필요 없음. 파일 영역도 겹치지
않으므로 각자 자기 브랜치에서 작업 → Week 1 말 main으로 병합하면 플러그인
완성.
════════════════════════════════════════════════════════
Sai — 플러그인 토대 + Villion 연결
════════════════════════════════════════════════════════
업무 정의:
플러그인이 WordPress에 설치·동작하기 위한 하부 구조와, Villion 백엔드와의
연결(등록·인증·상태 확인)을 담당. 콘텐츠 이전 기능 자체는 건드리지 않음
(Himanshu 담당).
파일 영역:
villion-migrate.php
uninstall.php
admin/views/settings.php
admin/views/logs.php
includes/class-villion-auth.php
includes/class-villion-logger.php
phpcs.xml
composer.json
.github/workflows/ci.yml
산출물:
1) 플러그인 진입점 (villion-migrate.php)
- WordPress 플러그인 표준 헤더 (Name, Version 0.1.0, License GPLv2,
Text Domain villion-migrate, Domain Path /languages)
- main 클래스 싱글턴 부트스트랩
- register_activation_hook: 기본 옵션 초기화
- register_deactivation_hook: 진행 중 transient 정리 (데이터 삭제 X)
- uninstall.php: wp_options 중 villion_* prefix 전부 정리
2) wp-admin 메뉴 등록
최상위 메뉴 "Villion" (capability: manage_options)
서브메뉴 등록 골격: Settings / Migrate / Logs
(Settings, Logs는 본인이 구현. Migrate 페이지는 Himanshu가 채움)
3) Settings 페이지 (admin/views/settings.php)
- 필드:
Villion API Key (text, 암호화 저장)
Villion Backend URL (text, 기본값 https://api-dev.villion.io)
- 폼 저장:
wp_nonce_field + check_admin_referer + current_user_can
openssl_encrypt + WP AUTH_KEY/AUTH_SALT로 API Key 암호화 후
update_option('villion_api_key_encrypted', ...)
평문 DB 저장 금지
- "Test Connection" 버튼 → AJAX로 Villion health 엔드포인트 호출
성공 시 "Connected to site_id: xxx" 표시
실패 시 에러 메시지
4) Site Registration (includes/class-villion-auth.php)
- Settings에 API Key 최초 저장 시 자동 트리거
- POST /api/v1/blog/import/wordpress/register
Body: { site_url, admin_email, plugin_version,
wp_version, php_version }
Response: { site_id, api_key, backend_base_url }
- site_id를 wp_options에 저장 (villion_site_id)
- HTTP 호출은 wp_remote_post 직접 사용
(retry 3회 / 15s timeout / HTTPS 강제 / is_wp_error 체크)
5) 로깅 (includes/class-villion-logger.php)
- 정적 메서드 Villion_Logger::log($level, $message, $context = [])
- error_log 래퍼 + 최근 100개 이벤트를 wp_options(villion_recent_events)
에 JSON 배열로 저장 (append + trim)
- Logs 서브메뉴에서 최근 이벤트 테이블로 렌더
- API Key / 민감 정보 로깅 금지
6) 개발 인프라
- phpcs.xml: WordPress-Extra ruleset, text-domain=villion-migrate
- composer.json: dev deps (squizlabs/php_codesniffer,
wp-coding-standards/wpcs, phpunit/phpunit ^9)
- .github/workflows/ci.yml: PR마다 PHPCS + PHPUnit 실행
- composer run lint 스크립트
보안 체크리스트:
- 모든 폼에 nonce + capability
- API Key 암호화 저장, 평문 로깅 금지
- URL HTTPS 강제 (http:// 거부)
- sanitize_text_field / esc_html / esc_attr / esc_url 일관 적용
Week 1 종료 기준:
- 깨끗한 WP 6.5에 설치 → 활성화 → PHP fatal 없음
- Settings 저장 → wp_options에서 암호화된 키 확인
- "Test Connection" → "Connected to site_id: xxx" 표시
- Site Registration 호출 성공, site_id 저장 확인
- Logs 페이지에 이벤트 로그 렌더
- PHPCS 0 error, GitHub Actions 녹색
- PHPUnit 기본 테스트 1개 이상 통과
════════════════════════════════════════════════════════
Himanshu — WXR 생성 + Villion 전송 파이프라인
════════════════════════════════════════════════════════
업무 정의:
고객 WP DB에서 콘텐츠를 WXR(WordPress eXtended RSS) 포맷으로 추출 →
청크 단위로 Villion 백엔드에 업로드 → 비동기 job 상태 추적 → 완료 후
301 Redirect 맵 생성. 플러그인 설정/연결 부분은 건드리지 않음
(Sai 담당).
파일 영역:
admin/views/migrate.php
includes/class-villion-exporter.php
includes/class-villion-uploader.php
includes/class-villion-job-poller.php
includes/class-villion-redirect-map.php
assets/js/migrate.js
assets/css/migrate.css
가정:
- Villion API Key와 site_id는 wp_options에 이미 저장되어 있음
(get_option('villion_api_key_encrypted'), get_option('villion_site_id'))
- 복호화 함수는 Sai가 구현 (includes/class-villion-auth.php)
본인은 이 함수를 호출만 함
- 본인의 HTTP 호출은 wp_remote_post를 직접 사용 (class-villion-api.php
같은 공용 래퍼 의존 X)
산출물:
1) Migrate 페이지 UI (admin/views/migrate.php + assets/js/migrate.js)
- 사이트 통계 카드:
포스트 N개, 페이지 M개, 이미지 K개, 예상 사이즈 (MB)
wp_count_posts, wp_count_attachments로 집계
- 이전 옵션:
[ ] 포스트 / [ ] 페이지 / [ ] Draft 포함
카테고리 multi-select
날짜 범위 (시작 / 끝)
Dry-run 체크박스 (업로드 없이 프리뷰만)
- Start / Pause / Cancel 컨트롤
- 진행 바 + 실시간 로그 tail (최근 5개)
- 완료 화면:
성공 N / 실패 M
실패 테이블 (wp_post_id + 사유)
"Villion에서 보기" 링크 목록
301 Redirect CSV 다운로드 버튼
2) WXR 생성 (includes/class-villion-exporter.php)
- WordPress core의 export_wp() 함수를 프로그래매틱 호출
(/wp-admin/includes/export.php 로드 → ob_start로 출력 캡처)
- 파라미터: content, category, start_date, end_date, status
- 결과를 uploads/villion-export-{timestamp}.xml에 임시 저장
- .htaccess (Deny from all)로 직접 URL 접근 차단
- 업로드 완료 후 임시 파일 자동 정리
3) 청크 분할 업로드 (includes/class-villion-uploader.php)
- 분기:
포스트 ≤ 500: 전체 WXR 단일 업로드
포스트 > 500: 포스트 단위 파싱 후 50개씩 청크 분할
- 각 청크 전송:
POST /api/v1/blog/import/wordpress/execute
wp_remote_post 직접 사용
Headers: X-Villion-Site-Key (복호화된 API Key)
Body: { chunk_index, total_chunks, cursor, wxr_chunk, options }
Response: { job_id, accepted, next_cursor }
- 재시도: 5xx 응답 시 3회 지수 백오프 (1s/2s/4s)
- timeout: 120s
4) Job 상태 폴링 (includes/class-villion-job-poller.php)
- GET /api/v1/blog/import/wordpress/jobs/{id}
- AJAX 엔드포인트 wp_ajax_villion_poll_job
- 프론트에서 5초 간격 polling
- Response 구조:
{ status: queued|running|completed|failed,
progress: {current, total},
errors: [{wp_post_id, reason}],
completed_articles: [{wp_post_id, villion_slug, villion_url}] }
- progress.current / progress.total로 진행 바 갱신
- errors 실시간 테이블 렌더
5) 중단 / 재개 (uploader + job-poller에 상태 로직 포함)
- Pause: 현재 청크 완료 대기 → 상태 paused →
WP transient (villion_migration_cursor, TTL 24h)에
마지막 커서 저장
- Resume: transient 복원 → next_cursor부터 재전송
- 네트워크 실패 3회 이후에도 복구 안 되면 paused 전환 + UI 배너
6) 이미지 처리 전략
- 플러그인에서 이미지 파일 다운로드 안 함
- WXR의 <wp:attachment_url> 태그에 포함된 원본 URL을 그대로 전달
- Villion 백엔드가 비동기로 다운로드 → Supabase Storage 업로드
- 이유: WP 서버 메모리·실행시간 제약 회피
7) 301 Redirect 맵 (includes/class-villion-redirect-map.php)
- job 완료 후 completed_articles 배열 수집
- CSV 렌더:
old_slug, villion_url, 301
- 다운로드 버튼 → Content-Disposition: attachment
- (Week 2+에 Redirection 플러그인 REST API 자동 등록 옵션 고려)
보안 체크리스트:
- 모든 AJAX 엔드포인트 wp_nonce + current_user_can('manage_options')
- WXR 임시 파일은 uploads 내 + .htaccess 차단
- 입력 sanitize_text_field / 출력 esc_html·esc_attr·esc_url 일관 적용
- wp_remote_post는 sslverify=true 강제
Week 1 종료 기준:
- Migrate 페이지 렌더링, 사이트 통계 카드 정확
- 테스트 사이트 10포스트 → WXR 생성 성공 + XML 유효성 검증 통과
- 단일 청크 업로드 → job_id 수신 → 폴링으로 completed까지 추적
- 완료 화면에 결과 리스트 + 301 CSV 다운로드 동작
- Pause / Resume 시나리오 수동 테스트 통과
- PHPCS 0 error
════════════════════════════════════════════════════════
스코프 밖 (두 사람 공통 — Week 1에 손대지 않음)
════════════════════════════════════════════════════════
× Villion Next.js 프론트엔드
× 백엔드 Python (FastAPI, Celery)
× AI / LLM / JSON-LD 생성 로직
× 인증 / RLS
× DevOps / 배포
× 플러그인 augment 기능 (Gutenberg 블록, wp_head JSON-LD 주입,
실시간 Citability 스코어, Action apply) — Phase 2 보류.
Week 1은 export-only.
2. 최승진
내가 전달해야할 것: 금주중으로 Villion 아키텍쳐 문서 전달. Villion에 대한 배경 지식 강화. Workspace 및 Slack에 추가 필요? OR 카톡 + Github 사용
업무: OCR 모델 학습 데이터 설계 (통이미지 → 구조화 데이터 변환)
• 이커머스 상품 통이미지 수집
• 학습용 구조화 데이터셋 구축 (본문 추출 + 메타데이터 라벨링)
• 좋은 강화학습 기법 리스트 찾아오라고 시키기
3. 박기범
업무: 이몰로지 프롬프트 전략
• 국내 ADHD 의료기기 / 수면, 집중 도와주는 웰니스 기기 시장조사
• 핵심 키워드 및 경쟁이 덜 빡센 키워드 탐색
• 경쟁사 콘텐츠 분석 혹은 경쟁사가 인용된 기사 매체 분석
4. 송찬우
업무: 이몰로지(1)/피아크(2) GEO 최적화 담당, 개발 인력 관리
• 이몰로지 작업 계획 24일 금요일 전까지 전달하기
o Villion 측이 당장 작업 가능한 파트 시작하기
o 27일날 이몰로지 GEO 작업 계획 확립, Google Workspace 설정하기
• 피아크 GEO 작업 계획 잠깐 보류 (계약서 받기 전까지)
• Inblog와 같은 Villion CMS 기능 개발
• 브랜드에게 적합한 키워드 찾아주는 알고리즘/로직 개발 → 기범과 함께 논의
o 경쟁 치열한 엔티티 / 아직 먹을 만한 키워드 파악 → 프롬프트 후보군 자동 생성
• OCR Model 트랙하기
댓글 (0)
불러오는 중…
새 글을 이메일로 받아보기
구독하시면 새 포스트가 발행될 때 이메일로 바로 받아보실 수 있어요. 언제든지 1-click 으로 해지할 수 있습니다.