Skip to content

[기술 공유] Android 라이브러리 비교

주재현 edited this page Dec 14, 2023 · 2 revisions

Android 라이브러리 비교

  • Retrofit

    okhttp를 네트워크 계층으로 활용하고 그 위에 구축된 상위 구현체

    장점

    • 빠른 성능

    AsyncTask를 사용하는 okhttp에 비해 3~10배의 성능차이

    • 간단한 구현

    HttpUrlConnection의 Connection / Input&OutputStream / URL Encoding 생성 및 할당의 반복작업

    OkHttp의 쿼리스트링, Request / Response 반복 설정 작업

    • 가독성

    Annotation 사용으로 코드의 가독성이 뛰어남, 직관적인 설계가 가능

    • 동기 / 비동시 쉬운 구현

    이전에 사용되던 HttpClient(Deprecated)와 달리 별도의 Async Task 없이 실제 네트워킹 코드는 OkHttp에서 관리하는 Thread Pool을 사용하게 됨 -> 속도와 성능이 크게 개선 (Coroutine과 같이 구현하는 방식을 선호). 네트워크 통신을 할 때 따로 thread pool을 신경쓰지 않아도 된다.

  • DI (Dependency Injection)

    의존성 주입은 다른 객체가 필요로 하는 객체를 직접 생성하는 대신에, 이를 외부에서 생성하고 전달받는 방식으로 구현하는 것을 의미합니다.

    안드로이드에서는 의존성 주입을 통해

    • 앱의 여러 컴포넌트에서 공통적으로 사용되는 객체를 한 곳에서 관리하고,
    • 이를 통해 코드의 중복을 줄이고
    • 유지보수와 테스트 용이성을 증가시킬 수 있습니다.

    하지만 수동으로 의존성을 주입하게 된다면 대규모 앱의 경우에는 대규모의 보일러 플레이트 코드가 발생할 수 있고, 의존성을 전달하기 전에 구성할 수 없을 때(지연 초기화나 객체 범위를 앱의 흐름으로 지정할 때) 메모리에서 의존 항목의 전체 기간을 관리하는 맞춤 컨테이너를 작성하고 유지해야 합니다. 이를 방지하기 위해 자동으로 의존성을 주입해주는 라이브러리를 사용하게 되었습니다.

    안드로이드 개발에 사용하는 의존성 주입 라이브러리는 주로 Koin과 Dagger-Hilt 인데, 저희는 이번 프로젝트에서 Hilt를 선택했고, 그 이유는 다음과 같습니다.

    • Koin은 Kotlin DSL을 사용하고, 러닝커브가 낮아 빠르게 적용이 가능하며 별도 어노테이션을 사용하지 않기 때문에 컴파일 시간이 단축된다는 장점이 있지만, 런타임에 서비스 로케이팅을 통해 인스턴스를 동적으로 주입해주기 때문에 런타임 퍼포먼스가 떨어지고, 리플렉션을 이용하기 때문에 성능 상 좋지 않다는 단점이 있습니다.
    • Hilt는 Jetpack의 권장 라이브러리이며, Dagger2를 기반으로 빌드되었기 때문에 Dagger의 이점을 가질 수 있습니다(리팩토링 / 테스트 용이, 보일러 플레이트 코드 감소). 그러면서도 Dagger 보다 기본 설정이 쉽고, 안드로이드 클래스에 최적화되어있습니다. 또한 컴파일 타임에 주입에 대한 검증을 마치기 때문에, 컴파일 타임에 에러를 검출할 수 있습니다.
  • Json Converter

    • 직접 파싱의 단점

    JSON 포맷을 메모리상의 데이터화 하기 위해서는 파싱을 요합니다.

    하지만 파서를 직접 구현하기에는 너무 많은 작업을 필요로 하는 단점이 있습니다.

    우선 직접 파싱을 하기 위해서는 구문 분석이 필요합니다.

    문자열을 분석을 해서 그것을 이루고 있는 구성 성분은 분해하고, 그들 사이 관계를 구조화하는 작업이 필요합니다.

    그리고 항상 규칙에 맞는 데이터만 입력을 받는 것이 아니기 때문에 여러 상황에 대한 예외처리도 필요합니다.

    이런 단점이 있어서 대표 라이브러리 3개 GSON, Kotlin Serialization, Moshi를 비교하여 어떤 라이브러리가 우리 프로젝트에 맞는 라이브러리인지 판단하고 적용하기로 했습니다.

    • gson

    자바 기반

    retrofit을 사용할 때 쉽게 직렬화/역직렬화 가능

    default value가 적용되지 않을 수 있음

    NPE 발생 가능성

    maintenance

    GSON은 구글에서 개발한 Java 객체를 JSON형식으로 변환하는 라이브러리입니다.

    데이터 클래스에 Java annotation을 사용하지 않아도 된다는 장점이 있습니다.

    사용법으로는 GSON 객체를 만들어서 gson.toJson(data)gson.fromJson(jsonString, T::class.java)으로 Java 객체와 JSON사이의 변환이 가능합니다.

    dependency도 한 줄이면 OK!

    dependencies {
      implementation 'com.google.code.gson:gson:2.10.1'
    }
    
    
    • kotlinx.serialization

    kotlinx.serialization은 kotlin의 라이브러리이며 JVM, JavaScript, Native를 지원합니다.

    데이터 클래스에 @Serializable주석을 추가하면 자동으로 내장된 serializer를 사용해서 변환할 수 있게 해줍니다.

    사용법으로는 별도의 객체 생성 없이 함수를 바로 호출해서 Json.encodeToString(data), Json.decodeFromString<T>(jsonString) 으로 Java 객체와 JSON 사이의 변환이 가능합니다.

    컴파일 타임에 에러 검출

    default value 처리 가능

    • Moshi

    Moshi는 Android를 위한 JSON 라이브러리이며 Java, Kotlin에서 JSON 데이터를 처리할 때 사용됩니다.

    Moshi는 특히 Kotlin과의 높은 호환성을 가지며 Gson보다 더 빠른 것으로 알려져 있습니다.

    Moshi의 특징으로는 Java 객체와 JSON간의 변환을 @FromJson 과 @ToJson주석을 사용해서 직접 규칙을 정할 수 있습니다.

    높은 성능과 속도 (대용량 데이터 빠르게 처리)

    default value 무시

    사용법으로는 먼저 어댑터 moshi.adapter<T>()를 만들고, jsonAdapter.fromJson(jsonString), jsonAdapter.toJson(data)을 사용해서 JSON과 객체 간 변환을 할 수 있습니다.

    ex)

    // JSON
    {
      "title": "Blackjack tournament",
      "begin_date": "20151010",
      "begin_time": "17:04"
    }
    
    // Event 클래스
    class Event(
      val title: String,
      val beginDateAndTime: String
    )
    
    // JSON포맷에 맞는 클래스
    class EventJson(
      val title: String,
      val begin_date: String,
      val begin_time: String
    )
    
    // Event 클래스를 JSON 포맷에 맞게 변환하는 어댑터
    class EventJsonAdapter {
      @FromJson
      fun eventFromJson(eventJson: EventJson): Event {
        return Event(
          title = eventJson.title,
          beginDateAndTime = "${eventJson.begin_date} ${eventJson.begin_time}"
        )
      }
    
      @ToJson
      fun eventToJson(event: Event): EventJson {
        return EventJson(
          title = event.title,
          begin_date = event.beginDateAndTime.substring(0, 8),
          begin_time = event.beginDateAndTime.substring(9, 14),
        )
      }
    }
  • 이미지 라이브러리

    Glide

    안드로이드 공식문서에서 추천하는 이미지 라이브러리

    이미지 로딩 속도가 빠름

    ImageView의 크기만큼 캐싱

    썸네일 기능으로 좀 더 쾌적한 UI 제공

    RGB_565

    Picasso

    gif 사용 불가

    원본 이미지를 캐싱하기 때문에 빠른 로딩을 하려면 resize 작업 필요

    ARGB_8888

    Coil

    Compose를 사용할 때 공식문서에서 추천하는 이미지 라이브러리

    Coroutine 기반으로 설계됨

    Fresco

    간편한 이미지 변환

    ImageView가 아닌 Fresco의 DraweeView를 사용해야 함

    DraweeView가 wrap_content를 지원하지 않음

  • Hilt @Provides vs @Binds

    InjectClassFactory의 생성 유무.

    공통점

    • @InstallIn으로 정의된 모듈 내부에서 종속성 주입을 위해 사용

    차이점

    • Binds - 인터페이스와 인터페이스의 구현체를 연결하는 데 사용
      • @Binds의 메서드는 추상 메서드여야 한다. abstract 키워드 요구
      • 동일한 인터페이스에 여러 개의 인터페이스 구현체를 연결할 수 없다.
      • 주입될 타입은 인터페이스이다.
    • Provides - 종속성 객체를 생성, 제공하는 메서드를 정의할 때 사용. (@Binds 외의 경우)
      • 종속성을 제공하는 데 의미가 있으므로, 반환값이 존재해야 함.
      • 복잡한 종속성을 제공하거나 외부 라이브러리를 제공하는 데 사용됨
      • 주입될 타입은 인터페이스, 클래스 등 다양

🚩SnapPoint🚩

Android 기술적 도전

Backend 기술적 도전

🤖기술 공유🤖

Android

Backend

📖회의록📖

스크럼
팀회고, 개인회고
Clone this wiki locally