Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

Studyyyyy

Next.js - react 본문

카테고리 없음

Next.js - react

manyYun 2022. 6. 28. 13:13

소개

 

React + Express.js + SSR + Router

 

설치

npx create-next-app@latest

실행

  • npm run dev : 개발
  • npm run build : 실서버 배포 버전 생성
  • npm run start : 실서버 구동

Hello World

pages/index.js

 

import Head from 'next/head';
import styles from '../styles/Home.module.css';

export default function Home() {
  return (
    <div>
      Hello World
    </div>
  );
}




Deploy

npm run build : 배포판을 만든다.

npm run start : 배포판을 실행한다. 

 

Vercel

 

  • nextjs은 vercel 의 오픈소스이다. 
  • 코드를 github로 업로드 한다. 
  • vercel에서 github 프로젝트를 import 한다. 
  • push 하면 자동으로 디플로이 된다.
  • 브랜치로 push 하면 브랜치별로 다른 서버가 활당된다. 

Router

Route rule

 

  • url에 따라서 적당한 ui를 출력해주는 기능
  • next.js는 웹서버, php처럼 디렉토리 기반으로 라우팅 하는 기능을 제공

 

 

  • 모든 페이지는 pages 디렉토리 하위에 있어야 한다. 
  • [id].js 형식으로 파일명을 만들면 id 부분이 파라미터로 처리된다. 

 

/sub/index.js

 

index.js는 기본 파일이다. 

 

export default function Sub(){
    return <>Sub/index.js</>
}

 

/sub/[id].js

 

id는 파라미터로 처리된다. useRouter를 통해서 id 값에 접근할 수 있. 

 

import {useRouter} from 'next/router';
export default function Param(){
    const router = useRouter();
    const id = router.query.id;
    return <>Sub/[id].js {id}</>
}



https://stackblitz.com/edit/nextjs-q4kffz?file=pages%2Findex.js

 

Link

 

페이지 리로드 없이 페이지를 전환하도록 돕는 컴포넌트.

 

import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <h1>index</h1>
      <ul>
        <li>
          <Link href="/sub">/sub/index.js</Link>
        </li>
        <li>
          <Link href="/sub/about">/sub/about.js</Link>
        </li>
        <li>
          <Link href="/sub/1">/sub/1.js</Link>
        </li>
        <li>
          <Link href="/sub/2">/sub/2.js</Link>
        </li>
      </ul>
    </div>
  );
}

 

https://stackblitz.com/edit/nextjs-fbqbdc?file=pages/sub/[id].js



API Route

 

nextjs는 express 처럼 백엔드 기능이 내장되어 있습니다. 

 

 

/data/topics.json

 

[
  {
    "id": 1,
    "title": "html",
    "body": "html is .."
  },
  {
    "id": 2,
    "title": "css",
    "body": "css is .."
  }
]

 

/pages/api/topic/index.js

 

/pages/api 디렉토리는 server side api를 위한 전용공간이다. 

여기에 파일을 만들면 클라이언트로 코드가 전송되지 않는다. 

 

import topics from '../../../data/topics.json';
export default (req, res) => {
  res.status(200).json(topics);
};

 

/pages/api/topic/[id].js

 

import topics from '../../../data/topics.json';
export default (req, res) => {
  const { id } = req.query;
  const topic = topics.filter(e => e.id === Number(id))[0]
  res.status(200).json(topic);
};

 

https://stackblitz.com/edit/nextjs-wjbxta?file=pages%2Fapi%2Ftopics%2F[id].js

Server Side Rendering

위의 파일의 페이지 소스 보기 한 결과 비교

=> Nextjs는 서버에서 랜더링 된 결과를 전송한다. 순수한 리액트는 자바스크립트가 로딩 된 후에 웹페이지가 실행된다. 

 

Next.js

 

https://stackblitz.com/edit/nextjs-32fuf3?file=pages%2Findex.js

 

<html>
    <body>
        <div id="__next" data-reactroot=""><div>Hello World</div></div>
    </body>
</html>

 

React 

 

https://stackblitz.com/edit/react-zvroa1?file=src%2FApp.js

 

<!DOCTYPE html>
<html>
    <body></body>
</html>



 

  • CSR - Client Side Rendering
  • SSR - Server Side Rendering
  • SSG - Static Site Generation
  • ISR - Incremental Static Regeneration

 

출처 : https://dev.to/pahanperera/visual-explanation-and-comparison-of-csr-ssr-ssg-and-isr-34ea






SSR과 데이터 통신

 

  • SSR에서 가장 어려운 문제가 데이터 통신이다.
  • 데이터의 신선도에 따라서 통신 방법이 다르다.  

