Skip to content

React Native Realm 적용(Typescript)

Published: at 오전 12:00

내가 다른 사람들에게서 받은 선물을 기록하고 저장하는 앱을 React Native로 개발하려고 합니다.

인터넷 연결이 없어도 사용할 수 있게 제작하려 해서 realm을 이용하여 개발을 진행했습니다.

설치

yarn add realm @realm/react react-native-get-random-values
yarn add -D @realm/babel-plugin @babel/plugin-proposal-decorators

관련 패키지를 먼저 설치해줍니다.

저는 yarn을 이용하고 있어서 yarn을 사용했지만 npm을 이용하시는 분은 npm으로 설치를 진행해주세요.

ts.config.json

// prettier-ignore
{
  "extends": "@tsconfig/react-native/tsconfig.json",     /* Recommended React Native TSConfig base */
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig.json to read more about this file */

    /* Completeness */
    "skipLibCheck": true,                                 /* Skip type checking all .d.ts files. */
    "experimentalDecorators": true
  }
}

먼저 ts.config.json 파일에 experimentalDecorators 옵션을 true로 설정해줍니다.

babel.config.json

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    '@realm/babel-plugin',
    ['@babel/plugin-proposal-decorators', {legacy: true}],
  ],
};

다음으로 babel.config.json 파일에 plugins에 위와 같이 realm/babel-plugin을 추가해주세요.

index.js

import "react-native-get-random-values"; // 해당 라인 추가
import { AppRegistry } from "react-native";
import App from "./src/App";
import { name as appName } from "./app.json";

AppRegistry.registerComponent(appName, () => App);

react-native-get-random-values를 import 해주세요.

고유한 id를 생성할 때 사용합니다.

Object Schema 정의

models/gift.ts

import { Realm } from "@realm/react";

export class Gift extends Realm.Object<Gift> {
  _id: Realm.BSON.ObjectId = new Realm.BSON.ObjectID();
  name!: string;
  price?: number;
  peopleId!: Realm.BSON.ObjectId;

  static primaryKey = "_id";

  constructor(
    realm: Realm,
    name: string,
    peopleId: Realm.BSON.ObjectId,
    price?: number
  ) {
    super(realm, { name, peopleId, price });
  }
}

저는 src 폴더에 models 폴더를 생성하고 해당 폴더에서 object schema를 관리하기로 하였습니다.
!는 required
?는 optional
=을 붙여서 값을 할당해주면 default 값을 줄 수 있습니다.

constructor에서 name과 peopleId는 required니 필수로 받아주고 price는 optional 하게 받아줍니다.

Context 생성

models/index.ts

import { createRealmContext } from "@realm/react";
import { Gift } from "./gift";

export const RealmContext = createRealmContext({
  schema: [Gift],
});

context를 생성해줍니다.
이전에 만들었던 Gift 클래스를 schema로 줍시다.

App.tsx

import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import RootStack from "./routers/RootStack";
import { SafeAreaView, StyleSheet } from "react-native";
import { RealmContext } from "./models";

const App = () => {
  const { RealmProvider } = RealmContext;

  return (
    <SafeAreaView style={styles.container}>
      <RealmProvider>
        <NavigationContainer>
          <RootStack />
        </NavigationContainer>
      </RealmProvider>
    </SafeAreaView>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

그 후 RealmProvider로 App을 감싸줍니다.

사용법

read

import React, {useEffect, useMemo} from 'react';
import {RealmContext} from '../models';
import {People} from '../models/people';
import {Gift} from '../models/gift';

const {useQuery} = RealmContext;

export default function Gifts({route, navigation}: Props) {
  const result = useQuery(Gift);

  console.log(result)

  ...
}

RealmContext에서 useQuery를 가져와 Gift를 넘기면 Gift 목록을 확인할 수 있습니다.

filter

const gifts = useMemo(
  () => result.filtered("peopleId == $0", _id),
  [result, _id]
);

해당 결과를 filter하고 싶다면 filtered를 사용합니다.
$를 사용해서 매개변수를 사용할 수 있습니다.(여러 개를 넣게 된다면 $0, $1, $2)
해당 예시는 _id에 해당하는 peopleId를 filter하는 예시입니다.

create

import React from 'react';
import {useForm, Controller} from 'react-hook-form';
import {RealmContext} from '../models';
import {Gift} from '../models/gift';

interface Form {
  name: string;
  price: string;
}

const {useRealm} = RealmContext;

export default function AddGift({navigation, route}: Props) {
  const realm = useRealm();
  const {_id} = route.params;
  const {
    control,
    handleSubmit,
    formState: {isValid},
  } = useForm<Form>();

  const onValid = async ({name, price}: Form) => {
    realm.write(() => {
      return new Gift(realm, name, _id, +price);
    });
    navigation.goBack();
  };

  ...
}

새로운 Gift를 생성하는 예시입니다.
react-hook-form을 사용하였으며 realm.write 내에서 new Gift의 생성자 매개 변수만 올바르게 넣어주신다면 문제없이 생성할 수 있습니다.

get

const { useObject } = RealmContext;

const gift = useObject(Gift, _id);

id로 한 객체만 가져오고 싶을땐 useObject를 사용합니다.

이 외에도 delete, update등 필요하신 작업들은 공식문서를 참고하시면 쉽게 구현 가능합니다.