[번역] Android Developer Skills for 2020

2020-07-24

원문 : https://www.techyourchance.com/android-developer-skills/

많은 안드로이드 개발자들이 "좋은 안드로이드 개발자가 되기위해 뭘 알아야 하죠?" 라고 물어본다. 그걸 다르게 표현할 수 있겠지만 결국 개발자들이 배워야할 유용한 기술 리스트를 찾는다는 사실로 귀결된다.

일리가 있는 질문이다. 안드로이드 개발은 거대하고 역동적인 생태계인데, 몇 주동안은 특정 도구의 사용법이나 개념을 익힐 수 있는데 이는 중요하지 않거나 거의 사용되지 않는 것들을 알아가는 것일 뿐이다. 이 글에서는 안드로이드 개발자들이 갖춰야할 기술 리스트를 공유하여 개발자들이 중요한 것에 집중하는데 도움이 되고자 한다.

경력 수준

분명히, 경력이 쌓이면 더 많은 지식을 얻을거라 기대한다. 그러나 몇몇 개념이나 아이디어들은 너무 앞서나가서 많은 경험이 쌓이기 전에 더 많은 지식을 요구한다. 그래서 전문적인 안드로이드 개발자가 알아야할 모든 기술 리스트를 언급할 수는 없다. 그 대신 독자의 경력에 따라 추천하는 기술셋이 있다. 하지만 이것이 정확한 척도는 아님을 명심하고 일반적인 사례라는 것을 명심했으면 한다.

간단한 앱도 만드는 방법을 모를 때

만약 안드로이드 개발자가 되기로 결심했고 아직 간단한 앱도 만들어보지 않았다면 이 글을 읽는게 이를 수도 있다. 이 글은 개발자나 어느정도 경험이 있는 사람들을 위한 것이다.

그러나 이 글을 읽는 사람이 아무것도 얻지 못하는 것은 아니다. 이 포스팅에서는 짧은 시간안에 안드로이드 개발자가 되는 단계를 요약할 것인데 실전 경험을 쌓고 다시 이 글을 읽으면 꽤 도움이 될 것이다.

이 포스팅의 끝부분에서는 독자가 이미 플레이스토어에 앱을 배포했고 소스코드는 GitHub에 있다고 가정할 것이다.

2년차 이하 경력의 안드로이드 개발자

안드로이드는 가파른 학습곡선을 가진 복잡한 프레임워크이다. 복잡성의 일부는 네이티브 앱 개발에 필수적인 요소이지만 나머지는 안드로이드 특성에 따른 우연한 복잡성이라고 할 수 있다.

안드로이드 개발자의 세계의 커리어를 시작할 때, 궁극적인 목표는 동작하는 소프트웨어를 만드는걸 떠나서 안드로이드 프레임워크를 배우는 것이다. 언어, 아키텍쳐, 최신 라이브러리, 트렌드 같은건 잊어버려라. 대신, 핵심 개념에 집중하고 깊이있게 탐구하자

정확히는 다음 주제에 대해 집중할 것을 권한다.

Android Memory Management and Process Death

안드로이드 개발의 가장 복잡한 측면 중 하나가 메모리가 부족할 때 얼마나 안정적이고 알맞게 동작하게 만드는 것이다. 요약하자면: 앱 프로세스는 다른 앱으로 전환될 때 종료될 수 있다. 하지만 사용자는 다시 앱으로 돌아왔을 때 프로세스가 종료되지 않은 화면을 기대하게 된다.

메모리 관리에 대한 자세한 내용은 여기서 언급하지 않겠다. 이 글에서 자세히 설명해놓았다.

Lifecycles

필자가 만약 안드로이드 어플의 복잡성과 버그의 가장 큰 원인에 이름을 붙인다면. 난 기꺼이 lifecycles라고 외칠 것이다. (얼굴을 감싸고 울부짖으며...)

Application, Activity, Fragment, Service, BroadcastReceiver, ContentProvider 그리고 아마도 안드로이드의 핵심 컴포넌트들까지 각자의 복잡성과 lifecycle을 가지고 있다. 거기에서 끝나지 않고 구글은 계속 각자의 복잡성과 lifecycle을 가지고 있는 새로운 라이브러리와 프레임워크를 출시한다. Loader, ViewModel and LiveData 같은 것들 말이다.

