본문 바로가기

NotionAPI로 블로그 만들기 (3) Next.js App Router 미들웨어로 redirection 설정하기

NotionAPI로 블로그 만들기 (3) Next.js App Router 미들웨어로 redirection 설정하기
Next.js의 App Router에서의 react-notion-x 라이브러리 적용기입니다. 
+ 다국적 언어 지원 라이브러리인 react-i18next 함께 사용하고 있습니다. 

* 23.10.25 : 현재는 모노레포 구축 후 nextjs-notion-starter-kit으로의 라이브러리 교체가 되었습니다.

 

문제상황

  • react-notion-x는 상세페이지 클릭시 자동으로 /{pageId} 경로로 redirection시킨다.
  • 나의 경우는 경로에 동적 언어 라우팅도 포함되고 있었기 때문에 /[lng]/{pageId} 이런 식으로 경로가 설정되어야만 했다.
    • lng는 en(영어), ko(한국어) 2개국어 지원 
    • 따라서 /en/{pageId} 또는 /ko/{pageId} 로 이동해야 함.
  • 관련된 레퍼런스가 없음.

 

해결과정

1. next.config

처음에는 root폴더 위치에 있는 next.config.js에서 리다이렉션 설정을 해주는 것으로 문제가 간단히 해결될 줄 알았다.

  • i18n과 관련하여 nextjs 공식문서에도 redirect 속성을 이용한 config 세팅에 대해 안내가 언급되어 있기도 하기 때문이다.
  • 하지만, 내가 원하는 것은 /ko (한글 서비스 - 메인)에서 /{pageId}로 리다이렉션 시, 현재 언어 상태를 감지해서 /ko/{pageId}로 리다이렉션 시키는 것이었기 때문에 아래의 내용과는 전혀 관련이 없었다. 

 

  • 문서에 나와있는 다른 예시들 역시 비슷했으며 그나마 /{pageId}로 갔을때 현재 언어 상태와는 관련없이 한국어 서비스로만 리다이렉션 시키는 것까지는 성공했으나 그 다음에 다른 메뉴로 이동하게 되면 사이드 이펙트가 발생했다.
안 됐던 코드 예시
module.exports = {
  async redirects() {
    return [
      {
        source: '/:pageId', // 페이지 Id로 들어왔을 때
        destination: '/ko/:pageId', // 중간에 :lng 등의 동적 값 입력이 안 됐으므로 ko로 고정시키고 pageId로 이동 
        permanent: false,
      },
    ]
  },
  
  // 성공은 했으나 /ko/{pageId}에서 다시 홈으로 이동할 때 /ko만 나와야 하지만 
  // /ko/ko로 나오는 사이드이펙트 발생
}

 

 

2 SSR나 CSR에서 redirect?

  • SSR이나 CSR에서 redirect 함수를 쓰면 된다. 
  • 그러나!! 
  • 내 프로젝트에서 현재 루트 페이지가 app/[lng]/pages.tsx 였기 때문에, 상세 페이지 데이터를 받아야 하는 정상적인 라우팅 폴더구조는 app/[lng]/[pageId]/pages.tsx가 된다.
    • 즉, 아예 최상위 url이 / 가 아니라 /en 또는 /ko라는 뜻이다.
    • / 로 들어가면 저절로 디폴트 언어인 /ko로 들어가게 된다.
  • 그러나 노션 상세페이지 url은 /{pageId}로 app/[pageId]/pages.tsx로 들어가고 있었다.
  • 따라서 애초에 리다이렉션을 시키려면 라우팅 구조에 맞게 pages.tsx파일이 위치해서 데이터를 만져야 하는데 루트 폴더가 app/[lng]였으므로 노션이 자동으로 링크시키는 url로는 데이터가 아예 들어가지 않는 구조적 문제가 있었다. 

 

3. 📌 미들웨어 사용하기

  • 결론적으로 middleware를 사용하여 해결했다! (공식문서)
  • middleware은 말 그대로 중간에 실제 요청이 처리되기 전에, 어떤 작업을 하는 것으로 헤더를 수정하거나, 쿠키 생성 및 삭제, 리다이렉션 등 다양한 작업을 수행할 수 있다. 
  • 위치는 app 라우터와 동일한 위치에 생성하면 된다.

 

  • 꼭 return을 넣어야 리다이렉션이 작동된다!
middleware.ts
import { NextRequest, NextResponse } from 'next/server';

const PUBLIC_FILE = /\.(.*)$/;

export function middleware(req: NextRequest) {
  if (
    req.nextUrl.pathname.startsWith('/_next') ||
    req.nextUrl.pathname.includes('/api/') ||
    PUBLIC_FILE.test(req.nextUrl.pathname)
  )
    return;

  const supportedLocales = ['ko', 'en'];
  
  // url 경로에 ko, en이 없으면 
  if (!supportedLocales.some((locale) => req.nextUrl.pathname.includes(locale))) {
 
 	// 쿠키에 저장되어 있는 최근 언어 상태를 가져와서 
 	const locale = req.cookies.get('i18next')?.value || 'ko';

    // 의도한 url 경로로 리다이렉션 시키면 된다.  
    return NextResponse.redirect(
      new URL(`/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url),
    );
  }
}

 

작동 확인

아래와 같이 서버에서 console.log(이동 url)을 찍어보았고 /{pageId}에 현재 언어 상태가 한국어면 /ko/{pageId}로 리다이렉션 시키는 것을 확인했다. 

 

참고 

 

 

728x90
⬆︎