이 글은 HTML5 로 아이폰 앱 만들기 라는 제목으로 월간 W.e.b. 에 연재하는 글에서 발췌한 것입니다.
( 잡지에 기고한 글이라 원래 제 블로그의 글과 어투가 다릅니다. ^^; 총 5회 분량으로 진행됩니다. )
이 글 전에 먼저 “HTML5 on Mobile : 왜 HTML5 가 모바일에서 중요한가” 글을 읽어보시기 바랍니다.
1.1. 모바일에서 중요한 HTML5 요소들
모바일에서 HTML5 가 특별히 다른 태그를 활용하는 것은 아니다. 다만 API 중 몇 개가 모바일에 더욱 쓰기 좋은 형태일 뿐이다.
- Offline 지원 : Web Storage ( Local & Session ) , Web Database , App Cache
- 미디어 처리 : Video , Audio , Canvas
- 입력 지원 : Advanced Forms
- 위치 정보 : GeoLocation ( 연계표준 )
Offline 지원의 경우 항상 인터넷에 연결되어 있는 데스크탑과 달리 모바일 환경은 꼭 3G 와 같은 네트웍에 항시 연결되어있지 않은 WIFI 전용 기기 ( iPod Touch , iPad ) 들도 있으며, 3G 환경이라 할지라도 네트웍 트래픽을 최소화 하는 것이 아주 중요하다. 또한 HTML5 의 중요 스펙중 몇 가지는 아직 모바일용 주요 브라우저에서도 지원되지 않는다 ( iOS 4 , Android )
- WebSocket
- FileReader
- IndexedDB
- Web Workers
현재로선 모바일에서의 HTML5 사용은 주로 Offline 지원을 통한 Local App 으로서의 동작 및 트래픽 최적화, Geo Location 을 통한 위치정보 연동이 가장 많이 쓰이고 있다. 이 연재에서는 모바일에서의 Offline 지원 / GeoLocation API 의 사용방법을 알아보고, 모바일 HTML5 기반 웹앱을 만드는 방법을 알아본다.
1.2. Application Cache
앞서 말했듯이 HTML5 어플리케이션은 Offline 환경을 고려하여 Local App 으로 동작할 때, 또는 모바일 환경에서 사용될 때 트래픽의 최소화를 위하여 Application Cache (어플리케이션 캐쉬) 기능을 제공한다. 사실 우리가 사용하는 많은 브라우저들은 자체 캐쉬 기능을 가지고 있다. 하지만 이 캐쉬는 브라우저가 임시폴더에 저장하고 브라우저 자체에 의해 관리되므로, 웹 어플리케이션은 실제로 자신의 데이타가 캐쉬되어 있는지 확인하거나 관리할 수 없다. 이 HTML5 의 Application Cache 는 브라우저 캐쉬 와는 다르게 전적으로 웹 어플리케이션에 의해 관리되어 어떤 파일을 캐쉬할지부터 캐쉬된 파일을 업데이트 할지 말지를 웹 어플리케이션이 결정하게 된다.
이 Application Cache는 우리가 일반적으로 웹사이트를 구성할 때 사용하는 주요 요소인 HTML, JS, CSS 등의 문서파일들과 각종 이미지 파일들을 브라우저가 제공하는 임시영역에 캐쉬로 저장하도록 지원하여, 오프라인상일 때 브라우저가 웹페이지를 Refresh 하더라도 페이지가 제대로 로딩되도록 한다. 이 캐쉬는 다음과 같은 장점을 가지고 있다.
- Offline 지원 : 한번 사이트에 접속하여 파일을 다운로드 해 놓으면, 사용자가 오프라인일때에도 페이지/사이트를 접근할 수 있다.
- 속도 향상 : 지정한 모든 파일을 로컬에 저장해두므로, 훨씬 빠르게 페이지를 표시할 수 있다. 일반적으로 CSS, JS 같은 파일들은 전체 사이트에서 공유되므로 초기에 한번만 다운로드해 놓으면 그 후에는 매우 빠르게 재사용된다.
- 서버 부하 감소 : 캐쉬된 파일들이 있을 경우에 브라우저가 그 페이지를 Reload 할 경우, 브라우저는 혹시 캐쉬된 파일이 업데이트 되었는지만 체크하고 변경 안되었을 경우 다운로드 하지 않으므로 서버측에서는 파일전송에 대한 부하가 줄어들게 된다.
현재 모바일/데스크탑 웹 브라우저의 경우 일반적으로 각 도메인당 5M로 캐쉬 크기가 설정되어 있는것으로 알려져 있으며, 데스크탑 브라우저의 경우 5MB 가 넘어갈 때 사용자에게 확장할 것인지를 묻기도 한다. ( 브라우저 구현에 따라 다르고, 현재로서는 스펙상 크기가 제한되어 있지 않다. )
1.2.1. Application Cache 동작방식 알아보기
사이트에 Application Cache 를 추가하는 건 매우 간단하다. 각 페이지의 html 태그에 다음과 같이 manifest 속성을 지정한다.
* 주의 : 몇몇 브라우저에서는 와 같은 HTML5 Doctype 선언이 없으면 Application Cache 가 잘 동작하지 않을 수도 있다.
이 manifest 속성에는 URI 형식으로 Manifest 파일을 지정하면 된다. 이 appcache.manifest 파일 ( 이름이나 확장자는 상관없다 ) 은 텍스트 파일이며 다음과 같은 내용으로 구성된다.
CACHE MANIFEST
# this is comment
# manifest version : v1.1 20100808
CACHE:
stylesheet.css
js/jquery.js
js/system.js
img/logo.png
img/icons.png
NETWORK:
login.php
FALLBACK:
img/main_image.png img/backup_image.png
Manifest 파일은 단순한 텍스트 파일이지만 서버에서 이 파일을 전송할 때 MIME 타입은 꼭 text/cache-manifest 로 되어있어야 한다. 웹 서버에 .manifest 의 MIME 타입을 등록 ( 확장자는 상관없기 때문에 원하는 걸로 해도 된다. ) 해주거나, 동적으로 manifest 를 생성할 때는 헤더를 지정해주면 된다. 예를 들어 php 에서는 아래와 같이 header 함수를 이용해 Content-Type 을 text/cache-manifest 로 지정한다.
이 Manifest 파일의 맨 첫 줄은 꼭 CACHE MANIFEST 라는 내용으로 시작해야 한다. 실제로는 CACHE: , NETWORK: , FALLBACK: 이라는 3개의 헤더정보가 있지만 맨 앞의 CACHE: 는 생략되어도 된다. 즉 앞의 Manifest 파일 앞 부분은 아래와 같이 CACHE: 를 제거해도 상관없다.
CACHE MANIFEST
# this is comment
# manifest version : v1.1 20100808
stylesheet.css
js/jquery.js
js/system.js
img/logo.png
img/icons.png
섹션아래에 리소스들은 Manifest 파일이 위치한 곳으로부터의 상대경로 또는 절대경로로 지정될 수 있다. html 파일이 위치한 경로가 아님에 주의하자. Manifest 파일의 경로가 다른 곳에 있으면 이미지등 URL 이 실제 html 페이지와 다를 수 있으므로, 일반적으로는 html 파일과 Manifest 를 같은 위치에 두는 것이 좋다. 그외에 # 으로 시작되는 주석문 또는 빈 줄도 추가될 수 있다.
각 섹션에 대해 알아보자
- CACHE:
- 이 섹션에 명시되어 있는 파일들은 맨 처음 로드되고 나서 캐쉬에 저장된다.
- 현재의 Manifest 파일을 지정한 html 파일은 이 섹션에 없더라도 자동으로 캐쉬에 저장된다.
- NETWORK:
- 이 섹션에 명시되어 있는 파일들은 무조건 네트웍에서만 불러오게 된다. 즉, 만약 브라우저가 오프라인 상태라면, 이 파일들은 캐쉬된 파일에서 사용되면 안 된다.
- FALLBACK:
- 이 섹션은 로딩에 실패했을 경우에 대신 사용할 파일들을 지정하는 것이다. A B 라는 형형태 지정했을 때 A 의 로딩에 실패하면 B 를 자동으로 로딩한다. 즉 이 경우 B 의 파일은 캐쉬에 저장되어, 오프라인 모드에서 A 를 못불러올 경우 캐쉬에서 읽히게 된다.
- Fallback 은 폴더 전체에도 적용이 가능하다. 즉
FALLBACK: /photo notavailable.png
위와 같이 지정했을 경우 오프라인 모드에서는 /photo 폴더 밑의 모든 이미지를 못 가져 오게 되므로 notavailable.png 파일로 대체되게 된다.
1.2.2. Application Cache 동작순서
브라우저에서 Application Cache가 동작하는 순서를 간략히 알아보자.
- 사이트에 최초 접속시 브라우저는 html 태그의 manifest 속성을 보고 manifest 파일을 로드한다.
- Manifest 파일 자체와 내부의 CACHE: 섹션의 모든 파일, 그리고 FALLBACK: 섹션에 있는 대체 파일들을 캐쉬에 저장한다.
- 두번째 접속시 브라우저는 manifest 파일을 불러서 이 파일이 변경되었는지를 비교한다. 수정이 되었다면 2번 프로세스를 다시 시작한다.
* 중요 체크포인트 1 : 리소스 파일이 변경되었는지가 아니라 manifest 파일내용 자체가 변경되었는지를 체크하는 것이다. 만약 캐쉬된 로고이미지가 바뀌거나 CSS 파일의 내용이 바뀌었다면 manifest 파일 자체를 수정해서 다시 로드 되도록 해야 한다. 이 때문에 손쉽게는 동적으로 생성되는 Manifest 파일의 코멘트부분에 수정한 날짜 또는 버전정보를 적어놓는 등의 방법을 이용하거나, Javascript 를 이용하여 수동으로 갱신하도록 한다.
* 중요 체크포인트 2 : 2번째 접속시에 만약 리소스가 변경되었더라도 2번째 접속 자체는 처음의 캐쉬를 이용하여 화면이 구성되게 된다. 즉 처음 캐쉬로 화면을 먼저 표시하고 , 백그라운드에서 캐쉬 업데이트 프로세스가 진행된다. 업데이트가 완료되면 Javascript 로 이벤트가 발생하게 되며, 이때 강제로 캐쉬를 교체해야만 수정된 캐쉬가 화면에 보여지게 된다.
- 오프라인 상태에서 해당 페이지로 접속시도시 실패한다면 Application Cache 에서 html 파일과 캐쉬된 파일을 로드한다. 즉, Offline 모드에서의 페이지 보기로 동작한다.
- 사이트의 html 태그에서 manifest 가 제거되었다면, 브라우저는 해당캐쉬를 삭제한다.
즉, 처음 접속시 manifest 가 지정되어 있다면 이 내용에 따라 캐쉬해 두었다가, 차후 접속 시에 사용하는 방식으로 동작한다.
1.2.3. Javascript 에서 Application Cache 관리하기
Application Cache는 Manifest 파일에 의해서 정적으로 관리되는 방식 외에 Javascript 를 통해서 좀더 세밀하게 관리가 가능하다. 브라우저가 Application Cache 를 지원하는지 여부, 캐쉬에 대한 상태를 읽어들이거나, 비동기적으로 업데이트 하는등의 동작을 자바스크립트 코드상에서 할수있도록 지원한다.
- Application Cache 지원여부 확인
- 코드상에서 window.applicationCache 를 객체를 검사하면 브라우저가 Application Cache를 지원하는지 여부를 확인할수 있다.
-
If (!!window.applicationCache) { // 지원함 } else { }
- Application Cache 상태
Window.applicationCache.status 를 확인하면 현재 캐쉬의 상태를 알 수 있다. 다음과 같이 6개의 상태값을 가질 수 있다. 각 상태값은 applicationCache 에 대문자로 된 상수로 선언되어 있다.
if ( window.applicationCache.status == window.applicationCache.UPDATEREADY) { // 작업진행 }
- 0 – UNCACHED
페이지가 캐쉬를 사용하지 않거나, 맨 처음 접속시에 캐쉬가 다운로드 되기 전까지는 UNCACHED 상태이다. - 1 – IDLE
브라우저가 최신버전의 Application Cache 로 업데이트되었고, 더 이상 다운로드 할 업데이트 버전이 없는 상태 - 2 – CHECKING
Manifest 파일이 업데이트 되었는지를 체크하는 상태 ( 현재 캐쉬된 Manifest 파일과 서버의 Manifest 파일을 바이트단위로 비교한다 ) - 3 – DOWNLOADING
캐쉬할 파일들을 다운로드 하는 상태 ( 2번 단계에서 Manifest 파일이 업데이트되었다고 알게 되었을 때 ) - 4 – UPDATEREADY
새로운 캐쉬의 다운로드가 끝나고 사용할 준비가 되었을 때 ( 아직 이 캐쉬가 사용된건 아님 ) - 5 – OBSOLETE
Manifest 파일 자체를 찾을 수 없을 때, 상태는 OBSOLETE로 지정되며 캐쉬는 삭제된다.
- 0 – UNCACHED
- Application Cache 에 의해 발생하는 Event 들
캐쉬의 상태에 따라 아래와 같은 이벤트 들이 발생한다. 아래와 같이 이벤트 리스너를 등록해서 각각의 이벤트에 대응할수 있다.window.applicationCache.addEventListener(‘updateready’, function() { // 이벤트 처리하기 }, false);
- checking
manifest 파일을 처음으로 다운받을때나, 업데이트된 manifest 가 있는지 확인할 때 발생하는 이벤트 - error
파일을 다운로드 할 수 없거나 하는 다양한 에러시 발생. 만약 manifest 에 있는 파일들중 하나라도 다운로드가 실패하면 캐쉬 업데이트 전체가 실패한다. 물론 실패하더라도 기존에 있는 캐쉬 자체가 깨지지는 않으며 브라우저는 계속해서 예전버전의 캐쉬를 이용하게 된다. - noupdate
업데이트할 파일이 없을 때 발생하는 이벤트 - downloading
처음으로 캐쉬할 파일들을 다운받거나, 업데이트된 캐쉬가 있을 때 발생
화면에 변경된 내용을 업데이트 중이라는 것을 표현해줄 수 있는 이벤트window.applicationCache.addEventListener(‘downloading, function() { showMessage(‘리소스 다운로드중입니다.’) }, false);
- progress
캐쉬할 각각의 파일이 다운로드 될 때마다 발생하는 이벤트 - updateready
새로 업데이트된 캐쉬의 모든 리소스가 다운로드되었을 때 발생하는 이벤트. 이 이벤트가 발생하면 swapCache() 함수를 호출하여 브라우저가 새로 업데이트된 캐쉬를 사용하도록 할 수 있다.window.applicationCache.addEventListener(‘updateready’, function() { window.applicationCache.swapCache(); }, false);
- cached
모든 리소스가 다운로드 되어, 어플리케이션이 캐쉬되었을 때 발생 - obsolete
manifest 파일을 찾을 수 없을 때 ( 404 또는 410 에러 )
- checking
- Application Cache 의 메소드들
캐쉬에 대해 사용할수 있는 메소드는 2가지이다.- window.applicationCache.swapCache()
앞에서 나왔듯이 새로 다운로드 받은 캐쉬와 현재 사용중인 캐쉬를 강제로 교체하는 함수이다.
- window.applicationCache.update()
Application Cache 다운로드를 다시 호출한다. 즉 Manifest 파일을 다운받아서, 현재 캐쉬 되어있는 Manifest 와 비교하여 변경된 부분이 있다면 새 캐쉬를 다운로드 한다. 이걸 호출하더라도, 현재 사용중인 캐쉬가 변경되지는 않으며, 새 캐쉬고 업데이트되고 updateready 이벤트 발생시에 swapCache() 함수를 호출해 줘야 한다.
- window.applicationCache.swapCache()
실제로 자신의 웹 어플리케이션에 Application Cache 를 적용하게 되면 항상 2가지 작업을 하게 된다.
- html 태그 에 manifest 속성추가
- 자바스크립트에 updateready 이벤트 받아서 swapCache() 호출
이를 통해 여러분의 웹 어플리케이션이 Offline 상에서도 동작 가능하게 하고, 또한 좀더 빠르게 로딩할 수 있도록 만들 수 있다.
1.3. Web Storage
1.3.1. Web Storage 와 Cookie
HTML5 의 Offline 지원 API 중에서 2번째는 Web Storage 라고 불리는 Key/Value 쌍으로 된 형식의 저장소이다. 우리는 이미 많은 웹 어플리케이션에서 Cookie 를 이용해서 이 Key/Value 값을 저장해왔다. 하지만 Cookie 는 다음과 같은 단점이 있다.
- 보통 브라우저에서 최대 크기가 4KB 정도로 제한이 있다.
- 매번 HTTP Request 호출 시마다 HTTP 헤더에 전송을 필요로 하기 때문에 많은 양의 값들을 저장하기 에는 무리가 있어서, Cookie 양이 커질 때마다 웹서버의 응답시간이 늘어나는 결과를 보인다. ( Cookie 에 대한 퍼포먼스 측정은 http://j.mp/nomore_cookies 를 참고 )
- 헤더에 전송되므로 악의적인 용도로 쓰일 수 있다.
HTML5의 Web Storage 는 이런 쿠키의 단점을 보완하여 클라이언트(브라우저) 상에서만 저장되고 관리되므로 더욱 효율적이다. Web Storage 는 2가지의 저장공간을 제공한다. 일반적으로 이 데이터들은 일반적으로 각 도메인 별로 약 5Mb 까지 저장이 가능하다. ( 브라우저 별로 차이가 있을수 있다 )
- LocalStorage
장기적으로 저장할 수 있는 공간이다. 브라우저 창을 닫아도 계속 유지되며 모든 브라우저 창 간에 공유된다. 유효기간이 없는 Cookie 와 같다고 보면 된다. - SessionStorage
세션이라는 이름에서 볼 수 있듯이 현재 브라우저 창에만 유효한 저장공간이다. 즉 브라우저창을 닫으면 모두 지워진다.
주의! : 만약 현재 브라우저 창 내에서 a 태그에 target=_blank 같은 걸 지정했을 경우 이 링크를 눌러서 새로운 창을 열게 되면, 지금까지 기록된 SessionStorage 내부의 값을 모두 복사해서 넘기게 된다. 그러면 두 개의 창은 처음에는 똑 같은 SessionStorage 내용으로 만들어지지만, 그 다음부터 수정된 SessionStorage 내용은 서로 다르게 된다. 즉 세션 데이터가 복사되지만 공유되는 것은 아니다.
1.3.2. Web Storage 사용하기
LocalStroage 와 Sesseion Storage 가 브라우저상에서 처리되는 것은 차이가 있지만, 코드상에서는 똑같이 동작한다. 제공되는 메소드는 다음과 같다. ( localStorage 를 sessionStorage 로 바꿔도 똑같이 동작한다 )
localStorage.setItem ( key , value ) // 키/밸류 아이템을 저장
localStorage.getItem ( key ) // 해당키의 아이템을 가져온다.
localStorage.removeItem ( key ) // 해당키의 아이템을 삭제한다
localStorage.clear ( ) // 전체 아이템을 삭제한다
localStorage.length // 스토리지에 들어있는 아이템의 개수
예제를 통해 조금 더 자세히 알아보자.
- setItem ( key , value )
스토리지에 아이템을 저장하는 setItem 함수는 다음과 같이 호출할 수 있다.
localStorage.setItem( ‘username’ , ‘철수’);
일반적으로 에러가 발생할 일은 없지만 단 하나의 에러가 발생할 수 있다. 앞에서 말한 5MB 크기제한을 넘겼을 경우다.
try { localStorage.setItem( ‘username’ , ‘철수’ ); } catch (e) { if (e == QUOTA_EXCEEDED_ERR) { alert('저장공간이 초과되었습니다!'); } }
- getItem ( key )
저장된 아이템은 키를 이용해서 가져올수 있다.
alert( ‘현재 사용자는 ‘ + localStorage.getItem(‘username’) + ‘입니다.’ );
만약 지정한 key 이름이 유효한 javascript 토큰 ( 빈칸없고, 언더바만 사용되는 일반 적인 변수명과 같은 ) 이라면 아래와 같이 축약해서 쓸 수도 있다.
alert( ‘현재 사용자는 ‘ + localStorage.username + ‘입니다.’ );
- removeItem( key ) , clear()
removeItem() 을 이용하여 key 별로 지우거나, clear() 를 이용해서 전체 아이템을 삭제할 수 있다. 주의할 것은 localStorage.clear() 의 경우 현재 해당된 도메인에 할당된 전체 LocalStorage 를 지운다는 것이다. 즉 http://foo.org/abc/ , http://foo.org/xyz/ 두 개의 폴더에서 만들었더라도 상관없이 모두 지워진다. 단, http://bar.foo.org 와 같은 서브 도메인은 상관없다. 폴더별이 아닌 도메인별로 관리된다고 보면 된다.
1.3.3. 브라우저에서 Web Storage 관리하기
HTML5 를 잘 지원하는 WebKit 기반 브라우저 ( 크롬 / 사파리 )에서는 LocalStorage / SessionStorage 를 UI 상에서 보고 관리할 수 있는 방법을 제공한다. 개발시에 유용하게 사용할 수 있으므로 꼭 알아두자. ( Firefox 는 Firebug 를 깔면 볼 수는 있지만, WebKit 에 비해 불편하다 )
Chrome : Ctrl+Shift+J (윈) 또는 Command+Option+J (맥) 을 눌러 Developer Tools 실행
Safari : Ctrl+Alt+I (윈) 또는 Command+Option+I (맥) 을 눌러 Web Inspector 실행
양쪽 브라우저에서 창의 이름은 다르지만 기능은 거의 동일하다. 아래와 같이 Storage 탭에서 Local / Session 데이터를 확인 가능하며, Key/Value 아이템의 추가/수정/삭제등이 모두 가능하다.
지금까지 HTML5 의 Offline 지원기능 중에 두 가지인 Application Cache 와 Web Storage 에 대해 알아보았다. 다음 회에선 브라우저에서 사용 가능한 데이터베이스인 Web SQL Database 와 위치정보 지원을 위한 GeoLocation API 를 알아보고, 이를 이용한 샘플 어플리케이션을 제작해볼 것이다.