반응형

 

#Firebase 를 대처할만한 편리하고 저렴하게 사용할 수 있는 backend solution인 supabase 소개는 따로.!

 

Supabase에서 Database를 생성하고 나서, database 를 사용하는 방법은 다음과 같습니다.

 

supabase guide 를 보면 쉽게 따라하실수 있습니다.

https://supabase.com/docs/reference/dart/upgrade-guide?queryGroups=version&version=2.0x

 

Flutter: Upgrade guide | Supabase Docs

Initialization does not await for session refresh In v1, Supabase.initialize() would await for the session to be refreshed before returning. This caused delays in the app's launch time, especially when the app is opened in a poor network environment. In v2

supabase.com

 

 

 

지금 하고 싶은 이야기는 이미 supabase를 사용하고 계시는 분들에게 유용한 기능인데요.

 

# database 컬럼으로 json 활용

database를 만들어 사용하다 보면, 데이터중에  json 으로 데이터를 넣어야 하는 경우가 있습니다.

 

 

그런데, json 으로 데이터 컬럼을 추가 할경우, 쿼리 할때 데이터를 가져온다음에 name 이나 type을 비교해야 하는 상당히 불편한 부분이 생깁니다.

다행히도 supabase의 eq() 함수는 json data 내부의 필드값을 접근 할 수 있는 기능을 제공합니다.

https://supabase.com/docs/reference/dart/using-filters

final data = await supabase
  .from('test')
  .select()
  .eq('data->type', 'hello');

 

 

 

# eq 의 -> 가 에러가 발생

그런데 안타깝게도 아래와 같은 에러가 발생 할 수 있습니다.

 

PostgrestException(message: invalid input syntax for type json, code: 22P02, details: The input string ended unexpectedly., hint: null)

 

 

아 !,  -> 기능으로 json 내부 접근해서 쿼리 할수 있을 줄 알았는데 동작을 안하네??? 이러고 좌절 하실수 있는데요.

걱정하지 마세요 !

 

제가 찾아본 자료에서는 json 내부에 접근하는 접근자  몇가지 있는데요.

가이드에 나와있는 접근자로는 오류가 발생하고 다른 접근자를 사용하면 됩니다.

가이드에 적힌 '->' 느ㄴ son형태의 값을 넘기는 것이고, '->>'를 사용하면 text 값을 정상적으로 처리할 수 있습니다.

 

final data = await supabase
  .from('test')
  .select()
  .eq('data->>type', 'hello');

 

이렇게 사용하면 정상적으로 eq 가 동작합니다.

 

 

#json, jsonb 의 차이 및 접근자에 대해서 더 알고 싶다면

 

OperatorRight Operand TypeDescriptionExampleExample Result

-> int Get JSON array element (indexed from zero, negative integers count from the end) '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 {"c":"baz"}
-> text Get JSON object field by key '{"a": {"b":"foo"}}'::json->'a' {"b":"foo"}
->> int Get JSON array element as text '[1,2,3]'::json->>2 3
->> text Get JSON object field as text '{"a":1,"b":2}'::json->>'b' 2
#> text[] Get JSON object at specified path '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}' {"c": "foo"}
#>> text[] Get JSON object at specified path as text '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' 3

https://www.postgresql.org/docs/9.5/functions-json.html

 

 

[참고]

https://yeongunheo.tistory.com/entry/PostgreSQL-json-jsonb-%ED%83%80%EC%9E%85%EA%B3%BC-%EC%97%B0%EC%82%B0%EC%9E%90

 

[PostgreSQL] json, jsonb 타입과 연산자

데이터베이스 테이블 내 하나의 컬럼에 JSON 데이터를 저장하는 경우가 있습니다. 보통 외부에서 제공된 데이터를 별도의 처리 없이 그대로 저장할 때 JSON 타입으로 저장하게 됩니다. PostgreSQL은 J

yeongunheo.tistory.com

 

 

#해피코딩

'Supabase' 카테고리의 다른 글

[supabase] postgres plv8 활성화  (0) 2025.01.24
[Supabase] Edge function 만들기  (0) 2024.12.11
반응형

 

JSON은 상당히 편리하면서 직관적인 데이터 형식이죠.

그래서 사람들이 많이 사용합니다.

 

코딩을 하다보면, json을 그대로 사용하기 보다는 보통 필요한 데이터 형을 class로 만들고 이를 json으로 encoding/decoding 하는 방식으로 많이 사용합니다.

 

그런데  매번 class 만들고 fromJson(), toJson()을 만들어서 사용하는것이 상당히 번거롭고, 실수할 때가 많습니다.

 

그래서 fromJson, toJson을 구현해주는 모듈들이 있죠.

대표적으로 json_serializable 이 있죠.

이를 활용하면 쉽게 json 변환이 가능한 data class를 정의 할 수 있습니다.

 

저는 요즘 freezed 라는 모듈을 주로 사용합니다.

 

freezed 2.5.7

https://pub.dev/packages/freezed

 

freezed | Dart package

Code generation for immutable classes that has a simple syntax/API without compromising on the features.

pub.dev

 

이 freezed 는 json_serialiazble 을 이용하여 data class를 구현해주는 모듈인데요. 제가 이를 사용하게 된 계기는 deep copy 때문이었습니다.

 

freezed는 fromJson, toJson 뿐만 아니라 copyWith() 함수를 자동으로 구현 해줍니다. 그리고 copyWith() 를 수행할때 멤버들의  copyWith()를 수행해서 전체가 복사가 됩니다.

이것이 하나의 큰 장점이고,

freezed 로 선언된 data class는 내부 데이터를 변경할 수 없습니다.

변경하려면, copyWith()로 특정 데이터만 변경해서 복사해서 사용해야 합니다.

그렇지 않고 변경가능한 class를 만들고 싶다면, @unfreezed를 이용합니다.

 

 

주의점!

간혹  freezed 로 정의한 class의 멤버중에 freezed로 되어있지 않은 class들을 데이터로 포함할 경우가 있습니다.

그런데 간혹, toJson() 이 정상적으로 동작하지 않을때도 있는데요.

이럴때 toJson()이 불리도록 explicitToJson  설정이 필요할때가 있습니다.

@unfreezed
class MyDataModel with _$MyDataModelModel {
  @JsonSerializable(explicitToJson: true)

  factory MyDataModel({
    required int id,
    required String name,
    DateTime? created_at,
    DateTime? updated_at,
    required Map<String, Health> data,
    bool? is_demo,
  })= _MyDataModel;

예를 들면 위와 같이 클래스를 정의한 경우, Health라는 class에 fromJson, toJson 을 구현 해놨다 하더라도, MyDataModel의 toJson()을 호출할때 Health의 toJson()이 호출되지 않습니다.

이유는 자동으로 생성된 코드에 Health의 toJson()을 호출하는 코드가 생성되지 않기 때문인데요.

이런 경우, toJson()이 불리도록,   @JsonSerializable(explicitToJson: true) 을 class 밑에 선언해 줍니다.

 

#해피코딩

+ Recent posts