SlideShare a Scribd company logo
1 of 105
Download to read offline
캠프앱 개발 사례를 통해 본

하이브리드앱 어디까지
    다음 커뮤니케이션
       유승근
오늘 얘기할 순서 ...

• 개발 전
 - Cross Platform
 - 캠프 하이브리드

• 개발 중
 - 화면 영역별 구현 방법
 - WebView & Web-App Bridge
 - Application Cache
 - 버전 관리
오늘 얘기할 순서

• 오픈 후(최적화)
 - WebView Request Intercept
 - JS 크기 줄이기
 - Touch 이벤트

• 마무리하며
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
Write Once, Run Anywhere
Cross Platform Tools

   • 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
캠프 하이브리드앱




  Web App
캠프 하이브리드앱




  Web App   Native
캠프 하이브리드앱




  Web App   Hybrid
            Native
캠프 하이브리드앱

• 기대                     • 우려
- One Source Multi Use   - 시스템 복잡도 증가
- 상대적으로 업데이트 용이          - 웹과 앱의 배포 시점 동기화
- Web UI 구현 문제 해결        - WebView 성능 문제
개발 시작!
Native / Web
무엇으로 구현해야 하나?
Native 영역

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

• 사용자 입력 Form
 - 이미지 업로드
 - 날짜 입력 등 복잡한 입력 요소들

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

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

• 사용자 입력 Form
 - 이미지 업로드
 - 날짜 입력 등 복잡한 입력 요소들

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

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

• 사용자 입력 Form
 - 이미지 업로드
 - 날짜 입력 등 복잡한 입력 요소들

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

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

• 사용자 입력 Form
 - 이미지 업로드
 - 날짜 입력 등 복잡한 입력 요소들

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

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

• 사용자 입력 Form
 - 이미지 업로드
 - 날짜 입력 등 복잡한 입력 요소들

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




 iOS 6
   webview.keyboardDisplayRequiresUserAction = NO;
WebView
WebView

• Android
 - WebView
 - WebSettings
 - WebChromeClient
 - WebViewClient

• iOS
 - UIWebView
 - UIWebViewDelegate
Browser                   WebView




          Android 4.0.4
Safari           UIWebView




         iOS 6
Native to Web Call

• Android
 - webview.loadUrl("http://camp.daum.net")
 - webview.loadUrl("javascript:hello('world')")

• iOS
 - [webview loadRequest:]
 - [webview stringByEvaluatingJavaScriptFromString:]
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 동일 인터페이스로 제공 위해 미사용
Internal URL Scheme

• Web to Native 명령 규칙

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

ex) daumcamp://daum.camp/camp/10
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);
 };
Web to Native Callback

 • Native 호출 후 응답이 필요한 경우
location.href = 'daumcamp://daum.camp/post/postComplete';


                                         callback JS 함수
Cookie

• Android
 - CookieManager
 - CookieSyncManager

• iOS
 - NSHTTPCookie
 - NSHTTPCookieStorage

• Cookie 관리자는 Singleton 객체
Application Cache
Application Cache

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

 <script>

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

 </script> ...

 </html>
Application Cache Manifest

 CACHE MANIFEST
 # 2012-06-18:v3

 CACHE:
 index.html
 css/style.css

 FALLBACK:
 / /offline.html

 NETWORK:
 *
Application Cache - Events

checking   downloading           progress...   cached    최초실행


checking    noupdate        변경없음


checking   downloading           progress...   updateready   앱캐쉬 업데이트


checking    obsolete        앱캐쉬 제거


checking    •••          error         에러
checking
checking   downloading
checking   downloading   progress...
checking   downloading   progress...   updateready




appCache.swapCache();
window.reload();
checking   downloading   progress...   updateready
이미지 해상도 대응

  MDPI       HDPI
이미지 해상도 대응

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


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
이미지 해상도 대응


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

String* pixelRatio = @"1";         iOS 4 이상인지 확인


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

// setCookie pixelRatio
이미지 해상도 대응

#set ($IMG_TYPE = "480")             Velocity Template
#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
주의 사항

