이 글은 Charlotte Wickham이 SciPy 2025에서 발표한 “한 개의 노트북에서 여러 보고서로: Quarto로 자동화하기”를 바탕으로 작성했습니다.
슬라이드는 cwickham.github.io/one-notebook-many-reports에서, 예제 코드는 github.com/cwickham/one-notebook-many-reports에서 확인할 수 있습니다.
문제: 반복적인 보고
“일반적인 기후 요약”을 읽고 싶으신가요, 아니면 “정확히 당신이 사는 지역을 위한 기후 요약”이 더 마음에 드시나요? 특정 상황에 맞춘 맞춤형 보고서는 참여자와의 연결감을 높여줍니다. 하지만 수동으로 수십 개의 맞춤 보고서를 만들려면 지루하고 실수하기 쉽습니다.
Quarto는 파라미터화된 보고서를 통해 이 문제를 해결합니다. 하나의 문서 템플릿을 만들고, 파라미터 값만 바꿔서 여러 번 렌더링하면 맞춤 출력물이 자동으로 생성됩니다.
훌륭한 예제로, Jadey Ryan이 posit::conf(2023)에서 소개한 Washington Soil Health Initiative의 State of the Soils Assessment 맞춤 토양 건강 보고서를 들 수 있습니다(소개 영상: YouTube). Jadey는 이 접근법을 R과 일반 텍스트 Quarto 파일(.qmd)로 시연했습니다.
이 글에서는 같은 원리를 Python으로 적용하는 방법을 소개합니다. Jupyter 노트북(.ipynb)을 파라미터화된 보고서로 바꾸고, 여러 맞춤 출력물을 자동으로 생성하는 과정을 따라갑니다. 끝으로 보고서를 더 다듬어 보이게 만드는 팁도 알려드립니다.
해결책: 파라미터화된 보고서
노트북부터 시작
예제로 오리건주 코발리스의 기후 데이터를 분석하는 Jupyter 노트북을 살펴보겠습니다.
전체 노트북은 GitHub의 corvallis.ipynb에서 확인할 수 있지만, 핵심 부분은 다음과 같습니다:
코드 셀은 오리건 전체 데이터를 가져와 코발리스에 해당하는 행만 필터링한 뒤, 요약 문장과 플롯을 생성합니다.
문서 옵션에서
echo: false를 지정해 최종 출력에 코드가 나타나지 않도록 하고,format: typst를 지정해 현대적인 LaTeX 대안인 Typst로 PDF를 생산합니다.
이 노트북 하나는 Quarto로 렌더링할 수 있습니다:
Terminal
quarto render corvallis.ipynb 결과물은 corvallis.pdf라는 PDF로, 제목 “Corvallis”와 기후 데이터를 한 문장으로 요약한 내용, 그리고 지난 30년과 비교해 올해 평균 기온을 강조한 플롯을 담은 간단한 보고서입니다.
이제 이 보고서를 오리건에서 가장 큰 50개 도시마다 만들고 싶다고 생각해보세요. 다음과 같은 단계를 따릅니다:
- 하드코딩된 값을 변수로 바꾸기
- 해당 변수를 파라미터로 선언하기
- 서로 다른 파라미터 값으로 노트북 렌더링하기
- 다양한 파라미터 값으로 렌더링 자동화하기
1. 하드코딩된 값을 변수로 바꾸기
도시별 보고서를 만들고자 합니다. 우선 파라미터로 지정할 city라는 변수를 생성합니다. 노트북 상단에 새로운 코드 셀을 만들고 변수를 정의합니다:
code
city = "Corvallis"이후 노트북에서 "Corvallis"을 직접 쓴 곳은 모두 city 변수로 바꿉니다.
첫 번째 등장 위치는 문서 제목입니다. 원래는 다음과 같은 level 1 heading 마크다운 셀이 있었습니다:
markdown
# Corvalliscity 변수를 기반으로 f-string으로 level 1 heading을 생성하는 코드 셀로 바꿉니다:
code
Markdown(f"# {city}")필터링 단계에서는 문자열을 변수로 바꾸는 것이 간단합니다:
Before:
code
tmean = tmean_oregon.filter(
pl.col("city") == "Corvallis",
)After:
code
tmean = tmean_oregon.filter(
pl.col("city") == city,
)마지막으로, plotnine을 사용하는 플롯 코드에서는 제목에 도시 이름을 포함합니다:
code
...
+ labs(title = "Corvallis, OR", ...)
...여기에도 city 변수를 포함한 f-string을 사용할 수 있습니다:
code
...
+ labs(title = f"{city}, OR", ...)
...이제 city 변수를 “Corvallis”가 아닌 값으로 설정한 뒤 셀을 다시 실행하면 변경을 테스트할 수 있습니다. 보고서가 더 이상 코발리스에만 국한되지 않으므로 파일명을 climate.ipynb로 바꿀 수 있습니다.
2. 변수에 파라미터 태그를 지정
파라미터를 나타내는 변수를 만들었으니 Quarto에도 파라미터라는 사실을 알려야 합니다. Quarto의 파라미터화된 보고서는 Papermill을 사용하며, Papermill 방식과 동일하게 파라미터를 정의한 셀에 parameters 태그를 붙입니다.
Jupyter에서는 셀 도구 모음에서 이 태그를 추가할 수 있습니다:
파라미터화된 노트북으로 바뀐 전체 내용은 GitHub의 climate.ipynb에서 확인할 수 있습니다.
3. 서로 다른 파라미터 값으로 렌더링
climate.ipynb를 렌더링하면 파라미터 값을 변경하지 않았기 때문에 여전히 코발리스 보고서가 생성됩니다:
Terminal
quarto render climate.ipynb이제 -P 플래그를 사용해 Quarto에 파라미터 값을 전달할 수 있습니다:
Terminal
# Generate report for Portland
quarto render climate.ipynb -P city:Portland --output-file portland.pdf
# Generate report for Eugene
quarto render climate.ipynb -P city:Eugene --output-file eugene.pdf각 보고서에 고유한 파일 이름이 지정되도록 --output-file도 추가했습니다.
4. 여러 파라미터 값으로 렌더링 자동화
50개 보고서를 모두 만들려면 quarto render를 50번 실행하고, 매번 다른 도시 이름을 파라미터 값으로 넘겨야 합니다. 이 과정을 여러 방식으로 자동화할 수 있지만, 여기서는 Python 스크립트를 사용합니다. 예를 들어 도시 이름과 출력 파일 이름을 담은 데이터셋을 준비할 수 있습니다:
gen-reports.py
cities = pl.DataFrame({
"city": ["Portland", "Cottage Grove", "St. Helens", "Eugene"],
"output_file": ["portland.pdf", "cottage_grove.pdf", "st_helens.pdf", "eugene.pdf"]
})위에서는 작은 예시만 만들었지만 실제로는 파일에서 cities 데이터를 읽어올 것입니다. 그다음 각 행을 순회하며 도시마다 노트북을 렌더링할 수 있습니다:
gen-reports.py
from quarto import render
for row in cities.iter_rows(named=True):
render(
"climate.ipynb",
execute_params={"city": row["city"]},
output_file=row["output_file"],
)이 스크립트를 한 번 실행하면 50개 맞춤 보고서를 모두 생성할 수 있습니다!
전체 작업 예시는 GitHub의 cwickham/one-notebook-many-reports/03-many-reports에서 볼 수 있습니다.
보기 좋은 보고서: 브랜드와 Typst
위에서 설명한 파라미터화된 보고서 제작 단계는 Quarto가 지원하는 모든 출력 형식에 적용됩니다. 그중 typst를 목표로 삼는다면 추가 기능을 활용해 더욱 아름다운 PDF 보고서를 만들 수 있습니다.
Brand.yml
Quarto는 색상, 글꼴, 로고를 지정할 수 있는 brand.yml을 지원합니다:
_brand.yml
color:
palette:
forest-green: "#2d5a3d"
charcoal-grey: "#555555"
foreground: charcoal-grey
primary: forest-green
typography:
fonts:
- family: Open Sans
source: google
base:
family: Open Sans
logo:
medium: logo.pngQuarto는 _brand.yml 파일을 감지해 보고서에 색상, 글꼴, 로고를 적용합니다. 도표의 색상과 글꼴은 코드에서 직접 커스터마이즈해야 하지만, _brand.yml의 값을 가져오는 brand-yml Python 패키지가 있어 작업이 훨씬 쉬워집니다.
climate.ipynb와 _brand.yml을 함께 사용한 전체 예시는 cwickham/one-notebook-many-reports/04-branded-reports에서 확인할 수 있으며, Quarto의 브랜드 지원에 대해서는 Brand guide를 참고하세요.
Typst
Typst 문법을 조금 익히면 보고서가 단순한 수준에서 벗어나 아름답게 바뀝니다. 노트북에 raw Typst 구문을 포함하거나 typst-function Quarto 확장을 활용해 요소를 Typst 함수로 감쌀 수도 있습니다. 예를 들어 도시 이름이 들어간 헤더와 위치 지도의 조합을 추가할 수 있습니다:
이 예제의 소스는 cwickham/one-notebook-many-reports/05-pretty-reports에서 확인할 수 있습니다.
jupyter vs knitr
앞에서 설명한 파라미터화된 보고서 제작 단계는 jupyter 엔진을 사용하는 문서에 해당합니다. Jupyter 노트북(.ipynb)이나 Python 코드 셀만 포함한 일반 텍스트 Quarto 문서(.qmd)에서는 Quarto가 기본적으로 jupyter 엔진을 사용합니다. 앞서 설명했듯 jupyter 엔진에서는 셀 태그를 통해 파라미터를 식별합니다.
.ipynb 파일에서는 IDE에서 셀 도구 모음을 통해 이러한 태그를 추가할 수 있는 기능을 제공할 가능성이 높습니다. .qmd 파일에서 작업 중이라면 코드 셀 옵션으로 태그를 지정할 수 있습니다:
```{python}
#| tags: [parameters]
city = "Corvallis"
```jupyter 엔진에서는 이후 코드 셀에서 city처럼 변수로 파라미터를 바로 참조할 수 있습니다.
R 코드 셀을 포함한 Quarto 문서(.qmd)에서는 Quarto가 기본적으로 knitr 엔진을 사용합니다. knitr 엔진에서는 문서 헤더의 params 아래에 파라미터를 설정합니다:
---
params:
city: "Corvallis"
---knitr에서는 params$city처럼 params 요소로 파라미터를 참조합니다.
파라미터 설정과 사용에 대해서는 Guide > Computations > Parameters를 참고하세요.
마무리하며
파라미터화된 보고서는 하나의 노트북을 수많은 맞춤 출력물로 만듭니다. 하드코딩된 값을 가진 노트북을 시작으로 서로 다른 값으로 렌더링 가능한 파라미터화된 보고서로 바꾸는 과정을 살펴보았습니다. 이후에는 원하는 방식으로 렌더링을 자동화해 수십 개의 보고서를 한꺼번에 생성할 수 있습니다.



