본문 바로가기

개발/App Developer

아이폰/아이팟 터치용 웹 애플리케이션 개발 팁 12개

아이폰/아이팟 터치용 웹 애플리케이션 개발 팁 12개

Stoyan Stefanov씨는 아이폰/아이팟 터치에서 제공하는 사파리 브라우저(이하 모바일 사파리)용 웹페이지를 구축할 때 알아두면 유용한 팁 12가지를 작성했습니다. 아시다시피 모바일 사파리는 데스크탑용 브라우저와 견주어도 손색없을 정도의 풀브라우징을 지원하며, 작은 화면에서 효과적으로 컨텐츠를 조작 및 조회할 수 있도록 추가적인 특수한 API를 제공하고 있습니다. 지금부터 소개할 12가지 팁과 트릭은 기존의 사이트를 모바일 사파리에 최적화하거나, 새롭게 구축할 때 유용하게 사용할 수 있을 것입니다.

1. 관련 문서와 아이폰 시뮬레이터

Peter-Paul Koch씨는 모바일 사파리를 가지고 연구하기 시작했을 무렵에는 그 어디에도 관련 개발 문서를 찾을수 없었다고 불평했습니다. 애플은 한참이 지나서야 모바일 사파리 브라우저의 명세인 iPhone-specific web development information 문서를 공개했습니다.

모바일 사파리용 웹사이트를 만들기 위해서 아이폰이나 아이팟 터치를 꼭 가지고 있어야 하는 것은 아닙니다. 아이폰 SDK(맥 버전만 제공됨)에서 제공하는 시뮬레이터로도 테스트 할 수 있으니까요. 이것을 설치하기 위해서는 애플측에 아이폰 개발자로 등록절차를 거친 후 SDK를 다운로드해야 합니다. 설치에 성공했다면 아래의 경로에서 아이폰 시뮬레이터를 찾을 수 있습니다.
/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications

2. 작은 화면용 CSS

PC 또는 맥과 아이폰의 분명한 차이점은 아이폰이 훨씬 작은 화면을 가지고 있다는 점입니다. 만약 이미 데스크탑 브라우저에서 잘 작동하는 웹사이트가 있다면 모바일 사파리로의 가장 간단한 최적화 방법은 아래와 같은 전용 스타일시트를 추가하는 것입니다.
<!--[if !IE]>-->
<link  
   rel="stylesheet"  
   href="small-screen.css"  
   type="text/css"  
   media="only screen and (max-device-width: 480px)"  
/>
<!--<![endif]-->

<link> 요소는 최대 너비가 480픽셀인 기기를 타깃으로 지정한 media query를 사용하여 스타일시트를 로드합니다. 이 크기는 아이폰을 가로로 보았을 때의 크기입니다. IE 조건부 코멘트는 IE 버전 5.5 또는 이하 버전이 여기에 해당하며 이 브라우저들은 media query를 지원하지 않기 때문에 우회하도록 하기 위한 것입니다. 몇가지 예제를 살펴봅시다.

예제 1에는 두가지 색상을 가진 박스가 작성되어 있습니다. 하나는 빨간색 박스이고 다른하나는 파란색 박스입니다. common.css에는 모든 브라우저를 위한 파란색 박스 스타일이 포함되어 있습니다. small-screen.css는 모바일 사파리에만 적용되는 빨간색 박스 스타일이 포함되어 있습니다. 예제를 아이폰에서 실행하면 빨간색 박스를 볼 수 있고 데스크탑에서는 파란색 박스를 볼 수 있을 것입니다.

만약 하나의 스타일시트만 사용하고 싶다면, 아래와 같이 @media 블럭을 사용하여 아이폰만을 위한 스타일을 추가 할 수 있습니다.
@media only screen and (max-device-width: 480px) {
  #test-block { 
    background: red;
  }
}

예제 2에서는 인라인 스타일 예제를 보여주고 있습니다. onestyleforall.css 스타일시트에서 @media 블럭 안에 박스의 배경을 빨간색으로 지정하는 코드를 발견할 수 있습니다.

3. 뷰포트 <meta> 요소

