본문 바로가기
모바일개발

[펌] Mobifying Your HTML5 Site

by 긴자손 2012. 4. 30.
728x90
반응형

※ 잘못 번역된 내용이 “당연히” 있을 테니 참고해서 읽으세요. 

번역 오류나 개선, 오타에 대한 피드백은 언제나 환영하고 감사드립니다. ^^

"Mobifying" Your HTML5 Site
당신의 HTML5 사이트를 “모바일화”하기


Written by Eric Bidelman - Developer Relations, Google on March 3, 2011
Translated by GyuCheol Choi(gc8134.choi@gmail.com) on March 9, 2011
원문 보기



개요

모바일 웹 개발이 최근 화두가 되고 있다. 최초로 올해에는 스마트폰이 PC보다 더 많이 팔릴 것이다. 더 많은 사용자가 웹 서핑을 위해 모바일 장치를 사용하게 될 것이고, 이것은 개발자들은 그들의 사이트를 모바일 브라우저에 최적화하는 것이 매우 중요해졌음을 의미한다.

"모바일"이라는 격전지는 아직 개발자들에게는 미지의 영역이다. 모바일 사용자들을 전혀 고려하지 않은 많은 전통적인 사이트들이 아직 존재한다. 대신 그 사이트들은 데스크탑 브라우징을 위해 디자인되고 모바일 브라우저용으로 조잡하게 변형되어 있다. 이 사이트(html5rocks.com) 역시 예외는 아니다. 초기에 우리는 사이트의 모바일 버전에는 전혀 신경을 쓰지 않았다.



모바일 친화적인 html5rocks.com 만들기

시험삼아, html5rocks(현재의 HTML5 사이트)를 가지고 모바일 친화적인 버전을 만들어보는 것이 재미있겠다고 생각했었다. 나는 스마트폰을 타겟으로 할 때 필요한 일의 양이 최소한인 것에만 관심이 있었다. 나의 목표는 완전히 새로운 모바일 사이트를 만들고 두 개의 코드 베이스를 유지하는 것이 아니었다. 그것은 끝나지도 않을 것이고, 엄청난 양의 시간 낭비일 것이다. 우리는 이미 정의된 사이트 구조(마크업)을 가지고 있다. 우리는 룩&필(CSS)을 가지고 있다. 주요 기능성(JS)도 있다. 중요한 점은 많은 사이트들이 비슷한 처지라는 것이다.

이 글을 통해 우리가 어떻게 안드로이드와 iOS 장치에 최적화된 html5rocks의 모바일 버전을 만들었는지 알아보려고 한다. 차이점을 보길 원하면 이러한 OS를 지원하는 장치에서 html5rocks.com 사이트를 열어보라. m.html5rocks.com으로의 리디렉션이나 이와 같은 어떠한 멍청한 조취도 없다. 당신은 html5rocks를 ?모바일 장치에서 잘 보이고 잘 동작하는 그러한 이점만 추가된- 있는 그대로를 보게 된다.

데스크탑(좌)과 모바일 장치(우)에서의 html5rocks.com



CSS 미디어 쿼리

HTML4와 CSS2는 필요에 의해 미디어-의존적인 스타일 시트를 지원한다. 예를 들면

<link rel="stylesheet" media="print" href="printer.css">

이 코드는 프린터를 타겟으로 하여, 이 페이지의 내용이 출력될 때를 위한 특별한 스타일을 제공한다. CSS3는 이 아이디어를 받아들여서 한 발 더 나아가 미디어 쿼리로 기능성을 향상 시켰다. 미디어 쿼리는 스타일 시트의 라벨에 더 자세한 사항을 기입할 수 있게 함으로써 미디어 타입의 사용성을 확장했다. 이것은 컨텐츠가 보여지는 것을 컨텐츠 자체를 수정하지 않아도 출력 장치의 특성에 맞게 최적화 할 수 있게 한다. 수정이 필요한 현재의 레이아웃에 있어서는 완벽한 것 같다!

타겟 스크린 폭, 장치의 폭, 방향 등을 나타내기 위해서 외부 스타일시트의 미디어 속성에 media 쿼리를 사용할 수 있다. 전체 리스트는 W3C media query specification을 보면 된다.


