Based on Variant ZIO Complete Website design (screenshot1-13): - tokens.css: color palette (#003366, #005A8C, #00A0C8), Pretendard font, 4px grid - global.css: section-label-v, section-title-v, v-card, v-stats-section, btn-v-* - Home.jsx: SVG icons for Business cards, Variant-style section labels, dark navy KPI section - Common.css: page-hero improved (navy gradient), section labels cyan, sub-nav refined Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
380 lines
17 KiB
JavaScript
380 lines
17 KiB
JavaScript
import React, { useState, useEffect, useRef } from 'react';
|
||
import { Link } from 'react-router-dom';
|
||
import axios from 'axios';
|
||
import './Home.css';
|
||
import { useSeoMeta } from '../hooks/useSeoMeta';
|
||
|
||
/* ── 히어로 슬라이드 데이터 ─────────────────────────────── */
|
||
const SLIDES = [
|
||
{
|
||
title: 'AI 기반 인프라\n자율 운영 플랫폼',
|
||
sub: 'GUARDiA ITSM — 메신저 한 줄로 1,000개 관공서 인프라를 자동화',
|
||
cta: { label: 'GUARDiA 알아보기', path: '/solution/guardia' },
|
||
badge: 'NEW',
|
||
bg: 'slide-1',
|
||
},
|
||
{
|
||
title: '공공기관 전문\nIT 솔루션 기업',
|
||
sub: '20년 경험의 지오정보기술이 최첨단 AI 기술로 여러분과 함께합니다',
|
||
cta: { label: '회사소개 보기', path: '/company/greeting' },
|
||
badge: '',
|
||
bg: 'slide-2',
|
||
},
|
||
{
|
||
title: '에이전트리스\n자동화 혁신',
|
||
sub: '대상 서버에 소프트웨어 설치 없이 SSH만으로 레거시 인프라를 관리',
|
||
cta: { label: '도입 문의', path: '/support/contact' },
|
||
badge: '',
|
||
bg: 'slide-3',
|
||
},
|
||
];
|
||
|
||
/* ── 핵심 사업 영역 (Variant SVG 아이콘) ─────────────────── */
|
||
const BUSINESS = [
|
||
{
|
||
svg: (
|
||
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<rect x="4" y="4" width="10" height="10" rx="2.5" fill="#005A8C" opacity=".9"/>
|
||
<rect x="18" y="4" width="10" height="10" rx="2.5" fill="#00A0C8" opacity=".8"/>
|
||
<rect x="4" y="18" width="10" height="10" rx="2.5" fill="#00A0C8" opacity=".6"/>
|
||
<rect x="18" y="18" width="10" height="10" rx="2.5" fill="#003366" opacity=".85"/>
|
||
<path d="M14 9h4M9 14v4M23 14v4M14 23h4" stroke="#fff" strokeWidth="1.5" strokeLinecap="round"/>
|
||
</svg>
|
||
),
|
||
title: 'AI 자동화',
|
||
desc: 'GUARDiA ITSM 플랫폼으로 레거시 인프라 운영을 완전 자동화',
|
||
path: '/solution/guardia',
|
||
},
|
||
{
|
||
svg: (
|
||
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M16 3L28 9v14L16 29 4 23V9L16 3z" fill="#E8F0F8" stroke="#005A8C" strokeWidth="1.5"/>
|
||
<path d="M16 3v26M4 9l12 6 12-6" stroke="#005A8C" strokeWidth="1.5" strokeLinecap="round"/>
|
||
<circle cx="16" cy="15" r="3" fill="#00A0C8"/>
|
||
</svg>
|
||
),
|
||
title: 'SI 구축',
|
||
desc: '공공기관 정보화사업 시스템 통합 및 맞춤형 개발',
|
||
path: '/business/reference',
|
||
},
|
||
{
|
||
svg: (
|
||
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<rect x="3" y="5" width="26" height="22" rx="3" fill="#E8F0F8" stroke="#005A8C" strokeWidth="1.5"/>
|
||
<path d="M9 22l4-6 4 3 4-8 4 5" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
|
||
<circle cx="9" cy="22" r="2" fill="#003366"/>
|
||
<circle cx="13" cy="16" r="2" fill="#005A8C"/>
|
||
<circle cx="17" cy="19" r="2" fill="#00A0C8"/>
|
||
<circle cx="21" cy="11" r="2" fill="#005A8C"/>
|
||
<circle cx="25" cy="16" r="2" fill="#003366"/>
|
||
</svg>
|
||
),
|
||
title: 'ERP·CRM·BI',
|
||
desc: '기업 경영 효율화를 위한 통합 솔루션 패키지',
|
||
path: '/solution/erp',
|
||
},
|
||
];
|
||
|
||
/* ── GUARDiA 핵심 기능 (SVG 아이콘) ─────────────────────── */
|
||
const GUARDIA_FEATURES = [
|
||
{
|
||
svg: <svg viewBox="0 0 24 24" fill="none"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>,
|
||
label: 'ChatOps', desc: '메신저 명령으로 인프라 제어',
|
||
},
|
||
{
|
||
svg: <svg viewBox="0 0 24 24" fill="none"><rect x="2" y="3" width="20" height="14" rx="2" stroke="#00A0C8" strokeWidth="2"/><path d="M8 21h8M12 17v4" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round"/><path d="M6 9h.01M9 9h6" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round"/></svg>,
|
||
label: '에이전트리스', desc: 'SSH만으로 에이전트 설치 없음',
|
||
},
|
||
{
|
||
svg: <svg viewBox="0 0 24 24" fill="none"><path d="M3 3h7v7H3zM14 3h7v7h-7zM3 14h7v7H3zM14 14h7v7h-7z" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>,
|
||
label: '통합 ITSM', desc: 'SR·인시던트·변경·SLA 통합',
|
||
},
|
||
{
|
||
svg: <svg viewBox="0 0 24 24" fill="none"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke="#00A0C8" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>,
|
||
label: '엔터프라이즈 보안', desc: 'MFA·PAM·Zero Trust',
|
||
},
|
||
];
|
||
|
||
/* ── KPI 수치 ────────────────────────────────────────────── */
|
||
const KPIS = [
|
||
{ value: '1,000+', label: '관리 가능 기관 수' },
|
||
{ value: '99.9%', label: '시스템 가용성' },
|
||
{ value: '70%', label: 'SR 처리 시간 단축' },
|
||
{ value: '20년+', label: 'IT 사업 경험' },
|
||
];
|
||
|
||
export default function Home() {
|
||
useSeoMeta({
|
||
title: 'AI 기반 인프라 자율 운영 플랫폼 GUARDiA ITSM',
|
||
description: '(주)지오정보기술은 메신저 한 줄 명령으로 공공기관 레거시 IT 인프라를 자동 운영하는 GUARDiA ITSM을 개발합니다. 에이전트 설치 없이 SSH/SFTP로 1,000개 기관 운영 자동화.',
|
||
path: '/',
|
||
keywords: '지오정보기술, GUARDiA ITSM, 공공기관 인프라 자동화, AI 운영, ChatOps',
|
||
});
|
||
|
||
const [slide, setSlide] = useState(0);
|
||
const [paused, setPaused] = useState(false);
|
||
const [news, setNews] = useState([]);
|
||
const timerRef = useRef(null);
|
||
|
||
/* 슬라이드 자동 전환 */
|
||
useEffect(() => {
|
||
if (paused) return;
|
||
timerRef.current = setInterval(() => setSlide(s => (s + 1) % SLIDES.length), 5000);
|
||
return () => clearInterval(timerRef.current);
|
||
}, [paused]);
|
||
|
||
/* 소식 로드 */
|
||
useEffect(() => {
|
||
axios.get('/api/news?size=4').then(r => setNews(r.data.content || [])).catch(() => {});
|
||
}, []);
|
||
|
||
const prevSlide = () => setSlide(s => (s - 1 + SLIDES.length) % SLIDES.length);
|
||
const nextSlide = () => setSlide(s => (s + 1) % SLIDES.length);
|
||
|
||
const current = SLIDES[slide];
|
||
|
||
return (
|
||
<main id="main-content">
|
||
|
||
{/* ── 히어로 슬라이더 ──────────────────────────────── */}
|
||
<section className={`hero hero-${slide}`}
|
||
onMouseEnter={() => setPaused(true)}
|
||
onMouseLeave={() => setPaused(false)}
|
||
aria-label="메인 슬라이더">
|
||
<div className="hero-overlay" />
|
||
<div className="hero-content container">
|
||
{current.badge && (
|
||
<span className="hero-badge">{current.badge}</span>
|
||
)}
|
||
<h1 className="hero-title">
|
||
{current.title.split('\n').map((line, i) => (
|
||
<React.Fragment key={i}>{line}{i < current.title.split('\n').length - 1 && <br/>}</React.Fragment>
|
||
))}
|
||
</h1>
|
||
<p className="hero-sub">{current.sub}</p>
|
||
<div className="hero-actions">
|
||
<Link to={current.cta.path} className="btn btn-white btn-lg">
|
||
{current.cta.label} →
|
||
</Link>
|
||
<Link to="/support/contact" className="btn btn-outline hero-btn-contact btn-lg">
|
||
무료 상담
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 슬라이드 컨트롤 */}
|
||
<div className="hero-controls">
|
||
<button onClick={prevSlide} aria-label="이전 슬라이드" className="hero-arrow">‹</button>
|
||
<div className="hero-dots">
|
||
{SLIDES.map((_, i) => (
|
||
<button key={i} className={`hero-dot ${i === slide ? 'active' : ''}`}
|
||
onClick={() => setSlide(i)}
|
||
aria-label={`슬라이드 ${i + 1}`} />
|
||
))}
|
||
</div>
|
||
<button onClick={nextSlide} aria-label="다음 슬라이드" className="hero-arrow">›</button>
|
||
<button onClick={() => setPaused(v => !v)} className="hero-pause" aria-label={paused ? '재생' : '일시정지'}>
|
||
{paused ? '▶' : '⏸'}
|
||
</button>
|
||
</div>
|
||
|
||
{/* 스크롤 유도 */}
|
||
<div className="hero-scroll-hint" aria-hidden="true">
|
||
<span>SCROLL</span>
|
||
<div className="scroll-line" />
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── 핵심 사업 영역 (Variant 스타일) ─────────────────── */}
|
||
<section className="section py-section bg-light">
|
||
<div className="container">
|
||
<div style={{ textAlign: 'center', marginBottom: '48px' }}>
|
||
<span className="section-label-v">저희 서비스</span>
|
||
<h2 className="section-title-v">핵심 전문성 및 솔루션</h2>
|
||
<div className="section-underline" />
|
||
</div>
|
||
<div className="grid-3">
|
||
{BUSINESS.map((b, i) => (
|
||
<Link to={b.path} key={i} style={{ textDecoration: 'none' }}>
|
||
<div className="v-card" style={{ height: '100%' }}>
|
||
<div className="v-icon-box">{b.svg}</div>
|
||
<h3 className="v-card-title">{b.title}</h3>
|
||
<p className="v-card-desc">{b.desc}</p>
|
||
<span style={{ display: 'inline-block', marginTop: '16px', fontSize: '14px',
|
||
fontWeight: 700, color: 'var(--v-cyan-500)', letterSpacing: '.02em' }}>
|
||
자세히 보기 →
|
||
</span>
|
||
</div>
|
||
</Link>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── GUARDiA 솔루션 하이라이트 (Variant 스타일) ────────── */}
|
||
<section className="section section-guardia py-section">
|
||
<div className="container">
|
||
<div className="guardia-inner">
|
||
<div className="guardia-text">
|
||
<span className="section-label-v" style={{ textAlign: 'left' }}>대표 솔루션</span>
|
||
<h2 className="section-title-v" style={{ textAlign: 'left' }}>
|
||
GUARDiA ITSM<br/>
|
||
<span style={{ color: 'var(--v-cyan-500)' }}>AI 기반 인프라 자율 운영</span>
|
||
</h2>
|
||
<div className="section-underline left" />
|
||
<p className="guardia-desc">
|
||
1,000개 이상의 관공서 레거시 인프라를 메신저 한 줄 명령으로 제어하는
|
||
온프레미스 AI ChatOps 플랫폼. 에이전트 설치 없이 SSH/SFTP만으로
|
||
배포·운영을 완전 자동화합니다.
|
||
</p>
|
||
<div className="guardia-features">
|
||
{GUARDIA_FEATURES.map((f, i) => (
|
||
<div key={i} className="guardia-feature">
|
||
<span className="feature-icon" style={{ background: 'var(--v-blue-100)', borderRadius: '8px', padding: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', width: '40px', height: '40px', flexShrink: 0 }}>
|
||
{f.svg}
|
||
</span>
|
||
<div>
|
||
<strong style={{ color: 'var(--v-navy-700)' }}>{f.label}</strong>
|
||
<p style={{ color: 'var(--v-gray-600)' }}>{f.desc}</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
<div className="guardia-actions" style={{ display: 'flex', gap: '12px', flexWrap: 'wrap' }}>
|
||
<Link to="/solution/guardia" className="btn-v-primary">
|
||
GUARDiA 상세보기
|
||
</Link>
|
||
<Link to="/support/contact" className="btn-v-ghost">
|
||
도입 문의
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
<div className="guardia-visual">
|
||
<div className="guardia-mockup">
|
||
<div className="mockup-bar">
|
||
<span/><span/><span/>
|
||
</div>
|
||
<div className="mockup-content">
|
||
<div className="mockup-chat">
|
||
<div className="chat-msg bot">
|
||
<span className="chat-name">GUARDiA Bot</span>
|
||
<p>안녕하세요! 무엇을 도와드릴까요?</p>
|
||
</div>
|
||
<div className="chat-msg user">
|
||
<p>/deploy web-server-01</p>
|
||
</div>
|
||
<div className="chat-msg bot">
|
||
<p>✅ web-server-01 배포 완료<br/>헬스체크: 정상 | 소요: 42초</p>
|
||
</div>
|
||
<div className="chat-msg user">
|
||
<p>/status</p>
|
||
</div>
|
||
<div className="chat-msg bot">
|
||
<p>📊 시스템 현황<br/>SR 처리중: 3건 | SLA 준수율: 98.2%<br/>서버 이상: 0건 ✅</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── KPI 수치 (Variant 다크 네이비) ─────────────────── */}
|
||
<section className="v-stats-section">
|
||
<div className="container">
|
||
<div style={{ textAlign: 'center', marginBottom: '56px' }}>
|
||
<span className="section-label-v" style={{ color: 'var(--v-cyan-400)' }}>숫자로 보는 지오정보기술</span>
|
||
<h2 style={{ fontSize: 'clamp(24px,3vw,36px)', fontWeight: 800, color: '#fff', marginTop: '8px' }}>
|
||
신뢰받는 IT 파트너
|
||
</h2>
|
||
</div>
|
||
<div className="grid-4">
|
||
{KPIS.map((k, i) => (
|
||
<div key={i} style={{ textAlign: 'center', padding: '24px 16px',
|
||
borderRight: i < KPIS.length - 1 ? '1px solid rgba(255,255,255,.1)' : 'none' }}>
|
||
<div className="v-stat-number">
|
||
{k.value.replace(/[+%년]/g, '')}
|
||
<span className="v-stat-unit">{k.value.match(/[+%년]/)?.[0] || ''}</span>
|
||
</div>
|
||
<div className="v-stat-label">{k.label}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── 최신 소식 (Variant 스타일) ──────────────────────── */}
|
||
<section className="section section-news py-section bg-white">
|
||
<div className="container">
|
||
<div className="section-header" style={{ marginBottom: '48px' }}>
|
||
<span className="section-label-v">최신 소식</span>
|
||
<h2 className="section-title-v">지오정보기술 소식</h2>
|
||
<div className="section-underline" />
|
||
</div>
|
||
<div className="news-grid">
|
||
{news.length > 0 ? news.map(n => (
|
||
<Link to={`/news/newsroom/${n.id}`} key={n.id} className="news-card card">
|
||
<div className="news-card-body">
|
||
<span className={`badge badge-accent`}>{n.category}</span>
|
||
<h3 className="news-title">{n.title}</h3>
|
||
<p className="news-summary">{n.summary}</p>
|
||
</div>
|
||
<div className="news-card-footer">
|
||
<span className="news-date">
|
||
{n.createdAt ? new Date(n.createdAt).toLocaleDateString('ko-KR') : ''}
|
||
</span>
|
||
<span className="news-more">더보기 →</span>
|
||
</div>
|
||
</Link>
|
||
)) : (
|
||
/* 스켈레톤 */
|
||
Array.from({length: 4}).map((_, i) => (
|
||
<div key={i} className="news-card card skeleton">
|
||
<div className="skel-line" style={{width:'30%',height:'16px'}} />
|
||
<div className="skel-line" style={{width:'90%',height:'20px',marginTop:'8px'}} />
|
||
<div className="skel-line" style={{width:'70%',height:'14px',marginTop:'6px'}} />
|
||
</div>
|
||
))
|
||
)}
|
||
</div>
|
||
<div style={{textAlign:'center',marginTop:'40px'}}>
|
||
<Link to="/news/newsroom" className="btn btn-outline">
|
||
모든 소식 보기
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
{/* ── CTA 배너 (Variant v-cta-banner) ─────────────────── */}
|
||
<section className="py-section bg-light">
|
||
<div className="container">
|
||
<div className="v-cta-banner">
|
||
<div>
|
||
<div className="v-cta-title">
|
||
GUARDiA ITSM 도입을 검토하고 계신가요?
|
||
</div>
|
||
<p className="v-cta-sub">
|
||
전문 컨설턴트가 귀 기관 환경에 맞는 최적의 방안을 제안해 드립니다.
|
||
</p>
|
||
</div>
|
||
<div style={{ display: 'flex', gap: '12px', flexShrink: 0, flexWrap: 'wrap' }}>
|
||
<Link to="/support/contact" className="btn-v-primary btn-v-cyan">
|
||
무료 상담 신청
|
||
</Link>
|
||
<Link to="/solution/guardia"
|
||
style={{ display: 'inline-flex', alignItems: 'center', padding: '12px 24px',
|
||
background: 'rgba(255,255,255,.15)', color: '#fff', fontWeight: 600, fontSize: '15px',
|
||
borderRadius: '9999px', border: '1px solid rgba(255,255,255,.3)',
|
||
textDecoration: 'none', transition: 'all 240ms' }}>
|
||
제품 소개서 →
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
);
|
||
}
|