프로그램개발/ClientSide(JavaScript,Angular,Vue)

jQuery Mobile 작업시 a href(앵커 태그)가 pc처럼 작동하려면

크레도스 2015. 4. 8. 15:04

jQuery Mobile로 모바일 웹페이지 작업하면서 이해가 잠깐 않되었던게 모바일 웹페이지로 앵커 태그 달고

페이지 이동을 누르면 페이지가 PC용 웹페이지처럼 새로고침이 되지 않는 요상한 증상을 발견하였다.

이걸 이해하려면 jQuery Mobile의 링크방식을 이해하여야 한다.

자세한 내용은 http://pgm-progger.blogspot.kr/2013/02/jquerymobile_20.html 참고


이 강좌는 아래 링크의 강좌를 토대로 설명을 덧붙인 내용입니다.

  http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html  

jQuery Mobile 에서 링크방식에 대해서 얘기를 해보겠습니다.

원래 우리가 흔히 웹에서 a 태그로 링크를 걸면, 전체 페이지가 갱신이 되면서, 페이지가 href 에 설정되어 있는 페이지로 이동(화면전환)을 하게 됩니다.

jQuery Mobile 프레임워크에서는 a 태그로 그냥 링크를 걸게 되면, 위의 기본 웹방식으로 화면이 전환되는 것이 아니고, ajax 로 해당 href 에 설정된 페이지 내용을 불러와서, 현재 페이지를 전체화면 갱신(화면깜빡거림현상) 없이 페이지를 전환하는 방식으로, 링크들을 기본적으로 처리합니다.

이 (ajax)방식으로 화면 갱신시에, 대상 페이지가(href 에 설정된 페이지) 시간이 오래 걸리게 되면, 로딩중 애니메이션이 나오면서 대기하다가, 페이지 로딩이 완료되면 화면깜빡거림 없이 페이지를 출력해줍니다.

ajax 링크방식

이 방식은 a 태그의 href 속성에 페이지 경로를 설정할때, 현재 사이트의 도메인과 다른 도메인으로 걸게되면, ajax 방식이 아닌, 원래 기본 웹방식(화면깜박거리면서 화면전환)으로 동작합니다.
크로스 도메인 페이지인 경우 보안상 ajax 호출이 제한되기 때문에, 이런 경우에는 기본적으로 ajax 가 아닌 기본 웹 링크방식으로 동작하는 것입니다.

현재 도메인 내의 페이지를 링크를 걸어주게 되면, 그때는 기본적으로 ajax 방식으로, 위에서 설명한 방식대로 화면이 전환 되게 됩니다.

<a href="index.asp">index</a>

특별한 속성 없는 위와 같은 링크는 ajax 방식으로 화면이 전환됩니다.

<a href="http://www.naver.com">naver</a>

위와 같이 다른 도메인으로 링크주소가 설정된 경우에는, 일반 웹 링크방식으로 전체화면이 갱신되면서 현재 페이지가 전환이 됩니다.

다중문서로의 링크

다중문서로 링크를 걸엇을때, 그냥 다중문서명만 링크를 걸면 해당 다중문서의 첫번째 페이지 내용의 화면으로 페이지가 전환됩니다.

만약 다중문서의 두번째 화면으로 이동하기 위해서, `다중문서명#페이지아이디` 이런식으로 링크를 걸게되면, 아무런 반응이 없습니다. ajax 방식의 링크에서는 위와 같은 식으로, #을 이용한 다중문서 내의 임의 페이지로의 링크방식을 허용하지는 않습니다.

단, 다음에 설명드릴 웹 링크방식 설정을 했을 경우에는, 다중문서의 임의 위치로도 이동이 가능하게 됩니다.

<a href="다중문서파일 경로">link</a>

위의 링크는, 기본 a 태그 링크를 했으므로, ajax 방식으로 링크이동을 할 것이고, 다중문서명을 입력했으므로, 해당 다중문서의 첫번째 페이지 내용으로 링크를 눌렀을때, 페이지가 전환될 것입니다.

웹 링크방식 지정하기

a 태그를 아무 속성없이 사용하면, 기본적으로 ajax 방식이 되는데요, a 태그에 rel="external" 속성이나 data-ajax="false" 속성 둘 중 하나를 a 태그에 지정해 주시면, 해당 링크는 ajax 링크방식이 아닌 일반 웹 링크방식으로 전체 화면이 깜빡거리면서 페이지가 전환됩니다.

