Translate

2014년 8월 29일 금요일

[CSS] Javascript 없이 CSS로 Click(누른상태) 할 때 Image 변경하기





이전부터 홈페이지들을 보면 마우스를 이미지위에 올리거나 누르게되면
이미지를 교체하는 기능이 이제는 기본이 되었다.


그중에 사용하는 방법중에 Javascript 로 다음과 같은 소스를 많이 볼 수 있었다.
(드림위버에서 자동 생성되는 코드라고 하는데 초보 개발자들이 많이들
  copy&paste 사용하곤한다.)

function MM_swapImgRestore() { //v3.0
    var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
    var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
        var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
            if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}

function MM_findObj(n, d) { //v4.01
    var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
        d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
    if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
    for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
    if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
    var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
        if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}





스크립트로 처리하는 방법은 여러가지가 있겠지만
최근 스크립트를 안쓰고 하려다보니 다음과 같은 방법을 생각해냈다.


<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
        }
        /*기본 상태*/
        #btn1 {
            width: 50px;
            height: 50px;
            background-image: url('./images/normal.png');
        }
        /*마우스오버 했을 때 상태*/
        #btn1:hover {
            background-image: url('./images/hover.png');
        }
        /*마우스 눌렀을 때 상태*/
        #btn1:active {
            background-image: url('./images/active.png');
        }
    </style>
</head>
<body>

<div id="btn1"></div>

</body>
</html>






일반적으로 링크에서 많이 사용하는 pseudo class 클래스(링크)가 떠올랐다.
혹시 링크가 아닌 일반 Element 에도 적용이 될까 싶어서 해봤는데 잘 된다!!

보통은 아래와 같이 사용을 하지만 말이다..ㅎ

a:link {
    color: #FF0000;
}
/* visited link */
a:visited {
    color: #00FF00;
}
/* mouse over link */
a:hover {
    color: #FF00FF;
}
/* selected link */
a:active {
    color: #0000FF;
}



하지만 Android 2.x 에서는 정상적으로 동작하지 않아서 결국 걷어내고
스크립트로 처리를 하고 말았다. ㅠ






2014년 8월 28일 목요일

[CSS] Element(Div, Img etc..) 세로 가운데 정렬 시키기







Element 를 가로 가운데 정렬시키는 것은 그리 어렵지 않지만 세로 가운데 정렬같은 경우는
가로에 비해서 쉽지 않기에 여러가지 방법이 있다.

처음에는 자바스크립트로 세로 정렬을 하던걸 스크립트로 처리할 수 없는 상황이 오자
이것저것 시도를 해보면서 아래와 같이 여러가지 방법으로 시도하고 사용했다.

[CSS] Div center 정렬방법
[CSS] Centering Percentage Width/Height Div Elements (크기가 동적인 Div 센터정렬)






하지만 조금더 근사한 방법을 찾아서 다시 포스팅 한다.




포인트는 아래와 같다.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #div1 {
            width: 100%;
            height: 200px;
            border: 1px solid black;
        }
        #div2 {
            width: 100px;
            height: 100px;
            border: 1px solid blue;
            position: relative;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            -webkit-transform: translate(-50%, -50%);
        }
    </style>
</head>
<body>

<div id="div1">
    <div id="div2"></div>
</div>

</body>
</html>





PS.
위의 방법은 일반적인 Desktop Browser 에서 사용하기 힘든부분이 있다.
핵심적인 CSS인 transform 은 CSS3에 나온거다보니 IE9 이상부터 지원이 된다.
링크

하지만 주 타겟이 모바일 이라면 Android 2.x 에서도 지원될 정도로 이미 웻킷 기반에서는
일찍이 지원을 하는 부분이기 때문에 모바일웹을 제작중이라면 강추를 드리고 싶다.




어쩔수 없이 대부분의 PC브라우저에서 지원을 해야 한다면 스크립트로 처리를 하거나
위에 걸린 링크와 같은 작업으로 해야 한다.






2014년 8월 27일 수요일

[KB스타뱅킹] 계좌이체 시 응답코드 CAQ70013 와 함께 오류가 발생한다.







문제

KB스타뱅킹 어플에서 계좌이체 시 응답코드 (CAQ70013) 과 함께 이체가 되지 않는다.
(정보를 다 입력 후 마지막에 공인인증서 암호를 입력했을 때 나타났다.)

일자: 2014년 8월 25일 기준
단말기정보: LG G3 (Android 4.4.2)






KB국민은행에 직접 전화를 걸어서 물어봤다.
공식적인 대답은 아래와 같다.








