PPTX 생성, 편집 및 분석
.pptx 파일은 XML 파일의 ZIP 아카이브입니다. 작업에 따라 접근 방식을 선택하세요:
| 작업 | 접근 방식 |
|---|---|
| 새 덱 생성 | pptxgenjs 스크립트 작성 — 아래 주의사항 참조 |
| 기존 덱 편집 또는 템플릿 기반 생성 | 압축 해제 → ppt/slides/slideN.xml 편집 → 압축 |
| 읽기 | "markitdown deck.pptx" (각 슬라이드는 <!-- Slide number: N --> 마커로 구분); 시각적 그리드: "python scripts/thumbnail.py deck.pptx" |
스크립트
경로는 이 스킬 디렉토리를 기준으로 합니다. 그 외 모든 것은 일반 Python, node 또는 셸입니다.
| 스크립트 | 기능 |
|---|---|
scripts/thumbnail.py deck.pptx [prefix] | 템플릿 레이아웃 선택을 위한 각 슬라이드의 레이블이 지정된 그리드입니다. .pptx만 지원합니다. prefix를 전달할 수 있으며, 기본값은 thumbnails입니다. 같은 디렉토리에서 다른 덱의 그리드를 덮어씁니다. |
scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml] | 모든 패키지 부기(bookkeeping)를 포함하여 슬라이드(또는 slideLayoutN.xml)를 복제합니다. 또한 -o out.pptx 옵션을 사용하여 .pptx 파일을 직접 입력받을 수도 있습니다. |
scripts/clean.py unpacked/ | 더 이상 참조되지 않는 슬라이드, 미디어 및 관계(rels)를 삭제합니다. <p:sldIdLst>가 최종 상태가 된 후에 실행하세요. |
scripts/office/validate.py deck.pptx [--original src.pptx] | 스키마, 관계, 콘텐츠 유형, 차트 및 슬라이드 검사를 수행합니다. 각 실패는 수정 방법을 제시합니다. 템플릿에서 파생된 덱의 경우 --original을 전달하면 템플릿을 기준으로 스키마 검사를 수행하여 템플릿 자체의 XSD 오류가 사용자 오류로 표시되지 않도록 합니다. |
scripts/office/soffice.py --headless --convert-to pdf deck.pptx | LibreOffice 래퍼 — 일반 soffice는 이 샌드박스에서 중단됩니다. |
pptxgenjs로 생성하기 — 주의사항
pptxgenjs는 사전 설치되어 있습니다. npm install을 실행하지 말고, 스크립트를 작성하여 직접 require('pptxgenjs') 하세요. require가 실패하는 경우에만 npm install pptxgenjs를 실행하세요. 모델은 API를 알고 있습니다. 다음은 자주 실수하는 부분들입니다:
- 슬라이드를 추가하기 전에
pres.layout을 설정하세요. 기본 캔버스는LAYOUT_16x9= 10" × 5.625" 이며, 13.3" 너비가 아닙니다. 가장자리를 넘는 좌표는 기록되지만 클램핑되지 않습니다. 즉, 도형이 슬라이드에 존재하지 않게 됩니다. (LAYOUT_WIDE는 13.3" × 7.5"입니다.) - 16진수 색상: 절대
#를 사용하지 말고, 8자리를 사용하지 마세요.color: "FF0000"."#FF0000"및 16진수에 알파 값을 포함하는 것("00000020")은 파일을 손상시킵니다. 반투명도 사용 시: 채우기 및 이미지에는transparency: 0-100, 그림자에는opacity: 0.0-1.0을 사용하세요. 각 속성은 다른 속성에서 조용히 무시됩니다. - pptxgenjs는 옵션 객체를 제자리에서 변경합니다 (처음 사용 시 값을 EMU로 변환). 두 개 이상의
add*호출 간에 하나의shadow/옵션 객체를 공유하지 마세요. 매번 새 객체를 생성하세요. - 그림자
offset은 0 이상이어야 합니다. — 음수 오프셋은 파일을 손상시킵니다. 위쪽으로 그림자를 드리우려면 양수 오프셋과 함께angle: 270을 사용하세요. letterSpacing은 조용히 무시됩니다 — 실제 옵션은charSpacing입니다.- 목록: 각 항목에
bullet: true를 사용하고, 리터럴•는 절대 사용하지 마세요 (이중 글머리 기호가 렌더링됩니다). 마지막 항목을 제외한 모든 배열 항목에breakLine: true를 설정하세요. 글머리 기호 단락 간격은lineSpacing이 아닌paraSpaceAfter로 설정하세요 (큰 간격이 생깁니다). - 출력 파일당 하나의
new pptxgen()— 인스턴스를 재사용하지 마세요. rectRadius는ROUNDED_RECTANGLE에서만 작동하며,RECTANGLE에서는 작동하지 않습니다.- 그라데이션 채우기는 지원되지 않습니다 — 대신 그라데이션 이미지를 배경으로 사용하세요.
- 텍스트 상자에는 기본 내부 패딩이 내장되어 있습니다 — 텍스트가 같은 x 위치의 도형, 선 또는 아이콘과 정렬되어야 할 때마다
margin: 0을 설정하세요. - 발표자 노트는
slide.addNotes("...")에 넣습니다 (일반 텍스트, 슬라이드당 한 번). 슬라이드의 텍스트 상자에 넣지 마세요. - 차트는 네이티브로 유지하세요. PowerPoint에서 차트로 만들 수 있는 모든 것에는
addChart()를 사용하세요 (콤보 차트의 경우{type, data, options}배열 전달). 라이브러리가 노출하지 않는 PowerPoint 네이티브 기능(추세선, 오차 막대)의 경우, 추가 계열을 직접 계산하거나 생성된 OOXML을 후처리하세요. 렌더링된 이미지로 대체하지 마세요. PowerPoint에 네이티브 형식이 없는 차트 유형(예: Sankey, 네트워크, 코드 다이어그램)만 이미지로 넣으세요. - 기본 차트는 밋밋하게 렌더링됩니다 — 제목, 데이터 레이블, 구식 팔레트가 없습니다.
showTitle+title,showValue: true+dataLabelPosition, 팔레트의chartColors: [...]를 설정하고, 프레임을 정리하세요 (catAxisLabelColor/valAxisLabelColor,valGridLine: { color, size },catGridLine: { style: "none" }, 단일 계열의 경우showLegend: false). - 누적 막대 또는 열 차트에서
dataLabelPosition은ctr,inEnd또는inBase여야 합니다.outEnd는 파일을 손상시킵니다. secondaryValAxis/secondaryCatAxis를 사용하는 콤보 계열은 차트 옵션에valAxes와catAxes가 각각 두 개의 항목으로 필요합니다. 이것들이 없으면 pptxgenjs는 선언되지 않은 축 id를 작성하고, PowerPoint는 해당 차트를 버리고 파일이 손상되었다고 보고합니다.valAxes만 제공하는 것으로는 충분하지 않습니다.writeFile()후에python scripts/office/validate.py deck.pptx를 실행하세요. 위의 두 가지 차트 결함과 PowerPoint가 거부하는 슬라이드 XML 결함을 보고하고 각각의 수정 방법을 제시합니다. 생성기에서 수정하고, 압축된 XML을 수동으로 편집하지 마세요.<p:presentation>의 자식 순서를 절대 변경하지 마세요. pptxgenjs는<p:sldIdLst>바로 뒤에<p:notesMasterIdLst>를 작성하고 두 마스터를 하나의 테마 파트로 연결합니다. PowerPoint는 이를 정상적으로 읽습니다. 요소를 이동하면 같은 덱을 열 수 없게 됩니다.- 아이콘:
react-icons를 SVG로 렌더링하고(ReactDOMServer.renderToStaticMarkup),sharp으로 ≥256px에서 래스터화한 다음,addImage({ data: "image/png;base64," + buf.toString("base64") })를 통해 삽입하세요.image/png;base64,접두사는 필수입니다 (react-icons,react,react-dom,sharp은 사전 설치되어 있습니다. require가 실패하는 경우에만npm install react-icons react react-dom sharp실행).
기존 덱 및 템플릿 편집
먼저 레이아웃을 선택하세요: python scripts/thumbnail.py template.pptx template-thumbs는 각 슬라이드의 레이블이 지정된 그리드를 작성하고 생성된 파일을 출력합니다. template-thumbs.jpg이며, 슬라이드가 12개를 넘으면 template-thumbs-N.jpg로 분할됩니다. 항상 덱 이름을 따서 명명된 두 번째 인수를 전달하세요. 기본값은 thumbnails이므로, 한 디렉토리에서 두 덱의 썸네일을 생성하면 서로의 그리드가 조용히 덮어써집니다. 첫 번째 덱의 그리드는 그냥 사라집니다. (템플릿 분석 전용 — 시각적 QA는 이미지로 변환의 전체 해상도 렌더링이 필요합니다. .pptx만 허용하므로 먼저 .potx를 .pptx 이름으로 복사하세요). 이것을 markitdown과 함께 사용하여 각 콘텐츠 섹션을 템플릿 슬라이드에 매핑하고 레이아웃을 다양화하세요. 모든 섹션을 동일한 제목 및 글머리 기호 슬라이드에 넣지 마세요.
python3 -c "import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall('unpacked')" deck.pptx
python scripts/add_slide.py unpacked/ slide2.xml --after slide2.xml # 슬라이드(또는 slideLayoutN.xml) 복제; 새 슬라이드 경로 출력
# 슬라이드 재정렬 / 삭제 = ppt/presentation.xml에서 <p:sldIdLst> 편집
python scripts/clean.py unpacked/ # 삭제 후: 고아 슬라이드, 미디어, 관계 제거
# ppt/slides/slideN.xml에서 슬라이드 콘텐츠 편집
(cd unpacked && rm -f ../out.pptx && zip -Xr ../out.pptx .) # 디렉토리 내부에서 압축; 먼저 rm 하지 않으면 삭제된 부분이 남습니다
python scripts/office/validate.py out.pptx --original deck.pptx
- 슬라이드 콘텐츠를 편집하기 전에 모든 구조적 작업(추가, 삭제, 재정렬)을 수행하세요.
add_slide.py는 슬라이드 파일을 그대로 복사하므로, 편집 후 복제하면 편집된 콘텐츠가 복제됩니다. 그리고clean.py는 방금 작성한 슬라이드를 포함하여<p:sldIdLst>에 없는 모든 슬라이드를 삭제합니다. - 슬라이드 파일을 수동으로 복사하지 마세요.
add_slide.py는 새 슬라이드에 필요한 모든 등록을 수행하고 생성된 내용을 보고합니다(Created ppt/slides/slide17.xml from slide2.xml). 또한 파일에서 직접 작동합니다:add_slide.py deck.pptx slide2.xml -o out.pptx—-o를 전달하지 않으면 입력 덱을 제자리에서 덮어씁니다. 복제된 슬라이드는 여전히 원본의 차트/SmartArt/임베디드 객체 파트를 복제하는 것이 아니라 참조하므로, 한 슬라이드의 차트를 편집하면 다른 슬라이드도 변경됩니다. python-pptx를 사용하는 경우, 할 수 없는 세 가지: 슬라이드 복제(유일한 진입점은add_slide(layout)),text_frame.text = "..."를 통한 서식 유지(단락을 스타일이 없는 단일 run으로 축소합니다. 대신run.text를 할당하세요), 대부분의 템플릿 아트에서 사용하는 SVG/EMF 읽기(add_picture는UnidentifiedImageError를 발생시킵니다).- 레거시
.ppt는 먼저 변환해야 합니다:python scripts/office/soffice.py --headless --convert-to pptx file.ppt..potx템플릿은 동일하게 압축 해제 및 압축됩니다. 출력 파일에.potx확장자를 유지하세요. - 템플릿 아이콘 또는 이미지를 재사용하려면 이미 포함된 슬라이드 또는 레이아웃을 복제하세요.
템플릿을 채울 때:
- XML 변환을 스크립팅하는 경우
defusedxml.minidom으로 구문 분석하세요.xml.etree.ElementTree를 통해 OOXML을 왕복하면 네임스페이스 접두사가 다시 작성되어 덱이 손상됩니다. - 템플릿 슬롯 ≠ 소스 항목. 템플릿에 4명의 팀 구성원이 표시되고 실제로 3명이 있는 경우, 4번째 구성원의 전체 그룹(이미지 + 텍스트 상자)을 텍스트만 삭제하지 말고 삭제하세요. 그런 다음 QA에서 고아 시각 요소를 확인하세요.
- 목록 항목당 하나의
<a:p>— 항목을 단일 단락으로 연결하지 마세요. 형제<a:pPr>를 복사하여 간격을 유지하고, 제목, 섹션 헤더 및 인라인 레이블(Status:,Owner:)의<a:rPr>에b="1"을 설정하세요. - 글머리 기호가 레이아웃에서 상속되도록 두고, 재정의해야 하는 경우에만
<a:buChar>,<a:buAutoNum>(번호 매기기) 또는<a:buNone>을 추가하세요. 텍스트에 리터럴•를 절대 사용하지 마세요. - 앞이나 뒤에 공백이 있는 텍스트는
<a:t>에xml:space="preserve"가 필요합니다.
디자인 아이디어
지루한 슬라이드를 만들지 마세요. 흰색 배경에 기본 글머리 기호는 누구에게도 깊은 인상을 주지 못합니다. 각 슬라이드에 대해 이 목록의 아이디어를 고려하세요.
시작하기 전에
- 대담하고, 콘텐츠에 맞는 색상 팔레트를 선택하세요: 팔레트는 이 주제에 맞게 디자인된 느낌이어야 합니다. 색상을 완전히 다른 프레젠테이션에 적용해도 여전히 "잘 어울린다면" 충분히 구체적인 선택을 하지 않은 것입니다.
- 평등보다 우세: 하나의 색상이 지배적이어야 하며(시각적 비중의 60-70%), 1-2개의 보조 톤과 하나의 선명한 악센트가 있어야 합니다. 모든 색상에 동일한 비중을 절대 주지 마세요.
- 어두움/밝음 대비: 제목 및 결론 슬라이드에는 어두운 배경, 콘텐츠 슬라이드에는 밝은 배경("샌드위치" 구조). 또는 프리미엄 느낌을 위해 전체적으로 어두운 배경을 사용하세요.
- 시각적 모티프를 정하세요: 하나의 독특한 요소를 선택하고 반복하세요. 예: 둥근 이미지 프레임, 색상 원 안의 아이콘. 모든 슬라이드에 걸쳐 이를 유지하세요. 모티프로 컬러 바 또는 악센트 스트라이프를 사용하지 마세요 (회피 목록 참조).
색상 팔레트
주제에 맞는 색상을 선택하세요. 기본 파란색으로 되돌아가지 마세요. 다음 팔레트를 영감으로 사용하세요:
| 테마 | 기본 | 보조 | 악센트 |
|---|---|---|---|
| 미드나잇 임원 | 1E2761 (네이비) | CADCFC (아이스 블루) | FFFFFF (흰색) |
| 숲과 이끼 | 2C5F2D (포레스트) | 97BC62 (모스) | F5F5F5 (크림) |
| 코랄 에너지 | F96167 (코랄) | F9E795 (골드) | 2F3C7E (네이비) |
| 따뜻한 테라코타 | B85042 (테라코타) | E7E8D1 (샌드) | A7BEAE (세이지) |
| 오션 그라데이션 | 065A82 (딥 블루) | 1C7293 (틸) | 21295C (미드나잇) |
| 차콜 미니멀 | 36454F (차콜) | F2F2F2 (오프 화이트) | 212121 (블랙) |
| 틸 트러스트 | 028090 (틸) | 00A896 (시폼) | 02C39A (민트) |
| 베리 앤 크림 | 6D2E46 (베리) | A26769 (더스티 로즈) | ECE2D0 (크림) |
| 세이지 칼름 | 84B59F (세이지) | 69A297 (유칼립투스) | 50808E (슬레이트) |
| 체리 볼드 | 990011 (체리) | FCF6F5 (오프 화이트) | 2F3C7E (네이비) |
각 슬라이드에 대해
모든 슬라이드에는 시각적 요소(이미지, 차트, 아이콘 또는 도형)가 필요합니다. 텍스트만 있는 슬라이드는 기억에 남지 않습니다.
레이아웃 옵션:
- 두 열 (왼쪽 텍스트, 오른쪽 일러스트레이션)
- 아이콘 + 텍스트 행 (색상 원 안의 아이콘, 굵은 헤더, 아래 설명)
- 2x2 또는 2x3 그리드 (한쪽에 이미지, 다른 쪽에 콘텐츠 블록 그리드)
- 하프 블리드 이미지 (전체 왼쪽 또는 오른쪽) 와 콘텐츠 오버레이
데이터 표시:
- 큰 숫자 콜아웃 (큰 숫자 60-72pt, 아래 작은 레이블)
- 비교 열 (이전/이후, 장점/단점, 나란히 옵션)
- 타임라인 또는 프로세스 흐름 (번호가 매겨진 단계, 화살표)
시각적 세부 사항:
- 섹션 헤더 옆의 작은 색상 원 안의 아이콘
- 주요 통계 또는 태그라인에 대한 이탤릭체 악센트 텍스트
타이포그래피
.pptx에 작성하는 글꼴 이름은 이 환경이 아닌 사용자의 PowerPoint에서 렌더링됩니다. 시각적 QA는 LibreOffice를 통해 렌더링되며, LibreOffice는 가지고 있지 않은 글꼴을 대체합니다. 일부 글꼴의 경우 대체 글꼴의 너비가 달라 QA 미리보기에서 실제 덱에는 없는 텍스트 오버플로(또는 맞춤)가 표시될 수 있습니다. QA의 신뢰성을 유지하려면:
- 안전한 글꼴 (QA에서 실제 너비로 렌더링되고 Office에 포함됨): Arial, Calibri, Cambria, Times New Roman, Courier New, Bookman Old Style, Century Schoolbook. 본문 텍스트 및 맞춤이 중요한 모든 항목에 사용하세요.
- QA 리스크 없이 개성 있는 헤더: 안전한 목록의 세리프 헤더(Cambria, Bookman Old Style, Century Schoolbook)와 안전한 목록의 산세리프 본문(Calibri 또는 Arial)을 짝지으세요. 신뢰할 수 있는 오버플로 검사를 포기하지 않으면서 시각적 대비를 얻을 수 있습니다.
- 사용자가 안전한 목록에 없는 글꼴(예: Georgia 또는 Trebuchet MS)을 요청하는 경우: 사용자가 요청한 곳에 사용하되, 해당 컨테이너의 크기를 추가 여유(~10%)를 두고 설정하고 해당 요소의 QA 텍스트 맞춤을 신뢰하지 마세요. 해당 글꼴의 미리보기는 근사치입니다. 사용자가 지정하지 않은 경우 본문 텍스트에는 안전한 목록의 글꼴을 선호하세요.
- QA 신뢰할 수 없는 글꼴 (대체 글꼴의 너비가 다릅니다. 오버플로 검사가 잘못될 수 있음): Georgia, Trebuchet MS, Impact, Arial Black, Garamond, Consolas, Palatino Linotype. Calibri Light 대체는 환경에 따라 다릅니다. QA 신뢰할 수 없음으로 취급하세요. 여유를 두고 제목/악센트에 사용하는 것은 괜찮지만, 이러한 글꼴의 QA 텍스트 맞춤은 신뢰하지 마세요.
- 절대 Aptos를 기본값으로 사용하지 마세요. Office의 2023년 이후 기본값은 여기에 메트릭 호환 대체 글꼴이 없으며 오래된 Office 설치에도 없으므로 양쪽 모두에서 신뢰할 수 없습니다.
| 요소 | 크기 |
|---|---|
| 슬라이드 제목 | 36-44pt 굵게 |
| 섹션 헤더 | 20-24pt 굵게 |
| 본문 텍스트 | 14-16pt |
| 캡션 | 10-12pt 흐리게 |
…
[잘림: 번역 대상]
{
"name": "PPTX 생성, 편집, 분석",
"description": ".pptx 또는 .potx 파일이 입력, 출력, 또는 둘 다 관련된 모든 작업(슬라이드 덱 생성, 읽기, 편집, 병합, 템플릿 작업 등)에 사용합니다.",
"aiSummary": "이 스킬은 PowerPoint 프레젠테이션(.pptx) 및 템플릿(.potx) 파일을 완전히 제어할 수 있도록 설계되었습니다. 새로운 슬라이드 덱을 생성하거나, 기존 파일을 편집하거나, 콘텐츠를 읽고 추출해야 하는 모든 경우에 이 스킬을 사용해야 합니다. 작업 방식은 명확하게 구분됩니다. 빠른 생성을 위해서는 사전 설치된 pptxgenjs 라이브러리를 사용하지만, 설계상의 주의사항(예: 색상 코드 앞에 '#' 사용 금지, 그림자 오프셋 음수 금지)을 엄격히 준수해야 합니다. 편집 및 템플릿 작업을 위해서는 파일을 압축 해제하고, 개별 슬라이드 XML을 수정한 후 다시 압축하는 방식의 정밀한 접근 방식을 사용합니다. 콘텐츠 읽기는 markitdown 명령어를 통해 각 슬라이드를 구분된 텍스트 블록으로 추출하거나, 썸네일 스크립트로 시각적 그리드를 확인할 수 있습니다. 또한 템플릿 기반 작업 시 스키마 검증, 중복 슬라이드 추가, 사용되지 않는 리소스 정리 등 일련의 스크립트를 제공하여 파일 무결성을 보장합니다. 시각적 디자인을 위해 다양한 색상 팔레트와 레이아웃 아이디어를 제안하며, 텍스트 오버플로 문제를 피하기 위해 안전한 폰트 목록을 사용할 것을 권장합니다. 최종 출력 파일은 제공된 검증 스크립트로 검사하여 잠재적인 오류를 찾고 수정 방법을 제시합니다.",
"skillMarkdown": "# PPTX 생성, 편집 및 분석\n\n`.pptx` 파일은 XML 파일의 ZIP 아카이브입니다. 작업에 따라 접근 방식을 선택하세요:\n\n| 작업 | 접근 방식 |\n|---|---|\n| **새** 덱 생성 | `pptxgenjs` 스크립트 작성 — 아래 주의사항 참조 |\n| **기존** 덱 편집 또는 템플릿 기반 생성 | 압축 해제 → `ppt/slides/slideN.xml` 편집 → 압축 |\n| **읽기** | \"`markitdown deck.pptx`\" (각 슬라이드는 `<!-- Slide number: N -->` 마커로 구분); 시각적 그리드: \"`python scripts/thumbnail.py deck.pptx`\" |\n\n## 스크립트\n\n경로는 이 스킬 디렉토리를 기준으로 합니다. 그 외 모든 것은 일반 Python, `node` 또는 셸입니다.\n\n| 스크립트 | 기능 |\n|---|---|\n| `scripts/thumbnail.py deck.pptx [prefix]` | 템플릿 레이아웃 선택을 위한 각 슬라이드의 레이블이 지정된 그리드입니다. `.pptx`만 지원합니다. `prefix`를 전달할 수 있으며, 기본값은 `thumbnails`입니다. 같은 디렉토리에서 다른 덱의 그리드를 덮어씁니다. |\n| `scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml]` | 모든 패키지 부기(bookkeeping)를 포함하여 슬라이드(또는 `slideLayoutN.xml`)를 복제합니다. 또한 `-o out.pptx` 옵션을 사용하여 `.pptx` 파일을 직접 입력받을 수도 있습니다. |\n| `scripts/clean.py unpacked/` | 더 이상 참조되지 않는 슬라이드, 미디어 및 관계(rels)를 삭제합니다. `<p:sldIdLst>`가 최종 상태가 된 **후에** 실행하세요. |\n| `scripts/office/validate.py deck.pptx [--original src.pptx]` | 스키마, 관계, 콘텐츠 유형, 차트 및 슬라이드 검사를 수행합니다. 각 실패는 수정 방법을 제시합니다. 템플릿에서 파생된 덱의 경우 `--original`을 전달하면 템플릿을 기준으로 스키마 검사를 수행하여 템플릿 자체의 XSD 오류가 사용자 오류로 표시되지 않도록 합니다. |\n| `scripts/office/soffice.py --headless --convert-to pdf deck.pptx` | LibreOffice 래퍼 — 일반 `soffice`는 이 샌드박스에서 중단됩니다. |\n\n## pptxgenjs로 생성하기 — 주의사항\n\n`pptxgenjs`는 사전 설치되어 있습니다. `npm install`을 실행하지 말고, 스크립트를 작성하여 직접 `require('pptxgenjs')` 하세요. require가 실패하는 경우에만 `npm install pptxgenjs`를 실행하세요. 모델은 API를 알고 있습니다. 다음은 자주 실수하는 부분들입니다:\n\n- **슬라이드를 추가하기 전에 `pres.layout`을 설정하세요.** 기본 캔버스는 `LAYOUT_16x9` = **10\" × 5.625\"** 이며, 13.3\" 너비가 아닙니다. 가장자리를 넘는 좌표는 기록되지만 클램핑되지 않습니다. 즉, 도형이 슬라이드에 존재하지 않게 됩니다. (`LAYOUT_WIDE`는 13.3\" × 7.5\"입니다.)\n- **16진수 색상: 절대 `#`를 사용하지 말고, 8자리를 사용하지 마세요.** `color: \"FF0000\"`. `\"#FF0000\"` 및 16진수에 알파 값을 포함하는 것(`\"00000020\"`)은 **파일을 손상시킵니다**. 반투명도 사용 시: 채우기 및 이미지에는 `transparency: 0-100`, 그림자에는 `opacity: 0.0-1.0`을 사용하세요. 각 속성은 다른 속성에서 조용히 무시됩니다.\n- **pptxgenjs는 옵션 객체를 제자리에서 변경합니다** (처음 사용 시 값을 EMU로 변환). 두 개 이상의 `add*` 호출 간에 하나의 `shadow`/옵션 객체를 공유하지 마세요. 매번 새 객체를 생성하세요.\n- **그림자 `offset`은 0 이상이어야 합니다.** — 음수 오프셋은 파일을 손상시킵니다. 위쪽으로 그림자를 드리우려면 양수 오프셋과 함께 `angle: 270`을 사용하세요.\n- **`letterSpacing`은 조용히 무시됩니다** — 실제 옵션은 `charSpacing`입니다.\n- **목록:** 각 항목에 `bullet: true`를 사용하고, 리터럴 `•`는 절대 사용하지 마세요 (이중 글머리 기호가 렌더링됩니다). 마지막 항목을 제외한 모든 배열 항목에 `breakLine: true`를 설정하세요. 글머리 기호 단락 간격은 `lineSpacing`이 아닌 `paraSpaceAfter`로 설정하세요 (큰 간격이 생깁니다).\n- **출력 파일당 하나의 `new pptxgen()`** — 인스턴스를 재사용하지 마세요.\n- **`rectRadius`는 `ROUNDED_RECTANGLE`에서만 작동하며**, `RECTANGLE`에서는 작동하지 않습니다.\n- **그라데이션 채우기는 지원되지 않습니다** — 대신 그라데이션 이미지를 배경으로 사용하세요.\n- **텍스트 상자에는 기본 내부 패딩이 내장되어 있습니다** — 텍스트가 같은 x 위치의 도형, 선 또는 아이콘과 정렬되어야 할 때마다 `margin: 0`을 설정하세요.\n- **발표자 노트는 `slide.addNotes(...)`에 넣습니다** (일반 텍스트, 슬라이드당 한 번). 슬라이드의 텍스트 상자에 넣지 마세요.\n- **차트는 네이티브로 유지하세요.** PowerPoint에서 차트로 만들 수 있는 모든 것에는 `addChart()`를 사용하세요 (콤보 차트의 경우 `{type, data, options}` 배열 전달). 라이브러리가 노출하지 않는 PowerPoint 네이티브 기능(추세선, 오차 막대)의 경우, 추가 계열을 직접 계산하거나 생성된 OOXML을 후처리하세요. 렌더링된 이미지로 대체하지 마세요. PowerPoint에 네이티브 형식이 없는 차트 유형(예: Sankey, 네트워크, 코드 다이어그램)만 이미지로 넣으세요.\n- **기본 차트는 밋밋하게 렌더링됩니다** — 제목, 데이터 레이블, 구식 팔레트가 없습니다. `showTitle` + `title`, `showValue: true` + `dataLabelPosition`, 팔레트의 `chartColors: [...]`를 설정하고, 프레임을 정리하세요 (`catAxisLabelColor`/`valAxisLabelColor`, `valGridLine: { color, size }`, `catGridLine: { style: \"none\" }`, 단일 계열의 경우 `showLegend: false`).\n- **누적 막대 또는 열 차트에서 `dataLabelPosition`은 `ctr`, `inEnd` 또는 `inBase`여야 합니다.** `outEnd`는 **파일을 손상시킵니다**.\n- **`secondaryValAxis`/`secondaryCatAxis`를 사용하는 콤보 계열**은 차트 옵션에 `valAxes`와 `catAxes`가 각각 두 개의 항목으로 필요합니다. 이것들이 없으면 pptxgenjs는 선언되지 않은 축 *id*를 작성하고, PowerPoint는 **해당 차트를 버리고** 파일이 손상되었다고 보고합니다. `valAxes`만 제공하는 것으로는 충분하지 않습니다.\n- **`writeFile()` 후에 `python scripts/office/validate.py deck.pptx`를 실행하세요.** 위의 두 가지 차트 결함과 PowerPoint가 거부하는 슬라이드 XML 결함을 보고하고 각각의 수정 방법을 제시합니다. 생성기에서 수정하고, 압축된 XML을 수동으로 편집하지 마세요.\n- **`<p:presentation>`의 자식 순서를 절대 변경하지 마세요.** pptxgenjs는 `<p:sldIdLst>` 바로 뒤에 `<p:notesMasterIdLst>`를 작성하고 두 마스터를 하나의 테마 파트로 연결합니다. PowerPoint는 이를 정상적으로 읽습니다. 요소를 이동하면 같은 덱을 열 수 없게 됩니다.\n- **아이콘:** `react-icons`를 SVG로 렌더링하고(`ReactDOMServer.renderToStaticMarkup`), `sharp`으로 ≥256px에서 래스터화한 다음, `addImage({ data: \"image/png;base64,\" + buf.toString(\"base64\") })`를 통해 삽입하세요. `image/png;base64,` 접두사는 필수입니다 (`react-icons`, `react`, `react-dom`, `sharp`은 사전 설치되어 있습니다. require가 실패하는 경우에만 `npm install react-icons react react-dom sharp` 실행).\n\n## 기존 덱 및 템플릿 편집\n\n먼저 레이아웃을 선택하세요: `python scripts/thumbnail.py template.pptx template-thumbs`는 각 슬라이드의 레이블이 지정된 그리드를 작성하고 생성된 파일을 출력합니다. `template-thumbs.jpg`이며, 슬라이드가 12개를 넘으면 `template-thumbs-N.jpg`로 분할됩니다. **항상 덱 이름을 따서 명명된 두 번째 인수를 전달하세요.** 기본값은 `thumbnails`이므로, 한 디렉토리에서 두 덱의 썸네일을 생성하면 서로의 그리드가 조용히 덮어써집니다. 첫 번째 덱의 그리드는 그냥 사라집니다. (템플릿 분석 전용 — 시각적 QA는 [이미지로 변환](#이미지로-변환)의 전체 해상도 렌더링이 필요합니다. `.pptx`만 허용하므로 먼저 `.potx`를 `.pptx` 이름으로 복사하세요). 이것을 `markitdown`과 함께 사용하여 각 콘텐츠 섹션을 템플릿 슬라이드에 매핑하고 레이아웃을 다양화하세요. 모든 섹션을 동일한 제목 및 글머리 기호 슬라이드에 넣지 마세요.\n\n```bash\npython3 -c \"import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall('unpacked')\" deck.pptx\npython scripts/add_slide.py unpacked/ slide2.xml --after slide2.xml # 슬라이드(또는 slideLayoutN.xml) 복제; 새 슬라이드 경로 출력\n# 슬라이드 재정렬 / 삭제 = ppt/presentation.xml에서 <p:sldIdLst> 편집\npython scripts/clean.py unpacked/ # 삭제 후: 고아 슬라이드, 미디어, 관계 제거\n# ppt/slides/slideN.xml에서 슬라이드 콘텐츠 편집\n(cd unpacked && rm -f ../out.pptx && zip -Xr ../out.pptx .) # 디렉토리 내부에서 압축; 먼저 rm 하지 않으면 삭제된 부분이 남습니다\npython scripts/office/validate.py out.pptx --original deck.pptx\n```\n\n- **슬라이드 콘텐츠를 편집하기 전에 모든 구조적 작업(추가, 삭제, 재정렬)을 수행하세요.** `add_slide.py`는 슬라이드 파일을 그대로 복사하므로, 편집 후 복제하면 편집된 콘텐츠가 복제됩니다. 그리고 `clean.py`는 방금 작성한 슬라이드를 포함하여 `<p:sldIdLst>`에 없는 모든 슬라이드를 삭제합니다.\n- **슬라이드 파일을 수동으로 복사하지 마세요.** `add_slide.py`는 새 슬라이드에 필요한 모든 등록을 수행하고 생성된 내용을 보고합니다(`Created ppt/slides/slide17.xml from slide2.xml`). 또한 파일에서 직접 작동합니다: `add_slide.py deck.pptx slide2.xml -o out.pptx` — **`-o`를 전달하지 않으면 입력 덱을 제자리에서 덮어씁니다.** 복제된 슬라이드는 여전히 원본의 차트/SmartArt/임베디드 객체 파트를 복제하는 것이 아니라 *참조*하므로, 한 슬라이드의 차트를 편집하면 다른 슬라이드도 변경됩니다.\n- **`python-pptx`를 사용하는 경우**, 할 수 없는 세 가지: 슬라이드 복제(유일한 진입점은 `add_slide(layout)`), `text_frame.text = \"...\"`를 통한 서식 유지(단락을 스타일이 없는 단일 run으로 축소합니다. 대신 `run.text`를 할당하세요), 대부분의 템플릿 아트에서 사용하는 SVG/EMF 읽기(`add_picture`는 `UnidentifiedImageError`를 발생시킵니다).\n- 레거시 `.ppt`는 먼저 변환해야 합니다: `python scripts/office/soffice.py --headless --convert-to pptx file.ppt`. `.potx` 템플릿은 동일하게 압축 해제 및 압축됩니다. 출력 파일에 `.potx` 확장자를 유지하세요.\n- 템플릿 아이콘 또는 이미지를 재사용하려면 이미 포함된 슬라이드 또는 레이아웃을 복제하세요.\n\n템플릿을 채울 때:\n\n- XML 변환을 스크립팅하는 경우 `defusedxml.minidom`으로 구문 분석하세요. `xml.etree.ElementTree`를 통해 OOXML을 왕복하면 네임스페이스 접두사가 다시 작성되어 덱이 손상됩니다.\n- **템플릿 슬롯 ≠ 소스 항목.** 템플릿에 4명의 팀 구성원이 표시되고 실제로 3명이 있는 경우, 4번째 구성원의 전체 그룹(이미지 + 텍스트 상자)을 텍스트만 삭제하지 말고 삭제하세요. 그런 다음 QA에서 고아 시각 요소를 확인하세요.\n- 목록 항목당 하나의 `<a:p>` — 항목을 단일 단락으로 연결하지 마세요. 형제 `<a:pPr>`를 복사하여 간격을 유지하고, 제목, 섹션 헤더 및 인라인 레이블(`Status:`, `Owner:`)의 `<a:rPr>`에 `b=\"1\"`을 설정하세요.\n- 글머리 기호가 레이아웃에서 상속되도록 두고, 재정의해야 하는 경우에만 `<a:buChar>`, `<a:buAutoNum>`(번호 매기기) 또는 `<a:buNone>`을 추가하세요. 텍스트에 리터럴 `•`를 절대 사용하지 마세요.\n- 앞이나 뒤에 공백이 있는 텍스트는 `<a:t>`에 `xml:space=\"preserve\"`가 필요합니다.\n\n## 디자인 아이디어\n\n**지루한 슬라이드를 만들지 마세요.** 흰색 배경에 기본 글머리 기호는 누구에게도 깊은 인상을 주지 못합니다. 각 슬라이드에 대해 이 목록의 아이디어를 고려하세요.\n\n### 시작하기 전에\n\n- **대담하고, 콘텐츠에 맞는 색상 팔레트를 선택하세요:** 팔레트는 이 주제에 맞게 디자인된 느낌이어야 합니다. 색상을 완전히 다른 프레젠테이션에 적용해도 여전히 \"잘 어울린다면\" 충분히 구체적인 선택을 하지 않은 것입니다.\n- **평등보다 우세:** 하나의 색상이 지배적이어야 하며(시각적 비중의 60-70%), 1-2개의 보조 톤과 하나의 선명한 악센트가 있어야 합니다. 모든 색상에 동일한 비중을 절대 주지 마세요.\n- **어두움/밝음 대비:** 제목 및 결론 슬라이드에는 어두운 배경, 콘텐츠 슬라이드에는 밝은 배경(\"샌드위치\" 구조). 또는 프리미엄 느낌을 위해 전체적으로 어두운 배경을 사용하세요.\n- **시각적 모티프를 정하세요:** 하나의 독특한 요소를 선택하고 반복하세요. 예: 둥근 이미지 프레임, 색상 원 안의 아이콘. 모든 슬라이드에 걸쳐 이를 유지하세요. **모티프로 컬러 바 또는 악센트 스트라이프를 사용하지 마세요** (회피 목록 참조).\n\n### 색상 팔레트\n\n주제에 맞는 색상을 선택하세요. 기본 파란색으로 되돌아가지 마세요. 다음 팔레트를 영감으로 사용하세요:\n\n| 테마 | 기본 | 보조 | 악센트 |\n|---|---|---|---|\n| **미드나잇 임원** | `1E2761` (네이비) | `CADCFC` (아이스 블루) | `FFFFFF` (흰색) |\n| **숲과 이끼** | `2C5F2D` (포레스트) | `97BC62` (모스) | `F5F5F5` (크림) |\n| **코랄 에너지** | `F96167` (코랄) | `F9E795` (골드) | `2F3C7E` (네이비) |\n| **따뜻한 테라코타** | `B85042` (테라코타) | `E7E8D1` (샌드) | `A7BEAE` (세이지) |\n| **오션 그라데이션** | `065A82` (딥 블루) | `1C7293` (틸) | `21295C` (미드나잇) |\n| **차콜 미니멀** | `36454F` (차콜) | `F2F2F2` (오프 화이트) | `212121` (블랙) |\n| **틸 트러스트** | `028090` (틸) | `00A896` (시폼) | `02C39A` (민트) |\n| **베리 앤 크림** | `6D2E46` (베리) | `A26769` (더스티 로즈) | `ECE2D0` (크림) |\n| **세이지 칼름** | `84B59F` (세이지) | `69A297` (유칼립투스) | `50808E` (슬레이트) |\n| **체리 볼드** | `990011` (체리) | `FCF6F5` (오프 화이트) | `2F3C7E` (네이비) |\n\n### 각 슬라이드에 대해\n\n**모든 슬라이드에는 시각적 요소(이미지, 차트, 아이콘 또는 도형)가 필요합니다.** 텍스트만 있는 슬라이드는 기억에 남지 않습니다.\n\n**레이아웃 옵션:**\n- 두 열 (왼쪽 텍스트, 오른쪽 일러스트레이션)\n- 아이콘 + 텍스트 행 (색상 원 안의 아이콘, 굵은 헤더, 아래 설명)\n- 2x2 또는 2x3 그리드 (한쪽에 이미지, 다른 쪽에 콘텐츠 블록 그리드)\n- 하프 블리드 이미지 (전체 왼쪽 또는 오른쪽) 와 콘텐츠 오버레이\n\n**데이터 표시:**\n- 큰 숫자 콜아웃 (큰 숫자 60-72pt, 아래 작은 레이블)\n- 비교 열 (이전/이후, 장점/단점, 나란히 옵션)\n- 타임라인 또는 프로세스 흐름 (번호가 매겨진 단계, 화살표)\n\n**시각적 세부 사항:**\n- 섹션 헤더 옆의 작은 색상 원 안의 아이콘\n- 주요 통계 또는 태그라인에 대한 이탤릭체 악센트 텍스트\n\n### 타이포그래피\n\n**.pptx에 작성하는 글꼴 이름은 이 환경이 아닌 사용자의 PowerPoint에서 렌더링됩니다.** 시각적 QA는 LibreOffice를 통해 렌더링되며, LibreOffice는 가지고 있지 않은 글꼴을 대체합니다. 일부 글꼴의 경우 대체 글꼴의 너비가 달라 QA 미리보기에서 실제 덱에는 없는 텍스트 오버플로(또는 맞춤)가 표시될 수 있습니다. QA의 신뢰성을 유지하려면:\n\n- **안전한 글꼴** (QA에서 실제 너비로 렌더링되고 *Office에 포함됨*): **Arial, Calibri, Cambria, Times New Roman, Courier New, Bookman Old Style, Century Schoolbook**. 본문 텍스트 및 맞춤이 중요한 모든 항목에 사용하세요.\n- **QA 리스크 없이 개성 있는 헤더**: 안전한 목록의 세리프 헤더(Cambria, Bookman Old Style, Century Schoolbook)와 안전한 목록의 산세리프 본문(Calibri 또는 Arial)을 짝지으세요. 신뢰할 수 있는 오버플로 검사를 포기하지 않으면서 시각적 대비를 얻을 수 있습니다.\n- **사용자가 안전한 목록에 없는 글꼴(예: Georgia 또는 Trebuchet MS)을 요청하는 경우**: 사용자가 요청한 곳에 사용하되, 해당 컨테이너의 크기를 추가 여유(~10%)를 두고 설정하고 해당 요소의 QA 텍스트 맞춤을 신뢰하지 마세요. 해당 글꼴의 미리보기는 근사치입니다. 사용자가 지정하지 않은 경우 본문 텍스트에는 안전한 목록의 글꼴을 선호하세요.\n- **QA 신뢰할 수 없는 글꼴** (대체 글꼴의 너비가 다릅니다. 오버플로 검사가 잘못될 수 있음): Georgia, Trebuchet MS, Impact, Arial Black, Garamond, Consolas, Palatino Linotype. Calibri Light 대체는 환경에 따라 다릅니다. QA 신뢰할 수 없음으로 취급하세요. 여유를 두고 제목/악센트에 사용하는 것은 괜찮지만, 이러한 글꼴의 QA 텍스트 맞춤은 신뢰하지 마세요.\n- **절대 Aptos를 기본값으로 사용하지 마세요.** Office의 2023년 이후 기본값은 여기에 메트릭 호환 대체 글꼴이 없으며 *오래된 Office 설치에도 없으므로* 양쪽 모두에서 신뢰할 수 없습니다.\n\n| 요소 | 크기 |\n|---|---|\n| 슬라이드 제목 | 36-44pt 굵게 |\n| 섹션 헤더 | 20-24pt 굵게 |\n| 본문 텍스트 | 14-16pt |\n| 캡션 | 10-12pt 흐리게 |\n\n#\n\n…\n\n[잘림: 번역 대상]"
}