<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jo_cw.log</title>
        <link>https://velog.io/</link>
        <description>개발자로 발돋움</description>
        <lastBuildDate>Tue, 09 May 2023 09:46:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. jo_cw.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jo_cw" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[풍선 터뜨리기]]></title>
            <link>https://velog.io/@jo_cw/%ED%92%8D%EC%84%A0-%ED%84%B0%EB%9C%A8%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@jo_cw/%ED%92%8D%EC%84%A0-%ED%84%B0%EB%9C%A8%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Tue, 09 May 2023 09:46:15 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/68646">https://school.programmers.co.kr/learn/courses/30/lessons/68646</a></p>
<h4 id="문제-설명">문제 설명</h4>
<p>일렬로 나열된 n개의 풍선이 있습니다. 모든 풍선에는 서로 다른 숫자가 써져 있습니다. 당신은 다음 과정을 반복하면서 풍선들을 단 1개만 남을 때까지 계속 터트리려고 합니다.</p>
<p>임의의 인접한 두 풍선을 고른 뒤, 두 풍선 중 하나를 터트립니다.
터진 풍선으로 인해 풍선들 사이에 빈 공간이 생겼다면, 빈 공간이 없도록 풍선들을 중앙으로 밀착시킵니다.
여기서 조건이 있습니다. 인접한 두 풍선 중에서 번호가 더 작은 풍선을 터트리는 행위는 최대 1번만 할 수 있습니다. 즉, 어떤 시점에서 인접한 두 풍선 중 번호가 더 작은 풍선을 터트렸다면, 그 이후에는 인접한 두 풍선을 고른 뒤 번호가 더 큰 풍선만을 터트릴 수 있습니다.</p>
<p>당신은 어떤 풍선이 최후까지 남을 수 있는지 알아보고 싶습니다. 위에 서술된 조건대로 풍선을 터트리다 보면, 어떤 풍선은 최후까지 남을 수도 있지만, 어떤 풍선은 무슨 수를 쓰더라도 마지막까지 남기는 것이 불가능할 수도 있습니다.</p>
<p>일렬로 나열된 풍선들의 번호가 담긴 배열 a가 주어집니다. 위에 서술된 규칙대로 풍선들을 1개만 남을 때까지 터트렸을 때 최후까지 남기는 것이 가능한 풍선들의 개수를 return 하도록 solution 함수를 완성해주세요.</p>
<h4 id="제한-사항">제한 사항</h4>
<ul>
<li>a의 길이는 1 이상 1,000,000 이하입니다.<ul>
<li>a[i]는 i+1 번째 풍선에 써진 숫자를 의미합니다.</li>
<li>a의 모든 수는 -1,000,000,000 이상 1,000,000,000 이하인 정수입니다.</li>
<li>a의 모든 수는 서로 다릅니다.</li>
</ul>
</li>
</ul>
<h3 id="접근">접근</h3>
<h4 id="너무-큰-배열">너무 큰 배열</h4>
<p>배열의 길이가 1,000,000로 아주 커서 BFS나 DFS를 사용하면 시간 제한은 물론 재귀의 한계에 도달하거나 큐의 크기가 너무 커져 공간이 부족할 것이라고 생각했다. 따라서 완전 탐색은 시작부터 포기하고 DP에 이용할 수 있는 규칙이 있는지 찾아봤다.</p>
<h4 id="한-번뿐인-기회">한 번뿐인 기회</h4>
<blockquote>
<p>인접한 두 풍선 중에서 번호가 더 작은 풍선을 터트리는 행위는 최대 1번만 할 수 있습니다.</p>
</blockquote>
<p>이 문장에 집중해서 답이 될 수 있는 후보를 고민해봤다. 
이 기회를 사용하지 않는다면 결국 이 배열 안에서 가장 작은 숫자만이 남을 것이다. 그렇다면 최솟값이 아닌 다른 숫자를 남기기 위해서는 이 최솟값과 만났을 때 이 기회를 사용해야 한다. 그렇다면 최솟값과 단 둘이 남기 위한 조건은 무엇인가?</p>
<h3 id="결론">결론</h3>
<p>최솟값의 양 옆의 숫자는 언제든지 규칙에 따라 제거할 수 있다. 따라서 모든 풍선들은 최솟값의 옆에 오도록 풍선을 터뜨릴 수 있다. 따라서 어떤 풍선이 최솟값과 단 둘이 남기 위해서는 최솟값을 기준으로 반대편의 풍선을 모두 터뜨릴 수 있는지 확인하면 된다.</p>
<ul>
<li>남길 풍선을 기준으로최솟값이 왼쪽에 있고 자신의 오른쪽에 자신보다 더 작은 수가 없는 경우</li>
<li>남길 풍선을 기준으로최솟값이 오른쪽에 있고 자신의 왼쪽에 자신보다 더 작은 수가 없는 경우</li>
</ul>
<p>위에 해당하는 풍선의 개수를 구하면 답을 찾을 수 있었다.</p>
<h4 id="예시">예시</h4>
<p><code>[-16,27,65,-2,58,-92,-71,-68,-61,-33]</code>
다음과 같은 배열이 주어졌을 때, 최솟값은 <code>-92</code>이다.
<code>-16</code>은 마지막에 남는 것이 가능하다. <code>-16</code>과 <code>-92</code> 사이에 있는 숫자는 모두 <code>-92</code>와 비교하여 터뜨릴 수 있다. <code>-92</code> 오른쪽에 있는 숫자 또한 마찬가지다.</p>
<p>하지만 <code>-2</code>는 불가능하다. <code>27</code> <code>65</code>와 비교해서 터뜨리는 것이 가능하지만 <code>-16</code>을 터뜨릴 방법이 없다.</p>
<h3 id="구현">구현</h3>
<h4 id="첫-시도">첫 시도</h4>
<p>처음에는 2중 for문을 사용해서 확인했다.</p>
<pre><code class="language-js">let answer = 1;
let min = Infinity;
let min_index = -1;
for (let i = 0; i &lt; a.length; i ++) {
  if (min &lt; a[i]) continue;
  min = a[i];
  min_index = i;
}
for (let i = 0; i &lt; min_index; i++) {
  let result = 1;
  for(let j = 0; j &lt; i; j++) {
    if (a[i] &gt; a[j]) {
      result = 0;
      break;
    }
  }
  answer += result;
}
//이하 생략</code></pre>
<p>하지만 이 방법은 $O(n^2)$의 시간 복잡도를 가지기 때문에 여전히 느렸다.</p>
<h4 id="개선">개선</h4>
<p>약간의 생각 후, 양 끝에서 최솟값으로 순회하는 동안 최솟값을 갱신한다면 그것이 바로 자신보다 작은 숫자가 반대편의 없는 경우라는 것에 도달했다.</p>
<h4 id="최종-코드">최종 코드</h4>
<pre><code class="language-js">function solution(a) {
      // 최솟값의 위치 탐색.
    let min = Infinity;
    let min_index = -1;
    for (let i = 0; i &lt; a.length; i ++) {
        if (min &lt; a[i]) continue;
        min = a[i];
        min_index = i;
    }
      // 정답에 최솟값을 포함하고 시작.
    let answer = 1; 

      // 만약 최솟값을 갱신한다면 마지막에 남을 수 있는 풍선.
      // 왼쪽에서 최솟값 위치까지 순회
    let temp_min = Infinity;
    for (let i = 0; i &lt; min_index; i ++) {
        if (temp_min &gt; a[i]) {
            temp_min = a[i];
            answer ++;
        }
    }
      // 오른쪽에서 최솟값 위치까지 순회
    temp_min = Infinity;
    for (let i = a.length - 1; i &gt; min_index; i --) {
        if (temp_min &gt; a[i]) {
            temp_min = a[i];
            answer ++;
        }
    }
    return answer;
}</code></pre>
<p>$O(n)$의 시간 복잡도를 가지는 코드로 통과할 수 있었다.</p>
<h3 id="후기">후기</h3>
<p>어떤 알고리즘을 알고 있느냐 보다는 시간 복잡도에 대해서 이해하고 어떤 방향으로 문제를 해결해야 하는지 방향을 잡는 것이 중요한 문제라고 생각한다. 제한 사항을 통해 완전 탐색이라는 선택지를 제외했고, 운좋게 규칙을 빠르게 찾아 시간이 오래 걸리지는 않았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 22.05.31]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-22.05.31</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-22.05.31</guid>
            <pubDate>Thu, 02 Jun 2022 11:10:13 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="components-구현">Components 구현</h2>
<p>강의를 들으며 페이지를 구성할 때 사용할 수 있는 아주 작은 단위의 컴포넌트를 구현해봤다.</p>
<h3 id="1-avatar">1. Avatar</h3>
<p><img style="float: left; margin: 20px" src="https://velog.velcdn.com/images/jo_cw/post/5a1614fa-d3ed-422b-b8a0-a03c086fcb3c/image.png" /><p>
여러 SNS에서 프로필 사진을 표시할 때 사용하는 Avatar 컴포넌트이다. 기본적으로 사진을 표시하는 것 이외에도 <code>Image</code> 객체의 <code>onload()</code>메소드를 사용해서 로딩 시에 추가적인 애니메이션이나 이팩트를 추가하는 방식을 접할 수 있었다. </p></p>
<div style="clear:both"></div>

<h3 id="2-slider">2. Slider</h3>
<p><img src="https://velog.velcdn.com/images/jo_cw/post/7a33edb8-ddc9-4a91-b38c-e02b980f4190/image.svg" alt="">
<code>&lt;input type=&quot;range&quot; /&gt;</code>와 동일한 역할을 하는 <code>Slider</code> 컴포넌트이다. </p>
<ul>
<li>전체 범위를 나타내는 <code>Rail</code>, 현재 범위를 나타내는 <code>Track</code>, 사용자와 상호작용하여 범위를 변경할 수 있는 <code>Handle</code> 3개의 컴포넌트로 나누어 각각 구현</li>
<li>제어를 위해서 <code>mousemove</code>, <code>mousedown</code>, <code>mouseup</code> 총 3개의 이벤트를 사용</li>
<li><code>mousemove</code>와 <code>mouseup</code>의 경우는 좌우로 이동하는 과정에서 Handle의 범위를 이탈 할 수 있어서 전역 이벤트로 지정</li>
<li>Slider 컴포넌트의 왼쪽 끝의 x좌표 <code>offsetLeft</code>와 드래깅 중인 마우스의 x좌표 <code>pageX</code>를 사용해서 <code>Track</code>의 길이와 <code>Handle</code>의 위치를 구한다.</li>
</ul>
<p><code>Slider</code> 컴포넌트를 storybook으로 테스트하는 중 마우스를 빠르게 움직이는 경우 드래그가 동작하지 않는 문제를 발견했는데 정확한 이유를 찾지 못했다.</p>
<p><code>&lt;input type=&quot;range&quot; /&gt;</code>와 비교하면 추가적인 최적화가 필요하지만 각 컴포넌트의 디자인이 자유로운 것이 유용해보인다.</p>
<h3 id="3-progress">3. Progress</h3>
<p>진행상황을 나타내는 <code>Progress</code> 컴포넌트</p>
<ul>
<li>props의 <code>width</code> 값에 따라서 로딩바가 길어지는 아주 단순한 구조이다.</li>
<li>시각적인 효과를 주기위해서 <code>animation</code>과 <code>@keyframe</code> css 속성을 사용</li>
</ul>
<p>크게 복잡하진 않았지만 CSS animation과 관련된 속성들을 알 수 있었다.</p>
<p>!codepen[jochaewoo/embed/QWQrPov?default-tab=css%2Cresult&amp;theme-id=dark]
[ progress bar에 마우스를 올려보자 ]</p>
<h3 id="4-divider">4. Divider</h3>
<p><img src="https://velog.velcdn.com/images/jo_cw/post/5ad3697b-7fbb-4dc1-bf8c-7d0345ee8b38/image.png" alt="">
네비게이션 바에서 메뉴를 분리할 때 사용하는 컴포넌트. styled component를 사용해서 단순하게 구현할 수 있었다.</p>
<h3 id="5-skeleton">5. Skeleton</h3>
<p style="margin-bottom: 0px;">
  <img 
style="margin: 0"    src="https://velog.velcdn.com/images/jo_cw/post/d8aa91a9-155f-45b7-b8cd-3a5960af25af/image.png" /><p style="text-align: center;margin-top: 3px;">&lt discode의 로딩화면 &gt</p></p>

<p>로딩중인 컨탠츠를 더 자세하게 나타낼 수 있는 컴포넌트. 위의 <code>Progress</code>에서 사용했던 animation을 이용하여 동적인 느낌을 줄수도 있다.</p>
<ul>
<li><p>여러 모양의 컴포넌트를 하나의 객체에 담아 export, import 할 수 있다.</p>
</li>
<li><p>이를 이용해서 <code>Circle</code> <code>Box</code> <code>Paragraph</code> 등 여러 모양의 <code>Skeleton</code>을 하나의 객체만 import 해서 사용할 수 있다.</p>
<pre><code class="language-js">// 예시
import Skeleton from &#39;Skeleton&#39;
const App = () =&gt; {
return (
  &lt;&gt;
    &lt;Skeleton.Box /&gt;
    &lt;Skeleton.Prargraph /&gt;
  &lt;/&gt;
)
}</code></pre>
<h3 id="6-select">6. Select</h3>
<p>기존 <code>&lt;select&gt;</code> 태그와 <code>option</code> 태그를 개선한 Select 컴포넌트</p>
</li>
<li><p><code>&lt;select&gt;</code>에서 사용할 수 없던 placeholer를 props에 전달해서 설정이 가능하도록 구성했다.</p>
</li>
<li><p>placeholer의 경우 가장 위의 <code>&lt;option&gt;</code> 태그에 placeholer의 값을 넣고 <code>hidden</code> 속성을 적용하면, 가장 위에 있는 값이 노출되지만 클릭시 노출되지 않는다.
<img src="https://velog.velcdn.com/images/jo_cw/post/a83fe904-a46d-48f0-9d4d-e0d5e2e1e245/image.png" alt=""></p>
</li>
<li><p>강의에서는 <code>&lt;select&gt;</code>와 <code>&lt;option&gt;</code>을 styled component로 수정해서 사용했지만 style 적용을 더 다양하게 만들기 위해서 다른 방식으로도 구현할 수 있다.</p>
</li>
</ul>
<p>!codepen[jochaewoo/embed/BaYxgLP?default-tab=css%2Cresult&amp;theme-id=dark]
<code>ul</code>과 <code>li</code> 태그를 이용해서 간단한 Select를 만든 예시이다.
구조가 더 복잡해질 수 있지만, CSS의 적용이 더 자유롭다.</p>
<hr>
<h1 id="더-공부할-것">더 공부할 것</h1>
<ul>
<li><code>@keyframes</code> 와 <code>animation</code> CSS</li>
<li><code>React.Children</code>를 사용한 children props 조작</li>
<li>mouse events</li>
</ul>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>React 공식 문서
<a href="https://ko.reactjs.org/docs/getting-started.html">https://ko.reactjs.org/docs/getting-started.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 22.05.30]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-22.05.30</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-22.05.30</guid>
            <pubDate>Wed, 01 Jun 2022 16:27:32 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="context-api">Context API</h2>
<p>Props를 이용한 데이터 전달은 Vue에서와 동일한 문제점을 공유한다. 컴포넌트 사이의 거리가 멀어지면 중간에 위치한 컴포넌트는 사용하지 않는 데이터임에도 불구하고 하위 또는 상위 컴포넌트에게 전달하기 위해서 props를 사용한다. 강의에서는 위와 같은 상황을 <code>props drilling</code>이라고 설명했다. Vue에서는 이를 위해서 <code>Provide</code>와 <code>Inject</code>를 사용한 것처럼. React에서는 <code>Context API</code>의 <code>Context Provider</code>와 <code>Context Consumer</code>를 사용할 수 있다.</p>
<h3 id="1-context-생성">1. Context 생성</h3>
<p><code>creatContext()</code>를 사용해서 Context 객체를 만들 수 있다. <code>creatContext()</code>의 입력으로 기본값을 설정할 수 있다.</p>
<pre><code class="language-js">const MyContext = React.creatContext(defaultValue)</code></pre>
<h3 id="2-provider---데이터의-전달">2. Provider - 데이터의 전달</h3>
<p>객체에 포함된 컴포넌트 <code>Provider</code>를 이용해 데이터를 전달하며, 이 데이터는 <code>value</code> prop으로 지정한다. 데이터는 <code>Provider</code>의 하위 컴포넌트에 전달이 가능하며, 여러 Context의 <code>Provider</code>를 중첩해서 사용할 수 있다.</p>
<pre><code class="language-html">&lt;MyContext.Provider value={data}&gt;
  &lt;!-- 데이터를 전달이 필요한 하위 컴포넌트 --&gt;
&lt;/MyContext.Provider&gt;</code></pre>
<h3 id="3-consumer---데이터의-사용-1">3. Consumer - 데이터의 사용 1</h3>
<p>Context 객체에 포함된 컴포넌트 <code>Consumer</code>를 사용해 <code>Provider</code>를 통해서 전달한 데이터를 사용할 수 있다. <code>Cousumer</code>의 자식은 반드시 함수여야 한다. 만약 <code>Consumer</code> 컴포넌트의 상위 컴포넌트에 <code>Provider</code>가 존재하지 않는다면 <code>createContext()</code>에 입력한 기본값이 데이터로 주어진다. </p>
<pre><code class="language-html">&lt;MyContext.Provider value={data}&gt;
  &lt;MyContext.Consumer&gt;
    {value =&gt; &lt;div&gt;{value}&lt;/div&gt;}
    &lt;!-- &lt;div&gt;data&lt;/div&gt; --&gt;
  &lt;/MyContext.Consumer&gt;
