Summary
- 배포 로직을 Shell Commands 입력란이 아니라 셸 스크립트 3종으로 분리한다.
- Preview, Quick Publish, Clean Publish를 목적에 따라 나눈다.
- 스크립트가 자기 위치를 기준으로 프로젝트 경로를 계산하므로 호출부를 짧게 유지한다.
- 변경이 없으면 커밋과 push를 건너뛰고, 실패 단계는 종료 코드와 로그로 확인한다.
실습 환경
이 시리즈는 macOS와 Quartz v5 기준이다.
들어가며
배포 로직을 스크립트 파일로 분리하면 경로·환경 변수·안전장치·로깅을 한곳에서 관리할 수 있다. Obsidian의 Shell Commands에는 스크립트 호출만 등록한다.
배포 시스템 구축
명령어 분리
배포 로직은 셸 스크립트 파일에 둔다. 인라인 명령은 디버깅과 재사용이 어렵고, GUI 앱과 터미널의 셸 환경 차이로 실행이 끊길 수 있다.
스크립트는 자기 위치 기준으로 프로젝트 경로를 계산한다. 따라서 Shell Commands에는 cd나 export를 다시 적지 않는다.
스크립트 준비
프로젝트 폴더 아래 scripts/ 디렉터리를 만들고 세 스크립트를 둔다.
haejunhyun.com/scripts/
├── deploy-dev.sh # Preview
├── deploy.sh # Quick Publish
└── deploy-clean.sh # Clean Publish실행 권한 부여
chmod +x scripts/*.sh환경 변수
아래 값은 자신의 환경에 맞게 수정한다.
| 값 | 기본값 | 수정 기준 |
|---|---|---|
BRANCH | v5 | Cloudflare 프로덕션 브랜치명 |
| Shell Commands 호출 경로 | /Users/haejun/Developer/haejunhyun.com | Quartz 프로젝트 절대 경로 |
PATH 추가 경로 | /opt/homebrew/bin | Intel Mac은 /usr/local/bin |
배포 스크립트
공통 셸 문법
세 스크립트에서 반복해서 사용하는 기본 문법은 다음과 같다.
| 문법 | 의미 | ||
|---|---|---|---|
cd 경로 | 작업 폴더로 이동 | ||
export PATH=... | 명령어 실행 경로 등록 | ||
| `명령어 | return 10` | 실패 시 오류 코드 반환 | |
>와 2>&1 | 실행 결과와 오류를 로그에 저장 | ||
git add → commit → push | 변경 결과를 배포 | ||
(...) & | 명령을 백그라운드에서 실행 |
||는 앞 명령이 실패했을 때 뒤 명령을 실행한다.
cd 경로 || exit 1
명령어 || return 10첫 번째 예시는 디렉터리 이동에 실패하면 스크립트를 종료한다. 두 번째 예시는 함수 안에서 명령 실패를 호출부에 오류 코드 10으로 알린다.
Preview
Preview는 로컬에서 빌드하고 localhost:8080 서버를 실행한다. 서버가 실제로 응답할 때 브라우저를 열고, 상세 출력은 로그에 기록한다.
deploy-dev.sh
#!/bin/bash set -u export PATH="$PATH:/opt/homebrew/bin" REPO="$(cd "$(dirname "$0")/.." && pwd)" LOG="/tmp/quartz-dev.log" cd "$REPO" || { echo "[ERROR] repo 경로 없음: $REPO"; exit 1; } echo "[START] 개발 서버 준비 중... 준비되면 브라우저가 자동으로 열립니다 (로그: $LOG)" echo "플러그인 설치..." | tee "$LOG" npx quartz plugin install >> "$LOG" 2>&1 || exit 5 lsof -ti tcp:8080 | xargs kill 2>/dev/null sleep 1 ( for _ in $(seq 1 60); do if curl -s -o /dev/null "http://localhost:8080"; then open "http://localhost:8080" break fi sleep 1 done ) & npx quartz build --serve >> "$LOG" 2>&1 status=$? echo "[ERROR] 개발 서버 종료됨 (exit $status). 마지막 로그:" tail -n 15 "$LOG" exit "$status"
Quick Publish
Quick Publish는 플러그인 설치, 빌드, public 커밋, 원격 push를 순서대로 실행한다. content는 심볼릭 링크 자체만 추적하므로 커밋하지 않는다.
deploy.sh
#!/bin/bash set -u export PATH="$PATH:/opt/homebrew/bin" REPO="$(cd "$(dirname "$0")/.." && pwd)" LOG="/tmp/quartz-deploy.log" BRANCH="v5" cd "$REPO" || { echo "[ERROR] repo 경로 없음: $REPO"; exit 1; } echo "[START] 일상 배포 시작 - 빌드 후 push합니다..." run() { npx quartz plugin install || return 5 npx quartz build || return 10 git add public if git diff --cached --quiet; then return 20; fi git commit -m "Update: $(date +%Y-%m-%d_%H:%M)" || return 30 git push origin "$BRANCH" --force-with-lease || return 40 return 0 } run > "$LOG" 2>&1 status=$? case "$status" in 0) echo "[OK] 배포 완료 -> Cloudflare 반영 중" ;; 20) echo "[SKIP] 변경 없음 - 배포 스킵" ;; 5) echo "[ERROR] 플러그인 설치 실패"; tail -n 15 "$LOG" ;; 10) echo "[ERROR] 빌드 실패"; tail -n 15 "$LOG" ;; 30) echo "[ERROR] 커밋 실패"; tail -n 15 "$LOG" ;; 40) echo "[ERROR] push 실패"; tail -n 15 "$LOG" ;; esac exit "$status"
Clean Publish
Clean Publish는 public과 .quartz-cache를 지운 뒤 처음부터 빌드한다. 파일 삭제·이름 변경 후 또는 캐시 문제가 있을 때 사용한다.
deploy-clean.sh
#!/bin/bash set -u export PATH="$PATH:/opt/homebrew/bin" REPO="$(cd "$(dirname "$0")/.." && pwd)" LOG="/tmp/quartz-clean.log" BRANCH="v5" cd "$REPO" || { echo "[ERROR] repo 경로 없음: $REPO"; exit 1; } echo "[START] 완전 재배포 시작 - 캐시 삭제 후 빌드/ push합니다..." run() { rm -rf public .quartz-cache npx quartz plugin install || return 5 npx quartz build || return 10 git add public if git diff --cached --quiet; then return 20; fi git commit -m "Clean: $(date +%Y-%m-%d_%H:%M)" || return 30 git push origin "$BRANCH" --force-with-lease || return 40 return 0 } run > "$LOG" 2>&1 status=$? case "$status" in 0) echo "[OK] 완전 재배포 완료 -> Cloudflare 반영 중" ;; 20) echo "[SKIP] 변경 없음 - 배포 스킵" ;; *) echo "[ERROR] 재배포 실패 (exit $status)"; tail -n 15 "$LOG" ;; esac exit "$status"
Obsidian 연결
Shell Commands 설정
Shell Commands에 세 명령을 만들고 각 스크립트 호출 한 줄만 넣는다.
| 명령 | Shell Commands 값 |
|---|---|
| Quartz: Preview | /bin/bash "/Users/haejun/Developer/haejunhyun.com/scripts/deploy-dev.sh" |
| Quartz: Quick Publish | /bin/bash "/Users/haejun/Developer/haejunhyun.com/scripts/deploy.sh" |
| Quartz: Clean Publish | /bin/bash "/Users/haejun/Developer/haejunhyun.com/scripts/deploy-clean.sh" |
출력과 알림
각 명령의 출력 채널은 Notification balloon, 처리 방식은 Realtime으로 설정한다. 상세 로그는 /tmp/quartz-*.log에서 확인한다.
단축키
| 단축키 | 기능 | 용도 | 빈도 |
|---|---|---|---|
Ctrl + Shift + K | Quick Publish | 일상 배포 | 90% |
Ctrl + Shift + L | Clean Publish | 완전 재배포 | 10% |
Ctrl + Shift + J | Preview | 로컬 미리보기 | 수시 |
배포 프로세스
일반적인 배포 흐름
- Obsidian에서 글을 작성하거나 수정한다.
- 필요하면 Preview로 결과를 확인한다.
- Quick Publish를 실행한다.
- 알림에서 완료 여부를 확인한다.
- 약 1분 후 도메인에서 확인한다.
문제가 생겼을 때
- Clean Publish로 캐시까지 지우고 재배포한다.
- Cloudflare 대시보드에서 배포 상태를 확인한다.
- 필요하면 Cloudflare 캐시를 삭제하고 브라우저를 강력 새로고침한다.
- 실패 단계와
/tmp/quartz-*.log의 마지막 로그를 확인한다.
디자인 변경 후 확인
quartz.config.yaml,custom.scss, 플러그인을 수정했다면 새public을 만들도록 다시 빌드해야 한다.
마치며
Preview, Quick Publish, Clean Publish를 분리하면 확인·일상 배포·문제 해결의 흐름을 각각 독립적으로 관리할 수 있다. 평소에는 Quick Publish를 사용하고, 문제가 생겼을 때 Clean Publish를 사용한다.
Reference
- 이전 글 3부 Cloudflare Pages 빌드 설정과 도메인 통합
- 다음 글 이미지 관리와 삽입 (예정)
