Next.js - Setting

moontag·2022년 3월 18일
1

Next.js

목록 보기
2/4




Next.js

Vercel에서 만든 React 프레임워크







Setting

  • cd Documents
  • npx create-next-app@latest,
    ts로 만들거면 : npx create-next-app@latest --typescript
  • 프로젝트명 입력
  • code 프로젝트명
  • eslintrc.json, gitignore, README파일 등 생성됨
  • npm run dev
  • pages폴더/_app.js 빼고 전부 삭제





기본구조

pages/           // HTML, App Container, 각종 페이지 등을 작성
    _document.js // HTML
    _app.js      // Application Container. 공통의 레이아웃 작성
    _error.js    // Error Page
    index.js     // /로 시작되는 경로
static/          // 정적 파일 (이미지, 파일 등) 업로드
next.config.js   // 환경 설정 파일. 라우팅 설정, ts, less 등 webpack 플러그인 설정.








Patterns

pages/_app.js

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

export default MyApp;
  • 서버요청들어왔을때 최초로 실행되는 파일.
  • 모든 컴포넌트에 적용될 공통 속성(pageProps) 관리.
  • 페이지 공통 레이아웃 관리.
  • Component, pageProps를 받음
  • ReactJS는 각각 구분된 페이지여서 전역 CSS가 적용이 안됨
  • NextJS는 pages/_app.js 파일에서만 전역 CSS 적용가능
  • 파일명 _app.js 필수, 컴포넌트명은 아무거나 가능
  • _app.js 파일에선 전역 import할 것이 많아서 (google analytics, 검색엔진, 스크립트분석 등) 해당파일이 커지는건 원하지 않으므로, Layout.js에서 코드를 작성한다.
  • 여기서 console.log는 서버, 클라이언트(localhost, 터미널) 둘다 보인다.
//Layout.js
import NavBar from "./NavBar";

export default function Layout({ children }) {
  return (
    <>
      <NavBar />
      <div>{children}</div>
    </>
  );
}
//_app.js
import Layout from "../components/Layout";
import "../styles/globals.css"; //이파일에서만 전역css import가능

export default function AnyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}
  • pageProps는
    getInitialProps, getStaticProps, getServerSideProps
    하나를 통해 초기 속성값이 된다.



pages/_documents.js

  • _app.js 다음에 실행되는 파일
  • 모든 Head에 공통 <meta>, <title>, <link> 정의가능
  • 필수태그 - <Html> <Head> <Main> <NextScript>
  • _documents.js의 Head는 next/document고 모든페이지의 Head속성을 조작할 때 사용한다.
    실제 컴포넌트에서 동작하는 Head는 next/head의 Head다.
  • 서버에서만 render되므로 이벤트 처리 (onClink 등)이 안된다.
  • getStaticPropsgetServerSideProps를 적용할 수 없다.
  • 여기서 console은 서버에서만 보인다.
  • Document 클래스를 상속받는 Class 컴포넌트로 작성해야만 한다.
import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return { ...initialProps }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument





<Image> - next/image

<사용이유>
App에 image 삽입하면 해상도, 용량을 그대로 사용하여 리소스 낭비가 된다.
그래서 크기에 따라 리소스 최적화를 위해 NextJS <Image> 컴포넌트로 이미지 최적화 기능을 사용한다.
이미지의 여러 버전을 불러오고 OS, 기기 크기에 따라 이미지 최적화해준다. 그리고 캐싱으로 저장되며 다른 OS, 기기에서 사용가능하다.

  • <img> 태그 대신 next/<Image>사용하기
  • width, height 값 설정이 필요하다.
import Image from "next/image";
...
<Image src="me.png" alt="Picture of the author" width={500} height={500} />;





SSR하기 : getServerSideProps

  • getServerSideProps 함수명 변경 불가
  • export는 필수고, async는 선택사항.
  • props라는 key가 들어있고 안에 원하는 데이터넣을 수 있음
  • 여기서 쓰는 내부코드는 서버(백엔드)에서만 작동함
  • API KEY를 여기에 쓰면 절대로 클라이언트(브라우저)에게 안보임
  • 동작순서
    1. nextJS가 백엔드(API)에서 받은 props(data)를 return한다
    2. reactJS가 props(data)인 results 배열 가져와서 프론트엔드에 html보여줌
// index.js ex
export async function getServerSideProps() {
  const { results } = await (
    await fetch(`http://localhost:3000/api/movies`)
  ).json();
  return {
    props: {
      results, // props에 원하는 데이터 api 넣기
    },
  };
}
  • Server side통해 props를 Page로 보낼 수 있다
//_app.js ex
export default function AnyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}
// <props전달 순서>
// (index.js)getServerSideProps의 props가
// _app.js의 Component {pageProps}로 오고
// (index.js) Home의 props로 온다

// <Home {results} />           예를들면 이렇게 들어오는 것.



Route

pages/movies폴더 생성/all.js 생성
ex) http~/movies/all
pages/movies폴더 생성/index.js 생성
ex) /movies

동적 라우트url

pages/movies폴더 생성/[...변수명].js 생성

ex) /movies/1212121

// pages/[변수명].js

import { useRouter } from "next/router";

export default () => {
  const router = useRouter();

  return (
    <>
      <h1>post</h1>
      <p>postid: {router.query.변수명}</p>
    </>
  );
};

localhost:3000/3525332 접속하면 postid가 3525332으로 출력된다
pages/[변수명].js 값은 router.query.변수명 와 동일하다

✅ SSR 하기 - [...params].js

  • SSR : 유저에게 Loading 화면 안보여주고, SEO 최적화 하기
  • 여기선 데이터fetch말고 미리 데이터 가져오기 위함으로 사용했음
  • [params].js 수정 - getServerSideProps 추가
//[...params].js
// 컴포넌트 내부 router = 클라이언트에서 실행
export default function Detail({ params }) {
  //{ params }추가
  const router = useRouter();
  const [title, id] = params || []; //params로 변경
  return (
    <div>
      <h4>{title}</h4>
    </div>
  );
}
// getServerSideProps = 서버에서 데이터가져옴, 소스코드에 데이터담음
export function getServerSideProps({ params: { params } }) {
  // console.log(ctx); //getServerSideProps(ctx)지원함
  return {
    props: {
      params,
    },
  };
}
  • || [] 추가 이유
    미리렌더링으로 초기html 다운받아오고
    아직 js다운안되서 useRouter가 정보를 못가져와서 에러난다.
    그래서 초기에 빈배열 추가해줘서 오류 안나게 하고
    js가 다시 렌더링하면 그때 빈배열아닌 router.query.params 출력한다








profile
터벅터벅 나의 개발 일상

0개의 댓글