40,000명의 학생, 6개월, 제로 다운타임: Drupal → Next.js 마이그레이션
프로그램 찾기가 8.2초에서 시간 초과된다. 또 다시. 등록주이고 학생 포털이 한계에 다다르고 있다 — 40,000명의 대학생들이 같은 망가진 검색을 새로고침하고, 당신의 지원 대기열이 티켓으로 가득 차고, 입학처 부총장이 실시간으로 변환율이 떨어지는 것을 본다. Drupal 7 보안 패치는 6개월 후 종료된다. 200개 이상의 프로그램 페이지, 당신의 팀이 거의 이해하지 못하는 레거시 CMS, 그리고 협상 불가능한 요구사항이 있다: 제로 다운타임. 2024년 초, 한 주의 대형 대학이 우리에게 정확히 이 문제를 제시했다. Drupal 7이 지원을 종료하기 전에 Next.js로 전체 마이그레이션이 필요했고, 프로그램 찾기가 학생을 잃지 않아야 했다. 26주 안에 전체 포털을 다시 구축하고, 검색 응답 시간을 340ms로 단축하고, 단 1분도 사이트를 오프라인으로 두지 않고 배포한 방법은 다음과 같다.
전체를 Next.js로 마이그레이션하고, 헤드리스 CMS 백엔드를 사용하고, 페이지 로드 시간을 73% 단축하고, 일정대로 배포한 방법의 이야기다. 우리가 내린 아키텍처 결정(그리고 거의 잘못된 것)과 실제 마이그레이션 프로세스, 성능 벤치마크, 그리고 대규모 CMS 마이그레이션에 적용되는 교훈을 공유하겠다.
목차
- 시작점: 우리가 다루고 있던 것
- 왜 Next.js인가 (그리고 Drupal 10이 아닌 이유)
- 아키텍처 결정
- 프로그램 찾기: 핵심 기능 재구축
- 학생 포털 마이그레이션
- 콘텐츠 마이그레이션 전략
- 6개월 타임라인
- 성능 결과
- 배운 교훈
- FAQ

