본문으로 건너뛰기

앱 사이드로딩

사이드로딩을 사용하면 공식 앱 스토어 레지스트리 외부에서 미니 프로그램을 설치할 수 있습니다. 이것이 개발 중 주요 워크플로우이며 개발자가 직접 공유하는 앱을 사용자가 설치하는 방법이기도 합니다.

세 가지 사이드로딩 방법이 있습니다:

방법입력용도
URL 설치매니페스트 URL호스팅된 앱, 로컬 서버로 개발
HTML 업로드단일 .html 파일빠른 프로토타이핑, 단일 파일 앱
.ais 번들ZIP 파일 (.ais 확장자)다중 파일 앱, 오프라인 배포

세 가지 방법 모두 앱 패널의 사이드로드 섹션에서 사용할 수 있습니다.


URL 설치

호스팅된 소스에서 미니 프로그램을 설치하는 표준 방법입니다.

작동 방식

  1. manifest.json 파일을 가리키는 URL 제공
  2. 플랫폼이 매니페스트를 가져와 검증
  3. 진입 HTML 파일이 {base_url}{entry}에서 가져와짐
  4. 권한 대화상자가 앱 이름, 설명, 요청된 권한을 표시
  5. 승인 시 매니페스트와 캐시된 HTML이 IndexedDB에 저장
  6. 설치된 앱 그리드에 앱이 나타남

단계

  1. 앱 패널 열기 (왼쪽 사이드바의 앱 아이콘 클릭)
  2. 사이드로드 섹션으로 스크롤
  3. 텍스트 필드에 매니페스트 URL 붙여넣기:
    https://example.com/my-app/manifest.json
  4. 설치 클릭
  5. 권한을 검토하고 허용 클릭

Localhost로 개발

개발 중에는 앱을 로컬에서 제공하고 localhost에서 설치합니다:

cd my-app
python3 -m http.server 8080

그 다음 설치: http://localhost:8080/manifest.json

대부분의 로컬 HTTP 서버는 기본적으로 관대한 CORS 헤더로 파일을 제공합니다. "매니페스트 가져오기 실패" 에러가 발생하면 서버가 응답에 Access-Control-Allow-Origin: *을 포함하는지 확인하세요.

사이드로드된 앱 업데이트

플랫폼은 설치 시점에 진입 HTML을 캐시합니다. 코드 변경사항을 반영하려면:

  1. 앱 제거 (앱 카드의 X 버튼 클릭)
  2. 동일한 URL에서 재설치

사이드로드된 앱에 대한 자동 업데이트 메커니즘은 없습니다. 레지스트리 앱은 레지스트리 새로고침 주기 동안 버전 비교를 사용하여 업데이트를 확인합니다.


HTML 업로드

미니 프로그램을 테스트하는 가장 빠른 방법. 단일 HTML 파일을 업로드하면 플랫폼이 자동으로 합성 매니페스트를 생성합니다.

작동 방식

  1. 컴퓨터에서 .html 또는 .htm 파일 선택
  2. 플랫폼이 파일 콘텐츠 읽기 (최대 5 MB)
  3. 합성 매니페스트 생성:
    • name: 파일 이름에서 파생 (소문자, 하이픈, 최대 64자)
    • version: 1.0.0
    • entry: index.html
    • base_url: local://
    • permissions: ["storage"] (최소)
    • description: "Sideloaded from {filename}"
  4. 권한 대화상자 표시
  5. HTML이 진입 콘텐츠로 캐시됨

단계

  1. 앱 패널 열기
  2. 사이드로드 섹션에서 앱 업로드 클릭
  3. .html 파일 선택
  4. 권한을 검토하고 허용 클릭

제한사항

  • 단일 파일만 -- 상대 URL로 참조되는 외부 CSS, JS, 이미지는 iframe이 null origin을 가지고 base_urllocal://로 설정되어 있어 로드되지 않음
  • 최소 권한 -- 합성 매니페스트는 storage만 부여. 앱에 chat:read 또는 다른 권한이 필요하면 URL 설치 또는 .ais 번들 사용
  • 최대 5 MB -- 5 MB보다 큰 파일은 거부됨
  • 매니페스트 커스터마이징 불가 -- 커스텀 설명, 아이콘, 권한을 설정할 수 없음
