next.js를 사용해야 하는 이유

규갓 God Gyu·2024년 4월 27일

TIL

목록 보기
63/74

Next.js 개요

next.js는 react를 기반으로 만든 프레임워크(for the Web = full-stack Web applications)

프레임워크

개발자가 기능 구현에만 집중할 수 있도록 필요한 모든 프로그래밍적 재원을 지원하는 기술의 조합
Spring Framework : Java 기반의 웹(백엔드) 프레임 워크
+ FE까지 가능한 full stack coverage framework
+ JSP, Thymeleaf
Vue.js Angular.js - js 기반 웹 프론트엔드 SPA 프레임워크
Django, Flask : Python 기반의 웹 프레임워크
Ruby on Rails
.NET Framework
Express.js, NestJS : Javascript 기반 웹 백엔드 프레임워크

라이브러리

공통 기능의 모듈화가 이루어진 프로그램의 집합

React.js

UI 만들기 위한 라이브러리
프레임워크라고 불리기엔 제공해야하는 기능이 부족함
상태관리(Redux), 라우팅(React-router-dom), 스타일링 등의 기능이 합쳐져 있었다면 프레임워크로 불릴 수 있었을지도?

react-router-dom
redux
물론, 제어의 역선(IoC : Inversion Of Control)로도 설명할 수 있음

Inversion of Control - IOC
프레임워크를 사용하는 경우 시키는대로 코드를 짜게 되면 프레임워크가 알아서 제어의 흐름을 가져가는 것

  • 본래 개발 시 '제어'를 하는 것은 개발자의 역할
  • 프레임워크를 사용하는 경우 시키는대로 코드를 짜게 되면 프레임워크가 알아서 제어의 흐름을 가져가는 것

ex) 라우팅을 위한 제어

  • next.js에선 미리 정해져있는 코드만 적재적소에 넣어주면 됨
    (프레임 워크가 제어를 함)

즉 react-router-dom을 위해선 개발자가 설치하고 세팅해서 불러와야만 사용할 수 있는데? 만약 next.js라면 그런 세팅 자체를 개발자가 할 필요가 없음
사용만 하면 됨. 즉 프레임워크가 라우팅을 위한 제어를 하고 있음
(제어의 역전 - IoC)

React.js

공식 홈페이지 : UI 만들기 위한 라이브러리
그 자체만으로 프레임웍이라고 불리기엔 제공해야 하는 기능이 부족함
상태관리, 라우팅, 스타일링 등의 기능이 다 합쳐져 있었다면 프레임워크라고 불렸을 만도?

Next.js

공식 페이지 : 웹 개발을 위한 React 프레임워크
React.js가 가지고 있는 기능을 확장
웹 애플리케이션 개발에 필요한 다양한 기능과 구조를 제공
다양한 렌더링 기법 - CSR, SSR, SSG, ISR
라우팅 - 파일(폴더) 기반 라우팅
route handler - 백엔드 기능(데이터 제공의 역할도 함)
스타일링 기본 제공 - CSS, Sass, CSS-in-JS, tailwind
최적화, 번들링 - 코드 스필리팅, 이미지 최적화, 웹팩 설정 등
(100MB 사진을 엄청 작은 사이즈로 넣으면 최적화해서 작은 용량으로 최적화해줌!!)

next.js를 사용해야하는 이유

  • 더 이상 어려운 설정은 그만 - 개발만 집중할 수 있게 하는 framework
  • full stack!!!!!
    - API Route를 지원하여 full stack 웹 개발이 가능하도록 함
    - 작은 기업, 작은 프로젝트에 매우 적합
    - but 복잡한 백엔드 로직은 구현 어렵거나 불가
    ex) WebSocket, WebRTC 등

    WebSocket, WebRTC 모두 실시간 통신을 위해 설계된 기술
    채팅이나 화상 회의, 파일 공유 등에서 사용
    HTTP와 비교했을 때 엄청나게 효율적인 실시간 통신을 제공

FE 로직과의 종속성 : 백엔드 로직만 변경해서 배포해야 하면 FE도 함께 배포해야함
아직까지는 완벽한 대체? 는 어려움

  • 유용한 기법 제공
  1. 렌더링
    기존 SPA 라이브러리에서 사용하던 CSR에서 벗어나 SSR, ISR, SSG 등을 가능케 함

  2. 코드스플리팅(별도 로직 없이 포함!!)
    Next.js는 코드스플리팅을 default로 지원
    - 웹 페이지 로딩 시간을 줄이기 위한 방법
    (react는 TTV가 상당히 오래 걸림 - Time To View) - 초기 로딩 속도
    - 전통적으로 우리는..!!
    - 일반적으로 웹사이트 전체 코드를 한 번에 다운로드 받아서 처리했었음
    - 방문하지 않는 페이지까지 다운받아야 해서 오래 걸렸음
    - 사용자가 최초 View를 보기 위한 시간이 오래 걸림

TTV란?

Time To View의 약자로써, 사용자가 최초 View를 볼 수 있을 때 까지의 시간
TTV가 짧으면 짧을수록 사용자가 더 빠르게 컨텐츠를 볼 수 있음
사용자 만족도나 서비스의 전반적인 품질에 직접적인 영향을 주기 때문에
TTV를 줄이는 것은 성능최적화의 주요한 지표 중 하나!!!!!

코드 스플리팅을 사용하면??(코드를 작은 단위로 잘라냄)

  • 사용자가 필요로 하는 부분만 우선 로딩
  • 나머지는 필요에 의해서만 로딩
  • TTV 향상
  • react에선 Suspense와 lazy를 이용해서 코드 스플리팅 구현이 가능하다(참고)

