캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | devon 2012

105
캠프앱 개발 사례를 통해 하이브리드앱 어디까지 다음 커뮤니케이션 유승근

Upload: daum-dna

Post on 20-Dec-2014

5.734 views

Category:

Documents


16 download

DESCRIPTION

 

TRANSCRIPT

Page 1: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

캠프앱 개발 사례를 통해 본

하이브리드앱 어디까지

다음 커뮤니케이션유승근

�������������

Page 2: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

오늘 얘기할 순서 ...

• 개발 전- Cross Platform

- 캠프 하이브리드

• 개발 중- 화면 영역별 구현 방법- WebView & Web-App Bridge

- Application Cache

- 버전 관리

�������������

Page 3: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

오늘 얘기할 순서

• 오픈 후(최적화)

- WebView Request Intercept

- JS 크기 줄이기- Touch 이벤트

• 마무리하며

�������������

Page 4: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

�������������

Page 5: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Write Once, Run Anywhere

�������������

Page 6: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

• JavaScript Libraries :

- jQuery Mobile, Sencha Touch

• Wrappers around web applications :

- Adobe PhoneGap, KTH Appspresso

• Transformers to Native code :

- Appcelerator Titanium

• Adobe Air

Cross-Platform Tools: Build Once and Run Everywhere

Cross Platform Tools

�������������

Page 7: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web App

캠프 하이브리드앱

�������������

Page 8: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web App Native

캠프 하이브리드앱

�������������

Page 9: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web App Native

캠프 하이브리드앱

Hybrid�������������

Page 10: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

캠프 하이브리드앱

• 기대- One Source Multi Use

- 상대적으로 업데이트 용이- Web UI 구현 문제 해결

• 우려- 시스템 복잡도 증가- 웹과 앱의 배포 시점 동기화- WebView 성능 문제

�������������

Page 11: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

개발 시작!

�������������

Page 12: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native / Web무엇으로 구현해야 하나?

�������������

Page 13: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native 영역

• 레이아웃- 네비게이션바, 메뉴- position: fixed

• 사용자 입력 Form

- 이미지 업로드- 날짜 입력 등 복잡한 입력 요소들

• 다음 공통 컴포넌트- 로그인, 지도, 이미지뷰어

�������������

Page 14: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native 영역

• 레이아웃- 네비게이션바, 메뉴- position: fixed

• 사용자 입력 Form

- 이미지 업로드- 날짜 입력 등 복잡한 입력 요소들

• 다음 공통 컴포넌트- 로그인, 지도, 이미지뷰어

�������������

Page 15: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native 영역

• 레이아웃- 네비게이션바, 메뉴- position: fixed

• 사용자 입력 Form

- 이미지 업로드- 날짜 입력 등 복잡한 입력 요소들

• 다음 공통 컴포넌트- 로그인, 지도, 이미지뷰어

�������������

Page 16: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native 영역

• 레이아웃- 네비게이션바, 메뉴- position: fixed

• 사용자 입력 Form

- 이미지 업로드- 날짜 입력 등 복잡한 입력 요소들

• 다음 공통 컴포넌트- 로그인, 지도, 이미지뷰어

�������������

Page 17: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native 영역

• 레이아웃- 네비게이션바, 메뉴- position: fixed

• 사용자 입력 Form

- 이미지 업로드- 날짜 입력 등 복잡한 입력 요소들

• 다음 공통 컴포넌트- 로그인, 지도, 이미지뷰어

�������������

Page 18: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

input Focus

�������������

Page 19: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

input Focus

iOS 6 webview.keyboardDisplayRequiresUserAction = NO;

�������������

Page 20: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

WebView

�������������

Page 21: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

WebView

• Android

- WebView

- WebSettings

- WebChromeClient

- WebViewClient

• iOS

- UIWebView

- UIWebViewDelegate

�������������

Page 22: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Android 4.0.4

Browser WebView

�������������

Page 23: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

iOS 6

Safari UIWebView

�������������

Page 24: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Native to Web Call

• Android

- webview.loadUrl("http://camp.daum.net")

- webview.loadUrl("javascript:hello('world')")

• iOS

- [webview loadRequest:]

- [webview stringByEvaluatingJavaScriptFromString:]

�������������

