Skip to content

ProcessCenter 검토 노트 — 프로세스관리 프로그램 관점 ​

작성: 2026-09-18 (자율 검토 세션) 방법: 코드베이스 실측(라우터·리포지토리·화면·테스트) 기반. 목적은 "있는 것"과 "빠진 것"을 구분하고 다음 작업 우선순위를 제안하는 것.

1. 현재 갖춘 것 (실측) ​

영역구현근거
프로세스 계층L1~L7 트리, 레벨별 코드·명칭, 게시본·버전 이력ProcessManagementPanel, ProcessWorkspace, shared/process
흐름 설계L4 통합맵, L5 워크플로우(L6 단계·의사결정·자동 조건), 외부유입/유출/왕복features/workflow-map
표준 교환BPMN 2.0 subset 내보내기/가져오기, PDF 인쇄domain/bpmn*, workflowMapExport, printWorkflowPdf
통제결재규정(L5 기본 · L6 예외 · Ad-hoc), RACI·역할자 마스터ApprovalPolicyManager, RoleSystemMasterManager
거버넌스게시/버전 이력, 변경 이력, 감사 로그, 검토 요청 알림ProcessVersionHistory, AdminConsole, 알림 센터
조직·사용자디렉터리 동기화, 조직 접근 관리directory-gateway, OrganizationAccessManager
지식용어집, 첨부파일(인증 blob), L7 시스템 조작 매뉴얼TerminologyManager, AssetAttachmentList
운영 점검라우팅 실패·미연결/고립 탐지, AI 변경 요약, 재시도 큐classifyWorkflowEndpoints, processVersionAiService, RetryQueuePanel
일관성공용 portal-foundation(Ant Design) 적용, 아이콘 전용 버튼 규칙docs/ANT_DESIGN_REFACTOR.md, docs/BUTTON_ICON_ONLY_PLAN.md

즉 "프로세스를 정의하고(L1~L7), 흐름을 그리고(L4/L5), 통제·게시하고, 조직에 연결하고, 변경을 추적한다"는 핵심 골격은 이미 갖춰져 있다.

2. 프로세스관리 관점에서 빠진 것 (권고) ​

우선순위 = 효과 × 실현성. 1~2번은 이미 있는 데이터로 계산 가능하므로 투자 대비 효과가 가장 크다.

2-1. 설계 품질 점검 요약 — 최우선 ​

getWorkflowValidation과 classifyWorkflowEndpoints가 이미 미연결·고아·종료 미지정·유입/유출 미지정을 계산한다. 그런데 결과가 개별 경고로만 보여 전체 상태를 알 수 없다.

  • 제안: 관리자 화면에 "설계 품질" 카드 — 미연결 N · 고아 N · 종료 미지정 N · 승인규정 누락 N. 클릭하면 해당 L5로 이동.
  • 효과: "그림은 있는데 흐름이 이어지지 않는" 프로세스를 게시 전에 걸러낸다. (프로세스관리에서 가장 흔한 사고)

2-2. 영향도 분석(Impact analysis) ​

핸드오프 그래프(A→B)가 이미 저장되어 있으므로 "이 L5를 바꾸면 누가 영향받는가"를 계산할 수 있다.

  • 제안: L5 상세에 "이 프로세스를 호출하는 L5 / 이 프로세스가 호출하는 L5" 섹션을 명시화(현재 유입/유출 카드가 부분적으로 담당) + 변경 전 확인 체크리스트.

2-3. 변경 사유·승인 단계 ​

게시 이력은 있으나 "왜 바뀌었는지"가 선택 입력이고 승인은 규정 기반 자동에 머문다.

  • 제안: 게시 시 변경 사유 필수 + 검토자 지정(기존 알림 재사용). 감사 대응력이 크게 올라간다.

2-4. 운영 지표(리드타임·병목) — 장기 ​

실행 로그가 없으면 계산할 수 없다. 지금은 설계 데이터만 있다.

  • 제안: 먼저 2-1(설계 지표)로 시작하고, 실행 로그 수집은 별도 과제로 분리한다(데이터 모델·수집 경로 신설 필요).

2-5. 일괄 내보내기 ​

엑셀 가져오기(일괄 등록)는 있는데 내보내기가 없다(CSV는 변경 이력만).

  • 제안: 프로세스 목록·흐름 점검 결과 엑셀 내보내기.

