<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://raacker.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://raacker.github.io/" rel="alternate" type="text/html" /><updated>2026-03-21T18:28:44-07:00</updated><id>https://raacker.github.io/feed.xml</id><title type="html">Haven’s Vault</title><subtitle>Haven Kim&apos;s log file</subtitle><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><entry><title type="html">어바웃 타임</title><link href="https://raacker.github.io/movie/movie-review-about-time/" rel="alternate" type="text/html" title="어바웃 타임" /><published>2024-06-18T00:00:00-07:00</published><updated>2024-06-17T08:07:00-07:00</updated><id>https://raacker.github.io/movie/movie-review-about-time</id><content type="html" xml:base="https://raacker.github.io/movie/movie-review-about-time/"><![CDATA[<h2 id="어바웃-타임을-열손가락이-부족할-정도로-본-것-같습니다만">어바웃 타임을 열손가락이 부족할 정도로 본 것 같습니다만</h2>

<p>2013년도에 개봉한 이 영화를 나는 꽤나 다양한 시간대에서 수차례 보아왔다. 원래 로맨스나 마음 따듯해지는 가족 영화를 좋아하지만 이 영화 특유의 기분 좋은 여운과 귀에 맴도는 OST들 때문이었다.</p>

<p>오늘로 따지자면 다시 본지 9번째는 되었으려나? 특별히 기대되거나 기억에 남을 만한 멋진 하루가 점차 사라진채 지내다보니 영화를 보면서 감상에 젖은지도 오래되어 언제가 마지막으로 봤는지 기억이 안난다. 그것은 오늘 보는 중간중간 <code class="language-plaintext highlighter-rouge">아~ 이런 장면도 있었지 참</code> 이라고 스스로 되뇌이는 순간이 많았다는 것으로 증명했다.</p>

<p>어렸을 때 가장 좋아했던 부분은 가족의 행복함과 팀, 메리의 사랑이 이루어지는 부분이 더 컸던 기억이 난다. 팀과 메리의 첫 만남, 일 몬도의 음악이 흘러나오는 빗속 결혼식 장면과, 우연히 마주친 여름 날의 크러쉬 샬롯을 마주치고 누구를 진정으로 사랑하는지 다짐하는 장면, 이윽고 팀이 침대 옆에서 조용하게 청혼하는 장면 등 지금도 여전히 사랑하는 장면들이 가득하다.</p>

<p>그런데 내가 나이도 제법 먹은 아저씨가 되어서일까? 혹은 그 사이에도 세상에 치이고 깨달은게 많아서였을까 오늘 느지막한 밤, 영화를 보면서 새롭고 다르게 느껴진 장면들이 유독 기억에 남아 이렇게 글까지 남겨본다.</p>

<p><em>물론 당연하지만 아래 부분에 풀어낸 내 보따리 타래는 스포일러가 가득하다.</em></p>

<h2 id="아버지의-결혼식-축사">아버지의 결혼식 축사</h2>

<p>영화 중반부에 팀은 결혼식 축사를 친구들에게 부탁했는데 꽤 형편없었다. 결국 팀은 아빠에게 마지막으로 부탁했는데 자신의 아들을 위해 낯간지럽지만 그만큼의 따듯한 말을 건넬 수 있는 아버지들은 세상에 몇이나 될 수 있을까 싶다. 물론 아버지의 마음은 모두 같을 것이고 모든 딸들, 아들들은 말하지 않아도 아버지의 마음을 잘 알겠지만. 그만큼 두 부자의 사이가 각별했고 소중하지 않았을까? 미래에 나를 닮은 사고뭉치 아들을 낳더라도 이런 말을 해줄 수 있는 아버지이고 싶다는 꿈을 가지게 되었다.</p>

<blockquote>
  <p>결혼하는 사람에게 전 항상 한 가지만 충고해 줍니다. 끝엔 우리 모두 다 비슷하다는 거. 모두 늙고 같은 얘기를 수십 번씩 반복하니까요. 하지만 상냥한 사람과 결혼하라는 것. 그리고 팀은 따듯한 마음을 가진 상냥한 사람입니다. 제 인생을 돌아봤을 때 특별히 자랑스러운 점은 없지만 제 아들의 아버지가 될 수 있다는 점이 정말 자랑스럽습니다. -팀의 아빠</p>
</blockquote>

<p>문득 아빠와 소주 마신지 한 달도 더 되었다는 사실이 마음을 치고 들어온다.</p>

<h2 id="어머니식-표현">어머니식 표현</h2>

<p>팀의 아빠가 암으로 시한부 선고를 받았다는 연락을 받고 모두들 집으로 모인다. 팀의 좀 어떠냐는 인사에 팀의 엄마가 답한 대답은 절제되면서 너무 아름다운 말로 느껴졌다.</p>

<blockquote>
  <p>- 왔구나<br />
- 엄마, 좀 어때요?<br />
- 솔직히?<br />
- 솔직히요<br />
- 화가 나 미치겠어. 네 아버지 없는 인생은 정말 관심이 없구나</p>
</blockquote>

<p>결혼을 하고 오랜 시간이 지나면 정으로 산다고 하지만 아무리 그래도 이렇게 사랑스러운 표현을 과연 나는 할 수 있을까? 할 수 있도록 많이 배우고 표현해야 겠다는 울림을 주었다.</p>

<h2 id="행복을-위한-공식">행복을 위한 공식</h2>

<p>요즘 좀 즐거운 기억을 많이 못찾아서 그랬을까, 좋아하는 장면이지만 또다시 보면서 새로운 느낌을 받았다. 팀의 아버지는 마지막으로 <code class="language-plaintext highlighter-rouge">행복을 위한 공식</code>을 알려준다. 일단은 평범한 하루를 그저 그렇게 보내보고, 그 다음에는 최대한 똑같은 하루를 다시 살아본다는 공식이다. 핵심은 처음엔 긴장과 걱정 때문에 놓치고 지나갔던 그 시간에만 존재하는 아름다운 순간들을 최대한 느껴보는 것이다. 이 부분과 더불어 영화의 마지막 부분까지가 영화 제목을 가장 잘 설명해준다고 생각한다. 흘러가는 시간을 어떻게 대할 것인가?</p>

<blockquote>
  <p>난 시간 여행에서 마지막 교훈을 얻었다. 아빠보다 한 단계 더 나아가기까지 했다. 이제 난 시간 여행을 하지 않는다. 하루를 위해서라도. 그저 내가 이날을 위해 시간 여행을 한 것처럼, 나의 특별하면서도 평범한 마지막 날이라고 생각하며 완전하고 즐겁게 매일 지내려고 노력할 뿐이다. 우린 우리 인생의 하루하루를 항상 함께 시간 여행을 한다. 우리가 할 수 있는 최선은 이 멋진 여행을 즐기는 것뿐이다.</p>
</blockquote>

<h2 id="나는-행복한가">나는 행복한가?</h2>

<p>매 순간 최선을 다하라, 살아있음을 느껴라, 카르페 디엠 등등 온갖 좋은 말은 많지만 이걸 마음 깊이 새겨놓고 실천하고 있는 낭만러들은 한국에서 이미 멸종했을지도 모르겠다. 그만큼 바쁘고 척박하게 돌아가는 것 아닐까 싶기도 하고. 인류애 충전할 거리는 점점 줄어드는데 잃을 곳만 늘어난다는 생각조차 들고 있으니 나 역시 낭만이니 추억이니 담 쌓은지 제법 된 것 같다.</p>

<p>추억을 좋아한다고 했던 누군가의 자기소갯글이 떠올랐다. 일상의 사소한 것들이 모여 행복이라고 느낄 수 있다면 그것이 그 사람의 취향이 되고, 그 사람 자체가 되어가는 것 같기도 하다. 그래서인지 오늘따라 수없이 보았던 이 영화가 낯설게 느껴지고 기억에 남는 장면들이 생겼다.</p>

<p>그래서 나중에 다시 이 글을 보거나 영화를 또 다시 볼 나에게 <code class="language-plaintext highlighter-rouge">오늘 하루 중 행복했던 순간 하나만 골라와</code>라는 문장을 선물로 남긴다. 그 행복들이 추억거리가 되고 나중에 이 시간대로 다시 돌아오고 싶게 만드는 시간 여행으로 남아줄 것 같다.</p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="Movie" /><category term="Essey" /><summary type="html"><![CDATA[어바웃 타임을 몇 번이나 봤으면서 새로운 느낌을 받았다면?]]></summary></entry><entry><title type="html">Force single instance of the C# application</title><link href="https://raacker.github.io/c%23/single-instance-csharp/" rel="alternate" type="text/html" title="Force single instance of the C# application" /><published>2023-09-19T00:00:00-07:00</published><updated>2023-09-19T01:34:00-07:00</updated><id>https://raacker.github.io/c%23/single-instance-csharp</id><content type="html" xml:base="https://raacker.github.io/c%23/single-instance-csharp/"><![CDATA[<h2 id="quick-snippet">Quick Snippet</h2>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static</span> <span class="k">class</span> <span class="nc">MainProgram</span>
<span class="p">{</span>
    <span class="c1">// Windows specific</span>
    <span class="p">[</span><span class="n">DllImport</span><span class="p">(</span><span class="s">"user32.dll"</span><span class="p">)]</span>
    <span class="k">static</span> <span class="k">extern</span> <span class="kt">bool</span> <span class="n">SetForegroundWindow</span><span class="p">(</span><span class="n">IntPtr</span> <span class="n">hWnd</span><span class="p">);</span>

    <span class="k">static</span> <span class="kt">void</span> <span class="n">Main</span><span class="p">(</span><span class="n">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">ApplicationRun</span><span class="p">();</span>
    <span class="p">}</span>

    <span class="p">[</span><span class="n">STAThread</span><span class="p">]</span>
    <span class="k">static</span> <span class="kt">void</span> <span class="n">ApplicationRun</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">bool</span> <span class="n">createdNew</span><span class="p">;</span>
        <span class="k">using</span> <span class="p">(</span><span class="n">Mutex</span> <span class="n">mutex</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Mutex</span><span class="p">(</span><span class="nb">true</span><span class="p">,</span> <span class="s">"TestProgram"</span><span class="p">,</span> <span class="n">out</span> <span class="n">createdNew</span><span class="p">))</span>
        <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">createdNew</span><span class="p">)</span>
            <span class="p">{</span>
                <span class="n">Application</span><span class="p">.</span><span class="n">EnableVisualStyles</span><span class="p">();</span>
                <span class="n">Application</span><span class="p">.</span><span class="n">SetCompatibleTextRenderingDefault</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
                <span class="n">Application</span><span class="p">.</span><span class="n">Run</span><span class="p">(</span><span class="k">new</span> <span class="n">MainGUI</span><span class="p">());</span>
            <span class="p">}</span>
            <span class="k">else</span>
            <span class="p">{</span>
                <span class="n">Process</span> <span class="n">current</span> <span class="o">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetCurrentProcess</span><span class="p">();</span>
                <span class="n">foreach</span> <span class="p">(</span><span class="n">Process</span> <span class="n">process</span> <span class="n">in</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetProcessesByName</span><span class="p">(</span><span class="n">current</span><span class="p">.</span><span class="n">ProcessName</span><span class="p">))</span>
                <span class="p">{</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">process</span><span class="p">.</span><span class="n">Id</span> <span class="o">!=</span> <span class="n">current</span><span class="p">.</span><span class="n">Id</span><span class="p">)</span>
                    <span class="p">{</span>
                        <span class="n">SetForegroundWindow</span><span class="p">(</span><span class="n">process</span><span class="p">.</span><span class="n">MainWindowHandle</span><span class="p">);</span>
                        <span class="k">break</span><span class="p">;</span>
                    <span class="p">}</span>
                <span class="p">}</span>
            <span class="p">}</span>
        <span class="p">}</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="how-it-works">How it works</h2>

