This project is licensed under the terms of the MIT license.
์ฌํํ ํ๋ซ ๋์์ธ์ ์ ์ ์น ํฌํธํด๋ฆฌ์ค/์ด๋ ฅ์ ํ์ด์ง๋ฅผ ์ ์ํ ์ ์๋ ํ ํ๋ฆฟ ํ๋ก์ ํธ์์ ๐ค
์ด๋ ค์ธ ๊ฒ ๊ฐ๋ค๊ตฌ์? ๋์ธ ๋
ธ๋
ธ.markdown
๊ณผ json
๋ง ์์ฑํ ์ค ์๋ค๋ฉด, ์์ฝ๊ฒ ๋ง๋ค ์ ์์ด์!๐
next.js
typescript
tailwind
next-seo
react-markdown
๐ข ๋ฌธ์ ๊ด๋ฆฌ ์ฑ์ ์ด์ฉํด์ ์ด๋ ฅ์ ๋ฐ ํฌํธํด๋ฆฌ์ค๋ฅผ ๊ด๋ฆฌํ ๋, ์กฐ๊ธ ๋๋ฆฌ๋ค๊ณ ์๊ฐํ์ง ์์๋์?
โน๏ธ ๋ฌธ์ ๊ด๋ฆฌ ์ฑ์ด ์ ๊ณตํ๋ ๋์์ธ์ด ๋ง์์ ๋ค์ง ์์๋์?
๐ ๋ด ์ด๋ ฅ์๊ฐ ์ผ๋ง๋ ๋ฐฉ๋ฌธ๋์๋์ง ๋ฐ์ดํฐ๋ฅผ ์๊ณ ์ถ์ง ์์๋์?
๐ ๊ตฌ๊ธ์์ ๋ด ์ด๋ ฅ์๊ฐ ๊ฒ์๋๋๋ก ๋ง๋ค๊ณ ์ถ์ง ์์๋์?
์ ๋ ์์ ๊ฐ์ ์ด์ ๋ก Next.js
๋ฅผ ์ฌ์ฉํ ์ ์ ์น ํฌํธํด๋ฆฌ์ค๋ฅผ ๋ง๋ค๊ธฐ๋ก ๊ฒฐ์ฌํ์ด์.
๊ทธ๋ฌ๋ค ๋ฌธ๋, ๋ค๋ฅธ ์ฌ๋๋ ๋์ ๋๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฐ๊ณ ์์ ๊ฑฐ๋ผ๋ ์๊ฐ์ด ๋ค์์ต๋๋ค.
๊ทธ๋์ ์ ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ์ฌ๋๋ ์ฌ์ฉํ ์ ์๋๋ก ํฌํธํด๋ฆฌ์ค ํ
ํ๋ฆฟ์ ๋ง๋ค๊ฒ ๋์๋ต๋๋ค ๐ค
์ ํฌํธํด๋ฆฌ์ค๋ very simple portfolio
๋ฅผ ์ฌ์ฉํด์ ์ ์ํ์ด์. ๐๐ ๋ง๋ ์ด ํฌํธํด๋ฆฌ์ค ๋ณด๋ฌ๊ฐ๊ธฐ ๐๐
๐จ ์ ๋ ์ ๋๋ฉ์ด์ ๊ณผ ํ๋กํ ์ฌ์ง ๋ฑ์ ์ถ๊ฐ ์์ ์ ํด๋ ์ํ์์. ๐จ
๐จ ํ ํ๋ฆฟ์๋ ์ ๋๋ฉ์ด์ ๊ณผ ํ๋กํ ์ฌ์ง์ด ํฌํจ๋์ด์์ง ์์ต๋๋ค! ๐จ
๊ธฐ๋ณธ ๋์์ธ์ ์ด๋ฐ ๋๋์ด์์ ๐
overview.mp4
-
โ๏ธ ๊ฐ์ธ์ ์ธ ์ทจํฅ์ด์ง๋ง, ๋ผ์ดํธ๋ชจ๋๊ฐ ๊น๋ํ๋ ๊ด์ฐฎ์์. (๋คํฌ๋ชจ๋๋ ๋์์ ๋์ด ์์ต๋๋ค. ์์คํ ์ค์ ์ ๋ฐ๋ฆ ๋๋ค.)
-
๐ ์ด๋ก์ด๋กํ ์ปฌ๋ฌ๊ฐ ๋ฉ์ธ์ธ๋ฐ, ์์ ํ ์ ์์ด์! ์ํ๋ ์์ผ๋ก ์ปค์คํ ํ์ฌ ์ฌ์ฉํ์ธ์.
-
๐ฑ ๋ฐ์ํ์ผ๋ก ๊ฐ๋ฐ๋์ด ์์ต๋๋ค.
23.05.18
project
activity
education
์description
ํญ๋ชฉ์\n
์ ์ ๋ ฅํ๋ฉด ์ค๋ฐ๊ฟ์ด ๊ฐ๋ฅํด์ก์ด์.
(ex. "description": "์ค๋ฐ๊ฟ\n์ค๋ฐ๊ฟ")
์ด์ , ์ด๋ป๊ฒ ๋ง๋๋์ง ์์๋ณผ๊น์?
- Setup
- data
- resumeTitle
- information
- workExperience
- project
- activity
- education
- ๐จํ๋ ๐จ COLOR
- SEO
- Vercel ๋ฐฐํฌํ๊ธฐ
- Google Analytics
Step 1๏ธโฃ very simple portfolio
๋ฅผ ํด๋ก ํด์ฃผ์ธ์.
git clone https://github.com/sjoleee/very-simple-portfolio.git
Step 2๏ธโฃ ์๋ก์ด ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ๋ง๋ค์ด, ํด๋ก ํ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ๋ฃ์ด์ฃผ์ธ์.
Github์์ ์๋ก์ด ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์์ฑํด์ฃผ์ธ์.
โฆor push an existing repository from the command line
๋ด์ฉ์ ๋ณต์ฌํ์ฌ ํฐ๋ฏธ๋์ ๊ทธ๋๋ก ๋ถ์ฌ๋ฃ์ด์ฃผ์ธ์.
- Step๏ธ 3๏ธโฃ ์์กด์ฑ์ ์ค์นํด์ฃผ์ธ์.
yarn
or
npm install
- Step 4๏ธโฃ next ๊ฐ๋ฐ ์๋ฒ๋ฅผ ๋์ฐ๊ณ ํ์ธํ๋ฉฐ ํฌํธํด๋ฆฌ์ค๋ฅผ ๋ง๋์ธ์.
yarn dev
or
npm run dev
๊ธฐ๋ณธ์ ์ผ๋ก, ํฌํธํด๋ฆฌ์ค๋ฅผ ๊ตฌ์ฑํ๋ ๋๋ถ๋ถ์ ๋ฐ์ดํฐ๋ ํ๋ก์ ํธ ๋ฃจํธ์ ์๋ data.json
์ ์์ฑ๋ฉ๋๋ค.
์์๋ฅผ ํจ๊ป ์ดํด๋ณด๋๋ก ํ์ฃ ! (์๋ ์์์ ๋น ํ
ํ๋ฆฟ์ธ data.templete.json
๊ฐ ๋ฃจํธ์ ์์ฑ๋์ด ์์ผ๋ ์ฐธ๊ณ ํ์ธ์!)
{
// ํฌํธํด๋ฆฌ์ค ์ต์๋จ์ ์ ๋ชฉ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
"resumeTitle": {
"title": "Hong Gil Dong"
},
// ์์ ์ ์ธ์ ์ฌํญ์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
"information": {
// ์ด๋ฆ์ ์ ์ด์ฃผ์ธ์
"name": "ํ๊ธธ๋",
// ๊ฐ์ข
๋งํฌ๋ฅผ ๊ฑธ์ด์ค ์ ์์ต๋๋ค. id ์์๋๋ก ๋์ด๋ฉ๋๋ค.
// ๊ฐ์ฅ ๋์ค์ ์ธ ๊ฒ ๊ฐ์ 3๊ฐ์ง๋ฅผ ๋ฏธ๋ฆฌ ์์ฑํด๋์ด์. ๋ ์ถ๊ฐํ๊ฑฐ๋, ์ ๊ฑฐํด๋ ๋ฉ๋๋ค.
// ๋จ, ์ด๋ฉ์ผ์ isEmail์ true๋ก ์์ฑํด์ฃผ์ธ์.
"contact": [
{ "id": 0, "name": "Email", "href": "honggildong@gmail.com", "isEmail": true }, // href์ ์ด๋ฉ์ผ์ ์ ์ด์ฃผ์ธ์.
{ "id": 1, "name": "Github", "href": "https://github.com/honggildong" }, // href์ ๊นํ๋ธ ์ฃผ์๋ฅผ ์ ์ด์ฃผ์ธ์.
{ "id": 2, "name": "Blog", "href": "https://velog.io/@honggildong" } // href์ ๋ธ๋ก๊ทธ ์ฃผ์๋ฅผ ์ ์ด์ฃผ์ธ์.
]
},
// ์ง์ฅ ๊ฒฝ๋ ฅ์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
// ๊ฐ ์ง์ฅ๋ณ ๋ฐ์ดํฐ๋ฅผ ๋ฐฐ์ด๋ก ์์ฑํด์ฃผ์๋ฉด ๋๋๋ฐ, ํฌํธํด๋ฆฌ์ค์์ ๋ฐฐ์ด ์ญ์์ผ๋ก ๋ฐฐ์น๋ฉ๋๋ค.
// ๋ฐ๋ผ์ ์ค๋๋(์์ ) ๊ฒฝ๋ ฅ์ ์์, ์ต๊ทผ ๊ฒฝ๋ ฅ์ ๋ค์ ์์ฑํด์ฃผ์ธ์.
"workExperience": [
{
"id": 0,
"name": "์ปคํผํ๋ฆฐ์ค 1ํธ์ ", // ์ง์ฅ๋ช
์ ์ ์ด์ฃผ์ธ์.
"position": "Front-end Engineer", // ๋ด๋น ์ง๋ฌด๋ฅผ ์ ์ด์ฃผ์ธ์.
"period": ["2019. 01", "2019. 09"] // ์ธ์ ๋ถํฐ ์ธ์ ๊น์ง ์ผํ์
จ๋์ง ์ ์ด์ฃผ์ธ์.
},
{
"id": 1,
"name": "์ปคํผํ๋ฆฐ์ค 2ํธ์ ",
"position": "๋ฐ๋ฆฌ์คํ",
"period": ["2022. 01", "now"] // ํ์ฌ ์ฌ์ง์ค์ด๋ผ๋ฉด, now๋ working ๋ฑ์ ์ ์ด์ฃผ์ธ์.
}
],
// ํ๋ก์ ํธ ๊ฒฝํ์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
// ์ง์ฅ ๋ฐ์ดํฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋ฐฐ์ด ์ญ์์ผ๋ก ๋ฐฐ์น๋ฉ๋๋ค.
// ์ค๋๋(์๋ ) ํ๋ก์ ํธ๋ฅผ ์์, ์ต๊ทผ ํ๋ก์ ํธ๋ฅผ ๋ค์ ์์ฑํด์ฃผ์ธ์.
// isTeam์ ๊ฐ์ ๋ฐ๋ผ์ ํ ํ๋ก์ ํธ์ ๊ฐ์ธ ํ๋ก์ ํธ ๊ฐ๊ฐ ๋๋์ด ๋ณด์ฌ์ง๋๋ค.
"project": [
{
"id": 0,
"name": "์ฒซ๋ฒ์งธ ํ ํ๋ก์ ํธ", // ํ๋ก์ ํธ๋ช
์ ์ ์ด์ฃผ์ธ์.
"description": "ํ๋ก์ ํธ์ ๋ํ ๊ฐ๋จํ ์ค๋ช
์ ์ ์ ์ ์์ต๋๋ค. ์ด๋ค ํ๋ก์ ํธ์ธ์ง ์ฃผ์ ๋ ๊ฐ์กฐํ๊ณ ์ถ์ ๋ถ๋ถ์ ์ ์ด๋ณด์ธ์.",
"webUrl": "https://github.com/sjoleee/", // ๋ฆด๋ฆฌ์ฆ๋ ํ์ด์ง๋ ์ฑ์คํ ์ด ๋ฑ ์ํ๋ ์นํ์ด์ง ๋งํฌ๊ฐ ์์ฑ๋ฉ๋๋ค. ์์ผ๋ฉด ์ ๊ฑฐ!
"repoUrl": "https://github.com/sjoleee/", // ๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ ๋งํฌ๊ฐ ์์ฑ๋ฉ๋๋ค. ์์ผ๋ฉด ์ ๊ฑฐ!
"isTeam": true, // ํ ํ๋ก์ ํธ์ ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ๊ตฌ๋ถํฉ๋๋ค. ํ ํ๋ก์ ํธ๋ผ๋ฉด true๋ก ์ ์ด์ฃผ์ธ์.
"period": ["2022. 07", "2022. 09"], // ํ๋ก์ ํธ ๊ธฐ๊ฐ์ ์ ์ด์ฃผ์ธ์.
"stack": ["์ฌ์ฉํ ๊ธฐ์ ์ ์ ์ด์ฃผ์ธ์", "React.js", "JavaScript", "styled-components", "Recoil"] // ์ฌ์ฉํ ๊ธฐ์ ์ ์ ์ด์ฃผ์ธ์.
},
{
"id": 1,
"name": "์ฒซ๋ฒ์งธ ๊ฐ์ธ ํ๋ก์ ํธ",
"description": "ํ๋ก์ ํธ์ ๋ํ ๊ฐ๋จํ ์ค๋ช
์ ์ ์ ์ ์์ต๋๋ค. ์ด๋ค ํ๋ก์ ํธ์ธ์ง ์ฃผ์ ๋ ๊ฐ์กฐํ๊ณ ์ถ์ ๋ถ๋ถ์ ์ ์ด๋ณด์ธ์.",
"webUrl": "https://github.com/sjoleee/",
"repoUrl": "https://github.com/sjoleee/",
"isTeam": false,
"period": ["2022. 10", "2022. 11"],
"stack": ["JavaScript", "HTML/CSS"]
},
],
// ๊ฐ์ข
๊ฒฝํ, ๋ํ ๋ฑ์ ํ๋์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
"activity": [
{
"id": 0,
"name": "์ฒซ๋ฒ์งธ ํ๋", // ํ๋๋ช
์ ์ ์ด์ฃผ์ธ์.
"period": ["2022. 06", "2022. 08"], // ํ๋ ๊ธฐ๊ฐ์ ์ ์ด์ฃผ์ธ์.
"description": "์ฒซ๋ฒ์งธ ํ๋์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
},
{
"id": 1,
"name": "๋๋ฒ์งธ ํ๋",
"period": ["2022. 06", "2022. 08"],
"description": "๋๋ฒ์งธ ํ๋์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
}
],
// ๋ฐ์๋ ๊ต์ก์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
// ์๋ฃํ ๋ถํธ์บ ํ, ์ ๊ณต ๋ฑ์ ์์ฑํด์ฃผ์ธ์.
"education": [
{
"id": 0,
"name": "์ฒซ๋ฒ์งธ ๊ต์ก", // ๊ต์ก๋ช
์ ์ ์ด์ฃผ์ธ์.
"period": ["2013. 02", "2020. 02"], // ๊ต์ก ๊ธฐ๊ฐ์ ์ ์ด์ฃผ์ธ์.
"description": "์ฒซ๋ฒ์งธ ๊ต์ก์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
},
{
"id": 1,
"name": "๋๋ฒ์งธ ๊ต์ก",
"period": ["2013. 02", "2020. 02"],
"description": "๋๋ฒ์งธ ๊ต์ก์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
}
],
// ์๊ฒฉ์ฆ์ ๋ํด ์์ฑํ๋ ๊ณณ์
๋๋ค.
// ๊ฐ์ข
์๊ฒฉ์ฆ์ ์์ฑํด์ฃผ์ธ์.
"certificate": [
{
"id": 0,
"name": "TOEIC 1000์ ", // ์๊ฒฉ์ฆ์ ์ด๋ฆ๊ณผ ์ ์ ํน์ ๋ฑ๊ธ์ ์ ์ด์ฃผ์ธ์.
"date": "2019. 07. 28", // ์ทจ๋ ๋ ์ง๋ฅผ ์ ์ด์ฃผ์ธ์.
"organizer": "ETS" // ์ฃผ๊ด์ฒ๋ฅผ ์ ์ด์ฃผ์ธ์.
},
{
"id": 1,
"name": "OPIC IH",
"date": "2019. 07. 28",
"organizer": "ETS"
}
]
}
์ด๋ ๊ฒ data.json
๋ฅผ ์์ฑํ์๋ฉด ๋ฉ๋๋ค.
๊ทผ๋ฐ, id
๋ ๋ญ๋๊ตฌ์?!
id๋ ๋ฐฐ์ด์์์ ์์(index) ๋ผ๊ณ ์๊ฐํ๊ณ ์์ฑํด์ฃผ์๋ฉด ๋ฉ๋๋ค.
๋ค์์ ๋์ฌ markdown
์ด๋ img
ํ์ผ๊ณผ ๊ฐ ํญ๋ชฉ์ ๋งค์นญ์์ผ์ฃผ๋ ์ฉ๋๋ก ์ฌ์ฉ๋๋, ์ง์ฐ์ง ๋ง์ธ์!!
๊ทธ๋ฐ๋ฐ data.json
์ ๋น ์ง์์ด ์์ฑํด๋ ์ฑ์์ง์ง ์๋ ์์ญ๋ค์ด ์์๊ฑฐ์์.
์๋์ชฝ์์ ๊ณ์ ์ค๋ช
ํ ๊ฒ์๐
ํฌํธํด๋ฆฌ์ค ์ต์๋จ์ ์ ๋ชฉ์ด์์.
์ฌ์ฉํ์ง ์์ผ์๋ ค๋ฉด ๋น ๋ฌธ์์ด์ ์ ๋ฌํด์ฃผ์๋ฉด ๋ฉ๋๋ค!
"resumeTitle": {
"title": "Hong Gil Dong"
}
์ธ์ ์ฌํญ์ ๋ณด์ฌ์ฃผ๋ ๋ณธ๋ฌธ ์ต์๋จ ์์ญ์ด์์.
๋จ, ์คํฌ๋ฆฐ์ท์์ ๋ณด์ด๋ ์๋
ํ์ธ์, ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ํ๊ธธ๋์
๋๋ค.
๋ฌธ๊ตฌ๋ data.json
์์ ์์ฑํ ๊ฒ์ด ์๋์์.
์ง์ ์ฝ๋๋ฅผ ์์ ํด์ผ ํฉ๋๋ค! ๊ฐ์ฅ ๋จผ์ ๋ณด์ด๋ ์ ๋ชฉ์ด๋ฏ๋ก, ๊ฐ์ธ์ด ์ํ๋ ๋๋ก ์ทจํฅ๊ป ์ปค์คํ
ํด์ฃผ์ธ์.
๊ฒฝ๋ก๋ /src/components/Information/index.tsx
์ด๋ฉฐ, 11๋ฒ ๋ผ์ธ์ ์ฃผ์์ ๋จ๊ฒจ๋์์ด์.
ํน์, ํ์ํ๋ค๋ฉด ํฌ์ง์
๋ง ์์ ํด์ ๊ทธ๋๋ก ์ฌ์ฉํ์๋ฉด ๋ฉ๋๋ค! ex) ์๋
ํ์ธ์, ๋ฐฑ์๋ ๊ฐ๋ฐ์ ํ๊ธธ๋์
๋๋ค.
"information": {
"name": "ํ๊ธธ๋",
"contact": [
{ "id": 0, "name": "Email", "href": "honggildong@gmail.com", "isEmail": true },
{ "id": 1, "name": "Github", "href": "https://github.com/honggildong" },
{ "id": 2, "name": "Blog", "href": "https://velog.io/@honggildong" }
]
}
๊ทธ๋ฐ๋ฐ, ์คํฌ๋ฆฐ์ท์ ditto
๊ฐ์ฌ๋ ์ด๋์ ์
๋ ฅ๋ ๊ฒ์ผ๊น์?๐ง
ํด๋น ์์ญ์ Markdown
์ ์ฌ์ฉํด์ ๋ณ๋์ ํ์ผ๋ก ์์ฑํฉ๋๋ค.
์๋ฌด๋๋ ๋ฌธ์์ด๋ก ์ญ~ ์ ๋ ๊ฒ ๋ณด๋จ Markdown
์ ์ฌ์ฉํ๋๊ฒ ๋์ฑ ๋ณด๊ธฐ๋ ์ข๊ณ , ์ ์ ๋ฆฌํ ์ ์๊ฒ ์ฃ ?๐ ๋
ธ์
์ฒ๋ผ์!
Markdown
์์ฑ ์์น๋ /public/markdown/information/introduce.md
์
๋๋ค.
๋
ธ์
์ ์์ฑํ๋ฏ ์์ฑํด์ฃผ์๋ฉด ๋ฉ๋๋ค!
์ง์ฅ ๊ฒฝ๋ ฅ์ ๋ณด์ฌ์ฃผ๋ ์์ญ์ด์์.
data.json์ ๋ฐฐ์ด ์ญ์์ผ๋ก ์ ๋ ฌ๋ฉ๋๋ค.
๋ฐฐ์ด์ ๋ค์ชฝ์ผ๋ก ๊ฐ์๋ก ์ต์ ๊ฒฝ๋ ฅ์ ์ถ๊ฐํ ๊ฒฝ์ฐ, ์๋ก์ด ๊ฒฝ๋ ฅ์ ์ถ๊ฐํ ๋ ์ด์ ๊ฒฝ๋ ฅ์ ์์ ํ์ง ์์๋ ๋๋ฏ๋ก ์ด๋ ๊ฒ ๊ตฌ์ฑํ์ด์.
"workExperience": [
{
"id": 0,
"name": "์ปคํผํ๋ฆฐ์ค 1ํธ์ ",
"position": "Front-end Engineer",
"period": ["2019. 01", "2019. 09"]
},
{
"id": 1,
"name": "์ปคํผํ๋ฆฐ์ค 2ํธ์ ",
"position": "๋ฐ๋ฆฌ์คํ",
"period": ["2022. 01", "now"]
}
]
๊ทธ๋ฐ๋ฐ, Foo Team, Bar Team ๋ฑ์ ๊ฒฝ๋ ฅ ์์ธ ์ฌํญ์ ์ ์ ์๊ฐ ์์ฃ ?
๊ฒฝ๋ ฅ ์์ธ ์ญ์ Markdown
์ ์ฌ์ฉํด์ ์์ฑํฉ๋๋ค.
์๋ฌด๋๋ ๋ฌธ์์ด๋ก ์ญ~ ์ ๋ ๊ฒ ๋ณด๋จ Markdown
์ ์ฌ์ฉํ๋๊ฒ ๋์ฑ ๋ณด๊ธฐ๋ ์ข๊ณ , ์ ์ ๋ฆฌํ ์ ์๊ฒ ์ฃ ?๐
Markdown
์์ฑ ์์น๋ /public/markdown/workExperience/[id].md
์
๋๋ค.
data.json
์ ๊ธฐ์
ํ id์ ํ์ผ๋ช
์ ๋งค์นญ์์ผ์ฃผ์ธ์. ๐ค
ํ๋ ๋, ์ด๋ก์ ๋ค๋ชจ ์๋ฆฌ์ ์ด๋ฏธ์ง๋ฅผ ๋ฃ์ ์ ์์ด์!
png ํ์ผ์ /public/images/workExperience/[id].png
๊ฒฝ๋ก์ ์ ์ฅํด์ฃผ์ธ์.
(์ ํ ์ฌํญ์
๋๋ค. ์ด๋ฏธ์ง ํ์ผ ์์ด ํ
์คํธ๋ก๋ง ์ฌ์ฉํ ์๋ ์์ด์.)
์ด๋ฏธ์ง๋ png
ํ์๋ง ๊ฐ๋ฅํ๋ฉฐ, 120px ์ด์์ ์ ๋ฐฉํ ์ด๋ฏธ์ง
๋ฅผ ๊ถ์ฅํฉ๋๋ค!
์ง๊ธ๊น์ง ์งํํ๋ ํ๋ก์ ํธ๋ฅผ ๋ณด์ฌ์ค ์ ์๋ ์์ญ์ด์์.
๊ฐ๋ตํ ์ค๋ช
์ ์ ๋ description
์ \n
์ผ๋ก ์ค๋ฐ๊ฟ์ด ๊ฐ๋ฅํฉ๋๋ค.
data.json
์ project
์ ์์ฑํ์ค๋, isTeam: boolean
์ ๊ธฐ์
ํจ์ผ๋ก์จ ํ ํ๋ก์ ํธ์ ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ๋๋ ์ ๋ณด์ฌ์ฃผ๊ฒ ๊ตฌ์ฑํ์ด์.
isTeam: true
์ธ ํญ๋ชฉ๋ผ๋ฆฌ ํ ํ๋ก์ ํธ์ ๋ฐฐ์ด ์ญ์์ผ๋ก ๋ณด์ฌ์ง๊ณ , isTeam: false
์ธ ํญ๋ชฉ๋ผ๋ฆฌ ๊ฐ์ธ ํ๋ก์ ํธ์ ๋ฐฐ์ด ์ญ์์ผ๋ก ๋ณด์ฌ์ง๋๋ค.
//๊ฐ์ํ๋ ์์
"project": [
{
"name": "ํ ํ๋ก์ ํธ 1",
"description": "ํ๋ก์ ํธ์ ๋ํ ๊ฐ๋จํ ์ค๋ช
์ ์ ์ ์ ์์ต๋๋ค.\n ์ด๋ค ํ๋ก์ ํธ์ธ์ง ์ฃผ์ ๋ ๊ฐ์กฐํ๊ณ ์ถ์ ๋ถ๋ถ์ ์ ์ด๋ณด์ธ์.",
"isTeam": true,
},
{
"name": "๊ฐ์ธ ํ๋ก์ ํธ 1",
"isTeam": false,
},
{
"name": "ํ ํ๋ก์ ํธ 2",
"isTeam": true,
},
{
"name": "๊ฐ์ธ ํ๋ก์ ํธ 2",
"isTeam": false,
},
],
์ ๊ฒฝ์ฐ, ์๋์ ๊ฐ์ด ๋ฐฐ์น๋ฉ๋๋ค.
- Team Project
- ํ ํ๋ก์ ํธ 2
- ํ ํ๋ก์ ํธ 1
- Personal Project
- ๊ฐ์ธ ํ๋ก์ ํธ 2
- ๊ฐ์ธ ํ๋ก์ ํธ 1
์ง์ฅ ๊ฒฝ๋ ฅ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, markdown
์ผ๋ก ๋ด์ฉ์ ์์ฑํ๋ฉฐ, image
๋ฅผ ์ฌ์ฉํ ์ ์์ด์.
markdown ๊ฒฝ๋ก๋ /public/markdown/project/[id].md
image ๊ฒฝ๋ก๋ /public/images/project/[id].md
์
๋๋ค.
๋ํ, ์์, ํด์ปคํค ๋ฑ ๊ฐ์ข
๊ฒฝํ์ ์์ฑํ๋ ๊ณณ์ด์์.
๊ฐ๋ตํ ์ค๋ช
์ ์ ๋ description
์ \n
์ผ๋ก ์ค๋ฐ๊ฟ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๊ธฐ๋ markdown
์ด๋ image
๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๊ตณ์ด ์ฌ๊ธฐ๊น์ง...? ๋ผ๋ ์๊ฐ์ ๊ฐ๋จํ ์ค๋ช
์ ๋๋ง ๋ฌธ์์ด๋ก ์ถ๋ ฅํ๊ฒ ํด๋์๋๋ฐ, ํ์ํ๋ค๋ฉด markdown
๋ฐ image
๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ์
๋ฐ์ดํธํด๋ณผ๊ฒ์!
"activity": [
{
"id": 0,
"name": "์ฒซ๋ฒ์งธ ํ๋",
"period": ["2022. 06", "2022. 08"],
"description": "์ฒซ๋ฒ์งธ ํ๋์ ๋ํ\n ๊ฐ๋ตํ ์ค๋ช
"
},
{
"id": 1,
"name": "๋๋ฒ์งธ ํ๋",
"period": ["2022. 06", "2022. 08"],
"description": "๋๋ฒ์งธ ํ๋์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
}
],
์ ๊ณต, ๋ถํธ์บ ํ, ๊ฐ์ข
๊ต์ก์ ๋ํด ์ ์ด์ฃผ์ธ์.
๊ฐ๋ตํ ์ค๋ช
์ ์ ๋ description
์ \n
์ผ๋ก ์ค๋ฐ๊ฟ์ด ๊ฐ๋ฅํฉ๋๋ค.
์์ activity์ ๋์ผํ ๊ตฌ์ฑ์ด๋ผ ๋์ด๊ฐ๋๋ค~ ํ๋ฆฌ๋ฆญ~ ๐
๋์ถฉ ๋์ด์์ ์์ธํ ์ค๋ช ์ ์๋ตํ๋ค ์งค
"education": [
{
"id": 0,
"name": "์ฒซ๋ฒ์งธ ๊ต์ก",
"period": ["2013. 02", "2020. 02"],
"description": "์ฒซ๋ฒ์งธ ๊ต์ก์\n ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
},
{
"id": 1,
"name": "๋๋ฒ์งธ ๊ต์ก",
"period": ["2013. 02", "2020. 02"],
"description": "๋๋ฒ์งธ ๊ต์ก์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
"
}
],
๊ฐ์ข
์๊ฒฉ ์ฆ๋ช
์ ๋ํด ์ ์ด์ฃผ์ธ์. ์๊ฒฉ ์ํ์ ์ฃผ๊ด์ฒ๋ ์
๋ ฅํด์ฃผ์ธ์.
์ฌ๊ธฐ๋ ์์ ๊ฑฐ์ ๋์ผํ ๊ตฌ์ฑ์ด๋ผ... ํํซ... ๐
"certificate": [
{
"id": 0,
"name": "TOEIC 1000์ ",
"date": "2019. 07. 28",
"organizer": "ETS" // ์ฃผ๊ด์ฒ๋ฅผ ์ ์ด์ฃผ์ธ์.
},
{
"id": 1,
"name": "OPIC IH",
"date": "2019. 07. 28",
"organizer": "ETS"
}
]
๐จ ๋ฐ๋์ ์ปฌ๋ฌ๋ฅผ ๋ณ๊ฒฝํด์ฃผ์ธ์ ๐จ
์ฌ๋ฌ ์ฌ๋์ด ๋๋ฌด๋๋ ๋๊ฐ์ ๋์์ธ์ ํฌํธํด๋ฆฌ์ค๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ๊ทธ๊ฒ๋ ๋ฌธ์ ๊ฒ ์ฃ ?๐
tailwind
์ theme
๋ฅผ ์ฌ์ฉํ์ฌ ํธํ๊ฒ ์ปฌ๋ฌ๋ฅผ ์ปค์คํ
ํ ์ ์๋๋ก ํด๋์์ผ๋ ๊ผญ ๋ณ๊ฒฝํด์ ์ฌ์ฉํด์ฃผ์ธ์!
ํ๋ก์ ํธ ๋ฃจํธ ๊ฒฝ๋ก์ /tailwind.config.js
๋ฅผ ์์ ํด์ฃผ์ธ์.
๊ฒ์ , ํฐ์ ๊ณํต์ ๋ชจ๋
ธํค์ ํฐํธ ์ปฌ๋ฌ, ๊ฐ๋ก์ , ๋ฐฐ๊ฒฝ์ ๋ฑ์ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค. ๊ตณ์ด ๋ณ๊ฒฝํ์ง ์์๋ ๊ด์ฐฎ์์.
PRIMARY_LIGHT
PRIMARY
PRIMARY_HEAVY
GRADIENT_FROM
GRADIENT_TO
5๊ฐ์ง ์๋ง ๋ณ๊ฒฝํด์ฃผ์ธ์!
...
theme: {
extend: {
// NOTE: ๋ณธ ํ
ํ๋ฆฟ์ ๋๋ถ๋ถ์ด ๋ชจ๋
ธํค์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. primary ์ปฌ๋ฌ๋ง ์์ ํ์ฌ ์ฌ์ฉํ์๋ ๊ฒ์ ๊ถ์ฅ๋๋ฆฝ๋๋ค.
colors: {
GRAY_LIGHT: "#f1f3f5",
GRAY: "#adb5bd",
GRAY_HEAVY: "#868e96",
GRAY_EXTRAHEAVY: "#495057",
BLACK: "#212529",
/**
* @description selection(๋๋๊ทธ ๋ธ๋ก)์ ์ฌ์ฉ๋๋ ์ปฌ๋ฌ์
๋๋ค.
*/
PRIMARY_LIGHT: "#c3fae8",
/**
* @description ์๊ธฐ์๊ฐ์ ์ด๋ฆ ๋ถ๋ถ, code tag์ darkmode์ ์ฌ์ฉ๋๋ ์ปฌ๋ฌ์
๋๋ค.
*/
PRIMARY: "#12b886",
/**
* @description code tag, link hover icon์ ์ฌ์ฉ๋๋ ์ปฌ๋ฌ์
๋๋ค.
*/
PRIMARY_HEAVY: "#087f5b",
/**
* @description ํ์ด์ง ์ต์๋จ gradient์ ์์ ์ปฌ๋ฌ์
๋๋ค.
*/
GRADIENT_FROM: "#51cf66",
/**
* @description ํ์ด์ง ์ต์๋จ gradient์ ์ข
๋ฃ ์ปฌ๋ฌ์
๋๋ค.
*/
GRADIENT_TO: "#0c8599",
},
},
},
๋๋ ์ด๋ค ์ ์กฐํฉ์ด ์ข์์ง ๋ชจ๋ฅด๊ฒ ๋ค! ๊ณ ๋ฏผ์ด์ ๋ถ๋ค์ ๋ง์์ ๋๋ ๋ฉ์ธ ์ปฌ๋ฌ ํ๋๋ง ์ ํ์ ํ, ์ด๋๋น ์ปฌ๋ฌ ์์ ์ ์ฌ
์์
์ผ๋ก ์ด์ธ๋ฆฌ๋ ์์ ์ฐพ์๋ณด์
๋ ์ข์ ๊ฒ ๊ฐ์์๐
ํน์, ์ด๋๋น ์ปฌ๋ฌ์ ํ์ ํญ์์ ์ธ์ฌ์ดํธ๋ฅผ ์ป์ด๋ณด์
๋ ์ข๊ฒ ์ต๋๋ค.๐
์ด์ SEO๋ฅผ ํฅ์์์ผ ๋ณผ๊น์?
very simple portfolio
๋ ํธํ SEO ์ค์ ์ ์ํด next-seo
๋ฅผ ์ค์นํด๋์์ด์.
/src/pages/_app.tsx
๊ฒฝ๋ก์ DEFAULT_SEO
๋ง ์์ ํด์ฃผ์๋ฉด ๋ฉ๋๋ค!
๊ฐ ์ต์
์ ๋ํ ์ ๋ณด๋ next-seo ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์!
/**
* @description SEO๋ฅผ ์ํด ๋ณธ์ธ์ ์ ๋ณด๋ก ์์ ํด์ฃผ์ธ์.
*/
const DEFAULT_SEO = {
title: "ํ๊ธธ๋ | Front-End Dev",
description: "์๋
ํ์ธ์, ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ํ๊ธธ๋์
๋๋ค.",
canonical: "https://www.naver.com/",
openGraph: {
type: "website",
locale: "ko_KR",
url: "https://www.naver.com/",
title: "ํ๊ธธ๋ | Front-End Dev",
site_name: "ํ๊ธธ๋ | Front-End Dev",
images: [
{
url: "/share.png", // ์นด์นด์คํก์ ๋น๋กฏํ ๊ณต์ ์ฉ ์ด๋ฏธ์ง ๊ฒฝ๋ก public/share.png์ ์ํ๋ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํด์ฃผ์ธ์.
width: 285,
height: 167,
alt: "ํ๊ธธ๋ | Front-End Dev",
},
],
},
additionalLinkTags: [
{
rel: "icon",
href: "/favicon.ico",
},
],
additionalMetaTags: [
{
name: "application-name",
content: "ํ๊ธธ๋ | Front-End Dev",
},
{
name: "msapplication-tooltip",
content: "ํ๊ธธ๋ | Front-End Dev",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1",
},
],
};
์์ง๋ง๊ณ favicon๋ ์ค์ ํด์ฃผ์ธ์! (ํญ์ ์กฐ๊ทธ๋งํ ์์ด์ฝ)
/public/favicon.ico
๊ฒฝ๋ก์ ico ํ์ผ์ ์ ์ฅํด์ฃผ์ธ์.
์ํ๋ ์ด๋ฏธ์ง๋ฅผ favicon์ผ๋ก ๋ณํํด์ฃผ๋ realfavicongenerator๋ฅผ ์ฌ์ฉํด๋ณด์
๋ ์ข์ ๊ฒ ๊ฐ์์.
Vercel์ ํด๋ฆญ ๋ช ๋ฒ์ผ๋ก ์์ฃผ์์ฃผ ํธํ๊ฒ ํ๋ก์ ํธ๋ฅผ ๋ฐฐํฌํ ์ ์๋ ๋ฐฐํฌ, ํธ์คํ
์๋น์ค์์.
https://vercel.com/new ์์ github์ผ๋ก ๋ก๊ทธ์ธํ์ ํ, ํฌํธํด๋ฆฌ์ค ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ ํํ์ฌ ๋ฐฐํฌํด์ฃผ์๋ฉด ๋ฉ๋๋ค!
๋๋ฌด ํธํ๋ค...!
ํฌํธํด๋ฆฌ์ค์ ๋ฐฉ๋ฌธ์๊ฐ ๋ช๋ช
์ธ์ง ๊ถ๊ธํ์ง ์์ผ์
จ๋์?๐ต๏ธโโ๏ธ
๊ฐ๋จํ GA ์ค์ ๋ง์ผ๋ก ๋ฐ์ดํฐ ์์ง์ด ๊ฐ๋ฅํฉ๋๋ค!
Step 1๏ธโฃ Google Analytics์ ๊ฐ์ ํด์ฃผ์ธ์.
https://analytics.google.com/ ์ ๋ฐฉ๋ฌธํ์ฌ ๊ฐ์
์ ์งํํด์ฃผ์ธ์.
๊ฐ๋จํ ์ ๋ณด๋ฅผ ์
๋ ฅํ๊ณ , ํ๋ซํผ์ ์น์ผ๋ก ์ ํํด์ฃผ์๋ฉด ์๋์ ๊ฐ์ ํ๋ฉด์ด ๋์ต๋๋ค.
์ฌ๊ธฐ์ Vercel๋ก ๋ฐฐํฌํ ์ฐ๋ฆฌ ํฌํธํด๋ฆฌ์ค์ url์ ์์ฑํด์ค๋๋ค.
๊ทธ๋ผ ์๋์ ๊ฐ์ด G-
๋ก ์์ํ๋ ์ธก์ ID ๋ฅผ ์ ๊ณตํด์ค๊ฑฐ์์.
- Step 2๏ธโฃ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
ํ๋ก์ ํธ ๋ฃจํธ ๊ฒฝ๋ก์ /.env
ํ์ผ์ ๋ง๋ค๊ณ ์๋์ ๊ฐ์ด ์์ฑํด์ฃผ์ธ์.
์ธก์ ID๋ฅผ ํ๊ฒฝ๋ณ์๋ก ์ฌ์ฉํ๊ณ , ์ธ๋ถ๋ก ๋
ธ์ถ๋์ง ์๋๋ก ํฉ๋๋ค. (gitignore๋ ์ด๋ฏธ ์์ฑํด๋์์ด์!)
NEXT_PUBLIC_GOOGLE_ANALYTICS = 'G-0000000000' // ์๊น ๋ฐ์ ์ธก์ ID๋ฅผ ์
๋ ฅํด์ฃผ์ธ์.
์ด์ , /src/lib/gtag.ts
ํด๋์ ํ์ผ์ ์์ฑํ๊ณ ์๋์ ๊ฐ์ด ์์ฑํด์ฃผ์ธ์.
GA์์ ์ ๊ณตํ๋ ํ๊ทธ์
๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ํ์ด์ง๊ฐ ๋ณด์ฌ์ง๋ฉด ์ง๊ณ๋ ์ ์๋๋ก ํ๋ pageview
ํจ์๊ฐ ์์ฑ๋์ด ์์ต๋๋ค.
์๋ง ์๋ฌ๊ฐ ๋ฐ์ํ ํ
๋ฐ, ๊ณ์ํด์ ์งํํ์๋ฉด ํด๊ฒฐ๋ฉ๋๋ค!
const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS;
export const pageview = (url: URL) => {
window.gtag("config", GA_TRACKING_ID, {
page_path: url,
});
};
interface GTagEvent {
action: string;
category?: string;
label?: string;
value?: string;
}
export const event = ({ action, category, label, value }: GTagEvent) => {
window.gtag("event", action, {
event_category: category,
event_label: label,
value: value,
});
};
๋ฃจํธ ๊ฒฝ๋ก์ /environment.d.ts
ํ์ผ์ ๋ง๋ค๊ณ ์๋์ ๊ฐ์ด ์์ฑํด์ฃผ์ธ์.
namespace NodeJS {
interface ProcessEnv extends NodeJS.ProcessEnv {
NEXT_PUBLIC_GOOGLE_ANALYTICS: string;
}
}
ํ์ ์คํฌ๋ฆฝํธ ํ๊ฒฝ์ด๋ฏ๋ก gtag์ ํ์ ์ ์ค์นํด์ค๋๋ค. > ์ ๊ฐ ์ด๋ฏธ ์ค์นํด๋์์ด์ ๐
yarn add -D @types/gtag.js
or
npm install @types/gtag.js --dev
/src/pages/_app.tsx
์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํฉ๋๋ค.
import * as gtag from "../lib/gtag";
const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS;
const App = ({ Component, pageProps }: AppProps) => {
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url: URL) => {
gtag.pageview(url);
};
router.events.on("routeChangeComplete", handleRouteChange);
router.events.on("hashChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
router.events.off("hashChangeComplete", handleRouteChange);
};
}, [router.events]);
return (
<>
{/* Global Site Tag (gtag.js) - Google Analytics */}
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
/>
<Script
id="gtag-init"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`,
}}
/>
<DefaultSeo {...DEFAULT_SEO} />
... ํ๋ต
- Step 3๏ธโฃ Vercel์์ ํ๊ฒฝ๋ณ์๋ฅผ ๋ฑ๋กํด์ฃผ์ธ์.
์๊น .env
๋ก ํ๊ฒฝ๋ณ์๋ฅผ ๋ฑ๋กํ์ง๋ง, vercel์ ๋ฐ๋ก ๋ฑ๋กํด์ฃผ์ด์ผํด์. (.env๋ gitignore๋ก ์ธํด ๊น์ ํฌํจ๋์ง ์์์)
vercel์์ ํฌํธํด๋ฆฌ์ค ํ๋ก์ ํธ์ ์ค์ ์ผ๋ก ๋ค์ด๊ฐ ๋ค์, ์๋ ์ฌ์ง์ฒ๋ผ ํ๊ฒฝ๋ณ์๋ฅผ ๋ฑ๋กํด์ฃผ์ธ์.
- Step 4๏ธโฃ GA ๋ฐ์ดํฐ ์์ง์ ๊ธฐ๋ค๋ ค์ฃผ์ธ์.
GA๊ฐ ์ด์ฌํ ๋ฐ์ดํฐ๋ฅผ ์์งํ์ฌ ๋ฉฐ์น ๋ด๋ก ๋ฐ์ดํฐ ์กฐํ๊ฐ ๊ฐ๋ฅํด์ง๊ฑฐ์์.
https://analytics.google.com/ ์์ ํ์ด์ง ๋ฐฉ๋ฌธ๊ณผ ์ค์๊ฐ ๋ฐฉ๋ฌธ์๋ฅผ ๋ณผ ์ ์๊ฒ ๋ ๊ฑฐ์์!
๊ทธ๋ฆฌ๊ณ , ๊ตฌ๊ธ์ ํฌํธํด๋ฆฌ์ค๊ฐ ๊ฒ์๋ ์ ์๋๋ก ๊ตฌ๊ธ ์์น์ฝ์์ URL ์์ธ ์์ฑ์ ์์ฒญํ์ธ์!
์ถํํฉ๋๋ค! ํฌํธํด๋ฆฌ์ค๋ฅผ ๋ง๋์ จ๊ตฐ์! ๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐
๋ฒ๊ทธ๋ ๊ฐ์ ๋ฑ์ ์๊ฒฌ์ ์ธ์ ๋ ํ์์ ๋๋ค! ๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐๐