macOS의 XProtect 검증이 빌드 스크립트와 테스트 바이너리 실행을 지연시켜 Rust 빌드/테스트/실행이 느려질 수 있다. 터미널을 ‘개발자 도구’로 등록해 검사를 우회하면 큰 속도 향상을 얻을 수 있으며, 실제 사례와 영향, 보안상의 주의점, Cargo의 경고 도입 논의 등을 다룬다.
Mac에서 더 빠른 Rust 빌드
macOS에는 Rust 빌드를 더 빠르게 만들 수 있는 비밀 설정이 있다는 걸 알고 있었나요? Rust 테스트도 더 빨라질 수 있습니다(때로는 엄청나게). 아마 C, C++, Go, Swift 같은 다른 컴파일 언어에도 비슷한 효과가 있을 겁니다. 황당하게 들리겠지만, 계속 읽어 보세요…
아이작 아시모프는 과학에서 들을 수 있는 가장 흥미로운 말은 “유레카!”가 아니라 “이상하네…”라고 말했다고 전해집니다.
최근 Mac에서
cargo build
--timings
의 출력을 보다가 이상한 점을 발견했습니다. 빌드 스크립트가 이상할 정도로 오래 걸렸습니다. 2019년형 MacBook Pro에서 wild를 컴파일하며 얻은 다음 출력을 보세요.

시간은 x축에 있습니다. 각 파란색/보라색 막대는 컴파일러의 단일 호출을 의미합니다. (이 이미지는 출력의 일부만 보여 줍니다. 전체 컴파일에는 100개가 넘는 크레이트가 있습니다.) 각 주황색 막대는 빌드 스크립트 실행 시간을 나타냅니다. 주황색 막대가 꽤 길죠!
빌드 스크립트는 일반적인 Cargo 워크플로 밖의 커스텀 작업을 수행할 수 있게 해 줍니다. C 컴파일러를 호출해 라이브러리를 빌드하는 경우처럼 느릴 것으로 기대되는 경우도 있습니다. 하지만 종종 아주 사소한 작업이기도 합니다. 흔한 예로 rustc --version을 실행해 설치된 컴파일러 버전을 확인하고 그에 맞춰 설정을 조정하는 일이 있습니다.
이 출력에 보인 빌드 스크립트들은 모두 매우 빨리 끝나야 하는 단순한 것들입니다. 실제로 리눅스에서는 그렇게 측정되었습니다. 그런데 왜 Mac에서는 0.48초에서 3.88초나 걸렸을까요? 그리고 왜 하나하나가 갈수록 더 느려졌을까요?
Cargo를 통해서가 아니라, 이들 빌드 스크립트 몇 개를 직접 실행해 보았습니다. 그랬더니 훨씬 빨랐습니다. 예를 들어 300ms 대신 75ms였습니다. 이상하네요. 처음에는 Cargo가 빌드 스크립트 실행 시간을 잘못 측정하는 게 아닐까 의심했습니다. Cargo의 관련 코드를 살펴봤지만 꽤 단순했고, 문제가 숨어 있을 것 같지는 않았습니다.
더 파기 전에, 혹시 이 현상을 아는 사람이 있는지 Zulip에 질문했습니다. Weihang Lo 가 코드 서명 검증이나 다른 보안 검사 때문일 수 있다고 제안했습니다.
잠깐, 뭐라고요? 예상과는 달랐지만 맞는 답이었습니다. macOS에는 XProtect라는 백신 기능이 있습니다.
XProtect는 다음과 같은 경우 알려진 악성 콘텐츠를 검사합니다:
- 앱이 처음 실행될 때
- 앱이(파일 시스템에서) 변경되었을 때
- XProtect 시그니처가 업데이트되었을 때
다시 말해, OS는 실행 파일을 처음 실행할 때마다 악성코드 검사를 수행합니다. 인터넷에서 내려받은 실행 파일에 대해서는 타당합니다. 하지만 직접 컴파일한 실행 파일에까지 그럴 필요가 있을까요? 사실, 빌드 스크립트는 성능 관점에서 이런 검사에 최악의 경우입니다. 보통 각 빌드 스크립트 실행 파일은 정확히 한 번만 실행되기 때문입니다.
(XProtect는 Gatekeeper라는 또 다른 보안 기능과 밀접하게 관련되어 있습니다. 제 이해로는 Gatekeeper가 서명된 코드를 검증하고, XProtect는 일반적인 악성코드 검사를 수행합니다. 사람들은 흔히 이런 모든 활동을 통칭해 “Gatekeeper”라고 부르기도 합니다.)
시스템 설정에서 터미널(또는 iTerm 같은 대체 터미널 앱)을 “개발자 도구”로 추가하면 이 검사를 피할 수 있습니다. 자세한 방법은 이 문서를 참고하세요. 참고: 문서에 쓰였듯이, 변경 사항이 적용되려면 터미널을 재시작해야 할 가능성이 큽니다. 반대로 설정을 되돌리고 싶다면, 변경 사항이 적용되려면 시스템을 재부팅해야 할 수도 있습니다.
이게 글의 도입부에서 말한 “비밀 설정”입니다. 찾아보니 온라인에서 이에 대한 언급이 몇 개밖에 없었습니다.
이 설정을 적용하면 OS의 보안 기능 하나를 비활성화하는 셈이라는 점을 유의하세요. 속도와 보안 사이의 트레이드오프에 동의하지 않는다면 적용하지 마세요.
아래 이미지는 앞서 본 cargo build --timings의 부분 출력을, XProtect를 비활성화한 뒤의 대응되는 부분 출력과 나란히 보여 줍니다.


