본문으로 건너뛰기

Usecase: Vite에서 Next.js 16으로 병렬 마이그레이션

이것은 실제 usecase로 Claude Code + Superpowers를 사용하여 수행되었습니다. 아래 내용은 브레인스토밍부터 완료까지의 과정을 설명하며, 마이그레이션 후 UI 재디자인 부분도 포함합니다.

React 애플리케이션을 Vite에서 Next.js 16으로 마이그레이션하는 것은 하나의 agent가 순차적으로 할 일이 아닙니다. Superpowers를 사용하면 전략을 브레인스토밍하고, 상세한 plan을 작성하고, 여러 agent를 병렬로 dispatch할 수 있습니다 — 각 agent가 자체 파일을 소유하므로 충돌이 없습니다.


배경

프로젝트는 React 19 + Vite 7로 작성된 로그인 기능이 있는 Todo App입니다. 현재 스택은 다음과 같습니다:

항목세부사항
FrameworkReact 19 + Vite 7 (SPA, 라우팅 없음)
언어TypeScript 5.9 (strict mode)
UITailwind CSS 4 + shadcn/ui
StateContext API + useReducer
Backend없음 — 100% localStorage
AuthClient-side SHA-256 hash, localStorage에 저장
FeaturesTodo CRUD, Drag-drop, Filters, Dark mode, Auth
TestingVitest + React Testing Library

목표: 전체를 Next.js 16 App Router로 마이그레이션하되, 기존 로직 (localStorage, client-side auth, UI 라이브러리)을 유지합니다. 팀에는 병렬로 작업할 수 있는 3-4개의 agent가 있습니다.

중요 요구사항:

  • 프레임워크만 변경, 로직은 변경하지 않음
  • 마이그레이션 후에도 기존 테스트가 모두 통과해야 함
  • 여러 agent가 서로 다른 파일에서 동시에 작업 가능

배울 수 있는 것

이 usecase를 읽고 나면, 실제 리팩토링/마이그레이션 상황에 Superpowers 기법을 적용하는 방법을 알게 됩니다:

  1. Brainstorming 마이그레이션 전략 — 올바른 질문을 하고, 접근 방식을 제안하고, 최적의 방향을 선택
  2. Plan 작성 병렬 작업을 위해 — 명확한 의존성과 함께 phase별로 task 분할
  3. Parallel Subagents 동시 실행 — 3개 agent가 별도 파일에서 동시 작업
  4. Two-Stage Code Review 품질 보장 — 각 phase 후 자동 spec 리뷰
  5. Verification 결과 검증 — 계속하기 전에 빌드 + 테스트가 통과해야 함

단계별 실습

0단계: 마이그레이션 전략 브레인스토밍

plan을 작성하기 전에, 전략을 결정하기 위한 브레인스토밍이 필요합니다. AI와 채팅을 열고 다음과 같이 말합니다:

"이 프로젝트 전체를 NextJS 16으로 리팩토링해야 합니다. 이것은 계정 로그인이 있는 웹 todo 프로젝트입니다. 팀에 3-4개의 agent가 병렬로 작업할 수 있습니다. 시작하기 전에 리팩토링 전략을 브레인스토밍합시다."

AI가 브레인스토밍 모드에 진입하고 (superpowers:brainstorming skill 사용), 코드베이스를 탐색한 후 하나씩 질문을 시작합니다:

AI: "이 리팩토링의 범위는 어디까지인가요?"

  • A) Full-stack — 실제 데이터베이스, API routes, 서버 사이드 인증 추가
  • B) Hybrid — 렌더링을 위한 Server Components + App Router, 하지만 localStorage 유지
  • C) Framework migration only — Vite에서 Next.js 16으로 전환, 로직은 유지

선택: C) Framework migration only — 프로젝트 구조와 라우팅에 집중.

AI: "라우팅에 대해, URL 구조를 어떻게 하시겠습니까?"

  • A) Minimal routing — 2개 route만: / (todo app)과 /login (auth page)
  • B) Structured routing — 여러 route: /login, /register, /todos, /todos/[id]

선택: A) Minimal routing — 간단하고, 현재와 가장 유사.

AI: "현재 UI 라이브러리를 유지할까요, 변경할까요?"

선택: 전부 유지 — shadcn/ui, @dnd-kit, sonner, date-fns, lucide-react.

AI: "Testing에 어떤 프레임워크를 사용할까요?"

  • A) Vitest 유지 — Next.js 16이 네이티브로 지원
  • B) Jest로 전환

