Supabase 버전업 트러블 슈팅

오리·2024년 8월 31일

realtime을 제대로 사용하기 위해 미루고 미루던 supabase version upgrade를 하기로 했다

0.7.x → 2.6.0 으로 올린 만큼 소스코드에도 변경사항이 많이 생겼다. (업보빔)

postgreSQL을 사용하는 거의 모든 함수들을 수정했다.

빌드한 후 마주한 오류들을 정리해보았다.

snake_case 강제 변환

이 앱은 supabase에서 camelCase를 사용하고, 앱에서도 camelCase를 사용한다.

근데 아래와 같은 오류가 난다.

io.github.jan.supabase.exceptions.BadRequestRestException: column Favorites.user_id does not exist (Perhaps you meant to reference the column "Favorites.userId".)

user_id 를 찾는 거 같은데 없다! 라는 오류인데, 나는 user_id를 찾은 적이 없다.


User filters 에서 디폴트로 알아서 바꿔주고 있었던 것인데 이 앱에선 필요가 없다.

config에서 바꿔주자!

   install(Postgrest) {
      propertyConversionMethod = PropertyConversionMethod.NONE
    }

찾아보다 보니까 postgreSQL은 snake_case로 설정하는 것이 좋을 것 같다는 생각이…든다..

큰 따옴표로 묶지 않으면 대문자가 무시되는 것도 그렇고, 이렇게 기본값으로 snake_case를 주는 것도 그렇고 … camelCase 사용으로 인한 다른 문제들도 많은 것 같다.

nullable 한 값을 파싱하지 못한다

kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 355: Unexpected symbol 'n' in numeric literal at path: $[0].monthlyUsage (Ask Gemini)
                                                                                                    JSON input: .....-bcdce03f66dc","monthlyUsage":null,"isTemporary":null,"statu.....

null이 오면 온갖 곳에서 이런 에러가 나고 파싱하지 못한다.

0.7.x 버전에서는 jsonConverter로 직접 파싱해줬는데, supabase client에서 따로 파싱 해주는 방식으로 바뀐듯.

supabase client 자체에서 커스텀 serializer를 설정해주는 방법을 찾았다!

supabase-kt provides several different ways to encode and decode your custom objects. By default, KotlinX Serializationis used.

 @Singleton
 @Provides
  fun provideSupabaseClient(application: Application): SupabaseClient = createSupabaseClient(
    supabaseUrl = BuildConfig.SUPABASE_URL,
    supabaseKey = BuildConfig.SUPABASE_API_KEY
  ) {
    defaultSerializer = KotlinXSerializer(Json {
      ignoreUnknownKeys = true
      coerceInputValues = true
      encodeDefaults = true
      isLenient = true
    })
    }
  }

설정 값은 아래와 같다.

  • ignoreUnknownKeys = true:
    • JSON 데이터에 클래스에서 정의되지 않은 키가 포함되어 있어도 무시하고 파싱
  • coerceInputValues = true:
    • JSON 데이터가 클래스에 정의된 필드 타입과 일치하지 않는 경우, 해당 값을 기본값으로 강제
  • encodeDefaults = true:
    • 기본값을 가진 프로퍼티도 JSON에 직렬화할 때 포함
  • isLenient = true:
    • JSON 파싱을 할 때 엄격한 규칙을 완화
    • 문자열에 따옴표가 없거나 숫자에 소수점이 없는 등 JSON 규격을 완벽히 준수하지 않는 경우에도 파싱을 시도

BadRequestRestException

io.github.jan.supabase.exceptions.BadRequestRestException: column "creator" of relation "Table" does not exist 

creator는 creatorId 값으로 매핑한 객체인데, 이 컬럼의 기본값이 null이다.

@Serializable
@TypeConverters(Converters::class)
data class Table(
  val id: String? = "",
...
  val creatorId: String = "",
  @Serializable val creator: User? = null,
...
)

table.insert(data)

위 쿼리가 실행될 때 request로 Table(id = "asdf", creatorId = "qwer", creator=null)
creator이 기본값으로 요청되기 때문에 supabase에서는 없는 해당 컬럼을 못찾겠다고 오류를 내는 것!

Kotlinx Serialization의 Json 설정에서 encodeDefaults = false를 사용하면 기본값이나 null 값은 직렬화에서 제외된다고 한다.

    defaultSerializer = KotlinXSerializer(Json {
      ignoreUnknownKeys = true
      coerceInputValues = true
      encodeDefaults = true
      isLenient = true
      encodeDefaults = false  // 기본값이나 null은 직렬화에서 제외
    })

설정 추가하니 잘 무시해서 보내준다.

0개의 댓글