출처 : htt//cafe.naver.com/webappdev/36110
< 하이브리드앱 개발방법 >
* 출처 : 도서 '만들면서 이해하는 웹앱 & 하이브리드 앱'
< 작성자 : 정동근 >
* 직업 - 앱 개발자 및 강사 (경력 10년 이상)
* 2009년 'Visual C++ 윈도우 스킨&테마 프로그래밍' 출간
* 2009년 '자가치유 바이블' 출간
* 2011년 '따라하면서 배우는 바다 모바일 프로그래밍' 출간
* 2012년 '만들면서 이해하는 웹앱 & 하이브리드 앱' 출간
* Mail : topofsan@hotmail.com
* Tel : 010-4265-0730
0 하이브리드앱 이란.
1. 네이티브앱의 특징
- 네이티브 앱은 모바일 기기에 최적화가 되어있는 앱으로 모바일 OS 제조사에서 제공하는 개발언어를 이용하여 자신들의 제품에서만 동작되는 앱을 말하는 것.
- 안드로이드 SDK를 이용한 안드로이드 앱과 iOS SDK를 이용한 아이폰 앱이 여기에 속한다.
-
- 장점 : 편리한 개발툴과 라이브러리 제공하여 개발이 쉽고 유지가 쉽다.
모바일 기기의 고유정보을 읽고 변경할 수가 있으며 하드웨어를 제어할수 있다.
고성능의 그래픽 처리가 가능하다.
- 단점 : 플랫폼 별로 어플리케이션을 별도로 개발해야 한다.
2. 모바일 웹앱의 특징
- 컴퓨터 브라우저에서 실행되는 웹 애플리케이션을 모바일 스크린 크기로 줄인것.
- HTML, CSS, JavaScript, JSP, PHP, ASP, ASP.NET 등의 웹 기술이 사용되며 모바일 브라우저에서 실행된다.
- 장점 : 하나의 웹사이트만 개발하면 모든 스마트폰 플랫폼에서 실행 가능.
- 단점 : 서버에서 웹페이지를 불러오기 때문에 속도가 느리다. 각각의 모바일 플랫폼에서 작동되는 API를 사용할수 없다. 앱스토어 또는 마켓에 등록할수 없다.
3. 하이브리드앱의 특징
- 모바일 웹앱의 단점을 해결하기 위해서 네이티브 앱으로 모바일 웹앱을 포장하는 기술을 하이브리드하고 부른다.
- 모바일 웹앱을 하이브리드 앱으로 변환해주는 툴로는 폰갭, 앱스프레소, 티타늄 등이 있다.
- 페이지 UI와 이미지, 파일 등 실행에 필요한 모든 리소스가 어플리케이션 내부에 저장되어서 서버에서 따로 받을 필요가 없다.
- 장점 : 구동속도가 모바일 웹앱 보다 빠르다. 앱스토어나 마켓에 등록할수 있다. 하드웨어 정보를 읽고 제어할수 있다. 하나의 어플리케이션만 개발하면 다른 스마트폰 플랫폼에 동일하게 적용 가능.
- 단점 : 네이티브 앱 보다는 속도가 느리다. 플랫폼이 자체적으로 지원하는 모든 기능을 사용하지 못한다.
4. 하이브리드앱 개발에 사용되는 언어와 라이브러리
- HTML5 : html + CSS3 + jQuery
- UI 기능 프레임 워크 : jQuery Mobile, Sencha Touch
- 크로스 플랫폼 : 폰갭, 티타늄 모바일, 앱스프레소
0 CSS(Cascading Style Sheets)란?
- HTML 문서를 비주얼하게 꾸밀수 있는 스타일시트 언어.
- 텍스트의 색상과 크기, 스타일(굵기, 이탤릭 처리 등), 페이지 레이아웃과 그레이디언트, 투명도는 물론, 그 이상의 복잡한 양식까지도 구현 가능.
0 CSS 사용 예시
body {
font-size: 12px;
font-weight: bold;
font-family: Arial; }
a { font-style: italic; }
h1 a { font-style: italic; }
.loud { font-style: italic; }
#highlight { background-color: yellow; }
0 CSS로 컨텐츠에 사각형 테두리 지정
#header ul li a {
background-color: #FFFFFF;
border: 1px solid #999999;
color: #222222;
display: block;
font-size: 17px;
font-weight: bold;
padding: 12px;
text-decoration: none;
}
0 CSS로 컨텐츠 감추기
#footer { display: none; }
0 텍스트에 그림자 효과 적용
#footer { text-shadow: 0px 1px 1px #fff; }
수평오프셋, 수직오프셋, 블러반경, 색상 순
0 모서리 둥근 사각형 모양 만들기
.roundbox { border: 2px solid #555;
border-radius: 20px; }
0 jQuery Mobile과 센차터치 특성 비교
|
jQuery Mobile |
Sencha Touch |
개발 난이도 |
낮음 |
높음 |
기능의 다양성 |
보통 |
높음 |
개발 방식 |
HTML과 같은 마크업 방식 |
JavaScript와 같은 언어 방식 |
테마 특징 |
CSS, 테마롤러 도구 지원 |
Sass 기반 |
기반 스크립트 |
jQuery |
ExtJS |
지원 기기 |
폰, 태블릿 |
폰, 태블릿 |
지원 플랫폼 |
iOS, 안드로이드, 블랙베리, 바다, 윈도우폰, 팜 웹OS, 심비안 |
iOS, 안드로이드, 블랙베리 |
0 jQuery Mobile
- 모바일 웹 애플리케이션 개발을 목적으로 만들어진 자바스크립트 프레임 워크.
- 모바일에 최적화된 UI 컨트롤과 이벤트 처리, 애니메이션 효과 및 자동 네비게이션, Ajax 통신 제공.
- 주요 특징
. jQuery 기반
. html 태그와 CSS 연동
. 경량 라이브러리 : 다운로드 시간이 절감. 빠른 다운로드를 위해 별도의 CDN 서비스도 제공.
0 Button 컨트롤 예제
<script type="text/javascript" charset="utf-8">
function onButtonOk() {
document.getElementById("labelMessagge").innerHTML = "OK Button clicked.";
}
</script>
<body>
<div data-role="content" data-theme="b">
<h2><span id="labelMessagge">Press Button.</span></h2>
<input type="button" value="OK" onClick="onButtonOk();">
</div>
</body>
0 Text 에디트 컨트롤 예제
function onButtonOk() {
var textBrand = $('#brand').val();
var textPassword = $('#passwordinput').val();
}
...
<input type="text" placeholder="Brand" name="brand" id="brand" />
<input type="password" placeholder="Password" name="passwordinput" id="passwordinput" />
<textarea cols="40" rows="8" name="textarea" id="textarea">
0 Checkbox 컨트롤 예제
function onCheckBox1() {
if($('#checkbox1').is(':checked') == true ) {
}
else {
}
}
...
<label><input type="checkbox" name="checkbox1" id="checkbox1" onClick="onCheckBox1();" />Cheese</label>
0 ListView 컨트롤 예제
function onListSelected(index) {
}
...
<ul data-role="listview" id="listPet" data-inset="true" data-theme="c">
<li data-role="list-divider">Pet</li>
<li><a href="javascript:onListSelected(0)">Cat</a></li>
<li><a href="javascript:onListSelected(1)">Dog</a></li>
</ul>
0 Sencha Touch 개요
- 객체 지향적으로 설계된 자바 스크립트 기반의 프레임워크.
- 모바일 친화적인 사용자 인터페이스와 애니메이션처리, Ajax 통신 및 데이터 처리 등을 객체지향적인 API를 통해 프로그래밍 할수 있다.
- 공식 사이트 : http://www.sencha.com/products/touch/
- API 도큐먼트 : http://dev.sencha.com/deploy/touch/docs/
- 주요 특징
. 웹표준 HTML5, CSS3 기능 이용
. 향상된 터치 이벤트 : touchstart, touchend, tap, double tap, swipe, tap and hold, pinch, rotate
. 폰갭과 연동하여 네이티브앱 개발 가능.
. ExtJS 라이브러리를 기반으로 jQTouch와 Raphal를 합쳐서 작성되었으며 방대한 API를 제공.
. 강력하고 쉬운 데이터 통합 : 동일한 도메인 내의 요청은 AJAX로 통신하고, 크로스 도메인일 경우 JSONP로 통신할수 있도록 API를 제공한다. XML과 JSON은 자체 API로 파싱 가능.
. 다양한 차트 기능 제공 : Readar, Bar, Line, Stacked, Pie 차트 등.
0 Sencha Touch 2가 제공하는 MVC(Model View Controller) 패턴
가독성 있고 테스트하기 쉽고 유지보수 하기 쉬운 코딩을 지원.
-History Support : 앱 내에서 full bacck button을 지원하고 어느 위치에서든지 link로 연결 가능.
-Deep Linking : 앱의 어떤 화면에서도 deep link들을 공유 가능. 웹페이지에 링크 걸듯 사용 가능.
-Device Profiles : 어플리케이션의 UI를 폰, 태블릿 기타 디바이스의 종류에 맞게 쉽게 customizing 가능.
0 컨트롤러의 규칙(Sencha Touch)
- 앱에 있는 각각의 컨트롤러는 모두 Ext.app.Controller의 subclass 이다.
- 컨트롤러는 MyApp.controller.* namespace에 존재한다. 예를 들어 세션 컨트롤러가 있다면 그것은 MyApp.controller.Sessions 라고 불려지게 된다.
- 그리고 app/controller/Sessions.js 라는 파일로 존재하게 된다.
0 Sencha Touch 어플리케이션의 시작
Ext.application({
name: 'MyApp',
models: ['User', 'Product', 'nested.Order'],
views: ['OrderList', 'OrderDetail', 'Main'],
controllers: ['Orders'],
launch: function() {
Ext.create('MyApp.view.Main');
}
});
- Models : 앱에서 객체의 타입을 표시합니다. 예를 들어 e-커머스 앱의 경우 유저, 제품, 주문과 관련한 모델이 필요하다.
- View : 객체나 데이터들을 display하는 것을 다루는 부분.
- Controllers : 어플리케이션 내의 사용자 상호 작용을 다룹니다. 어떤 이벤트를 listening하고 핸들링 하는 것도 컨트롤러에서 하게 된다.
- Store : 앱에 데이터를 로딩하는 부분. 리스트나 데이타뷰 같은 컴포넌트들도 다룬다.
- Profile : 앱의 UI를 디바이스 종류별로 쉽게 customizing 할 수 있도록 도와 준다.
0 컨트롤러 예제(Sencha Touch)
Ext.define('MyApp.controller.Sessions', {
extend: 'Ext.app.Controller',
config: {
refs: {
loginForm: 'formpanel'
},
control: {
'formpanel button': {
tap: 'doLogin'
}
}
},
doLogin: function() {
var form = this.getLoginForm(),
values = form.getValues();
MyApp.authenticate(values);
}
});
2개의 컨트롤러 configuration이 있다. Refs는 formpanel 컴포넌트에 loginForm 프로퍼티를 할당.
Control configuration은 loginForm의 button을 tap했을때 doLogin 함수를 호출한다.
0 Stores 설명(Sencha Touch)
Store는 데이타를 다루는 매우 중요한 부분인 반면에 그 사용법은 간단하다.
Store는 Model 인스턴스의 배열.
Data-bound 컴포넌트는 DataView나 리스트 같이 Store의 각 Model 인스턴스에서 한 item을 render 한다.
Model 인스턴스가 추가되거나 삭제되는 store 이벤트가 발생하면 이 data-bound 컴포넌트가 listening 해서 update를 해주게 된다.
0 Device Profiles 예제(Sencha Touch)
Ext.application({
name: 'MyApp',
profiles: ['Phone', 'Tablet'],
});
Device Profile은 서로 다른 장치(폰, 태블릿)에 앱이 제대로 보여지고 동작할 수 있도록 해 주는 간단한 클래스. 처음에는 이 profile 없이 앱을 개발했다가 나중에 추가하면 된다.
이 프로파일을 사용하기 위해서는 프로파일(device)들의 정보를 Application에 전달 해주고 그 디바이스들을 위해 Ext.app.Profile 서브클래스를 생성하면 된다.
어플리케이션은 app/profile/Phone.js와 app/profile/Tablet.js를 로드하게 된다.
0 Tablet 프로파일에 대한 예제(Sencha Touch)
Ext.define('MyApp.profile.Tablet', {
extend: 'Ext.app.Profile',
config: {
controllers: ['Groups'],
views: ['GroupAdmin'],
models: ['MyApp.model.Group']
},
isActive: function() {
return Ext.os.is.Tablet;
}
});
isActive 함수는 이 앱이 태블릿에서 작동을 할 때 true를 return 한다.
Ext.os.is.Tablet은 iPad에서 작동하면 true를 리턴하고 다른 경우엔 false를 리턴한다. isActive에 다양한 디바이스를 넣어서 사용하면 된다.
현재의 프로파일에 대해 추가적인 model,view,controller, store들이 있다면 이는 어플리케이션이 자동적으로 아래와 같이 해당 파일을 로딩 한다.
controllers: ['Groups'] - app/controller/tablet/Groups.js
views: ['GroupAdmin'] - app/view/tablet/GroupAdmin.js
models: ['MyApp.model.Group'] - app/model/Group.js
0 Launch Process(Sencha Touch)
launch 함수는 앱이 로드되고 launch될 준비가 되어있을 때 실행 되는 함수. start up 로직을 넣을 최적의 장소이고 main view structure를 생성하기에 적합한 장소.
launch 함수와 더불어 앱의 startup 로직을 넣을 좋은 장소가 두군데 더 있다.
첫번째로 각 controller에는 init 함수를 정의할 수 있다. 이 함수는 어플리케이션 launch 함수가 시작되기 이전에 call 된다.
두번째로는 Device Profile을 사용할 경우. 각각의 Profile에는 나름대로의 launch 함수를 정의할 수 있다. 이 함수는 controller의 init 함수 이후에 그리고 application launch 함수 전에 실행 된다.
주의 할 것은 해당 Profile에 매치하는 Device에서만 이 Profile launch 함수가 실행된다는 것이다.
앱이 시작할 때 call 되는 함수들의 순서는 아래와 같다.
- Controller#init functions called
- Profile#launch function called
- Application#launch function called
- Controller#launch functions called
Profile을 사용할 때 Profile launch 함수 안에 bootup 로직을 넣는 것이 일반적이다. 왜냐하면 각 프로파일들은 startup때 실행될 필요가 있는 각기 다른 view 세트를 가지고 있기 때문이다.
0 Routing 과 History Support(Sencha Touch)
Sencha Touch는 Routing과 History를 지원니다. Kitchen Sink 같은 SDK 예제를 보면 각 화면별로 옮겨다니기 쉽게 history를 사용해서 지원한다. 특히 안드로이드의 경우 유용하다.
0 폰갭 개요
여러 스마트폰 플랫폼에서 제공하는 네이티브 SDK는 서로 개발 언어와 환경 그리고 API 가 서로 다르다.
여러 플랫폼의 SDK를 통합해서 하나의 SDK로 개발할수있도록 개발한것을 크로스 플랫폼이라고 한다.
현재 가장 유명한 스마트폰 크로스 플랫폼은 폰갭과 티타늄 모바일이다. 그외 국내에서 개발한 앱스프레소가 있다.
폰갭은 ‘하이브리드 앱(Hybrid App)’ 부류에 속한다. 하이브리드 앱이란 개발자가 플랫폼에 의존적인 기능(카메라 등의 장치 제어)만 네이티브 라이브러리로 제작하고 HTML과 자바스크립트로 네이티브 기능을 이용할수 있도록 한것.
티타늄 모바일은 자체 자바스크립트 API로 애플리케이션을 개발하면, 컴파일러가 자바스크립트 코드를 네이티브 개발 언어로 치환하는 방식.
0 폰갭에서 지원하는 디바이스 API 종류
• Accelerometer: 가속도계 사용
• Camera: 사진 촬영과 사진 앨범 탐색
• Capture: 동영상 녹화, 오디오 녹음, 정지 영상 촬영
• Compass: 나침반 기능
• Connection: 모바일 네트워크 상태 확인
• Contacts: 주소록 검색 및 연락처 추가/수정/탐색
• Device: 단말기, 운영체제 버전 등
• Events: 하드웨어 버튼 이벤트
• File: 파일 입출력, 전송
• Geolocation: 위치 정보
• Media: 음성 재생과 녹음
• Notification: 벨 소리, 진동, 시스템 알림 메시지 등
• Storage: 네이티브 DB 접근
0 폰갭의 활용도
- 지원 가능한 네이티브 앱 기능 : 90%
폰갭에서 애플리케이션에 필요한 모든 기능을 제공하지는 않는다. 추가기능을 구현하려면 네이티브 언어를 사용하거나 플러그인으로 기능확장이 필요하다.
- 지원 가능한 스마트폰 플랫폼 : 90%
안드로이드와 iOS의 렌더링 방식 차이로 불가피하게 운영체제별로 구현을 따로해야하는 부분이 있다. 또한 운영체제별로 동작에 차이가 있는 경우도 있다. 운영체제 종류를 판별하는 분기문으로 해결 가능.
- 네이티브 앱만큼 미려한 UI 개발 가능 : 70%
웹뷰 상에서 U를 표현하는 방식이므로 모바일 웹 기능의 한계를 넘는 UI는 표현할수 없다. jQuery Mobile 또는 센차터치를 사용해서 보완할수 있다.
- 성능 문제
안드로이드의 경우 UI 반응성이 iOS에 비해서 느린 경우가 많다.
iOS 4.x 버전 이하에서는 사파리 브라우저와 웹뷰에서 사용하는 자바스크립트 엔진이 서로 다르다. 사파리용 엔진이 웹뷰용 엔진 보다 2~3배 빠르다. iOS 5 이후부터는 2개 엔진이 동일하다.
0 폰갭과 앱스프레소 특성 비교
|
폰갭 |
앱스프레소 |
지명도 |
높음. 2009년 시작. |
낮음. 2011년 시작. |
기능의 다양성 |
낮음 |
높음 |
개발의 편의성 |
개발 환경 제공하지 않음. |
이클립스에 플러그인을 설치하여 자체적인 개발환경을 제공 |
실행속도 |
보통 |
초기 실행 느림. 웹뷰를 웹서버에 띄워서 렌더링하는 방식. |
문서화 완성도 |
잘되어있음. 교재도 많음. |
잘되어있음. 교재는 없음. |
오픈소스 정책 |
오픈소스 |
무료이지만 오픈소스는 아님 |
지원 플랫폼 |
iOS, 안드로이드, 블랙베리, 바다, 윈도우폰, 팜 웹OS, 심비안 |
iOS, 안드로이드 |
0 폰갭 프로젝트 개발 환경 구축(안드로이드 기준)
- 자바 개발 도구 JDK(Java Development Kit)를 설치
. 사이트 주소 : http://www.oracle.com/technetwork/java/
- 이클립스 설치
. 사이트 주소 : http://www.eclipse.org/downloads/
- 안드로이드 SDK 설치하기
. 사이트 주소 : http://developerlandroid.com/sdk/index.html
- ADT 플러그인 설치하기
. 이클립스 메뉴 [Help > Install New Software] 에서 설치
. 메뉴 [Window > Preferences] 에서 안드로이드 SDK 경로를 지정.
- 안드로이드 플랫폼 버전용 tools, platforms, extras 설치
. 메뉴 [Windows > Android SDK Manager] 에서 Android SDK Platform-tools와 Android 2.3 버전을 설치.
- 안드로이드 AVD(Android Vertual Device) 가상기기(Emulator) 생성하기
. 메뉴 [Window > AVD Manager] 에서 생성
- 폰갭 다운로드
. 사이트 주소 : http://www.phonegap.com/download
0 폰갭 프로젝트 생성하기
- 새 안드로이드 프로젝트 생성
. 메뉴 [FIle > New > Project]를 클릭하고, 팝업창에서 Android Project를 선택.
- 라이브러리 파일 복사
. /libs 폴더를 생성하고 phonegap/lib/android 디렉터리에 들어있는 cordova-x.x.x.jar 파일을 복사.
. /assets/www 폴더를 생성하고 phonegap/lib/android 디렉터리에 들어있는 cordova-x.x.x.js 파일을 복사.
. phonegap/lib/android 디렉터리에 들어있는 xml 폴더를 /res 폴더로 복사.
- 라이브러리를 프로젝트에 등록
. 프로젝트 단축메뉴 [Build Path > Configure Build Path...] 에서 cordova-x.x.x.jar 파일을 등록.
- 메인 Activity 소스파일 수정
. /src/패키지명/~.java 파일을 연다.
. 클래스의 상속확장(extends) 클래스를 Activity 에서 DroidGap로 수정
. setContentView(R.layout.main); 구문을 삭제하고 그 위치에 다음 구문을 입력한다.
super.loadUrl("file:///android_asset/www/index.html");
- 매니패스트 파일 수정
. AndroidManifest.xml 파일을 연다.
. supports-screens 과 uses-permission 구문을 추가한다.
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
- index.html 파일을 생성
. /assets/www 폴더에 파일을 생성하고 이름을 index.html 으로 지정.
. 파일을 열고 아래 내용을 추가.
<!DOCTYPE HTML>
<html>
<head>
<title>Cordova</title>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
0 진동 발생 예제(폰갭)
navigator.notification.vibrate(200);
- 시간 단위는 밀리세컨드. 200이면 0.2초.
0 버튼 1개 짜리 메세지박스 예제(폰갭)
function buttonMessageBox() {
var message = 'Do you want make Game App';
navigator.notification.alert(message, null, 'Notice!', 'OK');
}
- 매개변수
. message (String) : 사용자에게 전달하는 텍스트 내용.
. alertCallback (Function) : 메세지박스가 사라질때 이벤트 함수.
. title (String) : 메세지박스 제목 텍스트. 선택사항이며, 기본값은 'Alert' 이다.
. buttonName (String) : 버튼의 텍스트 문자열. 선택사항이며, 기본값은 'OK' 이다.
0 버튼 2개 이상 표시하는 메세지박스 예제(폰갭)
function buttonMessageBox() {
var message = "Do you want make Game App";
navigator.notification.confirm(message, onConfirm, "Notice", "OK,Cancel,Retry");
}
function onConfirm(button) {
var result = 'You selected button ' + button;
}
0 단말기 정보 구하기(폰갭)
- device.name : 단말기의 제품명이나 모델명을 문자열 형식으로 제공
- device.phonegaep : 웹앱에 탑재한 폰갭 API의 버전 정보를 제공
- device.platform : 단말기의 운영체제 이름을 알려준다.
- device.version 속성 : 단말기 운영체제 버전 정보를 제공.
- device.uuid : 단말기의 일련번호(UUID - Universally Unique Identifier) 정보를 제공.