본문 바로가기
내일배움캠프/Today I Learned

[TIL 2023.08.02] Next.js 기본 개념

by 괴코딩 2023. 8. 2.

💻오늘 배운 내용

Library vs Framework

라이브러리와 프레임워크의 주요 차이점은 "Inversion of Control"(통제의 역전)이다.
라이브러리에서 메서드를 호출하면 사용자가 제어할 수 있다.
그러나 프레임워크에서는 제어가 역전되어 프레임워크가 사용자를 호출한다.

라이브러리
사용자가 파일 이름이나 구조 등을 정하고, 모든 결정을 내림 => React

프레임워크
파일 이름이나 구조 등을 정해진 규칙에 따라 만들고 따름 => Next

 

즉, React와 Next.js의 렌더링 프로세스 차이를 비교하자면..
- React: 주문을 받고 음식을 만들기 시작하는 식당.
- Next.js: 음식을 미리 만들어서 바로 내놓는 식당.

 

Next.js

nextjs는 React로 만드는 서버사이드 렌더링(SSR) 프레임 워크다.

 

기존 React의 문제점

1. 클라이언트 렌더링의 경우 모든 js 파일을 로드하고 사용자는 웹을 보게됩니다. -> 많은 시간을 대기해야 한다.

2. seo 문제 - 구글의 검색엔진의 경우 자바스크립트가 로드되지 않은 페이지를 검색엔진으로 스캔 : 결론적으로 검색에 아무 페이지도 걸리지 않게 된다.

 

이 두가지를 해결하는 것이 서버렌더링이다.

 

1. 서버에서 자바스크립트를 로딩함으로 클라이언트 측에서는 자바스크립트를 로딩하는 시간이 줄어들게 된다.

2. 검색엔진이 자바스크립트를 읽는 것이 아닌 서버 측에서 자바스크립트, html, css를 만들어 컨텐츠를 직접 업로드 함으로 검색엔진에 게시글이 걸리게 된다.

3. meta 태그를 자유롭게 추가함으로 seo를 용이하게 할수 있다.

 

Next.js가 제공하는 주요 기능

hot reloading

개발 중 저장되는 코드는 자동으로 새로고침 된다.

 

automatic routing

pages 폴더에 있는 파일은 해당 파일 이름으로 라우팅 된다. (pages/page1.js -> localhost:3000/page1)

public 폴더도 pages의 폴더와 동일하게 라우팅 할 수 있다. (그러나 모든 사람이 페이지에 접근할 수 있으므로 지양)

 

single file components

styled jsx를 사용함으로 컴포넌트 내부에 해당 컴포넌트만 스코프를 가지는 css를 만들수 있다.

  • <style jsx global>를 사용하면 글로벌로 스타일 정의 가능
  • 글로벌 스타일은 _app.tsx에만 정의 가능하다. 다른 컴포넌트에 정의한 경우 다른 클래스와 겹쳐 오류를 발생할 수 있음으로 _app에서만 허용한다. 

server landing

서버렌더링을 한다.

클라이언트 렌더링과 다르게 서버렌더링을 한 페이지의 페이지 소스보기를 클릭하면 내부에 소스가 있다.

 

code splitting

dynamic import를 이용하면 손쉽게 코드 스플리팅이 가능하다.

코드 스플리팅 : 내가 원하는 페이지에서 원하는 자바스크립트와 라이브러리를 렌더링 하는 것

모든 번들(chunk.js)이 하나로 묶이지 않고, 각각 나뉘어 좀 더 효율적으로 자바스크립트 로딩 시간을 개선할 수 있다.

 

typescript

타입스크립트 활용을 위해 웹팩을 만지거나 바벨을 만질 필요 없다.

타입스크립트를 설치하고

yarn add typescript @types/node @types/react 
yarn run dev

명령어만 입력하면 자동으로 tsconfig, next-end.d.ts가 생성되어 타입스크립트로 코딩이 가능하다.

 

Pages

pages 폴더 안에 있는 파일명에 따라 route가 결정된다.

pages/about.js 생성 ->
localhost:3000/about (O)
localhost:3000/about-us(X)

다만 예외사항으로, index.js의 경우에는 앱이 시작하는 파일이라고 보면 된다.
즉 localhost:3000 그 자체다. 경로는 '/'. 

Next에서는 import react from "react"를 쓸 필요가 없다.
다만 useState,useEffect, lifecycle method 같은 애들을 써야 할 경우에는 꼭 import를 해줘야 한다.

 

****

NextJS 13 버전부터는 pages 폴더가 자동생성 되지 않고, app 폴더가 생성된다.
이전 버전: root/pages/about.js => /about
13부터: root/app/about/page.js => /about

 

Styled JSX

컴포넌트 레벨의 CSS 

Next.js는 CSS 모듈 지원, CSS 파일 이름을 지을 때 아래의 네이밍 컨벤션에 따라 작성하면 된다.

 .module.css 확장자를 가진 파일에 한하여 가능

 
CSS-in-JS

현존하는 어떠한 종류의 CSS-in-JS든지 간에 Next.js에서 사용할 수 있다.

가장 단순한 방법은 아래와 같이 인라인 스타일로 작성하는 것