2-6. 검색·입력 품질 ​

검색은 코드·이름 중심이고, 코드 중복·형식·필수 항목 검증이 화면별로 흩어져 있다. 공통 검증 규칙으로 모으는 것이 좋다.

3. 이번 세션에서 실제로 한 일 ​

원칙: 되돌리기 쉬운 것만 손댔다. 위 2장의 제품 기능은 사용자 확인 없이 UI를 바꾸지 않고 문서로만 제안한다.

  1. UI 정책에 맞춰 화면 버튼을 공용 PortalButton(Ant Design)으로 전환 — 17개 완료
    • TaskFlowMap: PDF · BPMN · 다시 시도 · 하위 L6 동기화
    • WorkflowConnectionSummary: 전체 카드 선후행 현황 보기 / WorkflowConnectionOverviewModal: 닫기
    • WorkflowEntityRelationshipEditor: 선행 연결 저장 · 병렬 후행 연결 저장
    • WorkflowEntityPropertyEditor: 타 L5 추가 · 의사결정 추가 · 자동 조건 분기 추가 · START/END 추가·제거 · 엔티티 삭제 · 원본 L5 열기
    • IntegratedWorkflowMap: PDF · BPMN · 접기
  2. PDF/BPMN 버튼 겹침 해결 — 두 맵 모두 우상단 flex + gap-2 한 행으로 묶었다. 회귀 테스트로 "같은 flex 행에 있어 겹치지 않는다"를 고정.
  3. docs/BUTTON_INVENTORY.md 재생성, 이 검토 노트 작성.
  4. 검증: pnpm check 0 오류 · 전체 69파일 413개 통과 · 앱 200

4. 남은 작업 지시서 (다음 세션용) ​

4-1. 버튼 전환 잔여 — 86개 ​

파일별 개수(상위): ApprovalPolicyManager 6 · ConnectionHealthReport 6 · DirectoryOrganizationListPanel 6 · DirectoryUserDetailPanel 6 · PortalGroupManagement 5 · OrganizationAccessManager 5 · RoleSystemMasterManager 5 · AdminProcessTree 4 · PortalOperationSettings 4 · NoticeBoard 3 · DirectoryUserAccessPanel 3 · WorkflowGatewayEntityDetail 3 · CatalogTransferManager 3 · ProcessManagementPanel 2 · RetryQueuePanel 2 · TerminologyManager 2 · AdminConsole 2 · ProcessNotificationCenter 2 · AIChatBox 2 · DirectoryUserListPanel 2 · DirectoryOrganizationDetailPanel 2 + 단건.

