- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
1401 lines
52 KiB
PHP
1401 lines
52 KiB
PHP
<?php
|
|
require_once($_SERVER['DOCUMENT_ROOT'] . "/session.php");
|
|
?>
|
|
|
|
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>장기적 AI 챗봇 솔루션 전략</title>
|
|
|
|
<!-- Fonts: Pretendard -->
|
|
<link rel="stylesheet" as="style" crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.8/dist/web/static/pretendard.css" />
|
|
|
|
<!-- Tailwind CSS -->
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
fontFamily: {
|
|
sans: ['Pretendard', 'sans-serif'],
|
|
},
|
|
colors: {
|
|
background: 'rgb(250, 250, 250)',
|
|
primary: {
|
|
DEFAULT: '#2563eb', // blue-600
|
|
light: '#dbeafe', // blue-100
|
|
dark: '#1e40af', // blue-800
|
|
foreground: '#ffffff',
|
|
},
|
|
slate: {
|
|
850: '#1e293b', // Custom dark slate
|
|
}
|
|
},
|
|
borderRadius: {
|
|
'card': '12px',
|
|
'pill': '9999px',
|
|
},
|
|
animation: {
|
|
'fade-in': 'fadeIn 0.5s ease-out',
|
|
'slide-up': 'slideUp 0.5s ease-out',
|
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
},
|
|
keyframes: {
|
|
fadeIn: {
|
|
'0%': { opacity: '0' },
|
|
'100%': { opacity: '1' },
|
|
},
|
|
slideUp: {
|
|
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
|
'100%': { transform: 'translateY(0)', opacity: '1' },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<!-- Icons: Lucide -->
|
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|
|
|
<style>
|
|
/* Custom Scrollbar */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
background: #f1f5f9;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
background: #cbd5e1;
|
|
border-radius: 4px;
|
|
}
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: #94a3b8;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Pretendard', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
|
|
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
min-height: 100vh;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.presentation-container {
|
|
width: 100%;
|
|
height: 100vh;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.slide {
|
|
width: 100%;
|
|
height: 100vh;
|
|
display: none;
|
|
align-items: flex-start;
|
|
justify-content: center;
|
|
padding: 40px;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.slide.active {
|
|
display: flex;
|
|
animation: slideInRight 0.5s ease-out;
|
|
}
|
|
|
|
.slide-content {
|
|
background: rgba(255, 255, 255, 0.98);
|
|
border-radius: 24px;
|
|
padding: 60px;
|
|
max-width: 1200px;
|
|
width: 100%;
|
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15), 0 0 0 1px rgba(0, 0, 0, 0.05);
|
|
animation: fadeIn 0.8s ease-out;
|
|
margin: auto 0;
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
h1 {
|
|
color: #2563eb;
|
|
font-size: 3em;
|
|
margin-bottom: 20px;
|
|
text-align: center;
|
|
font-weight: 800;
|
|
}
|
|
|
|
h2 {
|
|
color: #1e40af;
|
|
font-size: 2.5em;
|
|
margin-bottom: 30px;
|
|
text-align: center;
|
|
border-bottom: 3px solid #2563eb;
|
|
padding-bottom: 15px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
h3 {
|
|
color: #2563eb;
|
|
font-size: 1.8em;
|
|
margin: 25px 0 15px 0;
|
|
font-weight: 700;
|
|
}
|
|
|
|
h4 {
|
|
color: #1e40af;
|
|
font-size: 1.3em;
|
|
margin: 15px 0 10px 0;
|
|
font-weight: 700;
|
|
}
|
|
|
|
p, li {
|
|
font-size: 1.2em;
|
|
line-height: 1.8;
|
|
color: #1e293b;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
ul, ol {
|
|
margin-left: 30px;
|
|
}
|
|
|
|
.company-info {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
gap: 20px;
|
|
margin: 30px 0;
|
|
}
|
|
|
|
.info-card {
|
|
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
color: white;
|
|
padding: 25px;
|
|
border-radius: 16px;
|
|
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);
|
|
animation: scaleIn 0.5s ease-out;
|
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.info-card h4 {
|
|
color: white;
|
|
font-size: 1.3em;
|
|
margin-bottom: 10px;
|
|
border-bottom: 2px solid rgba(255, 255, 255, 0.3);
|
|
padding-bottom: 8px;
|
|
}
|
|
|
|
.info-card p {
|
|
color: white;
|
|
font-size: 1em;
|
|
}
|
|
|
|
.comparison-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 25px 0;
|
|
font-size: 1em;
|
|
}
|
|
|
|
.comparison-table th,
|
|
.comparison-table td {
|
|
padding: 12px;
|
|
border: 1px solid #ddd;
|
|
text-align: left;
|
|
}
|
|
|
|
.comparison-table thead tr {
|
|
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
color: white;
|
|
}
|
|
|
|
.comparison-table tbody tr:nth-of-type(even) {
|
|
background: #f3f3f3;
|
|
}
|
|
|
|
.feature-list {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
gap: 15px;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.feature-item {
|
|
background: #f8fafc;
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
border-left: 4px solid #2563eb;
|
|
border: 1px solid #e2e8f0;
|
|
border-left-width: 4px;
|
|
}
|
|
|
|
.feature-item h4 {
|
|
color: #1e40af;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.conclusion-box {
|
|
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
color: white;
|
|
padding: 30px;
|
|
border-radius: 16px;
|
|
margin: 20px 0;
|
|
text-align: center;
|
|
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);
|
|
}
|
|
|
|
.conclusion-box p, .conclusion-box h3 {
|
|
color: white;
|
|
}
|
|
|
|
.warning-box {
|
|
background: #fef3c7;
|
|
border-left: 5px solid #f59e0b;
|
|
padding: 25px;
|
|
border-radius: 16px;
|
|
margin: 20px 0;
|
|
border: 1px solid #fde68a;
|
|
}
|
|
|
|
.warning-box h3, .warning-box li {
|
|
color: #92400e;
|
|
}
|
|
|
|
.flow-diagram {
|
|
background: #f1f5f9;
|
|
padding: 25px;
|
|
border-radius: 16px;
|
|
margin: 20px 0;
|
|
border: 2px solid #2563eb;
|
|
}
|
|
|
|
.flow-diagram pre {
|
|
font-size: 1em;
|
|
line-height: 1.6;
|
|
color: #1e293b;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.code-box {
|
|
background: #1e293b;
|
|
color: #aed581;
|
|
padding: 20px;
|
|
border-radius: 12px;
|
|
margin: 20px 0;
|
|
overflow-x: auto;
|
|
font-family: 'Courier New', monospace;
|
|
font-size: 0.9em;
|
|
border: 1px solid #334155;
|
|
}
|
|
|
|
.code-box pre {
|
|
margin: 0;
|
|
color: #aed581;
|
|
}
|
|
|
|
.navigation {
|
|
position: fixed;
|
|
bottom: 30px;
|
|
right: 30px;
|
|
display: flex;
|
|
gap: 15px;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.nav-btn {
|
|
background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
color: white;
|
|
border: none;
|
|
padding: 15px 30px;
|
|
border-radius: 9999px;
|
|
cursor: pointer;
|
|
font-size: 1.1em;
|
|
font-weight: 600;
|
|
box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.nav-btn:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 20px rgba(37, 99, 235, 0.4);
|
|
background: linear-gradient(135deg, #1d4ed8 0%, #1e3a8a 100%);
|
|
}
|
|
|
|
.nav-btn:disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.slide-number {
|
|
position: fixed;
|
|
bottom: 30px;
|
|
left: 30px;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
padding: 12px 24px;
|
|
border-radius: 9999px;
|
|
font-size: 1.1em;
|
|
color: #2563eb;
|
|
font-weight: 700;
|
|
z-index: 1000;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
border: 1px solid rgba(37, 99, 235, 0.1);
|
|
}
|
|
|
|
@keyframes slideInRight {
|
|
from {
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes scaleIn {
|
|
from {
|
|
transform: scale(0.9);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: scale(1);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.slide-content {
|
|
padding: 30px;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 2em;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 1.8em;
|
|
}
|
|
|
|
h3 {
|
|
font-size: 1.4em;
|
|
}
|
|
|
|
p, li {
|
|
font-size: 1em;
|
|
}
|
|
|
|
.navigation {
|
|
bottom: 15px;
|
|
right: 15px;
|
|
}
|
|
|
|
.nav-btn {
|
|
padding: 10px 20px;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.slide-number {
|
|
bottom: 15px;
|
|
left: 15px;
|
|
padding: 8px 15px;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.comparison-table {
|
|
font-size: 0.8em;
|
|
}
|
|
|
|
.comparison-table th,
|
|
.comparison-table td {
|
|
padding: 8px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-background text-slate-800 antialiased min-h-screen">
|
|
|
|
<!-- Navigation / Header -->
|
|
<header class="bg-white border-b border-slate-100 sticky top-0 z-50 shadow-sm">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-8 h-8 bg-primary rounded-lg flex items-center justify-center text-white font-bold shadow-md">
|
|
AI
|
|
</div>
|
|
<h1 class="text-lg font-bold text-slate-900 tracking-tight">장기적 AI 챗봇 솔루션 전략</h1>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<a href="../index.php" class="text-sm text-slate-500 hover:text-slate-900 flex items-center gap-1 font-medium transition-colors">
|
|
<i data-lucide="home" class="w-4 h-4"></i>
|
|
홈으로
|
|
</a>
|
|
<div class="h-4 w-px bg-slate-200"></div>
|
|
<span class="text-xs font-medium px-2.5 py-1 bg-slate-100 text-slate-600 rounded-full">중장기 계획</span>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="presentation-container">
|
|
<!-- Slide 1: Cover -->
|
|
<div class="slide active">
|
|
<div class="slide-content">
|
|
<h1>장기적 AI 챗봇 솔루션 전략</h1>
|
|
<h2 style="border: none; color: #2563eb;">Vertex AI Search 기반 지능형 문서 검색 시스템</h2>
|
|
<div style="text-align: center; margin-top: 50px;">
|
|
<p style="font-size: 1.5em; color: #1e40af; font-weight: 600;">노트북LM 수준의 자연어 질의응답 시스템</p>
|
|
<p style="margin-top: 30px; color: #64748b;">RAG (검색 증강 생성) 기반 고객 지원 자동화</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 2: Project Overview -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>프로젝트 개요</h2>
|
|
|
|
<div class="conclusion-box">
|
|
<h3 style="color: white; margin-top: 0;">배경</h3>
|
|
<p style="font-size: 1.2em;">중소기업의 고객 지원 자동화 필요성 증가<br>문서 기반 즉각적 답변 제공으로 업무 효율성 향상</p>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>핵심 목표</h3>
|
|
<ul>
|
|
<li><strong>자연어 질문 즉각 답변:</strong> 복잡한 질의에 대한 정확한 답변 제공</li>
|
|
<li><strong>노트북LM 유사 기술:</strong> Google의 Vertex AI Search RAG 기술 활용</li>
|
|
<li><strong>고객 지원 비용 절감:</strong> 자동화를 통한 인력 비용 및 시간 절약</li>
|
|
<li><strong>문서 기반 검색:</strong> PDF, DOCX, HTML 등 다양한 형식 지원</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>프로젝트 범위</h3>
|
|
<div class="company-info">
|
|
<div class="info-card">
|
|
<h4>✅ 포함 범위</h4>
|
|
<p>Vertex AI Search 연동, Laravel 백엔드 구현, 챗봇 UI, 문서 인덱싱, 참고 자료 제공</p>
|
|
</div>
|
|
<div class="info-card">
|
|
<h4>❌ 제외 범위</h4>
|
|
<p>음성 인식, 이미지 분석, 실시간 영상 통화, 복잡한 워크플로우 자동화</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 3: Vertex AI Search 기술 분석 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>Vertex AI Search 기술 분석</h2>
|
|
|
|
<div class="feature-list">
|
|
<div class="feature-item">
|
|
<h4>🤖 완전 관리형 서비스</h4>
|
|
<p>인프라 관리 불필요, Google이 스케일링 및 유지보수 담당</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>🔍 RAG (검색 증강 생성)</h4>
|
|
<p>문서 검색 + LLM 생성 결합으로 정확하고 맥락있는 답변</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>🎯 Google 수준의 검색 품질</h4>
|
|
<p>Google 검색 기술 기반의 고품질 문서 검색</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>📚 다양한 문서 형식 지원</h4>
|
|
<p>PDF, DOCX, HTML, JSON, 웹사이트 크롤링</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>핵심 특징</h3>
|
|
<ul>
|
|
<li><strong>Semantic Search:</strong> 키워드 매칭이 아닌 의미 기반 검색</li>
|
|
<li><strong>Personalization:</strong> 사용자별 맞춤 검색 결과 제공</li>
|
|
<li><strong>Multi-modal:</strong> 텍스트, 이미지, 비디오 등 다양한 데이터 타입</li>
|
|
<li><strong>Enterprise-grade Security:</strong> IAM 기반 접근 제어 및 데이터 격리</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 4: RAG 작동 원리 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>RAG (검색 증강 생성) 작동 원리</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1단계: 데이터 수집 (Ingestion)</h3>
|
|
<div class="info-card" style="margin: 15px 0;">
|
|
<p>문서를 Vertex AI Search Data Store에 업로드 (PDF, DOCX, HTML 등)</p>
|
|
<p>자동으로 청크 단위로 분할 및 임베딩 벡터 생성</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2단계: 인덱싱 (Indexing)</h3>
|
|
<div class="info-card" style="margin: 15px 0;">
|
|
<p>문서의 의미를 벡터로 변환하여 벡터 데이터베이스에 저장</p>
|
|
<p>메타데이터(제목, 작성자, 날짜 등)와 함께 인덱싱</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3단계: 검색 및 생성 (Search & Generation)</h3>
|
|
<div class="info-card" style="margin: 15px 0;">
|
|
<p><strong>검색:</strong> 사용자 질문을 벡터로 변환 후 유사 문서 검색</p>
|
|
<p><strong>생성:</strong> 검색된 문서를 컨텍스트로 LLM(Gemini)이 답변 생성</p>
|
|
<p><strong>참조:</strong> 답변에 사용된 원본 문서 링크 제공</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 5: Architecture Diagram -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>시스템 아키텍처</h2>
|
|
|
|
<div class="flow-diagram">
|
|
<pre>
|
|
┌─────────────┐
|
|
│ 사용자 │
|
|
└──────┬──────┘
|
|
│ 질문 입력
|
|
↓
|
|
┌──────────────────┐
|
|
│ SAM Frontend │
|
|
│ (Vue.js/ │
|
|
│ React) │
|
|
└────────┬─────────┘
|
|
│ HTTP Request
|
|
↓
|
|
┌──────────────────────────┐
|
|
│ SAM Backend (Laravel) │
|
|
│ ┌──────────────────────┐ │
|
|
│ │ ChatController │ │
|
|
│ │ - searchVertexAI() │ │
|
|
│ └──────────┬───────────┘ │
|
|
└────────────┼─────────────┘
|
|
│ API Call
|
|
↓
|
|
┌────────────────────────────┐
|
|
│ Google Cloud Platform │
|
|
│ ┌────────────────────────┐ │
|
|
│ │ Vertex AI Search │ │
|
|
│ │ - Data Store │ │
|
|
│ │ - Search Engine │ │
|
|
│ └───────────┬────────────┘ │
|
|
│ │ │
|
|
│ ┌───────────▼────────────┐ │
|
|
│ │ LLM (Gemini 1.5) │ │
|
|
│ │ - Answer Generation │ │
|
|
│ └────────────────────────┘ │
|
|
└────────────────────────────┘
|
|
</pre>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>데이터 흐름</h3>
|
|
<ol>
|
|
<li>사용자가 프론트엔드에서 질문 입력</li>
|
|
<li>Laravel 백엔드가 Vertex AI Search API 호출</li>
|
|
<li>Vertex AI가 문서 검색 후 Gemini에 전달</li>
|
|
<li>Gemini가 검색 결과 기반 답변 생성</li>
|
|
<li>백엔드가 답변 + 참고 자료를 프론트엔드로 반환</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 6: Phase 1 - Google Cloud 설정 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>Phase 1: Google Cloud 설정</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. GCP 프로젝트 생성</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
# 프로젝트 ID: sam-chatbot-project
|
|
# 위치: asia-northeast3 (서울)</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. 필수 API 활성화</h3>
|
|
<ul>
|
|
<li>Discovery Engine API (Vertex AI Search)</li>
|
|
<li>Vertex AI API</li>
|
|
<li>Cloud Storage API (문서 저장용)</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. 서비스 계정 생성</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
# 서비스 계정 이름: sam-chatbot-sa
|
|
# 역할:
|
|
# - Discovery Engine Admin
|
|
# - Vertex AI User</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>4. JSON 인증 키 다운로드</h3>
|
|
<div class="warning-box">
|
|
<h3>⚠️ 보안 주의사항</h3>
|
|
<ul>
|
|
<li>JSON 키 파일은 절대 Git에 커밋하지 않기</li>
|
|
<li>.gitignore에 추가 필수</li>
|
|
<li>환경 변수로 관리</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 7: Phase 2 - Vertex AI Search 데이터 스토어 구축 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>Phase 2: Vertex AI Search 데이터 스토어 구축</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. 앱 생성</h3>
|
|
<ul>
|
|
<li><strong>앱 유형:</strong> Chat (대화형)</li>
|
|
<li><strong>데이터 타입:</strong> Unstructured (비정형 문서)</li>
|
|
<li><strong>솔루션 타입:</strong> Search with Chat</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. 문서 업로드</h3>
|
|
<div class="feature-list">
|
|
<div class="feature-item">
|
|
<h4>📂 Cloud Storage</h4>
|
|
<p>대량 문서 업로드 (gs://bucket-name/)</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>🌐 웹사이트 크롤링</h4>
|
|
<p>sitemap.xml 기반 자동 수집</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>📄 개별 업로드</h4>
|
|
<p>콘솔에서 직접 파일 업로드</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. 인덱싱</h3>
|
|
<div class="info-card">
|
|
<p>업로드 후 자동 인덱싱 시작 (10-30분 소요)</p>
|
|
<p>인덱싱 상태: Console → Vertex AI Search에서 확인</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>4. 테스트</h3>
|
|
<p>GCP Console의 Preview 기능으로 샘플 질문 테스트</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 8: Phase 3 - Laravel 백엔드 구현 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>Phase 3: Laravel 백엔드 구현</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. Google Cloud PHP 클라이언트 설치</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
composer require google/cloud-discoveryengine</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. 환경 변수 설정 (.env)</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
GOOGLE_CLOUD_PROJECT_ID=sam-chatbot-project
|
|
GOOGLE_CLOUD_LOCATION=asia-northeast3
|
|
GOOGLE_CLOUD_DATA_STORE_ID=your-data-store-id
|
|
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. ChatController 구현</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
use Google\Cloud\DiscoveryEngine\V1\SearchServiceClient;
|
|
use Google\Cloud\DiscoveryEngine\V1\SearchRequest;
|
|
|
|
public function searchVertexAI(Request $request)
|
|
{
|
|
$query = $request->input('query');
|
|
|
|
$client = new SearchServiceClient([
|
|
'credentials' => env('GOOGLE_APPLICATION_CREDENTIALS')
|
|
]);
|
|
|
|
$servingConfig = sprintf(
|
|
'projects/%s/locations/%s/collections/default_collection/dataStores/%s/servingConfigs/default_config',
|
|
env('GOOGLE_CLOUD_PROJECT_ID'),
|
|
env('GOOGLE_CLOUD_LOCATION'),
|
|
env('GOOGLE_CLOUD_DATA_STORE_ID')
|
|
);
|
|
|
|
$searchRequest = new SearchRequest([
|
|
'serving_config' => $servingConfig,
|
|
'query' => $query,
|
|
'page_size' => 5
|
|
]);
|
|
|
|
$response = $client->search($searchRequest);
|
|
|
|
return response()->json([
|
|
'answer' => $response->getSummary(),
|
|
'references' => $response->getResults()
|
|
]);
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 9: Phase 4 - 프론트엔드 구현 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>Phase 4: 프론트엔드 구현</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. 챗봇 UI 컴포넌트</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
<template>
|
|
<div class="chatbot-container">
|
|
<div class="messages">
|
|
<div v-for="msg in messages" :key="msg.id">
|
|
<div :class="['message', msg.role]">
|
|
{{ msg.content }}
|
|
</div>
|
|
<div v-if="msg.references" class="references">
|
|
참고: <a v-for="ref in msg.references" :href="ref.url">
|
|
{{ ref.title }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<input v-model="userInput" @keyup.enter="sendMessage" />
|
|
</div>
|
|
</template></pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. API 호출 로직</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
async sendMessage() {
|
|
const response = await axios.post('/api/chatbot/search', {
|
|
query: this.userInput
|
|
});
|
|
|
|
this.messages.push({
|
|
role: 'user',
|
|
content: this.userInput
|
|
});
|
|
|
|
this.messages.push({
|
|
role: 'assistant',
|
|
content: response.data.answer,
|
|
references: response.data.references
|
|
});
|
|
|
|
this.userInput = '';
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 10: 초기 투자 비용 분석 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>초기 투자 비용 분석</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>Vertex AI Search 비용 (월간 예상)</h3>
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>항목</th>
|
|
<th>단가</th>
|
|
<th>예상 사용량</th>
|
|
<th>월 비용</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>데이터 저장</td>
|
|
<td>$0.10/GB</td>
|
|
<td>50GB</td>
|
|
<td>$5.00</td>
|
|
</tr>
|
|
<tr>
|
|
<td>질의 비용</td>
|
|
<td>$0.0025/query</td>
|
|
<td>3,000 queries</td>
|
|
<td>$7.50</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>총 합계</strong></td>
|
|
<td colspan="2"></td>
|
|
<td><strong>$12.50</strong></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>추가 비용 (선택사항)</h3>
|
|
<ul>
|
|
<li><strong>Cloud Storage:</strong> $0.023/GB (문서 백업용)</li>
|
|
<li><strong>Gemini API:</strong> 별도 호출 시 추가 비용 (RAG는 포함)</li>
|
|
<li><strong>네트워크 송신:</strong> $0.12/GB (아시아 → 외부)</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="conclusion-box" style="margin-top: 30px;">
|
|
<h3 style="color: white;">💰 월 $12.50 수준의 저렴한 운영 비용</h3>
|
|
<p>초기 3개월: 무료 크레딧 $300 활용 가능</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 11: 인프라 확장 권고 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>인프라 확장 권고사항</h2>
|
|
|
|
<div class="warning-box">
|
|
<h3>⚠️ 현재 인프라 분석</h3>
|
|
<ul>
|
|
<li><strong>현재 스펙:</strong> 2Core 4GB (부족)</li>
|
|
<li><strong>문제점:</strong> Laravel + MySQL + 챗봇 동시 운영 시 메모리 부족</li>
|
|
<li><strong>동시 사용자:</strong> 10-20명 수준으로 제한적</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>권장 인프라 구성</h3>
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>구분</th>
|
|
<th>현재</th>
|
|
<th>권장</th>
|
|
<th>비고</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>웹 서버</td>
|
|
<td>2Core 4GB</td>
|
|
<td>4Core 8GB</td>
|
|
<td>Laravel + 챗봇 동시 운영</td>
|
|
</tr>
|
|
<tr>
|
|
<td>DB 서버</td>
|
|
<td>통합</td>
|
|
<td>분리 (4Core 8GB)</td>
|
|
<td>MySQL 전용 서버</td>
|
|
</tr>
|
|
<tr>
|
|
<td>저장공간</td>
|
|
<td>100GB</td>
|
|
<td>200GB SSD</td>
|
|
<td>문서 저장 및 로그</td>
|
|
</tr>
|
|
<tr>
|
|
<td>백업</td>
|
|
<td>수동</td>
|
|
<td>자동 일일 백업</td>
|
|
<td>GCS 또는 별도 스토리지</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>Cloud VM 이전 필수</h3>
|
|
<div class="info-card">
|
|
<p><strong>이유:</strong> Vertex AI와의 네트워크 레이턴시 최소화</p>
|
|
<p><strong>권장 위치:</strong> GCP asia-northeast3 (서울) 리전</p>
|
|
<p><strong>예상 비용:</strong> 웹서버 $80/월 + DB서버 $80/월 = $160/월</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 12: 데이터 품질 관리 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>데이터 품질 관리 전략</h2>
|
|
|
|
<div class="conclusion-box">
|
|
<h3 style="color: white; margin-top: 0;">핵심 원칙</h3>
|
|
<p style="font-size: 1.2em;">문서의 품질이 곧 답변의 품질을 결정합니다</p>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. 문서 최신화</h3>
|
|
<div class="feature-list">
|
|
<div class="feature-item">
|
|
<h4>📅 정기 업데이트</h4>
|
|
<p>월 1회 문서 검토 및 업데이트</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>🗑️ 구버전 제거</h4>
|
|
<p>오래된 문서는 자동 아카이빙</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>✅ 변경 추적</h4>
|
|
<p>버전 관리 시스템 도입</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. 문서 표준화</h3>
|
|
<ul>
|
|
<li><strong>구조화:</strong> 제목, 소제목, 본문이 명확한 구조</li>
|
|
<li><strong>포맷:</strong> PDF 또는 DOCX 권장 (일관된 포맷)</li>
|
|
<li><strong>언어:</strong> 한국어 또는 영어 중 하나로 통일</li>
|
|
<li><strong>메타데이터:</strong> 제목, 작성자, 작성일, 카테고리 필수 입력</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. 품질 검증</h3>
|
|
<div class="info-card">
|
|
<p><strong>방법:</strong> 샘플 질문 10-20개로 주기적 테스트</p>
|
|
<p><strong>지표:</strong> 답변 정확도 90% 이상 유지</p>
|
|
<p><strong>개선:</strong> 부정확한 답변 발견 시 문서 보완</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 13: 보안 - API 키 관리 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>보안: API 키 및 인증 관리</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. 서비스 계정 키 보안</h3>
|
|
<div class="warning-box">
|
|
<h3>⚠️ 절대 금지 사항</h3>
|
|
<ul>
|
|
<li>JSON 키 파일을 Git에 커밋</li>
|
|
<li>클라이언트 사이드 코드에 키 노출</li>
|
|
<li>공개 저장소에 키 업로드</li>
|
|
<li>불필요한 권한 부여</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. .gitignore 설정</h3>
|
|
<div class="code-box">
|
|
<pre>
|
|
# Google Cloud 인증 키
|
|
service-account.json
|
|
google-credentials.json
|
|
*.json
|
|
|
|
# 환경 변수
|
|
.env
|
|
.env.local
|
|
.env.production</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. 최소 권한 원칙</h3>
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>역할</th>
|
|
<th>권한</th>
|
|
<th>용도</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Discovery Engine User</td>
|
|
<td>검색 API 호출</td>
|
|
<td>일반 검색 요청</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Storage Object Viewer</td>
|
|
<td>문서 읽기</td>
|
|
<td>문서 다운로드</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Discovery Engine Admin</td>
|
|
<td>데이터 스토어 관리</td>
|
|
<td>관리자 전용 (제한적)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>4. 환경 변수 관리</h3>
|
|
<div class="info-card">
|
|
<p><strong>개발:</strong> .env.local 사용</p>
|
|
<p><strong>운영:</strong> 서버 환경 변수 또는 Secret Manager</p>
|
|
<p><strong>CI/CD:</strong> GitHub Secrets 또는 GitLab Variables</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 14: Development Roadmap -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>개발 로드맵 (10-12주)</h2>
|
|
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>단계</th>
|
|
<th>기간</th>
|
|
<th>주요 작업</th>
|
|
<th>산출물</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Phase 1</strong></td>
|
|
<td>W1-2</td>
|
|
<td>GCP 설정, Vertex AI Search 앱 생성, 샘플 문서 업로드</td>
|
|
<td>테스트용 데이터 스토어</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 2</strong></td>
|
|
<td>W3-4</td>
|
|
<td>Laravel 백엔드 API 개발, 인증 구현</td>
|
|
<td>ChatController + API 엔드포인트</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 3</strong></td>
|
|
<td>W5-6</td>
|
|
<td>프론트엔드 챗봇 UI 개발, 답변 표시, 참고자료 링크</td>
|
|
<td>챗봇 인터페이스</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 4</strong></td>
|
|
<td>W7-8</td>
|
|
<td>전체 문서 업로드 및 인덱싱, 품질 테스트</td>
|
|
<td>프로덕션 데이터 스토어</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 5</strong></td>
|
|
<td>W9</td>
|
|
<td>사용자 피드백 수집, 답변 품질 개선</td>
|
|
<td>베타 테스트 리포트</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 6</strong></td>
|
|
<td>W10</td>
|
|
<td>인프라 확장 (4Core 8GB), DB 분리</td>
|
|
<td>스케일링 완료</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 7</strong></td>
|
|
<td>W11</td>
|
|
<td>모니터링 및 로깅 시스템 구축</td>
|
|
<td>운영 대시보드</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Phase 8</strong></td>
|
|
<td>W12</td>
|
|
<td>정식 오픈, 운영 가이드 작성</td>
|
|
<td>프로덕션 런칭</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 15: 테스트 시나리오 -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>테스트 시나리오</h2>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>1. 문서 기반 질의응답</h3>
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>질문 예시</th>
|
|
<th>기대 결과</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>"제품 A의 가격은 얼마인가요?"</td>
|
|
<td>제품 가격표 문서에서 정확한 가격 추출 및 답변</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"반품 정책이 어떻게 되나요?"</td>
|
|
<td>반품 규정 문서 기반 상세 답변 + 링크</td>
|
|
</tr>
|
|
<tr>
|
|
<td>"Laravel 설치 방법 알려줘"</td>
|
|
<td>기술 문서에서 단계별 설치 가이드 제공</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>2. 참조 자료 제공</h3>
|
|
<div class="info-card">
|
|
<p>모든 답변에 원본 문서 링크 포함</p>
|
|
<p>사용자가 상세 정보를 직접 확인할 수 있도록 지원</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>3. 다국어 지원 테스트</h3>
|
|
<ul>
|
|
<li>한국어 질문 → 한국어 문서 검색 → 한국어 답변</li>
|
|
<li>영어 질문 → 영어 문서 검색 → 영어 답변</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>4. 답변 정확도 평가</h3>
|
|
<div class="feature-list">
|
|
<div class="feature-item">
|
|
<h4>✅ 정확도</h4>
|
|
<p>사실 기반 답변 90% 이상</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>⏱️ 응답 속도</h4>
|
|
<p>평균 2-3초 이내</p>
|
|
</div>
|
|
<div class="feature-item">
|
|
<h4>📊 관련성</h4>
|
|
<p>질문과 답변 일치도 85% 이상</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 16: KPI & Success Metrics -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h2>성공 지표 (KPI)</h2>
|
|
|
|
<table class="comparison-table">
|
|
<thead>
|
|
<tr>
|
|
<th>지표</th>
|
|
<th>목표</th>
|
|
<th>측정 방법</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>응답 정확도</strong></td>
|
|
<td>90% 이상</td>
|
|
<td>샘플 질문 100개 테스트, 사람이 정확도 평가</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>평균 응답 시간</strong></td>
|
|
<td>3초 이내</td>
|
|
<td>API 응답 시간 모니터링</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>고객 만족도</strong></td>
|
|
<td>85% 이상</td>
|
|
<td>답변 후 👍/👎 피드백 수집</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>지원 티켓 감소</strong></td>
|
|
<td>50% 감소</td>
|
|
<td>챗봇 도입 전후 비교</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>일일 활성 사용자</strong></td>
|
|
<td>100명</td>
|
|
<td>Google Analytics 추적</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>문서 커버리지</strong></td>
|
|
<td>80% 이상</td>
|
|
<td>질문 중 문서에서 답변 가능한 비율</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div style="margin-top: 30px;">
|
|
<h3>ROI 분석</h3>
|
|
<div class="company-info">
|
|
<div class="info-card">
|
|
<h4>💰 비용 절감</h4>
|
|
<p>고객 지원 인력 50% 절감</p>
|
|
<p>월 $500 인건비 절약</p>
|
|
</div>
|
|
<div class="info-card">
|
|
<h4>⏱️ 시간 절약</h4>
|
|
<p>평균 응답 시간 30분 → 3초</p>
|
|
<p>고객 대기 시간 99% 감소</p>
|
|
</div>
|
|
<div class="info-card">
|
|
<h4>📈 만족도 향상</h4>
|
|
<p>즉각적 답변 제공</p>
|
|
<p>24/7 서비스 가능</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Slide 17: Thank You -->
|
|
<div class="slide">
|
|
<div class="slide-content">
|
|
<h1 style="font-size: 4em; margin-bottom: 40px;">감사합니다</h1>
|
|
<div style="text-align: center;">
|
|
<p style="font-size: 1.5em; color: #2563eb; margin-bottom: 30px; font-weight: 700;">장기적 AI 챗봇 솔루션 전략</p>
|
|
<p style="font-size: 1.2em; color: #1e40af; margin-bottom: 40px;">Vertex AI Search 기반 지능형 문서 검색 시스템</p>
|
|
|
|
<div style="margin-top: 50px; padding: 30px; background: #f1f5f9; border-radius: 16px; border: 1px solid #e2e8f0;">
|
|
<h3>프로젝트 요약</h3>
|
|
<div style="margin-top: 20px; text-align: left;">
|
|
<p><strong>🎯 목표:</strong> 노트북LM 수준의 자연어 질의응답 시스템 구축</p>
|
|
<p><strong>💰 비용:</strong> 월 $12.50 (Vertex AI Search) + $160 (인프라)</p>
|
|
<p><strong>⏱️ 기간:</strong> 10-12주</p>
|
|
<p><strong>📊 기대효과:</strong> 고객 지원 비용 50% 절감, 응답 시간 99% 단축</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="margin-top: 40px; padding: 30px; background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%); border-radius: 16px; box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);">
|
|
<h3 style="color: white;">문의 및 피드백</h3>
|
|
<p style="color: white; margin-top: 20px;">본 계획안에 대한 의견이나 추가 논의가 필요하신 경우</p>
|
|
<p style="color: white;">프로젝트 팀으로 연락 주시기 바랍니다.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="slide-number">
|
|
<span id="currentSlide">1</span> / <span id="totalSlides">17</span>
|
|
</div>
|
|
|
|
<div class="navigation">
|
|
<button class="nav-btn" id="prevBtn" onclick="changeSlide(-1)">← 이전</button>
|
|
<button class="nav-btn" id="nextBtn" onclick="changeSlide(1)">다음 →</button>
|
|
</div>
|
|
|
|
<script>
|
|
let currentSlide = 1;
|
|
const totalSlides = 17;
|
|
let touchStartX = 0;
|
|
let touchEndX = 0;
|
|
|
|
document.getElementById('totalSlides').textContent = totalSlides;
|
|
|
|
function showSlide(n) {
|
|
const slides = document.querySelectorAll('.slide');
|
|
|
|
if (n > totalSlides) {
|
|
currentSlide = 1;
|
|
}
|
|
if (n < 1) {
|
|
currentSlide = totalSlides;
|
|
}
|
|
|
|
slides.forEach(slide => {
|
|
slide.classList.remove('active');
|
|
});
|
|
|
|
slides[currentSlide - 1].classList.add('active');
|
|
document.getElementById('currentSlide').textContent = currentSlide;
|
|
|
|
document.getElementById('prevBtn').disabled = (currentSlide === 1);
|
|
document.getElementById('nextBtn').disabled = (currentSlide === totalSlides);
|
|
}
|
|
|
|
function changeSlide(direction) {
|
|
currentSlide += direction;
|
|
showSlide(currentSlide);
|
|
}
|
|
|
|
document.addEventListener('keydown', function(event) {
|
|
if (event.key === 'ArrowLeft') {
|
|
changeSlide(-1);
|
|
} else if (event.key === 'ArrowRight' || event.key === ' ') {
|
|
event.preventDefault();
|
|
changeSlide(1);
|
|
}
|
|
});
|
|
|
|
document.addEventListener('touchstart', function(event) {
|
|
touchStartX = event.changedTouches[0].screenX;
|
|
});
|
|
|
|
document.addEventListener('touchend', function(event) {
|
|
touchEndX = event.changedTouches[0].screenX;
|
|
handleSwipe();
|
|
});
|
|
|
|
function handleSwipe() {
|
|
if (touchEndX < touchStartX - 50) {
|
|
changeSlide(1);
|
|
}
|
|
if (touchEndX > touchStartX + 50) {
|
|
changeSlide(-1);
|
|
}
|
|
}
|
|
|
|
showSlide(currentSlide);
|
|
|
|
// Initialize Lucide icons
|
|
if (typeof lucide !== 'undefined') {
|
|
lucide.createIcons();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|