Next.js & React - 완벽 정복 가이드

MM·2022년 11월 8일
0
post-thumbnail

📃 페이지 & 파일 기반 라우팅

🔹 a태그를 사용하지 않는 이유

🔸 노마드코더에서 배웠던 내용

  • Link태그는 a태그와 달리 새로고침이 안돼서 훨씬 빠르다
  • Link태그가 이후 html로 변화될 때는 a가 되기 때문에, css등의 속성값은 a태그로 넣어준다.

🔸 유데미에서 배운 구체적인 이유

  • a태그는 새 페이지를 불러오기 위해 새 http요청을 보내는데, 이때 이 요청에 의해 react state가 초기 state로 바뀔 수 있다.
  • Link태그는 백엔드로 http 요청을 보내지 않는다. 따라서 페이지가 이동해도 state는 바뀌지 않는다.

😏 공식 문서에서 훔쳐 왔다네.

이런 식으로 메소드 내에 옵션을 넣어서도 사용 가능!

router.push('/?counter=10', undefined, { shallow: true })

🔸 replace

해당 페이지를 링크 페이지로 교체.
뒤로가기 history에 쌓이지 않아 뒤로가기 불가!

🔸 as

브라우저 URL 표시줄에 표시될 경로에 대한 선택적 데코레이터

<Link href="/" as="브라우저의 주소창에 표시될 URL">...</Link>

🔸passHref

href 속성을 자식 a태그에게 전달! 기본값은 false

<Link href={
      { 
        pathname: "post",
        query: { id: post_id } 
      }
      } passHref>
  <a>이 자식 태그가 위 속성을 이어받아요~</a>
</Link>

🔸 prefetch

뷰포트 내(전체 아님!)의 Link 태그 데이터를 백그라운드에서 미리 받아오는 속성. 운영 모드에서만 발생한다
기본값은 true.

🚲 운영 모드(production)

운영모드가 뭔데요

🔸 scroll

이동시 페이지 상단으로 자동 스크롤한다. 기본값은 true!

🔸 shallow

서버단 메소드를 재실행하지 않고 해당 url로 이동한다. 기본값은 false


🔹 router 메서드 목록

😏 이것도 공식 문서에서 훔쳐 왔다네.

🔸 push

해당 url로 이동.

🔸 replace

현재 페이지를 해당 페이지로 교체.
마찬가지로 뒤로가기로 이전 페이지 복구 불가능.

🔸 prefetch

Link의 prefetch와 같다!

🔸 beforePopState