Page 25: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web to Native Call

• location.href

- WebViewClient.shouldOverrideUrlLoading()

- webView:shouldStartLoadWithRequest:navigationType:

• window.prompt

- Android에서만 사용- WebChromeClient.onJsPrompt()

• Android - webview.addJavaScriptInterface()

- Java 객체를 JavaScript 객체로 삽입하여 public method 호출 가능- iOS, Android 동일 인터페이스로 제공 위해 미사용

�������������

Page 26: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Internal URL Scheme

• Web to Native 명령 규칙

scheme://namespace/action/param1/...

ex) daumcamp://daum.camp/camp/10

�������������

Page 27: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

location.href

• URL 변경을 연속해서 발생시키면 마지막 하나만 호출

• 해결책- setTimeout : 호출 시점 보장 못함

- iframe

function callByIframe(scheme) { var iframe = document.createElement('iframe'); iframe.src = scheme; document.body.appendChild(iframe);    setTimeout(function() {        document.body.removeChild(iframe);    }, 100);};

�������������

Page 28: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web to Native Callback

• Native 호출 후 응답이 필요한 경우

location.href = 'daumcamp://daum.camp/post/postComplete';

callback JS 함수

�������������

Page 29: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Cookie

• Android

- CookieManager

- CookieSyncManager

• iOS

- NSHTTPCookie

- NSHTTPCookieStorage

• Cookie 관리자는 Singleton 객체

�������������

Page 30: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Application Cache

�������������

Page 31: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Application Cache

<html manifest="appcache.manifest"> ...

<script>

applicationCache.addEventListener('updateready', function(e) { applicationCache.swapCache(); window.reload(); });

</script> ...

</html>

�������������

Page 32: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Application Cache Manifest

CACHE MANIFEST# 2012-06-18:v3

CACHE:index.htmlcss/style.css

FALLBACK:/ /offline.html

NETWORK:*

�������������

Page 33: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

cached progress... downloadingchecking 최초실행

noupdatechecking 변경없음

updateready progress... downloadingchecking 앱캐쉬 업데이트

obsoletechecking 앱캐쉬 제거

error • • •checking 에러

Application Cache - Events

�������������

Page 34: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

checking

�������������

Page 35: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

downloadingchecking

�������������

Page 36: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

progress... downloadingchecking

�������������

Page 37: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

updateready progress... downloadingchecking

appCache.swapCache(); window.reload();

�������������

Page 38: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

updateready progress... downloadingchecking

�������������

Page 39: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

MDPI HDPI

이미지 해상도 대응

�������������

Page 40: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

이미지 해상도 대응

• Cookie를 이용한 해결책- Native에서 해상도 정보 취득- 로딩 전 WebView에 해상도 정보를 cookie로 굽기- manifest 파일은 cookie 값을 바탕으로 동적 생성

�������������

Page 41: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

float density = Context.getResources() .getDisplayMetrics().density;

String pixelRatio = "1";

if (density >= 2.0) { pixelRatio = "2";} else if (density >= 1.5) { pixelRatio = "1.5";}

// setCookie pixelRatio

이미지 해상도 대응

�������������

Page 42: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

BOOL ios4 = [[UIScreen mainScreen] respondsToSelector: @selector(displayLinkWithTarget:selector:)];

String* pixelRatio = @"1";

if (ios4 && [UIScreen mainScreen].scale == 2.0) { // Retina display pixelRatio = @"2";}

// setCookie pixelRatio

이미지 해상도 대응

iOS 4 이상인지 확인

�������������

Page 43: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

#set ($IMG_TYPE = "480")

#if ($PIXEL_RATIO == "1") #set ($IMG_TYPE = "320")#endif

#set ($PATH = "http://m1.daumcdn.net/m/${IMG_TYPE}/")

...

CACHE:$!{PATH}/ico_camp01.png$!{PATH}/ico_camp02.png

이미지 해상도 대응

Velocity Template

�������������

Page 44: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

주의 사항

• html 파일은 항상 캐쉬

• 업데이트는 리소스 파일이 아닌 Manifest 파일의 변경

• Application cache 제거시 http 응답은 404

- obsolete 이벤트 처리 필요

• Android 2.1은 Network 섹션에서 * 선택자 미지원- 명시되지 않은 네트워크 요청은 모두 취소

�������������

Page 45: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

버전 관리

�������������

Page 46: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

�������������

Page 47: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

Web 1.0.1

�������������

Page 48: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

Web 1.0.1

Web 1.0.2

�������������

Page 49: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

Web 1.0.1

Web 1.0.2

Web 1.0.3App1.0.1

�������������

Page 50: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

Web 1.0.1

Web 1.0.2

Web 1.0.3

Web 1.0.4

App1.0.1

�������������

Page 51: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App1.0.0 Web 1.0.0

Web 1.0.1

Web 1.0.2

Web 1.0.3

Web 1.0.4

App1.0.1

MappingTable

�������������

Page 52: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Version Mapping Table

<bean ... >

" <property name="version" value="1.0.10-p6"/>

" <property name="androidVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.4)">1.0.6</prop>" " " <prop key="[1.0.4,)">1.0.10-p6</prop>" " </props>" </property>