시작점: 우리가 다루고 있던 것
그림을 그려보자. 대학의 디지털 존재는 2014년경에 출시된 Drupal 7로 구축되었다. 지난 10년 동안 다음과 같이 축적되었다:
- 약 12,000개의 콘텐츠 노드 — 프로그램, 과정, 교수진 프로필, 뉴스 기사, 이벤트에 걸쳐
- 200개 이상의 학술 프로그램 페이지 각각 복잡한 분류 관계(학위 수준, 학과, 대학, 배달 형식, 인증 상태)
- 커스텀 프로그램 찾기 Drupal Views 기반 검색으로 구축되고 필터가 노출됨 — 기능하지만 느림
- 학생 포털 조언 도구, 학위 감사, 등록 링크, 개인화된 대시보드에 인증된 접근
- 47개의 커스텀 Drupal 모듈, 그 중 19개는 더 이상 유지되지 않음
- 3개의 서로 다른 테마 계층 연속적인 재설계에서 위에 쌓임
사이트는 기관 로드 밸런서 뒤의 두 개의 노후 가상 머신에서 호스팅되었다. 등록 피크(8월과 1월) 동안 프로그램 찾기는 정기적으로 시간 초과되었다. 마케팅 팀은 프로그램의 PDF 목록을 백업으로 게시하는 것으로 돌아갔다. 그것이 모든 것을 말해준다.
Core Web Vitals는 악랐다:
| 메트릭 | Drupal 7 (이전) | 목표 |
|---|---|---|
| LCP | 6.2초 | < 2.5초 |
| FID | 380ms | < 100ms |
| CLS | 0.31 | < 0.1 |
| TTFB | 2.8초 | < 0.8초 |
| 프로그램 찾기 로드 | 8.4초 | < 1.5초 |
이해관계자 구성
대학 웹 프로젝트는 이해관계자의 수 때문에 독특하게 도전적이다. 우리는 다음과 함께 일하고 있었다:
- 중앙 IT — SSO 통합, 보안 준수, 호스팅 담당
- 마케팅 & 통신 — 브랜드, 콘텐츠 전략, 분석 소유
- 등록처 — 프로그램 데이터 및 학생 정보 시스템(SIS) 소유
- 개별 대학 & 학과 — 각각 자신의 콘텐츠 편집자(CMS 접근 권한이 있는 80명 이상)
- 학생회 — 모바일 우선 설계(정당하게)를 강력하게 옹호
모든 이 그룹으로부터 정렬을 얻는 것은 프로젝트의 처음 3주를 소요했다. 우리는 공유 우선순위와 협상 불가능한 것을 설정하기 위해 설계 스프린트를 실행했다.
왜 Next.js인가 (그리고 Drupal 10이 아닌 이유)
명백한 질문: 왜 Drupal 10으로 업그레이드하지 않는가? 대학의 IT 팀은 실제로 우리에게 연락하기 6개월 전에 그 경로를 시작했다. 47개의 커스텀 모듈 중 23개가 Drupal 10 동등물이 없고 완전히 다시 작성해야 한다는 것을 발견한 후 포기했다.
실제 계산은 다음과 같이 보였다:
| 요소 | Drupal 10 마이그레이션 | Next.js 재구축 |
|---|---|---|
| 예상 타임라인 | 8-10개월 | 6개월 |
| 커스텀 모듈 재작성 | 23개 모듈 | N/A (API/컴포넌트로 재구축) |
| 콘텐츠 편집자 재교육 | 중간 (새 관리 UI) | 중간 (새 CMS) |
| 성능 상한선 | 중간 개선 | 극적 개선 |
| 호스팅 유연성 | 전통 LAMP/유사 | 엣지 배포, CDN 우선 |
| 개발자 채용 풀 | 축소 (Drupal 전문가) | 성장 (React/Next.js) |
| 장기 유지보수 비용 | 연간 약 $180K | 연간 약 $95K |
유지보수 비용 차이가 행정부의 결정타였다. 기관 경험을 가진 Drupal 개발자는 찾기가 어려워지고 있으며 유지하는 데 더 비싸졌다. 대학의 자체 IT 팀은 3명의 React 개발자와 0명의 Drupal 전문가가 있었으며 선임 Drupal 개발자가 퇴직했다.
우리는 구체적으로 Next.js를 선택했다 (Gatsby, Remix, 또는 Astro에 비해) 여러 이유로:
- 하이브리드 렌더링 — 프로그램 페이지는 정적으로 생성될 수 있지만 학생 포털은 인증을 통한 서버 측 렌더링이 필요
- API 경로 — 별도의 백엔드 서비스 없이 SIS 통합을 위한 미들웨어를 구축할 수 있음
- 증분 정적 재생성(ISR) — 프로그램 데이터는 매주 변경되며, 시간 단위가 아님. 1시간 재검증 윈도우를 가진 ISR이 완벽
- 대학의 팀이 React를 알고 있었다 — 인수 후 이것을 유지보수할 것
유사한 옵션을 검토 중이라면, 우리의 Next.js 개발 기능 페이지는 우리가 일반적으로 구축하는 기술 세부사항을 다룬다.
아키텍처 결정
헤드리스 CMS 선택
우리는 대학의 요구사항에 대해 5개의 헤드리스 CMS 옵션을 평가했다: 80명 이상의 콘텐츠 편집자, 복잡한 콘텐츠 관계, 역할 기반 권한, 합리적인 좌석당 가격 모델.
우리는 이 프로젝트에 Sanity에 도착했다. 핵심 요소:
- GROQ 쿼리 프로그램, 학과, 대학 사이의 복잡한 분류 관계를 이 사용 사례에 대해 GraphQL보다 훨씬 잘 처리
- 실시간 협업 — 여러 편집자가 충돌 없이 동시에 작업할 수 있음
- 커스텀 입력 컴포넌트 — 우리는 스튜디오에서 프로그램 전제 조건 매퍼를 직접 구축
- 가격 — 엔터프라이즈 플랜은 약 $949/월로 예산 내에 있었고 사용자당 비용이 예측 가능
콘텐츠 모델링은 약 2주를 소요했다. 우리는 14개의 문서 유형과 8개의 참조 유형을 정의했다. 프로그램 스키마 혼자도 schema.org EducationalOrganization 및 Course 마크업을 위한 34개의 필드를 포함했다.
CMS 아키텍처에 대한 우리의 접근에 대해 자세히 알아보려면, 우리의 헤드리스 CMS 개발 페이지를 참조하라.
인프라
우리는 Next.js 프론트엔드를 위해 Vercel (FERPA 준수 및 SSO 요구사항에 필요한 엔터프라이즈 플랜)에 배포했다. 학생 포털의 인증된 경로는 대학의 기존 CAS (중앙 인증 서비스) SSO를 통한 세션 관리로 서버 측 렌더링을 사용한다.
데이터 흐름은 다음과 같다:
[Sanity CMS] → [Vercel의 Next.js] → [CDN 엣지]
↕
[대학 SIS API]
↕
[CAS SSO / LDAP]
정적 프로그램 페이지는 빌드 시간에 사전 렌더링되고 ISR을 통해 매시간 재검증된다. 프로그램 찾기는 사전 가져온 데이터(빌드 시간에 클라이언트에 JSON 인덱스로 로드)와 실시간 필터링의 조합을 사용한다 — 검색 작업에는 서버 왕복이 필요하지 않다.
API 계층
학생 정보 시스템 (Ellucian Banner, 궁금하다면 — 항상 Banner다)은 SOAP API를 노출했다. 네, 2024년에. 우리는 SOAP 엔드포인트를 소비하고 깔끔한 REST 엔드포인트를 프론트엔드에 노출하는 Next.js API 경로를 사용하여 변환 계층을 구축했다:
// /app/api/programs/[programId]/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { fetchFromBanner } from '@/lib/banner-client';
import { transformProgramData } from '@/lib/transforms';
export async function GET(
request: NextRequest,
{ params }: { params: { programId: string } }
) {
const bannerData = await fetchFromBanner(
'PROGRAM_DETAIL',
{ programCode: params.programId }
);
const program = transformProgramData(bannerData);
return NextResponse.json(program, {
headers: {
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
},
});
}
이 변환 계층은 프로젝트의 가장 높은 가치 조각 중 하나였다. 그것은 프론트엔드를 Banner의 특이성에서 분리하고 대학이 미래 프로젝트(모바일 앱이 이미 논의 중)를 위해 사용할 수 있는 깔끔한 API를 제공했다.

