1. 개요
나는 사이드 프로젝트를 좋아한다.
개인적으로 느낀 사이드프로젝트의 큰 장점은 2가지이다.
- 원하는 기술 스택을 도입하고 사용해볼 수 있다.
- 비즈니스적 관점, 사용자에게 닿을 수 있는 서비스에 대해 고민할 수 있다.
그래서 사이드 프로젝트를 자주 하려고 하는 편인데, 사이드 프로젝트를 하다보니 항상 발생하는 문제가 있었다.
기본적인 컴포넌트(버튼, Textinput등)를 만드는 것에 시간 소요가 너무 크게 발생하고, 이것이 병목으로 작용하는 것이다.
이런 문제는 크게 2가지 해결 방법이 있다.
- MUI같은 오픈소스 라이브러리를 사용한다.
- 자체적인 공통 컴포넌트 라이브러리를 구축한다.
나는 개인적으로 오픈소스 라이브러리는 내 입맛에 맞게, 내가 원하는대로 사용하는것이 편치 않아 선호하지 않는다. 그렇기에 공통 컴포넌트 라이브러리를 구축을 하기로 결정했다.
나는 Next.js와 React Native를 주로 사용해 웹/앱 서비스를 개발한다.
그리고 React Native의 경우, Expo보다는 Cli환경을 조금 더 선호한다.
Turborepo에서 Expo를 이용한 React Native환경 구축은 있는것 같은데, Cli환경을 구축하는 방법에 관한 내용은 잘 보이지 않기에, React Native cli에서도 사용할 수 있는 Monorepo환경을 구축하는 방법을 정리해 보았다.
2. Monorepo 환경 알아보기
Monorepo의 기본적인 아이디어는 다음과 같다.
- 공통 컴포넌트를 관리할 프로젝트를 구축한다.
- 이 프로젝트에 공통으로 사용할 컴포넌트들, 함수 등을 만들어둔다.
- 이 프로젝트의 하위로 프로젝트(React, React Native 등)을 만들고, 공통 컴포넌트를 import해서 사용한다.
- 특정 프로젝트에서만 사용할 컴포넌트는 해당 프로젝트의 하위에 만든다.

이렇게 공통 컴포넌트, 함수를 만들고 이를 import해서 사용하면 재사용성이 매우 높아지고, 컴포넌트의 이슈가 있을 때 해당 컴포넌트파일만 수정하면 모든 프로젝트에 수정 내용이 반영되는 장점이 있다.
3. Turborepo환경 구축하기
Turborepo는 vercel이 인수한곳으로, Monorepo를 위한 빌드 시스템이다.
https://turborepo.com/
Turborepo
Turborepo is a build system optimized for JavaScript and TypeScript, written in Rust.
turborepo.com
Turborepo프로젝트는 아래 명령어로 생성할 수 있다.
npx create-turbo@latest
이후 프로젝트명과 패키지 관리자를 선택하면 된다.
생성된 프로젝트를 열어보면 아래와 같은 파일구조를 확인할 수 있다.

- apps : 이 폴더에서 프로젝트를 생성하고, 생성된 프로젝트에서 공통 컴포넌트를 사용한다.
- packages/ui : 이 폴더에서 공통 컴포넌트를 개발한다.
4. React Native Cli 환경 구축하기
1) 공통 컴포넌트
React Native에서 사용할 컴포넌트를 만들기 위해선 View, Text같은 React Native컴포넌트가 필요하다.
packages/ui폴더로 이동해서 React Native를 설치한다.
yarn add react-native
2) React Native Cli 프로젝트 환경설정
apps폴더로 이동한 뒤 React Native프로젝트를 생성한다.
npx @react-native-community/cli@latest init AwesomeProject
이후 metro.config.js파일을 아래와 같이 수정한다.
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 = mergeConfig(getDefaultConfig(__dirname), config);
android폴더의 settings.gradle파일을 아래와 같이 수정한다.
pluginManagement { includeBuild("../../../../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
rootProject.name = 'AwesomeProject'
include ':app'
includeBuild('../../../../node_modules/@react-native/gradle-plugin')
android/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")
...
XCode, Android Studio에서 프로젝트를 실행했을 때 정상적으로 빌드되면 성공이다!


5. 공통 컴포넌트 사용하기
여기까지 작업이 완료되면 기본적인 환경설정은 완료됐다.
packages/ui폴더 하위에 공통 컴포넌트를 만들고, 아래처럼 import해서 사용하면 된다.
import { Button } from "@repo/ui/Button";
const App = () => {
return (
...
<Button/>
...'프론트엔드' 카테고리의 다른 글
| [ Vercel ] Type error: Type '{ params: string }' does not satisfy the constraint 'PageProps'. (1) | 2025.06.19 |
|---|---|
| [React Native] React Native 0.79 훑어보기 (0) | 2025.04.14 |
| [React Native] React Native 0.78 주요 업데이트 2가지 (0) | 2025.03.22 |
| [Frontend] Javascript없이 Drawer구현하기 (0) | 2025.02.17 |
| [React Native] numeric타입 키보드에서 onSubmitEditing함수가 동작하지 않음 (1) | 2025.01.15 |