스크린 사이즈 지정하기

다음의 예제에서, phone.css는 브라우저가 "handheld"로 인식하는 장치나 320px 이하의 폭을 가진 장치에 적용될 것이다.

<link rel="stylesheet" media="handheld, only screen and (max-device-width: 320px)" href="phone.css">

미디어 쿼리 앞에 "only"를 두는 것은 CSS3를 지원하지 않는 브라우저에서는 이 규칙을 무시하게 해준다. 다음은 641px과 800px 사이의 스크린 크기를 가진 장치를 대상으로 한다.

<link rel="stylesheet" media="only screenshot and (min-width: 641px) and (max-width: 800px)" href="ipad.css">

미디어 쿼리는 인라인 <style>태그 내에서도 사용될 수 있다. 다음은 가로 방향에서의 모든 미디어 타입을 대상으로 한다:

<style> 
@media only all and (orientation: portrait) { ... } 
</style>


media="handheld"

일단 여기서 media="handheld"에 대해서 잠시 이야기를 할 필요가 있다. 사실 안드로이드와 iOS에서는 media="handheld"를 무시한다. 사용자들은 media=”"screen"으로 지정된 고품질의 컨텐츠를 놓쳐버릴 것이고, 개발자들은 저품질의 media="handheld" 버전을 유지하기를 별로 원하지 않았기 때문에 요구된 것이다. "full web"이라는 모토 하에, 대부분의 현재 스마트폰 브라우저는 handheld 스타일 시트를 무시한다.

모바일 장치를 대상으로는 이 속성이 사용되는 것이 이상적이겠지만, 많은 브라우저들은 다른 방법으로 그것을 구현했다.

  • handheld 스타일 시트만 읽음
  • 존재하는 경우에는 handheld 스타일 시트만을 읽고, 없으면 기본적으로 screen 스타일 시트를 읽음
  • handheld 스타일 시트와 screen 스타일 시트를 모두 읽음
  • screen 스타일 시트만 읽음

오페라 미니는 media="handheld"를 무시하지 않는다. 윈도우 모바일에서는 media="handheld"를 인식하기 위해서 screen 스타일시트를 위한 미디어 속성의 값을 대문자로 변환하는 트릭을 사용한다.

<!-- media="handheld" trick for Windows Mobile -->
<link rel="stylesheet" href="screen.css" media="Screen">
<link rel="stylesheet" href="mobile.css" media="handheld">


html5rocks에서 미디어 쿼리를 사용한 방법

모바일 html5rocks 전반적으로 미디어 쿼리는 비중 있게 사용된다. 미디어 쿼리는 우리가 Django 템플릿 마크업에 중요한 수정을 가하지 않고도 레이아웃을 변경할 수 있게 해줬다. 진정한 구세주! 게다가, 여러 브라우저에서의 지원도 꽤나 괜찮았다.

각 페이지의 <head>부분에서 다음의 스타일 시트를 볼 수 있을 것이다.

<link rel="stylesheet" media="all" href="/static/css/base.min.css" />
<link rel="stylesheet" media="only screen and (max-width: 800px)" href="/static/css/mobile.min.css" />

base.css는 html5rocks.com의 메인 룩&필을 정의하기 위해 있었고, 여기에 우리는 800px 이하의 화면 폭을 가진 장치를 위한 새 스타일(mobile.css)를 추가 했다. 그 미디어 쿼리는 스마트폰(최대 320px)과 iPad를 (최대 768px) 지원한다. 그 결과 모바일에서 잘 보이도록 하기 위해 (꼭 필요할 때만) base.css 파일의 점점 많은 부분을 오버라이딩하고 있다. 

