quickStart : NextJS

55555-Jyeon·2024년 2월 20일
0

Let's

목록 보기
6/12
post-thumbnail
post-custom-banner
😎 본 게시글의 예시는 nomadcoders의 강의를 기반으로 작성했습니다.

NextJS ?

next.js에 대한 자세한 설명은 다른 게시글로 옮겼습니다.
👉 next.js 특징 알아보기

Let's NextJs

⬇️ install

npm init -y

npm init을 하게 되면 폴더 안에 package.json 파일이 생성됩니다.
파일의 내용 중 license 부분을 "MIT"로 바꿔주세요.

{
  "name": "next14",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "MIT" ✔️
}

npm i react@latest next@latest react-dom@latest

react, next, react-dom 세 가지를 모두 최신 버전으로 설치 후 다시 package.json의 내용 중 script를 아래와 같이 변경해주세요. 이제 dev 명령어를 실행하게 되면 next.js가 실행됩니다.

{
  "name": "next14",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "next dev" ✔️
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "next": "^14.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

😎 quick start

router

app/page.tsx

다음으로는 app이라는 폴더 안에 page.tsx 파일을 생성해줍니다.
이름은 반드시 app/page.tsx 이어야 합니다. NextJs를 실행하게 될 경우 app 폴더 안의 page 파일을 찾게 돼 있기 때문에 다른 이름으로 설정 시 실행이 정상적으로 되지 않습니다.

파일 생성 후 안에 기본적인 component를 export해주세요.
이때 함수의 이름은 원하는대로 설정해주셔도 됩니다.
처음 코드를 치게 되면 위와 같이 에러가 뜰텐데 신경쓰지 말고 그냥 터미널에 npm run dev 명령어를 입력해 실행시켜 주세요.

에러가 나는 이유는 typescript를 설치하지 않아서 입니다.
에러를 뒤로 하고 바로 NextJs를 실행시키게 되면 NextJs는 터미널에 아래와 같은 메세지를 띄워준 뒤 그대로 진행해줍니다.

It looks like you're trying to use TypeScript but do not have the required package(s) installed.
typescript를 사용하려고 하시는데 설치가 되어 있지 않네요. 설치 후 실행시키겠습니다.

그러면 page에 입력한 내용이 localhost에 정상적으로 보여지게 되며 에러도 사라집니다.

그리고 터미널을 살펴보면 또 무언갈 생성했다고 안내 문구가 띄워져 있습니다.

Your page app/page.tsx did not have a root layout. We created app/layout.tsx for you.
page에 root layout이 없으시네요. 당신을 위해 저희가 생성해드렸습니다.

react만 사용했을 때 비슷한 걸 본 적이 있을 겁니다.
layout과 outlet, 그리고 react-router-dom.

react-router의 작동방식은 지정된 url(path)에 해당하는 component(element)를 요청하는 겁니다.

NextJs에서는 위와 같은 과정 대신 파일 시스템을 통해서 url을 표현해야 합니다.
정해진 규칙에 맞게 폴더 구조를 따른다면 정말 편리하게 경로를 설정할 수 있습니다.

처음에 생성한 app 폴더의 최상위 page 파일은 root("/") segment, 이용자가 가장 먼저 보게 될 페이지입니다.

이제 여기에 새로운 경로의 페이지를 만들고 싶다면 어떻게 해야 할까요?

폴더를 새로 생성 → 최상위에 page 파일 생성

폴더의 이름이 슬래시(/)뒤 경로 이름이 되고 page 파일 안의 내용이 보여지게 됩니다.
위 이미지에서 제가 만든 걸 예시로 들자면 경로는 localhost:3000/about-us가 되는 겁니다.

경로 이동을 할 필요가 없는 폴더에는 page 파일을 생성하지 않으면 react에서 사용했던 것과 같이 그대로 이용할 수 있습니다.

예를 들면 components 폴더 안에 사용할 component 파일을 생성 후 page 파일에 import하면 react 때와 동일하게 component가 보여지는 페이지를 만들 수 있습니다.

url이 변경되어야 하는 폴더 안에만 page 파일을 생성해주면 됩니다. ⭐️


dynamic route

/movies/:id

NextJs에서는 동적 라우팅을 폴더의 구조로 구현할 수 있습니다.

(movies)/movies/[id]/page.tsx

(movies)로 되어 있기 때문에 /movies 경로로만 이동했을 때에는 아무 것도 보이지 않지만 특정 id 값을 뒤에 전달하게 되면 선택된 영화의 detail-page로 넘어갈 수 있도록 할 수 있습니다.

저 dataId 값은 해당 page의 props를 console에 찍어보면 알 수 있습니다.

터미널에 정상적으로 제가 적은 id 값이 찍히는 걸 확인할 수 있습니다.
params 뿐만 아니라 searchParams 값도 가져올 수 있습니다.


⛔️ 404 ErrorPage

NextJs에서 기본적으로 보여주는 404 not-found 페이지가 있습니다.
이 부분을 내가 의도한 화면으로 바꾸고 싶을 때에는 폴더 안에 not-found.tsx 파일을 생성해주면 됩니다.

그렇게 하면 내가 의도한 custom 404 error-page를 보여줄 수 있게 됩니다.
react의 error-boundary와 같은 역할이지만 보다 간편하게 구현할 수 있습니다.


🗺️ navigation

app/navigation/navigation.tsx

태그는 anchor 태그 대신 Link 태그를 사용할 겁니다.
a 태그를 사용하게 될 경우 페이지 이동 시 페이지가 강제로 새로고침 됩니다.
이를 hard navigation이라고 합니다.

반면에 Link 태그를 사용하면 새로고침 없이 페이지 이동이 가능합니다.
이는 클릭이 발생 시 react가 가로 채서 페이지를 새로고침 없이 보여주기 때문이고 이를 client side only navigation이라고 합니다. 이 태그는 react에서도 제공되고 next에서도 따로 제공해주고 있습니다.

NextJs에서는 경로와 관련해서 usePathname hook 함수를 사용할 수 있습니다.
분명 import해서 사용했는데 에러가 발생합니다.

usePathname은 client components에서만 동작하기 때문에 코드의 최상단에 "use client"를 넣으라고 하네요.

react에서 strict-mode를 적용할 때처럼 최상단에 적어주면 에러가 사라지는 것을 볼 수 있습니다. usePathname은 해당 page의 router를 가져오는 훅함수입니다. 따라서 위와 같은 삼항연산자로 선택된 Link에 아이콘도 추가할 수 있습니다.

만든 Navigation component를 layout 파일 안에 import 해주면 모든 페이지에서 navigation을 사용할 수 있게 됩니다.

React만 사용해서 만들 때보다 필요한 파일의 개수가 적어 좋은 것 같기도 하네요 :)


