모듈을 라이브러리로 만들기
React Native는 일반적인 문제를 해결하기 위한 다양한 라이브러리로 가득 차 있다. reactnative.directory 웹사이트에서 React Native 라이브러리를 모아두었는데, 모든 React Native 개발자가 북마크해두면 유용한 리소스다.
때로는 코드 재사용을 위해 별도의 라이브러리로 추출할 만한 가치가 있는 모듈을 작업할 수도 있다. 이 라이브러리는 모든 앱에서 재사용하고 싶은 라이브러리일 수도 있고, 오픈소스 컴포넌트로 생태계에 배포하고 싶은 라이브러리일 수도 있으며, 심지어 판매하고 싶은 라이브러리일 수도 있다.
이 가이드에서는 다음과 같은 내용을 배운다:
- 모듈을 라이브러리로 추출하는 방법
- NPM을 사용해 라이브러리를 배포하는 방법
라이브러리로 모듈 추출하기
create-react-native-library
도구를 사용해 새로운 라이브러리를 생성할 수 있다. 이 도구는 다양한 플랫폼에서 필요한 모든 설정 파일과 파일을 포함한 보일러플레이트 코드를 자동으로 설정한다. 또한 라이브러리 생성 과정을 안내하는 인터랙티브 메뉴도 제공한다.
모듈을 별도의 라이브러리로 추출하려면 다음 단계를 따르면 된다:
- 새로운 라이브러리를 생성한다.
- App에서 라이브러리로 코드를 이동한다.
- 새로운 구조를 반영하도록 코드를 업데이트한다.
- 라이브러리를 배포한다.
1. 라이브러리 생성하기
- 라이브러리 생성 프로세스를 시작하려면 다음 명령어를 실행한다:
npx create-react-native-library@latest <라이브러리 이름>
- 모듈에 이름을 추가한다. 이름은 유효한 npm 이름이어야 하므로 모두 소문자로 작성한다. 단어를 구분하기 위해
-
를 사용할 수 있다. - 패키지에 대한 설명을 추가한다.
- "어떤 타입의 라이브러리를 개발하고 싶은가요?" 질문이 나올 때까지 폼을 계속 작성한다.
- 이 가이드에서는 Turbo 모듈 옵션을 선택한다. New Architecture와 Legacy Architecture 모두에 대한 라이브러리를 생성할 수 있다는 점에 주목한다.
- 그런 다음, 플랫폼에 접근하는 라이브러리(Kotlin & Objective-C)를 만들지, 아니면 공유 C++ 라이브러리(Android와 iOS용 C++)를 만들지 선택할 수 있다.
- 마지막으로
Test App
을 선택한다. 이 옵션은 라이브러리 폴더 내에 이미 구성된 별도의 앱을 생성한다.
인터랙티브 프롬프트가 완료되면 도구는 폴더를 생성한다. 이 폴더의 구조는 Visual Studio Code에서 다음과 같이 보인다:

