# 설계서: 정형 데이터 원장 조회 (#618)

> **상태**: Implemented · QA passed · deployed
> **작성**: [AI] Architect · **최종수정**: 2026-07-07
> **추적성** — Redmine: #618 · 관련 ADR: 없음
> · 구현 파일: `StructuredDataController`, `StructuredDataService`, `structured-data.html` · 테스트: `StructuredDataServiceTest`, `GuidedFlowTemplateTest`

## 1. 목적 (Why)

VPD 권한 운영자가 KBAIPOC의 정형 보험 원장 데이터를 별도 SQL 도구 없이 빠르게 확인할 수 있게 한다.

## 2. 범위 (Scope)

- **포함**: `POC_2`의 고객·상품·계약·담보·청구·외부보유·이해관계자 7개 테이블 선택, 컬럼명, 최대 50건 읽기 전용 미리보기.
- **제외 (out of scope)**: 임의 SQL 실행, 데이터 수정·삭제, VPD 정책 자동 생성, RAG/약관/백업·시스템 테이블 표시.

## 3. 인수조건 (Acceptance Criteria)

- [x] 연동 도구 메뉴에서 정형 데이터 조회 화면으로 이동할 수 있다.
- [x] 지정된 7개 테이블만 선택할 수 있다.
- [x] 선택한 테이블의 컬럼 순서와 최대 50건의 행을 표시한다.
- [x] 허용 목록 밖의 table 파라미터는 SQL 문자열에 포함되지 않고 거부된다.
- [x] 데이터가 없거나 DB 조회가 실패해도 안전한 안내를 표시한다.

## 4. 컨텍스트 & 제약

- 데이터 owner는 현재 KBAIPOC의 `POC_2`로 고정한다.
- 백오피스는 관리자용 읽기 화면이므로 페이지를 인증 뒤에만 제공한다.
- 고객 식별 정보는 현 POC의 `RRN_MASKED`처럼 이미 마스킹된 컬럼만 사용한다. 운영 데이터에 적용하기 전에는 별도 VPD/마스킹 정책을 연결한다.

## 5. 아키텍처 개요

```
브라우저 GET /structured-data?table=customers
        ↓
StructuredDataController
        ↓
StructuredDataService (7개 고정 allowlist)
        ↓
JdbcTemplate → POC_2.KB_CUSTOMERS (ROWNUM <= 50)
        ↓
Thymeleaf 표 미리보기
```

사용자 입력은 allowlist key 선택에만 쓰고, DB owner·테이블명은 서버 상수에서만 가져온다. JDBC I/O는 서비스에 두고, 테이블 카탈로그 검증은 순수 메서드로 분리한다.

## 6. 데이터 모델

| key | DB 테이블 | 업무명 |
|---|---|---|
| `customers` | `KB_CUSTOMERS` | 고객원장 / 고객 기본정보 |
| `products` | `KB_PRODUCTS` | 상품원장 / 보험상품 마스터 |
| `contracts` | `KB_CONTRACTS` | 계약원장 / 보험계약 정보 |
| `coverages` | `KB_COVERAGES` | 담보원장 / 보장·특약 정보 |
| `claims` | `KB_CLAIMS` | 청구원장 / 보험금 청구·지급 정보 |
| `external-holdings` | `KB_EXTERNAL_HOLDINGS` | 외부보유정보 원장 / 타사·외부 가입·보유 정보 |
| `stakeholders` | `KB_STAKEHOLDERS` | 이해관계자 원장 / 역할·담당자 매핑 |

## 7. 함수 명세 (Function Specs)

| 함수 | 책임 | 입력 | 출력 | 에러/실패 | 복잡? |
|---|---|---|---|---|---|
| `requireTable` | allowlist key를 테이블 정의로 해석 | key | table definition | 알 수 없는 key 거부 | 단순 |
| `preview` | 컬럼과 제한된 행을 조회 | key | preview view | DB 접근 오류를 안전한 메시지로 변환 | 단순 |

## 8. 흐름 / 알고리즘

1. 기본값으로 고객원장을 선택한다.
2. 요청 key가 7개 allowlist에 있는지 검증한다.
3. `ALL_TAB_COLUMNS`에서 표시 컬럼 순서를 읽는다.
4. 고정 owner/table로 최대 50건을 조회한다.
5. 컬럼 헤더와 행을 표로 렌더링한다.

## 9. 엣지케이스 & 에러 처리

- 알 수 없는 key: SQL을 만들지 않고 안내 메시지를 표시한다.
- 대상 테이블이 없거나 권한이 없음: DB 오류 원문 대신 대상/권한 점검 안내를 표시한다.
- 0건: 빈 결과 안내와 함께 컬럼 헤더는 유지한다.

## 10. 테스트 계획

- 카탈로그가 정확히 7개 key와 테이블을 포함하는지 단위 테스트한다.
- 허용 목록 밖 key를 거부하는지 단위 테스트한다.
- 템플릿·메뉴가 정형 데이터 조회 경로와 읽기 전용 안내를 포함하는지 정적 템플릿 테스트한다.

## 11. 리스크 & 대안 검토

- 관리자 JDBC로 직접 조회하므로 운영 개인정보를 그대로 보여줄 수 있다. 따라서 임의 SQL과 RAG/백업 테이블 노출을 제외하고, 현 POC에서는 마스킹된 고객 식별자만 있는 7개 원장으로 범위를 제한한다.
- 최종 사용자별 행 보기가 필요하면 이 페이지가 아니라 ORDS + VPD 검증 경로를 사용한다.

## 12. 미해결 질문 (Open Questions)

- 운영 전환 시 `POC_2` owner를 환경 설정으로 분리할지 결정한다.
- 행 단위 VPD 적용 결과를 이 화면에서 볼 필요가 생기면 검증 세션을 필수 입력으로 하는 별도 화면으로 분리한다.

## 13. 구현·배포 검증

- `mvn test` 통과: allowlist 7개 테이블과 비허용 key 거부 단위 테스트, 메뉴·도움말 템플릿 검증을 포함한다.
- VM SQLcl에서 백오피스 계정으로 `POC_2.KB_CUSTOMERS` 110건을 읽을 수 있음을 확인했다.
- `vpd-backoffice.service`에 새 JAR를 배포한 뒤 인증된 `/structured-data?table=customers` 응답에서 `KB_CUSTOMERS`, `CUST_ID`, `고객원장` 렌더링을 확인했다.
