# GUARDiA 표준 프레임워크 (UIMS 기준) — 지식 문서

> **선언(2026-07-03):** UIMS(UIWS, `workspace/uiws`)가 **GUARDiA 표준 프레임워크**로 승격되었다.
> 모든 신규 프로젝트와 기존 솔루션은 이 표준을 기준으로 개발·리팩터링한다.
>
> - **표준 명세 단일 출처:** `workspace/_framework/GUARDIA_STANDARD_FRAMEWORK.md`
> - **정본 레퍼런스 구현:** `workspace/uiws` (읽기 전용 — 임의 수정 금지)
> - **AI 플랫폼 공통 계약:** `workspace/_ai_track/AI_PLATFORM_SPEC.md`
> - **WISE AI 적용 명세:** `workspace/_framework/WISE_APPLY_SPEC.md`
>
> 이 문서는 위 소스들을 하네스 지식용으로 통합 요약한 것이다. 충돌 시 단일 출처 문서가 우선한다.

---

## 1. 표준 기술 스택

| 레이어 | 표준 | 비고 |
|--------|------|------|
| 프론트(웹) | **React 18/19 + TypeScript + Vite + Tailwind** | `pages/components/api/store/hooks/routes` 구조 |
| 프론트(모바일) | **React Native + Expo (expo-router)** | `guardia-messenger/app/<sol>/` 통합 런처에 편입 |
| 백엔드 | **Spring Boot 3.5 / Java 17** | controller·service·repository·domain·dto 계층 |
| 백엔드 예외 | FastAPI (Python) | ITSM · Manager · guardia-rag 3개만 허용 |
| ORM | **MyBatis** (`@MapperScan(annotationClass=Mapper.class)`) 또는 JPA | 솔루션 내 일관성 유지 |
| DB | **PostgreSQL** — `<sol>_db` / `<sol>_user` | 공유 인스턴스 + 솔루션별 분리 계정, Hikari `maximum-pool-size: 3` |
| 리포트 | JasperReports (PDF) | 공통 |
| 패키징 | **단일 jar** | 프론트 빌드 → 백엔드 static 번들 → 하나의 jar로 배포 |

### 스택 관련 규칙
- 프론트 axios baseURL은 `/api` — nginx가 `/` → SPA 정적 파일, `/api/` → 백엔드 포트로 프록시하므로 별도 CORS 불필요.
- 모든 API 응답은 봉투(envelope) 형식: `ApiResponse<T> = { success, data, message }`, 목록은 `PageResponse<T>`.
  - 클라이언트(웹·모바일)는 봉투 언랩(unwrap) 유틸을 공통화한다 — 모바일 이식 시 `PageResponse` 봉투 언랩 누락이 실제 경계면 버그 사례.
- DB 스키마의 단일 진실원천은 마이그레이션 DDL (Hibernate 사용 시 `ddl-auto: validate`).
- 신규 솔루션 명명: DB `<sol>_db`/`<sol>_user`, 패키지 `com.zioinfo.<sol>`, 포트는 솔루션별 고정 할당.
- 시크릿·접속정보는 전부 환경변수/프로퍼티 주입 — 하드코딩 금지. (UIMS 예: `UIWS_DB_PASSWORD` 필수, `UIWS_JWT_SECRET` 32바이트 이상 권장 — 미설정 기본값은 개발 전용, 운영 금지.)
- 메일 발송은 모드 스위치 표준: `MAIL_MODE=log`(기본, 로컬 로그 출력) / `smtp`(실발송, SMTP 접속정보 env 주입). 개발 환경에서 실발송 사고를 구조적으로 차단한다.
- 원격 DB 개발 접속은 SSH 로컬 포워딩 터널 경유(DB 포트 외부 비개방 전제).

### UIMS(정본) 백엔드 패키지 구조 (레퍼런스)
```
com.urp.uiws
├── config    : SecurityConfig, JwtProperties, AuthProperties
├── security  : JwtTokenProvider, JwtAuthenticationFilter, UserPrincipal, RestAuthEntryPoint, TokenType
├── common    : response(ApiResponse·PageResponse), exception(ApiException·ErrorCode·GlobalExceptionHandler), mail(MailSender)
├── domain    : User, LoginVerify, Dept, Role, Menu, RoleMenu, DeptRole (BaseEntity)
└── auth      : controller / service(AuthService·TotpService) / repository / dto
```

---

## 2. 표준 인증 (JWT + RBAC + 2FA/OTP)

