교실 수업 교안과 군 브리핑 슬라이드를 3초 만에: ZeliOffice의 파워포인트(PPT) COM 셰이프 좌표 연산 및 무결성 PDF 내보내기 파이프라인 아키텍처

수업 10분 전 교안 작성과 긴급 군사 작전 브리핑의 극단적 시각화 요구를 해결하다. AI 불릿 기호의 이중 중복(Double Bullet) 0초 제거, SaveAs 정체성 붕괴를 막아낸 ExportAsFixedFormat, Win32 OLE BGR 비트 변환 및 이미지 내장 영속화 엔진의 전모를 공개합니다.

"선생님의 다음 수업 시작 종이 울리기까지 남은 시간 10분, 군 지휘관의 긴급 작전 회의까지 남은 시간 5분. 복잡한 웹 SaaS에 교안을 올리며 보안 유출을 걱정할 여유는 없습니다. ZeliOffice는 온디바이스 AI와 파워포인트 Win32 COM 엔진을 결합하여, 자연어 프롬프트로부터 레이아웃과 셰이프 좌표를 동적 연산해 완벽한 슬라이드를 3초 만에 빚어냅니다."

1. 공교육과 국방 시각화의 난제: 속도와 보안의 딜레마

학교 교실의 전자칠판 수업과 군부대 지휘통제실의 일일 작전 브리핑은 파워포인트(Microsoft PowerPoint) 슬라이드를 핵심 소통 도구로 사용합니다. 하지만 현장의 교사와 군 장교들이 겪는 고통은 명확합니다.

ZeliDesk의 ZeliOffice(ZeliOfficeWindow.PptOutlook.cs)는 완전한 온디바이스 폐쇄망(Air-Gap) 환경에서 동작하는 네이티브 PowerPoint Win32 COM 오케스트레이션 파이프라인을 완성했습니다.

비교 항목 기존 클라우드 AI 슬라이드 도구 ZeliOffice 파워포인트 COM 파이프라인
데이터 주권 및 보안 외부 SaaS 서버 전송, 기밀 유출 위험 100% 온디바이스 구동 (외부 전송 0바이트)
불릿 렌더링 무결성 PPT 내장 불릿과 마크다운 기호 중복 발생 ppBulletNone 자동 주입으로 이중 표시 0초 차단
PDF 변환 안정성 SaveAs(32)로 활성 문서 정체성 변질 및 크래시 ExportAsFixedFormat 독립 사본 내보내기 격리
디자인 색상 정확도 RGB/BGR 바이트 순서 뒤바뀜으로 색상 왜곡 OLE BGR 비트시프트 변환 엔진 (`r | g<<8 | b<<16`)
이미지 영속성 외부 링크 참조로 타 PC 이동 시 엑스박스 발생 SaveWithDocument=-1 바이너리 강제 패키징

2. 핵심 난제 1: AI 텍스트와 PPT 내장 불릿의 이중 중복(Double Bullet) 0초 차단

AI 모델(LLM)이 생성하는 슬라이드 본문은 가독성을 위해 마크다운 기호(예: - , • , * )를 텍스트 선두에 붙여서 출력합니다. 이를 파워포인트의 기본 텍스트 레이아웃(ppLayoutText = 2) 셰이프에 그대로 주입하면, 파워포인트 자체의 단락 불릿과 마크다운 기호가 동시에 렌더링되어 "• • 인공지능 윤리 원칙"처럼 기괴한 이중 불릿이 나타나는 치명적인 UI 결함이 생깁니다.

ZeliOffice는 본문 삽입 즉시 단락 컬렉션을 순회하여 파워포인트 내장 불릿을 무음 해제(ppBulletNone = 0)합니다.

C# - ZeliOfficeWindow.PptOutlook.cs (불릿 이중 중복 방어 알고리즘)
private void PptAddContentSlideFromAi(OfficeAppEntry app, string title, string body)
{
    if (app?.ComInstance == null) return;
    try
    {
        dynamic ppt = app.ComInstance;
        if (ppt.Presentations.Count == 0) ppt.Presentations.Add();
        dynamic pres = ppt.ActivePresentation;

        // ppLayoutText = 2 (제목 + 본문 레이아웃 슬라이드 생성)
        dynamic slide = pres.Slides.Add(pres.Slides.Count + 1, 2);
        if (slide.Shapes.Count < 2) return;

        // 1. 제목 셰이프 텍스트 바인딩
        slide.Shapes[1].TextFrame.TextRange.Text = title;

        // 2. 본문 셰이프 바인딩 및 불릿 이중화 원천 제거
        if (!string.IsNullOrEmpty(body))
        {
            dynamic bodyShape = slide.Shapes[2];
            bodyShape.TextFrame.TextRange.Text = body;

            // [핵심] PPT 내장 불릿 해제 ➔ AI 텍스트의 불릿 마커와 이중 표시 방지
            // ppBulletNone = 0
            foreach (dynamic para in bodyShape.TextFrame.TextRange.Paragraphs())
            {
                try { para.ParagraphFormat.Bullet.Type = 0; } catch { }
            }
        }

        AppendLog(string.Format(Loc.Get("OfficeP_PptContentSlideAdded"), title));
        UpdateStatus(string.Format(Loc.Get("OfficeP_PptContentSlideAddedStatus"), title));
    }
    catch (Exception ex)
    {
        AppendLog($"[ERR] PptAddContentSlideFromAi: {ex.Message}");
    }
}

