[NextJS] 구조

Jimin·2024년 4월 9일
0

Next.JS

목록 보기
2/13

폴더 구조

  • layout.tsx: root 페이지
  • url은 app 폴더 아래에 폴더 이름으로 생성 가능
    Next.js가 시작될 때 프레임워크로서 웹 사이트를 빌드하는데,
    이때 웹사이트의 첫번째 페이지를 app폴더 안 page와 layout이라는 파일에서 찾으려고 한다.

Next.js ➡️ app 폴더 ➡️ page.tsx 파일, layout.tsx 파일 (이름이 변하면 안됨)
➡️ 이 안에 있는 컴포넌트 확인
(이 컴포넌트의 이름은 상관 없음, 보통은 Page이고 반드시 export default 된 react 컴포넌트여야 한다.)

page.tsx 예시 코드

export default function page() {
  return <h1>Hello NextJs!</h1>
}

모듈 내보내고 가져오기

참고

  • export default
    • import 함수명 from * 사용
    • 해당 모듈엔 개체가 하나만 있다’는 사실을 명확히 나타낼 수 있다.
  • export
    import { 함수명 } from * 사용

layout

layout에는 기본 export 객체가 두 개 있다.

  • metadata 객체
    export
  • RootLayout 객체
    • export default
    • 자식 객체를 받음

이미지 파일 위치

  • public 폴더 아래에 넣고 '/'로 접근

ex)

<img src="/direction.svg"></img>

ROUTING

사용자가 요청한 url에 따라 해당 url에 맞는 페이지를 보여주는 것

Router

SPA 기법을 그대로 유지한 채로 React 페이지 이동처리하는 방법

react-router

NextJS 없이 기본적인 React 애플리케이션에서 라우팅하는 방법.

사용자가 입력한 주소를 감지하여 여러 환경에서 동작할 수 있도록 여러 종류의 router component를 제공한다.

react-router 작동방식

url 지정 ➡️ component 요청

예시) /about-us url 접근 ➡️ AboutUs 컴포넌트 연결

하지만, NextJS에서는 이렇게 직접 url을 적어줄 필요가 없다!

NextJS Routing

NextJS에서는 app 폴더 하단에 폴더만 만들어주면 된다!

app > page folder > page.tsx file

  • 여러 폴더가 중첩되면 url이 길어진다.
http://localhost:3000/about-us/compony/sales
  • page.tsx file이 있어야 실제 페이지가 된다. (꼭 이름이 page 여야함!)

폴더가 있어도 page 파일이 없으면 실제 경로에 포함되지도, 렌더링되지도 않는다.
따라서 app 폴더 하위에 다른 파일을 넣어도 괜찮다.
위의 예시 같은 경우 page라는 이름의 파일이 존재하지 않으므로 component는 url 이 되지 않는다.

Not Found Routes

app > not-found.tsx : 없는 경로로 url 요청시, 보여지는 화면

  • <a> 태그 사용시, 브라우저의 네비게이션을 사용하게 됨
  • <link> 태그를 사용해야 프레임워크의 네비게이션을 사용하게 됨
import Link from "next/link";

export default function Navigation() {
    return (
        <nav>
            <ul>
                <li>
                    <Link href="/">Home</Link>
                </li>
                <li>
              		<Link href="/about-us">About Us</Link>
              	</li>
            </ul>
        </nav>
    );
}

UsePathname

NextJS에는 우리에게 url에 관한 정보를 알려주는 hook 이 有
➡️ router까지 접근할 수 있게 한다.

path name : user 가 현재 머물고 있는 url

단, usePathname은 오직 client component에서만 작동한다.

React Hook이란?

리액트 혹은 리액트 클래스형 컴포넌트에서 이용하던 코드를 작성할 필요 없이,
함수형 컴포넌트에서 다양한 기능을 사용할 수 있게 만들어준 라이브러리
ex) useState/useEffect

NextJS가 application을 render하는 방식?

rendering이란?

NextJS가 우리의 react component를 가져와서 브라우저가 이해할 수 있는 html로 변환하는 작업.
React code ➡️ HTML

리액트가 render되는 방식: CSR,

  • 브라우저가 rendering 작업을 함.
  • 즉, client가 사용자 브라우저에 UI를 구축하는 것.

NextJS가 render되는 방식: SSR,

  • 웹사이트 빌드 시, 자동으로 SSR이 된다.
  • 기억해야할 것은, 이렇게 자동으로 SSR 방식으로 빌드되는 것이 모든 컴포넌트에 대해 발생한다는 것이다.
    • client components 이든, server components 이든, use clients를 쓴 컴포넌트이든!
    • 즉, 모든 컴포넌트들과 페이지가 backend에서 render 된다!

Hydration

React활성화되는 과정.
➡️ 즉, 단순 HTML을 React application으로 초기화하는 작업.

Hard Navigation : anchor 태그를 눌러 이동하기 때문에 전체 페이지가 로드되며 페이지를 이동한다.