선택: A) Vitest 유지.

AI: "배포에 대해, 특정 타겟이 있나요?"

  • A) Vercel — Next.js에 가장 최적화, 설정 불필요
  • B) Self-hosted / Docker
  • C) 아직 관심 없음 — 나중에 결정, 지금은 마이그레이션에 집중

선택: C) 아직 관심 없음 — 마이그레이션에 먼저 집중.

충분한 정보를 수집한 후, AI가 3가지 접근 방식을 제시합니다:

## Approach A: 새로 스캐폴딩 + 부분별 마이그레이션 (권장)
새 Next.js 16 프로젝트를 만들고, 각 부분을 복사/적응.
- 장점: 깨끗한 구조, agent 병렬 분배 용이, 프로젝트가 처음부터 실행 가능
- 단점: 설정 재구성 필요 (shadcn, tailwind)

## Approach B: In-place migration
현재 프로젝트에서 바로 전환 — Vite를 Next.js로 교체.
- 장점: git history 유지
- 단점: 충돌 가능성, 중간에 프로젝트 실행 불가, 병렬 task 분배 어려움

## Approach C: Codemods + 자동화
@next/codemod와 스크립트를 사용하여 자동 전환.
- 장점: 기본적인 부분은 빠름
- 단점: Vite → Next.js에 대한 codemod가 없고, 소규모 프로젝트에 과도함

## 권장
Approach A. 프로젝트가 작고 (~15개 컴포넌트), 새로 스캐폴딩하는 것이 in-place 마이그레이션보다 빠릅니다.
3-4개 agent에 병렬 분배가 용이합니다.

Approach A를 선택합니다. AI가 추가로 질문합니다: "다이어그램과 목업을 브라우저에 표시할까요?" → 동의합니다. AI가 visual companion (로컬 서버)을 시작하여 아키텍처 다이어그램을 브라우저에서 직접 렌더링합니다.

AI가 5개 섹션의 상세 설계를 계속 제시합니다 (브라우저에 표시):

  1. Project Structure — App Router를 사용한 새 디렉토리 구조 (app/, components/, hooks/, lib/, types/, contexts/)
  2. Component Mapping — Server vs Client Components 분류. 패턴: Thin Server Shell → Fat Client Tree
  3. Routing & Auth Flow/는 AuthGuard로 감싸기, /login은 이미 로그인했으면 리다이렉트, next/navigation 사용
  4. Agent Parallelization — 3 phases: Foundation → Parallel Features → Integration
  5. Migration Details — 패키지 추가/제거, 설정 변경, import 경로

AI가 디자인 spec을 docs/superpowers/specs/에 저장하고 자동 spec reviewer를 dispatch합니다. Reviewer가 3가지 이슈 발견 (todo-app.tsx orchestrator 누락, 테스트 디렉토리 구조, Toaster 배치) → AI 수정 → reviewer가 2차에서 승인.

Superpowers 참고: 디자인 spec은 docs/superpowers/specs/에 저장되며 plan 작성 전에 리뷰됩니다. 자세한 내용은 Brainstorming을 참조하세요.


1단계: Superpowers가 Task를 분할하는 Plan 작성

어떤 코드도 작성되기 전에, AI가 상세한 plan을 만듭니다 (superpowers:writing-plans skill 사용). 핵심 원칙입니다: plan이 없으면 실행도 없습니다.

AI가 모든 소스 파일을 읽은 후, 3개 phase로 나뉜 10개 task의 plan을 만듭니다:

Phase 1: Foundation (1 agent, 순차 — 먼저 완료해야 함)

  1. Task 1: create-next-app으로 새 Next.js 16 프로젝트 스캐폴딩
  2. Task 2: 의존성 및 설정 추가 (Tailwind, shadcn, Vitest, tsconfig)
  3. Task 3: 변경 없는 파일 복사 (lib/, types/, hooks/, contexts/, components/ui/)
  4. Task 4: app/layout.tsx 생성 — AuthProvider와 Toaster가 있는 Root layout
  5. Task 5: app/globals.css 생성 — src/index.css에서 CSS 마이그레이션

