Files
sam-kd/strategy/KoreaCardApiReport.php
hskwon aca1767eb9 초기 커밋: 5130 레거시 시스템
- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경
- DB 연결 하드코딩 → .env 기반으로 변경
- MySQL strict mode DATE 오류 수정
2025-12-10 20:14:31 +09:00

432 lines
23 KiB
PHP

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>분석 리포트: 한국 카드사 API 폐쇄성의 원인</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap');
body { font-family: 'Noto Sans KR', sans-serif; }
/* Chart Container Styles - Mandatory Compliance */
.chart-container {
position: relative;
width: 100%;
max-width: 600px; /* Max width to prevent excessive stretching */
height: 350px; /* Base height */
max-height: 400px;
margin-left: auto;
margin-right: auto;
}
@media (min-width: 768px) {
.chart-container {
height: 400px;
}
}
.card-shadow {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: transform 0.2s ease-in-out;
}
.card-shadow:hover {
transform: translateY(-2px);
}
.active-tab {
border-bottom: 2px solid #1e40af;
color: #1e40af;
font-weight: 700;
}
.inactive-tab {
color: #6b7280;
}
</style>
<!-- Chosen Palette: Warm Corporate Neutral (Stone/Slate background with Indigo/Blue accents for trust and Red for risk) -->
<!-- Application Structure Plan: The app uses a "Dashboard Narrative" structure.
1. Intro: Contextualizes the frustration.
2. Interactive Factor Analysis (Polar Chart): Allows users to explore the 5 reasons non-linearly by interacting with the chart.
3. Business Logic (Bar Chart): Visualizes the Cost vs. Benefit imbalance.
4. Strategic Alternatives (Grid): Shows the current reality (MyData) vs. the request.
5. Developer Guide: Actionable takeaways.
This structure moves from "Why?" (Abstract) to "Evidence" (Data) to "Solution" (Action). -->
<!-- Visualization & Content Choices:
1. Polar Area Chart: Used to represent the "5 Core Reasons". Goal: Inform & Compare. Justification: Shows that 'Security' and 'Regulation' are the dominant factors (largest radius) compared to others. Interaction: Click segment to view details.
2. Bar Chart: Used for "Cost vs Risk". Goal: Compare. Justification: Clearly displays the massive disparity between 'Maintenance Cost/Risk' and 'Zero Revenue' for open APIs.
3. Interactive Cards: For Developer Solutions. Goal: Organize. Justification: Cleanly separates the only two viable paths.
CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
</head>
<body class="bg-stone-50 text-slate-800">
<div class="container mx-auto">
<div class="mb-6 flex items-center justify-start">
<a href="<?=$root_dir?>/index.php" class="inline-flex items-center px-3 py-2 rounded-lg hover:bg-amber-100 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 md:w-8 md:h-8 text-amber-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 11.5L12 4l9 7.5M5 10v8a1 1 0 001 1h3.5a1 1 0 001-1v-3h2v3a1 1 0 001 1H18a1 1 0 001-1v-8"/>
</svg>
<span class="ml-2 text-base md:text-lg font-semibold text-amber-700 hidden md:inline">홈으로</span>
</a>
</div>
</div>
<!-- Header / Intro Section -->
<header class="bg-white border-b border-stone-200 sticky top-0 z-50">
<div class="max-w-5xl mx-auto px-4 py-4 flex justify-between items-center">
<h1 class="text-xl font-bold text-slate-900 tracking-tight">🔒 Data Insight: 카드사 API</h1>
<span class="text-xs bg-stone-100 text-stone-600 px-2 py-1 rounded">Analysis Report</span>
</div>
</header>
<main class="max-w-5xl mx-auto px-4 py-8 space-y-12">
<!-- Hero: The Core Question -->
<section class="text-center space-y-4 animate-fade-in-up">
<h2 class="text-3xl md:text-4xl font-extrabold text-slate-900 leading-tight">
한국 카드사는<br>사용내역 API를 제공하지 않을까요?
</h2>
<p class="text-lg text-slate-600 max-w-2xl mx-auto">
많은 개발자들이 궁금해하는 질문입니다. "내 돈 쓴 내역을 내가 보겠다는데 왜?"<br>
폐쇄성의 이면에 있는 <span class="text-indigo-700 font-bold">5가지 핵심 이유</span> 데이터 시각화로 분석합니다.
</p>
</section>
<!-- Section 1: Interactive Analysis of Reasons -->
<section class="bg-white rounded-2xl p-6 md:p-8 card-shadow border border-stone-100">
<div class="mb-6">
<h3 class="text-2xl font-bold text-slate-800 flex items-center gap-2">
<span class="text-indigo-600">📊</span> 폐쇄성의 5 원인 분석
</h3>
<p class="text-slate-500 mt-2">
아래 차트의 영역을 클릭하여 카드사가 API를 개방하지 못하는(혹은 하는) 구체적인 이유를 확인하세요.
영억의 크기는 <strong>영향력(중요도)</strong> 나타냅니다.
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 items-center">
<!-- Left: Chart -->
<div class="w-full bg-stone-50 rounded-xl p-4 flex flex-col justify-center items-center">
<div class="chart-container">
<canvas id="reasonsChart"></canvas>
</div>
<p class="text-xs text-stone-400 mt-4 text-center">Data Source: 업계 분석 규제 현황</p>
</div>
<!-- Right: Dynamic Content Panel -->
<div id="detailPanel" class="h-full flex flex-col justify-center bg-indigo-50 rounded-xl p-6 border-l-4 border-indigo-500 transition-all duration-300">
<h4 id="panelTitle" class="text-xl font-bold text-indigo-900 mb-3">차트의 영역을 클릭해보세요</h4>
<p id="panelDesc" class="text-slate-700 leading-relaxed">
왼쪽 차트는 카드사가 API를 공개하지 않는 5가지 주요 원인을 보여줍니다.<br><br>
가장 영역을 차지하는 요소들이 가장 강력한 장벽입니다. 항목을 클릭하면 상세한 분석 내용이 여기에 표시됩니다.
</p>
<div id="panelTags" class="mt-4 flex flex-wrap gap-2">
<!-- Dynamic Tags -->
</div>
</div>
</div>
</section>
<!-- Section 2: Cost vs Risk Logic -->
<section>
<div class="mb-4">
<h3 class="text-xl font-bold text-slate-800">📉 리스크 대비 수익성 구조</h3>
<p class="text-sm text-slate-500">카드사가 자체 API를 운영할 발생하는 비용과 기대 수익의 불균형</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Chart Col -->
<div class="md:col-span-2 bg-white rounded-2xl p-6 card-shadow border border-stone-100">
<div class="chart-container" style="height: 300px;">
<canvas id="costChart"></canvas>
</div>
</div>
<!-- Text Col -->
<div class="md:col-span-1 bg-white rounded-2xl p-6 card-shadow border border-stone-100 flex flex-col justify-center">
<div class="space-y-4">
<div class="border-l-4 border-red-500 pl-4">
<strong class="block text-red-700">막대한 비용 & 리스크</strong>
<span class="text-sm text-slate-600">보안 사고 책임, 24시간 트래픽 방어, 인증 시스템 운영 유지 비용 과다.</span>
</div>
<div class="border-l-4 border-slate-300 pl-4">
<strong class="block text-slate-700">수익 모델 부재</strong>
<span class="text-sm text-slate-600">API를 열어줘도 카드사가 얻는 직접적인 수익은 "0" 수렴합니다.</span>
</div>
</div>
</div>
</div>
</section>
<!-- Section 3: The New Standard (MyData) -->
<section class="bg-slate-900 rounded-2xl p-8 text-white relative overflow-hidden">
<div class="relative z-10">
<h3 class="text-2xl font-bold mb-4">🏛️ 패러다임의 변화: 정부 주도 표준화</h3>
<p class="text-slate-300 mb-8 max-w-3xl">
카드사가 개별 API를 만들 필요가 사라졌습니다. 한국은 이미 정부가 통제하는 <strong>'마이데이터(MyData)'</strong> <strong>'오픈뱅킹'</strong>이라는 거대한 표준 파이프라인이 구축되었기 때문입니다.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Legacy Path -->
<div class="bg-slate-800 bg-opacity-50 p-6 rounded-xl border border-slate-700 opacity-50">
<div class="flex items-center justify-between mb-2">
<h4 class="font-bold text-lg text-slate-400">과거: 개별 연동</h4>
<span class="text-2xl">🚫</span>
</div>
<p class="text-sm text-slate-500">
개발자 카드사 (개별 계약)<br>
표준 없음, 보안 취약, 협의 어려움
</p>
</div>
<!-- Current Path -->
<div class="bg-indigo-900 bg-opacity-60 p-6 rounded-xl border border-indigo-500 shadow-lg shadow-indigo-500/20">
<div class="flex items-center justify-between mb-2">
<h4 class="font-bold text-lg text-white">현재: 마이데이터 표준</h4>
<span class="text-2xl"></span>
</div>
<p class="text-sm text-indigo-200">
개발자 정부 표준 API 모든 금융사<br>
단일 규격, 법적 보호, 강력한 보안
</p>
</div>
</div>
</div>
<!-- Decorative circle -->
<div class="absolute -top-20 -right-20 w-64 h-64 bg-indigo-600 rounded-full blur-3xl opacity-20"></div>
</section>
<!-- Section 4: Actionable Advice for Developers -->
<section>
<div class="mb-6">
<h3 class="text-xl font-bold text-slate-800">🧭 개발자를 위한 현실적인 대안</h3>
<p class="text-sm text-slate-500">그래서, 지금 카드 내역을 가져오려면 어떻게 해야 하나요?</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Option A -->
<div class="bg-white p-6 rounded-xl border border-stone-200 card-shadow hover:border-indigo-300 group cursor-pointer transition-colors" onclick="highlightOption(this)">
<div class="flex items-center gap-3 mb-4">
<span class="bg-indigo-100 text-indigo-700 px-3 py-1 rounded-full text-sm font-bold">정공법</span>
<h4 class="font-bold text-lg">마이데이터 사업자 라이선스</h4>
</div>
<ul class="space-y-2 text-sm text-slate-600">
<li class="flex items-start gap-2"><span>🔹</span> 자본금 물적 보안 설비 필수</li>
<li class="flex items-start gap-2"><span>🔹</span> 금융보안원 보안 심사 통과</li>
<li class="flex items-start gap-2"><span>🔹</span> <strong>장점:</strong> 가장 안정적이고 합법적인 데이터 확보</li>
<li class="flex items-start gap-2"><span>🔻</span> <strong>단점:</strong> 초기 스타트업에게 진입장벽 매우 높음</li>
</ul>
</div>
<!-- Option B -->
<div class="bg-white p-6 rounded-xl border border-stone-200 card-shadow hover:border-indigo-300 group cursor-pointer transition-colors" onclick="highlightOption(this)">
<div class="flex items-center gap-3 mb-4">
<span class="bg-stone-100 text-stone-700 px-3 py-1 rounded-full text-sm font-bold">우회 전략</span>
<h4 class="font-bold text-lg">플랫폼 제휴 (토스/뱅크샐러드 )</h4>
</div>
<ul class="space-y-2 text-sm text-slate-600">
<li class="flex items-start gap-2"><span>🔹</span> 이미 라이선스가 있는 기업의 API 이용</li>
<li class="flex items-start gap-2"><span>🔹</span> 내부 파트너십 계약 필요</li>
<li class="flex items-start gap-2"><span>🔹</span> <strong>장점:</strong> 직접 인프라 구축 불필요</li>
<li class="flex items-start gap-2"><span>🔻</span> <strong>단점:</strong> 일반적인 오픈 API 형태가 아님 (B2B 계약)</li>
</ul>
</div>
</div>
</section>
<footer class="text-center text-sm text-slate-400 py-8 border-t border-stone-200 mt-8">
<p>© 2024 Financial Tech Insights. Source Data: Industry Report Analysis.</p>
</footer>
</main>
<script>
// Data Store
const reasonData = {
labels: ['금융보안 규제', '비용 및 리스크', '레거시 시스템', '정부 주도 대안', '폐쇄적 전략'],
datasets: [{
label: '영향력 점수 (100점 만점)',
data: [95, 85, 70, 90, 60],
backgroundColor: [
'rgba(220, 38, 38, 0.7)', // Red for Regulation (High Alert)
'rgba(234, 88, 12, 0.7)', // Orange for Cost
'rgba(100, 116, 139, 0.7)', // Slate for Legacy
'rgba(79, 70, 229, 0.7)', // Indigo for Gov/Alt
'rgba(16, 185, 129, 0.7)' // Green for Strategy
],
borderColor: [
'rgba(220, 38, 38, 1)',
'rgba(234, 88, 12, 1)',
'rgba(100, 116, 139, 1)',
'rgba(79, 70, 229, 1)',
'rgba(16, 185, 129, 1)'
],
borderWidth: 1
}],
details: {
0: {
title: "1. 금융보안 규제 (핵심)",
desc: "한국은 금융보안과 개인정보 규제가 세계적으로 가장 강력합니다. 카드 내역은 '금융거래정보'와 '민감 개인정보'가 결합된 최상위 보안 등급 데이터입니다. 이를 외부에 열었다가 보안 사고가 발생할 경우, 카드사는 감당하기 힘든 법적 책임과 제재를 받게 됩니다.",
tags: ["#금융보안원심사", "#망분리", "#실시간암호화", "#책임소재"]
},
1: {
title: "2. 리스크 대비 비용 과다",
desc: "API를 공개하려면 인증 시스템, 트래픽 방어, 24시간 보안 관제, 외부 개발자 지원 등 막대한 비용이 듭니다. 반면, API를 공개한다고 해서 카드사가 얻는 직접적인 수익은 거의 없습니다. 'High Risk, No Return' 구조입니다.",
tags: ["#운영비용", "#수익모델부재", "#사고리스크"]
},
2: {
title: "3. 노후화된 레거시 시스템",
desc: "많은 카드사 시스템이 오래된 메인프레임 구조에 기반하고 있습니다. 내부 시스템 자체가 최신 API 연동에 친화적이지 않으며, 외부 연동을 위한 개발 민첩성이 부족합니다.",
tags: ["#메인프레임", "#개발유연성부족", "#구형인프라"]
},
3: {
title: "4. 이미 존재하는 정부 대안",
desc: "한국에는 이미 '오픈뱅킹'과 '마이데이터'라는 정부 주도의 강력한 표준 API가 존재합니다. 카드사 입장에서는 '우리가 굳이 따로 만들 필요 없이, 정부 표준 API를 쓰면 된다'는 명분이 확실합니다.",
tags: ["#마이데이터", "#오픈뱅킹", "#국가표준"]
},
4: {
title: "5. 플랫폼화 의지 부족",
desc: "네이버나 토스 같은 테크 기업과 달리, 카드사는 독자적인 폐쇄 생태계를 유지하여 고객을 묶어두는 것(Lock-in)을 선호합니다. 데이터를 외부에 공유해 경쟁사를 키워줄 이유가 없다고 판단합니다.",
tags: ["#고객락인", "#폐쇄적생태계", "#경쟁방지"]
}
}
};
// Chart 1: Polar Area Chart (Reasons)
const ctxReasons = document.getElementById('reasonsChart').getContext('2d');
const reasonsChart = new Chart(ctxReasons, {
type: 'polarArea',
data: {
labels: reasonData.labels,
datasets: reasonData.datasets
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
r: {
pointLabels: {
display: true,
centerPointLabels: true,
font: {
size: 12,
family: "'Noto Sans KR', sans-serif"
}
},
ticks: { display: false } // Hide numbers on scale for cleaner look
}
},
plugins: {
legend: {
position: 'bottom',
labels: { font: { family: "'Noto Sans KR', sans-serif" } }
},
tooltip: {
callbacks: {
label: function(context) {
return context.label + ": 영향력 " + context.raw;
}
}
}
},
onClick: (event, elements) => {
if (elements.length > 0) {
const index = elements[0].index;
updateDetailPanel(index);
}
}
}
});
// Update Panel Logic
function updateDetailPanel(index) {
const data = reasonData.details[index];
const panel = document.getElementById('detailPanel');
const title = document.getElementById('panelTitle');
const desc = document.getElementById('panelDesc');
const tagsDiv = document.getElementById('panelTags');
// Animation Reset
panel.classList.remove('bg-indigo-50', 'border-indigo-500');
void panel.offsetWidth; // Trigger reflow
panel.classList.add('bg-white', 'border-l-4', 'border-indigo-600', 'shadow-md');
// Content Update
title.textContent = data.title;
desc.textContent = data.desc;
// Tags Update
tagsDiv.innerHTML = '';
data.tags.forEach(tag => {
const span = document.createElement('span');
span.className = 'bg-stone-100 text-stone-600 px-2 py-1 rounded text-xs font-semibold border border-stone-200';
span.textContent = tag;
tagsDiv.appendChild(span);
});
}
// Initialize with first item
updateDetailPanel(0);
// Chart 2: Cost vs Benefit (Bar Chart)
const ctxCost = document.getElementById('costChart').getContext('2d');
new Chart(ctxCost, {
type: 'bar',
data: {
labels: ['보안/운영 비용', '잠재적 사고 리스크', 'API 공개 직접 수익'],
datasets: [{
label: '추정 규모',
data: [90, 85, 5],
backgroundColor: [
'rgba(234, 88, 12, 0.8)', // High Cost
'rgba(220, 38, 38, 0.8)', // High Risk
'rgba(16, 185, 129, 0.8)' // Low Revenue
],
borderWidth: 0,
borderRadius: 8
}]
},
options: {
indexAxis: 'y', // Horizontal bar chart
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: function(context) {
const labels = ["매우 높음 (수십억+)", "치명적 (면허 취소급)", "없음 (0)"];
return labels[context.dataIndex];
}
}
}
},
scales: {
x: {
beginAtZero: true,
max: 100,
grid: { display: false },
ticks: { display: false }
},
y: {
grid: { display: false },
ticks: { font: { family: "'Noto Sans KR', sans-serif", weight: 'bold' } }
}
}
}
});
// Interactive List Highlight
function highlightOption(element) {
// Remove highlight from all
document.querySelectorAll('.group').forEach(el => {
el.classList.remove('border-indigo-500', 'bg-indigo-50');
el.classList.add('border-stone-200', 'bg-white');
});
// Add highlight to clicked
element.classList.remove('border-stone-200', 'bg-white');
element.classList.add('border-indigo-500', 'bg-indigo-50');
}
</script>
</body>
</html>