처음에는 anchors묶음 ➡️ React Component로 변환
(처음에는 dummy html ➡️ 사용자가 페이지에 도착
➡️ 프레임워크가 dummy html을 react application으로 초기화
➡️ hard refresh 없이, navigate 가능)

  1. 사용자가 /about-us 접근
  2. <button>0</button> 0을 사용자에게 전달 (그냥 0인 걸 받음)
  3. 프레임워크 로드
  4. 프레임워크가 initialize될 때 이 버튼이 우리가 만든 onClick eventListener가 연결된 버튼이 된다.
  5. 이렇게 되면 페이지가 interactive해진다. ➡️ 이것이 바로 hydration 프로세스!

단, 이 hydration 과정이 모든 component에 대해 발생하지는 않는다.
➡️ 그렇다면? Client에서 hydrate되는 component는,
오직 use client 지시어를 맨 위에 갖고 있는 component들 뿐이다.

그러니까 나는 interactive할 컴포넌트들에 use client 를 추가하면 되는 것이다.
➡️ use client : backend에서 render되고 frontend에서 hydrate되는 것을 의미한다.

use client를 쓴 컴포넌트들이 client component가 되고,
↔️ 반대로, use client를 안쓴 컴포넌트들이 server component가 된다.

Server component

  • 또한 server component 안에 client component들을 가질 수 있다.
  • 해당 코드는 절대 client로 넘어가지 않으므로 보안이 좋고, 우리는 보안을 신경쓰지 않아도 된다.

Layout

Navigation 같은 거 모든 컴포넌트들에 복사&붙여넣기 하는 건 너무 비효율적.
이를 해결하기 위해서 푸터나 헤더를 쓰는 것인데 이를 만드는데 Layout.tsx.
Layout은 app 폴더 내부의 모든 폴더와 페이지에서 사용된다.

만약 내가 AboutUs 페이지를 간다면, NextJS는 실제로는 layout component로 먼저 가서
Layout 컴포넌트에 있는 export된 default 컴포넌트를 렌더링 한다.

다음 코드의 children이 AboutUs 컴포넌트를 가르킨다.
해당 컴포넌트는 react 컴포넌트이다.
즉, 컴포넌트를 넣거나 어떤 컴포넌트를 넣을 때, 내부에 있는 컴포넌트들은 자동을 children이라는 props로 바뀌게 된다.

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

네비게이션 컴포넌트는 다음의 코드와 같이 넣어주면 된다.
이를 통해 모든 페이지를 수정하지 않아도 되게 된다.

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

(아니 그럼 네비게이션이 안보이면 좋겠으면 어떻게 하지?
➡️각각의 페이지 별로 다시 레이아웃 페이지를 생성할 수 있다. 이렇게 되면 해당 페이지에 있는 모든 페이지들은 이 레이아웃의 영향을 받게 된다.)

app(page, layout) > about-us(page, layout)
				  > another-page(page, layout)
                  ...

(home)

home에만 국한되는 것은 page.tsx이다.
route groups는 다음과 깉이 폴더 이름을 괄호로 묶어야 한다.

  • 괄호로 묶었기 때문에 URL을 생성하진 않는다.
  • 괄호 안에 있는 이름은 마음대로 해도 된다.
  • 한 개 이상의 route를 만들 수 있다.
  • routes를 그룹화해서 logical groups로 만들 수 있다.
  • layout, not-found는 전체에 공유되어야 한다. 전체적으로 적용되어야 하기 때문.
    하지만, page는 home에만 관련됐기 때문에 (home)에 있어도 된다.

MetaData

꼭 내보내야 하는 object, 메타데이터라고 부른다.

  • 메타데이터는 병합된다.
  • 페이지나 레이아웃만 메타데이터를 내보낼 수 있다.
    컴포넌트는 metadata를 내보낼 수 없고, metadata는 서버 컴포넌트에만 있을 수 있다.
    client 컴포넌트에는 metadata가 있을 수 없다!~!

Dynamic Routes

정적 라우트는 항상 똑같다. /about-us
↔️ 반면, 동적 라우트는 /movies/4545, /movies/121212, ... /movies/{id}

동적 라우트를 하고 싶다면 대괄호([]) 를 사용하면 된다.

이후 url을 다음과 같이 요청하고, props를 log로 찍어보면 결과는 다음과 같이 나오게 된다.

요청: http://localhost:3000/movies/1234?region=kr
log: { params: { id: '1234' }, searchParams: { region: 'kr' } }

Next.JS는 URL을 인식하여 해당 URL의 페이지를 렌더링한다.
➡️ movie detail 페이지로 이동
➡️ props로 id(user가 보낸 id)를 받고 렌더링을 하게 된다.

export default function MovieDetail({params: {id}}: {params:{id:string}}) {
    return <h1>Movie {id}</h1>;
}


Conclusion

Server Component 안에 Client Component를 넣을 수는 있지만,
반대로 Client Component 안에 Server Component를 넣을 수는 없다.

profile
https://github.com/Dingadung

0개의 댓글