next.js가 코드 스플리팅을 구현하는 법

  • 각 컴포넌트를 별도 JS 번들로 분리
  • 사용자가 어떤 페이지에 방문할 때 필요한 부분만 로드하도록 보장
  • '프레임워크'인 Next.js는 이런 부분을 개발자가 신경쓰지 않아도 알아서 구현
    덕분에 애플리케이션 자체의 구조설계와 비즈니스 로직 구현에 집중할 수 있음

Date Fetching

  • fetch 함수가 next.js에선 기능이 더욱 확장
  • 여러 옵션을 통해 한 번만 값을 가져올지, 일정 주기별로 가져올지, 지속적으로 계속 가져올지 결정할 수 있음
  • SSR,SSG,ISR과 밀접한 연관

쉬운 배포

  • Vercel에서 제공하는만큼 배포가 매우 쉬움
  • Full Stack 애플리케이션의 배포 프로세스

전통적인 방법
프론트엔드 : vercel
백엔드 : aws ec2

next.js를 사용하면 vercel로 일괄 배포

지금의 Next.js가 있기까지

  1. 2016
  • github 오픈소스 프로젝트로 첫 출시
  • 6가지 원칙을 기반으로 개발
    1. out-of-the-box functionality requiring no setup (셋업 불필요)
      2. JS everywhere + all functions are written in JS
    2. automatic code-splitting and server-rendering
    3. configurabla date-fetching (데이터 가지고 오는 옵션 제공하겠다)
    4. ☆☆anticipating requests
    • 사용자가 원하는 것이 무엇인지를 먼저 예측 = 요구사항 예측
    1. simplifying deployment (배포 쉽게)
  1. 2017
  • Next 2.0
  • 소규모 웹에서 쉽게 작업할 수 있도록 하는 개선사항
    - 빌드 효율성 높임
    • HMR 기능 : 애플리케이션 실행 중인 상태에서 특정 모듈 변경사항 실시간 교체
      (리액트 개발환경처럼 수정하면 바로바로 적용됨)
  1. 2018
  • Version 7.0
  • 에러 핸들링 기능 강화
  • 향상된 Dynamic Route handling을 위해 React context API 지원
  1. 2020
  • Version 9.3
  • SSG, SSR 뿐만 아니라, ISR(Incremental Static Regeneration)의 등장
  • Rewrite, Redirect 등장

5. 2022☆☆☆☆

  • Next.js 13 Version(Breaking Changes)
  • app route의 등장
  • React 18 버전에 등장한 Server Components 적용
  • (nested) layouts
  • Turbopack
  1. 2023
  • 5월
    - Version 13.4
    • stable version of App Router
    • Production으로 사용 가능한 수준의 안정화
  • 10월
    - Version 14
    - 메모리관리 향상(edge runtime)

    edge runtime?
    웹 에플리케이션의 일부분을 전 세계에 퍼져있는 여러 서버 중 사용자에게 가장 가까운 서버에서 실행하는 기술 -> 사용자의 요청에 더 빨리 응답할 수 있음

앱 라우터 vs 페이지 라우터

Next.js의 버전의 주요 분기점

  • 일반적으로 Next.js를 채택할 때 주요한 의사결정은 App router vs Pages router과 연관되어 있다

  • 왜 router 기반으로 주요한 속성을 분류할까??

    1. 우린 웹사이트 기획/설계할때, 어떤 페이지가 존재하게 할지, 라우팅은 어떻게 하게 할지를 항상 먼저 고려함. 그만큼 매우 중요

    2. 기존의 React.js를 사용하여 웹 애플리케이션을 만들 때는 react-router-dom을 이용해서 라우팅을 가능하게 했었음

    3. 이렇게 중요한 라우팅에 대한 근본적인 시각, 전략이 next.js 13버전 기점 변경

      • 변경 전 : pages 폴더에 원하는 페이지의 파일 이름을 둔다

      • 변경 후 : app 폴더 밑에 폴더명을 기반으로 자동 라우팅. 그래서 app router라고 말함

app router와 pages router 어떤 것을 사용해야 할까?

  1. app router 쓰는 쪽 입장
    • 이제 안정화도 되었고, 자꾸 이전 버전 사용하는 것은 리액트에서 class형 컴포넌트 쓰는 것과 같다
    • 추가 기능이 얼마나 많은데, 당연히 최신 버전 사용해야 한다!
    • 공식 홈페이지도 웬만하면 app router 쓰라고 함

      (기존 작업물도 app router로 migrating 하라고 추천하는 모습)
  2. pages router 쓰는 쪽 입장
    • next.js가 나온지 얼마나 오래됐는데! 이미 존재하는 프로젝트에 투입되면 적응 힘들다!
    • 더 직관적이다! app router에서 새롭게 제시하는 내용이 정말 효용이 있는지 모르겠다!
  3. 정말로 중요한 것??

    Next.js가 제시하는 본질. 기존 React.js가 가지고 있는 한계를 이해하고 내가 왜 Next.js를 사용하는지를 정확히 알고 있어야 한다.
    따라서 app router든 pages router든 주요 핵심 개념(Routing, Rendering, Data Fetching 등) 을 잘 이해하면 된다.
    app router로 배운 상태에서 pages router를 사용하는 회사에 들어가도라도 핵심 개념만 이해하고 있다면, 내가 배운게 pages에서는 이렇게 구현되는구나 하고 빠르게 적응할 수 있습니다.

