---
ai_assisted: true
title: "마크다운 슬라이드·PDF 변환 파이프라인"
description: "마크다운 한 파일을 pandoc·XeLaTeX으로 Beamer 슬라이드나 A4 문서 PDF로 만드는 zsh 함수 두 개와 macOS 스크린샷 설정 함수 하나"
pubDate: 2026-05-20T20:39:11+09:00
category: "Development"
tags: ["zsh", "Markdown", "Marp", "PDF", "Slides", "Chrome", "Content Workflow", "Dotfiles"]
heroImage: ""
serial: 16
draft: false
published: true
---

zsh 함수 세 개로 마크다운 한 파일에서 슬라이드 PDF, 본문 PDF, macOS 스크린샷 설정까지 처리합니다. `marp.zsh`의 `md_to_pdf`는 pandoc + XeLaTeX Beamer로 프레젠테이션 PDF를 생성하고, `md_pdf.zsh`의 `_md_pdf_impl`은 동일한 엔진으로 Beamer 슬라이드와 A4 문서 모드를 전환하며, `screenshot.zsh`의 `_screenshot`은 `defaults write com.apple.screencapture`를 단일 인터페이스로 감쌉니다. 세 스크립트의 역할 분담, 호출 인터페이스, 옵션·기본값, 그리고 콘텐츠 작업에서 묶어 쓰는 방식을 다룹니다.

---

## 무엇이 다른가

세 스크립트는 출력 목적이 각각 다릅니다.

`marp.zsh`의 `md_to_pdf`는 `md_latex` 프로젝트 내 Python 스크립트를 Python 가상환경(`md_latex/.venv`)으로 호출해 마크다운을 LaTeX Beamer 슬라이드 PDF로 변환합니다. `--template` 옵션으로 레이아웃 템플릿을 교체할 수 있고, `--tex-only`로 중간 LaTeX 파일만 뽑아낼 수도 있습니다. 별칭 `md2pdf`로 등록되어 있습니다.

`md_pdf.zsh`의 `_md_pdf_impl`은 pandoc을 직접 호출합니다. 기본값은 LaTeX Beamer 슬라이드(가로 16:10, XeLaTeX)이고, `--doc` 플래그를 주면 세로 A4 문서로 전환합니다. Beamer 테마는 `--theme` 옵션으로 지정하며, `red-gray`, `warm`, 그리고 표준 Beamer 테마 이름(Boadilla, Madrid, Berlin 등)을 모두 받습니다. 가상환경 없이 시스템 pandoc을 직접 씁니다.

`screenshot.zsh`의 `_screenshot`은 PDF 생성과 직접 관련이 없습니다. macOS의 `defaults write com.apple.screencapture` 명세를 단일 커맨드로 감싼 설정 래퍼입니다. 스크린샷 저장 경로, 파일 포맷, 미리보기 섬네일 표시 여부를 커맨드 한 줄로 바꿉니다. 스크린샷 자체를 찍는 기능은 없고, macOS 스크린샷 동작을 구성하는 기능입니다.

세 함수를 묶으면 같은 마크다운 소스에서 발표용 슬라이드 PDF, 문서 배포용 A4 PDF를 만들고, macOS 스크린샷 출력 경로를 콘텐츠 작업 폴더로 고정해두는 워크플로를 구성할 수 있습니다.

---

## marp.zsh — 마크다운 → LaTeX Beamer 슬라이드 PDF

`md_to_pdf`는 `MD_LATEX_PATH`에 설정된 `md_latex` 프로젝트 디렉토리의 Python 스크립트(`main.py`)를 가상환경으로 실행하는 래퍼입니다.

```zsh
# 경로 설정
MD_LATEX_PATH="/Users/jaesolshin/Documents/GitHub/md_latex"

# 기본 변환
md_to_pdf presentation.md

# 별칭
md2pdf presentation.md
```

### 옵션 인터페이스

| 옵션 | 기본값 | 설명 |
|---|---|---|
| `--template <템플릿>` | `base` | 레이아웃 템플릿 (`base`, `metropolis`) |
| `--title <제목>` | — | 프레젠테이션 제목 |
| `--author <저자>` | — | 저자명 |
| `--output <파일명>` | 입력명 기반 | 출력 PDF 파일명 |
| `--tex-only` | false | LaTeX 파일만 생성, PDF 컴파일 생략 |
| `--verbose` | false | 상세 출력 |

