NextJS

SSAD·2023년 2월 10일
0

FrontEnd

목록 보기
1/1

NextJS 13.1.6


00 Introduction

00 Welcome

NEXT.JS docs


01 Creating a Project

	yarn create next-app




01 FRAMEWORK OVERVIEW

00 Library VS Framework

  • 주요 차이점 : 통제의 역전(Inversion of Control)

  • 라이브러리 : 메서드를 호출하면 사용자가 제어
    예) 사용자가 파일 이름이나 구조 등을 결정, 모든 결정을 내림

  • 프레임워크 : 제어가 역전되어 프레임워크가 사용자를 호출
    예) 파일 이름이나 구조 등을 정해진 규칙에 따라 만들고 따름


01 Pages

  1. pages 폴더 안에 있는 파일명에 따라 route가 결정
    • pages/index.js 생성 : localhost:3000
    • pages/about.js 생성 : localhost:3000/about
  2. 컴포넌트 이름이 아닌 파일명을 기준으로 route 생성
    • export default function 설정한 경우만

예외 : index.js 의 경우 localhost:3000/index가 아닌 localhost:3000 이다.


02 Static Pre Rendering

SPA와 SSR의 단점을 해결하기 위해서
리액트에 서버사이드렌더링 기능을 더하여 SPA와 SSR의 장점을 가짐

리액트에 SSR 기능을 추가하려면
웹 서버를 만들어 주어야 하고, 웹팩 설정, 데이터 로딩, 코드 스플리팅 등 복잡한 과정을 필요

Next.js를 통해 이러한 것들을 설정하지 않고 사용

  1. Client-Side-Rendering

    • SPA로 클라이언트 사이드에서 HTML을 반환한 후에
      JS가 동작하면서 데이터만을 주고 받아서 클라이언트에서 렌더링을 진행하는 것

    • 동작과정

      1. HTML 다운로드
      2. JS 다운로드
      3. JS 실행
      4. DATA 서버로부터 받기
      5. Content 확인가능
    • CSR의 장점

      • 필요한 부분만 다시 읽어들이기때문에 SSR 보다 조금 더 빠른 인터랙션이 가능
      • page 전체를 요청하지 않고 페이지에 필요한 부분만 변경
        모바일 네트워크에서도 빠른 속도로 렌더링이 가능
      • lazy loading(페이지 로딩 시 중요하지 않은 리소스의 로딩을 늦추는 기술)을 지원해줌
        (Ex. 스크롤 내려야만 해당 이미지 보이게 하는 것)
      • 서버사이드 렌더링이 따로 필요하지 않기때문에 일관성있는 코드를 작성할 수 있음
    • CSR의 단점

      • Googlebot과 Searchconsole에 검색 노출이 되지 않음
        (브라우저가 없기때문에 html만 가져와서 검색에는 뜨지 않음)
      • 자바스크립트를 읽은 후 화면을 그리는 시간까지 모두 마쳐야 콘텐츠가 사용자에게 보여지기 때문에 초기구동 속도가 느림
  2. Server-Side-Rendering

    • 서버에서 렌더링을 작업하는 렌더링 방식

    • 전통적인 웹 어플리케이션 렌더링 방식
      사용자가 웹 페이지에 접근 서버에 각각의 페이지에 대한 요청
      서버에서 html, js 파일 등을 다 다운로드해서 화면에 렌더링하는 방식

    • SSR의 장점

      • 사용자가 처음으로 컨텐츠를 볼 수 있는 시점을 앞당길 수 있음
      • 검색엔진최적화(SEO) 적용이 용이
    • SSR의 단점

      • 필요한 부분만 수정하지 않고 완전히 새페이지를 로딩후 렌더
      • CSR보다 느림
      • bandwitdh를 많이 사용
      • 사용자 경험 좋지 않음
  3. Hydration

    • SSR에서 데이터가 클라이언트(react.js) DOM과 결합하는 과정

03 Routing

  1. Link from next/link
    • react.js react-router-dom 설치해줄 필요없음
import Link from "next/link";
import { useRouter } from "next/router";

export default function NavBar() {
  // Nextjs의 router hook
  const router = useRouter();

  return (
    <nav>
      <Link
        href="/"
        style={{ color: router.pathname === "/" ? "red" : "blue" }}
      >
        Home
      </Link>
      <Link
        href="/about"
        style={{ color: router.pathname === "/about" ? "red" : "blue" }}
      >
        About
      </Link>
    </nav>
  );
}

04 CSS Modules

  1. name.module.css

    • 일반적으로 적는 ccs 양식과 같이 작성

    • 임포트시켜서 사용

    • 다른 컴포넌트에서 동일 클래스 이름을 사용할 수 있음

    • Adding Component-Level CSS
      Next.js는[name].module.css 파일 명명 규칙을 사용하여 CSS Module을 지원

