5. 언제 네이티브 앱을 만들어야 할까요?
VS
디바이스 제어 (카메라 등)가 필요하다
오프라인 사용이 필요하다
플랫폼별로 최적 UI를 만들고 싶다
애니메이션 사용량이 많다
포맷 변경이 갑자기/자주 일어나지 않는다
내용 포맷 변경이 자주 있다
다양한 플랫폼에서 사용하고 싶다
심사를 기다리지 않고 업데이트해야 한다
네이티브앱 하이브리드앱
6. 일부분만 웹뷰를 사용하여 만들기도 합니다
• 공지사항, 고객문의 등의 여러 앱에서 사용하는 공
통기능을 웹뷰로 만드는 경우
• 컨텐츠의 자유도가 너무 높아서 웹뷰를 사용하여
내용을 구현하는 경우 (E-book 등)
• 지불결제 서비스 등 타사 연동을 위한 경우
14. Demo App “기획서”
…
영화목록 영화상세
여러분의 기획자가 이런걸 만들어달라고 합니다
• 최근 개봉한 순서대로 영화를 보여주세요.
• 영화 상세정보도 보여주세요.
• 오프라인 모드에서도 최근 데이터 기반으로 보여주세요.
• 앱 실행중 데이터에 번동이 있으면 바꿔 주세요.
• 데이터를 덜썼으면 좋겠어요
• 배터리 적게 썼으면 좋겠어요
• “ CGV앱”처럼 만들어주세요.
15. 일반적인 네이티브 앱
View Logic
Request
Response
SQLite
Event
3G/LTE
WiFi
서버
화살표가 있는 구간에서 모두 해결해야 할 문제가 하나 이상씩 있습니다.
16. 모바일 네트워크
• 분당에서 대구까지 KTX를 타고 이동했다. 과연 IP가 바뀔까?
• 단말기 전원을 껐다 켰다. IP가 바뀔까?
• 미국에 도착하여 비행기에서 내리자마자 로밍을 켰다. 미국에 할당된 IP를 받아올까?
• 데이터통신중에 전화가 걸려오면 통신중인 세션이 끊어질까?
(3G Fallback)
No
Maybe
No
No
이런 질문 해 보셨나요?
17. LTE 모바일 네트워크
단말기 기지국 패킷
게이트웨이
터널관리
인증
핸드오버
앵커PPP Tunnel
UE : User Equipment
eNodeB : Evolved Node B
S-GW : Servicing Gateway
PDN-GW : Packet Data Network GW
MME : Mobile Management Entity
HSS : Home Subscriber Server
PCRF : Policy and Charging Rule Function
ePDG : Evolved Packet Data Gateway
18. 바퀴를 새로 발명할 필요는 없습니다.
오픈소스 라이브러리를 최대한 활용하면
안정적이면서도 빠른 네이티브 앱 개발이 가능합니다.
20. 한국 무선 통계
0
50
100
150
LTE 3G WIFI
0
10
20
30
40
50
LTE 3G WIFI
DN (Mbps) UP (Mbps)
자료: 벤치비, 미래창조과학부
ms
Mbps
지연시간 (Latency)
전송속도
0
10
20
30
40
50
60
CDMA
3G
LTE
WIBRO
백만명 국내 무선통신 사용자 현황
“30%의 사용자는 아직도 3G망을 사용 중”
21. 믿을만하지 못한 무선 네트워크 환경 + 믿을만하지 못한 HTTP 라이브러리 = ?!
안드로이드는 기본적으로 두 가지의 HTTP 클라이언트를 제공합니다.
Apache HTTP Client HttpURLConnection
• 아파치에서 만든 HTTP 클라이언트.
• 최신 버전으로 제공은 안됨.
• 사용하기 복잡하고 무거움.
• 안드로이드 버전별로 약간씩 다른 행동.
• 버그가 많음.
둘다 Deserialization을 안해주므로, 좀 더 쓰기 편리한
써드파티 오픈소스 라이브러리도 많이 있습니다.
Volley OkHttp+Retrofit
• 이미지 처리에 특히 장점을 가지고 있음
• Google IO 에서 발표되었으나, follow up이
원활하지 않음.
• NIO기반으로 비교적 빠른 성능
• SPDY 지원
• Google 공식 컨퍼런스 등에서 사용된
적이 없음.
주: 기타 많은 라이브러리가 있습니다. HelloWorld 블로그에 있는 비교 포스트도 참고하세요.
22. HTTP 라이브러리 3G 성능측정
0
2
4
6
8
10
12
14
16
시나리오 1 시나리오 2 시나리오 3
AsyncTask Volley Retrofit + OkHttp
(초)
KT 3G / LG Nexus 5 / HTTP+SSL
시나리오 1 : 목록 API 5회
시나리오 2 : 목록 API 5회 + 상세 API 30회
시나리오 3 : 목록 API 30회 + 상세 API 100회
24. 서버를 확인하세요 : SPDY
자료: SIGCOMM 2013, “Towards a SPDY’ier Mobile Web?”
• Nginx : http://nginx.org/en/docs/http/ngx_http_spdy_module.html
• Apache : https://code.google.com/p/mod-spdy/
SPDY는 보다 적은 수의 컨넥션을 활용하여 더 많은 데이터를 처리합니다.
다량의 API 콜이 발생하는 경우, API 수정 없이도 더 빨라집니다.
25. Retrofit http://square.github.io/retrofit/
서비스 선언
Public interface MovieListService {
@GET(“/movielist”)
List<MovieList> movieList();
@GET(“/moviedetail/{id}”)
MovieDetail movieDetail(@Path("id") int id);
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(
"https://.../movielistdemo")
.build();
MovieListService service = restAdapter.create(MovieListService.class);
서비스 호출
List<MovieList> movieList = service.movieList();
서비스 호출 (비동기)
public interface MovieListService {
...
@GET(“/moviedetail/{id}”)
void movieDetail(@Path("id") int id, Callback<MovieDetail> callback);
}
service.movieDetail();
28. 난 데이터를 저장하고 불러들이고 싶었을 뿐인데…
android.database.sqlite.SQLiteException: database is
locked
android.database.sqlite.SQLiteException: unable to open
database file
...
SQLite를 잘 사용하는 것은 절대 쉽지 않습니다.
대부분의 모바일 앱에서 필요한 것은 복잡한 SQL이 아니라,
인스턴스를 저장했다 불러내는 기능입니다…
29. GreenDAO
TestDaoGenerator.java
public static void main(String args[]) throws Exception {
Schema schema = new Schema(3, "me.sungwoo.listdemo.dao");
Entity movieList = schema.addEntity(“MovieList");
movieList.addIdProperty();
movieList.addStringProperty("title");
movieList.addStringProperty("description");
new DaoGenerator().generateAll(schema, args[0]);
}
Generator 프로젝트를 만들어 준다.
build.gradle
apply plugin: 'application'
apply plugin: 'java'
mainClassName = 'me.sungwoo.listdemo.daogenerator.TestDaoGenerator'
outputDir = '../app/src/main/java-gen'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'de.greenrobot:DaoGenerator:1.3.0'
}
task createDocs {
def docs = file(outputDir)
docs.mkdirs()
}
run {
args outputDir
}
id title descrip
tion
1
2
3
http://greendao-orm.com
30. GreenDAO
DaoSession 생성
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,
“moviedb", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
그냥 사용하면 끝!
자료 조회 (Select)
MovieListDao movieListDao = daoSession.getMovieListDao();
MovieList movies = listDao.queryBuilder()
.where(MovieListDao.Properties.Id.eq(id))
.orderDesc(MovieListDao.Properties.Id)
.list();
자료 삽입 (Insert)
MovieList item = new MovieList(null, "은하수를 여행하는 히치하이커", “42");
movieListDao.insert(movieList);
자료 삭제 (Delete)
movieListDao.deleteByKey(id);
31. SQLite Tip
WAL 사용
SQLiteDatabase db = SQLiteDatabase.openDatabase(“db", cursorFactory,
SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
db.enableWriteAheadLogging();
• API 16 부터 지원
• 쓰기를 모아서 수행하여 Lock 시간을 감소
• E_SQLITE_LOCKED 볼 일을 줄여줍니다!
33. Event Bus의 활용
목록
View
상세정보
View
Logic
• 비동기로 완료된 작업이 어디로 값을 돌려줘야 할까?
• 데이터가 갱신되었는데 callback을 빼먹어서 버그 발생?
Event bus
Internet
새로운 데이터데이터 갱신 요청
“비동기적으로 연속적으로 처리되어야 할 작업들을
‘이벤트’로 정의하여 보다 부드럽게 구현”
34. Otto http://square.github.io/otto/
공용 이벤트 버스 생성
bus = new Bus(); // 일반 이벤트 버스
mainBus = new Bus(ThreadEnforcer.MAIN); // Main thread로 불러지는 버스
이벤트 수신자 (Subscriber)
@Subscribe public void updateMovieList(MovieList list) {
// Do something
}
bus.register(this);
이벤트 던지기
bus.post(new MovieList(1, "Hi", "There"));
35. 예제 앱 오픈소스 스택
View Logic
Request
Response
SQLite
Event
3G/LTE
WiFi
서버
Android SDK
RetroFit
OkHttp
OttoGreenDAO
SQLite
User View Logic
Otto
GreenDAO
RetroFit
36. One more thing : iOS
iOS용 라이브러리 몇 가지를 소개합니다
HTTP 통신
• AFNetworking (OkHttp + Picasso + Retrofit)
• FastImageCache (Picasso)
Event Delivery
• NSNotification
• Tolo (otto)
DB Storage
• Core Data
• 암호화가 필요한 경우 : SQLCipher