• html 파일은 항상 캐쉬
• 업데이트는 리소스 파일이 아닌 Manifest 파일의 변경
• Application cache 제거시 http 응답은 404
 - obsolete   이벤트 처리 필요

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


              Web   1.0.1
1.0.0   App   Web   1.0.0


              Web   1.0.1


              Web   1.0.2
1.0.0   App   Web   1.0.0


              Web   1.0.1


              Web   1.0.2


1.0.1   App   Web   1.0.3
1.0.0   App   Web   1.0.0


              Web   1.0.1


              Web   1.0.2


1.0.1   App   Web   1.0.3


              Web   1.0.4
1.0.0   App   Web   1.0.0


              Web   1.0.1

                            Mapping
              Web   1.0.2   Table


1.0.1   App   Web   1.0.3


              Web   1.0.4
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>
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>
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>      Android Version
 "   " " <prop key="[1.0.4,)">1.0.10-p6</prop>              Mapping
 "   " </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>
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>   iPhone Version
 "   " " <prop key="[1.0.2,)">1.0.10-p6</prop>             Mapping
 "   " </props>
 "   </property>

 </bean>
Version Mapping Table
 <bean ... >

 "   <property name="version" value="1.0.10-p6"/>
            App Version Range         Web Version
 "   <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 to Web URL



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

ex) http://camp.daum.net/app/ios/1.0.2/...
고민거리

• 현재 JS/CSS 만 버전 관리 대상
• HTML, Manifest 파일도 버전관리 해야 하지 않을까?
오픈 후...
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
SunSpider JavaScript
    Benchmark
Android

                             Browser       WebView


                   7,000



                   5,250
running time(ms)




                   3,500



                   1,750



                      0
                             Android 2.3     Android 4.0
iOS

                                 Safari           WebView

                   12,000



                    9,000
running time(ms)




                    6,000



                    3,000



                       0
                            iOS 4.3       iOS 5             iOS 6
장인은 도구를 탓하지 않는다.
Web Application 최적화
로딩 과정

                  onDOMContentLoaded
Load start                             onLoad     onHashchange


             css, js load/parse/eval


                                         init()


                                                       router / data load / render



                         Boot                                  View
로딩 과정

                  onDOMContentLoaded
Load start                             onLoad     onHashchange


             css, js load/parse/eval


                                         init()


                                                       router / data load / render
                                       App에서는 지속적 발생

                         Boot                                  View
로딩 중 구멍 찾기
Load Start


                         CSS            application cache

 웹앱 실행시 필수 정보
그러나 앱에도 존재하는 정보
                  <script src="/env">   no-cache

                       baselib.js
                        camp.js
                                        application cache


                         init()


                     View Render
Script Blocking




  Script Loading
Script Blocking




  Script Loading   API call
Script Blocking




  Script Loading   API call   Complete
Script Blocking




  Script Loading
Web
Script Blocking
                   Load Start


                      CSS       app cache


                    <script
                                no-cache
                  src="/env">


                   baselib.js   app cache
                    camp.js


                     init()


                  View Render
Web
Script Blocking
                       Load Start

          App             CSS       app cache

        Intercept
                        <script
                                    no-cache
                      src="/env">
      Http Response
                       baselib.js
   App에 있는 정보 바탕으로      camp.js
                                    app cache

         응답 생성
                         init()


                      View Render
WebView Request Intercept

• Android
 - webViewClient.shouldInterceptRequest()

 - API Level 11 - Android 3.0 이상 지원

• iOS
 - NSURLCache class의
   cachedResponseForRequest:   method override
 - [NSURLCache setSharedURLCache:]
JS 코드 줄이기
JS 코드 줄이기

• Google Closure Compiler
 - Minify & Code Merging

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

 var isDev = false;

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

 hello('New user');
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");
JS 코드 줄이기

 var isDev = false;

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

 hello('New user');
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");
JS Pre-Processor

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

• JavaScript Parser
  - Esprima : Source Code > Abstract Syntax Tree
  - Escodegen : Abstract Syntax Tree > Source Code
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();
 }
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();
 }
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());
JavaScript Build Process


                                                   MW-bin-
                         MW-JS
                                                     JS




                                                   AND-bin-
