Docs Menu

๋™๊ธฐํ™” ๊ตฌ๋… ๊ด€๋ฆฌ - React Native SDK

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ

Flexible Sync๋Š” ๊ตฌ๋… ๋ฐ ๊ถŒํ•œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ๊ณผ ๋™๊ธฐํ™”ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. Flexible Sync๊ฐ€ ํ™œ์„ฑํ™”๋œ ์˜์—ญ์—์„œ ์ฝ๊ธฐ ๋˜๋Š” ์“ฐ๊ธฐ (write)๋ฅผ ํ•˜๋ ค๋ฉด ๋จผ์ € ๊ตฌ๋…์ด ํ•˜๋‚˜ ์ด์ƒ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @realm/react ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋™๊ธฐํ™” ๊ตฌ๋…์— ๋Œ€ํ•œ ๊ถŒํ•œ ๋ฐ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ„์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ๊ตฌ๋…์„ ์ถ”๊ฐ€, ์—…๋ฐ์ดํŠธ ๋ฐ ์ œ๊ฑฐํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๊ธฐ์— ๋™๊ธฐํ™”ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Realm.js v12.0.0 ์ด์ƒ์—์„œ๋Š” ์ˆ˜๋™์œผ๋กœ ๊ตฌ๋…์„ ๊ด€๋ฆฌํ•˜๋Š” ๋Œ€์‹  ๋˜๋Š” ์ถ”๊ฐ€๋กœ ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋ฐ ๋น„๋Œ€์นญ ๊ฐ์ฒด ๋Š” App Services ๋ฐฑ์—”๋“œ ๋กœ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋ฏ€๋กœ ๊ตฌ๋…์„ ๋งŒ๋“ค ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ค‘์š”

Flexible Sync ์ฟผ๋ฆฌ ์ œํ•œ ์‚ฌํ•ญ

Flexible Sync ๊ตฌ๋…์€ RQL ์ฟผ๋ฆฌ ์—ฐ์‚ฐ์ž์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ง€์›๋˜์ง€ ์•Š๋Š” ์—ฐ์‚ฐ์ž์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Flexible Sync RQL ์ œํ•œ ์‚ฌํ•ญ ๋ฌธ์„œ ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

React Native SDK์™€ ํ•จ๊ป˜ Atlas Device Sync๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋จผ์ € ๋‹ค์Œ ์š”๊ตฌ ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

React Native ํด๋ผ์ด์–ธํŠธ์— Flexible Sync ๊ตฌ๋…์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด:

  1. ๋ฐฑ์—”๋“œ์—์„œ Flexible Sync ๊ตฌ์„ฑ

  2. ์•ฑ ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”

  3. ํด๋ผ์ด์–ธํŠธ์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ

  4. ๋™๊ธฐํ™”๋œ Realm ๊ตฌ์„ฑ

ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๊ตฌ๋… ์ฟผ๋ฆฌ๋Š” ๋ฐฑ์—”๋“œ App Services ์•ฑ์˜ Device Sync ๊ตฌ์„ฑ๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๋… ์ฟผ๋ฆฌ๋Š” ํ•ด๋‹น ์œ ํ˜•์˜ ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ•˜๋‚˜ ์ด์ƒ์˜ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๊ฐ€ ํฌํ•จ๋œ Realm Query Language ์ฟผ๋ฆฌ๋กœ ๊ฒฐ๊ณผ๋ฅผ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ ๊ตฌ์„ฑ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๋ฉด App Services ๋ฌธ์„œ์—์„œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Flexible Sync์™€ ํ•จ๊ป˜ Realm Query Language๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์ œํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๋ ค๋ฉด Flexible Sync RQL ์ œํ•œ ์‚ฌํ•ญ ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๋ฒ„์ „ realm@12.0.0์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ

realm@12.0.0 ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋…ํ•˜๊ฑฐ๋‚˜ ๊ตฌ๋… ์ทจ์†Œํ•˜๋Š” ์‹คํ—˜์  API ์ถ”๊ฐ€. ์ด๋Ÿฌํ•œ API๋Š” ์ˆ˜๋™์œผ๋กœ ๊ตฌ๋…์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ œ๊ฑฐํ•˜๋Š” ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ตฌ๋…์— ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์™€ Flexible Sync ์˜์—ญ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ฒ„์ „ realm@12.3.0์—์„œ ๋ณ€๊ฒฝ๋จ: Atlas Device Sync์—์„œ ์ง€์›๋˜๋Š” ์ง€๋ฆฌ ๊ณต๊ฐ„์  ๋ฐ์ดํ„ฐ

Realm.js v12.3.0 ์ด์ƒ์—์„œ๋Š” ์ง€๋ฆฌ ๊ณต๊ฐ„์  ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ๋…์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „ ๋ฒ„์ „์˜ SDK์—์„œ ์ง€๋ฆฌ ๊ณต๊ฐ„์  ์ฟผ๋ฆฌ๋ฅผ ๊ตฌ๋…ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋ณด์ •์šฉ ์“ฐ๊ธฐ์™€ ํ•จ๊ป˜ ์„œ๋ฒ„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ง€๋ฆฌ ๊ณต๊ฐ„์  - React Native SDK๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๊ตฌ๋…์— ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ตฌ๋…์„ ๋” ์‰ฝ๊ฒŒ ์ฐพ๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ๋… ์ด๋ฆ„์€ ๊ณ ์œ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๊ตฌ๋…๊ณผ ๋™์ผํ•œ ์ด๋ฆ„์œผ๋กœ ๊ตฌ๋…์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ๊ธฐ์กด ๊ตฌ๋…์„ ๋ฎ์–ด์”๋‹ˆ๋‹ค.