<h3 id="1-define-named-mutex">1. Define named mutex</h3>

<p>The first step is to spawn a Mutex with a specific name.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="p">(</span><span class="n">Mutex</span> <span class="n">mutex</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">Mutex</span><span class="p">(</span><span class="nb">true</span><span class="p">,</span> <span class="s">"TestProgram"</span><span class="p">,</span> <span class="n">out</span> <span class="n">createdNew</span><span class="p">))</span>
<span class="p">{</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This mutex is called <code class="language-plaintext highlighter-rouge">named system mutex</code>. It is not like an <code class="language-plaintext highlighter-rouge">unnammed mutex</code> or a local mutex. Check the reference below.</p>

<blockquote>
  <p>Mutexes are of two types: <strong>local mutexes</strong>, which are unnamed, and <strong>named system mutexes</strong>. <strong>A local mutex exists only within your process</strong>. It can be used by any thread in your process that has a reference to the Mutex object that represents the mutex. Each unnamed Mutex object represents a separate local mutex.</p>

  <p><strong>Named system mutexes are visible throughout the operating system, and can be used to synchronize the activities of processes</strong>. You can create a Mutex object that represents a named system mutex by using a constructor that accepts a name. The operating-system object can be created at the same time, or it can exist before the creation of the Mutex object. You can create multiple Mutex objects that represent the same named system mutex, and you can use the OpenExisting method to open an existing named system mutex.
<a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.mutex?view=net-7.0">Microsoft Docs Reference</a></p>
</blockquote>

<p>By defining the name of the mutex, this is visible overall in the system.</p>

<p>I used a random name here but ideally, GUID of the application would be a better fit.</p>

<h3 id="2-check-if-the-mutex-exists-or-not">2. Check if the mutex exists or not</h3>

<p>By passing the <code class="language-plaintext highlighter-rouge">out parameter createdNew</code>, we know that the mutex has never been created or not. If the new mutex creation was successful, you are a root process. Just go ahead and run the main GUI thread.</p>

<h3 id="3-setforegroundwindow">3. SetForegroundWindow</h3>

<p>If not, it is not the first attempt to run the application. You can simply do any feedback you want but I would use <code class="language-plaintext highlighter-rouge">SetForegroundWindow()</code> function in Windows.</p>

<p>If you are using Linux, you should have proper API equivalent to the function.</p>

<p>First, import the function from user32.dll.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">DllImport</span><span class="p">(</span><span class="s">"user32.dll"</span><span class="p">)]</span>
<span class="k">static</span> <span class="k">extern</span> <span class="kt">bool</span> <span class="nf">SetForegroundWindow</span><span class="p">(</span><span class="n">IntPtr</span> <span class="n">hWnd</span><span class="p">);</span>
</code></pre></div></div>

<p>And then, search for the same process ID from existing processes. If it matches with the process ID, bring it front.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Process</span> <span class="n">current</span> <span class="o">=</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetCurrentProcess</span><span class="p">();</span>
<span class="n">foreach</span> <span class="p">(</span><span class="n">Process</span> <span class="n">process</span> <span class="n">in</span> <span class="n">Process</span><span class="p">.</span><span class="n">GetProcessesByName</span><span class="p">(</span><span class="n">current</span><span class="p">.</span><span class="n">ProcessName</span><span class="p">))</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">process</span><span class="p">.</span><span class="n">Id</span> <span class="o">!=</span> <span class="n">current</span><span class="p">.</span><span class="n">Id</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">SetForegroundWindow</span><span class="p">(</span><span class="n">process</span><span class="p">.</span><span class="n">MainWindowHandle</span><span class="p">);</span>
        <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Happy hacking!</p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="C#" /><category term="C#" /><category term=".net" /><summary type="html"><![CDATA[If your exe shouldn't be launched more than once, check this out]]></summary></entry><entry><title type="html">Ask Privilege elevation in Windows batch</title><link href="https://raacker.github.io/scripting/batch-privilege/" rel="alternate" type="text/html" title="Ask Privilege elevation in Windows batch" /><published>2023-09-19T00:00:00-07:00</published><updated>2023-09-19T19:20:00-07:00</updated><id>https://raacker.github.io/scripting/batch-privilege</id><content type="html" xml:base="https://raacker.github.io/scripting/batch-privilege/"><![CDATA[<h2 id="quick-snippet">Quick Snippet</h2>

<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@echo <span class="na">off</span>

<span class="c">:: BatchGotAdmin</span>
:<span class="o">-------------------------------------</span>
<span class="c">REM  --&gt; Check for permissions</span>
<span class="kd">IF</span> <span class="s2">"</span><span class="nv">%PROCESSOR_ARCHITECTURE%</span><span class="s2">"</span> <span class="kd">EQU</span> <span class="s2">"amd64"</span> <span class="o">(</span>
<span class="o">&gt;</span><span class="kr">nul</span> <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\SysWOW64\cacls.exe"</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\SysWOW64\config\system"</span>
<span class="o">)</span> <span class="kd">ELSE</span> <span class="o">(</span>
<span class="o">&gt;</span><span class="kr">nul</span> <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\system32\cacls.exe"</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\system32\config\system"</span>
<span class="o">)</span>

<span class="c">REM --&gt; If error flag set, we do not have admin.</span>
<span class="k">if</span> <span class="s1">'</span><span class="nv">%errorlevel%</span><span class="s1">'</span> <span class="kd">NEQ</span> <span class="s1">'0'</span> <span class="o">(</span>
    <span class="nb">echo</span> <span class="kd">Requesting</span> <span class="kd">administrative</span> <span class="kd">privileges</span>...
    <span class="k">goto</span> <span class="kd">UACPrompt</span>
<span class="o">)</span> <span class="k">else</span> <span class="o">(</span> <span class="k">goto</span> <span class="kd">gotAdmin</span> <span class="o">)</span>

<span class="nl">:UACPrompt</span>
    <span class="nb">echo</span> <span class="kd">Set</span> <span class="kd">UAC</span> <span class="o">=</span> <span class="kd">CreateObject</span><span class="se">^(</span><span class="s2">"Shell.Application"</span><span class="se">^)</span> <span class="o">&gt;</span> <span class="s2">"</span><span class="nv">%temp%</span><span class="s2">\getadmin.vbs"</span>
    <span class="kd">set</span> <span class="kd">params</span><span class="o">=</span> <span class="err">%</span><span class="o">*</span>
    <span class="nb">echo</span> <span class="kd">UAC</span>.ShellExecute <span class="s2">"cmd.exe"</span><span class="o">,</span> <span class="s2">"/c ""</span><span class="vm">%~s0</span><span class="s2">"" </span><span class="vm">%params</span><span class="s2">:"</span><span class="o">=</span><span class="s2">""</span><span class="err">%</span><span class="s2">", "", "</span><span class="nb">runas</span><span class="s2">", 1 &gt;&gt; "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"

    "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"
    del "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"
    exit /B

:gotAdmin
    pushd "</span><span class="nv">%CD%</span><span class="s2">"
    CD /D "</span><span class="vm">%~dp0</span><span class="s2">"
:--------------------------------------    

Pause

:exit
</span></code></pre></div></div>

<p>This snippet lets you get an administrator privilege elevation so that you can modify registry key, install a program, etc.</p>

<h2 id="how-it-works">How it works</h2>

<h3 id="1-attempt-to-run-system-level-application-caclsexe">1. Attempt to run system level application cacls.exe</h3>

<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">IF</span> <span class="s2">"</span><span class="nv">%PROCESSOR_ARCHITECTURE%</span><span class="s2">"</span> <span class="kd">EQU</span> <span class="s2">"amd64"</span> <span class="o">(</span>
<span class="o">&gt;</span><span class="kr">nul</span> <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\SysWOW64\cacls.exe"</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\SysWOW64\config\system"</span>
<span class="o">)</span> <span class="kd">ELSE</span> <span class="o">(</span>
<span class="o">&gt;</span><span class="kr">nul</span> <span class="m">2</span><span class="o">&gt;&amp;</span><span class="m">1</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\system32\cacls.exe"</span> <span class="s2">"</span><span class="nv">%SYSTEMROOT%</span><span class="s2">\system32\config\system"</span>
<span class="o">)</span>
</code></pre></div></div>

<p><a href="https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cacls">cacls.exe</a> is a system program that lets you see the access of a specific file.</p>

<p>Since you are accessing system level program, it will return error code if you don’t have a right access it.</p>

<h3 id="2-if-you-dont-have-show-uac-prompt">2. If you don’t have, show UAC prompt</h3>

<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="s1">'</span><span class="nv">%errorlevel%</span><span class="s1">'</span> <span class="kd">NEQ</span> <span class="s1">'0'</span> <span class="o">(</span>
    <span class="nb">echo</span> <span class="kd">Requesting</span> <span class="kd">administrative</span> <span class="kd">privileges</span>...
    <span class="k">goto</span> <span class="kd">UACPrompt</span>
<span class="o">)</span> <span class="k">else</span> <span class="o">(</span> <span class="k">goto</span> <span class="kd">gotAdmin</span> <span class="o">)</span>
</code></pre></div></div>

<p>Check the error code. If there was an error running cacls.exe, run a vbs script which helps you getting the privilege access.</p>

<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nl">:UACPrompt</span>
    <span class="nb">echo</span> <span class="kd">Set</span> <span class="kd">UAC</span> <span class="o">=</span> <span class="kd">CreateObject</span><span class="se">^(</span><span class="s2">"Shell.Application"</span><span class="se">^)</span> <span class="o">&gt;</span> <span class="s2">"</span><span class="nv">%temp%</span><span class="s2">\getadmin.vbs"</span>
    <span class="kd">set</span> <span class="kd">params</span><span class="o">=</span> <span class="err">%</span><span class="o">*</span>
    <span class="nb">echo</span> <span class="kd">UAC</span>.ShellExecute <span class="s2">"cmd.exe"</span><span class="o">,</span> <span class="s2">"/c ""</span><span class="vm">%~s0</span><span class="s2">"" </span><span class="vm">%params</span><span class="s2">:"</span><span class="o">=</span><span class="s2">""</span><span class="err">%</span><span class="s2">", "", "</span><span class="nb">runas</span><span class="s2">", 1 &gt;&gt; "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"

    "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"
    del "</span><span class="nv">%temp%</span>\getadmin.vbs<span class="s2">"
    exit /B
</span></code></pre></div></div>

<p>Happy hacking!</p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="scripting" /><category term="Windows" /><category term="CMD" /><category term="Batch" /><summary type="html"><![CDATA[Get admin access to do more cool sh**]]></summary></entry><entry><title type="html">맥에서 기계식 키보드 매핑하기 (feat. 한영키 바꾸기)</title><link href="https://raacker.github.io/mac/mac-mechanical-keyboard-binding/" rel="alternate" type="text/html" title="맥에서 기계식 키보드 매핑하기 (feat. 한영키 바꾸기)" /><published>2023-08-20T00:00:00-07:00</published><updated>2023-08-20T00:34:00-07:00</updated><id>https://raacker.github.io/mac/mac-mechanical-keyboard-binding</id><content type="html" xml:base="https://raacker.github.io/mac/mac-mechanical-keyboard-binding/"><![CDATA[<h2 id="윈도우용-레이아웃으로-맞춰보자">윈도우용 레이아웃으로 맞춰보자</h2>

<p>이 글은 최소한의 노력과 최소한의 렉 등 불필요한 것 없이 세팅을 맞추는 것을 다룹니다.</p>

<p>맥에서 키보드 레이아웃을 바꾸는 방법은 다양합니다. 검색해보면 1번과 2번 방식을 정말 많이 볼 수 있습니다. 각자 가진 장단점이 조금은 명확합니다만, 최종적으로 제가 선택하는 결론은 1번과 3번 조합이에요. 둘다의 장점을 최대한 얻는 방법으로요.</p>

<p>가능한 옵션으로는 다음과 같습니다.</p>

<p>1) 맥에서 직접 키 레이아웃을 바꾸기</p>

<ul>
  <li>가장 간편합니다. 이미 맥북에서 제공하는 설정이라서요.</li>
  <li>맥에서 직접 바꾸는 것은 오히려 어떤 키가 어떤 키여야 하는지 좀 헷갈리는 편입니다.</li>
  <li>다른 키보드로 사용하려고 하면 다시 설정해줘야 합니다. (노트북과 외부키보드 역시 운영체제 입장에서는 다른 키보드입니다)</li>
</ul>

<p>2) <a href="https://karabiner-elements.pqrs.org/">Karabiner-Element</a></p>

<ul>
  <li>Daemon을 실행해서 동작하는 방식이기에 새로운 키보드 프로필, 다양한 인풋 처리 등에 자유롭습니다. 소프트웨어가 컨트롤하는 범위 안에서는 모든게 자유로우니까요.</li>
  <li>키매핑 방식으로 인해 인풋렉이 실제로 존재합니다. 입력한 키 이벤트가 Karabiner-element를 통해서 다른 입력으로 redirection되는 방식이기 때문에 어느정도 빠르게 친 입력은 인풋렉을 충분히 느낄 정도입니다.</li>
  <li>별다른 설치를 하고 이것저것 세팅해야하는 번거로움이 있습니다.</li>
</ul>

<p>3) plist 파일로 OS레벨에서 키 입력 자체를 바꾸기</p>

