주말에 gatsby 블로그를 만들며 삽질한 결과를 정리해봅니다

(결과물: https://github.com/joe-brothers/blog)

 

준비물

배포는 github pages로 진행합니다.

배포를 Netlify로 하지 않기 때문에, Netlify CMS OAuth 로그인을 위해 Firebase Cloud Functions을 사용할 예정입니다.

비용은 (웬만하면) 따로 들지 않습니다.

 

Github Pages over Netlify?

Netlify로 배포하면 Netlify CMS를 붙일 때 Oauth 서버를 따로 띄우지 않아도 쉽게 붙일 수 있습니다.

대신 무료 사용자인 경우 Build minute 제한이 300분이라서, 이 점은 public 리파지토리의 경우 제한이 없는 github actions + pages를 선택했습니다.

 

Gatsby-starter-minimal-blog

 

GitHub - LekoArts/gatsby-starter-minimal-blog: Typography driven, feature-rich blogging theme with minimal aesthetics. Includes

Typography driven, feature-rich blogging theme with minimal aesthetics. Includes tags/categories support and extensive features for code blocks such as live preview, line numbers, and line highligh...

github.com

개츠비 템플릿 중 깔끔해보이는 템플릿으로 시작했습니다.

반응형 디자인이고, 다크모드 지원도 됩니다.

남의 개츠비 테마를 쓰면 단점이 수정하기가 좀 어렵다는건데, shadowing을 쓰면 가능은 합니다. 사실 엄청 세세하게 수정할 건 아니라서 템플릿을 썼고, 만약 하나부터 열까지 커스터마이징 하고싶다 하면 자신만의 개츠비 테마를 만드는 게 더 나아보입니다.

 

함께하는 팀 블로그 만들기

메쉬코리아 웹 프런트엔드 팀에서 팀 블로그를 시작합니다. 팀 블로그를 왜 만들게 되었는지, Gatsby 스타터로 팀 블로그를 만들려고 하시는 분들에게 도움 될 만한 내용을 써봤습니다.

mesh.dev

혹시 테마 일부 수정이 필요하다면 위 글을 참고하세요

 

이 버튼을 눌러서 리파지토리를 만들어줍니다

 

GitHub Actions + GitHub Pages

리파지토리를 만들었다면, 이제 배포를 해 봅시다

Settings - Pages - Build and deployment에서 "GitHub Actions"를 체크해줍시다

브랜치 배포 방식도 있는데 굳이 브랜치로 안해도 됩니다. 자세한건 아래 글을 참고하세요

2022.09.16 - [version control/git] - [GitHub] actions 이용한 github pages 배포 방법 (베타)

이제 커밋할 때마다 빌드 및 GitHub Pages로 배포하는 워크플로를 작성해야 하는데요, gatsby 배포 템플릿이 있으니 걱정하지 않아도 됩니다.

# Sample workflow for building and deploying a Gatsby site to GitHub Pages
#
# To get started with Gatsby see: https://www.gatsbyjs.com/docs/quick-start/
#
name: Deploy Gatsby site to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["master"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

# Default to bash
defaults:
  run:
    shell: bash

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Detect package manager
        id: detect-package-manager
        run: |
          if [ -f "${{ github.workspace }}/yarn.lock" ]; then
            echo "::set-output name=manager::yarn"
            echo "::set-output name=command::install"
            exit 0
          elif [ -f "${{ github.workspace }}/package.json" ]; then
            echo "::set-output name=manager::npm"
            echo "::set-output name=command::ci"
            exit 0
          else
            echo "Unable to determine packager manager"
            exit 1
          fi
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: "16"
          cache: ${{ steps.detect-package-manager.outputs.manager }}
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v2
        with:
          # Automatically inject pathPrefix in your Gatsby configuration file.
          #
          # You may remove this line if you want to manage the configuration yourself.
          static_site_generator: gatsby
      - name: Restore cache
        uses: actions/cache@v3
        with:
          path: |
            public
            .cache
          key: ${{ runner.os }}-gatsby-build-${{ hashFiles('public') }}
          restore-keys: |
            ${{ runner.os }}-gatsby-build-
      - name: Install dependencies
        run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
      - name: Build with Gatsby
        env:
          PREFIX_PATHS: 'true'
        run: ${{ steps.detect-package-manager.outputs.manager }} run build
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v1
        with:
          path: ./public

  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v1

.github/workflows/gatsby.yml 파일이 이런식으로 만들어 질건데, 여기서 수정할 건 없습니다. 바로 커밋하시면 됩니다

 

이제 커밋을 하거나, Actions에서 "Run workflow"를 누르면 빌드와 배포가 진행됩니다.

 

테마 수정

블로그 이름을 바꾸거나, 링크 주소를 바꾸거나 하려면 매뉴얼에 나와있는대로 설정을 바꿔주세요.

- template 문서: https://github.com/LekoArts/gatsby-starter-minimal-blog

- theme 문서: https://github.com/LekoArts/gatsby-themes/tree/main/themes/gatsby-theme-minimal-blog

로컬에서 수정 후 프리뷰를 보려면 yarn run develop (== gatsby develop)을 입력하시면 됩니다

 

Headless CMS

markdown을 하나부터 열까지 직접 작성해 글을 쓰는건 해본 분들은 아시겠지만 이미지 넣는 것부터, frontmatter 넣는 것 등등 여러가지로 정말 번거롭기 때문에 CMS를 붙여봅시다.

 

Headless CMS - Top Content Management Systems | Jamstack

Check out this showcase of some of the best, open source headless CMSes. This is community-drive so be sure to submit your favorite CMS today!

jamstack.org

Headless CMS 여러가지 중 Netlify CMS를 선택했습니다. git-based CMS 중에 제일 괜찮은 것 같아 골랐는데, Tina CMS는 Next만 가능하다는 것 같기도 하고, 플러그인도 많이 없어서 netlify cms를 선택했습니다.

Headless CMS는 언제든 갈아탈 수 있으니 자유롭게 선택하면 됩니다.

yarn add netlify-cms-app gatsby-plugin-netlify-cms

관련 패키지 설치 후 설정파일을 수정해줍니다.

// gatsby-config.js
module.exports = {
  // ...
  plugins: [
    // ...
    {
      resolve: `gatsby-plugin-netlify-cms`
    },
  ]
}

개츠비 플러그인 추가해주시고요

backend:
  name: github
  repo: # ex) username/reponame
  branch: # ex) master
  base_url: # https://us-central-1-~~~.cloudfunctions.net
  auth_endpoint: /oauth/auth

media_folder: "static/img"
public_folder: "static"

collections:
  - name: "post"
    label: "Post"
    folder: "content/posts"
    create: true
    slug: "{{slug}}"
    media_folder: ''
    public_folder: ''
    path: '{{title}}/index'
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Publish Date", name: "date", widget: "datetime"}
      - {label: "Description", name: "description", widget: "text", required: false}
      - {label: "Body", name: "body", widget: "markdown"}
      - {label: "Tags" name: "tags" widget: "list"}
      - {label: "Banner", name: "banner", widget: "image", required: false}

static/admin/config.yml 을 추가해줍니다.

위 내용은 예제로 참고만 해주시고, 커스터마이징은 https://www.netlifycms.org/docs/configuration-options/ 이거 보고 해주세요

이제 배포 후, '블로그 주소/admin/'으로 접속하면 위처럼 netlify cms 로고와 깃허브 로그인 버튼이 나옵니다.

그런데 Netlify 배포가 아닌 github pages 배포라서 OAuth 인증 서버를 따로 띄워줘야 합니다.

 

GitHub - abhinavkrin/netlify-cms-oauth-firebase: Firebase Cloud Function based OAuth2 GitHub backend for Netlify CMS

Firebase Cloud Function based OAuth2 GitHub backend for Netlify CMS - GitHub - abhinavkrin/netlify-cms-oauth-firebase: Firebase Cloud Function based OAuth2 GitHub backend for Netlify CMS

github.com

위 리파지토리 README를 차근차근 따라해 Firebase Cloud Function을 추가합니다.

GitHub 계정 설정에서 OAuth App을 추가하고, Cloud Function 배포를 진행하면 됩니다.

따라하다보면 cloud function 배포가 실패할 수도 있는데, 에러 로그를 잘 읽으면 원인이 나와 있습니다. 제 경우는 gcp IAM에서 "Artifact Registry Reader" role을 추가해줬어야 했습니다.

배포 완료하면 firebase 콘솔에서 해당 내용을 확인할 수 있습니다. 참고로 Firebase Blaze 요금제를 써야 아웃바운드 네트워킹을 할 수 있으니 주의해주세요.

Cloud Function은 한달에 200만회 호출까지는 무료이고, 만에 하나 그걸 넘더라도 100만회 호출당 0.4달러라서 비용 걱정은 안하셔도 됩니다.

Firebase Cloud Function 말고 직접 node, python 등 서버를 띄우고 싶다고 하면 netlify cms External OAuth Clients 문서를 참고해서 배포해주시면 됩니다

 

preview

- blog page: https://joe-brothers.com/blog/

- blog repo: https://github.com/joe-brothers/blog

- admin (깃허브 권한 있는 유저만 로그인 가능): https://joe-brothers.com/blog/admin/

 

예시 페이지입니다.

 

Netlify CMS 화면입니다.

 

config.yml에서 설정한 대로 포스트 frontmatter를 입력할 수 있고, 좀 부실하지만 markdown preview도 됩니다.

기본적으로는 md 파일만 작성 가능한데 MDX는 따로 설정이 필요한가봅니다.

 

TODO

  • mdx support
  • cdn 연결
  • 깃허브나 티스토리처럼 붙여넣기로 이미지 넣기 기능

아직 갈 길이 멉니다. 그래도 오랜만에 재밌게 이것저것 해봤네요 ~.~

 

+ 몇 주 후..

ㅎㅎ.. netlify cms 업데이트도 안되고 짜증나는 에디터 버그가 있어서 tina cms로 갈아타려고 준비중입니다 ㅠ

 

Reference

https://blog.youngbin.xyz/2020-09-19-gatsby-netlify-cms/

https://www.netlifycms.org/docs/

 

반응형