-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
124 lines (76 loc) ยท 232 KB
/
index.html
File metadata and controls
124 lines (76 loc) ยท 232 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<!DOCTYPE html><html><head><meta charSet="utf-8" class="next-head"/><title class="next-head">Dev.log</title><meta name="description" content="salgum1114 Dev.log" class="next-head"/><meta name="keywords" content="salgum1114,blog,react,antd,webpack,css,javascript" class="next-head"/><meta property="og:title" content="Dev.log" class="next-head"/><meta property="og:description" content="salgum1114 Dev.log" class="next-head"/><meta property="og:type" content="website" class="next-head"/><meta property="og:site_name" content="Dev.log" class="next-head"/><meta property="og:locale" content="ko_KR" class="next-head"/><meta property="og:url" content="https://salgum1114.github.io" class="next-head"/><meta property="og:image" content="https://salgum1114.github.io/static/images/authors/salgum1114.png" class="next-head"/><meta name="twitter:title" content="Dev.log" class="next-head"/><meta name="twitter:image" content="https://salgum1114.github.io/static/images/authors/salgum1114.png" class="next-head"/><link rel="preload" href="/_next/static/WBzuTPjOfilMhrb159LWu/pages/index.js" as="script"/><link rel="preload" href="/_next/static/WBzuTPjOfilMhrb159LWu/pages/_app.js" as="script"/><link rel="preload" href="/_next/static/WBzuTPjOfilMhrb159LWu/pages/_error.js" as="script"/><link rel="preload" href="/_next/static/runtime/webpack-484a8928da4ec3492fcd.js" as="script"/><link rel="preload" href="/_next/static/chunks/commons.14799f0a166b7233d4ca.js" as="script"/><link rel="preload" href="/_next/static/chunks/styles.a8a2d4bb615b8dc9d9ef.js" as="script"/><link rel="preload" href="/_next/static/runtime/main-0463b6c82337fbcda1e9.js" as="script"/><link rel="stylesheet" href="/_next/static/css/commons.8ba03f37.chunk.css"/><link rel="stylesheet" href="/_next/static/css/styles.2d00b941.chunk.css"/><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no"/><meta name="google-site-verification" content="YCCU8qpDKf7ka8WDDPA6rt1y0m9egFSi7zeHgmayb6Y"/><meta name="description" content="salgum1114 Dev.log"/><meta name="keywords" content="salgum1114,blog,react,antd,webpack,css,javascript"/><meta property="og:title" content="Dev.log"/><meta property="og:description" content="salgum1114 Dev.log"/><meta property="og:type" content="website"/><meta property="og:site_name" content="Dev.log"/><meta property="og:locale" content="ko_KR"/><meta property="og:url" content="https://salgum1114.github.io"/><meta property="og:image" content="https://salgum1114.github.io/static/images/authors/salgum1114.png"/><meta name="twitter:title" content="Dev.log"/><meta name="twitter:image" content="https://salgum1114.github.io/static/images/authors/salgum1114.png"/><link rel="manifest" href="/static/manifest.json"/><link rel="icon" type="image/png" sizes="192x192" href="/static/images/favicon/icon-192x192.png"/><link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/static/images/favicon/favicon-96x96.png"/><link rel="shortcut icon" href="/static/favicon.ico"/><link rel="stylesheet" href="https://fonts.googleapis.com/earlyaccess/notosanskr.css"/><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css"/><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/railscasts.min.css"/><script async="" src="https://www.googletagmanager.com/gtag/js?id=UA-97485289-2"></script><script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-97485289-2');
</script><script async="" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script></head><body><div id="__next"><section class="ant-layout" style="height:100%"><header class="ant-layout-header" style="background-color:#fff;padding:0;box-shadow:0px 0px 10px -2px rgba(0, 0, 0, 0.75);z-index:1000;position:fixed;width:100%"><div style="display:flex;align-items:center;height:100%"><div style="display:flex;justify-content:flex-start;margin-left:16px;cursor:pointer"><i aria-label="icon: bars" style="font-size:1.25rem" tabindex="-1" class="anticon anticon-bars"><svg viewBox="0 0 1024 1024" class="" data-icon="bars" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M912 192H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM104 228a56 56 0 1 0 112 0 56 56 0 1 0-112 0zm0 284a56 56 0 1 0 112 0 56 56 0 1 0-112 0zm0 284a56 56 0 1 0 112 0 56 56 0 1 0-112 0z"></path></svg></i></div><div style="display:flex;justify-content:center;flex:1;color:#000;font-weight:500;overflow:hidden"><h2 class="container-title"></h2><a href="https://github.com/salgum1114" target="_blank"><i aria-label="icon: github" style="font-size:1.25rem" class="anticon anticon-github"><svg viewBox="64 64 896 896" class="" data-icon="github" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9a127.5 127.5 0 0 1 38.1 91v112.5c.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z"></path></svg></i></a></div><div style="display:flex;justify-content:flex-end;align-items:center;margin-right:16px"><i aria-label="icon: search" style="font-size:1.25rem" tabindex="-1" class="anticon anticon-search"><svg viewBox="64 64 896 896" class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0 0 11.6 0l43.6-43.5a8.2 8.2 0 0 0 0-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></i></div></div></header><main class="ant-layout-content" style="margin-top:64px;overflow:auto"><div class="container"><div class=""><div class="blog-masonry-sizer"></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/reactjs/2019-11-28-react-class-equivalents/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/react.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">React Class vs React Hooks Lifecycle ๋น๊ต ์ ๋ฆฌ</h2></div><div class="ant-card-meta-description">4์๊ฐ ํ</div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">React Class์์ ์ฌ์ฉํ๋ Lifecycle๊ณผ React Hooks์์ ์ฌ์ฉํ๋ Lifecycle์ ์ฐจ์ด์ ์ ๋น๊ต ์ ๋ฆฌํ๋ค.
COMPONENTDIDMOUNT
// Class
class Example extends React.Component {
componentDidMount() {
...
}
}
// Hook
con...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/etc/2019-11-14-letsencrypt-public-ca/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/letsencrypt.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Letsencrypt๋ก ๊ณต์ธ CA ์ ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">14์ผ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">1. LETSENCRYPT ํด๋ผ์ด์ธํธ ๋ค์ด๋ฐ๊ธฐ
๋ค์ด๋ก๋ ๋ฐ๊ณ ์ํ๋ ๊ฒฝ๋ก์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
git clone https://github.com/letsencrypt/letsencrypt
2. ์์กด์ฑ ๋ค์ด๋ก๋ ๋ฐ๊ธฐ
๋ค์ด๋ก๋ ๋ฐ์ ํ letsencrypt ๋๋ ํ ๋ฆฌ์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.
./letsencrypt-auto --help
3...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/reactjs/2019-10-30-react-hot-loader-patch-warning/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/react.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">React Hot Loader Patch Warning ํด๊ฒฐ ๋ฐฉ๋ฒ</h2></div><div class="ant-card-meta-description">ํ ๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ต๊ทผ React ๋ฒ์ ์ ์ต์ ์ผ๋ก ์ฌ๋ฆฌ๋ฉด์ ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ์ฝ์์์ ๋ถํ์ํ React Hot Loader Warning ๋ก๊ทธ๊ฐ ์ฐํ๋ค.
๋์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ๋ค์ํ ์ฌ๋๋ค์ด React Hot Loader ์ด์์ ์ฌ๋ ธ๊ณ , ๋๋ ๊ทธ ์ด์์ ๋ต๋ณ๋ค์ ๋ณด๊ณ ํด๊ฒฐ์ ๋์ฐ๋ค.
React-Hot-Loader: react-๐ฅ-dom patch is not d...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/etc/2019-10-22-react-design-editor-1/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/react-design-editor.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">[React Design Editor] ์ฐจํธ ์ถ๊ฐ</h2></div><div class="ant-card-meta-description">ํ ๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ด๋ฒ์ React Design Editor ํ๋ก์ ํธ์ ์ฐจํธ๋ฅผ ์ถ๊ฐํ ์ ์๋๋ก ์
๋ฐ์ดํธ ํ๋ค.
์ฐจํธ๋ Canvas๋ก ๊ฐ๋ฐ๋ Baidu์ Echarts๋ฅผ ์ฌ์ฉํ์๋ค.
์ต์ด๋ Chart.js๋ฅผ ์ฌ์ฉํ์ฌ Canvas์ Context๋ก ์ฐจํธ๋ฅผ Fabric.js ๋ด๋ก ์ง์ ๋ ๋๋ง ํ๋ ค ํ์ผ๋ Chart.js์
๋ ์ด์์ ๊ธฐ๋ฅ ์ ์ฝ์ ๋งํ Echarts๋ฅผ ์ ํํ๊ฒ ...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/nextjs/2019-05-28-nextjs-static-website-5/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/nextjs.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">6๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ด๋ฒ์๋ ํ๋ก์ ํธ์ Material UI๋ฅผ ์ ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด ๋ณด๊ณ ๋ช๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด๋ณด๋ ค๊ณ ํ๋ค.
๋จผ์ Metarial UI๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด npm package๋ฅผ ๋ฐ๋๋ค.
npm install --save @material-ui/core @material-ui/icons @material-ui/styles
Next...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/nextjs/2019-05-24-nextjs-static-website-4/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/nextjs.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">6๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ง๋ ๊ธ์์ index.js์ post.js๋ฅผ ์์ฑํ์๊ณ Routing์ ์ฌ์ฉํ์ง ์๊ณ URL๋ก ์ง์ ์ ๊ทผํด์ ํ๋ฉด์ ํ์ธํ์๋ค. ์ด๋ฒ ๊ธ์์๋
Next.js์ Routing์ ์ฌ์ฉํ์ฌ ํ์ด์ง ์ ํ์ ํด๋ณด๋ ค๊ณ ํ๋ค.
> Next.js github์ Routing์ ๋ํ ์ค๋ช
์ด ์ ๋์์๋ค.
Next.js์์ Route๋ pages๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก์ ์์ฑํ...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/nextjs/2019-05-21-nextjs-static-website-3/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/nextjs.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์</h2></div><div class="ant-card-meta-description">6๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ด์ ๊ธ์์ ํ๋ก์ ํธ ๊ตฌ์ฑ์ ํ์ฌ ๊ฐ๋จํ ํ๋ฉด์ ํ์ธํ์๋ค.
์ด๋ฒ์๋ Next.js์ ๋ด์ฅ๋์ด ์๋ _document.js, _app.js, _error.js๋ฅผ ์ปค์คํฐ๋ง์ด์งํ์ฌ ๋ ์ด์์์ ์๋กญ๊ฒ ๊ตฌ์ฑํ๋
๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.
> ๊ฐ๊ฐ์ ๋ํ ์ค๋ช
์ Next.js ๊ตฌ์กฐ์์ ํ์ธํ ์ ์๋ค.
_DOCUMENT.JS ํ์ผ ์์ฑ
_document.js...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/nextjs/2019-05-20-nextjs-static-website-2/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/nextjs.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ</h2></div><div class="ant-card-meta-description">6๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ฌ์ค Next.js๋ ์ค๋ช
ํ ๊ฒ ๋ณ๋ก ์๋ค. ์์ ๋ค์ด ๋๋ฌด ์๋์ด ์๊ธฐ ๋๋ฌธ์.. ๊ทธ๋ ์ง๋ง ๋ด ๋จธ๋ฆฟ์์์ ์ฌ๋ผ์ ธ๊ฐ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ก์ด๋ผ๋ ๋จ๊ธฐ๋ ค๊ณ
์์ฑํ๋ค.
1. NPM ํ๋ก์ ํธ ์์ฑ
ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด static-website ๋๋ ํ ๋ฆฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ cd static-website๋ก ๊ฐ์ npm init์ผ๋ก npm
ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์.
> ์ฐธ๊ณ ๋ก n...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/etc/2019-05-20-using-openssl-in-windows/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/openssl.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Windows์์ openssl๋ก ์ธ์ฆ์ ์์ฑํ๊ณ MQTT๋ก ํ
์คํธํ๊ธฐ</h2></div><div class="ant-card-meta-description">6๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">ํ์ฌ์์ MQTT๋ฅผ SSL/TLS๋ก ํ
์คํธํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ฒผ๋๋ฐ, ๊ธฐ์กด์ ๋์์๋ Eclipse Mosquitto๋ก ํ๋ ค๋ค๊ฐ ์ด์ ํ๋ ๊น์
Javascrpt๋ก MQTT Broker๋ Client (Pub, Sub)๋ฅผ ์ง์ ๊ตฌํํด๋ณด๊ธฐ๋ก ํ๋ค.
์ ์ฒด์ ์ผ๋ก MQTT Broker์ Client๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.
* Mosca ...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/reactjs/2019-05-11-using-typescript-without-tsx/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/react_typescript.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">React์์ .tsx ์์ด Typescript ์ฌ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ด๋ฒ ๊ธ์์๋ ๊ธฐ์กด์ .js, .jsx ํ์ฅ์๋ก ์์ฑ๋ React ์ปดํฌ๋ํธ์์ Typescript๋ฅผ ์ ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ๋ฐ์ด๋ ์ฌ์ฉ ์์ ํ์
์
ํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.
Button.js ์ปดํฌ๋ํธ๋ก ๊ฐ๋จํ ์๋ฅผ ๋ค์ด๋ณธ๋ค.
src/
components/
button/
index.js
...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/nextjs/2019-05-06-nextjs-static-website-1/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/nextjs.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">Next.js๋ ํ์ฌ ๊ฐ์ฅ ์ ๋ช
ํ React์ฉ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ํ๋ ์์ํฌ์ด๋ค.
ํ๋ ์์ํฌ๋ก์จ ์ดํดํ๊ธฐ ์ฌ์ด ๊ตฌ์กฐ์ ์๋ง์ ์์ ๋ค, ๊ทธ๋ฆฌ๊ณ ๋ค์ํ ํ๋ฌ๊ทธ์ธ๋ค์ ์ง์ํ๊ณ ์์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ์ฌ๋๋ฐ๊ณ ์๋ค.
๋ํ, Next.js๋ next export๋ผ๋ ๋ช
๋ น์ด๋ก routing ๊ฒฝ๋ก๋ก ํ์ฌ๊ธ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๊ณ ์๋ค.
> ...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/reactjs/2019-05-03-medium-zoom/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/medium-zoom.gif"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">medium-zoom ์ ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">ํ์ Medium์์ ๊ฐ๋ฐ ํฌ์คํ
์ ์ฐพ์๋ณด๋ ํธ์ธ๋ฐ, ๊ธ์์ ์ด๋ฏธ์ง๋ฅผ ํด๋ฆญํ์ ๋, ์ค์ด ๋๋ ๊ธฐ๋ฅ์ด ์ด๋ป๋ณด์ฌ์ ๋ด ๊ฐ๋ฐ ๋ธ๋ก๊ทธ์๋ ์ ์ฉํ๊ณ
์ถ์ด ๋น์ทํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ ์ฐพ์๋ณด๊ฒ ๋์๋ค.
์ฐ์ ์ด ๋ธ๋ก๊ทธ๊ฐ React๋ก ๊ฐ๋ฐํ์ผ๋ React์์ ์ฌ์ฉํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ณด๋ react-medium-image-zoom์ด
์์๋ค. ํ์ง๋ง React๋ก...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/css/2019-04-30-overscroll-behavior-contain/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/css.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">overscroll-behavior: contain ์์ฑ ์ฌ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์น์์ ์คํฌ๋กค์ ๋ค๋ฃจ๋ค๋ณด๋ฉด ํญ์ ๋ง์ฃผ์น๋ ๋ฌธ์ ์ค ํ๋๊ฐ ์คํฌ๋กค ์ฒด์ด๋์ด๋ค.
๋ค์ ์์ ๋ฅผ ๋ณด์.
See the Pen overscroll-behavior: cotain before by Sung Gyun Oh (@salgum1114) on
CodePen.์ ์์ ์์ Box-1์ ์คํฌ๋กค์ด ๋์ ๋๋ฌํ๊ฒ ๋๋ฉด ์์ ์์์ธ App์ ์คํฌ๋กค์ด ์์์ด๋๋ค.
...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/css/2019-04-28-scroll-behavior-smooth/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/css.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">scroll-behavior: smooth ์์ฑ ์ฌ์ฉํ๊ธฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">๋ธ๋ก๊ทธ์ ๋ถ๋๋ฌ์ด ์คํฌ๋กค๋ง์ ์ํด์ CSS์ scroll-behavior๋ฅผ ํ์ฉํด๋ณธ๋ค.
์ฐ์ , scroll-behavior์ด ๋ญ์ง ์์๋ณด์.
> w3school: CSS scroll-behavior Property์ ์์ฃผ ์ ๋์์๋ค.
์ฌ์ฉ ๋ฐฉ๋ฒ์ ์์ฃผ ๊ฐ๋จํ๋ค. ์๋ ์ฝ๋๋ฅผ ํ์ธํด๋ณด์.
SCROLL-BEHAVIOR: SMOOTH ์ ์ฉ ์
See...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/reactjs/2019-04-25-back-top-component/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/react.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">BackTop ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">๋ธ๋ก๊ทธ ๊ฐ๋ฐ ์ค ์คํฌ๋กค์ด ๋์์ ๋, ์์๋ก ์ด๋์ํค๋ BackTop์ ์ ์ฉํ๊ธฐ ์ํด Ant.Design์ BackTop ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ
ํ๋ค.
ํ์ง๋ง Ant.Design์ BackTop ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํด๋ณด๋ ์ ์๋๋ค. ๋ฐ๋ผ์ ์ง์ BackTop ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
> Ant.Design ํํ์ด์ง์์ ์ ๋์ํ๋ค.
๊ตฌํ ์ฝ๋๋ ...</div></div></div></div><div class="container-col blog-masonry-item col-3"><div class="ant-card ant-card-bordered ant-card-hoverable"><div class="ant-card-cover"><a style="width:100%;padding-top:56.25%;position:relative;display:block" href="/webpack/2019-04-22-uglifyjs-to-terser/"><img style="-o-object-fit:cover;object-fit:cover;display:block;border-top-left-radius:4px;border-top-right-radius:4px;position:absolute;top:0;left:0;width:100%;height:100%" alt="Post cover" src="/static/images/covers/webpack.png"/></a></div><div class="ant-card-body" style="height:12rem"><div class="ant-card-meta"><div class="ant-card-meta-avatar"><span class="ant-avatar ant-avatar-circle ant-avatar-image"><img src="/static/images/authors/salgum1114.png"/></span></div><div class="ant-card-meta-detail"><div class="ant-card-meta-title"><h2 class="ant-card-meta-title">UglifyJsPlugin const ์ค๋ฅ ํด๊ฒฐ ๋ฐฉ๋ฒ</h2></div><div class="ant-card-meta-description">7๋ฌ ์ </div></div></div><div style="overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;word-wrap:break-word;margin-top:1.5rem">์ต๊ทผ React Design Editor์ ๋น๋ ์คํจ ๊ด๋ จ ์ด์๊ฐ ์ฌ๋ผ์๋ค.
๋ด์ฉ์ธ ์ฆ์จ, production์ผ๋ก ๋น๋์ UglifyJsPlugin์์ Unexpected token: keyword ยซconstยป๋ผ๋
์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ๊ณ์ํด์ ๋น๋์ ์คํจํ๋ค๋ ๊ฒ์ด๋ค.
[Bug] Not able to create build for the applicati...</div></div></div></div></div><div style="margin:16px"><div style="max-height:250px;max-width:1200px;margin:auto"><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-8569372752842198" data-ad-slot="5204006558" data-ad-format="auto" data-full-width-responsive="true"></ins></div></div><button type="button" class="ant-btn blog-backtop ant-btn-primary ant-btn-circle"><i aria-label="icon: to-top" style="font-size:1.25rem" class="anticon anticon-to-top"><svg viewBox="64 64 896 896" class="" data-icon="to-top" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M885 780H165c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h720c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8zM400 325.7h73.9V664c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V325.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 171a8 8 0 0 0-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13z"></path></svg></i></button></div></main><div><div class="blog-dialog blog-dialog-right blog-dialog-hide" style="width:0"><div class="blog-dialog-title" style="background-color:#fff;width:100%"><div class="blog-dialog-title-extra"></div><div class="blog-dialog-title-close"><i aria-label="icon: close" tabindex="-1" class="anticon anticon-close"><svg viewBox="64 64 896 896" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></i></div></div><div class="blog-dialog-content" style="padding:0"><div class="blog-search" style="display:flex;flex-direction:column;height:100%"><div style="margin:16px"><span class="ant-input-search ant-input-affix-wrapper"><input type="text" value="" class="ant-input"/><span class="ant-input-suffix"><i aria-label="icon: search" tabindex="-1" class="anticon anticon-search ant-input-search-icon"><svg viewBox="64 64 896 896" class="" data-icon="search" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0 0 11.6 0l43.6-43.5a8.2 8.2 0 0 0 0-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path></svg></i></span></span></div><div style="margin:16px"><h4>์ต๊ทผ ๊ฒ์</h4><div style="display:flex;justify-content:center;padding:8px;color:#999999">๊ฒ์ ๊ธฐ๋ก์ด ์์ต๋๋ค</div></div><div style="margin:16px"><h4>์ต๊ทผ ๊ธฐ๋ก</h4><div style="display:flex;justify-content:center;padding:8px;color:#999999">์ฝ์ ๊ธฐ๋ก์ด ์์ต๋๋ค</div></div><div style="margin:16px;flex:1"><h4>์ ์ฒด ํ๊ทธ</h4><div style="margin:8px;cursor:pointer" class="ant-tag">react (11)</div><div style="margin:8px;cursor:pointer" class="ant-tag">react-hooks (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">letsencrypt (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">openssl (2)</div><div style="margin:8px;cursor:pointer" class="ant-tag">webpack (2)</div><div style="margin:8px;cursor:pointer" class="ant-tag">react-hot-loader (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">antd (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">fabricjs (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">react-design-editor (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">nextjs (5)</div><div style="margin:8px;cursor:pointer" class="ant-tag">website (5)</div><div style="margin:8px;cursor:pointer" class="ant-tag">typescript (2)</div><div style="margin:8px;cursor:pointer" class="ant-tag">mqtt (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">medium-zoom (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">css (2)</div><div style="margin:8px;cursor:pointer" class="ant-tag">overscroll-behavior (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">scroll-behavior (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">component (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">backtop (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">uglifyjs (1)</div><div style="margin:8px;cursor:pointer" class="ant-tag">terser-webpack-plugin (1)</div></div></div></div><div class="blog-dialog-footer" style="justify-content:center"><a href="https://github.com/salgum1114" target="_blank"><i aria-label="icon: github" style="font-size:1.25rem" class="anticon anticon-github"><svg viewBox="64 64 896 896" class="" data-icon="github" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9a127.5 127.5 0 0 1 38.1 91v112.5c.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z"></path></svg></i></a></div></div></div></section></div><script>__NEXT_DATA__ = {"props":{"pageProps":{"posts":{"/reactjs/2019-11-28-react-class-equivalents":{"path":"/reactjs/2019-11-28-react-class-equivalents","content":"\u003cp\u003eReact Class์์ ์ฌ์ฉํ๋ Lifecycle๊ณผ React Hooks์์ ์ฌ์ฉํ๋ Lifecycle์ ์ฐจ์ด์ ์ ๋น๊ต ์ ๋ฆฌํ๋ค.\u003c/p\u003e\n\u003ch2 id=\"componentdidmount\"\u003eComponentDidMount\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs jsx language-jsx\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Class\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n componentDidMount() {\n ...\n }\n}\n\n\u003cspan class=\"hljs-comment\"\u003e// Hook\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Example = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n useEffect(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n ...\n }, []);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"componentwillunmount\"\u003eComponentWillUnmount\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs jsx language-jsx\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Class\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n componentWillUnmount() {\n ...\n }\n}\n\n\u003cspan class=\"hljs-comment\"\u003e// Hook\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Example = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n useEffect(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n ...\n };\n }, []);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"componentwillreceiveprops\"\u003eComponentWillReceiveProps\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs jsx language-jsx\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Class\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n componentWillReceiveProps(nextProps) {\n ...\n }\n or\n UNSAFE_componentWillReceiveProps(nextProps) {\n ...\n }\n}\n\n\u003cspan class=\"hljs-comment\"\u003e// Hook\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Example = \u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003eprops\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { value } = props;\n useEffect(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n ...\n }, [value]);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"shouldcomponentupdate\"\u003eShouldComponentUpdate\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs jsx language-jsx\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Class\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n shouldComponentUpdate(nextProps) {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e nextProps.value !== \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props.value;\n }\n}\n\n\u003cspan class=\"hljs-comment\"\u003e// Hook\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Example = React.memo(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n ...\n}, (prevProps, nextProps) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e nextProps.value === prevProps.value;\n})\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003cstrong\u003e์ฃผ์\u003c/strong\u003e\u003c/p\u003e\n \u003cp\u003eclass ์ปดํฌ๋ํธ์ shouldComponentUpdate() ๋ฉ์๋์ ๋ฌ๋ฆฌ, areEqual ํจ์๋ props๋ค์ด ์๋ก ๊ฐ์ผ๋ฉด true๋ฅผ ๋ฐํํ๊ณ , props๋ค์ด ์๋ก ๋ค๋ฅด๋ฉด false๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๊ฒ์ shouldComponentUpdate์ ์ ๋ฐ๋์ ๋์์
๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"componentdidupdate\"\u003eComponentDidUpdate\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs jsx language-jsx\"\u003e\u003cspan class=\"hljs-comment\"\u003e// Class\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n componentDidUpdate(prevProps, prevState) {\n ...\n }\n}\n\n\u003cspan class=\"hljs-comment\"\u003e// Hook\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Example = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n useEffect(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n ...\n });\n}\n\u003c/code\u003e\u003c/pre\u003e","preview":"React Class์์ ์ฌ์ฉํ๋ Lifecycle๊ณผ React Hooks์์ ์ฌ์ฉํ๋ Lifecycle์ ์ฐจ์ด์ ์ ๋น๊ต ์ ๋ฆฌํ๋ค.\n\nCOMPONENTDIDMOUNT\n// Class\nclass Example extends React.Component {\n componentDidMount() {\n ...\n }\n}\n\n// Hook\ncon...","title":"React Class vs React Hooks Lifecycle ๋น๊ต ์ ๋ฆฌ","author":"salgum1114","date":"2019-11-28 20:30","tags":"react, react-hooks","cover":"/static/images/covers/react.png","next":"/etc/2019-11-14-letsencrypt-public-ca","prev":null},"/etc/2019-11-14-letsencrypt-public-ca":{"path":"/etc/2019-11-14-letsencrypt-public-ca","content":"\u003ch2 id=\"1letsencrypt\"\u003e1. Letsencrypt ํด๋ผ์ด์ธํธ ๋ค์ด๋ฐ๊ธฐ\u003c/h2\u003e\n\u003cp\u003e๋ค์ด๋ก๋ ๋ฐ๊ณ ์ํ๋ ๊ฒฝ๋ก์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003egit \u003cspan class=\"hljs-keyword\"\u003eclone\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003ehttps\u003c/span\u003e://github.com/letsencrypt/letsencrypt\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"2\"\u003e2. ์์กด์ฑ ๋ค์ด๋ก๋ ๋ฐ๊ธฐ\u003c/h2\u003e\n\u003cp\u003e๋ค์ด๋ก๋ ๋ฐ์ ํ \u003ccode\u003eletsencrypt\u003c/code\u003e ๋๋ ํ ๋ฆฌ์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-string\"\u003e./letsencrypt-auto\u003c/span\u003e \u003cspan class=\"hljs-params\"\u003e--help\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"3\"\u003e3. ์ธ์ฆ์ ๋ฐ๊ธ๋ฐ๊ธฐ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eletsencrypt\u003c/code\u003e ๋๋ ํ ๋ฆฌ์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e์ฃผ์: ๋ฐ๋์ 80ํฌํธ๊ฐ ๋น์ด์๋ ์ํ์์ ํด์ผํ๋ค.\u003c/em\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e./letsencrypt-auto certonly \u003cspan class=\"hljs-comment\"\u003e--standalone -n -m \u0026lt;your email\u0026gt; --agree-tos -d \u0026lt;your domain: www.example.com\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e\u0026lt;your email\u0026gt;\u003c/code\u003e์ ๋ด๋น์ ๋ฉ์ผ ์ฃผ์๋ฅผ ์์ฑํ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e\u0026lt;your domain\u0026gt;\u003c/code\u003e์ ๊ตฌ๋งคํ ๋๋ฉ์ธ ์ฃผ์๋ฅผ ์์ฑํ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/letsencrypt_create_ca.png\" alt=\"letsencrypt_create_ca\" /\u003e\u003c/p\u003e\n\u003ch2 id=\"4pempkcs12\"\u003e4. pem -\u0026gt; pkcs12 ๋ณํ\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eroot ๊ณ์ ์ผ๋ก ์ ๊ทผ \u003ccode\u003esudu su\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e๊ทธ ๋ค์ ๋ฐ๊ธ๋ ์ธ์ฆ์ ๊ฒฝ๋ก๋ก ์ด๋ํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ecd \u003cspan class=\"hljs-meta-keyword\"\u003e/etc/\u003c/span\u003eletsencrypt\u003cspan class=\"hljs-meta-keyword\"\u003e/live/\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e\u0026lt;your domain\u0026gt;\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์ ์๋ openssl ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003eopenssl pkcs12 -export -\u003cspan class=\"hljs-keyword\"\u003ein\u003c/span\u003e fullchain\u003cspan class=\"hljs-selector-class\"\u003e.pem\u003c/span\u003e -inkey privkey\u003cspan class=\"hljs-selector-class\"\u003e.pem\u003c/span\u003e -out cert_and_key\u003cspan class=\"hljs-selector-class\"\u003e.p12\u003c/span\u003e -name \u0026lt;project name\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e\u0026lt;project name\u0026gt;\u003c/code\u003e์ ํ๋ก์ ํธ ์ด๋ฆ์ ์์ฑํ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ผ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ฌผ์ด๋ณด๋๋ฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/letsencrypt_create_cert_and_key.png\" alt=\"letsencrypt_create_cert_and_key\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e๋น๋ฐ๋ฒํธ๋ ๊ธฐ์ตํ๊ณ ์์ด์ผํ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"5pkcs12jks\"\u003e5. pkcs12 -\u0026gt; jks๋ก ๋ณํ\u003c/h2\u003e\n\u003cp\u003ekeytool์ ์ด์ฉํด jks๋ฅผ ์์ฑํ๋ค. ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003ekeytool -importkeystore -srcstorepass \u0026lt;password\u0026gt; -destkeystore \u0026lt;project name\u0026gt;\u003cspan class=\"hljs-selector-class\"\u003e.jks\u003c/span\u003e -srckeystore cert_and_key\u003cspan class=\"hljs-selector-class\"\u003e.p12\u003c/span\u003e -srcstoretype PKCS12 -storepass \u0026lt;password\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e\u0026lt;project name\u0026gt;\u003c/code\u003e์ ํ๋ก์ ํธ ์ด๋ฆ์ ์์ฑํ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e\u003ccode\u003e\u0026lt;password\u0026gt;\u003c/code\u003e ์์ญ์ pem -\u003e pkcs12 ๋ณํํ์ ๋, ์
๋ ฅํ ๋น๋ฐ๋ฒํธ๋ก ๋ฐ๊พผ๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/letsencrypt_create_jks.png\" alt=\"letsencrypt_create_jks\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ์คํ๋์๊ณ ๋ค์๊ณผ ๊ฐ์ด ๋ชฉ๋ก์ด ๋ณด์ธ๋ค๋ฉด ์ ์์ ์ผ๋ก ์ธ์ฆ์ ๋ฐ๊ธ์ด ๋๋ฌ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/letsencrypt-list.png\" alt=\"letsencrypt-list\" /\u003e\u003c/p\u003e\n\u003ch2 id=\"6jks\"\u003e6. JKS ์์ฑ ๊ฒฝ๋ก\u003c/h2\u003e\n\u003cp\u003e์์ฑ๋ JKS๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๋ก์ ์์ฑ๋์ด ์๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-meta-keyword\"\u003e/etc/\u003c/span\u003eletsencrypt\u003cspan class=\"hljs-meta-keyword\"\u003e/live/\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e\u0026lt;your domain\u0026gt;\u003c/span\u003e/\u003cspan class=\"hljs-params\"\u003e\u0026lt;project name\u0026gt;\u003c/span\u003e.jks\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด ์์ฑ๋ JKS๋ฅผ ๊ฐ์ง๊ณ Java Keystore์ ๋ฑ๋กํ์ฌ ์ฌ์ฉํ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch2 id=\"7\"\u003e7. ํ๋ก์ ํธ ์ฌ๊ธฐ๋\u003c/h2\u003e\n\u003cp\u003e์์ฑ๋ JKS๋ฅผ Java Keystore์ ๋ฑ๋กํ ํ ํ๋ก์ ํธ๋ฅผ ์ฌ๊ธฐ๋ํ์ฌ ๋ธ๋ผ์ฐ์ URL ์
๋ ฅ ์ผ์ชฝ ๋ถ๋ถ์ ํ์ธํ์ฌ CA๊ฐ ์ ์ฉ๋์๋์ง ํ์ธํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e์ ์\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/letsencrypt-success.png\" alt=\"letsencrypt-success\" /\u003e\u003c/p\u003e","preview":"1. LETSENCRYPT ํด๋ผ์ด์ธํธ ๋ค์ด๋ฐ๊ธฐ\n๋ค์ด๋ก๋ ๋ฐ๊ณ ์ํ๋ ๊ฒฝ๋ก์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\n\ngit clone https://github.com/letsencrypt/letsencrypt\n\n\n2. ์์กด์ฑ ๋ค์ด๋ก๋ ๋ฐ๊ธฐ\n๋ค์ด๋ก๋ ๋ฐ์ ํ letsencrypt ๋๋ ํ ๋ฆฌ์์ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํ๋ค.\n\n./letsencrypt-auto --help\n\n\n3...","title":"Letsencrypt๋ก ๊ณต์ธ CA ์ ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-11-14 10:00","tags":"letsencrypt, openssl","cover":"/static/images/covers/letsencrypt.png","next":"/reactjs/2019-10-30-react-hot-loader-patch-warning","prev":"/reactjs/2019-11-28-react-class-equivalents"},"/reactjs/2019-10-30-react-hot-loader-patch-warning":{"path":"/reactjs/2019-10-30-react-hot-loader-patch-warning","content":"\u003cp\u003e์ต๊ทผ React ๋ฒ์ ์ ์ต์ ์ผ๋ก ์ฌ๋ฆฌ๋ฉด์ ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ์ฝ์์์ ๋ถํ์ํ React Hot Loader Warning ๋ก๊ทธ๊ฐ ์ฐํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/reactjs/react-hot-loader-patch-warning.png\" alt=\"react-hot-loader-patch-warning\" /\u003e\u003c/p\u003e\n\u003cp\u003e๋์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ๋ค์ํ ์ฌ๋๋ค์ด React Hot Loader ์ด์์ ์ฌ๋ ธ๊ณ , ๋๋ ๊ทธ ์ด์์ ๋ต๋ณ๋ค์ ๋ณด๊ณ ํด๊ฒฐ์ ๋์ฐ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/gatsbyjs/gatsby/issues/11934\"\u003eReact-Hot-Loader: react-๐ฅ-dom patch is not detected. React 16.6+ features may not work. #11934\u003c/a\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003ewarning์ด ํฐ ๋ฌธ์ ๋ ์๋๊ณ React ๋ฒ์ ์ ๋ฐ๋ฅธ React Hot Loader ๋ง์ด๊ทธ๋ ์ด์
์ด๋ผ๋์ง Webpack ์ค์ ์ ์กฐ๊ธ ๋ฐ๊ฟ ์ฃผ๋ฉด ๋๋ ๊ฒ์ด์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์ฐ์ ์๋กญ๊ฒ ์ค์นํด์ผ๋๋ Dependency๋ก \u003ccode\u003e@hot-loader/react-dom\u003c/code\u003e์ \u003ccode\u003enpm install --save-dev @hot-loader/react-dom\u003c/code\u003e๋ก ์ค์นํด์ค๋ค.\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์ Webpack Rules ์ต์
์์ ๋ค์๊ณผ ๊ฐ์ Rule์ ์ถ๊ฐํด์ค๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e{\n \u003cspan class=\"hljs-attr\"\u003etest\u003c/span\u003e: \u003cspan class=\"hljs-regexp\"\u003e/\\.(js|jsx|tsx|ts)?$/\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003einclude\u003c/span\u003e: \u003cspan class=\"hljs-regexp\"\u003e/node_modules/\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003euse\u003c/span\u003e: [\u003cspan class=\"hljs-string\"\u003e'react-hot-loader/webpack'\u003c/span\u003e],\n},\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์ ์ฌ๊ธฐ๋ ํ ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ์ฝ์์ ํ์ธํด๋ณด๋ฉด ๋ ์ด์ Warning ๋ก๊ทธ๊ฐ ์ฐํ์ง ์๋๋ค.\u003c/p\u003e","preview":"์ต๊ทผ React ๋ฒ์ ์ ์ต์ ์ผ๋ก ์ฌ๋ฆฌ๋ฉด์ ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ์ฝ์์์ ๋ถํ์ํ React Hot Loader Warning ๋ก๊ทธ๊ฐ ์ฐํ๋ค.\n\n\n\n๋์ ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฐ์ง๊ณ ๋ค์ํ ์ฌ๋๋ค์ด React Hot Loader ์ด์์ ์ฌ๋ ธ๊ณ , ๋๋ ๊ทธ ์ด์์ ๋ต๋ณ๋ค์ ๋ณด๊ณ ํด๊ฒฐ์ ๋์ฐ๋ค.\n\nReact-Hot-Loader: react-๐ฅ-dom patch is not d...","title":"React Hot Loader Patch Warning ํด๊ฒฐ ๋ฐฉ๋ฒ","author":"salgum1114","date":"2019-10-30 20:30","tags":"react, webpack, react-hot-loader","cover":"/static/images/covers/react.png","next":"/etc/2019-10-22-react-design-editor-1","prev":"/etc/2019-11-14-letsencrypt-public-ca"},"/etc/2019-10-22-react-design-editor-1":{"path":"/etc/2019-10-22-react-design-editor-1","content":"\u003cp\u003e์ด๋ฒ์ React Design Editor ํ๋ก์ ํธ์ ์ฐจํธ๋ฅผ ์ถ๊ฐํ ์ ์๋๋ก ์
๋ฐ์ดํธ ํ๋ค.\u003c/p\u003e\n\u003cp\u003e์ฐจํธ๋ Canvas๋ก ๊ฐ๋ฐ๋ Baidu์ Echarts๋ฅผ ์ฌ์ฉํ์๋ค.\u003c/p\u003e\n\u003cp\u003e์ต์ด๋ Chart.js๋ฅผ ์ฌ์ฉํ์ฌ Canvas์ Context๋ก ์ฐจํธ๋ฅผ Fabric.js ๋ด๋ก ์ง์ ๋ ๋๋ง ํ๋ ค ํ์ผ๋ Chart.js์ ๋ ์ด์์ ๊ธฐ๋ฅ ์ ์ฝ์ ๋งํ Echarts๋ฅผ ์ ํํ๊ฒ ๋๋ค.\u003c/p\u003e\n\u003cp\u003eChart.js๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๋ ๋ฐฐ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003e\u003cspan class=\"hljs-number\"\u003e1.\u003c/span\u003e Canvas์ Context๋ก ์ฐจํธ๋ฅผ ๋ ๋๋งํ๋ค.\n\u003cspan class=\"hljs-number\"\u003e2.\u003c/span\u003e \u003cspan class=\"hljs-module-access\"\u003e\u003cspan class=\"hljs-module\"\u003e\u003cspan class=\"hljs-identifier\"\u003eFabric\u003c/span\u003e.\u003c/span\u003e\u003c/span\u003ejs์ Custom Object Class์์๋ `_render`ํจ์์์ Canvas์ Context๋ฅผ ๋ค๋ฃฐ ์ ์๋ค.\n\u003cspan class=\"hljs-number\"\u003e3.\u003c/span\u003e \u003cspan class=\"hljs-module-access\"\u003e\u003cspan class=\"hljs-module\"\u003e\u003cspan class=\"hljs-identifier\"\u003eChart\u003c/span\u003e.\u003c/span\u003e\u003c/span\u003ejs์ ์ต์
์ด \u003cspan class=\"hljs-module-access\"\u003e\u003cspan class=\"hljs-module\"\u003e\u003cspan class=\"hljs-identifier\"\u003eEchart\u003c/span\u003e.\u003c/span\u003e\u003c/span\u003ejs์ ์ฌ์ฉ๋ฒ๋ณด๋ค ์ฝ๋ค.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ฒ์ ๊ฐ๋ฐ ๋จ๊ณ์์ ์์กฐ๋กญ๊ฒ Chart.js์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋, Fabric.js์ context๋ฅผ ํ์ฉํ์ฌ ์ฐจํธ๋ฅผ ๋ ๋๋งํ ์ ์์์ง๋ง, Chart.js์ ๋ ์ด์์ ์ต์
์๋ width, height๋ฅผ ๋ฐ๋ก ์ง์ ํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eChart.js์ ๋ ์ด์์ ์ต์
์๋ \u003ccode\u003eresponsive\u003c/code\u003e ๋ฐ์ํ ์ต์
๋ง ์ ๊ณต๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e๊ฒฐ๊ตญ Chart.js๋ ํฌ๊ธฐํ๊ณ ๋ค์ํ ์ฐจํธ๋ฅผ ์ง์ํ๋ Echarts๋ฅผ React Design Editor ๋ด์ ๊ตฌํ๋ Element Handler๋ฅผ ํตํด ๊ตฌํํ๊ฒ ๋์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eEcharts์ ๊ฒฝ์ฐ Canvas์ Context๋ก ์ง์ ๋ค๋ฃฐ ์ ์๋์ง์ ๋ํ ์ฌ๋ถ๋ ํ์ธ๋์ง ์์์ง๋ง, ํฅํ์ ๋ฐ๊ฒฌํ๊ฒ ๋๋ค๋ฉด ๋ณ๊ฒฝํ ์์ ์ด๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eํ์ฌ ์ฐจํธ ์ต์
์ ํต์ผ๋ก ์ค์ ํ๊ฒ ๋์ด ์๊ณ , ๋ณต์ฌ ๋ฐ ๋ถ์ฌ ๋ฃ๊ธฐ, ํฌ๊ธฐ ์กฐ์ , ๋ธ๋ผ์ฐ์ ๋ฐ์ํ์ ์ง์ํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/react-design-editor-chart.png\" alt=\"react-design-editor-chart\" /\u003e\u003c/p\u003e","preview":"์ด๋ฒ์ React Design Editor ํ๋ก์ ํธ์ ์ฐจํธ๋ฅผ ์ถ๊ฐํ ์ ์๋๋ก ์
๋ฐ์ดํธ ํ๋ค.\n\n์ฐจํธ๋ Canvas๋ก ๊ฐ๋ฐ๋ Baidu์ Echarts๋ฅผ ์ฌ์ฉํ์๋ค.\n\n์ต์ด๋ Chart.js๋ฅผ ์ฌ์ฉํ์ฌ Canvas์ Context๋ก ์ฐจํธ๋ฅผ Fabric.js ๋ด๋ก ์ง์ ๋ ๋๋ง ํ๋ ค ํ์ผ๋ Chart.js์\n๋ ์ด์์ ๊ธฐ๋ฅ ์ ์ฝ์ ๋งํ Echarts๋ฅผ ์ ํํ๊ฒ ...","title":"[React Design Editor] ์ฐจํธ ์ถ๊ฐ","author":"salgum1114","date":"2019-10-20 10:09","tags":"react, antd, fabricjs, react-design-editor","cover":"/static/images/covers/react-design-editor.png","next":"/nextjs/2019-05-28-nextjs-static-website-5","prev":"/reactjs/2019-10-30-react-hot-loader-patch-warning"},"/nextjs/2019-05-28-nextjs-static-website-5":{"path":"/nextjs/2019-05-28-nextjs-static-website-5","content":"\u003cp\u003e์ด๋ฒ์๋ ํ๋ก์ ํธ์ \u003ca href=\"https://material-ui.com/getting-started/installation/\"\u003eMaterial UI\u003c/a\u003e๋ฅผ ์ ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด ๋ณด๊ณ ๋ช๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด๋ณด๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cp\u003e๋จผ์ \u003ccode\u003eMetarial UI\u003c/code\u003e๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด \u003ccode\u003enpm package\u003c/code\u003e๋ฅผ ๋ฐ๋๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascrpt language-javascrpt\"\u003e\u003cspan class=\"hljs-built_in\"\u003enpm\u003c/span\u003e install --save @material-ui/core @material-ui/icons @material-ui/styles\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eNext.js\u003c/code\u003e๋ ๊ธฐ๋ณธ์ ์ผ๋ก Server Side Rendering ์ด๊ธฐ ๋๋ฌธ์, ๋จ์ํ \u003ccode\u003eMaterial UI\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉ๋งํ ๊ฒฝ์ฐ ์คํ์ผ์ด ์ ์์ ์ผ๋ก ๋จนํ์ง ์๋๋ค.\n๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ช๊ฐ์ง ์์
์ ํด์ค์ผ ํ๋๋ฐ, ์ผ๋ฐ์ ์ธ \u003cstrong\u003eServer Rendering\u003c/strong\u003e์ธ ๊ฒฝ์ฐ์๋ \u003ca href=\"https://material-ui.com/guides/server-rendering/\"\u003eMaterial Server Rendering\u003c/a\u003e์ ์ฐธ๊ณ ํ๋ฉด ๋๊ณ ์ฐ๋ฆฌ๋ \u003ccode\u003eNext.js\u003c/code\u003e๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ \u003ca href=\"https://github.com/mui-org/material-ui/tree/master/examples/nextjs\"\u003eMaterial with Next.js\u003c/a\u003e๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003cp\u003e๊ธฐ์กด์ \u003ccode\u003e_app.js\u003c/code\u003e์ ์์ฑ๋ ๋ ์ด์์์ ๋ฐ๊ฟ๋ณด๊ธฐ ์ํด \u003ccode\u003eLayout\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ์๋ก ๋ง๋ ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ecomponents\u003c/code\u003e ๋๋ ํ ๋ฆฌ์ \u003ccode\u003eLayout.js\u003c/code\u003e ํ์ผ์ ์์ฑํ๊ณ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLayout.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Link \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/link'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e {\n AppBar,\n IconButton,\n Toolbar,\n Typography,\n Drawer,\n Divider,\n List,\n ListItem,\n ListItemIcon,\n ListItemText,\n Container,\n} \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'@material-ui/core'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { Menu, ChevronLeft, Home, Inbox, Mail } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'@material-ui/icons'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e drawerWidth = \u003cspan class=\"hljs-number\"\u003e240\u003c/span\u003e;\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eLayout\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n state = {\n \u003cspan class=\"hljs-attr\"\u003eopen\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n }\n\n handleDrawerOpen = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.setState({\n \u003cspan class=\"hljs-attr\"\u003eopen\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n });\n }\n\n handleDrawerClose = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.setState({\n \u003cspan class=\"hljs-attr\"\u003eopen\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n });\n }\n\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { children } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { open } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.state;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u0026lt;section\u0026gt;\n \u0026lt;AppBar\n position=\"static\"\n style={{\n width: `calc(100% - ${open ? drawerWidth : 0}px)`,\n marginLeft: open ? drawerWidth : 0,\n transition: 'all 0.2s',\n }}\n \u0026gt;\n \u0026lt;Toolbar\u0026gt;\n \u0026lt;IconButton edge=\"start\" color=\"inherit\" aria-label=\"Menu\" onClick={this.handleDrawerOpen}\u0026gt;\n \u0026lt;Menu /\u0026gt;\n \u0026lt;/IconButton\u0026gt;\n \u0026lt;Typography variant=\"h6\" style={{ flex: 1 }}\u0026gt;\n Static Website\n \u0026lt;/Typography\u0026gt;\n \u0026lt;/Toolbar\u0026gt;\n \u0026lt;/AppBar\u0026gt;\n \u0026lt;Drawer variant=\"persistent\" open={open}\u0026gt;\n \u0026lt;div style={{ width: drawerWidth }}\u0026gt;\n \u0026lt;div style={{ display: 'flex', justifyContent: 'flex-end' }}\u0026gt;\n \u0026lt;IconButton onClick={this.handleDrawerClose}\u0026gt;\n \u0026lt;ChevronLeft /\u0026gt;\n \u0026lt;/IconButton\u0026gt;\n \u0026lt;/div\u0026gt;\n \u0026lt;Divider /\u0026gt;\n \u0026lt;List\u0026gt;\n \u0026lt;Link href=\"/\"\u0026gt;\n \u0026lt;a\u0026gt;\n \u0026lt;ListItem button\u0026gt;\n \u0026lt;ListItemIcon\u0026gt;\u0026lt;Home /\u0026gt;\u0026lt;/ListItemIcon\u0026gt;\n \u0026lt;ListItemText primary=\"Home\"/\u0026gt;\n \u0026lt;/ListItem\u0026gt;\n \u0026lt;/a\u0026gt;\n \u0026lt;/Link\u0026gt;\n \u0026lt;Link href=\"/post\"\u0026gt;\n \u0026lt;a\u0026gt;\n \u0026lt;ListItem button\u0026gt;\n \u0026lt;ListItemIcon\u0026gt;\u0026lt;Inbox /\u0026gt;\u0026lt;/ListItemIcon\u0026gt;\n \u0026lt;ListItemText primary=\"Post\"/\u0026gt;\n \u0026lt;/ListItem\u0026gt;\n \u0026lt;/a\u0026gt;\n \u0026lt;/Link\u0026gt;\n \u0026lt;Link href=\"/about\"\u0026gt;\n \u0026lt;a\u0026gt;\n \u0026lt;ListItem button\u0026gt;\n \u0026lt;ListItemIcon\u0026gt;\u0026lt;Mail /\u0026gt;\u0026lt;/ListItemIcon\u0026gt;\n \u0026lt;ListItemText primary=\"About\"/\u0026gt;\n \u0026lt;/ListItem\u0026gt;\n \u0026lt;/a\u0026gt;\n \u0026lt;/Link\u0026gt;\n \u0026lt;/List\u0026gt;\n \u0026lt;/div\u0026gt;\n \u0026lt;/Drawer\u0026gt;\n \u0026lt;Container\u0026gt;\n \u0026lt;article style={{\n width: `calc(100% - ${open ? drawerWidth : 0}px)`,\n marginLeft: open ? drawerWidth : 0,\n transition: 'all 0.2s',\n margin: '16px 0',\n }}\u0026gt;\n {children}\n \u0026lt;/article\u0026gt;\n \u0026lt;/Container\u0026gt;\n \u0026lt;/section\u0026gt;\n );\n }\n}\n\nexport default Layout;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ทธ๋ฆฌ๊ณ ๋์ \u003ccode\u003eapp.js\u003c/code\u003e์ ์์ฑ๋ ๋ ์ด์์ ์ฝ๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eapp.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e App, { Container } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/app'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Head \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/head'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Layout \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../components/material/Layout'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootApp\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { Component, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eStatic Website\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eLayout\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eComponent\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e} /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eLayout\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n );\n }\n}\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ์์ฑ ํ์ ํ๋ฉด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-material-ui.png\" alt=\"first-material-ui\" /\u003e\u003c/p\u003e\n\u003cp\u003eํ์ง๋ง ํ๋ฉด์ ์๋ก๊ณ ์นจํด์ ๋ณด๊ฒ๋๋ฉด ์ฒ์์ ์ค๋ช
ํ๋ค์ํผ ์คํ์ผ์ด ์ ์ฉ๋์ง ์์๋ค๊ฐ ๋ ๋๋ง์ด ๋ชจ๋ ๋๋ ํ ์คํ์ผ์ด ์ ์ฉ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/material-client-rendering.gif\" alt=\"material-client-rendering\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด \u003ccode\u003e_document.js\u003c/code\u003e์ \u003ccode\u003e_app.js\u003c/code\u003e๋ฅผ ์์ ํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e_document.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Document, { Head, Main, NextScript } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/document'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { ServerStyleSheets } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'@material-ui/styles'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e flush \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'styled-jsx/server'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootDocument\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eDocument\u003c/span\u003e \u003c/span\u003e{\n \u003cspan class=\"hljs-keyword\"\u003estatic\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003easync\u003c/span\u003e getInitialProps(ctx) {\n \u003cspan class=\"hljs-comment\"\u003e// Render app and page and get the context of the page with collected side effects.\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e sheets = \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e ServerStyleSheets();\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e originalRenderPage = ctx.renderPage;\n\n ctx.renderPage = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e\n originalRenderPage({\n \u003cspan class=\"hljs-attr\"\u003eenhanceApp\u003c/span\u003e: \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003eApp\u003c/span\u003e =\u0026gt;\u003c/span\u003e props =\u0026gt; sheets.collect(\u0026lt;App {...props} /\u0026gt;),\n });\n\n const initialProps = await Document.getInitialProps(ctx);\n\n return {\n ...initialProps,\n // Styles fragment is rendered after the app and page rendering finish.\n styles: (\n \u0026lt;React.Fragment\u0026gt;\n {sheets.getStyleElement()}\n {flush() || null}\n \u0026lt;/React.Fragment\u0026gt;\n ),\n };\n }\n\n render() {\n return (\n \u0026lt;html\u0026gt;\n \u0026lt;Head\u0026gt;\n \u0026lt;meta charSet=\"utf-8\" /\u0026gt;\n \u0026lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no\" /\u0026gt;\n \u0026lt;meta name=\"description\" content=\"My First Static Website\"/\u0026gt;\n \u0026lt;meta name=\"keywords\" content=\"nextjs,static,website\" /\u0026gt;\n \u0026lt;/Head\u0026gt;\n \u0026lt;body\u0026gt;\n \u0026lt;Main /\u0026gt;\n \u0026lt;NextScript /\u0026gt;\n \u0026lt;/body\u0026gt;\n \u0026lt;/html\u0026gt;\n );\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003e_app.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e App, { Container } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/app'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Head \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/head'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e CssBaseline \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'@material-ui/core/CssBaseline'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Layout \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../components/material/Layout'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootApp\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e \u003c/span\u003e{\n componentDidMount() {\n \u003cspan class=\"hljs-comment\"\u003e// Remove the server-side injected CSS.\u003c/span\u003e\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e jssStyles = \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(\u003cspan class=\"hljs-string\"\u003e'#jss-server-side'\u003c/span\u003e);\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (jssStyles) {\n jssStyles.parentNode.removeChild(jssStyles);\n }\n }\n\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { Component, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eStatic Website\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eCssBaseline\u003c/span\u003e /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eLayout\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eComponent\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e} /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eLayout\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n );\n }\n}\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๋ค์ ํ๋ฉด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/material-server-rendering.gif\" alt=\"material-server-rendering\" /\u003e\u003c/p\u003e\n\u003cp\u003e์๋ก๊ณ ์นจ์ ํด๋ ์คํ์ผ์ด ์ ์์ ์ผ๋ก ์ ์ฉ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e์ด๋ ๊ฒํด์ \u003ccode\u003eMaterial UI\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํด๋ดค๊ณ ์ปดํฌ๋ํธ๋ค์ ์ฌ์ฉํด์ ํ๋ฉด์ ๊ตฌ์ฑํด ๋๊ฐ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003cp\u003e๋ค์ ๊ธ์์๋ \u003ccode\u003eAnt.Design\u003c/code\u003e์ ์ ์ฉํ์ฌ Layout์ ์์ฑํด๋ณธ๋ค.\u003c/p\u003e\n\u003ch3 id=\"nextjs\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋ชฉ์ฐจ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-24-nextjs-static-website-4/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-28-nextjs-static-website-5/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"์ด๋ฒ์๋ ํ๋ก์ ํธ์ Material UI๋ฅผ ์ ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด ๋ณด๊ณ ๋ช๊ฐ์ง ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ด์์์ ๋ง๋ค์ด๋ณด๋ ค๊ณ ํ๋ค.\n\n๋จผ์ Metarial UI๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด npm package๋ฅผ ๋ฐ๋๋ค.\n\nnpm install --save @material-ui/core @material-ui/icons @material-ui/styles\n\n\nNext...","title":"Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-05-28 15:00","tags":"react, nextjs, website","cover":"/static/images/covers/nextjs.png","next":"/nextjs/2019-05-24-nextjs-static-website-4","prev":"/etc/2019-10-22-react-design-editor-1"},"/nextjs/2019-05-24-nextjs-static-website-4":{"path":"/nextjs/2019-05-24-nextjs-static-website-4","content":"\u003cp\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003e์ง๋ ๊ธ\u003c/a\u003e์์ \u003ccode\u003eindex.js\u003c/code\u003e์ \u003ccode\u003epost.js\u003c/code\u003e๋ฅผ ์์ฑํ์๊ณ \u003ccode\u003eRouting\u003c/code\u003e์ ์ฌ์ฉํ์ง ์๊ณ URL๋ก ์ง์ ์ ๊ทผํด์ ํ๋ฉด์ ํ์ธํ์๋ค. ์ด๋ฒ ๊ธ์์๋ \u003ccode\u003eNext.js\u003c/code\u003e์ \u003ccode\u003eRouting\u003c/code\u003e์ ์ฌ์ฉํ์ฌ ํ์ด์ง ์ ํ์ ํด๋ณด๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ca href=\"https://github.com/zeit/next.js/#routing\"\u003eNext.js github\u003c/a\u003e์ \u003ccode\u003eRouting\u003c/code\u003e์ ๋ํ ์ค๋ช
์ด ์ ๋์์๋ค.\u003c/p\u003e\n \u003cp\u003e\u003ccode\u003eNext.js\u003c/code\u003e์์ \u003ccode\u003eRoute\u003c/code\u003e๋ \u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก์ ์์ฑํ ํ์ผ๋ช
์ผ๋ก ์์ฑ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์, ํ์ผ๋ช
๋ ์ ๊ฒฝ์จ์ ์ ๋ง๋ค์ด์ผํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"aboutjs\"\u003eabout.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003eRouting ๊ฒฝ๋ก๋ฅผ ๋ ์ถ๊ฐํ๊ธฐ ์ํด \u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์ \u003ccode\u003eabout.js\u003c/code\u003eํ์ผ์ ์ถ๊ฐํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003eAbout\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eabout.js\u003c/code\u003e๊น์ง ์์ฑํ์๋ค๋ฉด ์ด 3๊ฐ์ Routing์ด ์๊ธฐ๊ฒ ๋์๋ค.\u003c/p\u003e\n\u003ch2 id=\"_appjslink\"\u003e_app.js์ Link ์ปดํฌ๋ํธ ์ถ๊ฐ\u003c/h2\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์, ๊ณตํต์ ๋ ์ด์์์ด ์์ฑ๋ \u003ccode\u003e_app.js\u003c/code\u003e์์ \u003ccode\u003e\u0026lt;header\u0026gt;\u003c/code\u003e์๋ฆฌ๋จผํธ ์์ \u003ccode\u003e\u0026lt;Link\u0026gt;\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ์ถ๊ฐํ์ฌ ์์ฑํ \u003ccode\u003eRouting\u003c/code\u003e ์ฐ๊ฒฐํด๋ณธ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e App, { Container } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/app'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Head \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/head'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Link \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/link'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e styles = {\n \u003cspan class=\"hljs-attr\"\u003elayout\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003edisplay\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'flex'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'100%'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'100%'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eflexDirection\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'column'\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003eheader\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e60\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003emain\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eflex\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003efooter\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e60\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003edivider\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003emargin\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'0 8px'\u003c/span\u003e,\n },\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootApp\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { Component, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eStatic Website\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.layout}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eheader\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.header}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ehref\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"/\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003eHome\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003espan\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.divider}\u003c/span\u003e\u0026gt;\u003c/span\u003e|\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003espan\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ehref\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"/post\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003ePost\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003espan\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.divider}\u003c/span\u003e\u0026gt;\u003c/span\u003e|\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003espan\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003ehref\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"/about\"\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003eAbout\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ea\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eLink\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eheader\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emain\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.main}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eComponent\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e} /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003emain\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003efooter\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.footer}\u003c/span\u003e\u0026gt;\u003c/span\u003eFooter\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003efooter\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n );\n }\n}\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eimport Link from 'next/link'\u003c/code\u003e๋ก ๋ชจ๋์ import ํด์ฃผ๊ณ \u003ccode\u003e\u0026lt;Link\u0026gt;\u003c/code\u003e ์ปดํฌ๋ํธ์ \u003ccode\u003ehref\u003c/code\u003e Props ๊ฐ์ผ๋ก \u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์์ ์์ฑํ ํ์ผ๋ช
์ ์์ฑํด์ค๋ค. ๋ง์ง๋ง์ผ๋ก \u003ccode\u003e\u0026lt;Link\u0026gt;\u003c/code\u003e์์๋ \u003ccode\u003e\u0026lt;a\u0026gt;\u003c/code\u003e๋ฅผ ์ถ๊ฐํด์ค๋ค.\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ์์ฑ๋์๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ํ๋ฉด์ด ๋ณด์ผ ๊ฒ์ด๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-routing.png\" alt=\"first-routing\" /\u003e\u003c/p\u003e\n\u003cp\u003eํ ๋ฒ์ฉ ๋๋ฌ๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-routing-click.gif\" alt=\"first-routing-click\" /\u003e\u003c/p\u003e\n\u003ch2 id=\"postjsrouter\"\u003epost.js์ Router ์ถ๊ฐ\u003c/h2\u003e\n\u003cp\u003e๋ค์์ผ๋ก, \u003ccode\u003e\u0026lt;button\u0026gt;\u003c/code\u003e์๋ฆฌ๋จผํธ \u003ccode\u003eonClick\u003c/code\u003e์ ์ด์ฉํด์ \u003ccode\u003eRouting\u003c/code\u003e์ ํด๋ณด๋๋ฐ, ์ด๋ \u003ccode\u003eNext.js\u003c/code\u003e์ \u003ccode\u003eRouter\u003c/code\u003e๋ฅผ ์ฌ์ฉํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e๋จผ์ , \u003ccode\u003e\u0026lt;Link\u0026gt;\u003c/code\u003e์ \u003ccode\u003eRouter\u003c/code\u003e์ ํฐ ์ฐจ์ด์ ์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋๋ก ๋ ๋๋ง ํ๋ ์ํ๋์ ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ccode\u003eRouter.push\u003c/code\u003e๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ ์ฌ์ด๋๋ก ๋ ๋๋ง์ ํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n First post page\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e \n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003epost.js\u003c/code\u003e์์ \u003ccode\u003eimport Router from 'next/router'\u003c/code\u003e๋ก ๋ชจ๋์ import ํด์ฃผ๊ณ \u003ccode\u003e\u0026lt;button\u0026gt;\u003c/code\u003e์ ์ถ๊ฐํ ๋ค์ \u003ccode\u003eonClick\u003c/code\u003e ์์ฑ์ \u003ccode\u003eRouter.push('/')\u003c/code\u003e๋ฅผ ์ถ๊ฐํ๋ค.\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ์์ฑ๋์๋ค๋ฉด ๋ค์์ฒ๋ผ ๋์ํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-router-click.gif\" alt=\"first-router-click\" /\u003e\u003c/p\u003e\n\u003cp\u003e๋ง์ฐฌ๊ฐ์ง๋ก \u003ccode\u003eabout.js\u003c/code\u003e์๋ ์ถ๊ฐํด์ค๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n About\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"urlparamsquerystring\"\u003eURL Params(Query String) ์ ๋ฌ\u003c/h2\u003e\n\u003cp\u003e๋ค์์ผ๋ก \u003ccode\u003eRouting\u003c/code\u003e์ ํ ๋, URL๋ก Parameter๋ฅผ ์ ๋ฌํ์ฌ ๊ฐ ํ์ด์ง์์ ์ ๋ฌ๋ฐ์ Parameter๋ฅผ ํ๋ฉด์ ์ฒ๋ฆฌํ ์ ์๋๋ก ํด๋ณธ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ccode\u003eHome\u003c/code\u003e ๋ฒํผ์ ํด๋ฆญ ํ์ ๋, ์ด๋ค ํ์ด์ง์์ \u003ccode\u003eHome\u003c/code\u003e์ผ๋ก ๋์์๋์ง ํ์ธํด๋ณด๋ ์์ ๋ฅผ ์์ฑํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003ccode\u003epost.js\u003c/code\u003e์์ ํ๋ ๊ฒ์ฒ๋ผ \u003ccode\u003eabout.js\u003c/code\u003e์๋ \u003ccode\u003e\u0026lt;button\u0026gt;\u003c/code\u003e์๋ฆฌ๋จผํธ๋ฅผ ์ถ๊ฐํ๊ณ \u003ccode\u003eonClick\u003c/code\u003e์์ฑ์ \u003ccode\u003eRouter.push\u003c/code\u003e๋ฅผ ์ถ๊ฐํ๋ค.\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ฌ๊ณ ๋์ \u003ccode\u003epost.js\u003c/code\u003e์ \u003ccode\u003eabout.js\u003c/code\u003e์ ์์ฑ๋ \u003ccode\u003eRouter.push('/')\u003c/code\u003e๋ฅผ ๊ฐ๊ฐ \u003ccode\u003eRouter.push('/?history=post')\u003c/code\u003e์ \u003ccode\u003eRouter.push('/?history=about')\u003c/code\u003e๋ก ๋ณ๊ฒฝํด์ค๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003epost.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n First post page\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/?history=post')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e \n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eabout.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n About\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/?history=about')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด๋ ๊ฒ ์์ฑ๋ ํ์ด์ง์์ \u003ccode\u003eHome\u003c/code\u003e ๋ฒํผ์ ํด๋ฆญํ์ฌ \u003ccode\u003eHome\u003c/code\u003e๊ฒฝ๋ก๋ก ๊ฐ๊ฒ ๋์ ๊ฒฝ์ฐ, URL์๋ Query String์ด ๋ถ๊ฒ ๋์๊ณ , \u003ccode\u003eindex.js\u003c/code\u003e์ ์ ๋ฌ๋๋ props์ \u003ccode\u003econsole.log(props)\u003c/code\u003e๋ก ๋ก๊ทธ๋ฅผ ํ์ธํด๋ณด๋ฉด \u003ccode\u003eDevelop Console\u003c/code\u003e์ ๋ค์์ฒ๋ผ ๋ณด์ด๊ฒ ๋๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-query-string.png\" alt=\"first-query-string\" /\u003e\u003c/p\u003e\n\u003cp\u003eprops์ \u003ccode\u003erouter\u003c/code\u003e ์ค๋ธ์ ํธ๊ฐ ์ ๋ฌ๋๋๋ฐ, \u003ccode\u003erouter\u003c/code\u003e ์ค๋ธ์ ํธ ์์์ ์ ๋ฌ๋ \u003ccode\u003equery\u003c/code\u003e๋ฅผ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e์ด๊ฒ์ ํ์ฉํด์ \u003ccode\u003eindex.js\u003c/code\u003e์์ ์ด๋ค ํ์ด์ง๋ก๋ถํฐ ๋์ด์๋์ง ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eindex.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e styles = {\n \u003cspan class=\"hljs-attr\"\u003efrom\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'red'\u003c/span\u003e,\n },\n};\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { router } = props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n Home\n {\n router.query.history ? (\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.from}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n From the {router.query.history}\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n ) : null\n }\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eํ๋ฉด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-query-string-from.png\" alt=\"first-query-string-from\" /\u003e\u003c/p\u003e\n\u003ch2 id=\"asurlparams\"\u003e\u003cstrong\u003eas\u003c/strong\u003e ์์ฑ์ผ๋ก URL Params ์จ๊ธฐ๊ธฐ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eURL Params\u003c/code\u003e๊ฐ URL์ ๋ณด์ด๋ ๊ฒ์ด ๋ง์ด ํธํ์ง ์๋ค๋ฉด \u003ccode\u003eNext.js\u003c/code\u003e์์๋ ์จ๊ธธ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eas\u003c/code\u003e์์ฑ์ ์ด์ฉํ๋ ๊ฒ์ธ๋ฐ, \u003ccode\u003e\u0026lt;Link href=\"/?history=post\" as=\"/\"\u0026gt;\u003c/code\u003e๋ก ์ฌ์ฉํ๊ฑฐ๋ \u003ccode\u003eRouter.push(\"/?history=post\", '/')\u003c/code\u003e๋ก ์ฌ์ฉํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epost.js\u003c/code\u003e์ \u003ccode\u003eabout.js\u003c/code\u003e์ ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ด ๋ฐ๊ฟ์ค๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003epost.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n First post page\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/?history=post', '/')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e \n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eabout.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n About\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{()\u003c/span\u003e =\u0026gt;\u003c/span\u003e Router.push('/?history=about', '/')}\u0026gt;Home\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๋ค์ ํ๋ฉด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-routing-as.gif\" alt=\"first-routing-as\" /\u003e\u003c/p\u003e\n\u003cp\u003e์๊น์๋ ๋ค๋ฅด๊ฒ URL์ \u003ccode\u003eQuery String\u003c/code\u003e์ด ๋ถ์ง ์๊ณ \u003ccode\u003ehistory\u003c/code\u003e๊ฐ ์ ๋ฌ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eํ์ง๋ง ์ด ๋ฐฉ๋ฒ์์ ๋ฌธ์ ์ ์ ์ฐพ์ผ๋ผ๊ณ ํ๋ค๋ฉด, ์๋ก๊ณ ์นจ์ ํ์ ๋ ์ ๋ฌ๋ฐ์ \u003ccode\u003erouter\u003c/code\u003e ์ค๋ธ์ ํธ์ \u003ccode\u003equery\u003c/code\u003e๊ฐ ๋น์ด์์ผ๋ฏ๋ก \u003ccode\u003eFrom the\u003c/code\u003e๋ฌธ๊ตฌ๊ฐ ๋ณด์ด์ง ์๊ฒ ๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"withrouter\"\u003e\u003cstrong\u003ewithRouter\u003c/strong\u003e ์ฌ์ฉ\u003c/h2\u003e\n\u003cp\u003e๋ค์์ผ๋ก \u003ccode\u003ewithRouter\u003c/code\u003e๋ฅผ ์ฌ์ฉํด๋ณผ ๊ฒ์ธ๋ฐ, ์ด ๋
์์ \u003ccode\u003eRouter\u003c/code\u003e์ \u003ccode\u003eHOC\u003c/code\u003e๋ก์จ ์ปดํฌ๋ํธ์์ \u003ccode\u003erouter\u003c/code\u003e props๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์๋๋ก ํด์ค๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eHistory\u003c/code\u003e ์์ ๋ฅผ ์ํด์ root ๊ฒฝ๋ก์ \u003ccode\u003ecomponents\u003c/code\u003e ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ ํ์์ \u003ccode\u003eHistory.js\u003c/code\u003e ํ์ผ์ ์์ฑํ๋ค.\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์, \u003ccode\u003eHistory.js\u003c/code\u003e์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHistory.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { withRouter } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e styles = {\n \u003cspan class=\"hljs-attr\"\u003ehistory\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ecolor\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'red'\u003c/span\u003e,\n },\n};\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eHistory\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { router } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e router.query.history ? (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.history}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n {router.query.history}\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n ) : \u003cspan class=\"hljs-literal\"\u003enull\u003c/span\u003e;\n }\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e withRouter(History);\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eimport { withRouter } from 'next/router'\u003c/code\u003e๋ก ๋ชจ๋์ import ์ํค๊ณ \u003ccode\u003ewithRouter(History)\u003c/code\u003e๋ก Component๋ฅผ ๊ฐ์ธ๊ฒ ๋๋ฉด props๋ก router๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์๊ฒ ๋๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eindex.js\u003c/code\u003e๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณ๊ฒฝํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eindex.js\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e History \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../components/History'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n Home\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eHistory\u003c/span\u003e /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์์ฑํ ํ์ ํ๋ฉด์ ํ์ธํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-router-history.png\" alt=\"first-router-history\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eindex.js\u003c/code\u003e์์ \u003ccode\u003e\u0026lt;History\u0026gt;\u003c/code\u003e๋ก \u003ccode\u003erouter\u003c/code\u003e๋ฅผ props์ผ๋ก ์ ๋ฌํ์ง ์์ง๋ง \u003ccode\u003e\u0026lt;History\u0026gt;\u003c/code\u003e์ปดํฌ๋ํธ์์ \u003ccode\u003eHOC\u003c/code\u003e๋ก \u003ccode\u003ewithRotuer\u003c/code\u003e๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ props๋ก \u003ccode\u003erouter\u003c/code\u003e์ค๋ธ์ ํธ๋ฅผ ์ ๋ฌ๋ฐ์ ๊ฒ์ ๋ณผ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-router-history-log.png\" alt=\"first-router-history-log\" /\u003e\u003c/p\u003e\n\u003ch3 id=\"nextjs\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋ชฉ์ฐจ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-24-nextjs-static-website-4/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-28-nextjs-static-website-5/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"์ง๋ ๊ธ์์ index.js์ post.js๋ฅผ ์์ฑํ์๊ณ Routing์ ์ฌ์ฉํ์ง ์๊ณ URL๋ก ์ง์ ์ ๊ทผํด์ ํ๋ฉด์ ํ์ธํ์๋ค. ์ด๋ฒ ๊ธ์์๋ \nNext.js์ Routing์ ์ฌ์ฉํ์ฌ ํ์ด์ง ์ ํ์ ํด๋ณด๋ ค๊ณ ํ๋ค.\n\n\u003e Next.js github์ Routing์ ๋ํ ์ค๋ช
์ด ์ ๋์์๋ค.\n\nNext.js์์ Route๋ pages๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก์ ์์ฑํ...","title":"Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-05-24 08:27","tags":"react, nextjs, website","cover":"/static/images/covers/nextjs.png","next":"/nextjs/2019-05-21-nextjs-static-website-3","prev":"/nextjs/2019-05-28-nextjs-static-website-5"},"/nextjs/2019-05-21-nextjs-static-website-3":{"path":"/nextjs/2019-05-21-nextjs-static-website-3","content":"\u003cp\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003e์ด์ ๊ธ\u003c/a\u003e์์ ํ๋ก์ ํธ ๊ตฌ์ฑ์ ํ์ฌ ๊ฐ๋จํ ํ๋ฉด์ ํ์ธํ์๋ค.\u003c/p\u003e\n\u003cp\u003e์ด๋ฒ์๋ Next.js์ ๋ด์ฅ๋์ด ์๋ \u003ccode\u003e_document.js\u003c/code\u003e, \u003ccode\u003e_app.js\u003c/code\u003e, \u003ccode\u003e_error.js\u003c/code\u003e๋ฅผ ์ปค์คํฐ๋ง์ด์งํ์ฌ ๋ ์ด์์์ ์๋กญ๊ฒ ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e๊ฐ๊ฐ์ ๋ํ ์ค๋ช
์ \u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js ๊ตฌ์กฐ\u003c/a\u003e์์ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"_documentjs\"\u003e_document.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003e_document.js\u003c/code\u003e๋ Next.js์์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ด ์์์ด๋๋ \u003ccode\u003eDocument\u003c/code\u003e ํ์ผ์ด๋ค.\u003c/p\u003e\n\u003cp\u003e์ฆ, \u003ccode\u003e\u0026lt;html\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;head\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;body\u0026gt;\u003c/code\u003e๋ฅผ ํฌํจํ๋ค๊ณ ๋ณด๋ฉด๋๋ค.\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ผ \u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์ \u003ccode\u003e_document.js\u003c/code\u003eํ์ผ์ ์์ฑํ๊ณ , ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Document, { Head, Main, NextScript } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/document'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootDocument\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eDocument\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u0026lt;html\u0026gt;\n \u0026lt;Head\u0026gt;\n \u0026lt;meta charSet=\"utf-8\" /\u0026gt;\n \u0026lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no\" /\u0026gt;\n \u0026lt;meta name=\"description\" content=\"My First Static Website\"/\u0026gt;\n \u0026lt;meta name=\"keywords\" content=\"nextjs,static,website\" /\u0026gt;\n \u0026lt;style global jsx\u0026gt;\n {`\n html, body, #__next {\n height: 100%;\n width: 100%;\n overflow: hidden;\n }\n `}\n \u0026lt;/style\u0026gt;\n \u0026lt;/Head\u0026gt;\n \u0026lt;body\u0026gt;\n \u0026lt;Main /\u0026gt;\n \u0026lt;NextScript /\u0026gt;\n \u0026lt;/body\u0026gt;\n \u0026lt;/html\u0026gt;\n );\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003e\u0026lt;Head\u0026gt;\u003c/code\u003e์์ \u003ccode\u003e\u0026lt;script\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;meta\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;link\u0026gt;\u003c/code\u003e ๋ฑ ๋ฆฌ์์ค ๋ฐ Metadata๋ค์ ์์ฑํด์ค ์ ์๋ค.\u003c/p\u003e\n\u003ch2 id=\"_appjs\"\u003e_app.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003e_app.js\u003c/code\u003e๋ ์ดํ๋ฆฌ์ผ์ด์
์ด ์์๋๋ ์ด๊ธฐ ํ์ด์ง๋ผ๊ณ ๋ณผ ์ ์๋ค. ์ด ํ์ด์ง์์๋ ๋ผ์ฐํ
์ ํตํด ์ปดํฌ๋ํธ๋ฅผ \u003ccode\u003eprops\u003c/code\u003e์ผ๋ก ์ ๋ฌ๋ฐ๊ธฐ ๋๋ฌธ์ ๊ณตํต์ ๋ ์ด์์์ ์์ฑํ์ฌ ๋ชจ๋ ํ๋ฉด์์ ๊ฐ์ ๋ ์ด์์์ด ๋์ฌ ์ ์๋๋ก ์์
ํ๊ฑฐ๋, \u003ccode\u003eComponentDidCatch\u003c/code\u003e์ ๊ฐ์ ๋ผ์ดํ ์ฌ์ดํด์ ํตํด \u003ccode\u003eError Handling\u003c/code\u003e์ ํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์ \u003ccode\u003e_app.js\u003c/code\u003eํ์ผ์ ์์ฑํ๊ณ , ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e App, { Container } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/app'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Head \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/head'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e styles = {\n \u003cspan class=\"hljs-attr\"\u003elayout\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003edisplay\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'flex'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'100%'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'100%'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eflexDirection\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'column'\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003eheader\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e60\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003emain\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eflex\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003efooter\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e60\u003c/span\u003e,\n },\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootApp\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { Component, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003eStatic Website\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003etitle\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eHead\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.layout}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eheader\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.header}\u003c/span\u003e\u0026gt;\u003c/span\u003eHeader\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eheader\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003emain\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.main}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eComponent\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e} /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003emain\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003efooter\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{styles.footer}\u003c/span\u003e\u0026gt;\u003c/span\u003eFooter\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003efooter\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eContainer\u003c/span\u003e\u0026gt;\u003c/span\u003e\n );\n }\n}\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003e\u0026lt;header\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;main\u0026gt;\u003c/code\u003e, \u003ccode\u003e\u0026lt;footer\u0026gt;\u003c/code\u003e๋ก ๋ ์ด์์์ ๋ง๋ค๊ณ \u003ccode\u003eprops\u003c/code\u003e๋ก ์ ๋ฌ ๋ฐ์ \u003ccode\u003eComponent\u003c/code\u003e๋ฅผ ๋ ๋๋งํ๋ค.\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ์์ฑํ ๋ค์ ํ๋ฉด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-layout.png\" alt=\"first-layout\" /\u003e\u003c/p\u003e\n\u003cp\u003eHeader, Static Website, Footer์์ผ๋ก ํ๋ฉด์ ๋ณด์ธ๋ค.\u003c/p\u003e\n\u003cp\u003e์ด๋ ๊ฒ ํด์ \u003ccode\u003epages\u003c/code\u003e์ ํ์ด์ง๋ค์ ์ถ๊ฐํ๊ฒ ๋๋ฉด Next.js์์๋ URL์์ ํ์ด์ง ๊ฒฝ๋ก๋ก ์ ๊ทผํ์ ๊ฒฝ์ฐ ํ์ด์ง์ ์์ฑ๋ \u003ccode\u003eComponent\u003c/code\u003e๋ฅผ ์ ๋ฌํด์ฃผ๊ฒ ๋์ด ๊ณตํต์ ๋ ์์ด์์ผ๋ก ํ๋ฉด์ ๊ตฌํํ ์ ์๊ฒ ๋๋ค.\u003c/p\u003e\n\u003ch2 id=\"_errorjs\"\u003e_error.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003eNext.js์์๋ \u003ccode\u003epages\u003c/code\u003e์ ์๋ ๊ฒฝ๋ก๋ก ์ ๊ทผํ์ ๊ฒฝ์ฐ, ๋ด์ฅ๋์ด ์๋ Error ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๊ฒ ๋์ด์๋ค.\u003c/p\u003e\n\u003cp\u003e๋ง์ฐฌ๊ฐ์ง๋ก Error ํ์ด์ง๋ ์๋กญ๊ฒ ์์ฑํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์ \u003ccode\u003e_error.js\u003c/code\u003eํ์ผ์ ์์ฑํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootError\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'Error!'\u003c/span\u003e;\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์์ฑํ ํ์ ํ์ฌ ๊ฒฝ๋ก์ \u003ccode\u003e/post\u003c/code\u003e๋ฅผ ๋ถ์ฌ URL์ ์ ๊ทผํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ์๋ฌ ํ๋ฉด์ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-error-page.png\" alt=\"first-error-page\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ๋ ์ด์์์ ๊ตฌ์ฑํ์๋ค๋ฉด \u003ccode\u003epages\u003c/code\u003e์ ์๋ก์ด ํ์ด์ง๋ฅผ ๋ง๋ค์ด์ ํ์ธํด๋ณธ๋ค.\u003c/p\u003e\n\u003ch2 id=\"postjs\"\u003epost.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003epages\u003c/code\u003e๋๋ ํ ๋ฆฌ์ \u003ccode\u003epost.js\u003c/code\u003eํ์ผ์ ์์ฑํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n First post page\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e \n );\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003epost.js\u003c/code\u003e๋ฅผ ๋ง๋ค๊ธฐ ์ ์ \u003ccode\u003e/post\u003c/code\u003e๊ฒฝ๋ก๋ก ์ ๊ทผํ์ ๋๋ ์๋ฌ๊ฐ ๋ฌ์์ง๋ง ์ด์ ๋ \u003ccode\u003eFirst post page\u003c/code\u003e๋ผ๋ ๋ฌธ๊ตฌ๋ก ํ๋ฉด์ ์๋ฌ์์ด ๋์ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-post-page.png\" alt=\"first-post-page\" /\u003e\u003c/p\u003e\n\u003ch3 id=\"nextjs\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋ชฉ์ฐจ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-24-nextjs-static-website-4/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-28-nextjs-static-website-5/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"์ด์ ๊ธ์์ ํ๋ก์ ํธ ๊ตฌ์ฑ์ ํ์ฌ ๊ฐ๋จํ ํ๋ฉด์ ํ์ธํ์๋ค.\n\n์ด๋ฒ์๋ Next.js์ ๋ด์ฅ๋์ด ์๋ _document.js, _app.js, _error.js๋ฅผ ์ปค์คํฐ๋ง์ด์งํ์ฌ ๋ ์ด์์์ ์๋กญ๊ฒ ๊ตฌ์ฑํ๋\n๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.\n\n\u003e ๊ฐ๊ฐ์ ๋ํ ์ค๋ช
์ Next.js ๊ตฌ์กฐ์์ ํ์ธํ ์ ์๋ค.\n\n\n_DOCUMENT.JS ํ์ผ ์์ฑ\n_document.js...","title":"Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์","author":"salgum1114","date":"2019-05-21 10:00","tags":"react, nextjs, website","cover":"/static/images/covers/nextjs.png","next":"/nextjs/2019-05-20-nextjs-static-website-2","prev":"/nextjs/2019-05-24-nextjs-static-website-4"},"/nextjs/2019-05-20-nextjs-static-website-2":{"path":"/nextjs/2019-05-20-nextjs-static-website-2","content":"\u003cp\u003e์ฌ์ค Next.js๋ ์ค๋ช
ํ ๊ฒ ๋ณ๋ก ์๋ค. \u003ca href=\"https://github.com/zeit/next.js/tree/canary/examples\"\u003e์์ ๋ค\u003c/a\u003e์ด ๋๋ฌด ์๋์ด ์๊ธฐ ๋๋ฌธ์.. ๊ทธ๋ ์ง๋ง ๋ด ๋จธ๋ฆฟ์์์ ์ฌ๋ผ์ ธ๊ฐ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ก์ด๋ผ๋ ๋จ๊ธฐ๋ ค๊ณ ์์ฑํ๋ค.\u003c/p\u003e\n\u003ch2 id=\"1npm\"\u003e1. npm ํ๋ก์ ํธ ์์ฑ\u003c/h2\u003e\n\u003cp\u003eํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด \u003ccode\u003estatic-website\u003c/code\u003e ๋๋ ํ ๋ฆฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ \u003ccode\u003ecd static-website\u003c/code\u003e๋ก ๊ฐ์ \u003ccode\u003enpm init\u003c/code\u003e์ผ๋ก npm ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์ฐธ๊ณ ๋ก \u003ccode\u003enpm init\u003c/code\u003e์ ์คํํ๊ฒ ๋๋ฉด ์ฌ๋ฌ ์
๋ ฅ์ ๋ฐ๊ฒ ๋๋๋ฐ, ๋์ค์ ๋ณ๊ฒฝํ ์ ์์ผ๋ ๋ค ์ํฐ๋ฅผ ์น๊ณ ๋์ด๊ฐ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003ccode\u003enpm init\u003c/code\u003e์ด ์๋ฃ๋์์ผ๋ฉด, \u003ccode\u003estatic-website\u003c/code\u003e ํด๋์ \u003ccode\u003epackage.json\u003c/code\u003e ํ์ผ์ด ํ๋ ์์ฑ๋๊ฑธ ๋ณผ ์ ์๋๋ฐ, npm ํ๋ก์ ํธ๋ ์ด ํ์ผ๋ก ์์ํด์ ๋๋๋ค๊ณ ๋ณด๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch2 id=\"2dependencies\"\u003e2. dependencies ์ค์น\u003c/h2\u003e\n\u003cp\u003e๊ธฐ๋ณธ์ ์ผ๋ก Next.js๋ก ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ์ฌ ์น ํ์ด์ง๊น์ง ๋์ฐ๊ธฐ ์ํด ํ์ํ ์ข
์์ฑ์ผ๋ก๋ ๋ค์์ด ํ์ํ๋ค.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e@babel/node // node ํ์ผ์์ es6 ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ธฐ ์ํด์\u003c/li\u003e\n\u003cli\u003e@babel/preset-env // es6 ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ธฐ ์ํด์\u003c/li\u003e\n\u003cli\u003enext@7.0.2 // \u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๊ตฌ์กฐ\u003c/a\u003e์์ ํ์ธ ๊ฐ๋ฅ\u003c/li\u003e\n\u003cli\u003ereact\u003c/li\u003e\n\u003cli\u003ereact-dom\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e์ด ์ข
์์ฑ๋ค์ ์ค์นํด๋ณด์.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003estatic-website\u003c/code\u003e ๊ฒฝ๋ก์์ ๊ฐ ๋ช
๋ น์ด๋ค์ ์คํํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003edepenencies\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003enpm install --save react react-dom next@7.0.2 express\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003edevDependecies\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003enpm install --save-dev @babel/node @babel/preset-env\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e์ด๋ ๊ฒ \u003ccode\u003enpm install\u003c/code\u003e ๋ช
๋ น์ด๋ก ์ข
์์ฑ๋ค์ ์ค์นํ๊ณ ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ด \u003ccode\u003epackage.json\u003c/code\u003e์ด ๊ตฌ์ฑ๋๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e-dev๊ฐ ๋ถ์ ๊ฒ๊ณผ ์๋ ๊ฒ์ ์ฐจ์ด๋ runtime ์ค์ ์ข
์์ฑ์ ์ฌ์ฉํ๋ ์ํ๋๋ก ๋๋ถ๋ถ ๊ตฌ๋ถ ์ง๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e{\n \u003cspan class=\"hljs-string\"\u003e\"name\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"static-website\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"version\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"1.0.0\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"description\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"main\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"index.js\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"scripts\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"test\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"echo \\\"Error: no test specified\\\" \u0026amp;\u0026amp; exit 1\"\u003c/span\u003e\n },\n \u003cspan class=\"hljs-string\"\u003e\"author\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"license\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"ISC\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"dependencies\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"next\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.0.2\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"react\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^16.8.6\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"react-dom\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^16.8.6\"\u003c/span\u003e\n },\n \u003cspan class=\"hljs-string\"\u003e\"devDependencies\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"@babel/node\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.2.2\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"@babel/preset-env\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.4.4\"\u003c/span\u003e\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ฌ๊ธฐ๊น์ง ๋์์ผ๋ฉด ํฅํ์ ์ด ํ๋ก์ ํธ๊ฐ \u003ccode\u003egit\u003c/code\u003e์ ์ฐ๊ฒฐ๋ ์๋ ์๊ธฐ ๋๋ฌธ์,\u003ccode\u003estatic-website\u003c/code\u003e ๊ฒฝ๋ก์ \u003ccode\u003e.gitignore\u003c/code\u003e๋ฅผ ๋ง๋ค์ด \u003ccode\u003enode_modules\u003c/code\u003e์ ๊ฐ์ ๊ฒ๋ค์ ์ ์ธ ์์ผ์ค๋ค.\u003c/p\u003e\n\u003cp\u003eํ์ฌ๋ \u003ccode\u003enode_modules\u003c/code\u003e์ \u003ccode\u003epackage-lock.json\u003c/code\u003e๋ง ์์ผ๋ ๋๊ฐ๋ฅผ ์ ์ธ์ํจ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003enode_modules/\npacakge-\u003cspan class=\"hljs-keyword\"\u003elock\u003c/span\u003e.json\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"nextconfigjs\"\u003enext.config.js ์์ฑ\u003c/h2\u003e\n\u003cp\u003e๊ธฐ๋ณธ์ ์ผ๋ก Next.js๋ ํ๋ก์ ํธ์ ๋ฃจํธ ๊ฒฝ๋ก์ ์๋ next.config.js๋ฅผ ์ฝ์ด๋ค์ด๊ฒ ๋๋ค.\u003c/p\u003e\n\u003cp\u003e๊ฐ๋จํ๊ฒ \u003ccode\u003enext.config.js\u003c/code\u003e๋ฅผ ์์ฑํ๋ค. ํ์ผ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-built_in\"\u003emodule\u003c/span\u003e.exports = {};\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n \u003cp\u003eํฅํ์ ํ๋ฌ๊ทธ์ธ๋ค์ ์ค์ ์ ์ถ๊ฐํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"packagejson\"\u003epackage.json ์คํฌ๋ฆฝํธ ์์ฑ\u003c/h2\u003e\n\u003cp\u003eNext.js ํจํค์ง๋ฅผ ์ค์นํ๊ฒ ๋๋ฉด ๋ค์๊ณผ ๊ฐ์ cli๋ฅผ ์ ๊ณตํ๋ค.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003enext // ๋ด์ฅ๋์ด ์๋ webpack-dev-server๋ก ๊ธฐ๋\u003c/li\u003e\n\u003cli\u003enext build // ํ๋ก์ ํธ๋ฅผ ๋น๋ํ์ฌ .next ํด๋๋ฅผ ์์ฑํ๋ค.\u003c/li\u003e\n\u003cli\u003enext start // ๋น๋๋ .next ํด๋๋ฅผ ๊ธฐ์ค์ผ๋ก ์น ์๋ฒ๋ฅผ ๊ธฐ๋ํด์ค๋ค.\u003c/li\u003e\n\u003cli\u003enext export // html ํ์ผ๋ค๋ก ๋ด๋ณด๋ด๊ธฐ๋ฅผ ํด์ค๋ค.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n \u003cp\u003eNext.js์๋ webpack ์ค์ ์ด ๋ด์ฅ๋์ด ์๊ธฐ ๋๋ฌธ์, hot-loader ๊ฐ์ ๊ฒ๋ค์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e๋ค์๊ณผ ๊ฐ์ด \u003ccode\u003epackage.json\u003c/code\u003e์ \u003ccode\u003escripts\u003c/code\u003e์ ์ถ๊ฐํด์ค๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e{\n \u003cspan class=\"hljs-string\"\u003e\"name\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"static-website\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"version\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"1.0.0\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"description\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"main\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"index.js\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"scripts\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"test\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"echo \\\"Error: no test specified\\\" \u0026amp;\u0026amp; exit 1\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"dev\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"next\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"build\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"next build\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"start\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"next start\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"export\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"next export\"\u003c/span\u003e\n },\n \u003cspan class=\"hljs-string\"\u003e\"author\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"license\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"ISC\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"dependencies\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"express\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^4.17.0\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"next\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.0.2\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"react\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^16.8.6\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"react-dom\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^16.8.6\"\u003c/span\u003e\n },\n \u003cspan class=\"hljs-string\"\u003e\"devDependencies\"\u003c/span\u003e: {\n \u003cspan class=\"hljs-string\"\u003e\"@babel/node\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.2.2\"\u003c/span\u003e,\n \u003cspan class=\"hljs-string\"\u003e\"@babel/preset-env\"\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"^7.4.4\"\u003c/span\u003e\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด ์ํ๋ก npm run dev๋ก ๊ธฐ๋ํด๋ณด๋ฉด ์คํจํ๋ค. ์ด์ ๋ \u003ccode\u003epages\u003c/code\u003e ํด๋๊ฐ ์์ด์ ๊ทธ๋ ๋ค.\u003c/p\u003e\n\u003ch2 id=\"pagesindexjs\"\u003epages ํด๋ ๋ฐ index.js ํ์ผ ์์ฑ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003estatic-website\u003c/code\u003e ๊ฒฝ๋ก์ \u003ccode\u003epages\u003c/code\u003e ํด๋๋ฅผ ์์ฑํ๊ณ ๊ทธ ํ์์ \u003ccode\u003eindex.js\u003c/code\u003e ํ์ผ์ ์์ฑํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eindex.js\u003c/code\u003e ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e (props) =\u0026gt; {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\n static webiste\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ediv\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n )\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ทธ๋ฆฌ๊ณ ๋์ \u003ccode\u003enpm run dev\u003c/code\u003e ๋ฅผ ๋ค์ ์คํํด๋ณธ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003enext์ ๊ธฐ๋ณธ ํฌํธ๋ 3000์ด๊ณ ๋ณ๊ฒฝํ๊ณ ์ ํ๋ฉด next -p \u003cํฌํธ ๋ฒํธ\u003e ๋ฅผ ๋ถ์ด๋ฉด ๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003elocalhost:3000์ผ๋ก ์ ์ํ์ฌ ํ๋ฉด์ ํ์ธํ๋ฉด static website๋ฅผ ์ถ๋ ฅํ๋ ํ๋ฉด์ด ๋์จ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/first-page.png\" alt=\"first-page\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003epages\u003c/code\u003e์ \u003ccode\u003eindex.js\u003c/code\u003e๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด \u003ccode\u003eindex.js\u003c/code\u003e๋ ๋ฃจํธ ์ปจํ
์คํธ๋ก ์ธ์ํ๊ฒ ๋๋ค. ๋ฐ๋ผ์ ๋์ค์ Home๊ณผ ๊ฐ์ ํ๋ฉด์ \u003ccode\u003eindex.js\u003c/code\u003e์์ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch3 id=\"nextjs\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋ชฉ์ฐจ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-24-nextjs-static-website-4/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-28-nextjs-static-website-5/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"์ฌ์ค Next.js๋ ์ค๋ช
ํ ๊ฒ ๋ณ๋ก ์๋ค. ์์ ๋ค์ด ๋๋ฌด ์๋์ด ์๊ธฐ ๋๋ฌธ์.. ๊ทธ๋ ์ง๋ง ๋ด ๋จธ๋ฆฟ์์์ ์ฌ๋ผ์ ธ๊ฐ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ก์ด๋ผ๋ ๋จ๊ธฐ๋ ค๊ณ \n์์ฑํ๋ค.\n\n1. NPM ํ๋ก์ ํธ ์์ฑ\nํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด static-website ๋๋ ํ ๋ฆฌ๋ฅผ ํ๋ ๋ง๋ค๊ณ cd static-website๋ก ๊ฐ์ npm init์ผ๋ก npm\nํ๋ก์ ํธ๋ฅผ ๋ง๋ค์.\n\n\u003e ์ฐธ๊ณ ๋ก n...","title":"Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ","author":"salgum1114","date":"2019-05-20 12:43","tags":"react, nextjs, website","cover":"/static/images/covers/nextjs.png","next":"/etc/2019-05-20-using-openssl-in-windows","prev":"/nextjs/2019-05-21-nextjs-static-website-3"},"/etc/2019-05-20-using-openssl-in-windows":{"path":"/etc/2019-05-20-using-openssl-in-windows","content":"\u003cp\u003eํ์ฌ์์ MQTT๋ฅผ SSL/TLS๋ก ํ
์คํธํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ฒผ๋๋ฐ, ๊ธฐ์กด์ ๋์์๋ \u003ca href=\"https://mosquitto.org/\"\u003eEclipse Mosquitto\u003c/a\u003e๋ก ํ๋ ค๋ค๊ฐ ์ด์ ํ๋ ๊น์ Javascrpt๋ก MQTT Broker๋ Client (Pub, Sub)๋ฅผ ์ง์ ๊ตฌํํด๋ณด๊ธฐ๋ก ํ๋ค.\u003c/p\u003e\n\u003cp\u003e์ ์ฒด์ ์ผ๋ก MQTT Broker์ Client๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mcollina/mosca\"\u003eMosca\u003c/a\u003e (MQTT Broker) \u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/mqttjs/MQTT.js\"\u003eMQTT.js\u003c/a\u003e (MQTT Client)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e๋๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฐ๊ณ ์์ ๋ฅผ ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ github์์ ์ฌ์ฉ๋ฒ์ ์ฐพ์๋ณด๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch2 id=\"moscaserverts\"\u003eMosca ์์ (server.ts)\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e mosca \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'mosca'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { moscaSettings } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'./options'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e server = \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e mosca.Server(moscaSettings, () =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e'Mosca server is up and running'\u003c/span\u003e);\n});\n\nserver.on(\u003cspan class=\"hljs-string\"\u003e'clientConnected'\u003c/span\u003e, (client: mosca.Client) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e'Client connected'\u003c/span\u003e, client.id, \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eDate\u003c/span\u003e());\n});\n\nserver.on(\u003cspan class=\"hljs-string\"\u003e'clientDisconnected'\u003c/span\u003e, (client: mosca.Client) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e'Client Disconnected:'\u003c/span\u003e, client.id, \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eDate\u003c/span\u003e());\n});\n\nserver.on(\u003cspan class=\"hljs-string\"\u003e'published'\u003c/span\u003e, (packet: mosca.Packet, client?: mosca.Client, callback?: \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003evoid\u003c/span\u003e) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(\u003cspan class=\"hljs-string\"\u003e'Published'\u003c/span\u003e, packet.payload, client \u0026amp;\u0026amp; client.id, callback);\n});\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"mqttjspublisherts\"\u003eMQTT.js ์์ (publisher.ts)\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e mqtt \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'mqtt'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { mqttClientOptions, mqttsClientOptions } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'./options'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e client = mqtt.connect(mqttsClientOptions);\n\nclient.on(\u003cspan class=\"hljs-string\"\u003e'connect'\u003c/span\u003e, () =\u0026gt; {\n client.subscribe(\u003cspan class=\"hljs-string\"\u003e'presence'\u003c/span\u003e);\n client.publish(\u003cspan class=\"hljs-string\"\u003e'presence'\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e'Hello mqtt'\u003c/span\u003e);\n client.end();\n});\n\nclient.on(\u003cspan class=\"hljs-string\"\u003e'error'\u003c/span\u003e, (error) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(error);\n});\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"mqttjssubsriberts\"\u003eMQTT.js ์์ (subsriber.ts)\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e mqtt \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'mqtt'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { mqttClientOptions, mqttsClientOptions } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'./options'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e client = mqtt.connect(mqttsClientOptions);\n\nclient.on(\u003cspan class=\"hljs-string\"\u003e'connect'\u003c/span\u003e, () =\u0026gt; {\n client.subscribe(\u003cspan class=\"hljs-string\"\u003e'presence'\u003c/span\u003e);\n});\n\nclient.on(\u003cspan class=\"hljs-string\"\u003e'message'\u003c/span\u003e, (topic, message) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(topic, message);\n client.end();\n});\n\nclient.on(\u003cspan class=\"hljs-string\"\u003e'error'\u003c/span\u003e, (error) =\u0026gt; {\n \u003cspan class=\"hljs-built_in\"\u003econsole\u003c/span\u003e.log(error);\n});\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"optionsts\"\u003e์ต์
(options.ts)\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { IClientOptions } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'mqtt'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e fs \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'fs'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e interface ClientOptions extends IClientOptions {\n passphrase?: string;\n secureProtocol?: string;\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e interface MoscaLogger {\n name?: string;\n level?: number | string;\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e interface MoscaSecure {\n port?: number;\n keyPath?: string;\n certPath?: string;\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e interface MoscaSettings {\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: number;\n logger?: MoscaLogger;\n secure?: MoscaSecure;\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e mqttClientOptions: ClientOptions = {\n \u003cspan class=\"hljs-attr\"\u003ehost\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'localhost'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1883\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eprotocol\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'mqtt'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003econnectTimeout\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e * \u003cspan class=\"hljs-number\"\u003e1000\u003c/span\u003e,\n};\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e mqttsClientOptions: ClientOptions = {\n \u003cspan class=\"hljs-attr\"\u003ehost\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'localhost'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e8443\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eprotocol\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'mqtts'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eprotocolId\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'MQIsdp'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eprotocolVersion\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e3\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003esecureProtocol\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'TLSv1_method'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ereconnectPeriod\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e5\u003c/span\u003e * \u003cspan class=\"hljs-number\"\u003e1000\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003erejectUnauthorized\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003econnectTimeout\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e10\u003c/span\u003e * \u003cspan class=\"hljs-number\"\u003e1000\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eca\u003c/span\u003e: [fs.readFileSync(\u003cspan class=\"hljs-string\"\u003e'keystore/ca/ca.crt'\u003c/span\u003e)],\n \u003cspan class=\"hljs-attr\"\u003ekey\u003c/span\u003e: fs.readFileSync(\u003cspan class=\"hljs-string\"\u003e'keystore/client/client.key'\u003c/span\u003e),\n \u003cspan class=\"hljs-attr\"\u003ecert\u003c/span\u003e: fs.readFileSync(\u003cspan class=\"hljs-string\"\u003e'keystore/client/client.crt'\u003c/span\u003e),\n};\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e moscaSettings: MoscaSettings = {\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1883\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003elogger\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ename\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e\"secure\"\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003elevel\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e40\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003esecure\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003eport\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e8443\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ekeyPath\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'keystore/server/server.key'\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ecertPath\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'keystore/server/server.crt'\u003c/span\u003e,\n },\n};\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด์ ๋ฌธ์ ๋ Openssl ์ธ๋ฐ, Windows์์ Openssl์ ์ฌ์ฉํ๊ธฐ ์ํด 2๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e๋ฐ์ด๋๋ฆฌ๋ก ๋ฌต์ธ ๊ฒ์ ๋ค์ด๋ก๋ ๋ฐ๊ธฐ.\u003c/li\u003e\n\u003cli\u003e์์ค๋ฅผ ๋ฐ์์ ์ง์ ๋น๋ํ๊ธฐ.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e2๋ฒ์ ๊ท์ฐฎ๊ธฐ ๋๋ฌธ์, 1๋ฒ์ ์ฐพ์๋ณด๊ณ ๋ค์ด๋ก๋ ๋ฐ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ca href=\"https://code.google.com/archive/p/openssl-for-windows/downloads\"\u003ehttps://code.google.com/archive/p/openssl-for-windows/downloads\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e๋ค์ด๋ก๋ ๋ฐ๊ณ ๋๋ฉด ์์ถ์ ํผ ๊ฒฝ๋ก๋ก ๋ค์ด๊ฐ \u003ccode\u003ebin\u003c/code\u003e์์ \u003ccode\u003eWindows Command Line\u003c/code\u003e์ผ๋ก ์ง์ \u003ccode\u003eopenssl\u003c/code\u003e๋ช
๋ น์ด๋ฅผ ์น๋ฉด ๋์ง๋ง, ๋งค๋ฒ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ๋ javascript๋ก \u003ccode\u003ekeygen\u003c/code\u003e์ ๋ง๋ค์๋ค.\u003c/p\u003e\n\u003cp\u003eํ๋ก์ ํธ ๊ฒฝ๋ก๋ก ๋ง์ถฐ ๋ช
๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ํด openssl์ ์์ถ์ ํ์ด ํ๋ก์ ํธ ๋ด๋ถ๋ก ์ฎ๊ธฐ๊ณ , ๋ง์ฐฌ๊ฐ์ง๋ก openssl๋ก ์์ฑ๋ ํค์ ์ธ์ฆ์๋ฅผ ํ๋ก์ ํธ ๋ด๋ถ์ ๋๊ธฐ ์ํด ํ๋ก์ ํธ ๋ด์ \u003ccode\u003ekeystore\u003c/code\u003e ํด๋๋ฅผ ๋ง๋ ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eOpenssl๋ก ์์ฑํด์ผ๋๋ ํค์ ์ธ์ฆ์๋ ์์ฒด ์๋ช
๋ CA, Server, Client๊ฐ ๋ชจ๋ ํ์ํ๊ธฐ ๋๋ฌธ์ keystore ํ์ ํด๋๋ก ca, server, client๋ฅผ ๋ง๋ ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์์ ์์ฑ๋ MQTT Broker, Client, Options๋ฅผ ํฌํจํ์ฌ ์ด๋ ๊ฒ ์๊ธด ํด๋ ๊ตฌ์กฐ๊ฐ ์๊ธธ ๊ฒ์ด๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/openssl-project-directory.png\" alt=\"project-directory\" /\u003e\u003c/p\u003e\n\u003cp\u003e๊ทธ ๋ค์ openssl ๋ช
๋ น์ด๋ฅผ ์คํํ๊ธฐ ์ํ Keygen์ ์์ฑํ๋ค.\u003c/p\u003e\n\u003ch2 id=\"keygenkeygents\"\u003eKeygen (keygen.ts)\u003c/h2\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { execSync, ExecSyncOptions } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'child_process'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e path \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'path'\u003c/span\u003e;\n\ntype Status = \u003cspan class=\"hljs-string\"\u003e'all'\u003c/span\u003e | \u003cspan class=\"hljs-string\"\u003e'ca'\u003c/span\u003e | \u003cspan class=\"hljs-string\"\u003e'server'\u003c/span\u003e | \u003cspan class=\"hljs-string\"\u003e'client'\u003c/span\u003e | \u003cspan class=\"hljs-string\"\u003e'verify'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e argsLength = process.argv.length;\n\u003cspan class=\"hljs-keyword\"\u003elet\u003c/span\u003e status: Status = \u003cspan class=\"hljs-string\"\u003e'all'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (argsLength \u0026gt; \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e) {\n status = process.argv.slice(\u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e)[\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e] \u003cspan class=\"hljs-keyword\"\u003eas\u003c/span\u003e Status;\n}\n\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e opensslPath = \u003cspan class=\"hljs-string\"\u003e'openssl/bin/openssl'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e opensslConfPath = \u003cspan class=\"hljs-string\"\u003e`openssl/openssl.cnf`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e binPath = path.resolve(__dirname, opensslPath)\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e confPath = path.resolve(__dirname, opensslConfPath);\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e execSyncOption: ExecSyncOptions = {\n \u003cspan class=\"hljs-attr\"\u003estdio\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'inherit'\u003c/span\u003e,\n}\n\n\u003cspan class=\"hljs-comment\"\u003e/**\n * Create CA\n */\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e caKeystorePath = \u003cspan class=\"hljs-string\"\u003e'keystore/ca'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e caKeyPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${caKeystorePath}\u003c/span\u003e/ca.key`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e caCrtPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${caKeystorePath}\u003c/span\u003e/ca.crt`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (status === \u003cspan class=\"hljs-string\"\u003e'all'\u003c/span\u003e || status === \u003cspan class=\"hljs-string\"\u003e'ca'\u003c/span\u003e) {\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e req -new -x509 -days 1024 -extensions v3_ca -keyout \u003cspan class=\"hljs-subst\"\u003e${caKeyPath}\u003c/span\u003e -out \u003cspan class=\"hljs-subst\"\u003e${caCrtPath}\u003c/span\u003e -config \u003cspan class=\"hljs-subst\"\u003e${confPath}\u003c/span\u003e`\u003c/span\u003e, execSyncOption);\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (status === \u003cspan class=\"hljs-string\"\u003e'verify'\u003c/span\u003e) {\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e x509 -text -in \u003cspan class=\"hljs-subst\"\u003e${caCrtPath}\u003c/span\u003e`\u003c/span\u003e, execSyncOption) ;\n}\n\n\u003cspan class=\"hljs-comment\"\u003e/**\n * Create server key\n */\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e serverKeystorePath = \u003cspan class=\"hljs-string\"\u003e'keystore/server'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e serverKeyPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${serverKeystorePath}\u003c/span\u003e/server.key`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e serverCsrPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${serverKeystorePath}\u003c/span\u003e/server.csr`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e serverCrtPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${serverKeystorePath}\u003c/span\u003e/server.crt`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (status === \u003cspan class=\"hljs-string\"\u003e'all'\u003c/span\u003e || status === \u003cspan class=\"hljs-string\"\u003e'server'\u003c/span\u003e) {\n \u003cspan class=\"hljs-comment\"\u003e// execSync(`${binPath} genrsa -des3 -out ${serverKeyPath} 2048`, execSyncOption);\u003c/span\u003e\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e genrsa -out \u003cspan class=\"hljs-subst\"\u003e${serverKeyPath}\u003c/span\u003e 2048`\u003c/span\u003e, execSyncOption);\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e req -out \u003cspan class=\"hljs-subst\"\u003e${serverCsrPath}\u003c/span\u003e -key \u003cspan class=\"hljs-subst\"\u003e${serverKeyPath}\u003c/span\u003e -new -config \u003cspan class=\"hljs-subst\"\u003e${confPath}\u003c/span\u003e`\u003c/span\u003e, execSyncOption);\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e x509 -req -in \u003cspan class=\"hljs-subst\"\u003e${serverCsrPath}\u003c/span\u003e -CA \u003cspan class=\"hljs-subst\"\u003e${caCrtPath}\u003c/span\u003e -CAkey \u003cspan class=\"hljs-subst\"\u003e${caKeyPath}\u003c/span\u003e -CAcreateserial -out \u003cspan class=\"hljs-subst\"\u003e${serverCrtPath}\u003c/span\u003e -days 1024`\u003c/span\u003e, execSyncOption);\n}\n\n\u003cspan class=\"hljs-comment\"\u003e/**\n * Create client key\n */\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e clientKeystorePath = \u003cspan class=\"hljs-string\"\u003e'keystore/client'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e clientKeyPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${clientKeystorePath}\u003c/span\u003e/client.key`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e clientCsrPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${clientKeystorePath}\u003c/span\u003e/client.csr`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e clientCrtPath = \u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${clientKeystorePath}\u003c/span\u003e/client.crt`\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (status === \u003cspan class=\"hljs-string\"\u003e'all'\u003c/span\u003e || status === \u003cspan class=\"hljs-string\"\u003e'client'\u003c/span\u003e) {\n \u003cspan class=\"hljs-comment\"\u003e// execSync(`${binPath} genrsa -des3 -out ${clientKeyPath} 2048`, execSyncOption);\u003c/span\u003e\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e genrsa -out \u003cspan class=\"hljs-subst\"\u003e${clientKeyPath}\u003c/span\u003e 2048`\u003c/span\u003e, execSyncOption);\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e req -out \u003cspan class=\"hljs-subst\"\u003e${clientCsrPath}\u003c/span\u003e -key \u003cspan class=\"hljs-subst\"\u003e${clientKeyPath}\u003c/span\u003e -new -config \u003cspan class=\"hljs-subst\"\u003e${confPath}\u003c/span\u003e`\u003c/span\u003e, execSyncOption);\n execSync(\u003cspan class=\"hljs-string\"\u003e`\u003cspan class=\"hljs-subst\"\u003e${binPath}\u003c/span\u003e x509 -req -in \u003cspan class=\"hljs-subst\"\u003e${clientCsrPath}\u003c/span\u003e -CA \u003cspan class=\"hljs-subst\"\u003e${caCrtPath}\u003c/span\u003e -CAkey \u003cspan class=\"hljs-subst\"\u003e${caKeyPath}\u003c/span\u003e -CAcreateserial -out \u003cspan class=\"hljs-subst\"\u003e${clientCrtPath}\u003c/span\u003e -days 1024`\u003c/span\u003e, execSyncOption);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ต์ข
์ ์ผ๋ก npm script๋ฅผ ์์ฑํ๋ค.\u003c/p\u003e\n\u003ch2 id=\"packagejsonscript\"\u003epackage.json script\u003c/h2\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/openssl-npm-script.png\" alt=\"npm-script\" /\u003e\u003c/p\u003e\n\u003ch2 id=\"tldr\"\u003eTL;DR\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003enpm run keygen\u003c/code\u003e์ ์คํํ๋ฉด CA, Server, Client ์์ผ๋ก ํค์ ์ธ์ฆ์๋ฅผ ์์ฑํ๊ธฐ ์ํ ์
๋ ฅ๋ค์ด ๋์ค๊ณ ์ง๋ฌธ์ ๋ง์ถฐ ์
๋ ฅํ๋ฉด ๋๊ณ , ์ต์ข
์ ์ผ๋ก keystore ํด๋ ํ์์ ca, server, client์ ํค์ ์ธ์ฆ์๋ค์ด ์์ฑ๋๋ค.\u003c/p\u003e\n\u003cp\u003e๊ทธ๋ฐ ๋ค์, \u003ccode\u003enpm start\u003c/code\u003e, \u003ccode\u003enpm run sub\u003c/code\u003e, \u003ccode\u003enpm run pub\u003c/code\u003e์ ์คํํ์ฌ ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ ํ์ธํด๋ณด๋ฉด ๋๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/etc/openssl-mqtt-result.png\" alt=\"mqtt-result\" /\u003e\u003c/p\u003e\n\u003cp\u003e์๋ ์์ฑ๋ณธ์ ๋ฐ์์ ํ
์คํธ ํด๋ณด๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch2 id=\"\"\u003e์์ฑ๋ ์์ \u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/salgum1114/mqtt-ssl\"\u003ehttps://github.com/salgum1114/mqtt-ssl\u003c/a\u003e\u003c/p\u003e","preview":"ํ์ฌ์์ MQTT๋ฅผ SSL/TLS๋ก ํ
์คํธํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๊ฒผ๋๋ฐ, ๊ธฐ์กด์ ๋์์๋ Eclipse Mosquitto๋ก ํ๋ ค๋ค๊ฐ ์ด์ ํ๋ ๊น์\nJavascrpt๋ก MQTT Broker๋ Client (Pub, Sub)๋ฅผ ์ง์ ๊ตฌํํด๋ณด๊ธฐ๋ก ํ๋ค.\n\n์ ์ฒด์ ์ผ๋ก MQTT Broker์ Client๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋ค์๊ณผ ๊ฐ๋ค.\n\n * Mosca ...","title":"Windows์์ openssl๋ก ์ธ์ฆ์ ์์ฑํ๊ณ MQTT๋ก ํ
์คํธํ๊ธฐ","author":"salgum1114","date":"2019-05-20 10:09","tags":"openssl, typescript, mqtt","cover":"/static/images/covers/openssl.png","next":"/reactjs/2019-05-11-using-typescript-without-tsx","prev":"/nextjs/2019-05-20-nextjs-static-website-2"},"/reactjs/2019-05-11-using-typescript-without-tsx":{"path":"/reactjs/2019-05-11-using-typescript-without-tsx","content":"\u003cp\u003e์ด๋ฒ ๊ธ์์๋ ๊ธฐ์กด์ .js, .jsx ํ์ฅ์๋ก ์์ฑ๋ React ์ปดํฌ๋ํธ์์ Typescript๋ฅผ ์ ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ๋ฐ์ด๋ ์ฌ์ฉ ์์ ํ์
์ ํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eButton.js\u003c/code\u003e ์ปดํฌ๋ํธ๋ก ๊ฐ๋จํ ์๋ฅผ ๋ค์ด๋ณธ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs\"\u003esrc/\n components/\n button/\n index\u003cspan class=\"hljs-selector-class\"\u003e.js\u003c/span\u003e\n Button\u003cspan class=\"hljs-selector-class\"\u003e.js\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ตฌ์กฐ๋ก ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋์ด ์๋ค๊ณ ํ๋ค๋ฉด. ๋์ผํ ํ์ผ ๊ฒฝ๋ก์ \u003ccode\u003eindex.d.ts\u003c/code\u003e๋ฅผ ๋ง๋ค์.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs diff language-diff\"\u003esrc/\n components/\n button/\n index.js\n + index.d.ts\n Button.js\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eindex.d.ts\u003c/code\u003e์๋ \u003ccode\u003ebutton\u003c/code\u003e์ ํ์ํ \u003ccode\u003eProps\u003c/code\u003e๋ค์ Typescript๋ก ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e interface ButtonProps extends React.HTMLAttributes\u0026lt;HTMLButtonElement\u0026gt; {}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eButton\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e\u0026lt;\u003cspan class=\"hljs-title\"\u003eButtonProps\u003c/span\u003e\u0026gt; \u003c/span\u003e{}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์ด ์์ ์์๋ ๋ณ๋ค๋ฅธ Props๊ฐ ํ์์์ด Button ์ปดํฌ๋ํธ์ Typescript๋ฅผ ์์ฑํ๋๋ฐ ์ค์ ์ ๋๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e๊ทธ๋ผ ์ด์ \u003ccode\u003eButton.js\u003c/code\u003e๋ฅผ ์์ฑํ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-comment\"\u003e/**\n * @augments {Component\u0026lt;import('.').ButtonProps\u0026gt;}\n */\u003c/span\u003e\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eButton\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { children, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e}\u0026gt;\u003c/span\u003e{children}\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e;\n }\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e Button;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด๋ ๊ฒ ์์ฑ๋ \u003ccode\u003eButton.js\u003c/code\u003e ์ปดํฌ๋ํธ์ \u003ccode\u003ethis.props\u003c/code\u003e์ deconstructing ๋ถ๋ถ์์ \u003ccode\u003ectrl + space\u003c/code\u003e๋ก ํํธ๋ฅผ ์ณ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ๊ณตํ ์ ์๋ props๋ค์ด ํํธ๋ก ๋์ค๊ฒ๋๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/reactjs/define-typescript-hint.png\" alt=\"define-typescript-hint\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ด์ ์ด \u003ccode\u003eButton.js\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ง๊ณ ๋ค๋ฅธ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/reactjs/using-typescript-hint.png\" alt=\"using-typescript-hint\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ถ๊ฐ์ ์ผ๋ก \u003ccode\u003efunctional component\u003c/code\u003e์์๋ ๋ค์์ฒ๋ผ ์์ฑํ ์ ์๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-comment\"\u003e/**\n * @description\n * @param {import('.').ButtonProps} props\n * @returns {React.ReactNode}\n */\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e Button = \u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003eprops\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { children, ...other } = props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e {\u003cspan class=\"hljs-attr\"\u003e...other\u003c/span\u003e}\u0026gt;\u003c/span\u003e{children}\u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003ebutton\u003c/span\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\n )\n}\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e Button;\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eํํธ๋ ๋๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/reactjs/functional-using-typescript-hint.png\" alt=\"functional-using-typescript-hint\" /\u003e\u003c/p\u003e","preview":"์ด๋ฒ ๊ธ์์๋ ๊ธฐ์กด์ .js, .jsx ํ์ฅ์๋ก ์์ฑ๋ React ์ปดํฌ๋ํธ์์ Typescript๋ฅผ ์ ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ๋ฐ์ด๋ ์ฌ์ฉ ์์ ํ์
์\nํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.\n\nButton.js ์ปดํฌ๋ํธ๋ก ๊ฐ๋จํ ์๋ฅผ ๋ค์ด๋ณธ๋ค.\n\nsrc/\n components/\n button/\n index.js\n ...","title":"React์์ .tsx ์์ด Typescript ์ฌ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-05-11 19:50","tags":"react, typescript","cover":"/static/images/covers/react_typescript.png","next":"/nextjs/2019-05-06-nextjs-static-website-1","prev":"/etc/2019-05-20-using-openssl-in-windows"},"/nextjs/2019-05-06-nextjs-static-website-1":{"path":"/nextjs/2019-05-06-nextjs-static-website-1","content":"\u003cp\u003e\u003ca href=\"https://nextjs.org/\"\u003eNext.js\u003c/a\u003e๋ ํ์ฌ ๊ฐ์ฅ ์ ๋ช
ํ \u003ca href=\"https://reactjs.org/\"\u003eReact\u003c/a\u003e์ฉ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ํ๋ ์์ํฌ์ด๋ค.\u003c/p\u003e\n\u003cp\u003eํ๋ ์์ํฌ๋ก์จ ์ดํดํ๊ธฐ ์ฌ์ด ๊ตฌ์กฐ์ \u003ca href=\"https://github.com/zeit/next.js/tree/canary/examples\"\u003e์๋ง์ ์์ \u003c/a\u003e๋ค, ๊ทธ๋ฆฌ๊ณ ๋ค์ํ ํ๋ฌ๊ทธ์ธ๋ค์ ์ง์ํ๊ณ ์์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ์ฌ๋๋ฐ๊ณ ์๋ค.\u003c/p\u003e\n\u003cp\u003e๋ํ, Next.js๋ \u003ccode\u003enext export\u003c/code\u003e๋ผ๋ ๋ช
๋ น์ด๋ก \u003ccode\u003erouting ๊ฒฝ๋ก\u003c/code\u003e๋ก ํ์ฌ๊ธ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๊ณ ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eNext.js์ ์ต์ ๋ฒ์ ์ 8.x.x์ธ๋ฐ ์ต์ ๋ฒ์ ์์๋ export ๊ธฐ๋ฅ์ด ์ ๋๋ก ๋์ํ์ง ์์ผ๋ฉฐ, ํ์ฌ \u003ccode\u003enext export\u003c/code\u003e ๊ธฐ๋ฅ์ 7.x.x ๋ฒ์ ์์ ์๋ฌ์์ด ์ ๋์ํ๋ค. \u003ca href=\"https://github.com/zeit/next.js/issues/6251\"\u003e[Static export failed when upgraded to v8.0.0 #6251]\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์ด ๊ธ์ Next.js์ export ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋ํด์ ์ค๋ช
ํ๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์ด ๊ธ์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ด ์๋ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋๋ ๊ฒ์ ์ค์ ์ผ๋ก ์ค๋ช
ํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"nextjs\"\u003eNext.js ๊ธฐ๋ณธ ๊ตฌ์กฐ\u003c/h2\u003e\n\u003cp\u003eNext.js์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ๋ค์์ฒ๋ผ ๊ตฌ์ฑ๋๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003epages/ \u003cspan class=\"hljs-comment\"\u003e// HTML Document, Application Container, ๊ฐ์ข
ํ์ด์ง ๋ฑ์ ์์ฑํ๋ค.\u003c/span\u003e\n _document.js \u003cspan class=\"hljs-comment\"\u003e// HTML Document.\u003c/span\u003e\n _app.js \u003cspan class=\"hljs-comment\"\u003e// Application Container. ๊ณตํต์ ๋ ์ด์์์ ์์ฑํ๋ค.\u003c/span\u003e\n _error.js \u003cspan class=\"hljs-comment\"\u003e// Error Page.\u003c/span\u003e\n index.js \u003cspan class=\"hljs-comment\"\u003e// Root Page /๋ก ์์๋๋ ๊ฒฝ๋ก๋ฅผ ๋งํ๋ค.\u003c/span\u003e\n hello.js \u003cspan class=\"hljs-comment\"\u003e// Hello Page /hello๋ก ์์๋๋ ๊ฒฝ๋ก๋ฅผ ๋งํ๋ค.\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003estatic\u003c/span\u003e/ \u003cspan class=\"hljs-comment\"\u003e// ์ ์ ํ์ผ (์ด๋ฏธ์ง, ํ์ผ ๋ฑ)์ ์
๋ก๋ ํ๋ค.\u003c/span\u003e\nnext.config.js \u003cspan class=\"hljs-comment\"\u003e// Next.js์ ํ๊ฒฝ ์ค์ ํ์ผ์ด๋ค. ๋ผ์ฐํ
์ค์ , typescript, less ๋ฑ์ webpack ํ๋ฌ๊ทธ์ธ์ ์ค์ ํ๋ค.\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"_documentjs\"\u003e_document.js\u003c/h2\u003e\n\u003cp\u003e_document.js๋ SPA์์ ์์์ ์ด ๋๋ index.html์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eCustom Document๋ฅผ ๋ง๋ค๋๋ง ์์ฑ์ด ํ์ํ๋ฉฐ, ์๋ต๋ ๊ฒฝ์ฐ Next.js๊ฐ ๊ธฐ๋ณธ ๊ฐ์ ์ฌ์ฉํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์์ฑ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Document, { Head, Main, NextScript } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/document'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootDocument\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eDocument\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u0026lt;html\u0026gt;\n \u0026lt;Head\u0026gt;\n \u0026lt;meta charSet=\"utf-8\" /\u0026gt;\n \u0026lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no\" /\u0026gt;\n \u0026lt;meta name=\"description\" content=\"Dev.log\"/\u0026gt;\n \u0026lt;meta name=\"keywords\" content=\"blog,react,antd,webpack,css,javascript\" /\u0026gt;\n \u0026lt;link rel=\"manifest\" href=\"/static/manifest.json\" /\u0026gt;\n \u0026lt;link rel=\"shortcut icon\" href=\"/static/favicon.ico\" /\u0026gt;\n \u0026lt;link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/earlyaccess/notosanskr.css\" /\u0026gt;\n \u0026lt;link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/3.0.1/github-markdown.min.css\" /\u0026gt;\n \u0026lt;link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/railscasts.min.css\" /\u0026gt;\n \u0026lt;/Head\u0026gt;\n \u0026lt;body\u0026gt;\n \u0026lt;Main /\u0026gt;\n \u0026lt;NextScript /\u0026gt;\n \u0026lt;/body\u0026gt;\n \u0026lt;/html\u0026gt;\n );\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e_document.js์์ React์ ๊ฐ์ ๋์์ ์ํํ ์ ์์ ๊ฒ์ฒ๋ผ ๋ณด์ด์ง๋ง \u003ccode\u003eReact Lifecycle\u003c/code\u003e๊ณผ \u003ccode\u003eData Fetching\u003c/code\u003e์ด ๋ถ๊ฐ๋ฅํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/nextjs/document-app-differences.png\" alt=\"document-app-differences\" /\u003e\u003c/p\u003e\n\u003cp\u003eReact์์๋ \u003ccode\u003e\u0026lt;div id=\"root\" /\u0026gt;\u003c/code\u003e์ฒ๋ผ React ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋๋ ์ต์ด ์์๋ฅผ ์์ฑํ๊ฒ ๋๋ค. ํ์ง๋ง Next.js์์๋ ๋ฐ๋ก ์์ฑํ ํ์ ์์ด, \u003ccode\u003eMain\u003c/code\u003e๊ณผ \u003ccode\u003eNextScript\u003c/code\u003e ํด๋์ค์ ๋ด์ฅ ๋์ด ์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eMain\u003c/code\u003e๊ณผ \u003ccode\u003eNextScript\u003c/code\u003e์ ์์ธํ ์ค๋ช
์ ์ด ๊ธ์ ์ฐธ์กฐํ๋ค. \u003ca href=\"https://stackoverflow.com/questions/52083848/nextjs-main-and-nextscript\"\u003eNextJS: Main and Nextscript\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"_appjs\"\u003e_app.js\u003c/h2\u003e\n\u003cp\u003eReact์์ ๋๋ถ๋ถ App.js์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ๊ณตํต์ ๋ ์ด์์์ ์์ฑํ๋ฏ์ด Next.js์์๋ Application์ ๊ณตํต ๋ ์ด์์์ _app.js์์ ์์ฑํ ์ ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์๋ต๋ ๊ฒฝ์ฐ Next.js๊ฐ ๊ธฐ๋ณธ ๊ฐ์ ์ฌ์ฉํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์์ฑ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e App, { Container } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/app'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e NProgress \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'nprogress'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Router \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'next/router'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Helmet \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react-helmet'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e moment \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'moment'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e Layout \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../components/Layout'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../styles/index.less'\u003c/span\u003e;\n\nmoment.locale(\u003cspan class=\"hljs-string\"\u003e'ko'\u003c/span\u003e);\n\nRouter.events.on(\u003cspan class=\"hljs-string\"\u003e'routeChangeStart'\u003c/span\u003e, (url) =\u0026gt; NProgress.start());\nRouter.events.on(\u003cspan class=\"hljs-string\"\u003e'routeChangeComplete'\u003c/span\u003e, () =\u0026gt; NProgress.done());\nRouter.events.on(\u003cspan class=\"hljs-string\"\u003e'routeChangeError'\u003c/span\u003e, () =\u0026gt; NProgress.done());\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootApp\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eApp\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { Component, ...other } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u0026lt;Container\u0026gt;\n \u0026lt;Helmet title=\"Dev.log\" /\u0026gt;\n \u0026lt;Layout {...other} {...this.state}\u0026gt;\n \u0026lt;Component {...other} {...this.state} /\u0026gt;\n \u0026lt;/Layout\u0026gt;\n \u0026lt;/Container\u0026gt;\n );\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e์ด๊ณณ์์ ComponentDidCatch๋ก Error Handling์ ํ๋ค๋์ง, Routing์ด ๋์์ ๋์ Progressing ์ฒ๋ฆฌ, ์คํ์ผ ์ํธ Import ๋ฑ์ ์์ฑํ๋ค.\u003c/p\u003e\n\u003ch2 id=\"_errorjs\"\u003e_error.js\u003c/h2\u003e\n\u003cp\u003eError ์ฒ๋ฆฌ๋ฅผ ๊ณตํต์ผ๋ก ํ๊ณ ์ ํ ๋, ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ Error Page๋ฅผ ์์ฑํ ์ ์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์๋ต๋ ๊ฒฝ์ฐ Next.js๊ฐ ๊ธฐ๋ณธ ๊ฐ์ ์ฌ์ฉํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์์ฑ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e ErrorPage \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'../components/ErrorPage'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-keyword\"\u003eexport\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003edefault\u003c/span\u003e \u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eRootError\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n render() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { statusCode } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eErrorPage\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estatusCode\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{statusCode}\u003c/span\u003e /\u0026gt;\u003c/span\u003e;\n }\n}\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"nextconfigjs\"\u003enext.config.js\u003c/h2\u003e\n\u003cp\u003ewebpack plugin๋ค๊ณผ Next.js์ ๋ผ์ฐํ
์ค์ ์ ์์ฑํ๋ค.\u003c/p\u003e\n\u003cp\u003e์์ฑ ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e withLess = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e'@zeit/next-less'\u003c/span\u003e);\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e withTypescript = \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e(\u003cspan class=\"hljs-string\"\u003e'@zeit/next-typescript'\u003c/span\u003e);\n\n\u003cspan class=\"hljs-comment\"\u003e// fix: prevents error when .less files are required by node\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-keyword\"\u003etypeof\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e !== \u003cspan class=\"hljs-string\"\u003e'undefined'\u003c/span\u003e) {\n \u003cspan class=\"hljs-built_in\"\u003erequire\u003c/span\u003e.extensions[\u003cspan class=\"hljs-string\"\u003e'.less'\u003c/span\u003e] = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003efile\u003c/span\u003e =\u0026gt;\u003c/span\u003e {}\n}\n\n\u003cspan class=\"hljs-built_in\"\u003emodule\u003c/span\u003e.exports = withTypescript(withLess({\n \u003cspan class=\"hljs-attr\"\u003elessLoaderOptions\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ejavascriptEnabled\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003eexportPathMap\u003c/span\u003e: \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e {\n \u003cspan class=\"hljs-string\"\u003e'/'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/'\u003c/span\u003e },\n \u003cspan class=\"hljs-string\"\u003e'/about'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/about'\u003c/span\u003e },\n \u003cspan class=\"hljs-string\"\u003e'/readme.md'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/readme'\u003c/span\u003e },\n \u003cspan class=\"hljs-string\"\u003e'/p/hello-nextjs'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/post'\u003c/span\u003e, \u003cspan class=\"hljs-attr\"\u003equery\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003etitle\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'hello-nextjs'\u003c/span\u003e } },\n \u003cspan class=\"hljs-string\"\u003e'/p/learn-nextjs'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/post'\u003c/span\u003e, \u003cspan class=\"hljs-attr\"\u003equery\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003etitle\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'learn-nextjs'\u003c/span\u003e } },\n \u003cspan class=\"hljs-string\"\u003e'/p/deploy-nextjs'\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003epage\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'/post'\u003c/span\u003e, \u003cspan class=\"hljs-attr\"\u003equery\u003c/span\u003e: { \u003cspan class=\"hljs-attr\"\u003etitle\u003c/span\u003e: \u003cspan class=\"hljs-string\"\u003e'deploy-nextjs'\u003c/span\u003e } }\n },\n}));\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNext.js์ ๊ด๋ จ๋ webpack plugin๋ค์ \u003ccode\u003e@zeit/next\u003c/code\u003e Prefix๋ก ํจํค์ง๋ฅผ ์ ๊ณตํ๊ณ ์์ผ๋ฉฐ, ์ฌ์ฉํ ๋๋ \u003ccode\u003ewith\u003c/code\u003e prefix๋ก ์ ์ธํด์ ์ฌ์ฉํ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eexportPathMap\u003c/code\u003e์ด Next.js์ ๋ผ์ฐํ
๊ฒฝ๋ก์ด๋ค.\u003c/p\u003e\n\u003ch3 id=\"nextjs-1\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋ชฉ์ฐจ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-06-nextjs-static-website-1/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-20-nextjs-static-website-2/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 2. ํ๋ก์ ํธ ๊ตฌ์ฑ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-21-nextjs-static-website-3/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 3. ๋ ์ด์์\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-24-nextjs-static-website-4/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 4. Routing ์ฌ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://salgum1114.github.io/nextjs/2019-05-28-nextjs-static-website-5/\"\u003eNext.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 5. Material UI ์ ์ฉํ๊ธฐ\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"Next.js๋ ํ์ฌ ๊ฐ์ฅ ์ ๋ช
ํ React์ฉ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ํ๋ ์์ํฌ์ด๋ค.\n\nํ๋ ์์ํฌ๋ก์จ ์ดํดํ๊ธฐ ์ฌ์ด ๊ตฌ์กฐ์ ์๋ง์ ์์ ๋ค, ๊ทธ๋ฆฌ๊ณ ๋ค์ํ ํ๋ฌ๊ทธ์ธ๋ค์ ์ง์ํ๊ณ ์์ด ๋ง์ ์ฌ๋๋ค์๊ฒ ์ฌ๋๋ฐ๊ณ ์๋ค.\n\n๋ํ, Next.js๋ next export๋ผ๋ ๋ช
๋ น์ด๋ก routing ๊ฒฝ๋ก๋ก ํ์ฌ๊ธ ์ ์ ์น์ฌ์ดํธ๋ฅผ ๋ง๋ค ์ ์๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๊ณ ์๋ค.\n\n\u003e ...","title":"Next.js๋ก ์ ์ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ - 1. Next.js ๊ตฌ์กฐ","author":"salgum1114","date":"2019-05-06 19:50","tags":"react, nextjs, website","cover":"/static/images/covers/nextjs.png","next":"/reactjs/2019-05-03-medium-zoom","prev":"/reactjs/2019-05-11-using-typescript-without-tsx"},"/reactjs/2019-05-03-medium-zoom":{"path":"/reactjs/2019-05-03-medium-zoom","content":"\u003cp\u003eํ์ \u003ca href=\"https://medium.com/\"\u003eMedium\u003c/a\u003e์์ ๊ฐ๋ฐ ํฌ์คํ
์ ์ฐพ์๋ณด๋ ํธ์ธ๋ฐ, ๊ธ์์ ์ด๋ฏธ์ง๋ฅผ ํด๋ฆญํ์ ๋, ์ค์ด ๋๋ ๊ธฐ๋ฅ์ด ์ด๋ป๋ณด์ฌ์ ๋ด ๊ฐ๋ฐ ๋ธ๋ก๊ทธ์๋ ์ ์ฉํ๊ณ ์ถ์ด ๋น์ทํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ ์ฐพ์๋ณด๊ฒ ๋์๋ค.\u003c/p\u003e\n\u003cp\u003e์ฐ์ ์ด ๋ธ๋ก๊ทธ๊ฐ React๋ก ๊ฐ๋ฐํ์ผ๋ React์์ ์ฌ์ฉํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ณด๋ \u003ca href=\"https://github.com/rpearce/react-medium-image-zoom\"\u003ereact-medium-image-zoom\u003c/a\u003e์ด ์์๋ค. ํ์ง๋ง React๋ก ์์ฑํด์ผ ํ๊ธฐ ๋๋ฌธ์, ๋งํฌ๋ค์ด์ด HTML๋ก ๋ฒ์ญ๋ ์ํ์์๋ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํด ๋ณด์ธ๋ค.\u003c/p\u003e\n\u003cp\u003e์ด์๋ ๋ค๋ฅด๊ฒ querySelector๋ก \u003ccode\u003e\u0026lt;img\u0026gt;\u003c/code\u003e์์๋ค์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๊ธฐ๋ง ํ๋ฉด ์ฌ์ฉํ ์ ์๋ \u003ca href=\"https://github.com/francoischalifour/medium-zoom\"\u003emedium-zoom\u003c/a\u003e ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ca href=\"https://github.com/francoischalifour/medium-zoom\"\u003emedium-zoom\u003c/a\u003e์ ๋ํ ์ฌ์ฉ ๋ฐฉ๋ฒ์ github์ ์ ๋์์๊ณ playground๋ก ๋ฐ๋ชจ๋ฅผ ํ์ธํ ์ ์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch4 id=\"mediumzoom\"\u003emedium-zoom ์ฌ์ฉ ๋ฐฉ๋ฒ\u003c/h4\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-comment\"\u003e// CSS selector\u003c/span\u003e\nmediumZoom(\u003cspan class=\"hljs-string\"\u003e'[data-zoomable]'\u003c/span\u003e);\n\n\u003cspan class=\"hljs-comment\"\u003e// HTMLElement\u003c/span\u003e\nmediumZoom(\u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(\u003cspan class=\"hljs-string\"\u003e'#cover'\u003c/span\u003e));\n\n\u003cspan class=\"hljs-comment\"\u003e// NodeList\u003c/span\u003e\nmediumZoom(\u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelectorAll(\u003cspan class=\"hljs-string\"\u003e'[data-zoomable]'\u003c/span\u003e));\n\n\u003cspan class=\"hljs-comment\"\u003e// Array\u003c/span\u003e\n\u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e images = [\n \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(\u003cspan class=\"hljs-string\"\u003e'#cover'\u003c/span\u003e),\n ...document.querySelectorAll(\u003cspan class=\"hljs-string\"\u003e'[data-zoomable]'\u003c/span\u003e),\n];\n\nmediumZoom(images);\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n \u003cp\u003e์ถ๊ฐ์ ์ธ ์ต์
์ด ์๋๋ฐ \u003ca href=\"https://github.com/francoischalifour/medium-zoom\"\u003emedium-zoom github\u003c/a\u003e์์ ํ์ธํ์.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eReact์์ ์ฌ์ฉํ ๋๋ ๋ค์ ์ฒ๋ผ ์ฌ์ฉํ๋ฉด ๋๋ค.\u003c/p\u003e\n\u003ch4 id=\"reactmediumzoom\"\u003eReact์์ medium-zoom ์ฌ์ฉ ๋ฐฉ๋ฒ\u003c/h4\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e mediumZoom \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'medium-zoom'\u003c/span\u003e;\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eMediumZoomExample\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eReact\u003c/span\u003e.\u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e \u003c/span\u003e{\n componentDidMount() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e images = \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelectorAll(\u003cspan class=\"hljs-string\"\u003e'.example-container img'\u003c/span\u003e);\n mediumZoom(images);\n }\n\n render() {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u0026lt;div className=\"example-container\"\u0026gt;\n \u0026lt;img src=\"/test.png\" /\u0026gt;\n \u0026lt;img src=\"/test2.png\" /\u0026gt;\n \u0026lt;/div\u0026gt;\n );\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๋ธ๋ก๊ทธ์ ์ ์ฉ๋ ๊ฒฐ๊ณผ.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/reactjs/medium-zoom.gif\" alt=\"medium-zoom-apply\" /\u003e\u003c/p\u003e","preview":"ํ์ Medium์์ ๊ฐ๋ฐ ํฌ์คํ
์ ์ฐพ์๋ณด๋ ํธ์ธ๋ฐ, ๊ธ์์ ์ด๋ฏธ์ง๋ฅผ ํด๋ฆญํ์ ๋, ์ค์ด ๋๋ ๊ธฐ๋ฅ์ด ์ด๋ป๋ณด์ฌ์ ๋ด ๊ฐ๋ฐ ๋ธ๋ก๊ทธ์๋ ์ ์ฉํ๊ณ \n์ถ์ด ๋น์ทํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์๋ ์ฐพ์๋ณด๊ฒ ๋์๋ค.\n\n์ฐ์ ์ด ๋ธ๋ก๊ทธ๊ฐ React๋ก ๊ฐ๋ฐํ์ผ๋ React์์ ์ฌ์ฉํ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ณด๋ react-medium-image-zoom์ด\n์์๋ค. ํ์ง๋ง React๋ก...","title":"medium-zoom ์ ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-05-03 12:46","tags":"react, medium-zoom","cover":"/static/images/covers/medium-zoom.gif","next":"/css/2019-04-30-overscroll-behavior-contain","prev":"/nextjs/2019-05-06-nextjs-static-website-1"},"/css/2019-04-30-overscroll-behavior-contain":{"path":"/css/2019-04-30-overscroll-behavior-contain","content":"\u003cp\u003e์น์์ ์คํฌ๋กค์ ๋ค๋ฃจ๋ค๋ณด๋ฉด ํญ์ ๋ง์ฃผ์น๋ ๋ฌธ์ ์ค ํ๋๊ฐ \u003cstrong\u003e์คํฌ๋กค ์ฒด์ด๋\u003c/strong\u003e์ด๋ค.\u003c/p\u003e\n\u003cp\u003e๋ค์ ์์ ๋ฅผ ๋ณด์.\u003c/p\u003e\n\u003ciframe height=\"465\" style=\"width: 100%;\" scrolling=\"no\" title=\"overscroll-behavior: cotain before\" src=\"//codepen.io/salgum1114/embed/MRMaWX/?height=265\u0026theme-id=0\u0026default-tab=css,result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\"\u003e\n See the Pen \u003ca href='https://codepen.io/salgum1114/pen/MRMaWX/'\u003eoverscroll-behavior: cotain before\u003c/a\u003e by Sung Gyun Oh\n (\u003ca href='https://codepen.io/salgum1114'\u003e@salgum1114\u003c/a\u003e) on \u003ca href='https://codepen.io'\u003eCodePen\u003c/a\u003e.\n\u003c/iframe\u003e\n\u003cp\u003e์ ์์ ์์ Box-1์ ์คํฌ๋กค์ด ๋์ ๋๋ฌํ๊ฒ ๋๋ฉด ์์ ์์์ธ App์ ์คํฌ๋กค์ด ์์์ด๋๋ค.\u003c/p\u003e\n\u003cp\u003e์ฌ์ง์ด App์ ์คํฌ๋กค์ด ๋์ ๋๋ฌํ๊ฒ ๋๋ฉด ์ด ํฌ์คํ
์ ๋ณธ๋ฌธ๊น์ง ์คํฌ๋กค์ด ์์๋๊ฒ ๋๋ค.\u003c/p\u003e\n\u003cp\u003e์ด๋ฌํ ํ์์ \u003cstrong\u003e์คํฌ๋กค ์ฒด์ด๋\u003c/strong\u003e์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ฉฐ, ๊ตฌ๊ธ ๊ฐ๋ฐ์ ์ฌ์ดํธ์ \u003ca href=\"https://developers.google.com/web/updates/2017/11/overscroll-behavior\"\u003eTake control of your scroll: customizing pull-to-refresh and overflow effects\u003c/a\u003e์ ์ค๋ช
์ด ์ ๋์ด์๋ค.\u003c/p\u003e\n\u003cp\u003e์ฌ๊ธฐ์ ์ค๋ช
ํ๊ธธ CSS์ \u003cstrong\u003eoverscroll-behavior\u003c/strong\u003e์์ฑ์ ์ฌ์ฉํ์ฌ ์คํฌ๋กค๋ก ์ผ์ด๋ ์ ์๋ ๋ค์ํ ํ์์ ์กฐ์ ํ ์ ์๋ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e๋จ, ์ด ์์ฑ์ ๋ณธ๋ฌธ์ ์ฒซ๋ฒ์งธ ๋จ๋ฝ์ ์ฃผ์๋ก ํฌ๋กฌ 63๋ฒ์ ์ด์๋ถํฐ ์ง์ํ๋ฉฐ, ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ ๊ณ ๋ ค ์ค์ด๋ผ๊ณ ์์ฑ๋์ด์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch4 id=\"\"\u003e๋ธ๋ผ์ฐ์ ํธํ์ฑ ์ฐธ๊ณ \u003c/h4\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/css/overscroll-behavior-support.png\" alt=\"overscroll-behavior-support\" /\u003e\u003c/p\u003e\n\u003cp\u003e์ด์ ์์ ์ \u003cstrong\u003eoverscroll-behavior\u003c/strong\u003e ์์ฑ์ ์ ์ฉํ์ฌ ์คํฌ๋กค ์ฒด์ด๋ ํ์์ ํผํด๋ณด์.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eoverscroll-behavior ์์ฑ์ x, y๋ ๋ฐ๋ก ๋ค๋ฃฐ ์ ์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ciframe height=\"465\" style=\"width: 100%;\" scrolling=\"no\" title=\"overscroll-behavior: cotain after\" src=\"//codepen.io/salgum1114/embed/EJBVvq/?height=265\u0026theme-id=0\u0026default-tab=css,result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\"\u003e\n See the Pen \u003ca href='https://codepen.io/salgum1114/pen/EJBVvq/'\u003eoverscroll-behavior: cotain after\u003c/a\u003e by Sung Gyun Oh\n (\u003ca href='https://codepen.io/salgum1114'\u003e@salgum1114\u003c/a\u003e) on \u003ca href='https://codepen.io'\u003eCodePen\u003c/a\u003e.\n\u003c/iframe\u003e\n\u003cp\u003eBox-1์์ ์คํฌ๋กค์ ๋๊น์ง ๋๋ฌ์์ผ๋ณด๋ฉด ์ด์ ๊ณผ ๋ค๋ฅด๊ฒ ์์ ์์์ธ App์ ์คํฌ๋กค์ด ์์๋์ง ์์ผ๋ฉด์ ์คํฌ๋กค ์ฒด์ด๋์ ํผํ๊ฒ ๋๋ค.\u003c/p\u003e\n\u003ch4 id=\"-1\"\u003e์ฐธ๊ณ ์ฌ์ดํธ\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior\"\u003eMDN: overscroll-behavior\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://developers.google.com/web/updates/2017/11/overscroll-behavior\"\u003eGoogle Developers - Take control of your scroll: customizing pull-to-refresh and overflow effects\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","preview":"์น์์ ์คํฌ๋กค์ ๋ค๋ฃจ๋ค๋ณด๋ฉด ํญ์ ๋ง์ฃผ์น๋ ๋ฌธ์ ์ค ํ๋๊ฐ ์คํฌ๋กค ์ฒด์ด๋์ด๋ค.\n\n๋ค์ ์์ ๋ฅผ ๋ณด์.\n\nSee the Pen overscroll-behavior: cotain before by Sung Gyun Oh (@salgum1114) on \nCodePen.์ ์์ ์์ Box-1์ ์คํฌ๋กค์ด ๋์ ๋๋ฌํ๊ฒ ๋๋ฉด ์์ ์์์ธ App์ ์คํฌ๋กค์ด ์์์ด๋๋ค.\n\n...","title":"overscroll-behavior: contain ์์ฑ ์ฌ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-04-30 19:28","tags":"css, overscroll-behavior","cover":"/static/images/covers/css.png","next":"/css/2019-04-28-scroll-behavior-smooth","prev":"/reactjs/2019-05-03-medium-zoom"},"/css/2019-04-28-scroll-behavior-smooth":{"path":"/css/2019-04-28-scroll-behavior-smooth","content":"\u003cp\u003e๋ธ๋ก๊ทธ์ ๋ถ๋๋ฌ์ด ์คํฌ๋กค๋ง์ ์ํด์ CSS์ \u003ccode\u003escroll-behavior\u003c/code\u003e๋ฅผ ํ์ฉํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e์ฐ์ , \u003ccode\u003escroll-behavior\u003c/code\u003e์ด ๋ญ์ง ์์๋ณด์.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e\u003ca href=\"https://www.w3schools.com/cssref/pr_scroll-behavior.asp\"\u003ew3school: CSS scroll-behavior Property\u003c/a\u003e์ ์์ฃผ ์ ๋์์๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์ฌ์ฉ ๋ฐฉ๋ฒ์ ์์ฃผ ๊ฐ๋จํ๋ค. ์๋ ์ฝ๋๋ฅผ ํ์ธํด๋ณด์.\u003c/p\u003e\n\u003ch4 id=\"scrollbehaviorsmooth\"\u003escroll-behavior: smooth ์ ์ฉ ์ \u003c/h4\u003e\n\u003ciframe height=\"465\" style=\"width: 100%;\" scrolling=\"no\" title=\"scroll-behavior: smooth before\" src=\"//codepen.io/salgum1114/embed/ZZPBjZ/?height=265\u0026theme-id=0\u0026default-tab=html,result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\"\u003e\n See the Pen \u003ca href='https://codepen.io/salgum1114/pen/ZZPBjZ/'\u003escroll-behavior: smooth before\u003c/a\u003e by Sung Gyun Oh\n (\u003ca href='https://codepen.io/salgum1114'\u003e@salgum1114\u003c/a\u003e) on \u003ca href='https://codepen.io'\u003eCodePen\u003c/a\u003e.\n\u003c/iframe\u003e\n\u003ch4 id=\"scrollbehaviorsmooth-1\"\u003escroll-behavior: smooth ์ ์ฉ ํ\u003c/h4\u003e\n\u003ciframe height=\"465\" style=\"width: 100%;\" scrolling=\"no\" title=\"scroll-behavior: smooth\" src=\"//codepen.io/salgum1114/embed/axMmrP/?height=265\u0026theme-id=0\u0026default-tab=html,result\" frameborder=\"no\" allowtransparency=\"true\" allowfullscreen=\"true\"\u003e\n See the Pen \u003ca href='https://codepen.io/salgum1114/pen/axMmrP/'\u003escroll-behavior: smooth\u003c/a\u003e by Sung Gyun Oh\n (\u003ca href='https://codepen.io/salgum1114'\u003e@salgum1114\u003c/a\u003e) on \u003ca href='https://codepen.io'\u003eCodePen\u003c/a\u003e.\n\u003c/iframe\u003e\n\u003cblockquote\u003e\n \u003cp\u003espeed๋ฅผ ์กฐ์ ํ ์ ์๋์ง๋ ๋ชจ๋ฅด๊ฒ ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์ด์ ๋ธ๋ก๊ทธ์ ์ ์ฉ๋ ๊ฒ์ ํ์ธํด๋ณด์.\u003c/p\u003e\n\u003ch4 id=\"bottom\"\u003eBottom\u003c/h4\u003e\n\u003cp\u003e\u003ca href=\"#top\"\u003e์๋๋ก ์ด๋\u003c/a\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\n\u003cbr /\u003e\u003c/p\u003e\n\u003ch4 id=\"top\"\u003eTop\u003c/h4\u003e\n\u003cp\u003e\u003ca href=\"#bottom\"\u003e์๋ก ์ด๋\u003c/a\u003e\u003c/p\u003e","preview":"๋ธ๋ก๊ทธ์ ๋ถ๋๋ฌ์ด ์คํฌ๋กค๋ง์ ์ํด์ CSS์ scroll-behavior๋ฅผ ํ์ฉํด๋ณธ๋ค.\n\n์ฐ์ , scroll-behavior์ด ๋ญ์ง ์์๋ณด์.\n\n\u003e w3school: CSS scroll-behavior Property์ ์์ฃผ ์ ๋์์๋ค.\n\n\n์ฌ์ฉ ๋ฐฉ๋ฒ์ ์์ฃผ ๊ฐ๋จํ๋ค. ์๋ ์ฝ๋๋ฅผ ํ์ธํด๋ณด์.\n\nSCROLL-BEHAVIOR: SMOOTH ์ ์ฉ ์ \nSee...","title":"scroll-behavior: smooth ์์ฑ ์ฌ์ฉํ๊ธฐ","author":"salgum1114","date":"2019-04-28 16:28","tags":"css, scroll-behavior","cover":"/static/images/covers/css.png","next":"/reactjs/2019-04-25-back-top-component","prev":"/css/2019-04-30-overscroll-behavior-contain"},"/reactjs/2019-04-25-back-top-component":{"path":"/reactjs/2019-04-25-back-top-component","content":"\u003cp\u003e๋ธ๋ก๊ทธ ๊ฐ๋ฐ ์ค ์คํฌ๋กค์ด ๋์์ ๋, ์์๋ก ์ด๋์ํค๋ \u003ccode\u003eBackTop\u003c/code\u003e์ ์ ์ฉํ๊ธฐ ์ํด \u003ca href=\"https://ant.design/components/back-top/\"\u003eAnt.Design์ BackTop ์ปดํฌ๋ํธ\u003c/a\u003e๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๋ค.\u003c/p\u003e\n\u003cp\u003eํ์ง๋ง \u003ca href=\"https://ant.design/components/back-top/\"\u003eAnt.Design์ BackTop ์ปดํฌ๋ํธ\u003c/a\u003e๋ฅผ ์ ์ฉํด๋ณด๋ ์ ์๋๋ค. ๋ฐ๋ผ์ ์ง์ \u003ccode\u003eBackTop\u003c/code\u003e ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003eAnt.Design ํํ์ด์ง์์ ์ ๋์ํ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e๊ตฌํ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eBackTop.tsx\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003e\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e React, { Component } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'react'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e { Icon, Button } \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'antd'\u003c/span\u003e;\n\u003cspan class=\"hljs-keyword\"\u003eimport\u003c/span\u003e throttle \u003cspan class=\"hljs-keyword\"\u003efrom\u003c/span\u003e \u003cspan class=\"hljs-string\"\u003e'lodash/throttle'\u003c/span\u003e;\n\ninterface IProps {\n scrollStep?: number;\n delayMs: number;\n target: string;\n}\n\n\u003cspan class=\"hljs-class\"\u003e\u003cspan class=\"hljs-keyword\"\u003eclass\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eBackTop\u003c/span\u003e \u003cspan class=\"hljs-keyword\"\u003eextends\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003eComponent\u003c/span\u003e\u0026lt;\u003cspan class=\"hljs-title\"\u003eIProps\u003c/span\u003e\u0026gt; \u003c/span\u003e{\n private content: Element;\n private timeoutId: NodeJS.Timeout;\n private intervalId: NodeJS.Timeout;\n\n \u003cspan class=\"hljs-keyword\"\u003estatic\u003c/span\u003e defaultProps = {\n \u003cspan class=\"hljs-attr\"\u003escrollStep\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e50\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003edelayMs\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e16\u003c/span\u003e,\n }\n\n componentDidMount() {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e { target } = \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props;\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (target) {\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content = \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(target);\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content.addEventListener(\u003cspan class=\"hljs-string\"\u003e'scroll'\u003c/span\u003e, \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.onScroll);\n }\n }\n\n onScroll = throttle(\u003cspan class=\"hljs-function\"\u003e(\u003cspan class=\"hljs-params\"\u003ee\u003c/span\u003e) =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (e.target.scrollTop \u0026gt;= \u003cspan class=\"hljs-number\"\u003e64\u003c/span\u003e) {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e backtop = \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(\u003cspan class=\"hljs-string\"\u003e'.backtop'\u003c/span\u003e);\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (backtop) {\n content.classList.add(\u003cspan class=\"hljs-string\"\u003e'visible'\u003c/span\u003e);\n }\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.timeoutId) {\n clearTimeout(\u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.timeoutId);\n }\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.timeoutId = setTimeout(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (backtop) {\n backtop.classList.remove(\u003cspan class=\"hljs-string\"\u003e'visible'\u003c/span\u003e);\n }\n }, \u003cspan class=\"hljs-number\"\u003e1500\u003c/span\u003e);\n } \u003cspan class=\"hljs-keyword\"\u003eelse\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003econst\u003c/span\u003e backtop = \u003cspan class=\"hljs-built_in\"\u003edocument\u003c/span\u003e.querySelector(\u003cspan class=\"hljs-string\"\u003e'.backtop'\u003c/span\u003e);\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (backtop) {\n backtop.classList.remove(\u003cspan class=\"hljs-string\"\u003e'visible'\u003c/span\u003e);\n }\n }\n }, \u003cspan class=\"hljs-number\"\u003e200\u003c/span\u003e);\n\n scrollStep = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content.scrollTop === \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e) {\n clearInterval(\u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.intervalId);\n }\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content.scrollTo(\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e, \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content.scrollTop - \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props.scrollStep);\n }\n\n scrollToTop = \u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (\u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.content \u0026amp;\u0026amp; \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props.target) {\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.intervalId = setInterval(\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-params\"\u003e()\u003c/span\u003e =\u0026gt;\u003c/span\u003e {\n \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.scrollStep();\n }, \u003cspan class=\"hljs-keyword\"\u003ethis\u003c/span\u003e.props.delayMs);\n }\n }\n\n render() {\n \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e (\n \u003cspan class=\"xml\"\u003e\u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eButton\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eclassName\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"backtop\"\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etype\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"primary\"\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eshape\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"circle\"\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003eonClick\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{this.scrollToTop}\u003c/span\u003e\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;\u003cspan class=\"hljs-name\"\u003eIcon\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003etype\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e\"to-top\"\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003estyle\u003c/span\u003e=\u003cspan class=\"hljs-string\"\u003e{{\u003c/span\u003e \u003cspan class=\"hljs-attr\"\u003efontSize:\u003c/span\u003e '\u003cspan class=\"hljs-attr\"\u003e1.25rem\u003c/span\u003e' }} /\u0026gt;\u003c/span\u003e\n \u003cspan class=\"hljs-tag\"\u003e\u0026lt;/\u003cspan class=\"hljs-name\"\u003eButton\u003c/span\u003e\u0026gt;\u003c/span\u003e\n );\n }\n}\n\nexport default BackTop;\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003ebacktop.less\u003c/strong\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs less language-less\"\u003e\u003cspan class=\"hljs-selector-class\"\u003e.backtop\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003ewidth\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e40px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003eheight\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e40px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003eposition\u003c/span\u003e: fixed;\n \u003cspan class=\"hljs-attribute\"\u003ebottom\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e16px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003eright\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e16px\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003etransition\u003c/span\u003e: all \u003cspan class=\"hljs-number\"\u003e0.25s\u003c/span\u003e ease-in;\n \u003cspan class=\"hljs-attribute\"\u003etransform\u003c/span\u003e: translateY(\u003cspan class=\"hljs-number\"\u003e10px\u003c/span\u003e);\n \u003cspan class=\"hljs-attribute\"\u003eopacity\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e;\n \u003cspan class=\"hljs-selector-tag\"\u003e\u0026amp;\u003c/span\u003e\u003cspan class=\"hljs-selector-class\"\u003e.visible\u003c/span\u003e {\n \u003cspan class=\"hljs-attribute\"\u003eopacity\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e1\u003c/span\u003e;\n \u003cspan class=\"hljs-attribute\"\u003etransform\u003c/span\u003e: translateY(\u003cspan class=\"hljs-number\"\u003e0\u003c/span\u003e);\n }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003cstrong\u003eBackTop์ด ์ ์ฉ๋ ํ๋ฉด์ด๋ค.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/css/blog-backtop-apply.gif\" alt=\"blog-backtop-apply\" /\u003e\u003c/p\u003e","preview":"๋ธ๋ก๊ทธ ๊ฐ๋ฐ ์ค ์คํฌ๋กค์ด ๋์์ ๋, ์์๋ก ์ด๋์ํค๋ BackTop์ ์ ์ฉํ๊ธฐ ์ํด Ant.Design์ BackTop ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ \nํ๋ค.\n\nํ์ง๋ง Ant.Design์ BackTop ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํด๋ณด๋ ์ ์๋๋ค. ๋ฐ๋ผ์ ์ง์ BackTop ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.\n\n\u003e Ant.Design ํํ์ด์ง์์ ์ ๋์ํ๋ค.\n\n\n๊ตฌํ ์ฝ๋๋ ...","title":"BackTop ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ","author":"salgum1114","date":"2019-04-25 18:23","tags":"react, component, backtop","cover":"/static/images/covers/react.png","next":"/webpack/2019-04-22-uglifyjs-to-terser","prev":"/css/2019-04-28-scroll-behavior-smooth"},"/webpack/2019-04-22-uglifyjs-to-terser":{"path":"/webpack/2019-04-22-uglifyjs-to-terser","content":"\u003cp\u003e์ต๊ทผ \u003ca href=\"https://github.com/salgum1114/react-design-editor\"\u003eReact Design Editor\u003c/a\u003e์ ๋น๋ ์คํจ ๊ด๋ จ ์ด์๊ฐ ์ฌ๋ผ์๋ค.\u003c/p\u003e\n\u003cp\u003e๋ด์ฉ์ธ ์ฆ์จ, \u003ccode\u003eproduction\u003c/code\u003e์ผ๋ก ๋น๋์ UglifyJsPlugin์์ \u003ccode\u003eUnexpected token: keyword ยซconstยป\u003c/code\u003e๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ๊ณ์ํด์ ๋น๋์ ์คํจํ๋ค๋ ๊ฒ์ด๋ค.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/salgum1114/react-design-editor/issues/101\"\u003e[Bug] Not able to create build for the application #101\u003c/a\u003e\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"hljs shell language-shell\"\u003e\u003cspan class=\"hljs-meta\"\u003ereact-design-editor\u0026gt;\u003c/span\u003e\u003cspan class=\"bash\"\u003e npm run build\u003c/span\u003e\n\nreact-design-editor@0.0.1 build D:\\Projects\\VirtualTutor\\vt-bkp\\react-design-editor\nwebpack -p --config webpack.prod.js\n\nclean-webpack-plugin: D:\\Projects\\VirtualTutor\\vt-bkp\\react-design-editor\\public\\js has been removed.\nHash: 6f635a8eff2d04c3d630\nVersion: webpack 4.30.0\nTime: 28583ms\nBuilt at: 04/19/2019 4:12:58 PM\n129 assets\nEntrypoint app = js/1.784bfc366d4d89f7.js js/app.359b7dab68a97eb6.js\n[17] (webpack)/buildin/harmony-module.js 573 bytes {1} [built]\n[45] ./node_modules/rc-animate/es/Animate.js + 3 modules 17.1 KiB {1} [built]\n| 4 modules\n[65] (webpack)/buildin/global.js 472 bytes {1} [built]\n[193] (webpack)/buildin/module.js 497 bytes {1} [built]\n[557] jsdom (ignored) 15 bytes {0} {1} [built]\n[558] jsdom/lib/jsdom/living/generated/utils (ignored) 15 bytes {0} {1} [built]\n[559] jsdom/lib/jsdom/utils (ignored) 15 bytes {0} {1} [built]\n[560] xmldom (ignored) 15 bytes {0} {1} [built]\n[765] ./src/containers/App.js 3.46 KiB {0} [built]\n[845] ./src/registerServiceWorker.js 6.72 KiB {0} [built]\n[846] ./src/i18n/index.js 53 bytes {0} [built]\n[1134] multi @babel/polyfill ./src/index.js 40 bytes {0} [built]\n[1310] ./src/index.js 1.72 KiB {0} [built]\n[1705] ./node_modules/antd/es/index.js + 303 modules 1.55 MiB {1} [built]\n| 304 modules\n[1708] multi react react-dom lodash fabric antd 76 bytes {1} [built]\n+ 1694 hidden modules\n\nERROR in js/1.784bfc366d4d89f7.js from UglifyJs\nUnexpected token: keyword ยซconstยป [./node_modules/@babel/polyfill/lib/index.js:6,0][js/1.784bfc366d4d89f7.js:185555,2]\nChild html-webpack-plugin for \"index.html\":\n1 asset\nEntrypoint undefined = index.html\n[2] (webpack)/buildin/global.js 472 bytes {0} [built]\n[3] (webpack)/buildin/module.js 497 bytes {0} [built]\n+ 2 hidden modules\nnpm ERR! code ELIFECYCLE\nnpm ERR! errno 2\nnpm ERR! react-design-editor@0.0.1 build: webpack -p --config webpack.prod.js\nnpm ERR! Exit status 2\nnpm ERR!\nnpm ERR! Failed at the react-design-editor@0.0.1 build script.\nnpm ERR! This is probably not a problem with npm. There is likely additional logging output above.\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR! C:\\Users\\manish.kumar.GATEWAYGROUP\\AppData\\Roaming\\npm-cache_logs\\2019-04-19T10_42_59_421Z-debug.log\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003ebabel polyfill\u003c/code\u003e์ ๋ญ๊ฐ ์ถฉ๋๋๋ ๊ฒ ๊ฐ์ ๋์ ๋น์ทํ ์ฌ๋ก๋ฅผ ์ฐพ๊ธฐ ์ํด ๊ตฌ๊ธ๋ง์ ํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e์ต๊ทผ ์ด์๋ ์๋์ง๋ง, ๋น์ทํ ์ฌ๋ก๊ฐ ๋ง์ด ๋์จ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/webpack/uglifyjs-const-issue-search.png\" alt=\"uglify-js-issue\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/webpack-contrib/uglifyjs-webpack-plugin/issues/362\"\u003e์ฒซ๋ฒ์งธ ์ด์\u003c/a\u003e ์ฌ์ดํธ์์ ๋ด์ฉ์ ์ฝ์ด๋ณด๋, UglifyJsPlugin ๋ฒ์ 2๋ถํฐ uglify-es๊ฐ ๋ฒ๋ ค์ก์ผ๋ es6๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด terser-webpack-plugin์ ์ฌ์ฉํ๋ผ๋ ๋ด์ฉ์ธ๊ฒ ๊ฐ๋ค.\u003c/p\u003e\n\u003cp\u003e์ค์ ๋ก ํ์ธํด๋ณด๋ \u003ca href=\"https://github.com/webpack-contrib/uglifyjs-webpack-plugin/releases/tag/v2.0.0\"\u003euglifyjs-webpack-plugin ๋ฆด๋ฆฌ์ฆ ํ๊ทธ v2.0 Change Log\u003c/a\u003e์ ๋ด์ฉ์ด ์์๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/webpack/uglifyjs-v2-change-log.png\" alt=\"uglify-js-2.0\" /\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n \u003cp\u003e๊ทผ๋ฐ terser๊ฐ ๋ฌด์จ ๋ป์ด์ง? naver ์ฌ์ ์์๋ ๊ฐ๊ฒฐํ ์ด๋ผ๊ณ ๋์จ๋ค.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e์๋ฌดํผ \u003ca href=\"https://github.com/salgum1114/react-design-editor/issues/101\"\u003e์ด์\u003c/a\u003e ํด๊ฒฐ์ ์ํด \u003ccode\u003euglifyjs-webpack-plugin\u003c/code\u003e์์ \u003ccode\u003eterser-webpack-plugin\u003c/code\u003e์ผ๋ก ๋ณ๊ฒฝ์ ์๋ํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e์ฐ์ ๋ณ๊ฒฝ์ ์ํด \u003ca href=\"https://github.com/webpack-contrib/terser-webpack-plugin\"\u003eterser-webpack-plugin\u003c/a\u003e github์์ ์ฌ์ฉ๋ฐฉ๋ฒ์ ์ฐพ์๋ดค๋ค.\u003c/p\u003e\n\u003cp\u003e์ฐพ์๋ณด๋ terser-webpack-plugin๊ณผ uglifyjs-webpack-plugin์ ์ฌ์ฉ๋ฒ์ด ํฌ๊ฒ ๋ค๋ฅด์ง ์์๋ค.\u003c/p\u003e\n\u003ch3 id=\"uglifyjswebpackplugin\"\u003e๊ธฐ์กด uglifyjs-webpack-plugin ์ต์
\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003eoptimization: {\n \u003cspan class=\"hljs-attr\"\u003eminimizer\u003c/span\u003e: [\n \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e UglifyJsPlugin({\n \u003cspan class=\"hljs-attr\"\u003ecache\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eparallel\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003euglifyOptions\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ewarnings\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ecompress\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ewarnings\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eunused\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003eecma\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003emangle\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eunused\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003esourceMap\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n }),\n ],\n},\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch3 id=\"terserwebpackplugin\"\u003e๋ณ๊ฒฝํ terser-webpack-plugin ์ต์
\u003c/h3\u003e\n\u003cpre\u003e\u003ccode class=\"hljs javascript language-javascript\"\u003eoptimization: {\n \u003cspan class=\"hljs-attr\"\u003eminimizer\u003c/span\u003e: [\n \u003cspan class=\"hljs-keyword\"\u003enew\u003c/span\u003e TerserPlugin({\n \u003cspan class=\"hljs-attr\"\u003ecache\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eparallel\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eterserOptions\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ewarnings\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003ecompress\u003c/span\u003e: {\n \u003cspan class=\"hljs-attr\"\u003ewarnings\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003efalse\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eunused\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003eecma\u003c/span\u003e: \u003cspan class=\"hljs-number\"\u003e6\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003emangle\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n \u003cspan class=\"hljs-attr\"\u003eunused\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n },\n \u003cspan class=\"hljs-attr\"\u003esourceMap\u003c/span\u003e: \u003cspan class=\"hljs-literal\"\u003etrue\u003c/span\u003e,\n }),\n ],\n},\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e๊ธฐ๋ณธ์ ์ธ ์ต์
์ ๊ฐ๊ณ , \u003ccode\u003euglifyOptions\u003c/code\u003e์์ \u003ccode\u003eterserOptions\u003c/code\u003e์ผ๋ก ๋ณ๊ฒฝํ๋ฉด ๋๋ ๊ฒ ๊ฐ๋ค.\u003c/p\u003e\n\u003cp\u003e์ด์ ๋ณ๊ฒฝ๋ ์ต์
์ผ๋ก \u003ca href=\"https://github.com/salgum1114/react-design-editor\"\u003eReact Design Editor\u003c/a\u003e๋ฅผ ๋น๋ํด๋ณธ๋ค.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"/static/images/webpack/terser-webpack-plugin-build.png\" alt=\"terser-webpack-plugin-build\" /\u003e\u003c/p\u003e\n\u003ch4 id=\"\"\u003e์ฑ๊ณตํ๊ฒ ๊ฐ๋ค.\u003c/h4\u003e\n\u003cp\u003e\u003cem\u003e๋ง์ง๋ง์ผ๋ก ์์ฒญ์์๊ฒ ์ด์๋ฅผ ํด๊ฒฐํ๋ค๋ ์ฝ๋ฉํธ๋ฅผ ๋ฌ์์ฃผ๋๊ฒ์ผ๋ก ๋ง๋ฌด๋ฆฌํ๋ค.\u003c/em\u003e\u003c/p\u003e","preview":"์ต๊ทผ React Design Editor์ ๋น๋ ์คํจ ๊ด๋ จ ์ด์๊ฐ ์ฌ๋ผ์๋ค.\n\n๋ด์ฉ์ธ ์ฆ์จ, production์ผ๋ก ๋น๋์ UglifyJsPlugin์์ Unexpected token: keyword ยซconstยป๋ผ๋\n์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ๊ณ์ํด์ ๋น๋์ ์คํจํ๋ค๋ ๊ฒ์ด๋ค.\n\n[Bug] Not able to create build for the applicati...","title":"UglifyJsPlugin const ์ค๋ฅ ํด๊ฒฐ ๋ฐฉ๋ฒ","author":"salgum1114","date":"2019-04-22 21:05","tags":"webpack, uglifyjs, terser-webpack-plugin","cover":"/static/images/covers/webpack.png","next":null,"prev":"/reactjs/2019-04-25-back-top-component"}}},"authors":{"salgum1114":{"name":"salgum1114","title":"Sung Gyun Oh","avatar":"/static/images/authors/salgum1114.png","bio":"Hello world!"}},"tags":{"react":{"total":11,"paths":["/reactjs/2019-11-28-react-class-equivalents","/reactjs/2019-10-30-react-hot-loader-patch-warning","/etc/2019-10-22-react-design-editor-1","/nextjs/2019-05-28-nextjs-static-website-5","/nextjs/2019-05-24-nextjs-static-website-4","/nextjs/2019-05-21-nextjs-static-website-3","/nextjs/2019-05-20-nextjs-static-website-2","/reactjs/2019-05-11-using-typescript-without-tsx","/nextjs/2019-05-06-nextjs-static-website-1","/reactjs/2019-05-03-medium-zoom","/reactjs/2019-04-25-back-top-component"]},"react-hooks":{"total":1,"paths":["/reactjs/2019-11-28-react-class-equivalents"]},"letsencrypt":{"total":1,"paths":["/etc/2019-11-14-letsencrypt-public-ca"]},"openssl":{"total":2,"paths":["/etc/2019-11-14-letsencrypt-public-ca","/etc/2019-05-20-using-openssl-in-windows"]},"webpack":{"total":2,"paths":["/reactjs/2019-10-30-react-hot-loader-patch-warning","/webpack/2019-04-22-uglifyjs-to-terser"]},"react-hot-loader":{"total":1,"paths":["/reactjs/2019-10-30-react-hot-loader-patch-warning"]},"antd":{"total":1,"paths":["/etc/2019-10-22-react-design-editor-1"]},"fabricjs":{"total":1,"paths":["/etc/2019-10-22-react-design-editor-1"]},"react-design-editor":{"total":1,"paths":["/etc/2019-10-22-react-design-editor-1"]},"nextjs":{"total":5,"paths":["/nextjs/2019-05-28-nextjs-static-website-5","/nextjs/2019-05-24-nextjs-static-website-4","/nextjs/2019-05-21-nextjs-static-website-3","/nextjs/2019-05-20-nextjs-static-website-2","/nextjs/2019-05-06-nextjs-static-website-1"]},"website":{"total":5,"paths":["/nextjs/2019-05-28-nextjs-static-website-5","/nextjs/2019-05-24-nextjs-static-website-4","/nextjs/2019-05-21-nextjs-static-website-3","/nextjs/2019-05-20-nextjs-static-website-2","/nextjs/2019-05-06-nextjs-static-website-1"]},"typescript":{"total":2,"paths":["/etc/2019-05-20-using-openssl-in-windows","/reactjs/2019-05-11-using-typescript-without-tsx"]},"mqtt":{"total":1,"paths":["/etc/2019-05-20-using-openssl-in-windows"]},"medium-zoom":{"total":1,"paths":["/reactjs/2019-05-03-medium-zoom"]},"css":{"total":2,"paths":["/css/2019-04-30-overscroll-behavior-contain","/css/2019-04-28-scroll-behavior-smooth"]},"overscroll-behavior":{"total":1,"paths":["/css/2019-04-30-overscroll-behavior-contain"]},"scroll-behavior":{"total":1,"paths":["/css/2019-04-28-scroll-behavior-smooth"]},"component":{"total":1,"paths":["/reactjs/2019-04-25-back-top-component"]},"backtop":{"total":1,"paths":["/reactjs/2019-04-25-back-top-component"]},"uglifyjs":{"total":1,"paths":["/webpack/2019-04-22-uglifyjs-to-terser"]},"terser-webpack-plugin":{"total":1,"paths":["/webpack/2019-04-22-uglifyjs-to-terser"]}}},"page":"/","query":{},"buildId":"WBzuTPjOfilMhrb159LWu","nextExport":true};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}</script><script async="" id="__NEXT_PAGE__/" src="/_next/static/WBzuTPjOfilMhrb159LWu/pages/index.js"></script><script async="" id="__NEXT_PAGE__/_app" src="/_next/static/WBzuTPjOfilMhrb159LWu/pages/_app.js"></script><script async="" id="__NEXT_PAGE__/_error" src="/_next/static/WBzuTPjOfilMhrb159LWu/pages/_error.js"></script><script src="/_next/static/runtime/webpack-484a8928da4ec3492fcd.js" async=""></script><script src="/_next/static/chunks/commons.14799f0a166b7233d4ca.js" async=""></script><script src="/_next/static/chunks/styles.a8a2d4bb615b8dc9d9ef.js" async=""></script><script src="/_next/static/runtime/main-0463b6c82337fbcda1e9.js" async=""></script></body></html>