게시물 파일이름의 목록을 나열하는 블로그 페이지 만들기.
src/pages/blog.tsx 파일을 만듭니다./* src/pages/blog.tsx */
import React from "react";
import Layout from "../components/Layout";
import Seo from "../components/Seo";
export default function Blog() {
return (
<Layout title="Blog">
<p>The most recent news from my shop.</p>
</Layout>
);
}
export const Head = () => <Seo title="Blog" />;
Layout 컴포넌트에 새 블로그 페이지에 대한 링크를 추가합니다.
/* src/components/layout.js */
// ... import statements
interface ILayoutProps {
children: any;
title: string;
}
export default function Layout({ children, title }: ILayoutProps) {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`);
return (
<div>
<header>{data.site.siteMetadata.title}</header>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about-us">About Us</Link>
</li>
<li>
<Link to="/blog">Blog</Link>
</li>
</ul>
</nav>
<main>
<h1>{title}</h1>
{children}
</main>
</div>
);
}

mdx 확장명으로 각각의 포스트를 만듭니다.
이제 일부 게시물이 로컬 파일 시스템에 저장되었으므로 해당 파일을 Gatsby 데이터 계층으로 가져올 차례입니다.
gatsby-source-filesystem 플러그인을 설치합니다.npm install gatsby-source-filesystem
gatsby-config.ts 파일에서 gatsby-source-filesystem 플러그인의 옵션을 설정합니다. path 에 파일 경로를 작성해줍니다./* gatsby-config.ts */
module.exports = {
siteMetadata: {
title: "My First Gatsby Site",
},
plugins: [
"gatsby-plugin-image",
"gatsby-plugin-sharp",
{
resolve: "gatsby-source-filesystem",
options: {
name: `blog-posts`,
path: `${__dirname}/blog-posts`,
}
},
],
};
옵션
__dirname : 현재 실행 중인 파일이 포함된 디렉터리의 절대 경로를 저장하는 Node.js의 변수입니다.name : 각 파일의 sourceInstanceName 필드로 설정 됩니다. 여러 폴더로부터 source 파일을 원할 때 유용합니다. GraphQL 쿼리를 작성할 때, 각 폴더의 name을 지정하면 특정 폴더를 필터링할 수 있습니다.GraphiQL 내부를 탐색하여 블로그 폴더에 있는 allFile의 이름을 가져오는 쿼리를 작성합니다 .
graphql from gatsby.page query를 정의하고 내보냅니다. GraphiQL에서 작성한 쿼리를 복사합니다./* src/pages/blog.tsx */
import React from "react";
import Layout from "../components/Layout";
import Seo from "../components/Seo";
import { graphql } from "gatsby";
export default function Blog() {
return (
<Layout title="Blog">
<p>The most recent news from my shop.</p>
</Layout>
);
}
export const query = graphql`
query BlogTitles {
allFile {
nodes {
name
}
}
}
`;
export const Head = () => <Seo title="Blog" />;
data prop을 정의합니다. GraphiQL에서 작성한 쿼리를 복사하고 쿼리의 이름을 지정해줍니다.
- 쿼리 이름은 Gatsby가 빌드 시 쿼리를 실행할 때 콘솔에 표시되는 오류를 디버깅하는 데 유용할 수 있습니다.
data prop의 쿼리 타입을 작성해줍니다. <Queries.BlogTitlesQuery>
자바스크립트 메서드 .map()를 사용하여 nodes 배열을 각각의 파일명을 가지는 게시물로 렌더링합니다.
/* src/pages/blog.tsx */
import React from "react";
import Layout from "../components/Layout";
import Seo from "../components/Seo";
import { PageProps, graphql } from "gatsby";
export default function Blog({ data }: PageProps<Queries.BlogTitlesQuery>) {
return (
<Layout title="Blog">
<ul>
{data.allFile.nodes.map((node) => (
<li key={node.name}>{node.name}</li>
))}
</ul>
</Layout>
);
}
export const query = graphql`
query BlogTitles {
allFile {
nodes {
name
}
}
}
`;
export const Head = () => <Seo title="Blog" />;

🔻MDX에서 Markdown 서식 사용
MDX 파일은 마크업 언어인 Markdown을 사용하여 텍스트 서식을 지정할 수 있습니다.
// mdx
---
name: "Fun Facts about Red Pandas"
datePublished: "2021-07-12"
author: "#1 Red Panda Fan"
---
npm install gatsby-plugin-mdx gatsby-source-filesystem @mdx-js/react`
blog-posts 디렉토리에 mdx 파일을 만듭니다.// blog-posts/my-first-post.mdx
---
title: "My First Post"
date: "2021-07-23"
slug: "my-first-post"
---
This is my first blog post! Isn't it *great*?
Some of my **favorite** things are:
* Petting dogs
* Singing
* Eating potato-based foods
gatsby-config 파일에 gatsby-plugin-mdx을 작성합니다.
import type { GatsbyConfig } from "gatsby";
const config: GatsbyConfig = {
siteMetadata: {
title: `My Blog`,
description: `Example project for the Gatsby Head API`,
siteUrl: `https://www.yourdomain.tld`,
},
graphqlTypegen: true,
plugins: [
"gatsby-plugin-image",
"gatsby-plugin-sharp",
{
resolve: "gatsby-source-filesystem",
options: {
name: `blog-posts`,
path: `${__dirname}/blog-posts`,
},
},
"gatsby-plugin-mdx",
],
};
export default config;
allFile 대신 allMdx 필드를 사용하도록 블로그 페이지 쿼리를 업데이트하세요.
gatsby-plugin-mdx 플러그인은 GraphQL 쿼리에 사용할 수 있는 두 개의 새로운 필드를 제공합니다 : allMdx 및 mdx
allMdx :http://localhost:8000/___graphql 에서 쿼리를 생성하고 실행합니다.
// graphql
query MyQuery {
allMdx {
nodes {
frontmatter {
date(formatString: "YYYY-MM-DD")
title
category
}
body
excerpt
}
}
}

id 필드는 Gatsby가 데이터 영역의 모든 노드에 자동으로 추가하는 고유 문자열입니다.
sort 인수를 사용하여 최신 게시물이 먼저 나열되도록 게시물을 역시간순으로 나열할 수 있습니다.
쿼리 :
query MyQuery {
allMdx(sort: { frontmatter: { date: DESC } }) {
nodes {
frontmatter {
date(formatString: "MMMM D, YYYY")
title
}
id
}
}
}

excerpt 를 추가하면 각 게시물 콘텐츠의 미리보기를 추가할 수 있습니다.쿼리 :
query MyQuery {
allMdx(sort: { frontmatter: { date: DESC } }) {
nodes {
frontmatter {
date(formatString: "MMMM D, YYYY")
title
}
id
excerpt
}
}
}
쿼리 실행 :

pages/blog.tsx에서 BlogTitles 쿼리를 allMdx로 수정합니다.// pages/blog.tsx
export const query = graphql`
query BlogTitles {
allMdx {
nodes {
frontmatter {
date(formatString: "YYYY-MM-DD")
title
category
}
body
excerpt
}
}
}
`;
// pages/blog.tsx
export default function Blog({ data }: PageProps<Queries.BlogTitlesQuery>) {
return (
<Layout title="Blog">
{data.allMdx.nodes.map((node) => (
<article key={node.id}>
<h2>{node.frontmatter?.title}</h2>
<p>
Posted: {node.frontmatter?.date} | {node.frontmatter?.category}
</p>
<p>{node.excerpt}</p>
<hr />
</article>
))}
</Layout>
);
}
localhost:8000/blog 로 이동하여 확인합니다.
Gatsby의 File System Route API를 사용하여 동적으로 새 경로 생성
slug : 머리말
slug 필드를 넣고 쿼리를 실행하면, 아래와 같은 결과가 반환됩니다.



blog.tsx를 폴더로 옮겨줍니다.src/pages/blog/{mdx.frontmatter__slug}.tsx 파일을 만듭니다.
// src/pages/blog/{mdx.frontmatter__slug}.tsx
import React from "react";
import Layout from "../../components/Layout";
import Seo from "../../components/Seo";
export default function BlogPost(props) {
console.log("props", props);
return (
<Layout title="Super Cool Blog Posts">
<p>My blog post contents will go here (eventually).</p>
</Layout>
);
}

GraphQL에서 쿼리 변수는 요청과 함께 추가 데이터를 보내는 방법입니다. 쿼리 변수를 사용하면 전달한 값에 따라 다른 데이터를 반환하는 동적 쿼리를 작성할 수 있습니다.
🌱쿼리 내에서 쿼리 변수를 사용하려면 다음을 수행합니다.
쿼리변수를 지정합니다.
$가 앞에 오는) 과 GraphQL 데이터 타입이 포함되어야 합니다.나의 쿼리에 쿼리 변수를 사용합니다.
$변수이름 을 추가합니다.example :
query MyQuery($slug: String) {
mdx(frontmatter: { slug: { eq: $slug } }) {
frontmatter {
title
}
}
}
결과 :

