
링크 드라퍼 서비스에서는
사용자가 접근할 때 "현재 서버가 점검 중인지"를 확인하는 기능이 필요했습니다.
Next.js Middleware를 이용해,
모든 요청이 들어올 때 점검 API를 호출하고,
점검 중이라면 /maintenance 페이지로 리디렉션하는 흐름을 만들었습니다.
구조도 간단했습니다:
// middleware.ts
import { customFetch } from '@/lib/fetch';
export async function middleware(req: NextRequest) {
const response = await customFetch('/api/maintenance');
const data = await response.json();
if (data.isMaintenance) {
return Response.redirect('/maintenance');
}
}
로컬에서는 정말 깔끔하게 잘 돌아갔습니다.
문제는… Vercel에 배포한 순간 시작됐습니다.
Middleware가 fetch를 못 한다고?
Vercel에 배포하고 나니
점검 처리가 아예 안 되는 것은 물론,
Middleware 자체가 에러를 뱉으며 동작을 멈췄습니다.
에러 로그를 살펴보니:
• fetch 호출 실패
• 특정 헤더 관련 오류
• Authorization 토큰이 undefined
“아니 로컬에선 잘 됐는데?”
Next.js에서 Middleware는 Vercel에 배포되면,
Node.js 서버가 아니라
Edge Function 위에서 실행됩니다.
Edge Runtime이라고 부르는 이 환경은,
Node.js가 아닙니다.
항목 Node.js Edge Runtime
런타임 완전한 Node.js 환경 V8 Isolate 기반
지원 API fs, http, https, net 등 자유롭게 사용 대부분 미지원
fetch 동작 서버 context 유지 새 요청 context로 동작
쿠키/헤더 관리 자동 포함 가능 수동 설정 필요
우리 customFetch는
getCookie()로 session_token을 가져와
Authorization 헤더를 만들고 있었습니다.
// customFetch 내부 (문제)
const token = getCookie('session_token');
headers['Authorization'] = `Bearer ${token}`;
Edge Middleware에서는
• getCookie() 자체가 제대로 동작하지 않고
• 새로 만든 fetch 요청에는 쿠키가 자동으로 전달되지 않습니다.
결국:
• Authorization 헤더가 비어 있음
• 인증 실패
• API 요청 실패
• Middleware 자체 에러
이라는 대참사가 일어난 것이죠.
✨ 해결법 1: Middleware 안에서는 ‘순수 fetch’만 쓰자
Middleware에서는
customFetch를 쓰지 않고,
순수 fetch로 API를 호출했습니다.
쿠키도 직접 수동으로 넘겼습니다.
export async function middleware(req: NextRequest) {
const baseUrl = process.env.BASE_URL || 'https://link-dropper.com';
const res = await fetch(`${baseUrl}/api/maintenance`, {
headers: {
cookie: req.headers.get('cookie') || '',
},
});
const data = await res.json();
if (data.isMaintenance) {
return Response.redirect('/maintenance');
}
}
✅ Edge Config 사용하기 (Vercel 기능)
Vercel에서는 Edge Config라는 기능을 제공해
초고속 Key-Value 저장소를 Edge Function에서 바로 읽을 수 있습니다.
• 점검 모드 여부를 Edge Config에 저장
• API 호출 없이 바로 읽기
단점: 관리하는 시스템이 하나 더 늘어남
✅ 환경변수 활용하기
process.env.MAINTENANCE_MODE 같은 환경변수로 점검 상태를 관리하는 방법도 있습니다.
단점: 런타임 중 실시간 변경이 불가능함
(배포해야 반영)
✅ API fetch 시 Bearer 인증 제거
점검 API 자체를 비인증 엔드포인트로 만들어서
fetch에 Authorization 헤더를 요구하지 않게 만드는 것도 하나의 방법입니다.
단점: 보안적인 고민 필요
• Middleware 안에서는 순수 fetch만 사용
• 요청 헤더로 쿠키를 수동 전달
• 점검 API는 인증 없이 접근 가능하도록 수정
현재는 이 구조로 Vercel에서도 문제없이 잘 작동 중입니다.
링크 드라퍼는 단순한 링크 저장 툴이 아닙니다.
링크를 정리하고, 다시 꺼내볼 수 있게 만드는 서비스를 목표로 하고 있습니다.
• 🔗 링크 삭제, 폴더 생성/수정 작업에 낙관적 UI 적용
• 🌐 OpenGraph 정보 자동 수집
• 👥 폴더를 친구에게 공유하는 기능까지
지금 체험해보시고,
빠르고 부드러운 사용자 흐름을 경험해보세요!
로컬에서 잘 돌아간다고 방심하면,
Vercel Edge Runtime이 발목을 잡을 수 있습니다.
Next.js를 Vercel에 올린다면,
Middleware는 Node.js가 아니다.
라는 점을 꼭 기억해야 합니다.
이 글이 같은 문제로 헤매는 개발자들에게 작은 등불이 되길 바랍니다 🙌
읽어주셔서 감사합니다!
비슷한 실수나 경험 있으셨다면 댓글로 공유해주세요 😊