개인 블로그 개발 회고: Turborepo + Next.js + Vercel

5년차 프론트엔드 엔지니어가 연말에 시간을 내어 Turborepo, pnpm workspace, Next.js, Vercel을 경험하며 배운 점들

·9 min read
회고Next.jsTurborepoVercelMonorepo

개인 블로그 개발 회고

왜 블로그를 만들었는가

5년간 기술 조직에서 프론트엔드 전담으로 일했지만, 내가 무슨 일을 했고 어떤 생각을 가지고 일하고 있는지 기록하고 싶다는 생각이 들었다.

경력직으로서 포트폴리오의 목적보다는:

  • 내가 한 프로젝트를 얼마나 이해하고 있는지
  • 트러블슈팅 과정에서 어떤 인사이트를 얻었는지
  • 내가 알고 있는 내용과 모르고 있는 내용을 명확하게 구분하기

이런 다양한 목적을 가지고 이 블로그를 시작했다.

이직 준비를 하기 전, NHN에서 있었던 모든 프로젝트에 대한 회고를 진행하고, 기술 튜토리얼과 주요 트러블슈팅 문제를 포스트로 작성할 예정이다.

기술 스택 선택

Next.js + Vercel을 선택한 이유

사실 Gatsby나 Netlify 같은 정적 사이트 생성기로도 충분했다. 하지만 기존 SSG 구조를 잘 알고 있던 나로서는, 이미 정적 사이트 제공만으로는 만족하지 못하는 몸이 되어버렸다.

연말에 시간도 있고, 공부할 겸 Next.js와 Vercel을 선택했다.

Turborepo + pnpm workspace

Monorepo 구성은 원래 꽤 어려운 작업이었다. 하지만 Turborepo의 경우, 모노레포에서 사용하는 내용만 빼고는 전부 내부 패키지에 위임하고 있어서 사용하기 편했다.

처음 사용해봤는데, 그 효과가 아주 좋다.

하루 정도의 러닝커브가 소요되었지만:

  • 의존성 그래프 자동 분석
  • 캐싱을 통한 빌드 속도 향상
  • 패키지 간 의존성 관리 자동화

이런 장점들이 러닝커브를 충분히 상쇄했다.

Tailwind CSS와 AI의 조합

Tailwind는 사실 현업 수준으로는 사용하지 못한다. 왜냐면, 이미 러닝커브를 AI에게 위임했고 크게 배우는 의미도 적어 보이기 때문이다.

하지만 style library와 AI가 결합되었을 때 주는 장점은 너무나도 잘 이해하고 있다.

사람은 같은 화면이어도 개발하는 방식과 구현 방법이 너무나도 다양하다. 이러면:

  • AI가 이해하기 너무 어려워진다
  • 코드만 읽고 화면이 어떻게 생겼는지 역으로 추론하기도 어렵다 (CSS 파일이 분리되어 있다면)

천천히 Tailwind를 사용하면서 리뷰 가능한 수준까지 몸에 익혀둘 생각이다.

구현 과정

npm → pnpm 마이그레이션

pnpm workspace를 사용하기 때문에, 당연히 npm에서 pnpm으로 변경했다.

주요 변경사항:

  • pnpm-workspace.yaml 생성
  • package.jsonworkspaces 필드 제거
  • 로컬 패키지 의존성을 workspace:* 프로토콜로 변경
  • package-lock.json 삭제, pnpm-lock.yaml 생성
1{
2 "packageManager": "pnpm@9.15.4",
3 "dependencies": {
4 "@hyunctrl/core": "workspace:*"
5 }
6}

Storybook 제거 결정

애플리케이션에서는 과감하게 제거했다.

개인 블로그에 Storybook은 오버엔지니어링이다. 팀 협업이나 디자인 시스템이 필요한 것도 아니고, 컴포넌트 문서화도 크게 필요하지 않았다.

UI나 컴포넌트 core 라이브러리에서만 사용할 예정이다.

Storybook 제거 후:

  • 패키지 수 감소: 749개 → 585개 (약 22% 감소)
  • 빌드 속도 개선
  • 관리 포인트 감소

Vercel Monorepo 배포 트러블슈팅

가장 많은 시행착오를 겪었던 부분이다.

1. @hyunctrl/core 패키지를 찾을 수 없는 문제

문제: Vercel Build Command가 pnpm run build였다.

이렇게 하면 Vercel이 apps/main/package.json의 build 스크립트를 직접 실행해버린다. Turborepo의 의존성 그래프를 우회하기 때문에 @hyunctrl/core 패키지가 빌드되지 않은 상태로 main 앱을 빌드하려다 에러가 발생한다.

1Module not found: Can't resolve '@hyunctrl/core/components'

해결: Vercel Build Command를 변경했다.

1cd ../.. && pnpm run build:main

이렇게 하면:

  1. Turborepo가 의존성 그래프 분석
  2. @hyunctrl/core 패키지를 먼저 빌드
  3. 그다음 main 앱 빌드

Monorepo에서 Vercel 배포 시 핵심: 루트에서 Turborepo 명령어를 실행해야 한다.

2. tailwindcss peerDependency 문제

문제: core 패키지에 tailwindcss를 peerDependency로 추가했는데, pnpm install을 안 했다.

1ERR_PNPM_OUTDATED_LOCKFILE Cannot install with "frozen-lockfile"
2because pnpm-lock.yaml is not up to date

해결: pnpm install 실행 후 lockfile 커밋.

package.json을 수정하면 항상 pnpm install을 실행해야 한다.

배운 점

1. Turborepo는 정말 편하다

Monorepo 구성이 이렇게 쉬울 줄 몰랐다.

  • 의존성 그래프 자동 분석: dependsOn만 설정하면 끝
  • 캐싱: 변경되지 않은 패키지는 재빌드하지 않음
  • 병렬 빌드: 독립적인 패키지는 동시에 빌드

2. Vercel Monorepo 배포는 명확한 이해가 필요하다

Build Command는 반드시 루트에서 Turborepo를 호출해야 한다.

1# ✅ 올바른 방법
2cd ../.. && pnpm run build:blog
3
4# ❌ 잘못된 방법 (의존성 그래프 무시)
5pnpm run build

3. Tailwind + AI는 강력하다

CSS Modules이나 Sass를 사용하면:

  • AI가 스타일을 이해하기 어렵다
  • 코드만 보고 UI를 추론하기 어렵다

Tailwind는:

  • 클래스 이름만 보면 스타일을 알 수 있다
  • AI가 코드를 이해하고 수정하기 쉽다
  • 개발 속도가 빨라진다

4. 오버엔지니어링은 지양한다

개인 블로그에 Storybook은 필요 없었다.

필요한 기능만 구현하는 것이 생산성과 유지보수에 훨씬 좋다.

마치며

이번 프로젝트를 통해 써보고 싶었던 Next.js와 Vercel, 그리고 기술 블로그 운영을 시작했다.

각각의 기술에 대한 사용법과 트러블슈팅, SEO를 적용하는 방법 등은 하나씩 글로 작성해볼 예정이다.

블로그의 대부분의 글은 AI를 활용해서 정리할 생각이다. 내 시간은 소중하므로. 다만, 그 내용이 잘못되지 않도록 항상 주의할 것이다.

AI가 난무하는 시대에, AI를 활용해서 양질의 콘텐츠를 만들고, 같은 방향으로 공부하며 성장하는 사람들과 함께하고 싶다.