티스토리 뷰

Pages

Next.js 프로젝트 구조 안에서 pages 안에 있는 폴더가 url과 1:1 혹은 1:N 매칭이 됩니다.

Pre-rendeers와 SEO

Next.js는 모든 페이지를 기본적으로 pre-render 합니다. pre-render는 말 그대로 미리 그려놓는다는 의미인데요.

pre-rendering은 처음 클라이언트 쪽에서 html을 로드할 때 이미 많은 부분이 그려진 상태에서 로드를 하는 것이고, 이후에 JS 번들이 load가 되면 그제서야 Hydration이라는 과정을 거쳐 사용자와 app이 인터랙션을 할 수 있게 됩니다.

html만을 가지고는 인터랙션을 할 수 없습니다(JS 코드들이 있어야 하죠?). JS 코드를 적용하는 것을 Hydration이라고 합니다.

pre-render가 없는 경우에는 처음 로드할 때 아무 것도 없습니다. 보통 React로 만들어진 Signle Page Application들이 그렇습니다. 반드시 JS가 로드되고 실행이 되어야지만 그제서야 화면에 컴포넌트들을 그립니다. 따라서 Hydration 과정에서 굉장히 많은 부분들이 그려질 것입니다.

pre-rendering과 SEO(검색 엔진 최적)의 상관관계

CSR(Client Side Render)만 제공한다면, Client(브라우저)처럼 동작하지 않는 검색엔진의 경우 아무런 데이터도 조회해갈 수 없습니다. 무슨 말이냐면, SEO는 검색 엔진 최적화로 다양한 검색 엔진들이 내가 만든 사이트를 더 잘 읽어갈 수 있도록 해서 상위에 노출시켜줄 수 있도록 하는 것인데

pre-render가 아닌 No Pre-render를 한 경우는 JS를 해석할 수 없는 엔진에서는 아무 것도 읽어갈 것이 없다는 말입니다. 따라서 JS를 해석할 수 없는 엔진에서는 아무 것도 읽어갈 것이 없다는 말과 같습니다.

 

하지만 SSR(Server Side Render)를 하게 되면 JS를 해석하지 못하는 엔진도 title이나 대표 이미지 등을 읽어갈 수 있다는 것입니다.

 

⭐ 따라서 Pre-render를 해두면 Client처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공할 수 있습니다.

Next.js의 Pre-rendering 방식 2가지 - SSG(추천) & SSR

Next.js에서는 SSG를 더 적극적으로 쓰라고 합니다. 왜냐하면 SSG는 빌드 타임에 pre-render를 하기 때문에 서버에 부하가 적습니다. 반대로 SSR은 요청 타임에 pre-render합니다. 그래서 사용자가 브라우저에 혹은 검색 엔진이 해당 URL로 요청을 했을 때 그제서야 Node 서버가 동작을 해서 화면을 미리 그려서 전달을 하는 것입니다.

 

❓SSG 2가지 상황

1. 페이지의 내용물이 외부 데이터에 의존적인 상황

2. Page Paths까지 외부 데이터에 의존적인 상황

 

즉, 외부 서버 혹은 API에 의해서 안에 있는 데이터 내용들이 달라질 수 있는 상황들을 말하는데요.

 

첫 번째 경우는, getStatisProps만 가지고도 가능하고

두 번째 경우는, getStaticPaths도 함께 활용해야 SSG를 구현할 수 있습니다.

Layouts

여러 Page들의 공통 처리입니다. 즉, 하나의 공통된 Layout을 쓰는 경우에 components/Layout.js로 쓸 수 있는데, 컴포넌트 하나를 pages/_app.js에서 활용하면 됩니다. 

모든 컴포넌트에 공통으로 들어가는 컴포넌트(Header, Footer, ...)에 대해서는 굳이 매 파일들마다 써 줄 필요없이 모듈화를 하면 중복되는 코드를 제거할 수 있는데요.

 

📜 components/Layout.js 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import Head from 'next/head';
import styles from '../styles/Home.module.css';
 
export default function Layout({ children }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
 
      <main>{children}</main>
 
      <footer>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          <img src="/vercel.svg" alt="Vercel" className={styles.logo} />
        </a>
      </footer>
 
      <style jsx>{`
       // ...
      `}</style>
    </div>
  );
}
cs
 

위 코드를 살펴보면 Head 부분과 footer 부분은 모든 컴포넌트가 필요한 부분이므로 추가하고 children이라는 prop을 main안에 넣어주고 있습니다. 예상을 해보면 해당 Layout에 들어오는 children을 받아 표시하게 될 것입니다.

 

그럼 이제 children을 전달해볼까요? 좀전에 언급한 _app.js는 모든 컴포넌트를 품을 수 있는 구조에 해당합니다. 따라서 이 파일에서 Layout 컴포넌트를 return하면서 children을 넘겨주면 되는데요.

 

