
제가 만들 Pointer 프로젝트는 수학 문제와 다양한 해설을 통해 수험생에게 진단과 처방을 제공하는 서비스입니다.
이 프로젝트는 크게 두 영역으로 나뉩니다.
관리자 페이지사용자 페이지사용자 페이지의 SEO가 중요하므로 Next.js를 도입하기로 했습니다.
기획 측에서는 사용자들이 사용하는 페이지와 관리자 페이지가 명확히 분리되도록,
두 페이지에 서로 다른 도메인을 적용하길 원했습니다.
페이지별로 다른 도메인을 적용하기 위해선 다음과 같은 방법들이 있었습니다.
가장 먼저 떠오른 방법은 두 페이지를 서로 다른 Git 레포지토리로 완전히 분리하는 것이었습니다. 구조적으로 단순하고 명확하지만, 다음과 같은 문제점이 있었습니다.
결국 1개의 서비스이기 때문에 공통적인 부분이 많은데, 이를 효율적으로 관리할 수 없게되는 문제가 있습니다.
EC2 등으로 배포한다면 Nginx에 리버스 프록시 설정을 통해 도메인에 따라 각각 다른 페이지로 라우팅할 수 있습니다.
하지만 Pointer 프로젝트는 Vercel로 배포하고 있기 때문에, 리버스 프록시 설정은 현실적으로 어려운 상태였습니다.
Next.js의 Middleware 기능을 활용하면 req.headers.host를 기준으로 도메인에 따른 라우팅 분기가 가능합니다.
하지만 이 방법은 아래와 같은 문제가 있었습니다.
이러한 이유들로, 관리자 사용자 페이지를 다른 프로젝트로 분리해서 개발하기로 했습니다.
그리고 어차피 다른 프로젝트로 만들거라면, SEO가 필요없는 관리자 페이지는 더 익숙한 React를 사용하기로 하였습니다.
하지만 이렇게 프로젝트가 물리적으로 나누어졌지만, 몇가지 문제가 있었습니다.
이러한 상황을 종합적으로 고려해, 두 프로젝트를 모노레포(monorepo)로 구성하기로 하였습니다.
- API 클라이언트, UI 등 공유할 수 있는 코드는 공유
- 다른 프로젝트이므로 각각 다른 도메인 연결 가능
- 배포는 앱 단위로 독립적으로 관리
모노레포 구조는 서로 다른 앱의 독립성을 보장하면서도,
공통 코드의 중복 없이 효율적으로 관리할 수 있는 구조라고 판단했습니다.
프로젝트는 Vercel로 배포할 계획이었기 때문에, Vercel에서 공식적으로 지원하고 있는 Turborepo를 도입하면 모노레포 구성부터 배포까지의 흐름을 간편하게 관리할 수 있을 것이라 판단했습니다.
Turborepo는 Vercel에 최적화된 모노레포 관리 도구로
- 앱별로 독립적인 빌드 및 배포가 가능하고,
- 캐싱을 통한 빠른 빌드 성능,
- 공통 패키지 관리의 효율성 등
모노레포의 빌드, 테스트, 배포 작업을 효율적으로 할 수 있게 해줍니다.
또한, Vercel과의 통합도 지원하므로 CI/CD 설정도 간단하게 구성할 수 있었습니다.
Turborepo의 공식문서를 참고하며 모노레포 구조를 생성하고,
admin (React) service (Next) 두개의 프로젝트를 만들어주었습니다.

Vercel에서 새로운 프로젝트 추가해주겠습니다.

Turborepo로 생성한 것을 인식하고 Trubo 라는 라벨도 붙여줍니다.
모노레포라고 해서 통째로 배포할 수 있는 것은 아니고, 프로젝트 별로 배포를 해줘야합니다.

