kintex/docs/architecture/tech.md
zio eccbeb1337 feat(v2.0): Phase A 아키텍처 + WISE 개발문서 + PM/PMO + DB 계층 + 프론트 착수
- 거버넌스: kintex-pm·dev-pm·pmo 에이전트
- Phase A 아키텍처 5종: docs/architecture/{app,system,tech,data,network}.md (성문화·NFR·SRID0 공간표준·M16 스타스키마·보안영역)
- WISE(UIWS) 참조 개발문서 6종: README·DEVELOPMENT_GUIDE·ENV_SETUP·COMMON_CODES·API_GUIDE·BUILD_DEPLOY
- DB 계층: PostGIS 스키마 V1~V6(홀·트렌치 가정그리드·GiST) + MyBatis 매퍼 5종(ST_* 공간쿼리) + Flyway. gradlew build SUCCESS
- 프론트 착수: React/Vite 스캐폴드 + design.md 토큰 + SCR-01 로그인·SCR-03 부스 에디터. tsc/vite build EXIT 0
- R-T1 수정: 나노바나나 워커 큐키 kintex:renderjob:queue 통일(백엔드 정합, silent no-op 방지)
- 도메인/게이트: G2 해소(dev kintex.zioinfo.kr·prod kintex.wise.ai.kr), CLAUDE.md 로스터 20종

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 18:10:01 +09:00

27 KiB

킨텍스 자동전시시스템 — 기술 표준 (Technical Architecture)

