diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e46c0eb --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +All notable portfolio documentation changes are recorded here. + +## 0.1.0 - 2026-05-21 + +### Added + +- Added the `Public Admin GIS Modernization` project title. +- Added a case-study structure under `cases/`. +- Added the consultation-management case with before/after screenshots. +- Added the boundary-adjustment case for file-parcel registration and map-based adjustment-count review. +- Added sanitized Java, JSP, and SQL mapper examples for the boundary-adjustment flow. +- Added public redaction rules for production table names, API paths, work codes, parcel identifiers, and internal system names. +- Added placeholder image slots for masked boundary-adjustment screenshots. +- Added a portfolio review license. + +### Changed + +- Moved existing sample source and images out of the repository root into case-specific folders. +- Reworked the root README into a navigation and evidence summary layer. + +### Security + +- Removed production-identifying names from public example code and documentation. +- Documented the repository's redaction checklist before publishing additional screenshots. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..773e7bc --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +Portfolio Review License + +Copyright (c) 2026 yungi0816 + +This repository is published for portfolio review and technical evaluation. + +You may view the documentation, screenshots, and sanitized source examples for +review purposes. + +You may not copy, redistribute, republish, or use the materials in another +project without written permission. + +The repository intentionally excludes production system identifiers, real +operational data, internal API names, and protected public-sector information. diff --git a/README.md b/README.md index e8e6305..384276d 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,57 @@ -# Government Admin UI/UX Modernization Example +# Public Admin GIS Modernization [한국어 README](README_KOR.md) -[![Java](https://img.shields.io/badge/Java-ED8B00?style=flat-square)](https://www.java.com/) -[![Maven](https://img.shields.io/badge/Maven-C71A36?style=flat-square&logo=apachemaven&logoColor=white)](https://maven.apache.org/) -[![OpenLayers](https://img.shields.io/badge/OpenLayers-1F6B75?style=flat-square&logo=openlayers&logoColor=white)](https://openlayers.org/) -[![UI/UX](https://img.shields.io/badge/UI%2FUX-modernization-2563EB?style=flat-square)](https://github.com/yungi0816/gov-admin-uiux-example) +Case-study repository for improving map-based work flows and legacy UI structure in public-sector administration systems. -This repository is a practical before/after example for modernizing a 10+ year-old public-sector admin system. +The repository does not expose the original production system. Each case keeps the workflow, design decisions, review notes, and sanitized implementation structure while removing internal table names, API names, organization identifiers, work codes, parcel identifiers, and real operational data. -The goal is not to redesign everything at once. The focus is to reduce user resistance, preserve familiar work patterns, and improve consultation management and map-based selection flows for real business users. +## Technical Evidence -## Summary +| Area | Evidence | +| --- | --- | +| Legacy Java/JSP modernization | UI improvements are documented within JSP, jQuery, Java controller/service/repository, and mapper constraints | +| GIS-enabled admin workflow | OpenLayers-based parcel selection and boundary review flows are documented as separate case studies | +| Public-sector system constraints | Audit logging, authorization, fixed business procedures, and shared UI rules are treated as design constraints | +| User-centered operation design | Before/after screenshots and review notes explain how the work reduces confirmation cost and input mistakes | +| Security-aware documentation | Sanitized source and redaction rules prevent production identifiers from being published | -- Target: legacy admin consultation and map-based workflow screens -- Main users: field operators and public-sector staff, especially users in their 40s to 60s -- Goal: reduce friction, improve task efficiency, and lower input errors -- Core methods: conversational consultation UI, OpenLayers map selection, report automation +## Cases -## Who This Is For +| Case | Topic | Improvement Focus | Document | +| --- | --- | --- | --- | +| 01 | Consultation management and map selection | Reorganized consultation flow and strengthened map-based selection | [cases/consult-management](cases/consult-management/README.md) | +| 02 | Boundary adjustment file and parcel review | Registers files with linked parcels and visualizes adjustment counts on the map | [cases/boundary-adjustment](cases/boundary-adjustment/README.md) | -- Developers modernizing old Java/JSP admin systems -- Teams looking for UI/UX examples that respect existing user habits -- Portfolio builders who want to explain a practical before/after redesign +## Documentation -## Features +| Area | Document | +| --- | --- | +| Documentation index | [docs/README.md](docs/README.md) | +| Review framework | [docs/review-framework.md](docs/review-framework.md) | +| Security redaction policy | [docs/security-redaction.md](docs/security-redaction.md) | +| Changelog | [CHANGELOG.md](CHANGELOG.md) | -- Conversational consultation management UI -- Map-based parcel selection to reduce manual input errors -- Automated operation report flow -- Performance notes for PL/SQL and query optimization examples +## Repository Structure -## Quick Start - -1. Install Java 11+ and Maven. -2. Build from the project root. - -```bash -mvn clean package +```text +. +|-- README.md +|-- README_KOR.md +|-- docs/ +`-- cases/ + |-- consult-management/ + `-- boundary-adjustment/ ``` -3. Check sample DB/config files under `resources/` when available. - -## Before & After - -The gallery below shows how the interface changes from dense legacy screens to more guided task flows. - - - - - - - - - - -
BeforeAfter
- Before 1
- Dense text and table-based screen -

- Before 2
- Nested forms and long lists -

- Before 3
- Map flow not integrated -
- After 1
- Conversational consultation with key summary -

- After 2
- Simplified filters and shortcut actions -

