대부분 알고 계시겠지만 앱개발하는데 있어서 유용한? 거의 꼭 필요한? 라이브러리를 소개합니다. Show 1. Glide -이미지 로딩 라이브러리. 여러 이미지 로딩 라이브러리 들이 존재하지만 속도가 매우 빠르며, 모양의 변형 (원모양, 사각모양 등), 여러 부가기능을 제공해준다. 기타 여러 이미지 로딩 라이브러리는 많음. ( picasso, AUIL, Fresco 등 ) - (참고) https://github.com/bumptech/glide - (참고 - 안드로이드에서 이미지 로딩 라이브러리 순위를 매겨놓은 사이트 ) https://ourcodeworld.com/articles/read/929/top-10-best-android-image-loading-and-caching-libraries 2. Retofit - 서버와 데이터를 주고받기 위해 사용하는 라이브러리. - java beans를 이용해서 매우 편하게 서버와 Json 데이터 매핑이 가능하다. - Interface 기반으로 각종 서버와 주고받을 API 들을 정의합으로써, 매우 코드상으로도 직관적이며 유지보수가 편함. - 최근에는 Retrofit2 & RxAndroid 조합으로 코드 구조를 짜기도 함. - (참고) http://square.github.io/retrofit/ 3. RxAndroid, RxJava - 코틀린 언어 도입 이후 자주 쓰이는 리액트 패러다임의 RxJava 입니다. - RxAndroid 라이브러리는 RxJava에 좀더 필요한 클래스를 추가하여 안드로이드내에서 리액티브 구성요소들을 편리하게 사용할 수 있게끔 한 라이브러리이다. - (참고) https://github.com/ReactiveX/RxAndroid 4. Stetho - Facebook 에서 나온 디버깅 라이브러리 - Chrome 브라우저를 이용해서 서버와 주고받는 프로토콜 상태 및 결과 데이터 를 바로바로 보기쉽게 정리하여 준다. - 또한 내부 자체 내에 내장된 DB 까지도 보기 편하게 정리해준다. - (참고) http://facebook.github.io/stetho/ 5. Otto - 이벤트 버스 라이브러리. 옵저버 패턴을 이용해서 현재화면에서 작업한 것을 다른 화면에도 공지해서 변경을 줄수있는 라이브러리. - (참고) https://github.com/square/otto 6. Fabric - Logging 라이브러리, 특히 실시간 Crash를 Logging하고 알람을 주기때문에 매우 유용. - (참고) https://fabric.io 7. Firebase ( Fabric - Crashlytics 간 통합하여 사용 ) - Logging 라이브러리. google 에서 추천하는 로깅 라이브러리. Logging, Crashlytics, Database, Hosting, A/B Testing 등 정말 많은 기능을 제공한다. - 기본적인 로딩은 firebase에 하고 crash의 경우는 fabric으로 실시간 확인하면 좋을듯 하다. - (참고) https://firebase.google.com 8. Butterknife (Android DataBinding(라이브러리) 또는 Kotlin(언어) 사용시에는 큰 필요성 없어짐. 기존 JAVA 언어로 앱 개발시 유용. ) - UI 를 매번 java 코드상에서 findByViewId 를 써줄 필요가 없다. UI binding 라이브러리 - OnClick, OnLongClick 등 여러 annotation 기능을 제공하여 코드의 간결함을 준다. - 요즘에는 DataBinding 또는 Kotlin 언어의 사용으로 인하여 사용성이 많이 떨어진 것 같음. - (참고) https://github.com/JakeWharton/butterknife - Android & Kotlin 에서는 자동으로 VIEW를 바인딩 해주어 자연스럽게 사용할 필요가 없어졌다. 이정도면 기본적인 서버와 클라이언트가 있고 앱을 개발하는데있어서 큰 무리없이 가능합니다. 그 밖에 정말 재밌고 신기한 수백 수천가지의 라이브러리들이 다양합니다. 웬만한 것은 Google 에 물어보시면 라이브러리가 많아요~ - circularimageView, photoView, email-input-view, crouton, pullToRefresh, etc.. 안드로이드 앱을 개발할 때 이미 있는 기능들을 굳이 처음부터 다시 만들 이유는 없습니다. 특히 초심자일때는 더욱 그렇죠. 이번 360AnDev 강연에서, Chris는 안드로이드 앱 개발에 사용할 수 있는 라이브러리들을 소개합니다. 이를 통해 다른 개발자들이 이미 해결해 둔 문제를 쉽게 해결할 수 있죠. 웹 API에서 데이터를 불러오는 일이나, 이미지를 보여주고 캐싱하는 일, 데이터를 저장하고 동기화하는 일을 쉽게 해결할 수 있도록 앱에 적용할 수 있는 라이브러리를 만나보세요. 소개 (0:00)제 이름은 Chris Guzman이고, Groupon에서 일하는 개발자입니다. 좀 더 소개하자면, 저는 1년 전에 안드로이드 개발자로 전환하기 전까지는 Ruby on Rails 개발자였습니다. 이 강연에서 제가 안드로이드 개발을 시작할 당시에 알고 있었다면 좋았을 여러 라이브러리들을 소개하고자 합니다. 새로운 앱 개발을 시작하셨나요? (0:44)새로운 앱이나 어떤 기능을 개발하기 시작했는데, 어떤 라이브러리를 사용하는 것이 적절한지 모르겠다고 가정해 봅시다. 가장 좋은 것은 “커뮤니티에서 사용하는 라이브러리”로, 이런 라이브러리들에 대해 말씀드리고자 합니다. 많은 기본 앱들이 비슷한 기능을 갖죠.
오늘 보여드릴 라이브러리와 버전은 다음과 같습니다.
다만 오늘은 어떻게 TAaSTY - Tacos As a Service To You (2:04)45분짜리 해커톤을 시작했다고 생각해 볼까요? 뭔가를 당장 만들어야 할텐데요, 무엇을 만들까요? Tacos As a Service To You라는 말을 줄인 TAsSTY라는 앱을 만들도록 하겠습니다. 타코를 좋아하는 분들을 위한 앱입니다. 텍스트 뷰와 이미지 뷰, 두 개의 버튼이 있고 아래쪽엔 정보 버튼이 있습니다. 이제 앱 개발을 시작해 보죠. 처음으로 할 일은 뷰를 설정하는 일입니다.
우리가 만들 앱은 아래처럼 생겼습니다. 뷰를 사용해야 하는데, 이 시점에서 첫 번째 라이브러리, Butter Knife를 적용해 보겠습니다. Butter Knife (3:01)Butter Knife는 판에 박힌 관용 코드 대신 애너테이션을 쓸 수 있도록 해주는 멋진 라이브러리입니다. 어떤 장점이 있을까요? 아마
Butter
Knife를 액티비티에 적용하면 이런 모습이 됩니다.
Butter Knife는 뷰나 자원을 찾아주는 코드를 만들고 프로퍼티로 저장합니다. 이 예제에서는 액티비티에 프로퍼티로 저장했습니다. 이것이 Butter Knife가 컴파일 타임에 프래그먼트를 사용할 때를 살펴볼까요?
프래그먼트를 사용한다면 조금 다른 방식을 사용해야 하지만 여전히 단순합니다. 두 개의 인자를 넘기고 또한 이벤트 리스너 기능도 Butter Knife의 큰 장점입니다.
Butter Knife를 사용하면 뷰에 레퍼런스를 필수적으로 넘기지 않아도 되므로 상당히 유연한 코드를 작성할 수 있습니다. 취소 버튼을 누르면 해당 버튼의 뷰를 더 업데이트할 이유가 없어질테죠. 사용자가 버튼을 클릭했음을 단지 로그로 남기거나, 5만 개의 분석 라이브러리가 있다 치면 이들에게 취소 버튼이 눌렸다고 알리면 됩니다. Butter Knife는 이런 리스너를 지원해줍니다. 자원 적용 (7:07)Butter Knife을 사용해서 자원을 넣을 수도 있습니다.
스트링 파일이 있고 거기서 스트링을 가져오는 상황을 가정해 보겠습니다. 해당 파일에서 스트링을 찾고 ID를 넘기고 액티비티에 프로퍼티로 설정하기만 하면 됩니다. drawable, color, dimension에도 마찬가지의 일을 할 수 있죠. color나 dimension에서 int 등을 가져올 수 있습니다. 더 멋진 기능은 뷰의 그룹화입니다.
이 경우 취소를 누르면 “Ew Gross!”라는 메시지를 보내는 뷰를 리스트로 묶는 것을 말하는 김에 다른 것도 말씀드리겠습니다. 모든 뷰에 프로퍼티를 한 번에 적용할 수도 있답니다.
이제
버튼을 비활성화해서 사용자들이 두 번 클릭하지 못하도록 합니다. 이제 Taco 이미지를 설정해볼 차례로, Picasso를 사용할 예정입니다. Picasso (9:47)Picasso는 이미지를 다운로드하고 이미지뷰에 보여주도록 하는 훌륭한 라이브러리입니다. 특히 HTTP 요청을 자동으로 만들어준다는 큰 장점이 있습니다. 어떤 종류인지 걱정할 필요도 없죠. 또한 Picasso는 이미지 캐싱도 해주므로 요청을 다시 하는 것을 고민할 필요도 없습니다. 크롭이나 중심 맞추기, 크기 조정 등 이미지와 관련한 어떤 종류의 일이라도 쉽게 할 수 있도록 합니다. 메인 스레드에서 다운로드하지 않도록 처리해주므로 메인 스레드에서 네트워킹을 하면서 발생하는 예외도 걱정할 필요가 없죠. 혹시 잠깐 질문을 드려보겠습니다. 두 가지 코드를 보여드릴텐데요, 어떤 쪽이 좋으신가요? 제가 안드로이드 개발로 전환한 시점에서 처음으로 이미지 다운로드 방법을 찾아볼 때, Stack Overflow에서 아래 코드를 찾았었습니다.
인풋 스트림을 사용해서 무언가를 다운받고, 잘못될 때를 대비해서 Picasso를 사용하면 다음처럼 됩니다.
웹에서 이미지를 불러올 때만 Picasso를 사용할 수 있는건 아닙니다. drawable이나 파일 스트링 혹은 새 파일 등에도 사용할 수 있습니다.
이제 어떻게 이미지를 불러오는지 살펴봤으니 우리 앱에 적용해 볼까요?
우리 앱에서 모델은 JSON으로 설정할 예정입니다. JSON 얘기가 나온 김에 Gson에 대해 말씀드릴까 합니다. Gson (13:29)Gson은 JSON와 Java 객체를 상호 변환해주는 라이브러리입니다. Gson을 사용하는 것의 장점은 클래스에 애너테이션이 필요하지 않다는 것인데요. 정말 효율적이고 자주 사용되는 라이브러리죠. Gson이 어마어마한 영역을 차지하는 통계를 본 적도 있습니다. 일단 우리 모델을 살펴볼까요?
구식의 평범한 Java 객체 모델입니다.
생성자로 Gson 객체를 만들고 제가 오늘 아침에 먹은 이제 JSON으로부터 Java 오브젝트를 디시리얼라이즈하는 반대 상황을 생각해 보겠습니다. Gson 인스턴스의 메서드,
Gson에 대해 더 알아둘 것은 Java 객체를 JSON으로 시리얼라이즈하는 경우에 null 필드가 있으면 해당 필드를 건너뛴다는 것입니다. 우리 타코에 tag가 빠졌다고
가정해보면, 그 tag는 Gson을 커스터마이즈할 수도 있습니다. 빙산의 일각일 뿐이지만 팁 하나를 보여 드리겠습니다.
첫 번째 포인트는 null을 시리얼라이즈하는 겁니다. JSON을 시리얼라이즈할 때 null을 건너뛴다고 말씀드렸는데요.
가끔 엉망인 API를 사용해야 하는 경우가 있습니다. API에서 snake case(단어 중간에 언더라인을 붙이는 방식: snake_case)를 사용했다던지 철자가 잘못됐다던지, 기본 이름을 사용하기 싫을 경우가 있죠. 이 경우 자신의 프로퍼티를 작성한 후 애너테이션으로 태그하고 API의 이름을 넘겨버릴 수 있습니다. 이후부터는 JSON에서 받아와서 시리얼라이즈된 라벨을 사용하는 대신 태그된 프로퍼티를 호출해서 Java 객체를 사용할 수 있습니다. 가끔은 date 포맷을 커스터마이징해야할 때도 있는데요, Gson에서는 어떻게 하는지 보여드리겠습니다.
date 포맷을 만들고 Gson을 만들어서 해당 포맷을 넘겨 줍니다. 이제 타코의 description을 불러올 준비가 끝났습니다.
타코의 description을 받아오기 위해 웹에 호출을 보낼텐데요, 여기서 AsyncTask 대신 Retrofit을 사용하겠습니다. Retrofit (18:27)네트워킹에 모두 AsyncTask를 사용하는 분이라면 다음과 같은 장점이 있으므로 Retrofit 도입을 권합니다.
바로 앞 챕터에서 Gson을 말씀드렸으니 이제 Gson 팩토리에 데이터를 넘길 겁니다. 참, Retrofit은 RxJava도 지원합니다. Retrofit은 동기적으로나 비동기적으로 HTTP 요청을 실행할 수 있게 해줍니다. 어떻게 사용하는지 볼까요?
먼저 인터페이스를 만들어야 합니다.
저는 랜덤으로 타코를 얻어오고 싶다면 이런 식으로 Retrofit을 사용해서 인자를 애너테이션하면 서버에 해당 쿼리 매개변수를 따라 요청을 보냅니다. 우리의 경우 두 번째 API에는 인자가 없고 contributor 리스트를 넘겨받게 됩니다. 리스트를 받았으니 리스트 안의 내용을 하나하나 순회해야 할테죠. 세 번째 API인 마지막으로 중요한 네 번째 API에서는 JSON을 동기적으로 받는 코드는 아래와 같습니다.
실제 API인 이 이번엔 새로운 레시피를 포스팅하는 것을 알아보도록 하겠습니다.
새 정말 좋은 팁을 하나 드리겠습니다. 기본 URL을 변경할 수 있다는 겁니다. 새로운 버전을 작업하는 경우 전체 URL을 넘기고 해당 메서드를 애너테이트할 수 있습니다.
이 방식으로 기본 URL을 건너뛸 수 있고, 필요하면 헤더도 추가할 수 있습니다. 랜덤 타코를 얻으려면 아래 같은 코드를 사용합니다.
랜덤 타코를 요청하는데 이 요청을 비동기식으로 만들 겁니다. 성공한다면 그 타코를 저장할 것이고, 실패한다면 45분짜리 해커톤이니만큼 무시해 버리겠습니다. Realm (24:20)
Realm의 장점은 다음과 같습니다.
Realm을 설정하기 위해서는 두 단계가 필요합니다. 먼저 우리 객체가
계속해서 사용해오던 같은 타코 객체를 사용했습니다. 그 다음 Realm을 설정합니다.
새 스레드에서 Realm을 사용할 때마다 새 Realm 인스턴스를 가져와야 합니다. 데이터베이스에 객체를 저장하는 방법은 다음과 같습니다.
모든 데이터가 트랜잭션 내에서 처리되도록 해야 합니다. 가장 먼저 할 일은 트랜잭션을 시작하는 일입니다. Realm이 자동으로 모든 객체를 메모리에서 관리해주므로, Realm에 이를 복사하거나 Realm 데이터베이스에서 객체를 만들 수 있습니다. 이미 타코 객체가 있다고 생각해 보죠. URL에 description을 설정하긴 했지만 데이터베이스에 저장하고 싶다면 혹시 새로운 타코 객체를 만든다면 Realm에서 인스턴스를 만들
수도 있습니다. 데이터 접근은 어떻게 하냐고요? 만약 좋아하는 타코를 모두 가져오고 싶다면 Realm에 다음처럼
Realm에다 “내가 좋아하는 타코를 줘 볼래?” 하고 묻기만 하면 됩니다. 그 결과는 데이터를 쓰는 다른 방법은 아래와 같습니다. 재차 말하지만 새 스레드에서 Realm을 사용하려면 새 Realm 인스턴스를 가져와야 합니다. 그 다음 아래처럼 트랜잭션 블록을 사용합니다.
이제 이 트랜잭션을 실행할 겁니다. Realm에서 새 객체를 만들고 description와 이미지 URL을 설정합니다. 이 블록이 실행되면 데이터베이스 내에 저장돼죠. 비동기식으로 실행하면 어떨까요?
다시 실행 블록을 사용해서 타코에 대해 잘 알려지지 않은 사실은 정말 많은 재료가 들어간다는 것입니다. 타코 사이의 관계나 타코와 성분 간의 관계를 어떻게 규정할 수 있을까요?
예를 들어 타코가 성분 리스트를 가지며, 이 성분 객체가 URL에서 이름을 갖는다고 생각해 보겠습니다. 타코와 성분 두 객체가 Realm을 상속받아야 하며, Realm이 이들 간의 관계를 관리해줍니다. 어떤 모습인지 확인해 볼까요?
이 코드에서 Realm에게 “라임이라는 성분이 들어가는 모든 타코를 줄래?”하고
물어봤습니다. 그 다음 Reaml이 건네준 Realm results를 또한 Realm은 가끔 타코를 지워야 할 경우도 생기기 마련이죠.
Realm 트랜잭션 블록에서 할 수 있는 것은 이런 리스트를 가져와서 첫 번째나 마지막 것을 지우는 것입니다. 인덱스로 객체를 지정해서 지울 수도 있고, 필요하다면 전체를 다 지워버릴 수도 있습니다. Realm의 좋은 점은 Realm 객체나
위 예제에서는 다른 Realm의 장점은 객체를 자동으로 업데이트해준다는 것입니다. Realm 활용 팁 (30:24)Realm 사용의 장점과 활용 팁 몇 가지를 공유해 드리겠습니다. 모델에 기본 키 애너테이션으로 ID를 지정했다면, integer인 ID를 가지고 Realm을 복제하거나 업데이트할 수 있습니다. 즉, 매번 새 객체를 만들지 않고도 메모리 상에 있는 같은 객체를 업데이트할 수 있다는 거죠. Realm은 Gson과 Retrofit과도 잘 어울립니다. Realm의 최신 버전을 사용하면 게터와 세터를 커스터마이즈할 수 있습니다. 이전에는 되지 않던 버전이 있었으므로 팁이라고 할 수 있겠습니다. Realm을 사용하면서 가비지 컬렉션이나 이상한 메모리 경고, 에러 등을 피하기 위해서는 Realm 객체나 RealmResult에 적용한 change listener를 꼭 지워야 한다는 것입니다. 뭔가 참조가 끝난 경우 꼭 change listener를 지우는 것을 잊지 마세요.
또한 액티비티, 프래그먼트, 스레드 등의 생명 주기에 따라 Realm 객체를 닫는 것을 잊지 마세요. 메모리 유출을 줄이는데 많은 도움이 됩니다. Realm은 정말 유용한 솔루션을 제공하며, 계속 발전하고 있는 회사로 언젠가 이 문제를 고칠 거라 예상하지만 현재로써는 객체에 스트링 리스트나 원시 타입을 저장할 수 없습니다. 예를 들어 제 타코 객체는 하나의 tag 스트링을 갖는데, 만약 이것이 리스트가 된다면 현재로써는 Realm에 저장할 수 없습니다. API에서 데이터를 다운받는다면 Gson 어댑터를 받는 것이 좋습니다. 혹은 RealmString 같은 스트링의 새 객체를 만드는 것도 우회책이죠. 만약 Realm에 API에서 가져온 데이터를 저장한다면, 해당 객체를 메모리로부터 Realm으로 복사하고, Realm 객체에서 이 복사본을 사용한다는 점입니다. 만약 데이터의 크기가 크거나 복잡한 쿼리가 있다면 메인 스레드에서 사용하지 않도록 주의하세요. 자, 마지막으로 가장 중요한 작업인 새 액티비티를 시작해보겠습니다.
참가하고 있는 해커톤에서 한 30분쯤 지났는데, 아직도 액티비티가 하나 뿐이네요. 다음 액티비티를 만들어 봅시다. Dart & Henson / Conclusion (33:04)이제부터는 Dart & Henson을 사용하겠습니다. Dart는 Butter Knife에서 영감을 받아 만들어진 라이브러리의 이름으로, 저희 Groupon에서 많이 사용하고 있습니다. 인텐트 엑스트라를 객체에 프로퍼티로 주입할 수 있게 해주므로 새 액티비티를 시작하고 이들 엑스트라를 인텐트에 실어서 보내는 작업을 한다면 Dart로 쉽게 해결할 수 있습니다.
먼저 말씀드린 둘을 구분해서 말씀드릴텐데요, 먼저 Dart부터 알려드리겠습니다. 인텐트로부터 엑스트라를 가져오는 코드는 다음과 같습니다.
Butter Knife와 비슷해 보이죠? 액티비티의 이들 프로퍼티를 이제 인텐트에 엑스트라를 실어 보내지 않아도 앱이 죽지 않을 겁니다. 기본 값도 만들 수 있는데요. 만약 인텐트의 엑스트라에 또한
Henson은 자동으로 이 인젝트 엑스트라 애너테이션을 가진 모든 액티비티를 찾아서 자동으로 만들어낸 빈 메서드로 보내줍니다. 또한 Henson은 어떤 엑스트라가 인텐트와 함께 이 액티비티를 시작하면서 해커톤을 마무리하겠습니다. 아무 엑스트라도 주입하지 않은채 Henson을 사용하고 싶으면 어떻게 할까요? 액티비티를 여기서 작은 팁을 드리자면, ProGuard를 사용하시는 분은 아래와 같은 법칙을 적용하시라는 겁니다. 구현할 메서드들도 없이 달랑 이거면 될까요?
네, 그렇습니다. 이로써 우리의 타코 앱이 완성됐습니다! Q & A (37:32)Q: Realm 데이터베이스 안에 저장된 객체가 업데이트됐는지 어떻게 알 수 있나요? Chris: 객체의 ID 애너테이션을 사용하면 모델에 고유한 ID가 생깁니다. SQL에서 하는 것과 비슷하죠. 앞에서 보여드린 조건문을 사용해서 Realm 객체를 ID로 탐색하고 그 특정 Reaml 객체를 업데이트합니다. ID로 탐색한 다음 업데이트를 하고 트랜젝션을 커밋하면 데이터베이스에 잘 업데이트됩니다. 참고자료
컨텐츠에 대하여
|