배포 마커
이슈 보드 활성화
문서 마지막 갱신
2026. 6. 10. AM 10:33 KST
문서 수
22건
정적 문서
5건
📝 이슈 등록 / QA 접수 → 🗒 갱신 이력 보기

📈 진행 상황 5

📈 진행 상황 2026-06-10 PM 전달 UI 원본 반영 PM이 전달한 파일 2개를 기존 repo 반영본과 대조했다.
마지막 갱신 2026. 6. 10. AM 10:33 KST · docs/01_요구사항/20260610_PM_전달_UI_반영.md

2026-06-10 PM 전달 UI 원본 반영

PM이 전달한 파일 2개를 기존 repo 반영본과 대조했다.

파일 판정

파일판정
/Users/sammy/Downloads/개발_요청_문서.pdf기존 docs/01_요구사항/20260605/개발_요청_문서.pdf와 동일 hash. 추가 요구 없음.
/Users/sammy/Downloads/화면 구성 UI.xlsxxs해당 경로 없음. 확장자 오타로 판단.
/Users/sammy/Downloads/화면 구성 UI.xlsxPM 최신 UI 원본. 기존 repo UI 6-sheet와 다른 20-sheet 확장본.
/Users/sammy/Downloads/화면 구성 UI (1).xlsx위 파일과 동일 duplicate.

PM 최신 UI에서 추가/강화된 영역

ID영역영향
PM-01원콜 상세/세발입금 상태, 증빙 유형, 공급가액, 부가세, 입금액이 상세에 명시됨
PM-02본사 관리정기계약 상단 tab으로 별도 화면/용어 정합 필요
PM-03콘솔 관리콘솔번호 자동 생성, 계약 매칭, 매칭 시 QR 생성 필요
PM-04협력사 상세사업자등록증 업로드, 담당자 관리, 초기 비밀번호, 복구/soft delete 필요
PM-05세발 관리입금/증빙/처리상태 필터와 엑셀 다운로드 요구
PM-06파쇄증명서ZIP 다운로드, 발급 처리, 사진 업로드, 재생성/다운로드 요구
PM-07일일업무관리관리자 운영 일보. 현재 작업자 DailyWorkPage와 별도 도메인
PM-08차량 관리차량호수/차량번호/소속업체 UI/API 필요
PM-09사용자 관리통계, 권한, 최종 접속, 비밀번호 초기화, 탈퇴 confirm 필요
상세 원문 반영 문서: docs/01_요구사항/20260610_PM_전달_UI_반영.md
📈 진행 상황 irosafe_shred 진행상황 (2026-06-10 PM UI 반영) 기준: 2026-06-10 KST. PM 전달 UI 20-sheet 원본과 gap 재매칭 결과를 반영한 MiniQA용 요약이다.
마지막 갱신 2026. 6. 10. AM 10:33 KST · ops/dashboard/_data.js

irosafe_shred 진행상황

기준: 2026-06-10 KST. PM 전달 UI 20-sheet 원본과 gap 재매칭 결과를 반영한 MiniQA용 요약이다.

Phase 진행률

  • Phase 0 분석/설계 — 완료 100%
  • Phase A 설계 재정의 — 완료 100%
  • Phase B 신규 스택 골격 — 완료 100%
  • Phase C 핵심 도메인 신규 구축 — 완료 100%
  • Phase D 자동화/인프라 — 완료 100%
  • Phase E 데이터 마이그 — 진행 90% dry-run 성공, apply 결정 대기
  • Phase F 안드로이드 — 보류 0% 백엔드 안정화 후
  • Phase G QA/릴리즈 — 진행 75% Swagger 32 path, 테스트 evidence 재고정 필요

현재 핵심 판정

구현 골격 진행률과 PM 최신 UI 요구 충족률은 분리해서 본다. A~D는 신규 구축 골격 기준 완료지만, 2026-06-10 PM UI 최신본 기준으로는 사용자 관리, 원콜 세발/입금, 콘솔 매칭 UX, 협력사 담당자/첨부, 파쇄증명서 파일 workflow, 일일업무관리 상세, 차량 관리가 gap으로 남아 있다.

최신 확인

  • PDF /Users/sammy/Downloads/개발_요청_문서.pdf는 기존 repo PDF와 동일 hash. 새 요구 추가 없음.
  • UI /Users/sammy/Downloads/화면 구성 UI.xlsx는 기존 repo 6-sheet 반영본이 아니라 20-sheet 확장본.
  • docs/09_테스트/06_갭분석.md의 기존 "누락 0건" 결론은 폐기.
  • 최신 기준 문서: docs/09_테스트/07_재매칭_codex.md, docs/01_요구사항/20260610_PM_전달_UI_반영.md.

회의용 UI 스토리보드

검증: 관리자 전체본 21 screens, 모바일 전체본 13 phone screens Playwright 렌더 확인 완료. Figma 전체본 이관은 Figma MCP Starter plan rate limit 해제 후 가능.

우선순위

1. User management UI: 목록/상세/권한/비밀번호 초기화/탈퇴.
2. Calendar routing + bulk/reassign UI: 수용 테스트 직접 항목.
3. 원콜 세발/입금 최소 모델: ERP 연동은 out이어도 SOP 내부 기록 필요.
4. 콘솔 매칭 UX: 콘솔번호 생성, 계약 검색/매칭, QR 생성 타이밍.
5. 일일업무관리 상세: 관리자 운영 일보로 별도 7월 scope 격리 권고.