function HiThere() {
  return <p style={{ color: 'red' }}>hi there</p>
}

export default HiThere

또한 Next.js는 각각의 독립적인 스코프를 갖는 CSS를 지원하기 위해, styled-jsx를 제공한다.

function HelloWorld() {
  return (
    <div>
      Hello world
      <p>scoped!</p>
      
      // styled-jsx
      <style jsx>{`
        p {
          color: blue;
        }
        div {
          background: red;
        }
        @media (max-width: 600px) {
          div {
            background: blue;
          }
        }
      `}</style>
      
      // styled-jsx 글로벌하게 사용 시
      <style jsx global>{`
        body {
          background: black;
        }
      `}</style>
    </div>
  )
}

export default HelloWorld​

 

Custom App

Next.js는 App 컴포넌트를 사용하여 page를 초기화 한다. 

초기화와 재정의 제어를 통해 아래의 기능을 제공한다.

1. 페이지 변경 간에 레이아웃 유지
2. 페이지 탐색 시 state 유지
3. componentDidCatch를 사용한 Custom 에러 처리
4. 페이지에 추가 데이터 삽입
5. Global CSS 추가

 

❓발생한 이슈/고민

직접 코드를 쳐보면서 실습하던 중 Link 태그에 style-jsx 적용이 안되는 문제가 생겼다.

// NavBar.js

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function NavBar() {
  const router = useRouter();
  console.log(router);

  return (
    <nav>
      <Link href="/" className={`link ${router.pathname === '/' ? 'active' : ''}`}>
        Home
      </Link>
      <Link href="/about" className={`link ${router.pathname === '/about' ? 'active' : ''}`}>
        About
      </Link>

      <style jsx>{`
        nav {
          background-color: tomato;
        }
        .link {
          text-decoration: none;
        }
        .active {
          color: yellow;
        }
      `}</style>
    </nav>
  );
}

클래스를 줘도 .link와 .active 둘 다 적용이 안되는 것!

 

💡해결과정

처음에 <style jsx global> 과 같이 글로벌을 붙여주어서 css를 적용시켜 주었는데,

이렇게 하니 이번엔 다른 컴포넌트에서 동일 클래스 사용하면 같이 적용 되어 버리는 문제가 생겼다.

NavBar 컴포넌트에서 사용한 .active를 index.js에서 사용하면 같이 적용 됨!

// index.js

export default function Home() {
  return (
    <div>
      <NavBar />
      <h1 className="active">Hello</h1>
    </div>
  );
}

같이 노래져 버리는 홈 텍스트..

 

span 태그로 Link 태그의 텍스트 감싸주고 스타일 적용,

global을 빼니 어떻게 해도 밑줄이 안사라진다.

 

 

 

 

span 태그로 Link 태그의 텍스트 감싸주고 스타일 적용, 

그런데 이제 global을 빼니 어떻게 해도 밑줄이 안사라진다.

// NavBar.js

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function NavBar() {
  const router = useRouter();
  console.log(router);

  return (
    <nav>
     <div className="link">
      <Link href="/">
        <span className={router.pathname === '/' ? 'active' : ''}>Home</span>
      </Link>
      <Link href="/about">
        <span className={router.pathname === '/about' ? 'active' : ''}>About</span>
      </Link>
     </div> 

      <style jsx>{`
        nav {
          background-color: tomato;
        }
        .link {
          text-decoration: none;
        }
        .active {
          color: yellow;
        }
      `}</style>
    </nav>
  );
}

 

해결방법은 Link 태그에 legacyBehavior 적용하는 것!

 

<Link> 태그에 legacyBehavior를 넣어주면 링크태그 아래에 <a> 태그 사용이 가능하고 스타일을 적용할 수 있다.

(* 12 버전까지는 됐었던건데, 13 버전으로 오면서 링크태그 아래에 a태그를 사용하면 오류가 났었는데 이걸 legacyBehavior로 가능하게 한 것)

import Link from 'next/link';
import { useRouter } from 'next/router';

export default function NavBar() {
  const router = useRouter();
  console.log(router);

  return (
    <nav>
      <Link href="/" legacyBehavior>
        <a className={`link ${router.pathname === '/' ? 'active' : ''}`}>
          Home
        </a>
      </Link>
      <Link href="/about" legacyBehavior>
        <a className={`link ${router.pathname === '/about' ? 'active' : ''}`}>
          About
        </a>
      </Link>

      <style jsx>{`
        nav {
          background-color: tomato;
        }
        a {
          text-decoration: none;
        }
        .active {
          color: tomato;
        }
      `}</style>
    </nav>
  );
}

해결해결

 

🧐궁금점과 부족한 내용

styled-jsx는 편리하고 다 좋은데 css 자동완성이 안된다.

그동안 매우 편하게 써온 입장에서 갑자기 있다 없으니까 매우 불편한 것!

 

찾아보니 역시나 선구자들이 이미 vscode 익스텐션을 만들어 놓았다.

 

styled-jsx Language Server

 

바아로 깔아줬다.

 

📋레퍼런스

Docs | Next.js

next.js 기본 개념 알아보기

NextJS 시작하기 – 노마드 코더 Nomad Coders

 

반응형