서버사이드 렌더링

0. 시작하기 전..

 - 코딩앙마님의 강의를 참고하였습니다! (강의영상 바로가기)

 

1. 로딩 페이지 제작

 - 화면이 넘어갈 때, 사용할 로딩 페이지를 만들어보겠습니다.

 - #1. index.js 에 들어가 다음과 같이 입력해줍니다.

import Axios from "axios";
import Head from "next/head";
import { useEffect, useState } from "react";
import ItemList from "@/src/component/ItemList";
import styles from "@/styles/Home.module.css";
import { Divider, Header, Loader } from "semantic-ui-react";

export default function Home() {
  const [list, setList] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  const API_URL =
    "http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline";

  function getData() {
    // 상품을 받아옴
    Axios.get(API_URL).then((res) => {
      console.log(res.data);
      setList(res.data);
      setIsLoading(false);
    });
  }

  useEffect(() => {
    getData();
  }, []);

  return (
    <div>
      <Head>
        <title>NewBean</title>
      </Head>
      {isLoading && (
        <div style={{ padding: "300px 0" }}>
          {/* 로딩화면 추가 */}
          <Loader inline="centered" active>
            Loading
          </Loader>
        </div>
      )}
      {!isLoading && (
        <>
          <Header as="h3" style={{ paddingTop: 40 }}>
            베스트 상품
          </Header>
          <Divider />
          <ItemList list={list.slice(0, 9)} />
          <Header as="h3" style={{ paddingTop: 40 }}>
            신상품
          </Header>
          <Divider />
          <ItemList list={list.slice(9)} />
        </>
      )}
    </div>
  );
}

 

 - #2. [id].js에 들어가 다음과 같이 입력해줍니다.

import Axios from "axios";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import Item from "../../src/component/Item";
import { Loader } from "semantic-ui-react";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;

  const [item, setItem] = useState({});
  const [isLoading, setIsLoading] = useState(true);

  const API_URL = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`;

  function getData() {
    Axios.get(API_URL).then((res) => {
      setItem(res.data);
      setIsLoading(false);
    });
  }

  useEffect(() => {
    if (id && id > 0) {
      getData();
    }
  }, [id]);

  return (
    <>
      {isLoading ? (
        <div style={{ padding: "300px 0" }}>
          {/* 로딩화면 추가 */}
          <Loader inline="centered" active>
            Loading
          </Loader>
        </div>
      ) : (
        <Item item={item} />
      )}
    </>
  );
};

export default Post;

 

 - #3. 이제 브라우저에 들어가보면, 로딩이 나오는 것을 확인할 수 있습니다.

  

2. 사전 렌더링 (pre-rendering)

 - 웹 개발에서는 사전 렌더링(pre-rendering)이라고 있습니다.

 - 사전 렌더링사용자가 특정 페이지로 이동하기 전, 해당 페이지의 일부 or 전체미리 렌더링합니다.

 - 그렇게 하면 페이지 로딩 시간을 단축하고 사용자 경험을 향상시키는데 사용될 수 있습니다.

 - 사전 렌더링에는 크게 정적 생성서버사이드 렌더링이 있습니다. 이 둘의 차이점은 언제 html 파일을 생성하는가 입니다.

 

 - 정적 생성 (Static Generation)

    - 웹 페이지의 콘텐츠미리 서버 측에서 생성하고 저장하는 방식을 가리킵니다.

    - 프로젝트가 빌드하는 시점 html 파일들을 생성합니다.

    - 모든 요청에 파일들을 재사용합니다.

    - 정적 생성된 페이지들은 CDN에 캐시됩니다.

    - 퍼모먼스 이유로, Next.js는 정적 생성을 권고합니다.

    - getStaticProps / getStaticPaths

 

 - 서버사이드 렌더링 (ServerSide Rendring)

    - 웹 페이지의 콘텐츠서버에서 동적으로 생성한 후, 클라이언트에게 제공하는 방식입니다.

    - 사용자가 페이지에 접속할 때마다 서버에서 요청을 받아 html을 생성하여 전달합니다.  

    - 항상 최신 상태를 유지합니다.

    - 각 요청마다 서버에서 동적으로 html을 생성하므로, CDN에 캐시되지 않아 느릴 수 있습니다

    - getServerSideProps

 

 - #1. 이제 적용해봅시다! 처음 index.js에서 title태그 밑에 다음과 같이 입력해줍니다.

<meta name="description" content="NewBean 홈입니다."></meta>

 

 - #2. [id].js 에서 다음과 같이 입력해줍니다.

    → 이렇게 하면, 검색엔진에서 상품의 내용이 검색되게끔 할 수 있습니다. 

import Axios from "axios";
import Head from "next/head";
import Item from "../../src/component/Item";

const Post = ({ item }) => {
  return (
    <>
      {item && (
        <>
          <Head>
            <title>{item.name}</title>
            <meta name="description" content={item.description}></meta>
          </Head>
          <Item item={item} />
        </>
      )}
    </>
  );
};

export default Post;

// 서브사이드 렌더링을 위한 코드
export async function getServerSideProps(context) {
  const id = context.params.id;
  const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`;
  const res = await Axios.get(apiUrl);
  const data = res.data;

  return {
    props: {
      item: data,
    },
  };
}

 

 - #3. gnb.js에 들어가서 다음과 같이 입력하여 메뉴 클릭시, 페이지 이동을 구현해봅시다.

    → 브라우저로 가서 클릭하면, 제대로 작동하는 것을 알 수 있습니다.

