sayren Docs

상점 플랫폼 앱 화면

ui/ 폴더로 만드는 앱 화면, 세션과 HTTP 핸들러 호출, 상점 플랫폼과의 연결(알림·이동)

매니페스트에 ui.adminPage를 적으면 상점 플랫폼 **앱 › {앱}**에 앱 화면이 생깁니다. 화면은 ui/ 폴더의 정적 파일(HTML·JS·CSS)이고 sayren이 앱 주소 https://{handle}.apps.sayren.app에서 서빙합니다. 상점 플랫폼은 이 주소를 격리된 프레임으로 엽니다.

ui/
  index.html      매니페스트 ui.adminPage.entry
  main.js         @sayren/app/ui로 세션을 받고 HTTP 핸들러를 부른다

ui/는 정적 파일 그대로 올라갑니다. sayren이 빌드하지 않습니다. ui/index.html이 진입이고 그 안에서 <script type="module" src="./main.js">처럼 코드를 가져옵니다. TypeScript·React·Vue를 쓰려면 자기 도구(Vite 등)로 ui/에 산출물을 만든 뒤 deploy합니다. 정적 파일은 합계 25MB·2,000개까지입니다.

브리지 스크립트는 deploy가 ui/_sayren/ui.js로 함께 올립니다(앱 폴더의 @sayren/app에서). 빌드 도구 없이 쓸 때는 이 경로에서 가져오고, 번들러를 쓸 때는 @sayren/app/ui를 import합니다.

세션과 핸들러 호출

앱 화면은 상점 플랫폼이 넘겨주는 세션으로만 앱의 HTTP 핸들러를 부를 수 있습니다. 세션은 「이 사람이 이 상점의 이 설치에서 화면을 열었다」는 증명이고 5분마다 갱신됩니다. @sayren/app/ui가 세션을 받고 요청에 싣습니다.

ui/main.js
import { createAppBridge } from "./_sayren/ui.js"; // 번들러를 쓰면 "@sayren/app/ui"

const app = createAppBridge();
await app.ready();                              // 상점 플랫폼에서 세션을 받을 때까지

const res = await app.fetch("/summary");        // → 앱 코드의 "GET /summary"
const { recent } = await res.json();

document.querySelector("#list").textContent = recent.map((o) => o.orderNo).join(", ");

await app.fetch("/notes", { method: "POST", body: JSON.stringify({ text: "안녕" }) });
메서드하는 일
ready()세션을 받을 때까지 기다립니다. 직접 연 창(프레임 밖)에서는 거부됩니다
fetch(path, init?)앱의 HTTP 핸들러를 부릅니다. path는 핸들러 키의 경로 부분입니다. 세션 헤더와 content-type: application/json(본문이 문자열일 때)을 넣습니다
session{ storeId, installationId, user: { userId, role } }
toast(message, { tone? })상점 플랫폼의 알림을 띄웁니다. tone은 success · error · info
navigate(path)상점 플랫폼 안 경로로 이동합니다(예: /orders/ord_01J…). 상점 플랫폼 밖 주소는 거부됩니다
resize(height?)프레임 높이를 내용에 맞춥니다. 생략하면 문서 높이입니다

세션 헤더 이름과 형식은 바뀔 수 있으므로 직접 만들지 말고 app.fetch를 쓰십시오.

핸들러에서 사람 확인

앱 화면에서 온 요청은 핸들러의 ctx.user에 사람 id와 역할이 들어 있습니다. 핸들러는 설치 토큰으로 실행되므로 관리 API 권한은 설치 동의 범위이고 사람의 역할로 좁혀지지 않습니다. 소유자만 할 작업은 ctx.user.role === "OWNER"로 직접 막으십시오.

제한

  • 화면은 상점 플랫폼 프레임 안에서만 동작합니다. 주소를 직접 열면 안내 페이지가 보입니다.
  • 프레임은 상점 플랫폼 창을 다른 주소로 이동시킬 수 없고, 팝업은 열 수 있습니다.
  • 앱 주소는 앱마다 다른 하위 도메인이라 다른 앱·상점 플랫폼의 쿠키·저장소에 닿지 않습니다. 브라우저 저장소(localStorage)는 설치가 아니라 사람의 브라우저 단위이므로 상점 데이터를 두지 마십시오.
  • 지금은 상점의 소유자·관리자만 앱 화면을 엽니다.
  • 앱 화면에서 로그인 폼을 그리지 마십시오(셀러 계정 정보를 받지 않습니다).

로컬에서 보기

npx sayren app dev가 http://localhost:4020/에 화면을 띄웁니다. 로컬에서는 상점 플랫폼 프레임이 없으므로 --store의 상점과 내 계정으로 세션을 흉내 냅니다. toast·navigate는 콘솔에 찍힙니다.

이 페이지 목차