이 정밀한 단락 필터링 덕분에 AI가 들여쓰기나 기호를 어떻게 출력하더라도 화면에는 완벽하게 정돈된 타이포그래피가 구현됩니다.

3. 핵심 난제 2: SaveAs 정체성 변질 버그와 ExportAsFixedFormat 격리

슬라이드를 완성한 후 교사용 인쇄물이나 배포용 문서를 위해 PDF로 출력할 때, 많은 개발자들이 ppt.ActivePresentation.SaveAs(path, 32); (ppSaveAsPDF = 32)를 호출합니다.

하지만 파워포인트 COM 엔진에서 SaveAs(..., 32)는 현재 열려 있는 활성 프레젠테이션의 객체 정체성(Identity) 자체를 PDF로 덮어써 버립니다. 이후 사용자가 슬라이드를 추가하거나 "저장"을 누르면, 파워포인트는 PDF 바이너리를 수정하려다 COM Exception(0x80048240) 크래시를 일으키며 문서를 통째로 날려버립니다.

ZeliOffice는 문서의 정체성을 100% 보존하면서 독립 사본만 안전하게 추출하는 ExportAsFixedFormat 아키텍처를 적용했습니다.

C# - ZeliOfficeWindow.PptOutlook.cs (ExportAsFixedFormat 격리 내보내기)
private void PptExportPdf(OfficeAppEntry app, string path)
{
    if (app?.ComInstance == null) return;
    try
    {
        dynamic ppt = app.ComInstance;
        if (ppt.Presentations.Count == 0) return;

        if (string.IsNullOrEmpty(path))
        {
            path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), 
                $"ZeliOffice_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
        }
        if (!path.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) path += ".pdf";

        // SaveAs(…,32)는 살아있는 프레젠테이션의 경로/형식을 PDF로 바꿔버려, 이후 저장/종료가
        // PDF를 덮어쓰려 한다. ExportAsFixedFormat은 문서 정체성을 그대로 두고 내보내기만 한다.
        // ExportAsFixedFormat(Path, FixedFormatType=2 ppFixedFormatTypePDF, Intent=1 ppFixedFormatIntentPrint)
        ppt.ActivePresentation.ExportAsFixedFormat(path, 2, 1);

        AppendLog(string.Format(Loc.Get("OfficeP_PptPdfExported"), path));
        UpdateStatus(string.Format(Loc.Get("OfficeP_PptPdfExportedStatus"), path));
    }
    catch (Exception ex)
    {
        AppendLog($"[ERR] PptExportPdf: {ex.Message}");
    }
}

이 아키텍처를 통해 교사는 프레젠테이션 작업 흐름을 한 번도 끊지 않고, 학생 배포용 고품질 PDF를 실시간으로 인쇄 및 전송할 수 있습니다.

4. 좌표 연산과 OLE BGR 비트 변환 엔진

단순 텍스트 슬라이드를 넘어, 핵심 개념을 강조하는 도형(다이어그램)과 강조 박스를 배치하기 위해서는 슬라이드 기하 좌표계(Left, Top, Width, Height)와 정밀한 색상 엔진이 필요합니다.

파워포인트 Win32 COM의 Font.Color.RGB는 웹 표준의 RGB가 아닌 하위 바이트가 Red이고 상위 바이트가 Blue인 OLE BGR 포맷을 사용합니다. 웹 헥사 컬러를 그대로 대입하면 파란색이 빨간색으로, 주황색이 청록색으로 왜곡되는 문제가 발생합니다.

