Gatsby 로 블로그 만들기 .02

102·2022년 12월 23일
0

gatsby로 블로그는 이제 대충 다 만들었는데 내가 블로그에 적은글이 검색상에 나왔으면 좋겠다!

Slug

제목을 핵심 키워드의 조합으로 간단히 만드는 방법

예를들면 포스트의 제목이 Gatsby 로 블로그 만들기 이면 그 포스트의 slug는 Gatsby-로-블로그-만들기 가 된다.

왜 slug를 써야하냐면 검색 엔진 최적화를 위해 사용한다.
slug를 사용하여 게시글 링크를 만들면 http://website/Gatsby-로-블로그-만들기 가 되기 때문에 URL을 통해 검색엔진이 더 쉽게 포스트를 찾게된다.

Gatsby에 Slug 써보기

slug도 gatsby에서 따로 제공해주는 API가 있다.
그중 onCreateNode 라는 API를 이용할것이다.

// gatsby-node.js
const path = require('path');
const { createFilePath } = require(`gatsby-source-filesystem`);

// Setup Import Alias
exports.onCreateWebpackConfig = ({ getConfig, actions }) => {
  const output = getConfig().output || {};

  actions.setWebpackConfig({
    output,
    resolve: {
      alias: {
        components: path.resolve(__dirname, 'src/components'),
        utils: path.resolve(__dirname, 'src/utils'),
        hooks: path.resolve(__dirname, 'src/hooks'),
      },
    },
  });
};

// Generate a Slug Each Post Data
exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions;

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode });

    createNodeField({ node, name: 'slug', value: slug });
  }
};

이렇게 추가해준뒤 slug 데이터를 graphql로 확인해볼수있다.

query MyQuery {
  allMarkdownRemark {
    edges {
      node {
        fields {
          slug
        }
      }
    }
  }
}

이 slug 데이터를 가지고 해당 component 를 눌렀을때 Link to={slug} 해주면 눌렀을때 해당 slug로 url이 이동하게 해준다.

그러면 해당 content 로 이동하는것은 이전에 적었던 글의 src/templates/post-template.jsx
에 이동시켜줄것이고 이 컴포넌트를 통해 patsby-node.js 파일 내에서 게시글 페이지를 생성해주는 부분이 필요하다.

// gatsby-node.js
const path = require('path');
const { createFilePath } = require(`gatsby-source-filesystem`);

// Setup Import Alias
exports.onCreateWebpackConfig = ({ getConfig, actions }) => {
  const output = getConfig().output || {};

  actions.setWebpackConfig({
    output,
    resolve: {
      alias: {
        components: path.resolve(__dirname, 'src/components'),
        utils: path.resolve(__dirname, 'src/utils'),
        hooks: path.resolve(__dirname, 'src/hooks'),
      },
    },
  });
};

// Generate a Slug Each Post Data
exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions;

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode });

    createNodeField({ node, name: 'slug', value: slug });
  }
};

// 이부분부터 추가됨
// Generate Post Page Through Markdown Data
exports.createPages = async ({ actions, graphql, reporter }) => {
  const { createPage } = actions;

  // Get All Markdown File For Paging
  const queryAllMarkdownData = await graphql(
    `
      {
        allMarkdownRemark(
          sort: {
            order: DESC
            fields: [frontmatter___date, frontmatter___title]
          }
        ) {
          edges {
            node {
              fields {
                slug
              }
            }
          }
        }
      }
    `,
  );

  // Handling GraphQL Query Error
  if (queryAllMarkdownData.errors) {
    reporter.panicOnBuild(`Error while running query`);
    return;
  }
  
   // Import Post Template Component
  const PostTemplateComponent = path.resolve(
    __dirname,
    'src/templates/post_template.jsx',
  );

  // Page Generating Function
  const generatePostPage = ({
    node: {
      fields: { slug },
    },
  }) => {
    const pageOptions = {
      path: slug,
      component: PostTemplateComponent,
      context: { slug },
    };

    createPage(pageOptions);
  };

  // Generate Post Page And Passing Slug Props for Query
  queryAllMarkdownData.data.allMarkdownRemark.edges.forEach(generatePostPage);
};
};

**generatePostPage**함수를 통해 slug 데이터를 통해 페이지를 생성해주었는데 이 함수는**createPage** API를 이용해 pageOptions 객체의 형식으로 인자를 받는다. 경로를 slug 데이터를 넘겨주고 해당 페이지에서 사용할 컴포넌트로 poste-template.jsx를 연결시켜 주었다. 그리고 context 라는 이름으로 slug를 넣어주었는데 이 데이터는 poste-template component 에서 props로 받을수 있으며 해당 컴포넌트에서 사용할 graphql query의 파라미터로도 받을수 있기 때문에, 이 데이터를 통해 slug에 맞는 마크다운 데이터를 불러온다.

그럼 이제 poste-template component 에서 slug에 맞는 데이터를 조회해야하는데
해당 객체에는 페이지 링크, 템플릿 컴포넌트, context의 세 가지 프로퍼티가 들어있었는데, context라는 이름으로 넘긴 객체 내의 값들은 컴포넌트에서 Props로 받을 수 있을 뿐더러 GraphQL Query의 파라미터로도 받을 수 있다고 했다.

query 내에서 사용하기 위한 파라미터 이름들은 필드 이름과 구분하기위해 $ 와 같은 접두사를 쓴다 (graphql이 원래 그렇다)

query queryMarkdownDataBySlug($slug: String) {
  allMarkdownRemark(filter: { fields: { slug: { eq: $slug } } }) {
    ...
  }
}

이렇게 쿼리를 불러오면 파라미터로 받은 slug와 일치하는 마크다운 데이터에서 필요한 값만 query 할수있다.

//post-template.jsx

query queryMarkdownDataBySlug($slug: String) {
  allMarkdownRemark(filter: { fields: { slug: { eq: $slug } } }) {
    edges {
      node {
        html
        frontmatter {
          title
          summary
          date(formatString: "YYYY.MM.DD.")
          categories
          thumbnail {
            childImageSharp {
              gatsbyImageData
            }
          }
        }
      }
    }
  }
}



[레퍼런스]
https://www.inflearn.com/course/gatsby-%EA%B8%B0%EC%88%A0%EB%B8%94%EB%A1%9C%EA%B7%B8

profile

0개의 댓글