# 🛂 VisaChat Project

> 대한민국 출입국 업무 관련 비자/체류 전문 상담 AI 챗봇

## 📋 프로젝트 개요

| 항목 | 내용 |
|------|------|
| **도메인** | `https://visachat.kr` |
| **서버 IP** | `210.114.1.234` |
| **서버 경로** | `/var/www/html/visachat` |
| **GitHub** | `https://github.com/barnanacle/visa-chat` |
| **호스팅** | 카페24 |
| **LLM** | OpenAI GPT-5.4-nano |
| **지원 언어** | 한국어, English, 中文, Русский, 日本語, Tiếng Việt, ภาษาไทย |

---

## 🏗️ 시스템 아키텍처

```
사용자 (visachat.kr)
         ↓
    Apache (443/80)
         ↓
    Node.js (3003) + Express
         ↓
   ┌─────┴─────┐
   ↓           ↓
ChromaDB    서식 파일
 (RAG)     (100+개 HWP)
```

---

## 📁 디렉토리 구조

```
visachat/
├── index.js                 # RAG 시스템 메인 (LangChain + ChromaDB)
├── server.js                # 서버 진입점
├── package.json             # 의존성
├── ecosystem.config.cjs     # PM2 설정
│
├── public/                  # 프론트엔드
│   ├── index.html           # SEO + OG태그 + 애드센스 + 스키마 마크업
│   ├── script.js            # 마크다운 파서 (링크 전처리 포함)
│   ├── style.css            # 레이아웃 (컴팩트 헤더, 자동확장 textarea)
│   ├── forms/               # ⭐ 서식 파일 (100+개 HWP)
│   │   ├── *.hwp
│   │   └── forms-list.json  # 서식 메타데이터 (동적 로드됨)
│   ├── og-image.png         # SNS 공유 이미지
│   └── favicon.svg
│
├── source_data/             # ⭐ RAG 소스 PDF (서버 업로드 안됨)
│   ├── 사증민원_매뉴얼.pdf
│   ├── 체류민원_매뉴얼.pdf
│   ├── 국적법.pdf
│   └── ...
│
├── document_forms/          # 서식 원본 (public/forms로 복사됨)
│
├── scripts/
│   └── build-vectordb.js    # PDF → 벡터DB 빌드 스크립트
│
├── vectordb_data.json       # ⭐ 빌드된 벡터 데이터 (서버 업로드)
├── .pdf-hash                # PDF 변경 감지용 해시
│
├── .github/workflows/
│   └── deploy.yml           # GitHub Actions 자동 배포
│
├── .agent/workflows/
│   └── update-source-data.md  # 슬래시 커맨드 워크플로우
│
├── .env                     # 환경 변수 (OPENAI_API_KEY 등)
├── .gitignore
└── PROJECT.md               # 이 파일
```

---

## ⚙️ 핵심 기능

### 1. RAG 기반 비자 상담
- **벡터 DB**: ChromaDB (서버 메모리)
- **임베딩**: OpenAI text-embedding-ada-002 (1536차원)
- **LLM**: GPT-5.4-nano (temperature: 0)
- **청킹 전략**: 핵심 매뉴얼은 비자 자격별(E-7, F-4 등) 전용 청킹, 일반 문서는 문단 기반 청킹
- **핵심 자료**: 「사증민원 자격별 안내 매뉴얼」, 「체류민원 자격별 안내 매뉴얼」 우선 가중치 적용 (+5점)
- **전문가 페르소나**: 최고 전문가 수준, 7개 언어 전용 프롬프트, 서식 링크 번역 제공

### 2. 서식 파일 다운로드 (동적 로드)
- **서식 수**: 100+개 HWP (forms-list.json에서 동적 로드)
- **로드 시점**: 서버 시작 시 `loadFormsList()` 함수 호출
- **다운로드 URL**: `https://visachat.kr/forms/파일명.hwp`
- **프롬프트 지시**: 질문과 관련된 모든 서식 제공, 정확한 파일명만 사용

### 3. 마크다운 렌더링 (script.js)
- 굵은 글씨 (`**bold**`)
- 제목 (`####`)
- 글머리 기호 (`-` → `•`)
- 링크 (`[텍스트](URL)`)
  - **전처리**: `]\n(` → `](` 변환 (LLM 줄바꿈 처리)
  - **URL 인코딩**: `encodeURI()` 사용 (공백, 괄호 처리)
  - **파일 확장자**: `.hwp` 매칭

### 4. UI/UX 특징
- **헤더**: 한 줄 통합 ("대한민국 비자/체류 AI 상담 VisaChat")
- **입력창**: textarea 자동확장 (최대 3줄, 이후 스크롤)
- **키보드**: Enter=전송, Shift+Enter=줄바꿈
- **광고 (AdSense)**: 입력창 하단 고정 배너 (90px)

