RSS
개발 도구

데스크톱 앱 코드 서명 정리: macOS 공증부터 Windows SmartScreen까지

작성자
듀오랩스 대표·17분 읽기

직접 빌드한 .dmg를 다른 맥에 보내면 "확인되지 않은 개발자"라는 창이 뜨고 앱이 열리지 않습니다. 같은 앱의 Windows 설치 파일은 파란 "Windows의 PC 보호" 창에 막힙니다. 두 경고 모두 코드 서명이 없어서 생깁니다.

그래서 코드 서명을 흔히 "경고창을 없애는 비용"으로 이해합니다. 그렇게 보면 Windows 서명을 하고도 경고가 계속 뜨는 상황이 설명되지 않고, macOS에서 업데이트할 때마다 사용자가 권한을 다시 켜야 하는 문제도 놓치게 됩니다. 제가 보기에 코드 서명의 본질은 앱의 신원을 버전이 바뀌어도 이어 주는 것입니다. 경고가 사라지는 것은 그 결과 중 하나입니다.

경고창보다 큰 문제, 버전마다 바뀌는 앱의 신원

macOS는 마이크, 화면 기록, 손쉬운 사용 같은 개인정보 권한을 앱의 이름이 아니라 **서명에서 나온 지정 요구사항(designated requirement)**에 묶어 기억합니다. Apple의 기술 노트 TN3127은 이렇게 설명합니다.

Ad hoc signed code… has a DR but it's tied to that specific version of the code… If you tweak the code and run it again, macOS repeats that prompt.

정식 서명이 없는 앱은 새 버전이 나올 때마다 macOS 입장에서 처음 보는 앱이 됩니다. 클립보드 관리자나 창 관리 앱처럼 손쉬운 사용 권한에 기대는 앱이라면, 사용자는 업데이트할 때마다 시스템 설정에 들어가 권한을 다시 켜야 합니다. TN3127의 예시는 마이크 권한이지만 같은 원리가 다른 권한에도 적용된다고 봅니다. Apple DTS도 포럼 답변에서 ad-hoc 서명과 Developer ID 서명을 섞으면 권한 기록이 계속 꼬인다고 설명합니다.

Windows의 SmartScreen도 결국 신원을 봅니다. Microsoft는 평판이 파일 해시와 게시자 인증서 두 가지에 쌓인다고 설명합니다. 같은 인증서로 계속 서명하면 평판이 다음 버전으로 이어지고, 서명하지 않은 파일은 버전마다 평판이 0에서 다시 시작합니다.

macOS에서 필요한 세 가지

macOS 앱을 App Store 밖에서 배포하려면 서명, 공증, 스테이플 세 단계가 필요합니다.

서명은 Developer ID Application 인증서로 합니다. Xcode에서 개발할 때 쓰는 Apple Development 인증서나 iPhone 배포 인증서로는 안 됩니다. 공증은 서명한 앱을 Apple에 올려 악성코드 검사를 받는 절차입니다. Apple 지원 문서에 따르면 macOS Catalina부터는 기본 설정에서 공증까지 요구합니다. 서명만으로는 부족하다는 뜻입니다. 스테이플은 공증 결과를 앱 파일에 붙여 두는 단계입니다. 사용자의 맥이 오프라인이어도 검사를 통과하게 해 줍니다.

macOS Sequoia부터는 이 세 단계가 더 중요해졌습니다. Apple은 개발자 뉴스에서 "Control 키를 누른 채 클릭해 Gatekeeper를 우회하는 방법을 더 이상 쓸 수 없다"고 공지했습니다. 이제 사용자는 시스템 설정 › 개인정보 보호 및 보안에 들어가 "그래도 열기"를 눌러야 합니다. 일반 사용자에게 이 경로를 안내하는 것은 사실상 배포를 포기하는 것과 같다고 봅니다.

Developer ID 인증서 발급 순서

Developer ID 인증서는 팀의 Account Holder만 만들 수 있습니다. Admin 권한의 팀원은 만들 수 없습니다. 팀당 Developer ID Application과 Developer ID Installer를 각각 5개까지 둘 수 있습니다. 비용은 Apple Developer Program 연회비 99달러에 포함돼 있습니다.

가장 간단한 방법은 Xcode입니다. 개인키가 바로 로그인 키체인에 들어가서 키 파일을 따로 다룰 일이 없습니다.

  1. Xcode › Settings › Accounts에서 Apple 계정과 팀을 고릅니다.
  2. Manage Certificates…를 누릅니다.
  3. 왼쪽 아래 +를 눌러 Developer ID Application을 고릅니다.
  4. 터미널에서 security find-identity -v -p codesigning을 실행해 Developer ID Application: <팀 이름> (<팀 ID>)가 보이는지 확인합니다.

