목차
안녕하세요, 여러분! 지난번 launchd 기초 다지기 글 기억나시나요? 😊 Homebrew 서비스 관리 너머에 있는 launchd의 매력에 살짝 발을 담가봤었죠! 많은 분들이 launchd의 가능성에 눈을 뜨셨을거예요. ㅎ
오늘은 그 다음 단계, launchd의 핵심이자 두뇌 역할을 하는 .plist 설정 파일을 더 깊숙이 파고들어 볼 거예요. 지난번에는 Label
, ProgramArguments
, StartInterval
같은 기본적인 키만 살짝 맛봤다면, 오늘은 마치 숨겨진 보물 지도를 펼치듯, launchd의 강력한 자동화 능력을 깨워줄 고급 설정 키들을 하나하나 탐험할 거랍니다! 🗺️💎
“특정 요일, 특정 시간에만 딱 맞춰서 작업을 실행하고 싶어!”, “이 폴더에 파일이 딱! 들어오면 자동으로 뭔가를 하고 싶은데?”, “중요한 서비스가 혹시 꺼지더라도 자동으로 다시 켜졌으면 좋겠어!” 하는 생각, 해보셨죠? 오늘 배울 .plist
키들을 활용하면 이 모든 것이 현실이 된답니다! 😉 자, 저와 함께 .plist
파일의 숨겨진 능력을 깨우고, 여러분의 Mac 자동화 실력을 한 단계 레벨업 시켜볼까요? 준비되셨으면 출발! 🚀
⏰🗓️ 시간 여행자 되기: StartCalendarInterval 완벽 마스터
지난번엔 StartInterval 키로 “몇 초마다 실행”하는 방법을 배웠죠? 이건 마치 알람시계처럼 단순 반복 작업에 유용해요. 하지만 “매주 금요일 오후 6시에”, “매달 1일 자정에”처럼 정확한 달력 기준으로 작업을 예약하고 싶다면? 바로 이때 StartCalendarInterval 키가 마법을 부린답니다! ✨
이 키는 마치 똑똑한 비서처럼, 우리가 원하는 정확한 날짜와 시간에 맞춰 작업을 수행하게 해줘요. 설정할 수 있는 항목들도 아주 다양하답니다:
Minute
: 몇 분에 실행할지 (0-59)Hour
: 몇 시에 실행할지 (0-23)Day
: 몇 일에 실행할지 (1-31)Weekday
: 무슨 요일에 실행할지 (0=일요일, 1=월요일, …, 6=토요일)Month
: 몇 월에 실행할지 (1-12)
이 키들을 조합해서 아주 정교한 스케줄링이 가능해요! 예를 한번 볼까요?
예시 1: 매주 금요일 오후 6시 정각에 백업 스크립트 실행하기
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>5</integer> <!-- 5 = 금요일 -->
<key>Hour</key>
<integer>18</integer> <!-- 18 = 오후 6시 -->
<key>Minute</key>
<integer>0</integer> <!-- 0 = 정각 -->
</dict>
예시 2: 매달 1일 새벽 3시 30분에 월간 리포트 생성 스크립트 실행하기
<key>StartCalendarInterval</key>
<dict>
<key>Day</key>
<integer>1</integer> <!-- 1 = 매월 1일 -->
<key>Hour</key>
<integer>3</integer> <!-- 3 = 새벽 3시 -->
<key>Minute</key>
<integer>30</integer> <!-- 30 = 30분 -->
</dict>
정말 편리하죠?⚠️ 주의할 점! 만약 여러 개의 조건을 넣으면 모든 조건이 만족될 때 실행돼요. 예를 들어 Weekday
를 5(금)로, Day
를 13으로 하면 13일의 금요일
에만 실행되는 거죠! 😱 그리고 시간은 기본적으로 Mac에 설정된 시간대를 따르니, 해외 서버 시간 등에 맞춰야 한다면 시간대 설정을 고려해야 할 수도 있어요.
📂👀 파일 시스템 감시자: WatchPaths & QueueDirectories 활용법
이번엔 파일이나 폴더의 변화를 실시간으로 감지해서 자동으로 작업을 실행하는 놀라운 기능을 알아볼까요? 마치 문지기처럼 특정 경로를 지켜보다가 변화가 생기면 즉시 우리에게 알려주거나(작업을 실행하거나!) 하는 거죠! 이 역할을 하는 대표적인 키가 바로 WatchPaths와 QueueDirectories랍니다.
WatchPaths – 변화를 감지하면 바로 실행! ⚡
이 키에 감시하고 싶은 파일이나 폴더의 경로를 지정해두면, 해당 경로의 내용이 변경(파일 추가, 삭제, 수정 등)될 때마다 지정된 작업을 실행해요. 정말 유용하겠죠?
예시: `/Users/bada/myconfig.conf` 파일이 수정되면 자동으로 관련 서비스 재시작 스크립트 실행
<key>WatchPaths</key>
<array>
<string>/Users/bada/myconfig.conf</string>
</array>
<key>ProgramArguments</key>
<array>
<string>/Users/bada/bin/restart_service.sh</string>
</array>
이렇게 해두면, 중요한 설정 파일을 실수로 건드렸을 때 서비스가 즉시 재시작되니 안심할 수 있겠죠? 여러 경로를 감시하고 싶다면 “ 안에 “으로 경로를 여러 개 추가하면 돼요.
QueueDirectories – 폴더에 들어온 순서대로 처리! FIFO (First-In, First-Out)
이 키는 특정 폴더를 감시하다가, 그 폴더 안에 새로운 파일이나 폴더가 추가되면 지정된 작업을 실행해요. 중요한 점은, 폴더 안의 내용이 비어 있을 때만 작업이 실행된다는 거예요! 즉, 작업이 실행 중일 때는 새로운 파일이 들어와도 기다렸다가, 폴더가 다시 비워지면 그 다음 파일을 처리하는 방식이죠. (정확히는 폴더가 비어야 다음 작업이 트리거되는 것은 아니고, 폴더에 파일이 존재하는 한 launchd는 지정된 프로그램을 실행하려고 시도합니다. 프로그램이 해당 파일을 처리하고 삭제해야 다음 파일을 처리할 수 있는 구조로 만드는 것이 일반적입니다.)
예시: `~/Downloads/process_queue` 폴더에 파일이 들어오면 `process_file.sh` 스크립트로 처리하기
<key>QueueDirectories</key>
<array>
<string>/Users/bada/Downloads/process_queue</string>
</array>
<key>ProgramArguments</key>
<array>
<string>/Users/bada/bin/process_file.sh</string>
<!-- 보통 스크립트에서 어떤 파일을 처리할지 알아야 하므로,
스크립트 내에서 해당 폴더를 확인하도록 구현 필요 -->
</array>
다운로드 폴더에 이미지 파일이 들어오면 자동으로 리사이징하고 다른 폴더로 옮기는 작업 같은 걸 만들 때 아주 유용하겠죠? 👍 WatchPaths는 변화 자체에 반응하고, QueueDirectories는 폴더에 들어온 항목을 처리하는 데 더 초점이 맞춰져 있다고 생각하면 쉬워요.
💪🔄 좀비 프로세스는 없다! KeepAlive로 서비스 안정성 높이기
우리가 launchd로 실행하는 중요한 서비스(예: 웹서버, 데이터베이스)가 갑자기 예기치 않게 종료되면 정말 난감하겠죠? 😱 이럴 때 우리를 구해줄 수호천사 같은 키가 바로 KeepAlive랍니다! 이 키는 작업(프로세스)이 살아있는지(Alive) 계속(Keep) 감시하다가, 만약 종료되면 자동으로 다시 시작시켜주는 아주 기특한 아이예요!
단순히 <true/>
로 설정하면 무조건 다시 시작해주지만, 더 똑똑하게 조건을 설정할 수도 있어요!
- 항상 재시작: 가장 기본적인 설정. 프로세스가 어떤 이유로든 종료되면 무조건 다시 시작해요.
<key>KeepAlive</key>
<true/>
- 성공적으로 종료됐을 때만 빼고 재시작: 프로세스가 정상적으로 완료(Exit Code 0)된 경우가 아니라면 다시 시작해요. 오류로 종료됐을 때 유용하겠죠?
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
- 특정 경로가 존재할 때만 실행 유지: 예를 들어, 특정 파일이 존재할 때만 서비스가 계속 실행되도록 하고 싶을 때 사용해요.
<key>KeepAlive</key>
<dict>
<key>PathState</key>
<dict>
<key>/var/run/myservice.pid</key>
<true/>
</dict>
</dict>
위 예시는 myservice.pid
파일이 존재하면 프로세스를 계속 실행 상태로 유지하라는 의미예요. (주로 서비스 데몬 관리에 사용돼요)
이 외에도 네트워크 상태 변화(NetworkState) 등 다양한 조건을 조합할 수 있어요! KeepAlive 키 하나만 잘 써도 서비스 안정성이 몰라보게 높아진답니다! 👍 다만, 주의할 점! 만약 스크립트 자체에 오류가 있어서 실행되자마자 계속 죽는다면, KeepAlive 때문에 무한 재시작 루프에 빠질 수 있어요. 이러면 시스템 자원을 엄청나게 소모하게 되니, 꼭 로그를 확인하며 안정성을 확보한 후에 적용하는 것이 좋답니다!

