04. 공공API를 활용한 웹 앱 만들어보기 (feat. RN+Next.js 모노레포 통합하기: 빌드 지옥...)

jhson·2025년 4월 25일

ReactNative

목록 보기
10/10

모노레포 도입.. 빌드 지옥의 서막

모노레포를 도입한 이유는 단순했다.
1. 웹은 Next.js로, 모바일은 React-Native로 만들기
2. 공통된 API 요청으로 UI 컴포넌트를 재사용해보고 싶다.
3. 배포 스크립트, ESLint, TypeScript의 설정 등을 한 번에 관리하고 싶다.
4. 현업에서 모노레포를 사용하는 경우도 있기 때문에 경험해보고 싶다.

그래서 아래와 같은 구조로 프로젝트를 세팅했다.

CheckBiz/
|----- apps/
|   	|----- web/       # Next.js
|   	|----- mobile/    # React Native
|----- packages/
    	|----- ui/        # 공유 UI 컴포넌트
    	|----- api/       # 공통 API 로직

첫 번째 충돌_Gradle plugin not found

나는 yarn workspace를 사용했고
이전에 yarn을 사용하면서 경험해보지 못한 문제를 경험하기 시작했다.

설치, 삭제... 그리고 설치, 삭제의 무한 굴레...
공식문서를 찾아보았다.
왜 자꾸 안되는걸까?

React Native 0.79.1은 새로운 Gradle plugin 방식 (com.facebook.react)을 사용한다.
공식 문서에 따르면 다음처럼 설정하라고 한다

settings.gradle.kts

pluginManagement {
includeBuild("../node_modules/@react-native/gradle-plugin")
}

하지만 나는 yarn workspace를 사용하고 있었고
아래와 같은 문제가 계속 발생했다.

node_modules/@react-native/gradle-plugin => 이게 계속루트에 설치됨
apps/mobile/node_modules/@react-native/gradle-plugin => 이건 설치를 계속 해도 계속 없음

Gradle은 includeBuild("상대경로")로 명시한 경로가 실제 존재하지 않으면 바로 실패한다.
즉, apps/mobile 기준의 상대경로에 해당 플러그인이 정확히 설치되어 있어야만 작동한다.
루트에 설치된 플러그인은 Gradle이 사용되어야하는 mobile에는 아예 설치가 되어있지 않고 그로 인해서 애초에 경로가 맞지 않기 때문에 무조건 실패한다는 의미다.

😵 여기서 헤맨 포인트

package.json의 workspace 설정이 정확히 어떻게 작동하는지 모른 상태에서
apps/mobile이 아닌 루트에서 자꾸 @react-native/gradle-plugin을 설치했다.

"workspaces": [
"apps/web",
"apps/mobile",
"packages/*"
]

이렇게 되어 있는 상태에서 루트에서 yarn add를 실행하면 해당 패키지가 workspace 내 apps/mobile로 연결되지 않고 루트에 깔리는 문제가 발생한다.
루트에서 yarn이 설치나 제거 시 이 경로 내의 디렉토리만 workspace로 인식해서 관리하겠다는 의미다.

하지만 중요한 점은 다음과 같다

  • 루트에서 yarn add 또는 yarn remove를 실행하면 해당 패키지는 루트에 설치된다.
  • apps/mobile에 종속된 개발 의존성(devDependencies)을 설치하려면 해당 디렉토리로 들어가서 명시적으로 실행해야 한다.

즉, 루트에서 설치한 것은 apps/mobile 하위에서는 상대 경로 기준에 맞지 않기 때문에 Gradle이 찾지 못한다.

따라서 루트의 package.json에서 workspace 내용들을 지우고 원하는 경로에 gradle-plugin을 설치한 다음에 다시 package.json에 workspace를 기존처럼 복구했다.

해결

루트에서 제거

cd /
yarn remove @react-native/gradle-plugin -W

apps/mobile로 이동해서 설치

cd apps/mobile
yarn add -D @react-native/gradle-plugin

이후 다시 gradlew clean 실행 → 플러그인 인식 성공

workspace가 뭘까?

workspace 설정 목적

여러 패키지 디렉토리를 하나의 프로젝트로 묶고, 의존성을 효율적으로 관리하기 위해서

왜 workspace 사용할까?

  • 루트에서 의존성 통합 관리
    예) react, typescript, eslint 등 공통 패키지를 루트에 한 번만 설치하면 하위 패키지들에서 전부 쓸 수 있음
  • 내부 패키지 간 의존성 자동 연결(symlink)
    예) packages/api에서 만든 모듈을 apps/web과 apps/mobile 양쪽에서 import 할 수 있음
    => yarn이 symlink로 연결함
  • 일괄 명령어 실행
    yarn workspaces run build 하면 모든 하위 앱/패키지에서 build 실행됨

그런데 왜 yarn add 했을 때 루트에 설치되었을까?

workspaces는 기본적으로 루트가 패키지를 컨트롤하는 관리자이기 때문.
yarn add를 루트에서 실행하면 루트가 그 패키지를 자기 자신의 의존성으로 등록하는 것이고
apps/mobile 디렉토리에서 yarn add를 실행해야 그걸 모바일 프로젝트 전용으로 인식함

즉,

workspaces는 공유/재사용/관리의 범위를 지정하는 것이지 자동으로 하위 프로젝트에 설치해주는 건 아님

두 번째 충돌_com.android.tools.build:gradle을 못 찾는다?

Could not find com.android.tools.build:gradle:8.8.2

Gradle은 google() 레포에서만 Android 플러그인을 찾는다.
하지만 나는 settings.gradle.kts에 이걸 안 넣고 있었던 것!

해결

pluginManagement {
repositories {
google() //이걸 빼먹었음!
mavenCentral()
}
includeBuild("../node_modules/@react-native/gradle-plugin")
}

마치며

모노레포에서 React Native와 Next.js를 함께 쓰는 건 분명 어렵다.
특히 Gradle과 Android 설정은 "당연하게 되겠지"라고 생각하면 무조건 막힌다.

하지만 이번 경험으로 확실히 얻은 점이 있다!

  • Gradle의 includeBuild 원리
  • yarn workspace의 패키지 경로 관리 방식
  • React Native 플러그인 구조와 버전 변화 대응

거의 일주일간 설치-삭제-빌드 반복하면서... 아 난 개발자가 아닌가 보다, 모노레포 포기하고 그냥 앱으로만 만들까? 이런 오만 생각에 사로잡혔다...
앞으로 개발자의 길을 가면서 온갖 문제들에 봉착하게 될텐데 이런건 사소한 문제지 하는 생각도 들었던 기간이었다.
그럼에도 불구하고 깨달을 수 있었던 건 이게 바로 개발의 묘미지!
막혔을 때 이유를 파고들고 그동안의 프로젝트에서는 막연하게 실행이 되니까 원리 이해없이 지나갔던 문제들도 이번 기회를 통해 이해할 수 있게 되었고 고칠 수 있게 된 점이 있어서 기쁘다.

다음번에는 이 구조 위에 테스트, 배포 파이프라인, CI/CD까지 이어서 작성할 계획이다.

나처럼 이런 문제에 부딪힌 사람들, 앱+웹 같이 운영하고 싶은 사람들에게 도움이 되었으면 함!

profile
게임회사 주니어 개발pm에서 프론트엔드 개발자로 전향하는 과정

0개의 댓글