- Published on
블로그개발기 (2) - NextJS, Tailwind
- Authors
- Name
- Cheesepaninim
Dev Stack
- React
Gatsby(with starter)- NextJS
SemanticUIBootstrap- Tailwind with tailwind-nextjs-starter-blog
- Vercel
- GA
History
Gatsby
개인 블로그를 갖고 싶다는 마음에 약간의 욕심을 보태어 사이트의 컨트롤이 가능하게 하고 싶었다. 그래서 기존에 사용했던 티스토리가 아닌 정적 사이트 개발로 눈을 돌리게 되었고 자연스레 React 를 사용하는 Gatsby를 알아보게 되었다.
다행히도 많은 스타터 템플릿(Gatsby Starters)들이 존재했고 데모 페이지를 둘러보며 세 개 정도를 선정했다. 새로운 나의 블로그라는 기분좋은 시작도 잠시, 개발을 하면 늘 그랬듯이 여러가지 문제들을 마주하였고 그 과정이 생각보다 길어져 결국 포기하게 되었다.
따로 기록을 하지는 않았지만 각각의 템플릿 소스에 문제도 있었던 것 같고 최근 Node 업데이트를 실행하면서 호환 문제나, npm cache 등의 문제가 있었던 것으로 기억한다. 길어지는 과정 속에서 node 재설치등의 과정을 반복하기 귀찮았던 나는 우선 빨리 시작하고 싶었던 마음이 컸던터라, 단순히 React 를 사용하여 개발하고 디벨롭하는 방향으로 마음을 바꾸었다. (이것도 역시 조금 지쳐서 너무 섣불리 정했던 것 같다.)
React
Semantic-UI → React-Bootstrap
아무리 맨땅에서 시작하더라도 UX/UI 고민까지 가면 부족한 센스에 넘쳐나는 창작욕의 시너지로 시간이 너무 길어질 것 같았다. 마음에 드는 UI 라이브러리를 찾아보다가 예전에 한 번 사용해보았던 semantic-ui 를 사용하기로 했다.(여전히 섣부른 결정이었다.)
•
•
다만 마지막 업데이트가 4년 전이었다. css 파일 하나에는 세미콜론이 두번 찍혀있는 어이없는 코드가 남아있었고 "@semantic-ui-react/css-patch": "^1.0.0"를 추가로 설치해서 "build": "semantic-ui-css-patch && react-scripts build" 로 빌드 스크립트를 변경함으로써 해결했다.
다음으로 Layout 을 잡기위해 header, footer 영역을 잡는데 다시 반응형에서 문제가 생겼고 (이 부분은 전적으로 나의 css 이해도 부족이다.) 더 익숙하긴 했지만 twitter 느낌을 피하고 싶어 안쓰려했던 Bootstrap 으로 넘어가기로 했다. 물론, 부트스트랩은 커스터마이징도 나름 어렵지 않게 할 수 있도록 제공된다고 생각되지만 UI/UX를 다루는 시간을 최소화 하고 싶었다.
(참고로 최근에는 Semantic UI가 아닌 Fomantic-UI 에서 버전 업이 진행되고 있는 것 같다.)
SEO Bootstrap 으로 넘어가서 화면 UI도 정말 심플하지만 완성이 되었고 홈화면, 목록화면(전체 / 카테고리별
목록), 게시글 화면 등 라우팅 처리까지 완료되었다. 앞으로 한 단계, SEO 만이 남았으나 이전에도 해보았고 무난하게 진행되리라 생각했다.
sitemap.xml
네이버와 구글에서 사이트 등록을 하고 Google Analytics 도 적용 했다. robots.txt 파일을 추가하고 react-router-sitemap 을 이용해 빌드할 때 sitemap.xml 파일이 추가되도록 하려 했으나 실패. babel preset 관련 문제였으나 여기에도 역시 npm 이 엮인 것 같았고 큰 고민 없이 포기했다. 정확히는 react-router-sitemap 의 사용을 포기했다.
url mapping 을 위한 카테고리 및 포스터 정보를 따로 관리하기 위해 분리 되어 있었고 아래와 같이 어렵지 않게 sitemapBuilder.js 를 만들 수 있었다.
[sitemapBuilder.js]
const URL = process.argv[2]
const c = [
// category
{ type: 'category', name: 'blog', count: 0 },
{ type: 'category', name: 'dev', count: 0 },
{ type: 'category', name: 'economy', count: 0 },
{ type: 'category', name: 'smalltalk', count: 0 },
]
const p = [
// post { type : {categoryName}, name : {postName} }
{
id: '',
type: 'blog',
title: '블로그 개발기',
intro: '블로그 개발기 1탄',
dttm: '2022-06-19 20:58',
},
{
id: '',
type: 'dev',
title: '개발일지',
intro: '2022년 6월 19일 개발 일지',
dttm: '2022-06-19 23:45',
},
{
id: '',
type: 'economy',
title: '경제학원론',
intro: '돈의 주인이 되자',
dttm: '2022-06-20 01:01',
},
]
const getCat = (nm) => c.filter((v) => v.name === nm)[0]
const cats = {
blog: getCat('blog'),
dev: getCat('dev'),
economy: getCat('economy'),
smalltalk: getCat('smalltalk'),
}
p.map((v) => (v.id = (++cats[v.type].count).toString()))
const create = async () => {
console.log(URL)
const urls = [`${URL}/profile`, `${URL}/post/all`]
const postUrl = `${URL}/post`
c.forEach(({ name }) => urls.push(`${postUrl}/${name}`))
const defaultUrl = ` <url>
<loc>${URL}</loc>
<priority>1.0</priority>
</url>\n`
const urlSet = urls.map(
(u) => ` <url>
<loc>${u}</loc>
</url>`
)
const postUrlSet = p.map(
(post) => ` <url>
<loc>${postUrl}/${post.type}/${post.id}</loc>
<lastmod>${post.dttm.slice(0, 10)}</lastmod>
</url>`
)
let intro = `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`
let outro = `\n</urlset>`
let sitemap = intro + defaultUrl + urlSet.join('\n') + '\n' + postUrlSet.join('\n') + outro
await fs.promises.writeFile('public/sitemap.xml', sitemap, {
encoding: 'utf-8',
})
return
}
create()
다만 위 코드에서 카테고리와, 포스트 정보는 CommonJS와 ES6 차이로 우선 손수 복사해오는 방식으로 했는데 개선이 필요한 부분이었다.
[package.json]
"scripts": {
// ...
"build": "npm run sitemap && react-scripts build",
"sitemap": "node ./src/config/sitemapBuilder.js https://cheesepaninim.netlify.app"
},
Open Graph
이 부분에서 이해도가 부족해서 시간을 많이 소비했던 것 같은데, 결론적으로는 다시 한 번 처음으로 돌아가 next-js로 갈아타게 된 계기가 되었다. 특히 테스트가 로컬에서 불가능하고 실제 배포 후에 가능하기에 더 오래 걸렸던 것 같다.
간단히 설명하자면, React는 CSR로 하나의 index.html 파일을 만들고 JS로 처리를 한다. 이 부분을 보완하기 위해 react-helmet 을 사용해 페이지 별로 <head></head> 영역 내의 정보들을 다르게 구성하였고 og 관련 meta 정보들을 추가하였다.
그리고 react-snap 으로 react-router-dom 의 구성에 맞게 index.html 을 여러개 생성되도록 pre-rendering 하려 했으나! react-snap 에서는 동적 라우팅에 대한 지원이 되지 않았다. 물론 방법이 있었을지도 모른다. 하지만 react-snap 역시 npm 에서 last published 가 4년전 이었기에, 아직 늦지 않았다는 생각에 next-js 로 넘어가기로 결심했다. (생각해보면 이전에 SEO를 적용했을 때도 next-js 를 사용했다...)
🔔 참고 URL
- 카카오 OG 캐시 삭제 : https://developers.kakao.com/tool/clear/og
- 페이스북 공유 디버거 : https://developers.facebook.com/tools/debug/
- Open Graph : https://www.opengraph.xyz/url/
생각보다 내용이 길어져서 현재 블로그에 관한 내용은 블로그개발기 (3)에서 이어가려 한다.
NextJS 로 갈아 엎기 전 ↓