Phase 2: Features (3 agents 병렬)

  1. Task 6 — Agent Auth: auth 페이지 생성 (auth-guard.tsx, auth-page.tsx, login-form.tsx, register-form.tsx, app/login/page.tsx)
  2. Task 7 — Agent Todo: todo 페이지 생성 (todo-app.tsx, header.tsx, filter-bar.tsx, todo-list.tsx, todo-item.tsx, todo-input.tsx, edit-todo-dialog.tsx, app/page.tsx)
  3. Task 8 — Agent Test: 8개 테스트 파일을 __tests__/로 마이그레이션, relative imports → @/ alias로 업데이트

Phase 3: Integration (1 agent, 순차)

  1. Task 9: npm run build + npx vitest run 실행, 모든 이슈 수정
  2. Task 10: 정리 및 최종 커밋

의존성 그래프:

Phase 1 (Tasks 1-5) ─── sequential ───→ Phase 2 (Tasks 6-8) ─── parallel ───→ Phase 3 (Tasks 9-10)
                                          ├─ Agent Auth (Task 6)
                                          ├─ Agent Todo (Task 7)
                                          └─ Agent Test (Task 8)

병렬 실행의 전제조건: 각 agent가 자체 파일을 소유하며, 겹치지 않습니다. Agent Auth는 auth 관련 파일만, Agent Todo는 todo 관련 파일만, Agent Test는 테스트 파일만 수정합니다.

AI가 자동 plan reviewer를 dispatch → reviewer가 1개 이슈 발견 (테스트 파일의 relative imports가 이동 시 깨짐) → AI가 import 매핑 테이블로 수정 → reviewer 승인.

AI가 실행 방법을 질문합니다:

"두 가지 실행 방법이 있습니다: 1) Subagent-Driven (권장) — agent를 dispatch하고, task 사이에 리뷰. 2) Inline Execution — 현재 세션에서 바로 실행. 어느 것을 선택하시겠습니까?"

선택: 1) Subagent-Driven — 3-4개 agent 병렬 요구사항에 적합.

2단계: Phase 1 — Foundation