MPA부터 SSR까지

핵심 개념을 이해하는게 제일 중요하고, 가장 핵심 개념인 렌더링 기법을 알아보자

  1. 원시적 방법, MPA
  • 원시적 서버 사이드 렌더링 방식인 MPA로부터 프론트엔드 웹 개발은 시작되었다.
/about -> about.html
/profile -> profile.html
  • 페이지 이동시 및 렌더링 시 깜빡거리는 현상이 있으므로 UX가 저하
  • 이러한 문제 때문에 React, Angular, Vue 등 SPA가 등장
  1. 획기적 방법, SPA
  • 브라우저에서 JS를 이용해 동적으로 페이지를 렌더링 하는 방식
    Client의 사이드에서 렌더링을 한다라는 개념은 기존 프론트엔드 개발자들에게 획기적 방법으로 소개
  • 최초 서버로부터는 텅 빈, root라는 id를 가진 div만 다운로드 => js로 UI완성
  • 더 이상 새로고침이나 깜빡거림 없이 웹서비스 이용이 가능하여 UX가 크게 향상
  • 그러나 다음과 같은 단점이 새롭게 대두
    • 늦는 초기 로딩속도
      1. 이를 보완하기 위해 Code Splitting(Lazy-Loading)방법 제시
      2. 하나로 번들된 코드를 여러 코드로 나눠 당장 필요한 코드가 아니면 나중에 불러옴
  1. 주요 렌더링 기법을 다음과 같이 분류

    build라는 용어가 어려우면, 소스코드를 실행 가능한 상태로 만들어 놓는 과정이라고 생각하면 된다. vercel을 통해 자동으로 배포가 되기 했다면, vercel 내부적으로 build 하는 과정을 포함함

  • CSR(Client Side Rendering)
    • 특징

      • 순수 리액트 사용했을 때 100%
      • 브라우저에서 JS를 이용해 동적으로 페이지를 렌더링 하는 방식
      • 렌더링의 주체 : 클라이언트
    • 장점

      • (최초 한번 로드가 끝나면) 사용자와의 상호작용이 빠르고 부드럽다
      • 서버에게 추가적인 요청을 보낼 필요가 없기 때문에, 사용자 경험이 좋다
      • 서버 부하가 적음
    • 단점

      • 첫 페이지 로딩 시간(Time To View)이 길 수 있다
      • JS가 로딩되고 실행될 때까지 페이지가 비어있어 검색 엔진 최적화(SEO)에 불리
        (컴퓨터 입장에선 초기 화면 div밖에없음)
    • 코드

      import React from 'react';
      import ReactDOM from 'react-dom';
      
      function App() {
      	return <h1>Hellom, Client Side Rendering!</h1>;
      }
      
      ReactDOM.render(<App />, document.getElementById('root'));
  • SSG(Static Site[변하지 않는] Generation)
    • 특징

      • 서버에서 페이지 렌더링하여 클라이언트에게 HTML을 전달하는 방식
      • 최초 빌드시에만 생성이 됨
      • 같이 '빌드'라는 것을 해보면
        - 우린 지금까지 yarn build, npm run build 등의 명령어를 통해 빌드 파일을 직접 생성해본적이 없었다
        - vercel을 이용할 때 알아서 build해주기 때문에 Local 환경에서 빌드할 필요가 없었었다
      • 사전에 미리 정적 페이지를 여러개 만들어놓음 -> 클라이언트가 홈페이지 요청을 하면, 서버에선 이미 만들어져있는 사이트를 바로 제공! -> 클라이언트는 표기만 함
    • 장점

      • 첫 페이지 로딩 시간이 매우 짧아(TTV) 사용자가 빠르게 페이지를 볼 수 있음. 또한 SEO에 유리
      • CDN(Content Delivery Network) 캐싱 가능
    • 단점

      • 정적인 데이터에만 사용할 수 있음
      • 사용자와의 상호작용이 서버와의 통신에 의존하므로, 클라이언트 사이드 렌더링보다 상호작용이 느릴 수 있고 서버 부하가 클 수 있음
      • 마이페이지처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가
    • 코드(next.js 12 버전)

      import React from 'react';
      
      function HomePage({ data }) {
      	return <div>{data}</div>;
      }
      
      export async function getStaticProps() {
      	const res = await fetch('https://...');
        const data = await res.json();
        
        return { props: {data}};
      }
      
      export default HomePage;
  • ISR(Incremental Static Regeneration)-점진적으로 스태틱을 다시 만들어냄
    (SSG인데 가끔씩은 다시 만들어 줌 [build])
    • 특징

      • SSG처럼 정적 페이지 제공
      • 설정한 주기만큼 페이지를 계속 생성
        (주기가 10분이면 10분마다 데이터베이스 또는 외부 영향때문에 변경된 사항 반영)
      • 정적 페이지 먼저 보여주고, 필요에 따라 서버에서 페이지 재생성하는 방식
    • 장점

      • 정적 페이지를 먼저 제공하므로 사용자 경험이 좋으며, 콘텐츠가 변경되었을 때 서버에서 페이지를 재생성하므로 최신 상태를(그나마)유지할 수 있음
      • CDN 캐싱 가능
    • 단점

      • 동적인 콘텐츠를 다루기에 한계가 있을 수 있습니다. 실시간 페이지 아님
      • 마이페이지 처럼 데이터에 의존하여 화면을 그려주는 경우 사용 불가
    • 코드

      import React from 'react';
      
      function HomePage({ data }) {
      	return <div>{data}</div>;
      }
      
      export async function getStaticProps() {
      	const res = await fetch('https://...'); // 외부 API 호출
        const data = await res.json();
        
        return {
        	props : { data },
            revalidate: 60, // 1초 후 페이지 재생성
        }
      }
      
      export default HomePage;
  • SSR
    • 특징
      • 빌드 시점에 모든 페이지를 미리 생성하여 서버 부하를 줄이는 방식
      • SSG, ISR처럼 렌더링 주체가 서버
      • 클라이언트의 요청 시 렌더링
        - C -> S : 이 페이지 줘!
        • S -> C : (데이터베이스 읽고 등등 이후) Html파일 제공
    • 장점
      • 빠른 로딩 속도(TTV)와 높은 보안성을 제공
      • SEO 최적화 좋음
      • 실시간 데이터를 사용
    • 단점
      • 사이트의 콘텐츠가 변경되면 전체 사이트를 다시 빌드해야 하는데, 이 과정이 시간이 오래 걸릴 수 있음 -> 서버 과부하
      • 요청할 때 마다 페이지를 만들어야 함
    • 코드
  • (종합)비교
  1. Hydration

    TTV, TTI 그리고 Hydration
    우리가 Next.js를 이해할 때는 위 언급한 세 개념. TTV, TTI, HYdration의 개념이 상당히 중요하다. 이 개념을 아는지 모르는지에 따라 렌더링 패턴을 이해하고 쓸 수 있느냐가 결정되기 떄문

  • CSR
    • React에서 CSR로만 컴포넌트 렌더링할 땐 TTV가 오래 걸렸음. 모든 React 소스파일을 다운 받아야만 화면을 볼 수 있었기 때문
    • 여기서 Hydration 개념. 최초 서버엔 index.html파일만 제공하지만 이후 React 소스 파일을 바탕으로 한 자바스크립트 파일이 모드 다운로드 되어야만(즉, Hydration이 되어야만) 최종 소스코드를 볼 수 있음
      but CSR의 과정에서의 Hydration 과정을 Hydration으로 볼 것이냐 하는 건 이견이 있을 수 있음
  • SSR
    • 서버에서 사용자의 요청이 있을 때 마다 페이지를 새로 그려 사용자에게 제공
    • 두 과정으로 나눠서 제공
      1. pre-rendering : 사용자와 상호작용하는 부분을 제외한 껍데기만을 먼저 브라우저에게 제공. TTV가 매우 빠름
      1. hydration : 이 과정이 일어나기 전까진 껍데기만 있는 html 파일이기 때문에 사용자가 아무리 버튼을 click 해도 아무 동작이 일어나지 않음. 인터렉션에 필요한 모든 파일을 다운로드 받는 과정 즉, hydration 과정이 끝나야 그제서야 인터렉션이 가능. 이 간극! TTI를 줄이는 것이 관건임
  • SSG, ISR도 SSR과 마찬가지로 hydration 과정이 존재함

