Posit Connect

개요

Posit Connect는 조직 내에서 데이터 제품을 안전하게 공유하는 배포 플랫폼입니다. 공개 인터넷이 아니라 조직 내부에 배포하고 싶다면 Posit Connect를 사용하세요.

Quarto 콘텐츠를 Posit Connect에 배포하는 방법은 여러 가지가 있습니다.

  1. 로컬에서 렌더링한 정적 콘텐츠를 quarto publish 명령으로 배포

  2. Posit Connect 서버에서 렌더링할 코드를 배포하기 위해 rsconnect-python Python 패키지 또는 quarto R 패키지 사용(예: 예약 보고서)

  3. Connect의 Git 기반 콘텐츠 지원을 사용해 Git 저장소에 코드가 체크인될 때 콘텐츠 자동 재배포

  4. Jenkins, Airflow, GitHub Actions 같은 CI(Continuous Integration) 서비스를 사용해 Connect에 렌더링 및 배포

각 옵션은 아래에서 자세히 설명합니다. 처음 시작하는 경우 첫 번째 방법(quarto publish)을 강력히 권장합니다. 이후 필요가 커지면 더 고급 옵션을 고려하세요.

배포 명령

quarto publish 명령은 로컬에서 렌더링한 콘텐츠를 배포하는 가장 쉬운 방법입니다. 프로젝트 디렉터리에서 Connect용 quarto publish 명령을 실행하세요.

Terminal
quarto publish connect

이전에 Connect에 배포한 적이 없다면 서버 URL 입력을 요구합니다.

Terminal
$ quarto publish connect
 ? Server URL: › 

다음으로 Connect API Key를 입력해야 합니다.

Terminal
$ quarto publish connect
 ? Server URL: › https://connect.example.com/
 ? API Key: › 

인증이 끝나면 콘텐츠가 렌더링되어 배포되고, 브라우저가 열려 Connect의 관리자 페이지를 보여줍니다.

이전 배포 기록은 프로젝트 또는 문서 디렉터리의 _publish.yml 파일에 저장됩니다. 이 파일에는 배포된 콘텐츠의 서비스, id, URL이 저장됩니다. 예:

- source: project
  connect:
    - id: "3bb5f59f-524a-45a5-9508-77e29a1e8bf0"
      url: "https://connect.example.com/content/3bb5f59f-524a-45a5-9508-77e29a1e8bf0/"

계정 정보는 이 파일에 저장되지 않으므로 버전 관리에 포함하거나 여러 게시자가 공유해도 안전합니다.

다음 명령줄 옵션으로 quarto publish 동작을 사용자 지정할 수 있습니다.

옵션 동작
--no-prompt 배포 확인 프롬프트를 표시하지 않습니다.
--no-browser 배포 후 브라우저를 열지 않습니다.
--no-render 배포 전에 다시 렌더링하지 않습니다.

웹사이트나 책이 아닌 문서를 배포하려면 문서 경로를 지정하세요.

Terminal
quarto publish connect document.qmd

코드로 배포

앞선 예시에서는 로컬에서 렌더링한 뒤 Connect에 배포했습니다. 하지만 경우에 따라 소스 코드를 Connect에 배포하고 서버에서 렌더링하도록 할 수 있습니다(예: 새 데이터로 자동 업데이트되는 예약 보고서).

코드 배포 도구는 Knitr(R)과 Jupyter(Python) 엔진에 따라 다르므로 아래에서 각각 설명합니다. 코드 배포 전에 Connect 서버에 Quarto가 설치되어 있어야 하며(보통 관리자가 수행), 자세한 내용은 Quarto 설치 문서를 참고하세요.

Knitr (R)

quarto R 패키지에는 R 코드가 포함된 Quarto 프로젝트를 Posit Connect에 배포할 때 사용할 수 있는 배포 함수가 포함되어 있습니다. 예를 들어 다음은 문서와 웹사이트를 배포하는 코드입니다.

library(quarto)

quarto_publish_doc(
  "document.qmd", 
  server = "rsc.example.com", 
  account = "njones",
  render = "server"
)

quarto_publish_site(
  server = "rsc.example.com", 
  account = "njones",
  render = "server"
)

render = "server" 인자는 콘텐츠가 아니라 코드를 배포해 서버에서 렌더링하도록 지정합니다.

한 번 배포한 뒤에는 인자를 명시하지 않고 업데이트할 수 있습니다.

quarto_publish_site()

