# IT센터 출입자관리시스템 (Access Control System) IT센터 방문자/출입자 관리 웹 시스템. 방문 사전신청·승인, 입·출입 체크인, QR/배지 발급, 통계·리포트·블랙리스트를 목표로 하며, 출입통제 하드웨어는 추후 연동 가능하도록 추상화한다. ## 기술 스택 - **백엔드**: Spring Boot 3.4.5 / Java 21 (JDK 26 빌드) · Spring Security(세션) · JPA · H2(dev)·PostgreSQL(prod) · POI · ZXing · Flyway - **프론트엔드**: React 19 · Vite 6 · TypeScript · react-router 7 - **포트**: API `8080`, 웹 `5173` ## 역할 | 역할 | 권한 | |------|------| | `ADMIN` | 전체 관리, 사용자/블랙리스트/리포트, 모든 승인 | | `SECURITY` | 입·출입 콘솔(체크인/아웃), 재실현황, 배지 발급 | | `HOST` | 방문 사전신청 등록, 담당 방문 승인 | ## 실행 (로컬 개발, H2) ```cmd :: 백엔드 (http://localhost:8080) run-backend.cmd :: 프론트엔드 (http://localhost:5173) run-frontend.cmd ``` > 두 스크립트는 `C:\ai-dev\scripts\env.cmd`(포터블 JDK/Maven/Node)를 먼저 로드한다. ### 초기 계정 (DataSeeder, dev 전용) | 아이디 | 비밀번호 | 역할 | |--------|----------|------| | admin | ChangeMe123! | ADMIN | | security | ChangeMe123! | SECURITY | | host | ChangeMe123! | HOST | 최초 로그인 시 비밀번호 변경이 요구된다. ## 주요 API - `POST /api/auth/login` · `POST /api/auth/logout` · `GET /api/auth/me` · `POST /api/auth/change-password` - `GET /api/zones` - `GET/POST /api/visit-requests` · `GET /api/visit-requests/pending` · `POST /api/visit-requests/{id}/cancel` · `POST /api/visit-requests/upload`(엑셀) - `POST /api/approvals/{id}/approve` · `POST /api/approvals/{id}/reject` - `POST /api/access/check-in` · `POST /api/access/check-out` · `GET /api/access/inside` · `GET /api/access/search?q=` - `GET /api/passes/{id}` · `GET /api/passes/{id}/qr.png`(배지 QR) - `GET /api/stats/summary` · `GET /api/reports/visits.xlsx?from=&to=` - `GET/POST /api/blacklist` · `DELETE /api/blacklist/{id}` (ADMIN) API 스모크 테스트는 [backend/test-api.http](backend/test-api.http) 참고. ## 구현 현황 - [x] **1단계** 스캐폴딩 (pom, 설정, 공통 클래스, 전역 예외/응답 래퍼, JPA auditing) - [x] **2단계** 인증·인가 (세션 로그인, 역할 기반 권한, 시드) - [x] **3단계** 방문 사전신청 + 승인 (신청/취소/엑셀 업로드, 승인/반려 시 qrToken 발급) + 프론트 화면 - [x] **4단계** 입·출입 체크인/체크아웃 + 재실현황 (`AccessEvent`, `AccessControlGateway`+Mock, QR/이름 체크인, 재실 목록, 중복입장·만료 검증) + 출입콘솔 화면 - [x] **5단계** QR/배지 발급 (ZXing PNG `/api/passes/{id}/qr.png`, 배지 인쇄 화면) - [x] **6단계** 블랙리스트(체크인 시 차단) + 대시보드 통계 집계 + 방문 리포트 엑셀(POI) 다운로드 - [x] **7단계** Flyway `V1__init.sql`(prod) + Docker Compose(db·app·web nginx) + Python 사용자 시드 ## Docker 실행 (prod, PostgreSQL) ```bash cd infra cp .env.example .env # 값 수정 (아래 참고) docker compose up -d --build # db + app(:8080) + web(nginx :80) docker compose run --rm seed # 사용자 시드 적재 (admin/security/host) docker compose logs -f app # 기동/마이그레이션 로그 ``` - 백엔드는 `prod` 프로파일로 기동, Flyway가 스키마를 생성/검증한다. - 웹(nginx)이 정적 파일 + `/api` 리버스 프록시를 담당한다. - DB는 named volume(`db_data`)에 영속 — 재기동해도 데이터 유지(dev H2와 다름). ### .env 주요 값 | 변수 | 설명 | |------|------| | `POSTGRES_PASSWORD` | DB 비밀번호 (실제값으로 변경) | | `WEB_PORT` | 웹 공개 포트 (기본 80) | | `ACS_SMS_PROVIDER` | `dev`(로그만) / `hanbank`(사내 API로 LMS 실발송) | | `ACS_PUBLIC_BASE_URL` | 문자 링크가 가리키는 주소 — **방문자 휴대폰에서 접속 가능한 실제 URL** (localhost 금지) | | `ACS_SMS_API_URL` | 사내 메시지 API 주소 (기본 `http://210.104.132.59:8000`) | ### 문자 실발송(hanbank) 전제 1. 서버에서 메시지 API 도달 확인: `nc -vz 210.104.132.59 8000` 2. `ACS_SMS_PROVIDER=hanbank`, `ACS_PUBLIC_BASE_URL`=외부 접속 URL 로 설정 후 재기동 ### HTTPS / 카메라 스캔 (선택, 접속 방식에 따라 필요) - 출입콘솔의 **웹캠 QR 스캔**은 secure context(HTTPS 또는 localhost)에서만 동작한다. 서버를 `http://내부IP`로 접속하면 카메라가 차단된다. - 방문자 공개 링크(`/pass/{token}`)도 HTTPS 도메인이면 휴대폰에서 안전하게 열린다. - 적용하려면: 사내 도메인/인증서 확보 → `frontend/nginx.conf`에 443 TLS server 블록 추가, `docker-compose.yml` web 서비스에 `"443:443"` 매핑 + 인증서 볼륨 마운트, `ACS_PUBLIC_BASE_URL`을 `https://...`로 설정. (도메인/인증서 확정 후 진행) ### 사내망 빌드 참고 `docker compose build`는 컨테이너 안에서 npm/maven 의존성을 받는다. dev 서버는 공개망 직접 접근이 되어 대개 그대로 성공하지만, 사내 SSL 인스펙션에 걸려 인증서 오류가 나면 Dockerfile에 사내 CA 주입 또는 내부 미러 설정이 필요하다(그때 별도 반영). ## 디렉터리 ``` backend/ Spring Boot (com.itcenter.acs) frontend/ React + Vite docs/ 워크플로우·시퀀스 다이어그램·이슈/유의사항 문서 ``` ## 문서 - [docs/workflow.md](docs/workflow.md) — 전체 업무 워크플로우(서술형) - [docs/workflow-sequence.md](docs/workflow-sequence.md) — 시퀀스/상태 다이어그램(Mermaid) - [docs/issues-and-guidelines.md](docs/issues-and-guidelines.md) — 이슈 정리 및 유의사항(규칙) ## 빌드 노트 - JDK 26 환경에서 Lombok은 **1.18.46** + maven-compiler-plugin `annotationProcessorPaths` 설정이 필요하다 (Spring Boot가 핀한 1.18.38은 JDK 26에서 애너테이션 처리가 동작하지 않음). `backend/pom.xml`에 반영됨.