Next.js 모바일과 PC를 구분해서 다른 경로로 이동 시키기(middleware 사용)
이슈
- 모바일로 접속할 때와 PC로 접속할 때 다른 화면을 보여줘야한다
- 모바일로 접속 시 기존 앱 경로를 보여주고
- PC로 접속 시 v2 앱 경로를 보여준다
해결
- Next.js의 middleware를 사용하여 모바일로 접속했는지 PC로 접속했는지 확인 후 의도한 화면의 경로로 redirect 시켰습니다
function isMobileUserAgent(userAgent: string): boolean {
const mobileRegex = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
return mobileRegex.test(userAgent);
}
// 루트 디렉토리에 middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const userAgent = request.headers.get('user-agent') || '';
const isMobile = isMobileUserAgent(userAgent);
const url = request.nextUrl.clone();
// 이미지와 같은 리소스는 redirect하지 않음
const isAsset = url.pathname.match(/\.(png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/);
if (isAsset) {
return NextResponse.next();
}
if (isMobile && url.pathname.startsWith('/v2')) {
// 모바일 디바이스일 때 '/v2' 경로 제거
url.pathname = url.pathname.replace(/^\/v2/, '');
return NextResponse.redirect(url);
} else if (!isMobile && !url.pathname.startsWith('/v2')) {
// PC 디바이스일 때 '/v2' 경로 추가
url.pathname = `/v2${url.pathname}`;
return NextResponse.redirect(url);
}
return NextResponse.next();
}
// config의 matcher를 설정하여 정규식을 허용하므로 부정 예측 또는 문자 일치와 같은 일치가 지원됩니다.
export const config = {
matcher: ['/((?!_next|api|favicon.ico).*)'],
};
- config의 matcher의 부정 예측으로 _next(빌드된 파일이 존재하는 곳), api, favicon.ico를 제외한 나머지 요청에 대해서 미들웨어를 실행합니다
- isMobileUserAgent함수에서 요청 헤더의 user-agent를 검사해서 모바일인지 아닌지 확인합니다
- isAsset으로 이미지 같은 정적 파일을 요청하는 경우 아무 동작없이 종료합니다
- 이슈의 내용과 같이 모바일인 경우 기존 앱 경로를 보여주고 PC로 접속 시 v2 앱 경로의 앱을 보여줍니다