정보

HTML 업로드는 빠른 프로토타이핑을 위해 설계되었습니다. 여러 파일이나 특정 권한이 필요한 앱은 .ais 번들 또는 URL 설치를 사용하세요.

단일 파일 앱 만들기

HTML 업로드를 최대한 활용하려면 HTML에 모든 것을 인라인하세요:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
/* 모든 CSS를 여기에 인라인 */
body {
font-family: system-ui;
padding: 16px;
color: #e0e0e0;
background: #1a1a2e;
}
</style>
</head>
<body>
<h1>내 앱</h1>
<script>
// 모든 JavaScript를 여기에 인라인
ais.ready(function () {
ais.ui.toast("앱 로드됨!");
});
</script>
</body>
</html>

이미지는 데이터 URI로 임베드할 수 있습니다:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />

.ais 번들

.ais 번들은 .ais 파일 확장자를 가진 표준 ZIP 아카이브입니다. 매니페스트, 진입 HTML, 모든 에셋을 포함합니다. 플랫폼은 설치 시점에 ZIP을 추출하고 모든 참조된 에셋을 단일 HTML 문서로 인라인합니다.

작동 방식

  1. .ais 파일 업로드 (최대 50 MB)
  2. 플랫폼이 네이티브 DecompressionStream으로 ZIP 파싱
  3. manifest.json이 ZIP 루트에서 추출되고 검증됨
  4. 진입 HTML 파일 (매니페스트의 entry에서 참조)이 추출됨
  5. ZIP의 다른 모든 파일이 인라이닝을 위한 에셋으로 사용 가능
  6. 에셋 인라이닝이 HTML 변환:
    • <link rel="stylesheet" href="style.css"><style>{CSS 콘텐츠}</style>
    • <script src="app.js"></script><script>{JS 콘텐츠}</script>
    • <img src="icon.png"><img src="data:image/png;base64,{base64}">
    • 인라인 스타일의 url(bg.png)url(data:image/png;base64,...)
  7. 권한 대화상자가 매니페스트의 권한을 표시
  8. 인라인된 HTML이 IndexedDB에 캐시됨

번들 구조

my-app.ais (ZIP 아카이브)
|-- manifest.json (필수, 루트에)
|-- index.html (필수, 매니페스트 "entry"에서 참조)
|-- style.css (선택, <style>로 인라인)
|-- app.js (선택, <script>로 인라인)
|-- icon.png (선택, 데이터 URI로 인라인)
|-- images/
| |-- logo.svg (선택, 데이터 URI로 인라인)
|-- fonts/
|-- custom.woff2 (선택, 데이터 URI로 인라인)

번들 만들기

# 앱 디렉토리로 이동
cd my-app

# 파일 확인
ls
# manifest.json index.html style.css app.js icon.png

# 번들 생성
zip -r ../my-app.ais manifest.json index.html style.css app.js icon.png

또는 전체 디렉토리를 압축:

cd my-app
zip -r ../my-app.ais .
주의

manifest.json은 하위 디렉토리가 아닌 ZIP의 루트에 있어야 합니다. ZIP 구조가 my-app/manifest.json과 같다면 플랫폼이 찾지 못합니다.

인라인되는 것

에셋 인라이너는 진입 HTML을 처리하고 상대 참조를 인라인 콘텐츠로 대체합니다:

패턴대체
<link rel="stylesheet" href="X"><style>{X의 콘텐츠}</style>
<script src="X"></script><script>{X의 콘텐츠}</script>
<img src="X"><img src="data:{mime};base64,{data}">
<audio src="X"><audio src="data:{mime};base64,{data}">
<video src="X"><video src="data:{mime};base64,{data}">
<source src="X"><source src="data:{mime};base64,{data}">
인라인 스타일의 url(X)url(data:{mime};base64,{data})

data:, http://, https://, 또는 //로 시작하는 참조는 변경되지 않음 -- 상대 경로만 인라인됩니다.

지원되는 MIME 타입