🎬 metadata

export const metadata = {
  title: "Next.js",
  description: "Generated by Next.js",
};

layout 파일의 맨 위에 있는 metadata 객체는 웹 페이지나 어플리케이션의 정보를 정의하고, 이 정보를 이용해 페이지의 제목이나 설명 등을 동적으로 설정할 수 있습니다.

결과적으로 이를 활용하면 페이지의 SEO(Search Engine Optimization)를 개선하거나 사용자에게 더 풍부한 정보를 제공하는 데 사용될 수 있습니다.

title : 브라우저 탭에 표시되는 제목(title)으로 사용됩니다.
description : 웹 페이지의 간단한 설명이나 메타데이터에 사용됩니다. 검색 엔진이나 소셜 미디어 등에서 페이지를 공유할 때 설명으로 활용될 수 있는 부분입니다.

나중에 favicon도 여기에 넣어줄 수 있을 것 같아요.


🥞 multi-layout

페이지에는 보통 여러 개의 레이아웃이 필요합니다.

인스타그램의 디자인을 99% 참고해 만들었던 복습용 토이 프로젝트를 예로 들어보겠습니다.

로그인과 회원가입 페이지에는 footer만 존재합니다. 그리고 가운데 content의 width가 100% (혹은 100vw) 만큼 차지하고 있습니다.

로그인해서 home으로 들어가게 되면 새로운 레이아웃을 적용해줘야 합니다.

상단에는 친구 목록을 slider로 넘길 수 있는 header(?)가 존재하고, 좌측 옆에는 menu-bar가 자리를 차지하고 있습니다. 하위 페이지들 중에서 home과 같은 레이아웃을 갖는 페이지들도 있고,