&lt;/MyContext.Provider&gt;
&lt;MyContext.Consumer&gt;
  {value =&gt; &lt;div&gt;{value}&lt;/div&gt;}
  &lt;!-- &lt;div&gt;defaultValue&lt;/div&gt; --&gt;
&lt;/MyContext.Consumer&gt;</code></pre>
<h3 id="4-usecontext---데이터의-사용-2">4. useContext - 데이터의 사용 2</h3>
<p><code>useContext</code>에 Context 객체를 입력해서 <code>Provider</code>의 <code>value</code>값을 반환받을 수 있으며, <code>useContext</code>를 호출하는 모든 컴포넌트는 <code>Provider</code>의 <code>value</code> props가 변경될 때 리렌더링 된다.</p>
<h3 id="5-사용-예시">5. 사용 예시</h3>
<p>예시에서는 <code>Provider</code>와 <code>Consumer</code> 컴포넌트를 사용했다. 부모-자식 관계가 아닌 두 노드가 있고 위에 있는 노드의 input에 값을 입력하면 아래에 있는 노드의 문구가 바뀌는 것을 볼 수있다.</p>
<p>!codepen[jochaewoo/embed/LYQmzep?default-tab=js%2Cresult&amp;theme-id=dark]</p>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>React 공식 문서
<a href="https://ko.reactjs.org/docs/getting-started.html">https://ko.reactjs.org/docs/getting-started.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 22.05.26]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-22.05.26</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-22.05.26</guid>
            <pubDate>Thu, 26 May 2022 16:13:40 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="react에-style-적용하기">React에 style 적용하기</h2>