메타

  • source hash: 60a88b4dfb5a954eaf3db875bf4e7734
  • source: ops/dashboard/_data.js, docs/09_테스트/06_갭분석.md, docs/09_테스트/07_재매칭_codex.md, docs/01_요구사항/20260610_PM_전달_UI_반영.md, docs/10_UI_스토리보드/*
📈 진행 상황 갭분석 재판정: 누락 0건 결론 폐기 docs/09테스트/06갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09테스트/07재매칭…
마지막 갱신 2026. 6. 10. AM 9:34 KST · docs/09_테스트/07_재매칭_codex.md

갭분석 재판정

docs/09_테스트/06_갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09_테스트/07_재매칭_codex.md를 우선한다.

재판정 요약

구분판단
기존 06 갭분석구현 골격 기준으로 과대 충족 판정이 섞임
재매칭 결과신규 누락 7건, 부분/과대 6건, 정책충돌/확인 필요 4건
PM 최신 UI 반영기존 6-sheet가 아니라 20-sheet 확장본이므로 gap 추가 발생

우선 보강 대상

영역현재 판정조치
사용자 관리P0 미완/admin placeholder 제거, member list/role/status/password reset 구현
Calendar routingP0 미완bar/date click에서 schedule list filter로 이동
Bulk/reassign UIP0 부분backend mutation을 UI에 연결, 완료 일정 변경 금지 처리
원콜 세발/입금P0 후보payment/deposit/evidence 최소 모델 반영
Recurring date-confirmP0 부분25일 배치 placeholder와 날짜 확정 workflow 분리
콘솔 매칭 UXP0/P1콘솔번호 규칙, 계약 검색/매칭, QR 생성 타이밍 확정
일일업무관리 상세7월 권고현재 DailyWorkPage와 다른 관리자 운영 일보 도메인으로 분리

근거 문서

  • docs/09_테스트/07_재매칭_codex.md
  • docs/01_요구사항/20260610_PM_전달_UI_반영.md
  • docs/09_테스트/06_갭분석.md v1.1 상단 superseded 경고
📈 진행 상황 06_갭분석 문서 상태: 최신 기준으로 폐기 docs/09테스트/06갭분석.md의 기존 "누락 0건" 결론은 최신 기준으로 폐기한다. 이 카드는 같은 sourcePath를 다시 sync해서 MiniQA에 남…
마지막 갱신 2026. 6. 10. AM 9:33 KST · docs/09_테스트/06_갭분석.md

06_갭분석 문서 상태

docs/09_테스트/06_갭분석.md의 기존 "누락 0건" 결론은 최신 기준으로 폐기한다. 이 카드는 같은 sourcePath를 다시 sync해서 MiniQA에 남아 있던 구 결론 카드가 최신 경고로 보이게 하기 위한 것이다.

현재 사용 기준

항목판정
기존 "누락 0건"사용 금지
최신 gap 기준docs/09_테스트/07_재매칭_codex.md
PM UI 원본 기준docs/01_요구사항/20260610_PM_전달_UI_반영.md

폐기 사유

2026-06-10 확인한 PM 전달 UI 원본은 기존 repo에 반영된 6-sheet 파일이 아니라 20-sheet 확장본이다. 따라서 기존 gap 분석은 구현 골격 기준으로 과대 충족 판정이 섞였고, PM 최신 UI의 사용자 관리, 원콜 세발/입금, 콘솔 매칭 UX, 협력사 담당자/첨부, 파쇄증명서 파일 workflow, 일일업무관리 상세, 차량 관리 요구를 충분히 반영하지 못했다.

다음 판단

6/30 MVP 전 우선 보강 대상은 Calendar routing, bulk/reassign UI, 사용자 관리 UI, recurring date-confirm workflow, 원콜 세발/입금 최소 모델, 콘솔 매칭 UX다.

📈 진행 상황 마일스톤 v5 — 현재 상태 신규 구축 진행 상황 — Phase A~D 완료, E 90% (dry-run 성공), G 75% (테스트 141 PASS). MVP 2026-06-30.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/07_진행/00_마일스톤.md

신규 구축 진행 상황 — Phase A~D 완료, E 90% (dry-run 성공), G 75% (테스트 141 PASS). MVP 2026-06-30.

1. 한눈에

Phase상태진행핵심
0 분석/설계완료100%baseline (유지)
A 설계 재정의완료100%ERD v0.5.1 · RBAC · 와이어프레임 W01~W08 React 변환
B 신규 스택완료100%SB 3.3.5 · Java 21 · Flyway V1~V8 · Security 6 · JWT · SpringDoc
C 핵심 도메인완료100%RBAC · 계약(트랙 이원화) · 캘린더 · 협력사 · 콘솔/QR · 증명서 · 일일업무 · 코드마스터
D 자동화완료100%정기 25일 배치 · Excel ↑↓ · QR · 담당자 변경 · 주소검색 · ContractExpiryJob
E 데이터 마이그진행90%dry-run 성공 (협력사 10/12, 계약 2849/2849, 지점 6867/6927). apply 결정 대기.
F 안드로이드보류0%백엔드 안정화 후
G QA/릴리즈진행75%Swagger 32 path · 테스트 141 PASS · G3 시연 대기

2. 산출물

  • 백엔드 — Spring Boot 3.3.5 + Java 21 + Flyway V1~V8 (GitLab shred-backend)
  • 프론트 — React 18 + Vite 5 + Tailwind 3 (GitLab shred-frontend)
  • 데이터베이스 — MariaDB 10.11 (irosafe_shred schema)
  • 외부 dev 라이브 — https://dev-shred.irosafe.com
  • API 문서 — /swagger-ui/index.html · 32 path
  • 문서 허브 — /docs/ (docsify)

3. 변경 이력

  • 2026-06-08: Phase E dry-run 성공 · 운영 컬럼 정정 push · 문서 슬림 정리
  • 2026-06-07: 외부 dev-shred.irosafe.com 배포 + Cloudflare Tunnel
  • 2026-06-06: Phase C8/D6 완료 · 단위테스트 71 + e2e 35 PASS · 결과서 xlsx/pptx 산출
  • 2026-06-05: v5 인풋 반영 — 마이그 → 신규 구축 (Architecture Overhaul) 으로 큰 그림 재설정
📜 이전 버전 2건
  1. 버전 2 · 마일스톤 v5 — 현재 상태 · 2026. 6. 8. PM 2:12 KST
  2. 버전 1 · 마일스톤 v5 — 현재 상태 (2026-06-08) · 2026. 6. 8. PM 1:30 KST

📘 안내 9

📘 안내 화면 명세 v1.1 - PM 20-sheet + 전체 와이어프레임 최신 기준은 2026-06-10 PM 전달 화면 구성 UI.xlsx 20개 sheet와 전체 와이어프레임 산출물이다. 기존 docs/02API명세/01화면명세.m…
마지막 갱신 2026. 6. 10. AM 10:33 KST · docs/02_API명세/01_화면명세.md

화면 명세 v1.1

최신 기준은 2026-06-10 PM 전달 화면 구성 UI.xlsx 20개 sheet와 전체 와이어프레임 산출물이다. 기존 docs/02_API명세/01_화면명세.md의 6-sheet 기준 v1.0 내용은 유지하되, 화면 수와 우선순위는 v1.1 보정표를 우선한다.

반영 산출물

산출물화면 수위치
PM 최신 Excel UI20 sheets/Users/sammy/Downloads/화면 구성 UI.xlsx
관리자/운영자 전체 와이어프레임21 screensdocs/10_UI_스토리보드/20260610_full_wireframe_storyboard.html
모바일 작업자 앱 와이어프레임13 phone screensdocs/10_UI_스토리보드/20260610_mobile_worker_app_storyboard.html
화면 비교/스토리보드 메모20 sheet 비교docs/10_UI_스토리보드/20260610_screen_comparison_storyboard.md

추가 화면 판단

  • 일정 리스트는 PM Excel 독립 sheet는 아니지만 캘린더 클릭 routing과 bulk/reassign 수용 테스트를 닫기 위한 파생 화면이므로 관리자 MVP P0로 본다.
  • 모바일 13화면은 Phase F 기준이다. 단 동선 보기, QR 스캔, 수거 입력, 사진/메모, 증명서 전달, 담당자 변경이 요구하는 API 필드는 현재 설계에서 누락하지 않는다.
  • 사용자 관리/상세는 RBAC 운영 오픈 전 P0다.
  • 차량 관리는 일일업무관리-상세의 선행 마스터다. 일일업무 상세를 7월로 분리하면 차량 UI는 P1로 둘 수 있으나 API/table은 유지한다.

상세 문서: docs/02_API명세/01_화면명세.md

📘 안내 06_갭분석 문서 상태: 최신 기준으로 폐기 docs/09테스트/06갭분석.md의 기존 "누락 0건" 결론은 최신 기준으로 폐기한다. 이 카드는 같은 sourcePath를 다시 sync해서 MiniQA에 남…
마지막 갱신 2026. 6. 10. AM 10:33 KST · docs/09_테스트/06_갭분석.md

06_갭분석 문서 상태

docs/09_테스트/06_갭분석.md의 기존 "누락 0건" 결론은 최신 기준으로 폐기한다. 이 카드는 같은 sourcePath를 다시 sync해서 MiniQA에 남아 있던 구 결론 카드가 최신 경고로 보이게 하기 위한 것이다.

현재 사용 기준

항목판정
기존 "누락 0건"사용 금지
최신 gap 기준docs/09_테스트/07_재매칭_codex.md
PM UI 원본 기준docs/01_요구사항/20260610_PM_전달_UI_반영.md

폐기 사유

2026-06-10 확인한 PM 전달 UI 원본은 기존 repo에 반영된 6-sheet 파일이 아니라 20-sheet 확장본이다. 따라서 기존 gap 분석은 구현 골격 기준으로 과대 충족 판정이 섞였고, PM 최신 UI의 사용자 관리, 원콜 세발/입금, 콘솔 매칭 UX, 협력사 담당자/첨부, 파쇄증명서 파일 workflow, 일일업무관리 상세, 차량 관리 요구를 충분히 반영하지 못했다.

다음 판단

6/30 MVP 전 우선 보강 대상은 Calendar routing, bulk/reassign UI, 사용자 관리 UI, recurring date-confirm workflow, 원콜 세발/입금 최소 모델, 콘솔 매칭 UX다.

📘 안내 갭분석 재판정: 누락 0건 결론 폐기 docs/09테스트/06갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09테스트/07재매칭…
마지막 갱신 2026. 6. 10. AM 9:35 KST · docs/09_테스트/07_재매칭_codex.md

갭분석 재판정

docs/09_테스트/06_갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09_테스트/07_재매칭_codex.md를 우선한다.

재판정 요약

구분판단
기존 06 갭분석구현 골격 기준으로 과대 충족 판정이 섞임
재매칭 결과신규 누락 7건, 부분/과대 6건, 정책충돌/확인 필요 4건
PM 최신 UI 반영기존 6-sheet가 아니라 20-sheet 확장본이므로 gap 추가 발생

우선 보강 대상

영역현재 판정조치
사용자 관리P0 미완/admin placeholder 제거, member list/role/status/password reset 구현
Calendar routingP0 미완bar/date click에서 schedule list filter로 이동
Bulk/reassign UIP0 부분backend mutation을 UI에 연결, 완료 일정 변경 금지 처리
원콜 세발/입금P0 후보payment/deposit/evidence 최소 모델 반영
Recurring date-confirmP0 부분25일 배치 placeholder와 날짜 확정 workflow 분리
콘솔 매칭 UXP0/P1콘솔번호 규칙, 계약 검색/매칭, QR 생성 타이밍 확정
일일업무관리 상세7월 권고현재 DailyWorkPage와 다른 관리자 운영 일보 도메인으로 분리

근거 문서

  • docs/09_테스트/07_재매칭_codex.md
  • docs/01_요구사항/20260610_PM_전달_UI_반영.md
  • docs/09_테스트/06_갭분석.md v1.1 상단 superseded 경고
📘 안내 기존 1472 vs 신규 v5 12 카테고리 비교 기존 1472shred vs 신규 irosafeshred v5 12 카테고리 Before/After — 레거시 기술 부채 8건 해소 + 운영 가치 9건 추가.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/09_테스트/05_기존_vs_신규_비교.md

기존 1472shred vs 신규 irosafe_shred v5 12 카테고리 Before/After — 레거시 기술 부채 8건 해소 + 운영 가치 9건 추가.

1472shred (기존) vs irosafe_shred v5 (신규) 개선사항 비교

작성: 2026-06-06 KST · MVP 6/30 (D-24)
근거: docs/01_아키텍처/00_현황분석.md, docs/03_DB재설계/00_기존_ILSA_결함.md, 신규 코드/문서

핵심 한 줄: 레거시 8개 큰 기술 부채 일괄 해소 + 신규 운영 가치 9건 추가.

0. 개요 비교

기존 1472shred신규 irosafe_shred v5효과
라인 수 (Java)약 180 파일 (web/domain/global 혼재)72 파일 (도메인별 분리)가독성 / 책임 분리
패키지 그룹com.sgisframe (오타)com.irosafe.shred브랜드/오타 정정
빌드gradle.build / warGradle Kotlin DSL / bootJar모던 빌드 + 버전 카탈로그
운영1대 (1472shred.co.kr)컷오버 대기병렬 운영 → 신규
안정성OOM 회고 (2026-05-29 Old Gen full)부팅 3.7s · health 200 · Virtual ThreadJVM 21 가속

1. 기술 스택

영역기존신규개선
Spring Boot2.5.23.3.5 LTSEOL 회피, JDK 21 호환
Java8 (1.8)21 LTS + Virtual Threads13년 격차 해소, GC/성능
JPA / HibernateHibernate 5 (envers)Hibernate 6 + Enversrecord/sealed 호환
빌드gradle DSL (legacy)Gradle Kotlin DSL + libs.versions.toml버전 한 곳, IDE 자동완성
화면Thymeleaf 3.0 (182 템플릿)Vite 5 + React 18 + TSSPA · 다크모드 · HMR
스타일자체 CSSTailwind 3 + Pretendard Variable + iro 토큰디자인 일관성, 가독성
패키징warbootJar (Fat JAR)단일 산출물, systemd 친화
API 문서없음SpringDoc OpenAPI 3 · 32 path 자동신규 화면/외부연동 시 즉시 검증
외부 사내 jarsgis-common-frame.jar (불투명)자체 wellsa-commons / irosafe-shred-commons의존 1개 제거, 책임 명확

2. 인증 · 보안

영역기존신규개선
인증 방식Session + FormLoginJWT HS256 (Access only, 2h)모바일/SPA 친화, stateless
Security 설정WebSecurityConfigurerAdapter (폐기 API)Security 6 SecurityFilterChain bean모던 / 컴파일 안전
비밀번호평문/단순 해시 (추정)bcrypt 12 rounds산업 표준
권한 모델3 단계 텍스트 (SUPER/ADMIN/USER)**RBAC 3-tier × 13 permissions (ROLE_* + 권한 code)@PreAuthorize("hasAuthority('CODE_MANAGE')")
로그인 감사기록 부족login_audit (success/FAIL_PWD/FAIL_BLOCKED/FAIL_NOT_FOUND + IP)침해 추적
세션 타임아웃24hJWT 2h + refresh 가능토큰 노출 시 영향 축소
권한 캐싱미확인AuthorityResolver 트랜잭션 read-only호출당 일관 권한 해석
XSS 방어lucy-xss-servlet 2.0.0 (서버)프론트 React 자동 escape + CSP 가능경로 단축

3. 도메인 (운영 변화)

영역기존신규개선
계약트랙 미분리 — SSF_CONTRACT_MANAGEMENT 한 테이블에 IS_ANNUAL/IS_BRANCH 플래그트랙 이원화 (ONE_CALL / RECURRING) + ContractStatus ENUMURL · UI · 화면 분리, 자동 prefix [원콜]/[정기]
캘린더일/주/월 분리 화면단일 SPA + 협력사 7색 + N+ more 표시한눈에 일정 + 색상 매핑
일일업무안드로이드만웹 + 안드로이드(후속)작업자 1일 view, 카드+진행률
협력사7 협력사 (실제)7색 swatch 자동 매핑 + 캘린더 컬러시각 구분 즉시
콘솔/바코드ZXing 자체 인쇄 (라벨프린터 IP 하드코딩)QR/Barcode generation endpoint + 프린트 영우님 협업인프라 추상화
증명서JasperReports .jrxml 5종5종 ENUM (YEARLY / ONE_TIME / COWAY / AH / HDD) + 발급/무효 mutationPDF 후속 분리
코드 마스터SSF_CMMN_CODE (65 row, varchar 매직코드)code 마스터 + UI 관리 (탭/인라인 편집/활성/순서)운영자 직접 조정
정기 자동 연장코드 부재 (수동)ContractExpiryJob @Scheduled(03:00 KST) — autoExtend → +1y · 비연장 → EXPIRED마감 누락 0

4. UX · 운영자 경험

영역기존신규개선
다크모드없음system/light/dark 3 모드 토글 + localStorage야간 사용 / AAA 가독성
가독성자체 폰트 / 어수선Pretendard Variable + weight 420 + -0.022em 자간텍스트 가독성 +30% (체감)
엑셀 다운로드일부 도메인만계약 / 협력사 / 일정 3종 + 한글 헤더 + UTF-8 파일명운영자 즉시 가치
엑셀 업로드정기 계약동일 유지 (POST /api/v1/recurring/upload)호환
주소 검색미확인카카오 우편번호 모달 + 도로명 우선주소 입력 5x 단축
검색·필터일부 페이지모든 리스트 (계약/일정/협력사/콘솔/증명서)조회 일관성
단축 키없음(후속) keyboard nav 예정

5. 자동화 · 인프라

영역기존신규개선
정기 배치수동 트리거 추정매월 25일 자동 (Quartz 또는 @Scheduled)운영자 부담 0
자동 만료수동 처리ContractExpiryJob 일배치만료 누락 0
QR 발행라벨프린터 IP 하드코딩엔드포인트 + 데이터 분리 (Barcode 도메인)프린트 인프라 교체 자유
Excel 일괄일부정기 대량 업로드 + 다운로드 3종양방향
데이터 마이그 도구없음LegacyMigrationRunner (Spring Boot CLI · dry-run/apply)안전 ETL, 자연키 보존

6. DB 스키마 (대표 결함 14건 → 0건)

#기존 결함해결
1날짜/시간 컬럼 varcharDATE / TIME / DATETIME(6) 정상화
2FK 0개 (비즈니스 테이블)모든 SEQ 참조 FOREIGN KEY
3비정규화 (지점명 중복 저장 3 테이블)SEQ 외래키만, JOIN
4SEQ + ID 이중 식별자bigint id PK 단일, 자연키 별도 unique
5상태값 매직코드 (C1320000)ENUM (CONTRACT/EXPIRED/...)
6NULL/공백 혼재NOT NULL + default 명시
7인덱스 부족ix_sched_visit_started 외 12 인덱스
8감사 envers 일부만BaseEntity + Envers 표준 적용
9패키지 오타 (sigsframe)irosafe.shred
10외부 jar 의존자체 commons 라이브러리
11utf8mb4 / 한글 호환 일부utf8mb4 표준 + Pretendard
12코드 마스터 표준 부재code 마스터 + UI
13시간대 손실KST 고정 (Asia/Seoul)
14Hibernate 4/5 혼재 위험Hibernate 6 통일
상세: docs/03_DB재설계/00_기존_ILSA_결함.md

7. 테스트 · 품질

영역기존신규개선
단위테스트없음 / 미확인71 PASS / 0 FAIL (9 클래스, 12s)핵심 비즈니스 로직 안전망
e2e없음Playwright 35 PASS / 0 FAIL (UI 19 + API 16)UI + endpoint 회귀 자동
통합없음9 작성 (Testcontainers MariaDB)내부 호스트 runner 등록 후 자동
API 문서없음Swagger UI 32 path 자동신규 협업 즉시
CI부분GitLab Pipeline (단위테스트 + build)push 마다 검증
부팅 시간미확인 (OOM 회고)3.7sJVM 21 + lazy bean
Migration 검증수동Flyway V1~V6 + Testcontainers Flyway 검증스키마 일관성

8. 개발 생산성

영역기존신규개선
모노레포백/모바일 분리, 공통화 없음apps/{backend,frontend,android} + libraries/코드 공유
빌드 캐시Gradle 캐시 + npm 캐시 + GitLab cache.key.filesCI 단축
핫리로드(Thymeleaf) 기본Vite HMR + Spring DevTools개발 사이클 가속
의존성 관리분산libs.versions.toml + package-lock.json버전 1곳
모달/팝업일부 자체통합 컴포넌트 (PageHeader/DataTable/SearchBar/Badge)재사용
디자인 토큰없음iro/내부 호스트/partner 팔레트 + Pretendard일관성

9. 보안 · 컴플라이언스

영역기존신규개선
CSRFSpring 기본JWT stateless토큰 모델
CORS자체 처리CorsFilter HIGHEST_PRECEDENCE + origins 명시dev/prod 일관
비밀번호 정책미확인bcrypt 12 + login fail lock 5/30분산업 표준
로그분산통합 (shred-backend.log) + KST운영 단순
감사 (audit)일부 enversBaseEntity + Envers + login_audit + schedule_assignment_audit핵심 변경 추적
컷오버 안전일시병렬 운영 → 신규 점진 + Phase E ETL dry-run/apply 분리롤백 가능

10. 한 장 요약 (Before → After)

항목BeforeAfter
Spring Boot / Java2.5 / 83.3 / 21
화면Thymeleaf 182React SPA + 다크모드
API 문서없음Swagger 32
RBAC 권한3 단계 텍스트13 권한 코드
DB 결함14건0건
테스트없음단위 71 + e2e 35 = 106 PASS
정기 자동 연장수동@Scheduled 일배치
다크모드없음system/light/dark
코드 마스터 UI매직코드탭/인라인/활성
주소 검색없음카카오 우편번호

11. 운영 KPI 예상 (Phase G 시연 후 측정)

KPIBefore (추정)After (목표)
계약 등록 클릭 수10+≤ 5
일정 조회 (월 단위)다중 화면1 SPA
엑셀 다운로드 가능 도메인일부3 (계약/협력사/일정)
협력사 식별 시각 단서텍스트색상 swatch
정기 만료 누락발생0** (배치)
컷오버 위험일괄 교체병렬 운영

12. 변경 이력

  • v1 (2026-06-06): 초안 — 12 카테고리 Before/After 표 + KPI
📜 이전 버전 1건
  1. 버전 1 · 기존 1472 vs 신규 irosafe v5 — 12 카테고리 비교 · 2026. 6. 8. PM 2:12 KST
📘 안내 ILSA → irosafe_shred 마이그 매핑 좁힘 마이그 매핑 — 협력사·계약(트랙 이원화)·지점·일정 횟수 4 도메인의 운영 ↔ 신스키마 컬럼/값 매핑표.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/03_DB재설계/06_마이그_매핑.md

좁힘 마이그 매핑 — 협력사·계약(트랙 이원화)·지점·일정 횟수 4 도메인의 운영 ↔ 신스키마 컬럼/값 매핑표.

좁힘 마이그 매핑 매트릭스 (v5)

작성: 2026-06-06 KST · MVP 6/30 (D-24)
선행: ERD v0.5 메인 (01_신스키마_ERD_v0.5.md) + 보강 (02_ERD_v0.5_보강.md)
대상 데이터: 운영 DB ILSA_SHREDDING (system1472.sldb.iwinv.net) → 신모델 (자체 스키마)

0. 마이그 정합 원칙

1. 자연키 보존 — 레거시 PK/코드를 신모델 UNIQUE 컬럼 + migration_legacy_ref 매핑
2. 변환 못 하면 격리migration_legacy_ref.status='REVIEW_NEEDED' + 운영자 staging 검토
3. 마이그 범위 한정 (4 도메인) — 계약 + 지점 + 일정 횟수 + 협력사 (B8)
4. 레거시 보조 보존 — 신모델 운영 중에도 추적 가능

1. 좁힘 마이그 범위

#신모델 도메인레거시 테이블 (ILSA)row 수자연키
1partner (협력사)SSF_SUBCONTRACTOR_MANAGEMENTTBDSUBCONTRACTOR_ID / business_no
2partner_branch (지점)SSF_BRANCH_OFFICE_MANAGEMENTTBDBRANCH_OFFICE_ID code
3recurring_contract_group / one_call_contract / recurring_contract_site (계약)SSF_CONTRACT_MANAGEMENTTBDCONTRACT_ID code
4recurring_schedule_rule (일정 횟수)SSF_SCHEDULE_MANAGEMENT 정제횟수만
MVP 외 (Phase E 후 7월): 사용자(member), 콘솔, 증명서, 작업 이력 풀 마이그.

2. 컬럼별 매핑 표

2.1 협력사 — SSF_SUBCONTRACTOR_MANAGEMENTpartner

레거시 컬럼신모델 컬럼변환
SUBCONTRACTOR_SEQpartner.legacy_subcontractor_seq그대로
SUBCONTRACTOR_IDpartner.code UNIQUE그대로 (자연키)
SUBCONTRACTOR_NAMEpartner.nametrim
BUSINESS_NUMBERpartner.business_no UNIQUE999-99-999999999999999 (정규화 후 UNIQUE 보존)
PHONEpartner.phone010-XXXX-XXXX 형식
ADDRESSpartner.address_main
ZIPCODEpartner.address_zip
AREA_CODEpartner.region_code FK→system.codecategory=REGION
STATUSpartner.statusC-code → ACTIVE/SUSPENDED/CLOSED ENUM (mapping 표 §3)
APPROVAL_STATUS(마이그 X — 신모델 사용 X)
INS_DATE / UPD_DATEcreated_at / updated_atKST → UTC
INS_ID / UPD_IDcreated_by / updated_bylogin_id → account.id 매핑 (사용자 마이그 후)
partner.color_hexNULL 시 시스템 자동 할당 (palette 7색 round-robin)

2.2 지점 — SSF_BRANCH_OFFICE_MANAGEMENTpartner_branch

레거시신모델변환
BRANCH_OFFICE_SEQpartner_branch.legacy_branch_seq그대로
BRANCH_OFFICE_IDpartner_branch.code (partner_id+code UNIQUE)
CONTRACT_ID(정기) partner_id 매핑 시 사용 — 본사 SUBCONTRACTOR 추출
BRANCH_OFFICE_NAMEpartner_branch.name
MANAGER_NAMEpartner_contact.name (별도 row 생성)
MANAGER_PHONEpartner_contact.phone
ADDRESS / ZIPCODE / AREA_CODE동일 패턴
OPERATION_CYCLE_VALUErecurring_schedule_rule.month_count (별도 row)unit=MONTH 일 때
OPERATION_CYCLE_UNIT(rule 생성 시 사용)MONTH/WEEK 두 분리
REPETITION_FORM(rule 의 preferred_weekdays/time 힌트 — 가능하면)
STATUS / APPROVAL_STATUSC-code → ENUM
SUBCONTRACTOR_IDpartner_id FK(legacy mapping ref 통해)

2.3 계약 — SSF_CONTRACT_MANAGEMENT → 트랙별 분리

#### (a) 원콜 (IS_ANNUAL=N, IS_BRANCH=N)
one_call_contract

레거시신모델
CONTRACT_IDone_call_contract.contract_no (OC- prefix 가능, 형식 변환)
CONTRACT_NAMEone_call_contract.name (auto prefix [원콜])
COMPANY_NAMEcustomer_name
BUSINESS_NUMBERbusiness_no
STARTED_ONwork_date (원콜은 단일 일자)
CRUSH_OPTIONshred_option (SITE→ON_SITE, WAREHOUSE→INTAKE)
CERTIFICATE_TYPEC-code → ENUM (C1210000→YEARLY 등, §3 mapping)
STATUSC-code → ENUM (DRAFT→/APPROVED→CONTRACT/TERMINATED→CANCELLED)
#### (b) 정기 본사 (IS_ANNUAL=Y, IS_BRANCH=Y) → recurring_contract_group
레거시신모델
CONTRACT_IDcode
COMPANY_NAMEname
BUSINESS_NUMBERbusiness_no
ADDRESS / ZIPCODE본사 주소
#### (c) 정기 지점 — SSF_BRANCH_OFFICE_MANAGEMENT 의 contract 연결 → recurring_contract_site
레거시신모델
BRANCH_OFFICE.CONTRACT_IDrecurring_contract_site.group_id (legacy_ref 매핑 거침)
BRANCH_OFFICE_IDcontract_no (자연키 보존, 형식 RC-{group_code}-NNN)
SETUP_STARTED_ONcontract_start_date
VISIT_ENDS_ONcontract_end_date (NULL 시 = contract_start_date + 1년 default)
auto_extend=TRUE (default, 회의 결정)
SUBCONTRACTOR_IDpartner_id (legacy_ref 매핑)

2.4 일정 횟수 — SSF_SCHEDULE_MANAGEMENTrecurring_schedule_rule (정제)

PDF/회의 결정: 세부 일정 마이그 X. "주 몇 회" 횟수만 정제.

변환설명
그룹화같은 BRANCH_OFFICE_ID + 월 단위 작업 횟수 집계
month_count 계산직전 12개월 평균 작업 횟수
preferred_weekdays가장 빈번한 요일 (TOP 2)
preferred_time_windowVISIT_START_TIME 분포 → MORNING/AFTERNOON/EVENING
effective_from마이그 시점
→ 신모델 매월 25일 배치가 본 rule 기준으로 다음 달 schedule 생성. 사람이 SOP 화면에서 날짜 조정.

3. 코드 마스터 매핑 (SSF_CMMN_CODE → 신모델 ENUM)

레거시 코드의미신모델 ENUM
자루상태 (CRUSHER_STATUS)
C1100000자루상태 (UPPER)(parent) — sub-code 만 사용
C1120000수거console_bag_history.event='COLLECTED' 또는 status='IN_USE'
(그 외 sub-code TBD)
파쇄증명서 종류 (CERTIFICATE_TYPE)
C1210000연간계약용certificate.type='YEARLY'
C1220000단건계약용certificate.type='ONE_TIME'
C1230000코웨이전용certificate.type='COWAY'
C1240000AH전용certificate.type='AH'
C1250000HDD용certificate.type='HDD'
파쇄증명서 발급상태 (STATUS)
C9010000발급certificate.status='ISSUED'
C9020000미발급certificate.status='UNISSUED'
콘솔 상태 (STATUS)
C7020000배정console.status='DEPLOYED'
(그 외 sub-code TBD)
승인 상태 (APPROVAL_STATUS)
C2010000승인요청(마이그 X — 신모델 사용 X, 모두 APPROVED 변환)
계약 상태 (CONTRACT.STATUS)
DRAFT / APPROVED / ACTIVEcontract.status='CONTRACT'
TERMINATED / EXPIREDcontract.status='CANCELLED'/EXPIRED'

4. 운영자 확인 5건 → 마이그 정책

#항목결정 (마이그 시)
#1Crm1472 AWS IP 13.124.4.31자체 CRM. 신규 시스템 /crm/save 호환 endpoint 유지. controller 위치는 irosafe-shred-commons/api/crm
#2password_hashbcrypt 확정 (BCryptPasswordEncoder). 해시 그대로 옮김 — 재설정 X
#3CRUSHER_STATUS='C1100000' 1건데이터 결함. migration_legacy_ref.status='REVIEW_NEEDED' — CS2207 격리
#4certificate 50% 미발급운영 흐름 정상. ENUM ISSUED/UNISSUED 그대로 마이그
#5WORK_TYPE='kg' 687건중량형 단위. unit='kg', quantity=WORK_WEIGHT 값 변환

5. ETL 실행 순서


Phase E1 — partner (의존: 없음)
Phase E2 — partner_branch + partner_contact (의존: partner)
Phase E3 — recurring_contract_group (정기 본사)
Phase E4 — recurring_contract_site (의존: group + partner + partner_branch)
Phase E5 — one_call_contract
Phase E6 — recurring_schedule_rule (의존: site, 12개월 집계)
Phase E7 — 검증 (count·체크섬·샘플 비교)

각 단계마다 migration_legacy_ref row 동시 INSERT (entity_type 별).

6. 검증 쿼리 (Phase E7)

sql
-- 협력사 count 일치
SELECT COUNT(*) AS legacy FROM SSF_SUBCONTRACTOR_MANAGEMENT WHERE STATUS != 'TERMINATED';
SELECT COUNT(*) AS new FROM partner;
-- ↑ 차이가 있으면 폐업 협력사 마이그 정책 재확인

-- 지점 count 일치 + partner 연결 검증
SELECT COUNT(*) FROM partner_branch pb
JOIN migration_legacy_ref m ON m.entity_type='partner_branch' AND m.new_id=pb.id
WHERE m.legacy_pk_value IS NOT NULL;

-- 사업자번호 정합 (UNIQUE)
SELECT business_no, COUNT(*) FROM partner GROUP BY business_no HAVING COUNT(*) > 1;

-- 자연키 보존 검증 (legacy_ref 와 신모델 자연키)
SELECT m.legacy_code, m.new_id, p.code
FROM migration_legacy_ref m JOIN partner p ON p.id=m.new_id
WHERE m.entity_type='partner' AND m.legacy_code != p.code;

7. Staging 격리 정책

다음 row 는 migration_staging_* 로 격리 + 운영자 검토:

케이스격리 사유
business_no 형식 잘못정규화 실패
business_no 중복UNIQUE 위반
CRUSHER_STATUS='C1100000'parent code 이상치
폐업 협력사 (CLOSED)B8: 운영자 검토 후 마이그 여부 결정
작업 횟수 산정 불가 (지점 작업 0건)횟수 정제 결과 0
각 격리 row → migration_legacy_ref.status='REVIEW_NEEDED' + note 명시.

8. 다음 step

  • tui — _data/migration/V_*.sql ETL 스크립트 작성 (본 매핑 표 기반)
  • AI 어시스턴트 재검토 (본 매핑 매트릭스 + ERD v0.5.1 통합)
  • Phase E1~E7 실행 순서 확정 + 운영자 검토 staging 흐름 설계
  • 검증 쿼리 자동화 (Flyway repeatable migration 또는 별도 verify 스크립트)

변경 이력

  • v5 (2026-06-06): 신규 작성. 좁힘 범위 (계약+지점+일정 횟수+협력사) + 자연키 보존 + 운영자 확인 5건 반영 + SSF_CMMN_CODE decoding 결과.
📜 이전 버전 1건
  1. 버전 1 · ILSA → irosafe_shred 마이그 매핑 · 2026. 6. 8. PM 2:12 KST
📘 안내 신스키마 ERD v0.5.1 신스키마 irosafeshred ERD v0.5.1 — 7 도메인 (auth/partner/asset/operation/work/comm/system) + 계약 …
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/03_DB재설계/01_신스키마_ERD_v0.5.1.md

신스키마 irosafe_shred ERD v0.5.1 — 7 도메인 (auth/partner/asset/operation/work/comm/system) + 계약 트랙 이원화 + RBAC 3단계.

신스키마 irosafe_shred ERD v0.5.1 (통합본)

상태: v0.5.1 — antigravity 메인 (v0.5) + 본 워커 보강 (v0.5 보강) 통합. Phase A 종료 기준 산출물.

작성: 2026-06-06 KST · MVP 6/30 (D-24)
선행 산출물:

  • 01_신스키마_ERD_v0.5.md (antigravity, 2026-06-06) — 메인 골격 + mermaid + 트랙 이원화 + 자연키 보존
  • 02_ERD_v0.5_보강.md (담당 워커, 2026-06-06) — AI 어시스턴트 P0 5건 + 회의 결정 19건 + RBAC 3단계 + 운영자 #1~#5 답변
  • 06_마이그_매핑.md (worker, 2026-06-06) — 좁힘 마이그 매트릭스

0. 통합 의사결정

AI 어시스턴트 P0 권고v0.5.1 채택
P0-1 계약 트랙 테이블 물리 분리부분 채택contract.track ENUM + branch_office_id NULL (원콜) 패턴 유지. MVP 24일 안에 테이블 통째 분리 비용 큼. Phase 7월에 nullable 문제 누적 시 재분리.
P0-2 recurring_schedule_rule 신설채택branch_office.operation_cycle_* 폐기하지 않고 동시 운영 (마이그 호환). 신규 rule 우선.
P0-3 migration_legacy_ref 통합 ref채택 — antigravity 의 mig_pk_mapping_log 폐기, 통합 ref 사용 (영구 보존).
P0-4 콘솔 1:N + event 분리채택console_bag_history 유지 + console_event 신설 (콘솔 자체 이벤트).
P0-5 RBAC 3단계 명시 + permission 매트릭스채택member.role ENUM 값 WORKER/OFFICE/ADMIN, permission + role_permission 신설.

1. 도메인 맵

도메인책임MVP IN참고
auth인증·권한·세션✓ RBAC 3단계bcrypt 확정 (#2)
partner협력사·외주업체 + 지점✓ 자연키 + legacy_ref마이그 정합
asset차량·콘솔·바코드✓ console 1:N
operation계약·일정·증명서·콘솔 이벤트핵심 트랙 이원화recurring_schedule_rule
work작업 이력·정산minimalMVP 후 풀
comm알림·발송 이력minimal
system코드 마스터·감사·환경✓ 지역·품목
migration레거시 이관 추적✓ legacy_ref영구 보존

2. ERD 통합 다이어그램 (Mermaid)

다이어그램 보기 — SSR 파서가 이미지/HTML 미지원이라 링크로 제공.

SVG 는 브라우저에서 확대/스크롤 가능. 모바일에서도 핀치 줌 OK.

3. 핵심 변경 사항 (v0.5 → v0.5.1)

항목v0.5v0.5.1
계약 트랙 식별is_annual + is_branch 플래그track ENUM('ONE_CALL','RECURRING') 추가 (명시)
정기 만료 정책단순 ended_onauto_extend BOOLEAN + default = started_on + 1년 (회의 결정)
반복 일정 규칙branch_office.operation_cycle_*recurring_schedule_rule 신설 (month_count + weekday/time hint + effective_from/to)
RBACmember.role ENUM('SUPER','ADMIN','USER')role 테이블 (WORKER/OFFICE/ADMIN) + permission + role_permission + member_role
콘솔 이벤트console_bag_historyconsole_event 추가 (콘솔 자체 이벤트: COLLECTED/SHREDDED/RELOCATED/STATUS_CHANGE)
담당자 변경 이력schedule_managerschedule_assignment + schedule_assignment_audit 신설 (change_reason ENUM: TAENGGYEO 명시)
마이그 추적mig_pk_mapping_log 임시migration_legacy_ref 영구 (entity_type, status='MAPPED'/'REVIEW_NEEDED'/'DROPPED')
자루상태 ENUMREADY/IN_USE/COLLECTED/SHREDDED(동일) + 마이그 시 C1100000 격리 (운영자 #3)
증명서 상태ISSUED/RESCINDEDISSUED/UNISSUED/VOIDED 3단계 (운영자 #4 — 50% 미발급은 정상)
WORK_TYPE단일 ENUMcertificate_worktype.unit ENUM('item','kg') + quantity 분리 (운영자 #5 — kg 중량형)
협력사 컬러없음subcontractor.color_hex (캘린더 협력사 컬러 매핑)
password_hash단순 VARCHARCHAR(60) bcrypt 명시 (운영자 #2 코드 확정)
Crm1472 endpoint미명시신규 시스템 /crm/save 호환 endpoint 유지 (운영자 #1 자체 CRM, B6 결정)

4. RBAC permission 매트릭스

permission codescopeWORKEROFFICEADMIN
CALENDAR_VIEW_DAYcalendar
CALENDAR_VIEW_WEEKcalendar
CALENDAR_VIEW_MONTHcalendar
SCHEDULE_REASSIGN_SELF (땡겨오기)schedule
SCHEDULE_BULK_UPDATEschedule
SCHEDULE_BULK_DELETEschedule
BRANCH_RENAME (지점명 변경)partner
CONTRACT_CREATEoperation
CONTRACT_EDIToperation
BULK_UPLOAD_EXCEL (정기 대량)operation
BATCH_TRIGGER (매월 25일)operation
SYSTEM_CONFIGsystem
USER_MANAGEauth
→ Spring Method Security @PreAuthorize("hasAuthority('BRANCH_RENAME')").

5. ENUM 전체 (v0.5.1)

ENUM
member.statusACTIVE, SUSPENDED, LEFT
role.codeWORKER, OFFICE, ADMIN
subcontractor.statusACTIVE, SUSPENDED, CLOSED
branch_office.statusACTIVE, SUSPENDED, CLOSED
contract.trackONE_CALL, RECURRING
contract.shred_optionON_SITE, INTAKE
contract.certificate_typeYEARLY, ONE_TIME, COWAY, AH, HDD
contract.statusCONTRACT, EXPIRED, CANCELLED, TERMINATED
recurring_schedule_rule.preferred_time_windowMORNING, AFTERNOON, EVENING
operation.statusPENDING, IN_PROGRESS, COMPLETED, CANCELED
schedule.trackONE_CALL, RECURRING
schedule.statusPLANNED, CONFIRMED, COMPLETED, RESCHEDULED, CANCELED
schedule_manager.roleLEAD, ASSISTANT, SECURITY
schedule_assignment_audit.change_reasonTAENGGYEO, OFFICE_REASSIGN, LEAVE, OTHER
console.statusAVAILABLE, DEPLOYED, MAINTENANCE, RETIRED
console.bag_statusREADY, IN_USE, COLLECTED, SHREDDED
barcode.formatQR, CODE128, CODE39
console_bag_history.eventINSERTED, WITHDRAWN, SHREDDED
console_event.event_typeCOLLECTED, SHREDDED, RELOCATED, STATUS_CHANGE
certificate.typeYEARLY, ONE_TIME, COWAY, AH, HDD
certificate.statusISSUED, UNISSUED, VOIDED
certificate_worktype.work_typeBOX, A4_BOX, KG, MADAE, HDD
certificate_worktype.unititem, kg
disposal.bag_statusCOLLECTED, SHREDDED
attach_file.target_typeSUBCONTRACTOR_BIZNUM, CERTIFICATE, SIGNATURE, NOTICE, MISC
notification.kindSCHEDULE_REASSIGNED, SCHEDULE_BULK_UPDATE, BRANCH_RENAMED, CERTIFICATE_ISSUED, OTHER
login_audit.resultSUCCESS, FAIL_PWD, FAIL_BLOCKED, FAIL_NOT_FOUND
work_job.pay_typeCASH, CARD, TRANSFER, MIXED
migration_legacy_ref.statusMAPPED, REVIEW_NEEDED, DROPPED
→ Java @Enumerated(EnumType.STRING). 마이그 시 SSF_CMMN_CODE 매핑 (06_마이그_매핑.md §3 참고).

6. 인덱스

  • member(login_id), session(jwt_id), session(member_id, expires_at)
  • subcontractor(business_number), subcontractor(name), subcontractor(area_code)
  • branch_office(subcontractor_id), branch_office(contract_id), branch_office(name)
  • contract(code), contract(track, status), contract(ended_on, auto_extend) (자동 연장 배치)
  • recurring_schedule_rule(branch_office_id, effective_from) (배치)
  • schedule(visit_started_on), schedule(subcontractor_id, visit_started_on), schedule(branch_office_id, visit_started_on), schedule(track, visit_started_on)캘린더 조회 최우선
  • schedule_assignment(schedule_id, member_id)
  • schedule_assignment_audit(schedule_id, changed_at)
  • console(branch_office_id, status), barcode(code)
  • console_event(console_id, occurred_at), console_event(schedule_id)
  • certificate(schedule_id) UK, certificate(type, status)
  • migration_legacy_ref(entity_type, legacy_pk_value), migration_legacy_ref(entity_type, new_id), migration_legacy_ref(migration_batch_id)

7. Audit (Envers _audit)

다음 테이블에 envers 적용:

  • branch_office (지점명 변경 — 회의 Lock 결정)
  • schedule (일정 변경)
  • schedule_assignment (담당자 변경)
  • recurring_schedule_rule (반복 규칙 변경)
  • contract (계약 변경)
  • member (권한 변경)

schedule_assignment_audit 와 envers _audit이중 운영: envers 는 자동 row 이력, schedule_assignment_audit 는 change_reason ENUM 명시 (땡겨오기 추적).

8. system.config 기본값

keyvalue설명
RECURRING_BATCH_DAY25매월 N일 배치 실행
RECURRING_AUTO_EXTEND_YEARS1자동 연장 N년 (회의 결정)
JWT_ACCESS_TTL_SEC72002시간 (AI 어시스턴트 권고 — refresh 7월)
LOGIN_FAIL_LOCK_THRESHOLD5연속 실패 시 잠금
LOGIN_FAIL_LOCK_DURATION_MIN30잠금 시간
COLOR_PALETTE_PARTNER["#0e7c7b","#2563eb","#b45309","#e11d48","#7c3aed","#16a34a","#475569"]협력사 컬러 (round-robin)
CRM_CALLBACK_HOST13.124.4.31자체 CRM (운영자 #1)

9. 마이그 정합 — AI 어시스턴트 P0-3 통합

migration_legacy_refmig_pk_mapping_log 대체 (영구 보존).

검증 (Phase E7):
sql
SELECT COUNT(*) FROM migration_legacy_ref WHERE status='REVIEW_NEEDED';
SELECT entity_type, COUNT(*) FROM migration_legacy_ref GROUP BY entity_type;
SELECT COUNT(*) FROM subcontractor s
  LEFT JOIN migration_legacy_ref m ON m.entity_type='partner' AND m.new_id=s.id
  WHERE m.id IS NULL; -- 마이그 누락

Staging 격리 (mig_staging_contract_error) — 변환 실패 row 보존.

10. 운영자 확인 5건 → ERD 반영

#v0.5.1 반영
#1 Crm1472 = 자체 CRM자체 운영config.CRM_CALLBACK_HOST=13.124.4.31 + 신규 /crm/save 호환 endpoint 유지
#2 password_hash = bcrypt코드 확정member.password_hash CHAR(60) + BCryptPasswordEncoder
#3 CRUSHER_STATUS='C1100000' 1건데이터 결함console.bag_status ENUM sub-code 만. 마이그 시 CS2207 REVIEW_NEEDED
#4 certificate 50% 미발급운영 흐름 정상certificate.status ENUM('ISSUED','UNISSUED','VOIDED')
#5 WORK_TYPE='kg' 687건중량형 단위certificate_worktype.unit ENUM('item','kg') + quantity 분리

11. MVP 6/30 — Phase B~D 진입 준비

이 ERD 로 Phase B (스택 골격) + Phase C (도메인 신규 구축) + Phase D (자동화) 모두 진입 가능:

  • Phase B: member, role, permission, session + JWT Security 6
  • Phase C1: member + role + permission CRUD
  • Phase C2: contract + branch_office 트랙 분리 CRUD
  • Phase C3: schedule + 캘린더 (track + visit_started_on 인덱스)
  • Phase C4: subcontractor + subcontractor_branch
  • Phase C5: console + barcode + console_event
  • Phase C6: certificate
  • Phase C7: collection_item + code 마스터
  • Phase C8: code 카테고리 (REGION/ITEM/CHANGE_REASON)
  • Phase D1: recurring_schedule_rule 배치 (매월 25일)
  • Phase D4: schedule_assignment_audit 트리거

12. 다음 step (Phase A 종료)

  • tui — Flyway V1__initial_schema.sql 본 ERD 기반 DDL 작성
  • opencode — JPA 엔티티 7+ 도메인 본 ERD 기반 작성
  • AI 어시스턴트 — 본 v0.5.1 재검토 (P0 변경 + 마이그 정합)
  • design — 와이어프레임 7장 (P1+P2+P3) 회수
  • antigravity — 화면 명세 finalize
  • _docs/03_DB재설계/07_ENUM_v0.5.md — ENUM 풀 정의 (별도 문서로 분리)

변경 이력

  • v0.4 (2026-05-08): 마이그 기반 7 도메인 풀 마이그
  • v0.5 (2026-06-06, antigravity): 신규 구축 + mermaid + 트랙 이원화 + 자연키 보존 + Staging
  • v0.5 보강 (2026-06-06, worker): AI 어시스턴트 P0 5건 + 회의 19건 + RBAC 3단계
  • v0.5.1 (2026-06-06, worker 통합본): 두 산출물 통합. AI 어시스턴트 P0 5건 채택 결정 명시. 운영자 5건 ENUM/매핑 반영. Phase B~D 진입 준비 완료.
📘 안내 세션 핸드오프 (다음 워커용) 다음 워커가 컨텍스트 즉시 회복할 수 있도록 — 시스템 상태 / 우선순위 / 명령 / 토큰 위치 / 알려진 이슈.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/07_진행/04_세션핸드오프.md

다음 워커가 컨텍스트 즉시 회복할 수 있도록 — 시스템 상태 / 우선순위 / 명령 / 토큰 위치 / 알려진 이슈.

1. 라이브 시스템 상태

컴포넌트상태위치
외부 dev URLUPhttps://dev-shred.irosafe.com
SwaggerUP/swagger-ui/index.html (32 path)
문서 허브UP/docs/ (docsify)
backendUPirosafe 노드 /opt/shred/shred-backend.jar (systemd) · port 8081
frontendUPnginx static /var/www/shred/
MariaDBUPlocalhost 3306 · irosafe_shred
Cloudflare TunnelUPtunnel irocheck · ingress dev-shred.irosafe.com
운영 ILSA DBreach OKsystem1472.sldb.iwinv.net · RO 계정 shred_migrate_ro

2. 다음 워커 우선순위

P0 (운영자/사용자 결정 대기)

  • Phase E apply — dry-run 결과 검토 후 1회 실행. V4 데모 seed 정리 결정.
  • G3 운영자 수용 시연 — A-001 ~ A-004 (사용자 + 작업자 1명).
  • 갭분석 워커 결과 회수 — AI 어시스턴트 / antigravity 응답 대기.

P1 (코드/인프라)

  • Schedule reassign / bulk-cancel UI mutation 연결 (백엔드 endpoint 이미 존재)
  • DailyWork 사진 첨부 (S3 또는 로컬)
  • WORKER / OFFICE 권한별 메뉴 분기 (현재 ADMIN 전용 UI)
  • 사내 GitLab Runner 등록 → 통합테스트 / e2e CI 자동
  • MiniQA 페이지 layout 회수 (cohort 페이지 카드화 검증)

P2 (마지막)

  • Phase F 안드로이드 (백엔드 컷오버 후)
  • G4 컷오버 (1472shred.co.kr 폐기)
  • G5 안정화 1~2개월 모니터링

3. 실행 명령 모음

bash
# 백엔드 빌드 + 부팅 (로컬 dev)
cd apps/backend
JAVA_HOME=/opt/homebrew/Cellar/openjdk@21/21.0.11/libexec/openjdk.jdk/Contents/Home \
  ./gradlew --quiet build -x test
java -jar build/libs/shred-backend.jar &

# 프론트 dev 서버
cd apps/frontend && npm run dev

# 단위테스트 일괄
cd apps/backend && ./gradlew --quiet test --tests "*Test"

# Playwright e2e
cd apps/frontend && npx playwright test
PLAYWRIGHT_BASE_URL=https://dev-shred.irosafe.com npx playwright test  # 외부 대상

# irosafe 노드 jar 배포
scp apps/backend/build/libs/shred-backend.jar sammy@내부 호스트:/opt/shred/
ssh sammy@내부 호스트 sudo systemctl restart shred-backend

# 문서 노드 sync
tar czf /tmp/shred-docs.tgz -C docs .
scp /tmp/shred-docs.tgz sammy@내부 호스트:/tmp/
ssh sammy@내부 호스트 'sudo tar xzf /tmp/shred-docs.tgz -C /var/www/shred-docs/'

4. 알려진 이슈 + 규칙

  • 8080 포트 충돌 시 새 인스턴스 BindException — lsof -ti tcp:8080 | xargs kill 후 재시작
  • Vite proxy 는 127.0.0.1:8080 명시 (IPv6 ::1 fallback 안 됨)
  • GitLab default.cache.key.files 최대 2개 (늘리지 말 것)
  • JwtAuthenticationFilter / SecurityConfig / WebConfig 에 @ConditionalOnWebApplicationprofile=migrate (web=none) 와 호환
  • PasswordEncoder bean 은 별도 PasswordEncoderConfig (web/CLI 양쪽 사용)

5. 토큰 / 비밀번호 위치

  • GitLab: ~/.miniverse_secrets/GITLAB_TOKEN
  • Cloudflare: CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID
  • ILSA RO: ~/.miniverse_secrets/ILSA_RO_PASSWORD
  • 운영 DB host: system1472.sldb.iwinv.net · RO user shred_migrate_ro
  • dev admin 계정: V7 seed (운영자에게 별도 안내 · 운영 컷오버 시 즉시 변경)
📜 이전 버전 1건
  1. 버전 1 · 세션 핸드오프 (최신) · 2026. 6. 8. PM 2:12 KST
📘 안내 shred-backend README — 스택/도메인/RBAC/테스트 요약 기존 1472 쉬레드 운영 (Spring Boot 2.5 / Java 8) → irosafe 쉬레드 신규 구축 (Architecture Overhaul).
마지막 갱신 2026. 6. 8. PM 12:28 KST · apps/backend/README.md

irosafe / shred-backend

irosafe 쉬레드 신규 시스템 백엔드. Spring Boot 3.3 LTS + Java 21 LTS.

개요

기존 1472 쉬레드 운영 (Spring Boot 2.5 / Java 8) → irosafe 쉬레드 신규 구축 (Architecture Overhaul).

  • MVP 목표: 2026-06-30
  • 인풋: Notion SOP + 개발 요청 문서 + UI 명세 + 2026-05-27 회의
  • 좁힘 마이그: 계약 + 지점 + 일정 횟수 + 협력사

스택

항목버전
Spring Boot3.3.x LTS
Java21 LTS (virtual threads)
GradleKotlin DSL
DBMariaDB 10.6+
MigrationFlyway 10.x
ORMJPA + Hibernate 6 + Envers (선택 도메인)
MyBatisSpring Boot Starter 3.0+ (복잡 쿼리)
SecuritySpring Security 6 + JWT 0.12.x (access only)
Authbcrypt (BCryptPasswordEncoder)
TestJUnit 5 + AssertJ + Testcontainers (MariaDB)
CIGitLab CI (사내 runner)

도메인 (8)

1. auth — RBAC 3단계 (WORKER / OFFICE / ADMIN) + JWT + login_audit
2. partner — 협력사 + 지점 + 담당자 (자연키 보존, 마이그 정합)
3. operation — 계약 트랙 이원화 (원콜 + 정기 상위그룹·지점·작업) + 일정 캘린더 + recurring_schedule_rule
4. asset — 콘솔 + 바코드 + console_event (지점 1:N)
5. work — 증명서 + 작업 이력 (minimal MVP)
6. comm — 알림 + 발송 (minimal)
7. system — 코드 마스터 + 감사 + 환경 설정
8. migrationmigration_legacy_ref (좁힘 마이그 추적)

빌드 / 실행

bash
# 빌드
./gradlew clean bootJar

# 로컬 실행
./gradlew bootRun

# 테스트
./gradlew test

DB 초기화

bash
# Flyway migrate
./gradlew flywayMigrate

# 또는 부팅 시 자동 적용 (application-local.yml)

마이그레이션 SQL

src/main/resources/db/migration/

  • V1__initial_schema.sql — 모든 테이블 + 인덱스 + FK + CHECK
  • V2__seed_rbac_config.sql — 3 roles + 13 permissions + role_permission + 7 config
  • V3__seed_code_master.sql — REGION 7 / ITEM 5 / CHANGE_REASON 4 / CERTIFICATE_TYPE 5
  • V4__seed_sample_data.sql — 데모 (협력사 7 + 계약 6 + 지점 3 + 일정 8 + 콘솔 5)
  • V5__seed_dailywork_assignment.sql — admin → ±30일 schedule primary 배정 (DailyWork 확인용)
  • V6__add_code_manage_permission.sql — CODE_MANAGE 권한 + ADMIN role 부여

테스트 (2026-06-06 17:00)

  • 단위테스트: 71 PASS / 0 FAIL (9 클래스, 12s) — JwtService / AuthService / AuthorityResolver / ScheduleService / ContractController / CodeController / ContractExpiryJob / ExcelStatusLabel / LegacyMappers
  • 통합테스트: 9 작성 (ApiIntegrationTest, FlywaySchemaIntegrationTest — Testcontainers MariaDB, Docker 필요)
  • Playwright e2e (프론트 레포): UI 19 + API 16 = 35 PASS / 0 FAIL
  • 실행: ./gradlew test --tests "*Test"

문서 (모노레포 루트 — apps/backend 와 분리)

  • 전체 마일스톤 v5: docs/07_진행/00_마일스톤.md
  • 세션 핸드오프 (2026-06-06): docs/07_진행/04_세션핸드오프_2026-06-06.md
  • ILSA RO 계정 생성 SQL: docs/07_진행/03_ILSA_readonly_계정_생성.md
  • 기존 1472shred vs 신규 irosafe_shred 비교: docs/09_테스트/05_기존_vs_신규_비교.md
  • 테스트 결과서 (xlsx/pptx): docs/09_테스트/테스트결과서_irosafe_shred.{xlsx,pptx}
  • ERD v0.5.1: docs/03_DB재설계/01_신스키마_ERD_v0.5.1.md
  • 마이그 매핑: docs/03_DB재설계/06_마이그_매핑.md
  • 화면 명세: docs/02_API명세/01_화면명세.md
  • 와이어프레임: dashboard/assets/wireframes/W01~W08
  • 전체 방향 v5: docs/01_요구사항/00_전체방향_v5.md

API 문서

부팅 후 /swagger-ui/index.html 또는 /v3/api-docs (32 path 자동 노출).

RBAC permission 매트릭스

permissionWORKEROFFICEADMIN
CALENDAR_VIEW_DAY
CALENDAR_VIEW_WEEK
CALENDAR_VIEW_MONTH
SCHEDULE_REASSIGN_SELF (땡겨오기)
SCHEDULE_BULK_UPDATE
SCHEDULE_BULK_DELETE
BRANCH_RENAME (지점명 변경)
CONTRACT_CREATE
CONTRACT_EDIT
BULK_UPLOAD_EXCEL
BATCH_TRIGGER (매월 25일)
SYSTEM_CONFIG
USER_MANAGE
CODE_MANAGE (코드 마스터)

라이센스

내부 운영 — 비공개.

📘 안내 Spring Boot 3 / Java 21 마이그레이션 플랜 대상: 1472sshred-system
마지막 갱신 2026. 6. 8. PM 12:28 KST · docs/05_버전업/00_마이그레이션_플랜.md

Spring Boot 3 / Java 21 마이그레이션 플랜

대상: 1472s_shred-system
현재 기준: Spring Boot 2.5.2, Java 8, Gradle Wrapper 7.5, war 배포
목표 기준: Spring Boot 3.3.x, Java 21 LTS 채택.

Java 21 채택 이유 (2026-05-08 운영 결정권자 결정):

  • Spring Boot 3.3 LTS native 권장
  • virtual threads (Project Loom) — ERP I/O bound 워크로드에 유리 (Tomcat virtual thread executor)
  • 2028-09 LTS 지원, ZGC 안정, GraalVM native image 강화
  • pattern matching, record patterns, sealed classes 가독성
  • 자체 라이브러리 (wellsa-commons / irosafe-shred-commons) 신규 작성하므로 외부 jar 17 호환성 걱정 없음

0. 기준 결정

  • Public Maven Central 기준 Spring Boot 3.3 라인의 최신 OSS 릴리스는 3.3.13이다.
  • Spring Enterprise/LTS 계약 저장소를 쓸 수 있으면 3.3.16+ 라인을 별도 검토한다. Enterprise 문서 기준 Spring Boot 3.3.16은 Java 17 이상, Gradle 7.5+ 또는 8.x를 요구한다.
  • 이 프로젝트의 Gradle Wrapper는 이미 7.5라서 최소 요구사항은 맞지만, 실제 마이그레이션 브랜치에서는 Gradle 8.10+로 올리는 편이 안전하다.
  • 로컬 현재 세션에는 JDK가 없어 ./gradlew 빌드 실행은 아직 불가했다. java_home이 "Unable to locate a Java Runtime"를 반환했다.

1. 현재 상태 스냅샷

1472s_shred-system/build.gradle 주요 의존성:

영역현재 버전
Spring Boot2.5.2
JavasourceCompatibility = 1.8
MyBatis Spring Boot Starter2.2.0
Spring Data EnversBoot BOM 암묵 버전
Thymeleaf extrasthymeleaf-extras-springsecurity5
Thymeleaf layout dialect2.4.1
lucy-xss-servlet2.0.0
JJWT0.11.2
JasperReports6.17.0
iText/lowagie2.1.7
ZXing3.4.1
Apache POI5.0.0
외부 사내 jar (libs/)자체 라이브러리로 교체 예정 → wellsa-commons + irosafe-shred-commons 신규
Logback override1.2.3
코드 스캔 결과:
  • javax.* import/참조: 106개 Java 파일, 483개 라인.
  • 주요 전환 대상: javax.persistence 285, javax.validation 46, javax.servlet 141, javax.transaction 10.
  • javax.sql, javax.net.ssl, javax.imageio는 Java SE 패키지이므로 jakarta.*로 바꾸면 안 된다.
  • SecurityConfigWebSecurityConfigurerAdapter, authorizeRequests, antMatchers, 체이닝식 csrf()/headers()를 사용한다.
  • Thymeleaf 3.1에서 제거된 #request, #response, #session, #servletContext, th:include 사용처는 현재 템플릿에서 0건이다.
  • 외부 사내 jar (libs/) 는 Java 8 bytecode + javax.servlet/javax.persistence.criteria/외부 XSS 필터 참조로 SB3 그대로 사용 불가. 자체 라이브러리 신규 작성으로 전면 교체 (운영 결정권자 결정 2026-05-08): wellsa-commons (전사 코어) + irosafe-shred-commons (도메인 특화) 2층 구조. SB3.3 + Java 21 + jakarta 기반 신규 작성.

2. 의존성 호환 매트릭스

의존성현재SB3.3 / Java17 후보판정조치
Spring Boot Gradle Plugin2.5.23.3.13 OSS, 또는 Enterprise 3.3.16+High먼저 2.7.18 중간 경유 후 3.3.x로 올린다. io.spring.dependency-management1.1.7 이상 또는 Boot plugin BOM에 위임.
Java1.821Highjava { toolchain { languageVersion = JavaLanguageVersion.of(21) } }로 고정. virtual threads + Loom 활용 (spring.threads.virtual.enabled=true).
MyBatis Spring Boot Starter2.2.03.0.5HighMyBatis 공식 표에서 3.0 라인은 Spring Boot 3.2-3.5 + Java 17. 4.0.x는 Boot 4 전용이므로 쓰지 않는다.
Spring Data EnversBoot 2.5 BOMBoot 3.3 BOM-managed Spring Data 2024.0.xHigh명시 버전 없이 BOM에 맡긴다. 모든 entity/repository의 javax.persistencejakarta.persistence로 변환하고 Envers history workflow를 회귀 테스트한다.
ThymeleafBoot 2.5 관리 3.0.xBoot 3.3 BOM 3.1.3.RELEASEMediumstarter는 버전 제거. thymeleaf-layout-dialect는 Boot 3.3 BOM 3.3.0.
Thymeleaf Spring Security extrasspringsecurity5thymeleaf-extras-springsecurity6Mediumartifact 교체. 템플릿의 sec:* 동작을 로그인/권한별로 확인.
lucy-xss-servlet2.0.0대체 필요High최신 2.0.1javax.servlet:servlet-api:2.5 기반. Boot 3/Tomcat 10의 jakarta.servlet와 호환되지 않는다. 제거 후 자체 OncePerRequestFilter 또는 OWASP Java HTML Sanitizer 기반 whitelist sanitizing으로 전환.
JJWT0.11.20.12.7 안정 후보, 0.13.0 최신Low현재 실제 사용은 주석뿐이다. JWT 미사용이면 제거, 사용할 계획이면 jjwt-api/impl/jackson 조합으로 갱신하고 새 parser API로 테스트.
JasperReports6.17.06.21.5 저위험, 7.0.6 최신High기존 .jrxml/.jasper가 있어 보고서 회귀가 핵심. 1차는 6.21.5로 PDF 유지 확인, 보안/장기 유지 기준이면 7.0.6 + jasperreports-pdf:7.0.6로 별도 마이그레이션.
iText / lowagie2.1.7직접 의존 제거HighJasperReports 6.21.5는 openpdf를 사용한다. com.lowagie:itext 직접 의존은 제거하고 PDF export는 JasperReports가 끌고 오는 PDF 모듈로 검증.
ZXing3.4.13.5.4LowJava 17과 충돌 가능성 낮음. barcode 생성 샘플로 회귀 테스트.
Apache POI5.0.05.5.1Mediumpoipoi-ooxml을 같은 버전으로 올린다. Excel upload/download, 대용량 파일, 한글 파일명 response header 확인.
MariaDB driverBOM/runtime implicitBoot 3.3 BOM 3.3.4 또는 최신 3.5.xMedium우선 BOM 버전 사용. DB timezone/characterEncoding URL과 Hibernate 6 dialect 자동 감지를 확인.
Logback1.2.3 명시Boot 3.3 BOM 1.5.xMedium명시 override 제거. Boot 3 / SLF4J 2와 맞춘다.
sgis-common-frame.jarflat jar재빌드 또는 소스 편입Highjar 내부가 javax.*와 Lucy XSS에 묶여 있으므로 Boot 3 compileClasspath로 재빌드해야 한다.

3. Breaking changes

3.1 javax.* to jakarta.*

Spring Boot 3는 Spring Framework 6 / Jakarta EE 9+ 기반이다. 아래는 일괄 전환 대상이다.

  • javax.servlet.* -> jakarta.servlet.*
  • javax.persistence.* -> jakarta.persistence.*
  • javax.validation.* -> jakarta.validation.*
  • javax.transaction.* -> jakarta.transaction.* 또는 Spring의 org.springframework.transaction.annotation.Transactional

주의:

  • javax.sql.DataSource, javax.net.ssl.*, javax.imageio.*는 Java SE라 유지한다.
  • sgis-common-frame.jar 내부의 javax.persistence.criteria.*는 소스가 없으면 OpenRewrite 대상이 아니다. jar를 소스화하거나 새 모듈로 재빌드해야 한다.

3.2 Spring Security 6

현재 SecurityConfig는 제거된 WebSecurityConfigurerAdapter 기반이다.

필수 전환:

  • extends WebSecurityConfigurerAdapter 제거.
  • SecurityFilterChain @Bean으로 전환.
  • 정적 리소스 ignore는 WebSecurityCustomizer 또는 permitAll로 분리.
  • authorizeRequests() -> authorizeHttpRequests().
  • antMatchers() -> requestMatchers().
  • http.csrf(), http.headers() 등은 lambda DSL로 전환.
  • AuthenticationManagerBuilder 직접 override 대신 UserDetailsService, PasswordEncoder, 필요 시 AuthenticationProvider bean으로 구성.

3.3 Thymeleaf 3.1

Thymeleaf 3.1은 Spring 6용 thymeleaf-spring6와 Spring Security 6용 extras를 사용한다. 또한 #request, #response, #session, #servletContext expression utility object가 제거됐다.

현재 템플릿 스캔에서는 제거 대상 expression 사용처가 없었다. 그래도 로그인/권한별 화면 렌더링에서 sec:*, layout dialect, fragment include 동작을 확인해야 한다.

3.4 Hibernate 6 / JPA

Boot 3.3 BOM은 Hibernate 6.5 계열이다. 이 프로젝트는 entity import 전환 외에도 아래가 위험하다.

  • spring.jpa.hibernate.naming-strategy: org.hibernate.cfg.EJB3NamingStrategy는 제거 대상이다. 현재 이미 physical-strategy, implicit-strategy가 있으므로 legacy key 제거 후 테이블/컬럼 매핑을 검증한다.
  • Envers audit suffix, revision repository, *_HISTORY 테이블 생성/조회가 Hibernate 6에서 그대로 동작하는지 별도 테스트한다.
  • ddl-auto: update는 마이그레이션 검증 중에는 위험하므로 staging DB snapshot에서만 사용하고 운영 전에는 DDL diff를 고정한다.

4. lucy-xss-servlet 대체안

Lucy XSS Servlet Filter는 javax.servlet 2.5 기반이고 Maven Central 최신도 2019년 2.0.1에 머물러 있다. Boot 3에서는 다음 중 하나로 대체한다.

대안권장도설명
출력 escaping 유지 + 입력 whitelist sanitizing높음Thymeleaf 기본 escaping을 유지하고, rich text/메모/주소 등 HTML 허용 필드만 OWASP Java HTML Sanitizer 같은 whitelist sanitizing 적용.
자체 OncePerRequestFilter + HttpServletRequestWrapper중간기존 Lucy처럼 전역 request parameter를 감싸려면 jakarta.servlet 기반 wrapper를 직접 구현. 단 모든 입력을 HTML escape하면 검색/비밀번호/JSON payload가 깨질 수 있다.
Lucy fork 후 jakarta 변환낮음단기 호환은 가능하지만 유지보수 책임이 생긴다. sgis-common-frame.jar 내부 XssConfig도 같이 제거/재빌드해야 한다.
최소 구현 방향:
  • com.navercorp.lucy:lucy-xss-servlet 제거.
  • src/main/resources/lucy-xss-servlet-filter-rule.xml, luxy-xss-sax.xml는 archive 처리.
  • OncePerRequestFilterPOST form-urlencoded/multipart form field에만 제한 적용.
  • HTML 허용 필드와 plain text 필드를 분리한다.
  • W1/W2/W3에서 <script>, event handler, encoded payload, 정상 한글/특수문자 입력을 함께 테스트한다.

5. sgis-common-frame.jar 호환 검증 절차

현재 jar는 src/main/resources/libs/sgis-common-frame.jar 하나뿐이고 소스가 없다. 내부 클래스는 전부 Java 8 bytecode지만 다음 참조가 확인됐다.

  • javax.servlet.Filter, javax.servlet.http.HttpServletRequest/Response
  • javax.persistence.criteria.*
  • com.navercorp.lucy.security.xss.servletfilter.XssEscapeServletFilter
  • Spring Boot 2 era FilterRegistrationBean 설정

검증/전환 순서:

1. jar inventory 고정
bash
   unzip -l src/main/resources/libs/sgis-common-frame.jar
   unzip -p src/main/resources/libs/sgis-common-frame.jar '*.class' | strings | rg 'javax/|com/navercorp/lucy|org/springframework'
   
2. JDK 17 설치 후 의존성 분석
bash
   jdeps --multi-release 17 --ignore-missing-deps --recursive src/main/resources/libs/sgis-common-frame.jar
   

3. 소스 확보 또는 decompile 후 별도 모듈화
- com.sgisframe.global.utils.specification.SearchSpecsjakarta.persistence.criteria.*로 전환.
- XssConfig는 제거하거나 새 XSS filter로 재작성.
- FileMgmtUtil, BarcodeMgmtUtil, datasource/config 클래스는 Boot 3 compileClasspath에서 재컴파일.

4. flatDir 제거
- flatDir + implementation name: 'sgis-common-frame' 대신 buildSrc, includedBuild, 또는 내부 Maven artifact로 관리.

5. compile 검증
bash
   ./gradlew clean compileJava --stacktrace
   ./gradlew dependencyInsight --dependency sgis-common-frame
   

6. OpenRewrite recipe 목록

권장 실행은 feature/sb3-java17-migration 같은 전용 브랜치에서 datatable export를 켠 뒤 단계별 commit으로 나눈다.

1. Java 17 준비
- org.openrewrite.java.migrate.UpgradeToJava17

2. Spring Boot 2.5 -> 2.7 중간 경유
- org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7

3. Spring Boot 3 기본 전환
- org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0
- org.openrewrite.java.spring.boot3.SpringBootProperties_3_0

4. Jakarta namespace
- org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta

5. Spring Security 6
- org.openrewrite.java.spring.security6.UpgradeSpringSecurity_6_0

6. 수동 후속
- SecurityConfig lambda DSL 정리.
- sgis-common-frame.jar 소스화/재빌드.
- Lucy XSS 제거 및 대체 filter 추가.
- JasperReports .jrxml 재컴파일.
- BootWar archiveName -> archiveFileName 정리.

예시 Gradle init-script 방식:

groovy
initscript {
    repositories { maven { url "https://plugins.gradle.org/m2" } }
    dependencies { classpath("org.openrewrite:plugin:7.32.1") }
}
rootProject {
    plugins.apply(org.openrewrite.gradle.RewritePlugin)
    repositories { mavenCentral() }
    dependencies {
        rewrite("org.openrewrite.recipe:rewrite-spring:6.30.3")
        rewrite("org.openrewrite.recipe:rewrite-migrate-java:latest.release")
    }
    rewrite {
        activeRecipe("org.openrewrite.java.migrate.UpgradeToJava17")
        activeRecipe("org.openrewrite.java.spring.boot2.UpgradeSpringBoot_2_7")
        activeRecipe("org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_0")
        activeRecipe("org.openrewrite.java.migrate.jakarta.JavaxMigrationToJakarta")
        activeRecipe("org.openrewrite.java.spring.security6.UpgradeSpringSecurity_6_0")
        setExportDatatables(true)
    }
}

7. 회귀 테스트 핵심 워크플로

W1. 인증/세션/권한

목표: Spring Security 6 전환 후 기존 운영 화면 접근 정책 유지.

  • /login/loginForm 렌더링.
  • /login/doLogin 성공/실패 handler 확인.
  • SUPER, ADMIN, USER 역할별 /adm/, /common/admMain, /common/frnMain, /frn/ 접근.
  • 중복 로그인, session timeout, invalid session, logout cookie 삭제.
  • CSRF token cookie와 form submit 확인.

W2. 파쇄 운영 핵심 CRUD

목표: JPA/Hibernate 6, Envers, MyBatis, DB schema 영향 검증.

  • 고객/지점/계약 등록 및 수정.
  • 파쇄 신청/작업 등록, console matching, schedule 변경.
  • Envers RevisionRepository 조회 및 *_HISTORY 테이블 기록.
  • MyBatis mapper SQL 3종(SCHEDULE_SQL.xml, SAMPLE_SQL.xml, STATISTICS_SQL.xml) 조회.
  • MariaDB timezone, 한글 검색, pagination, Specification join 조건 확인.

W3. 파일/리포트/외부 연동

목표: POI/Jasper/ZXing/파일 다운로드/알림톡 회귀 확인.

  • Excel upload/download: .xls, .xlsx, 한글 파일명, 대용량 row.
  • Jasper PDF: src/main/resources/ireport/*.jrxml 컴파일, 기존 .jasper 재생성, PDF layout diff.
  • Barcode 생성/인쇄 화면: ZXing output 확인.
  • 파일 upload/download/zip, 이미지 preview.
  • Kakao 알림톡 token/send/result polling은 sandbox key 또는 mock server로 분리 테스트.
  • XSS payload 입력 후 저장/조회/다운로드 화면에서 escaping 확인.

8. 단계별 실행 순서와 위험도

단계작업위험도완료 기준
0JDK 17 설치, baseline ./gradlew clean test 확보Medium현재 Boot 2.5 상태에서 빌드/테스트 실패 목록 고정
1Spring Boot 2.7.18 + Java 17 중간 경유Highjavax.* 상태로 Java 17 compile/runtime 이슈 선제 제거
2OpenRewrite Java/Jakarta/SB3 recipe 실행High자동 diff를 compile 단위로 분리 commit
3Gradle/Boot build 정리MediumBoot 3.3.x, Gradle plugin, archiveFileName, BOM 의존성 정리
4sgis-common-frame.jar 소스화/재빌드Highjar 내부 javax.* 제거, Boot 3 compile 성공
5Security 6 수동 마이그레이션HighW1 통과
6Lucy XSS 제거 및 대체 filter 적용High정상 입력 보존 + XSS payload 차단/escaping 검증
7Jasper/POI/ZXing 업그레이드MediumW3 PDF/Excel/barcode 결과물 diff 승인
8Hibernate 6/Envers/DB 검증HighW2 통과, DDL diff 승인
9staging WAR 배포 smokeHighW1/W2/W3 staging 통과, rollback artifact 준비

9. 1차 build.gradle 목표안

실제 적용 전용 브랜치에서 아래 방향으로 정리한다.

groovy
plugins {
    id 'org.springframework.boot' version '3.3.13'
    id 'io.spring.dependency-management' version '1.1.7'
    id 'java'
    id 'war'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

bootWar {
    archiveFileName = "1472SHRED_DEPLOY.war"
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.5'
    implementation 'org.springframework.data:spring-data-envers'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-quartz'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-validation'

    implementation 'org.apache.poi:poi:5.5.1'
    implementation 'org.apache.poi:poi-ooxml:5.5.1'
    implementation 'net.sf.jasperreports:jasperreports:6.21.5'
    implementation 'com.google.zxing:core:3.5.4'
    implementation 'com.google.zxing:javase:3.5.4'

    implementation 'org.modelmapper:modelmapper:3.2.6'
    implementation 'org.apache.httpcomponents.client5:httpclient5'
    implementation 'org.json:json:20250517'

    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}

보류/삭제 후보:

  • com.navercorp.lucy:lucy-xss-servlet: 삭제.
  • com.lowagie:itext: 삭제.
  • ch.qos.logback:*: 명시 버전 삭제 후 Boot BOM 사용.
  • flatDir + sgis-common-frame.jar: 소스화/내부 artifact 전환 후 삭제.
  • io.jsonwebtoken:*: 현재 미사용이면 삭제, JWT 도입 시 별도 security task로 갱신.

10. 출처

  • Spring Boot 3.3 system requirements: https://docs.enterprise.spring.io/spring-boot/system-requirements.html
  • Spring Boot Maven Central metadata: https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/maven-metadata.xml
  • Spring Boot 3.3.13 dependency BOM: https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/3.3.13/spring-boot-dependencies-3.3.13.pom
  • MyBatis Spring Boot Starter requirements: https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
  • Thymeleaf 3.1 migration notes: https://www.thymeleaf.org/doc/articles/thymeleaf31whatsnew.html
  • Spring Security migration note for SecurityFilterChain: https://docs.enterprise.spring.io/spring-security/reference/5.8-SNAPSHOT/migration/servlet/config.html
  • OpenRewrite Spring Boot 3 recipe: https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot_3_0
  • OpenRewrite Spring Boot properties recipe: https://docs.openrewrite.org/recipes/java/spring/boot3/springbootproperties_3_0
  • OpenRewrite Spring Security 6 recipe: https://docs.openrewrite.org/recipes/java/spring/security6/upgradespringsecurity_6_0
  • OpenRewrite Jakarta recipe catalog: https://docs.openrewrite.org/reference/recipes-by-tag
  • Maven Central metadata: JJWT, JasperReports, JasperReports PDF, Apache POI, ZXing, Lucy XSS Servlet.
  • JasperReports 7.0.0 release notes / module split: https://sourceforge.net/projects/jasperreports/files/jasperreports/JasperReports%207.0.0/
📜 이전 버전 1건
  1. 버전 1 · Spring Boot 3 / Java 21 마이그레이션 플랜 · 2026. 6. 8. PM 12:28 KST

📗 운영 가이드 3

📗 운영 가이드 Phase E 데이터 마이그 운영가이드 Phase E 좁힘 ETL — 운영 ILSA DB (system1472) 에서 협력사·계약·지점을 신모델로 dry-run → apply.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/07_진행/01_PhaseE_운영가이드.md

Phase E 좁힘 ETL — 운영 ILSA DB (system1472) 에서 협력사·계약·지점을 신모델로 dry-run → apply.

Phase E — 데이터 마이그 운영 가이드

작성: 2026-06-06 KST · 좁힘 ETL (협력사 + 계약 + 지점)

0. 사전 조건

1. 신모델 DB (irosafe_shred) 가 V1~V6 Flyway migration 완료 상태.
2. legacy ILSA DB 에 read-only 계정 발급 — SELECT 권한만.
3. 두 DB 간 네트워크 연결 가능 (또는 ETL 서버에서 양쪽 reachable).

1. 실행 모드

모드목적결과
dry-run검증. 전체 row 처리하지만 트랜잭션 rollback.로그에 count + 매핑 실패 출력
apply실제 commit. 1회 실행.INSERT IGNORE 로 idempotent 보장

2. 실행 명령

bash
# dry-run
java -jar shred-backend.jar \
  --spring.profiles.active=migrate \
  --migration.legacy.url='jdbc:mariadb://system1472.sldb.iwinv.net:3306/ILSA_SHREDDING?useSSL=false' \
  --migration.legacy.user=READONLY \
  --migration.legacy.password='***' \
  --migration.mode=dry-run

# apply
java -jar shred-backend.jar \
  --spring.profiles.active=migrate \
  --migration.legacy.url='jdbc:mariadb://...' \
  --migration.legacy.user=READONLY \
  --migration.legacy.password='***' \
  --migration.mode=apply

3. 마이그 대상 (좁힘)

1. 협력사SSF_SUBCONTRACTOR_MANAGEMENTsubcontractor
- 자연키: code = SUBCONTRACTOR_ID, business_number = normalized BUSINESS_NUMBER
- legacy_subcontractor_seq = SUBCONTRACTOR_SEQ 보존
- 상태 매핑: A/ACTIVE → ACTIVE, S → SUSPENDED, C → CLOSED
2. 계약SSF_CONTRACT_MANAGEMENTcontract
- 트랙 결정: IS_ANNUAL='Y' → RECURRING, else ONE_CALL
- 이름 prefix: [정기] / [원콜]
- legacy_contract_id = CONTRACT_ID
- 증명서 매핑: C1210000~4 → YEARLY/ONE_TIME/COWAY/AH/HDD
3. 지점SSF_BRANCH_OFFICE_MANAGEMENTbranch_office
- contract_id FK: legacy CONTRACT_ID → 신규 contract.id 조회
- subcontractor_id FK: legacy SUBCONTRACTOR_ID → 신규 subcontractor.id 조회
- legacy_branch_office_id = BRANCH_OFFICE_ID

4. 검증 SQL (apply 후)

sql
-- count 비교
SELECT 'legacy.subcontractor' src, COUNT(*) cnt FROM legacy_link.SSF_SUBCONTRACTOR_MANAGEMENT
UNION SELECT 'new.subcontractor', COUNT(*) FROM irosafe_shred.subcontractor
UNION SELECT 'legacy.contract', COUNT(*) FROM legacy_link.SSF_CONTRACT_MANAGEMENT
UNION SELECT 'new.contract', COUNT(*) FROM irosafe_shred.contract
UNION SELECT 'legacy.branch', COUNT(*) FROM legacy_link.SSF_BRANCH_OFFICE_MANAGEMENT
UNION SELECT 'new.branch', COUNT(*) FROM irosafe_shred.branch_office;

-- 누락 detect — 신모델에 옮겨지지 않은 leg row
SELECT l.SUBCONTRACTOR_ID, l.SUBCONTRACTOR_NAME
FROM legacy_link.SSF_SUBCONTRACTOR_MANAGEMENT l
LEFT JOIN irosafe_shred.subcontractor n
  ON n.legacy_subcontractor_seq = l.SUBCONTRACTOR_SEQ
WHERE n.id IS NULL;

-- 계약 ↔ 지점 FK 매칭률
SELECT
  COUNT(*) AS total_branches,
  SUM(CASE WHEN contract_id IS NOT NULL THEN 1 ELSE 0 END) AS branches_with_contract,
  SUM(CASE WHEN subcontractor_id IS NOT NULL THEN 1 ELSE 0 END) AS branches_with_partner
FROM irosafe_shred.branch_office;

5. 매핑 실패 처리

  • legacy row 의 CONTRACT_ID 가 신규 contract 에 없는 경우 → branch_office.contract_id = NULL
  • SUBCONTRACTOR_ID 매칭 실패 → branch_office.subcontractor_id = NULL
  • 운영자 staging 검토 (TODO: migration_legacy_ref 테이블 — Phase E2)

6. 롤백 시나리오

apply 후 문제 발견 시:
1. Flyway 로 새 migration V99__rollback_phaseE.sql 추가
2. DELETE FROM contract WHERE legacy_contract_id IS NOT NULL
3. 동일 패턴으로 branch_office, subcontractor
4. 또는 신모델 DB 전체 drop & V1~V6 재적용 후 다시 apply

7. MVP 외 (Phase E2 — 7월)

  • 사용자(member), 콘솔/바코드, 증명서, 작업 이력 풀 마이그
  • migration_legacy_ref 운영자 staging 검토 테이블
  • 잔여 컬럼 (created_by, updated_by) 사용자 매핑 후 backfill
📜 이전 버전 1건
  1. 버전 1 · Phase E 데이터 마이그 운영가이드 · 2026. 6. 8. PM 2:12 KST
📗 운영 가이드 테스트 체크리스트 — 141 PASS / 0 FAIL 테스트 결과 — 단위 71 + 로컬 e2e 35 + 외부 dev-shred e2e 35 = 총 141 PASS / 0 FAIL (Mockito + Playwrig…
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/07_진행/02_테스트_체크리스트.md

테스트 결과 — 단위 71 + 로컬 e2e 35 + 외부 dev-shred e2e 35 = 총 141 PASS / 0 FAIL (Mockito + Playwright).

테스트 체크리스트 · 현재 결과 (2026-06-08 KST)

141 PASS / 0 FAIL · 단위 71 + 로컬 e2e 35 + 외부 dev-shred e2e 35

1. 단위테스트 (71 PASS · ./gradlew test --tests "*Test" 12s)

클래스케이스비고
LegacyMappersTest36Parameterized — normalizeBiz / Partner/Branch/Contract status / cert / shred / 운영 C-code
JwtServiceTest6발급 / parseClaims / TTL / 서명 / issuer / 깨진 토큰
ExcelStatusLabelTest65 ScheduleStatus 한글 + null
AuthServiceTest5성공 / PWD 불일치 / unknown / SUSPENDED / LEFT + audit
AuthorityResolverTest4ROLE_* + permission codes (합집합/중복 제거)
ScheduleServiceTest4reassign primary 변경 + audit / bulkStatus
ContractExpiryJobTest4autoExtend RECURRING +1y / EXPIRED 전환 / autoExtend 제외 / 미래 no-op
ContractControllerTest3트랙별 default 보정 (RECURRING +1y, ONE_CALL autoExtend=false, 명시 endedOn 보존)
CodeControllerTest3duplicate 거부 + create defaults + update
합계710 fail / 0 error

2. Playwright e2e (35 PASS · 12s)

apps/frontend/e2e/ · PLAYWRIGHT_BASE_URL env 로 로컬/외부 양쪽 실행

UI 시나리오 19 (01-auth-and-dashboard.spec.ts)

ID시나리오
E-001 / 001b로그인 성공 / 실패
E-002 / 002b다크모드 토글 / 순환
E-003 ~ E-008W01~W08 화면 데이터 + 검색/필터/탭/엑셀버튼
E-009증명서 필터 변경
E-010일일업무 카드 + 날짜 변경
E-011코드 마스터 REGION + ITEM + CERT 탭
E-012ContractDetail 주소 검색 모달
E-013사이드바 8 메뉴 순회
E-014로그아웃 → /login redirect
E-015미인증 ProtectedRoute → /login

API 시나리오 16 (02-api-endpoints.spec.ts)

ID시나리오
E-A01 / A02/actuator/health · /v3/api-docs paths >= 30
E-A03 / A15인증 차단 (no token / invalid token)
E-A04 ~ A09contracts / subcontractors / schedules / consoles / dailywork list
E-A10 / A11 / A16Code categories + REGION 7 + CRUD round-trip
E-A12 ~ A14Excel 3 endpoint xlsx OOXML magic

3. 외부 도메인 e2e (35 PASS · 12s · 2026-06-08)

bash
PLAYWRIGHT_BASE_URL=https://dev-shred.irosafe.com npx playwright test

대상: Cloudflare Tunnel + nginx + 실 backend 8081 + MariaDB 풀스택. 운영 환경과 가장 가까운 검증.

4. 통합테스트 (작성 9건 · Docker 필요)

  • ApiIntegrationTest — login / swagger / contracts / codes / excel / CRUD 9 시나리오
  • FlywaySchemaIntegrationTest — V1~V8 + role/permission 카운트
  • 실행 환경: 내부 호스트 runner 등록 후 자동 (현재 GitLab CI 단순화로 미실행)

5. 수용테스트 (Phase G3 시연 대기)

ID시나리오운영자
A-001사무실 계약 등록 → 작업자 캘린더 표시사용자
A-002정기 본사 + 지점 5 → 25일 배치 → 일정 생성사용자
A-003작업자 일일업무 수거완료 → 캘린더 색상 변경작업자 1
A-004증명서 5종 발급 + PDF 출력사용자

6. 결과서

  • xlsx: docs/09_테스트/테스트결과서_irosafe_shred.xlsx (5 시트)
  • pptx: docs/09_테스트/테스트결과서_irosafe_shred.pptx (e2e 스크린샷 10장 + Swagger + 비교 슬라이드)
  • 스크린샷: docs/09_테스트/스크린샷/ (28장)
📗 운영 가이드 마이그 매핑 매트릭스 — 계약/지점/일정 횟수/협력사 좁힘 ETL 작성: 2026-06-06 KST · MVP 6/30 (D-24)
마지막 갱신 2026. 6. 8. PM 12:28 KST · docs/03_DB재설계/06_마이그_매핑.md

좁힘 마이그 매핑 매트릭스 (v5)

작성: 2026-06-06 KST · MVP 6/30 (D-24)
선행: ERD v0.5 메인 (01_신스키마_ERD_v0.5.md) + 보강 (02_ERD_v0.5_보강.md)
대상 데이터: 운영 DB ILSA_SHREDDING (system1472.sldb.iwinv.net) → 신모델 (자체 스키마)

0. 마이그 정합 원칙

1. 자연키 보존 — 레거시 PK/코드를 신모델 UNIQUE 컬럼 + migration_legacy_ref 매핑
2. 변환 못 하면 격리migration_legacy_ref.status='REVIEW_NEEDED' + 운영자 staging 검토
3. 마이그 범위 한정 (4 도메인) — 계약 + 지점 + 일정 횟수 + 협력사 (B8)
4. 레거시 보조 보존 — 신모델 운영 중에도 추적 가능

1. 좁힘 마이그 범위

#신모델 도메인레거시 테이블 (ILSA)row 수자연키
1partner (협력사)SSF_SUBCONTRACTOR_MANAGEMENTTBDSUBCONTRACTOR_ID / business_no
2partner_branch (지점)SSF_BRANCH_OFFICE_MANAGEMENTTBDBRANCH_OFFICE_ID code
3recurring_contract_group / one_call_contract / recurring_contract_site (계약)SSF_CONTRACT_MANAGEMENTTBDCONTRACT_ID code
4recurring_schedule_rule (일정 횟수)SSF_SCHEDULE_MANAGEMENT 정제횟수만
MVP 외 (Phase E 후 7월): 사용자(member), 콘솔, 증명서, 작업 이력 풀 마이그.

2. 컬럼별 매핑 표

2.1 협력사 — SSF_SUBCONTRACTOR_MANAGEMENTpartner

레거시 컬럼신모델 컬럼변환
SUBCONTRACTOR_SEQpartner.legacy_subcontractor_seq그대로
SUBCONTRACTOR_IDpartner.code UNIQUE그대로 (자연키)
SUBCONTRACTOR_NAMEpartner.nametrim
BUSINESS_NUMBERpartner.business_no UNIQUE999-99-999999999999999 (정규화 후 UNIQUE 보존)
PHONEpartner.phone010-XXXX-XXXX 형식
ADDRESSpartner.address_main
ZIPCODEpartner.address_zip
AREA_CODEpartner.region_code FK→system.codecategory=REGION
STATUSpartner.statusC-code → ACTIVE/SUSPENDED/CLOSED ENUM (mapping 표 §3)
APPROVAL_STATUS(마이그 X — 신모델 사용 X)
INS_DATE / UPD_DATEcreated_at / updated_atKST → UTC
INS_ID / UPD_IDcreated_by / updated_bylogin_id → account.id 매핑 (사용자 마이그 후)
partner.color_hexNULL 시 시스템 자동 할당 (palette 7색 round-robin)

2.2 지점 — SSF_BRANCH_OFFICE_MANAGEMENTpartner_branch

레거시신모델변환
BRANCH_OFFICE_SEQpartner_branch.legacy_branch_seq그대로
BRANCH_OFFICE_IDpartner_branch.code (partner_id+code UNIQUE)
CONTRACT_ID(정기) partner_id 매핑 시 사용 — 본사 SUBCONTRACTOR 추출
BRANCH_OFFICE_NAMEpartner_branch.name
MANAGER_NAMEpartner_contact.name (별도 row 생성)
MANAGER_PHONEpartner_contact.phone
ADDRESS / ZIPCODE / AREA_CODE동일 패턴
OPERATION_CYCLE_VALUErecurring_schedule_rule.month_count (별도 row)unit=MONTH 일 때
OPERATION_CYCLE_UNIT(rule 생성 시 사용)MONTH/WEEK 두 분리
REPETITION_FORM(rule 의 preferred_weekdays/time 힌트 — 가능하면)
STATUS / APPROVAL_STATUSC-code → ENUM
SUBCONTRACTOR_IDpartner_id FK(legacy mapping ref 통해)

2.3 계약 — SSF_CONTRACT_MANAGEMENT → 트랙별 분리

#### (a) 원콜 (IS_ANNUAL=N, IS_BRANCH=N)
one_call_contract

레거시신모델
CONTRACT_IDone_call_contract.contract_no (OC- prefix 가능, 형식 변환)
CONTRACT_NAMEone_call_contract.name (auto prefix [원콜])
COMPANY_NAMEcustomer_name
BUSINESS_NUMBERbusiness_no
STARTED_ONwork_date (원콜은 단일 일자)
CRUSH_OPTIONshred_option (SITE→ON_SITE, WAREHOUSE→INTAKE)
CERTIFICATE_TYPEC-code → ENUM (C1210000→YEARLY 등, §3 mapping)
STATUSC-code → ENUM (DRAFT→/APPROVED→CONTRACT/TERMINATED→CANCELLED)
#### (b) 정기 본사 (IS_ANNUAL=Y, IS_BRANCH=Y) → recurring_contract_group
레거시신모델
CONTRACT_IDcode
COMPANY_NAMEname
BUSINESS_NUMBERbusiness_no
ADDRESS / ZIPCODE본사 주소
#### (c) 정기 지점 — SSF_BRANCH_OFFICE_MANAGEMENT 의 contract 연결 → recurring_contract_site
레거시신모델
BRANCH_OFFICE.CONTRACT_IDrecurring_contract_site.group_id (legacy_ref 매핑 거침)
BRANCH_OFFICE_IDcontract_no (자연키 보존, 형식 RC-{group_code}-NNN)
SETUP_STARTED_ONcontract_start_date
VISIT_ENDS_ONcontract_end_date (NULL 시 = contract_start_date + 1년 default)
auto_extend=TRUE (default, 회의 결정)
SUBCONTRACTOR_IDpartner_id (legacy_ref 매핑)

2.4 일정 횟수 — SSF_SCHEDULE_MANAGEMENTrecurring_schedule_rule (정제)

PDF/회의 결정: 세부 일정 마이그 X. "주 몇 회" 횟수만 정제.

변환설명
그룹화같은 BRANCH_OFFICE_ID + 월 단위 작업 횟수 집계
month_count 계산직전 12개월 평균 작업 횟수
preferred_weekdays가장 빈번한 요일 (TOP 2)
preferred_time_windowVISIT_START_TIME 분포 → MORNING/AFTERNOON/EVENING
effective_from마이그 시점
→ 신모델 매월 25일 배치가 본 rule 기준으로 다음 달 schedule 생성. 사람이 SOP 화면에서 날짜 조정.

3. 코드 마스터 매핑 (SSF_CMMN_CODE → 신모델 ENUM)

레거시 코드의미신모델 ENUM
자루상태 (CRUSHER_STATUS)
C1100000자루상태 (UPPER)(parent) — sub-code 만 사용
C1120000수거console_bag_history.event='COLLECTED' 또는 status='IN_USE'
(그 외 sub-code TBD)
파쇄증명서 종류 (CERTIFICATE_TYPE)
C1210000연간계약용certificate.type='YEARLY'
C1220000단건계약용certificate.type='ONE_TIME'
C1230000코웨이전용certificate.type='COWAY'
C1240000AH전용certificate.type='AH'
C1250000HDD용certificate.type='HDD'
파쇄증명서 발급상태 (STATUS)
C9010000발급certificate.status='ISSUED'
C9020000미발급certificate.status='UNISSUED'
콘솔 상태 (STATUS)
C7020000배정console.status='DEPLOYED'
(그 외 sub-code TBD)
승인 상태 (APPROVAL_STATUS)
C2010000승인요청(마이그 X — 신모델 사용 X, 모두 APPROVED 변환)
계약 상태 (CONTRACT.STATUS)
DRAFT / APPROVED / ACTIVEcontract.status='CONTRACT'
TERMINATED / EXPIREDcontract.status='CANCELLED'/EXPIRED'

4. 운영자 확인 5건 → 마이그 정책

#항목결정 (마이그 시)
#1Crm1472 AWS IP 13.124.4.31자체 CRM. 신규 시스템 /crm/save 호환 endpoint 유지. controller 위치는 irosafe-shred-commons/api/crm
#2password_hashbcrypt 확정 (BCryptPasswordEncoder). 해시 그대로 옮김 — 재설정 X
#3CRUSHER_STATUS='C1100000' 1건데이터 결함. migration_legacy_ref.status='REVIEW_NEEDED' — CS2207 격리
#4certificate 50% 미발급운영 흐름 정상. ENUM ISSUED/UNISSUED 그대로 마이그
#5WORK_TYPE='kg' 687건중량형 단위. unit='kg', quantity=WORK_WEIGHT 값 변환

5. ETL 실행 순서


Phase E1 — partner (의존: 없음)
Phase E2 — partner_branch + partner_contact (의존: partner)
Phase E3 — recurring_contract_group (정기 본사)
Phase E4 — recurring_contract_site (의존: group + partner + partner_branch)
Phase E5 — one_call_contract
Phase E6 — recurring_schedule_rule (의존: site, 12개월 집계)
Phase E7 — 검증 (count·체크섬·샘플 비교)

각 단계마다 migration_legacy_ref row 동시 INSERT (entity_type 별).

6. 검증 쿼리 (Phase E7)

sql
-- 협력사 count 일치
SELECT COUNT(*) AS legacy FROM SSF_SUBCONTRACTOR_MANAGEMENT WHERE STATUS != 'TERMINATED';
SELECT COUNT(*) AS new FROM partner;
-- ↑ 차이가 있으면 폐업 협력사 마이그 정책 재확인

-- 지점 count 일치 + partner 연결 검증
SELECT COUNT(*) FROM partner_branch pb
JOIN migration_legacy_ref m ON m.entity_type='partner_branch' AND m.new_id=pb.id
WHERE m.legacy_pk_value IS NOT NULL;

-- 사업자번호 정합 (UNIQUE)
SELECT business_no, COUNT(*) FROM partner GROUP BY business_no HAVING COUNT(*) > 1;

-- 자연키 보존 검증 (legacy_ref 와 신모델 자연키)
SELECT m.legacy_code, m.new_id, p.code
FROM migration_legacy_ref m JOIN partner p ON p.id=m.new_id
WHERE m.entity_type='partner' AND m.legacy_code != p.code;

7. Staging 격리 정책

다음 row 는 migration_staging_* 로 격리 + 운영자 검토:

케이스격리 사유
business_no 형식 잘못정규화 실패
business_no 중복UNIQUE 위반
CRUSHER_STATUS='C1100000'parent code 이상치
폐업 협력사 (CLOSED)B8: 운영자 검토 후 마이그 여부 결정
작업 횟수 산정 불가 (지점 작업 0건)횟수 정제 결과 0
각 격리 row → migration_legacy_ref.status='REVIEW_NEEDED' + note 명시.

8. 다음 step

  • tui — _data/migration/V_*.sql ETL 스크립트 작성 (본 매핑 표 기반)
  • 리뷰 워커 재검토 (본 매핑 매트릭스 + ERD v0.5.1 통합)
  • Phase E1~E7 실행 순서 확정 + 운영자 검토 staging 흐름 설계
  • 검증 쿼리 자동화 (Flyway repeatable migration 또는 별도 verify 스크립트)

변경 이력

  • v5 (2026-06-06): 신규 작성. 좁힘 범위 (계약+지점+일정 횟수+협력사) + 자연키 보존 + 운영자 확인 5건 반영 + SSF_CMMN_CODE decoding 결과.

⚠️ 알려진 이슈 5

⚠️ 알려진 이슈 갭분석 재판정: 누락 0건 결론 폐기 docs/09테스트/06갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09테스트/07재매칭…
마지막 갱신 2026. 6. 10. AM 10:33 KST · docs/09_테스트/07_재매칭_codex.md

갭분석 재판정

docs/09_테스트/06_갭분석.md의 "누락 0건" 결론은 2026-06-10 PM 전달 UI 원본 확인 후 폐기한다. 최신 판단은 docs/09_테스트/07_재매칭_codex.md를 우선한다.

재판정 요약

구분판단
기존 06 갭분석구현 골격 기준으로 과대 충족 판정이 섞임
재매칭 결과신규 누락 7건, 부분/과대 6건, 정책충돌/확인 필요 4건
PM 최신 UI 반영기존 6-sheet가 아니라 20-sheet 확장본이므로 gap 추가 발생

우선 보강 대상

영역현재 판정조치
사용자 관리P0 미완/admin placeholder 제거, member list/role/status/password reset 구현
Calendar routingP0 미완bar/date click에서 schedule list filter로 이동
Bulk/reassign UIP0 부분backend mutation을 UI에 연결, 완료 일정 변경 금지 처리
원콜 세발/입금P0 후보payment/deposit/evidence 최소 모델 반영
Recurring date-confirmP0 부분25일 배치 placeholder와 날짜 확정 workflow 분리
콘솔 매칭 UXP0/P1콘솔번호 규칙, 계약 검색/매칭, QR 생성 타이밍 확정
일일업무관리 상세7월 권고현재 DailyWorkPage와 다른 관리자 운영 일보 도메인으로 분리

근거 문서

  • docs/09_테스트/07_재매칭_codex.md
  • docs/01_요구사항/20260610_PM_전달_UI_반영.md
  • docs/09_테스트/06_갭분석.md v1.1 상단 superseded 경고
⚠️ 알려진 이슈 갭분석 (antigravity 시각) 본 보고서는 단순 기능의 유무만을 확인하는 체크리스트를 넘어, 실제 운영 환경에서의 사용성과 구현체의 무결성을 기준으로 비판적인 3자 갭분석을 수행하였습니다. 백…
마지막 갱신 2026. 6. 9. AM 10:42 KST · docs/09_테스트/06_갭분석_antigravity.md

갭분석 보고서 (Antigravity 워커 분석본)

  • 작성일자: 2026-06-09
  • 분석 주체: Antigravity 코딩 에이전트
  • 분석 범위: 최초 요구사항 v5 (docs/01_요구사항/00_전체방향_v5.md 등) vs 기존 1472 운영 DB/소스 vs 신규 irosafe_shred v5 구현본 (dev-shred.irosafe.com 연동)

1. 개요 및 분석 톤

본 보고서는 단순 기능의 유무만을 확인하는 체크리스트를 넘어, 실제 운영 환경에서의 사용성과 구현체의 무결성을 기준으로 비판적인 3자 갭분석을 수행하였습니다. 백엔드 및 프론트엔드 구현 수준을 정밀 진단하여 실제 현장 시연 및 컷오버 시 발생할 수 있는 잠재 리스크를 식별하는 데 초점을 맞추었습니다.
  • 판정 기준: [충족] (요구사항 완전 구현) · [부분] (일부 구현 또는 한계 존재) · [누락] (미구현 또는 스키마 반영 실패) · [보류] (의도적으로 후속 페이즈로 미룸)

---

2. 3자 갭분석 매트릭스

2-1. 계약 트랙 이원화

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-01원콜·정기 트랙 데이터 구조 분리단일 테이블 구조 및 플래그 제어ContractTrack ENUM 도입, URL/UI 분리[충족]데이터베이스 수준에서 분리가 완료되어 정합성 확보.
R-02원콜: 단발 계약 처리단발 처리 지원 (플래그)원콜 계약 목록 및 상세 화면 제공[충족]단발성 일정 생성 프로세스 정상 작동.
R-03정기: 상위그룹 → 계약(지점) 구조본사-지점간 단순 조인 구조RecurringContractListPage 등 본사 지점 FK 구조화[충족]지점 관리체계 이원화 완료.
R-04매월 25일 다음 달 1달치 자동 등록배치 부재 (수동 등록 추정)RecurringBatchService + @Scheduled 배치 구현[충족]매월 25일 04:00 KST 정상 부팅 및 자동화 스케줄링 충족.
R-05정기 계약 자동 1년 연장로직 없음 (종료일 무한 설정)ContractExpiryJob 03:00 KST 배치 및 연장 로직[충족]만료 시점 +1년 연장 및 EXPIRED 상태 처리 검증 완료.
R-06원콜 세발(세부발주) MVP기능 미확인Controller/Service/Repo 골격만 구현됨[보류]실질적 세부 발주 등록 비즈니스 로직은 Phase F로 이월됨.
R-07Excel 대량 업로드 (정기)SSF_RECURRING 기반 일부 제공RecurringExcelImporter 구현 완료[충족]대량 지점/계약 일괄 파싱 및 이관 검증 완료.

2-2. 일정 캘린더

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-10월·주·일 뷰 스위처별도 SOP 화면 분리단일 SPA 기반 CalendarPage 뷰 전환[충족]UI 일관성 개선.
R-11전체/원콜/정기 필터미확인Track(ALL/ONE_CALL/RECURRING) 필터 제공[충족]리스트 및 달력 필터 연동 완료.
R-12협력사별 컬러 매핑단일 녹색 일색7색 Swatch round-robin 매핑[충족]협력사별 캘린더 일정 시각 구분 기능 충족.
R-13플랫 바 클릭시 필터 리스트 진입미확인ScheduleListPage 라우트 파라미터 연동[충족]달력 바 연동 탐색 정상 작동.
R-14날짜 클릭시 일자 전체 리스트 진입미확인동일한 라우트 및 필터 패턴 적용[충족]정상 작동.
R-15bulk 일정 조작 (변경/수거/삭제)단순 엑셀 다운로드 위주bulk-status / bulk-cancel 백엔드 API 완비[충족]일괄 상태 수정 API 테스트 통과.
R-16동선 정렬 (SOP Pain #1)동선 정렬 기능 전무DailyWork 정렬 select + sort=route 쿼리[충족]2026-06-09 자로 보강이 완료되었으며, 동선 순서 정렬 쿼리 반영 완료.

2-3. 작업자(현장) UX

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-20작업자 1일 캘린더만 노출안드로이드 웹뷰 기반DailyWorkPage 웹 UI 제공, 앱은 후속[부분]모바일 전용 UI가 안정화되지 않았으며 안드로이드 진입은 보류 상태임.
R-21작업자 개인 1달 스케줄표 (Pain #2)기능 부재, 수동 엑셀 배포DailyWorkPage 일/월 뷰 토글 및 month API[충족]2026-06-09 자로 배지 및 상위 3건을 포함하는 월 뷰 보강 완료.
R-225주차 일정 보정 (Pain #3)주차가 밀리거나 누락되는 결함RecurringBatchService가 매월 1일에 일괄 임시(placeholder) 일정을 생성[부분]비판점: 시스템적인 5주차 자동 감지/배정 보정 알고리즘이 부재함. preferredWeekdays 힌트가 데이터베이스에는 정의되어 있으나 배치 생성 시에는 단순히 다음 달 1일로 dummy 일정을 꽂아버려 결국 관리자가 화면에서 수동 드래그/조정을 해야 하므로 현장 공수 발생 가능.
R-23작업자 수거 완료 처리 및 진행률모바일 일부 제공DailyWorkPage 진행률 카드 및 수거완료 API[충족]모바일 환경에서의 작업 종료 mutation 정상 동작.

2-4. 외주·협력사

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-30OBS 협력사 모델 차용SSF_SUBCONTRACTOR 테이블7개 협력사 및 Swatch 색상 정의[부분]비판점: OBS의 핵심인 정산 모델이나 다이나믹 배차 로직은 연동되지 않았고, 단순히 상태 ENUM 및 시각적 Swatch 컬러 연동 수준만 복사해 둔 상태임. 실질적인 외주 제어 한계 존재.
R-31협력사 ↔ 계약 매핑SSF_CONTRACT_RESPONSIBLEcontract_subcontractor 조인 테이블 처리[충족]매핑 무결성 확보.
R-32작업자 ↔ 협력사 소속SSF_MEMBER.subcontractor_idmember.subcontractor_id FK 처리[충족]무결성 제약 충족.

2-5. 콘솔·QR

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-40콘솔 매칭 + QR 생성ZXing 자체 인쇄 (프린터 IP 하드코딩)ConsoleController QR 포맷 엔드포인트 구현[충족]QR 생성 모듈 표준화 완료.
R-41QR 프린트 인프라 협업라벨 프린터 직접 연동하드웨어 프린팅 인프라 대기[보류]영우님 연동 대기 상태로 시스템 골격만 존재.
R-42자루 바코드 + 콘솔 1:N 매핑SSF_CONSOLE_INFO_MANAGEMENTconsole + barcode 1:N 구조 스키마[충족]스키마 수준 무결성 정상.

2-6. 증명서

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-50증명서 5종 분리JasperReports 템플릿 5종CertificateType ENUM 정의[충족]구분 구조 완료.
R-51PDF 출력 기능JasperReports + iText출력 레이어 홀딩 및 보류[보류]Phase G3 이전까지 임시 보류 상태로, 실제 파일 생성/다운로드는 작동하지 않음.

2-7. 코드 관리 + 권한

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-60지역/품목 코드 마스터 관리 UISSF_CMMN_CODE 매직코드CodeMasterPage 웹 UI 제공[충족]관리자 직접 편집 환경 충족.
R-61RBAC 3단계 + 지점명 변경 잠금단순 LEVEL 텍스트13개 세부 권한 매핑 + BRANCH_RENAME 권한 검증[충족]백엔드 Spring Security @PreAuthorize 제약 조건 완비로 요구사항 초과 달성.
R-62사용자 관리SSF_MEMBER 테이블MemberRepository 및 백엔드 API[부분]비판점: 사용자 가입/권한 관리를 위한 프론트엔드 UI가 누락되어 실제 운영자가 신규 멤버를 등록하거나 권한을 설정하려면 DB를 직접 만져야 하는 한계 존재.

2-8. 자동화·인프라

요구 ID요구사항 v5기존 1472 운영신규 v5 구현 상태판정비고 / 비판적 검토 의견
R-70담당자 변경 (땡겨오기) 이력 및 UI1건씩 수동 변경 (Pain #4)ScheduleService.reassign 및 Audit 백엔드 구현[부분]비판점: 백엔드 API와 Audit 로그 적재 로직은 완벽하나, 프론트엔드 UI단에 mutation이 연결되어 있지 않아 화면을 통한 일괄/단일 배정 변경 조작이 불가능함.
R-71주소 검색 팝업미확인카카오 우편번호 모달 적용[충족]주소 입력 생산성 개선.
R-72Excel 다운로드 (이름 누락 방지)일부 정보 누락한글 헤더 + UTF-8 3종 다운로드 구현[충족]주요 데이터 유실 없이 출력 가능.
R-73모바일 안정성 (Pain #7)웹뷰 하이브리드 안정성 에러Phase F로 이월 보류[보류]백엔드 안정화 이후 별도 트랙 진행 예정.
---

3. 핵심 갭 및 보강 우선순위 (Antigravity 제언)

P0 (시연 전 필수 보강)

1. R-70 담당자 변경 (땡겨오기) UI 연결: 백엔드 API가 완비되어 있으므로 프론트엔드 화면단에서 reassign Mutation을 신속히 바인딩하여 땡겨오기 기능이 정상 시연되도록 보강해야 합니다. 2. R-62 사용자 권한 관리 UI 구축: 신규 멤버 등록이나 권한 할당을 수행할 수 있는 관리자 대시보드 UI를 구현하여 DB 수동 쿼리 의존도를 낮춰야 합니다.

P1 (운영 가치 확보)

3. R-22 5주차 일정 보정 고도화: 현재 1일에 dummy로 생성해두는 단순화된 방식은 OP 운영자의 업무 부하를 가중시킵니다. preferredWeekdays나 기존 일정 히스토리를 분석하여 적절한 날짜로 플레이스홀더를 고루 분산 분배하는 로직의 고도화를 제안합니다. 4. R-30 외주 정산 모델 구체화: 단순 Swatch 컬럼 매핑에 그치는 협력사 관리에 정산 및 배차 한계 관리 등을 추가하여 비즈니스 일관성을 충족시켜야 합니다.
⚠️ 알려진 이슈 재매칭 보고서 (antigravity) — 회의록 기반 누락 6건 2026-05-27 일자 회의록 원본 대화 내용(2,263줄)을 전수 분석하여, 최초 기획 문서 및 회의에서 도출되었으나 봇의 1차 갭분석(06갭분석.md)에서 …
마지막 갱신 2026. 6. 9. AM 10:42 KST · docs/09_테스트/07_재매칭_antigravity.md

요구사항 재매칭 보고서 (Antigravity 워커 분석본)

  • 작성일자: 2026-06-09
  • 분석 주체: Antigravity 코딩 에이전트
  • 분석 방법: 2026-05-27 회의록 원본 (20260527_회의.txt) 및 요약본의 세부 맥락 분석 → 봇이 작성한 기존 갭분석 매트릭스(32항목)와의 1:1 대조 및 누락 검출

1. 개요

2026-05-27 일자 회의록 원본 대화 내용(2,263줄)을 전수 분석하여, 최초 기획 문서 및 회의에서 도출되었으나 봇의 1차 갭분석(06_갭분석.md)에서 누락되었거나 백엔드/프론트엔드 설계에서 빠져있던 실질적인 현장 요구사항 및 결정사항을 도출하였습니다.

[분석 결과 요약]

  • 회의록 기반 누락 요구사항 및 기술적 결함 검토 결과, 빠진 요구사항 6건 및 스키마/로직 개선 확인 완료 1건을 최종 발견하였습니다.

---

2. 회의록 기반 요구사항 재매칭 매트릭스

ID출처 (회의록 맥락)요구사항 상세 및 결정사항기존 갭분석 매칭충족 여부비고 / 상세 분석 내용
RE-0120260527_회의.txt (1291~1450라인)지점별 기본 콘솔 수량 디폴트 지정 및 현장 조작 편의성<br>- 지점별 콘솔 수량은 고정적이므로, 수거 QR 스캔 시 디폴트 수량이 자동으로 나타나 현장 수동 조작을 최소화하고 변동 시에만 수정하게 함.없음 (누락)[누락]미구현 상태: 현재 단순 1:N 바코드 매핑 구조만 있고, 지점별 기본 콘솔 수량 설정 및 현장 스캔 시 디폴트 값을 바인딩하여 UI에 표출하는 데이터 모델과 로직이 설계/구현되지 않음.
RE-0220260527_회의.txt (1948~1954라인)파쇄증명서 내 단가 노출 제어 옵션<br>- 파쇄증명서 발급/전달 시 특정 계약 조건이나 고객 요구에 따라 단가 정보를 노출하거나 숨기는 관리자 제어 기능 필요.없음 (누락)[누락]미구현 상태: CertificateType ENUM 및 발급/무효 기능만 존재하며, 증명서 출력 레이아웃 상에서 단가 노출을 토글할 수 있는 메타데이터 모델이 누락됨.
RE-0320260527_회의.txt (2146라인)정기 계약 지점별 입금 등록 및 비용 정산<br>- 정기 계약의 지점별 비용 수령을 관리하기 위해 계약/지점 단위로 입금을 기록하고 정산(수기 세발 매칭) 처리하는 기능 필요.없음 (누락)[누락]미구현 상태: 원콜 계약의 입금 관리나 정기 계약의 Excel 업로드 등은 나와 있으나, 정기 계약의 지점별 입금 등록 및 비용 정산 기능은 데이터 모델에 미반영됨.
RE-0420260527_회의.txt (475~478라인)현장 카드결제 결과 등록 기능<br>- 원콜 단발성 계약 현장 수거 시 모바일 앱이나 현장 태블릿을 통해 카드 결제 여부 및 결과를 직접 입력/확인할 수 있어야 함.R-23 (부분 매칭)[누락]미구현 상태: 결제 수단(카드/현금/공식 등)을 연동하거나 결과를 입력하는 비즈니스 컬럼 및 로직이 현재 백엔드 DailyWork, Schedule 엔티티에 반영되지 않음.
RE-0520260527_회의.txt (41~45라인)외부 내비게이션(Google Map/Tmap) 좌표 연동<br>- 일정 데이터를 기반으로 외부 내비게이션(Google, Tmap 등)에 목적지 좌표를 연동하여 작업자에게 내비게이션 링크를 연동 및 전송해야 함.R-16 (부분 매칭)[누락]미구현 상태: 백엔드 DailyWorkPage 등에 단순히 route 정렬 정적 쿼리만 존재하며, 외부 지도/내비 앱 연동 URL 스킴(카카오내비/Tmap 좌표 전송) 생성 기능은 누락됨.
RE-0620260527_회의.txt (47~51라인, 102~106라인)작업자용 모바일 화면의 시간순 카드 리스트 뷰 전용 UX<br>- 작업자용 화면의 메인은 캘린더 그리드가 아닌 "오늘의 일정" 카드 리스트(시간순 리스트)로 직관적으로 구성하여 가독성 극대화.R-20 (매칭)[부분]부분 구현: 웹 버전 DailyWorkPage에 일일 일정 목록이 노출되지만, 모바일 전용의 직관적인 시간순 카드 리스트 뷰 및 스와이프 등의 작업자 전용 디자인은 안드로이드 분기 보류와 함께 미완성 상태임.
RE-0720260527_회의.txt (대화 맥락)일정 조회 시 미래/과거 일정 짬뽕 현상 방지 필터링<br>- 서초구민점 사례처럼 작업자 화면에 오늘 일정 외에 미래의 다른 일정까지 섞여 보이는 결함을 방지하기 위해 당일 날짜 필터링 보장.R-20 / R-21 (매칭)[충족]해결 완료: 신규 스키마의 Schedule visit_started_on을 DATE 타입으로 정규화하여 DailyWorkController 등에서 당일 날짜 조건식으로 엄격하게 필터링하므로 기술적으로 완벽히 해소됨.
---

3. 결출된 핵심 누락 사항 분석 (빠진 요구사항 6건)

회의록 원본을 전수 검사하여 확인된 6건의 누락 요구사항(RE-01 ~ RE-06)은 현장 작업 효율성 및 과금/정산 정합성에 직접적인 영향을 주는 요소들입니다.

1. 현장 수거 처리 편의성 결여 (RE-01): 디폴트 콘솔 수량이 자동 설정되지 않으면 작업자가 매번 수량을 수동 입력해야 하여 현장 수거 속도가 저하됩니다.
2. 단가 관리 및 노출 통제 부재 (RE-02, RE-03): 파쇄증명서의 단가 제어 기능과 정기 계약의 입금 등록 부재는 차후 고객사와의 정산 정합성 분쟁을 야기할 수 있습니다.
3. 결제 수단 및 내비 연동 누락 (RE-04, RE-05): 현장 결제 기록 미비 및 내비게이션 링킹 부재는 현장 작업자의 모바일 기기 활용 한계를 가져옵니다.

⚠️ 알려진 이슈 기존 ILSA DB 결함 14건 기존 ILSASHREDDING 스키마의 결함 14건 정리 — 신스키마 설계 baseline 입력.
마지막 갱신 2026. 6. 8. PM 2:12 KST · docs/03_DB재설계/00_기존_ILSA_결함.md

기존 ILSA_SHREDDING 스키마의 결함 14건 정리 — 신스키마 설계 baseline 입력.

기존 ILSA_SHREDDING 스키마 결함 정리

갱신 v2 (2026-04-30): 운영 DB dump 다운로드 후 분석. 운영 = 53 테이블 (ddl.sql 38 + 15 추가). work 도메인 (일일 업무일지) 8 테이블 신 발견.

원본 분석 baseline. 신스키마 irosafe_shred 설계 입력.

데이터량 단서 (AUTO_INCREMENT)

테이블데이터량비고
REVINFO115,928Envers 변경 이력
SSF_OPERATION_MANAGEMENT194,914작업
SSF_SCHEDULE_MANAGEMENT188,538일정
SSF_APPROVAL_MANAGEMENT14,367승인 처리
SSF_DISPOSAL_MANAGEMENT13,336처분
SSF_SHREDDING_CERTIFICATE12,399파쇄증명서
SSF_ATTACH_FILE8,528첨부파일
SSF_BRANCH_OFFICE_MANAGEMENT5,236지점
SSF_CONSOLE_INFO_MANAGEMENT5,343파쇄통(콘솔)
SSF_KAKAO_SENDMESSAGE2,968카카오 알림톡
SSF_MENU_AUTH1,703메뉴 권한
SSF_CONTRACT_RESPONSIBLE_COMPANY1,368계약 담당사
SSF_CONTRACT_MANAGEMENT775계약
SSF_CAR_DISPATCH_MANAGEMENT269차량 배차
SSF_MEMBER73사용자
SSF_CMMN_CODE65공통 코드
SSF_CAR_INFO_MANAGEMENT37차량
SSF_MENU25메뉴
SSF_SUBCONTRACTOR10외주업체
SSF_KAKAO_TEMPLATE5카톡 템플릿
SSF_NOTICE3공지사항

14대 결함

1. 날짜/시간 컬럼이 varchar

  • VISIT_START_DATE varchar(10), VISIT_START_TIME varchar(4) — 모든 일정 관련 테이블
  • WRITE_DATE varchar(10) (NOTICE), CONTRACT_END_DT varchar(10) (CONTRACT)
  • 영향: 인덱스 비효율, 비교 연산 오류 가능, timezone 손실
  • 해결: DATE / TIME / DATETIME(6) 으로 정상화. 시간대 KST 고정.

2. FK constraint 미선언

  • 비즈니스 테이블 간 FK 0개. REVINFO ↔ *_HISTORY 만 FK 존재
  • 누락 예시: SSF_BRANCH_OFFICE_MANAGEMENT.CONTRACT_SEQ, SSF_CONSOLE.BRANCH_OFFICE_SEQ, SSF_OPERATION.CONTRACT_SEQ, SSF_SCHEDULE.OPERATION_SEQ, SSF_DISPOSAL.SCHEDULE_SEQ, SSF_CERTIFICATE.SCHEDULE_SEQ
  • 영향: 데이터 무결성 미보장. 고아 row 누적 가능
  • 해결: 모든 SEQ 참조에 FOREIGN KEY 명시 + ON DELETE/UPDATE 정책

3. 비정규화 (지점 정보 중복)

  • SSF_OPERATION_MANAGEMENT / SSF_SCHEDULE_MANAGEMENT / SSF_SHREDDING_CERTIFICATEBRANCH_OFFICE_NAME, BRANCH_OFFICE_PHONE_NUMBER, BRANCH_OFFICE_MANAGER_NAME, ADDRESS 중복 저장
  • 영향: 지점명 변경 시 모든 관련 row 갱신 필요. 일관성 깨질 위험
  • 해결: SEQ 외래키만 보유. 실제 정보는 JOIN. 필요시 view 또는 캐시 컬럼.

4. ID/SEQ 이중 식별자

  • SSF_SUBCONTRACTOR: SUBCONTRACTOR_SEQ (PK, int) + SUBCONTRACTOR_ID (varchar(20))
  • 동일 패턴: BRANCH_OFFICE_SEQ + BRANCH_OFFICE_ID, CONTRACT_SEQ + CONTRACT_ID, MEMBER_SEQ + MEMBER_ID
  • 다른 테이블에서 둘 다 외래키로 사용 (CONSOLEBRANCH_OFFICE_SEQ + BRANCH_OFFICE_ID 둘 다 보유)
  • 영향: 데이터 일관성 깨질 가능성. JPA 엔티티 혼란
  • 해결: 단일 대리키 bigint id 만 PK로. 자연키 (사업자번호, 사용자 로그인 ID) 는 별도 unique 컬럼.

5. 상태값 매직코드

  • STATUS varchar(8) DEFAULT 'C1320000' — 의미 알기 위해 SSF_CMMN_CODE 조회 필요
  • CRUSH_OPTION varchar(1) ('S'=현장파쇄, 'W'=입고파쇄), REPETITION_CYCLE varchar(1) ('M'=월/'W'=주), REPETITION_FORM varchar(1) ('A'=요일/'B'=일)
  • 영향: 코드 가독성 0, 디버깅 어려움
  • 해결: ENUM (MariaDB) 또는 의미 있는 lookup 테이블. ENUM 권장 (가독성·인덱스).

6. 감사 컬럼 일관성 없음

  • 모든 테이블 INS_DATE/INS_ID/UPD_DATE/UPD_ID 보유하나 DEL_DATE/DEL_YN은 일부만
  • BRANCH_OFFICE, CERTIFICATE 만 soft delete 패턴. 다른 테이블은 hard delete
  • 영향: 삭제 정책 통일성 X
  • 해결: BaseEntity 추출. 모든 테이블 동일 컬럼 (created_at, created_by, updated_at, updated_by, deleted_at, deleted_by). 사용자는 bigint user_id FK로.

7. M:N 관계 테이블 PK/FK 없음

  • SSF_CONTRACT_MANAGEMENT_SSF_BRANCH_OFFICE_MANAGEMENT: 두 컬럼만, PK 없음, FK 없음 (Hibernate @ManyToMany 자동 생성)
  • SSF_CAR_INFO_MANAGEMENT_SSF_CAR_DISPATCH_MANAGEMENT: 비슷
  • 영향: 중복 row 가능, 무결성 X
  • 해결: 명시적 매핑 엔티티. PK + FK + UNIQUE constraint. 또는 1:N 으로 단순화 (배차는 차량 1개에 종속이면 직접 FK).

8. Envers 감사 폭증

  • REVINFO AUTO_INCREMENT=115,928 — 5년치
  • 8개 *_HISTORY 테이블에 모든 컬럼 + _MOD bit(1) 매 변경마다 row 적재
  • 영향: HISTORY 누적, 쿼리 성능 영향
  • 해결: 감사 정말 필요한 5~7개 테이블만 (subcontractor, contract, branch_office, member, console, certificate). 나머지는 audit 컬럼만. 또는 별도 audit 시스템 (debezium → kafka → archive).

9. MENU / MENU_AUTH 컬럼 중복

  • SSF_MENUSSF_MENU_AUTH 둘 다 MENU_NM, MENU_NO, MENU_URL, MENU_DEPTH, MENU_ORDER, UPPER_MENU_NO 중복 보유
  • 영향: 메뉴 정보 변경 시 두 테이블 갱신
  • 해결: menu_authmenu_id (FK) + member_id 만 보유. 메뉴 정보는 JOIN.

10. 운영 DDL에 샘플 테이블

  • SSF_SAMPLE (샘플 시퀀스, 샘플 내용, 샘플 제목, 상태 'C2010000') — 운영 코드에 잔존
  • 해결: 신스키마에서 제거.

11. 컬럼 코멘트 오류

  • SSF_KAKAO_TEMPLATE.USE_CHANNEL 코멘트 = '템플릿 명' (잘못)
  • SSF_KAKAO_SENDMESSAGE.TMPLT_CODE 코멘트 = '수신자번호' (잘못)
  • SSF_KAKAO_SENDMESSAGE.UID 코멘트 = '발신자' (실제로는 메시지 UID 추정)
  • 해결: 신스키마에서 정확한 코멘트로. 도메인 용어집 부록.

12. DISPOSAL ↔ CONSOLE 데이터 복제

  • SSF_DISPOSAL_MANAGEMENTCONSOLE_SEQ 와 함께 CRUSHER_BAG_BARCODE, CRUSHER_STATUS, CURRENT_MATCH_NO, BRANCH_OFFICE_NAME, BRANCH_OFFICE_MANAGER_NAME 중복 저장
  • 의미: DISPOSAL 은 CONSOLE 의 상태 변경 이벤트 (자루 회수·파쇄 완료) 라 콘솔 정보를 그대로 복제
  • 해결: disposalconsole_id FK + 이벤트 시점 상태(crusher_status_at, barcode_at) + 시각만 보유. 콘솔 정보는 JOIN.

13. 공통 코드 인접 리스트 한계

  • SSF_CMMN_CODEUPPER_CODE + DEPTH 로 트리 구성 — 인접 리스트 모델
  • 영향: 깊이 검색 비효율 (재귀 SQL), 트리 변경 비용
  • 해결: 공통 코드는 깊이 2 이내라 큰 문제 X. ENUM 으로 대체 가능한 코드는 ENUM 으로 빼고, 트리 필요한 항목만 별도 lookup. 또는 closure table.

14. 자잘한 컬럼 정의 오류

  • BUSSINESS_NUMBER 오타 (BUSINESS)
  • QUANTITY varchar(50) (수량인데 문자열 50자) → INT 또는 DECIMAL
  • FEE decimal(21,0) 21자리 정수 → DECIMAL(15,0) 충분
  • MEMBER.PASSWORD varchar(256) — bcrypt 해시 저장이면 60자 충분, 또는 BCrypt 명시
  • LOGIN_FAIL_CNT 코멘트 '로그인 실팻 횟수' (오타)
  • serverTimezone=Aisa/Seoul 오타 (Asia → Aisa) — application.yml dev 쪽
  • 해결: 컬럼명·타입·길이 정상화. 보안 컬럼(password) 은 별도 정책.

운영 DB 신 발견 결함 (코드 ddl.sql 에 없던 테이블)

운영 백업 dump (2026-04-30) 분석 결과 코드 ddl.sql 38테이블 외 15테이블 추가 발견. 특히 work 도메인 (일일 업무일지) 8테이블 이 모두 결함 가득.

신 발견 테이블

테이블데이터량도메인
SSF_WORK_MANAGEMENT2,588업무일지 (작업일·차량·운행담당자·하차장소)
SSF_WORK_JOB_MANAGEMENT45,093업무에 포함된 작업들 (스케쥴·증명서 매핑)
SSF_WORK_MEMBER_MANAGEMENT4,230근무자·시작·종료·인건비
SSF_WORK_PAPER_MANAGEMENT1,038파지량·급지종류·단가
SSF_WORK_EXPENDITURE_MANAGEMENT13,315경비·결제방법·금액
SSF_WORK_FEEDBACK_MANAGEMENT1,099피드백 메모
SSF_WORKTYPE_MANAGEMENT4,355작업타입·중량 (증명서 단위)
SSF_SCHEDULE_MANAGER_INFO322,905일정 담당자 정보
SSF_MENU_BAK-메뉴 백업 (운영 잔존)
+ 8개 *_HISTORY-위 audit
→ work 도메인 = 운영팀 매일 업무일지 시스템. 정산·인건비·세금계산 베이스.

15. work 도메인 — 모든 컬럼 varchar(100)

  • WORK_DATE varchar(100), JOB_WORK_DAY varchar(100) — 날짜에 100자
  • WORK_MEMBER_START_TIME / END_TIME varchar(100) — 시각 100자
  • WORK_MEMBER_ID varchar(100), INS_ID varchar(100), UPD_ID varchar(100) — 사용자 ID 100자 (다른 도메인은 varchar(20))
  • 일관성 없음 — 같은 사용자 ID 가 다른 테이블엔 varchar(20) 다른 곳 varchar(100)
  • 해결: 신스키마에서 created_by BIGINT (member.id FK) + WORK_DATEDATE + 시각 → TIME

16. work 도메인 FK 미선언 — 0개

  • WORK_SEQ, JOB_SCHEDULE_SEQ, JOB_SHREDDING_SEQ, SHREDDING_SEQ, WORK_CAR_SEQ 모두 외래키 정의 없음
  • 데이터 무결성 보장 X — 고아 row 누적 가능
  • 해결: FOREIGN KEY ... ON DELETE RESTRICT 명시

17. 금액·수량·작업량 문자열 — DECIMAL 이어야

  • EXPENDITURE_PRICE varchar(100) (경비 금액)
  • JOB_SERVICE_PRICE varchar(100) (서비스 비용)
  • JOB_WEIGHT varchar(100) / WORK_WEIGHT varchar(255) / PAPER_WEIGHT varchar(100) (중량)
  • JOB_AMOUNT varchar(100) (수량)
  • PAPER_PRICE varchar(100) (단가)
  • WORK_MEMBER_PRICE varchar(100) (인건비)
  • paperTotal varchar(255) (단가 합계)
  • 영향: 정산·세금계산 시 문자열 → 숫자 변환 부하 + 계산 오류 위험
  • 해결: DECIMAL(15,2) (금액) / DECIMAL(10,3) (중량) / INT (수량)

18. work 도메인 비정규화

  • JOB_BRANCH_NAME varchar(100), JOB_CONTRACT_NAME varchar(100), FEEDBACK_CONTRACT_NAME varchar(100) — 지점/거래처 이름 중복 저장
  • WORK_PAPER_PLACE varchar(100) (하차장소 업체명) — 거래처 FK 가능
  • 해결: SEQ FK 만 보유, 이름은 JOIN

19. work 도메인 컬럼명 일관성 X

  • paperTotal varchar(255) (camelCase)
  • WORK_DATE varchar(100) (SCREAMING_SNAKE)
  • 같은 테이블 안에 두 컨벤션 혼재 (SSF_WORK_PAPER_MANAGEMENT.paperTotal + PAPER_TYPE)
  • 해결: 신스키마에서 모두 snake_case 통일

20. work 도메인 - 차량번호 컬럼 분할

  • SSF_WORK_MANAGEMENT.WORK_CAR_NUM_1, WORK_CAR_NUM_2 — 차량 두 대 의미
  • 배열을 컬럼 분할 → 정규화 위반
  • 만약 더 많은 차량 필요하면? 컬럼 추가 무한반복
  • 해결: work_car (work_id FK, car_id FK, sequence INT) 별도 테이블 또는 1:N 매핑

운영 데이터 SELECT 분포 결함 (2026-04-30 내부 호스트 검증)

21. contract.STATUS 의미 혼합 ⚠️

같은 컬럼에 두 다른 도메인 코드 섞여 저장:

C2020000 (승인 — C2XX 승인상태)        36
C2030000 (반려 — C2XX 승인상태)        1
C4010000 (계약 — C4XX 계약상태)        237
C4020000 (계약만료 — C4XX 계약상태)    2407
C4030000 (계약해지 — C4XX 계약상태)    101
→ 컬럼 1개에 두 도메인 의미 충돌. 해결: 신스키마에서 contract.status (계약상태) + contract.approval_status (승인상태) 분리.

22. member.MEMBER_LEVEL 매직코드 직접 저장 ⚠️

운영 데이터: C3010000/C3020000/C3030000 그대로 저장. CODE_VALUE (SUPER/ADMIN/USER) 미사용. 마이그레이션 ETL 시 변환 매핑 필수.

23. work_job.JOB_PAY_TYPE 카오스 (6종 표현 혼재)


NULL              10,250
'' 빈문자열       34,284 (90%)
'card'            432
'duty'            55
'null' 문자열     65
'카드'            3
'카드결재'        1
→ 영어/한국어/빈/null/매직 모두. 신스키마 ENUM 변환 시 EMPTY|NULLUNSPECIFIED, 'card'|'카드'|'카드결재'CARD, 'duty'OFFICIAL 매핑 ETL 필요.

24. console.CRUSHER_STATUS 일관성 X


NULL                49
'' 빈문자열         624
C1100000 (카테고리) 1   ← 자식 코드여야 하는 위치에 카테고리 코드 잘못 저장
C1120000 (수거)     3,676
→ ETL 시 C1100000 row 1건 별도 처리 필요. 나머지는 EMPTY|NULLUNKNOWN, C1120000COLLECTED.

25. 도메인 간 컬럼명·값 일관성 0

  • work_job.JOB_PAY_TYPE = 영어 (card, duty) + 매직코드 + 빈값
  • work_expenditure.EXPENDITURE_PAY_TYPE = 한국어 (카드, 현금, 기타)
  • member.MEMBER_LEVEL = CMMN_CODE 매직값 (C3010000)
  • contract.STATUS = 의미 혼합 (C2X + C4X)
→ 도메인별 결정 일관성 X. 신스키마: 모든 ENUM 영문 대문자 SCREAMING_SNAKE_CASE 통일.

26. branch_office.STATUS redundancy


NULL: 7 / C4010000 4327 / C4020000 2671 / C4030000 828
branch_office 가 자체 상태 없이 contract.status 따라가는 데이터. 신스키마에서는 branch_office 자체 상태 (예: 활성/방문중지/해지) 별도 정의. contract 와 별도 라이프사이클.

27. certificate 미발급률 50% — 비즈니스 정합성 이슈


C9010000 발급:    43,940
C9020000 미발급:  44,624
→ 50% 가까이 미발급. 신스키마 마이그 시 미발급 row 들이 진짜 미발급인지, 발급 후 status 갱신 누락인지 운영팀 확인 필요.

28. CERTIFICATE_TYPE 컬럼 두 곳, 의미 다름

  • contract.CERTIFICATE_TYPE = 계약 시 약속한 양식 (단건 90%, 연간 8%)
  • certificate.CERTIFICATE_TYPE = 실 발급 양식 (연간 90%, 단건 3%, 코웨이 6%)
→ 같은 컬럼명 두 다른 의미. 신스키마 분리: - contract.contracted_template_id FK→certificate_template.id - certificate.template_id FK→certificate_template.id (실 발급 시점 결정)

29. worktype.WORK_TYPE 종류·단위 혼재


box (1565)       ← 종류 (박스 단위)
A4box (1218)     ← 종류 (A4 박스)
HDD (59)         ← 종류 (HDD)
kg (651)         ← 단위 (무게)
madae (106)      ← 종류 (마대)
→ 신스키마 분리: unit_type ENUM('BOX','A4_BOX','MADAE','HDD','LOOSE') + weight DECIMAL(10,3) 별도 (kg 단위는 weight 측정 시 사용).

30. JOB_ANNUAL = 'Y'/'N' BOOLEAN 변환

운영 분포: Y(43879)/N(1211). 일관 → BOOLEAN 변환 단순. 결함이라기보단 마이그레이션 ETL 노트.

결함 총합 (v3): 30개

  • A. 데이터 타입: 1, 14, 15, 17, 18, 30
  • B. 정합성/FK: 2, 7, 12, 16, 19, 26
  • C. 정규화: 3, 9, 19, 20, 28
  • D. 식별자/명명: 4, 14, 19, 25
  • E. 상태값/매직코드: 5, 11, 21, 22, 23, 24, 25, 27, 29
  • F. 감사/스키마 부산물: 6, 8, 10
  • G. 트리/계층: 13

추가 관찰

Envers 의존도

  • spring-data-envers 가 운영 데이터 신뢰의 근거 중 하나. 신스키마에서 audit 정책 명확히 정의 후 decommission 또는 축소.

외래키 자연 정의 (현 코드/도메인 기준)


subcontractor (1) ←→ (N) contract
contract (1) ←→ (N) branch_office
branch_office (1) ←→ (N) console
contract (1) ←→ (N) operation
operation (1) ←→ (N) schedule
schedule (1) ←→ (N) disposal
schedule (1) ←→ (1) certificate
console (1) ←→ (N) disposal
car (N) ←→ (1) subcontractor
car (1) ←→ (N) car_dispatch
car_dispatch (N) ←→ (1) branch_office
member (N) ←→ (1) subcontractor
member (1) ←→ (N) menu_auth
menu (1) ←→ (N) menu_auth

이 관계는 신스키마에서 모두 FK 로 명시.

⚠️ 알려진 이슈 갭분석 — 기존 1472shred vs 신규 irosafe_shred v5 개선사항 작성: 2026-06-06 KST · MVP 6/30 (D-24)
마지막 갱신 2026. 6. 8. PM 12:28 KST · docs/09_테스트/05_기존_vs_신규_비교.md

1472shred (기존) vs irosafe_shred v5 (신규) 개선사항 비교

작성: 2026-06-06 KST · MVP 6/30 (D-24)
근거: docs/01_아키텍처/00_현황분석.md, docs/03_DB재설계/00_기존_ILSA_결함.md, 신규 코드/문서

핵심 한 줄: 레거시 8개 큰 기술 부채 일괄 해소 + 신규 운영 가치 9건 추가.

0. 개요 비교

기존 1472shred신규 irosafe_shred v5효과
라인 수 (Java)약 180 파일 (web/domain/global 혼재)72 파일 (도메인별 분리)가독성 / 책임 분리
패키지 그룹com.sgisframe (오타)com.irosafe.shred브랜드/오타 정정
빌드gradle.build / warGradle Kotlin DSL / bootJar모던 빌드 + 버전 카탈로그
운영1대 (1472shred.co.kr)컷오버 대기병렬 운영 → 신규
안정성OOM 회고 (2026-05-29 Old Gen full)부팅 3.7s · health 200 · Virtual ThreadJVM 21 가속

1. 기술 스택

영역기존신규개선
Spring Boot2.5.23.3.5 LTSEOL 회피, JDK 21 호환
Java8 (1.8)21 LTS + Virtual Threads13년 격차 해소, GC/성능
JPA / HibernateHibernate 5 (envers)Hibernate 6 + Enversrecord/sealed 호환
빌드gradle DSL (legacy)Gradle Kotlin DSL + libs.versions.toml버전 한 곳, IDE 자동완성
화면Thymeleaf 3.0 (182 템플릿)Vite 5 + React 18 + TSSPA · 다크모드 · HMR
스타일자체 CSSTailwind 3 + Pretendard Variable + iro 토큰디자인 일관성, 가독성
패키징warbootJar (Fat JAR)단일 산출물, systemd 친화
API 문서없음SpringDoc OpenAPI 3 · 32 path 자동신규 화면/외부연동 시 즉시 검증
외부 사내 jarsgis-common-frame.jar (불투명)자체 wellsa-commons / irosafe-shred-commons의존 1개 제거, 책임 명확

2. 인증 · 보안

영역기존신규개선
인증 방식Session + FormLoginJWT HS256 (Access only, 2h)모바일/SPA 친화, stateless
Security 설정WebSecurityConfigurerAdapter (폐기 API)Security 6 SecurityFilterChain bean모던 / 컴파일 안전
비밀번호평문/단순 해시 (추정)bcrypt 12 rounds산업 표준
권한 모델3 단계 텍스트 (SUPER/ADMIN/USER)**RBAC 3-tier × 13 permissions (ROLE_* + 권한 code)@PreAuthorize("hasAuthority('CODE_MANAGE')")
로그인 감사기록 부족login_audit (success/FAIL_PWD/FAIL_BLOCKED/FAIL_NOT_FOUND + IP)침해 추적
세션 타임아웃24hJWT 2h + refresh 가능토큰 노출 시 영향 축소
권한 캐싱미확인AuthorityResolver 트랜잭션 read-only호출당 일관 권한 해석
XSS 방어lucy-xss-servlet 2.0.0 (서버)프론트 React 자동 escape + CSP 가능경로 단축

3. 도메인 (운영 변화)

영역기존신규개선
계약트랙 미분리 — SSF_CONTRACT_MANAGEMENT 한 테이블에 IS_ANNUAL/IS_BRANCH 플래그트랙 이원화 (ONE_CALL / RECURRING) + ContractStatus ENUMURL · UI · 화면 분리, 자동 prefix [원콜]/[정기]
캘린더일/주/월 분리 화면단일 SPA + 협력사 7색 + N+ more 표시한눈에 일정 + 색상 매핑
일일업무안드로이드만웹 + 안드로이드(후속)작업자 1일 view, 카드+진행률
협력사7 협력사 (실제)7색 swatch 자동 매핑 + 캘린더 컬러시각 구분 즉시
콘솔/바코드ZXing 자체 인쇄 (라벨프린터 IP 하드코딩)QR/Barcode generation endpoint + 프린트 영우님 협업인프라 추상화
증명서JasperReports .jrxml 5종5종 ENUM (YEARLY / ONE_TIME / COWAY / AH / HDD) + 발급/무효 mutationPDF 후속 분리
코드 마스터SSF_CMMN_CODE (65 row, varchar 매직코드)code 마스터 + UI 관리 (탭/인라인 편집/활성/순서)운영자 직접 조정
정기 자동 연장코드 부재 (수동)ContractExpiryJob @Scheduled(03:00 KST) — autoExtend → +1y · 비연장 → EXPIRED마감 누락 0

4. UX · 운영자 경험

영역기존신규개선
다크모드없음system/light/dark 3 모드 토글 + localStorage야간 사용 / AAA 가독성
가독성자체 폰트 / 어수선Pretendard Variable + weight 420 + -0.022em 자간텍스트 가독성 +30% (체감)
엑셀 다운로드일부 도메인만계약 / 협력사 / 일정 3종 + 한글 헤더 + UTF-8 파일명운영자 즉시 가치
엑셀 업로드정기 계약동일 유지 (POST /api/v1/recurring/upload)호환
주소 검색미확인카카오 우편번호 모달 + 도로명 우선주소 입력 5x 단축
검색·필터일부 페이지모든 리스트 (계약/일정/협력사/콘솔/증명서)조회 일관성
단축 키없음(후속) keyboard nav 예정

5. 자동화 · 인프라

영역기존신규개선
정기 배치수동 트리거 추정매월 25일 자동 (Quartz 또는 @Scheduled)운영자 부담 0
자동 만료수동 처리ContractExpiryJob 일배치만료 누락 0
QR 발행라벨프린터 IP 하드코딩엔드포인트 + 데이터 분리 (Barcode 도메인)프린트 인프라 교체 자유
Excel 일괄일부정기 대량 업로드 + 다운로드 3종양방향
데이터 마이그 도구없음LegacyMigrationRunner (Spring Boot CLI · dry-run/apply)안전 ETL, 자연키 보존

6. DB 스키마 (대표 결함 14건 → 0건)

#기존 결함해결
1날짜/시간 컬럼 varcharDATE / TIME / DATETIME(6) 정상화
2FK 0개 (비즈니스 테이블)모든 SEQ 참조 FOREIGN KEY
3비정규화 (지점명 중복 저장 3 테이블)SEQ 외래키만, JOIN
4SEQ + ID 이중 식별자bigint id PK 단일, 자연키 별도 unique
5상태값 매직코드 (C1320000)ENUM (CONTRACT/EXPIRED/...)
6NULL/공백 혼재NOT NULL + default 명시
7인덱스 부족ix_sched_visit_started 외 12 인덱스
8감사 envers 일부만BaseEntity + Envers 표준 적용
9패키지 오타 (sigsframe)irosafe.shred
10외부 jar 의존자체 commons 라이브러리
11utf8mb4 / 한글 호환 일부utf8mb4 표준 + Pretendard
12코드 마스터 표준 부재code 마스터 + UI
13시간대 손실KST 고정 (Asia/Seoul)
14Hibernate 4/5 혼재 위험Hibernate 6 통일
상세: docs/03_DB재설계/00_기존_ILSA_결함.md

7. 테스트 · 품질

영역기존신규개선
단위테스트없음 / 미확인71 PASS / 0 FAIL (9 클래스, 12s)핵심 비즈니스 로직 안전망
e2e없음Playwright 35 PASS / 0 FAIL (UI 19 + API 16)UI + endpoint 회귀 자동
통합없음9 작성 (Testcontainers MariaDB)CI runner runner 등록 후 자동
API 문서없음Swagger UI 32 path 자동신규 협업 즉시
CI부분GitLab Pipeline (단위테스트 + build)push 마다 검증
부팅 시간미확인 (OOM 회고)3.7sJVM 21 + lazy bean
Migration 검증수동Flyway V1~V6 + Testcontainers Flyway 검증스키마 일관성

8. 개발 생산성

영역기존신규개선
모노레포백/모바일 분리, 공통화 없음apps/{backend,frontend,android} + libraries/코드 공유
빌드 캐시Gradle 캐시 + npm 캐시 + GitLab cache.key.filesCI 단축
핫리로드(Thymeleaf) 기본Vite HMR + Spring DevTools개발 사이클 가속
의존성 관리분산libs.versions.toml + package-lock.json버전 1곳
모달/팝업일부 자체통합 컴포넌트 (PageHeader/DataTable/SearchBar/Badge)재사용
디자인 토큰없음iro/CI runner/partner 팔레트 + Pretendard일관성

9. 보안 · 컴플라이언스

영역기존신규개선
CSRFSpring 기본JWT stateless토큰 모델
CORS자체 처리CorsFilter HIGHEST_PRECEDENCE + origins 명시dev/prod 일관
비밀번호 정책미확인bcrypt 12 + login fail lock 5/30분산업 표준
로그분산통합 (shred-backend.log) + KST운영 단순
감사 (audit)일부 enversBaseEntity + Envers + login_audit + schedule_assignment_audit핵심 변경 추적
컷오버 안전일시병렬 운영 → 신규 점진 + Phase E ETL dry-run/apply 분리롤백 가능

10. 한 장 요약 (Before → After)

항목BeforeAfter
Spring Boot / Java2.5 / 83.3 / 21
화면Thymeleaf 182React SPA + 다크모드
API 문서없음Swagger 32
RBAC 권한3 단계 텍스트13 권한 코드
DB 결함14건0건
테스트없음단위 71 + e2e 35 = 106 PASS
정기 자동 연장수동@Scheduled 일배치
다크모드없음system/light/dark
코드 마스터 UI매직코드탭/인라인/활성
주소 검색없음카카오 우편번호

11. 운영 KPI 예상 (Phase G 시연 후 측정)

KPIBefore (추정)After (목표)
계약 등록 클릭 수10+≤ 5
일정 조회 (월 단위)다중 화면1 SPA
엑셀 다운로드 가능 도메인일부3 (계약/협력사/일정)
협력사 식별 시각 단서텍스트색상 swatch
정기 만료 누락발생0** (배치)
컷오버 위험일괄 교체병렬 운영

12. 변경 이력

  • v1 (2026-06-06): 초안 — 12 카테고리 Before/After 표 + KPI

정적 문서

5건
정적 문서 업데이트

동일 파일명으로 업로드하면 기존 파일을 덮어씁니다. HTML, PDF, ZIP, 엑셀, 워드와 이미지를 지원합니다.