📜 pages/_.app.js 파일

1
2
3
4
5
6
7
8
9
import Layout from '../components/Layout';
 
export default function App({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}
cs

 

그러면 여러 개의 Layouts을 활용하고 싶은 경우의 예제를 살펴보겠습니다. 예를 들어 메인 화면을 제외한 모든 페이지에서는 'Home으로' 라는 a태그를 주고 싶은 경우로 해보겠습니다.

 

📜 components/SubLayout.js 파일

1
2
3
4
5
6
7
8
9
10
11
12
import Link from 'next/link';
 
export default function SubLayout({ children }) {
  return (
    <div>
      <h1>
        <Link href="/">Home으로</Link>
      </h1>
      {children}
    </div>
  );
}
cs

Layout 파일에서는 내가 나타내고 싶은 부분을 표현해주고 children을 받아 내부에 작성만 해주면 됩니다.

저는 이 SubLayout을 csr.js 파일에도 놓고 싶다고 해보겠습니다.

 

📜 pages/csr.js 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { useEffect, useState } from 'react';
import Layout from '../components/Layout';
import SubLayout from '../components/SubLayout';
 
export default function CSR() {
  const [time, setTime] = useState();
 
  useEffect(() => {
    setTime(new Date().toISOString());
  }, []);
 
  return (
    <>
      <h2>CSR 페이지입니다 :)</h2>
      <h3>{time}</h3>
    </>
  );
}
 
CSR.getLayout = function getLayout(page) {
  return (
    <Layout>
      <SubLayout>{page}</SubLayout>
    </Layout>
  );
};
 
cs

위 코드에서 하단 부분을 보면 되는데요. CSR.getLayout 즉, 지금 있는 컴포넌트 이름이 CSR임을 보아서 이 컴포넌트의 getLayout이라는 걸 정의할건데~ 하면서 function getLayout 하고 정의하고 있습니다. 이 함수는 page를 받아 Layout 그리고 SubLayout에 page를 품고 있습니다.

 

⭐ 우리는 이제 이 컴포넌트가 getLayout이라는 걸 가지고 있다는 걸 이용할 겁니다.

 

아까 _app.js는 모든 컴포넌트를 품을 수 있다고 했습니다. 따라서 _app.js로 가서 getLayout이 있는 컴포넌트들에 대해서 그리고 아닌 컴포넌트들에 대해서 관제를 할 겁니다.

 

📜 pages/_app.js 파일

1
2
3
4
5
6
7
import Layout from '../components/Layout';
 
export default function App({ Component, pageProps }) {
  const getLayout = Component.getLayout || (page => <Layout>{page}</Layout>)
 
  return getLayout(<Component {...pageProps} />);
}
cs

 

위 코드에서 App 컴포넌트는 getLayout이라는 걸 선언하고 있습니다. Component.getLayout이 있다면 그걸 담고, 없다면 바로 Layout에 page를 품습니다. 이렇게 getLayout 변수에 담아주고 리턴을 하게 됩니다.

아까 getLayout 기억나시나요? page라는 매개변수를 Layout과 SubLayer 사이에 품었었습니다. 따라서 App에서도 getLayout을 통해 전달된 매개변수는 Layout 안에 SubLayout 안에 렌더될 것입니다.

실행 화면

Images

Next.js가 제공하는 최적화 Image Component입니다. 다음과 같은 기능을 제공합니다.

  • Improved Performance
  • Visual Stability(CLS- Cumulative Layout Shift 방지)
  • Faster Page Loads(viewport 진입시 로드 / blur 처리)
  • Asset Flexibility(리사이징)

확인을 해보기 위해 따로 파일을 만들지 않고 이미 만들어져 있는 예제를 통해 살펴보겠습니다.

1
$ npx create-next-app --example image-component image-app
cs

여기서 responsive와 color를 살펴보려고 합니다.


이번 글에서는 Layout / Pages / Image에 대해 알아보았습니다 :)

 

1. Pre-render

Pre-render는 미리 그려놓는 것을 의미했으며 그리는 주체는 서버입니다. 검색 엔진이 내 페이지를 읽어가기 용이하도록 미리 그려놓는 것이고, 한편으로는 사용자가 페이지를 받을 때 주소에 접속하자마자 이미 그려놓은 페이지를 보면서 초기 로딩 속도를 훨씬 당길 수 있는 기능까지 제공한다고 보면 되겠습니다.

 

2. SSG vs SSR

SSG는 빌드 시 화면을 미리 그리고, SSR은 요청 시 화면을 미리 그립니다.

 

3. Layout

pages/_app.js를 활용해서 페이지의 공통된 코드를 하나의 모듈로 합쳐놓을 수 있습니다.

 

4. Images

최적화된 이미지를 활용할 수 있는 Next.js가 제공하는 util입니다.

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함