WFrame

Scope 설정

Scope은 웹 페이지를 구성하는 모든 단위 화면에 유효 범위(Scope)를 설정하는 기능입니다. 모든 화면은 Scope 단위로 존재하기 때문에, Scope에 포함된 객체 및 스크립트는 Scope 내에서만 유효합니다. 즉, 동일한 컴포넌트 ID 및 스크립트를 여러 개의 화면에서 함께 사용하더라도 웹 페이지는 정상 동작합니다.

Scope 기능을 사용하기 위해서는 각 화면을 WFrame으로 구성하고 WFrame 내에 표시할 화면(XML 파일)은 srcsetSrc API를 통해 정적/동적으로 지정하십시오.

WFrame으로 구성한 화면은 Scope으로 인식되어 각 WFrame 내에 존재하는 객체 및 스크립트는 해당 WFrame 내에서만 유효합니다.

각 WFrame을 Scope 객체로 지정하기 위해서는 SPA Variable에서 Scope 변수명을 설정해야 합니다. 기본 값은 scwin입니다. WebSquare5 Studio에서 Page를 생성하여 이벤트를 추가할 경우 해당 함수 앞에 scwin.이 자동 추가되고 scwin.로 시작하는 스크립트는 자신이 호출된 WFrame 내에서만 실행됩니다.

WFrame의 Scope 기능을 사용하기 위해서는 아래의 설정이 필요합니다.

Scope 사용에 필요한 설정

No.

항목

설정 위치

설명

(1)

scriptPrecedence

config.xml

페이지 로딩 이벤트 순서 보장.

(2)

strictMode

config.xml

페이지 내의 객체 참조 제한.

(3)

postDrawMode

config.xml

페이지 내 스크립트 즉시 실행 여부.

(4)

SPA Variable

config.xml

Scope 변수 지정.

(5)

lazy="false"

화면 파일 (XML)

업무 스크립트 생성 시점.

(6)

mode="sync", scope="true"

config.xml (WFrame)

WFrame 속성.

페이지 내 스크립트 즉시 실행 여부.

(7)

<getWindow searchTarget="windowId"/>

config.xml (WindowContainer)

getWindow 함수가 windowId를 기준으로 동작하도록 설정.

scriptPrecedence

Scope 기능을 사용할 경우 스크립트 실행 순서에 따라 스크립트가 동작해야 합니다. 이를 보장하기 위해 config.xml 파일에서 <scriptPrecedence> 항목을 아래와 같이 설정하십시오.

설명

페이지 로딩 이벤트 순서 보장.

설정 위치

config.xml

$r_title(config.xml 설정 예)
<scriptPrecedence value="true"/>

strictMode

Scope 기능을 사용할 경우, 각 화면은 독립적으로 동작하며 객체의 직접 참조는 WFrame 내에서만 가능합니다. strictMode는 메인 화면에 내부적으로 WFrame을 씌우는 기능입니다. config.xml 파일에 아래 설정을 추가하십시오.

설명

페이지 내의 객체 참조 제한.

설정 위치

config.xml

$r_title(strictMode 설정 예)
<strictMode value="true" id="mainFrame용WFrameID"/>

strictMode의 id로 지정된 값에 따라 메인 화면에 포함된 객체의 ID가 변경됩니다.

<strictMode value ="true" id="mainFrame용WFrameID">

위의 예제에서 <strictMode value = "true" id="mf">로 설정할 경우, 메인 화면 내에 포함된 textbox1 및 image1 컴포넌트는, ID 앞에 mf_가 추가됩니다.

ID 변경 예시

<strictMode value = "false">

<strictMode value = "true" id="mf">

  • id="textbox1"

  • id="image1"

  • id="mf_textbox1"

  • id="mf_image1"

CSS 디자인


strictMode 사용은 최상단 메인 페이지를 WFrame으로 씌우는 것을 의미합니다.

즉, 메인 화면에 속한 컴포넌트의 ID는 "메인 화면에 사용한 WFrame의 ID" + "_" + "컴포넌트 ID"로 변경됩니다.

이는 메인 화면의 CSS 디자인에도 영향을 미칩니다.

예를 들어 #header 대신 #메인화면용WFrame의ID_header 형식을 사용해야 합니다.

좀더 자세한 내용은 CSSclass selector 사용jQuery의 id selector 사용 부분을 참고하십시오.

