글쓴이 보관물: xguru

GuruLinks: 아이폰 앱 76개 소스코드, 강좌, 개발 팁 링크모음

아이폰 개발시 도움이 되는 각종 팁 , 튜토리얼, 소스코드 링크 모음입니다. 제가 주로 트위터를 통해서 공개한 것들입니다만, 워낙 간헐적으로 트위팅 한듯해서 좀더 링크를 모아서 포스팅 합니다. 한글판 앱스토어 리뷰 가이드라인은 아이폰 앱 개발자분들은 꼭 한번 읽어보셔야 합니다.


.

HTML5 API 강좌 #1 – Web Storage 와 Application Cache

이 글은 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가 동작하는 순서를 간략히 알아보자.

  1. 사이트에 최초 접속시 브라우저는 html 태그의 manifest 속성을 보고 manifest 파일을 로드한다.
  2. Manifest 파일 자체와 내부의 CACHE: 섹션의 모든 파일, 그리고 FALLBACK: 섹션에 있는 대체 파일들을 캐쉬에 저장한다.
  3. 두번째 접속시 브라우저는 manifest 파일을 불러서 이 파일이 변경되었는지를 비교한다. 수정이 되었다면 2번 프로세스를 다시 시작한다.

    * 중요 체크포인트 1 : 리소스 파일이 변경되었는지가 아니라 manifest 파일내용 자체가 변경되었는지를 체크하는 것이다. 만약 캐쉬된 로고이미지가 바뀌거나 CSS 파일의 내용이 바뀌었다면 manifest 파일 자체를 수정해서 다시 로드 되도록 해야 한다. 이 때문에 손쉽게는 동적으로 생성되는 Manifest 파일의 코멘트부분에 수정한 날짜 또는 버전정보를 적어놓는 등의 방법을 이용하거나, Javascript 를 이용하여 수동으로 갱신하도록 한다.

    * 중요 체크포인트 2 : 2번째 접속시에 만약 리소스가 변경되었더라도 2번째 접속 자체는 처음의 캐쉬를 이용하여 화면이 구성되게 된다. 즉 처음 캐쉬로 화면을 먼저 표시하고 , 백그라운드에서 캐쉬 업데이트 프로세스가 진행된다. 업데이트가 완료되면 Javascript 로 이벤트가 발생하게 되며, 이때 강제로 캐쉬를 교체해야만 수정된 캐쉬가 화면에 보여지게 된다.

  4. 오프라인 상태에서 해당 페이지로 접속시도시 실패한다면 Application Cache 에서 html 파일과 캐쉬된 파일을 로드한다. 즉, Offline 모드에서의 페이지 보기로 동작한다.
  5. 사이트의 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로 지정되며 캐쉬는 삭제된다.
  • 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 에러 )
  • Application Cache 의 메소드들
    캐쉬에 대해 사용할수 있는 메소드는 2가지이다.

    • window.applicationCache.swapCache()

      앞에서 나왔듯이 새로 다운로드 받은 캐쉬와 현재 사용중인 캐쉬를 강제로 교체하는 함수이다.

    • window.applicationCache.update()
      Application Cache 다운로드를 다시 호출한다. 즉 Manifest 파일을 다운받아서, 현재 캐쉬 되어있는 Manifest 와 비교하여 변경된 부분이 있다면 새 캐쉬를 다운로드 한다. 이걸 호출하더라도, 현재 사용중인 캐쉬가 변경되지는 않으며, 새 캐쉬고 업데이트되고 updateready 이벤트 발생시에 swapCache() 함수를 호출해 줘야 한다.

실제로 자신의 웹 어플리케이션에 Application Cache 를 적용하게 되면 항상 2가지 작업을 하게 된다.

  1. html 태그 에 manifest 속성추가
  2. 자바스크립트에 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 아이템의 추가/수정/삭제등이 모두 가능하다.

Chrome Developer Tools Window

지금까지 HTML5 의 Offline 지원기능 중에 두 가지인 Application Cache 와 Web Storage 에 대해 알아보았다. 다음 회에선 브라우저에서 사용 가능한 데이터베이스인 Web SQL Database 와 위치정보 지원을 위한 GeoLocation API 를 알아보고, 이를 이용한 샘플 어플리케이션을 제작해볼 것이다.