17P by xguru 2022-11-04 | favorite | 댓글 4개
  • Meta의 안드로이드 Repo는 페이스북,인스타그램,메신저,Quest 등이 들어 있는 거대 저장소
  • 현재 약 1000만 라인이 넘는 Kotlin 코드를 포함하고 있음

Kotlin으로 전환한 이유

  • 인기도외에 주요 장점들
    • Nullability : NPE는 Meta에서 공통적인 문제였어서 다양한 대응을 했지만, Kotlin의 내장 Nullability 처리가 훨씬 강력하고 작업이 쉬움
    • 함수형 프로그래밍 : Kotlin의 인라인 함수와 람다 표현식이 실행속도 저하없이 FP 스타일을 적용하게 해줌
    • 더 짧은 코드
    • DSL / Type-safe Builder
  • 물론 무시할 수 없는 약간의 단점도 있음
    • 또 다른 언어를 도입함에 따른 혼합 코드베이스를 꽤 오래 유지해야한다는 점
    • Kotlin이 인기있긴 하지만, 그 인기도 면에서 Java와는 갭이 있긴 함. 그래서 도구들이 더 적으며, 많은 Kotlin 도구가 Kotlin & Java 상호 운용성을 고려해야 해서 구현이 복잡함
  • 가장 큰 걱정 거리는 빌드 시간이었음. 처음부터 Kotlin 빌드시간이 Java보다 느릴수 있다는 것은 알고 있었음. 느린 빌드시간은 개발자 경험에 좋지 않음

마이그레이션에 접근한 방법

  • Kotlin으로의 이관은 놀랍도록 쉬우면서도, 매우 복잡했음
  • J2K(Java To Kotlin Converter)가 있어서 편하긴 하지만, 그래도 복잡합
    • J2K가 항상 정확한 것은 아니고, Java와 Kotlin의 상호 운용성이 몇가지 극단적인 경우를 만듦
  • 마이그레이션에 두가지 옵션이 있었음
    • 새로운 코드만 Kotlin으로 작성하고 대부분의 코드는 Java 그대로 둔다
      • 장점은 일이 적지만, 두언어 혼용때문에 Kotlin 에서 플랫폼 타입을 쓰게 되면서 널포인터 역참조가 발생하여 크래시가 발생하기도 함.
        또 Java에서 타입 파라미터를 Nullable로 태그할수 없다거나(최근까지), Kotlin의 오버로딩 규칙은 Null 허용 여부를 고려하지만 Java의 오버로딩 규칙은 고려하지 않는 다는 이슈도 있음
    • 모든 인하우스 코드를 Kotlin으로 변환 시도한다

마이그레이션 한 방법

  • 두 옵션을 모두 고려했고, 모든 코드를 Kotlin으로 변환하는 것을 목표로 결정
    • 처음엔 좀 느렸지만, 몇몇 블록커를 해결하고 나서는 대량으로 변환이 가능해졌음
    • 현재는 페이스북, 메신저, 인스타그램 각각의 안드로이드 앱들이 1백만 라인의 Kotlin 코드를 포함하고 있으며 점차 변환율이 올라가는 중
    • 현재 전체 안드로이드 코드베이스에는 1천만 라인의 Kotlin 코드가 있음

Unblocking

  • 처음 변환 시작하고 몇몇 이슈가 발생
    • 바이트 코드 패턴 때문에 Redex를 업데이트 필요
    • 일부 내부 라이브러리가 성능때문에 바이트코드 트랜스포밍을 하고 있어서 이게 Kotlin에서 동작을 안했음
    • 내부에서 최적화를 많이 해뒀다면 비슷한 이슈들이 생길 것
  • 기존 도구들에도 문제가 발생
    • 코드리뷰/위키 등에서 Kotlin 구문 강조가 안되어서 Pygments를 업데이트 했음
    • Kotlin 포매터인 Ktfmt를 별도로 개발 했음

마이그레이션 가속화 하기

  • 도구가 준비되어서 코드를 코틀린으로 변환할 준비가 되었음
  • 하지만 각 마이그레이션은 수작업으로 진행해야할 보일러 플레이트 코드가 많았음
  • J2K는 일반적인 도구이므로, 코드에 대한 이해도는 없음. 이때문에 많은 수작업이 필요
    • 예를 들어 JUnit 테스팅 규칙 같은 것
  • 그래서 J2K를 3단계 파이프라인의 중간에 두었음
    • 첫번째로 Java 패키지 한개를 가져다 Kotlin으로 변환할 준비를 함. 버그 수정 및 내부 도구에 필요한 컨버전
    • 두번째로 스크립트를 통한 J2K 자동 실행
    • 세번째로 새 Kotlin 파일을 후 처리. 가장 중요함. 자동 리팩토링/린터등을 헤드리스 모드로 수행
  • 자동화가 모든 문제를 해결해주지는 못하지만, 공통적인 것들을 우선순위화 했음

Kotlin 마이그레이션에서 배운 것

  • 코드 길이가 줄었음
  • 실행 속도는 유지
  • 빌드 크기는 문제가 아님
  • 더 길어진 빌드 시간 문제 해결 : KSP(Kotlin Symbol Processing API) 사용

좋은 글 공유 감사합니다. 개인적으로 kotlin을 처음 쓸 때 java보다 편리한 점이 많아서 좋기도 하고 앞으로는 kotlin이 대세가 되지 않을까 싶었는데, 좀 쓰다보니 아직은 java더 좋다고 생각되는 부분도 많더군요.

  • 언어 자체는 kotlin이 확실히 편리하다고 생각
  • java의 ecosystem이나 troubleshooting 자료가 많은 것에 비해 kotlin은 좀 부족한 부분이 있음.
  • jdk 버전이나 kotlin 버전에 따라서 Java만 쓴다면 겪지 않아도 될 버그나 이슈들이 꽤 있음.
    Android는 kotlin으로 가도 괜찮다고 생각하지만 다른 환경 (Spring 이라던지..) 에서는 안정성이 중요하다면 아직은 Java가 더 나은 선택인 것 같습니다.

안정성의 사례 하나만 알려주실 수 있으실까요? 내공이 적어 아직 그런 사례를 만나보지 못했는데 몹시 궁금합니다

Jetbrains가 마구마구 릴리즈를 찍고있어서 그런지 모르겠지만, 의외로 컴파일러 버그 픽스가 많습니다.
https://github.com/JetBrains/kotlin/releases/tag/v1.7.20

컴파일러 자체가 터지는 경우도 종종 있고(이건 그나마 배포전이니깐 괜찮습니다만), 산출물에도 종종 버그가 포함됩니다.

더군다나 android의 경우에는 R8 bytecode optimiser 도 kotlin 버젼을 가립니다.
왜나면, kotlin 코드 전용 최적화 기능이 있는데 이것에 대한 공식적인 호환성 테이블 문서(Android Gradle Plugin : Kotlin Version)가 없습니다..
그래서 Android 프로젝트에서 코틀린 버젼을 변경할 때 주의해야 합니다;;;

관련 버그 리포트 : https://issuetracker.google.com/issues/207397158

감사합니다. 깊고 넓은 세계가 있군요..