Programming/Android

2021 Droid Knights 컨퍼런스 후기

YK Choi 2021. 9. 25. 23:31

2021 9월 25일 드로이드 나이츠 온라인 컨퍼런스에 참가했다.

 

작년에 참가했을 땐 무슨말인지 너무 어려워서 뛰쳐나갔는데, 이번엔 끝까지 들었다 ㅎㅎ;;

 

작년과 달라진 점은 참가료(만원)이 있다는 것과 개더타운으로도 접속할 수 있다는 것이 있다.

 

컨퍼런스 일정은 아래와 같다.

Track1과 Track2가 동시에 실시간으로 유튜브 스트리밍 방송되며, 취향에 따라 선택해서 들을 수 있다.

각 강의가 끝나면 짧으면 5분? 길면20분? 정도의 쉬는 시간이 있는데

이때 개더타운으로 QnA를 받기도 했다.

 

 

개더타운 내에는 토스, 헤이딜러, 카카오페이에서 채용 관련 홍보, 문의도 하고 있었다.(경력자들 대상인 것 같다)

 

 

이제 본론으로 들어가서 내가 들은것 요약+느낀점을 적어보겠다.

우선 나는 Track 2개를 동시에 틀어놓고, 관심있는 주제에 대해서만 음소거를 제거하면서 골라들었다.

둘다 듣고 싶은게 있으면 하나를 유튜브 일시정지해 놓고 둘 다 들었다.

 

1. 13:25 타임

[ Track 2 ] 액티비티 코드 제로

코드를 깔끔하게하고 가독성을 높이는 것은 언제나 내 관심사였다. 어떻게 액티비티의 코드를 줄일지 궁금해서 Track2를 선택했다.

 

완전 초창기의 안드로이드 개발 방식부터 서론을 띄우셨다.

그리고 이후에 생긴 데이터 바인딩으로 액티비티의 콜백 없애기, RxJava/Flow를 활용한 방법으로 코드 수를 줄인 배경에서 여전히 남은 문제에 대해 언급하셨다.

 

이미지 버튼 클릭시 액티비티의 의존성(접근 권한 여부 확인/ 권한 부여 이후 후처리), 스트림 처리시 스트림 종료 이슈 등이 남은 문제였다.

따라서 Lifecycle Awareness기반 RxJava 또는 Flow를 지향하고 ViewModel에서 모든 로직 처리를 가능하게 해야한다.

 

이를 어노테이션을 커스텀하여 @createdToDestroy, @resumedToPause 와 같은 어노테이션을 만든 방법을 소개하신다.

이를 통해 onCreate 에서 생성하고, onDestroy 에서 처리해야할 것들을 @createdToDestroy 어노테이션을 적용한 함수 내에서 한번에 처리하는 방법이다.(예를 들면 RxJava에서 Dispose와 관련된 것들)

따라서 onCreate ~ onDestroy 의 생명 주기 내에서만 동작하는 스트림을 쓰도록 커스텀하는 것으로 이해했다.

 

어노테이션을 커스텀한다는것은 나에겐 신박한(?) 방법이었다. 이걸 커스텀하다니..!

여담으로 viewModel에서 init{}을 쓰는것은 좋지 않다고 말씀하셨는데, 맞는 말씀인 것 같다. 왜냐하면 Activity/Fragment가 생성되기 전에 ViewModel이 @inject 등으로 먼저 생성될 수 있는데, 액티비티의 로직보다 뷰모델의 init이 실행될수 있기 때문이다.

 

2. 14:00 타임

[ Track 2 ] 복잡한 RecyclerView, 군더더기 없이 데이터로 표현하기

발표에서 말씀하신 방법을 요약하면 총 3가지 방법론이 있다.(셋 다 동시에 적용가능)

1. 어댑터 공통화

 - 뷰홀더의 재활용이 용이하지 않음 -> 뷰타입을 외부에서 정의하는 것!

어노테이션을 이용하여 컴파일 시점에 뷰타입과 뷰홀더를 매핑하는 방법이다.

(이건 좋은 방법같은데 구체적으로 어떻게 적용하는지 이해하지 못했다. minor한 방법은 아닐것 같은데 추가 조사를 좀해봐야겠다.) 

2. 뷰홀더의 구현 없애기

 - 데이터 바인딩에 대한 이야기다. 이렇게 해봤었으니 PASS~

3. RecyclerView의 상태를 ViewModel에 표현하기

 - 이벤트로서 ViewModel에 전달하는 것이라고 한다. RecyclerView State를 Interface로 전달하는 것이라고 한다.

이 부분은 이해가 잘 안간다.

Adapter의 이벤트를 인터페이스로 만들고, Activity에서 인터페이스를 재정의 하여, 해당 이벤트를 ViewModel에 전달하는 방법은 뻔한(?) 얘기일 것이라 생각하는데.. 그래서 이 방법이 아니라 더 신박한 방법을 제시한것 같다.

 

SnapShot? 이라는 단어가 등장했는데 이것도 잘 이해가 안갔다.

 

