웹케시 금융 AI Agent 전문 기업

Webcash — The Financial AI Agent Company

AI CMS
자금관리 에이전트

기업의 자금 조회·분석·실행을
자연어 질의로 자동화

Branch Q IHB Q AI경리나라 AI금고 rERP Q
Agent Banking
에이전트 뱅킹

메뉴 클릭 없이 자연어 질의 한 번으로
조회·이체·분석까지 처리

개인뱅킹 기업뱅킹
Information System Agent
정보계 에이전트

현업이 IT 없이 직접 자연어로
경영 데이터를 질의·분석

자연어 → SQL 즉시 분석
ERP / Finance Connector
ERP/금융 연결

금융기관·ERP 시스템을 AI로 연결해
데이터 흐름을 자동화

금융기관 연결 ERP 연계
QV-C
고객관리의 시작

고객·영업 관계를 체계적으로
관리하는 CRM Agent 솔루션

OPERIA
지능형 RDB 커넥트

이기종 데이터베이스를 AI로 연결해
데이터 흐름을 통합 자동화

쇼룸 동선
입구
01
회사 CI
웹케시는 어떤 회사인가
02
Webcash Value
고객에게 주는
가치는 무엇인가
03
Webcash Product
그 가치를 어떤
제품으로 구현하는가
04
Webcash News
웹케시의 새로운 소식과
도전의 과정이 있는가?
05
Webcash Studio
브랜드와 상품을
경험하는 공간이 있는가?

웹케시를 처음 만나고 → 웹케시의 가치를 이해하고 → 제품을 체험하고 → 새로운 소식과 도전의 과정을 확인한 뒤 → 스튜디오에서 경험하는 과정


페이지 구조

각 박스를 클릭하면 해당 페이지로 이동합니다