์ฟผ๋ฆฌ๋ฅผ ๊ตฌ๋…ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•˜์„ธ์š”:

  1. ์ฝ๊ณ  ์“ฐ๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  2. ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์— ๋Œ€ํ•ด subscribe() ํ˜ธ์ถœํ•˜์—ฌ ์ฟผ๋ฆฌ์™€ ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋™๊ธฐํ™” ๊ตฌ๋…์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

  3. SubscriptionOptions๊ฐ์ฒด์— name ์†์„ฑ์„ ํฌํ•จ์‹œ์ผœ subscribe() ํ•จ์ˆ˜์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

import React, {useEffect, useState} from 'react';
import {useRealm, useQuery} from '@realm/react';
import {View, Text, FlatList} from 'react-native';
import {Bird} from '../../models';
import {Subscription} from 'realm/dist/bundle';
export const BasicSubscription = () => {
const realm = useRealm();
// Get all local birds that have not been seen yet.
const seenBirds = useQuery(Bird, collection =>
collection.filtered('haveSeen == true'),
);
const [seenBirdsSubscription, setSeenBirdsSubscription] =
useState<Subscription | null>();
useEffect(() => {
// Create an async function so that we can `await` the
// promise from `.subscribe()`.
const createSubscription = async () => {
await seenBirds.subscribe({
name: 'Birds I have seen',
});
};
createSubscription().catch(console.error);
// Get the subscription...
const subscription = realm.subscriptions.findByName('Birds I have seen');
// ... and set it to a stateful variable or manage it in `useEffect`.
setSeenBirdsSubscription(subscription);
}, []);
return (
// Work with the subscribed results list or modify the subscription...
<></>
);
};

๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ๊ตฌ๋…์— ์ด๋ฆ„์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ด๋ฆ„์ด null๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

์ด๋ฆ„์ด ์ง€์ •๋˜์ง€ ์•Š์€ ์ฟผ๋ฆฌ ๊ตฌ๋…์— filtered() ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ตฌ๋… ์‹๋ณ„์ž๋Š” filtered ์ฟผ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฟผ๋ฆฌ ๋ฌธ์ž์—ด์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค subscribe()๊ฐ€ ์ƒˆ ๊ตฌ๋…์„ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

API ์ฐธ์กฐ

์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ๊ฒฝ์šฐ ๋™๊ธฐํ™”๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค์šด๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๊ฒฐ๊ณผ์—๋Š” ๊ฐ์ฒด๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋™๊ธฐํ™”๋œ ๊ฐ์ฒด์˜ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ waitForSync ์˜ต์…˜์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์‹œ์—์„œ๋Š” ๊ธฐ๋ณธ ๋™์ž‘์ธ FirstTime ์˜ต์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. FirstTime ๋™์ž‘์ด ์žˆ๋Š” ๊ตฌ๋…์€ ๊ตฌ๋…์ด ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ ๋™๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€๋งŒ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

import React, {useEffect, useState} from 'react';
import {BSON, WaitForSync} from 'realm';
import {useRealm, useQuery} from '@realm/react';
import {View, Text, Button, TextInput, FlatList} from 'react-native';
import {Bird} from '../../models';
import {Subscription} from 'realm/dist/bundle';
export const WaitFirstTime = () => {
const realm = useRealm();
const [birdName, setBirdName] = useState('Change me!');
// Get local birds that have been marked as "haveSeen".
const seenBirds = useQuery(Bird, collection =>
collection.filtered('haveSeen == true'),
);
const [seenBirdsSubscription, setSeenBirdsSubscription] =
useState<Subscription | null>();
useEffect(() => {
const createSubscription = async () => {
// Only wait for sync to finish on the initial sync.
await seenBirds.subscribe({
behavior: WaitForSync.FirstTime,
name: 'First time sync only',
});
};
createSubscription().catch(console.error);
// Get the subscription...
const subscription = realm.subscriptions.findByName('First time sync only');
// ... and set it to a stateful variable or manage it in `useEffect`.
setSeenBirdsSubscription(subscription);
}, []);
return (
// Work with the subscribed results list or modify the subscription...
<></>
);
};

์ง€์›๋˜๋Š” ๋‹ค๋ฅธ WaitForSync ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Always: ์•ฑ์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์•ฑ์„ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ์ธํ„ฐ๋„ท์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • Never: ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋‹ค๋ฆฌ์ง€ ๋งˆ์„ธ์š”. ์•ฑ์„ ์ฒ˜์Œ ์‹คํ–‰ํ•  ๋•Œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆํ•˜๊ธฐ ์œ„ํ•ด ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์ดํ›„ ์‹คํ–‰ ์‹œ ์บ์‹œ๋œ ์ž๊ฒฉ ์ฆ๋ช…์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜คํ”„๋ผ์ธ์œผ๋กœ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ ํƒ์ ์œผ๋กœ timeout ๊ฐ’์„ ์ง€์ •ํ•˜์—ฌ ๋™๊ธฐํ™” ๋‹ค์šด๋กœ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ๊ฐ„์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

