React Native의 BackHandler (뒤로가기, 앱 종료)

eeensu·2026년 3월 2일

React Native

목록 보기
16/37

BackHandler API

BackHandler는 Android의 물리적/소프트웨어 뒤로 가기 버튼을 가로채서 커스텀 동작을 구현할 수 있게 해주는 API이다.
여기서 중요한 점은, BackHandler 는 Android 전용이다. ios에는 뒤로 가기 버튼이 없으므로 이 API는 아무 동작도 하지 않는다.


언제 필요한가?

사용자가 뒤로 가기 버튼 누름 → 앱이 바로 종료되거나 이전 화면으로 돌아감

하지만 실무에서는 이런 상황이 자주 발생한다.

  • 모달이 열려 있으면 앱을 닫지 말고 모달만 닫아야 함
  • 작성 중인 글이 있으면 "정말 나가시겠습니까?" 경고창을 띄워야 함
  • 특정 화면에서는 뒤로 가기를 막아야 함 (결제 중, 로딩 중 등)
  • 뒤로 가기 2번 연속 누르면 앱 종료 (토스트 메시지: "한 번 더 누르면 종료됩니다")

이럴 때 BackHandler를 사용하면 좋다.


사용법

1) useExitApp.android.ts

import { useFocusEffect } from '@react-navigation/native';
import { useCallback, useRef } from 'react';
import { BackHandler, ToastAndroid } from 'react-native';

const useExitApp = () => {
  // 마지막으로 뒤로가기를 누른 시점 저장
  const lastBackPressed = useRef<number>(0);

  useFocusEffect(
    useCallback(() => {
      const onBackPress = () => {
        const now = Date.now();
        // 2초(2000ms) 안에 다시 눌렀는지 확인
        if (lastBackPressed.current && now - lastBackPressed.current < 2000) {
          BackHandler.exitApp(); // 앱 종료
          return true;
        }

        lastBackPressed.current = now;
        ToastAndroid.show('한 번 더 누르면 종료됩니다.', ToastAndroid.SHORT);

        // true를 반환해야 기본 동작(앱 종료/이전 화면 이동)을 막습니다.
        return true;
      };

      // 이벤트 리스너 등록
      const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);

      return () => {
        // 이벤트 리스너 해제
        subscription.remove();
      };
    }, []),
  );
};

export default useExitApp;

2) useExitApp.ios.ts
iOS는 시스템 구조상 앱 내에서 강제로 종료하는 기능을 지양하며, 하드웨어 뒤로가기 버튼도 존재하지 않기에 아무런 동작도 하지 않고 null 을 반환하는 함수를 사용한다. 시스템 홈 스와이프로 종료된다.

const useExitApp = () => null;

export default useExitApp;



returntruefalse 의 차이?

  1. return true : "이벤트를 수동으로 처리했기에, 시스템에 아무것도 하지 말라는 신호를 보냄" (이벤트 전파 중단) -> 뒤로 가기 막힘

  2. return false : "나는 처리 안 할래. 시스템 너 할 일 해." -> 기본 동작 수행 (이전 화면 이동 or 앱 종료)

BackHandler는 리스너 체인으로 동작한다. 내가 등록한 함수가 true를 반환하면 뒤에 있는 리스너나 시스템의 기본 동작은 실행되지 않는다. 따라서 뒤로 가기를 막고 싶다면 반드시 true를 반환해야 한다.


호출은 어디에서 하면 좋을까?

useExitApp 훅은 앱의 첫 진입 화면(예: HomeTab, MainScreen)에서만 사용해야 한다. 만약 상세 페이지(Detail Screen)에서 이 훅을 사용하면, 사용자가 뒤로 가서 목록을 보고 싶은데 "한 번 더 누르면 종료됩니다" 토스트가 뜨는 현상이 발생한다.

또한 React Navigation은 내부적으로 BackHandler를 이미 사용하고 있다. 우리가 등록한 리스너는 React Navigation보다 나중에 등록(useFocusEffect)되므로 우선순위가 높다. 즉, 상세 페이지에서는 이 훅이 실행되지 않도록 하는게 좋은 것이다.

profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글