3. 14:35 타임

[ Track 2 ] 해커입장에서 생각하고 안전한 앱 개발

데스크탑에서 해킹하는 과정들, 그 구현 C코드를 보여주고 원리들을 설명하는 발표였다.

해커입장에서의 구현코드를 상당히 detail하게 보여주는데 나한텐 조금 과한 정보가 아닌가 싶었다.

 

앱을 개발하는 입장에서 유념해야할 것을 요약하면 이렇다.

- 사용자 정보 사용을 최소화(사용이라 함은 통신도 포함이다.)

- 사용자를 의심하라(사용자가 권한을 갖고 있는 것이 맞는지 의심하고 판별하라)

- 오픈소스의 사용을 관리하라(앱 사이즈가 커지면서 오픈소스 사용은 피할 순 없겠지만 구현코드를 주의깊게 볼 필요가 있음)

- Secure한 코딩기법 공부/적용

 

[Track 1] Koin 걷어내고 Hilt 마이그레이션하기

Koin을 걷어낸다니...Koin이 안좋은 것처럼 들려서 마음이 아팠다

 

Koin을 Hilt로 마이그레이션하면서 문제가 발생할 수 있는데 주의할 점이 있다고 했다.

- 특정 Koin모듈을 제거하기 어려운 상황에서, Hilt 모듈 내 주입하는 코드를 별도로 더 만들게 되는 경우엔 -> 생성하고자 하는 인스턴스가 중복이 되어 문제가 발생할 수 있다고 한다.(Koin과 Hilt가 공존할 때)

 

결론
1. Koin과 Hilt가 공존하는 것은 많은 문제를 야기할 수 있다.
2. Koin에서 Hilt로 넘어가는 가이드가 없어서 각 서비스마다 현재 상황에 맞게 판단하자
3. 주입에 대한 Test코드가 잘 작성되어 있다면, Hilt를 반드시 도입할 필요는 없다.
4. Dagger2에서 보일러플레이트를 작성하는 데에 있어 어려움이 있었다면 Hilt는 필수다.
5. 동적으로 주입하는 코드가 많다면, Hilt를 재고하자
6. 멀티모듈 사용 시 무분별한 주입을 했다면, Dependency Graph를 명확히 정하자

 

4. 15:20 타임

[ Track 1 ] 2021 Junior Jetpack 

굉장히 짧은 발표였다. 내용은 이렇다.

 

MVC, MVP, MVVM 패턴을 각 등장 이유를 찾아보며 각 패턴의 장단점을 이해할 수 있다.
Spring boot를 경험해보면 아키텍쳐 이해에 도움이 될 수 있다.

CI/CD를 위해서 이해해야하는 개념 :

 - Git(Pull-Request, Merge)

 - JUnit/UnitTest

 - Github Action/Jenkins

 

5. 15:35 타임

이땐 관심있는 주제가 없었다. AppBundle괴담? Android Native 모듈 안정적인 개발?

흠.. 아직 먼 이야기 같았다. 이때 머리 식힐 겸 요즘 보던 오징어게임 봤다ㅋㅋ

 

6. 16:10 타임

[ Track 1 ] Jetpack Compose에 있는것, 없는 것

compose가 뭔지 잘 몰랐는데 이번에 조금 알게 되었다. compose는 근간이었던 view시스템과 레이아웃이 사라지는 시스템이고 학습할 것이 많다고 한다.

 

compose는 상속으로 인한 문제를 해소시킨다. (View는 반드시 상속해야만 하고, 그래서 원치않는 부모의 기능도 갖게 된다.) 아래의 장점들이 있다.

1. 상속으로 인한 문제 해소

2. 지연 초기화

3. 데이터 바인딩 불필요

4. 커스텀 뷰 구현

 

compose는 네웹인턴할때 한 번 커피챗 시간때 잠깐 나눴던 Topic이다. 그래서 대충 아 이런게 있구나~ 정도만 알고 있었는데 역시나 어렵다. 나중에 더 공부해봐야할 주제 같다.

 

[ Track 2 ] Android Testing Best Practices

우선 Test Code를 왜 써야하는가에 대한 대답을 주셨다.

생산성을 증대시킨다. 이게 무슨말인가? 하면 

확신을 갖고 시스템을 수정할 수 있다. 따라서 협업을 촉진시킨다.(올바른 의도, 사용법을 단번에 파악 가능)

 

테스트코드를 구현하는 방법(총 3단계)

1. 작은, 독립적인 부분부터 시작

2. 실제로 더 도움이 되는 테스트 코드를 적용

 - 실제에 가까운 단위 테스트 만들기

  1순위 : 의존성 관계에 있는 진짜 코드를 사용하라

  2순위 : 라이브러리에 의해 제공되는 표준 fake를 사용

  3순위 : 위의 방법이 불가할 때 mock 사용

3. 패자 부활전(이전에 잘 돌아갔던 테스트가 어느 순간 fail된다. 이유는 Brittle test! 확장성이 있어야한다.)

 

