최근 진행중인 프로젝트에서 url에 검색 키워드를 포함시켜 SEO를 최적화하는 작업을 진행해야했다.
기존 : {base_url}/real-estate/{agency_id}
변경 : {base_url}/real-estate/{agency_id}/{agency_seo_key}
ex) https://develop.com/real-estate/1/000공인중개사사무소-서울시강남구-000
기존에도 url에 id와 name 부가정보를 함께 담는 방법을 고려한 적이 있었다.
리뷰 작성페이지는 리뷰 작성 API를 호출하기 위한 공인 중개사 ID 값과 화면에 표시할 공인중개사 name 값이 필요하다.
이를 위해 URL의 path와 query에서 값을 파싱하여 사용했다.
ex) reviews/new/1?n=00공인중개사사무소
그러나 이러한 방식은 다음과 같은 문제점으로 인해 url에 id만 담는 방식으로 변경되었다.
1. 공인 중개사에 대한 정보가 불필요하게 중복되어 담겨있고
2. id나 name 값을 URL로 조작시 에러가 발생할 수 있다.
위의 문제점의 1번은 SEO 개선을 위해 수행되어야 하는 작업으로 의문점이 해결되었다.
2번을 해결하기 위해 다른 사이트를 참고해보았더니 id에 따라 name이 변경되며 redirect가 발생하고 있었다.
예를 들어 id가 1인 공인중개사는 000공인중개사사무소-서울시강남구-000
라는 seo key를 가지고 있다.
하지만 사용자가 임의적으로 주소창의 id를 바꾸거나 seo key를 바꾸는 경우가 생길 수 있다.
ex)
정상적인 url
https://develop.com/real-estate/1/000공인중개사사무소-서울시강남구-000
id를 변경한 url
https://develop.com/real-estate/10/000공인중개사사무소-서울시강남구-000
seo key를 변경한 url
https://develop.com/real-estate/1/000공인중개사사무소-용인시수지구-000
Catch-all Segments
우선 id 뒤의 path가 붙어도 detail 페이지를 렌더링하므로 파일 이름을 catch-all segements를 사용해 [...id.tsx]
로 변경한다.
[id.tsx]
real-estate/1
(O)real-estate/1/000공인중개사무소
(X)[...id.tsx]
real-estate/1
(O)real-estate/1/000공인중개사무소
(O)middleware
Next는 middleware를 사용해 네트워크 요청을 가로채고 응답을 받기 전 redirect 시킬 수 있다.
root 디렉토리(/src
)에 middleware.ts
를 생성하고 다음 로직을 작성한다.
request url의 pathname 중에 id와 seo key를 파싱한다.
id를 이용해 API 요청으로 올바른 seo key를 얻는다.
request url의 seo key와 API 응답으로 얻은 seo key가 같지 않은 경우 올바른 seo key의 url로 리다이렉트 한다.
import { NextResponse, type NextRequest } from 'next/server'
import { getRealEstateData } from './apis/realEstateApis'
export const middleware = async (request: NextRequest) => {
const [_x, _y, id, seo_key] = decodeURI(request.nextUrl.pathname).split('/')
const agencyData = await getRealEstateData(Number(id))
if (agencyData.seo_key !== seo_key) {
return NextResponse.redirect(new URL(`/real-estate/${id}/${agencyData.seo_key}`, request.url))
}
}
export const config = {
matcher: '/real-estate/:id*',
}
네트워크 요청을 가로채서 잘못된 url 주소인 경우 리디렉션을 한다.
이를 통해 원하는 응답 리소스를 시간 낭비없이 빠르게 얻을 수 있다.