macOS에서 떠 있는 대화상자, 멈춰버린 로그인 창, 정체불명의 팝업을 바라보며 이 창을 만든 프로세스가 무엇인지 궁금했던 적이 있다면 당신만 그런 것이 아닙니다. Finder나 Dock에서는 답이 명확하게 드러나지 않으며, Activity Monitor도 일부분만 도움이 됩니다.
빠른 답변
macOS에서 특정 창을 어떤 프로세스가 소유하고 있는지 알아내는 가장 신뢰할 수 있는 기본 방법은, CGWindowListCopyWindowInfo로 Quartz Window Services를 조회하여 해당 창의 kCGWindowOwnerPID를 읽은 다음 그 PID를 ps로 살펴보는 것입니다. Activity Monitor로 범위를 좁힐 수는 있지만, 창과 프로세스의 정확한 매핑은 Quartz가 제공합니다.
macOS에서 이것이 보기보다 어려운 이유
macOS에는 “이 창을 마우스 오른쪽 버튼으로 클릭하면 PID를 보여 준다” 같은 명확한 기능이 없습니다. 하나의 앱이 여러 개의 창, 여러 개의 헬퍼 프로세스, 여러 개의 백그라운드 에이전트를 소유할 수 있습니다. 또한 일부 창은 보이는 제목이 없어서 수동으로 추측하기가 어렵습니다.
Apple의 문서가 그 이유를 설명합니다. 창 정보 딕셔너리에서 kCGWindowOwnerPID는 필수 키이지만, kCGWindowOwnerName과 kCGWindowName은 선택 사항입니다. 즉, 소유 PID는 신뢰할 수 있지만 앱 이름과 창 제목은 일부 창에서 누락될 수 있습니다.
방법 1: 이미 어떤 앱인지 알 때는 Activity Monitor 사용
이미 어떤 앱이 그 창을 만들었는지 짐작할 수 있다면, Activity Monitor가 프로세스를 확인하는 가장 빠른 기본 GUI 도구입니다.
목록을 좁히는 방법
/Applications/Utilities/에서 Activity Monitor를 엽니다.- View > Windowed Processes를 선택하여 창을 만들 수 있는 프로세스를 표시합니다.
- 부모-자식 관계의 맥락이 필요하면 View > All Processes, Hierarchically를 선택합니다.
- 앱 이름을 검색한 다음 정보 패널을 열거나 PID를 기록합니다.
이는 “이 팝업이 Safari, Slack, 아니면 어떤 헬퍼 앱에서 온 것인가?” 같은 흔한 경우에 유용합니다.
Activity Monitor의 한계
Activity Monitor는 _이 특정 창_을 _그 특정 PID_에 직접 매핑해 주는 것이 아니라, 창을 만들 수 있는 프로세스를 보여 줍니다. 다음과 같은 경우에는 훨씬 덜 신뢰할 수 있습니다.
- 앱이 여러 헬퍼 프로세스를 생성하는 경우,
- 창 제목이 앱 이름과 일치하지 않는 경우,
- 창이 백그라운드 에이전트에 속하는 경우,
- 또는 조회를 스크립트로 자동화해야 하는 경우.
창의 정확한 소유 관계를 알려면 Quartz를 사용하세요.
방법 2: Quartz Window Services로 창을 PID에 매핑
Apple의 Core Graphics API인 CGWindowListCopyWindowInfo는 소유 PID를 포함하여 화면에 표시된 창의 메타데이터를 반환합니다. 완전한 앱을 만들지 않고도 짧은 Swift 명령으로 직접 호출할 수 있습니다.
보이는 창을 소유 프로세스와 함께 나열하기
swift -e '
import Foundation
import CoreGraphics
let query = CommandLine.arguments.dropFirst().joined(separator: " ").lowercased()
let windows = CGWindowListCopyWindowInfo(
[.optionOnScreenOnly, .excludeDesktopElements],
kCGNullWindowID
) as? [[String: Any]] ?? []
for window in windows {
let owner = (window[kCGWindowOwnerName as String] as? String) ?? ""
let pid = (window[kCGWindowOwnerPID as String] as? Int) ?? 0
let title = (window[kCGWindowName as String] as? String) ?? ""
guard !owner.isEmpty else { continue }
guard query.isEmpty ||
owner.lowercased().contains(query) ||
title.lowercased().contains(query) else { continue }
print("PID: \(pid)\tApp: \(owner)\tWindow: \(title)")
}
' "Safari"
"Safari"를 식별하려는 앱 이름이나 창 제목의 일부로 바꾸세요. 검색어를 생략하면 명령은 현재 열거할 수 있는 모든 보이는 창을 출력합니다.
출력이 알려 주는 것
- PID:
kCGWindowOwnerPID에서 가져온 소유 프로세스 ID - App:
kCGWindowOwnerName에서 가져온 프로세스 이름 - Window: 사용 가능한 경우
kCGWindowName에서 가져온 제목
진짜 궁금한 것이 “_이 특정 창_을 어떤 프로세스가 소유하고 있는가?”라면 이것이 가장 좋은 기본 방법입니다.
PID를 얻은 후 프로세스 조사하기
PID를 얻으면 ps로 실행 파일과 명령줄을 확인하세요.
ps -p <PID> -o pid,ppid,comm,args
예시:
ps -p 1234 -o pid,ppid,comm,args
이를 통해 수상한 창에서 정확한 바이너리, 부모 프로세스, 실행 인자로 곧장 이동할 수 있습니다.
중요한 주의사항
kCGWindowName이 선택 사항이기 때문에 일부 창은 제목이 비어 있습니다.- 시스템 오버레이와 유틸리티 패널은 같은 앱에 속하더라도 별도의 창으로 나타날 수 있습니다.
- 실제로 보호된 앱은 검사 도구가 적절한 macOS 개인정보 보호 권한을 가질 때까지 메타데이터를 덜 노출할 수 있습니다.
방법 3: 대화형 조사를 위해 ProcXray 사용
이 작업을 자주 한다면 원시 명령은 번거로워집니다. 정체불명의 창에서 그 주변 프로세스 맥락으로 빠르게 이동해야 할 때는 **ProcXray**가 더 낫습니다.
반복적인 디버깅에 ProcXray가 더 나은 이유
- 실시간 프로세스 트리는 소유 프로세스를 무엇이 실행했는지 보여 줍니다.
- 명령줄 검사는 헬퍼 프로세스와 메인 앱을 구분하는 데 도움이 됩니다.
- 환경 변수 검사는 Activity Monitor가 숨기는 실행 맥락을 드러냅니다.
- 단명 프로세스 캡처는 수상한 창이 잠깐만 나타날 때 도움이 됩니다.
- 코드 서명 가시성은 해당 프로세스가 예상된 것인지, 서명되지 않은 것인지, 의심스러운 것인지 판단하는 데 도움이 됩니다.
창이 헬퍼 프로세스, 업데이터, 일시적인 백그라운드 도구에 속한다면 그 주변 맥락이 PID 하나보다 더 중요합니다.
다음 관련 가이드도 참고해 보세요.
Activity Monitor vs Quartz vs ProcXray
| 방법 | 가장 적합한 용도 | 강점 | 한계 |
|---|---|---|---|
| Activity Monitor | 빠른 시각적 확인 | 기본 제공, 사용이 쉬움, PID 표시 | 임의의 창을 소유자에게 직접 매핑하지 못함 |
| Quartz 창 조회 | 정확한 창-PID 조회 | 공식 API, 스크립트 가능, 정밀함 | 원시 출력은 수동 후속 작업이 필요함 |
| ProcXray | 실제 조사 및 반복적인 디버깅 | 계보, 환경 변수, 서명, 단명 프로세스 가시성을 추가 | 별도의 앱 설치가 필요함 |
결론: 정확한 답이 한 번만 필요하다면 Quartz 조회를 사용하세요. 창, 헬퍼, 단명 프로세스를 정기적으로 조사한다면 ProcXray를 사용하세요.
자주 묻는 질문
Activity Monitor가 macOS에서 특정 창을 소유한 프로세스를 보여 줄 수 있나요?
직접적으로는 아닙니다. Activity Monitor는 Windowed Processes로 필터링하고 가능성 있는 앱 프로세스를 살펴보는 데는 도움이 되지만, 단일 창을 정확한 PID에 한 번에 매핑해 주지는 않습니다. Quartz Window Services가 더 정밀한 기본 방법입니다.
창의 소유 프로세스를 찾는 Apple의 공식 API는 무엇인가요?
Apple은 창 메타데이터를 가져오는 Core Graphics 함수로 CGWindowListCopyWindowInfo를 문서화하고 있습니다. 반환되는 딕셔너리에는 필수 키로 kCGWindowOwnerPID가 포함되어 있어, 창을 소유 프로세스에 매핑하는 표준 필드가 됩니다.
macOS 창 제목이 가끔 비어 있는 이유는 무엇인가요?
kCGWindowName이 선택 사항이며 항상 보장되지 않기 때문입니다. 일부 창은 소유 PID는 노출하지만 사용자에게 보이는 제목은 노출하지 않습니다. 이는 많은 유틸리티 창, 시스템 오버레이, 보호된 앱 화면에서 정상적인 현상입니다.
PID를 찾은 후 다음으로 무엇을 해야 하나요?
ps -p <PID> -o pid,ppid,comm,args를 실행하여 실행 파일 경로, 부모 프로세스, 명령줄 인자를 확인하세요. 프로세스가 여전히 수상해 보인다면 그다음으로 파일 디스크립터, 네트워크 활동, 코드 서명을 살펴보세요.
출처 및 참고 자료
- Apple Developer:
CGWindowListCopyWindowInfo - Apple Developer: Required Window List Keys
- Apple Developer: Optional Window List Keys
- Apple Support: View information about Mac processes in Activity Monitor
- Apple Support: Activity Monitor User Guide
- macOS 기본 참고 자료:
man ps
ProcXray 무료 다운로드 → — 수상한 창 뒤의 프로세스를 더 빠르게 조사하는 방법.