Published on

NextJS Basic Features

NextJS Basic

프로젝트 생성

$ npx create-next-app@latest

package.json

{
  "name": "nextjs-intro",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "12.1.4",
    "react": "18.0.0",
    "react-dom": "18.0.0"
  },
  "devDependencies": {
    "eslint": "8.12.0",
    "eslint-config-next": "12.1.4"
  }
}
  • 정상적으로 작동하는지 npm run dev로 실행
  • 웹 브라우저 상의 localhost:3000로 접근해서 index.js 페이지가 뜨는지 확인

index.js

export default function Home() {
  return 'hi'
}
  • http://localhost:3000 첫 페이지(root page) 설정
  • router나 다른 설정을 따로 하지 않아도 파일명을 가져가서 url으로 접근할 수 있음
    • ex) pages/about.js
      • http://localhost:3000/about 로 접근
  • '/' -> root path는 반드시 index.js 이름을 가져야 함

Next.js의 주요 특징 명세

Pages

  • root path('/')를 제외한 나머지 path는 파일명을 따라감
    • component 이름은 중요하지 않음
    • 존재하지 않는 페이지는 404 error page를 만들지 않아도 따로 만들어 줌

      404error

  • React.js 라이브러리와 다르게 Next.js 프레임워크는 정해놓은 몇 가지 규칙이 있음
    • component를 export default로 내보내야 함
      • ex) Server Error 발생 시 메시지
        • Error: The default export is not a React Component in page: "/blabla"
    • useEffect, useState와 같은 method를 사용할 경우에는 react를 import 해야 함
      • 파일 포맷이 jsx지 않아도 react import를 기본적으로 지원함

Pre-rendering

  • 앱에 있는 페이지들이 미리 렌더링 되어 있음

    CRA(create-react-app)

    • client-side render 방식
      • react.js가 만들어주는 javascript 코드

        noscript

      • div id root 일 뿐 유저가 보는 HTML 소스코드 안에 들어있지 않음
      • 브라우저가 자바스크립트, react.js를 fetch한 후에 client-side의 자바스크립트가 모든 UI를 만듦
      • 자바스크립트가 비활성화 되어 있을 때에는 noscript의 내용을 보여줌(흔한 상황은 아님)
      • 하지만 네트워크 환경이 느린 사용자는 어떤 UI를 보지 못하고 로드가 완료되기 전까지 흰 화면만 보게되는 상황 발생

    Next.js

    • 네트워크 환경이 느리거나, 자바스크립트가 비활성화되어 있어도 어떠한 형태의 HTML을 볼 수는 있음
      • 유저가 페이지를 요청하면 일반 client-side rendering 방식과는 다르게 미리 HTML을 만들어 줌
      • SEO 이슈에 좋음
      • 좋은 사용자 경험을 할 수 있음
        • 사용자의 브루아저가 코드를 다운받아서 react를 실행시키기까지 기다리지 않아도 됨
    • react.js를 프론트엔드 안에서 실행하는 hydration 방식
      • react.js를 백엔드에서 동작시켜서 페이지를 미리 만듦

Routing

잘못된 Routing 예시

<nav>
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>
  • react.js와 마찬가지로 anchor tag href 속성을 사용하지 말아야 함

올바른 Routing 예시

import Link from 'next/link' // Next Link import 해야 함
;<nav>
  <Link href="/">
    <a>Home</a>
  </Link>
  <Link href="/about">
    <a>About</a>
  </Link>
</nav>
  • Link component로 a tag를 감싸줘야 함
  • a tag에서는 href 제외한 나머지 속성을 적용할 수 있음

useRouter hook 지원

import { useRouter } from 'next/router'
  • router를 설치하지 않아도, hook을 통해 router의 속성을 응용할 수 있음
import Link from 'next/link'
;<Link href="/">
  <a style={{ color: router.pathname === '/' ? 'red' : 'blue' }}>Home</a>
  // router의 pathname 속성을 이용해 a tag의 style을 변경
</Link>

CSS Modules 지원

.module.css 패턴

  • [component_name].module.css 패턴 이용해서 독립된 style 적용

component_name.modules.css

.nav {
  display: flex;
  justify-content: space-between;
  background-color: tomato;
}

component_name.js

import styles from './component_name.module.css'
import Link from 'next/link'
;<nav className={styles.nav}>
  <Link href="/">
    <a>Home</a>
  </Link>
  <Link href="/about">
    <a>About</a>
  </Link>
</nav>
  • 장점
    • module.css를 import해서 평범한 CSS를 사용할 수 있게 해줌
    • 개발자도구로 보면 [component명]_[className]_[randomText] 형태로 클래스 이름이 생성됨
    • 다른 컴포넌트에서도 nav 클래스 이름을 사용해도 충돌이 나지 않는 장점이 있음
    • 같은 클래스 이름을 재사용할 수 있음
  • 단점
    • 소스 파일 관리가 용이하지 못함
    • 해당 module.css의 class명을 찾아야하는 번거로움 발생

Styles JSX

  • Next.js 어플리케이션에서 style을 추가하는 또 다른 방법
  • 일반 HTML 태그인 <style>을 이용한 NextJS 고유의 방식
<style jsx>{`
  nav {
    background-color: tomato;
  }
  a {
    text-decoration: none;
  }
`}</style>
  • jsx props를 추가하고 { + `(백틱)으로 감싸줌
  • javascript 문자열이므로 style value에 ${props}도 사용 가능함
  • 개발자 도구로 html을 확인하면 jsx-[random text] 형태의 클래스 이름이 생성됨
  • 파일 추가없이 독립된 module을 구성할 수 있음
  • global props를 추가해서 전역적인 style 적용 가능
    • NextJS는 page-based concept이라서 페이지별로 추가해야 하는 단점

Custom app

  • 공통 컴포넌트(ex. navbar, footer)를 위해 app component를 생성
  • _app.js 파일을 생성하여 pages/_app.js 경로에 위치
  • index.js를 렌더링하기 전에 _app.js 먼저 확인함(blueprint)

_app.js

export default function App({ Component, pageProps }) {
  return (
    <>
      <div>
        <Navbar />
        <Component {...pageProps} />
      </div>
    </>
  )
}
  • Component Props으로 _app.js 파일 내의 App 함수에 전달
  • 모든 페이지에서 공통으로 보여질 component를 Fragment 안에 넣을 수 있음
  • styles/*에 위치한 globals.css를 페이지 단위에서 import할 수 없지만, app component에서는 import가 가능함

Referenced