"리빌드할 때마다 macOS 는 앱을 보고 낯선 사람을 봤어. 기술적으론 맞는 얘기였으니까."
증상
접근성을 허가해. 마이크를 허가해. 오타 하나 고치려고 앱을 리빌드해. 그런데 macOS 가 둘 다 다시 물어. 또, 빌드할 때마다. 망가진 OS 처럼 느껴지고 망가진 앱처럼도 느껴져. 둘 다 아니야. macOS 가 두 바이너리를 '같은 앱' 으로 볼지 정하는 방식에서 완벽하게 논리적으로 나오는 결과야.
원인은 지정 요구사항(Designated Requirement)
macOS 는 TCC 허가를, 그러니까 접근성이나 마이크 같은 걸 앱의 지정 요구사항, 줄여서 DR 에 묶어. '이게 그 앱이다' 라고 말해 주는 코드 서명 규칙이지. 평범한 swift build 는 애드혹 서명을 만드는데, 그 지정 요구사항은 바이너리의 cdhash 에 못 박혀 있어. 소스를 한 글자만 바꿔도 cdhash 가 바뀌고, 그러면 DR 이 바뀌고, 방금 빌드한 앱이 유저가 허가해 준 앱이랑 안 맞게 돼. macOS 가 잊는 게 아니야. 이건 이름만 같은 다른 앱이라고 정확하게 결론 내리는 거야.
swift build -> 애드혹 서명 -> DR 이 cdhash 에 고정
|
v 한 줄 편집, 리빌드
cdhash 바뀜 -> DR 바뀜 -> TCC: "넌 누구야?" -> 영원히 재프롬프트
해법: 안정된 아이덴티티 하나로 서명 -> DR 안정 -> 허가 지속
해법, 그리고 해법 안의 함정
해법은 모든 앱이 같이 쓰는 안정된 자체 서명 아이덴티티 하나야. 앱마다 인증서를 따로 만드는 게 아니고. 그건 문제를 곱하기만 해. 기계마다 한 번 임포트해 두고 빌드 스크립트가 그걸로 서명하게 하면 DR 이 더는 안 바뀌어. 그리고 그 해법 안에 알아 둘 함정이 하나 더 있어. security find-identity -v 는 Gatekeeper 기준으로 유효한 아이덴티티만 걸러 내는데, 자체 서명 인증서는 유효로 안 쳐. 신뢰 안 됨으로 보고되거든. 그래서 네 아이덴티티가 아예 없는 것처럼 보여. -v 를 빼고 security find-identity -p codesigning 으로 확인해. 플래그 하나가 '설계대로 잘 돌아감' 과 한 시간짜리 혼란 사이에 서 있는 거야. 마지막으로, 제대로 서명한 첫 빌드가 나오면 예전 애드혹에 묶여 있던 허가를 tccutil reset 으로 한 번 지우고 다시 허가해 줘. 그때부터는 계속 유지돼.