Issue
주로 백엔드를 담당하면서 웹 디자인에 관심이 많아졌다. 무슨 소리인가 하면, 백엔드나 프론트엔드의 경우에는 사용자 입장에서 직관적으로 볼만한 것이 없다. 기능이 제대로 동작한다는 것과 코드 정도인데, 이것과 연결되는 게 웹 디자인이다.
기왕이면 기능이 동작하는걸 보여줄 때, 단순히 검은 배경의 콘솔창에 보여주는 것보다 최소한 디자인이 가미된 페이지가 좋지 않을까? 같은 백엔드, 프론트엔드 개발의 결과물을 단순히 보여주는 창이다. 하지만 코드의 효율성을 따지는 것과 별개로 샘플을 동작시켜 보는 입장에서 제멋대로인 길이의 입출력창 등에 시달리는 것보다, 서툴더라도 깔끔한 디자인의 창이 있는 것이 더 좋다고 생각했다.
그래서 생각한 것이 이 블로그에 간간히 웹 템플릿을 만들어보면서 데모 페이지를 다뤄볼 수 있는 뷰어 컴포넌트였다. 코드는 Github 등을 통해서 공유하더라도, 영상을 찍을 게 아니라면 데모 페이지를 다룰 수 있는 게 맞다고 봤다.
Gatsby
컴포넌트 추가에 있어서 필요한 것들이 부분들이 있다. 생성할 파일은 반복되는 페이지의 템플릿을 구성하는 템플릿 파일, 마크다운 포스트의 HTML 파일을 렌더링할 컴포넌트 파일이다. 그리고 페이지를 생성하는 create-pages.js 파일의 수정이 필요했다. 다른 파일이나 디렉토리 구조는 변경할 필요가 없었다.
else if (_.get(edge, 'node.frontmatter.template') === 'view') {
createPage({
path: edge.node.fields.slug,
component: path.resolve('./src/templates/view-template.js'),
context: { slug: edge.node.fields.slug }
});
}Gatsby는 사이트 내의 모든 페이지를 사전에 렌더링한다. 그 작업을 create-pages.js에서 진행하는데, 미리 새 템플릿 조건을 넣어 CreatePage 함수를 실행하도록 수정했다.
View Template
const ViewTemplate = ({ data }) => {
...
return (
<Layout title={`${postTitle} - ${siteTitle}`} description={metaDescription}>
<HTMLView view={data.markdownRemark} />
</Layout>
);
...
};먼저 포스트 컴포넌트와 비슷한 형태로 동작하기 때문에 포스트 템플릿 파일을 간단하게 수정했다.
View Component
const HTMLView = ({ view }) => {
const { html } = view;
return (
<div dangerouslySetInnerHTML={{ __html: html }}></div>
);
};
export default HTMLView;다음으로 HTMLView라는 이름으로 컴포넌트 파일을 만들었다. 마크다운에 작성된 HTML 코드를 읽어오기만 하면 되기 때문에 단순한 구문으로 작성이 끝났다.
마크다운에서 template가 view라면 ViewTemplate를 통해 렌더링 하고, Layout 컴포넌트 안에 작성된 HTMLView 컴포넌트를 참조한다. 이때 HTMLView 컴포넌트를 생성할 때, GraphQL로 가져온 데이터인 markdownRemark을 보내준다.
HTMLView 컴포넌트에서는 템플릿에서 보낸 HTML 코드를 받아와 렌더링 하는데, 여기서 HTML 코드는 String 형태로 넘어온다. 이때, dangerouslySetInnerHTML 속성을 사용하면 String 형태의 HTML을 렌더링할 수 있다.