org-JS   pre-processor   AND-JS   google-closure
                                                     JS




                         IOS-JS                    IOS-bin-JS
JS Pre-Processor

• Esprima에 없는 것들
 - Comment Parser
 - Semantic Analysis
Touch
Single Touch     ≒ Click
                touchstart
 Touch Events
                 touchend



                mouseover


                mousemove

  Emulated      mousedown
 Mouse Events
                 mouseup


                   click
Single Touch     ≒ Click
                touchstart
 Touch Events
                 touchend

                             300ms delay
                mouseover


                mousemove

  Emulated      mousedown
 Mouse Events
                 mouseup


                   click
캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 | Devon 2012
Touch 이벤트로 바꾸면 되겠네?
Ghost Click

• Touch 이후에 click 발생
• Clickable Element
 - Link
 - Form Button
 - onclick 이벤트 등록 element
Ghost Click

• Touch 이후에 click 발생
• Clickable Element
 - Link
 - Form Button
 - onclick 이벤트 등록 element
Ghost Click

• event.preventDefault()로 마우스 이벤트 제거

 - iOS 만 가능
 - Android 는 불가

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

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

• iOS 5 이하에서는
 - DOM 위치를 변경하면 touch event handler가 사라짐
 - 자식 element의 event handler는 유지
마무리하며
지금까지 언급한 내용

• 화면 영역별 구현 방법
• WebView & Web-App Bridge
• Application Cache
• 버전 관리
• WebView Request Intercept
• JS 크기 줄이기
• Touch 이벤트
캠프 하이브리드 앱

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

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

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

• 하이브리드 앱의 성능은 Web Application의 성능에 좌우
• 하지만, 아무리 튜닝해도 2% 부족한 느낌
• Facebook이 Native로 바꾸는 이 시점에...
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
참고

• 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
감사합니다.

More Related Content

What's hot

목적에 맞게 Angular, React, Vue
목적에 맞게 Angular, React, Vue목적에 맞게 Angular, React, Vue
목적에 맞게 Angular, React, VueGunhee Lee
 
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화흥래 김
 
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기Chang W. Doh
 
웹 Front-End 실무 이야기
웹 Front-End 실무 이야기웹 Front-End 실무 이야기
웹 Front-End 실무 이야기JinKwon Lee
 
Single-page Application
Single-page ApplicationSingle-page Application
Single-page ApplicationSangmin Yoon
 
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기Chang W. Doh
 
모바일 무한 스크롤 개발
모바일 무한 스크롤 개발모바일 무한 스크롤 개발
모바일 무한 스크롤 개발NAVER D2
 
웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁WebFrameworks
 
프로그레시브 웹앱(Pwa)
프로그레시브 웹앱(Pwa)프로그레시브 웹앱(Pwa)
프로그레시브 웹앱(Pwa)Woncheol Lee
 
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...Sang Seok Lim
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angularredribbon1307
 
구글앱엔진 스터디
구글앱엔진 스터디구글앱엔진 스터디
구글앱엔진 스터디소라 정
 
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망Sang Seok Lim
 
프로그레시브 웹앱이란? - Progressive Web Apps
프로그레시브 웹앱이란? - Progressive Web Apps프로그레시브 웹앱이란? - Progressive Web Apps
프로그레시브 웹앱이란? - Progressive Web AppsGihyo Joshua Jang
 
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신Sungwoo Choo
 
Ionic으로 모바일앱 만들기 #1
Ionic으로 모바일앱 만들기 #1Ionic으로 모바일앱 만들기 #1
Ionic으로 모바일앱 만들기 #1성일 한
 
하이브리드앱 아키텍쳐 및 개발 사례
하이브리드앱 아키텍쳐 및 개발 사례하이브리드앱 아키텍쳐 및 개발 사례
하이브리드앱 아키텍쳐 및 개발 사례동수 장
 
NAVER의 웹/HTML5환경 대응 현황
NAVER의 웹/HTML5환경 대응 현황NAVER의 웹/HTML5환경 대응 현황
NAVER의 웹/HTML5환경 대응 현황NAVER Engineering
 

