스케줄링의 두 방법
cron은 널리 쓰이는 시간 기반 스케줄러야. macOS에서는 launchd가 서비스 수명과 예약 실행을 함께 관리하는 기본 체계라 새 작업은 보통 LaunchAgent나 LaunchDaemon으로 구성해. 기존 cron 작업도 존재할 수 있으므로 둘 다 확인해야 해.
cron 빠른 참조
crontab -e # cron 테이블 편집
crontab -l # 나열
*/5 * * * * /path/to/script.sh
0 3 * * 1 /path/to/weekly.sh다섯 필드는 분, 시, 일, 월, 요일을 뜻해. cron의 환경은 대화형 셸보다 작고 실행 디렉터리도 기대와 다를 수 있어. 작업이 의도적으로 .zshenv 계약에 의존한다면 0 3 * * * . $HOME/.zshenv && /path/to/script.sh처럼 소스를 명시할 수 있어. 그렇지 않다면 대화형 설정 파일 전체를 가져오지 말고 실행 파일의 절대 경로, 필요한 환경 변수, 작업 디렉터리를 작업이나 래퍼 스크립트에 직접 적어.
launchd의 LaunchAgent로 예약 실행하기
plist를 ~/Library/LaunchAgents/에 두고 launchctl bootstrap gui/$UID ~/Library/LaunchAgents/com.me.mytask.plist로 등록해. 초 단위 주기는 StartInterval에, 달력 기준 일정은 StartCalendarInterval에 적어. 사용자 세션이 시작될 때 불러올지, 실패 뒤 다시 실행할지는 RunAtLoad와 KeepAlive 같은 수명주기 키로 명시해야 해.
<plist>
<dict>
<key>Label</key> <string>com.me.daily</string>
<key>ProgramArguments</key> <array><string>/path/to/daily.sh</string></array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>3</integer><key>Minute</key><integer>0</integer></dict>
<key>StandardOutPath</key> <string>/tmp/daily.log</string>
</dict>
</plist>앱 내부 스케줄러도 별도 층이야
애플리케이션이 자체 스케줄러를 품고 운영체제 서비스 매니저는 그 앱 프로세스만 살려 두는 구조도 있어. 이때 빈 crontab은 예약 작업이 없다는 증거가 아니야. 실행 중인 서비스의 설정과 영속 상태를 함께 확인해야 해.
- Linux 서버에서는 cron이나 systemd timer를 사용할 수 있어.
- macOS의 사용자 작업은 LaunchAgent, 시스템 작업은 LaunchDaemon이 맡아.
- 앱 내부 일정은 APScheduler나 node-cron 같은 스케줄러가 맡고, 운영체제 서비스 매니저가 앱 프로세스의 수명을 관리하게 할 수 있어.
예약 작업의 환경을 명시해
cron은 대화형 셸보다 작은 작업 환경을 제공해. 대화형 시작 파일을 통째로 불러오면 관련 없는 별칭, 프롬프트와 비밀 값까지 섞일 수 있어. 실행 파일의 절대 경로, 작업 디렉터리, 제한된 로그와 필요한 환경 변수를 명시하고, 중복 실행에는 락이나 멱등 설계를 사용해. macOS에서 launchd가 선언된 수명주기 소유자라면 예약 실행도 launchd에 맡겨.