오늘의 이슈를 시작하기 전에, 작게나마 기여한 것이 있어서 뿌듯한 마음에 사진으로 남겨본다.
바로 오늘 warehouse라는 사이트를 통해 문서나 관련 표현을 번역하여 기여하는 활동을 했는데, 내가 총 87개의 문장을 번역했다고 나와 있었다. 물론 1차 번역은 GPT가 하고 나는 첨삭만 했지만 그래도 한 게 어디인가.
암튼 좀 뿌듯해서 올려봤다.
이제 이슈로 돌아가자. 어제까지 장장 며칠간 우리 팀의 발을 묶어놓았던 이슈가 어제 드디어 해결되었다는 소식이 들려왔다. 발단은 동적으로 환경변수를 주입하거나 세팅하는 것과 관련된 파일(정확한 코드의 역할은 다른 팀원에게 물어봐야 하겠다. 암튼!)에서 난 오류였다. GPT에게 물어보니 Expo의 플러그인을 사용해서 ios 빌드에 사용되는 Podfile을 동적으로 런타임 시 변환시키는 코드라고 한다.
해당 파일에는 'return config'라는 부분이 있는데, 해당 부분을 'return innerConfig'로 바꿔 주었더니 해결되었다. 해당 파일에는 'withStaticFrameworks'라는 함수가 있는데, 여기서의 리턴값을 config 대신에 innerConfig로 바꿔 준 것이다. 그리고 인자로 주어지는 config는 expo 프로젝트의 전체 설정값을 담고 있는 객체라고 한다.
즉 기존의 withStaticFrameworks에서는 전체 설정 파일을 수정해서 그대로 리턴하고 있었다면, 이 중 하위 객체인 innerConfig만 리턴하도록 바꿔준 것이다. 내가 해결한 것은 아니었지만, 왜 이렇게 했더니 오류가 해결되었는지 궁금했다.
녀석(GPT)의 추론이 꽤 그럴듯하다. 역시 LLM 모델이다. 녀석은 expo의 전체 설정 파일(config)를 리턴할 경우 의도치 않은 다른 설정까지 덮어쓸 가능성을 제시해주었다. 그래서 innerConfig로 바꿨어야 하는구나. 그렇군! 하고 다시 문제의 그 명령어를 실행했다.
npm run ios:dev
이번에는 빌드가 5초 컷 당하지 않았다. 대신에 다른 에러가 났다. 아마도 설정 정보가 중복되어서 나는 에러로 보였다.
어제의 상황에서 아직 멈춰있다. GPT에게 도움을 요청했을 때도 sentry 관련 패키지 에러, expo와 sentry의 호환성(?)문제, 캐시 삭제 등의 방법을 알려주었지만, 다 해 봤는데도 똑같은 오류가 났다.
깃허브 관련 이슈를 찾아보니 해당 이슈에서는 expo를 prebuild했을 때 나는 이슈에 초점을 두고 있는 것 같았다. 사람들의 조언에 따라 우선 expo-cli를 최신 버전으로 업데이트 해 주었다. 아직 되지 않는다.
다만 패키지 호환성보다도 expo prebuild 문제인 것은 거의 확실해진 것이, 'expo prebuild' 명령어만 실행해도 관련 에러가 난다. 즉 prebuild 이후의 과정에서 나는 문제는 아니었던 것 같다. 해당 글에서는 다른 해결방법들도 제시해 주고 있었다. 문제는 그 방법이 좀 많이 번거로워서... 저걸 따라해야 한다는 데서 엄두가 잘 안 났다.
MacOS 업데이트, XCode 지웠다 깔기, 컴퓨터 다시 켜기, expo-cli 업데이트 하기 등등.... 할 수 있는 것은 다 해보신 것 같았다. 생각해보니 만약 ios 관련이라면 xcode나 pods 관련 오류일 수도 있지 않을까? 싶어서 xcode 관련 파일까지는 한번 제거해봐야 할 것 같다. ios 폴더와 xcode 관련 캐시를 제거해주었다.
역시나 되지 않는다... 뭐가 문제인 것일까? 생각해보니 안드로이드 에뮬레이터에서는 이 문제가 일어나지 않았다. 그렇다면 ios 설정이 잘못되었거나, expo와 ios 사이의 설정 등의 문제일 수 있겠다. 질문을 바꿔 해 보니 GPT도 아까와는 다른 방법을 알려주었다.
관련해서는 ios 환경을 초기화하고, CocoaPods(Swift 언어에 대한 의존성 관리 툴으로 보인다) 설정을 초기화해 주었다.
rm -rf ~/Library/Developer/Xcode/DerivedData
cd ios
pod install
cd ..
그리고 'npx expo-doctor' 라는 명령어를 이용해서 현재 expo의 설정 상에서 문제가 없는지를 확인해보았다. 그랬더니 이처럼 패키지 간의 의존관계에 문제가 있다는 답변이 나왔다.
아래와 같은 명령어를 시도하니 다음과 같은 에러가 났다.
npx expo install --check
typescript를 설치해볼 것을 권장하기에 그렇다고 했는데, 다음과 같은 에러가 났다. 알고보니 typescript 관련해서도 다른 패키지와 의존성 충돌이 있는 모양이었다.
npm install typescript --save-dev
친절히 오류 메시지를 알려 주길래 따라해 보았다.
sudo chown -R 501:20 "/Users/soyoung/.npm"
'chown'은 'change owner'의 약자인 듯 했다. 즉 해당 디렉토리 안에 있는 모든 파일에 대한 소유 권한을 그룹 ID 20, 사용자 ID 501에 할당한다는 의미였다. .npm 디렉토리 안에는 아마도 관련 캐시나 설정 파일이 들어있을 것 같아서 소유권 변경이 필요한가? 싶어서 일단 명령어를 입력했는데, 문제는 입력해도 오류가 난다는 것이었다. 특정 버전의 라이브러리를 설치하려고 해도 의존성 충돌이 계속 발생했다.
현재 상황에 대해서 간략히 정리해 보자. 애플 로그인 프론트 작업은 1차적으로 완료되었다. 다만 서버와 통신할 때 콘솔에 찍히는 응답이 null인 문제를 해결하면 되겠다.
그런데 오늘 추가적인 문제가 발생했다. 다른 팀원이 알려준 이슈인데, 앱을 지웠다가 다시 깔았을 때 messaging().getToken() 메소드에서 오류가 발생한다는 문제였다. (이 messaging은 RnFirebase 라이브러리의 기능이다.) 그리고 이 이슈는 아마도 내 apple developer 계정에 '프로비저닝 프로파일(Profile)'이 없는 것과 연관이 있다고 말해주었다.
결론은 '프로비저닝 프로파일'을 새로 만들어줘야 했다. 문제는 이 프로파일을 만들기 위해서는 '새 디바이스'를 등록해야 한다는 점이었다. 그런데 이 새 디바이스의 경우, 이미 기존 apple developer 계정에 연동되어 있던 내 아이패드나 팀원의 아이폰은 '이미 등록된 디바이스'로 간주되어 새 디바이스로 간주하지 않는다는 문제가 있었다.
그렇게 프로비저닝 프로파일 생성하는 난관에 부딪히고 있던 때, 다시 Device 탭에 들어가 봤더니 웬일로 잘 되는 것이 아닌가.
이 Device(다른 팀원의 iphone 디바이스다)를 사용해서 apple developer 계정에서 프로비저닝 프로파일을 생성할 수 있었고, 생성한 프로파일을 XCode에 적용할 수 있었다.
그렇게 프로파일을 무사히 적용하고, dev 브랜치와 rebase도 했다. 그리고 다시 'npm run ios:dev' 명령어를 실행하니, 다음과 같은 에러가 뜨는 게 아닌가.
GPT의 조언과 다양한 블로그 글들을 참고해봤는데, GPT가 제시한 원인과는 달리 RN 환경이 아닌 곳에서도 많은 github issue들을 볼 수 있었다. 그에 비해 GPT는 다음과 같은 원인들을 제시했는데, 과연 이 원인들이 정말이었을지는 조금 의문스럽다.
Sentry 설정 문제
Expo와 Sentry의 연동 문제
Sentry 관련 패키지(@sentry/react-native) 설정 문제
3번의 경우 npm i 명령어로 버전 업그레이드를 해 주었다. 여전히 되지 않아서 1-2번 아니면 다른 github issue(찾아봤는데 내 경우와 완벽히 일치하는 issue는 잘 보이지 않았다)를 찾아서 공통점을 파악해봐야 할 것 같다.
1번의 경우 sentry.properties 파일이 다른 경로에 있을 가능성을 제시해 주었는데, 문제는 나는 애초에 sentry.properties 파일이 없었다는 거였다.
2번의 경우도 마찬가지로 설정 파일(app.config.js)에서 expo 관련 설정에서 특정 파라미터(ios.dangerous)의 경로 설정이 잘못되었을 가능성을 제시해 주는데, 문제는 애초에 해당 파라미터와 관련된 설정은 없었다. 아직 여기에서 막히고 있다... 내일 다시 해 봐야겠다.
어제 많은 삽질을 통해서 애플로그인에서 액세스토큰을 발급받는 데는 성공하였다. 그러면 기존의 로직을 사용해서, 이렇게 얻어낸 값을 앱의 값으로 저장해주면 되겠다. 또한 어제 봤는데 애플 로그인에서 맨 처음에 이메일 값을 제대로 저장하지 못할 경우에 대해서 걱정이 많았었다. 그런데 그 밑의 내용을 읽어보니 계속적으로 이메일을 받아올 수 있는 방법이 있었다. (다만 이 경우는 테스트 환경에서만 가능하긴 했다...) 어쨌든 다음과 같은 두 가지 작업을 하면 되겠다.
설정 바꿔서 다시 email 받아오도록 설정하고, 이메일 값 저장해두는 로직 작성하기
받아온 identityToken 값을 백엔드 서버에 보내는 API 작성하기
우선 1번의 경우 위의 사진에 나온 것처럼 에뮬레이터의 설정에 들어가서 기존에 Apple ID를 사용한다는 설정을 다시 취소해 주어야 했다. 취소해 주고 다시 해보니 아래처럼 email 값과 identityToken 값 모두가 잘 들어온다.
그런데 여기서 두 가지의 잠재적 문제점을 발견했다.
첫 번째는 어쨌든 테스트 환경이 아니면 유저가 굳이 폰에서 로그인이 된 설정을 다시 풀 리가 없다. 그러므로 만약 유저가 앱에 최초 로그인을 하는데 그 과정에서 실패가 일어나서 실수로 딱 한번 주어지는 이메일 값을 저장소에 저장하지 못한다면, 문제가 생긴다.
두 번째는 유저가 본인의 이메일 정보를 제공하지 않는 옵션을 선택할 경우이다. 이 경우에는 최초 로그인이더라도 프론트에서 유저의 이메일 정보를 갖고 있을 수 없다.
그래도 두 경우 모두 identityToken의 값(애플에서 로그인을 마치고 받은 액세스토큰과 같은 개념)은 얻을 수 있었다. 여기서 궁금한 점은 identityToken 값으로 유저의 이메일 정보를 얻을 수 있는지였다.
이메일 정보가 중요한 이유는 사실상 이메일 필드가 pk를 제외하고 유저를 유일하게 구분할 수 있는 속성이기 때문에 꼭 필요하다고 판단했기 때문이다. 또한 구글 로그인 유저는 email이 항상 있는 반면 apple 로그인 유저에서는 없다면 이 경우에도 나중에 여러 유저의 데이터를 공통적으로 다루기 어려울 것 같았다.
그래서 찾아보니 pyJWT 라이브러리로 해당 Identitytoken을 분해해볼 수 있을 것 같았다. GPT의 도움을 받아 스크립트를 작성해봤다.
import jwt
import requests
import urllib3
from jwt.algorithms import RSAAlgorithm
APPLE_PUBLIC_KEY_URL = "https://appleid.apple.com/auth/keys"
urllib3.disable_warnings()
def get_apple_public_key(kid):
# SSL 검증 비활성화하고 Apple 공개 키를 가져옴
response = requests.get(APPLE_PUBLIC_KEY_URL, verify=False)
keys = response.json().get("keys", [])
# kid에 맞는 키 찾기
for key in keys:
if key["kid"] == kid:
return RSAAlgorithm.from_jwk(key)
raise ValueError("Matching key not found")
def validate_identity_token(identity_token):
try:
# JWT의 헤더에서 kid 추출
unverified_header = jwt.get_unverified_header(identity_token)
kid = unverified_header["kid"]
# kid에 맞는 Apple 공개 키 가져오기
public_key = get_apple_public_key(kid)
# 토큰 디코드 및 검증
decoded_token = jwt.decode(
identity_token,
public_key,
algorithms=["RS256"],
audience="audience", # 실제 Apple Login에서 설정한 client_id로 변경
issuer="https://appleid.apple.com"
)
# 유효한 토큰인 경우 정보 반환
user_id = decoded_token.get("sub")
email = decoded_token.get("email", None)
return {
"status": "success",
"user_id": user_id,
"email": email
}
except jwt.ExpiredSignatureError:
return {"status": "error", "message": "Token has expired"}
except jwt.InvalidTokenError:
return {"status": "error", "message": "Invalid token"}
except Exception as e:
return {"status": "error", "message": e}
identity_token = "identity_token"
result = validate_identity_token(identity_token)
그리고 그 과정에서 원래는 SSL 관련 에러가 났었다. 이 에러는 SSL 인증서가 없어서 나는 에러였고, SSL 인증서를 발급받거나 SSL 인증을 임시로 무효화하는 방법이 있었다. SSL 인증서 발급은 간단했지만, 그래도 SSL 인증서를 발급받는 방법은 해당 인증서를 서버에도 설치해줘야 했기 때문에 더 번거롭다고 판단했다. 그래서 위에 SSL 인증을 임시로 건너뛰는 코드를 추가해줬다.
그랬더니 다음과 같이 user id와 email 값이 잘 나오더라. 물론 user id는 실제 pk와 같은 정수값은 아니었다. 그리고 emai도 토큰에 잘 포함되어 있어서, 서버에 잘 저장이 가능해 보였다.
그렇다면 앞서 맨 처음에 걱정했던 이메일을 저장하는 문제를 해결해볼 수 있겠다. 이메일을 최초 시도에 바로 받아오는 방법만이 아니라, identityToken 값에서 이를 추출하는 방법이 있겠다. 이 방법을 프론트에서도 사용할 수 있도록 코드를 바꿔보자. js 코드로 애플로그인에서 받은 identityToken을 디코딩하는 방법은 생각보다 간단했다.
이로서 프론트 앱에서도 identityToken 값을 통해서 email 값을 얻을 수 있게 되었다. email 값뿐만 아니라 많은 정보를 볼 수 있었다.
이제 구글 로그인에서 해당 identityToken을 가지고 서버에 요청을 보내는 로직을 참고해서, 애플 로그인에서도 이를 비슷하게 구현해 보자.
그리고 아이폰에서도 구글로그인도 되어야한다... 이를 위해서는 iosClientId 값이 필요하다. 이것도 API를 통해 받아와 보자. 우선은 애플 로그인부터 구현해 보자.
우선 애플 로그인을 시도했을 때 response를 잘 받아와야 하기 때문에, 이를 저장할 상태 변수를 선언해 준다. 이 appleResponse는 애플 로그인이 성공적으로 실행되면 해당 response를 저장하기 위한 변수이다. 또한 구글로그인과 애플로그인은 로직이 겹치는 부분이 많기 때문에 중복 코드를 줄이기 위해서 loginType 변수에 구글 로그인인지, 애플 로그인인지를 저장하도록 하였다.
다만 걸리는 점은 credentialState의 값이 appleAuth.State.AUTHORIZED가 아니라 appleAuth.State.REVOKED였다는 점이다. 왜 revoked가 되었는지 원인을 찾아보려고 했는데, 하나같이 지금 상황에서는 해당되지 않는 원인들이었다.
GPT가 제시한 방법으로는 apple login 관련 설정이 옳지 않아서였다. 그런데, 세상에. 라이브러리에 멀쩡하게 메시지가 나와 있는게 아닌가?
그렇다. 그냥 내가 까막눈이었던 것이다. 그래서 3시간 장장의 삽질은 이렇게 허무하게 끝이 났다.
이제는 지금은 동작하지 않는 애플 로그인 버튼을 누르면 창이 켜지도록 만들어주면 되겠다. 우선 사용하려는 라이브러리의 Mac 설정으로 진행해봤다. 애플 로그인 버튼을 누르면 다음과 같은 에러 로그가 찍힌다.
GPT에게 물어봤더니 앱의 개발자 계정 설정이나 Xcode의 프로젝트 설정 문제 가능성이 있다고 하더라. 우선은 Xcode의 프로젝트 설정에 들어가서, 'apple sign in' 옵션을 추가해주었다. 그리고 Team의 값이 None으로 되어 있었는데, 이 값도 이름으로 바꿔 주었다.
그리고 다시 앱을 실행시켰더니 애플 로그인 버튼을 누르면 동작하지 않고 관련 경고 로그가 떴다.
스택을 보니 아까와 같은 로그가 그대로 찍히고 있었다. 그리고 아래에 보니 이런 로그도 함께 있었다. 무엇부터 해결해야 할지 감이 안 잡혔다. 우선 이것부터 해결해 보기로 했다.
해당 에러는 'expo-splash-screen'이라는 패키지가 ios 앱에서 스플래시 화면을 찾지 못해서 발생하는 에러라고 한다. 이를 위해서는 우선 Xcode를 열고, 파일 설정에서 Storyboard 파일을 찾아서 파일 이름을 SplashScreen.storyboard로 지정하고 프로젝트의 ios 디렉토리에 저장해 주어야 한다고 한다. 일단 해보자.
그저께 발생한 부분에서 아직 막혀있다. package.json 파일의 scripts 변수 안의 값들 중 ios 에뮬레이터에서 앱을 실행시키는 명령어인 'npm run ios'를 입력했다. (정확히는 이렇게 입력하면 그대로 실행되는 게 아니라, 해당 스크립트 파일에 key-value로 명시된 실제 값인 'npx expo run:ios' 명령어가 실행된다.
여러 로그가 쭉 나오더니 에러 로그가 나오면서 또 실행에 실패했다.
단순히 해당 파일을 만들어야 하는 오류는 아니라는 생각이 들어서, 또 어쩌면 Xcode 등과 관련된 문제 같아서 GPT 찬스를 썼다. GPT 피셜 React Native 버전과 패키지 사이의 종속성 오류거나, CocoaPods(이 친구의 정체를 아직도 모르겠다) 설정과 관련이 있을 수 있다고 한다. 그래서 일단 알려준 명령어들을 잘 따라해 보았다.
우선 Podfile을 업데이트 하고 종속성을 설치해 보았다. (여기서 말하는 '종속성'의 구체적인 의미는 무엇일지 모르겠다..)
cd ios
pod deintegrate
pod install
다시 deintegrate한 pod를 install 해 주었다. 이 과정에서 설정 에러가 해결될 가능성이 있을 수도 있나보다. 다시 'pod install'을 실행하니 웬걸 오류가 난다.
GPT 피셜, hermes-engine(js 엔진이라고만 알고 있다)의 버전이 Podfile.lock(podfile 의존성 패키지들을 관리하는 파일인 것으로 보인다)에 기록된 버전과 달라서 나는 오류였다고 한다. 그리고 이 오류가 난 원인은 CocoaPods에서 종속성 관리를 할 때 충돌이 생겨서일 것이라고 한다. (아니 왜...?) 근본 원인이 무엇인진 아직도 모르겠지만, 우선 알려준 명령어로 실행해 보았다.
오류 메시지에 나온 것처럼 뒤에 특정 옵션을 붙여주면 pod install을 할 때 hermes-engine 관련 종속성만 업데이트하고 cocoapods의 전체 repo 업데이트는 생략한다고 한다.
pod update hermes-engine --no-repo-update
미묘하게 또 다른 에러가 났다. 아까와 비슷하게 CocoaPods에서 Sentry/HybridSDK와 관련된 버전을 찾을 수 없다는 말이었다. 그런데 여기서 추천해 준 명령어를 다시 입력해 보았다.
pod update Sentry/HybridSDK
그랬더니 이번에는 'pod install'을 처음 실행할 때 났던 오류가 나면서 이미 실패했던 명령어를 다시 추천해 주는 게 아닌가. 오류가 돌고 돈다.
다시 한 스텝 이전으로 돌아가서 GPT가 알려준 또 다른 방법으로 접근해 보자. 아까 전에 'pod update hermes-engine --no-repo-update' 명령어 말고도 다른 명령어를 알려줬었다. Podfile.lock에서 계속 충돌이 발생하는 것 같으니 이걸 지우고 다시 'pod install'을 시도해 보라는 의미였다.
rm Podfile.lock
pod install
다행히도 해당 방법은 성공하였다. 그렇다면 다시 한 스텝 더 돌아가서, Podfile을 업데이트하고 종속성을 설치해 주었으니 그 다음 스텝을 진행해 보자. 그 다음 스텝은 패키지 의존성과 관련된 문제였는데, node_module이나 pods에서 일부 파일 누락의 가능성(대체 왜인진 모르겠다)이 있으므로 지웠다가 다시 설치하라는 답을 주었다. 일단 해보자.
rm -rf node_modules
rm -rf ios/Pods
npm install
cd ios
pod install
그 다음 방법은 Xcode의 설정을 확인하는 것이었다. 여기서 RN 관련 설정이 잘 되어있는지도 혹시 모르니 확인해 보자. ios 디렉토리에서 해당 프로젝트의 .xcworkspace 파일을 열어주자.
cd ios/onestep.xcworkspace
여기서 확인하려는 설정은 마치 SDK 경로가 잘 설정되어 있는지를 확인하는 것과 비슷했다. 다음과 같은 화면에서 'Header Search Paths'가 올바르게 설정되었는지를 확인하려고 했다.
그리고 XCode 툴을 열어서 위에서 한 것처럼 Build Settings > Header Search Path 설정에 다음과 같은 루트를 추가해 주었다. 해당 애니메이션 관련 라이브러리를 사용하기 위해서 필요한 모양이다.
마지막으로 캐시를 정리해 주었다.
watchman watch-del-all
npm start --reset-cache
cd ios && xcodebuild clean
그 과정에서 또 두 가지의 에러가 났다. 아직 앱을 iOS 에뮬에서 띄우지도 않았는데 말이다. 이쯤되면 발생한 에러들을 트리로 그려서 dependency를 파악하는 것도 어려울 정도로 히스토리가 복잡해진다...!^^
첫 번째는 'npm start --reset-cache' 명령어를 실행하면서 난 뉴 에러들이었다.
두 번째 캡처의 경우는 코드에서 뭔가 잘못된 설정이 되어있는 것 같아서 내가 직접 수정해야 할 것 같으니, 우선 첫 번째 오류(5-1-1)만 해결해보자. GPT 피셜 해당 라이브러리의 react native 코드와 js 코드가 서로 다른 버전으로 설치되어있을 때 나는 오류라고 한다. 나는 그냥 npm install을 한 것밖에 없는데 왜 저러는지, 그리고 이 말이 구체적으로 무슨 말인지는 정확히 이해하진 못했다.
npm list react-native-reanimated
해당 명령어를 입력하면 관련 라이브러리가 어떻게 설치되었는지를 보여주는 것 같다.
버전이 다른지를 확인하라는데, 내가 보기엔 버전이 모두 같다! 뭘 더 해야 하지 싶다. 일단은 GPT가 권장하는 대로 해당 라이브러리의 최신 버전으로 한번 바꿔보자.
npm install react-native-reanimated@latest
그리고 다시 문제의 명령어였던 'npm start --reset-cache'를 실행했다. 그런데 위에서와 똑같은 오류가 다시 나는 게 아닌가. 에러 메시지에서 관련 링크를 주길래 들어가봤다. 링크에서는 아래와 같은 솔루션을 주었다.
일단 저녁을 먹고와서 다시 해보자.
✅ 궁금한 점
1. cocoapods와 hermes-engine은 어떤 관계가 있을까? 위에서 pod install을 할 때 --no-repo-update를 붙이는 옵션이 왜 오류 해결에 영향을 주는지 의문이다.
2. pod deintegrate는 pod를 지우는 것과는 다른 명령어일까?
3. Xcode에서 header search path 설정할 때 recursive와 non-recursive 옵션의 차이는 무엇이고 왜 recursive로 설정해야 할까?
4. 'npm outdated'는 구체적으로 어떤 기능을 하는 명령어일까? 그냥 npm으로 설치된 라이브러리 중 outdated된 라이브러리들을 보여주는 용도인지 궁금하다.
5. 다른 팀원의 컴퓨터에서는 잘 동작하는데 이번에 내가 ios 에뮬레이터를 처음 설치하고 앱을 실행하려고 하면서 이런 많은 문제들이 발생한 상황이다. 이런 환경설정 dependency? 암튼 프론트에서 실행환경을 통일 혹은 통제할 수 있는 방법이 있을까? 이런 과정이 앞으로 틈틈이 있다고 생각하면 좀 많이 성가실 것 같다.
6. watchman을 직접 설치한 기억이 없는데, 물론 내 기억이 잘못되었을 수도 있다. 암튼 watchman은 RN과 직접적으로 연관된 것은 아닌 툴인지, 아님 연관된 어떤 툴인지 궁금했다.
그저께 마주한 문제에 대해서 팀원과 상의를 해 본 결과, 일단 안드로이드에서 애플 로그인 버튼을 disable 시키는 것도 하나의 방법이라는 생각이 들었다. 물론 '안드로이드에서도 당연히 애플 로그인 할 수 있어야 하는 거 아니야?' 라는 질문이 들어온다면 좀 많이 죄책감이 들겠지만... 일단 할 일이 많기에 어쩔 수 없다. 임시방편으로 덮어 쓰고 그 다음에 새로운 방법을 찾아보자.
그렇다면 문제의 그 라이브러리(사실 라이브러리가 문제인지 내가 문제인지는 확실하지 않다)를 사용해볼 수 있겠다. 설정을 차근차근히 따라해 보자.
빌드를 다시 하고 캐시를 삭제해준 뒤, 어제 막혔던 명령어를 실행해 주었더니 우선 expo 홈 화면까지 띄우는 것은 성공했다.
// 빌드 다시 하기
APP_MODE=development npx expo prebuild
// 캐시 삭제하기
rm-rf~/Library/Developer/Xcode/DerivedData
// 어제 막혔던 명령어 실행
APP_MODE=development npx react-native run ios
그러나 여기서 'Recently opened'를 누르면 다음과 같은 에러가 났다.
로그를 보니 특정 확장자로 시작하는 index 파일이 없어서 나는 에러 같았다. 보통 루트 디렉토리의 index 파일을 시작점으로 인식한다는 것은 알고 있었고, 아마도 이 ios emulator를 처음 런칭할 때에도 그렇게 생각하는 것 같았다. 그러나 현재 프로젝트에서는 app/_layout.jsx 파일을 진입점으로 사용하고 있었으므로, 이에 대한 설정이 필요한 것일수도 있다는 생각이 들었다.
GPT와 티키타카를 통해서 다음과 같은 방법들을 시도해봤고, 아쉽지만 모두 실패했다.
1. metro.config.js(metro의 설정파일)에서 기존 코드를 주석처리 한 다음에 다음과 같은 코드를 추가해주었다. return 값의 mainFields 값들 중 하나를 진입점으로 보는 것이라고 추측했고, 여기에 기본값인 'index.js/index.ts' 파일 대신에 'app/_layout.jsx' 값을 대신 넣어주었다.