What's hot (20)

목적에 맞게 Angular, React, Vue
목적에 맞게 Angular, React, Vue목적에 맞게 Angular, React, Vue
목적에 맞게 Angular, React, Vue
 
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화
[JCO 컨퍼런스] 웹사이트 Front-End 성능 최적화
 
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기
 
iOS9 소개
iOS9 소개iOS9 소개
iOS9 소개
 
웹 Front-End 실무 이야기
웹 Front-End 실무 이야기웹 Front-End 실무 이야기
웹 Front-End 실무 이야기
 
Single-page Application
Single-page ApplicationSingle-page Application
Single-page Application
 
현실적 PWA
현실적 PWA현실적 PWA
현실적 PWA
 
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
 
모바일 무한 스크롤 개발
모바일 무한 스크롤 개발모바일 무한 스크롤 개발
모바일 무한 스크롤 개발
 
웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁웹-프론트엔드 프레임워크를 고르기 위한 팁
웹-프론트엔드 프레임워크를 고르기 위한 팁
 
프로그레시브 웹앱(Pwa)
프로그레시브 웹앱(Pwa)프로그레시브 웹앱(Pwa)
프로그레시브 웹앱(Pwa)
 
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...
The comprehensive guide for optimizing the performance of mobile HTML5 Web ap...
 
응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular응답하라 반응형웹 - 4. angular
응답하라 반응형웹 - 4. angular
 
구글앱엔진 스터디
구글앱엔진 스터디구글앱엔진 스터디
구글앱엔진 스터디
 
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망
HTML5 관점에서 본 2014 모바일 웹 앱 개발 동향과 사례 및 발전 방향 전망
 
프로그레시브 웹앱이란? - Progressive Web Apps
프로그레시브 웹앱이란? - Progressive Web Apps프로그레시브 웹앱이란? - Progressive Web Apps
프로그레시브 웹앱이란? - Progressive Web Apps
 
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신
NAVER 오픈세미나 대구 (2014.08.01) - 오픈소스 라이브러리를 활용한 네이티브 어플리케이션의 데이터 저장과 통신
 
Ionic으로 모바일앱 만들기 #1
Ionic으로 모바일앱 만들기 #1Ionic으로 모바일앱 만들기 #1
Ionic으로 모바일앱 만들기 #1
 
하이브리드앱 아키텍쳐 및 개발 사례
하이브리드앱 아키텍쳐 및 개발 사례하이브리드앱 아키텍쳐 및 개발 사례
하이브리드앱 아키텍쳐 및 개발 사례
 
NAVER의 웹/HTML5환경 대응 현황
NAVER의 웹/HTML5환경 대응 현황NAVER의 웹/HTML5환경 대응 현황
NAVER의 웹/HTML5환경 대응 현황
 

Viewers also liked

[제너시스템즈]Biz com 소개자료
[제너시스템즈]Biz com 소개자료[제너시스템즈]Biz com 소개자료
[제너시스템즈]Biz com 소개자료xenersystems
 
[D2 오픈세미나]2.모바일웹디버깅
[D2 오픈세미나]2.모바일웹디버깅[D2 오픈세미나]2.모바일웹디버깅
[D2 오픈세미나]2.모바일웹디버깅NAVER D2
 
[D2 오픈세미나]4.네이티브앱저장통신
[D2 오픈세미나]4.네이티브앱저장통신[D2 오픈세미나]4.네이티브앱저장통신
[D2 오픈세미나]4.네이티브앱저장통신NAVER D2
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅NAVER D2
 
[D2 오픈세미나]1.무한스크롤성능개선
[D2 오픈세미나]1.무한스크롤성능개선[D2 오픈세미나]1.무한스크롤성능개선
[D2 오픈세미나]1.무한스크롤성능개선NAVER D2
 
서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해중선 곽
 
웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화NAVER D2
 

Viewers also liked (7)

[제너시스템즈]Biz com 소개자료
[제너시스템즈]Biz com 소개자료[제너시스템즈]Biz com 소개자료
[제너시스템즈]Biz com 소개자료
 