해결방법

1. KB스타뱅킹 어플을 삭제 후 다시 설치한다. => 링크
2. 앱 다시 설치 시에도 문제가 발생한다면 아래와 같이 어플 다운그레이드를 해야 한다.
  1) http://i.kbstar.com 사이트로 접속
  2) 하단의 '은행서버를 통한 설치'에서 '구)스타뱅킹' 버튼 누른 후 설치
  - 어플을 지우지 말고 하라고 했던 기억이..;;


* 나의 경우에는 1번과 같이 어플 삭제 후 다시 설치하니 정상적으로 이용이 가능했다.









2014년 8월 25일 월요일

[Android] Android 2.x 버전의 Browser에서 iframe 내의 페이지에서 window.open 했을 때 새창이 아니라 팝업이 뜨는경우






증상

OS: Android 2.x
Browser: OEM(default) Browser

iframe 내의 페이지에서 window.open 함수를 사용할 시 새창 또는 탭(tab)이 아니라 popup으로 표시가 된다.

아래의 모습처럼..









문제가 되는 소스는 다음과 같다.


outer.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
        }
        #wrapperDiv {
            width: 90%;
        }
    </style>
</head>
<body>

<br/><br/>
<div id="wrapperDiv">
    <iframe src="./sampleMessages/00/index.html" width="100%" />
</div>



</body>
</html>




index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta name="viewport" content="width=device-width, initial-scale=1,  user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<button type="button" onclick="window.open('http://nate.com/', '_blank');">네이트</button>

</body>
</html>







원인 및 해결방법

원인: Android 2.x 버그로 추측

해결방법
1. iframe 의 width 사이즈가 body의 사이즈와 같아야 한다. (100%)
2. html, body에 margin 사이즈 0 이 설정되어야 한다.


다음의 소스를 확인해 보면 알 수 있다.




outer.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
        }
        #wrapperDiv {
            width: 100%;
        }
    </style>
</head>
<body>

<br/><br/>
<div id="wrapperDiv">
    <iframe src="./sampleMessages/00/index.html"
            width="100%" />
</div>



</body>
</html>


또는 다음과 같이 해도 된다.


<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        html, body {
            margin: 0;
        }
    </style>
</head>
<body>

<br/><br/>
<iframe src="./sampleMessages/00/index.html"
        width="100%" />



</body>
</html>





결론은 iframe의 사이즈가 width="100%" 가 되어야 하며
iframe을 감싸고 있는 다른 Element 의 사이즈 또한 100%가 되어야 한다.

슬프게도 대부분의 사이트에서는 이렇게 간단한 페이지가 별로 없을테니
적용하기가 힘들다.

이번에 작업하는 2개의 페이지중에 1개의 페이지가 너무나도 심플하여
위와같이 해결을 했으나 다른 페이지는 DOM 구조가 복잡하다보니
적용이 어려워 일단 그냥 넘어가고 다른 이슈를 보기로 했다.







[OSX] 프린트 할 시 '프린트 준비 완료' 라는 메시지와 함께 프린트가 되지 않는경우






증상

아래의 캡쳐와 같이 테스트페이지를 프린트 할 시 '일시 정지됨, 최근 사용됨' 표시와
대기열 에서는 '프린트 준비 완료' 메시지와 같이 '재개' 버튼이 활성화 된다.









프린터 구성

1. 윈도우PC 에서 프린터를 연결 후 프린터 드라이버 셋팅 후 프린터를 공유
2. 맥(OSX 10.9.4) 에서 윈도우에서 공유된 프린터를 셋팅

* 증상과 같이 프린트가 되지 않을 때에는 윈도우 공유된 프린터가 다시 잡히지 않는다.








콘솔로그(Launchpad => 기타 => 콘솔)

프린트를 할 시 아래와 같은 로그가 나오며 프린트가 되지 않는다.

