반응형

요즘 모바일웹이 대세다.
어느 하나 모바일웹이 따로 없는 사이트는 찾아 보기 힘들며, 심지어는 모바일전용으로 런칭 되는 사이트들도 많다. 이제 나도 모바일웹을 시작해야지 라고 생각고 html...을 시작으로 코드를 마치고 모바일에서 확인하면 어라, 이게 아닌데...라는 질문을 스스로 하게 될것이다.

아래와 같은 코드로 HTML을 작성해서 모바일로 확인해보자.

1
어라이게아닌데

모바일 사파리 일반 페이지 렌더링 결과

위와같이 나오게 되기 쉽상이다, 이는 뷰포트에 대한 이해가 필요하다.

1.뷰 포트(view-port)

모바일의 브라우져는 보여지는 픽셀이 유동적이다. PC에서는 PC의 해상도에 맞춰서 내용이 늘어나면 스크롤바가 생기지만 모바일 브라우져는 그렇지 않다, 이유는 간단하다. 모바일을 꺼내들고 다음이나네이버 PC버전에 접속해보자.


보시는 바와 같이 우리의 똑똑한 스마트폰은 많은 양의 정보를 보여주기위해 해상도를 축소시켜서 한페이지에 보여준다. 그리고 손가락으로 슥슥 밀었을때 나타나는 스크롤바는 우리가 PC에서 접속해서 나타나는 스크롤바가 아닌 '보이는 영역'을 옮겨주는 스크롤바이다. 즉, 더 보여줄 내용이 있느냐, 없느냐에 따라서 뷰포트를 옮기는 거지, PC에서 옮기는 그런 스크롤바를 옮기는것이 아니다. 즉 div의 postion:fixed는 최초 고정자리에서 더이상 작동하지 않는다.


내용 정정 2012-05-09

버전업으로 인하여 iOS및 안드로이드에서도 position:fixed는 최초 고정자리에 고정됩니다.


메타태그 추가시 뷰포인트 변화

뷰 포트를 조정해서 1:1비율로 보여줄수 있는 메타태그를 삽입하면 위와 같이 나오게 된다.

메타태그는 기본적으로 <head>와 </head>사이에 넣는다.

1
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, width=device-width, height=device-height">

해당 항목값을 변경해서 다르게 보여줄 수 있다, user-scalable가 no일 경우 두손가락으로 확대/축소를 불가능하게 할 수 있다. (당연히 반대는 yes) 모든 스케일은 1.0으로 맞추고 width값을 device-width로 할경우에 모바일 브라우져의 너비값으로 자동으로 인식된다. (height=device-height는 2번에서 설명)


마찬가지로 메타태그로 홈화면에 추가시 아이콘과 홈화면에서 접속시 로딩화면 이미지도 지정해 줄 수 있다.
PNG파일 사용하면 투명은 검은색으로 처리되고, opacity까지 정확하게 먹는다.
57*57의 아이콘을 권장하나 114px x 114px정도 만들어줘야 아이폰4에서도 선명하게 나온다. (설명은 4번 참조)

1
2
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon.png">

반사광은 자동으로 입혀지며(첫번째 줄) 반사광을 원하지 않을경우 2번째줄의 코드로 대체한다.


또 아래 코드를 사용하면 위 진짜 앱처럼 사파리툴바들이 없어지고, 로딩화면을 사용할 수 있다. 사파리에서 접속과 홈화면에서 접속 구분은 에이전트 값으로 구분하면 되겠다. (설명은 2번 참조)

1
2
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-startup-image" href="startup.png">

마찬가지로 startup.png를 만들어 경로를 설정해주면 처음 구동시 로딩화면이 나온다.
startup.png는 320px x 460px이 정확해야 하며 사이즈가 맞지 않으면 저장되지 않는다.

웹 앱 (webapp)모드 에서는...

  • 앵커태그 사용시 사파리로 점프한다. (온클릭이벤트로 전환)
  • 홈화면에서 접속시 항상 새로고침 한다.
  • 멀티태스킹을 지원하지 않는다 (마찬가지로 새로고침되며 시작됨)
1
<a href="#" onclick="location.href='http://ojtiger.com/'">오중호랑이의 비밀로긔</a>

2. 주소표시줄 숨기기 (클라이언트 코드 사용)


열심히 만들다 보면 다른 모바일사이트와 또 다른게 생긴다, 로딩이 완료되면 주소표시줄이 숨어버리는것인데 이는 스크롤을 1px내려서 주소표시줄을 숨기는 원리이다. 아무 사이트나 들어가서 로딩이 완료 되기전에 스크롤을 미리 내려 놓으면 주소표시줄이 올라가는 것과 마찬가지이다.

이것은 자바스크립트로 해결 할 수 있다.

1
2
3
window.addEventListener('load', function(){
    setTimeout(scrollTo, 0, 0, 1);
}, false);