my-page 같이 header가 없는 레이아웃을 갖는 페이지들도 있습니다.


이렇게 다른 레이아웃들을 react에서는 layout과 outlet, 그리고 react-router를 활용해 여러 개의 레이아웃과 children element를 별도로 설정해 적용할 수 있었습니다.

const router = createBrowserRouter([
  {
    element: <Layout />,
    children: [
      { path: "/", element: <SignInPage /> },
      { path: "/sign-up", element: <SignUpPage /> },
    ],
  },
  {
    element: <ProtectedLayout />,
    children: [
      { path: "/home", element: <HomePage /> },
      { path: "/home:page", element: <HomePage /> },
      { path: "/explore", element: <ExplorePage /> },
      { path: "/my-page", element: <MyPage /> },
      { path: "/message", element: <ChattingPage /> },
    ],
  },
]);

NextJs에서는 어떻게 여러 개의 레이아웃을 설정할 수 있을까요?

1️⃣ nest-layout

폴더 안에 새로운 layout 파일을 만들어주면 됩니다.

이렇게 하면 이제 about-us 폴더 안에 생성되는 하위 page들에는 전부 이 layout이 적용되게 됩니다. (+ 전역 layout도 중첩돼서 적용 )

1. NextJs가 render를 하려고 app/page와 app/layout의 존재를 확인
	(전역 layout과 root-page 확인)

2. 폴더 별로 page와 layout의 존재를 확인

3. layout이 있다면 중첩해서 적용

2️⃣ multi-layout

route-groups 를 생성해줌으로써 다중 레이아웃을 설정할 수 있습니다.

(home) : 폴더 이름을 괄호로 감싸주세요.
이런 식으로 폴더 이름을 지정하게 되면 URL 변경이 되지 않고 에러도 발생하지 않습니다. 괄호로 묶여 있는 폴더는 URL을 생성하지 않습니다.


🪃 data fetching

1️⃣ client component

"use client";

import { useEffect, useState } from "react";
const URL = "https://nomad-movies.nomadcoders.workers.dev/movies";

export default function HomePage() {
  const [isLoading, setIsLoading] = useState(true);
  const [movies, setMovies] = useState([]);
  const getMovies = async () => {
    const res = await fetch(URL);
    const json = await res.json();
    setMovies(json);
    setIsLoading(false);
  };

  useEffect(() => {
    getMovies();
  }, []);
  return <div>{isLoading ? "...loading" : JSON.stringify(movies)}</div>;
}

client component로 data를 가져오게 되면 우선 metadata를 사용할 수 없습니다. 사용자가 사이트에서 로딩 중임을 UI로 확인할 수는 있지만 내부적인 코드 로직이 별로입니다.


2️⃣ server component

export const metadata = {
  title: "Home",
};

const URL = "https://nomad-movies.nomadcoders.workers.dev/movies";

async function getMovies() {
  const response = await fetch(URL);
  const json = await response.json();
  return json;
}

export default async function HomePage() {
  const movies = await getMovies();
  return <div>{JSON.stringify(movies)}</div>;
}

server component에서 data fetch를 하게 되면 브라우저 화면에서는 loading되는 것을 확인할 수 없습니다.
server에서 이미 다운로드를 진행한 후 보여주는 것이기 때문입니다.

console에 찍어서 확인해보면 터미널에서 데이터를 가져오고 있음을 알 수 있습니다. 브라우저에서 확인하고 싶다면 아래 setTimeout을 활용해 테스트해 볼 수 있습니다.

await new Promise((Resolve) => setTimeout(Resolve, 5000));

이렇게 하면(위 코드를 getMovies 안에 넣어주면) 사용자가 해당 주소로 접근하려고 해도 들어가지지 않고 5초가 지나야 들어가지는 것을 확인할 수 있습니다. 이는 UI가 아니라 브라우저에서 로딩 중임을 알려주게 되는 것입니다.

🚦 loading

client component처럼 UI에서 데이터가 로딩 중임을 보여주면서 server component의 코드를 그대로 사용하려면 loading.tsx 파일을 만들어주면 됩니다.



gitHub에서 코드 자세히 보기 👉 55555-Jyeon's start NextJs

profile
🥞 Stack of Thoughts
post-custom-banner

0개의 댓글