{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# DAT10: 데이터 마이닝 기반 공급망 재난 식별 SaaS (방산 공급망 회복력 연구)\n", "## Google Colab 실습 및 과제 수행 스타터 노트북\n", "\n", "본 노트북은 전술 통신 두절 환경에서의 야전 군수 재고 관리, CRDT 무충돌 동기화, 위변조 방지 해시 엔진, 전술 대시보드 및 HITL 워크플로우를 구현하기 위한 전체 실습 환경을 제공합니다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 0. 실습 환경 준비 및 디렉터리 생성" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 필수 패키지 설치\n", "!pip install -q jsonschema pytest pyyaml plotly\n", "\n", "# 프로젝트 디렉터리 구조 생성\n", "!mkdir -p data/schema docs src/preprocess src/models src/verification src/ui src/hitl tests configs\n", "print(\"디렉터리 생성 완료!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 01] 로컬 DB 스키마 설계 및 데이터 명세서\n", "- 산출물: `data/schema/dat10_input_schema.json`, `docs/dat10_data_spec.md`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile data/schema/dat10_input_schema.json\n", "{\n", " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", " \"title\": \"FieldLogisticsTransaction\",\n", " \"type\": \"object\",\n", " \"required\": [\"tx_id\", \"unit_id\", \"item_id\", \"tx_type\", \"quantity\", \"timestamp\", \"status\"],\n", " \"properties\": {\n", " \"tx_id\": {\n", " \"type\": \"string\",\n", " \"pattern\": \"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$\"\n", " },\n", " \"unit_id\": {\"type\": \"string\"},\n", " \"item_id\": {\"type\": \"string\"},\n", " \"tx_type\": {\"type\": \"string\", \"enum\": [\"ISSUE\", \"RECEIPT\", \"RETURN\", \"TRANSFER\"]},\n", " \"quantity\": {\"type\": \"integer\", \"minimum\": 1},\n", " \"timestamp\": {\"type\": \"string\", \"format\": \"date-time\"},\n", " \"status\": {\"type\": \"string\", \"enum\": [\"LOCAL_COMMITTED\", \"SYNC_PENDING\", \"SYNCED\", \"CONFLICT\"]}\n", " }\n", "}\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile docs/dat10_data_spec.md\n", "# DAT10 전술 군수 재고 데이터 명세서\n", "\n", "## 1. 개요\n", "전술 통신 두절 환경에서의 단말 자립형 재고 관리 표준 스키마 명세.\n", "\n", "## 2. 주요 필드 규격\n", "- `tx_id`: UUID v4 고유 식별자\n", "- `unit_id`: 부대 식별 코드\n", "- `item_id`: 군수 품목 국가재고번호(NSN)\n", "- `tx_type`: 수불 유형 (ISSUE, RECEIPT, RETURN, TRANSFER)\n", "- `quantity`: 수량 (정수형, 1 이상)\n", "- `status`: 동기화 상태" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 02] 전처리 및 로컬 SQLite 트랜잭션 모듈 구현\n", "- 산출물: `src/preprocess/dat10_preprocessor.py`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile src/preprocess/dat10_preprocessor.py\n", "import sqlite3\n", "import json\n", "from datetime import datetime\n", "\n", "class DataPreprocessor:\n", " def __init__(self, db_path=':memory:'):\n", " self.conn = sqlite3.connect(db_path)\n", " self._init_db()\n", "\n", " def _init_db(self):\n", " with self.conn:\n", " self.conn.execute('''\n", " CREATE TABLE IF NOT EXISTS tx_log (\n", " tx_id TEXT PRIMARY KEY,\n", " unit_id TEXT,\n", " item_id TEXT,\n", " tx_type TEXT,\n", " quantity INTEGER,\n", " timestamp TEXT,\n", " status TEXT\n", " )\n", " ''')\n", "\n", " def validate_and_insert(self, record):\n", " if record.get('quantity', 0) <= 0:\n", " raise ValueError(\"Quantity must be positive\")\n", " with self.conn:\n", " self.conn.execute('''\n", " INSERT INTO tx_log (tx_id, unit_id, item_id, tx_type, quantity, timestamp, status)\n", " VALUES (?, ?, ?, ?, ?, ?, ?)\n", " ''', (record['tx_id'], record['unit_id'], record['item_id'], record['tx_type'], record['quantity'], record['timestamp'], record['status']))\n", " return True\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 03] P2P/USB 재고 데이터 교환 Baseline\n", "- 산출물: `src/models/dat10_baseline_model.py`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile src/models/dat10_baseline_model.py\n", "class P2PBaselineSync:\n", " def __init__(self, node_id):\n", " self.node_id = node_id\n", " self.version_vector = {}\n", " self.store = {}\n", "\n", " def create_delta(self, target_version_vector):\n", " return {k: v for k, v in self.store.items()}\n", "\n", " def merge_delta(self, remote_delta):\n", " self.store.update(remote_delta)\n", " return len(self.store)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 04] CRDT 무충돌 동기화 및 이상 탐지기\n", "- 산출물: `src/models/dat10_advanced_detector.py`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile src/models/dat10_advanced_detector.py\n", "class AdvancedCRDTDetector:\n", " def __init__(self):\n", " self.p_counter = {}\n", " self.n_counter = {}\n", "\n", " def inc(self, item, qty):\n", " self.p_counter[item] = self.p_counter.get(item, 0) + qty\n", "\n", " def dec(self, item, qty):\n", " self.n_counter[item] = self.n_counter.get(item, 0) + qty\n", "\n", " def value(self, item):\n", " return self.p_counter.get(item, 0) - self.n_counter.get(item, 0)\n", "\n", " def detect_anomalies(self, tx_stream):\n", " anomalies = []\n", " for tx in tx_stream:\n", " if tx.get('quantity', 0) > 1000:\n", " anomalies.append({'tx_id': tx.get('tx_id'), 'risk': 'CRITICAL'})\n", " return anomalies\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 05] 위변조 방지 해시 및 데이터 무결성 검증 엔진\n", "- 산출물: `src/verification/dat10_confidence_engine.py`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile src/verification/dat10_confidence_engine.py\n", "import hashlib\n", "\n", "class ConfidenceEngine:\n", " @staticmethod\n", " def compute_hash(record, prev_hash=''):\n", " data_str = f\"{prev_hash}|{record['tx_id']}|{record['quantity']}|{record['timestamp']}\"\n", " return hashlib.sha256(data_str.encode('utf-8')).hexdigest()\n", "\n", " def evaluate_confidence(self, record, calculated_hash, expected_hash):\n", " if calculated_hash != expected_hash:\n", " return 0.0, 'LOW (TAMPERED)'\n", " return 0.95, 'HIGH (VERIFIED)'\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Mission 06] 전술 대시보드 시각화 UI\n", "- 산출물: `src/ui/dat10_dashboard.py`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%writefile src/ui/dat10_dashboard.py\n", "def render_dashboard(summary_stats):\n", " html_template = f'''\n", "
통신 상태: {'ONLINE' if summary_stats.get('online') else 'OFFLINE'}
\n", "동기화 대기 큐: {summary_stats.get('queue_len', 0)} 건
\n", "이상치 감지 건수: {summary_stats.get('anomalies', 0)} 건
\n", "