Skip to main content

모듈을 라이브러리로 만들기

React Native는 다양한 문제를 해결하기 위한 풍부한 라이브러리 생태계를 가지고 있다. reactnative.directory 웹사이트에서 React Native 라이브러리를 모아볼 수 있으며, 이는 모든 React Native 개발자가 북마크해두면 유용한 자료다.

때로는 코드 재사용을 위해 별도의 라이브러리로 추출할 가치가 있는 모듈을 작업할 수 있다. 이는 여러분이 모든 앱에서 재사용하고 싶은 라이브러리일 수도 있고, 오픈 소스 컴포넌트로 생태계에 배포하고 싶은 라이브러리일 수도 있으며, 심지어 판매하고 싶은 라이브러리일 수도 있다.

이 가이드에서는 다음을 배울 수 있다:

  • 모듈을 라이브러리로 추출하는 방법
  • NPM을 사용해 라이브러리를 배포하는 방법

모듈을 라이브러리로 분리하기

create-react-native-library 도구를 사용해 새로운 라이브러리를 생성할 수 있다. 이 도구는 필요한 모든 보일러플레이트 코드를 포함해 새로운 라이브러리를 설정한다. 다양한 플랫폼에서 요구하는 모든 설정 파일과 파일을 제공하며, 라이브러리 생성 과정을 안내하는 인터랙티브 메뉴도 포함되어 있다.

모듈을 별도의 라이브러리로 분리하려면 다음 단계를 따르면 된다:

  1. 새로운 라이브러리 생성
  2. App에서 라이브러리로 코드 이동
  3. 새로운 구조에 맞게 코드 업데이트
  4. 라이브러리 배포

이 과정을 통해 모듈을 독립적인 라이브러리로 만들 수 있다.

1. 라이브러리 생성하기

  1. 라이브러리 생성 프로세스를 시작하려면 다음 커맨드를 실행한다:
sh
npx create-react-native-library@latest <라이브러리 이름>
  1. 모듈에 이름을 추가한다. 이 이름은 유효한 npm 이름이어야 하므로 모두 소문자로 작성한다. 단어를 구분하기 위해 -를 사용할 수 있다.
  2. 패키지에 대한 설명을 추가한다.
  3. _"어떤 타입의 라이브러리를 개발하고 싶은가?"_라는 질문에 도달할 때까지 폼을 계속 작성한다. 어떤 타입의 라이브러리
  4. 이 가이드를 위해 Turbo 모듈 옵션을 선택한다. New Architecture와 Legacy Architecture 모두에 대한 라이브러리를 생성할 수 있다는 점을 기억한다.
  5. 그런 다음, 플랫폼에 접근하는 라이브러리(Kotlin & Objective-C)를 만들지, 아니면 공유 C++ 라이브러리(Android와 iOS 모두에서 사용할 수 있는 C++)를 만들지 선택할 수 있다.
  6. 마지막으로 Test App을 선택한다. 이 옵션은 라이브러리 폴더 내에 이미 구성된 별도의 앱을 생성한다.

인터랙티브 프롬프트가 완료되면, Visual Studio Code에서 다음과 같은 구조의 폴더가 생성된다:

새 라이브러리 초기화 후 폴더 구조.

생성된 코드를 자유롭게 탐색해 볼 수 있다. 그러나 가장 중요한 부분은 다음과 같다:

  • android 폴더: Android 코드가 위치한 곳
  • cpp 폴더: C++ 코드가 위치한 곳
  • ios 폴더: iOS 코드가 위치한 곳
  • src 폴더: JS 코드가 위치한 곳

package.json 파일은 이미 create-react-native-library 도구에 제공한 모든 정보로 구성되어 있으며, 패키지 이름과 설명이 포함되어 있다. 또한 package.json은 Codegen을 실행할 수 있도록 이미 구성되어 있다.

json
  "codegenConfig": {
"name": "RN<모듈 이름>Spec",
"type": "all",
"jsSrcsDir": "src",
"outputDir": {
"ios": "ios/generated",
"android": "android/generated"
},
"android": {
"javaPackageName": "com.<모듈 이름>"
}
},

마지막으로, 라이브러리에는 iOS와 Android와 연결할 수 있는 모든 인프라가 이미 포함되어 있다.

2. 앱에서 코드를 복사하기

이 가이드의 나머지 부분은 여러분의 앱에 로컬 Turbo Native Module이 있다고 가정한다. 이 모듈은 웹사이트의 다른 가이드에 나온 지침에 따라 생성된 것이다: 플랫폼별 Turbo Native Modules 또는 크로스 플랫폼 Turbo Native Modules. 하지만 이 방법은 컴포넌트와 레거시 아키텍처 모듈 및 컴포넌트에도 적용된다. 복사하고 업데이트해야 할 파일을 적절히 수정해야 한다.

  1. [레거시 아키텍처 모듈 및 컴포넌트에는 필요하지 않음] 앱의 specs 폴더에 있는 코드를 create-react-native-library로 생성된 src 폴더로 이동한다.
  2. index.ts 파일을 업데이트하여 Turbo Native Module 스펙이 라이브러리에서 접근 가능하도록 올바르게 내보낸다. 예를 들면 다음과 같다:
ts
import NativeSampleModule from './NativeSampleModule';