<ul>
  <li>잘 따라하면 어렵지 않게 할 수 있습니다. 별도의 세팅이 추가적으로 필요하지도 않구요.</li>
  <li>준물리적으로 키를 바꾸는 것이라서 어느 키보드를 사용해도 동일한 인풋이 됩니다. 대신 이 말은 어느 키보드를 사용하더라도 고정적으로 바뀌기 때문에 특정 경우에 따라서는 불편할 수 있고 문제가 발생할 수도 있습니다.</li>
</ul>

<h2 id="1-plist-파일로-입력-바꾸기">1. plist 파일로 입력 바꾸기</h2>

<p>맥은 Sierra부터 <a href="https://developer.apple.com/library/archive/technotes/tn2450/_index.html#//apple_ref/doc/uid/DTS40017618-CH1-KEY_TABLE_USAGES">hidutil</a>이라는 툴을 공식적으로 지원합니다.</p>

<p>이 툴에 세팅을 적용해주면 키보드 매핑 자체를 OS 레벨에서 적용해주는 것이구요.</p>

<p>이 세팅을 부팅시마다 적용시켜 주기위해 <code class="language-plaintext highlighter-rouge">/Library/LaunchAgents</code> 폴더에 plist 파일을 만들어 줄 것입니다. 그리고 안에 기본적인 내용을 채워넣겠습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo tee</span> /Library/LaunchAgents/com.local.KeyRemapping.plist <span class="o">&gt;</span> /dev/null <span class="o">&lt;&lt;</span> <span class="sh">'</span><span class="no">EOF</span><span class="sh">'
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;com.local.KeyRemapping&lt;/string&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/bin/hidutil&lt;/string&gt;
        &lt;string&gt;property&lt;/string&gt;
        &lt;string&gt;--set&lt;/string&gt;
        &lt;string&gt;{"UserKeyMapping":[

            {
              "HIDKeyboardModifierMappingSrc": 0x7000000E6,
              "HIDKeyboardModifierMappingDst": 0x70000006E
            }

        ]}&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</span><span class="no">EOF
</span></code></pre></div></div>

<p>이런식으로 .plist 확장자를 가지는 XML 파일로 세팅을 만들어주면 맥이 부팅하는 과정에서 이를 읽고 적용하는 방식입니다.</p>

<h2 id="2-한영키-만들기">2. 한영키 만들기</h2>

<p>아제 어떤 키를 바꿀지 확인하기 위해 <a href="https://keyboard-test.space/kor/">Keyboard Test</a> 사이트에서 키보드를 누르면서 키를 확인합니다. 저처럼 오른쪽 Alt키를 사용하신다면 Alt가 표시될거에요.</p>

<p>그리고 이 키를 <a href="https://hidutil-generator.netlify.app/">hidutil key remapping generator for MacOS</a>에서 찾아 매핑값을 얻습니다. 스페이스바 오른쪽에 위치한 Alt키는 보통 right_option에 해당합니다(0x7000000E6).</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">{</span>
    <span class="s2">"HIDKeyboardModifierMappingSrc"</span>: 0x7000000E6,
    <span class="s2">"HIDKeyboardModifierMappingDst"</span>: 0x70000006D
<span class="o">}</span>
</code></pre></div></div>

<p>맥북 키보드에서는 스페이스바 오른쪽에 Command키가 위치하고 있으니 노트북에서도 비슷한 위치에 놓고 싶으시다면 Right Command 역시 F18에 매핑해도 괜찮습니다. 저는 Right Option키만 사용하기로 했습니다.</p>

<p>위의 .plist 파일에서 매핑값을 설정한 뒤, 저장하고 <strong>재부팅</strong>을 하면 해당 키는 설정해놓은 입력 키 이벤트로 변경이 됩니다. 어느 키보드를 사용하더라도 동일하게 리매핑이 됩니다. 이제 <code class="language-plaintext highlighter-rouge">Settings -&gt; Keyboards -&gt; Keyboard Shortcuts... -&gt; Input Sources</code>로 들어가줍니다.</p>

<p><img src="/_posts/mac/2023-08-20-mac-mechanical-keyboard-binding/images/change_input_source.png" alt="Input source to f18" /></p>

<p>위 처럼 Input Sources에서 <code class="language-plaintext highlighter-rouge">Select the previous input source</code>를 꺼주고 <code class="language-plaintext highlighter-rouge">Select next source in input menu</code>의 키 값을 더블 클릭한 뒤, 저희가 방금 바꾼 키를 누르면 F18로 입력됩니다.</p>

<p>한영키를 눌러보시면 이젠 Ctrl + Space나 Tab키 같은 한영 변환을 안해도 됩니다.</p>

<h2 id="3-ctrl-alt-키바인딩-바꾸기">3. Ctrl, Alt 키바인딩 바꾸기</h2>

<p>그리고 맥북을 노트북으로 사용할 떄는 원래 가지고 있던 키 바인딩을 그대로 쓰려고 했습니다.</p>

<p>만약, 노트북 키보드나 외부키보드 모두 매핑을 맞추고 싶다면 hidutil 매핑 값을 바꾸도록 해주면 되구요. 각자 다른 매핑으로 쓰고 싶다면 Modifier Keys에 들어가서 아래처럼 바꿔주면 됩니다.</p>

<p><img src="/_posts/mac/2023-08-20-mac-mechanical-keyboard-binding/images/mechanical_keyboard.png" alt="Input source to f18" /></p>

<p>윈도우 키보드 레이아웃에 맞게</p>

<ul>
  <li>윈도우 Ctrl 키 -&gt; 맥 Command</li>
  <li>윈도우 Alt 키 -&gt; 맥 Control</li>
</ul>

<p>로 바꿔줍니다. 이렇게하면 외부키보드가 연결 되었을 때 자동으로 위 매핑이 사용됩니다.</p>

<p>윈도우키 같은 경우에는 맥에서 Option Key로 되어있는데 그대로 사용하는게 가장 편하다고 느꼈습니다.</p>

<p>위만큼만 설정 해주시고 추가적으로 원하는 바인딩은 추가만 해준다음 노트북을 재부팅하면 키매핑이 잘 바뀐 것을 보실 수 있습니다.</p>

<h2 id="4-추가-노트북에서-원화키값을-백틱키값으로-바꿔주기">4. (추가) 노트북에서 원화키값을 백틱키값으로 바꿔주기</h2>

