화면설계서: 검토인력관리
1. 기본 정보
| 항목 |
내용 |
| 버전 |
0.2 |
| 프로세스명 |
UI설계 |
| 화면명 |
검토인력관리 |
| 화면 유형 |
[v] 조회 [v] 입력 [ ] 수정 [v] 삭제 [ ] 출력 |
| 메뉴 경로 |
디지털행정지원 > 사이트관리 > 검토인력관리 |
2. 화면 목적
조직도에서 한 명의 사용자를 선택한 뒤, 결재 단계(접수·검토·승인·최종승인)별 인원 배치 영역에 즉시 등록한다. 등록·목록 갱신은 별도 저장 버튼 없이 [선택 인원 배치] 클릭 시 rvw-mnpw API로 바로 반영한다. 좌측 조직도는 CMS 조직·사용자 트리 API를, 우측 배치 목록은 검토인력관리 API를 사용한다.
3. 화면 구성
3-1. 전체 레이아웃
3-2. 화면 데이터 흐름
4. 영역 A — 조직도
4-1. 표시·상호작용
| 요소 |
내용 |
| 섹션 제목 |
조직도 |
| 검색 폼 (A-1) |
성명·부서 키워드 입력 + [조회] + [초기화] — §4-3 |
| 선택 안내 문구 |
선택된 인원: {userNm} ({ognzNm} / {직급표시}) — 미선택 시 안내 문구 |
| 트리 (A-2) |
본부 → 팀 계층 + 팀 소속 사용자 목록 (displayTree 기준 표시) |
| 선택 규칙 |
사용자 1명만 선택 가능 (라디오형 단일 선택) |
| 선택 시각 피드백 |
선택된 사용자 행 강조(배경·테두리) |
| 로딩/오류/빈값 |
Skeleton / 오류 문구 / "등록된 조직/사용자가 없습니다." |
| 검색 결과 없음 |
필터 후 매칭 노드·사용자 0건. "조회된 인원이 없습니다." 문구 노출 |
4-2. 조직도 데이터 매핑
| UI 표시 |
트리 DTO 필드 (OgnzUserTreeResponseDto) |
비고 |
| 조직명 |
ognzNm |
접기/펼치기 노드 |
| 사용자명 |
users[].userNm |
클릭 시 선택 |
| 부서(안내 문구) |
ognzNm (소속 팀 노드) |
선택 시 selectedPerson.ognzNm |
| 직급(안내 문구) |
users[].jbgdSeCd 또는 jbpsSeCd |
공통코드 라벨 변환 |
| 저장용 조직 SN |
ognzSn |
사용자가 속한 리프/팀 노드의 ognzSn |
| 저장용 사용자 |
users[].userUnqId |
API body userUuid로 전달 (§6-3) |
4-3. 조직도 검색 (영역 A-1)
결재선 관리 AprvrPickerDialog와 동일한 클라이언트 사이드 필터 패턴을 사용한다. 별도 검색 API는 없으며, useOgnzUserTree로 받은 원본 트리를 filterOgnzUserTree로 가공해 displayTree에 반영한다.
필드 정의
| 표시명 |
입력 유형 |
필수 |
기본값 |
API 파라미터 매핑 |
비고 |
| 성명·부서 검색 |
Text |
N |
(빈값) |
— (클라이언트만) |
placeholder="성명·부서 검색" |
| 조회 |
Button |
— |
— |
— |
type="submit" — 폼 제출 시 필터 적용 |
| 초기화 |
Button |
— |
— |
— |
type="button" — 키워드·트리·펼침 초기화 |
필터 규칙 (filterOgnzUserTree)
| 대상 |
매칭 조건 |
| 조직명 |
ognzNm에 키워드 포함 (대소문자 무시) |
| 사용자명 |
userNm에 키워드 포함 (대소문자 무시) |
| 조직 매칭 시 |
해당 노드 소속 사용자 전원 유지 |
| 사용자만 매칭 시 |
매칭 사용자만 남기고 상위 조직 노드는 유지(경로 보존) |
| 하위 조직 |
재귀 필터 — 자식·손자 노드 매칭 시 상위도 표시 |
| 키워드 빈값 |
원본 트리 전체 반환 |
조회 후 트리 펼침 (collectExpandedOgnzSnIds)
- [조회] 성공 후 필터 결과 트리의 모든 노드
ognzSn을 expandedOgnzSnIds에 넣어 자동 펼침
- 검색 결과에서 사용자·하위 조직을 바로 확인할 수 있도록 함
초기화 동작
| 상태 |
초기화 후 값 |
keyword |
"" |
displayTree |
useOgnzUserTree 원본 data |
expandedOgnzSnIds |
new Set() (전체 접힘) |
selectedPerson |
유지 — 검색 초기화와 선택 해제 분리 |
버튼
| 버튼명 |
동작 |
| 조회 |
filterOgnzUserTree(data, keyword) → displayTree 갱신 |
| 초기화 |
키워드·표시 트리·펼침 상태 리셋 (§3-2 ON [초기화] 블록) |
5. 영역 B — 인원 배치
5-1. 블록 공통
| 요소 |
내용 |
| 블록 제목 |
접수 / 검토 / 승인 / 최종승인 |
| 건수 뱃지 |
해당 atrzSeComCd에 배치된 인원 수 |
| 액션 버튼 |
[선택 인원 배치] — 클릭 시 즉시 save (§3-2) |
| 빈 상태 |
"배치된 인원이 없습니다." |
| 배치 목록(있을 때) |
인원명·부서·직급 등 |
5-2. 결재구분 ↔ 블록 매핑
| 블록 |
UI 제목 |
atrzSeComCd |
비고 |
| B-1 |
접수 |
ATRZ00 |
결재선 관리 ATRZ_RECEIVER_CD와 동일 |
| B-2 |
검토 |
ATRZ01 |
결재선 ATRZ_REVIEWER_1_CD. ATRZ02 별도 블록 여부 — TBD |
| B-3 |
승인 |
ATRZ03 |
결재선 ATRZ_APPROVER_CD |
| B-4 |
최종승인 |
ATRZ99 |
결재선 ATRZ_FINAL_CD |
공통코드 마스터 ATRZSE / 화면 셀렉트용 ATRZSECD와 정합성은 배포 환경 코드표로 최종 확인.
5-3. 배치 목록 항목 (표시)
| 표시명 |
Field (응답 DTO) |
비고 |
| 사용자명 |
userUuidNm |
@CodeName 미적용 시 TBD |
| 결재구분 |
atrzSeComCdNm |
블록 제목과 중복 — 생략 가능 |
| 조직 SN |
ognzSn |
삭제 API path에 사용 |
| 사용자 |
userUuid |
삭제 API path에 사용 |
5-4. 버튼
| 버튼명 |
위치 |
동작 |
| 선택 인원 배치 |
각 B-k 헤더 |
save 후 목록·뱃지 갱신 (§3-2) |
| 제거 |
목록 항목 |
delete 후 목록·뱃지 갱신 (§3-2) |
5-5. 검증·제약
| 규칙 |
내용 |
| 선택 필수 |
[선택 인원 배치] 시 selectedPerson 없으면 버튼 비활성 또는 안내 |
| 단일 선택 |
조직도에서 사용자 1명만 selectedPerson 유지 |
| 중복 등록 |
동일 PK (atrzSeComCd, ognzSn, userUuid) 재등록 시 서버 오류 |
| 다건 배치 |
동일 블록에 서로 다른 사용자·조직은 복수 행 가능 (PK가 다름) |
| 결재구분 변경 |
본 화면 주 흐름은 save만 |
6. API/DTO 명세
6-1. 공통
| 항목 |
내용 |
| 인증 |
JWT (Authorization 헤더) |
| 페이징 |
Spring Pageable: page, size, sort → PageResponse<T> |
| 프론트 엔티티 |
@/entities/user-organization, @/entities/rvw-mnpw |
6-2. 조직·사용자 트리 (영역 A) — user-ognz
| 항목 |
내용 |
| 서비스 |
cms-service |
| Base prefix |
/cms-service/api/v1/user-ognz |
| 기능 |
Method |
URL |
Request DTO |
Response DTO |
API |
| 조직·사용자 트리 |
GET |
/treeuser |
— |
OgnzUserTreeResponseDto[] |
userOgnzService.findOgnzUserTree |
OgnzUserTreeResponseDto: ognzSn, upOgnzSn, ognzNm, users[], children[]
OgnzUserTreeUserDto: userUnqId, userNm, jbpsSeCd, jbgdSeCd
React Query: useOgnzUserTree
6-3. 검토인력관리 (영역 B) — rvw-mnpw
| 항목 |
내용 |
| 서비스 |
as-service |
| Base prefix |
/as-service/api/v1/rvw-mnpw |
| ENDPOINT |
ENDPOINT.AS_COMMON_SERVICE.RVW_MNPW |
| 기능 |
Method |
URL |
Request DTO / Query |
Response DTO |
API |
| 목록 조회 |
GET |
/ |
RvwMnpwMngSearchDto + Pageable |
Page<RvwMnpwMngResponseDto> |
rvwMnpwMngService.findPage |
| 상세 조회 |
GET |
/{atrzSeComCd}/{ognzSn}/{userUuid} |
Path |
RvwMnpwMngResponseDto |
rvwMnpwMngService.findById |
| 등록(즉시 배치) |
POST |
/ |
RvwMnpwMngSaveRequestDto |
RvwMnpwMngResponseDto (201) |
rvwMnpwMngService.save |
| 결재구분 변경 |
PUT |
/{atrzSeComCd}/{ognzSn}/{userUuid} |
RvwMnpwMngUpdateRequestDto |
RvwMnpwMngResponseDto |
rvwMnpwMngService.update |
| 삭제 |
DELETE |
/{atrzSeComCd}/{ognzSn}/{userUuid} |
Path |
string |
rvwMnpwMngService.delete |
RvwMnpwMngSearchDto: atrzSeComCd?, ognzSn?, userUuid? + page, size, sort
RvwMnpwMngSaveRequestDto: atrzSeComCd*, ognzSn*, userUuid*
RvwMnpwMngUpdateRequestDto: newAtrzSeComCd* — 본 화면 기본 흐름에서는 미사용
RvwMnpwMngResponseDto: atrzSeComCd, atrzSeComCdNm?, ognzSn, userUuid, userUuidNm?, rgtr?, regDt?
6-4. 조직도 ↔ 검토인력 필드 매핑 (저장 시)
조직도 (OgnzUserTreeUserDto + 노드) |
RvwMnpwMngSaveRequestDto |
비고 |
(블록 k의 atrzSeComCd) |
atrzSeComCd |
§5-2 표 |
소속 팀 ognzSn |
ognzSn |
|
userUnqId |
userUuid |
문자열(UUID)로 직렬화 |
7. UI 구현 가이드
7-1. 기술 스택·원칙
- 공통 컴포넌트:
@common/components (Button, Badge, Card 또는 섹션 레이아웃)
- 데이터: React Query —
useOgnzUserTree, useRvwMnpwMngPage, useSaveRvwMnpwMng, useDeleteRvwMnpwMng
- 상태:
selectedPerson(단일), keyword, displayTree, expandedOgnzSnIds, 블록별 배치 목록(서버 데이터 파생)
- 조직도 검색:
filterOgnzUserTree, collectExpandedOgnzSnIds (widgets/ognz-user-tree/lib 또는 페이지 lib)
- 저장 UX: 별도 화면 저장 없음 — [선택 인원 배치] =
save mutation 즉시 호출
- 조직도 UI: 결재선 관리
ognz-user-tree.tsx를 widgets로 승격해 공통화
7-2. 모듈·파일 배치(제안)
| 구분 |
경로 |
| 라우트 |
apps/as/app/(with-base-layout)/rvw-mnpw-mng/page.tsx |
| 페이지 |
apps/as/src/pages/rvw-mnpw-mng/ |
| UI |
.../ui/rvw-mnpw-mng-page.tsx, rvw-mnpw-assignment-panel.tsx 등 |
| model |
.../model/selected-ognz-user.ts, rvw-mnpw-block-config.ts (atrzSeComCd 상수) |
| lib |
.../lib/group-rvw-mnpw-by-atrz-se.ts (목록 → B-1~B-4 분배) |
| 위젯 |
apps/as/src/widgets/ognz-user-tree/ — 아래 이전 대상 |
| 엔티티 |
entities/user-organization/, entities/rvw-mnpw/ (구현 완료) |
widgets/ognz-user-tree 이전 (결재선 → 공통)
| 현재 (결재선 관리) |
이전 후 (widgets) |
pages/approval-line-management/ui/ognz-user-tree.tsx |
widgets/ognz-user-tree/ui/ognz-user-tree.tsx |
pages/.../ui/ognz-user-tree-node.tsx |
widgets/ognz-user-tree/ui/ognz-user-tree-node.tsx |
pages/.../model/reviewer-option.ts |
widgets/ognz-user-tree/model/selected-ognz-user.ts (이름·필드 확장: ognzSn 필수) |
pages/.../lib/filter-ognz-user-tree.ts |
widgets/ognz-user-tree/lib/filter-ognz-user-tree.ts (필수 — 검색 공통화) |
widgets/ognz-user-tree/index.ts |
OgnzUserTree, OgnzUserTreeNode, 타입 export |
결재선 AprvrPickerDialog는 @/widgets/ognz-user-tree import로 교체. 검토인력관리 페이지는 인라인 조직도(다이얼로그 없음)로 동일 위젯 사용.
SelectedOgnzUser — ReviewerOption 확장:
7-3. 영역별 UI 매핑
| 영역 |
주요 UI |
| A-1 |
검색 폼 (Input + 조회/초기화) — AprvrPickerDialog 90~103행 패턴 |
| A-2 |
OgnzUserTree(nodes={displayTree}) + 선택 안내 + useOgnzUserTree |
| B-k |
제목·Badge(count)·선택 인원 배치·배치 목록(또는 empty) |
| 공통 |
페이지 헤더·브레드크럼·2열 레이아웃 (grid / flex, 모바일은 스택) |
7-4. 다이얼로그·라우팅
| 항목 |
내용 |
| 다이얼로그 |
없음 (조직도 인라인, 즉시 저장) |
| 라우팅 |
메뉴 검토인력관리 단일 페이지 |
7-5. 데이터 흐름(구현 요약)
- 진입:
useOgnzUserTree → displayTree = data + useRvwMnpwMngPage({ page: 0, size: N }) → 4패널.
- 검색:
keyword 로컬 상태 → [조회] 시 filterOgnzUserTree + collectExpandedOgnzSnIds → OgnzUserTree에 displayTree 전달.
- 초기화:
keyword·displayTree·expandedOgnzSnIds 리셋 (selectedPerson 유지).
- 선택: 트리
onSelect → selectedPerson (반드시 ognzSn 포함).
- 배치:
useSaveRvwMnpwMng().mutate({ atrzSeComCd, ognzSn, userUuid }) → onSuccess에서 rvw-mnpw query invalidate.
- 삭제: 목록 항목에서
useDeleteRvwMnpwMng — UI 확정 후 연결.
7-6. 미확정 / 검증 필요