### 2.1 JWT + RBAC
- JWT 발급(access·refresh) + 역할 기반 접근 제어.
- 역할 게이트 표준: `/api/admin/** = hasRole(ADMIN)`.
- 사용자 조회 `/api/auth/me`는 사용자 정보 + **메뉴 권한 트리**를 함께 반환(메뉴 노출 게이트).

### 2.2 2차 인증 (2FA)
- **OTP(TOTP)**: RFC 6238 — SHA1 · 30초 주기 · 6자리 · ±1 윈도우 허용. UIMS `TotpService`를 이식한다.
- 로그인은 **2단계**: ① ID/PW → `verifyToken` 발급 → ② OTP(또는 이메일 코드) 검증 → access·refresh 발급.
- 검증 방식은 사용자별 `VERIFY_METHOD`(`EMAIL`/`OTP`)로 분기 — `EMAIL`은 6자리 코드 메일 발송, `OTP`는 TOTP 검증(발송 없음). 단일 `/verify-otp` 엔드포인트가 두 방식 모두 처리.
- 최초 로그인 시 QR 등록, 마이페이지에서 재설정/해제, **관리자에 의한 OTP 초기화**(`otp_secret = NULL`) 지원.
- 기존 솔루션 이식 시 테이블에 `otp_secret`·`otp_enabled` 컬럼을 **멱등 ALTER**로 추가.

### 2.3 로그인 실패 잠금
- 연속 로그인 실패 시 계정 잠금 + 관리자 해제 기능.

### 2.4 admin 비밀번호 (env 암호화 주입 — 값 절대 미기재)
- 하드코딩 시드(예: 고정 초기 비밀번호) **금지**.
- 표준 방식: env `ADMIN_PASSWORD_ENC`(AES-256-GCM 암호문) + `ADMIN_KEY_FILE`(별도 키파일, root 전용 권한 600)을 기동 시 복호 → **BCrypt로 재시드**.
- 마스터 키·암호문 파일은 서버 시크릿 디렉터리에만 존재하며 코드·커밋·문서에 값을 기재하지 않는다.
- 서비스별 env 파일(`guardia-ai.env`: `ANTHROPIC_API_KEY` + `ADMIN_PASSWORD_ENC` + `ADMIN_KEY_FILE`)을 systemd **drop-in**(`ai-env.conf`, `EnvironmentFile` 추가)으로 주입한다 — Java 서비스 대부분이 명령줄 인자 기동이므로 drop-in이 표준.

### 2.4a 기존 솔루션 인증 이식 원칙
- 기존 auth 모듈이 있는 솔루션: **교체 금지** — 2FA(OTP)만 레이어로 추가한다.
- auth가 없는 솔루션: UIMS auth 전체 이식(JWT+2FA+잠금).
- 전환 트랙 표준 절차: ① `otp_secret`·`otp_enabled` 멱등 ALTER → ② `TotpService` 이식 → ③ 로그인 2단계 배선 → ④ 전 사용자 OTP 초기화(`otp_secret=NULL`) 1회 → ⑤ QR 등록/마이페이지 재설정/관리자 초기화 화면.
- admin 재시드 전환 시 하드코딩 시드는 제거하고 env 암호문 복호 → BCrypt 재시드로 대체(값은 서버 시크릿에만 존재).

### 2.5 인증 API 표준 (Base: `/api/auth`)
| 메서드 | 경로 | 설명 |
|--------|------|------|
| POST | `/login` | 1차 로그인(ID/PW) → verifyToken |
| POST | `/verify-otp` | 2차 검증(이메일 코드/OTP) → access·refresh |
| POST | `/refresh` | 토큰 재발급 |
| POST | `/logout` | 로그아웃 |
| POST | `/signup` | 회원가입(승인 대기) |
| POST | `/find-id` | 아이디 찾기(마스킹 반환) |
| POST | `/reset-password` | 임시 비밀번호 메일 발송 |
| GET | `/me` | 사용자 + 메뉴권한 트리 |

---

## 3. 표준 공통 업무 모듈 12종 (UIMS 업무협업 레이어)

신규 솔루션은 필요 모듈을 `uiws-port-orchestrator`로 이식한다. 기존 auth가 있는 솔루션에는 **교체가 아니라 2FA 레이어만 추가**한다.