export default NativeSampleModule;
  1. 네이티브 모듈을 복사한다:

    • 앱에서 작성한 네이티브 모듈 코드가 있다면, android/src/main/java/com/<모듈 이름>의 코드를 해당 코드로 교체한다.
    • 앱에서 작성한 네이티브 모듈 코드가 있다면, ios 폴더의 코드를 해당 코드로 교체한다.
    • 앱에서 작성한 네이티브 모듈 코드가 있다면, cpp 폴더의 코드를 해당 코드로 교체한다.
  2. [레거시 아키텍처 모듈 및 컴포넌트에는 필요하지 않음] 이전 스펙 이름을 라이브러리의 package.json에 있는 codegenConfig 필드에 정의된 새로운 스펙 이름으로 업데이트한다. 예를 들어, 앱의 package.json에서 codegenConfig.nameAppSpecs로 설정했고, 라이브러리에서는 RNNativeSampleModuleSpec으로 설정했다면, 모든 AppSpecsRNNativeSampleModuleSpec으로 바꾼다.

이제 모든 필요한 코드를 앱에서 분리하여 별도의 라이브러리로 옮겼다.

라이브러리 테스트 방법

create-react-native-library는 라이브러리와 잘 동작하도록 미리 구성된 유용한 예제 앱을 제공한다. 이는 라이브러리를 테스트하는 데 매우 효과적인 방법이다.

example 폴더를 보면 react-native-community/template에서 생성할 수 있는 새로운 React Native 앱과 동일한 구조를 확인할 수 있다.

라이브러리를 테스트하려면 다음 단계를 따르면 된다:

  1. example 폴더로 이동한다.
  2. 모든 의존성을 설치하기 위해 yarn install을 실행한다.
  3. iOS의 경우 CocoaPods를 설치해야 한다: cd ios && pod install.
  4. example 폴더에서 yarn android를 실행해 Android를 빌드하고 실행한다.
  5. example 폴더에서 yarn ios를 실행해 iOS를 빌드하고 실행한다.

로컬 모듈로 라이브러리 사용하기

NPM에 배포하지 않고 애플리케이션에서 로컬 모듈로 라이브러리를 재사용하고 싶은 경우가 있다. 이 경우 라이브러리가 애플리케이션과 동일한 레벨에 위치하는 구조가 될 수 있다.

shell
Development
├── App
└── Library

create-react-native-library로 만든 라이브러리도 이 방식으로 사용할 수 있다.

  1. App 폴더로 이동한 후 yarn add ../Library를 실행해 라이브러리를 추가한다.
  2. iOS의 경우, App/ios 폴더로 이동한 후 bundle exec pod install을 실행해 의존성을 설치한다.
  3. App.tsx 코드를 업데이트해 라이브러리의 코드를 임포트한다. 예를 들어:
tsx
import NativeSampleModule from '../Library/src/index';

이 상태에서 앱을 실행하면 Metro가 앱에 제공해야 할 JS 파일을 찾지 못한다. 이는 Metro가 App 폴더에서 실행되기 때문에 Library 폴더에 있는 JS 파일에 접근할 수 없기 때문이다. 이 문제를 해결하려면 metro.config.js 파일을 다음과 같이 업데이트한다.

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

/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
+ const path = require('path');

- const config = {}
+ const config = {
+ // Metro가 필요한 외부 의존성을 해결할 수 있도록 설정
+ watchFolders: [
+ path.resolve(__dirname, '../Library'),
+ ],
+ resolver: {
+ extraNodeModules: {
+ 'react-native': path.resolve(__dirname, 'node_modules/react-native'),
+ },
+ },
+};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

watchFolders 설정은 Metro가 추가 경로에서 파일과 변경 사항을 감시하도록 한다. 이 경우 ../Library 경로를 지정해 src/index 파일에 접근할 수 있게 한다. resolver 속성은 라이브러리가 앱에서 사용하는 React Native 코드를 제공하는 데 필요하다. 라이브러리가 React Native에서 코드를 참조하고 임포트할 수 있도록 추가 설정이 포함된다.

이제 평소처럼 앱을 빌드하고 실행할 수 있다:

  • example 폴더에서 yarn android를 실행해 Android 앱을 빌드하고 실행한다.
  • example 폴더에서 yarn ios를 실행해 iOS 앱을 빌드하고 실행한다.

라이브러리를 NPM에 배포하기

create-react-native-library 덕분에 NPM에 모든 것을 배포하기 위한 설정이 이미 준비되어 있다.

  1. 모듈의 의존성을 설치한다: yarn install
  2. 라이브러리를 빌드한다: yarn prepare
  3. 배포한다: yarn release

잠시 후, NPM에서 라이브러리를 찾을 수 있다. 이를 확인하려면 다음 명령을 실행한다:

bash
npm view <package.name>

여기서 package.name은 라이브러리 초기화 시 package.json 파일에 설정한 name이다.

이제 애플리케이션에 라이브러리를 설치할 수 있다:

bash
yarn add <package.name>
note

iOS의 경우, 네이티브 코드가 포함된 새로운 모듈을 설치할 때마다 CocoaPods를 다시 설치해야 한다. 이를 위해 bundle exec pod install(권장) 또는 Ruby의 Bundler를 사용하지 않는다면 pod install(비권장)을 실행한다.

축하한다! 첫 번째 React Native 라이브러리를 성공적으로 배포했다.