# 📋 T-AUTO-INJECT-UNIFIED-v1 — JSON-LD 자동 송출 통합 트랙 (골격, G0 대기)

> # 📋 T-AUTO-INJECT-UNIFIED-v1 — JSON-LD 자동 송출 통합 트랙 > 작성: 2026-05-08 KST | 상태: 🛑 **G0 대기 (발동 ❌)** > 양 방 공동 트랙 (GEOCARE + PREMIUM_GEO) > 짝 표준: STD-JSONLD-UNIFI

## 핵심 요약


# 📋 T-AUTO-INJECT-UNIFIED-v1 — JSON-LD 자동 송출 통합 트랙

> 작성: 2026-05-08 KST | 상태: 🛑 **G0 대기 (발동 ❌)**
> 양 방 공동 트랙 (GEOCARE + PREMIUM_GEO)
> 짝 표준: STD-JSONLD-UNIFIED v0.1 (본 문서 §6에 인라인) / 호출 표준: schema.geocare.ai 호출 v1.0 (별도 KHub 등재)
> 정본 근거: BMP 정책 v1.0 (`866eb3de`) + Phase D DevLog (`0c006e31`) + 본 세션 분석

---

## 0. 한 문장 정의

**3계열(sitegeo/brandgeo/ocr) JSON-LD를 단일 SSOT(`bmp_jsonld_delivery`)로 통합 + 인증·자동화·관측을 양 방 공동 트랙으로 6주+2주 안정화 완성.**

---

## 1. ⚠️ G0 발동 조건 (5건 모두 충족 시 진입)

| # | 조건 | 현 상태 | 책임 |
|---|---|---|---|
| 1 | **T-RENEW-GEOCARE-BMP v1.1 보강권고 회신** | 🛑 대기 | 구자훈 대표 (Asana `1214608078467144` 코멘트 회신) |
| 2 | **양 PO 미팅** (찰스 + 구자훈) | 미정 | 1번 회신 후 일정 합의 |
| 3 | **두 방 책임 분담 합의** (GEOcare 영역 vs BMP 영역 라인) | 미정 | 미팅 결과 |
| 4 | **Phase D DevLog v3.0 갱신** (PREMIUM_GEO 단독 작업) | 미정 | 3번 후 PREMIUM_GEO 측 진행 |
| 5 | **STD-JSONLD-UNIFIED 정본 합의 (v1.0)** | v0.1 본 문서 § | 1~4 후 양 방 합의 |

→ **5건 중 1건이라도 미충족 시 본 트랙 발동 ❌**.
→ G0 미충족 상태에서 부분 작업(예: gp_geoex_inject_keys 단독 DDL) **금지** — 6주 후 합의 결과로 폐기 가능성 ↑.

---

## 2. 배경 — 본 트랙 신설 사유

### 2.1 발견 (5/8 본 세션)
- 3계열 JSON-LD 생성/저장 영역이 **완전 분리** 사일로:
  - sitegeo (`gp_geoex_jsonld_log`): 701건, Schema Builder UI, 사용자 직접 입력
  - brandgeo (`bmp_jsonld_delivery`): 16건, Phase D 어드민 수동 트리거, EEAT와 무관
  - ocr (`gp_geoex_ocr_results`): 483건, schema 변환 미완 (raw text + jsonb만)
- `bmp_jsonld_delivery`가 자동 송출 SSOT (`geobh-jsonld` EF v2 우선 조회)
- 단, 자동 스케줄 미작동 (last_batch_at 모두 NULL)
- OCR → schema 변환 파이프라인 부재
- luvhunter PoC 시 적용할 데이터 0건

### 2.2 본 트랙의 필연성
T-RENEW-GEOCARE-BMP v1.1 보강권고가 GEOcare ↔ BMP 기능 재배치를 다루는데, **JSON-LD 영역이 정확히 그 사이의 모호 지대**. 본 트랙은 T-RENEW의 데이터 흐름 측면 정합 작업.