| 모듈 | 이름 | 역할 |
|------|------|------|
| 1. worklog | 업무일지 | 일 단위 업무 기록·상세(시간대별)·진행상태·이슈 기록. 조회 권한은 DataScope(부서/작성자) 기반. 금일 이전 일지는 조회 전용 정책 가능 |
| 2. schedule | 일정 | 개인/부서 일정 등록·캘린더 뷰(월/주)·공유 일정 관리 |
| 3. message | 쪽지 | 사내 사용자 간 쪽지 발신/수신함·읽음 처리 |
| 4. stats | 통계 | 업무일지·일정 데이터 집계(근무현황 피벗 등) 통계 화면 |
| 5. system | 시스템관리 | 사용자·부서·역할/권한(RBAC)·메뉴·공통코드 관리 등 관리자 백오피스 |
| 6. notice | 공지 | 전사/부서 공지사항 게시·조회 |
| 7. opinion | 의견접수 | 사용자 의견·건의 접수 및 관리자 처리 |
| 8. search | 통합검색 | 업무일지·공지·일정 등 모듈 횡단 통합 검색 |
| 9. meeting | 회의록 | 회의 기록·(음성 STT→회의록 자동작성 확장)·액션아이템·Jasper PDF 출력 |
| 10. report | 업무보고 | 일일/주간/월간/분기/연간 기간별 업무현황 집계(`/api/reports/work-status`) + Jasper PDF 다운로드. 기간 산출은 서버 권위(WEEKLY=ISO 월~일, QUARTERLY=역년 분기) |
| 11. notification | 알림센터 | 시스템 이벤트·승인·쪽지 등 통합 알림 수신함 |
| 12. audit | 감사로그 | 주요 행위(로그인·데이터 변경·관리자 조작) 감사 기록(TB_AUDIT_LOG) |

> 표준 명세에는 위 12종 외에 **dashboard(대시보드)·preference(개인화)·adminCode(공통코드)** 도 공통 레이어로 열거되어 있다(system과 함께 관리 영역 구성).

### 3.1 모듈별 상세 규약 (UIMS 정본 기준)

**worklog (업무일지)**
- 마스터/디테일 구조: `TB_WORKLOG`(일자·작성자·진행상태) + `TB_WORKLOG_DTL`(시간대별 상세 — 시작/종료 시각, 업무유형 코드, 이슈 내용).
- 조회 권한은 DataScope 3단계: ADMIN(전체) / MANAGER(부서+하위) / USER(본인). 모든 목록·집계 API에 필수 적용.
- 과거 일지 조회 전용 정책 적용 시: **저장된 workDate 기준**으로 백엔드 403(우회 차단) + UI 차단 이중 방어. 조회(GET)·신규 생성·댓글은 예외.

**meeting (회의록)**
- `TB_MEETING` + `TB_MEETING_ACTION`(액션아이템). 확장 시 오디오 업로드 → STT → 회의록 자동작성 파이프라인(AI degraded 폴백 포함, 오디오는 STT 후 폐기).
- 회의록 PDF는 JasperReports(`meeting_minutes.jrxml`) 렌더.

**report (업무보고)**
- 계약: `GET /api/reports/work-status?period=DAILY|WEEKLY|MONTHLY|QUARTERLY|YEARLY&baseDate&deptId&writerId` → `WorkReportDto(summary·byWriter·byType·byDay)`.
- PDF: `GET /api/reports/work-status/pdf`(동일 파라미터, `application/pdf`) — 공용 jrxml 1종으로 5기간 렌더.
- **기간 산출은 서버 권위**: WEEKLY = ISO 월~일, QUARTERLY = 역년 분기. DataScope 권한 필수.

**system (시스템관리)**
- 사용자·부서(`TB_DEPT`)·역할(`TB_ROLE`)·메뉴(`TB_MENU`·`TB_ROLE_MENU`)·공통코드 관리. 메뉴 권한 트리는 로그인 응답(`/me`)으로 내려가 프론트 메뉴 노출을 게이트한다.
- 회원가입은 승인 대기(`APPROVAL_YN='N'`) → 관리자 승인 흐름.

**audit (감사로그)**
- 로그인·데이터 변경·관리자 조작을 `TB_AUDIT_LOG`에 기록. 관리자 화면에서 조회. 감사로그 자체에 자격증명·PII 원문 미기록(마스킹).