작성: 기술 아키텍트(TA) · 작성일: 2026-07-11 · 버전: v1.0 근거: docs/PLANNING.md v2.0(§8 확정 스택·§8-1 아키텍처 보강·§10 리스크)·docs/IMPLEMENTATION_BACKLOG.md(A-3)·실측 스캐폴드(src/backend/build.gradle·src/backend/src/main/resources/application.yml·src/frontend/package.json·tools/nanobanana/.claude/agents/kintex-ai-dev.md 교차참조: 앱 아키텍처 docs/architecture/app.md(A-1) · 시스템/NFR docs/architecture/system.md(A-2) · 데이터 docs/architecture/data.md(A-4) · 네트워크 docs/architecture/network.md(A-5) 문서 소유권: 본 tech.md는 TA만 수정한다. 확정 스택·버전·빌드/배포·개발표준·관측성·AI 프로바이더 표준의 단일 출처(SSOT)다. 스택 변경은 본 문서 개정을 선행한다.


0. 이 문서의 위치

Phase A(아키텍처·거버넌스) 4개 표준 문서 중 기술 표준(A-3) 이다. 애플리케이션 경계·레이어(app.md), NFR·토폴로지(system.md), 데이터 모델(data.md), 네트워크(network.md)와 정합한다. 본 문서는 "무엇을 어떤 버전으로, 어떻게 빌드·배포·개발·관측하는가"의 기술 규범을 확정한다. 기능 범위·모듈 우선순위는 PLANNING이 권위이며 본 문서는 그 위 기술 계층만 다룬다.

핵심 원칙 4가지:

  1. 실측 스캐폴드 정합 — 이미 스캐폴드된 실제 스택(Spring Boot 3.2.5·React 18.3.1·google-genai 워커)에 표기를 맞춘다. "3.x" 같은 느슨한 표기 대신 핀 버전을 SSOT로 둔다.
  2. GUARDiA/UIWS 표준 정렬 — kintex는 zio/kintex 독립 저장소이나 GUARDiA 표준 프레임워크(UIWS)와 스택·인증·AI 프로바이더 패턴을 공유한다.
  3. 보안 불변 우선 — 시크릿 env-only, 스택트레이스·자격증명·PII 미노출, AES-256-GCM은 코드보다 상위 제약(§10, PLANNING §10·보안 불변).
  4. 결정론과 폐쇄망 우선 — 규정/요율은 버전 관리 데이터, AI는 온프레미스 폴백 필수, 외부 아웃바운드는 승인된 도메인만.

1. 확정 기술 스택 (버전 표준·SSOT)

아래 버전은 실측 스캐폴드에서 채택된 값이다. 임의 상향/하향 금지 — 변경은 TA 승인 + 본 표 개정 후.

1-1. 백엔드 (Spring Boot · Java 17 · MyBatis)

src/backend/build.gradle 기준.

항목 표준 값 근거/비고
언어/런타임 Java 17 (sourceCompatibility/targetCompatibility = 17) GUARDiA 표준(전 솔루션 Java 17 정렬). Java 21 금지
프레임워크 Spring Boot 3.2.5 핀 버전. org.springframework.boot 플러그인
의존성 관리 io.spring.dependency-management 1.1.4 Spring Boot BOM 정렬
빌드 도구 Gradle (wrapper 동봉 gradlew/gradlew.bat) 시스템 Gradle 미의존, wrapper 고정
그룹/패키지 com.zioinfo.kintex / rootProject kintex-backend GUARDiA 네이밍 규약
버전 0.1.0-SNAPSHOT SemVer, 릴리스 시 -SNAPSHOT 제거
ORM MyBatis mybatis-spring-boot-starter 3.0.3 Spring Boot 3.2.x 호환 핀. JPA 금지(공간 SQL은 매퍼 XML)
DB 드라이버 org.postgresql:postgresql (runtimeOnly, BOM 관리) PostGIS 함수는 ST_* 매퍼 XML
캐시/큐 spring-boot-starter-data-redis RenderJob·서류·알림 큐 + 옥션 실시간 순위
실시간 spring-boot-starter-websocket (STOMP) RenderJob 완료·옥션 순위 푸시
인증 spring-boot-starter-security + jjwt 0.12.5 (api/impl/jackson) JWT HS256 + RBAC + TOTP 2FA
검증 spring-boot-starter-validation DTO Bean Validation
보일러플레이트 Lombok (compileOnly + annotationProcessor)
테스트 spring-boot-starter-test + spring-security-test, JUnit Platform
인코딩 UTF-8 강제 (JavaCompile.options.encoding = 'UTF-8') Windows javac CP949 한글 리터럴 손상 방지 — 불변, 전 모듈 유지

MyBatis 규약(application.yml 기준):

  • mapper-locations: classpath*:mybatis/mapper/**/*.xml
  • map-underscore-to-camel-case: true, jdbc-type-for-null: NULL
  • @MapperScan은 GUARDiA 표준(annotationClass = Mapper.class) — 빈 누락 크래시 방지(다른 솔루션 회귀 이력). db-engineer가 공간 SQL 매퍼 XML 소유.

Hikari 풀 표준: maximum-pool-size = ${DB_POOL_MAX:3}. 공유 PostgreSQL 보호(GUARDiA 표준). kintex 전용 DB kintex_db라도 서버 공용 PG면 캡 유지. 상향 필요 시 SA(system.md)·DA와 합의.

1-2. 프론트엔드 (React · Vite · TypeScript)

src/frontend/package.json·vite.config.ts·tsconfig.json 기준.

항목 표준 값 비고
UI 라이브러리 React 18.3.1 (react/react-dom) PLANNING "18/19" 중 18.3.1 확정 채택
빌드/번들러 Vite 5.4.8 + @vitejs/plugin-react 4.3.2 dev 서버 :5173, /api·/ws 프록시
언어 TypeScript 5.6.2 (strict: true) noUnusedLocals/noUnusedParameters/noFallthroughCasesInSwitch
라우팅 react-router-dom 6.26.2 역할별 포털 라우팅
서버 상태 @tanstack/react-query 5.59.0 API 캐싱·재검증 표준. 수동 fetch 지양
클라이언트 상태 zustand 4.5.5 전역 상태(경량). Redux 금지
실시간 @stomp/stompjs 7.0.0 + sockjs-client 1.6.1 백엔드 STOMP 정합
경로 별칭 @/*src/* (vite alias + tsconfig paths) 상대경로 지옥 회피
모듈 타입 "type": "module" (ESM), target ES2020

빌드 스크립트(package.json): build = "tsc -b && vite build", typecheck/lint = "tsc --noEmit". 타입 에러는 빌드 실패 — CI 게이트.

역할별 프론트 분리(PLANNING §2-1·§8-1): organizer·exhibitor·contractor·ops·admin(인증) + public/visitor(공개). 번들 분리 방식은 designer/FE 트랙 결정(모노레포 다중 진입점 vs 서브패스). 공유 디자인 시스템(design.md)·공유 컴포넌트·공유 API 계약은 상속(중복 구현 금지). 현재 스캐폴드는 단일 Vite 앱(src/frontend) — 분리 실행 시 본 표준의 라이브러리 버전을 전 번들이 공유한다.

1-3. 나노바나나 Python 워커 (사이드카)

tools/nanobanana/ 기준. PLANNING §8 "Python 워커 유지 근거"(google-genai는 Python SDK, ReRoomAI 검증 client.py 재사용 — Java 재구현 회피).

항목 표준 값 비고
런타임 Python 3.11+ (개발 실측 3.14 __pycache__) 배포는 3.11/3.12 LTS 권장(3.14는 개발 로컬)
이미지 SDK google-genai (pip install google-genai) Gemini image-to-image. 지연 임포트(무네트워크 import 성립)
모델 gemini-3.1-flash-image-preview (나노바나나 2, env NANOBANANA_MODEL) 하드코딩 아님, env 오버라이드
이미지 처리 Pillow(PIL) S6 배선 오버레이 결정적 래스터 합성·목 플레이스홀더
큐/이벤트 redis (redis.from_url, BLPOP 소비 + pub/sub 발행) 지연 연결
실행 python -m tools.nanobanana.worker (루프) / --smoke (무네트워크)

워커 불변식(worker.py 헤더): ①G1 게이트 — 실 Gemini 호출은 NANOBANANA_LIVE=1 + GEMINI_API_KEY 동시 충족 시만, 기본 목/degraded. ②지연 연결 — Redis 미기동이어도 process_job() 직접 호출 성립. ③S6은 생성형 아님(항상 로컬 PIL). ④비밀 미노출(키/IP/스택트레이스 미기록).

의존성 관리 표준: 현재 워커에 requirements.txt 부재 — 배포 전 tools/nanobanana/requirements.txt(google-genai·Pillow·redis 핀 버전) 추가 필요(§9 백로그). devops-dev(DEV) 담당.

1-4. 데이터·인프라

항목 표준 값 비고
DB PostgreSQL + PostGIS (kintex_db) 공간 데이터 일원화(부스 폴리곤·트렌치 포인트·배선 LineString). 상세 DA/data.md
캐시/큐/실시간 Redis 작업 큐 + 옥션 라운드 타이머 + 순위
오브젝트 스토리지 로컬 FS(기본 degraded 어댑터) → S3/GCS(운영) ObjectStore.save_image() 반환 계약 유지하며 어댑터 교체
마이그레이션 미확정 — B-0 백로그는 Flyway 명시(현 build.gradle 미포함) §3-1 참조. TA 결정: Flyway 채택 권고

2. 통합 계약 (백엔드 ↔ 워커 ↔ 프론트)

2-1. RenderJob 큐 계약 (Spring → Redis → Python 워커)

Spring 백엔드가 RenderJob을 Redis 리스트에 push → 워커가 BLPOP 소비 → 오브젝트 스토리지 적재 → pub/sub 이벤트 발행 → 백엔드 구독 → WebSocket(STOMP) 프론트 푸시. 계약 단일 출처: tools/nanobanana/_workspace/01_worker_contract.md.

★ 실측 불일치(리스크 R-T1, §10): 큐/채널 키 기본값이 백엔드와 워커에서 다르다.

  • application.yml: kintex.render.queue-key = kintex:renderjob:queue
  • worker.py: NANOBANANA_QUEUE 기본 = kintex:renderjobs, EVENT_CHANNEL 기본 = kintex:renderjob:events

양측 모두 env 오버라이드 가능하나 기본값 불일치는 배포 시 조용한 무처리(silent no-op) 위험. 표준 확정: 큐 키 kintex:renderjob:queue, 이벤트 채널 kintex:renderjob:events로 통일하고 배포 env(RENDER_QUEUE_KEY/NANOBANANA_QUEUE/NANOBANANA_EVENT_CHANNEL)를 동일 값으로 명시 주입. BE·VIZ·DEV가 01_worker_contract.md에 최종 키를 고정한다.

2-2. WebSocket(STOMP) 계약

  • 백엔드 WebSocketConfig(STOMP) — 프론트 @stomp/stompjs + sockjs-client. dev는 Vite 프록시 /ws(ws:true).
  • 이벤트: renderjob.completed/renderjob.failed(워커→백엔드→구독 클라), 옥션 순위 푸시(M15). 페이로드에 image_ref·meta(live/degraded 플래그) 포함, 비밀·스택트레이스 미포함.

2-3. API 응답 봉투

실측: common/ApiResponse.java·common/PageResponse.java·common/error/GlobalExceptionHandler.java 존재. 표준 응답 봉투 + 페이지 봉투 + 전역 예외 핸들러로 에러 응답 표준화(스택트레이스 미노출, ErrorCode 코드+요약 메시지만). 상세 계약은 app.md(A-1) 소유 — 본 문서는 정합만 명시.


3. 빌드·배포 표준

3-1. 백엔드 빌드 (Gradle · 단일 jar)

  • 빌드: ./gradlew clean bootJar → 단일 실행 jar(build/libs/kintex-backend-<ver>.jar). GUARDiA 단일 jar 표준.
  • 프론트→백엔드 static 번들(GUARDiA 표준 옵션): 운영 배포는 역할별 프론트 번들을 백엔드 static 리소스 또는 nginx 정적 서빙 중 택1. 역할별 프론트 분리(§1-2)이므로 백오피스/포털별 별도 정적 서빙 + 공유 백엔드 jar 토폴로지가 기본(system.md 확정). 공개사이트(M12/M17)는 SEO·다국어로 별도 렌더 경로(SSR/정적 생성).
  • 테스트: ./gradlew test(JUnit Platform). compileJava·test 통과가 배포 게이트.
  • 마이그레이션(TA 결정): B-0가 Flyway를 명시하나 현 build.gradle 미포함. Flyway 채택 권고org.flywaydb:flyway-core + flyway-database-postgresql(PostGIS 정합) 추가, db/migration/V__*.sql(PostGIS 확장·공간 인덱스 포함). 시드/후행 테이블은 GUARDiA 교훈(멱등화 + 누출 차단) 준수 — sql.init mode=never 후행 추가 테이블 미적용 회귀(schema-integrity 하네스 교훈) 방지. DB 스키마 상세는 DA/data.md.

3-2. 프론트 빌드 (Vite)

  • npm ci && npm run build(= tsc -b && vite build) → dist/. 타입 에러 시 실패.
  • 역할별 번들 분리 시 각 진입점 빌드 산출물을 도메인/서브패스별 배포.
  • ★로컬 rollup win32 크래시 함정(리스크 R-T2, §10): GUARDiA 전 프로젝트에서 로컬 Windows rollup 네이티브 렌더 크래시가 반복 관측됨(homepage-renewal·CMS 등). 표준 대응: (1) CI/서버 빌드(Linux) 신뢰 — 서버 npm run build가 권위. (2) 로컬 검증은 tsc --noEmit(typecheck)로 대체하거나 esbuild 경로. (3) package-lock.json 커밋으로 npm ci 재현성 확보. (4) 로컬 크래시가 서버 빌드 성공을 막지 않음 — 서버 번들 검증(최신 청크 diff)로 마무리.

3-3. 워커 배포 (systemd 서비스)

  • 별도 프로세스(사이드카). systemd 유닛으로 상주(ExecStart=python -m tools.nanobanana.worker), Restart=on-failure.
  • env(EnvironmentFile 또는 drop-in): REDIS_URL·NANOBANANA_QUEUE·NANOBANANA_EVENT_CHANNEL·NANOBANANA_OUTPUT_DIR·(G1 승인 후)NANOBANANA_LIVE=1·GEMINI_API_KEY. GEMINI_API_KEY는 워커 env에만(백엔드 미보유 — application.yml 주석 명시). GUARDiA 서버는 명령줄 인자 기동 서비스가 많아 systemd drop-in EnvironmentFile 방식 채택(기존 ExecStart 불변, guardia-claude-ai 트랙 패턴).
  • 미승인(G2/G1 전) 기본 목/degraded 모드로 상주 가능(무네트워크).

3-4. CI/CD 파이프라인

GUARDiA 표준 흐름 정렬(솔루션 푸시 구조 메모리):

workspace/kintex (개발·SSOT)
  → repos/kintex (fresh git init — 모노레포 히스토리 상속 금지, bundle 비대화 방지)
  → Gitea zio/kintex (push)
  → webhook :9999 (deploy_server.py)
  → 서버 빌드(gradlew bootJar + npm build + 워커 배포) → systemd 재시작 → health 게이트
  • 선행 게이트 G2(BACKLOG): 배포 대상 서버·포트(GUARDiA 인프라와 별개 도메인) 확정 전 Phase E 착수 금지.
  • 함정(GUARDiA 교훈, 배포블록 반영 필수): ①repos/kintex는 반드시 fresh git init(모노레포 .git 상속 시 bundle 1.5GB 회귀). ②deploy_server.py에 kintex 블록 추가 시 서버 /opt/zioinfo/deploy_server.py 사본 반영 + zioinfo-deploy 재시작 필수(로컬만 고치면 웹훅 1ms no-op). ③백엔드 jar만이 아니라 워커 서비스도 배포 대상(별도 systemd). ④health 200 확인이 완료 게이트.

3-5. 환경변수 표준 (시크릿 env-only)

application.yml은 모든 시크릿을 플레이스홀더로만 주입(하드코딩 금지, 주석 명시).

env 용도 소비자
DB_URL/DB_USER/DB_PASSWORD PostgreSQL(PostGIS) 백엔드
DB_POOL_MAX (기본 3) Hikari 캡 백엔드
REDIS_HOST/REDIS_PORT/REDIS_PASSWORD Redis 백엔드
REDIS_URL Redis(워커) 워커
JWT_SECRET(≥32B)/JWT_ACCESS_TTL JWT HS256 백엔드
RENDER_QUEUE_KEY/NANOBANANA_QUEUE 큐 키(통일) 백엔드/워커
NANOBANANA_EVENT_CHANNEL 이벤트 채널 워커/백엔드
RENDER_EVENT_QUOTA(기본 500) 행사별 생성 쿼터 백엔드
NANOBANANA_LIVE/GEMINI_API_KEY G1 승인 후 실 Gemini 워커 전용
ANTHROPIC_API_KEY Claude AI(§6) 백엔드
ADMIN_PASSWORD_ENC + 키파일 admin 비번(AES-256-GCM) 백엔드
VITE_BACKEND_ORIGIN/VITE_API_BASE 프론트 오리진/프록시 프론트

admin 비번(B-1·GUARDiA 표준): admin123 등 평문 시드 금지. ADMIN_PASSWORD_ENC(AES-256-GCM) + 별도 키파일 주입, 최초 기동 재시드(guardia-claude-ai guardia_master.key 패턴).


4. 개발 표준

4-1. 코드 스타일

  • Java: Google Java Style 기준(4-space, 100~120 col). Lombok 활용(@Getter/@RequiredArgsConstructor/@Slf4j), 필드 주입 금지(생성자 주입). 패키지 = 모듈별(module.m2·module.m5·auth·common·config) — app.md 경계 준수. UTF-8 소스 필수(build.gradle 강제).
  • TypeScript: strict 전면. any 지양(불가피 시 주석). 컴포넌트 함수형, hooks 규약. 서버 상태는 react-query, 전역은 zustand. @/* 별칭 사용.
  • Python(워커): PEP 8 + type hints(from __future__ import annotations). 방어적 임포트(SDK/redis 지연). 비밀 미노출 규약(에러 메시지 300자 절단·키 미기록) 유지.

4-2. 테스트 표준

  • 백엔드: JUnit 5 + spring-security-test. 단위(서비스·룰엔진·요율 계산) + 슬라이스(@WebMvcTest/@MyBatisTest) + 통합(핵심 왕복). 필수 테스트(GUARDiA feedback_test_required): 임포트/컴파일 검증 + 라우트 확인 + curl 응답. 룰엔진(규정·요율)·PostGIS 공간 SQL은 결정적 테스트 필수.
  • 프론트: tsc --noEmit 게이트(현 최소선). 확장 시 Vitest + Testing Library 권고(현 미도입).
  • 워커: python -m tools.nanobanana.worker --smoke(무네트워크 스모크) — 목 잡 S2 + S6 래스터 처리·사이드카 확인. CI 필수 게이트.
  • AI/외부 호출: 목/degraded 경로가 무네트워크로 통과해야 함(폐쇄망·미승인 대비).

4-3. 브랜치·커밋 규약

  • 브랜치: main(보호) + 작업 브랜치(feat/·fix/·chore/). main 직접 커밋 금지(작업 브랜치 → PR). 기본 브랜치 push는 origin HEAD:main(BI repo master 함정 교훈 — repo별 기본 브랜치 확인).
  • 커밋(Conventional Commits): type(scope): summary. type = feat/fix/docs/refactor/test/chore/build/perf. scope = 모듈(m2·m5·auth·worker·bidding). 커밋 메시지 영어(kintex-ai-dev·visualizer 산출 규약). 예: feat(m5): add renderjob quota guard.
  • 커밋 금지 대상: 시크릿·.env·CAD zip(gitignore)·build 산출물. .gitignore 준수(.gradle/·build/·*.log·.env).
  • 커밋/푸시 타이밍: 사용자·오케스트레이터 명시 요청 시에만.

4-4. 저장소·문서 규약

  • kintex는 독립 저장소(zio/kintex) — GUARDiA ITSM(관공서 관제)과 별개 도메인. R12 게이트상 Gemini 외부호출은 kintex 독립성과 무관하게 소유자 승인 선행.
  • 아키텍처 문서는 docs/architecture/. PLANNING(planner)·design(designer) 소유권 존중 — 본 문서는 직접 수정하지 않고 교차참조.

5. 성능·관측성 표준

5-1. 로깅

  • 백엔드: SLF4J/Logback(Spring Boot 기본). logging.level.root: INFO, com.zioinfo.kintex: DEBUG(개발). 운영은 INFO로 하향(env LOGGING_LEVEL_* 오버라이드). 구조화(JSON) 로깅은 관측성 승격 시 권고.
  • 로그 보안 불변: 자격증명·IP·SSH·PII·스택트레이스 로그 금지. 워커는 예외 요약만(type(e).__name__), 키 미기록. include-stacktrace: never 유지.
  • 상관관계: 요청별 traceId(MDC) 표준화 권고 — 옥션·RenderJob 비동기 흐름 추적.

5-2. 메트릭·트레이싱 (Observability)

  • 표준(Micrometer + Actuator 권고): spring-boot-starter-actuator 추가(현 미포함) → /actuator/health(배포 게이트), /actuator/metrics, Prometheus /actuator/prometheus(GUARDiA guardia-rag /metrics 패턴 정렬).
  • 핵심 지표: RenderJob 처리량·지연·실패율(목/live 구분), 큐 적체(Redis 리스트 길이), 옥션 순위 계산 지연, PostGIS 공간 쿼리 지연, Hikari 풀 사용률, AI 프로바이더 폴백 발생률(Claude→Ollama).
  • 트레이싱: OpenTelemetry(OTel)는 관측성 트랙 승격 시(GreenOps/observability-platform 패턴). 초기는 로그 상관관계 + Actuator 메트릭.
  • health 계약: 배포 후 /actuator/health 200이 완료 게이트(§3-4). 워커는 하트비트/최근 처리 시각을 이벤트/로그로 관측(전용 health 엔드포인트 부재 — 큐 소비 로그로 감시).

5-3. 성능 표준·부하 목표

PLANNING §10 리스크(R6 이미지 비용·지연) 정렬:

  • 이미지 생성(R6): 홀당 200~600부스 동시 생성 시 비용/지연 급증. 표준: 자동 생성은 S1·S7 한정 + 온디맨드 + 스키마 해시 캐시(client.py 캐시) + 행사별 쿼터(RENDER_EVENT_QUOTA 기본 500). 워커는 성공 시에만 쿼터 차감(worker 방어 로직).
  • PostGIS 대량 배치: 부스 폴리곤·배선 LineString 대량 연산은 공간 인덱스(GiST) 전제. 배치 배치도 생성·정산 집계는 트랜잭션 분할.
  • BI 집계(M16, PLANNING §8-1): 운영 DB 부하 회피 — 배치/스냅샷(KpiSnapshot) 또는 읽기 전용 복제. 실시간 대시보드 직접 집계 지양.
  • 비동기 우선: 이미지·서류·알림·PDF(옥션 견적서)는 전면 Redis 큐 경유(동기 블로킹 금지).

6. AI 프로바이더 기술 표준 (Claude 기본 + 설정형 전환)

근거: .claude/agents/kintex-ai-dev.md·GUARDiA guardia-claude-ai 트랙·UIWS 패턴. 나노바나나(Gemini 이미지)는 별개(visualizer·§1-3·G1 게이트) — 본 절은 텍스트/지능 AI(부스배치 조건해석·규정검증 보조·예측·매칭·서류검수·챗봇).

6-1. 프로바이더 라우팅 아키텍처

UIWS 표준 3-컴포넌트(현 스캐폴드 미구현 — AI 모듈 착수 시 신설):

  • ClaudeTextClient: Anthropic Claude API(api.anthropic.com — 소유자 승인 예외 2026-07-03) 호출. 키는 env ANTHROPIC_API_KEY에서만 로드(코드·DB·로그·커밋·응답 기록 금지).
  • AiTextRouter: 프로바이더 선택·폴백 오케스트레이션. 기본 Claude → 실패 시 Ollama 자동 폴백(온프레미스 소형: qwen3:1.7b·llama3.2:1b 등). 하드코딩 금지.
  • AiConfig/AiConfigService + 설정 화면: 런타임 프로바이더/모델 전환(화이트리스트 claude-* 기본 + 승인된 Ollama). generation_model·temperature·top_k·enabled 설정.

6-2. 폴백·폐쇄망·결정론

  • Ollama 폴백 필수(폐쇄망·Claude 장애 대비). RAM 제약 준수 — 서버 가용 ~2GB, 대형 모델 금지(소형만, project_ollama_ram_constraint).
  • 결정론 기능(분류·추출·서류검수): 구조화 출력(format:json). 환각 방지 — 근거 없는 답변 보류·인용(guardia-ai-trust 정렬).
  • 부스 배치(M2): 생성형 LLM이 배치를 만드는 것이 아니라 제약 솔버/휴리스틱이 3안 생성, LLM은 조건 해석·설명에만(kintex-ai-dev 규약).

6-3. 외부 아웃바운드 게이트 (불변)

도메인 상태 조건
api.anthropic.com 승인(2026-07-03 소유자 예외) Claude 텍스트 AI. 키 env-only, 실패 시 Ollama 폴백
generativelanguage.googleapis.com 미승인 게이트 G1(PLANNING R12) 나노바나나. M5 실호출 착수 전 소유자 승인 선행. 미승인 시 목/degraded
그 외 외부 API 금지 GUARDiA 보안 불변

네트워크 아웃바운드 화이트리스트·프록시는 network.md(A-5) 소유. 본 문서는 AI 게이트만 확정.


7. 보안 기술 표준 (불변 요약)

PLANNING §10·GUARDiA 보안 불변 정렬(상세는 app.md/network.md):

  • 시크릿 env-only — 코드·DB·커밋·로그·응답 기록 금지. application.yml 플레이스홀더만.
  • 자격증명·PII·스택트레이스 미노출 — API 응답/에러/로그/이벤트. include-stacktrace: never, 워커 에러 요약만.
  • AES-256-GCM — admin 비번(ADMIN_PASSWORD_ENC)·민감 자격증명. 별도 키파일.
  • 인증(B-1): JWT(HS256, jjwt 0.12.5) + RBAC(6역할·행사 단위) + TOTP 2FA(RFC6238) + 로그인 실패 잠금. UIWS 이식.
  • AI 워터마크(R1): 나노바나나 전 이미지 "AI 생성 예상 — 실제 시공과 다를 수 있음" 고지 강제(worker 목/live 공통). 계약·심사 서류 자동 배제.
  • 등록업체 게이트(M15): 미등록 업체 옥션 응찰 원천 차단(M7 검증).

8. 기술 리스크 · PoC

PLANNING §10(R1~R12)의 기술 실행 리스크를 TA 관점으로 구체화. 도메인/법적 리스크(R1·R2·R8·R9·R10)는 PLANNING 소유.

8-1. TA 신규/구체화 리스크

# 리스크 영향 완화·PoC
R-T1 큐/이벤트 키 기본값 불일치(§2-1) — application.yml kintex:renderjob:queue vs worker.py kintex:renderjobs 높음(배포 시 조용한 무처리) 키 통일(kintex:renderjob:queue/kintex:renderjob:events) + 01_worker_contract.md 고정 + 배포 env 명시. PoC: 백엔드 push → 워커 소비 → WebSocket 완료 왕복 스모크
R-T2 로컬 rollup win32 크래시(§3-2) — Windows Vite 빌드 네이티브 렌더 크래시(GUARDiA 반복 관측) 중간(로컬 개발 저해) 서버 빌드 신뢰 + tsc --noEmit 로컬 게이트 + package-lock.json 커밋(npm ci 재현)
R-T3 PostGIS 대량 배치 성능 — 홀당 200~600부스 폴리곤·배선 최단경로·통로버퍼 검증 대량 연산 중간 GiST 공간 인덱스 + 매퍼 XML ST_* 튜닝 + 배치 분할. PoC: 600부스 배치도 생성·규정검증 SQL 부하 측정(DA 협업)
R-T4 이미지 큐 부하(PLANNING R6) — 대량 동시 RenderJob 비용·지연 중간 S1/S7 한정 자동생성 + 스키마 해시 캐시 + 행사 쿼터(500) + 워커 동시성 제한. PoC: 목 모드 N=500 잡 큐 처리량·적체 측정(무비용)
R-T5 Flyway 부재(§3-1·B-0 명시) — 마이그레이션 도구 미결정, 후행 테이블 미적용 회귀(GUARDiA schema-integrity 교훈) 중간 Flyway 채택 + 멱등 스키마 + 누출 차단. DA와 확정
R-T6 워커 requirements.txt 부재(§1-3) — 의존성 핀 미고정 낮음 tools/nanobanana/requirements.txt 추가(google-genai·Pillow·redis 핀). DEV 담당
R-T7 AiTextRouter/AiConfig 미구현(§6-1) — AI 프로바이더 표준 코드 부재 낮음(설계 확정, 착수 대기) AI 모듈 착수 시 UIWS 패턴 이식. Ollama 폴백 무네트워크 검증

8-2. 권장 PoC 순서 (TA 실행 가능·Bash)

  1. 워커 스모크(무네트워크·무비용) — python -m tools.nanobanana.worker --smoke. S2 목 + S6 래스터 사이드카 확인. 즉시 실행 가능.
  2. 큐 왕복 PoC(R-T1) — 로컬 Redis + 백엔드 push + 워커 소비 스모크(키 통일 검증).
  3. PostGIS 배치 PoC(R-T3) — 600부스 합성 데이터로 배치·검증 공간 SQL EXPLAIN ANALYZE.
  4. 이미지 큐 부하 PoC(R-T4) — 목 모드 500잡 처리량·적체.

본 구현은 구현 에이전트(BE·VIZ·DB·AI)가 표준대로 수행. TA는 PoC 스크립트 실행·표준 개선만.


9. 미결 사항 (구현 착수 전 확정 필요)

# 항목 담당 Phase
1 큐/이벤트 키 통일(R-T1) → 01_worker_contract.md 고정 BE·VIZ·DEV B/C
2 Flyway 채택·마이그레이션 구조(R-T5) DA·DB·TA B-0
3 Actuator/Micrometer 관측성 의존성 추가(§5-2) DEV·TA B
4 워커 requirements.txt 핀(R-T6) DEV C-M5
5 역할별 프론트 번들 분리 방식(§1-2) 확정 DES·FE C/D
6 AiTextRouter/AiConfig 이식(§6-1) AI·BE D
7 배포 서버·포트·도메인(G2) DEV·SA E
8 Gemini 외부호출 승인(G1) 소유자 C-M5

10. 변경 이력

버전 일자 작성자 내용
v1.0 2026-07-11 TA 최초 작성(A-3). 실측 스캐폴드 정합 — 확정 스택 핀 버전(Spring Boot 3.2.5·MyBatis 3.0.3·jjwt 0.12.5·React 18.3.1·Vite 5.4.8·TS 5.6.2·google-genai 워커) SSOT화, 빌드·배포(Gradle 단일 jar·Vite·워커 systemd·CI/CD)·개발표준(코드스타일·테스트·Conventional Commits·브랜치)·관측성(로깅·Actuator/Micrometer·성능목표)·AI 프로바이더(Claude 기본+AiTextRouter/AiConfig+Ollama 폴백·외부 아웃바운드 게이트)·기술 리스크7종(R-T1~R-T7)+PoC 확정. ★실측 불일치 발견: 큐 키 기본값 백엔드/워커 상이(R-T1) — 통일 표준 제시. app.md/system.md/data.md/network.md 교차참조