그걸 다 고려하며 살기엔 내 한 몸 건사하는 것도 바쁘고 고단하니까. 바쁘고 고단한 탓에 서로가 서로의 괴로움을 오래 바라보지 못하니, 딱 그만큼 우리는 또 외로워지고 소외된다. 그 외로움을 잊기 위해 소비자의 자리에 가서 타인의 노동을 외면하고, 노동자의 자리로 돌아가면 다시 외면당하는 이 악순환.
kingorihouse

kingorihouse:

인스타그램 블로그에 Building a better Instagram app for Android라는 안드로이드 앱 개선 관련 글이 올라와 맘대로 압축/발번역 해 봤다.

1. 디자인

6개월 전, 빠른 동작, 아름다움, 스크린 크기 최적화라는 3가지 목표로 인스타그램 앱의 디자인을 개편했다.

모바일 세상에선 윈폰, 안드로이드의 홀로 테마, ios 7등 플랫 디자인이 대세이다. 왜 플랫 디자인이 대세일까? 폰의 작은 화면에서 이쁘게 보인다는 이유도 있지만, 성능이 더 큰 이유이다. 갖가지 그라데이션, 이미지 리소스를 읽어들이지 않아도 되서 성능이 더 좋다.

위 3가지 목표를 갖고 앱의 모든 화면을 재작업했다. 플랫 디자인으로 이쁘게 재단장했고, 쓸데없는 UI 요소를 다 쳐내서 사진/비디오에 집중할 수 있게 했고, 성능을 끌어올렸다.

가장 크게 UI 최적화를 이뤄진 부분은 사진,비디오 캡쳐&편집 부분이다. 화면 사이즈에 민감하게 대응되도록 했다. 이를 위해 화면 종류를 화면 비율, DPI 값 기준으로 4종류로 분류했다. 제일 작은 류의 화면엔 오밀조밀한 레이아웃을 썼고, 중간, 큰 크기 화면은 남아도는 화면을 잘 활용하게 디자인했다. 그 결과 사용자들이 만족해했다.

그리고 asset tinting1 을 적극 활용했다. 플랫 세상에서 asset은 단순한 쉐입이다. 따라서 런타임에 색을 바꿀 수 있다. 그 결과, 상태 별로 별도의 asset을 쓰지 않아도 되었다. 안드로이드 L엔 색깔 먹이는 기능이 추가로 제공되지만, 기존 버전에서도 모두 사용가능하다. drawable, imageview 클래스에 ColorFilter 먹이면 된다. immutable ColorFilter 객체를 캐싱해뒀다가 재사용했다.

이런 방식으로 asset 갯수를 확 줄였다. 타이틀바와 탭 바에 쓰인 asset을 29개에서 8개로 줄였다. 그래서 속도가 왕 빨라졌다. 요것만 해도 기동시간 120ms가 줄었다. (10~20%의 속도향상) 하여간 전반적으로 빨라졌다. 유저 프로필은 2배 빨라졌다.

apk 크기도 작아졌다. xxhdpi 대응까지 했음에도 asset 개수는 오히려 반으로 줄었다. apk 크기는 절반으로 줄었다. 용량이 줄었기 때문에 느린 네트웍 사용자도 앱을 빨리 받을 수 있고, 모바일 데이터도 덜 쓴다.

2. 기동 시간

사용자는 앱이 뜰 때 까지 세월아 네월아 기다려주지 않는다. 성능 떨어지는 안드로이드 기기에선 메모리가 부족해서 툭하면 앱을 죽여버리기 때문에, 기동 시간이 길면 사용자들이 매우 괴롭다2.

지난 반년간 인스타그램 앱 기동 시간을 반으로 줄였다. 이제 제일 빨리 뜨는 앱 중 하나라고 봐도 될거다. 갤s5에선 0.5초면 사용 가능 상태가 되고, 성능 나쁜 갤y에서도 1.5초면 뜬다.

이런 성능 개선을 위해 안드로이드의 TraceVeiw 도구와 시간 측정 코드를 박아 프로파일링을 했다. 비효율적인 json 파싱 코드를 다시 짠다거나, 기동 시 필요없는 컴포넌트는 지연로딩을 하는 등의 다수의 자잘한 개선을 했다. 이런 작업 중 창조성이 필요한 영역이 2가지 있었다.

첫번째 영역은 이미지 캐시, 비디오 캐시, http client등 앱 전반에 걸쳐 사용하는 무거운 싱글톤 관리였다. 앱이 구동하려면 얘들이 떠야할 것 같지? 하지만 진짜로 그렇진 않다. 앱이 뜰 땐 네트웍 요청을 날리거나 사진/비디오를 보여주지 않는다. 이런 서비스는 지연로드 해도 된다. 하지만 이 녀석들을 초기값 null로 두면 코드가 복잡해지기 마련이다. 따라서 두 단계에 걸쳐 이들을 초기화했다. 일단 메인 쓰레드에서 기존과 같이 객체를 생성해 두지만, public API만 동작할 정도의 초기화되지 않은 상태로 두었다. 그 다음엔 다른 쓰레드를 이용해 네트워크로 부터 실제 이미지나 컨텐트를 로드하고, 디스크에서 SSL인증서를 가져오고 캐시 저널 파일을 읽는 등의 무거운 작업을 수행했다.

두번째 영역은 News 페이지였다. 이 화면이 앱 구동을 느리게 만드는 주범이었다. 이 화면은 누가 당신 사진을 좋아하고, 댓글을 남겼는지 보여주다. 사용자가 새로운 액티비티를 바로 확인할 수 있게 이 페이지를 구동 시에 보여준다. 이 화면은 원래 웹뷰로 구현했었는데, 뷰를 초기화하려고 여러 쓰레드가 돌면서 메인 프로세서의 시간을 좀먹는 걸 발견하고 깜짝 놀랐다. 우리는 웹뷰가 시스템 자원을 관리하는 방식을 직접 제어할 수 없다는 걸 깨달았다. 웹뷰는 자기만의 네트워킹 스택을 갖고, 별도의 이미지 캐시를 가진다. 따라서 앱과 이미지 캐시의 내용이 중복된다. 이 문제를 해결하려고 뉴스 화면을 네이티브 뷰로 바꿨다. 네이티브 뷰로 만들어서 메인 피드가 로드 된 다음 뉴스가 로드되도록 딜레이를 줄 수 있게 되었고, 네트워크 스택과 이미지 캐시도 다른 부분과 공유할 수 있게 되었다.

이런 노력의 결실로 훨씬 더 쓸만한 인스타그램 안드로이드 앱을 만들어 낼 수 있었다. 우리 엔지니어링과 제품 팀은 “단순성”이란 가치에 집중해서 노력을 기울여 사용자에게 빠르고 아름다운 인스타그램 사용자 경험을 제공할 수 있었다.


  1. 상태마다 개별 asset을 만드는 게 아니라, 하나의 asset을 가지고 색을 변형해서 제공하는 방식이라고 보면 된다. 안드로이드에선 본문에서 언급한 ColorFilter를 이용해 색깔만 바꾼 asset을 만들 수 있다. 또한 xml을 이용해 회전시킨 이미지를 제공할 수도 있다. 기술적인 내용은 cyrill mottier의 Putting Your APKs on Diet 중 Reuse whenever possible 섹션에서 확인할 수 있다. 

  2. 가뜩이나 폰도 꾸져서 느린데, 메모리가 딸려 앱은 쓸 때 마다 재기동되고, 그 때마다 또 꾸진 기기가 앱을 띄울 때 까지 기다려야 하고. 으악!