위 자바스크립트로 구현이 가능하나, 이는 IE에서 스크립트 오류를 불러낸다. 


위와 같은 유저 에이젼트값을 이용해서 아이폰일 경우에만 처리하도록 하면 된다.

1
2
3
4
5
6
7
8
9
if (navigator.userAgent.indexOf('iPhone') != -1) {
    addEventListener("load", function() {
    setTimeout(hideURLbar, 0);
    }, false);
}
 
function hideURLbar() {
    window.scrollTo(0, 1);
}
1
alert(navigator.userAgent);

안드로이드일 경우에는 위와 같이 직접 navigator.userAgent 값을 찍어보면 알겠지만, 

1
2
3
4
5
6
7
8
9
if (navigator.userAgent.indexOf('Linux') != -1) {
    addEventListener("load", function() {
    setTimeout(hideURLbar, 0);
    }, false);
}
 
function hideURLbar() {
    window.scrollTo(0, 1);
}

Linux라고 처리해 주면 된다, 리눅스에는 IE가 없고, 안드로이드의 브라우져의 navigator.userAgent는 Linux를 포함한다. 세로 내용이 짧아서 주소표시줄이 제대로 올라가지 않으면 다시 1번의 메타태그에 height에 device-height를 추가해준다.

이를 응용하면, 모바일 접속시 페이지 이동(m.뭐 이딴거)같은, 자바스크립트 함수를 호출할수 있다.

1
2
3
4
5
6
7
var mobileKeyWords = new Array('iPhone', 'iPod', 'BlackBerry', 'Android', 'Windows CE', 'LG', 'MOT', 'SAMSUNG', 'SonyEricsson');
    for (var word in mobileKeyWords){
        if (navigator.userAgent.match(mobileKeyWords[word]) != null){
            location.href = "#";
            break;
            }
    }

이 또한 유저에이전트값을 활용하는 방법인데, 모바일이라는 한정이 있으므로, 유저에이전트 값에서 각 제조사를 찾아서 이동시킨다. 

당연컨데 위 코드중 4번째줄 코드를 자신이 원하는 코드로 바꿔주면 모바일에서만 실행되는 코드를 사용 할 수 있다.

3. 서버코드(PHP) 사용

모바일에서 접속시에만 실행을 원하는 PHP코드가 있다면, PHP의 유저에이전트를 이용한다. 원리는 위 자바스크립트의 유저에이전트와 비슷하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--?
$browser = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone");
if ($browser !== false){
    $browser = 'iphone';
}
 
if($browser == 'iphone'){
    $texttype="email";
}else{
    $texttype="text";
}
?-->
 
<input type="<? echo $texttype ?>">

PHP코드를 이용해서 아이폰일 경우 email 키보드를 꺼낼수 있게 처리할 수 있다.
이는 어이없게도 파이어폭스4 이상에서 type이 email일 경우 강제로 email형식을 지정하기에 처리해줘야 한다.

HTML5 기초 - 5 : input 유형과 속성

위 링크를 가보면 HTML5의 요소인듯하다. (그래도 강제성이 좀 어이없음)

4. 가상키보드 (아이폰)

아이폰은 input type의 속성에 맞춰서 가상키보드를 꺼낼수 있는데 속성값에 따라서 밑에서 튀 나오는 키보드가 달라진다

1
2
3
4
<input type="email" value="email">
<input type="number" value="number">
<input type="url" value="url">
<input type="tel" value="tel">

input type="email"input type="number"input type="url"input type="tel"

순서대로 email, number, url, tel..


tel의 경우가 굉장히 편리한 경우이긴 하지만 HTML5와 파이어폭스4이상에 따르면 강제성이 부여 되므로, 두가지 속성을 입력받아야 한다면 반드시 클라이언트별로 분리해 놓는것이 좋겠다.

안드로이드일 경우에는 원래(세상엔 원래라는게 없지만) 편리한 키보드를 설치해서 사용하면 된다.

5.고DPI 디스플레이에서 고화질 이미지 보여주기

아이폰4가 DPI 300이 넘는다는건 애플에서 그렇게나 광고 해댔으니 누구나 안다. 하지만,

1번에서도 설명되어있지만, 아이폰4와 아이폰3GS그 이전단계는 해상도가 차이는 나지만 뷰포트는 width 320px로 같다는것도 누구나 안다. 그렇기 때문에 같은 이미지를 출력해도 3GS에서는 가로기준 이미지 1px당 디스플레이 1px로 일치하지만 아이폰4에서는 이미지에서 1px당 디스플레이에서는 2px이 보여지게 되므로 흐릿한 이미지로 보여지게 된다.

이를 해결하기 위해선 더 높은 해상도의 이미지를 줄여서 보여주면 된다.

상단 이미지를 클릭해서 직접 비교해보세요!

