React JS 마스터클래스 (GATSBY)

짜스의 하루 ·2024년 7월 18일

Gatsby

정적 웹사이트 생성기로 사용되는 프레임워크이다.
Gatsby는 React를 기반으로 하며, GraphQL을 이용해 데이터를 가져와 웹사이트를 빌드한다.

1 . React 기반: Gatsby는 React를 기반으로 하여 컴포넌트 기반 개발 방식을 지원한다. 이를 통해 코드의 재사용성을 높이고 유지보수를 용이하게 한다.

2 . GraphQL 통합: Gatsby는 GraphQL을 사용해 데이터를 가져온다. GraphQL은 데이터를 필요한 만큼만 효율적으로 가져올 수 있게 해주며, 다양한 데이터 소스(SQL, CMS, 파일 시스템 등)와의 통합을 용이하게 한다.

3 . 정적 사이트 생성: Gatsby는 빌드 시점에 정적 HTML 파일을 생성하여 배포한다. 정적 사이트는 로딩 속도가 빠르고, 보안성이 높으며, 호스팅 비용이 저렴하다.

4 . 플러그인 시스템: Gatsby는 다양한 플러그인을 제공하여 기능을 확장할 수 있다. 이미지 최적화, SEO 향상, PWA(Progressive Web App) 지원 등 다양한 플러그인을 통해 개발 시간을 단축하고 기능을 추가할 수 있다.

5 . SEO 친화적: 정적 HTML 파일로 빌드되기 때문에 검색 엔진에 친화적이며, 메타 태그나 Open Graph 태그 등을 쉽게 설정할 수 있다.

6 . 빠른 로딩 속도: Gatsby는 기본적으로 코드 스플리팅, PRPL 패턴(Push, Render, Pre-cache, Lazy-load) 등의 기술을 활용하여 빠른 로딩 속도를 제공한다.

예로 react로 만든 블로그를 빌드하면, 빌드 중 또는 빌드 시간에 프로젝트는 컴포넌트 요소 파일에서 호스팅 공급자에 배포할 수 있는 최적화된 HTML, CSS 및 JavaScript 파일로 변환됩니다.


Gatsby build

프로젝트를 하나 생성해서 폴더 구조를 보면

pages 폴더안에 404.tsx, index.tsx 두가지 파일이 생성된 것을 확인할 수 있다.
이제 npm run start를 터미널에 입력해서 화면을 렌더링해보면,

localhost:8000에서 Gatsby 개발 서버가 실행되고, src/pages 폴더에 있는 index.tsx 파일이 자동으로 렌더링되는 것을 확인할 수 있다.

그럼 여기서, page.tsx 파일을 간단하게 만들어 본 뒤, 렌더링하면?
라우터 설정을 해주지 않아도
/blog 에 화면이 렌더링 되는 것을 확인할 수 있다!



메인 페이지에 nav바를 생성해서 필요한 곳으로 이동할 수 있도록 해주었다. 여기서 사용한 Link는 react에서 제공하는 것이 아닌 Gatsby에서 제공하는 Link를 사용한다.

이렇게 하면, 손쉽게 Link를 사용해서 페이지 이동이 가능해진다.

그럼, 나는 home, about-us, blog에 모두 nav바를 생성하고 싶은데 어떻게 해야할까?
--> Gatsby에서 주로 사용하는 layout 컴포넌트를 생상하면 된다.

layout

Gatsby에서 layout은 웹사이트의 일관된 구조와 스타일을 유지하기 위해 사용되는 재사용 가능한 컴포넌트를 의미한다.
Layout 컴포넌트를 사용하면 여러 페이지에서 공통으로 사용되는 요소(예: 헤더, 푸터, 사이드바 등)를 한 곳에서 정의하고 관리할 수 있다.
--> 이를 통해 코드의 중복을 줄이고, 사이트의 유지보수를 쉽게 할 수 있게 된다.

src/components/layout.tsx를 생성해서 Layout 컴포넌트를 정의한다.

Layout 컴포넌트는 웹사이트의 여러 페이지에서 공통적으로 사용되는 네비게이션 바(nav bar) 와 페이지 타이틀을 포함하며, 페이지 컨텐츠를 children으로 받아서 렌더링한다.