Routing(핵심)

  1. 첫 installation : react와는 어떤 것이 다른지 특징!

    • 설치
      공식 홈페이지 내용 참조하여 설치

      npx create-next-app@latest

    그 후 전부 yes로 세팅

    • 특징
      1. src > app directory
      1. typescript 기반인것 확인

        3. 기본 파일 2가지

        layout, page 이 두 컴포넌트를 굉장히 많이 다루게 됨

        <layout.tsx>
        스타일링을 규정하는 컴포넌트
        children을 가지고 있다는게 중요
        리액트 컴포넌트

        <page.tsx>
        리액트 컴포넌트

        <tailwind.config.ts>

        <package.json>
        특히 next.js에선 "scripts"쪽 dev / build / start를 특히 체크해야함
        개발 시엔 dev모드
        local컴퓨터에서 build를 하면 start를 할 수도 있음

      • dev(npm run dev) : 개발 단계에서 사용
      • build(npm run build) : production 레벨로 배포하기 전 필요한 빌드 작업 과정 실행 위한 방법
      • start(npm run start) : 만들어진 build 파일을 이용하여 실행
        dev에선 변경사항 즉각 반영되지만 build start에선 꼭 변경사항 변경 후 재 build를 해야만 변경사항이 적용됨

        yarn dev로 실행하니 잘 실행됨
        page.tsx에 있는 내용이 화면에 나오고 있음

        바로바로 적용되는 모습
        yarn build 후 yarn start도 정상적으로 되지만
        혹여나 localhost:3000번을 이미 실행중이라면
        다른 포트번호로는 build가 안되기 때문에 꼭 이전 포트를 사용중인 프로젝트가 있다면 종료 후 사용해야 한다
  2. 라우팅을 이해하기 위한 주요 용어

    • Tree
      • 계층 구조를 시각적으로 잘 보기 위한 규칙(위->아래). DOM tree와 비슷
    • Subtree
      • tree의 한 부분
      • root부터 시작해서 leaf들에 이르기까지의 범위
    • Root
      • Tree 또는 Subtree의 첫 번째 노드
      • root layout 같은 것
    • Leaf
      • children이 더 이상 필요 없는 노드
    • URL Segment
      • 슬래시()로 분류된 URL path의 한 부분
    • URL Path
      • 도메인(www.saple-web.com) 이후 따라오는 전체 URL 부분
  3. 파일(폴더) 기반 라우팅

  • 스태틱 라우팅 - 변하지 않는 화면 출력

    이런 식으로 app 아래 폴더명을 두고 그 안에 파일을 page.tsx를 두면 path쪽에 파일명을 입력하면 그 내용이 출력된다

  • 다이나믹 라우팅 - 변하는 화면 출력

    일단 폴더 안에 [id]라는 명의 폴더를 하나 더 생성
    page.tsx 파일을 생성
    params에 대한 객체 안에 id를 string으로 type선언해준다
    div에 {params.id}로 세팅해주면 /test/00 <<
    어떤 숫자를 적느냐에 따라 다이나믹하게 본문에도 그 숫자를 배치할 수 있게 해준다
    기존 react에서는 react-router-dom에서 설정한걸
    next.js에선 폴더명으로 세팅해준다고 인지하면 된다

  • 라우트 그룹 - 경로에 포함 되지 않는 파일

    지금 보는 것처럼 () 괄호 안에 폴더명을 기입하게 되면 실제 경로에서는 그 폴더명은 빠지게 된다
    다만 이렇게 하는 이유는 폴더명을 보고 구분짓고 유지보수를 위해 경로까지 반영되지 않게라고 생각하면 될 것 같다

  1. 특별한 파일들
  • Layout.tsx
    기본적으로 react에선 상위 라우터가 하위 라우터의 스타일을 정해준다

    라우트 그룹인 (marketing)폴더 안에 있는 폴더들 즉 파일들은 다 marketing에 대한 layout.tsx의 영향을 주고싶다면 (marketing)폴더 안에 layout.tsx 파일을 생성하고, 아래 파일들에 영향을 끼칠 children에 대해 타입을 선언해준 뒤,
    <div>
      <p>여기는 마케팅과 관련된 페이지가 놓이는 곳입니다.</p>
      {children}
    </div>

