이슈
- 모바일로 접속할 때와 PC로 접속할 때 다른 화면을 보여줘야한다
- 모바일로 접속 시 기존 앱 경로를 보여주고
- PC로 접속 시 v2 앱 경로를 보여준다
해결
- Next.js의 middleware를 사용하여 모바일로 접속했는지 PC로 접속했는지 확인 후 의도한 화면의 경로로 redirect 시켰다
export function isMobileUserAgent(userAgent: string): boolean {
const mobileRegex = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
return mobileRegex.test(userAgent);
}
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { isMobileUserAgent } from 'utils/mobile';
export function middleware(request: NextRequest) {
const userAgent = request.headers.get('user-agent') || '';
const isMobile = isMobileUserAgent(userAgent);
const url = request.nextUrl.clone();
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')) {
url.pathname = url.pathname.replace(/^\/v2/, '');
return NextResponse.redirect(url);
} else if (!isMobile && !url.pathname.startsWith('/v2')) {
url.pathname = `/v2${url.pathname}`;
return NextResponse.redirect(url);
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!_next|api|favicon.ico).*)'],
};
- config의 matcher의 부정 예측으로 _next(빌드된 파일이 존재하는 곳), api, favicon.ico를 제외한 나머지에 대해서 미들웨어를 실행합니다
- isMobileUserAgent함수에서 요청 헤더의 user-agent를 검사해서 모바일인지 아닌지 확인합니다
- isAsset으로 이미지 같은 정적 파일을 요청하는 경우 아무 동작없이 종료합니다
- 이슈의 내용과 같이 모바일인 경우 기존 앱 경로를 보여주고 PC로 접속 시 v2 앱 경로의 앱을 보여줍니다
Next.js의 middleware
- Next.js에서 루트 디렉토리에 middleware.ts 파일을 만들어서 미들웨어를 설정할 수 있다
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: '/about/:path*',
}
- 이 미들웨어는 /about 경로 및 하위 경로로 들어오는 모든 요청을 /home으로 리디렉션합니다.
중첩 미들웨어
- 경로마다 미들웨어를 두는 것 같은 중첩 미들웨어는 허용되지 않는다
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith('/about')) {
}
if (request.nextUrl.pathname.startsWith('/dashboard')) {
}
}
- 대신 위와 같이 특정 경로에서만 실행할 코드를 작성할 수 있다