모바일 사파리는 기본으로 큰 화면을 가진 데스크탑 브라우저 처럼 페이지를 렌더링 합니다. 이를테면 너비가 980픽셀인 페이지를 작은 화면에 맞추기 위해서 컨텐츠의 스케일을 줄이고 있는 것입니다. 결과적으로 사용자에게는 아주 작고 읽기 어려운 문자들로 가득찬 페이지를 제공하게 되며 관심있는 부분을 보기 위해 확대해야 합니다. 웹페이지 자체에는 문제가 없어 보이지만 당신이 웹 애플리케이션을 설계하는 입장에서는 이러한 일을 받아들이기가 쉽지 않을 것입니다.

다행히도 이것은 아래와 같이 <meta> 요소에 viewport 속성을 사용하여 바로 잡을 수 있습니다.
<meta name="viewport" content="width=device-width" />

이는 너비가 980픽셀을 축소하여 그려지는 대신에 아이폰의 가로 크기를 사용할 수 있도록 합니다. 다음 두 예제를 통하여 직접 비교할 수 있습니다.

1. 예제 3에서는 <meta> 요소에 viewport 속성을 사용하지 않은 기본 단락입니다. 여기에 사용된 문자는 거의 보이지 않습니다.
2. 예제 4에서는 <meta> 요소에 viewport 속성을 포함하고 있습니다. 기기의 가로 크기는 320픽셀로 문자를 보기가 더욱 편해졌습니다.


또 다른 방법으로는 원하는 값으로 화면이 축소되도록 기기의 가로 크기를 device-width에 지정하는 것입니다. 예를 들어, 당신의 블로그가 800 x 600픽셀 화면에 맞는 가로 750픽셀 레이아웃으로 고정되어있다고 가정해 봅시다. 예제 5에서는 부가적인 빈공간을 없애기 위해, 화면영역 <meta>요소를 사용하여 가로 크기를 780픽셀로 지정하였습니다.
<meta name="viewport" content="width=780" />

예제 6에서는 이 <meta> 요소에 viewport 속성을 가진 고정 레이아웃을 볼 수 있습니다.

<meta> 요소의 viewport 속성 내용은 여러개의 콤마로 구분하여 기본 스케일 값, 줌 레벨, 스케일링 가능 여부 등을 기입할 수 있습니다. 일반적인 값들은 다음과 같습니다.
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />

모바일 사파리의 가로는 기기의 최대 가로 크기로 지정되었고 줌 레벨을 1로 지정하여 사용자가 컨텐츠를 확대/축소하는 것을 방지하고 있습니다. 마치 모바일 사파리에 최적화된 웹사이트처럼 보이게 할 수 있는 것이죠.

4. 기울기(Orientation) 변화

당신의 웹 페이지 또는 애플리케이션들은 아이폰의 기울기에 따라 세로형과 가로형 이 두가지 방향으로 모드를 전환해 가며 볼 수 있습니다. 모바일 사파리에서는 자바스크립트를 사용하여 window.orientation 프로퍼티에 접근 할 수 있으며 아래와 같은 값을 가지고 있습니다.

  • 0 : 일반적인 세로 화면(홈 버튼이 아래에 있음)
  • -90 : 시계 방향으로 회전된 가로 화면(홈 버튼이 좌측에 있음)
  • 90 : 시계 반대 방향으로 회전된 가로 화면(홈 버튼이 우측에 있음)
  • 180 : 180도 뒤집힌 화면(홈 버튼이 위에 있음)

사용자가 기기를 회전할 때 이벤트를 발생시키기 위해서 orientationchange를 사용할 수 있습니다. 다음은 가로/세로 방향이 변할때마다 alert을 실행하는 예제입니다.
window.onorientationchange = function() {
  alert(window.orientation);
}

예제 7에서는 위 코드가 어떻게 작동하는지 볼 수 있습니다. alert이 실행되기 위해서는 아이폰을 회전시켜야 합니다. 아이폰 시뮬레이터에서는 하드웨어 메뉴에서 기기를 회전하는 메뉴를 찾을 수 있습니다.



5. 스타일시트의 기울기 명세

기울기에 대하여 조금 더 알아봅시다. 때때로 방향에 따라서 컨텐츠가 가진 스타일을 별도로 지정할 필요가 있을 지도 모릅니다. 이를 위해서는 아래와 같은 세가지 간단한 단계가 필요합니다.