- After 3
- Direct map-based selection -
- -## Design Principles - -- Keep base text around 16px to 18px for readability. -- Use 44px to 48px minimum control heights to reduce click mistakes. -- Use explicit labels and step-by-step progressive disclosure. -- Preserve enough contrast between text and backgrounds. -- Explain both the cause and next action in error messages. - -## Suggested Design Tokens - -```css -:root { - --font-size-base: 18px; - --line-height: 1.4; - --button-min-height: 48px; - --space-section: 24px; - --accent-color: #2b7cff; -} -``` +## Redaction Standard + +Production table names, API paths, work codes, schema names, package names, organization names, user identifiers, parcel identifiers, and internal map utilities are replaced with role-based sample names. The sanitized source files are intended to explain architecture and review decisions, not to run against a real environment. -## Contributing +## Image Workflow -- Report bugs or setup problems in [Issues](https://github.com/yungi0816/gov-admin-uiux-example/issues). -- Share public-sector or legacy UI improvement ideas in [Discussions](https://github.com/yungi0816/gov-admin-uiux-example/discussions). -- Documentation, accessibility, and screenshot explanation improvements are welcome as pull requests. +Each case owns its screenshots under `cases//assets/`. Add images using the filenames documented in each case README and the gallery will render directly from the README. ## License -No explicit license is currently provided. If this project is intended for open reuse, adding MIT or Apache-2.0 is recommended. +This repository is published for portfolio review. See [LICENSE](LICENSE). diff --git a/README_KOR.md b/README_KOR.md index 8b84199..c4137a1 100644 --- a/README_KOR.md +++ b/README_KOR.md @@ -1,83 +1,102 @@ -# 국가 행정 시스템 UI/UX 개선 예시 +# Public Admin GIS Modernization [English README](README.md) -10년 이상 운영된 레거시 행정 시스템의 화면을 실사용자 중심으로 재설계한 사례입니다. - -핵심 목표는 기존 업무 흐름을 갑자기 뒤집지 않으면서, 상담 관리와 지도 기반 선택 작업의 사용성을 높이는 것입니다. +공공 행정 업무시스템의 지도 기반 업무 흐름 개선과 레거시 UI 현대화 사례를 정리한 저장소입니다. + +원본 운영 시스템을 공개하지 않고, 화면 구조, 사용자 흐름, 설계 판단, 리뷰 문서, 익명화된 코드 흐름만 남깁니다. 실제 테이블명, API명, 기관명, 업무 코드, 필지 식별자, 운영 데이터는 제거했습니다. + +## 기술 근거 + +| 영역 | 근거 | +| --- | --- | +| Java/JSP 레거시 개선 | JSP, jQuery, Java Controller/Service/Repository, SQL Mapper 제약 안에서 개선 구조를 문서화 | +| GIS 기반 업무 흐름 | OpenLayers 기반 필지 선택, 도면 확인, 경계조정 검증 흐름을 별도 사례로 정리 | +| 공공/행정 시스템 이해 | 권한, 감사 로그, 기존 공통 UI, 고정 업무 절차를 설계 제약으로 다룸 | +| 실사용자 중심 UX | Before/After 이미지와 리뷰 문서로 확인 비용, 입력 오류, 업무 흐름 단절을 설명 | +| 보안 의식 | 원본 식별자를 제거한 공개용 소스와 익명화 기준 문서 포함 | + +## 사례 목록 + +| Case | 주제 | 핵심 개선 | 자료 | +| --- | --- | --- | --- | +| 01 | 상담관리 및 지도 선택 흐름 | 상담 화면을 업무 맥락 중심으로 재정리하고 지도 기반 선택 흐름을 보강 | [cases/consult-management](cases/consult-management/README.md) | +| 02 | 경계조정 파일-필지 연계 검증 | 파일과 필지를 함께 등록하고 조정 횟수를 도면 위에서 확인 | [cases/boundary-adjustment](cases/boundary-adjustment/README.md) | + +## 기술 검토 포인트 + +| 영역 | 설명 | +| --- | --- | +| 업무 흐름 분석 | 현업 담당자가 실제로 확인해야 하는 정보와 오류 가능성이 높은 지점을 기준으로 화면 재배치 | +| 지도/GIS 연계 | 도면, 필지 목록, 등록 파일 상태를 연결해 시각적 검증 흐름 구성 | +| 레거시 호환 | 기존 JSP 화면, 공통 CSS, 테이블 UI, 권한 처리, 파일 저장 흐름을 유지하며 개선 | +| 계층 분리 | 화면, 컨트롤러, 서비스, 데이터 접근 계층의 책임을 공개용 코드로 분리해 설명 | +| 공개 보안 | 운영 테이블명, API 경로, 업무 코드, 필지번호를 익명화 | + +## 공개 기준 + +국가/공공 시스템 성격상 아래 항목은 공개 저장소에 남기지 않습니다. + +| 구분 | 공개 저장소 처리 방식 | +| --- | --- | +| 실제 테이블, 뷰, 스키마명 | `EXAMPLE_*` 또는 역할 중심 명칭으로 치환 | +| 실제 API 경로, 업무 코드 | `/example/...` 형태의 샘플 경로로 치환 | +| 실제 패키지명, 시스템 약어 | `gov.example` 계열 샘플 패키지로 치환 | +| 기관명, 사용자명, 필지 고유번호 | 샘플 데이터 또는 설명 문장으로 대체 | +| 내부 지도/공통 유틸 구현 | 호출 목적만 남기고 구현 세부는 제거 | + +자세한 기준은 [docs/security-redaction.md](docs/security-redaction.md)를 기준으로 관리합니다. + +## 저장소 구조 + +```text +. +|-- README.md +|-- README_KOR.md +|-- docs/ +| |-- README.md +| |-- review-framework.md +| `-- security-redaction.md +`-- cases/ + |-- consult-management/ + | |-- README.md + | |-- assets/ + | `-- source-sanitized/ + `-- boundary-adjustment/ + |-- README.md + |-- assets/ + `-- source-sanitized/ +``` -## 핵심 요약 +## 리뷰 방식 -- 대상: 레거시 행정 시스템의 상담관리 및 지도 기반 기능 -- 주요 사용자: 40대 ~ 60대 현업 담당자 -- 목적: 사용성 저항 최소화, 업무 효율화, 입력 오류 감소 -- 핵심 기법: 대화형 상담 UI, OpenLayers 지도 선택, 운영 리포트 자동화 +각 사례는 단순 화면 캡처가 아니라 아래 순서로 정리합니다. -## 이런 분에게 유용합니다 +1. 업무 문제와 사용자 리스크 +2. 변경이 금지되거나 제한된 시스템 조건 +3. 그 제약 안에서 선택한 UI/UX 판단 +4. 프론트엔드, 서버, 데이터 흐름의 역할 분리 +5. 공개 가능한 코드 구조와 비공개 처리 기준 +6. 앞으로 제약이 풀릴 때 개선할 수 있는 후속 과제 -- 오래된 JSP/Java 기반 행정 시스템을 점진적으로 개선해야 하는 분 -- 현업 사용자의 거부감을 낮추는 UI/UX 설계 사례가 필요한 분 -- Before/After 스크린샷과 함께 포트폴리오형 개선 사례를 정리하고 싶은 분 +이 기준은 [docs/review-framework.md](docs/review-framework.md)에 정리되어 있습니다. -## 주요 기능 +## 이미지 추가 규칙 -- 대화형 상담관리 UI: 간단한 문장 입력으로 업무 흐름 유도 -- 지도 기반 필지 선택: 시각적 선택으로 오류 감소 -- 운영 리포트 자동 생성: 반복 업무 자동화로 시간 절감 -- 성능 가이드: PL/SQL 튜닝 및 쿼리 최적화 예시 +각 사례의 `assets/` 폴더에 지정된 파일명으로 이미지를 추가하면 README의 갤러리에서 바로 확인할 수 있습니다. -## 빠른 시작 +경계조정 사례는 다음 파일명을 사용합니다. -1. Java 11+ 및 Maven을 설치합니다. -2. 프로젝트 루트에서 빌드합니다. +| 파일명 | 용도 | +| --- | --- | +| `01-boundary-overview.png` | 파일 등록, 도면, 선택 필지 목록이 함께 보이는 전체 화면 | +| `02-adjustment-legend.png` | 경계조정 횟수 색상 범례와 투명도 조정 | +| `03-linked-parcels.png` | 등록 파일 선택 후 연결 필지가 도면과 목록에 표시되는 상태 | +| `04-edit-mode.png` | 조회 상태에서 수정 모드로 전환해 필지 목록을 갱신하는 상태 | -```bash -mvn clean package -``` +## 현재 상태 -3. 샘플 DB/설정은 `resources/`의 샘플 파일을 확인하세요. - -## Before & After - - - - - - - - - - -
BeforeAfter
- Before 1
- 텍스트와 표 중심의 복잡 화면 -

