Files
sam-docs/sam/docs/guides/pptx-generation-guide.md
김보곤 00d7a583cb docs: [guides] HTML → PPTX 변환 도구 사용법 가이드 추가
- 슬라이드 작성법, 변환 스크립트 구조, 실행 방법 포함
- 기존 사용 사례, 문제 해결, 빠른 시작 가이드 포함
2026-03-01 13:02:43 +09:00

11 KiB

HTML → PPTX 변환 도구 사용법

작성일: 2026-03-01 상태: 확정


1. 개요

HTML 슬라이드 파일을 PowerPoint(PPTX)로 변환하는 로컬 도구이다. Playwright(브라우저 렌더링) + PptxGenJS(PPTX 생성)를 조합하여, HTML/CSS로 디자인한 슬라이드를 그대로 PPTX로 출력한다.

1.1 구성 요소

~/.claude/skills/pptx-skill/scripts/
├── html2pptx.js          ← 핵심 변환 엔진 (HTML → PPTX)
└── node_modules/
    ├── pptxgenjs          ← PPTX 파일 생성 라이브러리
    ├── playwright          ← 브라우저 렌더링 (HTML 파싱)
    ├── sharp               ← 이미지 처리
    └── ...

1.2 사전 조건

항목 현재 설치 상태
Node.js v24.13.0 (~/.nvm/versions/node/)
html2pptx.js ~/.claude/skills/pptx-skill/scripts/html2pptx.js
pptxgenjs 위 scripts/node_modules 안에 설치됨
playwright 위 scripts/node_modules 안에 설치됨

별도 npm install이 필요 없다. 이미 모든 의존성이 설치되어 있다.


2. 작업 흐름

① HTML 슬라이드 작성 (slides/ 폴더)
    ↓
② 변환 스크립트 작성 (convert.cjs)
    ↓
③ 터미널에서 실행: node convert.cjs
    ↓
④ PPTX 파일 생성 완료

3. HTML 슬라이드 작성법

3.1 기본 템플릿

<!DOCTYPE html>
<html>
<head>
  <!-- 폰트: Pretendard (CDN) -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      /* ⚠️ 반드시 width/height를 pt 단위로 지정 */
      width: 720pt; height: 405pt;   /* 16:9 가로형 */
      font-family: 'Pretendard', sans-serif;
      background: #0F2439;
      padding: 32pt 40pt;
    }
  </style>
</head>
<body>
  <!-- 여기에 슬라이드 내용 작성 -->
  <h1 style="font-size: 24pt; color: #ffffff;">제목</h1>
  <p style="font-size: 12pt; color: rgba(255,255,255,0.6);">본문 내용</p>
</body>
</html>

3.2 슬라이드 크기 (body width/height)

용도 body 크기 변환 스크립트 layout
16:9 가로형 (발표용) width: 720pt; height: 405pt; width: 10, height: 5.625
9:16 세로형 (브로셔) width: 405pt; height: 720pt; width: 5.625, height: 10
4:3 가로형 (구형) width: 720pt; height: 540pt; width: 10, height: 7.5

중요: HTML의 body 크기와 변환 스크립트의 layout 크기가 일치해야 한다. 불일치 시 에러 발생.

3.3 필수 규칙

텍스트 줄바꿈 방지 (가장 중요)

브라우저와 PowerPoint의 폰트 렌더링 차이로, HTML에서 한 줄인 텍스트가 PPTX에서 두 줄로 넘어가는 문제가 발생한다.

<!-- ✅ 한 줄짜리 텍스트에는 반드시 white-space: nowrap -->
<p style="white-space: nowrap; font-size: 10pt;">이 텍스트는 한 줄입니다</p>

<!-- ❌ nowrap 없으면 PPTX에서 줄바꿈될 수 있음 -->
<p style="font-size: 10pt;">이 텍스트는 한 줄입니다</p>