YouTube 동영상 (https://youtu.be/7jJ8zEbhz3M)

참고 (JavaScript "with"문)

WFrame의 scope 기능은 JavaScript의 "with" 문을 사용하여 구현하였습니다. "with" 문은 지정한 객체 내에 있는 자원에 빨리 접근할 수 있습니. 단, "with" 문에 내의 객체가 해당 자원을 포함하지 않을 경우, 객체 외부에서 동일한 이름의 자원을 찾으려는 시도를 합니다.

$r_title("with" 문 사용 예제)
function process(record) {
    with(record) {
        addRecord(firstName + " " + lastName, email);
    }
}

위의 예에서 record 객체에 firstName이나 lastName 혹은 email 자원이 없을 경우, 부모를 포함한 상위 화면에서 해당 자원을 찾습니다. 그러나, 이 같은 동작은 코드의 명확도를 낮추며 의도하지 않은 동작으로 이어질 수 있습니다. strictMode는 자원 참조를 해당 WFrame 내부로만 제한하여 이 같은 단점을 보완합니다.

strictMode는 최상단 메인 화면을 WFrame으로 씌워서 메인 화면 내 컴포넌트에 Scope를 설정합니다. 그 결과 최상단 메인 화면을 포함한 모든 화면을 WFrame 단위로 관리하여 모든 화면에 대해 Scope 기능을 적용할 수 있습니다.

strictMode 비교

항목

<strictMode value="false">

<strictMode value="true">

객체 참조 방법

자신이 속한 WFrame을 확인한 후 부모 및 전역을 참조.

명시적 지정이 필요 없음.

자신이 속한 WFrame 내에서만 찾음.

명시적 지정이 필요. (명시적 지정이 없을 경우, 부모나 전역의 자원을 자동으로 참조하지 않음.)

스크립트가 참조하는 자원이 자신이 속한 WFrame에 없는 경우

부모나 전역을 검색.

오류를 반환.

다른 유효 범위 참조


외부의 WFrame에 있는 객체를 참조하기 위해서는 명시적으로 해당 객체를 지정해야 합니다.

(WFrame 간의 화면 참조 참고.)

postDrawMode

본 설정은 다중 WFrame 구조를 사용하는 경우 필요합니다. 본 설정을 추가해야 Scope 기능 적용을 위해 정의된 스크립트 실행 순서를 보장할 수 있습니다.

config.xml 파일에 아래의 설정을 추가하십시오.

설명

페이지 내 스크립트 즉시 실행 여부.

설정 위치

config.xml

$r_title(config.xml 설정)
<postDrawMode value="synchronous"></postDrawMode>

SP1 이전 엔진의 하위 호환성을 유지하기 위해 별도로 설정하십시오.

SPA Variable

각 화면 파일의 스크립트를 해당 WFrame 내에서만 실행하기 위해서는 스크립트 앞에 변수를 추가해야 합니다. 이 변수를 config.xml 파일에 등록하십시오. 기본 값은 scwin입니다.

설명

Scope 변수 지정.

설정 위치

config.xml

$r_title(scope 변수 지정)
<spa>
	<variable value="scwin"/>
    ...

</spa>
  1. Project Explorer에서 WebSquare Project를 우클릭한 후 Properties를 클릭합니다.

  2. WebSquare - Engine Configuration을 선택합니다.

  3. <spa><variable> 옵션을 설정합니다. (여러 개를 등록할 경우, 제일 앞의 변수가 적용됩니다.)

  4. Project Explorer에서 WebSquare Project를 우클릭한 후 Properties를 클릭합니다.

  5. WebSquare - Engine Configuration을 선택합니다.

  6. <spa><variable> 옵션을 설정합니다. (여러 개를 등록할 경우, 제일 앞의 변수가 적용됩니다.)

scope 변수 지정

lazy="false"

화면 파일(XML)을 스크립트 실행 순서에 따라 로딩하기 위해 필요한 설정으로, 각 화면 파일에서 설정합니다.

설명

업무 스크립트 생성 시점.

설정 위치

화면 파일 (XML)

SP1 Studio 부터 WebSquare Page 선택시 기본 설정으로 선택됩니다.

Scope 기능을 사용하려면 아래와 같이 JavaScirpt의 lazy="false" 모드를 설정해야 합니다.

  1. Project Explorer에서 WebSquare Project를 우클릭한 후 Properties를 클릭합니다.

  2. WebSquare - Design Editor를 선택합니다.

  3. Use JavaScript Section Lazy Loading flag 항목을 선택 해제합니다.

lazy="false" 설정

  1. WebSquare 프로젝트 - New - WebSquare Page를 선택합니다.

  2. Source 탭에서 아래와 같이 JavaScript의 lazy="false" 모드가 설정된 것을 확인합니다.

$r_title(lazy="false" 모드)
<script type="text/javascript" lazy="false">

mode="sync", scope="true"

mode="sync" 설정은 다중 WFrame 구조를 사용하는 경우 필요합니다. 본 설정을 추가해야 Scope 기능용 스크립트 실행 순서를 보장할 수 있습니다.

scope="true'" 설정은  WFrame에 포함된 컴포넌트 및 스크립트의 유효 범위를 제한하기 위해 필요합니다. 
(1) 컴포넌트 ID에 WFrame에 대한 정보(유효 범위)를 추가.
(2) WFrame 내에서 정의된 스크립트는 해당 WFrame 내에서만 실행.

설명

WFrame 속성.

페이지 내 스크립트 즉시 실행 여부.

설정 위치

config.xml (WFrame)

config.xml 파일에 아래의 설정을 추가하십시오.

$r_title(설정 예 (config.xml))
<wframe>
	<mode value="sync"/>
	<scope value="true"/>
</wframe>

WFrame의 scope 기능은 WFrame의 속성을 통해서도 설정할 수 있습니다. Property 탭에서 scope 속성을 true로 선택하십시오.

Property 탭에서 설정

$r_title(소스 코드 상 scope 설정)
<w2:wframe ... scope="true" ...>

<getWindow searchTarget="windowId"/>

WindowContainer를 위한 설정으로 getWindow 함수가 windowId를 기준으로 동작하도록 설정합니다.

설명

getWindow 함수가 windowId를 기준으로 동작하도록 설정.

설정 위치

config.xml (WindowContainer)

<windowContainer>
	<getWindow searchTarget="windowId"/>
</windowContainer>

ID 변경

최상단 메인 화면

strictMode를 사용할 경우, 최상단 메인 화면은 WFrame으로 감싸지고 메인 화면에 속한 컴포넌트의 ID는 아래와 같이 변경됩니다.

ID 변경 예시

<strictMode value = "false">

<strictMode value = "true" id="mf">

  • id="textbox1"

  • id="mf_textbox1"

CSS 디자인


strictMode 사용은 최상단 메인 페이지를 WFrame으로 씌우는 것을 의미합니다.

즉, 메인 화면에 속한 컴포넌트의 ID는 "메인 화면에 사용한 WFrame의 ID" + "_" + "컴포넌트 ID"로 변경됩니다.

이는 메인 화면의 CSS 디자인에도 영향을 미칩니다.

예를 들어 #header 대신 #메인화면용WFrame의ID_header 형식을 사용해야 합니다.

좀더 자세한 내용은 CSSclass selector 사용jQuery의 id selector 사용 부분을 참고하십시오.

예제 (1)

strictMode 적용에 따른 ID 변경 (변경 전)

strictMode 적용에 따른 ID 변경 (변경 후)

$r_title(strictMode 적용 (config.xml))
<strictMode value="true" id="mf"/>
$r_title(main.xml)
<body ev:onpageload="scwin.onpageload">
	<xf:input id="input1" style="width: 120px;height: 21px;"></xf:input>
	<w2:textbox id="textbox1" label="Home" style=""></w2:textbox>
	<w2:wframe id="header" style="" src="header.xml" scope="true"></w2:wframe>
	<w2:wframe id="contents" style="" src="contents.xml" scope="true"></w2:wframe>
	<w2:wframe id="footer" style="" src="footer.xml" scope="true"></w2:wframe>
</body>
$r_title(header.xml)
<body ev:onpageload="scwin.onpageload">
	<xf:input id="input1" style="width: 120px;height: 21px;"></xf:input>
	<w2:textbox id="textbox1" label="Home" style=""></w2:textbox>
</body>
$r_title(contents.xml)
<body ev:onpageload="scwin.onpageload">
	<xf:input id="input1" style="width: 120px;height: 21px;"></xf:input>
	<w2:textbox id="textbox1" label="Home" style=""></w2:textbox>
	<w2:wframe id="sub" style="" src="sub.xml" scope="true"></w2:wframe>
</body>
$r_title(sub.xml & footer.xml)
<body ev:onpageload="scwin.onpageload">
	<xf:input id="input1" style="width: 120px;height: 21px;"></xf:input>
	<w2:textbox id="textbox1" label="Home" style=""></w2:textbox>
</body>

예제 (2)

$r_title(main.xml의 Script)
scwin.param = "main.xml";
$r_title(wframe1.xml의 Script)

scwin.pageParam = "wframe1.xml";

console.log("scwin.pageParam = " + scwin.pageParam);
console.log("scwin.param = " + scwin.param);
console.log("$p.parent().scwin.param = " + $p.parent().scwin.param);
$r_title(실행 결과 (strictMode 사용 안 함))
scwin.pageParam = wframe1.xml
scwin.param = main.xml
$p.parent().scwin.param  = main.xml
$r_title(실행 결과 (strictMode 사용))

scwin.pageParam = wframe1.xml
scwin.param = undefined
$p.parent().scwin.param  = main.xml

예제 (3)

아래 스크립트는 id="image1" 인 컴포넌트의 title 속성 값을 찾는 동작을 수행합니다.

$r_title(예제)
$p.getComponentById("image1").getTitle();

strictMode를 사용하지 않으면, id="image1" 컴포넌트가 존재하지 않을 경우 상위 화면에서 id="image1" 컴포넌트를 찾습니다.

sctrictMode="false"

아래와 같이 strictMode를 사용할 경우, 스크립트가 정의된 WFrame 화면 내에는 id="image1" 컴포넌트가 존재하지 않기 때문에 오류가 반환됩니다.

sctrictMode="true"

WFrame 내부

WFrame의 scope="true" 설정을 사용할 경우, WFrame 내부에 포함된 컴포넌트의 ID는 아래와 같이 변경됩니다. 이를 통해 ID 중복을 원척적으로 차단할 수 있습니다.

ID 변경 예시

scope="false"

scope="true"

  • id="textbox1"

  • id="WFrame의ID_textbox1"

변경된 ID 사용 금지!


컴포넌트 ID의 변경은 내부적인 동작입니다. 즉, "WFrame의ID_" 문자열을 원래의 컴포넌트 ID 앞에 추가하는 규칙은 스펙에 따라 변경될 수도 있습니다. WFrame의 scope가 적용된 전체 ID 사용을 피하십시오. 엔진 업데이트 시 정상 동작하지 않을 수 있습니다.

ID 중복 허용

아래 예제에서 메인 화면은 WFrame 3개를 포함합니다. 또한 각 WFrame과 메인 화면은 동일한 ID를 사용하는 TextBox와 Trigger 컴포넌트를 포함합니다.

Scope 기능을 사용할 경우, 최상단 메인 화면WFrame 내부 화면에 포함된 컴포넌트의 ID가 변경되어 각 화면에 포함된 동일한 ID는 내부적으로는 서로 다른 ID로 변환됩니다. 그 결과 개발자는 ID 중복 걱정 없이 WFrame을 이용하여 화면을 구성할 수 있습니다.

WFrame을 사용한 화면 구성 (예)

$w Vs. $p

Scope 기능을 적용할 경우, 각 화면은 Scope 단위로 관리됩니다. 따라서 함수 역시 Scope 객체 내에서 실행되며, 해당 함수는 자신이 어느 Scope에서 실행되는지에 대한 정보가 필요합니다. 그러나 자신이 속한 Scope 정보를 별도의 인자로 받도록 처리할 경우, 코딩이 복잡해 집니다.

이를 해결하기 위해 Scope 객체에 기존의 $w 계열 함수를 모두 추가했습니다. 즉, 유틸리티 기능을 제공하는 $w.XXX 부류의 API를 scwin.$w.XXX 형태로 사용할 수 있습니다. 그러나, 이 역시 코딩이 길어지는 문제가 있습니다. 이를 위해 scwin.$w$p에 매핑하여, scwin.$w 대신 $p를 사용할 수 있도록 했습니다.

$r_title($p 사용)
// (1) Scope 기능을 사용하지 않을 경우
$w.createSubmission("submission1");

// (2) Scope 기능을 사용할 경우
// (2-1) scwin을 붙여야 함
scwin.$w.createSubmission("submission1");

// (2-2) scwin.$w를 축약한 $p 사용 가능
$p.createSubmission("submission1");

WFrame 간의 화면 참조

주요 API

주요 API

API

설명

getWindow()

WFrame의 scope를 반환.

parent()

부모 페이지(WFrame)의 scope를 반환.

top()

최상위 페이지의 scope를 반환.

  • strictMode를 사용할 경우, 최상위에 id로 지정된 이름으로 자동 생성된 WFrame의 scope가 반환됨.

  • strictMode를 사용하지 않는 경우, window.top이 반환됨.

main()

페이지의 최상위 scope를 반환.

실제 프레임이 다른 영역까지는 검색하지 않음.

top vs. main


아래의 그림과 같은 경우 WFrame1-1에서 각 API를 실행하면 서로 다른 결과를 반환합니다.

top: main을 반환.

main: IFrame을 반환.

원칙

자식 → 부모 ($p.parent();)

$r_title(사용 예)
$p.parent().$p.parent().input1.setValue("test");

형제

$r_title(사용 예)
$p.parent().$p.parent().wframe2.getWindow().wframe2-2.getWindow().scwin.test1();

부모 → 자식 (wframe.getWindow();)

$r_title(사용 예)
wframe1.getWindow().wframe1-1.getWindow().input1.getValue();

정리

부모 → 자식

코딩 방식 비교

SP1

SP3 이후

getObj

getWindow

$r_title(SP1)
wframe1.getObj("wframe11").getObj("input1").getValue();
$r_title(SP3 이후)
wframe1.getWindow().wframe11.getWindow().input1.getValue();

자식 → 부모

코딩 방식 비교

SP1

SP3 이후

scwin.$w.getRuntimeId

$p.parent

$r_title(SP1)

var realId = scwin.$w.getRuntimeId("input2", "parent.parent");
WebSquare.util.getComponentById(realId).setValue("test");
$r_title(SP3 이후)
$p.parent().$p.parent().input2.setValue("test");

TabControl

TabControl에서 각 탭 접근

코딩 방식 비교

SP1

SP3 이후

  • TabControl의 getFrame()

  • WFrame의 getObj

  • getWindow()

  • getWindow()

$r_title(SP1)

tabControl1.getFrame(tabControl1.getTabIndex("tab1")).getObj("wframe_header").getObj("scwin").test();
$r_title(SP3 이후)
tabControl1.getWindow("tab1").wframe_header.getWindow().scwin.test();

WindowContainer

WindowContainer에서 각 Window 접근

코딩 방식 비교

SP1

SP3 이후

  • WindowContainer의 getWinInfoObj()

  • WFrame의 getObj

  • $p.main()

  • WindowContainer 및 WFrame 의 getWindow()

$r_title(SP1)
windowContainer1.getWinInfoObj("window2", "windowId").window.frame.getObj("wframe_header").getObj("dataList1").getAllJSON();
$r_title(SP3)
$p.main().windowContainer1.getWindow("window2").wframe_header.getWindow().dataList1.getAllJSON();

예제

화면 구성 예

wframe1-1의 input1에 접근하기

스크립트 위치

접근 방법

main

wframe1.getWindow().wframe1-1.getWindow().input1.getValue();

wframe1

wframe1-1.getWindow().input1.getValue();

wframe1-1

input1.getValue();

wframe2

$p.parent().wframe1.getWindow().wframe1-1.getWindow().input1.getValue();

iframe1

$p.parent().wframe1.getWindow().wframe1-1.getWindow().input1.getValue();

main의 scwin.test1(); 실행하기

스크립트 위치

접근 방법

main

scwin.test1();

wframe1

$p.parent().scwin.test1();

$p.top().scwin.test1();

wframe1-1

$p.top().scwin.test1();

$p.parent().$p.parent().scwin.test1();

wframe2

$p.parent().scwin.test1();

$p.top().scwin.test1();

iframe1

$p.parent().scwin.test1();

iframe1의 input2에 접근하기

스크립트 위치

접근 방법

main

iframe1.getWindow().input2.getValue();

wframe1

$p.top().iframe1.getWindow().input2.getValue();

wframe1-1

$p.parent().$p.parent().iframe1.getWindow().input2.getValue();

$p.top().iframe1.getWindow().input2.getValue();

wframe2

$p.parent().iframe1.getWindow().input2.getValue();

wframe3

$p.main.getWindow().input2.getValue();

iframe1

input2.getValue();

WFrame 생성 옵션 전달

WFrame 생성 시 dataObject 속성을 통해 데이터를 전달할 수 있고, 호출된 페이지는 $p.getParameter로 해당 데이터를 참조할 수 있습니다.

아래의 예와 같이 $p.openPopup을 통해 팝업을 생성할 때 새로 생성할 팝업의 옵션을 전달하는 방법과 동일합니다.

$r_title($p.openPopup 사용 예)
var options = {
    id: "popup1",
    type: "browser",
    width: "230px",
    height: "250px",
    top: "130px",
    left: "200px",
    popupName: "openPopup1",
    modal: true,
    useIFrame: useIFrame,
    resizable: true,
    status: true,
    menubar: false,
    scrollbars: false,
    title: false,
    dataObject: dataObj
};

$p.openPopup("/popup.xml", options);

설정 방법

dataObject는 크게 type, name, data 속성으로 구성되며, 모든 속성이 존재해야 정상 동작합니다.

dataObject 속성 설명

속성

설명

type

데이터 종류.

  • "json": 권장

  • "xml": 비권장

  • "array": 비권장

name

$p.getParameter API를 통해 데이터를 가져오기 위한 key 값.

data

실제 전달할 데이터.

데이터는 복제되어 전달되며 데이터를 받은 쪽에서 값을 변경해도 원래 데이터는 변경되지 않습니다.

$r_title(dataObject 예)
var dataObject = {
    "type": "json",
    "name": "dataObject",
    "data": {
        "param1": "test",
        "param2": {
            "param22": "test2"
        },
        "callback": "$p.parent().scwin.windowContainer1_callback"
    }
}

직접 설정

JSON.strinigfy를 통해 변환된 값을 dataObject로 그대로 설정하면 됩니다.

단, 각 속성을 반드시 큰 따옴표 ("")로 감싸야 합니다. 그렇지 않을 경우 JSON.parse 시에 오류가 발생합니다.

$r_title(직접 설정 (예))
<w2:wframe id="wframe1" src="wframe1.xml" 
	dataObject='{"type":"json",
		"name":"dataObject",
		"data":{"param1":"test","param2":{"param22":"test2"},
		"callback":"$p.parent().scwin.wframe1_callback"}}'/>

