40 KiB
dmbpRegist.jsp → React 마이그레이션 분석·구현 가이드
| 항목 | 내용 |
|---|---|
| 원본 JSP | adssNewOld/.../fnrsc/dmbp/dmbpRegist.jsp |
| 대상 앱 | frontend/apps/as |
| 도메인 | 하수도기본계획 (구: 기본계획검토 / dmbp) |
| API 엔티티 | @/entities/sewer-bsc-plan (SewerBscPlanController) |
| 참조 패턴 | @/pages/fnrs-cnsltn + @/widgets/pbadms-sprt |
| 문서 목적 | contents 영역 섹션별 UI·상태·API 매핑 및 구현 방향 |
| 작성 기준일 | 2026-07-27 |
1. 마이그레이션 범위
1-1. 포함 (contents만)
JSP 568~1274행: <div class="contents"> ~ <!-- //contents -->
| 영역 | JSP 식별 | 개요 |
|---|---|---|
| A | gTitle1 |
페이지 타이틀·브레드크럼 |
| B | slide_10 |
기본계획변경 신청(마스터·연도·개요) |
| C | slide_15 |
신청자·설계자 정보 |
| D | slide_19 |
개인정보 동의 |
| E | slide_11 |
사업개요(단계별 인구·보급률) |
| F | slide_12 |
총사업비 — BizCstMatrixFormSection 전용 |
| G | slide_13 |
재원분담 |
| H | slide_14 |
처리시설별 하수도정비기본계획 (Checkbox + Tabs) |
| I | slide_16 |
체크리스트 + 필수첨부 + 기타첨부 |
| J | JSP 상단 saveBtn / presentnBtn |
React: 폼 하단 액션바 (fnrs-form-page 279~323과 동일 구성, API만 sewer) |
1-2. 제외
<%@ include %>: top / sideMenu / footer /bscPlnPopup.jsp/sndrdBzAmnt.jsp- 레이아웃·메뉴·권한 셸 → 기존
BaseLayout/PageLayout/ AUTH 체계 mStep1진행 단계 표시 (미구현 · 마이그레이션 범위 밖)
팝업(이전기본계획조회)은 별도 Dialog 컴포넌트로 재구현하며, include JSP 자체는 포팅하지 않는다.
2. 목표 아키텍처
app/(with-base-layout)/sewer-bsc-plan/regist/page.tsx
└─ pages/sewer-bsc-plan/ui/sewer-bsc-plan-regist-page.tsx
└─ sewer-bsc-plan-form-page.tsx # FormProvider + 섹션 조립
├─ sections/*-form-section.tsx # 도메인 전용
└─ widgets/pbadms-sprt/* # 공통 재사용
entities/sewer-bsc-plan/ # 이미 구현됨
saveApply / findDetails / submitSupplement …
폼 스택 (fnrs-cnsltn과 동일)
react-hook-form+zod(zodResolver,mode: "onChange")- 섹션 래퍼:
SectionCollapsible(Accordion 아님) - UI:
@common/components(Input, Select, Textarea, Button, Radio, Tabs, Table 등) - 그리드가 필요한 곳만
@tanstack/react-table+DataTable - 데이터: React Query (
useSaveApplySewerBscPlan등) — 목데이터는 API 미연동 구간만@faker-js/faker
Vercel React Best Practices (적용 요약)
client-swr-dedup: React Query로 체크리스트/필수첨부/코드 조회 중복 제거bundle-dynamic-imports: 처리시설 Tabs 패널·이전계획 Dialog는next/dynamic후보rerender-derived-state: 단계 연도·합계·진행률은 render 중 파생, 불필요 effect 금지async-parallel: 등록 진입 시 코드/체크리스트트리/필수첨부트리를 병렬 조회
3. 전체 레이아웃
fnrs-form-page.tsx와 동일한 FormProvider + 세로 섹션 스택 구조를 따르고,
하단 액션바는 fnrs-form-page.tsx 279~323 과 동일 구성(목록·저장·신청완료·삭제·보완완료)이며 API/라우트만 sewer 로 바꾼다.
타이틀·브레드크럼은 폼 밖(PageLayout / regist·edit·view 셸)에서 처리한다.
(상세 View의 sticky FAB·검토/결재 버튼은 본 등록 문서 범위 밖 — fnrs-view-page 대응 후속.)
3-1. 컴포넌트 트리 (fnrs 대응)
PageLayout (title / breadcrumb)
└─ SewerBscPlanRegistPage | SewerBscPlanEditPage | SewerBscPlanViewPage
└─ SewerBscPlanFormPage | SewerBscPlanViewPage 본문
FormProvider (등록/수정) / 읽기 섹션 (상세)
└─ <form|div className="mt-6 space-y-4">
├─ BasicInfoFormSection // JSP slide_10
├─ ContactInfoFormSection // JSP slide_15 (pbadms-sprt)
├─ PrivacyConsentSection // JSP slide_19 (pbadms-sprt, 등록·수정)
├─ OutlineFormSection // JSP slide_11 (사업개요, 신규)
├─ BizCstMatrixFormSection // JSP slide_12 (총사업비 전용, 신규)
├─ FnrsCstFormSection // JSP slide_13 (재원분담, 신규 ※ FnrsShar 아님)
├─ TmplntFormSection // JSP slide_14 (처리시설, Tabs로 시설별 패널)
├─ ChecklistFormSection // JSP slide_16 (pbadms-sprt)
├─ AttachmentsFormSection // JSP 필수·기타첨부 (pbadms-sprt)
├─ SplmntDmndFormSection // edit + SL 상태만 (pbadms-sprt)
└─ form footer action bar // fnrs-form-page 279~323 동일
// [목록] / [저장] / edit시 [신청완료][삭제] / SL시 [보완완료]
폼 하단 액션바 버튼 구성
기준: fnrs-form-page.tsx 279~323. UI·분기만 동일하고 훅/라우트는 sewer.
| 순서 | 버튼 | 조건 | sewer 비고 |
|---|---|---|---|
| 1 | 목록 | 항상 | router.push("/sewer-bsc-plan") |
| 2 | 저장 | !isSplmntPrgrsStts |
type="submit" → saveApply / 임시저장(SV) |
| 3 | 신청완료 | !isSplmntPrgrsStts && isEditMode |
체크리스트+필수첨부 검증 → saveApply / LE |
| 4 | 삭제 | !isSplmntPrgrsStts && isEditMode |
confirm → delete → 목록 |
| 5 | 보완완료 | isSplmntPrgrsStts (prgrsSttsComCd=SL) |
submitSupplement (fnrs onSplmntCmptn 대응) |
fnrs와의 차이 (섹션 치환만, 골격 동일)
| fnrs-form-page | sewer-bsc-plan |
|---|---|
BasicInfoFormSection |
동일 역할 (마스터·연도·개요 필드는 sewer DTO) |
ContactInfoFormSection |
동일 (fieldPrefix="sewerBscPlanDtl") |
PrivacyConsentSection |
동일 |
BusinessScaleFormSection |
→ OutlineFormSection (단계별 인구·보급률) |
BusinessCostFormSection |
→ BizCstMatrixFormSection (단계×원가 계층 전용) |
FnrsSharFormSection |
→ FnrsCstFormSection (국고·지방비·원인자·기타) |
| (없음) | TmplntFormSection (체크박스 + Tabs 시설별 매트릭스) |
ChecklistFormSection docSeComCd="FNRS" |
docSeComCd="SEWER" (TBD) |
AttachmentsFormSection |
동일 패턴 |
SplmntDmndFormSection |
동일 (readOnly={!isSplmntPrgrsStts}) |
| 폼 하단 액션바 (목록·저장·신청완료·삭제·보완완료) | 동일 구성, API·라우트만 sewer |
3-2. 본문 ASCII (폼 페이지)
┌─────────────────────────────────────────────────────────────────┐
│ PageLayout: 하수도기본계획 신청/수정 breadcrumb │
├─────────────────────────────────────────────────────────────────┤
│ FormProvider │
│ <form className="mt-6 space-y-4"> │
│ │
│ ┌─ SectionCollapsible: 기본계획 신청 ─────────────────────┐ │
│ │ BasicInfoFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 신청자 정보 ────────────────────────────────────────────┐ │
│ │ ContactInfoFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 개인정보 동의 ──────────────────────────────────────────┐ │
│ │ PrivacyConsentSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 사업개요 ────────────── [이전기본계획조회] ─────────────┐ │
│ │ OutlineFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 총사업비 (백만원) ──────────────────────────────────────┐ │
│ │ BizCstMatrixFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 재원분담 (백만원) ──────────────────────────────────────┐ │
│ │ FnrsCstFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 처리시설별 하수도정비기본계획 ──────────────────────────┐ │
│ │ TmplntFormSection │ │
│ │ ├─ BscFctList Checkbox │ │
│ │ └─ Tabs (선택 시설별 TabsTrigger / TabsContent) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 체크리스트 ─────────────────────────────────────────────┐ │
│ │ ChecklistFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 첨부파일 ───────────────────────────────────────────────┐ │
│ │ AttachmentsFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 보완요구 (edit + SL) ───────────────────────────────────┐ │
│ │ SplmntDmndFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ form footer (fnrs-form-page 279~323 동일) ──────────────┐ │
│ │ [목록] [저장] / edit: [신청완료][삭제] / SL: [보완완료] │ │
│ │ ※ API·라우트만 sewer — UI 분기는 fnrs와 동일 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ </form> │
└─────────────────────────────────────────────────────────────────┘
3-3. 액션바 동작 (fnrs-form-page 279~323 동일, API만 sewer)
구현 위치: sewer-bsc-plan-form-page.tsx 하단
(fnrs-form-page.tsx의 mx-4 flex flex-wrap justify-center gap-3 블록을 그대로 옮기고 훅·path만 교체)
| 버튼 | 조건 | 대표 동작 |
|---|---|---|
| 목록 | 항상 | router.push("/sewer-bsc-plan") |
| 저장 | !isSplmntPrgrsStts |
type="submit" → saveApply + 임시저장(SV) |
| 신청완료 | edit && !isSplmntPrgrsStts |
체크리스트 완료 + 필수 첨부 완료 검증 → saveApply + LE |
| 삭제 | edit && !isSplmntPrgrsStts |
confirm → delete → 목록 |
| 보완완료 | isSplmntPrgrsStts (SL) |
form.handleSubmit → useSubmitSupplementSewerBscPlan |
신청완료 사전 검증 (fnrs handleApplyClick과 동일 정책)
- 체크리스트:
isFormChecklistComplete(cklstResultList)— 미완료 시"모든 체크리스트 항목을 체크해야 신청이 가능합니다." - 필수 첨부:
esntlAtchYn === "Y"인 필수첨부 슬롯마다esntlAtchFileList에atchFileGroupId가 있어야 함- Form:
AttachmentsFormSection의 트리 + 폼esntlAtchFileList - 미충족 시 예:
"필수 첨부파일을 모두 등록해야 신청이 가능합니다." - 헬퍼 후보:
isFormEsntlAtchComplete(requiredTree, esntlAtchFileList)(pbadms-sprt에 추가)
- Form:
저장에는 위 검증을 적용하지 않는다 (임시저장 허용).
저장/제출 버튼을 섹션 헤더(gTitle2 gRt)에 두지 않는다 — 폼 하단 액션바 단일 진입점 (§4-J).
3-4. 라우트
| 화면 | path | 셸 → FormPage |
|---|---|---|
| 등록 | /sewer-bsc-plan/regist |
mode="create" |
| 수정 | /sewer-bsc-plan/[id]/edit |
mode="edit" + useSewerBscPlanDetails |
| 상세 | /sewer-bsc-plan/[id] |
ViewPage (본 문서 범위 밖, fnrs-view 대응) |
docSeComCd 후보: 백엔드 체크리스트·필수첨부 등록값 확인 후 SEWER (또는 레거시 DMBP) — TBD, CMS 코드와 맞출 것.
4. 섹션별 상세 구현
4-0. Hidden / 세션 컨텍스트 (폼 루트)
JSP hidden → React 폼 기본값·세션 스토어로 흡수.
| JSP | 의미 | React |
|---|---|---|
chgSe / chgSeSp / chgSeCd |
변경구분 | sewerBscPlan.sewerBscPlanSeComCd + 표시용 코드명 |
progrsSttus |
SAVE / PRESENTN | 저장·제출 시 prgrsSttsComCd로 매핑 (임시저장 vs 제출) |
planSeCd |
고정 A |
필요 시 상수 또는 API 필드 확인 |
adstDstrCd / rgnCd |
행정구역 | sewerBscPlan.admdstCd |
sidoNm / gugunNm |
표시용 | 읽기 전용 표시 (detDto.sido/gugun) |
구현: getCreateDefaultValues(userInfo)에서 로그인 사용자·소속 지자체 주입.
4-A. 타이틀·브레드크럼
| JSP | React |
|---|---|
h3 기본계획검토 |
PageLayout title: 하수도기본계획 신청 (IIPBS 명명) |
| 설치인가 및 제원협의 > … | 메뉴 메타 기반 breadcrumb |
별도 섹션 컴포넌트 불필요. 라우트 page.tsx / layout metadata로 처리.
4-B. 기본계획변경 신청 (slide_10)
파일: ui/sections/basic-info-form-section.tsx
래퍼: SectionCollapsible title=기본계획 신청
필드 접두사: sewerBscPlan.* + sewerBscPlanDtl.*
| 표시명 | JSP | API 매핑 | UI | 필수 | 비고 |
|---|---|---|---|---|---|
| 기본계획명 | drngMtncPlanNm |
sewerBscPlan.sewerBscPlanNm |
Input | Y | |
| 계획년도 | planYr |
sewerBscPlanDtl.planYr |
Select (현재~2005) | Y | |
| 기준년도 | crtrYr |
sewerBscPlanDtl.crtrYr |
Select | Y | |
| 1~4단계 목표연도 | goalYrStep1~4 |
frlvlGoalYr~folvlGoalYr |
Select (현재~+30) | Y | 1단계 변경 시 +5/+10/+15 자동 연동 |
| 계획개요 | bzCn |
sewerBscPlanDtl.bizOtlnCn |
Textarea | Y | |
| 구분 | #chgSeNm |
sewerBscPlanSeComCd (+코드명) |
읽기 또는 Select | 신규/변경 등 | |
| 신청 지자체 | ${lclgvrnmntNm} |
admdstCd |
읽기 전용 |
동작
goalYrStep1onChange → 2·3·4단계 기본값 세팅 + E/F/G 헤더 연도 span 갱신 (watch파생)- JSP 상단
gRt저장/제출은 사용하지 않음 → FormPage 하단 액션바 (§3-3, §4-J)
4-C. 신청자 정보 (slide_15)
재사용: @/widgets/pbadms-sprt의 ContactInfoFormSection
props: fieldPrefix="sewerBscPlanDtl" (또는 dtl 필드 구조에 맞게)
| 표시 | JSP | API |
|---|---|---|
| 신청자 이름/전화/부서/이메일 | ${UsrNm} 등 서버렌더 |
로그인 사용자 읽기 전용 → aplcntNm, aplcntMblTelno, aplcntOgdpNm, aplcntEmlAddr |
| 설계자 | dsgnrNm/Telno/Psitn/Email |
dsgnrNm, dsgnrTelno, dsgnrOgdpNm, dsgnrEmlAddr |
신청자 4필드는 세션에서 defaultValues에 채우고 Input disabled.
4-D. 개인정보 동의 (slide_19)
재사용: PrivacyConsentSection
| JSP | React |
|---|---|
| 고지 textarea + 보유기간 문구 | 동일 문구 상수/마크다운 |
privacyAgree Y/N |
폼 필드 privacyAgree: "Y" | "N" (API 미전송, 클라이언트 검증만) |
검증: 제출 시 Y 필수 (JSP presentnBtn과 동일). 저장(임시)은 동의 없이 허용할지 정책 TBD — 기본은 JSP와 같이 제출만 강제.
4-E. 사업개요 (slide_11)
파일: ui/sections/outline-form-section.tsx (신규, 도메인 전용)
API: sewerBscPlanOtlnList: SewerBscPlanOtlnItem[] (planStpNo 1~4)
| 행(구분) | JSP name | Item 필드 |
|---|---|---|
| 계획인구 | arrPlanPpltn |
sewerPlanPpltnCnt |
| 처리인구 | arrPrcsPpltn |
sewerPrcsPpltnCnt |
| 하수도보급율 | arrDrngSplyRt |
sewerPsplyRt |
열: 1~4단계 (헤더에 frlvlGoalYr 등 표시).
버튼: 이전기본계획조회 → Dialog (PreviousPlanLookupDialog)
- 레거시:
fnbscPlnPopupToggle+bscPlnPopup.jsp - React: Modal + 조회 API (TBD: 이전 계획 조회 엔드포인트; 없으면 1차는 Dialog UI만 + mock)
숫자 입력: 콤마 제거 후 number 전송 (제출 시 JSP replaceComma 대체).
4-F. 총사업비 (slide_12)
파일: ui/sections/biz-cst-matrix-form-section.tsx (전용 컴포넌트 — fnrs BusinessCostFormSection 재사용 금지)
래퍼: SectionCollapsible title=총사업비 (단위 백만원은 헤더 우측)
JSP 현실: 단계(1~4) × 원가 계층(총사업비, 공사비, 처리시설, 하수관로 신설/보수, 펌프장, 배수설비, 기타, 부대경비, 설계/감리/부대비). 일부 readonly·자동합산 JS.
신규 API: bizCstList: SewerBscPlanBizCstItem[] = { planStpNo, acntgSeCd, cstrnAmt }
구현 방향 (BizCstMatrixFormSection 전용)
- 행 =
useAcntgSeMngTree→buildAcntgCostItems(fnrsBusinessCostFormSection과 동일 출처) costItems로드 시useEffect로bizCstList를mergeBizCstList(existing, costItems)로 동기화- 열 =
planStpNo1~4 (헤더에 목표연도 표시) - readonly 행(
CostItemDef.readonly=true)은 children 합산으로 자동계산; Input에readOnly+bg-muted - 변경 시
setAmt→recalculateBizCstMatrix(list, costItems)→setValue("bizCstList") - 저장 시 섹션 onChange 합산을 신뢰하여
bizCstList그대로 전송 (toBizCstSaveListidentity)
표준사업비 조회 버튼은 JSP에서 주석 처리됨 → 미구현.
4-G. 재원분담 (slide_13)
주의: fnrs의 FnrsSharFormSection(재원협의 공유구분 트리)과 다름.
| 행 | JSP | SewerBscPlanFnrsCstItem |
|---|---|---|
| 총사업비 | arrTotAmnt |
sumAmt (또는 파생) |
| 국고 | arrNlepAmt |
gvexpAmt |
| 지방비 | arrLcepAmt |
lcexpAmt |
| 원인자부담금 | arrCusrAlotm |
orgprBdchgAmt |
| 기타 | arrEtcAmt |
etcAmt |
파일: ui/sections/fnrs-cst-form-section.tsx (신규)
데이터: fnrsCstList 길이 4 (planStpNo 1~4).
검증(선택): 단계별 gvexp+lcexp+orgpr+etc === sumAmt (JSP calculateTotalFunding 참고).
4-H. 처리시설별 하수도정비기본계획 (slide_14) — 핵심 복잡도
JSP 동작
BscFctList체크박스로 처리시설 다중 선택 (arrBscFctCd)- 선택 시
createFormSection(code, name)로 당초 4단계 | 현재 | 변경 4단계 매트릭스 동적 삽입
→ React: 세로 삽입 대신@common/componentsTabs로 시설별 패널 관리 (§아래 Tabs 규칙) - 활성
formFields(축소판): 처리구역면적, 하수처리인구, 계획하수량, 시설용량, 분류식 오수/우수, 합류식, 차집, 배수설비, 오수중계/일반/우수 펌프 - 시설별 필수첨부
createFileAttachmentSection fetchBasicPlanData로 당초(이전) 데이터 바인딩
API 매핑
| UI | DTO |
|---|---|
| 선택 시설 목록 | sewerBscPlanTmplntList[].swtrmtFcltCd (+ atchFileGroupId) |
| 단계별 수치 (변경측) | sewerBscPlanTmplntDtlList[] → SewerBscPlanTmplntDtlItem |
| 임시저장 | tmplntTmprStrgList (편집 중 임시, 필요 시) |
필드 대응 (변경 단계 기준):
| UI 라벨 | SewerBscPlanTmplntDtlItem |
|---|---|
| 처리구역면적 | prcsZoneArea |
| 하수처리인구 | swtrmtPpltnCnt |
| 계획하수량 | planSwqty |
| 시설용량 | fcltCpct |
| 분류식 오수 | sprsysDrtwPplLen |
| 분류식 우수 | sprsysExlnPplLen |
| 합류식 | cbsysPplLen |
| 차집관로 | icptgPplLen |
| 배수설비 | drgCnt |
| 오수 중계 펌프 | drtwRlyPumpCnt |
| 오수 일반 펌프 | drtwPumpCnt |
| 우수 펌프 | exlnPumpCnt |
구현 구성
ui/sections/tmplnt-form-section.tsx
├─ TmplntFacilityPicker # BscFctList Checkbox 목록 (시설 마스터 API TBD)
└─ Tabs (@common/components Tabs) # 선택 시설별 동적 패널
├─ TabsList / TabsTrigger # value=swtrmtFcltCd, 라벨=시설명
└─ TabsContent (시설 1개당)
├─ TmplntMatrixTable # 당초|현재|변경 매트릭스 (useFieldArray)
└─ TmplntFacilityAttachments # 시설별 필수첨부 (선택)
Tabs 관리 규칙 (packages/common/components/src/ui/tabs)
BscFctList체크 선택 →useFieldArrayappend + 해당 시설TabsTrigger/TabsContent추가 →Tabsvalue를 신규 시설로 전환- 체크 해제 → confirm 후 remove + 해당 탭 제거 → 남은 탭 중 하나로
value이동 (없으면 Tabs 영역 비표시) - 선택 시설이 0개면 Tabs UI 숨김; 1개 이상이면 Tabs로 시설별 패널 전환
- 매트릭스·첨부는 각
TabsContent안에만 렌더 (JSP의 세로 동적 삽입을 탭 패널로 대체)
매트릭스 열
- 당초 열: 이전계획 API 조회 결과 읽기 전용 (없으면 빈 칸)
- 현재 열: 기준년도 시점 값 (API 제공 시)
- 변경 열: 편집 가능 → 저장 payload의 dtl만 전송
시설 마스터 목록 API: 레거시 BscFctList 대체 — TBD (swtrmtFclt 계열).
bundle-dynamic-imports: TmplntFormSection(또는 TabsContent 내부 매트릭스)을 next/dynamic 후보.
4-I. 체크리스트 + 첨부 (slide_16)
I-1. 체크리스트
재사용: ChecklistFormSection
docSeComCd="<SEWER|DMBP TBD>"
fieldPrefix: 마스터에서 taskSeComCd를 읽는 경로 (예: sewerBscPlan)
| JSP | React |
|---|---|
업무탭 ceckEssntlArr |
코드 taskSeComCd 다중 → Tabs |
| 진행률 / 전체 예·아니오 | 위젯 내장 로직 |
exmntResult Y/N |
cklstResultList[].selected (+ picRvwCn) |
저장: cklstResultList: CklstResultItem[]
I-2. 필수 첨부 (탭별)
재사용: AttachmentsFormSection
docSeComCd 동일, esntlAtchFileList
레거시: 체크리스트 탭마다 essntlList + uploadFile multipart.
신규: TUS/attach-service + esntlAtchFileId / atchFileGroupId (fnrs와 동일).
I-3. 기타 첨부
AttachmentsFormSection의 etc 영역 또는 atchFileGroupId on sewerBscPlanDtl.
JSP uploadFileETC multiple → Zip 안내 문구 유지.
4-J. 저장 / 제출
UI 구성: fnrs-form-page.tsx 279~323 과 동일.
마크업·분기(isSplmntPrgrsStts / isEditMode)·버튼 색상·disabled={isSubmitting} 패턴을 그대로 두고, 호출 API·목록 path만 sewer 로 교체한다.
<div className="mx-4 flex flex-wrap justify-center gap-3 sm:gap-4">
<Button color="white" type="button" onClick={() => router.push("/sewer-bsc-plan")} disabled={isSubmitting}>
목록
</Button>
{!isSplmntPrgrsStts ? (
<>
<Button type="submit" disabled={isSubmitting}>저장</Button>
{isEditMode && (
<>
<Button color="green" type="button" onClick={handleApplyClick} disabled={isSubmitting}>
신청완료
</Button>
<Button color="red" type="button" onClick={handleDelClick} disabled={isSubmitting}>
삭제
</Button>
</>
)}
</>
) : (
<Button type="button" onClick={form.handleSubmit(onSplmntCmptn)} disabled={isSubmitting}>
보완완료
</Button>
)}
</div>
| 버튼 | fnrs 대응 | sewer API / 동작 |
|---|---|---|
| 목록 | router.push("/fnrs-cnsltn") |
router.push("/sewer-bsc-plan") |
| 저장 | saveApply + 임시저장 |
useSaveApplySewerBscPlan + prgrsSttsComCd=임시저장(SV) |
| 신청완료 | handleApplyClick → 제출 |
체크리스트+필수첨부 검증 → saveApply + LE (상태코드 TBD) |
| 삭제 | handleDelClick |
useDeleteSewerBscPlan(또는 동등) → 목록 |
| 보완완료 | onSplmntCmptn |
useSubmitSupplementSewerBscPlan |
| JSP | 진행값 | URL | React |
|---|---|---|---|
| 저장 | SAVE |
insertFnrscDmbp.do |
saveApply + 임시저장 코드 |
| 제출 | PRESENTN |
insertFnrscDscss.do (!) |
saveApply + 제출 상태코드 — 백엔드 상태코드 확인 TBD |
페이로드 조립 (buildApplyPayload):
SewerBscPlanApplySaveRequestDto {
sewerBscPlan, sewerBscPlanDtl,
sewerBscPlanOtlnList, bizCstList, fnrsCstList,
sewerBscPlanTmplntList, tmplntTmprStrgList?,
cklstResultList, esntlAtchFileList,
splmntDmndList?, rvwOpnnList? // 등록 화면에서는 보통 빈 배열
}
성공 후: invalidateQueries(sewerBscPlanBaseKey) → router.push('/sewer-bsc-plan') (신청완료는 상세로 보낼 수 있음 — fnrs와 동일 정책).
권한: JSP AUTH3 → 기존 AS 권한 훅/역할로 버튼 disabled/hidden.
5. API / DTO 연결
Base: /as-service/api/v1/sewer-bsc-plans
엔티티: @/entities/sewer-bsc-plan
| 화면 동작 | Hook / Service | 비고 |
|---|---|---|
| 등록 저장·제출 | useSaveApplySewerBscPlan → saveApply |
본 문서 핵심 |
| 수정 로드 | useSewerBscPlanDetails(docNo, chgCycl) |
편집 시 |
| 마스터만 | useSewerBscPlan |
목록 행 클릭 등 |
| 보완 제출 | useSubmitSupplementSewerBscPlan |
edit + prgrsSttsComCd=SL 시 폼 하단 [보완완료] |
| 기술검토 | useTechReviewSewerBscPlan |
등록 JSP 범위 밖 |
등록 JSP에 없는 섹션(보완요구·검토의견)은 상세/검토 화면에서 SplmntDmndFormSection / 검토의견 섹션으로 후속 구현.
6. 권장 파일 배치
apps/as/
├── app/(with-base-layout)/sewer-bsc-plan/
│ └── regist/page.tsx
├── src/pages/sewer-bsc-plan/
│ ├── lib/
│ │ ├── sewer-bsc-plan-regist-schema.ts # zod
│ │ └── form-data-mapper.ts # Det ↔ Form, Apply payload
│ ├── model/
│ │ └── (필요 시 table columns)
│ └── ui/
│ ├── sewer-bsc-plan-regist-page.tsx
│ ├── sewer-bsc-plan-form-page.tsx
│ ├── components/
│ │ └── previous-plan-lookup-dialog.tsx
│ └── sections/
│ ├── basic-info-form-section.tsx
│ ├── outline-form-section.tsx # 사업개요
│ ├── biz-cst-matrix-form-section.tsx # 총사업비 (전용)
│ ├── fnrs-cst-form-section.tsx # 재원분담
│ └── tmplnt-form-section.tsx # 처리시설 (Checkbox + Tabs)
└── docs/sewer-bsc-plan/
└── dmbp-regist-migration.md # 본 문서
공통 재사용 (신규 작성 최소화):
ContactInfoFormSection,PrivacyConsentSectionChecklistFormSection,AttachmentsFormSectionSectionCollapsibleTabs/TabsList/TabsTrigger/TabsContent(@common/components— 처리시설 패널)
도메인 전용 (재사용 금지):
BizCstMatrixFormSection— 총사업비 (fnrsBusinessCostFormSection미사용)- 폼 하단 액션바 —
fnrs-form-page279~323 복제, API만 sewer
7. 화면 데이터 흐름
BEGIN
// 최초 진입 (등록)
CALL 로그인사용자조회
CALL 코드조회(SEWERBSCPLANSE, SEWER, …) // 병렬
CALL 체크리스트트리(docSeComCd) // 병렬
CALL 필수첨부트리(docSeComCd) // 병렬
CALL 처리시설마스터목록 // TBD (BscFctList)
DISPLAY 폼 defaultValues
ON 1단계목표연도 CHANGE DO
SET 2·3·4단계 연도 (+5/+10/+15)
DISPLAY E/F/G/H 헤더 연도
END ON
ON 처리시설 체크 DO
ADD tmplntList 항목
ADD TabsTrigger / TabsContent (시설 패널)
SET Tabs value = 신규 시설
CALL 이전기본계획수치(시설코드) // 당초열, TBD
END ON
ON 처리시설 체크해제 DO
CONFIRM 제거
REMOVE tmplntList + 해당 Tabs 패널
SET Tabs value = 남은 시설 (없으면 Tabs 숨김)
END ON
ON [이전기본계획조회] CLICK DO
OPEN PreviousPlanLookupDialog
END ON
ON [저장] CLICK DO
VALIDATE zod (동의 제외 가능)
CALL saveApply(payload, 임시저장 상태)
NAVIGATE 목록
END ON
ON [신청완료] CLICK DO
VALIDATE zod + privacyAgree=Y + 체크리스트 완료 + 필수첨부(esntlAtchYn=Y) 완료
CONFIRM 신청 확인
CALL saveApply(payload, 제출 상태 LE)
NAVIGATE 상세
END ON
END
8. JSP ↔ 신규 갭·리스크
| # | 이슈 | 대응 |
|---|---|---|
| 1 | JSP 제출 URL이 dscss로 분기 (오타/구프로세스 가능) |
신규는 saveApply 단일 진입으로 통일 |
| 2 | 총사업비 UI 계층 ≠ BizCstItem |
BizCstMatrixFormSection 전용 + acntgSeCd 매핑 테이블 |
| 3 | 재원분담 ≠ fnrs shar | 전용 fnrs-cst-form-section |
| 4 | 처리시설 매트릭스(당초/현재/변경) | Checkbox 선택 → Tabs 패널; 저장은 변경 dtl 중심; 당초는 조회 전용 |
| 5 | 시설·이전계획 API | TBD — 미정 시 체크박스 목록 mock(faker)만 |
| 6 | docSeComCd 값 |
CMS/체크리스트 마스터와 합의 |
| 7 | 레거시 multipart vs TUS | fnrs 첨부 패턴 준수 |
| 8 | 주석 처리된 상세 formFields (자연발생인구 등) |
축소된 formFields만 이관; 주석 블록 복원 금지 |
9. 구현 순서 (권장)
- 라우트 +
FormPage골격 + zod 스키마(마스터·dtl·동의) + 폼 하단 액션바(§4-J) - B·C·D 섹션 (공통 위젯 최대 활용)
- E 사업개요 + G 재원분담 (4열 매트릭스 패턴 공유)
- F 총사업비 (
BizCstMatrixFormSection전용) - I 체크리스트·첨부
- H 처리시설 (
BscFctListCheckbox +@common/componentsTabs — 가장 복잡) - 저장/신청완료/삭제/보완완료 API 연동 (§4-J)
- 이전계획 Dialog (API 확정 후)
10. 체크리스트 (jsp-migration-as)
- contents만 이관 (include 제외)
- vercel-react-best-practices 적용 (Query 병렬·파생상태·dynamic)
@common/components+ 필요 시 DataTable- API·모델은
@/entities/sewer-bsc-plan우선 - 목데이터는
@faker-js/faker만 (시설 마스터 등 TBD 구간) - 로딩·빈·에러 상태
router.push로 목록 복귀
11. 후속 문서
- 목록(
dmbpList.jsp) / 상세(dmbpView.jsp) / 수정(dmbpModify.jsp)은 본 문서와 동일 섹션 체계로 별도 확장 - 화면설계서 SPEC 형식이 필요하면
docs/sewer-bsc-plan/SPEC.md로 분리 (영역 A~J 표 + API 표)