### 5. SEO/GEO 최적화
- sitemap.xml, robots.txt
- 스키마 마크업 (Organization, FAQPage)
- Google Analytics (gtag.js)
- OG태그, JSON-LD, hreflang

---

## 🔄 업데이트 시퀀스

### 📌 RAG 소스 데이터 업데이트

source_data에 PDF 추가/변경 시:

```bash
# 1. PDF 파일을 source_data/ 디렉토리에 추가
cp 새로운_문서.pdf /Users/ryu/Antigravity/visachat/source_data/

# 2. 벡터 DB 빌드 (변경 감지 자동)
cd /Users/ryu/Antigravity/visachat
npm run build-vectordb

# 3. 커밋 및 배포
git add vectordb_data.json .pdf-hash
git commit -m "RAG 데이터 업데이트: [설명]"
git push origin main

# 약 1분 후 자동 배포 완료
```

**또는 슬래시 커맨드**: `/update-source-data`

---

### 📌 서식 파일 업데이트

document_forms에 HWP 추가/변경 시:

```bash
# 1. HWP 파일을 document_forms/ 디렉토리에 추가
cp 새서식.hwp /Users/ryu/Antigravity/visachat/document_forms/

# 2. public/forms/로 복사
cp document_forms/*.hwp public/forms/

# 3. forms-list.json 재생성
node -e "
const fs = require('fs');
const files = fs.readdirSync('./public/forms').filter(f => f.endsWith('.hwp'));
const forms = files.map(file => ({
    name: file.replace('.hwp', ''),
    file: file,
    url: '/forms/' + encodeURIComponent(file)
}));
const output = {
    version: '1.1',
    updatedAt: new Date().toISOString(),
    totalForms: forms.length,
    forms: forms
};
fs.writeFileSync('./public/forms/forms-list.json', JSON.stringify(output, null, 2));
console.log('Created forms-list.json with', forms.length, 'forms');
"

# 4. 커밋 및 배포
git add public/forms
git commit -m "서식 추가: [설명]"
git push origin main
```

---

### 📌 코드 변경 후 배포

```bash
git add .
git commit -m "설명"
git push origin main
# GitHub Actions가 자동으로 FTP 업로드 + PM2 재시작
```

---

## 📊 현재 상태 (2026-03-24)

| 항목 | 상태 |
|------|------|
| **UI 언어** | ✅ 영어 기반 (외국인 사용자 대상) |
| **레이아웃** | ✅ 100vh 고정, 컴팩트 헤더, ··· 메뉴/모달 시스템 |
| **입력창** | ✅ 자동확장 textarea (Shift+Enter 줄바꿈, IME 조합 처리) |
| **RAG 시스템** | ✅ GPT-5.4-nano, 비자 자격별 청킹, 최고 전문가 페르소나 |
| **서식 제공** | ✅ 동적 로드, 9개 카테고리 분류, 괄호 밸런싱 파서, 다국어 파일명 |
| **마크다운 파서** | ✅ 괄호 밸런싱 수동 파서, .hwp 중복 방지 |
| **광고** | ✅ 고정 배너 90px (AdSense 가이드라인 준수) |
| **다국어 지원** | ✅ 7개 언어 전용 프롬프트 (ko, en, ja, zh, vi, ru, th) |
| **SEO/GEO** | ✅ FAQPage 8개, Service/BreadcrumbList 스키마, AI 크롤러 허용 |
| **빠른 질문** | ✅ 18개 풀에서 랜덤 4개 표시 |

---

## 🔑 환경 변수 (.env)

```
OPENAI_API_KEY=sk-...
RUN_SERVER=true
PORT=3003
ADMIN_KEY=...
```

---

## 📝 주요 커밋 웨이포인트

### 2026-05-02

| 커밋 | 설명 |
|------|------|
| `e858015` | 도메인 전환 visachat.bluedawn.kr → visachat.kr (apex). canonical/og/sitemap/robots/script.js API_BASE_URL/index.js CORS·프롬프트 forms URL 일괄 갱신, PROJECT.md 포트 오기재(3002→3003) 정정 |

