생체인증은 보안과 편의성을 동시에 제공하는 인증 방식으로, 금융 앱과 민감한 데이터 접근에 필수적입니다.


expo-local-authentication

BASH
npx expo install expo-local-authentication
TSX
import * as LocalAuthentication from 'expo-local-authentication';

// 생체인증 가능 여부 확인
async function checkBiometricSupport() {
  const compatible = await LocalAuthentication.hasHardwareAsync();
  if (!compatible) return { supported: false, reason: '생체인증 하드웨어 미지원' };

  const enrolled = await LocalAuthentication.isEnrolledAsync();
  if (!enrolled) return { supported: false, reason: '등록된 생체 정보 없음' };

  const types = await LocalAuthentication.supportedAuthenticationTypesAsync();
  return {
    supported: true,
    hasFaceId: types.includes(LocalAuthentication.AuthenticationType.FACIAL_RECOGNITION),
    hasFingerprint: types.includes(LocalAuthentication.AuthenticationType.FINGERPRINT),
  };
}

// 생체인증 실행
async function authenticate() {
  const result = await LocalAuthentication.authenticateAsync({
    promptMessage: '본인 확인이 필요합니다',
    cancelLabel: '취소',
    fallbackLabel: '비밀번호로 인증',   // iOS: 생체인증 실패 시 대체 옵션
    disableDeviceFallback: false,        // true면 기기 비밀번호 대체 비활성화
  });

  if (result.success) {
    console.log('인증 성공');
    return true;
  } else {
    console.log('인증 실패:', result.error);
    return false;
  }
}

실전: 앱 잠금 화면

TSX
function AppLockScreen({ onUnlock }: { onUnlock: () => void }) {
  const [attempts, setAttempts] = useState(0);

  const handleBiometric = async () => {
    const success = await authenticate();
    if (success) {
      onUnlock();
    } else {
      setAttempts((prev) => prev + 1);
      if (attempts >= 3) {
        Alert.alert('인증 실패', '비밀번호로 로그인해주세요');
      }
    }
  };

  useEffect(() => {
    handleBiometric();
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.icon}>🔒</Text>
      <Text style={styles.title}>앱이 잠겨있습니다</Text>
      <Pressable style={styles.button} onPress={handleBiometric}>
        <Text style={styles.buttonText}>생체인증으로 잠금 해제</Text>
      </Pressable>
    </View>
  );
}

react-native-keychain — 안전한 자격증명 저장

BASH
npm install react-native-keychain
TSX
import * as Keychain from 'react-native-keychain';

// 자격증명 저장 (암호화됨)
await Keychain.setGenericPassword('user@email.com', 'accessToken123', {
  accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET,
  accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED,
});

// 생체인증 후 자격증명 읽기
const credentials = await Keychain.getGenericPassword({
  authenticationPrompt: { title: '본인 확인이 필요합니다' },
});

if (credentials) {
  console.log('토큰:', credentials.password);
}

// 자격증명 삭제
await Keychain.resetGenericPassword();

정리

  • expo-local-authentication 으로 Face ID, Touch ID, 지문인식을 간단히 구현할 수 있습니다
  • 생체인증 전 반드시 하드웨어 지원 여부와 등록 여부 를 확인하세요
  • 민감한 데이터(토큰 등)는 Keychain/Keystore 에 암호화하여 저장하세요
  • 생체인증 실패 시 PIN이나 비밀번호 대체 인증 을 제공하세요
댓글 로딩 중...