1. 마크업에서 <body> 요소에 클래스를 추가합니다.(예: portrait와 landscape)
2. 스타일시트에 body.portraitbody.landscape에 관련된 서로 다른 스타일을 지정합니다.
3. 자바스크립트를 사용하여 회전이 발생할때마다 <body> 요소의 클래스 값을 변경합니다.

첫번째 단계는 아래처럼 기본 클래스를 추가하는 것입니다.
<body class="portrait">

그리고 스타일을 추가 합니다.
body.portrait p {
   color: red;
}

body.landscape p {
   color: blue;
}

끝으로 다음과 같은 자바스크립트 코드들이 필요합니다.

1. 최초 클래스 이름을 정의하기 위한 'load' 이벤트 리스너 추가
2. 아이폰의 회전을 감지하기 위한 'orientationchange' 이벤트 리스너
3. 'orientationchange' 이벤트가 발생할때마다 클래스명을 바꿔주는 함수

아래 코드는 위 이벤트 리스너들 할당한 것입니다.
window.addEventListener('load', setOrientation, false);
window.addEventListener('orientationchange', setOrientation, false);

다음은 <body> 요소에 클래스명을 변경하기 위한 setOrientation 함수입니다.
function setOrientation() {
  var orient = Math.abs(window.orientation) === 90 ? 'landscape' : 'portrait';
  var cl = document.body.className;
  cl = cl.replace(/portrait|landscape/, orient);
  document.body.className = cl;
}

예제 8은 방향에 따라 지정된 스타일이 보여지고 있습니다.



6. 툴바 감추기

최초 모파일 사파리에 페이지가 로드되기 시작하면 URL 툴바가 보이고 페이지를 아래로 스크롤하면 URL 툴바는 사라지는 것을 알 수 있습니다.



만약 모바일 사파리에 최적화된 웹 애플리케이션을 만들고 싶다면 페이지 로드가 완료 된 후 곧장 툴바를 없애고 싶을 것입니다. 이 문제를 해결하기 위해서는 window.scrollTo메서드를 사용하여 1픽셀 아래로 페이지를 스크롤하여 해결할 수 있습니다.
window.addEventListener('load', function(){
  setTimeout(scrollTo, 0, 0, 1);
}, false);

예제 9는 아래처럼 보이게 됩니다.



페이지가 너무 짧아서 스크롤 할 내용이 없다면 어떻게 해야죠? 이럴땐 <meta>요소를 추가하세요. viewport 속성에 높이 값을 지정하여 페이지가 스크롤 될 수 있게 합니다.
<meta name="viewport" content="height=device-height,width=device-width" />

7. 둥근 모서리들

특정한 박스를 둥글게 만들어야 한다면 데스크탑용 브라우저에서 작업했던 방식으로 할 수도 있습니다. 하지만 단지 사파리 브라우저만을 위한 것이라면 -webkit-border-radius CSS속성을 사용할 수 있고 비슷한 방법으로 파이어폭스에서도 -moz-border-radius를 사용할 수 있습니다. 파이어폭스나 사파리에 border-radius CSS 속성을 사용하고 IE나 오페라일 때에는 보통 사각형으로 보이게 할 수도 있겠습니다.
.box {
   -webkit-border-radius: 5px;
   -moz-border-radius: 5px;
   background: #ddd;
   border: 1px solid #aaa;
}


예제 10번에서는 이 CSS속성들을 이용하여 <div>요소의 가장자리를 둥글게 만들었습니다.




8. 터치 이벤트

아이폰은 마우스가 아닌 손가락으로 제어합니다. 터치하고 탭하기 위해 여러개 손가락을 사용할 수도 있습니다. 아이폰에서는 마우스 이벤트 대신에 다음과 같은 터치 이벤트를 사용할 수 있습니다.

  • touchstart
  • touchend
  • touchmove
  • touchcancel (시스템이 터치한 것을 취소하는 경우)

위와 같은 이벤트를 사용할 때 리스너는 event 객체를 전달 받습니다. event 객체는 다음과 같은 중요한 프로퍼티를 가지고 있습니다.

  • touches : 복수로 화면에 터치되는 각 손가락들에 대한 터치 이벤트 모음들. 이 객체들은 페이지에 터치되는 좌표들의 값을 가지고 있습니다.
  • targetTouches : 터치할 때 발생합니다. 그러나 전체 페이지가 아닌 타깃 요소에만 반응합니다.