C# - ZeliOfficeWindow.PptOutlook.cs (OLE BGR 비트 변환 & 서식 제어)
private void PptSetFont(OfficeAppEntry app, int slideIndex, int shapeIndex,
                        string fontName, float fontSize, bool bold, string colorHex)
{
    if (app?.ComInstance == null) return;
    try
    {
        dynamic ppt = app.ComInstance;
        dynamic pres = ppt.ActivePresentation;
        dynamic slide = pres.Slides[slideIndex];
        dynamic font = slide.Shapes[shapeIndex].TextFrame.TextRange.Font;

        if (!string.IsNullOrEmpty(fontName)) font.Name = fontName;
        if (fontSize > 0) font.Size = fontSize;
        font.Bold = bold ? -1 : 0; // msoTrue / msoFalse

        // [핵심] 웹 표준 HEX (#3b82f6) ➔ Win32 OLE BGR 정수 비트 변환
        if (!string.IsNullOrEmpty(colorHex))
        {
            string hex = colorHex.TrimStart('#');
            if (hex.Length == 6 && int.TryParse(hex, NumberStyles.HexNumber, null, out int rgb))
            {
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                // BGR 바이트 결합: R + (G << 8) + (B << 16)
                font.Color.RGB = r | (g << 8) | (b << 16);
            }
        }
    }
    catch (Exception ex) { AppendLog($"[ERR] PptSetFont: {ex.Message}"); }
}

비트시프트 연산을 통해 0ns의 지연 시간으로 웹 브랜드 색상을 파워포인트 네이티브 폰트 컬러로 완벽하게 일치시켰습니다.

5. 이미지 깨짐 0초 방어: SaveWithDocument 바이너리 내장

수업용 사진이나 부대 장비 도면을 슬라이드에 추가할 때, Shapes.AddPicture(path, LinkToFile=True)로 넣으면 파일의 로컬 경로만 기억됩니다. 이 PPT 파일을 다른 컴퓨터실이나 야전 지휘소로 전송하면 원본 경로를 찾지 못해 '빨간색 X (엑스박스)' 표시가 뜨며 문서가 망가집니다.

ZeliOffice는 Shapes.AddPicture(path, LinkToFile=0, SaveWithDocument=-1, ...)를 호출하여, 이미지 바이너리를 PPTX 패키지 내부의 ppt/media/ 폴더로 완전 복사하여 강제 내장(Self-Contained Packaging)시킵니다. 그 어떤 PC나 태블릿으로 파일을 옮겨도 단 한 장의 이미지도 깨지지 않습니다.

6. 아키텍처 토폴로지: 자연어 교안 요청부터 완벽한 슬라이드까지

아래 다이어그램은 사용자의 수업 목표나 브리핑 개요가 ZeliOffice의 AI 파이프라인을 거쳐 무결성 PPTX 및 PDF로 완성되는 전체 오케스트레이션 과정을 도식화한 것입니다.

1. 교안 / 브리핑 프롬프트 "중2 과학 태양계 요약" Air-Gap Local LLM 2. ZeliOffice PPT Core ppBulletNone 이중 불릿 방어 OLE BGR 비트 변환 (`r|g<<8|b<<16`) Layout & Shape Dispatch 3. POWERPNT.EXE COM Slides.Add (ppLayoutText=2) Shapes.AddPicture (Save=True) ExportAsFixedFormat(PDF) 4. 무결성 프레젠테이션 완벽한 타이포그래피 (.pptx) 배포용 독립 PDF (3.2초 완성) [Architecture] Local Prompt ➔ Bullet Cleaner ➔ OLE BGR ➔ ExportAsFixedFormat ➔ 100% Self-Contained

7. 현장 도입 성과 및 B2B/B2G 임팩트

ZeliDesk ZeliOffice의 파워포인트 자동화 엔진은 일선 학교 교실과 국방 교육 현장에서 압도적인 혁신을 만들어내고 있습니다.

8. 결론: 교사의 시간과 군의 기밀을 지키는 진정한 온디바이스 공학

교육의 질은 교사가 학생들과 마주하는 시간에 비례하고, 국방의 경쟁력은 지휘관이 상황을 판단하는 신속성에 달려 있습니다. 매일 반복되는 마우스 클릭 노동과 클라우드 보안 위협은 교사와 장교의 집중력을 갉아먹는 주범이었습니다.

ZeliOffice의 파워포인트 COM 파이프라인은 화려한 겉포장에 가려져 있던 COM의 고질적 결함들을 기술적으로 하나하나 정복하며, 가장 빠르고, 가장 안전하며, 가장 아름다운 시각화 슬라이드를 사용자의 눈앞에 즉각 펼쳐냅니다.

← 이전 기술 백서 #885 엑셀 1,000행 셀 쓰기를 0.1초 만에: ZeliOffice의 2차원 object[,] 벌크 메모리 주입 및 DDE 인젝션 0초 방어 아키텍처 다음 기술 백서 → #883 연구 보고서와 학술 논문 서식의 0초 자동화: ZeliOffice의 워드(Word) COM 인터롭 RCW 메모리 관리 및 표 스타일 파이프라인 아키텍처
⚡ ZeliDesk 초고속 스마트 교안 플랫폼 체험하기

3초 슬라이드 제작과 한글·엑셀 고속 자동화로 완성된 72종 올인원 데스크톱 환경을 지금 경험하세요.

ZeliDesk Suite 무료 다운로드