" <property name="iosVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.2)">1.0.9-p3</prop>" " " <prop key="[1.0.2,)">1.0.10-p6</prop>" " </props>" </property>

</bean>

�������������

Page 53: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Version Mapping Table

<bean ... >

" <property name="version" value="1.0.10-p6"/>

" <property name="androidVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.4)">1.0.6</prop>" " " <prop key="[1.0.4,)">1.0.10-p6</prop>" " </props>" </property>

" <property name="iosVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.2)">1.0.9-p3</prop>" " " <prop key="[1.0.2,)">1.0.10-p6</prop>" " </props>" </property>

</bean>

최신 웹 버전

�������������

Page 54: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Version Mapping Table

<bean ... >

" <property name="version" value="1.0.10-p6"/>

" <property name="androidVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.4)">1.0.6</prop>" " " <prop key="[1.0.4,)">1.0.10-p6</prop>" " </props>" </property>

" <property name="iosVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.2)">1.0.9-p3</prop>" " " <prop key="[1.0.2,)">1.0.10-p6</prop>" " </props>" </property>

</bean>

Android VersionMapping

�������������

Page 55: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Version Mapping Table

<bean ... >

" <property name="version" value="1.0.10-p6"/>

" <property name="androidVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.4)">1.0.6</prop>" " " <prop key="[1.0.4,)">1.0.10-p6</prop>" " </props>" </property>

" <property name="iosVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.2)">1.0.9-p3</prop>" " " <prop key="[1.0.2,)">1.0.10-p6</prop>" " </props>" </property>

</bean>

iPhone VersionMapping

�������������

Page 56: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Version Mapping Table

<bean ... >

" <property name="version" value="1.0.10-p6"/>

" <property name="androidVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.4)">1.0.6</prop>" " " <prop key="[1.0.4,)">1.0.10-p6</prop>" " </props>" </property>

" <property name="iosVersionMap">" " <props>" " " <prop key="[1.0.0,1.0.2)">1.0.9-p3</prop>" " " <prop key="[1.0.2,)">1.0.10-p6</prop>" " </props>" </property>

</bean>

App Version Range Web Version

�������������

Page 57: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

App to Web URL

http://camp.daum.net/app/{platform}/{version}/...

ex) http://camp.daum.net/app/ios/1.0.2/...

�������������

Page 58: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

고민거리

• 현재 JS/CSS 만 버전 관리 대상

• HTML, Manifest 파일도 버전관리 해야 하지 않을까?

�������������

Page 59: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

오픈 후...

�������������

Page 60: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

�������������

Page 61: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

SunSpider JavaScript Benchmark

�������������

Page 62: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

0

1,750

3,500

5,250

7,000

Android 2.3 Android 4.0

Browser WebView

Androidru

nnin

g tim

e(m

s)

�������������

Page 63: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

0

3,000

6,000

9,000

12,000

iOS 4.3 iOS 5 iOS 6

Safari WebView

iOSru

nnin

g tim

e(m

s)

�������������

Page 64: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

장인은 도구를 탓하지 않는다.

�������������

Page 65: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Web Application 최적화

�������������

Page 66: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

로딩 과정

css, js load/parse/eval

init()

Load startonDOMContentLoaded

onLoad

Boot

router / data load / render

onHashchange

View

�������������

Page 67: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

