kintex/scripts/gen_rfp_docs.py
ythong 6acfeab1ab docs(rfp): KINTEX RFP docx and proposal pptx with generator script
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 12:12:58 +09:00

930 lines
66 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""RFP.docx(나라장터 표준) + 제안발표.pptx(50슬라이드) 생성 스크립트.
근거: docs/PLANNING.md v3.5 (M1~M18 + §5B 공통레이어 + §1A 멀티테넌시 + §8A AI),
docs/design.md v2.8, docs/FEATURE_BACKLOG_100.md
출력: docs/RFP.docx, docs/제안발표.pptx
"""
import os
BASE = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "docs")
KOR_FONT = "맑은 고딕"
BIZ_NAME = "킨텍스 AI 전시·행사시스템(KINTEX AI Exhibition & Event System) 구축 사업"
# ══════════════════════════════ RFP DOCX ══════════════════════════════
from docx import Document
from docx.shared import Pt, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn, nsdecls
from docx.oxml import parse_xml
PRIMARY = RGBColor(0x00, 0x4C, 0x86)
def _set_kr(style_or_font):
f = getattr(style_or_font, "font", style_or_font)
f.name = KOR_FONT
el = f.element if hasattr(f, "element") else None
# style 객체
try:
rpr = style_or_font._element.get_or_add_rPr()
rpr.rFonts.set(qn("w:eastAsia"), KOR_FONT)
except Exception:
pass
def run_kr(par, text, size=10, bold=False, color=None, italic=False):
r = par.add_run(text)
r.font.name = KOR_FONT
r._element.rPr.rFonts.set(qn("w:eastAsia"), KOR_FONT)
r.font.size = Pt(size)
r.bold = bold
r.italic = italic
if color:
r.font.color.rgb = color
return r
def para(doc, text, size=10, bold=False, color=None, align=None, space_after=6, indent=None):
p = doc.add_paragraph()
if align is not None:
p.alignment = align
p.paragraph_format.space_after = Pt(space_after)
if indent:
p.paragraph_format.left_indent = Cm(indent)
run_kr(p, text, size=size, bold=bold, color=color)
return p
def bullet(doc, text, size=10, level=0):
p = doc.add_paragraph(style="List Bullet" if level == 0 else "List Bullet 2")
run_kr(p, text, size=size)
p.paragraph_format.space_after = Pt(3)
return p
def heading(doc, text, level=1):
h = doc.add_heading(level=level)
sizes = {1: 16, 2: 13, 3: 11.5}
run_kr(h, text, size=sizes.get(level, 11), bold=True, color=PRIMARY)
return h
def shade(cell, hexcolor="D9EAF7"):
cell._tc.get_or_add_tcPr().append(
parse_xml(r'<w:shd {} w:val="clear" w:fill="{}"/>'.format(nsdecls("w"), hexcolor)))
def make_table(doc, header, rows, widths=None, hdr_size=9.5, size=9.5):
t = doc.add_table(rows=1 + len(rows), cols=len(header))
t.style = "Table Grid"
t.alignment = WD_TABLE_ALIGNMENT.CENTER
for j, htxt in enumerate(header):
c = t.cell(0, j)
c.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
run_kr(c.paragraphs[0], htxt, size=hdr_size, bold=True)
shade(c)
for i, row in enumerate(rows):
for j, val in enumerate(row):
c = t.cell(i + 1, j)
run_kr(c.paragraphs[0], str(val), size=size)
if widths:
for j, w in enumerate(widths):
for row in t.rows:
row.cells[j].width = Cm(w)
doc.add_paragraph().paragraph_format.space_after = Pt(4)
return t
def req_block(doc, rid, name, details):
"""요구사항 상세 카드(조달청 서식: 고유번호/명칭/상세설명)."""
t = doc.add_table(rows=3, cols=4)
t.style = "Table Grid"
hdr = [("요구사항 고유번호", rid), ("요구사항 명칭", name)]
for k, (label, val) in enumerate(hdr):
lc, vc = t.cell(0, k * 2), t.cell(0, k * 2 + 1)
run_kr(lc.paragraphs[0], label, size=9, bold=True); shade(lc)
run_kr(vc.paragraphs[0], val, size=9, bold=True)
dc = t.cell(1, 0); dc.merge(t.cell(1, 3))
run_kr(dc.paragraphs[0], "요구사항 상세설명", size=9, bold=True); shade(dc, "EFF6FC")
bc = t.cell(2, 0); bc.merge(t.cell(2, 3))
first = True
for d in details:
p = bc.paragraphs[0] if first else bc.add_paragraph()
first = False
run_kr(p, "" + d, size=9)
doc.add_paragraph().paragraph_format.space_after = Pt(2)
# ---- 요구사항 데이터 (총 50건) ----
SFR = [
("SFR-001", "행사·홀 배정 및 자동 견적(M1)", [
"행사 등록 시 희망 면적·기간·홀 조건을 입력하면 가용 홀 탐색과 충돌 검증을 자동 수행하여야 한다.",
"홀 요율 규칙(기준단가 2,250원/㎡ 등 요율 마스터) 기반 즉시 자동 견적을 산출하여야 한다.",
"홀 배정 확정 시 행사 워크스페이스가 자동 생성되어 후속 모듈(M2~M9)과 연계되어야 한다."]),
("SFR-002", "플로어플랜 스튜디오 — 부스 배치 자동화(M2)", [
"홀 도면(DWG/JPG) 언더레이 위에 부스 폴리곤을 배치·편집하는 웹 캔버스 에디터를 제공하여야 한다(팬·줌 포함).",
"조건(부스 수·규격·통로폭·소방 규정) 입력 시 복수 배치안을 자동 생성하고 비교·선택·병합할 수 있어야 한다.",
"K1·K2 전시홀 실측 도면(트렌치 좌표 포함)을 기준 데이터로 적재하여야 한다."]),
("SFR-003", "자동 배치 3단계 위저드(M2-1)", [
"초보 사용자용 3단계 위저드(홀/구역 선택 → 조건 입력 → 결과 비교·선택)를 제공하여야 한다.",
"전시홀 트리(전시장>홀>구역) 선택과 구역 경계 스냅 배치를 지원하여야 한다.",
"배치 적용(apply-option) 시 실제 저장·후속 단계 연계까지 폐루프로 완결되어야 한다."]),
("SFR-004", "부스 설계 스튜디오(M3)", [
"부스 단위 인테리어·장치 공사 설계(구조물·가구·사인·조명 배치)를 지원하여야 한다.",
"설계안으로부터 물량(BOQ)·예상 공사비 개산을 자동 산출하여야 한다."]),
("SFR-005", "유틸리티 설계 자동화(M4)", [
"부스 좌표 기반 전기·조명, 네트워크, 급배수 배선 경로를 트렌치 위치 기준으로 자동 산출하여야 한다.",
"배선 결과를 도면 오버레이로 시각화하고 자동 견적과 연동하여야 한다."]),
("SFR-006", "나노바나나 시공 예상 시각화(M5)", [
"배치·설계·배선 데이터를 근거로 이미지 생성 AI(Gemini 계열)를 통해 '시공 후 결과 사진'을 생성하여야 한다.",
"표준 샷 세트(부스 정면/야간 조명/통로 뷰/홀 조감 등 S1~S7)와 Before/After 비교를 제공하여야 한다.",
"생성 이미지에는 'AI 생성' 워터마크와 고지문구를 강제 적용하여야 한다.",
"생성 작업은 비동기 큐(RenderJob) 기반으로 처리하고 완료 시 실시간 통지(WebSocket)하여야 한다."]),
("SFR-007", "서류·마일스톤 워크플로(M6)", [
"행사 준비 서류(반입·전기·화기 등)의 온라인 제출·검수·승인 워크플로를 제공하여야 한다.",
"마일스톤(D-day) 기반 마감 관리와 알림(임박·초과)을 제공하여야 한다."]),
("SFR-008", "등록업체 매칭·견적(M7)", [
"킨텍스 등록업체(장치·전기·통신 등) 디렉토리와 업체 매칭·견적 요청 기능을 제공하여야 한다."]),
("SFR-009", "반입/반출 물류 슬롯(M8)", [
"반입·반출 차량 슬롯 예약과 게이트 배정, 현장 혼잡 분산 기능을 제공하여야 한다."]),
("SFR-010", "정산·결제(M9)", [
"홀 사용료·유틸리티·부대서비스 통합 정산과 PG 연동 온라인 결제, 환불 정책 처리를 제공하여야 한다."]),
("SFR-011", "공사/장치 옥션 플랫폼(M15)", [
"AI 설계 산출물(배치·설계·물량·예상 이미지)을 근거자료로 공사·장치업체 대상 역경매(입찰)를 운영하여야 한다.",
"견적서 제출·실시간 순위·채점(가격+실적+평가)·낙찰자 선정 흐름을 제공하여야 한다."]),
("SFR-012", "관람객 등록·티켓·배지·리드캡처(M10)", [
"관람객 사전등록·티켓 발급·QR 배지·현장 체크인을 제공하여야 한다.",
"참가업체용 리드 캡처(QR 스캔·명함)와 사후 리드 관리 기능을 제공하여야 한다."]),
("SFR-013", "비즈니스 매칭(M11)", [
"참가업체-바이어 프로필 기반 AI 추천 매칭과 상담 일정 예약 기능을 제공하여야 한다."]),
("SFR-014", "마케팅·EDM·공개 홍보 사이트(M12)", [
"일반 대중 대상 공개 홍보 사이트(전시 일정·안내·포스터, 반응형·SEO)를 제공하여야 한다.",
"EDM 발송·구독 관리·수신거부 처리 기능을 제공하여야 한다."]),
("SFR-015", "Wayfinding·실내 내비(M13)", [
"홀 도면 기반 부스 검색·경로 안내(모바일 웹) 기능을 제공하여야 한다."]),
("SFR-016", "현장운영(M14)", [
"혼잡·안전·주차·에너지 현황 모니터링 대시보드를 제공하여야 한다."]),
("SFR-017", "경영분석 BI(M16)", [
"매출·홀 가동률·참가사 리텐션·행사 P&L·수요예측 KPI 대시보드를 제공하여야 한다.",
"운영사 관점 수익성/ROI 분석과 데이터마트 기반 집계를 제공하여야 한다."]),
("SFR-018", "CMS(M17)", [
"전시 콘텐츠·공지·배너·참가업체 마이크로사이트·다국어 콘텐츠 관리(헤드리스)를 제공하여야 한다."]),
("SFR-019", "관리자 백오피스·시스템관리(M18·공통)", [
"사용자·역할/권한(RBAC)·메뉴·공통코드·감사로그·시스템설정 관리 기능을 제공하여야 한다.",
"룰셋(규정·요율) 관리와 통계·모니터링 기능을 제공하여야 한다."]),
("SFR-020", "공통 업무기능·멀티테넌시·모바일", [
"공통 업무기능(업무일지·일정·쪽지·공지·의견·검색·보고서·알림)을 전 역할 공용으로 제공하여야 한다.",
"다중 전시관(테넌트) 격리(tenant_id 전파·컨텍스트 해소·2계층 관리자)를 지원하여야 한다.",
"모바일 앱(운영 B2B·관람객 B2C)에서 조회·승인·현장 기능을 제공하여야 한다."]),
]
PER = [
("PER-001", "응답시간", ["일반 화면 조회 3초 이내, 자동 배치안 생성 30초 이내(안 3개 기준), AI 이미지 생성은 비동기 처리 후 완료 통지."]),
("PER-002", "동시사용자", ["평시 500명, 대형 행사 피크 3,000명 동시접속에서 성능 저하 없이 서비스 가능하여야 한다."]),
("PER-003", "가용성", ["연중 가용률 99.5% 이상, 계획 정지는 사전 공지 후 야간 수행."]),
]
SIR = [
("SIR-001", "결제(PG) 연동", ["신용카드·계좌이체 등 PG 연동 및 취소·부분환불 처리."]),
("SIR-002", "SSO·HR 연동", ["킨텍스 내부 SSO(Open SSO)와 인사(HR) 조직·직원 정보 연동."]),
("SIR-003", "CAD(DWG) 연동", ["홀 도면 DWG 입력 파이프라인(좌표 추출·캘리브레이션·JPG 렌더) 제공."]),
]
DAR = [
("DAR-001", "공간 데이터", ["부스 폴리곤·트렌치 포인트·배선 경로를 공간 타입(PostGIS)으로 관리하고 공간 연산을 지원."]),
("DAR-002", "마스터 데이터", ["홀·요율·규정 룰셋·공통코드·등록업체 마스터의 표준화 및 이관·시드."]),
("DAR-003", "데이터 표준", ["명명 규칙·코드 표준·이력 관리(감사) 등 데이터 표준 수립 및 준수."]),
]
ECR = [
("ECR-001", "서버 구성", ["WAS(Spring Boot)·WEB(nginx)·DB(PostgreSQL+PostGIS)·캐시/큐(Redis)·AI 워커(Python) 구성."]),
("ECR-002", "운영환경", ["개발·운영 환경 분리, 서비스 데몬(systemd) 및 무중단 배포 고려."]),
("ECR-003", "스토리지", ["AI 생성 이미지·도면 파일용 오브젝트 스토리지 및 백업 체계."]),
]
SER = [
("SER-001", "인증·인가", ["JWT 기반 인증 + 2차인증(OTP), 행사 단위 RBAC, 테넌트 격리 접근통제."]),
("SER-002", "개인정보보호", ["개인정보 암호화(저장·전송), 마스킹, 접속기록 보관 등 개인정보보호법 준수."]),
("SER-003", "시큐어코딩", ["행정안전부 소프트웨어 개발보안 가이드 준수 및 보안약점 진단·조치."]),
("SER-004", "AI 산출물 신뢰성", ["AI 생성물 'AI 생성/초안' 라벨·워터마크 강제, 구조 안전성 최종 판정은 인간 승인 절차 유지."]),
]
TER = [
("TER-001", "테스트", ["단위·통합·성능·보안 테스트 계획 수립 및 수행, 결함 관리 체계 운영."]),
("TER-002", "검수", ["기능별 검수 시나리오 기반 사용자 인수테스트(UAT) 지원."]),
]
QUR = [
("QUR-001", "품질보증", ["품질보증 계획 수립, 산출물 표준 준수, 단계별 품질 게이트 운영."]),
("QUR-002", "표준 준수", ["전자정부 표준프레임워크 상당의 개발표준 및 발주기관 UI/UX 표준(디자인 시스템) 준수."]),
]
COR = [
("COR-001", "기술 제약", ["확정 스택(React+TypeScript / Spring Boot 3.x Java 17 / MyBatis / PostgreSQL+PostGIS / Redis) 준수."]),
("COR-002", "지식재산권", ["개발 산출물 소유권은 발주기관에 귀속, 오픈소스 라이선스 검증 수행."]),
("COR-003", "AI 비용 제약", ["AI 호출은 토큰 최소화 원칙(소형모델 우선·캐싱·출력 상한·집계는 SQL) 준수, 사용량 측정지표 제공."]),
]
PMR = [
("PMR-001", "사업관리", ["WBS 기반 일정·진척 관리, 주간·월간 보고, 이슈·리스크 관리."]),
("PMR-002", "방법론", ["애자일(스프린트) 기반 반복 개발과 단계별 산출물 검토 병행."]),
("PMR-003", "형상관리", ["소스·문서 형상관리(Git), 변경관리 절차 운영."]),
("PMR-004", "투입인력", ["PM·아키텍트(AA/TA/DA)·백엔드·프론트·AI·DB·QA 등 분야별 적정 인력 투입 및 교체 승인 절차."]),
]
PSR = [
("PSR-001", "교육·기술이전", ["운영자·사용자 교육 및 운영 매뉴얼·기술문서 제공, 기술이전 계획 수립."]),
("PSR-002", "하자보수", ["검수 완료 후 무상 하자보수 12개월, 하자 등급별 대응시간 준수."]),
("PSR-003", "안정화 지원", ["오픈 후 안정화 기간(2개월) 상주 지원 및 비상 대응 체계."]),
]
REQ_GROUPS = [
("기능 요구사항(SFR)", SFR), ("성능 요구사항(PER)", PER), ("인터페이스 요구사항(SIR)", SIR),
("데이터 요구사항(DAR)", DAR), ("시스템 장비구성 요구사항(ECR)", ECR), ("보안 요구사항(SER)", SER),
("테스트 요구사항(TER)", TER), ("품질 요구사항(QUR)", QUR), ("제약사항(COR)", COR),
("프로젝트 관리 요구사항(PMR)", PMR), ("프로젝트 지원 요구사항(PSR)", PSR),
]
def build_docx(path):
doc = Document()
# 기본 스타일
normal = doc.styles["Normal"]
normal.font.name = KOR_FONT
normal.font.size = Pt(10)
normal._element.get_or_add_rPr().rFonts.set(qn("w:eastAsia"), KOR_FONT)
for hs in ["Heading 1", "Heading 2", "Heading 3"]:
st = doc.styles[hs]
st.font.name = KOR_FONT
st._element.get_or_add_rPr().rFonts.set(qn("w:eastAsia"), KOR_FONT)
sec = doc.sections[0]
sec.top_margin = sec.bottom_margin = Cm(2.2)
sec.left_margin = sec.right_margin = Cm(2.4)
# ── 표지 ──
for _ in range(4):
doc.add_paragraph()
para(doc, "제 안 요 청 서", size=32, bold=True, color=PRIMARY, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=18)
para(doc, "(RFP : Request For Proposal)", size=14, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=30)
para(doc, BIZ_NAME, size=17, bold=True, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=10)
para(doc, "— 나라장터(국가종합전자조달, g2b.go.kr) 공고용 —", size=11, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=60)
for _ in range(6):
doc.add_paragraph()
para(doc, "2026. 7.", size=14, bold=True, align=WD_ALIGN_PARAGRAPH.CENTER, space_after=14)
para(doc, "주식회사 킨텍스(KINTEX)", size=16, bold=True, align=WD_ALIGN_PARAGRAPH.CENTER)
doc.add_page_break()
# ── 목차(개요) ──
heading(doc, "목 차", 1)
for line in [
". 사업 개요", "Ⅱ. 현황 및 문제점", "Ⅲ. 사업 추진방안", "Ⅳ. 제안요청 내용(요구사항)",
". 제안서 작성요령(제안서 목차 포함)", "Ⅵ. 제안서 평가", "Ⅶ. 계약 일반조건 및 특수조건",
"[별첨] 제안서 표지 서식·요구사항 대응표"]:
para(doc, line, size=11, space_after=8)
doc.add_page_break()
# ── . 사업 개요 ──
heading(doc, ". 사업 개요", 1)
heading(doc, "1. 사업 기본정보", 2)
make_table(doc, ["구분", "내용"], [
["사 업 명", BIZ_NAME],
["발주기관", "주식회사 킨텍스(KINTEX)"],
["사업기간", "계약체결일로부터 12개월 (안정화 지원 2개월 별도)"],
["사업예산", "금 2,970,000,000원(부가가치세 포함) 이내 ※ 협상에 의한 계약"],
["계약방법", "제한경쟁입찰 / 협상에 의한 계약 (나라장터 전자입찰)"],
["입찰방식", "국가종합전자조달시스템(나라장터, g2b.go.kr) 전자제출"],
], widths=[3.2, 12.5])
heading(doc, "2. 추진 배경", 2)
bullet(doc, "킨텍스는 총 전시면적 108,011㎡의 국내 최대 전시장을 운영하나, 전시 준비 실무는 HWP 서식 다운로드 후 이메일 제출, CAD 수작업 배치안, 담당자 육안 규정 검토, 수기 위치표시도 기반 유틸리티 신청 등 수작업 중심에 머물러 있음.")
bullet(doc, "온라인 작업신고 시스템(kxwp)이 존재하나 로그인 기반 서류 업로드 창구 수준이며, 참가업체 유틸리티 신청은 전시회별 주최자 시스템으로 파편화되어 있음.")
bullet(doc, "2028년 제3전시장 개관(전공 면적 178,000㎡ 확대)에 대비하여 전시 생애주기 전 과정의 디지털 전환·자동화가 시급함.")
heading(doc, "3. 사업 목표", 2)
bullet(doc, "\"신청서를 내는 시간, 시공 후 사진을 먼저 본다\" — 전시 준비 전 과정(홀 배정→부스 배치→장치공사 설계→전기/조명→네트워크/유틸리티 배선→반입/반출)을 AI로 자동 설계·검증하고, 이미지 생성 AI(나노바나나)로 시공 결과를 사전 시각화.")
make_table(doc, ["목표", "현재(As-Is)", "목표(To-Be)"], [
["홀 배정 견적 회신", "문의→협의→견적 수일", "즉시 자동 견적"],
["부스 배치안 초안", "CAD 수작업 수일~수주", "조건 입력 후 복수 안 자동 생성(30초 이내)"],
["도면 규정 검토", "담당자 육안 검토", "규정 전반 자동 플래깅(통로폭·소방 등)"],
["유틸리티 신청", "수기 위치 표시", "부스 좌표 클릭 → 자동 배선·자동 견적"],
["시공 결과 예측", "불가(조감도 별도 외주)", "표준 샷 세트 자동 생성(부스 정면/야간/통로/조감)"],
], widths=[4.2, 5.4, 6.1])
heading(doc, "4. 사업 범위", 2)
bullet(doc, "응용시스템 구축: 부스 코어(M1~M9) + 도메인 확장(M10~M18) 총 18개 모듈, 공통/시스템관리 레이어, 6+2 역할별 웹 포털(MDI) 및 모바일 앱(운영 B2B·관람객 B2C).")
bullet(doc, "AI 서비스: 부스 배치 자동생성(제약 솔버+LLM), 규정 검증 보조, 나노바나나 시공 예상 이미지 파이프라인, 자연어 조회, 수요/매출 예측, 비즈니스 매칭 추천.")
bullet(doc, "데이터 구축: 홀·요율·규정 룰셋 마스터, K1·K2 실측 도면(DWG/JPG)·트렌치 좌표 공간데이터 적재.")
bullet(doc, "다중 전시관(멀티테넌트 SaaS) 기반 구조 및 시스템 인프라(서버·스토리지·배포체계) 구성, 교육·기술이전·안정화 지원.")
bullet(doc, "범위 제외: 전자계약 법적 체결(Phase 3 이후 검토), 구조 안전성 최종 판정의 AI 대체(인간 승인 유지), 관람객 택시·숙박 예약 등 부가 서비스.")
doc.add_page_break()
# ── Ⅱ. 현황 및 문제점 ──
heading(doc, "Ⅱ. 현황 및 문제점", 1)
heading(doc, "1. 업무 현황", 2)
bullet(doc, "주최자: 행사 유치→홀 배정 협의→도면 승인→서류 취합→현장 운영→정산의 전 과정을 이메일·전화·수기 문서로 수행, 단계 간 데이터 단절.")
bullet(doc, "참가업체·장치업체: 부스 설계·공사 견적을 개별 접촉으로 확보, 시공 결과를 사전에 확인할 수단 부재, 유틸리티 신청 창구 파편화.")
bullet(doc, "킨텍스 운영: 도면 규정 검토·서류 검수·현장 민원 대응에 수작업 반복, 행사별 데이터가 축적·분석되지 않아 경영분석 곤란.")
heading(doc, "2. 정보시스템 현황", 2)
make_table(doc, ["시스템", "기능", "한계"], [
["kxwp(온라인 작업신고)", "로그인 후 서류 업로드", "설계·검증·견적 기능 부재, 단순 창구"],
["홈페이지(kintex.com)", "행사 안내·홍보", "업무시스템과 미연계"],
["주최자별 개별 시스템", "행사별 참가업체 관리", "킨텍스 공통 플랫폼 부재, 데이터 미축적"],
], widths=[4.5, 5.2, 6.0])
heading(doc, "3. 개선 방향", 2)
bullet(doc, "전시 생애주기(영업·기획→설계·시각화→발주·계약→참가·관람→현장운영→사후·경영) 전 단계를 단일 플랫폼·단일 데이터 체계로 자동화.")
bullet(doc, "실측 공간데이터(PostGIS) 기반 자동 설계와 이미지 생성 AI 시각화를 결합한 차별화 — 설계→시각화→발주(옥션)→시공→운영→분석의 폐루프 완성.")
doc.add_page_break()
# ── Ⅲ. 사업 추진방안 ──
heading(doc, "Ⅲ. 사업 추진방안", 1)
heading(doc, "1. 추진 전략", 2)
bullet(doc, "P0 코어 우선: 차별화 핵심인 부스 배치(M2)→부스 설계(M3)→유틸리티 배선(M4)→나노바나나 시각화(M5)를 최우선 구축하여 조기 가시화.")
bullet(doc, "AI 산출물 신뢰성 확보: 모든 AI 산출물에 'AI 생성/초안' 라벨·워터마크, 규정 검증의 인간 최종 승인 절차 병행.")
bullet(doc, "표준 준수: 확정 기술스택(React·Spring Boot 3.x·MyBatis·PostgreSQL/PostGIS·Redis)과 발주기관 디자인 시스템 준수.")
bullet(doc, "멀티테넌트 기반: 킨텍스를 기준 테넌트로 하되 타 전시관 온보딩이 가능한 격리 구조(tenant_id 전파) 선반영.")
heading(doc, "2. 추진 체계", 2)
make_table(doc, ["주체", "역할"], [
["발주기관(킨텍스)", "사업총괄, 요구사항 확정, 검수, 마스터데이터 제공"],
["수행사(제안사)", "설계·구현·테스트·이행·교육·안정화, 품질/일정/위험 관리"],
["감리(필요 시)", "단계별 산출물·품질 점검"],
], widths=[4.5, 11.2])
heading(doc, "3. 추진 일정(안)", 2)
make_table(doc, ["단계", "기간", "주요 내용"], [
["Phase 1 분석·설계", "M1~M3", "요구사항 상세화, 아키텍처(AA/TA/DA) 확정, 데이터 표준·ERD, 화면 설계"],
["Phase 2 구축(P0 코어)", "M3~M7", "M2~M5 부스 코어 + 공통/시스템관리 레이어 + 인증(2FA)"],
["Phase 3 구축(도메인)", "M6~M10", "M1·M6~M18 도메인 모듈 + 모바일 앱 + 공개사이트"],
["Phase 4 통합·이행", "M10~M12", "통합테스트·성능·보안점검, 데이터 이관, UAT, 오픈"],
["안정화", "오픈 후 2개월", "상주 지원, 하자 대응, 운영 이관·기술이전"],
], widths=[3.8, 3.2, 8.7])
doc.add_page_break()
# ── Ⅳ. 제안요청 내용 ──
heading(doc, "Ⅳ. 제안요청 내용(요구사항)", 1)
para(doc, "본 장의 요구사항은 소프트웨어사업 요구사항 분류체계(기능 SFR·성능 PER·인터페이스 SIR·데이터 DAR·장비 ECR·보안 SER·테스트 TER·품질 QUR·제약 COR·관리 PMR·지원 PSR)에 따라 기술한다. 제안사는 전 요구사항에 대한 수용 여부와 구현 방안을 제안서에 명시하여야 한다.", size=10)
heading(doc, "1. 요구사항 총괄표", 2)
make_table(doc, ["분류", "요구사항 수", "고유번호"],
[[g[0], len(g[1]), f"{g[1][0][0]} ~ {g[1][-1][0]}"] for g in REQ_GROUPS]
+ [["합계", sum(len(g[1]) for g in REQ_GROUPS), ""]],
widths=[7.0, 3.2, 5.5])
for gi, (gname, items) in enumerate(REQ_GROUPS):
heading(doc, f"{gi + 2}. {gname}", 2)
for rid, name, details in items:
req_block(doc, rid, name, details)
doc.add_page_break()
# ── . 제안서 작성요령 ──
heading(doc, ". 제안서 작성요령", 1)
heading(doc, "1. 일반 지침", 2)
bullet(doc, "제안서는 본 제안요청서의 요구사항 순서에 따라 국문으로 작성하며, A4 기준 200쪽 이내(표지·목차·별첨 제외)로 한다.")
bullet(doc, "제안 내용은 구체적 구현 방안 중심으로 기술하고, 단순 일반론·타사 실적 나열은 지양한다.")
bullet(doc, "요구사항 대응표(요구사항 고유번호 ↔ 제안서 페이지)를 별첨으로 반드시 포함한다.")
bullet(doc, "제안서 및 제안발표자료는 나라장터 전자제출을 원칙으로 한다.")
heading(doc, "2. 제안서 목차(표준)", 2)
para(doc, "제안발표자료는 아래 제안서 목차와 동일한 체계로 작성한다.", size=10, bold=True)
make_table(doc, ["", "", "내용"], [
[". 제안 개요", "1~4", "제안사 일반현황 / 사업의 이해 / 제안 핵심 요지 / 제안 특장점"],
["Ⅱ. 기술 부문", "1~3", "목표 시스템(아키텍처·기술스택·멀티테넌시·3-트랙 IA)"],
["", "4~14", "기능 구현방안(M1~M18 모듈별) / 공통·시스템관리 레이어"],
["", "15~19", "AI 구현방안(나노바나나·토큰최소화) / 데이터·연동 / 모바일 / 보안 / 성능·품질(NFR)"],
["Ⅲ. 사업관리 부문", "1~6", "추진전략·방법론 / 조직·인력 / 일정 / 마일스톤·산출물 / 위험관리 / 품질보증·형상관리"],
["Ⅳ. 기술지원 부문", "1~4", "교육·기술이전 / 유지보수·하자보수 / 비상대응·보안준수 / 기대효과"],
], widths=[3.9, 2.0, 9.8])
heading(doc, "3. 제안발표", 2)
bullet(doc, "제안발표자료(PPT)는 50쪽 내외로 제안서 목차 순서에 따라 작성하며, 발표 20분·질의응답 15분으로 한다.")
bullet(doc, "발표자는 제안 PM을 원칙으로 한다.")
doc.add_page_break()
# ── Ⅵ. 제안서 평가 ──
heading(doc, "Ⅵ. 제안서 평가", 1)
heading(doc, "1. 평가 방법", 2)
bullet(doc, "협상에 의한 계약 체결 기준(기획재정부 계약예규)에 따라 기술능력평가(90%)와 입찰가격평가(10%)를 합산하여 협상적격자를 선정한다.")
bullet(doc, "기술능력평가 점수가 배점한도의 85% 이상인 자를 협상적격자로 한다.")
heading(doc, "2. 기술평가 배점(안)", 2)
make_table(doc, ["평가부문", "평가항목", "배점"], [
["전략·방법론(20)", "사업 이해도·추진전략", "10"],
["", "방법론·일정·자원 계획", "10"],
["기술·기능(45)", "시스템 아키텍처·기술 적합성", "10"],
["", "기능 요구사항 구현방안(M1~M18)", "20"],
["", "AI(자동설계·시각화) 구현방안·신뢰성", "10"],
["", "보안·성능·품질 확보방안", "5"],
["수행역량(15)", "투입인력 전문성·유사실적", "10"],
["", "품질보증·위험관리 체계", "5"],
["지원(10)", "교육·기술이전·하자보수·안정화", "10"],
["합계", "", "90"],
], widths=[4.4, 8.5, 2.4])
doc.add_page_break()
# ── Ⅶ. 계약조건 ──
heading(doc, "Ⅶ. 계약 일반조건 및 특수조건", 1)
for txt in [
"계약 방식: 협상에 의한 계약, 확정금액 방식. 선금·기성·잔금 지급은 국가계약법령 및 발주기관 규정에 따른다.",
"하자담보: 검수 완료일로부터 12개월 무상 하자보수. 하자 등급별 대응(긴급 4시간 내 착수, 일반 2영업일 내).",
"지식재산권: 사업 수행 산출물의 소유권은 발주기관에 귀속하며, 오픈소스 사용 시 라이선스 검증 결과를 제출한다.",
"보안 준수: 수행 인력 보안서약, 개인정보 취급 최소화, 개발·운영 데이터 반출 금지, 프로젝트 종료 시 자료 파기 확인.",
"지체상금: 지체일수 1일당 계약금액의 0.75/1000. 계약상대자 귀책 시 국가계약법령에 따라 부과.",
"기술이전: 소스코드·설계문서·운영매뉴얼 일체 제공 및 운영인력 교육(관리자·운영자·사용자 각 1회 이상).",
"AI 특수조건: 이미지 생성 등 외부 AI API 사용 비용의 산정 근거와 상한 관리 방안을 제안서에 명시하고, AI 생성물 표시(워터마크·라벨)를 준수한다.",
]:
bullet(doc, txt)
doc.add_page_break()
# ── 별첨 ──
heading(doc, "[별첨 1] 제안서 표지 서식", 1)
make_table(doc, ["항목", "기재 내용"], [
["사업명", BIZ_NAME], ["제안사명", "(상호·대표자·소재지)"],
["제출일자", "2026. . ."], ["담당자", "(성명·연락처·이메일)"],
], widths=[4.0, 11.7])
heading(doc, "[별첨 2] 요구사항 대응표 서식", 1)
make_table(doc, ["요구사항 고유번호", "요구사항 명칭", "수용여부", "제안서 페이지"],
[["SFR-001", "행사·홀 배정 및 자동 견적(M1)", "수용/부분수용/미수용", "p."],
["", "", "", ""]],
widths=[3.6, 7.0, 3.2, 2.6])
doc.save(path)
return path
# ══════════════════════════════ PPTX ══════════════════════════════
from pptx import Presentation
from pptx.util import Inches, Pt as PPt
from pptx.dml.color import RGBColor as PRGB
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.oxml.ns import qn as pqn
P_BLUE = PRGB(0x00, 0x66, 0xB3)
P_DARK = PRGB(0x00, 0x4C, 0x86)
P_AI = PRGB(0x6D, 0x4A, 0xFF)
P_GREY = PRGB(0x34, 0x40, 0x54)
P_LIGHT = PRGB(0xEF, 0xF6, 0xFC)
P_WHITE = PRGB(0xFF, 0xFF, 0xFF)
def pset(run, size, bold=False, color=P_GREY):
f = run.font
f.size = PPt(size)
f.bold = bold
f.color.rgb = color
f.name = KOR_FONT
rPr = run._r.get_or_add_rPr()
for tag in ("a:ea", "a:cs"):
el = rPr.find(pqn(tag))
if el is None:
el = rPr.makeelement(pqn(tag), {})
rPr.append(el)
el.set("typeface", KOR_FONT)
def add_box(slide, x, y, w, h):
tb = slide.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h))
tb.text_frame.word_wrap = True
return tb.text_frame
def add_rect(slide, x, y, w, h, fill, line=False):
sh = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, Inches(x), Inches(y), Inches(w), Inches(h))
sh.fill.solid()
sh.fill.fore_color.rgb = fill
if not line:
sh.line.fill.background()
sh.shadow.inherit = False
return sh
def footer(slide, idx, total):
tf = add_box(slide, 0.5, 7.05, 12.3, 0.35)
p = tf.paragraphs[0]
r = p.add_run()
r.text = f"{BIZ_NAME} 제안발표자료"
pset(r, 9, color=PRGB(0x66, 0x70, 0x85))
tf2 = add_box(slide, 12.3, 7.05, 0.7, 0.35)
p2 = tf2.paragraphs[0]
p2.alignment = PP_ALIGN.RIGHT
r2 = p2.add_run()
r2.text = f"{idx}/{total}"
pset(r2, 9, color=PRGB(0x66, 0x70, 0x85))
def slide_cover(prs, idx, total):
s = prs.slides.add_slide(prs.slide_layouts[6])
add_rect(s, 0, 0, 13.333, 7.5, P_DARK)
add_rect(s, 0, 4.9, 13.333, 0.06, P_AI)
tf = add_box(s, 1.0, 2.0, 11.3, 2.6)
p = tf.paragraphs[0]
r = p.add_run(); r.text = "킨텍스 AI 전시·행사시스템 구축 사업"; pset(r, 40, True, P_WHITE)
p2 = tf.add_paragraph()
r = p2.add_run(); r.text = "KINTEX AI Exhibition & Event System"; pset(r, 20, False, PRGB(0xD9, 0xEA, 0xF7))
tf2 = add_box(s, 1.0, 5.1, 11.3, 1.6)
p = tf2.paragraphs[0]
r = p.add_run(); r.text = "제 안 발 표 자 료"; pset(r, 24, True, P_WHITE)
p2 = tf2.add_paragraph()
r = p2.add_run(); r.text = '"신청서를 내는 시간, 시공 후 사진을 먼저 본다" · 2026. 7.'; pset(r, 14, False, PRGB(0xD9, 0xEA, 0xF7))
return s
def slide_section(prs, idx, total, no, title, subtitle):
s = prs.slides.add_slide(prs.slide_layouts[6])
add_rect(s, 0, 0, 13.333, 7.5, P_BLUE)
tf = add_box(s, 1.2, 2.5, 11.0, 2.5)
p = tf.paragraphs[0]
r = p.add_run(); r.text = no; pset(r, 22, True, PRGB(0xD9, 0xEA, 0xF7))
p2 = tf.add_paragraph()
r = p2.add_run(); r.text = title; pset(r, 40, True, P_WHITE)
p3 = tf.add_paragraph()
r = p3.add_run(); r.text = subtitle; pset(r, 15, False, PRGB(0xD9, 0xEA, 0xF7))
footer(s, idx, total)
return s
def slide_content(prs, idx, total, kicker, title, bullets):
"""bullets: list of (level, text) 또는 str(level 0)."""
s = prs.slides.add_slide(prs.slide_layouts[6])
add_rect(s, 0, 0, 13.333, 0.18, P_BLUE)
tf = add_box(s, 0.55, 0.35, 12.2, 1.15)
p = tf.paragraphs[0]
r = p.add_run(); r.text = kicker; pset(r, 12, True, P_AI)
p2 = tf.add_paragraph()
r = p2.add_run(); r.text = title; pset(r, 26, True, P_DARK)
add_rect(s, 0.6, 1.62, 12.1, 0.03, PRGB(0xD9, 0xEA, 0xF7))
body = add_box(s, 0.75, 1.85, 11.9, 5.0)
first = True
for b in bullets:
lvl, txt = (b if isinstance(b, tuple) else (0, b))
p = body.paragraphs[0] if first else body.add_paragraph()
first = False
p.space_after = PPt(8)
mark = "" if lvl == 0 else "·"
r = p.add_run()
r.text = f"{mark} {txt}" if lvl == 0 else f" {mark} {txt}"
pset(r, 15 if lvl == 0 else 13.5, lvl == 0 and txt.endswith(":"), P_GREY if lvl else PRGB(0x10, 0x18, 0x28))
footer(s, idx, total)
return s
SLIDES = [
("cover",),
("content", "AGENDA", "목차", [
". 제안 개요 — 제안사 현황 · 사업의 이해 · 제안 핵심 요지 · 특장점",
"Ⅱ. 기술 부문 — 목표 아키텍처 · 기능 구현방안(M1~M18) · AI · 데이터 · 보안 · 성능",
"Ⅲ. 사업관리 부문 — 전략·방법론 · 조직·인력 · 일정 · 위험 · 품질",
"Ⅳ. 기술지원 부문 — 교육·기술이전 · 유지보수 · 비상대응 · 기대효과",
(1, "본 자료는 제안요청서(RFP) Ⅴ장 제안서 목차 표준 체계에 따라 작성되었습니다."),
]),
("section", "PART ", "제안 개요", "제안사 현황 · 사업의 이해 · 제안 핵심 요지 · 특장점"),
("content", "-1. 제안 개요", "제안사 일반현황", [
"전시·컨벤션(MICE) 도메인과 AI 융합 시스템 구축에 특화된 수행 조직",
(1, "Spring Boot 3.x + React + PostgreSQL(PostGIS) 풀스택 표준 프레임워크 보유(WISE)"),
(1, "이미지 생성 AI(Gemini 계열) 상용 파이프라인 구축·운영 실증 경험"),
(1, "공간데이터(PostGIS) 기반 도면·배선 자동화 구현 실적"),
"본 사업 전담 조직: PM 1, 아키텍트(AA/TA/DA) 3, 백엔드 4, 프론트 4, AI 2, DB 1, QA 2, 모바일 2",
"품질·보안 체계: 개발보안 가이드 준수, 단계별 품질 게이트, 형상관리(Git) 표준 운영",
]),
("content", "-2. 제안 개요", "사업의 이해 — 현황과 문제(As-Is)", [
"국내 최대 전시장(108,011㎡)이지만 준비 실무는 수작업 중심:",
(1, "HWP 서식 다운로드 → 이메일 제출, 온라인 신고(kxwp)는 단순 업로드 창구"),
(1, "부스 배치안: 주최자 CAD 수작업 수일~수주 소요"),
(1, "도면 규정 검토: 담당자 육안 검토(통로폭·소방·높이 규정)"),
(1, "유틸리티 신청: 수기 위치표시도, 전시회별 시스템 파편화"),
"구조적 공백: 단계 간 데이터 단절 → 행사 데이터 미축적 → 경영분석 불가",
"2028년 제3전시장 개관(178,000㎡) 대비 디지털 전환이 시급한 시점",
]),
("content", "-2. 제안 개요", "사업의 이해 — 발주기관 요구 핵심", [
"전시 생애주기 전 과정의 자동화: 영업·기획 → 설계·시각화 → 발주·계약 → 참가·관람 → 현장운영 → 사후·경영분석",
"요구사항 총 50건: 기능(SFR) 20 + 성능·보안·데이터·연동·품질·관리·지원 30",
"확정 기술 제약(COR-001): React+TypeScript / Spring Boot 3.x(Java 17) / MyBatis / PostgreSQL+PostGIS / Redis",
"AI 신뢰성(SER-004): AI 생성물 라벨·워터마크 강제, 구조 안전 최종 판정은 인간 승인",
"AI 비용 제약(COR-003): 토큰 최소화 설계와 사용량 가시화",
"멀티테넌트(SFR-020): 킨텍스 기준 테넌트 + 타 전시관 온보딩 가능 구조",
]),
("content", "-3. 제안 개요", '제안 핵심 요지 — "신청서를 내는 시간, 시공 후 사진을 먼저 본다"', [
"차별화 폐루프: AI 설계 → 시각화 → 옥션 발주 → 시공 → 운영 → 분석",
(1, "① 조건 입력 → 부스 배치안 복수 자동 생성(제약 솔버 + LLM 조건해석)"),
(1, "② 배치·설계·배선 데이터 → 나노바나나가 '시공 후 결과 사진' 사전 생성(S1~S7 표준 샷)"),
(1, "③ AI 설계·물량·예상 이미지가 그대로 역경매(옥션) 근거자료 → 공사 발주까지 한 흐름"),
"실측 공간데이터가 경쟁력: K1·K2 홀 도면(DWG)·트렌치 좌표를 PostGIS로 적재 — 타 전시테크가 못 하는 정밀 배선 자동화",
"의사결정 혁신: 주최자·참가업체가 도면을 읽지 못해도 '사진 수준 시각화'로 결정",
]),
("content", "-4. 제안 개요", "제안 특장점 요약 (Why Us)", [
"① 검증된 표준 프레임워크(WISE) 이식 — 시스템관리·공통기능·2FA 인증을 재사용, 구축 리스크 최소화",
"② 이미지 생성 파이프라인 실증 — RenderJob 큐·워터마크·Before/After 등 상용 기법 확보",
"③ 공간데이터 전문성 — PostGIS 공간 연산(부스 폴리곤·트렌치·배선 LineString) 설계·구현 경험",
"④ AI 비용 통제 설계 — 소형모델 우선·캐싱·출력상한·집계는 SQL, 사용량 대시보드 제공",
"⑤ 멀티테넌트 선반영 — 기능 재개발 없이 타 전시관 확장 가능한 격리 구조",
"⑥ 전 요구사항(50건) 100% 수용 — 별첨 요구사항 대응표 제출",
]),
("section", "PART Ⅱ", "기술 부문", "목표 아키텍처 · 기능 구현방안(M1~M18) · AI · 데이터 · 보안 · 성능"),
("content", "Ⅱ-1. 기술 부문", "목표 시스템 개요", [
"단일 플랫폼에서 전시 생애주기 6단계를 커버하는 18개 모듈 + 공통 레이어",
(1, "영업·기획: M1 홀 배정·자동 견적, M16 수요예측"),
(1, "설계·시각화(핵심 P0): M2 배치 · M3 부스설계 · M4 배선 · M5 나노바나나"),
(1, "발주·계약: M6 서류, M7 등록업체, M15 공사/장치 옥션, M9 정산"),
(1, "참가·관람: M10 등록·배지·리드, M11 비즈매칭, M12 홍보사이트, M13 wayfinding"),
(1, "현장 운영: M8 물류 슬롯, M14 혼잡·안전·주차·에너지"),
(1, "사후·경영: M16 BI, M17 CMS, M18 관리자 + 공통/시스템관리 레이어(§5B)"),
]),
("content", "Ⅱ-1. 기술 부문", "목표 아키텍처", [
"웹: React 18/19 + Vite + TypeScript (역할별 포털, MDI 셸, 반응형)",
"API: Spring Boot 3.x(Java 17) + MyBatis — REST + WebSocket(STOMP)",
"엔진: 룰 엔진(규정·요율) · 배치/배선 엔진(PostGIS 공간 연산) · 옥션 채점 엔진",
"데이터: PostgreSQL + PostGIS(부스 폴리곤·트렌치·배선), Redis(작업 큐·캐시·세션)",
"AI 워커: Python 사이드카(나노바나나 이미지 생성) — Spring이 큐로 트리거, 완료 시 WebSocket 푸시",
"저장소: 오브젝트 스토리지(생성 이미지·도면), 배포: nginx + systemd + CI/CD(webhook)",
]),
("content", "Ⅱ-1. 기술 부문", "적용 기술 스택과 선정 사유", [
"RFP 제약(COR-001) 100% 준수 — 발주기관 표준 프레임워크(GUARDiA/WISE)와 정렬",
(1, "Spring Boot 3.x + MyBatis: 공공·기업 시스템 검증 스택, SQL 제어 용이(공간 쿼리 최적화)"),
(1, "React + TypeScript + Vite: 대규모 화면(80+ 라우트) 타입 안정성·생산성"),
(1, "PostGIS: 부스 겹침 검사·통로폭 검증·최단 배선 등 공간 연산을 DB 레벨에서 처리"),
(1, "Redis: RenderJob 큐·알림·세션 — 비동기 AI 작업의 표준 창구"),
"전자정부 표준프레임워크 상당의 계층 구조(controller/service/mapper)와 개발표준 적용",
]),
("content", "Ⅱ-2. 기술 부문", "멀티테넌트(다중 전시관 SaaS) 설계", [
"테넌트 = 전시관(Venue): KINTEX(기준 테넌트 #1) → COEX 등 타 전시관 온보딩 가능",
"격리 3원칙:",
(1, "데이터: 전 도메인 엔티티 tenant_id 전파, 조회 컨텍스트 자동 주입(누수 차단)"),
(1, "브랜딩: 테넌트별 로고·색상 토큰 오버레이(공유 디자인 시스템 위)"),
(1, "관리: 플랫폼 관리자 ↔ 테넌트 관리자 2계층 역할"),
"마스터데이터(홀·요율·규정 룰셋)는 테넌트 소유 — 전시관별 고유 규정 수용",
"기능·화면·모듈은 공유, 데이터만 격리 — 확장 시 재개발 불필요",
]),
("content", "Ⅱ-2. 기술 부문", "대외 접점 3-트랙 IA (visitor / business / agency)", [
"코엑스 3-사이트 IA 분석에 근거한 트랙 분리 — 랜딩 3-분기 + 트랙별 서브홈",
(1, "visitor(관람객): 공개 관람 랜딩, 행사 캘린더·티켓·wayfinding·AI 관람 도우미"),
(1, "business(주최자·참가업체): 행사 준비 전 과정 — 홀 배정→설계→서류→정산"),
(1, "agency(공사·장치·협력사): 옥션 열람·견적 제출·시공 일정·현장 작업"),
"로그인 사용자 구분이 메인페이지와 좌측 메뉴 그룹을 결정(역할→트랙 매핑 확정표)",
"내부 역할(ops/admin)은 트랙 외부 별도 백오피스 — 망·권한 분리",
]),
("content", "Ⅱ-2. 기술 부문", "역할별 포털·메뉴 결정 규칙 (6+2 역할)", [
"역할: 전시업체(참가) · 공사/장치업체 · 주최자 · 킨텍스 운영 · 킨텍스 관리 · 시스템 관리자(테넌트/플랫폼) + 일반 대중(공개)",
"미인증 진입 = visitor 공개 랜딩 / 인증 시 역할별 전용 메인으로 자동 라우팅",
"좌측 메뉴 그룹 매트릭스: 역할별 노출/차단을 시스템관리(메뉴·권한)에서 통제",
"모바일 하단 탭바도 동일 규칙(역할별 결정) — 웹·모바일 랜딩 패리티",
"멀티역할 사용자는 트랙 스위칭 UI 제공(판정 우선순위 규칙 적용)",
]),
("content", "Ⅱ-3. 기술 부문", "M1. 행사·홀 배정 및 자동 견적", [
"행사 등록 → 희망 면적·기간 입력 → 가용 홀 탐색·중복 예약 충돌 검증 자동화",
"요율 마스터(기준단가 2,250원/㎡ × 성수기·전시일 규칙) 기반 즉시 자동 견적",
"As-Is 수일 소요 견적 회신 → To-Be 즉시 산출(RFP 목표 정합)",
"배정 확정 시 행사 워크스페이스 자동 생성 → M2~M9 전 모듈 연계 시작점",
"홀 가동률 캘린더·활용도 통계로 영업 의사결정 지원(M16 연계)",
]),
("content", "Ⅱ-3. 기술 부문", "M2. 플로어플랜 스튜디오 — 부스 배치 자동화 (P0)", [
"웹 캔버스 에디터: 홀 실측 도면 언더레이 + 부스 폴리곤 배치·편집·팬/줌",
"자동 배치: 부스 수·규격·통로폭·소방 규정 입력 → 복수 배치안 생성(제약 솔버 + LLM 조건해석)",
"배치안 비교·선택·병합 → 규정 검증(통로폭·비상구·소방) 자동 플래깅",
"실측 데이터 확보 완료: K1·K2 전시홀 DWG(트렌치 좌표 포함)·JPG 15장 적재",
"As-Is CAD 수작업 수일~수주 → To-Be 30초 이내 복수 안(PER-001 정합)",
]),
("content", "Ⅱ-3. 기술 부문", "M2-1. 자동 배치 3단계 위저드 · DWG/JPG 언더레이", [
'"사용자가 쉽게" — 초보자도 3단계로 배치 완성:',
(1, "① 홀/구역 선택: 전시장>홀>구역 트리 + 구역 경계 스냅"),
(1, "② 조건 입력: 부스 수·규격·통로 조건(자연어 조건 해석 지원)"),
(1, "③ 결과 비교·선택: 3안 비교 → 적용(apply-option) 시 실제 저장·후속 연계"),
"도면 언더레이 이중화: 캘리브레이션된 JPG 탭 + DWG 정밀 렌더 탭 전환",
"K1 홀 1~5 축정렬 / K2 홀 6~10 회전보정(12°·11°·+11°) 결정론 캘리브레이션 완료",
]),
("content", "Ⅱ-3. 기술 부문", "M3. 부스 설계 스튜디오 (P0)", [
"부스 단위 인테리어·장치 설계: 구조물(벽체·리깅)·가구·사인·조명 배치",
"설계 템플릿 라이브러리(조립부스·독립부스·아일랜드형) + 커스터마이징",
"설계안 → 물량(BOQ)·예상 공사비 개산 자동 산출 → M15 옥션 근거자료",
"높이 5m·방염 등 장치 규정 자동 체크(룰 엔진 연동)",
"산출물: 설계 도면 + 물량서 + 나노바나나 시각화 입력 데이터",
]),
("content", "Ⅱ-3. 기술 부문", "M4. 유틸리티 설계 자동화 (P0)", [
"부스 좌표 클릭 → 트렌치 위치 기준 최단 배선 경로 자동 산출(PostGIS 공간 연산)",
"전기·조명 / 네트워크 / 급배수 3계통 — 계통별 오버레이 시각화",
"배선 물량 → 유틸리티 자동 견적(요율 마스터 연동) → 신청·승인 워크플로",
"As-Is 수기 위치표시도 → To-Be 좌표 클릭 한 번(트렌치 실측 좌표 V61 적재 완료)",
"현장 시공용 배선도 출력(PDF) 및 작업자 모바일 조회",
]),
("content", "Ⅱ-3. 기술 부문", "M5. 나노바나나 시각화 — 핵심 차별화 (P0)", [
"배치·설계·배선 데이터 → 이미지 생성 AI(Gemini 이미지 모델)로 '시공 후 결과 사진' 생성",
"표준 샷 세트 S1~S7: 부스 정면 · 인테리어 · 야간 조명 연출 · 통로 뷰 · 배선 오버레이 · 홀 조감 등",
"Before/After 슬라이더 — 도면 대비 시공 예상을 직관 비교",
"홀 조감(S7)은 버튼 클릭 시에만 생성(자동 발행 금지) — 비용 통제",
"생성 이미지는 갤러리에 영속·재열람, M15 옥션 참고 이미지로 재사용",
]),
("content", "Ⅱ-3. 기술 부문", "나노바나나 파이프라인 상세 (신뢰성·비용 방어)", [
"아키텍처: Spring → Redis 큐(RenderJob) → Python 워커(google-genai) → 오브젝트 스토리지 → WebSocket 완료 푸시",
"ReRoomAI 실증 기법 이식: image-to-image 보존/교체 프롬프트 제어, 파라미터 확정",
"방어 로직: 재시도·타임아웃·실패 폴백, 작업 상태 UX(대기·생성중·완료·실패)",
"워터마크·고지 정책(필수): 전 생성 이미지 'AI 생성 예상 이미지' 워터마크 강제(SER-004)",
"시공사 견적·계약의 참고자료 지위 명시 — 법적 리스크 차단(R1·R2 대응)",
]),
("content", "Ⅱ-3. 기술 부문", "M6. 서류·마일스톤 / M7. 등록업체 매칭", [
"M6 서류 워크플로:",
(1, "반입·전기·화기 등 서류 온라인 제출 → 검수 → 승인 (HWP·이메일 대체)"),
(1, "행사별 마일스톤(D-day) 자동 생성, 마감 임박(D-3)·초과 알림"),
(1, "AI 서류 검수 보조: 누락·불일치 사전 플래깅"),
"M7 등록업체:",
(1, "킨텍스 등록업체(장치·전기·통신·경비·청소) 디렉토리·자격 관리"),
(1, "업체 매칭·견적 요청 → M15 옥션과 연계"),
]),
("content", "Ⅱ-3. 기술 부문", "M15. 공사/장치 옥션(역경매) 플랫폼 — 핵심 플로우", [
"AI 산출물(배치·설계·물량·예상 이미지)이 그대로 입찰 근거자료 — 발주 준비 비용 제로화",
"흐름: 전시업체 옥션 개설 → 공사업체 열람·견적서 제출 → 역경매 경쟁 → 낙찰 확정",
"실시간 순위 푸시(WebSocket) · 마감 자동 처리 · 유찰/재공고 지원",
"채점 엔진: 가격 + 실적 + 평가점수 가중 합산, BOQ 기반 견적 검증",
"전시업체(주최자·참가업체) 포털과 공사업체(agency) 포털 양면 구현",
]),
("content", "Ⅱ-3. 기술 부문", "M8. 반입/반출 물류 / M9. 정산·결제", [
"M8 물류 슬롯:",
(1, "반입·반출 차량 슬롯 예약 + 게이트 배정 — 현장 혼잡 분산"),
(1, "행사 일정 연동 슬롯 캘린더, 현장 QR 확인"),
"M9 정산·결제:",
(1, "홀 사용료·유틸리티·부대서비스 통합 정산(행사 스코프 폐루프)"),
(1, "PG 연동 온라인 결제(SIR-001) · 취소/부분환불 · 세금계산서 연계"),
(1, "수수료·환불 정책 룰셋 관리(관리자 설정형)"),
]),
("content", "Ⅱ-3. 기술 부문", "M10. 관람객 등록·티켓·배지·리드캡처", [
"사전등록 → 티켓 발급 → QR 배지 → 현장 체크인 원스톱(간편가입·게스트 지원)",
"참가업체 리드 캡처: QR 스캔·명함 → 리드 목록·등급·메모 → 사후 팔로업",
"AI 관람 도우미: 행사·부스 추천, 연월 브리핑(크롤 적재 DB 근거 응답)",
"현장 체크인 대시보드(운영자): 시간대별 입장 현황·혼잡 알림",
"B2C 모바일 앱 트랙과 공유(스토어 공개·게스트 모드)",
]),
("content", "Ⅱ-3. 기술 부문", "M11. 비즈니스 매칭 / M13. Wayfinding", [
"M11 비즈매칭:",
(1, "참가업체-바이어 프로필 기반 AI 추천(관심 카테고리·행동 데이터)"),
(1, "상담 일정 예약·미팅 테이블 배정·사후 평가"),
"M13 wayfinding:",
(1, "홀 도면(M2 실측 데이터 재사용) 기반 부스 검색·경로 안내"),
(1, "모바일 웹 우선 — 앱 설치 없이 QR 진입"),
(1, "행사장 시설(화장실·출입구·부대시설) POI 안내"),
]),
("content", "Ⅱ-3. 기술 부문", "M12. 공개 홍보 사이트 / M17. CMS", [
"M12 공개 사이트(일반 대중):",
(1, "행사 일정·상세·포스터 안내, 코엑스 수준 비주얼(시네마틱 히어로·모션)"),
(1, "반응형·SEO·다국어(4개국어), 접근성(prefers-reduced-motion·CLS 0)"),
(1, "EDM 발송·구독 관리·수신거부(마케팅)"),
"M17 CMS(헤드리스):",
(1, "전시 콘텐츠·공지·배너·프로모션 관리, 예약 발행(스케줄 퍼블리시)"),
(1, "참가업체 마이크로사이트 셀프 관리 · 사이니지 연계 콘텐츠"),
]),
("content", "Ⅱ-3. 기술 부문", "M14. 현장운영 (혼잡·안전·주차·에너지)", [
"현장 통합 대시보드: 시간대별 입장·혼잡 히트맵(체크인 데이터 연동)",
"안전: 사건·사고 보고, 안전 점검 체크리스트(모바일 현장 입력)",
"주차: 주차장 현황·만차 안내 연계",
"에너지: 홀별 전력 사용 모니터링(유틸리티 신청 데이터 대사)",
"운영자(ops) 전용 화면 — 현장 이슈의 단일 상황판",
]),
("content", "Ⅱ-3. 기술 부문", "M16. 경영분석 BI (P2→P1 승격)", [
"경영 KPI 대시보드: 매출·홀 가동률·참가사 리텐션·행사 P&L",
"운영사(킨텍스) 관점 수익성/ROI: 행사별 원가·수익 구조 분석",
"수요예측: 시즌·산업군별 홀 수요 예측(과거 데이터 학습) → 영업 전략 지원",
"부스 트래픽·체류·히트맵, 리드/ROI 분석(참가업체 제공 리포트)",
"구현: 집계는 SQL(뷰·M-View·배치) — AI 호출 아닌 데이터마트 기반(COR-003 정합)",
]),
("content", "Ⅱ-3. 기술 부문", "M18. 관리자 백오피스 + 시스템관리 레이어", [
"관리자 대시보드: 행사·매출·시스템 현황 통계, 실시간 모니터링",
"룰셋 관리: 규정(통로폭·소방·높이)·요율(홀 단가·성수기) 설정형 관리 — 코드 수정 없이 정책 변경",
"시스템관리(WISE 표준 이식): 사용자·역할/권한(RBAC)·메뉴·공통코드·감사로그·시스템설정",
"마스터데이터: 홀·등록업체·프로그램 관리",
"테넌트 관리(플랫폼 관리자): 전시관 온보딩·브랜딩·격리 상태 점검",
]),
("content", "Ⅱ-3. 기술 부문", "공통 업무기능 레이어 (§5B — WISE 표준 이식)", [
"발주기관 표준 프레임워크(WISE/UIWS)의 검증된 공통기능을 이식 — 재개발 리스크 제거",
(1, "업무일지·일정(캘린더)·쪽지·공지·의견수렴·통합검색"),
(1, "회의·보고서·통계·알림(웹 푸시)·감사 추적"),
"전 역할 공용 — 트랙과 무관하게 로그인 사용자 공통 제공",
"UI 컨벤션도 WISE 정렬: 셸(햄버거·아코디언 메뉴)·캘린더·차트·테이블·폼 표준",
"이식 원칙: 정본 구조 유지, 킨텍스 토큰(kx) 테마만 교체",
]),
("content", "Ⅱ-4. 기술 부문", "인증·보안 아키텍처", [
"인증: JWT + 2차인증(OTP) — WISE 표준 인증 체계 이식(SER-001)",
"인가: 행사 단위 RBAC + 테넌트 격리 + 역할별 메뉴·API 이중 게이트",
"개인정보(SER-002): 저장·전송 암호화, 마스킹, 접속기록 보관, 취급 최소화",
"시큐어코딩(SER-003): 개발보안 가이드 준수, 보안약점 진단 도구 CI 편입",
"모바일 보안: 루트/탈옥 탐지·무결성 검증·화면캡처 방지·cleartext 금지",
"시크릿 관리: 환경변수 주입·fail-fast 검증, 키 마스킹·저장소 미커밋 원칙",
]),
("content", "Ⅱ-4. 기술 부문", "AI 아키텍처 — 사용성 표준 & 토큰 최소화 (§8A)", [
'AI 사용성 표준: "어디서나 한 번에 물어본다"',
(1, "전 화면 인라인 진입점·예시 질문 칩·원클릭 액션·다음 명령 제시"),
(1, "구조화 카드 + 근거 인용 응답·대화 히스토리·다국어(모바일 음성)"),
"토큰 최소화 6원칙(COR-003 정합):",
(1, "결정로직 우선 라우팅(LLM 미호출) · 소형모델 우선 · RAG 발췌로 프롬프트 축소"),
(1, "캐싱 · 출력 상한/구조화 · 집계는 SQL — AI는 해석만"),
"모델 전환 설정형: Claude 기본 + AiTextRouter로 대체 모델 폴백, 사용량 측정지표 대시보드",
]),
("content", "Ⅱ-4. 기술 부문", "데이터 아키텍처 — 공간데이터·마스터데이터", [
"공간 데이터(DAR-001): 부스 폴리곤(Polygon)·트렌치 포인트(Point)·배선(LineString) — PostGIS ST_* 연산",
"마스터 데이터(DAR-002): 홀(실측 15개)·요율·규정 룰셋·공통코드·등록업체 — 테넌트 소유",
"데이터 표준(DAR-003): 명명 규칙·FK 최소화·공통코드 체계·이력(감사) 관리",
"집계 체계: 뷰·Materialized View·배치 집계 — BI·통계의 성능 기반",
"마이그레이션: Flyway 버전 관리, 배포 전 라이브 dry-run(BEGIN…ROLLBACK) 검증 절차",
]),
("content", "Ⅱ-4. 기술 부문", "외부 연동 (SIR)", [
"PG 결제(SIR-001): 신용카드·계좌이체, 취소·부분환불, 정산 대사",
"SSO·HR(SIR-002): 킨텍스 Open SSO 연동 + 인사 조직·직원 정보 동기화(내부 사용자 프로비저닝)",
"CAD(SIR-003): DWG 입력 파이프라인 — 좌표 추출·캘리브레이션·JPG 렌더(CI_AI·CI_JPG 자동화)",
"이미지 생성 API: Gemini 계열(나노바나나 워커 경유 단일 창구)",
"확장 대비: 웹훅(인바운드/아웃바운드·서명 검증) 표준 창구 제공",
]),
("content", "Ⅱ-4. 기술 부문", "모바일 앱 (B2B 운영 · B2C 관람객)", [
"단일 코드베이스(React Native/Expo) + 배포 타깃 2:",
(1, "① 운영 B2B: 2FA 필수, 사내 QR 배포 — 현장 체크리스트·검수·승인·시각화 갤러리"),
(1, "② 관람객 B2C: 스토어 공개, 간편가입·게스트 — 티켓·배지·wayfinding·AI 도우미"),
"계정은 단일 통합, 가입 트랙만 분리(하이브리드 채택)",
"오프라인 대응·푸시 알림·다국어(i18n)·생체인증(내정보)",
"웹과 랜딩·메뉴 패리티(역할별 결정 규칙 공유)",
]),
("content", "Ⅱ-4. 기술 부문", "성능·품질 목표 (NFR)", [
"응답시간(PER-001): 일반 조회 3초 이내 · 자동 배치 30초 이내(3안) · AI 이미지는 비동기+완료 푸시",
"동시사용자(PER-002): 평시 500 / 피크 3,000 동시접속 — 부하테스트로 검증",
"가용성(PER-003): 99.5% 이상, 계획 정지 야간 수행",
"품질(QUR): 단계별 품질 게이트·산출물 표준·경계면 정합 QA(API shape ↔ 프론트 타입 교차 검증)",
"테스트(TER): 단위·통합·성능·보안 + UAT 시나리오 지원, 결함 관리 체계",
"성능 설계 선반영: 인덱스 전략·집계 뷰·이미지 CDN 캐싱·빌드 번들 최적화",
]),
("section", "PART Ⅲ", "사업관리 부문", "추진전략·방법론 · 조직·인력 · 일정 · 위험 · 품질"),
("content", "Ⅲ-1. 사업관리", "추진 전략 및 방법론", [
"P0 코어 우선 전략: M2→M3→M4→M5를 최우선 구축, 3개월 차 조기 가시화(경영진 시연)",
"애자일 스프린트(2주) + 단계별 산출물 검토 병행(PMR-002) — 공공 검수 체계와 양립",
"모듈별 완성 직후 점진 QA(incremental QA) — 전체 완성 후 일괄 검증의 리스크 제거",
"발주기관 협업: 주간 진척 보고 + 격주 시연(동작 소프트웨어 기준) + 월간 운영위원회",
"선행 게이트 관리: AI API 키·개발 서버·CI/CD 등 전제조건을 착수 2주 내 확정",
]),
("content", "Ⅲ-2. 사업관리", "수행 조직 및 투입 인력", [
"총 19명 — PM 1 / 아키텍트 3(AA·TA·DA) / 백엔드 4 / 프론트 4 / AI 2 / DB 1 / QA 2 / 모바일 2",
"거버넌스: PM(총괄) — 개발PM(트랙 조율) — PMO(표준·산출물·품질 게이트)",
"아키텍트 전담: 모듈 경계·API 표준(AA) / 기술표준·성능(TA) / 데이터 모델·표준(DA)",
"핵심 인력(PM·AA·AI 리드) 교체 제한 — 발주기관 사전 승인(PMR-004)",
"전 인력 보안서약·개인정보 교육 이수 후 투입",
]),
("content", "Ⅲ-3. 사업관리", "추진 일정 (12개월)", [
"M1~M3 [분석·설계]: 요구사항 상세화·아키텍처 확정·데이터 표준·ERD·화면 설계(디자인 시스템)",
"M3~M7 [구축 1차 — P0 코어]: M2 배치·M3 설계·M4 배선·M5 시각화 + 공통/시스템관리·인증(2FA)",
"M6~M10 [구축 2차 — 도메인]: M1·M6~M18 + 모바일 앱 + 공개사이트 (일부 병행)",
"M10~M12 [통합·이행]: 통합·성능·보안 테스트, 데이터 이관, UAT, 교육, 오픈",
"오픈 후 2개월 [안정화]: 상주 지원·하자 대응·운영 이관",
"중간 마일스톤: M3 설계 완료(1차 검수) · M7 P0 시연 · M10 기능 완료 · M12 최종 검수",
]),
("content", "Ⅲ-4. 사업관리", "마일스톤·산출물 관리", [
"단계별 산출물: 요구사항정의서·아키텍처설계서·ERD/데이터표준·화면설계서·테스트계획/결과서·운영매뉴얼",
"산출물 형상관리: Git 저장소 단일 출처, 문서-코드 버전 동기화",
"품질 게이트: 각 마일스톤 검수 전 자체 QA 통과 조건(빌드·경계면 정합·보안 점검)",
"요구사항 추적: 요구사항 대응표(RFP 50건) ↔ 설계 ↔ 구현 ↔ 테스트 전 구간 추적성 유지",
"주간 보고(진척·이슈) + 월간 보고(마일스톤·리스크·품질 지표)",
]),
("content", "Ⅲ-5. 사업관리", "위험 관리 방안", [
"R1 AI 산출물 신뢰: 워터마크·라벨 강제 + 인간 승인 절차 — 설계 단계 반영 완료",
"R2 규정 검증 책임: AI는 플래깅까지, 최종 판정은 킨텍스 구조기술팀 — 역할 경계 명문화",
"R3 AI 비용 초과: 토큰 최소화 6원칙 + 사용량 대시보드 + 월 상한 알림",
"R4 실측 데이터 정합: CAD 실측 좌표 검증 절차(캘리브레이션 리포트) 운영",
"R5 일정 지연: P0 우선·병행 트랙 조정 여력·격주 시연으로 조기 감지",
"공통: 위험 등록부 상시 운영, 발생 시 영향·대안 분석 후 운영위 보고",
]),
("content", "Ⅲ-6. 사업관리", "품질보증·형상/변경관리", [
"품질보증(QUR-001): 품질 계획 수립 → 단계별 게이트 → 지표 관리(결함 밀도·해결률)",
"경계면 QA 특화: 백엔드 API 응답 ↔ 프론트 타입/훅 shape 교차 검증(통합 결함 사전 차단)",
"표준 준수(QUR-002): 개발표준·DB 표준·UI 디자인 시스템(design.md 단일 출처) 준수 점검",
"형상관리(PMR-003): Git 브랜치 전략, 코드리뷰 필수, 파일단위 커밋 원칙",
"변경관리: 변경요청(CR) 절차 — 영향 분석 → 승인 → 반영 → 추적, 무단 범위 변경 차단",
]),
("section", "PART Ⅳ", "기술지원 부문", "교육·기술이전 · 유지보수 · 비상대응 · 기대효과"),
("content", "Ⅳ-1. 기술지원", "교육훈련 및 기술이전", [
"교육 3트랙(PSR-001): 시스템 관리자 / 운영자(킨텍스 실무) / 사용자(주최자·참가업체 안내)",
"교육 자료: 운영 매뉴얼·사용자 가이드·동영상 튜토리얼 제공",
"기술이전: 소스코드·설계문서·운영 절차 일체 + 개발환경 구성 가이드 인계",
"AI 파이프라인 특별 이전: 프롬프트 아키텍처·파라미터·비용 운영 노하우 문서화",
"운영 이관 리허설: 안정화 기간 중 킨텍스 운영조직 주도 운영 1개월 병행",
]),
("content", "Ⅳ-2. 기술지원", "유지보수·하자보수 체계", [
"무상 하자보수 12개월(PSR-002): 검수 완료일 기산",
"하자 등급별 SLA: 긴급(서비스 중단) 4시간 내 착수 / 중요 1영업일 / 일반 2영업일",
"안정화 상주 지원(PSR-003): 오픈 후 2개월 — 현장 대응·성능 튜닝·데이터 보정",
"원격 지원 체계: 이슈 트래킹 시스템·핫라인 운영",
"유상 유지보수 전환 옵션: 하자보수 종료 후 연간 유지보수 계약 제안(범위·요율 별도 협의)",
]),
("content", "Ⅳ-3. 기술지원", "비상대응·보안 준수", [
"장애 대응: 모니터링(헬스체크·알림) → 자동 감지 → 에스컬레이션 절차",
"백업·복구: DB 일일 백업 + 오브젝트 스토리지 이중화, 복구 목표(RTO 4시간/RPO 24시간)",
"배포 안전: 헬스 게이트 통과 후 전환, 마이그레이션 dry-run 검증, 롤백 절차 표준화",
"보안 준수: 인력 보안서약·자료 반출 금지·종료 시 파기 확인(계약 특수조건 이행)",
"개인정보 사고 대응: 유출 시 즉시 보고·차단·소명 절차 사전 수립",
]),
("content", "Ⅳ-4. 기술지원", "맺음말 — 기대효과와 약속", [
"정량 효과: 견적 회신 수일→즉시 · 배치안 수주→30초 · 규정 검토 자동화 · 유틸리티 신청 원클릭",
"정성 효과: 시공 전 '사진 수준' 의사결정 → 주최자·참가업체 만족도, 킨텍스 서비스 차별화",
"경영 효과: 전 과정 데이터 축적 → BI 기반 영업·수익성 분석, 제3전시장 확장 대응",
"확장 효과: 멀티테넌트 SaaS — 타 전시관 온보딩으로 신규 수익 모델",
"약속: 요구사항 50건 100% 수용, 12개월 내 완수, 무상 하자보수 12개월 + 안정화 2개월",
"감사합니다.",
]),
]
def build_pptx(path):
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
total = len(SLIDES)
for i, spec in enumerate(SLIDES, start=1):
kind = spec[0]
if kind == "cover":
slide_cover(prs, i, total)
elif kind == "section":
slide_section(prs, i, total, spec[1], spec[2], spec[3])
else:
slide_content(prs, i, total, spec[1], spec[2], spec[3])
prs.save(path)
return total
if __name__ == "__main__":
docx_path = os.path.join(BASE, "RFP.docx")
pptx_path = os.path.join(BASE, "제안발표.pptx")
build_docx(docx_path)
n = build_pptx(pptx_path)
print("DOCX OK:", docx_path)
print("PPTX OK:", pptx_path, "slides =", n)