[D2 오픈세미나]2.모바일웹디버깅
[D2 오픈세미나]2.모바일웹디버깅[D2 오픈세미나]2.모바일웹디버깅
[D2 오픈세미나]2.모바일웹디버깅
 
[D2 오픈세미나]4.네이티브앱저장통신
[D2 오픈세미나]4.네이티브앱저장통신[D2 오픈세미나]4.네이티브앱저장통신
[D2 오픈세미나]4.네이티브앱저장통신
 
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅[D2 오픈세미나]5.robolectric 안드로이드 테스팅
[D2 오픈세미나]5.robolectric 안드로이드 테스팅
 
[D2 오픈세미나]1.무한스크롤성능개선
[D2 오픈세미나]1.무한스크롤성능개선[D2 오픈세미나]1.무한스크롤성능개선
[D2 오픈세미나]1.무한스크롤성능개선
 
서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해서버 성능에 대한 정의와 이해
서버 성능에 대한 정의와 이해
 
웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화웨일브라우저 성능 및 메모리 최적화
웨일브라우저 성능 및 메모리 최적화
 

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

Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Appsjungkees
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Jiam Seo
 
도구를 활용한 더 나은 웹 개발: Yeoman
도구를 활용한 더 나은 웹 개발: Yeoman도구를 활용한 더 나은 웹 개발: Yeoman
도구를 활용한 더 나은 웹 개발: YeomanJae Sung Park
 
Node.js
Node.jsNode.js
Node.jsymtech
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptxwonyong hwang
 
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]WSConf.
 
[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기NAVER D2
 
원모먼트 Vue js 적용기
원모먼트 Vue js 적용기원모먼트 Vue js 적용기
원모먼트 Vue js 적용기우현 김
 
Internship backend
Internship backendInternship backend
Internship backendYein Sim
 
Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나JeongHun Byeon
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발지수 윤
 
HTML5 로 iPhone App 만들기
HTML5 로 iPhone App 만들기HTML5 로 iPhone App 만들기
HTML5 로 iPhone App 만들기정혁 권
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)LanarkSeung
 

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

Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Apps
 
okspring3x
okspring3xokspring3x
okspring3x
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기
 
Nodejs express
Nodejs expressNodejs express
Nodejs express
 
What's new in IE11
What's new in IE11What's new in IE11
What's new in IE11
 
Html5 performance
Html5 performanceHtml5 performance
Html5 performance
 
도구를 활용한 더 나은 웹 개발: Yeoman
도구를 활용한 더 나은 웹 개발: Yeoman도구를 활용한 더 나은 웹 개발: Yeoman
도구를 활용한 더 나은 웹 개발: Yeoman
 
Node.js
Node.jsNode.js
Node.js
 
Vue.js 기초 실습.pptx
Vue.js 기초 실습.pptxVue.js 기초 실습.pptx
Vue.js 기초 실습.pptx
 
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]
조은 - AMP PWA 101 [WSConf.Seoul.2017. Vol.2]
 
7. html5 api
7. html5 api7. html5 api
7. html5 api
 
[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기
 
원모먼트 Vue js 적용기
원모먼트 Vue js 적용기원모먼트 Vue js 적용기
원모먼트 Vue js 적용기
 
Internship backend
Internship backendInternship backend
Internship backend
 
Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나Front-end Development Process - 어디까지 개선할 수 있나
Front-end Development Process - 어디까지 개선할 수 있나
 
One-day-codelab
One-day-codelabOne-day-codelab
One-day-codelab
 
요즘웹개발
요즘웹개발요즘웹개발
요즘웹개발
 
Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발Jenkins를 활용한 javascript 개발
Jenkins를 활용한 javascript 개발
 
HTML5 로 iPhone App 만들기
HTML5 로 iPhone App 만들기HTML5 로 iPhone App 만들기
HTML5 로 iPhone App 만들기
 
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
Create-React-App으로 SSR을 구현하며 배운 점 (feat. TypeScript)
 

More from Daum DNA

Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum DNA
 
Daum OAuth 2.0
Daum OAuth 2.0Daum OAuth 2.0
Daum OAuth 2.0Daum DNA
 
Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum DNA
 
Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum DNA
 
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)Daum DNA
 
Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum DNA
 
Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum DNA
 
FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표Daum DNA
 
웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민Daum DNA
 
반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석Daum DNA
 
Daum devday 13 [bap]
Daum devday 13  [bap]Daum devday 13  [bap]
Daum devday 13 [bap]Daum DNA
 
Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DNA
 
Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DNA
 
Daum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DNA
 
Daum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DNA
 
Daum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DNA
 
Daum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DNA
 
Daum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DNA
 
Daum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DNA
 
Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum DNA
 

More from Daum DNA (20)

Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
Daum의 개방형 기술 전략 및 자바 기술 로드맵(2007)
 
Daum OAuth 2.0
Daum OAuth 2.0Daum OAuth 2.0
Daum OAuth 2.0
 
Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)Daum 음성인식 API (김한샘)
Daum 음성인식 API (김한샘)
 
Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)Daum 검색/지도 API (이정주)
Daum 검색/지도 API (이정주)
 
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)오픈 API 활용방법(Daum 사례 중심, 윤석찬)
오픈 API 활용방법(Daum 사례 중심, 윤석찬)
 
Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)Daum 티스토리 API (천정환)
Daum 티스토리 API (천정환)
 
Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)Daum 로그인 API (함태윤)
Daum 로그인 API (함태윤)
 
FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표FT직군의 현재와 미래 - 홍윤표
FT직군의 현재와 미래 - 홍윤표
 
웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민웹접근성과 장애인 차별 금지법 - 장성민
웹접근성과 장애인 차별 금지법 - 장성민
 
반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석반응형 웹 디자인은 만능인가? - 신현석
반응형 웹 디자인은 만능인가? - 신현석
 
Daum devday 13 [bap]
Daum devday 13  [bap]Daum devday 13  [bap]
Daum devday 13 [bap]
 
Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해Daum DevDay 13-힐링이 필요해
Daum DevDay 13-힐링이 필요해
 
Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리Daum DevDay 13 - 마음의 소리
Daum DevDay 13 - 마음의 소리
 
Daum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBraceDaum DevDay 13 - OpenBrace
Daum DevDay 13 - OpenBrace
 
Daum DevDay 13 - Ogangjang
Daum DevDay 13 - OgangjangDaum DevDay 13 - Ogangjang
Daum DevDay 13 - Ogangjang
 
Daum DevDay 13 - Mook
Daum DevDay 13 - MookDaum DevDay 13 - Mook
Daum DevDay 13 - Mook
 
Daum DevDay 13 - Moonlight
Daum DevDay 13 - MoonlightDaum DevDay 13 - Moonlight
Daum DevDay 13 - Moonlight
 
Daum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-OutDaum DevDay 13 - In-N-Out
Daum DevDay 13 - In-N-Out
 