- Before 2
- 중첩 폼과 긴 목록 -

- Before 3
- 지도 미연동 상태 -
- After 1
- 대화형 상담 + 핵심 정보 요약 -

- After 2
- 간결한 필터와 단축 액션 -

- After 3
- 지도 기반 직접 선택 -
- -## 디자인 원칙 - -- 기본 텍스트는 16~18px 이상으로 유지 -- 버튼과 컨트롤은 최소 44~48px 높이로 설계 -- 명확한 레이블과 단계적 흐름 제공 -- 텍스트와 배경 대비 확보 -- 오류 메시지는 원인과 다음 행동을 함께 안내 - -## 의견과 기여 - -- 버그나 실행 문제는 [Issues](https://github.com/yungi0816/gov-admin-uiux-example/issues)에 남겨주세요. -- 공공/레거시 UI 개선 아이디어나 화면 설계 피드백은 [Discussions](https://github.com/yungi0816/gov-admin-uiux-example/discussions)에 남겨주세요. -- 문서, 접근성, 스크린샷 설명 개선 PR은 환영합니다. +- 상담관리 사례: 기존 Before/After 이미지와 공개용 구조 정리 완료 +- 경계조정 사례: 리뷰 문서와 익명화 코드 구조 추가 완료 +- 변경 이력, 라이선스 문서 추가 +- 실제 업무 데이터, 운영 테이블명, 내부 API명은 포함하지 않음 diff --git a/cases/README.md b/cases/README.md new file mode 100644 index 0000000..4fdddbf --- /dev/null +++ b/cases/README.md @@ -0,0 +1,15 @@ +# Case Studies + +공개 가능한 UI/UX 개선 사례를 기능 테마 단위로 관리합니다. + +| Case | 문서 | 상태 | +| --- | --- | --- | +| 01. 상담관리 및 지도 선택 흐름 | [consult-management](consult-management/README.md) | 이미지 및 구조 정리 완료 | +| 02. 경계조정 파일-필지 연계 검증 | [boundary-adjustment](boundary-adjustment/README.md) | 리뷰 문서와 익명화 코드 추가, 스크린샷 추가 대기 | + +## 추가 규칙 + +- 새 기능은 `cases//README.md`를 먼저 작성합니다. +- 화면 이미지는 해당 사례의 `assets/` 폴더에 둡니다. +- 공개용 코드는 `source-sanitized/`에만 둡니다. +- 원본 업무 시스템 식별자는 사례 문서와 코드에 남기지 않습니다. diff --git a/cases/boundary-adjustment/README.md b/cases/boundary-adjustment/README.md new file mode 100644 index 0000000..5e40efd --- /dev/null +++ b/cases/boundary-adjustment/README.md @@ -0,0 +1,142 @@ +# Case 02. 경계조정 파일-필지 연계 검증 + +경계가 조정된 필지에 대해 파일과 필지를 함께 등록하고, 실제 필지별 조정 횟수를 도면 위에서 확인할 수 있게 만든 사례입니다. + +이 기능의 핵심은 화면을 새롭게 꾸미는 것이 아니라, 기존 공공 행정 시스템의 제약 안에서 사용자가 "이 파일이 어떤 필지와 연결되어 있는지", "해당 필지가 몇 번 조정되었는지", "도면상 위치가 맞는지"를 한 화면에서 검증할 수 있게 하는 것입니다. + +## 리뷰 요약 + +| 항목 | 내용 | +| --- | --- | +| 업무 문제 | 경계조정 파일과 실제 필지 연결 상태를 별도 목록과 도면을 오가며 확인해야 했음 | +| 사용자 리스크 | 잘못된 파일-필지 연결, 조정 이력 누락, 도면 확인 누락 가능성 | +| 시스템 제약 | 기존 JSP/jQuery 화면, 공통 테이블 UI, OpenLayers 지도 모듈, 권한/감사 로그, 기존 파일 저장 구조 유지 | +| 개선 방향 | 파일 등록, 필지 선택, 도면 하이라이트, 조정 횟수 시각화를 하나의 검증 흐름으로 연결 | +| 공개 방식 | 원본 식별자 제거 후 역할 중심 문서와 익명화 코드만 공개 | + +## 제약 조건 + +전체 시스템 UI를 마음대로 재설계할 수 없는 조건이었습니다. 공통 CSS와 기존 업무 화면 패턴을 유지해야 했고, 현업 사용자가 이미 익숙한 표 기반 입력 방식도 깨기 어려웠습니다. + +따라서 이 사례에서는 새로운 디자인 시스템을 도입하기보다 다음 판단을 우선했습니다. + +- 기존 등록 폼과 목록 구조는 유지하되, 지도와 선택 필지 목록을 같은 시야에 배치 +- 조회, 등록, 수정 상태를 명확하게 표시해 잘못된 저장을 방지 +- 파일을 선택하면 연결된 필지를 도면과 목록에 동시에 표시 +- 필지별 조정 횟수를 색상 단계로 표현해 검토 우선순위를 빠르게 판단 +- 투명도 조절을 제공해 기존 도면 판독을 방해하지 않도록 처리 + +## 사용자 흐름 + +```mermaid +flowchart TD + A["경계조정 파일 목록 조회"] --> B["도면에서 필지 확인"] + B --> C["필지 클릭 또는 목록 검색"] + C --> D["선택 필지 목록에 추가"] + D --> E["파일 업로드 및 설명 입력"] + E --> F["파일과 필지 연결 저장"] + A --> G["기존 파일 선택"] + G --> H["연결 필지 목록 조회"] + H --> I["도면에서 연결 필지 하이라이트"] + I --> J["필요 시 수정 모드로 전환"] +``` + +## 구현 구조 + +| 계층 | 책임 | +| --- | --- | +| JSP / JavaScript | 지도 초기화, 필지 선택/해제, 목록 렌더링, 등록/조회/수정 모드 관리 | +| Controller | 파일 업로드, 필지 목록 조회, 조정 횟수 조회, 저장/삭제 요청 진입점 | +| Service | 파일 저장과 필지 연결 저장의 트랜잭션 흐름, 입력값 정규화 | +| Repository / Mapper | 익명화된 파일 메타데이터, 파일-필지 연결, 도면 형상, 조정 횟수 조회 | +| Map Layer | 이전/확정 경계 도면을 읽어 색상, 라벨, 선택 상태로 표현 | + +## 데이터 흐름 + +```mermaid +sequenceDiagram + participant User as "User" + participant UI as "JSP + OpenLayers" + participant API as "Example Controller" + participant Service as "Boundary Service" + participant Store as "Example Data Store" + User->>UI: "파일과 필지 선택" + UI->>API: "등록 또는 수정 요청" + API->>Service: "입력 검증 및 저장 위임" + Service->>Store: "파일 메타데이터 저장" + Service->>Store: "파일-필지 연결 저장" + UI->>API: "조정 횟수 및 도면 조회" + API->>Store: "필지별 조정 횟수, 도면 형상 조회" + Store-->>UI: "익명화된 필지 속성, 형상, 조정 횟수" + UI-->>User: "색상 단계와 선택 하이라이트로 검증" +``` + +## 화면 검토 포인트 + +| 화면 요소 | 의도 | +| --- | --- | +| 등록/조회/수정 모드 배지 | 현재 작업 상태를 명확히 보여 저장 실수 방지 | +| 선택 필지 목록 | 도면에서 선택한 필지를 표로 재확인 | +| 도면 하이라이트 | 목록과 실제 경계 위치를 연결해 검토 | +| 조정 횟수 범례 | 조정이 반복된 필지를 우선 검토할 수 있게 지원 | +| 투명도 조절 | 색상 시각화가 기존 도면 판독을 가리지 않도록 보정 | +| 전체보기 지도 | 작은 업무 패널 안에서도 상세 위치를 확인할 수 있게 지원 | + +## 스크린샷 갤러리 + +이미지는 공개 전 주소, 필지번호, 사용자명, 내부망 URL이 보이지 않도록 마스킹한 뒤 아래 파일명으로 추가합니다. + + + + + + + + + + + + + + + + + + +
전체 화면조정 횟수 범례
+ Boundary adjustment overview
+ 파일 등록, 도면, 선택 필지 목록을 함께 확인 +
+ Adjustment count legend
+ 조정 횟수 색상 단계와 투명도 조절 +
연결 필지 확인수정 모드
+ Linked parcels
+ 등록 파일 선택 시 연결 필지를 목록과 도면에 표시 +
+ Boundary adjustment edit mode
+ 기존 파일의 연결 필지 목록을 수정 +
+ +## 공개용 소스 + +| 파일 | 설명 | +| --- | --- | +| [source-sanitized/java/BoundaryAdjustmentController.java](source-sanitized/java/BoundaryAdjustmentController.java) | 공개용 컨트롤러 구조 | +| [source-sanitized/java/BoundaryAdjustmentService.java](source-sanitized/java/BoundaryAdjustmentService.java) | 파일-필지 연결 저장 흐름 | +| [source-sanitized/java/BoundaryAdjustmentRepository.java](source-sanitized/java/BoundaryAdjustmentRepository.java) | 데이터 접근 책임 예시 | +| [source-sanitized/mapper/BoundaryAdjustmentMap.xml](source-sanitized/mapper/BoundaryAdjustmentMap.xml) | 익명화된 SQL 매퍼 예시 | +| [source-sanitized/web/boundary-adjustment.jsp](source-sanitized/web/boundary-adjustment.jsp) | 지도 선택과 모드 전환 중심의 JSP/JS 구조 | + +## 후속 개선 여지 + +현재 사례는 기존 시스템 제약 안에서 구현한 개선입니다. 제약이 완화된다면 다음 개선을 검토할 수 있습니다. + +- 지도, 파일 등록, 선택 필지 목록을 독립 컴포넌트로 분리 +- 등록/조회/수정 모드를 명시적인 상태 머신으로 관리 +- 필지 선택 이벤트와 저장 요청에 대한 프론트엔드 테스트 추가 +- 조정 횟수 색상 기준을 운영 설정으로 분리 +- 키보드 접근성과 스크린리더 레이블 보강 + +## 익명화 메모 + +이 문서와 공개용 소스는 실제 운영 테이블명, API명, 업무 코드, 패키지명, 필지 고유번호, 내부 지도 유틸명을 포함하지 않습니다. 공개 기준은 [../../docs/security-redaction.md](../../docs/security-redaction.md)를 따릅니다. diff --git a/cases/boundary-adjustment/assets/01-boundary-overview.png b/cases/boundary-adjustment/assets/01-boundary-overview.png new file mode 100644 index 0000000..2f0ca46 Binary files /dev/null and b/cases/boundary-adjustment/assets/01-boundary-overview.png differ diff --git a/cases/boundary-adjustment/assets/02-adjustment-legend.png b/cases/boundary-adjustment/assets/02-adjustment-legend.png new file mode 100644 index 0000000..3f5f6d9 Binary files /dev/null and b/cases/boundary-adjustment/assets/02-adjustment-legend.png differ diff --git a/cases/boundary-adjustment/assets/03-linked-parcels.png b/cases/boundary-adjustment/assets/03-linked-parcels.png new file mode 100644 index 0000000..dfec4c3 Binary files /dev/null and b/cases/boundary-adjustment/assets/03-linked-parcels.png differ diff --git a/cases/boundary-adjustment/assets/04-edit-mode.png b/cases/boundary-adjustment/assets/04-edit-mode.png new file mode 100644 index 0000000..37458ac Binary files /dev/null and b/cases/boundary-adjustment/assets/04-edit-mode.png differ diff --git a/cases/boundary-adjustment/assets/README.md b/cases/boundary-adjustment/assets/README.md new file mode 100644 index 0000000..6b14edf --- /dev/null +++ b/cases/boundary-adjustment/assets/README.md @@ -0,0 +1,17 @@ +# Boundary Adjustment Screenshots + +이미지를 추가할 때는 공개 전 다음 항목을 마스킹합니다. + +- 실제 주소, 필지번호, 좌표 +- 사용자명, 기관명, 내부망 URL +- 실제 파일명에 포함된 사업명 또는 기관명 +- 운영 시스템 메뉴 코드나 업무 코드 + +## Required Filenames + +| 파일명 | 설명 | +| --- | --- | +| `01-boundary-overview.png` | 파일 등록, 도면, 선택 필지 목록이 함께 보이는 전체 화면 | +| `02-adjustment-legend.png` | 조정 횟수 색상 범례와 투명도 조절 | +| `03-linked-parcels.png` | 등록 파일 선택 후 연결 필지가 도면과 목록에 표시되는 상태 | +| `04-edit-mode.png` | 수정 모드에서 연결 필지를 갱신하는 상태 | diff --git a/cases/boundary-adjustment/source-sanitized/README.md b/cases/boundary-adjustment/source-sanitized/README.md new file mode 100644 index 0000000..9d44fde --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/README.md @@ -0,0 +1,16 @@ +# Sanitized Source + +이 폴더의 코드는 경계조정 파일-필지 연계 기능의 구조를 설명하기 위한 공개용 예시입니다. + +| 폴더 | 내용 | +| --- | --- | +| `java/` | 컨트롤러, 서비스, 저장소 책임 분리 예시 | +| `mapper/` | 익명화된 iBatis 스타일 SQL 매퍼 예시 | +| `web/` | JSP, jQuery, OpenLayers 기반 화면 구조 예시 | + +## 주의 + +- 실제 운영 API 경로가 아닙니다. +- 실제 테이블, 뷰, 스키마명이 아닙니다. +- 실제 업무 코드값이 아닙니다. +- 실제 좌표계/지도 유틸 구현은 포함하지 않습니다. diff --git a/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentController.java b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentController.java new file mode 100644 index 0000000..012f81c --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentController.java @@ -0,0 +1,118 @@ +package gov.example.admin.boundary; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +/** + * Sanitized example controller. + * + * Production package names, API paths, work codes, authorization groups, and + * audit-log identifiers were replaced with public example names. + */ +@Controller +@RequestMapping("/example/boundary-adjustment") +public class BoundaryAdjustmentController { + + private final BoundaryAdjustmentService boundaryAdjustmentService; + + public BoundaryAdjustmentController(BoundaryAdjustmentService boundaryAdjustmentService) { + this.boundaryAdjustmentService = boundaryAdjustmentService; + } + + @RequestMapping(value = "/init", method = RequestMethod.GET) + public String init(Model model, @RequestParam Map params) { + model.addAttribute("params", params); + return "cases/boundary-adjustment"; + } + + @RequestMapping(value = "/files", method = RequestMethod.GET) + public String listFiles(Model model, @RequestParam Map params) { + model.addAttribute("stageAFileList", boundaryAdjustmentService.findFiles(params, "STAGE_A")); + model.addAttribute("stageBFileList", boundaryAdjustmentService.findFiles(params, "STAGE_B")); + return "jsonView"; + } + + @RequestMapping(value = "/file-parcels", method = RequestMethod.GET) + public String listFileParcels(Model model, @RequestParam Map params) { + model.addAttribute("list", boundaryAdjustmentService.findLinkedParcels(params)); + return "jsonView"; + } + + @RequestMapping(value = "/parcels/search", method = RequestMethod.GET) + public String searchParcels(Model model, @RequestParam Map params) { + model.addAttribute("list", boundaryAdjustmentService.searchParcels(params)); + return "jsonView"; + } + + @RequestMapping(value = "/map/boundaries", method = RequestMethod.GET) + public String listBoundaryGeometry(Model model, @RequestParam Map params) { + model.addAttribute("boundaryList", boundaryAdjustmentService.findBoundaryGeometry(params)); + return "jsonView"; + } + + @RequestMapping(value = "/adjustment-counts", method = RequestMethod.GET) + public String listAdjustmentCounts(Model model, @RequestParam Map params) { + model.addAttribute("list", boundaryAdjustmentService.findAdjustmentCounts(params)); + return "jsonView"; + } + + @RequestMapping(value = "/files", method = RequestMethod.POST) + public String registerFile( + Model model, + @RequestParam Map params, + @RequestParam("file") MultipartFile file) { + + if (isBlank(params.get("projectId")) || file == null || file.isEmpty()) { + model.addAttribute("errorMessage", "Invalid request."); + return "jsonView"; + } + + boundaryAdjustmentService.registerFileWithParcels(file, params); + model.addAttribute("successMessage", "Saved."); + model.addAttribute("fileList", boundaryAdjustmentService.findFiles(params, null)); + return "jsonView"; + } + + @RequestMapping(value = "/file-parcels", method = RequestMethod.PUT) + public String updateFileParcels(Model model, @RequestParam Map params) { + if (isBlank(params.get("fileMapId")) || isBlank(params.get("projectId"))) { + model.addAttribute("errorMessage", "Invalid request."); + return "jsonView"; + } + + boundaryAdjustmentService.replaceLinkedParcels(params); + model.addAttribute("successMessage", "Updated."); + return "jsonView"; + } + + @RequestMapping(value = "/files", method = RequestMethod.DELETE) + public String deleteFile(Model model, @RequestParam Map params) { + if (isBlank(params.get("fileMapId"))) { + model.addAttribute("errorMessage", "Invalid request."); + return "jsonView"; + } + + boundaryAdjustmentService.deleteFile(params); + model.addAttribute("successMessage", "Deleted."); + return "jsonView"; + } + + private boolean isBlank(Object value) { + return value == null || String.valueOf(value).trim().isEmpty(); + } + + @SuppressWarnings("unused") + private Map auditContext(String action) { + Map audit = new HashMap(); + audit.put("action", action); + audit.put("workCode", "REDACTED"); + return audit; + } +} diff --git a/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentRepository.java b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentRepository.java new file mode 100644 index 0000000..2a77ae6 --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentRepository.java @@ -0,0 +1,41 @@ +package gov.example.admin.boundary; + +import java.util.List; +import java.util.Map; + +import org.springframework.web.multipart.MultipartFile; + +/** + * Data-access boundary for the public example. + * + * Method names describe responsibilities. Mapper namespaces, schema owners, + * and production table/view names are intentionally omitted. + */ +public interface BoundaryAdjustmentRepository { + + List> selectFileList(Map params); + + List> selectLinkedParcelList(Map params); + + List> selectSearchParcelList(Map params); + + List> selectBoundaryGeometry(Map params); + + List> selectAdjustmentCountList(Map params); + + Object insertFileMetadata(MultipartFile file, Map params); + + Object insertBoundaryFileRecord(Map params); + + void insertFileMapping(Map params); + + void insertParcelLink(Map params); + + void deleteParcelLinks(Map params); + + void deleteFileRecord(Map params); + + void deleteFileMapping(Map params); + + void deleteStoredFile(Map params); +} diff --git a/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentService.java b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentService.java new file mode 100644 index 0000000..200c911 --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/java/BoundaryAdjustmentService.java @@ -0,0 +1,119 @@ +package gov.example.admin.boundary; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.web.multipart.MultipartFile; + +/** + * Sanitized service example for the boundary-adjustment review case. + * + * The original implementation had to stay compatible with an existing + * map-based parameter style. This example keeps that constraint visible while + * isolating the normalization and file-parcel linking responsibilities. + */ +public class BoundaryAdjustmentService { + + private final BoundaryAdjustmentRepository repository; + + public BoundaryAdjustmentService(BoundaryAdjustmentRepository repository) { + this.repository = repository; + } + + public List> findFiles(Map params, String stageCode) { + params.put("stageCode", stageCode); + return repository.selectFileList(params); + } + + public List> findLinkedParcels(Map params) { + return repository.selectLinkedParcelList(params); + } + + public List> searchParcels(Map params) { + return repository.selectSearchParcelList(params); + } + + public List> findBoundaryGeometry(Map params) { + return repository.selectBoundaryGeometry(params); + } + + public List> findAdjustmentCounts(Map params) { + return repository.selectAdjustmentCountList(params); + } + + public void registerFileWithParcels(MultipartFile file, Map params) { + validateAllowedExtension(file.getOriginalFilename()); + + Object storedFileId = repository.insertFileMetadata(file, params); + params.put("storedFileId", storedFileId); + + Object fileMapId = repository.insertBoundaryFileRecord(params); + params.put("fileMapId", fileMapId); + + repository.insertFileMapping(params); + insertParcelLinks(params, normalizeParcelIds(params.get("parcelIdList"))); + } + + public void replaceLinkedParcels(Map params) { + repository.deleteParcelLinks(params); + insertParcelLinks(params, normalizeParcelIds(params.get("parcelIdList"))); + } + + public void deleteFile(Map params) { + repository.deleteParcelLinks(params); + repository.deleteFileRecord(params); + repository.deleteFileMapping(params); + repository.deleteStoredFile(params); + } + + private void insertParcelLinks(Map params, List parcelIds) { + for (String parcelId : parcelIds) { + params.put("parcelId", parcelId); + repository.insertParcelLink(params); + } + } + + private List normalizeParcelIds(Object rawValue) { + if (rawValue == null) { + return Collections.emptyList(); + } + + List parcelIds = new ArrayList(); + + if (rawValue instanceof String[]) { + for (String parcelId : (String[]) rawValue) { + addIfPresent(parcelIds, parcelId); + } + } else if (rawValue instanceof Iterable) { + for (Object parcelId : (Iterable) rawValue) { + addIfPresent(parcelIds, String.valueOf(parcelId)); + } + } else { + String value = String.valueOf(rawValue); + for (String parcelId : value.split(",")) { + addIfPresent(parcelIds, parcelId); + } + } + + return parcelIds; + } + + private void addIfPresent(List parcelIds, String parcelId) { + if (parcelId != null && !parcelId.trim().isEmpty()) { + parcelIds.add(parcelId.trim()); + } + } + + private void validateAllowedExtension(String fileName) { + if (fileName == null) { + throw new IllegalArgumentException("File name is required."); + } + + String lowerName = fileName.toLowerCase(); + if (!lowerName.endsWith(".sdb") && !lowerName.endsWith(".dat")) { + throw new IllegalArgumentException("Only SDB and DAT files are allowed."); + } + } +} diff --git a/cases/boundary-adjustment/source-sanitized/mapper/BoundaryAdjustmentMap.xml b/cases/boundary-adjustment/source-sanitized/mapper/BoundaryAdjustmentMap.xml new file mode 100644 index 0000000..62e41b4 --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/mapper/BoundaryAdjustmentMap.xml @@ -0,0 +1,115 @@ + + + + + + + + INSERT INTO EXAMPLE_FILE_PARCEL_LINK ( + FILE_MAP_ID, + PARCEL_ID, + PROJECT_ID, + REGISTERED_AT, + REGISTERED_BY + ) VALUES ( + #fileMapId#, + #parcelId#, + #projectId#, + CURRENT_TIMESTAMP, + #userId# + ) + + + + DELETE FROM EXAMPLE_FILE_PARCEL_LINK + WHERE FILE_MAP_ID = #fileMapId# + + + + + + + + + + + diff --git a/cases/boundary-adjustment/source-sanitized/web/boundary-adjustment.jsp b/cases/boundary-adjustment/source-sanitized/web/boundary-adjustment.jsp new file mode 100644 index 0000000..25e9521 --- /dev/null +++ b/cases/boundary-adjustment/source-sanitized/web/boundary-adjustment.jsp @@ -0,0 +1,270 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + + + +
+ + + +
+
+ 등록 모드 + +
+ 경계조정 횟수 +
5회 이상
+
4회
+
3회
+
2회
+
1회
+ +
+
+ + + + + + + + + + + + + +
선택된 필지 목록
소재지지번지목면적관리
+ + + +
diff --git a/cases/consult-management/README.md b/cases/consult-management/README.md new file mode 100644 index 0000000..4857d48 --- /dev/null +++ b/cases/consult-management/README.md @@ -0,0 +1,54 @@ +# Case 01. 상담관리 및 지도 선택 흐름 개선 + +레거시 행정 시스템의 상담관리 화면과 지도 기반 필지 선택 흐름을 정리한 사례입니다. 기존 사용자의 업무 습관을 크게 흔들지 않으면서 상담 내용 확인, 핵심 정보 접근, 지도 선택 흐름을 더 명확하게 만드는 데 초점을 두었습니다. + +## 리뷰 요약 + +| 항목 | 내용 | +| --- | --- | +| 문제 | 표와 중첩 폼 중심 화면에서 상담 흐름과 지도 선택 맥락이 분리됨 | +| 제약 | JSP/Java 기반 화면, 기존 공통 CSS, 현업 사용자의 익숙한 조작 방식 유지 필요 | +| 개선 | 상담 핵심 정보를 더 빨리 파악하고 지도 선택 흐름으로 자연스럽게 이어지도록 정리 | +| 공개 범위 | 스크린샷과 익명화된 소스 구조만 포함 | + +## Before & After + + + + + + + + + + +
BeforeAfter
+ Before 1
+ 텍스트와 표 중심의 복잡 화면 +

