feat(homepage): GUARDiA 모바일 앱 목업 스크린샷 5장 생성 + 앱 탭 추가

- Playwright headless로 HTML 목업 → PNG 스크린샷 변환
  11_app_home.png    홈 대시보드 (SR·서버 실시간 현황)
  12_app_sr.png      SR 서비스 요청 목록
  13_app_chat.png    AI 챗봇 (Ollama 연동)
  14_app_dr.png      DR 재해복구 RTO/RPO 모니터링
  15_app_network.png 네트워크 장비 백업 현황

- GuardiaDetail.jsx: '모바일 앱' 탭 신규 추가
  5장 목업 5열 그리드 (390x844 세로 비율)
  Google Play / App Store 다운로드 배지

- GuardiaDetail.css: 모바일 스크린샷 5열 그리드 스타일

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
DESKTOP-TKLFCPR\ython 2026-05-31 12:27:48 +09:00
parent c046e173c9
commit 012b963a13
7 changed files with 486 additions and 7 deletions

View File

@ -0,0 +1,89 @@
<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{background:#0f172a;width:390px;height:844px;display:flex;flex-direction:column;overflow:hidden}
.sb{height:44px;background:#0f172a;display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0}
.sb .t{color:#fff;font-size:15px;font-weight:600}
.sb .i{color:#fff;font-size:13px}
.hd{background:linear-gradient(135deg,#1a3a6b,#1a5fd8);padding:14px 20px;display:flex;align-items:center;gap:12px;flex-shrink:0}
.ba{width:42px;height:42px;border-radius:50%;background:linear-gradient(135deg,#6366f1,#8b5cf6);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0}
.hi h1{color:#fff;font-size:17px;font-weight:700}
.hi p{color:rgba(255,255,255,.7);font-size:12px}
.ol{display:inline-block;width:8px;height:8px;background:#22c55e;border-radius:50%;margin-right:4px}
.msgs{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:14px}
.msg{display:flex;gap:10px;max-width:85%}
.mu{align-self:flex-end;flex-direction:row-reverse}
.mb{padding:12px 14px;border-radius:18px;font-size:13px;line-height:1.6}
.bot .mb{background:#1e293b;color:#e2e8f0;border-bottom-left-radius:4px}
.mu .mb{background:#1a5fd8;color:#fff;border-bottom-right-radius:4px}
.ba2{width:32px;height:32px;border-radius:50%;background:linear-gradient(135deg,#6366f1,#8b5cf6);display:flex;align-items:center;justify-content:center;font-size:14px;flex-shrink:0;align-self:flex-end}
.mt{font-size:10px;color:#475569;align-self:flex-end}
.qr{display:flex;gap:8px;flex-wrap:wrap;padding:0 16px 12px;flex-shrink:0}
.qc{padding:7px 13px;background:#1e293b;border-radius:20px;font-size:12px;color:#94a3b8;border:1px solid rgba(255,255,255,.08)}
.ib{background:#1e293b;padding:12px 16px;display:flex;gap:10px;align-items:center;flex-shrink:0;border-top:1px solid rgba(255,255,255,.06)}
.inp{flex:1;background:#0f172a;border:1px solid rgba(255,255,255,.1);border-radius:24px;padding:10px 16px;color:#e2e8f0;font-size:14px}
.snd{width:40px;height:40px;background:#1a5fd8;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:16px;color:#fff;flex-shrink:0}
.tb{height:60px;background:#1e293b;border-top:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-around;flex-shrink:0}
.tab{display:flex;flex-direction:column;align-items:center;gap:3px}
.tab .ic{font-size:20px}
.tab .lb{font-size:9px;color:#64748b}
</style></head>
<body>
<div class="sb"><span class="t">9:41</span><span class="i">● ●● ▐▌</span></div>
<div class="hd">
<div class="ba">🤖</div>
<div class="hi"><h1>GUARDiA AI</h1><p><span class="ol"></span>Ollama llama3:8b 연결됨</p></div>
</div>
<div class="msgs">
<div class="msg bot">
<div class="ba2">🤖</div>
<div>
<div class="mb">안녕하세요 홍 관리자님! 👋<br>GUARDiA AI 어시스턴트입니다.<br>무엇을 도와드릴까요?</div>
<div class="mt">9:35</div>
</div>
</div>
<div class="msg mu">
<div>
<div class="mb">서울시청 WAS-01 서비스 상태 확인해줘</div>
<div class="mt" style="text-align:right">9:40</div>
</div>
</div>
<div class="msg bot">
<div class="ba2">🤖</div>
<div>
<div class="mb">📡 <strong>WAS-01 상태 확인 중...</strong><br><br><strong>서비스 정상 운영 중</strong><br>• CPU: 34% | 메모리: 2.1/4GB<br>• Tomcat 8.5.99 — UP (14일)<br>• 최근 에러로그: 없음<br><br>⚡ 응답시간: 12ms (정상 범위)</div>
<div class="mt">9:41</div>
</div>
</div>
<div class="msg mu">
<div>
<div class="mb">DR 테스트 실행해줘</div>
<div class="mt" style="text-align:right">9:41</div>
</div>
</div>
<div class="msg bot">
<div class="ba2">🤖</div>
<div>
<div class="mb">🛡️ <strong>DR 복구 테스트 시작합니다</strong><br><br>시나리오: WAS-01 장애<br>단계 1/4 ✅ 서비스 중단 확인<br>단계 2/4 🔄 대기 서버 활성화 중...</div>
<div class="mt">9:41</div>
</div>
</div>
</div>
<div class="qr">
<span class="qc">서버 상태 확인</span>
<span class="qc">SR 목록 보여줘</span>
<span class="qc">최근 인시던트</span>
<span class="qc">DR 테스트 실행</span>
</div>
<div class="ib">
<div class="inp">메시지 입력...</div>
<div class="snd"></div>
</div>
<div class="tb">
<div class="tab"><div class="ic">📊</div><div class="lb"></div></div>
<div class="tab"><div class="ic">📋</div><div class="lb">SR</div></div>
<div class="tab"><div class="ic">🛡️</div><div class="lb">DR</div></div>
<div class="tab"><div class="ic">🤖</div><div class="lb" style="color:#60a5fa">AI</div></div>
<div class="tab"><div class="ic">⚙️</div><div class="lb">설정</div></div>
</div>
</body></html>

View File

@ -0,0 +1,79 @@
<!DOCTYPE html><html><head><meta charset="UTF-8">
<meta name="viewport" content="width=390">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{background:#0f172a;width:390px;height:844px;overflow:hidden;display:flex;flex-direction:column}
.sb{height:44px;background:#0f172a;display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0}
.sb .t{color:#fff;font-size:15px;font-weight:600}
.sb .i{color:#fff;font-size:13px}
.gnb{background:linear-gradient(135deg,#1a3a6b,#1a5fd8);padding:16px 20px 20px;flex-shrink:0}
.gnb .g{color:rgba(255,255,255,.7);font-size:12px;margin-bottom:4px}
.gnb .n{color:#fff;font-size:20px;font-weight:700}
.gnb .b{display:inline-flex;align-items:center;gap:4px;background:rgba(255,255,255,.15);border-radius:20px;padding:4px 10px;font-size:11px;color:#fff;margin-top:8px}
.sc{flex:1;overflow-y:auto;padding:16px}
.sr{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px}
.st{background:#1e293b;border-radius:14px;padding:16px;border:1px solid rgba(255,255,255,.06)}
.st .num{color:#60a5fa;font-size:28px;font-weight:700}
.st .lab{color:#94a3b8;font-size:11px;margin-top:4px}
.st .sub{color:#22c55e;font-size:10px;margin-top:2px}
.sec{background:#1e293b;border-radius:14px;padding:16px;margin-bottom:14px;border:1px solid rgba(255,255,255,.06)}
.sec h3{color:#94a3b8;font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:12px}
.si{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid rgba(255,255,255,.05)}
.si:last-child{border-bottom:none}
.sd{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.st2{flex:1}
.tt{color:#e2e8f0;font-size:13px;font-weight:500}
.tm{color:#64748b;font-size:11px;margin-top:2px}
.sb2{font-size:10px;padding:2px 8px;border-radius:10px;font-weight:600}
.bp{background:rgba(59,130,246,.2);color:#60a5fa}
.bw{background:rgba(245,158,11,.2);color:#fbbf24}
.bc{background:rgba(34,197,94,.2);color:#4ade80}
.svr{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid rgba(255,255,255,.05)}
.svr:last-child{border-bottom:none}
.sn{color:#e2e8f0;font-size:13px}
.sp{color:#94a3b8;font-size:11px}
.sok{color:#22c55e;font-size:12px}
.swn{color:#f59e0b;font-size:12px}
.tb{height:60px;background:#1e293b;border-top:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-around;flex-shrink:0}
.tab{display:flex;flex-direction:column;align-items:center;gap:3px}
.tab .ic{font-size:20px}
.tab .lb{font-size:9px;color:#64748b}
.tab.act .lb{color:#60a5fa}
</style></head>
<body>
<div class="sb"><span class="t">9:41</span><span class="i">● ●● ▐▌</span></div>
<div class="gnb">
<div class="g">안녕하세요</div>
<div class="n">홍 관리자님 👋</div>
<span class="b">🟢 ITSM 운영 중 &nbsp;|&nbsp; Enterprise</span>
</div>
<div class="sc">
<div class="sr">
<div class="st"><div class="num">23</div><div class="lab">오늘 SR 접수</div><div class="sub">▲ 3 증가</div></div>
<div class="st"><div class="num" style="color:#f59e0b">7</div><div class="lab">처리 대기</div><div class="sub" style="color:#ef4444">SLA 위험 2건</div></div>
</div>
<div class="sr">
<div class="st"><div class="num" style="color:#22c55e">98.2%</div><div class="lab">서버 가용률</div><div class="sub">24대 중 24대 정상</div></div>
<div class="st"><div class="num" style="color:#a78bfa">14</div><div class="lab">오늘 배포</div><div class="sub">성공 13 / 실패 1</div></div>
</div>
<div class="sec">
<h3>최근 서비스 요청</h3>
<div class="si"><div class="sd" style="background:#ef4444"></div><div class="st2"><div class="tt">행정망 WAS 서비스 장애</div><div class="tm">서울시청 · 10분 전</div></div><span class="sb2 bp">처리중</span></div>
<div class="si"><div class="sd" style="background:#f59e0b"></div><div class="st2"><div class="tt">Tomcat 재기동 요청</div><div class="tm">안산시청 · 23분 전</div></div><span class="sb2 bw">대기</span></div>
<div class="si"><div class="sd" style="background:#3b82f6"></div><div class="st2"><div class="tt">DB 백업 스케줄 변경</div><div class="tm">수원시청 · 1시간 전</div></div><span class="sb2 bc">완료</span></div>
</div>
<div class="sec">
<h3>서버 상태</h3>
<div class="svr"><div><div class="sn">WAS-서울시청-01</div><div class="sp">응답 12ms</div></div><span class="sok">● 정상</span></div>
<div class="svr"><div><div class="sn">DB-안산시청-01</div><div class="sp">응답 45ms</div></div><span class="swn">⚠ 주의</span></div>
<div class="svr"><div><div class="sn">WEB-수원시청-01</div><div class="sp">응답 8ms</div></div><span class="sok">● 정상</span></div>
</div>
</div>
<div class="tb">
<div class="tab act"><div class="ic">📊</div><div class="lb" style="color:#60a5fa"></div></div>
<div class="tab"><div class="ic">📋</div><div class="lb">SR</div></div>
<div class="tab"><div class="ic">🛡️</div><div class="lb">DR</div></div>
<div class="tab"><div class="ic">🤖</div><div class="lb">AI</div></div>
<div class="tab"><div class="ic">⚙️</div><div class="lb">설정</div></div>
</div>
</body></html>

80
manual/mockups/m_dr.html Normal file
View File

@ -0,0 +1,80 @@
<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{background:#0f172a;width:390px;height:844px;display:flex;flex-direction:column;overflow:hidden}
.sb{height:44px;background:#0f172a;display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0}
.sb .t{color:#fff;font-size:15px;font-weight:600}
.sb .i{color:#fff;font-size:13px}
.hd{background:linear-gradient(135deg,#1a3a6b,#1a5fd8);padding:16px 20px;flex-shrink:0}
.hd h1{color:#fff;font-size:20px;font-weight:700}
.hd p{color:rgba(255,255,255,.7);font-size:12px;margin-top:2px}
.sc{flex:1;overflow-y:auto;padding:16px}
.sr{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:14px}
.su{background:#1e293b;border-radius:12px;padding:10px 6px;text-align:center;border:1px solid rgba(255,255,255,.06)}
.su .n{font-size:20px;font-weight:700;color:#e2e8f0}
.su .l{font-size:9px;color:#94a3b8;margin-top:2px}
.sec{background:#1e293b;border-radius:14px;padding:16px;margin-bottom:14px;border:1px solid rgba(255,255,255,.06)}
.sec h3{color:#94a3b8;font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:12px}
.sc2{padding:12px 0;border-bottom:1px solid rgba(255,255,255,.05)}
.sc2:last-child{border-bottom:none}
.st{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}
.sn{color:#e2e8f0;font-size:13px;font-weight:600}
.sbg{font-size:10px;padding:2px 8px;border-radius:10px;font-weight:700}
.bps{background:rgba(34,197,94,.2);color:#4ade80}
.bfl{background:rgba(239,68,68,.2);color:#f87171}
.bpd{background:rgba(148,163,184,.2);color:#94a3b8}
.rb{display:flex;align-items:center;gap:8px;margin-top:5px}
.rl{font-size:10px;color:#64748b;width:55px}
.rt{flex:1;height:6px;background:rgba(255,255,255,.08);border-radius:3px;overflow:hidden}
.rf{height:100%;border-radius:3px}
.rv{font-size:10px;color:#94a3b8;width:30px;text-align:right}
.sm{font-size:10px;color:#475569;margin-top:4px}
.tb{height:60px;background:#1e293b;border-top:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-around;flex-shrink:0}
.tab{display:flex;flex-direction:column;align-items:center;gap:3px}
.tab .ic{font-size:20px}
.tab .lb{font-size:9px;color:#64748b}
</style></head>
<body>
<div class="sb"><span class="t">9:41</span><span class="i">● ●● ▐▌</span></div>
<div class="hd"><h1>🛡️ DR 재해복구</h1><p>RTO/RPO 목표 대비 실적 모니터링</p></div>
<div class="sc">
<div class="sr">
<div class="su"><div class="n">5</div><div class="l">전체</div></div>
<div class="su"><div class="n" style="color:#22c55e">3</div><div class="l">PASS</div></div>
<div class="su"><div class="n" style="color:#ef4444">1</div><div class="l">FAIL</div></div>
<div class="su"><div class="n" style="color:#f59e0b">1</div><div class="l">미테스트</div></div>
</div>
<div class="sec">
<h3>시나리오 목록</h3>
<div class="sc2">
<div class="st"><span class="sn">서울시청 WAS 장애</span><span class="sbg bps">PASS</span></div>
<div class="rb"><span class="rl">RTO 목표</span><div class="rt"><div class="rf" style="width:15%;background:#22c55e"></div></div><span class="rv">120분</span></div>
<div class="rb"><span class="rl">RTO 실적</span><div class="rt"><div class="rf" style="width:10%;background:#60a5fa"></div></div><span class="rv">18분</span></div>
<div class="sm">최근 테스트: 2026-05-30 ✔ 충족</div>
</div>
<div class="sc2">
<div class="st"><span class="sn">안산시청 DB 페일오버</span><span class="sbg bps">PASS</span></div>
<div class="rb"><span class="rl">RTO 목표</span><div class="rt"><div class="rf" style="width:30%;background:#22c55e"></div></div><span class="rv">240분</span></div>
<div class="rb"><span class="rl">RTO 실적</span><div class="rt"><div class="rf" style="width:18%;background:#60a5fa"></div></div><span class="rv">45분</span></div>
<div class="sm">최근 테스트: 2026-05-29 ✔ 충족</div>
</div>
<div class="sc2">
<div class="st"><span class="sn">수원시청 사이트 장애</span><span class="sbg bfl">FAIL</span></div>
<div class="rb"><span class="rl">RTO 목표</span><div class="rt"><div class="rf" style="width:25%;background:#22c55e"></div></div><span class="rv">200분</span></div>
<div class="rb"><span class="rl">RTO 실적</span><div class="rt"><div class="rf" style="width:80%;background:#ef4444"></div></div><span class="rv">320분</span></div>
<div class="sm" style="color:#ef4444">최근 테스트: 2026-05-28 ✘ 목표 초과</div>
</div>
<div class="sc2">
<div class="st"><span class="sn">화성시청 네트워크 장애</span><span class="sbg bpd">미테스트</span></div>
<div class="sm" style="margin-top:4px">테스트 예정: 2026-06-15</div>
</div>
</div>
</div>
<div class="tb">
<div class="tab"><div class="ic">📊</div><div class="lb"></div></div>
<div class="tab"><div class="ic">📋</div><div class="lb">SR</div></div>
<div class="tab"><div class="ic">🛡️</div><div class="lb" style="color:#60a5fa">DR</div></div>
<div class="tab"><div class="ic">🤖</div><div class="lb">AI</div></div>
<div class="tab"><div class="ic">⚙️</div><div class="lb">설정</div></div>
</div>
</body></html>

View File

@ -0,0 +1,81 @@
<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{background:#0f172a;width:390px;height:844px;display:flex;flex-direction:column;overflow:hidden}
.sb{height:44px;background:#0f172a;display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0}
.sb .t{color:#fff;font-size:15px;font-weight:600}
.sb .i{color:#fff;font-size:13px}
.hd{background:linear-gradient(135deg,#1a3a6b,#1a5fd8);padding:16px 20px;flex-shrink:0}
.hd h1{color:#fff;font-size:20px;font-weight:700}
.hd p{color:rgba(255,255,255,.7);font-size:12px;margin-top:2px}
.se{padding:10px 16px;background:#0f172a;flex-shrink:0}
.se input{width:100%;background:#1e293b;border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:10px 14px;color:#94a3b8;font-size:13px}
.sc{flex:1;overflow-y:auto;padding:12px 16px}
.sr{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:12px}
.su{background:#1e293b;border-radius:10px;padding:10px 8px;text-align:center;border:1px solid rgba(255,255,255,.06)}
.su .n{font-size:18px;font-weight:700;color:#e2e8f0}
.su .l{font-size:9px;color:#94a3b8;margin-top:2px}
.cd{background:#1e293b;border-radius:14px;padding:16px;margin-bottom:10px;border:1px solid rgba(255,255,255,.06)}
.dt{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.di{font-size:28px}
.dn{flex:1}
.dna{color:#e2e8f0;font-size:14px;font-weight:600}
.dm{font-size:11px;color:#64748b;margin-top:2px}
.dst{font-size:20px}
.dd{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px}
.tg{background:rgba(255,255,255,.06);border-radius:8px;padding:4px 10px;font-size:11px;color:#94a3b8}
.bk{display:flex;align-items:center;justify-content:space-between}
.bi{font-size:11px;color:#64748b}
.bb{border-radius:8px;padding:5px 12px;font-size:11px;font-weight:600;color:#fff;background:#1a5fd8}
.bw{background:rgba(245,158,11,.2);color:#fbbf24}
.tb{height:60px;background:#1e293b;border-top:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-around;flex-shrink:0}
.tab{display:flex;flex-direction:column;align-items:center;gap:3px}
.tab .ic{font-size:20px}
.tab .lb{font-size:9px;color:#64748b}
</style></head>
<body>
<div class="sb"><span class="t">9:41</span><span class="i">● ●● ▐▌</span></div>
<div class="hd"><h1>🔀 네트워크 장비</h1><p>스위치·라우터·방화벽 관제</p></div>
<div class="se"><input placeholder="장비명 / 벤더 검색..." /></div>
<div class="sc">
<div class="sr">
<div class="su"><div class="n">12</div><div class="l">전체</div></div>
<div class="su"><div class="n" style="color:#22c55e">10</div><div class="l">정상</div></div>
<div class="su"><div class="n" style="color:#ef4444">2</div><div class="l">미백업</div></div>
</div>
<div class="cd">
<div class="dt">
<div class="di">🔀</div>
<div class="dn"><div class="dna">Core-Switch-서울-01</div><div class="dm">CISCO Catalyst 9300 · 서울시청 IDC</div></div>
<div class="dst"></div>
</div>
<div class="dd"><span class="tg">SWITCH</span><span class="tg">cisco_ios</span><span class="tg">백업 2일 전</span></div>
<div class="bk"><span class="bi">최근 백업: 2026-05-29 · 변경 0줄</span><span class="bb">백업</span></div>
</div>
<div class="cd">
<div class="dt">
<div class="di">🛡️</div>
<div class="dn"><div class="dna">FW-안산-01</div><div class="dm">PIOLINK TPLINK · 안산시청</div></div>
<div class="dst">⚠️</div>
</div>
<div class="dd"><span class="tg">FIREWALL</span><span class="tg">linux</span><span class="tg" style="color:#ef4444">미백업 8일</span></div>
<div class="bk"><span class="bi" style="color:#f59e0b">갱신 필요 — 8일 초과</span><span class="bb bw">백업 필요</span></div>
</div>
<div class="cd">
<div class="dt">
<div class="di">🔗</div>
<div class="dn"><div class="dna">Router-수원-01</div><div class="dm">HUAWEI AR3200 · 수원시청</div></div>
<div class="dst"></div>
</div>
<div class="dd"><span class="tg">ROUTER</span><span class="tg">huawei_vrp</span><span class="tg">백업 1일 전</span></div>
<div class="bk"><span class="bi">최근 백업: 2026-05-30 · 변경 3줄</span><span class="bb">백업</span></div>
</div>
</div>
<div class="tb">
<div class="tab"><div class="ic">📊</div><div class="lb"></div></div>
<div class="tab"><div class="ic">📋</div><div class="lb">SR</div></div>
<div class="tab"><div class="ic">🛡️</div><div class="lb">DR</div></div>
<div class="tab"><div class="ic">🤖</div><div class="lb">AI</div></div>
<div class="tab"><div class="ic">⚙️</div><div class="lb">설정</div></div>
</div>
</body></html>

86
manual/mockups/m_sr.html Normal file
View File

@ -0,0 +1,86 @@
<!DOCTYPE html><html><head><meta charset="UTF-8">
<style>
*{margin:0;padding:0;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,sans-serif}
body{background:#0f172a;width:390px;height:844px;display:flex;flex-direction:column;overflow:hidden}
.sb{height:44px;background:#0f172a;display:flex;align-items:center;justify-content:space-between;padding:0 20px;flex-shrink:0}
.sb .t{color:#fff;font-size:15px;font-weight:600}
.sb .i{color:#fff;font-size:13px}
.hd{background:linear-gradient(135deg,#1a3a6b,#1a5fd8);padding:16px 20px;flex-shrink:0}
.hd h1{color:#fff;font-size:20px;font-weight:700}
.hd p{color:rgba(255,255,255,.7);font-size:12px;margin-top:2px}
.fr{display:flex;gap:8px;padding:12px 16px;background:#0f172a;flex-shrink:0;overflow-x:auto}
.ch{padding:6px 14px;border-radius:20px;font-size:12px;font-weight:600;white-space:nowrap;flex-shrink:0}
.cha{background:#1a5fd8;color:#fff}
.chi{background:#1e293b;color:#94a3b8}
.ls{flex:1;overflow-y:auto;padding:12px 16px}
.cd{background:#1e293b;border-radius:14px;padding:16px;margin-bottom:10px;border:1px solid rgba(255,255,255,.06)}
.ct{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:8px}
.si{font-size:11px;color:#64748b;font-family:monospace}
.pr{font-size:10px;padding:2px 8px;border-radius:8px;font-weight:700}
.pc{background:rgba(239,68,68,.2);color:#f87171}
.ph{background:rgba(245,158,11,.2);color:#fbbf24}
.pm{background:rgba(59,130,246,.2);color:#60a5fa}
.cn{color:#e2e8f0;font-size:14px;font-weight:600;margin-bottom:4px}
.cm{display:flex;gap:8px;align-items:center}
.cm span{font-size:11px;color:#64748b}
.dt{width:3px;height:3px;background:#475569;border-radius:50%}
.sr2{display:flex;justify-content:space-between;align-items:center;margin-top:10px;padding-top:10px;border-top:1px solid rgba(255,255,255,.05)}
.av2{display:flex;align-items:center;gap:6px}
.av{width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;color:#fff}
.an{font-size:11px;color:#94a3b8}
.stb{font-size:10px;padding:3px 10px;border-radius:10px;font-weight:600}
.sp{background:rgba(59,130,246,.2);color:#60a5fa}
.sw{background:rgba(245,158,11,.2);color:#fbbf24}
.sc{background:rgba(34,197,94,.2);color:#4ade80}
.sr3{background:rgba(148,163,184,.2);color:#94a3b8}
.tb{height:60px;background:#1e293b;border-top:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:space-around;flex-shrink:0}
.tab{display:flex;flex-direction:column;align-items:center;gap:3px}
.tab .ic{font-size:20px}
.tab .lb{font-size:9px;color:#64748b}
.fab{position:fixed;right:20px;bottom:78px;width:52px;height:52px;border-radius:50%;background:#1a5fd8;display:flex;align-items:center;justify-content:center;font-size:26px;color:#fff;box-shadow:0 4px 16px rgba(26,95,216,.5)}
</style></head>
<body>
<div class="sb"><span class="t">9:41</span><span class="i">● ●● ▐▌</span></div>
<div class="hd"><h1>서비스 요청</h1><p>전체 23건 · 대기 7건</p></div>
<div class="fr">
<span class="ch cha">전체</span>
<span class="ch chi">처리중</span>
<span class="ch chi">대기</span>
<span class="ch chi">완료</span>
<span class="ch chi">CRITICAL</span>
</div>
<div class="ls">
<div class="cd">
<div class="ct"><span class="si">SR-20260531-0042</span><span class="pr pc">CRITICAL</span></div>
<div class="cn">행정망 WAS 서비스 장애 — 즉시 대응 요망</div>
<div class="cm"><span>서울시청</span><div class="dt"></div><span>WAS-01</span><div class="dt"></div><span>10분 전</span></div>
<div class="sr2"><div class="av2"><div class="av" style="background:linear-gradient(135deg,#6366f1,#8b5cf6)"></div><span class="an">김엔지니어</span></div><span class="stb sp">처리중</span></div>
</div>
<div class="cd">
<div class="ct"><span class="si">SR-20260531-0041</span><span class="pr ph">HIGH</span></div>
<div class="cn">Tomcat 8.5 재기동 요청</div>
<div class="cm"><span>안산시청</span><div class="dt"></div><span>WAS-02</span><div class="dt"></div><span>23분 전</span></div>
<div class="sr2"><div class="av2"><div class="av" style="background:linear-gradient(135deg,#0ea5e9,#06b6d4)"></div><span class="an">박엔지니어</span></div><span class="stb sw">대기</span></div>
</div>
<div class="cd">
<div class="ct"><span class="si">SR-20260531-0040</span><span class="pr pm">MEDIUM</span></div>
<div class="cn">DB 백업 스케줄 매일 02:00 변경</div>
<div class="cm"><span>수원시청</span><div class="dt"></div><span>DB-01</span><div class="dt"></div><span>1시간 전</span></div>
<div class="sr2"><div class="av2"><div class="av" style="background:linear-gradient(135deg,#10b981,#059669)"></div><span class="an">이엔지니어</span></div><span class="stb sc">완료</span></div>
</div>
<div class="cd">
<div class="ct"><span class="si">SR-20260531-0039</span><span class="pr pm">MEDIUM</span></div>
<div class="cn">SSL 인증서 갱신 — 만료 7일 전</div>
<div class="cm"><span>화성시청</span><div class="dt"></div><span>WEB-01</span><div class="dt"></div><span>2시간 전</span></div>
<div class="sr2"><div class="av2"><div class="av" style="background:linear-gradient(135deg,#f59e0b,#d97706)"></div><span class="an">최엔지니어</span></div><span class="stb sr3">접수됨</span></div>
</div>
</div>
<div class="fab"></div>
<div class="tb">
<div class="tab"><div class="ic">📊</div><div class="lb"></div></div>
<div class="tab"><div class="ic">📋</div><div class="lb" style="color:#60a5fa">SR</div></div>
<div class="tab"><div class="ic">🛡️</div><div class="lb">DR</div></div>
<div class="tab"><div class="ic">🤖</div><div class="lb">AI</div></div>
<div class="tab"><div class="ic">⚙️</div><div class="lb">설정</div></div>
</div>
</body></html>

View File

@ -85,17 +85,28 @@
gap: 20px;
margin-top: 40px;
}
/* 모바일 앱 스크린샷: 세로 비율 */
/* 모바일 앱 스크린샷: 세로 비율 5열 */
.gd-screenshots--mobile {
grid-template-columns: repeat(3, 1fr);
max-width: 720px;
margin-left: auto;
margin-right: auto;
grid-template-columns: repeat(5, 1fr);
gap: 14px;
}
.screenshot-card--mobile {
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 32px rgba(0,0,0,.25);
border: 3px solid #1e293b;
}
.screenshot-card--mobile .screenshot-img {
aspect-ratio: 9/16;
width: 100%;
aspect-ratio: 390/844;
object-fit: cover;
border-radius: 12px 12px 0 0;
display: block;
}
@media (max-width: 900px) {
.gd-screenshots--mobile { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
.gd-screenshots--mobile { grid-template-columns: repeat(2, 1fr); }
}
.screenshot-card {
border-radius: var(--radius);

View File

@ -138,6 +138,7 @@ export default function GuardiaDetail() {
<div className="gd-tabs">
{[
{id:'features', label:'핵심 기능'},
{id:'app', label:'모바일 앱'},
{id:'messenger', label:'Messenger Bot'},
{id:'manager', label:'Manager'},
{id:'editions', label:'에디션 비교'},
@ -258,6 +259,58 @@ export default function GuardiaDetail() {
</section>
)}
{/* ── 모바일 앱 ────────────────────────────────────── */}
{activeTab === 'app' && (
<section className="section">
<div className="container">
<div className="section-header">
<span className="section-label">GUARDiA Messenger App</span>
<h2 className="section-title">현장에서 바로<br/><em>스마트폰으로 관제</em></h2>
<div className="divider" />
<p className="section-desc">
Android · iOS 모두 지원. SR 접수·처리, DR 복구 테스트, 네트워크 장비 관제,<br/>
AI 챗봇 명령까지 어디서든 GUARDiA를 손에 쥐세요.
</p>
</div>
<div className="gd-screenshots gd-screenshots--mobile">
{[
{file:'11_app_home', caption:'홈 대시보드 — SR·서버 실시간 현황'},
{file:'12_app_sr', caption:'SR 서비스 요청 — 등록·처리·완료'},
{file:'13_app_chat', caption:'AI 챗봇 — 자연어 명령으로 서버 제어'},
{file:'14_app_dr', caption:'DR 재해복구 — RTO/RPO 실적 모니터링'},
{file:'15_app_network', caption:'네트워크 장비 — 백업·상태 현장 점검'},
].map((s,i) => (
<div key={i} className="screenshot-card screenshot-card--mobile">
<img src={`/screenshots/${s.file}.png`} alt={s.caption}
className="screenshot-img"
onError={e=>{e.target.style.display='none';e.target.nextSibling.style.display='flex';}}/>
<div className="screenshot-placeholder" style={{display:'none'}}>
<span className="icon">📱</span><span>준비 </span>
</div>
<div className="screenshot-caption">{s.caption}</div>
</div>
))}
</div>
{/* 앱 스토어 배지 */}
<div style={{display:'flex',justifyContent:'center',gap:16,marginTop:40}}>
<a href="#" style={{display:'flex',alignItems:'center',gap:10,
padding:'12px 24px',background:'#1e293b',borderRadius:12,
color:'#e2e8f0',textDecoration:'none',border:'1px solid rgba(255,255,255,.1)'}}>
<span style={{fontSize:28}}>🤖</span>
<div><div style={{fontSize:10,opacity:.6}}>다운로드</div><div style={{fontWeight:700,fontSize:15}}>Google Play</div></div>
</a>
<a href="#" style={{display:'flex',alignItems:'center',gap:10,
padding:'12px 24px',background:'#1e293b',borderRadius:12,
color:'#e2e8f0',textDecoration:'none',border:'1px solid rgba(255,255,255,.1)'}}>
<span style={{fontSize:28}}>🍎</span>
<div><div style={{fontSize:10,opacity:.6}}>다운로드</div><div style={{fontWeight:700,fontSize:15}}>App Store</div></div>
</a>
</div>
</div>
</section>
)}
{/* ── 메신저 봇 상세 소개 ──────────────────────────── */}
{activeTab === 'messenger' && (
<section className="section">