setDataObject를 통해 동적으로 설정

wframe1.setDataObject(dataObject); 호출하여 데이터를 설정한 후 $p.getParameter를 통해 해당 데이터를 가져올 수 있습니다.

$r_title( parameter를 받는 페이지에서 parameter를 활용하는 예제 (main.xml))
scwin.wframe1_callback = function(scope) {
    $p.log("parent : "
        $p.id + ", child : " + scope.id);
}
$r_title( parameter를 받는 페이지에서 parameter를 활용하는 예제 (wframe.xml))
scwin.trigger1_onclick = function() {
    var obj = $p.getParameter("dataObject");
    // $p.getParameter로 값을 가져온다.
    $p.log(JSON.stringify(obj));
    try {
        eval(obj.callback)($p);
        // parameter로 전달받은 함수를 실행할 때는 eval을 사용한다.
        // 부모 페이지의 scwin.wframe1_callback 함수가 실행된다. 
    } catch (e) {}
}

관련 컴포넌트

TabControl, WFrame, WindowContainer 컴포넌트에서 WFrame을 생성할 때 WFrame의 옵션을 dataObject를 통해 전달 할 수 있습니다.

각 컴포넌트 별 관련 API

TabControl: addTab()

WindowContainer: createWindow()

popUp: $p.openPopup()