.link {
  text-decoration: none;
}

.active {
  color: tomato;
}
import Link from "next/link";
import { useRouter } from "next/router";
import styles from "./NavBar.module.css";

export default function NavBar() {
  const router = useRouter();

  return (
    <nav>
      <Link
        href="/"
        className={`${styles.link} ${
          router.pathname === "/" ? styles.active : ""
        }`}
      >
        Home
      </Link>
      <Link
        href="/about"
        className={[
          styles.link,
          router.pathname === "/about" ? styles.active : "",
        ].join(" ")}
      >
        About
      </Link>
    </nav>
  );
}

적용


05 Styles JSX

import Link from "next/link";
import { useRouter } from "next/router";

export default function NavBar() {
  const router = useRouter();

  return (
    <nav>
      <Link href="/" legacyBehavior>
        <a className={router.pathname === "/" ? "active" : ""}>Home</a>
      </Link>
      <Link href="/about" legacyBehavior>
        <a className={router.pathname === "/about" ? "active" : ""}>About</a>
      </Link>
      <style jsx>{`
        nav {
          background-color: tomato;
        }
        a {
          text-decoration: none;
        }
        .active {
          color: yellow;
        }
      `}</style>
    </nav>
  );
}

Built-In CSS Support (내장 CSS 지원)

  • Next.js를 사용하면 JavaScript 파일에서 CSS 파일을 가져올 수 있음

  • Next.js가 import 개념을 JavaScript 이상으로 확장

  • CSS-in-JS 격리된 범위 CSS에 대한 지원을 제공하기 위해 styled-jsx를 번들로 제공


06 Custom App

Next.js는 App 컴포넌트를 사용하여 page를 초기화
재정의 후 페이지 초기화를 제어

  1. 페이지 변경 간에 레이아웃 유지
  2. 페이지 탐색 시 state 유지
  3. componentDidCatch를 사용한 Custom 에러 처리
  4. 페이지에 추가 데이터 삽입
  5. Global CSS 추가

기본 App을 재정의하려면 아래와 같이 ./pages/_app.js 파일을 만듬

export default function MyApp({ Component, pageProps }) {
return < Component {...pageProps} />
}

https://nextjs.org/docs/advanced-features/custom-app

_app.js

import "@/styles/globals.css";

import NavBar from "@/components/NavBar";

export default function App({ Component, pageProps }) {
  return (
    <>
      <NavBar />
      <Component {...pageProps} />
      <style gsx global>{`
        a {
          color: white;
        }
      `}</style>
    </>
  );
}


02 PRACTICE PROJECT

00 Patterns

layout Pattern

  • children - reactjs 제공하는 prop
    하나의 component를 또 따른 component안에 넣을 때 사용

head component

  • Next.js 제공 앱 Head 부분을 관리


01 Fetching Data

import Seo from "@/components/Seo";
import { useEffect, useState } from "react";

const API_KEY = "xxxxxxxxxxx";

export default function Home() {
  const [movies, setMovies] = useState();

  useEffect(() => {
    (async () => {
      const { results } = await (
        await fetch(
          `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`
        )
      ).json();
      setMovies(results);
    })();
  }, []);
  return (
    <div>
      <Seo title="Home" />
      {!movies && <h4>Loading...</h4>}
      {movies?.map((movie) => (
        <div key={movie.id}>
          <h4>{movie.original_title}</h4>
        </div>
      ))}
    </div>
  );
}

IIFE 즉시 실행 함수 표현 ()()

  • 첫 괄호 익명함수를 감싸 실행 될 함수가 전역 스코프에 불필요한 변수를 추가하거나
    내부 안으로 다른 변수들 접근하는 것을 막을 수 있는 방법

  • 두번째 괄호 즉시 실행 함수를 실행

  • 함수를 즉시 해석 실행


02 Redirect and Rewrite

next.config.js

  • Next.js에서 커스텀 설정을 하기 위해서 프로젝트 디렉터리의 루트에
    next.config.js 또는 next.config.mjs 파일을 만들 수 있음

  • next.config.js는 JSON 파일이 아닌 일반 Node.js 모듈

  • Next.js 서버 및 빌드 단계에서 사용
    브라우저 빌드에는 포함되지 않음

1. Redirects (URL변경됨)


  • Redirect을 사용하면 들어오는 request 경로를 다른 destination 경로로 Redirect 함

  • Redirect을 사용하려면 next.config.js에서 redirects 키를 사용

  • Redirects은 새 페이지로 reroute되고 URL 변경 사항을 표시

  • Redirects은 source, destination 및 permanent 속성이 있는 객체를 포함하는 배열을 반환하는 비동기 함수

    • source : 들어오는 request 경로 패턴 (request 경로)

    • destination: 라우팅하려는 경로 (redirect할 경로)

    • permanent

      • true인 경우 클라이언트와 search 엔진에
        redirect를 영구적으로 cache하도록 지시하는 308 status code를 사용
      • false인 경우 일시적이고 cache되지 않은 307 status code를 사용

2. Rewrites (URL변경되지 않음)


  • Rewrites를 사용하면 들어오는 request 경로를 다른 destination 경로에 매핑
  • Rewrites은 URL 프록시 역할
  • destination 경로를 mask하여 사용자가 사이트에서 위치를 변경하지 않은 것처럼 함

03 Server Side Rendering

  1. getServerSideProps
  • page에서 서버 측 랜더링 함수인 getServerSideProps함수를 export하는 경우
    Next.js는 getServerSideProps에서 반환된 데이터를 사용하여
    각 request에서 이 페이지를 pre-rendering을 함
  • getServerSideProps는 서버 측에서만 실행되며 브라우저에서는 실행되지 않음
  1. getServerSideProps를 사용하여 request시 데이터 fetch하기

index.js

export default function Home({ data }) {
// 데이터 랜더링
}

// 매 request마다 실행됩니다.
export async function getServerSideProps() {
  const res = await fetch(`https://.../data`);
  const data = await res.json();

  // props를 통해 page에 data전달
  return { 
    props: {
      data 
    	} 
	}
}

04 Dynamic Routes

  1. Dynamic Routes
  • page에 대괄호([param])를 추가 Dynamic Route를 생성

  • /movies/1, /movies/abc 등과 같은 모든 경로는 pages/movies/[id].js와 일치

const router = useRouter()
const { id } = router.query
  1. Catch all routes
  • 대괄호 안에 세 개의 점(...)을 추가하여
    모든 경로를 포착하도록 Dynamic Routes를 확장할 수 있음

  • pages/movies/[...id].js는 /movies/1와 일치하지만
    /movies/1/2
    /movies/1/ab/cd
    등과도 일치

  • 일치하는 매개변수는 페이지에 쿼리 매개변수로 전송
    항상 배열이므로 /movies/a 경로에는 다음 쿼리 개체가 있음
    ex) { "id": ["a"] }




05 Movie Detail

router.push(url, as, options)

  • 클라이언트 측 전환을 처리

  • 이 방법은 next/link가 충분하지 않은 경우에 유용

  • url: UrlObject | String: 탐색할 URL

  • as: UrlObject | String: 브라우저 URL 표시줄에 표시될 경로에 대한 선택적 데코레이터

router.push({
pathname: '/post/[pid]',
query: { pid: post.id },
})
  • 외부 URL에 대해서는 router.push()를 사용할 필요가 없음
    window.location을 사용하는 것이 더 적합

  • next/link 도 사용방법이 동일
    아래 코드 참조

index.js

import Seo from "@/components/Seo";
import Link from "next/link";
import { useRouter } from "next/router";

export default function Home({ results }) {
  const router = useRouter();

  // router.push 
  const onClick = (id, title) => {
    router.push(
      {
        pathname: `/movies/${id}`,
        query: {
          title,
        },
      },
      `/movies/${id}`
    );
  };

  return (
    <div className="container">
      <Seo title="Home" />
      {results?.map((movie) => (
        <div className="movie" key={movie.id}>
          // Link
          <Link 
            href={{
              pathname: `/movies/${movie.id}`,
              query: {
                title: movie.original_title,
              },
            }}
            as={`/movies/${movie.id}`}
          >
            <img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`} />
          </Link>
          <h4 onClick={() => onClick(movie.id, movie.original_title)}>
            {movie.original_title}
          </h4>
        </div>
      ))}
      <style jsx>{`
        .container {
          display: grid;
          grid-template-columns: 1fr 1fr;
          padding: 20px;
          gap: 20px;
        }
        .movie {
          cursor: pointer;
        }
        .movie img {
          max-width: 100%;
          border-radius: 12px;
          transition: transform 0.2s ease-in-out;
          box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
        }
        .movie:hover img {
          transform: scale(1.05) translateY(-10px);
        }
        .movie h4 {
          font-size: 18px;
          text-align: center;
        }
      `}</style>
    </div>
  );
}

export async function getServerSideProps() {
  const { results } = await (
    await fetch(`http://localhost:3000/api/movies`)
  ).json();

  return {
    props: {
      results,
    },
  };
}

06 404Pages



profile
learn !

0개의 댓글