ios에서 앱이 정상 동작해야 앱 스토어에 제출을 하거나 말거나를 하기 때문에 하던 것들을 마저 마무리 해보려고 한다!
마무리해야하는 것들

여기서 ios에서 구글 로그인을 하려고 할 때 iosClientId 없는 문제는 방금 했다!
그리고 더 해야하는건 messaging.getToken 문제를 해결하기 위해 퍼널을 임시로 도입했다가 이제 퍼널을 넣는거에 대해 반응이 좋아서 어떤 내용을 넣어야할지 좀 더 픽스해야한다! 그리고 별개로 getToken 문제 자체는 해결되었는데 부가적인 문제로 앞서 말했던 해야했던 정해야 하는 것과 추가로 신규회원과 기존회원을 구분하는 로직이 추가로 필요하다!
근데 이렇게 되어 버리면 ios에서 FCM getToken 함수 관련 문제를 해결하기 위해 퍼널과 기존/신규 유저 구분이 우선되어야한다는 점에서 배보다 배꼽이 커지는 것같다.
그래서 일단 ios에서는 앱을 켜자마자 알림을 허용할 것인지 물어보는 식으로 해결한 뒤 추후 퍼널 붙이면서 알림 허용 물어보는걸 퍼널 단계에 추가하는 식으로 해야겠다.
구글 로그인을 하기 위해 Google.useAuthRequest 함수를 사용하고 있다. 여기에 휴대폰 os에 따라 androidClientId 혹은 iosClientId를 인자로 줘야한다.
근데 iosClientId를 구글 클라우드 콘솔에서 발급바지 않았던 것. <- 이건 며칠 전에 해결했다.
근데! 이제 내가 알기로 이 clientId 값도 외부에 노출되면 안된다고 하길래 서버에서 받아와서 쓰기로 결정했고 오늘 막 코드에 해당 결정을 적용했다.
그래서!
내가 생각한 것은 우선
1. Platform 함수를 사용해 android인지 ios인지 구분한다.
2. 구분한 거에 따라 서버에 clientId 값을 요청하고 받아온다.
3. 그걸 Google.useAuthRequest에 넣어준다.
그래서!
const [clientId, setClientId] = useState('')
...
const [request, response, promptAsync] =
Google.useAuthRequest(clientId);
...
const getClientId = async () => {
let clientIdResponse;
if (Platform.OS === 'android') {
clientIdResponse = await Api.getAndroidClientId();
} else {
clientIdResponse = await Api.getIosClientId();
}
setClientId(clientIdResponse);
};
이렇게 했더니 Google.useAuthRequest는 반드시 androidClientId 혹은 iosClientId가 필요하다는 에러가 발생!
알고보니 해당 파일이 처음 로드될 때 Google.useAuthRequest의 초기값으로 ''이 들어가는 것을 확인!
처음부터 Google.useAuthRequest에 androidClientId인지 iosClientId인지 알려줘야 한다는 것을 확인!
const googleLoginClientIdKey =
Platform.OS === 'android' ? 'androidClientId' : 'iosClientId';
const [googleLoginClientId, setgoogleLoginClientId] = useState({
[googleLoginClientIdKey]: '',
});
const [request, response, promptAsync] =
Google.useAuthRequest(googleLoginClientId);
이렇게 os를 정해서 clientId를 넣어주되 처음 로드될 때는 빈값으로 넣어준 뒤 서버에서 값을 받아 업데이트하는 식으로 구현!
이때! JS에서 객체에 키로 변수를 넣고 싶으면 []로 감싸야한다는 것을 배움!
그리고! 로그인 버튼에 들어갈 콜백 함수에서 googleLoginClientId 객체의 value가 ''이면 promptAsync 함수를 실행하지 못하게 하려고 했는데
이때 os에 따라 googleLoginClientId 객체의 key가 바뀔텐데 해당 객체의 value가 ''이라는 것을 어떻게 명명해야할까 막막했음! 그래서 찾았음!
Object.values(googleLoginClientId)[0] === ''
Object.values라는 메서드를 쓰면 배열로 객체의 value를 반환한다고함!
에러 원인 : ios에서는 FCM getToken 함수를 실행하기 전 꼭 사용자에게 알림 동의 여부를 물어봐야한다!
일단 퍼널 페이지 구현한 건 퍼널 기능 이슈를 파서 거기로 옮긴다!
앱 켰을 때 바로 알림 허용 alert가 뜨도록 한다!
useEffect(async () => {
getAndroidClientId();
handleLocalToken();
await messaging().requestPermission()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
이렇게 하려했더니 useEffect 콜백은 무조건 동기여야한다함. 할거면 콜백 안에 비동기함수를 정의해서 쓰라함!
(async () => {
await messaging().requestPermission();
})();
그래서! 즉시실행함수로 만들어서 넣어줌!
그리고 getToken 함수는 예전엔 어떤 커스텀훅을 사용할 때 그 과정에서 바로 호출이 되었는데 조금 바꿔서 우리 api 서버에 요청 보내기 직전에 실행하도록 순서를 수정함!
그래서 이제 사용자가 구글 로그인버튼을 누르고 웹뷰가 떳다가 다시 우리 서비스로 리디렉션되었을 때 그때서야 getToken을 하게 됨! 굿!
굿!! 이제 앱 켜지자마자 잘 물어본다!

근데 여기서 알림 허용 거부하니까
LOG [Error: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().]
라고함!! ㅠㅠ
이거 관련 스택오버플로도 있었다.
그래서! 설정 들어가서 알림 허용하고 다시 해봄!
그러니! 에러가 바뀜.
LOG [Error: [messaging/unknown] The operation couldn’t be completed. No APNS token specified before fetching FCM Token]
근데 이상하다.
분명 이번에 이렇게 알림 허용을 앱 켜자마자 물어보는 식으로 바꾸고 잘 물어보는지 확인하기 위해 앱을 지우고 다시 설치하기 전에는 getToken 코드라인 아래에 있는 우리 api 서버에 request 보내는 코드가 잘 작동했는데...? 왜 앱을 지웠다가 다시 까니까 알림을 허용해도 getToken에서 문제가 생겨서 try catch에 에러가 걸릴까나
동기화 기능을 포기해도 된다면 당장 지금 출시가 급하다면 getToken을 감싸는 래핑함수를 만든 다음에 거기서 try catch로 에러를 핸들링하고 에러가 발생하면 catch 부분에서 null이나 팀원들과 합의한 어떠한 값을 리턴하는 식으로 해서 FCM에서 getToken 때문에 로그인이 안되는 문제는 해결할 수 있을 것 같다!
암튼 알림허용해도 뜨는 에러도 스택오버플로에 있었다.
근데 너무 잠와서 내일 봐야겠다.
ios 업로드와는 별개로 테스트 붙일 것!
젤 간단한 거 부터 == 로그인버튼부터!
https://docs.expo.dev/develop/unit-testing/
expo 문서에 유닛테스트 페이지가 있어서 보고 할 예정!
디스콰이엇 초안도 작성해야한다!
미룬이 노래에서 나오는 미루는 행동의 원인을 논문에서 찾아서 작성해보고... 우리앱으로 해결할 수 있다고 하는 흐름 생각중!