금요일 저녁, 제 Mac에서는 몇 번이나 성공한 자동화가 다른 팀원의 Mac에 배포하자 조용히 멈췄어요. 알림도 없고 결과 파일도 없었습니다. 터미널에서 다시 실행하면 정상인데 로그인 직후에는 실패했고, 원인은 권한 하나와 상대 경로 하나였습니다. 이런 일은 스크립트 문법보다 실행 환경을 기록하지 않았을 때 자주 생깁니다. 배포 전에는 “한 번 실행됐다”가 아니라 “다른 조건에서도 실패 이유를 확인하고 되돌릴 수 있다”까지 점검해야 해요.

macOS 자동화는 왜 배포 전에 따로 점검해야 할까요?
AppleScript, JXA, 셸 스크립트, Automator 워크플로는 실행한 계정과 호출한 앱의 영향을 받아요. 터미널에서 허용한 접근이 Automator나 백그라운드 작업에도 그대로 적용된다고 볼 수 없습니다. 로그인한 사용자의 홈 폴더, 현재 작업 디렉터리, PATH, 대상 앱의 실행 상태도 달라집니다.
그래서 실행 성공과 운영 배포 가능은 다른 판정이에요. 운영 가능한 자동화는 입력이 없거나 권한이 거부돼도 데이터를 망가뜨리지 않습니다. 누가 언제 무엇을 실행했는지 남고, 실패 원인을 찾을 수 있으며, 이전 상태로 복구할 수 있어야 합니다.
배포 전 1차 점검표를 한눈에 보세요
| 점검 영역 | 배포 전에 답할 질문 | 남길 증거 |
|---|---|---|
| 목적 | 입력, 출력, 성공 조건이 무엇인가요? | 한 문장 설명과 예시 파일 |
| 실행 조건 | 어느 계정에서 언제 실행되나요? | 계정·호출 방식·주기 |
| 경로 | 다른 Mac에도 파일과 명령이 있나요? | 확인 명령 결과 |
| 권한 | 어떤 데이터와 앱에 접근하나요? | 최소 권한 목록 |
| 안전성 | 재실행과 동시 실행이 안전한가요? | 중복 실행 테스트 |
| 관찰성 | 실패 지점이 로그에 보이나요? | 성공·실패 로그 |
| 복구 | 배포 취소와 데이터 복원이 가능한가요? | 이전 파일과 복구 절차 |
스크립트의 일을 문장으로 설명할 수 있나요?
입력과 결과를 먼저 고정해요
“파일을 정리한다”는 배포 명세로는 부족해요. “로그인한 사용자의 지정 폴더에서 확장자가 CSV인 파일을 읽고, 처리 완료 폴더에 날짜를 붙여 이동한다”처럼 적습니다. 원본을 읽기만 하는지, 이름을 바꾸는지, 삭제하는지도 구분해요. 입력이 없을 때 정상 종료할지 오류로 볼지도 정합니다.
성공과 실패를 숫자로 판단해요
성공 기준은 화면이 닫히는 것이 아닙니다. 처리 대상 12개 중 12개가 완료되고 종료 상태가 0이며 결과 파일이 검증됐다는 식이 좋아요. 권한 거부, 대상 앱 무응답, 파일 누락은 서로 다른 오류 메시지와 종료 상태로 남깁니다. 그래야 재시도할 문제와 사람이 확인할 문제를 나눌 수 있어요.
같은 작업을 다시 실행해 봐요
중간에 실패한 뒤 재실행하면 파일이 두 번 이동되거나 같은 메일이 중복 발송될 수 있습니다. 이미 처리한 항목을 식별할 키를 두고, 결과가 있으면 건너뛸지 덮어쓸지 정하세요. 변경 파일은 임시 위치에 완성한 다음 교체하는 방식이 안전합니다. 삭제·이동 자동화라면 테스트 데이터, 백업, 복원 순서를 먼저 준비해요.
실행 계정과 환경을 확인했나요?
터미널 실행을 배포 테스트로 착각하지 않아요
대화형 터미널은 사용자의 셸 설정과 환경 변수를 읽을 수 있지만, launchd 작업은 같은 환경을 보장하지 않아요. 먼저 whoami, id, pwd, printenv 결과를 테스트 환경과 배포 환경에서 비교합니다. 사용자 로그인 전 필요한 일인지, 로그인한 사용자의 앱과 화면이 필요한 일인지도 구분해야 해요.
경로는 발견하고 검증해요
/Users/minsu/...처럼 특정 사용자의 홈을 박아 두지 않습니다. 셸에서는 $HOME이 실제 실행 계정의 홈을 가리키는지 먼저 확인하고, 필요하면 설정 파일로 경로를 주입해요. 명령은 command -v 도구명으로 위치를 확인합니다. 시스템 기본 도구가 아닌 실행 파일은 설치 여부와 아키텍처 호환성도 배포표에 남겨요.
- 셸 첫 줄의 인터프리터 경로가 실제로 존재하는지 확인합니다.
test -x /절대/경로/스크립트로 실행 가능 여부를 봅니다.ls -l로 소유자와 실행 비트를 확인합니다.- 상대 경로를 쓴다면 시작 디렉터리를 코드에서 명시합니다.
- 환경 변수 누락 시 안전하게 종료하도록 기본값과 검사를 둡니다.
/usr/bin/env은 인터프리터 탐색에 도움이 되지만, 필요한 도구가 PATH에 있다는 보장은 아닙니다. 배포 대상에서 명령 결과를 직접 확인해야 해요.
macOS 개인정보 보호 권한을 최소 범위로 확인했나요?
Files & Folders, Full Disk Access, Accessibility, Automation은 이름만 다른 같은 권한이 아닙니다. Files & Folders는 데스크탑·문서·다운로드 같은 보호 위치 접근과 관련되고, Automation은 Apple events를 통해 다른 앱을 제어하는 흐름과 관련돼요. Accessibility는 UI 조작에 필요할 수 있고, Full Disk Access는 훨씬 넓은 저장소 접근입니다. Apple의 macOS 파일 접근 제어 안내에서도 항목과 승인 방식이 구분돼 있습니다.