<p>마크다운을 작성하다보면 백틱(`)을 쓸 일이 정말 많이 생깁니다. 그런데 맥북에서 한글 입력 상태에서는 백틱이 아닌 원화가 입력됩니다. 강제로 Option 키를 누르면서 백틱을 입력하는  방법도 있는데 이건 우리가 생각하는 생산성에 위배되죠.</p>

<p>hidutil은 키보드 인풋 이벤트 매핑을 바꿔줬다면 이번에는 <code class="language-plaintext highlighter-rouge">DefaultKeybinding</code>라는 파일을 만들어 입력되는 캐릭터 값 자체를 바꿔주는 방법입니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">touch</span> ~<span class="se">\L</span>ibrary<span class="se">\K</span>eyBindings<span class="se">\D</span>efaultKeyBinding.dict
</code></pre></div></div>

<p>를 하여 .dict 파일을 만든 다음, 그 안에</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="s2">"₩"</span><span class="w"> </span><span class="err">=</span><span class="w"> </span><span class="err">(</span><span class="s2">"insertText:"</span><span class="p">,</span><span class="w"> </span><span class="s2">"`"</span><span class="err">);</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>위 처럼 <code class="language-plaintext highlighter-rouge">₩</code> 캐릭터를 ` 로 바꿔주는 것입니다.</p>

<p>이 역시  재부팅을 해주면 바로 적용이 되고 한글입력, 영어입력 상관없이 사용할 수 있습니다.</p>

<h3 id="참고자료">참고자료</h3>

<p><a href="https://chillog.page/148">레오폴드 매핑하기</a>
<a href="https://www.korecmblog.com/blog/backtick-fix">Mac 한글 키보드에서 항상 원화(₩)대신 백틱(`) 입력되게 하기</a></p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="Mac" /><category term="Mac" /><category term="Setup" /><category term="DevEnv" /><summary type="html"><![CDATA[키보드 레이아웃이 다른 맥에서 윈도우 기계식 키보드 세팅해보기]]></summary></entry><entry><title type="html">맥에서 마우스 정확도 높이기</title><link href="https://raacker.github.io/mac/mac-mouse-pointer-accuracy/" rel="alternate" type="text/html" title="맥에서 마우스 정확도 높이기" /><published>2023-08-20T00:00:00-07:00</published><updated>2023-08-20T04:34:00-07:00</updated><id>https://raacker.github.io/mac/mac-mouse-pointer-accuracy</id><content type="html" xml:base="https://raacker.github.io/mac/mac-mouse-pointer-accuracy/"><![CDATA[<h2 id="결론">결론</h2>

<p><a href="https://downloads.steelseriescdn.com/drivers/tools/steelseries-exactmouse-tool.dmg">SteelSeries ExactMouse Tool</a> 깔아서 쓰세요.</p>

<h2 id="나의-mx-master-s3">나의 MX Master S3…</h2>

<p>이번에 한국에 돌아오면서 마우스를 새로 구하게 되었습니다. 그동안 로지텍의 g305를 정말 잘 사용해왔는데 한국와서 사용하다보니 오른손목이 너무 아프더라구요?? 지금 쓰는 책상이 문제인건지… 후… 이유는 찾지 못한채 계속 늘어가는 손목 통증에 결국 버티컬 마우스를 사용해보자는 결론이 났었습니다.</p>

<p>가장 잘 써왔던건 로지텍의 Lift 였는데요, 제 손이 좀 더 크다보니 작다는 느낌을 지우기 어려웠습니다.</p>

<p><img src="/_posts/mac/2023-08-20-mac-mouse-pointer-accuracy/images/lift.png" alt="lift" /></p>

<p>그렇게 당근하게된 MX Master 3S. 와 뭐 버튼도 많고 Horizontal scroll 이 있질 않나, 무한 스크롤도 있고 대박 예감?</p>

<p>MX Vertical처럼 딱 손을 세우고 쓰는건 아니지만 그래도 적당한 각도로 휘어진 형태는 나름 편하다고 느낄 정도였습니다.</p>

<p><img src="/_posts/mac/2023-08-20-mac-mouse-pointer-accuracy/images/mx_master_3s.jpg" alt="이제 잘 적응한 MX Master 3S..." />
이제 잘 적응한 MX Master 3S…</p>

<h2 id="마우스-포인터가-자꾸-어긋난다">마우스 포인터가 자꾸 어긋난다?</h2>

<p>그런데 사용을 시작한지 2일쯤 되었을까요? 제 마우스의 정확도가 상당히 떨어졌음을 실감합니다. 나이탓이겠죠. 그래도 소싯적 스타크래프트 APM 300은 나오던 사람인데… 하면서 아쉬워 했지만.</p>

<p>근데 왠걸, 윈도우도 연결해서 써봤더니 제 손은 여전한 노련미를 펼치고 있었습니다. 코드 사이를 선택하고, 창을 닫는 정확도는 여전하더라구요. 아… 맥 또 너야? 맥또너?</p>

<h2 id="마우스는-가속이-항상-문제입니다">마우스는 가속이 항상 문제입니다</h2>

<p>글쎄요, 분명! 가속을 잘 활용하고 적응하신 분들도 많을 것이라고 생각합니다. 적은 마우스 움직임만으로도 화면을 크게 넘나들 수 있을터이니 좋아하시는 분들도 많을 것 같아요. 그런데 마우스 포인터의 정확성에 민감하신 분들(저)이라면 그 미묘한 차이에 불편함을 적잖이 느낄 것입니다.</p>

<p>단순하게 구글에 검색만 해봐도 이 맥에서의 가속도를 없애기위한 노력이 많습니다.</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">LinearMouse</code>라는 앱으로도 컨트롤이 가능합니다.</li>
  <li><code class="language-plaintext highlighter-rouge">defaults write .GlobalPreferences com.apple.mouse.scaling -1</code>을 터미널에서 치면 적용되는 설정</li>
  <li><code class="language-plaintext highlighter-rouge">SteelSeries ExactMouse Tool</code>이라는 앱도 있습니다.</li>
</ul>

<p>제 기억에는 몇개가 더 있었던 것 같은데, 재부팅도 몇번 해보고 이런저런 설정 열심히 만져보다가 결국 정착하고 만족하고 쓰는 방법은</p>

<p><code class="language-plaintext highlighter-rouge">SteelSeries ExactMouse Tool</code>입니다.</p>

<h2 id="steelseries-exactmouse-tool-깔기">SteelSeries ExactMouse Tool 깔기</h2>

<p>단순합니다. 이 유지보수가 오랫동안 되지 않아서 이미지도 깨지는 앱을 깔아서 항상 데몬이 실행되도록 해주면 됩니다.</p>

<p>여전히 다운로드는 문제없이 받을 수 있습니다.</p>

<p><a href="https://downloads.steelseriescdn.com/drivers/tools/steelseries-exactmouse-tool.dmg">https://downloads.steelseriescdn.com/drivers/tools/steelseries-exactmouse-tool.dmg</a></p>

<p>다운 받고 <code class="language-plaintext highlighter-rouge">Steelseries ExactMouse: Always On</code>, <code class="language-plaintext highlighter-rouge">Start on Log on</code> 을 체크해서 마무리해주면 단순하게 끝납니다.</p>

<p>사실 프로그램 자체가 하는 일은 내부 OS 레벨에서 마우스 가속도를 막는 것입니다. 위에 적어놓은 설정등을요. 그런데 묘하게도 체감상 그 설정등이 정확하게 적용되는 느낌적인 느낌이 몇번을 시도해도 바뀌지 않더라구요. 그렇게 정착하게 된 것이 ExactMouse 입니다.</p>

<p>아직 윈도우와 비교하면 여전히 약간의 느낌을 가끔 받는데요, 불편함을 느낄 수준은 전혀 아니어서 충분히 사용하게 되었습니다.</p>

<p>마우스 고민된다면… ExactMouse, 깔아보세요!</p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="Mac" /><category term="Mac" /><category term="Setup" /><category term="DevEnv" /><summary type="html"><![CDATA[맥에서 마우스 포인터 정확도, 적중률을 더 높여보자!]]></summary></entry><entry><title type="html">Use VSCode for C++ Coding Interview Prep</title><link href="https://raacker.github.io/c++/vscode-for-coding-interview-mac/" rel="alternate" type="text/html" title="Use VSCode for C++ Coding Interview Prep" /><published>2023-08-14T00:00:00-07:00</published><updated>2023-08-14T00:34:00-07:00</updated><id>https://raacker.github.io/c++/vscode-for-coding-interview-mac</id><content type="html" xml:base="https://raacker.github.io/c++/vscode-for-coding-interview-mac/"><![CDATA[<h2 id="intro">Intro</h2>

<p>Modern coding interview websites have amazing supports for you to focus on only <em>solving the problems</em>, not dealing with compiler settings, or library includes, or even test cases. Test Case part would be the most important and encouraging key feature that which platform you would pick.</p>

<p>But then, what if you are preparing a coding interview which happens to be in other platforms? Or what if you don’t have a proper support of comprehensive intellisense?</p>

<p>The most common case for Korean engineers would be the <strong>Bakjoon Online Judge</strong> website. It has lots of problems to solve, good language supports, random competitions, etc, which is pretty nice.</p>

<p>But it has a barebone code submit system compare to other modern online coding website. You are literally writing to the nodepad and you need to handle input values as well. Well I mean it is not terrible. Some offline contests want you to handle inputs as well.</p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/boj_interface.png" alt="BOJ Website interface" /></p>

<p>It still doesn’t change that you need to write extra repetitive code to solve a problem which is… generally not your concern.</p>

<p>I was struggling with this problem as well. Even though I like the websites and its problem sets, dealing with bunch of Ctrl + C &amp; V on test cases was not fun. Furthermore, if you are preparing a second interview followed by the first coding interview, you even don’t have any platform to practice of previous questions (there is a chance that you will be asked to write the same code in live). You need to write your own test program.</p>

<p>Your last bullet here is your local development. Write yourself, test yourself, and finish yourself without anything’s help.</p>

<p>This article will cover how you setup the VSCode for simple C++ compiler, install gtest, and setup the whole test cases.</p>

<h2 id="action">Action</h2>

<h3 id="1-install-c-plugins">1. Install C++ plugins</h3>

<p>I will assume you already have g++ compiler.</p>

<p>We will install the basic plugins for C++ and as an extra, will install <code class="language-plaintext highlighter-rouge">C/C++ Compile Run</code></p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/plugins.png" alt="VSCode plugins" /></p>

<h3 id="2-install-gtest-using-homebrew">2. Install gtest using homebrew</h3>

<p>In this article, I would not cover about cmake. We will savage gtest using homebrew, easy-peasy.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew tap ros/deps
brew <span class="nb">install </span>gtest
</code></pre></div></div>

<p>ROS package has gtest included. It is not the latest version but good enough to use. Currently, I was able to download gtest 1.7.0 version.</p>

<p>Once it has done, you can find it under /opt/homebrew/</p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/homebrew_path.png" alt="homebrew path" /></p>

<p>We are going to include this path into our vscode setting.</p>

<h3 id="3-put-gtest-path-into-the-action">3. Put gtest path into the action</h3>

<p>We will change our cpp properties first so that our intellisense can find gtest.</p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/cpp_properties.png" alt="cpp properties" /></p>

<p>Add under <code class="language-plaintext highlighter-rouge">includePath</code></p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s2">"/opt/homebrew/Cellar/"</span><span class="err">,</span><span class="w">
</span><span class="s2">"/opt/homebrew/Cellar/gtest/1.7.0/include/"</span><span class="w">
</span></code></pre></div></div>

<p>And now, we need to link them with our compile setting.</p>

<p>If you go into Settings -&gt; search for compiler</p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/compiler_setting.png" alt="compiler setting basic" /></p>

<p>You will be able to see “Cpp-flags”. This is what the plugin will pass to the g++ compiler when you run.</p>

<p>I’m going to change the options to</p>

<p><code class="language-plaintext highlighter-rouge">-Wall -Wextra -g3 -std=c++17 -I/opt/homebrew/Cellar/gtest/1.7.0/include -L/opt/homebrew/Cellar/gtest/1.7.0/lib/ -lgtest</code></p>

<ul>
  <li>-std=c++17 : set my c++ standard to C++17. You can use C++11, C++14, C++20, etc.</li>
  <li>-I/path/to/include : Add gtest’s include path here</li>
  <li>-L/path/to/lib : Add gtest’s lib path here</li>
  <li>-lgtest : Link gtest.</li>
</ul>

<h3 id="4-write-a-test">4. Write a test</h3>

<p>You need to setup the main function as below.</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;gtest/gtest.h&gt;</span><span class="cp">
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="k">namespace</span> 
<span class="p">{</span>
    <span class="n">TEST</span><span class="p">(</span><span class="n">ClassName</span><span class="p">,</span> <span class="n">Test1</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
        <span class="kt">int</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">20</span><span class="p">;</span>

        <span class="n">ASSERT_EQ</span><span class="p">((</span><span class="n">a</span> <span class="o">*</span> <span class="n">b</span><span class="p">),</span> <span class="mi">200</span><span class="p">);</span>
    <span class="p">}</span>    
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
    <span class="o">::</span><span class="n">testing</span><span class="o">::</span><span class="n">InitGoogleTest</span><span class="p">(</span><span class="o">&amp;</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
    
    <span class="n">RUN_ALL_TESTS</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>You need to call <code class="language-plaintext highlighter-rouge">InitGoogleTest()</code> with parameters but you don’t have to use them particulary.</p>

<p>And write a test case using <code class="language-plaintext highlighter-rouge">TEST()</code> under different namespace for an easy of use.</p>

<p>Now, let’s compile and run.</p>

<p><img src="/_posts/c++/08_14_vscode_for_cpp/images/run_result.png" alt="run result" /></p>

<p>If your test cases are successful, you are all set!</p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="C++" /><category term="C++" /><category term="Interview" /><summary type="html"><![CDATA[Let's install g++ and gtest for coding interview practice.]]></summary></entry><entry><title type="html">React Note - 7. React Route</title><link href="https://raacker.github.io/react/react-note-route/" rel="alternate" type="text/html" title="React Note - 7. React Route" /><published>2022-12-07T00:00:00-08:00</published><updated>2022-12-07T21:30:00-08:00</updated><id>https://raacker.github.io/react/react-note-route</id><content type="html" xml:base="https://raacker.github.io/react/react-note-route/"><![CDATA[<p>We have every tools for a single page now.</p>

<p>It’s time for a multi page system.</p>

<p>We are going to have a following file structures that categorizing</p>

<ul>
  <li><strong>components</strong> : main <em>content</em> items that fill out a page.</li>
  <li><strong>routes</strong> : pages that contents are being placed.</li>
</ul>

<p><img src="/_posts/react/react-note-06-route/images/source_structure.png" alt="source structure" /></p>

<blockquote>
  <p>For example</p>

  <p>raacker.github.io will have the <em>Main.js</em> under routes folder.</p>

  <p>raacker.github.io/about will have the <em>About.js</em> under routes folder.</p>

  <p><em>Post.js</em>, <em>CodeSnippet.js</em>, or any small widgets will be parts of components folder</p>
</blockquote>

<p>Let’s define Movie component first. Data will be a json result of <em>https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&amp;sort_by=year</em></p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nx">PropTypes</span> <span class="k">from</span> <span class="dl">"</span><span class="s2">prop-types</span><span class="dl">"</span><span class="p">;</span>

<span class="kd">function</span> <span class="nx">Movie</span><span class="p">({</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">coverImage</span><span class="p">,</span> <span class="nx">title</span><span class="p">,</span> <span class="nx">year</span><span class="p">,</span> <span class="nx">summary</span><span class="p">,</span> <span class="nx">genres</span> <span class="p">})</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">div</span> <span class="nx">key</span><span class="o">=</span><span class="p">{</span> <span class="nx">id</span> <span class="p">}</span><span class="o">&gt;</span>
            <span class="o">&lt;</span><span class="nx">img</span> <span class="nx">src</span><span class="o">=</span><span class="p">{</span> <span class="nx">coverImage</span> <span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/img</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">h2</span><span class="o">&gt;</span>
                <span class="p">{</span> <span class="nx">title</span> <span class="p">}</span> <span class="p">(</span> <span class="p">{</span> <span class="nx">year</span> <span class="p">}</span> <span class="p">)</span>
            <span class="o">&lt;</span><span class="sr">/h2</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">summary</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">ul</span><span class="o">&gt;</span>
                <span class="p">{</span>
                    <span class="nx">genres</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">genre</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                        <span class="k">return</span> <span class="p">(</span><span class="o">&lt;</span><span class="nx">li</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">genre</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/li&gt;</span><span class="se">)</span><span class="err">;
</span>                    <span class="p">})</span>
                <span class="p">}</span>
            <span class="o">&lt;</span><span class="sr">/ul</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>

<span class="nx">Movie</span><span class="p">.</span><span class="nx">propTypes</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">id</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">number</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
    <span class="na">coverImage</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">string</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
    <span class="na">title</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">string</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
    <span class="na">year</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">string</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
    <span class="na">summary</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">number</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
    <span class="na">genres</span><span class="p">:</span> <span class="nx">PropTypes</span><span class="p">.</span><span class="nx">array</span><span class="p">.</span><span class="nx">isRequired</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">Movie</span><span class="p">;</span>
</code></pre></div></div>

<p>It covers</p>

<ul>
  <li>Define propTypes to secure expected parameters and their types</li>
  <li>Return a <em>React Component</em> which shows some movie information briefly</li>
</ul>

<p>Then we will have a Home page that list up all the movies of the query result.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">useState</span><span class="p">,</span> <span class="nx">useEffect</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="nx">Movie</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">../components/Movie</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">function</span> <span class="nx">Home</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">isLoading</span><span class="p">,</span> <span class="nx">setLoading</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">page</span><span class="p">,</span> <span class="nx">setPage</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
    <span class="kd">const</span> <span class="p">[</span><span class="nx">fetchResult</span><span class="p">,</span> <span class="nx">setFetchResult</span><span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">([]);</span>
    <span class="kd">const</span> <span class="nx">getMovies</span> <span class="o">=</span> <span class="k">async</span><span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">`https://yts.mx/api/v2/list_movies.json?minimum_rating=8.8&amp;sort_by=year&amp;page=</span><span class="p">${</span><span class="nx">page</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>

        <span class="kd">const</span> <span class="nx">json</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>

        <span class="nx">setFetchResult</span><span class="p">(</span><span class="nx">json</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">movies</span><span class="p">);</span>
        <span class="nx">setLoading</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="kd">const</span> <span class="nx">prevPage</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">setPage</span><span class="p">(</span><span class="nx">curr</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="k">if</span> <span class="p">(</span><span class="nx">curr</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
            <span class="k">return</span> <span class="nx">curr</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
        <span class="p">});</span>
    <span class="p">}</span>
    <span class="kd">const</span> <span class="nx">nextPage</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">setPage</span><span class="p">(</span><span class="nx">curr</span> <span class="o">=&gt;</span> <span class="nx">curr</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">getMovies</span><span class="p">();</span>
    <span class="p">},</span> <span class="p">[</span><span class="nx">isLoading</span><span class="p">,</span> <span class="nx">page</span><span class="p">]);</span>

    <span class="k">return</span> <span class="p">(</span>

    <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">h2</span><span class="o">&gt;</span><span class="nx">Movie</span> <span class="nx">App</span><span class="o">&lt;</span><span class="sr">/h2</span><span class="err">&gt;
</span>        <span class="p">{</span>
            <span class="nx">isLoading</span> <span class="p">?</span> <span class="o">&lt;</span><span class="nx">b</span><span class="o">&gt;</span><span class="nx">Loading</span><span class="p">...</span><span class="o">&lt;</span><span class="sr">/b&gt; : &lt;button onClick={ getMovies }&gt;Refresh&lt;/</span><span class="nx">button</span><span class="o">&gt;</span>
        <span class="p">}</span>
        <span class="p">{</span>
            <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">length</span> <span class="o">!==</span> <span class="mi">0</span> <span class="p">?</span> <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span> <span class="nx">prevPage</span> <span class="p">}</span><span class="o">&gt;</span><span class="nx">Prev</span> <span class="nx">Page</span><span class="o">&lt;</span><span class="sr">/button&gt; : nul</span><span class="err">l
</span>        <span class="p">}</span>
        <span class="p">{</span>
            <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">length</span> <span class="o">!==</span> <span class="mi">0</span> <span class="p">?</span> <span class="o">&lt;</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span> <span class="nx">nextPage</span> <span class="p">}</span><span class="o">&gt;</span><span class="nx">Next</span> <span class="nx">Page</span><span class="o">&lt;</span><span class="sr">/button&gt; : nul</span><span class="err">l
</span>        <span class="p">}</span>

        <span class="p">{</span>
            <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">movie</span><span class="p">)</span> <span class="o">=&gt;</span> 
                <span class="o">&lt;</span><span class="nx">Movie</span>
                    <span class="nx">id</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">id</span> <span class="p">}</span>
                    <span class="nx">coverImage</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">medium_cover_image</span> <span class="p">}</span>
                    <span class="nx">title</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">title</span> <span class="p">}</span>
                    <span class="nx">year</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">year</span> <span class="p">}</span>
                    <span class="nx">summary</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">summary</span> <span class="p">}</span>
                    <span class="nx">genres</span><span class="o">=</span><span class="p">{</span> <span class="nx">movie</span><span class="p">.</span><span class="nx">genres</span> <span class="p">}</span>
                <span class="sr">/</span><span class="err">&gt;
</span>            <span class="p">)</span>
        <span class="p">}</span>
    <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">Home</span><span class="p">;</span>