플랫폼은 파일 확장자에서 MIME 타입을 감지합니다:

확장자MIME 타입
.csstext/css
.js, .mjstext/javascript
.jsonapplication/json
.pngimage/png
.jpg, .jpegimage/jpeg
.gifimage/gif
.svgimage/svg+xml
.webpimage/webp
.icoimage/x-icon
.wofffont/woff
.woff2font/woff2
.ttffont/ttf
.mp3audio/mpeg
.mp4video/mp4
.webmvideo/webm
.oggaudio/ogg
.wavaudio/wav

예시: 다중 파일 앱 번들

manifest.json:

{
"name": "dashboard",
"version": "1.0.0",
"abi": 1,
"type": "mini-program",
"title": "Dashboard",
"description": "Chat analytics dashboard",
"entry": "index.html",
"base_url": "local://",
"permissions": ["storage", "chat:read", "auth:read", "ui:toast"]
}

index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<h1>대시보드</h1>
<img src="logo.svg" alt="Logo" width="64" />
<div id="stats"></div>
<script src="app.js"></script>
</body>
</html>

style.css:

body {
font-family: system-ui;
padding: 16px;
color: #e0e0e0;
background: #1a1a2e;
}
h1 {
font-size: 22px;
}
#stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}

app.js:

ais.ready(async function () {
var history = await ais.chat.getHistory(100);
document.getElementById("stats").textContent = history.length + "개 메시지";
});

번들 설치 후 플랫폼은 단일 인라인 HTML을 생성합니다:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: system-ui;
padding: 16px;
color: #e0e0e0;
background: #1a1a2e;
}
h1 {
font-size: 22px;
}
#stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
</style>
</head>
<body>
<h1>대시보드</h1>
<img src="data:image/svg+xml;base64,..." alt="Logo" width="64" />
<div id="stats"></div>
<script>
ais.ready(async function () {
var history = await ais.chat.getHistory(100);
document.getElementById("stats").textContent =
history.length + "개 메시지";
});
</script>
</body>
</html>

파일 크기 제한

방법최대 크기
HTML 업로드5 MB
.ais 번들50 MB
URL 설치하드 제한 없음 (브라우저 메모리에 의해 제한)
경고

많은 임베드 이미지나 미디어 파일이 있는 큰 번들은 IndexedDB에 매우 큰 캐시된 HTML 문자열을 생성할 수 있습니다. 번들을 가볍게 유지하세요. 포함하기 전에 이미지를 압축하고 큰 미디어 에셋에는 외부 URL 사용을 고려하세요.


보안

사이드로드된 앱은 레지스트리 앱과 동일한 샌드박스를 얻습니다:

  • sandbox="allow-scripts allow-forms" (null origin)
  • 부모 DOM, localStorage, 쿠키에 접근 불가
  • 오직 window.ais postMessage 브리지를 통해서만 통신
  • 호스트 플랫폼에 의해 권한 강제 (iframe이 아님)

레지스트리 앱과의 유일한 차이점은 앱 그리드에 신뢰 배지(Community, AI Verified, 또는 Verified)가 없다는 것입니다. 사이드로드된 앱은 배지가 없습니다.

정보

사이드로딩은 마켓플레이스 배포 모델의 "직접 설치" 등급입니다. 웹의 네이티브 배포 메커니즘입니다 -- 샌드박스가 기본 보안을 제공하는 상태에서 어떤 URL에서든 어떤 앱이든 설치할 수 있습니다.


사이드로드 UI

앱 패널의 사이드로드 섹션은 다음을 제공합니다:

  1. URL 입력 필드 -- 매니페스트 URL을 붙여넣고 설치 클릭
  2. "또는" 구분선
  3. 앱 업로드 버튼 -- .html, .htm, .ais, .zip 파일을 허용하는 파일 선택기 열기
  4. 도움말 텍스트 -- ".html 단일 파일 앱 또는 .ais 번들(manifest.json이 있는 ZIP) 허용"

세 가지 방법 모두 설치 완료 전에 표준 권한 대화상자를 트리거합니다. 설치된 앱은 위쪽 설치됨 섹션에 열기 및 제거 버튼과 함께 나타납니다.