interface

  • Layout 컴포넌트가 받는 props를 설명한다.
    --> children: React의 children prop으로, Layout 컴포넌트 내에서 렌더링될 자식 컴포넌트들을 의미한다,
    --> title: 각 페이지의 제목을 나타내는 문자열을 의미한다.

Layout 컴포넌트

  • Props: children과 title을 props로 받아온다.
  • 네비게이션 바(nav): 페이지 간 이동을 위한 링크 목록을 포함
    (여기서 사용하는 Link => Gatsby에서 제공하는 Link)

메인 콘텐츠(main)

  • <h1>{title}</h1>: 페이지의 제목을 렌더링한다.
  • {children} : 자식 컴포넌트들을 렌더링한다.

그럼 이렇게 정의한 Layout은 어떻게 사용할까?

const IndexPage = () => {
  return (
    <Layout title="Welcome to DevStickers 🫶">
      <div></div>
    </Layout>
  );
};

<Layout> 컴포넌트 : IndexPage를 감싸고, 공통 레이아웃(네비게이션 바 등)을 제공한다.
title Prop : "Welcome to DevStickers 🫶" 값이 Layout 컴포넌트로 전달되어, Layout 컴포넌트 내에서 {title}로 사용되게 된다.
children Prop : <Layout> 컴포넌트의 자식 요소로 <div></div>가 전달되어, Layout 컴포넌트 내에서 {children} 위치에 렌더링된다.

그럼 이렇게 nav, title이 나타나는 것을 확인할 수 있다.

그럼 이번에는 페이지마가 각각 페이지 title을 생성해보자

이것 또한 하나의 Layout을 만들 것이다

seo.tsx

import React from 'react';

interface ISeoProps {
  title: string;
}

export default function Seo({ title }: ISeoProps) {
  return (
    <>
      <title>{title} | DevStickers</title>;
    </>
  );
}

React를 사용하여 SEO(검색 엔진 최적화) 를 위한 Seo 컴포넌트를 정의한다. 이 컴포넌트는 HTML 문서의 <title> 태그를 설정하여 각 페이지의 제목을 지정하는 역할을 하게 된다.

Seo 컴포넌트

  • Props: ISeoProps 인터페이스를 통해 title이라는 문자열 props를 받는다.
  • JSX 반환값:
    <title>{title} | DevStickers</title> : HTML 문서의 <title> 태그를 설정한다. 이 태그는 브라우저의 탭 제목과 검색 엔진의 검색 결과에 표시되는 페이지 제목을 정의한다.
  • {title} | DevStickers : 전달된 title props와 문자열 " | DevStickers"를 결합하여 최종 제목을 설정한다.
    예를 들어, title이 "Home"이면 최종 제목은 "Home | DevStickers"가 되게 된다.

이렇게 정의한 Seo 컴포넌트

이렇게 불러다 사용하면 된다!

Gatsby에서는 페이지 컴포넌트에서 Head 컴포넌트를 정의하여 SEO 관련 태그를 설정할 수 있다. Head 컴포넌트는 Gatsby의 gatsby-plugin-react-helmet와 통합되어 SEO 설정을 쉽게 관리할 수 있게 해준다

Seo 컴포넌트가 페이지의 <title> 태그를 설정하고, 페이지 제목이 "Home | DevStickers"로 표시된다. 이 방법을 사용하면 각 페이지에서 SEO 관련 설정을 쉽게 관리할 수 있게 된다.


Blog 데이터 저장하기

만약, Gatsby에서 GraphQL을 사용해서 데이터를 가져오고, 블로그 글을 작성한다면,
여기서 보통 데이터를 html 로 변환하여 화면에 렌더링 하게 된다.

정적 사이트 생성도 지원하지만, 동적 데이터를 사용하여 페이지 렌더링하는 방식도 가능하다.
1 . 정적 사이트 생성 (Static Site Generation, SSG)
Gatsby는 정적 사이트 생성을 통해 사전에 HTML 파일을 생성하여 서버에 배포한다.
이 방식은 초기 로딩 속도가 빠르고 SEO에 유리하지만, 데이터가 변경될 때마다 사이트를 재빌드해야 한다.