</code></pre></div></div>

<p>This is literally a barebone page without any styles.</p>

<p>It has</p>

<ul>
  <li>Use an asynchronous function to fetch API result and apply it to the React Component.</li>
  <li>Use <em>useEffect</em> to update only when desired states get changed</li>
  <li>To render Movie data, we are using <em>Movie Component</em>.</li>
</ul>

<p>Let’s modify <strong>App.js</strong> to open Home.js</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span>
    <span class="nx">BrowserRouter</span> <span class="k">as</span> <span class="nx">Router</span><span class="p">,</span>
    <span class="nx">Routes</span><span class="p">,</span>
    <span class="nx">Route</span>
<span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-router-dom</span><span class="dl">'</span><span class="p">;</span>

<span class="k">import</span> <span class="nx">Home</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./routes/Home</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">function</span> <span class="nx">App</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
      <span class="o">&lt;</span><span class="nx">Router</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">Routes</span><span class="o">&gt;</span>
          <span class="o">&lt;</span><span class="nx">Route</span> <span class="nx">path</span><span class="o">=</span><span class="dl">"</span><span class="s2">/</span><span class="dl">"</span> <span class="nx">element</span><span class="o">=</span><span class="p">{</span> <span class="o">&lt;</span><span class="nx">Home</span> <span class="o">/&gt;</span> <span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/Routes</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/Router</span><span class="err">&gt;
</span>  <span class="p">);</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">App</span><span class="p">;</span>
</code></pre></div></div>

<p><img src="/_posts/react/react-note-06-route/images/barebone_image.png" alt="Home.js" /></p>