이런식으로 기재하게 되면
p와 관련된 내용은 marketing안에 어떤 경로로 들어가도 동일하게 보여지고,
{children}만 해당 파일의 내용에 따라 바뀌게 출력되게 된다


그리고 이렇게 초기 layout.tsx에 본문 {children}위에 nav바를 넣어주게 되면 해당 폴더가 어디에 위치하느냐에 따라 세부 layout.tsx의 영향을 받아서 내용이 조금씩 바뀌게 된다.


이렇게 상위 코드에 "use client";를 넣은 컴포넌트 같은 경우
test폴더 안에 넣은 layout.tsx 파일의 내용이지만,
어떤 Link를 눌러 이동하더라도,
우측에 콘솔에 보이는 것처럼 렌더링이 되지 않으면서 이동이 된다

그러나

위의 파일명처럼 layout.tsx를 template.tsx로 바꿔주면??
link따라 움직일 때 마다 렌더링이 계속 진행된다(새로고침 한 것 처럼)

  • template
    layout과 상당히 유사한 컴포넌트. 그래서 두 요소는 늘 비교 대상이 됨

    상태를 유지하는가? 리-렌더링이 일어나는가?

이 부분이 가장 두드러진 차이이다.
경로 전반에 걸쳐서 상태가 유지되는 레이아웃과 달리, 템플릿은 라우팅을 탐색할 때 각 하위 항목에 대해 새 인스턴스를 만듬. 즉, User입장에서 동일한 Template을 공유하는 경로 사이를 왔다 갔다 할 때 DOM 요소가 다시 생성된다는 것을 의미한다
그래서 이러한 use-case가 있다

  • 템플릿을 통한 페이지 open animation

    • 페이지 간 전환 시 애니메이션을 계속해서 주고 싶을 때
    • layout으로 만들어 놓으면, 최초 렌더링시에만 animation이 적용되고 끝나버림
  • useEffect, useState에 의존하는 기능

  • not-found

    원치 않는 경로로 간 유저들을 위한 화면을 출력하고 싶다면
    not-found.tsx 파일에서 내용을 채워주면 된다.

  • metadata와 SEO
    Next.js는 기본적으로 Metedata를 가지고 있음(프레임워크!)

    향상된 SEO를 제공하기 위해 기존 우리가 html head에 삽입했었던 많은 정보를 metadata는 객체 형태로 지원
    react에선 vite든 cra든 index.html파일이 존재했고, 이 파일의 head 태그에 SEO향상을 위해 여러 meta, link태그 등 메타데이터를 작성했었다

SEO
Search Engine Optimization, 검색엔진최적화
웹사이트나 웹페이지를 검색 엔진에서 더 높은 순위에 노출시키기 위한 방법
SEO는 검색 결과에서 웹사이트가 더 위에 나타나도록 만드는 여러 기술과 전략
ex) img태그 내의 alt 속성은 SEO를 위해 상당히 중요

<img src='../assets/sample.jpg" />
<img src='../assets/sample.jpg" alt="sample image" />
  1. 검색 엔진에 이미지 내용 설명하기
    alt 텍스트는 검색 엔진에 이미지의 내용과 맥락을 설명.
    검색 엔진은 이미지 자체를 보지 못하므로, alt 텍스트를 통해 이미지가 무엇에 관한 것인지 이해하고, 관련 검색 쿼리에 대한 결과로 해당 이미지를 더 정확하게 랭킹
  2. 접근성 향상
    alt 텍스트는 시각 장애가 있는 사용자가 웹 사이트의 이미지 콘텐츠를 이해하는 데 도움을 줌. 이러한 접근성 개선은 검색 엔진에 의해 긍정적인 신호로 해석되어, 전반적인 사이트의 SEO 점수를 향상

그러나 Next.js에선 Config-based Metadata를 활용할 수 있음
1. static

  • page.tsx든 layout.tsx든
    export const metadata: Metadata = {
    	title: "Sparta Next App",
    	description: "This is awesome Website",
    }
    이 코드를 삽입하면 적용됨
    • metadata in page.tsx : 해당 page.tsx 컴포넌트에만 적용
    • metadata in layout.tsx : 해당 layout의 하위 요소에 모두 적용
  1. dynamic
  • dynamic route를 갖고 있는 route에서 동적으로 변경되는 params를 기반으로 metadata를 변경하고 싶을 땐, generateMetadata function을 사용하면 됨
import React from "react";
 
 type Props = {
 	params : {
    	id: string;
    };
 };
 
 export function generateMetadata({params}" Props){
 	return {
    	title: `Detail 페이지 : ${params.id}`,
        description: `Detail 페이지 : ${params.id}`,
    };
 }
 
const TestDetailPage = ({ params }: Props) => {
  return <div>Detail 페이지 : {params.id}</div>;
};

export default TestDetailPage;


이런식으로 동적으로 들어온 params에 대해서도 metadata 이용 가능!!

  1. 페이지 이동과 관련된 기능 목록

    react-router-dom에서 페이지 이동에 관한 기능이 있듯, Next.js에서도 역시 이러한 기능을 제공함

  • Link

    Next.js는 Link 라는 리액트 컴포넌트를 제공합니다. link 태그는 기본 HTML의 a 태그를 확장한 개념. 크게 두가지 주요 역할을 하기 때문에 우리는 기본 a태그를 사용하기 보단 Link 태그를 사용해야 한다

    • Link 태그는 prefetching을 지원
      + Next.js의 Link 컴포넌트는 뷰포트(보고 있는 곳)에 링크가 나타나는 순간 해당 페이지의 코드와 데이터를 미리 가져오는 프리페칭 기능을 지원. 사용자가 링크를 클릭했을 때 거의 즉시 페이지를 볼 수 있게 합니다.

      뷰포트가 링크에 나타나는 순간?
      사용자가 웹 브라우저에서 현재 보이는 부분. 쉽게 말해, 스크롤을 하기 전에 사용자가 볼 수 있는 화면의 영역. 따라서 뷰포트를 링크가 나타나는 순간이라 함은, 사용자가 웹 페이지를 스크롤하거나 페이지를 이동하면서 해당 링크가 실제로 사용자의 화면(즉 뷰포트 내)에 보이기 시작하는 순간을 의미

      사용자의 마우스가 링크 위에 mouseover 되는 순간 네트워크 요청이 생긴다는 것인가?
      기본적으로 Link컴포넌트에 의해 렌더링된 링크가 사용자의 뷰포트 내에 나타나는 순간, Next.js는 해당 페이지의 데이터와 필요한 자원(ex) JS파일)을 미리 가져오기 시작합니다. 마우스 오버보다 더 넓은 개념으로, 링크가 화면에 보이기만 하면 프리페칭이 시작. 이 프리페칭은 페이지를 더 빠르게 로드할 수 있도록 미리 준비하는 과정

    • Link 태그는 route 사이에 client-side navigation을 지원

      • Link 컴포넌트는 브라우저가 새 페이지를 로드하기 위해 서버에 요청을 보내는 대신, 클라이언트 측에서 페이지를 바꾸어 주기 때문에 페이지 전환 시 매우 빠른 사용자 경험(UX)을 제공
    • 페이지의 HTML을 서버에서 다시 가져올 필요 없이, 필요한 JSON 데이터만 서버로부터 가져와서 클라이언트에서 페이지를 재구성하여 렌더링
  • useRouter

    Next.js에서 페이지를 이동 시킬 수 있는 3대장

  1. a태그 vs Link vs Router
    • a 태그

      • 순수 HTML 요소
      • 완전한 새 페이지로 전환을 원할 때 : 페이지는 완전히 새로고침 됨
      • 빈 화면 보일 수 있음 => UX 좋지 않음
      • Next.js에서는 Link 또는 Router를 사용합니다!
    • Link 태그

      • 위 설명 참조
      • 결국 Link 태그는 a 태그를 만들어내기 때문에 SEO가 유리
        (브라우저에선 a태그가 보임)
      • 클릭 즉시 페이지 이동
    • Router(useRouter)

      useRouter를 사용할 때는 항상 코드 최상단에 "use client"를 삽입해야 합니다. Rendering 파트에서 다루게 됩니다

      • a 태그를 알아차릴 수 없기 때문에 크롤러 입장에서는 해당 요소가 '이동을 원한다'라는 것을 알 수 없음 => SEO 불리

      • 대부분 onClick 같은 이벤트 핸들러에서 사용

      • 클릭 후 로직의 순서에 따라 실행하므로, 즉시 이동이 아님

      • 실습해보기

        일단 페이지 간 이동이기 때문에 next/router가 아닌 navigation으로 세팅해야함

        router.push를 통해 페이지 이동을 시킬 수 있는데 상단에 'use client'를 적지 않으면 실행이 안되는 점 참고!!

      • router.push, router.replace, router.back, router.reload

    • router.push

      • 새로운 URL을 히스토리 스택에 추가
      • 사용자가 router.push로 페이지 이동하면 이동한 페이지의 URL이 히스토리 스택의 맨 위에 쌓임
      • 이후 사용자가 브라우저의 뒤로가기 버튼을 클릭하면, 스택에서 가장 최근에 추가된 URL로부터 이전 페이지(URL)로 돌아감
    • router.replace

      • 현재 URL을 히스토리 스택에서 새로운 URL로 대체
      • 현재 페이지의 URL이 새로운 URL로 교체되며, 뒤로가기 클릭했을 때 이전 페이지로 이동하지만, 교체된 페이지로는 돌아갈 수 없습니다
      • 현재 페이지를 히스토리에서 완전히 대체합니다
    • router.back

      • 사용자를 히스토리 스택에서 한 단계 뒤로 이동시킵니다
      • 마치 브라우저의 뒤로가기 버튼을 클릭한 것과 같은 효과를 내며, 사용자를 이전에 방문했던 페이지로 돌아가게 합니다.
    • router.reload

      • 현재 페이지를 새로고침합니다
      • 히스토리 스택에 영향을 미치지 않습니다. 페이지의 데이터를 최신 상태로 업데이트하고 싶을 때 사용할 수 있습니다.
  2. Tailwind CSS
    • 세팅
      필요없음. create-next-app에서 세팅 되어있음
    • 사용방법
      웹사이트 접속
      원하는 디자인을 검색
      React 컴포넌트의 className에 삽입
      (한번만 따라하면 매우 쉽다 ㅎㅎ)