### 3.2 데이터 관례
- 테이블 접두어 `TB_*` (UIMS 관례: `TB_USER`, `TB_WORKLOG`, `TB_MEETING`, `TB_LOGIN_VERIFY`, `TB_AUDIT_LOG` 등).
- 모든 시드·DDL은 **멱등**(유니크 인덱스 + on conflict / IF NOT EXISTS / 멱등 ALTER)으로 작성 — 재실행 안전.
- 후행 스키마 확장 시 `sql.init mode=never`면 재적용되지 않아 런타임 `relation does not exist` 500이 난다 → `mode=always` + `continue-on-error` + 시드 멱등화가 표준 패턴.
- 메뉴 신설 시 메뉴 시드까지 함께 커밋(화면은 있는데 메뉴에 없는 누락 방지).

---

## 4. WISE 디자인 시스템

### 4.1 브랜드 토큰
| 토큰 | 값 | 용도 |
|------|-----|------|
| 시안(Cyan) | `#11c3ff` | 브랜드 포인트 |
| 블루(Blue) | `#1f29fc` | 주 액션·강조 |
| 잉크(Ink) | `#252525` | 본문 텍스트 |
| 그레이(Gray) | `#3f3f3f` | 보조 텍스트 |

### 4.2 원칙
- **서체: Pretendard** 전면 적용.
- **카드 중심 레이아웃** + 라이트/다크 테마 토글 지원.
- **선(stroke) SVG 아이콘 직접 제작**: `fill:none`, `stroke:currentColor`. **외부 아이콘 라이브러리 금지**(이모지 아이콘도 공개 화면에서 배제).
- 색상 버튼/배지 위 텍스트는 다크 모드 대응 토큰(`--color-on-accent` 패턴)으로 흰 글자 보장.
- **디자인 수석 `guardia-chief-designer`가 전 UI 작업의 고정 리드** — 화면 방향 확정 → 구현 → 검수 순서.

### 4.3 WISE AI 브랜딩 (전 솔루션 적용 표준)
- AI 메뉴명은 **"WISE AI"** + 부제 "Enterprise AI for Trusted Knowledge" (WISE = Workplace Intelligence Search Engine). 기존 AI 메뉴가 있으면 개명하며 중복 메뉴 신설 금지.
- AI 질의 화면 표준 구성: 질문 입력 → 답변(plain text) → **인용(sources) 카드 리스트**(문서명·위치, 없으면 "근거 문서 없음" 표기) → abstain/degraded 배지 → 👍/👎 피드백(기존 피드백 API 있을 때 연결).
- 환각차단 UX: `abstained=true` → 경고 톤 배지("근거가 부족해 답변을 보류했습니다" — 오류 아님 안내), `degraded` → 회색 배지(사유 코드).

### 4.4 WISE AI 적용 판정 매트릭스 (A~F — WISE_APPLY_SPEC)
솔루션에 WISE AI를 적용할 때는 아래 6개 항목을 감사해 미충족분만 보강한다(기존 재구현 금지).

| 항목 | 표준 |
|---|---|
| A. rag 클라이언트 | 백엔드 RagClient(기존 것 재사용 우선) — `/rag/answer` 프록시 엔드포인트 `POST /api/wise/ask` |
| B. AI 질의 화면 | 관리자 웹에 "WISE AI" 메뉴/페이지 1개 — 질문 입력 → 스피너 → 답변 |
| C. 인용 UX | 답변 하단 `sources[]` 카드(문서명·위치) |
| D. 환각차단 UX | abstain 경고 배지 / degraded 회색 배지 |
| E. 브랜딩 | 메뉴명 "WISE AI" + 부제, 기존 AI 메뉴 개명 |
| F. AI 설정 | 기존 AiConfig 화면 있으면 유지(없으면 별도 트랙) |

**완료 정의(솔루션당):** A~E 충족(F는 기존 있을 때만) · 백엔드/프론트 빌드 통과 · 라이브 `/api/wise/ask` 200(답변 또는 abstain) · 화면 진입 확인 · 기존 화면 회귀 0(라우트 충돌 0).

---

## 5. 표준 AI 플랫폼 (온프레미스 우선 + Claude)

### 5.1 프로바이더 패밀리 (설정 화면 선택형 — UIMS AiConfigPage 미러)
| 패밀리 | 성격 | 경로 |
|--------|------|------|
| **Claude** | 프리미엄(외부, 소유자 승인 단일 예외) | Anthropic Messages API — 키는 env `ANTHROPIC_API_KEY`에서만 로드 |
| **Qwen** | 최고성능 오픈소스(범용, 기본 `qwen3:1.7b`) | Ollama 온프레미스 |
| **DeepSeek** | 오픈소스(추론 특화, `deepseek-r1:1.5b`) | Ollama 온프레미스 |
| **GLM (Zhipu)** | 오픈소스(범용, 9B — RAM 제약으로 서버 기동 보류) | Ollama 온프레미스 |
| **Ollama 소형** | 최종 폴백 (`llama3.2:1b`, 비전 `moondream`) | Ollama 온프레미스 |