<p>Now, let’s add a detail page we can reroute when we click a title or a poster image.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">useParams</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react-router-dom</span><span class="dl">'</span><span class="p">;</span>
<span class="k">import</span> <span class="p">{</span> <span class="nx">useState</span><span class="p">,</span> <span class="nx">useEffect</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">react</span><span class="dl">'</span><span class="p">;</span>

<span class="kd">function</span> <span class="nx">Detail</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="p">{</span> <span class="nx">id</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">useParams</span><span class="p">();</span>
    <span class="kd">const</span> <span class="p">[</span> <span class="nx">fetchResult</span><span class="p">,</span> <span class="nx">setFetchResult</span> <span class="p">]</span> <span class="o">=</span> <span class="nx">useState</span><span class="p">([]);</span>

    <span class="kd">const</span> <span class="nx">getMovieDetail</span> <span class="o">=</span> <span class="k">async</span><span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s2">`https://yts.mx/api/v2/movie_details.json?movie_id=</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>

        <span class="kd">const</span> <span class="nx">json</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">();</span>

        <span class="nx">setFetchResult</span><span class="p">(</span><span class="nx">json</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">movie</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nx">useEffect</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">getMovieDetail</span><span class="p">();</span>
    <span class="p">},</span> <span class="p">[]);</span>

    <span class="k">return</span> <span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
            <span class="o">&lt;</span><span class="nx">h2</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">title</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/h2</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">img</span> <span class="nx">src</span><span class="o">=</span><span class="p">{</span> <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">background_image</span> <span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/img</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">t</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">fetchResult</span><span class="p">.</span><span class="nx">description_full</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/t</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>

<span class="k">export</span> <span class="k">default</span> <span class="nx">Detail</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>See the <strong>id</strong> in <em>String literal url</em> and <strong>useParams</strong> of react-router-dom. It lets you bind parameters that you pass to the <em>Detail</em> component.</li>
</ul>

<p>If you add a one more line to the App.js, and a <strong>Link Component</strong> to the Movie, it’s done.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">App</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="p">(</span>
      <span class="o">&lt;</span><span class="nx">Router</span><span class="o">&gt;</span>
        <span class="o">&lt;</span><span class="nx">Routes</span><span class="o">&gt;</span>
          <span class="o">&lt;</span><span class="nx">Route</span> <span class="nx">path</span><span class="o">=</span><span class="dl">"</span><span class="s2">/</span><span class="dl">"</span> <span class="nx">element</span><span class="o">=</span><span class="p">{</span> <span class="o">&lt;</span><span class="nx">Home</span> <span class="o">/&gt;</span> <span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>          <span class="o">&lt;</span><span class="nx">Route</span> <span class="nx">path</span><span class="o">=</span><span class="dl">"</span><span class="s2">/movie/:id</span><span class="dl">"</span> <span class="nx">element</span><span class="o">=</span><span class="p">{</span> <span class="o">&lt;</span><span class="nx">Detail</span> <span class="o">/&gt;</span> <span class="p">}</span> <span class="sr">/</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/Routes</span><span class="err">&gt;
</span>      <span class="o">&lt;</span><span class="sr">/Router</span><span class="err">&gt;
</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">function</span> <span class="nx">Movie</span><span class="p">({</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">coverImage</span><span class="p">,</span> <span class="nx">title</span><span class="p">,</span> <span class="nx">year</span><span class="p">,</span> <span class="nx">summary</span><span class="p">,</span> <span class="nx">genres</span> <span class="p">})</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span>
        <span class="o">&lt;</span><span class="nx">div</span> <span class="nx">key</span><span class="o">=</span><span class="p">{</span> <span class="nx">id</span> <span class="p">}</span><span class="o">&gt;</span>
            <span class="o">&lt;</span><span class="nx">Link</span> <span class="nx">to</span><span class="o">=</span><span class="p">{</span><span class="s2">`/movie/</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">`</span><span class="p">}</span><span class="o">&gt;</span>
                <span class="o">&lt;</span><span class="nx">img</span> <span class="nx">src</span><span class="o">=</span><span class="p">{</span> <span class="nx">coverImage</span> <span class="p">}</span><span class="o">&gt;&lt;</span><span class="sr">/img</span><span class="err">&gt;
</span>                <span class="o">&lt;</span><span class="nx">h2</span><span class="o">&gt;</span>
                    <span class="p">{</span> <span class="nx">title</span> <span class="p">}</span> <span class="p">(</span> <span class="p">{</span> <span class="nx">year</span> <span class="p">}</span> <span class="p">)</span>
                <span class="o">&lt;</span><span class="sr">/h2</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="sr">/Link</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">summary</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/p</span><span class="err">&gt;
</span>            <span class="o">&lt;</span><span class="nx">ul</span><span class="o">&gt;</span>
                <span class="p">{</span>
                    <span class="nx">genres</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">genre</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
                        <span class="k">return</span> <span class="p">(</span><span class="o">&lt;</span><span class="nx">li</span><span class="o">&gt;</span><span class="p">{</span> <span class="nx">genre</span> <span class="p">}</span><span class="o">&lt;</span><span class="sr">/li&gt;</span><span class="se">)</span><span class="err">;
</span>                    <span class="p">})</span>
                <span class="p">}</span>
            <span class="o">&lt;</span><span class="sr">/ul</span><span class="err">&gt;
</span>        <span class="o">&lt;</span><span class="sr">/div</span><span class="err">&gt;
</span>    <span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<ul>
  <li>Using colons like <strong><code class="language-plaintext highlighter-rouge">:id</code></strong> is how you determine URL with parameters.</li>
  <li>By using <strong><code class="language-plaintext highlighter-rouge">&lt;Link&gt;</code></strong>, you are rerouting URL to this component with a specific URL format which is <code class="language-plaintext highlighter-rouge">*/movie/${ id }*</code></li>
</ul>

<p><img src="/_posts/react/react-note-06-route/images/after_reroute.png" alt="Detail.js" /></p>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="React" /><category term="react" /><category term="frontend" /><summary type="html"><![CDATA[Paging has never been easier than this]]></summary></entry><entry><title type="html">캐나다에서 한식 만들기 - 육회</title><link href="https://raacker.github.io/hobby/beef-tartar/" rel="alternate" type="text/html" title="캐나다에서 한식 만들기 - 육회" /><published>2022-12-05T00:00:00-08:00</published><updated>2022-12-05T19:20:00-08:00</updated><id>https://raacker.github.io/hobby/beef-tartar</id><content type="html" xml:base="https://raacker.github.io/hobby/beef-tartar/"><![CDATA[<h2 id="실상은-이러했습니다">실상은 이러했습니다</h2>

<p>제가 짧은 기간인 3년동안 살면서 본 캐나다는 한국 식품에 대해 이미지가 정말 좋습니다.</p>

<p>한국 식료품의 접근성은 정말 높고, 한식 식당도 많이 생기고 있습니다. 또한 한국인이 아니신 분들도 여러 영상매체 등을 통해 소개된 한국 음식 또는 친구를 통해 접한 한국 음식 덕분에 이미지나 선호도가 정말 높다고 느껴집니다.</p>

<p>제가 살고 있는 밴쿠버는 한국 분들도 많으시고 오래전부터 이민이 이루어지던 도시라서 더 가능했을거에요. 아마 몇몇 지역에서는 상황이 조금 다를 수도 있을 것 같습니다.</p>

<p>그러나..! 한식을 좋아하는 저에게 항상 아쉬움이 남아있었는데요. 그것은 바로 맛과 가격에 대한 욕심이었습니다.</p>

<p>밴쿠버 물가 미쳤죠. 밖에서 몇번 사먹고나면 강남가서 일주일 먹을 수 있지 않을까 하는 (실제로 그렇진 않습니다) 생각이 들 정도로 체감이 상당해요. 최근 각국 경제 상황이 안좋아지면서 식재료 값에 대한 타격도 피부에 많이 와닿습니다.</p>

<p>한식은 밴쿠버에 있는 많고 많은 식당중에서도 가격대가 조금 높다는 이미지가 있는 라인업입니다. 일반 음식점에 가서 찌개류를 먹으면 팁+세금 포함 CAD $18을 심심치 않게 내야하고 철판 요리나 메인류를 먹고 싶다면 술 없이도 두세명이서 명당 $30은 우스워집니다.</p>

<p>이러한 실정이니 사먹는 것을 점점 멀리하면서 한식을 먹기는 더더욱 힘들어 졌습니다. 자취 생활이라고는 대학교 시절에 기숙사 살고 동생과 살았던게 다였으니 음식을 제대로 할 줄도 모르는 한낱 공돌이에 불과했으니까요. 하지만 밴쿠버로 오게 되면서 저는 어떻게든 한식을 배우고 연습하고 만들어봐야 했습니다. 허구헌날 파스타만 만들어 먹을 수는 없잖아요? 🥲</p>

<h2 id="육회가-먹고-싶더라">육회가 먹고 싶더라</h2>

<p>밴쿠버에서 육회를 파는 식당은 횟집보다 찾기 어렵습니다. 아무래도 신선한 소고기를 공급받는 것, 그리고 그 물량을 꾸준히 소비해줄 소비층의 부재가 겹쳐서 일까요? 그래도 육회라도 먹어야겠다 생각하던 저는 열심히 찾아내고 공부한 끝에 육회를 만들어 먹게 되었습니다.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/gwangjang-sijang.jpeg" alt="광장시장 육회" />
<sub>동생이 놀리듯 자랑하던 광장시장 육회 츄릅</sub></p>

<p>물론 한국의 그 맛에 근접하기엔 너무 힘듭니다. 제가 대전 궁동에서 먹었던 갓잡은 소의 신선한 육회 맛은 아직도 불가능에 가까운 것 같습니다. 하지만 그래도 얼추 따라는 갈 수 있어요..!</p>

<p>서론이 쓸데없이 너무 길었습니다. 육회를 어떻게 찾고 만들게 되었는지 빠르고 간단하게 공유해드릴게요!</p>

<h2 id="고기-부위-이름이-정말-헷갈립니다">고기 부위 이름이 정말 헷갈립니다</h2>

<p>그동안 시도하기 어려워하고 시행착오를 겪던 이유는 바로 부위 이름때문이었습니다. 나름 한 구글링한다고 생각했는데 찾아보면 자료마다 부위 명칭이 제각각이더라구요? 어느 그림에는 단순히 뭉뚱그려서 엉덩이쪽 전체를 Rump라고 하기도 하고 서로 비교해보면 어느 말이 맞는지 확인이 어려워져서 생각보다 혼동하기 쉽습니다.</p>

<p>보통 육회는 주로 우둔살과 홍두깨살을 사용하여 먹습니다.</p>

<p>우둔(牛臀)은 소의 엉덩이를 뜻하는 단어입니다. 영어로는 Beef Hip, 또는 Beef Round라고 불립니다. 우둔살 및 홍두깨살 모두 이 우둔이라는 카테고리에 속하며 우둔살은 보통 <em>Top Round, Inside Round, Rump</em>라고 하고 홍두깨살은 <em>Eye of Round</em>라고 불립니다.</p>

<ul>
  <li>
    <p>우둔살은 엉덩이의 안쪽에 위치한 부위이며 지방이 적은 살코기 덩어리입니다. 연하고 담백한데 질긴 맛이 덜하여 육회 부위로 선호됩니다. 엉덩이 안쪽에 위치하여서 Inside Round라는 이름이 붙여진 듯 하네요.</p>
  </li>
  <li>
    <p>홍두깨살은 우둔살 바로 옆에 홍두깨 방망이처럼 길게 붙어있는 부위입니다. 역시 지방이 거의 없는 살코기 부위입니다. 길게 늘여뜨린 모양새라서 Eye라는 이름이 붙여진 것 같죠?</p>
  </li>
  <li>
    <p>설도, 설깃은 <em>Bottom Round</em>이라 불리는 부위입니다. 운동량이 많은 부위라서 우둔살에 비해 조금 질기다고 알려져있습니다. 하지만 취향에 따라 이 부위 육회를 선호하시는 분들도 있다고 하네요.</p>
  </li>
</ul>

<p>다른 사진 다 필요 없어요. 열심히 공부한 결과, 이 사진이 최종 결론이었습니다.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/beef-round.png" alt="" />
<br />
<sub><a href="https://www.philinlove.com/entry/Beef-cuts">출처 - [필리핀 생활] 소고기의 부위별 영어 명칭과 요리용도</a></sub></p>

<p><img src="/_posts/foods/korean/beef-tartar/images/beef-chart.png" alt="Beef Chart" />
<br />
<a href="https://canadabeef.wpenginepowered.com/wp-content/uploads/2019/03/RS3290_CBI_Bilingual_Consumer_Cuts_Chart_EN_021517_F.zip-CBI_Retail_Consumer_Cuts_Chart_ENG_F_LOWRES.pdf">출처 - Buying and cooking canadian beef, canadianbeef.ca</a></p>

<p>CanadianBeef에서 정리해놓은 pdf인데 이곳에서는 정확하게 모든 부위를 상세히 나누어주었습니다.</p>

<h2 id="이제-부위만-잘-사오면-됩니다">이제 부위만 잘 사오면 됩니다</h2>

<p>보통은 Round라는 이름이 붙은 것을 찾은 뒤 취향에 따라서 각 부위를 찾으시면 됩니다. 초보 요리사인 제 입에는 우둔살이나 홍두깨살이나 그게 그거였어요.</p>

<p>단, 육회는 말 그대로 고기를 날것으로 먹는 것이기에 신선한 부위로 잘 사야 맛있습니다. <a href="https://imnews.imbc.com/replay/2021/nwtoday/article/6109147_34943.html">갈변 현상</a>을 거의 찾아 볼 수 없는 수준의 고기로 사면 괜찮아요. <em>갈변은 산소에 노출 될 수록 많이 생기기 때문에</em> 최대한 없을 수록 생산된지 얼마 안되었다는 의미이기도 합니다. 그리고 아무래도 생고기이니 더 조심할 수 밖에 없어요.</p>

<p>정리된 팁을 드리자면</p>

<ul>
  <li><em>마트마다(심지어 같은 체인이라해도) 고기 공급 일정이 다릅니다</em>. 물론 정말 당일에 갓 들어온 고기라고 해도 아주 신선한 육회라고 기대하기는 참 어렵지만… 그래도 <em>마트의 일정에 가까울 수록</em> 신선도가 높습니다. 이는 2~3일 간격으로 그 마트를 가서 살펴보면 어느정도 알 수 있게 됩니다.</li>
  <li>주변 <em>다른 부위들의 Best Before 날짜</em>를 잘 살펴보세요. 자주 소비되는 부위일 수록 재고를 더 받는 편이고 부위마다 날짜도 조금씩 다르더라구요. 하지만 대충 잘 보면 이 마트의 재고 회전율이 높은지 적은지 앵간하면 보입니다. <em>재고 회전율이 높다면 신선도 좋은 고기를 구하기는 상대적으로 쉬워</em>집니다.</li>
  <li>되도록이면 <strong>붉은 빛</strong> &gt; 분홍빛 &amp; 갈색 이라고 생각하면 될 것 같습니다.</li>
  <li>핏물이 최대한 안빠져 있어야 합니다. 그만큼 패키징 된지 시간이 지난 것이니까요.</li>
</ul>

<p>예로 몇가지 사진을 보여드릴께요. 보정이나 필터 없이 제 아이폰이 주는 사진 날 것 그대로를 가져왔습니다.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/eye_of_round_steak.png" alt="Eye of Round Steak" />
<img src="/_posts/foods/korean/beef-tartar/images/eye_of_round_steak2.png" alt="Eye of Round Steak" /></p>

<p>Safeway에서 팔고 있는 홍두깨살입니다. 윗 사진에는 Packaged On 날짜가 안적혀 있지만 아래 부위에는 써있네요. 대략 유통기한을 5일로 잡고 있다는 것을 확인 할 수 있으니 Best Before에서 5일을 뺀 날짜를 기준으로 찾으시면 되겠습니다. 그리고 물론 정확하진 않지만 육안 상으로도 위에 있는 것이 더 불그스름 했어요.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/eye_of_round_roast.png" alt="Eye of Round Roast" /></p>

<p>사실 Unit Price로 미뤄봤을때 그냥 Roast와 Steak의 차이는 단순히 양인 것 같습니다. Unit Price 자체가 완전 같으니 고기의 질은 둘이 별반 다를바가 없어요. 나는 오늘 육회로 배를 찢겠다 혹은 친구 여러명이서 먹을 예정이다 싶으시면 Roast로 사면 될 것 같습니다. 아니면 일부는 회 썰어먹고 나머지는 다져서 산적이나 떡갈비로 만드셔도 됩니다.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/costco_eye_of_round.jpeg" alt="Eye of Round Roast Costco" /></p>

<p>코스트코에서 파는 통짜 홍두깨살입니다. 양이 진짜 많긴 한데 얼린 고기도 맛이 제법 괜찮아서 나쁘지 않은 선택인것 같습니다. 단위 가격도 다른 마트에 비해 훨씬 싸기도 하구요. 이게 2.8kg니까 9인분까지는 가능할 수 있는… 양 같아요.</p>

<p><img src="/_posts/foods/korean/beef-tartar/images/bad_sample_1.png" alt="Bad Sample 1" />
<img src="/_posts/foods/korean/beef-tartar/images/bad_sample_2.png" alt="Bad Sample 2" /></p>

<p>사진을 잘 보시면 알겠지만 위쪽은 H Mart고 아래는 T&amp;T입니다.</p>

<p>H Mart 사진을 보시면 Best Before가 26일까지 입니다. 제가 19일에 구매를 했으니 최소 7일 정도의 유통기한을 준다는 것인데 색이 상당히 분홍색이죠? 맛도 그저 그랬습니다.</p>

<p>T&amp;T 사진을 보면 그 유명한 Angus Beef 라는데 정작 재고는 전부 23일까지만 있더라구요. 20일 일요일에 봤으니 어쩌면 재고가 들어오는 날에 다시 확인하면 상태가 다를지도 모릅니다.</p>

<h2 id="썰고-양념하기">썰고 양념하기</h2>

<p>육회에 대해서 공부하고 있다보니 예전에 친구들과 육사시미를 먹었던 기억이 나서 찾아봤었는데요,</p>

<p>육사시미와 육회는 뭐 거의 같은 것이 아닌가.. 싶었는데 먹는 방법에 따라 구분이 되는 형태라고 합니다. 육사시미 자체가 일본어가 섞인 형태이지만 대체할 용어가 따로 없다고 하네요.</p>

<blockquote>
  <p>육사시미는 육회와 동일하게 소고기를 이용하지만, 육회는 채썰기를, 육사시미는 지역마다 차이는 있지만 생선회처럼 얇게 썰어 먹습니다.</p>

  <p>또한 육사시미는 육회처럼 미리 양념하지 않고, 생선회처럼 참기름장 또는 초고추장 등의 양념장에 찍어 먹는 것도 차이점입니다.</p>

  <p>즉, 육회와 육사시미는 소고기 부위에 따라 구분되는 것이 아니고, 먹는 방법에 따라 구분되는 것입니다.</p>
</blockquote>

<p><sub><a href="https://themeat.tistory.com/634">출처 - 소고기 육회 만들기</a></sub></p>

<p>저는 육회가 더 좋아서 양념장들을 여러가지 찾아봤습니다. 취합해봤을때 공통적으로 사용하는 재료들이 있었어요.</p>

<blockquote>
  <p>육회 300g 기준</p>

  <ul>
    <li>한국인의 긍지를 보여주는 정도의 마늘 한 스푼. 그렇다고 너무 넣으면 맛을 가립니다ㅋㅋㅋ</li>
    <li>참기름 한 스푼. 너무 많이 넣으면 물리고 느끼해집니다.</li>
    <li>간장 반 스푼. 또는 소금 한 꼬집. 간은 취향에 따라서 하시면 됩니다.</li>
    <li>(Optional) 후추 한 꼬집.</li>
    <li>(Optional) 설탕 반 스푼. 대신 꿀을 넣거나 유청을 넣기도 하더라구요.</li>
    <li>(Optional) 배 1/4개.</li>
    <li>(Optional) 계란 노른자</li>
    <li>(Optional) 새싹 채소 또는 채썬 파</li>
  </ul>
</blockquote>

<p>저는 최종적으로</p>

<p>다진 마늘 두 스푼, 간장 반 스푼, 소금 한 꼬집, 꿀 한 스푼, 계란 노른자, 그리고 새싹 채소 조합으로 결론이 나더라구요. 물론 이 부분은 적당히 취향대로 시도해 보시는 것을 추천드립니다.</p>

<h2 id="만드는-순서">만드는 순서</h2>

<ol>
  <li>
    <p>겉면에 있는 핏물을 열심히 제거한 고기를 1~2시간동안 냉동시킵니다.</p>

    <p>얼린 고기가 채썰기 훨씬 쉽구요, 맛도 시원하게 해서 먹는게 더 괜찮았던 것 같습니다.</p>
  </li>
  <li>
    <p>고기를 고깃결과 반대 방향으로 채를 썬 뒤, 물기를 한 번 더 제거해줍니다.</p>

    <p>물기가 없을 수록 양념이 잘 묻어나 맛을 살릴 수 있습니다.</p>

    <p>고깃결의 반대 방향이라는 것은 고기의 살점이 나있는 방향을 수직으로 끊어주는 느낌입니다. 이미 있는 선을 가로로 다 그어버리는 거죠. 고기의 근섬유와 결합조직을 끊어주는 작업입니다.</p>
  </li>
  <li>
    <p>원하는 대로 양념장을 만들어 짧은 시간안에 젓가락으로 섞어줍니다.</p>

    <p>신선도와 시원한 맛이 떨어지면 맛과 식감이 조금 떨어질 수 있으니 빠르게 해야합니다. 그리고 체온으로 식는 것을 피하기 위해 젓가락 사용을 추천드립니다.</p>
  </li>
</ol>

<h2 id="정리해주세요">정리해주세요</h2>

<ul>
  <li>우둔살은 <em>Top Round, Inside Round, 또는 Beef Rump</em>라는 이름으로 찾을 수 있습니다.</li>
  <li>홍두깨살은 <em>Eye of Round Steak 또는 Eye Round Chuck</em> 이라는 이름으로 찾을 수 있습니다.</li>
  <li>최대한 선명한 붉은 색, 그리고 핏물이 안나온 것으로 사세요.</li>
</ul>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="hobby" /><category term="food" /><category term="korean" /><summary type="html"><![CDATA[캐나다에서 한식 만들기 - 육회]]></summary></entry><entry><title type="html">TMIOS Design Pattern, 18 - Memento</title><link href="https://raacker.github.io/designpattern/tmios-18-memento/" rel="alternate" type="text/html" title="TMIOS Design Pattern, 18 - Memento" /><published>2022-11-23T00:00:00-08:00</published><updated>2022-11-23T23:39:00-08:00</updated><id>https://raacker.github.io/designpattern/tmios-18-memento</id><content type="html" xml:base="https://raacker.github.io/designpattern/tmios-18-memento/"><![CDATA[<blockquote>
  <p>GoF Numbering : 18<br />
Category : Behavioral Pattern<br />
Readings : <a href="https://en.wikipedia.org/wiki/Memento_pattern">Wikipedia</a>,
<a href="https://www.cs.unc.edu/~stotts/GOF/hires/pat5ffso.htm">cs.unc.edu</a>,
<a href="https://refactoring.guru/design-patterns/memento">Refactoring.guru</a><br />
As known as : Snapshot</p>
</blockquote>

<h2 id="in-one-sentence">In One Sentence</h2>

<p>Hänsel and Gretel’s bread scrums that helps you go back to where you were at.</p>

<blockquote>
  <p>All the bread scrums were gone because of birds but let’s just say it is still there. Hänsel and Gretel can track them back to see where the location was.</p>
</blockquote>

<p><img src="/_posts/design-pattern/18-Memento/images/hansel_and_gretel.png" alt="hansel_and_gretel_states" /></p>

