AI 기반 프로세스 자동 설계 엔진 (Process Portal AI Engine)
상태: 구현 완료(1차) · 근거: [구현 의뢰서] AI 기반 프로세스 자동 설계 지원 모듈 §1~§6 범위: L5(서브프로세스 플로우 맵) · L6(태스크) · L7(액션) — L1~L4 는 주어진 메타데이터다 소유: ProcessCenter — 프로세스 정본은 이 포털이다. AI 는 초안만 만들고 확정은 사람이 한다(게시본 AI 요약과 같은 원칙).
1. 파이프라인
비정형 원천 소스(SOP·인터뷰 녹취·업무 서술) + L1~L4 컨텍스트
│
▼ Stage 1·2 — 구조화 생성 (프롬프트 §3.3 + completeStructured)
{ L6 태스크 + L7 액션, L5 nodes/edges(START·GATEWAY·END) } ← 계약 검증(JSON) 실패 시 재요청
│
▼ Stage 3 — 결정론적 룰 검증 (§4, 순수 함수)
hard 오류 있으면 → 오류를 프롬프트에 되먹여 재생성(자가교정, 기본 2회)
│ └ 실패 시 WARNING + 위반 목록으로 반환(Human-in-the-Loop)
▼
검증 통과 DTO → 화면 확인 → **확정(사람)** → 기존 엔티티로 매핑 저장AI 는 DB 에 쓰지 않는다. 생성 라우터는 DTO 만 돌려주고, 확정 라우터가 매퍼를 통해 저장한다.
2. 계약과 구현 위치
| 조각 | 파일 | 비고 |
|---|---|---|
| DTO 계약(Zod) | shared/processAiEngine.ts | 문서 §2 의 L7Action·L6TaskNode·ArtifactDefinition·ProcessEdge·L5SubProcessMapDTO |
| 결정론적 검증기 | shared/processAiValidator.ts | 문서 §4.2. networkx 대신 인접 리스트 + Kahn 위상 정렬(외부 그래프 의존 없음) |
| 프롬프트·구조화 생성 | server/services/processAiGenerator.ts | 문서 §3.3 시스템 프롬프트·스키마 힌트, completeStructured |
| 자가교정 오케스트레이션 | server/services/processAiOrchestrator.ts | 문서 §5. maxRetries·WARNING 반환 |
| 사내 문서 근거(RAG) | server/services/processAiGrounding.ts | 선택. 실패해도 생성을 막지 않는다 |
| 저장 매퍼 | server/services/processAiMapper.ts | DTO → 노드·워크플로우맵·역할·산출물·액션·이력 |
| 저장소 | server/repositories/processAiRepository.ts | 액션·산출물·생성 이력 |
| 라우터 | server/routers/processAi.ts (processAi.*) | generate·confirm·rules·generations — 관리자 게이트 |
| 화면 | client/src/components/ProcessAiBuilder.tsx | 관리자 콘솔 /admin/ai 전용 화면(좌측 메뉴 「AI 프로세스 설계」) |
3. 결정론적 검증 룰 (문서 §4.1 카탈로그 · §4.2 동작)
| 룰 | 심각도 | 내용 |
|---|---|---|
GOV-L6-FTE-001 | hard | L6 태스크 담당자(responsibleRole)는 단일 직무여야 한다(, / 및 and 금지). 빈 값도 위반 |
GOV-L6-ART-001 | soft | TASK 타입은 산출물을 1개 이상 가져야 한다 — 경고 |
GOV-L7-ACT-001 | soft | L7 액션은 targetSystem 이 명시돼야 한다(UNKNOWN·빈 값은 경고) |
GOV-TOP-001 | hard | START 정확히 1개 · END 1개 이상 |
GOV-TOP-002 | hard | 고립 노드(들어오는 연결 없음)·미완결 노드(나가는 연결 없음) 금지 |
GOV-TOP-003 | hard | 순환 참조 금지(DAG) |
문서 §4.1 은
GOV-L6-ART-001을hard로 적었지만 §4.2 구현은warnings에 넣는다 — 실행 가능한 명세인 §4.2 를 따랐다(코드 주석에도 남겨 두었다).
4. 저장 매핑 (DTO → 기존 엔티티)
| DTO | 저장처 |
|---|---|
| 시작/종료 조건·최종 산출물·추출 계층 | process_nodes.detailContent(L5) |
TASK·APPROVAL·NOTIFICATION | process_nodes L6(parentId=L5) |
estimatedCycleMinutes (FTE 기초) | process_nodes.estimatedCycleMinutes |
responsibleRole(이름) | role_masters(이름 매칭 → 없으면 자동 생성) + process_role_assignments |
artifacts[] | process_node_artifacts |
actions[] (L7) | process_nodes L7 + process_node_actions(순서·시스템·화면·근거) + manualContent(사람용) |
START/END/GATEWAY | workflow_steps(start/end/gateway) |
| 태스크 단계 | workflow_steps(process, processNodeId=L6) |
edges[] | workflow_transitions(분기 출발점은 label→결과 상태, 중복 시 접미사) |
| 생성 DTO 전문·검증 결과 | process_ai_generations(초안 PROPOSED → 확정 CONFIRMED) |
확정 노드 상태 기본값은 DRAFT 다 — 게시 전 사람 검토를 거친다.
5. 신규 스키마 (PG 0028·0029 · MySQL 0037·0038)
process_node_actions— L7 시스템 조작 단위(sequence·actionType·targetSystem·uiElement·sourceEvidence)process_node_artifacts— L6 산출물 정의(name·artifactType·isRequired·templateId)process_nodes.estimatedCycleMinutes— FTE 산정 기초(분)process_ai_generations— 원천 소스·DTO 전문·검증 결과·상태(감사·역추적 정본)0029/0038는 제안 검토 필드를 더한다:submitterRef(제출자 식별자 = Directory subject·openId) ·reviewedBy·reviewedAt·reviewNote(반려 사유) + 제출자/상태 인덱스.status의 enum 값은 그대로 두고 뜻만 쓴다:PROPOSED=검토 대기(제출됨) ·CONFIRMED=확정 ·DISCARDED=반려.
6. 라우터 계약
| 절차 | 권한 | 입력 | 동작 |
|---|---|---|---|
processAi.generate | 로그인 사용자 | l4Id·rawSource(20자+)·useRag?·maxRetries? | L1~L4 컨텍스트 조립 → (선택)RAG 근거 → 생성·검증·자가교정 → 검토 대기(PROPOSED) 기록 → DTO + 검증 결과 + generationId |
processAi.mySubmissions | 로그인 사용자 | — | 내가 제출한 제안(식별자 기준, 최신 30건) |
processAi.rules | 로그인 사용자 | — | 룰 카탈로그(제출자·검토자가 같은 기준을 본다) |
processAi.queue | 관리자 | — | 검토 대기 큐(PROPOSED 최신 100건, DTO 포함) |
processAi.confirm | 관리자 | l4Id·dto·generationId?·status? | 검토 대기 상태 확인 → 확정 경계 재검증(hard 오류면 거부) → 매핑 저장 → 이력 CONFIRMED + 검토자·시각 |
processAi.discard | 관리자 | id·note? | 검토 대기 제안을 반려(DISCARDED)하고 사유 기록 |
processAi.generations | 관리자 | l4Id | L4별 생성 이력(감사) |
제출(generate)은 로그인한 사용자면 누구나 가능하고, 스키마·워크플로우·역할을 만드는 confirm·discard 는 canManageProcesses(관리자)로 잠근다 — 담당자는 제안만, 정본 반영은 검토 뒤에.
6-1. 화면 — 누가 어떻게 쓰는가
두 입구가 같은 화면(ProcessAiBuilder)을 모드만 바꿔 쓴다.
| 담당자(제출) | 관리자(검토) | |
|---|---|---|
| 입구 | 프로세스 화면 상단 「AI 프로세스 제안」 → 대화상자 | 관리자 콘솔 좌측 메뉴 「AI 프로세스 설계」(/admin/ai) |
| 모드 | mode="submit" | mode="admin" |
| 화면이 하는 일 | ① L4 선택 → ② 아는 대로 적기/파일 붙이기 → ③ 초안 확인(태스크·L7 액션·산출물·FTE·원천 인용) → ④ 규칙 위반 안내 → 제출 | ① 검토 대기 큐에서 제안 열기 → 내용 확인 → 확정 또는 반려(사유 필수) / 또는 직접 초안 생성 후 확정 |
| 확정 버튼 | 없음(제출만) | 있음(Confirm & save) |
| 이력 | 내 제안(검토 대기·확정·반려 + 반려 사유) | 검토 대기 큐 |
- 검증 판정은 화면도 서버와 같은 모듈(
shared/processAiValidator)로 다시 계산한다 — 제안을 나중에 열어도 같은 규칙 위반이 그대로 보인다(저장된 결과 문구에만 기대지 않는다). - 조작 유형은 enum 원문(
FILE_UPLOAD)이 아니라 「파일 업로드」처럼 읽는 말로 보여 준다. - 확정 이력·원천 근거·반려 사유는
process_ai_generations가 정본이므로 화면을 닫아도 남는다.
7. 검증(실측)
| 항목 | 결과 |
|---|---|
shared/processAiValidator.test.ts | 16건 — 문서 §6 Step 4 인터뷰 예시 + 6개 룰 |
server/services/processAiOrchestrator.test.ts | 5건 — 검증 통과·재생성 되먹임·WARNING·AI 미설정·프롬프트 주입 |
server/services/processAiMapper.test.ts | 12건 — 매핑·분기 중복 회피·비-L4 거부·hard 오류 거부·경고 허용·제출 기록·검토 기록·반려·이미 처리된 제안 거부 |
client/src/components/ProcessAiBuilder.test.tsx | 13건 — 생성·차단·확정·입력 가드·L7 액션 표시·규칙 펼침·파일 가드·검토 큐·반려(사유 필수)·제출 모드 전용 동작 |
기존 ProcessManagementPanel.test.tsx | 22건 통과(담당자 제안 입구는 대화상자라 목록 화면 계약을 바꾸지 않는다) |
| dev DB(PG) | pnpm db:migrate 적용 → 테이블 3개 + 컬럼 5개, drizzle.__drizzle_migrations id 50·51 기록, pnpm db:check-drift → 없는 컬럼 0개 |
8. 문서와 다르게 해석한 지점(명시)
- 언어 — 문서는 Python(Pydantic·networkx) 또는 TS(Zod)를 허용했고, 이 저장소는 TS/Zod 이므로 Zod + 순수 함수로 구현했다.
- 2-Stage — 문서 §3.3·§5 는 실제로 단일 프롬프트 + 사후검증 구조다. 1차는 그대로 단일 구조화 생성으로 구현했다(품질 이슈 시 Stage 1 추출 / Stage 2 합성 분리 호출로 쪼갤 수 있다).
- GATEWAY →
gateway— 문서의 GATEWAY 는 워크플로우맵의 의사결정 분기(사람이 판단)로 매핑했다. 자동 조건 분기(condition)는 AI 가 임의로 만들지 않는다(엔진이 실행 조건식을 확정할 근거가 없다). - 결재선 규칙 — 문서 Stage 3 의 "전결 규정 및 승인 노드 시퀀스 준수"는 §4 의 선언된 룰 카탈로그에 없다. 이번 1차에서는 구현하지 않았다(승인 정책 데이터와의 결합이 필요하다).
artifactType— DTO 필드명은type이지만 컬럼명은 SQL 예약어 오해를 피해artifactType으로 두었다.- sourceEvidence — 별도 컬럼을 두지 않고
process_ai_generations.dto(생성 DTO 전문)에 보존한다(L6/L7 역추적의 정본).
9. 하지 않은 것 / 남은 과제
confirm은 항상 새 L5 를 만든다(기존 L5 갱신·병합 없음). 같은 원천 소스를 다시 확정하면 중복 초안이 생긴다 — 갱신(업서트) 경로는 별도 결정이 필요하다.- 담당자 제출은 제안까지다 — 확정된 뒤의 게시·승인(IN_REVIEW → ACTIVE)은 기존 프로세스 거버넌스를 그대로 쓴다(AI 는 DRAFT 로만 만든다).
- 반려한 제안은 다시 열 수 없다(
DISCARDED) — 담당자가 다시 생성해 올린다. 반려 사유와 이력은 남는다. - 제출에 별도 쿼터를 두지 않았다 — AI 호출 비용은 ModelGateway 의 목적(
process.node-generation) 단위 쿼터로 통제한다. - 검증 실패 초안을 화면에서 직접 편집하는 UI 는 없다(현재는 다시 생성하거나 담당자가 노드를 손본다).
- 결재선(전결규정) 연동,
condition(자동 조건 분기) 생성,triggerEvent의 외부 유입 연결은 후속이다. - 캔버스 미리보기는 태스크 카드 목록 + 단계 요약이다 — 합성 맵을
workflow-map캔버스로 그리는 "제안 모드" 렌더는 별도 작업이다.