Electron AI 앱을 Microsoft Store에 출시하기: 내가 실수했던 모든 것
요약
Electron 기반 AI 앱을 Microsoft Store에 출시하며 겪은 시행착오와 해결 방법을 공유합니다. 앱 아이콘 설정, 패키지 크기 최적화, 그리고 생성형 AI 콘텐츠 관련 스토어 정책 준수 사항을 다룹니다.
핵심 포인트
- Appx 패키지용 특정 규격의 PNG 아이콘 에셋이 반드시 필요함
- runFullTrust 정당화 필드는 글자 수 제한이 매우 짧으므로 간결하게 작성해야 함
- electron-builder 설정 시 개발 의존성을 제외하여 패키지 크기를 최적화해야 함
- 생성형 AI 앱은 부적절한 콘텐츠 신고 기능을 앱 내에 반드시 포함해야 함
저는 1인 개발자로서 Windows 데스크톱 AI 어시스턴트를 Microsoft Store에 출시했습니다. 두 번의 제출, 한 번의 거절, 그리고 문서화되지 않은 몇 가지 놀라운 일들을 겪었습니다.
이것은 제가 시작하기 전에 알았더라면 좋았을 목록입니다.
왜 굳이 스토어인가
저는 이미 작동하는 NSIS 설치 프로그램과 외부 제공업체를 통한 결제 흐름을 갖추고 있었습니다. 스토어 이용이 명백히 수고를 들일 가치가 있어 보이지는 않았습니다. 하지만 두 가지가 제 마음을 바꿨습니다.
Microsoft가 패키지에 서명해 줍니다. 스토어를 이용하지 않으면, 첫 실행 시 모든 사용자에게 Windows SmartScreen 경고가 나타나며, 이를 피할 수 있는 유일한 방법은 유료 코드 서명 인증서 (code signing certificate)를 사용하는 것입니다. 개인정보 보호에 중점을 둔 제품을 출시하는 1인 개발자에게, 사용자에게 보안 경고를 무시하고 클릭하라고 말하는 것은 좋지 않은 첫인상을 줍니다.
두 번째 이유는 게임이 아닌 앱도 자체 결제 시스템을 사용할 수 있도록 허용하는 2026년 정책입니다. 저의 전체 구매 흐름은 스토어 외부에서 이루어지며, 그 중 어떤 것도 변경할 필요가 없었습니다.
놀라움 1: electron-builder가 appx용 아이콘을 무시함
제 package.json에는 완벽하게 잘 작동하는 build/icon.ico가 있었습니다. NSIS는 이를 사용했습니다. 하지만 appx 타겟은 그렇지 않았습니다.
Appx 패키지는 특정 크기의 PNG 에셋이 필요하며, electron-builder는 사용자의 ico 파일로부터 이를 생성하지 않습니다. 최소한 다음을 포함하는 build/appx/ 폴더가 필요합니다:
Square44x44Logo.pngSquare150x150Logo.pngStoreLogo.png(50x50)Wide310x150Logo.png
이것들을 놓치면 빌드는 성공하지만, 앱은 빈 타일로 표시됩니다.
놀라움 2: runFullTrust 정당화 필드가 조용히 잘림
Electron 앱이 파일 시스템에 접근한다면, runFullTrust를 선언해야 하며 Partner Center는 텍스트 상자에 그 이유를 기술하도록 요청합니다.
해당 상자는 글자 수 제한이 매우 낮으며, 그 제한이 얼마인지 알려주지 않습니다. 긴 설명은 경고 없이 잘려 나갑니다. 두 단락이 아니라 두 문장으로 작성하세요.
놀라움 3: 패키지 크기
제 첫 번째 appx는 526 MB였습니다. 기능적으로 동일한 두 번째 appx는 191 MB였습니다.
원인은 제 electron-builder 설정의 files 배열이었습니다. **/*는 배포할 필요가 없는 개발 의존성 (development dependencies)을 포함한 모든 것을 의미합니다. 0.5GB를 업로드하기 전에 반드시 해당 배열을 검토하세요.
거절 사유: 정책 11.16
제 첫 번째 제출은 거절되었습니다. 이유는 단 하나뿐이었습니다.
정책 11.16, 라이브 생성형 AI 콘텐츠 (Live Generative AI Content). 만약 앱이 생성형 AI (generative AI) 출력을 생성한다면, 사용자가 부적절한 콘텐츠를 신고할 수 있는 방법을 앱 내에 제공해야 하며, 이는 눈에 잘 띄고 한 번의 클릭으로 접근 가능해야 합니다.
저는 개인정보 보호 아키텍처 (privacy architecture)에 수개월을 소비했습니다. 데이터 보관 제로, 파일 업로드 없음, 로컬 처리 (local processing), 제공자 측 데이터 수집 비활성화 등. 저는 데이터가 어디로 가는지에 대해서는 신중하게 생각했지만, 모델이 잘못된 말을 했을 때 어떤 일이 벌어질지에 대해서는 전혀 생각하지 못했습니다.
해결하는 데는 반나절이 걸렸습니다:
- 모든 어시스턴트 메시지 하단, 복사 및 읽어주기 버튼 옆에 신고 (flag) 버튼 추가
- 사용자가 무엇이 잘못되었는지 작성하는 모달 (modal) 창 추가
- 보고서를 데이터베이스에 기록하고 알림 이메일을 보내는 엔드포인트 (endpoint) 구축
- 문제 신고는 사용자에게 어떠한 비용도 발생시켜서는 안 되므로, 크레딧 소모 제외
재제출했습니다. 24시간 만에 승인되었습니다.
놀라움 4: 인증을 통과해도 앱은 여전히 작동하지 않을 수 있다
이것이 실제로 가장 뼈아픈 부분이었습니다.
제 서버는 다음과 같이 자식 프로세스 (child process)를 생성했습니다:
spawn("node", [path.join(__dirname, "dist/index.js")])
제 컴퓨터에서는 작동합니다. 제 컴퓨터에는 Node.js가 설치되어 있으니까요. 하지만 사용자들의 컴퓨터에는 설치되어 있지 않습니다.
앱은 정상적으로 실행되었습니다. UI도 렌더링되었습니다. 아무것도 충돌하지 않았습니다. 인증도 통과했습니다. 하지만 메시지를 입력한 모든 사용자는 60초를 기다린 후 일반적인 오류 메시지를 받았습니다. 자식 프로세스가 시작되지 않았기 때문입니다.
해결책은 단 한 줄입니다:
spawn(process.execPath, [path.join(__dirname, "dist/index.js")], {
env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" },
})
Electron은 자체적인 Node 런타임 (runtime)을 포함하고 있습니다. 사용자가 설치해 두었기를 바라지 말고, 그것을 사용하세요.
해결책을 검증하기 위해 저는 Node 설치 폴더의 이름을 변경했습니다. 이렇게 하면 컴퓨터가 깨끗한 사용자 환경처럼 동작하게 됩니다:
Rename-Item "C: extbackslash Program Files extbackslash nodejs" "C: extbackslash Program Files extbackslash nodejs_off"
매번 제출하기 전에 해당 상태에서 패키징된 앱을 실행하여 테스트하세요. 이 5분간의 테스트가 2일간의 인증 대기 시간을 줄여줍니다.
인증이 실제로 확인하는 것
스토어 인증은 기능 검토가 아닌 준수 사항 검토 (compliance review)입니다. 서명 (signing), 매니페스트 (manifest) 유효성, 선언된 권한 (capabilities), 정책 준수 여부, 그리고 앱이 실행 시 충돌하지 않는지를 확인합니다.
인증은 앱이 제대로 작동하는지 확인하지 않습니다. 그 부분은 전적으로 개발자의 책임입니다.
보너스: IARC 등급 이전
연령 등급 설문지를 작성하면 IARC 글로벌 등급 ID (IARC Global Rating ID)가 생성됩니다. 이 ID는 설문지를 다시 작성하지 않고도 다른 IARC 라이선스 스토어에서 그대로 사용할 수 있습니다. 만약 답변을 변경해야 할 만큼 새로운 기능을 추가했다면, 설문지를 다시 작성해야 합니다.
요약
- appx PNG 에셋을 수동으로 생성할 것
- runFullTrust 정당성 설명을 짧게 유지할 것
files배열을 감사 (audit)할 것- 앱이 AI 콘텐츠를 생성한다면, 제출하기 전에 신고 메커니즘 (reporting mechanism)을 포함할 것
- 사용자의 컴퓨터에 개발 의존성 (development dependencies)이 설치되어 있다고 절대 가정하지 말 것
- 매번 깨끗한 환경에서 패키징된 빌드를 테스트할 것
이 제품은 문서를 어디에도 업로드하지 않고 처리하는 Windows AI 어시스턴트인 NeonCore입니다. 1인 개발되었습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기