들어오는 이벤트에 따라 특정 기능 수행.

 router.beforePopState(({ url, as, options }) => {
      if (as !== '/' && as !== '/other') {
       window.location.href = as
       return false
      }
 }

🔸 back

뒤로가기. window.history.back()와 같다

🔸 reload

새로고침. window.location.reload()와 같다

🔸 events

라우터에서 발생하는 이벤트를 확인. 콘솔에 찍어서 읽어보자!
지원되는 이벤트 목록은 다음과 같다.

  • routeChangeStart(url, { shallow })- 경로가 변경되기 시작할 때 발생
  • routeChangeComplete(url, { shallow })- 경로가 완전히 변경되면 발생
  • routeChangeError(err, url, { shallow })- 경로 변경 시 오류가 발생 or 경로 로드 취소시 발생
  • err.cancelled- 탐색 취소여부
  • beforeHistoryChange(url, { shallow })- 브라우저의 기록을 변경하기 전에 실행
  • hashChangeStart(url, { shallow })- 해시는 변경되지만 페이지는 변경되지 않을 때 발생
  • hashChangeComplete(url, { shallow })- 해시가 변경되었지만 페이지가 변경되지 않은 경우 발생

😯 router의 무엇을 사용하던...

페이지 리랜더링은 발생한다!




📃 메인페이지 설정하기

🔹 파일 이름에 매개변수 넣기

🔸 [event]

/event 뒤에 이어지는 모든 주소를 처리.

🔸 [...slug]

/event/.../... 와 같이 2개 이상의 인자가 붙을 때 처리.

🥺 주의! next는 run start가 아니라 run dev.

개발자 모드로 실행을 해야만 변화상황이 build하지 않아도 반영되어 보인다!
start로 시작하면 build해야만 수정사항이 반영된다!

😳 header와 head

header은 app__에 존재하여 어느 페이지를 가도 보이는 것!
head는 react-helmet을 써서 고치는, body 위쪽 메타태그 값!




📃 사전 렌더링

🔹 next가 사전 렌더링을 하는 방법

사전 렌더링은 최초 로딩에만 영향을 끼친다!

🔸 hydrate

  1. 서버단에서 서버사이드렌더링된 정적 페이지와 js파일을 클라이언트에게 보낸다.
  2. 클라이언트단에서 html코드와 js코드를 매칭하여 렌더링한다.


새롭게 페이지를 로딩할 때마다 뒤늦게 스타일이 적용되고 있다!
HTML DOM 요소에 뒤늦게 js가 적용되어-Hydration되어 나타나는 현상이다.

😯 두번 렌더링하면 비효율적인거 아닌가요?

서버단에서는 사전 렌더링으로 빠르게 렌더링이 진행된다! 이렇게 렌더링된 HTML은 JS가 없어 아주 가볍고 로딩이 빠르다.
이떄 발생하는 속도의 이점이 두 번 렌더링의 단점을 보완하고도 남는다고!
또한, 클라이언트단에서 발생하는 렌더링은 렌더링중 가장 시간이 오래걸리는 Paint부분 없이 단순 js매칭만 하기 때문에 그리 느리지 않다!


🔹 Static Genenration

일반적으로 권장되는 방법으로, 빌드하는 동안 사전에 모든 페이지를 생성해놓는 방법.

🔸 getStaticProps

페이지 사전 렌더링을 요청하는 함수

해당 함수를 페이지에 추가하면, next가 페이지를 사전생성할 때 사용자를 대신하여 해당 함수를 호출한다.
해당 페이지가 사전 생성되어야 하는 페이지임을 알려줌.

//[pid] 페이지가 있는 경우..
export async function getStaticProps(context){
  const {params} = context;
  const productId = prams.pid; 
  const data = fetch등으로 가져온 데이터
  const product = data.products.find(product=>product.id==producId);
  
  if(!product){
  	return {notFound:true};
    //이렇게 해주면 에러 대신 404페이지가 뜹니다.
  }
  
  return{
  	props:{ 
      loadedProduct: product, },
     revalidate: 10 //증분정적생성 주기 초
  };
}

😬 next는 모든 페이지를 사전생성하지만...

동적 세그먼트([id].tsx)의 경우에는 사전생성하지 않는다!
해당 페이지는 여러 주소와 여러 데이터를 가질 수 있기 떄문에 사전에 모든 값을 생성해놓는것이 불가능!
항상 서버에서 그때그때 생성된다.
따라서 getStaticProps함수로 강제 사전생성을 하게 되면, 오류가 발생한다!
👉 이것을 해결하기 위해선 밑의 getStaticPaths함수를 같이 사용하면 된다!

🔸 Incremental Static Generation(증분 정적 생성)

정적 생성시 빌드되는 시점에서 받은 데이터가 최신 데이터가 아닐 수 있다!
따라서 일정 주기마다 데이터를 업데이트하여 비교후 사전생성된 페이지를 재생성해준다.

배포 후에도 재배포 없이 계속 업데이트할 수 있게 해준다~

캐시를 사용한다는 점이 react query와 비슷한 듯?!

🔸 getStaticPaths

동적 페이지의 어떤 인스턴스를 생성할지 nextjs에 알리는 함수.
fallback으로 필요여부에 따라 페이지 생성 타이밍을 결정할 수 있다.

//[pid] 페이지가 있는경우..
export async function getStaticPaths(){
	return{
    	paths:[
          {params: {pid: "1"}},
          {params: {pid: "2"}},
          {params: {pid: "3"}},
        ],
      fallback: false; 
      //paths에 없는 다른 페이지을 요청하는 경우 서버에서 생성하게 하는 속성!
      //흔히 방문 많은 페이지만 paths에 명시하고 나머지 방문 적은 페이지는 fallback:true로 처리한다고!
    };
}

😂 fallback의 함정

명시되지 않은 페이지를 url로 검색하면 에러가 발생한다!
동적 사전 생성 기능이 즉시 끝나지 않기 때문!
따라서 해당 페이지를 보여주기 전 존재하는지 if문으로 확인해야 한다.

function DetailPage(props){
  const {loadedProduct} = props;
  return <>{ //존재한다면 자동으로 페이지를 업데이트해준다.
    loadProduct ? loadedProduct | <p>Loading...</p>}</> 
}

혹은, fallback: "blocking"으로 설정하면 서버에 사전 생성될 때까지 nextjs가 기다리게 할 수 있다!


🔹 Server-side Rendering

유입되는 모든 요청에 대한 페이지를 사전렌더링 한다!

🔸 getServerSideProps()

서버에서만 돌아가며 요청을 처리하는 함수~
서버측에서 모든 것을 처리하기 때문에, 동적 경로를 미리 설정하거나 모든 페이지를 미리 랜더링할 필요가 없다!

export async function getServerSideProps(context){
    const { results } = await ( await 		fetch(`http://localhost:3000/api/movies`)).json();
  //이렇게 서버측에서 실행하고 싶은 것들을 실행시키거나..
  
  
   const {params, req, res} = context;
  const productId = prams.pid; 
  //컨텍스트로 받아온 요청을 확인할 수도 있음.
  //serverside에서는 request와 response에도 접근할 수 있다!
  //접근하여 수정한 request와 response는 next가 다시 보내 준다. 
  
    return {props: {results}};
}

😳 get~Props함수는 하나만 사용해야 한다!

같은 일을 하는 함수라서 충돌을 일으키기 때문!


🔹 Client-side Data Fetching

값이 자주 변경되어 사전 렌더링이 의미가 없는 경우,
값이 특정 유저에게만 한정되는 경우,
값이 아직 입력되지 않아 사전 렌더링이 불가능한 경우에 사용!

🔸 평소에 하던 것들이 client-side fetching!

fetch, axios, useEffect 등을 사용하는 것!
👉 next는 첫 컴포넌트 결과대로 사전렌더링을 진행한다!
👉 따라서 useEffect로 변화된 결과는 사전렌더링되지 않는다...


🔹 NextJS 훅

🔸 useSWR

데이터 캐싱 및 데이터 유효성 재검사를 해주는 훅!

  • 같은 url에 작은 요청을 여러번 보내지 않고, 특정기간동안의 요청을 한 번에 묶어 보낸다!
  • 포커스를 잃었다가 다시 얻으면 자동으로 데이터 패칭을 해주는 기능도 있다!
//npm i swr로 swr훅 패키지를 설치한다.
const {data, error} = useSWR(<request-url>, (url) => fetch(url).then(res => res.json()))

🔹 클라이언트 사이드 데이터 패칭과 서버사이드 사전 렌더링 결합하기

기본 스냅샷을 사전 렌더링하고, 클라이언트에서 최신 데이터를 패칭한다!


export async function getStaticProps(){
	const res=await fetch(url);
  	const data=await res.json();
  //이 위는 클라이언트 사이드 데이터 패칭~
  //이 아래는 서버사이드 사전 렌더링~
	return {props: {sales: data},
            revaldate: 10}
  ;
}

사전 페칭에 대해서도 알아두기..

profile
중요한 건 꺾여도 그냥 하는 마음

0개의 댓글