QV-C 고객관리의 시작
OPERIA 지능형 RDB 커넥트
AI CMS 자금관리 에이전트
Main 공통 고객현황
Branch Q IHB Q AI경리나라 AI금고 rERP Q
데모
Branch Q IHB Q AI경리나라 AI금고 rERP Q
동영상
Branch Q IHB Q AI경리나라 AI금고 rERP Q
Connector ERP/금융 연결
Main 공통
금융 연결
은행 (22) 증권 (24) 카드 (18) 보험 (40) 저축은행 (34) 세계기관 (419)
ERP 연계
연계현황 ERP업체
프로젝트 개요
기본 정보
목적웹케시 AI 에이전트 제품 쇼룸 (고객사 시연/영업용)
로컬 URLhttp://localhost:8788
로컬 실행npm run dev
언어한국어 / 영어 (KR/EN 버튼으로 전환)
기술 스택
호스팅Cloudflare Pages (Edge 배포)
데이터베이스Cloudflare D1 (SQLite)
백엔드Cloudflare Pages Functions (TypeScript)
프론트엔드Vanilla HTML / CSS / JS (빌드 없음)
파일 구조
showroom/ ├── public/ # 정적 파일 — 빌드 없이 그대로 배포됨 │ ├── index.html # 허브 페이지 (제품 목록 + 이 문서) │ ├── css/showroom.css # 전체 스타일 (제품별 포인트 컬러 포함) │ ├── js/showroom.js # 클라이언트 JS (API 호출, 렌더링, 상태) │ ├── cms/index.html # AI CMS 쇼룸 │ ├── banking/index.html # Agent Banking 쇼룸 │ ├── infosys/index.html # 정보계 에이전트 쇼룸 │ └── connector/index.html # ERP/금융 연결 쇼룸 │ ├── functions/api/ # Cloudflare Pages Functions → /api/* 라우팅 │ ├── count.ts # GET /api/count — 누적/올해/이달 고객 수 │ ├── breakdown.ts # GET /api/breakdown — 카테고리별 통계 │ ├── trend.ts # GET /api/trend — 최근 12개월 월별 추이 │ └── customers.ts # GET /api/customers — 고객 목록 (페이징) │ ├── schema.sql # DB 테이블 + 인덱스 생성 DDL ├── seed.sql # products / categories 마스터 데이터 ├── add-2026.mjs # 더미 고객 데이터 추가 스크립트 (Node.js) ├── wrangler.toml # Cloudflare 설정 (D1 binding 등) └── package.json # npm 스크립트 모음
제품 구성
제품 ID한국어명영어명포인트 컬러URL
cms자금관리 에이전트AI CMS#2563eb (블루)/cms/
banking에이전트 뱅킹Agent Banking#4f46e5 (인디고)/banking/
infosys정보계 에이전트Information System Agent#7c3aed (바이올렛)/infosys/
connectorERP/금융 연결ERP / Finance Connector#0f9981 (틸)/connector/
DB 스키마 (schema.sql)
-- products: 제품 마스터 CREATE TABLE products ( id TEXT PRIMARY KEY, -- 'cms' | 'banking' | 'infosys' | 'connector' name_kr TEXT NOT NULL, name_en TEXT NOT NULL, sort_order INTEGER NOT NULL DEFAULT 0 ); -- categories: 카테고리 마스터 (제품에 귀속) CREATE TABLE categories ( id TEXT PRIMARY KEY, product_id TEXT NOT NULL REFERENCES products(id), name_kr TEXT NOT NULL, name_en TEXT NOT NULL, sort_order INTEGER NOT NULL DEFAULT 0 ); -- customers: 도입 고객 (실제 데이터 or 더미) CREATE TABLE customers ( id TEXT PRIMARY KEY, -- UUID product_id TEXT NOT NULL REFERENCES products(id), category_id TEXT REFERENCES categories(id), name TEXT NOT NULL, joined_at TEXT NOT NULL, -- 'YYYY-MM-DD' 형식 created_at TEXT NOT NULL ); -- 인덱스 (API 쿼리 성능) CREATE INDEX idx_customers_product ON customers(product_id); CREATE INDEX idx_customers_category ON customers(category_id); CREATE INDEX idx_customers_joined ON customers(joined_at);
⚠️ is_new 컬럼 없음. customers 테이블에 is_new 컬럼은 존재하지 않습니다. API(customers.ts)에서 joined_at >= 당월 1일 조건으로 실시간 계산합니다.
카테고리 구성 (seed.sql 기준)
product_idcategory_id한국어명영어명
cmsbranchqBranch QBranch Q
cmsihbqIHB QIHB Q
cmsserpAI경리나라AI Kyungri
cmsaigumgoAI금고AI Vault
cmsrerprERP QrERP Q
bankingpersonal개인뱅킹Personal Banking
bankingbiz기업뱅킹Business Banking
infosysnl2sql자연어→SQLNL to SQL
infosysinstant즉시 분석Instant Analysis
connectorfinconn금융기관 연결Financial Connection
connectorerplinkERP 연계ERP Integration
로컬 SQLite 파일 위치
.wrangler/state/v3/d1/miniflare-D1DatabaseObject/ ├── cc9b6845...cdd.sqlite # Miniflare D1 인스턴스 A └── 6f7bfe81...d95.sqlite # Miniflare D1 인스턴스 B (동일 내용) # 두 파일 모두 항상 같은 데이터를 유지해야 함 # add-2026.mjs 등 스크립트는 두 파일 모두 업데이트함
주의: wrangler dev 서버가 실행 중이면 SQLite 파일에 직접 쓰기가 실패(WAL 잠금)할 수 있습니다. 데이터 추가 스크립트 실행 전 서버를 먼저 종료하세요.
모든 API는 ?product={product_id} 파라미터 필수. CORS 허용 (Access-Control-Allow-Origin: *). 인증 없음 (내부 전용).
GET /api/count
항목내용
설명제품의 누적 / 올해(YTD) / 이달(MTD) 고객 수 반환
파라미터product (필수) — 제품 ID
응답{ total: number, ytd: number, mtd: number }
YTD 기준당해 1월 1일 이후 joined_at
MTD 기준당월 1일 이후 joined_at
# 요청 예시 GET /api/count?product=cms # 응답 { "total": 89, "ytd": 14, "mtd": 7 }
GET /api/breakdown
항목내용
설명제품 내 카테고리별 고객 수 (sort_order 기준 정렬)
파라미터product (필수)
응답{ breakdown: [{ category_id, name_kr, name_en, cnt, cnt_ytd, cnt_mtd }] }
특이사항고객이 없는 카테고리도 포함 (LEFT JOIN). 프론트에서 breakdownCache에 저장해 고객현황 탭 stat 카드에 재활용
GET /api/trend
항목내용
설명최근 12개월 월별 신규 고객 수
파라미터product (필수)
응답{ months: [{ month: "YYYY-MM", cnt: number }] }
특이사항데이터 없는 월은 응답에 포함되지 않음. 프론트(showroom.js)에서 getLast12Months()로 빈 월을 0으로 채워 렌더링
GET /api/customers
항목내용
설명고객 목록 (페이징, 카테고리 필터)
파라미터product (필수), page (기본 1), category (선택 — 없으면 전체)
응답{ total: number, page: number, records: [{ name, joined_at, is_new }] }
페이지 크기10건 고정
is_new당월 1일 이후 joined_at이면 true (컬럼 없음, 쿼리 계산)
joined_at 형식DB는 YYYY-MM-DD, 응답은 YYYY-MM (앞 7자리만 반환)
# 요청 예시 — 2페이지, branchq 카테고리만 GET /api/customers?product=cms&page=2&category=branchq # 응답 { "total": 23, "page": 2, "records": [ { "name": "삼성전자", "joined_at": "2026-05", "is_new": true }, ... ] }
functions/api/count.ts
/// <reference types="@cloudflare/workers-types" /> interface Env { DB: D1Database; } export const onRequestGet: PagesFunction<Env> = async ({ request, env }) => { const url = new URL(request.url); const product = url.searchParams.get('product'); if (!product) return json(400, { error: 'product required' }); const now = new Date().toISOString(); const yearStart = now.substring(0, 4) + '-01-01'; const monthStart = now.substring(0, 7) + '-01'; const result = await env.DB.prepare(` SELECT COUNT(*) AS total, COUNT(CASE WHEN joined_at >= ? THEN 1 END) AS ytd, COUNT(CASE WHEN joined_at >= ? THEN 1 END) AS mtd FROM customers WHERE product_id = ? `).bind(yearStart, monthStart, product).first(); return json(200, result); };
functions/api/customers.ts — 핵심 쿼리
// is_new는 DB 컬럼이 아닌 쿼리 계산값 const monthStart = new Date().toISOString().substring(0, 7) + '-01'; const rows = await env.DB.prepare(` SELECT name, joined_at, CASE WHEN joined_at >= ? THEN 1 ELSE 0 END AS is_new FROM customers WHERE product_id = ? [AND category_id = ?] -- category 파라미터 있을 때만 ORDER BY joined_at DESC LIMIT 10 OFFSET ? `).bind(monthStart, product, ...optionalCategory, offset).all(); // joined_at 응답 시 앞 7자리만 (YYYY-MM) records: rows.results.map(r => ({ ...r, joined_at: r.joined_at.substring(0, 7), is_new: r.is_new === 1, }))
public/js/showroom.js — 프론트 핵심 구조
/* 전역 상태 */ let currentLang = 'kr'; // 'kr' | 'en' let currentSection = 'main'; // 'main' | 'customers' | 'demo' | 'video' let currentPage = 1; let currentCategory = ''; // 빈 문자열 = 전체 let breakdownCache = []; // /api/breakdown 결과 캐시 → 고객현황 stat 카드 재활용 const PRODUCT = document.body.dataset.product ?? ''; // HTML body의 data-product 속성 /* 다국어: [data-kr] / [data-en] 속성으로 텍스트 전환 */ function applyLang() { document.querySelectorAll('[data-kr]').forEach(el => { el.textContent = currentLang === 'en' ? (el.dataset.en || el.dataset.kr) : el.dataset.kr; }); } /* 고객현황 탭 stat 카드 — 별도 API 호출 없이 breakdownCache 재사용 */ function updateCustStats(categoryId) { if (!breakdownCache.length) return; let total, ytd, mtd; if (!categoryId) { // 전체 total = breakdownCache.reduce((s, c) => s + c.cnt, 0); ytd = breakdownCache.reduce((s, c) => s + c.cnt_ytd, 0); mtd = breakdownCache.reduce((s, c) => s + c.cnt_mtd, 0); } else { // 특정 카테고리 const cat = breakdownCache.find(c => c.category_id === categoryId); if (!cat) return; total = cat.cnt; ytd = cat.cnt_ytd; mtd = cat.cnt_mtd; } animateCounter('#cust-total', total); animateCounter('#cust-ytd', ytd); animateCounter('#cust-mtd', mtd); }
CSS — 제품별 포인트 컬러 구조 (showroom.css)
/* :root — 기본값 (허브 페이지) */ :root { --blue: #334155; /* 기본 슬레이트 */ --blue-rgb: 51,65,85; } /* body[data-product] — 제품 페이지 진입 시 덮어씀 */ body[data-product="cms"] { --blue: #2563eb; --blue-rgb: 37,99,235; } body[data-product="banking"] { --blue: #4f46e5; --blue-rgb: 79,70,229; } body[data-product="infosys"] { --blue: #7c3aed; --blue-rgb: 124,58,237; } body[data-product="connector"] { --blue: #0f9981; --blue-rgb: 15,153,129; } /* 이후 모든 컴포넌트는 var(--blue) / rgba(var(--blue-rgb), 0.x) 사용 → HTML의 data-product만 바꾸면 전체 테마 자동 전환 */
로컬 개발 환경 설정
# 1. 의존성 설치 npm install # 2. DB 스키마 초기화 (최초 1회) npm run db:apply # → wrangler d1 execute showroom-db --file=schema.sql # 3. 마스터 데이터 시드 (products / categories) npm run db:seed # → wrangler d1 execute showroom-db --file=seed.sql # 4. 더미 고객 데이터 추가 (선택) node add-2026.mjs # 2026년 데이터 33건 — YTD/MTD 표시용 # 5. 개발 서버 시작 npm run dev # → http://localhost:8788
주의: 스크립트(add-2026.mjs 등)로 SQLite에 직접 쓸 때는 반드시 npm run dev를 먼저 종료하세요. 서버 실행 중에는 WAL 잠금으로 쓰기가 실패합니다.
Cloudflare 프로덕션 배포
# 1. wrangler.toml에 실제 D1 database_id 입력 (최초 1회) # wrangler d1 create showroom-db 실행 후 출력된 ID 사용 npm run db:create # 2. 원격 DB에 스키마 + 시드 적용 npm run db:apply:remote npm run db:seed:remote # 3. Pages 배포 (public/ 폴더를 통째로 배포) npm run deploy # → wrangler pages deploy public # Functions(functions/api/*.ts)는 배포 시 자동 포함됨 # 별도 빌드 스텝 없음
wrangler.toml 확인: database_id = "PLACEHOLDER"로 되어 있으면 반드시 실제 D1 ID로 교체해야 프로덕션에서 데이터가 동작합니다.
고객 데이터 추가 방법
방법설명사용 시기
스크립트 직접 작성 add-2026.mjs 참고해서 Node.js 스크립트 작성 후 실행. node:sqlite 모듈(Node.js v22+) 사용 대량 더미 데이터, 초기 구축
seed.sql 추가 seed.sql에 INSERT 구문 추가 후 npm run db:seed 재실행 마스터 데이터(products/categories) 변경
wrangler d1 execute wrangler d1 execute showroom-db --command "INSERT INTO customers ..." 단건 수동 추가, 운영 중 긴급 수정
원격 DB 직접 위 명령에 --remote 플래그 추가 프로덕션 데이터 수정
새 제품 추가 시 체크리스트
# 1. seed.sql — products / categories INSERT 추가 INSERT INTO products VALUES ('newprod', '제품명', 'Product Name', ...); INSERT INTO categories VALUES ('cat1', 'newprod', '카테고리명', ...); # 2. public/newprod/index.html — 기존 제품 HTML 복사 후 수정 # - body data-product="newprod" # - .category-tabs 버튼의 data-category 맞게 수정 # - .concept-diagram 내용 수정 # 3. public/css/showroom.css — 포인트 컬러 추가 body[data-product="newprod"] { --blue: #색상코드; --blue-rgb: R,G,B; } # 4. public/index.html — 허브 카드 추가 # - .card[href="/newprod/"] 에 --card-accent 자동 적용됨 # 5. DB 적용 npm run db:seed # 로컬 npm run db:seed:remote # 프로덕션