Railway가 프론트엔드를 Next.js에서 벗어난 이야기 — 빌드 시간 10분 → 2분 미만
We moved Railway's frontend off Next.js. Builds went from 10+ mins to under 2
TL;DR Highlight
Railway가 프로덕션 프론트엔드를 Next.js에서 Vite + TanStack Start로 마이그레이션해 빌드 시간을 10분대에서 2분 미만으로 줄인 실전 경험기다. 하루에 여러 번 배포하는 팀이라면 빌드 시간이 개발 속도에 얼마나 직접적인 영향을 주는지 실감할 수 있다.
Who Should Read
Next.js로 클라이언트 중심의 대시보드나 SPA를 운영 중인데 빌드 시간이 늘어나거나 서버 우선 패러다임과 맞지 않는다고 느끼는 프론트엔드 개발자. 특히 하루에 여러 번 배포하는 팀에서 빌드 병목을 해소하고 싶은 경우.
Core Mechanics
- Railway의 프로덕션 프론트엔드(대시보드, 캔버스, railway.com 전체)가 Next.js에서 Vite + TanStack Router로 완전 전환됐고, 단 두 개의 PR로 다운타임 없이 마이그레이션을 완료했다.
- 기존 Next.js 빌드는 10분 이상 걸렸는데 그 중 6분이 Next.js 자체 처리 시간이었고, 특히 'finalizing page optimization' 단계에서 절반 가까이 막혀 있었다. 하루 수차례 배포하는 팀에게 이건 단순한 불편함이 아니라 이터레이션마다 붙는 무거운 세금이었다.
- Railway 앱은 대시보드가 리치한 상태 기반 인터페이스이고, 캔버스는 실시간, WebSocket이 전반적으로 사용되는 구조라서 Next.js의 서버 우선(server-first) 설계 방향과 근본적으로 맞지 않았다.
- Pages Router를 유지하면서 레이아웃 공유 등을 처리하려다 보니 프레임워크 위에 자체 추상화를 덧붙이는 상황이 됐고, 모든 레이아웃 패턴이 프레임워크 기능이 아닌 임시방편 워크어라운드였다. App Router로 전환하면 일부 문제는 해결되지만 서버 우선 패러다임을 강요받게 돼 그쪽도 맞지 않았다.
- TanStack Start + Vite를 선택한 이유는 크게 네 가지다: 라우트 파라미터와 검색 파라미터가 자동 추론되는 타입 안전 라우팅, 레이아웃을 일급 개념으로 지원하는 Pathless Layout Route, 즉각적인 HMR로 피드백 루프가 사실상 사라지는 빠른 개발 루프, 마케팅 페이지 등 필요한 곳에만 선택적으로 SSR을 적용하는 유연성.
- 마이그레이션은 두 단계로 나뉘었다. PR 1에서는 프레임워크는 건드리지 않고 next/image, next/head, next/router 등 Next.js 의존성만 네이티브 브라우저 API 또는 프레임워크 무관한 대안으로 교체했다. PR 2에서는 200개 이상의 라우트를 실제로 마이그레이션했다.
- 서버 레이어로 Nitro를 추가하고 next.config.js를 Nitro 설정으로 교체했다. 리다이렉트 500개 이상, 보안 헤더, 캐싱 규칙을 한 곳에 통합했다. 또한 Next.js가 폴리필 처리하던 Node.js API(Buffer, url.parse 등)를 브라우저 네이티브 대안으로 교체해 코드가 더 깔끔해지는 부수 효과도 얻었다.
- 트레이드오프도 있다. next/image의 내장 이미지 최적화는 Fastly 엣지 이미지 최적화로 대체했고, next-seo나 next-sitemap 같은 에코시스템 도구들은 소규모 인하우스 구현으로 교체했다. TanStack Start 자체가 아직 새로운 프레임워크라 거친 부분이 있을 수 있다는 점도 감수했다.
Evidence
- 비슷한 마이그레이션을 경험한 팀의 사례 공유가 있었다. Next.js 랜딩 페이지와 TanStack Router SPA를 하나의 Vite + TanStack Start 앱으로 통합했더니 빌드 시간이 12분에서 2분 미만으로 줄었고, 클라이언트 중심의 실시간 상태 앱에서 Next.js의 서버 우선 가정과 싸우는 게 더 이상 의미 없었다는 의견이었다.
- Next.js 빌드가 Railway 플랫폼에서 특히 느리다는 지적이 있었다. Railway는 컨테이너 기반이라 Vercel에서 2분짜리 빌드가 Railway에서는 12분씩 걸리는 반면, VPS 직접 배포는 20초 수준이라는 경험담이 공유됐다. 이는 Railway의 마이그레이션 결정에 맥락을 더해준다.
- LLM이 Next.js와 Vercel 에코시스템에 매우 익숙하고 Vercel이 LLM 도구 통합에 공격적으로 투자하고 있다는 점에서, AI 코딩 도구를 사용하는 개발자들이 Next.js/Vercel 쪽으로 더 강하게 쏠리게 될 것이라는 우려가 제기됐다.
- 2분도 여전히 너무 길다는 비판적 시각도 있었다. '2분짜리 빌드도 말이 안 된다'는 댓글과 '10분이 정상이었다는 게 놀랍다. 얼마나 퇴보한 건가'라는 냉소적 반응이 있었다.
- 원문에서 어떤 Next.js 버전을 쓰고 있었는지, Turbopack은 사용했는지 언급하지 않았다는 지적이 있었다. Turbopack을 켰다면 빌드 시간이 달라질 수 있기 때문에 비교의 기준점이 명확하지 않다는 점이 지적됐다.
How to Apply
- 현재 Next.js 앱이 클라이언트 중심(SPA, 대시보드, 실시간 기능 위주)인데 빌드가 5분 이상 걸린다면, PR을 두 단계로 나눠 마이그레이션하는 방법을 참고할 수 있다. 첫 번째 PR에서 next/image, next/head, next/router 등 Next.js 전용 API만 프레임워크 무관한 대안으로 교체하고, 두 번째 PR에서 실제 프레임워크를 교체하면 리스크를 줄일 수 있다.
- 500개 이상의 리다이렉트와 보안 헤더, 캐싱 규칙을 next.config.js에서 관리하고 있다면, Nitro 서버 레이어로 이전하면서 이를 한 파일에 통합할 수 있다. Railway 사례처럼 설정 파일 단일화와 코드 정리를 함께 가져갈 수 있다.
- Next.js에서 레이아웃을 Pages Router 위에 자체 추상화로 구현하고 있는 팀이라면, TanStack Router의 Pathless Layout Route가 그 워크어라운드를 대체할 수 있다. 파일 시스템 기반 라우트 생성과 함께 타입 안전 라우팅도 자동으로 얻을 수 있다.
- next/image 없이 이미지 최적화가 필요한 경우, Railway처럼 Fastly 같은 CDN의 엣지 이미지 최적화를 사용하거나 Cloudflare Image Resizing 등 외부 서비스를 활용하면 프레임워크 의존 없이 동일한 효과를 낼 수 있다.
Terminology
TanStack StartTanStack Router(타입 안전 클라이언트 라우팅 라이브러리)를 기반으로 만든 풀스택 프레임워크. Vite를 빌드 도구로 쓰고, 클라이언트 우선 방식을 지향한다.
Nitro서버리스, 엣지, Node.js 등 다양한 환경에 배포 가능한 범용 서버 엔진. Next.js의 서버 기능을 대체하거나 독립적으로 사용할 수 있다.
HMRHot Module Replacement의 약자. 코드를 수정할 때 브라우저 전체를 새로 고침하지 않고 바뀐 모듈만 실시간으로 교체해주는 기능. 개발 중 피드백 속도를 크게 높인다.
Pathless Layout RouteURL 경로에 영향을 주지 않으면서 레이아웃(헤더, 사이드바 등)을 여러 라우트에 공유할 수 있는 TanStack Router의 기능. 기존 Pages Router에서 레이아웃을 억지로 구현하던 워크어라운드를 대체한다.
Pages RouterNext.js의 구형 라우팅 방식. pages/ 폴더 안의 파일이 그대로 URL이 되는 구조. 레이아웃 공유 등에서 제약이 있어 커스텀 추상화가 필요한 경우가 많다.
Polyfill최신 브라우저 API나 Node.js API를 지원하지 않는 환경에서도 동작하도록 동일한 기능을 흉내 내는 코드. Next.js가 제공하던 Buffer, url.parse 등의 Node.js 폴리필을 제거하고 브라우저 네이티브 API로 교체한 것이 이 사례다.