lifecycles 에 관한 한가지 흥미로운 사실은 lifecycle 이라는 단어의 정의를 본적이 없다는 것이다. 항상 사용하고 있지만 이것의 정확한 의미는 무엇일까? 지금까지 얘기한 것으로 lifecycle 에 관한 직관적인 이미지를 떠올릴 수도 있다. 필자는 lifecycle에 대해 많이 생각도 해보고 써보기도 했으니 이 용어를 한번 정의해보고자 한다.

컴포넌트의 Lifecycle 은 Final State Machine에 대한 추상화이다. 여기서 추상화라는 말의 뜻은 state machine 의 상태와 그것들이 전환되는 조건이 미리 정의되었다는 의미이다. 하지만 완전히 설명하기엔 부족하다. 부족한 부분은 "lifecycle callback"이라고 부르는 컴포넌트 메서드의 일부를 뜻한다. FSM 자체 외에 특정 lifecycle callback 에서 할 수 있는 암시적 한계와 제약이 있다. 이러한 한계는 문서에 나와있지만 어떤 점은 나와있지 않다.

lifecycle 이 얼마나 복잡해질까? 글쎄, 이 다이어그램은 Acitivity 와 Fragment 의 lifecycle 을 보여주는데 (심지어 업데이트가 안되어 정확한 것도 아님). 딱봐도 복잡하고 어렵지만 대부분의 안드로이드 개발자가 이걸 다 이해하는건 아니니까 너무 스트레스 받지 말자. 사실 안드로이드를 만든 구글러도 다 이해못한다. 예를들어 구글이 LifecycleOwner 프레임워크를 출시했을 때, Fragment lifecycle의 context에서 심각한 버그를 지적하면서 그 다음 ViewLifecycleOwner를 사용해서 버그를 피해야한다고 발표했었다.

이제, 안드로이드 lifecycle 을 완벽하게 이해할 필요는 없지만, 어느 정도의 디테일은 이해할 필요가 있다. 그렇지 않으면 코드가 엉망이 되고 매우 까다롭고 심각한 버그를 발생시킬 수 있다. 필자는 최대한 실용적인 방법으로 Activity lifecycle은 여기서 Fragment lifecycle은 여기서 설명해보았다. onStart() 와 onResume()이 뭐가 다른지 확신이 안들면 읽어보기 바란다.

lifecycle 에 대한 기본개념이 감이 온다면 안드로이드 개발자의 7가지 원죄(실제로는 10가지) 을 읽어보길 바란다. 이러한 "원죄"는 대부분의 안드로이드 개발자들이 하는 실수이다. 예상했듯이 lifecycle과 관련된 실수이다.

lifecycle에 대한 질문은 매우 일반적인 면접 질문이다. 정확히 공부해야할 이유가 생겼다.

Context

모든 안드로이드 앱은 하나 이상의 Context가 있다.

lifecycle과 마찬가지로 Context는 수 많은 역할을 하기 때문에 무엇인지 설명하기는 어렵다. 따라서 이를 한두 문장으로 설명하기엔 불가능하다. 그렇지만, Context의 역할과 서로다른 Context들의 차이점을 이해하는 것은 중요하다.

context는 말그대로 맥락이다. 이 StackOverflow 쓰레드이 글을 읽어보길 권한다.(채택답변은 스킵하고)

User Interface (UI) Thread Responsiveness

안드로이드 앱 마다 UI 쓰레드를 가지고 있다. 이 쓰레드는 화면에서 UI를 그리는 역할을 담당하고 있는데 이 쓰레드를 잘못 다루게 되면 앱 반응성에 악영향을 끼치게 된다. 최악의 경우 앱이 멈춰버리게 된다.

따라서 UI 쓰레드에서 이해하고 거기에 따라서 사용해야한다. 이 비디오에서 UI 쓰레드에 관련된 세부사항과 유의사항을 포함한 멀티 쓰레딩에 대해 설명하고 있다

Logic Decomposition

엄밀히 말해서 안드로이드 프레임워크는 "clean code" 라고 할 수는 없다. 수천줄의 코드가 있는 소위 갓 클래스가 혼재되어 있고 이것들을 확장시켜 사용해야하는 것을 강요하고 있다. 결과적으로 한번에 많은 일을 하는 클래스를 작성할 수 밖에 없다. 일반적으로 Application, Activity, Fragment, Service 등을 사용할 때 일어나는 일이다.