mobile.css에 적용된 몇몇 스타일 변경 사항: 

  • 사이트 전반적으로 불필요한 whitespace/padding을 제거함. 작은 화면에서는 공간이 최우선!
  • :hover 상태를 없앰. 터치 장치에서는 절대 보이지 않음.
  • 레이아웃을 단일 칼럼으로 조절함. 이후에 상세히 설명.
  • 사이트의 메인 컨테이너 div 주변의 box-shadow 효과를 없앰. 큰 박스-그림자 효과를 페이지 성능을 저하시킴.
  • 홈페이지에서 각 섹션의 순서를 변경하기 위해서 CSS 박스 모델인 box-original-group을 사용. 홈페이지에서 “LEARN BY MAJOR HTML5 FEATURE GROUP”이 “TUTORIALS” 섹션보다 이전에 있었는데, 모바일 버전에서는 이후에 있음을 확인할 수 있음. 이러한 순서는 모바일에서 인식성을 높여줬지만, 마크업의 변화는 없었음. CSS는 승리를 위한 FlexBox!! (Flexible Box Layout Module, 역자주)
  • opacity 변경을 제거함. 모바일에서는 알파 값 변경이 성능에 치명적.



모바일 메타 태그

모바일 웹킷은 사용자들에게 특정 장치에서 더 좋은 브라우징 환경을 제공하는 몇몇 장점을 지원한다.


뷰포트 설정

첫 번째 (그리고 가장 자주 사용할) 메타 셋팅은 뷰포트 속성이다. 뷰포트를 셋팅하는 것은 브라우저가 컨텐츠가 어떻게 장치의 화면에 맞게 보여야 되는지를 알려주고, 브라우저에게 사이트가 모바일에 최적화되어 있다는 점을 알려준다. 예를 들면:

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

이 코드는 기본 확대비율이 1인 장치의 가로 크기를 뷰포트로 설정했다는 것을 브라우저에게 알려준다. 이 예제는 또한 줌이 가능하게 하는데, 아마 웹 어플리케이션 보다는 웹 사이트에 요구되는 점일 것이다. user-scalable=no나 확대비율을 특정 레벨로 지정함으로써 줌 동작을 하지 않게 할 수 있다.

<meta name=viewport content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

노트 : width는 픽셀 값을 가질 수도 있다. width=320으로 셋팅하는 것은 아이폰이나 다른 일부 스마트폰에서는 width=device-width로 설정하는 것과 같은 효과를 가진다. 모든 폰이 이와 정확히 동일한 가로 크기를 가지고 있지 않음을 유념해야 한다. 그래서 device-width로 지정을 하고 브라우저가 나머지는 판단하도록 하는 것이 최선의 방법이다.

안드로이드는 개발자가 사이트가 어떤 화면 크기에 맞게 개발 되었는지를 명시함으로써 뷰포트 매타 태그를 확장할 수 있게 한다.

<meta name="viewport" content="target-densitydpi=device-dpi">

target-densitydpi에 적용 가능한 값은 device-dpihigh-dpimedium-dpilow-dpi가 있다.

만약 웹 페이지를 서로 다른 스크린 density에 모두 맞게 수정하고 싶다면 ?webkit-device-pixel-radio CSS 메타 태그와 자바 스크립트의 window.devicePixelRatio 속성을 이용하면 된다. 그러면 target-densitydpi 메타 속성을 device-dpi로 설정한다. 이러한 것은 안드로이드에서 웹 페이지의 크기 변경을 불가능하게 하고, 각각의 density에 대해서 CSS와 자바스크립트를 통해서 필요한 조절을 할 수 있게 해준다.

타켓 디바이스 해상도와 관련된 더 자세한 정보를 위해서는 안드로이드의 WebView documentation을 참고하면 된다. 


풀 스크린 브라우징

iOS 전용인 메타 값이 두 가지가 있다. apple-mobile-web-app-capable과 apple-mobile-web-app-status-bar-style은 컨텐츠를 어플리케이션과 같이 풀스크린에 맞게 렌더링하고 상태표시줄을 반투명으로 변경해준다.

<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

메타 옵션의 설정 값에 대해서는 Safari reference documentation을 참조하면 된다.


홈 스크린 아이콘

안드로이드와 iOS는 링크를 위해서 rel="apple-touch-icon" (iOS) 과 rel="apple-touch-icon-precomposed" (안드로이드) 를 허용한다. 이것들은 사용자가 사이트를 북마크에 추가했을 때 플래쉬 어플리케이션 같은 아이콘을 사용자의 홈스크린에 생성한다.