export const AlwaysWait = () => {
const realm = useRealm();
// Get all local birds that have not been seen yet.
const unSeenBirds = useQuery(Bird, collection =>
collection.filtered('haveSeen == false'),
);
const [unSeenBirdsSubscription, setUnseenBirdsSubscription] =
useState<Subscription | null>();
useEffect(() => {
const createSubscription = async () => {
// Add subscription with timeout.
// If timeout expires before sync is completed, currently-downloaded
// objects are returned and sync download continues in the background.
await unSeenBirds.subscribe({
behavior: WaitForSync.Always,
name: 'Always wait',
timeout: 500,
});
};
createSubscription().catch(console.error);
// Get the subscription...
const subscription = realm.subscriptions.findByName('Always wait');
// ... and set it to a stateful variable or manage it in `useEffect`.
setUnseenBirdsSubscription(subscription);
}, []);
return (
// Work with the subscribed results list or modify the subscription...
<></>
);
};

API ์ฐธ์กฐ

๊ตฌ๋…์„ ์ทจ์†Œํ•˜์ง€ ์•Š๋Š” ํ•œ ๊ตฌ๋…์€ ์‚ฌ์šฉ์ž ์„ธ์…˜ ์ „๋ฐ˜์— ๊ฑธ์ณ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. unsubscribe()์„(๋ฅผ) ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์˜ ๊ตฌ๋…์„ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ˆ˜๋™์œผ๋กœ ๊ตฌ๋…์„ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ํ™œ์„ฑ ๊ตฌ๋… ๋ชฉ๋ก์—์„œ ๊ตฌ๋…์ด ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

๊ฒน์น˜๋Š” ๊ฐ์ฒด๊ฐ€ ํฌํ•จ๋œ ๋‹ค๋ฅธ ๊ตฌ๋…์ด ์žˆ๋Š” ๊ฒฝ์šฐ unsubscribe()์„(๋ฅผ) ํ˜ธ์ถœํ•œ ํ›„์—๋„ ๊ฒฐ๊ณผ ๋ชฉ๋ก์— ์—ฌ์ „ํžˆ ๊ฐ์ฒด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

unsubscribe()์„(๋ฅผ) ํ˜ธ์ถœํ•˜๋ฉด ์—ฐ๊ฒฐ๋œ ๊ตฌ๋…์ด ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๊ตฌ๋…์€ ์ด๋ฆ„์œผ๋กœ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฆ„์ด ์—†์œผ๋ฉด unsubscribe()์€(๋Š”) unsubscribe()์„(๋ฅผ) ํ˜ธ์ถœํ•œ ์ฟผ๋ฆฌ์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋ชจ๋‘ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์ œ๊ฑฐ๋œ ๊ตฌ๋…๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์˜์—ญ์—์„œ ์‚ญ์ œ๋˜๊ธฐ ์ „์— unsubscribe() ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋™๊ธฐํ™”๋Š” ์ƒˆ ๊ตฌ๋… ์„ธํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค.

import React, {useEffect, useState} from 'react';
import {useRealm, useQuery} from '@realm/react';
import {View, Text, Button} from 'react-native';
import {Bird} from '../../models';
import {Subscription} from 'realm/dist/bundle';
export const Unsubscribe = () => {
const realm = useRealm();
const birds = useQuery(Bird);
const unsubscribeFromQuery = () => {
birds.unsubscribe();
};
return (
<View>
<Button
title="Unsubscribe"
onPress={() => {
unsubscribeFromQuery();
}}
/>
</View>
);
};

API ์ฐธ์กฐ

๊ตฌ๋… API ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ ์˜ ํŠน์ • ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๊ด€๋ฆฌ ์žˆ์Šต๋‹ˆ๋‹ค.

Realm.subscriptions ์ฟผ๋ฆฌ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ ์— ๋Œ€ํ•œ ํŠน์ • ์ฟผ๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ๋ฅผ ๊ด€๋ฆฌ ํ•˜๋Š” API ์ž…๋‹ˆ๋‹ค.

@realm/react์„(๋ฅผ) ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ ์ ˆํ•˜๊ฒŒ ๊ตฌ์„ฑ๋œ ์˜์—ญProvider ๋‚ด์—์„œ ์˜์—ญ ๊ตฌ๋…์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. use์˜์—ญ() ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ํ˜„์žฌ ์—ด๋ ค ์žˆ๋Š” ์˜์—ญ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋…์œผ๋กœ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

๋ฐ์ดํ„ฐ๊ฐ€ ๊ตฌ๋…๊ณผ ์ผ์น˜ํ•˜๊ณ  ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ์ ˆํ•œ ๊ถŒํ•œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, Device Sync๋Š” ๋ฐฑ์—”๋“œ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์•ฑ๊ณผ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๋…์„ ์ƒ์„ฑํ•˜๋ฉด Realm์€ ํŠน์ • ๊ฐ์ฒด ์œ ํ˜•์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ์™€ ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ฐ์ฒด ์œ ํ˜•์— ๋Œ€ํ•œ ๊ตฌ๋…์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ๊ฐ์ฒด ์œ ํ˜•์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ค‘์š”

๊ฐ์ฒด ๋งํฌ