넓은 권한부터 주지 않아요
파일이 열리지 않는다는 이유만으로 Full Disk Access부터 켜면 원인을 가리고 영향 범위만 키울 수 있어요. 먼저 어떤 프로세스가 어느 경로에 접근하는지 적습니다. 그다음 필요한 항목만 승인하고 같은 입력으로 다시 시험해요. 승인 창이 나타나지 않았다고 권한 문제가 없다고 단정해서도 안 됩니다. 이전 거부 기록이나 실행 주체 차이도 확인해야 해요.
시스템 설정의 이름과 위치는 macOS 버전에 따라 달라질 수 있습니다. 배포 문서에는 클릭 순서만 쓰지 말고 운영체제 버전, 승인 대상 앱 또는 실행 주체, 필요한 접근 범위를 함께 적으세요. 사용자가 무엇을 허용하는지 이해할 수 있는 설명도 넣습니다.
다른 앱을 제어하는 승인 흐름을 재현했나요?
AppleScript나 JXA가 Finder, Mail, Calendar 같은 앱에 명령을 보내면 Automation 승인이 관련될 수 있어요. 반면 화면 좌표를 누르거나 UI 요소를 조작하는 방식은 Accessibility 검토가 필요할 수 있습니다. 두 권한을 서로 대신할 수 있다고 보면 안 됩니다. 대상 앱과 동작에 따라 결과가 다르므로 실제 조합으로 시험해요.
- 깨끗한 테스트 계정에서 최초 실행과 승인 대화상자를 확인합니다.
- 허용했을 때와 거부했을 때의 메시지와 종료 상태를 기록합니다.
- 대상 앱이 종료됐거나 응답하지 않을 때 제한 시간을 확인합니다.
- 앱 이름, 버전, 제어 기능, 다루는 데이터 범위를 배포 기록에 남깁니다.
사용자는 시스템 설정의 Automation에서 앱별 제어 허용 상태를 검토하고 바꿀 수 있습니다. 구체적인 확인 위치는 Apple의 앱 자동화 권한 안내를 참고하되, 배포 대상 macOS에서 메뉴 명칭을 다시 확인하세요. 개인정보가 든 메일이나 일정 내용을 로그에 복사하지 않는 것도 중요합니다.
launchd로 배포한다면 plist를 검증했나요?
LaunchAgent와 LaunchDaemon의 범위를 나눠요
로그인한 사용자별 작업과 시스템 수준 작업은 실행 맥락이 달라요. 사용자 앱 제어와 홈 폴더 작업이라면 LaunchAgent가 자연스러운지 먼저 검토합니다. 시스템 서비스라는 이유만으로 LaunchDaemon이나 관리자 권한을 택하지 마세요. 설치 위치, 소유자, 실행 계정, 로그인 필요 여부를 한 묶음으로 기록해야 합니다.
plist의 핵심 키를 읽어 봐요
Label은 다른 작업과 겹치지 않는 고유한 값으로 정합니다. ProgramArguments에는 실행 프로그램과 각 인자를 배열 요소로 분리하고, 실제 존재하는 절대 경로를 우선 검증해요. KeepAlive는 무조건 켜는 옵션이 아닙니다. 계속 살아 있어야 하는 서비스인지, 정해진 시점이나 요청 때만 실행할 작업인지 판단하세요.
plutil -lint ~/Library/LaunchAgents/com.team.job.plist
test -x /opt/team/bin/job.sh
plutil 통과는 XML 문법 확인일 뿐입니다. 인자, 파일 접근, 실행 시점까지 보증하지 않아요. 표준 출력과 오류 로그 경로는 실행 계정이 만들고 쓸 수 있어야 합니다. Apple의 launchd 문서는 일부가 아카이브 자료이므로 개념을 확인하는 데 활용하고, 실제 배포 명령과 세부 동작은 대상 macOS에서 재검증하는 편이 안전합니다.

