KoDATA EW 리포트

인터뷰 계획안
This commit is contained in:
2025-12-22 13:30:59 +09:00
parent be7909fb36
commit 685184763a
13 changed files with 979 additions and 0 deletions

442
kodata/index.php Normal file
View File

@@ -0,0 +1,442 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KoDATA EW 리포트 인터뷰 계획안 - SAM Project</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 CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Pretendard', 'sans-serif'],
},
borderRadius: {
'card': '20px',
},
colors: {
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
},
}
}
}
}
</script>
<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest"></script>
<style>
.glass-sidebar {
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
}
.glass-header {
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(12px);
}
@media print {
.no-print { display: none !important; }
aside { display: none !important; }
main { width: 100% !important; margin-left: 0 !important; }
.scroll-mt-24 { scroll-margin-top: 0 !important; }
}
.stat-card {
transition: transform 0.2s, box-shadow 0.2s;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.05);
}
.question-card::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
border-radius: 4px 0 0 4px;
}
.question-card-high::before { background-color: #f43f5e; }
.question-card-medium::before { background-color: #f59e0b; }
.question-card-low::before { background-color: #94a3b8; }
</style>
</head>
<body class="bg-slate-50 text-slate-900 font-sans selection:bg-primary-100 selection:text-primary-700">
<?php
$MEETING_OVERVIEW = [
'date' => '12월 23일(화) 예정',
'target' => 'KoDATA 영업 및 기술 담당자',
'purpose' => [
'EW 리포트 API 도입 비용 산정',
'데이터 가공 및 재제공에 따른 법적 리스크 점검',
'서비스 종료 이슈 대응'
]
];
$SECTIONS = [
[
'id' => 'cost',
'title' => '. 비용 및 계약 조건',
'subtitle' => 'Cost Efficiency & Terms',
'icon' => 'credit-card',
'color' => 'blue',
'questions' => [
['id' => 'c1', 'text' => '과금 체계: EW 리포트 API 호출 시 건당 과금 방식인지, 아니면 정액제인지 명확한 기준은 무엇입니까?', 'priority' => 'high'],
['id' => 'c2', 'text' => 'API 방식별 차등: VALUE(JSON/XML) 방식과 WEB API(HTML/URL) 방식 간에 이용료 차이가 존재합니까?', 'priority' => 'high'],
['id' => 'c3', 'text' => '대량 호출 할인: SAM 프로젝트 규모에 따라 호출량이 늘어날 경우 적용 가능한 슬라이딩 단가제(구간별 할인)가 있습니까?', 'priority' => 'medium'],
['id' => 'c4', 'text' => '유지보수비: API 연동 이후 발생하는 별도의 기술 지원료나 유지보수 비용이 포함됩니까?', 'priority' => 'medium']
]
],
[
'id' => 'legal',
'title' => 'Ⅱ. 데이터 가공 및 법적 리스크',
'subtitle' => 'Legal Stability & Usage Rights',
'icon' => 'shield-check',
'color' => 'emerald',
'questions' => [
['id' => 'l1', 'text' => '데이터 가공 권한: VALUE 방식을 통해 받은 JSON 데이터를 SAM 프로젝트의 UI에 맞춰 재가공하거나, 다른 지표와 결합하여 새로운 인사이트를 도출해 제공하는 것이 저작권법상 허용됩니까?', 'priority' => 'high'],
['id' => 'l2', 'text' => '재제공 범위: KoDATA에서 제공하는 EW등급, 등급산출사유 등의 정보를 SAM 프로젝트 사용자(제3자)에게 열람하게 하는 것이 계약상 위반 소지가 없습니까?', 'priority' => 'high'],
['id' => 'l3', 'text' => '데이터 저장: API로 호출한 기업 개요, 재무 정보, 연체 정보 등을 당사 DB에 영구적 또는 일시적으로 저장하여 리포트 이력 관리용으로 사용할 수 있습니까?', 'priority' => 'medium'],
['id' => 'l4', 'text' => '법적 책임 소재: KoDATA 제공 데이터의 오류로 인해 SAM 프로젝트 사용자가 의사결정 손실을 보았을 경우, 법적 책임의 한계와 면책 조항은 어떻게 됩니까?', 'priority' => 'high']
]
],
[
'id' => 'continuity',
'title' => 'Ⅲ. 서비스 종료 및 연속성 대응',
'subtitle' => 'Business Continuity',
'icon' => 'refresh-ccw',
'color' => 'amber',
'questions' => [
['id' => 's1', 'text' => "종료 사유 및 영향: 2026년 2월 27일 종료 예정인 '기업신용안심서비스'의 종료 사유가 API 서비스의 품질 저하나 데이터 공급 중단과 관련이 있습니까?", 'priority' => 'medium'],
['id' => 's2', 'text' => "대체 서비스: 서비스 종료 공지에서 언급된 '더 좋은 서비스'가 현재 SAM 프로젝트에서 검토 중인 EW 리포트 API와 어떤 차별점이 있습니까?", 'priority' => 'medium'],
['id' => 's3', 'text' => '전환 지원: 만약 향후 API 사양이나 서비스 체계가 변경될 경우, SAM 프로젝트가 중단 없이 운영될 수 있도록 하는 마이그레이션 지원 대책이 있습니까?', 'priority' => 'medium']
]
],
[
'id' => 'technical',
'title' => 'Ⅳ. 기술적 활용 상세',
'subtitle' => 'Technical Integration',
'icon' => 'cpu',
'color' => 'slate',
'questions' => [
['id' => 't1', 'text' => '항목 선택: VALUE 방식을 선택할 경우, EW등급 외에 단기연체(신용정보원), 휴폐업정보 등 필요한 항목만 선별하여 단가를 낮추는 구성이 가능합니까?', 'priority' => 'medium'],
['id' => 't2', 'text' => "'VALUE API 목록WEB' 방식 사용 시 HTML에 인코딩된 CSS가 SAM 프로젝트의 기존 스타일과 충돌할 가능성에 대해 기술적 가이드를 제공합니까?", 'priority' => 'low']
]
]
];
?>
<div class="min-h-screen flex flex-col md:flex-row">
<!-- Sidebar - Desktop Only -->
<aside class="hidden md:flex w-72 glass-sidebar border-r border-slate-200 flex-col sticky top-0 h-screen no-print z-50">
<div class="p-8 border-b border-slate-100/50">
<div class="flex items-center gap-2 mb-2">
<div class="bg-indigo-600 text-white w-8 h-8 rounded-lg flex items-center justify-center font-black text-xs shadow-lg shadow-indigo-200">SAM</div>
<span class="font-extrabold text-slate-800 tracking-tight text-lg">KoDATA Plan</span>
</div>
<p class="text-[10px] text-slate-400 font-bold uppercase tracking-[0.2em]">Internal Guideline</p>
</div>
<nav class="flex-1 p-6 space-y-8 overflow-y-auto">
<div>
<p class="px-3 mb-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Main Overview</p>
<a href="#overview" class="flex items-center gap-3 px-4 py-3 text-sm font-semibold text-slate-600 hover:bg-white hover:text-indigo-600 rounded-xl transition-all hover:shadow-sm group">
<i data-lucide="info" class="w-4 h-4 text-slate-400 group-hover:text-indigo-600"></i>
인터뷰 개요
</a>
</div>
<div>
<p class="px-3 mb-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Questions</p>
<div class="space-y-1">
<?php foreach ($SECTIONS as $section): ?>
<a href="#<?php echo $section['id']; ?>" class="flex items-center gap-3 px-4 py-3 text-sm font-semibold text-slate-600 hover:bg-white hover:text-indigo-600 rounded-xl transition-all hover:shadow-sm group">
<i data-lucide="<?php echo $section['icon']; ?>" class="w-4 h-4 text-slate-300 group-hover:text-indigo-400"></i>
<?php echo str_replace(['. ', 'Ⅱ. ', 'Ⅲ. ', 'Ⅳ. '], '', $section['title']); ?>
</a>
<?php endforeach; ?>
</div>
</div>
<div>
<p class="px-3 mb-4 text-[10px] font-black text-slate-400 uppercase tracking-widest">Strategy</p>
<a href="#tips" class="flex items-center gap-3 px-4 py-3 text-sm font-semibold text-slate-600 hover:bg-white hover:text-indigo-600 rounded-xl transition-all hover:shadow-sm group">
<i data-lucide="lightbulb" class="w-4 h-4 text-amber-400"></i>
협상 전략 및 팁
</a>
</div>
</nav>
<div class="p-6 border-t border-slate-100 bg-slate-50/50">
<div class="flex items-center gap-3 p-4 bg-white border border-slate-200 rounded-2xl shadow-sm">
<div class="w-10 h-10 rounded-full bg-gradient-to-tr from-indigo-500 to-primary-400 flex items-center justify-center text-white font-black text-sm shadow-md">JD</div>
<div>
<p class="text-xs font-black text-slate-900 leading-tight">SAM Lead</p>
<p class="text-[10px] text-slate-400 font-bold uppercase mt-0.5">Project Manager</p>
</div>
</div>
</div>
</aside>
<!-- Main Content Area -->
<main class="flex-1 flex flex-col min-w-0">
<header class="sticky top-0 z-40 flex h-20 items-center justify-between border-b border-slate-200 glass-header px-8 no-print">
<h2 class="text-sm font-black text-slate-800 truncate uppercase tracking-widest flex items-center gap-3">
<span class="w-2 h-2 rounded-full bg-indigo-500 animate-pulse"></span>
KoDATA EW API Interview Dashboard
</h2>
<div class="flex items-center gap-4">
<button class="p-2.5 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-xl transition-all">
<i data-lucide="share-2" class="w-5 h-5"></i>
</button>
<button
onclick="window.print()"
class="flex items-center gap-2.5 px-6 py-3 bg-slate-900 text-white rounded-xl text-sm font-black hover:bg-slate-800 transition-all shadow-xl shadow-slate-200 active:scale-95"
>
<i data-lucide="printer" class="w-4 h-4"></i>
PDF 출력
</button>
</div>
</header>
<div class="flex-1 p-8 sm:p-12 max-w-5xl mx-auto w-full space-y-20">
<!-- Hero / Overview -->
<div id="overview" class="relative overflow-hidden rounded-[32px] bg-slate-900 p-10 sm:p-16 shadow-2xl shadow-indigo-100 scroll-mt-32">
<div class="absolute top-0 right-0 p-12 opacity-5 pointer-events-none">
<i data-lucide="package" class="w-64 h-64 text-white rotate-12"></i>
</div>
<div class="relative z-10 space-y-8">
<div class="inline-flex items-center gap-2.5 px-4 py-2 bg-indigo-500/10 text-indigo-300 rounded-full text-xs font-black border border-indigo-500/20 uppercase tracking-widest">
<i data-lucide="calendar" class="w-3.5 h-3.5"></i>
<?php echo $MEETING_OVERVIEW['date']; ?>
</div>
<div class="space-y-4">
<h1 class="text-4xl sm:text-6xl font-black text-white leading-[1.15] tracking-tight">
KoDATA EW 리포트 <br />
<span class="text-transparent bg-clip-text bg-gradient-to-r from-indigo-400 to-primary-400">인터뷰 계획안</span>
</h1>
<p class="text-slate-400 max-w-2xl text-xl font-medium leading-[1.6]">
비용 효율성과 데이터 활용의 법적 안정성을 최우선으로 고려한 <br class="hidden sm:block" />
SAM 프로젝트의 데이터 소싱 가이드라인입니다.
</p>
</div>
<div class="grid sm:grid-cols-2 gap-6 pt-6">
<div class="bg-white/5 backdrop-blur-md border border-white/10 rounded-3xl p-6 flex items-start gap-4 hover:bg-white/10 transition-all duration-300">
<div class="p-3 bg-indigo-500/20 rounded-2xl text-indigo-400">
<i data-lucide="user" class="w-6 h-6"></i>
</div>
<div>
<p class="text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] mb-1">미팅 대상</p>
<p class="text-white text-lg font-bold"><?php echo $MEETING_OVERVIEW['target']; ?></p>
</div>
</div>
<div class="bg-white/5 backdrop-blur-md border border-white/10 rounded-3xl p-6 flex items-start gap-4 hover:bg-white/10 transition-all duration-300">
<div class="p-3 bg-indigo-500/20 rounded-2xl text-indigo-400">
<i data-lucide="target" class="w-6 h-6"></i>
</div>
<div>
<p class="text-[10px] font-black text-slate-500 uppercase tracking-[0.2em] mb-1">주요 목적</p>
<ul class="text-white font-bold text-base space-y-1">
<?php foreach ($MEETING_OVERVIEW['purpose'] as $purpose): ?>
<li class="flex items-center gap-2">
<span class="w-1 h-1 bg-indigo-500 rounded-full"></span>
<?php echo $purpose; ?>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Stats Summary -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-6">
<?php
$stats = [
['label' => '총 질문수', 'value' => '13건', 'color' => 'text-slate-900', 'bg' => 'bg-white'],
['label' => '필수 항목', 'value' => '6건', 'color' => 'text-rose-600', 'bg' => 'bg-rose-50/50'],
['label' => '미팅 시간', 'value' => '오전(90m)', 'color' => 'text-slate-900', 'bg' => 'bg-white'],
['label' => '전략 우선순위', 'value' => '비용/법무', 'color' => 'text-indigo-600', 'bg' => 'bg-indigo-50/50'],
];
foreach ($stats as $stat): ?>
<div class="<?php echo $stat['bg']; ?> p-8 rounded-[32px] border border-slate-200 shadow-sm stat-card">
<p class="text-[10px] font-black text-slate-400 uppercase tracking-[0.2em] mb-2"><?php echo $stat['label']; ?></p>
<p class="text-3xl font-black <?php echo $stat['color']; ?>"><?php echo $stat['value']; ?></p>
</div>
<?php endforeach; ?>
</div>
<!-- Sections -->
<div class="space-y-24">
<?php foreach ($SECTIONS as $section): ?>
<section id="<?php echo $section['id']; ?>" class="scroll-mt-32">
<div class="flex items-center justify-between mb-8 group">
<div class="flex items-center gap-5">
<div class="p-4 rounded-3xl bg-white shadow-xl shadow-slate-200/50 group-hover:scale-110 transition-transform duration-300">
<i data-lucide="<?php echo $section['icon']; ?>" class="w-8 h-8 text-indigo-600"></i>
</div>
<div>
<h3 class="text-3xl font-black text-slate-900 leading-tight"><?php echo $section['title']; ?></h3>
<p class="text-xs text-slate-400 font-bold uppercase tracking-[0.2em] mt-1"><?php echo $section['subtitle']; ?></p>
</div>
</div>
<div class="hidden sm:block h-[2px] flex-1 mx-8 bg-slate-100 rounded-full"></div>
</div>
<div class="grid gap-6">
<?php foreach ($section['questions'] as $idx => $q): ?>
<div class="relative group bg-white rounded-[28px] border border-slate-200 p-8 shadow-sm hover:shadow-2xl hover:shadow-indigo-100/50 hover:border-indigo-100 transition-all duration-300 question-card question-card-<?php echo $q['priority']; ?>">
<div class="flex gap-6">
<div class="shrink-0 flex items-center justify-center w-10 h-10 rounded-2xl bg-slate-50 text-xs font-black text-slate-400 border border-slate-100 group-hover:bg-indigo-600 group-hover:text-white group-hover:border-indigo-600 transition-all duration-300">
<?php echo str_pad($idx + 1, 2, '0', STR_PAD_LEFT); ?>
</div>
<div class="space-y-4 flex-1">
<p class="text-slate-700 leading-relaxed font-semibold text-lg">
<?php
$parts = explode(':', $q['text'], 2);
if (count($parts) > 1): ?>
<span class="text-slate-900 font-black relative">
<?php echo $parts[0]; ?>:
<span class="absolute bottom-0 left-0 w-full h-[6px] bg-indigo-500/10 -z-10 rounded-sm"></span>
</span>
<?php echo $parts[1]; ?>
<?php else: echo $q['text']; endif; ?>
</p>
<div class="flex items-center gap-4">
<?php if ($q['priority'] === 'high'): ?>
<span class="inline-flex items-center gap-1.5 px-3 py-1 bg-rose-50 text-rose-600 rounded-full text-[10px] font-black uppercase tracking-widest border border-rose-100">
<span class="w-1 h-1 bg-rose-600 rounded-full animate-pulse"></span>
Essential
</span>
<?php endif; ?>
<button class="flex items-center gap-2 text-[10px] font-black text-slate-400 hover:text-indigo-600 transition-all uppercase tracking-widest bg-slate-50 px-3 py-1.5 rounded-lg border border-transparent hover:border-indigo-100 hover:bg-white active:scale-95">
<i data-lucide="check-circle-2" class="w-3.5 h-3.5"></i>
Check Done
</button>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</section>
<?php endforeach; ?>
<!-- Tips Section -->
<div id="tips" class="scroll-mt-32 space-y-10">
<div class="flex items-center gap-5">
<div class="p-4 rounded-3xl bg-amber-100 shadow-xl shadow-amber-100/50">
<i data-lucide="lightbulb" class="w-8 h-8 text-amber-600"></i>
</div>
<h3 class="text-3xl font-black text-slate-900">인터뷰 협상 전략 및 팁</h3>
</div>
<div class="relative overflow-hidden bg-white border border-slate-200 rounded-[40px] p-10 sm:p-14 shadow-2xl shadow-slate-200/50">
<div class="absolute top-0 right-0 p-12 opacity-[0.03] pointer-events-none">
<i data-lucide="lightbulb" class="w-48 h-48 text-amber-500"></i>
</div>
<div class="space-y-12">
<div class="relative">
<p class="text-2xl font-bold text-slate-800 leading-[1.6] italic pl-8 border-l-8 border-amber-400 py-2">
"데이터의 소유권은 KoDATA에 있지만, <span class="bg-amber-100 text-amber-900 px-2 py-0.5 rounded-lg">활용권은 SAM 프로젝트</span>에 있다"는 점을 명확히 하고, 가공된 데이터가 원본을 대체하지 않음을 강조하십시오.
</p>
</div>
<div class="grid md:grid-cols-2 gap-12">
<div class="space-y-6">
<div class="flex items-center gap-4">
<div class="p-3 bg-amber-50 rounded-2xl text-amber-600">
<i data-lucide="chef-hat" class="w-6 h-6"></i>
</div>
<h4 class="text-xl font-black text-slate-900">식재료와 레시피의 비유</h4>
</div>
<p class="text-slate-600 leading-[1.8] text-lg font-medium">
이 과정은 마치 <strong class="text-slate-900 font-black underline decoration-amber-300 underline-offset-4">고급 식재료(KoDATA 데이터)</strong>를 구매하여 <br />
우리만의 <strong class="text-slate-900 font-black underline decoration-indigo-300 underline-offset-4">레시피(SAM 프로젝트)</strong>로 요리해 <br />
손님에게 대접할 때의 과정과 같습니다.
</p>
</div>
<div class="bg-slate-50 rounded-3xl p-8 border border-slate-100 shadow-inner">
<h5 class="text-[10px] font-black text-slate-400 uppercase tracking-[0.25em] mb-6 flex items-center gap-2">
<span class="w-2 h-2 bg-amber-500 rounded-full"></span>
Core Negotiation Points
</h5>
<ul class="space-y-6">
<?php
$tips = [
"이 요리를 우리 메뉴로 팔아도 되는가? (활용권 권한 확보)",
"재료비는 얼마나 깎아줄 수 있는가? (구간별 대량 할인)",
"재료 공급이 중단될 경우 대안은? (데이터 지속성 협의)"
];
foreach ($tips as $tip): ?>
<li class="flex items-start gap-4 group">
<div class="mt-1 w-6 h-6 rounded-full bg-white flex items-center justify-center text-amber-500 shadow-sm border border-slate-100 group-hover:bg-amber-500 group-hover:text-white transition-all duration-300">
<i data-lucide="check" class="w-3.5 h-3.5"></i>
</div>
<span class="text-slate-700 font-bold text-lg group-hover:text-amber-900 transition-colors"><?php echo $tip; ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="pt-20 pb-12 border-t border-slate-200 flex flex-col sm:flex-row justify-between items-center gap-6">
<div class="flex items-center gap-3">
<div class="bg-indigo-600 text-white w-6 h-6 rounded flex items-center justify-center font-black text-[10px]">SAM</div>
<span class="text-sm font-black text-slate-400 uppercase tracking-widest">Internal Document</span>
</div>
<p class="text-sm text-slate-400 font-medium">© 2025 CodeBridge-X</p>
<div class="flex gap-4">
<div class="w-8 h-8 rounded-full bg-slate-100"></div>
<div class="w-8 h-8 rounded-full bg-slate-100"></div>
</div>
</footer>
</div>
</main>
</div>
<script>
// Initialize Lucide Icons
lucide.createIcons();
// Smooth Scroll for Navigation
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
</script>
</body>
</html>

24
kodata/ref/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

130
kodata/ref/App.tsx Normal file
View File

@@ -0,0 +1,130 @@
import React from 'react';
import Layout from './components/Layout';
import SectionCard from './components/SectionCard';
import { SECTIONS, MEETING_OVERVIEW } from './constants';
import { Calendar, User, Target, Lightbulb, ChefHat, Package } from 'lucide-react';
const App: React.FC = () => {
return (
<Layout>
<div className="max-w-4xl mx-auto space-y-12">
{/* Hero / Overview */}
<div id="overview" className="relative overflow-hidden rounded-2xl bg-slate-900 p-8 sm:p-10 shadow-xl shadow-slate-200 scroll-mt-24">
<div className="absolute top-0 right-0 p-8 opacity-10">
<Package className="w-48 h-48 text-white rotate-12" />
</div>
<div className="relative z-10 space-y-6">
<div className="inline-flex items-center gap-2 px-3 py-1 bg-indigo-500/20 text-indigo-300 rounded-full text-xs font-semibold border border-indigo-500/30">
<Calendar className="w-3 h-3" />
12 23()
</div>
<div className="space-y-2">
<h1 className="text-3xl sm:text-4xl font-extrabold text-white tracking-tight">
KoDATA EW <br className="sm:hidden" />
<span className="text-indigo-400"> </span>
</h1>
<p className="text-slate-400 max-w-xl text-lg leading-relaxed">
SAM .
</p>
</div>
<div className="grid sm:grid-cols-2 gap-4 pt-4">
<div className="bg-white/5 border border-white/10 rounded-xl p-4 flex items-start gap-3">
<User className="w-5 h-5 text-indigo-400 mt-1" />
<div>
<p className="text-xs font-bold text-slate-500 uppercase tracking-widest"> </p>
<p className="text-slate-200 font-medium">{MEETING_OVERVIEW.target}</p>
</div>
</div>
<div className="bg-white/5 border border-white/10 rounded-xl p-4 flex items-start gap-3">
<Target className="w-5 h-5 text-indigo-400 mt-1" />
<div>
<p className="text-xs font-bold text-slate-500 uppercase tracking-widest"> </p>
<ul className="text-slate-200 font-medium text-sm list-disc list-inside">
{MEETING_OVERVIEW.purpose.map((p, i) => (
<li key={i}>{p}</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
{/* Stats Summary */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{[
{ label: '총 질문수', value: '13건', color: 'text-slate-900' },
{ label: '필수 항목', value: '6건', color: 'text-rose-600' },
{ label: '미팅 시간', value: '오전 예정', color: 'text-slate-900' },
{ label: '전략 우선순위', value: '비용/법무', color: 'text-indigo-600' },
].map((stat, i) => (
<div key={i} className="bg-white p-4 rounded-xl border border-slate-200 shadow-sm">
<p className="text-[10px] font-bold text-slate-400 uppercase tracking-widest mb-1">{stat.label}</p>
<p className={`text-xl font-bold ${stat.color}`}>{stat.value}</p>
</div>
))}
</div>
{/* Sections */}
<div className="space-y-12">
{SECTIONS.map((section) => (
<SectionCard key={section.id} section={section} />
))}
</div>
{/* Tips Section */}
<div id="tips" className="scroll-mt-24 space-y-6">
<div className="flex items-center gap-2 mb-4">
<Lightbulb className="w-6 h-6 text-amber-500" />
<h3 className="text-2xl font-bold text-slate-800"> </h3>
</div>
<div className="bg-amber-50 border border-amber-100 rounded-2xl p-6 sm:p-8 space-y-6 shadow-sm">
<p className="text-amber-900 font-medium leading-relaxed italic border-l-4 border-amber-300 pl-4">
"데이터의 소유권은 KoDATA에 있지만, 활용권은 SAM 프로젝트에 있다" , KoDATA의 .
</p>
<div className="grid sm:grid-cols-2 gap-6 pt-4">
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="p-2 bg-amber-200 rounded-lg text-amber-800">
<ChefHat className="w-5 h-5" />
</div>
<h4 className="font-bold text-amber-900"> </h4>
</div>
<p className="text-sm text-amber-800/80 leading-relaxed">
<strong> (KoDATA )</strong> <strong>(SAM )</strong> .
</p>
</div>
<div className="space-y-3 bg-white/50 p-4 rounded-xl border border-amber-200/50">
<h5 className="text-xs font-bold text-amber-900 uppercase tracking-wider flex items-center gap-2">
<span className="w-1 h-1 bg-amber-500 rounded-full"></span>
</h5>
<ul className="space-y-2">
{[
"이 요리를 우리 메뉴로 팔아도 되는가? (활용권)",
"재료비는 얼마나 깎아줄 수 있는가? (대량 할인)",
"재료 공급이 중단될 경우 대안은? (연속성)"
].map((item, idx) => (
<li key={idx} className="text-sm text-amber-900 flex gap-2">
<span className="text-amber-500 shrink-0"></span>
{item}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
</div>
</Layout>
);
};
export default App;

20
kodata/ref/README.md Normal file
View File

@@ -0,0 +1,20 @@
<div align="center">
<img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
</div>
# Run and deploy your AI Studio app
This contains everything you need to run your app locally.
View your app in AI Studio: https://ai.studio/apps/drive/1sjPYpIWhj0KUSRKJ2WG-5kA8vh1bo9KF
## Run Locally
**Prerequisites:** Node.js
1. Install dependencies:
`npm install`
2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
3. Run the app:
`npm run dev`

View File

@@ -0,0 +1,98 @@
import React from 'react';
import { Calendar, User, Target, ChevronRight, Printer, Share2, Info } from 'lucide-react';
import { MEETING_OVERVIEW } from '../constants';
interface LayoutProps {
children: React.ReactNode;
}
const Layout: React.FC<LayoutProps> = ({ children }) => {
return (
<div className="min-h-screen flex flex-col md:flex-row">
{/* Sidebar - Desktop Only */}
<aside className="hidden md:flex w-72 bg-white border-r border-slate-200 flex-col sticky top-0 h-screen">
<div className="p-6 border-b border-slate-100">
<div className="flex items-center gap-2 mb-1">
<span className="bg-indigo-600 text-white p-1 rounded font-bold text-sm">SAM</span>
<span className="font-bold text-slate-800 tracking-tight">Project Dashboard</span>
</div>
<p className="text-xs text-slate-500 font-medium">Internal Interview Plan</p>
</div>
<nav className="flex-1 p-4 space-y-1 overflow-y-auto">
<p className="px-3 py-2 text-[10px] font-bold text-slate-400 uppercase tracking-widest">Outline</p>
<a href="#overview" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors group">
<Info className="w-4 h-4 text-slate-400 group-hover:text-indigo-600" />
</a>
<p className="px-3 py-2 pt-6 text-[10px] font-bold text-slate-400 uppercase tracking-widest">Questionnaire</p>
<a href="#cost" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors">
<div className="w-1.5 h-1.5 rounded-full bg-blue-500"></div>
</a>
<a href="#legal" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors">
<div className="w-1.5 h-1.5 rounded-full bg-emerald-500"></div>
</a>
<a href="#continuity" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors">
<div className="w-1.5 h-1.5 rounded-full bg-amber-500"></div>
</a>
<a href="#technical" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors">
<div className="w-1.5 h-1.5 rounded-full bg-slate-400"></div>
</a>
<p className="px-3 py-2 pt-6 text-[10px] font-bold text-slate-400 uppercase tracking-widest">Strategy</p>
<a href="#tips" className="flex items-center gap-3 px-3 py-2 text-sm font-medium text-slate-600 hover:bg-slate-50 hover:text-indigo-600 rounded-md transition-colors">
<ChevronRight className="w-4 h-4" />
</a>
</nav>
<div className="p-4 border-t border-slate-100 bg-slate-50">
<div className="flex items-center gap-3 p-3 bg-white border border-slate-200 rounded-lg shadow-sm">
<div className="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-700 font-bold text-xs">JD</div>
<div>
<p className="text-xs font-bold text-slate-800">SAM Lead</p>
<p className="text-[10px] text-slate-500">Project Manager</p>
</div>
</div>
</div>
</aside>
{/* Main Content Area */}
<main className="flex-1 flex flex-col min-w-0">
<header className="sticky top-0 z-30 flex h-16 items-center justify-between border-b bg-white/80 px-6 backdrop-blur-md">
<h2 className="text-sm font-semibold text-slate-800 truncate">
KoDATA EW API
</h2>
<div className="flex items-center gap-3">
<button className="p-2 text-slate-500 hover:bg-slate-100 rounded-lg transition-colors">
<Share2 className="w-4 h-4" />
</button>
<button
onClick={() => window.print()}
className="flex items-center gap-2 px-3 py-1.5 bg-indigo-600 text-white rounded-lg text-sm font-medium hover:bg-indigo-700 transition-colors shadow-sm shadow-indigo-200"
>
<Printer className="w-4 h-4" />
<span className="hidden sm:inline">PDF </span>
</button>
</div>
</header>
<div className="flex-1 overflow-y-auto p-4 sm:p-8 space-y-8">
{children}
<footer className="pt-12 pb-6 border-t border-slate-200 text-center">
<p className="text-sm text-slate-400">© 2024 SAM Project - Internal Use Only</p>
</footer>
</div>
</main>
</div>
);
};
export default Layout;

View File

@@ -0,0 +1,81 @@
import React from 'react';
import { CreditCard, ShieldCheck, RefreshCcw, Cpu, LucideIcon, CheckCircle2 } from 'lucide-react';
import { Section } from '../types';
const IconMap: Record<string, LucideIcon> = {
CreditCard,
ShieldCheck,
RefreshCcw,
Cpu,
};
interface SectionCardProps {
section: Section;
}
const SectionCard: React.FC<SectionCardProps> = ({ section }) => {
const Icon = IconMap[section.icon] || Cpu;
const getPriorityColor = (priority: string) => {
switch (priority) {
case 'high': return 'border-l-4 border-l-rose-500';
case 'medium': return 'border-l-4 border-l-amber-500';
default: return 'border-l-4 border-l-slate-300';
}
};
return (
<section id={section.id} className="scroll-mt-24">
<div className="flex items-center gap-3 mb-4">
<div className={`p-2 rounded-lg ${section.id === 'cost' ? 'bg-blue-100 text-blue-600' : section.id === 'legal' ? 'bg-emerald-100 text-emerald-600' : section.id === 'continuity' ? 'bg-amber-100 text-amber-600' : 'bg-slate-100 text-slate-600'}`}>
<Icon className="w-5 h-5" />
</div>
<div>
<h3 className="text-lg font-bold text-slate-800">{section.title}</h3>
<p className="text-xs text-slate-400 font-medium tracking-wide uppercase">{section.subtitle}</p>
</div>
</div>
<div className="grid gap-3">
{section.questions.map((q, idx) => (
<div
key={q.id}
className={`group bg-white rounded-xl border border-slate-200 p-5 shadow-sm hover:shadow-md hover:border-indigo-200 transition-all ${getPriorityColor(q.priority)}`}
>
<div className="flex gap-4">
<div className="shrink-0 flex items-center justify-center w-6 h-6 rounded-full bg-slate-50 text-[10px] font-bold text-slate-400 border border-slate-100 group-hover:bg-indigo-50 group-hover:text-indigo-500 group-hover:border-indigo-100 transition-colors">
{idx + 1}
</div>
<div className="space-y-2 flex-1">
<p className="text-slate-700 leading-relaxed font-medium">
{q.text.split(':').length > 1 ? (
<>
<span className="text-slate-900 font-bold underline decoration-indigo-200 underline-offset-4">{q.text.split(':')[0]}:</span>
{q.text.split(':')[1]}
</>
) : q.text}
</p>
<div className="flex items-center gap-4 pt-1">
{q.priority === 'high' && (
<span className="flex items-center gap-1 text-[10px] font-bold bg-rose-50 text-rose-600 px-2 py-0.5 rounded-full uppercase tracking-tight">
Essential
</span>
)}
<div className="flex gap-2">
<button className="flex items-center gap-1.5 text-xs text-slate-400 hover:text-emerald-600 transition-colors">
<CheckCircle2 className="w-3.5 h-3.5" />
</button>
</div>
</div>
</div>
</div>
</div>
))}
</div>
</section>
);
};
export default SectionCard;

62
kodata/ref/constants.tsx Normal file
View File

@@ -0,0 +1,62 @@
import React from 'react';
import { Section, MeetingOverview } from './types';
import { CreditCard, ShieldCheck, RefreshCcw, Cpu } from 'lucide-react';
export const MEETING_OVERVIEW: MeetingOverview = {
date: '2024년 12월 23일 (화) 오전',
target: 'KoDATA 영업 및 기술 담당자',
purpose: [
'EW 리포트 API 도입 비용 산정',
'데이터 가공 및 재제공에 따른 법적 리스크 점검',
'서비스 종료 이슈 대응'
]
};
export const SECTIONS: Section[] = [
{
id: 'cost',
title: '. 비용 및 계약 조건',
subtitle: 'Cost Efficiency & Terms',
icon: 'CreditCard',
questions: [
{ id: 'c1', category: 'cost', text: '과금 체계: EW 리포트 API 호출 시 건당 과금 방식인지, 아니면 정액제인지 명확한 기준은 무엇입니까?', priority: 'high' },
{ id: 'c2', category: 'cost', text: 'API 방식별 차등: VALUE(JSON/XML) 방식과 WEB API(HTML/URL) 방식 간에 이용료 차이가 존재합니까?', priority: 'high' },
{ id: 'c3', category: 'cost', text: '대량 호출 할인: SAM 프로젝트 규모에 따라 호출량이 늘어날 경우 적용 가능한 슬라이딩 단가제(구간별 할인)가 있습니까?', priority: 'medium' },
{ id: 'c4', category: 'cost', text: '유지보수비: API 연동 이후 발생하는 별도의 기술 지원료나 유지보수 비용이 포함됩니까?', priority: 'medium' }
]
},
{
id: 'legal',
title: 'Ⅱ. 데이터 가공 및 법적 리스크',
subtitle: 'Legal Stability & Usage Rights',
icon: 'ShieldCheck',
questions: [
{ id: 'l1', category: 'legal', text: '데이터 가공 권한: VALUE 방식을 통해 받은 JSON 데이터를 SAM 프로젝트의 UI에 맞춰 재가공하거나, 다른 지표와 결합하여 새로운 인사이트를 도출해 제공하는 것이 저작권법상 허용됩니까?', priority: 'high' },
{ id: 'l2', category: 'legal', text: '재제공 범위: KoDATA에서 제공하는 EW등급, 등급산출사유 등의 정보를 SAM 프로젝트 사용자(제3자)에게 열람하게 하는 것이 계약상 위반 소지가 없습니까?', priority: 'high' },
{ id: 'l3', category: 'legal', text: '데이터 저장: API로 호출한 기업 개요, 재무 정보, 연체 정보 등을 당사 DB에 영구적 또는 일시적으로 저장하여 리포트 이력 관리용으로 사용할 수 있습니까?', priority: 'medium' },
{ id: 'l4', category: 'legal', text: '법적 책임 소재: KoDATA 제공 데이터의 오류로 인해 SAM 프로젝트 사용자가 의사결정 손실을 보았을 경우, 법적 책임의 한계와 면책 조항은 어떻게 됩니까?', priority: 'high' }
]
},
{
id: 'continuity',
title: 'Ⅲ. 서비스 종료 및 연속성 대응',
subtitle: 'Business Continuity',
icon: 'RefreshCcw',
questions: [
{ id: 's1', category: 'continuity', text: "종료 사유 및 영향: 2026년 2월 27일 종료 예정인 '기업신용안심서비스'의 종료 사유가 API 서비스의 품질 저하나 데이터 공급 중단과 관련이 있습니까?", priority: 'medium' },
{ id: 's2', category: 'continuity', text: "대체 서비스: 서비스 종료 공지에서 언급된 '더 좋은 서비스'가 현재 SAM 프로젝트에서 검토 중인 EW 리포트 API와 어떤 차별점이 있습니까?", priority: 'medium' },
{ id: 's3', category: 'continuity', text: '전환 지원: 만약 향후 API 사양이나 서비스 체계가 변경될 경우, SAM 프로젝트가 중단 없이 운영될 수 있도록 하는 마이그레이션 지원 대책이 있습니까?', priority: 'medium' }
]
},
{
id: 'technical',
title: 'Ⅳ. 기술적 활용 상세',
subtitle: 'Technical Integration',
icon: 'Cpu',
questions: [
{ id: 't1', category: 'technical', text: '항목 선택: VALUE 방식을 선택할 경우, EW등급 외에 단기연체(신용정보원), 휴폐업정보 등 필요한 항목만 선별하여 단가를 낮추는 구성이 가능합니까?', priority: 'medium' },
{ id: 't2', category: 'technical', text: "'VALUE API 목록WEB' 방식 사용 시 HTML에 인코딩된 CSS가 SAM 프로젝트의 기존 스타일과 충돌할 가능성에 대해 기술적 가이드를 제공합니까?", priority: 'low' }
]
}
];

29
kodata/ref/index.html Normal file
View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SAM Project | KoDATA Interview Plan</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
</style>
<script type="importmap">
{
"imports": {
"react/": "https://esm.sh/react@^19.2.3/",
"react": "https://esm.sh/react@^19.2.3",
"lucide-react": "https://esm.sh/lucide-react@^0.562.0",
"react-dom/": "https://esm.sh/react-dom@^19.2.3/"
}
}
</script>
<link rel="stylesheet" href="/index.css">
</head>
<body class="bg-slate-50 text-slate-900">
<div id="root"></div>
<script type="module" src="/index.tsx"></script>
</body>
</html>

16
kodata/ref/index.tsx Normal file
View File

@@ -0,0 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
if (!rootElement) {
throw new Error("Could not find root element to mount to");
}
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

5
kodata/ref/metadata.json Normal file
View File

@@ -0,0 +1,5 @@
{
"name": "SAM-KoDATA-Interview-Planner",
"description": "A sophisticated interview planning dashboard for the SAM project's KoDATA EW Report API integration, focusing on cost efficiency and legal stability.",
"requestFramePermissions": []
}

22
kodata/ref/package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "sam-kodata-interview-planner",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.2.3",
"lucide-react": "^0.562.0",
"react-dom": "^19.2.3"
},
"devDependencies": {
"@types/node": "^22.14.0",
"@vitejs/plugin-react": "^5.0.0",
"typescript": "~5.8.2",
"vite": "^6.2.0"
}
}

29
kodata/ref/tsconfig.json Normal file
View File

@@ -0,0 +1,29 @@
{
"compilerOptions": {
"target": "ES2022",
"experimentalDecorators": true,
"useDefineForClassFields": false,
"module": "ESNext",
"lib": [
"ES2022",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
"types": [
"node"
],
"moduleResolution": "bundler",
"isolatedModules": true,
"moduleDetection": "force",
"allowJs": true,
"jsx": "react-jsx",
"paths": {
"@/*": [
"./*"
]
},
"allowImportingTsExtensions": true,
"noEmit": true
}
}

21
kodata/ref/types.ts Normal file
View File

@@ -0,0 +1,21 @@
export interface Question {
id: string;
text: string;
category: string;
priority: 'high' | 'medium' | 'low';
}
export interface Section {
id: string;
title: string;
subtitle: string;
icon: string;
questions: Question[];
}
export interface MeetingOverview {
date: string;
target: string;
purpose: string[];
}