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.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.name을 AppSpecs로 설정했고, 라이브러리에서는 RNNativeSampleModuleSpec으로 설정했다면, AppSpecs를 RNNativeSampleModuleSpec으로 모두 바꾼다.

이제 모든 필수 코드를 앱에서 분리해 별도의 라이브러리로 이동했다.

라이브러리 테스트하기​

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