2026 Mac 클라우드 24/7 백그라운드 작업: Linux cron에서 macOS launchd로 이전하는 결정표와 환경 변수 체크리스트
Mac 클라우드 SSH는 되는데 야간 동기화나 헬스 체크를 crontab에 올리면 실행 안 됨, PATH 손실, 로그 없음이 흔합니다. 본문은 VPS처럼 운영하려는 팀을 위해 cron과 launchd 비교표, LaunchAgent와 LaunchDaemon 선택, 최소 plist, launchctl bootstrap, 5단계 검증을 정리합니다.
1. 세 가지 문제: crontab은 맞는 듯하지만 Mac 클라우드에서 깨지는 이유
macOS에도 cron은 남아 있지만 통합 스케줄러는 launchd입니다. 헤드리스 Mac 클라우드에서는 「SSH 수동 실행은 성공, 예약만 실패」 패턴이 흔합니다.
- PATH·환경 변수 단절: Linux는 crontab 안에
PATH=를 적을 수 있습니다. macOS cron 환경은 매우 빈약해node·python3를 못 찾습니다. SSH는.zprofile·.zshrc를 읽지만 cron/launchd는 기본적으로 읽지 않아 「수동 OK=예약 OK」로 오인하기 쉽습니다. - 실행 주체와 키체인: 상대 경로,
~, 키체인 접근은 cron과 LaunchAgent에서 다르게 동작합니다. GUI 가정 작업을 무헤드에 올리면 조용히 실패합니다. 빌드 큐·디스크와 겹치면 DerivedData 정리가 때때로 로그 없이 실패합니다. - 관측성 부족:
StandardOutPath·StandardErrorPath가 없으면 실패가 unified logging 조각으로만 남아 CI와 시계열 대조가 어렵습니다. Runbook이 없으면 crontab만 고치는 루프에 빠집니다.
다음 표로 plist 도메인을 한 번에 정해 잘못된 층에서 시간을 쓰지 않습니다.
2. 의사결정 표: cron, LaunchAgent, LaunchDaemon
노트북의 「로그인 후 돌면 됨」과 달리 Mac 클라우드는 대개 24시간 가동·GUI 세션 없음이 많습니다. 재부팅 후에도 launchd가 읽는 배치를 우선합니다.
| 시나리오 | Linux 습관 | macOS 권장 | 이유 |
|---|---|---|---|
| 개발기, 로그인 후 동기화 | user crontab | ~/Library/LaunchAgents | 사용자 도메인에서 툴체인 접근 |
| 클라우드 24/7, 로그인 없음 | system cron | LaunchDaemon 또는 bootstrap된 Agent | GUI 분리, 재부팅 후 자동 기동 |
| root·저포트 | root crontab | LaunchDaemon + UserName | 실행 사용자 명시로 감사 용이 |
| 초단위 고빈도 | systemd timer | StartInterval + 스로틀 이해 | 이벤트 병합 주의 |
| 일회 유지보수 | at | launchctl submit / RunAtLoad | 장기 항목 최소화 |
nvm·pyenv에 기대지 말고 ProgramArguments에 절대 경로 셸·스크립트를 쓰며, EnvironmentVariables로 PATH를 고정하세요. 비밀은 plist 평문 금지, 키체인·CI 시크릿으로.
3. plist·launchctl·bootstrap·5단계 검증
SSH 권한 전제. 라벨은 제로 트러스트 SSH Runbook과 맞춥니다.
- 인터프리터 고정:
which bash,which node기록. Homebrew는/opt/homebrew/bin또는/usr/local/bin절대 경로로 「대화형엔 brew, 잡엔 없음」 제거. - 최소 plist:
Label,ProgramArguments,StartCalendarInterval(또는StartInterval), stdout/stderr,EnvironmentVariables. 매일 03:15 예(경로 교체):
- 배치·로드:
~/Library/LaunchAgents또는/Library/LaunchDaemons에 두고launchctl bootstrap …. 변경 시bootout후bootstrap또는kickstart -k. - 시험·로그:
launchctl kickstart -kp gui/$(id -u)/com.example.vpsmac.nightly-sync. stdout/stderr 로테이션, 파일 쓰기 시WorkingDirectory. - 환경 diff: 임시로
env | sort파일(디버그 후 삭제) 또는launchctl print로 대화형 SSH와 비교. - CI·에이전트 공존: OpenClaw·
xcodebuild피크와 분리.Nice나 별 노드로 I/O 경쟁 완화.
1~4는 실행, 5~6은 관측·공존을 보장합니다. 장애 시 stdout/stderr 마지막 200줄, launchctl print, plist SHA-256 세트를 티켓에 첨부하면 수렴이 빨라집니다.
4. 인용·운영 파라미터
① 시스템 명령만이면 PATH=/usr/bin:/bin:/usr/sbin:/sbin로 충분한 경우가 많음. ② 캘린더 트리거는 시스템 타임존·DST 따름. ③ 로그 무로테이션은 GB까지 팽창, newsyslog 등 병행. ④ 짧은 주기는 병합될 수 있어 초당 엄격 주기 기대 금지. ⑤ plist 644 등으로 변조 어렵게.
대용량 rsync와 xcodebuild 의존성 해결이 같은 시각에 겹치면 SSD가 200~400MB/s대에서 포화되어 「네트워크 장애」처럼 보이는 I/O 대기가 납니다. 10~15분만 어긋나도 재현률이 떨어지는 경우가 많습니다.
5. 임시 crontab에서 감사 가능한 Mac 클라우드로
개인 export·짧은 수명 crontab은 환경 드리프트·비밀 분산·공존 워크로드 경쟁을 부릅니다. plist를 저장소로 관리하는 것이 프로덕션 노드 예의입니다.
범용 Linux VPS에서 macOS 스케줄 전제를 억지로 맞추면 launchd 부재·키체인 서사 불일치·Xcode 체인 비정렬이 쌓입니다. 컨테이너로 경로를 흉내도 코드 서명·시뮬레이터 전제 iOS 파이프라인까지 대체하기 어렵고 제2 플랫폼 운용만 늘어납니다.
2026년 VPS형 SSH와 네이티브 macOS를 함께 원한다면 VPSMAC M4 Mac 클라우드에 launchd를 개통 Runbook에 넣고 동일 plist 정책을 노드에 복제하는 편이 장기적으로 단순합니다.
6. FAQ
crontab을 써도 되나요?
가능하지만 기본 권장은 아닙니다. PATH·절대 경로·로그 전달을 필수로 하세요.
LaunchAgent와 LaunchDaemon 차이는?
Agent는 사용자 GUI 세션 쪽, Daemon은 시스템 부트 쪽에 가깝습니다. 무헤드 호스트에서는 키체인·파일 소유 요구로 고릅니다.
plist를 바꿨는데 반영이 안 됩니다
bootout/bootstrap 순서와 Label 일치, stderr 경로 쓰기 권한을 확인하세요.