왼쪽호랑이는 260px × 200px의 이지를 width, height값을 조정해서 130px x 100px로 축소시킨것이구 오른쪽 호랑이는 원래(세상에 원래라는건 없지만) 130px x 100px의 호랑이이다.

고화질 이미지를 보여주는것도 좋지만, 접속하는 사람이 3G로 접속할경우, 혹은 통신상태가 불안정할 경우 상당히 부하가 많이 걸린다는 점을 인지해서 꼭 필요한부분에 사용하면 된다.

6. 모바일 브라우저 회전 인식

자바스크립트의 오리엔테이션체인지를 이용하면 되는데 아이폰은 확실히 지원을 하고 안드로이드는 지원하는것이 있는지 모르겠으나, 모토로이의 경우에는 지원하지 않는다.

이럴 경우에는 window.resize이벤트를 합쳐서 안드로이드에도 함께 적용해준다.



slope변수를 직접 찍어봐두 알겠지만, 정상일때0, 회전일때90, 혹은 반대방향일 경우-90이다.

(이는 아이폰과 안드로이드가 방향이다르다.. 사이가 안좋은가 보군..)

1
2
3
4
5
6
7
8
9
10
11
var slope = 0;
var supportsOrientationChange = "onorientationchange" in window,
orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";
    window.addEventListener(orientationEvent, function() {
        if (slope!=window.orientation){
            slope = window.orientation;
                if(slope == 90 || slope == -90) {
                    location.href('#');
                }
        }
}, false);

2번과 마찬가지로 원하는 코드를 넣을수도 있고 위와 같이 페이지이동을 시킬 수 도 있다.

7. 라운드 div CSS

웹킷계열(모바일사파리, 안드로이드브라우져 등)과 모질라 파이어폭스에서 지원하는 css를 사용하면 손쉽게 라운드 div를 만들 수 있다. 이는 IE에서는 라운드하지 않은 div가 생성되는데 IE는 따로 처리를 해주던가 포기하면 쉽다.

CSS를 정확하게 지원하며 아래의 두줄을 추가하면, 웹킷계열과 모질라계열에서 라운드박스를 얻을 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
.loading_div {
    position:absolute;
    top: 50%;
    left: 50%;
    width: 140px;
    height: 180px;
    color:#fff;
    border: 1px solid #ccc;
    background: #162344;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border: 1px solid #b2b7c2;
    opacity:0.9;
    }

스타일 시트에 위 코드를 추가하고 아래와 같이 div를 생성하면 스크린샷같은 라운드박스를 얻을 수 있다.

1
2
3
4
<div class="loading_div">
    <img src="http://i1.daumcdn.net/cfs.tistory/static/images/xBoxReplace_250.png" width="250" height="250" alt="오중호랑이">
    라운드박스'-'
</div>

스타일에서-webkit-border-radius: 5px; 와 -moz-border-radius: 5px;에 따라서 라운딩 정도의 차이가 난다.
이 소스를 잘만 활용하면 jquery나 AJAX에서 쓰이는 '더보기'같은 바(bar)는 이미지 하나 없이 만들 수 있다.


배경색과 테두리색 radius를 조절 잘하면 분명 이미지 없이도 멋진 버튼을 만들 수 있을꺼라 생각한다!

그리고 CSS3를 지원하기 추가적인 이미지 수정없이 필터를 줄 수 있다.  이방법은 CSS3로 검색하면 더 자세히 나올꺼라 생각하고 여기서는, 반사효과에 대해서만 살짝 알아보자.

CSS3를 지원하기에 사용가능한 이미지 반사 그라데이션 효과도 있다. 아이폰은 완벽히 지원하나 안드로이드(일단은 모토로이)의 경우에는 반사 길이 및 투명효과를 제대로 지원하지 않기에 안드로이드에 대한 처리를 따로해줘야 한다.

간단히 아래 한줄로 class를 만들고 img에 씌어주면 된다.

1
2
3
4
.gra{
-webkit-box-reflect:below 0 -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(rgba(255,255,255,0.5)));
}
<img src="http://i1.daumcdn.net/cfs.tistory/static/images/xBoxReplace_250.png" class="gra" alt="#" width="250" height="250">

8. 모바일 사파리 디버깅 모드

설정 > Safari > 개발자용 > 콘솔 디버그를 켜주면 주소표시줄하단에 디버깅 모드가 자동으로 나타난다. (일반적으로 나타나지 않는 항목이기에 여러오류에 대해서 치명적이지 않다면 포기하면 쉽다.)

9. 마치며

이상 근 두달간 작업하면서 "아.. 미리 알고 있었더라면"의 결정체 였다, 모바일사파리 전용 CSS나 더 많은 여러 방법들은 안드로이드와 아이폰 모두에게 적합한 방법을 제시해주지는 못해서 잘 쓰이지 않는것들은 제외시켰다. 이상으로 많은 도움이 되길 빈다.


출처: http://ojtiger.com/146

반응형
,