다음은 터치를 이용한 드래그와 드랍에 대한 간다한 예제입니다. 빈 페이지에 놓여진 박스에 손가락을 올려놓고 드래그 되도록 할 것입니다. 다음 코드는 touchmove 이벤트를 등록하여 손가락으로 움직일 때마다 박스의 포지션을 업데이트 합니다.
 window.addEventListener('load', function() {
 
  var b = document.getElementById('box'),
      xbox = b.offsetWidth  / 2, // half the box width
      ybox = b.offsetHeight / 2, // half the box height
      bstyle = b.style; // cached access to the style object
 
  b.addEventListener('touchmove', function(event) {
    event.preventDefault(); // the default behaviour is scrolling
    bstyle.left =  event.targetTouches[0].pageX - xbox + 'px';
    bstyle.top  =  event.targetTouches[0].pageY - ybox + 'px';
  }, false);
     
}, false);

touchmove 이벤트 리스너는 최초 손가락 움직임에는 반응하지 않습니다. 이것은 모바일 사파리의 페이지를 스크롤 컨트롤과 중복되기 때문입니다. event.targetTouches는 타깃 <div> 요소 위에 있는 각 손가락에 대한 데이터 목록들을 가지고 있습니다. 우리는 그중 하나에 대한 것만 필요하므로 event.targetTouches을 사용합니다. pageX는 손가락 위치의 x 좌표값입니다. 손가락이 박스의 중간에 위치할 수 있게 하기 위해 <div>의 가로 크기의 반을 x 좌표값에서 뺐습니다.

예제 11번은 위 코드로 작성되었습니다.

9. 제스처들

아이폰에는 손가락 하나 이상의 동작에 대한 제스쳐가 있습니다. 스케일링(줌-인과 줌-아웃) 그리고 회전 입니다. 기기에 터치하고 있는 각 손가락에 대한 정보를 가지고 있는 touchestargetTouches 이벤트에 관하여 우리는 이미 배웠습니다. 줌과 팬(파노라마)과 같은 제스쳐를 다루기 위해서도 위와 같은 이벤트들을 사용할 수 있지만, 조금 더 편리한 제스처 이벤트 들이 있습니다. 다음을 살펴 봅니다.

  • gesturestart
  • gestureend
  • gesturechange

다음 예제에서 gesturechange 이벤트에 반응하고 WebKit 전용 CSS 스타일 프로퍼티인 webkitTransform을 사용하여 div를 스케일링도 해보고 회전도 시켜볼 것입니다. 마찬가지로 이벤트 리스너는 이벤트 객체를 넘겨 받습니다. 이벤트 객체는 다음과 같은 프로퍼티를 가지고 있습니다.

  • event.scale : 값 1은 스케일링이 전혀 없습니다. 값이 1보다 작을 때는 줌-아웃(<div> 요소를 작게 만듦)이며 줌-인일때 1보다 값이 큽니다.
  • event.rotate - 이것은 회전 각도입니다.

아래 코드는 이전에 살펴봤던 터치 앤 드래그 코드와 매우 흡사합니다.
window.addEventListener('load', function() {
  var b = document.getElementById('box'),
      bstyle = b.style;
  b.addEventListener('gesturechange', function(event) {
    event.preventDefault();
    bstyle.webkitTransform = 'scale(' + event.scale + ') ' +
                             'rotate('+ event.rotation + 'deg)';
  }, false);
}, false);

예제 12번은 위 코드에 대한 액션을 보여줍니다. <div>요소를 스케일링하고 회전할 수 있습니다.

만약에 아이폰 시뮬레이터로 이 예제를 확인 하는 경우, 옵션키를 활성화 하면 손가락 모양의 두 회색 점이 나타날 것입니다. 마우스를 드래그하여 그 점들을 좁히거나 늘릴 수 있습니다.



10. 특수한 링크들

아이폰에서 전화번호가 나온 페이지를 조회하다가 이 전화번호를 일일이 타이핑하지 않고 클릭만으로 전화가 걸린다면 얼마나 좋을까요? 모바일 사파리에서는 이것이 가능합니다. 전화번호 링크를 생성하기를 원한다면 tel: 스키마를 사용할 수 있습니다.
<a href="tel:12345678900">Call me</a>