<link rel="apple-touch-icon" href="/static/images/identity/HTML5_Badge_64.png" />
<link rel="apple-touch-icon-precomposed" href="/static/images/identity/HTML5_Badge_64.png" />


html5rocks가 모바일 메타 태그를 사용하는 방법

모든 것들을 취합한, html5rocks의 <head> 섹션의 일부분이다. 
<head>
...
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
<link rel="apple-touch-icon" href="/static/images/identity/HTML5_Badge_64.png" />
<link rel="apple-touch-icon-precomposed" href="/static/images/identity/HTML5_Badge_64.png" />
...
</head>



세로 레이아웃

작은 화면에서는 가로 스크롤 보다는 세로 스크롤이 훨씬 편리하다. 컨텐츠를 단일 칼럼에 배치하는 세로 레이아웃이 모바일에서는 더 선호된다. html5rocks에서는, 그러한 레이아웃을 만들기 위해 CSS3 미디어 쿼리를 이용했다. 다시 말하지만 마크업의 변경은 없었다.

사이트의 세로 레이아웃 화면들



모바일 최적화

우리가 한 대부분의 최적화 작업들은 첫 단계에서 완료되어야 하는 것들이다. 네트워크 요구의 횟수를 줄이는 것, JS/CSS 압축, gzipping, DOM 조작 최소화 등. 이러한 것들은 보편적인 최고의 행동들이지만, 사이트를 오픈할 때 때론 간과되기도 한다.


네트워크 요청을 줄이고 대역폭 아끼기

HTTP 요청 횟수를 줄이는 것은 성능을 극적으로 향상 시킬 수 있다는 점은 이미 알려진 사실이다. 모바일 장치는 브라우저가 생성할 수 있는 동시 접속수를 제한하기도 하는데, 때문에 모바일 사이트는 이러한 불필요한 요청을 줄이는 것으로도 상당한 효과를 볼 수 있다. 게다가, 폰에서는 대역폭이 제한되기 때문에 하나의 바이트라도 줄이는 것은 매우 중요하다. 사용자의 돈을 계산해야 한다!

다음은 네트워크 요청을 줄이고 대역폭을 줄이기 위해 html5rocks에서 사용한 몇 가지 접근법이다.? 

  • ?iframe 제거 - iframe은 느리다! 튜토리얼 페이지에서 3자 제공 위젯(Buzz, Google Friend Connect, Twitter, Facebook) 때문에 많은 양의 지연이 발생했다. 이 API들은 <script> 태그를 통해서 포함되었고, 페이지의 속도를 느리게하는 iframe을 만들었다. 모바일 버전에서는 위젯을 제거했다.
  • display:none - 특정한 경우에, 모바일에 맞지 않으면 마크업을 숨겼다. 좋은 예로 홈페이지의 상단에 있는 네 개의 상자를 들 수 있다. 
    이것들은 모바일 사이트에서는 빠졌다. 브라우저는 각 아이콘에 대해서는 여전히 요청을 한다는 것을 기억해야 한다. 대신에 그들은 display:none에 의해서 숨겨진다. 그러므로, 이것들을 단순히 숨기는 것은 충분하지 않다. 대역폭을 낭비하고 있을 뿐만 아니라, 그 대역폭을 낭비하는 요소들을 사용자들은 보지도 못한다! 해답은 HTML의 섹션을 조건에 따라 생략하기 위해 Django 템플릿의 “is_mobile” 이진변수를 생성하는 것이다. 사용자가 스마트 장치에서 사이트를 볼 때, 버튼들은 생략된다.
  • Application cache ? 이것은 오프라인 지원 뿐만 아니라, 더 빠른 시작을 가능하게 해준다.
  • CSS/JS 압축 ? CSS와 JS를 동시에 처리할 수 있다는 이유로 Closure compiler 대신에 YUI compressor를 사용했다. 우리가 겪은 하나의 이슈는 YUI compressor 2.4.2에서 인라인 미디어 쿼리(스타일 시트 내부에 있는 미디어쿼리)가 정상적으로 처리되지 않는 문제였다.(이 문제에 대해서는 여기를 보라.) YUI compressor 2.4.2+를 이용하니 그 문제가 해결됐다.
  • 가능한 곳에는 CSS 이미지 스프라이트(이미지를 등록해서 이용하는 기능, 역자주)를 사용했다.
  • 이미지 압축을 위해서 pngcrush를 사용했다.
  • 작은 이미지는 dataURI를 이용했다. Base64 인코딩은 이미지의 크기를 최대 30%까지 증가시키지만 네트워크 사용량을 절약할 수 있다.
  • google.load()를 이용한 동적인 구글 커스텀 서치 로딩보다는 단일 스트립트 태그를 이용한 자동 로딩을 사용했다. 전자는 추가의 요청을 필요로 한다. 
    <script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"></script>
    사용되지 않더라도 모든 페이지에 PrettyPrinter와 Modernizr(코드 정리 툴 등, 역자주)을 사용했다. Modernize는 훌륭한데, 매 페이지 로드마다 많은 테스트를 실행한다. 이러한 테스트 중 일부는 DOM에 꽤나 큰 수정을 만들어냈고, 페이지 로드 속도를 느리게 했다. 이제는 실제로 필요한 페이지에만 이 라이브러리들을 포함시켰다.

