이전 글들에서는 Gatsby 기본 기능을 구현을 위한 튜토리얼을 소개했고 태그 기능을 구현했고, MDX 글 안에 인라인 이미지와 테이블을 삽입했으며, 시리즈 기능도 만들어보았다.

이번에는 임시글 기능을 구현해보자.

1. 개요

임시글은 작성자에게는 보이고 다른 사람들에게는 보이지 않는 비공개 글을 의미한다. Gatsby 에서 기본 제공하는 기능은 아니므로, 약간의 작업이 필요하다.

2. 구현

먼저 임시글들은 별도의 디렉토리에 모으고, 해당 디렉토리에 있는 글은 개발 환경에서만 보이고 프로덕션 환경에서는 보이지 않도록 할 것이다. 그리고 개발환경에서만 보이는 임시글 목록 페이지도 추가해서 이미 공개된 글들과 목록을 분리할 것이다.

2.1. 개발 환경에서만 보이는 임시글 디렉토리 환경 설정

gatsby-config.ts 에 아래 설정을 추가하자

// gatsby-config.ts

// 개발 환경인지 확인하는 플래그
const isDevelopment = process.env.NODE_ENV === "development";

const config: GatsbyConfig = {
  // ...
  plugins: [
    // ...
    // 개발환경이면 "gatsby-source-filesystem" 플러그인으로
    // 임시글 폴더의 파일들도 읽을 수 있도록 적용
    ...(isDevelopment
      ? [
          {
            resolve: "gatsby-source-filesystem",
            options: {
              name: "drafts",
              path: `${__dirname}/drafts`,
            },
          },
        ]
      : []),
  ],
};

export default config;

이제 drafts 디렉토리에 mdx 파일을 추가하면 Gatsby 가 해당 파일도 GraphQL 쿼리로 읽어올 수 있게 된다. 프로덕션 환경이면 해당 설정이 적용되지 않으므로 npm run deploy 를 했을 때는 drafts 디렉토리의 글들은 배포되지 않는다.

2.2. 임시글 목록 페이지 구현

아쉽게도 GraphQL 쿼리로는 mdx 파일이 속한 디렉토리까지는 알 수 없다. GraphQL 쿼리로 임시글만 가져오려면 mdx 의 frontmatter 영역에 이 글이 임시글이라는 정보를 남겨야 한다.

임시글을 위한 별도의 플래그를 만드는 방법도 있지만, 여기서는 작성일 필드를 빈 칸으로 두는 방법을 선택했다.

---
title: "React Native 디버거 에러"
date: ""
slug: "react-native-debugger-error"
tags: ["iOS", "react native", "빌드 에러", "안드로이드", "에러"]
series: "React Native 빌드 에러"
---

기존 글목록 페이지에서 임시글은 가져오지 쿼리를 수정하자.

// src/pages/posts/index.tsx

//...

export const query = graphql`
  query {
    allMdx(
      # 아래처럼 filter 를 추가하자
      filter: { frontmatter: { date: { ne: "" } } }
      sort: { frontmatter: { date: DESC } }
    ) {
      # ...
    }
  }
`;

// ...

그리고 임시글 목록 페이지를 만들자.

// src/pages/drafts/index.tsx

// ...

function DraftsPage({ data }: PageProps<DraftsPageData>) {
  const drafts = data.allMdx.nodes;
  return (
    <Layout>
      <ListPageHeader title="임시글" note={drafts.length} />
      <PostList data={drafts} />
    </Layout>
  );
}

export const query = graphql`
  query {
    allMdx(
      filter: { frontmatter: { date: { eq: "" } } }
      sort: { frontmatter: { date: DESC } }
    ) {
      # ...
    }
  }
`;

// ...

2.3. 임시글 링크를 메뉴에 추가

마지막으로 메뉴 컴포넌트에 (개발환경일 경우) 임시글 링크도 보이도록 추가하자.

// src/components/Layout.tsx

// ...

const isDevelopment = process.env.NODE_ENV === "development";

const menuItems = [
  { path: "/posts", title: "글" },
  { path: "/series", title: "시리즈" },
  { path: "/tags", title: "태그" },
  // 개발 환경일 경우에만 임시글 목록에 보이도록 추가하자.
  ...(isDevelopment ? [{ path: "/drafts", title: "임시글" }] : []),
];

function Layout({ children }: LayoutProps) {
  // ...
  return (
    <ThemeProvider theme={normalTheme}>
      <GlobalStyle />
      <Container>
        <Header>
          {/* ... */}
          <nav>
            <ul>
              {menuItems.map((item) => (
                <li key={item.path}>
                  <Link to={item.path}>{item.title}</Link>
                </li>
              ))}
            </ul>
          </nav>
        </Header>
        <main>{children}</main>
      </Container>
    </ThemeProvider>
  );
}

// ...

export default Layout;

2.4. 상세 코드

위 코드 조각들은 생략된 부분이 있으므로, 코드 전문을 보고 싶다면 아래를 참고하자.

3. 다음

이로서 시리즈 기능을 구현해보았다. 다음으로 구현 및 정리할 것들은 아래와 같다.

  • 댓글 기능 구현
  • 코드블록 문법 하이라이팅 기능 구현
  • 글의 목차 기능 구현
  • GitHub Pages 배포
  • 등등

순서는 미정이다.

4. 참고