2 . 클라이언트 사이드 렌더링 (Client-Side Rendering, CSR)
Gatsby는 React 기반으로 동작하며, 클라이언트 사이드 렌더링을 지원한다. 이 방식은 서버로부터 HTML을 받은 후에 JavaScript를 사용하여 데이터를 가져와 렌더링한다. 이 과정에서 초기 로딩 중 로딩 인디케이터를 표시할 수 있다.

GraphQL

GraphQL은 데이터를 효율적으로 관리하고 쿼리하기 위한 쿼리 언어

GraphQL의 주요 개념

  • 타입 시스템(Type System): GraphQL은 데이터를 타입 시스템으로 정의한다. 서버에 존재하는 데이터의 타입들과 관계를 명확하게 정의하여, 클라이언트가 필요한 데이터를 정확하게 요청할 수 있다.

  • 쿼리(Query): 클라이언트는 원하는 데이터를 서버에게 요청하기 위해 쿼리를 작성한다GraphQL 쿼리는 원하는 필드와 관계를 지정하여 구조화된 JSON 형태의 응답을 받을 수 있다.

  • 리졸버(Resolver): GraphQL 서버는 클라이언트의 쿼리를 해석하고, 각 필드의 데이터를 제공하기 위해 리졸버 함수를 사용한다. 리졸버는 데이터를 가져오거나 계산하여 응답을 구성하는 역할을 한다.

  • 뮤테이션(Mutation): 데이터를 변경하거나 업데이트하기 위해 사용된다. 쿼리와 달리 뮤테이션은 데이터를 생성, 수정, 삭제하는 작업을 수행한다.

  • 서브스크립션(Subscription): 데이터의 실시간 업데이트를 구독하고 이벤트 기반으로 처리할 수 있도록 지원하는 기능이다. 실시간으로 데이터가 변경될 때마다 클라이언트에게 업데이트를 전달할 수 있게 된다.

GraphQL 쿼리 연습해보기


우리는 렌더링할때, url을 두가지를 받아올 수 있다.
하나는 http://localhost:8000/___graphqlGatsby 개발 서버에서 제공하는 GraphQL IDE(GraphiQL) 이다.
이는 로컬 개발 환경에서 GraphQL 쿼리를 작성하고 실행할 수 있는 인터페이스를 제공하게 된다.


사이트를 타고 들어가면,

"Docs" 탭에서는 사용 가능한 GraphQL 스키마의 모든 타입(Type), 필드(Field), 인자(Argument) 등을 확인할 수 있다.
--> 이는 프로젝트에서 사용되는 데이터 소스(예: Markdown 파일, JSON 데이터 등)와 관련된 모든 정보를 제공한다.

여기서 나는

query MyQuery {
  site {
    siteMetadata{
			title
    	
    }
	}
}

MyQuery 라는 이름의 쿼리를 작성해 보았다.
(GraphQL에서 모든 쿼리는 이름을 가져야 하며, 이를 통해 클라이언트는 여러 쿼리를 구분할 수 있다)
site : site는 Gatsby에서 제공하는 특별한 타입이다. 이는 Gatsby의 데이터 소스에서 사이트 정보를 나타내는 객체이다. site 타입에는 사이트의 메타데이터와 관련된 정보가 포함된다.

siteMetadata : siteMetadata 는 site 객체의 하위 필드로, 사이트의 메타데이터 정보를 담고 있는 객체이다.

title : title은 siteMetadata 객체의 필드로, 사이트의 제목을 나타낸다. 이 필드는 주로 웹사이트의 제목을 표시하는 데 사용된다.


나는 제목의 DevStickers 를 GraphQL에 있는 title로 가져와서 사용해보려고 한다.

이때, 정적 쿼리를 사용해야 한다.
왜 ? Gatsby는 정적 사이트 생성을 지원하며, 이 과정에서 페이지의 데이터를 사전에 렌더링하여 최종 HTML 파일로 생성하게 된다.

Gatsby에서는 useStaticQuery 를 사용하여 정적 쿼리를 정의할 수 있다.
정적 쿼리는 Gatsby 빌드 시점에 실행되어 데이터를 가져오고, 사전에 HTML 파일로 렌더링 된다.
이 방식으로 페이지가 서버에 요청될 때마다 동저긍로 데이터를 가져오는 것이 아니라 , 사전에 빌드과정에 필요한 데이터를 표함시킨다.
--> 초기 로딩 속도를 빠르게 하고, SEO에 유리한 방법이다.

