[Android] Apollo-Client 커스텀 타입

H43RO·2021년 9월 25일
2

Android 와 친해지기

목록 보기
14/26
post-thumbnail

Custom Type

GraphQL 에서는 다양한 스칼라 타입 (단 하나의 값만을 저장할 수 있는 데이터 타입) 을 주고받을 수 있는데, 스칼라 타입은 우리가 알고 있는 기본적인 자료형을 지원할 뿐만 아니라, 서버 개발자가 직접 정의한 커스텀 스칼라 타입 또한 주고받을 수 있다.

GraphQL 에 내장되어 있는 기본 스칼라 타입은 이러한 것들이 있다.

  • Int : 부호가 있는 32비트 정수
  • Float : 부호가 있는 부동소수점 값
  • String : UTF-8 문자열
  • Booleantrue 또는 false

아래는 URL 이라는 커스텀 타입이 정의되어 있는 경우이다. 누구나 알다시피, 이 URL 타입이 갖고있는 값은 String 타입으로 매핑될 수 있다. 어차피 https://velog.io/@haero_kim 와 같은 모양일테니까.

커스텀 스칼라 타입을 정의하면, 해당 값이 어떤 역할을 하는 값인지에 대해 깔끔하게 명시할 수 있어 편리하다는 장점이 있다.


Apollo-Client 의 역할

안드로이드용 Apollo-Client 는 다양한 쿼리, 뮤테이션에 사용되는 스칼라 타입들에 대해 자동으로 Kotlin 의 자료형에 적절히 대응 (매핑) 해준다. 예를 들어 이런 상황이다.

GraphQL 의 내장 스칼라 타입인 StringKotlin 의 kotlin.String 으로 어댑팅하여 코틀린의 String 타입으로 자유 분방하게 사용할 수 있는 것이다.

여기서 문제점!

하지만, 위에서 살펴봤던 예시인 URL 이라는 커스텀 타입은 어떨까? Apollo-Client 는 이 타입을 Kotlin 의 어떤 자료형에 매핑해야 할지 알 길이 없다. 따라서 이럴 경우 Any 로 컴파일 되게 된다.

Any 타입은 코틀린 최상위 클래스이기 때문에, 이를 적절히 활용할 방안이 없다. 그냥 데이터가 유실된 것과 다름 없다. 따라서 우리는 GraphQL 의 커스텀 스칼라 타입을 코틀린의 어떤 타입으로 직렬화 할 지에 대해 따로 정의해주어야 한다.

Apollo-Client 에서는 이러한 것 역시 편리하게 구현할 수 있다.


Custom Type Adapter

커스텀 스칼라 타입을 코틀린의 클래스로 매핑하기 위해, Custom Type Adapter 라는 것을 활용할 수 있다. 이번 예시에서는 URL 이라는 커스텀 타입을 예로 들겠다.

목표

URL 타입을 코틀린의 String 타입으로 변환해보기

Gradle 설정

먼저, app 단위의 build.gradle 에서 아래와 같이 설정해준다.

apollo {
    generateKotlinModels = true
    customTypeMapping = [
            "URL" : "kotlin.String"
    ]
}

이렇게 하면 URL 이라는 녀석을 kotlin.String 클래스에 매핑하겠다는 의미이다.

Adapter 정의

그 다음 아래와 같이 Custom Type Adapter 를 정의해주자.

decode()encode() 메소드를 통해 커스텀 타입을 어떻게 해석하고, 어떻게 다시 GraphQL 커스텀 스칼라 타입으로 변환할 지에 대해 정의해주는 것이다.

val urlTypeAdapter = object : CustomTypeAdapter<String> {
    override fun decode(value: CustomTypeValue<*>): String {
        return try {
            value.value.toString()
        } catch (e: ParseException) {
            throw RuntimeException(e)
        }
    }

    override fun encode(value: String): CustomTypeValue<*> {
        return CustomTypeValue.GraphQLString(value)
    }
}

Adapter 추가

이제 우리가 만든 어댑터를, ApolloClient 객체에 붙여주기만 하면 된다.

addCustomTypeAdapter() 를 통해 '어떤 커스텀 타입에 대한 어댑터인지'와 우리가 정의한 어댑터를 넘겨주게 되면 정상적으로 등록된다.

참고로 CustomType 은 이전에 다운받은 스키마 파일을 기반으로 자동으로 생성되는 enum 클래스이므로 걱정하지 않아도 된다.

val apolloClient: ApolloClient = ApolloClient.builder()
    .serverUrl(serverBaseUrl)
    .addCustomTypeAdapter(CustomType.URL, urlTypeAdapter)
    .build()

이후 Rebuild 를 한 번 돌리게 되면, URL 타입은 kotlin.String 타입으로 매핑되어, 친숙한 String 형태로 자유자재로 사용할 수 있다.


다음 포스팅에선 파일을 업로드하는 방법에 대해 알아보고자 한다.

profile
어려울수록 기본에 미치고 열광하라

0개의 댓글