Daum DevDay 13 - i-DF
Daum DevDay 13 - i-DFDaum DevDay 13 - i-DF
Daum DevDay 13 - i-DF
 
Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012Daum 키노트 | Devon 2012
Daum 키노트 | Devon 2012
 

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

  • 1. 캠프앱 개발 사례를 통해 본 하이브리드앱 어디까지 다음 커뮤니케이션 유승근
  • 2. 오늘 얘기할 순서 ... • 개발 전 - Cross Platform - 캠프 하이브리드 • 개발 중 - 화면 영역별 구현 방법 - WebView & Web-App Bridge - Application Cache - 버전 관리
  • 3. 오늘 얘기할 순서 • 오픈 후(최적화) - WebView Request Intercept - JS 크기 줄이기 - Touch 이벤트 • 마무리하며
  • 5. Write Once, Run Anywhere
  • 6. Cross Platform Tools • 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
  • 8. 캠프 하이브리드앱 Web App Native
  • 9. 캠프 하이브리드앱 Web App Hybrid Native
  • 10. 캠프 하이브리드앱 • 기대 • 우려 - One Source Multi Use - 시스템 복잡도 증가 - 상대적으로 업데이트 용이 - 웹과 앱의 배포 시점 동기화 - Web UI 구현 문제 해결 - WebView 성능 문제
  • 12. Native / Web 무엇으로 구현해야 하나?
  • 13. Native 영역 • 레이아웃 - 네비게이션바, 메뉴 - position: fixed • 사용자 입력 Form - 이미지 업로드 - 날짜 입력 등 복잡한 입력 요소들 • 다음 공통 컴포넌트 - 로그인, 지도, 이미지뷰어
  • 14. Native 영역 • 레이아웃 - 네비게이션바, 메뉴 - position: fixed • 사용자 입력 Form - 이미지 업로드 - 날짜 입력 등 복잡한 입력 요소들 • 다음 공통 컴포넌트 - 로그인, 지도, 이미지뷰어
  • 15. Native 영역 • 레이아웃 - 네비게이션바, 메뉴 - position: fixed • 사용자 입력 Form - 이미지 업로드 - 날짜 입력 등 복잡한 입력 요소들 • 다음 공통 컴포넌트 - 로그인, 지도, 이미지뷰어
  • 16. Native 영역 • 레이아웃 - 네비게이션바, 메뉴 - position: fixed • 사용자 입력 Form - 이미지 업로드 - 날짜 입력 등 복잡한 입력 요소들 • 다음 공통 컴포넌트 - 로그인, 지도, 이미지뷰어
  • 17. Native 영역 • 레이아웃 - 네비게이션바, 메뉴 - position: fixed • 사용자 입력 Form - 이미지 업로드 - 날짜 입력 등 복잡한 입력 요소들 • 다음 공통 컴포넌트 - 로그인, 지도, 이미지뷰어
  • 19. input Focus iOS 6 webview.keyboardDisplayRequiresUserAction = NO;
  • 21. WebView • Android - WebView - WebSettings - WebChromeClient - WebViewClient • iOS - UIWebView - UIWebViewDelegate
  • 22. Browser WebView Android 4.0.4
  • 23. Safari UIWebView iOS 6
  • 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 함수
  • 29. Cookie • Android - CookieManager - CookieSyncManager • iOS - NSHTTPCookie - NSHTTPCookieStorage • Cookie 관리자는 Singleton 객체
  • 31. Application Cache <html manifest="appcache.manifest"> ... <script> applicationCache.addEventListener('updateready', function(e) { applicationCache.swapCache(); window.reload(); } ); </script> ... </html>
  • 32. Application Cache Manifest CACHE MANIFEST # 2012-06-18:v3 CACHE: index.html css/style.css FALLBACK: / /offline.html NETWORK: *
  • 33. Application Cache - Events checking downloading progress... cached 최초실행 checking noupdate 변경없음 checking downloading progress... updateready 앱캐쉬 업데이트 checking obsolete 앱캐쉬 제거 checking ••• error 에러
  • 35. checking downloading
  • 36. checking downloading progress...
  • 37. checking downloading progress... updateready appCache.swapCache(); window.reload();
  • 38. checking downloading progress... updateready
  • 40. 이미지 해상도 대응 • Cookie를 이용한 해결책 - Native에서 해상도 정보 취득 - 로딩 전 WebView에 해상도 정보를 cookie로 굽기 - manifest 파일은 cookie 값을 바탕으로 동적 생성
  • 41. 이미지 해상도 대응 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
  • 42. 이미지 해상도 대응 BOOL ios4 = [[UIScreen mainScreen] respondsToSelector: @selector(displayLinkWithTarget:selector:)]; String* pixelRatio = @"1"; iOS 4 이상인지 확인 if (ios4 && [UIScreen mainScreen].scale == 2.0) { // Retina display pixelRatio = @"2"; } // setCookie pixelRatio
  • 43. 이미지 해상도 대응 #set ($IMG_TYPE = "480") Velocity Template #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
  • 44. 주의 사항 • html 파일은 항상 캐쉬 • 업데이트는 리소스 파일이 아닌 Manifest 파일의 변경 • Application cache 제거시 http 응답은 404 - obsolete 이벤트 처리 필요 • Android 2.1은 Network 섹션에서 * 선택자 미지원 - 명시되지 않은 네트워크 요청은 모두 취소
  • 46. 1.0.0 App Web 1.0.0
  • 47. 1.0.0 App Web 1.0.0 Web 1.0.1
  • 48. 1.0.0 App Web 1.0.0 Web 1.0.1 Web 1.0.2
  • 49. 1.0.0 App Web 1.0.0 Web 1.0.1 Web 1.0.2 1.0.1 App Web 1.0.3
  • 50. 1.0.0 App Web 1.0.0 Web 1.0.1 Web 1.0.2 1.0.1 App Web 1.0.3 Web 1.0.4
  • 51. 1.0.0 App Web 1.0.0 Web 1.0.1 Mapping Web 1.0.2 Table 1.0.1 App Web 1.0.3 Web 1.0.4
  • 52. 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>
  • 53. 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>
  • 54. 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> Android Version " " " <prop key="[1.0.4,)">1.0.10-p6</prop> Mapping " " </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>
  • 55. 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> iPhone Version " " " <prop key="[1.0.2,)">1.0.10-p6</prop> Mapping " " </props> " </property> </bean>
  • 56. Version Mapping Table <bean ... > " <property name="version" value="1.0.10-p6"/> App Version Range Web Version " <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>
  • 57. App to Web URL http://camp.daum.net/app/{platform}/{version}/... ex) http://camp.daum.net/app/ios/1.0.2/...
  • 58. 고민거리 • 현재 JS/CSS 만 버전 관리 대상 • HTML, Manifest 파일도 버전관리 해야 하지 않을까?
  • 61. SunSpider JavaScript Benchmark
  • 62. Android Browser WebView 7,000 5,250 running time(ms) 3,500 1,750 0 Android 2.3 Android 4.0
  • 63. iOS Safari WebView 12,000 9,000 running time(ms) 6,000 3,000 0 iOS 4.3 iOS 5 iOS 6
  • 66. 로딩 과정 onDOMContentLoaded Load start onLoad onHashchange css, js load/parse/eval init() router / data load / render Boot View
  • 67. 로딩 과정 onDOMContentLoaded Load start onLoad onHashchange css, js load/parse/eval init() router / data load / render App에서는 지속적 발생 Boot View
  • 69. Load Start CSS application cache 웹앱 실행시 필수 정보 그러나 앱에도 존재하는 정보 <script src="/env"> no-cache baselib.js camp.js application cache init() View Render
  • 70. Script Blocking Script Loading
  • 71. Script Blocking Script Loading API call
  • 72. Script Blocking Script Loading API call Complete
  • 73. Script Blocking Script Loading
  • 74. Web Script Blocking Load Start CSS app cache <script no-cache src="/env"> baselib.js app cache camp.js init() View Render
  • 75. Web Script Blocking Load Start App CSS app cache Intercept <script no-cache src="/env"> Http Response baselib.js App에 있는 정보 바탕으로 camp.js app cache 응답 생성 init() View Render
  • 76. WebView Request Intercept • Android - webViewClient.shouldInterceptRequest() - API Level 11 - Android 3.0 이상 지원 • iOS - NSURLCache class의 cachedResponseForRequest: method override - [NSURLCache setSharedURLCache:]
  • 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());
  • 87. JavaScript Build Process MW-bin- MW-JS JS AND-bin- org-JS pre-processor AND-JS google-closure JS IOS-JS IOS-bin-JS
  • 88. JS Pre-Processor • Esprima에 없는 것들 - Comment Parser - Semantic Analysis
  • 89. Touch
  • 90. Single Touch ≒ Click touchstart Touch Events touchend mouseover mousemove Emulated mousedown Mouse Events mouseup click
  • 91. Single Touch ≒ Click touchstart Touch Events touchend 300ms delay mouseover mousemove Emulated mousedown Mouse Events mouseup click
  • 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 등 라이브러리 사용
  • 97. touch click
  • 98. 기타 • Galaxy S3 Browser, Android Chrome 에서는 - viewport 값을 user-scalable=no 로 설정하면 300ms 지연 없음 • iOS 5 이하에서는 - DOM 위치를 변경하면 touch event handler가 사라짐 - 자식 element의 event handler는 유지
  • 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