본문 바로가기

카테고리 없음

Nextjs 튜토리얼 핵심내용 정리 및 요약

반응형

튜토리얼 완성본 구경하기 (해당 페이지는 홈이 아닌 404로 연결하게 해둠) 

404 not found (nextjs-emotion-typescript-blog.vercel.app)

 

 

리액트를 사용하여 웹 애플리케이션을 만들려면 고려할 사항들

  • 컴파일러 / 번들러
  • 코드 스플리팅
  • 프리렌더링 / SSG / SEO / SSR or CSR
  • API

With Next.js

  • 페이지 기반 라우팅 시스템
  • 프리 렌더링 / SSG / SSR / CSR
  • 자동 코드 분할
  • 내장 CSS/ SaSS 지원. CSS-in-JS 라이브러리 지원
  • Fest Refresh 지원
  • API 호출 가능 (노드임)
  • 완전히 확장 가능

타입스크립트와 함께 사용하기

import { GetStaticProps, GetStaticPaths, GetServerSideProps } from 'next'

export const getStaticProps: GetStaticProps = async context => {
  // ...
}

export const getStaticPaths: GetStaticPaths = async () => {
  // ...
}

export const getServerSideProps: GetServerSideProps = async context => {
  // ...
}

import { NextApiRequest, NextApiResponse } from 'next'

export default (req: NextApiRequest, res: NextApiResponse) => {
  // ...
}

import { AppProps } from 'next/app'

function App({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}

export default App
  • <a> tag를 <Link> tag로 감싸면 클라이언트 사이드 라우팅이 가능함
  • 또한 Next.js의 프로덕션 빌드에서 Link 구성 요소가 브라우저의 뷰포트에 나타날 때마다 Next.js는 백그라운드에서 연결된 페이지의 코드를 자동으로 프리 페치합니다.
  • 참고 : Next.js 앱 외부의 외부 페이지에 연결해야하는 경우 Link없이 태그를 사용하면됩니다.
import Link from 'next/link'

<h1 className="title">
  Learn <a href="https://nextjs.org">Next.js!</a>
</h1>

// >>> 

<h1 className="title">
  Read{' '}
  <Link href="/posts/first-post">
    <a>this page!</a>
  </Link>
</h1>

 

next/image 는 Resizing & optimizing 을 간소화해줌

import Image from 'next/image'

const YourComponent = () => (
  <Image
    src="/images/profile.jpg" // Route of the image file
    height={144} // Desired size with correct aspect ratio
    width={144} // Desired size with correct aspect ratio
    alt="Your Name"
  />
)
  • 레이아웃 컴포넌트
    • children을 감쌈
import Head from 'next/head'
import Link from 'next/link'
import Layout from '../../components/layout'

export default function FirstPost() {
  return (
    <Layout>
      <Head>
        <title>First Post</title>
      </Head>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </Layout>
  )
}

const Container = styled.div`
  max-width: 36rem;
  padding: 0 1 rem;
  margin: 3rem auto 6rem;
`;
  • Next.js는 styled-jsx 지원 내장. styled-componentemotion 미지원
    • .babelrc 설정 필요
  • 글로벌 스타일
    • pages/_app.js 파일을 만든다.
      • 전역 스타일은 여기서만 적용 가능하다.
    • 해당 프로젝트는 emotion을 사용하여 글로벌 스타일을 설정한다.
import { AppProps } from 'next/app';
import { globalStyles } from '../shared';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      {globalStyles}
      <Component {...pageProps} />
    </>
  );
  • toggle class에 classnames 활용하기
    • 좋은지 모르겠음. 난 그냥 emotion 쓰고싶음
import styles from './alert.module.css'
import cn from 'classnames'

export default function Alert({ children, type }) {
  return (
    <div
      className={cn({
        [styles.success]: type === 'success',
        [styles.error]: type === 'error'
      })}
    >
      {children}
    </div>
  )
}

css`
.success {
  color: green;
}
.error {
  color: red;
}
`
  • 프리렌더링
    • 미리 페이지를 그려 클라이언트에 제공함
    • 클라이언트 사이드 렌더링과 달리 만들어진 페이지가 제공됨.
    • SEO와 성능에 좋음
      • 코드 스플리팅
        • 각각의 페이지는 해당 페이지에 딱 필요한 최소 자바스크립트 코드와 같이 전달됨.
        • 브라우저에서 페이지를 로드하면 해당 JavaScript 코드가 실행되고 페이지가 인터랙티브 하게 됨. (이 과정을 수화라고 함.)

<Link/>는 클라이언트 사이드 라우팅을 가능하게 해주는 요소
페이지별 정적 HTML 문서를 제공하는 nextjs와 달리 일반 React 앱은 탬플릿 html 하나만 사용한다

  • 프리렌더링의 종류
    • 스태틱 사이트 제너레이션
      • 빌드 타임에 페이지를 HTML로 만들어 계속 재사용함
        • 딱봐도 성능에 좋을것같음
    • 서버사이드 렌더링
      • 매 요청마다 페이지를 만들어서 HTML로 클라이언트에 넘겨줌
        • SEO에는 좋은데 CSR보다 성능에는 안좋다함.
        • 꼭 필요한 부분만 해주는게 좋음

