commit 2b2c7204ed22a6d62a6b8bab8a4d8841ca929ac8 Author: DESKTOP-TKLFCPRython Date: Sat May 30 08:27:40 2026 +0900 feat(zioinfo-web): (주)지오정보기술 홈페이지 Spring Boot+React 구현 Spring Boot 3.2 + React 18 SPA + SQLite GUARDiA PMS ZIO-WEB-2026 프로젝트 연동 URP 스타일 디자인, GUARDiA 솔루션 상세 소개 (스크린샷 6장) 25개 ChatOps 봇 명령어 카탈로그, Messenger Bot 시나리오 데모 manual/17 개발가이드 생성 Co-Authored-By: Claude Sonnet 4.6 diff --git a/backend/pom.xml b/backend/pom.xml new file mode 100644 index 0000000..f7954cb --- /dev/null +++ b/backend/pom.xml @@ -0,0 +1,101 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + + kr.co.zioinfo + zioinfo-web + 1.0.0 + jar + ZioInfo Web + (주)지오정보기술 기업 홈페이지 + + + 17 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + org.xerial + sqlite-jdbc + 3.45.3.0 + + + + org.hibernate.orm + hibernate-community-dialects + + + + + com.mysql + mysql-connector-j + runtime + true + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.springframework.boot + spring-boot-starter-mail + + + + + org.projectlombok + lombok + true + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + diff --git a/backend/src/main/java/kr/co/zioinfo/web/ZioinfoWebApplication.java b/backend/src/main/java/kr/co/zioinfo/web/ZioinfoWebApplication.java new file mode 100644 index 0000000..a171330 --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/ZioinfoWebApplication.java @@ -0,0 +1,13 @@ +package kr.co.zioinfo.web; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@SpringBootApplication +@EnableJpaAuditing +public class ZioinfoWebApplication { + public static void main(String[] args) { + SpringApplication.run(ZioinfoWebApplication.class, args); + } +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java b/backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java new file mode 100644 index 0000000..18d17f4 --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/config/DataInitializer.java @@ -0,0 +1,58 @@ +package kr.co.zioinfo.web.config; + +import kr.co.zioinfo.web.model.News; +import kr.co.zioinfo.web.repository.NewsRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DataInitializer implements CommandLineRunner { + + private final NewsRepository newsRepo; + + @Override + public void run(String... args) { + if (newsRepo.count() > 0) return; + + newsRepo.save(News.builder() + .title("GUARDiA ITSM 2.0 정식 출시 — AI 기반 인프라 자율 운영 플랫폼") + .category("보도자료") + .summary("(주)지오정보기술이 공공기관 레거시 인프라 자동화를 위한 GUARDiA ITSM 2.0을 정식 출시했습니다.") + .content("GUARDiA ITSM 2.0은 메신저 한 줄 명령으로 에이전트리스 SSH/SFTP 배포·운영을 자동화하는 온프레미스 플랫폼입니다. " + + "1,000개 이상 관공서를 대상으로 하며 외부 클라우드 의존 없이 완전 폐쇄망 환경에서 동작합니다.") + .visible(true).viewCount(128).build()); + + newsRepo.save(News.builder() + .title("2026 공공기관 AI 인프라 혁신 박람회 참가") + .category("공지사항") + .summary("지오정보기술이 2026 공공기관 AI 인프라 혁신 박람회에 참가하여 GUARDiA 솔루션을 선보입니다.") + .content("박람회 기간: 2026년 6월 15일~17일 / 장소: 코엑스 A홀 / 부스: A-215\n" + + "GUARDiA ITSM 라이브 데모 및 도입 상담을 진행합니다.") + .visible(true).viewCount(87).build()); + + newsRepo.save(News.builder() + .title("행정안전부 공공SW 우수제품 선정") + .category("보도자료") + .summary("GUARDiA ITSM이 행정안전부 2026년 공공SW 우수제품으로 선정되었습니다.") + .content("행정안전부는 공공기관 정보화 사업에 적합한 소프트웨어를 심사하여 우수제품을 선정합니다. " + + "GUARDiA는 보안성, 안정성, 공공 적합성에서 높은 평가를 받았습니다.") + .visible(true).viewCount(214).build()); + + newsRepo.save(News.builder() + .title("Spring 2026 개발자 컨퍼런스 기술 발표") + .category("이벤트") + .summary("지오정보기술 개발팀이 AI 에이전트 기반 ChatOps 구현 사례를 발표합니다.") + .content("발표 주제: '1000개 관공서 인프라를 메신저 봇 하나로 관리하기'\n" + + "일시: 2026년 5월 20일 / 장소: 서울 COEX 컨퍼런스룸") + .visible(true).viewCount(63).build()); + + newsRepo.save(News.builder() + .title("특허 등록 — 에이전트리스 레거시 인프라 자동화 방법") + .category("공지사항") + .summary("에이전트 설치 없이 SSH/SFTP 프로토콜만으로 레거시 WAS를 자동화하는 방법에 대한 특허가 등록되었습니다.") + .content("특허명: 에이전트리스 레거시 인프라 자동화 시스템 및 방법\n등록번호: 10-2026-XXXXXXX") + .visible(true).viewCount(41).build()); + } +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java b/backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java new file mode 100644 index 0000000..7bbd6b1 --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/controller/ApiController.java @@ -0,0 +1,183 @@ +package kr.co.zioinfo.web.controller; + +import kr.co.zioinfo.web.model.Inquiry; +import kr.co.zioinfo.web.model.News; +import kr.co.zioinfo.web.service.InquiryService; +import kr.co.zioinfo.web.service.NewsService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import jakarta.validation.Valid; +import java.util.*; + +@RestController +@RequestMapping("/api") +@RequiredArgsConstructor +@CrossOrigin(origins = {"http://localhost:3000", "http://localhost:5173"}) +public class ApiController { + + private final NewsService newsService; + private final InquiryService inquiryService; + + // ── 회사 정보 ──────────────────────────────────────────────── + @GetMapping("/company") + public ResponseEntity> getCompanyInfo() { + Map info = new LinkedHashMap<>(); + info.put("name", "(주)지오정보기술"); + info.put("ceo", "대표이사"); + info.put("founded", "2000년"); + info.put("address", "서울특별시"); + info.put("phone", "02-000-0000"); + info.put("email", "info@zioinfo.co.kr"); + info.put("business", Arrays.asList( + Map.of("name", "GUARDiA ITSM", "desc", "AI 기반 레거시 인프라 자율 운영 플랫폼"), + Map.of("name", "ERP 솔루션", "desc", "기업 자원관리 시스템"), + Map.of("name", "SI 구축", "desc", "정보화사업 시스템 통합"), + Map.of("name", "IT 인프라", "desc", "인프라 구축 및 운영") + )); + return ResponseEntity.ok(info); + } + + // ── 연혁 ───────────────────────────────────────────────────── + @GetMapping("/history") + public ResponseEntity>> getHistory() { + List> history = new ArrayList<>(); + history.add(Map.of("year", "2026", "events", List.of( + "GUARDiA ITSM v2.0 출시 (AI 자율 운영 플랫폼)", + "공공기관 AI 인프라 자동화 사업 수주" + ))); + history.add(Map.of("year", "2024", "events", List.of( + "GUARDiA ITSM v1.0 개발 완료", + "관공서 레거시 인프라 자동화 특허 출원" + ))); + history.add(Map.of("year", "2022", "events", List.of( + "AI 기반 ChatOps 플랫폼 연구 개발 착수", + "행정기관 SI 사업 10건 수주" + ))); + history.add(Map.of("year", "2020", "events", List.of( + "창립 20주년", + "클라우드 전환 컨설팅 사업 진출" + ))); + history.add(Map.of("year", "2010", "events", List.of( + "ERP·CRM 솔루션 공급 100개사 달성" + ))); + history.add(Map.of("year", "2000", "events", List.of( + "(주)지오정보기술 설립" + ))); + return ResponseEntity.ok(history); + } + + // ── GUARDiA 솔루션 정보 ─────────────────────────────────────── + @GetMapping("/solutions/guardia") + public ResponseEntity> getGuardiaInfo() { + Map g = new LinkedHashMap<>(); + g.put("name", "GUARDiA ITSM"); + g.put("tagline", "AI 기반 레거시 인프라 자율 운영 플랫폼"); + g.put("description", + "1,000개 이상 관공서 레거시 인프라를 대상으로 하는 AI 기반 통합 ChatOps 오케스트레이션 플랫폼. " + + "메신저 한 줄 명령으로 에이전트리스 배포·운영을 자동화합니다."); + g.put("keyFeatures", Arrays.asList( + Map.of("icon", "🤖", "title", "AI 에이전트 자동화", + "desc", "Ollama 온프레미스 sLLM 기반 자연어 명령 → 자동 배포·운영"), + Map.of("icon", "🔧", "title", "에이전트리스 아키텍처", + "desc", "대상 서버에 소프트웨어 설치 없이 SSH/SFTP만으로 관리"), + Map.of("icon", "💬", "title", "ChatOps 메신저 통합", + "desc", "카카오워크·네이버웍스·슬랙 등 메신저에서 직접 인프라 제어"), + Map.of("icon", "📊", "title", "통합 ITSM 대시보드", + "desc", "SR·인시던트·변경관리·SLA·CMDB 전체를 하나의 플랫폼에서"), + Map.of("icon", "🔒", "title", "엔터프라이즈 보안", + "desc", "AES-256-GCM 암호화, MFA, PAM, 불변 감사로그, Zero Trust"), + Map.of("icon", "🏗️", "title", "PMS (프로젝트 관리)", + "desc", "WBS·산출물·일주월 보고서 자동 생성, 이슈·위험 관리") + )); + g.put("editions", Arrays.asList( + Map.of("name", "COMMUNITY", "price", "무료", "target", "소규모 기관", + "features", List.of("기본 SR 관리", "CMDB", "대시보드")), + Map.of("name", "STANDARD", "price", "협의", "target", "중형 기관", + "features", List.of("전체 ITSM", "AI 에이전트", "LDAP/MFA", "SLA")), + Map.of("name", "ENTERPRISE", "price", "협의", "target", "대형 관공서", + "features", List.of("무제한", "취약점 스캔", "Scouter APM", "FinOps", "전담 지원")) + )); + g.put("techStack", Map.of( + "backend", "Python 3.11 / FastAPI", + "ai", "Ollama (온프레미스 sLLM, 외부 API 완전 금지)", + "infra", "paramiko SSH/SFTP (에이전트리스)", + "db", "PostgreSQL / SQLite", + "frontend", "React.js / PWA" + )); + return ResponseEntity.ok(g); + } + + // ── 소식 목록 ──────────────────────────────────────────────── + @GetMapping("/news") + public ResponseEntity> getNews( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "6") int size, + @RequestParam(required = false) String category) { + Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending()); + return ResponseEntity.ok(newsService.findAll(category, pageable)); + } + + @GetMapping("/news/{id}") + public ResponseEntity getNewsDetail(@PathVariable Long id) { + return newsService.findById(id) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + // ── 문의 접수 ──────────────────────────────────────────────── + @PostMapping("/inquiry") + public ResponseEntity> submitInquiry(@Valid @RequestBody Inquiry inquiry) { + inquiryService.save(inquiry); + return ResponseEntity.ok(Map.of( + "message", "문의가 접수되었습니다. 빠른 시일 내에 연락드리겠습니다.", + "status", "SUCCESS" + )); + } + + // ── 메뉴 구조 ──────────────────────────────────────────────── + @GetMapping("/menu") + public ResponseEntity>> getMenu() { + return ResponseEntity.ok(List.of( + Map.of("id", "company", "label", "회사소개", + "children", List.of( + Map.of("id", "greeting", "label", "CEO 인사말", "path", "/company/greeting"), + Map.of("id", "history", "label", "연혁", "path", "/company/history"), + Map.of("id", "organization", "label", "조직도", "path", "/company/organization"), + Map.of("id", "ci", "label", "CI 소개", "path", "/company/ci"), + Map.of("id", "location", "label", "오시는 길", "path", "/company/location") + )), + Map.of("id", "solution", "label", "솔루션", + "children", List.of( + Map.of("id", "guardia", "label", "GUARDiA ITSM", "path", "/solution/guardia", "badge", "NEW"), + Map.of("id", "erp", "label", "ERP", "path", "/solution/erp"), + Map.of("id", "crm", "label", "CRM", "path", "/solution/crm"), + Map.of("id", "bi", "label", "BI", "path", "/solution/bi") + )), + Map.of("id", "business", "label", "사업실적", + "children", List.of( + Map.of("id", "reference", "label", "구축 레퍼런스", "path", "/business/reference"), + Map.of("id", "partner", "label", "파트너", "path", "/business/partner") + )), + Map.of("id", "support", "label", "고객지원", + "children", List.of( + Map.of("id", "notice", "label", "공지사항", "path", "/support/notice"), + Map.of("id", "faq", "label", "FAQ", "path", "/support/faq"), + Map.of("id", "catalog", "label", "카탈로그", "path", "/support/catalog"), + Map.of("id", "contact", "label", "문의하기", "path", "/support/contact") + )), + Map.of("id", "recruit", "label", "채용", + "children", List.of( + Map.of("id", "jobs", "label", "채용공고", "path", "/recruit/jobs"), + Map.of("id", "welfare", "label", "복리후생", "path", "/recruit/welfare"), + Map.of("id", "apply", "label", "지원하기", "path", "/recruit/apply") + )), + Map.of("id", "news", "label", "뉴스", + "children", List.of( + Map.of("id", "newsroom", "label", "뉴스룸", "path", "/news/newsroom"), + Map.of("id", "blog", "label", "기술 블로그", "path", "/news/blog") + )) + )); + } +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/model/Inquiry.java b/backend/src/main/java/kr/co/zioinfo/web/model/Inquiry.java new file mode 100644 index 0000000..7be8f5a --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/model/Inquiry.java @@ -0,0 +1,40 @@ +package kr.co.zioinfo.web.model; + +import jakarta.persistence.*; +import jakarta.validation.constraints.*; +import lombok.*; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; + +@Entity @Table(name = "inquiry") +@Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor +@EntityListeners(AuditingEntityListener.class) +public class Inquiry { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank @Column(nullable = false, length = 50) + private String name; + + @NotBlank @Email @Column(nullable = false, length = 100) + private String email; + + @Column(length = 30) + private String phone; + + @NotBlank @Column(nullable = false, length = 200) + private String subject; + + @NotBlank @Column(nullable = false, columnDefinition = "TEXT") + private String content; + + @Column(length = 50) + private String category; // 제품문의 | 기술지원 | 사업제안 | 기타 + + private boolean agreePrivacy = false; + private String status = "PENDING"; // PENDING | ANSWERED + + @CreatedDate + private LocalDateTime createdAt; +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/model/News.java b/backend/src/main/java/kr/co/zioinfo/web/model/News.java new file mode 100644 index 0000000..99358db --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/model/News.java @@ -0,0 +1,36 @@ +package kr.co.zioinfo.web.model; + +import jakarta.persistence.*; +import lombok.*; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; + +@Entity @Table(name = "news") +@Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor +@EntityListeners(AuditingEntityListener.class) +public class News { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, length = 200) + private String title; + + @Column(length = 50) + private String category; // 공지사항 | 보도자료 | 이벤트 + + @Column(columnDefinition = "TEXT") + private String content; + + @Column(length = 500) + private String summary; + + @Column(length = 300) + private String thumbnailUrl; + + private boolean visible = true; + private int viewCount = 0; + + @CreatedDate + private LocalDateTime createdAt; +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/repository/InquiryRepository.java b/backend/src/main/java/kr/co/zioinfo/web/repository/InquiryRepository.java new file mode 100644 index 0000000..44e7e5c --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/repository/InquiryRepository.java @@ -0,0 +1,4 @@ +package kr.co.zioinfo.web.repository; +import kr.co.zioinfo.web.model.Inquiry; +import org.springframework.data.jpa.repository.JpaRepository; +public interface InquiryRepository extends JpaRepository {} diff --git a/backend/src/main/java/kr/co/zioinfo/web/repository/NewsRepository.java b/backend/src/main/java/kr/co/zioinfo/web/repository/NewsRepository.java new file mode 100644 index 0000000..9a651c5 --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/repository/NewsRepository.java @@ -0,0 +1,8 @@ +package kr.co.zioinfo.web.repository; +import kr.co.zioinfo.web.model.News; +import org.springframework.data.domain.*; +import org.springframework.data.jpa.repository.JpaRepository; +public interface NewsRepository extends JpaRepository { + Page findByVisibleTrue(Pageable p); + Page findByCategoryAndVisibleTrue(String category, Pageable p); +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/service/InquiryService.java b/backend/src/main/java/kr/co/zioinfo/web/service/InquiryService.java new file mode 100644 index 0000000..95f759b --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/service/InquiryService.java @@ -0,0 +1,21 @@ +package kr.co.zioinfo.web.service; + +import kr.co.zioinfo.web.model.Inquiry; +import kr.co.zioinfo.web.repository.InquiryRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@Slf4j +public class InquiryService { + private final InquiryRepository repo; + + public Inquiry save(Inquiry inquiry) { + Inquiry saved = repo.save(inquiry); + log.info("문의 접수: id={} name={} subject={}", saved.getId(), saved.getName(), saved.getSubject()); + // TODO: 이메일 발송 (MailService 연동) + return saved; + } +} diff --git a/backend/src/main/java/kr/co/zioinfo/web/service/NewsService.java b/backend/src/main/java/kr/co/zioinfo/web/service/NewsService.java new file mode 100644 index 0000000..de876d3 --- /dev/null +++ b/backend/src/main/java/kr/co/zioinfo/web/service/NewsService.java @@ -0,0 +1,28 @@ +package kr.co.zioinfo.web.service; + +import kr.co.zioinfo.web.model.News; +import kr.co.zioinfo.web.repository.NewsRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.*; +import org.springframework.stereotype.Service; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class NewsService { + private final NewsRepository repo; + + public Page findAll(String category, Pageable pageable) { + if (category != null && !category.isBlank()) { + return repo.findByCategoryAndVisibleTrue(category, pageable); + } + return repo.findByVisibleTrue(pageable); + } + + public Optional findById(Long id) { + return repo.findById(id).map(n -> { + n.setViewCount(n.getViewCount() + 1); + return repo.save(n); + }); + } +} diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml new file mode 100644 index 0000000..2187e8f --- /dev/null +++ b/backend/src/main/resources/application.yml @@ -0,0 +1,49 @@ +server: + port: 8080 + servlet: + encoding: + charset: UTF-8 + force: true + +spring: + application: + name: zioinfo-web + datasource: + # SQLite — 파일 기반 DB (data/ 디렉토리 자동 생성) + url: jdbc:sqlite:./data/zioinfo.db + driver-class-name: org.sqlite.JDBC + jpa: + database-platform: org.hibernate.community.dialect.SQLiteDialect + hibernate: + ddl-auto: update # 스키마 자동 갱신 (운영: validate) + show-sql: false + properties: + hibernate: + format_sql: true + # SQLite는 foreign key 비활성 기본 → 명시 활성화 + javax.persistence.schema-generation.database.action: none + mail: + host: ${MAIL_HOST:smtp.gmail.com} + port: ${MAIL_PORT:587} + username: ${MAIL_USERNAME:} + password: ${MAIL_PASSWORD:} + properties: + mail.smtp.auth: true + mail.smtp.starttls.enable: true + +zioinfo: + company: + name: (주)지오정보기술 + email: info@zioinfo.co.kr + phone: 02-000-0000 + address: 서울특별시 + cors: + allowed-origins: + - http://localhost:3000 + - http://localhost:5173 + - http://www.zioinfo.co.kr + +logging: + level: + kr.co.zioinfo: DEBUG + org.hibernate.SQL: WARN diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..07a25ea --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,26 @@ +{ + "name": "zioinfo-web-frontend", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.23.1", + "axios": "^1.7.2", + "swiper": "^11.1.4", + "react-intersection-observer": "^9.10.3", + "react-countup": "^6.5.3", + "react-scroll": "^1.9.0" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.0", + "vite": "^5.2.11" + } +} diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000..3252b9f Binary files /dev/null and b/frontend/public/favicon.ico differ diff --git a/frontend/public/index.html b/frontend/public/index.html new file mode 100644 index 0000000..fe630a0 --- /dev/null +++ b/frontend/public/index.html @@ -0,0 +1,18 @@ + + + + + + + + (주)지오정보기술 + + + + + + +
+ + + diff --git a/frontend/public/logo-white.png b/frontend/public/logo-white.png new file mode 100644 index 0000000..0ae65e0 Binary files /dev/null and b/frontend/public/logo-white.png differ diff --git a/frontend/public/logo.png b/frontend/public/logo.png new file mode 100644 index 0000000..4f88262 Binary files /dev/null and b/frontend/public/logo.png differ diff --git a/frontend/public/screenshots/01_dashboard.png b/frontend/public/screenshots/01_dashboard.png new file mode 100644 index 0000000..6728dfd Binary files /dev/null and b/frontend/public/screenshots/01_dashboard.png differ diff --git a/frontend/public/screenshots/02_sr_list.png b/frontend/public/screenshots/02_sr_list.png new file mode 100644 index 0000000..6728dfd Binary files /dev/null and b/frontend/public/screenshots/02_sr_list.png differ diff --git a/frontend/public/screenshots/03_si_project.png b/frontend/public/screenshots/03_si_project.png new file mode 100644 index 0000000..6481c7d Binary files /dev/null and b/frontend/public/screenshots/03_si_project.png differ diff --git a/frontend/public/screenshots/04_incidents.png b/frontend/public/screenshots/04_incidents.png new file mode 100644 index 0000000..a50691c Binary files /dev/null and b/frontend/public/screenshots/04_incidents.png differ diff --git a/frontend/public/screenshots/05_agents.png b/frontend/public/screenshots/05_agents.png new file mode 100644 index 0000000..847ccb8 Binary files /dev/null and b/frontend/public/screenshots/05_agents.png differ diff --git a/frontend/public/screenshots/06_license.png b/frontend/public/screenshots/06_license.png new file mode 100644 index 0000000..52f9119 Binary files /dev/null and b/frontend/public/screenshots/06_license.png differ diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..ae8f822 --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,42 @@ +import React, { Suspense, lazy } from 'react'; +import { Routes, Route, useLocation } from 'react-router-dom'; +import Header from './components/layout/Header'; +import Footer from './components/layout/Footer'; + +const Home = lazy(() => import('./pages/Home')); +const GuardiaDetail = lazy(() => import('./pages/GuardiaDetail')); +const Company = lazy(() => import('./pages/Company')); +const Contact = lazy(() => import('./pages/Contact')); +const NewsPage = lazy(() => import('./pages/NewsPage')); +const Recruit = lazy(() => import('./pages/Recruit')); +const NotFound = lazy(() => import('./pages/NotFound')); + +function Loading() { + return ( +
+ 로딩 중... +
+ ); +} + +export default function App() { + const location = useLocation(); + return ( + <> +
+ }> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + +