게으른개발너D

Practice Project 1 - Patterns and Redirect, Rewrite 본문

개발/NextJS

Practice Project 1 - Patterns and Redirect, Rewrite

lazyhysong 2023. 11. 28. 17:30

 

1. Patterns

1.1 Layout

이제 많은 사람들이 next.js를 이용할 때 따르는 아주 흔한 패턴에 대해 공부할 것이다.

바로, custom app component를 사용할 때 쓰는 layout 패턴이다.

 

먼저, components 디렉토리 안에 Layout.js라는 component를 만들자.

// Layout.js

import NavBar from "./NavBar";

function Layout({children}) {
  return <>
    <NavBar />
    <div>{children}</div>
  </>
}

export default Layout;

 

div 안에 children을 넣어주었는데, children은 react에서 기본적으로 제공하는 prop이다.

하나의 component를 또 다른 component 안에 넣을 때 쓸 수 있다.

 

 

이전 게시글에서 다뤘던 _app.js에 NavBar 컴포넌트를 지우고 <></> fragment를 Layout component로 바꿔준다.

// _app.js

import Layout from "../components/Layout";
import "../styles/globals.css";

export default function App({Component, pageProps}) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

 

_app.js에는 global로 import 해야할 것들이 많을 것이다.

예를 들어 Google Analytics라든지, 검색엔진에 관한 무언가를 구성해 본다던가 스크립트 분석을 할 수도 있다.

그래서 아주 큰 react.js component를 사용하기보다는 Layout component에다가 만드는 것이다.

 

1.2 head component

이제 next.js에서 제공하는 head component를 사용해 볼 것이다.

 

index.js로 가서 Head를 import 하자.

create-react-app을 사용한다면 head 부분을 관리하기 위해 react-helmet을 설치해야겠지만 next.js에는 이미 이렇게 존재하고 있다.

// index.js

import Head from "next/head";

function Home() {
  return (
    <div>
      <Head>
        <title>Home | Next Moives</title>
      </Head>
      <h2>Hello</h2>
    </div>
  );
}

export default Home;

Head 컴포넌트를 쓰면 이 안에 들어가는 모든 것들이 html의 head 안에 보여질 것이다.

 

이걸 index.js에서 했으니 다음엔 about.js에도 붙여넣을 차례이다.

이렇게 일일이 Head를 복사해서 다른 모든 페이지에 붙여넣지말고 component 하나를 만들어보자.

 

components 디렉토리에 Seo.js 파일을 만든다.

// Seo.js

import Head from 'next/head';

function Seo({ title }) {
  return (
    <Head>
      <title>{title} | Next Movies</title>
    </Head>
  );
}

export default Seo;

 

이제 더 많은 props를 넣어서 head(SEO) component를 개인화 할 수 있다.

예를들어 다른 태그나 Meta Description, 작성자 같은 정보를 말이다.

 

이제 index.js, about.js에 Seo 컴포넌트를 사용하자.

// index.js

import Seo from '../components/Seo';

function Home() {
  return (
    <div>
      <Seo title="Home" />
      <h2>Hello</h2>
    </div>
  );
}

export default Home;

 

 

 

 

 

2. Fetching Data

NavBar.js를 조금 꾸며주고 이미지를 넣어주려고 한다.

next.js를 이용하면 public 파일들을 아주 쉽게 다룰 수 있다.

우리가 할 건 public 파일들을 public 디렉토리에 넣는 것 뿐이다.

 

만약 public 디렉토리에 있는 vercel.svg를 넣는다고 하면 이렇게 적어주면 된다.

<img src="/vercel.svg" />

 

../../ 이런식으로 적을 필요없이 그냥 슬러쉬 하나에 경로만 적어주면 된다!

 

이렇게만 적어주면 img 태그에 img component를 사용하지 말라는 경고창이 뜰 것이다.

대신 next image를 사용해야한다.

image component는 로컬 이미지, 원격 이미지를 사용할 때 좀 복잡해질 수도 있으니 여기서는 일단 다루지 않겠다.

 

https://nextjs.org/docs/messages/no-img-element

 

No img element

Using App Router Features available in /app

nextjs.org

 

 

2.1 API  fetching

지금부터 next.js를 이용하여 API Key를 숨기는 기능을 다뤄보려고 한다.

https://www.themoviedb.org/

여기서 api를 가져와서 간단한 앱을 만들자.

 

// index.js

import { useEffect, useState } from 'react';
import Seo from '../components/Seo';

const API_KEY = '...';

function Home() {
  const [movies, setMovies] = useState();
  useEffect(() => {
    (async () => {
      const response = await fetch(
        `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
      );
      const data = await response.json();
      const { results } = data;
      setMovies(results);
    })();
  }, []);
  
  return (
    <div className="container">
      <Seo title="Home" />
      {!movies && <h4>Loading..</h4>}
      {movies?.map((movie) => (
        <div className="movie" key={movie.id}>
          <img src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`} />
          <h4>{movie.original_title}</h4>
        </div>
      ))}
      <style jsx>{`
        // ...
      `}</style>
    </div>
  );
}

