// ═══════════════════════════════════════════════════════════════════════════ // ENTERPRISE SECURITY BLUEPRINT — 기업 전체 보안 아키텍처 인터랙티브 맵 // SVG + CSS. Canvas/WebGL 미사용. 모바일은 존(zone)별 카드로 전환. // ═══════════════════════════════════════════════════════════════════════════ const TOPO_CATS = { mail: { ko:'메일 보안', en:'Email Security', ja:'メールセキュリティ', c:'#22D3EE' }, system: { ko:'시스템 보안', en:'System Security', ja:'システムセキュリティ', c:'#38BDF8' }, network: { ko:'네트워크 보안', en:'Network Security', ja:'ネットワーク', c:'#6366F1' }, endpoint: { ko:'엔드포인트 보안', en:'Endpoint Security', ja:'エンドポイント', c:'#34D399' }, data: { ko:'데이터 보안', en:'Data Security', ja:'データセキュリティ', c:'#A78BFA' }, ai: { ko:'AI & 자동화', en:'AI & Automation', ja:'AI・自動化', c:'#FB923C' }, infra: { ko:'인프라', en:'Infrastructure', ja:'インフラ', c:'#64748B' }, }; // ── 인프라 존(배경) ──────────────────────────────────────────────────────── const TOPO_ZONES = [ { k:'perimeter', x:28, y:62, w:400, h:150, ko:'경계 · DMZ', en:'PERIMETER · DMZ', ja:'境界・DMZ', c:'#6366F1' }, { k:'mailzone', x:440, y:62, w:932, h:150, ko:'메일 서비스 존', en:'MAIL SERVICE ZONE', ja:'メールゾーン', c:'#22D3EE' }, { k:'syszone', x:28, y:246, w:1344, h:352, ko:'업무 서버 존 · 시스템 보안', en:'APPLICATION SERVER ZONE · SYSTEM SECURITY', ja:'業務サーバーゾーン', c:'#38BDF8' }, { k:'netzone', x:28, y:632, w:1344, h:150, ko:'내부망 · 엔드포인트 · 관제', en:'INTERNAL NETWORK · ENDPOINT · SOC', ja:'内部網・端末・監視', c:'#6366F1' }, { k:'datazone', x:28, y:816, w:1344, h:150, ko:'데이터 존 · 백업 · 감사', en:'DATA ZONE · BACKUP · AUDIT', ja:'データゾーン', c:'#A78BFA' }, { k:'aizone', x:28, y:1000, w:1344, h:150, ko:'AI · 업무 자동화 레이어', en:'AI · AUTOMATION LAYER', ja:'AI・自動化', c:'#FB923C' }, ]; // ── 노드 (x,y = viewBox 1400×1096) ───────────────────────────────────────── const TOPO_NODES = [ // 경계 · DMZ { k:'internet', x:96, y:130, cat:'infra', ic:'globe', ko:'인터넷', en:'Internet', ja:'インターネット' }, { k:'fw', x:242, y:130, cat:'network', ic:'brick', ko:'방화벽 · IPS', en:'Firewall · IPS',ja:'FW・IPS', page:'sol_network' }, { k:'dmz', x:378, y:130, cat:'infra', ic:'zone', ko:'DMZ', en:'DMZ', ja:'DMZ' }, // 메일 서비스 존 { k:'spamout', x:520, y:130, cat:'mail', ic:'shield', ko:'SpamOut', en:'SpamOut', ja:'SpamOut', page:'sol_spamout', key:true }, { k:'mserver', x:660, y:130, cat:'infra', ic:'server', ko:'메일 서버', en:'Mail Server', ja:'メールサーバー' }, { k:'arch5', x:800, y:130, cat:'mail', ic:'archive',ko:'Arch5', en:'Arch5', ja:'Arch5', page:'sol_arch5', key:true }, { k:'users', x:940, y:130, cat:'infra', ic:'users', ko:'사용자', en:'Users', ja:'ユーザー' }, { k:'checkout', x:1080, y:130, cat:'mail', ic:'send', ko:'CheckOut', en:'CheckOut', ja:'CheckOut', page:'sol_checkout', key:true }, { k:'mailin', x:1250, y:130, cat:'ai', ic:'brain', ko:'Mail Insight', en:'Mail Insight', ja:'Mail Insight', page:'sol_mailinsight', key:true }, // 시스템 보안 — 서버 계층 { k:'websrv', x:150, y:330, cat:'infra', ic:'web', ko:'웹 서버', en:'Web Server', ja:'Webサーバー' }, { k:'was', x:296, y:330, cat:'infra', ic:'layers', ko:'WAS', en:'WAS', ja:'WAS' }, { k:'appsrv', x:442, y:330, cat:'infra', ic:'app', ko:'애플리케이션', en:'App Server', ja:'アプリサーバー' }, { k:'ad', x:596, y:330, cat:'system', ic:'tree', ko:'Active Directory', en:'Active Directory', ja:'Active Directory' }, { k:'dns', x:742, y:330, cat:'system', ic:'globe', ko:'DNS', en:'DNS', ja:'DNS' }, { k:'sysac', x:896, y:330, cat:'system', ic:'gate', ko:'서버 접근제어',en:'Server Access', ja:'サーバーアクセス制御', page:'sol_system', key:true }, { k:'monitor', x:1042, y:330, cat:'system', ic:'pulse', ko:'모니터링', en:'Monitoring', ja:'モニタリング' }, { k:'soc', x:1250, y:330, cat:'endpoint',ic:'eye', ko:'SOC 관제', en:'SOC', ja:'SOC 監視', page:'sol_mdr' }, // 시스템 보안 — 운영·통제 계층 { k:'winsrv', x:150, y:452, cat:'infra', ic:'win', ko:'Windows Server', en:'Windows Server', ja:'Windows Server' }, { k:'linuxsrv', x:296, y:452, cat:'infra', ic:'linux', ko:'Linux Server', en:'Linux Server', ja:'Linux Server' }, { k:'patch', x:442, y:452, cat:'system', ic:'patch', ko:'패치 관리', en:'Patch Mgmt', ja:'パッチ管理' }, { k:'vuln', x:596, y:452, cat:'system', ic:'bug', ko:'취약점 관리', en:'Vulnerability', ja:'脆弱性管理' }, { k:'account', x:742, y:452, cat:'system', ic:'idcard', ko:'계정 관리', en:'Account Mgmt', ja:'アカウント管理' }, { k:'privilege',x:896, y:452, cat:'system', ic:'key', ko:'권한 관리', en:'Privilege Mgmt',ja:'権限管理' }, { k:'logmgmt', x:1042, y:452, cat:'system', ic:'lines', ko:'로그 관리', en:'Log Mgmt', ja:'ログ管理' }, { k:'cce', x:1250, y:452, cat:'system', ic:'bug', ko:'SolidStep CCE',en:'SolidStep CCE', ja:'SolidStep CCE', page:'sol_cce', key:true }, { k:'cve', x:1250, y:562, cat:'system', ic:'patch', ko:'SolidStep CVE',en:'SolidStep CVE', ja:'SolidStep CVE', page:'sol_cve', key:true }, // 내부망 · 엔드포인트 { k:'ddos', x:150, y:700, cat:'network', ic:'wave', ko:'SNIPER ONE-d', en:'SNIPER ONE-d', ja:'SNIPER ONE-d', page:'sol_sniper', key:true }, { k:'vpn', x:296, y:700, cat:'network', ic:'lock', ko:'VPN · ZTNA', en:'VPN · ZTNA', ja:'VPN・ZTNA', page:'sol_network' }, { k:'nac', x:442, y:700, cat:'network', ic:'net', ko:'Genian NAC', en:'Genian NAC', ja:'Genian NAC', page:'sol_genian', key:true }, { k:'ndr', x:596, y:790, cat:'network', ic:'radar', ko:'NetWitness NDR',en:'NetWitness NDR',ja:'NetWitness NDR', page:'sol_netwitness', key:true }, { k:'switch', x:596, y:700, cat:'infra', ic:'switch', ko:'스위치', en:'Switch', ja:'スイッチ' }, { k:'pc', x:742, y:700, cat:'infra', ic:'pc', ko:'PC · 단말', en:'PC · Device', ja:'PC・端末' }, { k:'edr', x:896, y:700, cat:'endpoint',ic:'radar', ko:'EDR', en:'EDR', ja:'EDR', page:'sol_edr', key:true }, { k:'eset', x:1042, y:790, cat:'endpoint',ic:'shield', ko:'ESET PROTECT',en:'ESET PROTECT', ja:'ESET PROTECT', page:'sol_eset', key:true }, { k:'mdr', x:1042, y:700, cat:'endpoint',ic:'headset',ko:'MDR 관제', en:'MDR', ja:'MDR 監視', page:'sol_mdr', key:true }, { k:'admin', x:1250, y:700, cat:'infra', ic:'admin', ko:'보안 담당자', en:'Security Admin',ja:'セキュリティ担当' }, // 데이터 존 { k:'catchsecu',x:150, y:884, cat:'data', ic:'privacy',ko:'CatchSecu', en:'CatchSecu', ja:'CatchSecu', page:'sol_privacy', key:true }, { k:'db', x:296, y:884, cat:'infra', ic:'db', ko:'데이터베이스', en:'Database', ja:'データベース' }, { k:'dbac', x:442, y:884, cat:'data', ic:'keyhole',ko:'DBSAFER DB', en:'DBSAFER DB', ja:'DBSAFER DB', page:'sol_dbsafer', key:true }, { k:'dlp', x:596, y:884, cat:'data', ic:'outbox', ko:'DLP', en:'DLP', ja:'DLP' }, { k:'backup', x:742, y:884, cat:'data', ic:'stack', ko:'백업 · 복구', en:'Backup', ja:'バックアップ' }, { k:'audit', x:896, y:884, cat:'data', ic:'doc', ko:'감사 대응', en:'Audit', ja:'監査対応' }, { k:'cloud', x:1042, y:884, cat:'infra', ic:'cloud', ko:'클라우드', en:'Cloud', ja:'クラウド' }, // AI · 자동화 체인 { k:'aichat', x:118, y:1068, cat:'ai', ic:'bot', ko:'AI 상담', en:'AI Assistant', ja:'AI相談' }, { k:'rag', x:264, y:1068, cat:'ai', ic:'search', ko:'RAG 검색', en:'RAG Search', ja:'RAG検索' }, { k:'agent', x:410, y:1068, cat:'ai', ic:'agent', ko:'AI Agent', en:'AI Agent', ja:'AIエージェント' }, { k:'autoquote',x:556, y:1068, cat:'ai', ic:'quote', ko:'자동 견적', en:'Auto Quote', ja:'自動見積' }, { k:'autorep', x:702, y:1068, cat:'ai', ic:'chart', ko:'자동 보고서', en:'Auto Report', ja:'自動レポート' }, { k:'autoticket',x:848, y:1068, cat:'ai', ic:'ticket', ko:'자동 티켓', en:'Auto Ticket', ja:'自動チケット' }, { k:'autoresp', x:994, y:1068, cat:'ai', ic:'bolt', ko:'자동 대응', en:'Auto Response', ja:'自動対応' }, { k:'customer', x:1180, y:1068, cat:'infra', ic:'handshake',ko:'고객', en:'Customer', ja:'顧客' }, ]; const TOPO_LINKS = [ ['internet','fw'],['fw','dmz'],['dmz','spamout'],['spamout','mserver'],['mserver','arch5'],['arch5','users'],['users','checkout'],['arch5','mailin'], ['dmz','websrv'],['websrv','was'],['was','appsrv'],['appsrv','ad'],['ad','dns'],['dns','sysac'],['sysac','monitor'],['monitor','soc'], ['winsrv','patch'],['linuxsrv','patch'],['patch','vuln'],['vuln','account'],['account','privilege'],['privilege','logmgmt'],['logmgmt','monitor'],['logmgmt','cce'],['cce','cve'],['vuln','cce'],['patch','cve'], ['fw','ddos'],['ddos','vpn'],['vpn','nac'],['nac','switch'],['switch','pc'],['switch','ndr'],['ndr','soc'],['pc','edr'],['edr','mdr'],['pc','eset'],['eset','edr'],['mdr','admin'], ['catchsecu','db'],['db','dbac'],['dbac','dlp'],['dlp','backup'],['backup','audit'],['audit','cloud'], ['aichat','rag'],['rag','agent'],['agent','autoquote'],['autoquote','autorep'],['autorep','autoticket'],['autoticket','autoresp'],['autoresp','customer'], ['appsrv','db'],['pc','logmgmt'],['mailin','rag'], ]; // 데이터 흐름 — 색상별 구분 const TOPO_FLOWS = [ { id:'mail', color:'#38BDF8', label:{ko:'정상 메일',en:'Legitimate mail',ja:'正常メール'}, seq:['internet','fw','dmz','spamout','mserver','arch5','users'], dur:6.4 }, { id:'spam', color:'#F87171', label:{ko:'스팸 — 차단',en:'Spam — blocked',ja:'スパム — 遮断'}, seq:['internet','fw','dmz','spamout'], dur:3.2, block:true }, { id:'malware', color:'#FB923C', label:{ko:'악성코드 — 차단',en:'Malware — blocked',ja:'マルウェア — 遮断'}, seq:['internet','fw','dmz','spamout'], dur:3.6, block:true }, { id:'phishing', color:'#C084FC', label:{ko:'피싱 — 차단',en:'Phishing — blocked',ja:'フィッシング — 遮断'}, seq:['internet','fw','dmz','spamout'], dur:4.0, block:true }, { id:'system', color:'#38BDF8', label:{ko:'서버 접근 통제',en:'Server access control',ja:'サーバーアクセス制御'}, seq:['dmz','websrv','was','appsrv','ad','dns','sysac','monitor'], dur:7.0 }, { id:'vuln', color:'#0891B2', label:{ko:'취약점 진단',en:'Vulnerability assessment',ja:'脆弱性診断'}, seq:['patch','vuln','account','privilege','logmgmt','cce','cve'], dur:6.8 }, { id:'endpoint', color:'#6366F1', label:{ko:'단말 접속 경로',en:'Endpoint access',ja:'端末アクセス'}, seq:['fw','ddos','vpn','nac','switch','pc','edr','mdr'], dur:7.2 }, { id:'data', color:'#A78BFA', label:{ko:'데이터 보호',en:'Data protection',ja:'データ保護'}, seq:['catchsecu','db','dbac','dlp','backup','audit'], dur:6.2 }, { id:'ai', color:'#FB923C', label:{ko:'AI 자동화',en:'AI automation',ja:'AI自動化'}, seq:['aichat','rag','agent','autoquote','autorep','autoticket','autoresp','customer'], dur:7.6 }, ]; // ── AI 가이드 투어 시나리오 ──────────────────────────────────────────────── // f: 카메라가 담을 노드 / p: 패킷이 지나갈 경로 / k: 단계명 / t: AI 나레이션(HTML) const TOPO_STEPS = [ { k:{ko:'경계 방어',en:'Perimeter defense',ja:'境界防御'}, f:['internet','fw','dmz','ddos','vpn'], p:['internet','fw','dmz'], t:{ko:'모든 트래픽은 방화벽·IPS를 먼저 통과합니다. 대량 공격은 SNIPER ONE-d가 회선 앞단에서 정제하고, 외부 공개 서비스는 DMZ에 분리 배치합니다.', en:'All traffic passes the firewall and IPS first. SNIPER ONE-d scrubs volumetric attacks at the circuit edge, and public services sit isolated in the DMZ.', ja:'すべてのトラフィックはまずファイアウォール・IPSを通過します。大量攻撃はSNIPER ONE-dが回線前段で精製します。'} }, { k:{ko:'수신 메일 검사',en:'Inbound mail inspection',ja:'受信メール検査'}, f:['dmz','spamout','mserver'], p:['dmz','spamout','mserver'], t:{ko:'침해의 대부분은 메일로 들어옵니다. SpamOut이 메일 서버 앞단에서 스팸·피싱·악성 첨부를 다단계로 검사해 차단합니다.', en:'Most breaches begin with email. SpamOut inspects spam, phishing and malicious attachments ahead of the mail server and blocks them by policy.', ja:'侵害の多くはメールから始まります。SpamOutがメールサーバー前段で多段階検査し遮断します。'} }, { k:{ko:'보존과 발신 통제',en:'Retention & outbound control',ja:'保存と発信統制'}, f:['mserver','arch5','users','checkout','mailin'], p:['mserver','arch5','users','checkout'], t:{ko:'송수신 메일은 Arch5가 원본 그대로 보존해 감사·소송에 대응하고, CheckOut이 오발송과 정보 유출을 사전에 차단합니다. Mail Insight는 이 데이터를 지식DB로 전환합니다.', en:'Arch5 preserves every message intact for audit and litigation, while CheckOut stops misdelivery and data leakage before it leaves. Mail Insight turns that data into a knowledge base.', ja:'Arch5が原本を保存し、CheckOutが誤送信と情報漏えいを事前に遮断します。'} }, { k:{ko:'서버·시스템 통제',en:'Server & system control',ja:'サーバー・システム統制'}, f:['websrv','was','appsrv','ad','dns','sysac','monitor'], p:['dmz','websrv','was','appsrv','ad','sysac'], t:{ko:'업무 서버 접속 경로를 서버 접근제어로 일원화하고, 계정·권한·작업 이력을 통제합니다. 모든 상태는 모니터링 계층에서 상시 관측됩니다.', en:'Server access control consolidates every path into the application tier and governs accounts, privileges and session history — all observed by the monitoring layer.', ja:'サーバーアクセス制御で接続経路を一元化し、アカウント・権限・作業履歴を統制します。'} }, { k:{ko:'취약점 상시 진단',en:'Continuous assessment',ja:'脆弱性の常時診断'}, f:['patch','vuln','account','privilege','logmgmt','cce','cve'], p:['patch','vuln','account','privilege','logmgmt','cce'], t:{ko:'SolidStep CCE가 보안 설정 취약점을, SolidStep CVE가 알려진 취약점을 전수 진단합니다. 진단 → 조치 → 이력까지 자동으로 관리됩니다.', en:'SolidStep CCE assesses configuration weaknesses and SolidStep CVE scans known vulnerabilities across every asset — assessment, remediation and history handled automatically.', ja:'SolidStep CCEが設定脆弱性を、CVEが既知脆弱性を全数診断します。'} }, { k:{ko:'단말과 내부망',en:'Endpoints & internal network',ja:'端末と内部網'}, f:['ddos','vpn','nac','switch','pc','edr','eset','ndr','mdr','admin'], p:['vpn','nac','switch','pc','edr','mdr'], t:{ko:'Genian NAC가 네트워크에 붙는 모든 단말을 식별·통제하고, EDR·ESET PROTECT가 행위 기반으로 위협을 탐지해 즉시 격리합니다. NetWitness NDR은 풀패킷으로 사각지대를 메웁니다.', en:'Genian NAC identifies and controls every device joining the network; EDR and ESET PROTECT detect threats behaviorally and isolate them instantly. NetWitness NDR covers blind spots with full packet capture.', ja:'Genian NACが全端末を識別・統制し、EDR・ESETが挙動ベースで検知・隔離します。'} }, { k:{ko:'데이터·개인정보 보호',en:'Data & privacy protection',ja:'データ・個人情報保護'}, f:['catchsecu','db','dbac','dlp','backup','audit','cloud'], p:['catchsecu','db','dbac','dlp','backup','audit'], t:{ko:'DBSAFER DB가 DB 접근을 통제하고 모든 쿼리를 감사합니다. CatchSecu는 개인정보 수집부터 파기까지 전 주기를 자동화해 규제 대응을 지원합니다.', en:'DBSAFER DB governs database access and audits every query. CatchSecu automates the personal-data lifecycle from collection to disposal for regulatory compliance.', ja:'DBSAFER DBがDBアクセスを統制し、CatchSecuが個人情報の全周期を自動化します。'} }, { k:{ko:'AI 자동화 계층',en:'AI automation layer',ja:'AI自動化レイヤー'}, f:['aichat','rag','agent','autoquote','autorep','autoticket','autoresp','customer'], p:['aichat','rag','agent','autoquote','autorep','autoticket','autoresp','customer'], t:{ko:'문의는 AI 상담이 1차 응대하고, RAG 검색이 근거를 찾아 AI Agent가 견적·보고서·티켓·초기 대응까지 자동으로 처리합니다.', en:'AI Assistant handles first-line inquiries, RAG search retrieves grounded evidence, and the AI Agent automates quoting, reporting, ticketing and first response.', ja:'AI相談が一次対応し、RAG検索とAI Agentが見積・レポート・チケット・初期対応まで自動化します。'} }, { k:{ko:'통합 아키텍처',en:'Unified architecture',ja:'統合アーキテクチャ'}, f:null, p:['internet','fw','dmz','spamout','mserver','arch5','mailin'], t:{ko:'개별 제품이 아니라 계층이 연결된 하나의 구조로 동작합니다. 고객 환경에 맞춰 필요한 계층부터 단계적으로 구축할 수 있습니다.', en:'These are not standalone products but one connected structure of layers — you can start with the layer you need and expand in stages.', ja:'個別製品ではなく層が連結した一つの構造として動作します。必要な層から段階的に構築できます。'} }, ]; // ── 라이브 이벤트 스트림 (관제 화면 재현) ────────────────────────────────── const TOPO_EVENTS = [ { c:'#22D3EE', s:'SpamOut', m:{ko:'수신 메일 검사 완료 · 정상 전달',en:'Inbound inspection complete — delivered',ja:'受信検査完了・正常配信'} }, { c:'#F87171', s:'SpamOut', m:{ko:'피싱 메일 차단 — 발신자 사칭 탐지',en:'Phishing blocked — sender impersonation',ja:'フィッシング遮断 — 送信者偽装'} }, { c:'#F87171', s:'SpamOut', m:{ko:'악성 첨부 격리 · 매크로 문서',en:'Malicious attachment quarantined — macro doc',ja:'不正添付を隔離・マクロ文書'} }, { c:'#6366F1', s:'Genian NAC', m:{ko:'비인가 단말 접속 시도 차단',en:'Unauthorized device blocked',ja:'非認可端末の接続を遮断'} }, { c:'#34D399', s:'Insights E', m:{ko:'의심 프로세스 행위 탐지 · 격리',en:'Suspicious process behavior — isolated',ja:'疑わしいプロセスを検知・隔離'} }, { c:'#22D3EE', s:'CheckOut', m:{ko:'대외 발송 승인 대기 1건',en:'1 outbound message awaiting approval',ja:'社外送信の承認待ち 1件'} }, { c:'#A78BFA', s:'DBSAFER DB', m:{ko:'DB 접근 승인 · SELECT 감사 기록',en:'DB access approved — SELECT audited',ja:'DBアクセス承認・SELECT監査記録'} }, { c:'#22D3EE', s:'Arch5', m:{ko:'송수신 메일 원본 보존 완료',en:'Message originals preserved',ja:'送受信メール原本を保存'} }, { c:'#34D399', s:'Genian MDR', m:{ko:'위협 인텔리전스 갱신 적용',en:'Threat intelligence updated',ja:'脅威インテリジェンスを更新'} }, { c:'#6366F1', s:'SNIPER ONE-d', m:{ko:'비정상 트래픽 정제 · 회선 정상',en:'Anomalous traffic scrubbed — link healthy',ja:'異常トラフィック精製・回線正常'} }, { c:'#FB923C', s:'Mail Insight', m:{ko:'메일 지식DB 증분 인덱싱 반영',en:'Knowledge base incrementally indexed',ja:'メール知識DBを増分インデックス'} }, { c:'#A78BFA', s:'CatchSecu', m:{ko:'보유기간 초과 개인정보 자동 파기',en:'Expired personal data auto-disposed',ja:'保有期間超過の個人情報を自動破棄'} }, { c:'#38BDF8', s:'SolidStep CVE', m:{ko:'신규 CVE 반영 · 영향 자산 12건',en:'New CVE ingested — 12 assets affected',ja:'新規CVE反映・影響資産12件'} }, { c:'#6366F1', s:'NetWitness', m:{ko:'세션 재구성 완료 · 이상 없음',en:'Session reconstructed — no findings',ja:'セッション再構成完了・異常なし'} }, { c:'#38BDF8', s:'서버 접근제어', m:{ko:'관리자 세션 기록 · 작업 이력 저장',en:'Admin session recorded',ja:'管理者セッションを記録'} }, ]; // ── 노드 상세 ────────────────────────────────────────────────────────────── const TOPO_INFO = { spamout:{ t:'SpamOut', s:{ko:'수신메일 보안 게이트웨이',en:'Inbound email security gateway',ja:'受信メールセキュリティ'}, d:{ko:'메일 서버 앞단에서 스팸·피싱·랜섬웨어·악성 첨부파일을 다단계로 검사하고 정책에 따라 차단합니다.',en:'Inspects mail ahead of the mail server across multiple layers and blocks spam, phishing, ransomware, and malicious attachments by policy.',ja:'メールサーバー前段で多段階検査を行い、ポリシーに従って遮断します。'}, f:{ko:['SMTP · 평판 · 백신 다단계 검사','첨부파일 확장자 · 압축 · Hash 검사','SPF / DKIM / DMARC','RBL / SURBL · APT 연동'],en:['Multi-layer SMTP, reputation, AV','Attachment type, archive, hash checks','SPF / DKIM / DMARC','RBL / SURBL, APT integration'],ja:['SMTP・レピュテーション・AV検査','添付ファイル・圧縮・Hash検査','SPF / DKIM / DMARC','RBL / SURBL・APT連携']}, p:['Cloud','구축형 SMB','구축형 Enterprise'], loc:{ko:'메일 서버 앞단 (경계 · DMZ)',en:'In front of the mail server (DMZ)',ja:'メールサーバー前段(DMZ)'}, r:['CheckOut','Arch5','Mail Insight'], cs:{ko:'대규모 메일 트래픽 환경에서 이중화 구성으로 구축하고, APT 장비와 연동해 다단계 검사 체계를 운영한 사례가 있습니다.',en:'Deployed in redundant configuration for high mail volumes, integrated with APT appliances for layered inspection.',ja:'大規模環境で冗長構成を構築し、APT装置と連携した多段階検査を運用した事例があります。'}, ind:{ko:['공공기관','제조','금융','의료','교육'],en:['Public','Manufacturing','Finance','Healthcare','Education'],ja:['公共','製造','金融','医療','教育']} }, checkout:{ t:'CheckOut', s:{ko:'발신메일 보안 · 유출방지',en:'Outbound email security · DLP',ja:'発信メールセキュリティ'}, d:{ko:'사외로 발송되는 메일의 본문·첨부파일을 검사하고 승인·차단·암호화 정책을 적용합니다.',en:'Inspects outbound mail bodies and attachments, applying approval, blocking, and encryption policies.',ja:'社外送信メールを検査し、承認・遮断・暗号化ポリシーを適用します。'}, f:{ko:['발신메일 승인 결재','개인정보 탐지 · 마스킹','보안메일 암호화 / 링크변환','대용량 첨부 관리'],en:['Outbound approval workflow','Personal data detection & masking','Secure mail encryption / link conversion','Large attachment management'],ja:['発信メール承認','個人情報検知・マスキング','セキュアメール暗号化','大容量添付管理']}, p:['온프레미스','하이브리드'], loc:{ko:'사용자 → 인터넷 발신 구간',en:'Between users and outbound internet',ja:'ユーザー → 送信区間'}, r:['SpamOut','CatchSecu','DLP'], cs:{ko:'부서장 승인 정책과 개인정보 탐지 정책을 함께 운영해 외부 발송 메일의 사전 검토 체계를 구축한 사례가 있습니다.',en:'Combined manager approval with personal-data detection to establish pre-send review for outbound mail.',ja:'承認ポリシーと個人情報検知を併用し、送信前レビュー体制を構築した事例があります。'}, ind:{ko:['공공기관','금융','제조','의료'],en:['Public','Finance','Manufacturing','Healthcare'],ja:['公共','金融','製造','医療']} }, arch5:{ t:'Arch5', s:{ko:'메일 아카이빙 · 원본 보존',en:'Email archiving · original preservation',ja:'メールアーカイブ'}, d:{ko:'송수신 메일과 첨부파일을 발생 시점에 자동 보존하고, 통합 검색으로 즉시 추출합니다.',en:'Automatically preserves inbound and outbound mail with attachments at transit time and retrieves them via unified search.',ja:'送受信メールを発生時点で保存し、統合検索で即時抽出します。'}, f:{ko:['발생 시점 자동 보존','Hash 기반 무결성 검증','통합 검색 · 즉시 복원','감사 증적 확보'],en:['Automatic preservation at transit','Hash-based integrity verification','Unified search & instant restore','Audit evidence'],ja:['発生時点の自動保存','Hashによる完全性検証','統合検索・即時復元','監査証跡']}, p:['온프레미스','전용 클라우드'], loc:{ko:'메일 서버 후단 (보존 계층)',en:'Behind the mail server (retention layer)',ja:'メールサーバー後段'}, r:['SpamOut','Mail Insight','백업 · 복구'], cs:{ko:'장기 보존 요건이 있는 환경에서 원본 무결성 증빙과 통합 검색을 함께 요구한 프로젝트에 적용된 사례가 있습니다.',en:'Applied where long-term retention required both integrity evidence and unified search.',ja:'長期保存要件のある環境で、原本の完全性証明と統合検索を要求されたプロジェクトに適用されました。'}, ind:{ko:['공공기관','금융','제조','교육'],en:['Public','Finance','Manufacturing','Education'],ja:['公共','金融','製造','教育']} }, mailin:{ t:'Mail Insight', s:{ko:'AI/RAG 메일 지식DB',en:'AI/RAG email knowledge DB',ja:'AI/RAGメール知識DB'}, d:{ko:'보관된 메일과 첨부파일을 AI/RAG로 분석해 자연어 검색이 가능한 조직 지식 자산으로 전환합니다.',en:'Analyzes archived mail and attachments with AI/RAG, turning them into a searchable organizational knowledge asset.',ja:'保管メールをAI/RAGで分析し、自然言語検索可能な知識資産へ転換します。'}, f:{ko:['AI/RAG 자연어 검색','첨부파일 내용 분석','자동 태깅 · 메타데이터','원본 증적 제공'],en:['AI/RAG natural-language search','Attachment content analysis','Auto-tagging & metadata','Original evidence'],ja:['AI/RAG自然言語検索','添付ファイル内容分析','自動タグ付け','原本証跡']}, p:['SaaS','전용 클라우드','온프레미스'], loc:{ko:'아카이빙 계층 위 AI 분석 레이어',en:'AI layer above the archiving tier',ja:'アーカイブ層上のAI分析レイヤー'}, r:['Arch5','RAG 검색'], cs:{ko:'퇴사자 업무 히스토리 확인과 회신 누락 점검을 목적으로 보관 메일 검색 체계를 개선한 사례가 있습니다.',en:'Improved archived-mail search to recover departed-staff history and detect missed replies.',ja:'退職者の業務履歴確認と返信漏れ点検を目的に検索体制を改善した事例があります。'}, ind:{ko:['제조','금융','IT','공공기관'],en:['Manufacturing','Finance','IT','Public'],ja:['製造','金融','IT','公共']} }, sysac:{ t:{ko:'서버 접근제어',en:'Server Access Control',ja:'サーバーアクセス制御'}, s:{ko:'시스템 보안 · 계정 · 권한 통제',en:'System security · account & privilege control',ja:'システム・アカウント・権限統制'}, d:{ko:'서버 접속 경로를 일원화하고 계정·권한·작업 이력을 통제해 시스템 보안 수준을 높입니다.',en:'Consolidates server access paths and controls accounts, privileges, and activity history.',ja:'サーバー接続経路を一元化し、アカウント・権限・作業履歴を統制します。'}, f:{ko:['접속 경로 일원화 (게이트웨이)','계정 · 권한 최소화','작업 이력 기록 · 재생','패치 · 취약점 관리 연동'],en:['Consolidated access gateway','Least-privilege accounts','Session recording & replay','Patch & vulnerability integration'],ja:['接続経路の一元化','アカウント・権限の最小化','作業履歴の記録','パッチ・脆弱性連携']}, p:['Windows Server','Linux Server','WAS'], loc:{ko:'업무 서버 존 (AD · DNS 인접)',en:'Application server zone (next to AD/DNS)',ja:'業務サーバーゾーン'}, r:['패치 관리','취약점 관리','로그 관리'], cs:{ko:'다수 서버 운영 환경에서 접속 경로를 게이트웨이로 통합하고 권한 체계를 재정비한 사례가 있습니다.',en:'Consolidated access through a gateway and restructured privilege model across many servers.',ja:'多数のサーバー環境で接続経路をゲートウェイに統合し、権限体系を再整備した事例があります。'}, ind:{ko:['공공기관','금융','제조','IT'],en:['Public','Finance','Manufacturing','IT'],ja:['公共','金融','製造','IT']} }, cce:{ t:'SolidStep CCE', s:{ko:'IT 인프라 취약점(CCE) 진단 자동화',en:'IT infrastructure (CCE) assessment automation',ja:'ITインフラ脆弱性(CCE)診断'}, d:{ko:'OS·DBMS·WEB·WAS·네트워크 영역의 보안 설정 취약점을 상시 자동 진단하고, 조치와 이력까지 관리합니다.',en:'Continuously assesses security configuration vulnerabilities across OS, DBMS, WEB, WAS, and network domains, managing remediation and history.',ja:'OS・DBMS・WEB・WAS・ネットワークの設定脆弱性を常時自動診断します。'}, f:{ko:['대규모 전수 검사','Agent · Agentless · 수동 진단','통합 대시보드 · 통계','자동조치 · 결재관리'],en:['Full-scale scanning','Agent · Agentless · manual','Integrated dashboard','Auto remediation & approvals'],ja:['大規模全数検査','Agent・Agentless・手動','統合ダッシュボード','自動措置・承認管理']}, p:['OS','DBMS','WEB · WAS','네트워크','클라우드'], loc:{ko:'업무 서버 존 · 진단 계층',en:'Application server zone, assessment layer',ja:'業務サーバーゾーン'}, r:['SolidStep CVE','서버 접근제어','로그 관리'], cs:{ko:'주요정보통신기반시설 및 클라우드 보안 인증 대응을 위해 정기 진단과 조치 이력을 자동화한 사례가 있습니다.',en:'Automated periodic assessment and remediation history for critical infrastructure and cloud certification response.',ja:'重要情報通信基盤施設およびクラウド認証対応のため、定期診断と措置履歴を自動化した事例があります。'}, ind:{ko:['공공기관','금융','제조','교육'],en:['Public','Finance','Manufacturing','Education'],ja:['公共','金融','製造','教育']} }, cve:{ t:'SolidStep CVE', s:{ko:'알려진 취약점(CVE) 진단 자동화',en:'Known vulnerability (CVE) assessment automation',ja:'既知脆弱性(CVE)診断'}, d:{ko:'운영 중인 전체 자산의 CVE 취약점을 원클릭 전수 진단하고, 자산별 상세 인벤토리까지 관리합니다.',en:'One-click full-scale CVE assessment across all operating assets with per-asset detailed inventory.',ja:'運用中の全資産のCVE脆弱性をワンクリックで全数診断します。'}, f:{ko:['원클릭 전수 진단','MITRE · KISA CVE 반영','자산 상세 인벤토리','조치관리 · 이력관리'],en:['One-click full scan','MITRE · KISA CVE ingestion','Detailed asset inventory','Remediation & history'],ja:['ワンクリック全数診断','MITRE・KISA CVE反映','資産詳細インベントリ','措置・履歴管理']}, p:['서버','PC · 단말','애플리케이션'], loc:{ko:'업무 서버 존 · 패치 관리 인접',en:'Application server zone, next to patch management',ja:'業務サーバーゾーン'}, r:['SolidStep CCE','패치 관리','EDR'], cs:{ko:'Log4j와 같은 긴급 취약점 공개 시 영향 자산을 즉시 전수 진단하고 내부 보고 체계를 갖춘 사례가 있습니다.',en:'Established immediate full-asset assessment and internal reporting when urgent vulnerabilities such as Log4j were published.',ja:'Log4jのような緊急脆弱性の公開時に、影響資産を即時全数診断する体制を構築した事例があります。'}, ind:{ko:['공공기관','금융','제조','IT'],en:['Public','Finance','Manufacturing','IT'],ja:['公共','金融','製造','IT']} }, dbac:{ t:'DBSAFER DB', s:{ko:'데이터베이스 접근제어 · SQL 감사',en:'Database access control · SQL audit',ja:'DBアクセス制御・SQL監査'}, d:{ko:'DB 접근 및 권한 제어와 SQL 감사로 개인정보 유출을 차단하며, Server Agent로 Gateway 우회 접속과 콘솔 직접 접속까지 모니터링합니다.',en:'Blocks personal data leakage through access and permission control plus SQL audit, with a Server Agent monitoring gateway-bypassing and direct console connections.',ja:'アクセス・権限制御とSQL監査で漏えいを防ぎ、迂回接続まで監視します。'}, f:{ko:['IP · 애플리케이션별 접속 권한','테이블 · 컬럼 조합 명령어 차단','조회 결과값 데이터 마스킹','약 93종 통계 보고서'],en:['Access rights by IP and application','Command blocking by table and column','Data masking on result sets','About 93 report templates'],ja:['IP・アプリ別アクセス権限','テーブル・カラム単位の遮断','結果値マスキング','約93種の統計レポート']}, p:['Oracle','MSSQL','MySQL','Tibero','PostgreSQL','DB2'], loc:{ko:'데이터 존 · DB 서버 앞단',en:'Data zone, in front of DB servers',ja:'データゾーン・DBサーバー前段'}, r:['DLP','백업 · 복구','감사 대응'], cs:{ko:'Gateway 우회 접속과 전산실 콘솔 직접 접속까지 통제 범위에 포함하고, 쿼리 단위 감사 로그로 점검 증적을 확보한 사례가 있습니다.',en:'Brought gateway-bypassing and direct console access into scope while securing query-level audit evidence.',ja:'迂回接続とコンソール直接接続まで統制範囲に含め、クエリ単位の監査証跡を確保した事例があります。'}, ind:{ko:['공공기관','금융','의료','제조'],en:['Public','Finance','Healthcare','Manufacturing'],ja:['公共','金融','医療','製造']} }, ndr:{ t:'NetWitness NDR', s:{ko:'네트워크 위협 탐지 및 대응',en:'Network detection & response',ja:'ネットワーク脅威検知・対応'}, d:{ko:'스위치 TAP·SPAN으로 트래픽을 복제받아 풀패킷을 실시간 분석하고, 세션 재구성으로 공격 전체 행위를 조사합니다.',en:'Mirrors traffic via switch TAP/SPAN to analyze full packets in real time, reconstructing sessions to investigate the full scope of attacker activity.',ja:'TAP・SPANでトラフィックを複製し、フルパケットをリアルタイム分析します。'}, f:{ko:['풀패킷 실시간 수집 · 저장','세션 완벽 재현 · 포렌식','위협 상관관계 분석','FirstWatch Threat Intelligence'],en:['Real-time full-packet capture','Complete session replay & forensics','Threat correlation analysis','FirstWatch threat intelligence'],ja:['フルパケット収集','セッション完全再現','脅威相関分析','FirstWatch脅威情報']}, p:['온프레미스','클라우드','가상 환경','하이브리드'], loc:{ko:'Core Switch TAP · SPAN 구간',en:'Core switch TAP/SPAN',ja:'コアスイッチTAP・SPAN区間'}, r:['SNIPER ONE-d','Genian NAC','SOC 관제'], cs:{ko:'로그만으로 확인이 어려운 구간을 풀패킷으로 보완하고, 은닉된 2·3차 경유지를 역추적한 사례가 있습니다.',en:'Complemented log-only blind spots with full packets and traced hidden second/third-stage hops.',ja:'ログでは確認困難な区間をフルパケットで補完し、隠れた経由地を逆追跡した事例があります。'}, ind:{ko:['공공기관','금융','에너지','의료','대기업'],en:['Public','Finance','Energy','Healthcare','Enterprise'],ja:['公共','金融','エネルギー','医療','大企業']} }, eset:{ t:'ESET PROTECT Enterprise', s:{ko:'엔드포인트 · XDR 통합 보안 플랫폼',en:'Endpoint · XDR unified platform',ja:'エンドポイント・XDR統合'}, d:{ko:'다계층 엔드포인트 보호, 서버 보안, 전체 디스크 암호화, 클라우드 샌드박스, XDR을 단일 콘솔에서 통합 운영합니다.',en:'Unifies multilayered endpoint protection, server security, full disk encryption, cloud sandbox, and XDR in one console.',ja:'多層保護・サーバー保護・暗号化・サンドボックス・XDRを単一コンソールで運用します。'}, f:{ko:['머신러닝 + 행위 분석 다계층 방어','랜섬웨어 실드 · 익스플로잇 차단','클라우드 샌드박스 자동 분석','전체 디스크 암호화 원격 관리'],en:['ML + behavior layered defense','Ransomware Shield & exploit blocking','Automatic cloud sandbox','Remote full disk encryption'],ja:['ML+挙動分析の多層防御','ランサムウェア対策','クラウドサンドボックス','ディスク暗号化の遠隔管理']}, p:['Windows','Linux','macOS','Server','가상화'], loc:{ko:'PC · 서버 단말 + 관리 콘솔',en:'PC/server endpoints + console',ja:'PC・サーバー端末+コンソール'}, r:['Genian Insights E','Genian MDR','SpamOut'], cs:{ko:'백신·암호화·샌드박스가 분리 운영되던 환경을 단일 콘솔로 통합하고, 단말 암호화 준수 현황을 함께 관리한 사례가 있습니다.',en:'Consolidated separately operated antivirus, encryption, and sandbox into one console while tracking encryption compliance.',ja:'分離運用されていた製品を単一コンソールへ統合し、暗号化準拠状況も併せて管理した事例があります。'}, ind:{ko:['제조','공공기관','금융','의료'],en:['Manufacturing','Public','Finance','Healthcare'],ja:['製造','公共','金融','医療']} }, nac:{ t:'Genian NAC', s:{ko:'네트워크 접근제어',en:'Network access control',ja:'ネットワークアクセス制御'}, d:{ko:'네트워크에 접속하는 모든 단말을 식별·가시화하고 정책에 따라 허용·격리·차단합니다.',en:'Identifies and visualizes every device on the network, allowing, quarantining, or blocking by policy.',ja:'接続する全端末を識別・可視化し、ポリシーに従って制御します。'}, f:{ko:['전 단말 식별 · 가시성','정책 기반 접근제어','비인가 단말 격리','IP 충돌 · 자산 관리'],en:['Full device visibility','Policy-based access control','Quarantine of rogue devices','IP conflict & asset management'],ja:['全端末の可視化','ポリシー制御','非認可端末の隔離','IP競合・資産管理']}, p:['온프레미스','클라우드 관리'], loc:{ko:'내부망 스위치 계층',en:'Internal switch layer',ja:'内部網スイッチ層'}, r:['EDR','SNIPER ONE-d','VPN · ZTNA'], cs:{ko:'자산 현황 파악이 어려운 환경에서 단말 가시성을 확보하고 비인가 접속 통제를 적용한 사례가 있습니다.',en:'Established device visibility and rogue-access control where asset inventory was unclear.',ja:'資産把握が困難な環境で端末可視性を確保し、非認可接続の統制を適用した事例があります。'}, ind:{ko:['공공기관','제조','교육','의료'],en:['Public','Manufacturing','Education','Healthcare'],ja:['公共','製造','教育','医療']} }, edr:{ t:'Genian Insights E (EDR)', s:{ko:'엔드포인트 위협 탐지 · 대응',en:'Endpoint detection & response',ja:'エンドポイント検知・対応'}, d:{ko:'단말의 행위를 기반으로 위협을 탐지하고 격리·차단·추적까지 대응합니다.',en:'Detects threats from endpoint behavior and responds with isolation, blocking, and tracing.',ja:'端末の挙動から脅威を検知し、隔離・遮断・追跡まで対応します。'}, f:{ko:['행위 기반 위협 탐지','자동 격리 · 차단','침해 경로 추적','랜섬웨어 대응'],en:['Behavior-based detection','Automatic isolation','Attack path tracing','Ransomware response'],ja:['挙動ベース検知','自動隔離・遮断','侵害経路の追跡','ランサムウェア対応']}, p:['Windows','Linux','macOS'], loc:{ko:'PC · 서버 단말 (에이전트)',en:'PC & server endpoints (agent)',ja:'PC・サーバー端末'}, r:['MDR 관제','Genian NAC','로그 관리'], cs:{ko:'랜섬웨어 대응력을 높이기 위해 단말 행위 탐지와 자동 격리 정책을 함께 운영한 사례가 있습니다.',en:'Combined behavior detection with automatic isolation to strengthen ransomware readiness.',ja:'挙動検知と自動隔離ポリシーを併用し、ランサムウェア対応力を高めた事例があります。'}, ind:{ko:['제조','금융','공공기관','의료'],en:['Manufacturing','Finance','Public','Healthcare'],ja:['製造','金融','公共','医療']} }, mdr:{ t:'Genian MDR', s:{ko:'보안 관제 서비스',en:'Managed detection & response',ja:'セキュリティ監視サービス'}, d:{ko:'전문 관제팀이 24/7로 위협을 모니터링하고, 탐지부터 대응·복구까지 대행합니다.',en:'A dedicated team monitors threats 24/7 and handles detection through response and recovery.',ja:'専門チームが24/7で監視し、検知から対応・復旧まで代行します。'}, f:{ko:['24/7 위협 모니터링','위협 헌팅','침해사고 대응','정기 리포트'],en:['24/7 monitoring','Threat hunting','Incident response','Regular reporting'],ja:['24/7監視','脅威ハンティング','インシデント対応','定期レポート']}, p:['구독형 서비스'], loc:{ko:'SOC 관제 계층',en:'SOC layer',ja:'SOC監視層'}, r:['EDR','로그 관리','자동 대응'], cs:{ko:'보안 전담 인력이 부족한 환경에서 관제와 대응을 위임해 운영 부담을 줄인 사례가 있습니다.',en:'Delegated monitoring and response to reduce operational load where security staffing was limited.',ja:'専任人材が不足する環境で監視と対応を委任し、運用負担を軽減した事例があります。'}, ind:{ko:['제조','유통','IT','교육'],en:['Manufacturing','Retail','IT','Education'],ja:['製造','流通','IT','教育']} }, ddos:{ t:'SNIPER ONE-d', s:{ko:'디도스(DDoS) 대응',en:'Anti-DDoS',ja:'DDoS対応'}, d:{ko:'네트워크 전단에서 DDoS 공격을 실시간 탐지·차단하고 정상 트래픽만 정제합니다.',en:'Detects and blocks DDoS at the network edge, forwarding only legitimate traffic.',ja:'ネットワーク前段でDDoSを検知・遮断し、正常トラフィックのみ通します。'}, f:{ko:['실시간 탐지 · 차단','트래픽 정제','L3 / L4 / L7 대응','임계치 정책'],en:['Real-time detection & blocking','Traffic scrubbing','L3 / L4 / L7 coverage','Threshold policies'],ja:['リアルタイム検知・遮断','トラフィック精製','L3/L4/L7対応','しきい値ポリシー']}, p:['인라인','아웃오브패스'], loc:{ko:'방화벽 전단 (회선 구간)',en:'Ahead of the firewall (circuit)',ja:'ファイアウォール前段'}, r:['방화벽 · IPS','Genian NAC'], cs:{ko:'외부 공개 서비스의 가용성 확보를 위해 회선 구간에 탐지·정제 체계를 구성한 사례가 있습니다.',en:'Configured edge detection and scrubbing to protect availability of public-facing services.',ja:'公開サービスの可用性確保のため、回線区間に検知・精製体制を構成した事例があります。'}, ind:{ko:['공공기관','IT · 호스팅','금융','유통'],en:['Public','IT · Hosting','Finance','Retail'],ja:['公共','IT・ホスティング','金融','流通']} }, catchsecu:{ t:'CatchSecu', s:{ko:'개인정보 보호 자동화',en:'Privacy protection automation',ja:'個人情報保護の自動化'}, d:{ko:'개인정보 수집·동의·암호화·파기 전 주기를 자동화해 규제 대응을 지원합니다.',en:'Automates the personal-data lifecycle — collection, consent, encryption, disposal — to support compliance.',ja:'個人情報の収集・同意・暗号化・破棄を自動化し、規制対応を支援します。'}, f:{ko:['AI 동의서 자동 생성','암호화 보관','보유기간 자동 파기','오남용 모니터링'],en:['AI consent form generation','Encrypted storage','Automatic disposal at expiry','Misuse monitoring'],ja:['AI同意書の自動生成','暗号化保管','保有期間満了時の自動破棄','不正利用モニタリング']}, p:['SaaS','온프레미스'], loc:{ko:'데이터 존 · 수집 채널 앞단',en:'Data zone, ahead of collection channels',ja:'データゾーン・収集チャネル前段'}, r:['CheckOut','DLP','감사 대응'], cs:{ko:'무료 설문폼과 엑셀로 관리하던 개인정보 수집 절차를 정책 기반 자동화로 전환한 사례가 있습니다.',en:'Replaced free-form and spreadsheet-based personal-data collection with policy-driven automation.',ja:'無料フォームとExcelで管理していた収集手続きを、ポリシー基盤の自動化へ移行した事例があります。'}, ind:{ko:['공공기관','교육','의료','유통'],en:['Public','Education','Healthcare','Retail'],ja:['公共','教育','医療','流通']} }, }; // 인프라·보조 노드용 간단 설명 const TOPO_BRIEF = { fw:{ko:'외부와 내부 사이 트래픽을 정책으로 통제하고 침입을 탐지·차단하는 경계 보안 계층입니다.',en:'Perimeter layer that controls traffic by policy and detects intrusions.',ja:'境界でトラフィックを統制し侵入を検知・遮断する層です。'}, dmz:{ko:'외부 공개 서비스를 내부망과 분리해 배치하는 완충 구간입니다.',en:'Buffer segment isolating public-facing services from the internal network.',ja:'公開サービスを内部網から分離する緩衝区間です。'}, vpn:{ko:'외부에서 내부 자원에 접속할 때 신원과 단말을 검증하고 최소 권한으로 연결합니다.',en:'Verifies identity and device for remote access with least privilege.',ja:'外部から内部資源へ接続する際に身元と端末を検証します。'}, patch:{ko:'서버와 단말의 보안 패치 적용 현황을 관리하고 누락을 점검합니다.',en:'Manages patch deployment across servers and endpoints.',ja:'サーバー・端末のパッチ適用状況を管理します。'}, vuln:{ko:'정기 진단으로 취약점을 식별하고 조치 우선순위를 관리합니다.',en:'Identifies vulnerabilities through periodic scans and prioritizes remediation.',ja:'定期診断で脆弱性を特定し、対応優先度を管理します。'}, account:{ko:'계정 생성·변경·삭제 절차를 표준화하고 유휴 계정을 점검합니다.',en:'Standardizes account lifecycle and reviews dormant accounts.',ja:'アカウントのライフサイクルを標準化し、休眠アカウントを点検します。'}, privilege:{ko:'권한을 최소한으로 부여하고 관리자 권한 사용 이력을 통제합니다.',en:'Grants least privilege and controls administrative usage history.',ja:'権限を最小限に付与し、管理者権限の使用履歴を統制します。'}, logmgmt:{ko:'서버·단말·보안장비 로그를 수집·보관하고 이상 징후를 점검합니다.',en:'Collects and retains logs across servers, endpoints, and appliances.',ja:'サーバー・端末・機器のログを収集保管し、異常を点検します。'}, monitor:{ko:'시스템과 보안 상태를 상시 모니터링하고 임계치 초과 시 알림을 발송합니다.',en:'Continuously monitors system and security state with threshold alerts.',ja:'システムとセキュリティ状態を常時監視し、しきい値超過時に通知します。'}, ad:{ko:'사용자 계정과 정책을 중앙에서 관리하는 디렉터리 서비스입니다.',en:'Directory service centrally managing accounts and policies.',ja:'アカウントとポリシーを中央管理するディレクトリサービスです。'}, dbac:{ko:'DB 접속 경로를 일원화하고 쿼리 단위로 권한을 통제·기록합니다.',en:'Consolidates DB access and controls privileges at query level.',ja:'DB接続経路を一元化し、クエリ単位で権限を統制します。'}, dlp:{ko:'중요 데이터가 외부로 나가는 경로를 탐지하고 정책에 따라 차단·기록합니다.',en:'Detects and blocks paths where sensitive data leaves the organization.',ja:'重要データの外部流出経路を検知し、遮断・記録します。'}, backup:{ko:'중요 데이터를 정기적으로 백업하고 장애·침해 시 신속하게 복구합니다.',en:'Backs up critical data and enables rapid recovery.',ja:'重要データを定期的にバックアップし、迅速に復旧します。'}, audit:{ko:'접근·처리 이력을 보관하고 감사·점검 시 필요한 증적을 제공합니다.',en:'Retains access history and provides evidence for audits.',ja:'アクセス履歴を保管し、監査時に必要な証跡を提供します。'}, aichat:{ko:'제품 문의와 보안 상담을 AI가 1차 응대하고 필요 시 담당자로 연결합니다.',en:'AI handles first-line product and security inquiries, escalating when needed.',ja:'AIが一次対応し、必要に応じて担当者へ接続します。'}, rag:{ko:'사내 문서와 메일을 벡터화해 자연어 질문으로 근거와 함께 답을 찾습니다.',en:'Vectorizes documents and mail to answer natural-language questions with sources.',ja:'社内文書とメールをベクトル化し、根拠付きで回答します。'}, agent:{ko:'문의 내용을 분석해 적합한 솔루션과 다음 절차를 제안합니다.',en:'Analyzes inquiries to recommend solutions and next steps.',ja:'問い合わせ内容を分析し、適切なソリューションを提案します。'}, autoquote:{ko:'사용자 수·구축 방식 등 조건을 수집해 견적 산정 절차를 자동으로 시작합니다.',en:'Collects conditions such as user count and deployment model to start quoting.',ja:'ユーザー数や構築方式などの条件を収集し、見積手続きを開始します。'}, autorep:{ko:'보안 현황과 처리 내역을 정기 리포트로 자동 생성합니다.',en:'Generates periodic security status and activity reports automatically.',ja:'セキュリティ状況と処理内容を定期レポートとして自動生成します。'}, autoticket:{ko:'문의와 장애 접수를 티켓으로 자동 등록하고 담당자에게 배정합니다.',en:'Registers inquiries and incidents as tickets and assigns owners.',ja:'問い合わせと障害を自動でチケット登録し、担当者に割り当てます。'}, autoresp:{ko:'정의된 시나리오에 따라 초기 대응 조치를 자동으로 수행합니다.',en:'Executes initial response actions per defined playbooks.',ja:'定義されたシナリオに従い初期対応を自動実行します。'}, }; const topoStyles = ` .tp-wrap{min-height:100vh;background:radial-gradient(130% 80% at 50% 0%,#0d1b3e 0%,#0A1226 46%,#050912 100%);padding-top:68px;position:relative;overflow:hidden} .tp-wrap::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:.55; background-image:linear-gradient(rgba(255,255,255,.024) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.024) 1px,transparent 1px); background-size:52px 52px;mask-image:radial-gradient(ellipse 92% 62% at 50% 24%,#000 28%,transparent 80%); -webkit-mask-image:radial-gradient(ellipse 92% 62% at 50% 24%,#000 28%,transparent 80%)} .tp-wrap::after{content:'';position:absolute;width:72%;height:52%;top:-8%;left:14%;pointer-events:none; background:radial-gradient(closest-side,rgba(34,211,238,.075),transparent 70%);filter:blur(64px)} .tp-head{position:relative;max-width:1400px;margin:0 auto;padding:50px 24px 22px} .tp-eyebrow{display:inline-flex;align-items:center;gap:8px;padding:6px 13px;border-radius:100px;background:rgba(34,211,238,.10); border:1px solid rgba(34,211,238,.26);font-family:'DM Sans',sans-serif;font-size:11px;font-weight:600;letter-spacing:2px;color:#67E8F9;margin-bottom:16px} .tp-eyebrow i{width:6px;height:6px;border-radius:50%;background:#22D3EE;display:block;animation:tpBlink 2.4s ease-in-out infinite} @keyframes tpBlink{0%,100%{opacity:1}50%{opacity:.35}} .tp-title{font-size:clamp(26px,3.3vw,42px);font-weight:700;color:#fff;letter-spacing:-.8px;line-height:1.24;margin-bottom:12px} .tp-sub{font-size:15.5px;color:rgba(255,255,255,.58);line-height:1.7;max-width:760px} .tp-bar{display:flex;flex-wrap:wrap;gap:18px 26px;margin-top:24px;padding-top:20px;border-top:1px solid rgba(255,255,255,.07)} .tp-bar-col{display:flex;flex-direction:column;gap:9px} .tp-bar-k{font-family:'DM Sans',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.8px;color:rgba(255,255,255,.34);text-transform:uppercase} .tp-chips{display:flex;flex-wrap:wrap;gap:7px} .tp-chips button{display:inline-flex;align-items:center;gap:7px;padding:6px 12px;border-radius:100px;cursor:pointer;font-family:inherit; font-size:12.5px;font-weight:500;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.09);color:rgba(255,255,255,.6);transition:all .18s ease} .tp-chips button:hover{background:rgba(255,255,255,.08);color:#fff} .tp-chips button.on{color:#fff;font-weight:600} .tp-chips s{width:8px;height:8px;border-radius:2px;display:block;text-decoration:none} .tp-chips.flows s{border-radius:50%} .tp-stage{position:relative;max-width:1400px;margin:0 auto;padding:0 24px 64px;display:grid;grid-template-columns:1fr 336px;gap:20px;align-items:start} .tp-canvas{position:relative;background:rgba(255,255,255,.016);border:1px solid rgba(255,255,255,.07);border-radius:18px;padding:10px;overflow:hidden} .tp-canvas svg{width:100%;height:auto;display:block;overflow:hidden} /* AI 가이드 투어 — 카메라 */ .tp-cam{transition:transform 1.45s cubic-bezier(.65,.02,.2,1)} .tp-node.spot circle.ring{stroke-width:2.6} .tp-node.spot{filter:drop-shadow(0 0 14px rgba(103,232,249,.35))} .tp-spot{fill:none;stroke-width:1.6;opacity:0} .tp-node.spot .tp-spot{opacity:.9;animation:tpSpot 2.3s ease-out infinite} @keyframes tpSpot{0%{r:26;opacity:.8}100%{r:52;opacity:0}} /* AI 에이전트 말풍선 */ .tp-agent{position:static;display:flex;gap:13px;align-items:flex-start;padding:4px 8px 6px;z-index:4} .tp-av{width:40px;height:40px;border-radius:12px;flex:none;display:flex;align-items:center;justify-content:center; font-family:'DM Sans',sans-serif;font-size:11.5px;font-weight:700;letter-spacing:.5px;color:#fff; background:linear-gradient(135deg,#0891B2,#2563EB);box-shadow:0 0 26px rgba(37,99,235,.5)} .tp-av i{width:7px;height:7px;border-radius:50%;background:#fff;position:absolute;transform:translate(16px,-16px);animation:tpBlink 1.6s ease-in-out infinite} .tp-bub{background:rgba(8,18,36,.93);border:1px solid rgba(34,211,238,.26);border-radius:4px 15px 15px 15px;padding:13px 17px;max-width:620px; backdrop-filter:blur(12px)} .tp-bub-k{font-family:'DM Sans',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.6px;color:#22D3EE;margin-bottom:6px;text-transform:uppercase} .tp-bub-t{font-size:13.5px;line-height:1.66;color:rgba(255,255,255,.85)} .tp-bub-t b{color:#fff;font-weight:600} .tp-tourctl{display:flex;align-items:center;gap:6px;margin-top:11px;flex-wrap:wrap} .tp-tourctl button{background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.11);color:rgba(255,255,255,.72); border-radius:8px;padding:6px 12px;font-size:12px;font-weight:600;font-family:inherit;cursor:pointer;transition:all .18s ease} .tp-tourctl button:hover{background:rgba(34,211,238,.14);border-color:rgba(34,211,238,.4);color:#fff} .tp-dots{display:flex;gap:4px;margin-left:6px} .tp-dots i{width:18px;height:3px;border-radius:2px;background:rgba(255,255,255,.14);display:block;cursor:pointer;transition:all .3s ease} .tp-dots i.on{background:#22D3EE;box-shadow:0 0 8px rgba(34,211,238,.8)} /* 라이브 이벤트 스트림 */ .tp-live{margin-top:18px;padding-top:15px;border-top:1px solid rgba(255,255,255,.08)} .tp-live-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px} .tp-live-h span{display:inline-flex;align-items:center;gap:6px;font-family:'DM Sans',sans-serif;font-size:10px;font-weight:700;letter-spacing:1.5px;color:rgba(255,255,255,.36);text-transform:uppercase} .tp-live-h s{width:6px;height:6px;border-radius:50%;background:#34D399;display:block;text-decoration:none;animation:tpBlink 1.4s ease-in-out infinite} .tp-logs{display:flex;flex-direction:column;gap:5px;max-height:268px;overflow:hidden} .tp-log{display:flex;gap:7px;padding-left:8px;border-left:2px solid;font-size:11px;line-height:1.5;animation:tpLogIn .38s ease-out both} @keyframes tpLogIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}} .tp-log .ts{color:rgba(255,255,255,.3);flex:none;font-family:'DM Sans',sans-serif} .tp-log .ms{color:rgba(255,255,255,.66)} .tp-log .ms b{font-weight:600} .tp-kpis{display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:14px} .tp-kpi{background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.07);border-radius:10px;padding:10px 11px} .tp-kpi b{display:block;font-family:'DM Sans',sans-serif;font-size:17px;font-weight:700;letter-spacing:-.3px;white-space:nowrap} .tp-kpi span{display:block;font-size:10.5px;color:rgba(255,255,255,.4);margin-top:2px} /* 인프라 스파인 (배경) */ .tp-spine{stroke-dasharray:6 7;animation:tpSpine 1s ease-out both} @keyframes tpSpine{from{stroke-dashoffset:340;opacity:0}to{stroke-dashoffset:0;opacity:1}} .tp-zone{transition:opacity .28s ease} .tp-zone rect{fill:rgba(255,255,255,.028);stroke:rgba(255,255,255,.1);stroke-dasharray:3 5} .tp-zone-label{font-size:11px;font-weight:700;letter-spacing:1.9px;text-transform:uppercase;opacity:.75} .tp-zone.dim{opacity:.5} .tp-link{stroke-dasharray:var(--len,140);stroke-dashoffset:var(--len,140);animation:tpDraw .46s ease-out both;transition:stroke .26s ease} @keyframes tpDraw{to{stroke-dashoffset:0}} .tp-packet{opacity:0} .tp-packet.run{animation:tpMove var(--pd,5s) linear infinite} @keyframes tpMove{0%{opacity:0;offset-distance:0%}5%{opacity:1}95%{opacity:1}100%{opacity:0;offset-distance:100%}} .tp-node{cursor:pointer;opacity:0;animation:tpPop .44s cubic-bezier(.2,.8,.3,1) both;transition:opacity .26s ease} .tp-node.plain{cursor:default} @keyframes tpPop{from{opacity:0;transform:scale(.74)}to{opacity:1;transform:scale(1)}} .tp-node circle.ring{transition:stroke .2s ease,stroke-width .2s ease,fill .2s ease} .tp-node text{transition:fill .2s ease} .tp-node:hover circle.ring,.tp-node.sel circle.ring{stroke-width:2} .tp-node.dim{opacity:.34} .tp-halo{opacity:0;transition:opacity .22s ease} .tp-node:hover .tp-halo,.tp-node.sel .tp-halo{opacity:.55} /* 클릭 확대 → 이동 */ .tp-node.zoom{animation:tpZoom .42s cubic-bezier(.3,.7,.3,1) both} @keyframes tpZoom{0%{transform:scale(1)}55%{transform:scale(1.4)}100%{transform:scale(1.24);opacity:.9}} /* 우측 패널 */ .tp-panel{position:sticky;top:88px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.09);border-radius:16px;padding:22px;backdrop-filter:blur(10px);max-height:calc(100vh - 108px);overflow-y:auto} .tp-panel::-webkit-scrollbar{width:5px}.tp-panel::-webkit-scrollbar-thumb{background:rgba(255,255,255,.12);border-radius:3px} .tp-p-mark{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;margin-bottom:12px} .tp-panel h3{font-size:19px;font-weight:700;color:#fff;letter-spacing:-.4px;margin:0 0 4px} .tp-p-sub{font-size:12.5px;font-weight:600;margin-bottom:14px} .tp-p-desc{font-size:13.5px;color:rgba(255,255,255,.66);line-height:1.72;margin-bottom:18px} .tp-p-sect{font-size:10px;font-weight:700;letter-spacing:1.5px;color:rgba(255,255,255,.36);text-transform:uppercase;margin:0 0 8px} .tp-p-list{display:flex;flex-direction:column;gap:7px;margin-bottom:16px} .tp-p-list div{display:flex;gap:8px;font-size:13px;color:rgba(255,255,255,.74);line-height:1.55} .tp-p-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:16px} .tp-p-chips span{padding:3px 9px;border-radius:100px;font-size:11.5px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);color:rgba(255,255,255,.66)} .tp-p-quote{font-size:12.5px;color:rgba(255,255,255,.6);line-height:1.7;padding:11px 13px;border-radius:10px;background:rgba(255,255,255,.035);border-left:2px solid rgba(255,255,255,.14);margin-bottom:16px} .tp-p-loc{font-size:12.5px;color:rgba(255,255,255,.7);padding:9px 12px;border-radius:9px;background:rgba(255,255,255,.04);margin-bottom:16px} .tp-p-btns{display:flex;flex-direction:column;gap:7px} .tp-p-btn{width:100%;padding:11px;border:none;border-radius:10px;font-family:inherit;font-size:13px;font-weight:600;color:#fff;cursor:pointer; display:inline-flex;align-items:center;justify-content:center;gap:7px;transition:filter .18s ease,background .18s ease} .tp-p-btn:hover{filter:brightness(1.14)} .tp-p-btn.ghost{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12)} .tp-p-btn.ghost:hover{background:rgba(255,255,255,.12)} .tp-panel-empty{color:rgba(255,255,255,.4);font-size:13.5px;line-height:1.75} /* 모바일 */ .tp-mobile{display:none} .tp-m-cat{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:18px;margin-bottom:12px} .tp-m-cat-h{display:flex;align-items:center;gap:9px;margin-bottom:6px} .tp-m-cat-h s{width:9px;height:9px;border-radius:2px;display:block;text-decoration:none} .tp-m-cat-h b{font-size:14.5px;color:#fff;font-weight:700} .tp-m-flow{font-size:11.5px;color:rgba(255,255,255,.4);margin-bottom:12px;line-height:1.6} .tp-m-items{display:grid;grid-template-columns:1fr 1fr;gap:8px} .tp-m-item{display:flex;align-items:center;gap:8px;padding:10px 11px;border-radius:10px;background:rgba(255,255,255,.04); border:1px solid rgba(255,255,255,.07);font-size:12.5px;color:rgba(255,255,255,.8);cursor:pointer;font-family:inherit;text-align:left} .tp-m-item:active{background:rgba(255,255,255,.09)} .tp-m-item s{width:6px;height:6px;border-radius:50%;display:block;text-decoration:none;flex-shrink:0} @media(max-width:1120px){ .tp-stage{grid-template-columns:1fr} .tp-panel{position:static;max-height:none} } @media(max-width:768px){ .tp-canvas,.tp-panel,.tp-modes{display:none} .tp-mobile{display:block;max-width:1400px;margin:0 auto;padding:0 18px 56px} .tp-head{padding:38px 18px 20px} .tp-title{font-size:24px}.tp-sub{font-size:14px} .tp-bar{gap:14px 18px} } @media(max-width:768px){ .tp-agent{display:none} } @media(prefers-reduced-motion:reduce){ .tp-cam{transition:none} .tp-node.spot .tp-spot,.tp-log{animation:none!important} .tp-link,.tp-node,.tp-spine{animation:none!important;opacity:1!important;stroke-dashoffset:0!important;transform:none!important} .tp-packet.run{animation:none!important;opacity:0!important} .tp-eyebrow i{animation:none} .tp-node.zoom{animation:none!important} } `; const tpIcon = (kind, c, sc=1) => { const P = { fill:'none', stroke:c, strokeWidth:1.95/sc, strokeLinecap:'round', strokeLinejoin:'round' }; const M = { transform:`scale(${sc})` }; const inner = (() => { switch (kind) { case 'globe': return ; case 'brick': return ; case 'zone': return ; case 'shield': return ; case 'server': return ; case 'archive': return ; case 'users': return ; case 'send': return ; case 'brain': return ; case 'web': return ; case 'layers': return ; case 'app': return ; case 'tree': return ; case 'gate': return ; case 'pulse': return ; case 'eye': return ; case 'win': return ; case 'linux': return ; case 'patch': return ; case 'bug': return ; case 'idcard': return ; case 'key': return ; case 'keyhole': return ; case 'lines': return ; case 'wave': return ; case 'lock': return ; case 'net': return ; case 'switch': return ; case 'pc': return ; case 'radar': return ; case 'headset': return ; case 'admin': return ; case 'privacy': return ; case 'db': return ; case 'outbox': return ; case 'stack': return ; case 'doc': return ; case 'cloud': return ; case 'bot': return ; case 'search': return ; case 'agent': return ; case 'quote': return ; case 'chart': return ; case 'ticket': return ; case 'bolt': return ; case 'handshake':return ; default: return null; }})(); return {inner}; }; const TopologyPage = ({ lang, setPage, openQuote, openDemo }) => { const [sel, setSel] = React.useState(null); const [hov, setHov] = React.useState(null); const [cat, setCat] = React.useState(null); const [flowOn, setFlowOn] = React.useState(null); const [zoom, setZoom] = React.useState(null); const [step, setStep] = React.useState(0); const [playing, setPlaying] = React.useState(true); const [logs, setLogs] = React.useState([]); const [mode, setMode] = React.useState('tour'); // tour | attack | assess const [atkId, setAtkId] = React.useState(null); const [atkStep, setAtkStep] = React.useState(0); const [atkPlay, setAtkPlay] = React.useState(true); const [have, setHave] = React.useState([]); const [kpi, setKpi] = React.useState([0,0,0,0]); const isKo = lang === 'ko'; const L = o => (o && (o[lang] || o.en || o.ko)) || ''; const byKey = React.useMemo(() => Object.fromEntries(TOPO_NODES.map(n=>[n.k,n])), []); const nodeR = n => (n.key ? 34 : 29); // 투어는 사용자가 직접 탐색을 시작하면(노드 선택·필터) 멈춤 const touring = mode === 'tour' && playing && !sel && !cat && !flowOn; const atk = atkId ? TOPO_ATTACKS.find(a=>a.id===atkId) : null; const curStep = TOPO_STEPS[step]; React.useEffect(() => { if (!touring) return; const id = setTimeout(()=>setStep(s=>(s+1)%TOPO_STEPS.length), 7200); return ()=>clearTimeout(id); }, [touring, step]); // 공격 시뮬레이터 재생 React.useEffect(()=>{ if (mode !== 'attack' || !atk || !atkPlay) return; const id = setTimeout(()=>setAtkStep(v => v + 1 >= atk.steps.length ? 0 : v + 1), 2300); return ()=>clearTimeout(id); }, [mode, atk, atkPlay, atkStep]); // 모드별 노드 상태 (ok / gap / hit / block) const nodeState = React.useMemo(()=>{ const m = {}; if (mode === 'attack' && atk) { atk.steps.forEach((st,i)=>{ if (i > atkStep) return; m[st.n] = st.block ? (i === atkStep ? 'block' : 'ok') : (i === atkStep ? 'hit' : 'hit'); }); } else if (mode === 'assess') { TOPO_ASSESS.forEach(a=>{ const on = have.includes(a.id); a.nodes.forEach(n=>{ m[n] = on ? 'ok' : 'gap'; }); }); } return m; }, [mode, atk, atkStep, have]); // 라이브 이벤트 스트림 React.useEffect(() => { const mk = () => { const e = TOPO_EVENTS[Math.floor(Math.random()*TOPO_EVENTS.length)]; const d = new Date(); const ts = [d.getHours(),d.getMinutes(),d.getSeconds()].map(n=>String(n).padStart(2,'0')).join(':'); return { ...e, ts, id: d.getTime()+Math.random() }; }; setLogs(Array.from({length:9},mk)); const id = setInterval(()=>setLogs(p=>[mk(),...p].slice(0,14)), 2100); return ()=>clearInterval(id); }, []); // KPI 카운트업 React.useEffect(() => { const tg = [184320, 2847, 1263, 99.98]; let f = 0; const id = setInterval(()=>{ f++; const p = Math.min(1, f/46), e = 1-Math.pow(1-p,3); setKpi(tg.map((v,i)=>i===3 ? (v*e) : Math.round(v*e))); if (p >= 1) clearInterval(id); }, 34); return ()=>clearInterval(id); }, []); // 카메라 — 투어 단계의 노드 집합을 화면에 맞춤 const camStyle = React.useMemo(() => { if (!touring || !curStep || !curStep.f) return { transform:'none' }; const ns = curStep.f.map(k=>byKey[k]).filter(Boolean); if (!ns.length) return { transform:'none' }; const xs = ns.map(n=>n.x), ys = ns.map(n=>n.y); const x0 = Math.min(...xs)-150, x1 = Math.max(...xs)+150; const y0 = Math.min(...ys)-120, y1 = Math.max(...ys)+130; const s = Math.min(1400/(x1-x0), 1184/(y1-y0), 1.7); return { transform:`translate(${700-s*(x0+x1)/2}px, ${592-s*(y0+y1)/2}px) scale(${s})` }; }, [touring, curStep, byKey]); const focus = React.useMemo(() => { const active = hov || sel; if (mode === 'attack' && atk) return new Set(atk.steps.slice(0, atkStep+1).map(s=>s.n)); if (mode === 'assess') return null; if (touring && curStep && curStep.f) return new Set(curStep.f); if (!active && !cat && !flowOn) return null; const set = new Set(); if (cat) TOPO_NODES.forEach(n=>{ if(n.cat===cat) set.add(n.k); }); if (flowOn) { const f = TOPO_FLOWS.find(x=>x.id===flowOn); if (f) f.seq.forEach(k=>set.add(k)); } if (active) { set.add(active); TOPO_FLOWS.forEach(f=>{ if(f.seq.includes(active)) f.seq.forEach(k=>set.add(k)); }); TOPO_LINKS.forEach(([a,b])=>{ if(a===active) set.add(b); if(b===active) set.add(a); }); } return set; }, [hov, sel, cat, flowOn, touring, curStep, mode, atk, atkStep]); const spot = touring && curStep && curStep.f ? new Set(curStep.f) : null; const tourPath = touring && curStep ? curStep.p.map((k,i)=>{ const n=byKey[k]; return `${i===0?'M':'L'}${n.x} ${n.y}`; }).join(' ') : null; const linkPath = (a,b) => { const n1 = byKey[a], n2 = byKey[b]; if (!n1 || !n2) return null; const r1 = nodeR(n1), r2 = nodeR(n2); if (n1.y === n2.y) { const x1 = Math.min(n1.x,n2.x)+r1+6, x2 = Math.max(n1.x,n2.x)-r2-6; return { d:`M${x1} ${n1.y}H${x2}`, len:Math.abs(x2-x1) }; } const dir = n2.y > n1.y ? 1 : -1; const y1 = n1.y + dir*(r1+6), y2 = n2.y - dir*(r2+6); if (n1.x === n2.x) return { d:`M${n1.x} ${y1}V${y2}`, len:Math.abs(y2-y1) }; return { d:`M${n1.x} ${y1}C${n1.x} ${y1+dir*38} ${n2.x} ${y2-dir*38} ${n2.x} ${y2}`, len:Math.hypot(n2.x-n1.x,y2-y1)+46 }; }; const flowPath = seq => seq.map((k,i)=>{ const n = byKey[k]; return `${i===0?'M':'L'}${n.x} ${n.y}`; }).join(' '); const go = (node) => { if (!node.page) { setPage('contact'); return; } setZoom(node.k); setTimeout(()=>{ setZoom(null); setPage(node.page); }, 420); }; const detail = sel && TOPO_INFO[sel] ? TOPO_INFO[sel] : null; const brief = sel && !detail ? TOPO_BRIEF[sel] : null; const selNode = sel ? byKey[sel] : null; const selColor = selNode ? TOPO_CATS[selNode.cat].c : '#22D3EE'; return (
ENTERPRISE SECURITY BLUEPRINT

