실전 웹 어플리케이션 개발 1,2장 정리

이수빈·2023년 10월 13일
0

Next.js

목록 보기
5/15
post-thumbnail

ALTJS

  • 컴파일을 통해 JS를 생성하는 프로그래밍 언어 => 대표적으로 TS , Coffe Script, 클로저 스크립트, Dart등이 존재함

빌드

  • 빌드시스템이란 코드상의 로딩한 모듈의 의존성을 해결하고 실행가능한 JS 형식으로 변환하는 구조임

  • 대표적인게 웹팩, ES 모듈 기반으로 라이브러리 배포등에 사용되는 rollup.js 이나 Next.js에서도 채용된 고속의 러스트기반 SWC라는 빌드도구도 등장함.

좋은 컴포넌트란?

  • 추상적이여야함. 컴포넌트가 사용하는 상태를 다른 컴포넌트에 의존하지 않는 형태로 구현하는 것이 중요, 재사용성을 확인해라

하이드레이션

1.서버측에서 미리 렌더링된 html을 반환한다.
2. 브라우저에서 정적인 html로 표시한다.
3. 자비스크립트 chunk들 로드 => hydration 과정 발생
4. 동적인 리액트 어플리케이션으로 작동한다.

  • SSG, SSR에서 리액트 컴포넌트의 렌더링은 브라우저에 반환되기전, 즉 서버사이드에서 실행됨

  • 클라이언트 측에서는 interactive 한 리액트 애플리케이션으로서 작동하도록 하기 위해 서버 측에서 미리 생성된 정적인 HTML 다운로드 한 뒤 동적인 리액트 컴포넌트로 복원함. => 이때 INTERACTION이 가능함.

  • Next.js에서는 Pre-Rendering된 웹페이지를 클라이언트에게 보내고 나서, 바로 리액트가 번들링된 자바스크립트 코드들을 클라이언트들에게 전송한다.

  • 이게 가장 큰 장점 => 만약 CSR에서 JS파일이 disabled 된다면? 사용자는 화면을 볼 수 없다. 그러나 Next.js는 프리렌더링으로 이를 방지한다.

  • React 응답
    => 빈 html + 번들 받아옴 + 코드스플릿팅했다면 페이지 이동시 컴포턴트를 받아옴

  • pre rendering시 getStaticProps을 사용하면 사이트를 배포 때 정의하는 props를 사용해서 사이트를 생성하게 됨 => cdn에 의해 캐싱되어 재사용됨.

  • Next.js 응답

  • 먼저 document Type의 파일을 응답받고 (pre-rendering) React로 번들링 된 JS파일들을 Chunk 단위로 전달 후 재 랜더링이 일어남.

  • 즉 html 자체가 변하는 방식(기본적으로 ssr방식으로 동작)

  • 페이지 이동 및 동작이 발생하는 경우에는 CSR 방식을 통해서 서버를 거치지 않고 브라우저에서 페이지를 이동한다. (Next.js의 Link 컴포넌트에 의해 가능함)

  • CSR방식으로 이동시 필요한 JS파일만 불러옴. GetStaticProps에 관련된 데이터들

  • 아래와 같이 4가지 경우의 경우 다시 pre-Rendering이 발생함.

javascript 에서 location.href 으로 페이지를 이동했을 경우
html 에서 a 태그의 href 으로 페이지를 이동했을 경우
브라우저 주소창에 url 을 입력하여 해당 페이지에 접근 했을 경우
새로고침 했을 경우

Next.js의 pre-Rendering방식

  • 2가지 방식이 존재한다.

SSG(Static Stie Generation) : 빌드타임에 HTML에 생성되어 요청마다 이를 재사용하게 해주는 방식임.(getStaticProps) 에 정의 (캐싱의 이점)

  • 모든 페이지에 대한 html 문서를 빌드할 때 생성하고 요청이 올 때마다 빌드할 때 만들어둔 html 문서를 재활용하는 방식입니다. 그렇기 때문에 SSR 방식이면서 빠르게 클라이언트에게 응답할 수 있다는 특징이 있습니다. 하지만 매 요청마다 페이지에 대한 내용이 변경되어야 하는 경우라면 적합하지 않을 수 있습니다.