๋งํฌ๋œ ๊ฐ์ฒด๋ฅผ ๋ณด๋ ค๋ฉด ๊ฐ์ฒด์™€ ํ•ด๋‹น ๋งํฌ๋œ ๊ฐ์ฒด๋ฅผ ๋ชจ๋‘ ๊ตฌ๋… ์„ธํŠธ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ๋… ๊ฒฐ๊ณผ์— ๊ฒฐ๊ณผ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ๊ฐ์ฒด์— ์—ฐ๊ฒฐ๋˜๋Š” ์†์„ฑ์ด ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ๋งํฌ๋Š” null๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์†์„ฑ ๊ฐ’์ด ์‹ค์ œ null์ธ์ง€, ์•„๋‹ˆ๋ฉด ๋งํฌ๋œ ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ ์ฟผ๋ฆฌ ๊ตฌ๋…์˜ ํ‘œ์‹œ ์˜์—ญ์—์„œ ๋ฒ—์–ด๋‚œ ๊ฒƒ์ธ์ง€ ๊ตฌ๋ถ„ํ•  ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค.

Flexible Sync๋ฅผ ์œ„ํ•ด ๊ตฌ์„ฑ๋œ RealmProvider ๋‚ด์—์„œ SubscriptionSet์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. SubscriptionSet์€ ์•ฑ์— ๋Œ€ํ•œ ๋ชจ๋“  ๊ตฌ๋…์˜ ์ปฌ๋ ‰์…˜์ž…๋‹ˆ๋‹ค.

import React, {useEffect, useState} from 'react';
import {Text, FlatList} from 'react-native';
import {useRealm, useQuery} from '@realm/react';
import {Bird} from '../Models/Bird';
function SubscriptionManager() {
const realm = useRealm();
// Pass object model to useQuery and filter results.
// This does not create a subscription.
const seenBirds = useQuery(Bird, birds => {
return birds.filtered('haveSeen == true');
});
const [subscriptions, setSubcriptions] = useState<
App.Sync.SubscriptionSet | undefined
>();
useEffect(() => {
const createSubscription = async () => {
// Create subscription for filtered results.
await realm.subscriptions.update(mutableSubs => {
mutableSubs.add(seenBirds, {name: 'seen birds'});
});
};
createSubscription().catch(console.error);
// Set to state variable.
setSubcriptions(realm.subscriptions);
}, []);
return (
<FlatList
data={subscriptions}
keyExtractor={subscription => subscription.id.toString()}
renderItem={({item}) => <Text>{item.name}</Text>}
/>
);
}

API ์ฐธ์กฐ

๋‹ค์Œ ์˜ˆ์‹œ์—์„œ๋Š” completed ๋ฐ progressMinutes์ด(๊ฐ€) App Services App์—์„œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๋กœ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์—์„œ ํ•„ํ„ฐ๋ง๋œ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค.

  • ์™„๋ฃŒ๋œ ์ž‘์—…

  • 120 ์ด์ƒ ๊ฑธ๋ฆฐ ์™„๋ฃŒ๋œ ์ž‘์—… progressMinutes

๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ ค๋ฉด useQuery()์— ํ™œ์„ฑ ๊ตฌ๋…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„์ง ๊ตฌ๋…์ด ์ถ”๊ฐ€๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ useQuery()์€(๋Š”) MutableSubscriptionSet.add()์— ๋Œ€ํ•ด ์œ ํšจํ•œ query ์ด(๊ฐ€) ์•„๋‹Œ ๋นˆ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

import React, {useEffect} from 'react';
import {Text, FlatList} from 'react-native';
import {useRealm, useQuery} from '@realm/react';
function SubscriptionManager() {
const realm = useRealm();
const seenBirds = useQuery(Bird, birds => {
return birds.filtered('haveSeen == true');
});
useEffect(() => {
realm.subscriptions.update(
(mutableSubs: Realm.App.Sync.MutableSubscriptionSet) => {
// Create subscription for filtered collection.
mutableSubs.add(seenBirds, {name: 'seenBirds'});
},
);
});
return (
<FlatList
data={seenBirds}
keyExtractor={item => item._id.toString()}
renderItem={({item}) => <Text>{item._id.toString()}</Text>}
/>
);
}

Flexible Sync ์˜์—ญ์—์„œ ์ฝ๊ฑฐ๋‚˜ ์“ฐ๋ ค๋ฉด ๋จผ์ € ๊ตฌ๋…์ด ํ•˜๋‚˜ ์ด์ƒ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ ๊ตฌ๋…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋™๊ธฐํ™”๋œ ์˜์—ญ์„ ๊ตฌ์„ฑํ•  ๋•Œ ๊ตฌ๋…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ๊ตฌ๋…์œผ๋กœ ๋™๊ธฐํ™”๋œ ์˜์—ญ์„ ์—ด๋ ค๋ฉด initialSubscriptions ์†์„ฑ์„ RealmProvider์˜ ๋™๊ธฐํ™” ๊ตฌ์„ฑ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ดˆ๊ธฐ ๊ตฌ๋…์„ ์„ค์ •ํ•  ๋•Œ @realm/react ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ›… useQuery ๋ฐ useObject์„(๋ฅผ) ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  Realm.js ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ (write) ์ž‘์—…์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

