개요
- 정의
SPA란 Single Page Application의 약자로 신속한 페이지 전환을 위해 단일 페이지 동작을 시도하는 웹 어플리케이션이나 사이트를 의미합니다. SPA를 적용한 웹 어플리케이션이나 사이트는 반복되는 HTML 코드를 다시 다운받지 않기 때문에 페이지 이동 속도가 빠르고 효율적인 자원 관리가 가능합니다.
- 특징
페이지 이동 속도가 향상됩니다.
WebSquare5 자원(엔진파일, CSS, 이미지 파일 등) 및 이미 로딩한 외부 JS파일을 재사용합니다.
페이지 이동이 일어나도 전역변수나 타이머는 그대로 남아 있기 때문에 이를 정리하기 위한 별도의 코딩이 필요합니다.
페이지 이동 시 ?w2xPath 인자가 아닌 #w2xPath 해시값으로 변합니다.
캐싱 설정
config.xml
config.xml 혹은 각 화면의 XML 페이지를 통해 자원의 캐싱 여부를 설정할 수 있습니다.
config.xml 파일은 아래와 같이 설정하십시오.
[Window] -[Preferences] - [WebSquare] - [Engine Modification]을 선택합니다.
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를 로딩하는 경우
[cache] 옵션을 통하여 한번 로딩했던 스크립트는 다시 로딩하지 않습니다.
<script type="javascript" src="jquery-1.10.2.min.js" cache="true"/>
와 같이 cache인자로 설정합니다.
$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
Design 뷰에서 Trigger 컴포넌트를 생성합니다.
Trigger를 우클릭한 후 [이벤트 추가] - [onclick(e)]을 선택합니다.
이벤트 함수를 아래와 같이 정의합니다.
$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
Design 뷰에서 Anchor를 생성합니다.
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에 담긴 화면이 아닌 브라우저 전체가 이젠 페이지를 표시합니다.
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를 구현할 수 있습니다. 좀 더 자세한 내용은 동작 부분을 참조하십시오.