Skip to main content
Version: Next

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

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.jsoncreate-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 라이브러리를 성공적으로 배포했다.