useStaticQuery란?
useStaticQuery는 빌드 시 리액트 훅을 사용하여 Gatsby의 GraphQL 데이터 계층을 쿼리하는 기능을 제공한다.
이를 통해 React 컴포넌트는 구문 분석, 평가 및 컴포넌트에 삽입될 GraphQL 쿼리를 통해 데이터를 검색할 수 있다.

그럼 useStaticQuery를 사용해서 data를 가져와보자

useStaticQuery 사용

  • useStaticQuery를 사용해서 GraphQL 쿼리를 실행한다.
  • graphql 템플릿 리터럴을 이용해 GraphQL 쿼리를 작성하고, useStaticQuery의 인자로 전달된다.
  • TypeScript에서 제네릭을 사용하여 반환되는 데이터의 타입을 명시적으로 지정한다.
    여기서 Queries.SeoDataQuery는 Gatsby 프로젝트에서 자동으로 생성된 타입 정의이다. 이는 Gatsby의 GraphQL 쿼리 결과에 기반한 타입을 생성하는 방식으로 사용된다.

쿼리 작성

  • 위 GraphQL 쿼리는 site 객체에서 siteMetadata의 title 필드를 가져오는 것을 목적으로 한다.

  • siteMetadata는 주로 Gatsby 설정 파일(gatsby-config.js)에서 정의된 사이트 메타데이터를 포함한다.

  • 이 쿼리는 Gatsby의 빌드 시점에 실행되어 사이트의 제목을 가져와서 사용할 수 있다.

이렇게 이전과 똑같이 제대로 출력되는 것을 확인할 수 있다!

GraphQL로 블로그 글 불러오기

만약, 이렇게 블로그 글이 있다고 가정해보자.

여기서 gatsby-source-filesystem
파일 시스템의 데이터를 Gatsby GraphQL 데이터 레이어로 가져오는 역할을 한다. gatsby-source-filesystem 은 가장 기본적인 데이터 소스 플러그인 중 하나를 나타낸다.

resolve : 플러그인의 이름을 지정한다. 여기서는 gatsby-source-filesystem을 사용한다.
options : 플러그인에 전달되는 옵션을 지정한다.
path : 데이터를 가져올 파일들의 디렉토리 경로를 지정한다. 여기서는 ${__dirname}/blog-posts 로 설정하여 프로젝트의 blog-posts 폴더에 있는 파일들을 가져온다.

이렇게 정의해 두었으니, GraphQL 쿼리로 한번 가져와보자!

query Myquery {
  allFile {
    nodes {
      name
    }
  }
}

이렇게 쿼리를 작성하니, 파일들의 name을 만들 수 있었다.
그럼, Blog 페이지에서 BlogTitle를 가져와보자

  • PageProps<Queries.BlogTitleQuery>: TypeScript를 사용하여 data prop의 타입을 지정합니다. 이 타입은 GraphQL 쿼리 결과의 타입과 일치해야 합니다.
  • data: Gatsby가 GraphQL 쿼리의 결과를 이 prop으로 전달한다. data는 쿼리에서 반환된 데이터를 포함한다.
  • data.allFile.nodes.map((file, index) => (<li key={index}>{file.name}</li>)): data.allFile.nodes는 파일 노드들의 배열이다.
    map 함수를 사용하여 각 파일 노드의 이름을 <li> 요소로 렌더링한다.
    <li> 요소는 file.name을 표시하며, 고유한 key로 index를 사용하게 된다.

GraphQL 쿼리

  • graphql 태그를 사용하여 GraphQL 쿼리를 정의한다
  • query BlogTitle: 쿼리의 이름이다
  • allFile: Gatsby의 파일 시스템에서 모든 파일을 쿼리한다.
  • nodes: 파일 노드들의 배열이다.
  • name: 각 파일 노드의 이름을 가져온다


이렇게 페이지를 렌더링해보면, 파일들의 이름이 출력되는 것을 확인할 수 있다!

profile
2024. 01. 02 ~ 백앤드 공부 시작, 2024. 04.01 ~ 프론트 공부 시작

0개의 댓글