혼자 적어보는 노트

프로그래머스 데브코스 TIL - Day 71 본문

스터디

프로그래머스 데브코스 TIL - Day 71

jinist 2022. 6. 29. 00:25

 

✅ 오늘의 학습

📌 React 심화(2)

 

- 서버사이드렌더링(SSR)

- Next.js

 


서버 사이드 렌더링 이해하기

 

서버 사이드 렌더링(Server Side Rendering)이란?

브라우저가 페이지에 처음 진입했을 때 서버로부터 HTML을 받아서 렌더링을 하는 것

 

서버사이드 렌더링의 특징

1. 검색엔진 최적화
=> 과거에는 ajax 호출을 통한 렌더링 결과를 수집하지 못했지만
요즘엔 검색 엔진이 발전해서 수집하는 경우도 있다.

 

2. 더 빠른 초기 로딩 속도.
Client-side 렌더링은 브라우저 렌더링 후 데이터를 가져오기 위한 로직이 수행되기 때문에
초기 로딩 속도가 느리다.

 

기존  SSR의 문제점

서버와 클라이언트의 각각 렌더링을 위한 코드를 따로 만들어야 한다.

 

Isomorphic Javascript

같은 언어의 코드로 server와 client에서 동일하게 작성하는 형태.

Front-end 와 Back-end 에서 모두 사용가능한 Universal Javascript을 의미한다.

 

CSR의 단점(SEO, 초기 화면 로딩 속도)을 보완하고

html렌더링을 손쉽게 처리할 수 있다는 장점을 가지고 있지만

하나의 자바스크립트 코드로만 작성을 하게되면 코드에 제약이 생긴다.

Server Side에서는 window와 같은 브라우저 객체를 사용할 수 없기 때문에 이부분에 대한 예외처리가 필요하다.

 

쨌든, SSR을 Isomorphic 방식으로 제공하는 것이 NextJs이다.

 


Next.js

리액트를 기반으로 동작하는 서버 사이드 렌더링 프레임 워크이다.

client side 렌더링의 단점인 비교적 느린 초기 로딩속도, SEO문제를 해결 할 수 있다.

 

 

AutoRouting

Next.js에서는 라우팅이 자동으로 지원이 된다.

디렉토리와 파일 이름으로 결정된다 (pages/about -> localhost:3000/about)

 

Link 컴포넌트

react router의 Link와 유사하게 페이지 간의 경로를 변경할 수 있다.

<Link href="/"></Link>

 

동적 페이지/ 동적 URL

동적 경로가 있는 페이지는 page/posts/[id].js 와 같은 형태로 생성할 수 있다.

const Post = ({ post }: Props) => {
  const router = useRouter();
  return (
    <div>
      {router.query.id}
    </div>
  );

동적으로 변경되는 URL은 useRouter를 사용하여 값을 받을 수 있다.

 

_app.tsx

- 앱의 첫 진입점이 되는 파일.

- 이 곳에서 렌더링 하는 값들은 모든 페이지에 영향을 준다.

- component와 pageProps를 받는다.

- 이 곳에서 console.log 실행 시 client, server 둘 다 나타난다.

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

export default MyApp;

component는 진입한 페이지의 component 파일이 props로 내려온다.

pageProps는 getInitialProps를 통해 내려받은 props이다.

 

* _app.tsx에서는 getStaticProps, getServerSideProps 메서드를 지원하지 않는다.

 

getServerSideProps

getServerSideProps는 서버 측에서만 실행되고 브라우저에서는 실행되지 않는다.

link, router를 통해 클라이언트 측 페이지 전환 시 api요청을 서버로 전송한다.

클라이언트에서 요청을해서 데이터를 가져와서 렌더링을 하는 것이 아니라
렌더링이 된 값을 가지고 오게된다. => 결과를 미리 렌더링

*_app.tsx에서는 사용할 수 없다.

 

export const getServerSideProps = async () => {
  const { data: posts } = await axios.get("https://jsonplaceholder.typicode.com/posts");

  return {
    props: { posts },
  };
};

const HomePage = ({ posts }) => {
  return (
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
  );
};

export default HomePage;

return한 props값을 통해 해당 페이지의 props로 데이터를 전달해줄 수 있다.

 

SPA의 경우 Html이 빈 상태로 내려오지만

서버로부터 미리 받아서 렌더링을 할 경우 Html의 내용이 데이터로 차있다.

 

page.getInitialProps

getServerSideProps와 비슷하지만 _app.tsx에서 사용할 수 있다.

* next v9 이상에서는 getInitialProps 대신 getStaticProps, getStaticPaths, getServerSideProps 사용을 권장한다.

 

도움되었던 글

import "../styles/globals.css";
import type { AppContext, AppProps } from "next/app";

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

MyApp.getInitialProps = (appContext: AppContext) => {
  return {
    pageProps: {
      test: 100,
    },
  };
};

export default MyApp;

 

❗ 주의사항

 

1. getInitialProps는 서버에서 실행된다.

브라우저 API(setTImeout, window, document)는 실행하면 안된다.

2. 하나의 페이지에서는 하나의 getInitialProps만 실행된다.

앱의 첫 진입점인 _app.tsx에서 getinitialProps를 사용하고 있다면

하위 컴포넌트에서의 getInitialProps는 실행되지 않는다.

 

API Routs

Next.js에서는 간단한 api를 만들 수 있다.

pages/api 폴더를 생성하여 api를 정의할 수 있다.

 

pages/api/posts/index.ts

import { NextApiRequest, NextApiResponse } from "next";
import data from "./data.json";

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.status(200).json(data);
}

api를 생성하고 page에서 localhost:3000/api/posts로 요청하면 해당 데이터를 받을 수 있다.

 

api는 동적인 경로를 지원하며 req.query를 통해 값을 받을 수 있다.

 

pages/api/posts/[id].ts

import { NextApiRequest, NextApiResponse } from "next";
import data from "./data.json";

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  if (req.method === "GET") {
    const id = parseInt(req.query.id as string);
    const post = data.find((item) => item.id === id);
    if (post) {
      res.status(200).json(post);
    } else {
      res.status(404).send({ error: "Not Found", status: 404 });
    }
  } else {
    res.status(405).send({ error: "Method not allow", status: 405 });
  }
}

 


✍느낀 점

이전에 next+node의 강의를 듣다가 전부 마무리 짓지 못하고 데브코스에 참여하게 되어서

아쉬운 마음이 들었었는데, 이번에 강의로 다루어 주셔서 좋았다.

강의를 듣고 부족함을 느껴서 공식 문서를 읽어보았는데 next의 동작 방식이 아직 100% 이해 되지는 않는다😢

하루 하루 새로운 게 강의로 나와서 좀 더 깊게 알고 싶은데 다음 파트로 넘어가야 하는 것이 아쉽다ㅜ

Comments