이 글의 원문은 여기서 확인할 수 있으며 블로그 리뷰에는 노현석(GDE)님이 참여해주셨습니다.
사용자는 앱이 원활하게 작동하길 기대합니다. 비정상 종료는 부정적인 리뷰 혹은 앱 삭제로 이어질 수 있으며, 더 나아가 브랜드 이미지에 악영향을 주기도 합니다. 커뮤니티 구성원의 의견에 따르면 Kotlin을 채택하는 주된 이유 중 하나는 더욱 안전한 코드이기 때문입니다. 이번 게시물에서는 Google 파트너가 Kotlin을 통해 코드의 안정성을 개선한 방법을 알아봅니다. 또한 Google Play 스토어 통계를 보고 Kotlin 사용과 비정상 종료 발생 횟수 간에 상관관계가 있는지도 살펴보겠습니다. (스포일러는 당연히 있죠!)
앱 품질(App quality)
앱 품질은 사용자 경험에만 영향을 미치는 것이 아닙니다. 비정상 종료 횟수가 높아지면 다음과 같은 요소도 영향을 받습니다.
- 앱 발견 가능성(App discoverability) — Google Play 스토어에서 추천하는 앱은 담당자의 선별(human curation)과 알고리즘 계산(algorithmic calculations)이 함께 사용되는데, 이 과정에서 앱 품질이 큰 부분을 차지합니다.
- 브랜드(Brand) — 제품 성능은 평가(ratings)와 리뷰(reviews)에 영향을 주고, 이로 인해 브랜드 이미지도 영향 받을 수 있습니다.
- 더 많은 사용자와 높은 참여도(Higher number of (engaged) users) — 향상된 자연 트래픽(organic traffic)과 브랜드 인지도(brand perception)를 바탕으로 사용자 획득(user acquisition)과 유지율(retention)을 높이고, 이를 통해 사용자 참여(engagement)와 하위 유입경로 측정항목(lower funnel metrics)도 개선할 수 있습니다.
Kotlin으로 빌드한 앱은 비정상 종료 발생 확률이 20% 낮습니다.
여기서 Kotlin은 어떤 역할을 할까요? Google Play의 상위 1,000개 앱을 살펴본 결과, Kotlin을 사용하는 앱은 다른 앱보다 사용자당 비정상 종료(crashes)가 20% 더 적은 것으로 나타났습니다.
코드의 74%를 Kotlin으로 작성하는 Swiggy 엔지니어링팀의 사례를 살펴보면, 새로운 기능 개발에 Kotlin을 사용한 이후로 비정상 종료가 50% 감소했습니다.
NullPointerException 방지하기(Avoiding NullPointerExceptions)
Google Play에서 비정상 종료의 가장 큰 원인은 NullPointerException입니다. 2018년부터 Google Home팀에서는 모든 새 기능을 Kotlin으로 개발하기 시작했으며, 1년 동안 Null 포인터 비정상 종료가 33% 감소하는 성과를 얻었습니다.
Google Home은 NullPointerException가 33% 감소했습니다.
NullPointerException을 방지하려면 메서드를 호출하거나 멤버에 액세스하기 전에 작업 중인 객체 참조가 null이 아닌지 확인해야 합니다. Kotlin에서 null 허용 여부는 유형 시스템의 일부입니다. 예를 들어, 변수는 처음부터 null 허용 또는 null을 허용하지 않음으로 선언되어야 합니다. null 허용 여부를 유형 시스템의 일부로 만들면 메모리과 코드베이스 지식 또는 컴파일 시간 경고(필드/매개변수에 @Nullable로 주석을 남기는 경우)에 의존할 필요 없이, null 허용 여부가 적용됨에 따라 경고뿐만 아니라 컴파일 시간 오류도 표시됩니다. null 허용 여부를 처리하는 방법은 이 페이지에서 확인하세요.
일반적인 문제 방지하기(Avoiding common issues)
개발자가 자신도 모르게 일으키는 문제가 많은데, 그중 상당수는 아주 미묘하고 파악하기 어렵습니다. 다음은 Kotlin 사용으로 방지할 수 있는 문제의 몇 가지 예입니다.
hashCode() 및 equals()
두 객체가 같다면 해시코드도 같아야 합니다. 그런데 이러한 메서드 중 하나를 구현하지 않거나 클래스에 새로운 속성이 추가되었을 때 업데이트하지 않는 경우가 자주 있습니다. 데이터를 보관하는 역할을 하는 클래스로 작업할 때는 Kotlin data class를 사용하세요. data class를 사용하면 컴파일러에 의해 hashCode() 및 equals()가 생성되며 클래스의 속성을 변경하면 자동으로 업데이트됩니다.
구조 동등성(Structural equality)과 참조 동등성(referential equality)
두 객체가 구조적으로 동일(동일한 내용을 가짐)하거나 참조적으로 동일(포인터가 동일함)하나요? 자바 프로그래밍 언어에서 기본 유형에 항상 == 기호를 사용하므로, 구조적으로 동등한지 확인(equals()를 호출하여 확인)하려는 경우에도 객체에 ==(참조 동등성) 를 호출하는 실수를 흔히 하게 됩니다. 첫째로 Kotlin에는 기본 유형(primitive types)이 없고 Int 또는 String 등의 클래스를 사용하므로 더 이상 객체와 기본 유형을 구분할 필요가 없습니다. 모두 객체이기 때문입니다. 둘째로 Kotlin에서는 == 기호를 구조 동등성으로, === 기호를 참조 동등성으로 정의하므로 구조 동등성을 확인해야 할 때 참조 동등성을 확인할 일이 없습니다.
if else의 반복사용으로도 충분하지 않은 경우
enum으로 작업할 때는 가능한 모든 케이스를 다루고 있는지 확인해야 할 때가 많습니다. 그로 인해 switch나 일련의 if else를 사용하게 됩니다. 새 값을 추가하기 위해 enum을 수정하는 경우에는 enum을 사용 중인 각 코드 스니펫을 수동으로 확인하며 새로운 케이스를 처리하는지 확인해야 합니다. 그러나 이 과정에서 쉽게 오류가 발생합니다. Kotlin에서는 이 작업에 컴파일러를 활용(rely on the compiler)할 수 있으며 when표현식을 사용할 수 있습니다. 가능한 모든 케이스를 다루고 있지 않을 경우 컴파일러 오류가 발생합니다.
결론
앱의 안정성은 사용자와 브랜드 모두에 중요합니다. Kotlin 사용을 시작하여 비정상 종료 발생률을 낮추고 만족스러운 사용자 경험을 제공하세요. 높은 앱 평점을 유지하여 사용자 획득과 유지율 측면에서도 좋은 성과를 낼 수 있습니다.
Kotlin으로 더 나은 앱 만들기에서 자세한 내용을 읽어 보고 우수 사례에서 Kotlin이 개발자에게 어떤 이점을 가져다 주는지 확인해 보세요. Kotlin은 전 세계의 많은 개발자에게 사랑받는 언어입니다. 첫걸음을 내딛는 데 도움을 받으려면 시작하기 페이지를 확인하세요.