전환 규칙(이번 세션에서 확정):

  • <button className="editorial-button …"> → <PortalButton variant="outline|primary|danger|ghost" size="sm" icon={…} loading={…}>
  • disabled/onClick 그대로, className에서 위치·레이아웃 클래스만 유지
  • testId prop은 공용 타입에 없다 → 테스트는 getByRole("button", { name })로 바꾼다(정책 문서와 동일)
  • 위치가 absolute right-*로 흩어진 버튼들은 부모 flex 행으로 묶어 겹침을 없앤다(이번 PDF/BPMN 사례)
  • 제외: components/ui/*(Radix), 텍스트 링크형 버튼, 엔티티 카드 래퍼(WorkflowNode)

검증 루프: 파일 3~5개 묶음 → pnpm check → pnpm exec vitest run <해당 테스트> → 커밋.

4-3. 검증 실행 규칙 (2026-09-18 관찰) ​

  • 테스트는 한 번에 하나만 돌린다. pnpm test가 도는 동안 다른 vitest를 함께 실행하면 파일 단위 병렬 실행끼리 자원을 다투어 기본 5초 타임아웃으로 실패한다(실측: Home.test.tsx의 관리자 등록 흐름이 단독 1.3초 → 동시 실행 5.5~6.3초).
  • 그래서 이런 실패는 코드 결함이 아니다 — 먼저 격리 실행으로 확인하고, 필요하면 그 테스트에만 타임아웃을 명시한다(현재 관리자 등록 흐름 15초).
  • 전체 검증은 pnpm verify:full(= pnpm test + check + build)로 한 번에 돌리고, 원격 검증은 PR에서 한 번만 쓴다(AGENTS.md 규칙).

4-2. 검토 항목 구현 현황 ​

  1. 설계 품질 점검 요약 — 구현 완료(클라이언트 포함)
    • 서버: server/services/designQuality.ts(순수 집계·입력 조립) + flow.designQuality(admin) — 11 테스트.
    • 클라이언트: client/src/components/DesignQualityPanel.tsx — 이슈 카드(PortalMetricGrid) + 문제 L5 목록(클릭 시 해당 L5로 이동) + 다시 점검. 관리자 화면(ProcessManagementPanel, !isPortal) 상단에 배치 — 4 테스트.
    • 이슈별 필터 완료: 공용 PortalMetricGrid의 카드에는 클릭 API가 없어(PortalMetric = id·label·value·hint), 목록의 이슈 배지를 버튼으로 만들어 누르면 그 이슈가 있는 L5만 보고 다시 누르면 풀린다(헤더에 …만 보는 중 표시).
    • 점검 결과 엑셀 내보내기는 4번 항목과 함께 완료.
  2. 영향도 분석 — 구현 완료 → 2026-09-21 하단 L5 연결 요약으로 통합
    • 클라이언트: features/workflow-map/ui/WorkflowImpactPanel.tsx — 캔버스 위 2열 패널로 넣었으나, 하단 WorkflowConnectionSummary가 같은 inboundTransitions/outboundTransitions 로 같은 목록을 이미 보여주고 캔버스의 FROM L5·TO L5 카드와도 겹쳐 중복 3곳이 됐다.
    • 통합 후: 연결 요약의 두 목록이 L5 단위 그룹(workflow-connection-inbound/workflow-connection-outbound)으로 바뀌어 건수(N건)·클릭 이동(onSelectL5)·영향도 안내 문구를 담당하고, 전이 단위 상세(L6 단계·outcome)는 행의 title과 「전체 카드 선후행 현황」 모달로 옮겼다. WorkflowImpactPanel.tsx는 삭제.
    • 서버 변경 없음 — 이미 받아 둔 유입·유출 전이만 쓴다(추가 조회 0).
    • 테스트: WorkflowConnectionSummary.test.tsx 5건(선행·후행 표시, 클릭 이동, 건수·상세, 빈 상태, 모달 열기).
  3. 변경 사유 필수 + 검토자 지정 — 구현 완료
    • 서버: processGovernanceService.requirePublishReason — 게시(불변 확정)는 사유가 없으면 BAD_REQUEST로 막는다(검토 요청·반려는 기존대로 기본 문구 허용). normalizeReviewerIds(중복 제거·최대 20명)로 정리한 지정 검토자를 A 승인자와 함께 알림 발송(dispatchProcessNotificationTo)하고, 이력 요약에 (지정 검토자 N명)을 남긴다.
    • 클라이언트: ProcessGovernanceBar에 변경 사유 입력 + 검토자 지정(PortalMultiSelect) — 검토 중에는 사유를 입력하기 전까지 승인 · 게시가 잠기고, 입력한 사유는 게시·반려·검토 요청 모두에 실린다. 검토자는 작성·게시 중(=isProcessEditableStatus)에만 고를 수 있고, 값은 기존 resolveRaciUserIds 규칙대로 이메일·openId로 환산해 보낸다.
    • 테스트: 서버 5 + 거버넌스 바 6 + 게시 거버넌스 9 통과.
  4. 엑셀 내보내기 — 구현 완료
    • client/src/lib/processExport.ts: 순수 빌더(processListSheet, designQualitySheets, exportDate, exportFileName) + 파일 쓰기(exportSheets, xlsx). 값 만들기와 쓰기를 분리해 테스트한다.
    • 프로세스 관리 화면의 프로세스 노드 관리 헤더에서 현재 보이는 목록(검색 결과 포함)을, 설계 품질 점검 패널에서 요약 + 문제 L5 두 장을 내보낸다. 실패해도 화면은 계속 동작하고 토스트로 알린다.
    • 테스트: client/src/lib/processExport.test.ts 7 + DesignQualityPanel 내보내기 1.
  5. 엑셀 내보내기: 프로세스 목록·설계 품질 점검 결과를 xlsx로 내보내기(이미 의존성 있음).
  6. 검색·입력 품질 — 구현 완료(담당자 검색·공통 검증) / 용어 검색은 범위 밖
    • 담당자 통합 검색: client/src/lib/processSearch.ts — 목록(ProcessManagementPanel)과 트리(AdminProcessTree)가 각자 다른 필드를 보고 있었다(목록: 코드·이름·영문명·설명 / 트리: 코드·이름·영문명). 판정을 한 곳으로 모으고 담당자(R/A/C/I)·조직까지 넓혔다. 검색어는 공백으로 나눠 모든 토큰이 걸려야 일치(AND) — "김책임 변경"이 그대로 동작한다. 트리는 withAncestors로 조상 경로를 유지한다.
      • 주의(회귀 방지): filterProcessNodes/filterProcessTree는 검색어가 없으면 원본 배열 참조를 그대로 돌려준다. 매 렌더 새 배열을 넘기면 트리 펼침 효과가 계속 다시 돌아 화면이 멈춘다 — 테스트로 고정했다(toBe(nodes)).
    • 공통 검증: shared/processValidation.ts — missingProcessFields(코드 → 이름 → 상위 순)가 필수 항목의 단일 출처다. 등록·수정 다이얼로그가 이 함수로 안내 문구(process-form-missing-field)와 등록 버튼 잠금을 함께 처리하고, submit도 같은 규칙으로 막는다. 상한 상수(PROCESS_CODE_MAX_LENGTH 등)를 서버 zod(server/routers/processes.ts)가 그대로 import 해 화면·서버 상한이 갈라지지 않는다. 레벨·상위 규칙은 기존 PROCESS_LEVEL_META를 계속 단일 출처로 쓴다(중복 정의 없음).
      • 구현 중 Home.test.tsx 등록 흐름이 5초 타임아웃으로 실패해 코드 문제로 의심했으나, 원인은 다른 vitest 프로세스와의 동시 실행 부하였다(단독 실행·전체 실행 모두 통과). 지금은 waitFor 계측 없이 그대로 통과한다.
    • 용어(글로서리) 통합 검색 — 연동 완료: 용어 관리 화면(TerminologyManager, 관리자 콘솔)은 이미 있고, 용어를 프로세스에 연결할 수 있다(directory_glossary_term_links). 그 연결을 검색에 붙였다 — process.termLinkedProcesses(정의·번역문은 내려보내지 않고 {term, processId}만) + client/src/lib/processSearch.withTermLinkedNodes(텍스트 결과 ∪ 용어 연결, 순서·참조 유지).
      • 외부(DirectoryService) 호출은 60초 캐시하고 용어 생성·수정·삭제 시 즉시 비운다(invalidateTermLinkCache) — 키 입력마다 부르지 않는다. 검색어가 2자 미만이면 아예 부르지 않는다.
      • 화면에서는 검색 결과 위에 process-term-hint로 연결된 용어를 알리고, 트리도 같은 합집합을 쓴다(AdminProcessTree.termLinkedProcessIds).
      • 관리자 콘솔에서는 용어를 눌러 전문용어 사전으로 이동한다(ProcessManagementPanel.onOpenTerminology → AdminWorkspace가 terminology 패널로 전환). 포털에는 사전 화면이 없어 콜백을 넘기지 않으면 글자로만 보여준다(테스트로 두 경우 모두 고정).
      • (이전 기록 정정: 5순위 조사 때 "용어 화면이 없다"고 적었으나 실제로는 TerminologyManager가 관리자 콘솔에 있고, 빠졌던 것은 검색 연동뿐이었다.)
    • 덤: vitest.config.ts의 include가 client/**/*.test.tsx만 담고 있어 client/**/*.test.ts(순수 로직 테스트)가 전체 실행에서 빠져 있었다 — client/**/*.test.ts·shared/**/*.test.ts를 추가해 이제 CI에서 함께 돈다(이 조치로 processExport.test.ts의 라벨 매핑 버그도 드러나 함께 고쳤다).
    • 테스트: processSearch 9 + processValidation 7.

각 항목은 "화면 → 서버 → 테스트 → 문서" 순서로, 항목 하나가 끝나면 커밋 하나로 묶는다(AGENTS.md 규칙).