WFrame: setSrc()

제약 사항

dataObject의 data 객체 전달 시 JSON.stringifyJSON.parse를 통해 값을 복사하며, 그 결과 다음 제약 사항이 존재합니다.

객체에 함수 직접 입력 금지

객체의 값에 함수를 직접 넣을 경우, 해당 속성 값은 무시됩니다. dataObject 객체는 JSON.stringify API로 변환이 가능해야 하는데 JSON.stringify는 함수를 무시합니다. 함수는 string 형태로 전달한 다음, 전달 받는 페이지서 eval을 통해 실행하십시오.

함수 실행 시 scopeparameter를 받는 페이지입니다. 즉, parameter를 전달한 페이지 내의 함수를 실행하려면 함수명 앞에 $p.parent().를 붙여야 합니다.

순환 참조 금지

객체는 순환 참조를 포함할 수 없으며, 모든 속성은 반드시 유한한 depth를 가져야 합니다. 순환 참조가 있을 경우, 값을 복사할 수 없습니다. 순환 참조가 필요한 경우, 해당 객체명을 string 형태로 넘긴 후, parameter를 받는 쪽에서 별도의 처리를 해야합니다. 예를 들어 {"test" : window}와 같은 window 객체를 parameter로 넘겨야 하는 경우, {"test" : "window"}와 같이 string으로 넘긴 후, 추후 eval 등으로 별도로 처리해야 합니다.

