[Specification] 작업 타임테이블 + Excel 다운로드
SM 운영, 정기점검, PM, SR 기반 작업 등 모든 수행 이력을 타임테이블로 관리하고
Excel 파일로 다운로드하는 기능 명세.
1. 타임테이블 개요
1.1. 목적
| 목적 |
설명 |
| 작업 이력 관리 |
정기점검·PM·SR·장애대응 모든 작업을 단일 화면에서 통합 관리 |
| 감사 자료 제출 |
기관·감사원 요청 시 Excel로 즉시 제출 가능한 형태 유지 |
| PM 보고 자료 |
월간/분기 활동 보고서 자동 생성 기반 데이터 |
| 작업 표준화 |
수행 명령어·쉘 스크립트를 기록해 재사용 가능하도록 관리 |
1.2. 작업 유형
| work_type |
한글명 |
설명 |
REGULAR_CHECK |
정기점검 |
월간·분기·반기·연간 계획된 점검 |
PM |
예방 정비 |
하드웨어 교체, 패치 적용, 취약점 조치 |
SR |
SR 기반 작업 |
ITSM SR과 연계된 작업 |
ADHOC |
수시점검 |
비정기 확인, 고객 요청 확인 |
DEPLOY |
배포 작업 |
소스 배포, 설정 변경 |
EMERGENCY |
긴급 대응 |
장애 복구, 긴급 조치 |
2. 데이터 모델
2.1. 주요 컬럼 상세
| 컬럼 |
타입 |
필수 |
설명 |
timetable_id |
BIGINT |
PK |
|
work_type |
VARCHAR(30) |
✅ |
작업 유형 |
title |
VARCHAR(200) |
✅ |
작업 제목 (예: 2025 Q1 정기점검 - 기획재정부) |
inst_id |
VARCHAR(20) |
|
대상 기관 |
server_id |
VARCHAR(30) |
|
대상 서버 (복수면 JSON) |
sr_id |
VARCHAR(30) |
|
연계 SR ID |
script_id |
BIGINT |
|
사용 쉘 스크립트 ID |
scheduled_at |
TIMESTAMP |
✅ |
처리 예정 일시 |
started_at |
TIMESTAMP |
|
실제 시작 일시 |
completed_at |
TIMESTAMP |
|
완료 일시 |
content |
TEXT |
✅ |
처리 내용 (무엇을, 어떻게, 왜) |
command_or_shell |
TEXT |
|
실행한 명령어 또는 쉘 이름 |
result |
TEXT |
|
처리 결과 (성공/실패 내용) |
result_status |
VARCHAR(20) |
|
PENDING / SUCCESS / FAILED / PARTIAL |
assignee |
VARCHAR(50) |
✅ |
담당 엔지니어 사번 |
reviewer |
VARCHAR(50) |
|
PM/검토자 사번 |
attachments |
JSONB |
|
첨부파일 목록 |
3. API 엔드포인트
| 메서드 |
URL |
권한 |
설명 |
GET |
/api/timetable |
ADMIN, PM, ENGINEER |
타임테이블 목록 (필터링 지원) |
GET |
/api/timetable/{id} |
ADMIN, PM, ENGINEER |
상세 조회 |
POST |
/api/timetable |
ENGINEER, PM, ADMIN |
새 작업 등록 |
PATCH |
/api/timetable/{id} |
ENGINEER, PM, ADMIN |
수정 |
DELETE |
/api/timetable/{id} |
ADMIN |
삭제 |
GET |
/api/timetable/export/excel |
ADMIN, PM |
Excel 다운로드 |
GET |
/api/timetable/stats |
ADMIN, PM |
기간별 통계 |
3.1. 목록 조회 쿼리 파라미터
GET /api/timetable
?inst_code=MOF # 기관 필터
&work_type=REGULAR_CHECK # 작업 유형 필터
&result_status=SUCCESS # 결과 상태 필터
&assignee=EMP-0101 # 담당자 필터
&date_from=2025-01-01 # 시작일
&date_to=2025-03-31 # 종료일
&keyword=점검 # 제목/내용 검색
&skip=0&limit=50
3.2. Excel 다운로드 쿼리 파라미터
GET /api/timetable/export/excel
?inst_code=MOF
&date_from=2025-01-01
&date_to=2025-03-31
&work_type=REGULAR_CHECK
응답: Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
파일명: GUARDiA_작업이력_MOF_20250101_20250331.xlsx
4. Excel 파일 구조
openpyxl 라이브러리 사용 (on-premise, 외부 API 호출 없음)
4.1. 시트 구성
| 시트 |
내용 |
작업이력 |
전체 타임테이블 데이터 |
통계요약 |
작업 유형별·결과별 집계 |
서버현황 |
대상 서버 목록 (민감정보 제외) |
4.2. 작업이력 시트 컬럼
| # |
컬럼명 |
데이터 |
| A |
번호 |
순번 |
| B |
작업유형 |
정기점검 / PM / SR작업 / 수시점검 |
| C |
제목 |
work timetable title |
| D |
기관명 |
inst_name |
| E |
대상서버 |
server_id (hostname) |
| F |
처리예정일시 |
scheduled_at |
| G |
시작일시 |
started_at |
| H |
완료일시 |
completed_at |
| I |
소요시간(분) |
completed_at - started_at |
| J |
처리내용 |
content |
| K |
명령어/쉘 |
command_or_shell |
| L |
처리결과 |
result |
| M |
결과상태 |
SUCCESS / FAILED / PARTIAL |
| N |
담당자 |
assignee 이름 |
| O |
검토자 |
reviewer 이름 |
| P |
SR번호 |
sr_id |
| Q |
비고 |
note |
4.3. 스타일 규칙
# 헤더 스타일
header_fill = PatternFill("solid", fgColor="1E3A5F") # 네이비
header_font = Font(name="맑은 고딕", bold=True, color="FFFFFF", size=11)
header_align = Alignment(horizontal="center", vertical="center")
# 데이터 행 교대 색상
row_fill_even = PatternFill("solid", fgColor="F2F6FA")
row_fill_odd = None # 흰색
# 결과 상태 강조 색상
status_colors = {
"SUCCESS": "C6EFCE", # 연초록
"FAILED": "FFC7CE", # 연빨강
"PARTIAL": "FFEB9C", # 연노랑
"PENDING": "F4F4F4", # 연회색
}
5. 프론트엔드 화면 구성
5.1. 타임테이블 뷰 (view-timetable)
┌─────────────────────────────────────────────────────────┐
│ 📅 작업 타임테이블 [+ 작업 등록] [📥 Excel] │
├─────────────────────────────────────────────────────────┤
│ [기관▼] [작업유형▼] [결과▼] [날짜범위] [담당자] [검색] │
├─────────────────────────────────────────────────────────┤
│ 날짜/시간 │ 유형 │ 제목 │ 기관 │
│ │ │ │ │
│ 2025-03-15 14:00 │ 정기점검 │ 1분기 정기점검 │ MOF │
│ │ │ - 기획재정부 │ ✅완료 │
│ │ │ │ │
│ 2025-03-20 09:00 │ SR작업 │ SR-20250320-001 │ MOIS │
│ │ │ WAS 재기동 │ ⚠일부 │
└───────────────────────────────────────────────────────--┘
5.2. 신규 등록 모달
┌─ 작업 등록 ──────────────────────────────────────────┐
│ 작업유형 [정기점검 ▼] 기관 [MOF ▼] │
│ 제목 [___________________________________] │
│ 대상서버 [MOF-WAS-01 ▼] SR연계 [선택 ▼] │
│ 처리예정 [2025-03-15] [14:00] │
│ │
│ 처리내용 │
│ [──────────────────────────────────────────] │
│ [ ] │
│ │
│ 명령어/쉘 스크립트 │
│ [쉘 선택 ▼] 또는 직접 입력 │
│ [──────────────────────────────────────────] │
│ │
│ 처리결과 [___________________________] │
│ 결과상태 [완료 ✅ / 부분완료 ⚠ / 실패 ❌] │
│ 담당자 [김엔지니어 ▼] 검토자 [이PM ▼] │
│ │
│ [취소] [저장] │
└───────────────────────────────────────────────────────┘
6. Excel 생성 코드 구조 (서버측)
# routers/timetable.py
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from fastapi.responses import StreamingResponse
import io
@router.get("/export/excel")
async def export_excel(
inst_code: str | None = Query(None),
date_from: date | None = Query(None),
date_to: date | None = Query(None),
work_type: str | None = Query(None),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
# 1. 데이터 조회
rows = await _fetch_timetable(db, inst_code, date_from, date_to, work_type)
# 2. Workbook 생성
wb = Workbook()
ws = wb.active
ws.title = "작업이력"
# 3. 헤더 작성
headers = ["번호", "작업유형", "제목", "기관명", "대상서버",
"처리예정", "시작", "완료", "소요(분)",
"처리내용", "명령어/쉘", "처리결과", "결과상태",
"담당자", "검토자", "SR번호", "비고"]
_write_header(ws, headers)
# 4. 데이터 작성
for i, row in enumerate(rows, start=2):
_write_row(ws, i, row)
# 5. 통계 시트 추가
_add_stats_sheet(wb, rows)
# 6. StreamingResponse 반환
buf = io.BytesIO()
wb.save(buf)
buf.seek(0)
filename = f"GUARDiA_작업이력_{inst_code or 'ALL'}_{date.today():%Y%m%d}.xlsx"
return StreamingResponse(
buf,
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
headers={"Content-Disposition": f"attachment; filename*=UTF-8''{filename}"}
)
7. 의존성
openpyxl>=3.1.0 # Excel 생성 (on-premise, 외부 API 없음)
requirements.txt에 추가:
openpyxl==3.1.2