- GLM/Qwen/DeepSeek은 **Ollama 온프레미스로만** 사용 — 각사의 클라우드 API(Zhipu/DashScope/DeepSeek 클라우드) 호출 금지.

**모델 화이트리스트 (임의 문자열 거부):**
```
provider ∈ { claude, qwen, deepseek, glm, ollama }
claude   ∈ { claude-sonnet-4-6 (기본), claude-haiku-4-5, claude-opus-4-8 }
qwen     ∈ { qwen3:1.7b (기본), qwen3:0.6b, qwen3:4b* }
deepseek ∈ { deepseek-r1:1.5b (기본), deepseek-r1:7b* }
glm      ∈ { glm4:9b* }
ollama   ∈ { llama3.2:1b (기본), moondream(vision) }
```
- `*` = RAM 초과 가능 — 설정 화면에 "RAM 여유 필요" 배지 표시, 선택은 허용하되 콜드로드 실패 시 폴백.
- GLM RAM 정책: 대형 모델이 서버 가용 RAM을 초과하면 화이트리스트 등록(선택 가능)은 유지하되 서버 pull/기동은 RAM 증설 전까지 보류 — 설정 화면에 "RAM 증설 필요" 경고를 **명시**한다(조용한 드롭 금지).

### 5.2 AiTextRouter — 3계층 추론 폴백 체인
```
선택 provider 1차 시도 → 실패(degraded) 시:
  claude              → qwen(qwen3:1.7b) → ollama(llama3.2:1b) → degraded:true
  qwen/deepseek/glm   → 해당 Ollama 모델 → llama3.2:1b        → degraded:true
```
- Claude 실패는 예외(장애)로 취급하지 않는다 — degraded 표시 후 다음 단계 폴백(**서비스 중단 금지**).
- 동시 모델 로드 금지(서버 RAM 제약), 콜드로드 타임아웃 240s 이상 감안.
- 구현 레퍼런스: UIMS `common/ai/ClaudeTextClient` · `system/ai(AiTextRouter·AiConfigService)` · `AiConfigPage.tsx`.

### 5.3 중앙 RAG 서비스 (guardia-rag) 계약
- 아키텍처 결정: LangChain은 Python, 대부분 솔루션은 Java → **중앙 Python RAG 서비스 1개 + 각 솔루션의 얇은 REST 클라이언트**. 솔루션별 컬렉션 격리(`rag_<solution>`).
- 스택: LangChain + ChromaDB + Ollama 임베딩(`nomic-embed-text`). 엔터프라이즈 목표 스택(Milvus·vLLM·BGE-M3 등)은 어댑터로 정렬하되 개발 서버에서는 경량 폴백만 실행.

**중앙 계약 엔드포인트** (변경 금지 — 소비만):
| 엔드포인트 | 역할 |
|-----------|------|
| `POST /rag/answer` | 근거 기반 답변. 요청 `{solution, query, retrieval_mode?}` → 응답 `answer, sources[], grounded, faithfulness, abstained, degraded/degraded_reason, trace_id` |
| `POST /rag/verify` (`/verify`) | 근거검증(grounding/faithfulness)·팩트체크 |
| `POST /rag/agent` (`/agent`) | 에이전틱 tool-use 실행 |
| `POST /rag/structured` (`/structured`) | 구조화 출력(JSON) 생성 |
| `POST /rag/feedback` (`/feedback`) | 👍/👎 + 교정 피드백 수집(학습 루프) |
| `POST /rag/chat` (`/chat`) | 멀티턴 RAG 대화(메신저 어시스턴트용) |

**검색·응답 옵션:**
- `retrieval_mode`: `vector`(기본 벡터) | `hybrid`(BM25+Dense 하이브리드) | `graph`(GraphRAG — 문서 지식그래프) 선택형. 리랭킹은 중앙 서비스가 수행.
- 응답의 `grounded`/`faithfulness`는 근거검증 점수, `abstained`는 근거 미달 시 답변 보류(환각 차단), `trace_id`는 추적용.
- 생성/비전 모델 콜드로드는 서버 RAM을 위협 — 소형 모델 기본, 비전 자동 로드 금지, 동시성 제한, 실패 시 검색만 수행하는 `degraded:true` 폴백.

