Forbid403 개발 블로그
Jekyll
2022-08-08T23:17:03+09:00
https://forbid403.github.io/
https://forbid403.github.io/
https://forbid403.github.io/algorithm/[leetcode] Two Sum
2022-08-08T00:00:00+09:00
2022-08-08T00:00:00+09:00
https://forbid403.github.io
<p><a href="https://leetcode.com/problems/two-sum/">문제 링크</a></p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">twoSum</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nums</span><span class="p">,</span> <span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">m</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="nx">nums</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">num</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">=></span> <span class="nx">m</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">num</span><span class="p">,</span> <span class="nx">index</span><span class="p">));</span>
<span class="k">for</span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">nums</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">temp</span> <span class="o">=</span> <span class="nx">target</span> <span class="o">-</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">temp</span><span class="p">)</span> <span class="o">&&</span> <span class="nx">m</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">temp</span><span class="p">)</span> <span class="o">!==</span> <span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">i</span><span class="p">,</span> <span class="nx">m</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">temp</span><span class="p">)];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">twoSum</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">nums</span><span class="p">,</span> <span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">m</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Map</span><span class="p">();</span>
<span class="k">for</span><span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">nums</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">temp</span> <span class="o">=</span> <span class="nx">target</span> <span class="o">-</span> <span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">temp</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">i</span><span class="p">,</span> <span class="nx">m</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="nx">temp</span><span class="p">)];</span>
<span class="p">}</span>
<span class="nx">m</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>가장 간단한 방법은 배열을 전부 돌면서 하나씩 더해보는 것이다.</li>
<li>성능을 개선하는 방법은 <code class="language-plaintext highlighter-rouge">map</code>을 활용 하는 방법이다. O(N~2N)
<ul>
<li>
<ol>
<li>맵에 숫자, 인덱스로 저장 해 두고 배열을 돌면서 <code class="language-plaintext highlighter-rouge">target - nums[i]</code> 값이 맵에 존재하는지 확인한다.</li>
</ol>
</li>
<li>
<ol>
<li>배열을 돌면서 존재하지 않는 경우에만 맵에 넣어둘 수도 있다.</li>
</ol>
</li>
</ul>
</li>
<li>런타임 시간은 1번이 더 빨랐지만 메모리는 2번이 덜 차지한다.</li>
</ul>
https://forbid403.github.io/js/[코어자바스크립트] 1장 데이터 타입
2022-08-07T00:00:00+09:00
2022-08-07T00:00:00+09:00
https://forbid403.github.io
<h1 id="1장-데이터-타입">1장 데이터 타입</h1>
<blockquote>
<p>JS의 데이터 타입은 크게 두 가지가 있음: 기본형, 참조형</p>
</blockquote>
<h1 id="기본형">기본형</h1>
<blockquote>
<p>할당이나 연산 시 <strong>값</strong>을 복제함, <strong>불변성</strong></p>
<ul>
<li>Number</li>
<li>String</li>
<li>Boolean</li>
<li>Symbol</li>
<li>null</li>
<li>undefined</li>
</ul>
</blockquote>
<h1 id="참조형">참조형</h1>
<blockquote>
<p>할당이나 연산 시 <strong>주솟값</strong>을 복제함</p>
<ul>
<li>Object
<ul>
<li>Array</li>
<li>Function</li>
<li>Date</li>
<li>RegExp</li>
<li>Map, WeakMap</li>
<li>Set, WeakSet</li>
</ul>
</li>
</ul>
</blockquote>
<h1 id="변수와-식별자">변수와 식별자</h1>
<ul>
<li>변수: 변할 수 있는 무언가</li>
<li>식별자: 변수명</li>
</ul>
<h1 id="변수-선언과-데이터-할당">변수 선언과 데이터 할당</h1>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>위의 코드를 풀어 쓰면, “변할 수 있는 데이터(변수)를 만든다. 이 데이터의 식별자는 a이다”</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/41617388/183297267-55c43e50-0b46-46e3-9ff9-6dbb99fd058b.png" alt="Untitled" /></p>
<ul>
<li>메모리 영역에는 위와 같이 저장된다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">abc</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297360-5eadd54a-57cf-4e6c-865d-b9d8e7cec974.png" alt="Untitled 1" /></p>
<ul>
<li>직접 변수 공간에 값을 저장하지 않고, 해당 데이터의 주솟값을 저장한다.</li>
<li>값은 별도의 메모리 공간에 저장한다.</li>
<li>순서는 다음과 같다.
<ol>
<li>변수 영역에서 빈 공간(@1003)을 확보한다.</li>
<li>확보한 공간의 식별자를 a로 지정한다.</li>
<li>데이터 영역의 빈 공간(@4003)에 값을 저장한다.</li>
<li>변수 영역에서 a라는 식별자를 검색한다.</li>
<li>저장한 값의 주솟값 (@4003)을 @1003의 공간에 대입한다.</li>
</ol>
</li>
<li>왜 이렇게 따로 저장하는 것일까?
<ul>
<li>JS는 숫자형 데이터는 64비트 (8바이트)의 공간을 확보한다.</li>
<li>하지만 문자열의 경우 한글은 2바이트, 영어는 1바이트로 필요한 용량이 가변적이다.</li>
<li>값을 바로 저장하게 되면, 재할당시 데이터 크기에 맞춰 늘려줘야 한다.
<ul>
<li>만약 뒤에 이미 공간이 차있으면? 뒤에 저장된 데이터들을 모두 몇 칸씩 옮겨줘야 한다.</li>
</ul>
</li>
<li>컴퓨터의 연산이 많아지게 된다.</li>
</ul>
</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">abc</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">abcdef</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297254-288f5ee2-ef4f-48f5-80b0-6a0e19e8ffcf.png" alt="Untitled 2" /></p>
<ul>
<li>값을 재할당 하면, 기존 주솟값에 저장된 게 바뀌는게 아니라 <strong>새로</strong> 생성 후에 할당하게 된다.</li>
<li>만약 100개의 변수에 5라는 값을 할당한다고 하면, 매번 생성하는 것이 아니라, 주솟값만 동일하게 할당한다.
<ul>
<li>이와 같은 장점 때문에 변수와 값을 따로 저장하는 것이다.</li>
</ul>
</li>
</ul>
<h1 id="기본형-데이터와-참조형-데이터">기본형 데이터와 참조형 데이터</h1>
<h2 id="불변값">불변값</h2>
<ul>
<li>변수와 상수를 구분 짓는 것은 <strong>변수 영역</strong> 메모리의 변경 가능성이다.
<ul>
<li>한 번 데이터 할당이 이루어진 변수 공간에 다른 데이터를 재할당 할 수 있는지의 여부</li>
</ul>
</li>
<li>불변성의 구분 여부는 <strong>데이터 영역</strong> 메모리의 변경 가능성이다.</li>
<li>기본형 데이터들은 전부 불변값이다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">abc</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">a</span> <span class="o">=</span> <span class="nx">a</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">def</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="nx">b</span> <span class="o">=</span> <span class="mi">7</span><span class="p">;</span>
</code></pre></div></div>
<ul>
<li>a의 값은 아예 새로운 데이터가 할당된다.
<ul>
<li>‘abc’, ‘abcdef’는 완전히 별개의 데이터이다.</li>
</ul>
</li>
<li>b, c의 값은 동일하다.
<ul>
<li>b를 7로 재할당 했을 때, 5가 7로 바뀌지 않고 새로운 데이터가 할당된다.</li>
<li>따라서 5, 7 모두 다른 값으로 변경할 수 없다.</li>
</ul>
</li>
<li>한 번 만든 값을 바꿀 수 없고, 변경은 새로 만드는 동작을 통해서만 이루어진다. → 불변성</li>
</ul>
<h3 id="가변값">가변값</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">b</span><span class="p">:</span> <span class="dl">'</span><span class="s1">bbb</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297257-3b224133-f13c-4a87-8e26-fdccb7cd744d.png" alt="Untitled 3" /></p>
<ol>
<li>변수 영역의 빈 공간(@1002) 확보 후 이름을 obj1로 지정한다.</li>
<li>임의의 데이터 저장 공간(@5001)에 데이터를 저장하려고 보니, 여러 개의 프로퍼티로 이뤄진 데이터 그룹이다. 내부 프로퍼티들을 저장하기 위해 별도의 변수 영역을 마련하고, 그 영역의 주소(@7103~)를 저장한다.</li>
<li>@7103, @7104에 각각 a, b 프로퍼티 이름을 지정한다.</li>
<li>데이터 영역에서 1을 검색한다. 없으므로 생성 후 주솟값을 저장한다. ‘bbb’도 마찬가지.</li>
</ol>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">b</span><span class="p">:</span> <span class="dl">'</span><span class="s1">bbb</span><span class="dl">'</span>
<span class="p">}</span>
<span class="nx">obj1</span><span class="p">.</span><span class="nx">a</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297261-4925a634-393a-487a-be86-ebd90ceb2791.png" alt="Untitled 4" /></p>
<ul>
<li><code class="language-plaintext highlighter-rouge">obj1</code> 이 바라보고 있는 주소는 변하지 않았다. 즉 ‘새로운 객체’가 만들어진 것이 아니라, 기존 객체의 내부 값만 바뀐 것이다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 중첩 객체</span>
<span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">x</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">arr</span><span class="p">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297262-f6bff73e-77f4-4e7b-b46f-1d34a5593cfd.png" alt="Untitled 5" /></p>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">obj</span><span class="p">.</span><span class="nx">arr</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">str</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297264-a32a2d3e-a67d-4d15-aca6-06418594abbe.png" alt="Untitled 6" /></p>
<ul>
<li>이 상태에서 재할당 한다면, 참조 카운트가 0인 메모리들이 GC의 대상이 된다.</li>
</ul>
<h2 id="변수-복사-비교">변수 복사 비교</h2>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span> <span class="na">c</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="na">d</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ddd</span><span class="dl">'</span> <span class="p">};</span>
<span class="kd">var</span> <span class="nx">obj2</span> <span class="o">=</span> <span class="nx">obj1</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297265-516b5a67-dc96-42c7-9b75-0c39cb5f1db9.png" alt="Untitled 7" /></p>
<ul>
<li>위의 코드에서 값들을 재할당 한다면,</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">b</span> <span class="o">=</span> <span class="mi">15</span><span class="p">;</span>
<span class="nx">obj2</span><span class="p">.</span><span class="nx">c</span> <span class="o">=</span> <span class="mi">20</span><span class="p">;</span>
</code></pre></div></div>
<p><img src="https://user-images.githubusercontent.com/41617388/183297266-771f942c-1005-4bd9-acfb-d0badb14681b.png" alt="Untitled 8" /></p>
<ul>
<li>객체 내부 프로퍼티 값이 변경 되지만, 객체의 주솟값은 그대로이기 때문에 <code class="language-plaintext highlighter-rouge">obj1</code>, <code class="language-plaintext highlighter-rouge">obj2</code> 모두 값이 바뀌게 된다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">a</span> <span class="o">!==</span> <span class="nx">b</span>
<span class="nx">ob1</span> <span class="o">===</span> <span class="nx">obj2</span>
</code></pre></div></div>
<ul>
<li>인 상태가 된다. 이게 기본형과 참조형의 제일 큰 차이점이다.</li>
<li>위의 예제는 객체 자체가 아닌, 객체 내부의 프로퍼티 값 변경에 대한 예제이다.</li>
<li>만약 <code class="language-plaintext highlighter-rouge">obj2</code> 에 새로운 객체를 할당하게 되면, 메모리 주소가 변경이 되기 때문에 <code class="language-plaintext highlighter-rouge">obj1 !== obj2</code> 가 된다.
<ul>
<li>따라서 참조형 데이터가 가변값이라고 말할 수 있는 경우는, 내부 프로퍼티의 값이 변경되는 경우이다.</li>
</ul>
</li>
</ul>
<h2 id="얕은-복사와-깊은-복사">얕은 복사와 깊은 복사</h2>
<ul>
<li>얕은 복사는 바로 아래 단계의 값만 복사하는 방법이고,</li>
<li>깊은 복사는 내부의 모든 값들을 복사하는 방법이다.</li>
</ul>
<h3 id="얕은-복사">얕은 복사</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">copyObject</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">target</span><span class="p">[</span><span class="nx">prop</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>만약 객체가 nested 된 참조형이라면, 내부 프로퍼티는 원본이 그대로 저장된다.</li>
</ul>
<h3 id="깊은-복사">깊은 복사</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">copyDeepObject</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">target</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span> <span class="o">&&</span> <span class="nx">target</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">copyDeepObject</span><span class="p">(</span><span class="nx">target</span><span class="p">[</span><span class="nx">prop</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">result</span> <span class="o">=</span> <span class="nx">target</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>만약 참조형 데이터를 만나면, 재귀 함수로 복사하게 된다.</li>
<li><code class="language-plaintext highlighter-rouge">hasOwnProperty</code> 를 활용해 프로토타입 체이닝을 통해 상속된 프로퍼티를 복사하지 않게끔 할 수도 있다.</li>
<li>ES5의 <code class="language-plaintext highlighter-rouge">getter/setter</code> 를 복사하는 방법은 ES6 <code class="language-plaintext highlighter-rouge">Object.getOwnPropertyDescriptor</code> 또는 ES2017의 <code class="language-plaintext highlighter-rouge">Object.getOwnPropertyDescriptors</code>` 밖에 없다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">copyObjectByJSON</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">target</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">JSON</code> 을 활용하여 문자열 → JSON 객체로 바꾸는 방법으로도 깊은 복사를 수행할 수 있다.</li>
<li>하지만 함수, <code class="language-plaintext highlighter-rouge">__proto__</code>, <code class="language-plaintext highlighter-rouge">getter/setter</code> 와 같은 값들은 복사할 수 없다.</li>
</ul>
<h1 id="undefined와-null">undefined와 null</h1>
<ul>
<li>JS에는 ‘없음’을 나타내는 값이 두가지가 있다.</li>
</ul>
<h3 id="undefined">undefined</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 1번</span>
<span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span> <span class="c1">// undefined</span>
<span class="c1">// 2번</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">b</span><span class="p">);</span> <span class="c1">// undefined</span>
<span class="c1">// 3번</span>
<span class="kd">var</span> <span class="nx">func</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{}</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="nx">func</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span> <span class="c1">// undefined</span>
</code></pre></div></div>
<ul>
<li>JS 엔진은 다음 세 가지 경우에 <code class="language-plaintext highlighter-rouge">undefined</code>를 반환한다.
<ol>
<li>값을 대입하지 않은 변수에 접근할 때</li>
<li>객체 내부의 존재하지 않는 프로퍼티에 접근할 때</li>
<li>return 문이 없거나 호출되지 않는 함수의 실행 결과</li>
</ol>
</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span> <span class="c1">// [empty x 3]</span>
<span class="kd">var</span> <span class="nx">arr2</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Array</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr2</span><span class="p">);</span> <span class="c1">// [empty x 3]</span>
<span class="kd">var</span> <span class="nx">arr3</span> <span class="o">=</span> <span class="p">[</span><span class="kc">undefined</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">,</span> <span class="kc">undefined</span><span class="p">];</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr3</span><span class="p">);</span> <span class="c1">// [undefined, undefined, undefined]</span>
</code></pre></div></div>
<ul>
<li>1번의 경우, 배열이라면 조금 다르게 동작한다.</li>
<li>배열에 <code class="language-plaintext highlighter-rouge">length</code> 값을 주면 그만큼 값을 할당할 것 같지만, 객체와 동일하게 값을 지정할 때에 공간 확보 후 값을 저장한다. 배열도 객체이기 때문이다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">arr1</span> <span class="o">=</span> <span class="p">[</span><span class="kc">undefined</span><span class="p">,</span> <span class="mi">1</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">arr2</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">arr2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">arr1</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">v</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">i</span><span class="p">));</span> <span class="c1">// undefined 0, 1 1</span>
<span class="nx">arr2</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">v</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">i</span><span class="p">));</span> <span class="c1">// 1 1</span>
</code></pre></div></div>
<ul>
<li>비어있는 요소는 순회하는 메서드들의 순회 대상에서 제외된다.</li>
<li>사용자가 지정한 <code class="language-plaintext highlighter-rouge">undefined</code> 는 그 자체로 값이 되기 때문에 순회 대상이 되어버린다.</li>
<li>JS가 지정한 <code class="language-plaintext highlighter-rouge">undefined</code>는 값이 없음을 나타낸다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">n</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">n</span><span class="p">);</span> <span class="c1">// object</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">n</span> <span class="o">==</span> <span class="kc">undefined</span><span class="p">);</span> <span class="c1">// true</span>
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">undefined</code> 는 여러모로 헷갈리기 때문에,</li>
<li>비어있음을 명시적으로 나타내고 싶은 경우에는 <code class="language-plaintext highlighter-rouge">null</code> 을 사용하자.</li>
<li>주의해야 할 점은, JS 자체 버그로 <code class="language-plaintext highlighter-rouge">typeof null</code>이 <code class="language-plaintext highlighter-rouge">object</code>라는 것이다.</li>
</ul>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">n</span> <span class="o">==</span> <span class="kc">null</span><span class="p">);</span> <span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">n</span> <span class="o">===</span> <span class="kc">undefined</span><span class="p">);</span> <span class="c1">// false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">n</span> <span class="o">===</span> <span class="kc">null</span><span class="p">);</span> <span class="c1">// true</span>
</code></pre></div></div>
<ul>
<li>따라서 <code class="language-plaintext highlighter-rouge">null</code> 값을 체크할 경우에는 <code class="language-plaintext highlighter-rouge">==</code> 연산자가 아닌 <code class="language-plaintext highlighter-rouge">===</code> 연산자를 사용해서 비교해야 한다.</li>
</ul>
https://forbid403.github.io/fe/yarn2
2022-07-31T00:00:00+09:00
2022-07-31T00:00:00+09:00
https://forbid403.github.io
<h1 id="yarn2">Yarn2</h1>
<h1 id="yarn-vs-npm">yarn vs npm</h1>
<h2 id="npm의-문제점">npm의 문제점</h2>
<ul>
<li>lock 파일이 없다보니 생기는 패키지의 버저닝/의존 이슈
<ul>
<li>패키지 설치 순서에 따라서 디바이스, 환경마다 <code class="language-plaintext highlighter-rouge">node_modules</code> 트리가 다를 수 있다.</li>
</ul>
</li>
<li>안정성/보안 이슈
<ul>
<li>패키지가 설치될 때 자동으로 코드와 의존성을 실행할 수 있도록 허용된다.</li>
<li>검증되지 않은 패키지가 포함될 수 있다는 위험성이 존재한다.</li>
</ul>
</li>
<li>패키지가 늘어날수록 성능 저하</li>
</ul>
<h2 id="yarn">yarn</h2>
<ul>
<li>yarn.lock 파일 자동생성, checksum을 통해 어느 환경에서든 동일한 패키지를 설치한다.</li>
<li>yarn.lock에 있는 패키지를 <code class="language-plaintext highlighter-rouge">설치만</code> 한다.
<ul>
<li>추가적으로 실행되는 코드나 의존성이 없어 안정성이 상대적으로 높다.</li>
</ul>
</li>
<li>병렬 설치로 속도를 높였다.</li>
<li>내부적으로 mutex를 사용 해 다수의 CLI 실행 시 충돌하거나 오염시키지 않도록 방지한다.</li>
<li>cache directory를 통한 오프라인 미러링
<ul>
<li>처음 빌드 할 때 레지스트리에서 다운로드한 파일을 로컬 캐시에 저장한다.</li>
</ul>
</li>
<li><a href="https://www.bloter.net/newsView/blt201604040002">left-pad</a> 이슈 방지
<ul>
<li>npm 레지스트리뿐만 아니라 Bower 레지스트리도 확인한다.</li>
</ul>
</li>
</ul>
<h1 id="기존-패키지-관리의-문제점">기존 패키지 관리의 문제점</h1>
<h3 id="1-거대한-node_modules">1. 거대한 <code class="language-plaintext highlighter-rouge">node_modules</code></h3>
<p><img src="https://user-images.githubusercontent.com/41617388/182021914-62b3321e-e9b5-4b56-954d-5b56e59b6923.png" alt="Untitled" /></p>
<ul>
<li>파일 시스템(<code class="language-plaintext highlighter-rouge">node_modules</code>)을 이용하여 의존성을 관리한다.
<ul>
<li>특정 라이브러리 패키지를 찾기 위해 계속 상위 디렉토리의 폴더를 탐색한다.
<ul>
<li>결과가 패키지의 상위 디렉터리 환경에 따라 달라질 수 있다.</li>
<li>패키지를 찾지 못하면 readdir, stat과 같은 느린 I/O 호출이 반복된다.</li>
</ul>
</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">node_modules</code> 디렉토리 구조는 매우 큰 용량을 필요로 한다.</li>
</ul>
<h3 id="2-유령-의존성-phanthom-dependency">2. 유령 의존성 (Phanthom Dependency)</h3>
<ul>
<li>npm과 yarn1 에서는 중복해서 설치되는 문제를 해결하기 위해 끌어올리기(hoisting) 기법을 사용한다.</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/41617388/148636206-55e23abf-c414-44ef-bad7-621ce4f55061.png" alt="https://user-images.githubusercontent.com/41617388/148636206-55e23abf-c414-44ef-bad7-621ce4f55061.png" /></p>
<ul>
<li>A(1, 0), B(1, 0) 이 겹친다. 디스크 공간을 아끼기 위해 왼쪽 > 오른쪽 모양으로 바꾼다.</li>
<li>오른쪽으로 바뀌면서 B(1, 0)을 require 할 수 있게 된다.</li>
<li>이렇게 직접 의존하지 않는 라이브러리를 require 할 수 있는 현상을 유령 의존성이라고 한다.</li>
<li>package.json에 정의 하지 않은 라이브러리를 조용하게 사용할 수 있지만, 다른 의존성을 제거했을 때 소리없이 같이 사라지기도 한다.</li>
<li>이런 특성은 의존성 관리 시스템을 혼란스럽게 만든다.</li>
</ul>
<h1 id="yarn2-1">Yarn2</h1>
<ul>
<li>yarn2 에서는 위의 문제점들을 해결하기 위해 몇 가지 방법을 고안해냈다.</li>
</ul>
<h2 id="zipfs-zip-filesystem">ZipFS (Zip Filesystem)</h2>
<ul>
<li>yarn2에서 패키지 설치 시 <code class="language-plaintext highlighter-rouge">node_modules</code> 에 디렉터리 구조를 그리는게 아니라,</li>
<li>
<p><code class="language-plaintext highlighter-rouge">.yarn/cache</code> 하위에 ZIP 파일로 저장된다. <br />
<img src="https://user-images.githubusercontent.com/41617388/182021944-25117de0-78f5-4169-a0c1-9fbe74b2b465.png" alt="Untitled 1" /></p>
</li>
<li>ex) <code class="language-plaintext highlighter-rouge">recoil@0.1.2</code> > <code class="language-plaintext highlighter-rouge">recoil-npm-0.1.2-9a0edbd2b9-c69105dd7d.zip</code></li>
<li><code class="language-plaintext highlighter-rouge">yarn install</code> 실행 시, zip파일을 <code class="language-plaintext highlighter-rouge">node_modules</code> 하위에 압축 해제한다.</li>
<li>장점
<ul>
<li><code class="language-plaintext highlighter-rouge">node_modules</code> 디렉토리 구조를 그릴 필요가 없다. > 설치 빨라짐</li>
<li>각 패키지는 버전마다 하나의 zip만 가져서 중복 설치를 방지한다. > 설치 용량 감소</li>
<li>zip 파일이 변경되면 checksum으로 비교하여 변경을 감지한다.
<ul>
<li>의존성을 구성하는 파일의 수가 많지 않으므로, 변경 사항 감지, 삭제 작업이 빠르다.</li>
</ul>
</li>
<li>패키지를 탐색하는데 사용하는 연산들이 감소한다.</li>
</ul>
</li>
</ul>
<h2 id="offline-cache">Offline-cache</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/182021940-13895f78-fe8c-401b-9f73-a984f51ba616.png" alt="Untitled 2" /></p>
<ul>
<li>의존성도 git 등을 이용하여 버전 관리를 하면 어떨까? > 버전 관리에 포함하자!</li>
<li><code class="language-plaintext highlighter-rouge">.yarn</code> 디렉토리를 레포지토리에 추가하면, 의존성을 설치할 필요가 없이 레포지토리를 클론해서 바로 쓰면 된다.</li>
</ul>
<h3 id="pros">Pros</h3>
<ul>
<li>새로 저장소를 복제하거나 브랜치 변경 시 remote registry에서 패키지들을 받아오지 않는다.
<ul>
<li>여러 환경, 디바이스에서 동일한 패키지 버전이 보장된다. > 유령 의존성 해결</li>
<li>단순 압축 해제만 하기 때문에 CI에서 의존성 설치 시간을 크게 절약 가능하다.</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">npm</code> 서버가 다운 되더라도 zip 파일 압축 해제만 하면 되기 때문에 오프라인에서도 동작 가능하다.</li>
</ul>
<h2 id="plugnplay-pnp">Plug’n’Play (PnP)</h2>
<blockquote>
<p>a.k.a. Zero Install</p>
<ul>
<li>PnP는 꽂으면 바로 사용할수 있다.. 라는 의미라고 한다.</li>
</ul>
</blockquote>
<h2 id="동작-방법">동작 방법</h2>
<ul>
<li><code class="language-plaintext highlighter-rouge">.pnp.cjs</code> 에 의존성을 찾을 수 있는 정보가 <code class="language-plaintext highlighter-rouge">map</code> 으로 기록된다.</li>
<li><code class="language-plaintext highlighter-rouge">pnp.cjs</code> 파일과 zip 파일을 런타임 시 링크 해준다.</li>
<li>
<p>ex) 리액트는 .pnp.cjs 파일에서 다음과 같이 나타난다.</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="w"> </span><span class="err">/*</span><span class="w"> </span><span class="err">패키지</span><span class="w"> </span><span class="err">이름:</span><span class="w"> </span><span class="err">react</span><span class="w"> </span><span class="err">패키지</span><span class="w"> </span><span class="err">중에서</span><span class="w"> </span><span class="err">*/</span><span class="w">
</span><span class="p">[</span><span class="s2">"react"</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="err">/*</span><span class="w"> </span><span class="err">패키지</span><span class="w"> </span><span class="err">버전:</span><span class="w"> </span><span class="err">npm:</span><span class="mf">17.0</span><span class="err">.</span><span class="mi">1</span><span class="w"> </span><span class="err">버전은</span><span class="w"> </span><span class="err">*/</span><span class="w">
</span><span class="p">[</span><span class="s2">"npm:17.0.1"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="err">/*</span><span class="w"> </span><span class="err">패키지</span><span class="w"> </span><span class="err">경로:</span><span class="w"> </span><span class="err">이</span><span class="w"> </span><span class="err">위치에</span><span class="w"> </span><span class="err">있고</span><span class="w"> </span><span class="err">*/</span><span class="w">
</span><span class="nl">"packageLocation"</span><span class="p">:</span><span class="w"> </span><span class="s2">"./.yarn/cache/react-npm-17.0.1-98658812fc-a76d86ec97.zip/node_modules/react/"</span><span class="p">,</span><span class="w">
</span><span class="err">/*</span><span class="w"> </span><span class="err">패키지</span><span class="w"> </span><span class="err">의존성:</span><span class="w"> </span><span class="err">이</span><span class="w"> </span><span class="err">의존성들을</span><span class="w"> </span><span class="err">참조한다.</span><span class="w"> </span><span class="err">*/</span><span class="w">
</span><span class="nl">"packageDependencies"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">[</span><span class="s2">"loose-envify"</span><span class="p">,</span><span class="w"> </span><span class="s2">"npm:1.4.0"</span><span class="p">],</span><span class="w">
</span><span class="p">[</span><span class="s2">"object-assign"</span><span class="p">,</span><span class="w"> </span><span class="s2">"npm:4.1.1"</span><span class="p">]</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="p">}]</span><span class="w">
</span><span class="p">]]</span><span class="err">,</span><span class="w">
</span></code></pre></div> </div>
</li>
<li><strong>Zero Install</strong>이라는 말에 걸맞게 <code class="language-plaintext highlighter-rouge">node_modules</code> 폴더가 없다!</li>
<li>pull이나 clone시에 패키지를 설치 할 필요 없이 바로 실행 가능하다.</li>
<li>하지만…
<ul>
<li><a href="https://yarnpkg.com/features/pnp#compatibility-table">호환성 테이블</a></li>
<li>런타임 시에 node가 <code class="language-plaintext highlighter-rouge">import</code>, <code class="language-plaintext highlighter-rouge">require</code> 를 사용 할 때마다 <code class="language-plaintext highlighter-rouge">.pnp.cjs</code> 를 연결해줘야 하는데, 라이브러리 제공자들이 PnP에서 지원할 수 있도록 제공해줘야 한다.</li>
<li>지원하지 않는 패키지들은 커스텀 플러그인이나,<code class="language-plaintext highlighter-rouge">node_modules</code> 플러그인과 함께 사용해야한다.</li>
<li>또한 디버깅이 쉽지 않은 에러들 때문에 호불호가 갈린다.</li>
<li>이러한 리스크 때문에 보통 PnP는 제외하고 적용하는 듯 하다.</li>
</ul>
</li>
</ul>
<h2 id="기타-yarn2의-새로운-기능들">기타 yarn2의 새로운 기능들</h2>
<ul>
<li>플러그인 지원</li>
<li>워크스페이스 (모노레포)</li>
<li><code class="language-plaintext highlighter-rouge">patch</code> 명령어 기본 지원
<ul>
<li>npm에 배포된 라이브러리 일부분만 수정 가능</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">yarn install</code> 시 peerDependency에 등록된 css 패키지가 <code class="language-plaintext highlighter-rouge">yarn.lock</code> 에서 사라져 매번 롤백해줘야 했는데, yarn2부터 개선되었다.
<ul>
<li><a href="https://yarnpkg.com/getting-started/migration#fix-dependencies-with-packageextensions">https://yarnpkg.com/getting-started/migration#fix-dependencies-with-packageextensions</a></li>
</ul>
</li>
</ul>
<h1 id="결론">결론</h1>
<ul>
<li>yarn2의 큰 특징은 1. Offline cache, 2. PnP 이다.</li>
<li>Offline Cache는 패키지들이 ZIP으로 관리 돼 안정성과 속도 개선의 이점이 있어 적용해봄직 하다.</li>
<li>PnP는 아직 지원도 적고 관리가 어려워 보여 도입이 어려울 것 같다.
<ul>
<li>또한 지원 버전도 낮은 편이 아니라, 기존 프로젝트보다는 새로운 프로젝트에 적용해보는게 좋을 것 같다.</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">pnpm</code> 도 대체제로 많이 언급 되던데 리서치를 좀 더 해봐야겠다.</li>
</ul>
<h1 id="ref">ref</h1>
<ul>
<li><a href="https://medium.com/wantedjobs/yarn-berry-%EC%A0%81%EC%9A%A9%EA%B8%B0-1-e4347be5987">원티드</a></li>
<li><a href="https://toss.tech/article/node-modules-and-yarn-berry">토스</a></li>
<li><a href="https://medium.com/inato/make-your-ci-faster-and-improve-developer-experience-upgrade-to-yarn-2-with-or-without-939524d9bef2">https://medium.com/inato/make-your-ci-faster-and-improve-developer-experience-upgrade-to-yarn-2-with-or-without-939524d9bef2</a></li>
</ul>
https://forbid403.github.io/fe/웹 어셈블리
2022-03-12T00:00:00+09:00
2022-03-12T00:00:00+09:00
https://forbid403.github.io
<p align="center">
<img src="[https://user-images.githubusercontent.com/41617388/131326021-a8a67a36-2cf1-4f5c-8192-64298e0c6597.png](https://user-images.githubusercontent.com/41617388/131326021-a8a67a36-2cf1-4f5c-8192-64298e0c6597.png)" width="500px" />
</p>
<ul>
<li>C, C++, Rust 등으로 작성한 코드를 바이너리로 컴파일하고 그 결과를 웹 브라우저 환경에서 호출하고 실행할 수 있는 새로운 유형의 기술</li>
<li>JS 엔진 내에서 나란히 JS와 함께 실행된다.</li>
</ul>
<h1 id="웹-어셈블리의-역사">웹 어셈블리의 역사</h1>
<h2 id="모질라와-asmjs">모질라와 asm.js</h2>
<ul>
<li>2013년에 모질라가 발표한 asm.js는 C/C++ 코드를 JS로 변환하는 방법을 제공했다.</li>
<li>Emscripten과 같은 툴을 사용하면 C/C++ -> asm.js로 변환해 쉽게 배포할 수 있다.</li>
</ul>
<h2 id="그럼-왜-asmjs를-안씀-wasm이랑-똑같은데">그럼 왜 asm.js를 안씀? WASM이랑 똑같은데?</h2>
<ul>
<li>결국은 JS 코드, 큰 파일 사이즈</li>
<li>숫자만 가능 (연산에만 치중)</li>
<li>Web API 호출이 불가</li>
<li>WASM은 바이너리 형식이어서 더 효율적으로 전송될 수 있다.</li>
<li>WASM 모듈은 Promise 기반의 접근 방식을 사용 해 코드의 로드를 비동기적으로 처리한다.</li>
</ul>
<h1 id="wasm이-js보다-뭐가-나은데">WASM이 JS보다 뭐가 나은데?</h1>
<p><a href="https://hacks.mozilla.org/2017/02/what-makes-webassembly-fast/">https://hacks.mozilla.org/2017/02/what-makes-webassembly-fast/</a></p>
<p>WASM이 왜 빠른지 알기 위해서는 우선 JS의 실행 과정을 살펴보자.</p>
<p><img src="https://user-images.githubusercontent.com/41617388/130311879-10e0ee70-6014-4d84-a70c-0ecd942b58de.png" alt="https://user-images.githubusercontent.com/41617388/130311879-10e0ee70-6014-4d84-a70c-0ecd942b58de.png" /></p>
<ul>
<li>Parsing(파싱)
<ul>
<li>소스코드를 interpreter가 실행할 수 있도록 변경</li>
</ul>
</li>
<li>Compiling + Optimizing (컴파일 + 최적화)</li>
<li>Re-optimizing (재최적화)</li>
<li>Execution (실행)</li>
<li>Garbage Collection (가비지 콜렉팅)</li>
</ul>
<p>TradeOff는 모니터링과 컴파일링하는 과정이다. > 개선할 수 있음</p>
<h1 id="웹-어셈블리는-그럼-어떤데">웹 어셈블리는 그럼 어떤데?</h1>
<h2 id="1-fetching">1. Fetching</h2>
<ul>
<li>서버에서 파일을 fetching하는 과정</li>
<li>아무리 JS파일이 압축을 한다고 해도 WASM은 파일이 JS보다 더 작기 때문에(binary) 더 빠르게 fetching 한다.</li>
<li>따라서 클라이언트, 서버간의 통신이 더 빠르다는 뜻이다. 느린 네트워크 환경에서도 효율적으로 작동할 수 있다.</li>
</ul>
<h2 id="2-parse">2. Parse</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/130312543-2219dad6-2801-45aa-872d-85d196a7ac9e.png" alt="https://user-images.githubusercontent.com/41617388/130312543-2219dad6-2801-45aa-872d-85d196a7ac9e.png" /></p>
<ul>
<li>JS코드는 AST로 변환되고, 이로부터 JS엔진이 이해할 수 있는 중간 표현식 (Intermediate representation)인 bytecode를 생성한다.</li>
<li>WASM은 이미 중간 표현식으로 되어있으므로 이 과정이 불필요하다.</li>
<li>단지, 디코딩과 유효성 검사를 통해 오류 여부만 확인한다.</li>
</ul>
<h2 id="3-compile--optimizing">3. Compile + Optimizing</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/130312538-4ec1ecc8-95c9-47b2-9ad4-d68f67304856.png" alt="https://user-images.githubusercontent.com/41617388/130312538-4ec1ecc8-95c9-47b2-9ad4-d68f67304856.png" /></p>
<ul>
<li>JS는 실행 중에 컴파일링 된다. 어떤 코드들은 다시 컴파일 할 필요가 없는데도 컴파일 된다.</li>
<li>브라우저에 따라서 WASM 컴파일은 다르게 수행될 수 있지만, WASM 자체는 기계어에 가까우며, 명시적 타입이 사용되었다.</li>
<li>명시적 타입을 사용하면 이점이 뭔데?
<ul>
<li>컴파일을 시작하기 전에 어떤 타입인지 observe 하는 데 시간을 사용하지 않아도 된다.</li>
<li>컴파일러는 다른 타입을 기반으로 동일한 코드를 다른 버전으로 컴파일하지 않아도 된다.</li>
<li>최적화는 이미 LLVM에서 수행이 되어 컴파일 시간에 덜 해도 된다.</li>
</ul>
</li>
</ul>
<h2 id="4-reoptimizing">4. Reoptimizing</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/130312614-d6ce0158-c6d6-4b2d-93ed-f72f223ec188.png" alt="https://user-images.githubusercontent.com/41617388/130312614-d6ce0158-c6d6-4b2d-93ed-f72f223ec188.png" /></p>
<ul>
<li>JIT의 예측이 실패할 경우 재최적화가 실행된다.</li>
<li>prototype chain에 새 함수가 추가되거나 루프문에서 변수가 이전 반복에서 변경될때 수행</li>
<li>이미 최적화한 코드를 버리고 다시 최적화를 수행해야 한다.</li>
<li>다시 최적화한 코드를 재컴파일 해야한다.</li>
<li>WASM에서는 JIT이 assumption을 할 필요가 없다. 왜냐하면 명시적 타입이기 때문에..</li>
</ul>
<h2 id="5-executing">5. Executing</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/131213688-1d2d269e-b087-4240-99a6-694ee67bbd8c.png" alt="https://user-images.githubusercontent.com/41617388/131213688-1d2d269e-b087-4240-99a6-694ee67bbd8c.png" /></p>
<ul>
<li>JIT을 최적화하는 방법은 있긴 있지만, 그러려면 JIT의 내부 구조를 잘 알아야 한다.</li>
<li>대부분의 개발자는 잘 모르고, 하려고 해도 어렵다.</li>
<li>또한 브라우저마다 최적화가 다르기 때문에 브라우저 내부 코드로 인해 성능이 떨어질 수 있다.</li>
<li>JS가 필요로하는 최적화 방법들(타입 specialization)이 필요가 없다.</li>
<li>wasm은 컴파일러를 타겟으로 디자인되어 있어 컴파일러 최적화된 결과물을 출력한다. 컴퓨터에 더 이상적인 명령어로 구성될 수 있음을 말한다.</li>
</ul>
<h2 id="6-garbage-collecting">6. Garbage Collecting</h2>
<ul>
<li>JS 엔진이 알아서 콜렉팅을 해주지만, 어느 시점에 발생할지 알 수 없으므로 단점일 수가 있다.</li>
<li>WASM은 GC를 제공하지 않는다. 메모리는 C, C++처럼 manually 하게 관리해야 한다. 더 어렵게 만들수도 있지만, performance를 더 consistent 하게 할 수도 있다.</li>
</ul>
<h1 id="js와-web-api">JS와 Web API</h1>
<ul>
<li>JS, Web과 상호작용할 수 있는 API 사양을 발표했다.</li>
</ul>
<h2 id="웹어셈블리-네임스페이스-메소드">웹어셈블리 네임스페이스 메소드</h2>
<blockquote>
<p>브라우저 내의 전역 웹어셈블리 객체에서 사용할 수 있는 다양한 객체를 다룬다.</p>
</blockquote>
<h3 id="instantiate"><code class="language-plaintext highlighter-rouge">instantiate()</code></h3>
<ul>
<li>웹 어셈블리 코드를 컴파일하고 인스턴스화 하기 위한 기본 API</li>
</ul>
<h3 id="instantiatestreaming"><code class="language-plaintext highlighter-rouge">instantiateStreaming()</code></h3>
<ul>
<li>instantiate()와 동일한 기능을 수행하지만, 스트리밍을 통해 모듈을 컴파일하고 인스턴스화한다.</li>
</ul>
<h3 id="compile"><code class="language-plaintext highlighter-rouge">compile()</code></h3>
<ul>
<li>컴파일만 하고 인스턴스화는 X</li>
</ul>
<h3 id="compilestreaming"><code class="language-plaintext highlighter-rouge">compileStreaming()</code></h3>
<ul>
<li>스트리밍으로 compile</li>
</ul>
<h3 id="validate"><code class="language-plaintext highlighter-rouge">validate()</code></h3>
<ul>
<li>바이너리 코드 유효성 검사</li>
</ul>
<h2 id="wasm-모듈-로딩-과정">WASM 모듈 로딩 과정</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/131221733-3334fb98-35a1-4144-81d2-5489a741a8b7.png" alt="https://user-images.githubusercontent.com/41617388/131221733-3334fb98-35a1-4144-81d2-5489a741a8b7.png" /></p>
<ul>
<li>fetch로 wasm파일 가져오기</li>
<li>response로 받아온 Bytes를 ArrayBuffer 생성</li>
<li>buffer와 option으로 받은 import객체로 WebAssembly.instantiate() 호출</li>
</ul>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">example.wasm</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=></span> <span class="nx">response</span><span class="p">.</span><span class="nx">arrayBuffer</span><span class="p">())</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">buffer</span> <span class="o">=></span> <span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">instantiate</span><span class="p">(</span><span class="nx">buffer</span><span class="p">,</span> <span class="nx">importObj</span><span class="p">))</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(({</span><span class="nx">module</span><span class="p">,</span> <span class="nx">instance</span><span class="p">})</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">//모듈이나 인스턴스로 작업 수행</span>
<span class="p">})</span>
<span class="c1">// 위와 동일하지만 간단하게 한번에 처리해줌</span>
<span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">instantiateStreaming</span><span class="p">(</span><span class="nx">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">example.wasm</span><span class="dl">'</span><span class="p">),</span> <span class="nx">importObj</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(({</span><span class="nx">module</span><span class="p">,</span> <span class="nx">instance</span><span class="p">})</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">//모듈이나 인스턴스로 작업 수행</span>
<span class="p">})</span>
</code></pre></div></div>
<ul>
<li>WebAssembly.Module(module), WebAssembly.Instance(instance)를 포함하는 객체를 반환한다</li>
</ul>
<h2 id="webassembly-객체">WebAssembly 객체</h2>
<h3 id="webassemblymodule"><code class="language-plaintext highlighter-rouge">WebAssembly.Module</code></h3>
<ul>
<li>이미 컴파일 된 statelss 웹어셈블리 코드를 포함</li>
<li>Web Worker와 효과적으로 공유됨</li>
<li>IndexedDB에 캐싱됨</li>
<li>여러 번 인스턴스화 될 수 있음</li>
</ul>
<h3 id="webassemblyinstance"><code class="language-plaintext highlighter-rouge">WebAssembly.Instance</code></h3>
<ul>
<li>WebAssembly.Module의 상태가 저장되고 실행 가능한 인스턴스</li>
<li>익스포트된 웹어셈블리 함수를 호출할 수 있다</li>
<li>instance.exports.sayHello() : sayHello는 함수명</li>
</ul>
<h3 id="webassemblymemory"><code class="language-plaintext highlighter-rouge">WebAssembly.Memory</code></h3>
<ul>
<li>값을 저장하고 로드하는 데 사용할 수 있는 선형 배열. 사이즈 조절이 가능한 ArrayBuffer이다.</li>
<li>웹어셈블리 Instance에 의해서 접근되는 메모리를 담고 있음</li>
<li>JS, WASM 모두 해당 메모리에 접근하거나 변경 가능</li>
<li>새로운 Memory를 만들기 위해서는 인자로 initial값과 maximum? 값을 전달해줘야함</li>
</ul>
<h3 id="webassemblytable"><code class="language-plaintext highlighter-rouge">WebAssembly.Table</code></h3>
<ul>
<li>함수 참조를 저장하는 공간</li>
<li>JS, WASM 모두 해당 메모리에 접근하거나 변경 가능</li>
<li>element, initial, maximum?을 인자로 전달 가능</li>
<li>element는 테이블에 저장될 값의 유형을 말함. 현재는 ‘anyfunc’만 가능</li>
<li>get(), set()으로 요소들에 접근 가능</li>
</ul>
<h3 id="webassemblycompileerror"><code class="language-plaintext highlighter-rouge">WebAssembly.CompileError</code></h3>
<ul>
<li>디코딩, 혹은 유효성 검사 시 발생하는 에러</li>
</ul>
<h3 id="webassemblylinkerror"><code class="language-plaintext highlighter-rouge">WebAssembly.LinkError</code></h3>
<ul>
<li>인스턴스화 하는 동안 문제가 발생</li>
</ul>
<h3 id="webassemblyruntimeerror"><code class="language-plaintext highlighter-rouge">WebAssembly.RuntimeError</code></h3>
<h1 id="튜토리얼">튜토리얼</h1>
<p>현재 WASM을 사용하는 방법은 총 4가지가 있다.</p>
<ol>
<li>Emscripten으로 c/c++ 애플리케이션 포팅하기.</li>
<li>어셈블리 수준에서 바로 WebAssembly를 작성하거나 생성하기.</li>
<li>Rust 응용 프로그램을 작성하고 WebAssembly를 출력으로 지정합니다.</li>
<li>TypeScript와 비슷한 AssemblyScript를 사용하여 WebAssembly바이너리 컴파일.</li>
</ol>
<h1 id="emscripten">Emscripten</h1>
<p><img src="https://user-images.githubusercontent.com/41617388/131340859-605f0ce0-fcbd-4576-b248-114a18b2062e.png" alt="https://user-images.githubusercontent.com/41617388/131340859-605f0ce0-fcbd-4576-b248-114a18b2062e.png" /></p>
<ul>
<li>C/C++ 소스코드를 clang+LLVM (오픈소스 C/C++ 컴파일러 툴체인)에 던져준다.</li>
<li>컴파일 결과를 받아다가 .wasm 바이너리로 변환시킨다.</li>
<li>HTML과 자바스크립트 글루 코드를 생성한다.
<ol>
<li>Emscripten SDK 설치</li>
</ol>
</li>
</ul>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone <https://github.com/emscripten-core/emsdk.git>
<span class="nb">cd </span>emsdk
<span class="c"># Download and install the latest SDK tools.</span>
./emsdk <span class="nb">install </span>latest
<span class="c"># 현재 사용자를 위한 최신 버전의 SDK를 활성화한다</span>
./emsdk activate latest
<span class="c"># Activate PATH and other environment variables in the current terminal</span>
<span class="nb">source</span> ./emsdk_env.sh
</code></pre></div></div>
<ol>
<li>C파일 작성</li>
</ol>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">printf</span><span class="p">(</span><span class="s">"Hello World!</span><span class="se">\\</span><span class="s">n"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<ol>
<li>컴파일</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emcc main.c -Os
-s WASM=1 -s
-o $(출력 파일 명)
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">Os</code> 컴파일 최적화 레벨. 모듈 인스턴스화를 허용한다</li>
<li><code class="language-plaintext highlighter-rouge">s WASM=1</code> 컴파일러가 코드를 WASM으로 컴파일하게 만든다</li>
<li><code class="language-plaintext highlighter-rouge">SIDE_MODULE=1</code> 웹 어셈블리 모듈만을 출력한다</li>
<li><code class="language-plaintext highlighter-rouge">o</code> 출력 파일 경로
<ol>
<li>WASM 파일 생성 완료!</li>
</ol>
</li>
</ul>
<h2 id="glue-code">Glue Code</h2>
<p>컴파일된 wasm 파일을 JS로 로딩하기 위해서는 glue code가 필요하다.</p>
<h3 id="html과-글루-코드-출력">HTML과 글루 코드 출력</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emcc with-glue.c -Os -s WASM=1 -o with-glue.html
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">o</code>의 확장자를 <code class="language-plaintext highlighter-rouge">html</code>로 하면 html파일과 js파일이 자동으로 만들어진다.</li>
<li>C/C++의 main을 html이 로드 되자마자 실행 할 것이다.</li>
</ul>
<h3 id="사용자-정의-html-템플릿-사용">사용자 정의 HTML 템플릿 사용</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emcc custom-loading.c -Os -s WASM=1 \\
-o custom-loading.js
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><</span><span class="nx">script</span> <span class="nx">type</span><span class="o">=</span><span class="dl">"</span><span class="s2">application/javascript</span><span class="dl">"</span> <span class="nx">src</span><span class="o">=</span><span class="dl">"</span><span class="s2">custom-loading.js</span><span class="dl">"</span><span class="o">><</span><span class="sr">/script</span><span class="err">>
</span>
<span class="nx">Module</span><span class="p">({</span>
<span class="na">canvas</span><span class="p">:</span> <span class="p">(()</span> <span class="o">=></span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">canvas</span><span class="dl">'</span><span class="p">))(),</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">Loaded!</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<ul>
<li>를 html에 추가</li>
</ul>
<h2 id="글루-코드-없이-c컴파일">글루 코드 없이 C컴파일</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> emcc without-glue.c -Os -s WASM=1 -s SIDE_MODULE=1 \\
-s EXPORTED_FUNCTIONS='["_doubler"]' \\
-o without-glue.wasm
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><</span><span class="nx">script</span> <span class="nx">type</span><span class="o">=</span><span class="dl">"</span><span class="s2">application/javascript</span><span class="dl">"</span><span class="o">></span>
<span class="c1">// importObj</span>
<span class="kd">const</span> <span class="nx">env</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">loadWasm</span><span class="p">(</span><span class="dl">'</span><span class="s1">without-glue.wasm</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="nx">env</span> <span class="p">})</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(({</span> <span class="nx">instance</span> <span class="p">})</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">instance</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">m</span> <span class="o">=</span> <span class="nx">instance</span><span class="p">.</span><span class="nx">exports</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">m</span><span class="p">.</span><span class="nx">doubler</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">});</span>
<span class="o"><</span><span class="sr">/script</span><span class="err">>
</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* Emscripten의 WASM 모듈을 위한 WebAssembly.Instance 생성자에 전달할
* importObj.env 객체를 디폴트 값으로 셋팅 후 반환한다.
*/</span>
<span class="kd">const</span> <span class="nx">getDefaultEnv</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">({</span>
<span class="na">__memory_base</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="na">__table_base</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="na">memory</span><span class="p">:</span> <span class="k">new</span> <span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">Memory</span><span class="p">({</span> <span class="na">initial</span><span class="p">:</span> <span class="mi">256</span> <span class="p">}),</span>
<span class="na">table</span><span class="p">:</span> <span class="k">new</span> <span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">Table</span><span class="p">({</span> <span class="na">initial</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="na">element</span><span class="p">:</span> <span class="dl">'</span><span class="s1">anyfunc</span><span class="dl">'</span> <span class="p">}),</span>
<span class="na">abort</span><span class="p">:</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">,</span>
<span class="p">});</span>
<span class="cm">/**
* 지정된 .wasm 파일로부터 컴파일된 WebAssembly.Instance 인스턴스를 반환한다.
*/</span>
<span class="kd">function</span> <span class="nx">loadWasm</span><span class="p">(</span><span class="nx">fileName</span><span class="p">,</span> <span class="nx">importObj</span> <span class="o">=</span> <span class="p">{</span> <span class="na">env</span><span class="p">:</span> <span class="p">{}</span> <span class="p">})</span> <span class="p">{</span>
<span class="c1">// 지정된 importObj.env 값으로 디폴트 env값을 재설정한다.</span>
<span class="kd">const</span> <span class="nx">allEnv</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">({},</span> <span class="nx">getDefaultEnv</span><span class="p">(),</span> <span class="nx">importObj</span><span class="p">.</span><span class="nx">env</span><span class="p">);</span>
<span class="c1">// importObj값이 유효한지 확인한다.</span>
<span class="kd">const</span> <span class="nx">allImports</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">({},</span> <span class="nx">importObj</span><span class="p">,</span> <span class="p">{</span> <span class="na">env</span><span class="p">:</span> <span class="nx">allEnv</span> <span class="p">});</span>
<span class="c1">// 모듈을 인스턴스화한 결과를 리턴한다. (인스턴스와 모듈)</span>
<span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">ok</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">response</span><span class="p">.</span><span class="nx">arrayBuffer</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">`Unable to fetch WebAssembly file </span><span class="p">${</span><span class="nx">fileName</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">bytes</span> <span class="o">=></span> <span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">instantiate</span><span class="p">(</span><span class="nx">bytes</span><span class="p">,</span> <span class="nx">allImports</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>
<hr />
<h1 id="emscripten-module">Emscripten Module</h1>
<ul>
<li>Emscripten의 자바스크립트 글루 코드를 가져와 로딩한 후에는 Module을 전역적인 범위(window.Module)에서 사용할 수 있다.</li>
</ul>
<h2 id="js에서-컴파일된-cc-함수-호출">JS에서 컴파일된 C/C++ 함수 호출</h2>
<h3 id="moduleccall"><code class="language-plaintext highlighter-rouge">Module.ccall()</code></h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ccall</span><span class="p">(</span><span class="n">ident</span><span class="p">,</span> <span class="n">returnType</span><span class="p">,</span> <span class="n">argTypes</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">opts</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">ccall</span><span class="p">(</span>
<span class="dl">'</span><span class="s1">c_add</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// 함수 이름</span>
<span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// 리턴 타입</span>
<span class="p">[</span><span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">],</span> <span class="c1">// 인자 타입</span>
<span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">]</span> <span class="c1">// 인자</span>
<span class="p">)</span>
<span class="c1">// 30</span>
</code></pre></div></div>
<ul>
<li>JS에서 컴파일 된 C함수를 호출하여 결과를 반환함</li>
</ul>
<h3 id="modulecwrap"><code class="language-plaintext highlighter-rouge">Module.cwrap()</code></h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cwrap</span><span class="p">(</span><span class="n">ident</span><span class="p">,</span> <span class="n">returnType</span><span class="p">,</span> <span class="n">argTypes</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">c_javascript_add</span> <span class="o">=</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">cwrap</span><span class="p">(</span>
<span class="dl">'</span><span class="s1">c_add</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// 함수 이름</span>
<span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">,</span> <span class="c1">// 리턴 타입</span>
<span class="p">[</span><span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">number</span><span class="dl">'</span><span class="p">],</span> <span class="c1">// 인자 타입</span>
<span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">c_javascript_add</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">));</span> <span class="c1">// 30</span>
</code></pre></div></div>
<ul>
<li>결과가 아닌 재사용 가능한 JS 함수를 반환</li>
</ul>
<h3 id="wasm-인스턴스에서-호출">WASM 인스턴스에서 호출</h3>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">WebAssembly</span><span class="p">.</span><span class="nx">instantiateStreaming</span><span class="p">(</span><span class="nx">fetch</span><span class="p">(</span><span class="dl">'</span><span class="s1">simple.wasm</span><span class="dl">'</span><span class="p">),</span> <span class="nx">importObj</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">result</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">addNumbers</span> <span class="o">=</span> <span class="nx">result</span><span class="p">.</span><span class="nx">instatnce</span><span class="p">.</span><span class="nx">exports</span><span class="p">.</span><span class="nx">_addTwoNumbers</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
<span class="c1">// 3</span>
<span class="p">});</span>
</code></pre></div></div>
<h2 id="cc에서-js-함수-호출">C/C++에서 JS 함수 호출</h2>
<h3 id="emscripten_run_script로-코드-문자열-실행">emscripten_run_script()로 코드 문자열 실행</h3>
<ul>
<li>가장 직접적이지만 다소 느린 방법</li>
<li>문자열을 코드로 인식해 eval()을 이용해 코드를 실행시킨다.</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>emscripten_run_script("alert('hi')");
</code></pre></div></div>
<h3 id="em_asm으로-인라인-js-실행">EM_ASM()으로 인라인 JS 실행</h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <emscripten.h>
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">EM_ASM</span><span class="p">({</span>
<span class="n">console</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="err">'</span><span class="n">js</span> <span class="n">code</span><span class="err">'</span> <span class="o">+</span> <span class="p">[</span><span class="err">$</span><span class="mi">0</span><span class="p">,</span> <span class="err">$</span><span class="mi">1</span><span class="p">]);</span>
<span class="p">},</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">30</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="em_js로-인라인-js-재사용">EM_JS()로 인라인 JS 재사용</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>EM_JS(return_type, function_name, arguments, code)
</code></pre></div></div>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include <emscripten.h>
</span><span class="n">EM_JS</span><span class="p">(</span><span class="kt">void</span><span class="p">,</span> <span class="n">take_args</span><span class="p">,</span> <span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">),</span> <span class="p">{</span>
<span class="n">console</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="err">`</span><span class="n">received</span> <span class="err">$</span><span class="p">{</span><span class="n">x</span><span class="p">},</span> <span class="err">$</span><span class="p">{</span><span class="n">y</span><span class="p">}</span><span class="err">`</span><span class="p">)</span>
<span class="p">});</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">take_args</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="emscripten_keepalive">EMSCRIPTEN_KEEPALIVE</h3>
<ul>
<li>모듈 외부에서 함수를 사용하려면 선언해야함</li>
<li>아니면 컴파일러는 데드코드로 취급해 제거</li>
</ul>
<h2 id="글루-코드-없이-js와-통합">글루 코드 없이 JS와 통합</h2>
<ul>
<li>C/C++ 파일 안에서 JS를 작성하기보다는 웹어셈블리 인스턴스화 코드에 함수를 전달한다.</li>
</ul>
<h3 id="import-객체를-이용">import 객체를 이용</h3>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">env</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">_exampleFunc</span><span class="p">:</span> <span class="nx">value</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`echo </span><span class="p">${</span><span class="nx">value</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>importObj.env에 함수를 정의하여 추가</li>
</ul>
<h3 id="cc에서-import된-함수를-호출">C/C++에서 import된 함수를 호출</h3>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">loadWasm</span><span class="p">(</span><span class="err">'</span><span class="n">main</span><span class="p">.</span><span class="n">wasm</span><span class="err">'</span><span class="p">,</span> <span class="p">{</span><span class="n">env</span><span class="p">})</span>
<span class="p">.</span><span class="n">then</span><span class="p">(({</span><span class="n">instance</span><span class="p">})</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">const</span> <span class="n">result</span> <span class="o">=</span> <span class="n">instance</span><span class="p">.</span><span class="n">exports</span><span class="p">.</span><span class="n">_exampleFunc</span><span class="p">(</span><span class="mi">33</span><span class="p">);</span>
<span class="n">console</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
<span class="c1">// 33이 두 번 출력 됨</span>
<span class="p">})</span>
</code></pre></div></div>
<h1 id="고급-기능">고급 기능</h1>
<h2 id="fetch-api">fetch API</h2>
<ul>
<li>Emscripten은 fetch API를 지원한다.</li>
<li>XHR로 파일을 전송할 수 있도록 해주며,</li>
<li>브라우저의 로컬 IndexedDB 저장소에 다운로드한 파일을 유지시킨다.</li>
<li>네트워크 요청은 비동기/동기로 선택해서 요청 가능하다</li>
</ul>
<h2 id="file-system-api">File System API</h2>
<ul>
<li>FS 라이브러리를 사용 해 파일 작업을 지원한다.</li>
</ul>
<h1 id="assemblyscript">AssemblyScript</h1>
<ul>
<li><a href="https://www.assemblyscript.org/introduction.html">링크</a></li>
<li>TypeScript 기반</li>
<li>컴파일이 statically하게 된다. JIT과는 다른 방식! (C/C++과 같이..)</li>
<li>문제는 아직 정식 release가 안 된것 같음</li>
</ul>
<h1 id="use-cases">Use cases</h1>
<p><a href="https://madewithwebassembly.com/">https://madewithwebassembly.com/</a></p>
<ul>
<li>figma</li>
<li>sketch up</li>
<li>구글 어스</li>
<li>autocad in web</li>
<li>그 외 게임들..</li>
</ul>
<h1 id="단점">단점?</h1>
<ul>
<li>높은 러닝커브</li>
<li>C/C++ 기반 지식이 필요</li>
<li>보안 문제</li>
<li>GC가 없음</li>
<li>DOM에 대한 직접적인 접근이 없음</li>
</ul>
<h1 id="이후-로드맵">이후 로드맵</h1>
<ul>
<li>Garbage Collection</li>
<li>스레딩</li>
<li>모듈화 (WASM이 직접 Web API 호출)</li>
</ul>
<h1 id="ref">ref</h1>
<ul>
<li><a href="https://webassembly.org/">https://webassembly.org/</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/WebAssembly">https://developer.mozilla.org/ko/docs/WebAssembly</a></li>
<li><a href="https://www.assemblyscript.org/introduction.html">https://www.assemblyscript.org/introduction.html</a></li>
<li><a href="https://d2.naver.com/helloworld/8257914">https://d2.naver.com/helloworld/8257914</a></li>
<li>웹 어셈블리 (Wasm과 C/C++를 이용한 고성능 웹 어플리케이션 개발) - 마이크 루크</li>
</ul>
https://forbid403.github.io/fe/스크롤 이벤트 성능 이슈 (passive 옵션)
2022-01-25T00:00:00+09:00
2022-01-25T00:00:00+09:00
https://forbid403.github.io
<ul>
<li>일반적으로 이벤트들은 observable이 아니고, 콜백으로만 처리된다고 믿는다.</li>
<li>그래서 side-effect가 없다고 여길 수 있는데… 몇몇 이벤트들은 observing 할 수 있도록 구현되어 있다.</li>
<li><code class="language-plaintext highlighter-rouge">touchstart</code>, <code class="language-plaintext highlighter-rouge">touchmove</code>, <code class="language-plaintext highlighter-rouge">wheel 이벤트</code> 핸들러들은 이벤트 발생 시 <code class="language-plaintext highlighter-rouge">preventDefault()</code>를 호출하는지 확인한다. (중간에 멈춰야 하는 지 확인하기 위해)</li>
<li>따라서 단순히 이벤트 리스너만 등록하더라도.. 성능 상으로는 큰 delay가 생길 수도 있다.
<ul>
<li>10%의 이벤트들은 100ms delay 발생, 최악의 경우(약 1%) 500ms 까지 딜레이 발생.</li>
</ul>
</li>
</ul>
<h2 id="해결방법">해결방법</h2>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">element</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">touchstart</span><span class="dl">'</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="na">passive</span><span class="p">:</span> <span class="kc">true</span><span class="p">});</span>
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">{passive:true}</code>옵션을 줌으로서 <code class="language-plaintext highlighter-rouge">preventDefault</code>를 호출하지 않겠다고 알려준다.</li>
<li>스크롤 이벤트를 막지 않겠다고 브라우저에게 알려주기 때문에, lookup 연산을 절약할 수 있다.
<ul>
<li><a href="https://www.youtube.com/watch?v=NPM6172J22g">스크롤 성능 비교 영상</a></li>
</ul>
</li>
<li>다만, (당연하게도) <code class="language-plaintext highlighter-rouge">preventDefault</code>를 사용할 수 없다. 사용 시 에러가 발생한다.</li>
</ul>
<h2 id="주의사항">주의사항</h2>
<ul>
<li>Chrome 54+ 부터 <code class="language-plaintext highlighter-rouge">{passive:true}</code>가 default가 되기 때문에, <code class="language-plaintext highlighter-rouge">preventDefault</code> 작업이 필요하다면 설정해줘야 한다.</li>
<li>패시브 옵션이 없는 구버전 브라우저를 지원해야 하는 경우 polyfill이나 passive 옵션을 적용하는지 검사를 따로 해줘야 한다.</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// passive 옵션 지원 확인</span>
<span class="kd">let</span> <span class="nx">supportsPassive</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="kd">get</span> <span class="nx">passive</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">isPassiveSupport</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,</span> <span class="nx">options</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">removeEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,</span> <span class="nx">options</span><span class="p">,</span> <span class="nx">options</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">isPassiveSupport</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">touchstart</span><span class="dl">'</span><span class="p">,</span> <span class="nx">callback</span><span class="p">,</span> <span class="nx">supportsPassive</span> <span class="p">?</span> <span class="p">{</span> <span class="na">passive</span><span class="p">:</span><span class="kc">true</span> <span class="p">}</span> <span class="p">:</span> <span class="kc">false</span><span class="p">);</span>
</code></pre></div></div>
<ul>
<li>+) react17 부터 <code class="language-plaintext highlighter-rouge">{passive: true}</code>가 디폴트이기 때문에 <code class="language-plaintext highlighter-rouge">preventDefault</code>가 필요할 시 옵션에 추가 해줘야 한다.</li>
</ul>
<h2 id="refs">refs</h2>
<ul>
<li><a href="https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md">https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md</a></li>
</ul>
https://forbid403.github.io/fe/Mock Service Worker
2022-01-19T00:00:00+09:00
2022-01-19T00:00:00+09:00
https://forbid403.github.io
<h1 id="mock-service-worker">Mock Service Worker</h1>
<h2 id="service-worker">Service Worker?</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/149941338-4bc1770d-712a-4ef1-94c8-df7fb12f5757.png" alt="msw" /></p>
<ul>
<li>브라우저단에서 실행되는 백그라운드 스크립트</li>
<li>‘백그라운드’이기 때문에 웹페이지와는 별개로 동작한다. (non-blocking)</li>
<li>워커의 한 종류로, 서비스와 브라우저 및 네트워크 사이에서 프록시 서버의 역할을 한다.</li>
</ul>
<h2 id="발생-배경">발생 배경</h2>
<ul>
<li>오프라인에서 웹페이지를 사용자에게 보여줄 수 없을까 하는 고민에서 시작</li>
<li>네트워크 연결이 끊어졌을 경우, 캐싱을 통해 보여줄 수 있도록 만들고자 함.</li>
</ul>
<h2 id="사전-요구-사항">사전 요구 사항</h2>
<ul>
<li>브라우저 지원
<ul>
<li><a href="https://jakearchibald.github.io/isserviceworkerready/">https://jakearchibald.github.io/isserviceworkerready/</a></li>
<li>대부분의 브라우저가 지원한다. (IE 제외…)</li>
</ul>
</li>
<li>HTTPS
<ul>
<li>보안상의 이슈로 HTTPS에서만 동작</li>
<li>localhost는 http여도 사용 가능</li>
</ul>
</li>
<li>Worker이므로 DOM에 직접 접근 불가능
<ul>
<li>이벤트 드리븐 형식으로 웹페이지와는 별도의 쓰레드에서 동작한다.</li>
<li>postMessage 인터페이스를 통해 통신해야 함.</li>
</ul>
</li>
</ul>
<h2 id="what-is-msw">What is MSW?</h2>
<ul>
<li><a href="https://mswjs.io/">Mock Service Worker</a></li>
<li>네트워크 요청을 가로 채서 Mock 응답을 보내주는 역할을 한다.</li>
<li>Service Worker 기반으로 모킹하기 때문에 프레임워크나 라이브러리 종속성이 없다.</li>
</ul>
<h2 id="기타-제공되는-기능들">기타 제공되는 기능들</h2>
<ul>
<li>쿠키 지원</li>
<li>fallback 모드</li>
</ul>
<h2 id="어떻게-동작하나요">어떻게 동작하나요</h2>
<p><img src="https://user-images.githubusercontent.com/41617388/182169066-d6754820-981e-475d-9ba0-4f7e7d207de9.png" alt="image" /></p>
<ol>
<li>Service Worker <code class="language-plaintext highlighter-rouge">fetch</code> 이벤트로 app의 request listening</li>
<li><code class="language-plaintext highlighter-rouge">fetch</code> 이벤트가 발생하면, 라이브러리에서 mocked response 확인</li>
<li>만약 있다면, Service Worker의 <code class="language-plaintext highlighter-rouge">respondWith</code>으로 return</li>
</ol>
<h2 id="pros">Pros?</h2>
<ul>
<li>로직 분리가 가능
<ul>
<li>API 클래스를 그냥 둬도 된다.
<ul>
<li>추후에 json 제거 작업이 필요 없다.</li>
<li>mocking시 로직을 작성할 수 있다. (if 문을 api response 내부에서 해줄 필요가 없다)</li>
</ul>
</li>
<li>적용과 제거가 편리하다.
<ul>
<li>핸들러를 주석 처리만 해주면 된다.</li>
</ul>
</li>
</ul>
</li>
<li>네트워크 탭에서 확인할 수 있음
<ul>
<li>브라우저 입장에서는 실제 HTTP 요청이다.</li>
<li>DX적으로 실제 서버 API랑 interacting 한다는 느낌을 줌</li>
</ul>
</li>
<li>node 환경 상에서 실행 가능
<ul>
<li>non-browser 노드 환경에서도 mock이 공유가 가능함</li>
<li>즉, SSR 환경에서도 지원이 가능함.</li>
</ul>
</li>
<li>GQL 지원이 가능한 first-party API가 있음</li>
</ul>
<h2 id="문제점">문제점</h2>
<ul>
<li>브라우저 밖이기 때문에 에러 메세지가 정확하지 않음: 디버깅이 어려움</li>
<li>비-CORS는 실패</li>
<li>설치 이외의 추가적인 초기 셋팅이 필요</li>
<li>모든 엔드포인트를 작성 해 줘야 함</li>
</ul>
<h2 id="타-라이브러리와-비교">타 라이브러리와 비교</h2>
<ul>
<li>일반적으로 mocking시에는 두 가지 방법을 주로 사용한다.
<ol>
<li>서버를 구축</li>
<li>기존 http/https/fetch를 대체(stub)해서 intercept</li>
</ol>
</li>
</ul>
<p>하지만,</p>
<h3 id="서버를-구축할때-발생하는-이슈">서버를 구축할때 발생하는 이슈</h3>
<ul>
<li>당연히 실제 서버랑 다를 수 밖에 없음.</li>
<li>결국 2개의 서버를 관리하는 셈</li>
</ul>
<h3 id="네이티브-모듈을-확장">네이티브 모듈을 확장</h3>
<ul>
<li>좋은 타협안이긴 하지만,</li>
<li>네이티브 모듈을 확장하면 어쨌든 네이티브 모듈을 건드는 것이기 때문에 완전한 로직 분리가 불가능하다.</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align: center"> </th>
<th style="text-align: center">MirageJS</th>
<th style="text-align: center">Service Mocker</th>
<th style="text-align: center">JSON Server</th>
<th style="text-align: center"><strong>MSW</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">지원 API</td>
<td style="text-align: center">REST</td>
<td style="text-align: center">REST</td>
<td style="text-align: center">REST</td>
<td style="text-align: center">REST / GraphQL</td>
</tr>
<tr>
<td style="text-align: center">지원 환경</td>
<td style="text-align: center">Browser</td>
<td style="text-align: center">Browser</td>
<td style="text-align: center">Node / Browser</td>
<td style="text-align: center">Node / Browser</td>
</tr>
<tr>
<td style="text-align: center">구현</td>
<td style="text-align: center">네이티브 fetch, XHR을 stubbing 함으로서 어플리케이션 레벨에서 request를 인터셉트</td>
<td style="text-align: center">서비스워커를 등록하고 워커에서 mocked response 응답</td>
<td style="text-align: center">HTTP서버를 구축</td>
<td style="text-align: center">서비스워커 API를 활용해 네트워크 레벨에서 request 인터셉트</td>
</tr>
<tr>
<td style="text-align: center">적용</td>
<td style="text-align: center">기존 코드를 변경할 필요 없음</td>
<td style="text-align: center">빌드 워커 파일이 스코프 안에 존재 해야 함. sw-loader가 필요하거나, 서버에 Service-Worker-Allowed 헤더를 적용해야 함.</td>
<td style="text-align: center">기존 request를 mocking된 서버 엔드포인트를 가리키도록 해야 함.</td>
<td style="text-align: center">기존 코드를 변경할 필요 없음</td>
</tr>
<tr>
<td style="text-align: center">정의</td>
<td style="text-align: center">OOP, ORM</td>
<td style="text-align: center">Mocking 로직이 서비스 워커의 context에 있는 server.js에 작성됨</td>
<td style="text-align: center">커스텀 JSON file</td>
<td style="text-align: center">client-side에서 JS로 작성됨. App의 로직, util, typing을 재사용할 수 있음.</td>
</tr>
</tbody>
</table>
<h1 id="설치-방법">설치 방법</h1>
<p><a href="https://mswjs.io/docs/getting-started/install">Getting Started 참고</a></p>
<ol>
<li>msw 설치</li>
<li>서비스 워커 등록
<ul>
<li>public/ 하위에 serviceWorker 설정 파일 생성</li>
</ul>
</li>
<li>앱에 워커 적용</li>
</ol>
<h2 id="보안-이슈">보안 이슈</h2>
<ul>
<li>서비스 워커는 https에서만 동작한다.</li>
<li>하지만 크롬 설정으로 우회할 수 있다.
<ol>
<li>chrome://flags 접속</li>
<li>Insecure origins treated as secure 검색</li>
<li>사용할 도메인 추가 후 relaunch</li>
</ol>
<ul>
<li>ex) <a href="http://local-partners.worksmobile.com:3000/">http://local-partners.worksmobile.com:3000</a>
<ol>
<li>실행 시 콘솔에 해당 로그가 발생하면 적용이 된 것이다.</li>
</ol>
</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/41617388/182169198-20bb8ef9-8758-4c2e-85e5-2d09b4be31a2.png" alt="image" /></p>
</li>
</ul>
<h1 id="적용-방법">적용 방법</h1>
<ol>
<li>API 클래스를 작성한다.</li>
<li><code class="language-plaintext highlighter-rouge">mocks/handlers/...</code>에 핸들러를 작성한다.</li>
</ol>
<h1 id="request-handler">Request Handler</h1>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">rest</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">,</span> <span class="kc">null</span><span class="p">),</span>
<span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/user</span><span class="dl">'</span><span class="p">,</span> <span class="kc">null</span><span class="p">),</span>
</code></pre></div></div>
<ul>
<li><code class="language-plaintext highlighter-rouge">rest.{http메서드}</code>로 핸들러를 생성한다.</li>
<li>첫 번째 인자는 API 요청을 매핑하는 key 역할을 한다.</li>
<li>매핑 안하는 요청들은 bypassing 된다.</li>
<li>파라미터나 해싱은 제외 하고 매칭된다.</li>
<li>다음 세 가지 방법으로 매핑이 가능하다.
<ul>
<li>exact url</li>
<li>path</li>
<li>RegExp</li>
</ul>
</li>
</ul>
<h3 id="exact-url">exact url</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">rest</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1"><https://api.backend.dev/users></span><span class="dl">'</span><span class="p">,</span> <span class="nx">responseResolver</span><span class="p">)</span> <span class="c1">// full url</span>
<span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/invoices</span><span class="dl">'</span><span class="p">,</span> <span class="nx">invocesResolver</span><span class="p">)</span> <span class="c1">// 상대 경로</span>
</code></pre></div></div>
<ul>
<li>위와 같이 직접 url으로 매핑할 경우, 입력된 string에 엄격하게 매칭된다.</li>
<li>상대 경로인 경우 <code class="language-plaintext highlighter-rouge">location.origin</code>에 대해서 매핑된다.</li>
</ul>
<h3 id="path">path</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Matches:</span>
<span class="c1">// - /users/admin</span>
<span class="c1">// - /users/octocat</span>
<span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/users/*</span><span class="dl">'</span><span class="p">,</span> <span class="nx">responseResolver</span><span class="p">),</span>
<span class="nx">rest</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1"><https://api.backend.dev/user/:userId></span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">ctx</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// `userId` value becomes "abc-123"</span>
<span class="kd">const</span> <span class="p">{</span> <span class="nx">userId</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">params</span>
<span class="p">}),</span>
</code></pre></div></div>
<ul>
<li>wildcard를 사용하거나, <code class="language-plaintext highlighter-rouge">:paramName</code>을 사용할 수 있다.</li>
</ul>
<h3 id="regexp">RegExp</h3>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// This request handler would match all these requests:</span>
<span class="c1">// - DELETE <http://localhost:8080/posts/></span>
<span class="c1">// - DELETE <https://backend.dev/user/posts/></span>
<span class="nx">rest</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="sr">/</span><span class="se">\\</span><span class="sr">/</span><span class="nx">posts</span><span class="err">\\</span><span class="c1">//, responseResolver)</span>
</code></pre></div></div>
<h1 id="response-resolver">Response Resolver</h1>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/login</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">ctx</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">res</span><span class="p">(</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span>
<span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}),</span>
<span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<ul>
<li>response를 정의한다.</li>
<li>Response resolver는 세 개의 인자를 받는다.
<ul>
<li><code class="language-plaintext highlighter-rouge">[req](https://mswjs.io/docs/api/request)</code> request의 정보</li>
<li><code class="language-plaintext highlighter-rouge">[res](https://mswjs.io/docs/api/response)</code> mock response를 만드는데 사용되는 functional utility</li>
<li><code class="language-plaintext highlighter-rouge">[ctx](https://mswjs.io/docs/api/context)</code> status, header, body 등을 설정하는 데 사용 하는 함수 그룹</li>
</ul>
</li>
<li>ctx를 사용해서 response 값을 리턴한다.
<ul>
<li><a href="https://mswjs.io/docs/api/context/status">status</a> HTTP Status와 text를 셋팅한다.</li>
<li><a href="https://mswjs.io/docs/api/context/set">set</a> 헤더를 셋팅한다.</li>
<li><a href="https://mswjs.io/docs/api/context/body">body</a> raw response body를 셋팅한다.</li>
<li><a href="https://mswjs.io/docs/api/context/text">text</a> text 형식의 body를 셋팅한다. <code class="language-plaintext highlighter-rouge">Content-Type: text/plain</code> 헤더가 추가된다.</li>
<li><a href="https://mswjs.io/docs/api/context/json">json</a> json 형식의 body를 셋팅한다. <code class="language-plaintext highlighter-rouge">Content-Type: application/json</code> 헤더가 추가된다.</li>
<li><a href="https://mswjs.io/docs/api/context/xml">xml</a> xml 형식의 body를 셋팅한다. <code class="language-plaintext highlighter-rouge">Content-Type: test/xml</code> 헤더가 추가된다.</li>
<li><a href="https://mswjs.io/docs/api/context/delay">delay</a> response에 딜레이를 준다.</li>
<li><a href="https://mswjs.io/docs/api/context/fetch">fetch</a> 핸들러 내부에서 fetch를 실행한다.</li>
</ul>
</li>
</ul>
<h1 id="query-parameters">Query Parameters</h1>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/products</span><span class="dl">'</span><span class="p">,</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">ctx</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">productId</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">.</span><span class="nx">searchParams</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">id</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">productIds</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">.</span><span class="nx">searchParams</span><span class="p">.</span><span class="nx">getAll</span><span class="p">(</span><span class="dl">'</span><span class="s1">id</span><span class="dl">'</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">res</span><span class="p">(</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span>
<span class="nx">productId</span><span class="p">,</span>
<span class="p">}),</span>
<span class="p">)</span>
<span class="p">}),</span>
</code></pre></div></div>
<ul>
<li>request url에서 넘어온 파라미터들에 접근하려면, <code class="language-plaintext highlighter-rouge">searchParams</code> 프로퍼티를 사용하면 된다.</li>
<li>해당 프로퍼티의 값들은 <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams">UrlSearchParams</a>의 인스턴스이다. 해당 메서드들을 사용하면 된다.</li>
</ul>
<h1 id="recipes">Recipes</h1>
<h2 id="real-api-적용">Real API 적용</h2>
<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">rest</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1"><https://api.github.com/users/:username></span><span class="dl">'</span><span class="p">,</span> <span class="k">async</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">ctx</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// Perform an original request to the intercepted request URL</span>
<span class="kd">const</span> <span class="nx">originalResponse</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">ctx</span><span class="p">.</span><span class="nx">fetch</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">originalResponseData</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">originalResponse</span><span class="p">.</span><span class="nx">json</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">res</span><span class="p">(</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">json</span><span class="p">({</span>
<span class="na">location</span><span class="p">:</span> <span class="nx">originalResponseData</span><span class="p">.</span><span class="nx">location</span><span class="p">,</span>
<span class="na">firstName</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Not the real first name</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}),</span>
<span class="p">)</span>
<span class="p">}),</span>
</code></pre></div></div>
<ul>
<li>Mock response에서 실제 API를 호출할 수 있다.</li>
</ul>
https://forbid403.github.io/til/[TIL] webpack.config.js 살펴보기
2020-11-30T00:00:00+09:00
2020-11-30T00:00:00+09:00
https://forbid403.github.io
<p>React 개발 환경 설정 시 CRA로만 진행했었다. 멘토님께서 CRA는 불필요한 것들이 많으니 직접 customizing을 해 가는게 좋다고 해주셨다. React 공식 documentation에 나와있는 해당 <a href="https://blog.usejournal.com/creating-a-react-app-from-scratch-f3c693b84658">article</a>을 보며 React 개발 환경을 기초부터 진행 해 봤다. 이 과정에서 webpack.config.js에 있는 환경변수들의 의미를 살필 수 있었다.</p>
<h3 id="webpackconfigjs">webpack.config.js</h3>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">path</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">webpack</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">webpack</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1">// Where to start bundling</span>
<span class="c1">// 번들링을 시작하는 entry</span>
<span class="na">entry</span><span class="p">:</span> <span class="dl">"</span><span class="s2">./src/index.js</span><span class="dl">"</span><span class="p">,</span>
<span class="na">mode</span><span class="p">:</span> <span class="dl">"</span><span class="s2">development</span><span class="dl">"</span><span class="p">,</span>
<span class="c1">// Define how exported js modules are transformed (defined in rules list)</span>
<span class="c1">// exported된 js 모듈들을 어떻게 변환시킬지 정의한다. (rules 리스트에 작성)</span>
<span class="na">module</span><span class="p">:</span> <span class="p">{</span>
<span class="na">rules</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="c1">// conditions to match file</span>
<span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.(</span><span class="sr">js|jsx</span><span class="se">)</span><span class="sr">$/</span><span class="p">,</span>
<span class="c1">// match anything outside of node_modules and bower_components</span>
<span class="c1">// node_modules와 bower_components 이외의 파일들을 matching 한다</span>
<span class="na">exclude</span><span class="p">:</span> <span class="sr">/</span><span class="se">(</span><span class="sr">node_modules|bower_components</span><span class="se">)</span><span class="sr">/</span><span class="p">,</span>
<span class="na">loader</span><span class="p">:</span> <span class="dl">"</span><span class="s2">babel-loader</span><span class="dl">"</span><span class="p">,</span>
<span class="na">options</span><span class="p">:</span> <span class="p">{</span> <span class="na">presets</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">@babel/env</span><span class="dl">"</span><span class="p">]</span> <span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">css$/</span><span class="p">,</span>
<span class="na">use</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">style-loader</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">css-loader</span><span class="dl">"</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="c1">// specify which extensions Webpack will resolve</span>
<span class="c1">// 웹팩이 어떤 extension들을 resolve 할 것인지 정의</span>
<span class="na">resolve</span><span class="p">:</span> <span class="p">{</span> <span class="na">extensions</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">*</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">.jsx</span><span class="dl">"</span><span class="p">]</span> <span class="p">},</span>
<span class="c1">// ** notice **</span>
<span class="c1">// output.publicPath and devServer.publicPath are different!</span>
<span class="c1">// output.publicPath와 devServer.publicPath는 다르다</span>
<span class="c1">// Where to put bundled code</span>
<span class="c1">// 번들링된 코드를 어디에 둘 것인지 정의</span>
<span class="na">output</span><span class="p">:</span> <span class="p">{</span>
<span class="c1">// what directory bundle should go in</span>
<span class="c1">// webpack-dev-server serve files from here</span>
<span class="c1">// bundle된 것이 어디에 저장 될 것인지 정의</span>
<span class="c1">// webpack-dev-server가 여기에서 파일들을 serve한다.</span>
<span class="na">path</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">"</span><span class="s2">dist/</span><span class="dl">"</span><span class="p">),</span>
<span class="c1">// specifies the public URL of the directory for dev-server</span>
<span class="c1">// if thie set is wrong, will retrun 404</span>
<span class="c1">// dev-server이 접근할 public URL을 정의한다.</span>
<span class="c1">// 잘못 정의할 시 404 코드를 리턴한다.</span>
<span class="na">publicPath</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/dist/</span><span class="dl">"</span><span class="p">,</span>
<span class="na">filename</span><span class="p">:</span> <span class="dl">"</span><span class="s2">bundle.js</span><span class="dl">"</span>
<span class="p">},</span>
<span class="c1">// For dev server</span>
<span class="na">devServer</span><span class="p">:</span> <span class="p">{</span>
<span class="c1">// location where the static files exist</span>
<span class="c1">// static 파일들이 어디에 위치해야 하는지</span>
<span class="na">contentBase</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">"</span><span class="s2">public/</span><span class="dl">"</span><span class="p">),</span>
<span class="na">port</span><span class="p">:</span> <span class="mi">3000</span><span class="p">,</span>
<span class="c1">// tell server where our bundled code is located</span>
<span class="c1">// Dev server에게 번들링된 코드라 어디에 존재하는지 알려줌</span>
<span class="na">publicPath</span><span class="p">:</span> <span class="dl">"</span><span class="s2">http://localhost:3000/dist/</span><span class="dl">"</span><span class="p">,</span>
<span class="c1">// Hot Module Replacement</span>
<span class="c1">// module will updated at runtime without fully refreshing</span>
<span class="c1">// HMR을 이용할 시 refresh하지 않고도 module이 업데이트 된다.</span>
<span class="na">hotOnly</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">},</span>
<span class="na">plugins</span><span class="p">:</span> <span class="p">[</span><span class="k">new</span> <span class="nx">webpack</span><span class="p">.</span><span class="nx">HotModuleReplacementPlugin</span><span class="p">()]</span>
<span class="p">};</span>
</code></pre></div></div>
<p>Article을 보면 좀 더 풀어서 설명되어 있으니 참고하길 바란다.</p>
https://forbid403.github.io/algorithm/[leetcode] House Robber III
2020-11-24T00:00:00+09:00
2020-11-24T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-house-robber-iii">[leetcode] House Robber III</h2>
<p><a href="https://leetcode.com/problems/house-robber-iii/">문제 링크</a></p>
<h3 id="recursive-시간-초과">Recursive (시간 초과)</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">dfs</span><span class="p">(</span><span class="n">TreeNode</span> <span class="o">*</span><span class="n">cur</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">isParentRobbed</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">isParentRobbed</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// cannot rob here</span>
<span class="k">return</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">left</span><span class="p">,</span> <span class="nb">false</span><span class="p">)</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">// rob here</span>
<span class="kt">int</span> <span class="n">rob</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">val</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">left</span><span class="p">,</span> <span class="nb">true</span><span class="p">)</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">not_rob</span> <span class="o">=</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">left</span><span class="p">,</span> <span class="nb">false</span><span class="p">)</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
<span class="k">return</span> <span class="n">max</span><span class="p">(</span><span class="n">rob</span><span class="p">,</span> <span class="n">not_rob</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">rob</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">dfs</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>연결된 노드끼리 도둑질을 하면 안 되기 때문에, 부모 노드에 따라 훔칠지 훔치지 않을지가 결정된다.</li>
<li>만약 부모 노드를 훔쳤다면, 자식 노드는 훔치면 안된다.</li>
<li>부모 노드를 훔치지 않았다면, 자식 노드를 훔치거나, 훔치지 않거나의 두 경우로 나뉜다.
<ul>
<li>이 경우에는 훔친 경우, 훔치지 않은 경우를 비교 해 큰 값을 저장해주면 된다.</li>
</ul>
</li>
<li>이렇게 풀면 시간초과가 난다.</li>
</ul>
<h3 id="memoization">Memoization</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="n">unordered_map</span><span class="o"><</span><span class="n">TreeNode</span><span class="o">*</span><span class="p">,</span> <span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">>></span> <span class="n">m</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">dfs</span><span class="p">(</span><span class="n">TreeNode</span> <span class="o">*</span><span class="n">cur</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">isParentRobbed</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">cur</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="o">!=</span> <span class="n">m</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">&&</span> <span class="n">m</span><span class="p">[</span><span class="n">cur</span><span class="p">][</span><span class="n">isParentRobbed</span><span class="p">]</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="n">m</span><span class="p">[</span><span class="n">cur</span><span class="p">][</span><span class="n">isParentRobbed</span><span class="p">];</span>
<span class="k">else</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">m</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">cur</span><span class="p">)</span> <span class="o">==</span> <span class="n">m</span><span class="p">.</span><span class="n">end</span><span class="p">())</span> <span class="n">m</span><span class="p">[</span><span class="n">cur</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">};</span>
<span class="kt">int</span> <span class="n">rob</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">val</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">left</span><span class="p">,</span> <span class="nb">true</span><span class="p">)</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">not_rob</span> <span class="o">=</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">left</span><span class="p">,</span> <span class="nb">false</span><span class="p">)</span> <span class="o">+</span> <span class="n">dfs</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">isParentRobbed</span><span class="p">)</span> <span class="k">return</span> <span class="n">m</span><span class="p">[</span><span class="n">cur</span><span class="p">][</span><span class="n">isParentRobbed</span><span class="p">]</span> <span class="o">=</span> <span class="n">not_rob</span><span class="p">;</span>
<span class="k">else</span> <span class="k">return</span> <span class="n">m</span><span class="p">[</span><span class="n">cur</span><span class="p">][</span><span class="n">isParentRobbed</span><span class="p">]</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">not_rob</span><span class="p">,</span> <span class="n">rob</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">rob</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">dfs</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>중복된 계산을 제거 해 주기 위해 해쉬 맵을 사용해 결과를 저장해준다.</li>
<li>맵에 계산 결과가 저장 되어 있다면, 해당 결과를 리턴한다.</li>
<li>결과가 저장 되어 있지 않다면 훔친 경우, 훔치지 않은 경우를 맵에 저장하여 리턴한다.</li>
</ul>
https://forbid403.github.io/algorithm/[leetcode] Flatten Binary Tree to Linked List
2020-11-22T00:00:00+09:00
2020-11-22T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-flatten-binary-tree-to-linked-list">[leetcode] Flatten Binary Tree to Linked List</h2>
<p><a href="https://leetcode.com/problems/flatten-binary-tree-to-linked-list/">문제 링크</a></p>
<h3 id="recursion">Recursion</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">void</span> <span class="n">flatten</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">root</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="n">flatten</span><span class="p">(</span><span class="n">root</span><span class="o">-></span><span class="n">left</span><span class="p">);</span>
<span class="n">flatten</span><span class="p">(</span><span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">root</span><span class="o">-></span><span class="n">left</span><span class="p">)</span> <span class="p">{</span>
<span class="n">TreeNode</span> <span class="o">*</span><span class="n">right</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">;</span> <span class="c1">// save right node</span>
<span class="n">root</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">left</span><span class="p">;</span>
<span class="n">root</span><span class="o">-></span><span class="n">left</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">)</span> <span class="n">root</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">;</span>
<span class="n">root</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">right</span><span class="p">;</span>
<span class="n">flatten</span><span class="p">(</span><span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<h3 id="iterative">Iterative</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="kt">void</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">TreeNode</span><span class="o">*</span> <span class="n">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span><span class="p">(</span><span class="n">root</span><span class="p">)</span> <span class="p">{</span>
<span class="n">TreeNode</span> <span class="o">*</span><span class="n">cur</span> <span class="o">=</span> <span class="n">root</span><span class="p">;</span>
<span class="n">TreeNode</span> <span class="o">*</span><span class="n">right</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">;</span>
<span class="n">root</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">left</span><span class="p">;</span>
<span class="n">root</span><span class="o">-></span><span class="n">left</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">)</span> <span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">right</span><span class="p">;</span>
<span class="n">cur</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">right</span><span class="p">;</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">root</span><span class="o">-></span><span class="n">right</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<ul>
<li>후위 순회로 가장 아래에 있는 노드중, 작은 값부터 계산해서 올라온다.</li>
<li>만약 Left가 있다면, right을 저장해 놓고, left를 right로 옮긴다.</li>
<li>저장된 right를 맨 아래 right에 부착한다.</li>
</ul>
https://forbid403.github.io/algorithm/[leetcode] Search in Rotated Sorted Array
2020-11-21T00:00:00+09:00
2020-11-21T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-search-in-rotated-sorted-array">[leetcode] Search in Rotated Sorted Array</h2>
<p><a href="https://leetcode.com/problems/search-in-rotated-sorted-array/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">search</span><span class="p">(</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">>&</span> <span class="n">arr</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">arr</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o"><=</span> <span class="n">right</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o">==</span> <span class="n">target</span><span class="p">)</span> <span class="k">return</span> <span class="n">mid</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o"><=</span> <span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">])</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o"><</span> <span class="n">target</span> <span class="o">&&</span> <span class="n">target</span> <span class="o"><=</span> <span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">])</span> <span class="n">left</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">else</span> <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o">></span> <span class="n">target</span> <span class="o">&&</span> <span class="n">target</span> <span class="o">>=</span> <span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">])</span> <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">else</span> <span class="n">left</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>엄청 헷갈리는 문제라서 제대로 정리하기 위해 기록한다.</li>
<li>이분탐색으로 접근하면 되는 문제이다.
<img width="729" alt="ex1" src="https://user-images.githubusercontent.com/41617388/99877171-8623ff80-2c3f-11eb-9786-b0503962fe91.png" />
<img width="721" alt="ex2" src="https://user-images.githubusercontent.com/41617388/99877173-88865980-2c3f-11eb-809a-7b33ab8b6cfe.png" /></li>
<li>첫 번째 배열과 두 번째 배열로 나뉠 것이다.
<ul>
<li><code class="language-plaintext highlighter-rouge">4,5,6,7,1,2,3</code>이라면, <code class="language-plaintext highlighter-rouge">4,5,6,7</code>은 첫 번째 배열, <code class="language-plaintext highlighter-rouge">1,2,3</code>을 두 번째 배열이라고 하자.</li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">arr[mid] <= arr[right]</code>일 때, (mid->right으로 오름차순으로 배열된 배열)
<ul>
<li><code class="language-plaintext highlighter-rouge">arr[mid] < target <= arr[right]</code> 이라면, target과 mid가 같은 배열에 있기 때문에 left를 mid+1로 옮겨서 범위를 좁혀준다.</li>
<li>이외의 경우에는 target과 mid가 다른 배열에 있기 때문에 right을 mid-1로 옮겨준다.</li>
</ul>
</li>
<li>이외의 경우일 때, (섞인 배열)
<ul>
<li><code class="language-plaintext highlighter-rouge">arr[left] <= target < arr[mid]</code> 이라면, target과 mid가 다른 배열에 있기 때문에 right = mid-1이 된다.</li>
<li>이하 같다.</li>
</ul>
</li>
</ul>
https://forbid403.github.io/algorithm/[leetcode] Decode String
2020-11-19T00:00:00+09:00
2020-11-19T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-decode-string">[leetcode] Decode String</h2>
<p><a href="https://leetcode.com/problems/decode-string/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="n">string</span> <span class="n">decodeString</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="n">stack</span> <span class="o"><</span><span class="kt">char</span><span class="o">></span> <span class="n">st</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">char</span> <span class="n">c</span><span class="o">:</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">c</span> <span class="o">==</span> <span class="sc">']'</span><span class="p">)</span> <span class="p">{</span>
<span class="n">string</span> <span class="n">temp</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">()</span> <span class="o">==</span> <span class="sc">'['</span><span class="p">)</span> <span class="p">{</span> <span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span> <span class="k">break</span><span class="p">;</span> <span class="p">}</span>
<span class="n">temp</span> <span class="o">+=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
<span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">reverse</span><span class="p">(</span><span class="n">temp</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">temp</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="n">string</span> <span class="n">number</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">()</span> <span class="o">&&</span> <span class="n">isdigit</span><span class="p">(</span><span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">())){</span>
<span class="n">number</span> <span class="o">=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">()</span> <span class="o">+</span> <span class="n">number</span><span class="p">;</span>
<span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">num</span> <span class="o">=</span> <span class="n">stoi</span><span class="p">(</span><span class="n">number</span><span class="p">);</span>
<span class="k">while</span><span class="p">(</span><span class="n">num</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">temp</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">temp</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">string</span> <span class="n">ans</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
<span class="n">ans</span> <span class="o">+=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
<span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">reverse</span><span class="p">(</span><span class="n">ans</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">ans</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>코테에서 비슷한 문제를 본 것 같아서 기록한다.</li>
<li><code class="language-plaintext highlighter-rouge">]</code>가 아니면 스택에 넣어주고,</li>
<li><code class="language-plaintext highlighter-rouge">]</code>를 만나면 해당 괄호를 처리 해 준다.
<ul>
<li>괄호가 닫힐 때까지 글자들을 더해준다.</li>
<li>괄호가 닫히면 더한 글자들을 거꾸로 돌려준다.</li>
<li>괄호 앞의 숫자들을 구한다.</li>
<li>숫자만큼 글자들을 스택에 다시 넣어준다.</li>
</ul>
</li>
<li>모든 처리가 끝나면 스택에 들어있는 글자들을 ans에 더해주고, reverse 처리 해 준다.</li>
</ul>
https://forbid403.github.io/algorithm/[leetcode] Convert Sorted List to Binary Search Tree
2020-11-13T00:00:00+09:00
2020-11-13T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-convert-sorted-list-to-binary-search-tree">[leetcode] Convert Sorted List to Binary Search Tree</h2>
<p><a href="https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="n">TreeNode</span><span class="o">*</span> <span class="n">sortedListToBST</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">head</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">head</span><span class="o">-></span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span> <span class="k">new</span> <span class="n">TreeNode</span><span class="p">(</span><span class="n">head</span><span class="o">-></span><span class="n">val</span><span class="p">);</span>
<span class="c1">// get mid</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">pre</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">&&</span> <span class="n">fast</span><span class="o">-></span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
<span class="n">pre</span> <span class="o">=</span> <span class="n">slow</span><span class="p">;</span>
<span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-></span><span class="n">next</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">pre</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">TreeNode</span> <span class="o">*</span><span class="n">root</span> <span class="o">=</span> <span class="k">new</span> <span class="n">TreeNode</span><span class="p">(</span><span class="n">slow</span><span class="o">-></span><span class="n">val</span><span class="p">);</span>
<span class="n">root</span><span class="o">-></span><span class="n">left</span> <span class="o">=</span> <span class="n">sortedListToBST</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">root</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">sortedListToBST</span><span class="p">(</span><span class="n">slow</span><span class="o">-></span><span class="n">next</span><span class="p">);</span>
<span class="k">return</span> <span class="n">root</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>좋은 트리 + 리스트 문제라서 기록한다.</li>
<li>정렬된 리스트를 이진검색트리로 만드는 문제이다.</li>
<li>재귀로 접근해서 풀 수 있는데, base condition은 <code class="language-plaintext highlighter-rouge">head</code>가 <code class="language-plaintext highlighter-rouge">null</code>일 경우, <code class="language-plaintext highlighter-rouge">null</code> 리턴하고 노드가 하나만 있을 경우는 해당 노드를 리턴한다.</li>
<li><code class="language-plaintext highlighter-rouge">slow</code>, <code class="language-plaintext highlighter-rouge">fast</code>포인터로 가운데 값을 찾는다. 이 리스트를 절반으로 나누기 위해 <code class="language-plaintext highlighter-rouge">prev</code>노드로 <code class="language-plaintext highlighter-rouge">slow</code>의 이전 노드를 저장한다.</li>
<li><code class="language-plaintext highlighter-rouge">prev->next</code>를 <code class="language-plaintext highlighter-rouge">null</code>처리 해 주어 리스트를 두 개로 나눈다.</li>
<li>중간의 노드가 <code class="language-plaintext highlighter-rouge">root</code>가 되고, 해당 노드의 <code class="language-plaintext highlighter-rouge">left</code>는 왼쪽 리스트의 중간 값, <code class="language-plaintext highlighter-rouge">right</code>는 왼쪽 리스트의 중간값이 된다.`</li>
</ul>
https://forbid403.github.io/algorithm/[leetcode] Best Time to Buy and Sell Stock
2020-11-07T00:00:00+09:00
2020-11-07T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-best-time-to-buy-and-sell-stock">[leetcode] Best Time to Buy and Sell Stock</h2>
<p><a href="https://leetcode.com/problems/best-time-to-buy-and-sell-stock/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">maxProfit</span><span class="p">(</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">>&</span> <span class="n">prices</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">prices</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
<span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">ans</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">minimum</span> <span class="o">=</span> <span class="n">prices</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">minimum</span> <span class="o"><</span> <span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="n">minimum</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">minimum</span> <span class="o">=</span> <span class="n">min</span><span class="p">(</span><span class="n">minimum</span><span class="p">,</span> <span class="n">prices</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
https://forbid403.github.io/algorithm/[leetcode] Palindrome Linked List
2020-11-06T00:00:00+09:00
2020-11-06T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-palindrome-linked-list">[leetcode] Palindrome Linked List</h2>
<p><a href="https://leetcode.com/problems/palindrome-linked-list/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">bool</span> <span class="n">isPalindrome</span><span class="p">(</span><span class="n">ListNode</span><span class="o">*</span> <span class="n">head</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">head</span> <span class="o">||</span> <span class="o">!</span><span class="n">head</span><span class="o">-></span><span class="n">next</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">fast</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">fast</span> <span class="o">&&</span> <span class="n">fast</span><span class="o">-></span><span class="n">next</span><span class="p">)</span> <span class="p">{</span>
<span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="n">fast</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-></span><span class="n">next</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">fast</span> <span class="o">=</span> <span class="n">slow</span><span class="p">;</span> <span class="c1">// mid</span>
<span class="n">slow</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">prev</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">fast</span><span class="p">)</span> <span class="p">{</span>
<span class="n">ListNode</span> <span class="o">*</span><span class="n">tmp</span> <span class="o">=</span> <span class="n">fast</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="n">fast</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="n">prev</span><span class="p">;</span>
<span class="n">prev</span> <span class="o">=</span> <span class="n">fast</span><span class="p">;</span>
<span class="n">fast</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">slow</span> <span class="o">||</span> <span class="o">!</span><span class="n">prev</span> <span class="o">||</span> <span class="n">slow</span> <span class="o">==</span> <span class="n">prev</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">slow</span><span class="o">-></span><span class="n">val</span> <span class="o">!=</span> <span class="n">prev</span><span class="o">-></span><span class="n">val</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">slow</span> <span class="o">=</span> <span class="n">slow</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="n">prev</span> <span class="o">=</span> <span class="n">prev</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>지금까지 공부한 LinkedList의 기법?은 다 나온듯</li>
<li>중간을 찾고, 중간부터 뒤집는다.</li>
<li>뒤집은 리스트랑 앞부분 리스트를 비교하면서 palindrome인지 확인 해 주면 된다.</li>
</ul>
https://forbid403.github.io/algorithm/정렬 알고리즘 정리
2020-11-04T00:00:00+09:00
2020-11-04T00:00:00+09:00
https://forbid403.github.io
<h2 id="안정-정렬">안정 정렬</h2>
<h3 id="버블-정렬">버블 정렬</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="o">=</span><span class="n">i</span><span class="p">;</span> <span class="n">j</span><span class="o"><</span><span class="n">n</span><span class="o">-</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">></span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span> <span class="n">swap</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="o">+</span><span class="mi">1</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Time Complexity <code class="language-plaintext highlighter-rouge">O(n^2)</code></p>
<h3 id="삽입-정렬">삽입 정렬</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">></span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="p">{</span>
<span class="n">swap</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="o">-</span><span class="mi">1</span><span class="p">]);</span>
<span class="n">j</span><span class="o">--</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Time Complexity Worst <code class="language-plaintext highlighter-rouge">O(n^2)</code> Best <code class="language-plaintext highlighter-rouge">O(n)</code>
비교 연산은 많지만, swap연산은 적다.
정렬된 데이터일 경우 효율적</p>
<h3 id="합병-정렬">합병 정렬</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">merge</span><span class="p">(</span><span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mid</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">left</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">vector</span> <span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">temp</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o"><=</span> <span class="n">start</span> <span class="o">&&</span> <span class="n">right</span> <span class="o"><=</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="p">]</span> <span class="o">></span> <span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="p">])</span> <span class="n">temp</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="o">++</span><span class="p">]);</span>
<span class="k">else</span> <span class="n">temp</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="o">++</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">while</span><span class="p">(</span><span class="n">left</span> <span class="o"><=</span> <span class="n">start</span><span class="p">)</span> <span class="n">temp</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">left</span><span class="o">++</span><span class="p">]);</span>
<span class="k">while</span><span class="p">(</span><span class="n">right</span> <span class="o"><=</span> <span class="n">end</span><span class="p">)</span> <span class="n">temp</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">right</span><span class="o">++</span><span class="p">]);</span>
<span class="kt">int</span> <span class="n">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">idx</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">idx</span><span class="o"><=</span><span class="n">end</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">arr</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span><span class="p">[</span><span class="n">cnt</span><span class="o">++</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">mergeSort</span><span class="p">(</span><span class="kt">int</span> <span class="n">left</span><span class="p">,</span> <span class="kt">int</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">left</span> <span class="o"><</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">left</span> <span class="o">+</span> <span class="n">right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">mergeSort</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">mid</span><span class="p">);</span>
<span class="n">mergeSort</span><span class="p">(</span><span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">right</span><span class="p">);</span>
<span class="n">merge</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">right</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Time Complexity <code class="language-plaintext highlighter-rouge">O(logn)</code></p>
<hr />
<h2 id="unstable">UNSTABLE</h2>
<h3 id="선택-정렬">선택 정렬</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">target</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="o">=</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">j</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">target</span><span class="p">]</span> <span class="o">></span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="n">target</span> <span class="o">=</span> <span class="n">j</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">swap</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">target</span><span class="p">],</span> <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Time Complexity <code class="language-plaintext highlighter-rouge">O(n^2)</code></p>
<h3 id="퀵-정렬">퀵 정렬</h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">partition</span><span class="p">(</span><span class="kt">int</span> <span class="n">left</span><span class="p">,</span> <span class="kt">int</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">pivot</span> <span class="o">=</span> <span class="n">left</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">low</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">high</span> <span class="o">=</span> <span class="n">right</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">low</span> <span class="o"><=</span> <span class="n">high</span><span class="p">)</span> <span class="p">{</span>
<span class="k">while</span><span class="p">(</span><span class="n">low</span> <span class="o"><=</span> <span class="n">right</span> <span class="o">&&</span> <span class="n">ans</span><span class="p">[</span><span class="n">pivot</span><span class="p">]</span> <span class="o">>=</span> <span class="n">ans</span><span class="p">[</span><span class="n">low</span><span class="p">])</span> <span class="n">low</span><span class="o">++</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">high</span> <span class="o">></span> <span class="n">left</span> <span class="o">&&</span> <span class="n">ans</span><span class="p">[</span><span class="n">pivot</span><span class="p">]</span> <span class="o"><=</span> <span class="n">ans</span><span class="p">[</span><span class="n">high</span><span class="p">])</span> <span class="n">high</span><span class="o">--</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">low</span> <span class="o">></span> <span class="n">high</span><span class="p">)</span> <span class="n">swap</span><span class="p">(</span><span class="n">ans</span><span class="p">[</span><span class="n">pivot</span><span class="p">],</span> <span class="n">ans</span><span class="p">[</span><span class="n">high</span><span class="p">]);</span>
<span class="k">else</span> <span class="n">swap</span><span class="p">(</span><span class="n">ans</span><span class="p">[</span><span class="n">low</span><span class="p">],</span> <span class="n">ans</span><span class="p">[</span><span class="n">high</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">high</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">quickSort</span><span class="p">(</span><span class="kt">int</span> <span class="n">left</span><span class="p">,</span> <span class="kt">int</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">left</span> <span class="o"><</span> <span class="n">right</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">p</span> <span class="o">=</span> <span class="n">partition</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">);</span>
<span class="n">quickSort</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="n">quickSort</span><span class="p">(</span><span class="n">p</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">right</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Time Complexity Best <code class="language-plaintext highlighter-rouge">O(logn)</code> Worst <code class="language-plaintext highlighter-rouge">O(n^2)</code>
역순 정렬일 때는 n^2의 시간복잡도를 가진다.
이를 해결하기 위해서는 피봇을 랜덤이나 가운데 값으로 고르면 된다.</p>
https://forbid403.github.io/algorithm/[leetcode] Palindrome Partitioning
2020-11-02T00:00:00+09:00
2020-11-02T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-palindrome-partitioning">[leetcode] Palindrome Partitioning</h2>
<p><a href="https://leetcode.com/problems/palindrome-partitioning/">문제 링크</a></p>
<p>backtracking</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">isPalindrome</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">l</span><span class="p">,</span> <span class="kt">int</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="n">l</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">end</span> <span class="o">=</span> <span class="n">r</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="o">++</span><span class="p">]</span> <span class="o">!=</span> <span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="o">--</span><span class="p">])</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">dfs</span><span class="p">(</span><span class="n">vector</span> <span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>>&</span> <span class="n">ans</span><span class="p">,</span> <span class="n">vector</span> <span class="o"><</span><span class="n">string</span><span class="o">>&</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">idx</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">idx</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
<span class="n">ans</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">candidates</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="n">idx</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">s</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">isPalindrome</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">idx</span><span class="p">,</span> <span class="n">i</span><span class="p">))</span> <span class="p">{</span>
<span class="n">candidates</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">idx</span><span class="p">,</span> <span class="n">i</span><span class="o">-</span><span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">));</span>
<span class="n">dfs</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="n">candidates</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">vector</span><span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>></span> <span class="n">partition</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="n">vector</span> <span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>></span> <span class="n">ans</span><span class="p">;</span>
<span class="n">vector</span> <span class="o"><</span><span class="n">string</span><span class="o">></span> <span class="n">candidates</span><span class="p">;</span>
<span class="n">dfs</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<p>backtracking + dp</p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">dp</span><span class="p">[</span><span class="mi">204</span><span class="p">][</span><span class="mi">204</span><span class="p">];</span>
<span class="kt">void</span> <span class="n">dfs</span><span class="p">(</span><span class="n">vector</span> <span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>>&</span> <span class="n">ans</span><span class="p">,</span> <span class="n">vector</span> <span class="o"><</span><span class="n">string</span><span class="o">>&</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">string</span> <span class="n">s</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="n">s</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
<span class="n">ans</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">candidates</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">end</span><span class="o">=</span><span class="n">start</span><span class="p">;</span> <span class="n">end</span><span class="o"><</span><span class="n">s</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="n">end</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">end</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">&&</span> <span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span> <span class="o"><=</span> <span class="mi">2</span> <span class="o">||</span> <span class="n">dp</span><span class="p">[</span><span class="n">start</span><span class="o">+</span><span class="mi">1</span><span class="p">][</span><span class="n">end</span><span class="o">-</span><span class="mi">1</span><span class="p">]))</span> <span class="p">{</span>
<span class="n">dp</span><span class="p">[</span><span class="n">start</span><span class="p">][</span><span class="n">end</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">candidates</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">-</span><span class="n">start</span><span class="o">+</span><span class="mi">1</span><span class="p">));</span>
<span class="n">dfs</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">end</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="n">candidates</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">vector</span><span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>></span> <span class="n">partition</span><span class="p">(</span><span class="n">string</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
<span class="n">vector</span> <span class="o"><</span><span class="n">vector</span><span class="o"><</span><span class="n">string</span><span class="o">>></span> <span class="n">ans</span><span class="p">;</span>
<span class="n">vector</span> <span class="o"><</span><span class="n">string</span><span class="o">></span> <span class="n">candidates</span><span class="p">;</span>
<span class="n">dfs</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">candidates</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
https://forbid403.github.io/algorithm/[leetcode] Number Of Longest Increasing Subsequence
2020-10-30T00:00:00+09:00
2020-10-30T00:00:00+09:00
https://forbid403.github.io
<h2 id="leetcode-number-of-longest-increasing-subsequence">[leetcode] Number of Longest Increasing Subsequence</h2>
<p><a href="https://leetcode.com/problems/number-of-longest-increasing-subsequence/">문제 링크</a></p>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span> <span class="p">{</span>
<span class="nl">public:</span>
<span class="kt">int</span> <span class="n">findNumberOfLIS</span><span class="p">(</span><span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">>&</span> <span class="n">nums</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">nums</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">n</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">dp</span><span class="p">[</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">cnt</span><span class="p">[</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">];</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">cnt</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">j</span><span class="o"><</span><span class="n">i</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">nums</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">></span> <span class="n">nums</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">cnt</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">cnt</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
<span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">dp</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">cnt</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="n">cnt</span><span class="p">[</span><span class="n">j</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">cur</span><span class="p">,</span> <span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">ans</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span><span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="k">if</span><span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">cur</span><span class="p">)</span> <span class="n">ans</span> <span class="o">+=</span> <span class="n">cnt</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="k">return</span> <span class="n">ans</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<ul>
<li>LIS의 경우의 수를 구하는 문제이다.</li>
<li>dp 배열 말고 경우의 수를 저장하는 cnt 배열을 추가로 선언 해 주고 1로 초기화 시켜 준다.</li>
<li>IS인 경우에만 다음의 검사를 해준다.
<ul>
<li>뻗어나갈 수 있는 경우의 수가 존재한다면(<code class="language-plaintext highlighter-rouge">dp[i] == dp[j] + 1</code>)
<ul>
<li><code class="language-plaintext highlighter-rouge">cnt[i]</code>는 <code class="language-plaintext highlighter-rouge">cnt[j]</code>가 더해진다</li>
</ul>
</li>
<li>경우의 수가 존재하지 않는다면 (<code class="language-plaintext highlighter-rouge">dp[i] > dp[j] + 1</code>)
<ul>
<li><code class="language-plaintext highlighter-rouge">cnt[i]</code>는 그대로 유지된다.</li>
</ul>
</li>
</ul>
</li>
<li>마지막으로 가장 긴 LIS가 여러 개 있을 수 있으므로, 해당 LIS에 해당하는 경우의 수들을 모두 더해준다. (2,2,2,2와 같은 경우)</li>
</ul>
https://forbid403.github.io/os/[OS] Ch9.가상 메모리
2020-10-29T00:00:00+09:00
2020-10-29T00:00:00+09:00
https://forbid403.github.io
<h3 id="가상-메모리">가상 메모리</h3>
<ul>
<li>물리 메모리 개념과 사용자의 논리 메모리 개념을 분리한 것</li>
<li><code class="language-plaintext highlighter-rouge">가상 주소 공간</code> : 프로세스가 메모리에 저장되는 논리적인 번지</li>
<li>페이지 공유를 통해 파일이나 메모리가 프로세스들에 공유될 수 있는 장점이 있다.</li>
</ul>
<h3 id="요구-페이징-demand-paging">요구 페이징 (Demand Paging)</h3>
<ul>
<li>메모리에 필요한 것들만 적재한다.</li>
<li>필요한 페이지는 swap in, 필요 없으면 swap out</li>
<li>스와핑 기법과 비슷 - 페이저라는 용어 사용</li>
</ul>
<h3 id="기본-개념">기본 개념</h3>
<ul>
<li>메모리에 존재하는 페이지에 접근하면 실행, 존재하지 않는다면 페이지 부재 트랩 발생</li>
<li>페이지 부재 처리 과정
<ul>
<li>메모리 참조가 유효한지, 무효한지 판단.</li>
<li>무효하다면 프로세스 중단, 유효하지만 페이지가 없다면 디스크로부터 가져오기</li>
<li>빈 공간 (자유 프레임)을 찾는다.</li>
<li>새로 할당된 프레임에 페이지를 읽어 들이도록 요청한다.</li>
<li>페이지 테이블 갱신, 프로세스의 내부 테이블 수정</li>
<li>트랩에 의해 중단된 명령어 수행.</li>
</ul>
</li>
</ul>
<h3 id="페이지-교체">페이지 교체</h3>
<ul>
<li>페이지 교체 과정
<ul>
<li>디스크에서 필요한 페이지의 위치를 알아낸다.</li>
<li>빈 페이지 프레임을 찾는다.
<ul>
<li>빈 프레임이 있다면 사용한다.</li>
<li>없다면 희생될 프레임을 선정하기 위해 페이지 교체 알고리즘을 실행한다.</li>
<li>희생될 페이지를 디스크에 기록하고, 테이블을 수정한다.</li>
</ul>
</li>
<li>빼앗은 프레임에 새 페이지를 읽어오고 테이브를 수행한다.</li>
<li>트랩이 발생한 지점에서부터 프로세스를 실행한다.</li>
</ul>
</li>
</ul>
<h3 id="페이지-교체-알고리즘">페이지 교체 알고리즘</h3>
<ul>
<li>FIFO (First In First Out)
<ul>
<li>가장 오래 된 페이지 교체</li>
<li>이해하기 쉽고, 구현도 쉽다.</li>
<li>성능이 항상 좋지 않다. 교체한 페이지가 자주 사용되는 페이지일 수도 있다.</li>
<li><code class="language-plaintext highlighter-rouge">Belady의 모순</code> 프로세스에게 프레임을 더 주었는데 페이지 부재율은 더 상승한다.</li>
</ul>
</li>
<li>최적 페이지 교체 (Optimal Page Replacement)
<ul>
<li>가장 오랫동안 사용되지 않는 페이지 교체</li>
<li>가장 낮은 페이지 부재율 보장</li>
<li>구현하기 어렵다.</li>
<li>Belady 모순 X</li>
</ul>
</li>
<li>LRU (Least Recently Used)
<ul>
<li>가장 오랜 기간동안 사용되지 않은 페이지 교체</li>
<li>카운터 변수나 스택을 사용한다.</li>
<li>Belady 모순 X</li>
</ul>
</li>
<li>LFU (Least Frequently Used)
<ul>
<li>가장 참조 횟수가 적은 페이지 교체</li>
<li>교체 대상이 여러 개인 경우, LRU 이용</li>
<li>구현 비용이 크다.</li>
</ul>
</li>
</ul>
<h2 id="스레싱-thrashing">스레싱 (Thrashing)</h2>
<ul>
<li>페이지 부재가 연속적으로 발생 돼 프로세스 수행 시간보다 페이지 교체 시간이 더 많을 경우</li>
</ul>
<h3 id="스레싱의-원인">스레싱의 원인</h3>
<ul>
<li>부적절한 페이지 교체 알고리즘
<ul>
<li>Belady 모순</li>
</ul>
</li>
<li>시스템 리소스 부족
<ul>
<li>작은 캐시</li>
<li>낮은 메모리 용량</li>
</ul>
</li>
<li>프로그램 메모리 관리 실패
<ul>
<li>과도한 스레드 생성, 무분별한 fork</li>
</ul>
</li>
</ul>
<h3 id="스레싱-해결-방법">스레싱 해결 방법</h3>
<ul>
<li>Working Set Model
<ul>
<li>프로세스가 많이 참조하는 페이지 집합을 메모리 공간에 계속 상주시켜 빈번한 페이지 교체현상(스레싱)을 줄이는 방법</li>
<li>다중 프로그래밍 높임, CPU 사용률 최적화</li>
<li>Working set 관리 복잡, Window 사이즈 설정 모호</li>
<li>지역성 활용</li>
</ul>
</li>
<li>Page Fault Frequency
<ul>
<li>페이지 부재율의 상, 하한으로 페이지 부재율을 예측하고 조절</li>
<li>페이지 부재율이 높으면 프레임 할당, 낮으면 회수</li>
<li>페이지 부재 발생 시에만 실행, 직접 페이지 부재율 조절 가능</li>
<li>프로세스 중지 과정 발생</li>
<li>Working set보다 오버헤드가 작다.</li>
</ul>
</li>
</ul>
https://forbid403.github.io/os/[OS] Ch9. 연습문제
2020-10-29T00:00:00+09:00
2020-10-29T00:00:00+09:00
https://forbid403.github.io
<h3 id="2-스레드의-상태를-준비-완료ready실행running봉쇄됨blocked으로-간단하게-정의-할-수-있다-여기서-준비-완료는-실행할-준비가-되어-스케줄-되기를-기다리고-있는-상태이고-실행은-처리기에서-실행-중인-상태-그리고-입출력-완료를-기다리는-것과-같은-대기-상태가-봉쇄됨이다-이러한-상태를-도시한-그림이-930에-나와-있다-스레드가-실행상태라고-가정하고-다음-질문에-답하시오">2. 스레드의 상태를 준비 완료(ready),실행(running),봉쇄됨(blocked)으로 간단하게 정의 할 수 있다. 여기서 준비 완료는 실행할 준비가 되어 스케줄 되기를 기다리고 있는 상태이고, 실행은 처리기에서 실행 중인 상태 그리고 입출력 완료를 기다리는 것과 같은 대기 상태가 봉쇄됨이다. 이러한 상태를 도시한 그림이 9.30에 나와 있다. 스레드가 실행상태라고 가정하고 다음 질문에 답하시오.</h3>
<p>a. 페이지 부재가 발생하면 스레드는 상태를 변화시키는가? 그렇다면 변화된 새로운 상태는 무엇인가?
b. 페이지 테이블을 참조하여 해결할 수 있는 TLB 미스를 발생시킬 경우 스레드는 상태를 변화시키는가? 그렇다면 변화된 새로운 상태는 무엇인가?
c. 페이지 테이블에 의해 주소 참조가 해결된다면 스레드는 상태를 변화시키는가? 그렇다면 새로운 상태는 무엇인가?</p>
<h3 id="3-순수-요구-페이징을-사용하는-시스템이-있다고-하자">3. 순수 요구 페이징을 사용하는 시스템이 있다고 하자.</h3>
<p>a. 프로세스가 처음 실행을 시작할 때, 페이지 부재율은 어떻게 되는가?
b. 프로세서의 작업 집합이 메모리 적재된 후에는 페이지 부재율은 어떻게 되는가?
c. 프로세서의 지역성이 변하고 새로운 작업 집합의 크기가 너무 커서 자유 메모리에 적재될 수 없다고 가정하자. 이 상황을 해결하기 위하여 시스템 설계자가 선택 할 수 있는 결정들을 제시하시오.</p>
<h3 id="4-쓰기-시-복사가-어떤-기능인지-설명하고-이-기능을-어떤-상황에서-사용하는-것이-좋은지-설명하시오-이-기능을-구현하기-위한-하드웨어-지원-사항은-무엇인가">4. 쓰기 시 복사가 어떤 기능인지 설명하고 이 기능을 어떤 상황에서 사용하는 것이 좋은지 설명하시오. 이 기능을 구현하기 위한 하드웨어 지원 사항은 무엇인가?</h3>
<h3 id="11-lfu-교체-정책이-lru-교체-정책보다-더-적은-수의-페이지-부재를-발생시키는-상황에-대해-설명하시오-또한-반대의-경우는-어떤-경우인지-설명하시오">11. LFU 교체 정책이 LRU 교체 정책보다 더 적은 수의 페이지 부재를 발생시키는 상황에 대해 설명하시오. 또한 반대의 경우는 어떤 경우인지 설명하시오.</h3>
<h3 id="14-다음과-같이-측정된-이용률을-가진-요구-페이징-시스템을-생각해-보시오">14. 다음과 같이 측정된 이용률을 가진 요구 페이징 시스템을 생각해 보시오.</h3>
<p>CPU 이용률 20%
페이징 디스크 97.7%
기타 입출력 장치 5%</p>
<p>다음 항목 각각에 대해 CPU 이용률을 개선할 수 있는지(또는 개선 가능성이 있는지) 답하고 그 이유를 설명하시오.</p>
<p>a. 더 빠른 CPU 설치
b. 더 큰 페이징 디스크 설치
c. 다중 프로그래밍의 정도 증가
d. 다중 프로그래밍의 정도 감소
e. 주 메모리 추가 장착
f. 더 빠른 하드디스크나 여러 개의 하드디스크를 가진 다중 제어기의 설치
g. 페이지 인출 알고리즘에 프리페이징 추가
h. 페이지 크기 증가</p>
<h3 id="16-여러분이-사용하는-페이징-시스템의-교체-정책이-각-페이지를-정기적으로-검사하고-마지막-검사-이후에-참조되지-않은-페이지를-쫓아내는-정책이라고-가정하자-lru-또는-2차-기회-교체-정책-알고리즘-대신에-이러한-정책을-사용할-경우-이해득실은-어떻게-되는가">16. 여러분이 사용하는 페이징 시스템의 교체 정책이 각 페이지를 정기적으로 검사하고 마지막 검사 이후에 참조되지 않은 페이지를 쫓아내는 정책이라고 가정하자. LRU 또는 2차 기회 교체 정책 알고리즘 대신에 이러한 정책을 사용할 경우 이해득실은 어떻게 되는가?</h3>
<h3 id="19-스레싱의-원인은-무엇인가-시스템이-스레싱을-발견하는-방법은-무엇이며-일단-스레싱이-발견되면-이-문제를-해결하기-위해-시스템은-무엇을-할-수-있는가">19. 스레싱의 원인은 무엇인가? 시스템이 스레싱을 발견하는 방법은 무엇이며, 일단 스레싱이 발견되면 이 문제를 해결하기 위해 시스템은 무엇을 할 수 있는가?</h3>
<h3 id="23-사용자-수준-스레드와-커널-수준-스레드를-지원하는-시스템이-있다고-하자-사용자-수준-스레드와-커널-수준-스레드의-사상은-일대일-사상을-사용한다-즉-사용자-수준-스레드에-대응되는-하나의-커널-스레드가-존재한다-다중프로세스는-a-전체-프로세스의-작업-집합-또는-b-각-스레드의-작업-집합으로-구성되는가-이유를-설명하시오">23. 사용자 수준 스레드와 커널 수준 스레드를 지원하는 시스템이 있다고 하자. 사용자 수준 스레드와 커널 수준 스레드의 사상은 일대일 사상을 사용한다. 즉 사용자 수준 스레드에 대응되는 하나의 커널 스레드가 존재한다. 다중프로세스는 (a) 전체 프로세스의 작업 집합 또는 (b) 각 스레드의 작업 집합으로 구성되는가? 이유를 설명하시오.</h3>
<h3 id="25-프로세스에-서로-다른-크기의-페이지들을-할당하는-시스템을-생각하자-이러한-페이징-시스템의-장점은-무엇인가-가상-메모리-시스템을-어떻게-수정하면-이러한-기능을-제공할-수-있는가">25. 프로세스에 서로 다른 크기의 페이지들을 할당하는 시스템을 생각하자. 이러한 페이징 시스템의 장점은 무엇인가? 가상 메모리 시스템을 어떻게 수정하면 이러한 기능을 제공할 수 있는가?</h3>
https://forbid403.github.io/os/[OS] Ch8. 연습문제
2020-10-29T00:00:00+09:00
2020-10-29T00:00:00+09:00
https://forbid403.github.io
<h3 id="1-내부-단편화와-외부-단편화-사이의-차이점을-설명하고-어떻게-다른지-설명하시오">1. 내부 단편화와 외부 단편화 사이의 차이점을 설명하고, 어떻게 다른지 설명하시오.</h3>
<p>내부 단편화 : 프로세스보다 분할 된 공간이 커 잉여 공간이 남는 것
외부 단편화 : 할당된 공간을 모으면 충분히 프로세스가 들어갈 수 있지만 프로세스가 들어갈 공간은 없는 것</p>
<h3 id="5-다음의-쟁점들을-참고하여-연속적-메모리-할당-순수-세그멘테이션-순수-페이징-기법들을-비교하시오">5. 다음의 쟁점들을 참고하여 연속적 메모리 할당, 순수 세그멘테이션, 순수 페이징 기법들을 비교하시오.</h3>
<p>a. 외부 단편화
연속 메모리 할당 (고정 파티션 크기) : X
연속 메모리 할당 (가변 파티션 크기) : O
순수 세그멘테이션 : O
순수 페이징 : X</p>
<p>b. 내부 단편화
연속 메모리 할당 (고정 파티션 크기) : O
연속 메모리 할당 (가변 파티션 크기) : X
순수 세그멘테이션 : X
순수 페이징 : O</p>
<p>c. 프로세스 사이의 코드 공유 가능성
연속 메모리 할당 (고정 파티션 크기) : X
연속 메모리 할당 (가변 파티션 크기) : X
순수 세그멘테이션 : O
순수 페이징 : O</p>
<h3 id="7-ios-android와-같은-모바일-운영체제에서-스와핑을-지원하지-않는-이유를-설명하시오">7. IOS, Android와 같은 모바일 운영체제에서 스와핑을 지원하지 않는 이유를 설명하시오.</h3>
<p>모바일 기기들은 플래시 메모리를 사용하기 때문에 공간이 한정되어 있기 때문이다.</p>
<h3 id="14-물리-메모리의-최대-크기는-얼마인가">14. 물리 메모리의 최대 크기는 얼마인가?</h3>
<p>32비트 컴퓨터라면 2^32 = 4GB</p>
<h3 id="18-세그멘테이션과-페이징-기법을-결합하여-사용하는-이유는-무엇-때문인가">18. 세그멘테이션과 페이징 기법을 결합하여 사용하는 이유는 무엇 때문인가?</h3>
<p>페이지 테이블이 클 때 유용한 기법이다. 세그먼트가 매우 커서 할당에 시간이 오래 걸리는 것을 방지할 수 있다.</p>
<h3 id="21-페이지-테이블을-페이징-하는-목적은-무엇인가">21. 페이지 테이블을 페이징 하는 목적은 무엇인가?</h3>
<p>페이지 테이블을 페이징 함으로서 페이지 테이블은 매우 커질 수 있다. 메모리 할당 방식을 단순화 시킬 수 있고, 사용되지 않는 페이지를 쉽게 스와핑 할 수 있다.</p>