웹에서 만들 때는 Certificates, Identifiers & Profiles › Certificates › + › Developer ID를 고르고, 키체인 접근에서 만든 인증서 서명 요청(CSR)을 올립니다. 내려받은 .cer를 더블클릭하면 키체인에 설치됩니다. Developer ID Installer 인증서는 .pkg 설치 파일에 서명할 때만 필요합니다. .dmg나 .zip으로 배포하면 만들지 않아도 됩니다.

인증서가 만료되거나 멤버십이 끝나도 이미 서명해서 배포한 앱은 계속 실행됩니다. 서명할 당시 인증서가 유효했고 타임스탬프가 붙어 있기 때문입니다. 다만 .pkg는 Installer 인증서가 유효할 때만 열리므로, 만료되면 다시 서명해야 합니다.

공증을 빌드에 붙이는 환경 변수

공증은 xcrun notarytool로 합니다. 예전에 쓰던 altool은 2023년 11월 1일부터 공증 업로드를 받지 않습니다. 인증 방법은 둘입니다. Apple ID와 앱 전용 암호를 쓰는 방법, 그리고 App Store Connect API 키를 쓰는 방법입니다. CI에서는 개인 계정 암호가 필요 없는 API 키 쪽이 낫다고 봅니다.

공증을 통과하려면 Developer ID 서명, Hardened Runtime, 보안 타임스탬프가 모두 있어야 합니다. Tauri 2는 환경 변수만 넣으면 이 과정을 빌드 안에서 처리합니다(Tauri 문서).

export APPLE_SIGNING_IDENTITY="Developer ID Application: <팀 이름> (<팀 ID>)"
# 공증: App Store Connect API 키
export APPLE_API_KEY="<키 ID>"
export APPLE_API_ISSUER="<Issuer ID>"
export APPLE_API_KEY_PATH="$HOME/.config/<경로>/AuthKey_<키 ID>.p8"
npm run tauri build

CI에서는 인증서를 .p12로 내보내 base64로 바꾼 뒤 APPLE_CERTIFICATE와 APPLE_CERTIFICATE_PASSWORD 시크릿으로 넘깁니다. 직접 할 때는 공증이 끝난 뒤 xcrun stapler staple "<앱 이름>.app"으로 스테이플합니다. ZIP 파일 자체에는 스테이플할 수 없으므로 안의 앱에 붙이고 다시 압축합니다.

Windows 서명이 선택인 이유와 그 대가

Windows는 서명이 없어도 앱이 설치되고 실행됩니다. 사용자는 SmartScreen 창에서 "추가 정보 › 실행"을 한 번 누르면 됩니다. macOS처럼 개인정보 권한을 서명에 묶는 체계도 없습니다. 예를 들어 다른 앱에 키 입력을 보내는 SendInput에는 사용자 권한 대신 무결성 수준 규칙(UIPI)이 적용됩니다. 관리자 권한으로 뜬 창에는 키를 보낼 수 없다는 제약이고, 서명과는 무관합니다.

서명을 해도 경고가 바로 사라지지는 않습니다. 이 부분이 가장 많이 오해받는다고 봅니다. 한때는 비싼 EV 인증서를 사면 SmartScreen 평판을 바로 얻었습니다. Microsoft는 2024년에 이 혜택을 없앴습니다. 지금은 OV든 EV든 처음에는 "인식되지 않은 앱"으로 표시되고, 게시자 이름만 보입니다. 경고가 사라지려면 깨끗한 설치가 쌓여야 하고, Microsoft는 이를 "몇 주와 수백 번의 설치"로 표현합니다. 같은 문서는 EV 인증서를 경고 회피 목적으로 사는 것이 더는 정당화되지 않는다고까지 적습니다.

인증서 규칙도 바뀌었습니다. CA/Browser Forum 기준에 따라 2023년 6월 1일부터 모든 코드 서명 인증서의 개인키는 하드웨어 보안 모듈(USB 토큰이나 클라우드 HSM) 안에서 만들고 써야 합니다. 개인키를 파일로 내려받아 CI에 넣는 예전 방식은 더 이상 쓸 수 없습니다. Ballot CSC-31에 따라 2026년 3월 1일 이후 발급되는 인증서의 최대 유효기간은 39개월에서 460일로 줄었습니다.

Windows에서 고를 수 있는 네 가지 선택지