**솔루션 측 소비 패턴:**
- 브라우저는 rag를 직접 호출하지 않는다 — **솔루션 백엔드가 프록시**: `POST /api/wise/ask {query}` → rag `/rag/answer` 호출(기존 JWT 필터 뒤, 로그인 사용자만).
- 솔루션에서 **LLM/Ollama 직접 호출 신설 금지** — 전부 중앙 rag 경유(서버 RAM 보호).
- rag 호출 실패는 "AI 서비스 일시 불가" 요약 메시지(스택트레이스 미노출), 타임아웃 240s.

### 5.4 AI 학습 (피드백 루프 + DuckDB)
- 각 솔루션은 로컬 임베디드 **DuckDB**(`<sol>_learning.duckdb`)를 AI 피드백·학습 데이터셋·분석 저장소로 사용 (Java: `org.duckdb:duckdb_jdbc`, Python: `duckdb`).
- 표준 스키마(멱등): `ai_feedback(id, ts, solution, feature, question, answer, verdict, correction, user_masked)` · `ai_infer_log(id, ts, provider, model, latency_ms, degraded)`.
- 피드백 UI는 **로컬 DuckDB 기록 + 중앙 guardia-rag `/feedback` 전달 둘 다** 수행 — 중앙은 통합 학습·평가 게이트, 로컬은 솔루션별 분석/오프라인.
- 학습 파이프라인: 피드백 → 데이터셋 → LoRA 오프서버 학습 → 평가 게이트 → 모델 반영.
- PII·자격증명은 수집 시 마스킹, 솔루션별 파일 격리.

---

## 6. 표준 보안 (불변 규칙)

| 규칙 | 내용 |
|------|------|
| **외부 API 금지** | 온프레미스(Ollama)만 허용. **단일 예외:** Anthropic Claude API(`api.anthropic.com`, 소유자 승인) — 키는 서버 env에서만 로드, DB·코드·커밋·로그·응답 기록 금지, 실패 시 Ollama 자동 폴백. 그 외 외부 API 전면 금지 |
| **자격증명 미노출** | 비밀번호·SSH 계정·내부 IP·API 키·OTP 시크릿은 env 또는 DB(해시/암호화)에만 존재. API 응답·에러 메시지·로그·커밋에 절대 노출 금지 |
| **암호화 저장** | 민감 자격증명은 **AES-256-GCM** 암호화 저장(예: 서버 접속 비밀번호 컬럼, admin 비번 env 암호문). 사용자 비밀번호는 BCrypt 해시 |
| **스택트레이스 차단** | 에러 응답은 요약 메시지만 반환. `DataAccessException` 등 전역 예외 핸들러로 내부 정보 누출 차단 |
| **감사 추적** | 주요 명령·변경은 감사로그(TB_AUDIT_LOG)에 기록 |
| **응답 스키마 필터** | 서버 자산 API 응답에서 IP·SSH 계정·암호화 비번 컬럼 완전 제외 |
| **시드 안전성** | `sql.init mode=always` + `continue-on-error` + 시드 멱등화(유니크 인덱스) — 후행 스키마 확장에 의한 누락 테이블 500 방지 |
| **최소 권한** | 관리 대상(테넌트) 서버에 root SSH 직접 접속 금지 — 관제 전용 일반 계정 사용(자체 인프라 서버만 소유자 승인 예외) |

---

## 7. 표준 배포

### 7.1 파이프라인 흐름
```
workspace/<sol>  (개발 소스)
   → repos/<sol> (fresh git init 독립 저장소)
   → Gitea push  (git.zioinfo.co.kr/zio/<sol>)
   → Gitea webhook (push 이벤트)
   → deploy_server (webhook 수신 → git pull → 빌드 → 재시작)
   → systemd (<sol>.service — 부팅 자동기동·재시작)
   → nginx (도메인 vhost: / → SPA 정적, /api/ → 백엔드 포트 프록시, certbot TLS)
```

### 7.1a nginx vhost 표준 (도메인 서빙형)
```
브라우저 ── https ──> nginx(<sol>.zioinfo.co.kr)
                        ├─ /      → /var/www/<sol>  (React SPA build, index.html 폴백)
                        └─ /api/  → 127.0.0.1:<백엔드 포트> (Spring Boot)
```
- vhost 정본은 repo의 `deploy/nginx/*.conf`에 두고 서버 `sites-available` → `sites-enabled` 심링크. `nginx -t` 통과 후 reload(타 사이트 무영향 확인).
- 절차: DNS A 레코드 등록 → 전파 확인 → `certbot --nginx -d <domain>`(443 블록 + 80→443 리다이렉트 자동 주입, 갱신은 certbot timer) → 프론트 dist 복사 → 백엔드 systemd 기동.
- 백엔드 포트는 서버 점유 현황 확인 후 솔루션별 고정(`server.port: ${SERVER_PORT:<포트>}`).

