{
  "id": "1b7eb0ff-40cd-4642-84a9-f47f26c55884",
  "slug": "ref/khub/geocare-geocare-changelog-w08-2-2026-02-21-phase0-통합-리팩토링",
  "doc_type": "ref",
  "title": "📋 GEOcare Changelog W08-2 (2026-02-21) — Phase0 통합 리팩토링",
  "title_en": null,
  "one_liner": "# GEOcare Changelog W08-2 (2026-02-21) ## Phase0 통합 리팩토링 — Starter/Paid WF 병합 ### 배경 소스 코드 검증 결과 Phase0 온보딩에 심각한 구조적 버그 6건 발견. Starter/Paid 2개 WF를 1개로 통합하고 프론",
  "summary_bullets": [],
  "body_md": "# GEOcare Changelog W08-2 (2026-02-21)\n\n## Phase0 통합 리팩토링 — Starter/Paid WF 병합\n\n### 배경\n소스 코드 검증 결과 Phase0 온보딩에 심각한 구조적 버그 6건 발견. Starter/Paid 2개 WF를 1개로 통합하고 프론트엔드 3파일 수정.\n\n### 버그 수정 상세\n\n#### BUG-1: 이중 Job INSERT (🔴 Critical)\n- 원인: 프론트 createAnalysisJob() INSERT + n8n 📋 Create Analysis Job INSERT → 2개 row\n- 프론트는 자기 job_id 폴링(pending 영원), n8n은 자기 job 업데이트(completed)\n- 수정: n8n If(job_id) 분기 — 있으면 PATCH(프론트 job), 없으면 POST(Admin Hub)\n\n#### BUG-2: Webhook URL 하드코딩 (🔴 Critical)\n- 원인: analysisJobService.ts:199 `onboarding-free-start-v8` 하드코딩\n- 유료 고객도 Starter WF(crawl_limit=20, SoM 미실행)로 처리\n- 수정: 프론트 3파일 → `onboarding-start-analysis-v8` 통합\n\n#### BUG-3: Starter WF 비활성 (🔴 Critical)\n- 원인: UNCEDNu4Bft6g3Nx 비활성 상태 → 신규 분석 404\n- 수정: 통합 WF v8.1로 대체\n\n#### BUG-4: Status 이중 업데이트 (🟡 Medium)\n- 원인: 프론트 status='queued' UPDATE + n8n status='crawling' PATCH → 경쟁\n- 수정: 프론트 UPDATE 제거, n8n 단독 담당\n\n#### BUG-5: Code 노드 SB_KEY 하드코딩 (🟡 Medium)\n- 원인: 💾 Save Brand & Site Settings Code 노드에 SB_KEY 직접 작성\n- 수정: HTTP Request 노드 2개(UPSERT site/brand)로 전환\n\n#### BUG-6: 병렬 저장 Race Condition (🟡 Medium)\n- 원인: 병렬A(크롤링) / 병렬B(저장) → Completion Handler가 brand 조회 시 미저장 가능\n- 수정: UPSERT를 메인 경로 앞 순차 배치\n\n### n8n WF 변경\n\n**`[Phase0][Main] 유무료 온보딩 v8.1`** (tViiA9NQOeVXh0B8)\n- 이전: 6노드 (Webhook → Plan Settings → Create Job → Crawl → Respond + 병렬 Code)\n- 이후: 9노드 순차 플로우\n\n```\nWebhook → 💾 UPSERT site → 💾 UPSERT brand → ⚙️ Plan Settings\n  → ❓ Has Job ID?\n    ├─ [true]  → 📋 PATCH Existing Job\n    └─ [false] → 📋 POST New Job\n                    → 🚀 geo-crawl-start → ✅ Respond\n```\n\nDetermine Plan Settings 필드: plan_type(default:'starter'), crawl_limit(20/50/100), site_domain, user_id, job_id, brand_name, industry\n\n### 프론트엔드 커밋\n\n| 레포 | Commit | 파일 | 변경 |\n|------|--------|------|------|\n| geocare | 9d06ad5c | analysisJobService.ts | URL 통합, plan_type:'starter' 추가, status 업데이트 제거 |\n| geocare | 655baa64 | PremiumStatusGuard.tsx | WEBHOOK_URLS→단일URL, job_id+plan_type 전달 |\n| geocare-admin-hub | 18480092 | UserDetailPage.tsx | free URL 통합, plan_type 동적매핑(starter/tier) |\n\n### 🔴 프론트 테스트 대기\nLovable 빌드 후 3개 시나리오 테스트 필요:\n1. 무료 분석 (job 1개만 생성)\n2. PremiumStatusGuard 재시도 (통합 URL + job_id)\n3. Admin Hub 재트리거 (plan_type 분기)\n\n### KHub 문서 업데이트\n- 온보딩 레퍼런스 v2→v3: `58fa4631-18fc-4343-9314-2570956f9640`\n- DevLog Snapshot: `061e5edb-9f55-4a2d-b7dc-a89e6bef16d8`\n",
  "related_slugs": [],
  "faq": [],
  "jsonld": null,
  "keywords": [],
  "source_id": "251dfdf3-acc7-451c-9cb7-ad2f32cdf1a9",
  "video_url": null,
  "duration_sec": null,
  "thumbnail_url": null,
  "image_url": null,
  "caption": null,
  "solution_slug": null,
  "captured_at": null,
  "width": null,
  "height": null,
  "created_at": "2026-08-24T11:53:44.684733+00:00",
  "updated_at": "2026-08-24T11:53:44.684733+00:00",
  "visibility": "public",
  "source_stage": "1",
  "anonymized": true,
  "source_key": "legacy-khub",
  "origin": "ingest",
  "locked": false,
  "locked_by": null,
  "locked_at": null,
  "gate_state": {
    "g1": {
      "hits": [],
      "pass": true
    },
    "g2": {
      "pass": true,
      "total": 50,
      "issues": [
        "숫자·규격 같은 검증 가능한 구체가 부족합니다",
        "핵심 요약 불릿이 3개 미만입니다",
        "Q&A 쌍이 3개 미만입니다"
      ],
      "applies": true
    },
    "g3": {
      "pass": true,
      "required": false
    },
    "stage": "1",
    "decided_at": "2026-08-24T11:53:44.334Z"
  },
  "raw_id": "bfd85f7d-6212-4704-a7b9-c994dead5166",
  "search_text": "📋 GEOcare Changelog W08-2 (2026-02-21) — Phase0 통합 리팩토링  # GEOcare Changelog W08-2 (2026-02-21) ## Phase0 통합 리팩토링 — Starter/Paid WF 병합 ### 배경 소스 코드 검증 결과 Phase0 온보딩에 심각한 구조적 버그 6건 발견. Starter/Paid 2개 WF를 1개로 통합하고 프론  # GEOcare Changelog W08-2 (2026-02-21)\n\n## Phase0 통합 리팩토링 — Starter/Paid WF 병합\n\n### 배경\n소스 코드 검증 결과 Phase0 온보딩에 심각한 구조적 버그 6건 발견. Starter/Paid 2개 WF를 1개로 통합하고 프론트엔드 3파일 수정.\n\n### 버그 수정 상세\n\n#### BUG-1: 이중 Job INSERT (🔴 Critical)\n- 원인: 프론트 createAnalysisJob() INSERT + n8n 📋 Create Analysis Job INSERT → 2개 row\n- 프론트는 자기 job_id 폴링(pending 영원), n8n은 자기 job 업데이트(completed)\n- 수정: n8n If(job_id) 분기 — 있으면 PATCH(프론트 job), 없으면 POST(Admin Hub)\n\n#### BUG-2: Webhook URL 하드코딩 (🔴 Critical)\n- 원인: analysisJobService.ts:199 `onboarding-free-start-v8` 하드코딩\n- 유료 고객도 Starter WF(crawl_limit=20, SoM 미실행)로 처리\n- 수정: 프론트 3파일 → `onboarding-start-analysis-v8` 통합\n\n#### BUG-3: Starter WF 비활성 (🔴 Critical)\n- 원인: UNCEDNu4Bft6g3Nx 비활성 상태 → 신규 분석 404\n- 수정: 통합 WF v8.1로 대체\n\n#### BUG-4: Status 이중 업데이트 (🟡 Medium)\n- 원인: 프론트 status='queued' UPDATE + n8n status='crawling' PATCH → 경쟁\n- 수정: 프론트 UPDATE 제거, n8n 단독 담당\n\n#### BUG-5: Code 노드 SB_KEY 하드코딩 (🟡 Medium)\n- 원인: 💾 Save Brand & Site Settings Code 노드에 SB_KEY 직접 작성\n- 수정: HTTP Request 노드 2개(UPSERT site/brand)로 전환\n\n#### BUG-6: 병렬 저장 Race Condition (🟡 Medium)\n- 원인: 병렬A(크롤링) / 병렬B(저장) → Completion Handler가 brand 조회 시 미저장 가능\n- 수정: UPSERT를 메인 경로 앞 순차 배치\n\n### n8n WF 변경\n\n**`[Phase0][Main] 유무료 온보딩 v8.1`** (tViiA9NQOeVXh0B8)\n- 이전: 6노드 (Webhook → Plan Settings → Create Job → Crawl → Respond + 병렬 Code)\n- 이후: 9노드 순차 플로우\n\n```\nWebhook → 💾 UPSERT site → 💾 UPSERT brand → ⚙️ Plan Settings\n  → ❓ Has Job ID?\n    ├─ [true]  → 📋 PATCH Existing Job\n    └─ [false] → 📋 POST New Job\n                    → 🚀 geo-crawl-start → ✅ Respond\n```\n\nDetermine Plan Settings 필드: plan_type(default:'starter'), crawl_limit(20/50/100), site_domain, user_id, job_id, brand_name, industry\n\n### 프론트엔드 커밋\n\n| 레포 | Commit | 파일 | 변경 |\n|------|--------|------|------|\n| geocare | 9d06ad5c | analysisJobService.ts | URL 통합, plan_type:'starter' 추가, status 업데이트 제거 |\n| geocare | 655baa64 | PremiumStatusGuard.tsx | WEBHOOK_URLS→단일URL, job_id+plan_type 전달 |\n| geocare-admin-hub | 18480092 | UserDetailPage.tsx | free URL 통합, plan_type 동적매핑(starter/tier) |\n\n### 🔴 프론트 테스트 대기\nLovable 빌드 후 3개 시나리오 테스트 필요:\n1. 무료 분석 (job 1개만 생성)\n2. PremiumStatusGuard 재시도 (통합 URL + job_id)\n3. Admin Hub 재트리거 (plan_type 분기)\n\n### KHub 문서 업데이트\n- 온보딩 레퍼런스 v2→v3: `58fa4631-18fc-4343-9314-2570956f9640`\n- DevLog Snapshot: `061e5edb-9f55-4a2d-b7dc-a89e6bef16d8`\n",
  "embedding": null,
  "embedded_at": null,
  "embedding_hash": null,
  "backlinks": [],
  "html_url": "https://bizspring.ai/kb/ref/khub/geocare-geocare-changelog-w08-2-2026-02-21-phase0-통합-리팩토링",
  "markdown_url": "https://bizspring.ai/kb/ref/khub/geocare-geocare-changelog-w08-2-2026-02-21-phase0-통합-리팩토링.md"
}