<h3 id="1-style-sheet">1. style sheet</h3>
<p>css, scss 등의 별도 파일로 적용</p>
<h3 id="2-inline-style">2. inline style</h3>
<p>컴포넌트 태그 안에 <code>style</code> 속성을 지정, <code>props</code>를 이용한 동적 적용이 가능.</p>
<h3 id="3-css-in-js---emotion">3. CSS in JS - Emotion</h3>
<p>외부 라이브러리를 사용하는 방식 <a href="https://emotion.sh/docs/introduction"><code>emotion</code></a> 등이 있다.</p>
<h2 id="usememo"><code>useMemo</code></h2>
<h3 id="목적">목적</h3>
<p>컴포넌트 리렌더링 발생 상황은 다음과 같다.</p>
<ol>
<li>자신의 상태가 변경될 때 (함수 컴포넌트의 경우만)</li>
<li>부모 컴포넌트로 부터 받는 props가 변경될 때</li>
<li>부모 컴포넌트의 상태가 변경될 때
컴포넌트가 리렌더링되면 말 그대로 JSX를 반환하는 함수를 다시 실행하는 것이고 이 과정에서 불필요한 동작이 있을 수 있다. 이렇게 불필요한 코드 실행을 방지하기 위해서 사용할 수 있는 Hook이 <code>useMemo</code>이다.<h3 id="사용">사용</h3>
<code>useEffect</code>와 비슷하게 감시할 인자와, 그 인자가 변경될 때 실행할  함수를 매개변수로 대입한다.<blockquote>
<h5 id="코드">코드</h5>
</blockquote>
<pre><code class="language-js">function App() {
const [data, setData] = useState(0)
return (
&lt;div className=&quot;App&quot;&gt;
  &lt;button onClick={() =&gt; setData(data + 1)}&gt;
    Change Data
  &lt;/button&gt;
  &lt;Component data={data}&gt;
&lt;/div&gt;
)
}</code></pre>
<pre><code class="language-js">function calculate(data) {
let result = data
//매우매우 복잡하고 오래걸리는 연산
return result
}
function Component({ data }) {
// data의 값이 변경되었을 때만 &#39;calculate&#39; 함수가 실행된다.
const result = useMemo(calculate(data), [data])
return (
&lt;div&gt;
  {result}
&lt;/div&gt;
)
}</code></pre>
위 처럼 Component의 <code>result</code>에 영향을 주는 <code>data</code>값에 변경이 있을 경우만 <code>calculation</code>함수가 실행되게 할 수 있으며, 이를 통해서 불필요한 동작을 막을 수 있다.</li>
</ol>
<h2 id="reactmemo"><code>React.memo</code></h2>
<h3 id="목적-1">목적</h3>
<p>위에서 설명했듯 부모 컴포넌트의 상태가 변경될 때 자식 컴포넌트의 리렌더링이 발생한다. <code>useMemo</code>를 사용해서 일부 최적화가 가능하지만 리렌더링 자체를 막을 수는 없었다. 이 경우 <code>React.memo</code>를 사용하여 부모 컴포넌트의 상태 변경시 리렌더링을 막을 수 있다.</p>
<h3 id="사용-1">사용</h3>
<p>JSX를 반환하는 함수를 <code>React.memo()</code>로 감싸서 사용한다.</p>
<blockquote>
<h5 id="코드-1">코드</h5>
</blockquote>
<pre><code class="language-js">import React from &#39;react&#39;
const Memo = React.memo(({ memo }) =&gt; {
  console.log(&#39;memo rendered&#39;)
  return &lt;div&gt;Memo: {memo}&lt;/div&gt;
})
export default Memo</code></pre>
<pre><code class="language-js">import React from &#39;react&#39;
function Memo({ memo }) {
  console.log(&#39;memo rendered&#39;)
  return &lt;div&gt;Memo: {memo}&lt;/div&gt;
}
export default React.memo(Memo)</code></pre>
<p>위 처럼 <code>React.memo</code>를 사용해서  props의 변화가 있을 경우만 렌더링이 진행되도록 할 수 있다. 하지만 props의 변화 감지가 <strong>얕은 비교</strong>를 통해서 이루어지므로 참조형 데이터가 props인 경우 이를 비교하여 true, false 값을 반환하는 비교 함수를 두 번째 인자에 추가할 수 있다. 
<a href="https://ko.reactjs.org/docs/react-api.html#reactmemo">관련 문서</a></p>
<h2 id="usecallback"><code>useCallback</code></h2>
<h3 id="함수의-재정의">함수의 재정의</h3>
<p><code>useCallback</code>의 사용 목적을 알기 위해서 리렌더링 동작에서 <strong>함수의 재정의</strong> 개념을 이해해야 한다. 이에 대해서 내가 이해한대로 정리하면 아래와 같다.
!codepen[jochaewoo/embed/preview/ZErawVL?default-tab=js%2Cresult&amp;theme-id=light]
위의 예시 코드에서 <code>Childe</code> 컴포넌트는 렌더링시에 메세지를 출력한다
(<code>f12</code>를 누르면 나오는 개발도구의 콘솔창에 출력된다). 
<code>Child</code> 컴포넌트는 <code>React.memo</code>를 사용해서 부모 컴포넌트의 상태가 변경되어도 리렌더링이 발생하지 않아야 하지만 <code>Change State</code> 버튼을 클릭해 부모 컴포넌트인 <code>App</code>의 상태를 변경하면 메세지가 출력된다. 이는 다음과 같은 일련의 과정 때문이다.</p>
<ol>
<li><code>App</code>의 상태가 변경되어 리렌더링</li>
<li><code>App</code>의 리렌더링 과정에서 <code>onClick</code> 함수가 재정의</li>
<li><code>onClick</code> 함수는 <code>Child</code>의 props이므로 <code>Child</code>가 리렌더링</li>
</ol>
<p>즉, <code>App</code>이 리렌더링 될 때 <code>onClick</code> 함수는 변경이 없어보이지만, 이름과 내용이 동일한 또 다른 함수로 대체되는 것이다.</p>
<h3 id="목적-2">목적</h3>
<p>위의 예시에서 알 수 있듯이 자식 컴포넌트에 props로 callback 함수를 사용하면 실행 내용에 변경이 없어도 불필요한 렌더링이 발생할 수 있다. 이를 방지하기 위해서 <code>useCallback</code>을 사용한다.</p>
<h3 id="사용-2">사용</h3>
<p>렌더링 시에 재정의를 막을 함수와 의존성 배열을 매개변수로 입력한다.</p>
<pre><code class="language-js">function App() {
  const [state, setState] = useState(0)
  const onClick = useCallback(() =&gt; console.log(&#39;click&#39;), [])
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h2&gt; App &lt;/h2&gt;
      &lt;p&gt;state: {state}&lt;/p&gt;
      &lt;button onClick={() =&gt; setState(state + 1)}&gt;Change State&lt;/button&gt;
      &lt;Child onClick={onClick}/&gt;
    &lt;/div&gt;
  );
};</code></pre>
<h2 id="storybook">Storybook</h2>
<p><a href="https://storybook.js.org/tutorials/intro-to-storybook/react/ko/get-started/">공식문서</a>
UI를 분리하여 관리할 수 있는 라이브러리에 대해서 간단한 예제를 직접 실행해봤다. 프로젝트 진행에 있어 고려할만한 라이브러리였다. </p>
<hr>
<h1 id="🧐느낀점">🧐느낀점</h1>
<p>정리를 하면서 내가 이해한 것을 설명하는 것이 가장 어렵다는 것을 새삼 느낀다. 다른 사람이 봤을 때 이해하기 쉽게 정리하고 싶었는데, 뭔가 내용만 길어진 느낌이다.</p>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>React 공식 문서
<a href="https://ko.reactjs.org/docs/getting-started.html">https://ko.reactjs.org/docs/getting-started.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 22.05.25]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-22.05.25</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-22.05.25</guid>
            <pubDate>Wed, 25 May 2022 14:50:23 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="react">React</h2>
<h3 id="1-시작하기">1. 시작하기</h3>
<p><code>create-react-app</code>을 이용해서 앞서 배웠던 여러가지 webpack 설정과 의존성 관리가 끝나있는 프로젝트를 만들 수 있었다. <code>npx create-react-app [app 이름]</code> 명령 한 줄로 간단하게 만들 수 있는 점이 인상깊다.</p>
<h3 id="2-jsx">2. JSX</h3>
<p>최근의 React에서는 함수 형태의 컴포넌트 사용이 권장된다고 한다. 하나의 함수가 컴포넌트 역할을 하며, <code>return</code> 값으로 <code>html</code>과 유사한 형태의 <code>JSX</code>를 반환한다. <code>JSX</code>를 사용해서 App을 구성할 때 주의할 점은 최상위 노드가 반드시 하나로 구성해야하는 것이다. 이렇게 하는 이유는 virtual DOM에서 변화를 효율적으로 감지하기 위해서라고 한다.</p>
<h3 id="react-fragment">react fragment</h3>
<p>최상위 노드를 하나로 만들기 위해서<code>&lt;div&gt;</code> 태그 등을 이용해서 감싸는 것이 렌더링 된 <code>html</code> 구조를 복잡하게 한다고 생각 할 수 있다. 이 경우 이름이 없는 태그(<code>&lt;&gt;</code> <code>&lt;/&gt;</code>)로 감싸 렌더링 되지않는 최상위 노드를 만들 수 있다. 이름 없는 태그는 <strong><code>&lt;React.Fragment&gt;</code>의 단축 문법</strong>이다.</p>
<h3 id="표현식-포함">표현식 포함</h3>
<p>JSX 안에 <code>{}</code>를 추가하여 표현식을 넣을 수 있다. 표현식은 text node, node의 attribute 등에 위치할 수 있다.</p>
<h3 id="조건부-렌더링">조건부 렌더링</h3>
<p>Vue의 <code>v-if</code>같은 특별한 구문 없이 앞서 말한 표현식을 이용한다. 표현식 안에 논리곱연산자 또는 삼항연산자를 사용할 수 있다.</p>
<blockquote>
<h5 id="예시">예시</h5>
</blockquote>
<pre><code class="language-js">    const isVisible = false;
    return (
      &lt;div&gt;
      { isVisible &amp;&amp; &lt;p&gt; Optional Rendering &lt;/p&gt; }
      &lt;/div&gt;
    )</code></pre>
<h3 id="반복">반복</h3>
<p>표현식 안에 <code>map()</code>, <code>filter()</code>같은 Array method를 사용하여 리스트 데이터를 반복되는 요소로 만들 수 있다. 이 때 렌더링 효율성을 위해서 <code>key</code> attribute를 설정하는 것이 권장된다. <code>key</code>값은 id와 같이 중복되지 않는 값으로 설정한다.</p>
<blockquote>
<h5 id="예시-1">예시</h5>
</blockquote>
<pre><code class="language-js">// map을 이용해서 JSX로 이루어진 Array를 반환
    const listData = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;];
    return (
      &lt;ul&gt;
      { listData.map(data =&gt; &lt;li&gt;{data}&lt;/li&gt;) }
      &lt;/ul&gt;
    )</code></pre>
<pre><code class="language-html">&lt;!-- 다음과 같이 렌더링 된다. --&gt;
    &lt;ul&gt;
      &lt;li&gt;a&lt;/li&gt;
      &lt;li&gt;b&lt;/li&gt;
      &lt;li&gt;c&lt;/li&gt;
      &lt;li&gt;d&lt;/li&gt;
    &lt;/ul&gt;</code></pre>
<h3 id="props">props</h3>
<p>Vue와 마찬가지로 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전송할 때 <code>props</code>를 사용할 수 있다.</p>
<blockquote>
<h5 id="예시-2">예시</h5>
</blockquote>
<pre><code class="language-js">// 상위 컴포넌트
function App() {
  return (
    &lt;div&gt;
      &lt;Component name=&quot;kiko&quot; /&gt;
    &lt;/div&gt;
  )
}
// 하위 컴포넌트
function Component(props) {
  return (
    &lt;div&gt;Hello! my name is {props.name}&lt;/div&gt;
  )
}</code></pre>
<p>위 처럼 상위 컴포넌트는 하위컴포넌트의 attribute로 값을 전달하며, 하위 컴포넌트는 모든 값들을 하나의 <code>props</code> 객체로 입력받는다.
특수한 <code>props</code>로 <code>children</code> 값이 있는데, 이 값은 컴포넌트의 자식 노드를 값으로 전달받는다. Vue의 <code>slot</code>과 비슷한 역할을 하는 것으로 이해했다.</p>
<blockquote>
<h5 id="예시-3">예시</h5>
</blockquote>
<pre><code class="language-js">// 상위 컴포넌트
function App() {
  return (
    &lt;div&gt;
      &lt;h1&gt;This is App&lt;/h1&gt;
      &lt;Component name=&quot;kiko&quot;&gt;
        &lt;h2&gt;This is Children&lt;/h2&gt;
      &lt;/Component&gt;
    &lt;/div&gt;
  )
}
// 하위 컴포넌트
function Component(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello! my name is {props.name}&lt;/h1&gt;
      {props.children}
    &lt;/div&gt;
  )
}</code></pre>
<pre><code class="language-html">&lt;!-- 이렇게 렌더링 된다. --&gt;
&lt;div&gt;
  &lt;h1&gt;This is App&lt;/h1&gt;
  &lt;div&gt;
    &lt;h1&gt;Hello! my name is kiko&lt;/h1&gt;
    &lt;h2&gt;This is Children&lt;/h2&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
<p><code>propType</code>를 사용하여 <code>props</code>의 type과 필수 여부를 지정해 줄 수 있다.</p>
<blockquote>
<h5 id="예시-4">예시</h5>
</blockquote>
<pre><code class="language-js">import propType from &#39;prop-types&#39;
function Component(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello! my name is {props.name}&lt;/h1&gt;
      {props.children}
    &lt;/div&gt;
  )
}
// props 객체 안의 name은 string type이어야 하며 반드시 입력되야 한다.
// 그렇지 않을 시에 error가 발생한다.
Component.propType = {
  name: propType.string.isRequired
}</code></pre>
<p><code>defaultProps</code> 또는 구조분해할당을 사용해서 <code>props</code>의 기본값을 지정할 수 있다.</p>
<blockquote>
<h5 id="예시-5">예시</h5>
</blockquote>
<pre><code class="language-js">function Component(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello! my name is {props.name}&lt;/h1&gt;
      {props.children}
    &lt;/div&gt;
  )
}
Component.defaultProps = {
  name: &#39;unknown&#39;
}</code></pre>
<pre><code class="language-js">function Component({name = &#39;unknown&#39;}) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello! my name is {props.name}&lt;/h1&gt;
      {props.children}
    &lt;/div&gt;
  )
}</code></pre>
<h3 id="usestate">useState</h3>
<p>반응형 데이터를 만들고 관리하기 위해 사용하는 함수이다. <code>useState(defaultValue)</code>를 사용하면 반응형 데이터와 해당 데이터의 값을 변경시 사용하는 setter 함수를 배열에 담아 반환한다. setter 함수를 사용해서 값을 변경할 시 컴포넌트가 리렌더링된다.</p>
<blockquote>
<h5 id="예시-6">예시</h5>
</blockquote>
<pre><code class="language-js">// 주로 구조분해할당을 이용한다.
const defaultValue = 0
const [value, setValue] = useState(defaultValue)
console.log(value) // 0
setValue(12)
console.log(value) // 12</code></pre>
<h3 id="useeffect">useEffect</h3>
<p><code>useEffect</code>는 컴포넌트가 렌더링을 수행한 뒤에 필요한 side effect를 실행하기 위한 hook이다. 
<code>useEffect(sideEffectFunction, [])</code>
위와 같은 형태로 사용할 수 있으며 첫번째 인자로 입력한 함수가 렌더링이 될 때 실행되고 두번째 인자에 따라서 추가적인 실행을 할 수 있다. 두번째 인자인 배열에 <code>useState</code>를 통해서 얻은 데이터 값을 넣으면, 해당하는 값의 변경이 생길때마다 반복해서 실행한다. 첫번째 인자인 함수에서 함수를 반환하면, 반환한 함수는 컴포넌트가<code>unmount</code>될 때 실행하며 가이드에서는 이 동작을 <a href="https://ko.reactjs.org/docs/hooks-effect.html#effects-with-cleanup"><code>clean-up</code></a>이라고 설명한다. </p>
<blockquote>
<h5 id="예시-7">예시</h5>
</blockquote>
<pre><code class="language-js">import { useEffect, useState } from &#39;react&#39;
function Component() {
  const [state, setState] = useState(0)
  useEffect(() =&gt; {
    console.log(&#39;rendering&#39;) // 컴포넌트의 렌더링이 완료된 뒤 실행
    return () =&gt; { 
      console.log(&#39;unmount&#39;) // 컴포넌트가 제거(unmount)될 때 실행
    }
  }, [])
  useEffect(() =&gt; {
    console.log(&#39;state change&#39;) // state 값이 변경될 때마다 실행
  }, [state])
}</code></pre>
<h3 id="useref">useRef</h3>
<p><code>useRef</code>는 하나의 컴포넌트가 반환하는 JSX안의 자식요소에 접근하기 위해서 주로 사용한다. 또한 setState와 다르게 값이 변경되어도 리렌더링이 되지 않기 때문에 지역변수로도 사용이 가능하다. 이 부분에 대해서는 아직 이해가 더 필요하다.</p>
<h4 id="useref-관련-react-문서"><a href="https://ko.reactjs.org/docs/hooks-reference.html#useref">useRef 관련 React 문서</a></h4>
<hr>
<h1 id="🧐느낀점">🧐느낀점</h1>
<p>이전에 들었던 Vanilla JS에서의 컴포넌트 구조와 아주 유사하다는 느낌을 받았다. 그래서 그런지 Vue보다 조금 더 익숙하고 어렵지 않게 컴포넌트를 구성할 수 있을 것 같은 자신감도 약간 느껴진다. React는 심화 과정도 있는 만큼 지금 확실하게 정리하는 것이 좋아보인다.</p>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>React 공식 문서
<a href="https://ko.reactjs.org/docs/getting-started.html">https://ko.reactjs.org/docs/getting-started.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 22.05.17]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-22.05.17</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-22.05.17</guid>
            <pubDate>Tue, 17 May 2022 15:43:39 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="pinia">Pinia</h2>
<p>특강을 통해서 기존에 배운 상태관리 라이브러리 vuex와 비교하여 pinia가 가지는 특징에 대해서 알아보는 시간을 가졌다.</p>
<h3 id="모듈화">모듈화</h3>
<p>vuex는 <code>createStore</code>의 입력에 <code>modules</code> 속성을 이용해서 모듈을 등록할 수 있으며 모듈 등록 없이도 사용이 가능하다.
반면 pinia는 모듈 사용이 필수적이다. 각각의 모듈은 <code>defineStore</code>를 사용해서 생성하며 첫 번째 인자로 고유한 모듈명이 두 번째 인자로 <code>state</code>와 관련된 정보가 담긴 객체가 필요하다.</p>
<h3 id="store-등록">store 등록</h3>
<p>vuex에서는 <code>state</code>나 <code>getters</code>를 컴포넌트의 <code>computed</code>에 등록하여 반응형 데이터로 사용하거나 <code>mapState</code>, <code>mapGetters</code> 같은 helper 함수를 사용했다.
pinia의 경우 모든 store의 접근이 이런 helper 함수를 사용하는 것이 강제된다. 또한 <code>mapGetters</code> 함수가 없고 getters의 값은 <code>mapState</code>에서 같이 등록이 가능하다.</p>
<h3 id="state-접근">state 접근</h3>
<p>vuex에서 getters나 mutations의 메서드를 정의 할 때 함수의 매개변수로 state를 입력받아 이를 이용해 store의 state 값에 접근할 수 있었다.</p>
<pre><code class="language-js">    getters: {
        doubleCount(state) {
          return state.count * 2
        }
    }</code></pre>
<p>pinia에서는 단순히 this를 사용해서 state에 접근이 가능하다.</p>
<pre><code class="language-js">    getters: {
        doubleCount() {
          return this.count * 2
        }
    }</code></pre>
<h3 id="state-변경-권한">state 변경 권한</h3>
<p>pinia와 vuex의 가장 큰 차이점이라고 생각되는 것이 이 부분이었다. 
vuex에서는 state의 변경은 반드시 mutations를 통해서만 가능했다. 따라서 언제나 commit을 사용해 state의 값을 바꿔야 했다.
pinia에서는 이러한 제한이 전혀 없다. store 내부의 <code>actions</code>에서도 <code>this.state</code> 로 접근하여 바로 수정이 가능하며, 컴포넌트에서도 <code>defineStore</code>가 반환한 인스턴스를 사용해서 state를 수정할 수 있다.</p>
<h3 id="추가적인-메서드">추가적인 메서드</h3>
<h4 id="reset">$reset</h4>
<p>store에 있는 state를 초기값으로 설정하는 메서드이다. vuex의 경우는 초기 상태를 별도로 저장하고 초기화 동작을 하는 actions를 만들어야 하는 걸 생각하면 매우 유용한 메서드 같다.</p>
<h4 id="patch">$patch</h4>
<p>state를 변경할 수 있는 메서드이다. 객체를 사용해서 한번에 여러개의 state를 변경할 수도 있으며, 함수를 이용해서도 변경이 가능하다.
함수를 이용한 state 변경은 state를 참조할 때 값의 평가가 순서대로 이루어진다.</p>
<p>예를 들어, 다음과 같은 state가 있다고 가정하자
<code>{ age: 17, cost: 1500 }</code>
나이가 20살 이상부터는 cost를 3000으로 하고싶다. 객체를 이용해서 state를 다음처럼 갱신한다고 가정하자.
<code>store.$patch({ age: 24, cost: this.age &gt;= 20 ? 3000 : 1500})</code>
state는 어떻게 바뀔까? 다음과 같다. <code>{ age: 24, cost: 1500 }</code>
객체 안의 <code>age</code>의 평가는 바로 이루어져 <code>cost</code>가 24로 바뀌기 전인 17로 평가되고 그 결과 삼항 연산자를 통해서 1500으로 평가되는 것이다.
여기서 함수를 이용하면 아래와 같이 사용할 수 있다.</p>
<pre><code class="language-js">store.$path((state) =&gt; {
    state.age = 24
    state.cost = state.age &gt;= 20 ? 3000 : 1500
})</code></pre>
<p>입력된 함수는 순차적으로 실행되어 평가가 순서대로 이루어진다. <code>age</code>는 24로 변경되고, <code>cost</code>를 변경하는 시점에서는 <code>age</code>가 24로 평가가 되어 <code>cost</code>가 3000으로 변경된다.</p>
<p>예시는 아주 단순해서 크게 특별하다는 느낌을 받지 못했는데, 사용하는 방식이나 프로젝트의 크기에 따라서 유용하게 사용할 수 있을 것 같다는 생각도 든다.</p>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 40]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-40</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-40</guid>
            <pubDate>Mon, 16 May 2022 17:02:39 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="vue-router">Vue Router</h2>
<h3 id="vue-router란">Vue Router란?</h3>
<p>Vue.js의 공식 라우터로 공식 홈페이지에 적혀있는 특징으로는 중첩 맵핑, 동적 라우팅, HTML5 history mode와 Hash mode 지원 등이 있다.</p>
<h3 id="생성">생성</h3>
<p><code>vue-router</code> 패키지의 <code>createRouter()</code>를 사용한다. 경로 정보를 담고있는 <code>routes</code>와 사용할 방식의 <code>history</code>를 하나의 객체에 넣어 <code>createRouter()</code>의 입력으로 사용한다.</p>
<h4 id="routes"><code>routes</code></h4>
<p><code>routes</code>는 경로에 대한 정보를 가진 객체들을 담고있는 하나의 배열이다. 각 객체는 다음과 같은 정보를 담고있다.</p>
<h5 id="1-path">1. <code>path</code></h5>
<p>주소창에 표시되는 경로, root경로는 <code>/</code>이다.</p>
<h5 id="2-component">2. <code>component</code></h5>
<p><code>path</code>에 해당하는 경로에서 표시할 컴포넌트.</p>
<h5 id="3-name">3. <code>name</code></h5>
<p><code>path</code>의 별칭.</p>
<h4 id="history"><code>history</code></h4>
<p>history의 모드를 지정한다.</p>
<ul>
<li>Hash Mode
<code>createWebHashHistory()</code>로 생성한 인스턴스를 입력해 Hash Mode로 라우팅을 할 수 있다. Hash Mode는 URL앞에 Hash Charater(<code>#</code>)가 위치하며 서버로의 요청은 최초 페이지를 로딩할 때만 이루어진다. SPA에 적합하지만 검색엔진최적화 등 단점이 존재한다.</li>
<li>HTML5 Mode
<code>createWebHistory()</code>로 생성한 인스턴스를 입력해 HTML5 Mode로 라우팅 할 수 있다. 이 모드를 사용해서 SPA를 만든다면 새로고침시 <strong>404 Error</strong>가 발생할 수 있어 루트 경로로 리다이렉트 해주는 처리가 필요하다.</li>
</ul>
<pre><code class="language-js">// e.g.
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: &#39;/&#39;,
      name: &#39;home&#39;,
      component: Home
    }
  ]
})</code></pre>
<h3 id="사용">사용</h3>
<h4 id="전역으로-등록">전역으로 등록</h4>
<p><code>vuex</code>와 동일하게 어플리케이션 인스턴스에 <code>use()</code>를 사용하면 Vue 컴포넌트에서 전역으로 사용이 가능하다. <code>this.$router</code>로 접근하여 관련 함수들을 사용한다.</p>
<h4 id="컴포넌트에-표시">컴포넌트에 표시</h4>
<p>라우팅된 컴포넌트는 <code>&lt;RouterView /&gt;</code> 또는 <code>&lt;router-view /&gt;</code> 태그의 위치에 표시된다.</p>
<h4 id="라우팅">라우팅</h4>
<p>Vue 컴포넌트에서 url을 변경하는 방법은 크게 2가지다.</p>
<h5 id="1-routerlink-태그-사용">1. <code>&lt;RouterLink&gt;</code> 태그 사용</h5>
<p><code>&lt;RouterLink&gt;</code> 또는 <code>&lt;router-link&gt;</code> 태그에 <code>to</code> 속성을 사용하면 클릭시 해당 url로 라우팅 되며 이는 html의 <code>&lt;a&gt;</code>태그와 비슷하다. <code>to</code>속성 또한 <code>:</code>를 붙여 동적으로 설정이 가능하며 routes의 <code>name</code>을 이용한 라우팅 또한 가능하다.</p>
<h5 id="2-push-메서드-사용">2. <code>push</code> 메서드 사용</h5>
<p><code>this.$router.push()</code>를 사용해서 <code>&lt;RouterLink&gt;</code>와 동일한 동작을 할 수 있다. </p>
<pre><code class="language-html">&lt;!--Root URL--&gt;
&lt;RouterLink to=&quot;/&quot;&gt;HOME&lt;/RouterLink&gt;
&lt;!--name을 사용--&gt;
&lt;RouterLink :to=&quot;{ name: &#39;home&#39;}&quot;&gt;HOME&lt;/RouterLink&gt;

&lt;script&gt;
  function goHome() {
    this.$router.push(&#39;/&#39;)
    this.$router.push({ name: &#39;home&#39; })
  }
&lt;/script&gt;</code></pre>
<h3 id="추가-기능">추가 기능</h3>
<h4 id="query">query</h4>
<p>url 뒤에 <code>?</code>로 구분하여 query를 추가하는 것이 가능하다. query간의 구분을 <code>&amp;</code>로 하며 key=value형식으로 작성한다. 이렇게 입력한 query는 Vue 컴포넌트 내에서<code>this.$router.query</code>로, 외부에서는 <code>createRouter()</code>로 생성된 인스턴스 router의 <code>router.currentRoute.value.query</code>로 접근이 가능하다.</p>
<blockquote>
<p>예를 들어 url이 <code>https://abc.com/home?name=kiko&amp;id=30109</code>일 때, <code>this.$router.query</code> 또는 <code>router.currentRoute.value.query</code>에는 
{ name: &#39;kiko&#39;, id: &#39;30109&#39; } 객체가 저장되어 있다.
<img src="https://velog.velcdn.com/images/jo_cw/post/64c55a75-55d2-4246-be17-197ce5bed53a/image.png" alt=""></p>
</blockquote>
<h4 id="param">param</h4>
<ul>
<li>param은 동적 라우팅에 사용된다. <code>path</code>의 url의 뒤에 <code>/:name</code>을 붙여 사용한다. (<code>name</code>은 예시이며 원하는 이름으로 설정이 가능하다.)</li>
<li>url에 적힌 값은 <code>this.$router.params</code> 또는 <code>router.currentRoute.value.params</code>에서 접근해 사용할 수 있다.<blockquote>
<p><code>path</code>가 &#39;/info/:id&#39;로 지정된 상태에서 <code>https://abc.com/info/35</code>를 입력하면 해당하는 컴포넌트로 라우팅되고 <code>this.$router.params</code>에는 { id: &#39;35&#39;}와 같은 객체가 있다.
<code>https://abc.com/info/</code>뒤에 어떠한 값이 들어와도 표시되는 컴포넌트는 하나이며 params의 값만 다르게 적용된다.</p>
</blockquote>
</li>
</ul>
<h3 id="navigation-guard">Navigation Guard</h3>
<p><code>Navigation Guard</code>는 다른 url로 라우팅 될 때 시기별로 동작하며 주로 접근 권한을 확인하는데 사용된다.</p>
<h4 id="routerbeforeeachto-from-next"><code>router.beforeEach(to, from, next)</code></h4>
<p><code>router.beforeEach</code>는 전역으로 모든 라우팅 과정에서 동작하며, 한 페이지에 접근하기 직전에 실행된다.</p>
<h5 id="parameter">parameter</h5>
<ul>
<li>to
접근하려는 경로의 정보를 담고있다.</li>
<li>from
접근 이전에 있었던 경로의 정보를 담고있다.</li>
<li>next
Vue2에서 사용되던 함수로 실행시키면 입력에 따라 다른 경로로 이동한다. <code>this.$router.push()</code>와 유사하게 사용한다.</li>
</ul>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>Vue Router 가이드 
<a href="https://router.vuejs.org/introduction.html">https://router.vuejs.org/introduction.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 39]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-39</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-39</guid>
            <pubDate>Sun, 15 May 2022 19:20:44 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="refs">refs</h2>
<p>기존 Javascript에서 html element에 접근하기 위해서 <code>doucument.querySelector()</code> 등의 메서드를 사용해왔다. 하지만 <code>document.querySelector()</code>는 html 문서를 처음부터 탐색하여 컴포넌트 단위로 탐색할 수 없다. 
이를 위해 <code>ref</code> 속성과 <code>$refs</code>를 사용할 수 있다. html element의<code>ref</code>속성에 이를 식별할 수 있는 키워드를 등록하면 전역 객체인 <code>$refs</code>에 등록되어 <code>this.$refs.name</code> 과 같은 형식으로 등록해 놓은 요소에 접근이 가능하다.</p>
<h2 id="동적-컴포넌트">동적 컴포넌트</h2>
<p>컴포넌트의 속성을 <code>v-bind</code>를 이용해서 동적으로 이용할 수 있듯이 컴포넌트 또한 동적으로 변경이 가능하다. 동적 컴포넌트를 사용하기 위해서 <code>component</code> 태그가 사용되며, 이 태그에 <code>is</code> 속성으로 컴포넌트의 이름을 지정한다. 
이 방식은 <code>v-if</code>와 유사하게 <code>is</code> 속성 값이 변경될 때마다 (즉, 동적 컴포넌트가 바뀔 때 마다) 기존의 컴포넌트는 <code>unmount</code>되고 새로운 컴포넌트가 <code>create</code>되는 동작이 반복되어 변경이 일어날 때의 비용이 크다. </p>
<h4 id="keep-alive-태그"><code>keep-alive</code> 태그</h4>
<p><code>keep-alive</code> 태그 안에 있는 동적 컴포넌트는 컴포넌트가 변경되어 <code>unmount</code>되어도 이를 캐싱하고 다시 사용할 때 <code>create</code> 과정을 거치지 않는다. 하지만 캐싱에도 메모리 등의 자원이 소모되므로 사용에 주의해야한다.</p>
<h2 id="slots">Slots</h2>
<p>컴포넌트 태그 사이에 text content 또는 html element가 존재하는 경우 이 요소들은 모두 컴포넌트의 <code>template</code>에 존제하는 <code>slot</code> 태그 위치에 위치하게 된다. </p>
<h3 id="v-slot"><code>v-slot</code></h3>
<p>만약 태그 사이에 여러개의 요소들이 존재하고 각 요소들의 위치를 다른 곳에 위치하고 싶을 때 <code>v-slot</code> 디렉티브를 사용할 수 있다. <code>v-slot=&quot;after&quot;</code> 속성을 가진 element는<code>name=&quot;after&quot;</code> 속성을 가진 slot에 위치하게 된다. 이를 위해서 <code>slot</code> 태그는 <code>name</code> 속성을 지정해 줘야한다.</p>
<h4 id="약어">약어</h4>
<p><code>v-slot</code> 디렉티브는 <code>#</code>으로 대체가 가능하다. 즉, <code>v-slot=&quot;after&quot;</code>는 <code>#after</code>로 표기할 수 있다.</p>
<h4 id="동적-v-slot">동적 <code>v-slot</code></h4>
<p>다른 디렉티브처럼 <code>v-slot</code>도 대괄호로 감싸 동적으로 사용이 가능하다. 
요소의 속성이 <code>#[slotName]</code>이라면 <code>slotName</code>에 저장된 값에 따라서 위치가 동적으로 바뀐다.</p>
<h2 id="plugin">Plugin</h2>
<p>만약 하나의 함수가 여러 컴포넌트에서 공통적으로 사용된다면 이를 <code>plugin</code>으로 만들어 사용할 수 있다.</p>
<h3 id="생성">생성</h3>
<p><code>plugin</code>은 <code>install</code> 함수를 가진 객체 리터럴로 생성된다. <code>install</code> 함수는 <code>app</code>과 <code>option</code>을 매개변수로 입력받으며, 이 매개변수 중 <code>app</code>의 <code>app.config.globalProperties</code>에 플러그인의 이름과 동작할 함수를 key-value 쌍으로 선언한다.</p>
<pre><code class="language-js">// &#39;$fetch&#39; plugin을 생성하는 경우
export default {
  install(app, options) {
    app.config.globalProperties[&#39;$fetch&#39;] = () =&gt; {
        // $fetch plugin 동작 코드
    }
  }
}</code></pre>
<h3 id="등록">등록</h3>
<p>전역 컴포넌트의 등록을 위해서 어플리케이션 인스턴스에 <code>component()</code> 메서드를 사용하듯이 <code>plugin</code>은 <code>use()</code> 메소드를 이용해서 등록한다. </p>
<pre><code class="language-js">const app = Vue.createApp(App)
app.use(fetchPlugin, {})
app.mount(&#39;#app&#39;)</code></pre>
<h3 id="사용">사용</h3>
<p>위의 과정을 거쳐 등록된 <code>plugin</code>은 component안에서 <code>this</code>로 바로 사용이 가능하다.</p>
<pre><code class="language-js">this.$fetch()</code></pre>
<h2 id="mixin">mixin</h2>
<p>scss의 <code>@mixin</code>에서 유추할 수 있듯 mixin은 컴포넌트 내부의 값들이 반복될 때 코드의 중복을 줄이기 위해서 사용할 수 있다. </p>
<h3 id="사용-1">사용</h3>
<p><code>methods</code>, <code>props</code>, <code>computed</code> 등 컴포넌트의 옵션이 중복되는 부분을 별도의 객체 리터럴로 선언한다. 
이후 <code>mixin</code>이 필요한 컴포넌트의 <code>mixins</code> 옵션에 배열 리터럴로 <code>mixin</code>을 추가한다.
<code>component()</code>, <code>plugin()</code>과 동일하게 <code>mixin()</code> 메서드로 전역 mixin을 등록할 수 있다.</p>
<pre><code class="language-js">
// mixin 생성
const myMixin = {
  props: {
    name: {
      type: String,
      default: &#39;&#39;
    }
  },
  methods: {
    duplicatedMethod() {
      // do something
    }
  }
}
// mixin 사용
export default {
  mixins: [&#39;myMixin&#39;, &#39;anotherMixin&#39;]
}
</code></pre>
<h3 id="주의점">주의점</h3>
<p>mixin 안에 있는 옵션과 컴포넌트 안에 있는 옵션 중 이름이 같은 것이 존재한다면 컴포넌트 안에 있는 옵션이 우선권을 가진다. 
(mixin의 옵션이 컴포넌트의 옵션으로 덮어 쓰여진다.)
<code>created</code>, <code>mounted</code> 등과 같은 <code>life cycle hook</code>의 경우 배열에 병합되어 모두 실행되며 <strong>mixin hook -&gt; component hook 순</strong>으로 실행된다. </p>
<h2 id="provide와-inject">provide와 inject</h2>
<p><em>조상-부모-자식</em> 3 개의 컴포넌트가 존재하고 조상 컴포넌트의 데이터를 자식 컴포넌트가 써야하는 상황을 가정하자. 만약 <code>props</code>를 이용해서 데이터를 전달한다면 조상 컴포넌트의 데이터를 부모 컴포넌트를 거쳐 자식 컴포넌트에 전달해야하는 아주 불필요한 과정이 필요하다. 데이터를 공유해야하는 두 컴포넌트 사이에 다른 컴포넌트들이 많을 수록 문제는 더욱 심각해진다.
이 문제점을 해결하기 위해서 <code>provide</code>와 <code>inject</code>를 사용할 수 있다.</p>
<h3 id="사용-2">사용</h3>
<p>공유할 데이터를 가진 컴포넌트에서 <code>provide</code> 옵션을 지정한다. 이 때 <code>provide</code>는 데이터를 전달하므로 반드시 함수로 선언한다.</p>
<pre><code class="language-js">export default {
   provide() {
    return {
      msg: this.msg
    }
  }
}</code></pre>
<p>데이터가 필요한 컴포넌트에서 <code>inject</code> 옵션을 배열 리터럴 안에 지정한다.</p>
<pre><code class="language-js">export default {
  inject: [&#39;msg&#39;]
}</code></pre>
<h3 id="주의점-1">주의점</h3>
<p>위처럼 값을 <code>provide</code>에 바로 입력할 경우 이 데이터는 반응형 데이터가 아니며 따라서 값이 변경되도 렌더링이 적용되지 않는다. 반응형 데이터로 만들기 위해서 <code>vue</code>의 <code>computed</code> 함수를 사용해야한다.
(이 때도 <code>computed()</code>의 매게 변수에 들어가는 데이터는 함수로 입력한다.)</p>
<pre><code class="language-js">export default {
   provide() {
    return {
      msg: computed(() =&gt; this.msg)
    }
  }
}</code></pre>
<h2 id="전역-스토어">전역 스토어</h2>
<p><code>props</code>의 문제점을 <code>provide &amp; inject</code>를 사용해서 해결했지만 이 또한 한계가 존재한다. <code>provide &amp; inject</code>는 어디까지나 데이터의 전달만이 이루어지기 때문에 데이터의 수정은 데이터를 가지고 있는 컴포넌트만이 가능하다. 
<strong>전역 스토어를 사용하면 이 문제점을 해결할 수 있다.</strong></p>
<h3 id="구조">구조</h3>
<p>전역 스토어는 4개의 구성요소를 가지고 있다.</p>
<ol>
  <li>상태를 보관하는 "state"</li>
  <li>상태를 변경하는 "mutations"</li>
  <li>상태의 변경을 요청하는 "actions"</li>
  <li>상태를 가공하여 출력하는 "getters"</li>
</ol>

<h3 id="생성-1">생성</h3>
<p>각 구성요소들은 정해진 규칙 없이 자유롭게 작성이 가능하지만 상태를 보관하는 state의 경우 반응형 데이터로 사용하기 위해서  <code>vue</code>의 <code>reactive()</code>를 사용한다. <code>reactive()</code>는 객체 리터럴을 입력받아 반응형 데이터인 proxy를 반환하는 함수이다.</p>
<h2 id="vuex">Vuex</h2>
<p>vuex는 위의 전역 스토어를 좀 더 체계적으로 구현한 라이브러리다.</p>
<h3 id="구조-1">구조</h3>
<p><img src="https://velog.velcdn.com/images/jo_cw/post/bba8ee54-c1f3-4b79-9739-9222a9a51041/image.png" alt="">
전역 스토어와 구조 자체는 같을 수 있지만 동작 방식에 차이가 있다. vuex에서는 Mutaions의 함수가 동작하기 위해서 <code>commit</code> 함수를 사용하며, Action의 함수가 동작하기 위해서 <code>dispatch</code>함수를 사용한다.</p>
<h3 id="생성-2">생성</h3>
<p><code>vuex</code>의 <code>createStore</code> 함수를 사용하며 컴포넌트의 옵션처럼 객체 리터럴에 필요한 값을 지정하여 매개변수로 입력한다.
component의 data와 같은 이유로 <strong>state는 함수로 작성한다.</strong>
<code>getters</code>와 <code>mutations</code>에서 함수의 첫 번째 매게변수를 통해서 state의 값에 접근이 가능하며, <code>actions</code>에 있는 함수의 첫 번째 매게변수인  <code>context</code>는 <code>state</code>, <code>getters</code>, <code>commit</code>, <code>dispatch</code>가 저장된 객체이다.</p>
<pre><code class="language-js">// vuex store 생성 예시
const myStore = createStore({
  state() {
    return {
      data: &#39;something&#39;
    }
  },
  getters: {
      important(state) {
      return data + &#39;important&#39;
    }
  },
  mutations: {
      updateData(state, nextData) {
      state.data = nextData
    }
  },
  actions: {
      fetchData(context) {
      //fetch data
    }
  }
})</code></pre>
<h3 id="사용-3">사용</h3>
<p>가장 먼저 전역으로 사용하기 위해서 어플리케이션 인스턴스에 <code>use()</code> 메서드로 등록이 필요하다.</p>
<pre><code class="language-js">const app = Vue.createApp(App)
app.use(myStore)
app.mount(&#39;#app&#39;)</code></pre>
<p>컴포넌트 내부에서 store를 사용하는 경우</p>
<ul>
<li><p><code>state</code>
<code>this.$store.state</code>로 접근</p>
</li>
<li><p><code>getters</code>
<code>this.$store.getters</code>로 접근</p>
</li>
<li><p><code>action</code>
<code>this.$store.dispatch()</code>로 함수 호출 </p>
</li>
<li><p><code>mutations</code>
<code>this.$store.commit()</code>로 함수 호출</p>
<pre><code class="language-js">// state
this.$store.state.data
</code></pre>
</li>
</ul>
<p>// getters
this.$store.getters.important</p>
<p>// action
this.$store.dispatch(&#39;fetchData&#39;)</p>
<p>// state
this.$store.state.commit(&#39;updateData&#39;)</p>
<pre><code>### 모듈화
하나의 store가 모든 컴포넌트의 데이터를 관리할 경우 코드가 길어져 유지보수가 어려울 수 있으며 이 외에도 여러 단점이 존재한다. 모듈화는 과도하게 커질 수 있는 store를 여러 개로 나누어 관리할 수 있게 해준다.

#### 생성
모듈은 전역 스토어 생성시 `createStore`에 입력하는 객체와 거의 동일하다. 추가적으로 `namespaced: true` 값을 객체 리터럴에 추가해주면 끝이다.
```js
const myModule = {
  namespaced: true,
  state() {},
  getters: {},
  mutations: {},
  actions: {}
}</code></pre><h4 id="등록-1">등록</h4>
<p>생성된 모듈은 전역 스토어의 옵션 중 <code>modules: {...}</code>에 입력하여 등록할 수 있다.</p>
<pre><code class="language-js">const myStore = {
  modules: {
    moduleName: myModule 
  }
}</code></pre>
<h4 id="사용-4">사용</h4>
<p>기존의 전역스토어에 <code>namespace</code> 명을 추가하는 방식으로 사용한다.</p>
<pre><code class="language-js">// namespace 가 &#39;module&#39;인 경우
// state
this.$store.state.module.data

// getters
this.$store.getters.[&#39;module/important&#39;]

// action
this.$store.dispatch(&#39;module/fetchData&#39;)

// state
this.$store.state.commit(&#39;module/updateData&#39;)</code></pre>
<h4 id="mapping">mapping</h4>
<p><code>vuex</code>의 함수 <code>mapState</code>, <code>mapGetters</code>, <code>mapActions</code>, <code>mapMutations</code>를 사용해 Store의 값을 컴포넌트의 옵션에 빠르게 mapping이 가능하다. 모든 함수의 입력은 아래와 같다.</p>
<blockquote>
<p><strong>(namespace 이름, [사용할 값 또는 함수의 이름, ...])</strong>
전역 스토어의 경우 namespace 이름은 생략한다. <a href="https://vuex.vuejs.org/guide/modules.html#binding-helpers-with-namespace">참고 링크</a></p>
</blockquote>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>Vue 3 가이드 
<a href="https://v3.vuejs-korea.org/guide/introduction.html">https://v3.vuejs-korea.org/guide/introduction.html</a></li>
<li>vuex<br><a href="https://vuex.vuejs.org/">https://vuex.vuejs.org/</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 34]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-34</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-34</guid>
            <pubDate>Sat, 14 May 2022 18:07:53 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="vue">Vue</h2>
<p>Javascript 프레임워크 vue에 대해서 학습했다.
기존 Vanilla JS를 이용하여 여러 프로젝트를 만들면서 직접 구현해야 했던 내용들을 자체적으로 지원한다.</p>
<h3 id="시작하기">시작하기</h3>
<ul>
<li><code>Vue.createApp({})</code>
입력값: 어플리케이션과 관련된 옵션들을 저장한 객체 리터럴
반환값: 어플리케이션 인스턴스
실행 결과 반환된 어플리케이션 인스턴스의 <code>mount()</code>메소드를 이용해서 DOM에 마운트할 수 있으며, ViewModel을 반환한다. <code>mount()</code>에는 자신이 마운트하고 싶은 html element의 선택자를 매개변수로 넣어 사용한다.<pre><code class="language-js">// 옵션 객체
const App = {
data() {
  return {
    attr: &quot;class&quot;,
  };
},
};
// 어플리케이션 인스턴스
const app = Vue.createApp(App);
// ViewModel, id=&quot;app&quot;인 html element에 마운트
const vm = app.mount(&quot;#app&quot;);</code></pre>
<h3 id="옵션-객체">옵션 객체</h3>
위의 <code>Vue.createApp({})</code>의 입력인 옵션 객체는 이후 <strong>루트 컴포넌트</strong> 구성에 사용된다.<h4 id="1-data">1. data</h4>
컴포넌트에서 사용할 데이터를 객체 리터럴로 선언한다. data안에 존재하는 값들은 <strong>반응형 데이터</strong>로 해당 값이 변경될 때 자동으로 DOM이 변경된다.
옵션 객체는 하나의 컴포넌트로 재사용이 가능하다. 만약 data를 일반 객체 리터럴로 작성한다면 객체는 <strong>참조형 데이터</strong>이기 때문에 다른 컴포넌트에서의 data값 변경이 영향을 미칠 수 있다. 따라서 객체를 return하는 함수로 작성해서 컴포넌트 생성시 서로 다른 주소를 가진 객체를 사용하도록 한다.<h4 id="2-methods">2. methods</h4>
컴포넌트에서 사용할 함수를 객체 리터럴로 선언한다.<h4 id="3-watch">3. watch</h4>
반응형 데이터가 변경되었을 때 수행할 동작들을 객체 리터럴로 선언한다.</li>
<li>handler
data가 변경되었을 때 수행할 동작이 담긴 함수. handler 함수 이외의값이 없다면 key-value쌍 대신 data와 동일한 이름을 가진 함수로 대체 가능하다.
매개변수 지정시 첫번째 매게변수에는 변경된 새로운 값이, 두번째 매게변수에는 변경되기 전 기존 값이 입력되며 생략이 가능하다.<pre><code class="language-js">  // 아래 두 코드는 동일하게 동작함.
  // key-value 쌍
  name: {
    handler() {
      // data의 name이 변경시 실행되는 코드
    }
  }
  // 함수로 대체
  name() {
    // data의 name이 변경시 실행되는 코드
  }    </code></pre>
</li>
<li>deep
Array, Object와 같은 참조형 데이터의 경우 참조하는 주소의 변경 없이 내부의 값만 변경된다면 동작하지 않는다. 이 경우는 deep값을 true로 설정해야 한다.</li>
<li>immediate
immediate가 true일 경우 값의 변경이 없어도 실행 즉시 핸들러가 동작한다. 기본값에도 동일한 처리가 필요할 경우 주로 사용한다. <pre><code class="language-js">// 아래와 같이 작성한다.
watch: {
name(newName, oldName) {
  console.log(&#39;watch&#39;, newName, oldName);
},
fruits: {
  handler() {
    console.log(this.fruits);
  },
  deep: true,
  immediate: true
}
},</code></pre>
<h4 id="4-computed">4. computed</h4>
반응형 데이터를 이용해 새로운 값을 만들어 사용해야 할 때, 이 값을 효율적으로 사용하기 위한 옵션이다. 새롭게 만들어진 값은 캐싱되어 재사용시에 여러 동작을 생략할 수 있으며, 반응형 데이터가 변경된 경우에도 캐싱된 값을 갱신한다.
getter와 setter로 구성되며, getter만 사용시 아래와 같이 하나의 함수로 선언이 가능하다.</li>
</ul>
<pre><code class="language-js">computed: {
  // 객체로 선언
  computedValueName: {
    get() {
      // data값을 가공
      return computedValue;
    }
  },
  // 함수로 선언
  computedValueName() {
    //data값을 가공
    return computedValue;
  }
}</code></pre>
<h3 id="템플릿-문법">템플릿 문법</h3>
<h4 id="1-보간법">1. 보간법</h4>
<ul>
<li><p>Mustache 기법
Mustache라 불리는 이중 중괄호 안에 반응형 데이터를 넣어 html안에 포함시킬 수 있으며 간단한 Javascript 표현식을 사용할 수 있다.</p>
<pre><code class="language-html">  &lt;!--문자열 보간--&gt;
  &lt;h1&gt;data: {{ data }}&lt;/h1&gt;
  &lt;!--Javascript 표현식--&gt;
  &lt;h2&gt;{{ number * 2 }}&lt;/h2&gt;
  &lt;!--Javascript 표현식: 삼항 연산자--&gt;
  &lt;h3&gt;{{ number % 2 === 1 ? &#39;yes&#39; : &#39;no&#39; }}&lt;/h3&gt;</code></pre>
</li>
<li><p>v-html
<code>&lt;h2 style=&quot;color: yellowgreen;&quot;&gt; Raw HTML&lt;/h2&gt;</code> 등과 같은 html 형식의 문자열은 <code>v-html</code> 디렉티브를 이용해서 html 요소로 출력시킬 수 있다. 하지만 <code>XSS</code> 공격에 취약하므로 <code>v-html</code>을 사용하는 부분에서는 유저의 입력이 관여해서는 안된다.</p>
<pre><code class="language-html">  &lt;div v-html=&quot;rawHTML&quot;&gt;&lt;/div&gt;</code></pre>
<pre><code class="language-js">  data() {
    return {
      rawHTML: &#39;&lt;h2 style=&quot;color: yellowgreen;&quot;&gt; Raw HTML&lt;/h2&gt;&#39;
    }
  }</code></pre>
<h4 id="2-디렉티브">2. 디렉티브</h4>
</li>
<li><p><code>v-show</code>
값이 truthy한 값인지 falsy한 값인지에 따라서 <code>display</code> 스타일 속성을 조정한다.</p>
</li>
<li><p><code>v-if</code>
값이 truthy한 값인지 falsy한 값인지에 따라서 렌더링 여부를 정한다.</p>
<blockquote>
<p><strong><code>v-show</code> vs <code>v-if</code></strong>
<code>v-show</code>의 경우 무조건 렌더링 이루어지고 <code>display: none</code>과 같이 스타일로 표시 여부를 지정한다. 따라서 초기 렌더링 비용이 <code>v-if</code>보다 큰 대신 변경시에는 추가적인 렌더링이 필요하지 않다. 
반대로 <code>v-if</code>의 경우는 표시하지 않는 요소는 렌더링하지 않아 초기 렌더링 비용이 적다. 하지만 변경시마다 렌더링이 필요하여 변경시 비용이 크다. </p>
</blockquote>
</li>
<li><ul>
<li>즉, 변경이 잦은 경우 <code>v-show</code>를, 변경이 없는 경우 <code>v-if</code>를 사용하는 것이 좋다.**</li>
</ul>
</li>
<li><p><code>v-bind</code>
html element의 attribute에 반응형 데이터를 적요할 때 사용한다. <code>:</code> 로 줄여서 사용이 가능하다. </p>
<pre><code class="language-html">  &lt;!-- class attribute가 data의 className으로 적용된다. --&gt;
  &lt;div v-bind:class=&quot;className&quot;&gt;&lt;/div&gt;

  &lt;!-- 약어로 &#39;:&#39;만 입력해도 동일하게 동작한다. --&gt;
  &lt;div :class=&quot;className&quot;&gt;&lt;/div&gt;

  &lt;!-- attribute의 key값 또한 &#39;[]&#39;를 사용하여 동적으로 적용이 가능하다. --&gt;
  &lt;div v-bind:[keyName]=&quot;keyValue&quot;&gt;&lt;/div&gt;</code></pre>
</li>
<li><p><code>v-on</code>
이벤트를 처리하는 디렉티브, DOM 이벤트명과 함깨 사용하여 해당하는 이벤트 발생시 <code>methods</code>에 있는 함수를 동작하게 한다. <code>@</code>로 줄여서 사용이 가능하다.</p>
<pre><code class="language-html">  &lt;!-- click 이벤트 발생 시, methods의 doSomething() 함수가 동작함. --&gt;
  &lt;button v-on:click=&quot;doSomething&quot; /&gt;

  &lt;!-- 약어인 &#39;@&#39;로 대체가 가능하며 위의 element와 동일하게 동작한다. --&gt;
  &lt;button @click=&quot;doSomething&quot; /&gt;</code></pre>
</li>
</ul>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>Vue 3 가이드 <a href="https://v3.vuejs-korea.org/guide/introduction.html">https://v3.vuejs-korea.org/guide/introduction.html</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 30]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-30</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-30</guid>
            <pubDate>Mon, 02 May 2022 15:16:20 GMT</pubDate>
            <description><![CDATA[<h1 id="📚-공부한-내용">📚 공부한 내용</h1>
<h2 id="float">float</h2>
<ul>
<li>float 속성의 해제</li>
</ul>
<ol>
<li><code>overflow: hidden</code> (직접적인 해결 방법이 아님)</li>
<li><code>clear: both</code> 속성 사용</li>
<li>::after 가상요소를 사용하자.</li>
</ol>
<ul>
<li><p>float: right 사용시 쌓이는 순서에 유의</p>
</li>
<li><p>float 요소는 display값이 block으로 변경된다. (flex, grid 등 일부 제외)</p>
</li>
<li><p>fixed는 항상 뷰포트를 기준으로 삼는 것이 아님
(transform, perspectiv, filter 에 의해서 기준이 변경된다)</p>
</li>
</ul>
<h3 id="stacking-context-쌓임-맥락">stacking context, 쌓임 맥락</h3>
<ul>
<li><p><code>z-index</code>는 static position에선 동작하지 않음. 기본값은 auto (=0)</p>
</li>
<li><p>position: absolute, fixed는 display값을 block으로 변경한다.</p>
<h2 id="flex">flex</h2>
<h3 id="flex의-display-속성">flex의 display 속성</h3>
</li>
<li><p>flex : 수직으로 쌓임, width가 최대한 늘어남</p>
</li>
<li><p>inline-flex : 수평으로 쌓임, width가 최소한으로 줄어듦. 글자처럼 다룬다</p>
<h3 id="줄바꿈">줄바꿈</h3>
</li>
<li><p>flex-warp: 줄바꿈 처리 관련 nowrap(기본값), wrap, wrap-reverse</p>
<h3 id="flex-container의-정렬-속성">flex container의 정렬 속성</h3>
</li>
<li><p>justify-content: flex-start, flex-end, center, space-between, space-around;</p>
</li>
<li><p>align-items: stratch, flex-start, flex-end, center, baseline(문자 기준선 정렬)</p>
</li>
<li><p>align-content: 2줄 이상일 때 (flex-wrap: wrap 일 때), 교차축 정렬 방식. 기본값 stratch</p>
</li>
</ul>
<h3 id="flex-item의-속성">flex item의 속성</h3>
<ul>
<li><p>flex-grow: 기본값 0, 컨테이너의 공간이 남을 때, item의 증가 비율을 나타냄</p>
</li>
<li><p>flex-shrink: 기본값 1, 줄바꿈이 없는 컨테이너의 공간이 부족할 때, 감소 비율을 나타냄.</p>
</li>
<li><p>flex-basis: 기본값 auto, flex item의 기본 너비를 설정함 width 보다 우선됨</p>
</li>
<li><p>flex: 위 3가지 속성의 단축 속성, grow shrink basis 순서로 작성하며, 띄어쓰기로 구분함. basis 값을 생략했을 때, 기본값이 아닌 0으로 설정됨.</p>
</li>
<li><p>order: item의 순서의 가중치를 설정함. 기본 값 0. 더 작은 값이 정렬 시작 위치에 온다. 음수도 사용 가능.</p>
</li>
<li><p>align-self: 아이템 별로 align-items를 개별 적용</p>
<h2 id="grid">grid</h2>
<h3 id="grid-container">grid container</h3>
</li>
<li><p>grid-template-rows : 각 행의 개수와 너비를 지정 (명시적)</p>
</li>
<li><p>grid-template-columns : 각 열의 개수와 높이를 지정 (명시적)</p>
</li>
<li><p>repeat(num, val) : 반복함수</p>
<blockquote>
<p>아래 두 속성은 동일하게 동작한다.<br>grid-template-rows: 100px 100px 100px 100px;<br>grid-template-rows: repeat(4, 100px);</p>
</blockquote>
</li>
<li><p>fr : container의 width, column을 비율로 나타내는 단위.</p>
</li>
<li><p>grid-auto-flow : 기본 값 row. container 안의 item들의 순서를 제어한다. 빈 공간을 자동으로 채워주는 row dense, column dense 값도 있으며, row가 기본값이므로 dense만 입력시 row dense가 적용된다.</p>
</li>
<li><p>grid-auto-rows, grid-auto-columns : template로 지정된 범위 밖의 row 또는 column의 크기를 지정한다. (암시적)</p>
</li>
</ul>
<h3 id="grid-content-정렬">grid content 정렬</h3>
<p>grid container 안의 item들을 content라고 하며 아래의 속성으로 content의 정렬 방식을 정할 수 있다.</p>
<ul>
<li><p>justify-content: container 안의 content의 x축의 정렬 방식을 정할 수 있다. flex의 속성과 유사</p>
<ul>
<li>normal(기본값) : stratch와 동일</li>
<li>start : 시작점(왼쪽) 정렬</li>
<li>end : 끝점(오른쪽) 정렬</li>
<li>center : 중앙 정렬</li>
<li>space-between : 각 열의 사이 여백을 동일한 간격으로 나누어 정렬(start와 end에 item)</li>
<li>space-around : 각 열의 양쪽 여백을 동일하게 나누어 정렬</li>
<li>space-evenly : 각 열의 사이 여백을 동일한 간격으로 나누어 정렬(start와 end에 공백)</li>
</ul>
</li>
<li><p>align-content: content의 y축 정렬 속성. justify-content와 같은 속성값을 가진다.</p>
</li>
</ul>
<h3 id="grid-cell-정렬">grid cell 정렬</h3>
<p>하나의 grid cell 안에 존재하는 item의 정렬 방식을 지정한다. 하나의 cell에 하나의 item만 존재하므로 content 정렬에서 사용한 space-between, space-around, space-evenly는 사용할 수 없다.</p>
<ul>
<li>justify-items: x축</li>
<li>align-items: y축<ul>
<li>normal(기본값)</li>
<li>start</li>
<li>end</li>
<li>center</li>
</ul>
</li>
</ul>
<h3 id="area">area</h3>
<ul>
<li>grid-area: grid item에 적용. grid-template-areas에서 사용할 이름을 지정함.</li>
<li>grid-template-areas</li>
</ul>
<pre><code class="language-css">grid-template-areas:
  &quot;header header header&quot;
  &quot;main main aside&quot;
  &quot;. . aside&quot;
  &quot;footer footer footer&quot;;
grid-gap: 10px;
  /* .은 none으로 대체가 가능하다 */</code></pre>
<p><img src="https://velog.velcdn.com/images/jo_cw/post/c9237898-e9d1-4264-b101-db3265143e36/image.png" alt=""></p>
<h3 id="line-gutter">line (gutter)</h3>
<p>grid-gap: grid item 사이에 간격을 적용하는 속성. 단축 속성</p>
<blockquote>
<p>grid-gap: 10px 는 grid-row-gap: 10px와 grid-column-gap: 10px와 동일한 속성<br>grid-gap: 10px 40px 는 grid-row-gap: 10px와 grid-column-gap: 40px와 동일한 속성</p>
</blockquote>
<p>gap 또한 동일하게 동작하며 row-gap과 column-gap으로 나누어 사용할 수 있다. <strong>gap은 flex와 grid에서 동일하게 사용하기 위해 이후에 추가된 속성이다.</strong> 따라서 호환성에 따라 사용 여부를 결정하자.</p>
<h3 id="grid-item-속성">grid item 속성</h3>
<h3 id="line">Line</h3>
<p>grid에는 각 row와 column의 시작점과 끝점을 표시하는 line이 존재한다.</p>
<ul>
<li>grid-row-start, grid-row-end : grid item의 row 방향의 시작점, 끝점을 정하는 속성. 기본적으로 시작과 끝의 차이는 1이다</li>
<li>grid-column-start, grid-column-end : grid item의 column 방향의 시작점, 끝점을 정하는 속성. row와 동일하게 시작과 끝의 차이는 기본적으로 1이다</li>
<li>grid-row : grid-row-start와 grid-row-end의 단축속성. start와 end 값을 <code>/</code>로 구분한다.</li>
<li>grid-column: grid-column-start와 grid-column-end의 단축 속성. 사용 방식은 grid-row와 동일하다.</li>
<li>span : 위의 속성에 사용하는 키워드, item이 차지하는 공간을 뜻한다. 기본값은 1</li>
</ul>
<h3 id="개별-정렬">개별 정렬</h3>
<p>위의 grid container에서 각 cell을 정렬하는 방식인 justify-items, align-items를 하나의 item에서 개별 적용하는 속성</p>
<ul>
<li>justify-self: justify-items와 동일하게 사용. 기본 값은 justify-items와 같은 normal(stretch)</li>
<li>align-self: align-items와 동일하게 사용. 기본 값은 align-items와 같은 normal(stretch)</li>
</ul>
<h3 id="순서">순서</h3>
<ul>
<li>order: 기본값 0, 같은 order값을 가진 element는 html의 순서대로 정렬된다. 값이 작을 수록 더 앞에 순서에 위치하며 음수로도 설정이 가능하다.</li>
<li>z-index: grid-item의 z축 쌓임 순서를 정하는 속성값</li>
</ul>
<h2 id="grid-functions-units">grid functions, units</h2>
<h3 id="grid-container의-행과-열을-만들-때-사용할-수-있는-함수들">grid container의 행과 열을 만들 때 사용할 수 있는 함수들</h3>
<ul>
<li><p>repeat: 값의 반복에 사용.</p>
<blockquote>
<p>아래 두 속성은 동일하게 동작한다.<br>grid-template-rows: 100px 100px 100px 100px;<br>grid-template-rows: repeat(4, 100px);</p>
</blockquote>
<blockquote>
<p>다음과 같이 반복도 가능하다.<br>grid-template-rows: 100px 200px 100px 200px;<br>grid-template-rows: repeat(4, 100px 200px);</p>
</blockquote>
</li>
<li><p>minmax: 각 행과 열의 최소, 최대 크기를 지정한다. 명시적, 암시적 속성에 모두 사용 가능</p>
</li>
<li><p>fit-content(<em>max_value</em>) : item의 크기를 content에 맞추되 최대 크기를 <code>max_value</code>까지 제한한다.(<code>max_value</code>이상으로 커지지 않는다.)</p>
</li>
</ul>
<h3 id="단위-units">단위 (Units)</h3>
<ul>
<li>fr (fraction) : <strong>사용 가능한 남은 공간</strong>을 비율로 표시함.</li>
<li>min-content<br>grid item 내부에 있는 content를 기준으로 가능한 최소의 너비를 지정함.<br><strong>한글의 경우 단어의 너비(띄어쓰기)가 아닌 글자의 너비를 최소 너비로 지정하므로 이를 위해서 grid item에 <code>word-break:keep-all</code> 설정이 필요함.</strong></li>
<li>max-content : grid item 내부에 있는 content를 기준으로 가능한 최대 너비를 지정함.</li>
<li>auto-fill : repeat 함수의 반복 횟수 부분에 사용. row 또는 column의 수를 자동으로 지정해줌. <strong>지정할 수 있는 최대 너비 우선 적용 (aka. minmax)</strong></li>
<li>auto-fit : repeat 함수의 반복 횟수 부분에 사용. row 또는 column의 수를 자동으로 지정해줌. <strong>지정할 수 있는 최소 너비 우선 적용 (aka. minmax)</strong></li>
</ul>
<pre><code class="language-css">/* 아래와 같이 사용 */
grid-template-columns: repeat(auto-fit, 1fr);
grid-template-columns: repeat(auto-fill, 1fr);</code></pre>
<hr>
<h1 id="📝-더-공부할-것">📝 더 공부할 것</h1>
<ul>
<li>각 CSS 속성이 필요할 때, 바로 연상할 수 있도록 복습!</li>
</ul>
<hr>
<h1 id="🤔-느낀점">🤔 느낀점</h1>
<p>CSS의 각 속성에 대해서 꼼꼼하게 설명해주셔서 이해가 쉬우면서도 정리하고나니 양이 엄청나다. 이번 CSS 과제를 하면서 이론적으로 이해한 부분을 직접 사용하면서 익숙해질 필요가 있어보인다.</p>
<hr>
<h1 id="reference">Reference</h1>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 28]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-28</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-28</guid>
            <pubDate>Thu, 28 Apr 2022 16:40:07 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h2 id="1-drag--drop-이벤트">1. Drag &amp; Drop 이벤트</h2>
<p>drag와 drop이 되는 간단한 웹 어플리케이션 실습을 진행했다.</p>
<h3 id="1-1draggable-droppable">1-1.draggable, droppable</h3>
<p>기본적으로 html element는 drag를 할 수 없다. 이를 위해서 <code>draggable=&quot;true&quot;</code> 옵션을 드래그 하고싶은 element에 적용해야한다.
!codepen[jochaewoo/embed/wvywBYP?default-tab=html%2Cresult&amp;theme-id=light]
위에서 볼 수 있듯 draggable 설정에 따라 상호작용이 다르게 적용된다. drop의 경우도 마찬가지다. MDN문서의 drop event를 살펴보면 아래와 같이 적혀있다.</p>
<blockquote>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/drop_event">drop</a>
This event is fired when an element or text selection is dropped on a valid drop target.</p>
</blockquote>
<p>위에서 말하는 <strong>valid drop target</strong>이 바로 <code>droppable=&quot;true&quot;</code>인 element를 말하는 것으로 drop event를 사용하기 위해서 droppable attribute의 설정이 필요하다.</p>
<h3 id="1-2-datatransfer">1-2. <a href="https://developer.mozilla.org/ko/docs/Web/API/DataTransfer">dataTransfer</a></h3>
<p>drag event가 동작할 때, 관련 정보를 dataTransfer라는 객체에 저장해서 전달한다. 수업에서는 dataTransfer에 <code>setData()</code>와 <code>getData()</code>로 필요한 정보를 이벤트간에 전달하는 방식으로 사용했다. 데이터의 저장 방식은 로컬 스토리지와 동일한 방식으로 string type의 key와 value를 이용한다. 따라서 Object, Array등의 값을 저장하고 읽어온 값을 사용할 때 <code>JSON.stringify</code>와 <code>JSON.parse</code>를 이용하자. 이 외에도 <code>DataTransfer.dropEffect</code>를 사용해서 드래그 시에 커서의 모양을 바꾸는 예시를 실습했다.</p>
<h3 id="1-3-dragstart---dragover---drop">1-3. dragstart - dragover - drop</h3>
<p>실습에서는 dragstart event에서 지금 drag된 target의 정보를 저장하고, dragover event 동안 <code>DataTransfer.dropEffect</code>로 커서의 모양을 설정하며, drop event에서 저장된 정보로 처리했다. 그리고 dragover와 drop에서 <code>preventDefault()</code>로 기본 동작을 막아줘야 정상 동작했다.</p>
<h2 id="2-task-queue">2. Task Queue</h2>
<h3 id="2-1-서론">2-1. 서론</h3>
<p>실습에서 만든 웹 어플리케이션은 사용자의 상호작용에 의해서 값이 변경되면 변경된 값을 서버에 보내 동기화하고 다시 서버로부터 값을 받아와 화면을 다시 랜더링했다. 하지만 네트워크가 느릴 경우 사용자의 상호작용이 명확하지 않았다. 이를 해결하기 위해서 앞서 배운 낙관적 업데이트를 적용했지만 서버에서 받아온 값들이 밀리면서 랜더링이 부자연스러운 경우가 발생한다. 이 경우 적용할 수 있는 방법이 Task Queue다.</p>
<h3 id="2-2-task-queue">2-2. Task Queue</h3>
<p>Task Queue에 일정 시간동안 API 동작 정보를 저장해 놓은 뒤 한꺼번에 처리하는 방식이다. 이 방식을 사용하면 사용자가 데이터의 수정을 취소한 경우 두 번의 API통신을 생략하는 등 여러 이점이 있을 수 있다. </p>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<ul>
<li>web worker</li>
<li>window.requestIdleCallback()</li>
</ul>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>노션 클로닝 주간동안 TIL에 소홀해 졌더니 관성이 엄청났다...
조금 더 의지가 필요하다.</p>
<hr>
<h2 id="reference">Reference</h2>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 20 ]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-20</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-20</guid>
            <pubDate>Fri, 15 Apr 2022 18:26:51 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h2 id="1-event">1. Event</h2>
<h3 id="이벤트">이벤트</h3>
<p>이벤트는 주로 마우스를 클릭하거나 스크롤을 내리는 등 사용자의 동작에 의해서 발생한다. 우리는 DOM Element에 <code>addEventListener</code>를 사용해 특정 이벤트가 발생할 때, 어떻게 처리할 것인지 이벤트 핸들러를 등록할 수 있다. 하나의 Element에 여러개의 이벤트가 존재할 수 있으며, <code>removeEventListener</code>를 사용해 제거하는 것도 가능하다. 만약 핸들러가 등록된 element에 이벤트가 발생하면, 브라우저는 이벤트에 관련된 세부 내용들을 <code>Event Object</code>에 넣어 핸들러에 전달한다.</p>
<h3 id="이벤트-페이즈">이벤트 페이즈</h3>
<p>이벤트는 3개의 단계(Phase)를 거쳐서 생성되고 소멸한다.</p>
<ul>
<li><p>Capturing Phase
DOM tree의 최상위 요소부터 이벤트가 발생한 target element까지 전파되는 단계.</p>
</li>
<li><p>Target Phase
이벤트가 실제 target element까지 전파되는 단계</p>
</li>
<li><p>Bubbling Phase
이벤트가 target element에서 최상위 element까지 전파되는 단계 
(Capturing Phase와 역순)</p>
</li>
</ul>
<p>아무런 옵션 없이 <code>addEventListener</code>를 사용했다면, 핸들러가 동작한는 단계는 Target Phase와 Bubbling Phase이다. 그리고 만약 capture 옵션이 true라면 Capturing Phase부터 핸들러가 동작한다.</p>
<p><img src="https://velog.velcdn.com/images/jo_cw/post/68fa8a29-f80f-4c91-95d1-983c401fbb96/image.svg" alt="">
위와 같이 3개의 <code>&lt;div&gt;</code> element가 중첩되어 있을 때, div3을 클릭해 이벤트가 발생한 상황을 가정하자. Capturing Phase에서는 div1 - div2 - div3 순서로 이벤트가 전파된다. 이벤트가 발생한 div3에서 Target Phase가 진행되고, 이후 Bubbling Phase에서 div3 - div2 - div1 순서로 이벤트가 전파된다.</p>
<h3 id="이벤트-델리게이션">이벤트 델리게이션</h3>
<p>어떤 element에 이벤트가 발생할 때 실행하고 싶은 코드가 있다면 해당 element에 <code>addEventListener</code>를 사용하는 것이 일반적이다. 하지만 그러한 element가 수가 아주 많다면? 무분별하게 모든 element에 이벤트 핸들러를 할당하면 너무 많은 메모리를 사용하게 되고, 성능면에서도 효율적이지 않다. 이 상황에서 사용할 수 있는 패턴이 바로 이벤트 델리게이션 패턴이다.
이벤트 델리게이션 패턴은 이벤트 버블링을 이용한다. 이벤트 핸들러의 할당이 필요한 여러 element들을 상위 element로 감싸고, 이 상위 element에만 핸들러를 할당한다. 
<img src="https://velog.velcdn.com/images/jo_cw/post/9a5bff8e-d81e-4a69-9524-0823e5a74e61/image.svg" alt="">
위와 같은 element 구조에서 <code>&lt;div&gt;</code> element에 이벤트 핸들러를 할당하면, 4개의 <code>&lt;button&gt;</code>에서 이벤트가 발생해도, 버블링에 의해서 <code>&lt;div&gt;</code>의 이벤트 핸들러가 동작한다. 또한 어떤 하위 element가 target이 되는지 <code>Event Object</code>의 target 프로퍼티에서 확인이 가능하다.</p>
<pre><code class="language-html">&lt;div id=&quot;button-container&quot;&gt;
  &lt;button id=&quot;button1&quot;&gt;Button1&lt;/button&gt;
  &lt;button id=&quot;button2&quot;&gt;Button2&lt;/button&gt;
  &lt;button id=&quot;button3&quot;&gt;Button3&lt;/button&gt;
  &lt;button id=&quot;button4&quot;&gt;Button4&lt;/button&gt;
&lt;/div&gt;</code></pre>
<pre><code class="language-js">const $div = document.querySelector(&#39;#button-container&#39;);

$div.addEventListener(&#39;click&#39;, (e) =&gt; {
  const $targetElement = e.target;
  if ($targetElement.id === &quot;button1&quot;) {
    // do something
  } else if ($targetElement.id === &quot;button2&quot;) {
    // do something
  } 
  ...
});</code></pre>
<p>위의 코드는 이벤트 델리게이션을 사용한 예시이다. 이렇게 이벤트 델리게이션 패턴을 사용하면 여러개의 이벤트를 하나의 핸들러에서 처리하는 것이 가능하다.</p>
<h3 id="이벤트-디바운스">이벤트 디바운스</h3>
<p>이벤트 디바운스는 이벤트 핸들러의 동작을 조절하는 기법 중 하나이다. 동일한 이벤트가 짧은 간격으로 여러번 발생할 때, 일정 시간동안 이벤트의 처리를 미루고 일정 시간이 지나도 이벤트가 발생하지 않았다면 가장 마지막 이벤트에 대해서만 처리가 이뤄진다.</p>
<blockquote>
<p>자동 저장 기능을 가진 문서 편집기를 구현한다고 생각해 보자. 문서의 내용이 바뀔 때마다 이벤트를 발생시켜 변경된 내용을 저장한다면 한 글자 입력할 때 마다 이벤트 핸들러가 동작한다. <em>&quot;안녕하세요&quot;</em> 같이 단순한 문자를 입력할 때도, 별도의 처리가 없을 경우 이벤트 핸들러는 12번 동작한다. 만약 저장이 API를 통해서 이루어 진다면 더더욱 큰 성능 저하가 일어날 것이다.</p>
</blockquote>
<p>이벤트 디바운스는 <code>setTimeout</code>과 <code>clearTimeout</code>을 이용해서 구현한다.</p>
<pre><code class="language-js">let timer = null;
const delay = 2000;
$element.addEventListener(&#39;change&#39;, (e) =&gt; {
    if(timer !== null) {
        clearTimeout(timer);
    }
      time = setTimeout(() =&gt; {
        //do something
    }, delay)
});</code></pre>
<p>이벤트가 발생하면 <code>setTimeout</code>이 실행되며, 타이머가 <code>delay</code>에 해당하는 시간이 지났을 때 실행하고자 하는 내용의 코드가 동작할 것이다. 하지만 정해놓은 시간이 지나기 전에 동일한 이벤트가 발생한다면 <code>clearTimeout</code>에 의해서 이전의 타이머는 취소되고 새로운 타이머가 처음부터 시작한다.</p>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<ul>
<li><code>dispatchEvent</code>와 커스텀 이벤트</li>
<li>이벤트 쓰로틀</li>
</ul>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>노션 클로닝 프로젝트 주간이라 TIL을 꾸준히 적지 못하고있다. 프로젝트에 대해서도 생각할 일이 많아지고 필요한 부분만 찾아서 쓰다보니 공부한 내용에 대해서 정리가 어렵다. 다시 마음을 다잡고 이벤트부터 찬찬히 정리를 해봤는데, 적지 못한 내용이 대부분일 정도로 그 범위가 너무 넓고 깊다. 역시 공부는 끝이 없다.😅</p>
<hr>
<h2 id="reference">Reference</h2>
<ol>
<li><p>프로그래머스 프론트엔드 데브코스</p>
</li>
<li><p>JAVASCRIPT.INFO, 브라우저 이벤트 소개
<a href="https://ko.javascript.info/introduction-browser-events">https://ko.javascript.info/introduction-browser-events</a></p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 14]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-14</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-14</guid>
            <pubDate>Thu, 07 Apr 2022 16:48:30 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h3 id="1-fetch">1. fetch</h3>
<h4 id="비동기-http-request를-쓰기-편하게-해주는-api">비동기 http request를 쓰기 편하게 해주는 API.</h4>
<pre><code class="language-js">fetch(url).then(res =&gt; res.json())</code></pre>
<ul>
<li><p>실행 동작
fetch는 실행 결과로 <strong>Promise</strong>를 return하며 fulfilled 상태가 되면 <strong>Response</strong> 객체를 결과 값으로 갖는다.</p>
</li>
<li><p>메서드</p>
</li>
<li><p><em>Response*</em> 객체의 메소드 중 주로 사용되는 것으로는 JSON으로 파싱해서 반환하는 <code>.json()</code>, 텍스트 그대로 반환하는 <code>.text()</code>, 그리고 이미지를 url 형식으로 변환해서 반환하는 <code>.blob()</code> 등이 있다. 그리고 모든 메서드는 결과를 <strong>Promise</strong>로  감싸서 반환한다.</p>
</li>
<li><p>주의점
fetch API는 HTTP error가 발생해도 reject하지 않는다. 따라서 fetch를 사용할 때, <code>catch</code>를 사용하는 것 이외에도 방어코드의 작성이 필요하다. 일반적으로 Response 객체의 프로퍼티 <code>ok</code>와 <code>status</code>를 확인하여 HTTP error를 처리한다.
  추가적으로 <code>ok</code> 프로퍼티는 <code>status</code>가 200번대의 값에서만 true이다. 300번대의 <code>status</code>가 필요한 특수한 상황에서는 <code>ok</code>의 값 대신 <code>status</code>를 확인하는 것이 좋다.</p>
</li>
</ul>
<h3 id="2-history-api">2. history API</h3>
<p>브라우저에서 페이지를 로딩할 때마다 세션 히스토리가 생기며, 페이지를 이동할 때마다 사라지지 않고 쌓이게 된다. 이를 이용해서 우리는 &#39;앞으로 가기&#39;, &#39;뒤로 가기&#39; 등의 기능을 이용할 수 있는 것이다. 이를 이용하여 SPA(Single Page Application)를 만드는 것이 가능하다.</p>
<ul>
<li><p><code>history.pushState(state, title, url)</code>
state : history가 변경이 된 이후에도 필요한 값을 넣는다. 이후 history.state를 이용해 사용이 가능하다.
title : 대부분의 브라우저에서 지원하지 않는 값. 주로 null string을 넣는다.
url : 세션 히스토리에 새로 추가할 url값. history를 이용해서 url을 변경하면 화면이 리로드 되지 않는다.</p>
</li>
<li><p><code>history.replaceState(state, title, url)</code>
<code>pushState</code>의 경우 기존 히스토리 위에 새로운 히스토리를 추가하지만, <code>replaceState</code>의 경우 현제 히스토리를 대체한다. 이용자의 상태에 따라서 뒤로가기로 다시 접근할 필요가 없는 경우에 사용한다.(로그인 화면 등)</p>
</li>
</ul>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<p>CSR, SSG, ISR</p>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>점차 코드의 양이 많아지고 이를 관리하는 것이 어렵다. 3주차 과제도 validation 확인 등 얼마나 세부적인 부분까지 확인해야 하지? 등 여러가지 생각할 점이 많다. 실무에서도 이와 같은 문제점이 분명 있을 것이다. 확실하게 이를 해결하는 노하우를 지금부터 익혀보자.</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 12]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-12</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-12</guid>
            <pubDate>Tue, 05 Apr 2022 18:14:14 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h3 id="1-모듈">1. 모듈</h3>
<p>10일차에 컴포넌트 방식의 설계를 하면서 실습했던 Simple Todo List는 여러 컴포넌트를 <code>html</code> 안의 <code>&lt;script src=&quot;&quot;&gt;</code>를 이용해서 외부 JS파일을 로딩했는데, 이 때 강조했던 부분이 파일간의 의존성이다. 만약 App.js파일에서 TodoList.js와 TodoForm.js 파일의 함수를 사용한다면 반드시 App.js파일의 스크립트를 읽어오기 전에 TodoList.js와 TodoForm.js를 읽어와야 한다. 이를 고려하지 않고 <code>html</code>을 작성하면 아래와 같은 오류를 직면하게 된다.
<img src="https://velog.velcdn.com/cloudflare/jo_cw/1a518394-0129-474d-8628-12f5b735a410/image.png" style="margin-bottom:0px; margin-top:15px">
하지만 파일이 많아질 수록 파일간의 스크립트 의존성 파악이 더욱 힘들어지며, 이를 더 간편하게 관리할 수 있도록 해주는 것이 모듈이다.</p>
<h4 id="사용법">사용법</h4>
<p>다른 파일에서 <code>export</code>를 통해 내보내진 변수, 함수 등을 <code>import</code> 명령어를 이용해서 불러온다. 변수나 함수는 하나 또는 그 이상일 수 있으며, 사용 방식에 따라서 어떤 스크립트를 불러올지 정할 수 있다.
아래는 그 예시이다.</p>
<pre><code class="language-js">// 파일 안의 모든 정보를 불러올 때
import * from &quot;./src/storage.js&quot;

// 파일 안에 export default로 설정된 함수 또는 변수를 불러올 때
import TodoList from &quot;./src/TodoList.js&quot;

// 파일의 일부를 불러올 때
import { getItem } from &quot;./src/storage.js&quot;

// 파일의 일부를 다른 이름으로 사용할 때
import { getItem as g } from &quot;./src/storage.js&quot;

// export default로 설정된 것과 추가로 다른 일부분을 불러올 때
import TodoList, { util } from &quot;./src/TodoList.js&quot;</code></pre>
<h3 id="2-비동기-처리">2. 비동기 처리</h3>
<h4 id="2-1-비동기-처리란">2-1. 비동기 처리란</h4>
<p>어떤 코드를 즉시 처리할 수 없을 때, 처리가 끝날 때까지 기다리지 않고 그 동안 다음 코드를 우선 수행하는 처리방식. <code>addEventListener</code>, <code>setTimeout</code> 등이 대표적이다.</p>
<h4 id="2-2-callback-방식">2-2. callback 방식</h4>
<p>callback 방식은 비동기 처리한 결과물을 callback 함수에 넘겨서 다음 동작을 진행하는 비동기 처리방식이다. 예를 들어 비동기로 id를 입력받아 name을 가져오고 그 text를 console에 출력해야 한다고 가정하면 아래와 같을 것이다.</p>
<pre><code class="language-js">    // id를 입력받아 비동기로 name을 가져오는 함수
    getNameById(id, (name) =&gt; {
      console.log(name);
    });</code></pre>
<p>callback 방식은 callback hell이라는 용어가 존재할 만큼 비동기 처리한 데이터를 계속해서 비동기로 처리할 때 가독성이 좋지않다. 예를 들어 id로 name을 찾고 name으로 주소를 찾고, 주소를 이용해서 우편번호를 찾는다고 한다면?</p>
<pre><code class="language-js">    getNameById(id, (name) =&gt; {
      getAddressByName(name, (address) =&gt; {
          getCodeByAddress(address, (code) =&gt; {
            console.log(code);
        });
      });
    });</code></pre>
<p>이렇게 처리과정이 늘어날수록 코드의 구조를 이해하는 것이 어려워진다.</p>
<h4 id="2-3-promise">2-3. Promise</h4>
<p>Promise는 비동기 처리를 체인 형식으로 제어할 수 있게하는 객체다. Promise에는 비동기 처리 상태를 나타내는 PromiseStatus와 처리 결과인 PromiseResult로 구성된다. Status는 비동기 처리가 정상적으로 끝난 <code>fulfilled</code>, 비동기 처리가 끝나지 않고 진행중인 <code>pending</code>, 비정상으로 종료된 <code>rejected</code> 세 가지 중 하나다.</p>
<p>Promise 객체에 <code>then</code> 명령어를 이용해서 다음 동작을 지정하는 것이 가능하다. <code>then</code> 위의 callback에서의 코드를 Promise 객체를 이용해서 작성하면 아래와 같다.</p>
<pre><code class="language-js">// 모든 get 함수가 Promise 객체를 return한다고 가정할 때.
    const code = new Promise((resolve, reject) =&gt; resolve(getNameById(id)))
        .then((result) =&gt; {
          return getAddressByName(result)
        }).then((result) =&gt; {
          return getCodeByAddress(result)
        }).then((result) =&gt; {
          console.log(result)
        });
</code></pre>
<h4 id="promise의-내장함수">Promise의 내장함수</h4>
<ul>
<li><p><code>catch</code>
try-catch 구문과 비슷한 역할. rejected 상태의 Promise가 반환되는 경우 catch에 있는 코드가 실행된다.</p>
</li>
<li><p><code>finally</code>
Promise의 상태에 상관없이 모든 비동기 처리가 끝난 이후에 finally에 있는 코드가 실행된다. </p>
</li>
<li><p><code>Promise.all</code>
입력받은 모든 Promise를 순차적으로 실행한다.</p>
</li>
<li><p><code>Promise.race</code>
입력받은 모든 Promise를 동시에 실행한다. 이들 중 가장 먼저 종료된 결과를 반환한다. (reject, resolve 상관 없이)</p>
</li>
<li><p><code>Promise.any</code>
입력받은 모든 Promise를 동시에 실행한다. 이들 중 가장 먼저 resolve한 Promise 결과를 반환한다.</p>
</li>
<li><p><code>Promise.allSettled</code>
입력받은 모든 Promise의 실행 결과를 배열에 담아서 반환한다.</p>
</li>
<li><p><code>Promise.resolve</code>
status가 fulfilled, result가 입력받은 값인 Promise를 반환한다.</p>
</li>
<li><p><code>Promise.reject</code>
status가 rejected, result가 입력받은 값인 Promise를 반환한다.</p>
</li>
</ul>
<h4 id="2-4-async-await">2-4. async, await</h4>
<p>async와 await은 Promise를 이용하는 또 다른 비동기 처리방식이다. </p>
<ul>
<li><p><code>async</code> 명령어를 함수의 이름 앞에 붙이면 기존에 반환하던 값을 Promise에 감싸서 return한다.</p>
</li>
<li><p><code>await</code> 명령어는 async function 내부에서만 사용가능한 명령어다. <code>await</code>은 Promise가 전부 처리될 때까지 기다리기 때문에 일반적인 동기 코드와 동일하게 위에서 아래로 순서대로 실행된다.</p>
</li>
<li><p>만약 Promise가 reject된다면 try-catch를 이용해서 오류를 처리할 수 있다.</p>
</li>
</ul>
<p>아래는 지금까지 예시로 들었던 코드를 <code>async</code>와 <code>await</code>을 사용해서 작성한 것이다.</p>
<pre><code class="language-js">  // 모든 get 함수가 Promise 객체를 return한다고 가정할 때.
  const getCodeById = async (id) =&gt; {
    const name = await getNameById(id);
    const address = await getAddressByName(name);
    const code = await getCodeByAddress(address);
    return code;
  };</code></pre>
<p>이처럼 <code>async</code>와 <code>await</code>을 이용하면 더욱 가독성이 좋은 비동기 처리코드를 작성하는 것이 가능하다. </p>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<p>비동기 처리, 함수형 프로그래밍에서의 비동기 처리</p>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>3주차로 넘어오면서 확실히 배우는 양과 공부할 내용이 더 많다. 비동기 처리는 익숙하지도 않고 중요하게 느껴져서 확실하게 정리해야겠다. 아직 함수형 프로그래밍 강의도 전부 듣고 정리하지 못했고, 새로나온 과제도 완성하지 못했다. 다음주는 악명높은 노션클로닝 기간이다. 이번주에 최대한 많이 해놓아야 한다. </p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 11]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-11</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-11</guid>
            <pubDate>Mon, 04 Apr 2022 17:39:00 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h3 id="1-컴포넌트-방식">1. 컴포넌트 방식</h3>
<p>하나의 큰 기능을 구현할 때, 작은 기능 단위(컴포넌트)로 분리해서 구현하는 방식. 컴포넌트를 구성할 때는 재사용성에 영향이 없도록 다른 컴포넌트에 의존하지 않도록 만드는 것이 중요하다. 하나의 컴포넌트에서 다른 컴포넌트로 값을 전달하고 처리해야한다면 콜백함수를 사용할 수 있다. 컴포넌트는 어떤 컴포넌트에게 값을 전달하는지 모르는 상태에서 값의 처리를 전적으로 콜백함수에 맡긴다.</p>
<h3 id="2-쿠키">2. 쿠키</h3>
<ul>
<li>브라우저에 저장되는 작은 문자열, key=value의 형태로 document.cookie에 저장되어있다. </li>
<li>각각의 key-value쌍은 세미콜론으로 구분되어 있어 cookie의 값을 이용할 때 split을 이용해 사용할 수 있다. </li>
<li>유효기간이 설정되어 있지 않으면 브라우저 종료시 사라지며, 유효기간은 GMT 시간을 사용한다.</li>
<li>HTTP request시에 쿠키값이 헤더에 포함된다. 따라서 쿠키값이 커진다면 요청의 부하가 커진다.</li>
<li>여러가지 보안취약점에 유의해야 한다. (XSS, CSRF 등)</li>
</ul>
<h3 id="3-로컬-스토리지">3. 로컬 스토리지</h3>
<ul>
<li>key-value 쌍으로 로컬에 데이터를 저장할 수 있게 만든 저장공간</li>
<li>도메인 기반으로 Storage가 생성된다.
(동일한 도메인을 여러 탭에서 이용하는 경우 스토리지 공유가 가능하다.)</li>
<li>별도의 동작으로 삭제하지 않는다면 브라우저를 꺼도 데이터가 유지된다.</li>
<li><code>window.localstorage</code>에 <code>setItem(key) = value</code>, <code>getItem(key)</code>, <code>removeItem(key)</code>, <code>clear()</code> 함수를 이용해서 데이터를 관리한다.</li>
<li>모든 <code>value</code>값은 <code>string</code>으로 저장되며 <code>Object</code>나 <code>Array</code> 등을 저장할 때는 <code>JSON.stringify()</code>를 이용하고, 값을 읽어올 때는 <code>JSON.parse()</code>를 이용하는 것이 좋다.</li>
<li>로컬 스토리지를 이용할 때, 외부에서 악의적으로 데이터의 조작이 가능한 것을 고려하자. <code>try-catch</code>를 이용한다면 더욱 안전한 코드를 짤 수 있다.</li>
</ul>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<p>컴포넌트 패턴, 디자인 패턴</p>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>컴포넌트 방식으로 구성을 할 때, 어느 정도의 기능까지 나누는 것이 적당한지 정하는 것이 많이 어렵다. 이 부분을 중심으로 코드리뷰를 받아봐야겠다. 요즘 TIL을 자주 빼먹었다. 끝까지 완주하려는 마음가짐으로 다시한번 의지를 다잡자.</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 9]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-9</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-9</guid>
            <pubDate>Thu, 31 Mar 2022 19:12:16 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h3 id="1-선언형-프로그래밍">1. 선언형 프로그래밍</h3>
<ul>
<li><p>명령형 프로그래밍
데이터를 다룰 때 어떠한 과정을 거쳐서 결과를 도출하는지에 집중하는 방식.</p>
</li>
<li><p>선언형 프로그래밍
데이터의 처리나 순서보다 실행 후의 결과가 목적이 되는 방식.</p>
</li>
<li><p>선언형과 명령형
선언형의 대표적인 언어가 바로 HTML이다. 우리는 웹 페이지의 구성요소들이 어떠한 과정을 거쳐서 화면에 표시되는지 알지 못하지만 우리가 원하는 대로 화면을 구성할 수 있다.</p>
<pre><code class="language-js">//명령형 프로그래밍 예시
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let even = [];
for(let i = 0; i &lt; arr.length; i++) {
  if(arr[i] % 2 === 0) {
    even.push(arr[i]);
  }
}

//선언형 프로그래밍 예시
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let even = arr.filter(a =&gt; a % 2 === 0);</code></pre>
<p>위의 코드가 또다른 예시이다. 명령형 프로그래밍에서 우리는 어떻게 arr의 원소를 순회할지, 순회를 멈추는 조건이 무엇인지, 각 원소를 어떤 조건에 따라서 처리할지 모든 과정을 나열한다. 반면, 선언형 프로그래밍에서는 원하는 결과를 나타낼 뿐이다.</p>
</li>
</ul>
<h3 id="2-지연-평가">2. 지연 평가</h3>
<p>지연 평가는 제너레이터를 이용하여 리스트를 다루는 기법 중 하나이다. 제너레이터는 앞서 배운 내용대로 미리 계산하지 않고 이터레이터의 <code>next()</code>의 호출이 있을 때 다음 값을 평가한다. 제너레이터를 이용해서 기존의 <code>range()</code>와 <code>map()</code>, <code>filter()</code> 함수를 지연 평가되는 <code>L.range()</code>, <code>L.map()</code>, <code>L.filter()</code> 함수를 선언했다. 이 함수를 <code>go()</code> 함수를 이용해서 순차적으로 실행할 때, 기존의 함수와 다른 순서로 동작한다.</p>
<pre><code class="language-js">go(range(12),
   map(a =&gt; a + 10),
   filter(a =&gt; a % 2 === 0),
   take(4)
  );

go(L.range(12),
   L.map(a =&gt; a + 10),
   L.filter(a =&gt; a % 2 === 0),
   take(4)
  );
// take() 함수는 이터러블을 입력받아 지정된 개수만큼의 원소를 반환하는 함수이다.</code></pre>
<p><img src="https://images.velog.io/images/jo_cw/post/edc8dafa-642e-4355-80d6-3cf8211d4761/lazy.svg" alt=""></p>
<p>위의 그림은 <code>go()</code> 내부에 있는 함수가 실행되는 순서를 간단하게 시각화 한 것이다. 일반 함수에서는 위에서 아래순서(range - map - filter - take)로 한 함수의 모든 연산이 끝나고 난 뒤에 다음 함수로 넘어간다. 마지막의 <code>take()</code> 함수로 인해서 4개의 결과만을 필요로 하지만 12개의 데이터를 전부 평가한다. 반면 지연 평가가 적용된 함수의 경우 <code>take()</code> 함수부터 실행되며, 이터레이터의 <code>next()</code>가 호출될 때 위에 위치한 함수(take - filter - map - range)에 값을 요청한다. 요청이 최종적으로 <code>range()</code>까지 도달하면 가장 위에있는 <code>range()</code>에서 값을 평가한 뒤 다시 아래로 반환한다. 이 과정을 통해서 단 하나의 값이 전달되며, 이 일련의 과정이 <code>take()</code>가 요구하는 4개의 결과를 충족하면 끝난다. 이런 동작 방식은 그림에서도 알 수 있듯, 더 적은 연산으로 동일한 결과를 얻을 수 있으며, 리스트나 이터러블의 길이가 길 수록 더 많은 시간을 줄일 것이다.</p>
<hr>
<h2 id="📝-더-공부할-것">📝 더 공부할 것</h2>
<ul>
<li>지연 평가를 실제로 실무에서 이용하는 사례</li>
<li>실제 프로젝트에서의 선언형 프로그래밍 패러다임</li>
</ul>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>함수형 프로그래밍이나 선언형 프로그래밍에 대해서 공부할 수록 실제 업무에서 응용하는 방식이 궁금해진다. 프론트엔드에서 많은 양의 데이터를 처리할 일이 있을지는 몰라도 확실히 습득하고 이용할 수 있으면 좋을 것 같다.</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 8]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-8</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-8</guid>
            <pubDate>Wed, 30 Mar 2022 16:40:47 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-공부한-내용">📚 공부한 내용</h2>
<h3 id="1-dom">1. <a href="https://velog.io/@jo_cw/DOM">DOM</a></h3>
<p>문서 객체 모델 (Document Object Model), HTML의 문서에 접근하기 위한 모델. 트리의 구조를 하고있다.</p>
<h3 id="2-javascript-기본-역량">2. Javascript 기본 역량</h3>
<p>Javascript를 이용할 때 주의해야 할점.</p>
<ul>
<li>this 사용 
this를 사용할 때 this가 가리키고 있는 것이 무엇인지 확인하자, bind를 이용할 수도 있다.</li>
<li>전역 사용
전역(window)을 오염시키면 원하지 않은 side effect가 발생할 수 있다.</li>
</ul>
<hr>
<h2 id="📝추가로-공부할-것">📝추가로 공부할 것</h2>
<ul>
<li><code>document.createDocumentFragment</code></li>
<li>XSS (Cross Site Scripting)</li>
</ul>
<hr>
<h2 id="🤔-느낀점">🤔 느낀점</h2>
<p>사전 테스트 문제 이용 시간을 앞당겨 주셔서 하루 일찍 봤다. 문제를 풀면서 앞서 공부했던 내용을 보게되어 약간의 보람을 느꼈지만... 이후 더 큰 절망을 맛봤다. 대충 내가 어느 정도인지 확인하는 시험이었지만 아쉬움이 있는 시험이었다. 하지만 그만큼 더 배울 것이 많다는 점이 더 기대가 되기도 한다. 알고리즘과 자료구조도 끝났고 본격적으로 프론트엔드에 대해 공부해서 내 것으로 만들자!</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DOM]]></title>
            <link>https://velog.io/@jo_cw/DOM</link>
            <guid>https://velog.io/@jo_cw/DOM</guid>
            <pubDate>Wed, 30 Mar 2022 10:06:55 GMT</pubDate>
            <description><![CDATA[<h2 id="1-dom의-뜻">1. DOM의 뜻</h2>
<p>문서 객체 모델 (Document Object Model), HTML의 문서에 접근하기 위한 모델. 트리의 구조를 하고있다.</p>
<h2 id="2-dom의-구성">2. DOM의 구성</h2>
<p><img src="https://images.velog.io/images/jo_cw/post/15090500-e57b-4261-a9f7-66442b0b1152/image.png" alt=""></p>
<ul>
<li><p>문서 노드 (document)
DOM 트리의 최상위 노드. DOM에 접근하기 위해서는 반드시 거쳐야한다.</p>
</li>
<li><p>요소 노드 (Element)
HTML의 tag에 대응하는 노드. (h1, div, img 등)</p>
</li>
<li><p>속성 노드 (Attribute)
요소 노드의 속성을 나타내는 노드.** 요소 노드의 자식 노드가 아니다**.</p>
</li>
<li><p>텍스트 노드
요소 노드 안의 문자들을 저장하는 노드. 자식 노드를 가질 수 없어 단말 노드가 된다.</p>
<h2 id="3-dom관련-js-명령어">3. DOM관련 JS 명령어</h2>
<h3 id="3-1-dom-선택">3-1. DOM 선택</h3>
<ul style="list-style-type: circle;">
<li><code>getElementById</code></li>
DOM Tree에서 입력과 동일한 id를 가진 요소 노드를 탐색한다. 가장 먼저 찾은 요소 하나를 반환한다.<br><br>
<li><code>getElementByClassName</code></li>
DOM Tree에서 입력과 동일한 class name을 가진 요소 노드를 탐색한다. 일치하는 모든 요소를 List로 반환한다.<br><br>
<li><code>getElementByTagName</code></li>
DOM Tree에서 입력과 동일한 tag name을 가진 요소 노드를 탐색한다. 일치하는 모든 요소를 List로 반환한다.<br><br>
<li><code>querySelector</code></li>
DOM Tree에서 CSS Selector 문법을 이용해 요소 노드를 탐색한다. 가장 먼저 찾은 요소 하나를 반환한다.<br><br>
<li><code>querySelectorAll</code></li>
querySelector와 동일한 방식으로 탐색한다. 찾은 모든 요소를 List로 반환한다.<br><br>
<li><code>window</code> 객체 이용</li>
<code>window.id</code> 또는 <code>window[id]</code>와 같은 방법으로 <code>window</code> 객체에 id로 접근이 가능하다. 해당 id를 가진 노드가 여러개라면 List로 반환된다. 
</ul>

</li>
</ul>
<h3 id="3-2-dom-탐색">3-2. DOM 탐색</h3>
<p>위의 방법을 이용해 얻은 DOM 노드를 탐색에 이용이 가능하다.</p>
<p><img src="https://images.velog.io/images/jo_cw/post/5e92112a-a67b-45af-b150-09621d58bbdc/%EA%B7%B8%EB%A6%BC1.svg" alt=""></p>
<ul style="list-style-type: circle;">
  <li><code>parentNode</code></li>
  선택한 요소의 부모 노드를 불러온다.<br><br>

  <li><code>firstElementNode</code></li>
  선택한 요소의 자식 노드 중 가장 첫 번째 노드를 불러온다. 자식 노드가 없을 경우 <code>null</code>을 반환한다.<br><br>

  <li><code>lastElementNode</code></li>
  선택한 요소의 자식 노드 중 가장 마지막 노드를 불러온다. 자식 노드가 없을 경우 <code>null</code>을 반환한다.<br><br>

  <li><code>children</code></li>
  선택한 요소의 모든 자식 노드를 배열로 반환한다. 자식 노드가 없을 경우 빈 배열을 반환한다.<br><br>

  <li><code>nextElementSibling</code></li>
  선택한 요소의 다음 형제 노드 (Sibling Node)를 가져온다. 없을 경우 <code>null</code>을 반환한다.<br><br>

  <li><code>previousElementSibling</code></li>
  선택한 요소의 이전 형제 노드를 가져온다. 없을 경우 <code>null</code>을 반환한다.<br><br>

</ul>

<h3 id="3-3-dom-조작">3-3. DOM 조작</h3>
<ul style="list-style-type: circle;">
  <li><code>className</code>, <code>classList</code></li>
  선택한 요소 노드의 class 속성을 불러오고, 이를 이용해 class 속성의 변경 또한 가능하다.<br><br>

  <li><code>hasAttribute</code></li>
  선택한 요소 노드의 속성이 존재하는지 확인한다. <code>boolean</code> 값을 반환한다.<br><br>

  <li><code>getAttribute</code></li>
  선택한 요소 노드의 속성의 값을 반환한다. 해당 속성이 없다면 <code>null</code>을 반환한다. <br><br>

  <li><code>setAttribute</code></li>
  선택한 요소 노드의 속성의 값을 정의한다.<br><br>

  <li><code>removeAttribute</code></li>
  선택한 요소 노드의 속성을 제거한다.<br><br>

  <li><code>textContent</code></li>
  선택한 요소 노드에서 텍스트 노드에 접근하고 변경할 수 있다.<br><br>

  <li><code>innerHTML</code></li>
  선택한 요소 노드의 내부 HTML을 직접 수정한다. XSS(Cross Site Scripting)의 위험이 있다.<br><br>

  <li><code>creatElement</code></li>
  입력받은 태그에 해당하는 새로운 요소 노드를 생성한다.<br><br>

  <li><code>appendChild</code></li>
  입력받은 요소 노드를 선택한 요소 노드의 마지막 child node로 추가한다.<br><br>

  <li><code>removeChild</code></li>
  입력받은 요소 노드를 선택한 요소 노드의 child node에서 제거한다.<br>
  <br><br>

</ul>

<h2 id="4-redering">4. Redering</h2>
<p><img src="https://images.velog.io/images/jo_cw/post/7c7d0d3b-f915-44cd-b159-60714d7bc4f0/image.png" alt="">
브라우저는 우리에게 화면을 보여주기까지 다음과 같은 과정을 거친다.</p>
<ol>
  <li>HTML 문서를 HTML Parser가 파싱해서 DOM Tree를 생성한다.</li>
  <li>CSS 문서를 CSS Parser가 파싱해서 Style Rules을 생성한다.</li>
  <li>Style Rules의 정보를 DOM Tree에 추가하여 Render Tree를 생성한다. 이 과정을 Attachment라고 한다.</li>
  <li>Layout 또는 Reflow를 거쳐 현제 표시하려는 화면의 크기에 맞게 노드들의 정확한 위치와 크기를 계산한다.</li>
  <li>계산 결과를 이용해서 최종적으로 화면이 표시된다.</li>
</ol>

<h2 id="5-virtual-dom">5. Virtual DOM</h2>
<p>위에서 설명한 렌더링 과정을 javascript 등에 의해서 DOM이 변경될 때마다 반복한다. 하나의 노드의 변경에도 DOM tree 전체를 파싱하고 새로운 Render Tree를 생성하는 것이다. 이 과정은 경우에 따라서 큰 부하로 작용하며, 이에 대응하는 방식이 Virtual DOM이다. Virtual DOM은 DOM의 노드 정보 중 일부를 복사해 만든, 이름 그대로 가상의 DOM이다. 만일 하나의 기능 동작에 DOM의 변경이 여러 번 발생한다면, 기능이 끝나기 전의 변경을 Virtual DOM에만 적용하고 끝난 이후 최종 결과만을 실제 DOM에 적용해서 Render Tree의 재생성 횟수를 줄인다.</p>
<h2 id="reference">Reference</h2>
<ol>
<li>프로그래머스 프론트엔드 데브코스</li>
<li>위키백과, 문서 객체 모델
<a href="https://ko.wikipedia.org/wiki/%EB%AC%B8%EC%84%9C_%EA%B0%9D%EC%B2%B4_%EB%AA%A8%EB%8D%B8">https://ko.wikipedia.org/wiki/%EB%AC%B8%EC%84%9C_%EA%B0%9D%EC%B2%B4_%EB%AA%A8%EB%8D%B8</a></li>
<li>hashnode, Why Virtual DOM
<a href="https://hashnode.com/post/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-cisczhfj41bmssp53mvfwmgrq">https://hashnode.com/post/the-one-thing-that-no-one-properly-explains-about-react-why-virtual-dom-cisczhfj41bmssp53mvfwmgrq</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 7]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-7</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-7</guid>
            <pubDate>Tue, 29 Mar 2022 17:47:43 GMT</pubDate>
            <description><![CDATA[<h2 id="공부한-내용">공부한 내용</h2>
<h3 id="1-동적프로그래밍">1. 동적프로그래밍</h3>
<p>한 지점까지 탐색한 정보를 바탕으로 다음 상태의 최적해를 구하는 알고리즘. 이전의 정보를 저장해놓는 메모이제이션, 앞으로 사용할 정보를 미리 계산하는 타뷸레이션 두 방식이 존재한다. 코딩 테스트에서는 주로 메모이제이션을 이용하며, 이로 인해 메모리 공간을 많이 사용하지만 탐색 시간이 빠른 것이 장점이다. 가장 전형적인 동적프로그래밍 문제로 피보나치 수열이 있다. </p>
<blockquote>
<p>피보나치 수,
$f(1) = 1, f(2) = 1$의 초기조건과 $f(n) = f(n-1) + f(n-2)$의 규칙을 가지는 수열. 이전 값 $f(n-1), f(n-2)$을 메모이제이션 했다면 $f(n)$값을 알 수 있다.</p>
</blockquote>
<p>위와 같이 초기조건을 지정할 수 있고, 초기 조건을 바탕으로 다음 값을 알아낼 수 있다면 동적프로그래밍으로 해결 할 수 있는 문제인지 고려해보는 것이 좋다.</p>
<h3 id="3-html과-css">3. HTML과 CSS</h3>
<ul>
<li>HTML
HyperText Markup Language, 웹 문서를 표현하기 위한 구조(Structure)와 의미(Sementic)를 태그를 이용해 저장하는 마크업 언어이다. 과거 HTML과 CSS가 분리되기 이전에는 문서의 서식과 관련된 태그도 존재했지만, 이 역할을 CSS가 맡게되면서 점차 사라졌다.</li>
<li>CSS
Cascading Style Sheets, HTML 문서의 표현 방식에 대해서 기술하는 언어다. 어디에 적용하는 지를 나타내는 Selector, 어떤 속성을 기술할지 나타내는 Property, 그 속성을 어떻게 적용할지 나타내는 Value, 총 3개의 구조로 나타낼 수 있다.</li>
</ul>
<h3 id="4-함수형-프로그래밍">4. 함수형 프로그래밍</h3>
<p>앞서 배운 map, reduce, filter를 적절하게 조합하면 하나의 이터러블로 부터 자신이 원하는 값을 얻을 수 있다. 또한 이 조합을 함수로 선언하여 코드의 재사용성을 높힐 수 있다.</p>
<pre><code class="language-javascript">const iter = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const powerSum = pipe(
  map(a =&gt; a*a),
  reduce((a, b) =&gt; a + b)
  );
console.log(powerSum(iter)) // 285</code></pre>
<p>위의 코드에서 <code>powerSum</code>은 이터러블의 모든 요소의 제곱을 더한 값을 출력하는 함수이다. 그런데 만약 모든 요소의 제곱근의 총합을 구하는 <code>sqrtSum</code>을 구현해야 한다면 어떨까?</p>
<pre><code class="language-javascript">const sqrtSum = pipe(
  map(a =&gt; Math.sqrt(a)),
  reduce((a, b) =&gt; a + b)
  );</code></pre>
<p>이렇게 구현한 두 개의 함수는  공통의 코드 부분이 너무 많다. 따라서 각 요소를 처리하는 map 부분을 입력받는 함수에 맡겨서 다형성을 높일 수 있다.</p>
<pre><code class="language-javascript">const add = (a, b) =&gt; a + b;
const optionalSum = (opt, param) =&gt; go(
  param,
  map(opt),
  reduce(add)
  );

//sqrtSum
const sqrtSum = optionalSum(a =&gt; Math.sqrt(a), iter);

//powerSum
const powerSum = optionalSum(a =&gt; a * a, iter);
</code></pre>
<p>위와 같이 함수 <code>opt</code>의 입력에 따라 <code>powerSum</code> 또는 <code>sqrtSum</code>의 동작을 하며 중복된 부분을 최소화 할 수 있다. 또한 currying을 통해서 더 가독성이 좋은 함수를 만드는 것이 가능하다.</p>
<pre><code class="language-javascript">const optionalSum = curry((opt, param) =&gt; go(
  param,
  map(opt),
  reduce(add)
  ));
const powerSum = optionalSum(a =&gt; a * a);
console.log(powerSum(iter));</code></pre>
<hr>
<h2 id="다시-볼-내용">다시 볼 내용</h2>
<p>CSS selector, CSS의 id와 class의 차이점, 동적프로그래밍 문제풀이</p>
<hr>
<h2 id="느낀점">느낀점</h2>
<p>오늘은 오랜만에 답안이나 해설없이 실습을 스스로 풀었다. 효용성에서 약간 막히는 부분이 있어서 시간을 좀 썼지만 혼자서 끝까지 했다는 사실이 뜻깊다. 동적프로그래밍은 점화식을 짜는 것도 어렵지만, 풀고 있는 문제가 동적프로그래밍 문제인지 판단하는 것도 어렵다고 한다. DP 실습인 걸 알고 풀어서 금방 풀리지 않았을까? 라는 생각도 든다.</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프론트엔드 Day 6]]></title>
            <link>https://velog.io/@jo_cw/TIL-FE-Day-5-j2imgb1e</link>
            <guid>https://velog.io/@jo_cw/TIL-FE-Day-5-j2imgb1e</guid>
            <pubDate>Mon, 28 Mar 2022 17:10:53 GMT</pubDate>
            <description><![CDATA[<h2 id="공부한-내용">공부한 내용</h2>
<h3 id="1-dfs-bfs">1. DFS, BFS</h3>
<ul>
<li>DFS
깊이 우선 탐색 (Depth Fisrt Search). 탐색 트리를 탐색할 때, 가장 깊은 노드를 우선 탐색하는 탐색방식. 실제 코드에서 구현은 스택 자료구조 또는 재귀 함수를 이용한다. 하나의 경로를 우선적으로 탐색하고, 이미 탐색한 경로를 저장할 필요가 없어 공간 복잡도가 낮은 편이다. 찾은 해가 최적해가 아닐 수 있으며, Cycle이 존재할 경우 무한루프의 위험이 있다.</li>
<li>BFS
너비 우선 탐색 (Breadth Fisrt Search). 탐색 트리를 탐색할 때, 현제 지점과 인접한 곳을 먼저 탐색하는 탐색방식. 실제 코드에서 구현은 큐 자료구조를 이용한다. 목표 노드까지의 최단거리를 보장하지만, 이전의 모든 경로를 기억하는데 공간이 많이 필요하다. </li>
</ul>
<h3 id="2-그리디">2. 그리디</h3>
<p>그리디 알고리즘은 총 이득을 바라보는 것이 아닌, 판단하는 순간 순간의 이득에 집중하는 알고리즘이다. 이러한 판단 방식이 매우 직관적이며, 항상 최적해를 보장하지는 않는다. 현재의 선택이 미래에 영향을 주지 않는 경우, 입출력 제한이 너무 큰 경우 그리디 알고리즘을 고려해보자.</p>
<h3 id="3-백트래킹">3. 백트래킹</h3>
<p>앞서 배운 DFS, BFS와 같은 완전 탐색에서 추가적으로 속도를 높이기 위한 탐색기법. 현제 방문한 노드가 답일 확률이 낮을 때, 해당 노드와 이어진 노드의 탐색을 생략한다(가지치기). 얼마나 가지치기 조건을 잘 세우냐가 중요하며, 자바스크립트의 경우에 재귀의 성능이 좋지 않아 Stack, Queue 자료구조를 이용하여 구현하는 것이 좋다.</p>
<h3 id="4-map-filter-reduce">4. map, filter, reduce</h3>
<h4 id="map">map</h4>
<p>이터러블 데이터가 있을 때, 이터러블의 각 요소마다 일정한 변경을 준 또다른 이터러블을 반환하는 함수이다.</p>
<pre><code class="language-JavaScript">const arr = [1, 2, 3, 4, 5];
const func = a =&gt; a + 1;
console.log(arr.map(func));
// [2, 3, 4, 5, 6]</code></pre>
<p>위의 Array.prototype.map()과 동일하게 동작한다. 하지만 이터러블 프로토콜을 이용해서 구현한다면, Array를 포함한 이터러블 프로토콜을 따르는 모든 데이터에 사용할 수 있다.</p>
<h4 id="filter">filter</h4>
<p>여러 데이터 중 조건과 일치하는 요소만을 가진 이터러블을 반환하는 함수이다.</p>
<pre><code class="language-JavaScript">const arr = [1, 2, 3, 4, 5];
const func = a =&gt; a &lt; 4;
console.log(arr.filter(func));
// [1, 2, 3]</code></pre>
<p>위의 Array.prototype.filter()와 동일하게 작동한다.</p>
<h4 id="reduce">reduce</h4>
<p>여러 요소를 가진 이터러블에서 하나의 값으로 수를 줄이는 함수이다. 파라미터는 다음과 같다.
<code>reduce(function f(a, b), acc, iterable)</code> </p>
<ul>
<li>요소를 줄이는 계산 방식을 지닌 함수 f</li>
<li>초기 값이자 계산이 누적되는 acc</li>
<li>계산에 이용된 데이터들을 가진 iterable</li>
</ul>
<pre><code class="language-JavaScript">const arr = [1, 2, 3, 4, 5];
const func = (a, b) =&gt; a + b;
console.log(reduce(func, 0, arr));
// 15</code></pre>
<p>위와 같은 reduce 함수가 있을 때, 이 함수의 동작 순서를 표기하면 다음과 같은 재귀 구조이다.</p>
<pre><code class="language-JavaScript">func(func(func(func(func(0, 1), 2), 3), 4), 5);</code></pre>
<p>위의 파라미터 중 acc는 생략이 가능하며, 만약 생략된다면 기본적으로 iterable의 첫번 째 원소가 되고 계산은 두번째 원소부터 시작한다.</p>
<pre><code class="language-JavaScript">reduce(func, arr);
// 아래와 같은 방식으로 동작한다.
// (func, [first, ...arr]) =&gt; reduct(func, first, arr);
// func(func(func(func(1, 2), 3), 4), 5);</code></pre>
<h3 id="5-go-pipe-curry">5. go, pipe, curry</h3>
<h4 id="go">go</h4>
<p>앞서 본 함수형 프로그래밍의 함수들은 결과를 별도로 사용하지 않고 그대로 반환하므로 중첩하여 사용이 가능하다. 하지만 중첩이 많을수록 가독성이 떨어지며, 가장 안쪽에 위치한 함수부터 동작하므로 사람이 글을 읽는 방향과 반대방향이 된다. 이런 중첩된 코드의 가독성을 높이기 위해서 사용하는 함수가 go 함수이다. go 함수는 시작값과 <strong>함수들을 인자로 받아</strong> 인자로 받은 함수들을 차례대로 실행한 결과를 반환한다. </p>
<h4 id="pipe">pipe</h4>
<p>go와 비슷하게 동작하지만 모든 함수들의 실행 결과 값이 아닌, 모든 함수실행하는 하나의 함수를 반환한다. 선언한 함수를 반복적으로 사용할 수 있는 점이 go와 다르다. </p>
<h4 id="curry">curry</h4>
<p>curry는 함수를 입력받고, 입력받은 인자의 개수에 따라서 다르게 동작하는 또 다른 함수를 결과물로 반환한다. 지정한 숫자만큼의 인자가 입력된다면 실행 결과를 반환하지만, 보다 적은 인자를 입력할 경우에 입력받은 인자는 저장하고 <strong>나머지 입력을 받아 결과를 반환하는 함수</strong>를 반환한다. </p>
<pre><code class="language-JavaScript">const add = (a, b) =&gt; a + b;
const curry_add = curry(add);
const add5 = curry_add(5); 

// a와 b 두개의 인자들 중 a를 5로 저장, 나머지 입력을 받는 함수로 반환한다.
// add5 = (5, b) =&gt; 5 + b;
// add5 = b =&gt; 5 + b;
</code></pre>
<hr>
<h2 id="다시-볼-내용">다시 볼 내용</h2>
<p>Currying, 함수형 프로그래밍 구현(go, pipe)</p>
<hr>
<h2 id="느낀점">느낀점</h2>
<p>프로그래밍을 접하고 난 뒤로 명령형 프로그래밍에서 벗어난 적이 없었는데, 이렇게 함수형 프로그래밍에 대해서 배울 기회가 생겨 뜻깊다. 아무래도 사고 방식의 전환이라 평범하게 새로운 프로그래밍 언어를 배울 때와는 사뭇 다른 느낌이다. 아직도 함수를 변수에 저장하는 개념이나 표기법에서 이해가 더디다. 함수형 프로그래밍 관련 질문은 기간이 짧으니 이번주 동안은 좀 더 노력해 봐야겠다.</p>
<hr>
<h2 id="reference">Reference</h2>
<p>프로그래머스 프론트엔드 데브코스</p>
]]></description>
        </item>
    </channel>
</rss>