Root Directory를 선택하는 부분에서 어떤 프로젝트를 배포할 것인지 선택 해줍니다.
/apps 안에 admin(관리자) service(사용자) 가 있는 것을 볼 수 있고, Vite, Next 프로젝트라는 것도 알려줍니다.
이 과정을 2번 반복하며 각 프로젝트를 배포해주면 됩니다.

Vercel은 기본적으로 연결된 프로젝트에 변경이 발생하면 자동으로 재배포를 진행합니다.
하지만 모노레포에서는 여러개의 프로젝트가 하나의 브랜치에 존재하기 때문에,
한쪽만 수정해도 모든 프로젝트가 함께 재배포되는 비효율적인 작업이 발생할 수 있습니다.
이를 방지하기 위해, Vercel은 “변경되지 않은 프로젝트는 빌드를 건너뛰는 기능”을 제공합니다.
Vercel은 아래 조건 중 하나라도 해당되면 프로젝트가 변경된 것으로 간주합니다
- 해당 프로젝트의 소스 코드가 변경된 경우
- 해당 프로젝트가 의존하고 있는 내부 패키지(예: 공통 라이브러리 등)에 변경이 생긴 경우
- 패키지 매니저의 lockfile이 변경되었고, 그 영향이 해당 프로젝트의 의존성에 반영되는 경우
프로젝트 -> Settings -> Build and Deployment 에 들어가면

Root Directory 영역에 Skip deployments ~ 라고 되어있는 토글 버튼이 있습니다.
이 옵션을 활성화하면 해당 프로젝트에 영향이 없는 커밋일 경우 배포가 자동으로 건너뛰어집니다.
처음에 이 간단한 설정을 못찾아서 별의별 짓을 다해봤습니다...
모노레포의 공통 패키지에서 수정이 일어날 경우에는 해당 변경을 사용하는 모든 프로젝트가 함께 재배포됩니다.


배포 페이지에서 우측에 Status 필터에서 canceled도 추가해주면 cancel된 배포들도 확인할 수 있습니다.

최근 서비스 페이지만 수정한 작업에서는 관리자 페이지 배포가 일어나지 않은 것을 확인할 수 있습니다.
공식문서에 따르면 이 기능을 이용할 경우 빌드 슬롯을 점유하지 않기 때문에, 빌드 대기 시간도 줄여주는 장점도 있다고 합니다.
기획 측의 요구로 QA 등을 진행할 수 있는 별도의 개발 환경이 필요했고,
API 서버도 이미 prod와 dev로 분리되어 있는 상황이었습니다.
Vercel은 하나의 프로젝트 안에서 브랜치별로 다른 배포 환경(Preview, Production 등)을 구성할 수 있는 기능을 제공합니다.
또한, 각 환경에 맞는 환경 변수 설정과 도메인 연결도 가능하여 실제 운영과 유사한 환경을 쉽게 구성할 수 있습니다.

프로젝트 세팅 -> Environments에 들어가서 Preview에 들어가서

Branch Tracking 옵션을 활성화하면, 지정한 브랜치(ex. develop)로 커밋 시 자동으로 Preview 환경이 배포됩니다.
하단에서는 Preview 환경 전용 커스텀 도메인도 연결할 수 있습니다.

배포 환경별로 서로 다른 환경변수를 설정할 수 있어,
Preview 환경에서는 dev API 서버를,
Production 환경에서는 prod API 서버와 통신하게 설정할 수 있습니다.
이 모든 설정을 마친 뒤에야 알게 되었는데,
브랜치별 Preview 환경 구성은 Vercel의 Pro 요금제 이상에서만 지원되는 기능이었습니다.🥲
결국 어쩔 수 없이 개발 환경에 대해 추가로 프로젝트를 등록해야 했습니다.

😭
이렇게 프로젝트를 분리함으로써 프로젝트의 개수는 많아졌지만, 무료 요금제 내에서도 모노레포의 모든 프로젝트를 운영/개발 환경을 분리하여 배포할 수 있었습니다.
참고자료