### 2.3 5/11 luvhunter PoC와의 분리
- 5/11 시연 자산 = Brand Hub 3중 안전망 (이미 라이브, 변경 ❌)
- 5/11 시연 메시지 추가: "자동 송출 정식 트랙 6주+2주 진행 — 계약 사인 시 luvhunter 우선 적용 사이트 1호 등록"
- **본 트랙 발동은 5/11 후 + G0 충족 시점**

---

## 3. 6 Phase 구조 (총 6주 + 안정화 2주)

### Phase 1 — 인증 인프라 + Phase D 인증 통합 (1.5주)

**GEOcare 영역**:
- `gp_geoex_inject_keys` 신규 테이블 (인증 SSOT)
- `verify_geoex_inject_key` RPC (3중 검증: 키·만료·Origin)
- 메모리 캐시 정책 (60초 TTL, EF 측)

**BMP 영역 (PREMIUM_GEO 작업)**:
- `geobh-jsonld` EF v3 패치 — 인증 헤더 검증 + 3단계 fallback 유지
- jsonld-serve `/api/jsonld-serve` 인증 통합
- 어드민 UI 토큰 발급/관리 화면 (`bmp.ai/admin` PDP 탭 확장)

**검증**: 토큰 검증 부하 + Origin 화이트리스트 + 만료/재발급/폐기 시나리오

### Phase 2 — Phase D 자동화 부활 (1주)

**PREMIUM_GEO 작업**:
- PDP-SCHED (`s5JaX2zYy2RU2fkt`) 자동 스케줄 미작동 원인 추적 + 수정
- Webhook/Schedule 트리거 패턴 재정립 (`bmp_jsonld_sites.is_pdp_enabled`)
- 24h/12h 스케줄 실 작동 검증
- 갱신 정책 표준 (사용자 변경 트리거 vs 정기)
- last_batch_count·errors Telegram 알림

### Phase 3 — OCR → schema 변환 파이프라인 (2주) ⭐ 핵심 차별화

**GEOcare 영역**:
- HITL 검수 후 `gp_geoex_ocr_review` 통과 row만 변환 대상
- 신규 WF: `[Phase D-OCR] OCR-to-Schema Pipeline` 신설
  - `lifestyle/model_wearing/product_only` → Product image[] 보강
  - `detail_text/spec_table` → Product description + additionalProperty
  - `care_guide/care_instruction` → HowTo 신규
  - `infographic` → FAQPage 신규
  - `size_chart` → PropertyValue
- LLM 변환 비용 추적 (OCR raw → Gemini/GPT)

**BMP 영역**:
- `bmp_jsonld_delivery.source = 'ocr'` row 추가 (정책: 별도 row vs array merge — Phase 3 진입 시 결정)
- 우선순위 merge 정책 (extracted > generated > ocr 또는 통합)

### Phase 4 — sitegeo 통합 + 데이터 정합 (1주)

**GEOcare 영역**:
- `gp_geoex_jsonld_log` → `bmp_jsonld_delivery` 마이그 정책 결정
  - 옵션 A: 모두 마이그 후 deprecated (단일 SSOT)
  - 옵션 B: 사용자 직접 입력 이력은 영구 보존, 운영 송출만 bmp 활용 (권장)
- `gp_geoex_jsonld_log.site_domain` 정규화 (`https://...` 제거)
- WebSite/Organization/WebPage/BreadcrumbList → bmp 적재 시 `source='sitegeo'`

**검증**: 이바나 사례 (sitegeo 8 + brandgeo 12 + ocr 216 → 통합 결과 측정)

### Phase 5 — 관측·운영·알림 (1주)

**BMP 영역 (어드민 UI 확장)**:
- 호출량 dashboard 신규 탭
- Rate Limit 실 적용 (현재 컬럼만 존재, 작동 ❌)
- 운영 알림 표준 (delivery 갱신 실패 / 인증 실패 폭증 등)
- A/B 테스트 인프라 활용 (`bmp_jsonld_ab_tests`)
- 비용 추적 (Vision GPT-4o · GPT 생성 fallback · OCR 변환)

