Next.js 기초 정리

siwoo jang·2024년 3월 31일
0
post-thumbnail

보호된 파일명

NextJS에는 일부 보호된 파일명이 있다.

이 파일명들은 app/폴더(부 폴더 포함) 내부에서 생성될 때만 보호된다.
app/폴더 외부에서 생성될 경우 이 파일명들을 특별한 방식으로 처리하지 않는다.

다음 목록은 NextJS에서 보호된 파일명들이다.

page.js => 신규 페이지 생성 (예: app/about/page.js은 /about page을 생성)

layout.js => 형제 및 중첩 페이지를 감싸는 신규 레이아웃 생성

not-found.js => ‘Not Found’ 오류에 대한 폴백 페이지(형제 또는 중첩 페이지 또는 레이아웃에서 전달된)

error.js => 기타 오류에 대한 폴백 페이지(형제 또는 중첩 페이지 또는 레이아웃에서 전달된)

loading.js => 형제 또는 중첩 페이지(또는 레이아웃)가 데이터를 가져오는 동안 표시되는 폴백 페이지

route.js => API 경로 생성(즉, JSX 코드가 아닌 데이터를 반환하는 페이지, 예: JSON 형식)

보호된 파일명 공식 문서 : https://nextjs.org/docs/app/api-reference/file-conventions

Dynamic Routing

CSS 모듈 사용

이름.module.css 파일을 만들고
main-header.js파일에서 import main-header.module.css 파일을 가져와서

  import classes from './main-header.module.css'
  <header className={classes.header}> ...
   <nav className={classes.nav}> ...

이렇게 사용하면 된다

이미지 컴포넌트

Next.js에서 이미지를 사용할때는 Image라는 태그를 next/image에서 import해와서 사용하는 것이 좋다.

이미지 컴포넌트가 페이지를 로드할때 불필요한 깜빡임이나 새로고침이 일어나지 않게 하려면,
가능한 빨리 로딩 될 필요가 있다.

 import Image from 'next/image'
 ...
<Image src={logoImg} alt = "A plate with food on it" priority/>

우선적으로 로딩되게 하는 priority 속성을 주면 해결된다.

fill 속성을 사용하면 부모 요소에 꽉차도록 이미지가 적용된다
(주의: fill은 부모요소가 포지셔닝 된것만 적용됨)

  <Image src="/image.jpg" fill/>

object-fit: cover 속성을 사용해서 브라우저를 줄이거나 늘렸을 때 이미지 비율이 깨지지 않게 막을 수 있다

  <Image  src="/image.jpg" style={{ objectFit: "cover" }} fill />

클라이언트 컴포넌트

Next.js는 기본적으로 서버 사이드 랜더링으로 돌아가지만,
몇몇 페이지같은 경우 클라이언트 사이드 랜더링으로 짜야 할 필요가 있다 ex> 5초마다 바뀌는 그림

클라이언트 컴포넌트를 작성하려면 간단하게 'use client'를 파일 맨 위에 추가하면 된다.

이런식으로 쓰면 된다.

  
  import { usePathname } from 'next/navigation'
  ...
  
  export default function Header() {

    const path = usePathname();
  ...
  	<Link href="/meals" className={ path.startsWith('/meals') 
          ? classes.active : undefined}>Browse Meals</Link>
    <Link href="/community" className={ path === '/community' 
          ? classes.active : undefined}>Foodies Community</Link>

usePathname() 훅을 이용해서 현재 경로를 탐지하고,
현재 어떤 페이지에 있는지 Nav바가 보여주게 하이라이트 할 수 있다.

그러나 클라이언트 컴포넌트는 최대한 아랫단계의 트리에 작성하는 것이 좋다.
따라서 nav-link.js 파일을 만들고,

'use client';

import Link from 'next/link'
import { usePathname } from 'next/navigation'
import classes from './nav-link.module.css'

export default function NavLink({href,children}) {

    const path = usePathname();

    return (
        <Link href={href} className={path.startsWith(href) 
        ? `${classes.link} ${classes.active}` 
        : classes.link}>
            {children}
        </Link>
    )
}

메인 헤더에서 클라이언트 컴포넌트를 import 해서 사용하는 것이 좋다.
특정 부분을 제외한 나머지 부분을 서버에서 계속 랜더링되게 할 수 있다.

...
import classes from './main-header.module.css'
import NavLink from './nav-link'



export default function Header() {

  return (
      <>
...
          <nav className={classes.nav}>
              <ul>
                  <li>
                      <NavLink href="/meals">Browse Meals</NavLink>
                  </li>
                  <li>
                      <NavLink href="/community">Foodies Community</NavLink>
                  </li>
              </ul>
          </nav>
      </header>
  </>)
}

데이터베이스

npm install better-sqlite3

로컬에서 세팅없이 바로 데이터베이스 이용할 수 있게 함
깔고 initdb.js 파일 루트 디렉토리에 놓고, 루트 디렉토리에서
node initdb.js 실행하면 meals.db가 생성됨

loading 은 페이지와 연관된 다른 페이지들에 로딩페이지를 보여주는 파일명이다.
현재 page들과 하위 page들이 로딩중일때 이 컴포넌트가 실행된다

// lib>meals.js
import sql from 'better-sqlite3'

const db = sql('meals.db');

export async function getMeals() {
    await new Promise((resolve)=> setTimeout(resolve,2000));
    return db.prepare('SELECT * FROM meals').all();
}
    
//meals>page.js
    // 이런식으로 async, await으로 가져와서 사용 가능 
    async function Meals() {

    const meals = await getMeals();

    return <MealsGrid meals={meals} />

}

Suspense는 리액트에서 제공하는 컴포넌트로,
일부 데이터가 불러와질때까지 로딩 상태를 처리하고 대체 컨텐츠를 표시한다.
데이터를 불러오는 Meals Function이 있을떄 이것을 suspense로 감싸줘서, fallback 함수를 표시해서 사용할 수 있다.

   
import { Suspense } from 'react';
   
<Suspense fallback={<p className={classes.loading}>Fetching meals...</p>}>
     <Meals />
</Suspense>

이제 Next.js는 새로고침없이 , 랜더링 할 수있는 콘텐츠로 부분적으로 랜더링한 후에
로딩된 컨텐츠를 스트리밍하여 랜더링 한다. 더 나은 사용자 경험을 제공할 수 있는 것이다.

profile
프론트/백엔드 개발자입니다

0개의 댓글