expo 프로젝트 앱스토어 제출기 - 1

황토소금·2024년 10월 16일

TIL

목록 보기
38/49

들어가며

애플 앱스토어에 앱 올리는걸 더 이상 지체할 수 없다.
앱 기능이 모두 정상동작하는진 어제 테스트완료했고 이제 ios에서 빌드되게 한 후 스토어에 제출하기

ios 빌드하기

지금까지 안드로이드를 중심으로 개발했어서 ios는 신경도 안쓰고 있었음

당장 생각나는 문제

  • firebase sdk를 사용하기 위해 googleservice 어쩌구 파일이 필요하다
    이거 말곤 아직 빌드도 안해보았기에 문제될 게 없음
    firebase console 들어가서 .plist 파일 받아서 환경에 맞게 ios폴더 안으로 들어가게 app config도 잘 작성했다.
    eas에서 빌드할 때도 잘 들어갈 수 있게 eas scret에도 등록해야 한다.
    근데 최근에 안건데 eas cloud 말고 로컬에서도 빌드가 가능한듯 문서
eas build --platform android --local
//or
eas build --platform ios --local

아무튼 이제 expo run prebuild:ios를 해보니

⚠️ Something went wrong running pod install in the ios directory.
Command pod install failed.
└─ Cause: The following Swift pods cannot yet be integrated as static libraries:
The Swift pod FirebaseCoreInternal depends upon GoogleUtilities, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set use_modular_headers! globally in your Podfile, or specify :modular_headers => true for particular dependencies.

라고 한다. 아래 스위프트 팟들이 아직 정적 라이브러리로 통합되지 않았다...? 라고 하는데 이해가 잘 안되어서 구글에 검색하니까 감사하게도 스택오버플로에 같은 문제를 겪은 사례가 있었다.

ios를 전혀 몰라서 조금 찾아봄
podfile: 필요한 외부 라이브러리를 관리하는 곳 package.json같은건가
pod: 외부 라이브러리들. pod install하면 podfile에 적힌 pod들을 다운받는다.
module: 우리가 아는 모듈. 특정 기능을 하는 독립된 부분
module map: Objective-C API 와 Swift API 의 중간 다리 역할을 한다 출처
swift는 모듈화 방식을 사용하는데 object c는 헤더 파일 방식을 써서 그렇다고함.
무슨 차이인지 잘 모르겠음.
static libraries: 파일 내에서 import하는 식으로 라이브러리를 사용할 때 라고 함.
아무튼 swift에서는 모듈로 정의되어야 해당 라이브러리를 import할 수 있는데 그게 안되나봄

그리고 저 스택오버플로에서 하라는게 gpt랑 얘기해보니까
use_framework란 CocoaPods의 Podfile DSL에서 제공하는 메서드 또는 지시문입니다. 이 명령어는 프로젝트 내의 모든 Pod를 동적 프레임워크(dynamic frameworks)로 통합하도록 CocoaPods에 지시합니다.
:linkage => :static 옵션을 추가하면, 정적 프레임워크(static frameworks)로 통합하도록 설정합니다.
use_react_native!란 Podfile DSL에서 제공하는 메서드로, React Native 관련 Pods를 설정하고 통합하는 역할을 합니다.
$RNFirebaseAsStaticFramework = true란 전역 변수를 설정하는 Ruby 코드입니다.
라고 설명해준다. ios를 잘 몰라서 맞는 말을 하는건진 모르겠지만 일리있어보인다.
실제로 저렇게 스택오버플로 따라한 뒤에 prebuild:ios 해보니까 에러가 해결되었다.

그리고 이때 ios 폴더 내에 있는 파일을 직접 수정한건데 이러면 나중에 prebuild를 할 때마다 방금 수정한 내용을 다시 해야하는 불편함이 생긴다.
expo에서 CNG(continuous native generation) 기능을 강조하는 것 같은데 이렇게 어쩔 수 없이 네이티브 파일을 건드려야 하는 일이 생기면 어쩌나 예전부터 고민했었는데 실제가 되었다.

firebase sdk를 쓰려고 google service 파일을 네이티브 파일에 넣는 간단한 작업은 app.config.js에 설정만 하면 해결되는데 이렇게 옵션으로 지원해주지 않는 수정사항은 어떻게 일관되게 적용할 수 있을까

몰라서 물어보았다.
expo 개발자 디스코드방에 물어보니까 한시간 정도만에 바로 댓글이 달렸다. expo 직원같아 보이는 분이 예전부터 느꼈는데 커뮤니티에서 댓글을 너무 잘 달아주시는듯