하지만, 이런 일이 빈번하더라도 이러한 접근은 유지보수나 개발자의 정신건강에 좋은 일은 아니다. 그러니 이 문제를 유념하면서 클래스를 작성할 때 로직을 분리하여 별도의 클래스를 작성하는 것을 계속 고려하는 것이 좋다.

솔직히 말하자면, 신입 개발자들이 이러한 아키택쳐나 디자인패턴 관련된 작업을 할 수 있다고 생각하지 않는다. 로직을 분리하고 캡슐화하여 클래스로 따로 분리하는 작업은 좀더 많은 경력이 필요하다. 하지만 신입개발자가 로직을 분리하는 작업을 잘해낼 수는 없어도 최악의 경우를 피하기 위해 조금씩 시도는 해봐야 한다. (5천라인이 넘는 activity 같은 최악의 경우)

이 글에서 설명한대로 Context 관련된 로직을 분리하는 것을 시도해볼 수 있다.

Android Developers With 2-4 Years of Experience

어느 정도 경력이 있는 개발자. 안드로이드 프레임워크에 대해 잘 이해하고 있어야 하고 학습과 검색이 좀 필요하더라도 특별한 기능이 아니라면 일정 기한안에 구현할 수 있어야 한다. 그 다음엔 뭘 해야할까?

이제 안드로이드 프레임워크에 익숙할 것이다. 이제 고수준의 스킬을 익힐 차례이다. 이러한 스킬들은 안드로이드 개발에 국한되지 않은 일반적인 개발 스킬들이다. 다음과 같은 주제를 참고해보자.

Dependency Injection

의존성 주입(DI)은 Separation of Concerns principle(관심사 분리 원칙)에 따른 아키텍쳐 패턴이다. DI는 목적은 어플리케이션에서 두 가지의 주요 관심사를 분리하는 것이다. 하나는 어플리케이션의 핵심 기능 다른 하나는 핵심 기능을 구현하는 구성 요소간의 상호연결

어떤 관점에서는 DI 의 구성요소는 개인용 컴퓨터의 구조와 유사하다. DI 기반은 메인보드와 유사하고, CPU, memory, 주변기기 등의 구성요소는 DI의 기능적 구성요소라고 할 수 있다. DI 가 코드베이스에 구성되면 재사용 가능한 컴포넌트를 추가할 수 있다. 예로 들었단 비유를 잘 기억하면 DI의 핵심 컨셉을 잘 이해할 수 있을 것이다.

아쉽게도 DI라는 주제는 분량이 매우 많기 때문에 이글에서는 다루지 않겠다. 이 글을 읽어보면서 시작하면 좋을 것이다. DI "신화"에 대해서 광범위하게 분석한 글이다.

Decoupling of User Interface Logic

안드로이드 프레임워크의 아키텍쳐 자체는 UI 로직과 나머지 부분의 결합이 강하다. 신입 개발자들은 여기에 따라 코드를 작성한다. 이러한 결합은 UI를 "그리는" 네트워킹, 멀티쓰레딩, 디바이스 제어, 비지니스로직이 들어 있는 거대한 클래스 등을 만들어낸다.

내 경험으로는 이러한 UI 로직의 결합은 안드로이드 앱을 유지보수 문제의 가장 큰 원인이다. 당장이든 나중이든 이러한 방식의 코드는 매우 이해하기 어렵고 작은 수정에도 side effect 를 발생시킨다.

UI 로직 분리는 Model-View- 아키텍쳐 패턴의 주요 목적이다. MVC, MVP, MVVM 등등의 아키텍쳐 패턴이 이러한 경우에 해당된다. 나는 이러한 패턴들을 묶어서 MVx 패턴이라고 한다.

MVx 에 대해서 한가지 유념해야할 점은 아키텍쳐가 아니라 아키텍쳐 패턴이라는 점이다. 게다가 이런 아키텍쳐 패턴은 앱 내부의 프레젠테이션 로직에만 적용된다. 따라서 MVx를 도입한다고 "좋은" 아키텍쳐가 나오지는 않는다. 좋은 아키텍쳐란 그보다 더 많은 노력이 필요하다는 소리다.

Multithreading

경력 안드로이드 개발자는 안드로이드의 멀티쓰레딩 개념과 멀티쓰레딩이 앱에 어떻게 영향을 주는지에 대해 알고 있어야 한다. "나는 AsyncTask/RxJava/Coroutine 등등으로 다루는게 익숙해. 그럼 됐네"라고 생각할 수도 있지만 내 말의 의미는 그런것이 아니고 멀티쓰레딩 프레임워크를 사용한다는것이 멀티쓰레딩을 이해한다는 것이 아니라는 것이다.

