[React Native] Firebase 전화번호 인증 기능 추가하기 (Feat. 안드로이드 자동 인증)
HYPE 앱은 전화번호 기반으로 유저 로그인, 회원가입이 이루어지기 때문에 전화번호 인증이 필수적이었다. 그래서 Google Firebase에서 제공하는 문자메세지 인증 서비스를 처음으로 사용해보게 되었다.
Google Firebase 연동하기
먼저 개발하려는 앱과 프로젝트를 연동해주어야 한다. React Native
프로젝트에 쉽게 프로젝트를 연동할 수 있는 react-native-firebase
라이브러리를 사용하면 편하다.
연동하는 일련의 방법은 공식문서 및 블로그를 참고했다. Firebase 공식문서는 Swift와 Kotlin 기반으로 설명이 되어있어서, 타 블로그가 도움이 많이 되었다.
Firebase에서는 여러 가지 방법의 Authentication(인증)수단을 제공하는데, 그 중 전화(phone)을 이용하면 유저가 입력한 번호로 인증번호를 전송할 수 있다. 그리고 유저가 입력한 인증번호와 대조하면 핸드폰 번호 인증이 가능해진다.
인증번호 전송 및 대조 검증 코드
대부분의 로직은 React Native Firebase
에서 제공하는 Phone Authentication
공식문서를 참고하면 된다.
전화번호 인증의 전체적인 로직은 이렇다.
- 전화번호를 매개변수로
signInWithPhoneNumber()
함수를 호출하고, 반환된 값을 state로 저장한다. - 그러면 firebase에서 해당 전화번호로 OTP(One Time Passcode)가 전송된다.
- 유저에게서 OTP를 입력받고, 이를 state에 저장된 변수 내
confirm()
함수의 매개변수로 넣는다. - 인증번호가 맞다면 문제가 없지만, 인증번호가 틀리거나 만료된다면
Error
가 반환한다.
전체 코드는 아래와 같다.
1 | const SignInComponent = () => { |
Troubleshooting
⚠️ Google Playstore 등록 이후 실기기에서 인증번호 발송 실패 이슈
안드로이드 시뮬레이터에서는 정상적으로 동작하던 인증이 Playstore을 통해서 배포된 앱에서는 Error: [auth/invalid-app-credential] Invalid token
에러가 발생한다면, Playstore 앱 서명 SHA-1
과 SHA-256
키를 Firebase에 등록했는지 다시 확인해보는 것이 좋다.
앱을 Firebase에 처음으로 연동할 때, SHA-1
키를 입력하고 google-service.json을 다운로드하는 과정을 거친다. 이때 들어가는 SHA-1
키는 디버그용 키이기 때문에, 릴리즈용 키와 Playstore 앱 서명 키까지 추가로 다시 등록해주어야 한다.
릴리즈용 SHA-1
, SHA-256
Key는 터미널에서 아래 커맨드를 입력하여 얻을 수 있다.
1 | keytool -list -v -keystore "C:\work\prj1\prj1.jks" |
Playstore 앱 서명 키는 Play Console - 설정(좌측 메뉴) - 앱 무결성 - 앱 서명
에서 확인할 수 있다. 업로드 키가 아닌 앱 서명 키를 이용해야 한다!
이후 Firebase Console - 앱 설정 - Android 앱 - SHA 인증서 지문
에서 디지털 지문 추가를 클릭해 위에서 얻은 키를 입력해주고, 다시 google-service.json을 앱 폴더 내에 위치시키면 끝!
⚠️ Android 기기에서 인증번호 자동 인증으로 인한 인증번호 만료 이슈
모든 설정을 마쳤는데도, Android 실기기에서만 인증번호를 확인하는 confirm
함수에서 계속 오류를 반환했다. 오류를 재현하는 것 부터 까다로웠는데,
- iOS 기기는 전혀 문제가 없음
- Android Simulator에서 테스트 전화번호로 하면 문제가 없음.
- Android Simulator에서 실기기 전화번호로 인증번호를 받으면 문제가 없음.
- Android 실기기에서 테스트 전화번호로 하면 문제가 없음.
- Android 실기기에서 실기기 전화번호로 인증번호를 받아 입력하면 오류가 발생
이유는 안드로이드 일부 기기에서 문자로 보내진 인증번호를 이용해 자동으로 인증을 진행하기 때문이었다. 그래서 confirm
함수는 이미 실행되고 인증까지 된 상태에서 유저가 똑같은 OTP를 이용해 수동으로 한 번 더 인증을 하니 auth/session-expired
오류가 떴던 것이다.
공식문서의 설명은 아래와 같다.
Some Android devices can automatically process the verification code (OTP) message, and the user would NOT need to enter the code.
Actually, if he/she tries to enter it, he/she will get an error message because the code was already used in the background.
In this function, make sure you hide the component(s) for entering the code and/or navigate away from this screen.
It is also recommended to display a message to the user informing him/her that he/she has successfully logged in.
그래서 인증화면에서는 아래처럼 onAuthStateChanged
리스너를 둬서 로그인(또는 회원가입)이 되어 user객체가 생긴 걸 감지하도록 해야한다.
1 | useEffect(() => { |
이 오류를 발견하고 고치는데에 일주일정도 삽질을 했던 것 같다… 이렇게 오랜 시간이 소요됐던 건 네 가지 병크가 겹쳤기 때문이라고 본다.
- 일단 공식문서의 초록 주석을 제대로 안읽었음. 몇몇 기기에서는 자동인증이 진행될 수 있다는 내용을 몰랐음.
- 실기기에서는 console창에 에러메세지가 뜨지 않아서 OTP expire 오류인지 알아내는데 며칠이 걸렸음.
- 안드로이드 실기기가 없어서 애초에 디버깅을 지인 핸드폰으로 했기에 시간제한이 있었음.
- 디버깅하려면 수정 -> 새로 빌드(및 버전 업) -> 실기기에서 앱 업데이트 -> 확인의 과정을 매번 거쳐야 해서 속도가 느렸음.
안드로이드 자동인증 만든넘… 밤길 조심하세요 진짜