Client Side Rendering : useEffect

 

  • 클라이언트 측에서 통신이 이루어져야 할 때 사용한다. 
  • 가장 신선하다. 
  • SEO에 취약하다. 

 

/use_effect.js

 

import {useEffect, useState} from 'react';
import Link from 'next/link';
export default function(){
  const [topics, setTopics] = useState([]);
  async function loadData(){
    const URL = 'https://jsonplaceholder.typicode.com/posts';
    const resp = await fetch(URL);
    const data = await resp.json();
    setTopics(topics=>data);
  }
  useEffect(()=>{
    loadData();
  });
  const ui = topics.map(e=><li key={e.id}>{e.title}</li>);
  return <div>
    <ol>
      {ui}
    </ol>
    <Link href="/">/index.js</Link>
  </div>;
}



https://stackblitz.com/edit/nextjs-41hvkt?file=pages%2Findex.js,pages%2Fuse_effect.js

 

Server Side Rendering : getServerSideProps

 

  • getServerSideProps 는 페이지에 진입했을 때 호출된다. 
  • 리턴값으로 props를 전달하면 default 컴포넌트의 props로 데이터가 전달된다. 
  • 사용자가 접속 될 때마다 백그라운드에서 실행되고, 이것이 끝나야 응답이 시작된다. 
  • fetch를 할 때 URL은 주소 전체를 적어야 한다. 



import Link from 'next/link';
export default function Main(props){
  const topics = props.topics;
  const ui = topics.map(e=><li key={e.id}>{e.title}</li>);
  return <div>
    <ol>
      {ui}
    </ol>
    <Link href="/">/index.js</Link>
  </div>;
}

export async function getServerSideProps(context) {
  const URL = 'https://jsonplaceholder.typicode.com/posts';
  const resp = await fetch(URL);
  const data = await resp.json();
  return {
    props: {topics:data},
  }
}

 

https://stackblitz.com/edit/nextjs-m58gzp?file=pages%2Fssr%2Fuse_effect.js,pages%2Fssr%2Fget_server_side_props.js

 

Static Site Generation : getStaticProps

 

import Link from 'next/link';
export default function Main(props){
  const topics = props.topics;
  const ui = topics.map(e=><li key={e.id}>{e.title}</li>);
  return <div>
    <ol>
      {ui}
    </ol>
    <Link href="/">/index.js</Link>
  </div>;
}

export async function getServerSideProps(context) {
  const URL = 'https://jsonplaceholder.typicode.com/posts';
  const resp = await fetch(URL);
  const data = await resp.json();
  return {
    props: {topics:data},
  }
}

 

https://stackblitz.com/edit/nextjs-utgdma?file=pages%2Fssr%2Fget_static_props.js,pages%2Fssr%2Fget_server_side_props.js,pages%2Findex.js



Incremental Static Regeneration

 

revalidate를 10으로 지정하면 10초 후에 다시 데이터가 갱신 됩니다. 

 

import Link from 'next/link';
export default function Main(props){
  const topics = props.topics;
  const ui = topics.map(e=><li key={e.id}>{e.title}</li>);
  return <div>
    <ol>
      {ui}
    </ol>
    <Link href="/">/index.js</Link>
  </div>;
}

export async function getServerSideProps(context) {
  const URL = 'https://jsonplaceholder.typicode.com/posts';
  const resp = await fetch(URL);
  const data = await resp.json();
  return {
    props: {topics:data},
    revalidate:10
  }
}



https://stackblitz.com/edit/nextjs-51tibo?file=pages%2Fssr%2Fget_static_props.js,pages%2Fssr%2Fget_server_side_props.js,pages%2Findex.js



환경변수

 

환경마다 접속 주소 등이 달라지는 경우 환경변수를 이용한다. 

 

.env.local 

 

이 파일을 최상위 디렉토리에 만들어두면 개발환경이 만들어질 때 환경변수를 읽어서 앱에 공급한다. 

 

API_URL = http://localhost:3000/

 

API_URL = http://localhost:3000/

 

/pages/rendering/ssr.js

 

process.env.API_URL 를 통해서 환경변수에 접근할 수 있다. 

 

import Link from 'next/link';
export default function Main(props){
  const topics = props.topics;
  const ui = topics.map(e=><li key={e.id}>{e.title}</li>);
  return <div>
    <ol>
      {ui}
    </ol>
    <Link href="/">/index.js</Link>
  </div>;
}

export async function getServerSideProps(context) {
  let URL = process.env.API_URL+'api/topic';
  const resp = await fetch(URL);
  const data = await resp.json();
  return {
    props: {topics:data},
  }
}



Vercel