SMS 문자도 문제없습니다. 아이폰 텍스트 메세지 어플에 연결되는 sms: 스키마를 사용하세요.
<a href="sms:12345678900">Send me a text</a>

다음은 특별한 URI 스키마를 사용하지는 않지만 때때로 어떠한 링크들은 아이폰에서는 특별한 액션을 취하기도 합니다.
  • 아이튠즈 스토어 링크는 아이튠즈와 연결됩니다.
  • 구글맵 링크는 지도 애플리케이션과 연결됩니다.
  • 유튜브 링크는 유튜브 애플리케이션과 연결됩니다.
  • 이메일 주소 링크는 메일 애플리케이션에 연결됩니다.

11. 홈 아이콘

기쁘게도 어떠한 방문자가 당신의 사이트를 홈스크린(아이폰의 애플리케이션 실행 화면)으로 등록하고 싶어할 지도 모릅니다. 일반적으로 당신의 사이트를 홈스크린으로 추가하면, 아이폰은 당신의 사이트를 스크린샷해서 아이콘처럼 사용할 것입니다. 하지만 이보다는 아이폰에 최적화된 개인 아이콘을 제공하는 것이 더 좋지 않을까요?

그렇게 하기 위해서, 57x57픽셀의 PNG 파일을 만들고 apple-touch-icon.png라고 이름 짓습니다. 그리고 파비콘과 마찬가지로 웹서버의 root에 그 이미지를 넣으면 됩니다. 아이폰은 자동으로 이미지를 글로시하게 효과를 주고 라운드 박스로 만들기 때문에 일부러 제작할 필요까지는 없습니다.



<link> 요소를 사용하여 그 아이콘의 파일 이름이나 위치를 변경할 수도 있습니다. CDN처럼 다른 웹서버에서 이미지를 호스트하는 경우라면 <link> 요소에 아이콘의 위치를 지정하기 위해 다음과 같이 작성하세요.
<link rel="apple-touch-icon" href="http://www.example.com/my-filename.png" />

12. 디버깅: 소스 보기와 콘솔

아이폰에서 어떻게 소스를 볼 수 있을까요? 불행하게도 모바일 사파리만으로는 불가능합니다. 하지만 다행스럽게도 북마클릿은 모바일 사파리에서도 사용할 수 있기 때문에 소스를 조회하는 기능을 가진 북마클릿을 사용 할 수 있습니다.

자바스크립트로 document.documentElement.innerHTML를 사용하여 페이지의 소스를 출력할 수 있고 이러한 내용을 북마클릿으로 만들어 새 창으로 소스를 볼 수 있습니다. iPHoneWebDev에서는 이미 이런 소스보기 관련 북마클릿를 여럿 제공하고 있으며 이 밖에도 모바일 사파리의 디스플레이를 최적화 하는데 도움을 주는 다른 것들도 많습니다. 이 북마클릿을 사용하기 위해서는 데스크탑용 사파리에서 즐겨찾기에 추가하고 아이튠즈로 동기화하면 됩니다.

모바일 사파리는 디버깅 콘솔을 가지고 있습니다. 환경설정 > 사파리 > 개발자용 > 디버그 콘솔 옵션을 활성화하면 아이폰에서 디버깅 콘솔을 작동시킬 수 있습니다. 자 이제 디버그 콘솔이 사파리 브라우저 URL 툴바 아래에 나타날 것입니다. 페이지에 대한 에러를 보여주고 자바스크립트에서 디버그 메세지를 작성하기 위해 콘솔객체가 사용될 겻입니다.
console.log('Something');
console.error('Oops');
console.warning('Beware!');


이 것을 끝으로 흥분되고 도전할 만한 새로운 아이폰 웹 애플리케이션 개발에 조금이나마 도음이 되셨으면 좋겠습니다. 당신만의 특별한 아이디어로 승부하여 이루고자 하는 것들을 모두 이뤄내시길 바랍니다.

 

 

 

* 많은 내용이 책 또는 검색 후 개인적인 생각을 포함하여 개인용도로 쉽게 찾아보기 위해 정리한 것입니다.

본의 아니게 정리도중 출처를 읽어버린 경우가 있어 출처를 밝히지 못한 곳도 있으니 양해바랍니다.

문제가 될 경우 댓글 달아주시면 삭제/보완처리를 하겠습니다.

감사합니다.