RSS듀오랩스
모바일 앱

Expo CNG: android 와 ios 폴더가 리포에 없는 이유

작성자
듀오랩스 대표·5분 읽기

Expo 로 만든 앱의 리포를 클론하면 ios/android/ 도 없습니다. .gitignore 를 열어 보면 아예 막혀 있습니다.

/ios/
/android/

그런데 그 리포에서 나온 앱은 스토어에 올라가 있습니다. 네이티브 프로젝트 없이 네이티브 앱이 나온 셈입니다.

아직 안 만든 것이라는 오해

흔한 이해는 두 가지입니다. 아직 네이티브 코드를 건드릴 일이 없어서 안 만든 것이거나, 예전 Expo 의 eject 를 아직 안 한 것이라는 쪽입니다. 둘 다 "언젠가 만들면 그때부터 내 소스" 라는 그림을 전제합니다.

그 그림으로는 설명되지 않는 것이 있습니다. npx expo prebuild 를 돌리면 ios/ 가 생기는데, 한 번 더 돌리면 또 생깁니다. 지우고 다시 돌려도 같은 것이 나옵니다. 소스라면 이럴 이유가 없습니다.

소스가 아니라 산출물인 네이티브 프로젝트

Expo 는 이 방식을 Continuous Native Generation 이라고 부릅니다. 문서의 표현을 그대로 옮기면, 네이티브 프로젝트는 "필요할 때만 생성되는 짧은 수명" 을 갖고, 개발자는 "네이티브 프로젝트 코드 전부가 아니라 자기 커스터마이징의 정의만" 유지합니다.

정본은 app.json 과 config plugin 입니다. ios/ 는 그것을 컴파일러가 읽을 수 있는 형태로 펼쳐 놓은 결과입니다. 컴파일러는 app.json 을 모르고 .xcodeproj 만 알기 때문에 그 변환이 필요합니다.

node_modules 와 같은 자리라고 보면 대체로 맞습니다. package.json 이 정본이고 node_modules 는 그것을 펼친 결과이며, 지우고 다시 만들어도 같은 것이 나오고, 그래서 커밋하지 않습니다.

안드로이드도 똑같습니다. npx expo prebuild -p android 를 돌리면 android/ 가 같은 방식으로 생깁니다. 한쪽만 특별하지 않습니다.

손으로 고친 것이 사라지는 이유

이 구분이 실무에서 값을 치르는 자리는 여기입니다. Xcode 를 열어 서명 설정을 바꾸거나 build.gradle 을 손보면 그 순간에는 됩니다. 다음에 SDK 를 올리거나 플러그인을 추가하면서 prebuild 를 다시 돌리면 원래대로 돌아갑니다.

바꿀 것이 있으면 결과물이 아니라 생성 과정에 넣어야 합니다. 그 자리가 config plugin 입니다. 플러그인은 두 시점에 끼어듭니다. 앱 설정을 평가할 때 한 번, 그리고 prebuild 가 네이티브 파일을 쓰는 동안 한 번입니다. 뒤쪽이 우리가 필요로 하는 시점입니다. 매번 생성될 때마다 같은 수정이 다시 적용되기 때문입니다.

--clean 없이 돌릴 때 갈리는 결과

prebuild 는 기본적으로 기존 파일 위에 변경을 얹습니다. 빠른 대신, 문서가 적어 둔 대로 "경우에 따라 같은 결과가 나오지 않을 수 있습니다". --clean 은 기존 네이티브 디렉터리를 지우고 처음부터 만듭니다.

무엇이 남고 무엇이 덮이는지는 파일마다 다릅니다. 문서도 그 경계를 나열하지 않고 다를 수 있다고만 말합니다. 저는 이 부분을 추측하지 않는 편이 낫다고 봅니다. 플러그인이 실제로 먹는지 확인할 때는 --clean 으로 돌려서 보는 쪽이 확실합니다.

커밋하는 순간 소스가 되는 지점

문서는 네이티브 디렉터리를 .gitignore 에 넣는 것을 기본으로 두면서도, 커밋해서 쓰는 경우를 함께 설명합니다. 플러그인이 없는 네이티브 수정이 필요하거나 빌드 파이프라인이 그것을 요구할 때입니다.

그 선택을 하면 CNG 를 반쯤 끄는 것입니다. 그때부터는 SDK 를 올릴 때마다 생성된 결과와 손으로 고친 것을 사람이 합쳐야 합니다. 저라면 플러그인으로 표현할 방법을 먼저 찾고, 정말 안 될 때만 커밋 쪽으로 넘어가겠습니다. 되돌아오기가 쉽지 않은 방향이라서 그렇습니다.

설계에서 무엇이 달라지나

네이티브 폴더를 산출물로 보면 판단이 몇 가지 따라옵니다. 리포에 없는 것은 결함이 아니라 정상입니다. 빌드 기계에는 prebuild 를 돌릴 수 있는 환경이 있어야 합니다. 그리고 "네이티브를 고쳤다" 는 말은 app.json 이나 플러그인을 고쳤다는 뜻이어야 하며, 그렇지 않다면 그 수정은 다음 생성까지만 사는 것입니다.

클라우드 빌드를 떠나 로컬에서 빌드하려 할 때 이 구분이 먼저 걸립니다. 그 준비에서 걸린 다른 항목들은 따로 적었습니다.

이 게시글 공유하기

마지막 수정:

공유하실 때는 출처(Duolabs)와 원문 주소를 표시해 주세요.