+ Before 2
+ 중첩 폼과 긴 목록 +

+ Before 3
+ 지도 흐름이 업무 화면과 분리된 상태 +
+ After 1
+ 상담 맥락과 핵심 정보 요약 +

+ After 2
+ 간결한 필터와 단축 액션 +

+ After 3
+ 지도 기반 직접 선택 +
+ +## 설계 판단 + +- 기존 테이블형 화면의 인지 구조를 완전히 버리지 않고, 사용자가 이미 알고 있는 조작 위치를 유지했습니다. +- 지도 선택 기능은 별도 도구처럼 보이지 않도록 상담 흐름과 연결했습니다. +- 폼 입력 오류를 줄이기 위해 사용자가 직접 좌표나 식별자를 입력하는 상황을 최소화했습니다. +- 화면의 미적 변화보다 업무 중 확인해야 하는 정보의 우선순위를 재정렬했습니다. + +## 공개용 소스 + +`source-sanitized/`는 원본 시스템 코드가 아니라 구조 설명용 파일입니다. 실제 테이블명, API명, 패키지명, 업무 코드는 제거되어 있습니다. diff --git a/images/after_1.png b/cases/consult-management/assets/after_1.png similarity index 100% rename from images/after_1.png rename to cases/consult-management/assets/after_1.png diff --git a/images/after_2.png b/cases/consult-management/assets/after_2.png similarity index 100% rename from images/after_2.png rename to cases/consult-management/assets/after_2.png diff --git a/images/after_3.png b/cases/consult-management/assets/after_3.png similarity index 100% rename from images/after_3.png rename to cases/consult-management/assets/after_3.png diff --git a/images/before_1.png b/cases/consult-management/assets/before_1.png similarity index 100% rename from images/before_1.png rename to cases/consult-management/assets/before_1.png diff --git a/images/before_2.png b/cases/consult-management/assets/before_2.png similarity index 100% rename from images/before_2.png rename to cases/consult-management/assets/before_2.png diff --git a/images/before_3.png b/cases/consult-management/assets/before_3.png similarity index 100% rename from images/before_3.png rename to cases/consult-management/assets/before_3.png diff --git a/cases/consult-management/source-sanitized/README.md b/cases/consult-management/source-sanitized/README.md new file mode 100644 index 0000000..9f2c11c --- /dev/null +++ b/cases/consult-management/source-sanitized/README.md @@ -0,0 +1,5 @@ +# Sanitized Source + +상담관리 사례의 공개용 코드 구조입니다. 기존 저장소에 있던 예시 파일을 사례 폴더 아래로 이동해 이후 기능과 같은 규칙으로 관리합니다. + +이 폴더의 파일은 원본 업무 시스템의 전체 구현이 아니라 공개 가능한 구조 참고용입니다. diff --git a/pom.xml b/cases/consult-management/source-sanitized/pom.xml similarity index 100% rename from pom.xml rename to cases/consult-management/source-sanitized/pom.xml diff --git a/src/main/java/pplis/biz/dao/ConsultDao.java b/cases/consult-management/source-sanitized/src/main/java/gov/example/biz/dao/ConsultDao.java similarity index 100% rename from src/main/java/pplis/biz/dao/ConsultDao.java rename to cases/consult-management/source-sanitized/src/main/java/gov/example/biz/dao/ConsultDao.java diff --git a/src/main/java/pplis/biz/service/ConsultService.java b/cases/consult-management/source-sanitized/src/main/java/gov/example/biz/service/ConsultService.java similarity index 100% rename from src/main/java/pplis/biz/service/ConsultService.java rename to cases/consult-management/source-sanitized/src/main/java/gov/example/biz/service/ConsultService.java diff --git a/src/main/java/pplis/biz/service/impl/ConsultServiceImpl.java b/cases/consult-management/source-sanitized/src/main/java/gov/example/biz/service/impl/ConsultServiceImpl.java similarity index 100% rename from src/main/java/pplis/biz/service/impl/ConsultServiceImpl.java rename to cases/consult-management/source-sanitized/src/main/java/gov/example/biz/service/impl/ConsultServiceImpl.java diff --git a/src/main/java/pplis/biz/web/ConsultController.java b/cases/consult-management/source-sanitized/src/main/java/gov/example/biz/web/ConsultController.java similarity index 100% rename from src/main/java/pplis/biz/web/ConsultController.java rename to cases/consult-management/source-sanitized/src/main/java/gov/example/biz/web/ConsultController.java diff --git a/src/main/resources/pplis/sqlmap/ConsultMap.xml b/cases/consult-management/source-sanitized/src/main/resources/gov/example/sqlmap/ConsultMap.xml similarity index 100% rename from src/main/resources/pplis/sqlmap/ConsultMap.xml rename to cases/consult-management/source-sanitized/src/main/resources/gov/example/sqlmap/ConsultMap.xml diff --git a/src/main/webapp/WEB-INF/jsp/gisMap/viewLxMapPop.jsp b/cases/consult-management/source-sanitized/src/main/webapp/WEB-INF/jsp/map/mapSelectionPopup.jsp similarity index 100% rename from src/main/webapp/WEB-INF/jsp/gisMap/viewLxMapPop.jsp rename to cases/consult-management/source-sanitized/src/main/webapp/WEB-INF/jsp/map/mapSelectionPopup.jsp diff --git a/src/main/webapp/css/consult.css b/cases/consult-management/source-sanitized/src/main/webapp/css/consult.css similarity index 100% rename from src/main/webapp/css/consult.css rename to cases/consult-management/source-sanitized/src/main/webapp/css/consult.css diff --git a/src/main/webapp/js/calendar/consult.js b/cases/consult-management/source-sanitized/src/main/webapp/js/calendar/consult.js similarity index 100% rename from src/main/webapp/js/calendar/consult.js rename to cases/consult-management/source-sanitized/src/main/webapp/js/calendar/consult.js diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..b356fa7 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,15 @@ +# Documentation + +이 폴더는 공개 가능한 범위에서 사례를 설명하기 위한 기준 문서입니다. + +| 문서 | 역할 | +| --- | --- | +| [review-framework.md](review-framework.md) | 기능 사례를 전문가 리뷰 형식으로 정리하는 공통 구조 | +| [security-redaction.md](security-redaction.md) | 공공 시스템 정보를 공개 저장소에 남기지 않기 위한 익명화 기준 | + +## 작성 원칙 + +- README는 사례 탐색과 요약에 집중합니다. +- 상세한 판단 근거는 각 `cases/*/README.md`에 둡니다. +- 원본 업무 시스템의 실제 식별자는 공개 문서에 쓰지 않습니다. +- 구현 코드는 재사용 가능한 제품 코드가 아니라 리뷰를 위한 익명화 예시로 관리합니다. diff --git a/docs/review-framework.md b/docs/review-framework.md new file mode 100644 index 0000000..267106b --- /dev/null +++ b/docs/review-framework.md @@ -0,0 +1,39 @@ +# 전문가 리뷰 작성 프레임워크 + +각 사례는 단순히 "화면을 바꿨다"가 아니라 어떤 제약 안에서 어떤 판단을 했는지 설명해야 합니다. 특히 공공 행정 시스템은 화면 일관성, 권한, 감사 로그, 기존 사용자 숙련도, 배포 리스크 때문에 자유로운 리디자인이 어려운 경우가 많습니다. + +## 권장 구조 + +| 섹션 | 작성 목적 | +| --- | --- | +| 문제 정의 | 사용자가 실제로 겪는 혼선, 오류 가능성, 확인 비용을 설명 | +| 운영 제약 | 변경 불가한 UI 규칙, 기술 스택, 권한/로그, 데이터 구조를 명시 | +| 개선 방향 | 제약 안에서 선택한 화면 배치, 상태 표시, 확인 흐름을 설명 | +| 구현 구조 | 프론트엔드, 컨트롤러, 서비스, 데이터 접근 계층의 책임을 분리 | +| 검증 관점 | 사용자가 무엇을 더 명확히 확인할 수 있게 되었는지 정리 | +| 보안 처리 | 공개 저장소에서 제거하거나 치환한 내부 식별자를 명시 | +| 후속 개선 | 제약이 완화될 때 개선 가능한 항목을 현재 구현과 분리 | + +## 리뷰 톤 + +좋은 리뷰 문서는 과장하지 않습니다. "최신 UI로 바꿨다"보다 "기존 공통 컴포넌트를 유지하면서 사용자가 필지와 파일의 연결 상태를 한 화면에서 검증할 수 있게 했다"처럼 검증 가능한 문장으로 씁니다. + +## 제약을 설명하는 방식 + +제약은 변명이 아니라 설계 조건입니다. 다음처럼 표현합니다. + +| 피해야 할 표현 | 권장 표현 | +| --- | --- | +| 전체 시스템 때문에 원하는 대로 못 바꿨다 | 공통 JSP/CSS와 기존 업무 화면 규칙을 유지해야 했기 때문에 화면 체계를 벗어나지 않는 범위에서 개선했다 | +| 예쁜 UI를 만들 수 없었다 | 미관보다 현업 사용자의 확인 정확도, 기존 학습 비용, 운영 리스크를 우선했다 | +| 임시로 붙였다 | 기존 지도 모듈과 등록 폼 사이에 상태 동기화 계층을 추가했다 | + +## 코드 공개 기준 + +공개 코드는 원본을 그대로 옮기지 않습니다. 구현 판단을 설명할 수 있을 만큼의 구조만 남깁니다. + +- 실제 API 경로 대신 역할 중심 샘플 경로 사용 +- 실제 테이블/스키마 대신 `EXAMPLE_*` 명칭 사용 +- 업무 코드값은 `STAGE_A`, `STAGE_B`처럼 의미 중심으로 치환 +- 감사 로그, 권한 체크, 공통 유틸은 목적만 설명 +- 실데이터, 사용자명, 필지번호, 좌표는 포함하지 않음 diff --git a/docs/security-redaction.md b/docs/security-redaction.md new file mode 100644 index 0000000..ecd90ac --- /dev/null +++ b/docs/security-redaction.md @@ -0,0 +1,35 @@ +# 보안 및 익명화 기준 + +이 저장소는 공공 행정 시스템 개선 사례를 설명하기 위한 공개 자료입니다. 따라서 실제 운영 환경을 식별할 수 있는 이름, 경로, 코드, 데이터는 남기지 않습니다. + +## 비공개 처리 항목 + +| 항목 | 처리 방식 | +| --- | --- | +| 실제 테이블, 뷰, 스키마명 | `EXAMPLE_FILE`, `EXAMPLE_FILE_PARCEL_LINK`, `EXAMPLE_GIS_BOUNDARY_VIEW`처럼 역할 중심 명칭으로 치환 | +| 실제 API 경로 | `/example/boundary-adjustment/...` 같은 샘플 경로로 치환 | +| 실제 업무 코드 | `STAGE_A`, `STAGE_B`, `DOC_TYPE_BOUNDARY` 등 의미 중심 값으로 치환 | +| 실제 패키지명 | `gov.example.admin.*` 형태로 치환 | +| 실제 사용자, 권한 그룹, 감사 코드 | 권한/감사 처리 목적만 설명 | +| 실제 필지 고유번호, 주소, 좌표 | 샘플 값 또는 설명 문장으로 대체 | +| 내부 지도/공통 유틸 | 호출 목적만 남기고 내부 구현은 제외 | + +## 공개 가능한 항목 + +- 사용자가 수행하는 업무 단계 +- UI 상태 전환 방식 +- 지도와 목록이 동기화되는 구조 +- 파일 등록과 필지 연결의 책임 분리 +- 조정 횟수 시각화 같은 UX 판단 +- 익명화된 레이어 구조와 데이터 흐름 + +## 검토 체크리스트 + +공개 전 다음 항목을 확인합니다. + +- 실제 스키마명, 테이블명, 뷰명이 남아 있지 않은가 +- 실제 API 경로나 컨트롤러 매핑이 남아 있지 않은가 +- 업무 코드값이 내부 시스템을 추정할 수 있을 만큼 구체적이지 않은가 +- 이미지에 기관명, 사용자명, 주소, 필지번호, 좌표, 내부망 URL이 보이지 않는가 +- 로그 코드, 권한 그룹 코드, 파일 저장소 구조가 그대로 노출되지 않았는가 +- 코드가 운영 시스템에 바로 연결될 수 있는 수준의 접속 정보나 쿼리를 포함하지 않는가