🗺️⚙️ 환경 설정의 마법: EnvironmentVariables & WorkingDirectory
지난 글에서도 살짝 언급했지만, launchd에서 실행되는 스크립트는 우리가 평소에 터미널에서 실행할 때와 환경이 조금 다를 수 있다는 점, 기억하시죠? 특히 환경 변수(Environment Variables)나 현재 작업 디렉토리(Working Directory)가 달라서 스크립트가 예상과 다르게 동작하는 경우가 종종 있어요. 이럴 때 우리를 도와줄 마법 같은 키들이 있답니다!
EnvironmentVariables – 스크립트에 날개 달아주기! 🧚
스크립트가 실행될 때 필요한 환경 변수를 직접 설정해 줄 수 있는 키예요. 예를 들어, 스크립트에서 특정 API 키를 사용해야 하거나, Homebrew로 설치한 프로그램 경로(`PATH`)를 알려줘야 할 때 아주 유용하죠!
<key>EnvironmentVariables</key>
<dict>
<key>API_KEY</key>
<string>여기에_여러분의_API_키를_넣으세요</string>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
이렇게 PATH를 명시적으로 지정해주면, 스크립트 안에서 brew 같은 명령어를 전체 경로 없이도 사용할 수 있게 되어 편리해요. 😊
WorkingDirectory – 스크립트의 ‘집’ 정해주기! 🏠
스크립트가 실행되는 기준 디렉토리를 지정하는 키예요. 만약 스크립트 안에서 상대 경로(예: ./data/input.txt
)를 사용하는데, launchd가 스크립트를 어디서 실행할지 몰라 헤맨다면? 바로 이 키로 “여기서 실행해!” 하고 알려주면 된답니다.
<key>WorkingDirectory</key>
<string>/Users/bada/my_project/</string>
이렇게 설정하면, 스크립트는 항상 /Users/bada/my_project/
디렉토리 안에서 실행되는 것처럼 동작해요. 상대 경로 때문에 골치 아팠던 문제가 깔끔하게 해결될 수 있겠죠? 😉
📜🕵️♀️ 디버깅 필수템: StandardOutPath & StandardErrorPath
자, 열심히 .plist
파일을 만들고 launchctl load까지 했는데… 어라? 스크립트가 실행되지 않거나 뭔가 이상하게 동작할 때! 😱 정말 답답하죠? 이럴 때 문제 해결의 실마리를 찾으려면 로그(Log)를 확인하는 것이 무엇보다 중요해요! launchd는 친절하게도 스크립트의 표준 출력(Standard Output)과 표준 에러(Standard Error)를 파일로 저장할 수 있는 기능을 제공한답니다. 바로 StandardOutPath와 StandardErrorPath 키를 통해서요!
- StandardOutPath : 스크립트가 정상적으로 실행되면서 출력하는 내용들(예:
echo
명령 결과)을 저장할 파일 경로를 지정해요. - StandardErrorPath : 스크립트 실행 중 발생한 오류 메시지들을 저장할 파일 경로를 지정해요. 디버깅할 때 가장 먼저 확인해야 할 파일이죠!
예시: 로그 파일 경로 지정하기
<key>StandardOutPath</key>
<string>/Users/bada/logs/myscript.log</string>
<key>StandardErrorPath</key>
<string>/Users/bada/logs/myscript_error.log</string>
이렇게 설정해두면, 스크립트가 실행될 때마다 지정된 경로에 로그 파일이 생성되거나 내용이 추가돼요. 스크립트가 왜 제대로 동작하지 않는지 단서를 찾을 때 정말 큰 도움이 된답니다! 👍
🍯 꿀팁! 로그 파일이 너무 커지는 것을 방지하려면, 주기적으로 로그 파일을 백업하고 비워주는 별도의 스크립트를 만들거나, macOS의 newsyslog 같은 로그 로테이션 기능을 활용하는 것도 좋은 방법이에요.