2014. 8. 25. 오전 11:43:59.327 cups-exec[3213]: sandbox cache error 3850
2014. 8. 25. 오전 11:43:59.327 cups-exec[3211]: sandbox cache error 3850
2014. 8. 25. 오전 11:43:59.359 cups-exec[3214]: sandbox cache error 3850
2014. 8. 25. 오전 11:44:00.619 Samsung_M267x_287x_Series[3213]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
2014. 8. 25. 오후 12:25:35.406 cups-exec[3374]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:35.409 cups-exec[3375]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:35.409 cups-exec[3373]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:35.796 cups-exec[3372]: sandbox cache error 26: file is encrypted or is not a database
2014. 8. 25. 오후 12:25:36.098 Samsung_M267x_287x_Series[3374]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
2014. 8. 25. 오후 12:25:39.045 cups-exec[3384]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:39.046 cups-exec[3382]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:39.271 cups-exec[3383]: sandbox cache error 1: no such table: main.imports
2014. 8. 25. 오후 12:25:39.361 cups-exec[3385]: sandbox cache error 1: no such table: profiles
2014. 8. 25. 오후 12:25:39.503 Samsung_M267x_287x_Series[3384]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
2014. 8. 25. 오후 12:25:45.416 Samsung_M267x_287x_Series[3392]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
2014. 8. 25. 오후 12:25:48.356 cups-exec[3404]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:48.362 cups-exec[3403]: sandbox cache error 11: database disk image is malformed
2014. 8. 25. 오후 12:25:48.628 Samsung_M267x_287x_Series[3404]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.
2014. 8. 25. 오후 12:25:57.193 cups-exec[3412]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:57.193 cups-exec[3414]: sandbox cache error 3850
2014. 8. 25. 오후 12:25:57.348 cups-exec[3415]: sandbox cache error 1: no such table: main.imports
2014. 8. 25. 오후 12:25:57.438 cups-exec[3413]: sandbox cache error 1: no such table: profiles
2014. 8. 25. 오후 12:25:57.632 Samsung_M267x_287x_Series[3414]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.








지난번에 로그로 인터넷 검색해보니 윈도우쪽에 뭔가 문제가 있었던 걸로 기억한다.
OSX 사용자가 한명 더 있는데 위와같이 안될 때에는 그 분도 안되는 걸로봐서는
내 PC에 문제가 있는게 아니라 공유해준 윈도우 쪽에서 문제가 있다고 의심이 된다.

==================================
추가

프린터 공유한 PC를 재부팅 해보고 내 OSX을 재부팅 해봤는데도
프린트가 되지 않는다.

지난번에도 이렇게 되지 않았을 때 며칠 지나면 정상적으로 됐었는데..
그때에 로그한번 확인해 봐야겠다.
==================================



==================================
추가 - 2014.08.30

프린터 공유한 PC가 꺼져있어서 켰더니 내 OSX을 재부팅 없이 프린트가 잘 됐다.

