회사에서 예전에 기술 아티클로 작성한 내용입니다.


앱 개발할 때 이벤트 버스 Otto를 사용하여 이벤트 처리를 편하게 하자라는게 요지입니다. 서두의 추상화 뭐라고 하는건 무시해주세요;; 추상화 어쩌거 저쩌고는 크게 관심도 없는데 굳이 어떤분이 서두에 그런 문장을 넣으라고 해서 억지로 넣었네요;;;

미국 쪽 블로그 보면 RxJava가 핫하게 쓰이고 있는데, learning curve가 아주 높더군요. 저도 공부할 려면 시간 좀 걸릴것 같고 모든 팀원이 공부를 좋아한다는 보장이 없기 때문에 일차적으로 이벤트 처리는 learning curve가 짧고 낮은 이벤트 버스 Otto가 좋을 것 같아 보입니다. 


http://tmondev.blog.me/220605524250


Posted by 제이제이랩
,

자바로 웹 프론트 엔드, 백 엔드를 다루시는 분들이라면 필히 스프링의 Dependency Injection은 많이 다뤄보셨으리라 봅니다. 저 같은 경우는 안드로이드 native 개발자로 첫 단추를 풀어서 인지 몇년이 지나도록 DI에 대한 개념과 필요성을 인식하지 못했습니다. 물론 저의 게이름과 안일함 때문이긴 한데요;;;


이전에 벤처에 있을 때 여러 오픈소스를 탐닉하다 RoboGuice를 앱에 적용해 보고 DI 프레임 워크의 편리함을 맛 보았습니다. ButterKnife 또한 사용해 보면서 그 편리함에 감탄했었는데요. RoboGuice가 Guice로부터 파생된 걸 알게 되었고 런타임 도중 reflection의 과도한 사용으로 고질적으로 앱의 성능에 치명적인 단점을 제공하고 있었습니다. 다른 프레임워크를 찾다 Square에서 만든 Dagger를 접하였습니다. 구글에서 Guice를 대체할 DI 프레임워크로 Dagger에 주목하여 지금은 구글 core library team에서 Dagger 2를 주도하여 개발하고 있습니다. 


http://google.github.io/dagger/ [Dagger 2 설명보기]


런타임 Reflection을 완전히 없애고 Annotation processing으로 code generation해서 성능상 문제가 없게 만들었습니다. 모바일, 서버, 일반 자바 애플리메이션 개발에서 쓸 수 있습니다. 저야 저의 샘플앱에 Dagger, Dagger 2를 둘다 적용해 봤지만 지금도 이해가 되지 않는게 많답니다. 아직도 Object graph가 머리속에 그려지지 않네요. 


아무튼 회사에서 제가 드디어 테스트 코드를 짜면서 개발을 하게 된지라.(개발 6년차인데 지금 짜고 있습니다;;) 이전에는 샘플 프로젝트에 먼저 만들 코드 작업하고 실행시켜보고 이상이 있나 없나 검증한뒤에 실제 앱 코드에 적용하는 방식을 썼었습니다. QA팀에서도 버그가 걸러져 나오고 이러한 방식에 익숙하다 보니 앱 개발하면서 unit test, instrumentation test 코드 작성에 대한 필요성을 많이 못 느끼고 있었죠. 그 시간에 요구사항 개발하기도 바쁘고 현재 앱의 수많은 버그 잡는데 더 시간을 쏟겠다라는게 기본 철학이었죠. 현 회사에서 앱 시작 속도 개선이라는 메이저급 변경을 하면서 사이드 이펙트가 상당히 크게 나고 긴급 배포 2번이나 하면서 이대론 안되겠다 테스트 코드밖에 답이 없겠구나 절실히 느꼈습니다;;


그래서 이번에 저에게 떨어진 일은 junit4, hamcrest, mockito, robolectric, espresso 기반으로 테스트 코드를 작성하면서 진행하고 있습니다. 그러다 보니 진정한 테스트 가능한 앱 코드를 만들기 위해 기존 회사앱에 Dagger 2를 적용시켜야할 필요성이 생겼습니다. 그런데 제가 오픈 소스를 적용하면 귀찮은 일을 해야 합니다. 왜 이 오픈 소스를 적용해야 하는지 팀원들한테 설득시켜야 하는데요. 처음 입사해서 몇번 했는데 제 시간 쏟으면서 발표자료 만들랴 일도 하랴 너무 귀찮습니다. 그리고 이번에 인사 평가가 나왔는데 기대한 것보다 실망스러워서 회사에 대한 애정도 없어진 터라 더 이상 발표 같은건 아예 안할 작정입니다;; 아무튼 Injector가 필요한데 Dagger 2를 앱에 녹이면 귀찮은 일이 생길것 같아서 아주 단순한 Injector를 만들어야 겠습니다. 앱 뿐만 아니라 SDK를 만들때도 이 단순한 Injector를 사용하면 괜찮겠다는 생각이 드네요. 