import { useRouter } from "next/router";
import { Menu } from "semantic-ui-react";

export default function Gnb() {
  const router = useRouter();
  let activeItem;

  if (router.pathname === "/") {
    activeItem = "home";
  } else if (router.pathname === "/about") {
    activeItem = "about";
  }

  // 버튼 클릭 시, 원하는 링크로 이동하기
  function goLink(e, data) {
    if(data.name === 'home') {
      router.push("/");
    } else if (data.name === 'about') {
      router.push("/about");
    }
  }

  return (
    <Menu inverted>
      <Menu.Item
        name="home"
        active={activeItem === "home"}
        onClick={goLink}
      />
      <Menu.Item
        name="about"
        active={activeItem === "about"}
        onClick={goLink}
      />
    </Menu>
  );
}

 

 - #4. view 폴더에 있는 about.js에 들어가 다음과 같이 입력하여 디자인해줍니다. (파일이 없을 시, 생성)

import {
  Button,
  Divider,
  Form,
  Header,
  List,
  TextArea,
} from "semantic-ui-react";

export default function about() {
  return (
    <div>
      <Header as="h3" style={{ paddingTop: 40 }} color="teal">
        회사 소개
      </Header>
      <Divider />
      <List>
        <List.Item>
          <List.Icon name="users" />
          <List.Content>Semantic UI</List.Content>
        </List.Item>
        <List.Item>
          <List.Icon name="marker" />
          <List.Content>New York, NY</List.Content>
        </List.Item>
        <List.Item>
          <List.Icon name="mail" />
          <List.Content>
            <a href="mailto:kim@semantic-ui.com">kim@semantic-ui.com</a>
          </List.Content>
        </List.Item>
        <List.Item>
          <List.Icon name="linkify" />
          <List.Content>
            <a href="http://www.semantic-ui.com">semantic-ui.com</a>
          </List.Content>
        </List.Item>
      </List>
      <Header as="h3" style={{ paddingTop: 40 }} color="teal">
        문의 사항
      </Header>
      <Divider />
      <Form>
        <Form.Field>
          <label>제목</label>
          <input />
        </Form.Field>
        <Form.Field>
          <label>내용</label>
          <TextArea />
        </Form.Field>
        <Button color="green">보내기</Button>
      </Form>
    </div>
  );
}

 

3. 정리하며

 - 지금까지 서버사이드 렌더링에 대해 알고 로딩 페이지 About 페이지를 작업해 보았습니다.

 

※ 참고 깃 주소 : https://github.com/NewBean0312/nextjs-study/commit/ae16b8603b6af9756c6d408fff18c9b917c181cf

 

로딩 페이지 및 About 페이지 작업 · NewBean0312/nextjs-study@ae16b86

NewBean0312 committed Dec 12, 2023

github.com

 

 

'Front-End Study > Next.js' 카테고리의 다른 글

정적 생성 (Static Generation)  (1) 2023.12.18
에러 페이지와 환경 변수  (0) 2023.12.13
Dynamic Routes  (0) 2023.12.11
페이지 레이아웃 생성  (0) 2023.12.01
Next.js 설치  (0) 2023.12.01