You should as much as possible avoid modifying the native folders.
Modifying them manually basically applies disabling Prebuild/CNG. That's just the nature of it, since Prebuild generates them from scratch.
Hence, if you want to make modifications you'd always first want to look at using or writing an Expo config plugin

라고 알려주심. Expo config plugin이라는게 있는지 처음 알았다.

스택오버플로 내용과 위 expo config plugin 링크를 주고 gpt한테 코드를 짜달라 하니까 뚝딱 만들어준다.

// plugins/withStaticFrameworks.js

const { withAppBuildGradle, withDangerousMod, createRunOncePlugin } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

/**
 * Modifies the Podfile to include `use_frameworks! :linkage => :static` and `$RNFirebaseAsStaticFramework = true`
 */
const withStaticFrameworks = (config) => {
  return withDangerousMod(config, [
    'ios',
    async (config) => {
      const podfilePath = path.join(config.modRequest.projectRoot, 'ios', 'Podfile');
      let podfile = fs.readFileSync(podfilePath, 'utf8');

      // Define the lines to add
      const linesToAdd = `
use_frameworks! :linkage => :static

$RNFirebaseAsStaticFramework = true

use_react_native!
`.trim();

      // Check if `use_frameworks! :linkage => :static` is already present
      if (!podfile.includes('use_frameworks! :linkage => :static')) {
        // Insert the lines before `use_react_native!`
        podfile = podfile.replace(/use_react_native!/, `${linesToAdd}\n\nuse_react_native!`);
        
        // Save the modified Podfile
        fs.writeFileSync(podfilePath, podfile, 'utf8');
        console.log('Podfile modified to include static frameworks settings.');
      } else {
        console.log('Podfile already includes static frameworks settings.');
      }

      return config;
    },
  ]);
};

module.exports = createRunOncePlugin(withStaticFrameworks, 'withStaticFrameworks', '1.0.0');

withDangerousMod: 네이티브 파일을 직접 수정할 수 있게 해주는 Expo Config Plugin API입니다.
• createRunOncePlugin: 플러그인이 여러 번 실행되지 않도록 보장합니다.
• Podfile 수정 로직:
• use_frameworks! :linkage => :static와 $RNFirebaseAsStaticFramework = true를 Podfile에 추가합니다.
• 이미 설정이 포함되어 있는지 확인하여 중복 추가를 방지합니다.
• use_react_native! 앞에 설정을 삽입합니다.

설명도 너무 잘해줌

근데 withAppBuildGradle는 쓰지도 않는데 임포트함

그리고 expo문서를 읽어보니까 withDangerousMod는 실험적이고 사용하는걸 추천을 안하고 있는데 gpt는 과감한 거 같다.
withPodfile같은 이미 만들어진 plugin을 사용해서 podfile을 수정할 수도 있을 것 같은데
하지만 여기서 이걸 더 깊게 파고 들어가면 ios 빌드를 성공적으로 하는 지금 목표와는 다른거니 일단 여기까지만 기록해두고 지라에 남겨두고 할 일 하기

아무튼 빌드는 이제 성공적으로 잘 되고 앱도 잘 켜진다.

앱 실행 후 에러 해결

앱 실행 후에 생기는 에러는 전체적으로 파악하기가 불가능 한 에러때문에 그대로 멈춰버리니까...

일단 당장 생기는 문제는 google 로그인할 때 iosClientId가 없는게 문제라고 함.
예전에 구글 클라우드 콘솔에서 구글 로그인 api키 만들 때 ios는 키를 만들지 않았나봄

다시 들어가서

OAuth 2.0 클라이언트 ID 메뉴를 보니까 android client Id만 만들어져있다.
ios용도 만들기

아이디 받아서 Google.useAuthRequest의 인자로 넣어주니까 에러가 사라졌다.

그런데 이걸 해결하니 다음 에러가 발생했다.
디바이스를 구분하기 위해서 FCM에서 발급하는 토큰을 가지고 디바이스를 구분하고 있었는데 여기서 messaging.getToken()가 ios에서 제대로 동작하지 않음

[Error: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().][onestep] [Error: [messaging/unregistered] You must be registered for remote messages before calling getToken, see messaging().registerDeviceForRemoteMessages().]

getToken을 호출하기 전에 원격 메세지를 등록해야한다는게 무슨 말일까
messaging().registerDeviceForRemoteMessages() 이걸 보라고 하니까 봐야겠다

유저가 remote notification에 등록되어있는지 확인하는 거라고 한다.
remote notification에 등록은 어떻게 하는거지??

profile
안녕하세요, 반갑습니다.

0개의 댓글