Rendering

  • v12와 v13의 주요 차이점

    • v12까진 CSR,SSR,ISR,SSG 이러한 렌더링 방식을 '페이지 단위'로 규정
      ex) about 페이지는 SSG로 동작 / todolist 페이지는 SSR로 동작 / sample페이지는 CSR로 동작
      그러나 v13에선 React 18 버전에서 제시한
      + 서버컴포넌트(서버상에서만 동작)
      + 클라이언트컴포넌트(브라우저에서만 동작)
      렌더링 방식이 '페이지 단위'가 아닌 '컴포넌트 단위'로 변경
      즉 한 페이지 안에도 여러 렌더링 방식이 공존할 수 있게됨


      이렇게 다양하게 공존함
  • 클라이언트 컴포넌트 vs 서버 컴포넌트(composition pattern)

    • 기본적으로 app 폴더 하위의 모든 컴포넌트는 서버컴포넌트이다
    • 서버 컴포넌트
      • 서버상에서 실행되는 컴포넌트
        (console.log가 검사창이 아닌 터미널에서 뜸!!)
    • 언제 SC/CC를 써야하나?
      • user와의 상호작용이 있는경우 CC, 그 외의 경우 SC를 쓰도록 권장
        처음이라 잘 모르겠으면 일단 SC로 쓰고 오류가 뜨면 CC로 바꿔주자!!

        보이는 것처럼 서버 컴포넌트 안에 클라이언트 컴포넌트를 넣으면 두 가지가 공존하는 composition pattern을 적용할 수 있다!!
        즉 컴포넌트 분리가 어느때보다 중요!!
  • 렌더링 이해를 위한 핵심 개념 이해

    • SSG(Static Site Generation

      fetch한 데이터는 영원히 변치 않음. 계속 컴포넌트를 갱신할 필요가 없음

    SSG는 빌드타임 때만 컴포넌트를 생성하고, 이후는 변하지 않는 페이지로 가정하여 static 컴포넌트를 제공하는 것을 말한다. 그리고 Next.js는 아무것도 하지 않으면 기본적으로 SSG로 동작

    • ISR(Incremental Site Regeneration)

      fetch한 데이터는 가끔 변함. 일정 주기마다 가끔씩만 컴포넌트를 갱신

    ISR은 빌드타임 때 컴포넌트를 초기 생성하고, 이후는 일정 주기마다 변화를 적용하여 컴포넌트를 제공하는 것

    • SSR(Server Side Rendering)

      fetch한 데이터는 실시간으로 계속 바뀜. 컴포넌트 요청이 있을 때 마다 데이터를 갱신해서 최신 데이터만 제공

    SSR은 빌드타임 때 컴포넌트를 초기 생성하고, 이후 컴포넌트 요청이 있을 때 마다 변화를 적용하여 가장 최신의 데이터를 user에게 제공

    • CSR(Client Side Rendering)

      fetch한 데이터는 실시간으로 계속 바뀜. ㅁ컴포넌트 요청이 있을 때 마다 데이터를 갱신해서 최신 데이터만 제공

    CSR은 빌드타임에 컴포넌트를 초기 생성하진 않음. JS로 이루어진 리액트 파일을 다운로드 받고 그제서야 화면이 그려지게 됨

  • 주요 렌더링 패턴 4가지를 직접 구현해보기(with fetch) --- 매우 중요!!
    (코드로 진행하였음) - 다른 TIL에 있음

클라이언트 컴포넌트와 서버 컴포넌트

fetch와 주요 옵션을 통한 렌더링 이해

fetch를 활용해 주요 렌더링 패턴 이해

Route Handlers

Next.js의 이점에 대해 설명할 때 늘 full-stack 개발이 가능한 웹 프레임워크로 소개했음. 이 부분을 만족시키는게 Route Handler.

Full Stack이란?


웹 애플리케이션이 정상적인 모습을 갖추기 위해선 아래의 내용이 필요함

  • FE=FrontEnd
    • 브라우저 상(또는 모바일 앱 등)에 보여지는 부분으로 UI(User Interface)영역
  • BE=BackEnd
    • 외부의 어떤 요청이 발생하였을 때, 데이터핸들링 등 주요 비즈니스 로직을 수행하는 영역
  • DB=DataBase
    • 백엔드에 의해 핸들링되는, 웹 애플리케이션에서 관리되는 모든 데이터베이스

그래서 보통 이런 시스템 구성도가 예상됨

우리의 경험과 연결 지어보기

백엔드를 직접 구축할 수 없었을 땐 이렇게 프로젝트를 구성했다

백엔드 로직 신경쓰지 않고, json-server supabase firebase 등에 요청만 함
(Baas)

BaaS는 Backend as a Service의 약자로, 모바일 및 웹 애플리케이션 개발 시 서버 측 기능을 클라우드 서비스 형태로 제공하는 것

Baas도 서비스이며, 그에 따른 비용을 부담해야하고, 속도도 내부 로직이 아니기 때문에 상대적으로 느릴 수 밖에 없어 Next.js를 통해 백엔드 직접 구현해야 한다

Router Handlers

Web요청 및 응답 API를 다루는 것. HTTP를 배우며 웹 환경에서 요청과 응답을 서로 주고받는 방법을 배웠고, 그것은 대체로 REST API로 설명이 됨

  • GET / POST / PATCH / PUT / DELETE

router handlers에서 이 부분을 만들 수 있음

서버컴포넌트, 클라이언트 컴포넌트 개념을 포함하는 React컴포넌트 개념을 벗어나 우린 routes.ts 파일을 다루게 됨

app directory 내부에 route.ts 파일을 만나면 기본적으로 Next.js는 router handler로 인식

Router handlers 체험하기

새로운 폴더 app>api>apiTest를 만든 후, 하위에 route.ts 파일을 만듬

이 내부 로직으로 접근해서 request 즉 요청을 하면 내부 함수 로직이 실행됨(콘솔)

Thunder Client에서 요청방식에 따라 해당 URL을 실행시키면 node에 console.log가 찍히게 된다

실습환경 설명


실제 db를 연결하기엔 복잡하므로 JSON-Server로 대체하고 연습해보기
1. Next.js가 프론트, 백엔드 역할을 모두 함
2. (중요) Next.js의 백엔드(route.ts)는 직접 데이터베이스와 통신할 수 있지만, 세팅 등 절차가 다소 복잡하여 json-server를 구축하고 데이터베이스 서버라고 가정

GET,POST,PATCH,DELETE 실습

백엔드를 만들어야 하기 때문에 렌더링이 일어나는 페이지를 만드는 것이 아님

  • pages.tsx로직이 호출할 백엔드
  • 외부의 어떤 시스템에서 호출할 백엔드
    와 같이 별도 시스템으로서의 백엔드
  1. 환경세팅
    1 src>app>api>practice>route.ts 파일 생성
    2 json-server 설치 - yarn add json-server
    3 db.json을 생성하여 todos를 만들기
    가장 최상단에 db.json 파일 생성하고 그 안에 값 넣어주기

    4 다음 명령어를 통해 DB 서버를 시작

    yarn json-server db.json --port 4000


    route.ts에 GET방식에 대해 사진과 같이 처리
    나처럼 human error를 조심하기..!!


그 후 실제 백엔드인 route.ts 내용을 호출하면 위와 같이 안의 내용이 잡힌다


이런식으로 직접 db json 안에 내용을 백엔드 환경에서 추가할 수도 있음~!!

POST는 말 그래도 게시를 db.json에 해주는 요청이기 때문에 thunder client에서 body 부분에 객체 형태의 title, contents값을 넣어주기로 하고, 그 body 부분을 stringify를 통해 합쳐주면??

이렇게 요청할 수 있고,


보이는 것처럼 새로운 객체가 생성된다.

  1. GET POST 코드

React Query(tanstack query) 세팅하기

User와 인터랙션 하는 단계를 위해서는 CSR이 필요할 수 밖에 없다. 리스트 추가 후 invalidate queries 등을 활용하기 위해선 이전에 배운 tanstack query가 필요

  1. 패키지 설치

    yarn add @tanstack/react-query

  2. query provider를 담는 생성

    layout에 쿼리를 적용해야 모든 컴포넌트에 적용이 되기 때문에 여기에 담을 예정이고,

    queryClient는 이곳저곳에서 선언하는게 아닌 딱 한번 선언해주면 된다.

    그 후 앞서 선언한 queryClient를 연결해주면 children에게 전부 적용할 tanstack Query 세팅 끝!!

  3. RootLayout 변경

    그 후 layout.tsx에 children을 이렇게 감싸주면 된다!!

Next로 TodoList 만들기

이렇게 해주면 정상적으로 todos url에서 console.log가 잘 찍히게 된다

이제 return문쪽 수정을 위해서 type 선언을 해줘야 하는데,

이건 다른 TIL에서 다뤄보도록 하겠다... 아 어렵다 ㅠㅠㅠ

============================================================

이어서 next.js에서 a 앵커 대신 Link를 사용해야 하는 이유

  • SPA 유지를 위해
    Link 컴포넌트는 클라이언트 측 라우팅을 처리하여 페이지 전체를 새로고침하지 않고도 페이지 간 전환이 가능
    사용자 경험 향상 & 성능 최적화

  • 서버에서 불러오는 완전한 페이지 & SPA 두 가지의 장점 활용 가능
    클라이언트 측 라우팅을 통해 SPA의 장점을 제공하면서도 서버 측에서 페이지를 사전 렌더링하는 기능을 활용할 수 있음
    SEO 최적화와 초기 로딩 속도 개선에 도움이 됨

profile
웹 개발자 되고 시포용

0개의 댓글