쿼토 (Quarto)

이 장에서는 워크플로우: 코드 작성하기 (Workflow: Writing Code) 에서의 짧은 소개에 이어 Quarto에 대해 더 깊이 알아보겠습니다. Quarto는 코드와 텍스트( 마크다운 (Markdown) 에서 다룬 마크다운 형식)를 결합하여 리포트나 프레젠테이션과 같은 풍부한 출력물을 만들 수 있게 해주는 도구입니다.

서론

Quarto는 데이터 과학을 위한 통합 저작 프레임워크로, 여러분의 코드, 코드 실행 결과, 그리고 산문 형태의 설명을 하나로 결합합니다. Quarto는 완전한 재현성을 보장하며 PDF, 마이크로소프트 워드 파일, 슬라이드쇼 등 수십 가지 출력 포맷을 지원합니다.

Quarto 마크다운은 크게 세 가지 용도로 설계되었습니다:

  1. 분석 뒤에 숨겨진 코드가 아니라 결론에 집중하고 싶어 하는 의사 결정권자들과 소통하기 위해서입니다.

  2. 여러분의 결론뿐만 아니라 그 결론에 어떻게 도달했는지(즉, 코드)에도 관심이 있는 다른 데이터 과학자들(미래의 본인 포함!)과 협업하기 위해서입니다.

  3. 여러분이 무엇을 했는지뿐만 아니라 무슨 생각을 했는지까지 기록할 수 있는 현대적인 실험 노트로서, 데이터 과학을 수행하기 위한 환경으로 사용하기 위해서입니다.

예를 들어, 최신 무역 통계를 탐색하는 기술 리포트를 작성할 때 코드 부분에서 최신 데이터를 가져와 플롯을 그리는 유스케이스가 있을 수 있습니다. 또는 동일한 분석을 수행하여 웹사이트에 게시할 수도 있습니다. 무엇보다도 최종 출력물에서 코드 부분을 숨길지 보여줄지 결정할 수 있습니다(또는 html 출력의 경우 사용자가 코드를 볼지 말지 선택하게 할 수도 있습니다). 더 자세한 유스케이스는 다음과 같습니다:

  • 실행할 때마다 데이터나 차트가 비슷하게 사용되는 리포트 (예: 데이터만 업데이트되는 경우)

  • 기존 코드 베이스의 기능을 보여주거나 사용하는 기술 리포트

  • 최신 데이터를 요약하고 정기적으로 생성되는 슬라이드 덱

  • 탐색적 또는 프로토타입 분석 결과를 공동 저자나 협업자에게 보내기

  • .md 파일을 허용하는 블로그 서비스에 블로그 글 쓰기 (마크다운으로 내보내기 필수)

  • 자동으로 업데이트되는 웹사이트를 비교적 쉽게 만들기——이 장에서는 다루지 않지만, 여기에서 관련 정보를 찾을 수 있습니다.

Quarto는 자동화된 리포트를 편리하게 제작할 수 있게 해주는 여러 도구들의 아주 유용한 래퍼(wrapper)입니다. 최신 사용 가이드는 공식 문서를 확인해야 합니다——여기서는 기초를 살펴보고 유용하게 쓰일 몇 가지 템플릿을 소개하겠습니다.

사전 준비

먼저 Quarto 웹사이트에 접속하여 설치 지침을 따라야 합니다. 명령줄에서 quarto check install을 실행하여 제대로 설치되었는지 확인할 수 있습니다.

또한 Visual Studio Code의 quarto 익스텐션이 유용하므로 설치를 권장합니다. 이 익스텐션은 Visual Studio Code 내에 “render”라는 특별한 버튼을 만들어주어, 입력 파일과 출력 결과물이 나란히 보이도록 해줍니다.

Quarto를 이용한 자동화된 리포트

Quarto는 HTML, PDF, 마이크로소프트 오피스(docx 및 pptx), 오픈오피스 등 매우 다양한 포맷의 출력 문서와 슬라이드를 만드는 데 사용될 수 있습니다.

