Gatsby에서 Sanity 콘텐츠 액세스하기

September 21, 2020

개츠비(Gatsby)로 웹사이트를 만들 경우, ‘데이터 소스를 어떻게 관리하면 좋을까?’ 하는 문제가 종종 생깁니다. 아주 간단한 사이트라면 주로 마크다운(markdown) 파일을 데이터 소스로 해서 관리하면 되겠지만, 마크다운 콘텐츠를 직접 다루는 게 부담이 되는 것도 사실이죠.

물론 워드프레스 같은 도구를 CMS(headless 방식)로 사용하여 REST API나 GraphQL로 데이터를 가져올 수도 있겠지만, 그러자니 또 워드프레스를 설치하고 관리해야 하는 부담이 생깁니다.

여기에 추가로 만약 내가 관리하려는 콘텐츠가 일반적인 글(Post)이나 페이지(Page)가 아닌, 예를 들면 영화 사이트에서 영화 콘텐츠를 다루거나 온라인 쇼핑몰 사이트에서 제품 콘텐츠를 다뤄야 하는 것이라면요?

그럴 경우엔 무언가 다른 방식이 필요해 보입니다. (물론 마크다운 파일이나 워드프레스로는 구현할 수 없다는 뜻은 아닙니다. 워드프레스에서라면 커스텀 포스트 유형(Custom Post Types)을 사용하여 비슷한 효과를 낼 수 있겠죠?)

조금 더 간단하게 콘텐츠 유형을 만들고 좀더 쉽게 관리할 수 있는 방법은 없을까요?

Sanity를 소개합니다!

이럴 경우, 사용할 수 있는 한 가지 방법이 바로 여기서 소개할 Sanity입니다.

Sanity를 한마디로 말하면, 간단한 클라우드 기반 CMS라고 할 수 있습니다. 다만, 바깥으로 보이는 부분 없이 콘텐츠 그 자체만 만들고 관리할 수 있도록 해주니 좀더 정확히는 클라우드 기반 Headless CMS라고 할 수 있겠죠. (Sanity에서는 자신들을 구조화된 콘텐츠 저장소라고 소개하고 있습니다)

Sanity를 사용하면 나만의 콘텐츠 유형과 스키마를 만들 수 있고, 콘텐츠는 클라우드에 저장되어 관리됩니다. 물론 사용자는 API를 통해 언제든 콘텐츠에 액세스할 수 있구요!

Sanity Studio

특히 Sanity에서는 “새너티 스튜디오(Sanity Studio)”라는 리액트 기반의 오픈소스 콘텐츠 관리도구를 제공하여 사용자들이 좀더 쉽게 콘텐츠를 관리할 수 있도록 해주죠.

엄밀해 말해 Sanity Studio는 Sanity 데이터 소스에 액세스하는 API 클라이언트 앱입니다. Sanity Studio로는 다음과 같은 일들을 할 수가 있습니다:

  • 콘텐츠 스키마 관리
  • 콘텐츠 관리(데이터 추가/수정/삭제)
  • 스튜디오 커스터마이징

이 스튜디오는 로컬 환경에 만들 수도 있고 리모트 호스팅 환경에 둘 수도 있습니다. 특히 여러 명이 공동으로 콘텐츠 작업을 하는 경우라면 로컬보다는 모두가 액세스할 수 있는 리모트 환경에 둬야 겠죠. Sanity Studio가 리액트 기반의 SPA 이니, 리액트를 배포할 수 있는 환경이면 어디든 Studio를 배포할 수 있습니다.

※ 참고로, Sanity의 가격 정책은 이 스튜디오 사용자에 부가됩니다. 사용자 수가 3명까지는 무료지만, 그 이상일 경우는 유료 과금을 받고 있습니다. 자세한 내용은 Pricing 페이지를 참조하세요!

Sanity 시작하기

그럼 Sanity 프로젝트를 하나 만들어 볼까요?

Sanity 프로젝트를 시작하는 간단한 방법은 웹 브라우저에서 “sanity.io/create” 에 접속하는 것입니다.

그러면, 아래와 같이 스타터(starter) 템플릿으로 시작하는 방식과,

스타터 템플릿 없이 직접 처음부터 만드는 방식,

이렇게 둘 중 하나를 택할 수 있습니다.

여기서는 두 번째 방식, 즉 CLI로 직접 만드는 방법을 택해 보겠습니다.

Sanity Studio 설치하기

새 프로젝트 디렉터리를 하나 만든 다음, 그 곳에서 아래 명령을 내립니다.

$ mkdir sanity-demo && cd sanity-demo
$ npm install @sanity/cli -g
$ sanity init

sanity init 명령을 실행하면 프로젝트 설정과 관련한 몇몇 항목들을 물어 오며, 그에 대해 답을 하면서 지나가면 최종적으로 프로젝트 디렉터리 내에 Sanity Studio가 설치되게 됩니다.

참고로, 여기서는 데이터셋 선택 항목에서 “Movie project (schema + sample data)”를 선택했습니다. 이러면 Sanity Studio에서 사용할 스키마와 몇몇 샘플 데이터들이 자동으로 추가됩니다.

$ sanity init
You're setting up a new project!
We'll make sure you have an account with Sanity.io. Then we'll
install an open-source JS content editor that connects to
the real-time hosted API on Sanity.io. Hang on.

Press ctrl + C at any time to quit.

Prefer web interfaces to terminals?
You can also set up best practice Sanity projects with
your favorite frontends on https://sanity.io/create

Looks like you already have a Sanity-account. Sweet!

