RFQ 바이어 검색 — 전체 구조 · 기능 · API

운영 콘솔의 AI B2B 바이어 발굴 메뉴 · 자연어 프롬프트로 130만 기업 DB를 검색해 리드·캠페인으로 전환

operations?tab=rfq-companies-search

Q. 프롬프트 입력 후 바로 캠페인 발송까지 되나요?

아니오 발송은 자동으로 되지 않습니다. "Send to RINDA"는 ① 선택 기업을 리드로 저장 → ② 고객 그룹 묶기 → ③ status: "draft" 시퀀스 생성까지만 하고 시퀀스 편집 화면으로 이동합니다. 실제 발송은 사용자가 편집 화면에서 명시적으로 활성화해야 시작됩니다. (의도된 안전장치 — 검토 없는 대량 발송 방지)

1개요

수출기업 매니저가 자연어 한 문장으로 해외 B2B 바이어를 찾아 검토 후, 선택 기업을 바이어 리스트(리드)로 저장하거나 draft 캠페인으로 보내는 read-first 발굴 도구. 검색 대상은 외부 RFQ Companies API(읽기 전용, 약 130만 건), rinda DB에는 저장 시점에만 기록.

항목
접근 경로operations?tab=rfq-companies-search (영업 메일함 ↔ 바이어 네트워크 사이)
메인 컴포넌트admin/src/pages/rfq-companies/RfqCompaniesSearchPage.tsx
BE 프록시/api/v1/admin/rfq-companies (전 라우트 workspaceAuth)
외부 소스RFQ Companies API — 1,295,681건 (JP 91% · GB 7% · KR 등)
스택React 19 · Jotai · TanStack Query · Elysia · Drizzle · LLM(query-extraction)

2전체 흐름 (입력 → 발송까지)

자연어 프롬프트 입력 │ ▼ POST /plan-search LLM(query-extraction) facets 컨텍스트 주입 → 검색조건(plan) 생성 + 검증·클램프 │ (LLM 실패 시 프롬프트를 query 로 폴백) ▼ 외부 RFQ API: semantic + rerank 결과 테이블 + 편집 가능한 조건 칩(country/vertical/recordType/businessType/keywords/limit/rerank) │ ├─▶ 조건 수정 → "이 조건으로 재검색" POST /companies/search (반복) │ ▼ 행 선택 → 액션 ┌─ "Save to buyer list" → POST /save-to-leads → 리드 저장 (끝) └─ "Send to RINDA" → POST /to-campaign 리드 저장 → 고객 그룹 → draft 시퀀스 생성 → /sequences/edit 이동 ■ 여기서 멈춤 — 발송은 편집 화면에서 사용자가 직접 활성화

3화면 구조 #9062 단일 흐름

제1원리 재설계: 중복이던 "고급 검색" 패널 제거(편집가능 plan 칩이 동일 역할) → 단일 흐름.

RfqCompaniesSearchPage ├ Header ─ 제목 + [Save to buyer list (N)] [Send to RINDA (N)] ├ FacetsSummary ──────── 필터값 분포 요약 카드 ├ PromptSearchPanel ──── 자연어 Textarea + 예시칩3 + [Search] ← 유일 진입점 ├ SearchProgressPanel ── 2단계 진행 (planning → searching) ├ PlanConditionsPanel ── AI 생성 조건(편집 가능) = 유일 조건 제어 │ ├ EditableChips: country / vertical / recordType / businessType / keywords │ ├ NumberField: limit, candidates + Switch: rerank │ └ [Reset] [Search with these conditions] └ ResultsTable ───────── ☑전체선택 | Company | Country | Vertical | BizType | FitScore | Similarity + 결과수·rerank 배지·잘림 안내

4API 매핑 (rinda 프록시)

prefix /api/v1/admin/rfq-companies · 전 라우트 workspaceAuth · 외부 키는 서버 어댑터에서만

메서드 · 경로서비스권한
POST /plan-searchplanSearch() — LLM 조건생성 + 검색read
POST /companies/searchsearch() — 편집조건 재검색read
GET /facetsfacets() — 필터 분포read
POST /save-to-leadssaveToLeads() — bulkCreateLeadsbulk:create
POST /to-campaigntoCampaign() — 리드+그룹+draft 시퀀스bulk:create
/companies(list·cursor) · /companies/:id 는 프록시 존재하나 현재 FE 미사용

라우트 routes/rfq-companies.routes.ts · 서비스 services/rfq-companies/rfq-companies.service.ts · 외부 호출 어댑터 + 필터 SSOT domain/rfq-companies/rfq-filter-keys.ts

5외부 RFQ Companies API 계약 라이브 실측

Base …/api/v1 · 헤더 x-api-key · 총 1,295,681건

facet 키

country(71) · industry(100) · category(51) · vertical(4) · record_type(2: buyer/supplier) · business_type(9) · company_size(7) · b2b_or_b2c(5) · quality(3) · intent(5)

필터 arity가 키마다 다름 — 대부분 배열, record_type스칼라(buyer|supplier). rinda는 어댑터의 toWireFilters가 canonical(camelCase 배열) → wire(snake_case; record_type 스칼라)로 단일 변환(#9051).

검색 전용 필드 · count

6이번 세션 개선 (머지 완료)

PR내용
#9051필터 wire 계약 수정 — LLM 스칼라/FE camelCase ↔ API 배열 불일치로 필터 검색 전멸하던 것 어댑터 단일 변환점으로 복구 + facet 인젝션 sanitize + 해석문 언어 전달 + 워크스페이스 전환 리셋
#9055메뉴 이동 — admin 콘솔 → 운영 콘솔(영업 메일함↔바이어 네트워크 사이)
#9060감사 이슈 수정 — toCampaign 보상삭제(orphan 방지) · 입력 배열 상한 · facets 미수신 시 필터 드롭 · a11y
#9062제1원리 단일 흐름 — 중복 고급검색·dead code(atoms/hooks) 삭제 + 결과 카피 정직화 + 잘림 안내

남은 한계 (외부/구조적)