24. Native to Web Call
• Android
- webview.loadUrl("http://camp.daum.net")
- webview.loadUrl("javascript:hello('world')")
• iOS
- [webview loadRequest:]
- [webview stringByEvaluatingJavaScriptFromString:]
25. 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 동일 인터페이스로 제공 위해 미사용
26. Internal URL Scheme
• Web to Native 명령 규칙
scheme://namespace/action/param1/...
ex) daumcamp://daum.camp/camp/10
27. 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);
};
28. Web to Native Callback
• Native 호출 후 응답이 필요한 경우
location.href = 'daumcamp://daum.camp/post/postComplete';
callback JS 함수
44. 주의 사항
• html 파일은 항상 캐쉬
• 업데이트는 리소스 파일이 아닌 Manifest 파일의 변경
• Application cache 제거시 http 응답은 404
- obsolete 이벤트 처리 필요
• Android 2.1은 Network 섹션에서 * 선택자 미지원
- 명시되지 않은 네트워크 요청은 모두 취소
78. JS 코드 줄이기
• Google Closure Compiler
- Minify & Code Merging
• SIMPLE_OPTIMIZATIONS
- 공백, 주석 삭제, Local 변수를 짧은 변수명으로 변경
- 도달하지 않는 코드 제거 / 미사용 변수 제거
79. JS 코드 줄이기
var isDev = false;
function hello(name) {
if (isDev) { console.log('hello called'); }
return 'Hello, ' + name;
}
hello('New user');
80. JS 코드 줄이기
var isDev = false;
function hello(name) {
if (isDev) { console.log('hello called'); }
return 'Hello, ' + name;
}
hello('New user');
SIMPLE_OPTIMIZATION
var isDev=!1;function hello(a)
{isDev&&console.log("hello called");return"Hello, "+a}
hello("New user");
81. JS 코드 줄이기
var isDev = false;
function hello(name) {
if (false) { console.log('hello called'); }
return 'Hello, ' + name;
}
hello('New user');
82. JS 코드 줄이기
var isDev = false;
function hello(name) {
if (false) { console.log('hello called'); }
return 'Hello, ' + name;
}
hello('New user');
SIMPLE_OPTIMIZATION
function hello(a){return"Hello, "+a}hello("New user");
83. JS Pre-Processor
• Idea
- 플랫폼 구분자를 상수로 치환하여 컴파일러가 제거 가능하게 하자
- 플랫폼 별로 별도의 JavaScript 파일 생성
• JavaScript Parser
- Esprima : Source Code > Abstract Syntax Tree
- Escodegen : Abstract Syntax Tree > Source Code
84. 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();
}
85. 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();
}
86. Compiled Code
• 전처리기 처리후 컴파일된 코드 (83 byte)
camp.Util.installExtAnchorHandler();camp.UI.navi.init(
);camp.Util.hideAddressBar();
• 원 소스 코드로 컴파일된 코드 (262 byte)
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.hid
eAddressBar(),camp.Env.uid=camp.Util.getUserId(),camp.
Function.startLoginCheckTimer());
94. Ghost Click
• Touch 이후에 click 발생
• Clickable Element
- Link
- Form Button
- onclick 이벤트 등록 element
95. Ghost Click
• Touch 이후에 click 발생
• Clickable Element
- Link
- Form Button
- onclick 이벤트 등록 element
96. Ghost Click
• event.preventDefault()로 마우스 이벤트 제거
- iOS 만 가능
- Android 는 불가
• 해결책
- Busting Ghost Clicks - touch와 click 동시 발생 제거
- 모든 Clickable element의 click 이벤트 제거하고 touch 사용
- jQuery Mobile 등 라이브러리 사용
100. 지금까지 언급한 내용
• 화면 영역별 구현 방법
• WebView & Web-App Bridge
• Application Cache
• 버전 관리
• WebView Request Intercept
• JS 크기 줄이기
• Touch 이벤트
101. 캠프 하이브리드 앱
• 개발 속도
- 상대적으로 빠르다
- Mobile Web Application의 Front-End 개발 역량에 따름
• 실행 성능
- WebView 성능 한계 존재
- Native 성능 최적화 간과하면 안됨
• 운영
- One Source Multi Use로 인해 테스트 부담 증가
- 앱/웹 버전 관리의 Best Practice 찾기 쉽지 않다
102. 마지막으로
• 하이브리드 앱의 성능은 Web Application의 성능에 좌우
• 하지만, 아무리 튜닝해도 2% 부족한 느낌
• Facebook이 Native로 바꾸는 이 시점에...
103. 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
104. 참고
• Cross-Platform Tools: Build Once and Run Everywhere
http://www.infoq.com/presentations/Cross-Platform-Mobile-Tools
• Sunspider JavaScript Benchmark
http://www.webkit.org/perf/sunspider/sunspider.html
• Creating Fast Buttons for Mobile Web Applications
https://developers.google.com/mobile/articles/fast_buttons
• Substituting local data for remote UIWebView requests
http://www.cocoawithlove.com/2010/09/substituting-local-data-for-remote.html
• Esprima & Escodegen