쿼리를 만들고 실행합니다.

{mdx.frontmatter__slug}.tsx 에 쿼리를 추가합니다.
// pages/blog/{mdx.frontmatter__slug}.tsx
export const query = graphql`
query PostDetail($frontmatter__slug: String) {
mdx(frontmatter: { slug: { eq: $frontmatter__slug } }) {
frontmatter {
author
title
category
date
slug
}
body
}
}
`;
// pages/blog/{mdx.frontmatter__slug}.tsx
import React from "react";
import Layout from "../../components/Layout";
import Seo from "../../components/Seo";
import { graphql } from "gatsby";
interface BlogPostProps {
data: Queries.PostDetailQuery;
children: any;
}
export default function BlogPost({ data, children }: BlogPostProps) {
return (
<Layout title={data.mdx?.frontmatter?.title as string}>{children}</Layout>
);
}
export const query = graphql`
query PostDetail($frontmatter__slug: String) {
mdx(frontmatter: { slug: { eq: $frontmatter__slug } }) {
frontmatter {
title
category
date
slug
}
body
}
}
`;
export const Head = ({ data }: BlogPostProps) => (
<Seo title={data.mdx?.frontmatter?.title as string} />
);

// pages/blog/index.tsx
import React from "react";
import Layout from "../../components/Layout";
import Seo from "../../components/Seo";
import { Link, PageProps, graphql } from "gatsby";
export default function Blog({ data }: PageProps<Queries.BlogTitlesQuery>) {
return (
<Layout title="Blog">
{data.allMdx.nodes.map((node) => (
<article key={node.id}>
<Link to={`/blog/${node.frontmatter?.slug}`}>
{node.frontmatter?.title}
</Link>
<p>
Posted: {node.frontmatter?.date} | {node.frontmatter?.category}
</p>
<p>{node.excerpt}</p>
<hr />
</article>
))}
</Layout>
);
}
export const query = graphql`
query BlogTitles {
allMdx {
nodes {
frontmatter {
date(formatString: "YYYY-MM-DD")
title
category
slug
}
body
id
excerpt
}
}
}
`;
export const Head = () => <Seo title="Blog" />;

게시물의 제목을 클릭하면 포스팅 페이지로 이동된다.
참고문서
[gatsby] docs - 튜토리얼 part4
[gatsby] docs - 튜토리얼 part5
[gatsby] docs - 튜토리얼 part6