방법 비용 경고 조건
서명 없음 없음 매 버전 "PC 보호" 창 버전마다 평판이 0부터
OV 인증서(HSM) 인증 기관별 연 단위 유료 평판이 쌓일 때까지 "인식되지 않은 앱" 토큰 또는 클라우드 HSM, 최대 460일
Artifact Signing 월 9.99달러(Basic, 서명 5,000회) OV와 같음 법인은 한국 포함 일부 국가, 개인은 미국·캐나다만
Microsoft Store(MSIX) 개발자 등록 무료 없음 스토어 심사

Artifact Signing은 예전 이름이 Trusted Signing인 Microsoft의 클라우드 서명 서비스입니다. 인증서 갱신과 키 보관을 Microsoft가 맡아서 HSM 규칙을 따로 신경 쓸 필요가 없습니다. 다만 자격 조건에 따르면 한국의 법인은 쓸 수 있지만 한국에 사는 개인 개발자는 쓸 수 없습니다. 신원 확인에는 1~20 영업일이 걸립니다.

Microsoft Store는 패키지 형식에 따라 다릅니다. MSIX로 올리면 Microsoft가 서명해 주고 SmartScreen 경고도 뜨지 않습니다. 반면 .exe나 .msi 설치 파일을 그대로 올리면 개발자가 직접 서명해야 합니다. 스토어로 가면서 서명을 피하고 싶다면 MSIX로 가야 합니다. 개발자 등록은 storedeveloper.microsoft.com의 새 절차로 하면 개인과 회사 모두 무료입니다. 개인은 신분증과 셀카로 본인 확인을 합니다.

Tauri의 Windows 설정과 업데이트 서명 키

Tauri 2에서 Windows 서명은 tauri.conf.json에서 설정합니다. 인증서 지문(certificateThumbprint)을 넣는 방식은 Tauri 문서도 밝히듯 2023년 6월 이전에 발급된 OV 인증서에만 해당합니다. 지금은 대부분 signCommand로 외부 서명 도구를 부릅니다. Artifact Signing이라면 cargo install artifact-signing-cli로 도구를 깔고 다음처럼 씁니다.

"bundle": {
  "windows": {
    "signCommand": "artifact-signing-cli -e https://<지역>.codesigning.azure.net -a <계정> -c <인증서 프로필> -d <앱 이름> %1"
  }
}

여기에 하나가 더 있습니다. Tauri의 자동 업데이트는 운영체제 서명과 별개로 업데이트 파일을 자체 키로 서명합니다. tauri signer generate로 만들고, 빌드할 때 TAURI_SIGNING_PRIVATE_KEY로 넘깁니다. 이 서명은 끌 수 없고, 키를 잃어버리면 이미 설치된 앱에 더 이상 업데이트를 보낼 수 없습니다. 인증서는 다시 발급받으면 되지만 이 키는 되살릴 방법이 없으므로 가장 조심해서 보관해야 할 키라고 봅니다.

OS별 이상적인 길과 차선책

이상적인 길 차선책 최소한
macOS Developer ID 서명 + 공증 + 스테이플을 CI 빌드에 넣기 로컬에서 서명·공증하고 CI는 검사만 없음. 서명이 없으면 일반 사용자는 거의 열지 못합니다
Windows 법인이면 Artifact Signing, 스토어 배포가 가능하면 MSIX OV 인증서를 클라우드 HSM에 두고 signCommand로 서명 서명 없이 배포하고 "추가 정보 › 실행"을 안내
업데이트 업데이트 서명 키를 처음부터 만들어 따로 보관 첫 공개 배포 전에는 반드시 없음

제가 정할 순서는 이렇습니다. macOS 서명과 공증, 그리고 업데이트 서명 키는 첫 배포 전에 끝냅니다. 비용이 들지 않거나 이미 낸 비용 안에 있고, 나중에 붙이면 기존 사용자가 권한을 다시 켜거나 업데이트를 받지 못하게 됩니다. Windows 서명은 사용자가 생긴 뒤에 고릅니다. 지금은 어떤 인증서를 사도 경고가 바로 사라지지 않기 때문에, 서명이 없어도 초기 손해가 생각보다 작습니다.

여기서부터는 확실하지 않습니다. Developer ID 인증서의 유효기간은 Apple 문서에서 숫자를 찾지 못했습니다. Artifact Signing의 문서는 아직 "public preview"라는 표기를 달고 있어서, 정식 서비스로 바뀌었는지도 확인이 필요합니다. 서명을 붙일 앱을 Tauri로 만든 과정은 Tauri 2로 클립보드 관리자를 만든 글에 적었습니다.

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.