794 lines
34 KiB
HTML
794 lines
34 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>통합 관리자 대시보드 구현 계획 및 테이블 명세 가이드</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;500;600;700&family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||
|
||
<!-- Mermaid JS for Dynamic Diagrams -->
|
||
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
||
<script>
|
||
mermaid.initialize({
|
||
startOnLoad: true,
|
||
theme: 'forest',
|
||
themeVariables: {
|
||
primaryColor: '#1e5149',
|
||
primaryTextColor: '#fff',
|
||
lineColor: '#1e5149',
|
||
secondaryColor: '#142e29'
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
:root {
|
||
--primary: #1e5149;
|
||
--primary-dark: #142e29;
|
||
--primary-light: #e9eeed;
|
||
--primary-border: #d2dcdb;
|
||
--accent: #4db251;
|
||
--bg: #f4f7f6;
|
||
--card-bg: #ffffff;
|
||
--text-main: #1f2937;
|
||
--text-muted: #4b5563;
|
||
--code-bg: #1e293b;
|
||
--code-text: #f8fafc;
|
||
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
|
||
--sidebar-width: 280px;
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
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;
|
||
display: flex;
|
||
}
|
||
|
||
/* Sidebar Navigation */
|
||
aside {
|
||
width: var(--sidebar-width);
|
||
background: linear-gradient(180deg, var(--primary-dark) 0%, #0c1a18 100%);
|
||
color: #ffffff;
|
||
height: 100vh;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
overflow-y: auto;
|
||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||
padding: 24px;
|
||
z-index: 100;
|
||
}
|
||
|
||
aside h2 {
|
||
font-size: 1.15rem;
|
||
font-weight: 700;
|
||
margin-bottom: 24px;
|
||
color: var(--accent);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
|
||
padding-bottom: 12px;
|
||
}
|
||
|
||
aside ul {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
aside li {
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
aside a {
|
||
color: #b3c5c2;
|
||
text-decoration: none;
|
||
font-size: 0.9rem;
|
||
display: block;
|
||
padding: 8px 12px;
|
||
border-radius: 6px;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
aside a:hover, aside li.active a {
|
||
color: #ffffff;
|
||
background-color: rgba(255, 255, 255, 0.08);
|
||
padding-left: 16px;
|
||
}
|
||
|
||
aside .category-title {
|
||
font-size: 0.75rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: #628781;
|
||
margin: 16px 0 8px 12px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
/* Main Content */
|
||
main {
|
||
margin-left: var(--sidebar-width);
|
||
flex-grow: 1;
|
||
padding: 40px 50px;
|
||
max-width: 1000px;
|
||
}
|
||
|
||
header {
|
||
border-bottom: 2px solid var(--primary-border);
|
||
padding-bottom: 24px;
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
header h1 {
|
||
font-size: 2.2rem;
|
||
font-weight: 700;
|
||
margin: 0 0 10px 0;
|
||
color: var(--primary);
|
||
}
|
||
|
||
header .subtitle {
|
||
font-size: 1.1rem;
|
||
color: var(--text-muted);
|
||
margin: 0;
|
||
}
|
||
|
||
/* Content Sections */
|
||
section {
|
||
background-color: var(--card-bg);
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
margin-bottom: 30px;
|
||
box-shadow: var(--shadow);
|
||
border: 1px solid var(--primary-border);
|
||
}
|
||
|
||
h2.section-title {
|
||
font-size: 1.4rem;
|
||
font-weight: 700;
|
||
color: var(--primary);
|
||
margin-top: 0;
|
||
margin-bottom: 20px;
|
||
border-left: 4px solid var(--accent);
|
||
padding-left: 12px;
|
||
}
|
||
|
||
h3 {
|
||
font-size: 1.15rem;
|
||
font-weight: 600;
|
||
color: var(--primary-dark);
|
||
margin-top: 24px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
p {
|
||
margin: 0 0 16px 0;
|
||
color: var(--text-main);
|
||
}
|
||
|
||
/* Callouts (GitHub alerts) */
|
||
.callout {
|
||
border-left: 4px solid;
|
||
padding: 16px;
|
||
margin-bottom: 20px;
|
||
border-radius: 0 8px 8px 0;
|
||
}
|
||
|
||
.callout-note {
|
||
background-color: #f0f7ff;
|
||
border-color: #0066cc;
|
||
color: #004080;
|
||
}
|
||
|
||
.callout-important {
|
||
background-color: #fff8f8;
|
||
border-color: #ef4444;
|
||
color: #991b1b;
|
||
}
|
||
|
||
.callout-title {
|
||
font-weight: 700;
|
||
margin-bottom: 6px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
/* Tables */
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 20px 0;
|
||
font-size: 0.9rem;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
border: 1px solid var(--primary-border);
|
||
}
|
||
|
||
th {
|
||
background-color: var(--primary);
|
||
color: #ffffff;
|
||
font-weight: 600;
|
||
text-align: left;
|
||
padding: 12px 16px;
|
||
}
|
||
|
||
td {
|
||
padding: 12px 16px;
|
||
border-bottom: 1px solid var(--primary-border);
|
||
color: var(--text-main);
|
||
vertical-align: top;
|
||
}
|
||
|
||
tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
tr:nth-child(even) td {
|
||
background-color: #f9fafb;
|
||
}
|
||
|
||
/* Code Blocks */
|
||
pre {
|
||
background-color: var(--code-bg);
|
||
color: var(--code-text);
|
||
padding: 18px;
|
||
border-radius: 8px;
|
||
font-family: 'Consolas', 'Courier New', Courier, monospace;
|
||
font-size: 0.85rem;
|
||
overflow-x: auto;
|
||
margin: 16px 0;
|
||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
code {
|
||
font-family: 'Consolas', 'Courier New', Courier, monospace;
|
||
background-color: #f1f5f9;
|
||
color: #0f172a;
|
||
padding: 2px 6px;
|
||
border-radius: 4px;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
pre code {
|
||
background-color: transparent;
|
||
color: inherit;
|
||
padding: 0;
|
||
border-radius: 0;
|
||
font-size: inherit;
|
||
}
|
||
|
||
.method-badge {
|
||
display: inline-block;
|
||
padding: 3px 8px;
|
||
border-radius: 4px;
|
||
font-size: 0.75rem;
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
margin-right: 6px;
|
||
}
|
||
|
||
.method-get { background-color: #0ea5e9; }
|
||
.method-post { background-color: #22c55e; }
|
||
.method-put { background-color: #f59e0b; }
|
||
.method-delete { background-color: #ef4444; }
|
||
|
||
.api-url {
|
||
font-weight: 600;
|
||
font-family: monospace;
|
||
}
|
||
|
||
/* List Styling */
|
||
ul {
|
||
padding-left: 20px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
li {
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
/* Diagram Container */
|
||
.diagram-container {
|
||
display: flex;
|
||
justify-content: center;
|
||
margin: 24px 0;
|
||
background-color: #ffffff;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
border: 1px solid var(--primary-border);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Sidebar Navigation -->
|
||
<aside>
|
||
<h2>📁 PM_ver4 Admin Guide</h2>
|
||
<ul>
|
||
<li><a href="#overview">가이드 소개</a></li>
|
||
</ul>
|
||
|
||
<div class="category-title">01. 시스템 아키텍처</div>
|
||
<ul>
|
||
<li><a href="#architecture">전체 구조 & 로직</a></li>
|
||
<li><a href="#migration">단계별 구현 계획</a></li>
|
||
</ul>
|
||
|
||
<div class="category-title">02. 데이터 모델 (ERD)</div>
|
||
<ul>
|
||
<li><a href="#schema-design">스키마 구조 & 관계</a></li>
|
||
</ul>
|
||
|
||
<div class="category-title">03. 화면별 데이터 매핑</div>
|
||
<ul>
|
||
<li><a href="#screen-dashboard">1. 종합 용량 및 접속자</a></li>
|
||
<li><a href="#screen-project">2. 프로젝트 관리</a></li>
|
||
<li><a href="#screen-banner">3. 실시간 배너 공지</a></li>
|
||
<li><a href="#screen-user">4. 사용자 관리</a></li>
|
||
<li><a href="#screen-audit">5. 감사 로그 조회</a></li>
|
||
<li><a href="#screen-policy">6. 자동 삭제 정책 설정</a></li>
|
||
<li><a href="#screen-codes">7. 공통 코드 관리</a></li>
|
||
</ul>
|
||
|
||
<div class="category-title">04. 백엔드 API 설계</div>
|
||
<ul>
|
||
<li><a href="#api-endpoints">핵심 CRUD API 목록</a></li>
|
||
</ul>
|
||
</aside>
|
||
|
||
<!-- Main Content -->
|
||
<main>
|
||
<header id="overview">
|
||
<h1>통합 관리자 대시보드 구현 계획 및 테이블 명세 가이드</h1>
|
||
<p class="subtitle">관리자 화면(Admin Panel) 마이그레이션 및 데이터베이스 연동 설계서</p>
|
||
</header>
|
||
|
||
<!-- Section 1 -->
|
||
<section id="architecture">
|
||
<h2 class="section-title">1. 전체 시스템 아키텍처 및 구현 계획</h2>
|
||
<p>본 설계서는 <code>관리자화면_통합대시보드_UI제안.html</code> 정적 파일의 사용자 동작 시뮬레이션을 프로덕션 급 서버 인프라에 안착하기 위한 설계 명세입니다. 시스템 환경은 Node.js / PostgreSQL / MinIO S3 및 Redis Queue 아키텍처를 준수합니다.</p>
|
||
|
||
<div class="diagram-container">
|
||
<div class="mermaid">
|
||
graph TD
|
||
Client[Browser Admin Page] -->|REST API Requests| Backend[Express.js Web Server]
|
||
Client -->|WebSocket Event Channel| SocketServer[Socket.io Server]
|
||
Backend -->|SQL Query / PG client| DB[(PostgreSQL Database)]
|
||
Backend -->|Enqueue / Monitor| Redis[(Redis / BullMQ Queue)]
|
||
SocketServer -->|Active Session Cache| Memory[Node.js Process Memory]
|
||
</div>
|
||
</div>
|
||
|
||
<div class="callout callout-note">
|
||
<div class="callout-title">ℹ️ 백엔드 연동 방식</div>
|
||
<div class="callout-content">
|
||
본 시스템은 관리 업무의 연속성 확보 및 동시성 처리를 위해 REST API 채널 외에도 Socket.io 서버 채널을 동시에 가용하여 실시간 웹소켓 통신을 처리하도록 구성됩니다.
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Section 2 -->
|
||
<section id="migration">
|
||
<h2 class="section-title">구현 단계별 개발 로드맵</h2>
|
||
|
||
<h3>[1단계] 데이터베이스 스키마 확장 및 마이그레이션</h3>
|
||
<ul>
|
||
<li>공통 코드 분류 및 세부 값 제어를 위한 <code>code_master</code> 및 <code>code_detail</code> 테이블 신설.</li>
|
||
<li><strong>기존 테이블 활용 (컬럼 추가 없음)</strong>: 기존에 존재하는 프로젝트 테이블(<code>tb_project</code>)의 <code>category</code> 컬럼과 사용자 테이블(<code>tb_user</code>)의 <code>"group"</code> 컬럼을 <code>code_detail.base_code</code> 외래키 참조 구조로 그대로 연동하여 불필요한 테이블 팽창 및 컬럼 추가를 차단합니다.</li>
|
||
<li>시스템 공통 자동 보존 및 삭제 임계치를 독립적으로 제어하기 위한 <strong><code>tb_system_policy</code> (시스템 공통 정책 테이블)</strong> 신설.</li>
|
||
<li>실시간 배너 공지 이력 보관을 위한 <code>tb_banner_notice</code> 및 정기 자동삭제 실행 결과를 기록하기 위한 <code>tb_auto_clean_log</code> 신설.</li>
|
||
</ul>
|
||
|
||
<h3>[2단계] 백엔드 RESTful API 및 WebSocket 핸들러 개발</h3>
|
||
<ul>
|
||
<li><strong>REST API</strong>: 각 기능 및 공통 코드 데이터의 CRUD API Endpoint 구축 (Express Controller 연동).</li>
|
||
<li><strong>WebSocket</strong>: <code>socket.js</code>에 접속한 클라이언트 세션을 <code>users</code> 메모리 맵에 보관 및 관리자가 강제퇴장(<code>forcedLogout</code>) 이벤트를 호출하면 해당 클라이언트 소켓의 접속을 끊고 세션을 제거하도록 구현.</li>
|
||
</ul>
|
||
|
||
<h3>[3단계] 프론트엔드 어드민 대시보드 UI 연동</h3>
|
||
<ul>
|
||
<li>프로토타입 디자인 컨셉(Pretendard 서체, Forest Green 테마 색상)을 CSS 변수로 그대로 반영.</li>
|
||
<li>모달 다이얼로그와 탭 렌더링에 실시간 API 데이터 통신 로직 바인딩.</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- Section 3 -->
|
||
<section id="schema-design">
|
||
<h2 class="section-title">2. 데이터베이스 스키마 설계 (ERD)</h2>
|
||
<p>기존에 이미 보유한 <code>tb_project.category</code> 및 <code>tb_user."group"</code> 구조를 활용한 관계 정의는 다음과 같습니다.</p>
|
||
|
||
<div class="diagram-container">
|
||
<div class="mermaid">
|
||
classDiagram
|
||
class code_master {
|
||
+main_code : VARCHAR(30) PK
|
||
+main_code_nm : VARCHAR(100)
|
||
+use_yn : CHAR(1)
|
||
+rmk : VARCHAR(255)
|
||
}
|
||
class code_detail {
|
||
+main_code : VARCHAR(30) PK/FK
|
||
+sub_code : VARCHAR(30) PK
|
||
+base_code : VARCHAR(61) UNIQUE
|
||
+code_nm : VARCHAR(100)
|
||
+sort_ord : INT
|
||
+use_yn : CHAR(1)
|
||
+rmk : VARCHAR(255)
|
||
}
|
||
class tb_project {
|
||
+project_id : VARCHAR(50) PK
|
||
+project_nm : VARCHAR(100)
|
||
+category : VARCHAR(50) FK
|
||
+limit_storage : INT
|
||
+is_active : BOOLEAN
|
||
}
|
||
class tb_system_policy {
|
||
+policy_id : INT PK
|
||
+policy_key : VARCHAR(50) UNIQUE
|
||
+limit_file_count : INT
|
||
+limit_days : INT
|
||
+is_active : BOOLEAN
|
||
+upd_date : TIMESTAMP
|
||
}
|
||
class tb_user {
|
||
+user_id : VARCHAR(50) PK
|
||
+user_nm : VARCHAR(50)
|
||
+user_pw : VARCHAR(255)
|
||
+company : VARCHAR(50)
|
||
+dept : VARCHAR(50)
|
||
+position : VARCHAR(50)
|
||
+group : VARCHAR(50) FK
|
||
+is_resigned : BOOLEAN
|
||
}
|
||
class tb_permission {
|
||
+project_id : VARCHAR(50) PK/FK
|
||
+user_id : VARCHAR(50) PK/FK
|
||
+lev : INT
|
||
}
|
||
class tb_banner_notice {
|
||
+banner_id : SERIAL PK
|
||
+project_id : VARCHAR(50) FK
|
||
+reg_date : DATE
|
||
+start_date : DATE
|
||
+end_date : DATE
|
||
+notice_text : TEXT
|
||
+status_code : VARCHAR(61) FK
|
||
}
|
||
class tb_log {
|
||
+log_id : SERIAL PK
|
||
+project_id : VARCHAR(50)
|
||
+activity : VARCHAR(100)
|
||
+user_id : VARCHAR(50)
|
||
+user_ip : VARCHAR(50)
|
||
+log_date : TIMESTAMP
|
||
+path_arr : TEXT[]
|
||
}
|
||
code_master "1" --> "0..*" code_detail
|
||
code_detail "1" --> "0..*" tb_project : "category 참조"
|
||
code_detail "1" --> "0..*" tb_user : "group 참조"
|
||
code_detail "1" --> "0..*" tb_banner_notice : "status_code 참조"
|
||
tb_project "1" --> "0..*" tb_permission
|
||
tb_user "1" --> "0..*" tb_permission
|
||
tb_project "1" --> "0..*" tb_banner_notice
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Section 4 -->
|
||
<section id="screen-dashboard">
|
||
<h2 class="section-title">3. 화면별 연동 테이블 및 데이터베이스 상세 매핑</h2>
|
||
|
||
<h3>📊 화면 1: 종합 용량 및 접속자 현황 (Dashboard)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>전체 사용 용량 KPI & 현장별 게이지바</strong>:
|
||
<code>tb_project</code> 테이블의 한도 용량(<code>storage_byte</code>)과 <code>tb_data</code> 테이블의 실 누적 용량(<code>data_size</code>) 합산 결과 및 파일 건수를 <code>COUNT()</code>하여 렌더링.
|
||
</li>
|
||
<li><strong>실시간 접속자 세션 목록</strong>:
|
||
데이터베이스를 경유하지 않고 Node.js 메인 프로세스(<code>socket.js</code>)의 메모리 세션 해시맵에서 직접 연결 상태(ID, IP, 위치 경로)를 추출.
|
||
</li>
|
||
<li><strong>대기 중인 압축작업</strong>:
|
||
Redis(BullMQ Queue) 대기열 API를 조회하여 보류 중인 백그라운드 압축 다운로드 개수 파악.
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-project">
|
||
<h3>🏗️ 화면 2: 프로젝트 관리 (Project Management)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>좌측 프로젝트 그리드</strong>: <code>tb_project</code> 테이블 전체 데이터와 <code>code_detail</code>의 카테고리 코드 한글 명칭(TDC, GPD 등)을 <code>tb_project.category</code> 외래키 관계를 조인하여 렌더링.</li>
|
||
<li><strong>우측 참여 권한 사용자 목록</strong>: <code>tb_permission</code> $\bowtie$ <code>tb_user</code> 조인을 통해 해당 현장에 기속된 사용자 리스트업 및 등급 인라인 셀렉트 업데이트.</li>
|
||
<li><strong>사용자 배정 추가 모달</strong>: <code>tb_user</code>의 전체 사용자 데이터와 현재 프로젝트에 속해 있지 않은 유저 차집합 연산으로 가용 유저 목록 구성.</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-banner">
|
||
<h3>📢 화면 3: 실시간 배너 공지 (Banner Notice)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>공지사항 이력 및 등록 폼</strong>: <code>tb_banner_notice</code> 테이블 CRUD 매핑.</li>
|
||
<li><strong>송출 상태 계산</strong>:
|
||
오늘 날짜 기준 <code>start_date</code>와 <code>end_date</code> 조건을 체크하여 공통코드 매핑 상태(<code>NOTICE_STATUS_active</code>, <code>NOTICE_STATUS_scheduled</code>, <code>NOTICE_STATUS_expired</code>)를 동적 할당.
|
||
</li>
|
||
<li><strong>검색 필터</strong>: 송출상태 및 등록일 범위(From ~ To) 기준 <code>WHERE status_code = ? AND reg_date BETWEEN ? AND ?</code> 쿼리 연동.</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-user">
|
||
<h3>👥 화면 4: 사용자 관리 (User Management)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>좌측 계정 목록</strong>: <code>tb_user</code> 테이블 및 <code>code_detail</code> 권한그룹(기존 <code>"group"</code> 컬럼 재사용) 매핑 렌더링.</li>
|
||
<li><strong>우측 참여 프로젝트 목록</strong>: <code>tb_permission</code> $\bowtie$ <code>tb_project</code> 조인을 활용하여 선택 유저가 소속된 모든 프로젝트 ID 및 현장명 출력.</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-audit">
|
||
<h3>🔎 화면 5: 감사 로그 조회 (Audit Logs)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>시스템 감사 이력 목록</strong>:
|
||
파일 삭제/이동/다운로드 이벤트를 적재하는 <code>tb_log</code> 테이블을 필터 검색 쿼리(사용자 ID, 액션타입)와 연동하여 리스트 렌더링.
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-policy">
|
||
<h3>⚙️ 화면 6: 자동 보존 및 파일 삭제 정책 설정 (Delete Policy)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>시스템 공통 자동 삭제 정책 설정 폼</strong>:
|
||
프로젝트 단위 설정을 탈피하고, 신설된 <code>tb_system_policy</code>의 단일 글로벌 레코드를 제어.
|
||
</li>
|
||
<li><strong>자동 삭제 정기 실행 이력</strong>:
|
||
정기 스케줄러 배치 구동 시의 로그 기록을 <code>tb_auto_clean_log</code>에서 리스트업. 설정값 저장 및 기록 적재 시 프로젝트 ID 대신 <code>'SYSTEM'</code> 기록 식별자를 사용.
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section id="screen-codes">
|
||
<h3>🔑 화면 7: 공통 코드 관리 (Common Code Management)</h3>
|
||
<p><strong>주요 데이터 흐름 및 활용 테이블:</strong></p>
|
||
<ul>
|
||
<li><strong>상단 마스터 대분류</strong>: <code>code_master</code> 테이블 CRUD.</li>
|
||
<li><strong>하단 상세 소분류</strong>: <code>code_detail</code> 테이블 CRUD.
|
||
<ul>
|
||
<li>대분류 선택이 없을 시 소분류 등록 폼 진입 차단 유효성 제어.</li>
|
||
<li>소분류의 <code>base_code</code> 컬럼은 <code>main_code || '_' || sub_code</code> 조합으로 자동 동기화.</li>
|
||
<li>대분류 삭제 시 외래키 <code>ON DELETE CASCADE</code> 명세를 통하여 소분류 레코드가 데이터베이스에서 연쇄적으로 자동 청소되도록 설정.</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- Section 5 -->
|
||
<section id="api-endpoints">
|
||
<h2 class="section-title">4. 핵심 백엔드 CRUD API Endpoint 설계안</h2>
|
||
<p>프론트엔드-백엔드 간 통신을 위해 구성되어야 할 RESTful API 리스트입니다.</p>
|
||
|
||
<h3>1. 프로젝트 관리 API (<code>/api/admin/projects</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>전체 프로젝트 및 카테고리 정보 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>신규 프로젝트 등록</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/:id</td>
|
||
<td>특정 프로젝트 내용(카테고리 category 값, 용량제한, 활성화) 갱신</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-delete">DELETE</span></td>
|
||
<td class="api-url">/:id</td>
|
||
<td>프로젝트 영구 삭제 (참여 권한 및 메타데이터 자동 CASCADE)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>2. 프로젝트 권한 배정 API (<code>/api/admin/permissions</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/project/:projectId</td>
|
||
<td>특정 현장에 참여 중인 유저 목록 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/assign</td>
|
||
<td>현장에 특정 사용자 권한 신규 부여 (다중 배정)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/update</td>
|
||
<td>배정 유저의 권한 등급(lev) 수정</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-delete">DELETE</span></td>
|
||
<td class="api-url">/remove</td>
|
||
<td>현장 참여 권한 배정 제외 (매핑 행 삭제)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>3. 실시간 배너 공지 API (<code>/api/admin/banners</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>배너 송출 이력 조회 (상태, 날짜검색 필터 지원)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>신규 배너 공지 작성 및 등록</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/stop/:id</td>
|
||
<td>공지 수동 송출 중지 (상태를 expired로 강제 업데이트)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>4. 사용자 관리 API (<code>/api/admin/users</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>전체 계정 정보 및 권한그룹 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/:id/permissions</td>
|
||
<td>해당 유저가 참여 권한을 지닌 프로젝트 목록 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>신규 사용자 계정 등록 (패스워드 bcrypt 암호화)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/:id</td>
|
||
<td>사용자 정보(권한 그룹 group 포함) 및 재직 상태 갱신</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-delete">DELETE</span></td>
|
||
<td class="api-url">/:id</td>
|
||
<td>사용자 계정 삭제 (권한 정보 및 설정 연쇄 삭제)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>5. 공통 코드 관리 API (<code>/api/admin/common-codes</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/masters</td>
|
||
<td>대분류 마스터 코드 목록 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/masters</td>
|
||
<td>신규 대분류 등록</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/masters/:code</td>
|
||
<td>대분류 수정</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-delete">DELETE</span></td>
|
||
<td class="api-url">/masters/:code</td>
|
||
<td>대분류 삭제 (하위 소분류 자동 연쇄 삭제)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/details/:mainCode</td>
|
||
<td>선택된 대분류에 해당하는 소분류 정렬 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/details</td>
|
||
<td>신규 소분류 등록 (base_code 자동 연산 생성)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-put">PUT</span></td>
|
||
<td class="api-url">/details/:mainCode/:subCode</td>
|
||
<td>소분류 수정 (명칭, 정렬순서, 사용여부)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-delete">DELETE</span></td>
|
||
<td class="api-url">/details/:mainCode/:subCode</td>
|
||
<td>소분류 삭제</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>6. 시스템 공통 보존 정책 API (<code>/api/admin/system-policy</code>)</h3>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 15%;">메소드</th>
|
||
<th style="width: 35%;">엔드포인트</th>
|
||
<th style="width: 50%;">설명</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="method-badge method-get">GET</span></td>
|
||
<td class="api-url">/</td>
|
||
<td>시스템 글로벌 보존 정책 조회</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="method-badge method-post">POST</span></td>
|
||
<td class="api-url">/update</td>
|
||
<td>글로벌 보존 정책 값 갱신 및 저장</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
</main>
|
||
|
||
</body>
|
||
</html>
|