<p><sub>Image by <a href="https://storiestogrowby.org/story/hansel-and-gretel-bedtime-stories-for-kids/">AlyssaTallent</a></sub></p>

<h2 id="problem">Problem</h2>

<p>The easiest case to think about is <strong>Undo</strong> operation.</p>

<p>When you are using <a href="https://raacker.github.io/designpattern/tmios-14-command/">Command Pattern</a>, the advantage you could get from using it is “Undo &amp; Redo” feature.</p>

<p>Since you have a history of each command, you can track back operations of the command to un-apply. Then, you need to remember what happened to the object after and before the command (using timestone 🙄).</p>

<p>At this point, <strong>Memento Pattern</strong> exactly acts as a <em>Snapshot</em>. Store affected values of the object and retrieve them when undoing.</p>

<p>Well sadly, our <em>actual problem</em> joins the game now. Here is why.</p>

<p>In our real life development, most of data objects (or classes) contain very important information and <strong>we don’t want them to be exposed externally</strong>. Why “Exposing members” deserves hatred?</p>

<p>Compiler will let you expose them, no problem. But it creates so much coupling overall and the logic &amp; pipeline of the program goes <em>unexpected</em>. Because no one cares which value goes in, what methods can be used or not, etc. It is a total mayhem!</p>

<p><em>Getter and Setter</em>, <em>Access modifiers (private, protected, etc.)</em> are introduced to defeat this monster. They fight really well by restricting access of own members. They draw boundaries that others cannot across. And eventually if the data or method belongs to its own, no one can touch it. Perfect.</p>

<p>No.</p>

<p>We have different problem now because of this restriction.</p>

<p>When we want to take a snapshot of an object, it means we have to store most of, basically all of, members. Especially, as I mentioned above, most of private members are very critical information of an object. We need to store them for sure. But most of modern software design uses lots of design patterns and mostly they ensure you have abtraction layers at some point.</p>

<p>In other words, You don’t have any acknowledgement or access inside of an object. It is kind of trade off we made. We got huge flexibilty, modularity, maintainability (which are the most important factors in Software Design though) but we lose access to “<strong>Detailed</strong> control over data”.</p>

<h2 id="what-memento-pattern-is-trying-to-solve">What Memento Pattern is trying to solve?</h2>

<p><strong>Memento Pattern</strong> doesn’t act only for storing intermediate data. It has an important role to secure encapsulation of objects and let them unrevealed even though we need some access to their very hidden deep informations.</p>

<p>In formal words, Memento Object works with the <strong>Owner Object(or Originator)</strong> closely and it has an access to private fields of the owner. The Originator can store Memento Objects as many as it wants(as a history of states). When a desired state is required, it retrieves a Memento Object and rollback all the fields.</p>

<p>If we don’t use Memento Pattern for storing states, we <em>have to</em> modify the accessor or find something very <del>shitty</del> bad solution.</p>

<h2 id="keep-in-mind">Keep in mind</h2>

<p>Memento Pattern could be language-specific pattern when it comes to immutability and integrity of a Memento Object.</p>

<p>Nested Class or Friend Class will work very well as a Memento Object but we must ensure they cannot be changed overtime. But some of dynamic languages such as php, javascript will not assure when they get changes.</p>

<p>And someone should take care of the history, mostly the Originator. But it means the external controller (so called caretaker or controller) doesn’t know the existence of leftover states. Since each Memento Object tends to be a memory object, it could lead a memory leak if their life cycles are not managed properly.</p>

<h2 id="code-example">Code Example</h2>

<p><a href="https://github.com/raacker/raacker.github.io/tree/master/_posts/design-pattern/18-Mememto/codes/cpp">Conceptual C++ Version</a></p>

<p>The conceptual C++ Version demonstrates simple concept of storing states and retrieving them back using Serialization library.</p>

<p>As you can see from the code, states are managed by Originator itself and the memento is accessing its private member value to store.</p>

<blockquote>
  <p>Disclaimer : Yes, this example is yet perfect. But the ideal and real-life solutions will be serializing, in most of cases. And friend class keyword will be another which is only C++/C# feature though.</p>

  <p>In this Conceptual example, I used <em>Introduce Parameter Object</em> from Refactoring and <em>alpaca library</em> to accept struct as a parameter.</p>
</blockquote>

<h2 id="example-ideas">Example Ideas</h2>

<ul>
  <li>OS Reset System
    <ul>
      <li>As you can see from Window’s recovery system, they keep a snapshot of the OS before some specific events or big changes. You can select the backup time and use the backup information to rollback.</li>
    </ul>
  </li>
  <li>Server Client Snapshot
    <ul>
      <li>Very similar concept as above example. But I think it’s more common to think about nowadays since most of cloud based computing instances support backup and recovery system.</li>
    </ul>
  </li>
  <li>Text File Editor
    <ul>
      <li>Very common idea to think about when it comes to <em>undo</em> command.</li>
    </ul>
  </li>
</ul>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="designpattern" /><category term="Design Pattern" /><category term="TMIOS" /><summary type="html"><![CDATA[Teach me in one sentence, Design Pattern series - Memento]]></summary></entry><entry><title type="html">TMIOS Design Pattern, 17 - Mediator</title><link href="https://raacker.github.io/designpattern/tmios-17-mediator/" rel="alternate" type="text/html" title="TMIOS Design Pattern, 17 - Mediator" /><published>2022-11-20T00:00:00-08:00</published><updated>2022-11-20T22:18:00-08:00</updated><id>https://raacker.github.io/designpattern/tmios-17-mediator</id><content type="html" xml:base="https://raacker.github.io/designpattern/tmios-17-mediator/"><![CDATA[<blockquote>
  <p>GoF Numbering : 17<br />
Category : Behavioral Pattern<br />
Readings : <a href="https://en.wikipedia.org/wiki/Mediator_pattern">Wikipedia</a>,
<a href="https://www.digitalocean.com/community/tutorials/mediator-design-pattern-java">DigitalOcean</a>,
<a href="https://www.cs.unc.edu/~stotts/GOF/hires/pat5efso.htm">cs.unc.edu</a>,
<a href="https://refactoring.guru/design-patterns/mediator">Refactoring.guru</a><br />
As known as : Moderator, Intermediary, Channel Center</p>
</blockquote>

<h2 id="in-one-sentence">In One Sentence</h2>

<p>A Police officer that you can ask how you can go or where you need to go.</p>

<p><img src="/_posts/design-pattern/17-Mediator/images/police_officer.jpg" alt="police_officer" /></p>

<p><sub>Image by <a href="&quot;https://www.freepik.com/free-vector/traffic-police-concept-illustration_32439083.htm#query=traffic%20policeman&amp;position=4&amp;from_view=search&amp;track=sph&quot;">storyset on Freepik</a></sub></p>

<blockquote>
  <p>You need to bring your new report to the hospital. But to drive through, you must pass the intersection of the city. There is a police officer who guides you where you should go.</p>

  <p>Funny enough, sometimes they bring a report to you. You don’t know who sent it but at least you know that’s from the hospital.</p>
</blockquote>

<h2 id="problem">Problem</h2>

<p>The problem that Mediator Pattern aims for is straighforward: Kill couplings.</p>

<p>If your modifications to a component affects others to be changed, it means they have coupling, whole lotta dependencies. It’s not love, at all.</p>

<h2 id="what-mediator-pattern-is-trying-to-solve">What Mediator Pattern is trying to solve?</h2>

<ul>
  <li>Common Interface for sub components.
    <ul>
      <li>Obtain <a href="https://en.wikipedia.org/wiki/Single-responsibility_principle">Single Responsibility Principle</a> : Each component does only their own thing.</li>
      <li>Obtain <a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle">Open-Closed Principle</a> : By putting an abstraction layer around components, adding extra components is a piece of cake.</li>
    </ul>
  </li>
</ul>

<p>But…</p>

<ul>
  <li>At the end, Mediator Object controls lots of logics. And even though we are reducing coupling of each components, we sacrifice large coupling of Mediator-Components. We call it <strong>God Object</strong>.
    <ul>
      <li>Suggested way would be splitting Mediator Object into several small Mediators based on responsibility. And let them communicate each other as well. By putting nets around similar &amp; related components, it increases maintainability of each Mediator Object and makes it easy to read.</li>
    </ul>

    <blockquote>
      <p>If there is a ProjectManager, splitting responsibilities into ProjectIOManager, DocumentManager, UnitManager, LogManager, etc. will make it a lot easier to handle. They can be singletons or nested &amp; composition objects depends on designs.</p>
    </blockquote>
  </li>
</ul>

<h2 id="keep-in-mind">Keep in mind</h2>

<p>Dealing with coupling? yes, the goal is simple enough. But there is a special role of Mediator.</p>

<p>Unlike the other <em>sender &amp; receiver</em> patterns such as <a href="https://raacker.github.io/designpattern/tmios-13-cor/">Chain of Responsibility</a>, <a href="https://raacker.github.io/designpattern/tmios-14-command/">Command</a>, Mediator opens <em>Bi-directional</em> communication channels for sub components.</p>

<p>It means that Mediator Pattern still keep the components do not know each other, they can send a request or receive a message from the Mediator Object. It abstracts everthing still. But it gives them a chance to send and receive at the same time.</p>

<p>Thus, sub components also have a reference of Mediator Object, or a channel to access Mediator Object depends on implementation.</p>

<p>Meanwhile, other patterns are <em>Uni-directional</em> relationship which they send a message to the sub components but sub components do not know the presence of Handler Object.</p>

<h2 id="code-example">Code Example</h2>

<p><a href="https://github.com/raacker/raacker.github.io/tree/master/_posts/design-pattern/17-Mediator/codes/cpp">C++ Version</a></p>

<p>I realized I was doing too much “external” works rather than focusing on the Mediator Object 😅. Thus I will stop at the current state.</p>

<p>Some of the code should be refactored and for sure currently they remain undone.</p>

<p>But you will get ideas of</p>

<ul>
  <li>How does the Mediator Object <em>communicate with sub components</em></li>
  <li>How is the <em>Command Pattern</em> used as a manner of communication protocol</li>
  <li><em>FactoryMethod</em> to create Commands.
    <ul>
      <li>Eventually, Aircrafts and extra components should also use Factory Method or Abstract Factory to generalize and give extra abstraction in between structures.</li>
    </ul>
  </li>
</ul>

<p>I will come back to this sample if I’m willing to put more comprehensive pattern mixture example later when I get into other patterns.</p>

<h2 id="example-ideas">Example Ideas</h2>

<ul>
  <li>Aircraft Control Tower
    <ul>
      <li>It manages a region of skyline, by calling the aircrafts to land or depart. They get approval requests from the planes.</li>
    </ul>
  </li>
  <li>MVC Architecture
    <ul>
      <li>A controller of Model - View - Controller pattern is a mediator pattern as well. It cuts off the dependency of each data model &amp; UI representation components. But it is able to interact with them bidirectionally.</li>
    </ul>
  </li>
</ul>]]></content><author><name>Haven Kim</name><email>haven.cpp@gmail.com</email></author><category term="designpattern" /><category term="Design Pattern" /><category term="TMIOS" /><summary type="html"><![CDATA[Teach me in one sentence, Design Pattern series - Mediator]]></summary></entry></feed>