if 카카오 2020
if 카카오는 카카오에서 주최하는 개발자 컨퍼런스 입니다.
2020년도에는 11/18 ~ 11/20 까지 코로나로 인해 온라인 동영상으로 진행이 되었고 날짜별로 세션을 나누어 진행되었습니다.
재미있고 유익했던 여러 세션들이 있었지만 그중에서 day1 세션의 카카오톡 사례로 살펴보는 견고한 안드로이드 앱 개발하기 를 리뷰해보도록 하겠습니다.
카카오톡 사례로 살펴보는 견고한 안드로이드 앱 개발하기 - 채기병 Carey 님
“왜 견고함이 필요한가요?”
- 좋은 사용자 경험을 제공하기 위해
- 크래시나 이슈로 인해 불필요한 업데이트를 방지하기 위해
- 더 중요한 핵심 문제에 집중할 수 있는 시간 확보를 위해
제공하는 서비스에서 발생하는 이슈들로 인해 사용자에게 안좋은 경험을 주게되면 결국 사용자들은 해당 서비스를 떠나가게 되기 때문에 견고한 앱, 앱의 기능이 문제 없이 동작하는 앱을 만들어야 한다.
카카오톡 안드로이드 앱 현황
카카오톡이 2010.08에 출시하여 벌써 10년이 되었다는 사실에 놀랐다. (내가 스마트폰을 처음 접한게 2011년이니까 그때 카카오톡은 꽤나 소규모 기업이었나보다..)
하루 발생하는 카카오톡의 크래시는 4만건으로 전체적인 비율로는 0.1%밖에 되지 않는다는 사실에 놀랐다. 꽤나 안정적인 앱이라도 대개 0.1~0.4% 정도 크래시가 발생하는데 카카오는 그중에서도 0.1%가 발생한다는 걸 보니 견고한 앱 을 개발하기 위한 많은 노력들은 한다는 것이 느껴졌고 이어서 설명할 내용들에 대해 궁금해지기 시작했다.
크래시 분석하기
사내 크래시 분석툴, Firebase Crashlytics, PlayStore Developer Console 등을 사용하여 크래시를 분석하고 있다고 한다.
대신 안드로이드 프레임워크 내부에서 크래시가 발생했을 경우 크래시 stacktrace가 프레임워크 내부 로직으로 찍히기 때문에 크래시 발생 원인을 파악하는데 어려움이 있을 수 있다.
해서 카카오톡은 어려움을 해소하고자 사용자가 본 UI를 순서대로 표시해 어떤 경로를 통해서 크래시가 발생했는지를 추가로 로깅한다고 한다.
어떤 식으로 로깅했는지 자세히 나오진 않지만 적용하면 굉장히 유용하게 쓰일 수 있는 방안인 것 같다. 대신에 사용자가 진입한 화면이 많을 경우 너무 많은 데이터가 쌓이지 않도록 서버에서 관리한다던가 하는 별도의 방안이 필요할 것 같긴 하다.
리뷰 분석하기
보통의 서비스에서는 “고객센터”를 운영해 고객의 CS를 처리하고 있다. 하지만 많은 사용자들이 고객센터에 문의사항을 남기는 것이 귀찮아서, 혹은 화가 나 많은 사람에게 함께 알리기 위해서 (물론 나도 귀찮아서 문의를 안하고 넘어가는 경우가 많다..) 고객센터가 아닌 Google Play Store에 글을 남기곤 한다.
카카오톡에서는 이를 위해 Google Play Developer API 를 활용해서 리뷰들을 크롤링하고 카카오톡으로 주기적으로 전송해서 주기적으로 리포트를 받고 있다고 한다.
이슈의 개선 사례 소개
Lifecycle 에 대한 이슈
위의 코드는 IO 스레드에서 데이터를 요청하고 Main 스레드에서 이를 받아 UI를 갱신하는 간단한 예제이다. (feat. 코루틴)
위와 같은 코드에서 IO 스레드의 동작이 시간이 오래걸릴 경우 UI 갱신시 문제가 발생할 수 있다고 한다. (처음 위 코드를 보고 왜 문제가 생기는지 몰랐다.. 나는 아직 부족한 주니어 개발자인가보다..)
만약 Activity에서 위의 코드가 수행 됐을 경우 Activity 가 종료되었는데에도 Activity에 대한 참조가 계속 살아있어서 Activity 가 생명주기보다 오래 살아있어서 Activity가 재사용될 경우 메모리 릭이 발생할 여지가 있다는 것이다.
특히 Fragment에서 수행 될 경우에는 Main 스레드에서 UI 갱신을 할 때에 getString()
에서 Context가 필요한데, Activity에 detach
되어있는 상태라면 context가 null로 크래시가 발생할 수 있다.
이러한 Lifecycle 에러를 방지하기 위해 아래와 같이 Lifecycle이 유효하지 않으면 코루틴 작업을 취소하도록 하는 방법을 사용한다고 한다.
여기서 얻는 교훈은 시간이 오래 걸리는 비동기 작업의 경우, 항상 적절한 예외 처리가 되어있는지 생각하기 라고 한다.
Lint
실제 빌드를 하지 않아도 잠재적인 에러를 캐치해낼 수 있따는 점에서 굉장히 유용한 기능이다.
발표자분이 영상에서 말씀하셨던 것 처럼 많은 개발자들이 Lint 에러를 무시하고 넘어가는 경우가 많다. 사실 나조차도 무시하는 경우가 많다. 이번 기회를 통해 Lint 에러의 중요성을 다시 한번 깨닫고 Lint 에러를 유심히 살펴보는 습관을 가지도록 노력해야될 것 같다.
위의 예시에서 한국어를 중점으로 서비스하는 경우에는 한국어에서는 정상적으로 동작하기 때문에 아주 간단하지만 오류를 발견하기 까지 시간이 걸리게 될 수 있다. 위와 같은 경우에는 Lint 에서 같은 문장에서 언어간의 formatting이 다르거나 formatting 자체의 오류 를 검출해주기 때문에 Lint를 유심히 봐야한다고 설명해주었다.
위의 예시는 이전 예시보다 발견하기가 훨씬 어려운 에러이다. 코드상에서는 문제가 없어 Lint 에러가 발생하지 않지만 의미상 에러가 있다. 한국어와 어순이 다를 경우 발생할 수 있는 문제다. 이를 해결하기 위해서는 아래처럼 한 문장에서 여러개의 formatting이 필요할 때에는 순서를 명시해야 한다.
개인적으로 이 부분이 정말 유용했다. 글로벌한 서비스를 할 경우 다국어 처리를 많이 다루게 되는데, String Format에서 저런 방식으로 순서를 정해준다는 것을 몰랐고 이번 컨퍼런스를 통해 알게 되었다.
Kotlin 사용 이슈
코틀린 언어의 경우, 컴파일 타임에 Nullable, NonNull 을 엄격하게 구분하는 언어이지만 자바 언어의 경우 이 두가지를 구분하지 않기 때문에 코틀린 언어와 자바 언어를 함께 사용하는 경우 (레거시 때문에 아마 대부분의 기업이 함께 혼용하여 사용하고 있을 것이다.) 코틀린에서 NonNull 타입으로 선언된 경우 자바 코드에서 정말 Null이 들어올 일이 없는지를 한번 더 확인해야 하고 자신이 없다면 @NonNull
어노테이션이 있는 경우에만 코틀린에서 NonNull 타입으로 받도록 설계 해야 한다.
코틀린 property에 대한 기본 지식이지만 바쁘게 개발을 하다보면 간과할 수 있는 부분을 다시 한번 짚어주셨던 것 같다.
위의 주석처럼 get()
을 사용할 경우 호출 시마다 계산되기 때문에 조심해서 사용해야 하고 두번째 초기화의 경우 초기화 시점에만 값이 결정되기 때문에 주의하여야 한다.
코틀린에서 apply, run block
에서는 외부와 동일한 이름의 변수나 메소드가 없는지 잘 확인해야 한다. apply, run block
내에서 this 와 같은 참조는 내부의 참조를 먼저 가르키기 때문에 웬만하면 내/외부의 메소드의 네이밍을 다르게 하거나 내부에서 외부 메소드를 사용하지 않도록 하는것이 좋고 불가피할 경우에는 명확하게 표시해주어야 한다.
Infinite
maxCount가 0이 될 경우 앞의 double
타입 에 의해 자동 캐스팅이 되면서 maxCount는 double
타입이 되고 결과는 infinite 가 되게 된다.
이후 toInt()
에 의해 viewCount의 값은 약 21억이라는 값이 들어가게 되고 for문을 통해 draw를 약 21억번을 수행하게 될 것이고 Main 스레드에서 위와 같은 상황이 발생하게 될 경우 ANR이 발생하게 된다.
이를 방지하기 위해서 0으로 나눌 가능성이 있다면 0으로 나누지 않도록 default 값을 설정해두는 것이 안전하다고 한다.
위 예제를 보고 0으로 나누었을 때에는
ArithmeticException
이 발생할 것이라고 생각을 했는데 실수 0으로 나누었을 경우에는ArithmeticException
이 발생하지 않는다고 한다. 이 부분을 다룰 때에도 굉장히 흥미롭고 유익했다.
회고
이처럼 카카오톡 사례를 통해 견고한 앱을 만들기 위해서 주의애야 할 이슈들에 대한 설명을 들었는데 생각보다 많은 이슈들이 어려운 로직이 아닌 간단한 부분, 놓치기 쉬운 기본적인 부분에서 발생한다는 것을 알게 되었다. 기본적인 이슈더라도 크래시나 ANR과 같은 치명적인 사용자 경험을 제공할 수 있다는 점에서 내가 짠 코드에 대해서 좀 더 주의 깊게 살펴보도록 노력해야 할 것 같다는 생각을 하였고 특히 Lint를 무시하는 습관은 정말 버리고 주의해서 보는 습관을 들이도록 해야겠다는 생각이 들었다.
if 카카오 2020의 Carey님의 발표를 통해서 많은 것을 얻었고 주니어 개발자가 아직 맞닥들이지 못한 기본적인 이슈들이나 고려해야할 점들에 대해 간접적으로 체험할 수 있는 기회였던 것 같다. 내년에 코로나가 종식되어 오프라인으로 진행이 된다면 경쟁률이 꽤나 치열하겠지만.. 내년에도 또 신청하고 참여하고 싶다는 생각이 들었다.