SPA

개요

정의

SPA란 Single Page Application의 약자로 신속한 페이지 전환을 위해 단일 페이지 동작을 시도하는 웹 어플리케이션이나 사이트를 의미합니다. SPA를 적용한 웹 어플리케이션이나 사이트는 반복되는 HTML 코드를 다시 다운받지 않기 때문에 페이지 이동 속도가 빠르고 효율적인 자원 관리가 가능합니다.

특징

페이지 이동 속도가 향상됩니다.

WebSquare5 자원(엔진파일, CSS, 이미지 파일 등) 및 이미 로딩한 외부 JS파일을 재사용합니다.

페이지 이동이 일어나도 전역변수나 타이머는 그대로 남아 있기 때문에 이를 정리하기 위한 별도의 코딩이 필요합니다.

페이지 이동 시 ?w2xPath 인자가 아닌 #w2xPath 해시값으로 변합니다.

캐싱 설정

config.xml

config.xml 혹은 각 화면의 XML 페이지를 통해 자원의 캐싱 여부를 설정할 수 있습니다.

config.xml 파일은 아래와 같이 설정하십시오.

  1. [Window] -[Preferences] - [WebSquare] - [Engine Modification]을 선택합니다.

  2. config.xml<spa> 노드 아래 scriptCache 항목(이미 로딩한 스크립트를 다시 사용할지 여부)을 설정합니다.

$r_title(config.xml을 통한 설정)
<WebSquare>
     <spa>
            <scriptCache value="false"/>  
			<!-- 전역 설정은 false, 즉 캐싱하지 않음 -->
     </spa>

     <engine>
         <module src="xxx1.js" cache="true"/>  
		 <!-- xxx1.js는 캐싱 -->
         <module src="xxx2.js" cache="true"/>  
		 <!-- xxx2.js는 캐싱 --> 
     </engine>
</WebSquare>

위의 예에서 전역 캐시 옵션은 false로 스크립트는 캐싱되지 않습니다. 단, <module> 노드에서 cache="true"로 설정하여 xxx1.js xxx2.js는 캐싱되어 화면 이동시 다시 실행하지 않습니다.

config.xml<environment>노드의 cache 설정이 nocache 인 경우, config.xml의 module에서 등록한 js 파일은 scriptCache 설정에 관계없이 항상 다시 로드됩니다.

화면 XML 파일

각 화면 XML 파일의 경우, <script> 태그의 cache="[true|false]" 인자를 통해 외부 모듈의 캐싱 여부를 설정할 수 있습니다.

$r_title(개별 XML 파일을 통한 설정)
//화면 xml안에서 script 태그를 이용해서 등록한 외부 모듈
<script src="temp.js" cache="true|false"/>

//config.xml에서 등록한 외부 모듈
<engine>
	<module src="common.js" cache="true|false"/>
</engine>

<script> 태그를 통해 외부 JS 파일을 로딩하는 경우 XML 파일에 [cache] 옵션을 아래와 같이 설정하여 JS 파일을 캐싱할 수 있습니다.

$r_title(JS 파일 캐싱)
<script type="javascript" src="jquery-1.10.2.min.js" cache="true"/>

$p.js

$p.js API 호출 시 마지막 인자로 빈 함수를 전달하면 한 번 로딩했던 JS파일은 다시 로딩하지 않습니다. 마지막 인자가 함수가 아닐 경우에는 한 번 로딩했던 JS라도 다시 로딩합니다.

아래의 예에서, foo.js, bar.js, jquery-1.10.2.min.js 파일들이 각각 1번씩 순차적으로 로딩됩니다.

$r_title($p.js 사용 예)

$p.js("foo.js", "bar.js", "jquery-1.10.2.min.js", new Function());
$p.js("foo.js", "bar.js", "jquery-1.10.2.min.js", new Function());
$p.js("foo.js", "bar.js", "jquery-1.10.2.min.js", new Function());
$p.js("foo.js", "bar.js", "jquery-1.10.2.min.js", new Function());

사용

Location 객체를 통한 방법

#w2xPath 해시값

"#w2xPath" 해시값을 사용하여 페이지 이동 이벤트용 함수를 정의하십시오.

