๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์์ฒด์ ์ง์ ์ ์ผ๋ก ๋ฃ์ด์ฃผ๋ ๊ฒ๋ณด๋ค๋ ๋ฐ์ดํฐ๋ง์ ๊ด๋ฆฌํ ์ ์ ์ธ ํ์ผ์ ๋ถ๋ฌ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ ๊ฒ ๊ฐ๋ค๊ณ ์๊ฐํด์ ๊ทธ๊ฒ์ ์คํํ ๋ฐฉ๋ฒ์ ์์ฑํ๋ ํฌ์คํธ์ ๋๋ค.
HTML
์ด๋ JavaScript
์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ ์ฌ์ฉํ ์๋ ์๊ฒ ์ง๋ง ๋ฐ์ดํฐ ๋ฐ๋ก ํ๋ฉด์ ๊ตฌ์ฑํ๋ ์ฝ๋ ๋ฐ๋ก ์ค๊ณํ๋ ๊ฒ ์ ์งใ๋ณด์ ์ธก๋ฉด์์๋ ๋ ์ข๋ค๊ณ ํ๋จํด์ ๋ฐ๋ก markdown
ํ์์ ํ์ผ๋ค์ ์ ์ ์ธ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด๋๊ณ ๊ฐ์ ธ์์ ์ฌ์ฉํฉ๋๋ค.
# "front-matter"๋ฅผ ํ์ฑํด์ ๊ฐ์ฒด ํํ์ ๋ฐ์ดํฐ๋ก ๋ณํํด์ค๋๋ค.
npm i gray-matter
markdown.md
---
title: ๋์ถฉ ์ ๋ชฉ
skills: ["HTML", "CSS"]
project: {
name: "Blegram",
description: "๋์ถฉ ๋ด์ฉ"
}
---
**๋์ถฉ ๋ณธ๋ฌธ ๋ด์ฉ**
import { readFile } from "fs/promises";
(async () => {
// ์ฌ๋ฌ ํ์ผ์ ์ฝ์ผ๋ฉด ๋์์ ์ฒ๋ฆฌํด์ฃผ๊ธฐ ์ํด promise์ฌ์ฉ
const markdownFilePromise = readFile("./src/markdowns/cover.md");
const [markdownFile] = await Promise.all([markdownFilePromise]);
// JSON.parse(), JSON.stringify()์ ์ฌ์ฉํ๋ ์ด์ ๋ ์๊ฐ๊ฐ์ด ์ ๋๋ก ๋ชป์ฝ์ด์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ๋๋ฌธ
const result = JSON.parse(JSON.stringify(matter(markdownFile));
/*
* result์๋ ์ฌ๋ฌ ๊ฐ์ด ์์ง๋ง ์ฌ์ฉํ๋ ๊ฒ๋ง ๊ธฐ์ฌํ๊ฒ ์
* result.data => { title: "๋์ถฉ ์ ๋ชฉ", skills: ["HTML", "CSS"], project: { name: "Blegram", description: "๋์ถฉ ๋ด์ฉ" } }
* result.content => "\r\n**๋์ถฉ ๋ณธ๋ฌธ ๋ด์ฉ**"
*/
})();
# `markdown`ํ์์ผ๋ก ์
๋ ฅ๋ฐ์ ํ
์คํธ๋ฅผ `HTML`ํ์์ผ๋ก ํ์ฑํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
npm i remark-parse remark-html unified
// ์ง์ ์คํํ๋ ค๋ฉด "type": "module"๋ก ๋ณ๊ฒฝํ๊ธฐ
import remarkHtml from "remark-html";
import remarkParse from "remark-parse";
import { unified } from "unified";
const markdown = `# ์ ๋ชฉ
## ์์ ๋ชฉ
**๊ฐ์กฐ**
[๋งํฌ](https://naver.com)`;
(async () => {
const { value } = await unified()
.use(remarkParse)
.use(remarkHtml)
.process(markdown);
console.log(value);
/**
* '<h1>์ ๋ชฉ</h1>\n' +
* '<h2>์์ ๋ชฉ</h2>\n' +
* '<p><strong>๊ฐ์กฐ</strong>\n' +
* '<a href="https://naver.com">๋งํฌ</a></p>\n'
*/
})();
src/markdowns/skills.md
---
skills: {
HTML/CSS: "์ต๋ํ ์๋ฉํฑ ๊ตฌ์กฐ๋ฅผ ์งํค๊ธฐ ์ํด ๋
ธ๋ ฅํ๋ฉฐ, ์์ํ CSS๋ฅผ ๋จผ์ ์ดํดํ๊ณ ์ ์ฒ๋ฆฌ๊ธฐ๋ ํ๋ ์์ํฌ์ ๊ดํด ๊ณต๋ถํฉ๋๋ค.",
JavaScript: "[์คํ ์ปจํ
์คํธ, ํด๋ก์ , ํธ์ด์คํ
, ์ค์ฝํ ์ฒด์ธ](https://velog.io/@1-blue/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B2%B4%EC%9D%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%ED%81%B4%EB%A1%9C%EC%A0%80%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C), [ํ๋กํ ํ์
](https://velog.io/@1-blue/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-prototype) ๋ฑ์ ์์์ผ ํ ๊ธฐ๋ณธ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ํ ๊ฐ๋
์ ์ถฉ๋ถํ ์ดํดํ๊ณ ์์ต๋๋ค.\n ๋ํ ๋ฐฐ์ด ๋ฉ์๋๋ค, destructuring, spread operator, [Promise, async, await](https://velog.io/@1-blue/Promise-async-await) ๋ฑ์ ๋ฅ์ํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.",
TypeScript: "ํ์
๊ณผ ์ธํฐํ์ด์ค ์ ์ธ๊ณผ ๊ธฐ๋ณธ์ ์ธ ํ์
๋ค์ ๋ํด์ ์ดํดํ๊ณ ์์ผ๋ฉฐ, React.js์ Next.js์์ ์ฌ์ฉํด๋ณธ ๊ฒฝํ์ด ์์ต๋๋ค.",
React.js: "[Virtual DOM์ ์ด์ฉํ ์ฑ๋ฅ ๊ฐ์ ๊ณผ ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ ์ฝ๋ ๊ตฌํ์ ๋ํด ์ดํด](https://velog.io/@1-blue/React%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C#-react%EC%9D%98-%EC%82%AC%EC%9A%A9-%EC%9D%B4%EC%9C%A0)ํ๊ณ ์์ต๋๋ค.\n๋ํ Hook ๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐํ๋ ๊ฒ์ ์ต์ํ๋ฉฐ, ๊ธฐ๋ณธ์ ์ธ Hook์ ๋ํ ์ดํด๊ฐ ์์ต๋๋ค.",
Next.js: "SSR๊ณผ SSG์ ๋ํ ์ฌ์ฉ ๊ฒฝํ์ด ์์ผ๋ฉฐ, ์ด๋ค ๊ฒ์ ์ฌ์ฉํ ์ง ์ค์ค๋ก ํ๋จํ ์ ์์ต๋๋ค.\n๋ํ ์ด๋ฏธ์ง ์ต์ ํ, ๋ผ์ฐํ
์ฒ๋ฆฌ, ๊ฐ๋จํ API๋ค์ ์ฌ์ฉํด๋ณธ ๊ฒฝํ์ด ์์ต๋๋ค.",
Node.js: "์๋ฒ ๊ตฌํ(Express), ORM([sequlize](https://velog.io/@1-blue/sequelize), prisma), auth([passport](https://velog.io/@1-blue/passport))์ ๋ํ ๊ฒฝํ์ด ์์ต๋๋ค.\n๋ํ [์ฟ ํค์ ์ธ์
](https://velog.io/@1-blue/%EC%BF%A0%ED%82%A4%EC%99%80-%EC%84%B8%EC%85%98)์ ๋ํด ์ดํดํ๊ณ ์์ต๋๋ค.",
Mysql: "DDL, DCL, DML์ ๋ํ ๊ฒฝํ์ด ์์ผ๋ฉฐ, ๊ฐ๋จํ SQL์ ์์ฑํ๊ฑฐ๋ ๋ณด๊ณ ์ดํดํ ์ ์์ต๋๋ค. ( [mysql ์ ๋ฆฌ](https://velog.io/@1-blue/mysql) )",
Git/GitHub: "[Git๊ณผ GitHub](https://velog.io/@1-blue/Git%EA%B3%BC-GitHub-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC)์ ์ด์ฉํ ํ์
๊ฒฝํ์ด ์์ผ๋ฉฐ, Git-Flow ๋ฐฉ์์ ์ดํดํ๊ณ ์์ต๋๋ค.",
Trello: "๊ฐ๋ฐ ์ผ์ ๊ด๋ฆฌ๋ฅผ ์ํด ์ฌ์ฉํ๋ฉฐ, ํ์
์ ์ํด ์ฌ์ฉํ ๊ฒฝํ์ด ์์ต๋๋ค."
}
---
# โ๏ธ Skills ๐ ๏ธ
(async () => {
// ๋งํฌ๋ค์ด ํ์ผ ์ฝ๊ธฐ
const skillsFilePromise = readFile("./src/markdowns/skills.md");
const [parsedMarkdownSkills] = await Promise.all([parsedMarkdownSkillsPromise]);
// ์ฝ์ ํ์ผ ํ์ฑํ๊ธฐ ( front-matter )
// "content"์ ๋งํฌ๋ค์ด ๋ด์ฉ, "data"์ front-matter๊ฐ ๋ค์ด๊ฐ ์์
const parsedSkills = JSON.parse(JSON.stringify(matter(skillsFile)));
// ํ์ฑํ ํ์ผ์ front-matter์์ ๋ค์ ๋งํฌ๋ค์ด ํ์ ํ์ฑ
const promiseArray = Object.keys(parsedSkills.data).map((skill) =>
unified().use(remarkParse).use(remarkHtml).process(skills[skill])
);
// ๊ฒฐ๊ณผ
const descriptions = (await Promise.all(promiseArray)).map((v) => v.value)
})();
// ์๋์ ๊ฐ์ ํ์์ผ๋ก html ๊ทธ๋๋ก ๋๋๋ง ( with "dangerouslySetInnerHTML" )
return (
<div
className="description"
dangerouslySetInnerHTML={{ __html: descriptions[0] }}
/>
)
๋ฐ์ดํฐ๋ฅผ ๋ฃ์ ๋งํฌ๋ค์ด ํ์ผ์ ์์ฑํ๋ฉด์ ๊ทธ๋ฅ ๋งํฌ๋ค์ด ํ์์ผ๋ก ์์ฑํด์ ๊ทธ๋๋ก HTML
๋ก ํ์ฑํ ํ์ ํ๋ฉด์ ๋ ๋๋งํ๊ณ ์ถ์์ง๋ง ์ค๊ฐ์ ์คํ์ผ๋ ๋ฃ๊ณ , ์ด๋ฒคํธ๋ ๋ฑ๋กํ๋ ๋ฑ์ ๋ง์ ์์
์ ์ฒ๋ฆฌํด์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ํ์ฑํ HTML
์ ๊ทธ๋๋ก ๋ฃ์ ์๊ฐ ์์ด์ ๋ ๋ฒ์ ํ์ฑ๊ณผ์ (markdown
ํ์ฑ -> markdown
์ front-matter
ํ์ฑ)์ ๊ฑฐ์ณ์ ์ฝ๋๊ฐ ๋ง์ด ๋ณต์กํด๋ณด์
# โ๏ธ Skills ๐ ๏ธ
## HTML/CSS
์ต๋ํ ์๋ฉํฑ ๊ตฌ์กฐ๋ฅผ ์งํค๊ธฐ ์ํด ๋
ธ๋ ฅํ๋ฉฐ, ์์ํ CSS๋ฅผ ๋จผ์ ์ดํดํ๊ณ ์ ์ฒ๋ฆฌ๊ธฐ๋ ํ๋ ์์ํฌ์ ๊ดํด ๊ณต๋ถํฉ๋๋ค.
## JavaScript
[์คํ ์ปจํ
์คํธ, ํด๋ก์ , ํธ์ด์คํ
, ์ค์ฝํ ์ฒด์ธ](https://velog.io/@1-blue/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B2%B4%EC%9D%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85-%ED%81%B4%EB%A1%9C%EC%A0%80%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C), [ํ๋กํ ํ์
](https://velog.io/@1-blue/%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-prototype) ๋ฑ์ ์์์ผ ํ ๊ธฐ๋ณธ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ํ ๊ฐ๋
์ ์ถฉ๋ถํ ์ดํดํ๊ณ ์์ต๋๋ค.\n ๋ํ ๋ฐฐ์ด ๋ฉ์๋๋ค, destructuring, spread operator, [Promise, async, await](https://velog.io/@1-blue/Promise-async-await) ๋ฑ์ ๋ฅ์ํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
... ๋๋จธ์ง ์๋ต