비권장


parameter로 window 객체를 넘기는 것은 권장하지 않습니다.

WFrame 사용 시 유의 사항

외부 라이브러리 수동 릴리즈

WFrame이 언로딩될 때 엔진은 아래의 자원을 자동으로 제거합니다.

그러나 이외의 자원은 그대로 제거되지 않고 남아 있습니다. 예를 들어, WFrame 화면 내에서 전역 변수를 선언한 경우, 해당 변수는 페이지가 제거되어도 그대로 남아있습니다. 마찬가지로 특정 화면이 외부 라이브러리를 사용할 경우 해당 화면이 제거되어도 외부 라이브러리는 그대로 남아있습니다. 따라서 페이지의 onpageunload 이벤트에서 외부 라이브러리를 반드시 수동으로 릴리즈해야 합니다.

onpageload에서 setSrc 호출 시 src 속성 비우기

onpageload 이벤트가 자기 화면 WFrame에 대해 setSrc를 호출할 경우, WFrame의 src 속성을 비우십시오. setSrc를 호출할 경우, 기존 페이지를 먼저 언로딩해야 합니다. 즉, src 속성이 존재할 경우, 화면 렌더링 직후 해당 화면을 폐기히고 onpageload 이벤트로 새 화면을 호출하게 되어 자원 낭비를 초래합니다.

