diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-26 00:37:41 +0000 |
| commit | e0dfb55c5457aec489fc084c4567e791b4c65eb1 (patch) | |
| tree | 68543a65d88f5afb3a0202925804103daa91bc6f /middleware.ts | |
3/25 까지의 대표님 작업사항
Diffstat (limited to 'middleware.ts')
| -rw-r--r-- | middleware.ts | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 00000000..4237bfb4 --- /dev/null +++ b/middleware.ts @@ -0,0 +1,84 @@ +/** middleware.ts */ +export const runtime = 'nodejs'; + +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; +import acceptLanguage from 'accept-language'; + +import { fallbackLng, languages, cookieName } from '@/i18n/settings'; + +acceptLanguage.languages(languages); + +export function middleware(request: NextRequest) { + /** + * 1. 쿠키에서 언어 가져오기 + */ + let lng = request.cookies.get(cookieName)?.value; + + /** + * 2. 쿠키가 없다면 브라우저의 Accept-Language 헤더에서 언어를 추론 + */ + if (!lng) { + const headerLang = request.headers.get('accept-language'); + lng = acceptLanguage.get(headerLang) || fallbackLng; + } + + const { pathname, searchParams, origin } = request.nextUrl; + + /** + * 3. "/"" 경로로 들어온 경우 -> "/{lng}"로 리다이렉트 + * (예) / -> /en, / -> /ko ... + */ + if (pathname === '/') { + const redirectUrl = new URL(`/${lng}`, origin); + // 쿼리 파라미터가 있을 경우도 붙여주기 + redirectUrl.search = searchParams.toString(); + return NextResponse.redirect(redirectUrl); + } + + /** + * 4. 현재 pathname이 언어 경로를 포함하고 있는지 확인 + * - /en + * - /en/... (다른 하위 경로들) + * - /ko + * - /ko/... + */ + const hasValidLngInPath = languages.some( + (language) => pathname === `/${language}` || pathname.startsWith(`/${language}/`), + ); + + /** + * 5. 언어 경로가 누락된 경우 -> "/{lng}" + 기존 pathname 으로 리다이렉트 + * 예) /dashboard -> /en/dashboard + */ + if (!hasValidLngInPath) { + const redirectUrl = new URL(`/${lng}${pathname}`, origin); + redirectUrl.search = searchParams.toString(); + return NextResponse.redirect(redirectUrl); + } + + /** + * 6. 위 조건에 걸리지 않았다면 그대로 Next.js로 넘긴다. + */ + const response = NextResponse.next(); + + /** + * 7. 쿠키에 저장된 언어와 현재 lng가 다르면 업데이트 + */ + const currentCookie = request.cookies.get(cookieName)?.value; + if (lng && lng !== currentCookie) { + response.cookies.set(cookieName, lng, { path: '/' }); + } + + return response; +} + +/** + * 8. (선택) 매칭할 경로 설정 + * - _next, 정적파일(.*), API 등의 경로는 제외시키는 예시 + */ +export const config = { + matcher: [ + '/((?!_next|.*\\..*|api).*)', + ], +};
\ No newline at end of file |
