/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/
*/
// You can delete this file if you're not using it
import "./src/tailwind.css";
7. PurgeCSS 설정(Optional but Recommended for Production)
Disqus.com에 로그인 후 Site Admin 으로 이동하여 기본 정보들을 입력하여 내 사이트를 추가해줍니다. 그리고 설치방법을 찾아보면 Gatsby에 반영하는 방법이 나옵니다. [ Site Admin > 내 사이트 선택 > Installation > Gatsby 선택 ]
Disqus에서는 아래와 같은 형식으로 안내를 합니다. 단 config에서 괄호가 두개 들어가야합니다. 안내와 조금 차이가 있습니다.
import { Disqus } from 'gatsby-plugin-disqus';
const Template = () => (
/* Page contents */
<Disqus
config={{
/* Replace PAGE_URL with your post's canonical URL variable */
url: 'PAGE_URL',
/* Replace PAGE_IDENTIFIER with your page's unique identifier variable */
identifier: 'PAGE_IDENTIFIER',
/* Replace PAGE_TITLE with the title of the page */
title: 'PAGE_TITLE',
}}
/>
);
서치 콘솔에서 새로운 사이트를 등록하는 방법은 [ 여기 ]포스팅을 참조하시기 바랍니다. 이제 <meta>태그를 적용시켜줘야하는데, 기본 Gatsby Starter로 시작했다면, src/components/layout.js파일을 수정하는게 편합니다. 우선 react-helmet이라는 플러그인을 설치해줍니다.
npm i react-helmet
그리고 아래와 같이 <Header /> 태그의 아래쪽에 <Helmet> 컴포넌트를 이용해서 코드를 추가해줍니다
아래 정도의 frontmatter를 작성해줍니다. 샘플로 몇개를 더 만들어놓습니다. 그리고 thumbnail경로에 예시 코드와 맞도록 이미지를 준비해줍니다.
---
title: Todo List
date: "2022-05-10T22:12:03.284Z"
description: 남은 할일 목록
slug: page1
thumbnail: './images/page1.png'
---
- 댓글기능
- 검색최적화(SEO)
- 카테고리 만들기
4./gatsby-node.js
이 부분에서는 이전 포스트 대비 특별히 손댈 것은 없습니다. thumbnail노드 하위의 속성은 gatsby-plugin-image 플러그인을 통해 인식된 이미지들로 인해 자동으로 생성됩니다.
이전 포스팅에서 작성한 내용에서, 각 포스팅의 타이틀 스타일을 변경해주고, 표시되는 순서를 작성일의 역순정렬로 변ㄱ여하였습니다.
import React from "react"
import { useStaticQuery, Link, graphql } from "gatsby"
import Layout from "../components/layout"
export default ({ data }) => {
console.log(data)
return (
<Layout>
<div>
<h1>
A World of Hello World and Todo List
</h1>
<h4>{data.allMarkdownRemark.totalCount} Posts</h4>
{data.allMarkdownRemark.edges.map(({ node }) => (
<div key={node.id} style={{
marginBottom: "50px",
}}>
<h2>
<Link to={node.fields.slug}
style={{
color: "#555",
textDecoration: "none",
}}>
{node.frontmatter.title}{" "}
<span>
— {node.frontmatter.date}
</span>
</Link>
</h2>
<p>{node.excerpt}</p>
</div>
))}
</div>
</Layout>
)
}
export const query = graphql`
query {
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
description
}
excerpt
fields{
slug
}
}
}
}
}
`
7. src/templates/md-files.js
이부분이 마크다운 파일들을 읽어서 동일한 템플릿 형태로 표현해주는 부분입니다. 여기서 gatsby-plugin-image 플러그인에서 제공하는 GatsbyImage 컴포넌트와 getImage 메서드를 활용합니다. gatsby-plugin-image 역시 이미 설치되어있을 확률이 높습니다.
import React from "react"
import { graphql } from "gatsby"
import { GatsbyImage, getImage } from "gatsby-plugin-image"
import Layout from "../components/layout"
export default function Template({ data }) {
const { markdownRemark } = data
const { frontmatter, html } = markdownRemark
const thumbnailImg = getImage(frontmatter.thumbnail?.childImageSharp?.gatsbyImageData)
return (
<Layout>
<div className="blog-post-container">
<div className="blog-post">
<GatsbyImage image={thumbnailImg} alt="Thumbnail" />
<h1>{frontmatter.title}</h1>
<h2>{frontmatter.date}</h2>
<div dangerouslySetInnerHTML={{ __html: html }} />
</div>
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
thumbnail {
childImageSharp {
gatsbyImageData
}
}
}
}
}
`
8. gatsby-remark-images 설치 및 설정
gatsby-remark-images플러그인을 설치한 후 gatsby-config.js파일에 아래와 같이 추가합니다. 이 플러그인은 마크다운 파일의 이미지를 최적화하여 사용할 수 있도록 도와주는 플러그인입니다. 화면에서 이상하게 나오던 이미지들이 아래의 설정 이후정상적으로 나옵니다.
정적사이트 생성기(SSG, Static Site Generator)에 대해 공부하다보니 다시 Gatsby에 대한 흥미가 돌기 시작해서 오랫만에 Gatsby로 프로젝트를 만들어봤습니다. 예전에 이걸 공부했던 적이 있었나 싶을 정도로 하나도 기억이 안나더군요. React에 대한 두려움으로 React 계통의 프레임워크들은 무조건 멀리했었던 것 같기도 하고, 사실은 Gatsby, GraphQL에 대해 정확히 공부한적이 없었던 것 같기도 하네요. 그래서 오늘은 설치하고 마크다운 문서 표기하기까지 알게된 내용을 정리해볼까 합니다.
[ 목차 ]
1. Gatsby란?
Gatsby는 서두에 말했듯이 React에 기반한 정적사이트 생성기(SSG, Static Site Generator)입니다. 예전부터 Ruby on Rails로 작성된 Jekyll 이 가장 많이 사용되었었는데, React에 기반한 점, GraphQL을 사용하여 이미지, 컨텐츠 등 데이터를 빠르고 쉽게 반영할 수 있는점 등으로 매우 큰 인기를 끌고 있습니다. 거기다 다양한 테마를 적용한 스타터 킷이 존재하여 사용자 편의성을 지원하고 있습니다. 이전 포스트(정적 사이트 생성기 (SSG, Static Site Generator) 로 나만의 블로그를 만들어보자 (tistory.com))에서도 소개했듯이 다양한 SSG가 존재하지만 그 중에서도 Gatsby는 만들어진 이래 항상 최상위권을 유지하고 있습니다.
이제 한단계씩 시작해보겠습니다. 이번 프로젝트에서도 마크다운 문서들을 이용해 각 URL별로 문서를 표시하는 기능을 만들어보겠습니다.
2. 설치
아래의 명령어로 글로벌 설치를 합니다.
npm i -g gatsby-cli
3. 프로젝트 생성
gatsby new [프로젝트(폴더) 이름]
//현재 폴더에 프로젝트를 구성할 경우 폴더명(".") 입력
gatsby new . // 개인적으로 이 방법 자주씀
package.json에서 "script"부분을 조금 수정하여, develop 대신 dev로 간단히 바꿔놓았습니다.
//from
"develop": "gatsby develop"
// to
"dev": "gatsby develop",
이제 아래의 명령어로 시작하면..
npm run dev
아래와 같이 2개의 URL이 주어지는데, 첫번째 URL이 결과 화면이고, 두번째는 graphql 관련 페이지입니다.
5. Index페이지에서 마크다운 문서 리스트 보이기
다음으로 Index페이지에 마크다운 문서들의 목록을 보여주도록 구성하겠습니다. 우선 마크다운 샘플 문서를 3개정도 만들어줍니다. 위치는 루트 디렉토리 내에 /content/posts폴더를 새로 만들어줍니다.
[content/posts/post1.md] 새 폴더와 함께 새 파일 생성
---
title: My Markdown Page
date: "2023-07-25T22:12:03.284Z"
description: This is an example of a Markdown page.
slug: page1
---
# My Markdown Page
This is an example of a Markdown page. You can use Markdown syntax to format the content of your pages.
## Subheading
Here's another section with a subheading. You can use various formatting options such as **bold**, *italic*, and `code` to add emphasis.
첫째는 `gatsby-source-filesystem` 플러그인으로 posts폴더를 인식시켜주는 것이고,
둘째는 `gatsby-transformer-remark` 를 이용해 마크다운 문서를 HTML로 변환시켜주는 것입니다.
<posts 폴더 인식>
gatsby-config.js파일의 plugin 부분을 보면 `gatsby-source-filesystem`을 이용해 images폴더를 설정한 부분이 있습니다. 이미 해당 플러그인이 설치가 되있다는 얘기입니다. package.json에서도 확인이 가능합니다. 그 아래쪽에 한단락을 복사해서 posts폴더를 인식할 수 있도록 설정을 추가합니다.
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
siteUrl: `https://gatsbystarterdefaultsource.gatsbyjs.io/`,
},
plugins: [
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
{ // 추가 여기서부터
resolve: `gatsby-source-filesystem`,
options: {
name: `posts`,
path: `${__dirname}/content/posts`,
},
}, // 여기까지
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
// This will impact how browsers show your PWA/website
// https://css-tricks.com/meta-theme-color-and-trickery/
// theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
],
}
<마크다운 문서 변환>
마크다운 문서 변환을 위해서는 `gatsby-transformer-remark` 플러그인을 우선 설치해야합니다.
npm i gatsby-transformer-remark
다음으로 gatsby-config.js파일에 해당 플러그인이 적용되도록 한줄 추가해넣습니다.
<src/pages/index.js 파일 수정>
index.js파일을 아직은 잘 모르겠지만, 아래와 같이 수정합니다. 아래부분은 GraphQL을 이용해 내가만든 컨텐츠(md파일들)로부터 정보를 가져오는 부분입니다.
리스트는 나오는데, 각 포스트별 페이지도 없고 링크도 안됩니다. 이 부분을 추가해보도록 하겠습니다.
</src/templates/md-files.js>
우선 md-files.js라고 템플릿 파일을 하나 생성합니다. GraphQL로부터 값들을 가져와 화면에 뿌려주는 역할을 합니다.
import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
export default function Template({ data }) {
// console.log(data)
const { markdownRemark } = data
const { frontmatter, html } = markdownRemark
return (
<Layout>
<div className="blog-post-container">
<div className="blog-post">
<h1>{frontmatter.title}</h1>
<h2>{frontmatter.date}</h2>
<div dangerouslySetInnerHTML={{ __html: html }} />
</div>
</div>
</Layout>
)
}
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
}
}
}
`
markdownRemark(fields: {slug: {eq: $slug} }) 부분은 slug를 키 값으로 하여 각 포스트의 정보를 가져오라는 의미입니다.
<gatsby-node.js>
page를 생성해주는 템플릿 파일을 만들었으면, 이제 적용해주어야 합니다. 아래와 같이 gatsby-node.js를 작성하여 실행되도록 합니다. createPages는 gatsby에서 페이지를 생성할 때 실행되고, onCreateNode함수는 노드가 생성될 때마다 실행됩니다. onCreateNode 함수에서 마크다운 파일을 읽어 Slug 값을 추출하고, createNodeField 함수를 사용하여 노드에 Slug 값을 추가합니다.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./reducers";
import { Provider } from "react-redux";
const store = configureStore({
reducer: rootReducer,
devTools: process.env.NODE_ENV !== "production",
});
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();