kintex/docs/architecture/system.md
zio 214b6df1ef feat(public,security,data): visitor public site + AI guide, security hardening, V42-V45 migrations
- frontend: visitor public home (AiAssistant, AiPlanningBriefing, VisitorTrackPage),
  3-track public routing (PublicShell/App), i18n ko/en/zh/ja, favicon
- backend: public AI visitor-assistant + event calendar API (publicsite/*),
  profile avatar API (auth/profile/*), SecurityConfig CORS whitelist,
  SecretStartupValidator (B12 fail-fast, prod only), application-prod.yml,
  AppIntegrity, /api/auth/me expansion (MeResponse)
- db: V42 bulk demo seed, V43 visitor_guide/transport + event calendar view,
  V44 performance indexes, V45 app_user profile photo columns (all idempotent)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 19:05:00 +09:00

358 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 킨텍스 자동전시시스템 — 시스템 아키텍처 · 비기능요건(NFR)
> 산출: 시스템 아키텍트(SA) · 작성일: 2026-07-11 · 대상 백로그: `IMPLEMENTATION_BACKLOG.md` **A-2**
> 정합 근거: [`../PLANNING.md`](../PLANNING.md) v2.0 §2(6역할)·§7(데이터·연동)·§8(아키텍처)·§10(리스크) · [`../IMPLEMENTATION_BACKLOG.md`](../IMPLEMENTATION_BACKLOG.md) · [`../analysis/reroomai-source.md`](../analysis/reroomai-source.md)(나노바나나 워커)
> 확정 스택(불변): React 18/19(Vite·TS) + Spring Boot 3.x(Java 17)+MyBatis + PostgreSQL(PostGIS) + Redis + 나노바나나 Python 워커. — `../DEVELOPMENT_GUIDE.md` §1, `../PLANNING.md` §8
> **문서 소유권**: 본 문서는 SA(시스템 아키텍처·NFR·구성·배포 토폴로지)만 정본. 애플리케이션 경계/API 표준=AA([`app.md`](app.md), A-1), 기술 표준/빌드·관측성=TA([`tech.md`](tech.md), A-3), 전사 ERD/공간·마스터·BI마트=DA([`data.md`](data.md), A-4), DMZ/방화벽/부하분산=NA([`network.md`](network.md), A-5). 본 문서는 그 상위 시스템 관점만 다루며 세부는 각 문서로 위임(교차참조).
---
## 0. 선행 게이트 (SA 반영 — 착수 전 소유자 확인)
| 게이트 | 내용 | 시스템 아키텍처 영향 |
|---|---|---|
| **G1** | 나노바나나(Gemini `generativelanguage.googleapis.com`) 외부 호출 승인(PLANNING R12) | 미승인 시 나노바나나 워커는 **목(mock)/degraded 모드**로 기동(구조·큐·워터마크 계약은 유지, 실이미지 생성만 차단). 승인 시 워커 서비스에만 `GEMINI_API_KEY` env 주입(§6-4). **아웃바운드 방화벽 정책은 워커 서브넷 한정** — NA 확정 |
| **G2** | 배포 대상 서버·포트(GUARDiA 인프라와 **별개 도메인**) | 배포 토폴로지(§4)의 물리 매핑·도메인·포트·TLS는 G2 확정 후 Phase E에서 실체화. 본 문서는 **논리 토폴로지**를 확정하고 물리값은 플레이스홀더(`<kintex-domain>`) 처리 |
> 두 게이트는 **아키텍처 설계를 막지 않는다** — 논리 구성·NFR·용량 산정은 게이트와 무관하게 확정하고, 물리 실체화(실호출·실배포)만 게이트에 종속시킨다.
---
## 1. 시스템 개요
킨텍스 자동전시시스템은 전시 생애주기(판매·기획 → 설계·시각화 → 발주·계약 → 참가·관람 → 현장운영 → 사후·경영)를 하나의 데이터·계정 체계로 자동화하는 **베뉴 운영 플랫폼**이다. 시스템은 **6개 역할별 분리 프론트 + 단일 공유 Spring Boot 백엔드 + 나노바나나 Python 워커 사이드카**를 **SSO·역할 RBAC** 위에 얹고, **PostGIS 공간 데이터 · Redis 비동기 큐 · 오브젝트 스토리지**를 공유 자원으로 둔다.
**아키텍처 대원칙 (PLANNING §4·§8 정합)**
1. **단일 공간 데이터 모델** — 부스 폴리곤·트렌치 포인트·배선 LineString을 PostGIS 지오메트리로 일원화. 시각화(M5)·검증(M2)·정산(M9)·wayfinding(M13)·BI(M16)가 같은 원천을 재사용.
2. **이미지 생성 전면 비동기** — Spring이 RenderJob을 Redis 큐에 발행 → Python 워커가 소비·생성 → 오브젝트 스토리지 적재 → WebSocket 완료 푸시. 백엔드는 오케스트레이션·상태만, `GEMINI_API_KEY`는 워커 전유.
3. **역할별 프론트 분리** — 최소권한·공격면 축소. 공유 디자인 시스템·컴포넌트·API 계약을 상속(중복 구현 금지).
4. **룰셋은 코드가 아닌 버전 데이터** — 요율·규정을 버전 파일로 두어 킨텍스 연 단위 개정을 무중단 반영.
5. **공개 vs 내부 보안영역 분리** — 공개 홍보/관람객(비인증·쓰기제한)과 내부 백오피스(관리자·크로스테넌트)를 물리·논리로 격리.
---
## 2. 논리 아키텍처 (컴포넌트 구성도)
```mermaid
graph TB
subgraph EDGE["엣지 / 공개영역 (DMZ)"]
CDN[CDN · 정적 캐시<br/>공개 이미지·번들·플로어플랜]
WAF[WAF / Reverse Proxy · nginx<br/>TLS 종단·라우팅·레이트리밋]
end
subgraph FRONT["역할별 분리 프론트 (React·Vite·TS, 공유 디자인시스템)"]
FO[organizer. 주최자 콘솔]
FE[exhibitor. 참가업체 포털]
FC[contractor. 업체 포털·옥션]
FM[ops. 운영 대시보드]
FA[admin. 관리자 백오피스<br/>★내부 전용]
FP[www/expo. 공개 홍보 사이트<br/>SSR/SSG·SEO·다국어]
FV[관람객 모바일/웹<br/>배지·wayfinding·매칭]
end
subgraph GATE["SSO · 역할 RBAC · API 진입"]
SSO[JWT SSO + TOTP 2FA<br/>플랫폼·행사 이중 RBAC 평가]
end
subgraph BACKEND["공유 Spring Boot 3.x 백엔드 (Java 17·MyBatis)"]
API[REST + WebSocket/STOMP]
RULE[룰 엔진 · 요율/규정 버전셋]
LAYOUT[배치·배선 엔진 · PostGIS 공간 SQL]
AUC[옥션 엔진 M15 · 라운드·순위·낙찰스코어]
BI[BI 집계 M16 · KpiSnapshot]
CMS[CMS·다국어 M17]
PUBSVC[공개 API · 사전등록·조회 read-only]
end
subgraph ASYNC["비동기 처리"]
REDIS[(Redis<br/>작업 큐·순위·타이머·캐시·쿼터·세션)]
NBW[나노바나나 Python 워커<br/>tools/nanobanana · google-genai]
DOCW[서류·PDF·EDM 워커<br/>동일 큐 계약]
end
subgraph DATA["데이터 계층"]
PG[(PostgreSQL + PostGIS<br/>업무·공간 데이터)]
RPL[(읽기 복제본<br/>BI·공개조회 오프로드)]
OBJ[(오브젝트 스토리지<br/>도면·생성이미지·서식·콘텐츠)]
end
subgraph EXT["외부 시스템 / 게이트"]
GEM[Google Gemini<br/>나노바나나 · ★G1]
CLA[Anthropic Claude<br/>AiTextRouter · env only]
PGPAY[PG 결제 · 세금계산서]
KXWP[kxwp/kxfp 작업신고<br/>파일 릴레이]
CCPY[등록업체 DB 739]
EVT[행사일정 시스템]
end
CDN --> WAF
FP -.CDN 캐시.-> CDN
FO & FE & FC & FM & FA & FP & FV --> WAF --> SSO --> API
WAF -->|공개 read-only| PUBSVC
API --> RULE & LAYOUT & AUC & BI & CMS
API --> REDIS
REDIS --> NBW & DOCW
NBW --> OBJ
NBW -.WebSocket 완료푸시.-> API
NBW -.★G1.-> GEM
DOCW --> OBJ
API --> PG
BI --> RPL
PUBSVC --> RPL
API -.AiTextRouter.-> CLA
API --> PGPAY
API -.파일 릴레이.-> KXWP
API --- CCPY & EVT
PG -.복제.-> RPL
```
### 2-1. 컴포넌트 책임 (시스템 관점)
| 컴포넌트 | 실행 단위 | 책임 | 확장 방식 |
|---|---|---|---|
| **역할별 프론트 6종+공개** | nginx 정적 서빙(역할별 dist 번들) | organizer·exhibitor·contractor·ops·admin(내부)·public/visitor. SPA. 데스크톱=설계·에디터, 모바일=현장·조회·승인 | CDN + 정적 스케일(무상태) |
| **공개 홍보 사이트(M12·M17)** | SSR/SSG 렌더 경로 + CDN | SEO·다국어(한/영/중/일)·hreflang·사이트맵, 공개 플로어플랜(M2 부산물) | CDN 캐시·정적 재생성, 인증영역과 별도 |
| **공유 백엔드(Spring Boot jar)** | `java -jar`(systemd, N 인스턴스) | REST+WebSocket, 룰/배치/배선/옥션/BI/CMS 서비스, 큐 발행·상태·콜백 | **수평 확장(무상태)** — 세션·순위·타이머는 Redis 외부화 |
| **나노바나나 워커** | Python 데몬(systemd, M 인스턴스) | Redis 큐 소비 → Gemini image-to-image → 워터마크 후처리 → OBJ 적재 → WebSocket 콜백. 재시도·비용상한·스키마해시 캐시·쿼터(성공 시 차감) | **큐 깊이 기반 수평 확장**(GPU/비용 독립 스케일) |
| **서류·PDF·EDM 워커** | Python/Java 데몬(동일 큐 계약) | 서식(HWP/PDF)·견적서 PDF(M15)·EDM 발송 비동기 | 큐 깊이 기반 확장 |
| **Redis** | 관리형/전용 노드(HA) | 작업 큐, 옥션 실시간 순위·라운드 마감 타이머, 응답 캐시·스키마해시 캐시, RenderJob 쿼터, WebSocket 세션 상관 | Sentinel/Cluster(§3-2) |
| **PostgreSQL+PostGIS** | 프라이머리 + 읽기 복제 | 업무·공간 데이터 단일 진실원천(Flyway 스키마) | 프라이머리 수직 + 읽기 복제 수평(BI·공개조회 오프로드) |
| **오브젝트 스토리지** | S3 호환/파일 스토어 | 도면·생성이미지·서식·콘텐츠·마이크로사이트 자산 | 스토리지 독립 확장 + CDN 프론팅 |
> **AA 위임**: 모듈 경계·패키지·API 표준·응답 봉투는 [`app.md`](app.md). 본 표는 **배포 단위·확장 특성** 관점만.
---
## 3. 비기능요건(NFR)
> 정량 목표는 킨텍스 실측(홀당 200~600부스, 홀 10개, 대형 행사 수만 관람객)과 PLANNING §10 리스크(R6 이미지 비용·지연)를 근거로 산정. 값은 **초기 목표치**이며 파일럿(Phase 1) 실측으로 보정한다.
### 3-1. 확장성 (Scalability)
| 항목 | 설계 | 근거·목표 |
|---|---|---|
| **백엔드 수평 확장** | Spring 인스턴스 무상태화 — JWT(자족적)·세션 없음, 옥션 순위·타이머·쿼터·캐시는 **Redis 외부화**. WebSocket은 STOMP+Redis 브로커 릴레이(다중 인스턴스 팬아웃) | 인스턴스 N대 로드밸런싱, 무중단 스케일아웃 |
| **워커 독립 확장** | 나노바나나·서류·EDM 워커는 백엔드와 **분리 스케일** — 큐 깊이(대기 Job 수) 기반 인스턴스 증감 | 이미지 생성 피크(행사 오픈 전 대량 컨펌)를 백엔드 응답성과 무관하게 흡수 |
| **읽기 부하 오프로드** | BI 집계·공개사이트 조회·플로어플랜 열람은 **읽기 복제본** 라우팅. 운영 프라이머리는 쓰기 트랜잭션 보호 | BI(M16) 무거운 집계가 운영 DB를 압박하지 않음(PLANNING §8-1) |
| **공개 트래픽 흡수** | 공개 홍보 사이트·공개 플로어플랜·이미지는 **CDN·SSG 캐시**로 오리진 오프로드. 사전등록만 오리진 write | 관람객 트래픽 급증(행사 D-데이) 시 오리진 보호 |
| **데이터 파티셔닝 여지** | 행사(Event) 단위 격리(§5) → 대량 데이터(리드·체크인·RenderJob)는 행사·기간 파티션 가능(DA 후속) | 다년·다행사 누적 확장 |
| **멀티테넌시** | 행사 단위 워크스페이스 + 플랫폼 RBAC. 신규 행사는 데이터·권한만 추가(코드·인프라 불변) | 무제한 행사 온보딩 |
### 3-2. 가용성 · HA (Availability)
| 계층 | HA 설계 | 목표 |
|---|---|---|
| **프론트/공개** | 정적 번들 CDN 다중 엣지 + nginx 다중화 | 단일 노드 장애 무영향 |
| **백엔드** | 최소 2 인스턴스 + 헬스체크(`GET /health`) 로드밸런싱. 롤링 배포(무중단) | 무중단 배포·인스턴스 장애 격리 |
| **Redis** | Sentinel(자동 failover) 또는 Cluster. 큐 손실 방지 위해 **AOF 지속화** + 소비자 ACK/재큐 | 프라이머리 다운 시 자동 승격, 진행 중 Job 유실 0 |
| **PostgreSQL** | 프라이머리-스탠바이 스트리밍 복제 + 자동 failover(Patroni/관리형). PITR 백업 | RPO 최소·RTO 분 단위 |
| **워커** | 무상태 소비자 N대. 처리 중 죽으면 **가시성 타임아웃 후 재큐**(멱등 Job) | 워커 장애가 사용자 응답 차단 안 함(비동기) |
| **오브젝트 스토리지** | 복제·버전 관리 스토리지 | 자산 내구성 보장 |
| **Fail-Safe 배포** | 백업 → 배포 → 헬스체크(200) → 실패 시 롤백(이전 jar 유지). clean bootJar 검증 후 교체 | 깨진 배포가 서비스 중단 유발 안 함(`../BUILD_DEPLOY.md`) |
| **degraded 모드** | G1 미승인/Gemini 장애 시 워커 목 응답(구조·워터마크 유지). Claude 실패 시 Ollama 폴백(AiTextRouter). PG 복제 지연 시 프라이머리 폴백 | 외부 의존 장애 시에도 코어 기능 유지 |
> **HA 목표 SLO(초기)**: 코어 인증·설계·조회 경로 **99.5%**(행사 성수기 99.9% 지향). 나노바나나 생성은 **best-effort 비동기**(SLA 대상 아님, 큐 소진 목표만). — 구체 SLO/알림 임계는 TA 관측성([`tech.md`](tech.md))과 연계.
### 3-3. 성능 (Performance)
**(a) 대량 부스 · 공간 연산**
| 시나리오 | 부하 특성 | 설계 대응 | 목표 |
|---|---|---|---|
| 플로어플랜 3안 생성(M2) | 홀당 200~600부스 제약 솔버 | 결정적 솔버(비-LLM) + 서비스 계층 연산, LLM은 조건 해석만. 무거운 생성은 필요 시 비동기화 | 3안 생성 수 분 내(PLANNING 목표) |
| 규정 검증·최단 배선(M2/M4) | PostGIS 버퍼·거리·KNN(`<->`) 연산 | 공간 인덱스(GiST) + 매퍼 XML `ST_*` 최적화. 홀 단위 스코프 쿼리 | 배치·배선 상호작용 P95 < 2s |
| 부스 목록·조회 | 대형 행사 수천 부스 그리드 | 페이지네이션(PageResponse) + 읽기 복제 + 캐시 | 목록 P95 < 500ms |
**(b) 이미지 생성 (나노바나나)**
| 항목 | 산정 | 설계 |
|---|---|---|
| 생성 지연 | 단건 평균 ~40s(design 배지), Gemini 왕복 의존 | **전면 비동기** 사용자는 진행 배지·WebSocket 완료 푸시 수신. 동기 대기 없음 |
| 대량 동시 요청 | 홀당 200~600부스 × S1·S7 자동(PLANNING R6) | **자동 생성은 S1·S7 한정**, 나머지 온디맨드. **동일 스키마해시 캐시**로 재생성 회피. 행사별 **RenderJob 쿼터**(성공 시에만 차감) |
| 처리량 스케일 | 워커 M대 병렬, 깊이 기반 증감 | 피크 워커 스케일아웃으로 소진 시간 제어. Gemini 쿼터·비용 상한은 워커 레벨 관리 |
| 전처리 절감 | 도면/현장사진 클라이언트 Canvas **긴 쪽 1024px 다운스케일 + JPEG 0.85**(ReRoomAI 실증) | 전송량·모델 비용·지연 동시 절감 |
| S6 배선 오버레이 | 좌표 정확성 목적 | **백엔드 래스터 합성 우선**(Gemini 미경유 결정적 산출) 생성 비용·지연에서 제외 |
**(c) 공개사이트 트래픽**
| 항목 | 설계 | 목표 |
|---|---|---|
| 공개 홍보/플로어플랜 | SSR/SSG + CDN 캐시, 오리진 캐시 미스만 read-replica | 캐시 히트 P95 < 200ms, 트래픽 스파이크 CDN 흡수 |
| 사전등록 write | 오리진 write(멱등·중복 등록 가드) + 큐잉 완충(배지 발급 비동기) | 등록 급증 write 완충 |
| 실시간 옥션 순위(M15) | Redis 정렬셋 순위 + WebSocket 델타 푸시, 라운드 마감 타이머 | 순위 갱신 < 1s, 다중 인스턴스 팬아웃 |
### 3-4. 용량 산정 (Capacity — 초기 근사)
> 단일 대형 행사 기준. 킨텍스 대형 홀(홀7/8 각 510부스, 홀9/10 ~600부스), 대형 행사 관람객 수만 명 가정. **Phase 1 파일럿 실측으로 교정**.
| 자원 | 산정 기준 | 초기 용량 |
|---|---|---|
| **부스 데이터** | 대형 행사 3,000~5,000부스 × (폴리곤 + DesignPlan 버전 + UtilityOrder 배선) | 행사당 수만 지오메트리 레코드 GiST 인덱스 필수 |
| **RenderJob/이미지** | 부스 3,000 × 자동 2샷(S1·S7) + 온디맨드 α, 이미지 평균 0.5~2MB(1024px) | 행사당 ~수천~1만 이미지, GB~수십 GB OBJ + CDN. 캐시로 재생성 억제 |
| **리드·체크인(M10)** | 관람객 수만 × 체크인 이벤트 + 참가업체 리드캡처 | 행사당 수만~수십만 이벤트 로우 파티셔닝 후보(개인정보 §5) |
| **동시 사용자** | 설계 피크(주최자·업체) 수백 + 공개/관람객 수천~수만(D-데이) | 인증영역 수백 동시(백엔드 N대) / 공개영역 CDN 흡수 |
| **Redis** | 대기 Job + 옥션 순위셋 + 캐시 + 쿼터 카운터 | GB. 백로그 상한·모니터링 |
| **DB 연결풀** | 공유 백엔드 다인스턴스 × Hikari | **Hikari max 제한 + PgBouncer 권고**(GUARDiA 실측 교훈: 공유 PG `max_connections` 포화 방지). 인스턴스 × PG 상한 |
| **오브젝트 스토리지** | 도면 + 이미지 + 서식 + 콘텐츠, 다년 누적 | 행사당 수십 GB, 보존정책5-3) 기반 아카이빙 |
---
## 4. 배포 토폴로지
> **논리 토폴로지 확정**. 물리 서버·도메인·포트·TLS는 **G2 확정 후 Phase E**(`E-DEP`, `kintex-devops-dev`)에서 실체화. DMZ/방화벽/부하분산 세부는 NA([`network.md`](network.md)).
### 4-1. 배포 존(Zone) 구성
```mermaid
graph TB
subgraph PUBZ["공개 존 (DMZ / 인터넷 노출)"]
LB1[Reverse Proxy / WAF · nginx · TLS]
CDNZ[CDN 엣지]
PUBFE[공개 프론트 · SSR/SSG 정적]
end
subgraph APPZ["애플리케이션 존 (내부망)"]
APPFE[인증 프론트 정적 서빙<br/>organizer·exhibitor·contractor·ops]
APPBE[공유 백엔드 jar × N · systemd]
WKZ[워커 데몬 × M · systemd<br/>나노바나나 · 서류/EDM]
end
subgraph MGMTZ["관리 존 (내부 전용 · 접근 제한)"]
ADMFE[admin. 백오피스 프론트]
end
subgraph DATAZ["데이터 존 (내부, 최심부)"]
PGZ[(PostgreSQL+PostGIS<br/>프라이머리+스탠바이)]
RPLZ[(읽기 복제본)]
REDISZ[(Redis HA)]
OBJZ[(오브젝트 스토리지)]
end
subgraph EGRESS["아웃바운드 게이트 (워커/백엔드 한정)"]
OUT[허용 아웃바운드<br/>Gemini(G1)·Claude·PG결제·kxwp]
end
CDNZ --> PUBFE
LB1 --> PUBFE & APPFE & ADMFE
APPFE & ADMFE --> APPBE
APPBE --> PGZ & REDISZ & RPLZ & OBJZ
WKZ --> REDISZ & OBJZ
WKZ --> OUT
APPBE --> OUT
PGZ -.복제.-> RPLZ
```
### 4-2. 배포 단위(산출물) — `../BUILD_DEPLOY.md` §1 정합
| 단위 | 빌드 | 산출물 | 실행 | 배포 |
|---|---|---|---|---|
| 인증 프론트 6종 | `vite build`(역할별 번들) | `dist/`(organizer·exhibitor·contractor·ops·admin) | nginx 정적(SPA 폴백) | APP존(admin은 MGMT존) |
| 공개 프론트 | SSR/SSG 빌드 | 정적/렌더 번들 | CDN + 엣지 렌더 | 공개존 |
| 공유 백엔드 | `./gradlew bootJar`(JDK17) | `kintex-*.jar` | `java -jar` systemd × N | APP존 |
| 나노바나나 워커 | (빌드 없음) | `tools/nanobanana` | 소비 데몬 systemd × M | APP존(아웃바운드 게이트) |
| 서류/EDM 워커 | | 워커 모듈 | 소비 데몬 | APP존 |
- **배포 흐름**(GUARDiA 표준 준용): `workspace/kintex` git push Gitea(`zio/kintex`) webhook deploy_server 빌드(`bootJar`·`vite build`) Flyway 마이그 jar 재기동·dist 배포 헬스 게이트(`GET /health` 200) 실패 롤백.
- **systemd 유닛**: 백엔드 jar · 워커 데몬 각각 유닛(부팅 자동기동·재시작). AI env drop-in(`ANTHROPIC_API_KEY`·`ADMIN_PASSWORD_ENC`) 표준 프레임워크 §7 방식. **`GEMINI_API_KEY` 나노바나나 워커 유닛에만** 주입(백엔드·프론트 미취급).
- **nginx vhost**: `<kintex-domain>` `/`=프론트 정적, `/api/`·`/ws`=백엔드 포트. 관리자 백오피스(admin.) **별도 vhost + 접근 제한**5-1). TLS certbot. 도메인·포트=G2.
- **환경 분리**: dev / staging / prod. staging에서 헬스·마이그·경계면 검증 prod 승격(운영 배포는 소유자 승인 필수).
> CI/CD 파이프라인 상세(deploy_server·롤백·webhook)는 **Phase E `kintex-devops-dev`** 정본. TA([`tech.md`](tech.md))의 빌드·관측성 표준과 연계.
---
## 5. 보안영역 · 데이터 보존 · 개인정보 경계
### 5-1. 보안영역 분리 (공개 vs 내부 백오피스)
| 영역 | 대상 | 노출 | 인증 | 격리 |
|---|---|---|---|---|
| **공개 영역** | www/expo 홍보사이트, 공개 플로어플랜, 사전등록, 관람객 | 인터넷(DMZ) | 비인증 또는 셀프서비스(쓰기 제한) | 별도 렌더 경로·read-only API·행사 데이터 write 불가 |
| **인증 업무 영역** | organizer·exhibitor·contractor·ops | 인증 접근 | JWT SSO + TOTP 2FA + 행사 RBAC | 행사 단위 데이터 격리5-2) |
| **관리 영역(백오피스)** | admin. 사용자·RBAC·마스터데이터·룰셋·감사로그·크로스테넌트 | **내부 전용**( 전용, 모바일 미제공) | ADMIN 역할 + 2FA 필수 + **접근 제한**(내부망/허용 IP NA 확정) | 별도 vhost·, 공개영역과 물리·논리 분리 |
- **최소권한·공격면 축소**: 6개 프론트 번들 분리로 역할별 코드·권한 최소화. 백오피스는 공개 인터넷에 노출하지 않는다.
- **이중 RBAC 평가**: 플랫폼 레벨(관리자) 행사 레벨(주최자/참가/업체/홀매니저) JWT 클레임(`roles` eventId역할, `hm` 홀매니저)으로 이중 평가. `/api/admin/**`·`/api/system/**` = `hasRole(ADMIN)`(PLANNING §5B-1, `../DEVELOPMENT_GUIDE.md` §4).
- **인증 스택(UIWS 표준 이식)**: JWT(HS256) + TOTP(RFC6238 SHA1·30s·6자리·±1) 2차 인증 + 로그인 실패 잠금 + admin 비번 env(`ADMIN_PASSWORD_ENC` AES-256-GCM + 별도 키파일 재시드, `admin123` 하드코딩 금지). 대상: 관리자·홀매니저·주최자·업체(내부/발주 권한) 2FA 필수, 관람객 셀프서비스 선택.
### 5-2. 데이터 격리 (행사 단위 · 영업비밀)
- **행사(Event) 단위 워크스페이스**: 부스 설계는 경쟁사에 민감(PLANNING R10). 부스 데이터 접근은 **소유 참가업체 + 주최자 + 홀매니저** 한정. 모든 도메인 경로는 `{eventId}` 스코프 + RBAC 가드.
- **옥션(M15) 자료 격리**: AI 설계자료(M2~M5) 옥션 초대된 **킨텍스 등록업체(M7 검증 통과)** 열람. 미등록 업체 응찰 원천 차단(`NOT_REGISTERED_COMPANY` 403).
- **BI 관점 격리**: 참가업체 관점 ROI(자기 부스) 운영사 관점 수익성( 행사) **별도 대시보드·권한**으로 격리(PLANNING M16-1).
### 5-3. 개인정보 경계 · 데이터 보존
| 데이터 | 개인정보 등급 | 처리 원칙 | 보존 |
|---|---|---|---|
| 관람객 등록·배지·체크인·리드(M10) | **개인정보(PLANNING R10)** | 수집 **동의** 필수. 리드 접근은 감사로그(`TB_AUDIT_LOG`) 전수 기록. 참가업체는 자기 리드만 | **보존정책 명시**(행사 N개월, 동의 철회·삭제권 지원 DA 확정) |
| 부스 설계·도면·생성이미지 | 참가업체 자산·영업비밀 | 행사 단위 격리, 응답에서 내부 식별자·해시 shape 제외 | **행사 종료 후 보존 정책 별도**(참가업체 자산, PLANNING §8) |
| 결제·정산(M9) | 금융·과세 정보 | PG 위임(카드정보 비보관), 세금계산서 연동 | 법정 보존 기간 준수 |
| 자격증명·비밀·API키 | 최고 민감 | **응답·로그·에러·커밋에 절대 노출 금지**. `GEMINI_API_KEY`·`ANTHROPIC_API_KEYOTP 시크릿·비번 해시 미노출. AES-256-GCM 저장, 비번 BCrypt | env only, DB·코드 미기록 |
| AI 생성 이미지 | 오인 위험(R1) | **워터마크 강제**("AI 생성 예상 이미지…") + 메타데이터. 계약·심사 서류 자동 배제. 제거 불가 | 캐시·스키마해시 관리 |
- **보안 불변(위반=QA 반려)**: 스택트레이스 차단(`GlobalExceptionHandler`·`DataAccessException` 핸들러), 민감필드 응답 제외, AI 워터마크 항상 포함, 등록업체 응찰 가드, admin env 시드. `../DEVELOPMENT_GUIDE.md` §5 계약.
- **감사 추적**: 승인·낙찰(M15설계 변경·룰셋 개정·리드 접근(개인정보) 전수 `TB_AUDIT_LOG` 기록(PLANNING §5B-1).
---
## 6. 연동 아키텍처
### 6-1. SSO · 역할 RBAC (6역할)
- **단일 JWT SSO** 위에 플랫폼 레벨 + 행사 레벨 권한 이중 평가. 6역할: 주최자·참가업체·장치/공사업체·킨텍스 직원(홀매니저·운영관리자·관람객/일반대중.
- 역할별 프론트는 동일 SSO·API 계약을 상속하되 **번들·도메인 분리**. 백오피스(admin.) 내부 전용·2FA 필수5-1).
- 등록업체 계정은 **M7 등록업체 DB 검증** 통과분만 초대·옥션 응찰. 관람객·일반대중은 셀프서비스(쓰기 제한).
- 인증 상세 계약은 [`app.md`](app.md)(AA)·`../DEVELOPMENT_GUIDE.md` §4.
- **Open SSO(OIDC/Keycloak) 도입 + 인사·조직 API 연동** 별도 정본 [`sso-hr-integration.md`](sso-hr-integration.md)(SA) 기존 JWT+2FA를 삭제 없이 **공존(SSO 1차 인증→앱 JWT 브로커, 로컬 폴백)**, 직원·조직은 `HrDirectoryClient` 어댑터로 조달(로컬 스냅샷 폴백). 관람객/외부는 SSO 제외(셀프서비스 유지).
### 6-2. 외부 게이트 (아웃바운드 통제)
| 연동 | 경로 | 통제 | 게이트 |
|---|---|---|---|
| **나노바나나(Gemini)** | 나노바나나 **워커 전용** 아웃바운드 `generativelanguage.googleapis.com` | `GEMINI_API_KEY` 워커 env only. 워커 서브넷만 아웃바운드 허용(NA). 미승인 /degraded | **G1** |
| **Claude(텍스트 AI)** | 백엔드 `AiTextRouter` `api.anthropic.com` | `ANTHROPIC_API_KEY` env only(코드·DB·로그·응답 미기록). **실패 시 Ollama 폴백** | 승인됨(예외) |
| **PG 결제(M9)** | 백엔드 국내 PG(카드·계좌·세금계산서) | 카드정보 비보관(PG 위임), 결제 콜백 검증 | |
| **kxwp/kxfp 작업신고(M6)** | **파일 릴레이**(제출용 파일 생성 + 업로드 안내) | 폐쇄형·API 미공개(R3). 초기 수동 릴레이, 정식 API는 킨텍스 협의(Phase 3) | |
| **등록업체 DB(739)** | 주기 수집 자체 DB화 | 공개 데이터 수집, 추후 공식 피드 | |
| **행사일정 시스템** | 공개 캘린더 수집 가용성 역산 | 정확 가용성은 킨텍스 내부 데이터 협의 | |
| **CDN** | 공개 자산·이미지 프론팅 | 공개 read-only 자산만 | |
- **아웃바운드 원칙**: 인터넷 아웃바운드는 **워커·백엔드 특정 경로만 허용**(화이트리스트). 외부 API 금지(GUARDiA 보안 제약, `../DEVELOPMENT_GUIDE.md` §5). 세부 방화벽 규칙은 NA([`network.md`](network.md)).
### 6-3. 비동기 큐 계약 (Redis)
- Spring 백엔드는 RenderJob·서류·EDM·알림을 **Redis 큐에 발행**하고 상태만 관리. 워커가 소비·처리·완료 콜백(WebSocket). **Java 재구현 대신 얇은 큐 계약으로 결합**(PLANNING §8, google-genai는 Python SDK 워커 유지).
- 신뢰성: AOF 지속화 + 소비자 ACK + 가시성 타임아웃 재큐(멱등 Job). 쿼터·순위·타이머·캐시도 Redis2-1).
---
## 7. 아키텍처 결정 요약 (ADR-lite)
| # | 결정 | 이유 | 대안·트레이드오프 |
|---|---|---|---|
| 1 | 나노바나나를 **Python 워커 사이드카** 분리 | google-genai=Python SDK, ReRoomAI 검증 방어로직 이식(Java 재구현 회피). 이미지 생성 독립 스케일 | Java 통합(재검증 비용·강결합) 배제 |
| 2 | **역할별 프론트 번들 분리** | 최소권한·공격면 축소, 공개/백오피스 격리 | 단일 SPA(권한 혼재·공격면 확대) 배제. 공유 디자인/API로 중복 완화 |
| 3 | 백엔드 **무상태 + Redis 외부화** | 수평 확장·무중단 배포·다중 인스턴스 WebSocket 팬아웃 | 인메모리 상태(ReRoomAI Map 방식) 재시작·다중인스턴스 취약reroomai (F)) 배제 |
| 4 | **읽기 복제 오프로드**(BI·공개조회) | 운영 프라이머리 보호(PLANNING §8-1) | 단일 DB 직조회(BI 부하 전파) 배제 |
| 5 | **CDN + SSG** 공개 트래픽 흡수 | 관람객 스파이크·SEO·다국어 | 오리진 직서빙(스파이크 취약) 배제 |
| 6 | 룰셋 **버전 데이터** 분리 | 단위 요율·규정 개정 무중단 반영 | 코드 하드코딩(배포 필요) 배제 |
| 7 | S6 배선 오버레이 **백엔드 래스터 우선** | 좌표 정확성(생성 왜곡 배제비용/지연 제외 | Gemini 생성(재질· 왜곡) 배제 |
---
## 8. 교차참조
- 기획 정본: [`../PLANNING.md`](../PLANNING.md) §2·§7·§8·§10
- 구현 백로그: [`../IMPLEMENTATION_BACKLOG.md`](../IMPLEMENTATION_BACKLOG.md) Phase A~E
- **Open SSO · 인사(조직) API 연동(SA)**: [`sso-hr-integration.md`](sso-hr-integration.md) OIDC/Keycloak·HrDirectoryClient·3자 매핑·이행(coexistcutover)
- 나노바나나 파이프라인 근거: [`../analysis/reroomai-source.md`](../analysis/reroomai-source.md)
- 애플리케이션 아키텍처(AA·A-1): [`app.md`](app.md) 모듈 경계·API 표준·패키지
- 기술 표준(TA·A-3): [`tech.md`](tech.md) 빌드·배포·관측성·AiTextRouter
- 데이터 아키텍처(DA·A-4): [`data.md`](data.md) 전사 ERD·공간·마스터·BI 마트
- 네트워크 아키텍처(NA·A-5): [`network.md`](network.md) DMZ/방화벽/부하분산/아웃바운드
- 개발 표준: [`../DEVELOPMENT_GUIDE.md`](../DEVELOPMENT_GUIDE.md) · 빌드/배포: [`../BUILD_DEPLOY.md`](../BUILD_DEPLOY.md)
---
## 9. 변경 이력
| 버전 | 일자 | 작성자 | 내용 |
|---|---|---|---|
| v1.0 | 2026-07-11 | SA | 최초 작성(A-2) 시스템 구성도(역할별 프론트·공유 백엔드·백오피스·공개사이트·나노바나나 워커·Redis·PostGIS), 논리/배포 토폴로지, NFR(확장성·HA·성능(대량부스·이미지큐·공개트래픽용량 산정), 연동 아키텍처(SSO/RBAC 6역할·PG결제·kxwp 릴레이·외부 게이트 Claude/Gemini), 보안영역(공개 vs 백오피스데이터 보존·개인정보 경계, G1/G2 게이트, ADR-lite. PLANNING §8 정합·확정 스택 준수. AA/TA/DA/NA 교차참조 |