<![CDATA[Gatsby Advanced Blog]]><![CDATA[Gatsby Advanced Blog]]>https://wonism.github.ioRSS for NodeWed, 06 Nov 2019 14:35:11 GMT- <![CDATA[Create your own blog with Gatsby]]>https://wonism.github.io/create-blog-with-gatsby-en/https://wonism.github.io/create-blog-with-gatsby-en/Wed, 15 Aug 2018 21:24:50 GMT<p><a href="https://www.gatsbyjs.org/">Gatsby</a> is a Static site generator. (There are so many kinds of generator like Jekyll(Ruby), Hexo(Node.js), Hugo(Go), etc.) Gatsby support PWA(Progressive Web App), Hot reloading, SSR(Server Side Rendering).<br />
You can see more detailed in <a href="https://www.gatsbyjs.org/features/">this link</a>.</p>
<h2>Install Gatsby CLI and Gatsby Starter</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ npm i -g gatsby-cli
$ gatsby new <<BLOG_NAME>> https://github.com/wonism/gatsby-advanced-blog
$ cd <<BLOG_NAME>>
$ npm run dev</code></pre></div>
<h2>Basic structure of project</h2>
<p>The project has the following structure.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">src/
├── components
│ ├── ... # Many of shared sections
│ └── layout.jsx # general layout for page
├── constants
├── containers # to connect states to react component
├── html.jsx # page template for page
├── pages # pages of your web site
│ ├── 404.jsx
│ └── index.js
├── postComponents # react application that will be added in page
│ └── ...
├── resources # asset files
│ └── images
├── store # to use redux
│ ├── ...
│ └── index.js
├── templates # template for creating page with file system
│ └── ...
└── utils # utilities
└── ...</code></pre></div>
<h2>Create a post</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ mkdir src/pages/<<DIRECTORY_NAME>>
$ touch src/pages/<<DIRECTORY_NAME>>/index.md</code></pre></div>
<p>These markdown files are referred by the <code class="hljs-text">gatsby-source-filesystem</code> and converted to HTML files by <code class="hljs-text">gatsby-transformer-remark</code>.<br />
These are called at build time. You can check this <code class="hljs-text">createPages</code> in <code class="hljs-text">gatsby-node.js</code>.</p>
<h3>Caution</h3>
<p>There is a <code class="hljs-text">.sample.md</code> file in <code class="hljs-text"><<PROJECT_ROOT>>/src/pages</code>.
If you delete this file, you can not get <code class="hljs-text">category</code>, <code class="hljs-text">image</code>, etc. in <code class="hljs-text">frontmatter</code> of GraphQL query.<br />
The <code class="hljs-text">.sample.md</code> file serves as the dummy data and creates custom <code class="hljs-text">frontmatter</code> fields.</p>
<h3>The basic components of a markdown file</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/hello-world/"
category: "Sample"
tags: ["tag", "should", "be", "array"]
title: "Hello, World!"
date: "2018-08-15T00:00:00.000Z"
<span class="token title important">summary: "You can create your own blog with Gatsby!"
<span class="token punctuation">---</span></span>
Content of this page</code></pre></div>
<ul>
<li><code class="hljs-text">path</code> is a <strong>required</strong> attribute to create a page. It must be unique.</li>
<li><code class="hljs-text">category</code> allows you to create category pages and access to pages like <code class="hljs-text">/categories/<<CATEGORY_NAME>>/<<PAGE_NUMBER>></code>.</li>
<li><code class="hljs-text">tags</code> allows you to create tag pages and access to pages like <code class="hljs-text">/tags/<<TAG_NAME>>/<<PAGE_NUMBER>></code>.</li>
<li>As you can see the name oof property. <code class="hljs-text">title</code> is the title of the page, and <code class="hljs-text">summary</code> is a summary of the page. In below image, each corresponds to a red line and a blue line.</li>
<li><code class="hljs-text">date</code> is the date the post was created, and posts are sorted based on it.</li>
</ul>
<p>(You can more detailed information about the formatting in <a href="https://github.com/jonschlinkert/gray-matter">gray-matter</a>.)</p>
<div class="render-image" id="post-detail"></div>
<p>Those will be called by <code class="hljs-text">query</code> in <code class="hljs-text">src/templates/Post.jsx</code>. and you can run the query directly on <a href="http://localhost:8000/___graphql">http://localhost:8000/___graphql</a></p>
<h3>Add image into post</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md">images: ["(<<src/resources/>>)PATH_TO/IMAGE"]</code></pre></div>
<p>Use an absolute path including <code class="hljs-text">http://</code> or <code class="hljs-text">https://</code>. or use a relative path relative to <code class="hljs-text">src/resources</code>.
(On line 145 of<code class="hljs-text">components/Post/index.jsx</code>, the image is imported via <code class="hljs-text">IF CONDITION ? <<image>> : '<<src/resources/${image}>>'</code></p>
<h3>Add react application into post</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/inject-app/"
category: "Sample"
tags: ["tag", "must", "be", "array"]
title: "Injecting React application"
date: "2018-08-15T00:00:00.000Z"
summary: "You can inject react application into post"
components: [{
rootId: 'sample-component', # <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-component<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> must be in contents
fileName: 'sample', # this will render src/postComponents/sample/index.jsx
<span class="token title important">}]
<span class="token punctuation">---</span></span>
<span class="token list punctuation">1.</span> ...
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-component<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token list punctuation">2.</span> ...</code></pre></div>
<p>Put an object in the array. Object has to include the path to the file of the react application that is to be added and the ID of the tag to be rendered.<br />
Then, in the middle of the article, add the tag with this ID where you want to insert the react application.</p>
<h3>Add tweet into post</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/inject-tweet/"
category: "Sample"
tags: ["tag", "must", "be", "array"]
title: "Injecting Tweet"
date: "2018-08-15T00:00:00.000Z"
summary: "You can inject tweet into post"
tweets: [{
rootId: 'sample-tweet', # <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-tweet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> must be in contents
userId: 'twitter', # twitter user id
tweetId: '977557540199456775', # tweet id
<span class="token title important">}]
<span class="token punctuation">---</span></span>
<span class="token list punctuation">1.</span> ...
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-tweet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token list punctuation">2.</span> ...</code></pre></div>
<p>Put an object in the array. Object has to include the tweet’s ID and the author or the tweet and the ID of the tag to be rendered.<br />
You can use it as you added the react application.</p>
<h3>Add codes into post</h3>
<p>If you write the three back quote ` before and after the codes that you want to highlight, It will be highlighted by <code class="hljs-text">gatsby-remark-prismjs</code>.</p>
<h2>Add portfolios</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ mkdir src/resources/<<DIRECTORY_NAME>>
$ touch src/resources/<<DIRECTORY_NAME>>/index.md</code></pre></div>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
type: "portfolio"
title: "Gatsby Advanced Blog"
date: "2018-08-15T00:00:00.000Z"
path: "/portfolios/portfolio-1/"
images: [
"test-1/1.png",
"test-1/2.png",
<span class="token title important">]
<span class="token punctuation">---</span></span>
<span class="token title important"><span class="token punctuation">#</span> Gatsby Advanced Blog</span>
<span class="token title important"><span class="token punctuation">##</span> What I did</span>
<span class="token list punctuation">-</span> Develop Gatsby Advanced Blog
<span class="token title important"><span class="token punctuation">##</span> Libraries / Tools</span>
<span class="token list punctuation">-</span> ReactJS
<span class="token list punctuation">-</span> Redux
<span class="token list punctuation">-</span> Redux saga
<span class="token list punctuation">-</span> ...
<span class="token url">[Go to Web Site →](https://github.com/wonism/gatsby-advanced-blog)</span></code></pre></div>
<ul>
<li><code class="hljs-text">path</code> is a <strong>required</strong> attribute to create a page. It must be unique.</li>
<li><code class="hljs-text">type</code> is a value that allows you to specify the format of the page, in this case it should be <code class="hljs-text">portfolio</code>.</li>
<li><code class="hljs-text">title</code> is the title of the portfolio.</li>
<li><code class="hljs-text">images</code> are the images you want to attach to the portfolio and have the same value as the post’s. Images are rendered in the order they were added to the array.</li>
<li>Portfolios are sorted based on the <code class="hljs-text">data</code>. Give a bigger value to the portfolio to show first.</li>
</ul>
<p>Portfolios will be shown one the portfolio page. and if there are more than 4, they will be shown on the home page.<br />
(You can see it in <code class="hljs-text">src/components/Home</code> and modify how it is rendered.)</p>
<h2>Add resume</h2>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
type: "resume"
title: "Resume"
date: "2000-01-01T00:00:00.000Z"
<span class="token title important">path: "/resume/"
<span class="token punctuation">---</span></span>
<span class="token title important"><span class="token punctuation">##</span> Experience</span>
<span class="token list punctuation">-</span> Engineer at OOO ∙ 2000. 01 ~ Present
<span class="token list punctuation">-</span> Develop something
<span class="token list punctuation">-</span> Maintain something
<span class="token title important"><span class="token punctuation">##</span> Education</span>
<span class="token list punctuation">-</span> B.S. in Computer Science Engineering at OOO
<span class="token list punctuation">-</span> <span class="token list punctuation">2000.</span> 01 ~ 2000. 01
<span class="token title important"><span class="token punctuation">##</span> Projects</span>
<span class="token list punctuation">-</span> Gatsby Advanced Blog (https://github.com/wonism/gatsby-advanced-blog) ∙ 2000. 01 ~ Present
<span class="token list punctuation">-</span> Integrate Redux
<span class="token code keyword"> - Use Redux, Redux Saga, Reselect...</span>
<span class="token title important"><span class="token punctuation">##</span> Skills</span>
<span class="token list punctuation">-</span> JavaScript
<span class="token list punctuation">-</span> ES2015+
<span class="token list punctuation">-</span> ReactJS
<span class="token list punctuation">-</span> Lodash
<span class="token list punctuation">-</span> CSS
<span class="token list punctuation">-</span> SASS
<span class="token list punctuation">-</span> Less</code></pre></div>
<ul>
<li><code class="hljs-text">path</code> is a <strong>required</strong> attribute to create a page. It must be unique.</li>
<li><code class="hljs-text">type</code> is a value that allows you to specify the format of the page, in this case it should be <code class="hljs-text">portfolio</code>.</li>
</ul>
<h2>Other features</h2>
<ul>
<li>On the right side of the GNB, you can search posts by title, summary, tag, category, etc. of the post.</li>
<li>When you add codes in markdown, a button will be created automatically. If user clicks the button, user can copy the codes.</li>
</ul>
<h2>Deployment</h2>
<p>You can build the application with <code class="hljs-text">npm run build</code>.
Then you can distribute it where you want. such as <a href="https://pages.github.com/">Github Page</a>, <a href="https://aws.amazon.com/s3">AWS S3</a> or <a href="https://www.netlify.com/">Netlify</a>.</p>
- <![CDATA[React - 기본적인 이론 컨셉]]>https://wonism.github.io/react-basic/https://wonism.github.io/react-basic/Wed, 15 Aug 2018 20:34:38 GMT<p>참고 : 이 문서는 <a href="https://github.com/reactjs/react-basic">react-basic</a> 을 번역한 것으로 의역 혹은 오역이 있을 수 있음을 참고바랍니다.</p>
<p>이 문서는 필자의 React 모델에 대한 이해를 설명하기 위한 문서이다.
이 디자인을 이끄는 연역적 추론의 관점에서 이를 설명하고자 한다.</p>
<p>분명 논쟁의 여지가 있는 몇 가지 전제가 있을 수 있으며, 예제의 실제 디자인은 버그나 틈이 있을 수 있다.
이 예제는 단지 공식화의 시작이며,
어떻게 공식화하는 지에 대한 더 좋은 아이디어가 있다면 망설이지 말고 <a href="https://github.com/reactjs/react-basic/pulls">Pull Request</a>를 보내주길 바란다.
단순 > 복잡으로의 진행은 너무 많은 라이브러리 세부사항 없이도 합당해야 한다.</p>
<p>리액트의 실제 구현은 실용적인 솔루션, 점진적 단계, 알고리즘 최적화, 레거시 코드, 디버깅 툴 및 실제로 유용하게 만드는 데 필요한 것들로 구성되어있다.
그러한 것들은 순간적이며, 시간이 흐름에 따라 더 효율적이고 높은 우선 순위를 가지는 것들과 바뀔 수 있다.
실제 구현은 추론하기가 매우 어렵다.</p>
<p>나는 내가 생각할 수 있는 더 단순한 이해를 하고 싶다.</p>
<h2>변형</h2>
<p>리액트의 핵짐 전제는 UI가 단순히 데이터를 다른 형식의 데이터로 투영한다는 것이다.
동일한 입력은 항상 동일한 결과를 출력하며, 단순한 순수 함수이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">NameBox</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> fontWeight<span class="token punctuation">:</span> <span class="token string">'bold'</span><span class="token punctuation">,</span> labelContent<span class="token punctuation">:</span> name <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">'Sebastian Markbåge' ->
{ fontWeight: 'bold', labelContent: 'Sebastian Markbåge' };</code></pre></div>
<h2>추상</h2>
<p>하나의 함수에 복잡한 UI를 넣을 수 없다.
UI를 재사용 가능한 부분으로 추상화하는 것이 중요하며, 재사용 가능한 부분은 구현 세부 사항을 누설하지 않는다.
하나의 함수를 다른 함수에서 호출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">FancyUserBox</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
borderStyle<span class="token punctuation">:</span> <span class="token string">'1px solid blue'</span><span class="token punctuation">,</span>
childContent<span class="token punctuation">:</span> <span class="token punctuation">[</span>
<span class="token string">'Name: '</span><span class="token punctuation">,</span>
<span class="token function">NameBox</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">' '</span> <span class="token operator">+</span> user<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">{ firstName: 'Sebastian', lastName: 'Markbåge' } ->
{
borderStyle: '1px solid blue',
childContent: [
'Name: ',
{ fontWeight: 'bold', labelContent: 'Sebastian Markbåge' }
]
};</code></pre></div>
<h2>구성</h2>
<p>진정으로 재사용할 수 있는 기능을 구성하기 위해서는 단순히 재사용 가능한 것들을 사용하는 것만으로는 충분하지 않다.
그들을 위한 새로운 컨테이너를 구성해야 한다.
또한, 다른 추상화를 구성하는 컨테이너에서 추상화를 구성할 수 있어야 한다.
내가 구성에 대해 생각하는 방식은 둘 이상의 다른 추상화를 새로운 추상화로 결합하는 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span><span class="token parameter">children</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
borderStyle<span class="token punctuation">:</span> <span class="token string">'1px solid blue'</span><span class="token punctuation">,</span>
children<span class="token punctuation">:</span> children
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">UserBox</span><span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
<span class="token string">'Name: '</span><span class="token punctuation">,</span>
<span class="token function">NameBox</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">' '</span> <span class="token operator">+</span> user<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>상태</h2>
<p>UI는 단순히 서버와 비지니스 로직의 상태에 대한 사본이 아니다.
실제로 정확한 투영과 관련이 있는 상태가 많이 있으며, 다른 투영과는 관련이 없다.
예를 들어 텍스트 필드에 입력을 하면, 다른 탭이나 모바일 기기에 복제되거나 복제되지 않을 수 있다.
스크롤 위치는 여러 투영 사이에 거의 복제되지 않는 전형적인 예이다.</p>
<p>우리는 데이터 모델이 불변하기를 선호하는 경향이 있다.
우리는 맨 위에 있는 단일 원자로써 상태를 업데이트 할 수 있는 함수를 쓰레드한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">FancyNameBox</span><span class="token punctuation">(</span><span class="token parameter">user<span class="token punctuation">,</span> likes<span class="token punctuation">,</span> onClick</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
<span class="token string">'Name: '</span><span class="token punctuation">,</span> <span class="token function">NameBox</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">' '</span> <span class="token operator">+</span> user<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token string">'Likes: '</span><span class="token punctuation">,</span> <span class="token function">LikeBox</span><span class="token punctuation">(</span>likes<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">LikeButton</span><span class="token punctuation">(</span>onClick<span class="token punctuation">)</span>
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Implementation Details</span>
<span class="token keyword">var</span> likes <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">addOneMoreLike</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
likes<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token function">rerender</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Init</span>
<span class="token function">FancyNameBox</span><span class="token punctuation">(</span>
<span class="token punctuation">{</span> firstName<span class="token punctuation">:</span> <span class="token string">'Sebastian'</span><span class="token punctuation">,</span> lastName<span class="token punctuation">:</span> <span class="token string">'Markbåge'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
likes<span class="token punctuation">,</span>
addOneMoreLike
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>참고 : 이 예제는 상태를 업데이트하기 위해 사이드 이펙트를 사용한다.
실제 리액트의 모델은 업데이트 과정에서 다음 버전의 상태를 반환한다.
위의 코드처럼 설명하는 것이 더 간단하지만, 미래에 이 예제를 바꾸고자 한다.</p>
<h2>메모이제이션</h2>
<p>어떤 함수가 순수하다는 것을 아는 상태에서 그 함수를 반복해서 호출하는 것은 낭비이다.
마지막 인자와 마지막 결과를 추적하는 메모이즈된 버전의 함수를 만들 수 있다.
이렇게 하면 같은 값을 넘겨받는 함수를 다시 실행할 필요가 없다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">memoize</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> cachedArg<span class="token punctuation">;</span>
<span class="token keyword">var</span> cachedResult<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">arg</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>cachedArg <span class="token operator">===</span> arg<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> cachedResult<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
cachedArg <span class="token operator">=</span> arg<span class="token punctuation">;</span>
cachedResult <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> cachedResult<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> MemoizedNameBox <span class="token operator">=</span> <span class="token function">memoize</span><span class="token punctuation">(</span>NameBox<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">NameAndAgeBox</span><span class="token punctuation">(</span><span class="token parameter">user<span class="token punctuation">,</span> currentTime</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
<span class="token string">'Name: '</span><span class="token punctuation">,</span>
<span class="token function">MemoizedNameBox</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>firstName <span class="token operator">+</span> <span class="token string">' '</span> <span class="token operator">+</span> user<span class="token punctuation">.</span>lastName<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token string">'Age in milliseconds: '</span><span class="token punctuation">,</span>
currentTime <span class="token operator">-</span> user<span class="token punctuation">.</span>dateOfBirth
<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p>역자 주 : <a href="https://wonism.github.io/memoization/">메모이제이션에 대해 작성한 글</a>을 보면 더 자세히 알 수 있다.</p>
<h2>리스트</h2>
<p>대부분의 UI는 목록에 있는 각 항목에 대해 여러 값을 만드는 어떤 형태의 목록이다.
이것은 자연적인 계층 구조를 만든다.</p>
<p>목록에 있는 각 항목에 대한 상태를 관리하기 위해 특정 항목의 상태를 유지하는 <code class="hljs-text">Map</code>을 만들 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">UserList</span><span class="token punctuation">(</span><span class="token parameter">users<span class="token punctuation">,</span> likesPerUser<span class="token punctuation">,</span> updateUserLikes</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> users<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">user</span> <span class="token operator">=></span> <span class="token function">FancyNameBox</span><span class="token punctuation">(</span>
user<span class="token punctuation">,</span>
likesPerUser<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>id<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">updateUserLikes</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>id<span class="token punctuation">,</span> likesPerUser<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>user<span class="token punctuation">.</span>id<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> likesPerUser <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Map</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">updateUserLikes</span><span class="token punctuation">(</span><span class="token parameter">id<span class="token punctuation">,</span> likeCount</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
likesPerUser<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> likeCount<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">rerender</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">UserList</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>users<span class="token punctuation">,</span> likesPerUser<span class="token punctuation">,</span> updateUserLikes<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>참고 : 이제 <code class="hljs-text">FancyNameBox</code>에 전달되는 여러 다른 인자들이 있다.
여러 다른 인자들과 함께 호출되는 함수로 하여금 메모이제이션을 깨지게 하는데, 한 번에 하나의 값만 기억할 수 있기 때문이다.
아래에 더 자세한 내용이 후술된다.</p>
<h2>연속성</h2>
<p>불행히도, UI 목록에는 너무 많은 목록이 있어서 명시적으로 관리해야하는 상용구 코드가 많아진다.</p>
<p>함수의 실행을 연기함으로써 상용구 코드의 일부를 중요 비지니스 로직 바깥으로 옮기는 것이 가능하다.
예를 들어, <code class="hljs-text">Partial Application</code>을 사용할 수 있다.
그 다음, 상용구 코드로 부터 자유로워진 핵심 함수의 외부로부터 상태를 전달한다.</p>
<p>역자 주 : 원 글에서는 <code class="hljs-text">Partial Application</code>이 아닌 <code class="hljs-text">Currying</code>이라고 되어있다. 하지만 커링이라면, <code class="hljs-text">box.children(likesPerUser)(updateUserLikes)</code>과 같이 코드가 작성되어야 한다. 이 외에도 <code class="hljs-text">bind</code> 에 대한 링크가 추가되어 있는데, 별 관련성이 없다고 생각하기 때문에 제거하였다. 커링과 파셜 애플리케이션의 차이는 <a href="https://codeburst.io/javascript-currying-vs-partial-application-4db5b2442be8">Javascript- Currying VS Partial Application</a>에서 더 자세하게 볼 수 있다.</p>
<p>이것은 상용구 코드를 줄이진 않지만, 중요한 비지니스 로직 바깥으로 벗어나야 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">FancyUserList</span><span class="token punctuation">(</span><span class="token parameter">users</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span>
<span class="token function">UserList</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> users<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> box <span class="token operator">=</span> <span class="token function">FancyUserList</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>users<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> resolvedChildren <span class="token operator">=</span> box<span class="token punctuation">.</span><span class="token function">children</span><span class="token punctuation">(</span>likesPerUser<span class="token punctuation">,</span> updateUserLikes<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> resolvedBox <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token operator">...</span>box<span class="token punctuation">,</span>
children<span class="token punctuation">:</span> resolvedChildren
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>상태 Map</h2>
<p>앞서 우리는 반복되는 패턴을 볼 때 같은 패턴을 다시 구현하는 것을 피하기 위해 구성을 할 수 있다는 것을 안다.
상태를 추출하고 전달하는 로직을 재사용되는 저수준 함수로 옮길 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">FancyBoxWithState</span><span class="token punctuation">(</span>
<span class="token parameter">children<span class="token punctuation">,</span>
stateMap<span class="token punctuation">,</span>
updateState</span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span>
children<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">child</span> <span class="token operator">=></span> child<span class="token punctuation">.</span><span class="token function">continuation</span><span class="token punctuation">(</span>
stateMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>child<span class="token punctuation">.</span>key<span class="token punctuation">)</span><span class="token punctuation">,</span>
updateState
<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">UserList</span><span class="token punctuation">(</span><span class="token parameter">users</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> users<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">user</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
continuation<span class="token punctuation">:</span> <span class="token function">FancyNameBox</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> user<span class="token punctuation">)</span><span class="token punctuation">,</span>
key<span class="token punctuation">:</span> user<span class="token punctuation">.</span>id
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">FancyUserList</span><span class="token punctuation">(</span><span class="token parameter">users</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBoxWithState</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span>
<span class="token function">UserList</span><span class="token punctuation">(</span>users<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> continuation <span class="token operator">=</span> <span class="token function">FancyUserList</span><span class="token punctuation">(</span>data<span class="token punctuation">.</span>users<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">continuation</span><span class="token punctuation">(</span>likesPerUser<span class="token punctuation">,</span> updateUserLikes<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>메모이제이션 Map</h2>
<p>목록에 있는 여러 항복을 메모이즈하는 것은 상당히 어렵다.
메모리 사용량과 빈도 사이의 균형을 맞추는 복잡한 캐싱 알고리즘을 찾아야 한다.</p>
<p>다행히도, UI는 동일한 위치에서 안정되려는 경향이 있다.
트리의 같은 위치는 항상 같은 값을 가지며, 이 트리는 메모이제이션에 유용한 전략임이 밝혀졌다.</p>
<p>우리는 상태에 사용했던 것과 동일한 트릭을 사용할 수 있으며, 구성 가능한 함수를 통해 메모이제이션 캐시를 전달할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">memoize</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">arg<span class="token punctuation">,</span> memoizationCache</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>memoizationCache<span class="token punctuation">.</span>arg <span class="token operator">===</span> arg<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> memoizationCache<span class="token punctuation">.</span>result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span><span class="token punctuation">;</span>
memoizationCache<span class="token punctuation">.</span>arg <span class="token operator">=</span> arg<span class="token punctuation">;</span>
memoizationCache<span class="token punctuation">.</span>result <span class="token operator">=</span> result<span class="token punctuation">;</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">FancyBoxWithState</span><span class="token punctuation">(</span>
<span class="token parameter">children<span class="token punctuation">,</span>
stateMap<span class="token punctuation">,</span>
updateState<span class="token punctuation">,</span>
memoizationCache</span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span>
children<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">child</span> <span class="token operator">=></span> child<span class="token punctuation">.</span><span class="token function">continuation</span><span class="token punctuation">(</span>
stateMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>child<span class="token punctuation">.</span>key<span class="token punctuation">)</span><span class="token punctuation">,</span>
updateState<span class="token punctuation">,</span>
memoizationCache<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>child<span class="token punctuation">.</span>key<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> MemoizedFancyNameBox <span class="token operator">=</span> <span class="token function">memoize</span><span class="token punctuation">(</span>FancyNameBox<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>대수학 효과</h2>
<p>여러 수준의 추상화를 통해 필요한 모든 작은 값을 전달하는 것은 PITA와 같은 것으로 밝혀졌다.
중간 생성자를 포함하지 않은 채 두 추상화 사이에서 무언가를 전달하기 위한 지름길을 갖는 것이 때때로 바람직하다.
리액트에서는 이것을 <code class="hljs-text">컨텍스트</code>라고 부른다.</p>
<p>역자 주 : PITA의 뜻이 뭔지 찾아봤는데, 알아내지 못했다. 원문은 다음과 같다.<br />
It turns out that it is kind of a PITA to pass every little value you might need through several levels of abstractions.</p>
<p>때로는 데이터 종속성이 추상화 트리를 완전히 따르지 않는 경우가 있다.
예를 들어, 레이아웃 알고리즘에서 하위의 크기를 알아야 그들의 위치를 완전하게 이행할 수 있다.</p>
<p>이제, 이 예제는 조금 바깥에 있다.
<a href="https://esdiscuss.org/topic/one-shot-delimited-continuations-with-effect-handlers">ECMAScript</a>에 제안된 <a href="http://math.andrej.com/eff/">대수학 효과</a>를 사용하겠다.
함수형 프로그래밍에 익숙하다면 모나드에 의해 부과된 중간 식을 피할 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">ThemeBorderColorRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">FancyBox</span><span class="token punctuation">(</span><span class="token parameter">children</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> color <span class="token operator">=</span> raise <span class="token keyword">new</span> <span class="token class-name">ThemeBorderColorRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
borderWidth<span class="token punctuation">:</span> <span class="token string">'1px'</span><span class="token punctuation">,</span>
borderColor<span class="token punctuation">:</span> color<span class="token punctuation">,</span>
children<span class="token punctuation">:</span> children
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">BlueTheme</span><span class="token punctuation">(</span><span class="token parameter">children</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token function">children</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> effect ThemeBorderColorRequest <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token punctuation">,</span> continuation<span class="token punctuation">]</span> <span class="token punctuation">{</span>
<span class="token function">continuation</span><span class="token punctuation">(</span><span class="token string">'blue'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">BlueTheme</span><span class="token punctuation">(</span>
<span class="token function">FancyUserList</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span>users<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
- <![CDATA[Gatsby로 블로그 만들기]]>https://wonism.github.io/create-blog-with-gatsby/https://wonism.github.io/create-blog-with-gatsby/Wed, 15 Aug 2018 03:39:28 GMT<p><a href="https://www.gatsbyjs.org/">Gatsby</a>는 React를 기반으로 한 정적 사이트 생성기(Jekyll(Ruby), Hexo(Node.js), Hugo(Go) 등이 있다.)이며, PWA, Hot reloading, SSR 등 다양한 기능을 제공한다. 더 자세한 내용은 이 <a href="https://www.gatsbyjs.org/features/">링크</a>에서 참고할 수 있다.</p>
<h2>Gatsby CLI와 Gatsby 스타터 다운받기</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ npm i -g gatsby-cli
$ gatsby new <<BLOG_NAME>> https://github.com/wonism/gatsby-advanced-blog
$ cd <<BLOG_NAME>>
$ npm run dev</code></pre></div>
<h2>기본 구조 살펴보기</h2>
<p>프로젝트는 다음과 같은 구조로 이루어져있다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">src/
├── components
│ ├── ... # Many of shared sections
│ └── layout.jsx # general layout for page
├── constants
├── containers # to connect states to react component
├── html.jsx # page template for page
├── pages # pages of your web site
│ ├── 404.jsx
│ └── index.js
├── postComponents # react application that will be added in page
│ └── ...
├── resources # asset files
│ └── images
├── store # to use redux
│ ├── ...
│ └── index.js
├── templates # template for creating page with file system
│ └── ...
└── utils # utilities
└── ...</code></pre></div>
<h2>Post 작성하기</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ mkdir src/pages/<<DIRECTORY_NAME>>
$ touch src/pages/<<DIRECTORY_NAME>>/index.md</code></pre></div>
<p>이 마크다운 파일들은 <code class="hljs-text">gatsby-source-filesystem</code>에 의해 불려지게 되며, <code class="hljs-text">gatsby-transformer-remark</code> 에 의해 HTML 파일로 변환된다.<br />
이들은 빌드 타임에 호출되며, <code class="hljs-text">gatsby-node.js</code>의 <code class="hljs-text">createPages</code>를 참고하면 된다.</p>
<h3>주의 사항</h3>
<p><code class="hljs-text"><<PROJECT_ROOT>>/src/pages</code> 경로에 <code class="hljs-text">.sample.md</code> 파일이 있는데, 이 파일을 지우면 GraphQL 쿼리의 <code class="hljs-text">frontmatter</code> 프로퍼티의 <code class="hljs-text">category</code>, <code class="hljs-text">images</code> 등을 가져올 수 없다는 에러가 발생한다.<br />
<code class="hljs-text">.sample.md</code> 파일은 더미 데이터의 역할을 하여 <code class="hljs-text">frontmatter</code>의 필드를 생성한다고 보면 된다.</p>
<h3>마크다운 파일의 기본 구성 요소</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/hello-world/"
category: "Sample"
tags: ["tag", "should", "be", "array"]
title: "Hello, World!"
date: "2018-08-15T00:00:00.000Z"
<span class="token title important">summary: "You can create your own blog with Gatsby!"
<span class="token punctuation">---</span></span>
Content of this page</code></pre></div>
<ul>
<li><code class="hljs-text">path</code>는 페이지를 생성하기 위해 <strong>반드시</strong> 필요한 속성으로 값은 유일한 값을 가져야 한다.</li>
<li><code class="hljs-text">category</code>는 카테고리 페이지를 생성하게 해주며, <code class="hljs-text">/categories/<<CATEGORY_NAME>>/<<PAGE_NUMBER>></code>와 같은 페이지에 접근할 수 있게 된다.</li>
<li><code class="hljs-text">tags</code>는 태그 페이지를 생성하게 해주며, <code class="hljs-text">/tags/<<TAG_NAME>>/<<PAGE_NUMBER>></code>와 같은 페이지에 접근할 수 있게 된다.</li>
<li><code class="hljs-text">title</code>는 페이지의 제목, <code class="hljs-text">summary</code>는 페이지의 요약된 내용이다. 아래 이미지에서 각각 빨간 줄과 파란 줄에 해당된다.</li>
<li><code class="hljs-text">date</code>는 글이 작성된 날짜로 포스트들은 이 값을 기반으로 정렬된다.</li>
</ul>
<p>(이는 <a href="https://github.com/jonschlinkert/gray-matter">gray-matter</a>를 참고하면 더 자세한 작동 원리를 알 수 있다.)</p>
<div class="render-image" id="post-detail"></div>
<p>이 값들은 <code class="hljs-text">src/templates/Post.jsx</code>의 <code class="hljs-text">query</code>에 의해 불려지게 되며, <a href="http://localhost:8000/___graphql">http://localhost:8000/___graphql</a> 에서 쿼리를 직접 실행해볼 수 있다.</p>
<h3>포스트에 이미지 추가하기</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md">images: ["(<<src/resources/>>)PATH_TO/IMAGE"]</code></pre></div>
<p><code class="hljs-text">http://</code>혹은 <code class="hljs-text">https://</code>를 포함한 절대경로를 사용하거나, <code class="hljs-text">src/resources</code>를 기준으로 한 상대경로를 할당해준다.</p>
<p>(<code class="hljs-text">components/Post/index.jsx</code>의 145번째 줄을 보면, <code class="hljs-text">IF CONDITION ? <<image>> : '<<src/resources/${image}>>'</code>와 같이 이미지를 불러온다.)</p>
<h3>포스트에 리액트 애플리케이션 추가하기</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/inject-app/"
category: "Sample"
tags: ["tag", "must", "be", "array"]
title: "Injecting React application"
date: "2018-08-15T00:00:00.000Z"
summary: "You can inject react application into post"
components: [{
rootId: 'sample-component', # <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-component<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> must be in contents
fileName: 'sample', # this will render src/postComponents/sample/index.jsx
<span class="token title important">}]
<span class="token punctuation">---</span></span>
<span class="token list punctuation">1.</span> ...
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-component<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token list punctuation">2.</span> ...</code></pre></div>
<p>추가할 리액트 애플리케이션의 파일의 경로와, 렌더될 태그의 ID 값을 포함한 객체를 배열 안에 넣어준다.<br />
그리고 글 중간에 리액트 애플리케이션을 삽입하고 싶은 곳에 이 ID를 가진 태그를 추가해준다.</p>
<h3>포스트에 트윗 추가하기</h3>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
path: "/inject-tweet/"
category: "Sample"
tags: ["tag", "must", "be", "array"]
title: "Injecting Tweet"
date: "2018-08-15T00:00:00.000Z"
summary: "You can inject tweet into post"
tweets: [{
rootId: 'sample-tweet', # <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-tweet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> must be in contents
userId: 'twitter', # twitter user id
tweetId: '977557540199456775', # tweet id
<span class="token title important">}]
<span class="token punctuation">---</span></span>
<span class="token list punctuation">1.</span> ...
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sample-tweet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token list punctuation">2.</span> ...</code></pre></div>
<p>추가할 트윗을 작성한 사람과 해당 트윗의 ID, 그리고 렌더될 태그의 ID 값을 포함한 객체를 배열 안에 넣어준다.<br />
그리고 리액트 애플리케이션을 삽입했던 것처럼 사용하면 된다.</p>
<h3>포스트에 코드 추가하기</h3>
<p>하이라이팅을 하고자 하는 코드의 앞 뒤로 `를 연달아 3개를 붙여넣어주면, <code class="hljs-text">gatsby-remark-prismjs</code>에 의해 하이라이팅이 된다.</p>
<h2>포트폴리오 추가하기</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ mkdir src/resources/<<DIRECTORY_NAME>>
$ touch src/resources/<<DIRECTORY_NAME>>/index.md</code></pre></div>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
type: "portfolio"
title: "Gatsby Advanced Blog"
date: "2018-08-15T00:00:00.000Z"
path: "/portfolios/portfolio-1/"
images: [
"test-1/1.png",
"test-1/2.png",
<span class="token title important">]
<span class="token punctuation">---</span></span>
<span class="token title important"><span class="token punctuation">#</span> Gatsby Advanced Blog</span>
<span class="token title important"><span class="token punctuation">##</span> What I did</span>
<span class="token list punctuation">-</span> Develop Gatsby Advanced Blog
<span class="token title important"><span class="token punctuation">##</span> Libraries / Tools</span>
<span class="token list punctuation">-</span> ReactJS
<span class="token list punctuation">-</span> Redux
<span class="token list punctuation">-</span> Redux saga
<span class="token list punctuation">-</span> ...
<span class="token url">[Go to Web Site →](https://github.com/wonism/gatsby-advanced-blog)</span></code></pre></div>
<ul>
<li><code class="hljs-text">path</code>는 페이지를 생성하기 위해 <strong>반드시</strong> 필요한 속성으로 값은 유일한 값을 가져야 한다.</li>
<li><code class="hljs-text">type</code>은 페이지의 형식을 지정할 수 있는 값으로 여기에서는 <code class="hljs-text">portfolio</code>라고 할당한다.</li>
<li><code class="hljs-text">title</code>는 포트폴리오의 제목이다.</li>
<li><code class="hljs-text">images</code>는 포트폴리오에 첨부하고자 하는 이미지들로, 포스트와 같은 형태의 값을 가진다. 이미지는 배열에 추가된 순서로 렌더링이 된다.</li>
<li>포트폴리오들은 <code class="hljs-text">data</code> 값을 기반으로 정렬된다. 우선적으로 보여줄 포트폴리오에 큰 값을 준다.</li>
</ul>
<p>포트폴리오는 포트폴레오 페이지에서 보여지게 되며, 포트폴리오가 4개 이상일 경우 홈페이지 메인에서도 보여지게 된다.<br />
(<code class="hljs-text">src/components/Home</code>에서 확인할 수 있으며, 어떻게 렌더링할 지는 수정하면 된다.)</p>
<h2>Resume 추가하기</h2>
<div class="gatsby-highlight" data-language="md"><pre class="hljs-md"><code class="hljs-md"><span class="token hr punctuation">---</span>
type: "resume"
title: "Resume"
date: "2000-01-01T00:00:00.000Z"
<span class="token title important">path: "/resume/"
<span class="token punctuation">---</span></span>
<span class="token title important"><span class="token punctuation">##</span> Experience</span>
<span class="token list punctuation">-</span> Engineer at OOO ∙ 2000. 01 ~ Present
<span class="token list punctuation">-</span> Develop something
<span class="token list punctuation">-</span> Maintain something
<span class="token title important"><span class="token punctuation">##</span> Education</span>
<span class="token list punctuation">-</span> B.S. in Computer Science Engineering at OOO
<span class="token list punctuation">-</span> <span class="token list punctuation">2000.</span> 01 ~ 2000. 01
<span class="token title important"><span class="token punctuation">##</span> Projects</span>
<span class="token list punctuation">-</span> Gatsby Advanced Blog (https://github.com/wonism/gatsby-advanced-blog) ∙ 2000. 01 ~ Present
<span class="token list punctuation">-</span> Integrate Redux
<span class="token code keyword"> - Use Redux, Redux Saga, Reselect...</span>
<span class="token title important"><span class="token punctuation">##</span> Skills</span>
<span class="token list punctuation">-</span> JavaScript
<span class="token list punctuation">-</span> ES2015+
<span class="token list punctuation">-</span> ReactJS
<span class="token list punctuation">-</span> Lodash
<span class="token list punctuation">-</span> CSS
<span class="token list punctuation">-</span> SASS
<span class="token list punctuation">-</span> Less</code></pre></div>
<ul>
<li><code class="hljs-text">path</code>는 페이지를 생성하기 위해 <strong>반드시</strong> 필요한 속성으로 값은 유일한 값을 가져야 한다.</li>
<li><code class="hljs-text">type</code>은 페이지의 형식을 지정할 수 있는 값으로 여기에서는 <code class="hljs-text">resume</code>라고 할당한다.</li>
</ul>
<h2>기타 기능</h2>
<ul>
<li>GNB의 오른쪽에선 포스트의 제목, 요약된 내용, 태그, 카테고리 등으로 검색을 할 수 있다.</li>
<li>코드를 추가하면, 코드를 복사할 수 있는 버튼이 자동으로 생성된다.</li>
</ul>
<h2>배포</h2>
<p><code class="hljs-text">npm run build</code>를 통해 애플리케이션을 빌드하고,
<a href="https://pages.github.com/">Github Page</a> 또는 <a href="https://aws.amazon.com/s3">AWS S3</a>, <a href="https://www.netlify.com/">Netlify</a> 등 자신이 원하는 곳에 배포하면 된다.</p>
- <![CDATA[React를 실질적으로 제어하는 updater]]>https://wonism.github.io/react-updater/https://wonism.github.io/react-updater/Wed, 15 Aug 2018 02:00:56 GMT<p><code class="hljs-text">node_modules</code>에서 <code class="hljs-text">react</code> 모듈의 내용을 보면, <code class="hljs-text">react</code>는 추상 클래스의 모음이고, 실제 중요한 로직들은 대부분 <code class="hljs-text">react-reconsiler</code>, <code class="hljs-text">react-dom</code> 등 안에 구현되어 있다.<br />
이번 글에서 알아보고자 하는 <code class="hljs-text">updater</code>(<code class="hljs-text">UpdateQueue</code>)는 <code class="hljs-text">setState</code> 및 <code class="hljs-text">forceUpdate</code> 등에 사용된다.</p>
<p>(이 글은 React 16.4.1 버전을 기준으로 작성되었다.)</p>
<p><code class="hljs-text">react</code>의 <code class="hljs-text">Component</code>를 살펴보면, <code class="hljs-text">updater</code>가 사용된다는 것을 살펴볼 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/**
* Base class helpers for the updating state of a component.
*/</span>
<span class="token keyword">function</span> <span class="token function">Component</span><span class="token punctuation">(</span><span class="token parameter">props<span class="token punctuation">,</span> context<span class="token punctuation">,</span> updater</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>props <span class="token operator">=</span> props<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>context <span class="token operator">=</span> context<span class="token punctuation">;</span>
<span class="token comment">// If a component has string refs, we will assign a different object later.</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>refs <span class="token operator">=</span> emptyObject<span class="token punctuation">;</span>
<span class="token comment">// We initialize the default updater but the real one gets injected by the</span>
<span class="token comment">// renderer.</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>updater <span class="token operator">=</span> updater <span class="token operator">||</span> ReactNoopUpdateQueue<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>UpdateQueue</h2>
<p><code class="hljs-text">updater</code>는 <code class="hljs-text">react-reconsiler</code>의 <code class="hljs-text">ReactUpdateQueue</code>에서 살펴볼 수 있다.<br />
이 파일에서 export 되는 <code class="hljs-text">UpdateQueue</code>는 우선 순위가 지정된 업데이트의 링크드 리스트이다.</p>
<p>이들은 (일종의 이중 버퍼링으로) 현 상태 큐와 작업 진행 중 큐로 구성이 되며, 이 각 큐는 다음과 같은 특징을 가진다.</p>
<ul>
<li>현 상태 큐 : 화면 내 가시 상태를 나타낸다.</li>
<li>작업 진행 중 큐 : 커밋되기 전에 비동기적으로 변형되거나 처리될 수 있다. (만약, 작업 진행 중 렌더가 끝나기 전에 버려진다면, 현 상태 큐를 복제함으로써 새로운 작업 진행 중 큐를 만들게 된다.)</li>
</ul>
<p>여기서 위 두 가지 큐는 영속적이고, 단일 링크된 리스트 구조를 공유한다.<br />
이 때, 업데이트를 스케줄링하려면,</p>
<ol>
<li>두 큐의 끝 부분에 업데이트를 추가한다.</li>
<li>각 큐는 <code class="hljs-text">아직 처리되지 않은 영속적인 리스트</code>에서의 첫 업데이트에 대한 포인터를 관리한다.</li>
<li>작업 진행 중 포인터는 항상 현 상태 큐와 같거나 큰 위치를 갖게 된다.</li>
<li>현 상태 큐의 포인터는 커밋 단계 안에서<strong>만</strong> 업데이트가 이루어진다.</li>
</ol>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">A - B - C - D - E - F (현재 상태 포인터)
D - E - F (작업 진행 중 포인터)
^
작업 진행 중 큐는 현 상태 큐보다 많은 업데이트를 처리했다.</code></pre></div>
<p>업데이트를 하기 위해 두 개의 큐를 사용하는 이유는 업데이트의 손실 등을 방지하기 위함이다.<br /></p>
<p>만약,</p>
<ol>
<li>작업 진행 중 큐에<strong>만</strong> 업데이트를 추가한다면, 현재 상테 렌더를 복제함으로써 작업 진행 중 렌더를 재시작 할 때마다 어떤 업데이트들이 없어질 수 있다.</li>
<li>현재 큐에<strong>만</strong> 업데이트를 추가한다면, 이미 진행 중인 큐가 커밋되고 현재 큐와 교체될 때마다 업데이트가 없어질 것이다.</li>
</ol>
<p>하지만, 두 큐 모두에 업데이트를 추가함으로써 업데이트가 다음 작업 진행 중에 있도록 보장할 수 있으며,<br />
이 때, 진행 중 작업 큐가 커밋되면 현재 상태 큐가 되기 때문에 업데이트가 중복 발생할 일이 없다.</p>
<h3>업데이트 우선순위</h3>
<p>업데이트는 우선 순위별로 정렬되지 않고, 삽입에 의해 정렬된다.<br />
새 업데이트는 항상 리스트의 마지막에 추가되지만, 우선순위는 업데이트 처리에 중요한 영향을 미친다.</p>
<p>렌더 단계동안 업데이트 큐를 처리할 때, 충분한 우선순위를 가진 업데이트만 처리가 된다.<br />
우선 순위가 충분하지 않은 업데이트는 처리되지 않고 큐에 남아있다가, 나중에 처리가 된다.<br />
(이 때, 생략된 업데이트 이후의 모든 업데이트는 우선순위에 상관 없이 큐에 남아있게 된다.)</p>
<p>이 말은 우선 순위가 높은 업데이트는 두 개의 별도 우선 순위에서 두 번 처리될 수 있다는 뜻이다.<br />
이 때, 리액트는 큐 안에 있는 첫 번째 업데이트가 적용되기 전의 상태를 추적한다.</p>
<p>이는 아래 도식을 통해 설명할 수 있다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">업데이트 큐
A1 - B2 - C1 - D2</code></pre></div>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">기본 상태
''</code></pre></div>
<p>이 때, 숫자는 우선 순위를 나타내며, 업데이트는 이전 상태에 문자를 추가함으로써 적용이 된다.</p>
<p>리액트는 이러한 업데이트를 두 개의 별도 우선 순위 별 렌더로 처리한다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">우선 순위 1의 첫 번째 렌더링
상태의 변화 :
'' -> 'AC'
처리될 업데이트 :
[A1, C1]</code></pre></div>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">우선 순위 2의 두 번째 렌더링
상태의 변화 :
'A' -> 'ABCD'
처리될 업데이트 :
[B2, C1, D2]</code></pre></div>
<p>기본 상태는 <code class="hljs-text">C1</code>을 포함하지 않는데, <code class="hljs-text">B2</code>가 생략되었기 때문이다.
<code class="hljs-text">C1</code>은 <code class="hljs-text">B2</code>위에 리베이스된다.</p>
<p>이처럼, 삽입 순서로 업데이트를 처리하고, 앞선 업데이트가 생략될 때 우선 순위가 높은 업데이트를 리배이스하기 때문에 우선 순위에 상관 없이 최종 결과가 결정된다.
(중간 상태는 시스템 자원에 따라 달라질 수 있지만, 최종 상태는 항상 동일하다.)</p>
<h2>참고</h2>
<ul>
<li><a href="https://github.com/facebook/react/blob/master/packages/react-reconciler/README.md">Github Repository : react-reconciler</a></li>
</ul>
<h2>더 알아보기</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=nLF0n9SACd4">Youtube : Dan Abramov: Beyond React 16 | JSConf Iceland 2018</a></li>
</ul>
- <![CDATA[JavaScript Generator 이해하기]]>https://wonism.github.io/javascript-generator/https://wonism.github.io/javascript-generator/Wed, 08 Aug 2018 00:35:14 GMT<h2>Generator Function</h2>
<p><code class="hljs-text">Generator Function</code>는 사용자의 요구에 따라 다른 시간 간격으로 여러 값을 반환할 수 있으며, 내부 상태를 관리할 수 있는 함수이며, <code class="hljs-text">function* generatorFunction() { /* ... */ }</code>와 같이 사용한다.</p>
<p>단 한 번의 실행으로 함수의 끝까지 실행이 완료되는 일반 함수와는 달리,<br />
제너레이터 함수는 사용자의 요구에 따라 (<code class="hljs-text">yield</code>와 <code class="hljs-text">next</code>를 통해) 일시적으로 정지될 수도 있고, 다시 시작될 수도 있다.<br />
또한, 제너레이터 함수의 반환으로는 제너레이터가 반환된다.</p>
<h2>Generator</h2>
<p><code class="hljs-text">Generator</code>는 이 제너레이터 함수의 반환으로 iterable 프로토콜과 iterator 프로토콜을 따르는 객체이다.<br />
이 때, 제너레이터의 이터러블에서 반환하는 이터레이터는 자기 자신이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">generatorFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> generator <span class="token operator">=</span> <span class="token function">generatorFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
generator <span class="token operator">===</span> generator<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 이 말인 즉슨, 제너레이터의 이터러블은 다음과 같은 방식으로 구현되어 있을 거라는 것을 암시한다.</span>
<span class="token comment">// generator[Symbol.iterator] = () => this;</span></code></pre></div>
<h2>yield / next</h2>
<p><code class="hljs-text">yield</code>는 제너레이터 함수의 실행을 일시적으로 정지시키며, <code class="hljs-text">yield</code> 뒤에 오는 표현식은 제너레이터의 caller에게 반환된다.<br />
즉, 일반 함수의 <code class="hljs-text">return</code>과 매우 유사하다고 볼 수 있다.</p>
<p>여기서 제너레이터 함수는 Callee이고, 이를 호출하는 함수가 Caller이며, Caller는 Callee의 <code class="hljs-text">yield</code> 부분에서 다음 statement로 진행을 할 지 여부를 제어한다. 이는 <code class="hljs-text">next</code>로 인해 재개될 수 있다.</p>
<p><code class="hljs-text">yield</code>와 <code class="hljs-text">next</code>의 관계를 보고 이러한 의문이 생길 수 있다. <code class="hljs-text">모든 yield를 처리하기 위해 그만큼의 next를 사용해야 하나?</code><br />
그럴 수도 있고, 아닐 수도 있다.</p>
<p><code class="hljs-text">next</code>를 일일이 호출하지 않고, programmitically하게 호출하게 하려면, 다음과 같이 재귀 호출을 하면 된다.<br />
아래 예제 코드는 홀수는 그대로 출력을 하고, 짝수에는 <code class="hljs-text">1</code>을 더하여 출력하는 Runner이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">sampleGFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">yield</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">yield</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">yield</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token parameter">gen</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> it <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">iterate</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> value<span class="token punctuation">,</span> done <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>done<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>value <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">iterate</span><span class="token punctuation">(</span>it<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>value <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token function">iterate</span><span class="token punctuation">(</span>it<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>it<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">run</span><span class="token punctuation">(</span>sampleGFunction<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 11</span>
<span class="token comment">// 5</span>
<span class="token comment">// 1</span></code></pre></div>
<h2>제너레이터 함수에서의 return</h2>
<p><code class="hljs-text">return</code>은 수행되고 있는 이터레이터를 종료시키며, <code class="hljs-text">return</code> 뒤에 오는 값은 <code class="hljs-text">IteratorResult</code> 객체의 <code class="hljs-text">value</code> 프로퍼티에 할당되며, <code class="hljs-text">done</code> 프로퍼티는 <code class="hljs-text">true</code>가 할당된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">sampleGFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> generator <span class="token operator">=</span> <span class="token function">sampleGFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>generator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 42, done: true }</span></code></pre></div>
<h2>제너레이터 종료하기</h2>
<p>제너레이터에는 <code class="hljs-text">next</code> 외에도 <code class="hljs-text">throw</code>, <code class="hljs-text">return</code> 등의 메소드가 있는데, 이 <code class="hljs-text">return</code>과 <code class="hljs-text">throw</code>를 통해 제너레이터를 종료할 수 있다. 다만, 이 둘은 조금의 차이가 있다.</p>
<h3>return</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'[ENTERED]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> i<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'[ERROR]'</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> withReturn <span class="token operator">=</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturn<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturn<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturn<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturn<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturn<span class="token punctuation">.</span><span class="token function">return</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [ENTERED]</span>
<span class="token comment">// { value: 0, done: false }</span>
<span class="token comment">// { value: 1, done: false }</span>
<span class="token comment">// { value: 2, done: false }</span>
<span class="token comment">// { value: 3, done: false }</span>
<span class="token comment">// { value: 42, done: true }</span></code></pre></div>
<p><code class="hljs-text">return</code>이 호출되고 나면, <code class="hljs-text">value</code>에는 <code class="hljs-text">return</code>의 인자가 할당되고, <code class="hljs-text">done</code>은 <code class="hljs-text">true</code>가 된다.</p>
<h3>return with try/finally</h3>
<p><code class="hljs-text">return</code>메소드가 호출되었을 때 제너레이터 함수의 코드가 <code class="hljs-text">try / finally</code> 안에 있으면, 시퀸스가 종료되지 않는다.<br />
<code class="hljs-text">return</code> 이후 <code class="hljs-text">finally</code>블록의 <code class="hljs-text">yield</code> 표현식이 실행되며, 시퀸스는 결국 <code class="hljs-text">return</code>에 전달된 값으로 종료된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">oneToX</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token number">4</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">yield</span> <span class="token number">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> withReturnWithFinally <span class="token operator">=</span> <span class="token function">oneToX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturnWithFinally<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 1, done: false }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturnWithFinally<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 2, done: false }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturnWithFinally<span class="token punctuation">.</span><span class="token function">return</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 3, done: false }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturnWithFinally<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 4, done: false }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withReturnWithFinally<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { value: 6, done: true }</span></code></pre></div>
<h3>throw</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> withThrow <span class="token operator">=</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrow<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrow<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrow<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrow<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrow<span class="token punctuation">.</span><span class="token function">throw</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [ENTERED]</span>
<span class="token comment">// { value: 0, done: false }</span>
<span class="token comment">// { value: 1, done: false }</span>
<span class="token comment">// { value: 2, done: false }</span>
<span class="token comment">// { value: 3, done: false }</span>
<span class="token comment">// { value: undefined, done: true }</span></code></pre></div>
<p><code class="hljs-text">throw</code>가 호출되고 나면, <code class="hljs-text">catch</code> 블록에 <code class="hljs-text">throw</code>의 인자가 전달된다.</p>
<h3>throw with yield</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">decrement</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'[ENTERED]'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> i<span class="token operator">--</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> e<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> withThrowWithYield <span class="token operator">=</span> <span class="token function">decrement</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">throw</span><span class="token punctuation">(</span><span class="token number">Infinity</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>withThrowWithYield<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [ENTERED]</span>
<span class="token comment">// { value: 0, done: false }</span>
<span class="token comment">// { value: -1, done: false }</span>
<span class="token comment">// { value: -2, done: false }</span>
<span class="token comment">// { value: -3, done: false }</span>
<span class="token comment">// { value: Infinity, done: false }</span>
<span class="token comment">// { value: undefined, done: true }</span></code></pre></div>
<p><code class="hljs-text">catch</code>에서 <code class="hljs-text">yield</code>를 사용하게 되면, <code class="hljs-text">next</code>를 <code class="hljs-text">n</code> 번 더 사용할 때까지 이터레이터는 끝나지 않는다.</p>
<h2>yield*</h2>
<p><code class="hljs-text">yield</code>에 <code class="hljs-text">*</code>를 붙여 사용하게 되면, <code class="hljs-text">yield*</code>와 함께 표현된 이터러블 객체를 순회하게 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">iterableYield</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> a<span class="token punctuation">;</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=></span> el <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">10</span> <span class="token operator">**</span> a<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> b <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> b<span class="token punctuation">;</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=></span> el <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">10</span> <span class="token operator">**</span> b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> c <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> c<span class="token punctuation">;</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=></span> el <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token number">10</span> <span class="token operator">**</span> c<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token parameter">gen</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> it <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">iterate</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> value<span class="token punctuation">,</span> done <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">{</span> value<span class="token punctuation">,</span> done <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>done<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">iterate</span><span class="token punctuation">(</span>it<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>it<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">run</span><span class="token punctuation">(</span>iterableYield<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { value: 1, done: false }</span>
<span class="token comment">// { value: 10, done: false }</span>
<span class="token comment">// { value: 20, done: false }</span>
<span class="token comment">// { value: 30, done: false }</span>
<span class="token comment">// { value: 2, done: false }</span>
<span class="token comment">// { value: 100, done: false }</span>
<span class="token comment">// { value: 200, done: false }</span>
<span class="token comment">// { value: 300, done: false }</span>
<span class="token comment">// { value: 3, done: false }</span>
<span class="token comment">// { value: 1000, done: false }</span>
<span class="token comment">// { value: 2000, done: false }</span>
<span class="token comment">// { value: 3000, done: false }</span>
<span class="token comment">// { value: undefined, done: true }</span></code></pre></div>
<h2>다른 Generator Function에 컨텍스트 위임하기</h2>
<p>제너레이터는 앞서 살펴본 <code class="hljs-text">yield*</code>를 통해 다른 제너레이터 함수를 실행할 수 있다.
이 때, 아래 예제에서 <code class="hljs-text">innerGenerator</code> 를 호출하면 객체가 반환되지만, 실제로 <code class="hljs-text">innerGenerator</code>가 실행되지는 않는다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">innerGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">,</span> <span class="token string">'c'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> innerGen <span class="token operator">=</span> <span class="token function">innerGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Did nothing</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>innerGen<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">innerGenerator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">[</span><span class="token operator">...</span><span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// [1, 2, 3, 'a', 'b', 'c']</span></code></pre></div>
<h2>Iterable한 Generator</h2>
<p>여기까지의 설명으로 보아 제너레이터는 이터러블한 것을 알 수 있을 것이다.<br />
따라서, <code class="hljs-text">for..of</code> 반복문을 통해 제너레이터를 순회할 수 있으며, <code class="hljs-text">...</code> 연산자를 사용할 수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">generateName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token string">'W'</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token string">'O'</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token string">'N'</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token string">'I'</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token string">'S'</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token string">'M'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// for..of</span>
<span class="token keyword">const</span> genForForOf <span class="token operator">=</span> <span class="token function">generateName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token keyword">of</span> genForForOf<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// W</span>
<span class="token comment">// O</span>
<span class="token comment">// N</span>
<span class="token comment">// I</span>
<span class="token comment">// S</span>
<span class="token comment">// M</span>
<span class="token comment">// ...</span>
<span class="token keyword">const</span> genForSpread <span class="token operator">=</span> <span class="token function">generateName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">...</span>genForSpread<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ['W', 'O', 'N', 'I', 'S', 'M']</span></code></pre></div>
<h2>기타</h2>
<p>제너레이터를 사용한 라이브러리는 <a href="http://github.com/tj">TJ</a>의 <a href="https://github.com/tj/co">co</a>, Node.js의 프레임워크 중 하나인 <a href="https://koajs.com/">Koa</a>, 비동기 처리를 위한 리덕스 미들웨어인 <a href="https://github.com/redux-saga/redux-saga">Redux Saga</a> 등이 있다.</p>
<h2>참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators">MDN : Iterators and generators</a></li>
<li><a href="http://exploringjs.com/es6/ch_generators.html">Exploring JS: Generators</a></li>
</ul>
- <![CDATA[JavaScript iterables와 iterator 이해하기]]>https://wonism.github.io/javascript-iteration-protocol/https://wonism.github.io/javascript-iteration-protocol/Wed, 08 Aug 2018 00:28:31 GMT<h2>Iteration</h2>
<p>Iteration 프로토콜에는 두 가지 프로토콜이 있다. 한 가지는 <code class="hljs-text">iterable</code> 프로토콜이고 또 다른 한 가지는 <code class="hljs-text">iterator</code> 프로토콜이다.<br />
ES2015에서 추가된 이 두 가지는 새로운 빌트인 혹은 구문이 아닌 프로토콜 즉, 규약이다. 이들은 같은 규칙을 준수하는 객체에 의해 구현될 수 있다.</p>
<h2>Iterables</h2>
<p><code class="hljs-text">iterable</code> 프로토콜은 반복 가능한 객체를 나타내는 프로토콜로 <code class="hljs-text">for..of</code> 등에서 반복되는 행동을 정의하는 객체를 <code class="hljs-text">반복 가능</code>하다고 한다.<br />
반복 가능한 객체로는 내장 객체인 <code class="hljs-text">Array</code>, <code class="hljs-text">Map</code>, <code class="hljs-text">Set</code>, <code class="hljs-text">String</code> 등이 있다. 또한, <code class="hljs-text">[Symbol.iterator]</code>라는 키를 가진다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// example of usage</span>
<span class="token keyword">const</span> iterator <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token comment">// 1</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token comment">// 2</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token comment">// 3</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>done<span class="token punctuation">;</span> <span class="token comment">// true</span></code></pre></div>
<p>반복가능한 객체를 만들기 위해서는 <code class="hljs-text">[Symbol.iterator]</code>라는 키에 <code class="hljs-text">next</code>라는 메소드를 가지는 객체를 반환하는 함수를 할당한다. 이 때, 이 함수의 반환 값은 <code class="hljs-text">value</code> 프로퍼티를 가진 객체이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
<span class="token function-variable function">next</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> value<span class="token punctuation">:</span> i<span class="token operator">++</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> v <span class="token keyword">of</span> iterator<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Infinity loop</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p>하지만, 이런 경우는 시퀸스가 무한하기 때문에 <code class="hljs-text">for..of</code> 루프 사용 시 조건문을 사용해야 한다.</p>
<h2>Iterator</h2>
<p><code class="hljs-text">iterator</code> 프로토콜은 반복 가능한 객체의 값을 시퀸스대로 처리하는 프로토콜로 다음은 iterator 에 대한 설명이다.</p>
<ol>
<li>컬렉션 내의 항목에 대해 한 번에 하나씩 접근하면서 현재의 위치를 추적하는 방법을 알고 있는 객체</li>
<li>반복 가능 인터페이스에 의해 반환되는 객체</li>
</ol>
<p>iterator 객체는 <code class="hljs-text">next</code> 메소드를 통해 다음 시퀸스를 진행하게 된다. 이 메소드는 위에서 살펴본 대로 <code class="hljs-text">value</code>와 <code class="hljs-text">done</code>을 가진 객체를 리턴한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
<span class="token function-variable function">next</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> value<span class="token punctuation">:</span> i<span class="token operator">++</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> iterator <span class="token operator">=</span> obj<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token comment">// 0</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span> <span class="token comment">// 1</span>
<span class="token comment">// ...</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">MDN : Iteration protocols</a></li>
</ul>
- <![CDATA[JavaScript Decorator 이해하기]]>https://wonism.github.io/what-is-decorator/https://wonism.github.io/what-is-decorator/Mon, 06 Aug 2018 19:48:56 GMT<h2>Descriptor</h2>
<p>데코레이터를 이해하기 전에 <code class="hljs-text">설명자</code>(<code class="hljs-text">Descriptor</code>)에 대해 먼저 알아야 한다.<br />
설명자는 자바스크립트 객체의 프로퍼티로 프로퍼티가 쓰기 가능한지 열거 가능한지 여부를 나타낸다.<br />
간단한 객체를 만든 뒤, 프로퍼티를 추가하면 각 프로퍼티는 기본 프로퍼티 설명자를 가진다.</p>
<p>프로퍼티의 설명자를 구하기 위해서는 <code class="hljs-text">Object.getOwnPropertyDescriptor(obj, propName)</code> 메소드를 사용해야 한다.
이 때, 2번째 인자인 <code class="hljs-text">propName</code>은 객체인 <code class="hljs-text">obj</code>의 속성이며 프로토타입 체인에 속하지 않아야 한다.<br />
이 메소드는 프로퍼티의 현재 값, 권한 등을 가지는 객체를 돌려주며, 사용 예는 다음과 같다.
(이외에도 값을 반환하거나 변경하는 함수인 <code class="hljs-text">get</code>과 <code class="hljs-text">set</code> 인자가 있지만, 선택사항이다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
num<span class="token punctuation">:</span> <span class="token number">42</span><span class="token punctuation">,</span>
str<span class="token punctuation">:</span> <span class="token string">'e'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>Object<span class="token punctuation">.</span><span class="token function">getOwnPropertyDescriptor</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">'num'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { value: 42, writable: true, enumerable: true, configurable: true }</span></code></pre></div>
<p>객체에 새 속성을 부여하기 위해서 <code class="hljs-text">obj.propName = value;</code>와 같은 방식을 사용하기도 하지만, <code class="hljs-text">Object.defineProperty</code> 메소드를 사용하기도 한다.
이 때, 메소드의 결과값은 1번째 인자의 객체이다.</p>
<p><strong>writable</strong>
<code class="hljs-text">writable</code>은 객체의 프로퍼티가 쓰기 가능한 지의 여부이며, <code class="hljs-text">false</code>일 경우 값 쓰기가 안 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
num<span class="token punctuation">:</span> <span class="token number">100</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">'num'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> writable<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// you can also pass the `value` in 3rd parameter</span>
obj<span class="token punctuation">.</span>num <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { num: 100 }</span></code></pre></div>
<p><strong>enumerable</strong>
<code class="hljs-text">enumerable</code>은 객체의 프로퍼티가 열거 가능한 지의 여부이며, <code class="hljs-text">false</code>일 경우 <code class="hljs-text">Object.keys</code>에서 해당 프로퍼티를 볼 수 없다.<br />
(<code class="hljs-text">Object.values</code>, <code class="hljs-text">Object.entries</code>도 마찬가지이다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
num<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">'num'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> enumerable<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// []</span>
Object<span class="token punctuation">.</span><span class="token function">values</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// []</span>
Object<span class="token punctuation">.</span><span class="token function">entries</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// []</span></code></pre></div>
<p><strong>configurable</strong>
<code class="hljs-text">configurable</code>은 객체의 프로퍼티가 <code class="hljs-text">defineProperty</code>를 통해 설정 될 수 있는 지의 여부이며, <code class="hljs-text">false</code>일 경우 <code class="hljs-text">Object.defineProperty</code>로 해당 프로퍼티를 수정할 수 없다.<br />
이는 주로 사용자가 객체의 행동을 수정하지 못 하게 할 때 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
num<span class="token punctuation">:</span> <span class="token number">5</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">'num'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> writable<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> configurable<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> <span class="token string">'num'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> writable<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Uncaught TypeError</span></code></pre></div>
<p><strong>getter/setter</strong>
<code class="hljs-text">get</code>(<code class="hljs-text">getter</code>)나 <code class="hljs-text">set</code>(<code class="hljs-text">setter</code>)는 주로 동적으로 계산된 값을 반환하는 프로퍼티에 접근해야하는 경우 또는 명시적인 메소드 호출을 사용하지 않고도 내부 변수의 상태에 접근하는 경우 등에 사용한다.</p>
<p>이 때, 다음과 같은 주의사항이 있다.</p>
<ul>
<li>식별자는 숫자 혹은 문자열이다.</li>
<li><code class="hljs-text">getter</code>는 오직 0개 혹은 1 개의 인자를 가질 수 있으며, <code class="hljs-text">setter</code>는 오직 1개의 인자를 가질 수 있다.</li>
<li>중복되는 프로퍼티는 금지된다.</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> car <span class="token operator">=</span> <span class="token punctuation">{</span>
model<span class="token punctuation">:</span> <span class="token string">'x5'</span><span class="token punctuation">,</span>
maker<span class="token punctuation">:</span> <span class="token string">'bmw'</span><span class="token punctuation">,</span>
color<span class="token punctuation">:</span> <span class="token string">'white'</span><span class="token punctuation">,</span>
<span class="token comment">/*
get detail() {
return `${this.color} ${this.model}`
},
set detail(desc = '') {
const [color, model] = desc.split(' ');
this.color = color;
this.model = model;
}
*/</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
car<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>car<span class="token punctuation">,</span> <span class="token string">'detail'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token function-variable function">get</span><span class="token punctuation">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>model<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function-variable function">set</span><span class="token punctuation">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">desc</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>color<span class="token punctuation">,</span> model<span class="token punctuation">]</span> <span class="token operator">=</span> desc<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">' '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>color <span class="token operator">=</span> color<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>model <span class="token operator">=</span> model<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
car<span class="token punctuation">.</span>detail<span class="token punctuation">;</span> <span class="token comment">// white x5</span>
car<span class="token punctuation">;</span> <span class="token comment">// { model: 'x5', maker: 'bmw', color: 'white' }</span>
car<span class="token punctuation">.</span>detail <span class="token operator">=</span> <span class="token string">'red x3'</span><span class="token punctuation">;</span>
car<span class="token punctuation">.</span>detail<span class="token punctuation">;</span> <span class="token comment">// red x3</span>
car<span class="token punctuation">;</span> <span class="token comment">// { model: 'x3', maker: 'bmw', color: 'red' }</span></code></pre></div>
<h2>Decorator</h2>
<p><code class="hljs-text">장식자</code>는 클래스 프로퍼티나 메소드 혹은 클래스 자체를 수정하는 데 사용되는 자바스크립트 함수이다. (순수 함수로 작성되는 것이 좋다.)<br />
문법은 <code class="hljs-text">@decoratorFunction</code>과 같으며 클래스의 프로퍼티, 메소드, 클래스 자신의 바로 윗줄에 추가해준다.</p>
<p>또한, 장식자는 장식자가 적용된 메소드가 호출되거나, 클래스 인스턴스가 만들어지는 등 런타임에 실행된다.</p>
<p>위 함수는 추후 메소드에 @chaining 형식으로 사용될 함수입니다. @과 함께 함수가 호출되는 경우 받게 되는 파라미터는 다음과 같습니다.</p>
<p>target : 속성을 정의하고자 하는 객체
name : 속성의 이름
descriptor : 새로 정의하고자 하는 속성에 대한 설명</p>
<h3>Environments</h3>
<p>트랜스파일러인 <a href="http://babeljs.io/">babel</a>과 플러그인 등을 설치한다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text"># install packages
$ npm i -D @babel/cli @babel/node @babel/core @babel/plugin-proposal-decorators
# create .babelrc
$ echo "{ \"plugins\": [ [\"@babel/plugin-proposal-decorators\", { \"legacy\": true }] ] }" > .babelrc
# run babel-node
$ ./node_modules/.bin/babel-node ./FILE</code></pre></div>
<h3>Class method decorator</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">readOnly</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> property<span class="token punctuation">,</span> descriptor</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// with new Person, target will be an instance of Person</span>
descriptor<span class="token punctuation">.</span>writable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> descriptor<span class="token punctuation">;</span> <span class="token comment">// this function MUST return descriptor</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">firstName<span class="token punctuation">,</span> lastName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> firstName<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>lastName <span class="token operator">=</span> lastName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@readOnly
<span class="token function">getFullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>firstName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>lastName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// create instance</span>
<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'John'</span><span class="token punctuation">,</span> <span class="token string">'Doe'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span><span class="token function">getFullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Person.prototype.getFullName = () => 'CRACKED';</span></code></pre></div>
<p><strong>참고 : 인자를 포함한 장식자</strong>
<a href="/closure/">클로저</a>를 이용해 인자를 가지는 장식자를 정의할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">logger</span> <span class="token operator">=</span> <span class="token parameter">msg</span> <span class="token operator">=></span>
<span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> property<span class="token punctuation">,</span> descriptor</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> method <span class="token operator">=</span> descriptor<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
<span class="token comment">// do NOT use arrow function in here. to bind `this`</span>
descriptor<span class="token punctuation">.</span><span class="token function-variable function">value</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'[LOG]'</span><span class="token punctuation">,</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token function">method</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> descriptor<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">readOnly</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> property<span class="token punctuation">,</span> descriptor</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
descriptor<span class="token punctuation">.</span>writable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> descriptor<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">firstName<span class="token punctuation">,</span> lastName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> firstName<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>lastName <span class="token operator">=</span> lastName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@<span class="token function">logger</span><span class="token punctuation">(</span><span class="token string">'call getFullName method on Person'</span><span class="token punctuation">)</span>
@readOnly
<span class="token function">getFullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>firstName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>lastName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// create instance</span>
<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'John'</span><span class="token punctuation">,</span> <span class="token string">'Doe'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span><span class="token function">getFullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>Class instance field decorator</h3>
<p>클래스 인스턴스의 필드 장식자를 만드는 것은 까다롭다. 클래스 인스턴스 필드는 클래스의 일부나 프로토타입이 아니기 때문이다.<br />
(인스턴스 필드 장식자는 실험적이기 때문에 stage 4로 넘어갈 때까지 구문이 변경될 가능성이 있다. 참고 : <a href="https://tc39.github.io/proposal-decorators/">Decorators proposal</a>)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">toPascalCase</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> property<span class="token punctuation">,</span> descriptor</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> value <span class="token operator">=</span> descriptor<span class="token punctuation">.</span><span class="token function">initializer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
descriptor<span class="token punctuation">.</span><span class="token function-variable function">initializer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> value<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex">/(\w)(\w*)/g</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">$<span class="token number">0</span><span class="token punctuation">,</span> $<span class="token number">1</span><span class="token punctuation">,</span> $<span class="token number">2</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>$<span class="token number">1.</span><span class="token function">toUpperCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> $<span class="token number">2.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> descriptor<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
@toPascalCase
firstName <span class="token operator">=</span> <span class="token string">'jane'</span><span class="token punctuation">;</span>
@toPascalCase
lastName <span class="token operator">=</span> <span class="token string">'doe'</span><span class="token punctuation">;</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">firstName<span class="token punctuation">,</span> lastName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>firstName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> firstName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>lastName<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>lastName <span class="token operator">=</span> lastName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">getFullName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>firstName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>lastName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Person { firstName: "Jane", lastName: "Doe" }</span></code></pre></div>
<h3>Class decorator</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">withDob</span> <span class="token operator">=</span> <span class="token parameter">PersonRef</span> <span class="token operator">=></span>
<span class="token keyword">class</span> <span class="token class-name">extends</span> PersonRef <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>dob <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">setDob</span><span class="token punctuation">(</span><span class="token parameter">dob</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>dob <span class="token operator">=</span> dob<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
@withDob
<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">firstName<span class="token punctuation">,</span> lastName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> firstName<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>lastName <span class="token operator">=</span> lastName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'Jaewon'</span><span class="token punctuation">,</span> <span class="token string">'Kim'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span><span class="token function">setDob</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token string">'1990-02-05'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="https://codeburst.io/javascript-object-property-attributes-ac012be317e2">JavaScript — Property Descriptor</a></li>
<li><a href="https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841">Exploring EcmaScript Decorators</a></li>
<li><a href="https://github.com/wycats/javascript-decorators">Github repository : wycats/javascript-decorators</a></li>
</ul>
- <![CDATA[Virtual DOM 살펴보기]]>https://wonism.github.io/deep-dive-into-vdom/https://wonism.github.io/deep-dive-into-vdom/Fri, 18 May 2018 00:13:41 GMT<h2>Virtual DOM 의 컨셉</h2>
<p>가상 DOM은 크게 두 가지 컨셉을 가진다.</p>
<ol>
<li>가상 DOM은 실제 DOM의 표현 방법이다.</li>
<li>가상 DOM 트리에서 무엇인가 변경되면 새로운 트리를 얻게된다.
알고리즘은 두 트리를 비교하여 변경점을 찾고, 실제 DOM 변경에 필요한
최소한의 변경만을 수행한다. (참고로, 리액트의 트리 변경 알고리즘의 Big O는 O(n)이다.)</li>
</ol>
<h2>DOM 트리의 표현</h2>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>first<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>second<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>third<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre></div>
<p>위와 같은 DOM 트리는 다음과 같은 자바스크립트 객체로 표현할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'ul'</span><span class="token punctuation">,</span>
props<span class="token punctuation">:</span> <span class="token punctuation">{</span>
id<span class="token punctuation">:</span> <span class="token string">'list'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
children<span class="token punctuation">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'li'</span><span class="token punctuation">,</span>
props<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
children<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'first'</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'li'</span><span class="token punctuation">,</span>
props<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
children<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'second'</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'li'</span><span class="token punctuation">,</span>
props<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
children<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'third'</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span></code></pre></div>
<p>간단한 DOM 트리 구조는 쉽게 구현할 수 있지만, 복잡한 DOM 트리구조라면 구현하기 어렵다.<br />
이를 해결하기 위해 간단한 헬퍼 함수를 만들면 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">h</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">type<span class="token punctuation">,</span> props<span class="token punctuation">,</span> <span class="token operator">...</span>children</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">,</span> props<span class="token punctuation">,</span> children <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>(참고: <a href="https://github.com/hyperhype/hyperscript">hyperscript</a>)</p>
<p>이제, 위의 DOM 트리는 아래와 같이 나타낼 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token function">h</span><span class="token punctuation">(</span><span class="token string">'ul'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token string">'list'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">h</span><span class="token punctuation">(</span><span class="token string">'li'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'first'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">h</span><span class="token punctuation">(</span><span class="token string">'li'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'second'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">h</span><span class="token punctuation">(</span><span class="token string">'li'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'third'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>JSX와 바벨</h2>
<p>바벨을 사용하면 <code class="hljs-text">jsx</code>문법을 사용할 수 있다.<br />
이 때, 바벨 플러그인 <a href="https://www.npmjs.com/package/babel-plugin-transform-react-jsx">babel-plugin-transform-react-jsx</a>이 필요하며,
<code class="hljs-text">pragma</code>를 통해 <code class="hljs-text">jsx</code>문법을 트랜스파일할 때 사용되는 함수를 변경할 수 있다.<br />
(<code class="hljs-text">pragma</code>의 기본 값은 리액트를 사용해본 사람이라면, 누구든 유추 가능할 것이다. 바로 <code class="hljs-text">React.createElement</code>이다.)</p>
<div class="gatsby-highlight" data-language="jsx"><pre class="hljs-jsx"><code class="hljs-jsx"><span class="token comment">/** @jsx h */</span>
<span class="token keyword">const</span> <span class="token function-variable function">h</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">type<span class="token punctuation">,</span> props<span class="token punctuation">,</span> <span class="token operator">...</span>children</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">,</span> props<span class="token punctuation">,</span> children <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> div <span class="token operator">=</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><span class="token plain-text">Deep dive into V-DOM!</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>div<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// {"type":"div","props":null,"children":["Deep dive into V-DOM!"]}</span></code></pre></div>
<p>(참고: <a href="https://babeljs.io/docs/plugins/transform-react-jsx/">React JSX transform</a>)</p>
<h2>실제 DOM에 그려보기</h2>
<p>위에서 만든 가상 DOM에서 <code class="hljs-text">children</code>은 텍스트 노드이거나 요소(element)이다. 따라서 가상 DOM은 조건에 따라 재귀적으로 호출될 것이며, 함수는 다음과 같을 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">createElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> document<span class="token punctuation">.</span><span class="token function">createTextNode</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> parent <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
node
<span class="token punctuation">.</span>children
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>createElement<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> parent<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<div class="gatsby-highlight" data-language="jsx"><pre class="hljs-jsx"><code class="hljs-jsx"><span class="token comment">/** @jsx h */</span>
<span class="token comment">// const h = ...</span>
<span class="token comment">// const createElement = ...</span>
<span class="token comment">// const div = ...</span>
<span class="token keyword">const</span> root <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
root<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>div<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>새로운 노드 그리기</h2>
<p>변경점을 찾고, 새로운 노드를 그리기 위해 가상 DOM을 업데이트하는 함수를 만들고자 한다.
먼저 변경에 대한 유즈케이스는 아래와 같다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token comment"><!-- before --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- after --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre></div>
<p>위와 같이 노드가 추가되는 경우에는 <code class="hljs-text">appendChild</code>를 이용한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token comment"><!-- before --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- after --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre></div>
<p>위와 같이 노드가 삭제되는 경우에는 <code class="hljs-text">removeChild</code>를 이용한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token comment"><!-- before --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- after --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre></div>
<p>위와 같이 노드가 변경되는 경우에는 <code class="hljs-text">replaceChild</code>를 이용한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token comment"><!-- before --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span>
<span class="token comment"><!-- after --></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span>3<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre></div>
<p>위와 같이 노드가 같은 구조를 가지는 경우에는 하위 노드들까지 동일한지 최하위 단계까지 내려가야 한다.</p>
<h3>업데이트 함수 작성하기</h3>
<p>위에서 살펴본 유즈케이스에 따라 점진적으로 함수를 작성한다.</p>
<p><strong>새로운 노드가 추가될 때</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">updateElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> newNode<span class="token punctuation">,</span> oldNode</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p><strong>기존의 노드가 제거될 때</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">updateElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">,</span> index <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> parent<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p><strong>노드가 변경될 때</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">isChanged</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node1<span class="token punctuation">,</span> node2</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
<span class="token keyword">typeof</span> node1 <span class="token operator">!==</span> <span class="token keyword">typeof</span> node2 <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node1 <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&&</span> node1 <span class="token operator">!==</span> node2<span class="token punctuation">)</span> <span class="token operator">||</span> node1<span class="token punctuation">.</span>type <span class="token operator">!==</span> node2<span class="token punctuation">.</span>type
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">,</span> index <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isChanged</span><span class="token punctuation">(</span>newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">replaceChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">,</span> parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>newNode<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> newLength <span class="token operator">=</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">const</span> oldLength <span class="token operator">=</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> newLength <span class="token operator">||</span> i <span class="token operator"><</span> oldLength<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateElement</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>props 설정하기</h2>
<p>JSX에서는 다음과 같이 <code class="hljs-text">className</code>이나 <code class="hljs-text">htmlFor</code>, <code class="hljs-text">defaultChecked</code>등의 속성을 <code class="hljs-text">props</code>로 전달할 수 있다.</p>
<div class="gatsby-highlight" data-language="jsx"><pre class="hljs-jsx"><code class="hljs-jsx"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">role</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>button<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">Click</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token comment">/*
{
type: 'div',
props: {
className: 'btn',
role: 'button',
},
children: [],
}
*/</span></code></pre></div>
<p>이러한 속성들을 렌더링하기 위해 먼저 노드의 <code class="hljs-text">attribute</code>를 설정하는 함수를 만든다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">setProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">props</code>의 <code class="hljs-text">key</code>를 순회하면서 <code class="hljs-text">setProp</code>을 호출함으로써 여러 <code class="hljs-text">props</code>를 설정하는 함수 <code class="hljs-text">setProps</code>는 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">setProps</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>앞서 정의했던 <code class="hljs-text">createElement</code> 내부에서 <code class="hljs-text">setProps</code>를 호출함으로써 <code class="hljs-text">attribute</code>를 가진 노드를 생성할 수 있다.<br />
변경된 <code class="hljs-text">createElement</code>는 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">createElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> document<span class="token punctuation">.</span><span class="token function">createTextNode</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> parent <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setProps</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> node<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
node
<span class="token punctuation">.</span>children
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>createElement<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> parent<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">주의</code>할 점이 있다면, <code class="hljs-text">class</code>나 <code class="hljs-text">for</code> 등의 자바스크립트 예약어는 <code class="hljs-text">jsx</code> 내에서도 사용할 수 없기 때문에 <code class="hljs-text">className</code>, <code class="hljs-text">htmlFor</code> 등으로 대체되는데, 이에 대한 처리가 필요하다는 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">setProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>이외에도 <code class="hljs-text">boolean</code>타입의 값을 넘기는 경우, HTML attribute를 추가하거나 제거하는 작업이 필요하다. 이를 구현하면 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">setBooleanProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">setProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>props 비교하기</h2>
<p>위에서 노드에 대한 변경점을 찾았던 것처럼 <code class="hljs-text">props</code> 에 대해서도 변경점을 찾고 가상 DOM을 업데이트하는 함수를 만든다.<br />
위와 비슷한 내용이며, 어려운 코드가 아니기 때문에 코드에 대한 설명은 생략한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token punctuation">{</span> isEqual <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">removeBooleanProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">removeProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">removeBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newValue<span class="token punctuation">,</span> oldValue</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">removeProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> oldValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldValue <span class="token operator">||</span> <span class="token function">isEqual</span><span class="token punctuation">(</span>newValue<span class="token punctuation">,</span> oldValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateProps</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> newProps <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> oldProps <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> props <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token operator">...</span>newProps<span class="token punctuation">,</span>
<span class="token operator">...</span>oldProps<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">updateProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newProps<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">,</span> oldProps<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h3>업데이트 함수 작성하기</h3>
<p><code class="hljs-text">props</code>가 변경되었을 때, DOM을 업데이트하는 함수는 다음과 같이 작성한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">updateElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">,</span> index <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isChanged</span><span class="token punctuation">(</span>newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">replaceChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">,</span> parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>newNode<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateProps</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> newNode<span class="token punctuation">.</span>props<span class="token punctuation">,</span> oldNode<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// added</span>
<span class="token keyword">const</span> newLength <span class="token operator">=</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">const</span> oldLength <span class="token operator">=</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> newLength <span class="token operator">||</span> i <span class="token operator"><</span> oldLength<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateElement</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>이벤트 리스너 등록하기</h2>
<p>먼저 추가되는 이벤트 리스너의 특징을 말하자면, prefix로 <code class="hljs-text">on</code>이 붙으며, 전달받는 값의 타입은 함수이다.<br />
따라서, <code class="hljs-text">setProp</code>에서 전달받는 파라미터 중 <code class="hljs-text">value</code>의 타입이 함수이면, 아무런 attribute도 설정하지 않는다. (또른 <code class="hljs-text">name</code>이 <code class="hljs-text">on</code>으로 시작하는지 체크한다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">setProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// or.. 2 is length of `on`</span>
<span class="token comment">// if (name.substr(0, 2) === 'on') {</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>이벤트 리스너를 등록하기 위해 <code class="hljs-text">on</code>을 제외한 이벤트 이름을 추출하고, 해당 리스너를 추가하는 함수를 작성하면 다음과 같다.<br />
(위에서 이벤트를 전달받았는지 체크하기 위한 조건문은 <code class="hljs-text">addEventListeners</code>에서 또 다시 한번 사용되기 때문에 <code class="hljs-text">isEvent</code> 함수로 만들어 재사용한다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">isEvent</span> <span class="token operator">=</span> <span class="token parameter">value</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">getEventName</span> <span class="token operator">=</span> <span class="token parameter">name</span> <span class="token operator">=></span> name<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">addEventListeners</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isEvent</span><span class="token punctuation">(</span>props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token function">getEventName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">,</span> props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>여기서 이벤트 캡처링 방식의 동작을 위해서 suffix로 <code class="hljs-text">Capture</code>가 붙는지 확인하고, 조건에 부합하면, <code class="hljs-text">addEventListner</code>의 세 번째 인자에 <code class="hljs-text">true</code>를 넘겨주도록 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">isCapture</span> <span class="token operator">=</span> <span class="token parameter">name</span> <span class="token operator">=></span> <span class="token regex">/Capture$/</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">addEventListeners</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isEvent</span><span class="token punctuation">(</span>props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token function">getEventName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">,</span> props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token function">isCapture</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>이를 <code class="hljs-text">createElement</code>에 넣으면 아래와 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">createElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> document<span class="token punctuation">.</span><span class="token function">createTextNode</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> parent <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setProps</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> node<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addEventListeners</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> node<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
node
<span class="token punctuation">.</span>children
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>createElement<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> parent<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<h2>이벤트 리스너 제거하기</h2>
<p>등록된 이벤트 리스너를 제거하기 위해서는 <code class="hljs-text">removeProp</code>을 수정한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">removeProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token function">getEventName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">,</span> value<span class="token punctuation">,</span> <span class="token function">isCapture</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">removeBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>(이벤트 리스너를 다시 등록하는 것은 복잡한 작업이라 다음 기회에 다시 작성을 해볼 예정이다.)</p>
<h2>마무리</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/** @jsx h */</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> isEqual <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'lodash'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">h</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">type<span class="token punctuation">,</span> props<span class="token punctuation">,</span> <span class="token operator">...</span>children</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">,</span> props<span class="token punctuation">:</span> props <span class="token operator">||</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> children <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">isEvent</span> <span class="token operator">=</span> <span class="token parameter">value</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">getEventName</span> <span class="token operator">=</span> <span class="token parameter">name</span> <span class="token operator">=></span> name<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">isCapture</span> <span class="token operator">=</span> <span class="token parameter">name</span> <span class="token operator">=></span> <span class="token regex">/Capture$/</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">addEventListeners</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isEvent</span><span class="token punctuation">(</span>props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token function">getEventName</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">,</span> props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">createElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> document<span class="token punctuation">.</span><span class="token function">createTextNode</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> parent <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>type<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setProps</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> node<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addEventListeners</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> node<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
node
<span class="token punctuation">.</span>children
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>createElement<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> parent<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">setBooleanProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">removeBooleanProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
node<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">removeProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">removeBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newValue<span class="token punctuation">,</span> oldValue</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newValue<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">removeProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> oldValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldValue <span class="token operator">||</span> <span class="token function">isEqual</span><span class="token punctuation">(</span>newValue<span class="token punctuation">,</span> oldValue<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateProps</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> newProps <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> oldProps <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> props <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token operator">...</span>newProps<span class="token punctuation">,</span>
<span class="token operator">...</span>oldProps<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">updateProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> newProps<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">,</span> oldProps<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">setProp</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'className'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'class'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>name <span class="token operator">===</span> <span class="token string">'htmlFor'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'for'</span><span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> value <span class="token operator">===</span> <span class="token string">'boolean'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setBooleanProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
node<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">setProps</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setProp</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> name<span class="token punctuation">,</span> props<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">isChanged</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">node1<span class="token punctuation">,</span> node2</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
<span class="token keyword">typeof</span> node1 <span class="token operator">!==</span> <span class="token keyword">typeof</span> node2 <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> node1 <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&&</span> node1 <span class="token operator">!==</span> node2<span class="token punctuation">)</span> <span class="token operator">||</span> node1<span class="token punctuation">.</span>type <span class="token operator">!==</span> node2<span class="token punctuation">.</span>type
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">updateElement</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">,</span> index <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>oldNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>newNode<span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">removeChild</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isChanged</span><span class="token punctuation">(</span>newNode<span class="token punctuation">,</span> oldNode<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
parent<span class="token punctuation">.</span><span class="token function">replaceChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>newNode<span class="token punctuation">)</span><span class="token punctuation">,</span> parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>newNode<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateProps</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> newNode<span class="token punctuation">.</span>props<span class="token punctuation">,</span> oldNode<span class="token punctuation">.</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> newLength <span class="token operator">=</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">const</span> oldLength <span class="token operator">=</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> newLength <span class="token operator">||</span> i <span class="token operator"><</span> oldLength<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateElement</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>childNodes<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> newNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> oldNode<span class="token punctuation">.</span>children<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> div <span class="token operator">=</span> <span class="token operator"><</span>div onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span>Deep dive into <span class="token constant">V</span><span class="token operator">-</span><span class="token constant">DOM</span><span class="token operator">!</span><span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span><span class="token punctuation">;</span>
<span class="token keyword">const</span> root <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
root<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span><span class="token function">createElement</span><span class="token punctuation">(</span>div<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="https://reactjs.org/docs/introducing-jsx.html">Introducing JSX</a></li>
<li><a href="https://github.com/hyperhype/hyperscript">hyperscript</a></li>
<li><a href="https://babeljs.io/docs/plugins/transform-react-jsx/">React JSX transform</a></li>
</ul>
- <![CDATA[Git 관련 팁]]>https://wonism.github.io/git-tips/https://wonism.github.io/git-tips/Wed, 02 May 2018 23:42:22 GMT<h2>깃 커맨드 별칭(alias)</h2>
<h4>커맨드로 alias 설정하기</h4>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text"># git command without parameters
$ git config --global alias.s status
# same as git status
$ git s
# git command with parameters
$ git config --global alias.nb "!f(){ git checkout -b \"$1\"; };f"
# same as git checkout -b "BRANCH_NAME"</code></pre></div>
<h4>.gitconfig로 alias 설정하기</h4>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">[color]
...
[user]
...
[core]
...
[merge]
...
[push]
...
[filter "lfs"]
...
[alias]
# add alias here
a = add
c = commit
s = status
d = diff
b = branch
l = log
p = push
pu = pull
co = checkout
nb = "!f(){ git checkout -b \"$1\"; git push origin \"$1\" --set-upstream; };f"</code></pre></div>
<h2>특정 브랜치 클로닝하기</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ git clone -b <BRANCH_NAME> [email protected]:<USER_NAME>/<REPOSITORY_NAME>.git</code></pre></div>
<h2>깃 커맨드 자동완성</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ cd ~/github
$ git clone git://git.kernel.org/pub/scm/git/git.git
$ mkdir -p /usr/local/etc/bash_completion.d
$ cp git/contrib/completion/git-completion.bash /usr/local/etc/bash_completion.d/
$ echo -e '# Git command completion\nsource /usr/local/etc/bash_completion.d/git-completion.bash' >> ~/.bash_profile
$ source ~/.bash_profile</code></pre></div>
<p>터미널에서 <code class="hljs-text">git</code> 을 타이핑한 뒤 <code class="hljs-text">tab</code> 키를 누르면, 사용할 수 있는 명령어들이 나온다.
또, <code class="hljs-text">git l</code> 까지 타이핑한 뒤 <code class="hljs-text">tab</code> 키를 누르면, <code class="hljs-text">git log</code>가 자동완성된다.</p>
<h2>풀 리퀘스트와 이슈 템플릿 만들기</h2>
<p>프로젝트 루트 아래 <code class="hljs-text">.github</code> 디렉토리를 만들고, <code class="hljs-text">ISSUE_TEMPLATE.md</code>(이슈 템플릿), <code class="hljs-text">PULL_REQUEST_TEMPLATE.md</code>(풀 리퀘스트 템플릿)을 생성한다.<br />
사용 예는 아래 링크에서 확인할 수 있다.</p>
<p><a href="https://github.com/aframevr/aframe/tree/master/.github">https://github.com/aframevr/aframe/tree/master/.github</a></p>
<h2>Something went wrong. 에러</h2>
<p><code class="hljs-text">Github</code>에서 새로운 저장소를 만들기 위해 (<a href="https://github.com/new">https://github.com/new</a> 페이지에서) 저장소 이름의 유효성 검사를 하던 도중,
<code class="hljs-text">Something went wrong.</code> 이라는 메시지가 출력되었다.</p>
<p>구글에 검색을 해보니, 같은 문제를 겪은 사람이 또 있었다.</p>
<p>해결 방법은 <code class="hljs-text">Allow-Control-Allow-Origin</code> 이라는 크롬 확장프로그램을 중지시키는 것이었다.<br />
(<code class="hljs-text">Allow-Control-Allow-Origin</code> 은 <code class="hljs-text">CORS (Cross-Origin Resource Sharing)</code> 관련 디버깅을 위해 설치했던 확장프로그램이다.)</p>
<p><strong>참고</strong>
<a href="http://stackoverflow.com/questions/32851144/cannot-create-repository-on-github">http://stackoverflow.com/questions/32851144/cannot-create-repository-on-github</a></p>
<h2>서브모듈 관련 명렁어</h2>
<h4>모든 서브모듈 리셋하기</h4>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ git submodule foreach git reset --hard
# or
$ git submodule foreach --recursive git reset --hard</code></pre></div>
<h4>서브모듈이 특정 브랜치를 바라보도록 하기</h4>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ cd <PATH_TO_SUBMODULE>
$ git fetch --all # if needed
$ git checkout <SPECIFIC_BRANCH></code></pre></div>
<h2>포크된 저장소를 원래 저장소와 동기화하기</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text"># 1. remote 설정하기
$ git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
# 2. upstream 으로부터 변경된 파일 가져오기
$ git fetch upstream
# 3. master 브랜치로 이동
$ git checkout master
# 4. 병합하기
$ $ git merge upstream/master
# more> 만약, conflict 가 발생했다면, 필요한 부분을 편집한다.</code></pre></div>
<h2>깃허브 페이지에 SPA 호스팅하기</h2>
<p><a href="https://github.com/rafrex/spa-github-pages">https://github.com/rafrex/spa-github-pages</a></p>
- <![CDATA[Anchor 태그의 mailto 사용하기]]>https://wonism.github.io/email-with-anchor/https://wonism.github.io/email-with-anchor/Tue, 01 May 2018 23:30:56 GMT<h2>기본 사용 방법</h2>
<p><code class="hljs-text"><a /></code> 태그의 <code class="hljs-text">href</code> 속성에 <code class="hljs-text">mailto:</code>를 접두사로 사용한다.<br />
여러 사람에게 메일을 보내고자 할 때는 받는 사람 사이에 <code class="hljs-text">,</code>를 추가한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>mailto:[email protected]<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Send<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre></div>
<h2>참조 및 숨은 참조</h2>
<p>참조받는 주소를 추가하고자 할 땐 <code class="hljs-text">cc</code>를 추가한다.
숨은 참조를 위해서는 <code class="hljs-text">bcc</code>를 추가한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"mailto:[email protected][email protected]&[email protected]"</span><span class="token operator">></span>Send<span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span></code></pre></div>
<h2>제목과 내용</h2>
<p>제목을 추가할 땐 <code class="hljs-text">subject</code>를 추가하며, 본문 내용을 추가할 땐 <code class="hljs-text">body</code>를 추가한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"mailto:[email protected]?subject=Hello, Mailto&body=Lorem Ipsum is simply dummy text of the printing and typesetting industry."</span><span class="token operator">></span>Send<span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span></code></pre></div>
<h3>본문 내용의 줄바꿈</h3>
<p><code class="hljs-text">%0D%0A</code>를 사용하면 줄바꿈을 할 수 있다.</p>
<h2>활용 사례</h2>
<p><a href="/contacts">링크</a>에서 확인할 수 있다.</p>
- <![CDATA[setInterval과 싱글 스레드 그리고 시간 보정]]>https://wonism.github.io/set-interval-correction/https://wonism.github.io/set-interval-correction/Mon, 30 Apr 2018 19:17:16 GMT<h2>setInterval</h2>
<p><code class="hljs-text">setInterval</code>을 사용하면, 일정한 주기로 반복적인 함수를 실행할 수 있다.<br />
사용 방법은 <code class="hljs-text">setInterval(function callback () {}, interval.ms)</code>과 같이 사용하며, 두번째 인자는 <code class="hljs-text">ms</code>단위이다.<br />
예를 들어 다음과 같은 코드는 1초에 한 번씩 <code class="hljs-text">Hello, Interval!</code>이란 문자열을 출력한다.<br /></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> hello <span class="token operator">=</span> <span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Hello, Interval'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">setInterval</code>을 실행함으로써 반환되는 값은 자연수(<code class="hljs-text">Number</code> 타입)이며, 일종(一種)의 프로세스 아이디(pid)라고 봐도 무방하다.<br />
이 값은 <code class="hljs-text">clearInterval(pid)</code>로 인터벌을 중지하고자 할 때 사용된다.</p>
<h2>setInterval과 싱글 스레드</h2>
<p>자바스크립트는 싱글 스레드를 사용하기 때문에 이벤트 루프 기반의 동시성 지원을 한다.<br />
이로 인해 <code class="hljs-text">setInterval</code>은 (<code class="hljs-text">setTimeout</code>도 마찬가지이다.) 약간의 지연이 발생한다.</p>
<p>다음 예제 코드를 실행하고, 그 결과를 보겠다.<br />
(크롬 브라우저(65.0.3325.181 사용 중)에서는 내부적으로 보정이 들어가기 때문에 파이어폭스에서 실행을 한 결과를 첨부했다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> start <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> start<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">ms`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1001ms</span>
<span class="token comment">// 2002ms</span>
<span class="token comment">// 3003ms</span>
<span class="token comment">// 4004ms</span>
<span class="token comment">// 5005ms</span>
<span class="token comment">// 6009ms</span>
<span class="token comment">// 7009ms</span>
<span class="token comment">// 8010ms</span>
<span class="token comment">// 9013ms</span>
<span class="token comment">// 10016ms</span></code></pre></div>
<h2>setInterval 보정하기</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> setCorrectedInterval <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">callback<span class="token punctuation">,</span> delay</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> startTime<span class="token punctuation">;</span>
<span class="token keyword">let</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">tick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">cb<span class="token punctuation">,</span> dl</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>count<span class="token punctuation">)</span> <span class="token punctuation">{</span>
startTime <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
isStarted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">tick</span><span class="token punctuation">(</span>cb<span class="token punctuation">,</span> dl<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> dl<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> delayed <span class="token operator">=</span> <span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> startTime<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> correction <span class="token operator">=</span> <span class="token punctuation">(</span>delay <span class="token operator">*</span> count<span class="token punctuation">)</span> <span class="token operator">-</span> delayed<span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">tick</span><span class="token punctuation">(</span>cb<span class="token punctuation">,</span> dl <span class="token operator">+</span> correction<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> dl <span class="token operator">+</span> correction<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">tick</span><span class="token punctuation">(</span>callback<span class="token punctuation">,</span> delay<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> now <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setCorrectedInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> now<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>시간 보정을 위해 클로저 구문 안에 <code class="hljs-text">startTime</code>, <code class="hljs-text">count</code> 등의 지역 변수를 선언한다.</p>
<p>함수가 처음 시작되면 첫 번째 인자인 콜백 함수를 즉시 시작하는게 아니라,
<code class="hljs-text">setTimeout</code>에 내부 함수와 인터벌값을 인자로 전달한다.<br />
두 번째 부터는 지연된 시간과 콜백 함수를 실행하고자 하는 시간의 갭을 구한 뒤,
내부 함수에서 전달받은 2번째 인자와 더하여 시간을 보정하며,
<code class="hljs-text">setInterval</code>을 호출하며 콜백함수를 인터벌로 반복하도록 한다.</p>
<h2>setCorrectedInterval을 비우기 위한 clearCorrectedInterval</h2>
<p><code class="hljs-text">setInterval</code>이나 <code class="hljs-text">setTimeout</code>처럼 <code class="hljs-text">id</code>값을 반환하도록하며,
조건문을 통해 <code class="hljs-text">clear</code>되지 않은 인터벌들만 실행하도록 한다.<br />
아이디들을 저장할 객체 <code class="hljs-text">intervals</code>는 <code class="hljs-text">setCorrectedInterval</code>과 같은 스코프에 생성하며, 각 아이디들은 <code class="hljs-text">setTimeout</code>의 아이디와 맵핑된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">let</span> intervalId <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> intervals <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> setCorrectedInterval <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">callback<span class="token punctuation">,</span> delay</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> startTime<span class="token punctuation">;</span>
<span class="token keyword">let</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> id <span class="token operator">=</span> intervalId<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">tick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">cb<span class="token punctuation">,</span> dl</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>count<span class="token punctuation">)</span> <span class="token punctuation">{</span>
startTime <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
isStarted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
count<span class="token operator">++</span><span class="token punctuation">;</span>
intervals<span class="token punctuation">[</span>id<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">tick</span><span class="token punctuation">(</span>cb<span class="token punctuation">,</span> dl<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> dl<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> delayed <span class="token operator">=</span> <span class="token punctuation">(</span>Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> startTime<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> correction <span class="token operator">=</span> <span class="token punctuation">(</span>delay <span class="token operator">*</span> count<span class="token punctuation">)</span> <span class="token operator">-</span> delayed<span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>intervals<span class="token punctuation">[</span>id<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
intervals<span class="token punctuation">[</span>id<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">tick</span><span class="token punctuation">(</span>cb<span class="token punctuation">,</span> dl <span class="token operator">+</span> correction<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> dl <span class="token operator">+</span> correction<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">tick</span><span class="token punctuation">(</span>callback<span class="token punctuation">,</span> delay<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> id<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">clearCorrectedInterval</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">clearTimeout</span><span class="token punctuation">(</span>intervals<span class="token punctuation">[</span>id<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">delete</span> intervals<span class="token punctuation">[</span>id<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
- <![CDATA[도메인 샤딩]]>https://wonism.github.io/domain-sharding/https://wonism.github.io/domain-sharding/Sun, 22 Apr 2018 21:14:06 GMT<p>도메인 샤딩은 정적파일(이미지, CSS, JS 등)의 로딩 속도를 개선하는 방법으로, 여러개의 서브도메인을 생성하여 정적파일을 병렬로 가져온다.</p>
<p>도메인 샤딩의 등장 배경은 HTTP/1.x에서 도메인 당 동시 요청 갯수의 제한때문이다. (대부분의 모던 브라우저는 <code class="hljs-text">6~8</code>개, IE 하위 버전은 <code class="hljs-text">2</code>개까지 동시 요청을 할 수 있다.(하단의 표 참고) 이러한 제한은 웹서버에 과부하가 걸리지 않도록 IETF(Internet Engineering Task Force)에 의해 <code class="hljs-text">HTTP/1.1 사양</code>으로 정의되었다.)</p>
<p>동시 요청을 함으로써 웹 페이지 로딩 속도가 무조건 빨라질 것 같지만 그렇지 않다. 각 하위 도메인에 DNS 조회를 함으로써 꽤 많은 시간과 CPU, 전력을 소모하기 때문이다.(“김기정, 이성원. 웹 성능을 향상시키기 위한 DNS Resolution 감소 방안에 대한 연구”에 따르면, 3G환경에서는 평균 361ms, 4G환경에서는 평균 176ms의 왕복 지연시간이 발생한다고 한다.) 따라서, 도메인 샤딩은 동시 요청에 대한 완벽한 솔루션이라고 볼 수 없다.(도메인 샤딩 대신 HTTP/2로 전환하는 것이 좋다. HTTP/2 설정 방법은 <a href="https://github.com/wonism/TIL/tree/master/back-end/nginx/http2">링크</a>를 참고한다.)</p>
<p>추가로, 많은 모바일 브라우저가 HTTP 파이프라이닝을 구현하고 있다. 따라서, 도메인 샤딩은 더 이상 동시 요청에 대한 좋은 솔루션이 아니다.</p>
<table>
<thead>
<tr>
<th align="left">Browser </th>
<th align="center">Request</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Firefox 2</td>
<td align="center">2</td>
</tr>
<tr>
<td align="left">Firefox 3+</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">Opera 9.26</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">Opera 12</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">Safari 3</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">Sarafi 5</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">IE 7</td>
<td align="center">2</td>
</tr>
<tr>
<td align="left">IE 8</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">IE 10</td>
<td align="center">8</td>
</tr>
<tr>
<td align="left">Chrome</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">Safari Mobile</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">Android Browser</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">Chrome Mobile</td>
<td align="center">6</td>
</tr>
<tr>
<td align="left">Firefox Mobile</td>
<td align="center">4</td>
</tr>
</tbody>
</table>
<h2>참조</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x">MDN : HTTP/1.x의 커넥션 관리</a></li>
<li><a href="https://www.kics.or.kr/storage/paper/event/winter2014/publish/3D-5.pdf">웹 성능을 향상시키기 위한 DNS Resolution 감소 방안에 대한 연구</a></li>
</ul>
- <![CDATA[Reflow 와 Repaint]]>https://wonism.github.io/reflow-repaint/https://wonism.github.io/reflow-repaint/Sun, 22 Apr 2018 21:09:09 GMT<p><code class="hljs-text">reflow</code>와 <code class="hljs-text">repaint</code>는 수정된 렌더 트리를 다시 렌더링하는 과정에서 발생하는 것으로 웹 애플리케이션의 성능을 떨어뜨리는 주된 요인이다. 극단적인 경우, CSS 효과로 인해 Java Script 의 실행 속도가 느려질 수도 있다.</p>
<h2>Repaint</h2>
<p><code class="hljs-text">리페인트</code>는 <code class="hljs-text">레이아웃</code>에는 영향을 주지 않지만, 가시성에는 영향을 주는 엘리먼트가 변경되면 발생한다.<br />
예를 들면, <code class="hljs-text">opacity</code>, <code class="hljs-text">background-color</code>, <code class="hljs-text">visibility</code>, <code class="hljs-text">outline</code></p>
<p><a href="https://dev.opera.com/articles/efficient-javascript/?page=3#reflow">오페라</a>에 따르면, “브라우저가 DOM 트리에 있는 다른 모든 노드의 가시성을 확인해야 하므로 리페인트는 비용이 많이 든다.”고 한다.</p>
<h2>Reflow</h2>
<p>“리플로우”는 모든 엘리먼트의 위치와 길이 등을 다시 계산하는 것으로 문서의 일부 혹은 전체를 다시 렌더링한다.<br />
단일 엘리먼트 하나를 변경해도, 하위 엘리먼트나 상위 엘리먼트 등에 영향을 미칠 수 있다.</p>
<h3>리플로우가 트리거되는 경우</h3>
<ul>
<li>DOM 엘리먼트 추가, 제거 또는 변경</li>
<li>
<p>CSS 스타일 추가, 제거 또는 변경</p>
<ul>
<li>CSS 스타일을 직접 변경하거나, 클래스를 추가함으로써 레이아웃이 변경될 수 있다. 엘리먼트의 길이를 변경하면, DOM 트리에 있는 다른 노드에 영향을 줄 수 있다.</li>
</ul>
</li>
<li>
<p>CSS3 애니메이션과 트랜지션</p>
<ul>
<li>애니메이션의 모든 프레임에서 리플로우가 발생한다.</li>
</ul>
</li>
<li>
<p>offsetWidth 와 offsetHeight 의 사용</p>
<ul>
<li>offsetWidth 와 offsetHeight 속성을 읽으면, 초기 리플로우가 트리거되어 수치가 계산된다.</li>
</ul>
</li>
<li>
<p>유저 행동</p>
<ul>
<li>유저 인터랙션으로 발생하는 <code class="hljs-text">hover</code> 효과, 필트에 텍스트 입력, 창 크기 조정, 글꼴 크기 변경, 스타일시트 또는 글꼴 전환등을 활성화하여 리플로우를 트리거할 수 있다.</li>
</ul>
</li>
</ul>
<h2>성능 저하 최소화하기</h2>
<ul>
<li>
<p>클래스 변경을 통해 스타일을 변경할 경우, 최대한 말단의 노드의 클래스를 변경한다.</p>
<ul>
<li>최대한 말단에 있는 노드를 변경함으로써, 리플로우의 영향을 최소화한다.</li>
</ul>
</li>
<li>
<p>인라인 스타일을 사용하지 않는다.</p>
<ul>
<li>스타일 속성을 통해 스타일을 설정하면, 리플로우가 발생한다.</li>
<li>엘리먼트의 클래스가 변경될 때 엘리먼트는 하나의 리플로우만 발생시킨다.</li>
<li>인라인 스타일은 HTML 이 다운로드될 때, 레이아웃에 영향을 미치면서 추가 리플로우를 발생시킨다.</li>
</ul>
</li>
<li>
<p>애니메이션이 들어간 엘리먼트는 <code class="hljs-text">position: fixed</code> 또는 <code class="hljs-text">position: absolute</code> 로 지정한다.</p>
<ul>
<li><code class="hljs-text">absolute</code> 또는 <code class="hljs-text">fixed</code> 위치인 엘리먼트는 다른 엘리먼트의 레이아웃에 영향을 미치지 않는다. (리플로우가 아닌 리페인트가 발생하는데, 이것은 훨씬 적은 비용이 든다.)</li>
</ul>
</li>
<li>
<p>부드러운 애니메이션이 성능을 저하시킨다.</p>
<ul>
<li>한 번에 1px 씩 엘리먼트를 이동하면 부드러워 보이지만, 성능이 떨어지는 디바이스는 말썽일 수 있다.</li>
<li>엘리먼트를 한 프레임당 4px 씩 이동하면 덜 부드럽게 보이겠지만, 리플로우 처리의 <code class="hljs-text">1/4</code>만 필요하다.</li>
</ul>
</li>
<li>
<p>레이아웃을 위한 <code class="hljs-text"><table></code> 은 피한다.</p>
<ul>
<li><code class="hljs-text"><table></code> 은 점진적으로 렌더링되지 않고, 모두 불려지고 계산된 다음에서야 렌더링이 된다. 또한, 작은 변경만으로도 테이블의 다른 모든 노드에 대한 리플로우가 발생한다.</li>
<li>레이아웃 용도가 아닌 데이터 표시 용도의 <code class="hljs-text"><table></code> 을 사용하더라고, <code class="hljs-text">table-layout: fixed</code> 속성을 주는 것이 좋다. <code class="hljs-text">table-layout: fixed</code> 를 사용하면, 열 너비가 머리글 행 내용을 기반으로 계산되기 때문이다.</li>
</ul>
</li>
<li>
<p><code class="hljs-text">CSS</code> 에서 Java Script 표현식을 사용하지 않는다.</p>
<ul>
<li>IE 와 FF 는 모두 CSS 에서 Java Script 를 실행할 수 있다. IE 에서는 표현 기법과 HTC 동작 방법이 있고, FF 에서는 XBL 을 사용하는 방법이 있다. (이 방법은 CSS 에서 Java Script 를 직접 실행하지는 않지만, 그 효과는 동일하다.)</li>
<li>문서가 리플로우될 때마다 Java Script 표현식이 다시 계산된다.</li>
</ul>
</li>
<li>
<p>CSS 하위 셀렉터를 최소화한다.</p>
<ul>
<li>사용하는 규칙이 적을수록 리플로우가 빠르다.</li>
<li><code class="hljs-text">gulp-uncss</code>, <code class="hljs-text">grunt-uncss</code> 와 같은 도구로 스타일 정의 및 파일 크기를 줄인다.</li>
</ul>
</li>
<li>
<p>숨겨진 엘리먼트를 변경한다.</p>
<ul>
<li><code class="hljs-text">display: none;</code> 으로 숨겨진 엘리먼트는 변경될 때, 리페인트나 리플로우를 일으키지 않는다. 그렇기 때문에 엘리먼트를 표시하기 전에 엘리먼트를 변경한다.</li>
</ul>
</li>
<li>
<p>Java Script 를 통해 스타일을 변경할 경우, <code class="hljs-text">.cssText</code> 를 사용하거나, 클래스를 변경한다.</p>
</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> el <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'reflow-test'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>padding <span class="token operator">=</span> <span class="token string">'8px'</span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>width <span class="token operator">=</span> <span class="token string">'320px'</span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>height <span class="token operator">=</span> <span class="token string">'240px'</span><span class="token punctuation">;</span>
<span class="token comment">// 3 번의 리플로우 발생</span>
<span class="token comment">/////////</span>
<span class="token keyword">var</span> el <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'reflow-test'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>cssText <span class="token operator">=</span> <span class="token string">'padding: 8px; width: 320px; height: 240px;'</span><span class="token punctuation">;</span>
<span class="token comment">/* or */</span>
el<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'changed'</span><span class="token punctuation">;</span>
<span class="token comment">// 1 번의 리플로우 발생</span>
<span class="token comment">/**
* Style of `changed` class
* .changed {
* padding: 8px;
* width: 320px;
* height: 240px;
* }
*/</span></code></pre></div>
<ul>
<li>
<p>Java Script 를 통해 리스트를 추가하는 경우, DOM Fragment 를 통해 추가한다.</p>
<ul>
<li>3 개의 리스트를 추가하는 경우, 한 번에 하나씩 추가하면 최대 7 개의 리플로우가 발생한다.<br />
<code class="hljs-text"><ul></code> 이 추가될 때<br />
<code class="hljs-text"><li></code> 에 대해 3번<br />
텍스트 노드에 대해 3번</li>
</ul>
</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> frag <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createDocumentFragment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> ul <span class="token operator">=</span> frag<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'ul'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">3</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
li <span class="token operator">=</span> ul<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'li'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
li<span class="token punctuation">.</span>textContent <span class="token operator">=</span> <span class="token template-string"><span class="token string">`item </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> i <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>frag<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<ul>
<li>
<p>캐쉬를 활용한 Reflow 최소화.</p>
<ul>
<li>브라우저는 레이아웃 변경을 큐에 저장했다가 한 번에 실행함으로써 리플로우를 최소화하는데, offset, scrollTop 과 같은 계산된 스타일 정보를 요청할 때마다 정확한 정보를 제공하기 위해 큐를 비우고, 모든 변경을 다시 적용한다.</li>
<li>이를 최소화하기 위해 수치에 대한 스타일 정보를 변수에 저장하여 정보 요청 횟수를 줄임으로써 리플로우를 최소화한다.</li>
</ul>
</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// Bad practice</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>top <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> el<span class="token punctuation">.</span>offsetTop <span class="token operator">+</span> <span class="token number">10</span> <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">px`</span></span><span class="token punctuation">;</span>
el<span class="token punctuation">.</span>style<span class="token punctuation">.</span>left <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> el<span class="token punctuation">.</span>offsetLeft <span class="token operator">+</span> <span class="token number">10</span> <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">px`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Good practice</span>
<span class="token keyword">let</span> top <span class="token operator">=</span> el<span class="token punctuation">.</span>offsetTop<span class="token punctuation">,</span> left <span class="token operator">=</span> el<span class="token punctuation">.</span>offsetLeft<span class="token punctuation">,</span> elStyle <span class="token operator">=</span> el<span class="token punctuation">.</span>style<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
top <span class="token operator">+=</span> <span class="token number">10</span><span class="token punctuation">;</span>
left <span class="token operator">+=</span> <span class="token number">10</span><span class="token punctuation">;</span>
elStyle<span class="token punctuation">.</span>top <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> top <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">px`</span></span><span class="token punctuation">;</span>
elStyle<span class="token punctuation">.</span>left <span class="token operator">=</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> left <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">px`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<ul>
<li>
<p>브라우저 도구로 리페인트 이슈 분석하기</p>
<ul>
<li>모든 주류 브라우저는 리플로우가 성능에 미치는 영향을 보여주는 [타임라인] 도구를 제공한다.</li>
<li><code class="hljs-text">IE</code> 의 경우에는 <code class="hljs-text">dynaTrace AJAX Edition</code>, <code class="hljs-text">Webkit Browser</code> 의 경우에는 <code class="hljs-text">Google Chrome SpeedTracer</code> 가 있다.</li>
</ul>
</li>
</ul>
<h2>참고</h2>
<ul>
<li><a href="http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/">Stubbornella : REFLOWS & REPAINTS: CSS PERFORMANCE MAKING YOUR JAVASCRIPT SLOW?</a></li>
<li><a href="https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/">Sitepoint : 10 Ways to Minimize Reflows and Improve Performance</a></li>
<li><a href="https://dev.opera.com/articles/efficient-javascript/?page=3#reflow">Opera : Efficient JavaScript</a></li>
<li><a href="http://stackoverflow.com/questions/476276/using-javascript-in-css">SO : Using Javascript in CSS</a></li>
</ul>
- <![CDATA[React Native에서 alias 설정하기]]>https://wonism.github.io/react-native-alias/https://wonism.github.io/react-native-alias/Fri, 20 Apr 2018 01:09:07 GMT<p>이전에 작성한 <a href="/resolve-import-path">resolve.alias로 import 개선하기</a>에서 이어지는 글이다.</p>
<p>보통 <code class="hljs-text">React JS</code>로 웹 애플리케이션을 개발하면 <code class="hljs-text">webpack</code>을 사용하기 마련이지만,
<code class="hljs-text">React Native</code>로 모바일 애플리케이션을 개발할 땐, <code class="hljs-text">webpack</code>을 사용하지 않는 경우도 많다.</p>
<p>웹팩을 통해 <code class="hljs-text">alias</code>를 사용하는 방법은 위의 링크를 참고하고,
웹팩을 사용하지 않는 경우, 어떻게 <code class="hljs-text">alias</code>를 설정하는지 보겠다.</p>
<p>크게 두 가지 방법이 있다.</p>
<h2>babel을 사용하는 경우</h2>
<p>먼저, <a href="https://github.com/tleunen/babel-plugin-module-resolver">babel-plugin-module-resolver</a>를 설치한 뒤, <code class="hljs-text">.babelrc</code>의 <code class="hljs-text">plugins</code>를 다음과 같이 설정한다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">{
"plugins": [
"module-resolver",
{
"root": ["./src"],
"alias": {
"~": "./src"
}
}
]
}</code></pre></div>
<p><code class="hljs-text">root</code>를 사용하면, 사용자 정의 프로젝트 루트를 지정한며, 위의 예제의 경우, <code class="hljs-text">src/some/path</code>의 무언가를 가져올 때, <code class="hljs-text">import something from 'some/path';</code>와 같이 가져올 수 있다.</p>
<p><code class="hljs-text">alias</code>는 웹팩의 <code class="hljs-text">resolve.alias</code>와 같은 역할을 하며, <code class="hljs-text">src/some/path</code>의 무언가를 가져올 때, <code class="hljs-text">import something from '~/some/path';</code>와 같이 가져올 수 있다.</p>
<h2>package.json 을 이용하는 방법</h2>
<p><code class="hljs-text">alias</code>를 지정하기 위한 디렉토리에서 <code class="hljs-text">package.json</code>을 생성한 뒤, <code class="hljs-text">alias</code>로 지정하고자 하는 값을 <code class="hljs-text">name</code>에 준다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">{
"name": "~"
}</code></pre></div>
- <![CDATA[모르고 지나쳤을 수도 있는 Sequalize 메소드]]>https://wonism.github.io/unknown-sequelize-methods/https://wonism.github.io/unknown-sequelize-methods/Sat, 14 Apr 2018 12:04:48 GMT<h2>IS NOT NULL 조건 주기</h2>
<p><code class="hljs-text">where</code>절에 들어갈 객체의 에서 <code class="hljs-text">IS NOT NULL</code>이 되어야 할 <code class="hljs-text">컬럼</code>의 값을 <code class="hljs-text">{ ne: null }</code>로 준다.
<code class="hljs-text">column_name</code>이 <code class="hljs-text">null</code>이 아닌 <code class="hljs-text">Row</code>들을 구할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">TableName
<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
where <span class="token punctuation">:</span> <span class="token punctuation">{</span> column_name<span class="token punctuation">:</span> <span class="token punctuation">{</span> ne<span class="token punctuation">:</span> <span class="token keyword">null</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token comment">// ne : Not Equal</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">rows</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">ne</code>는 <code class="hljs-text">not equal</code>을 뜻하며, 이외에도 <code class="hljs-text">gt(greater than)</code>, <code class="hljs-text">lt(less than)</code>, <code class="hljs-text">in(where in Array)</code>, <code class="hljs-text">like</code> 등이 있다.</p>
<h2>INSERT 전에 존재 여부 체크하기</h2>
<p><code class="hljs-text">findOrCreate</code>메소드는 <code class="hljs-text">Sequelize</code>에서 <code class="hljs-text">Row</code>를 <code class="hljs-text">INSERT</code>하기 전에 존재하는지 여부를 체크한다.<br />
그 다음, <code class="hljs-text">Row</code>가 존재하면 <code class="hljs-text">INSERT</code>하지 않고, 존재하지 않으면 <code class="hljs-text">INSERT</code>한다.<br />
이전에 개인 프로젝트를 진행할 때 이러한 처리를 로우 쿼리로써 해결했었지만, <code class="hljs-text">findOrCreate</code>메소드가 있었다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">TableName
<span class="token punctuation">.</span><span class="token function">findOrCreate</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
where <span class="token punctuation">:</span> <span class="token punctuation">{</span> column_name<span class="token punctuation">:</span> <span class="token string">'VALUE1'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
defaults<span class="token punctuation">:</span> <span class="token punctuation">{</span> column_name<span class="token punctuation">:</span> <span class="token string">'VALUE1'</span><span class="token punctuation">,</span> column_name2<span class="token punctuation">:</span> <span class="token string">'VALUE2'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">rows</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">TableName</code> 테이블에 <code class="hljs-text">where</code> 에 해당하는 <code class="hljs-text">Row</code>가 있으면, <code class="hljs-text">INSERT</code>하지 않고, 해당하는 <code class="hljs-text">Row</code>가 없으면, <code class="hljs-text">default</code>에 있는 값들을 <code class="hljs-text">INSERT</code>한다.</p>
<h2>Increment integer 인 값을 1 증가 시키기</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* import sequelize from 'sequelize'; */</span>
TableName
<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
increment_attribute<span class="token punctuation">:</span> sequelize<span class="token punctuation">.</span><span class="token function">literal</span><span class="token punctuation">(</span><span class="token string">'increment_attribute + 1'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token comment">// Query options</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">rows</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Do something</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
- <![CDATA[resolve.alias로 import 개선하기]]>https://wonism.github.io/resolve-import-path/https://wonism.github.io/resolve-import-path/Sat, 14 Apr 2018 11:38:44 GMT<h2>상대경로, 무엇이 문제인가?</h2>
<p>파일의 구조가 복잡한 프로젝트에서 <code class="hljs-text">import</code> 또는 <code class="hljs-text">require</code>를 사용할 때, 상대적인 경로로 파일을 불러오는 것은 귀찮을 뿐더러 실수를 유발할 수 있다.<br />
상위 폴더로 가기 위해 <code class="hljs-text">..</code>를 사용하는 데, 아래처럼 수많은 <code class="hljs-text">..</code>가 필요할 수 있기 때문이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// /A_PATH/a.js</span>
<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> userSelectors <span class="token keyword">from</span> <span class="token string">'../../../store/user/selectors'</span><span class="token punctuation">;</span></code></pre></div>
<p>또한, 다른 경로에서 같은 파일을 불러올 경우 같은 역할을 하는 코드임에도 불구하고, <code class="hljs-text">..</code>의 개수가 다르다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// /B_PATH/b.js</span>
<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> userSelectors <span class="token keyword">from</span> <span class="token string">'../store/user/selectors'</span><span class="token punctuation">;</span></code></pre></div>
<h2>절대경로로 가져오는 방법</h2>
<p><code class="hljs-text">절대경로</code>로 파일을 불러온 다면, 아래 코드를 어떤 파일에서든 똑같이 사용할 수 있을 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> userSelectors <span class="token keyword">from</span> <span class="token string">'~/store/user/selectors'</span><span class="token punctuation">;</span></code></pre></div>
<p>위처럼 <code class="hljs-text">절대경로</code>로 파일을 불러오려면, <code class="hljs-text">webpack.config.js</code>의 <code class="hljs-text">resolve.alias</code>를 설정해주면 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">module<span class="token punctuation">.</span>esports <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token operator">...</span>
resolve<span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token operator">...</span>
alias<span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token string">'~'</span><span class="token punctuation">:</span> path<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'src'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
- <![CDATA[프론트엔드 개발자를 위한 VIM 설정]]>https://wonism.github.io/vim-for-fe-dev/https://wonism.github.io/vim-for-fe-dev/Sat, 24 Mar 2018 13:40:32 GMT<h2>Vundle & Janus 설치</h2>
<p>플러그인 매니저인 <a href="https://github.com/VundleVim/Vundle.vim">Vundle</a>과
플러그인 & 매퍼인 <a href="https://github.com/carlhuda/janus">Janus</a>을 설치해야한다.<br />
이들은 다음 명령어를 통해 설치할 수 있다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text"># Vundle
$ git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
# Janus
$ curl -L https://bit.ly/janus-bootstrap | bash</code></pre></div>
<h2>Vundle 설정</h2>
<p><code class="hljs-text">.vimrc</code>파일의 가장 상단에 다음 설정을 붙여넣는다.<br />
(<code class="hljs-text">"</code>는 주석이다.)</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">set nocompatible " be iMproved, required
filetype off " required
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" 플러그인들은 vundle#begin과 vundle#end 사이에 있어야한다.
" 이 플러그인은 반드시 필요한 플러그인이다.
Plugin 'VundleVim/Vundle.vim'
call vundle#end() " required
filetype plugin indent on " required</code></pre></div>
<h2>Vundle 명령어</h2>
<p><code class="hljs-text">vim</code> 실행 중일 때, <code class="hljs-text">:PluginList</code> 등의 명령어를 입력할 수 있다.
|명령어|하는 일|
|------|-------|
|:PluginList|설정된 플러그인 리스트|
|:PluginInstall|플러그인 설치 (<code class="hljs-text">!</code>와 함께 사용하면 업데이트이며, :PluginUpdae도 가능)|
|:PluginSearch foo|<code class="hljs-text">foo</code>를 검색한다.|
|:PluginClean|사용되지 않는 플러그인을 삭제한다.|</p>
<h2>Vundle 플러그인 설치</h2>
<p>다음과 같은 플러그인을 <code class="hljs-text">.vimrc</code>에 넣고, <code class="hljs-text">:PluginInstall</code>을 실행한다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">call vundle#begin()
Plugin 'VundleVim/Vundle.vim'
Plugin 'vim-airline/vim-airline'
Plugin 'tpope/vim-fugitive'
Plugin 'isRuslan/vim-es6'
Plugin 'pangloss/vim-javascript'
Plugin 'mxw/vim-jsx'
Plugin 'rstacruz/sparkup', {'rtp': 'vim/'}
call vundle#end() " required</code></pre></div>
<h2>Janus 설정</h2>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">""
"" Janus setup
""
if has('win32') || has('win64') || has('win32unix')
let g:janus_path = escape(expand("~/.vim/janus/vim"), ' ')
let g:janus_vim_path = escape(expand("~/.vim/janus/vim"), ' ')
else
let g:janus_path = escape(fnamemodify(resolve(expand("<sfile>:p")), ":h"), ' ')
let g:janus_vim_path = escape(fnamemodify(resolve(expand("<sfile>:p" . "vim")), ":h"), ' ')
endif
let g:janus_custom_path = expand("~/.janus")
exe 'source ' . g:janus_vim_path . '/core/before/plugin/janus.vim'
call janus#add_group("tools")
call janus#add_group("langs")
call janus#add_group("colors")
if filereadable(expand("~/.vimrc.before"))
source ~/.vimrc.before
endif
exe 'source ' . g:janus_vim_path . '/core/plugins.vim'
call janus#load_pathogen()</code></pre></div>
- <![CDATA[redux-saga를 redux-observable와 비교해 살펴보기]]>https://wonism.github.io/redux-saga-vs-redux-observable/https://wonism.github.io/redux-saga-vs-redux-observable/Fri, 16 Feb 2018 12:24:12 GMT<p><code class="hljs-text">redux-observable</code>과 <code class="hljs-text">redux-saga</code>는 <code class="hljs-text">redux</code>의 비동기 액션을 처리하기 위한 라이브러리다.<br />
기존에 회사 프로젝트에서는 비동기 액션을 처리하기 위해 <code class="hljs-text">redux-thunk</code>와 <code class="hljs-text">redux-observable</code>을 사용하고 있었다.<br />
하지만 팀의 규모도 점점 커지는 상황에서 새로운 프로젝트를 진행하게 되었기 때문에 여러 방안들을 검토하게 되었다.
(개인적으로는 <code class="hljs-text">redux-observable</code>을 좋아하지만,)<br />
익혀야할 기술(<code class="hljs-text">RxJS</code>, <code class="hljs-text">Functional programming</code> 등)이 많고 <code class="hljs-text">러닝커브</code>도 가파르기 때문이었다.</p>
<p>팀원의 추천으로 먼저 <code class="hljs-text">redux-saga</code>를 공부해보기로 했고,
<code class="hljs-text">redux-observable</code>과 비교하면서 <code class="hljs-text">redux-observable</code>을 그대로 사용할지, <code class="hljs-text">redux-saga</code>를 새로 적용할지, 아니면 또 다른 라이브러리를 사용할 지 판단하기로 했다.</p>
<h2>어디에 기반을 두었나?</h2>
<p><code class="hljs-text">redux-saga</code>는 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Generator">Generator</a> 기반이며,
<code class="hljs-text">redux-observable</code>은 이름에서 알 수 있듯 <a href="http://reactivex.io/rxjs/">RxJS</a> 기반이다.</p>
<p>먼저, <code class="hljs-text">redux-saga</code>를 살펴보면 <code class="hljs-text">Worker + Watcher</code>라는 구조를 가진다.<br />
<code class="hljs-text">redux-observable</code>은 <code class="hljs-text">Epic</code>이라는 구조를 가지며, 이는 <code class="hljs-text">Type</code>과 <code class="hljs-text">Operators</code>로 구성된다.</p>
<h2>기본적인 사용 방법</h2>
<h3>redux-saga</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> call<span class="token punctuation">,</span> put<span class="token punctuation">,</span> take<span class="token punctuation">,</span> fork<span class="token punctuation">,</span> cancel <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga/effects'</span>
<span class="token comment">// Worker</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'START_TO_DO'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>fetch<span class="token punctuation">,</span> action<span class="token punctuation">.</span>payload<span class="token punctuation">.</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'DONE_SUCCESSFULLY'</span><span class="token punctuation">,</span> data <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Error handling</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'FAILED'</span><span class="token punctuation">,</span> error<span class="token punctuation">:</span> e <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// Watcher</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token keyword">yield</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token string">'DO_SOMETHING'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> backgroundSyncTask <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">fork</span><span class="token punctuation">(</span>worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token string">'STOP_DO_THAT'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Cancelable</span>
<span class="token keyword">yield</span> <span class="token function">cancel</span><span class="token punctuation">(</span>backgroundSyncTask<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>redux-observable</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> combineEpics<span class="token punctuation">,</span> ofType <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-observable'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> switchMap<span class="token punctuation">,</span> takeUntil<span class="token punctuation">,</span> map<span class="token punctuation">,</span> catchError <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs/operators'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> ajax <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'rxjs/observable/dom/ajax'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">epic</span> <span class="token operator">=</span> <span class="token parameter">action$</span> <span class="token operator">=></span>
action$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>
<span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'DO_SOMETHING'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'START_TO_DO'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">switchMap</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
url<span class="token punctuation">:</span> <span class="token string">'/end-points'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>
<span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">res</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'DONE_SUCCESSFULLY'</span><span class="token punctuation">,</span>
data<span class="token punctuation">:</span> res<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">takeUntil</span><span class="token punctuation">(</span>action$<span class="token punctuation">.</span><span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'STOP_DO_THAT'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// Cancelable</span>
<span class="token function">catchError</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">of</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token comment">// Error handling</span>
type<span class="token punctuation">:</span> <span class="token string">'FAILED'</span>
error<span class="token punctuation">:</span> e<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> epics <span class="token operator">=</span> <span class="token function">combineEpics</span><span class="token punctuation">(</span>
epic<span class="token punctuation">,</span>
<span class="token comment">// ...</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>여러 개의 비동기 액션 처리하기</h2>
<h3>redux-saga</h3>
<p><code class="hljs-text">worker</code>를 작성하고, <code class="hljs-text">watcher</code>에 나열한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> res1 <span class="token operator">=</span> <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">worker1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'WORKER_1'</span><span class="token punctuation">,</span> res1 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> res2 <span class="token operator">=</span> <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">worker2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'WORKER_2'</span><span class="token punctuation">,</span> res2 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> res3 <span class="token operator">=</span> <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">worker3</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">'WORKER_3'</span><span class="token punctuation">,</span> res3 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>redux-observable</h3>
<p>각 <code class="hljs-text">epic</code>을 작성하고, <code class="hljs-text">combinEpics</code>를 통해 결합한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">epic1</span> <span class="token operator">=</span> <span class="token parameter">action$</span> <span class="token operator">=></span>
action$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>
<span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'EPIC_1'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">epic2</span> <span class="token operator">=</span> <span class="token parameter">action$</span> <span class="token operator">=></span>
action$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>
<span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'EPIC_2'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">epic3</span> <span class="token operator">=</span> <span class="token parameter">action$</span> <span class="token operator">=></span>
action$<span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>
<span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'EPIC_3'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> epics <span class="token operator">=</span> <span class="token function">combineEpics</span><span class="token punctuation">(</span>
epic1<span class="token punctuation">,</span>
epic2<span class="token punctuation">,</span>
epic3<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>여러 개의 비동기 액션 병렬 처리하기</h2>
<h3>redux-saga</h3>
<p>처리할 비동기 작업을 배열에 넣고, 비구조화 할당(<code class="hljs-text">Destructuring Assignment</code>)을 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>users<span class="token punctuation">,</span> accounts<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token punctuation">[</span>
<span class="token function">call</span><span class="token punctuation">(</span>fetch<span class="token punctuation">,</span> <span class="token string">'/users'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">call</span><span class="token punctuation">(</span>fetch<span class="token punctuation">,</span> <span class="token string">'/accounts'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>redux-observable</h3>
<p><code class="hljs-text">RxJS</code>의 <code class="hljs-text">merge</code>를 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">action$
<span class="token comment">// ...</span>
<span class="token punctuation">.</span><span class="token function">switchMap</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">merge</span><span class="token punctuation">(</span>Promise1<span class="token punctuation">,</span> Promise2<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>Throttling, Debouncing, Retrying</h2>
<h3>redux-saga</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// throttling</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> throttle <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga/effects'</span><span class="token punctuation">;</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">throttle</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">'THROTTLED_ACTION_TYPE'</span><span class="token punctuation">,</span> worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// debouncing</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> delay <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga'</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> call<span class="token punctuation">,</span> cancel<span class="token punctuation">,</span> fork<span class="token punctuation">,</span> take <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga/effects'</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>delay<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> task<span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token string">'DEBOUNCED_ACTION_TYPE'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>task<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">cancel</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
task <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">fork</span><span class="token punctuation">(</span>worker<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// delay can be replaced with this</span>
<span class="token keyword">const</span> <span class="token function-variable function">customDelay</span> <span class="token operator">=</span> <span class="token parameter">ms</span> <span class="token operator">=></span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token parameter">resolve</span> <span class="token operator">=></span> <span class="token function">setTimeout</span><span class="token punctuation">(</span>resolve<span class="token punctuation">,</span> ms<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// debouncing 2</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> delay <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> call<span class="token punctuation">,</span> takeLatest <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-saga/effects'</span><span class="token punctuation">;</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> input <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>delay<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">takeLatest</span><span class="token punctuation">(</span><span class="token string">'DEBOUNCED_ACTION_TYPE'</span><span class="token punctuation">,</span> worker<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// retrying</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">worker</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">3</span><span class="token punctuation">;</span> i <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>fetch<span class="token punctuation">,</span> <span class="token string">'/end-point'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator"><</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>delay<span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'API request failed'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token string">'START_REQUEST'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">call</span><span class="token punctuation">(</span>worker<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'RECEIVE_RESPONSE'</span><span class="token punctuation">,</span>
payload<span class="token punctuation">:</span> result<span class="token punctuation">.</span>body<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">yield</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token string">'GET_FAILED_RESPONSE'</span><span class="token punctuation">,</span>
error<span class="token punctuation">:</span> e<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>redux-observable</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// throttling</span>
action$
<span class="token punctuation">.</span><span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'THROTTLED_ACTION_TYPE'</span><span class="token punctuation">)</span>
<span class="token comment">// ...</span>
<span class="token punctuation">.</span><span class="token function">throtleTime</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
<span class="token comment">// debouncing</span>
action$
<span class="token punctuation">.</span><span class="token function">ofType</span><span class="token punctuation">(</span><span class="token string">'DEBOUNCED_ACTION_TYPE'</span><span class="token punctuation">)</span>
<span class="token comment">// ...</span>
<span class="token punctuation">.</span><span class="token function">debouncing</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
<span class="token comment">// retrying</span>
action$
<span class="token comment">// ...</span>
<span class="token punctuation">.</span><span class="token function">retry</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span></code></pre></div>
<h2>로그 사용하기</h2>
<h3>redux-saga</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">watcher</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> action <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token string">'*'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'action: %s'</span><span class="token punctuation">,</span> action<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'state: %s'</span><span class="token punctuation">,</span> state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<h3>redux-observable</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">action$
<span class="token comment">// ...</span>
<span class="token punctuation">.</span><span class="token function">do</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span></code></pre></div>
<h2>redux-saga 정리</h2>
<p><code class="hljs-text">call</code>, <code class="hljs-text">apply</code>는 부작용을 표현하는 객체를 만드는데 사용되며, <code class="hljs-text">put</code>, <code class="hljs-text">select</code>, <code class="hljs-text">take</code>는 <code class="hljs-text">redux</code>의 <code class="hljs-text">store</code>와 상호작용함으로써, 부작용을 처리한다.(아래 다이어그램 참고)</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">┌───────────────┐
│ Side Effects │
└───────┬───────┘
|
apply, call
|
┌───────┴───────┐
│ Redux Saga │ <----> call, apply, fork,
└───────┬───────┘ spawn, join, cancel
|
put, select,
take(every, latest)
|
┌───────┴───────┐
│ Redux Store │
└───────────────┘</code></pre></div>
<p>몇 가지 기능들만 알면 모든 부작용을 처리할 수 있으며, 코드 또한 간결해진다.<br />
<code class="hljs-text">redux-saga</code>는 <code class="hljs-text">redux-observable</code>만큼 기능들이 강력하지 않는 단점이 있지만,
<code class="hljs-text">액션</code>을 <code class="hljs-text">dispatch</code>하기도 쉬우며, 무엇보다 배우기 쉽다는 장점이 있다.<br />
생산성, 난이도 등 여러 가지를 고려했을 때 부작용을 다루기 위한 충분한 라이브러리이다.</p>
- <![CDATA[RxJS 살펴보기- 5]]>https://wonism.github.io/rxjs-5/https://wonism.github.io/rxjs-5/Mon, 20 Nov 2017 23:48:32 GMT<p><code class="hljs-text">Ctrl+Shift+J</code> (Windows / Linux) 또는 <code class="hljs-text">Cmd+Opt+J</code> (Mac)를 눌러 콘솔창을 연 뒤, 전역 객체에 등록되어 있는 <code class="hljs-text">Rx</code>를 사용하여 예제 코드를 실행할 수 있다.<br />
(* 참고 : <code class="hljs-text">subscription.unsubscribe();</code>을 통해 옵저버블 관찰을 취소할 수 있다.)</p>
<div class="none" id="register-rx"></div>
<h2>Transform Operators</h2>
<p><code class="hljs-text">변형</code> 연산자는 옵저버블의 값의 형태를 변형하는 작업을 한다</p>
<h3>buffer</h3>
<p>제공된 값이 방출될 때까지 값들을 모은 뒤, 배열로 한꺼번에 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> buffer$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">490</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">290</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> bufferedInterval$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">buffer</span><span class="token punctuation">(</span>buffer$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> bufferedInterval$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [0, 1, 2, 3], [4, 5, 6]</span></code></pre></div>
<h3>bufferTime</h3>
<p>주어진 시간이 지날 때까지 방출된 값을 모은 뒤, 배열로 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> bufferTime$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">bufferTime</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> bufferedInterval$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [0, 1, 2], [3, 4, 5, 6], [7, 8, 9, 10], ...</span></code></pre></div>
<h3>concatMap</h3>
<p>내부 옵저버블에 값을 매핑하고, 구독한며 순서대로 값을 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">,</span> <span class="token string">'Goodbye'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> concatMap$ <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">concatMap</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>val<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, World!`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> concatMap$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Hello, World!</span>
<span class="token comment">// Goodbye, World!</span></code></pre></div>
<h3>map</h3>
<p>각 값에 투영함수를 적용하여 값을 변형한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> map$ <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> val <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> map$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2 4 6 8</span></code></pre></div>
<h3>mapTo</h3>
<p>방출되는 값을 일정한 값으로 매핑한다. (방출되는 값이 상수로 변환된다고 보면 된다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mapTo$ <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token string">'CONSTANT'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> mapTo$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// CONSTANT</span>
<span class="token comment">// CONSTANT</span>
<span class="token comment">// CONSTANT</span>
<span class="token comment">// ...</span></code></pre></div>
<h3>mergeMap</h3>
<p>내부 옵저버블이 방출되면, 해당 값을 바깥 옵저버블과 함께 병합한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> outer$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> inner$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> mergeMap$ <span class="token operator">=</span> outer$<span class="token punctuation">.</span><span class="token function">mergeMap</span><span class="token punctuation">(</span>
<span class="token parameter">outer</span> <span class="token operator">=></span> inner$<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>
<span class="token parameter">inner</span> <span class="token operator">=></span>
<span class="token template-string"><span class="token string">`Outer : </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>outer<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> / Inner: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>inner<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span>
<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> mergeMap$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// after 1s</span>
<span class="token comment">// Outer : a / Inner : 0</span>
<span class="token comment">// Outer : b / Inner : 0</span>
<span class="token comment">// after 2s</span>
<span class="token comment">// Outer : a / Inner : 1</span>
<span class="token comment">// Outer : b / Inner : 1</span>
<span class="token comment">// after 3s</span>
<span class="token comment">// Outer : a / Inner : 2</span>
<span class="token comment">// Outer : b / Inner : 2</span></code></pre></div>
<h3>pluck</h3>
<p>프로퍼티를 선택한다. (중첩된 프로퍼티를 가져오기 위해서는 <code class="hljs-text">n</code>개의 프로퍼티를 전달한다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> click$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> pluck$ <span class="token operator">=</span> click$<span class="token punctuation">.</span><span class="token function">pluck</span><span class="token punctuation">(</span><span class="token string">'target'</span><span class="token punctuation">,</span> <span class="token string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> pluck$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>위 코드는 <code class="hljs-text">pluck</code>을 통해 클릭된 노드의 내용을 가져온다.<br />
이를 <code class="hljs-text">map</code>을 통해 구현하면 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> click$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> map$ <span class="token operator">=</span> click$<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> map$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">map</code>보다는 <code class="hljs-text">pluck</code>이 좀 더 간결하다.
(물론, <code class="hljs-text">lodash</code>의 <code class="hljs-text">fp</code>를 사용하면, <code class="hljs-text">map(fp.get('target.value'))</code>처럼 <code class="hljs-text">pluck</code>과 유사하게 사용할 수 있다.)</p>
<h3>reduce</h3>
<p>소스가 완료될 때, 한 개의 값으로 줄여진 값을 방출한다.<br />
<code class="hljs-text">Array.prototype.reduce</code>처럼 순회하면서 실행할 콜백함수와 초기값을 전달받는다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> reduce$ <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prev<span class="token punctuation">,</span> curr</span><span class="token punctuation">)</span> <span class="token operator">=></span> prev <span class="token operator">+</span> curr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> reduce$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 10</span></code></pre></div>
<h3>scan</h3>
<p>소스가 완료되어 하나의 값을 방출할 때까지의 값들을 차례로 방출한다.<br />
<code class="hljs-text">reduce</code>와 하는 일이 거의 유사하지만, 중간 과정의 값들이 방출된다는 점이 다르다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> scan$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">scan</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prev<span class="token punctuation">,</span> curr</span><span class="token punctuation">)</span> <span class="token operator">=></span> prev <span class="token operator">+</span> curr<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> scan$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0 1 3 6 10</span></code></pre></div>
<h3>switchMap</h3>
<p>mergeMap과 비슷하지만, 외부 옵저버블이 내부 옵저버블의 이전 구독을 취소할 때 발생한다.<br />
즉, 외부 옵저버블이 발생될 때마다 내부 옵저버블의 새로운 구독이 시작된다.</p>
<p>예를 들어 아래와 같은 코드는 클릭을 할 때마다 이전의 구독이 취소되고 새 구독이 시작된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> click$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> inner$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> switchMap$ <span class="token operator">=</span> click$<span class="token punctuation">.</span><span class="token function">switchMap</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> inner$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> switchMap$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// click</span>
<span class="token comment">// 0</span>
<span class="token comment">// 1</span>
<span class="token comment">// 2</span>
<span class="token comment">// click</span>
<span class="token comment">// 0</span>
<span class="token comment">// click</span>
<span class="token comment">// 0</span>
<span class="token comment">// ...</span></code></pre></div>
<h2>정리</h2>
<p>자주 사용되거나 알아두면 좋을 <code class="hljs-text">변형 연산자</code>에 대한 간단한 설명과 사용 예제를 정리하였다.<br />
더 많은 연산자를 공부하려면 아래 사이트를 참고하는 것이 좋다.</p>
<h2>참고</h2>
<ul>
<li><a href="http://reactivex.io/rxjs">http://reactivex.io/rxjs</a></li>
<li><a href="https://www.learnrxjs.io">https://www.learnrxjs.io</a></li>
</ul>
<p>※ 모든 예제 코드는 직접 작성한 코드입니다. 다른 곳에서 사용하실 경우 출처를 남겨주시면 감사하겠습니다.</p>
- <![CDATA[RxJS 살펴보기- 4]]>https://wonism.github.io/rxjs-4/https://wonism.github.io/rxjs-4/Sun, 19 Nov 2017 23:03:27 GMT<p><code class="hljs-text">Ctrl+Shift+J</code> (Windows / Linux) 또는 <code class="hljs-text">Cmd+Opt+J</code> (Mac)를 눌러 콘솔창을 연 뒤, 전역 객체에 등록되어 있는 <code class="hljs-text">Rx</code>를 사용하여 예제 코드를 실행할 수 있다.<br />
(* 참고 : <code class="hljs-text">subscription.unsubscribe();</code>을 통해 옵저버블 관찰을 취소할 수 있다.)</p>
<div class="none" id="register-rx"></div>
<h2>Filtering Operators</h2>
<p><code class="hljs-text">필터</code> 연산자는 옵저버블의 원하는 값만을 선택해 여과하게 해준다.<br />
바로 아래 있는 컴퍼넌트는 몇 가지 옵저버블 예제를 직접 확인할 수 있는 컴퍼넌트이다.</p>
<div id="rx-with-input"></div>
<h3>debounceTime</h3>
<p>출력 사이의 지정된 시간보다 적은 시간에 방출된 모든 값들을 버린다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> input <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'input'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> input$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Ovservable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> <span class="token string">'input'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">pluck</span><span class="token punctuation">(</span><span class="token string">'target'</span><span class="token punctuation">,</span> <span class="token string">'value'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">debounceTime</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> input$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>distinctUntilChanged</h3>
<p>현재 값이 이전의 마지막 값과 다른 경우에만 값을 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> input <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'input'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> input$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Ovservable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> <span class="token string">'input'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">pluck</span><span class="token punctuation">(</span><span class="token string">'target'</span><span class="token punctuation">,</span> <span class="token string">'value'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">debounceTime</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">distinctUntilChanged</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> input$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>(충분한 <code class="hljs-text">debounceTime</code>이 주어졌다고 가정하고) <code class="hljs-text">Hello</code>를 입력한 뒤, 다시 <code class="hljs-text">Hello</code>를 입력하면 옵저버는 아무런 반응을 하지 않는다는 것을 볼 수 있다.</p>
<h3>throttleTime</h3>
<p>지정된 시간동안 처음의 값을 제외한 모든 값들을 버린다.<br />
스크롤 이벤트를 제어하는 데 주로 사용된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> input$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Ovservable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> <span class="token string">'input'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">throttleTime</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">pluck</span><span class="token punctuation">(</span><span class="token string">'target'</span><span class="token punctuation">,</span> <span class="token string">'value'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> input$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> scroll$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>window<span class="token punctuation">,</span> <span class="token string">'scroll'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">throttleTime</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> scroll$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>filter</h3>
<p><code class="hljs-text">filter</code>에 전달된 값을 통해 수행된 연산의 결과가 <code class="hljs-text">true</code>를 반환하는 값들만 방출시킨다.<br />
(<code class="hljs-text">Array.prototype.filter</code>와 같은 역할을 한다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> filtered$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">value</span> <span class="token operator">=></span> value <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> filtered$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2, 4</span></code></pre></div>
<h3>take</h3>
<p><code class="hljs-text">take</code>에 전달된 값과 같은 개수의 값들만을 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> take5$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> take5$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>takeUntil</h3>
<p>주어진 옵저버블이 방출될 때까지 값을 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> filter$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">i</span> <span class="token operator">=></span> i <span class="token operator">></span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> takeUntil$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">takeUntil</span><span class="token punctuation">(</span>filter$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> takeUntil$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1, 2, 3, 4, 5</span>
<span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> timer$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> takeUntil$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">takeUntil</span><span class="token punctuation">(</span>timer$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> takeUntil$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0, 1, 2, 3</span></code></pre></div>
<h2>정리</h2>
<p>자주 사용되거나 알아두면 좋을 <code class="hljs-text">필터링 연산자</code>에 대한 간단한 설명과 사용 예제를 정리하였다.<br />
더 많은 연산자를 공부하려면 아래 사이트를 참고하는 것이 좋다.<br /></p>
<p>다음에는 <code class="hljs-text">Observable</code>의 <code class="hljs-text">Transformation</code> 연산에 대해 알아보겠다.</p>
<h2>참고</h2>
<ul>
<li><a href="http://reactivex.io/rxjs">http://reactivex.io/rxjs</a></li>
<li><a href="https://www.learnrxjs.io">https://www.learnrxjs.io</a></li>
</ul>
<p>※ 모든 예제 코드는 직접 작성한 코드입니다. 다른 곳에서 사용하실 경우 출처를 남겨주시면 감사하겠습니다.</p>
- <![CDATA[RxJS로 만든 간단한 예제 프로그램]]>https://wonism.github.io/rxjs-ex-1/https://wonism.github.io/rxjs-ex-1/Sat, 18 Nov 2017 12:57:25 GMT<h2>마우스를 바라보는 3D 효과</h2>
<div id="lerp-animation"></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// 리액트 컴퍼넌트를 만드는 코드이지만,</span>
<span class="token comment">// 분석하기 어려운 코드는 아니다.</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> Rx <span class="token keyword">from</span> <span class="token string">'rxjs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> styled <span class="token keyword">from</span> <span class="token string">'styled-components'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> url <span class="token keyword">from</span> <span class="token string">'./logan.jpg'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> StyledDiv <span class="token operator">=</span> styled<span class="token punctuation">.</span>div<span class="token template-string"><span class="token string">`
position: relative;
margin: 10vh auto;
width: 50%;
height: 30vh;
background-color: bisque;
transform: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token parameter">props</span> <span class="token operator">=></span> <span class="token punctuation">(</span>props<span class="token punctuation">.</span>transform<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">;
overflow: hidden;
img {
position: absolute;
top: 0;
right: 0;
left: 0;
margin: auto;
width: 100%;
}
`</span></span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> <span class="token function">lerp</span><span class="token punctuation">(</span><span class="token parameter">start<span class="token punctuation">,</span> end</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> dx <span class="token operator">=</span> end<span class="token punctuation">.</span>x <span class="token operator">-</span> start<span class="token punctuation">.</span>x<span class="token punctuation">;</span>
<span class="token keyword">const</span> dy <span class="token operator">=</span> end<span class="token punctuation">.</span>y <span class="token operator">-</span> start<span class="token punctuation">.</span>y<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
x<span class="token punctuation">:</span> start<span class="token punctuation">.</span>x <span class="token operator">+</span> <span class="token punctuation">(</span>dx <span class="token operator">*</span> <span class="token number">0.1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
y<span class="token punctuation">:</span> start<span class="token punctuation">.</span>y <span class="token operator">+</span> <span class="token punctuation">(</span>dy <span class="token operator">*</span> <span class="token number">0.1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
transform<span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>rotateElement <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">rotateElement</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> docEl <span class="token operator">=</span> document<span class="token punctuation">.</span>documentElement<span class="token punctuation">;</span>
<span class="token keyword">const</span> mouseMove$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>docEl<span class="token punctuation">,</span> <span class="token string">'mousemove'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> x<span class="token punctuation">:</span> e<span class="token punctuation">.</span>clientX<span class="token punctuation">,</span> y<span class="token punctuation">:</span> e<span class="token punctuation">.</span>clientY <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> touchMove$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>docEl<span class="token punctuation">,</span> <span class="token string">'touchmove'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> x<span class="token punctuation">:</span> e<span class="token punctuation">.</span>touches<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>clientX<span class="token punctuation">,</span> y<span class="token punctuation">:</span> e<span class="token punctuation">.</span>touches<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>clientY <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> move$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">merge</span><span class="token punctuation">(</span>mouseMove$<span class="token punctuation">,</span> touchMove$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> animationFrame$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> Rx<span class="token punctuation">.</span>Scheduler<span class="token punctuation">.</span>animationFrame<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> smoothMove$ <span class="token operator">=</span> animationFrame$
<span class="token punctuation">.</span><span class="token function">withLatestFrom</span><span class="token punctuation">(</span>move$<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">frame<span class="token punctuation">,</span> move</span><span class="token punctuation">)</span> <span class="token operator">=></span> move<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">scan</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">current<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=></span> App<span class="token punctuation">.</span><span class="token function">lerp</span><span class="token punctuation">(</span>current<span class="token punctuation">,</span> next<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
smoothMove$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>rotateElement<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">rotateElement</span><span class="token punctuation">(</span><span class="token parameter">pos</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> docEl <span class="token operator">=</span> document<span class="token punctuation">.</span>documentElement<span class="token punctuation">;</span>
<span class="token keyword">const</span> rotX <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>pos<span class="token punctuation">.</span>y <span class="token operator">/</span> docEl<span class="token punctuation">.</span>clientHeight<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token operator">-</span><span class="token number">50</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">25</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> rotY <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>pos<span class="token punctuation">.</span>x <span class="token operator">/</span> docEl<span class="token punctuation">.</span>clientWidth<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">50</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">25</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> transform <span class="token operator">=</span> <span class="token template-string"><span class="token string">`rotateX(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rotX<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">deg) rotateY(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>rotY<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">deg);`</span></span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> transform <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>div<span class="token operator">></span>
<span class="token operator"><</span>StyledDiv transform<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>transform<span class="token punctuation">}</span><span class="token operator">></span>
<span class="token operator"><</span>img src<span class="token operator">=</span><span class="token punctuation">{</span>url<span class="token punctuation">.</span>default<span class="token punctuation">}</span> alt<span class="token operator">=</span><span class="token string">"rx example"</span> <span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>StyledDiv<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> App<span class="token punctuation">;</span></code></pre></div>
- <![CDATA[RxJS 살펴보기- 3]]>https://wonism.github.io/rxjs-3/https://wonism.github.io/rxjs-3/Thu, 16 Nov 2017 22:56:32 GMT<p><code class="hljs-text">Ctrl+Shift+J</code> (Windows / Linux) 또는 <code class="hljs-text">Cmd+Opt+J</code> (Mac)를 눌러 콘솔창을 연 뒤, 전역 객체에 등록되어 있는 <code class="hljs-text">Rx</code>를 사용하여 예제 코드를 실행할 수 있다.<br />
(* 참고 : <code class="hljs-text">subscription.unsubscribe();</code>을 통해 옵저버블 관찰을 취소할 수 있다.)</p>
<div class="none" id="register-rx"></div>
<h2>Conditional Operators</h2>
<p><code class="hljs-text">조건</code> 연산자는 특정 조건에서 무언가를 수행할 수 있게 해준다.</p>
<h3>defaultIfEmpty</h3>
<p>아무것도 방출되지 않으면, 주어진 값을 방출한다.<br />
(<code class="hljs-text">of</code>에 <code class="hljs-text">undefined</code>, <code class="hljs-text">null</code>를 넘기면 이들이 방출된 것으로 간주되어 주어진 값이 방출되지 않는다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> empty$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> defaultIfEmpty$ <span class="token operator">=</span> empty$<span class="token punctuation">.</span><span class="token function">defaultIfEmpty</span><span class="token punctuation">(</span><span class="token string">'Empty Observable'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> defaultIfEmpty$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Empty Observable</span>
<span class="token keyword">var</span> empty$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> defaultIfEmpty$ <span class="token operator">=</span> empty$<span class="token punctuation">.</span><span class="token function">defaultIfEmpty</span><span class="token punctuation">(</span><span class="token string">'Empty Observable'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> defaultIfEmpty$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Empty Observable</span></code></pre></div>
<h3>every</h3>
<p>모든 값들이 조건을 통과하면 <code class="hljs-text">true</code> 그렇지 않으면 <code class="hljs-text">false</code>가 반환된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> mixed$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> areNotEvens$ <span class="token operator">=</span> mixed$<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> val <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> areNotEvens$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// false</span>
<span class="token keyword">var</span> evens$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> areEvens$ <span class="token operator">=</span> evens$<span class="token punctuation">.</span><span class="token function">every</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> val <span class="token operator">%</span> <span class="token number">2</span> <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> areEvens$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// true</span></code></pre></div>
<h2>Creation Operators</h2>
<p><code class="hljs-text">생성</code> 연산자는 옵저버블을 만들 때 사용된다.<br />
모든 것들을 스트림으로 바꾸는 게 가능하다.</p>
<h3>create</h3>
<p>함수를 통해 옵저버블을 생성한다.<br />
매개변수로 전달된 <code class="hljs-text">observer</code>의 <code class="hljs-text">next</code> 메소드를 실행할 때마다 값이 생성된다.<br />
또한, <code class="hljs-text">observer</code>는 <code class="hljs-text">error</code>메소드와 <code class="hljs-text">complete</code>메소드가 있으며, 이름대로 각각 에러를 발생시키거나 옵저버블을 완료시킨다.<br />
(주의할 것은 <code class="hljs-text">error</code> 또한 옵저버블을 종료시킨다는 것이다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> helloWorld$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">observer</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
observer<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
observer<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Error'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
observer<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token string">'World'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// observer.next()는 undefined를 반환하기 때문에 체이닝할 수 없다.</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// subscribe에 객체를 전달할 수도 있으며,</span>
<span class="token comment">// 이 객체는 `next`, `error`, `complete` 등의 프로퍼티를 가진다.</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> helloWorld$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
<span class="token function">next</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">error</span><span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">compelete</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'DONE'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Hello</span>
<span class="token comment">// World</span>
<span class="token comment">// Error</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">observer</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> interval <span class="token operator">=</span> window<span class="token punctuation">.</span><span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> observer<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0</span>
<span class="token comment">// 1</span>
<span class="token comment">// 2</span>
<span class="token comment">// ...</span></code></pre></div>
<h3>from</h3>
<p>배열, 프로미스 등을 옵저버블로 만든다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> array$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> array$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1, 2, 3, 4, 5</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> promise$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token parameter">resolve</span> <span class="token operator">=></span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'Promise'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> promise$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Promise</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> string$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">'String'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> string$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// S, t, r, i, n, g</span></code></pre></div>
<h3>fromEvent</h3>
<p>이벤트를 옵저버블 시퀀스로 만든다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> event$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> coords$ <span class="token operator">=</span> event$<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> e<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> coords$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// DOM Element</span></code></pre></div>
<h3>of</h3>
<p>인자로 전달된 값들을 시퀀스로 만든다.</p>
<p><strong>※ 주의</strong> : <code class="hljs-text">from</code>에서 배열을 전달하는 것과 헷갈리면 안 된다.<br />
(<code class="hljs-text">Function.prototype.call</code>과 <code class="hljs-text">Function.prototype.apply</code>의 차이처럼)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token punctuation">{</span> num<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token function">hello</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">'Hello'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { num: 42 }, [1, 2, 3], function hello() { return 'Hello'; }</span></code></pre></div>
<h2>정리</h2>
<p>자주 사용되거나 알아두면 좋을 <code class="hljs-text">조건 연산자</code>와 <code class="hljs-text">생성 연산자</code>에 대한 간단한 설명과 사용 예제를 정리하였다.<br />
더 많은 연산자를 공부하려면 아래 사이트를 참고하는 것이 좋다.<br /></p>
<p>다음에는 <code class="hljs-text">Observable</code>의 <code class="hljs-text">Filtering</code> 연산에 대해 알아보겠다.</p>
<h2>참고</h2>
<ul>
<li><a href="http://reactivex.io/rxjs">http://reactivex.io/rxjs</a></li>
<li><a href="https://www.learnrxjs.io">https://www.learnrxjs.io</a></li>
</ul>
<p>※ 모든 예제 코드는 직접 작성한 코드입니다. 다른 곳에서 사용하실 경우 출처를 남겨주시면 감사하겠습니다.</p>
- <![CDATA[RxJS 살펴보기- 2]]>https://wonism.github.io/rxjs-2/https://wonism.github.io/rxjs-2/Tue, 14 Nov 2017 23:52:58 GMT<p><code class="hljs-text">Ctrl+Shift+J</code> (Windows / Linux) 또는 <code class="hljs-text">Cmd+Opt+J</code> (Mac)를 눌러 콘솔창을 연 뒤, 전역 객체에 등록되어 있는 <code class="hljs-text">Rx</code>를 사용하여 예제 코드를 실행할 수 있다.<br />
(* 참고 : <code class="hljs-text">subscription.unsubscribe();</code>을 통해 옵저버블 관찰을 취소할 수 있다.)</p>
<div class="none" id="register-rx"></div>
<h2>Combination Operators</h2>
<p><code class="hljs-text">조합</code> 연산자는 여러 <code class="hljs-text">옵저버블</code>을 결합할 수 있게 해준다.</p>
<h3>combineAll</h3>
<p>외부 옵저버블이 완료되면, 내부 옵저버블(옵저버블의 옵저버블)의 최근 값들을 출력한다.</p>
<p><code class="hljs-text">combineAll</code>에 함수가 전달되면, 각각의 내부 옵저버블의 최근 값과 함께 호출된다.<br />
그리고, 함수가 전달되지 않으면, 가장 최근 값의 배열이 옵저버블 출력에 의해 방출된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// Pass the function in `combineAll`</span>
<span class="token keyword">var</span> arr$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> example$ <span class="token operator">=</span> arr$<span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span>Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">,</span> <span class="token string">'World'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> combined$ <span class="token operator">=</span> example$<span class="token punctuation">.</span><span class="token function">combineAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> combined$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Value from inner Observable:'</span><span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Value from inner Observable: ["Hello"]</span>
<span class="token comment">// Value from inner Observable: ["World"]</span>
<span class="token comment">// Does not Pass the function in `combineAll`</span>
<span class="token comment">// Does not Pass the function in `combineAll`</span>
<span class="token keyword">var</span> arr$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> example$ <span class="token operator">=</span> arr$<span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span>Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">,</span> <span class="token string">'World'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> combined$ <span class="token operator">=</span> example$<span class="token punctuation">.</span><span class="token function">combineAll</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>val<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, Wonism!`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> combined$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token parameter">val</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Value with delivered function to `combineAll`:'</span><span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Value with delivered function to `combineAll`: Hello, Wonism!</span>
<span class="token comment">// Value with delivered function to `combineAll`: Bye, Wonism!</span></code></pre></div>
<h3>combineLatest</h3>
<p>여러 옵저버블의 그룹이 주어지고 그 중 하나가 방출될 때, 각각의 최신 값들을 방출한다.<br />
두 옵저버블을 <code class="hljs-text">combineLatest</code>로 조합한 옵저버벌을 시간축에 그리면 다음과 같다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">---a------b--------------c------>
-1-----2-----3----4---5-----6--->
vvvvvvvvv combineLatest vvvvvvvvv
---a1--a2-b2-b3---b4--b5-c5-c6--></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> firstOb$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> secondOb$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> combined$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">combineLatest</span><span class="token punctuation">(</span>firstOb$<span class="token punctuation">,</span> secondOb$<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> combined$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0, 0</span>
<span class="token comment">// 1, 0</span>
<span class="token comment">// 1, 1</span>
<span class="token comment">// 1, 2</span>
<span class="token comment">// 2, 2</span>
<span class="token comment">// 2, 3</span>
<span class="token comment">// 2, 4</span>
<span class="token comment">// ...</span></code></pre></div>
<h3>concat</h3>
<p>옵저버블을 순서대로 구독한다. 이 때, 이전 시퀀스가 완료되어야만 다음 시퀀스가 시작된다.<br />
이전 시퀀스가 끝나지 않으면 다음 시퀀스가 실행되지 않는다.<br /></p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">----a--b--c-->
--1--2----3--4->
vvvvvvvvvvv concat vvvvvvvvvvv
----a--b--c-----1--2----3--4-></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> one$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> two$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> concatenated$ <span class="token operator">=</span> one$<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>two$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> concatenated$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1</span>
<span class="token comment">// a</span>
<span class="token comment">// 2</span>
<span class="token comment">// b</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> one$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> two$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> delayedOne$ <span class="token operator">=</span> one$<span class="token punctuation">.</span><span class="token function">delay</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> concatenated$ <span class="token operator">=</span> delayedOne$<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>two$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> concatenated$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// after 1s</span>
<span class="token comment">// 1</span>
<span class="token comment">// a</span>
<span class="token comment">// 2</span>
<span class="token comment">// b</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> unfinishableOne$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> two$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'This won\'t not be finished'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> concatenated$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>
unfinishableOne$<span class="token punctuation">,</span>
two$<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> concatenated$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>forkJoin</h3>
<p><code class="hljs-text">forkJoin</code>은 <code class="hljs-text">Promise.all</code>과 비슷하다.<br />
모든 옵저버블이 완료되면, 마지막에 각각의 값을 방출한다.<br />
옵저버블을 병렬로 실행하고자 할 때 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> one$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token punctuation">{</span> name<span class="token punctuation">:</span> <span class="token string">'one'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> two$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">timer</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token punctuation">{</span> name<span class="token punctuation">:</span> <span class="token string">'two'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> joined$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">forkJoin</span><span class="token punctuation">(</span>one$<span class="token punctuation">,</span> two$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> joined$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>merge</h3>
<p>여러 옵저버블을 하나로 줄인다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">---a-----b----c----d---->
-----1-----2----3------->
vvvvvvvvv merge vvvvvvvvv
---a-1---b-2--c-3--d----></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> firstOb$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">600</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token string">'A'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> secondOb$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token string">'B'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> thirdOb$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">mapTo</span><span class="token punctuation">(</span><span class="token string">'C'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> merged$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">merge</span><span class="token punctuation">(</span>
firstOb$<span class="token punctuation">,</span>
secondOb$<span class="token punctuation">,</span>
thirdOb$<span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> merged$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// C, B, A, C, B, A, ...</span>
<span class="token keyword">var</span> mergedWithInstance$ <span class="token operator">=</span> firstOb$<span class="token punctuation">.</span><span class="token function">merge</span><span class="token punctuation">(</span>thirdOb$<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> mergedWithInstance$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// C, A, C, A, C, C, A, ...</span></code></pre></div>
<h3>pairwise</h3>
<p>이전 값과 현재 값을 배열로 방출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> interval$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> pairwise$ <span class="token operator">=</span> interval$<span class="token punctuation">.</span><span class="token function">pairwise</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> pairwise$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// [0, 1], [1, 2], [2, 3], [3, 4]</span></code></pre></div>
<h3>startWith</h3>
<p><code class="hljs-text">startWith</code>는 해당 값을 먼저 방출하게 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> source$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> sourceWithStart$ <span class="token operator">=</span> source$<span class="token punctuation">.</span><span class="token function">startWith</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">9</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> sourceWithStart$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// -10, -9, 1, 2, 3</span></code></pre></div>
<h3>withLatestFrom</h3>
<p>옵저버블과 <code class="hljs-text">withLatestFrom</code>에 전달된 옵저버블이 결합하는데, 이 때 만들어진 옵저버블은 <code class="hljs-text">withLatestFrom</code>을 호출한 옵저버블이 방출될때만 각각의 최신 값을 통해서만 만들어진다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> slower$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> faster$ <span class="token operator">=</span> Rx<span class="token punctuation">.</span>Observable<span class="token punctuation">.</span><span class="token function">interval</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> combined$ <span class="token operator">=</span> slower$
<span class="token punctuation">.</span><span class="token function">withLatestFrom</span><span class="token punctuation">(</span>faster$<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>first<span class="token punctuation">,</span> second<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>first<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>second<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> combined$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 0 1</span>
<span class="token comment">// 1 4</span>
<span class="token comment">// 2 7</span>
<span class="token comment">// 3 10</span>
<span class="token comment">// ...</span>
<span class="token keyword">var</span> combined2$ <span class="token operator">=</span> faster$
<span class="token punctuation">.</span><span class="token function">withLatestFrom</span><span class="token punctuation">(</span>slower$<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>first<span class="token punctuation">,</span> second<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>first<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>second<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> subscription <span class="token operator">=</span> combined2$<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2 0</span>
<span class="token comment">// 3 0</span>
<span class="token comment">// 4 1</span>
<span class="token comment">// 5 1</span>
<span class="token comment">// 6 2</span>
<span class="token comment">// 7 2</span>
<span class="token comment">// ...</span></code></pre></div>
<h2>정리</h2>
<p>자주 사용되거나 알아두면 좋을 <code class="hljs-text">조합 연산자</code>에 대한 간단한 설명과 사용 예제를 정리하였다.<br />
더 많은 연산자를 공부하려면 아래 사이트를 참고하는 것이 좋다.<br /></p>
<p>다음에는 <code class="hljs-text">Observable</code>의 <code class="hljs-text">Conditional</code> 연산과 <code class="hljs-text">Creation</code> 연산에 대해 알아보겠다.</p>
<h2>참고</h2>
<ul>
<li><a href="http://reactivex.io/rxjs">http://reactivex.io/rxjs</a></li>
<li><a href="https://www.learnrxjs.io">https://www.learnrxjs.io</a></li>
</ul>
<p>※ 모든 예제 코드는 직접 작성한 코드입니다. 다른 곳에서 사용하실 경우 출처를 남겨주시면 감사하겠습니다.</p>
- <![CDATA[RxJS 살펴보기- 1]]>https://wonism.github.io/rxjs-1/https://wonism.github.io/rxjs-1/Sat, 11 Nov 2017 14:23:26 GMT<h2>Reactive Programming</h2>
<p><code class="hljs-text">RxJS</code>는 <code class="hljs-text">MS</code>가 만든 <code class="hljs-text">ReactiveX</code>의 <code class="hljs-text">JS</code> 라이브러리로 이에 대해 공부하기 전에 먼저 <code class="hljs-text">Reactive 프로그래밍</code>에 대해 아는 것이 좋다.<br />
<code class="hljs-text">Reactive 프로그래밍</code>은 이름 그대로 데이터의 변화에 반응한다는 뜻을 가지며, <code class="hljs-text">비동기 데이터 스트림</code>을 사용하여 프로그래밍한다.</p>
<p>변수, 이벤트, 데이터 구조 등 어떤 것이든 <code class="hljs-text">비동기 데이터 스트림</code>이 될 수 있다.<br />
이 <code class="hljs-text">비동기 데이터 스트림</code>이라는 단어가 어색할 수도 있다.
하지만, 사실 <code class="hljs-text">비동기 데이터 스트림</code>은 전혀 새로운 개념이 아니다.<br />
이를 간단한 이벤트 처리 예제로 설명해보겠다.</p>
<p>대부분의 <code class="hljs-text">Plain JavaScript</code>, <code class="hljs-text">jQuery</code> 혹은 <code class="hljs-text">ReactJS</code> 등 어떤 프레임워크/라이브러리를 사용했던지 간에 사용자로부터 발생한 비동기적인 <code class="hljs-text">이벤트</code>를 처리해본 경험이 있을 것이다.<br />
예를 들어 클릭 이벤트를 처리한다고 가정할 때 다음과 같이 처리할 수 있을 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">button<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* DO SOMETHING */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">click stream : ---c---c---c-c---c----c--></code></pre></div>
<p>이벤트 리스너, 이벤트 핸들러 등을 통해 클릭 이벤트를 구독하고, 위와 같은 비동기적인 이벤트를 처리할 수 있다.</p>
<p><code class="hljs-text">비동기 데이터 스트림</code>도 마찬가지로 구독 가능하며, 이를 통해 <code class="hljs-text">데이터</code> 혹은 <code class="hljs-text">사이드 이펙트</code>를 안전하게 처리할 수 있다.<br />
<code class="hljs-text">이벤트</code>와 어느 정도 비슷하긴 하지만, <code class="hljs-text">비동기 데이터 스트림</code>는 아래와 같은 많은 연산을 수행할 수 있다.</p>
<ul>
<li>스트림은 다른 스트림의 입력이 될 수(map) 있으며,</li>
<li>여러 스트림은 하나의 스트림으로 합쳐질 수도(merge/reduce) 있다.</li>
<li>또한, 스트림에 필터를 적용하여 관심 있는 스트림의 데이터만을 처리할 수도(filter) 있다.</li>
</ul>
<p>이외에도 수많은 연산들이 존재한다.</p>
<p>이처럼 <code class="hljs-text">ReactiveX</code>는 데이터를 <code class="hljs-text">효과적</code>이고 안전하게 처리할 수 있게 해준다.</p>
<h2>Observable</h2>
<p><code class="hljs-text">RxJS</code>를 사용하기 위해서는 반드시 <code class="hljs-text">옵저버블</code>을 이해해야 한다.<br />
<code class="hljs-text">옵저버블</code>은 간단히 말하면, 시간축 위의 데이터 집합의 표현이라고 할 수 있다.<br /></p>
<p>데이터의 형태는 상관 없지만, 쉬운 예시를 위해 클릭 이벤트와 해당 좌표가 비동기적으로 발생한다고 가정한다.
클릭 이벤트와 그의 좌표를 도식화하면 다음과 같을 것이다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">It is a click stream
-----c-------c-------c------c------>
(0, 5) (3, 1) (1, 4) (2, 2)</code></pre></div>
<h3>옵저버블의 특징</h3>
<h4>1. 옵저버블과 배열</h4>
<p><code class="hljs-text">옵저버블</code>은 배열의 <code class="hljs-text">map</code>, <code class="hljs-text">filter</code>, <code class="hljs-text">reduce</code> 와 비슷한 연산을 수행할 수 있다.<br />
또한, 위의 도식화를 보면 <code class="hljs-text">옵저버블</code>은 순서가 있는 데이터 집합으로써, <code class="hljs-text">시간</code>을 인덱스로 하며, 배열(불변 배열)과 유사하다는 것을 알 수 있다.</p>
<h4>2. 불변성</h4>
<p><code class="hljs-text">옵저버블</code>은 관찰만 가능하다.<br />
이는 즉, <code class="hljs-text">옵저버블</code>은 불변이라는 뜻이며, <code class="hljs-text">RxJS</code>는 <code class="hljs-text">Functional Programming</code> 패러다임도 사용하고 있다는 것을 알 수 있다.</p>
<p>따라서, 어떤 <code class="hljs-text">옵저버블</code>을 변형해야 한다면, 새로운 <code class="hljs-text">옵저버블</code>을 만들어야 한다.</p>
<p><strong>예제 : x 좌표가 2 이상인 새로운 스트림만들기</strong></p>
<p><code class="hljs-text">[0, 3, 1, 4]</code>와 같은 배열에서 값이 <code class="hljs-text">2</code> 이상인 원소만을 얻고자 할 땐, <code class="hljs-text">filter</code>를 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">(</span>x <span class="token operator">>=</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">옵저버블</code>도 마찬가지로 <code class="hljs-text">filter</code>를 사용하며, 다음과 같이 코드를 작성할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">Rx<span class="token punctuation">.</span>Observable
<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>element<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>clientX <span class="token operator">>=</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>정리</h2>
<p><code class="hljs-text">RxJS</code>를 공부하기 전에 알고 있어야 할 <code class="hljs-text">Reactive Programming</code>과 <code class="hljs-text">옵저버블</code>에 대한 간단한 개념을 알아보았다.</p>
<p>정리하자면,</p>
<p><code class="hljs-text">Reactive Programming</code>은 데이터의 형태(이벤트, 입력, 변수 등)가 어떻든 간에 이를 효과적이고 안전하게 처리할 수 있다는 장점이 있으며,<br />
<code class="hljs-text">옵저버블</code>은 인덱스가 시간인 불변 배열과 유사한 형태를 가진다고 볼 수 있다.<br /></p>
<p>다음에는 <code class="hljs-text">Observable</code>의 <code class="hljs-text">Combination</code> 연산에 대해 알아보겠다.</p>
- <![CDATA[Reselect로 Redux 성능 개선하기]]>https://wonism.github.io/redux-with-reselect/https://wonism.github.io/redux-with-reselect/Mon, 30 Oct 2017 00:03:19 GMT<h2>셀렉터에 대해</h2>
<p><code class="hljs-text">selector</code>는 <code class="hljs-text">store</code>로부터 온 데이터를 가져오거나 계산하는 역할을 하며, <code class="hljs-text">Redux</code>가 상태를 최소한으로 유지할 수 있도록 한다.<br />
이 <code class="hljs-text">셀렉터</code>는 인자가 변경될 때까지 다시 계산하는 일이 없기에 효율적이다.<br />
(이 원리를 이해하기 위해 <a href="/memoization/">메모이제이션에 대해 작성한 글</a>을 참고하면 도움이 될 것이다.)</p>
<p><strong>+</strong><br />
<code class="hljs-text">Dan Abramov</code>는 <code class="hljs-text">Reselect</code>에 대해 아래 트윗과 같이 말했다.</p>
<div id="redux-tweet"></div>
<h2>왜 리셀렉트인가?</h2>
<p><code class="hljs-text">Redux</code>를 사용하면서 데이터를 가져올 때, <code class="hljs-text">mapStateToProps</code>와 같은 함수를 통해 상태 데이터를 가져온다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/**
* STORE
*
* {
* height: 180,
* weight: 60,
* bloodPress: { high: 120, low: 80 },
* }
*/</span>
<span class="token keyword">const</span> <span class="token function-variable function">getBmi</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">height<span class="token punctuation">,</span> weight</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>weight <span class="token operator">/</span> <span class="token punctuation">(</span>height <span class="token operator">**</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">isHypertension</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> high<span class="token punctuation">,</span> low <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>high <span class="token operator">></span> <span class="token number">140</span> <span class="token operator">&&</span> low <span class="token operator">></span> <span class="token number">90</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">mapStateToProps</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
bmi<span class="token punctuation">:</span> <span class="token function">getBmi</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>height<span class="token punctuation">,</span> state<span class="token punctuation">.</span>weight<span class="token punctuation">)</span><span class="token punctuation">,</span>
isHypertension<span class="token punctuation">:</span> <span class="token function">isHypertension</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>bloodPress<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">getBmi</code>는 몸무게와 키를 통해 <code class="hljs-text">bmi</code>를 구하는 함수이다.<br />
이 함수의 단점은 상태의 일부가 업데이트될 때마다 함수가 데이터를 다시 계산한다는 것이다.<br />
<code class="hljs-text">BMI</code>와는 상관 없는 <code class="hljs-text">bloodPress</code>가 업데이트되어도 함수가 실행된다.</p>
<p>하지만, <code class="hljs-text">Reselect</code>를 사용하면 인자가 변경되지 않으면 재계산을 수행하지 않는다.<br />
<code class="hljs-text">리셀렉트</code>를 사용하면 함수 인자가 메모된 함수에 캐시되기 때문이다.<br />
오직 함수의 인자가 이전 호출 때의 값과 다를 경우에만 <code class="hljs-text">셀렉터</code>가 다시 계산을 수행한다.</p>
<h2>리셀렉트 사용하기</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// selectors.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createSelector <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'reselect'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> getHeight <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'height'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> getWeight <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'weight'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> getBloodPress <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'bloodPress'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> getBmi <span class="token operator">=</span> <span class="token function">createSelector</span><span class="token punctuation">(</span>
<span class="token comment">// 맨 아래 함수를 제외한 함수들을 Input Selector 라고도 한다.</span>
getHeight<span class="token punctuation">,</span>
getWeight<span class="token punctuation">,</span>
<span class="token comment">// 맨 아래 함수를 Result Selector 라고도 한다.</span>
<span class="token punctuation">(</span><span class="token parameter">height<span class="token punctuation">,</span> weight</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>weight <span class="token operator">/</span> height <span class="token operator">**</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> isHypertension <span class="token operator">=</span> <span class="token function">createSelector</span><span class="token punctuation">(</span>
getBloodPress<span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> high<span class="token punctuation">,</span> low <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>high <span class="token operator">></span> <span class="token number">140</span> <span class="token operator">&&</span> low <span class="token operator">></span> <span class="token number">90</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">mapStateToProps</span> <span class="token operator">=</span> <span class="token parameter">state</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
bmi<span class="token punctuation">:</span> <span class="token function">getBmi</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span><span class="token punctuation">,</span>
isHypertension<span class="token punctuation">:</span> <span class="token function">isHypertension</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>아래 예제와 같이 <code class="hljs-text">createSelector</code>를 통해 만들어진 <code class="hljs-text">셀렉터</code>는 다른 <code class="hljs-text">셀렉터</code>의 인자로 사용할 수도 있다.<br />
이는 복잡한 계산을 하기 위한 <code class="hljs-text">셀렉터</code>를 작은 여러 <code class="hljs-text">셀렉터</code>로 구성하여 읽기 쉽게 작성할 수 있음을 뜻한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> isUnderWeight <span class="token operator">=</span> <span class="token function">createSelector</span><span class="token punctuation">(</span>
getBmi<span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token parameter">bmi</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>bmi <span class="token operator"><</span> <span class="token number">18</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>정리</h2>
<p>어떤 값을 계산함에 있어 불필요한 연산을 수행하지 않을 수 있다는 것만으로도 성능을 개선할 수 있다.<br />
그리고, <code class="hljs-text">셀렉터</code>를 중첩할 수 있다는 것은 코드의 유연함을 제공하며, 리팩토링도 수월해진다.</p>
<p><code class="hljs-text">Reselect</code>의 러닝커브도 그렇게 높지 않기 때문에 프로젝트에 <code class="hljs-text">Redux</code>를 사용한다면, <code class="hljs-text">Reselect</code> 도입을 추천한다.</p>
- <![CDATA[SNS를 위한 meta태그]]>https://wonism.github.io/meta-for-social/https://wonism.github.io/meta-for-social/Sun, 29 Oct 2017 14:58:32 GMT<p><code class="hljs-text">Facebook</code>이나 <code class="hljs-text">Twitter</code>에 URL을 공유하면 대표이미지와 제목, 내용 등이 보이게 된다.<br />
이와 같은 속성을 설정하기 위해 <code class="hljs-text"><meta></code>태그를 사용한다.<br />
페이스북은 Open Graph protocol 을 사용하는데, 자세한 정보는 <a href="http://ogp.me/">Open Graph 공식 홈페이지</a>에서 볼 수 있다.<br />
많은 속성들이 보이는데, 자주 쓰이게 되는 속성은 다음과 같다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:title<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>제목<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:description<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>설명<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:image<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>대표 이미지<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:url<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>표준 링크(같은 콘텐츠를 가리키는 여러 개의 URL 중 대표 URL)<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre></div>
<p><code class="hljs-text">트위터</code>는 <code class="hljs-text">Open Graph protocal</code>과 유사한 <code class="hljs-text"><meta></code>태그를 사용하며, 다음과 같은 속성을 사용하면 된다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>twitter:title<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>제목<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>twitter:description<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>설명<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>twitter:image<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>대표 이미지<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>twitter:card<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>트위터 카드 타입<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token comment"><!-- 트위터 카드 타입은 summary_large_image, summary, photo 중 하나를 선택할 수 있다. --></span></code></pre></div>
<p>이 때, title, description, image 는 prefix 만 다르고, 모두 같은데, 두 번씩 써줘야 하나? 라는 의문이 생길 수 있다.<br />
<code class="hljs-text">트위터</code>는 트위터용 메타태그를 <code class="hljs-text">Open Graph</code>로 대체할 수 있도록 허용하기 때문에 다음과 같이 설정하면 된다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:title<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>제목<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:description<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>설명<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:image<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>대표 이미지<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">property</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>og:url<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>표준 링크(같은 콘텐츠를 가리키는 여러 개의 URL 중 대표 URL)<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>twitter:card<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>트위터 카드 타입<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre></div>
<p>이미지에 대한 가이드라인이 있는데 각각 다음과 같다.<br />
페이스북은 이미지의 사이즈가 최소 1200x630 픽셀보다 크기를 권장하며, 1.91:1 의 비율인 이미지가 오길 권장한다.<br />
트위터는 파일 사이즈가 1MB 보다 크기를 권장한다.</p>
<p><strong>메타 태그 검증하기</strong></p>
<ul>
<li>페이스북 : <a href="https://developers.facebook.com/tools/debug/sharing">https://developers.facebook.com/tools/debug/sharing</a></li>
<li>트위터 : <a href="https://cards-dev.twitter.com/validator">https://cards-dev.twitter.com/validator</a></li>
</ul>
<p>이 외에도 다양한 meta 태그들이 있으며, <a href="https://github.com/joshbuchea/HEAD">https://github.com/joshbuchea/HEAD</a> 에서 더 많은 정보를 알아볼 수 있다.</p>
- <![CDATA[innerHTML과 insertAdjacentHTML의 차이]]>https://wonism.github.io/innerhtml-insertadjacenthtml/https://wonism.github.io/innerhtml-insertadjacenthtml/Sun, 29 Oct 2017 01:04:03 GMT<p>DOM 노드의 내용을 수정할 때, <code class="hljs-text">[DOM Element].innerHTML = VALUE</code>를 사용하는 경우가 있다.</p>
<p>이 방식은 <code class="hljs-text">DOOM</code>을 파싱하는 과정에서 기존의 하위 노드들의 노드 트리가 삭제되고 재구성되는 과정이 추가된다.<br />
따라서, 실행 시간이 많이 낭비된다.</p>
<p><code class="hljs-text">insertAdjacentHTML</code>은 이를 개선하기 위한 메소드, <code class="hljs-text">인접(Adjacent)</code>한 위치에 <code class="hljs-text">HTML</code> 태그를 삽입해준다.<br />
어떤 <code class="hljs-text">DOM Element</code>에 대한 상대적인 위치를 지정하여 노드를 추가하는 방식으로 기존의 하위 노드는 건드리지 않기 때문에 속도가 상당히 빠르다.</p>
<p><code class="hljs-text">insertAdjacentHTML</code>에는 <code class="hljs-text">2</code>개의 인자가 필요하며, 첫 번째 인자는 <code class="hljs-text">DOM Element</code>의 상대적인 위치를 지정한다.
<code class="hljs-text">beforebegin</code>, <code class="hljs-text">afterbegin</code>, <code class="hljs-text">beforeend</code>, <code class="hljs-text">afterend</code> <code class="hljs-text">4</code>가지 중 하나이다.</p>
<p>아래에서 각 메소드를 <code class="hljs-text">1000</code>번씩 수행하는 데 걸린 시간을 확인할 수 있다.<br />
개발환경 특성 상(<code class="hljs-text">Virtual DOM</code>을 사용하기 때문에) 실행 시간이 다소 짧을 수 있다.</p>
<div id="dom-manipulation-performance"></div>
- <![CDATA[자바스크립트 패턴 - 5]]>https://wonism.github.io/js-pattern-5/https://wonism.github.io/js-pattern-5/Sun, 29 Oct 2017 00:14:31 GMT<h2>Decorator</h2>
<p><code class="hljs-text">장식자 패턴</code>은 객체의 동작을 동적으로 확장한다. 런타임 시 새로운 동작을 추가하는 기능은 원본 객체를 감싸는 <code class="hljs-text">Decorator</code> 객체에 의해 수행된다.<br />
데코레이터는 컴파일 타임에 발생하는 상속과 달리 런타임 변경을 허용함으로써 정적 언어에 유연성을 제공한다.</p>
<h2>ES5에서의 구현</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">Math</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> sum <span class="token operator">=</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'result is %d'</span><span class="token punctuation">,</span> sum<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> sum<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> math <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Math</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
math<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">DecoratedMath</span><span class="token punctuation">(</span><span class="token parameter">math</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>math <span class="token operator">=</span> math<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> sum <span class="token operator">=</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`result is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sum<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">. </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>a<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> + </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>b<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sum<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> sum<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>ES2017에서의 구현</h2>
<p>먼저, 데코레이터를 지원하지 않는 환경이라면, <code class="hljs-text">babel-plugin-transform-decorators-legacy</code> 패키지가 필요하다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// .babelrc.js</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token string">"presets"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"env"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token string">"plugins"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">"transform-decorators-legacy"</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">class</span> <span class="token class-name">Math</span> <span class="token punctuation">{</span>
@log
<span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* target : 클래스의 인스턴스에 매핑된다.
* name : 데코레이팅할 메소드의 이름
* descriptor : 동작을 지정하거나, 접근 제한, 캐싱 구현 등을 할 수 있게 도와주는 객체
*/</span>
<span class="token keyword">function</span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> name<span class="token punctuation">,</span> descriptor</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> oldValue <span class="token operator">=</span> descriptor<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
descriptor<span class="token punctuation">.</span><span class="token function-variable function">value</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`Calling "</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">" with </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>args<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token function">oldValue</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> descriptor<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> math <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Math</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
math<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Calling "add" with 42,5</span></code></pre></div>
<h2>정리</h2>
<p><code class="hljs-text">반복자 패턴</code>은 클라이언트가 객체 컬렉션을 효과적으로 반복할 수 있게 해준다.<br />
<code class="hljs-text">반복자 패턴</code>을 사용하면 개발자는 훨씬 유연하고 정교한 반복 구문을 설계할 수 있다.</p>
<p>다음엔 <code class="hljs-text">퍼사드 패턴</code>에 대해 알아보겠다.</p>
- <![CDATA[자바스크립트 패턴 - 4]]>https://wonism.github.io/js-pattern-4/https://wonism.github.io/js-pattern-4/Sat, 28 Oct 2017 23:58:29 GMT<h2>Iterator</h2>
<p><code class="hljs-text">반복자 패턴</code>은 클라이언트가 객체 컬렉션을 효과적으로 반복할 수 있게 해준다.<br />
<code class="hljs-text">반복자 패턴</code>을 사용하면 개발자는 훨씬 유연하고 정교한 반복 구문을 설계할 수 있다.</p>
<h2>구현</h2>
<p><code class="hljs-text">Iterator</code> 객체는 컬렉션 및 현재 위치에 대한 참조를 관리하며, <code class="hljs-text">first</code>, <code class="hljs-text">current</code>, <code class="hljs-text">next</code>, <code class="hljs-text">hasNext</code>, <code class="hljs-text">reset</code>, <code class="hljs-text">each</code>같은 메소드를 제공한다.
<code class="hljs-text">반복자 패턴</code>에서는 특히 <code class="hljs-text">next</code>메소드가 중요한데, <code class="hljs-text">next()</code>를 호출하면 다음 순서의 요소를 반환하게 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">Iterator</span><span class="token punctuation">(</span><span class="token parameter">items</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> items<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">Iterator</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token comment">// 맨 처음 요소를 가져온다.</span>
<span class="token function-variable function">first</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 현재 요소를 가져온다.</span>
<span class="token function-variable function">current</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">current</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
done<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
value<span class="token punctuation">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 현재 요소를 가져오며, 다음 호출 시 다음 값을 가져오게 된다.</span>
<span class="token function-variable function">next</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> value <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span>index<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">hasNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
done<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
value<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> done<span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 다음 요소가 있는지 확인한다.</span>
<span class="token function-variable function">hasNext</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">hasNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>index <span class="token operator"><=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 첫 요소를 가리키게 한다.</span>
<span class="token function-variable function">reset</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 객체를 순회하며 인자로 받은 함수를 실행하도록 한다.</span>
<span class="token function-variable function">each</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token function">each</span><span class="token punctuation">(</span><span class="token parameter">callback</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> item <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">hasNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> item <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">callback</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> items <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'one'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'삼'</span><span class="token punctuation">,</span> <span class="token string">'4'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> iterable <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Iterator</span><span class="token punctuation">(</span>items<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>iterable<span class="token punctuation">.</span><span class="token function">hasNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterable<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { done: false, value: 'one' }</span>
<span class="token comment">// { done: false, value: 2 }</span>
<span class="token comment">// { done: false, value: '삼' }</span>
<span class="token comment">// { done: false, value: '4' }</span>
<span class="token comment">// { done: true }</span>
<span class="token punctuation">}</span>
iterable<span class="token punctuation">.</span><span class="token function">first</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { done: false, value: 'one' }</span>
iterable<span class="token punctuation">.</span><span class="token function">each</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// { done: false, value: 'one' }</span>
<span class="token comment">// { done: false, value: 2 }</span>
<span class="token comment">// { done: false, value: '삼' }</span>
<span class="token comment">// { done: false, value: '4' }</span></code></pre></div>
<h2>정리</h2>
<p>이처럼 <code class="hljs-text">반복자 패턴</code>을 사용하면, 다양한 메소드를 통해 데이터에 쉽고 편리하게 접근할 수 있다.</p>
<p>다음엔 <a href="/js-pattern-5">장식자 패턴</a>에 대해 알아보겠다.</p>
- <![CDATA[정규식으로 소수 찾기]]>https://wonism.github.io/prime-with-regex/https://wonism.github.io/prime-with-regex/Sat, 28 Oct 2017 00:46:32 GMT<p>보통 <code class="hljs-text">소수</code>를 찾는 방법이라 하면, <code class="hljs-text">에라토네스의 체(Sieve of Eratosthenes)</code>가 떠오를 것이다.<br />
하지만, <code class="hljs-text">정규식</code>을 이용해 단 몇 줄만으로 <code class="hljs-text">소수</code>를 찾는 방법이 있다.</p>
<p>코드는 아래와 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">isPrime</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token punctuation">(</span><span class="token regex">/^,?$|^(,,+?)\1+$/</span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span><span class="token function">Array</span><span class="token punctuation">(</span><span class="token operator">++</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">isPrime</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token function">isPrime</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>
<span class="token function">isPrime</span><span class="token punctuation">(</span><span class="token number">19</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span></code></pre></div>
<p><code class="hljs-text">isPrime</code>함수는 양의 정수 <code class="hljs-text">x</code>를 인자로 받고, <code class="hljs-text">x</code>에 <code class="hljs-text">1</code> 을 더한 크기의 배열을 만든다.<br />
여기서, <code class="hljs-text">RegExp.prototype.test</code>는 스트링을 인자로 받기 때문에 <code class="hljs-text">Array(++x)</code>는 <code class="hljs-text">x</code>개의 <code class="hljs-text">,</code>로 이루어진 문자열로 형변환된다.</p>
<p>즉, <code class="hljs-text">x</code>만큼의 <code class="hljs-text">,</code>가 만들어진다.</p>
<p>그리고, <code class="hljs-text">/^,?$/</code>와 <code class="hljs-text">/^(,,+?)/</code>는 <code class="hljs-text">x</code>개의 <code class="hljs-text">,</code> 로 이루어진 문자열에 대해 정규표현식 검색을 수행한다.</p>
<p>먼저, 미리 알아두면 좋은 표현식 몇 가지를 설명하고 예시를 들어 코드를 설명하겠다.</p>
<p>정규표현식에서</p>
<ul>
<li><code class="hljs-text">^X</code>는 <code class="hljs-text">X</code>로 시작하는 문자열이며, <code class="hljs-text">X$</code>는 <code class="hljs-text">X</code>로 끝나는 문자열이다.</li>
<li><code class="hljs-text">(X)?</code>는 <code class="hljs-text">X</code> 또는 없음을 뜻한다.</li>
<li><code class="hljs-text">(X)+</code>는 <code class="hljs-text">X</code>가 <code class="hljs-text">1</code>번 이상 반복되는 문자열이다.</li>
<li><code class="hljs-text">(X)\1</code>는 정규식 안 <code class="hljs-text">1</code>번째 괄호의 최근 일치 부분에 대한 역참조이다.</li>
</ul>
<p>만약 <code class="hljs-text">x</code>가 <code class="hljs-text">5</code>라고 하자. 그럼, <code class="hljs-text">RegExp.prototype.test</code>의 인자는 <code class="hljs-text">,,,,</code>가 된다.<br />
<code class="hljs-text">(,,+?)</code>는 <code class="hljs-text">,,,,,</code> 의 첫 두 <code class="hljs-text">,,</code>와 매칭된다. 그리고, 역참조 <code class="hljs-text">\1</code>은 <code class="hljs-text">,,</code> 이 되며, 전체 정규식은 <code class="hljs-text">/^,,(,,)+$/</code> 이 된다.</p>
<p><code class="hljs-text">,,,,,</code>은 <code class="hljs-text">/^,,(,,)+$/</code> 와 매칭되지 않는다.
<code class="hljs-text">(,,+?)</code>에서 <code class="hljs-text">+?</code> 이 사용되었기 때문에 <code class="hljs-text">,,,</code> 와 매칭을 한다.</p>
<p><code class="hljs-text">(,,+?)</code>는 <code class="hljs-text">,,,,,</code> 의 첫 세 <code class="hljs-text">,,,</code> 와 매칭되며, <code class="hljs-text">\1</code>는 <code class="hljs-text">,,,</code> 이 되어 정규식은 <code class="hljs-text">/^,,,(,,,)+$/</code>이 된다.</p>
<p>매칭은 또 실패하며, <code class="hljs-text">,,,,</code>와 <code class="hljs-text">,,,,,</code>도 마찬가지이다.<br />
따라서 <code class="hljs-text">5</code>는 <code class="hljs-text">소수</code>라는 것을 알 수 있다.</p>
<p>이 정규식은 1998 년 <a href="https://github.com/Abigail">Abigail</a> 에 의해 처음으로 구현되었다.</p>
- <![CDATA[nodemailer로 이메일 전송하기]]>https://wonism.github.io/nodemailer/https://wonism.github.io/nodemailer/Sat, 28 Oct 2017 00:25:05 GMT<h2>Node Mailer</h2>
<p><code class="hljs-text">nodemailer</code>는 <code class="hljs-text">Node.js</code>에서 <code class="hljs-text">e-mail</code>을 쉽게 보낼 수 있게 도와주는 모듈이다.<br />
<code class="hljs-text">Gmail</code>뿐만 아니라, <code class="hljs-text">Naver</code>, <code class="hljs-text">Yahoo</code> 등의 서비스도 지원한다.</p>
<p>지원 리스트는 이 <a href="https://nodemailer.com/smtp/well-known/#supported-services">링크</a>에서 볼 수 있다.</p>
<h2>사용방법</h2>
<p><code class="hljs-text">0.x</code> 버전과 <code class="hljs-text">>=1.0</code> 버전은 사용 방법이 다르다.<br />
이 예제에서는 <code class="hljs-text">4.3.0</code> 버전을 사용한다.</p>
<h3>모듈 설치</h3>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ npm i -S nodemailer nodemailer-smtp-pool</code></pre></div>
<h3>구현하기</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> nodemailer <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'nodemailer'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> smtpPool <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'nodemailer-smtp-pool'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// smtpPool는 smtp서버를 사용하기 위한 모듈로</span>
<span class="token comment">// transporter객체를 만드는 nodemailer의 createTransport메소드의 인자로 사용된다.</span>
<span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token punctuation">{</span>
mailer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
service<span class="token punctuation">:</span> <span class="token string">'Gmail'</span><span class="token punctuation">,</span>
host<span class="token punctuation">:</span> <span class="token string">'localhost'</span><span class="token punctuation">,</span>
port<span class="token punctuation">:</span> <span class="token string">'465'</span><span class="token punctuation">,</span>
user<span class="token punctuation">:</span> <span class="token string">'[email protected]'</span><span class="token punctuation">,</span>
password<span class="token punctuation">:</span> <span class="token string">'PA%%W0RD'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token keyword">from</span> <span class="token operator">=</span> <span class="token string">'FROM < [email protected] >'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> to <span class="token operator">=</span> <span class="token string">'[email protected]'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> subject <span class="token operator">=</span> <span class="token string">'This is title'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> html <span class="token operator">=</span> <span class="token string">'<p>This is paragraph.</p>'</span><span class="token punctuation">;</span>
<span class="token comment">// const text = 'This is just text.';</span>
<span class="token keyword">const</span> mailOptions <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token keyword">from</span><span class="token punctuation">,</span>
to<span class="token punctuation">,</span>
subject<span class="token punctuation">,</span>
html<span class="token punctuation">,</span>
<span class="token comment">// text,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// 본문에 html이나 text를 사용할 수 있다.</span>
<span class="token keyword">const</span> transporter <span class="token operator">=</span> nodemailer<span class="token punctuation">.</span><span class="token function">createTransport</span><span class="token punctuation">(</span><span class="token function">smtpPool</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
service<span class="token punctuation">:</span> config<span class="token punctuation">.</span>mailer<span class="token punctuation">.</span>service<span class="token punctuation">,</span>
host<span class="token punctuation">:</span> config<span class="token punctuation">.</span>mailer<span class="token punctuation">.</span>host<span class="token punctuation">,</span>
port<span class="token punctuation">:</span> config<span class="token punctuation">.</span>mailer<span class="token punctuation">.</span>port<span class="token punctuation">,</span>
auth<span class="token punctuation">:</span> <span class="token punctuation">{</span>
user<span class="token punctuation">:</span> config<span class="token punctuation">.</span>mailer<span class="token punctuation">.</span>user<span class="token punctuation">,</span>
pass<span class="token punctuation">:</span> config<span class="token punctuation">.</span>mailer<span class="token punctuation">.</span>password<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
tls<span class="token punctuation">:</span> <span class="token punctuation">{</span>
rejectUnauthorize<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
maxConnections<span class="token punctuation">:</span> <span class="token number">5</span><span class="token punctuation">,</span>
maxMessages<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 메일을 전송하는 부분</span>
transporter<span class="token punctuation">.</span><span class="token function">sendMail</span><span class="token punctuation">(</span>mailOptions<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'failed... => '</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'succeed... => '</span><span class="token punctuation">,</span> res<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
transporter<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>메일이 전송되지 않는 경우</h3>
<p>메일이 전송되지 않는 경우는 대부분 보안 문제때문 일 것이다.<br />
메일을 다른 앱을 통해 사용할 수 있도록 설정을 바꾸면 된다.</p>
<p><code class="hljs-text">Gmail</code>의 경우 <a href="https://myaccount.google.com/lesssecureapps%EC%97%90%EC%84%9C">https://myaccount.google.com/lesssecureapps에서</a> 설정을 변경하면 될 것이다.</p>
- <![CDATA[자바스크립트 패턴 - 3]]>https://wonism.github.io/js-pattern-3/https://wonism.github.io/js-pattern-3/Wed, 25 Oct 2017 23:15:15 GMT<h2>Prototype</h2>
<p><code class="hljs-text">프로토타입</code>은 프로토타입 인스턴스를 사용하여 만들 객체의 종류를 지정하고, 이 프로토타입을 복사함으로써 새 객체를 만든다.</p>
<p><code class="hljs-text">프로토타입 패턴</code>은 데이터베이스의 기본값과 일치하는 값을 가지는 객체 초기화에서 유용하게 사용된다.</p>
<h2>구현</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">CarPrototype</span><span class="token punctuation">(</span><span class="token parameter">proto</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>proto <span class="token operator">=</span> proto<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">clone</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> car <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Car</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
car<span class="token punctuation">.</span>colors <span class="token operator">=</span> proto<span class="token punctuation">.</span>colors<span class="token punctuation">;</span>
<span class="token keyword">return</span> car<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">Car</span><span class="token punctuation">(</span><span class="token parameter">colors</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>colors <span class="token operator">=</span> colors<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">go</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">go</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'%s car is driven by human.'</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>colors<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> carProto <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Car</span><span class="token punctuation">(</span><span class="token string">'red'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> carPrototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CarPrototype</span><span class="token punctuation">(</span>carProto<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> car <span class="token operator">=</span> carPrototype<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
car<span class="token punctuation">.</span><span class="token function">go</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// red car is driven by human.</span></code></pre></div>
<p><code class="hljs-text">CarPrototype</code> 객체는 주어진 프로토타입 객체가 주어진 객체를 복제한다.<br />
또, <code class="hljs-text">clone</code> 메소드를 호출하면 프로토타입으로 초기화된 속성 값들을 가지는 <code class="hljs-text">Car</code> 객체를 생성한다.</p>
<h2>정리</h2>
<p><code class="hljs-text">프로토타입 패턴</code>은 새 객체를 생성하지만, 초기화되지 않은 객체를 생성하는 대신 <code class="hljs-text">원형(Prototype)</code>에서 복사한 값으로 초기화되는 객체를 반환한다.<br />
이를 <code class="hljs-text">Properties 패턴</code>이라고 하기도 한다.</p>
<p>구현을 통해 사용방법을 알아봤지만, 자바스크립트에 내장된 <code class="hljs-text">prototype</code>기능을 사용하면 훨씬 효과적으로 이 작업을 수행할 수 있다.</p>
<p>다음엔 <a href="/js-pattern-4">반복자 패턴</a>에 대해 알아보겠다.</p>
- <![CDATA[자바스크립트 패턴 - 2]]>https://wonism.github.io/js-pattern-2/https://wonism.github.io/js-pattern-2/Wed, 25 Oct 2017 22:47:51 GMT<h2>Factory</h2>
<p><code class="hljs-text">공장</code>의 역할은 <code class="hljs-text">물건</code>을 <code class="hljs-text">생산</code>하는 것이다.<br />
프로그래밍에서도 같은 일을 수행한다. 프로그래밍에서의 <code class="hljs-text">팩토리</code>는 <code class="hljs-text">객체</code>를 <code class="hljs-text">생성</code>한다.</p>
<p>팩토리 패턴은 클래스 내부나 클래스의 스태틱 메소드로 구현되는데,
객체를 생성하는 부분을 서브 클래스에 위임한다고 볼 수 있다.</p>
<h2>팩토리가 하는 일</h2>
<p>팩토리가 하는 일은 다음과 같다.</p>
<ul>
<li>비슷한 객체를 생성하는 반복 작업 수행한다.</li>
<li>구체적인 타입을 몰라도 객체를 생성할 수 있게 한다.
(자바스크립트에서는 강타입 언어가 아니기 때문에 두 번째 일을 쉽게 구현할 수 있다.)</li>
</ul>
<p><code class="hljs-text">팩토리</code>의 가장 대표적인 예제는 <code class="hljs-text">Object</code>이다.<br />
전달받은 값에 따라 다른 객체를 생성한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> num <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> str <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token string">'abc'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> bool <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> reg <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token regex">/\w/</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
num<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// Number</span>
str<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// String</span>
bool<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// Boolean</span>
obj<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// Object</span>
arr<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// Array</span>
reg<span class="token punctuation">.</span>constructor<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// RegExp</span></code></pre></div>
<h2>구현</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">Factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">createEmployee</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">createElement</span><span class="token punctuation">(</span><span class="token parameter">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> employee<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">===</span> <span class="token string">'fulltime'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
employee <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FullTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">===</span> <span class="token string">'parttime'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
employee <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PartTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">===</span> <span class="token string">'manager'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
employee <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Manager</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>type<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> does not exist.`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
employee<span class="token punctuation">.</span>type <span class="token operator">=</span> type<span class="token punctuation">;</span>
employee<span class="token punctuation">.</span><span class="token function-variable function">earn</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'I\'m %s. I get %f dollar per hour'</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>type<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>money<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> employee<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">FullTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>money <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">PartTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>money <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">Manager</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>money <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> factory <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Factory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> e1 <span class="token operator">=</span> factory<span class="token punctuation">.</span><span class="token function">createEmployee</span><span class="token punctuation">(</span><span class="token string">'fulltime'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> e2 <span class="token operator">=</span> factory<span class="token punctuation">.</span><span class="token function">createEmployee</span><span class="token punctuation">(</span><span class="token string">'parttime'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> e3 <span class="token operator">=</span> factory<span class="token punctuation">.</span><span class="token function">createEmployee</span><span class="token punctuation">(</span><span class="token string">'manager'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
e1<span class="token punctuation">.</span><span class="token function">earn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// I'm fulltime. I get 10 dollar per hour</span>
e2<span class="token punctuation">.</span><span class="token function">earn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// I'm parttime. I get 5 dollar per hour</span>
e3<span class="token punctuation">.</span><span class="token function">earn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// I'm manager. I get 20 dollar per hour</span></code></pre></div>
<p><code class="hljs-text">createEmployee</code>메소드는 실제 팩토리 메소드로 클라이언트에서 유형을 전달받는다.<br />
이 팩토리에 의해 만들어진 모든 직원은 동일한 인터페이스를 갖게 된다.</p>
<h2>정리</h2>
<p><code class="hljs-text">팩토리 패턴</code>을 사용하면 클라이언트에 객체 생성을 위임하면서 인스턴스화할 형식을 관리할 수 있다.<br />
또한, 자주 사용되면서 다른 특성을 가지는 객체 컬렉션에서 유용하게 사용될 수 있다.</p>
<p>다음엔 <a href="/js-pattern-3/">프로토타입 패턴</a>에 대해 알아보겠다.</p>
- <![CDATA[자바스크립트 패턴 - 1]]>https://wonism.github.io/js-pattern-1/https://wonism.github.io/js-pattern-1/Tue, 24 Oct 2017 21:38:57 GMT<h2>디자인 패턴이란?</h2>
<p><code class="hljs-text">디자인 패턴</code>은 특정 문맥에서 공통적으로 발생하는 문제에 대한 재사용가능한 해결책이다.</p>
<h2>Singleton</h2>
<p>먼저, 제일 간단한 <code class="hljs-text">싱글톤</code>에 대해 알아보겠다.</p>
<p>싱글톤은 특정 클래스의 인스턴스를 오직 하나만 유지하게 되는데, 동일한 클래스로 새로운 객체를 생성해도 처음 만들어진 객체를 얻게 된다.</p>
<h3>객체 리터럴</h3>
<p>자바스크립트의 리터럴로 객체를 생성하게 되면, 다른 어떤 객체와도 같지 않기 때문에 이 자체만으로 싱글톤이라고 볼 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> num<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> <span class="token punctuation">{</span> num<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
obj <span class="token operator">==</span> obj2<span class="token punctuation">;</span> <span class="token comment">// false</span>
obj <span class="token operator">===</span> obj2<span class="token punctuation">;</span> <span class="token comment">// false</span></code></pre></div>
<p>위처럼 동일한 멤버를 가지는 객체를 생성해도 이전에 만들어진 객체와 동일하지 않다.</p>
<h3>new 연산자로 생성된 객체</h3>
<p><code class="hljs-text">new</code> 연산자는 <code class="hljs-text">생성자 함수</code> 또는 <code class="hljs-text">클래스</code>를 통해 객체를 만들 수 있게 한다.<br />
즉, <code class="hljs-text">new Constructor();</code>를 통해 생성된 객체는 항상 처음 만들어진 객체를 가리키게 되며, 다음과 같은 결과가 나와야 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> a1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> a2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
a1 <span class="token operator">===</span> a2<span class="token punctuation">;</span> <span class="token comment">// true</span></code></pre></div>
<p>이를 위한 방법으로는 여러가지 방법이 있다.</p>
<h4>스태틱 프로퍼티에 인스턴스 저장하기</h4>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Person<span class="token punctuation">.</span>instance<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> Person<span class="token punctuation">.</span>instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
Person<span class="token punctuation">.</span>instance <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> p1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'wonism'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> p2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'human'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p1 <span class="token operator">===</span> p2 <span class="token comment">// true</span>
p2<span class="token punctuation">.</span>name <span class="token comment">// wonism</span></code></pre></div>
<p>위에 언급한대로 스태틱 프로퍼티에 인스턴스를 저장한다.
간단한 방법이지만, <code class="hljs-text">instance</code>가 공개되어 있다는 단점이 있다.</p>
<h4>클래스 키워드 사용하기</h4>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Person<span class="token punctuation">.</span>instance<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> Person<span class="token punctuation">.</span>instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token keyword">return</span> Person<span class="token punctuation">.</span>instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> p1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'wonism'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> p2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'human'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p1 <span class="token operator">===</span> p2 <span class="token comment">// true</span>
p2<span class="token punctuation">.</span>name <span class="token comment">// wonism</span></code></pre></div>
<p>바로 이전에 살펴본 예제 코드를 <code class="hljs-text">class</code>로 변경한 것 뿐이다.</p>
<h4>클로저에 인스턴스 저장하기</h4>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">let</span> Person<span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">iife</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> instance<span class="token punctuation">;</span>
<span class="token function-variable function">Person</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">Singleton</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>instance<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
instance <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> p1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'wonism'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> p2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token string">'human'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p1 <span class="token operator">===</span> p2 <span class="token comment">// true</span>
p2<span class="token punctuation">.</span>name <span class="token comment">// wonism</span></code></pre></div>
<p>생성자가 최초로 호출되면 생성자는 객체를 생성하고, 비공개 변수인 <code class="hljs-text">instance</code>를 가리킨다. 두 번째 부터는 <code class="hljs-text">instance</code>를 가리킨다.</p>
<br />
<h2>정리</h2>
<p><code class="hljs-text">싱글톤 패턴</code>은 객체지향 언어에서 여러 개의 인스턴스 생성을 피하는 유용한 패턴이다.<br />
(하지만 클래스 기반의 언어가 아닌 약타입 프로토타입 언어인 자바스크립트(ES3, ES5 등)에서는 이 패턴이 그렇게 유용한 편은 아니다.)</p>
<p>다음엔 <a href="/js-pattern-2/">팩토리 패턴</a>에 대해 알아보겠다.</p>
- <![CDATA[자바스크립트 음성 합성]]>https://wonism.github.io/speech-synthesis/https://wonism.github.io/speech-synthesis/Mon, 23 Oct 2017 20:15:15 GMT<p><code class="hljs-text">Web Speech API</code>의 <code class="hljs-text">SpeechSynthesis</code>는 음성 서비스의 컨트롤러 인터페이스로 이를 사용하여 장치에서 사용할 수 있는 합성 음성에 대한 정보를 가져오고, 음성 재생 등의 역할을 수행할 수 있게 해준다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">speak</span><span class="token punctuation">(</span><span class="token parameter">text</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> SpeechSynthesisUtterance <span class="token operator">===</span> <span class="token string">'undefined'</span> <span class="token operator">||</span> <span class="token keyword">typeof</span> speechSynthesis <span class="token operator">===</span> <span class="token string">'undefined'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'This browser does not support speech API'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> message <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SpeechSynthesisUtterance</span><span class="token punctuation">(</span>text<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> voices <span class="token operator">=</span> speechSynthesis<span class="token punctuation">.</span><span class="token function">getVoices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
message<span class="token punctuation">.</span>voice <span class="token operator">=</span> voices<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
speechSynthesis<span class="token punctuation">.</span><span class="token function">speak</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">speak</span><span class="token punctuation">(</span><span class="token string">'Hello, World!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<div id="speech-synthesis"></div>
<h2>참조</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis">MDN : SpeechSynthesis</a></li>
</ul>
- <![CDATA[CSS의 calc()]]>https://wonism.github.io/css-calc/https://wonism.github.io/css-calc/Sun, 15 Oct 2017 19:46:11 GMT<p><code class="hljs-text">CSS</code> 함수 <code class="hljs-text">calc()</code>는 <code class="hljs-text">CSS3</code>에 추가된 기능 중 하나로, 계산을 해주는 속성이다.<br />
<code class="hljs-text">calc()</code>는 <code class="hljs-text"><length></code> <code class="hljs-text"><frequency></code>, <code class="hljs-text"><angle></code>, <code class="hljs-text"><time></code>, <code class="hljs-text"><number></code>, 또는 <code class="hljs-text"><integer></code> 가 필요한 곳 어디서든 사용 가능하며,
기존에 자바스크립트로 하던 계산을 대신 해줄 수 있다.<br />
예를 들어, <code class="hljs-text">"100% 너비에서 50px 만큼을 뺀 만큼의 너비를 사용하고 싶다"</code>면, 다음과 같이 코드를 작성한다.</p>
<div class="gatsby-highlight" data-language="css"><pre class="hljs-css"><code class="hljs-css"><span class="token selector">*</span> <span class="token punctuation">{</span>
<span class="token property">box-sizing</span><span class="token punctuation">:</span> border-box<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token selector">p</span> <span class="token punctuation">{</span>
<span class="token property">width</span> <span class="token punctuation">:</span> 95%<span class="token punctuation">;</span> <span class="token comment">/* calc() 를 지원하지 않는 브라우저를 위한 fallback */</span>
<span class="token property">width</span> <span class="token punctuation">:</span> <span class="token function">-webkit-calc</span><span class="token punctuation">(</span>100% - 80px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* WebKit */</span>
<span class="token property">width</span> <span class="token punctuation">:</span> <span class="token function">-moz-calc</span><span class="token punctuation">(</span>100% - 80px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Firefox */</span>
<span class="token property">width</span> <span class="token punctuation">:</span> <span class="token function">-ms-calc</span><span class="token punctuation">(</span>100% - 80px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* MS Explorer */</span>
<span class="token property">width</span> <span class="token punctuation">:</span> <span class="token function">-o-calc</span><span class="token punctuation">(</span>100% - 80px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Opera */</span>
<span class="token property">width</span> <span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span>100% - 80px<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Standard */</span>
<span class="token punctuation">}</span></code></pre></div>
<p><code class="hljs-text">calc()</code>내부에서는 <code class="hljs-text">+</code>, <code class="hljs-text">-</code>, <code class="hljs-text">*</code>, <code class="hljs-text">/</code> 등의 사칙 연산이 가능하다.<br />
이 때, 주의할 것은 <code class="hljs-text">+</code> 연산과 <code class="hljs-text">-</code> 연산 시, 반드시 연산자의 양쪽에 공백이 한 칸 있어야 한다는 것이다.<br />
또한, 같은 형식(길이는 길이 끼리, 각도는 각도끼리)을 갖는 피연산자 끼리만 연산이 가능하다.</p>
<p>다음 코드펜은 <code class="hljs-text">calc()</code>와 <code class="hljs-text">vh</code>(View Height, 높이값의 100분의 1 값) 등 <code class="hljs-text">CSS</code>만을 사용하여 구현한 Scroll Indicator 이다.</p>
<div class="render-codepen" id="css-calc-example"></div>
- <![CDATA[Critical Rendering Path란?]]>https://wonism.github.io/critical-rendering-path/https://wonism.github.io/critical-rendering-path/Sun, 15 Oct 2017 18:03:16 GMT<p>이 글은 <a href="https://ireaderinokun.com/">Ire Aderinokun</a>의 허락을 받고
<a href="https://bitsofco.de/understanding-the-critical-rendering-path/">Understanding the Critical Rendering Path</a>라는 글의 일부를 번역한 것이다.</p>
<p><code class="hljs-text">Critical Rendering Path(CRP)</code>는 브라우저가 서버로부터 HTML 응답을 받아 화면을 그리기 위해 실행하는 과정이다.<br />
CRP는 6단계를 거치며 각 단계는 다음과 같다.</p>
<ol>
<li><code class="hljs-text">DOM 트리</code> 만들기</li>
<li><code class="hljs-text">CSSOM 트리</code> 만들기</li>
<li><code class="hljs-text">JavaScript</code> 실행</li>
<li><code class="hljs-text">Render 트리</code> 만들기</li>
<li>레이아웃 생성하기</li>
<li>페인팅</li>
</ol>
<h2>DOM 트리 만들기</h2>
<p><code class="hljs-text">DOM 트리</code>는 완전하게 파싱된 <code class="hljs-text">HTML</code> 페이지의 Object 표현이다.<br />
<code class="hljs-text">html</code>로부터 시작되어, 페이지의 각 <code class="hljs-text">element</code>, <code class="hljs-text">text</code>에 대한 노드가 만들어진다.<br />
다른 요소 내에 중첩된 요소는 자식 노드로 표시되며, 각 노드에는 해당 요소의 특성(attribute)이 포함된다.</p>
<p>이 예제 코드는 아래 이미지와 같은 <code class="hljs-text">DOM 트리</code>를 구성한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Understanding the Critical Rendering Path<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>style.css<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>header</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Understanding the Critical Rendering Path<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>header</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>Introduction<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Lorem ipsum dolor sit amet<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>footer</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>small</span><span class="token punctuation">></span></span>Copyright 2017<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>small</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>footer</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre></div>
<div class="render-image" id="crp-dom"></div>
<p><code class="hljs-text">HTML</code>은 부분적으로 실행될 수 있으며, 페이지에 내용이 표시되기 위해 문서 전체를 로드할 필요가 없다.
하지만, <code class="hljs-text">CSS</code>와 <code class="hljs-text">JavaScript</code>는 페이지의 렌더링을 차단할 수 있다.</p>
<h2>CSSOM 트리 만들기</h2>
<p><code class="hljs-text">CSSOM</code>은 <code class="hljs-text">DOM</code>과 관련된 스타일의 Object 표현이다.<br />
<code class="hljs-text">CSSOM</code>은 <code class="hljs-text">DOM</code>과 비슷한 방식으로 표현되지만, (명시적으로) 선언되었는지 (암시적으로) 상속되었는지 상관없이 각 노드에 대한 스타일이 포함된다.</p>
<p>위 <code class="hljs-text">HTML</code> 예제 코드에서 포함된 <code class="hljs-text">style.css</code>는 다음과 같다고 가정하며, 이는 아래 이미지와 같은 <code class="hljs-text">CSSOM 트리</code>를 구성한다.</p>
<div class="gatsby-highlight" data-language="css"><pre class="hljs-css"><code class="hljs-css"><span class="token selector">body</span> <span class="token punctuation">{</span> <span class="token property">font-size</span><span class="token punctuation">:</span> 18px<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token selector">header</span> <span class="token punctuation">{</span> <span class="token property">color</span><span class="token punctuation">:</span> plum<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token selector">h1</span> <span class="token punctuation">{</span> <span class="token property">font-size</span><span class="token punctuation">:</span> 28px<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token selector">main</span> <span class="token punctuation">{</span> <span class="token property">color</span><span class="token punctuation">:</span> firebrick<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token selector">h2</span> <span class="token punctuation">{</span> <span class="token property">font-size</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token selector">footer</span> <span class="token punctuation">{</span> <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre></div>
<div class="render-image" id="crp-cssom"></div>
<p><code class="hljs-text">CSS</code>는 렌더링을 차단하는 리소스로, 완전히 파싱되지 않으면 <code class="hljs-text">Render 트리</code>를 구성할 수 없다.
<code class="hljs-text">HTML</code>과 달리 <code class="hljs-text">CSS</code>는 상속된 계단식 특성때문에 부분적으로 실행될 수 없으며, 문서의 뒷부분에 정의된 스타일은 이전에 정의된 스타일을 덮어쓰게된다.</p>
<p>(<code class="hljs-text">CSS</code>전체가 파싱되기 전에 먼저 스타일 시트에 정의한 <code class="hljs-text">CSS</code>스타일을 사용하면, 잘못된 <code class="hljs-text">CSS</code>가 적용되는 상황이 발생할 수 있다.
하지만, 완전히 파싱되기 전까지 렌더링을 차단함으로써 이와 같은 일이 일어나지 않는다.)</p>
<p><code class="hljs-text"><link rel="stylesheet" /></code> 태그는 미디어 속성을 받을 수 있고, 미디어 속성은 스타일이 적용되는 미디어쿼리를 지정할 수 있다.
만약, 미디어 속성이 <code class="hljs-text">orientation: landscape</code> 인 스타일 시트가 있고, 페이지를 세로모드로 보고있는 경우 해당 리소스는 렌더링 블로킹으로 간주되지 않는다.
<code class="hljs-text">CSS</code>는 <code class="hljs-text">스크립트 블로킹</code>일수도 있다. 왜냐하면, <code class="hljs-text">JavaScript</code> 파일은 실행되기 전에 <code class="hljs-text">CSSOM</code>이 생성되는 것을 기다려야 하기 때문이다.</p>
<h2>JavaScript 실행</h2>
<p><code class="hljs-text">JavaScript</code>는 <code class="hljs-text">파서 차단 리소스</code>로 간주된다.
이것은 <code class="hljs-text">HTML</code> 문서 자체의 파싱이 <code class="hljs-text">JavaScript</code>에 의해 차단된다는 뜻이다.</p>
<p>파서가 내부 태그이든 외부 태그이든 <code class="hljs-text"><script></code> 태그에 도달하면, (외부 태그라면, 외부 스크립트를 가져오고) 스크립트를 실행한다.
따라서 문서 내의 요소를 참조하는 <code class="hljs-text">JavaScript</code>파일이 있는 경우, 해당 문서가 표시된 후에 오도록 해야한다.</p>
<p><code class="hljs-text">JavaScript</code>가 파서를 차단하는 것을 피하기 위해 <code class="hljs-text">async</code> 속성을 사용할 수도 있다.</p>
<h2>Render 트리 만들기</h2>
<p><code class="hljs-text">Render 트리</code>는 DOM 과 CSSOM 이 합쳐진 것으로 페이지에서 최종적으로 렌더링할 내용을 나타내는 트리이다.
<code class="hljs-text">display: none;</code> 으로 숨겨진 요소는 포함되지 않는다.<br />
위의 <code class="hljs-text">DOM</code>, <code class="hljs-text">CSSOM</code> 예제 코드는 다음 렌더 트리를 생성한다.</p>
<div class="render-image" id="crp-render-tree"></div>
<h4>레이아웃 생성하기</h4>
<p>레이아웃은 뷰포트의 크기를 결정하며, 뷰포트의 크기는 뷰포트의 크기와 관련있는 <code class="hljs-text">CSS</code> 스타일에 대한 컨텍스트를 제공한다.
뷰포트 크기는 <code class="hljs-text"><meta></code> 태그의 <code class="hljs-text">viewport</code> 속성을 통해 결정되는데, 기본 뷰포트 너비는 <code class="hljs-text">980px</code> 이다.</p>
<p>(일반적으로 메타태그의 뷰포트 값은 장치 너비에 맞게 설정한다.)</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>width=device-width,initial-scale=1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre></div>
<h2>페인팅</h2>
<p>그리는 단계에서는 페이지의 가시적인 내용을 픽셀로 변환하여 화면에 표시한다.</p>
<p>페인팅 단계에서 소요되는 시간은 <code class="hljs-text">DOM</code>의 크기와 적용되는 스타일에 따라 다르다. (예를 들면, 복잡한 gradient 배경은 단순 배경색보다 더 많은 시간이 소요된다.)</p>
<h2>Reference</h2>
<ul>
<li><a href="https://bitsofco.de/understanding-the-critical-rendering-path/">Understanding the Critical Rendering Path</a></li>
</ul>
- <![CDATA[JavaScript에서 Object 복사하기]]>https://wonism.github.io/copy-object/https://wonism.github.io/copy-object/Sat, 14 Oct 2017 23:06:33 GMT<h2>객체를 참조하는 복사</h2>
<p>객체가 아닌 Primitive의 값을 복사하려면 단순히 <code class="hljs-text">b = a</code>와 같이 변수에 복사하고자 하는 변수를 대입하면 된다.<br />
하지만, 객체에서는 <code class="hljs-text">b = a</code>와 같은 방법을 사용할 수 없다. 객체를 참조하는 복사가 이루어지기 때문이다.<br />
따라서, <code class="hljs-text">b = a</code>를 수행한 뒤 <code class="hljs-text">a</code>가 수정이 되면, <code class="hljs-text">b</code>까지 수정되는 것을 볼 수 있다.<br /></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> obj1<span class="token punctuation">;</span>
obj2<span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { a: 5 }</span></code></pre></div>
<h2>얕은 복사하기(Shallow copy)</h2>
<p>객체를 복사하기 위한 방법으로 다양한 방법이 있다.<br />
<code class="hljs-text">Object.prototype.constructor</code>메소드를 사용하거나, <code class="hljs-text">Lodash</code>, <code class="hljs-text">Ramda</code>같은 라이브러리를 사용하는 것이다.<br /></p>
<h3>constructor 메소드 사용하기</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">copyObject</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token operator">===</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token keyword">typeof</span> obj <span class="token operator">===</span> <span class="token string">'object'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> obj<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> copiedObject <span class="token operator">=</span> obj<span class="token punctuation">.</span><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">in</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>obj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>prop<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
copiedObject<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> <span class="token function">copyObject</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span>
obj2<span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { a: 42 }</span></code></pre></div>
<p>위와 같이, 인자가 <code class="hljs-text">null</code>이 아닌 객체일 경우, <code class="hljs-text">constructor</code>메소드로 해당 객체와 똑같은 객체를 생성한다.
그 다음, <code class="hljs-text">hasOwnProperty</code>를 통해 해당 객체가 인자로 넘긴 프로퍼티를 가지고 있는지 체크하고, 이에 맞는 프로퍼티에 같은 값을 할당한다.</p>
<h4>참고 : Spread operator 사용하기</h4>
<p><code class="hljs-text">ES2015</code>의 <code class="hljs-text">...</code>를 사용해도 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>obj1 <span class="token punctuation">}</span><span class="token punctuation">;</span>
obj2<span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { a: 42 }</span></code></pre></div>
<h3>Lodash & Ramda</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token constant">R</span> <span class="token keyword">from</span> <span class="token string">'ramda'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj3 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj4 <span class="token operator">=</span> <span class="token constant">R</span><span class="token punctuation">.</span><span class="token function">merge</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> obj3<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">Ramda</code>도 <code class="hljs-text">clone</code>이란 메소드가 있지만, <code class="hljs-text">Ramda</code>의 <code class="hljs-text">clone</code>은 깊은 복사를 수행한다.<br />
따라서 얕은 복사의 목적으로 객체를 복사하고자 할 때는 <code class="hljs-text">merge</code>가 훨씬 빠르다.</p>
<h2>깊은 복사하기(Deep copy)</h2>
<p>위 얕은 복사에서는 객체의 한 프로퍼티 값이 객체이고, 해당 객체가 수정이 되면, 원본의 프로퍼티 값이 수정이 되는 문제가 있다.<br />
이를 피하려면 깊은 복사를 수행한다. 깊은 복사는 얕은 복사와 마찬가지로 <code class="hljs-text">constructor</code>메소드를 사용하거나, 외부 라이브러리를 사용하는 방법이 있다.</p>
<h3>constructor 메소드 사용하기</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">copyObject</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token operator">===</span> <span class="token keyword">null</span> <span class="token operator">||</span> <span class="token keyword">typeof</span> obj <span class="token operator">!==</span> <span class="token string">'object'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> obj<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> copiedObject <span class="token operator">=</span> obj<span class="token punctuation">.</span><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">in</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>obj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
copiedObject<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">copyObject</span><span class="token punctuation">(</span>obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> copiedObject<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> foo <span class="token operator">=</span> <span class="token punctuation">{</span>
deep<span class="token punctuation">:</span> <span class="token punctuation">{</span>
key<span class="token punctuation">:</span> <span class="token string">'value'</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
shallow<span class="token punctuation">:</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> bar <span class="token operator">=</span> <span class="token function">copyObject</span><span class="token punctuation">(</span>foo<span class="token punctuation">)</span><span class="token punctuation">;</span>
bar<span class="token punctuation">.</span>deep<span class="token punctuation">.</span>key <span class="token operator">=</span> <span class="token string">'other value'</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>foo<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { deep: { key: 'value' }, shallow: false }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>bar<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { deep: { key: 'other value' }, shallow: false }</span></code></pre></div>
<h3>Lodash & Ramda</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token constant">R</span> <span class="token keyword">from</span> <span class="token string">'ramda'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj2 <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">cloneDeep</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj3 <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> obj4 <span class="token operator">=</span> <span class="token constant">R</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span>obj3<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
- <![CDATA[Lodash로 좀 더 간결한 Reducer 코드 작성하기]]>https://wonism.github.io/redux-with-lodash/https://wonism.github.io/redux-with-lodash/Sat, 07 Oct 2017 00:26:02 GMT<p>일반적으로 리듀서에서 액션의 타입에 따라 다른 작업을 수행하기 위해 <code class="hljs-text">switch</code>를 사용한다.<br />
이 때, 각 <code class="hljs-text">case</code>마다 블록<code class="hljs-text">{ /* ... */ }</code>으로 사용하지 않는 이상 스코프의 범위는 <code class="hljs-text">switch</code>의 블록이다.
따라서 여러 <code class="hljs-text">case</code>에서 중복되는 변수명을 사용하려면, 해당 <code class="hljs-text">case</code>마다 명시적으로 블록을 작성해야한다는 불편한 점이 있다.<br />
(참고 : <a href="/block-scope-in-switch">Switch안에서의 let과 const</a>)</p>
<p>하지만 지금 설명하고자 하는 방법을 사용하면 이러한 문제를 자연스럽게 해결할 수 있을 뿐만 아니라, 코드 또한 더욱 간결해진다.<br />
(예제에서 <code class="hljs-text">lodash</code>를 사용하지만, <code class="hljs-text">Ramda</code>를 사용하거나 외부 라이브러리를 사용하지 않고 직접 구현해도 된다.)</p>
<p><a href="/redux-from-scratch">Redux 튜토리얼</a>의 예제 코드를 수정하면서 코드가 어떻게 변하는지 살펴 보겠다.</p>
<h2>Reducer 코드 변경하기</h2>
<p>먼저 리듀서를 생성하는 코드를 작성한다.<br />
정의되지 않은 <code class="hljs-text">액션 타입</code>에 대해서는 전달받은 상태를 그대로 반환하며, 정의된 <code class="hljs-text">액션 타입</code>에 대해서는 특정 연산을 한 새로운 상태를 반환한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/utils/createReducer.js</span>
<span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">createReducer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">reducers <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token punctuation">(</span><span class="token parameter">state <span class="token operator">=</span> initialState<span class="token punctuation">,</span> <span class="token punctuation">{</span> type<span class="token punctuation">,</span> <span class="token operator">...</span>action <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span>
fp<span class="token punctuation">.</span><span class="token function">has</span><span class="token punctuation">(</span>type<span class="token punctuation">)</span><span class="token punctuation">(</span>reducers<span class="token punctuation">)</span> <span class="token operator">?</span>
reducers<span class="token punctuation">[</span>type<span class="token punctuation">]</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> action<span class="token punctuation">)</span> <span class="token punctuation">:</span>
state
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> createReducer<span class="token punctuation">;</span></code></pre></div>
<p>다음, <code class="hljs-text">src/index.jsx</code>의 리듀서 설정 부분을 변경한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/index.jsx</span>
<span class="token comment">/* ... */</span>
<span class="token keyword">import</span> createReducer <span class="token keyword">from</span> <span class="token string">'./utils/createReducer'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> reducers <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span><span class="token punctuation">{</span> todos<span class="token punctuation">:</span> <span class="token function">createReducer</span><span class="token punctuation">(</span>TodoReducers<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* ... */</span></code></pre></div>
<p>마지막으로 <code class="hljs-text">리듀서</code> 코드를 수정한다.<br />
이 파일은 객체를 <code class="hljs-text">export</code>하기만 하면 된다.</p>
<p>이 객체는 <code class="hljs-text">액션 타입</code>들을 프로퍼티로 가지며, 이 프로퍼티들의 값은 각각 액션 타입에 따른 연산을 할 함수이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoReducers.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>
<span class="token constant">ADD_TODO</span><span class="token punctuation">,</span>
<span class="token constant">REMOVE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">TOGGLE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./TodoActionTypes'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span>
<span class="token punctuation">[</span><span class="token constant">ADD_TODO</span><span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> <span class="token punctuation">{</span> todo <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">,</span>
<span class="token punctuation">{</span> todo<span class="token punctuation">,</span> done<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">[</span><span class="token constant">REMOVE_TODO</span><span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> <span class="token punctuation">{</span> index <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> length <span class="token operator">=</span> state<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> index<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span>index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">[</span><span class="token constant">TOGGLE_TODO</span><span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> <span class="token punctuation">{</span> index <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> length <span class="token operator">=</span> state<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">const</span> selectedTodo <span class="token operator">=</span> state<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> todo <span class="token punctuation">}</span> <span class="token operator">=</span> selectedTodo<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> index<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
todo<span class="token punctuation">,</span>
done<span class="token punctuation">:</span> <span class="token operator">!</span>todo<span class="token punctuation">.</span>done<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span>index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">[</span><span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">]</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token parameter">state</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'중복된 아이템입니다.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// eslint-disable-line</span>
<span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>완성된 애플리케이션</h2>
<div id="redux-with-lodash"></div>
- <![CDATA[Redux 튜토리얼]]>https://wonism.github.io/redux-from-scratch/https://wonism.github.io/redux-from-scratch/Thu, 05 Oct 2017 20:39:24 GMT<p><code class="hljs-text">Redux</code>는 상태를 관리해주는 라이브러리로 <code class="hljs-text">React JS</code>, <code class="hljs-text">Vue JS</code> 등과 함께 사용되며, 큰 애플리케이션의 상태를 보다 쉽게 할 수 있도록 도와준다.</p>
<h2>Flux</h2>
<p><code class="hljs-text">Redux</code>에 대해 설명하기 앞서, <code class="hljs-text">Flux</code>란 아키텍쳐에 대해 설명하겠다.<br />
<code class="hljs-text">Flux</code>는 단방향 데이터 흐름을 이용함으로써 리액트의 컴퍼넌트들을 보완한다.<br />
사용자가 뷰와 상호작용할 때, 뷰는 중앙 디스패쳐를 통해 다양한 <code class="hljs-text">store</code>에 <code class="hljs-text">액션</code>을 전파한다.<br />
(<code class="hljs-text">store</code>는 애플리케이션의 데이터와 로직을 가지고 있으며, 데이터와 로직은 상태에 따라 뷰를 업데이트하는 역할을 수행한다.)<br />
<code class="hljs-text">Flux</code>에는 많은 <code class="hljs-text">store</code>가 있으며, 각 <code class="hljs-text">store</code>는 상태의 각각 다른 작은 부분이나 애플리케이션의 데이터를 사용한다.</p>
<h3>Flux 데이터 흐름</h3>
<ul>
<li>사용자가 뷰와 상호작용을 하면, 뷰는 <code class="hljs-text">액션</code>을 트리거한다.</li>
<li><code class="hljs-text">액션</code>이 해당 함수를 전달하고, 해당 함수는 <code class="hljs-text">store</code>를 변경한다.</li>
<li><code class="hljs-text">store</code>가 데이터를 갱신하면, 뷰는 이에 따라 갱신된다.</li>
</ul>
<p>애플리케이션이 커지면, 여러 <code class="hljs-text">store</code>가 데이터를 관리하게 된다.</p>
<h2>Redux</h2>
<p><code class="hljs-text">Redux</code>는 예측가능한 상태 컨테이너로 <code class="hljs-text">Flux</code>의 구현체이다.<br />
하지만 완전한 <code class="hljs-text">Flux</code> 구현체라고 보기는 힘들다. <code class="hljs-text">Redux</code>는 애플리케이션의 상태를 위해 단 한 개의 스토어를 사용하기 때문이다.
대신, <code class="hljs-text">Redux</code>의 <code class="hljs-text">store</code>는 다양한 상태 객체로 나뉘어진다.</p>
<h3>Redux의 세 가지 원칙</h3>
<ol>
<li>진리의 단일 소스</li>
<li>상태는 읽기 전용</li>
<li>순수 함수로써 변경이 된다.</li>
</ol>
<h3>액션</h3>
<p><code class="hljs-text">Redux</code>의 상태를 변경하기 위해서는 <code class="hljs-text">액션</code>을 내보내야한다. <code class="hljs-text">액션</code>은 자바스크립트 객체이며, 어떤 일이 발생하는지 설명하는 <code class="hljs-text">type</code> 속성을 반드시 가진다. 또한, 상태 변경을 위한 값인 <code class="hljs-text">payload</code>를 가진다.<br />
이 때, <code class="hljs-text">payload</code>는 없을 수도 있으며, <code class="hljs-text">2</code>개 이상일 수도 있다. 또한, 속성 이름은 개발자가 임의로 지정할 수 있다.</p>
<h3>액션 생성자</h3>
<p><code class="hljs-text">액션 생성자</code>는 <code class="hljs-text">액션</code>을 생성하는 함수이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> <span class="token constant">ADD_TODO</span><span class="token punctuation">,</span> <span class="token constant">REMOVE_TODO</span> <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./actionTypes'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">addTodo</span> <span class="token operator">=</span> <span class="token parameter">text</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token constant">ADD_TODO</span><span class="token punctuation">,</span> text <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">removeTodo</span> <span class="token operator">=</span> <span class="token parameter">index</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> typd<span class="token punctuation">:</span> <span class="token constant">REMOVE_TODO</span><span class="token punctuation">,</span> index <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>리듀서</h3>
<p><code class="hljs-text">액션</code>은 단지 어떤 일이 발생할지만을 설명한다. 애플리케이션의 상태가 어떻게 변할지 설명하는 일은 <code class="hljs-text">리듀서</code>의 일이다.<br />
<code class="hljs-text">리듀서</code>는 이전의 상태를 받아 새로운 상태를 반환한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token punctuation">(</span><span class="token parameter">previousState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token operator">=></span> newState</code></pre></div>
<p>다음은 <code class="hljs-text">리듀서</code> 내부에서 절대 해서는 안 되는 일들이다.</p>
<ul>
<li><code class="hljs-text">리듀서</code>의 인자를 변경하는 일</li>
<li>
<p>부작용을 일으킬 수 있는 일</p>
<ul>
<li>DB 호출, API 호출, 라우팅 전환</li>
<li><code class="hljs-text">Date.now()</code>, <code class="hljs-text">Math.random()</code>과 같은 순수하지 않은 함수를 호출하는 일</li>
</ul>
</li>
</ul>
<h3>스토어</h3>
<p><code class="hljs-text">store</code>는 객체로써 그들을 하나로 모으는 일을 하며, 다음과 같은 일을 한다.</p>
<ul>
<li>애플리케이션의 상태를 가진다.</li>
<li><code class="hljs-text">getState()</code>를 통해 상태에 접근할 수 있다.</li>
<li><code class="hljs-text">dispatch(action)</code>를 통해 상태를 업데이트할 수 있다.</li>
<li><code class="hljs-text">subscribe(listener)</code>를 통해 리스너를 등록할 수 있다.</li>
<li><code class="hljs-text">subscribe(listener)</code>에 의해 반환된 함수를 호출함으로써 리스너의 등록 취소를 할 수 있다.</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token punctuation">{</span> createStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> todoReducer <span class="token keyword">from</span> <span class="token string">'./todo/reducers'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>todoReducer<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>Redux 구현해보기</h2>
<p>다음과 같은 <code class="hljs-text">Todo</code> 애플리케이션을 구현하고자 한다.</p>
<div id="redux-tutorial"></div>
<p>파일 구조도는 다음과 같다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">src
├── index.jsx
└── todo
├── Todo.jsx
├── TodoActionTypes.js
├── TodoActions.js
├── TodoAdder.jsx
├── TodoContainer.jsx
├── TodoItem.jsx
└── TodoReducers.js</code></pre></div>
<h3>액션</h3>
<p>먼저 액션 타입(동작 유형)들을 정의한다.<br />
아래에 정의된 동작을 발생하면, <code class="hljs-text">리듀서</code>가 상태를 변경하게 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoActionTypes.js</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">ADD_TODO</span> <span class="token operator">=</span> <span class="token string">'ADD_TODO'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">REMOVE_TODO</span> <span class="token operator">=</span> <span class="token string">'REMOVE_TODO'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">TOGGLE_TODO</span> <span class="token operator">=</span> <span class="token string">'TOGGLE_TODO'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token constant">FAILED_TO_ADD_TODO</span> <span class="token operator">=</span> <span class="token string">'FAILED_TO_ADD_TODO'</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">액션</code>은 액션을 설명하는 객체를 전달한다.<br />
(액션 타입을 상수로 만듦으로써 오타를 방지할 수 있다.
<code class="hljs-text">{ type: 'ADDD_TODO', todo }</code>와 같이 액션 타입을 문자열로 직접 전달하게 되면, 예상하지 못한 버그가 발생할 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoActions.js</span>
<span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>
<span class="token constant">ADD_TODO</span><span class="token punctuation">,</span>
<span class="token constant">REMOVE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">TOGGLE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./TodoActionTypes'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">addTodo</span> <span class="token operator">=</span> <span class="token parameter">todo</span> <span class="token operator">=></span>
<span class="token punctuation">(</span><span class="token parameter">dispatch<span class="token punctuation">,</span> getState</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> todos <span class="token punctuation">}</span> <span class="token operator">=</span> state<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span>fp<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">{</span> todo <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>todos<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token constant">ADD_TODO</span><span class="token punctuation">,</span>
todo<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">removeTodo</span> <span class="token operator">=</span> <span class="token parameter">index</span> <span class="token operator">=></span>
<span class="token parameter">dispatch</span> <span class="token operator">=></span>
<span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token constant">REMOVE_TODO</span><span class="token punctuation">,</span>
index<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> <span class="token function-variable function">toggleTodo</span> <span class="token operator">=</span> <span class="token parameter">index</span> <span class="token operator">=></span>
<span class="token parameter">dispatch</span> <span class="token operator">=></span>
<span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
type<span class="token punctuation">:</span> <span class="token constant">TOGGLE_TODO</span><span class="token punctuation">,</span>
index<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>리듀서</h3>
<p>위에서 언급했듯이, <code class="hljs-text">리듀서</code>에서는 부작용을 일으키면 안 된다. 전달받은 이전의 상태값을 통해 새로운 상태값을 만들어 반환해야 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoReducers.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>
<span class="token constant">ADD_TODO</span><span class="token punctuation">,</span>
<span class="token constant">REMOVE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">TOGGLE_TODO</span><span class="token punctuation">,</span>
<span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./TodoActionTypes'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">todoReducers</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> type<span class="token punctuation">,</span> <span class="token operator">...</span>action <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">switch</span> <span class="token punctuation">(</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">case</span> <span class="token constant">ADD_TODO</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> todo <span class="token punctuation">}</span> <span class="token operator">=</span> action<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">,</span>
<span class="token punctuation">{</span> todo<span class="token punctuation">,</span> done<span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token constant">REMOVE_TODO</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> index <span class="token punctuation">}</span> <span class="token operator">=</span> action<span class="token punctuation">;</span>
<span class="token keyword">const</span> length <span class="token operator">=</span> state<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> index<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span>index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token constant">TOGGLE_TODO</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> index <span class="token punctuation">}</span> <span class="token operator">=</span> action<span class="token punctuation">;</span>
<span class="token keyword">const</span> length <span class="token operator">=</span> state<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token keyword">const</span> selectedTodo <span class="token operator">=</span> state<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> todo <span class="token punctuation">}</span> <span class="token operator">=</span> selectedTodo<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> index<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
todo<span class="token punctuation">,</span>
done<span class="token punctuation">:</span> <span class="token operator">!</span>todo<span class="token punctuation">.</span>done<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token operator">...</span>state<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span>index <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token constant">FAILED_TO_ADD_TODO</span><span class="token punctuation">:</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'중복된 아이템입니다.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// eslint-disable-line</span>
<span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token keyword">default</span><span class="token punctuation">:</span>
<span class="token keyword">return</span> state<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> todoReducers<span class="token punctuation">;</span></code></pre></div>
<h3>메인 파일과 컴퍼넌트들</h3>
<p><code class="hljs-text">redux</code>의 <code class="hljs-text">combineReducer</code>는 이름 그대로 모든 <code class="hljs-text">리듀서</code>를 결합하여 하나의 <code class="hljs-text">스토어</code>로 결합한다.<br />
<code class="hljs-text">react-redux</code>의 <code class="hljs-text">Provider</code>에 <code class="hljs-text">store</code>를 설정하면, 그 하위 컴퍼넌트들에게 따로 전달해주지 않아도 <code class="hljs-text">connect</code>될 때, <code class="hljs-text">store</code>에 접근할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/index.jsx</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createStore<span class="token punctuation">,</span> combineReducers<span class="token punctuation">,</span> applyMiddleware <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> Provider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> thunk <span class="token keyword">from</span> <span class="token string">'redux-thunk'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> TodoContainer <span class="token keyword">from</span> <span class="token string">'./todo/TodoContainer'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> TodoReducers <span class="token keyword">from</span> <span class="token string">'./todo/TodoReducers'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> reducers <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span><span class="token punctuation">{</span> todos<span class="token punctuation">:</span> TodoReducers <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> middleware <span class="token operator">=</span> <span class="token function">applyMiddleware</span><span class="token punctuation">(</span>thunk<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>reducers<span class="token punctuation">,</span> middleware<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">render</span><span class="token punctuation">(</span>
<span class="token operator"><</span>Provider store<span class="token operator">=</span><span class="token punctuation">{</span>store<span class="token punctuation">}</span><span class="token operator">></span>
<span class="token operator"><</span>TodoContainer <span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>Provider<span class="token operator">></span><span class="token punctuation">,</span>
document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>Container 컴퍼넌트 (Smart 컴퍼넌트)</h3>
<p><code class="hljs-text">컨테이너 컴퍼넌트</code>는 애플리케이션의 상태와 직접 상호작용하는 컴퍼넌트이다.<br />
<code class="hljs-text">store</code>에 접근할 수 있으며, <code class="hljs-text">action</code>을 전달하거나 현재 상태를 가져올 수 있다.</p>
<p><code class="hljs-text">connect</code>는 리액트의 컴퍼넌트와 리덕스의 <code class="hljs-text">store</code>를 연결해준다. 전달받는 인자는 아래와 같으며, 전달하지 않아도 무방하다.</p>
<ul>
<li><code class="hljs-text">mapStateToProps</code> : <code class="hljs-text">store</code>의 상태를 <code class="hljs-text">props</code>로 전달한다.</li>
<li><code class="hljs-text">mapDispatchToProps</code> : 컴퍼넌트의 <code class="hljs-text">props</code>로 전달된 함수를 실행할 때, 특정한 <code class="hljs-text">action</code>을 전달하도록 한다.</li>
</ul>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoContainer.jsx</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> connect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> bindActionCreators <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>
addTodo<span class="token punctuation">,</span>
removeTodo<span class="token punctuation">,</span>
toggleTodo<span class="token punctuation">,</span>
<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./TodoActions'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> Todo <span class="token keyword">from</span> <span class="token string">'./Todo'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">mapStateToProps</span> <span class="token operator">=</span> <span class="token parameter">state</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
todos<span class="token punctuation">:</span> state<span class="token punctuation">.</span>todos<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">mapDispatchToProps</span> <span class="token operator">=</span> <span class="token parameter">dispatch</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
addTodo<span class="token punctuation">:</span> <span class="token function">bindActionCreators</span><span class="token punctuation">(</span>addTodo<span class="token punctuation">,</span> dispatch<span class="token punctuation">)</span><span class="token punctuation">,</span>
removeTodo<span class="token punctuation">:</span> <span class="token function">bindActionCreators</span><span class="token punctuation">(</span>removeTodo<span class="token punctuation">,</span> dispatch<span class="token punctuation">)</span><span class="token punctuation">,</span>
toggleTodo<span class="token punctuation">:</span> <span class="token function">bindActionCreators</span><span class="token punctuation">(</span>toggleTodo<span class="token punctuation">,</span> dispatch<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token function">connect</span><span class="token punctuation">(</span>mapStateToProps<span class="token punctuation">,</span> mapDispatchToProps<span class="token punctuation">)</span><span class="token punctuation">(</span>Todo<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>Presentational 컴퍼넌트 (Dumb 컴퍼넌트)</h3>
<p><code class="hljs-text">Presentational 컴퍼넌트</code>는 하위 컴퍼넌트를 가지지만, <code class="hljs-text">store</code>와 상호작용하지는 않는다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/Todo.jsx</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">'prop-types'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> TodoItem <span class="token keyword">from</span> <span class="token string">'./TodoItem'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> TodoAdder <span class="token keyword">from</span> <span class="token string">'./TodoAdder'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">Todo</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> propTypes <span class="token operator">=</span> <span class="token punctuation">{</span>
todos<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span><span class="token function">arrayOf</span><span class="token punctuation">(</span>PropTypes<span class="token punctuation">.</span><span class="token function">shape</span><span class="token punctuation">(</span><span class="token punctuation">{</span> todo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>string<span class="token punctuation">,</span> done<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>bool <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
addTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
removeTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
toggleTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> todos<span class="token punctuation">,</span> addTodo<span class="token punctuation">,</span> removeTodo<span class="token punctuation">,</span> toggleTodo <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>div<span class="token operator">></span>
<span class="token operator"><</span>TodoAdder addTodo<span class="token operator">=</span><span class="token punctuation">{</span>addTodo<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span>ul<span class="token operator">></span>
<span class="token punctuation">{</span>fp<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> todo<span class="token punctuation">,</span> done <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> index <span class="token operator">=</span> fp<span class="token punctuation">.</span><span class="token function">findIndex</span><span class="token punctuation">(</span><span class="token punctuation">{</span> todo <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>todos<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>TodoItem
key<span class="token operator">=</span><span class="token punctuation">{</span>todo<span class="token punctuation">}</span>
index<span class="token operator">=</span><span class="token punctuation">{</span>index<span class="token punctuation">}</span>
todo<span class="token operator">=</span><span class="token punctuation">{</span>todo<span class="token punctuation">}</span>
done<span class="token operator">=</span><span class="token punctuation">{</span>done<span class="token punctuation">}</span>
removeTodo<span class="token operator">=</span><span class="token punctuation">{</span>removeTodo<span class="token punctuation">}</span>
toggleTodo<span class="token operator">=</span><span class="token punctuation">{</span>toggleTodo<span class="token punctuation">}</span>
<span class="token operator">/</span><span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>todos<span class="token punctuation">)</span><span class="token punctuation">}</span>
<span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoItem.jsx</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">'prop-types'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">TodoItem</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> propTypes <span class="token operator">=</span> <span class="token punctuation">{</span>
index<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>number<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
todo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>string<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
done<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>bool<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
toggleTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
removeTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> index<span class="token punctuation">,</span> todo<span class="token punctuation">,</span> done<span class="token punctuation">,</span> toggleTodo<span class="token punctuation">,</span> removeTodo <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>li<span class="token operator">></span>
<span class="token operator"><</span>input
id<span class="token operator">=</span><span class="token punctuation">{</span><span class="token template-string"><span class="token string">`check-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>todo<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">}</span>
type<span class="token operator">=</span><span class="token string">"checkbox"</span>
defaultChecked<span class="token operator">=</span><span class="token punctuation">{</span>done<span class="token punctuation">}</span>
style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> cursor<span class="token punctuation">:</span> <span class="token string">'pointer'</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">toggleTodo</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span>label htmlFor<span class="token operator">=</span><span class="token punctuation">{</span><span class="token template-string"><span class="token string">`check-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>todo<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">}</span> style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> margin<span class="token punctuation">:</span> <span class="token string">'0 20px 0 10px'</span><span class="token punctuation">,</span> cursor<span class="token punctuation">:</span> <span class="token string">'pointer'</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span>
<span class="token punctuation">{</span>todo<span class="token punctuation">}</span>
<span class="token operator"><</span><span class="token operator">/</span>label<span class="token operator">></span>
<span class="token operator"><</span>button
style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> cursor<span class="token punctuation">:</span> <span class="token string">'pointer'</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">removeTodo</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token operator">></span>
<span class="token constant">X</span>
<span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// src/todo/TodoAdder.jsx</span>
<span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> PropTypes <span class="token keyword">from</span> <span class="token string">'prop-types'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">class</span> <span class="token class-name">TodoAdder</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> propTypes <span class="token operator">=</span> <span class="token punctuation">{</span>
addTodo<span class="token punctuation">:</span> PropTypes<span class="token punctuation">.</span>func<span class="token punctuation">.</span>isRequired<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>handleSubmit <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">handleSubmit</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">handleSubmit</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
e<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> todo <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$input<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>todo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span><span class="token function">addTodo</span><span class="token punctuation">(</span>todo<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>$input<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>form onSubmit<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleSubmit<span class="token punctuation">}</span><span class="token operator">></span>
<span class="token operator"><</span>fieldset<span class="token operator">></span>
<span class="token operator"><</span>input
ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token parameter">$input</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>$input <span class="token operator">=</span> $input<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">}</span>
type<span class="token operator">=</span><span class="token string">"text"</span>
<span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span>button<span class="token operator">></span>Add<span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>fieldset<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>form<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>참조</h2>
<ul>
<li><a href="https://github.com/reactjs/redux">Redux github repository</a></li>
</ul>
- <![CDATA[이벤트 핸들링 모델과 이벤트 버블링/캡쳐링]]>https://wonism.github.io/event-bubbling-capturing/https://wonism.github.io/event-bubbling-capturing/Tue, 03 Oct 2017 15:57:26 GMT<p><code class="hljs-text">DOM</code>의 <code class="hljs-text">event</code>는 이벤트 중심 프로그래밍 언어가 DOM 트리 내의 요소 노드 (<code class="hljs-text">HTML</code>, <code class="hljs-text">XHTML</code>, <code class="hljs-text">SVG</code> 등)에 <code class="hljs-text">이벤트 처리기/수신기</code>를 등록할 수 있도록 한다.<br />
하지만, 초창기 다양한 웹 브라우저에서 사용되는 이벤트 모델에는 몇 가지 차이점이 있었는데 이로 인해 호환성 문제가 발생했다. <code class="hljs-text">W3C</code>는 이를 해결하기 위해 <code class="hljs-text">DOM Level 2</code>에서 이벤트 모델을 표준화하였다.</p>
<h2>이벤트 핸들링 모델</h2>
<h3>DOM Level 0에서의 이벤트 핸들링 모델</h3>
<p>이 이벤트 핸들링 모델은 <code class="hljs-text">Netscape Navigator</code>에서 소개되었으며, 인라인 모델과 전통적 모델의 두 가지 모델 유형이 있다.</p>
<p><strong>인라인 모델</strong></p>
<p>인라인 모델에서는 이벤트 핸들러는 태그의 속성으로 추가된다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>alert('Hello, Event!'); return false;<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Click<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span></code></pre></div>
<p><code class="hljs-text">JavaScript 엔진</code>이 <code class="hljs-text">onclick</code>속성의 내용을 포함하는 익명 함수를 생성하며, <code class="hljs-text"><button></code>의 onclick 핸들러는 다음 익명 함수에 바인드된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'Hello, Event!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p><strong>전통적 모델</strong></p>
<p>전통적 모델에서는 스크립트로 이벤트 핸들러를 추가하거나 제거할 수 있다.<br />
이 때, 각 이벤트는 하나의 이벤트 핸들러만 등록할 수 있다.</p>
<p>이벤트는 태그의 이벤트 속성에 핸들러 이름을 할당함으로써 추가되며, 이벤트 핸들러를 제거하려면, <code class="hljs-text">null</code>을 할당한다.<br />
인자를 넘기기 위해 클로저 개념을 사용할 수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">window<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'window is loaded'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
window<span class="token punctuation">.</span>onload <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span>onload <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token string">'Event is fired!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>DOM Level 2에서의 이벤트 핸들링 모델</h3>
<p><code class="hljs-text">W3C</code>에서는 보다 유연한 이벤트 핸들링 모델을 설계했다.<br />
<code class="hljs-text">addEventListener</code>를 통해 이벤트 대상에 이벤트 리스너를 등록할 수 있으며, <code class="hljs-text">removeEventListener</code>를 통해 이벤트 리스너를 제거할 수 있다.<br />
또, <code class="hljs-text">dispatchEvent</code>를 통해 구독된 이벤트 리스너에 이벤트를 보낼 수 있다.
<code class="hljs-text">DOM Level 0</code>와 달리 동일한 이벤트에 대해 여러 이벤트 핸들러를 등록할 수 있으며, 다양한 옵션들을 사용할 수 있다.</p>
<h4>이벤트 기본 동작 호출 방지</h4>
<p>이벤트의 기본 동작이 호출되지 않게 하기위해 이벤트 객체의 <code class="hljs-text">preventDefault</code>메소드를 호출한다.</p>
<h4>이벤트 버블링 방지</h4>
<p>뒤에 이벤트 버블링에 대한 설명을 하겠지만, 이벤트가 버블링되지 않게 하기 위해서는 이벤트 객체의 <code class="hljs-text">stopPropagation</code> 메소드를 호출한다.<br /></p>
<h4>IE 구버전에서의 이벤트 핸들링 모델</h4>
<p><code class="hljs-text">Internet Explorer 9</code> 미만의 버전에서는 <code class="hljs-text">addEventListener</code>대신 <code class="hljs-text">attachEvent</code>, <code class="hljs-text">removeEventListener</code>대신 <code class="hljs-text">detachEvent</code>, <code class="hljs-text">dispatchEvent</code>대신 <code class="hljs-text">fireEvent</code>를 사용한다.<br />
이벤트 기본 동작 호출을 방지하기 위해서는 이벤트 객체의 <code class="hljs-text">returnValue</code> 속성을 <code class="hljs-text">false</code>로 하며,
이벤트 버블링을 방지하기 위해서는 이벤트 객체의 <code class="hljs-text">cancelBubble</code> 속성을 <code class="hljs-text">true</code>로 한다.</p>
<h4>addEventListener의 옵션</h4>
<p><code class="hljs-text">addEventListener</code>의 <code class="hljs-text">boolean</code> 타입 옵션을 통해 이벤트 캡쳐링 방식으로 이벤트 핸들러를 호출하거나,
<code class="hljs-text">object</code> 타입 옵션을 통해 단 한 번만 이벤트 핸들러를 호출하게 할 수 있다.<br />
(IE Edge에서는 <code class="hljs-text">object</code> 타입 옵션을 사용할 수 없다.)</p>
<h2>이벤트 종류</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/DOM_events#HTML_events">링크</a> 참고</li>
</ul>
<h2>이벤트 흐름</h2>
<p>이벤트 흐름은 이벤트가 전달되는 과정으로 다음 세 단계로 생명주기가 구성된다.</p>
<ul>
<li>이벤트 캡쳐링</li>
<li>타겟</li>
<li>이벤트 버블링</li>
</ul>
<p>캡쳐링과 버블링의 차이를 설명하기 위해 다음과 같은 <code class="hljs-text">DOM</code>이 있다고 가정한다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Click!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span></code></pre></div>
<p>이 때, <code class="hljs-text"><button></code>요소에 <code class="hljs-text">click</code> 이벤트가 발생하면, <code class="hljs-text"><button></code>요소는 물론, <code class="hljs-text"><main></code>, <code class="hljs-text"><form></code>요소 등도 이벤트를 감지할 수 있다. 이렇게 중첩되는 요소가 있는 구조에서 이벤트가 발생할 때, 다음과 같이 이벤트가 발생한다.</p>
<h3>이벤트 캡쳐링</h3>
<p>이벤트 흐름이 가장 얕은 깊이의 노드(부모 노드)에서 가장 깊은 깊이의 노드(자식 노드)로 향한다.<br />
또한 <code class="hljs-text">button</code>을 클릭했을 때, 클릭 이벤트는 다음 순서대로 발생한다.</p>
<p><code class="hljs-text"><main> ▶ <section> ▶ <div> ▶ <button></code></p>
<p>(이벤트 캡쳐링 방식의 흐름을 원할 경우 <code class="hljs-text">addEventListener</code>의 3번째 인자를 <code class="hljs-text">true</code>로 넘긴다.)</p>
<h3>타겟</h3>
<p>실제 타겟(<code class="hljs-text"><button></code>)이 이벤트를 가져온다.</p>
<h3>이벤트 버블링</h3>
<p>이벤트 흐름이 가장 깊은 깊이의 노드(자식 노드)에서 가장 얕은 깊이의 노드(부모 노드)로 향한다.<br />
또한 <code class="hljs-text">button</code>을 클릭했을 때, 클릭 이벤트는 다음 순서대로 발생한다.<br /></p>
<p><code class="hljs-text"><button> ▶ <div> ▶ <section> ▶ <main></code></p>
<p>(이벤트 버블링 방식의 흐름을 원할 경우 <code class="hljs-text">addEventListener</code>의 3번째 인자를 <code class="hljs-text">false</code>로 넘기거나, 넘기지 않는다. (기본값은 <code class="hljs-text">false</code>))</p>
<h2>이벤트 버블링과 캡쳐링 예제</h2>
<h3>이벤트 버블링 예제</h3>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>event-bubbling-example<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Click!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">handleClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-bubbling-example main'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handleClick<span class="token punctuation">)</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-bubbling-example section'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handleClick<span class="token punctuation">)</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-bubbling-example div'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handleClick<span class="token punctuation">)</span><span class="token punctuation">;</span>
document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-bubbling-example button'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handleClick<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<div id="event-bubbling-example"></div>
<p>이 예제 코드를 실행하면, <code class="hljs-text">BUTTON</code> ▶ <code class="hljs-text">DIV</code> ▶ <code class="hljs-text">SECTION</code> ▶ <code class="hljs-text">MAIN</code>순서로 경고창이 출력되는 것을 볼 수 있다.</p>
<h3>이벤트 전파 방지하기 예제</h3>
<p>다음과 같은 코드를 작성하면, 이벤트가 전파되지 않는다.<br />
이벤트가 전파되지 않기 때문에 경고창이 <code class="hljs-text">BUTTON</code>만 출력함을 알 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">handleClick</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">alert</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>e<span class="token punctuation">.</span>stopPropagation<span class="token punctuation">)</span> <span class="token punctuation">{</span>
e<span class="token punctuation">.</span><span class="token function">stopPropagation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
e<span class="token punctuation">.</span>cancelBubble <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
<div id="prevent-event-bubbling-example"></div>
<h3>이벤트 캡쳐링 예제</h3>
<p><code class="hljs-text">addEventListener</code>의 3번째 인자를 통해 이벤트 캡쳐링 방식으로 이벤트를 핸들링할 수 있다.</p>
<div class="gatsby-highlight" data-language="html"><pre class="hljs-html"><code class="hljs-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>event-capturing-example<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span><span class="token punctuation">></span></span>Click!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>section</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// DOM LEVEL 2 Event Model 처리 함수</span>
<span class="token keyword">const</span> <span class="token function-variable function">addEvent</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">element<span class="token punctuation">,</span> type<span class="token punctuation">,</span> handler<span class="token punctuation">,</span> capture</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
type <span class="token operator">=</span> <span class="token keyword">typeof</span> type <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">&&</span> type <span class="token operator">||</span> <span class="token string">''</span><span class="token punctuation">;</span>
handler <span class="token operator">=</span> handler <span class="token operator">||</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>element<span class="token punctuation">.</span>addEventListener<span class="token punctuation">)</span> <span class="token punctuation">{</span>
element<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> handler<span class="token punctuation">,</span> capture<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>element<span class="token punctuation">.</span>attachEvent<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// For IE8</span>
element<span class="token punctuation">.</span><span class="token function">attachEvent</span><span class="token punctuation">(</span><span class="token string">'on'</span> <span class="token operator">+</span> type<span class="token punctuation">,</span> handler<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> element<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">addEvent</span><span class="token punctuation">(</span>window<span class="token punctuation">,</span> <span class="token string">'load'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">addEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-capturing-example main'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-capturing-example section'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-capturing-example div'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">addEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#event-capturing-example button'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>currentTarget<span class="token punctuation">.</span>tagName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>이 예제 코드를 실행한 뒤 버튼을 클릭하면, <code class="hljs-text">MAIN</code> ▶ <code class="hljs-text">BUTTON</code> ▶ <code class="hljs-text">DIV</code> ▶ <code class="hljs-text">SECTION</code>이 출력되는 것을 볼 수 있다.<br />
<code class="hljs-text">DIV</code>와 <code class="hljs-text">SECTION</code>이 가장 늦게 출력되는 이유는 이벤트 버블링 방식으로 이벤트가 등록되기 때문이다.<br />
구버전의 IE에서 이를 수행하면, 이벤트 버블링 방식으로 <code class="hljs-text">BUTTON</code> ▶ <code class="hljs-text">DIV</code> ▶ <code class="hljs-text">SECTION</code> ▶ <code class="hljs-text">MAIN</code>이 출력된다.</p>
<div id="event-capturing-example"></div>
<h2>기타 : 리액트에서의 버블링과 캡쳐링</h2>
<p>리액트의 이벤트 핸들러는 버블링 단계의 이벤트에 의해 트리거된다.<br />
캡쳐링 단계에 대한 이벤트 핸들러를 등록하려면, <code class="hljs-text">Capture</code>를 접미사로 붙인다.<br />
예 : <code class="hljs-text">onClickCapture</code>, <code class="hljs-text">onKeyPressCapture</code></p>
<h2>참조</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/DOM_events">Wiki : DOM events</a></li>
<li><a href="http://www.tutorialspark.com/javascript/JavaScript_Event_Flow.php">Tutorials Park : Javascript : Event Flow</a></li>
</ul>
- <![CDATA[간단한 Monad 예제]]>https://wonism.github.io/monad-simple-example/https://wonism.github.io/monad-simple-example/Tue, 26 Sep 2017 23:01:23 GMT<p><code class="hljs-text">Monad</code>는 순서가 있는 연산을 처리할 때 사용되는 디자인 패턴으로 부작용을 관리하기 위해 함수형 프로그래밍 언어에서 사용된다.</p>
<h2>간단한 모나드 구현</h2>
<h3>f⋄g(x) = f(g(x))</h3>
<p>삼각함수 <code class="hljs-text">sine</code>의 값을 구하는 <code class="hljs-text">Math.sin</code>을 래핑하는 함수 <code class="hljs-text">sine</code>과 숫자의 큐브를 구하는 래퍼 함수가 있다고 가정한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">sine</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> Math<span class="token punctuation">.</span><span class="token function">sin</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">sine</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token constant">PI</span> <span class="token operator">*</span> <span class="token number">1</span><span class="token operator">/</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1</span>
<span class="token keyword">const</span> <span class="token function-variable function">cube</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">(</span>x <span class="token operator">**</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">cube</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 27</span></code></pre></div>
<p><code class="hljs-text">x</code>를 입력받는 <code class="hljs-text">sine</code>의 반환값을 <code class="hljs-text">cube</code>에 전달하는 함수는 다음과 같이 구성될 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">cubeThenSine</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token function">cube</span><span class="token punctuation">(</span><span class="token function">sine</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">cubeThenSine</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.5958232365909556</span></code></pre></div>
<p>함수 구성을 캡슐화하는 <code class="hljs-text">compose</code>를 사용한다면 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">compose</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">f<span class="token punctuation">,</span> g</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// posibble to use Ramda's or Lodash's</span>
<span class="token keyword">const</span> sineCube <span class="token operator">=</span> <span class="token function">compose</span><span class="token punctuation">(</span>cube<span class="token punctuation">,</span> sine<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">sineCube</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.5958232365909556</span></code></pre></div>
<h3>함수 구성</h3>
<p><strong>로깅</strong></p>
<p>함수가 호출되었다는 것을 추적하기 위해 <code class="hljs-text">console.log</code>를 사용하는 대신 함수가 한 쌍의 값을 반환하도록 수정한다. (<code class="hljs-text">console.log</code>는 부작용을 일으키기 때문이다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">sine</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">[</span>Math<span class="token punctuation">.</span><span class="token function">sin</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'sine was called.'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">cube</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">[</span>x <span class="token operator">**</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">'cube was called.'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">sine</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [0.9092974268256817, 'sine was called.']</span>
<span class="token function">cube</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [8, 'cube was called.']</span>
<span class="token function">compose</span><span class="token punctuation">(</span>sine<span class="token punctuation">,</span> cube<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [NaN, 'sine was called.']</span></code></pre></div>
<p>위 함수는 두 가지 측면에서 예상치 못한 값을 반환한다.</p>
<ol>
<li><code class="hljs-text">sine</code>은 <code class="hljs-text">Math.sin</code>을 계산하려고 하지만, 입력받은 인자가 숫자가 아니기 때문에 <code class="hljs-text">NaN</code>을 반환하게 된다.</li>
<li><code class="hljs-text">cube</code>의 반환값의 2번째 원소인 <code class="hljs-text">cube was called.</code>가 사라진다.</li>
</ol>
<p>이를 해결하기 위해 각 함수의 반환값을 분리하고 관심사에 따라 다시 결합한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">composeM</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">f<span class="token punctuation">,</span> g</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>y<span class="token punctuation">,</span> s<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">g</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>z<span class="token punctuation">,</span> t<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>z<span class="token punctuation">,</span> s <span class="token operator">+</span> t<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">composeM</span><span class="token punctuation">(</span>sine<span class="token punctuation">,</span> cube<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.956375928404503, 'cube was called.sine was called.'</span></code></pre></div>
<h3>Bind</h3>
<p>각각의 함수를 그대로 사용하려면, 원하는 형식으로 변환하는 도구를 제공하는 것이 좋다.<br />
이를 <code class="hljs-text">bind</code> 함수라고 하는데, <code class="hljs-text">Haskell</code>에서는 <code class="hljs-text">>>=</code>로 사용된다.<br />
<code class="hljs-text">bind</code>는 <code class="hljs-text">Number -> (Number, String)</code>함수를 받아 <code class="hljs-text">(Number, String) -> (Number, String)</code>함수를 반환한다.<br />
(이 <code class="hljs-text">bind</code>는 <code class="hljs-text">Function.prototype.bind</code>와는 전혀 다르다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">bind</span> <span class="token operator">=</span> <span class="token parameter">f</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token parameter">tuple</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>x<span class="token punctuation">,</span> s<span class="token punctuation">]</span> <span class="token operator">=</span> tuple<span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">[</span>y<span class="token punctuation">,</span> t<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">[</span>y<span class="token punctuation">,</span> s <span class="token operator">+</span> t<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>이 <code class="hljs-text">bind</code>함수는 다음과 같이 사용할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token function">composeM</span><span class="token punctuation">(</span><span class="token function">bind</span><span class="token punctuation">(</span>sine<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">bind</span><span class="token punctuation">(</span>cube<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.956375928404503, 'cube was called.sine was called.'</span></code></pre></div>
<h3>Unit</h3>
<p><code class="hljs-text">composeM</code>된 함수의 인자로 쓸데 없는 <code class="hljs-text">''</code>를 넘기고 있다.<br />
함수를 변환하는 것 뿐만 아니라 값을 수용가능한 형태로 변환하는 것이 필요하다.<br />
함수 <code class="hljs-text">unit</code>는이를 위한 함수로, 함수가 사용할 수 있는 기본 컨테이너로 래핑하는 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">unit</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token punctuation">[</span>x<span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">composeM</span><span class="token punctuation">(</span><span class="token function">bind</span><span class="token punctuation">(</span>sine<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">bind</span><span class="token punctuation">(</span>cube<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token function">unit</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.956375928404503, 'cube was called.sine was called.'</span></code></pre></div>
<p><code class="hljs-text">composeM(bind(sine), bind(cube))</code>와 <code class="hljs-text">unit</code>을 구성할수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token function">compose</span><span class="token punctuation">(</span><span class="token function">composeM</span><span class="token punctuation">(</span><span class="token function">bind</span><span class="token punctuation">(</span>sine<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">bind</span><span class="token punctuation">(</span>cube<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> unit<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0.956375928404503, 'cube was called.sine was called.'</span></code></pre></div>
<h3>Lift</h3>
<p><code class="hljs-text">lift</code>는 <code class="hljs-text">Number -> Number</code> 함수를 받아 <code class="hljs-text">Number -> (Number, String)</code> 함수를 반환하며, 다음과 같이 구현할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">lift</span> <span class="token operator">=</span> <span class="token parameter">f</span> <span class="token operator">=></span> <span class="token function">compose</span><span class="token punctuation">(</span>unit<span class="token punctuation">,</span> f<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">lift</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">x</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">/* ... */</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참조</h2>
<ul>
<li><a href="https://blog.jcoglan.com/2011/03/05/translation-from-haskell-to-javascript-of-selected-portions-of-the-best-introduction-to-monads-ive-ever-read/">Translation from Haskell to JavaScript of selected portions of the best introduction to monads I’ve ever read</a></li>
</ul>
- <![CDATA[Memoization에 대해]]>https://wonism.github.io/memoization/https://wonism.github.io/memoization/Sat, 16 Sep 2017 00:04:07 GMT<p><code class="hljs-text">Memoization</code>은 매번 함수를 다시 계산하는 대신 함수의 값을 저장하는 기술로 연산 결과를 저장하는 객체를 사용함으로써 불필요한 작업을 피할 수 있다.<br />
즉, 메모는 함수를 위한 캐싱 기법이라고 할 수 있다.<br />
메모이제이션은 주어진 입력에 대해 항상 동일한 출력을 반환하는 알고리즘에 한해 사용된다. (e.g. <code class="hljs-text">Fibonacci</code>, <code class="hljs-text">Factorial</code>)</p>
<h2>피보나치 수열</h2>
<p>피보나치 수열의 <code class="hljs-text">n</code>번째 값을 구하는 함수는 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">fibonacci</span> <span class="token operator">=</span> <span class="token parameter">n</span> <span class="token operator">=></span>
n <span class="token operator"><</span> <span class="token number">2</span> <span class="token operator">?</span> n <span class="token punctuation">:</span> <span class="token function">fibonacci</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token function">fibonacci</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>만약 이 함수가 여러 번 실행된다면, 이 함수는 수없이 호출되어야 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>i<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> : </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">fibonacci</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 직접 호출한 횟수 11 번</span>
<span class="token comment">// 이미 계산한 값들을 다시 계산하기 위해 호출된 횟수 11 번</span>
<span class="token comment">// 총 453 번 호출</span></code></pre></div>
<h2>피보나치 수열과 메모이제이션</h2>
<p>만약 메모이제이션을 적용한다면 작업량을 엄청나게 줄일 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> fibonacci <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> memo <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">fn</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> result <span class="token operator">=</span> memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> result <span class="token operator">!==</span> <span class="token string">'number'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token function">fn</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span> <span class="token operator">=</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> fn<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>i<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> : </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token function">fibonacci</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 직접 호출한 횟수 11번</span>
<span class="token comment">// 앞선 메모이제이션 결과를 얻기 위해 호출한 18번</span>
<span class="token comment">// 총 29번 호출</span></code></pre></div>
<h2>메모이제이션 함수의 구현</h2>
<p>재귀함수를 <code class="hljs-text">memoize</code>할 수 있도록 해주는 함수를 만들어 보겠다.<br />
(이 함수는 예시일 뿐이며, 얼마든지 커스터마이즈할 수 있다.)<br /></p>
<h4>구현 전략</h4>
<ol>
<li>첫 번째 인자로는 결과를 저장할 배열을 받으며, 두 번째 인자로는 메모이즈할 함수를 받는다.</li>
<li>반환 값은 함수이며, 구하고자 하는 값이 메모에 없으면 해당 함수를 실행하여 값을 계산한 뒤 메모에 해당 값을 저장한다.</li>
</ol>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">memoizer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">memo<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> <span class="token function-variable function">calc</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> result <span class="token operator">=</span> memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> result <span class="token operator">!==</span> <span class="token string">'number'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
result <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>calc<span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">;</span>
memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span> <span class="token operator">=</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> calc<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p>구현된 함수는 위와 같으며, <code class="hljs-text">fibonacci</code>와 <code class="hljs-text">factorial</code>을 <code class="hljs-text">memoizer</code>함수를 통해 메모이제이션할 수 있다.</p>
<h4>피보나치와 팩토리얼의 메모이제이션</h4>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> fibonacci <span class="token operator">=</span> <span class="token function">memoizer</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">calc<span class="token punctuation">,</span> n</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">calc</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token function">calc</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> factorial <span class="token operator">=</span> <span class="token function">memoizer</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">calc<span class="token punctuation">,</span> n</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> n <span class="token operator">*</span> <span class="token function">calc</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h4>성능 확인</h4>
<p>위에서 구현한 <code class="hljs-text">fibonacci</code>함수를 통해 성능을 측정해보겠다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">console<span class="token punctuation">.</span><span class="token function">time</span><span class="token punctuation">(</span><span class="token string">'fibonacci - 1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">fibonacci</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">timeEnd</span><span class="token punctuation">(</span><span class="token string">'fibonacci - 1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// fibonacci - 1: 0.076904296875ms</span>
console<span class="token punctuation">.</span><span class="token function">time</span><span class="token punctuation">(</span><span class="token string">'fibonacci - 2'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">fibonacci</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">timeEnd</span><span class="token punctuation">(</span><span class="token string">'fibonacci - 2'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// fibonacci - 2: 0.005126953125ms</span></code></pre></div>
<h2>주의할 점</h2>
<ol>
<li>메모이즈된 함수는 오래된 결과를 저장하기 때문에 메모리를 추가적으로 소비하게 된다.</li>
<li>실행 속도가 빠르거나 자주 실행되지 않는 함수의 경우 실용적이지 않을 수 있다.</li>
<li>부작용이 없는 순수 함수에만 적용될 수 있다.</li>
</ol>
<h2>관련 라이브러리 및 데코레이터</h2>
<ul>
<li><a href="https://github.com/developit/decko#memoize">ES 2016 decorators</a></li>
<li><a href="https://github.com/lodash/lodash/blob/master/memoize.js">Lodash</a></li>
<li><a href="https://github.com/ramda/ramda/blob/master/src/memoize.js">Ramda</a></li>
<li><a href="https://github.com/reactjs/reselect">Reselect</a></li>
</ul>
- <![CDATA[리액트 성능 향상 시키기 - React.PureComponent]]>https://wonism.github.io/react-pure-component/https://wonism.github.io/react-pure-component/Wed, 13 Sep 2017 21:39:50 GMT<p><code class="hljs-text">React.PureComponent</code>는 <code class="hljs-text">React.Component</code>와 매우 유사하다. 하지만 한 가지 다른 점이 있다면, <code class="hljs-text">React</code>의 생명주기 메소드 중 하나인 <code class="hljs-text">shouldComponentUpdate</code>를 다루는 방식이 다르다는 것이다.<br />
<code class="hljs-text">React.PureComponent</code>는 <code class="hljs-text">shouldComponentUpdate</code>가 이미 구현되어 있는데, <code class="hljs-text">props</code>와 <code class="hljs-text">state</code>를 <code class="hljs-text">얕은 비교</code>를 통해 비교한 뒤 변경된 것이 있을 때만 리렌더링한다.<br />
즉, <code class="hljs-text">React.PureComponent</code>를 사용하면 <code class="hljs-text">React</code>애플리케이션 성능을 향상시키는 데 가장 중요한 것 중 하나인 <code class="hljs-text">shouldComponentUpdate</code>를 신경쓰지 않아도 된다.<br />
하지만 <code class="hljs-text">props</code>나 <code class="hljs-text">state</code>가 복잡한 데이터 구조를 포함하고 있다면, <code class="hljs-text">props</code>와 <code class="hljs-text">state</code>를 비교하는 과정에서 의도하지 않은 결과가 발생할 수 있다.<br />
(<code class="hljs-text">얕은 비교(shallow comparison)</code>와 <code class="hljs-text">깊은 비교(deep comparison)</code>의 차이를 알면 무슨 의미인지 알 것이다.)</p>
<h2>PureComponent vs Component</h2>
<p>사용자가 버튼을 클릭하면 카운터가 랜덤하게 증가하는 컴퍼넌트이다.<br />
<code class="hljs-text">PureComponent</code>와 <code class="hljs-text">Component</code>의 차이를 비교하려면, 아래 예제 코드에서 단지 <code class="hljs-text">Pure</code>를 지우거나 다시 쓰면 된다.<br />
<code class="hljs-text">PureComponent</code>를 <code class="hljs-text">extends</code>한 컴퍼넌트는 카운터가 증가할 때만 <code class="hljs-text">re-render</code>되지만, <code class="hljs-text">Component</code>를 <code class="hljs-text">extends</code>한 컴퍼넌트는 버튼을 클릭하면 <code class="hljs-text">setState</code>가 실행되기 때문에 매 클릭마다 <code class="hljs-text">re-render</code>된다는 것을 볼 수 있다.<br />
(참고로 <code class="hljs-text">PureComponent</code>를 <code class="hljs-text">extends</code>한 컴퍼넌트 안에서도 <code class="hljs-text">shouldComponentUpdate</code> 메소드를 사용할 수 있다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> render <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-dom'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> root <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#root'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> pTag <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">logClosure</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> clickedCount <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> reRenderedCount <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">isReRendered</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>isReRendered<span class="token punctuation">)</span> <span class="token punctuation">{</span>
reRenderedCount <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
clickedCount <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
pTag<span class="token punctuation">.</span>textContent <span class="token operator">=</span> <span class="token template-string"><span class="token string">`log -> click count : </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>clickedCount<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> | re-render count : </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>reRenderedCount<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> log <span class="token operator">=</span> <span class="token function">logClosure</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span>
counter<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>handleClick <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">handleClick</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
root<span class="token punctuation">.</span><span class="token function">after</span><span class="token punctuation">(</span>pTag<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">handleClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
counter<span class="token punctuation">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>counter <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
counter<span class="token punctuation">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>counter<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">log</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span>
<span class="token operator"><</span>div<span class="token operator">></span>
<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>counter<span class="token punctuation">}</span>
<span class="token operator"><</span>br <span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span>input
type<span class="token operator">=</span><span class="token string">"button"</span>
onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleClick<span class="token punctuation">}</span>
value<span class="token operator">=</span><span class="token string">"click"</span>
<span class="token operator">/</span><span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token operator"><</span>App <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> root<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h3>실행결과</h3>
<p>다음 컴퍼넌트는 <code class="hljs-text">PureComponent</code>를 <code class="hljs-text">extends</code>한 컴퍼넌트이다.</p>
<div id="pure-component-example"></div>
<p>다음 컴퍼넌트는 <code class="hljs-text">Component</code>를 <code class="hljs-text">extends</code>한 컴퍼넌트이다.</p>
<div id="component-example"></div>
<h2>결론</h2>
<p><code class="hljs-text">functional components</code>는 아직까지 최적화되어있지 않다. 그 이유는 함수형 컴퍼넌트도 결국엔 클래스 기반 컴퍼넌트로 래핑되기 때문이다.<br />
(하지만 <code class="hljs-text">React Team</code>은 언젠가 함수형 컴퍼넌트를 최적화하겠다고 했다.)<br />
따라서 현재까지는 최적화가 필요한 컴퍼넌트에서는 클래스 컴퍼넌트의 <code class="hljs-text">shouldComponentUpdate</code> 메소드를 사용하거나 <code class="hljs-text">PureComponent</code>를 통해 최적화하는 것이 가장 좋은 방법이라고 할 수 있다.</p>
<div id="functional-component"></div>
<h2>참조</h2>
<ul>
<li><a href="https://facebook.github.io/react/docs/react-api.html#react.purecomponent">React Top-Level API</a></li>
<li><a href="https://twitter.com/dan_abramov/status/755343749983657986">Dan Abramov’s Twitter</a></li>
</ul>
- <![CDATA[node-sass/vendor 에러]]>https://wonism.github.io/node-sass-vendor/https://wonism.github.io/node-sass-vendor/Mon, 11 Sep 2017 22:57:26 GMT<p><code class="hljs-text">node_modules</code> 디렉토리를 삭제하고 다시 패키지들을 설치한 뒤 <code class="hljs-text">js</code> 파일들을 번들링할 일이 있었다.<br />
하지만 잘 번들링 되던 파일들이 번들링되지 않는 문제가 발생했다.<br />
무슨 에러인지 봤더니, <code class="hljs-text">node-sass/vendor</code>가 없다는 에러였다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">ENOENT: no such file or directory, scandir '/PROJECT_PATH/node_modules/node-sass/vendor'</code></pre></div>
<p><code class="hljs-text">node_modules</code>디렉토리를 확인해보니 <code class="hljs-text">node-sass</code>패키지는 제대로 설치가 되어있는 듯 해보였지만, <code class="hljs-text">node_modules/node-sass/vendor</code> 디렉토리가 존재하지 않았다.<br />
<a href="https://github.com/sass/node-sass/issues"><code class="hljs-text">node-sass</code></a>의 <code class="hljs-text">Issues</code> 탭에 이미 여러 번 올라와 있는 이슈였다.<br />
원인은 패키지 설치 이후 <code class="hljs-text">node-sass</code>의 <code class="hljs-text">scripts/install.js</code>를 실행하지 않아서였다.</p>
<p>해결 방법은 수동으로 <code class="hljs-text">node-sass</code>의 스크립트를 실행하거나, <code class="hljs-text">node-sass</code> 패키지를 리빌드하는 것이다.</p>
<div class="gatsby-highlight" data-language="text"><pre class="hljs-text"><code class="hljs-text">$ node node_modules/node-sass/scripts/install.js
# or
$ npm rebuild node-sass</code></pre></div>
- <![CDATA[module.exports와 exports]]>https://wonism.github.io/module-exports-and-exports/https://wonism.github.io/module-exports-and-exports/Sun, 10 Sep 2017 13:32:32 GMT<p><code class="hljs-text">module</code>은 <code class="hljs-text">exports</code>속성이 있는 자바스크립트 객체이며, <code class="hljs-text">exports</code>는 보통 <code class="hljs-text">module.exports</code>로 설정되는 일반적인 자바스크립트 변수이다.<br />
<code class="hljs-text">exports.a = 42;</code>와 같이 <code class="hljs-text">exports</code>의 속성을 설정하면, <code class="hljs-text">module.exports.a</code>도 설정이 된다. 자바스크립트에서는 객체가 참조로 전달되기 때문이다.<br />
즉, <code class="hljs-text">exports</code>와 <code class="hljs-text">module.exports</code>는 같은 객체를 참조하며, <code class="hljs-text">this</code> 또한 마찬가지이다.<br />
다음과 같은 예제를 통해 확인할 수 있다.</p>
<div class="gatsby-highlight" data-language="sh"><pre class="hljs-sh"><code class="hljs-sh"># write file with printf
$ printf "// module.exports\nmodule.exports.add = function (a, b) { return a + b; };\n\n// exports\nexports.add = function (a, b) { return a + b; };\n\n// this\nthis.add = function (a, b) { return a + b; };" > math.js
# execute node.js
$ node
> const math = require('./math');
undefined
> math
{ add: [Function] }
> math.add(42, 5);
47</code></pre></div>
- <![CDATA[ES2015에서 import로 이미지 불러오기]]>https://wonism.github.io/import-image-with-import/https://wonism.github.io/import-image-with-import/Sun, 10 Sep 2017 13:28:09 GMT<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> url <span class="token keyword">from</span> <span class="token string">'/PATH/TO/IMAGE/filename.extension'</span><span class="token punctuation">;</span>
<span class="token comment">// for example</span>
<span class="token comment">// import * as logo from '../public/assets/images/logo.png';</span>
<span class="token comment">/* Native DOM */</span>
<span class="token keyword">const</span> image <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'img'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
img<span class="token punctuation">.</span>src <span class="token operator">=</span> url<span class="token punctuation">.</span>default<span class="token punctuation">;</span>
<span class="token comment">/* JSX */</span>
<span class="token operator"><</span>img src<span class="token operator">=</span><span class="token punctuation">{</span>url<span class="token punctuation">.</span>default<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span></code></pre></div>
- <![CDATA[Switch안에서의 let과 const]]>https://wonism.github.io/block-scope-in-switch/https://wonism.github.io/block-scope-in-switch/Sun, 10 Sep 2017 13:22:48 GMT<p>ES2015 의 <code class="hljs-text">let</code>, <code class="hljs-text">const</code> 키워드는 변수를 블록 스코프를 가지는 지역변수로 만들어 준다.<br />
이외에도 <code class="hljs-text">let</code>, <code class="hljs-text">const</code> 는 TDZ 를 해결해주며, 함수 스코프를 따름으로써 발생하는 문제들을 해결해준다.<br />
하지만, <code class="hljs-text">switch</code> 문 안에서 <code class="hljs-text">let</code>, <code class="hljs-text">const</code> 를 사용할 떄는 유의할 점이 있다.<br />
<code class="hljs-text">case</code> 문은 별도의 Lexical Scope 가 없기 때문에 다음과 같은 코드에서는 에러가 발생한다는 것이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">switch</span> <span class="token punctuation">(</span>foo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span>
<span class="token keyword">let</span> foo <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span>
<span class="token keyword">const</span> foo <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">}</span></code></pre></div>
<br />
<p>이런 이슈를 해결하기 위해서는 블록 스코프가 필요한 곳의 <code class="hljs-text">case</code> 문을 <code class="hljs-text">{}</code> 로 감싸야 한다.<br /></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">switch</span> <span class="token punctuation">(</span>foo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> foo <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> foo <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token number">3</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">function</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> <span class="token number">4</span><span class="token punctuation">:</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">default</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
<span class="token keyword">class</span> <span class="token class-name">C</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre></div>
- <![CDATA[화살표 함수에 대해서]]>https://wonism.github.io/arrow-function/https://wonism.github.io/arrow-function/Sun, 10 Sep 2017 11:03:12 GMT<p><code class="hljs-text">화살표함수</code>는 <code class="hljs-text">ES2015</code>에서 사용할 수 있는 함수 표현식으로 익명함수를 축약하여 표현할 수 있다. 이 화살표함수는 편리하면서도 특이한 성질이 있는데, 이에 대해 알아보겠다.</p>
<h2>표현식</h2>
<p><code class="hljs-text">ES2015</code>에서는 익명함수를 <code class="hljs-text">=></code>로 축약하여 나타낼 수 있다. 함수 표현식에 비하면 구문이 상당히 짧다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* Function expression */</span>
<span class="token keyword">function</span> <span class="token function">square</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> n <span class="token operator">*</span> n<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* Arrow function */</span>
<span class="token keyword">const</span> <span class="token function-variable function">square</span> <span class="token operator">=</span> <span class="token parameter">n</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> n <span class="token operator">*</span> n<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/* Arrow function without block */</span>
<span class="token keyword">const</span> <span class="token function-variable function">square</span> <span class="token operator">=</span> <span class="token parameter">n</span> <span class="token operator">=></span> n <span class="token operator">*</span> n<span class="token punctuation">;</span>
<span class="token comment">// 블록을 사용하지 않는다면, return을 생략한채로 값을 반환할 수 있다.</span>
<span class="token comment">/* Arrow function with multiple parameters */</span>
<span class="token keyword">const</span> <span class="token function-variable function">power</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">n<span class="token punctuation">,</span> e</span><span class="token punctuation">)</span> <span class="token operator">=></span> n <span class="token operator">**</span> e<span class="token punctuation">;</span>
<span class="token comment">// 여러 개의 인자를 사용할 떄에는 파라미터들을 ()로 묶어줘야 한다.</span>
<span class="token comment">/* Arrow function returns simple object */</span>
<span class="token keyword">const</span> <span class="token function-variable function">createObj</span> <span class="token operator">=</span> <span class="token parameter">n</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
number<span class="token punctuation">:</span> n<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 단순 객체를 반환하기 위해서는 객체 리터럴을 ()로 묶어줘야 한다.</span></code></pre></div>
<h2>화살표 함수와 this</h2>
<p>화살표 함수는 자기 고유의 <code class="hljs-text">this</code>값을 갖지 않으며, <code class="hljs-text">this</code>는 화살표 함수를 감싸는 외부 스코프로부터 계승받는다.<br />
다음 코드는 함수 표현식과 비교한 예제이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> t1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1초마다 t를 확인해보면, passedTime은 0이다.</span>
<span class="token comment">// setInterval의 인자인 함수 안에 있는 this는 Timer의 생성자에 의해 생성되기 때문이다.</span>
<span class="token comment">// 이를 제대로 동작하게 하기 위해선 this 객체를 다른 변수에 등록하여 사용하거나,</span>
<span class="token keyword">function</span> <span class="token function">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> that <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
that<span class="token punctuation">.</span>passedTime <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
that<span class="token punctuation">.</span>passedTime<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> t2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// bind 메소드를 통해 Timer의 this를 바인딩한다.</span>
<span class="token keyword">function</span> <span class="token function">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> t3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// this를 바인딩하거나, 참조하는 변수를 사용하는 방식대신,</span>
<span class="token comment">// 화살표 함수를 사용하면, 훨씬 간편하다.</span>
<span class="token keyword">function</span> <span class="token function">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>passedTime<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> t4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Timer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>화살표 함수와 arguments</h2>
<p>화살표함수에서는 <code class="hljs-text">arguments</code>를 사용할 수 없다.<br />
일반적인 함수 표현식에서는 전달받은 인자를 <code class="hljs-text">arguments</code>라는 유사배열로써 접근할 수 있었지만, 화살표 함수에서는 이를 사용할 수 없다.<br />
이와 같은 기능을 사용하고 싶다면, <code class="hljs-text">spread operator</code>를 사용해야 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// Function expression</span>
<span class="token keyword">function</span> <span class="token function">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> arguments<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator"><</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arguments<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">func</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1, 2, 3</span>
<span class="token comment">// Arrow function</span>
<span class="token keyword">const</span> <span class="token function-variable function">func2</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> arguments<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator"><</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Throw error when execute this function</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arguments<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment">// func2(1, 2, 3);</span>
<span class="token comment">// Arrow function with rest parameters</span>
<span class="token keyword">const</span> <span class="token function-variable function">func3</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> args<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator"><</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">func3</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1, 2, 3</span></code></pre></div>
- <![CDATA[함수형 프로그래밍이란?]]>https://wonism.github.io/what-is-fp/https://wonism.github.io/what-is-fp/Sat, 09 Sep 2017 23:52:32 GMT<p>함수형 프로그래밍은 순수한 함수를 작성하고, 공유된 상태와 변경 가능한 데이터 및 부작용을 피하여 소프트웨어를 작성하는 프로세스이다.<br />
함수형 프로그래밍은 명령형이 선언형이며, 애플리케이션의 상태는 순수한 함수를 통해 전달된다.<br />
애플리케이션의 상태가 공유되고, 객체의 메소드와 사용되는 객체 지향 프로그래밍과는 대조된다.</p>
<h2>함수형 프로그래밍의 장점</h2>
<p>함수형 코드는 명령형이나 객체지향 코드보다 간결하고 예측하기 쉬우며, 이에 따라 테스트가 더 쉬워진다.</p>
<h2>Pure functions</h2>
<p>함수형 프로그래밍에서 중요한 핵심은 함수는 부작용이 없어야 하며, 외부의 상태에 종속되지 않아야 한다.<br />
즉, 함수는 입력을 받고 출력을 반환함에 있어 외부의 값에 접근하지 않아야 한다.<br />
다음 예제를 통해 <code class="hljs-text">순수함수</code>와 <code class="hljs-text">순수함수가 아닌 함수</code>에 대해 알아보겠다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* pure function */</span>
<span class="token keyword">const</span> <span class="token function-variable function">double</span> <span class="token operator">=</span> <span class="token parameter">num</span> <span class="token operator">=></span> <span class="token punctuation">(</span>num <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* impure function */</span>
<span class="token keyword">const</span> operand <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">multiple</span> <span class="token operator">=</span> <span class="token parameter">num</span> <span class="token operator">=></span> <span class="token punctuation">(</span>num <span class="token operator">*</span> operand<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">double</code>의 입력이 <code class="hljs-text">2</code>라면, 해당 함수의 반환값은 항상 <code class="hljs-text">4</code>이다.<br />
반면, <code class="hljs-text">multiple</code>의 입력이 <code class="hljs-text">2</code>로 고정되어도 함수 외부의 <code class="hljs-text">operand</code>가 다른 <code class="hljs-text">2</code>가 확실하지 않다면 반환 값을 <code class="hljs-text">4</code>라고 예상하기 힘들다.</p>
<h2>Higher Order Functions</h2>
<p><code class="hljs-text">HOC</code>(Higher Order Functions)는 다른 함수를 인자로 사용하거나 함수를 반환하는 함수, 또는 두 가지 특징을 모두 가진 함수이다.<br />
고차 함수는 다음과 같은 경우 주로 사용된다.<br /></p>
<ul>
<li>콜백 함수, 프로미스, 모나드 등을 사용하여, 동작과 효과 또는 비동기 흐름 제어를 추상화하거나 격리한다.</li>
<li>다양한 데이터 유형에 대해 작동할 수 있는 유틸리티 생성한다.</li>
<li>함수를 부분적으로 인수에 적용하거나 재사용 또는 함수 조합을 위한 커리함수를 작성한다.</li>
<li>함수 목록을 가져오고, 해당 입력 함수의 조합을 반환한다.</li>
</ul>
<p>다음은 사용 예제이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">isEven</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token operator">!</span><span class="token punctuation">(</span>x <span class="token operator">%</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> numbers <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> evenNumbers <span class="token operator">=</span> numbers<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>isEven<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>evenNumbers<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 2, 4, 6, 8, 10</span></code></pre></div>
<p><code class="hljs-text">isEven</code>은 배열을 처리하는 로직이 필요 없으며, 배열을 순환하면서 재사용된다.</p>
<h2>Currying</h2>
<p>커링은 여러 인자를 받는 함수를 인자 하나씩 사용하여 함수 순서를 실행할 수 있도록 변환하는 것을 말한다.<br />
이는 람다 표현식과 클로저를 통해 쉽게 구현할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* not curried function */</span>
<span class="token keyword">function</span> <span class="token function">sumOfThreeThings</span><span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> z</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> x <span class="token operator">+</span> y <span class="token operator">+</span> z<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">sumOfThreeThings</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 6</span>
<span class="token comment">/* curried function */</span>
<span class="token keyword">const</span> <span class="token function-variable function">sumOfThreeThings</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span>
<span class="token parameter">y</span> <span class="token operator">=></span>
<span class="token parameter">z</span> <span class="token operator">=></span>
x <span class="token operator">+</span> y <span class="token operator">+</span> z<span class="token punctuation">;</span>
<span class="token function">sumOfThreeThings</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 6</span></code></pre></div>
<h3>Auto-currying</h3>
<p><a href="https://github.com/lodash/lodash"><code class="hljs-text">lodash</code></a>와 <a href="https://github.com/ramda/ramda"><code class="hljs-text">Ramda</code></a>는 <code class="hljs-text">curry</code>메소드를 가지고 있다. 이는 여러개의 인수를 가지는 함수를 커링된 함수로 만들어준다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// use lodash or ramda</span>
<span class="token keyword">const</span> curry <span class="token operator">=</span> _<span class="token punctuation">.</span>curry <span class="token operator">||</span> <span class="token constant">R</span><span class="token punctuation">.</span>curry<span class="token punctuation">;</span>
<span class="token comment">// given function that add 2 parameters</span>
<span class="token keyword">const</span> <span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token operator">=></span> x <span class="token operator">+</span> y
<span class="token comment">// transfired function</span>
<span class="token keyword">const</span> curriedAdd <span class="token operator">=</span> <span class="token function">curry</span><span class="token punctuation">(</span>add<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// results</span>
<span class="token function">curriedAdd</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// 3</span>
<span class="token function">curriedAdd</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// (y) => 1 + y</span>
<span class="token function">curriedAdd</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// 3</span></code></pre></div>
<h2>Function composition</h2>
<p>합성함수는 말그대로 두 가지 이상의 함수가 합성되었음을 뜻한다.<br />
두 함수 <code class="hljs-text">f</code>와 <code class="hljs-text">g</code>가 있고 <code class="hljs-text">f(g(x))</code>와 같이 사용된다고 할 때, 이를 수식 <code class="hljs-text">f ∘ g(x)</code>과 같이 표현할 수 있다.<br />
다음은 합성함수의 예시이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">compose</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">f<span class="token punctuation">,</span> g</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token parameter">y</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">pow</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token parameter">y</span> <span class="token operator">=></span> y <span class="token operator">**</span> x<span class="token punctuation">;</span>
<span class="token keyword">const</span> add2 <span class="token operator">=</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> square <span class="token operator">=</span> <span class="token function">pow</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> add2ThenSqaure <span class="token operator">=</span> <span class="token function">compose</span><span class="token punctuation">(</span>square<span class="token punctuation">,</span> add2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">add2ThenSquare</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 144</span></code></pre></div>
<h2>Point free notation</h2>
<p><code class="hljs-text">Point free</code>는 함수를 작성할 때, 매개변수를 정의하지 않는 것이다.<br />
이는 함수를 더욱 간결하게 해준다.<br />
다음은 <code class="hljs-text">point free</code>한 함수에 대한 예이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">map</span> <span class="token operator">=</span> <span class="token parameter">fn</span> <span class="token operator">=></span> <span class="token parameter">list</span> <span class="token operator">=></span> list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// or use lodash/fp</span>
<span class="token comment">// import { map } from 'lodash/fp';</span>
<span class="token keyword">const</span> <span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token parameter">x</span> <span class="token operator">=></span> <span class="token parameter">y</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token comment">/* function without point-free */</span>
<span class="token keyword">const</span> <span class="token function-variable function">incrementAll</span> <span class="token operator">=</span> <span class="token parameter">numbers</span> <span class="token operator">=></span> <span class="token function">map</span><span class="token punctuation">(</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">(</span>numbers<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/* function with point-free */</span>
<span class="token keyword">const</span> incrementAllWithPointFree <span class="token operator">=</span> <span class="token function">map</span><span class="token punctuation">(</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">incrementAll</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [2, 3, 4]</span>
<span class="token function">incrementAllWithPointFree</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [2, 3, 4]</span></code></pre></div>
<p>불필요한 매개변수를 사용하지 않으므로 매개변수에 대한 이름들에 대해 생각하지 않아도 되며, 코드가 훨씬 간결해진다.</p>
<h2>Recursion</h2>
<p>재귀 함수는 어느 조건을 만족할 때까지 자기 자신을 호출하는 함수이다.<br />
자바스크립트는 반복을 할 때, <code class="hljs-text">for</code>, <code class="hljs-text">while</code> 등의 반복문을 사용하지만, 함수형 프로그래밍에서는 반복문 대신 재귀를 사용한다.<br />
아래 예제는 동일한 루프 회수와 값을 얻게되는 반복문과 재귀함수이다.<br />
기존의 어떤 값을 수정하는 것이 아니라, 기존 값으로 새로운 값을 계산하고 이를 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* sum 1..10 with loop */</span>
<span class="token keyword">let</span> sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
sum <span class="token operator">+=</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>acc<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 55</span>
<span class="token comment">/* sum 1..10 with recursion */</span>
<span class="token function-variable function">sumRange</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> start<span class="token punctuation">,</span> end <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span>
<span class="token punctuation">(</span><span class="token parameter">sum</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>start <span class="token operator">></span> end<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> sum<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">sumRange</span><span class="token punctuation">(</span><span class="token punctuation">{</span> start<span class="token punctuation">:</span> start <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> end <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>sum <span class="token operator">+</span> start<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">sumRange</span><span class="token punctuation">(</span><span class="token punctuation">{</span> start<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> end<span class="token punctuation">:</span> <span class="token number">10</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>재귀는 <code class="hljs-text">for</code>, <code class="hljs-text">while</code> 등의 반복문을 대체할 수 있을 뿐만 아니라, 훨씬 유용하다. 특히 <code class="hljs-text">분할 및 정복</code> 알고리즘을 구현하는 데 매우 유용하다.<br />
가장 대표적인 재귀 함수 사용 예는 팩토리얼(<code class="hljs-text">!</code>)이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">factorial</span> <span class="token operator">=</span> <span class="token parameter">n</span> <span class="token operator">=></span>
n <span class="token operator">?</span>
n <span class="token operator">*</span> <span class="token function">factorial</span><span class="token punctuation">(</span>n <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">:</span>
<span class="token number">1</span><span class="token punctuation">;</span></code></pre></div>
<h4>재귀의 단점</h4>
<p>꼬리재귀 최적화가 되어있지 않은 언어에서는 재귀 사용 시 단점들이 있다.</p>
<ul>
<li>반복문에 비해 속도가 느리다.</li>
<li>스택을 사용하기 때문에 반복이 많아질 경우, 스택오버플로우가 발생될 수도 있다.</li>
</ul>
<p><code class="hljs-text">ES2015</code>의 <code class="hljs-text">strict mode</code>는 <code class="hljs-text">TCO</code>(Tail Call Optimization)를 제공하지만, ES5는 그렇지 않다.<br />
따라서, ES5에서 일반 반복대신 재귀를 사용하는 것은 성능 상의 이슈를 가질 수 있다.</p>
<h2>Monads</h2>
<p><code class="hljs-text">Monad</code>는 <code class="hljs-text">of</code>와 <code class="hljs-text">chain</code>이 있는 객체이다.(<code class="hljs-text">chain</code>은 중첩된 객체를 <code class="hljs-text">un-nenesting</code>하는 점을 제외하면, <code class="hljs-text">map</code>과 같다.)<br /></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// Implementation</span>
<span class="token class-name">Array</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">chain</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">f</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">acc<span class="token punctuation">,</span> it</span><span class="token punctuation">)</span> <span class="token operator">=></span> acc<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token function">f</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Usage</span>
Array<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'cat,dog'</span><span class="token punctuation">,</span> <span class="token string">'fish,bird'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">chain</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> e<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ['cat', 'dog', 'fish', 'bird']</span>
<span class="token comment">// Difference with map</span>
Array<span class="token punctuation">.</span><span class="token function">of</span><span class="token punctuation">(</span><span class="token string">'cat,dog'</span><span class="token punctuation">,</span> <span class="token string">'fish,bird'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">e</span> <span class="token operator">=></span> e<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [['cat', 'dog'], ['fish', 'bird']]</span></code></pre></div>
<h2>함수형 자바스크립트</h2>
<p>자바스크립트는 유연하다. 함수형, 객체지향형 패러다임의 특징을 모두 가지고 있다.<br />
함수형 패러다임으로 코드를 작성할 수 있지만 이상적인 함수형 프로그래밍을 하긴 어렵다. 하지만, 다양한 라이브러리를 통해 이를 보완할 수 있다.</p>
<h3>불변성</h3>
<p>위에서 말했듯이 함수형 프로그래밍에서는 부작용이 없어야 한다.<br />
따라서, 변수를 없애고 모든 값을 상수로 만들기 위해 <code class="hljs-text">ES2015</code>의 <code class="hljs-text">const</code>를 사용할 수 있다.<br />
<code class="hljs-text">const</code>는 객체가 아닌 값에 대해서는 충분하지만, 객체에서는 충분하지 않다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
arr<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
arr<span class="token punctuation">.</span><span class="token function">unshift</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [0, 1, 2, 3, 4]</span>
<span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">delete</span> obj<span class="token punctuation">.</span>x<span class="token punctuation">;</span>
obj<span class="token punctuation">.</span>y <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span>
obj<span class="token punctuation">.</span>z <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { y: 5, z: 0 };</span></code></pre></div>
<p><code class="hljs-text">const</code>로 선언되었지만, <code class="hljs-text">arr</code>와 <code class="hljs-text">obj</code>는 변경되었다.
이를 방지하기 위해, <a href="https://github.com/facebook/immutable-js"><code class="hljs-text">Immutable.js</code></a> 등의 라이브러리를 사용하거나, <a href="https://developer.mozilla.org/cs/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze"><code class="hljs-text">Object.freeze</code></a> 메소드를 사용할 수 있다.</p>
<h4>Object.freeze</h4>
<p>다음은 <code class="hljs-text">Object.freeze</code>의 사용 예제이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> arr <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">freeze</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// arr.push(4); throw error</span>
<span class="token comment">// arr.unshift(0); throw error</span>
<span class="token keyword">const</span> obj <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">freeze</span><span class="token punctuation">(</span><span class="token punctuation">{</span> x<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// delete obj.x; throw error</span>
<span class="token comment">// obj.y = 5; throw error</span>
<span class="token comment">// obj.z = 0; throw error</span></code></pre></div>
<p>하지만 <code class="hljs-text">Object.freeze</code>는 깊은 곳 까지 불변성을 가지게 하지는 못한다. 이 때, <a href="https://github.com/substack/deep-freeze"><code class="hljs-text">deep-freeze</code></a>를 사용할 수도 있다.</p>
<h4>lodash/fp</h4>
<p>다음은 <code class="hljs-text">fp.set</code>을 통한 객체 사용의 예제이다.<br />
<code class="hljs-text">Immutablity.js</code>나 <code class="hljs-text">Object.freeze</code>를 사용하지 않으면 객체의 불변성을 보장할 수는 없지만, 객체를 직접 사용하는 경우를 만들지 않음으로써, 객체의 불변성을 보장할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">import</span> fp <span class="token keyword">from</span> <span class="token string">'lodash/fp'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token punctuation">{</span> <span class="token keyword">set</span> <span class="token punctuation">}</span> <span class="token operator">=</span> fp<span class="token punctuation">;</span>
<span class="token comment">// const { set, flow } = fp;</span>
<span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token punctuation">{</span> innerY<span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> newObj <span class="token operator">=</span> <span class="token keyword">set</span><span class="token punctuation">(</span><span class="token string">'y.innerY'</span><span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token keyword">set</span><span class="token punctuation">(</span><span class="token string">'z'</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// of use flow</span>
<span class="token comment">// const newObj = flow(fp.set('y.innerY', 42), fp.set('z', 3))(obj);</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { x: 1, y: { innerY: 2 } }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>newObj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { x: 1, y: { innerY: 42 }, z: 3 }</span></code></pre></div>
<h4>Spread operator</h4>
<p><code class="hljs-text">ES2016</code>의 <code class="hljs-text">...</code>를 통해 객체를 변경을 피할 수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> newObj <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>obj<span class="token punctuation">,</span> z<span class="token punctuation">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { x: 1, y: 2 }</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>newObj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { x: 1, y: 2, z: 3 }</span></code></pre></div>
<h3>커링</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> <span class="token function-variable function">f</span> <span class="token operator">=</span> <span class="token parameter">a</span> <span class="token operator">=></span> <span class="token parameter">b</span> <span class="token operator">=></span> <span class="token parameter">c</span> <span class="token operator">=></span> <span class="token parameter">d</span> <span class="token operator">=></span> <span class="token parameter">e</span> <span class="token operator">=></span> a <span class="token operator">+</span> b <span class="token operator">+</span> c <span class="token operator">+</span> d <span class="token operator">+</span> e<span class="token punctuation">;</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>이 커링된 함수는 <code class="hljs-text">()</code>가 너무 많다. 이를 개선하기 위해 위에서 언급한 <code class="hljs-text">lodash</code>나 <code class="hljs-text">ramda</code>를 사용할 수 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> curry <span class="token operator">=</span> _<span class="token punctuation">.</span>curry <span class="token operator">||</span> <span class="token constant">R</span><span class="token punctuation">.</span>curry<span class="token punctuation">;</span>
<span class="token keyword">const</span> f <span class="token operator">=</span> <span class="token function">curry</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c<span class="token punctuation">,</span> d<span class="token punctuation">,</span> e</span><span class="token punctuation">)</span> <span class="token operator">=></span> a <span class="token operator">+</span> b <span class="token operator">+</span> c <span class="token operator">+</span> d <span class="token operator">+</span> e<span class="token punctuation">;</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 15</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 15</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 15</span>
<span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 15</span></code></pre></div>
<h3>합성함수</h3>
<p>합성함수 예제에서 <code class="hljs-text">const compose = (f, g) => x => f(g(x));</code>와 같이 함수를 합성했지만, <code class="hljs-text">ramda</code>의 <code class="hljs-text">compose</code>함수를 사용할 수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> composedFunction <span class="token operator">=</span> <span class="token constant">R</span><span class="token punctuation">.</span><span class="token function">compose</span><span class="token punctuation">(</span><span class="token parameter">x</span> <span class="token operator">=></span> x <span class="token operator">+</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token parameter">x</span> <span class="token operator">=></span> x <span class="token operator">*</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0">Master the JavaScript Interview: What is Functional Programming?</a></li>
<li><a href="https://www.airpair.com/javascript/posts/mastering-es6-higher-order-functions-for-arrays">Mastering ES6 higher-order functions for Arrays</a></li>
<li><a href="https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf">Why Functional Programming Matters</a></li>
<li><a href="http://2ality.com/2015/06/tail-call-optimization.html">Tail call optimization in ECMAScript 6</a></li>
</ul>
- <![CDATA[Async / Await]]>https://wonism.github.io/async-await/https://wonism.github.io/async-await/Sun, 03 Sep 2017 23:52:32 GMT<p><code class="hljs-text">ES2017(ECMA-262)</code>에서 새롭게 추가된 <code class="hljs-text">async/await</code>는 비동기 함수를 처리하기 위한 키워드이다.<br />
처음 제안된 것은 <a href="https://blogs.msdn.microsoft.com/typescript/2015/11/30/announcing-typescript-1-7/">TypeScript 1.7</a>였다.<br />
또한, <code class="hljs-text">async/await</code>는 <code class="hljs-text">Promise</code>위에 구축되었고, 기존의 모든 프로미스 기반 API와 호환되기 때문에 프로미스와 같이 사용하거나, 프로미스를 대체할 수 있다.<br />
비동기 동작을 위한 동기식 구문을 제공함으로써 코드 가독성을 높일 수 있으며, 에러 핸들링을 위해 <code class="hljs-text">try/catch</code>를 사용한다.</p>
<h2>시작하기 전에</h2>
<p><code class="hljs-text">async</code>와 <code class="hljs-text">await</code>는 키워드이므로 <code class="hljs-text">polyfill</code>이 없으며, 이전 브라우저를 지원하려면, <code class="hljs-text">babel</code> 등 트랜스파일러를 사용해야 한다.<br />
사용하는 브라우저가 <code class="hljs-text">async</code>, <code class="hljs-text">await</code>를 지원하는지 확인하려면, <a href="http://caniuse.com/">Can I use?</a>에서 해당 키워드를 검색하면 된다.</p>
<h2>예제 코드를 통해 async/await 살펴보기</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolve</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span>resolve<span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">asyncFunc</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> resolvedValue <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> resolvedValue <span class="token operator">+</span> <span class="token number">500</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">asyncFunc</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolvedValue</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 42</span>
<span class="token comment">// 542</span></code></pre></div>
<p><code class="hljs-text">async</code>키워드는 일반적인 함수를 자동으로 프로미스 형태로 만들며, <code class="hljs-text">async</code>함수를 호출하면 해당 함수가 무엇을 반환하든 <code class="hljs-text">resolve</code>된다. 또한, <code class="hljs-text">async</code> 함수는 <code class="hljs-text">await</code>의 사용을 가능하게 한다.<br />
<code class="hljs-text">await</code>키워드는 프로미스 객체와 작동하며, 함수의 호출 앞에 사용되면 프로미스가 해결될 때까지 코드 실행을 중단하게 한다. <code class="hljs-text">await</code>는 오직 <code class="hljs-text">async</code>함수와 사용될 수 있다.</p>
<p><code class="hljs-text">asyncFunc</code>를 일반 프로미스 스타일로 재작성하면, 다음과 같다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">asyncFunc</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolvedValue</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> resolvedValue <span class="token operator">+</span> <span class="token number">500</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>에러 핸들링</h2>
<p>프로미스는 해결(<code class="hljs-text">resolve</code>)될 수도 있고, 거절(<code class="hljs-text">reject</code>)될 수 있으며, 거절된다면 프로미스 객체의 <code class="hljs-text">Promise.prototype.catch</code>메소드를 통해 처리한다.<br />
<code class="hljs-text">async/await</code>의 경우에는 <code class="hljs-text">try { ... } catch { ... }</code>를 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span>reject<span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token string">'Error occured!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">asyncFunc</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> resolvedValue <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> resolvedValue <span class="token operator">+</span> <span class="token number">500</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token string">'Error occured when \'willBeAwaited\' is executed'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">asyncFunc</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolvedValue</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Error occured!</span>
<span class="token comment">// Error occured when 'willBeAwaited' is executed</span></code></pre></div>
<p>만약, <code class="hljs-text">async</code> 함수에서 거절된 프로미스를 반환하려면 <code class="hljs-text">throw</code>를 통해 에러를 던지면 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span>reject<span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token string">'Error occured!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">asyncFunc</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> resolvedValue <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">willBeAwaited</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> resolvedValue <span class="token operator">+</span> <span class="token number">500</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">asyncFunc</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">resolvedValue</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>resolvedValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Error occured!</span>
<span class="token comment">// Error occured!</span></code></pre></div>
<h2>async/await의 한계</h2>
<p><em>1. <code class="hljs-text">async</code>가 없이는 <code class="hljs-text">await</code>를 사용할 수 없다.</em></p>
<p>전역 스코프나 일반 함수 스코프 안에서 <code class="hljs-text">await</code>를 직접 사용할 수 없음을 의미한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">one</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// const num = await one();</span>
<span class="token comment">// can not be executed</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> num <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">one</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>num<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><em>2. <code class="hljs-text">Promise.all</code>과 같은 경우를 대체할 수 없다.</em></p>
<p>모든 비동기 호출이 끝날 때까지 기다려야 하는 경우, <code class="hljs-text">Promise.all</code>을 사용하는 것이 훨씬 좋다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token parameter">ms <span class="token operator">=</span> <span class="token number">0</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token parameter">resolve</span> <span class="token operator">=></span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">awaitAyncFunctions</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> start <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">await</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> end <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`execution time is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Math<span class="token punctuation">.</span><span class="token function">round</span><span class="token punctuation">(</span><span class="token punctuation">(</span>end <span class="token operator">-</span> start<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">seconds.`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// execution time is 6seconds.</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">awaitAyncFunctions</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> start <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> results <span class="token operator">=</span> <span class="token keyword">await</span>
Promise<span class="token punctuation">.</span><span class="token function">all</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> end <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token string">`execution time is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>Math<span class="token punctuation">.</span><span class="token function">round</span><span class="token punctuation">(</span><span class="token punctuation">(</span>end <span class="token operator">-</span> start<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">seconds.`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// execution time is 3seconds.</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function">MDN : async</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await">MDN : await</a></li>
</ul>
- <![CDATA[Function 객체의 apply, bind, call]]>https://wonism.github.io/apply-bind-call/https://wonism.github.io/apply-bind-call/Mon, 28 Aug 2017 20:49:39 GMT<p><code class="hljs-text">.apply()</code>, <code class="hljs-text">.bind()</code>, <code class="hljs-text">.call()</code>는 일급 객체인 <code class="hljs-text">Function</code>의 메소드로 함수의 <code class="hljs-text">this</code>를 바꿔준다. (즉, 이 메소드들을 통해 호출된 함수의 스코프를 변경하는 것과 같다.)</p>
<h2>apply</h2>
<p><code class="hljs-text">.apply()</code> 메소드는 주어진 <code class="hljs-text">this</code>값과 <code class="hljs-text">arguments</code>혹은 <code class="hljs-text">array</code>로 함수를 호출한다. (<code class="hljs-text">arguments</code>는 유사배열 객체로 <code class="hljs-text">.length</code>등의 <code class="hljs-text">property</code>가 있다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">personContainer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> person <span class="token operator">=</span> <span class="token punctuation">{</span>
personName<span class="token punctuation">:</span> <span class="token string">'Jaewon'</span><span class="token punctuation">,</span>
<span class="token function-variable function">say</span><span class="token punctuation">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span><span class="token punctuation">.</span>personName <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> says </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> arguments<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
person<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>person<span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// arguments[0] : Hi, arguments[1] : Hello</span>
<span class="token punctuation">}</span>
<span class="token function">personContainer</span><span class="token punctuation">(</span><span class="token string">'Hi'</span><span class="token punctuation">,</span> <span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Jaewon says Hello</span></code></pre></div>
<h2>call</h2>
<p><code class="hljs-text">.apply()</code>와 유사하지만, <code class="hljs-text">.call()</code> 은 (유사)배열 대신, 값들을 하나하나 전달하여 함수를 호출한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> john <span class="token operator">=</span> <span class="token punctuation">{</span>
personName<span class="token punctuation">:</span> <span class="token string">'John'</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> person <span class="token operator">=</span> <span class="token punctuation">{</span>
personName<span class="token punctuation">:</span> <span class="token string">'Jaewon'</span><span class="token punctuation">,</span>
<span class="token function-variable function">say</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>personName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> says </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> str <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
person<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>john<span class="token punctuation">,</span> <span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 'John says Hello.'</span>
person<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>person<span class="token punctuation">,</span> <span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 'Jaewon says Hello.'</span></code></pre></div>
<h2>bind</h2>
<p><code class="hljs-text">.bind()</code>는 호출될 때 인자로 전달된 객체를 <code class="hljs-text">this</code>로 하는 함수를 반환한다. 즉, 함수가 가리키는 <code class="hljs-text">this</code>를 바꾼다고 봐도 된다.<br />
(함수 안에서 <code class="hljs-text">this</code>는 해당 함수를 호출한 객체이다.)</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> num<span class="token punctuation">:</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>num <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">power</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>num <span class="token operator">**</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">power</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1764</span>
<span class="token function">power</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 25</span></code></pre></div>
<p>아래 예제에서는 객체의 메소드를 일반 함수로 추출한 뒤, 이 함수의 실행 컨텍스트를 알아볼 수 있는 코드다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> person <span class="token operator">=</span> <span class="token punctuation">{</span>
personName<span class="token punctuation">:</span> <span class="token string">'Jaewon'</span><span class="token punctuation">,</span>
<span class="token function-variable function">say</span><span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">str</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> <span class="token keyword">this</span><span class="token punctuation">.</span>personName<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>personName<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token keyword">this</span><span class="token punctuation">.</span>personName <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> says </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> str <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> func <span class="token operator">=</span> person<span class="token punctuation">.</span>say<span class="token punctuation">;</span>
<span class="token function">func</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 'undefined says Hello'</span>
<span class="token comment">// 'undefined' undefined window</span>
<span class="token keyword">const</span> func2 <span class="token operator">=</span> person<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>person<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">func2</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 'Jaewon says Hello'</span>
<span class="token comment">// 'string' Jaewon { personName: 'Jaewon', say: function }</span></code></pre></div>
<p><code class="hljs-text">func</code>의 <code class="hljs-text">this</code>는 <code class="hljs-text">window</code>이기 때문에 <code class="hljs-text">this.personName</code>은 <code class="hljs-text">undefined</code>이다.</p>
<h2>참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">MDN : apply</a></li>
<li><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/call">MDN : call</a></li>
<li><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">MDN : bind</a></li>
</ul>
- <![CDATA[자바스크립트 클로저]]>https://wonism.github.io/closure/https://wonism.github.io/closure/Mon, 28 Aug 2017 01:21:39 GMT<p>클로저는 다른 함수의 스코프 안에 있는 변수들에 접근할 수 있는 함수를 뜻한다.</p>
<h2>특징</h2>
<ul>
<li>클로저는 lexical scope로 인해 독립적인 변수를 가리키는 함수로, 클로저 안에 정의된 함수는 만들어진 환경(lexical environment) 를 기억한다.</li>
<li>클로저는 자신의 스코프에 정의된 변수, 외부 함수의 변수, 전역 변수에 대한 접근으로 구분된다.</li>
<li>클로저를 통해 함수 내의 지역 변수를 감출 수 있다. (private 와 비슷한 역할)</li>
<li>함수 안에 함수를 만드는 것은 처리 속도와 메모리 사용량에 좋지 않다.</li>
</ul>
<h2>간단한 사용 예제</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">statefulFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> number <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">param</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
number <span class="token operator">+=</span> param<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>number<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> closure <span class="token operator">=</span> <span class="token function">statefulFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">closure</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 11</span>
<span class="token function">closure</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 21</span></code></pre></div>
<p>예제를 보면 알 수 있듯이, <code class="hljs-text">closure(parameter);</code> 로 함수 <code class="hljs-text">closure</code>를 호출하면, 내부 변수 <code class="hljs-text">number</code> 가 매 호출마다 다시 생성되지 않고 상태를 유지시키며 참조된다.
클로저의 참조를 제거하려면 명시적으로 <code class="hljs-text">null</code>을 대입한다. (e.g. <code class="hljs-text">closure = null;</code>)</p>
<h2>클로저와 클로저가 아닌 함수의 예</h2>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* Not a closure */</span>
<span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token parameter">param1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> local <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token parameter">param2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
local <span class="token operator">+=</span> <span class="token punctuation">(</span>param1 <span class="token operator">+</span> param2<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>local<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">foo</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 152</span>
<span class="token function">foo</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 152</span>
<span class="token function">foo</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 152</span></code></pre></div>
<p><code class="hljs-text">bar</code>함수는 <code class="hljs-text">foo</code>안에 속하기 때문에 <code class="hljs-text">foo</code>스코프를 외부 스코프 참조로 저장한다. 또, <code class="hljs-text">bar</code>함수는 자신의 렉시컬 스코프 체인을 통해 <code class="hljs-text">local</code>을 참조한다. 하지만, <code class="hljs-text">bar</code>은 <code class="hljs-text">foo</code>안에서 정의 및 실행을 하기만 할뿐, 바깥으로 나오지 않으므로 클로저 라고 부르지 않는다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">/* Closure */</span>
<span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token parameter">param1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> local <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">bar</span><span class="token punctuation">(</span><span class="token parameter">param2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
local <span class="token operator">+=</span> <span class="token punctuation">(</span>param1 <span class="token operator">+</span> param2<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>local<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> bar<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> bar <span class="token operator">=</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 57</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 72</span>
<span class="token function">bar</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 87</span>
<span class="token keyword">const</span> baz <span class="token operator">=</span> <span class="token function">foo</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">baz</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 57</span>
<span class="token function">baz</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 72</span>
<span class="token function">baz</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 87</span></code></pre></div>
<p>반면, <code class="hljs-text">const</code>로 선언된 변수 <code class="hljs-text">bar</code>는 <code class="hljs-text">foo</code>내부의 <code class="hljs-text">bar</code>를 가져오며, <code class="hljs-text">bar</code>(param) 로써 외부에서 호출된다.
또한, <code class="hljs-text">bar</code>, <code class="hljs-text">baz</code>두 가지 변수에 외부함수의 리턴을 대입한 결과를 보면, 또 다른 클로저가 생성되면서 <code class="hljs-text">bar</code>와 <code class="hljs-text">baz</code>의 상태는 서로 다르다는 것을 알 수 있다.</p>
<h3>for loop 와 closure</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>위 코드의 예상 결과로 <code class="hljs-text">1, 2, 3, ..., 9</code> 를 생각할 수 있다. 하지만, 실제 실행 결과는 <code class="hljs-text">10, 10, 10, ..., 10</code>이다. 반복문 안에 있는 함수는 상위 스코프인 <code class="hljs-text">count</code>함수의 영역에서 <code class="hljs-text">i</code>를 찾는다.<br />
그런데 이때, 이 익명 함수는 호출 스택에 쌓여있다가, loop 를 다 돌고 난 뒤에 실행된다. 따라서, <code class="hljs-text">10</code>이 되어버린 <code class="hljs-text">i</code>를 출력하게 된다.<br />
(<code class="hljs-text">setTimeout</code>바로 위에 <code class="hljs-text">console.log(i);</code> 라인을 추가하여 확인해보면 더 쉽게 알 수 있다.)<br />
이 코드를 정상적으로 수행하게 하기 위해서는 즉시 실행 함수 안에서 <code class="hljs-text">setTimeout</code>를 사용하는 방법 과 블록 스코프를 사용하는 방법 이 있다.</p>
<p><strong>즉시 실행 함수 사용</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">cnt</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>cnt<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">for</code>루프 안에서 실행된 즉시실행함수는 i 를 매개변수로 호출된다.<br />
<code class="hljs-text">setTimeout</code>안에 있는 익명함수는 매개 변수 <code class="hljs-text">cnt</code>즉, <code class="hljs-text">i</code>를 출력하게 되며, 비로소 원하는 결과인 <code class="hljs-text">1, 2, 3, ..., 9</code> 를 출력하게 되는 것이다.</p>
<p><strong>블록 스코프 사용</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">count</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">var</code>로 선언된 <code class="hljs-text">i</code>를 <code class="hljs-text">let</code>키워드로 선언해주면 해결된다. <code class="hljs-text">let</code>은 함수 스코프가 아닌 블록 스코프를 사용하기 때문이다.</p>
<p><strong>번외 : 다른 방식(callback)으로 구현해보기</strong></p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">function</span> <span class="token function">count</span><span class="token punctuation">(</span><span class="token parameter">i</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator"><=</span> <span class="token number">9</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">count</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">count</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>참고</h2>
<ul>
<li><a href="http://meetup.toast.com/posts/86">NHN Ent. 기술 블로그 : 자바스크립트의 스코프와 클로저</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures">MDN : 클로저</a></li>
</ul>
- <![CDATA[bind 메소드 간단하게 구현하기]]>https://wonism.github.io/implement-bind/https://wonism.github.io/implement-bind/Sun, 27 Aug 2017 02:28:39 GMT<h2>bind란?</h2>
<p><code class="hljs-text">.bind()</code>는 호출될 때 인자로 전달된 객체를 <code class="hljs-text">this</code>로 하는 함수를 반환하며, 다음과 같이 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>num<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token punctuation">{</span> num<span class="token punctuation">:</span> <span class="token number">42</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<h2>뼈대</h2>
<p><code class="hljs-text">Function.prototype.bind()</code>는 인자로 넘겨받은 객체를 <code class="hljs-text">this</code>로 하는 함수를 반환한다.<br />
즉, 함수를 리턴하게 된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token class-name">Function</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">bindImplementation</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">/* ... */</span>
<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<h2>실제 구현</h2>
<p><code class="hljs-text">Function.prototype.bind()</code>는 어떤 함수가 가리키는 <code class="hljs-text">this</code>를 원하는 객체로 변환한다.<br />
즉, 어떤 함수를 실행할 때, 이 함수의 <code class="hljs-text">this</code>를 원하는 객체로 변환하기 위해 <code class="hljs-text">apply</code>메소드를 사용하며, 첫 번째 인자로 <code class="hljs-text">bind</code>의 인자를 전달해준다.<br />
이 때, 인자가 넘어오지 않으면 해당 함수의 <code class="hljs-text">this</code>를 사용한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token class-name">Function</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">bind</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> that <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">that</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>이를 ES2015 문법으로 구현하면, 더 간단하다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token class-name">Function</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">bind</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
- <![CDATA[let과 const는 호이스팅 될까?]]>https://wonism.github.io/is-let-hoisted/https://wonism.github.io/is-let-hoisted/Sat, 26 Aug 2017 23:24:08 GMT<p><code class="hljs-text">let</code> 또는 <code class="hljs-text">const</code>가 호이스팅 되는지 여부를 알아보기 전에 <code class="hljs-text">호이스팅</code>과 <code class="hljs-text">Temporal Dead Zone(TDZ)</code>이란 개념에 대해 알아보겠다.</p>
<h2>Hoisting</h2>
<p><code class="hljs-text">let</code> 또는 <code class="hljs-text">const</code>가 호이스팅 되는지 여부를 알아보기 전에 <code class="hljs-text">호이스팅</code>과 <code class="hljs-text">Temporal Dead Zone(TDZ)</code>이란 개념에 대해 알아보겠다.<br />
호이스팅은 말 그대로 끌어올려진다는 의미를 가진다. 스코프 안의 어디에서든 변수 선언은 최상위에서 선언된 것과 동등하다.<br />
아래 예제에서 출력되는 <code class="hljs-text">x</code>는 <code class="hljs-text">outer scope</code>가 아닌 <code class="hljs-text">undefined</code>이다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token string">'outer scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// undefined</span>
<span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token string">'inner scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>스코프 안에서 선언된 변수는 항상 최상위에 선언한 것과 동등한 의미를 가지기 때문이다.
즉, 위 코드는 아래와 같은 의미를 지닌다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">var</span> x <span class="token operator">=</span> <span class="token string">'outer scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> x<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// undefined</span>
x <span class="token operator">=</span> <span class="token string">'inner scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>여기서 끝나는 것이 아니다. 변수가 선언되기 전에 변수를 사용할 수도 있다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">foo <span class="token operator">=</span> <span class="token string">'bar'</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> foo<span class="token punctuation">;</span>
<span class="token comment">// 위는 아래와 같은 의미를 가진다.</span>
<span class="token keyword">var</span> foo<span class="token punctuation">;</span>
foo <span class="token operator">=</span> <span class="token string">'bar'</span><span class="token punctuation">;</span></code></pre></div>
<h2>Temporal Dead Zone</h2>
<h3>var와 let/const의 비교로 보는 TDZ</h3>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// throws a ReferenceError</span>
<span class="token keyword">const</span> x <span class="token operator">=</span> <span class="token string">'hey'</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">var</code>와 <code class="hljs-text">let/const</code>선언에 대한 범위의 차이 중 하나는 <code class="hljs-text">let/const</code>가 <code class="hljs-text">TDZ</code>에 의해 제약을 받는다는 것이다.<br />
즉, 변수가 초기화되기 전에 액세스하려고 하면, <code class="hljs-text">var</code>처럼 <code class="hljs-text">undefined</code>를 반환하지 않고, <code class="hljs-text">ReferenceError</code>가 발생한다.
이는 코드를 예측가능하고 잠재적 버그를 쉽게 찾아낼 수 있도록 한다.</p>
<p>위 예제를 보면, <code class="hljs-text">let/const</code>선언은 호이스팅을 수행하지 않는다고 생각할 수 있다.<br />
하지만 이는 잘못된 것이며, Hoisting에 관한 예제 코드에서 <code class="hljs-text">var</code>를 <code class="hljs-text">const</code>으로 바꾸면, 어떤 일이 발생하는지 살펴본다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> x <span class="token operator">=</span> <span class="token string">'outer scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> x <span class="token operator">=</span> <span class="token string">'inner scope'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p><code class="hljs-text">console.log(x);</code>는 TDZ에 의해 <code class="hljs-text">ReferenceError</code>를 발생하게 된다.<br />
이는, <code class="hljs-text">let/const</code> 선언은 호이스팅을 수행하기 때문이다.<br />
<code class="hljs-text">undefined</code>를 반환하는 <code class="hljs-text">var</code>와는 달리, 초기화되기 전에 액세스할 때 에러가 발생한다.</p>
<h3>TDZ 살펴보기</h3>
<p><code class="hljs-text">let/const</code>선언은 실행중인 실행 컨텍스트의 <code class="hljs-text">어휘적 환경(Lexical Environment)</code>으로 범위가 지정된 변수를 정의한다.<br />
변수는 그들의 어휘적 환경에 포함될 때 생성되지만, 어휘적 바인딩이 실행되기 전까지는 액세스할 수 없다.<br />
새로운 범위에 진입할 때마다 지정된 범위에 속한 모든 <code class="hljs-text">let/const</code>바인딩이 지정된 범위 내부의 코드가 실행되기 전에 실행된다. (즉, <code class="hljs-text">let/const</code>선언이 호이스팅된다.)<br />
어휘적 바인딩이 실행되기 전까지 액세스할 수 없는 현상을 <code class="hljs-text">TDZ</code>라고 한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token comment">// const x를 실행하기 전에 x에 접근하면, TDZ에 의해 ReferenceError가</span>
발생하게 된다<span class="token punctuation">.</span>
<span class="token comment">// console.log(x);</span>
<span class="token keyword">const</span> x <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span>
<span class="token comment">// 위 코드 실행 이후에는 x에 접근할 수 있다.</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>
<p>어휘적 바인딩에 의해 초기화되며 정의된 변수는 변수가 만들어질 때가 아닌, 값이 해당 초기화 구문 어휘적 바인딩이 실행될 때 값을 할당받는다.<br />
<code class="hljs-text">let/const</code>선언의 어휘적 바인딩에 초기화 구문이 없으면, 어휘적 바인딩을 실행할 때, 변수에 <code class="hljs-text">undefined</code>가 할당된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">let</span> x<span class="token punctuation">;</span> <span class="token comment">// 이는 let x = undefined; 와 같다.</span>
<span class="token comment">// const 키워드는 반드시 선언과 동시에 값을 할당해야 한다.</span>
<span class="token comment">// const x; Uncaught SyntaxError: Missing initializer in const declaration</span></code></pre></div>
<p><code class="hljs-text">let/const</code>변수는 초기화 구문이 완전히 실행된 이후에 우변이 실행되고 그 결과 값이 선언된 변수에 할당된 후 초기화된다.
우변에서 <code class="hljs-text">let/const</code>로 선언된 변수를 사용하는 경우, 우변은 변수를 읽으려고 시도하지만 초기화 구문이 아직 완전히 실행되지 않은 상태이므로, <code class="hljs-text">ReferenceError</code>가 발생한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> x <span class="token operator">=</span> x<span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span></code></pre></div>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span>
<span class="token keyword">const</span> b <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> b<span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre></div>
<p><code class="hljs-text">디폴트 파라미터(Default Parameters)</code>에서도 <code class="hljs-text">TDZ</code>가 적용되는데, 디폴트 파라미터는 주어진 함수의 해당 범위와 내부 범위 사이에 있는 중간 범위에서 실행된다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b <span class="token operator">=</span> a</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
a <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
b <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">undefined</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 디폴트 파라미터는 왼쪽에서 오른쪽으로 실행되며, a의 초기화 구문이 b를 읽을 때, b는 TDZ에 있다.</span>
<span class="token comment">// 따라서, ReferenceError가 발생한다.</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">a <span class="token operator">=</span> b<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span>
<span class="token comment">// a는 a의 초기화구문이 a를 읽으려고 할 때, TDZ에 있으므로, ReferenceError가 발생한다.</span>
<span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">a <span class="token operator">=</span> a</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ReferenceError</span></code></pre></div>
<p><code class="hljs-text">class</code>에서도 <code class="hljs-text">TDZ</code>가 적용된다. 상위 생성자를 호출하기 전에 <code class="hljs-text">this</code>에 액세스하려고 하는 하위 클래스의 생성자는 <code class="hljs-text">ReferenceError</code>를 발생시킨다.
하위 클래스의 생성자가 <code class="hljs-text">super();</code>를 호출하지 않는 한, <code class="hljs-text">this</code> 바인딩은 초기화되지 않은 것으로 간주된다.
하위 클래스 생성자에 <code class="hljs-text">super();</code>가 없으면, 생성자는 암시적으로 <code class="hljs-text">return this;</code>를 시도한다.</p>
<div class="gatsby-highlight" data-language="js"><pre class="hljs-js"><code class="hljs-js"><span class="token keyword">class</span> <span class="token class-name">A</span> <span class="token keyword">extends</span> <span class="token class-name">B</span> <span class="token punctuation">{</span> <span class="token comment">// ReferenceError</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">B</span> <span class="token punctuation">{</span>
<span class="token comment">/* ... */</span>
<span class="token punctuation">}</span></code></pre></div>
<p><code class="hljs-text">TDZ</code>는 초기화되지 않은 바인딩에 액세스하려는 경우, 예기치 않은 결과를 내는 대신에 개발자에게 에러 피드백을 제공하기 때문에 유용하게 사용된다.</p>
<h2>결론</h2>
<p><code class="hljs-text">let/const</code>선언 변수는 호이스팅되지 않는 것이 아니다.
스코프에 진입할 때 변수가 만들어지고 TDZ(Temporal Dead Zone)가 생성되지만, 코드 실행이 변수가 실제 있는 위치에 도달할 때까지 액세스할 수 없는 것이다.
<code class="hljs-text">let/const</code>변수가 선언된 시점에서 제어흐름은 <code class="hljs-text">TDZ</code>를 떠난 상태가 되며, 변수를 사용할 수 있게 된다.</p>
<h2>참고</h2>
<ul>
<li><a href="http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified">JS ROCKS : TEMPORAL DEAD ZONE (TDZ) DEMYSTIFIED</a></li>
<li><a href="https://tc39.github.io/ecma262/#sec-let-and-const-declarations">TC39 Github pages : Section 13.3</a></li>
<li><a href="https://dzone.com/articles/learning-es6-using-let-const-and-temporal-dead-zon">DZone : Learning ES6: Using let, const, and Temporal Dead Zone</a></li>
<li><a href="https://ponyfoo.com/articles/es6-let-const-and-temporal-dead-zone-in-depth">Pony Foo : ES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth</a></li>
</ul>
- <![CDATA[Korbit]]>https://wonism.github.io/portfolios/korbit/https://wonism.github.io/portfolios/korbit/Mon, 01 May 2017 00:00:00 GMT<h1>Korbit</h1>
<h2>Period</h2>
<ul>
<li><code class="hljs-text">2017. 05. ~ Current</code></li>
</ul>
<h2>What I did</h2>
<ul>
<li>Develop new landing page</li>
<li>Introduce Reselect to improve performance</li>
<li>Write test codes with Jest</li>
</ul>
<h2>Libraries / Tools</h2>
<ul>
<li>ReactJS</li>
<li>Redux (for managing state)</li>
<li>Reselect (to improve performance)</li>
<li>Jest (for test)</li>
</ul>
<p><a href="https://korbit.co.kr">Go to Web Site →</a></p>
- <![CDATA[Camscon]]>https://wonism.github.io/portfolios/camscon/https://wonism.github.io/portfolios/camscon/Thu, 01 Sep 2016 00:00:00 GMT<h1>Camscon</h1>
<h2>Period</h2>
<ul>
<li><code class="hljs-text">2016. 09. ~ 2017. 03.</code></li>
</ul>
<h2>What I did</h2>
<ul>
<li>Develop Camscon web page with ReactJS</li>
<li>Develop feature that upload images and its pin tags, color informations</li>
</ul>
<h2>Libraries / Tools</h2>
<ul>
<li>ReactJS</li>
<li>webpack</li>
</ul>
<p><a href="https://camscon.kr">Go to Web Site →</a></p>
- <![CDATA[Ciceron]]>https://wonism.github.io/portfolios/ciceron/https://wonism.github.io/portfolios/ciceron/Sun, 01 May 2016 00:00:00 GMT<h1>Ciceron</h1>
<h2>Period</h2>
<ul>
<li><code class="hljs-text">2016. 05. ~ 2016. 05.</code></li>
</ul>
<h2>What I did</h2>
<ul>
<li>Develop translation editor & memo editor via contenteditable API</li>
</ul>
<h2>Libraries / Tools</h2>
<ul>
<li>jQuery</li>
<li>gulp</li>
<li>contenteditable API</li>
</ul>
<p><a href="http://ciceron.me">Go to Web Site →</a></p>
- <![CDATA[Goodoc]]>https://wonism.github.io/portfolios/goodoc/https://wonism.github.io/portfolios/goodoc/Mon, 01 Dec 2014 00:00:00 GMT<h1>Goodoc</h1>
<h2>Period</h2>
<ul>
<li><code class="hljs-text">2014. 12. ~ 2015. 12.</code></li>
</ul>
<h2>What I did</h2>
<ul>
<li>Changing main page UI</li>
<li>UI that Finding hospitals based on map</li>
<li>Goodoc cast platform</li>
</ul>
<h2>Frameworks / Libraries</h2>
<ul>
<li>ChartJS</li>
<li>Google Maps API</li>
<li>Google Analytics</li>
<li>jQuery</li>
<li>Bootstrap 3</li>
<li>Rails</li>
</ul>
<p><a href="http://www.goodoc.co.kr">Go to Web Site →</a></p>
- <![CDATA[Resume]]>https://wonism.github.io/resume/https://wonism.github.io/resume/Mon, 05 Feb 1990 00:00:00 GMT<h2>Experience</h2>
<ul>
<li>
<p>Front-end Engineer at Korbit ∙ 2017. 05 ~ Present</p>
<ul>
<li>Web application for Crypto currency exchange with ReactJS and redux</li>
</ul>
</li>
<li>
<p>Front-end Engineer at Yeastudio ∙ 2015. 12 ~ 2016. 11</p>
<ul>
<li>Admin pages of Junimong</li>
<li>Admin pages of Colorfil</li>
<li>Migrate framework to Spring Boot from JSON-RPC</li>
</ul>
</li>
<li>
<p>Front-end Engineer at Goodoc ∙ 2014. 12 ~ 2015. 12</p>
<ul>
<li>Web application for Goodoc</li>
<li>Adimin pages of Goodoc</li>
<li>Client pages of Goodoc</li>
<li>Internationalization for Japan</li>
</ul>
</li>
</ul>
<h2>Education</h2>
<ul>
<li>B.S. in Computer Science Engineering at Seoul Tech ∙ 2008. 03 ~ 2015. 02</li>
</ul>
<h2>Projects</h2>
<ul>
<li>
<p>Korbit (<a href="https://korbit.co.kr">https://korbit.co.kr</a>) ∙ 2017. 05 ~ Present</p>
<ul>
<li>Maintain and Develop new features</li>
<li>Remove jQuery and use ReactJS</li>
<li>Introduce Redux and Reselect for managing states</li>
<li>Develop new landing page</li>
<li>Develop process of Enhanced Due Diligence</li>
<li>Develop test codes with Jest</li>
</ul>
</li>
<li>
<p>Camscon (<a href="https://camscon.kr">https://camscon.kr</a>) ∙ 2016. 09 ~ 2017. 02</p>
<ul>
<li>Develop Camscon web page with ReactJS</li>
<li>Develop feature that upload images and its pin tags, color informations</li>
</ul>
</li>
<li>
<p>Ciceron (<a href="http://ciceron.me">http://ciceron.me</a>) ∙ 2016. 05 ~ 2016. 05</p>
<ul>
<li>Develop text editor and memo with contenteditable API</li>
</ul>
</li>
<li>
<p>Yeastudio (no link) ∙ 2015. 12 ~ 2016. 11</p>
<ul>
<li>Develop admin pages of Junimong</li>
<li>Develop admin pages of Colorfil</li>
<li>Migrate framework to Spring Boot from JSON-RPC</li>
</ul>
</li>
<li>
<p>Goodoc (<a href="http://www.goodoc.co.kr">http://www.goodoc.co.kr</a>) ∙ 2014. 12 ~ 2015. 12</p>
<ul>
<li>Use Google maps API for menu that search hospitals</li>
<li>Develop Content platform called Goodoc cast</li>
<li>Do Internationalization work for Japan</li>
<li>Develop client/admin web page</li>
<li>Develop chart for measuring marketing performance ratio using ChartJS</li>
</ul>
</li>
<li>
<p>Open sources</p>
<ul>
<li>gatsby-advanced-blog (<a href="https://github.com/wonism/gatsby-advanced-blog">https://github.com/wonism/gatsby-advanced-blog</a>)</li>
<li>reacteum (<a href="https://github.com/wonism/reacteum">https://github.com/wonism/reacteum</a>)</li>
<li>redux-segment-node (<a href="https://github.com/wonism/redux-segment-node">https://github.com/wonism/redux-segment-node</a>)</li>
<li>react-google-ads (<a href="https://github.com/wonism/react-google-ads">https://github.com/wonism/react-google-ads</a>)</li>
<li>react-kakao-login (<a href="https://github.com/wonism/react-kakao-login">https://github.com/wonism/react-kakao-login</a>)</li>
<li>react-github-info (<a href="https://github.com/wonism/react-github-info">https://github.com/wonism/react-github-info</a>)</li>
<li>react-d3-pie-chart (<a href="https://github.com/wonism/react-d3-pie-chart">https://github.com/wonism/react-d3-pie-chart</a>)</li>
<li>@wonism/react-retina-image (<a href="https://github.com/wonism/react-retina-image">https://github.com/wonism/react-retina-image</a>)</li>
<li>@wonism/react-dropdown (<a href="https://github.com/wonism/react-dropdown">https://github.com/wonism/react-dropdown</a>)</li>
<li>easy-map (<a href="https://github.com/wonism/easy-map">https://github.com/wonism/easy-map</a>)</li>
</ul>
</li>
<li>
<p>Chrome extensions</p>
<ul>
<li>Image downloader (<a href="https://github.com/wonism/image-downloader">https://github.com/wonism/image-downloader</a>)</li>
<li>Special characters finder (<a href="https://github.com/wonism/special-characters-finder">https://github.com/wonism/special-characters-finder</a>)</li>
</ul>
</li>
<li>
<p>Today I learned</p>
<ul>
<li><a href="https://github.com/wonism/til">https://github.com/wonism/til</a></li>
</ul>
</li>
</ul>
<h2>Skills</h2>
<ul>
<li>
<p>JavaScript</p>
<ul>
<li>ES2015+</li>
<li>ReactJS</li>
<li>Redux</li>
<li>Lodash</li>
<li>jQuery</li>
<li>D3</li>
</ul>
</li>
<li>
<p>CSS</p>
<ul>
<li>SCSS</li>
<li>Less</li>
</ul>
</li>
</ul>
<h2>Tools</h2>
<ul>
<li>Webpack</li>
<li>Gulp</li>
</ul>