import React from 'react';
import {AppProvider, UserProvider} from '@realm/react';
// get realm context from createRealmContext()
import {RealmContext} from '../RealmConfig';
import {Text, FlatList} from 'react-native';
const {RealmProvider, useQuery} = RealmContext;
function AppWrapper() {
return (
<AppProvider id={APP_ID}>
<UserProvider fallback={LogIn}>
<RealmProvider
sync={{
flexible: true,
initialSubscriptions: {
update(subs, realm) {
subs.add(realm.objects('Turtle'));
},
},
onError: console.log,
}}>
<SubscriptionManager />
</RealmProvider>
</UserProvider>
</AppProvider>
);
}
function SubscriptionManager() {
// Pass object model to useQuery to get all objects of type `Turtle`.
// These results automatically update with changes from other devices
// because we created a subscription with `initialSubscriptions`.
const allTurtles = useQuery('Turtle');
return (
<FlatList
data={allTurtles}
keyExtractor={turtle => turtle._id.toString()}
renderItem={({item}) => <Text>{item._id}</Text>}
/>
);
}

๊ธฐ๋ณธ์ ์œผ๋กœ ์ดˆ๊ธฐ ๊ตฌ๋…์€ ์˜์—ญ์ด ์ฒ˜์Œ ์—ด๋ฆด ๋•Œ๋งŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์•ฑ์ด ์‹œ์ž‘๋  ๋•Œ๋งˆ๋‹ค ์ด ์ดˆ๊ธฐ ๊ตฌ๋…์„ ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ rerunOnOpen์„(๋ฅผ) true(์œผ)๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์  ์‹œ๊ฐ„ ๋ฒ”์œ„ ๋˜๋Š” ๊ตฌ๋…์— ๋Œ€ํ•œ ์ •์  ๋ณ€์ˆ˜๋ฅผ ๋‹ค์‹œ ๊ณ„์‚ฐํ•ด์•ผ ํ•˜๋Š” ๊ธฐํƒ€ ์ฟผ๋ฆฌ๋ฅผ ์žฌ์‹คํ–‰ํ•˜๋ ค๋ฉด ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API ์ฐธ์กฐ

๊ตฌ๋… ์ƒํƒœ ๋ฅผ ํ™•์ธํ•˜์—ฌ ์„œ๋ฒ„ ๊ฐ€ ๊ตฌ๋… ์„ ์Šน์ธํ–ˆ๋Š”์ง€, ์žฅ์น˜๊ฐ€ ๋กœ์ปฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ–ˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋… ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Trigger error handling

  • ํŠธ๋žœ์žญ์…˜์ด ๋ณด๋ฅ˜ ์ค‘์ธ์ง€ ๋˜๋Š” ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ‘œ์‹œ

  • ๊ตฌ๋… ์„ธํŠธ ๋Œ€์ฒด ์‹œ๊ธฐ๋ฅผ ํ™•์ธํ•˜๊ณ  ๊ตฌ๋… ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ž‘์„ฑํ•˜๋ ค๋ฉด ํ•ด๋‹น ๊ตฌ๋… ์„ธํŠธ์˜ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค

import React, {useEffect} from 'react';
import {Text, View} from 'react-native';
import {useRealm, useQuery} from '@realm/react';
import {Bird} from '../Models/Bird';
function SubscriptionManager() {
const realm = useRealm();
const seenBirds = useQuery(Bird, birds => {
return birds.filtered('haveSeen == true');
});
useEffect(() => {
realm.subscriptions.update(
(mutableSubs: Realm.App.Sync.MutableSubscriptionSet) => {
// Create subscription for filtered collection.
mutableSubs.add(seenBirds, {name: 'seenBirds'});
},
);
});
// Returns state of all subscriptions, not individual subscriptions.
// In this case, it's just the subscription for `Bird` objects where
// `haveSeen` is true.
const allSubscriptionState = realm.subscriptions.state;
return (
<View>
<Text >
Status of all subscriptions: {allSubscriptionState}
</Text>
</View>
);
}

๋ฒ„์ „ realm@12.0.0์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ

Realm.js v12.0.0 ๊ตฌ๋… ์ƒํƒœ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ๋… ์—ด๊ฑฐํ˜• ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋… ์„ธํŠธ ์ƒํƒœ "์™„๋ฃŒ" ๋Š” "๋™๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋จ" ๋˜๋Š” "๋ชจ๋“  ๋ฌธ์„œ๊ฐ€ ๋™๊ธฐํ™”๋จ" ์„ ์˜๋ฏธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. "์™„๋ฃŒ" ๋Š” ๋‹ค์Œ ๋‘ ๊ฐ€์ง€๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค:

  • ๊ตฌ๋…์ด ํ˜„์žฌ ์„œ๋ฒ„์™€ ๋™๊ธฐํ™”๋˜๊ณ  ์žˆ๋Š” ํ™œ์„ฑ ๊ตฌ๋… ์„ธํŠธ๊ฐ€

  • ์ด์ œ ๊ตฌ๋…์ด ์„œ๋ฒ„๋กœ ์ „์†ก๋  ๋•Œ ๊ตฌ๋…๊ณผ ์ผ์น˜ํ–ˆ๋˜ ๋ฌธ์„œ๊ฐ€ ๋กœ์ปฌ ์žฅ์น˜์— ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ํ˜„์žฌ ๊ตฌ๋…๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์„œ๊ฐ€ ๋ฐ˜๋“œ์‹œ ํฌํ•จ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