$r_title(사용 예)
scwin.trigger1_onclick = function(e) {
    location.href = WebSquare.baseURI + "websquare.html#w2xPath=/SPA_DEMO/result.xml";
};

$p.url

$p.url(w2xPath, option) 함수는 전체 URL 대신 w2xPath에 해당하는 경로만 전달하여 페이지를 이동합니다. options 인자를 통해 SPA 모드를 사용할 수 있습니다. $p.url과 관련된 좀 더 자세한 정보는 API 가이드를 참고하십시오.

$r_title(API 사용 예)
scwin.trigger1_onclick = function(e) {
    $p.url("/SPAN_DEMO/result.xml", {
        "spa": true
    });
};
$r_title(SPA 적용)
[적용 전] : location.replace("http://.../websquare.html?w2xPath=/folder1/bar.xml");
[적용 후] : $p.url("/folder1/bar.xml", {"spa" : true, {"replaceHistory" : true});

아래와 같이 브라우저를 갱신하여 전역 자원을 초기화할 수 있습니다.

$r_title(브라우저 강제 갱신)
$p.url("/folder1/bar.xml", {"spa" : true, "forceReload" : true});

config.xml에 설정을 추가할 것을 권장합니다.

<spa value="true">인 경우, $p.url API 두 번째 옵션 인자의 spa 기본값이 true가 됩니다.

또한, {"spa" : true}, IFrame의 SPA 옵션도 true로 설정됩니다.

그 결과 IFrame의 setSrc API를 호출 시에 IFrame에도 SPA가 적용됩니다.

w2xPath이외의 추가 인자 전달하기

#w2xPath 뒤에 '&'를 붙여 추가 인자를 전달하거나 $p.url API의 두번째 인자에 {param : paramObj}를 전달합니다.

$r_title(SPA 적용 전)
function reloadEmp(eventObject) {
    var pernr = eventObject.dataObject.pernr;
    var url = "/websquare/websquare.jsp?w2xPath=/com.kt.pct.parf.ep.hr.personnel.profile/xml/personalMain.xml" + " & PERNR = " + pernr;
    document.location.href = url;
}
var pernr = WebSquare.net.getParameter("PERNR");
$r_title(SPA 적용 후 (w2xPath뒤에 &인자 전달))
function reloadEmp(eventObject) {
    var pernr = eventObject.dataObject.pernr;
    var url = "/websquare/websquare.jsp#w2xPath=/com.kt.pct.parf.ep.hr.personnel.profile / xml / personalMain.xml " + " & PERNR = " + pernr;
    document.location.href = url;
}
var pernr = WebSquare.net.getParameter("PERNR");
$r_title(SPA 적용 후 (WebSquare.util.url API 이용))
function reloadEmp(eventObject){
var pernr = eventObject.dataObject.pernr;
            var w2xPath ="/com.kt.pct.parf.ep.hr.personnel.profile/xml/personalMain.xml";
            var param1 = {"PERNR" : pernr};
            $p.url( w2xPath, { "spa" : true, "param" : param1 } );  
      }
var pernr = WebSquare.net.getParameter( "PERNR" );

현재 화면 다시 그리기

현재 화면을 다시 그리고 싶은 경우 $p.reinitialize(reload) API를 사용합니다.

reload값을 지정하지 않은 경우 브라우저 갱신 없이 body 영역만 다시 그리며, reload="true"로 설정하면 location.reload를 호출하여 브라우저를 갱신합니다. 좀 더 자세한 정보는 API 가이드를 참고하십시오.

URL 인자 우선순위

url인자에 같은 값이 반복해서 나올 경우 항상 뒤에 있는 인자의 값을 가져옵니다.

$r_title(인자 중복시)
[실행문]
location.href = "http://.../websquare.html?w2xPath=/x1/foo.xml#w2xPath=/x2/bar.xml";
[실행결과]
/x2/bar.xml로 페이지가 이동됨.

[실행문]
loccation.href= ".../?w2xPath=/x1/foo.xml#w2xPath=/x2/bar.xml&w2xPath=/x3/baz.xml";
[실행결과]
/x3/baz.xml로 페이지가 이동됨.
$r_title(인자 중복시)
[실행문]
loccation.href= ".../?AA=100&BB=20#w2xPath=/x2/bar.xml&AA=200&BB=100&AA=50";
WebSquare.net.getParameter("AA") + "_" + WebSquare.net.getParameter("BB");
[실행결과]
50_100

노트

search는 항상 hash보다 먼저 위치합니다. hash뒤에 오는 '?'는 hash의 일부로 인식합니다.

'#'뒤에 올 수 있는 string은 '#'을 제외한 나머지 string이 올 수 있습니다. # 허용 string

스크립트 중복 로딩 방지

<script> 태그를 통해 외부 js를 로딩하는 경우

$r_title(cache 옵션)
[foo.xml]
<head>
<script type="javascript" src="jquery-1.10.2.min.js" cache="true"/> 
<script type="javascript" src="foo.js" cache="true"/>   
</head>

[bar.xml]
<head>
<script type="javascript" src="jquery-1.10.2.min.js" cache="true"/> 
<script type="javascript" src="bar.js" cache="true"/>
</head>

[baz.xml]
<head>
<script type="javascript" src="jquery-1.10.2.min.js" cache="true"/> 
<script type="javascript" src="foo.js" cache="true"/>   
<script type="javascript" src="bar.js" cache="false"/>  
<script type="javascript" src="baz.js" cache="true"/>
</head>

foo.xml에서 bar.xml 호출 시

1. jquery-1.10.2.min.js는 이미 로딩된 채로 남아있으므로 페이지 전환시에도 다시 로딩하지 않음

2. bar.js의 경우 로딩된 적이 없는 스크립트 파일이므로 새로 로딩하고 스크립트를 실행함

bar.xml에서 baz.xml 호출 시

1. jquery-1.10.2.min.js는 다시 로딩하지 않음

2. foo.js : cache="true"이므로 다시 로딩하지 않음

3. bar.js : cache="false"이므로 로딩 여부와 상관없이 새로 로딩해서 스크립트를 실행

4. baz.js : cache="true"이지만 로딩된 적이 한번도 없으므로 새로 로딩하고 스크립트를 실행

$p.js API를 이용하여 외부 js를 동적으로 로딩하는 경우

$p.js API 호출 시 마지막 인자로 빈 함수를 전달하면 한 번 로딩했던 js파일은 다시 로딩하지 않게 됩니다. 마지막 인자가 함수가 아닐 경우에는 한 번 로딩했던 js라도 다시 로딩하게 됩니다.

관련 컴포넌트

Trigger

  1. Design 뷰에서 Trigger 컴포넌트를 생성합니다.

  2. Trigger를 우클릭한 후 [이벤트 추가] - [onclick(e)]을 선택합니다.

  3. 이벤트 함수를 아래와 같이 정의합니다.

$r_title(SPA 모드용 이벤트 함수)
scwin.trigger1_onclick = function(e){
	location.href = WebSquare.baseURI + "websquare.html#w2xPath=/SPA_DEMO/result.xml";
};

위의 예제에 따르면 새로운 URL로 이동할 경우 w2xPath 인자는 #으로 전달됩니다.

$r_title(SPA 적용)
[적용 전] :
    location.href = "http://.../websquare.html?w2xPath=/folder1/bar.xml";
    location.assign("http://.../websquare.html?w2xPath=/folder1/bar.xml");
[적용 후] :
    location.href = "http://.../websquare.html#w2xPath=/folder1/bar.xml";
    location.assign("http://.../websquare.html#w2xPath=/folder1/bar.xml");

Anchor

  1. Design 뷰에서 Anchor를 생성합니다.

  2. Source 탭에서 href 속성을 아래와 같이 정의합니다.

$r_title(Anchor 속성 수정)
<w2:anchor id="anchor1" style="position: absolute ;left:41px;top:155px;width: 189px;height: 74px;" href="#w2xPath=/SPA_DEMO/result.xml" >

IFrame

화면에 공통 영역이 존재할 경우, 변경되는 부분만 I-Frame으로 그린 다음, I-Frame 부분만 SPA 모드로 로딩할 수 있습니다.

I-Frame 내부에서 SPA 모드로 이동할 경우

페이지 내에서 $p.url(w2xPath, options) API를 호출

$r_title(main.xml)
<w2:iframe id="iframe1" style="position: relative;width: 200px;height: 200px;" src="/SPA_DEMO/inner.xml" spa="false"></w2:iframe>
$r_title(inner.xml)
<head>
	<script type="javascript"><![CDATA[ 
		scwin.trigger1_onclick = function(e){
			$p.url("/SPA_DEMO/another.xml", {"spa": true});
		};
	]]></script>
	<w2:require src="/W5_ReleaseNote/WebSuqare5/WebSquare3.xml"></w2:require>
</head>
<body>
	<xf:trigger type="button" id="trigger1" style="position: relative;width:153px;height:23px;" ev:onclick="scwin.trigger1_onclick">
		<xf:label><![CDATA[click(inner.xml)]]></xf:label>
	</xf:trigger>
</body>
I-Frame 외부에서 SPA 모드로 이동할 경우

I-Frame의 spa 옵션을 true로 설정하고 iframe.setSrc(w2xPath)을 호출

$r_title(main.xml)
<w2:iframe id="iframe1" style="position: relative;width: 200px;height: 200px;" src="" spa="true"></w2:iframe>
<head>
	<script type="javascript"><![CDATA[ 
		scwin.trigger1_onclick = function(e){
			iframe1.setSrc("/SPA_DEMO/inner.xml");
		};
	]]></script>
	<w2:require src="/W5_ReleaseNote/WebSuqare5/WebSquare3.xml"></w2:require>
</head>
<body>
	<xf:trigger type="button" id="trigger1" style="position: relative;width:153px;height:23px;" ev:onclick="scwin.trigger1_onclick">
		<xf:label><![CDATA[click(inner.xml)]]></xf:label>
	</xf:trigger>
</body>

뒤로가기(History) 제어

SPA 모드에서 IFrame 화면의 뒤로가기를 제어할 수 있습니다. spaReplaceHistory="true"로 설정할 경우 뒤로 가기 버튼을 클릭하면 각 IFrame에 담긴 화면이 아닌 브라우저 전체가 이젠 페이지를 표시합니다.

예제 파일


인터넷에서 다운로드 혹은

WEBSQUARE_DEV_PACK의 GUIDE 프로젝트에서 보기

(/IFrame/spa_spaReplaceHistory_IFrame/)

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

TabControl

contents를 I-Frame으로 생성하는 경우

탭 종료 시 I-Frame을 파괴하지 않고 감춘 상태로 보관합니다. 이같은 방법으로 새 tab을 열면 감춰두었던 I-Frame의 setSrc API를 호출하여 I-Frame내에서 브라우저가 갱신 되지 않고 새로운 페이지를 열 수 있습니다.

$r_title(SPA용 IFrame 생성 개수 지정)
<w2:tabControl id="tabControl1"  windowMaxNum="10" spaInitCount="5"> 
//SPA용 I-Frame을 미리 5개 생성해 둔 상태에서 최대 10개 까지 열 수 있습니다.

WindowContainer

WindowContainer에서 xml파일을 읽어와 새로운 window를 생성하는 경우 SPA 적용이 가능합니다. WindowContainer 컴포넌트의 spaInitCount 속성에 미리 생성할 화면 개수를 설정하십시오. (I-Frame만으로도 새 창을 생성할 수 있습니다.)

$r_title(SPA용 IFrame 생성 개수 지정)
<w2:windowContainer id="windowContainer1" spaInitCount="10" windowMaxNum="10" />

뒤로가기(History) 제어

WindowContainer가 IFrame을 포함할 경우, IFrame 화면의 뒤로가기를 제어할 수 있습니다. spaReplaceHistory="true"로 설정할 경우 뒤로 가기 버튼을 클릭하면 각 IFrame에 담긴 화면이 아닌 브라우저 전체가 이젠 페이지를 표시합니다.

예제 파일


인터넷에서 다운로드 혹은

WEBSQUARE_DEV_PACK의 GUIDE 프로젝트에서 보기

(/WindowContainer/frameMode_spaReplaceHistory_WindowContainer/)

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

Scope 기능을 통한 SPA 구현

Scope 기능 및 WFrame을 사용하여 SPA를 구현할 수 있습니다. 좀 더 자세한 내용은 동작 부분을 참조하십시오.