Javascript/NextJS

[NextJS] NextJS Routing Files

  • -
728x90

https://wonillism.tistory.com/318

 

[NextJS] NextJS 13

예전에 NextJS로 SSR은 아니고, SSG로 프로젝트를 한 번 진행해본적이 있었다. 간단한 프로젝트이기도 했고, SSR이 목적도 아니었어서, 어렵지 않게 해결할 수 있었다. NextJS를 한 번 써보자라고 생각

wonillism.tistory.com

앞서 보았던 app Routing Conventions 에 있던 Routing File을 자세히 알아보자.  

 

확실히 프레임워크라 그런지 React에서는 일일이 해야했던 작업들을 미리 정의해둔 기능들이 많았다.  

이전에 Nest 튜토리얼을 맛봤을 때는 이게 왜 이렇게 작동하는지 왜 필요한지 감이 잘 안왔었는데, React를 쓰다가 Next를 써보니 확실히 느낌이 왔다. 뭔가 라이브러리와 프레임워크가 확실히 와닿는달까 ... 

 

page [.js, .jsx, .tsx] 와 layout [.js, .jsx, .tsx]

next create app을 해보면 app 폴더에 존제하는 layout 파일이다. 필수 파일이며, 없으면 에러가 난다.

처음에는 그냥 최상단에서 html 태그(header, main, footer 등)을 정의하는 단순한 레이아웃 파일인줄 알았다. 하지만 그게 아니었다...

 

우선 src/app/layout.tsx 파일을 먼저 알아보자.

 

import type { Metadata } from "next";
import { Inter } from "next/font/google";

import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "chat-app",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        {children}
      </body>
    </html>
  );
}

요런 식으로 생겼다. 

 

src/app/page.tsx 파일은 아래와 같이 초기화해줬다.

export default function Home() {
  return <main>Home</main>;
}

루트 경로로 들어가면 보여질 페이지이다.

 

다시 레이아웃으로 돌아가서

<html lang="en">
  Hello World!
  <body className={inter.className}>ddd{children}</body>
</html>

위 코드와 같이 작성하면 아래와 같은 에러를 볼 수 있다.

Hello World! 텍스트 코드가 html 태그 안에 있다고 경고하고, 머 서버의 초기 ui와 일치하지 않아서 실패했다고 한다.

<html lang="en">
  <body className={inter.className}>Hello World! ddd{children}</body>
</html>

body 태그안으로 옮겨주면 문제 없이 작동한다.

 

다음으로 네비게이션 바를 만들어보자. 아래와 같이 Header 컴포넌트를 구성했다.

import Link from "next/link";

import React from "react";

interface LinkOptions {
  id: number;
  title: string;
  path: string;
}
const links: LinkOptions[] = [
  { id: 2, title: "About", path: "/about" },
];

const Header = () => {
  return (
    <header>
      <Link href="/">Logo</Link>

      <nav>
        {links.map((link) => (
          <Link key={link.id} href={link.path}>
            {link.title}
          </Link>
        ))}
      </nav>
    </header>
  );
};

export default Header;

그런다음 RootLayout에 헤더를 추가해주자.

header 태그는 body 태그 안에 있어야하니 body 태그 안으로~

 

src/app/layout.tsx

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Header />
        {children}
      </body>
    </html>
  );
}

그 다음 about 페이지를 만들어보자.

import React from "react";

const About = () => {
  return <div>About Page</div>;
};

export default About;

브라우저를 확인해보면 아래와 같이 구성되는 것을 확인할 수 있다. about을 누르면 about 페이지로, logo를 누르면 home 페이지로

여기까진 뭐.. 그런데 하나 신기했던점이 있다. 이전 블로그나 공식문서에 보면 Routing Convention 밑에 Routing Files가 있는데 이게 page를 제외하고 나머지 파일들은 그냥 최상단 디렉토리에 있는 파일이라고 생각했었는데, 그게 아니었다. 그냥 직관적으로 생각하면된다. app 디렉토리 아래에 디렉토리를 만들면 그건 routing 디렉토리이고 Routing Files는 그 안에 들어가는 파일들인 것이다.

 

about 디렉토리 아래에 layout.tsx 파일을 하나 만들어보자. 

import React from "react";

const AboutLayout = () => {
  return <div>AboutLayout</div>;
};

export default AboutLayout;

자 이렇게 하면 다음과 같은 브라우저를 확인할 수 있다.

AboutPage 텍스트가 사라지고 AboutLayout이 생겨버렸다. 어 이거 언젠가 겪었던 상황인데?? 

react-router-dom v6부터 oulet 기능을 하면서 겪었던 상황이다. 중첩 라우팅을 레이아웃 용도로 사용했는데 <Outlet /> 처리를 안해줘서 왜 레이아웃만 나오지 하면서 짜증냈었던... ㅋㅋㅋ

 

자 그러면 여기서는 어떻게 처리해야하나, children prop 을 이용하면 된다.

import React, { ReactNode } from "react";

interface AboutLayoutProps {
  children: ReactNode;
}

const AboutLayout = ({ children }: AboutLayoutProps) => {
  return (
    <div>
      AboutLayout
      {children}
    </div>
  );
};

export default AboutLayout;

children 처리를 하면 이제 AboutPage가 잘 나오는걸 확인할 수 있다.

 

자 그러면 loading 을 한 번 만들어볼까?

about 디렉토리 아래에 loading.tsx를 만들어 보자.

import React from "react";

const AboutLoading = () => {
  return <div>Loading...</div>;
};

export default AboutLoading;

그런 다음 개발자 도구의 네트워크 탭에서 스로틀링을 다음과 같이 걸어주면

그러면 로딩 컴포넌트가 보였다가 About Page를 확인할 수 있다. 캡쳐하기가 힘들다....

 

이 뿐만 아니라 다른 Routing file 들도 이런식으로 작동할 것이다.

 

 

 

 

 

역시 프레임워크... 리액트로 구성했던 것들을 떠올리면서 이렇게 구성되어있구나 파해쳐보니 신기하기도하고 재밌기도하다.

728x90
300x250
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.