Realm SDK๋Š” ๊ตฌ๋…๊ณผ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์„œ๊ฐ€ ๊ธฐ๊ธฐ์— ๋™๊ธฐํ™”๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ƒˆ ์ฟผ๋ฆฌ๋กœ ์ด๋ฆ„์ด ์ง€์ •๋œ ๊ตฌ๋…์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ๋… ์ฟผ๋ฆฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ์—…๋ฐ์ดํŠธํ•˜๋ ค๋Š” ๊ตฌ๋… ์ด๋ฆ„๊ณผ ํ•จ๊ป˜ ์ƒˆ ์ฟผ๋ฆฌ์™€ ๊ตฌ๋… ์˜ต์…˜์„ MutableSubscriptionSet.add() ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ƒˆ ๊ตฌ๋…์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ subscriptions.update()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๊ตฌ๋…์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์—์„œ๋Š” ์žฅ๊ธฐ ์‹คํ–‰ ์ž‘์—…์„ 180๋ถ„ ์ด์ƒ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์œผ๋กœ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.add(
tasks.filtered('status == "completed" && progressMinutes > 180'),
{
name: "longRunningTasksSubscription",
}
);
});

์ฐธ๊ณ 

SubscriptionOptions.throwOnUpdate ํ•„๋“œ๊ฐ€ true๋กœ ์„ค์ •๋œ ๊ตฌ๋…์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

API ์ฐธ์กฐ

๊ตฌ๋… ์„ธํŠธ๋Š” ๋” ์ด์ƒ ์ฝ”๋“œ์— ๊ตฌ๋…์„ ํฌํ•จํ•˜์ง€ ์•Š๋”๋ผ๋„ ์„ธ์…˜ ์ „๋ฐ˜์— ๊ฑธ์ณ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ๊ตฌ๋… ์ •๋ณด๋Š” ๋™๊ธฐํ™”๋œ ์˜์—ญ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ์ผ์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ผ์น˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™” ์‹œ๋„๋ฅผ ์ค‘์ง€ํ•˜๋ ค๋ฉด ๊ตฌ๋…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌ๋…์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํŠน์ • ์ฟผ๋ฆฌ๋กœ ๋‹จ์ผ ๊ตฌ๋… ์ œ๊ฑฐ

  • ํŠน์ • ์ด๋ฆ„์œผ๋กœ ๋‹จ์ผ ๊ตฌ๋… ์ œ๊ฑฐ

  • ํŠน์ • ๊ฐ์ฒด ๋ชจ๋ธ์— ๋Œ€ํ•œ ๋ชจ๋“  ๊ตฌ๋… ์ œ๊ฑฐ

  • ์ด๋ฆ„ ์—†๋Š” ๋ชจ๋“  ๊ตฌ๋… ์ œ๊ฑฐ

  • ๋ชจ๋“  ๊ตฌ๋… ์‚ญ์ œ

๊ตฌ๋… ์ฟผ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ ์žฅ์น˜์—์„œ ๋™๊ธฐํ™”๋œ ๋ฐ์ดํ„ฐ๋„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์ด ์„น์…˜์˜ ์˜ˆ์‹œ์—์„œ๋Š” @realm/react ๋ฐ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌ์„ฑ๋œ RealmProvider๋กœ ์ž‘์—…ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

import {useEffect} from 'react';
// get realm context from createRealmContext()
import {RealmContext} from '../RealmConfig';
const {useRealm} = RealmContext;
function SubscriptionManager() {
const realm = useRealm();
useEffect(() => {
realm.subscriptions.update(mutableSubs => {
// Remove subscription for object type `Turtle`,
// which we added in `initialSubscriptions`.
mutableSubs.removeByObjectType('Turtle');
});
});
return (
// ...
);
}

๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ์—์„œ ํŠธ๋žœ์žญ์…˜ ์„ ์‹คํ–‰ํ•˜์—ฌ ์ฟผ๋ฆฌ ๋ฅผ ํ†ตํ•ด ํŠน์ • ๊ตฌ๋… ์„ ์ œ๊ฑฐ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ๋ฅผ MutableSubscriptionSet์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์“ฐ๊ธฐ ํŠธ๋žœ์žญ์…˜( ์“ฐ๊ธฐ ํŠธ๋žœ์žญ์…˜ (write transaction)) ๋‚ด์—์„œ ()์„(๋ฅผ) ์ œ๊ฑฐ ํ•ฉ๋‹ˆ๋‹ค.

realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific query
mutableSubs.remove(tasks.filtered('owner == "Ben"'));
});

์ด๋ฆ„์œผ๋กœ ํŠน์ • ๊ตฌ๋… ์„ ์ œ๊ฑฐ ํ•˜๋ ค๋ฉด ๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ์—์„œ ํŠธ๋žœ์žญ์…˜ ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ด๋ฆ„์„ MutableSubscriptionSet.removeByName()์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

realm.subscriptions.update((mutableSubs) => {
// remove a subscription with a specific name
mutableSubs.removeByName("longRunningTasksSubscription");
});

๊ตฌ๋… ์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๊ตฌ๋… ์„ ์ œ๊ฑฐ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ์—์„œ ํŠธ๋žœ์žญ์…˜ ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ฐธ์กฐ ๋ณ€์ˆ˜๋ฅผ MutableSubscriptionSet.removeSubscription()์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