<!-- ✅ 의도적 멀티라인은 nowrap 불필요 -->
<p style="font-size: 10pt; line-height: 1.6;">
  여러 줄로 의도된 텍스트입니다.<br>
  이 경우 nowrap을 넣지 않는다.
</p>

적용 대상

  • 뱃지 텍스트 (01, UC-01 등)
  • 카드 제목, 태그, 짧은 라벨
  • 푸터 텍스트
  • 단일행 <p> 태그 전부

이미지 경로

<!-- ✅ 절대 경로 사용 -->
<img src="/home/aweso/sam/docs/assets/bi/sam_bi_white.png" style="height: 24pt;">

<!-- ❌ 상대 경로는 동작하지 않을 수 있음 -->
<img src="../../assets/bi/sam_bi_white.png">

스타일 작성

<!-- ✅ 인라인 스타일 사용 (가장 안정적) -->
<div style="background: #2E86AB; padding: 8pt; border-radius: 6pt;">

<!-- ⚠️ <style> 태그의 클래스도 사용 가능하지만, 인라인이 더 안정적 -->

3.4 사용 가능한 CSS 속성

속성 지원 비고
background (색상) 단색, rgba 모두 지원
background (그라데이션) linear-gradient 지원
border 색상, 두께, radius
border-radius px, pt 단위
font-size, font-weight pt 단위 권장
color hex, rgba
padding, margin pt 단위 권장
display: flex gap, align-items 등
white-space: nowrap 줄바꿈 방지 (필수)
opacity
box-shadow ⚠️ 부분 지원
transform 미지원
animation 미지원

4. 변환 스크립트 작성법

4.1 기본 구조 (복사해서 사용)

const path = require('path');

// ① 패키지 경로 설정 (이 두 줄은 항상 동일)
module.paths.unshift(
  path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')
);
const PptxGenJS = require('pptxgenjs');
const html2pptx = require(
  path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')
);

async function main() {
    const pres = new PptxGenJS();

    // ② 레이아웃 설정 (HTML body 크기와 일치해야 함)
    pres.defineLayout({ name: 'CUSTOM', width: 10, height: 5.625 });
    pres.layout = 'CUSTOM';

    // ③ HTML 파일 변환
    await html2pptx('/절대경로/slides/slide-01.html', pres);

    // ④ PPTX 출력
    await pres.writeFile({ fileName: '/절대경로/output.pptx' });
    console.log('완료!');
}

main().catch(console.error);

4.2 실전 예시: 여러 슬라이드 변환

const path = require('path');
module.paths.unshift(
  path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules')
);
const PptxGenJS = require('pptxgenjs');
const html2pptx = require(
  path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js')
);

async function main() {
    const pres = new PptxGenJS();

    // 16:9 가로형
    pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 });
    pres.layout = 'CUSTOM_16x9';

    const slidesDir = path.join(__dirname, 'slides');

    // 변환할 HTML 파일 목록
    const slides = [
        'slide-01.html',
        'slide-02.html',
        'slide-03.html',
    ];

    for (const file of slides) {
        console.log(`Converting ${file} ...`);
        try {
            await html2pptx(path.join(slidesDir, file), pres);
        } catch (err) {
            console.error(`Error: ${err.message}`);
        }
    }

    const outputPath = path.join(__dirname, 'my-presentation.pptx');
    await pres.writeFile({ fileName: outputPath });
    console.log(`\nPPTX created: ${outputPath}`);
}

main().catch(console.error);

4.3 실전 예시: 번호 기반 자동 변환 (18슬라이드)

// slide-01.html ~ slide-18.html 자동 변환
const totalSlides = 18;
for (let i = 1; i <= totalSlides; i++) {
    const num = String(i).padStart(2, '0');
    const htmlFile = path.join(slidesDir, `slide-${num}.html`);
    await html2pptx(htmlFile, pres);
}

5. 실행 방법

5.1 터미널에서 직접 실행

# 해당 폴더로 이동 후 실행
cd /home/aweso/sam/docs/brochure
node convert-2page.cjs

