- Frontend: Next.js 14 with TypeScript - Backend: FastAPI with SQLAlchemy - Agent: Carmodoo sync agent - Deployment: Docker Compose based staging/production setup - Scripts: Automated deployment with rollback support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
99 KiB
몽골 중고차 수출 플랫폼 개발 계획서
📋 프로젝트 개요
| 항목 | 내용 |
|---|---|
| 프로젝트명 | MongolCar - 몽골 중고차 수출 플랫폼 |
| 목적 | 한국 중고차를 몽골 고객에게 실시간 검색/판매하는 B2C 플랫폼 |
| 대상 고객 | 몽골, 러시아, 카자흐스탄 등 중앙아시아 고객 |
| 개발 기간 | 8~10주 |
| 개발 도구 | Claude Code |
🏗️ 시스템 아키텍처
┌─────────────────────────────────────────────────────────────────────────────┐
│ 전체 시스템 구성도 │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 몽골/러시아 사용자 (웹브라우저) │
│ - 차량 검색 (차종/연식/마일리지) │
│ - 상세보기 (포인트 차감) │
│ - 실시간 채팅 (AI 번역) │
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 우분투 웹서버 (Ryzen 7700, 32GB) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Next.js │ │ Node.js │ │ Socket.io │ │ Claude API │ │
│ │ Frontend │ │ API Server │ │ 실시간채팅 │ │ 번역+FAQ 챗봇 │ │
│ │ (다국어) │ │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────────────────┐ │
│ │ Nginx │ │ Redis │ │ 이미지 저장소 │ │
│ │ Reverse │ │ Cache │ │ /var/www/car-images/ │ │
│ │ Proxy │ │ Session │ │ 1000대 × 20장 = ~10GB │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────────────────┘ │
└─────────────────────────────────────┬───────────────────────────────────────┘
│
┌─────────────────┴─────────────────┐
│ 내부 네트워크 │
└─────────────────┬─────────────────┘
│
┌─────────────────────────────┴─────────────────────────────┐
│ │
▼ ▼
┌───────────────────────────────────┐ ┌───────────────────────────────────┐
│ 우분투 DB서버 (Ryzen 7700, 32GB) │ │ Windows PC (사무실) │
│ ┌─────────────────────────────┐ │ │ ┌─────────────────────────────┐ │
│ │ PostgreSQL 16 │ │ │ │ 카모두 프로그램 │ │
│ │ - vehicles (차량정보) │ │ │ │ (GGKucar.exe) │ │
│ │ - users (회원) │ │ │ └──────────────┬──────────────┘ │
│ │ - payments (결제) │ │ │ │ │
│ │ - chat_messages (채팅) │ │ │ ┌──────────────▼──────────────┐ │
│ │ - view_history (열람기록) │ │ │ │ Python 자동화 에이전트 │ │
│ └─────────────────────────────┘ │ │ │ - pywinauto (UI 제어) │ │
│ ┌─────────────────────────────┐ │ │ │ - API Client (서버 통신) │ │
│ │ 백업 스토리지 (10TB) │ │ │ │ - 이미지 추출/업로드 │ │
│ └─────────────────────────────┘ │ │ └─────────────────────────────┘ │
└───────────────────────────────────┘ └───────────────────────────────────┘
🖥️ 서버 인프라
서버 1: 웹서버
| 항목 | 사양 |
|---|---|
| CPU | AMD Ryzen 7 7700 |
| RAM | 32GB (64GB 중 할당) |
| 스토리지 | SSD (OS + 앱) + HDD 10TB 일부 |
| OS | Ubuntu 22.04 LTS |
설치 서비스:
- Nginx (리버스 프록시, SSL)
- Node.js 20 LTS
- Next.js 14
- Redis 7
- PM2
서버 2: DB서버
| 항목 | 사양 |
|---|---|
| CPU | AMD Ryzen 7 7700 |
| RAM | 32GB (64GB 중 할당) |
| 스토리지 | SSD (DB) + HDD 10TB (백업) |
| OS | Ubuntu 22.04 LTS |
설치 서비스:
- PostgreSQL 16
- 자동 백업 스크립트
💻 기술 스택
Frontend
| 기술 | 버전 | 용도 |
|---|---|---|
| Next.js | 14.x | React 프레임워크, SSR |
| TypeScript | 5.x | 타입 안전성 |
| Tailwind CSS | 3.x | 스타일링 |
| next-intl | latest | 다국어 (mn/en/ru/ko) |
| Socket.io-client | 4.x | 실시간 채팅 |
| React Query | 5.x | 서버 상태 관리 |
| Zustand | 4.x | 클라이언트 상태 관리 |
Backend
| 기술 | 버전 | 용도 |
|---|---|---|
| Node.js | 20 LTS | 런타임 |
| Express.js | 4.x | API 서버 |
| TypeScript | 5.x | 타입 안전성 |
| Socket.io | 4.x | 실시간 통신 |
| Prisma | 5.x | ORM |
| Redis | 7.x | 캐시, 세션, 큐 |
| Bull | 4.x | 작업 큐 |
Database
| 기술 | 버전 | 용도 |
|---|---|---|
| PostgreSQL | 16.x | 메인 데이터베이스 |
External APIs
| 서비스 | 용도 |
|---|---|
| Claude API (Anthropic) | 번역 + FAQ 챗봇 |
| NOWPayments | USDT/USDC 결제 |
| ExchangeRate API | 환율 조회 |
Windows Agent
| 기술 | 버전 | 용도 |
|---|---|---|
| Python | 3.11+ | 에이전트 개발 |
| pywinauto | 0.6.8+ | UI 자동화 |
| aiohttp | 3.x | 비동기 HTTP |
| Pillow | 10.x | 이미지 처리 |
📁 프로젝트 구조
mongol-car-platform/
├── README.md
├── docker-compose.yml
├── .env.example
│
├── apps/
│ ├── web/ # Next.js 프론트엔드
│ │ ├── package.json
│ │ ├── next.config.js
│ │ ├── tailwind.config.js
│ │ ├── tsconfig.json
│ │ │
│ │ ├── public/
│ │ │ ├── locales/ # 다국어 파일
│ │ │ │ ├── mn/ # 몽골어
│ │ │ │ ├── en/ # 영어
│ │ │ │ ├── ru/ # 러시아어
│ │ │ │ └── ko/ # 한국어
│ │ │ └── images/
│ │ │
│ │ ├── src/
│ │ │ ├── app/ # App Router
│ │ │ │ ├── [locale]/
│ │ │ │ │ ├── layout.tsx
│ │ │ │ │ ├── page.tsx # 메인 (검색)
│ │ │ │ │ ├── vehicles/
│ │ │ │ │ │ ├── page.tsx # 검색 결과
│ │ │ │ │ │ └── [id]/
│ │ │ │ │ │ └── page.tsx # 차량 상세
│ │ │ │ │ ├── auth/
│ │ │ │ │ │ ├── login/page.tsx
│ │ │ │ │ │ └── register/page.tsx
│ │ │ │ │ ├── mypage/
│ │ │ │ │ │ ├── page.tsx # 마이페이지
│ │ │ │ │ │ ├── points/page.tsx # 포인트 내역
│ │ │ │ │ │ ├── history/page.tsx # 열람 기록
│ │ │ │ │ │ ├── orders/page.tsx # 주문 내역
│ │ │ │ │ │ └── tracking/
│ │ │ │ │ │ ├── page.tsx # 내차찾기 목록
│ │ │ │ │ │ └── [orderId]/
│ │ │ │ │ │ └── page.tsx # 상세 추적
│ │ │ │ │ ├── payment/
│ │ │ │ │ │ ├── page.tsx # 충전 페이지
│ │ │ │ │ │ ├── success/page.tsx
│ │ │ │ │ │ └── cancel/page.tsx
│ │ │ │ │ └── chat/
│ │ │ │ │ └── [roomId]/page.tsx # 채팅방
│ │ │ │ └── api/ # API Routes (필요시)
│ │ │ │
│ │ │ ├── components/
│ │ │ │ ├── common/
│ │ │ │ │ ├── Header.tsx
│ │ │ │ │ ├── Footer.tsx
│ │ │ │ │ ├── LanguageSwitcher.tsx
│ │ │ │ │ └── Loading.tsx
│ │ │ │ ├── vehicles/
│ │ │ │ │ ├── SearchForm.tsx
│ │ │ │ │ ├── VehicleCard.tsx
│ │ │ │ │ ├── VehicleList.tsx
│ │ │ │ │ ├── VehicleDetail.tsx
│ │ │ │ │ └── ImageGallery.tsx
│ │ │ │ ├── chat/
│ │ │ │ │ ├── ChatWindow.tsx
│ │ │ │ │ ├── MessageList.tsx
│ │ │ │ │ └── MessageInput.tsx
│ │ │ │ ├── payment/
│ │ │ │ │ ├── PaymentModal.tsx
│ │ │ │ │ ├── CryptoSelector.tsx
│ │ │ │ │ └── QRCodeDisplay.tsx
│ │ │ │ ├── order/
│ │ │ │ │ ├── OrderSummary.tsx
│ │ │ │ │ ├── FeeBreakdown.tsx # 수수료 상세 내역
│ │ │ │ │ └── OrderHistory.tsx
│ │ │ │ └── tracking/
│ │ │ │ ├── TrackingMap.tsx # 지도 컴포넌트
│ │ │ │ ├── TrackingStatus.tsx # 현재 상태 표시
│ │ │ │ ├── TrackingTimeline.tsx # 배송 이력 타임라인
│ │ │ │ └── EstimatedArrival.tsx # 예상 도착일
│ │ │ │
│ │ │ ├── hooks/
│ │ │ │ ├── useAuth.ts
│ │ │ │ ├── useVehicles.ts
│ │ │ │ ├── useChat.ts
│ │ │ │ ├── usePayment.ts
│ │ │ │ ├── useOrder.ts
│ │ │ │ └── useTracking.ts
│ │ │ │
│ │ │ ├── lib/
│ │ │ │ ├── api.ts # API 클라이언트
│ │ │ │ ├── socket.ts # Socket.io 클라이언트
│ │ │ │ └── utils.ts
│ │ │ │
│ │ │ ├── stores/
│ │ │ │ ├── authStore.ts
│ │ │ │ └── chatStore.ts
│ │ │ │
│ │ │ └── types/
│ │ │ ├── vehicle.ts
│ │ │ ├── user.ts
│ │ │ ├── payment.ts
│ │ │ ├── order.ts
│ │ │ ├── fee.ts
│ │ │ └── tracking.ts
│ │ │
│ │ └── messages/ # next-intl 메시지
│ │ ├── mn.json
│ │ ├── en.json
│ │ ├── ru.json
│ │ └── ko.json
│ │
│ └── api/ # Node.js 백엔드
│ ├── package.json
│ ├── tsconfig.json
│ │
│ └── src/
│ ├── index.ts # 엔트리포인트
│ ├── app.ts # Express 앱
│ │
│ ├── config/
│ │ ├── database.ts
│ │ ├── redis.ts
│ │ └── env.ts
│ │
│ ├── routes/
│ │ ├── index.ts
│ │ ├── auth.routes.ts
│ │ ├── vehicles.routes.ts
│ │ ├── payment.routes.ts
│ │ ├── chat.routes.ts
│ │ ├── order.routes.ts # 주문 관련
│ │ ├── tracking.routes.ts # 배송 추적
│ │ ├── fee.routes.ts # 수수료 관련
│ │ ├── container.routes.ts # 컨테이너 관리 (관리자)
│ │ └── agent.routes.ts # Windows 에이전트용
│ │
│ ├── controllers/
│ │ ├── auth.controller.ts
│ │ ├── vehicles.controller.ts
│ │ ├── payment.controller.ts
│ │ ├── chat.controller.ts
│ │ ├── order.controller.ts
│ │ ├── tracking.controller.ts
│ │ ├── fee.controller.ts
│ │ ├── container.controller.ts
│ │ └── agent.controller.ts
│ │
│ ├── services/
│ │ ├── auth.service.ts
│ │ ├── vehicles.service.ts
│ │ ├── payment.service.ts
│ │ ├── translation.service.ts # Claude API
│ │ ├── chat.service.ts
│ │ ├── order.service.ts
│ │ ├── tracking.service.ts
│ │ ├── fee.service.ts # 수수료 계산 로직
│ │ ├── container.service.ts # 컨테이너 적재 로직
│ │ └── nowpayments.service.ts
│ │
│ ├── middleware/
│ │ ├── auth.middleware.ts
│ │ ├── rateLimit.middleware.ts
│ │ └── error.middleware.ts
│ │
│ ├── socket/
│ │ ├── index.ts # Socket.io 설정
│ │ └── chat.handler.ts # 채팅 이벤트 핸들러
│ │
│ ├── jobs/
│ │ └── searchQueue.ts # Bull 큐
│ │
│ └── types/
│ └── index.ts
│
├── packages/
│ └── database/ # Prisma 스키마 (공유)
│ ├── package.json
│ ├── prisma/
│ │ ├── schema.prisma
│ │ └── migrations/
│ └── src/
│ └── index.ts # Prisma Client export
│
├── agent/ # Windows 자동화 에이전트
│ ├── requirements.txt
│ ├── config.yaml
│ │
│ ├── src/
│ │ ├── main.py # 엔트리포인트
│ │ ├── carmodoo_agent.py # 카모두 자동화
│ │ ├── api_client.py # 서버 API 클라이언트
│ │ ├── image_handler.py # 이미지 추출/업로드
│ │ └── utils.py
│ │
│ └── tests/
│ └── test_agent.py
│
├── database/ # DB 스키마 및 시드
│ ├── schema.sql # PostgreSQL 스키마
│ ├── seed.sql # 초기 데이터
│ └── backup.sh # 백업 스크립트
│
├── deploy/ # 배포 설정
│ ├── nginx/
│ │ └── default.conf
│ ├── systemd/
│ │ ├── api.service
│ │ └── web.service
│ └── scripts/
│ ├── setup-server.sh # 서버 초기 설정
│ └── deploy.sh # 배포 스크립트
│
└── docs/ # 문서
├── API.md # API 문서
├── DEPLOYMENT.md # 배포 가이드
└── AGENT.md # 에이전트 설정 가이드
🗄️ 데이터베이스 스키마
ERD 개요
┌─────────────┐ ┌─────────────┐ ┌─────────────────┐
│ users │────<│view_history │>────│ vehicles │
└─────────────┘ └─────────────┘ └─────────────────┘
│ │
│◀───────────[referred_by] │
│ │
│ ┌─────────────┐ │
└───────────<│ payments │ │
│ └─────────────┘ │
│ │ │
│ ┌─────────────┐ │
│ │point_history│ │
│ └─────────────┘ │
│ │
│ ┌─────────────┐ │
└───────────<│ chat_rooms │>────────────┘
│ └─────────────┘
│ │
│ ┌─────────────┐
│ │chat_messages│
│ └─────────────┘
│
│ ┌──────────────────┐
└───────────<│dealer_commissions│ (현지딜러 수수료)
└──────────────────┘
주요 테이블
-- 1. 사용자 (users)
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(100),
phone VARCHAR(20),
country VARCHAR(50) DEFAULT 'MN',
language VARCHAR(10) DEFAULT 'mn',
-- 회원 유형
user_type VARCHAR(20) DEFAULT 'customer', -- 'customer', 'local_dealer', 'admin'
-- 현지딜러 추천 시스템 (1단계 직접 추천)
referred_by INTEGER REFERENCES users(id), -- 추천인 (현지딜러)
referral_code VARCHAR(20) UNIQUE, -- 본인의 추천 코드 (딜러용)
free_views_remaining INTEGER DEFAULT 3,
point_balance DECIMAL(12,2) DEFAULT 0,
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 1-1. 회원 유형 (user_types) - 참조 테이블
CREATE TABLE user_types (
code VARCHAR(20) PRIMARY KEY,
name_ko VARCHAR(50) NOT NULL,
name_en VARCHAR(50) NOT NULL,
name_mn VARCHAR(50),
description TEXT,
can_refer_customers BOOLEAN DEFAULT false, -- 고객 추천 가능 여부
commission_rate DECIMAL(4,2) DEFAULT 0, -- 기본 수수료율 (%)
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO user_types (code, name_ko, name_en, name_mn, description, can_refer_customers, commission_rate) VALUES
('customer', '일반고객', 'Customer', 'Хэрэглэгч', '일반 구매 고객', false, 0),
('local_dealer', '현지딜러', 'Local Dealer', 'Орон нутгийн дилер', '몽골 현지 딜러 (고객 추천 가능)', true, 3.5),
('admin', '관리자', 'Administrator', 'Админ', '시스템 관리자', false, 0);
-- 1-2. 현지딜러 정보 (dealer_profiles)
CREATE TABLE dealer_profiles (
id SERIAL PRIMARY KEY,
user_id INTEGER UNIQUE REFERENCES users(id) ON DELETE CASCADE,
-- 사업자 정보
business_name VARCHAR(200), -- 상호명
business_registration_no VARCHAR(50), -- 사업자등록번호
business_address TEXT, -- 사업장 주소
business_phone VARCHAR(30), -- 사업장 전화번호
-- 딜러 등급 및 수수료
dealer_grade VARCHAR(20) DEFAULT 'standard', -- 'standard', 'silver', 'gold', 'platinum'
commission_rate DECIMAL(4,2) DEFAULT 3.5, -- 개별 수수료율 (기본 3.5%)
-- 은행 정보 (수수료 지급용)
bank_name VARCHAR(100),
bank_account_number VARCHAR(50),
bank_account_holder VARCHAR(100),
-- 활동 통계
total_referrals INTEGER DEFAULT 0, -- 총 추천 고객 수
total_sales_count INTEGER DEFAULT 0, -- 총 판매 건수
total_commission_earned DECIMAL(14,2) DEFAULT 0, -- 총 수령 수수료
-- 상태
verification_status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'verified', 'rejected'
verified_at TIMESTAMP,
notes TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 1-3. 딜러 등급 (dealer_grades)
CREATE TABLE dealer_grades (
code VARCHAR(20) PRIMARY KEY,
name_ko VARCHAR(50) NOT NULL,
name_en VARCHAR(50) NOT NULL,
name_mn VARCHAR(50),
min_sales_count INTEGER DEFAULT 0, -- 승급 조건: 최소 판매 건수
commission_rate DECIMAL(4,2) NOT NULL, -- 등급별 수수료율
benefits TEXT, -- 혜택 설명
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO dealer_grades (code, name_ko, name_en, name_mn, min_sales_count, commission_rate, benefits, sort_order) VALUES
('standard', '일반', 'Standard', 'Стандарт', 0, 3.0, '기본 수수료율 적용', 1),
('silver', '실버', 'Silver', 'Мөнгө', 10, 3.5, '수수료율 0.5% 상향', 2),
('gold', '골드', 'Gold', 'Алт', 30, 4.0, '수수료율 1.0% 상향, 우선 배정', 3),
('platinum', '플래티넘', 'Platinum', 'Платин', 100, 4.5, '수수료율 1.5% 상향, 전담 매니저', 4);
-- 2. 차량 (vehicles)
CREATE TABLE vehicles (
id SERIAL PRIMARY KEY,
source_id VARCHAR(100) UNIQUE,
make VARCHAR(50) NOT NULL,
model VARCHAR(100) NOT NULL,
year INTEGER NOT NULL,
mileage INTEGER,
price DECIMAL(14,2),
fuel_type VARCHAR(20),
transmission VARCHAR(20),
color VARCHAR(30),
engine_cc INTEGER,
options JSONB DEFAULT '{}',
inspection_data JSONB DEFAULT '{}',
accident_history JSONB DEFAULT '[]',
status VARCHAR(20) DEFAULT 'active',
view_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
-- 3. 차량 이미지 (vehicle_images)
CREATE TABLE vehicle_images (
id SERIAL PRIMARY KEY,
vehicle_id INTEGER REFERENCES vehicles(id) ON DELETE CASCADE,
image_url VARCHAR(500) NOT NULL,
thumbnail_url VARCHAR(500),
image_type VARCHAR(30),
sort_order INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
-- 4. 열람 기록 (view_history)
CREATE TABLE view_history (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
vehicle_id INTEGER REFERENCES vehicles(id),
is_free BOOLEAN DEFAULT false,
points_used DECIMAL(10,2) DEFAULT 0,
viewed_at TIMESTAMP DEFAULT NOW(),
UNIQUE(user_id, vehicle_id)
);
-- 5. 결제 (payments)
CREATE TABLE payments (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
payment_id VARCHAR(100) UNIQUE,
payment_type VARCHAR(20),
amount_krw DECIMAL(12,2),
amount_crypto DECIMAL(20,8),
crypto_type VARCHAR(20),
pay_address VARCHAR(200),
tx_hash VARCHAR(100),
points_added DECIMAL(12,2),
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT NOW(),
confirmed_at TIMESTAMP
);
-- 6. 포인트 이력 (point_history)
CREATE TABLE point_history (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
amount DECIMAL(12,2) NOT NULL,
type VARCHAR(20),
description VARCHAR(200),
balance_after DECIMAL(12,2),
created_at TIMESTAMP DEFAULT NOW()
);
-- 7. 채팅방 (chat_rooms)
CREATE TABLE chat_rooms (
id SERIAL PRIMARY KEY,
vehicle_id INTEGER REFERENCES vehicles(id),
customer_id INTEGER REFERENCES users(id),
dealer_id VARCHAR(50),
status VARCHAR(20) DEFAULT 'active',
last_message_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
-- 8. 채팅 메시지 (chat_messages)
CREATE TABLE chat_messages (
id BIGSERIAL PRIMARY KEY,
room_id INTEGER REFERENCES chat_rooms(id),
sender_id VARCHAR(50) NOT NULL,
sender_type VARCHAR(20),
original_text TEXT NOT NULL,
original_language VARCHAR(10),
translations JSONB DEFAULT '{}',
is_faq_response BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT NOW()
);
-- 9. 검색 요청 큐 (search_requests)
CREATE TABLE search_requests (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
criteria JSONB NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
result_count INTEGER,
created_at TIMESTAMP DEFAULT NOW(),
processed_at TIMESTAMP
);
-- 10. 차량 크기 분류 (vehicle_size_types)
CREATE TABLE vehicle_size_types (
id SERIAL PRIMARY KEY,
code VARCHAR(20) UNIQUE NOT NULL, -- 'compact', 'midsize'
name_ko VARCHAR(50) NOT NULL,
name_en VARCHAR(50) NOT NULL,
name_mn VARCHAR(50),
max_per_container INTEGER NOT NULL, -- 컨테이너당 최대 적재 수량
created_at TIMESTAMP DEFAULT NOW()
);
-- 초기 데이터
INSERT INTO vehicle_size_types (code, name_ko, name_en, name_mn, max_per_container) VALUES
('compact', '소형차', 'Compact Car', 'Жижиг машин', 4),
('midsize', '중형차', 'Midsize Car', 'Дунд машин', 2);
-- 11. 수수료 항목 마스터 (fee_types)
CREATE TABLE fee_types (
id SERIAL PRIMARY KEY,
code VARCHAR(50) UNIQUE NOT NULL,
category VARCHAR(30) NOT NULL, -- 'vehicle', 'container', 'terminal'
name_ko VARCHAR(100) NOT NULL,
name_en VARCHAR(100) NOT NULL,
name_mn VARCHAR(100),
calculation_type VARCHAR(20) NOT NULL, -- 'fixed', 'percentage', 'per_day', 'per_container', 'per_car'
default_amount DECIMAL(14,2),
percentage_rate DECIMAL(5,2), -- 퍼센트 계산 시 사용
is_shared BOOLEAN DEFAULT false, -- 컨테이너 비용 분담 여부
sort_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW()
);
-- 수수료 항목 초기 데이터
-- 차량별 비용 (vehicle)
INSERT INTO fee_types (code, category, name_ko, name_en, calculation_type, default_amount, percentage_rate, is_shared, sort_order) VALUES
('performance_inspection', 'vehicle', '성능점검보험료', 'Performance inspection fee', 'fixed', 100000, NULL, false, 1),
('sales_fee', 'vehicle', '매도세', 'Sales fee', 'fixed', 440000, NULL, false, 2),
('brokerage_commission', 'vehicle', '매매알선수수료', 'Brokerage commission', 'fixed', 250000, NULL, false, 3),
('registration_tax', 'vehicle', '취등록세', 'Registration tax', 'fixed', 50000, NULL, false, 4),
('expiration_cost', 'vehicle', '말소', 'Expiration cost', 'fixed', 50000, NULL, false, 5),
('domestic_transport', 'vehicle', '국내 운송료', 'Domestic transportation charges', 'fixed', 160000, NULL, false, 6),
('yard_fee', 'vehicle', '야드비', 'Yard fee', 'per_day', 20000, NULL, false, 7),
('export_license', 'vehicle', '수출면장발급', 'Issuance of export exemption', 'fixed', 45000, NULL, false, 8),
('korean_margin', 'vehicle', '한국 마진', 'Korean Margin', 'percentage', NULL, 5.00, false, 9),
('mongolian_margin', 'vehicle', '몽골 마진', 'Mongolian Margin', 'percentage', NULL, 5.00, false, 10),
-- 컨테이너 비용 (분담, container)
('shipping_cost', 'container', '운송비(기차 4주)', 'Shipping Cost (Train 4weeks)', 'per_container', 5220000, NULL, true, 11),
('shoring', 'container', '쇼링(컨테이너작업)', 'Shoring', 'per_container', 600000, NULL, true, 12),
-- 터미널 비용 (분담, terminal)
('thc', 'terminal', '터미널 조작비용', 'THC(Terminal Handling Charge)', 'per_container', 190000, NULL, true, 13),
('wharfage', 'terminal', '부두하역료', 'Wharfage', 'per_container', 8400, NULL, true, 14),
('seal_fee', 'terminal', '컨테이너 실 비용', 'Seal Fee', 'per_container', 10000, NULL, true, 15),
('document_fee', 'terminal', '서류수수료', 'Document fee', 'per_container', 50000, NULL, true, 16);
-- 12. 주문 (orders)
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
order_number VARCHAR(50) UNIQUE NOT NULL, -- ORD-20241127-0001
user_id INTEGER REFERENCES users(id),
vehicle_id INTEGER REFERENCES vehicles(id),
vehicle_size_type_id INTEGER REFERENCES vehicle_size_types(id),
vehicle_price DECIMAL(14,2) NOT NULL, -- 차량가액
total_fees DECIMAL(14,2) NOT NULL, -- 총 수수료
total_amount DECIMAL(14,2) NOT NULL, -- 총 결제금액
status VARCHAR(30) DEFAULT 'pending', -- pending, paid, processing, shipping, customs, delivered, cancelled
payment_status VARCHAR(20) DEFAULT 'unpaid', -- unpaid, partial, paid
notes TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 13. 주문 수수료 상세 (order_fees)
CREATE TABLE order_fees (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES orders(id) ON DELETE CASCADE,
fee_type_id INTEGER REFERENCES fee_types(id),
fee_code VARCHAR(50) NOT NULL,
fee_name_ko VARCHAR(100) NOT NULL,
fee_name_en VARCHAR(100) NOT NULL,
calculation_type VARCHAR(20) NOT NULL,
base_amount DECIMAL(14,2), -- 기준 금액
quantity INTEGER DEFAULT 1, -- 일수 등
calculated_amount DECIMAL(14,2) NOT NULL, -- 최종 계산된 금액
is_shared BOOLEAN DEFAULT false,
share_count INTEGER DEFAULT 1, -- 분담 차량 수
notes VARCHAR(200),
created_at TIMESTAMP DEFAULT NOW()
);
-- 14. 컨테이너 (containers)
CREATE TABLE containers (
id SERIAL PRIMARY KEY,
container_number VARCHAR(50) UNIQUE, -- CNTR-20241127-001
container_type VARCHAR(20) DEFAULT '40ft', -- 20ft, 40ft
max_compact_cars INTEGER DEFAULT 4, -- 소형차 최대 적재량
max_midsize_cars INTEGER DEFAULT 2, -- 중형차 최대 적재량 (중형 4대 불가 규칙)
current_compact_count INTEGER DEFAULT 0,
current_midsize_count INTEGER DEFAULT 0,
status VARCHAR(20) DEFAULT 'loading', -- loading, sealed, in_transit, arrived, cleared
-- 출발/도착 정보
departure_port VARCHAR(100), -- 부산항
arrival_port VARCHAR(100), -- 울란바타르
-- 일정
estimated_departure_date DATE,
actual_departure_date DATE,
estimated_arrival_date DATE,
actual_arrival_date DATE,
-- 비용 정보 (컨테이너 비용은 적재된 차량들이 분담)
shipping_cost DECIMAL(14,2),
shoring_cost DECIMAL(14,2),
terminal_cost DECIMAL(14,2),
total_shared_cost DECIMAL(14,2),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 15. 컨테이너-차량 매핑 (container_vehicles)
CREATE TABLE container_vehicles (
id SERIAL PRIMARY KEY,
container_id INTEGER REFERENCES containers(id) ON DELETE CASCADE,
order_id INTEGER REFERENCES orders(id),
vehicle_id INTEGER REFERENCES vehicles(id),
vehicle_size_type VARCHAR(20) NOT NULL, -- 'compact', 'midsize'
shared_cost_amount DECIMAL(14,2), -- 분담된 비용
loaded_at TIMESTAMP DEFAULT NOW()
);
-- 16. 배송 추적 (shipment_tracking)
CREATE TABLE shipment_tracking (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES orders(id),
container_id INTEGER REFERENCES containers(id),
-- 위치 정보
current_location VARCHAR(200),
latitude DECIMAL(10, 7),
longitude DECIMAL(10, 7),
location_type VARCHAR(30), -- 'port', 'railway', 'customs', 'warehouse', 'delivered'
-- 상태
status VARCHAR(30) NOT NULL, -- preparing, departed_korea, in_transit, arrived_mongolia, customs_clearance, delivered
status_detail VARCHAR(200),
-- 예상 일정
estimated_arrival_date DATE,
estimated_arrival_days INTEGER, -- 남은 예상 일수
-- 통관 정보
customs_status VARCHAR(30), -- pending, in_progress, cleared
customs_document_number VARCHAR(100),
updated_at TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW()
);
-- 17. 배송 이력 (shipment_history)
CREATE TABLE shipment_history (
id SERIAL PRIMARY KEY,
order_id INTEGER REFERENCES orders(id),
container_id INTEGER REFERENCES containers(id),
status VARCHAR(30) NOT NULL,
location VARCHAR(200),
latitude DECIMAL(10, 7),
longitude DECIMAL(10, 7),
description_ko VARCHAR(300),
description_en VARCHAR(300),
description_mn VARCHAR(300),
event_time TIMESTAMP DEFAULT NOW(),
created_at TIMESTAMP DEFAULT NOW()
);
-- 배송 상태 코드 참조 테이블 (shipment_status_codes)
CREATE TABLE shipment_status_codes (
code VARCHAR(30) PRIMARY KEY,
name_ko VARCHAR(100) NOT NULL,
name_en VARCHAR(100) NOT NULL,
name_mn VARCHAR(100),
sort_order INTEGER,
icon VARCHAR(50) -- 프론트엔드 아이콘 매핑용
);
INSERT INTO shipment_status_codes (code, name_ko, name_en, name_mn, sort_order, icon) VALUES
('preparing', '출고 준비 중', 'Preparing for shipment', 'Тээвэрлэлтэнд бэлтгэж байна', 1, 'package'),
('loaded', '컨테이너 적재 완료', 'Loaded into container', 'Чингэлэг ачигдсан', 2, 'truck'),
('departed_korea', '한국 출발', 'Departed from Korea', 'Солонгосоос гарсан', 3, 'ship'),
('in_transit_rail', '기차 운송 중', 'In transit (Rail)', 'Тээвэрлэж байна (Төмөр зам)', 4, 'train'),
('arrived_mongolia', '몽골 도착', 'Arrived in Mongolia', 'Монголд ирсэн', 5, 'flag'),
('customs_clearance', '통관 진행 중', 'Customs clearance in progress', 'Гаалийн бүрдүүлэлт хийгдэж байна', 6, 'clipboard'),
('customs_cleared', '통관 완료', 'Customs cleared', 'Гаалийн бүрдүүлэлт дууссан', 7, 'check'),
('ready_for_pickup', '인수 대기', 'Ready for pickup', 'Авахад бэлэн', 8, 'warehouse'),
('delivered', '인도 완료', 'Delivered', 'Хүргэгдсэн', 9, 'check-circle');
-- =====================================================
-- 현지딜러 수수료 시스템 (1단계 직접 추천 구조)
-- =====================================================
-- 18. 딜러 수수료 내역 (dealer_commissions)
CREATE TABLE dealer_commissions (
id SERIAL PRIMARY KEY,
dealer_id INTEGER REFERENCES users(id), -- 현지딜러 (수수료 수령자)
order_id INTEGER REFERENCES orders(id), -- 연결된 주문
customer_id INTEGER REFERENCES users(id), -- 추천받은 고객
-- 수수료 계산
vehicle_price DECIMAL(14,2) NOT NULL, -- 차량가액
mongolian_margin_rate DECIMAL(4,2) NOT NULL, -- 몽골 마진율 (전체 5%)
dealer_commission_rate DECIMAL(4,2) NOT NULL, -- 딜러 수수료율 (3~4.5%)
platform_rate DECIMAL(4,2) NOT NULL, -- 플랫폼 수수료율 (0.5~2%)
dealer_commission_amount DECIMAL(14,2) NOT NULL, -- 딜러 수수료 금액
platform_amount DECIMAL(14,2) NOT NULL, -- 플랫폼 수수료 금액
-- 지급 정보
status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'approved', 'paid', 'cancelled'
payment_method VARCHAR(30), -- 'bank_transfer', 'crypto'
payment_reference VARCHAR(100), -- 송금 참조번호
paid_at TIMESTAMP,
notes TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- 19. 딜러 수수료 정산 (dealer_payouts)
CREATE TABLE dealer_payouts (
id SERIAL PRIMARY KEY,
dealer_id INTEGER REFERENCES users(id),
payout_number VARCHAR(50) UNIQUE, -- PAY-20241127-001
-- 정산 기간
period_start DATE NOT NULL,
period_end DATE NOT NULL,
-- 정산 금액
total_orders INTEGER DEFAULT 0, -- 해당 기간 주문 건수
total_commission DECIMAL(14,2) NOT NULL, -- 총 수수료
deductions DECIMAL(14,2) DEFAULT 0, -- 공제액 (있을 경우)
net_amount DECIMAL(14,2) NOT NULL, -- 실 지급액
-- 지급 정보
payment_method VARCHAR(30) NOT NULL, -- 'bank_transfer', 'crypto'
bank_name VARCHAR(100),
bank_account_number VARCHAR(50),
payment_reference VARCHAR(100),
status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'processing', 'completed', 'failed'
processed_at TIMESTAMP,
completed_at TIMESTAMP,
notes TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
-- 20. 추천 코드 사용 이력 (referral_history)
CREATE TABLE referral_history (
id SERIAL PRIMARY KEY,
referral_code VARCHAR(20) NOT NULL,
dealer_id INTEGER REFERENCES users(id), -- 코드 소유자 (딜러)
customer_id INTEGER REFERENCES users(id), -- 코드 사용자 (고객)
used_at TIMESTAMP DEFAULT NOW(),
ip_address VARCHAR(50),
user_agent TEXT
);
🔌 API 명세
인증 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/auth/register |
회원가입 |
| POST | /api/auth/login |
로그인 |
| POST | /api/auth/logout |
로그아웃 |
| GET | /api/auth/me |
현재 사용자 정보 |
| PUT | /api/auth/profile |
프로필 수정 |
차량 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/vehicles/search |
차량 검색 요청 |
| GET | /api/vehicles/search/:requestId |
검색 결과 조회 |
| GET | /api/vehicles/:id |
차량 상세 (포인트 차감) |
| GET | /api/vehicles/:id/preview |
차량 미리보기 (무료) |
결제 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/payment/card |
카드 결제 생성 |
| POST | /api/payment/direct |
직접 전송 주소 생성 |
| POST | /api/payment/webhook |
NOWPayments 웹훅 |
| GET | /api/payment/history |
결제 내역 |
채팅 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/chat/rooms |
채팅방 생성 |
| GET | /api/chat/rooms |
채팅방 목록 |
| GET | /api/chat/rooms/:id/messages |
메시지 조회 |
주문/배송 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/orders |
주문 생성 |
| GET | /api/orders |
내 주문 목록 |
| GET | /api/orders/:id |
주문 상세 (수수료 내역 포함) |
| GET | /api/orders/:id/fees |
주문 수수료 상세 조회 |
| GET | /api/tracking/:orderId |
내차 위치 추적 |
| GET | /api/tracking/:orderId/history |
배송 이력 조회 |
수수료 API
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/fees |
수수료 항목 목록 |
| POST | /api/fees/calculate |
수수료 계산 (견적) |
컨테이너 API (관리자용)
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/admin/containers |
컨테이너 생성 |
| POST | /api/admin/containers/:id/vehicles |
차량 적재 |
| PUT | /api/admin/containers/:id/status |
컨테이너 상태 업데이트 |
| PUT | /api/admin/tracking/:orderId |
배송 추적 정보 업데이트 |
현지딜러 API
| Method | Endpoint | 설명 |
|---|---|---|
| POST | /api/dealer/register |
딜러 등록 신청 |
| GET | /api/dealer/profile |
딜러 프로필 조회 |
| PUT | /api/dealer/profile |
딜러 프로필 수정 |
| GET | /api/dealer/referrals |
추천 고객 목록 |
| GET | /api/dealer/commissions |
수수료 내역 조회 |
| GET | /api/dealer/commissions/summary |
수수료 요약 (대시보드) |
| GET | /api/dealer/payouts |
정산 내역 조회 |
| POST | /api/referral/apply |
추천 코드 적용 (고객용) |
| GET | /api/referral/validate/:code |
추천 코드 유효성 검증 |
딜러 관리 API (관리자용)
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/admin/dealers |
딜러 목록 조회 |
| PUT | /api/admin/dealers/:id/verify |
딜러 승인/거부 |
| PUT | /api/admin/dealers/:id/grade |
딜러 등급 변경 |
| POST | /api/admin/payouts |
정산 처리 |
| GET | /api/admin/commissions/report |
수수료 리포트 |
에이전트 API (내부용)
| Method | Endpoint | 설명 |
|---|---|---|
| GET | /api/agent/pending-searches |
대기 중인 검색 요청 |
| POST | /api/agent/search-results |
검색 결과 전송 |
| POST | /api/agent/vehicle-detail |
차량 상세 정보 전송 |
| POST | /api/agent/upload-images |
이미지 업로드 |
👥 현지딜러 시스템 (1단계 직접 추천 구조)
시스템 개요
┌─────────────────────────────────────────────────────────────────────────┐
│ 1단계 직접 추천 구조 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 플랫폼 운영사 │ │
│ │ (한국 마진 5% 수령) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 몽골 마진 5% │ │
│ │ │ │ │
│ │ ┌─────────────────┴─────────────────┐ │ │
│ │ ▼ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ 현지딜러 몫 │ │ 플랫폼 몫 │ │ │
│ │ │ 3~4.5% │ │ 0.5~2% │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 현지딜러 │ │
│ │ • 고객에게 추천 코드 제공 │ │
│ │ • 고객이 차량 구매 시 수수료 수령 │ │
│ │ • 등급에 따라 수수료율 차등 │ │
│ └──────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 고객 A │ │ 고객 B │ │ 고객 C │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ✅ 핵심 규칙: │
│ • 딜러가 직접 추천한 고객만 수수료 지급 (1단계만) │
│ • 고객이 다시 다른 고객을 추천해도 원래 딜러에게 수수료 없음 │
│ • 다단계 구조 아님 → 법적 문제 없음 │
└─────────────────────────────────────────────────────────────────────────┘
회원 유형
| 유형 | 설명 | 추천 가능 | 수수료 수령 |
|---|---|---|---|
| 일반고객 (customer) | 차량 구매 고객 | ❌ | ❌ |
| 현지딜러 (local_dealer) | 몽골 현지 딜러 | ✅ | ✅ |
| 관리자 (admin) | 시스템 관리자 | ❌ | ❌ |
현지딜러 등급 및 수수료율
| 등급 | 조건 | 수수료율 | 혜택 |
|---|---|---|---|
| 일반 (Standard) | 기본 | 3.0% | 기본 수수료율 적용 |
| 실버 (Silver) | 10건 이상 판매 | 3.5% | 수수료율 0.5%p 상향 |
| 골드 (Gold) | 30건 이상 판매 | 4.0% | 수수료율 1.0%p 상향, 우선 배정 |
| 플래티넘 (Platinum) | 100건 이상 판매 | 4.5% | 수수료율 1.5%p 상향, 전담 매니저 |
수수료 계산 예시
차량가: ₩25,000,000
몽골 마진 (5%): ₩1,250,000
┌─────────────────────────────────────────────────────────────┐
│ 딜러 등급별 수수료 배분 │
├─────────────────┬─────────────┬─────────────┬───────────────┤
│ 딜러 등급 │ 딜러 수수료 │ 플랫폼 몫 │ 합계 (5%) │
├─────────────────┼─────────────┼─────────────┼───────────────┤
│ 일반 (3.0%) │ ₩750,000 │ ₩500,000 │ ₩1,250,000 │
│ 실버 (3.5%) │ ₩875,000 │ ₩375,000 │ ₩1,250,000 │
│ 골드 (4.0%) │ ₩1,000,000 │ ₩250,000 │ ₩1,250,000 │
│ 플래티넘 (4.5%) │ ₩1,125,000 │ ₩125,000 │ ₩1,250,000 │
└─────────────────┴─────────────┴─────────────┴───────────────┘
※ 추천인 없는 직접 구매 시: 플랫폼이 5% 전액 수령
추천 시스템 플로우
1. 딜러 등록
┌──────────────────────────────────────────────────────────┐
│ 현지딜러 신청 → 서류 심사 → 승인 → 추천 코드 발급 │
│ │
│ 예: 추천코드 "DEALER-ABC123" │
└──────────────────────────────────────────────────────────┘
2. 고객 추천
┌──────────────────────────────────────────────────────────┐
│ 딜러가 고객에게 추천 코드 제공 │
│ ↓ │
│ 고객이 회원가입 시 추천 코드 입력 │
│ ↓ │
│ 고객 계정에 referred_by = 딜러 ID 저장 │
└──────────────────────────────────────────────────────────┘
3. 차량 구매
┌──────────────────────────────────────────────────────────┐
│ 고객이 차량 구매 완료 │
│ ↓ │
│ 시스템이 고객의 추천인(딜러) 확인 │
│ ↓ │
│ 딜러 수수료 자동 계산 및 기록 │
│ ↓ │
│ 월별/주별 정산 후 딜러에게 지급 │
└──────────────────────────────────────────────────────────┘
딜러 대시보드 기능
┌─────────────────────────────────────────────────────────────┐
│ 딜러 대시보드 (My Dashboard) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 추천 고객 │ │ 이번달 판매 │ │ 총 수수료 │ │
│ │ 127명 │ │ 5건 │ │ ₩4,750,000 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 내 등급: 🥇 골드 (다음 등급까지 8건) │
│ 수수료율: 4.0% │
│ 추천 코드: DEALER-ABC123 [복사] │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 최근 수수료 내역 │ │
│ │ ────────────────────────────────────────────────── │ │
│ │ 2024.11.25 소나타 DN8 ₩1,000,000 지급완료 │ │
│ │ 2024.11.20 아반떼 CN7 ₩800,000 지급완료 │ │
│ │ 2024.11.15 K5 DL3 ₩950,000 지급대기 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 내 추천 고객 목록 │ │
│ │ ────────────────────────────────────────────────── │ │
│ │ 바트수흐 bat***@email.com 가입일: 2024.11.01 │ │
│ │ 엥흐바야르 enk***@email.com 가입일: 2024.10.15 │ │
│ │ ... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
정산 주기
| 구분 | 주기 | 최소 지급액 | 지급일 |
|---|---|---|---|
| 일반 정산 | 월 1회 | ₩100,000 | 매월 10일 |
| VIP 정산 | 주 1회 | ₩500,000 | 매주 금요일 |
🚚 수수료 체계 및 비용 구조
차량별 비용 (1대 기준)
| 내역 | Detail | 단가 | 계산 방식 |
|---|---|---|---|
| 차량가액 | Vehicle value | 변동 | 차량별 상이 |
| 성능점검보험료 | Performance inspection fee | ₩100,000 | 고정 |
| 매도세 | Sales fee | ₩440,000 | 고정 |
| 매매알선수수료 | Brokerage commission | ₩250,000 | 고정 |
| 취등록세 | Registration tax | ₩50,000 | 고정 |
| 말소 | Expiration cost | ₩50,000 | 고정 |
| 국내 운송료 | Domestic transportation charges | ₩160,000 | 고정 |
| 야드비 | Yard fee (₩20,000/일) | ₩60,000~ | 일수 × 20,000 |
| 수출면장발급 | Issuance of export exemption | ₩45,000 | 고정 |
| 한국 마진 | Korean Margin (5%) | 차량가 × 5% | 퍼센트 |
| 몽골 마진 | Mongolian Margin (5%) | 차량가 × 5% | 퍼센트 |
컨테이너 비용 (4대 분담)
| 내역 | Detail | 컨테이너당 | 차량당(4대 분담) |
|---|---|---|---|
| 운송비(기차 4주) | Shipping Cost (Train 4weeks) | ₩5,220,000 | ₩1,305,000 |
| 쇼링(컨테이너작업) | Shoring | ₩600,000 | ₩150,000 |
터미널 비용 (4대 분담)
| 내역 | Detail | 컨테이너당 | 차량당(4대 분담) |
|---|---|---|---|
| 터미널 조작비용 | THC (Terminal Handling Charge) | ₩190,000 | ₩47,500 |
| 부두하역료 | Wharfage | ₩8,400 | ₩2,100 |
| 컨테이너 실 비용 | Seal Fee | ₩10,000 | ₩2,500 |
| 서류수수료 | Document fee | ₩50,000 | ₩12,500 |
비용 계산 예시 (차량가 ₩25,000,000 기준)
차량별 비용 소계: ₩28,655,000
- 차량가액: ₩25,000,000
- 성능점검보험료: ₩100,000
- 매도세: ₩440,000
- 매매알선수수료: ₩250,000
- 취등록세: ₩50,000
- 말소: ₩50,000
- 국내 운송료: ₩160,000
- 야드비(3일): ₩60,000
- 수출면장발급: ₩45,000
- 한국 마진(5%): ₩1,250,000
- 몽골 마진(5%): ₩1,250,000
컨테이너 분담 비용 소계 (4대 분담시): ₩1,519,600
- 운송비 분담: ₩1,305,000
- 쇼링 분담: ₩150,000
- THC 분담: ₩47,500
- 부두하역료 분담: ₩2,100
- Seal Fee 분담: ₩2,500
- 서류수수료 분담: ₩12,500
총계: ₩30,174,600
🚢 컨테이너 적재 규칙
차량 크기 분류
| 분류 | 예시 차종 | 컨테이너당 최대 |
|---|---|---|
| 소형차 (Compact) | 모닝, 스파크, 레이, i10, i20 등 | 4대 |
| 중형차 (Midsize) | 아반떼, K3, 소나타, K5, 싼타페 등 | 2대 |
적재 조합 규칙
1대의 컨테이너(40ft)에 다음 조합만 가능:
| 조합 | 소형차 | 중형차 | 총 차량 수 | 가능 여부 |
|---|---|---|---|---|
| A | 4대 | 0대 | 4대 | ✅ 가능 |
| B | 2대 | 2대 | 4대 | ✅ 가능 |
| C | 0대 | 2대 | 2대 | ✅ 가능 |
| D | 3대 | 1대 | 4대 | ✅ 가능 |
| E | 1대 | 2대 | 3대 | ✅ 가능 |
| F | 0대 | 4대 | 4대 | ❌ 불가능 |
중요: 중형차 4대 조합은 물리적 공간 제약으로 불가능합니다.
비용 분담 계산
컨테이너 공유 비용은 적재된 차량 수로 균등 분담:
분담 비용 = 컨테이너 총 비용 ÷ 적재 차량 수
예시:
- 4대 적재시: ₩6,078,400 ÷ 4 = ₩1,519,600/대
- 3대 적재시: ₩6,078,400 ÷ 3 = ₩2,026,133/대
- 2대 적재시: ₩6,078,400 ÷ 2 = ₩3,039,200/대
📍 내차찾기 (Vehicle Tracking)
기능 개요
차량 구매 고객이 자신의 차량 배송 현황을 실시간으로 확인할 수 있는 서비스
주요 기능
-
지도 표시
- 한국 → 몽골 운송 경로 시각화
- 현재 차량 위치 마커 표시
- 주요 경유지 표시 (부산항, 중국 경유, 울란바타르)
-
배송 상태 추적
- 단계별 진행 상황 표시
- 예상 도착일 표시
- 잔여 일수 카운트다운
-
배송 이력
- 타임라인 형태의 상세 이력
- 각 단계별 날짜/시간
- 다국어 설명 (몽골어/영어/러시아어/한국어)
배송 상태 단계
1. 출고 준비 중 (Preparing for shipment)
↓
2. 컨테이너 적재 완료 (Loaded into container)
↓
3. 한국 출발 (Departed from Korea)
↓
4. 기차 운송 중 (In transit - Rail)
[약 4주 소요]
↓
5. 몽골 도착 (Arrived in Mongolia)
↓
6. 통관 진행 중 (Customs clearance in progress)
↓
7. 통관 완료 (Customs cleared)
↓
8. 인수 대기 (Ready for pickup)
↓
9. 인도 완료 (Delivered)
운송 경로 (예상 소요 시간)
부산항 → (기차 4주) → 중국 경유 → 울란바타르
- 총 예상 소요 기간: 28~35일
- 통관 소요 기간: 3~7일 (추가)
UI/UX 설계
┌─────────────────────────────────────────────────────────────┐
│ 내 차 찾기 (Track My Vehicle) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ [ 지도 영역 ] │ │
│ │ │ │
│ │ 부산 ●━━━━━━━●━━━━━🚗━━━━━━━━━━━━● 울란바타르 │ │
│ │ 중국 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 현재 상태: 🚂 기차 운송 중 │
│ 예상 도착일: 2024년 12월 25일 (D-18) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 배송 이력 │ │
│ │ ───────────────────────────────────────────────── │ │
│ │ ✅ 2024.11.20 출고 준비 완료 │ │
│ │ ✅ 2024.11.22 컨테이너 적재 완료 │ │
│ │ ✅ 2024.11.25 한국 출발 (부산항) │ │
│ │ 🔵 2024.11.27 기차 운송 중 (현재) │ │
│ │ ⭕ 예정 몽골 도착 │ │
│ │ ⭕ 예정 통관 진행 │ │
│ │ ⭕ 예정 인도 완료 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
프론트엔드 구조
apps/web/src/app/[locale]/
└── mypage/
└── tracking/
├── page.tsx # 내 차량 목록
└── [orderId]/
└── page.tsx # 상세 추적 페이지
apps/web/src/components/
└── tracking/
├── TrackingMap.tsx # 지도 컴포넌트
├── TrackingStatus.tsx # 현재 상태 표시
├── TrackingTimeline.tsx # 배송 이력 타임라인
└── EstimatedArrival.tsx # 예상 도착일 표시
지도 서비스 옵션
| 서비스 | 장점 | 단점 |
|---|---|---|
| Leaflet + OpenStreetMap | 무료, 커스터마이징 가능 | 기본 스타일 제한 |
| Mapbox | 고품질, 커스터마이징 | 유료 (월 50,000뷰 무료) |
| Google Maps | 신뢰성, 정확도 | 비용, 몽골 지역 상세도 낮음 |
권장: Leaflet + OpenStreetMap (무료 + 충분한 기능)
💰 과금 시스템 (CC 코인 기반)
🪙 CC (AutonetSellCar Coin) 시스템
| 항목 | 내용 |
|---|---|
| 기준 화폐 | USDC (Solana 네트워크) |
| 내부 화폐 | CC (AutonetSellCar Coin) |
| 환율 | 1 USDC = 10 CC |
| 신규 가입 보너스 | 3 CC 무상 지급 |
| 차량 정보 열람 | 1대당 1 CC |
📸 차량 정보 공개 정책
| 구분 | 비회원/무료 | CC 결제 후 |
|---|---|---|
| 대표 이미지 | 2장만 공개 | 전체 공개 |
| 상세 이미지 | 🔒 블러 처리 | ✅ 전체 공개 |
| 차량 성능표 | 🔒 접근 불가 | ✅ 열람 가능 |
| 연락처 | 🔒 비공개 | ✅ DamonHong +82-10-3331-5258 |
| 상세 옵션 | 🔒 비공개 | ✅ 공개 |
┌─────────────────────────────────────────────────────────────────┐
│ 차량 상세 페이지 구조 │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [대표이미지 1] [대표이미지 2] [🔒 블러] [🔒 블러] │ │
│ │ 무료로 볼 수 있는 사진 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 기본 정보 (무료 공개) │ │
│ │ • 차량명: 기아 K5 2024년형 │ │
│ │ • 연식: 2024년 7월 │ │
│ │ • 주행거리: 14,605 km │ │
│ │ • 가격: $28,500 USDC │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 🔒 상세 정보 열람하기 (1 CC 필요) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ [1 CC로 상세 정보 열람하기] │ │ │
│ │ │ │ │ │
│ │ │ 포함 내용: │ │ │
│ │ │ ✓ 전체 사진 (20장) │ │ │
│ │ │ ✓ 차량 성능표 │ │ │
│ │ │ ✓ 상세 옵션 목록 │ │ │
│ │ │ ✓ 연락처 (DamonHong +82-10-3331-5258) │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
💳 결제 방식
| 방식 | 설명 | 수수료 | 구현 우선순위 |
|---|---|---|---|
| 카드 결제 | Visa/Mastercard → USDC 자동 변환 | ~3% | Phase 1 |
| Solana USDC 전송 | 사용자 지갑에서 직접 전송 | <$0.01 | Phase 1 |
| Phantom Wallet 연동 | 원클릭 결제 | <$0.01 | Phase 2 |
| TRC-20 USDT | Tron 네트워크 (레거시 지원) | ~1 USDT | Phase 3 |
💼 사용자 지갑 시스템
┌─────────────────────────────────────────────────────────────────┐
│ 사용자 지갑 구조 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 사용자 계정 (users 테이블) │ │
│ │ ├── user_id: 12345 │ │
│ │ ├── email: user@example.com │ │
│ │ ├── cc_balance: 23 CC (현재 보유 코인) │ │
│ │ └── solana_wallet_address: "ABC123..." │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 플랫폼 Solana 지갑 (수신 전용) │ │
│ │ ├── 주소: "PLATFORM_WALLET_ADDRESS..." │ │
│ │ ├── USDC 수신 → 자동 CC 변환 (1 USDC = 10 CC) │ │
│ │ └── 관리자만 출금 가능 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
📊 CC 거래 내역 관리
-- cc_transactions 테이블
CREATE TABLE cc_transactions (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
type VARCHAR(20) NOT NULL, -- 'purchase', 'spend', 'bonus', 'refund'
amount INTEGER NOT NULL, -- CC 금액 (양수: 획득, 음수: 사용)
balance_after INTEGER NOT NULL, -- 거래 후 잔액
reference_type VARCHAR(50), -- 'car_view', 'usdc_payment', 'card_payment', 'signup_bonus'
reference_id VARCHAR(100), -- 관련 ID (차량 ID, 결제 ID 등)
usdc_amount DECIMAL(12,2), -- USDC 결제 시 금액
tx_hash VARCHAR(100), -- Solana 트랜잭션 해시 (USDC 결제 시)
created_at TIMESTAMP DEFAULT NOW()
);
-- 차량 열람 기록
CREATE TABLE car_views (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
car_id INTEGER REFERENCES cars(id),
cc_spent INTEGER DEFAULT 1,
viewed_at TIMESTAMP DEFAULT NOW(),
UNIQUE(user_id, car_id) -- 동일 차량 중복 결제 방지
);
💰 가격 정책
CC 사용 기준: 1 CC = 10대 차량 추천 받을 수 있음
| 충전 금액 (USD) | 받는 CC | 추천 가능 차량 | 할인율 |
|---|---|---|---|
| $10 | 10 CC | 100대 | - |
| $27 | 30 CC | 300대 | 10% 할인 |
| $40 | 50 CC | 500대 | 20% 할인 |
※ 결제 수단: Stripe (Visa/Mastercard), 몽골 파트너 계좌 (러시아 사용자)
🔐 Solana USDC 지갑 통합 계획
Phase 1: 기본 지갑 시스템
1.1 플랫폼 수신 지갑 생성
┌─────────────────────────────────────────────────────────────────┐
│ 플랫폼 지갑 아키텍처 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [플랫폼 메인 지갑] │
│ ├── 주소: 공개 (사용자가 입금할 주소) │
│ ├── 비밀키: 서버에서 안전하게 관리 (환경변수/Vault) │
│ ├── 용도: USDC 수신 전용 │
│ └── 모니터링: Webhook으로 입금 감지 │
│ │
│ [관리자 출금 지갑] │
│ ├── 주소: 비공개 │
│ ├── 비밀키: 콜드 스토리지 / 하드웨어 지갑 │
│ └── 용도: 수익금 출금 │
│ │
└─────────────────────────────────────────────────────────────────┘
1.2 USDC 입금 감지 시스템
# Solana USDC 입금 감지 서비스
class SolanaPaymentService:
def __init__(self):
self.rpc_url = "https://api.mainnet-beta.solana.com"
self.usdc_mint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" # USDC SPL Token
self.platform_wallet = os.getenv("PLATFORM_WALLET_ADDRESS")
async def monitor_deposits(self):
"""Webhook 또는 폴링으로 입금 감지"""
# 1. 새 USDC 전송 감지
# 2. 메모 필드에서 user_id 추출
# 3. CC 크레딧 자동 지급
# 4. 트랜잭션 기록 저장
pass
async def credit_user(self, user_id: int, usdc_amount: float, tx_hash: str):
"""USDC 입금 시 CC 자동 지급"""
cc_amount = int(usdc_amount * 10) # 1 USDC = 10 CC
# DB에 CC 잔액 업데이트 및 거래 기록
pass
1.3 입금 프로세스 (사용자 관점)
1. 사용자가 "CC 충전하기" 클릭
2. 입금 안내 페이지 표시:
- 플랫폼 Solana 지갑 주소
- 메모(Memo): USER_12345 (사용자 식별용)
- QR 코드 (Solana Pay 호환)
3. 사용자가 Phantom/Solflare 등에서 USDC 전송
4. 서버가 입금 감지 (1-5초 내)
5. 자동으로 CC 잔액 증가
6. 푸시 알림 또는 화면 갱신
Phase 2: Phantom Wallet 연동 (원클릭 결제)
2.1 Solana Pay 통합
// Solana Pay를 이용한 원클릭 결제
import { createQR, encodeURL, TransactionRequestURL } from '@solana/pay';
const createPaymentRequest = (userId: string, usdcAmount: number) => {
const url: TransactionRequestURL = {
recipient: PLATFORM_WALLET,
amount: new BigNumber(usdcAmount),
splToken: USDC_MINT,
reference: generateReference(),
label: 'MongolCar CC 충전',
message: `${usdcAmount} USDC → ${usdcAmount * 10} CC`,
memo: `USER_${userId}`,
};
return encodeURL(url);
};
2.2 Phantom Wallet Connect
// Phantom 지갑 연결
const connectPhantom = async () => {
if (window.solana?.isPhantom) {
const response = await window.solana.connect();
const publicKey = response.publicKey.toString();
// 사용자 계정에 지갑 주소 연결
await api.linkWallet(publicKey);
}
};
// 원클릭 USDC 결제
const payWithPhantom = async (usdcAmount: number) => {
const transaction = await buildUSDCTransferTx(usdcAmount);
const signedTx = await window.solana.signTransaction(transaction);
const txHash = await connection.sendRawTransaction(signedTx.serialize());
return txHash;
};
Phase 3: 카드 결제 통합
3.1 결제 게이트웨이 옵션
| 서비스 | 특징 | 수수료 | 지원 통화 |
|---|---|---|---|
| Stripe | 글로벌, 안정적 | 2.9% + $0.30 | USD, EUR, KRW |
| MoonPay | 암호화폐 특화 | 4.5% | USDC 직접 구매 |
| Transak | 암호화폐 특화 | 3-5% | USDC 직접 구매 |
| KG이니시스 | 한국 결제 | 3.3% | KRW |
3.2 카드 → USDC 변환 플로우
1. 사용자가 충전 금액 선택 (예: $10)
2. Stripe/MoonPay 결제 창 열림
3. 카드 결제 완료
4. 서버에서 결제 확인
5. CC 잔액 자동 증가 (100 CC)
6. 완료 알림
📁 필요한 DB 스키마 추가
-- 사용자 테이블 확장
ALTER TABLE users ADD COLUMN cc_balance INTEGER DEFAULT 0;
ALTER TABLE users ADD COLUMN solana_wallet_address VARCHAR(44);
ALTER TABLE users ADD COLUMN linked_wallet_verified BOOLEAN DEFAULT FALSE;
-- USDC 결제 기록
CREATE TABLE usdc_payments (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
tx_hash VARCHAR(100) UNIQUE NOT NULL,
from_wallet VARCHAR(44) NOT NULL,
usdc_amount DECIMAL(12,6) NOT NULL,
cc_credited INTEGER NOT NULL,
bonus_cc INTEGER DEFAULT 0,
status VARCHAR(20) DEFAULT 'confirmed', -- pending, confirmed, failed
confirmed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
-- 카드 결제 기록
CREATE TABLE card_payments (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
payment_provider VARCHAR(20) NOT NULL, -- stripe, moonpay, transak
provider_payment_id VARCHAR(100) UNIQUE,
amount_usd DECIMAL(10,2) NOT NULL,
cc_credited INTEGER NOT NULL,
bonus_cc INTEGER DEFAULT 0,
status VARCHAR(20) DEFAULT 'pending',
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
🛠️ 구현 우선순위
| 순서 | 기능 | 예상 기간 | 설명 |
|---|---|---|---|
| 1 | CC 시스템 기본 구조 | 1주 | users 테이블 확장, cc_transactions 테이블, 잔액 관리 API |
| 2 | 차량 상세 열람 잠금 | 1주 | 사진 블러 처리, 상세 정보 잠금, CC 차감 로직 |
| 3 | 관리자 CC 수동 지급 | 2일 | 테스트/프로모션용 수동 지급 기능 |
| 4 | Solana 지갑 생성 | 3일 | 플랫폼 수신 지갑 생성, 주소 공개 |
| 5 | USDC 입금 감지 | 1주 | Solana RPC 모니터링, 자동 CC 지급 |
| 6 | Phantom Wallet 연동 | 1주 | 지갑 연결, Solana Pay QR 생성 |
| 7 | 카드 결제 (Stripe) | 1주 | 결제 위젯, 웹훅 처리 |
| 8 | MoonPay/Transak 통합 | 1주 | 암호화폐 직접 구매 옵션 |
🌐 다국어 지원
지원 언어
| 코드 | 언어 | 용도 |
|---|---|---|
mn |
몽골어 (Монгол) | 기본 언어 |
en |
영어 (English) | 국제 |
ru |
러시아어 (Русский) | 러시아, 중앙아시아 |
ko |
한국어 | 관리자, 딜러 |
번역 대상
- UI 텍스트 (정적)
- 차량 정보 (동적 - AI 번역)
- 채팅 메시지 (실시간 - Claude API)
- FAQ 응답 (사전 번역 + AI)
💬 AI 채팅 시스템
기능
- 실시간 번역: 몽골어 ↔ 한국어 양방향
- FAQ 자동 응답: 딜러 부재 시 AI가 응답
- 맥락 인식: 문의 중인 차량 정보 반영
FAQ 카테고리
| 카테고리 | 예시 질문 |
|---|---|
shipping |
배송 기간, 방법 |
payment |
결제 방법, 환불 |
document |
필요 서류, 관세 |
vehicle |
차량 상태, 옵션 |
general |
영업시간, 연락처 |
🔧 개발 단계별 작업
Phase 1: 인프라 구축 (1주)
목표: 서버 환경 설정 및 기본 인프라 구축
# 작업 목록
□ 우분투 서버 2대 OS 설치 및 기본 설정
□ PostgreSQL 16 설치 및 설정
□ Redis 7 설치
□ Nginx 설치 및 SSL 설정
□ Node.js 20 LTS 설치
□ PM2 설치
□ 방화벽 설정
□ SSH 키 기반 인증 설정
□ 서버 간 내부 네트워크 설정
□ 데이터베이스 스키마 생성
Claude Code 명령 예시:
서버 초기 설정 스크립트 작성해줘 (deploy/scripts/setup-server.sh)
- PostgreSQL 16 설치
- Redis 7 설치
- Nginx 설치
- Node.js 20 설치
- PM2 전역 설치
- 기본 보안 설정
Phase 2: Windows 에이전트 (2~3주) ⭐ 핵심
목표: 카모두 프로그램 자동화
# 작업 목록
□ 카모두 프로그램 UI 구조 분석 (Inspect.exe)
□ Python 에이전트 기본 구조 개발
□ 프로그램 연결 기능
□ 차량 검색 자동화
□ 검색 결과 추출
□ 상세 정보 추출
□ 이미지 추출 (20장)
□ API 클라이언트 연동
□ 에러 처리 및 재시도 로직
□ 로깅 시스템
□ Windows 서비스로 등록
Claude Code 명령 예시:
카모두 프로그램 자동화 에이전트 개발해줘 (agent/src/)
- pywinauto 기반
- 검색 조건: 제조사, 모델, 연식, 마일리지, 가격
- 결과 추출: 기본 정보 + 상세 정보 + 이미지 20장
- 비동기 처리 (asyncio)
- API 서버와 통신
Phase 3: 백엔드 API (2주)
목표: REST API 서버 개발
# 작업 목록
□ Express.js 프로젝트 설정
□ Prisma 스키마 및 마이그레이션
□ 인증 API (회원가입/로그인/JWT)
□ 차량 검색 API
□ 차량 상세 조회 API (포인트 차감)
□ 결제 API (카드/직접전송)
□ NOWPayments 웹훅 처리
□ 포인트 관리 API
□ 채팅 API
□ 에이전트 통신 API
□ Bull 큐 (검색 요청 처리)
□ 에러 핸들링
□ API 문서화 (Swagger)
Claude Code 명령 예시:
Express.js 백엔드 API 개발해줘 (apps/api/src/)
- TypeScript 기반
- Prisma ORM
- JWT 인증
- 차량 검색/조회 API
- 결제 API (NOWPayments 연동)
- Socket.io 채팅
Phase 4: 프론트엔드 (2주)
목표: Next.js 웹 애플리케이션 개발
# 작업 목록
□ Next.js 14 프로젝트 설정
□ 다국어 설정 (next-intl)
□ 레이아웃 및 공통 컴포넌트
□ 메인 페이지 (차량 검색 폼)
□ 검색 결과 페이지
□ 차량 상세 페이지
□ 이미지 갤러리
□ 회원가입/로그인 페이지
□ 마이페이지 (포인트, 열람기록)
□ 결제 페이지 (카드/직접전송)
□ QR 코드 표시
□ 반응형 디자인
□ 로딩/에러 상태 처리
Claude Code 명령 예시:
Next.js 14 프론트엔드 개발해줘 (apps/web/src/)
- App Router 사용
- TypeScript
- Tailwind CSS
- 다국어 (몽골어/영어/러시아어/한국어)
- 차량 검색/목록/상세 페이지
- 결제 모달 (USDT/USDC)
Phase 5: 채팅 + 결제 통합 (1~2주)
목표: 실시간 채팅 및 결제 시스템 완성
# 작업 목록
□ Socket.io 서버 설정
□ 채팅방 생성/입장
□ 실시간 메시지 전송
□ Claude API 번역 연동
□ FAQ 자동 응답 로직
□ 채팅 UI 컴포넌트
□ 결제 플로우 테스트
□ 웹훅 테스트
□ 포인트 충전 확인
Claude Code 명령 예시:
실시간 번역 채팅 시스템 개발해줘
- Socket.io 기반
- Claude API로 몽골어↔한국어 번역
- FAQ 자동 응답
- 채팅 UI 컴포넌트
Phase 6: 테스트 및 배포 (1주)
목표: 전체 시스템 테스트 및 프로덕션 배포
# 작업 목록
□ 단위 테스트 작성
□ 통합 테스트
□ E2E 테스트 (검색→결제→열람)
□ 성능 테스트
□ 보안 점검
□ SSL 인증서 적용
□ PM2 설정
□ Nginx 설정 최적화
□ 모니터링 설정
□ 백업 스크립트 설정
□ 프로덕션 배포
□ DNS 설정
Claude Code 명령 예시:
배포 스크립트 작성해줘 (deploy/)
- Nginx 설정
- PM2 ecosystem 설정
- systemd 서비스 파일
- 자동 배포 스크립트
⚙️ 환경 변수
웹서버 (.env)
# 서버
NODE_ENV=production
PORT=4000
FRONTEND_URL=https://your-domain.com
API_BASE_URL=https://your-domain.com/api
# 데이터베이스
DATABASE_URL=postgresql://user:password@db-server:5432/mongolcar
# Redis
REDIS_URL=redis://localhost:6379
# JWT
JWT_SECRET=your-jwt-secret-key
JWT_EXPIRES_IN=7d
# Claude API
CLAUDE_API_KEY=your-claude-api-key
# NOWPayments
NOWPAYMENTS_API_KEY=your-nowpayments-api-key
NOWPAYMENTS_IPN_SECRET=your-ipn-secret
# 에이전트
AGENT_API_KEY=your-agent-api-key
# 이미지 저장
IMAGE_STORAGE_PATH=/var/www/car-images
IMAGE_BASE_URL=https://your-domain.com/images
Windows 에이전트 (config.yaml)
api:
base_url: https://your-domain.com/api
api_key: your-agent-api-key
carmodoo:
process_name: GGKucar
search_timeout: 30
detail_timeout: 10
polling:
interval: 5 # 초
logging:
level: INFO
file: agent.log
🚀 Claude Code 개발 시작 명령
1. 프로젝트 초기화
몽골 중고차 수출 플랫폼 프로젝트 초기화해줘
- monorepo 구조 (apps/web, apps/api, packages/database, agent)
- TypeScript 설정
- ESLint, Prettier 설정
- 기본 README 작성
2. 데이터베이스 설정
PostgreSQL 데이터베이스 스키마 작성해줘 (database/schema.sql)
- 위 계획서의 테이블 구조 기반
- 인덱스 포함
- 초기 데이터 시드 파일도 작성
3. 백엔드 개발
Express.js API 서버 개발 시작해줘 (apps/api/)
- 먼저 프로젝트 구조 설정
- 인증 API부터 시작
- Prisma 스키마 작성
4. 프론트엔드 개발
Next.js 14 프론트엔드 개발 시작해줘 (apps/web/)
- App Router 사용
- 다국어 설정 (next-intl)
- 메인 페이지 (차량 검색) 먼저 개발
5. 에이전트 개발
카모두 자동화 에이전트 개발해줘 (agent/)
- Python 프로젝트 구조 설정
- pywinauto 기반 UI 자동화
- 검색 및 데이터 추출 기능
📝 참고사항
카모두 프로그램 정보
- 개발사: (주)이엠아이앤씨
- 용도: 경기도자동차매매사업조합 딜러 전용
- 기술: .NET Assembly (WinForms/WPF 추정)
- 파일: GGKucar.exe (64KB, 런처)
주요 외부 서비스
| 서비스 | 용도 | 링크 |
|---|---|---|
| NOWPayments | 암호화폐 결제 | https://nowpayments.io |
| Anthropic Claude | AI 번역/챗봇 | https://anthropic.com |
| ExchangeRate API | 환율 조회 | https://exchangerate-api.com |
📞 문의사항
대표 연락처 (모든 딜러 연락처 통일)
- 담당자: DamonHong
- 전화: +82-10-3331-5258
개발 진행 중 추가 정보가 필요한 사항:
- 카모두 프로그램 UI 스크린샷 - 자동화 개발에 필요
- 도메인 및 SSL 인증서 - 배포 시 필요
- NOWPayments 계정 - 결제 테스트에 필요
- Claude API 키 - 번역/챗봇 개발에 필요
🔍 카모두 API 분석 (Reverse Engineering)
개요
Fiddler를 통해 캡처한 카모두 프로그램(GGKucar.exe)의 네트워크 트래픽 분석 결과입니다.
기본 정보
| 항목 | 내용 |
|---|---|
| 도메인 | dealer.carmodoo.com (메인), ck.carmodoo.com (성능점검) |
| 프로토콜 | HTTPS (TLS 1.2/1.3) |
| 인증 방식 | 세션 기반 (PHPSESSID 쿠키) |
| 서버 | Apache/2.4.6 (CentOS), PHP/5.4.16 |
| 인코딩 | EUC-KR |
인증 API
1. 로그인
POST https://dealer.carmodoo.com/member/login_ok.html
Content-Type: application/x-www-form-urlencoded
prevURL=&id={전화번호}&passwd={비밀번호}&idSave=Y&button=LOGIN
응답:
<script type='text/javascript'>
try { window.external.GoMain(); } catch(ex1) {}
try { cAPI.goMain(); } catch(ex1) {}
</script>
인증 쿠키: PHPSESSID, idSave
2. 세션 유지
POST https://dealer.carmodoo.com/common/ajax/sessionHold.html
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID={세션ID}
차량 데이터 API
1. 제조사/모델 코드 조회 (AutoDBCode.html)
초기 데이터 로드:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarInit&ctl=car
제조사별 모델 목록:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarModelInit&ctl=car&company={제조사ID}
모델별 세부 모델:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarModel&ctl=car&company={제조사ID}&c_nameInit={모델ID}
세부 모델별 연식:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarYear&ctl=car&c_name={모델코드}
시리즈 조회:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarSeries&ctl=car&c_name={모델코드}
세부사양 조회:
GET https://dealer.carmodoo.com/common/ajax/AutoDBCode.html?mode=getCarSdetail&ctl=car&series={시리즈코드}
응답 형식 (XML):
<?xml version="1.0" encoding="EUC-KR"?>
<root>
<ctl>car</ctl>
<item>
<key>5</key>
<name><![CDATA[현대]]></name>
<cho>1</cho>
<field>c_bmNo</field>
</item>
...
</root>
주요 제조사 코드:
| 코드 | 제조사 |
|---|---|
| 5 | 현대 |
| 2 | 기아 |
| 1 | 쌍용 |
| 3 | 르노 |
| 67 | BMW |
| 68 | 벤츠 |
| 70 | 아우디 |
2. 차량 목록 조회 (AutoDBProc.html)
관심 차량 조회:
GET https://dealer.carmodoo.com/common/ajax/AutoDBProc.html?mode=getInterest&iStr={차량번호들!구분}
예시: iStr=6290623!6290630!6290644!...
응답: Y| (관심등록 여부)
관심 차량 추가:
POST https://dealer.carmodoo.com/common/ajax/AutoDBProc.html
Content-Type: application/x-www-form-urlencoded
mode=addInterest&c_no={차량번호}&memo={메모}
관심 차량 삭제:
GET https://dealer.carmodoo.com/common/ajax/AutoDBProc.html?mode=delInterest&c_no={차량번호}
3. 차량 상세 조회 (AutoDB.html)
GET https://dealer.carmodoo.com/common/ajax/AutoDB.html?mode=view&key={암호화된키}
key 파라미터: Base64 인코딩된 암호화 문자열
예시: U1VqWHNxc2FOaDY0LzAyYUtaRDdibTdQZnc4cXZ4dXh6czVyelJjdHRHcz0
응답 형식 (XML):
<cars>
<no>6320434</no>
<c_bgNo>1</c_bgNo>
<c_boNo>2828</c_boNo>
<carName>2020년형 기아 K5 DL3 2.0 가솔린</carName>
<c_subject>차량 제목</c_subject>
<c_gearbox>오토</c_gearbox>
<c_fuel>가솔린</c_fuel>
<c_mileage>45000</c_mileage>
<c_colorName>흰색</c_colorName>
<c_carNum>12가3456</c_carNum>
<dPrice>25000000</dPrice>
<YM>2020년 06월</YM>
<c_year>2020</c_year>
<c_month>6</c_month>
<c_displacement>1998</c_displacement>
<c_seize>0</c_seize>
<c_collateral>0</c_collateral>
<c_memoStr>메모 내용</c_memoStr>
<c_options>1#5#12#34#...</c_options>
<mainImage>/data/__carPhoto/006/320/434/cmcar_0.jpg</mainImage>
<strPhotos>/data/__carPhoto/006/320/434/cmcar_0.jpg|cmcar_1.jpg|...</strPhotos>
<strPhotosThum>썸네일 경로들</strPhotosThum>
<c_checkNum>123456789</c_checkNum>
<c_checkUrl>성능점검 URL</c_checkUrl>
<c_checkGubun>ggkucar</c_checkGubun>
<d_name>딜러명</d_name>
<d_hp>010-1234-5678</d_hp>
<s_name>매매상사명</s_name>
<s_tel>031-123-4567</s_tel>
</cars>
4. 차량 상세 페이지 (HTML)
GET http://dealer.carmodoo.com/car/dealerCarView.html?key={암호화된키}&tabStart=1
이미지 URL 패턴
원본 이미지:
http://dealer.carmodoo.com/data/__carPhoto/{3자리}/{3자리}/{3자리}/cmcar_{순번}.jpg
썸네일 이미지:
http://dealer.carmodoo.com/data/__carPhoto/{3자리}/{3자리}/{3자리}/cmcar_{순번}.jpg__THUM
URL 구조 설명:
- 차량번호 6320434의 경우:
/006/320/434/ - 첫 번째 이미지:
cmcar_0.jpg - 두 번째 이미지:
cmcar_1.jpg
성능점검 API
GET https://ck.carmodoo.com/carCheck/carmodooPrint.do?checkNum={성능점검번호}
시세 조회 API
GET https://dealer.carmodoo.com/common/ajax/SiseDB.html?mode=getSiseData&ctl={구분}&company={제조사코드}&c_name={모델코드}
Python 에이전트 구현 참고
import aiohttp
import asyncio
from urllib.parse import urlencode
class CarmodooClient:
BASE_URL = "https://dealer.carmodoo.com"
def __init__(self):
self.session = None
self.cookies = {}
async def login(self, user_id: str, password: str) -> bool:
"""로그인 및 세션 쿠키 획득"""
async with aiohttp.ClientSession() as session:
data = {
'prevURL': '',
'id': user_id,
'passwd': password,
'idSave': 'Y',
'button': 'LOGIN'
}
async with session.post(
f"{self.BASE_URL}/member/login_ok.html",
data=data,
headers={'Content-Type': 'application/x-www-form-urlencoded'}
) as resp:
if resp.status == 200:
self.cookies = {c.key: c.value for c in session.cookie_jar}
return 'goMain' in await resp.text()
return False
async def get_car_makers(self) -> list:
"""제조사 목록 조회"""
params = {'mode': 'getCarInit', 'ctl': 'car'}
async with aiohttp.ClientSession(cookies=self.cookies) as session:
async with session.get(
f"{self.BASE_URL}/common/ajax/AutoDBCode.html",
params=params
) as resp:
# XML 파싱 후 반환
pass
async def get_car_detail(self, key: str) -> dict:
"""차량 상세 정보 조회"""
params = {'mode': 'view', 'key': key}
async with aiohttp.ClientSession(cookies=self.cookies) as session:
async with session.get(
f"{self.BASE_URL}/common/ajax/AutoDB.html",
params=params
) as resp:
# XML 파싱 후 반환
pass
async def download_image(self, car_no: int, index: int) -> bytes:
"""차량 이미지 다운로드"""
# 차량번호를 3자리씩 분할
path = f"{car_no:09d}"
folder = f"{path[0:3]}/{path[3:6]}/{path[6:9]}"
url = f"{self.BASE_URL}/data/__carPhoto/{folder}/cmcar_{index}.jpg"
async with aiohttp.ClientSession(cookies=self.cookies) as session:
async with session.get(url) as resp:
if resp.status == 200:
return await resp.read()
return None
주요 데이터 필드 매핑
| carmodoo 필드 | 의미 | DB 필드 |
|---|---|---|
| c_no / no | 차량 고유번호 | source_id |
| carName | 차량명 (풀네임) | - |
| c_bmNo | 제조사 코드 | make |
| c_boNo | 모델 코드 | model |
| c_year | 연식 | year |
| c_mileage | 주행거리 | mileage |
| dPrice | 판매가격 | price |
| c_fuel | 연료 | fuel_type |
| c_gearbox | 변속기 | transmission |
| c_colorName | 색상 | color |
| c_displacement | 배기량 | engine_cc |
| c_options | 옵션 (#구분) | options |
| c_checkNum | 성능점검번호 | inspection_data |
| c_seize | 압류 건수 | - |
| c_collateral | 저당 건수 | - |
보안 고려사항
- HTTPS 필수: 모든 요청은 HTTPS로 전송
- 세션 관리: PHPSESSID 쿠키 유지 필요
- Rate Limiting: 과도한 요청 시 차단 가능성
- 인코딩: EUC-KR → UTF-8 변환 필요
구현 완료 기능 (2024-12-25)
상세사양조회 시스템
차량번호 기반으로 AUTOBEGINS 서비스에서 상세사양을 조회하는 시스템이 구현되었습니다.
주요 기능:
- Playwright 브라우저 자동화로 Carmodoo 딜러 포탈의 AUTOBEGINS iframe 접근
- 차량번호 입력 → 상세사양 파싱 → DB 저장
- 배너 등록(import) 시 자동 사양 조회
조회 가능 정보:
| 카테고리 | 정보 |
|---|---|
| 기본 정보 | 제조사, 모델명, 등급, 연식 |
| 엔진/구동 | 배기량, 연료, 변속기, 구동방식 |
| 성능 | 최대출력, 최대토크, 연비 |
| 차체 | 차체형식, 도어수, 승차정원, 전장/전폭/전고/휠베이스 |
| 가격 | 출고가, 기본가, 옵션가 |
관련 파일:
backend/app/services/spec_service.py- 사양 조회 로직backend/app/models/car_specification.py- CarSpecification 모델backend/app/api/carmodoo.py- API 엔드포인트
딜러 상세설명
Carmodoo 상세페이지에서 딜러가 작성한 설명을 추출하여 저장합니다.
추출 방식 (2024-12-25 업데이트):
- 차량 검색 결과에서
dealerCarviewPopup('암호화키')JavaScript 호출 패턴을 파싱하여car_key추출 dealerCarView.html?key=<car_key>&tabStart=1URL로 딜러 상세페이지 조회<div class="carViewMemoWrap"><h3>상세설명</h3><div class="memo">...</div></div>HTML 구조에서 설명 추출cars.dealer_description컬럼에 저장
주의: 이전의 carPopView.html은 더 이상 작동하지 않음 (404 반환)
관련 코드:
carmodoo.py: _parse_car_list_html()- car_key 추출 (dealerCarviewPopup 패턴)carmodoo.py: get_car_detail()- dealerCarView.html에서 상세설명 파싱- 차량 상세 페이지에서 amber 배경으로 표시 (로그인 사용자만)
Quote Request 1CC 결제
차량 추천 요청 시 1 CC가 차감되도록 구현되었습니다.
흐름:
- 사용자가
/vehicle-request페이지에서 조건 입력 - 제출 시 CC 잔액 확인 (1 CC 필요)
- 잔액 부족 시
/cc충전 페이지로 안내 - CC 차감 후 요청 생성
관련 파일:
backend/app/api/vehicle_requests.py- CC 차감 로직backend/app/models/vehicle_request.py- cc_paid 컬럼frontend/src/app/vehicle-request/page.tsx- UI (CC 잔액 표시, 비용 안내)
마지막 업데이트: 2024년 12월 25일
변경 이력
| 날짜 | 변경 내용 |
|---|---|
| 2024-12-25 | 딜러 상세설명 추출 방식 변경 (carPopView.html → dealerCarView.html + car_key) |
| 2024-12-25 | car_key 필드 추가 (CarmodooSearchResultItem, AdminSearchResultItem, ImportCarRequest) |
| 2024-12-25 | 프론트엔드 api.ts, hero-banners/page.tsx에 car_key 연동 |