거의 알고리즘 일기장

Monorepo 환경에 react native 추가하기(with turborepo) 본문

react-native

Monorepo 환경에 react native 추가하기(with turborepo)

건우권 2023. 9. 20. 00:31

필자는 개인적으로 프로젝트에 기능을 추가할때, 미니 프로젝트를 만들어서 테스트를 충분히 해본 이후 적용하는것을 선호한다.

하지만, 미니 프로젝트를 너무 여러개 만들다보니 예전에 만들었던것을 잊고 새로 세팅하고 새로 세팅하는 금붕어 같은 짓으로 시간을 쓰곤했다.

그래서 떠올린게 최근에 만든 turborepo가 no configuration 수준으로 설정이 간편해서 이걸 이용해 모노레포 환경을 만들면 관리하기 편하지 않을까? 생각해서 시간이 남을때 조금씩 해보게 되었다.

 

솔직히 Next, react, expo 까지는 문서에 적혀있기도하고 example 보고 세팅하기 편했다.

근데, react native cli는 세팅하면서 자료도 없고 몇가지 짜증난 부분이 있었어서 정리해둔다.


변경해야 할 사항은 크게 세가지 부분이다.

1. metro config

2. ios node_module 상대경로로 쓰여있는 부분 수정

3. android node_module 상대경로로 쓰여있는 부분 수정

metro config

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const path = require('path');

// Find the workspace root, this can be replaced with `find-yarn-workspace-root`
const workspaceRoot = path.resolve(__dirname, '../..');
const projectRoot = __dirname;

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = getDefaultConfig(projectRoot);

// 1. Watch all files within the monorepo
config.watchFolders = [workspaceRoot];
// 2. Let Metro know where to resolve packages, and in what order
config.resolver.nodeModulesPaths = [
  path.resolve(projectRoot, 'node_modules'),
  path.resolve(workspaceRoot, 'node_modules'),
];
// 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths`
config.resolver.disableHierarchicalLookup = true;

module.exports = config;

root와 project의 node_module 둘다 추가해주는 부분이 들어간다. 해당 내용은 expo 문서에 Monorepo 환경에서 metro config 변경하는 부분 참고해서 변경했다.
https://docs.expo.dev/guides/monorepos/

 

Work with monorepos

Learn about setting up Expo projects in a monorepo with Yarn v1 workspaces.

docs.expo.dev


Ios 

아마 이 상태로 실행하면, react native code and images 과정에서 적절하게 node_modules 파일을 찾아가지 못하는 현상이 있을텐데, 아래와 같이 경로를 수정해주면 된다.


android

1. project/settings.gradle

rootProject.name = 'rn-bare-app'
apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../../../node_modules/@react-native/gradle-plugin')

2. app/build.gradle
아래부분 참고하센

//...
react {
    /* Folders */
    //   The root of your project, i.e. where "package.json" lives. Default is '..'
    // root = file("../")
    //   The folder where the react-native NPM package is. Default is ../node_modules/react-native
     reactNativeDir = file("../../../../node_modules/react-native")
    //   The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
     codegenDir = file("../../../../node_modules/@react-native/codegen")
    //   The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
     cliFile = file("../../../../node_modules/react-native/cli.js")

//...
}
//...
apply from: file("../../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

3. (option) react-native-gesture-handler 쓰는 경우에 해당 내용안에 react-native를 상대경로로 찾아가는 부분이 있다 ㅡㅡ 이 부분은 환경변수에 값을 추가해주면 됨 (gradle.properties)

REACT_NATIVE_NODE_MODULES_DIR=../../../../../node_modules/react-native

근거는 다음과 같다.

//react-native-gesture-handler/android/build.gradle중
//...
def resolveReactNativeDirectory() {
    //여기보면 REACT_NATIVE_NODE_MODULES_DIR 이렇게 경로를 환경변수로 보면 이걸 먼저 읽으므로 이걸 사용해서 해결하는게 나이스해보임
    //근데 gesture handler docs에 저 환경변수에 대한 내용이 검색이 안되는데ㅠ 알잘딱깔센 해야하는듯
    def reactNativeLocation = safeExtGet("REACT_NATIVE_NODE_MODULES_DIR", null)
    if (reactNativeLocation != null) {
        return file(reactNativeLocation)
    }

    // monorepo workaround
    // react-native can be hoisted or in project's own node_modules
    def reactNativeFromProjectNodeModules = file("${rootProject.projectDir}/../node_modules/react-native")
    if (reactNativeFromProjectNodeModules.exists()) {
        return reactNativeFromProjectNodeModules
    }

    def reactNativeFromNodeModulesWithReanimated = file("${projectDir}/../../react-native")
    if (reactNativeFromNodeModulesWithReanimated.exists()) {
        return reactNativeFromNodeModulesWithReanimated
    }

    throw new Exception(
        "[react-native-gesture-handler] Unable to resolve react-native location in " +
            "node_modules. You should add project extension property (in app/build.gradle) " +
            "`REACT_NATIVE_NODE_MODULES_DIR` with path to react-native."
    )
}
//...

결과

성공적

응~ 완료


해보면 별거아니지만, 왠지 react native 처음 하거나 익숙하지 않은 사람들은 세팅할때 혐오증 걸릴수도 있을것 같은 느낌을 살짝 받았다.


참고

https://velog.io/@jihoson94/%EB%AA%A8%EB%85%B8-%EB%A0%88%ED%8F%AC%EC%97%90%EC%84%9C-react-native-%EC%84%A4%EC%A0%95-%EB%B0%A9%EB%B2%95

 

모노 레포에서 react-native 설정 방법

react native 프로젝트를 웹 프로젝트들과 함께 관리하고 유틸 함수를 함께 관리하면 용이할 것 같아서 구성을 해보게 되었습니다.NX를 이용해서 React Native 프로젝트를 포함한 모노레포를 구성할 때

velog.io

https://github.com/byCedric/expo-monorepo-example/blob/main/apps/mobile/metro.config.js

반응형
Comments