Continuous Integration(CI)으로 배포
개요
Continuous Integration(CI)은 버전 관리 시스템에 체크인된 코드에서 콘텐츠를 자동으로 배포하는 관행을 말합니다. CI를 사용한 배포는 설정이 조금 더 복잡하지만 다음과 같은 장점이 있습니다.
소스 코드가 변경될 때마다 콘텐츠가 자동으로 배포됩니다(명시적으로 렌더링할 필요 없음).
다른 시스템에서 렌더링하면 코드 재현성을 보장할 수 있습니다(다만 렌더링에 특별한 요구 사항이 있다면 양날의 검이 될 수 있으니 아래의 CI 렌더링 논의를 참고하세요).
렌더링 출력물을 버전 관리에 포함하지 않으면 diff가 작아지고 병합 충돌이 줄어듭니다.
이 문서는 GitHub Actions(GitHub에서 제공하는 서비스), 일반 셸 명령(모든 CI 서비스에서 활용 가능), Posit Connect를 사용해 Quarto CI를 구현하는 방법을 다룹니다.
CI 렌더링
CI 서버를 사용하기 전에 실행 가능한 코드(R, Python, Julia 등)와 quarto render를 어디에서 실행할지 생각해야 합니다. 모든 것을 CI 서버에서 실행하는 것이 좋다고 직관적으로 생각할 수 있지만, 그렇게 하면 여러 가지 복잡성이 생깁니다.
CI 환경에 적절한 Quarto 버전이 있어야 합니다.
CI 환경에서 모든 의존성(필요한 R, Python, Julia 패키지)을 재현해야 합니다.
코드가 특별한 권한(예: 데이터베이스 또는 네트워크 접근)을 요구한다면 그 권한도 CI 서버에 있어야 합니다.
프로젝트에 더 이상 쉽게 실행할 수 없는 문서(예: 오래된 패키지 버전을 사용하는 몇 년 전 블로그 글)가 있을 수 있습니다.
위 내용을 고려하면 렌더링은 모든 것을 로컬에서 실행하는 것( quarto render 포함)부터 모든 것을 CI에서 원격 실행하는 것까지의 연속선으로 볼 수 있습니다.
로컬 실행 및 렌더링 — 로컬 환경에서 모두 실행한 후 출력물(예:
_site디렉터리)을 버전 관리에 포함합니다. 이 시나리오에서 CI 서버는 커밋마다 체크인된 콘텐츠가 올바른 위치에 복사/배포되도록 보장만 합니다. CI 서버에 필요한 소프트웨어 요구 사항을 최소화하고 싶다면 이 방법을 선택할 수 있습니다.로컬 실행 + CI 렌더링 — R, Python, Julia 코드를 로컬에서 실행하고 Quarto의 계산 출력 동결 기능으로 계산 결과를
_freeze디렉터리에 저장합니다. CI 서버에서 사이트를 렌더링하면_freeze에 저장된 계산 결과를 사용합니다. CI 서버에서 코드를 완전 재실행하기 어렵다면 이 방법을 사용하세요.CI 실행 및 렌더링 — 모든 코드를 CI 서버에서 실행하고 렌더링합니다. 이는 자동화와 재현성의 표준이지만, R/Python/Julia 의존성을
renv.lock또는requirements.txt같은 파일로 고정하고 CI 서버에 설치하도록 구성해야 합니다. 또한 코드에 필요한 권한(예: 데이터베이스 접근)이 CI 서버에 있어야 합니다.
아래에서는 GitHub Actions, 일반 셸 명령 (모든 CI 환경에서 응용 가능), Posit Connect를 사용해 각 전략을 구현하는 방법을 설명합니다.
GitHub Actions
GitHub Actions는 GitHub의 CI 서비스이며, 소스 코드가 GitHub 저장소에서 관리된다면 훌륭한 선택입니다. Quarto는 Quarto 설치와 콘텐츠 렌더링/배포를 쉽게 해주는 표준 GitHub Actions를 제공합니다.
다양한 배포 서비스에서 GitHub Actions를 사용하는 방법은 다음을 참고하세요.
표준 Quarto 액션을 다른 워크플로에 사용하려면 Quarto용 GitHub Actions 저장소를 참고하세요.
Posit Connect
소스 코드 형태의 콘텐츠를 Posit Connect에 배포한다면, Connect가 Git 저장소에서 코드를 가져와 Connect 서버에서 렌더링/실행하도록 구성할 수 있습니다.
자세한 내용은 Posit Connect의 Git 기반 콘텐츠 문서를 참고하세요.
셸 명령
이 섹션은 사용자 상호작용이 불가능한 서버에서 quarto publish 명령을 사용하는 방법을 다룹니다. 다음 단계가 포함됩니다.
- 콘텐츠 렌더링
- 배포 대상 지정(서비스/서버, 배포 대상 id 등)
- 배포 자격 증명 제공
예를 들어 다음은 프로젝트 루트의 _publish.yml 파일 정보를 기반으로 Netlify에 배포하는 셸 스크립트입니다.
Terminal
# credentials from https://app.netlify.com/user/applications
export NETLIFY_AUTH_TOKEN="45fd6ae56c"
# publish to the netlify site id provided within _publish.yml
quarto publish netlify_publish.yml의 내용은 다음과 같습니다.
- source: project
netlify:
- id: "5f3abafe-68f9-4c1d-835b-9d668b892001"
url: "https://tubular-unicorn-97bb3c.netlify.app"다음은 명령줄에서 배포 대상을 지정하는 다른 변형입니다.
Terminal
quarto publish netlify --id 5f3abafe-68f9-4c1d-835b-9d668b892001아래에서 배포 스크립트의 구성 요소와 함께 추가적인 완전한 예시를 제공합니다.
배포를 위한 렌더링
기본적으로 배포 명령을 실행하면 사이트나 문서가 자동으로 다시 렌더링됩니다.
Terminal
quarto publish이는 최신 소스 코드 버전을 기반으로 배포되도록 보장하므로 일반적으로 권장됩니다.
별도로 렌더링하거나(또는 렌더링하지 않으려면) --no-render 옵션을 지정할 수 있습니다.
Terminal
quarto publish --no-render기본적으로 quarto publish는 프로젝트에 포함된 모든 R, Python, Julia 코드를 실행합니다. 따라서 CI 서버에 필요한 도구 버전과 패키지가 설치되어 있어야 합니다. 이는 이 문서의 범위를 벗어나므로, 의존성 저장/복원에 대해서는 가상 환경 문서를 참고하세요.
코드는 로컬에서 실행하고 CI에서는 마크다운 렌더링만 하려면 Quarto의 freeze 기능을 사용할 수 있습니다. 예를 들어 _quarto.yml에 다음을 추가하면 됩니다.
execute:
freeze: true로컬에서 렌더링할 때 계산이 실행되고 결과가 프로젝트 루트의 _freeze 폴더에 저장됩니다. 이후 CI 서버에서 quarto publish 또는 quarto render를 실행하면 계산을 다시 실행할 필요가 없으며(서버에서는 마크다운 렌더링만 수행됨), 저장된 결과를 사용합니다.
배포 대상
quarto publish 명령의 배포 대상을 지정하는 방법은 두 가지입니다.
- 이전 배포에서 생성된
_publish.yml파일의 내용 사용 - 명령줄 파라미터 사용(예:
--id,--server)
quarto publish 명령을 실행하면 배포 대상 기록이 소스 코드 옆의 _publish.yml 파일에 기록됩니다. 예:
- source: project
netlify:
- id: "5f3abafe-68f9-4c1d-835b-9d668b892001"
url: "https://tubular-unicorn-97bb3c.netlify.app"_publish.yml 파일을 버전 관리에 포함하면 CI 서버에서 배포할 때 사용할 수 있습니다. 인자 없이 quarto publish를 실행하고 위의 _publish.yml이 프로젝트 디렉터리에 있다면, 지정된 id로 Netlify에 배포됩니다.
Terminal
quarto publish netlify명시적인 명령줄 인자로 배포 대상을 지정할 수도 있습니다. 예:
Terminal
quarto publish netlify --id 5f3abafe-68f9-4c1d-835b-9d668b892001_publish.yml에 여러 배포 대상을 저장했다면 --id 옵션으로 그중 하나를 선택할 수 있습니다.
배포 자격 증명
배포 자격 증명은 환경 변수 또는 명령줄 파라미터로 지정할 수 있습니다. 서비스별로 다음 환경 변수가 인식됩니다.
| Service | Variables |
|---|---|
| Quarto Pub | QUARTO_PUB_AUTH_TOKEN |
| Netlify | NETLIFY_AUTH_TOKEN |
| Posit Connect | CONNECT_SERVER and CONNECT_API_KEY |
| Confluence | CONFLUENCE_AUTH_TOKEN, CONFLUENCE_USER_EMAIL, and CONFLUENCE_DOMAIN |
quarto publish 호출 전에 스크립트에서 이 환경 변수를 설정하세요. 예:
Terminal
export NETLIFY_AUTH_TOKEN="45fd6ae56c"
quarto publish netlify 배포 대상 --id도 명령줄 인자로 지정할 수 있습니다. 예:
Terminal
export CONNECT_SERVER=https://connect.example.com/
export CONNECT_API_KEY=7C0947A852D8
quarto publish connect --id DDA36416-F950-4647-815C-01A24233E294완전한 예시
다음은 배포 셸 스크립트를 작성하는 다양한 방법을 보여주는 완전한 예시입니다.
Terminal
# publish (w/o rendering) to quarto pub based on _publish.yml
export QUARTO_PUB_AUTH_TOKEN="45fd6ae56c"
quarto publish quarto-pub --no-renderTerminal
# render and publish to netlify based on _publish.yml
export NETLIFY_AUTH_TOKEN="45fd6ae56c"
quarto publish netlifyTerminal
# publish (w/o rendering) to netlify with explicit id
export NETLIFY_AUTH_TOKEN="45fd6ae56c"
quarto publish netlify --id DDA36416-F950-4647-815C-01A24233E294 --no-renderTerminal
# publish (w/o rendering) to connect based on _publish.yml
export CONNECT_SERVER=https://connect.example.com/
export CONNECT_API_KEY=7C0947A852D8
quarto publish connect --no-renderTerminal
# render and publish to connect with explicit id
export CONNECT_SERVER=https://connect.example.com/
export CONNECT_API_KEY=7C0947A852D8
quarto publish connect --id DDA36416-F950-4647-815C-01A24233E294Terminal
# render and publish to Confluence based on _publish.yml
export CONFLUENCE_AUTH_TOKEN=7C0947A852D8
export CONFLUENCE_USER_EMAIL=email@domain.com
export CONFLUENCE_DOMAIN=https://domain.atlassian.net/
quarto publish confluence --no-browser --no-prompt