Contents
see ListmacOS는 강력한 자동화 인프라를 내장하고 있지만, 많은 개발자가 이를 충분히 활용하지 못합니다. launchd로 데몬 및 스케줄 작업을 관리하고, 셸 스크립트와 osascript로 시스템을 제어하면 반복 작업을 완전히 자동화할 수 있습니다. 이 글에서는 macOS 터미널 자동화의 핵심 기법을 실전 예제와 함께 상세히 다룹니다.
launchd: macOS의 작업 스케줄러
launchd는 macOS의 시스템 및 사용자 서비스 관리자로, Linux의 systemd + cron을 합친 것과 유사합니다. cron보다 안정적이고 기능이 풍부합니다.
LaunchAgent 기본 구조
<!-- ~/Library/LaunchAgents/com.myapp.backup.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 고유 라벨 (필수) -->
<key>Label</key>
<string>com.myapp.backup</string>
<!-- 실행할 명령 -->
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/dev/scripts/backup.sh</string>
</array>
<!-- 매일 새벽 3시 실행 -->
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<!-- 로그 출력 -->
<key>StandardOutPath</key>
<string>/tmp/backup-stdout.log</string>
<key>StandardErrorPath</key>
<string>/tmp/backup-stderr.log</string>
<!-- 실행 환경 -->
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/usr/local/bin:/usr/bin:/bin</string>
</dict>
</dict>
</plist>launchctl 관리 명령어
# LaunchAgent 등록 (로드)
launchctl load ~/Library/LaunchAgents/com.myapp.backup.plist
# LaunchAgent 해제 (언로드)
launchctl unload ~/Library/LaunchAgents/com.myapp.backup.plist
# 즉시 실행 (테스트용)
launchctl start com.myapp.backup
# 상태 확인
launchctl list | grep myapp
# PID Status Label
# - 0 com.myapp.backup (0 = 정상, 그 외 = 에러)
# 상세 정보 확인
launchctl print gui/$(id -u)/com.myapp.backup
# 모든 사용자 에이전트 목록
launchctl list
# 에러 코드 확인
# 0: 정상 종료
# 1: 일반 에러
# 78: 설정 파일 오류다양한 트리거 설정
<!-- 1. 주기적 실행 (10분 간격) -->
<key>StartInterval</key>
<integer>600</integer>
<!-- 2. 크론 스타일 스케줄 -->
<!-- 매주 월/수/금 09:30 -->
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Weekday</key>
<integer>1</integer>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
<dict>
<key>Weekday</key>
<integer>3</integer>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
</array>
<!-- 3. 파일 감시 트리거 -->
<key>WatchPaths</key>
<array>
<string>/Users/dev/uploads/</string>
</array>
<!-- 4. 부팅 시 자동 실행 + 항상 유지 -->
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<!-- 5. 네트워크 연결 시에만 실행 -->
<key>KeepAlive</key>
<dict>
<key>NetworkState</key>
<true/>
</dict>osascript: macOS 앱 제어
osascript는 AppleScript나 JavaScript(JXA)를 통해 macOS 앱을 프로그래밍 방식으로 제어합니다.
# 알림 표시
osascript -e 'display notification "백업 완료" with title "시스템" sound name "Glass"'
# 대화상자
osascript -e 'display dialog "작업을 계속할까요?" buttons {"취소", "확인"} default button "확인"'
# 파일 선택 대화상자
osascript -e 'choose file with prompt "파일을 선택하세요"'
# 폴더 선택
osascript -e 'choose folder with prompt "폴더를 선택하세요"'
# 시스템 볼륨 조절
osascript -e 'set volume output volume 50'
osascript -e 'set volume output muted true'
# 현재 Wi-Fi SSID
osascript -e 'do shell script "networksetup -getairportnetwork en0"'
# 클립보드 읽기/쓰기
osascript -e 'set the clipboard to "복사할 텍스트"'
osascript -e 'the clipboard'앱 제어
# Safari에서 URL 열기
osascript -e '
tell application "Safari"
activate
open location "https://www.softmoa.com"
end tell'
# Finder에서 폴더 열기
osascript -e 'tell application "Finder" to open folder "projects" of home'
# 터미널에서 명령 실행
osascript -e '
tell application "Terminal"
activate
do script "cd ~/projects && ls -la"
end tell'
# System Events로 키보드/마우스 제어
osascript -e '
tell application "System Events"
keystroke "c" using command down -- Cmd+C
delay 0.5
keystroke "v" using command down -- Cmd+V
end tell'실전: 자동 개발 환경 셋업 스크립트
#!/bin/bash
# dev-setup.sh - 프로젝트별 개발 환경 자동 구성
PROJECT="$1"
if [ -z "$PROJECT" ]; then
# fzf로 프로젝트 선택
PROJECT=$(ls ~/projects | fzf --prompt="프로젝트 선택: ")
fi
PROJECT_DIR="$HOME/projects/$PROJECT"
if [ ! -d "$PROJECT_DIR" ]; then
echo "프로젝트 없음: $PROJECT"
exit 1
fi
echo "개발 환경 구성: $PROJECT"
# 1. Docker 서비스 시작
if [ -f "$PROJECT_DIR/docker-compose.yml" ]; then
echo "Docker 서비스 시작..."
cd "$PROJECT_DIR" && docker compose up -d
fi
# 2. 의존성 설치 확인
if [ -f "$PROJECT_DIR/package.json" ]; then
cd "$PROJECT_DIR" && npm install
elif [ -f "$PROJECT_DIR/pom.xml" ]; then
cd "$PROJECT_DIR" && ./mvnw dependency:resolve
elif [ -f "$PROJECT_DIR/requirements.txt" ]; then
cd "$PROJECT_DIR" && pip install -r requirements.txt
fi
# 3. VS Code 열기
code "$PROJECT_DIR"
# 4. 브라우저에서 로컬 서버 열기
if [ -f "$PROJECT_DIR/.env" ]; then
PORT=$(grep PORT "$PROJECT_DIR/.env" | cut -d= -f2)
if [ -n "$PORT" ]; then
sleep 3 # 서버 시작 대기
open "http://localhost:$PORT"
fi
fi
# 알림
osascript -e "display notification \"$PROJECT 환경 준비 완료\" with title \"Dev Setup\" sound name \"Glass\""
echo "완료!"실전: 자동 백업 스크립트
#!/bin/bash
# backup.sh - 프로젝트 백업 (rsync + 로테이션)
SOURCE="$HOME/projects"
BACKUP_BASE="/Volumes/Backup/dev-backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_BASE/$DATE"
LATEST="$BACKUP_BASE/latest"
MAX_BACKUPS=30
# 백업 디스크 마운트 확인
if [ ! -d "$BACKUP_BASE" ]; then
echo "백업 디스크가 마운트되지 않았습니다."
osascript -e 'display notification "백업 디스크 없음" with title "Backup Error"'
exit 1
fi
# rsync로 증분 백업 (hard link 활용)
mkdir -p "$BACKUP_DIR"
rsync -az --delete \
--link-dest="$LATEST" \
--exclude='node_modules' \
--exclude='.git' \
--exclude='dist' \
--exclude='build' \
--exclude='__pycache__' \
--exclude='.env' \
"$SOURCE/" "$BACKUP_DIR/"
# latest 심볼릭 링크 업데이트
rm -f "$LATEST"
ln -s "$BACKUP_DIR" "$LATEST"
# 오래된 백업 삭제 (30개 초과 시)
cd "$BACKUP_BASE" || exit
ls -dt */ | tail -n +$((MAX_BACKUPS + 1)) | xargs rm -rf
# 결과 로깅
SIZE=$(du -sh "$BACKUP_DIR" | awk '{print $1}')
echo "$(date): 백업 완료 - $BACKUP_DIR ($SIZE)" >> "$BACKUP_BASE/backup.log"
osascript -e "display notification \"백업 완료: $SIZE\" with title \"Backup\" sound name \"Glass\""유용한 macOS 터미널 명령어 모음
# 시스템 정보
system_profiler SPHardwareDataType # 하드웨어 정보
sw_vers # macOS 버전
sysctl -n machdep.cpu.brand_string # CPU 모델
sysctl hw.memsize | awk '{print $2/1024/1024/1024 " GB"}' # RAM
# 전원 관리
pmset -g batt # 배터리 상태
caffeinate -d -t 3600 # 1시간 동안 슬립 방지
sudo pmset -a sleep 0 # 슬립 비활성화
# 네트워크
networksetup -listallhardwareports # 네트워크 인터페이스
ifconfig en0 | grep inet # IP 주소
curl ifconfig.me # 외부 IP
nslookup example.com # DNS 조회
# 앱 관리
mdfind "kMDItemKind == 'Application'" | sort # 설치된 앱 목록
open -a "Safari" # 앱 실행
killall Safari # 앱 종료
pkill -f "process_name" # 프로세스 종료
# Spotlight 인덱싱 관리
sudo mdutil -i off /Volumes/External # 외장 드라이브 인덱싱 끄기
sudo mdutil -E / # 인덱스 재구성
# 파일 시스템
xattr -cr ~/Downloads/* # 확장 속성 제거 (검역 해제)
diskutil list # 디스크 목록
hdiutil create -size 1g -fs APFS -volname "Work" work.dmg # DMG 생성macOS의 자동화 인프라는 launchd, osascript, 셸 스크립트의 조합으로 거의 모든 반복 작업을 자동화할 수 있습니다. 특히 launchd의 파일 감시 트리거와 KeepAlive 기능은 Linux의 cron보다 훨씬 유연한 스케줄링을 제공합니다. 개발 환경 셋업, 백업, 모니터링 등을 자동화하면 하루에 수십 분의 시간을 절약할 수 있습니다.