Files
PM_test/PM관리자화면개발산출물_20260611/워크플로우_데이터흐름도.html
2026-06-19 17:58:47 +09:00

424 lines
16 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PM 프로젝트 워크플로우 및 데이터 흐름도</title>
<!-- Google Fonts - Inter & Noto Sans KR -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=Noto+Sans+KR:wght@300;400;500;700&display=swap"
rel="stylesheet">
<!-- Mermaid.js 라이브러리 (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
theme: 'default',
securityLevel: 'loose',
themeVariables: {
fontFamily: 'Inter, Noto Sans KR, sans-serif',
primaryColor: '#f43f5e',
primaryTextColor: '#fff',
lineColor: '#cbd5e1'
}
});
</script>
<style>
:root {
--primary: #f43f5e;
--primary-dark: #be123c;
--primary-light: #fff1f2;
--bg: #f8fafc;
--card-bg: #ffffff;
--text-main: #0f172a;
--text-muted: #475569;
--border: #e2e8f0;
--shadow: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.05), 0 4px 6px -4px rgb(0 0 0 / 0.05);
}
body {
font-family: 'Inter', 'Noto Sans KR', sans-serif;
background-color: var(--bg);
color: var(--text-main);
line-height: 1.7;
margin: 0;
padding: 0;
}
.container {
max-width: 1200px;
margin: 40px auto;
padding: 40px;
background-color: var(--card-bg);
border-radius: 16px;
box-shadow: var(--shadow-lg);
border: 1px solid var(--border);
}
/* Header Styling */
header {
border-bottom: 2px solid var(--border);
padding-bottom: 24px;
margin-bottom: 30px;
}
h1 {
font-size: 2.2rem;
font-weight: 700;
margin: 0 0 8px 0;
background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
font-size: 1.1rem;
color: var(--text-muted);
margin: 0;
}
h2 {
font-size: 1.5rem;
color: #1e293b;
border-left: 5px solid var(--primary);
padding-left: 12px;
margin-top: 40px;
margin-bottom: 20px;
font-weight: 700;
}
h3 {
font-size: 1.2rem;
color: #334155;
margin-top: 30px;
margin-bottom: 15px;
font-weight: 600;
}
p,
li {
color: var(--text-muted);
font-size: 1rem;
}
ul {
padding-left: 20px;
}
li {
margin-bottom: 8px;
}
/* Card / Diagram Area Style */
.diagram-card {
background: #ffffff;
border: 1px solid var(--border);
border-radius: 12px;
padding: 24px;
margin: 20px 0 35px 0;
box-shadow: var(--shadow);
overflow-x: auto;
}
.mermaid {
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
}
/* Highlight text */
code {
font-family: monospace;
background-color: #f1f5f9;
color: #e11d48;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9rem;
}
.badge {
display: inline-block;
background-color: var(--primary-light);
color: var(--primary-dark);
padding: 4px 10px;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
margin-bottom: 10px;
}
/* Responsive */
@media (max-width: 768px) {
.container {
margin: 0;
padding: 20px;
border-radius: 0;
box-shadow: none;
border: none;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>PM 프로젝트 워크플로우 및 데이터 흐름도</h1>
<p class="subtitle">로컬 개발 인프라 및 핵심 기능(업로드/압축)에 대한 시각화 명세서</p>
</header>
<p>본 문서는 <code>PM_ver4</code> 프로젝트의 시스템 아키텍처, 기능별 워크플로우 및 엔티티 간 데이터 흐름을 시각적으로 구현하여 이해를 돕기 위한 HTML 문서입니다.</p>
<!-- 1. 전체 아키텍처 -->
<h2>1. 전체 시스템 아키텍처 및 데이터 흐름도</h2>
<p>사용자 브라우저에서 출발하여 웹 서버(Express), PostgreSQL, Redis 및 로컬 MinIO(S3) 스토리지까지 연결되는 데이터 흐름도입니다.</p>
<div class="diagram-card">
<div class="mermaid">
graph LR
%% 1. 사용자 영역 (가장 좌측 배치)
subgraph Client [사용자 브라우저]
UI["HTML CSS JS views"]
SocketClient["Socket.io Client"]
end
%% 2. 백엔드 웹서버 영역 (중앙 배치)
subgraph WebServer [백엔드 서버 Port 6565]
Express["Express App"]
Router["Router / Controller"]
AuthMid["SSO / Login Bypass"]
SocketServer["Socket.io Server"]
BullQueue["BullMQ Producer"]
S3SDK["aws-sdk s3 - MinIO 연동"]
PGDriver["pg - PostgreSQL 연동"]
end
%% 3. 백그라운드 워커 영역 (중앙 하단 배치)
subgraph BackgroundWorker [비동기 워커 프로세스]
Worker["BullMQ Worker - 압축 수행"]
ExternalCLI["programs - pdf_thumb / encryp"]
end
%% 4. 인프라 영역 (가장 우측 배치)
subgraph Infrastructure [Docker 가상 환경]
PostgresDB["PostgreSQL DB"]
RedisDB["Redis Broker"]
MinIOStorage["MinIO S3"]
end
%% 좌측 (Client) -> 중앙 (WebServer) 흐름
UI -->|HTTP Request| Express
Express --> UI
SocketClient ---|Socket Event| SocketServer
%% 웹서버 내부 로직 흐름
Express --> AuthMid
AuthMid --> Router
%% 중앙 (WebServer) -> 우측 (Infrastructure) 데이터 흐름
Router -->|Query| PGDriver
PGDriver --> PostgresDB
Router -->|Push Job| BullQueue
BullQueue --> RedisDB
Router -->|Generate URL| S3SDK
S3SDK --> MinIOStorage
%% 좌측 (Client) -> 우측 (Infrastructure) 다이렉트 업로드 흐름
UI -->|Direct Upload| MinIOStorage
%% 워커 동작 흐름 (중앙 하단 -> 우측 및 외부)
Worker -->|Pop Job| RedisDB
Worker -->|Execute CLI| ExternalCLI
Worker -->|Read Write Files| MinIOStorage
Worker -->|Update Status| PGDriver
</div>
</div>
<!-- 2. 주요 기능별 핵심 워크플로우 -->
<h2>2. 주요 기능별 핵심 워크플로우</h2>
<h3>2.1 파일 업로드 워크플로우 <span class="badge">Presigned URL 방식</span></h3>
<p>서버 리소스를 보존하기 위해 브라우저에서 스토리지(MinIO)로 파일을 직접 올릴 수 있게 구현된 프로세스입니다.</p>
<div class="diagram-card">
<div class="mermaid">
sequenceDiagram
autonumber
actor User as 사용자 (브라우저)
participant Server as 백엔드 서버 (Node.js)
participant MinIO as 로컬 MinIO 스토리지
participant DB as 데이터베이스 (PostgreSQL)
User->>Server: 1. 업로드 링크 요청 (POST /:projectId/archive/generateUploadUrl)
Note over Server: Bucket명 변환 미들웨어 작동<br>(PM_TEST_01 -> pm-test-01)
Server->>MinIO: 2. S3 SDK를 통한 Presigned PUT URL 요청
MinIO-->>Server: 3. 제한 시간 설정된 Presigned URL 반환
Server-->>User: 4. Presigned URL 전달
User->>MinIO: 5. 해당 Presigned URL로 직접 파일 업로드 (HTTP PUT)
Note over User,MinIO: 브라우저에서 스토리지로 다이렉트 전송
MinIO-->>User: 6. 업로드 완료 응답 (HTTP 200 OK)
User->>Server: 7. 업로드 정보 DB 반영 요청
Server->>DB: 8. tb_data / _test_tb_data 테이블에 파일 정보 INSERT
DB-->>Server: 9. 삽입 성공
Server-->>User: 10. 업로드 최종 완료 처리
</div>
</div>
<h3>2.2 폴더 비동기 압축 및 다운로드 워크플로우 <span class="badge">BullMQ + Redis 방식</span></h3>
<p>오래 걸리는 압축 다운로드 작업을 백그라운드에서 비동기로 수행하고, 소켓으로 클라이언트에 완료 알림을 제공하는 워크플로우입니다.</p>
<div class="diagram-card">
<div class="mermaid">
sequenceDiagram
autonumber
actor User as 사용자 (브라우저)
participant Server as 백엔드 서버 (Node.js)
participant Redis as Redis (6379)
participant Worker as 백그라운드 Worker
participant MinIO as 로컬 MinIO 스토리지
participant DB as 데이터베이스 (PostgreSQL)
User->>Server: 1. 폴더 압축 다운로드 요청
Server->>DB: 2. tb_download_folder에 'PENDING' 상태로 이력 기록
Server->>Redis: 3. BullMQ를 통해 압축 Job 발행 (Push)
Server-->>User: 4. 압축 작업 시작 안내 응답 (즉시 반환, 화면 안멈춤)
loop Worker 감시
Worker->>Redis: 5. 대기 중인 Job 가져오기 (Pop)
end
Note over Worker: 6. 폴더 내 모든 파일 탐색 및<br>zip 압축 파일 로컬 생성
Worker->>MinIO: 7. 생성된 zip 파일을 S3 스토리지에 업로드
Worker->>DB: 8. tb_download_folder 상태를 'COMPLETED'로 갱신,<br>zip_key 및 만료일(expire_date) 기록
Note over Server,User: 소켓(Socket.io) 또는 폴링 감시
Server->>User: 9. 압축 완료 알림 전송 (Socket.io)
User->>Server: 10. 내 다운로드 리스트 요청 (GET /getMyDownloadList)
Server->>DB: 11. 완료된 zip 다운로드 정보 조회
DB-->>Server: 12. zip 키값 반환
Server-->>User: 13. MinIO zip 다운로드 다운로드 링크 반환
</div>
</div>
<!-- 3. ERD 맵핑 관계 -->
<h2>3. 주요 데이터 스키마 간 맵핑 관계 (Core ERD)</h2>
<p>시스템 비즈니스 로직의 핵심이 되는 6개 주요 테이블 간의 참조 관계와 주요 필드 중심의 ERD 다이어그램입니다.</p>
<div class="diagram-card">
<div class="mermaid">
erDiagram
tb_user {
varchar user_id PK
varchar user_nm
varchar company
varchar dept
varchar group
}
tb_project {
varchar project_id PK
varchar user_id FK
varchar project_nm
varchar short_nm
boolean overview
boolean official_doc
boolean gsim
}
tb_data {
integer data_id PK
varchar project_id FK
varchar user_id FK
boolean is_folder
bigint data_size
text object_key
bigint popup_size
bigint preview_size
text ai_summary
timestamp create_date
}
tb_download_folder {
integer download_id PK
varchar project_id FK
varchar user_id FK
varchar status
text zip_key
timestamp expire_date
boolean made
}
tb_official_doc_file {
integer doc_id PK
varchar project_id FK
varchar uploader FK
varchar doc_number
varchar doc_date
text doc_title
text doc_title_summary
text doc_content_summary
bigint popup_size
bigint preview_size
}
tb_click_log {
integer click_log_id PK
varchar project_id FK
varchar user_id FK
varchar activity
varchar user_ip
text_array path_arr
int_array data_id_arr
}
%% Relationships
tb_user ||--o{ tb_project : "manages"
tb_project ||--o{ tb_data : "contains"
tb_user ||--o{ tb_data : "creates"
tb_project ||--o{ tb_download_folder : "contains"
tb_user ||--o{ tb_download_folder : "requests"
tb_project ||--o{ tb_official_doc_file : "contains"
tb_user ||--o{ tb_official_doc_file : "uploads"
tb_project ||--o{ tb_click_log : "records"
tb_user ||--o{ tb_click_log : "performs"
</div>
</div>
<!-- 4. 사용자 관리 업무 흐름 -->
<h2>4. 사용자 관리 업무 흐름</h2>
<p>신규 사용자 계정을 생성한 뒤, 프로젝트 현장을 등록하고, 해당 현장에 사용자를 배정하여 시스템 기능을 가동하는 일련의 흐름입니다.</p>
<div class="diagram-card">
<div class="mermaid">
graph TD
A["👤 1. 사용자 등록 (tb_user)<br>사용자 아이디, 패스워드, 이름, 회사/소속부서 등록"] --> B["🏗️ 2. 프로젝트 등록 (tb_project)<br>현장 고유
ID, 공식 명칭, 카테고리 구분, 용량제한 설정"]
B --> C["🔗 3. 프로젝트 사용자 등록 (tb_permission)<br>등록된 사용자를 특정 현장에 권한 등급(lev)과 함께 배정 및 연결"]
C --> D["💻 4. 시스템 사용 (tb_data / tb_official_doc_file)<br>배정받은 권한 레벨(Owner, Sub-Master, Worker, Viewer)에
맞춰 시스템 기능 활용"]
%% Styling
style A fill:#fff1f2,stroke:#f43f5e,stroke-width:2px;
style B fill:#fff1f2,stroke:#f43f5e,stroke-width:2px;
style C fill:#fff1f2,stroke:#f43f5e,stroke-width:2px;
style D fill:#be123c,stroke:#be123c,stroke-width:2px,color:#fff;
</div>
</div>
</div>
</body>
</html>