입력 문서(코드 스니펫 포함)를 작성하는 방법은 크게 두 가지가 있습니다:

  1. 확장자가 .qmd인 특별한 종류의 마크다운 파일입니다. 마크다운에 대한 자세한 내용은 마크다운 (Markdown) 을 참조하세요. 특별한 구문을 가진 코드 블록이 실행되고 그 결과가 출력물에 포함됩니다.

  2. 확장자가 .ipynb인 주피터 노트북입니다. 코드 셀이 실행되고 그 결과가 출력물에 포함됩니다.

선택적으로 문서에 코드(예: 파이썬, R, 자바스크립트 등)를 추가하여 피겨, 표 등을 동적으로 생성한 다음 Quarto를 사용하여 최종 포맷으로 렌더링 할 수 있습니다.

마크다운 콘텐츠로 작성된 리포트의 최소 예제

이제 코드와 출력을 포함하는 첫 번째 방식인 .qmd 파일의 가장 최소화된 예제를 시도해 보겠습니다.

리포트를 .qmd 포맷으로 작성하는 것에는 장단점이 있습니다. 장점은 단순히 평범한 텍스트 파일이므로 누구나 텍스트 에디터로 열어보고, 살펴보고, 수정할 수 있다는 점입니다(또한 버전 관리 시에도 이 방식이 더 편리합니다). 아주 큰 단점은 작성하는 동안 코드가 어떻게 되어가고 있는지 실시간으로 볼 수 없다는 점입니다(잠시 후에 보겠지만 코드 출력을 확인하려면 렌더링을 해야 합니다). 다음 하위 섹션에서 더 나은 워크플로우를 달성하는 방법을 살펴보겠습니다.

최소 예제를 설정해 봅시다. 아래의 코드와 마크다운은 report.qmd라는 파일의 내용입니다:

---
title: "리포트 예제"
author: "조안 로빈슨"
format: pdf
toc: true
number-sections: true
jupyter: python3
---

## 극좌표 축 (Polar Axis)

극좌표 축에서의 선 그래프 데모는 @fig-polar를 참조하세요.