위의 2번이 나에겐 특히 중요한 내용같다. 왜냐하면 가급적 mock를 쓰는 것은 바람직하다고 생각했는데 그렇지 않았다. 실제상황과 비슷한 환경을 만들 수 있으면 그렇게 하는 것이 좋다는 것이 납득이 갔다!

 

Test Code에서 중요한점!!

- 테스트 코드는 완결성과 간결성을 가져야 한다.

  - 테스트가 하고자 하는 것을 명확히 알 수 있어야 하고, 반대로 불필요한 내용은 감춰야 한다.

- 테스트에 로직이 들어가면 안된다.

- 새로운 기능이 추가되더라도 작동하는 확장성이 있어야 한다.

 

7. 16:45 타임

[ Track 1 ] 앱 성능 분석 어떻게 할까?

사용자들을 조사한 결과 아래와 같은 조사가 있다고 한다.

- 75% 사용자 : 사용자 경험에 의해 속도가 중요
- 86% 사용자 : 성능 이슈로 앱 삭제

 

따라서 앱 성능은 상당히 중요한 이슈중에 하나이며, 이를 측정하는 지표는 여러가지가 있다.

ANR, Crash, Rendering, StartUp Time(앱 시작시간), Network ...

이 중에서 StartUp Time에 대해서의 발표자님의 통찰을 말씀해주셨다.

 

우선 StartUp이란? 런쳐에서 앱을 실행하여 사용자가 서비스와 상호작용할 수 있게 되기까지의 과정이다.

SplashActivity를 포함하고, 첫 화면에 들어가서 초기 렌더링이 끝나는것을 말하는 것 같다.

그리고 StartUp에는 3가지 종류가 있다.

- Cold Start : 앱이 메모리에 없을때 처음 시작하는 것

- Hot Start : 앱을 비교적 최근에 닫았고, 다시 foreground에 올라가는것

- Warm Start : 앱을 비교적 오래전에 닫았고, 시스템이 메모리에서 제거했는데 사용자가 re-launch한 경우 (saved instance state bundle이 활용됨)

 

플레이콘솔(Android Vital), Firebase Performance(trace) 에서 StartUp time을 측정할 수 있다.

 

개인적으로 StartUp Time보다는 Network나 CPU성능의 정확한 분석을 기대했는데 쪼~~끔 아쉬웠다.

 

같은 시간대의 Track2 이다. 

[ Track 2 ] Asynchronous Programming for Android

Android 에서 비동기 프로그래밍의 방법론을 비교하셨다.

RxJava, Coroutine + suspend fun, Coroutine Flow에 대해서 비교분석하셨다.

다른 발표들은 deep한 내용들을 다루고 있어서 안드로이드 초심자들에겐 어려울 수있는 내용이었는데, 이부분은 Junior를 위한 발표 같았다. 

 

1. RxJava

- 다양한 연산자(operator)가 있다. flatMap, subscribeOn, observeOn..

- subscribeBy(onError) 를 통해 쉬운 에러 핸들링이 가능하다

 

2. coroutine + suspend fun

- ViewModel에서는 viewModelScope를 사용해서 ViewModel의 라이프사이클을 따라간다.(RxJava보다 메모리 핸들링에서 장점을 가진다)

- suspend fun에서는 try-catch가 최선이다.(별로 이쁘지가 않다.)

- 스트림과 operator가 없어서 코드 이해가 쉽다.

- Sequential Code 구조이다.(이는 RxJava도 마찬가지다. sequential하다는 것은 콜백이 없어서 가독성이 좋다.)

 

3. coroutine Flow

- RxJava의 onError를 catch라는 operator로 에러핸들링할 수 있다.

- 오퍼레이터 수가 RxJava만큼 많지 않고, 아직 실험적인 부분들이 있다.

 

RxJava vs Coroutine Flow

 

RxJava vs Coroutine+suspend fun

 

결론

높은 수준의 작업과 데이터를 사용한다면? -> RxJava, Flow

실시간(real time) 데이터 작업? -> RxJava, Flow

반대로 네트워크 작업이 screen에서 1,2번이다? -> coroutine + suspend fun

 으로 사용하면 적절할 것으로 보인다.

 

새로 프로젝트를 만든다면 RxJava를 적용해서 할지, Flow를 적용해서 할지 고민이 되었는데

안정적인 RxJava로 하는게 낫겠다는 생각이 들었다. Flow가 아직 실험적이며 개선되고 있고, RxJava의 방식과 비슷할 것 같다는 이유 때문이다.

 

 

마무리하며..

어떻게 보면 조금은 많은 사람들이 알고 있는 내용일 수도 있는 내용도 포함되어 있고, 자신만의 아이디어로 독특하게 문제를 해결한 경험을 들려주시는 것들도 있었다. 뭐가 됐든 저 자리에서 발표할 수 있다는 것이 멋있는 것 같다. 개발적인 정보 전달 외로도 사람 대 사람으로서 자극이 되는 날이다.

코로나가 종식되고 오프라인으로 진행하면 더 재밌을 것 같다.