생성된 코드를 자유롭게 탐색할 수 있다. 그러나 가장 중요한 부분은 다음과 같다:
android
폴더: Android 코드가 위치한 곳cpp
폴더: C++ 코드가 위치한 곳ios
폴더: iOS 코드가 위치한 곳src
폴더: JS 코드가 위치한 곳
package.json
은 create-react-native-library
도구에 제공한 모든 정보로 이미 구성되어 있다. 여기에는 패키지의 이름과 설명이 포함된다. 또한 package.json
은 Codegen을 실행할 수 있도록 이미 설정되어 있다.
"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)에 따라 생성되었다. 하지만 이 가이드는 컴포넌트와 레거시 아키텍처 모듈 및 컴포넌트에도 적용된다. 복사하고 업데이트해야 할 파일을 적절히 조정해야 한다.
- [레거시 아키텍처 모듈 및 컴포넌트에는 필요 없음] 앱의
specs
폴더에 있는 코드를create-react-native-library
로 생성된src
폴더로 이동한다. index.ts
파일을 업데이트하여 Turbo Native Module 스펙을 올바르게 내보내도록 한다. 예를 들면 다음과 같다:
import NativeSampleModule from './NativeSampleModule';
export default NativeSampleModule;
-
네이티브 모듈을 복사한다:
- 앱에서 작성한 네이티브 모듈 코드가 있다면,
android/src/main/java/com/<모듈 이름>
에 있는 코드를 해당 코드로 대체한다. - 앱에서 작성한 네이티브 모듈 코드가 있다면,
ios
폴더에 있는 코드를 해당 코드로 대체한다. - 앱에서 작성한 네이티브 모듈 코드가 있다면,
cpp
폴더에 있는 코드를 해당 코드로 대체한다.
- 앱에서 작성한 네이티브 모듈 코드가 있다면,
-
[레거시 아키텍처 모듈 및 컴포넌트에는 필요 없음] 이전 스펙 이름을 새로운 스펙 이름으로 모두 업데이트한다. 새로운 스펙 이름은 라이브러리의
package.json
에 있는codegenConfig
필드에 정의된 이름이다. 예를 들어, 앱package.json
에서codegenConfig.name
을AppSpecs
로 설정했고, 라이브러리에서는RNNativeSampleModuleSpec
으로 설정했다면,AppSpecs
를RNNativeSampleModuleSpec
으로 모두 바꾼다.
이제 모든 필수 코드를 앱에서 분리해 별도의 라이브러리로 이동했다.
라이브러리 테스트하기
create-react-native-library
는 라이브러리와 잘 동작하도록 미리 구성된 유용한 예제 애플리케이션을 제공한다. 이는 라이브러리를 테스트하기에 매우 적합한 방법이다.
example
폴더를 살펴보면, react-native-community/template
에서 생성할 수 있는 새로운 React Native 애플리케이션과 동일한 구조를 확인할 수 있다.
라이브러리를 테스트하려면 다음 단계를 따르면 된다:
example
폴더로 이동한다.yarn install
을 실행해 모든 의존성을 설치한다.- iOS만 해당되며, CocoaPods를 설치해야 한다:
cd ios && pod install
. example
폴더에서yarn android
를 실행해 Android를 빌드하고 실행한다.example
폴더에서yarn ios
를 실행해 iOS를 빌드하고 실행한다.
로컬 모듈로 라이브러리 사용하기
NPM에 게시하지 않고 애플리케이션에서 로컬 모듈로 라이브러리를 재사용하고 싶은 경우가 있다. 이 경우, 라이브러리가 애플리케이션과 같은 레벨에 위치하는 구조가 될 수 있다.
Development
├── App
└── Library
create-react-native-library
로 만든 라이브러리를 이런 상황에서도 사용할 수 있다.
App
폴더로 이동한 후yarn add ../Library
를 실행해 라이브러리를 추가한다.- iOS의 경우,
App/ios
폴더로 이동해bundle exec pod install
을 실행해 의존성을 설치한다. App.tsx
코드를 업데이트해 라이브러리의 코드를 임포트한다. 예를 들어:
import NativeSampleModule from '../Library/src/index';
이 상태에서 앱을 실행하면 Metro가 앱에 제공해야 할 JS 파일을 찾지 못한다. Metro가 App
폴더에서 실행되기 때문에 Library
폴더에 있는 JS 파일에 접근할 수 없기 때문이다. 이 문제를 해결하기 위해 metro.config.js
파일을 다음과 같이 업데이트한다.
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에 모든 것을 배포하기 위한 설정이 이미 준비되어 있다.
- 모듈에서 의존성을 설치한다:
yarn install
- 라이브러리를 빌드한다:
yarn prepare
- 배포한다:
yarn release
잠시 후 NPM에서 라이브러리를 찾을 수 있다. 이를 확인하려면 다음 명령어를 실행한다:
npm view <package.name>
여기서 package.name
은 라이브러리 초기화 시 package.json
파일에 설정한 name
이다.
이제 애플리케이션에서 라이브러리를 설치할 수 있다:
yarn add <package.name>
iOS의 경우, 네이티브 코드가 포함된 새 모듈을 설치할 때마다 CocoaPods를 다시 설치해야 한다. bundle exec pod install
(권장) 또는 Ruby의 Bundler를 사용하지 않는 경우 pod install
(권장하지 않음)을 실행한다.
축하한다! 첫 번째 React Native 라이브러리를 성공적으로 배포했다.