let subscriptionReference;
realm.subscriptions.update((mutableSubs) => {
subscriptionReference = mutableSubs.add(realm.objects("Task"));
});
// later..
realm.subscriptions.removeSubscription(subscriptionReference);

ํŠน์ • ๊ฐ์ฒด ์œ ํ˜•์— ๋Œ€ํ•œ ๋ชจ๋“  ๊ตฌ๋…์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ๊ตฌ๋… ์„ธํŠธ์—์„œ ํŠธ๋žœ์žญ์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๊ฐ์ฒด ์œ ํ˜•์„ string ๋กœ MutableSubscriptionSet.removeByObjectType()์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeByObjectType("Team");
});

๋ฒ„์ „ realm@v12.0.0์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ

์ผ์‹œ์ ์ด๊ฑฐ๋‚˜ ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋œ ์ด๋ฆ„ ์—†๋Š” ๊ตฌ๋…์„ ์ œ๊ฑฐํ•˜๊ณ  ์ด๋ฆ„์ด ์ง€์ •๋œ ๊ตฌ๋…์€ ๊ทธ๋Œ€๋กœ ๋‘๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

mutableSubs์—์„œ .removeUnnamed()์„(๋ฅผ) ํ˜ธ์ถœํ•˜์—ฌ ๊ตฌ๋… ์„ธํŠธ์—์„œ ๋ช…๋ช…๋˜์ง€ ์•Š์€ ๋ชจ๋“  ๊ตฌ๋…์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. .removeUnnamed()์€(๋Š”) ์ œ๊ฑฐ๋œ ๋ช…๋ช…๋˜์ง€ ์•Š์€ ๊ตฌ๋… ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

// Remove unnamed subscriptions.
let numberRemovedSubscriptions = 0;
await realm.subscriptions.update((mutableSubs) => {
numberRemovedSubscriptions = mutableSubs.removeUnnamed();
});

API ์ฐธ์กฐ

๊ตฌ๋… ์„ธํŠธ์—์„œ ๋ชจ๋“  ๊ตฌ๋…์„ ์ œ๊ฑฐํ•˜๋ ค๋ฉด ๊ตฌ๋… ์„ธํŠธ์—์„œ ํŠธ๋žœ์žญ์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์“ฐ๊ธฐ ํŠธ๋žœ์žญ์…˜(write transaction) ๋‚ด์—์„œ MutableSubscriptionSet.removeAll() ์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

realm.subscriptions.update((mutableSubs) => {
mutableSubs.removeAll();
});

์ฟผ๋ฆฌ ๊ตฌ๋… ์„น์…˜์— ์„ค๋ช…๋œ subscribe() ๋ฐ unsubscribe() API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ๊ตฌ๋…์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์€ ์ˆ˜๋™์œผ๋กœ ๊ตฌ๋…์„ ๊ด€๋ฆฌํ•  ๋•Œ ๋ฐฐ์น˜ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํšจ์œจ์„ฑ์ด ๋–จ์–ด์ง‘๋‹ˆ๋‹ค.

๊ตฌ๋…์„ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ณ€๊ฒฝํ•  ๋•Œ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒํ•˜๋ ค๋ฉด subscriptions API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ชจ๋“  ๊ตฌ๋…์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๋ ค๋ฉด ์ˆ˜๋™์œผ๋กœ ๊ตฌ๋… ๊ด€๋ฆฌํ•˜๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๊ตฌ๋… ์„ธํŠธ์— ๋Œ€ํ•œ ๋ชจ๋“  ์“ฐ๊ธฐ ํŠธ๋žœ์žญ์…˜(write transaction)์—๋Š” ์„ฑ๋Šฅ์ด ์†Œ๋ชจ๋ฉ๋‹ˆ๋‹ค. ์„ธ์…˜ ์ค‘์— ์˜์—ญ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ชจ๋“  ๋ณ€๊ฒฝ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ํŽธ์ง‘ํ•œ ๊ฐ์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋ณด๊ด€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ ๋Œ€์‹  ์™„์ „ํ•˜๊ณ  ์—…๋ฐ์ดํŠธ๋œ ๊ฐ์ฒด๋งŒ ์˜์—ญ์— ๊ธฐ๋กํ•˜๋ฏ€๋กœ ๋™๊ธฐํ™” ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.

์•ฑ์— ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋ถ„ํ• ๋œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ์ฟผ๋ฆฌ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด user_id == $0, โ€œ641374b03725038381d2e1fbโ€ ์™€ ๊ฐ™์ด ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๊ธฐ, ์Šคํ† ์–ด ๋˜๋Š” ์‚ฌ์šฉ์ž์— ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋งคํ•‘ํ•˜๋Š” ์•ฑ์€ ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ์˜ ์ข‹์€ ํ›„๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ์—๋Š” ์ฟผ๋ฆฌ ๊ตฌ๋…์— ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํŠน์ • ์š”๊ตฌ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๋Š” ๋ชจ๋“  ๊ตฌ๋… ์ฟผ๋ฆฌ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ์—์„œ ๋ˆ„๋ฝ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๋Š” ๊ตฌ๋… ์ฟผ๋ฆฌ์—์„œ ์ƒ์ˆ˜์— ๋Œ€ํ•ด == ๋˜๋Š” IN ๋น„๊ต๋ฅผ ํ•œ ๋ฒˆ ์ด์ƒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด user_id == $0, "641374b03725038381d2e1fb" ๋˜๋Š” store_id IN $0, {1,2,3}์ž…๋‹ˆ๋‹ค.