### Phase 6 — 공식 표준화 + 외부 통보 (0.5주)

**양 방 공동**:
- STD-JSONLD-UNIFIED v1.0 정본 KHub 등재 (양 방 동시)
- 11줄 PHP 코드 v1.0 정식 발표 (라이브러리화 검토)
- 운영 매뉴얼 작성 (어드민/파트너용)
- 학습 #17~#22 KHub 일괄 등재
- 외부 통보 (옥경화 상무 → 러브헌터 등 적용 사이트)

### 안정화 (2주)
- 내부 dogfooding (bizspring.co.kr · growthplatform.ai 직접 적용)
- 첫 외부 사이트 1건 적용 (luvhunter 또는 medicube)
- 부하·장애·롤백 드릴
- 🔍 VERIFIED → 본 트랙 종결

---

## 4. 영역 격벽 매트릭스

| 작업 | 영역 | 책임 |
|---|---|---|
| `gp_geoex_inject_keys` 테이블/RPC | GEOcare 단독 | 본 방 |
| OCR → schema 변환 파이프라인 | GEOcare 단독 | 본 방 |
| `gp_geoex_jsonld_log` 정규화/마이그 | GEOcare 단독 | 본 방 |
| `bmp_jsonld_delivery` source/install_method 표준 | BMP 단독 | PREMIUM_GEO 방 |
| `geobh-jsonld` EF v3 패치 | BMP 단독 | PREMIUM_GEO 방 |
| jsonld-serve EF 패치 | BMP 단독 | PREMIUM_GEO 방 |
| PDP-SCHED 자동 스케줄 부활 | BMP 단독 | PREMIUM_GEO 방 |
| 어드민 UI (PDP 탭 확장) | BMP 단독 | PREMIUM_GEO 방 |
| OCR 변환 결과 → bmp 적재 정책 | **양 방 합의** | 공동 |
| Phase 6 정본 표준 등재 | **양 방 공동** | 공동 |

---

## 5. 본 세션(2026-05-08) 산출물 — 본 트랙 자료로 보존

| 자산 | 위치 | 용도 |
|---|---|---|
| schema.geocare.ai DNS 등록 ✅ | 후이즈 + Supabase ENABLED | 본 트랙 호출 도메인 (즉시 활용) |
| schema.geocare.ai 호출 표준 v1.0 | 별도 KHub 문서 | 본 트랙 Phase 1 직접 활용 |
| 3계열 schema 분석 (701/16/483건) | 본 문서 §2.1 | Phase 4 통합 근거 |
| 4/1 이바나 12건 timestamp 시퀀스 | 본 문서 §2.1 | Phase 2 자동 스케줄 부활 근거 |
| `gp_geoex_inject_keys` v0.1 스키마 | 본 문서 §6.1 | Phase 1 GEOcare 작업 진입점 |
| `verify_geoex_inject_key` RPC v0.1 | 본 문서 §6.2 | Phase 1 GEOcare 작업 진입점 |
| 11줄 PHP 코드 v1.3 (luvhunter) | 본 문서 §6.3 | Phase 6 정식 발표 직전 검토 후보 |

⛔ DDL/INSERT 미실행 — G0 충족 후 Phase 1 정식 진입 시점에 양 방 합의 후 적용.

---

## 6. 본 세션 G1 설계 자산 (Phase 1 진입 시 검토 후보)

### 6.1 `gp_geoex_inject_keys` v0.1 (Phase 1 검토)