Scope 권장

SP3 이상 버전은 Scope 기능 적용을 권장합니다. scope="true" WFrame을 사용하십시오. scope="true" WFrame과 scope="false" WFrame의 혼용은 코딩의 복잡성을 증가시킵니다.

IFrame 제한

외부 솔루션과의 연계 등 브라우저를 다시 로딩하여 메모리를 비워야 하는 것과 같이 특수한 경우에만 IFrame을 사용하십시오. 대부분의 경우, WFrame 사용을 권장합니다.

공통 함수

각 공통 함수는 자신이 실행된 Scope 내에서만 유효해야 합니다. 즉, WFrame에서 호출된 공통 함수는 해당 WFrame 내에서만 실행되어야 합니다. 그 결과, 공통 함수 개발자는 호출된 공통 함수가 어느 Scope에서 호출되었는지 파악할 수 있는 방법을 제공해야 합니다. 아래 두 가지 방법으로 가능합니다.

  1. Scope 내에 공통 함수 객체를 생성 (권장)

  2. 공통 함수 호출시 scope를 변수로 전달

객체 생성 방식 (권장)

config.xml의 설정 중 <engine>/<module>로 로딩되는 JS에 포함된 공통 함수는 Main에 생성됩니다. 그러나 각 Scope에서 공통 함수를 호출할 경우, 호출된 공통 함수는 해당 Scope 내에서만 유효해야 합니다.

이를 위해 SP3 이상 버전은 config.xml 파일에 각 scope 마다 서로 다른 공통 함수 객체를 자동으로 생성할 수 있는 설정 항목을 제공합니다.

아래의 예제의 경우, 각 Scope마다 각기 다른 com 객체가 자동 생성됩니다.

$r_title(config.xml 설정 예)
<engine>
	<module src="/common/js/common.js" />
</engine>
<spa>
	<variable value="scwin" clone="com"/>
</spa>

객체 생성 방식은 가장 간단히 scope를 참조할 수 있는 방법으로 아래 설명할 변수 전달 방식에서 발생할 수 있는 변수 전달 오류를 방지할 수 있어 권장합니다.

예제

  1. 공통 함수를 작성한 파일을 common.js 파일에 작성합니다.

  2. 공통 함수 객체를 com이라고 가정합니다.

  3. config.xml 파일에 아래 설정을 추가하십시오. (Scope에 생성할 공통 함수 객체를 clone 속성에 지정.)

$r_title(config.xml 설정 예)
<engine>
	<module src="/common/js/common.js" />
</engine>
<spa>
	<variable value="scwin" clone="com"/>
