본문 바로가기

Programming/React

Next.js 시작하기 (Sanity Blog 작성 완료된 경우)

반응형

1. 프로젝트 생성 및 Library 설치

yarn create next-app .
yarn add @sanity/client	//Sanity 연결하여 Data를 가져오기 위한 라이브러리

2. 시작

yarn dev

yarn start는 빌드 이후 가능합니다.

 

3. 라우팅 설정

(기초)

폴더/페이지구조					url
pages/index.js 				-> 	/
pages/blog/index.js			-> 	/blog
pages/blog/first-post.js		->	/blog/first-post
pages/dashboard/setting/username.js	->	/dashboard/settings/username

pages/blog/[slug].js			->	/blog/:slug	(/blog/hello-world)
pages/[username]/settings.js		->	/:username/settings (/foo/settings)
pages/post/[...all].js			->	/post/* (/post/2020/id/title)

static routing이 우선됩니다.

 

(pages/post/index.js)

import React from 'react';

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

export default Blog;

(pages/post/[slug].js)

import React from 'react';
import { useRouter } from 'next/router';

const Blog = () => {
  const router = useRouter();

  const { slug } = router.query;

  return (
    <div>
      <h1>blog/{slug}</h1>
    </div>
  );
};

export default Blog;

 

3. Sanity 연결 및  Data 가져오기

getStaticProps (Static Generation) - Fetch data at build time

getStaticPaths (Static Generation) - Specify dynamic routes to pre-render pages based on data.

getServerSideProps (Server-side Rendering) - Fetch data on each request

 

(/services/SanityService.js) sanity 연결 및 데이터를 요청하는 메서드(클래스)를 정의합니다.

import sanityClient from '@sanity/client';

export default class SanityService {
  _client = sanityClient({
    dataset: 'production',
    projectId: 'ozi5ivc6',  // sanity.io에 접속하여 프로젝트의 ID를 확인한다.
    useCdn: process.env.NODE_ENV === 'production',  // production 모드일 경우 cdn 사용
  });

  // main post를 가져오는 요청
  async getHome() {    
    return await this._client.fetch(`
      *[_type =='home'][0]{'mainPostUrl': mainPost -> slug.current}
    `)
  }

  // main 이외의 포스트를 가져오는 요청
  async getPosts() {
    return await this._client.fetch(`
      *[_type=='post']{
        title, 
        subtitle, 
        createdAt, 
        'content': content[]{
          ..., 
          ...select(_type == 'imageGallery' => {'images': images[]{..., 'url': asset -> url }} )
        },
        'slug': slug.current,
        'thumbnail': {
          'alt': thumbnail.alt,
          'imageUrl': thumbnail.asset -> url
        },
        'author': author -> {
          name,
          role,
          'image': image.asset -> url
        },
        'tag': tag -> {
          title,
          'slug': slug.current
        }
      }
    `)
  }
}

 

(/pages/index.js) 루트 경로에서 메인 포스트와 기타 포스트들을 가져옵니다.

import styles from '../styles/Home.module.css';
import SanityService from '../services/SanityService';

export default function Home({home, posts}) {
  console.log(home);
  console.log(posts);
  return (
    <div className={styles.container}>
      <h1>Blog Home</h1>
    </div>
  )
}

export async function getStaticProps() {  
  const sanityService = new SanityService();
  const home = await sanityService.getHome();
  const posts = await sanityService.getPosts();

  return {
    props: {
      home,
      posts,
    }
  }
}

(/pages/post/[slug].js) 특정 포스트(slug)의 데이터를 가져옵니다.

import React from 'react';
import SanityService from '../../services/SanityService';

const PostAll = ({slug, post}) => {
  return (
    <div>
      <h1>blog/{slug}</h1>
    </div>
  );
};

export default PostAll;

export async function getStaticPaths() {
   
  const posts = await new SanityService().getPosts();

  const paths = posts.map(post => ({
    params: {
      slug: post.slug
    }
  }));

  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps({params}) {
  const {slug} = params;

  const posts = await new SanityService().getPosts();
  const post = posts.find(p => p.slug === slug);

  return {
    props: {
      slug,
      post,
    }
  }
}

 

4. 결과

/localhost:3000/post/my-blog-test

 

/localhost:3000/

 

반응형