Claude Code 스킬 제작기 — 회사 PPT 템플릿을 자동화하다 오픈소스까지
Braincrew 사내 PPT 템플릿을 매번 손으로 채우던 일을 Claude Code 스킬로 자동화한 과정 — 이미지 기반 PPTX 한계, 편집 가능 PPTX로의 개선, 그리고 오픈소스 버전(oh-my-slides)에서는 회사 템플릿 대신 사용자 PPTX를 받아 에셋을 추출하는 구조까지.
프로젝트 소개
회사에서 발표 자료를 만들 일이 자주 있다. 표지·목차·섹션 표지·본문 9종·Thank-you — 회사 브랜드 가이드를 따르려면 매번 색상, 폰트, 여백, 워드마크를 일일이 맞춰야 한다. 한 덱에 20장만 돼도 30분~1시간이 그냥 사라진다.
이걸 한 줄 명령으로 끝내고 싶었다.
bc ppt: AI 기술 트렌드 2026
이 한 줄이 채워야 할 것:
- 회사 브랜드 — 정확히 같은 색·폰트·로고·악센트
- 13종 레이아웃 — 표지/목차/섹션/본문 9종/Thank-you
- 편집 가능한 PPTX — 이미지로 박힌 게 아니라, 발표자가 PowerPoint에서 텍스트를 그대로 수정 가능
- 발표용 HTML도 같이 — 애니메이션, 키보드 네비게이션 포함
이 글은 그 스킬을 만들어가는 과정이다. 사내용 bc-ppt → 편집 가능 PPTX 개선 → 오픈소스 oh-my-slides 세 단계.
v1 — bc-ppt: 사내 템플릿 그대로 재현하기
첫 버전은 단순했다. 회사가 이미 만들어둔 4종 PPTX 템플릿(다크-A / 라이트-B / 내부-A / 내부-B)이 있었고, 그 디자인 시스템을 그대로 옮기는 게 목표.
디자인 토큰 추출
PPTX 파일은 사실 ZIP이다. 압축을 풀면 theme1.xml 안에 색상·폰트가 다 들어있다. 이걸 파싱해 CSS 변수로 매핑하는 스크립트부터 시작.
:root {
--bg-primary: #08262A;
--accent: #D3F0A0;
--text-primary: #FFFFFF;
--font-display: "Pretendard", "Noto Sans KR", sans-serif;
/* ... */
}13개 레이아웃을 고정으로
자유도를 높이면 결과가 들쭉날쭉했다. 그래서 레이아웃을 13개로 못 박았다.
cover(표지)toc(목차)section(섹션 표지)body-1~body-9(본문 9종)thank-you
레이아웃 9종이 본문에 다 있는 이유는 — 같은 정보 구조라도 문장형/카드형/타임라인형/대비형/프로세스형 등으로 다양하게 표현해야 단조롭지 않기 때문.
spec_lock으로 드리프트 방지
긴 덱(15장 이상)을 한 번에 만들면 후반부로 갈수록 LLM이 자기 스타일을 슬슬 흘린다. 폰트 크기가 커지거나 레이아웃이 임의로 만들어지거나.
해결: spec_lock.md라는 단일 파일에 이번 덱의 모든 결정(variant, 색상 토큰, 슬라이드 별 레이아웃·page_rhythm)을 못 박고, 슬라이드 생성 직전마다 LLM이 다시 읽도록 강제했다.
## Brand Tokens
bg-primary: #08262A
accent: #D3F0A0
font-display: Pretendard
## Slide Plan
| # | layout | page_rhythm | title |
|---|--------|-------------|-------|
| 1 | cover | anchor | bc-ppt 업데이트 |
| 2 | toc | anchor | 목차 |
| 3 | section | breathing | 01 — 왜 만들었나 |
| 4 | body-3 | dense | 기존 워크플로우의 비효율 |
| ... |page_rhythm 태그는 단조로움 방지용. 연속 dense 3개 이상 금지. anchor / dense / breathing 셋이 번갈아 나오게.
결과 — 사내 템플릿 그대로

여기까지가 바로 v1. 한 줄 명령으로 회사 발표자료 한 덱이 30초 안에 나온다.
v2 — 편집 가능 PPTX로 개선
v1에는 큰 한계가 있었다. PPTX는 사실 HTML 슬라이드의 스크린샷이었다.
HTML 슬라이드 → Playwright로 캡처 → PNG → PptxGenJS로 PPTX에 박기
발표자가 PowerPoint를 열어 오타를 고치려고 하면 — 텍스트가 아니라 이미지라 안 된다. "PPT 자동 생성"은 됐지만 "편집"은 안 됐다.
구조 바꾸기 — Deep-clone + Placeholder 치환
해결책은 회사 PPTX 템플릿 자체를 베이스로 삼고, 그 안의 placeholder 텍스트만 치환하는 것.
흐름이 이렇게 바뀌었다:
1. 회사 템플릿 PPTX (다크-A.pptx)를 deep-clone
2. 슬라이드 13장의 placeholder를 식별 ("제목을 입력하세요" 등)
3. LLM이 만든 콘텐츠로 placeholder만 교체
4. 텍스트는 진짜 텍스트로 살아있음 (편집 가능)
이 방식의 장점:
- PowerPoint, Keynote, Google Slides에서 그대로 편집 가능
- 폰트 임베딩, 마스터 슬라이드, 차트 스타일 등 PPTX 고유 기능 보존
- 파일 크기도 이미지 박힌 PPTX보다 훨씬 작다
문제는 placeholder 식별이다. 한 PPTX 안에는 텍스트 박스 수십 개가 있는데, 그중 어느 게 "제목"이고 어느 게 "부제"인지 파일만 봐서는 모른다. 그래서 spec_lock_template.md에 각 레이아웃의 placeholder 위치를 미리 등록해두고, 스크립트가 그 매핑대로 치환한다.
이 작업이 v2의 핵심이고, 지금도 계속 다듬어가는 중이다. 차트 데이터 동적 주입(native_chart.py), 표 셀 채우기, 이미지 placeholder 등이 이 기반 위에서 추가되고 있다.
quality_check.py — 사후 검증
PPTX 생성이 끝나면 자동으로 검사한다.
- placeholder 텍스트(
"내용을 작성해주세요"등) 잔존 여부 - 빈 슬라이드
- 폰트 폴백(Pretendard 외 폰트)
- 색상 팔레트 일탈
문제 발견 시 어느 슬라이드의 어느 박스인지까지 리포트. AI가 한 번에 못 잡은 걸 게이트가 잡는다.
v3 — 오픈소스 oh-my-slides: 회사 템플릿 X, 사용자 템플릿 O
만들고 보니 회사 동료가 아니어도 쓰고 싶어하는 사람이 많았다. 그런데 회사 템플릿을 그대로 공개할 수는 없다 — 브랜드 자산이니까.
오픈소스 버전을 만들면서 발상을 뒤집었다.
공개되는 건 회사 템플릿이 아니다. 사용자가 자기 템플릿을 올리면, 거기서 디자인 시스템을 추출해 쓰는 프레임워크다.
이게 oh-my-slides.
두 가지 사용 흐름
1) 큐레이팅된 20개 프리셋
브랜드가 따로 없는 일반 사용자를 위해, 분위기별 프리셋 20개를 직접 만들어 넣었다. Bold Signal, Electric Studio, Creative Voltage, Dark Botanical, Swiss Modern, Terminal Green, Dark Academia, Bento Grid, Risograph Print, Cyberpunk Outline 등.

각 프리셋은 단일 CSS 파일이라 사용자가 직접 추가/수정할 수 있다.
2) 자기 PPTX 템플릿 임포트
회사 브랜드를 가진 사람이라면 자기 PPTX를 직접 올릴 수 있다.
node skills/oh-my-slides/scripts/import-pptx-theme.js \
company-template.pptx my-brand --dark이 스크립트가 하는 일:
- PPTX의
theme1.xml을 읽어 색상·폰트·악센트 추출 - Office 폰트(예: 맑은 고딕, Calibri)를 Google Fonts 등가물로 매핑
- 첫 페이지/배경의 미디어 에셋(로고, 도형 SVG)을 추출
- 새 프리셋 CSS 파일로 자동 생성
즉, 오픈소스로 공개된 건 **회사 템플릿이 아니라 "어떤 PPTX든 받아서 에셋을 추출해 쓰는 파이프라인"**이다.
5-Phase 워크플로우

가장 큰 차별점은 Phase 2다. 보통 도구는 "어떤 색이 좋아?"를 묻지만, oh-my-slides는 세 가지 미니 미리보기 HTML을 실제로 만들고 Playwright로 스크린샷을 찍어 나란히 보여준다. 사용자는 시각적으로 고른다.
Viewport Fitting — 어느 화면이든 잘리지 않게
height: 100dvh;
overflow: hidden;
--title-size: clamp(2rem, 6vw, 5rem);
@media (max-height: 700px) { /* 패딩 축소 */ }
@media (max-height: 500px) { /* 헤딩 축소 */ }13인치 노트북부터 4K 모니터까지 슬라이드 한 장이 정확히 한 화면이 되게. 옛날 Reveal.js 스타일의 내부 스크롤은 없다.
Dual Output — 발표용 HTML + 편집용 PPTX
bc-ppt에서 다듬은 편집 가능 PPTX 경험이 그대로 들어가 있다. 다만 오픈소스 버전은 세 가지 export 옵션을 제공:
| 방식 | 편집 가능? | 충실도 |
|---|---|---|
| Viewport capture | ✗ | 픽셀 완벽 |
| Slide capture | ✗ | 픽셀 완벽 |
| html2pptx (PptxGenJS) | ✓ | 제한적 |
복잡한 디자인은 캡처(이미지) 방식이 충실도 높지만 편집 불가. 발표 후 수정이 필요하면 html2pptx 방식. 같은 HTML 소스에서 양쪽 다 뽑을 수 있게 했다.
결과와 회고
좋았던 점
spec_lock패턴의 효과가 컸다. 긴 덱에서도 후반부 드리프트가 거의 사라졌다. 이 패턴은 다른 LLM 워크플로우에도 그대로 옮길 수 있다.- Dual Output이 실전에서 매우 유용했다. HTML로는 발표하고, PPTX는 동료에게 넘기거나 회사 양식에 맞춰 살짝 수정하는 식.
- 오픈소스화하면서 "회사 템플릿 → 사용자 템플릿" 발상 전환이 결과적으로 더 일반적인 도구가 됐다. 어느 회사나 자기 브랜드를 그대로 쓸 수 있다.
어려웠던 점
- 편집 가능 PPTX의 한계. 복잡한 도형·차트·애니메이션은 PptxGenJS 한 라이브러리로 다 표현 못 한다. 그래서 "캡처" 방식과 "편집" 방식 두 가지를 같이 두는 절충.
- placeholder 매핑의 수동 관리. 새 레이아웃 추가할 때마다
spec_lock_template.md에 위치를 등록해야 한다. 이걸 PPTX 분석으로 자동화하는 게 다음 과제. - 폰트 임베딩. 한글 폰트 라이선스 이슈로 모든 PPTX에 Pretendard를 임베드할 수는 없다. Google Fonts URL로 우회하지만 오프라인 환경에서는 폴백.
앞으로
- 차트 데이터 동적 주입 강화 (
native_chart.py확장) - 표 cell 단위 placeholder
- 이미지 placeholder의 AI 자동 생성 통합
- Phase 2 미니 프리뷰의 캐싱 (지금은 매번 새로 렌더)
GitHub
- oh-my-slides (오픈소스): github.com/seongyeon1/oh-my-slides
- 라이브 데모: seongyeon1.github.io/oh-my-slides
- 사내
bc-ppt는 회사 브랜드 자산이라 비공개.
설치는 한 줄.
git clone https://github.com/seongyeon1/oh-my-slides.git
cd oh-my-slides
bash install.shClaude Code 재시작하고 PPT 만들어줘: <주제> 또는 Create a presentation about <topic> 라고 치면 된다.
정리
자동화 스킬을 만드는 과정에서 깨달은 한 줄.
"브랜드를 박제한 도구"보다 "브랜드를 받아서 쓰는 도구"가 훨씬 멀리 간다.
회사 템플릿에 종속됐던 v1이 결국 오픈소스 v3에서는 임의의 PPTX를 받아 자기 디자인 시스템으로 변환하는 파이프라인이 됐다. 처음부터 이 구조를 의도한 건 아니지만, 결과적으로 더 단단한 도구가 됐다. 만들면서 배우는 게 결국 가장 큰 수확이다.