예를 들어, 많은 경력 개발자들은 AsyncTask를 사용하는게 메모리 누수로 이어진다라고 생각한다. 이러한 생각은 AsyncTask 공식문서와 AndroidStudio의 기본 lint 규칙에도 포함되어 있다. 정말 그런가? 아쉽게도 틀렸다. 이 글에서 이 주제에 대해 자세하게 다루지는 않겠다. 이 글에서 자세한 내용을 확인할 수 있다.

내생각에 멀티쓰레딩을 이해하기 위해서는 Thread 클래서 안에서도 동시성 코드를 올바르게 작성해야 한다. 이 목적을 달성하려면 가장 자주 사용하는 멀티쓰레딩 라이브러리의 API를 아는 것만으로는 충분하지 않다. 라이브러리가 좋아도 멀티쓰레딩을 기본을 이해하지 못하면 멀티쓰레딩 관련 버그가 발생할 수 밖에 없다.

안드로이드의 멀티쓰레딩에 대해 공부하려면 이 비디오를 참고하자. 모든 경력 개발자가 알아야할 기본 사항에 대한 체계적인 설명이 포함되어 있다.

Automated Testing

대부분의 안드로이드 프로젝트들은 여전히 테스트 자동화를 사용하지 않고 있다. 그 중에서 대부분은 QA 담당자가 Appium과 같은 도구를 사용하여 처리한다. 이 업계의 슬픈현실이고 이 문제는 Android의 기원과 Google이 타사 앱의 자동화된 테스트 과정을 오랬동안 무시했다는 사실로 거슬러 올라간다.

그렇지만, 유닛테스트와 UI 테스트 경험이 있는 개발자들은 매우 수요가 많다. 테스트 자동화되지 않은 회사에 면접을 보더라도 코드를 유닛테스트 할 수 있다고 말하면 보너스 점수를 받을 것이다. 반대로 테스트 자동화를 많이 쓰는 회사에 면접을 본다면 다른 지원자들에 비해 좋은 점수를 받지 못할 것이다.

따라서 필수는 아니지만 경력 개발자라면 테스트 자동화에 대해 공부해 놓는 편이 좋다. 개인적으로 유닛테스트를 선호하고 UI 테스트는 많이 쓰지 않지만 다른 많은 개발자들은 반대이기도 하다. 뭐가 됐든 더 재밌는 쪽을 선택해 실행해보는걸 권한다.

Android Developers With 4+ Years of Experience

여기까지 왔다면 이른바 "meta" 스킬을 익히고 특정 분야를 전문화 시킬 차례다. 아래의 스킬들은 전문적인 개발자들에게 매우 바람직하다.

Trade-Off Identification

결정해야할 많은 기술적인 결정이 결국 타협점을 보는 것이라고 때달아야 할 때이다. 어떨때는 결정이 분명하게 즉각적으로 이루어질 수 있지만 항상 그런것은 아니다. 대게 판단의 범위가 클수록 즉시 할 수 있는 결정들 보다 더 추상적이고 더 많은 절충이 필요하다.

이 수준의 경력에 도달하면 적어도 어느 부분에서 타협을 봐야할지 알 수 있게 된다. 모든 문제가 명박하게 선택할 수 있는 척도를 제공하면 좋겠지만 현실은 좀 더 복잡하다. 보통은 타협점을 판단할 수 있다면 다른 개발자나 관리자들과 토론에서 절충안을 제안할 수 있을 것이다. 따라서 대부분의 경우 타협점을 알아볼 수 있는 정도로 충분하다.

이제 내가 얘기했던 "타협점 알기" 이라는 말의 의미가 이해가 가는가? 솔직히 말해서 명확하게 정의하기는 어렵지만 내가 들었던 몇가지 예를 들수는 있다.

"AsyncTask 는 메모리 누수가 발생하기 때문에 RxJava로 바꿔야 한다.": 위에 언급 했듯이 틀렸다. 이 얘기를 한 사람은 멀티쓰레딩의 개념을 충분히 이해하지 못한 것이다. 그리고 RxJava의 단점에 대한 언급이 없었다. 적어도 프로젝트에 참여하는 모든 개발자들의 러닝커브를 고려하지 못했다.