์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๊ฐ€ == ๋˜๋Š” IN์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์ˆ˜์™€ ํ•œ ๋ฒˆ ์ด์ƒ ์ง์ ‘ ๋น„๊ต๋˜๋Š” ๊ฒฝ์šฐ, ์„ ํƒ์ ์œผ๋กœ AND ๋น„๊ต๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด store_id IN {1,2,3} AND region=="Northeast" ๋˜๋Š” store_id == 1 AND (active_promotions < 5 OR num_employees < 10) ์ž…๋‹ˆ๋‹ค.

์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ์— ๋Œ€ํ•œ ์œ ํšจํ•˜์ง€ ์•Š์€ Flexible Sync ์ฟผ๋ฆฌ์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฟผ๋ฆฌ๊ฐ€ ํฌํ•ฉ๋ฉ๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๊ฐ€ AND๋ฅผ ๋‚˜๋จธ์ง€ ์ฟผ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ.์˜ˆ๋ฅผ ๋“ค์–ด store_id IN {1,2,3} OR region=="Northeast"์€ AND ๋Œ€์‹  OR์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์œ ํšจํ•˜์ง€์•Š์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ store_id == 1 AND active_promotions < 5 OR num_employees < 10๋Š” AND๊ฐ€ ์ „์ฒด ์ฟผ๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ ์˜†์— ์žˆ๋Š” ์šฉ์–ด์—๋งŒ ์ ์šฉ๋˜๋ฏ€๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๊ฐ€ ๋™๋“ฑ ์—ฐ์‚ฐ์ž์— ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ.์˜ˆ๋ฅผ ๋“ค์–ด store_id > 2 AND region=="Northeast"๋Š” > ์—ฐ์‚ฐ์ž๋งŒ ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ์— ์‚ฌ์šฉํ•˜๊ณ  ๋™๋“ฑ ๋น„๊ต๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๊ฐ€ ์ฟผ๋ฆฌ์—์„œ ์™„์ „ํžˆ ๋ˆ„๋ฝ๋œ ๊ฒฝ์šฐ.์˜ˆ๋ฅผ ๋“ค์–ดregion=="Northeast ๋˜๋Š” truepredicate๋Š” ์ธ๋ฑ์‹ฑ๋œ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Flexible Sync๋Š” RQL ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ช‡ ๊ฐ€์ง€ ์ œํ•œ ์‚ฌํ•ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋™๊ธฐํ™”ํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์ฟผ๋ฆฌ ๊ตฌ๋… ์„ ์ž‘์„ฑํ•  ๋•Œ ์„œ๋ฒ„๋Š” ์ด๋Ÿฌํ•œ ์ฟผ๋ฆฌ ์—ฐ์‚ฐ์ž๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ „์ฒด RQL ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋™๊ธฐํ™”๋œ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฐ์‚ฐ์ž ์œ ํ˜•
์ง€์›๋˜์ง€ ์•Š๋Š” ์—ฐ์‚ฐ์ž

์ง‘๊ณ„ ์—ฐ์‚ฐ์ž

@avg, @count, @max, @min, @sum

์ฟผ๋ฆฌ ์ ‘๋ฏธ์‚ฌ

DISTINCT, SORT, LIMIT

๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๋Š” ์ฟผ๋ฆฌ([c])์€(๋Š”) ์ธ๋ฑ์Šค๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๋Š” ์ฟผ๋ฆฌ๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

Flexible Sync๋Š” ๋ฐฐ์—ด ํ•„๋“œ์— ๋Œ€ํ•ด @count๋งŒ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

Flexible Sync๋Š” IN ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชฉ๋ก ์ฟผ๋ฆฌ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

์ƒ์ˆ˜ ๋ชฉ๋ก์„ ์ฟผ๋ฆฌํ•˜์—ฌ ์ฟผ๋ฆฌ ๊ฐ€๋Šฅ ํ•„๋“œ ๊ฐ’์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

์ฟผ๋ฆฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ์— ๋ฐฐ์—ด ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ์— ์ƒ์ˆ˜ ๊ฐ’์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

๊ฒฝ๊ณ 

Flexible Sync ์ฟผ๋ฆฌ์—์„œ๋Š” ๋‘ ๋ชฉ๋ก์„ ๋น„๊ตํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ตฌ๋ฌธ์€ Flexible Sync ์ฟผ๋ฆฌ ์™ธ์—๋Š” ์œ ํšจํ•œ Realm Query Language ๊ตฌ๋ฌธ์ด๋ผ๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

Flexible Sync๋Š” ๋‚ด์žฅ๋œ ๊ฐ์ฒด ๋˜๋Š” ๋งํฌ์˜ ์†์„ฑ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์˜ˆ์‹œ: obj1.field == "foo"

๊ตฌ๋… ์„ค์ •ํ•˜๋‹ค ์— ์žˆ๋Š” ํŠน์ • ์ฟผ๋ฆฌ ๊ตฌ๋… ์˜ ํฌ๊ธฐ ์ œํ•œ ์€ 256 KB ์ž…๋‹ˆ๋‹ค. ์ด ์ œํ•œ์„ ์ดˆ๊ณผํ•˜๋ฉด LimitsExceeded ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