이 함수 사용에 대한 자세한 내용은 R에서 Quarto 배포 문서를 참고하세요.

RStudio IDE

RStudio IDE를 사용하는 경우 Posit Connect로의 버튼 배포도 지원됩니다. 소스 편집기나 뷰어 패널의 배포 버튼 을 사용해 문서나 웹사이트를 배포하세요.

자세한 내용은 Connect의 RStudio IDE에서 배포 문서를 참고하세요.

Jupyter (Python)

rsconnect-python Python 패키지는 Jupyter를 사용하는 Quarto 문서와 웹사이트를 Posit Connect에 배포할 수 있는 CLI를 제공합니다. CLI 사용 방법은 다음과 같습니다.

  1. 먼저 rsconnect-python 패키지를 설치하고 Posit Connect 서버를 배포용으로 구성합니다: https://docs.rstudio.com/connect/user/connecting-cli/

  2. 프로젝트 디렉터리에서 rsconnect deploy quarto 명령을 실행합니다.

    Terminal
    rsconnect deploy quarto

CLI를 사용해 Connect에 배포하는 자세한 내용은 Quarto 콘텐츠 배포 문서를 참고하세요.

Git에서 배포

콘텐츠는 원격 Git 저장소에서 Posit Connect로 직접 배포될 수 있습니다. 연관된 원격 Git 저장소에서 자동으로 가져와 재배포하므로 Git 중심 워크플로와 지속적 배포 자동화를 통합할 수 있습니다.

Git 기반 콘텐츠를 Posit Connect에 배포하려면 다음 두 단계를 따릅니다.

  1. 매니페스트 파일을 생성하고 커밋합니다(콘텐츠 렌더링에 필요한 R/Python 의존성 정보 포함)

  2. Posit Connect를 Git 저장소에 연결합니다.

Git에서 배포하기 전에 Connect 서버에 Quarto가 설치되어 있어야 합니다(보통 관리자가 수행, 자세한 내용은 Quarto 설치 참고).

매니페스트 생성

매니페스트 생성 및 저장소 커밋에 대한 전체 내용은 Git 기반 콘텐츠 문서를 참고하세요. 대략적인 흐름을 보여주기 위해 Knitr와 Jupyter 프로젝트의 매니페스트 생성 예시를 제공합니다.

# write a manifest for a Knitr project
install.packages("rsconnect") # if required
rsconnect::writeManifest()
Terminal
# write a manifest for a Jupyter notebook
pip install rsconnect-python # if required
rsconnect write-manifest notebook MyNotebook.ipynb

매니페스트 생성에 대한 자세한 내용은 Git 기반 콘텐츠 문서를 참고하세요.

저장소 연결

Git 저장소에서 새 콘텐츠를 만들려면 Connect 사용자는 최소 publisher 역할이 있어야 합니다.

Content 페이지 상단 근처에 Publish 버튼이 있습니다. 이 버튼을 클릭하면 “Import from Git” 항목이 있는 메뉴가 열리며, 이를 클릭하면 새 콘텐츠 마법사가 시작됩니다.

저장소 URL, 배포할 브랜치, 배포할 대상 디렉터리(예: manifest.json이 있는 폴더)를 입력하라는 안내가 표시됩니다.

Git 저장소를 Connect에 연결하는 자세한 내용은 Git 기반 콘텐츠 문서를 참고하세요.

지속적 통합

Jenkins, Airflow, GitHub Actions 같은 CI 서비스를 사용해 Quarto 콘텐츠를 배포할 수도 있습니다. 대부분은 quarto publish 명령을 스크립트로 구성하게 되지만, GitHub Actions의 경우 표준 Quarto publish 액션을 사용할 수 있습니다.

CI 서비스에서 Connect로 배포할 때는 Python/R 코드를 CI 서버에서 직접 실행할지, 아니면 이전에 동결된 실행 결과를 활용할지 결정해야 합니다. 먼저 이 가능성을 살펴보고 CI에서 배포하는 구체적인 방법으로 넘어갑니다.

계산 동결

런타임 요구 사항(패키지, 데이터베이스 자격 증명 등)이 복잡할수록 필요한 소프트웨어와 자격 증명이 갖춰진 로컬 환경에서만 Python/R 코드를 실행하는 편이 더 편리할 수 있습니다.

R, Python, Julia 코드가 로컬에서만 실행되도록 하려면 _quarto.yml에 다음을 추가해 Quarto의 freeze 기능을 사용하도록 프로젝트를 구성하세요.