프로그램 찾기: 핵심 기능 재구축
프로그램 찾기는 전체 사이트에서 가장 중요한 페이지였다. 분석에 따르면 모든 유기 검색 트래픽의 34%를 차지했으며 예비 학생의 #1 진입점이었다. 이것을 잘못 얻는 것은 옵션이 아니었다.
오래된 접근 방식 (그리고 왜 느렸는가)
Drupal 버전은 노출된 필터가 있는 Views를 사용했다. 모든 필터 변경은 전체 서버 왕복을 트리거했고, 데이터베이스를 다시 쿼리했으며, 전체 페이지를 다시 렌더링했다. 200개 이상의 프로그램과 6개의 분류 치수 (학위 수준, 대학, 학과, 배달 형식, 관심 분야, 키워드 검색)를 가지고, 쿼리는 비용이 컸다.
새로운 접근 방식
우리는 빌드 시간에 검색 인덱스를 사전 구축했다. 200개 이상의 모든 프로그램은 페이지와 함께 제공되는 약 180KB JSON 파일로 직렬화되었다 (gzip으로 약 22KB로 압축). 필터링은 커스텀 훅을 사용하여 완전히 클라이언트 측에서 발생한다:
// hooks/useProgramSearch.ts
import { useMemo, useState } from 'react';
import Fuse from 'fuse.js';
import { Program, ProgramFilters } from '@/types';
const fuseOptions = {
keys: [
{ name: 'title', weight: 0.4 },
{ name: 'description', weight: 0.2 },
{ name: 'keywords', weight: 0.3 },
{ name: 'department', weight: 0.1 },
],
threshold: 0.3,
};
export function useProgramSearch(programs: Program[]) {
const [filters, setFilters] = useState<ProgramFilters>({});
const fuse = useMemo(() => new Fuse(programs, fuseOptions), [programs]);
const results = useMemo(() => {
let filtered = programs;
if (filters.degreeLevel) {
filtered = filtered.filter(p => p.degreeLevel === filters.degreeLevel);
}
if (filters.college) {
filtered = filtered.filter(p => p.college === filters.college);
}
if (filters.deliveryFormat) {
filtered = filtered.filter(p =>
p.deliveryFormats.includes(filters.deliveryFormat!)
);
}
if (filters.searchQuery) {
const fuseResults = fuse.search(filters.searchQuery);
const fuseIds = new Set(fuseResults.map(r => r.item.id));
filtered = filtered.filter(p => fuseIds.has(p.id));
}
return filtered;
}, [programs, filters, fuse]);
return { results, filters, setFilters };
}
우리는 퍼지 텍스트 검색을 위해 Fuse.js를 사용했고 패싯에 대해 순수 JavaScript 필터링을 사용했다. 결과: 검색 결과는 50ms 미만에 나타난다. 로딩 스피너 없음. 서버 호출 없음. 사용자는 원하는 만큼 빠르게 필터를 사용할 수 있다.
각 프로그램 결과는 전체 schema.org 마크업을 가진 정적으로 생성된 상세 페이지에 링크되어 있으며, 이는 Google의 교육 관련 검색 기능에서 대학의 모습을 극적으로 개선했다.
학생 포털 마이그레이션
학생 포털은 가장 까다로운 부분이었다. 인증, 개인화, Banner의 실시간 데이터가 필요했다. 그것의 어떤 부분도 정적으로 생성할 수 없었다.
인증 흐름
대학은 모든 기관 시스템에서 단일 로그인을 위해 CAS를 사용한다. 우리는 CAS를 Next.js와 통합했다 커스텀 인증 흐름 사용:
- 미인증 사용자가
/portal에 접근 → CAS 로그인으로 리다이렉트 - CAS가 서비스 티켓으로 다시 리다이렉트
- 우리의 API 경로가 CAS 서버에 대해 티켓을 검증
- 우리는 httpOnly 쿠키에 저장된 서명된 JWT를 생성
- 후속 요청은 세션 관리를 위해 JWT를 사용
우리는 당시 유지되는 CAS 제공자가 없었기 때문에 우리가 처음부터 작성한 커스텀 CAS 제공자와 함께 next-auth (이제 Auth.js)를 사용했다.
포털 기능
학생 포털은 다음을 포함했다:
- 개인화된 대시보드 다가오는 등록 날짜, 지연 및 고문 정보 포함
- 학위 감사 요약 Banner에서 실시간으로 끌어옴
- 빠른 링크 LMS (Canvas), 이메일, 도서관 시스템으로
- 프로그램별 리소스 학생의 선언된 전공에 따라
모든 포털 페이지는 서버 측 렌더링을 사용한다. 우리는 시스템을 압도하는 것을 피하기 위해 Banner API 응답을 공격적으로 캐시한다 (대부분 엔드포인트에 30초 TTL, 학위 감사에 5분 TTL).
콘텐츠 마이그레이션 전략
Drupal에서 Sanity로 12,000개의 콘텐츠 노드를 마이그레이션하려면 체계적 접근이 필요했다. 우리는 커스텀 마이그레이션 파이프라인을 구축했다:
# 간소화된 마이그레이션 파이프라인
1. Drupal 노드 내보내기 → 커스텀 Drush 명령을 통한 JSON
2. JSON 변환 → Node.js 스크립트를 통한 Sanity 문서 형식
3. 미디어 파일 처리 → Sanity CDN에 업로드
4. 문서 가져오기 → Sanity 마이그레이션 API
5. 검증 → 끊긴 참조에 대한 자동화된 확인
미디어 마이그레이션은 가장 지루한 부분이었다. Drupal의 파일 관리는 내부 경로와 데이터베이스 참조로 파일을 저장한다. 우리는 다음을 수행한 스크립트를 작성했다:
- Drupal 파일 디렉토리에서 모든 파일을 다운로드
- Sanity의 자산 파이프라인에 업로드
- 이전 Drupal 파일 ID를 새 Sanity 자산 참조로 매핑
- 새 자산 참조를 가리키도록 모든 리치 텍스트 콘텐츠 업데이트
이 스크립트는 전체 데이터 세트에서 약 14시간 동안 실행되었다. 우리는 프로젝트 중에 3번 실행했다: 초기 테스트용, 중간 지점에 스테이징 새로고침용, 최종 전환용.
콘텐츠 동결 전략
우리는 2단계 콘텐츠 동결을 구현했다:
- 1-20주: 콘텐츠 편집자는 Drupal에서 정상적으로 작업한다. 우리는 매주 스테이징에 스냅샷을 마이그레이션한다.
- 21-23주: 이중 항목. 새 콘텐츠는 Drupal과 Sanity 모두에 들어간다. 편집자는 새 CMS에서 교육받는다.
- 24주: 전체 전환. Drupal은 읽기 전용이 되고, 그 다음 오프라인이 된다.
이중 항목 기간은 고통스러웠지만 필요했다. 80명 이상의 편집자가 있었고 Sanity로 유일한 옵션이 되기 전에 근육 기억을 구축해야 했다.
6개월 타임라인
| 월 | 단계 | 핵심 전달물 |
|---|---|---|
| 1월 | 발견 & 아키텍처 | 이해관계자 정렬, CMS 선택, 인프라 설정, 콘텐츠 모델링 |
| 2월 | 핵심 개발 | 설계 시스템, 페이지 템플릿, 프로그램 상세 페이지, 네비게이션 |
| 3월 | 프로그램 찾기 & 검색 | 검색 인덱스, 필터링 UI, 프로그램 데이터 파이프라인, SEO 마크업 |
| 4월 | 학생 포털 | CAS 통합, Banner API 계층, 대시보드, 학위 감사 표시 |
| 5월 | 콘텐츠 마이그레이션 & 교육 | 마이그레이션 스크립트, 편집자 교육 (6개 세션), 스테이징 QA |
| 6월 | QA, 성능, 출시 | 로드 테스트, 접근성 감사, 콘텐츠 동결, DNS 전환 |
우리 팀은 4명의 개발자, 1명의 설계자, 1명의 프로젝트 관리자로 구성되었다. 대학은 전담 제품 소유자와 Banner/CAS 통합 작업을 위한 IT 연락처를 제공했다.
우리는 두 가지 주요 문제에 부딪혔다:
3월: Banner의 SOAP API는 분당 100개의 요청의 문서화되지 않은 속도 제한을 가지고 있었다. 우리의 프로그램 찾기는 빌드 중에 모든 프로그램 데이터를 배치 가져오도록 설계되었다. 우리는 큐 시스템을 구현하고 여러 배치에 걸쳐 빌드를 확산해야 했다.
5월: 접근성 감사는 34개의 WCAG 2.1 AA 위반을 발견했다. 대부분은 설계에서 상속되었다 (2차 버튼에 불충분한 색 대비, 프로그램 찾기 필터에 누락된 포커스 표시기). 우리는 예정되지 않은 8일을 치료에 소비했다.
성능 결과
출시 후 숫자는 다음과 같이 보였다:
| 메트릭 | Drupal 7 (이전) | Next.js (이후) | 개선 |
|---|---|---|---|
| LCP | 6.2초 | 1.1초 | 82% 더 빠름 |
| FID / INP | 380ms | 45ms | 88% 더 빠름 |
| CLS | 0.31 | 0.02 | 94% 개선 |
| TTFB | 2.8초 | 0.12초 | 96% 더 빠름 |
| 프로그램 찾기 로드 | 8.4초 | 0.8초 | 90% 더 빠름 |
| Lighthouse 점수 | 34 | 97 | +63점 |
| 빌드 시간 (전체) | N/A | 4분 12초 | — |
| 월간 호스팅 비용 | 약 $2,400 | 약 $1,100 | 54% 절감 |
그러나 대학에게 가장 중요한 숫자는 다음과 같았다:
- 프로그램 찾기 사용량이 156% 증가 출시 후 첫 학기
- 모바일 이탈율이 67%에서 31%로 감소
- 프로그램 페이지의 유기 검색 트래픽이 43% 증가 4개월 이내 (schema.org 마크업 + Core Web Vitals 개선)
- 포털 관련 지원 티켓이 62% 감소 — 주로 페이지가 실제로 안정적으로 로드되었기 때문
- 가을 등록 중 제로 다운타임 — 3년 만에 처음
배운 교훈
1. CAS/SSO 통합을 일찍 시작하라
우리는 CAS 통합을 4월로 예정했다. 1월에 개념 증명을 시작했어야 한다. 대학 IT 팀은 계획적으로 (즉, 천천히) 보안 검토를 진행한다. SSO 아키텍처 승인을 얻는 데는 보안 사무실과의 3주간의 왕복이 소요되었다.
2. 콘텐츠 모델링은 아키텍처다
우리는 아무 프론트엔드 코드도 작성하기 전에 콘텐츠 모델링에 전체 2주를 소비했다. 당시 느렸다. 우리가 만든 최고의 투자였다. 200개 이상의 프로그램을 학과, 대학, 학위 수준, 농도, 배달 형식 사이의 복잡한 관계와 함께 가지고 있을 때, 스키마를 미리 올바르게 얻으면 수백 시간의 리팩토링을 절약한다.
3. 출시 직전이 아니라 일찍 편집자를 교육하라
우리는 처음에 5월 편집자 교육을 계획했다. 우리는 피드백 후 4월로 이동했다. 이것은 편집자에게 2주가 아닌 6주간 Sanity에 편하게 지낼 시간을 제공했다. 이중 항목 기간 중에 입력된 콘텐츠의 품질은 이 때문에 극적으로 더 나았다.
4. Banner는 Banner다
Ellucian Banner와 함께 일하고 있다면 (그리고 고등 교육에 있다면 아마도) API 통합을 위해 추가 시간을 계획하라. 문서는 드물고, SOAP 엔드포인트는 일관성이 없으며, 모든 기관은 자신의 Banner 인스턴스를 다르게 커스터마이즈했다. 우리의 변환 계층은 필수적이었다.
5. 처음부터 접근성을 위해 예산을 배정하라
5월의 34개 WCAG 위반은 거의 전적으로 방지 가능했다. 우리는 이제 모든 PR에 대해 CI 파이프라인에서 axe-core 확인을 실행한다. 공립 대학을 위해 구축하고 있다면, WCAG 2.1 AA 준수는 선택 사항이 아니다 — Section 508에 따른 법적 요구사항이다.
유사한 마이그레이션 도전에 직면해 있다면, 구체적인 내용을 논의하기 위해 우리에게 기꺼이 말씀드린다. 당신은 우리에게 직접 연락할 수 있거나 우리가 일반적으로 이 프로젝트의 범위를 어떻게 지정하는지 확인하기 위해 가격 페이지를 확인할 수 있다.
FAQ
Drupal에서 Next.js로 대학 웹사이트를 마이그레이션하는 데 얼마나 걸리나?
이 규모의 사이트 — 12,000개의 콘텐츠 노드, 200개 이상의 프로그램, 인증된 학생 포털 — 6개월이 현실적이며 4-6명의 헌신적인 팀이 있다. 더 작은 기관 사이트 (2,000개 이하의 페이지, 포털 없음)는 종종 3-4개월에 가능하다. 타임라인은 프론트엔드 빌드보다 콘텐츠 마이그레이션, 이해관계자 정렬, Banner 또는 PeopleSoft와 같은 기관 시스템과의 통합으로 주도된다.
고등 교육 웹사이트에 가장 좋은 헤드리스 CMS는 무엇인가?
편집 팀의 규모와 기술 편의성에 따라 다르다. 우리는 실시간 협업, 유연한 콘텐츠 모델링, GROQ 쿼리 언어 때문에 이 프로젝트에 Sanity를 선택했다. Contentful과 Storyblok도 강력한 옵션이다. 100명 이상의 편집자가 있는 대학의 경우, Contentful의 워크플로우와 권한 모델이 유리할 수 있다. 더 기술적으로 편한 팀과 더 많은 커스터마이제이션을 원하는 팀의 경우, Sanity가 경향이 있다.
Next.js가 인증된 학생 포털을 처리할 수 있나?
절대로. Next.js는 인증된 페이지에 대한 서버 측 렌더링을 지원하며, App Router의 서버 컴포넌트는 클라이언트 번들에 노출하지 않고 사용자별 데이터를 가져오는 것을 간단하게 만든다. 우리는 Auth.js와 함께 우리가 작성한 커스텀 제공자를 사용하여 CAS (중앙 인증 서비스)와 통합했다. 포털은 성능 문제 없이 40,000명의 학생을 처리했다.
대학을 위한 Drupal에서 Next.js로의 마이그레이션 비용은 얼마나 드나?
이 범위의 프로젝트 — 프로그램 찾기, 학생 포털, 200개 이상의 프로그램, 전체 콘텐츠 마이그레이션, CMS 설정, 교육 — 일반적으로 복잡도에 따라 $250,000에서 $450,000 범위다. 그러나 장기 절감액은 중요하다. 이 대학은 연간 유지보수 비용을 약 $180K에서 $95K로 감소시켰으며, 높은 범위에서도 프로젝트는 3-4년 내에 자체 비용을 지불한다.
대규모 CMS 마이그레이션 중 SEO는 어떻게 되나?
정당한 우려다. 우리는 포괄적인 리다이렉트 맵 (2,400개 이상의 301 리다이렉트)을 구현했으며, 가능한 경우 모든 기존 URL 구조를 보존했으며, Drupal 사이트가 부족했던 schema.org 구조화된 데이터를 추가했다. 유기 트래픽은 출시 후 약 2주 동안 8% 하락했다 (모든 주요 마이그레이션의 정상), 그 후 4개월 이내에 회복되고 기준선을 43%로 초과했다.
Drupal 10이 헤드리스로 이동하는 것보다 대학에 더 나은 선택인가?
상황에 따라 그럴 수 있다. 팀이 강력한 Drupal 전문성을 가지고 있다면, 커스텀 모듈이 Drupal 10 호환성을 가지고 있으며, 정적/하이브리드 사이트의 성능 특성이 필요하지 않으면, Drupal 10은 완벽히 유효한 경로다. 우리의 경우, 대학은 Drupal 전문성을 잃었고, 23개의 호환되지 않는 모듈을 가지고 있었으며, 극적인 성능 개선이 필요했다. 헤드리스 접근은 명확하게 더 나은 적합이었다.
Drupal에서 헤드리스 CMS로 콘텐츠를 어떻게 마이그레이션하나?
우리는 Drush 명령을 통해 Drupal 콘텐츠를 내보내고, 새로운 CMS 스키마와 일치하도록 데이터를 변환하며, 미디어 파일을 처리하고, CMS의 마이그레이션 API를 통해 모든 것을 가져오는 커스텀 Node.js 스크립트를 사용한다. 프로세스는 일반적으로 3번 실행된다: 초기 테스트, 스테이징 새로고침, 최종 전환. 포함된 미디어를 가진 리치 텍스트 콘텐츠는 가장 어려운 부분이다 — 모든 내부 파일 참조를 다시 매핑해야 한다.
마이그레이션 중에 Drupal과 Next.js를 동시에 실행할 수 있나?
네, 그리고 우리는 추천한다. 우리의 마이그레이션 중에 Drupal은 계속해서 프로덕션 사이트를 제공했으며 우리는 스테이징 도메인에서 Next.js 버전을 구축하고 테스트했다. 우리는 콘텐츠가 두 시스템에 들어간 3주간의 이중 항목 기간을 사용했다. 최종 전환은 약 15분 정도 소요된 DNS 스위치였으며, Drupal은 30일 동안 폴백으로 읽기 전용 모드로 유지되었다.