로딩 과정

css, js load/parse/eval

init()

Load startonDOMContentLoaded

onLoad

Boot

router / data load / render

onHashchange

View

App에서는 지속적 발생

�������������

Page 68: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

로딩 중 구멍 찾기

�������������

Page 69: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Load Start

CSS

<script src="/env">

baselib.jscamp.js

init()

View Render

no-cache

application cache

application cache

웹앱 실행시 필수 정보그러나 앱에도 존재하는 정보

�������������

Page 70: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script Blocking

Script Loading

�������������

Page 71: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script Blocking

Script Loading API call

�������������

Page 72: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script Blocking

Script Loading API call Complete

�������������

Page 73: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script Blocking

Script Loading

�������������

Page 74: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script BlockingLoad Start

CSS

<script src="/env">

baselib.jscamp.js

init()

View Render

no-cache

app cache

app cache

Web

�������������

Page 75: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Script BlockingLoad Start

CSS

<script src="/env">

baselib.jscamp.js

init()

View Render

no-cache

app cache

app cache

Web

App

Intercept

Http Response

App에 있는 정보 바탕으로응답 생성

�������������

Page 76: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

WebView Request Intercept

• Android

- webViewClient.shouldInterceptRequest()

- API Level 11 - Android 3.0 이상 지원

• iOS

- NSURLCache class의cachedResponseForRequest: method override

- [NSURLCache setSharedURLCache:]

�������������

Page 77: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

�������������

Page 78: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

• Google Closure Compiler

- Minify & Code Merging

• SIMPLE_OPTIMIZATIONS

- 공백, 주석 삭제, Local 변수를 짧은 변수명으로 변경- 도달하지 않는 코드 제거 / 미사용 변수 제거

�������������

Page 79: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

var isDev = false;

function hello(name) { if (isDev) { console.log('hello called'); } return 'Hello, ' + name;}

hello('New user');

�������������

Page 80: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

var isDev = false;

function hello(name) { if (isDev) { console.log('hello called'); } return 'Hello, ' + name;}

hello('New user');

var isDev=!1;function hello(a){isDev&&console.log("hello called");return"Hello, "+a}hello("New user");

SIMPLE_OPTIMIZATION

�������������

Page 81: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

var isDev = false;

function hello(name) { if (false) { console.log('hello called'); } return 'Hello, ' + name;}

hello('New user');

�������������

Page 82: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS 코드 줄이기

var isDev = false;

function hello(name) { if (false) { console.log('hello called'); } return 'Hello, ' + name;}

hello('New user');

function hello(a){return"Hello, "+a}hello("New user");

SIMPLE_OPTIMIZATION

�������������

Page 83: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS Pre-Processor

• Idea

- 플랫폼 구분자를 상수로 치환하여 컴파일러가 제거 가능하게 하자- 플랫폼 별로 별도의 JavaScript 파일 생성

• JavaScript Parser

- Esprima : Source Code > Abstract Syntax Tree

- Escodegen : Abstract Syntax Tree > Source Code

�������������

Page 84: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Source Code

