Mac에서 .pkg 패키지로 설치한 앱 제거하는 방법
.pkg 설치 프로그램으로 들어온 앱은 디스크 이미지에서 끌어다 놓은 앱과 같지 않습니다. 설치 프로그램은 root로 실행되었고, 패키지가 지시하는 곳이면 어디든 쓸 수 있었으며, 설치한 내용을 설치 프로그램의 영수증 데이터베이스에 기록으로 남겼습니다. 앱을 휴지통으로 끌어다 놓으면 그 기록 속 폴더 하나가 지워질 뿐, 기록 자체를 포함한 나머지는 그대로 남습니다. 이 글은 바로 그 경우를 다룹니다. 앱이 패키지로 설치되었는지 확인하는 방법, 패키지가 디스크에 무엇을 두었는지 읽는 방법, 무엇을 지우고 무엇을 남길지입니다. Finder가 아예 거부하거나 삭제한 앱이 다시 나타난다면 Mac 앱이 제거되지 않을 때부터 보시고, 직접 끌어다 설치한 앱이라면 완전한 제거 가이드에서 일반적인 방법을 다룹니다.
휴지통만으로는 부족한 이유
패키지는 앱 안뿐 아니라 앱 바깥에도 파일을 둘 수 있습니다. 공식 설치 프로그램으로 앱을 다시 설치했다 제거해 보니, Zoom 공식 패키지는 zoom.us.app 바깥에 launchd 작업 세 개와 권한 헬퍼 us.zoom.ZoomDaemon을 남겼습니다. Logi Options+ 설치 프로그램은 두 번째 제품인 LogiRightSight까지 설치했고, 이 제품에는 자체 영수증과 자체 LaunchAgent가 있었습니다. DisplayLink Manager는 /Library/LaunchAgents에 LaunchAgent를 추가했습니다. Microsoft Office는 Word, Excel, PowerPoint가 모두 불러오는 공유 프레임워크 패키지를 설치하고, Microsoft AutoUpdate와 라이선스 헬퍼도 함께 따라옵니다. 앱 번들을 옮겨도 이 중 어느 것도 함께 옮겨지지 않습니다.
영수증도 옮겨지지 않습니다. 영수증은 그것이 설명하는 파일과는 별도로 설치 프로그램 자체의 데이터베이스에 있으므로, 앱을 제거해도 pkgutil은 여전히 그 패키지를 설치된 것으로 보고합니다. DisplayLink 공식 제거 도구가 문제없이 끝난 뒤에도 영수증 두 개는 그대로 있었습니다.
Finder의 암호 입력 요구도 패키지를 상대하고 있다는 또 다른 신호입니다. 설치 프로그램이 root로 실행되었으니 남긴 번들도 root 소유이고, 옮기려면 인증이 필요합니다. 이것은 정상이며 제거 문제 해결 가이드에서 다룹니다.
패키지로 설치되었는지 확인하기
영수증 목록과 앱 자체의 경로부터 살펴봅니다.
pkgutil --pkgs | grep -i zoom
pkgutil --file-info /Applications/zoom.us.app
pkgutil --pkgs는 설치 프로그램이 시동 볼륨에 기록한 모든 패키지 ID를 나열합니다. 앱의 번들 식별자만이 아니라 개발사 이름과 제품 이름으로도 검색하세요. 둘이 전혀 닮지 않은 경우가 많기 때문입니다. Zoom 앱은 us.zoom.xos이고 영수증은 us.zoom.pkg.videomeeting입니다. Cookie.app을 설치하는 영수증은 app.fantasticthing.Bookkeeping입니다. 대소문자가 다를 때도 있습니다. 爱思助手의 번들 식별자는 cn.i4Tools.mac이고 영수증은 cn.i4tools.mac인데, pkgutil은 ID를 정확히 일치시키므로 대소문자가 섞인 표기로는 영수증이 바로 거기 있는데도 "No receipt"라고 답합니다. ID는 직접 입력하지 말고 --pkgs 출력에서 복사하세요.
pkgutil --file-info는 원래 어떤 경로를 설치한 패키지를 경로 아래 pkgid: 줄로 알려 주어야 합니다. 답이 없다고 해서 「패키지로 설치된 것이 아니다」로 읽지는 마세요. macOS 27에서 확인해 보니 대부분의 경로에 대해 삭제되었든 존재하든 volume과 path만 출력했습니다. DisplayLink Manager 앱도 영수증 두 개가 아직 Mac에 있는데 이렇게 빈 답을 받았습니다. 영수증이 있다고 해서 사용자가 직접 .pkg를 실행했다는 증거도 아닙니다. Mac App Store도 com.apple.pkg.TestFlight처럼 일부 앱에 영수증을 남깁니다.
영수증에 기록되는 것
패키지 하나가 무엇을 어디에 설치했는지는 명령 두 개로 볼 수 있습니다.
pkgutil --pkg-info us.zoom.pkg.videomeeting
pkgutil --files us.zoom.pkg.videomeeting
--pkg-info는 패키지 ID, 버전, volume, location, 설치 시각을 출력합니다. --files는 그 볼륨과 위치를 기준으로 한 경로를 출력하므로, 실제 경로는 이 셋을 이어 붙인 것입니다. 위치가 Applications인 영수증은 Foo.app/Contents/...를 나열하고, 위치가 비어 있는 영수증은 대신 Applications/Foo.app/...를 나열합니다. 목록을 읽기 전에 위치부터 확인하세요. 그러지 않으면 찾아보는 경로가 전부 틀립니다.
목록에는 파일뿐 아니라 디렉터리도 들어 있습니다. --only-files와 --only-dirs로 둘을 나눌 수 있는데, 영수증이 Library와 Library/LaunchAgents 자체를 나열할 수 있다는 것을 알고 나면 쓸모가 있습니다. 원본 기록은 패키지마다 .bom 하나와 .plist 하나로 /private/var/db/receipts에 있지만, pkgutil 매뉴얼은 영수증 파일의 위치가 바뀔 수 있으니 항상 pkgutil로 조회하라고 말합니다.
영수증은 삭제 목록이 아니라 지도
pkgutil --files를 반복문에 넣고 전부 지우고 싶어지기 쉽습니다. 패키지를 제거하다 다른 것을 망가뜨리는 전형적인 방식입니다. 이 목록이 말해 주는 것은 이 패키지가 쓴 것이지, 이 패키지만 쓰는 것이 아닙니다.
| 목록에 들어 있는 것 | 그냥 지우면 안 되는 이유 |
|---|---|
Applications, Library, Library/LaunchAgents 같은 디렉터리 |
패키지가 만들거나 건드렸지만, Mac의 다른 모든 앱도 사용함 |
| 개발사가 여러 앱에서 공유하는 프레임워크와 헬퍼 | Word, Excel, PowerPoint가 모두 Office 공유 프레임워크를 불러오며, 없으면 실행하자마자 충돌함 |
| 여러 앱이 공유하는 콘텐츠 | GarageBand, Logic Pro, MainStage, Final Cut Pro가 /Library/Application Support/GarageBand, /Library/Application Support/Logic, /Library/Audio/Apple Loops를 공유하며, 이것들은 com.apple.pkg.MAContent10_* 영수증에 기록됨 |
| 같은 설치 프로그램이 함께 가져온 다른 제품 | LogiRightSight는 Logi Options+와 함께 들어왔고 단독으로도 계속 동작함 |
| LaunchAgent와 LaunchDaemon plist | 로드된 작업은 plist를 지우기 전에 멈춰야 하며, 그러지 않으면 launchd가 디스크에 아무것도 없는 작업을 계속 붙잡고 있음 |
목록에서 빠지는 것도 있습니다. 영수증은 패키지 페이로드가 디스크에 둔 것을 기록합니다. 설치 스크립트는 그 이상을 할 수 있고, 패키지에는 그런 스크립트가 들어 있습니다. 예를 들어 Foxit 패키지에는 postinstall 스크립트와 업데이트 서비스가 있습니다. 앱은 실행되고 나면 홈 폴더의 라이브러리에 자체 데이터를 쓰는데, 이것은 어떤 영수증에도 없습니다. 그쪽은 앱 제거 후 잔여물 찾기를 참고하세요.
개발사 제거 도구부터 실행하기
Apple의 앱 삭제 안내는 이 점을 분명히 말합니다. 앱에 제거 프로그램이 포함되어 있다면 「앱은 물론 앱이 다른 위치에 저장했을 수 있는 로그인 항목, 확장 프로그램, 기타 데이터를 삭제하는 가장 좋은 방법」이라는 것입니다. 패키지로 설치되는 소프트웨어는 제거 도구를 함께 제공하는 경우가 많습니다. 개발사가 자기 스크립트, 헬퍼, 공유 구성 요소를 알고 있기 때문입니다. 패키지가 들어 있던 디스크 이미지, 응용 프로그램 폴더 안의 앱 폴더, /Applications/Utilities, 앱 자체의 메뉴, 개발사 지원 사이트를 살펴보세요. 한 예로 Splashtop Personal은 패키지와 같은 디스크 이미지에 제거 도구를 넣어 둡니다.
앱을 이미 휴지통으로 끌어다 놓았다면 파일 › 되돌려 놓기로 되돌린 뒤 앱을 열고 거기서 제거 도구를 실행하세요. 보안 소프트웨어, VPN 클라이언트, 드라이버는 개발사 도구가 선택이 아니라 필수입니다. 확장 프로그램과 네트워크 필터는 그것을 소유한 앱을 통해서만 내려갈 수 있으며, 이는 Mac에서 백신 프로그램 제거하기에서 다룹니다.
직접 제거하기
제거 도구가 없을 때는 영수증이 어디를 봐야 할지 알려 줍니다. 다음 순서로 진행합니다.
- 앱과 앱이 백그라운드에서 실행하는 것을 모두 종료합니다.
--pkg-info로 위치를 확인한 다음--files로 목록을 읽고, 앱 번들 바깥에 있는 경로를 적어 둡니다.- 목록에 있는 LaunchAgent나 LaunchDaemon마다 plist를 옮기기 전에
launchctl bootout으로 작업을 언로드합니다. 순서가 왜 중요한지는 문제 해결 가이드의 launchd 섹션에서 설명합니다. - 이 제품의 것이 분명한 것만 휴지통으로 옮깁니다. 앱 번들, 번들 식별자나 제품 이름을 딴 폴더와 plist,
/Library/PrivilegedHelperTools에 있는 헬퍼입니다. 공유 상위 폴더와 개발사의 다른 앱이 아직 쓰는 것은 남겨 둡니다.pkgutil --pkgs | grep -i vendorname으로 같은 개발사의 다른 패키지가 아직 설치되어 있는지 알 수 있으며, 설치되어 있다면 공유 프레임워크는 남겨 둡니다. - 목록에 있는 것이 하나도 남지 않았을 때 마지막으로 영수증을 지웁니다.
sudo pkgutil --forget com.vendor.pkg
--forget은 영수증을 버리며, 매뉴얼의 표현을 빌리면 「설치된 파일은 건드리지 않습니다」. 이것을 먼저 실행하면 모든 파일이 그대로 남은 채 그 파일들을 가리키는 기록만 사라져, 남은 작업이 더 어려워집니다. /private/var/db/receipts가 root 소유라서 sudo가 필요하고, ID는 --pkgs에 표기된 그대로 입력해야 합니다. 남은 영수증에는 사용자 데이터가 없으므로, 목록에 있는 무언가가 아직 쓰이는지 확신이 서지 않으면 영수증을 남겨 두어도 손해 볼 것이 없습니다.
결과 확인하기
아래 명령은 읽기만 합니다. com.vendor.pkg와 vendorname은 위에서 찾은 값으로 바꾸세요.
id=com.vendor.pkg
loc=$(pkgutil --pkg-info "$id" | sed -n 's/^location: //p')
pkgutil --files "$id" --only-files | while IFS= read -r f; do
p="/${loc:+$loc/}$f"
[ -e "$p" ] && echo "$p"
done
pkgutil --pkgs | grep -i vendorname
ls /Library/LaunchAgents /Library/LaunchDaemons /Library/PrivilegedHelperTools | grep -i vendorname
launchctl list | grep -i vendorname
launchctl print system | grep -i vendorname
반복문은 영수증에 있는 파일 중 아직 존재하는 것을 전체 경로와 함께 모두 출력합니다. 아무것도 출력되지 않으면 페이로드가 사라진 것이고 영수증을 지워도 안전합니다. 앱 번들 안의 경로가 출력되면 앱이 아직 설치되어 있는 것이고, 그 밖의 경로는 제거할 때 놓쳤거나, 다른 앱과 공유하기 때문에 남기기로 한 것입니다. pkgutil이 "No receipt for ... found"라고 답하면 영수증이 이미 지워졌거나 ID 표기가 다른 것입니다. ls와 launchctl 줄은 영수증에 한 번도 나오지 않은 헬퍼를 잡아냅니다. launchctl list는 내 LaunchAgent를, launchctl print system은 데몬을 보여 줍니다. 어느 쪽에서든 줄이 출력되면 작업이 아직 로드되어 있다는 뜻이고, 첫 번째 열이 0이 아닌 숫자면 지금 실행 중입니다.
Mole이 pkg로 설치된 앱을 처리하는 방법
Mole에서 앱을 제거하면, 이름이 앱의 번들 식별자나 제품 이름과 일치하는 영수증을 읽고 그중 아직 존재하는 경로를 나열합니다. 다만 범위는 좁습니다. 응용 프로그램 폴더의 앱 번들, 그리고 /Library 아래에서는 Application Support, Caches, Logs, PrivilegedHelperTools, WebKit, HTTPStorages 폴더와 정확히 그 번들 식별자로 이름 붙은 Preferences, LaunchAgents, LaunchDaemons plist만입니다. 이 줄들은 체크되지 않은 상태로 나오므로, 하나씩 읽어 본 뒤 직접 체크합니다. /Users, /opt, /usr, /private 아래 경로는 영수증에서 절대 목록 줄이 되지 않으며, 영수증 파일 자체도 마찬가지입니다.
앱이 사라진 뒤 Mole은 번들 식별자를 이름으로 쓰는 영수증을 디스크에 있는 pkgutil의 표기 그대로 지우고, pkgutil --file-info로 찾은 개발사 영수증도 지웁니다. 후자는 그 영수증이 나열하는 파일이 하나도 남아 있지 않을 때만입니다. 이 작업은 해당 제거에 대해 관리자 헬퍼가 이미 승인된 경우에만 하므로, 영수증 때문에 암호 입력 창이 한 번 더 뜨는 일은 없습니다. 개발사 영수증을 찾을 때 Apple의 com.apple.* 영수증은 건너뜁니다.
한계는 위에서 설명한 그대로입니다. macOS 27에서는 pkgutil --file-info가 거의 답하지 않기 때문에, ID가 앱과 아무 관련 없는 영수증은 Mole이 앱을 제거한 뒤에도 남을 수 있습니다. DisplayLink의 영수증 두 개와 Zoom의 영수증이 그랬습니다. 이것들은 기록일 뿐이며 sudo pkgutil --forget으로 지울 수 있습니다. 드라이버, VPN 클라이언트, 보안 소프트웨어에서는 Mole이 개발사 제거 도구를 대신하지 않습니다.
자주 묻는 질문
pkgutil --forget을 실행하면 앱이 제거되나요?
아닙니다. 매뉴얼에 따르면 이 명령은 패키지의 영수증 데이터를 모두 버리지만 설치된 파일은 건드리지 않습니다. 파일을 지운 뒤에 실행하고, 파일을 지우는 대신 실행하지는 마세요.
pkgutil --files가 나열하는 파일을 모두 지워도 되나요?
안 됩니다. 목록에는 Library와 Applications 같은 시스템 디렉터리, 개발사의 다른 앱이 불러오는 프레임워크, 아직 실행 중일 수 있는 작업의 plist가 들어 있습니다. 검토할 대상을 찾는 데 쓰고, 이 제품에만 속한 것을 지우세요.
앱은 사라졌는데 pkgutil --pkgs에 아직 나옵니다. 아직 설치된 건가요?
꼭 그렇지는 않습니다. 파일을 지워도 영수증은 갱신되지 않으므로, 누군가 지울 때까지 남아 있습니다. 위의 확인용 반복문을 실행해 보세요. 영수증에 있는 것이 하나도 남아 있지 않다면 기록만 남은 것이고, sudo pkgutil --forget으로 지울 수 있습니다.