콘솔로그는 다음과 같다.
2014. 8. 30. 오후 4:01:19.457 cups-exec[18065]: sandbox cache error 3850
2014. 8. 30. 오후 4:01:19.458 cups-exec[18064]: sandbox cache error 3850
2014. 8. 30. 오후 4:01:19.458 cups-exec[18062]: sandbox cache error 11: database disk image is malformed
2014. 8. 30. 오후 4:01:19.920 cups-exec[18063]: sandbox cache error 1: no such table: profiles
2014. 8. 30. 오후 4:01:20.474 Samsung_M267x_287x_Series[18064]: The function `CGContextErase' is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.


뭐,, 지난번에 비해서 로그는 별로 달라진 점이 없다.
다른 부분을 의심해 봐야겠다.
==================================




=============================
14.10.28 추가

결국 리눅스에서 프린터를 설정하고 Samba로 공유를 한 뒤 OSX에서 공유한 프린터를 설정하는 방식으로 변경을 했다.
[OSX][Mevericks] 리눅스에서 Samba 로 공유한 프린터에 연결하기



2014년 8월 24일 일요일

[Android] Android 2.x 의 OEM(기본) Browser 에서 이미지변경이 렌더링 되지 않는경우





문제
Android 2.x 에서 이미지를 교체(변경) 했을 시 처음에는 렌더링이 되지 않고 있다가
스크롤을 내린다거나 해야만 변경된 이미지로 정상적으로 렌더링이 된다.



예제 소스를 만들어 봤는데 예제소스에서는 렌더링이 안되는 증상 재현이 힘들다.
(만들던 프로그램은 DOM 구조도 복잡하고 Event 가 여러 Element 에 사용되고
Event Bubble 까지 처리하기 때문에 그렇게 복잡한 예제를 만들기가 귀찮다;;)

아래의 소스를 Android 2.x 에서 돌릴 시 정상적으로 잘 된다.
해결 방법만 확인해 보면 될것 같다.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" />
    <script src="http://code.jquery.com/jquery-2.1.1.min.js" ></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $('.post').bind('touchend', function(post) {
                changeImage($(post).children('.wrapperImg').children('img'));
            });
        });
        function changeImage(image) {
            var selectedImage = $(image).children('.wrapperImg').children('img');
            if (selectedImage.attr('src').indexOf('normal') > -1) {
                selectedImage.attr('src', 'select.png');
            } else {
                selectedImage.attr('src', 'normal.png');
            }
            // Android 2.x 의 경우 화면이 바뀌거나 DOM 구조가 변경되어야 변경된 이미지가 렌더링된다.
            if (navigator.userAgent.match(/Android 2/)) {
                $('body').append('<div style="display:none;"></div>');
            }
        }
    </script>
    <style type="text/css">
        #wrapperDiv {
            margin: 0;
            padding: 5px;
            border: 1px solid blue;
        }
        .post {
            width: 100%;
            height: 25px;
        }
        .title {
            margin-left: 30px;
        }
        .wrapperImg {
            float: left;
            right: 15px;
        }
        .checkBtn {
            width: 20px;
            height: 20px;
        }
        .division {
            width: 100%;
            height: 1px;
            background-color: #999999;
        }
    </style>
</head>
<body>

<div id="wrapperDiv">
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물1</div>
    </div>
    <div class="division"></div>
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물2</div>
    </div>
    <div class="division"></div>
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물3</div>
    </div>
    <div class="division"></div>
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물4</div>
    </div>
    <div class="division"></div>
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물5</div>
    </div>
    <div class="division"></div>
    <div class="post" ontouchend="changeImage(this);">
        <div class="wrapperImg"><img src="normal.png" class="checkBtn"/></div>
        <div class="title">게시물6</div>
    </div>
</div>

</body>
</html>






[Github] Github로 소스를 올린 링크가 404로 보여지는 증상






블로그 댓글중에 소스링크가 깨졌다는 댓글이 올라왔다. 링크



소스를 올린 github 링크를 눌러서 들어가보니 아래와 같은 화면이 나왔다.





어라?? 갑자기 왜??


로그인을 해보니 아까와는 다르게 같은 URL에서 소스가 보여졌다.
하지만 상단에 아래와 같이 Github의 robot이 나를 인간이 아닌 것으로 의심이 된다고 한다.

One of our mostly harmless robots seems to think you are not a human.

Because of that, it's hidden your profile from the public. If you really are human, please contact support to have your profile reinstated.
We promise we won't require DNA proof of your humanity.






일단 다음과 같은 조치를 취했다.
프로필 계정에 사진을 등록하고 이름, 이메일 등등 계정 정보를 업데이트 했다.

그리고 contact support 페이지에 들어가서 왜 이렇게 되었는지 알 수 없다고 메시지를 보냈다.

얼른 계정이 정상으로 돌아와야 하는데..ㅠ


========================================
추가

요청을 보낸지 한시간정도 밖에 되지 않았는데 미안하다고 바로 답변이 왔다.
이놈들.. 일요일이고 뭐고 없는건가??
아니면 그쪽은 월요일 이려나..

암튼 링크는 로그인하지 않더라도 이제는 정상적으로 보이게 되었다.

========================================






2014년 8월 22일 금요일

[VirtualBox] USB 연결 시 “USB device in use by someone else” 라는 메시지가 뜨면서 연결이 되지 않는경우






문제

VirtualBox 에서 USB에 LG G3를 끼우고 USB인식하도록 다음과 같이 클릭을 하는경우..



아래와 같이 경고메시지가 나오면서 USB가 연결되지 않는다.


===============================================
Failed to attach the USB device LG Electronics Inc. LGE Android Phone [0232] to the virtual machine winxp_32bit.

USB device 'LG Electronics Inc. LGE Android Phone' with UUID {c5c290df-b238-48ca-8cb4-540fdebe2959} is in use by someone else.

Result Code: NS_ERROR_FAILURE (0x80004005)
Component: HostUSBDevice
Interface: IHostUSBDevice {173b4b44-d268-4334-a00d-b6521c9a740a}
Callee: IConsole {8ab7c520-2442-4b66-8d74-4ff1e195d2b6}
===============================================






해결방법

1. Settings 에서 다음과 같이 설정을 해줍니다.


2. 아래와 같이 등록이 되면 OK 버튼을 누릅니다.

3. 다시 USB설정을 해 줍니다.






2014년 8월 18일 월요일

[Android][Javascript] Android 2.x 에서 touchmove Event 걸린 Element 를 화면 움직이는 중에 Stop 되는 문제





대상: Android 2.x


증상
touchmove Event 지정한 Element 를 손가락으로 움직일 시
화면이 한번 움직이며 touchmove 가 수행이 된 후
더 이상 화면이 움직이지 않으며 touchmove 가 작동하지 않는다.




다음과 같이 증상을 해결했다.

$('Element').bind('touchmove', function(event){
    event.preventDefault();

    // Logic

    return false;
});

// OR

document.getElementById('Element').addEventListener('touchmove', function(event){
    event.preventDefault();

    // Logic

    return false;
}, false);



참고: 링크





2014년 8월 6일 수요일

[Android] Web 에서 Application 설치여부 체크 및 Custom URL로 이동시키기




Android Chrome version 25 이상부터는 Chrome의 변경된 정책(Link)으로 인해
기존에 사용하던 아래와 같은 방법(iframe 형식)을 사용할 수 없게 되었다.

<script>
 function checkApplicationInstall() {
  document.checkframe.location = "myapp://check_install";
  setTimeout("checkApplicationInstall_callback()", 1000);
 }
 
 function checkApplicationInstall_callback() {
  try {
   var s = document.checkframe.document.body.innerHTML;
   // 어플리케이션 설치되어있음
  } catch (e) {
   // 어플리케이션 설치 안 되어있음
  }
 }
</script>


<input type="button" value="check app install" onclick="checkApplicationInstall()"/><br/>
<iframe id="checkframe" name="checkframe" src="check.html" width="1" height="1"></iframe>



안드로이드에서 사용하라는 아래의 방법은 다음과 같은 문제가 있다.
<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end"> Take a QR code </a>
Application 이 설치되어 있지 않은경우 무조건 Google Play Store 로 이동하게 된다.
1004lucifer
위와 같은 문제로 인해 아래와 같은 불편함이 따른다.
1004lucifer
1. Google Play Store 에 올라와 있지 않고 다른 스토어에 있는 Application 을 다운로드 안내 할 수 없다. (Custom URL)
2. Store 에 올리지 않은 프로그램을 APK 형식으로 배포를 할 수 없다.
   (어쩔 수 없이 APK로 배포를 해야 하는 경우가 있을 수 있다.)








1004lucifer
며칠의 고난끝에 다음과 같은 방법을 생각해냈다.

index.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" />
    <title></title>
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script type="text/javascript">

        var schemeUrl = 'kakaolink://';
        var redirectUrl = 'http://www.kakao.com/';

        window.closeWindow = (function(){
            var isWindowRef = null;
            setInterval(function() {
                // 새로열린 창이 닫혔을 때 다시 버튼 클릭 시 동작이 실행이 되어야 하므로 해당 객체를 삭제
                isWindowRef = (isWindowRef && isWindowRef.window) ? isWindowRef : null;
            }, 1000);

            return function (windowRef, time) {
                //  새로열린 Window에서 백버튼 누를 시 해당 함수가 계속 호출되는 무한루프 방지
                if (isWindowRef == null) {
                    isWindowRef = windowRef;

                    setTimeout(function() {
                        try {
                            // Custom Scheme 이 실행되지 않고 잘못된 페이지가 노출된 상태에서
                            // 아래의 코드 실행 시 Security Error 발생
                            windowRef.location == 'undefind';

                            // Custom Scheme 이 실행되었다면 앱 종료 후 해당 tab 을 닫는다.
                            windowRef.close();

                        } catch (e) {
                            windowRef.location.href = redirectUrl;
                        }
                    }, time);
                    return true;
                }
            }
        })();

        function runApp() {

//            Check Chrome for Android Version is V25
//            https://developer.chrome.com/multidevice/android/intents - Android Chrome Version
//            http://en.wikipedia.org/wiki/Google_Chrome_for_Android - Chrome WebKit Version
            if (parseFloat(navigator.userAgent.match(/WebKit\/[^\ ]*/)[0].toLowerCase().substr(7)) > 537.22){
                var openWindow = window.open('./openWindow.html#' + schemeUrl);

            } else {
                $('<iframe></iframe>', {
                    src: schemeUrl,
                    width: 0,
                    height: 0,
                    id: 'checkframe'
                }).css('border', '0').appendTo('body');

                setTimeout(function() {
                    if($("#checkframe").contents().find("body").html() == undefined){
                        window.location.href = redirectUrl;
                    }
                }, 1000);
            }
        }
    </script>
</head>
<body>

<a href="javascript:runApp();">앱 실행하기</a>

</body>
</html>


openWindow.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width" />
    <title></title>
    <script type="text/javascript">
        var valid = parent.window.opener.closeWindow(this, 50);
        if (valid) {
            window.location.href = document.location.href.split('#')[1];
        }
    </script>
</head>
<body>
</body>
</html>



다른 방법이나 의견 환영합니다. ^^