스태틱 제너레이션은 한 번 만든 페이지를 계속 재사용한다
서버사이드 렌더링은 요청마다 HTML을 새로 만들어 제공한다
페이지 별로 전략을 다르게 가져갈 수 있음

 

You can use Static Generation for many types of pages, including:

  • Marketing pages
  • Blog posts
  • E-commerce product listings
  • Help and documentation

사용자 요청 전에 페이지를 미리 만들어 둘 수 있으면 스태틱 제너레이션이 좋음

항상 최신이어야 하면 CSR / SSR 사용

외부 데이터 없이 그냥 정적 HTML을 제공하는 경우
getStaticProps를 사용하면 Next.js에 해당 페이지에 데이터 종속성이 있음을 알릴 수 있음

 

  • nextjs도 노드라서 외부에서 data fetch 해오기 가능
    • 직접 디비에서 쿼리하는것도 가능함
  • getStaticProps 은 오직 서버에서만 동작함
// 서버에서 데이터 떙겨오기
export async function getSortedPostsData() {
  // Instead of the file system,
  // fetch post data from an external API endpoint
    // Next.js polyfills fetch() on both the client and server. You don't need to import it.
  const res = await fetch('..')
  return res.json()
}

// 디비에서 직접 쿼리 가능
import someDatabaseSDK from 'someDatabaseSDK'

const databaseClient = someDatabaseSDK.createClient(...)

export async function getSortedPostsData() {
  // Instead of the file system,
  // fetch post data from a database
  return databaseClient.query('SELECT posts...')
}
  • 요청 전에 미리 만들어 재사용이 불가능하면 SSR 을 사용하면 됨
export async function getServerSideProps(context) {
  return {
    props: {
      // props for your component
    }
  }
}
  • CSR을 언제 쓰나요?
    • SEO와 관계없는 비공개 사적인 유저 페이지 (dashboard)
  • 다이나믹 라우팅
    • /posts/ 경로에 각각 페이지 포스팅
    • id는 마크다운 파일명

param.id를 통해 해당 페이지에 맞는 데이터를 불러와 페이지를 생성한다
위 내용 요약

  • 정리
    • getStaticPaths로 params.id를 만들어준다.
    • getStaticProps로 parameter를 받아 해당 경로 컨텐츠를 정적 생성한다.
    • getStaticProps를 사용하여 ID가 지정된 특정 게시물을 가져오고getStaticPaths를 사용하여 가능한 모든 블로그 게시물을 가져옵니다.
import Layout from '../../components/layout'

export default function Post() {
  return <Layout>...</Layout>
}
// 해당 페이지 경로(id) 지정하기
export async function getStaticPaths() {
  // Return a list of possible value for id
}
// 딱 한번 만들어 정적으로 사용할 데이터 만들기
export async function getStaticProps({ params }) {
  // Fetch necessary data for the blog post using params.id
}
// getStaticPath를 쓰려면 아래와 같은 형태로 배열을 제공해야 함.
export function getAllPostIds(): { params: { id: string } }[] {
  const fileNames = fs.readdirSync(postsDirectory);

// Returns an array that looks like this:
  // [
  //   {
  //     params: {
  //       id: 'ssg-ssr'
  //     }
  //   },
  //   {
  //     params: {
  //       id: 'pre-rendering'
  //     }
  //   }
  // ]
  return f
  return fileNames.map(fileName => {
    return {
      params: {
        id: fileName.replace(/\.md$/, ''),
      },
    };
  });
}

// 사용은 다음과 같이 한다.
export async function getStaticPaths() {
  const paths = getAllPostIds()
  return {
    paths,
    fallback: false // false면 404페이지로 보낸다. true면 최신 버전 빌드 성공시 까지 다른 버전을 보여준다.
  } // blocking이면 서버사이드 렌더링을 하고 캐시되어 계속 같은것을 제공함
}
  • 모든 라우팅에 대해 하나의 파일로 처리하기 [...id].js
// pages/posts/[...id].js matches /posts/a, but also /posts/a/b, /posts/a/b/c and so on.

//getStaticPaths
return [
  {
    params: {
      // Statically Generates /posts/a/b/c 
      id: ['a', 'b', 'c']
    }
  }
  //...
]

export async function getStaticProps({ params }) {
  // params.id will be like ['a', 'b', 'c']
}
  • API Routes
// You can do so by creating a function inside the pages/api directory that has the following format:
// req = HTTP incoming message, res = HTTP server response
// Try accessing it at http://localhost:3000/api/hello. You should see {"text":"Hello"}. Note that:
export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json({ text: 'Hello' });
}
  • API를 getStaticProps나 getStaticPath에서 쓸 필요 없음
    • NextJS 앱은 그냥 노드라서 그냥 거기에서 DB 접근도 가능함
    • 서버코드는 그냥 여기에서 써라
  • Good Use Case : 인풋 핸들링 (폼의 POST)
export default function handler(req, res) {
  const email = req.body.email
  // Then save email to your database, etc...
}

추가로 보기

 

API Routes: Dynamic API Routes | Next.js

You can add the dynamic routes used for pages to API Routes too. Learn how it works here.

nextjs.org

커스텀 404 페이지 만들기

 

- pages/404.tsx 파일 만들기

 

구경하기

404 not found (nextjs-emotion-typescript-blog.vercel.app)

 

반응형