🔍 더 정교한 제어: 그 외 유용한 키들 살짝 맛보기 🤏
오늘 정말 많은 키들을 배웠는데요, 사실 .plist
파일에는 더 다양한 설정 키들이 숨어있답니다! 전부 다 설명하기는 어렵지만, 알아두면 유용한 몇 가지 키들만 살짝 더 소개해 드릴게요.
- UserName / GroupName : 특정 사용자나 그룹의 권한으로 작업을 실행하고 싶을 때 사용해요. 보안상 중요한 작업에 유용하겠죠?
- ThrottleInterval : 작업이 너무 자주 실행되는 것을 방지하기 위해 최소 실행 간격을 지정해요. (예: 10초 안에 여러 번 실행 요청이 와도 딱 한 번만 실행). 시스템 부하를 줄이는 데 도움이 돼요.
- Nice : 프로세스의 실행 우선순위를 조절해요. 값이 낮을수록 우선순위가 높아요. (-20 ~ 20)
- LaunchOnlyOnce : 시스템 부팅 후 딱 한 번만 실행되도록 설정해요.
이런 키들까지 활용하면 정말 launchd를 자유자재로 다룰 수 있게 된답니다! 더 자세한 정보가 궁금하다면, 터미널에서 man launchd.plist 명령어를 입력하거나 Apple Developer 문서를 참고해보세요! 😉
이제 당신도 .plist 마스터! ✨
오늘 정말 많은 .plist
설정 키들을 함께 탐험했어요! StartCalendarInterval로 똑똑하게 시간을 예약하고, WatchPaths로 파일 변화를 감지하고, KeepAlive로 서비스를 튼튼하게 지키고, EnvironmentVariables로 환경 걱정을 덜고, 로그 설정으로 문제 해결 능력까지! 이제 launchd의 기본을 넘어, 그 강력한 잠재력을 깨우는 열쇠(.plist
키)들을 손에 쥐게 되신 거예요! 🔑
오늘 배운 키들을 조합해서 여러분만의 Mac 자동화 루틴을 직접 만들어보세요! 처음에는 작은 것부터 시작해도 좋아요. 여러분의 Mac 생활이 훨씬 더 편리하고 즐거워질 거라고 확신합니다! 💪
마무리
launchd와 .plist
의 세계, 알면 알수록 정말 매력적이지 않나요? 오늘 배운 내용들이 여러분의 Mac 자동화 여정에 든든한 디딤돌이 되기를 진심으로 바랍니다.
이 글이 도움이 되셨다면, 주변에 Mac 자동화에 관심 있는 친구들에게도 꼭 공유해주세요! 함께 배우고 성장하면 기쁨도 두 배가 되니까요. 🙂