```sql
CREATE TABLE gp_geoex_inject_keys (
  id                    uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  api_key               text UNIQUE NOT NULL,
  client_code           text UNIQUE NOT NULL,
  site_domain           text NOT NULL,
  display_name          text,
  permissions           text[] DEFAULT ARRAY['inject']::text[],
  allowed_origins       text[],
  rate_limit_per_hour   integer DEFAULT 10000,
  is_active             boolean DEFAULT true,
  expires_at            timestamptz,
  last_used_at          timestamptz,
  metadata              jsonb,
  created_at            timestamptz NOT NULL DEFAULT now(),
  updated_at            timestamptz NOT NULL DEFAULT now(),
  CONSTRAINT chk_api_key_prefix CHECK (api_key ~ '^[a-z]{2,5}_[a-zA-Z0-9]{24,64}$'),
  CONSTRAINT chk_client_code_format CHECK (client_code ~ '^[A-Z][A-Z0-9_]{2,30}$'),
  CONSTRAINT chk_site_domain_format CHECK (site_domain ~ '^[a-z0-9.-]+\.[a-z]{2,}$')
);

CREATE UNIQUE INDEX idx_inject_keys_api_key_active ON gp_geoex_inject_keys (api_key) WHERE is_active = true;
CREATE INDEX idx_inject_keys_origins ON gp_geoex_inject_keys USING GIN (allowed_origins);
CREATE INDEX idx_inject_keys_expires ON gp_geoex_inject_keys (expires_at) WHERE is_active = true AND expires_at IS NOT NULL;
CREATE INDEX idx_inject_keys_client_code ON gp_geoex_inject_keys (client_code);

ALTER TABLE gp_geoex_inject_keys ENABLE ROW LEVEL SECURITY;
CREATE POLICY no_direct_access ON gp_geoex_inject_keys FOR ALL USING (false) WITH CHECK (false);
```

→ 패턴 근거: `gp_mcp_api_keys` (GEOcare MCP 인증) + BIZDATA `de_unified_client.api_key` 합성.

### 6.2 `verify_geoex_inject_key` RPC v0.1 (Phase 1 검토)

```sql
CREATE OR REPLACE FUNCTION verify_geoex_inject_key(
  p_api_key text,
  p_origin text DEFAULT NULL,
  p_request_url text DEFAULT NULL
)
RETURNS TABLE(
  is_valid boolean,
  client_code text,
  site_domain text,
  permissions text[],
  metadata jsonb,
  failure_reason text
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_row gp_geoex_inject_keys%ROWTYPE;
BEGIN
  SELECT * INTO v_row FROM gp_geoex_inject_keys
  WHERE api_key = p_api_key AND is_active = true LIMIT 1;
  
  IF NOT FOUND THEN
    RETURN QUERY SELECT false, NULL::text, NULL::text, NULL::text[], NULL::jsonb, 'key_not_found_or_inactive'::text;
    RETURN;
  END IF;
  
  IF v_row.expires_at IS NOT NULL AND v_row.expires_at < now() THEN
    RETURN QUERY SELECT false, v_row.client_code, v_row.site_domain, NULL::text[], NULL::jsonb, 'key_expired'::text;
    RETURN;
  END IF;
  
  IF v_row.allowed_origins IS NOT NULL AND array_length(v_row.allowed_origins, 1) > 0 AND p_origin IS NOT NULL THEN
    IF NOT (p_origin = ANY(v_row.allowed_origins)) THEN
      RETURN QUERY SELECT false, v_row.client_code, v_row.site_domain, NULL::text[], NULL::jsonb, 'origin_not_allowed'::text;
      RETURN;
    END IF;
  END IF;
  
  UPDATE gp_geoex_inject_keys SET last_used_at = now() WHERE id = v_row.id;
  
  RETURN QUERY SELECT true, v_row.client_code, v_row.site_domain, v_row.permissions, v_row.metadata, NULL::text;
END;
$$;

GRANT EXECUTE ON FUNCTION verify_geoex_inject_key(text, text, text) TO anon, authenticated, service_role;
```

### 6.3 11줄 PHP 코드 v1.3 (Phase 6 정식 발표 직전 검토)

