화면설계서: 결재선 관리
1. 기본 정보
| 항목 |
내용 |
| 버전 |
0.3 |
| 프로세스명 |
UI설계 |
| 화면명 |
결재선 관리 |
| 화면 유형 |
[v] 조회 [v] 입력 [v] 수정 [v] 삭제 [ ] 출력 |
| 메뉴 경로 |
디지털행정지원 > 시스템관리 > 결재선 관리 |
2. 화면 목적
전자결재 처리에 사용할 결재서식(템플릿)을 등록·관리하고, 각 서식별로 결재선(결재구분·결재자·순서)을 구성한다. 상단의 결재서식 목록에서 하나를 선택하면 하단 영역에 해당 서식의 결재선이 표시되며, 사용자는 그리드 인라인 폼으로 결재자를 등록·수정한다. 행 추가 또는 한 행 수정 중에는 다른 행을 편집할 수 없다(단일 행 편집 잠금). 드래그로 순서를 변경한 뒤 [결재선 저장] 으로 서버에 반영한다.
3. 화면 구성
3-1. 전체 레이아웃
3-2. 화면 데이터 흐름
4. 영역 A: 전자결재선 관리 목록
선택된 결재서식이 영역 B의 작업 대상이 된다. 행 클릭으로 선택 상태를 표시(좌측 컬러 바·배경 강조)한다.
4-1. 헤더 / 툴바
| 항목 |
내용 |
| 섹션 타이틀 |
전자결재선 관리 목록 |
| 우측 버튼 |
[서식 등록] — 결재서식 등록 다이얼로그 오픈 |
4-2. 그리드 컬럼
| 컬럼명 |
Field |
타입 |
비고 |
| 전자결재서식아이디 |
elaprTmpltId |
string |
등록 시 서버(DB 함수) 자동 발급 |
| 결재서식명 |
elaprTmpltNm |
string |
|
| 문서구분 |
docSeComNm |
string |
코드 docSeComCd, 상위코드 ASDOCSECD |
| 등록일시 |
regDt |
string |
yyyy-MM-dd HH:mm:ss |
| 관리 |
— |
— |
행별 [수정] · [삭제] 버튼 |
- 행 클릭 시:
elaprTmpltId 선택 → 영역 B 라벨·B-2 그리드 갱신.
- 페이지네이션: Spring
Pageable (page, size, sort).
4-3. 버튼
| 버튼명 |
위치 |
동작 |
| 서식 등록 |
섹션 우측 상단 |
결재서식 등록 다이얼로그 오픈 |
| 수정 |
행별 |
결재서식 수정 다이얼로그 (기존 값 초기화) |
| 삭제 |
행별 |
확인 후 삭제. 선택 중인 서식이면 영역 B 초기화. |
4-4. 다이얼로그(개요)
| 다이얼로그명 |
트리거 |
입력 항목 |
비고 |
| 결재서식 등록 |
[서식 등록] |
elaprTmpltNm, docSeComCd |
elaprTmpltExpln 선택, ID는 저장 후 응답 |
| 결재서식 수정 |
행별 [수정] |
elaprTmpltNm, docSeComCd, elaprTmpltExpln |
ID는 변경 불가 |
| 결재서식 삭제 확인 |
행별 [삭제] |
(확인/취소) |
|
5. 영역 B: 결재선 관리
영역 A에서 선택된 elaprTmpltId 기준으로 결재선을 관리한다. 등록·수정은 B-2 그리드 인라인 폼으로 수행하며, 검토인력 지정만 [선택] 보조 다이얼로그를 사용한다.
5-1. 헤더 / 툴바
| 항목 |
내용 |
| 섹션 타이틀 |
결재선 관리 |
| 우측 라벨 |
선택된 서식: {elaprTmpltId} — 미선택 시 영역 B 비활성 |
| 우측 버튼 |
[행 추가] — 편집 중인 행이 없을 때만 활성 · [결재선 저장] — 편집 중인 행이 없을 때만 활성(순서·미저장 행 일괄 반영) |
5-2. 영역 B-2: 결재선 그리드 (인라인 편집)
그리드 컬럼
| 컬럼명 |
Field |
입력 UI (편집 모드) |
비고 |
| (드래그 핸들) |
— |
— |
useSortable 연동 |
| 결재선아이디 |
aplnId |
읽기 전용 |
신규 행: —, 저장 후 서버 aplnId 표시 |
| 결재순서번호 |
atrzSeqNo |
읽기 전용 (그리드 행 순서 1부터 표시) |
저장 시 행 순서 기준 자동 채번 |
| 결재구분 |
atrzSeComCd |
Select (ATRZSECD 공통코드) |
표시명 atrzSeComNm (조회 행) |
| 결재자 |
aprvrUuid |
읽기 전용 이름 + [선택] 버튼 |
응답에 성명 없음 — 선택 시 로컬 aprvrNm 유지 |
| 등록일시 |
regDt |
읽기 전용 |
신규 행은 — |
| 관리 |
— |
편집 중인 행: [저장] [취소] · 조회 행: [수정] [삭제] (다른 행 편집 중이면 비활성) |
|
인라인 편집 정책
| 항목 |
내용 |
| 단일 행 편집 |
행 추가 또는 한 행 수정 중에는 다른 행을 편집할 수 없다. editingRowId 로 현재 편집 행 1건만 허용. |
| 편집 잠금 시 비활성 |
다른 행: 셀·[수정]·[삭제] 비활성 · [행 추가] 비활성 · 행 드래그 비활성 · (선택) [결재선 저장] 비활성 |
| 편집 해제 |
행별 [저장] 성공 또는 [취소] 시 editingRowId 초기화 후 전체 조회 모드 복귀 |
| 조회 행 |
편집 중이 아닐 때 읽기 전용. [수정] 클릭 시 해당 행만 편집 모드 진입 |
| 신규 행 |
[행 추가] 시 맨 아래 편집 행 1건 생성 (editingRowId = 임시 키) |
| 필수값 |
atrzSeComCd, aprvrUuid |
| 순서 중복 |
저장 시 행 순서로 자동 채번하므로 중복 없음 |
| 결재구분 코드 |
ATRZSECD — 예: ATRZ01 검토자, ATRZ02 승인자, ATRZ03 최종승인자 |
| 순서 제약 |
ATRZ01은 최상단 블록, ATRZ03은 최하단 블록. 드래그 종료·저장 시 validateAtrzOrder로 검증, 위반 시 적용/저장 불가 (결재구분 변경 시에는 미검증) |
| 저장 단위 |
행별 [저장] (단건 POST/PUT) 또는 툴바 [결재선 저장] (일괄) |
행 드래그 정렬 (@dnd-kit + useSortable)
| 항목 |
내용 |
| 목적 |
결재 단계 순서를 그리드에서 직접 변경 |
| 라이브러리 |
@dnd-kit/core, @dnd-kit/sortable — 테이블 행 POC 후 확정 |
| 저장 시점 |
드래그는 클라이언트 상태만 변경 → [결재선 저장] 또는 행별 [저장] 시 atrzSeqNo PUT |
| 편집 중 |
editingRowKey != null 이면 드래그 불가 |
| 순서 제약 |
드래그 종료 시 validateAtrzOrder — 실패하면 순서 변경 미적용 + 안내. 결재구분 미선택 행은 드래그 불가 |
5-3. 보조 다이얼로그 (검토인력만)
| 다이얼로그명 |
트리거 |
결과 |
| 검토인력 선택 |
그리드 결재자 셀 [선택] |
aprvrUuid 및 UI용 aprvrNm 반영 |
결재자 등록·수정 다이얼로그는 사용하지 않음 (v0.2 변경).
6. API/DTO 명세
6-1. 공통
| 항목 |
내용 |
| 서비스 |
as-elapr-service |
| Base prefix |
/as-elapr-service/api/v1 (프록시 경유) |
| 인증 |
JWT (Authorization 헤더) |
| 페이징 |
Spring Pageable: page, size, sort → PageResponse<T> |
| 엔티티 |
@/entities/elapr (elaprTmpltService, elaprAplnService) |
6-2. 전자결재서식 (영역 A) — elapr-tmplt
| 기능 |
Method |
URL |
Request / Query |
Response |
클라이언트 |
| 목록 조회 |
GET |
/elapr-tmplt |
Query: ElaprTmpltSearchParams + Pageable |
Page<ElaprTmplt> |
elaprTmpltService.findPage |
| 단건 조회 |
GET |
/elapr-tmplt/{elaprTmpltId} |
— |
ElaprTmplt |
elaprTmpltService.findById |
| 등록 |
POST |
/elapr-tmplt |
ElaprTmpltSaveRequest |
ElaprTmplt (201) |
elaprTmpltService.create |
| 수정 |
PUT |
/elapr-tmplt/{elaprTmpltId} |
ElaprTmpltUpdateRequest |
ElaprTmplt |
elaprTmpltService.update |
| 삭제 |
DELETE |
/elapr-tmplt/{elaprTmpltId} |
— |
204 |
elaprTmpltService.remove |
ElaprTmplt (응답)
| Field |
타입 |
설명 |
elaprTmpltId |
string |
전자결재서식아이디 |
elaprTmpltNm |
string |
결재서식명 |
elaprTmpltExpln |
string? |
서식 설명 |
docSeComCd |
string? |
문서구분 코드 |
docSeComNm |
string? |
문서구분명 |
regDt |
string? |
등록일시 |
ElaprTmpltSaveRequest: elaprTmpltNm_, elaprTmpltExpln?, docSeComCd?
ElaprTmpltUpdateRequest: elaprTmpltNm*, elaprTmpltExpln?, docSeComCd?
ElaprTmpltSearchParams: elaprTmpltNm?, docSeComCd?, regDtStart?, regDtEnd? + page, size, sort
6-3. 결재선 (영역 B) — elapr-apln
| 기능 |
Method |
URL |
Request / Query |
Response |
클라이언트 |
| 목록 조회 |
GET |
/elapr-apln |
Query: elaprTmpltId, Pageable |
Page<ElaprApln> |
elaprAplnService.findPage |
| 단건 조회 |
GET |
/elapr-apln/{aplnId} |
— |
ElaprApln |
elaprAplnService.findById |
| 등록 |
POST |
/elapr-apln |
ElaprAplnSaveRequest |
ElaprApln (201) |
elaprAplnService.create |
| 수정 |
PUT |
/elapr-apln/{aplnId} |
ElaprAplnUpdateRequest |
ElaprApln |
elaprAplnService.update |
| 삭제 |
DELETE |
/elapr-apln/{aplnId} |
— |
204 |
elaprAplnService.remove |
일괄 저장 API 없음 — UI의 [결재선 저장]은 변경된 행에 대해 POST/PUT을 순차(또는 병렬) 호출하는 클라이언트 오케스트레이션으로 구현.
ElaprApln (응답)
| Field |
타입 |
설명 |
aplnId |
string |
결재선아이디 |
elaprTmpltId |
string |
전자결재서식아이디 |
aprvrUuid |
string? |
결재자 UUID |
atrzSeComCd |
string? |
결재구분 코드 |
atrzSeComNm |
string? |
결재구분명 |
atrzSeqNo |
number? |
결재순서번호 |
regDt |
string? |
등록일시 |
ElaprAplnSaveRequest: elaprTmpltId_, aprvrUuid?, atrzSeComCd?, atrzSeqNo?
ElaprAplnUpdateRequest: elaprTmpltId*, aprvrUuid?, atrzSeComCd?, atrzSeqNo?
6-4. 검토인력 (보조)
| 기능 |
Method |
URL |
비고 |
| 검토인력 목록 조회 |
TBD |
TBD |
사용자 서비스 또는 별도 API |
6-5. Backend ↔ 화면 필드 매핑 (구 SPEC 대비)
| 구 SPEC 필드 |
백엔드 필드 |
elctAtrzTmpltId |
elaprTmpltId |
atrzTmpltNm |
elaprTmpltNm |
docSeNm |
docSeComNm |
atrzLineId |
aplnId |
atrzSeNm |
atrzSeComNm |
atrzUserNm |
(없음) aprvrUuid + 사용자 조회/선택 시 로컬 표시명 |
7. UI 구현 가이드
7-1. 기술 스택·원칙
- 공통 컴포넌트:
@common/components
- 테이블:
@tanstack/react-table + 인라인 편집 셀 (Select, Input, Button)
- 드래그:
@dnd-kit — B-2 행 정렬 (POC 필수)
- 데이터: React Query —
@/entities/elapr hooks
- 상태: 선택된
elaprTmpltId, editingRowId (단일 행 편집 잠금), B-2 행 배열(dirty·신규·aprvrNm·수정 전 스냅샷)
- 모의 데이터: API 연동 전
@faker-js/faker
7-2. 모듈·파일 배치(제안)
| 구분 |
경로 |
| 라우트 |
apps/as/app/(with-base-layout)/approval-line-management/page.tsx |
| 페이지 |
apps/as/src/pages/approval-line-management/ (Public API: page만 export) |
| UI |
.../ui/elapr-tmplt-list.tsx, elapr-tmplt-form-dialog.tsx, elapr-apln-grid.tsx 등 |
| model |
.../model/columns.tsx, apln-row-types.ts, mock-reviewers.ts |
| lib |
.../lib/use-apln-rows.ts, validators.ts, use-dnd-sensors.ts |
| 엔티티 |
apps/as/src/entities/elapr/ |
7-3. 영역별 UI 매핑
| 영역 |
주요 UI |
| A |
DataTable + 행 선택 + 서식 등록/수정 다이얼로그 |
| B 헤더 |
상태 라벨 + 행 추가, 결재선 저장 |
| B-2 |
인라인 편집 DataTable + editingRowId 단일 행 잠금 + 드래그 핸들 + 행별 수정/저장/삭제/취소 |
| 공통 |
서식 Dialog, 검토인력 선택 Dialog만 |
7-4. 데이터 흐름(요약)
- 진입:
useElaprTmpltPage → 영역 A. B 비활성.
- 서식 선택:
useElaprAplnPage({ elaprTmpltId }) → B-2.
- 행 추가:
editingRowId 없을 때만 가능 → 신규 행 1건 편집 잠금 → 저장/취소 후 해제.
- 인라인 수정: [수정]으로
editingRowId 설정 → 해당 행만 편집 → useUpdateElaprApln 후 해제.
- 드래그:
editingRowId == null 일 때만 가능 → 로컬 atrzSeqNo 재부여 → 일괄 PUT.
- 삭제:
useDeleteElaprApln 또는 신규 행 로컬 제거.
7-5. 미확정 / 검증 필요
- 검토인력 API 경로·DTO.
@dnd-kit + react-table 행 인라인 Input 동시 적용 POC.
- 결재자 성명 표시:
aprvrUuid → 사용자명 조회 API.
- 영역 A·B 페이지네이션·검색 UI 노출 여부.
- 권한(역할별 CRUD).