둘 중 아무속성으로 설정해 주셔도 다 같은 방식으로 동작합니다.
단지 의미적으로 구분한 것 같습니다.
rel="external" 는 외부 도메인 링크를 걸때 이 속성을 사용해 주시고,
data-ajax="false" 는 내부 도메인 페이지로 이동할때, 웹 링크방식으로 이동시켜 주시려면, 이 속성을 a 태그에다가 설정해 줍니다.

<a href="index.html" data-ajax="false">index</a>

위의 링크는, data-ajax="false" 속성을 안줬으면, ajax 링크방식으로 화면이 전환되었을텐데, data-ajax="false" 속성으로 인해서, 전체화면이 깜빡거리면서 웹 링크방식으로 화면이 전환되게 됩니다.

target 속성 지정하기

a 태그에다가 target 속성을 지정하신 경우에는, ajax 링크방식으로 동작하지 않게 되고, 기존 웹의 방식 그대로 동작하게 됩니다.

즉, target 에 지정된 이름의 iframe 이나, 팝업윈도우가 있으면 해당 태그의 페이지가 갱신되고, 없으면 새창이 뜨게 됩니다.

<a href="index.html" target="_blank">index</a>

그냥 새창으로 index.html 페이지가 뜹니다.
기존 웹방식과 완전 동일합니다.

뒤로가기 속성 설정하기

a 태그에다가 data-rel="back" 속성이나 data-direction="reverse" 속성을 설정하시면, 해당 태그를 눌렀을때, href 값과는 전혀 상관없이, 웹브라우저의 뒤로가기 역할을 하여, 이전 페이지로 돌아가게 됩니다.

단, data-rel="back" 속성과 data-direction="reverse" 속성의 차이점은, 

data-rel="back" 속성은 웹브라우저 뒤로가기 기능과 일치하게 동작합니다. 
즉, 웹브라우저에서 뒤로가기 하게되면, 이전 화면의 상태를 그대로 복구합니다. 
스크롤 했던 상태라든지, 등등..

data-direction="reverse" 속성은, 이전페이지로 이동하는 것은 동일하지만, data-rel="back" 과는 달리 이전 화면의 상태를 그대로 복원하지는 않습니다. 스크롤 상태라든지 이런 상태를 복원하지 않고, 그냥 단순히 이전 페이지로 이동하는 기능만 합니다.