? Select project to use Create new project
? Your project name: Hello Sanity
Your content will be stored in a dataset that can be public or private, depending on
whether you want to query your content with or without authentication.
The default dataset configuration has a public dataset named "production".
? Use the default dataset configuration? Yes
✔ Creating dataset
? Project output path: /Users/sjoonk/sanity-demo
? Select project template Movie project (schema + sample data)
? Add a sampling of sci-fi movies to your dataset on the hosted backend? Yes
✔ Bootstrapping files from template
✔ Resolving latest module versions
✔ Creating default project files

✔ Saved lockfile
✔ [100%] Fetching available datasets
✔ [100%] Reading/validating data file (190ms)
✔ [100%] Importing documents (1.67s)
✔ [100%] Importing assets (files/images) (29.40s)
✔ [100%] Setting asset references to documents (2.85s)
✔ [100%] Strengthening references (669ms)
Done! Imported 205 documents to dataset "production"

If you want to delete the imported data, use
	sanity dataset delete production
and create a new clean dataset with
	sanity dataset create 

여기까지 완료되었으면, 이제 터미널에서 sanity start 명령으로 스튜디오를 한번 실행시켜 보세요!

$ sanity start
✔ Checking configuration files...
⠙ Compiling...webpack built 4d87eec04f5888cd2d4d in 29597ms
✔ Compiling...
Content Studio successfully compiled! Go to http://localhost:3333

그런 다음, 브라우저에서 http://localhost:3333 주소로 접속하면 우선 아래와 같이 사용자 인증창이 먼저 뜨게 되고,

어느 방식이든 하나를 골라 인증을 마치면, 스튜디오가 로컬 환경에서 실행되는 것을 확인할 수 있습니다.

여기까지 다 되었으면, 스튜디오를 한번 둘러 보세요! 새로 데이터를 추가할 수도 있고 기존 데이터를 변경할 수도 있습니다. 물론 이렇게 추가하거나 변경된 데이터는 Sanity API를 통해 리모트 클라우드(sanity.io) 측에 바로 반영됩니다.

일단 여기까지 했으면, Sanity 셋팅은 완료되었습니다. 물론 몇 가지 추가로 더 설명할 것들이 있습니다만, 이미 내용이 너무 길어진 관계로 이 글에서는 생략하겠습니다. 예를 들면 이런 것들입니다.

  • 스키마(schema)를 새로 만들거나 기존 스키마를 변경할 수 있습니다.
  • 로컬 스튜디오를 리모트 서버 환경에 배포할 수 있습니다.
  • 자체 쿼리언어 또는 GraphQL을 사용하여 데이터를 쿼리할 수 있습니다.
  • Sanity API에 대한 인증을 설정할 수 있습니다.
  • 외부 데이터를 임포트(import) 시킬 수 있습니다.

더 자세한 내용은 Sanity 공식 문서를 참고하시면 될 것입니다.

Gatsby와 연동하기

이제 Gatsby와 연동을 할 차례입니다.

앞서도 잠깐 언급했듯이 Sanity는 일종의 Headless CMS입니다. 그러니 Gatsby에서는 Sanity를 데이터 소스로 취급하여 불러 올 수 있습니다. 이 때는 물론 GraphQL을 사용해야 겠죠.

다행히 Sanity에서는 Sanity를 Gatsby 데이터 소스로 사용할 수 있도록 플러그인을 제공합니다. 이 플러그인을 Gatsby 프로젝트에 추가하면 어렵지 않게 Gatsby 사이트에서 Sanity 데이터를 가져올 수 있습니다.

그럼, 앞서 Sanity Studio에서 만든 데이터를 한번 Gatsby로 불러와 볼까요?

gatsby-source-sanity 플러그인 설치

우선 Gatsby 프로젝트에 gatsby-source-sanity 플러그인을 설치합니다.

$ npm install gatsby-source-sanity

그런 다음, gatsby-config.js 파일을 열어 플러그인 정보를 다음과 같이 추가해 줍니다.

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-sanity`,
      options: {
        projectId: `abc123`,
        dataset: `blog`,
        // a token with read permissions is required
        // if you have a private dataset
        token: process.env.SANITY_TOKEN,
      },
    },
  ],
}

이 때 options 항목에 들어가는 projectId 값과 dataset 값은 Sanity Studio 프로젝트 루트 디렉터리에 있는 sanity.json 파일에서 확인할 수 있습니다. 그 값을 여기 options 항목에 넣어주면 됩니다.

GraphQL API 셋팅

이제 Sanity 측에서 데이터셋을 GraphQL API로 액세스할 수 있도록, Sanity에 요청해야 합니다. 이 작업은 Sanity Studio 프로젝트 내에서 아래 명령을 주면 됩니다.

$ sanity graphql deploy

※ 참고로, 이 명령은 Sanity Studio에서 데이터 스키마를 변경했을 때마다 한번씩 호출해 주어야 합니다. 데이터 스키마의 변경 내역을 GraphQL API에 반영해야 하기 때문입니다.

이제 Gatsby에서 GraphQL이 제대로 작동되는지 확인할 수 있습니다.

gatsby develop 명령으로 Gatsby를 개발 서버를 띄운 다음, GraphiQL ( http://localhost:8000/__graphql )에 접속해 보면, 다음과 같이 Sanity 데이터가 로드되어 있는 것을 확인할 수 있습니다.

나머지는 통상적인 Gatsby 처리 루틴을 따르면 됩니다. 이 데이터를 가져와 필요한 곳에서 로드하여 보여주면 되겠죠.

이런 부분들은 일반적인 Gatsby 사용법이기 때문에 별도 설명을 생략합니다. 관심있는 분들은 직접 한번 해 보시면 좋을 듯 싶습니다. 🙂