미주알고주알

Next.js에서 url 바꾸는 방법 3가지 본문

Next.js

Next.js에서 url 바꾸는 방법 3가지

미주알고주알 2023. 2. 16. 23:10

1. `location.replace()` 메소드 사용하기

`location.replace()` 메소드는 현재 문서를 다른 문서로 대체(replace)하는 역할을 한다. 이 메소드는 브라우저의 `Location` 객체의 메소드 중 하나로, 현재 문서의 위치를 변경한다.

 

`location.replace()` 메소드를 호출하면, 브라우저는 현재 페이지를 새로운 문서로 대체한다. 이 때 브라우저의 히스토리(history) 스택에서 현재 페이지 이후의 모든 페이지를 제거하고, 새로운 페이지를 히스토리 스택의 맨 위에 삽입한다. 이렇게 하면 사용자가 뒤로가기 버튼을 눌렀을 때 이전 페이지로 돌아가는 것이 불가능진다. 따라서 `location.replace() `메소드는 이전 페이지로 돌아갈 필요가 없는 경우에 사용하는 것이 좋다.

 

location.replace(url)
// 📌 여기서 url은 대체할 새로운 문서의 URL로, url 인자는 반드시 문자열 형태로 전달되어야 함

location.replace("https://www.example.com")
 

2. `next/link`의 Link 컴포넌트 사용하기

`next/link` 라이브러리는 Next.js에서 클라이언트 측 라우팅을 가능하게 해주는 라이브러리이다. 이 라이브러리를 사용하면 페이지 전환 시 브라우저의 새로고침 없이도 페이지 전환이 가능하고, 성능 개선에도 도움을 줄 수 있다.

 

`next/link` 에서 Link 컴포넌트를 사용하여 페이지 이동을 처리할 수 있는데, Link 컴포넌트는 href prop으로 이동할 페이지의 경로를 전달받는다. 이때, 전달되는 값은 문자열 형태의 URL 경로를 나타낸다.

 

예를 들어, 다음과 같이 Link 컴포넌트를 사용하여 ` /about` 경로로 이동하는 링크를 생성할 수 있다.

 

import Link from 'next/link';

function MyComponent() {
  return (
    <Link href="/about">
      <a>About Me</a>
    </Link>
  );
}

위 코드에서 Link 컴포넌트는 `/about` 경로로 이동하는 링크를 생성하며, 이동할 페이지의 경로는 href prop으로 전달된다. 이때 `a` 태그는 클릭 가능한 링크를 나타내며, Link 컴포넌트는 클릭 이벤트를 처리하여 이동할 페이지로 이동한다.

 

3. `next/router`의  useRouter 훅 사용하기

`next/router`라이브러리 역시 Next.js에서 클라이언트 측 라우팅을 처리하는데 사용되는 라이브러리이며, 이 라이브러리에서 제공하는 useRouter 훅을 통해 현재 페이지의 URL과 관련된 정보(쿼리 파라미터나 경로)를 알 수 있다.

 

또한 `router.push() `등의 메서드를 호출해 브라우저의 새로고침 없이도 주어진 경로로 페이지 이동시킬 수도 있다. 이때, Next.js는 브라우저의 history API를 사용하여 페이지 전환을 처리하므로, 브라우저의 뒤로가기 버튼 등도 정상적으로 동작한다. 

import { useRouter } from 'next/router';

function MyComponent() {
 
  const router = useRouter(); // useRouter 훅을 실행해 router 객체를 가져와,

  return (
    <div>
      <h1>Current Path: {router.pathname}</h1>  {/* url 관련 정보를 가져올 수 있고 */}
      <button onClick={() => router.push('/about');}> {/* 페이지를 전환할 수도 있다. */} 
        Go to About Page
      </button>
    </div>
  );
}

 

이때, `router.push()` 메소드 두, 세번째의 인자를 통해 다양하게 페이지를 전환시킬 수 있다.

 

- 첫번째 인자: 앞에서 언급한 url

- 두번째 인자, as: 브라우저 주소 표시줄에 표시될 경로를 지정하는 옵션으로 실제 경로가 아닌 개발자가 원하는 경로로 바꾸어 표시할 수 있다. 

- 세번째 인자, shallow: 데이터를 새로 가져와 페이지를 렌더링하지 않고, history 스택에 새로운 url을 추가한다. 새로운 페이지가 렌더링되지 않고, 페이지의 props만 업데이트되어 현재 상태나 query를 남길 수 있다.

router.push('/about', '/myabout')
// /about이 아닌 /myabout으로 표시됨. 말 그대로 표시된다는 거지 두 주소가 호환된다는 건 아님.

router.push('/about', undefined, { shallow: true })

 

인스타그램처럼 이미지를 눌렀을 때 url은 변경되었지만 ( `/` -> `/p/xxxx`) 동일한 페이지에 모달만 추가되고, 모달이 닫힐 때 원래 url로 돌아오는 식의 url 눈속임(`/p/xxxx` -> `/`)은 이런 방법을 사용한 거 아닐까?

 

`Link` 컴포넌트를 통해서도 as와 shallow를 구현할 수 있다. `useRouter` 훅과 `Link` 컴포넌트 둘다 라우팅을 처리하는 라이브러리니까 동일/유사한 기능을 가지는 듯하다.

// pages/Home.tsx

import type { NextPage } from 'next'
import Image from 'next/image'
import Link from 'next/link'
import { useRouter } from 'next/router'
import Modal from '../components/Modal'

const Home: NextPage = ({ images }: { images: ImageProps[] }) => {
  const router = useRouter()
  const { photoId } = router.query
  
  const handleClose = () => {
    router.push("/", undefined, { shallow: true })
  }

  return (
    <>
      <main>
        { photoId && ( <Modal images={images} onClose={handleClose} /> )}
        <div>
          { images.map(({ id, src}) => (
            <Link
              key={id}
              href={`/?photoId=${id}`}
              as={`/p/${id}`}
              shallow
            >
              <Image
                src={src}
                width={100}
                height={100}
              />
            </Link>
          ))}
        </div>
      </main>
    </>
  )
}

export default Home