3. 블로그 만들기 - 리펙토링
블로그를 만들기 시작한지 한달 정도 지났다. 평소 생각하던 디자인과 기능, 로직을 작성하고 개선하고 포스팅글을 적다보니 여러 부족하고 개선하고 싶은 부분들이 자꾸 눈에 밟혔다. 그래서 추가적인 기능 개선을 할려고 보니 흔히 말하는 클린코드, 모듈화에 대하여 많이 부족하다고 느껴졌다. 그래서 지금까지의 기능을 포괄하도록 새로운 코드로 앞으로의 개선을 위한 리팩토링을 진행하였다.
핵심 데이터 기준의 작동
- 우선 리팩토링의 가장 핵심은 핵심 데이터의 존재이다. 구 버전에서는 네비게이션, 포스팅 페이지를 제작할때마다 파일 탐색을 진행하며 파일에 작성되어 있는 데이터를 읽어 들이는 작업을 진행하였다. 이러한 방식은 로직이 간편하다는 장점이 있지만 성능상의 이슈가 우려되고 개선 작업이 추가될때마다 네비게이션과 포스팅 페이지 작성 로직을 모두 수정해야 되는 단점이 있었다. 다양한 기능과 로직이 추가될수록 두 곳에서의 로직을 수정해야하는데 분석에 들어가는 시간이 늘어가기에 로직 수정의 필요성을 느끼게 되었다.
- 핵심 데이터는 위와 같은 이슈를 해결하기위 최초 1회 파일 탐색을 수행하며 필요한 데이터를 모두 포함하는 JSON 기반의 데이터 트리를 제작하고 이러한 데이터를 기반으로 네비게이션과 포스팅 페이지를 제작하는 방식이다. 기능이 추가되고 수정작업이 진행되며 필요한 데이터가 추가될시 JSON 데이터를 생성할때 추가하여 로직간의 충돌을 최소화 하게 되었다.
const recursion = (root, fold = []) => {
const temp = {}
// ballboy / index 파일과 공통 파일들의 관리 방안에 대하여 고민해보기
const post = fs.readdirSync(root).filter((v) => { return ['_Common', 'index.md'].indexOf(v) < 0 })
post.map((v) => {
// 최초 1회 파일 리딩
const isDir = fs.statSync(`${root}/${v}`).isDirectory();
if (isDir) {
// 디렉토리/네비게이션 제작을 위한 데이터를 포함한 json 데이터
const [title, index] = path.basename(v, path.extname(v)).split('_');
if (parseInt(index) !== 0) {
const child = recursion(`${root}/${v}`, [...fold, index]);
const count = Object.keys(child).reduce((a, b) => {
const [type, index] = b.split('_');
return a + (type === 'dir' ? child[b].count : (parseInt(index) === 0 ? 0 : 1));
}, 0);
const item = {
title,
file: '',
index: parseInt(index),
count,
// 디렉토리 내부 아이템은 children이라는 데이터 내부에 저장된다.
children: { ...child }
};
temp[`dir_${index}`] = item;
}
} else {
// 포스팅 페이지 제작을 위한 데이터를 포함한 json 데이터
const mdFile = matter(fs.readFileSync(`${root}/${v}`, 'utf8').trim());
const title = mdFile.data?.title;
const index = mdFile.data?.index || 0;
if (parseInt(index) !== 0) {
const item = {
title,
file: path.basename(v, path.extname(v)),
index: parseInt(index),
path: `${root}/${v}`,
fold,
date: mdFile.data?.date || '99999999',
...mdFile.data,
content: mdFile.content
};
temp[`post_${index}`] = item;
utils.contents.push(item);
}
}
})
return temp
}
레이아웃 세분화
- 기존 하나의 텍스트 데이터를 기반으로 데이터만 추가하여 포스팅 페이지 html 코드를 제작했지만 개선된 버전에서는 포스팅 페이지 html 코드의 헤더와 profile, navi, content, prev, next 등 코드를 세분화 하여 최종적으로 하나로 합치도록 수정이 되었다. 그 결과 디자인 개선 작업이나 기능 추가 작업에서도 좀 더 직관적인 코드 분석과 개선 작업이 가능해졌다.
const assets = (param) => {
const { assetsUrl, index, fold } = param
const html = `
<link rel='stylesheet' href='${assetsUrl}/markdown.css'>
<link rel='stylesheet' href='${assetsUrl}/skin.css'>
<style>
#p-${index} {
color: rgb(76, 193, 237) !important;
}
</style>
<script id='data' type='application/json'>
{
'fold': ${JSON.stringify(fold)}
}
</script>
<script src='${assetsUrl}/skin.js'></script>
`
return html
}
const prev = (param) => {
const { url, prev } = param
const html = `
<a href='${url}/post/${prev}.html' class='prev post'>
<img src='${url}/assets/img/prev.svg' alt='' srcset=''>
</a>
`
return html
}
const next = (param) => {
const { url, next } = param
const html = `
<a href='${url}/post/${next}.html' class='next post'>
<img src='${url}/assets/img/next.svg' alt='' srcset=''>
</a>
`
return html
}
포스팅 파일 데이터 관리 방법 - gray-matter
- 기존 포스팅 파일을 위한 메타 데이터는 파일 이름 타이틀과 index 번호를 작성하고 좀더 디테일한 데이터는 파일 내용에 json 형식으로 작성하였고 파일 변환 과정에서 json 형식을 추출하고 삭제하는 방식을 사용하였다. 이러한 방법은 데이터 추가에 어려움을 야기하고 데이터 처리의 난이도를 높이게 되었다. 다양한 방법을 찾아보다가 gray-matter 라이브러리를 찾아 사용하게 되어 데이터 관리 방안을 개선할 수 있었다.