**서버 측 작업 (Cafe24 `210.114.1.234`)**
- `/etc/apache2/sites-available/visachat.kr.conf` 신규 (포트 80 + HTTP→HTTPS 301)
- `/etc/apache2/sites-available/visachat.kr-le-ssl.conf` 신규 (포트 443 + www→apex 301)
- Let's Encrypt 인증서 발급 `visachat.kr`,`www.visachat.kr` (만료 2026-07-31, 자동 갱신)
- 정적 = Apache가 `/var/www/html/visachat/public`에서 직접 서빙, `/chat`·`/api`·`/health`·`/admin`만 `localhost:3003` 프록시 (visachat.bluedawn.kr 동일 패턴 미러)
- 잔존 vhost: `visachat.bluedawn.kr.conf`, `visachat.bluedawn.kr-le-ssl.conf` (DNS는 끊겼으므로 다음 갱신 시점에 정리 예정)

### 2026-03-23

| 커밋 | 설명 |
|------|------|
| `2999bb5` | 사증/체류민원 매뉴얼 최신본(260310) 기반 벡터DB 재빌드 (1,483청크) |
| `73e87b6` | LLM 모델 gpt-4o-mini → gpt-5.4-nano 업그레이드 |
| `e6218df` | 챗봇 프롬프트 개선 - 답변 거부 방지 및 전문 상담 품질 강화 |
| `37e707d` | footer 기준일 업데이트 (2026년 1월 → 3월) |
| `d2a3e25` | 한글 IME 조합 중 Enter 입력 시 마지막 글자 중복 버그 수정 |
| `762f6ea` | 프롬프트 구조 개선 - [참고자료] 블록 구분, 검증기 과잉 개입 방지 |
| `5321096` | 서식 목록 9개 카테고리 분류, 서식 정확 매칭 프롬프트 보강 |
| `1e93a3f` | 사용자 관점 답변 원칙, 서식 중복 표시 방지, 내부 용어 노출 차단 |

### 2026-03-24

| 커밋 | 설명 |
|------|------|
| `9e6ffca` | SEO/GEO 종합 최적화 - FAQPage 8개, Service 스키마, AI 크롤러 허용 |
| `c841ab8` | 애드센스 가이드라인 최적화 - 메뉴/모달 시스템 및 서비스 콘텐츠 추가 |
| `61eca97` | 모바일 헤더 제목-메뉴 겹침 수정 |
| `6b327a4` | 서식 다운로드 링크 .hwp 중복 및 괄호 매칭 수정 |
| `d81f8c5` | 정보 없는 항목은 답변에서 생략하도록 프롬프트 개선 |
| `eea5824` | RAG 청킹 전략 개선 (비자 자격별 분할) 및 최고 전문가 페르소나 강화 |
| `8b97fa4` | 서식 링크 괄호 매칭 근본 수정 - 정규식 → 괄호 밸런싱 파서 |
| `c658f63` | UI 영문 전환 (헤더, 버튼, 푸터, 메뉴, 모달) 및 다국어 프롬프트 강화 |
| `9ee6546` | 빠른 질문 버튼 랜덤화 - 18개 풀에서 4개 표시 |
| `5826f8d` | 서식 링크 다국어 파일명 지원 (download 속성 활용) |
| `feee272` | 모든 언어 프롬프트에 서식 목록 및 링크 규칙 추가 |
| `d236e30` | 영어 질문 시 한국어 응답 및 링크 깨짐 수정 |
| `ca1a965` | "Not specified" 빈 항목 나열 방지 강화 |
| `e1daada` | 러시아어/태국어 전용 프롬프트 추가 - 7개 언어 완전 지원 |
| `cde4223` | 웰컴 메시지 및 모달 콘텐츠 전면 보완 |

### 2026-02-01

| 커밋 | 설명 |
|------|------|
| `6513321` | 마크다운 링크 전처리 (줄바꿈/공백 수정) |
| `9e6490b` | 공백 포함 URL 링크 인코딩 |
| `b639bcb` | 서식 파일명 정확 매칭 강화 |
| `824cc50` | 서식 동적 로드 (forms-list.json) |
| `929eb8f` | 괄호 포함 파일명 링크 수정 |
| `b673b61` | 헤더 통합, textarea 자동확장 |
| `93a592a` | RAG 전문가 페르소나 강화 |

---

## ⚠️ 주의사항

### 서식 링크 제공 시
1. `forms-list.json`에 있는 **정확한 파일명만** 사용
2. 파일명 수정, 축약, 풀어쓰기 금지
3. 질문과 관련된 **모든** 서식 제공

### 마크다운 링크 문법
- LLM이 `]`와 `(` 사이에 줄바꿈을 넣을 수 있음 → 전처리로 자동 수정됨
- URL 공백은 `encodeURI()`로 자동 인코딩

---

## 🔗 참고 자료

- [출입국관리법](https://www.law.go.kr)
- [하이코리아](https://www.hikorea.go.kr)
- [출입국외국인정책본부](https://www.immigration.go.kr)
