- 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>
752 lines
29 KiB
Markdown
752 lines
29 KiB
Markdown
# AutonetSellCar 개발 계획서
|
|
## 몽골 중고차 수출 플랫폼 (www.autonetsellcar.com)
|
|
### 작성일: 2025-12-06
|
|
|
|
---
|
|
|
|
## 1. 프로젝트 개요
|
|
|
|
### 서비스 소개
|
|
**AutonetSellCar**는 한국 중고차를 몽골 바이어에게 수출하는 B2C/B2B 플랫폼입니다.
|
|
카모두(Carmodoo) 딜러 시스템에서 차량 데이터를 자동 수집하여 몽골 바이어에게 제공합니다.
|
|
|
|
### 타겟 사용자
|
|
| 사용자 유형 | 설명 | 인증 방식 |
|
|
|------------|------|----------|
|
|
| 몽골 일반 바이어 | 개인 차량 구매자 | 이메일/Facebook/Google |
|
|
| 몽골 비즈니스 바이어 | 대량 구매/딜러 | Google OAuth + 사업자 인증 |
|
|
| 중계자 (Agent) | 한-몽 중개인 | 신분증 인증 필수 |
|
|
| 관리자 | 시스템 관리 | 이메일/비밀번호 + 2FA |
|
|
|
|
---
|
|
|
|
## 2. 현재 구현 상태
|
|
|
|
### 완료된 기능
|
|
- [x] FastAPI Backend 기본 구조
|
|
- [x] 차량 목록/상세 API
|
|
- [x] 기본 이메일/비밀번호 인증
|
|
- [x] Next.js Frontend 기본 구조
|
|
- [x] 차량 목록/상세 페이지
|
|
- [x] SQLite 로컬 개발 환경
|
|
- [x] Carmodoo Agent (차량 데이터 수집기)
|
|
|
|
### 미구현 기능
|
|
- [ ] 소셜 로그인 (Facebook, Google OAuth)
|
|
- [ ] 몽골 SMS OTP 인증
|
|
- [ ] 중계자 신분증 인증
|
|
- [ ] 메인 히어로 슬라이더 (영화 필름 스타일)
|
|
- [ ] 관리자 대시보드
|
|
- [ ] 배너/슬라이더 관리 기능
|
|
|
|
---
|
|
|
|
## 3. 기술 스택
|
|
|
|
### 3.1 Frontend
|
|
| 기술 | 버전 | 용도 |
|
|
|------|------|------|
|
|
| Next.js | 14.1.0 | React 프레임워크 (App Router) |
|
|
| TypeScript | 5.3+ | 타입 안정성 |
|
|
| Tailwind CSS | 3.4+ | 스타일링 |
|
|
| Axios | 1.6+ | HTTP 클라이언트 |
|
|
| Zustand | 4.5+ | 상태 관리 |
|
|
| React Hook Form | 7.49+ | 폼 관리 |
|
|
| Framer Motion | 11.x | 애니메이션 (슬라이더용) |
|
|
| next-auth | 4.x | 소셜 로그인 통합 |
|
|
|
|
### 3.2 Backend
|
|
| 기술 | 버전 | 용도 |
|
|
|------|------|------|
|
|
| FastAPI | 0.109+ | Python 웹 프레임워크 |
|
|
| SQLAlchemy | 2.0+ | ORM |
|
|
| PostgreSQL | 16 | 프로덕션 DB (Server1) |
|
|
| SQLite | - | 로컬 개발용 DB |
|
|
| Redis | 7 | 세션/캐시 (Server1) |
|
|
| Pydantic | 2.x | 데이터 검증 |
|
|
| python-jose | - | JWT 토큰 |
|
|
| passlib | - | 비밀번호 해싱 |
|
|
| httpx | - | 비동기 HTTP 클라이언트 |
|
|
| aiofiles | - | 비동기 파일 처리 |
|
|
|
|
### 3.3 인증 서비스 (외부)
|
|
| 서비스 | 용도 | 비고 |
|
|
|--------|------|------|
|
|
| Facebook OAuth 2.0 | 소셜 로그인 | PKCE 방식 |
|
|
| Google OAuth 2.0 | 소셜 로그인 | 비즈니스용 |
|
|
| Twilio / MessageBird | SMS OTP | 몽골 번호 지원 확인 필요 |
|
|
| AWS S3 / Cloudflare R2 | 이미지 저장 | 선택 |
|
|
|
|
### 3.4 인프라
|
|
| 서버 | IP | 역할 |
|
|
|------|-----|------|
|
|
| Server1 | 192.168.0.201 | PostgreSQL, Redis, Nginx Proxy Manager |
|
|
| Server2 | 192.168.0.202 | AutonetSellCar (Backend:8000, Frontend:3000) |
|
|
| Server3 | 192.168.0.203 | Grantech.kr, Cylinx.kr |
|
|
|
|
---
|
|
|
|
## 4. 인증 시스템 상세 설계
|
|
|
|
### 4.0 보안 아키텍처 개요
|
|
|
|
중고차 거래 플랫폼의 특성상 **보안이 매우 중요**합니다. 고액 거래가 이루어지므로 이중 토큰 전략을 적용합니다.
|
|
|
|
#### 최종 권장 아키텍처
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 몽골 중고차 사이트 인증 │
|
|
├─────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
│ │ Facebook OAuth │ │ 이메일/비밀번호 │ │
|
|
│ │ + PKCE │ │ (대체 수단) │ │
|
|
│ └────────┬────────┘ └────────┬────────┘ │
|
|
│ │ │ │
|
|
│ └──────────┬───────────┘ │
|
|
│ ▼ │
|
|
│ ┌─────────────────────┐ │
|
|
│ │ 자체 JWT 발급 │ │
|
|
│ │ (Access + Refresh) │ │
|
|
│ └──────────┬──────────┘ │
|
|
│ │ │
|
|
│ ┌──────────┴──────────┐ │
|
|
│ ▼ ▼ │
|
|
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
│ │ Access Token │ │ Refresh Token │ │
|
|
│ │ (메모리/State) │ │ (HttpOnly Cookie)│ │
|
|
│ │ 15분 수명 │ │ 7일 수명 │ │
|
|
│ └─────────────────┘ └─────────────────┘ │
|
|
│ │
|
|
│ + 판매자 등록 시: 휴대폰 인증 추가 │
|
|
│ + 고액 거래 시: 2FA 고려 │
|
|
│ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
#### 이중 토큰 전략 (Dual Token Strategy)
|
|
```
|
|
┌─────────────────────────────────────────────────────────┐
|
|
│ Access Token │
|
|
│ - 수명: 15분 (기본) ~ 1시간 (최대) │
|
|
│ - 용도: API 요청 인증 │
|
|
│ - 저장: 메모리 (더 안전) 또는 Zustand State │
|
|
│ - 특징: 짧은 수명으로 탈취 시 피해 최소화 │
|
|
├─────────────────────────────────────────────────────────┤
|
|
│ Refresh Token │
|
|
│ - 수명: 7일 (기본) ~ 30일 (최대) │
|
|
│ - 용도: Access Token 재발급 │
|
|
│ - 저장: HttpOnly Cookie (XSS 방지) │
|
|
│ - 특징: JavaScript 접근 불가, CSRF 보호 필요 │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
#### 토큰 갱신 플로우
|
|
```
|
|
┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
│ Frontend │ │ Backend │ │ Database │
|
|
└────┬─────┘ └────┬─────┘ └────┬─────┘
|
|
│ │ │
|
|
│ API 요청 (Access Token 만료) │
|
|
│──────────────▶│ │
|
|
│ │ │
|
|
│ 401 Unauthorized │
|
|
│◀──────────────│ │
|
|
│ │ │
|
|
│ /auth/refresh (Refresh Token in Cookie)
|
|
│──────────────▶│ │
|
|
│ │ 토큰 검증 │
|
|
│ │──────────────▶│
|
|
│ │◀──────────────│
|
|
│ │ │
|
|
│ 새 Access Token + 새 Refresh Token
|
|
│◀──────────────│ │
|
|
│ │ │
|
|
│ 원래 API 재요청 │
|
|
│──────────────▶│ │
|
|
└───────────────┴───────────────┘
|
|
```
|
|
|
|
### 4.1 인증 방식 목록
|
|
|
|
#### 1) 이메일/비밀번호 기본 인증
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Frontend │───▶│ Backend │───▶│ Database │
|
|
│ Login Form │ │ /auth/login │ │ users │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
- bcrypt 해싱 (비밀번호 암호화)
|
|
- 이중 토큰 (Access + Refresh) 발급
|
|
- Access Token: 15분 수명
|
|
- Refresh Token: 7일 수명, HttpOnly Cookie 저장
|
|
|
|
**비밀번호 정책:**
|
|
- 최소 8자 이상
|
|
- 대문자, 소문자, 숫자, 특수문자 포함 권장
|
|
- bcrypt cost factor: 12 (보안 강화)
|
|
|
|
#### 2) Facebook OAuth 2.0 + PKCE + JWT
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Frontend │───▶│ Facebook │───▶│ Backend │───▶│ 자체 JWT │
|
|
│ FB Button │ │ OAuth+PKCE │ │ /auth/fb/cb │ │ 토큰 발급 │
|
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
- **PKCE (Proof Key for Code Exchange)** 필수 적용
|
|
- Facebook 인증 후 → 자체 JWT(Access + Refresh) 발급
|
|
- 몽골에서 Facebook 사용률 높음
|
|
- 프로필 정보: email, name, profile_picture
|
|
|
|
**PKCE 플로우:**
|
|
```
|
|
1. Frontend: code_verifier (랜덤 문자열) 생성
|
|
2. Frontend: code_challenge = SHA256(code_verifier) 계산
|
|
3. Frontend → Facebook: code_challenge 전송
|
|
4. Facebook → Frontend: authorization_code 반환
|
|
5. Frontend → Backend: authorization_code + code_verifier 전송
|
|
6. Backend → Facebook: code_verifier로 토큰 교환
|
|
7. Backend: 자체 JWT(Access + Refresh) 발급
|
|
```
|
|
|
|
**필요 설정:**
|
|
```env
|
|
FACEBOOK_APP_ID=your_app_id
|
|
FACEBOOK_APP_SECRET=your_app_secret
|
|
FACEBOOK_REDIRECT_URI=https://autonetsellcar.com/api/auth/facebook/callback
|
|
```
|
|
|
|
#### 3) Google OAuth 2.0 + JWT
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Frontend │───▶│ Google │───▶│ Backend │───▶│ 자체 JWT │
|
|
│ Google Btn │ │ OAuth Server│ │ /auth/google│ │ 토큰 발급 │
|
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
- 비즈니스 바이어/외국인 용
|
|
- Google Workspace 계정 연동 가능
|
|
- Google 인증 후 → 자체 JWT(Access + Refresh) 발급
|
|
|
|
**필요 설정:**
|
|
```env
|
|
GOOGLE_CLIENT_ID=your_client_id
|
|
GOOGLE_CLIENT_SECRET=your_client_secret
|
|
GOOGLE_REDIRECT_URI=https://autonetsellcar.com/api/auth/google/callback
|
|
```
|
|
|
|
#### 4) 몽골 휴대폰 SMS OTP 인증
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Frontend │───▶│ Backend │───▶│ SMS Gateway │───▶│ User Phone │
|
|
│ Phone Input │ │ /auth/sms │ │ Twilio │ │ +976 xxxx │
|
|
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
- 몽골 휴대폰 번호 형식: +976 XXXX XXXX
|
|
- OTP 6자리, 유효시간 5분
|
|
- Redis에 OTP 임시 저장
|
|
|
|
**SMS 게이트웨이 옵션:**
|
|
| 서비스 | 몽골 지원 | 가격 | 비고 |
|
|
|--------|----------|------|------|
|
|
| Twilio | O | ~$0.05/SMS | 글로벌 |
|
|
| MessageBird | O | ~$0.04/SMS | 유럽 기반 |
|
|
| Vonage | O | ~$0.05/SMS | 글로벌 |
|
|
| 몽골 로컬 | 확인 필요 | - | 직접 연동 |
|
|
|
|
**필요 설정:**
|
|
```env
|
|
TWILIO_ACCOUNT_SID=your_account_sid
|
|
TWILIO_AUTH_TOKEN=your_auth_token
|
|
TWILIO_PHONE_NUMBER=+1234567890
|
|
```
|
|
|
|
#### 5) 중계자 신분증 인증
|
|
```
|
|
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
│ Frontend │───▶│ Backend │───▶│ Admin │
|
|
│ ID Upload │ │ /auth/verify│ │ Manual OK │
|
|
└─────────────┘ └─────────────┘ └─────────────┘
|
|
```
|
|
- 신분증 이미지 업로드 (앞/뒤)
|
|
- 관리자 수동 승인
|
|
- 승인 후 "중계자" 역할 부여
|
|
|
|
### 4.2 사용자 역할 (Role)
|
|
| 역할 | 권한 | 비고 |
|
|
|------|------|------|
|
|
| buyer | 차량 조회, 문의하기 | 기본 |
|
|
| business | buyer + 대량 견적 요청 | 사업자 인증 |
|
|
| agent | business + 중계 수수료 관리 | 신분증 인증 |
|
|
| admin | 모든 권한 | 시스템 관리 |
|
|
|
|
### 4.3 데이터베이스 스키마 (인증 관련)
|
|
|
|
```sql
|
|
-- 사용자 테이블 (확장)
|
|
ALTER TABLE users ADD COLUMN auth_provider VARCHAR(20) DEFAULT 'email';
|
|
-- 'email', 'facebook', 'google', 'phone'
|
|
|
|
ALTER TABLE users ADD COLUMN provider_id VARCHAR(100);
|
|
-- 소셜 로그인 시 provider의 user_id
|
|
|
|
ALTER TABLE users ADD COLUMN phone_number VARCHAR(20);
|
|
ALTER TABLE users ADD COLUMN phone_verified BOOLEAN DEFAULT FALSE;
|
|
|
|
ALTER TABLE users ADD COLUMN role VARCHAR(20) DEFAULT 'buyer';
|
|
-- 'buyer', 'business', 'agent', 'admin'
|
|
|
|
ALTER TABLE users ADD COLUMN id_card_front VARCHAR(500);
|
|
ALTER TABLE users ADD COLUMN id_card_back VARCHAR(500);
|
|
ALTER TABLE users ADD COLUMN verification_status VARCHAR(20) DEFAULT 'none';
|
|
-- 'none', 'pending', 'approved', 'rejected'
|
|
|
|
-- SMS OTP 테이블 (또는 Redis 사용)
|
|
CREATE TABLE sms_otps (
|
|
id SERIAL PRIMARY KEY,
|
|
phone_number VARCHAR(20) NOT NULL,
|
|
otp_code VARCHAR(6) NOT NULL,
|
|
expires_at TIMESTAMP NOT NULL,
|
|
is_used BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 5. 메인 히어로 슬라이더 설계
|
|
|
|
### 5.1 요구사항
|
|
- **이미지 크기**: 500x300 픽셀 (중고차 사진)
|
|
- **애니메이션**: 영화 필름처럼 한 칸씩 연속 슬라이드
|
|
- **속도**: 3-5초마다 자동 전환
|
|
- **관리자 기능**: 배너 이미지 CRUD
|
|
|
|
### 5.2 UI/UX 컨셉
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
│ │ 🚗 Car1 │ │ 🚗 Car2 │ │ 🚗 Car3 │ │ 🚗 Car4 │ ───────▶ │
|
|
│ │ 500x300 │ │ 500x300 │ │ 500x300 │ │ 500x300 │ │
|
|
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
|
│ │
|
|
│ Premium Korean Used Cars │
|
|
│ Quality vehicles exported to Mongolia at competitive prices │
|
|
│ │
|
|
│ [ Browse All Cars ] │
|
|
└────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
### 5.3 기술 구현
|
|
|
|
#### Frontend 컴포넌트 (FilmStripSlider.tsx)
|
|
```typescript
|
|
// Framer Motion 기반 무한 슬라이드
|
|
const FilmStripSlider = ({ images }: { images: BannerImage[] }) => {
|
|
// 무한 루프를 위한 이미지 복제
|
|
const duplicatedImages = [...images, ...images];
|
|
|
|
return (
|
|
<motion.div
|
|
animate={{ x: [0, -totalWidth] }}
|
|
transition={{
|
|
x: {
|
|
repeat: Infinity,
|
|
repeatType: "loop",
|
|
duration: images.length * 3, // 이미지당 3초
|
|
ease: "linear"
|
|
}
|
|
}}
|
|
>
|
|
{duplicatedImages.map((img, i) => (
|
|
<div key={i} className="w-[500px] h-[300px]">
|
|
<Image src={img.url} alt={img.title} fill />
|
|
</div>
|
|
))}
|
|
</motion.div>
|
|
);
|
|
};
|
|
```
|
|
|
|
### 5.4 배너 관리 API
|
|
|
|
#### Backend Endpoints
|
|
| Method | Endpoint | 설명 |
|
|
|--------|----------|------|
|
|
| GET | /api/hero-banners | 활성 배너 목록 (Public) |
|
|
| GET | /api/hero-banners/settings | 슬라이더 설정 |
|
|
| GET | /api/admin/hero-banners | 모든 배너 (Admin) |
|
|
| POST | /api/admin/hero-banners | 배너 생성 |
|
|
| PUT | /api/admin/hero-banners/{id} | 배너 수정 |
|
|
| DELETE | /api/admin/hero-banners/{id} | 배너 삭제 |
|
|
| POST | /api/admin/hero-banners/upload | 이미지 업로드 |
|
|
| PUT | /api/admin/hero-banners/settings | 설정 변경 |
|
|
|
|
#### 데이터베이스 스키마
|
|
```sql
|
|
-- 히어로 배너 설정
|
|
CREATE TABLE hero_banner_settings (
|
|
id SERIAL PRIMARY KEY,
|
|
slide_interval INTEGER DEFAULT 3000, -- ms
|
|
animation_type VARCHAR(20) DEFAULT 'film-strip', -- 'film-strip', 'fade', 'slide'
|
|
image_width INTEGER DEFAULT 500,
|
|
image_height INTEGER DEFAULT 300,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- 히어로 배너 이미지
|
|
CREATE TABLE hero_banners (
|
|
id SERIAL PRIMARY KEY,
|
|
title_ko VARCHAR(100),
|
|
title_en VARCHAR(100),
|
|
title_mn VARCHAR(100), -- 몽골어
|
|
image_url VARCHAR(500) NOT NULL,
|
|
link_url VARCHAR(500), -- 클릭 시 이동 URL (선택)
|
|
car_id INTEGER REFERENCES cars(id), -- 연결된 차량 (선택)
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
display_order INTEGER DEFAULT 0,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 6. 관리자 페이지 설계
|
|
|
|
### 6.1 관리자 메뉴 구조
|
|
```
|
|
/admin
|
|
├── /dashboard # 대시보드 (통계, 현황)
|
|
├── /hero-banners # 히어로 배너 관리
|
|
├── /cars # 차량 관리
|
|
│ ├── /list # 차량 목록
|
|
│ ├── /sync # 카모두 동기화
|
|
│ └── /makers # 제조사/모델 관리
|
|
├── /users # 사용자 관리
|
|
│ ├── /list # 사용자 목록
|
|
│ └── /verifications # 신분증 인증 대기
|
|
├── /inquiries # 문의 관리
|
|
├── /settings # 사이트 설정
|
|
└── /profile # 관리자 프로필
|
|
```
|
|
|
|
### 6.2 대시보드 통계
|
|
| 항목 | 설명 |
|
|
|------|------|
|
|
| 총 차량 수 | 등록된 차량 수 |
|
|
| 오늘 방문자 | 일일 방문자 통계 |
|
|
| 신규 문의 | 미읽음 문의 수 |
|
|
| 신규 가입 | 오늘 가입자 수 |
|
|
| 인증 대기 | 신분증 인증 대기 건수 |
|
|
|
|
### 6.3 Grantech.kr 참고 구조
|
|
Grantech.kr에서 참고할 관리자 기능:
|
|
- 배너 관리 (`/admin/banners`)
|
|
- 프로젝트 관리 (`/admin/projects`)
|
|
- 문의 관리 (`/admin/contact`)
|
|
- 알림 관리 (`/admin/notifications`)
|
|
|
|
---
|
|
|
|
## 7. 개발 일정 (작업 순서)
|
|
|
|
### Phase 1: 메인 히어로 슬라이더 (우선순위 높음)
|
|
| 작업 | 상세 | 예상 |
|
|
|------|------|------|
|
|
| 1-1 | Backend: hero_banners 모델/스키마 생성 | - |
|
|
| 1-2 | Backend: hero_banners API 구현 | - |
|
|
| 1-3 | Frontend: FilmStripSlider 컴포넌트 | - |
|
|
| 1-4 | Frontend: 메인 페이지 히어로 섹션 적용 | - |
|
|
| 1-5 | Admin: 히어로 배너 관리 페이지 | - |
|
|
|
|
### Phase 2: 관리자 페이지 기본
|
|
| 작업 | 상세 | 예상 |
|
|
|------|------|------|
|
|
| 2-1 | Admin: 레이아웃 및 네비게이션 | - |
|
|
| 2-2 | Admin: 로그인 페이지 | - |
|
|
| 2-3 | Admin: 대시보드 | - |
|
|
| 2-4 | Admin: 차량 관리 페이지 | - |
|
|
|
|
### Phase 3: 소셜 로그인
|
|
| 작업 | 상세 | 예상 |
|
|
|------|------|------|
|
|
| 3-1 | Facebook OAuth 설정 (Developer Console) | - |
|
|
| 3-2 | Google OAuth 설정 (Cloud Console) | - |
|
|
| 3-3 | Backend: OAuth 엔드포인트 구현 | - |
|
|
| 3-4 | Frontend: 소셜 로그인 버튼 | - |
|
|
| 3-5 | 사용자 DB 스키마 확장 | - |
|
|
|
|
### Phase 4: SMS OTP 인증
|
|
| 작업 | 상세 | 예상 |
|
|
|------|------|------|
|
|
| 4-1 | SMS 게이트웨이 선정 및 계정 생성 | - |
|
|
| 4-2 | Backend: SMS 발송 서비스 구현 | - |
|
|
| 4-3 | Backend: OTP 검증 API | - |
|
|
| 4-4 | Frontend: 휴대폰 인증 UI | - |
|
|
|
|
### Phase 5: 중계자 인증
|
|
| 작업 | 상세 | 예상 |
|
|
|------|------|------|
|
|
| 5-1 | Backend: 신분증 업로드 API | - |
|
|
| 5-2 | Frontend: 신분증 업로드 UI | - |
|
|
| 5-3 | Admin: 인증 승인 관리 페이지 | - |
|
|
|
|
---
|
|
|
|
## 8. 환경 변수 설정
|
|
|
|
### Backend (.env)
|
|
```env
|
|
# Database
|
|
USE_SQLITE=True # False for production
|
|
DB_HOST=192.168.0.201
|
|
DB_PORT=5432
|
|
DB_NAME=mongolcar
|
|
DB_USER=admin
|
|
DB_PASSWORD=your_password
|
|
|
|
# Redis (Refresh Token 저장, OTP 임시 저장)
|
|
REDIS_HOST=192.168.0.201
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=your_password
|
|
|
|
# ============================================
|
|
# JWT 이중 토큰 설정 (보안 강화)
|
|
# ============================================
|
|
# Access Token 설정
|
|
SECRET_KEY=your-super-secret-key-for-jwt-minimum-32-chars
|
|
ALGORITHM=HS256
|
|
ACCESS_TOKEN_EXPIRE_MINUTES=15 # 15분 (보안 강화)
|
|
|
|
# Refresh Token 설정
|
|
REFRESH_SECRET_KEY=your-refresh-secret-key-different-from-access
|
|
REFRESH_TOKEN_EXPIRE_DAYS=7 # 7일
|
|
|
|
# 세션 타임아웃 (참고용 - 프론트엔드에서 관리)
|
|
SESSION_TIMEOUT_MINUTES=30
|
|
|
|
# ============================================
|
|
# 비밀번호 보안 설정
|
|
# ============================================
|
|
BCRYPT_COST_FACTOR=12 # bcrypt rounds (12 권장, 높을수록 안전)
|
|
|
|
# ============================================
|
|
# OAuth 설정
|
|
# ============================================
|
|
# Facebook OAuth 2.0 + PKCE
|
|
FACEBOOK_APP_ID=
|
|
FACEBOOK_APP_SECRET=
|
|
FACEBOOK_REDIRECT_URI=http://localhost:3000/api/auth/facebook/callback
|
|
|
|
# Google OAuth 2.0
|
|
GOOGLE_CLIENT_ID=
|
|
GOOGLE_CLIENT_SECRET=
|
|
GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google/callback
|
|
|
|
# ============================================
|
|
# SMS OTP 설정 (Twilio)
|
|
# ============================================
|
|
TWILIO_ACCOUNT_SID=
|
|
TWILIO_AUTH_TOKEN=
|
|
TWILIO_PHONE_NUMBER=
|
|
OTP_EXPIRE_MINUTES=5 # OTP 유효시간 5분
|
|
|
|
# ============================================
|
|
# Carmodoo Agent
|
|
# ============================================
|
|
CARMODOO_USER_ID=01033315258
|
|
CARMODOO_PASSWORD=alskfl@1122
|
|
AGENT_API_KEY=your_agent_api_key
|
|
|
|
# ============================================
|
|
# 파일 업로드
|
|
# ============================================
|
|
UPLOAD_DIR=./uploads
|
|
MAX_FILE_SIZE=10485760 # 10MB
|
|
|
|
# ============================================
|
|
# 보안 설정
|
|
# ============================================
|
|
CORS_ORIGINS=http://localhost:3000,https://autonetsellcar.com
|
|
COOKIE_DOMAIN=localhost # 프로덕션: .autonetsellcar.com
|
|
COOKIE_SECURE=False # 프로덕션: True (HTTPS 필수)
|
|
```
|
|
|
|
### Frontend (.env.local)
|
|
```env
|
|
NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
|
|
# NextAuth (소셜 로그인 사용 시)
|
|
NEXTAUTH_URL=http://localhost:3000
|
|
NEXTAUTH_SECRET=your-nextauth-secret
|
|
|
|
# Facebook
|
|
FACEBOOK_ID=
|
|
FACEBOOK_SECRET=
|
|
|
|
# Google
|
|
GOOGLE_ID=
|
|
GOOGLE_SECRET=
|
|
```
|
|
|
|
---
|
|
|
|
## 9. 파일 구조 (예상)
|
|
|
|
### Backend 추가 파일
|
|
```
|
|
mongolcar/backend/app/
|
|
├── api/
|
|
│ ├── auth.py # 확장: OAuth, SMS OTP
|
|
│ ├── hero_banners.py # 새로 추가
|
|
│ └── admin/
|
|
│ ├── __init__.py
|
|
│ ├── dashboard.py
|
|
│ ├── users.py
|
|
│ └── verifications.py
|
|
├── models/
|
|
│ ├── hero_banner.py # 새로 추가
|
|
│ └── user.py # 확장
|
|
├── schemas/
|
|
│ ├── hero_banner.py # 새로 추가
|
|
│ └── user.py # 확장
|
|
└── services/
|
|
├── oauth.py # 새로 추가
|
|
└── sms.py # 새로 추가
|
|
```
|
|
|
|
### Frontend 추가 파일
|
|
```
|
|
mongolcar/frontend/src/
|
|
├── app/
|
|
│ ├── admin/
|
|
│ │ ├── layout.tsx
|
|
│ │ ├── page.tsx # 대시보드
|
|
│ │ ├── login/page.tsx
|
|
│ │ ├── hero-banners/page.tsx
|
|
│ │ ├── cars/page.tsx
|
|
│ │ ├── users/page.tsx
|
|
│ │ └── verifications/page.tsx
|
|
│ └── auth/
|
|
│ ├── login/page.tsx # 확장
|
|
│ └── verify-phone/page.tsx
|
|
├── components/
|
|
│ ├── FilmStripSlider.tsx # 새로 추가
|
|
│ ├── SocialLoginButtons.tsx
|
|
│ └── admin/
|
|
│ ├── Sidebar.tsx
|
|
│ └── Header.tsx
|
|
└── lib/
|
|
└── auth.ts # NextAuth 설정
|
|
```
|
|
|
|
---
|
|
|
|
## 10. API 엔드포인트 전체 목록
|
|
|
|
### 인증 API (이중 토큰 전략)
|
|
| Method | Endpoint | 설명 | 권한 |
|
|
|--------|----------|------|------|
|
|
| POST | /api/auth/register | 회원가입 (Access + Refresh 발급) | Public |
|
|
| POST | /api/auth/login | 이메일 로그인 (Access + Refresh 발급) | Public |
|
|
| POST | /api/auth/refresh | Access Token 재발급 (Refresh Cookie 필요) | Public |
|
|
| POST | /api/auth/logout | 로그아웃 (Refresh Token 무효화) | User |
|
|
| GET | /api/auth/me | 현재 사용자 정보 | User |
|
|
| GET | /api/auth/facebook | Facebook OAuth + PKCE 시작 | Public |
|
|
| POST | /api/auth/facebook/callback | Facebook 콜백 (자체 JWT 발급) | Public |
|
|
| GET | /api/auth/google | Google OAuth 시작 | Public |
|
|
| POST | /api/auth/google/callback | Google 콜백 (자체 JWT 발급) | Public |
|
|
| POST | /api/auth/send-otp | SMS OTP 발송 (Redis 저장) | Public |
|
|
| POST | /api/auth/verify-otp | SMS OTP 검증 | Public |
|
|
| POST | /api/auth/upload-id-card | 신분증 업로드 (중계자용) | User |
|
|
| PUT | /api/auth/change-password | 비밀번호 변경 (bcrypt) | User |
|
|
|
|
### 히어로 배너 API
|
|
| Method | Endpoint | 설명 | 권한 |
|
|
|--------|----------|------|------|
|
|
| GET | /api/hero-banners | 활성 배너 목록 | Public |
|
|
| GET | /api/hero-banners/settings | 슬라이더 설정 | Public |
|
|
| GET | /api/admin/hero-banners | 모든 배너 | Admin |
|
|
| POST | /api/admin/hero-banners | 배너 생성 | Admin |
|
|
| PUT | /api/admin/hero-banners/{id} | 배너 수정 | Admin |
|
|
| DELETE | /api/admin/hero-banners/{id} | 배너 삭제 | Admin |
|
|
| POST | /api/admin/hero-banners/upload | 이미지 업로드 | Admin |
|
|
| PUT | /api/admin/hero-banners/settings | 설정 변경 | Admin |
|
|
|
|
### 관리자 API
|
|
| Method | Endpoint | 설명 | 권한 |
|
|
|--------|----------|------|------|
|
|
| GET | /api/admin/dashboard | 대시보드 통계 | Admin |
|
|
| GET | /api/admin/users | 사용자 목록 | Admin |
|
|
| GET | /api/admin/verifications | 인증 대기 목록 | Admin |
|
|
| PUT | /api/admin/verifications/{id} | 인증 승인/거절 | Admin |
|
|
|
|
---
|
|
|
|
## 11. 참고 자료
|
|
|
|
### 프로젝트 파일 위치
|
|
```
|
|
D:\Workspace\claudeCode\AutonetSellCar\
|
|
├── mongolcar/
|
|
│ ├── backend/ # FastAPI 백엔드
|
|
│ ├── frontend/ # Next.js 프론트엔드
|
|
│ └── agent/ # Carmodoo Agent
|
|
├── agent/ # 원본 Agent (백업)
|
|
├── Grantech.kr/ # 참고용 (관리자 페이지)
|
|
└── 문서들
|
|
├── PROGRESS_2025-11-27.md
|
|
├── PROGRESS_2025-11-28.md
|
|
├── SERVER_INFRASTRUCTURE_PLAN.md
|
|
└── AUTONETSELLCAR_DEVELOPMENT_PLAN.md (이 파일)
|
|
```
|
|
|
|
### OAuth 설정 가이드
|
|
- Facebook: https://developers.facebook.com/docs/facebook-login/
|
|
- Google: https://developers.google.com/identity/protocols/oauth2
|
|
|
|
### SMS 게이트웨이
|
|
- Twilio: https://www.twilio.com/docs/sms
|
|
- MessageBird: https://developers.messagebird.com/
|
|
|
|
---
|
|
|
|
## 12. 보안 체크리스트
|
|
|
|
### 12.1 인증 보안
|
|
- [ ] bcrypt cost factor 12 이상 적용
|
|
- [ ] Access Token 수명 15분 이하
|
|
- [ ] Refresh Token HttpOnly Cookie 저장
|
|
- [ ] PKCE 적용 (Facebook OAuth)
|
|
- [ ] CSRF 토큰 적용
|
|
- [ ] Rate Limiting (로그인 시도 제한)
|
|
|
|
### 12.2 통신 보안
|
|
- [ ] HTTPS 강제 (프로덕션)
|
|
- [ ] CORS 설정 (허용 도메인만)
|
|
- [ ] Cookie Secure 플래그 (HTTPS)
|
|
- [ ] Cookie SameSite=Strict
|
|
|
|
### 12.3 데이터 보안
|
|
- [ ] SQL Injection 방지 (ORM 사용)
|
|
- [ ] XSS 방지 (React 자동 이스케이프)
|
|
- [ ] 민감 정보 로깅 금지
|
|
- [ ] 환경 변수 Git 제외
|
|
|
|
---
|
|
|
|
## 13. 변경 이력
|
|
|
|
| 날짜 | 내용 | 작성자 |
|
|
|------|------|--------|
|
|
| 2025-12-06 | 최초 작성 | Claude Code |
|
|
| 2025-12-06 | 이중 토큰 전략 추가 (Access + Refresh Token) | Claude Code |
|
|
| 2025-12-06 | Facebook OAuth PKCE 상세 플로우 추가 | Claude Code |
|
|
| 2025-12-06 | 보안 아키텍처 다이어그램 추가 | Claude Code |
|
|
| 2025-12-06 | bcrypt 비밀번호 정책 추가 | Claude Code |
|
|
| 2025-12-06 | 보안 체크리스트 추가 | Claude Code |
|
|
|
|
---
|
|
|
|
*Generated by Claude Code - 2025-12-06*
|