[NextJS] Layout에서 현재 주소 url 구하기 + query 추출하기

Hwanhoon KIM·2023년 10월 18일

Next JS에서 query params를 구하는 것은 page에서 한다면 쉽게 할 수 있다. 하지만 왜인지는 모르겠지만, layout에서는 그게 불가능 하다. 그래서 미들웨어를 이용하여 query params을 구하는 함수를 만들어서 공유하고자 한다.

순서

  1. 현재 url을 구한다. (미들웨어 사용)
  2. 원하는 query를 구할 수 있는 함수를 만든다.

크게보면 이런 순서이다.

가장 쉬운 첫 번째는 미들웨어로 req의 url을 받아서 headers에 붙여 보내주는 것이다.

1. 현재 url을 구한다. (미들웨어 사용)

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';

export async function middleware(req: NextRequest) {
  const requestHeaders = new Headers(req.headers);
  requestHeaders.set('x-url', req.url);
  return NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });
}

// matcher는 원하는 데로 설정 한다.
export const config = {
  matcher: ['/:path*'],
};

2. 원하는 query를 구할 수 있는 함수를 만든다.

나는 함수형 프로그래밍을 지향하기 때문에 다음과 같은 코드를 만들었다.

// url = 'http://localhost:3000/tours/title?ref=100&ref2=200&ref3=300'

const divideQueryByQuestionMark = (url: string) => url.split('?')[1];
const divideEachQueries = (stringQueryParams: string): string[] =>
  stringQueryParams.split('&');
const queryParamsResult = (eachQueries: string[]) =>
  eachQueries.map(query => {
    const queryKey = query.split('=')[0];
    const queryValue = query.split('=')[1];
    return { [queryKey]: queryValue };
  });

// returns [{ ref = '100' },{ ref2 = '200' },{ ref3 = '300' }]
export const getQueryParams = (url: string) => {
  const stringQueryParams: string = divideQueryByQuestionMark(url);
  const eachQueries = divideEachQueries(stringQueryParams);
  const result = queryParamsResult(eachQueries);
  return result;
};

//
//
//

interface QueryParams {
  [key: string]: string;
}

interface Params {
  query: string;
  queryParams?: Array<QueryParams>;
  fullUrl?: string;
}

export const searchQueryParams = ({ query, queryParams, fullUrl }: Params) => {
  if (queryParams) {
    const queryKeys = queryParams.map(keyValuePair => {
      const keys = Object.keys(keyValuePair); // ['ref']
      const values = Object.values(keyValuePair); // ['1']
      if (!keys.includes(query)) {
        return;
      } else {
        const targetIndex = keys.findIndex(key => key === query);
        const result = values[targetIndex];
        return result;
      }
    });
    const excludePossibleUndefined = queryKeys.filter(el => el !== undefined);
    return excludePossibleUndefined[0];
  } else if (fullUrl) {
    const queryParams = getQueryParams(fullUrl);
    const result: unknown = searchQueryParams({
      queryParams,
      query,
    });
    return result;
  } else {
    return undefined;
  }
};

//를 기준으로 위 부분과 아래 부분으로 나뉘어 지는데, 하다 보니까 아래의 searchQueryParams함수를 사용함을 목적으로 아래는 새로 만들었다. 즉, searchQueryParams()함수에 인자로 원하는 queryParam의 이름을 적고, url을 적으면 그 queryParams의 값을 리턴하는 함수이다.

예를들어 const url = http://localhost:3000/tours/title?ref=100&ref2=200&ref3=300가 있다고 할 때,

searchQueryParams({query: 'ref3', fullUrl: url})
을 적으면 리턴값으로 300이 나오는 개념이다.

profile
Fullstack Developer, I post about HTML, CSS(SASS, LESS), JavaScript, React, Next, TypeScript.

0개의 댓글