0Pricing
React Native Academy · 강의

저장소 삭제와 마이그레이션 전략

선택적 또는 전체 캐시 삭제에 multiRemove와 clear를 사용하고, 앱 업데이트에 따른 저장소 스키마 변경을 처리하도록 버전이 지정된 마이그레이션 전략을 구현합니다.

저장소 삭제와 마이그레이션 전략은(는) CoddyKit의 무료 React Native Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 React Native Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Storage Maintenance Matters

As your app evolves across versions, the data structure you store in AsyncStorage may change. Old data from previous app versions might not match what the new code expects, leading to crashes or incorrect behavior. A solid storage maintenance strategy — including selective clearing and versioned migrations — is essential for apps that have real users with existing data.

Removing Specific Keys with multiRemove

AsyncStorage.multiRemove accepts an array of key strings and deletes all of them in a single operation. This is more efficient than calling removeItem repeatedly in a loop. Use it when a user action should clear a specific subset of data — for example removing all cached API responses without touching user preferences.

async function clearCache() {
  const cacheKeys = [
    'posts_cache',
    'comments_cache',
    'user_feed_cache',
  ];
  try {
    await AsyncStorage.multiRemove(cacheKeys);
    console.log('Cache cleared');
  } catch (err) {
    console.error('Failed to clear cache:', err);
  }
}

Clearing All App Data with clear

AsyncStorage.clear() removes all keys stored by the app. Use this only for destructive operations like a factory reset or during development when you need a clean slate. In production, always confirm with the user before calling clear() because it cannot be undone and deletes everything — preferences, cached data, and auth tokens alike.

async function factoryReset() {
  await AsyncStorage.clear();
  // Reset in-memory state too
  useAuthStore.getState().logout();
  useSettingsStore.getState().reset();
  navigation.reset({ index: 0, routes: [{ name: 'Onboarding' }] });
}

Finding Keys to Remove Dynamically

When you store data with dynamic keys (like post_123, post_456), use getAllKeys to find them and filter by a prefix before passing the matching keys to multiRemove. This pattern is useful for clearing all cached pages from a paginated feed without hardcoding each key.

async function clearPostsCache() {
  const allKeys = await AsyncStorage.getAllKeys();
  const postKeys = allKeys.filter((key) => key.startsWith('post_'));
  if (postKeys.length > 0) {
    await AsyncStorage.multiRemove(postKeys);
    console.log('Cleared', postKeys.length, 'cached posts');
  }
}

What Is a Storage Migration?

A storage migration upgrades stored data from one schema version to a newer one. When you release a new app version that changes how data is stored — for example renaming a key or adding a required field — migrating existing users' data prevents crashes and data loss. Migrations run once on startup and mark the completion with a version flag.

Versioning Your Storage Schema

Store a schema version number in AsyncStorage alongside your data. On startup, read this version number and compare it to the current expected version. If they differ, run the appropriate migration steps, then update the stored version number. Future launches skip the migration because the versions match.

const CURRENT_VERSION = 3;
const VERSION_KEY = 'storage_version';

async function getStorageVersion(): Promise<number> {
  const v = await AsyncStorage.getItem(VERSION_KEY);
  return v ? parseInt(v, 10) : 0; // 0 means fresh install or pre-versioning
}

async function setStorageVersion(version: number) {
  await AsyncStorage.setItem(VERSION_KEY, String(version));
}

Writing a Migration Function

Write a migration function that handles each version upgrade step. Use a switch statement or a series of if checks that fall through from the stored version up to the current version. Each case applies the changes needed to advance one version, so a user upgrading from v1 to v3 runs both the v1-to-v2 and v2-to-v3 migrations in sequence.

async function runMigrations(fromVersion: number) {
  if (fromVersion < 1) {
    // v0 → v1: rename 'user_name' key to 'username'
    const old = await AsyncStorage.getItem('user_name');
    if (old) {
      await AsyncStorage.setItem('username', old);
      await AsyncStorage.removeItem('user_name');
    }
  }
  if (fromVersion < 2) {
    // v1 → v2: add default 'fontSize' to settings
    const json = await AsyncStorage.getItem('settings');
    if (json) {
      const settings = JSON.parse(json);
      if (!settings.fontSize) settings.fontSize = 'medium';
      await AsyncStorage.setItem('settings', JSON.stringify(settings));
    }
  }
  await setStorageVersion(CURRENT_VERSION);
}