export default Home;

 

이런식으로 영화 제목과 사진을 간단히 불러오는 기능을 마쳤다.

 

 

3. Redirect and Rewrite

API를 돈주고 사용할 수도 있고 모두에게 공개하고 싶지 않을 수도 있기때문에 API Key는 숨겨줘야한다.

우리가 작업한 화면에서 개발자도구 네트워크를 보면 우리가 api로 호출한 url 전체를 볼 수 있게된다. api 키가 모두 노출된채로!!

 

그래서 request에 mask를 씌운 것 같은 redirect와 rewrite에 대해 공부할 것이다.

 

next.config.js 파일을 열자!

 

먼저, API Key를 숨기지 않는 redirect가 있다.

next.js가 redirection을 허용하기 때문이다.

npm run dev로 next.js 앱을 실행하면 terminal 창에서는 client와 server가 실햄됨이 보인다.

 

3.1 redirection

원한다면 항상 쓰는 것처럼 redirect는 할 수 있을 것이다.

// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
};

module.exports = nextConfig;

nomadcoders.co/shop

 

예를들면 아래쪽에 저렇게 주소를 쓰면 우릴 어딘가로 redirect 해줄 것이다.

 

// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  async redirects() {
    return [
      {}
    ]
  }
};

module.exports = nextConfig;

nextConfig 안에 object를 가지는 array를 반환하는 redirects 라는 함수를 써주자

 

첫번째로, source를 찾는다.

만약 유저가 contact로 갈거라면, 우리는 유저를 form이라는 destination으로 보낼 것이다.

  async redirects() {
    return [
      {
        source: "/contact",
        destination: "/form",
        permanent: false,
      }
    ]
  }

 

여기서 이 redirection이 permanent(영구적)인지 아닌지에 따라서, 브라우저나 검색엔진이 이 정보를 기억하는지 여부가 결정된다.

 

저장을 한다!

next.config.js 파일을 수정하면 서버를 재시작해줘야한다.

 

재시작한 후 http://localhost:3000/contact로 들어가보자!

결과는 /form으로 redirect 된다.

 

이제 우린 website 이내에서든 바깥으로든 redirect 할 수 있다.

 

예를들어 이렇게 바꿔줄 수도 있다.

  async redirects() {
    return [
      {
        source: "/contact",
        destination: "https://nomadcoders.co",
        permanent: false,
      }
    ]
  }

 

/contact로 들어가면 노마드코더 홈페이지로 리다이렉트 될 것이다.

 

3.2 pattern matching

next는 pattern matching 또한 지원한다.

  async redirects() {
    return [
      {
        source: "/old-blog/:path",
        destination: "/new-sexy-blog/:path",
        permanent: false,
      }
    ]
  }

 

이렇게 작성한 후 /old-blog/1234 로 들어가보면?!

/new-sexy-blog/1234 로 리다이렉트되게 된다!

뒤에 붙여준 1234같은 post id는 그대로 남고 destination으로 지정해준 부분만 변경된다!

 

만약 주소 뒤에 별표를 붙이면 모든 걸 catch 할 수도 있다.

  async redirects() {
    return [
      {
        source: "/old-blog/:path*",
        destination: "/new-sexy-blog/:path*",
        permanent: false,
      }
    ]
  }

 

/old-blog/1234/comments/1212 로 들어가면?

/new-sexy-blog/1234/comments/1212 로 리다이렉트된다.

 

 

3.3 rewrites

이번엔 rewrites를 사용해보자!

  async rewrites() {
    return [
      {
        
      }
    ]
  }

rewrites 또한 다양한 obj들이 들어가는 배열을 반환시킨다.

 

redirect는 source에서 써준 url로 갈 때, 유저는 말 그대로 URL이 바뀌는 것을 볼 수 있다.

하지만 rewrites는 유저를 redirect 시키기는 하지만 URL은 변하지 않는다.

 

예를들어 우리는 index.js에서 api 주소를 이용해서 영화 목록을 fetch했다.

하지만 api_key는 숨기고싶다.

따라서 rewrites의 source를 이렇게 쓸 것이다.

const API_KEY = "~~~";

...
 
  async rewrites() {
    return [
      {
        source: '/api/movies',
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
      }
    ]
  }

 

redirect와 비슷하긴 하지만 유저는 URL의 변화를 볼 수 없을 것이다.

즉, 유저가 API_KEY를 볼 수 없다는 뜻이다.

 

저장 후 서버를 재 시작하고, index.js에서 적었던 fetch의 주소는 /api/movies로 변경해 준다.

 

이제 재시작하면? 기존에 구현했던대로 잘 나온다!

 

개발자도구를 켜서 네크워크를 확인하면 request에는 /api/movies만 나오며 api_key가 포함된 url은 나오지 않는다.

 

 

 

 

 


출처

노마드코더

https://nomadcoders.co/nextjs-fundamentals/

 

All Courses – 노마드 코더 Nomad Coders

초급부터 고급까지! 니꼬쌤과 함께 풀스택으로 성장하세요!

nomadcoders.co

 

Comments