오류 처리와 중복 실행 방지를 준비했나요?
운영 자동화의 목표는 절대 실패하지 않는 코드가 아니라, 실패를 알아보고 안전하게 멈추는 코드에 가까워요. 네트워크 단절, 외장 디스크 분리, 입력 파일 없음, 권한 거부, 대상 앱 무응답을 각각 만들어 봅니다. 재시도에는 횟수와 간격을 두고, 영구적인 권한 오류를 무한 반복하지 않게 해요.
동시에 두 번 실행될 가능성도 봐야 합니다. 잠금 파일이나 원자적 디렉터리 생성을 이용하되, 비정상 종료 뒤 남은 잠금을 판별할 기준도 필요해요. 결과 파일은 임시 이름으로 쓴 뒤 검증이 끝나면 바꾸고, 이동 전에는 목적지 충돌을 확인합니다. 파괴적인 작업은 미리보기 모드나 별도 보관 폴더를 두면 복구가 쉬워집니다.
- 각 실패 지점은 사람이 이해할 오류 메시지와 0이 아닌 종료 상태를 남깁니다.
- 부분 성공을 전체 성공으로 기록하지 않습니다.
- 시간 제한을 두어 응답 없는 앱을 무한히 기다리지 않습니다.
- 재시도해도 같은 항목이 중복 처리되지 않는지 확인합니다.
- 삭제 전 대상 목록과 복구 위치를 기록합니다.
로그와 배포 기록을 남길 준비가 됐나요?
제가 오래된 사내 도구를 자동화하며 가장 자주 꺼내 본 것은 소스보다 배포 기록이었어요. 로그에는 시작·성공·실패 시각, 스크립트 버전, 실행 계정, 입력 개수, 처리 개수, 오류 단계 정도를 남깁니다. “실패” 한 줄보다 “입력 검사 단계에서 파일 0개로 종료”가 훨씬 쓸모 있어요.
반대로 토큰, 비밀번호, 세션 값, 개인 문서 내용, 메일 본문은 남기지 않습니다. 파일명 자체가 민감할 수 있다면 식별자를 마스킹하거나 개수만 기록해요. 로그 파일의 위치, 최대 크기, 보존 기간, 열람 가능한 사용자를 정하고 디스크가 가득 찼을 때 동작도 확인합니다.
| 기록 파일 | 포함할 내용 | 제외할 내용 |
|---|---|---|
| 실행 로그 | 시각, 버전, 단계, 결과, 오류 코드 | 비밀번호, 토큰, 원문 데이터 |
| 배포 기록 | 설치 위치, plist 위치, 권한, 담당자 | 개인 계정의 인증 정보 |
| 변경 기록 | 변경 이유, 영향, 테스트 결과 | 검증하지 않은 추측 |
| 복구 기록 | 이전 버전, 백업 위치, 복원 순서 | 실행 불가능한 임시 메모 |
배포 전 테스트와 원상복구를 실제로 해봤나요?
테스트는 정상 입력 하나로 끝내지 않아요. 빈 입력, 읽기 전용 파일, 사라진 폴더, 끊긴 네트워크, 종료된 대상 앱, 권한 거부를 재현합니다. 새 사용자 계정이나 운영 조건과 비슷한 테스트 Mac에서 최초 실행도 봐야 해요. Automator에서 성공했다면 저장된 워크플로를 실제 호출 방식으로 다시 실행하고, 수동 터미널 실행 결과와 비교합니다.
복구도 문서만 두지 말고 한 번 수행해 봅니다. 새 스크립트와 plist를 내리고 이전 버전을 올리는 순서, 생성 파일을 격리하는 위치, 변경된 데이터를 복원하는 방법을 확인해요. 중단 시점에 따라 무엇이 남는지도 적습니다. 되돌리기가 데이터까지 복원하는지, 실행 파일만 이전 버전으로 바꾸는지도 분명히 해야 합니다.
최종 자가진단 체크리스트
- ☐ 자동화의 목적, 입력, 성공 조건을 한 문장으로 설명할 수 있다.
- ☐ 실행 계정, 로그인 필요 여부, 실행 시점을 알고 있다.
- ☐ 셸,
PATH, 현재 디렉터리와 모든 필수 경로를 배포 환경에서 확인했다. - ☐ Files & Folders, Automation, Accessibility, Full Disk Access를 구분하고 필요한 권한만 요청한다.
- ☐ 외부 앱 제어의 허용·거부 흐름과 앱 미실행 상황을 재현했다.
- ☐ plist 문법, 고유한 Label, ProgramArguments, 실행 파일 권한과 로그 경로를 검증했다.
- ☐ 입력 누락, 네트워크 단절, 권한 거부를 안전하게 처리한다.
- ☐ 동시 실행과 재실행으로 파일이나 작업이 중복되지 않는다.
- ☐ 로그만 보고 실패 단계와 버전을 찾을 수 있으며 민감 정보는 남지 않는다.
- ☐ 테스트 데이터로 정상·실패 사례를 실행했고 결과를 기록했다.
- ☐ 배포를 취소하고 실행 파일, 설정, 변경 데이터를 이전 상태로 되돌릴 수 있다.
이 항목 중 답하지 못한 것이 하나라도 있다면 배포를 미루고, 그 항목의 실행 결과와 복구 방법부터 기록하는 편이 안전해요.