생각해보니 SDK 개발할 때 Dagger 2를 사용해도 될지 의문이 들고 아주 간단한 Injector를 하나 만들어서 두고두고 써 먹으면 제 실력도 향상되고 재밌을것 같습니다. 그래서 JSR 330(https://jcp.org/en/jsr/detail?id=330)을 준수하는 Injector를 만들까 합니다. GitHub 페이지만 만들었네요. https://github.com/jayjaylab/syringe 별생각없이 주입하는거니까 syringe라고 이름지었습니다. 시작을 해야 하는데 이것저것 하느라 진행을 못하고 있네요;;

Posted by 제이제이랩
,

안드로이드 앱 개발하실 때 어떤 비트맵 캐쉬 라이브러리를 사용하시나요?

지금 회사 오기전에는 UIL부터 Picasso까지 써보았는데요. 처음 입사했을 때 큰 회사인데도 불구하고 앱의 bitmap 캐쉬 관리가 엉망이어서 Picasso를 적용하려 했었죠. 소스 코드 분석하고 그러던 중 갑자기 여러 이슈가 떨어져서 앱의 문제점만 분석한 문서만 만들어 놓았는데.. 몇 개월 후 입사하신 다른 분이 Glide를 소개해 주셔서 Glide를 제 개인 샘플앱에도 적용해보았습니다. 회사 앱에 적용은 다른분이 하셨다능.. 구글링 해보면 Picasso와의 벤치마킹은 Glide가 여러면에서 압승이었습니다.

(Square에서 Picasso 업그레이드 하려는 움직임을 보이는 것 같은데... 차후에 두 라이브러리의 대결이 궁금하네요ㅋㅋ)


여러 상품의 이미지를 앱에서 노출해야 하는데, 간혹 서버에서 이미지 URL 변경없이 이미지를 변경하는 경우가 있는데, 앱에는 캐쉬된 이전 이미지가 계속해서 나타나는 경우가 있죠. 저 같은 경우 Glide가 알아서 처리 해준다고 착각했었습니다. 혹시나 해서 Glide측에 문의 해보니 아니나 다를까 제가 기대한 cache invalidation은 없었습니다. (https://github.com/bumptech/glide/issues/996 참조)

저희 회사의 고객 서비스 센터에서 안드로이드는 최신 이미지가 정상적으로 노출된다 길래 okhttp에서 알아서 처리하나 추측했지만 아무리 봐도 Glide와 okhttp 연동에는 그런 작업이 없길래 도저히 안되겠다 싶어 제가 직접 확인해 보았는데, 역시나 HTTP 통신을 okhttp를 쓰도록 세팅하고 bitmap cache는 Glide로 하더라도 최신 이미지가 노출되지 않더라구요. 


제가 기대한 건 각 이미지의 ETag를 conditional GET request의 If-None-Match 헤더에 태워 보내서 서버에서 이미지가 변경되면 변경되었다고 응답하고 변경 안되면 안되었다고 응답하여 그 응답을 라이브러리 단에서 처리하여 포워딩 캐쉬가 되는 거였는데... 아무래도 conditional request 보내는 것도 적으면 몇 ms, 많으면 몇십, 몇백 ms가 걸릴수도 있어서 이를 피하기 위해 memory, disk 캐쉬 hit이 발생하면 바로 바로 캐쉬된 이미지를 가져다 뿌려주는 것으로 보입니다.

그러면 사용자에게 가장 최신의 이미지만을 노출하고 싶은데, 어떻게 해야할까요?


결론부터 말하면 이미지가 바뀌면 그 이미지 리소스를 가리키는 URL도 변경해서 클라이언트에 내려주면 된다입니다. Glide에서 cache invalidation을 위해 StringSignature라는 것을 제공하지만 이보다는 서버쪽에서 이미지가 변경되면 이미지 리소스에 대한 URL도 변경되도록 처리하고 이를 클라이언트가 전달 받아 뿌려지도록 하는 구조가 맞을 것 같습니다. 그러면 클라이언트측에서는 디스크, 메모리 캐쉬를 사용하여 앱 속도를 보장하면서 항상 사용자에게는 최신 이미지를 노출할 수가 있습니다.

Posted by 제이제이랩
,