# 또는 절대 경로로 실행
node /home/aweso/sam/docs/brochure/convert-2page.cjs

5.2 실행 결과

Converting brochure-2page-front.html ...
Converting brochure-2page-back.html ...

PPTX created: /home/aweso/sam/docs/brochure/sam-brochure-2page.pptx

에러가 나면 HTML body 크기와 layout 설정 불일치가 가장 흔한 원인이다.


6. 프로젝트 내 기존 사용 사례

경로 슬라이드 수 레이아웃 용도
docs/usecase/ 18장 16:9 가로 방화셔터 제안서
docs/usecase/brochure/ 1장 / 2장 9:16 세로 방화셔터 브로셔
docs/brochure/ 1장 / 2장 9:16 세로 SAM 범용 브로셔
docs/plans/slides/ N장 16:9 가로 배포 계획 발표
docs/rules/slides/ N장 16:9 가로 정책 규칙 문서

7. 폴더 구조 권장 패턴

새 PPTX를 만들 때 아래 구조를 따른다:

docs/my-document/
├── slides/                    ← HTML 슬라이드 파일들
│   ├── slide-01.html
│   ├── slide-02.html
│   └── slide-03.html
├── convert.cjs                ← 변환 스크립트
└── my-document.pptx           ← 생성된 PPTX (node convert.cjs 실행 후)

8. 문제 해결

증상 원인 해결
Error: dimensions don't match HTML body 크기 ≠ layout 설정 body의 width/height와 defineLayout 값 맞추기
텍스트가 PPTX에서 줄바꿈됨 white-space: nowrap 미적용 단일행 <p> 태그에 nowrap 추가
이미지 안 보임 상대 경로 사용 절대 경로(/home/aweso/...)로 변경
Cannot find module 'pptxgenjs' module.paths 설정 누락 스크립트 상단 2줄(module.paths.unshift) 확인
Cannot find module 'playwright' Playwright 미설치 cd ~/.claude/skills/pptx-skill/scripts && npx playwright install chromium
PPTX는 생성되지만 빈 슬라이드 HTML 내용 없음 HTML 파일을 브라우저로 열어 확인

9. 빠른 시작 (3분 가이드)

Step 1: 폴더 만들기

mkdir -p /home/aweso/sam/docs/my-pptx/slides

Step 2: HTML 슬라이드 만들기

slides/slide-01.html 파일 생성:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      width: 720pt; height: 405pt;
      font-family: 'Pretendard', sans-serif;
      background: #0F2439;
      padding: 60pt 80pt;
      display: flex; flex-direction: column;
      justify-content: center;
    }
  </style>
</head>
<body>
  <p style="white-space: nowrap; font-size: 10pt; color: #10B981; margin-bottom: 12pt;">MY COMPANY</p>
  <h1 style="font-size: 36pt; font-weight: 800; color: #ffffff;">발표 제목을 여기에</h1>
  <p style="font-size: 14pt; color: rgba(255,255,255,0.5); margin-top: 16pt;">부제목 또는 설명</p>
</body>
</html>

Step 3: 변환 스크립트 만들기

convert.cjs 파일 생성:

const path = require('path');
module.paths.unshift(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/node_modules'));
const PptxGenJS = require('pptxgenjs');
const html2pptx = require(path.join(require('os').homedir(), '.claude/skills/pptx-skill/scripts/html2pptx.js'));

async function main() {
    const pres = new PptxGenJS();
    pres.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 });
    pres.layout = 'CUSTOM_16x9';

    await html2pptx(path.join(__dirname, 'slides', 'slide-01.html'), pres);

    await pres.writeFile({ fileName: path.join(__dirname, 'my-presentation.pptx') });
    console.log('완료!');
}
main().catch(console.error);

Step 4: 실행

cd /home/aweso/sam/docs/my-pptx
node convert.cjs
# → my-presentation.pptx 생성됨

최종 업데이트: 2026-03-01