</spa>
$r_title(common.js 예)
com = {
    // 통신 속성 정보
    CONTEXT_PATH: "", // Context Path 경로
    SERVICE_URL: "", // Service Url
    DEFAULT_OPTIONS_MODE: "asynchronous", // 기본 통신 모드 ( "asynchronous" / "synchronous")
    DEFAULT_OPTIONS_MEDIATYPE: "application/json", // 기본 미디어 타입

    // 통신 상태 코드
    MESSAGE_CODE: {
        STATUS_ERROR: "E",
        STATUS_SUCCESS: "S",
        STATUS_WARNING: "W"
    }
}
com.setCommonCode = function(codeOption, callbackFunc) {
        ……

변수 전달 방식

공통 함수 호출시 scope를 알 수 있는 객체(예: scwin, $p, 웹스퀘어 컴포넌트)를 함수의 변수로 받을 수 있습니다. 객체 정보에서 Scope 정보를 참조하여 해당 Scope에 생성된 $p를 사용하십시오.

$r_title(사용 예)
com.openPopup = function($p, url, opt, dataJson) {
        ……

예를 들어, 컴포넌트 ID를 변수로 받아 해당 컴포넌트에 대해 $w.XXX 류의 유틸리티성 API를 실행하는 공통 함수가 존재할 수 있습니다. 이 경우, 공통 함수는 Scope 내에서만 실행되어야 하기 때문에 변수로 받은 컴포넌트에 대해 $p.XXX (혹은 scwin.$w.XXX) 형태의 API를 실행해야 합니다.

예제

다음은 컴포넌트의 title 값을 반환하는 공통 함수 예제입니다. 공통 함수는 컴포넌트 ID를 변수로 받아 해당 컴포넌트에 대해 정의된 API를 실행합니다. 본 함수는 해당 Scope 내에서만 실행되어야 하기 때문에, 함수 앞에 scwin.을 추가하거나 유틸성 API 경우 $w 대신에 $p(혹은 scwin.$w)를 사용해야 합니다.

$r_title(공통 함수 정의 (예))
titleFinder = function($p, compId) {
    return $p.getComponentById(compId).getTitle();
}

pathFinder = function($p, compId) {
    var rawpath = $p.getComponentById(compId).getSrc();
    return rawpath.substring(rawpath.lastIndexOf('/') + 1);
}

위와 같이 정의한 공통 함수를 화면 파일에서 사용할 경우 $p를 변수로 입력해야 합니다.

$r_title(공통 함수 사용 (예))
scwin.trigger1_onclick = function(e) {
    var title = titleFinder($p, "image1");
    input1.setValue(title);
};

scwin.trigger2_onclick = function(e) {
    var imagepath = pathFinder($p, "image1");
    input2.setValue(imagepath);
};

프로젝트의 Scope 기능 사용 여부 및 함수의 Scope 참조 여부에 따라 공통 함수의 변수가 변경될 수 있습니다. 따라서 변수 전달 방식은 공통 함수의 표준화와 개발의 편의를 위해서 권장하지 않습니다.

외부 라이브러리 연동

SP3 이상 버전은 외부 JS를 내부 화면 내에 정의된 script와 동일하게 실행할 수 있는 기능을 제공합니다. 즉, 화면이 외부 JS를 포함할 경우, 해당 외부 JS는 화면의 컴포넌트 및 scwin 객체를 직접 참조할 수 있습니다.

WebSquare 페이지 내에서 외부 라이브러리를 로딩할 경우 아래 두 가지 속성을 추가하십시오.

scopeExternal

scopeExternal="true"인 경우, 연동된 외부 JS는 Scope 내에 접근할 수 있습니다.

$r_title(설정 예)
<script src="external_wframe1.js" scopeExternal="true"/>

객체 참조 가능 시점

스크립트 로딩 시 즉시 함수가 선언/실행 되기 때문에 로딩 직후에는 렌더링된 객체를 참조하지 못할 수 있습니다. onpageload 이벤트 이후부터 객체를 참조하십시오.

외부 라이브러리 객체 삭제

외부 라이브러리에서 생성한 객체는 Page 언로드시에 자동 삭제되지 않습니다. 메모리 문제가 우려되는 경우, IFrame으로 분리하여 사용할 것을 권장합니다.

scopeVariable

엔진이 외부 JS 객체를 해당 Scope 내에 생성하고 삭제합니다. 이 때 사용할 객체명을 지정하십시오. 로딩된 객체는 해당 Scope 내에서만 사용 가능하고 Page 언로딩 시에 삭제됩니다.

$r_title(설정 예 (wframe1.xml))
<script src="/common/biz/ctiCommon.js" scopeExternal="true" scopeVariable="cti"/>
wframe1.xml 파일 내부에 아래 예제와 같이 외부 JS를 로딩할 경우,

(1) cti 변수가 자동으로 생성되고,

(2) ctiCommon.js wframe1.xml 내부 스크립트에서만 해당 변수에 접근할 수 있습니다.

변수 재정의 금지


scopeVariable로 등록한 변수를 외부 JS 파일 내에 재정의하지 마십시오. 이 변수를 재정의할 경우 해당 변수는 전역에 생성됩니다.

$r_title(citiCommon.js 내 객체 선언 금지)

/* 객체 선언 금지!!! */ 
/* 선언시 scope가 정상 동작하지 않습니다. */

//var cti = {}; // 금지

cti.pushCall = function() {
……

CSS

class selector 사용

WFrame을 사용하여 화면을 구성할 경우, 각 화면 내 컴포넌트의 ID는 항상 변합니다. 즉, input1 객체는 연결되는 WFrame에 따라 wframe1_input1이 될 수도 있고 wframe2_wframe22_input1이 될 수도 있습니다. 따라서 id selector 대신 class selector 사용을 권장합니다.

$r_title(사용 예)

// class 사용 (권장)
<xf:group id="group1" class="contentZ1"/> .contentZ1 { }

// id 사용 (비권장)
<xf:group id="group1"/> #group1 { }

class명 중복 주의


class selector를 사용할 경우 부모 화면에 정의된 스타일 이름과 겹치지 않도록 주의하십시오. 이름이 겹칠 경우 부모 화면의 class를 덮어 쓰게 되어 부모 화면의 스타일이 변경됩니다.

class명이 겹치지 않도록 화면 ID를 class명 뒤에 붙이는 방법을 권장합니다.

jQuery의 id selector 사용

Scope 기능을 사용할 경우, 각 화면에 존재하는 객체의 ID는 변합니다. 그러나 jQuery와 같은 외부 모듈을 사용할 경우, ID를 통해 WebSquare 객체에 접근해야 할 경우가 있습니다. 이를 위해 SP3 이상 버전은 외부 모듈이 ID를 통해서 WebSquare 객체에 접근할 수 있는 방법을 제공합니다.

아래와 같이 $p.$("#" + componentID) 형식으로 ID를 통해 객체에 접근하십시오.

$r_title(ID를 통한 접근 방법)

// Scope 적용 전 접근 방법 
// $("#input1")

// Scope 적용 후 접근 방식
$p.$("#input1")

$ 대신 $p.$를 사용하여 객체를 검색할 수 있습니다. 반환된 결과는 jQuery의 검색 결과와 동일하며, jQuery와 동일하게 API를 사용할 수 있습니다.

$r_title(사용 예)
$p.$("#link_area .link_text").css("color", "red")

SPA

Scope은 웹페이지 전체를 하나의 Single Page로 구현하기 위한 기능입니다. SP3 이전 엔진의 경우, IFrame을 통해 SPA를 구현했습니다. TabControl 및 WindowContainer의 경우 spaInitCount를 통해 엔진 재활용 가능한 IFrame 개수를 지정하고 spaAuto 속성을 통해 빈 IFrame을 1개씩만 미리 준비하도록 함으로써 초기 로딩 속도 저하를 방지했습니다. 그러나 SP3 이후 버전에서는 WFrame으로 구성환 화면에서 setSrc(); 함수만 실행하여 SPA를 쉽게 구현할 수 있습니다. 즉, Scope 기능 및 WFrame을 사용하여 별도의 추가 코딩 없이 SPA를 손쉽게 구현할 수 있습니다.

SP1 vs. SP3 이상


SP1

SP3 이상

구현 수단

  • IFrame 사용

  • WFrame 사용

구현 방식

  • 소스 코드를 통한 구현.

  • IFrame의 효율적 사용이 핵심.

  • TabControl 및 WindowContainer의 경우,

    • spaInitCount를 통해 엔진 재활용 가능한 IFrame 개수를 지정

    • spaAuto 속성을 통해 빈 IFrame을 1개씩만 준비하여 초기 로딩 속도 저하를 방지

  • 구현 방식 복잡

  • SPA 적용이 제한적

  • setSrc(); 함수 사용

  • 구현 방식 간단.

  • 적용에 제한 없음

디버깅

객체에 접근하기 위해서는, 해당 객체가 존재하는 Scope을 먼저 찾아야 합니다. 이후 해당 Scope 내에 있는 객체에 접근하십시오. Scope는 아래 방법으로 찾을 수 있습니다.

  1. $p.main() 혹은 $p.top()으로 상위 scope에 접근.

  2. $p.getWindow를 이용하여 원하는 객체가 포함된 scope에 접근.

아래는 디버깅용으로 Scope를 쉽게 찾기 위해 제공하는 API입니다.

디버깅용 API

API

설명

$p.debug.getScope(domElement);

렌더링된 domElement가 속한 화면의 Scope 객체를 반환.

$p.debug.getFrame(domElement);

렌더링된 domElement가 속한 화면의 WFrame ID를 반환.

예제

  1. 브라우저에서 개발자 도구를 실행합니다.

  2. DOM 탐색기에서 원하는 element를 클릭한다.

  3. 콘솔 창에서 $p.debug.getScope($0); API를 실행합니다.

  4. 반환되는 Scope 객체를 확인합니다.

브라우저의 디버깅 도구가 제공하는 특수 전역 객체 $0을 사용하면 DOM Element를 확인할 수 있습니다. $0은 현재 선택된 DOM Element를 반환하여 이는 디버깅용 API의 변수로 사용됩니다.

DOM Element 확인