### 7.2 배포 규칙
- **Fail-Safe 시퀀스**: 백업 → 배포 → 헬스체크 → 롤백.
- 배포 후 **health 게이트** 확인 필수(엔드포인트 200 확인 후 완료 선언).
- **서버 빌드는 직렬 실행** — 공유 메모리 서버에서 병렬 빌드 시 OOM 위험.
- AI env는 systemd **drop-in**으로 주입: 서비스 작업 디렉터리의 `guardia-ai.env`(600) + `ai-env.conf`(EnvironmentFile) — 기존 ExecStart 불변.
- 웹훅 시크릿·자격증명은 설정 파일/env로만 관리(마스킹), 배포 로그에 미노출.
- 함정 주의: 배포 로그가 "완료"여도 소요가 비정상적으로 짧으면 deploy_server에 해당 솔루션 블록이 없는 것일 수 있다 — deploy_server 수정 시 서버 사본 반영 + 재시작 필수.

### 7.2a 배포 검증 체크리스트
- [ ] 빌드: 백엔드 compile/bootJar 통과 + 프론트 빌드 통과(단일 jar면 프론트 → 백엔드 static 번들 순서 준수).
- [ ] DB: 마이그레이션/시드 멱등 확인 — 라이브 반영 전 dry-run(트랜잭션 BEGIN…ROLLBACK) 권장.
- [ ] 시크릿: fail-fast — 필수 env 미설정 시 기동 실패로 조기 검출(운영에서 개발 기본값 사용 금지).
- [ ] 커밋: 파일 단위로 스코프 분리(공유 트리 교차 커밋 방지).
- [ ] 배포 후: health 엔드포인트 200 → 대표 화면/대표 API 스팟체크 → 기존 기능 회귀 확인.
- [ ] 웹훅: Gitea webhook URL·secret·allowed hosts 정합(불일치 시 403/no-op으로 조용히 실패하는 사례 있음).

### 7.3 프론트/백엔드 배포 형태
- 표준은 **단일 jar**(프론트 빌드를 백엔드 static으로 번들) — jar 하나만 systemd로 기동.
- 일부 솔루션(UIMS 등)은 nginx 직접 서빙형: 프론트 `dist/` → `/var/www/<sol>/`(SPA `index.html` 폴백), 백엔드는 전용 포트 systemd 기동.
- DNS(서브도메인 A 레코드) → certbot TLS(80→443 리다이렉트 자동 주입) → 배포 순서.

---

## 8. 준수·이식 하네스 맵

| 트랙 | 담당 하네스 |
|------|------------|
| 공통 업무모듈·2FA 이식 | `uiws-port-orchestrator` |
| Claude AI 전환·OTP·admin 표준화 | `guardia-claude-ai-orchestrator` |
| RAG 검색 인프라 | `guardia-rag-orchestrator` |
| 환각 방지·근거검증 레이어 | `guardia-ai-trust-orchestrator` |
| 검색 품질 기법(GraphRAG·rerank 등) | `guardia-ai-technique-orchestrator` |
| WISE AI 전 솔루션 적용 | `wise-ai-platform-orchestrator` (+ `WISE_APPLY_SPEC.md`) |
| 관리자 백오피스 표준화 | `guardia-admin-orchestrator` |
| 스키마 무결성 점검·수복 | `schema-integrity-orchestrator` |

### WISE AI 적용 불변 규칙 (적용 에이전트 공통)
1. 기존 기능 회귀 0 — 기존 AI/RAG 코드 삭제·개조 금지(보강·개명만). 빌드 통과 필수.
2. 외부 API 0(anthropic 예외) — 단, WISE 적용 트랙은 **rag 경유만**: 솔루션에서 LLM 직접 호출 신설 금지.
3. 자격증명·내부 IP·스택트레이스 미노출. rag 호출 실패는 요약 메시지로 처리.
4. 서버 RAM 존중 — 솔루션에서 Ollama 직접 호출 신설 금지(전부 중앙 rag 경유).
5. 커밋 메시지는 영문. push는 자동배포 스크립트 경유, 배포 후 health 확인.