"모든 새 코드에 유닛테스트를 적용하여 장기적인 목표범위를 세워 앱의 퀄리티를 올려야한다.": 이 주장은 몇가지를 전제로 한다. 하나, 지금 당장 유닛테스트를 시작할 수는 없다. 적어도 개발자들은 이 기술에 대한 공부가 필요하다. 또 테스트를 실행할 CI 시스템이 갖춰져있는지 확인이 필요하다. 그리고 유닛 테스트 할 수 없는 부분이 분명 존재하기 때문에 모든 코드에 적용할 수는 없다. 둘째, 장기적인 목표범위를 이룬다고 저절로 퀄리티가 좋아지는 것도 아니다. 이 경우 개발자는 유닛테스트에 대한 이해도 없다. 그래서 프로젝트에 유닛테스트를 도입하는거에 대한 많은 절충안에 대해 인지 하지 못했다.

몇가지 예를 더 들수는 있지만 이제 무슨 얘기인지 알 것이다. 중요한 결정을 해야할 때 절충안에 대한 복잡함을 깨닫지 못한다면 경력을 쌓는데 필요한 과정을 다 밟지 않았을 수도 있다. 몇몇의 타협점은 기술적인 문제를 벗어나는 것도 있다. 따라서 결정이 다른 부서에 미치는 영향에 대해서도 생각해봐야 한다.

Specialization

뛰어난 개발자들이 다른 개발자와 비교했을 때 어떠한 점이 다른가? 많은 기술을 써본거? 내생각은 아니다. 가장 큰 차이점은 지식의 깊이이다.

뛰어난 개발자가 되려면 하나 이상의 전문분야를 가져야한다. 평균적인 개발자들 보다 깊이 이해하고 있는 분야를 말하는 것이다. 전문 분야의 개발에 대한 최신 정보를 얻으려면 지속적으로 노력해야하므로 새로운 도구나 기술에 놀라지 않아도 된다. 그리고 프로젝트에서 이 전문분야가 사용되지 않더라도 전문 분야와 연관된 장단점을 찾아낼 수 있어야 한다.

전문분야를 갖추는 것은 어렵다. 블로그 포스팅에서 고르는 일이 아니다. 좋은 책을 읽고 좋은 수업을 들어서 갖출 수 있는 것도 아니다. 물론 도움이 될 수는 있지만 전문분야를 갖는 유일한 방법은 적극적으로 참여하고 많은 경험을 쌓는 것이다.

난 물리학자 닐보어가 한말을 좋아한다.

전문가는 좁은 분야에서 발생할 수 있는 모든 실수를 해본 사람이다. 

어떤 분야가 전문분야가 될 수 있을까? 글세 어떤 것이든? 전문분야가 되기엔 작은 노력으로 될 수 있는 영역이 거의 없다. 당장 생각나는 것들은

  • User interfaces
  • Build systems
  • Offline work
  • Concurrency
  • NDK
  • Continuous Integration
  • Performance
  • Architecture
  • Mentoring
  • Project management
  • Business domain knowledge
  • and many, many more.

언급한 것들은 기술적인 영역을 벗어나는 것들도 있다. 맞다. 독자가 좋아하는 어떤 분야도 고용주에게 가치를 보이는 한 전문분야가 될 수 있다.

좋은 안드로이드 개발자가 되기 위해서는 적어도 2~3가지 영역에서 전문분야가 되어야 한다고 생각한다. 예를들어 나같은 경우 : 아키텍쳐, 유닛 테스트, 동시성, DI 등이다. 레거시 코드 리팩토링이 곧 들어갈 것 같기도 하다.

독자가 4년 이상 경력의 개발자라면 어떠한 전문 분야가 있다고 할 수 있는가?

Conclusion

자 여기까지 전문 안드로이드 개발자로 익혀야할 기술 리스트 였다.

흥미로운 사실은 이 포스팅의 제목에도 불구하고 어떤 내용도 2020년에 국한되지 않는다는 것이다. 기본 개념과 중요한 개념이 바뀌지 않기 때문이다.

안드로이드 생태계에 더 궁금하다면 지난 포스팅 2019년말 네이티브 안드로이드 개발 트렌드를 참고하라. 하지만 좋은 안드로이드 개발자가 되려면 기본적이고 중요한 것들에 더 집중하길 바란다.