- SessionStart hook (scripts/graphify_setup.py): auto-install graphifyy[sql], build knowledge graph on first run (graphify extract --code-only, local AST), incremental graphify update thereafter — install-only smartness - knowledge/kintex/: all 183 KINTEX md docs bundled (planning/design/analysis) - knowledge/guardia/: distilled GUARDiA-wide knowledge from 2,483 md files (solutions-catalog, standard-framework, operations-cicd, lessons-learned; credentials/IP-free curated) - SKILL.md: graph-first codebase query rules + knowledge base loading guide Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
131 lines
9.5 KiB
Markdown
131 lines
9.5 KiB
Markdown
# 킨텍스 자동전시시스템 — 개발 표준 가이드
|
|
|
|
> **WISE(UIWS) 참조** — `workspace/uiws`(GUARDiA 표준 프레임워크 정본)의 백엔드/인증/보안 컨벤션을 킨텍스 스택(MyBatis·PostGIS·Redis·나노바나나 워커)에 맞춰 정리했다.
|
|
> 정본 링크: 아키텍처 표준은 Phase A `docs/architecture/*`(kintex-aa/sa/ta), API 계약은 [`_workspace/01_backend_contracts.md`](../_workspace/01_backend_contracts.md), 프로젝트 규칙은 [`CLAUDE.md`](../CLAUDE.md).
|
|
|
|
---
|
|
|
|
## 1. 기술 스택 (확정 — 변경 금지)
|
|
|
|
[`CLAUDE.md`](../CLAUDE.md) §기술 스택이 정본. 요약:
|
|
|
|
| 레이어 | 표준 |
|
|
|--------|------|
|
|
| 프론트(웹) | React 18/19 + Vite + TypeScript (역할별 번들 분리 — PLANNING §2-1) |
|
|
| 백엔드 | Spring Boot 3.x(Java 17) + MyBatis — REST + WebSocket(STOMP) |
|
|
| DB | PostgreSQL + **PostGIS**(부스 polygon·트렌치 point·배선 LineString) |
|
|
| 비동기 | Redis 작업 큐(RenderJob·서류·알림) |
|
|
| 이미지 생성 | 나노바나나 Python 워커 사이드카(`tools/nanobanana`, google-genai) |
|
|
| AI(텍스트) | Claude 기본 + 설정형 전환(`AiTextRouter`/`AiConfig`) — 실패 시 Ollama 폴백 |
|
|
| 인증 | 행사 단위 RBAC(JWT HS256) + 2차 인증(OTP/TOTP) |
|
|
|
|
- 패키지 루트: **`com.zioinfo.kintex`** · DB: **`kintex_db`**
|
|
- 신규 코드는 이 스택만 사용. 나노바나나 호출은 `tools/nanobanana` Python 워커만 경유(백엔드는 큐 발행·상태·콜백까지만, `GEMINI_API_KEY` 미취급).
|
|
|
|
---
|
|
|
|
## 2. 패키지·레이어 구조 (백엔드)
|
|
|
|
WISE 계층(`controller·service·repository·domain·dto`)을 MyBatis로 매핑한다. `com.zioinfo.kintex` 하위:
|
|
|
|
```
|
|
com.zioinfo.kintex
|
|
├── config # SecurityConfig, JwtProperties, WebSocketConfig, RedisConfig, MyBatis @MapperScan(annotationClass=Mapper.class)
|
|
├── security # JwtTokenProvider, JwtAuthenticationFilter, KintexPrincipal, RestAuthEntryPoint
|
|
├── common # response(ApiResponse·PageResponse), exception(ApiException·ErrorCode·GlobalExceptionHandler), audit(AOP)
|
|
├── auth # controller / service(AuthService·TotpService) / mapper / dto
|
|
├── module
|
|
│ ├── m2 # 플로어플랜: controller·service·mapper(BoothMapper, PostGIS ST_*)·dto·engine(ComplianceRuleEngine)
|
|
│ ├── m3 # 부스 설계: DesignMapper·precheck
|
|
│ ├── m4 # 유틸리티/배선: WiringMapper·요율 룰
|
|
│ ├── m5 # 나노바나나 RenderJob: 큐 발행·콜백·WebSocket 푸시
|
|
│ └── … # M10·M12·M15·M16·M18 등 (Phase D)
|
|
├── system # 시스템관리(사용자·역할/권한·공통코드·메뉴·감사로그·설정) — WISE 이식(B-2)
|
|
└── work # 공통 업무기능(worklog·schedule·message·stats·notice…) — WISE 이식(B-3)
|
|
```
|
|
|
|
- **레이어 규칙**: `controller`(요청 검증·RBAC 진입) → `service`(트랜잭션·룰·엔진) → `mapper`(MyBatis XML, 공간 쿼리 `ST_*`). 컨트롤러는 도메인 로직 금지, 매퍼는 비즈니스 판단 금지.
|
|
- **매퍼**: `@Mapper` 인터페이스 + `resources/mybatis/mapper/*.xml`. PostGIS 연산(`ST_MakePolygon`·`ST_Area`·`ST_Distance`·`<->` KNN)은 XML에.
|
|
- **룰셋은 코드가 아닌 데이터**: 규정(`rulesets/compliance-v1.json`)·요율(`rulesets/rates-v1.json`)은 버전 파일. 개정 시 파일 교체, 리포트에 `rulesetVersion`·`disclaimer` 항상 기록.
|
|
|
|
### 프론트(웹) 구조
|
|
WISE 컨벤션 `pages/components/api/store/hooks/routes`. 역할별 포털(organizer·exhibitor·contractor·ops·admin·public+visitor)은 번들 분리(PLANNING §2-1)하되 공유 디자인 시스템·공통 컴포넌트·API 계약을 상속한다. axios `baseURL=/api`.
|
|
|
|
---
|
|
|
|
## 3. API·응답 규약
|
|
|
|
상세는 [`API_GUIDE.md`](API_GUIDE.md) 및 계약서 [`_workspace/01_backend_contracts.md`](../_workspace/01_backend_contracts.md). 핵심:
|
|
|
|
- 응답 봉투 `ApiResponse<T>` = `{ success, data, error }`, 목록 `PageResponse<T>` = `{ items, page, size, total }`.
|
|
- 오류 코드(문자열)→HTTP 매핑 고정(`VALIDATION`400·`FORBIDDEN`403·`COMPLIANCE_BLOCKED`422·`NOT_IMPLEMENTED`501 …).
|
|
- 모든 도메인 경로는 `{eventId}` 스코프 + 행사 단위 RBAC 가드.
|
|
|
|
---
|
|
|
|
## 4. 인증 표준 (JWT + 2FA/OTP) — WISE 이식
|
|
|
|
GUARDiA 표준 프레임워크 §2 + WISE `auth` 모듈을 이식한다(백로그 B-1).
|
|
|
|
- **1차 로그인**(ID/PW) → `verifyToken` 발급 → **2차 검증**(EMAIL 인증코드 또는 OTP/TOTP) → access·refresh 토큰.
|
|
- **OTP**: TOTP RFC6238(SHA1·30초·6자리·±1윈도). `TotpService` 이식. 최초 QR 등록, 마이페이지 재설정/해제, **관리자 OTP 초기화**(`otp_secret=NULL`). 사용자별 `VERIFY_METHOD`(EMAIL/OTP)로 분기.
|
|
- **RBAC**: JWT 클레임 `roles`(eventId→역할)·`hm`(홀매니저). `/api/system/**`·`/api/admin/**` = `hasRole(ADMIN)`. 데이터 가시범위(역할 스코프)는 WISE `DataScopeService` 패턴 참조.
|
|
- **로그인 실패 잠금** + 관리자 해제.
|
|
- **admin 비밀번호**: env `ADMIN_PASSWORD_ENC`(AES-256-GCM) + 별도 키파일 복호 → 기동 시 BCrypt 재시드. **`admin123` 하드코딩 시드 금지.**
|
|
|
|
---
|
|
|
|
## 5. 보안 불변 (계약 강제 — 위반 시 QA 반려)
|
|
|
|
| 규칙 | 내용 |
|
|
|------|------|
|
|
| 자격증명 미노출 | IP·SSH·비밀번호·해시·`GEMINI_API_KEY`·`ANTHROPIC_API_KEY`·OTP 시크릿을 응답·로그·에러메시지·커밋에 절대 노출 금지 |
|
|
| 민감 필드 제외 | 사용자/업체 응답은 이름·역할·번호 등 비민감 필드만. 내부 식별자·해시 shape 제외 |
|
|
| 스택트레이스 차단 | `error.message`는 사람이 읽을 요약만. 상세는 서버 로그. `GlobalExceptionHandler`·`DataAccessException` 핸들러로 누출 차단 |
|
|
| AI 이미지 워터마크 | 나노바나나 산출 이미지 응답은 `watermarkRequired:true`+`watermarkText`+`notice`(계약·심사 서류 사용 금지) **항상** 포함 — 제거 불가 |
|
|
| 등록업체 응찰 | 장치업체(CONTRACTOR)는 킨텍스 등록업체 검증 통과분만 초대·응찰(`NOT_REGISTERED_COMPANY` 403) |
|
|
| 외부 API 금지 | 온프레미스 우선. 예외: `api.anthropic.com`(Claude, 키 env only·실패 시 Ollama 폴백) + `Gemini`(나노바나나, G1 승인 대상·워커 전용) |
|
|
| 암호화 저장 | 비밀·자격증명 AES-256-GCM. 비밀번호는 BCrypt 해시 |
|
|
|
|
---
|
|
|
|
## 6. 코딩 규약
|
|
|
|
- **언어**: 문서·주석·커밋 본문 설명은 한국어 허용, **코드 식별자·커밋 제목·PR 제목은 영어**.
|
|
- **네이밍**: Java `camelCase`/`PascalCase`, DB 컬럼 `SNAKE_CASE`(WISE와 동일 — 예 `WRITER_ID`·`START_HOUR`), DTO 필드 `camelCase`.
|
|
- **DTO ↔ 코드그룹 매핑**은 [`COMMON_CODES.md`](COMMON_CODES.md) 표를 단일 출처로 준수(`boothType`·`myRole`·`severity` 등).
|
|
- **널/기본값**: 상태·역할 등 NOT NULL 기본값은 코드 문서 기준(예 역할 기본 `USER`/부스 상태 기본 `draft`).
|
|
- **프론트**: TypeScript strict. API 응답 타입은 계약서 shape과 1:1. 임의 `any` 지양.
|
|
- **DB 마이그레이션**: `kintex_db`는 **Flyway 순번 마이그레이션**(`V__` / 번호 규약, 백로그 B-0). 스키마가 단일 진실원천 — 엔티티/매퍼는 이를 따른다. 마이그 번호 충돌 금지(신규는 최대 번호+1).
|
|
|
|
---
|
|
|
|
## 7. 브랜치·커밋·PR
|
|
|
|
WISE 파이프라인 보호(`.githooks/pre-push`) 관행을 준용한다.
|
|
|
|
- **브랜치**: `main`(정본) 보호. 기능은 `feat/<module>-<요약>`, 수정은 `fix/<요약>`. 아키텍처/공통은 Phase 라벨(예 `phaseB/auth-otp`).
|
|
- **커밋 메시지**: **Conventional Commits** — `feat(m2): 플로어플랜 규정검증 API`, `fix(auth): OTP 윈도우 경계 처리`, `docs(codes): 옥션 상태 코드 추가`. 타입: `feat·fix·docs·refactor·test·chore·build·ci`.
|
|
- **push 전 게이트(권장)**: 변경분 백엔드 `compileJava` / 프론트·워커 `tsc`·lint 통과 → 실패 시 push 금지. 시크릿 파일 커밋 차단(`.env`·`*.key`·`*-firebase-adminsdk-*.json` 등은 gitignore 유지).
|
|
- **PR 규칙**: 대상 Phase/모듈 명시 · 계약서(경계면) 변경 시 frontend·db·qa 영향 기재 · 보안 불변 체크(§5) · 관련 QA 통과 링크. 아키텍처 표준(Phase A) 위반은 시정 후 병합.
|
|
- **커밋/푸시 시점**: 사용자/오케스트레이터 지시가 있을 때만. 운영 배포는 소유자 승인 필수.
|
|
|
|
---
|
|
|
|
## 8. 테스트
|
|
|
|
- **백엔드**: 서비스·룰 엔진 단위 테스트(규정 평가·요율 산식·배선 최단경로). 공간 쿼리는 PostGIS 통합 테스트(testcontainers 또는 로컬 PostGIS).
|
|
- **경계면(계약) 검증**: `kintex-qa`가 API 응답 shape ↔ 프론트 훅/컴포넌트 호출을 교차 대조(계약서 단일 출처). 각 모듈 완성 직후 점진 검증.
|
|
- **보안 회귀**: 자격증명·PII·스택트레이스 미노출, AI 워터마크 강제, 등록업체 응찰 가드, admin env 시드를 QA 반려 사유로 상시 점검.
|
|
- **워커**: 나노바나나 모듈은 키/네트워크 없이도 import·구조 성립(목/degraded). 쿼터는 성공 시에만 차감.
|
|
|
|
---
|
|
|
|
## 9. 참조
|
|
|
|
- 프로젝트 규칙·에이전트 워크플로: [`CLAUDE.md`](../CLAUDE.md)
|
|
- 환경 구축: [`ENV_SETUP.md`](ENV_SETUP.md) · 빌드/배포: [`BUILD_DEPLOY.md`](BUILD_DEPLOY.md)
|
|
- API 규약: [`API_GUIDE.md`](API_GUIDE.md) · 공통코드: [`COMMON_CODES.md`](COMMON_CODES.md)
|
|
- 백엔드 계약서(정본): [`_workspace/01_backend_contracts.md`](../_workspace/01_backend_contracts.md)
|
|
- 표준 프레임워크: `workspace/_framework/GUARDIA_STANDARD_FRAMEWORK.md`
|