### 적용 대상 스코프 (2026-07 기준)
- Java(Spring Boot): erp·crm·ocr(WISE)·bi·pms·rpa·groupware·portal·mall·cms·mes·hrm·fa·esn·zioinfo-esn + 신규(mro·signage 등).
- Python(FastAPI 예외): itsm·manager·guardia-rag(중앙).
- 제외: uiws(표준 정본 — 읽기 전용)·zioinfo-web(AI 없음).

### 신규 프로젝트 체크리스트 (요약)
1. 스택: React+TS+Vite / Spring Boot 3.5 Java 17 + MyBatis / PostgreSQL `<sol>_db` / 단일 jar.
2. 인증: JWT+RBAC + TOTP 2FA + 로그인 잠금 + admin 비번 env 암호화 재시드.
3. 공통 모듈: worklog·schedule·message·stats·system·notice·opinion·search·meeting·report·notification·audit 중 필요분 이식.
4. 디자인: WISE 토큰·Pretendard·카드·선 SVG 아이콘, `guardia-chief-designer` 리드.
5. AI: AiTextRouter 폴백 체인 + 중앙 guardia-rag 경유(`/api/wise/ask` 프록시) + DuckDB 피드백.
6. 보안: 외부 API 금지(Anthropic 예외)·자격증명 미노출·AES-256-GCM·스택트레이스 차단·감사로그.
7. 배포: repos→Gitea→webhook→systemd→nginx, health 게이트, Fail-Safe 롤백.

---

## 8a. 용어 정리

| 용어 | 의미 |
|------|------|
| UIMS / UIWS | URP Infra Working System — GUARDiA 표준 프레임워크의 정본 레퍼런스 구현(`workspace/uiws`) |
| WISE | Workplace Intelligence Search Engine — 엔터프라이즈 AI 브랜드이자 디자인 시스템 명칭 |
| guardia-rag | 중앙 온프레미스 RAG 서비스(Python FastAPI) — 전 솔루션 AI 질의의 단일 경유점 |
| AiTextRouter | 프로바이더 선택 + 3계층 폴백을 수행하는 표준 AI 라우터(UIMS 패턴) |
| DataScope | 목록·집계 API의 조회 범위 권한(ADMIN 전체 / MANAGER 부서+하위 / USER 본인) |
| abstain | 근거 미달 시 답변을 보류하는 환각 차단 동작(`abstained=true`) |
| degraded | 상위 프로바이더 실패로 폴백·축소 동작 중임을 알리는 상태 플래그 |
| 단일 jar | 프론트 빌드 산출물을 백엔드 static에 번들해 jar 하나로 배포하는 표준 패키징 |

---

## 9. 참조 소스 맵

| 문서 | 경로 | 성격 |
|------|------|------|
| 표준 프레임워크 명세 | `workspace/_framework/GUARDIA_STANDARD_FRAMEWORK.md` | **단일 출처(최우선)** |
| WISE AI 적용 명세 | `workspace/_framework/WISE_APPLY_SPEC.md` | 전 솔루션 WISE AI 적용 계약 |
| Stitch 디자인 베이스 | `workspace/_framework/STITCH_DESIGN_BASE.md` | 디자인 생성 기준 |
| AI 플랫폼 스펙 | `workspace/_ai_track/AI_PLATFORM_SPEC.md` | 프로바이더·화이트리스트·폴백·DuckDB 계약 |
| AI 설정화면 스펙 | `workspace/_ai_track/design/ai_platform_settings_spec.md` | AiConfig 화면 |
| OTP 마이페이지 스펙 | `workspace/_ai_track/design/otp_mypage_spec.md` | 2FA UX |
| UIMS 백엔드 README | `workspace/uiws/backend/README.md` | auth·봉투·패키지 구조 정본 |
| UIMS 배포 가이드 | `workspace/uiws/deploy/README_배포.md` | nginx vhost·certbot·systemd 절차 |
| 프로젝트 마스터 컨텍스트 | `C:\GUARDiA\CLAUDE.md` § "GUARDiA 표준 프레임워크 (UIMS 기준)" | 승격 선언·하네스 맵 |

> **주의:** 이 지식 문서에는 비밀번호·API 키·토큰·SSH 자격증명을 기재하지 않는다. 실제 값은 서버 env/시크릿 파일에만 존재하며, 서버 식별은 도메인(`zioinfo.co.kr`, `git.zioinfo.co.kr` 등)으로만 한다.
