๐Ÿง ์ •์  ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๋ฐ ๋งˆํฌ๋‹ค์šด ํŒŒ์‹ฑ

๋ฐ•์ƒ์€ยท2022๋…„ 6์›” 16์ผ
0

๋ฐ์ดํ„ฐ๋ฅผ ์ฝ”๋“œ ์ž์ฒด์— ์ง์ ‘์ ์œผ๋กœ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ๋ฐ์ดํ„ฐ๋งŒ์„ ๊ด€๋ฆฌํ•  ์ •์ ์ธ ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์™€์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ๊ทธ๊ฒƒ์„ ์‹คํ–‰ํ•œ ๋ฐฉ๋ฒ•์„ ์ž‘์„ฑํ•˜๋Š” ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

HTML์ด๋ž‘ JavaScript์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์žˆ๊ฒ ์ง€๋งŒ ๋ฐ์ดํ„ฐ ๋”ฐ๋กœ ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๋Š” ์ฝ”๋“œ ๋”ฐ๋กœ ์„ค๊ณ„ํ•˜๋Š” ๊ฒŒ ์œ ์ง€ใ†๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ๋„ ๋” ์ข‹๋‹ค๊ณ  ํŒ๋‹จํ•ด์„œ ๋”ฐ๋กœ markdownํ˜•์‹์˜ ํŒŒ์ผ๋“ค์— ์ •์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด๋‘๊ณ  ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๐Ÿคœ ํŒŒ์ผ๊ณผ front-matter ์ฝ๊ธฐ

1. ์„ค์น˜

# "front-matter"๋ฅผ ํŒŒ์‹ฑํ•ด์„œ ๊ฐ์ฒด ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋กœ ๋ณ€ํ™˜ํ•ด์ค๋‹ˆ๋‹ค.
npm i gray-matter

2. ์‚ฌ์šฉ ์˜ˆ์‹œ

  • 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**๋Œ€์ถฉ ๋ณธ๋ฌธ ๋‚ด์šฉ**"
   */
})();

๐Ÿค› ๋งˆํฌ๋‹ค์šด ํŒŒ์‹ฑ

1. ์„ค์น˜

# `markdown`ํ˜•์‹์œผ๋กœ ์ž…๋ ฅ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ `HTML`ํ˜•์‹์œผ๋กœ ํŒŒ์‹ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
npm i remark-parse remark-html unified

2. ์˜ˆ์‹œ

// ์ง์ ‘ ์‹คํ—˜ํ•˜๋ ค๋ฉด "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) ๋“ฑ์„ ๋Šฅ์ˆ™ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

... ๋‚˜๋จธ์ง€ ์ƒ๋žต

0๊ฐœ์˜ ๋Œ“๊ธ€