호출 예시:

```zsh
md_to_pdf presentation.md --template metropolis --title "Q2 리뷰"
md_to_pdf presentation.md --author "홍길동" --output final.pdf
md_to_pdf presentation.md --tex-only
```

### 동작 흐름

실행 시 `activate_md_latex`가 `$MD_LATEX_PATH/.venv/bin/activate`를 소싱해 가상환경을 활성화하고, `python main.py convert`에 절대 경로를 넘깁니다. 변환이 끝나면 작업 디렉토리를 원래 위치로 복원합니다. `--tex-only`가 없으면 `--output-format pdf`, 있으면 `--output-format tex`를 내부적으로 전달합니다.

출력 파일명은 `--output`을 지정하지 않으면 `입력파일명.pdf`로 결정됩니다. 변환 완료 후 파일 크기(bytes)를 함께 출력합니다.

zsh 자동 완성이 내장되어 있습니다. `compdef _md_to_pdf_complete md_to_pdf`로 등록되므로 탭으로 `.md` 파일과 옵션을 완성할 수 있습니다.

---

## md_pdf.zsh — pandoc 직접 호출로 Beamer·문서 PDF

`_md_pdf_impl`은 pandoc을 직접 호출하고 가상환경이 필요 없습니다. 기본값은 LaTeX Beamer 슬라이드이며, `--doc`으로 A4 문서로 전환합니다.

```zsh
# 기본 — Beamer 슬라이드, 현재 디렉토리의 모든 .md 파일 변환
_md_pdf_impl

# 특정 파일만
_md_pdf_impl slides.md

# A4 문서 모드
_md_pdf_impl --doc report.md

# Beamer 테마 지정
_md_pdf_impl --theme Madrid slides.md
_md_pdf_impl --theme red-gray slides.md
```

파일 인자가 없으면 현재 디렉토리의 `*.md` 파일을 모두 변환합니다.

### Beamer 슬라이드 모드 (기본값)

기본 pandoc 호출은 다음과 같습니다.

```bash
pandoc slides.md -o slides.pdf -t beamer --pdf-engine=xelatex \
  -V aspectratio=1610 \
  -V theme=Boadilla \
  -V colortheme=default \
  -V CJKmainfont="AppleGothic" \
  -V mainfont="AppleGothic" \
  -V monofont="Menlo" \
  --include-in-header="$temp_header"
```

비율은 16:10(`aspectratio=1610`)으로 맥북 화면에 맞춥니다. CJK 폰트는 `AppleGothic`, 모노스페이스는 `Menlo`, PDF 엔진은 `xelatex`이 고정입니다.

`temp_header`는 매번 임시 파일(`mktemp`)로 생성하고 변환 후 삭제합니다. 헤더에는 여백(`text margin left=1.5cm, text margin right=1.5cm`), 프레임 제목 서체(`\Large`, bold), 줄 간격(`\renewcommand{\baselinestretch}{2}`)이 공통으로 들어갑니다.

### Beamer 테마 옵션

`--theme Boadilla`(또는 테마 미지정)는 표준 Boadilla 테마에 공통 헤더(여백, 프레임 제목, 줄 간격)만 적용합니다.

`--theme warm`은 `\definecolor{beigecolor}{RGB}{250,245,230}`으로 미색 배경을 설정하고 `colortheme=seahorse`와 조합합니다. 출력이 따뜻한 계열로 보입니다.

`--theme red-gray`(또는 `red_gray`)는 커스터마이징 범위가 가장 넓습니다.

```latex
\definecolor{crimsoncolor}{RGB}{139,0,0}
\definecolor{lightgraycolor}{RGB}{230,230,230}
\setbeamercolor{frametitle}{bg=crimsoncolor,fg=white}
\setbeamercolor{title in head/foot}{bg=crimsoncolor,fg=white}
\setbeamercolor{section in head/foot}{bg=lightgraycolor,fg=crimsoncolor}
```

헤더 바, 푸터 바, 프레임 제목 배경이 crimson(RGB 139,0,0)과 light gray(RGB 230,230,230)로 구분됩니다. `\useoutertheme{infolines}`로 섹션 정보를 상단 바에 표시하고, 커스텀 `title page` 템플릿이 들어갑니다. 마크다운 YAML 헤더에 `event:` 필드가 있으면 타이틀 페이지 상단에 이벤트명을 별도로 렌더링합니다.

```zsh
# .md 파일 YAML 헤더
---
title: "Q2 성과 리뷰"
author: 홍길동
date: 2026-05-20
event: 전사 킥오프
---
```

`event_value`는 `grep -E "^event:"` + `sed`로 추출합니다.

표준 Beamer 테마(Madrid, Berlin, Copenhagen 등)는 `-V theme="$theme"`으로 그대로 pandoc에 전달합니다. 공통 헤더만 적용됩니다.

### 문서 모드 (`--doc`)

A4 세로 PDF를 생성합니다. Beamer 없이 일반 pandoc → xelatex 경로입니다.

```bash
pandoc report.md -o report.pdf --pdf-engine=xelatex \
  -V geometry:margin=2cm \
  -V CJKmainfont="AppleGothic" \
  -V mainfont="AppleGothic" \
  -V monofont="Menlo" \
  --wrap=preserve \
  -H "$temp_header"
```

헤더에는 `\usepackage{xeCJK}`, `\setlength{\parindent}{0pt}`, `\setlength{\parskip}{0.5em}`이 들어갑니다. 변환 실패 시 `-V CJKmainfont` 없이 재시도하는 폴백이 내장되어 있습니다.

```bash
pandoc "$file" -o "${file%.md}.pdf" --pdf-engine=xelatex \
  -V geometry:margin=2cm \
  -V mainfont="AppleGothic" \
  -V monofont="Menlo" \
  --wrap=preserve \
  -H "$temp_header"
```

CJK 폰트 설정이 없는 환경에서도 최소한의 PDF를 생성합니다.

---

## screenshot.zsh — macOS 스크린샷 설정 래퍼

`_screenshot`은 macOS `defaults write com.apple.screencapture` 커맨드를 감싸는 설정 관리 함수입니다. `alias screenshot='_screenshot'`으로 등록됩니다. 스크린샷을 찍는 함수는 아니고, macOS 스크린샷 동작을 구성하는 함수입니다.

```zsh
# 저장 경로 변경
screenshot -location ~/Pictures/Screenshots

# 파일 포맷 변경
screenshot -type jpg
screenshot -type png

# 미리보기 섬네일 표시 여부
screenshot -thumb false
screenshot -thumb true

# 현재 설정 조회
screenshot -get

# 도움말
screenshot -h
```

### 옵션 상세

**`-location <path>`:** 스크린샷 저장 디렉토리를 설정합니다. 경로가 존재하지 않으면 `mkdir -p`로 생성합니다. `~` 확장을 위해 `eval`을 사용합니다. `defaults write com.apple.screencapture location "$target"`을 호출합니다.

**`-type <포맷>`:** 허용값은 `png`, `jpg`, `jpeg`, `pdf`, `tiff`, `gif`, `heic`입니다. `jpeg`를 입력하면 `jpg`로 정규화합니다. 대소문자 구분 없이 받습니다.

**`-thumb <true|false>`:** 미리보기 섬네일 표시 여부를 설정합니다. `true/1/on/yes` → `TRUE`, `false/0/off/no` → `FALSE`로 변환 후 `defaults write com.apple.screencapture show-thumbnail -bool`을 호출합니다.

**`-get`:** 현재 설정된 location, type, thumbnail 값을 출력합니다. 설정이 없으면 macOS 기본값(`png`, Desktop)을 표시합니다.

```
location : /Users/jaesolshin/Pictures/Screenshots
type     : png
thumbnail: true
```

설정 변경(`-location`, `-type`, `-thumb`) 후에는 `killall SystemUIServer`를 실행해 변경 사항을 즉시 적용합니다.

---

## 묶어 쓰기

같은 마크다운 소스에서 여러 형태의 출력을 뽑습니다.

### 발표 준비: 슬라이드 + 문서 동시 생성

```zsh
# 한 파일에서 두 가지 PDF 생성
_md_pdf_impl --theme red-gray keynote.md    # 슬라이드 PDF
_md_pdf_impl --doc keynote.md               # A4 문서 PDF (배포용)
```

`keynote.pdf`가 슬라이드, 같은 이름의 두 번째 변환 결과가 A4 문서로 나옵니다. 실제로는 출력 경로가 겹치므로 `--output`으로 구분하거나 `md_to_pdf`의 `--output` 옵션을 사용합니다.

```zsh
# md_to_pdf 경로
md_to_pdf keynote.md --template metropolis --output keynote-slides.pdf

# md_pdf 문서 경로
_md_pdf_impl --doc keynote.md
mv keynote.pdf keynote-doc.pdf
```

### 스크린샷 출력 경로를 작업 폴더로 고정

콘텐츠 작업 중 스크린샷을 찍을 때 저장 경로를 자동으로 현재 프로젝트 폴더로 고정해두면 파일 이동 없이 바로 마크다운에서 참조할 수 있습니다.

```zsh
# 작업 시작 시 스크린샷 경로 설정
screenshot -location ~/Documents/GitHub/jaesolshin.com/public/images/posts/my-post
screenshot -type png
screenshot -thumb false
```

이후 Cmd+Shift+4로 찍은 스크린샷이 해당 디렉토리에 바로 저장됩니다. 작업이 끝나면 경로를 되돌립니다.

```zsh
screenshot -location ~/Desktop
screenshot -thumb true
```

### LaTeX 중간 파일 확인

pandoc이 생성하는 `.tex`을 보고 싶을 때는 `--tex-only`를 씁니다.

```zsh
md_to_pdf presentation.md --tex-only
# presentation.tex 생성, PDF 컴파일은 건너뜀
```

Beamer 레이아웃을 수동 조정하거나 헤더 커스터마이징을 디버그할 때 유용합니다.

---

## 운영상 주의

### 의존성

`md_to_pdf`(`marp.zsh`)는 `$MD_LATEX_PATH/.venv`가 존재해야 합니다. 가상환경이 없으면 함수 시작 시점에 오류를 반환합니다.

```
오류: 가상환경을 찾을 수 없습니다: /Users/jaesolshin/Documents/GitHub/md_latex/.venv
```

`_md_pdf_impl`(`md_pdf.zsh`)은 시스템 pandoc과 XeLaTeX이 필요합니다.

```zsh
# macOS (Homebrew)
brew install pandoc
brew install --cask mactex     # 또는 BasicTeX
```

BasicTeX를 설치한 경우 Beamer 패키지가 없을 수 있습니다. `tlmgr install beamer`로 추가합니다.

### 한글 폰트

두 스크립트 모두 `AppleGothic`을 CJK 폰트로 지정합니다. macOS에는 기본 탑재되어 있지만, Linux CI 환경이나 Docker 컨테이너에서는 누락됩니다. 이 경우 pandoc 호출의 `-V CJKmainfont`를 시스템에 설치된 폰트명으로 교체해야 합니다.

```zsh
# 설치된 폰트 확인
fc-list :lang=ko
```

`_md_pdf_impl`의 `--doc` 모드는 CJK 폰트 설정 실패 시 폴백 변환을 시도합니다. Beamer 모드에는 폴백이 없으므로 폰트가 없으면 xelatex 컴파일 오류가 발생합니다.

### 환경별 PDF 엔진

두 스크립트 모두 `--pdf-engine=xelatex`를 사용합니다. `pdflatex`나 `lualatex`로 교체하면 CJK 지원이 달라집니다. xelatex 없이 lualatex만 있는 환경에서는 pandoc 호출의 `--pdf-engine` 값을 교체하고, 헤더의 `\usepackage{xeCJK}` 대신 `luatexja` 계열 패키지를 써야 합니다.

### `screenshot.zsh`와 SystemUIServer

`-location`, `-type`, `-thumb` 변경 후 `killall SystemUIServer`를 자동으로 실행합니다. Dock, 메뉴바 아이콘 등 SystemUIServer에 의존하는 프로세스가 잠깐 재시작됩니다. 자동으로 복원되므로 정상 동작입니다.

`defaults write`는 `~/Library/Preferences/com.apple.screencapture.plist`에 기록하므로 재부팅 후에도 유지됩니다. 기본값으로 되돌리려면 `defaults delete com.apple.screencapture <key>`를 씁니다.
