Iframe 위젯
Iframe 위젯은 외부의 전체 페이지 앱을 Workshop 안에 표시합니다. Slate나 양방향 통신을 구성한 앱은 Workshop 변수와 이벤트를 주고받을 수도 있습니다. 새 사용자 위젯을 개발한다면 Custom widget을 우선 사용하고, Iframe의 Bidirectional은 기존 양방향 앱을 연결할 때 검토합니다.
iframe은 별도 메모리와 처리 자원을 사용하므로 한 화면에 하나를 넘겨 배치하는 것은 권장하지 않습니다.
접근 조건
외부 리소스를 삽입하려면 Foundry의 Content Security Policy(CSP)에 해당 리소스가 허용되어야 합니다. 외부 앱 응답의 CSP frame-ancestors도 Foundry URL의 삽입을 허용해야 합니다. 외부 URL의 앱에서 Foundry API를 요청한다면 Foundry의 CORS 설정도 필요합니다.
삽입되는 앱이 자기 인증 절차를 수행해야 하므로 처음 열 때 로그인 화면이 보일 수 있습니다. iframe 표시 허용과 API 접근 인증을 각각 구성합니다.
URL
정적 문자열이나 String 변수로 URL을 입력합니다. 다른 Foundry 앱을 삽입할 때에는 embedded=true 질의 매개변수로 Foundry 사이드바를 숨길 수 있습니다. 기존 질의 매개변수가 있으면 &embedded=true, 없으면 ?embedded=true를 붙입니다.
일반 YouTube URL인 https://www.youtube.com/watch?v=VIDEO_ID를 넣으면 위젯이 이를 감지하고 https://www.youtube.com/embed/VIDEO_ID로 변환하는 버튼을 제공합니다. VIDEO_ID는 실제 동영상 식별자로 바꿉니다.
Slate 삽입
Slate source에서 Compass reference를 선택하면 리소스 선택기로 Slate 앱을 고릅니다. Permalink는 permalink 또는 RID를 직접 입력합니다. Slate URL의 /workspace/slate/documents/<slate-permalink>/latest에서 식별자를 확인할 수 있습니다.
URL 매개변수
URL parameters는 Slate URL에 붙여 초기 변수를 정합니다. 값이 바뀌면 페이지 전체를 다시 읽으므로 자주 바뀌지 않는 값에 사용합니다. 정적 문자열은 URI 인코딩하여 입력합니다.
예를 들어 사용자 이름과 ID에 따라 초기 화면을 바꾸려면 Workshop에 username 같은 URL 매개변수를 정의하고 Slate에도 같은 이름의 변수를 만듭니다. Slate에서는 {{username}}으로 참조합니다.
Workshop에서 Slate로 입력
Input parameters에 키와 값의 유형을 정의합니다. 정적 String, String 변수, Number와 객체 집합을 전달할 수 있습니다.
Slate Events 패널의 Slate.getMessage에서 수신한 메시지 본문을 {{slEventValue}}로 읽습니다. 다음은 키를 flight-alerts로 정한 경우의 이벤트 수식 본문입니다. {{...}}는 Slate가 치환하는 참조입니다.
const payload = {{slEventValue}};
return payload["flight-alerts"];
이 값을 Slate 화면의 필터나 표시 입력에 연결하면 Workshop 필터에 따라 Slate의 내용을 바꿀 수 있습니다.
Slate에서 Workshop으로 출력
Output parameters에 키, 유형과 값을 받을 Workshop 변수를 지정합니다. 객체 집합, 객체 집합 필터 또는 String 변수를 전달할 수 있습니다.
Slate의 선택 상태를 반환하는 수식 f_selection을 준비하고 그 결과가 연결한 Workshop 변수의 유형과 일치하게 합니다. Slate.sendMessage에 다음 본문을 넣습니다. selected-objects는 Workshop에서 설정한 출력 키입니다.
return {
type: "WORKSHOP//SET_OUTPUT_VALUE",
outputParameterKey: "selected-objects",
value: {{f_selection}}
};
String 변수에 출력할 때 undefined는 변수를 기본값으로 되돌리고 null은 값을 비웁니다.
Slate에서 Workshop 이벤트 실행
Triggerable events에 키와 실행할 Workshop 이벤트를 정합니다. 오버레이 열기, 변수 초기화나 접을 수 있는 섹션 전환 등을 연결할 수 있습니다.
예를 들어 toggle-details라는 키를 섹션 전환 이벤트에 매핑한 뒤 Slate 버튼의 Slate.sendMessage에 다음 수식 본문을 넣습니다.
return {
type: "WORKSHOP//TRIGGER_WORKSHOP_EVENT",
eventKey: "toggle-details"
};
Bidirectional 앱
Bidirectional은 사용자 React 앱에서 Workshop 변수의 값과 로딩 상태를 읽고 갱신하며 설정된 이벤트를 실행하게 합니다. 온톨로지 자체를 조회하려면 앱에 OSDK와 인증을 별도로 구성합니다.
앱 구현
아래 예제는 기존 React/TypeScript 앱에 넣는 컴포넌트이며 @osdk/workshop-iframe-custom-widget 1.1.1을 사용합니다.
npm install @osdk/workshop-iframe-custom-widget@1.1.1
useWorkshopContext에 변수와 이벤트 정의를 전달합니다. fieldId가 반환 문맥의 속성명이 되므로 정의를 객체 리터럴과 as const로 선언합니다. 문맥 전체와 각 변수값의 로딩, 성공, 재로딩, 실패를 구분해야 합니다.
import React from "react";
import {
useWorkshopContext,
visitLoadingState,
type IConfigDefinition,
type IWorkshopContext,
} from "@osdk/workshop-iframe-custom-widget";
const CONFIG = [
{
fieldId: "stringField",
field: {
type: "single",
label: "공유 문자열",
fieldValue: {
type: "inputOutput",
variableType: { type: "string", defaultValue: "Workshop" },
},
},
},
{
fieldId: "workshopEvent",
field: {
type: "single",
label: "화면 모드 전환",
fieldValue: { type: "event" },
},
},
] as const satisfies IConfigDefinition;
function LoadedWidget({ context }: { context: IWorkshopContext<typeof CONFIG> }) {
return (
<section>
{visitLoadingState(context.stringField.fieldValue, {
loading: () => <p>문자열을 불러오는 중입니다.</p>,
reloading: () => <p>문자열을 다시 불러오는 중입니다.</p>,
failed: error => <p role="alert">{String(error)}</p>,
succeeded: value => (
<label>
공유 문자열
<input
value={value ?? ""}
onChange={event => context.stringField.setLoadedValue(event.target.value)}
/>
</label>
),
})}
<button onClick={() => context.workshopEvent.executeEvent()}>
화면 모드 전환
</button>
</section>
);
}
export default function WorkshopIframeWidget() {
const context = useWorkshopContext(CONFIG);
return visitLoadingState(context, {
loading: () => <p>Workshop 구성을 기다리는 중입니다.</p>,
reloading: () => <p>Workshop 구성을 다시 불러오는 중입니다.</p>,
failed: error => <p role="alert">{String(error)}</p>,
succeeded: loaded => <LoadedWidget context={loaded} />,
});
}
문자열 입력을 바꾸면 매핑한 Workshop 변수에 값을 기록합니다. 버튼에는 아래 단계에서 Toggle between light and dark mode 이벤트를 매핑합니다. 값 갱신과 이벤트 실행은 사용자 입력 처리기 안에서 수행합니다.
이벤트는 executeEvent()를 인자 없이 호출합니다. SDK 1.1.1은 이벤트 인자를 postMessage에 그대로 넣으므로 React 이벤트 객체나 DOM MouseEvent를 전달하면 구조화 복제 오류가 발생합니다.
앱을 iframe 없이 직접 열면 SDK는 정의의 기본값으로 문맥을 제공합니다. 이 예제의 Workshop은 그 기본 문자열입니다. Workshop 안에서는 호스트가 정의를 수락할 때까지 문맥이 로딩 상태이며 거절하면 오류가 전달됩니다.
비동기 입력을 처리하는 앱은 setLoading(), setReloadingValue(value), setFailedWithError(message)로 변수 상태도 전달할 수 있습니다. fieldValue의 상태와 값을 읽어 아직 준비되지 않은 입력에 의존하는 동작을 제어합니다.
위젯 하나에 대응하는 삽입 경로에서 훅을 한 번 호출합니다. 같은 위젯 안에서 여러 경로를 사용하는 앱은 상위 컴포넌트에서 문맥을 만들고 자식 경로에 전달합니다. 서로 다른 위젯인 두 경로에는 각각 훅을 둡니다.
Workshop 연결
- 앱에 위 구현을 포함하여 배포합니다. Iframe 위젯을 추가하고 Bidirectional을 선택합니다.
- 앱 URL을 정적 문자열 또는 String 변수로 지정합니다. 위젯은 앱이 필요한 변수와 이벤트의 정의를 보낼 때까지 기다립니다.
- 정의를 받으면 각 필드의 변수 선택기와 이벤트 선택기가 나타납니다. 예제의 공유 문자열에는 String 변수를, 화면 모드 전환에는 Toggle between light and dark mode를 연결합니다.
- 연결한 변수의 값이나 로딩 상태가 바뀔 때마다 앱으로 전달됩니다. 앱은 매핑한 이벤트만 해당 필드로 실행합니다.
Text Input의 출력 String 변수를 같은 입력에 연결하면 Workshop에서 입력한 내용이 앱에 반영됩니다.
숫자 필드를 둔 앱이 값을 기록하면 매핑한 Number 변수도 갱신됩니다.
설정된 화면 모드 이벤트를 앱이 실행하면 Workshop의 표시 모드가 바뀝니다.
객체 집합 전달 방식
1.1.1의 두 필드 유형을 구분합니다.
| 필드 | 전달과 한도 |
|---|---|
objectSet | 구체적인 objectTypeId를 지정하고 객체 RID 또는 기본 키를 주고받습니다. 다른 유형의 객체는 전달 전에 제외합니다. 어느 방향이든 10,000개를 넘기면 첫 10,000개 이후를 잘라 냅니다. 이전 @osdk/client 2.0 미만 경로에 사용합니다. |
temporaryObjectSetRid | 임시 객체 집합 RID를 문자열로 전달합니다. @osdk/client 2.0 이상에서 hydrateObjectSetFromRid로 집합을 구성하고 createAndFetchTempObjectSetRid로 반대 방향의 RID를 만듭니다. 객체를 나열하는 전송 방식의 10,000개 절단을 적용하지 않습니다. |
이 전송 방식에서 Struct 변수는 지원하지 않습니다. 임시 RID를 사용하는 경우에도 객체 조회의 권한과 OSDK 질의 조건은 적용됩니다.
글로벌 브랜치
Workshop의 글로벌 브랜치를 사용하는 Developer Console 앱은 Bidirectional 구성과 브랜치 연동 준비가 필요합니다. 저장소 준비를 기본 브랜치에 먼저 반영하고 @osdk/client 2.77.0 이상, createPublicOauthClient의 useHistory: false, 명시적인 OSDK branch override가 없는 구성을 사용합니다. 기존 OAuth scopes는 유지합니다.
iframe URL의 배포 자산이나 포함 SDK는 Workshop 브랜치를 바꿔도 새로 만들어지지 않으므로 브랜치 스키마와 호환되어야 합니다. 다른 Iframe 구성은 Workshop의 글로벌 브랜치 문맥을 상속하지 않으며 액션이 main을 편집할 수 있습니다.
표시 수명주기
iframe을 페이지에서 제거한 뒤 다시 표시하면 새로 로드되어 내부 상태가 사라집니다. 표시 최적화로 위젯을 마운트 상태로 유지하거나, 유지할 데이터를 Workshop 변수에 보관하여 앱으로 다시 전달합니다.
로컬 네트워크 접근
브라우저의 기본 보안 정책은 삽입 앱에서 localhost나 로컬 네트워크 주소로 보내는 요청을 제한합니다. 필요한 경우에만 Allow local network access를 켭니다. 이 설정은 iframe의 allow 속성에 local-network 권한을 추가합니다.
이 옵션을 켜면 앱이 사용자의 컴퓨터에서 실행 중인 서비스와 통신할 수 있으므로 신뢰하는 앱에만 허용합니다.