추가적인 퍼포먼스 향상 작업은:

  • 가능하다면 모든 JS를 페이지의 하단으로 옮겼다.
  • 인라인 <style> 태그를 제거했다.
  • DOM 검색을 캐쉬화하고 DOM 호출을 최소화했다 ? DOM을 건드릴 때마다, 브라우저는 reflow를 수행한다. Reflow는 모바일에서 더 낭비가 심하다.
  • 낭비성 클라이언트측 코드를 서버로 옮겼다. 특히, 현재 페이지의 네비게이션 스타일을 설정하는 것을 확인하는 체크 코드: 
    var lis = document.querySelectorAll('header nav li');
    var i = lis.length;
    while (i--) {
      var a = lis[i].querySelector('a');
      var section = a.getAttribute("data-section");
      if (new RegExp(section).test(document.location.href)) {
        a.className = 'current';
      }
    }
  • 고정폭을 가진 요소들은 width:100%나 width:auto로 변경되었다.


어플리케이션 캐시

모바일 버전의 html5rock는 초기 로드 속도를 빠르게 하고 사용자가 오프라인에서도 컨텐츠를 볼 수 있도록 하기 위해서 어플리케이션 캐시를 사용한다. 

사이트에 어플리케이션 캐시를 사용할 때, 매니페스트 파일 (명시적으로 매니페스트 파일이거나 또는 묵시적으로 무거운 캐시 컨트롤 헤더를 가진 경우 모두)을 캐시하지 않는 것이 매우 중요하다. 매니페스트가 브라우저에 의해서 캐시되면 디버깅하기에는 악몽이다. iOS와 안드로이드는 이 파일을 캐싱하는데 있어서 부분적으로 좋은 성능을 내기도 하지만, 데스크탑 브라우저처럼 캐시를 플러싱하는 편리한 방법을 제공하지는 않는다.

위에서 언급한 캐싱을 방지하기 위해서, 우리는 우선 어플리케이션 엔진이 매니페스트 파일을 캐시하지 못하도록 가장 먼저 설정 했다:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

둘째로, 새로운 매니페스트가 다운로드 완료되었음을 사용자에게 알리기 위해서 JS API를 사용했다. 이것들은 페이지를 리프레시하는데 즉각적이었다.

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

네트워크 트래픽을 절약하기 위해서는 매니페스트를 간단하게 유지해야 한다. 즉, 사이트의 모든 페이지를 호출하면 안된다. 중요한 이미지, CSS, 자바스크립트 파일만 목록에 넣어라. 마지막으로 하고 싶은 것은 매 어플리케이션 캐시 업데이트마다 많은 양의 데이터를 브라우저가 다운로드 받게 하는 것이다. 대신에, 사용자가 페이지를 방문할 때 (그리고 <html manifest="..."> 속성을 가지고 있을 때) 브라우저는 묵시적으로 html 페에지를 캐싱한다는 것은 기억해야 한다.

크리에이티브 커먼즈 라이선스
Creative Commons License


원본 출처 : http://gc8134.tistory.com/trackback/40



728x90
반응형