엄청난 차이죠! 주황색 막대가 이제 아주 작습니다. 제 오래된 MacBook Pro에서는 빌드 스크립트가 개당 대략 0.06~0.14초 걸립니다.
이는 여러 Rust 프로젝트의 전체 빌드를 분명히 빨라지게 할 잠재력이 있습니다. 이 경우, 원래 wild 빌드는 25.9초가 걸렸고 새 빌드는 25.0초가 걸렸습니다. 이 숫자들이 일관적인지 꼼꼼히 측정하진 않았습니다. (개별 크레이트 컴파일 시간에 너무 의미를 두지 마세요. 두 번의 실행 사이의 스케줄링이 많이 다릅니다.)
정확한 효과는 프로젝트의 의존 그래프와 사용자의 머신 특성에 크게 좌우되지만, 빌드 스크립트 실행이 크리티컬 패스에 있다면 확실히 영향이 있습니다.
좋습니다! 하지만 여러분은 사실 빌드 스크립트를 그렇게 자주 실행하지 않을지도 모릅니다. 대부분은 자신의 코드만 다시 빌드하고, 써드파티 의존성은 가끔 cargo clean 후에나 다시 빌드하죠, 그렇죠? 글쎄요…
프로젝트가 실행 파일이라면, 매번 다시 빌드해 실행할 때마다 XProtect 비용을 매번 지불하게 됩니다. 편집-컴파일-실행 주기마다 추가 시간이 붙습니다. 영 불쾌하죠.
XProtect 비활성화는 테스트 바이너리에도 도움이 됩니다. 사실, 여기서 가장 큰 속도 향상을 기대할 수 있습니다. 일부 테스트 구성은 작은 바이너리 여러 개를 포함하기 때문입니다. 예를 들어, 각 통합 테스트는 자신만의 바이너리를 갖습니다. 그리고 2024 이전 에디션의 모든 도크테스트는 각각 자신만의 바이너리를 갖습니다! cargo-nextest 쪽도 분명히 이 현상을 파악했습니다.
Rust 컴파일러 자체가 특히 설득력 있는 예시를 제공합니다. 가장 큰 테스트 슈트는 tests/ui/로, 거의 4,000개의 개별 실행 파일을 실행합니다. 대부분은 아주 작습니다. Mads Marquart는 XProtect를 비활성화하면 이 테스트 슈트의 실행 시간이 9분 42초에서 3분 33초로 줄어든다는 것을 발견했습니다! 놀랍습니다.
제가 직접 테스트하진 않았지만, 다른 컴파일 언어를 사용하는 개발자도 비슷하게 이득을 볼 가능성이 큽니다. 개발 중 바이너리를 자주 컴파일해 실행한다면 말이죠.
현재 상태는, 이 동작이 몇몇 잘 알려지지 않은 곳에만 문서화되어 있고 Mac 사용자 99% 이상이 모른다는 것입니다. 다행히도 Mads가 XProtect가 활성화되어 있으면 이를 감지하고 사용자에게 영향과 비활성화 방법을 설명하는 경고를 띄우는 Cargo용 드래프트 PR을 준비했습니다. (터미널에서 XProtect를 프로그래밍 방식으로 비활성화하는 방법은 없어 보이며, 설령 가능하더라도 그렇게 하고 싶지는 않습니다. 사용자가 능동적으로 선택해야 합니다.)
이 PR은 상황을 제가 여기서보다 더 자세히, 정확하게 설명하고 있으므로 한 번 볼 가치가 있습니다. 또한, 글의 앞부분에서 제기했던 질문 하나에 답을 줍니다. 원래의 cargo build --timings 출력에서 왜 빌드 스크립트가 하나하나 갈수록 더 느려졌을까요? PR에 답이 있습니다.
XprotectService 데몬은 단일 스레드로 동작하므로, 10개의 새로운 바이너리를 한꺼번에 실행하려 하면 지연 시간이 1초보다 더 커집니다.
8코어인 제 오래된 MacBook Pro에서는 1초보다 훨씬 더 큽니다. 원래의 cargo build --timings 실행으로 돌아가 보면, 마지막 빌드 스크립트는 실행에 3.88초가 걸렸습니다. 그 실행은 직전 대다수 빌드 스크립트와 겹쳤습니다. 그 3.88초 대부분은 사실 데몬을 기다리는 데 쓰였습니다. 이런.
OS 보안 기능을 비활성화하라는 경고를 어떻게 사용자에게 보여줄지에 대해서는 신중한 논의와 검토가 필요합니다. 하지만, 이 지식이 ‘깊은 전설’ 영역에만 머무르지 않고 일반 사용자들도 알 수 있도록 하는 분명한 길이 열려서 기쁩니다. 그동안 Mac 사용자라면 터미널에서 XProtect를 비활성화하는 것을 고려해 보고, 즉시 속도 향상을 누려 보세요.