AI가 5개 foundation task를 1개의 큰 agent로 합칩니다 (순차적으로 의존하기 때문). Agent가 다음을 수행합니다:

  1. Scaffold: TypeScript, Tailwind CSS, App Router와 함께 npx create-next-app@latest
  2. Config: 의존성 추가 (@dnd-kit/*, sonner, date-fns, shadcn 등), vitest.config.ts, components.json 설정
  3. 파일 복사: lib/, types/, hooks/, contexts/, components/ui/ — 그대로 복사, 파일 시작에 "use client"만 추가
  4. Layout: metadata, fonts, <AuthProvider>, <Toaster />가 있는 app/layout.tsx 생성
  5. CSS: Tailwind 4 구문으로 globals.css 마이그레이션

Phase 1 완료 후 (7개 커밋), AI가 Phase 2를 준비하면서 백그라운드에서 spec reviewer를 dispatch하여 compliance를 확인합니다.

Phase 1: DONE — 7개 커밋, 빌드 성공, 모든 파일이 올바른 위치

3단계: 3개 Agent를 병렬로 Dispatch (Phase 2)

Phase 1이 완료되면, controller가 3개 agent를 동시에 dispatch합니다:

AgentTask소유 파일
Auth AgentAuth 페이지 + route protectionauth-guard, auth-page, login-form, register-form, app/login/page.tsx
Todo AgentTodo 페이지 + 모든 컴포넌트todo-app, header, filter-bar, todo-list, todo-item, todo-input, edit-todo-dialog, app/page.tsx
Test Agent8개 테스트 파일 마이그레이션__tests__/components/, __tests__/contexts/, __tests__/hooks/, __tests__/lib/

각 agent가 받는 것:

  • 명확한 범위: plan의 구체적인 파일 목록
  • Spec 참조: 컴포넌트를 어떻게 적응해야 하는지 알기 위한 디자인 spec 링크
  • 제약사항: 범위 밖의 파일 수정 금지, 모든 interactive 컴포넌트 시작에 "use client" 추가

실제 진행:

  • Auth Agent가 가장 먼저 완료 — 5개 파일, TypeScript 통과, 커밋 740e5dd. IDE가 todo-list.tsx./todo-item import에서 오류를 표시하지만 — 이것은 Todo Agent가 아직 파일을 완성하지 않아서이며, 자동으로 해결됩니다.

  • Todo Agent가 다음으로 완료 — 8개 파일, TypeScript 통과, 커밋 55a8988. 새로운 orchestrator로 todo-app.tsx를 생성 (App.tsx에서 로직 추출), <AuthGuard>로 감싸기.

  • Test Agent가 마지막으로 완료 — 8개 테스트 파일 생성 완료, 하지만 권한 부족으로 테스트 실행/커밋 불가. Controller가 npx vitest run을 실행하고 대신 커밋 — 39/39 테스트 PASS.

Auth Agent: DONE — 5개 파일, TypeScript 통과
Todo Agent: DONE — 8개 파일, TypeScript 통과
Test Agent: DONE — 8개 테스트 파일 마이그레이션, 39/39 테스트 통과

4단계: Phase 3 — Integration Verification

3개 agent가 모두 완료되면, controller가 integration을 실행합니다:

npm run build

빌드 실패! 오류: window is not defineduseThemeuseTodosuseState initializer에서 window/localStorage에 접근하기 때문. Next.js 특유의 SSR prerendering 이슈입니다 (Vite에는 없음).

수정: hook에 SSR guard 추가:

// hooks/use-theme.ts
const [theme, setTheme] = useState<'light' | 'dark'>(() => {
  if (typeof window === 'undefined') return 'light' // SSR guard
  const saved = loadTheme()
  if (saved) return saved
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
})

// hooks/use-todos.ts
const [todos, dispatch] = useReducer(todoReducer, [], () => {
  if (typeof window === 'undefined') return [] // SSR guard
  return loadTodos()
})

재실행: npm run build빌드 성공! npx vitest run39/39 테스트 PASS!

실무 교훈: SPA (Vite)에서 SSR이 있는 프레임워크 (Next.js)로 마이그레이션할 때, initial state에서 브라우저 전용 API (window, localStorage, document)를 항상 guard하세요. 이것이 가장 흔한 이슈입니다.

5단계: Verification Gate

마이그레이션 완료를 선언하기 전에:

1. 실행

npm run build && npx vitest run

2. 읽기

✓ Compiled successfully
Routes:
  ○ /           — Static
  ○ /login      — Static
  ○ /_not-found — Static

Test Suites: 8 passed, 8 total
Tests:       39 passed, 39 total

3. 확인

지표결과
Buildnext build 성공
Tests39/39 통과 (8개 테스트 파일)
Routes/ (todo app), /login (auth)
Commits깨끗한 11개 커밋

4. GIT HISTORY

050db4f chore: add .superpowers/ to .gitignore
edfa697 fix: guard window/localStorage access for SSR prerendering
97542b0 test: migrate all test files to __tests__/ directory
55a8988 feat: add todo page with all components
740e5dd feat: add auth pages with client-side route protection
76abbff fix: add "use client" to sonner component, accept Next.js tsconfig updates
e78ce06 feat: add root layout with AuthProvider and Toaster
65ff090 chore: copy unchanged source files
451ad1d chore: configure TypeScript, Vitest, and shadcn
a50080f chore: add project dependencies
bb0f5c5 chore: scaffold Next.js 16 project

보너스: Neo Brutalism 재디자인 (이어지는 병렬 작업)

마이그레이션이 완료되고 검증된 후, 팀은 새로운 요구사항으로 계속합니다: Neo Brutalism 스타일로 전체 UI 재디자인. Superpowers 프로세스가 동일하게 반복됩니다:

Neo Brutalism 브레인스토밍

AI가 5가지 질문을 합니다:

  1. Brutal 수준 → 선택: Bold Neo Brutalism (3px 검은 테두리, 하드 그림자, 선명한 색상)
  2. Color palette → 선택: Candy Crush (핑크/보라/파랑 — #FF85A1, #A855F7, #38BDF8)
  3. Scope → 선택: 전체 (login과 todo 페이지 모두)
  4. Dark mode → 선택: 둘 다 유지 (light Neo Brutalism 메인, dark adapted)
  5. Font → 선택: Space Grotesk (Neo Brutalism에서 인기 있는 geometric sans-serif)

AI가 3가지 접근 방식 제안 → CSS-first 선택 (CSS 변수 + Tailwind 클래스를 통한 변경, 컴포넌트 구조 유지, 테스트 통과 유지).

Neo Brutalism Plan: 6 Tasks, 4 Phases

PhaseTasksAgents설명
1: FoundationTask 11Font 교체, CSS 변수, 유틸리티 클래스
2: Base UITask 21button, input, dialog, select, dropdown, popover, sonner, calendar
3: ComponentsTask 3-53 병렬Auth (A), Layout (B), Items (C)
4: IntegrationTask 61Build, tests, 시각적 확인

병렬 실행

Phase 1+2 (순차 의존성으로 1 agent로 병합):

  • Font Geist → Space Grotesk으로 교체
  • 전체 CSS 변수 교체 (colors OKLch → Candy Crush palette)
  • 유틸리티 클래스 추가: .brutal-shadow, .brutal-border, hover/active transforms
  • shadcn/ui 기본 컴포넌트 업데이트 (button, input, dialog, select...)

Phase 3 — 3 agents 병렬:

AgentFiles
Agent A: Authauth-page, login-form, register-form
Agent B: Layoutheader, filter-bar, todo-list
Agent C: Itemstodo-item, todo-input, edit-todo-dialog

Phase 4: Build + Test → 39/39 테스트가 여전히 통과 (스타일링만 변경하고 로직은 건드리지 않았으므로).

Neo Brutalism 결과

  • Font: Geist → Space Grotesk Variable
  • Colors: OKLch neutral → Candy Crush (pink/purple/blue)
  • Borders: 1px transparent → 3px solid black
  • Shadows: Soft blur → Hard 4px offset (no blur)
  • Hover/Active: Lift up / Push down transforms
  • Dark mode: Navy 배경, 컬러 테두리, bold 색상 유지
  • 전체 재디자인에 5개 커밋

전체 결과

마이그레이션과 재디자인을 모두 완료한 후:

지표이전이후
FrameworkReact 19 + Vite 7 (SPA)Next.js 16 App Router
Routing없음 (toggle state)//login (next/navigation)
Components전부 client-sideServer shells + Client components
Style기본 shadcn/uiBold Neo Brutalism (Candy Crush)
FontGeistSpace Grotesk
Tests39 통과39 통과 (깨지지 않음)
Commits11 (마이그레이션) + 5 (재디자인) = 16 커밋
  • 0개 테스트 깨짐 — 로직 100% 유지
  • 병렬 실행 덕분에 시간이 크게 단축됨 (3 agents Phase 2 마이그레이션 + 3 agents Phase 3 재디자인)
  • 실제 이슈가 즉시 수정됨: SSR window guard, sonner용 "use client" directive, 테스트 import 경로

핵심 포인트

  1. 코드 전에 브레인스토밍. 올바른 질문 (범위, 접근 방식, 제약사항)을 통해 잘못된 방향의 리팩토링을 방지합니다. 이 경우, 5가지 브레인스토밍 질문이 "framework migration only, 새로 스캐폴딩, 로직 유지"를 명확히 했습니다.

  2. 상세한 plan은 병렬 실행의 전제조건입니다. Plan은 다음을 명확히 지정해야 합니다: 누가 무엇을, 어떤 파일을, task 간 의존성을. 파일 소유권을 명확히 나누지 않으면 agent들이 충돌합니다.

  3. 의존성에 따라 phase를 나누고, 각 phase 내에서 병렬로. Foundation이 먼저 완료되어야 (scaffold, config) 기능별 agent를 병렬로 dispatch할 수 있습니다. 패턴: Sequential Phases → Parallel Tasks Within Phase.

  4. Spec과 plan 모두 자동 리뷰. AI가 spec/plan 작성 후 reviewer agent를 dispatch합니다. Reviewer가 이슈 (orchestrator 컴포넌트 누락, 잘못된 테스트 import 경로)를 실행 시작 전에 발견합니다 — 코드 작성 후보다 수정 비용이 훨씬 저렴합니다.

  5. 실제 이슈는 항상 발생합니다. 이 경우, SSR window is not defined는 SPA → SSR 프레임워크 마이그레이션 시 특유의 이슈입니다. Integration phase (Phase 3)는 이러한 이슈를 catch하고 수정하기 위해 존재합니다.

  6. 프로세스는 반복 가능합니다. 마이그레이션이 끝난 후, Neo Brutalism 재디자인도 동일한 프로세스를 따릅니다: brainstorm → spec → plan → parallel execution → verify. 같은 패턴, 다른 컨텍스트.


요약: React/Vite 애플리케이션을 Next.js 16으로 마이그레이션 + Neo Brutalism 재디자인을 같은 세션에서 수행. Superpowers가 전체를 orchestrate합니다: 브레인스토밍으로 전략 결정, plan으로 phase별 task 분할, 병렬 agent로 동시 실행, spec 리뷰로 품질 보장, verification gate로 완료 선언 전 이슈 catch. 결과: 16개 커밋, 39/39 테스트 통과, 0 regression.