React Native 앱 백그라운드 상태 처리와 AppState API

문제 상황

회사 메신저 앱에서 사용자가 앱을 백그라운드로 전환했다가 돌아오면 WebSocket 연결이 끊어진 채로 유지되는 이슈가 발생했다. iOS에서는 백그라운드 진입 후 약 30초 뒤 연결이 끊기고, Android에서는 절전 모드에서 불규칙하게 끊겼다.

AppState API 활용

React Native의 AppState API를 사용해 앱의 상태 변화를 감지했다.

import { AppState } from 'react-native';
import { useEffect, useRef } from 'react';

const ChatScreen = () => {
  const appState = useRef(AppState.currentState);
  const reconnectTimeoutRef = useRef(null);

  useEffect(() => {
    const subscription = AppState.addEventListener('change', nextAppState => {
      if (
        appState.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        // 포어그라운드 복귀 시 재연결
        handleReconnect();
      }

      if (nextAppState === 'background') {
        // 백그라운드 진입 시 타임아웃 설정
        reconnectTimeoutRef.current = setTimeout(() => {
          socket.disconnect();
        }, 25000);
      }

      appState.current = nextAppState;
    });

    return () => {
      subscription.remove();
      if (reconnectTimeoutRef.current) {
        clearTimeout(reconnectTimeoutRef.current);
      }
    };
  }, []);

  const handleReconnect = () => {
    if (reconnectTimeoutRef.current) {
      clearTimeout(reconnectTimeoutRef.current);
    }
    
    if (!socket.connected) {
      socket.connect();
    }
  };

  return (/* ... */);
};

추가 고려사항

백그라운드에서 완전히 종료되기 전에 미리 연결을 끊어 배터리를 절약하도록 했다. iOS의 경우 백그라운드 실행 시간이 제한적이므로 25초 정도에 타임아웃을 설정했다.

Android에서는 react-native-background-timer를 추가로 사용해 더 정확한 타이밍 제어가 가능했지만, 일단은 기본 API만으로 처리했다.

결과

포어그라운드 복귀 시 자동 재연결이 안정적으로 동작하고, 불필요한 백그라운드 연결 유지로 인한 배터리 소모도 줄었다. 다음에는 네트워크 상태 변화도 함께 감지하는 로직을 추가할 예정이다.