{isKo ? <>기업 보안은 제품이 아니라
아키텍처로 완성됩니다 : lang==='ja' ? <>企業セキュリティは製品ではなく
アーキテクチャで完成します : <>Enterprise security is built on
architecture, not products}

{isKo ? '경계·메일·업무 서버·내부망·데이터·AI 계층이 실제로 어떻게 연결되어 동작하는지 한 화면에서 확인하세요. 노드를 클릭하면 해당 영역의 역할과 적용 솔루션 정보를 볼 수 있습니다.' : lang==='ja' ? '境界・メール・業務サーバー・内部網・データ・AI 各層の連携を一画面で確認できます。ノードをクリックすると詳細が表示されます。' : 'See how the perimeter, mail, application server, internal network, data, and AI layers actually connect. Click any node for its role and applied solutions.'}

{isKo?'보기 모드':(lang==='ja'?'表示モード':'View mode')}
{[['tour', isKo?'AI 가이드':(lang==='ja'?'AI案内':'AI guide')], ['attack', isKo?'공격 시뮬레이션':(lang==='ja'?'攻撃シミュレーション':'Attack simulation')], ['assess', isKo?'내 회사 진단':(lang==='ja'?'自社診断':'Assess my stack')]].map(([m,l])=>( ))}
{mode==='tour' &&
{isKo?'보안 영역':(lang==='ja'?'領域':'Domains')}
{Object.entries(TOPO_CATS).filter(([k])=>k!=='infra').map(([k,v])=>( ))}
} {mode==='tour' &&
{isKo?'데이터 흐름':(lang==='ja'?'データフロー':'Data flows')}
{TOPO_FLOWS.map(f=>( ))}
}
{/* 인프라 존 */} {TOPO_ZONES.map((z,i)=>{ const dim = cat && !TOPO_NODES.some(n=>n.cat===cat && n.x>=z.x && n.x<=z.x+z.w && n.y>=z.y && n.y<=z.y+z.h); return ( {L(z)} ); })} {/* 인프라 스파인 (배경 흐름) */} {/* 연결선 */} {TOPO_LINKS.map(([a,b],i)=>{ const p = linkPath(a,b); if (!p) return null; const on = !focus || (focus.has(a) && focus.has(b)); return ; })} {/* 데이터 흐름 패킷 */} {TOPO_FLOWS.map(f=>{ const on = !focus || f.seq.some(k=>focus.has(k)); return ( {[0,1].map(j=>( ))} ); })} {/* 차단 라벨 */} {isKo?'스팸 · 악성코드 · 피싱 차단':(lang==='ja'?'スパム・マルウェア・フィッシング遮断':'SPAM · MALWARE · PHISHING BLOCKED')} {/* 투어 안내 패킷 */} {tourPath && ( )} {/* 노드 */} {TOPO_NODES.map((n,i)=>{ const c = TOPO_CATS[n.cat].c, r = nodeR(n); const dim = focus && !focus.has(n.k); const isSel = sel === n.k; const clickable = !!(n.page || TOPO_INFO[n.k] || TOPO_BRIEF[n.k]); return ( setHov(n.k)} onMouseLeave={()=>setHov(null)} onClick={()=>clickable && setSel(isSel?null:n.k)} tabIndex={clickable?0:-1} role={clickable?'button':undefined} onKeyDown={e=>{ if(clickable&&(e.key==='Enter'||e.key===' ')){e.preventDefault();setSel(isSel?null:n.k);} }}> {tpIcon(n.ic, n.key?c:'rgba(255,255,255,.9)', n.key?1.24:1.1)} {L(n)} ); })} {/* AI 가이드 에이전트 */} {mode==='tour' &&
AI
{touring ? `STEP ${step+1} / ${TOPO_STEPS.length} · ${L(curStep.k)}` : (isKo?'직접 탐색 중':(lang==='ja'?'手動探索中':'MANUAL EXPLORATION'))}
안내 재개를 누르면 전체 구조를 다시 순서대로 설명해 드립니다.' :lang==='ja'?'ノード選択またはフィルタ適用中は案内を停止します。案内を再開で順に説明します。' :'The tour pauses while you select a node or apply a filter. Press Resume tour to walk the full architecture again.') }}/>
{touring ? ( <> ) : ( )}
{TOPO_STEPS.map((s,i)=>( {setSel(null);setCat(null);setFlowOn(null);setStep(i);setPlaying(true);}}/> ))}
}
{/* 우측 정보 패널 */}
{/* 모바일 */}
{Object.entries(TOPO_CATS).filter(([k])=>k!=='infra').map(([ck,cv])=>{ const items = TOPO_NODES.filter(n=>n.cat===ck); const flowTxt = { mail: isKo?'인터넷 → 방화벽 → DMZ → SpamOut → 메일서버 → Arch5 → 사용자':'Internet → Firewall → DMZ → SpamOut → Mail Server → Arch5 → Users', system: isKo?'DMZ → 웹/WAS → AD · DNS → 서버 접근제어 → 패치 · 취약점 진단 (CCE · CVE)':'DMZ → Web/WAS → AD · DNS → Access Control → Patch · Vulnerability (CCE · CVE)', network: isKo?'방화벽 → SNIPER ONE-d → VPN · ZTNA → NAC → 스위치 → NetWitness NDR (TAP)':'Firewall → SNIPER ONE-d → VPN · ZTNA → NAC → Switch → NetWitness NDR (TAP)', endpoint: isKo?'PC · 단말 → ESET PROTECT · EDR → MDR 관제 → 보안 담당자':'PC · Device → ESET PROTECT · EDR → MDR → Security Admin', data: isKo?'CatchSecu → DB → DBSAFER DB → DLP → 백업 → 감사':'CatchSecu → DB → DBSAFER DB → DLP → Backup → Audit', ai: isKo?'AI 상담 → RAG → AI Agent → 자동 견적 · 보고서 · 티켓 · 대응':'AI Assistant → RAG → Agent → Auto Quote · Report · Ticket · Response', }[ck]; return (
{L(cv)}
{flowTxt}
{items.map(n=>( ))}
); })}
); }; Object.assign(window, { topoStyles, TopologyPage, TOPO_CATS, TOPO_NODES, TOPO_ZONES });