이 헤더의 값은 응답이 Vercel의 에지 캐시에서 제공되었는지 여부를 나타냅니다.
제공되는 콘텐츠가 정적이거나 Cache-Control 헤더를 사용하는 경우 다음 값이 가능합니다.
MISS: 엣지캐시에서 응답을 찾지 못하고 오리진서버에서 가져온 응답입니다.
HIT: 응답이 엣지 캐시에서 제공되었습니다.
STALE: 응답이 엣지 캐시에서 제공되었습니다. 콘텐츠를 업데이트하기 위해 원본 서버에 대한 백그라운드 요청이 이루어졌습니다.
PRERENDER: 응답이 정적 저장소에서 제공되었습니다.
REVALIDATED: 원본 서버에서 응답이 제공되었으며 수신 요청에서 사용자의 인증으로 인해 캐시가 새로 고쳐졌습니다.

  • develoopment 환경에서는 항상 getStaticProps를 실행함.

  • API 호출결과가 달라질때는 ? => revalidate 값을 지정해서 사용함.(stale, fresh개념)

  • 호출된 api결과가 stale한 상태라면 재호출해서 최신값을 가져옴

  • 이것이 ISR방식(Increment Static Generation) => 빌드가 완료된 상태에서도 주기적으로 페이지 업데이트 가능함.

  • data가 변하지 않는다면? Next.js는 프리렌더링 즉 stale하지만 프리렌더링을 다시 수행하지 않음.

import type { NextPage } from 'next';

interface Props {
  data: number;
}

const Example: NextPage<Props> = ({ data }) => {
  return (
    <main>
      <h1>getStaticProps Page</h1>
      <p>: {data}</p>
    </main>
  );
};

export default Example;

export async function getStaticProps() {
  const delayInSeconds = 2;
  const data = await new Promise((resolve) =>
    setTimeout(() => resolve(Math.random()), delayInSeconds * 1000)
  );

  return {
    props: { data },
    revalidate: 5 /** https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration */,
  };
}

SSR 방식 : 매 요청마다 HTML을 생성하는 SSR방식 (getServerSideProps) 에 정의

  • 매 요청마다 페이지에 대한 html 문서를 렌더링하여 클라이언트에게 전달하는 방식입니다. getServerSideProps 함수를 정의하면 해당 페이지는 항상 매 요청마다 html 문서를 Pre-Rendering 하게 됩니다.

  • Next.js 공식문서에서는 Static Generation (SSG) 방식을 권장하고 있었습니다.

  • 사용자의 인증정보에 따라 변하는 페이지이거나 보안이 중요한 페이지에 적용

Next.js CSR방식

  • noSSR은 window.innerWidth를 렌더링하는 컴포넌트
const NoSSR = () => {
  return <p>width: {window.innerWidth}</p>;
};
export default NoSSR;
  • dynamic import 말고 그냥 import를 한다면?

  • 에러발생. 페이지에 포함되는 컴포넌트는 서버에서 렌더링이 되야함. => window 객체에 접근 불가능함. document도 마찬가지

  • 결국 next server에서 프리렌더링을 진행하기 때문.

import type { NextPage } from 'next';
import { useEffect, useState } from 'react';
import dynamic from 'next/dynamic';

/** https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr */
const NoSSR = dynamic(() => import('../../components/section1/NoSSR'), {
  ssr: false,
}); // 이 구문이 없다면 에러뜸 

const Example: NextPage = () => {
  const [data, setData] = useState(0);

  useEffect(() => {
    const delayInSeconds = 2;
    new Promise<number>((resolve) =>
      setTimeout(() => resolve(Math.random()), delayInSeconds * 1000)
    ).then((result) => setData(result));
  }, []);

  return (
    <main>
      <h1>Client-side data fetching</h1>
      <p>: {data}</p>

      <h1>no SSR</h1>
      <NoSSR />
    </main>
  );
};

export default Example;

타입스크립트 interface

  • Class Type 을 설정할때 interface에 대한 구현 강제가능
// 머릿 글자의 I는 인터페이스임을 나타내기 위한 것이다
interface IUser {
  name: string;
  age: number;
  sayHello: () => string; // 인수 없이 문자열을 반환한다
}

class User implements IUser {
  name: string;
  age: number;

  constructor() {
    this.name = ''
    this.age = 0
  }

  // 인터페이스에 정의되어 있는 메서드를 구현하지 않으면, 컴파일 시 에러가 된다
  sayHello(): string {
    return `안녕하세요. 저는 ${this.name}이며, ${this.age}살입니다.`
  }
}

const user = new User()
user.name = 'Hana'
user.age = 36
console.log(user.sayHello()) // '안녕하세요. 저는 Hana이며, 36살입니다.'

ref)

hydration :https://www.howdy-mj.me/next/hydrate
https://helloinyong.tistory.com/315
https://velog.io/@wooseok123/Next.js-CSR-vs-
https://funveloper.tistory.com/164

profile
응애 나 애기 개발자

0개의 댓글