::: {#cell-fig-polar .cell execution_count=1}
``` {.python .cell-code}
import numpy as np
import matplotlib.pyplot as plt

r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.plot(theta, r)
ax.set_rticks([0.5, 1, 1.5, 2])
ax.grid(True)
plt.show()
Figure 34.1: 극좌표 축의 선 그래프

:::


이 예제에는 세 가지 중요한 유형의 콘텐츠가 포함되어 있습니다:

1.  `---`로 둘러싸인 **YAML 헤더**.
2.  ```` ``` ````로 둘러싸인 파이썬 **코드 청크**.
3.  `# 제목` 및 `_기울임꼴_`과 같이 단순한 텍스트 서식이 섞인 마크다운.

이 '가공되지 않은' 입력 쿼토 마크다운 `.qmd` 파일에서 `{python}`은 **Quarto**에게 해당 코드 청크가 파이썬이며 실행되어야 함을 알려주고, `jupyter: python3`은 **Quarto**에게 어떤 주피터 노트북 설치본을 사용할지 알려줍니다. 본인의 주피터 설치본 이름이 무엇인지 확실하지 않다면, 명령줄에서 `jupyter kernelspec list`를 실행하여 목록을 확인할 수 있습니다.

### 출력 문서로 렌더링하기

위의 리포트를 출력 PDF로 바꾸려면, `report.qmd`로 저장한 다음 해당 파일이 있는 디렉토리의 명령줄에서 다음을 실행하세요.

```{bash}
quarto render report.qmd

만약 Visual Studio Code의 quarto 익스텐션을 사용 중이라면(권장), 렌더 버튼을 누르면 됩니다(단, 출력 형식을 PDF로 선택해야 합니다).


위의 마크다운 내용을 `report.qmd` 파일로 저장하여 PDF를 성공적으로 생성해 보세요.

만약 주피터 커널을 찾을 수 없다는 에러가 발생하면, 먼저 Jupyter Lab이 설치되어 있는지 확인한 다음 명령줄에서 `jupyter kernelspec list`를 실행하여 주피터 커널의 이름을 확인하세요. 헤더 문서에 주피터 커널의 이름을 정확히 지정해야 합니다(위의 예제에서는 기본값인 'python3'입니다).

이제 파일의 ’헤더’에 pdf를 지정했으므로 자동으로 pdf를 얻었습니다. 하지만 다양한 출력 포맷을 사용할 수 있습니다. 예를 들어, HTML의 경우:

quarto render report.qmd --to html

마이크로소프트 워드의 경우:

quarto render report.qmd --to docx

워드 문서로 변환할 때 한 가지 아쉬운 점은 코드에서 생성된 표(데이터 프레임)가 워드 문서 내에서 표 형식으로 렌더링 되지 않는다는 점입니다.

기본 구문은 렌더 명령어 끝에 --to 출력포맷을 붙이는 것입니다.


### 연습 문제

위의 마크다운 내용을 `report.qmd`로 저장하고 quarto render 명령에 to html 옵션을 사용하여 HTML 리포트를 성공적으로 생성해 보세요.

`##` 마크다운 구문을 사용하여 추가 제목을 더할 때 오른쪽 메뉴에 어떤 변화가 생기나요?

코드 블록 실행 옵션

코드 블록이 실행되는 방식에 대해 다양한 옵션이 있습니다. 실행되지 않는 코드 블록을 포함하려면 일반적인 마크다운 구문(즉, ```python으로 시작하는 블록)을 사용하면 됩니다. 실행되는 블록의 경우, 입력 코드를 보여줄지, 결과만 보여줄지, 둘 다 보여줄지, 아니면 (코드는 실행하면서) 둘 다 숨길지에 대한 풍부한 옵션이 있습니다.

입력 코드는 숨기고 결과만 보여주는 예로, 아래 코드는 echo: false 옵션을 사용하여 결과 표 보여줍니다.


::: {#d503254c .cell execution_count=2}

::: {.cell-output .cell-output-display execution_count=2}
```{=html}
<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead tr th {
        text-align: left;
    }

    .dataframe thead tr:last-of-type th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr>
      <th>island</th>
      <th colspan="2" halign="left">Biscoe</th>
      <th colspan="2" halign="left">Dream</th>
      <th colspan="2" halign="left">Torgersen</th>
      <th>All</th>
    </tr>
    <tr>
      <th>sex</th>
      <th>Female</th>
      <th>Male</th>
      <th>Female</th>
      <th>Male</th>
      <th>Female</th>
      <th>Male</th>
      <th></th>
    </tr>
    <tr>
      <th>species</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Adelie</th>
      <td>22</td>
      <td>22</td>
      <td>27</td>
      <td>28</td>
      <td>24</td>
      <td>23</td>
      <td>146</td>
    </tr>
    <tr>
      <th>Chinstrap</th>
      <td>0</td>
      <td>0</td>
      <td>34</td>
      <td>34</td>
      <td>0</td>
      <td>0</td>
      <td>68</td>
    </tr>
    <tr>
      <th>Gentoo</th>
      <td>58</td>
      <td>61</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>119</td>
    </tr>
    <tr>
      <th>All</th>
      <td>80</td>
      <td>83</td>
      <td>61</td>
      <td>62</td>
      <td>24</td>
      <td>23</td>
      <td>333</td>
    </tr>
  </tbody>
</table>
</div>

::: :::


아래 표는 코드 블록에 대한 모든 옵션을 제공합니다.

| 옵션 | 설명 |
|---|---|
| `eval` | 코드 청크를 평가함 (false인 경우 코드를 출력물에 그대로 표시만 함). |
| `echo` | 출력물에 소스 코드를 포함함 |
| `output` | 출력물에 코드 실행 결과를 포함함 (true, false, 또는 asis. asis는 출력이 원시 마크다운이며 Quarto의 표준 마크다운 감싸기를 적용하지 않아야 함을 의미함). |
| `warning` | 출력물에 경고를 포함함. |
| `error` | 출력물에 에러를 포함함 (이는 코드 실행 중 에러가 발생해도 문서 처리를 중단하지 않음을 의미함). |
| `include` | 모든 출력(코드 및 결과)이 포함되지 않도록 하는 포괄적인 설정 (예: include: false는 코드 블록의 모든 출력을 억제함). |
| `true` | 참 |
| `false` | 거짓 |

### 텍스트 내 인라인 코드 사용
 
 또한 **텍스트 중간에 코드 결과를 삽입하는 것도 가능합니다**. 다음은 그 최소 예제입니다.

```{.callout-note}
---
title: "텍스트 내에 코드 숫자가 포함된 리포트 예제"
author: "조안 로빈슨"
format: pdf
toc: true
number-sections: true
jupyter: python3
---

## 리포트

극좌표 축에서의 선 그래프 데모는 @fig-polar를 참조하세요.

입력 코드는 표시되지 않는 코드 출력 예제로, 아래 코드는 `echo: false` 옵션을 사용하여 결과 표만 표시합니다.



### 가장 무거운 펭귄

총 `python f"{number}"`마리의 펭귄 중에서 가장 무거운 펭귄의 몸무게는 `python f"{big_pen:.2f}"` 킬로그램임을 확인했습니다.

이 예제에서 {big_pen:.2f}:2f 부분은 해당 숫자를 소수점 둘째 자리까지 표시하라는 지시임에 유의하세요.


### 연습 문제

위의 예제를 사용하여 인라인 숫자가 포함된 HTML 리포트를 만들되, 가장 무거운 펭귄의 몸무게 서식을 소수점이 보이지 않도록 변경해 보세요.

물론 이 예제 외에도 수많은 추가 기능들이 있습니다.

주피터 노트북으로 작성된 리포트의 최소 예제

주피터 노트북으로도 리포트를 작성할 수 있습니다. 다시 말씀드리면, 주피터 노트북은 텍스트(마크다운 형식) 또는 코드(수많은 언어 지원)가 들어가는 셀들로 구성되며, 파일 포맷은 .ipynb입니다. 이 책은 Visual Studio Code에서 노트북으로 작업하는 것을 권장합니다. Google Colab 노트북 또한 주피터 노트북의 한 종류입니다(.ipynb 파일로 다운로드 가능).

자동화된 리포트를 작성할 때 주피터 노트북을 사용하는 것은 .qmd 마크다운 파일을 사용하는 것에 비해 큰 장점이 있습니다: 작성하면서 코드를 즉시 실행해 볼 수 있으므로 어떤 결과를 얻을지 알 수 있고 버그를 잡아내기가 훨씬 쉽습니다. 이 책은 자동화된 리포트 작성 시 이 방식을 권장합니다.

그렇다면 앞서 본 것과 무엇이 다를까요? 실제로는 거의 차이가 없습니다. 여러분의 콘텐츠는 여전히 정확히 동일한 헤더로 시작하겠지만, 이번에는 노트북 최상단의 마크다운 셀에 들어갑니다. 명확히 하자면, 여러분의 노트북 첫 번째 셀은 다음 내용을 담게 됩니다:

---
title: "리포트 예제"
author: "조안 로빈슨"
format: pdf
toc: true
number-sections: true
jupyter: python3
---

이후의 셀들은 풍부한 결과물(피겨 및 표)이 필요한지 아니면 텍스트가 필요한지에 따라 코드 셀 또는 마크다운 셀이 됩니다. 따라서 .qmd 방식처럼 ```{python}으로 시작하는 코드 청크 대신, 단순히 새로운 코드 셀을 생성하면 됩니다.

이 헤더에 format: pdf를 넣으면 render 명령어가 자동으로 pdf를 생성한다는 점을 기억하세요. 기본값을 html 파일로 하려면 format: html로 바꿀 수 있습니다—두 옵션 모두 --to format을 전달하여 덮어쓸 수 있습니다.

이전과 마찬가지로 코드 출력으로 동적으로 업데이트되는 텍스트를 만들 수 있습니다. 마크다운 셀 대신 코드 셀을 선택하기만 하면 됩니다.

주피터 노트북의 주요 차이점은 렌더링 하기 전에 노트북을 실행(execute)할지 여부를 결정해야 한다는 것입니다. 노트북을 실행한다는 것은 다른 포맷으로 내보내기 전에 코드를 돌린다는 의미입니다. (참고로, 주피터 노트북을 사용하는 가장 좋은 방법은 코드 결과 없이 저장하는 것이며, 따라서 실행 후 렌더링 하는 것이 표준적인 방법입니다.) 노트북을 실행하고 렌더링 하는 터미널 명령어는 다음과 같습니다:

quarto render jupyter-report.ipynb --execute

### 연습 문제

위의 헤더를 사용하여 `jupyter-report.ipynb`라는 이름의 새로운 주피터 노트북을 만드세요. 이전 섹션의 `qmd` 예제에 있는 코드와 텍스트 블록들을 재사용하세요. 위의 명령어로 렌더링 해보세요.

출력 타입을 바꾸려면 명령에 --to를 사용하여 다른 지시를 추가하세요:

quarto render jupyter-report.ipynb --execute --to html

자동화된 리포트 작성을 위한 최적의 워크플로우

이는 Visual Studio Code의 Quarto 익스텐션을 사용하는 방식의 대안입니다.

이제 자동화된 리포트와 슬라이드를 만들기 위한 최적의 워크플로우에 대한 큰 팁을 드리겠습니다. 종종 코드를 변경함에 따라 최종 리포트가 어떻게 보일지 실시간으로 확인하고 싶을 때가 있습니다. 주피터 노트북과 Quarto를 사용하면 이것이 가능합니다. 터미널에 다음을 실행하세요.

quarto preview jupyter-report.ipynb

브라우저 창이 열리면서 pdf의 라이브 프리뷰가 나타날 것입니다(헤더에서 pdf를 기본 출력 옵션으로 설정한 경우). HTML 문서의 라이브 프리뷰를 만들려면 다음과 같이 합니다.

quarto preview jupyter-report.ipynb --to html
### 연습 문제
이전 연습의 주피터 예제를 가져와 포맷을 HTML로 변경하세요. 그런 다음 프리뷰 모드에서 위의 `quarto preview` 명령어를 사용하여 새로운 텍스트 셀과 (코드 셀로부터의) 새로운 피겨를 모두 추가해 보세요. 새로운 피겨에 대한 아이디어가 필요하다면 여기 간단한 산점도 코드가 있습니다:

```python
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter(
    [1, 2, 3, 4, 5, 6],
    [1, 4, 2, 3, 1, 7],
    s=np.linspace(300, 2000, 6),
    c=["b", "r", "g", "k", "cyan", "yellow"],
    edgecolors="k",
    alpha=0.5,
)
plt.show()

## **Quarto**를 이용한 자동화된 슬라이드

리포트뿐만 아니라 슬라이드 덱도 만들 수 있습니다. 슬라이드를 위한 세 가지 주요 출력 포맷을 선택할 수 있습니다:

- 'revealjs'를 통한 html: `format: revealjs` 사용
- LaTeX beamer 패키지를 통한 pdf: `format: beamer` 사용
- pptx 포맷을 사용한 파워포인트: `format: pptx` 사용

그 외의 모든 것은 이전에 본 것과 동일합니다. 코드와 텍스트를 모두 포함하는 최소 예제입니다. HTML 슬라이드 덱을 생성합니다.

```{.callout-note}
---
title: "나의 발표"
author: "조안 로빈슨"
format: revealjs
---

## 서론

- 이것은 텍스트입니다
- 이것도 마찬가지입니다

## 여기에 코드 결과물이 나옵니다

::: {#68aec7ee .cell execution_count=4}

::: {.cell-output .cell-output-display}
![](quarto_files/figure-html/cell-5-output-1.png){width=450 height=439}
:::
:::

코드 청크에 #| echo: false를 설정했으므로 코드는 표시되지 않고 피겨만 나타납니다. 헤더에서 덱 전체에 대해 echo: false를 설정할 수도 있습니다.


### 연습 문제
이 슬라이드 예제를 세 가지 주요 포맷 모두로 렌더링 해보세요.

### 연습 문제
이전의 가장 무거운 펭귄 예제를 활용하여, 렌더링 된 덱에 인라인 코드의 출력 결과를 추가해 보세요.