<!DOCTYPE html>
<html>
<head>
<title>링크 연습</title>
<meta charset="euc-kr">
<meta name="viewportcontent="width=device-width, initial-scale=1">
<link rel="stylesheethref="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>링크 연습입니다.</h1>
</div><!-- /header -->
<div data-role="content">
<h2>Link examples</h2>
<p>
All standard HTML link types are supported in jQuery Mobile in addition to the types outlined above.
<br />(jQuery Mobile 에서는 일반적인 html 링크방식 및 위에서 설명한 다양한 링크방식을 지원합니다. ajax 방식 등등.. ^^)
</p>
<p>
Here is a sampler of many common link types:
<br />(아래에 다양한 형식의 링크방식의 샘플이 있으니 참조바랍니다. ^^)
</p>
<ul data-role="listviewdata-inset="truedata-theme="ddata-divider-theme="d">
<!-- ########## ajax 링크 이동방식 ########## -->
<!-- data-role="list-divider" : 리스트 하위그룹단위 구분자 -->
<li data-role="list-divider">Links that will be Ajax-loaded with page transitions</li>
<!--
링크를 걸때, ajax 를 사용할 수 있는 상황이면, 기본적으로 ajax 를 이용하여 페이지를 전환하고,
크로스 도메인이나, 기타 ajax 를 호출할 수 없는 상황이면, 원래 기본 링크방식으로 페이지를 전환합니다.
기본적으로, jQuery Mobile 프레임워크는 링크태그의 href 속성값을 읽어서 ajax 방식으로 페이지를 역동적으로 전환합니다.
역동적이라는 의미는, 페이지 전환시 기존 링크방식처럼 페이지가 흰색바탕화면을 잠깐 보여주고 페이지를 이동하는 것이 아닌,
현재 페이지에서 페이지를 ajax 로 로딩하여, 페이지를 갱신하므로, 화면깜빡거림 현상이 보이지 않게 되고,
대신 프레임워크에서 기본적으로 페이지 로딩시간동안 로딩 애니메이션을 보여줍니다.
href 속성값이 동일한 도메인내의 페이지로 이동하는 것이면, 기본적으로 ajax 방식으로 페이지를 전환합니다.
만약 링크값이 잘못되어 있으면, 에러메시지를 레이어가 잠깐 나왔다가 사라지는 방식으로, 잘못된 링크에 대해서 처리를 합니다.
다중문서로 구성된 페이지로의 링크는 ajax 방식으로는 지원되지 않습니다.
그냥 해당 다중문서의 페이지명으로만 링크를 걸면, 해당 다중문서의 첫번째 문서로 전환됩니다.
예를들어 다중문서의 두번째 페이지 아이디가 foo2 라고 하면, '페이지명#foo2' 라고 링크를 걸면, 아무런 동작도 안합니다.
-->
<li><a href="index.asp">Link in the same domain</a></li>
<li><a href="001_1.asp">다중문서로의 페이지 링크 (다중문서의 첫번째 페이지로 이동)</a></li>
<li><a href="001_1.asp#foo2">다중문서로의 페이지 링크 (두번째 문서[#foo2]로의 링크, 동작안함)</a></li>
<li><a href="001_1.asp#foo2data-ajax="false">다중문서로의 페이지 링크 (두번째 문서[#foo2]로의 링크, data-ajax="false" 속성을 설정해주면, 정상적으로 이동합니다.)</a></li>
<li><a href="abc.html">링크오류, abc.html은 이 사이트에서 존재하지 않습니다.</a></li>
<!--
링크속성에 data-rel="dialog" 를 설정하시면, 링크대상 페이지가 뒤로가기 히스토리에 남지 않게 됩니다.
즉 링크대상 페이지가 떴다가 다시 현재 페이지로 돌아오면, 다시 뒤로가기를 했을때 바로 전에 떴던 다이얼로그
페이지가 뜨지 않고, 현재 페이지의 이전 페이지로 이동하게 됩니다.
다이얼로그 페이지의 동작방식을 지원해주게 됩니다.
-->
<li><a href="010_dialog.htmldata-rel="dialog">Dialog link: data-rel="dialog" (not tracked in history)</a></li>
<!-- ########## 기존 웹방식 링크(전체화면 갱신) ########## -->
<!--
ajax 방식이 아닌 링크방식
현재 사이트의 도메인과 다른 도메인으로 링크를 걸어주거나,
링크 속성에 rel="external", data-ajax="false" 를 설정해주시거나,
target 속성을 설정해 주시면, ajax 방식으로 링크를 처리하지 않고,
전체 페이지를 갱신하면서, 페이지 전환 애니메이션 없이, 원래 기본 웹방식의 링크방식으로 처리합니다.
rel="external" 속성과 data-ajax="false" 속성은 똑같은 링크효과를 주게 되지만,
의미와 용도에 따라서 맞는 속성을 사용하는 것이 좋습니다.
rel="external" 속성은 다른 도메인으로 링크를 걸때 a 태그에 속성을 지정해 주시고,
data-ajax="false" 속성은 동일한 도메인 내의 페이지로 ajax 방식이 아닌 기존 웹방식으로 이동하고자 할때,
a 태그에 속성값을 주시면 됩니다.
버전1.1 에서는, data-ajax="false" 를 많이 사용해야 하는 경우를 위해서, a 태그가 아닌 그 부모요소에
data-ajax="false" 속성을 설정하시면, 모든 그 하위 a태그들이 웹방식 링크로 동작하게 됩니다.
이 기능을 이용하시려면, $.mobile.ignoreContentEnabled = true; 옵션값을 활성화 시키시면 됩니다.
-->
<li data-role="list-divider">Links that will refresh the page</li>
<li><a href="http://www.jquery.com">External domain (외부 jquery 사이트 도메인으로 이동이라, 전체화면이 갱신되면서 이동합니다.)</a></li>
<!--
index.asp 는 같은 내부도메인 페이지 이지만,
rel="external" 속성으로인해 전체화면 갱신방식의 링크로 이동합니다.
하지만 내부도메인으로의 이동이므로, rel="external" 속성보다는,
동일한 기능을 하는 data-ajax="false" 속성 설정으로 지정해주시는게 용도에 맞는 것 같습니다.
-->
<li><a href="index.asprel="external">Link with rel="external"</a></li>
<li><a href="index.aspdata-ajax="false">link with [data-ajax="false"]</a></li>
<!--
target 속성을 지정해 주시면, 기존의 웹방식처럼,
target 에 지정된 이름의 iframe 이나, 팝업윈도우가 있으면 해당 태그의 페이지가 갱신되고,
없으면 새창이 뜨게 됩니다.
기존 웹방식과 동일한 방식으로 동작합니다.
-->
<li><a href="index.asptarget="foo">Link with target="foo"</a></li>
<!-- ########## 이메일 링크 ########## -->
<li data-role="list-divider">Email links</li>
<li><a href="mailto:jdoe@foo.com">Basic email: mailto:jdoe@foo.com</a></li>
<li><a href="mailto:jdoe@foo.com?cc=bill@bar.com&bcc=mark@abc.com&subject=Happy%20Birthday&body=Best%20wishes!">Mailto with a cc:, bcc:, subject and body pre-filled</a></li>
<!-- ########## 전화번호 링크 ########## -->
<li data-role="list-divider">Phone links</li>
<li><a href="tel:15555555555">Phone: tel:15555555555</a></li>
<!-- ########## 기타링크 ########## -->
<li data-role="list-divider">Other</li>
<!--
일반 웹에서 href="#" 이렇게 링크를 걸면, 화면 상단으로 이동을 하게 되는데요,
jQuery Mobile 에서는 화면이동이 없습니다.
웹에서 <a href="#" onclick="return false">link</a> 와 같은 효과입니다.
-->
<li><a href="#">A href="#" will return false</a></li>
<!--
링크에다가 data-rel="back" 속성을 설정하시면,
href 속성값과는 상관없이, 무조건 현재 페이지에서 뒤로가기로 이동합니다.
-->
<li><a href="index.aspdata-rel="back">뒤로가기 속성 설정 [data-rel="back"]</a></li>
<!--
링크에다가 data-direction="reverse" 속성을 설정하셔도,
href 속성값과는 상관없이, 무조건 현재 페이지에서 뒤로가기로 이동합니다.
하지만 data-rel="back" 과의 차이점은, data-rel="back" 은 뒤로가기 했을때,
단순히 그 페이지로 이동만 하는 것이 아닌, 원래 그 상태를 유지해 줍니다.
이전 페이지의 스크롤 상태 등의 화면 상태를 그대로 복원해 줍니다.
하지만 data-direction="reverse" 는 그냥 단순히 이전 페이지로 이동만 합니다.
이전 화면 스크롤 상태 등을 복원해주지는 않습니다. 그냥 단순히 이전 페이지로의 이동입니다.
-->
<li><a href="index.aspdata-direction="reverse">뒤로가기 속성 설정 [data-direction="reverse"]</a></li>
<!--
<div data-role="page" data-url="/jquery/">
data-role="page" 이 설정된 태그에 data-url="/jquery/" 를 설정하면,
아래의 상대경로 링크가 제대로 동작하게 됩니다.
구체적인 내용은 저도 잘 이해가 안됩니다. ^^;
-->
<li><a href="mobile/" >상대경로 링크</a></li>
</ul>
</div><!-- /content -->
<div data-role="footer">
<h4><a href="/jquery/mobile/data-ajax='falsestyle="text-decoration:none">HOME</a>    page footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
</body>
</html>


해결방법은

1번. 앵커태그에 data-ajax='false' 추가

2번. 일일이 태그에 달기 번거로우면 

jQuery를 모바일이로드되기 전에, 이벤트 처리기를 바인딩해야합니다.

아래와 같이 하면 끝

<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>

<script type="text/javascript">

$(document).bind("mobileinit", function(){

                $.mobile.ajaxLinksEnabled = false;

                $.mobile.ajaxFormsEnabled = false;

                $.mobile.ajaxEnabled = false;

});

</script>

<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script>

주의 할것은 mobileinit 이벤트는 웹앱이 시작되자마자 발생하는 이벤트로 jQuery Mobile 라이브러리가 로딩되자마자 발생한다.

그렇기 때문에 이벤트 핸들러는 jQuery Mobile 라이브러리가 로딩되기 전에 바인딩 되어야 한다. 쉽게 설명하면 mobileinit 핸들러의 위치는 jQuery 라이브러리와 jQuery Mobile 라이브러리 사이에 위치해야한다.