```php
<!-- GEOcare JSON-LD Auto-Inject (비즈스프링) -->
<?php
$_g_url = 'https://www.luvhunter.net' . $_SERVER['REQUEST_URI'];
$_g_cache = sys_get_temp_dir() . '/gc_' . md5($_g_url);
if (!file_exists($_g_cache) || time() - filemtime($_g_cache) > 3600) {
    $_g_ctx = stream_context_create(['http' => ['timeout' => 2, 'header' => 'X-GEOcare-Key: lvh_xxxxxxxxxxxxxxxxxxxxxxxx']]);
    $_g_res = @file_get_contents('https://schema.geocare.ai/functions/v1/geobh-jsonld?url=' . urlencode($_g_url), false, $_g_ctx);
    if ($_g_res) @file_put_contents($_g_cache, $_g_res);
}
if (file_exists($_g_cache)) echo '<script type="application/ld+json">' . file_get_contents($_g_cache) . '</script>';
?>
```

→ 적용 위치: `_inc_index_header.tpl` 188~189행 사이 (`</head>` 직전).

---

## 7. 후속 트랙 시드 (본 트랙에서 분기 가능성)

| 후속 트랙 | 시점 | 책임 |
|---|---|---|
| `T-PIPELINE-OCR-TO-SCHEMA-FULLAUTO` | Phase 3 종결 후 풀자동화 | GEOcare |
| `T-MIGRATION-SITEGEO-LEGACY` | Phase 4 후속 (gp_geoex_jsonld_log 거취 결정) | GEOcare |
| `T-OPS-AUTO-INJECT-MULTISITE` | 안정화 후 다수 사이트 적용 | 양 방 공동 |
| `T-MARKETING-AUTO-INJECT-LAUNCH` | 안정화 후 영업 메시지 | SALES + GEOCARE |

---

## 8. 학습 누적 (Phase 6 일괄 등재 후보)

| # | 가칭 |
|---|---|
| 17 | 외부 EF 활용 코드 제안 시 인증 모델 단정 금지 |
| 18 | 가칭 자산명 자연 노출 금지 |
| 19 | 인벤토리 미확인 상태로 신규 테이블 설계 금지 |
| 20 | 동일 명칭 테이블 발견 시 용도 검증 필수 |
| 21 | 신규 인프라 설계 시 인증·데이터·실행 3축 동시 확인 |
| 22 | 외부 변수(영업 일정) 압박 시 PO에게 명시적 환기 요청 |

→ 본 트랙 Phase 6 종결 시 KHub COMMON 일괄 등재.

---

## 9. 새 세션 진입 명령

### 트리거 발화
- **"T-AUTO-INJECT-UNIFIED 이어서"** → 본 문서 로드 + G0 5건 상태 점검
- **"T-RENEW v1.1 회신 왔어"** → G0 #1 충족 → #2 일정 합의 진입
- **"양 PO 미팅 결과"** → G0 #2~#3 진입
- **"Phase 1 진입"** → G0 충족 시점 + 양 방 합의 시 발동
- **"본 트랙 종결"** → 사양 폐기 또는 다른 트랙으로 흡수 시

### 본 트랙 발동 전 새 세션 작업 우선순위 (높→낮)
1. **자동 패치 사후 검토 6건** (5/7 17:00 SLA D-1)
2. **BUG-002 G3 재검증** (PREMIUM_GEO 처리 후, SLA 5/9 EOD)
3. **나이스페이 회신 메일** (P0-3, AP-25)
4. **T-EEAT-LLM-FAIL** 트랙 신설 (2,959건 score=0)
5. **5/11 미팅 준비** (KHub `d00aceea` + bmp.ai 5종 + 어드민 시연)
6. **T-RENEW v1.1 회신 모니터링** (구자훈 대표)
7. T-SALES-MPRD-UPSELL Phase 1 메시지 본문 컨펌

---

## 10. 변경 이력

| 일자 | 버전 | 변경 |
|------|------|------|
| 2026-05-08 | v1.0 (골격) | 초판 — G0 대기 상태로 등재. Phase 1~6 + 안정화 골격. 본 세션 산출물 보존. T-RENEW v1.1 회신 후 발동. |


## FAQ


---
출처: https://bizspring.ai/kb/ref/khub/geocare-t-auto-inject-unified-v1-json-ld-자동-송출-통합-트랙-골격-g0-대기 · 최종 갱신 2026-08-24T11:53:44.684733+00:00