if (camp.isApp) {" camp.Util.installExtAnchorHandler();" if (camp.os === camp.OS.IOS) {" " camp.UI.navi.init();" " camp.Util.hideAddressBar();" }} else {" // 메뉴, 네비 적용" camp.UI.navi.init();" camp.UI.menu.init();" // body의 높이를 window.height에 맞춤" camp.Util.hideAddressBar();" // daum id 저장" camp.Env.uid = camp.Util.getUserId();" // 로그인 인증 쿠키 갱신 타이머 시작" camp.Function.startLoginCheckTimer();}

�������������

Page 85: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Pre-processed Code

if (true) { camp.Util.installExtAnchorHandler(); if ('ios' === 'ios') { camp.UI.navi.init(); camp.Util.hideAddressBar(); }} else { camp.UI.navi.init(); camp.UI.menu.init(); camp.Util.hideAddressBar(); camp.Env.uid = camp.Util.getUserId(); camp.Function.startLoginCheckTimer();}

아이폰 앱인 경우

�������������

Page 86: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Compiled Code

camp.Util.installExtAnchorHandler();camp.UI.navi.init();camp.Util.hideAddressBar();

camp.isApp?(camp.Util.installExtAnchorHandler(),camp.os===camp.OS.IOS&&(camp.UI.navi.init(),camp.Util.hideAddressBar())):(camp.UI.navi.init(),camp.UI.menu.init(),camp.Util.hideAddressBar(),camp.Env.uid=camp.Util.getUserId(),camp.Function.startLoginCheckTimer());

• 전처리기 처리후 컴파일된 코드 (83 byte)

• 원 소스 코드로 컴파일된 코드 (262 byte)

�������������

Page 87: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JavaScript Build Process

org-JS pre-processor

MW-JS

AND-JS

IOS-JS

google-closure

MW-bin-JS

AND-bin-JS

IOS-bin-JS

�������������

Page 88: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

JS Pre-Processor

• Esprima에 없는 것들- Comment Parser

- Semantic Analysis

�������������

Page 89: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Touch

�������������

Page 90: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Single Touch ≒ Click

touchstart

touchend

mouseover

mousemove

mousedown

mouseup

click

Touch Events

EmulatedMouse Events

�������������

Page 91: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Single Touch ≒ Click

touchstart

touchend

mouseover

mousemove

mousedown

mouseup

click

Touch Events

EmulatedMouse Events

300ms delay

�������������

Page 92: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

�������������

Page 93: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Touch 이벤트로 바꾸면 되겠네?

�������������

Page 94: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Ghost Click

• Touch 이후에 click 발생• Clickable Element

- Link

- Form Button

- onclick 이벤트 등록 element

�������������

Page 95: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Ghost Click

• Touch 이후에 click 발생• Clickable Element

- Link

- Form Button

- onclick 이벤트 등록 element

�������������

Page 96: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

Ghost Click

• event.preventDefault()로 마우스 이벤트 제거- iOS 만 가능- Android 는 불가

• 해결책- Busting Ghost Clicks - touch와 click 동시 발생 제거- 모든 Clickable element의 click 이벤트 제거하고 touch 사용- jQuery Mobile 등 라이브러리 사용

�������������

Page 97: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

touch click

�������������

Page 98: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

기타

• Galaxy S3 Browser, Android Chrome 에서는- viewport 값을 user-scalable=no 로 설정하면 300ms 지연 없음

• iOS 5 이하에서는- DOM 위치를 변경하면 touch event handler가 사라짐- 자식 element의 event handler는 유지

�������������

Page 99: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

마무리하며

�������������

Page 100: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

지금까지 언급한 내용

• 화면 영역별 구현 방법• WebView & Web-App Bridge

• Application Cache

• 버전 관리

• WebView Request Intercept

• JS 크기 줄이기

• Touch 이벤트

�������������

Page 101: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

캠프 하이브리드 앱

• 개발 속도- 상대적으로 빠르다- Mobile Web Application의 Front-End 개발 역량에 따름

• 실행 성능- WebView 성능 한계 존재- Native 성능 최적화 간과하면 안됨

• 운영- One Source Multi Use로 인해 테스트 부담 증가- 앱/웹 버전 관리의 Best Practice 찾기 쉽지 않다

�������������

Page 102: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

마지막으로

• 하이브리드 앱의 성능은 Web Application의 성능에 좌우

• 하지만, 아무리 튜닝해도 2% 부족한 느낌

• Facebook이 Native로 바꾸는 이 시점에...

�������������

Page 103: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

WebView 이해를 위한 추천 강의

• Android

- Google I/O 2012 : Android WebView

• iOS

- WWDC 2012 : Optimizing Web Content in UIWebViews and Websites on iOS

- WWDC 2012 : Debugging UIWebViews and Websites on iOS

�������������

Page 104: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

참고

• Cross-Platform Tools: Build Once and Run Everywherehttp://www.infoq.com/presentations/Cross-Platform-Mobile-Tools

• Sunspider JavaScript Benchmarkhttp://www.webkit.org/perf/sunspider/sunspider.html

• Creating Fast Buttons for Mobile Web Applicationshttps://developers.google.com/mobile/articles/fast_buttons

• Substituting local data for remote UIWebView requestshttp://www.cocoawithlove.com/2010/09/substituting-local-data-for-remote.html

• Esprima & Escodegen

�������������

Page 105: 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012

감사합니다.

�������������