_quarto.yml
execute:
  freeze: auto

이제 사이트를 완전히 다시 렌더링하세요.

Terminal
quarto render

프로젝트에 실행 가능한 코드가 있으면 최상위에 _freeze 디렉터리가 생성됩니다. 이 디렉터리는 계산 결과를 저장하며 버전 관리에 포함해야 합니다. 실행 가능한 코드가 있는 .qmd 파일을 변경하면 다음 렌더링에서 자동으로 다시 실행되고, 업데이트된 계산 결과가 _freeze에 저장됩니다.

CI 배포에서 프로젝트의 모든 Python/R 코드를 실행하려면 필요한 도구 버전과 패키지가 CI 서버에 설치되어 있어야 합니다. 이는 이 문서의 범위를 벗어나므로, 의존성 저장/복원은 가상 환경 문서를 참고하세요.

배포 명령

어떤 CI 서비스든 quarto publish 명령을 스크립트로 구성해 Connect에 Quarto 콘텐츠를 배포할 수 있습니다. 이를 위해 CI 서버 환경 변수로 Connect 서버 주소와 자격 증명이 준비되어 있어야 합니다.

변수 설명
CONNECT_SERVER Posit Connect 서버 주소(예: https://connect.example.com).
CONNECT_API_KEY Posit Connect API Key

또한 업데이트할 대상 콘텐츠의 ID를 지정해야 합니다. 대부분 배포 시 프로젝트 디렉터리에 저장되는 _publish.yml 파일에서 가져옵니다. 예:

_publish.yml
- source: project
  connect:
    - id: 4f2ffc46-24b0-4cc7-a854-c5eb671e0dd7
      url: 'https://connect.example.com/content/4f2ffc46-24b0-4cc7-a854-c5eb671e0dd7/'

위와 같은 _publish.yml이 있다고 가정하면, 다음 명령으로 CI에서 Connect에 배포할 수 있습니다.

Terminal
export CONNECT_SERVER=https://connect.example.com/
export CONNECT_API_KEY=7C0947A852D8
quarto publish connect

또는 _publish.yml 파일이 없다면 다음과 같이 명령줄에서 ID를 지정할 수 있습니다.

Terminal
quarto publish connect --id 4f2ffc46-24b0-4cc7-a854-c5eb671e0dd7

GitHub Actions

CI 서비스가 GitHub Actions라면 Quarto의 표준 publish 액션을 활용해 Connect 배포를 자동화할 수 있습니다.

서버 자격 증명

publish 액션을 만들기 전에, 저장소에 Connect 배포에 필요한 자격 증명이 있는지 확인해야 합니다. 다음과 같이 설정합니다.

  1. 아직 없다면 해당 Connect 서버에서 Posit Connect API Key를 생성한 뒤 클립보드에 복사합니다.

  2. Connect API Key를 저장소의 action Secrets(저장소 Settings에서 접근)에 추가합니다. 오른쪽 상단에 New repository secret 버튼이 있습니다.

    버튼을 클릭하고 1단계에서 복사한 API Key를 CONNECT_API_KEY라는 이름의 secret으로 추가합니다.

Publish 액션

publish 액션을 설정하려면 저장소에 .github/workflows/publish.yml 파일을 만드세요. 계산 동결 (즉, 액션에서 Python/R 코드를 실행하지 않음)을 사용하는 경우 파일은 다음과 비슷합니다.

.github/workflows/publish.yml
on:
  workflow_dispatch:
  push:
    branches: main

name: Quarto Publish

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4 

      - name: Set up Quarto
        uses: quarto-dev/quarto-actions/setup@v2

      - name: Render and Publish 
        uses: quarto-dev/quarto-actions/publish@v2
        with:
          target: connect
          CONNECT_SERVER: https://connect.example.com
          CONNECT_API_KEY: ${{ secrets.CONNECT_API_KEY }}

publish 액션과 _freeze 디렉터리를 포함해 업데이트한 저장소를 GitHub에 푸시하면, 이후 커밋에서 액션이 실행되어 Connect에 자동으로 렌더링하고 배포합니다.

코드 실행

필요하다면 GitHub Actions에서 렌더링 과정의 일부로 Python 또는 R 코드를 실행하도록 구성할 수 있습니다. 직관적으로 가장 좋은 방법처럼 보일 수 있지만, GitHub Actions 같은 CI 서비스에서 코드를 실행할 때 적용되는 다음 요구 사항을 고려해야 합니다.

  • CI 환경에서 모든 의존성(R, Python, Julia 및 필요한 패키지의 정확한 버전)을 재현해야 합니다.

  • 코드가 특별한 권한(예: 데이터베이스 또는 네트워크 접근)을 요구한다면 해당 권한도 CI 서버에 있어야 합니다.

  • 프로젝트에는 더 이상 쉽게 실행할 수 없는 문서(예: 오래된 패키지 버전을 사용하는 몇 년 전 블로그 글)가 있을 수 있습니다. 이런 문서는 CI에서 실행되지 않도록 개별적으로 freeze를 활성화해야 할 수 있습니다.

사전 요구 사항

GitHub Action에서 코드가 실행되도록 보장하는 가장 좋은 방법은 프로젝트에 venvrenv 같은 가상 환경을 사용하는 것입니다(아래에 각 예시 액션을 제공합니다). 이 도구가 익숙하지 않다면 Quarto의 가상 환경 문서를 참고하세요.

GitHub Action에서 코드를 실행하기로 했다면 앞서 설명한 _quarto.ymlfreeze: auto 설정을 제거할 수 있습니다. 일부 문서나 디렉터리에만 freeze를 선택적으로 사용하고 싶다면 여전히 가능합니다(디렉터리의 경우 해당 디렉터리에 _metadata.yml 파일을 만들고 그 안에 freeze 설정을 지정합니다. Quarto는 블로그 프로젝트의 posts 폴더에 대해 기본적으로 이 방식으로 처리합니다).

예시: venv를 사용하는 Jupyter

다음은 requirements.txt에서 Python, Jupyter, 패키지 의존성을 설치한 다음 코드를 실행하고 Connect로 출력물을 렌더링하는 GitHub Action의 전체 예시입니다.

.github/workflows/publish.yml
on:
  workflow_dispatch:
  push:
    branches: main

name: Quarto Publish

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4 

      - name: Set up Quarto
        uses: quarto-dev/quarto-actions/setup@v2
        
      - name: Install Python and Dependencies
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'
          cache: 'pip'
      - run: pip install jupyter
      - run: pip install -r requirements.txt
      
      - name: Render and Publish 
        uses: quarto-dev/quarto-actions/publish@v2
        with:
          target: connect
          CONNECT_SERVER: https://connect.example.com
          CONNECT_API_KEY: ${{ secrets.CONNECT_API_KEY }}
예시: renv를 사용하는 Knitr

다음은 renv.lock에서 R과 패키지 의존성을 설치한 다음 코드를 실행하고 Connect로 출력물을 렌더링하는 GitHub Action의 전체 예시입니다.

.github/workflows/publish.yml
on:
  workflow_dispatch:
  push:
    branches: main

name: Quarto Publish

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v4 

      - name: Set up Quarto
        uses: quarto-dev/quarto-actions/setup@v2
        
      - name: Install R
        uses: r-lib/actions/setup-r@v2
        with:
          r-version: '4.2.0'
      
      - name: Install R Dependencies 
        uses: r-lib/actions/setup-renv@v2
        with:
          cache-version: 1
      
      - name: Render and Publish
        uses: quarto-dev/quarto-actions/publish@v2
        with:
          target: connect
          CONNECT_SERVER: https://connect.example.com
          CONNECT_API_KEY: ${{ secrets.CONNECT_API_KEY }}

추가 옵션

Quarto 프로젝트가 더 큰 GitHub 저장소 안에 있고 최상위 디렉터리에 위치하지 않을 수도 있습니다. 이 경우 publish 액션 호출에 path 입력을 추가합니다. 예:

- name: Render and Publish
  uses: quarto-dev/quarto-actions/publish@v2
  with:
    target: connect
    path: subdirectory-to-use
    CONNECT_SERVER: https://connect.example.com
    CONNECT_API_KEY: ${{ secrets.CONNECT_API_KEY }}

기본적으로 quarto publish는 배포 전에 프로젝트를 다시 렌더링합니다. 그러나 렌더링된 출력물을 버전 관리에 저장한다면 GitHub 액션에서 재렌더링할 필요가 없습니다. 이 경우 publish 액션에 render: false 옵션을 추가합니다.

- name: Render and Publish
  uses: quarto-dev/quarto-actions/publish@v2
  with:
    target: connect
    render: false
    CONNECT_SERVER: https://connect.example.com
    CONNECT_API_KEY: ${{ secrets.CONNECT_API_KEY }}