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개의 댓글

관련 채용 정보