Running Migrations on App Start

Call the migration logic in your root component's useEffect before anything else reads from storage. This ensures all data is in the expected shape before any screen tries to use it. Keep migrations idempotent — running them twice on the same data should produce the same result to handle edge cases like interrupted writes.

useEffect(() => {
  async function init() {
    const version = await getStorageVersion();
    if (version < CURRENT_VERSION) {
      await runMigrations(version);
    }
    // Now safe to load data — migration is complete
    await loadAppData();
    setAppReady(true);
  }
  init();
}, []);

Expiring Cached Data

Cache data should not live forever. Store a timestamp alongside cached API responses and check whether it has expired when the app starts or when the user navigates to a screen. If expired, delete the cache and fetch fresh data. A helper function that wraps the cache check makes this reusable across all cached endpoints.

const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour

async function isCacheExpired(key: string): Promise<boolean> {
  const tsStr = await AsyncStorage.getItem(key + '_timestamp');
  if (!tsStr) return true;
  return Date.now() - parseInt(tsStr, 10) > CACHE_TTL_MS;
}

async function setCache(key: string, data: any) {
  await AsyncStorage.setItem(key, JSON.stringify(data));
  await AsyncStorage.setItem(key + '_timestamp', String(Date.now()));
}

Selective Logout: Clearing Only User Data

When a user logs out, clear their personal data (auth token, profile, private cache) but preserve device preferences like theme and language. Use multiRemove with a specific list of keys rather than clear(). This provides a better UX because the user's display preferences are still there when they log back in.

const USER_DATA_KEYS = ['authToken', 'userProfile', 'feed_cache', 'userId'];

async function logout() {
  await AsyncStorage.multiRemove(USER_DATA_KEYS);
  // Preferences (theme, language) remain intact
  navigation.reset({ index: 0, routes: [{ name: 'Login' }] });
}

Documenting Your Storage Schema

Maintain a storage schema documentation file in your project that lists every AsyncStorage key, its type, its default value, and which version it was introduced. This is invaluable when writing migrations, debugging storage issues, and onboarding new developers. Treat it like a database schema — update it every time you add, rename, or remove a stored key.

/**
 * AsyncStorage Schema v3
 * -------------------------
 * Key              | Type    | Since | Description
 * authToken        | string  | v1    | JWT auth token
 * username         | string  | v1    | (was user_name in v0)
 * settings         | JSON    | v1    | { darkMode, notifications, fontSize }
 *   .fontSize added v2, .language added v3
 * storage_version  | number  | v1    | Current schema version
 */

Quick Check

Test your understanding of React Native Mobile Development concepts from this lesson.

Lesson Recap

In this lesson you learned: multiRemove efficiently clears a specific set of keys while leaving others intact, versioned migrations upgrade old stored data when the app schema changes across releases, and expiring cached data with timestamps prevents stale API responses from living in storage indefinitely. Next up we explore camera access with expo-camera.

자주 묻는 질문

“저장소 삭제와 마이그레이션 전략” 강의는 무료인가요?

네 — “저장소 삭제와 마이그레이션 전략” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 React Native Academy 강의 전체를 잠금 해제할 수 있습니다. React Native Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“저장소 삭제와 마이그레이션 전략”에서 뭘 배우나요?

선택적 또는 전체 캐시 삭제에 multiRemove와 clear를 사용하고, 앱 업데이트에 따른 저장소 스키마 변경을 처리하도록 버전이 지정된 마이그레이션 전략을 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 React Native Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

React Native Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 React Native Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“저장소 삭제와 마이그레이션 전략” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 React Native Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 React Native Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. AsyncStorage로 읽고 쓰기
  2. JSON 객체 저장 및 파싱
  3. 영구 설정 화면 만들기
  4. 저장소 삭제와 마이그레이션 전략
← React Native Academy(으)로 돌아가기