<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[낭중일기]]></title><description><![CDATA[낭중일기]]></description><link>http://github.com/dylang/node-rss</link><generator>RSS for Node</generator><lastBuildDate>Wed, 06 Jun 2018 10:56:34 GMT</lastBuildDate><item><title><![CDATA[electron의 윈도우용 인스톨러 NSIS 설정]]></title><description><![CDATA[인스톨러를 인스톨러처럼 보이게 하기 위해 흘린 땀과 진땀.]]></description><link>https://wanderer.work/articles/electron의-윈도우용-인스톨러-NSIS-설정/</link><guid isPermaLink="false">https://wanderer.work/articles/electron의-윈도우용-인스톨러-NSIS-설정/</guid><pubDate>Wed, 06 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;얼마 전부터 일렉트론으로 무언가를 하고 있는데 슬슬 인스톨러를 붙여볼 시점이 되어 &lt;a href=&quot;https://github.com/electron-userland/electron-builder&quot;&gt;electron-builder&lt;/a&gt;의 설정을 뒤적이며 삽질한 결과 몇가지 알게된 것이 기뻐 몇자 끄적여본다.&lt;/p&gt;
&lt;h2&gt;NSIS&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt;에서 윈도우용 인스톨러로는 &lt;code&gt;nsis&lt;/code&gt;, &lt;code&gt;appx&lt;/code&gt;, &lt;code&gt;msi&lt;/code&gt;, &lt;code&gt;squirrel&lt;/code&gt; 등을 선택할 수 있는데 나는 그 중에 &lt;code&gt;nsis&lt;/code&gt;를 선택했다. 특별한 이유가 있지는 않고 &lt;code&gt;electron-builder&lt;/code&gt;의 기본값이기도 하고 문서에서도 상대적으로 자세하게 설명되어 있기 때문에 선택했다. &lt;a href=&quot;https://ko.wikipedia.org/wiki/NSIS&quot;&gt;NSIS&lt;/a&gt;는 널소프트 스크립터블 인스톨 시스템의 약자로 추억의 프로그램 윈앰프의 인스톨러를 위해 만들어졌다고 한다.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;package.json&lt;/code&gt;을 이용한 설정&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt;를 사용할 때는 &lt;code&gt;package.json&lt;/code&gt; 파일에 &lt;code&gt;build&lt;/code&gt; 설정을 추가할 수 있다. 여기에 입력할 수 있는 옵션들은 홈페이지에 자세히 나와있다. 주소마저 기억하기 쉽다. 그것은 바로 &lt;a href=&quot;https://electron.build/&quot;&gt;https://electron.build/&lt;/a&gt;이다. 가령 내 경우 현재 이 정도 설정을 추가했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-json&quot;&gt;&lt;code&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  ...
  &lt;span class=&quot;token property&quot;&gt;&quot;productName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;소중한 앱이름&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;electron-builder build&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ...소중한 의존모듈님들
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;devDependencies&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ...소중한 개발의존모듈님들
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;appId&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;com.myappid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;files&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;나의소중한파일들의경로&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;win&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nsis&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;arch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;x64&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;ia32&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;나의소중한아이콘경로.ico&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;nsis&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;oneClick&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;perMachine&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;allowToChangeInstallationDirectory&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;language&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1042&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;include&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;build/installer.nsh&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;shortcutName&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;단축아이콘 이름&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;directories&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;output&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;빌드를마친파일이가야할경로&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;하나씩 살펴보면 다음과 같다.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;productName&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;인스톨러에 표시되는 프로그램 이름을 설정할 때 이 값을 사용한다.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;scripts&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt;의 cli 명령은 &lt;a href=&quot;https://www.electron.build/cli&quot;&gt;문서&lt;/a&gt;에 잘 나와있다. npm script에 &lt;code&gt;electron-builder build&lt;/code&gt;를 등록하여 사용하고 있다.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;build&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;electron-builder&lt;/code&gt;의 본격적인 설정이다. 이름만 봐도 어느 정도 알 수 있다. 이름만으로 알 수 없는 설정은 다음과 같다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.oneClick&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;별도의 경로 설치없이 한방에 설치되게 할 것인가를 설정한다. 기본값은 &lt;code&gt;true&lt;/code&gt;라서 이 설정없이 만든 인스톨러를 실행하면 &lt;code&gt;%APPDATA%&lt;/code&gt;로 설치된다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.perMachine&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;사용자별 설치인지 기기 단위 설치인지 설정하는 옵션이다. &lt;code&gt;oneClick&lt;/code&gt; 값에 따라서 기본값이 바뀐다고 문서에 설명되어 있다. &lt;code&gt;oncClick&lt;/code&gt;을 &lt;code&gt;false&lt;/code&gt;로 두고 인스톨러를 빌드해서 실행했더니 사용자가 선택하도록 하는 화면이 나왔다. &lt;code&gt;perMachine&lt;/code&gt;을 &lt;code&gt;true&lt;/code&gt;로 해서 선택화면이 나오지 않게 했다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.allowToChangeInstallationDirectory&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;사용자가 설치하면서 설치 디렉토리를 변경할 수 있는지 여부이다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.language&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;인스톨러의 언어를 지정한다. 설명에는 기본값이 시스템 언어라고 되어 있던데 내가 해보니 영문을 모르겠지만 영어로 나왔다. 여기에는 마이크로소프트의 LCID 값을 넣어줘야 한다고 되어 있다. 그런데 문서에 있는 링크로 가보면 필요한 값이 없어서 좀 더 찾아보니 &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/ff531906(v=office.12).aspx&quot;&gt;이런 문서&lt;/a&gt;를 발견했다. 한국어는 &lt;code&gt;1042&lt;/code&gt;이다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.shortcutName&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;바탕화면에 생성되는 단축아이콘의 이름이다.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;nsis.include&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;NSIS가 사용하는 스크립트를 추가할 수 있다. &lt;code&gt;build/installer.nsh&lt;/code&gt; 경로에 파일을 생성한다. 위에서 언급한 것처럼 설치 디렉토리의 기본값이 &lt;code&gt;%APPDATA%&lt;/code&gt;라서 변경하기 위해서 여기에 스크립트를 사용했다. 문서의 경우에는 &lt;code&gt;C:\MyApp&lt;/code&gt;에 설치하도록 설명하고 있는데, &lt;code&gt;C&lt;/code&gt;외의 드라이브를 루트로 사용하는 사람들도 간혹 있기 때문에 불안한 방법이라고 생각되어 조금 더 찾아본 결과 아래와 같이 사용하기로 했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;Var SystemDrive

!macro preInit
    ReadEnvStr $SystemDrive SYSTEMDRIVE
    SetRegView 64
    WriteRegExpandStr HKLM &quot;${INSTALL_REGISTRY_KEY}&quot; InstallLocation &quot;$SystemDrive\앱이설치될폴더명&quot;
    WriteRegExpandStr HKCU &quot;${INSTALL_REGISTRY_KEY}&quot; InstallLocation &quot;$SystemDrive\앱이설치될폴더명&quot;
    SetRegView 32
    WriteRegExpandStr HKLM &quot;${INSTALL_REGISTRY_KEY}&quot; InstallLocation &quot;$SystemDrive\앱이설치될폴더명&quot;
    WriteRegExpandStr HKCU &quot;${INSTALL_REGISTRY_KEY}&quot; InstallLocation &quot;$SystemDrive\앱이설치될폴더명&quot;
!macroend&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;변수는 &lt;code&gt;!macro&lt;/code&gt;안에 선언할 수 없고 전역에 두어야 하는 모양이다. &lt;code&gt;ReadEnvStr $SystemDrive SYSTEMDRIVE&lt;/code&gt; 구문은 변수 &lt;code&gt;$SystemDrive&lt;/code&gt;에 환경변수인 SYSTEMDRIVE를 담도록 하고 있다. 그 아래는 64bit와 32bit 운영체제에 따라 별도의 경로를 설정할 수 있다.&lt;/p&gt;
&lt;p&gt;가령 위의 경우처럼 &lt;code&gt;$SystemDrive&lt;/code&gt; 대신에 &lt;code&gt;$ProgramFiles64&lt;/code&gt; 또는 &lt;code&gt;$ProgramFiles&lt;/code&gt;도 사용할 수 있는 것 같다. &lt;code&gt;ProgramFiles&lt;/code&gt;의 경우에는 별도로 변수를 할당해 주지 않아도 경로 지정이 가능했다.&lt;/p&gt;
&lt;p&gt;참고로 잘못된 경로를 넣으면 빌드에 실패한다. 나 같은 경우에는 시스템 드라이브 루트에 설치되게 하기 위해서 삽질을 하다보니 잘못 넣으면 빌드에 실패한다는 사실을 체감하고 말았다.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;directories.output&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;빌드된 인스톨러가 저장되는 경로이다. 별도로 지정하지 않으면 &lt;code&gt;dist&lt;/code&gt; 디렉토리에 저장된다.&lt;/p&gt;
&lt;h3&gt;그리고, &lt;code&gt;node-gyp&lt;/code&gt; 또는 &lt;code&gt;node-pre-gyp&lt;/code&gt; 빌드오류&lt;/h3&gt;
&lt;p&gt;일렉트론을 빌드할 때 네이티브 모듈을 재빌드하곤 하는데, 이유는 알 수 없지만 &lt;code&gt;windows-build-tools&lt;/code&gt;로 설정해놓은 작업환경에서도 빌드가 실패했다. 빌드실패로 생기는 오류가 엉뚱한 점 중의 하나는 빌드에 실패한 후 바이너리 다운로드를 시도하다가 다운로드에 실패한 것으로 나오는 경우이다.&lt;/p&gt;
&lt;p&gt;혹시 &lt;code&gt;node-pre-gyp ERR! Tried to download(403):&lt;/code&gt; 같은 오류와 함께 URL이 생기는 오류라면 다운로드가 아니라 로컬환경에서 빌드가 되지 않아 생기는 오류를 의심하는 편이 문제를 빨리 해결하는데 도움이 될 것이다. 내 경우에는 &lt;code&gt;sqlite3&lt;/code&gt;로 인해 다음과 같은 오류를 경험했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;node-pre-gyp ERR! Tried to download(403): https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.0/electron-v1.8-win32-x64.tar.gz&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;결론적으로는 &lt;code&gt;node-gyp&lt;/code&gt; 빌드가 가능한 환경을 달성하면 된다. 마이크로소프트의 Node.js 가이드라인에 &lt;a href=&quot;https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#environment-setup-and-configuration&quot;&gt;수동 환경설정 과정&lt;/a&gt;이 소개되어 있다. 빌드에 성공한 방법은 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual C++ BuildTools 설치: &lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkId=691126&quot;&gt;http://go.microsoft.com/fwlink/?LinkId=691126&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python 2.7 설치: &lt;a href=&quot;https://www.python.org/downloads/&quot;&gt;https://www.python.org/downloads/&lt;/a&gt; (윈도우 환경변수에 파이썬 경로를 추가해주어야 한다.)&lt;/li&gt;
&lt;li&gt;모두 설치를 마치면 명령창에서 &lt;code&gt;npm config set msvs_version 2015&lt;/code&gt;를 실행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이렇게 해도 실패한다면 &lt;code&gt;node_modules&lt;/code&gt; 디렉토리를 삭제하고 의존 모듈을 다시 설치해보기를 추천한다. 혹시 그래도 안된다면… 멀리서나마 행운을 빌겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[나의 Amazon Go 방문기]]></title><description><![CDATA[시애틀에 간 김에 들른 아마존 고. 포켓몬 고가 아닙니다. 그리고 시애틀은 잠도 잘 옵니다.]]></description><link>https://wanderer.work/articles/나의-Amazon-Go-방문기/</link><guid isPermaLink="false">https://wanderer.work/articles/나의-Amazon-Go-방문기/</guid><pubDate>Wed, 23 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEC/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQID/9oADAMBAAIQAxAAAAGTTEwKP//EABgQAAMBAQAAAAAAAAAAAAAAAAABERAS/9oACAEBAAEFAhw5W0//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAWEQADAAAAAAAAAAAAAAAAAAAAARL/2gAIAQIBAT8Btls//8QAFxABAAMAAAAAAAAAAAAAAAAAACAxQf/aAAgBAQAGPwJqof/EABoQAQEAAwEBAAAAAAAAAAAAAAEAESExoeH/2gAIAQEAAT8h0Y0kOn1K/Ucsys3/2gAMAwEAAgADAAAAEEgf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAEDAQE/EEsL/8QAFhEBAQEAAAAAAAAAAAAAAAAAARBB/9oACAECAQE/EANn/8QAGxABAQEAAgMAAAAAAAAAAAAAAREAITFBUdH/2gAIAQEAAT8QrUQOhhqYT6rLCt48r7rlupe9YL1v/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;평화로운 조류들&quot;
        title=&quot;&quot;
        src=&quot;/static/birds-17d0ef1598c6fb463a9a68b4233947ba-1155e.jpg&quot;
        srcset=&quot;/static/birds-17d0ef1598c6fb463a9a68b4233947ba-53e7a.jpg 240w,
/static/birds-17d0ef1598c6fb463a9a68b4233947ba-5db52.jpg 480w,
/static/birds-17d0ef1598c6fb463a9a68b4233947ba-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gas_Works_Park&quot;&gt;Gas Works Park&lt;/a&gt;의 평화로운 조류들. 나랑은 관련이 없다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;시애틀은 졸립습니다.&lt;/h2&gt;
&lt;p&gt;시차와 피로의 영향으로 밤낮을 가리지 않고 잠이 오는 시애틀에는 유명한 우주바늘을 비롯해서 별다방 1호점, 파이크플레이스 마켓 같은 유명 관광지도 많다. 잠못 이룰만한 일은 벌어지질 않는다. 여기에는 블로그 분위기에 어울리게 아마존의 편의점인 Amazon Go에 방문한 이야기를 잠시 적어본다.&lt;/p&gt;
&lt;h2&gt;아마존 고&lt;/h2&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAgb/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAVrXOvhsjGd//8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAEQMEEhP/2gAIAQEAAQUC1MnE9egzLaCo2VwpY3//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFX/8QAFREBAQAAAAAAAAAAAAAAAAAAABL/2gAIAQIBAT8BS//EABgQAAIDAAAAAAAAAAAAAAAAAAABEBEh/9oACAEBAAY/AnY0sh6VH//EABgQAAMBAQAAAAAAAAAAAAAAAAABEVEx/9oACAEBAAE/IdykhdyTB22RhF2ssHqp/9oADAMBAAIAAwAAABC07//EABYRAAMAAAAAAAAAAAAAAAAAAAEQIf/aAAgBAwEBPxChP//EABYRAQEBAAAAAAAAAAAAAAAAAAEAIf/aAAgBAgEBPxB2CX//xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhMVFh/9oACAEBAAE/EDoBmK8+Qmdz2+e7kJILRHbZoFODsdM0IWqi5LZ//9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;아마존 고&quot;
        title=&quot;&quot;
        src=&quot;/static/amazongo-b57320ca26d7b7c769d56a15069bab8d-1155e.jpg&quot;
        srcset=&quot;/static/amazongo-b57320ca26d7b7c769d56a15069bab8d-53e7a.jpg 240w,
/static/amazongo-b57320ca26d7b7c769d56a15069bab8d-5db52.jpg 480w,
/static/amazongo-b57320ca26d7b7c769d56a15069bab8d-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;아마존 고는 계산하는 점원이 없는 대형 편의점 정도의 느낌이었다. 예상과 달리 무인점포 같은 느낌은 아니고 점원도 매우 여러명이 있고, 일도 하는 것 같지만 자기들끼리 모여서 이야기를 나누고 있는 것 같기도 하다. 한국 편의점 알바의 업무 강도에 비하면 뭔가 행복해보이는 사람들이 주황색 옷을 입고 서성이고 있다.&lt;/p&gt;
&lt;div&gt;
          &lt;div
            class=&quot;gatsby-resp-iframe-wrapper&quot;
            style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden;margin-bottom: 1.0725rem&quot;
          &gt;
            &lt;iframe src=&quot;https://www.youtube.com/embed/NrmMk1Myrxc?rel=0&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen style=&quot;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
          &quot;&gt;&lt;/iframe&gt;
&amp;gt; &amp;#xC544;&amp;#xB9C8;&amp;#xC874; &amp;#xACE0;&amp;#xC758; &amp;#xBAA8;&amp;#xB4E0; &amp;#xAC83;&amp;#xC744; &amp;#xBCF4;&amp;#xC5EC;&amp;#xC8FC;&amp;#xB294; &amp;#xB3D9;&amp;#xC601;&amp;#xC0C1;. &amp;#xADF8;&amp;#xB807;&amp;#xB2E4; &amp;#xC800;&amp;#xAC8C; &amp;#xC804;&amp;#xBD80;&amp;#xB2E4;.
          &lt;/div&gt;
          &lt;/div&gt;
&lt;p&gt;입장을 위해서는 아마존 고 전용 앱을 설치하고 카드를 등록해야 한다. 한국에서 발급받은 신용카드도 쓸 수 있다. 나는 해외결제가 되는 신한은행 체크카드를 사용했는데 이걸로도 문제없이 결제가 되었다. 입장할 때 앱을 실행해서 출입구에서 태그를 찍고 입장한다. 일행이 있는 경우에는 일행을 먼저 입장시키고 입장해야 한다. 바구니에 상품을 넣었다 빼는 경우에는 물건을 넣은 사람이 꺼내야 제대로 인식한다는 설명이 있었다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAwABBP/EABYBAQEBAAAAAAAAAAAAAAAAAAIBA//aAAwDAQACEAMQAAABDQ6s0cMp/8QAGxAAAgIDAQAAAAAAAAAAAAAAAQIAEQMSISL/2gAIAQEAAQUCxNRfg3i+RLof/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAaEAACAgMAAAAAAAAAAAAAAAAAAQIRECEx/9oACAEBAAY/ApIVmpMbJKuLH//EABoQAQADAQEBAAAAAAAAAAAAAAEAESExUUH/2gAIAQEAAT8hoLiezUVXFeKGgeZMbQ1N1BkY59n/2gAMAwEAAgADAAAAEBwv/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAERIVH/2gAIAQMBAT8QSiFp/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERUf/aAAgBAgEBPxB4yvD/xAAaEAEAAwEBAQAAAAAAAAAAAAABABEhMUHh/9oACAEBAAE/EEYpRAblnjG7OXhxyZeBm/IlPKMHeR5VIrW0wvUIcXU//9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;상품들&quot;
        title=&quot;&quot;
        src=&quot;/static/pic1-13baa2bc199bacbb27c88b03445a7a3b-1155e.jpg&quot;
        srcset=&quot;/static/pic1-13baa2bc199bacbb27c88b03445a7a3b-53e7a.jpg 240w,
/static/pic1-13baa2bc199bacbb27c88b03445a7a3b-5db52.jpg 480w,
/static/pic1-13baa2bc199bacbb27c88b03445a7a3b-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;봄 신상품으로 소바 샐러드가 출시되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQBAv/EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAGXlpYiS//EABwQAAEFAAMAAAAAAAAAAAAAAAEAAgMREgQTIf/aAAgBAQABBQJ0lijMhim8hduyfV//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAfEAABAwMFAAAAAAAAAAAAAAAAAREhAiIxMmGBkaH/2gAIAQEABj8CminotaELuDT6MyzuYQ//xAAcEAACAgIDAAAAAAAAAAAAAAABEQAhMUFhofD/2gAIAQEAAT8hCoQndIWyhdOGNqfTELgwQBeDiEEdAU//2gAMAwEAAgADAAAAEPMv/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/EKF//8QAFhEBAQEAAAAAAAAAAAAAAAAAABEB/9oACAECAQE/EJqP/8QAHxABAAICAAcAAAAAAAAAAAAAAREhAGExQVGBodHh/9oACAEBAAE/EIpAi1G6yYkAVCAInxh/WNfYcXYvmMyH/JFDwLxe1VrpX3vn/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;cctv&quot;
        title=&quot;&quot;
        src=&quot;/static/pic2-da6750bfdfbf7615d012fc4f4b261448-1155e.jpg&quot;
        srcset=&quot;/static/pic2-da6750bfdfbf7615d012fc4f4b261448-53e7a.jpg 240w,
/static/pic2-da6750bfdfbf7615d012fc4f4b261448-5db52.jpg 480w,
/static/pic2-da6750bfdfbf7615d012fc4f4b261448-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;콤부차를 집을까봐 일거수일투족을 감시하는 카메라.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAwQA/8QAFgEBAQEAAAAAAAAAAAAAAAAAAwEC/9oADAMBAAIQAxAAAAGZpFzZM+Jf/8QAGBABAQEBAQAAAAAAAAAAAAAAAQIAAxL/2gAIAQEAAQUCtmasnPPIbqvmJKP/xAAXEQEAAwAAAAAAAAAAAAAAAAAAAQMR/9oACAEDAQE/AUV6/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERA//aAAgBAgEBPwGD0h//xAAYEAEAAwEAAAAAAAAAAAAAAAAAASExMv/aAAgBAQAGPwLIcqY1b//EABsQAQADAAMBAAAAAAAAAAAAAAEAESExUXGR/9oACAEBAAE/IRpaPRDjVCrZpop3Zhv4YscPIxdI1P/aAAwDAQACAAMAAAAQNy//xAAXEQEBAQEAAAAAAAAAAAAAAAABABFB/9oACAEDAQE/ENOwAb//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQIBAT8QNFj/xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMVFhkf/aAAgBAQABPxBsmNBXvn7AwBUHLgwDLI96U7RFyljUI57uGCo2vs//2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;머그잔&quot;
        title=&quot;&quot;
        src=&quot;/static/mug-41b8f9fe0189750fcebc85e4ae7f751b-1155e.jpg&quot;
        srcset=&quot;/static/mug-41b8f9fe0189750fcebc85e4ae7f751b-53e7a.jpg 240w,
/static/mug-41b8f9fe0189750fcebc85e4ae7f751b-5db52.jpg 480w,
/static/mug-41b8f9fe0189750fcebc85e4ae7f751b-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;들고 나가기만 하면 된다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAWAQEBAQAAAAAAAAAAAAAAAAACAAH/2gAMAwEAAhADEAAAAZVRo1Bniv/EABoQAAICAwAAAAAAAAAAAAAAAAECABESMUH/2gAIAQEAAQUCZ6AUFyEz5qXc/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Bh//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/Aaf/xAAbEAACAgMBAAAAAAAAAAAAAAAAEQECEiFRcf/aAAgBAQAGPwKuMR6b2WfRcGM//8QAHRABAAICAgMAAAAAAAAAAAAAAQARMUEhUWFxgf/aAAgBAQABPyG2CU0hldVtI2z4eo/JQMXU2MvM/9oADAMBAAIAAwAAABDfz//EABYRAQEBAAAAAAAAAAAAAAAAABEAAf/aAAgBAwEBPxDBrN//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREh/9oACAECAQE/EHWEP//EABwQAQEAAgIDAAAAAAAAAAAAAAERACExUXGRof/aAAgBAQABPxB9xSgtsYcHrGtitMeTWjTgAB8wINbE7wpoo3fjLTVVW8//2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;출구&quot;
        title=&quot;&quot;
        src=&quot;/static/pic3-d3ebfdcfb77c6d2e50b519983835a4ce-1155e.jpg&quot;
        srcset=&quot;/static/pic3-d3ebfdcfb77c6d2e50b519983835a4ce-53e7a.jpg 240w,
/static/pic3-d3ebfdcfb77c6d2e50b519983835a4ce-5db52.jpg 480w,
/static/pic3-d3ebfdcfb77c6d2e50b519983835a4ce-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;나도 모르게 돈이 빠져나가는 신비의 문.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAADBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAE+XQKJI8X/xAAaEAABBQEAAAAAAAAAAAAAAAABAAIEETED/9oACAEBAAEFAsPTSo5LhMpppf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAAEDBQAAAAAAAAAAAAAAAAEAECEREjFRgf/aAAgBAQAGPwIUwpYCBGlaB1v/xAAbEAEAAgIDAAAAAAAAAAAAAAABABEhYTFBkf/aAAgBAQABPyFEVr7uZOoUXAXyeQgbRlBq5XlYo7n/2gAMAwEAAgADAAAAEJDf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAEh/9oACAEDAQE/EJGP/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAEhUf/aAAgBAgEBPxBsun//xAAdEAACAwACAwAAAAAAAAAAAAABEQAhMUFxUYHR/9oACAEBAAE/EC3tgnJ0cLXcAgFzI03ee5jo6GJ70dpXk/IEiggEBadM8RCth5P/2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;전자렌지&quot;
        title=&quot;&quot;
        src=&quot;/static/pic4-5feaa83cba32225da598c62a5e7890fc-1155e.jpg&quot;
        srcset=&quot;/static/pic4-5feaa83cba32225da598c62a5e7890fc-53e7a.jpg 240w,
/static/pic4-5feaa83cba32225da598c62a5e7890fc-5db52.jpg 480w,
/static/pic4-5feaa83cba32225da598c62a5e7890fc-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;위장에 약간의 따스함을 전달하고 싶을 때는 전자렌지를 쓸 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;물건을 모두 고른 후에 훔쳐가듯이 재빠르게 출구로 나와도 결제가 되고 만다. 출구 근처에는 음식을 먹을 수 있는 공간이 있다. 일회용 식기도 있고 전자렌지도 준비되어 있다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 500px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 177.8%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAkABQDASIAAhEBAxEB/8QAGgABAAMAAwAAAAAAAAAAAAAAAAECBgMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHzraqYyTXq63PW8SKiwQD/xAAdEAACAQQDAAAAAAAAAAAAAAAAAQMQERMhEhQx/9oACAEBAAEFAsEpgmOvMbuITWW6Ea5XovRH/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAg/9oACAEDAQE/AUY//8QAFhEAAwAAAAAAAAAAAAAAAAAAARAg/9oACAECAQE/AUI//8QAHBAAAQQDAQAAAAAAAAAAAAAAAAECEDEDITMy/9oACAEBAAY/At4nHNxzcWh6h1lQutlQs//EAB8QAAICAgEFAAAAAAAAAAAAAAABESExQdEQUXGB8P/aAAgBAQABPyFcYHon9kvGWdUEMYWQaJRdHyRgQr9FilsLydhfV//aAAwDAQACAAMAAAAQjAhMcA//xAAWEQEBAQAAAAAAAAAAAAAAAAABESD/2gAIAQMBAT8QSaf/xAAXEQEBAQEAAAAAAAAAAAAAAAABERAg/9oACAECAQE/EBuCcf/EAB8QAAICAgIDAQAAAAAAAAAAAAERACExQWFxEFHw8f/aAAgBAQABPxAskl0Eyi2e2qRQZBm0aFBoZE+ijYmRur5hT4PBAre4IDl3RxSUA0IiBLLf5GAEdiAA01+4pMmjAsi/Fge5/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;결제내역&quot;
        title=&quot;&quot;
        src=&quot;/static/app-3f13947b07479adc19c9e312b33a2639-7390c.jpg&quot;
        srcset=&quot;/static/app-3f13947b07479adc19c9e312b33a2639-f2a59.jpg 240w,
/static/app-3f13947b07479adc19c9e312b33a2639-ef19d.jpg 480w,
/static/app-3f13947b07479adc19c9e312b33a2639-7390c.jpg 500w&quot;
        sizes=&quot;(max-width: 500px) 100vw, 500px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;과자는 역시 감자칩이랑게. 감자에 싹이 나서 잎이 나서 칩, 감자감자칩…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 640px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 66.71875%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAAD/8QAFQEBAQAAAAAAAAAAAAAAAAAAAgP/2gAMAwEAAhADEAAAATbCXGh40x//xAAZEAADAQEBAAAAAAAAAAAAAAABAgMREjH/2gAIAQEAAQUCkBxMDGbGV8VfKkh//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAECMf/aAAgBAwEBPwGGPT//xAAXEQADAQAAAAAAAAAAAAAAAAAAAQIh/9oACAECAQE/AaWCP//EABgQAQEBAQEAAAAAAAAAAAAAAAEAETEi/9oACAEBAAY/AnyXAkwssLt//8QAGhABAQEBAAMAAAAAAAAAAAAAAREAITFRgf/aAAgBAQABPyFyU91zwrPM3SLuQI5dKaH25CVv/9oADAMBAAIAAwAAABAfD//EABYRAQEBAAAAAAAAAAAAAAAAAAEAEf/aAAgBAwEBPxAlyKIv/8QAFxEBAQEBAAAAAAAAAAAAAAAAAQARIf/aAAgBAgEBPxAzW9goN//EABsQAQEAAwEBAQAAAAAAAAAAAAERACExYUFR/9oACAEBAAE/EAsmPFZucxe8ojYfMdCVbRHvmDLYrHvv5kFiDFwoITre5//Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;결과&quot;
        title=&quot;&quot;
        src=&quot;/static/result-08dc96e35654327cd099366fb18d6886-1155e.jpg&quot;
        srcset=&quot;/static/result-08dc96e35654327cd099366fb18d6886-53e7a.jpg 240w,
/static/result-08dc96e35654327cd099366fb18d6886-5db52.jpg 480w,
/static/result-08dc96e35654327cd099366fb18d6886-1155e.jpg 640w&quot;
        sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;그리고 감자칩을 맛있게 먹었다. &lt;del&gt;러플스를 수입해달라.&lt;/del&gt; 바닥에 깔려있는 아마존 고 봉투는 &lt;strong&gt;기간 한정 사은품&lt;/strong&gt;으로 매장에 비치되어 있었다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Hammerspoon을 이용한 macOS 한영전환키 설정]]></title><description><![CDATA[Hammerspoon을 이용해서 원하는 키를 한영 전환에 사용해봅니다.]]></description><link>https://wanderer.work/articles/hammerspoon을-이용한-macOS-한영전환키-설정/</link><guid isPermaLink="false">https://wanderer.work/articles/hammerspoon을-이용한-macOS-한영전환키-설정/</guid><pubDate>Wed, 27 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Caps Lock이 싫어서&lt;/h2&gt;
&lt;p&gt;시에라 이후로는 CapsLock 키로 한영전환을 할 수 있게 되서 버릇을 고친 사람도 많겠지만, 미개한 나의 버릇을 고치기 보다는 컴퓨터에게 일 시키는 것이 더 편하다. 사실 &lt;a href=&quot;https://pqrs.org/osx/karabiner/&quot;&gt;Karabiner-elments&lt;/a&gt;를 설치하면 간단하게 해결할 수 있지만, 마음에 들지 않는 구석이 있어 다른 방법을 찾아보다가 &lt;a href=&quot;http://www.hammerspoon.org/&quot;&gt;Hammerspoon&lt;/a&gt;을 쓰게 되었다. 참고로 이 글은 macOS는 시에라 10.12.6, Hammerspoon은 0.9.55 버전을 기준으로 작성했다.&lt;/p&gt;
&lt;h2&gt;Hammerspoon&lt;/h2&gt;
&lt;p&gt;Hammerspoon은 macOS용 매크로라고 볼 수 있다. macOS에 JXA라고 해서 Javascript로 매크로를 짜는 방법도 있기는 한데, Hammerspoon의 경우에는 Lua(&lt;a href=&quot;http://www.lua.org/&quot;&gt;http://www.lua.org/&lt;/a&gt;)로 작성한 스크립트를 실행해준다. 오픈 소스 앱이고 무료이다. 우선 앱을 설치하면 다음과 같이 상단 메뉴 막대 우측에 망치모양의 아이콘이 추가된다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 960px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 48.987854251012145%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAABYlAAAWJQFJUiTwAAACgUlEQVQozy2SXU/SYRiH+UCVLlsnbq2aWpYgqEwQBERNa77Lm2kqgiBtrtkqTBFRW00rNaPMVECjfJuZadY6yK0vcnXzp4Pf7ufoeq7fcz+qQq2eIl02BdoK+kLDaC21XHYvcsGToqDSRr7WKKnimvkW1W1d2Dq7uWKs47qtCW2jg6vmRs5rTFzUWVC9/X5K/PiUDyd/WZTz3MEf5g9PuT0cQefwofcMoe70o3OHyLN0cNbYwnmrk/pnm9imNzBPpjBMJNCPrVE2+hHVWPqE2NYvwjLD6Z+MpH4Q3f6NPTSGzjmI1hmg3BNC7QiQa24nR5JX48YaS2CJJTFFkxjG16l4uoouA3yyccRI8oj7a4f4lg8IrHzjQfIYg+8xxS196FxBCpt6yalqVezOSHItDgGuY51KUT2ZxBgRQwGWhVdQjW4eM/D+K91Le/S/28cv0NDqIUZ/mOJWr2KncQYpavGSY2rjnIAzle1iWDOdwj6ziUmglWJZHhbD4PI+PW92cS9sC3RXAffG9ynvf0RxmxeNVC3pHKREZqlziJsdAQVYK3a1ArPPbEj1VLZ2pvJAfJeexR0F6FGSPat7RiiQqlqpXNTcz412v5xD5Nd3kVvtoG4qSd1/oFWAVVK7Umqr7i5s4ZnfwvX6C26Z7vltuuQCzb2HYjigGGbM1I6gArzU2EOezUWtLMQuW87EJkBzVCxl0yrn3CccL9O4Xn2mb2lH6u8owIaxJfRDUcoCE5T6ImgGIqi9EUq845QOxuQNk9RIrLHs1zFNyHIywNbnSZol7bOb9AqsP76HU2yb59I0zaa58yJNg/y5OjHJvJsCmkxgFSNLNIF5IrvlDMwwuso/LkoGEL6YzLMAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Hammerspoon&quot;
        title=&quot;&quot;
        src=&quot;/static/hammerspoon-651af8bf106d81046e83a9c30be62e26-2e2fd.png&quot;
        srcset=&quot;/static/hammerspoon-651af8bf106d81046e83a9c30be62e26-b6d7a.png 240w,
/static/hammerspoon-651af8bf106d81046e83a9c30be62e26-bf06b.png 480w,
/static/hammerspoon-651af8bf106d81046e83a9c30be62e26-2e2fd.png 960w,
/static/hammerspoon-651af8bf106d81046e83a9c30be62e26-04c85.png 988w&quot;
        sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ㅁ..망치숟가락!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;여기서 &lt;code&gt;Open Config&lt;/code&gt;을 선택하면 Hammerspoon이 실행하는 스크립트 파일이 열린다. 이 스크립트 파일은 &lt;code&gt;~/.hammerspoon/init.lua&lt;/code&gt;에 위치하고 있다. 그런데 내가 Lua 문법을 좀 아느냐 하면 잘 모른다. 그렇지만 한영키 전환 정도야 간단하리라는 희망을 품고 방법을 찾아보았다.&lt;/p&gt;
&lt;h2&gt;키 맵핑 적용하기&lt;/h2&gt;
&lt;p&gt;나의 긍정적인 예상대로(?) Hammerspoon의 &lt;a href=&quot;https://github.com/Hammerspoon/hammerspoon/wiki/Sample-Configurations&quot;&gt;GitHub wiki&lt;/a&gt;에서 내가 원하는 모듈을 찾을 수 있었다. 키를 리맵핑 할 때 쓸 수 있는 &lt;a href=&quot;https://github.com/hetima/hammerspoon-foundation_remapping&quot;&gt;foundation_remapping&lt;/a&gt; 모듈을 쓰기로 하고 &lt;code&gt;foundation_remapping.lua&lt;/code&gt; 파일을 내려 받았다.&lt;/p&gt;
&lt;p&gt;내려 받은 &lt;code&gt;foundation_remapping.lua&lt;/code&gt; 파일은 &lt;code&gt;~/.hammerspoon/&lt;/code&gt; 디렉토리에 넣어준다. 개별 파일을 모듈로 쓸 수 있는 모양이다. &lt;code&gt;init.lua&lt;/code&gt; 파일에 아래의 내용을 추가했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-lua&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; FRemap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foundation_remapping&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; remapper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FRemap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

remapper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ralt&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;f18&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
remapper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;내려받은 모듈을 불러온 후에 우측 알트키를 &lt;code&gt;f18&lt;/code&gt;에 맵핑 &lt;em&gt;한 것 같다.&lt;/em&gt; 이렇게 해서 저장을 하고 다시 메뉴 막대의 망치를 눌러서 &lt;code&gt;Reload Config&lt;/code&gt;을 실행한다. 이제 한영키가 잘 적용되었는지 해보면 &lt;em&gt;아무 일도 일어나지 않았습니다.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 960px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 47.35973597359736%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABCklEQVQoz62RO0+EQBSF+bV2djabWGj8LVtY+IjG3oYY3jMYsgjLAMPKIvjYITSwJEeYYrNmYyHxJF/mZib35twzCqUUlmVB0zQ4jgNVVeVJCIFpmtB1HbZty3q8NwxD1mNPmqbgnP9Aoa4Lxhii5RJBECBJYghR49GrwPIvaMQHWTBJvP5E/tEc4IUcbsCxKjdQyDOFaZlI4hhZtkLTNBg1f6pwfPmGi4d3nN1VOL+vcHJV4vS2wtG8OGB2U2J2nUMJw1CuNLorimKHEAJ/Vdu2UFicwvdfwIc89lXX9bSBejRkla2H7BJ02273ONkhjV5BvYX8wX1Xkx0KsUHXtej7/n9W/q1x6sBvBTGksQsw4/gAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;시스템 환경설정&quot;
        title=&quot;&quot;
        src=&quot;/static/setting-c4b5233dcb6af8cc3623d693cbabd0d3-2e2fd.png&quot;
        srcset=&quot;/static/setting-c4b5233dcb6af8cc3623d693cbabd0d3-b6d7a.png 240w,
/static/setting-c4b5233dcb6af8cc3623d693cbabd0d3-bf06b.png 480w,
/static/setting-c4b5233dcb6af8cc3623d693cbabd0d3-2e2fd.png 960w,
/static/setting-c4b5233dcb6af8cc3623d693cbabd0d3-ae210.png 1212w&quot;
        sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;시스템 단축키 설정을 바꿔주어야 한다. &lt;code&gt;시스템 환경설정 - 키보드 - 단축키 - 입력소스 - 입력메뉴에서 다음 소스 선택&lt;/code&gt;을 고르고, 앞에서 열심히 맵핑한 오른쪽 Alt키에 &lt;code&gt;넌 F18이고 난 주인이야&lt;/code&gt;를 외치면서 살며시 눌러본다. 그럼 아마 잘될 것이다. (부디…)&lt;/p&gt;
&lt;h2&gt;Hammerspoon Preference 창 자동으로 닫기&lt;/h2&gt;
&lt;p&gt;보통 맥 사용자라면 재부팅을 잘 하지 않지만 나에게는 &lt;em&gt;컴퓨터는 껐다 켜야 제 맛&lt;/em&gt; 같은 습관이 있어서 사용을 마치면 전원을 꺼버리는 편이다. 그런데 부팅 때 마다 Hammerspoon을 실행시키도록 &lt;code&gt;Launch Hammerspoon at login&lt;/code&gt;을 체크해 놓으면 매번 설정창이 등장해서 귀찮았다.&lt;/p&gt;
&lt;p&gt;그래서 이 창을 닫는 스크립트를 추가해버렸다. Hammerspoon이 제공하는 &lt;a href=&quot;http://www.hammerspoon.org/docs/hs.timer.html&quot;&gt;타이머 기능&lt;/a&gt;이 문서에 정리되어 있는데, 그 중 하나를 사용했다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 960px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 83.01158301158301%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAABYlAAAWJQFJUiTwAAABvUlEQVQ4y52UW07CQBRAecUYE40mRv0xxn8X4DL88UfjhvwxGpchK6hAgBDpg1IKpdIHbdAWaCm4g+udoYNEIQJtTm7nkTOPO51E4udJIqkNScbMnoybfXn4ULKc3tY50zAphVyBy7/maSwWilwOX/LNv/GzPpSOycmSfBfLqXnPsiyx7/dhEb7vw7I21i5J0j16tpnwCIX10WgEQRBQwjAE24toJJA60s4Igmk9K1cqlSf07CbiaZ6YpqmQBjKaKErQbDaBtyYgCALwPA98tQqlUomWNU0DrdUCx3FnwnK5/ExW+kc4z3g8RrkItZoMEkZBEOmAv/utLOS0L2jhTHVdh3a7TRkOh5sLHX8CiqLQJaoNlUZSnso1GAwGs31cSVg1IrqXREBiA2W0rBGhDk1VBc/zVhNGUQQ+dnZdF2zbhl6vh0lwwOk6dNnzGV4qJB1lmSRAool473SgHpdVnA2ZYRWzPd1THZR6HQzDWC/LZBB2NqffIXyGHliD7vpJYYd6Ef9l+RiF8qLjsCoofGR/Cvn1DpBL5Bq5XZMb5Aq5QHbYbbOFHCJnyPkGnCL7SHr+CkvFFZkNSLP78BufshzKERJGqwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Hammerspoon preference&quot;
        title=&quot;&quot;
        src=&quot;/static/preference-53e195c248a778484f2f3a5e516e0bab-2e2fd.png&quot;
        srcset=&quot;/static/preference-53e195c248a778484f2f3a5e516e0bab-b6d7a.png 240w,
/static/preference-53e195c248a778484f2f3a5e516e0bab-bf06b.png 480w,
/static/preference-53e195c248a778484f2f3a5e516e0bab-2e2fd.png 960w,
/static/preference-53e195c248a778484f2f3a5e516e0bab-04f3e.png 1036w&quot;
        sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;악의 근원, Launch Hammerspoon at login&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-lua&quot;&gt;&lt;code&gt;hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hammerspoon Preferences&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hammerspoon Preferences&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;재부팅 해보면 아마 잘 될 것이다. (부디…)&lt;/p&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;p&gt;완료된 나의 &lt;code&gt;init.lua&lt;/code&gt; 파일은 다음과 같다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-lua&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; FRemap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;foundation_remapping&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;local&lt;/span&gt; remapper &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; FRemap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

remapper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;remap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ralt&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;f18&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
remapper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitUntil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hammerspoon Preferences&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;false&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        hs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Hammerspoon Preferences&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;사실 이렇게 까지 할 필요가 있나, 습관을 고치면 편할 것을! 같은 생각이 들기도 하지만 1도 모르는 Lua를 (몇 줄 안되지만) 끄적거려본 나름 즐거운 시간이었다. &lt;del&gt;&lt;code&gt;end&lt;/code&gt;를 제대로 안써서 오류나고 그런 건 비밀이다.&lt;/del&gt; 모듈 불러올 때 &lt;code&gt;require&lt;/code&gt;라서 왠지 익숙한 느낌적인 느낌이 들기도 했고.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;그러나 애석하게도 이 후로는 아무 것도 자동화 하지 않았다는 슬픈 사연이…&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[react-navigation과 redux 통합하기]]></title><description><![CDATA[react-navigation 상태관리를 redux에 떠넘기는 과정을 살펴봅니다.]]></description><link>https://wanderer.work/articles/react-navigation과-redux-통합하기/</link><guid isPermaLink="false">https://wanderer.work/articles/react-navigation과-redux-통합하기/</guid><pubDate>Sun, 17 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;tl;dr&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;어떤 내비게이션이 좋은지는 아몰랑&lt;/li&gt;
&lt;li&gt;Expo: &lt;a href=&quot;http://docs.expo.io/&quot;&gt;http://docs.expo.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;react-navigation&lt;/code&gt; + &lt;code&gt;redux&lt;/code&gt;: &lt;a href=&quot;https://reactnavigation.org/docs/guides/redux&quot;&gt;https://reactnavigation.org/docs/guides/redux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jhen0409/react-native-debugger&quot;&gt;React Native Debugger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;이 글에 사용한 코드의 저장소: &lt;a href=&quot;https://github.com/hyunchulkwak/rn-practices&quot;&gt;https://github.com/hyunchulkwak/rn-practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Expo 링크: &lt;a href=&quot;https://expo.io/@hyunchulkwak/rn-practices&quot;&gt;https://expo.io/@hyunchulkwak/rn-practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;단도직입적으로…&lt;/h2&gt;
&lt;p&gt;대부분의 경우에 새로운 기술을 접하거나 소개할 때는 &lt;strong&gt;React Native 시작하기&lt;/strong&gt; 같은 제목의 글을 쓰는 것이 보통일 것이다&lt;del&gt;(선빵)&lt;/del&gt;. 그러나 React Native는 시작하는 것이 사실 좀 번거롭기도 하다. 게다가 시작하기 류의 글은 왠지 이어서 쓰기가 부담스러울 것 같다. 그래서 대신에 요즘 백수생활의 시간낭비 삼아 사소한 앱을 만들면서 겪은 내가 삽질한 결과를 조금 옮겨보기로 했다.&lt;/p&gt;
&lt;h2&gt;Expo&lt;/h2&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 775px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 49.16129032258065%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMBBf/EABYBAQEBAAAAAAAAAAAAAAAAAAABA//aAAwDAQACEAMQAAAB42wayiY//8QAGBAAAwEBAAAAAAAAAAAAAAAAAAECICL/2gAIAQEAAQUCSo6HNY//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAVEQEBAAAAAAAAAAAAAAAAAAAQIf/aAAgBAgEBPwGH/8QAGRAAAwADAAAAAAAAAAAAAAAAABExASBh/9oACAEBAAY/Ap0mIxrT/8QAGRABAQEBAQEAAAAAAAAAAAAAAREAMUEh/9oACAEBAAE/IRAT9I5zRB7eBzIi6KTV1dXf/9oADAMBAAIAAwAAABD03//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABcRAQADAAAAAAAAAAAAAAAAAAARIVH/2gAIAQIBAT8QjCn/xAAbEAEAAgMBAQAAAAAAAAAAAAABADEhUWFBEf/aAAgBAQABPxANKKyJdphFQ9B7PggFQBJ0dXOjq50cdn//2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;expo 종합선물셋트&quot;
        title=&quot;&quot;
        src=&quot;/static/expo-0a91a902dbd163f2666537874bbb9644-da9dc.jpg&quot;
        srcset=&quot;/static/expo-0a91a902dbd163f2666537874bbb9644-ac019.jpg 240w,
/static/expo-0a91a902dbd163f2666537874bbb9644-62752.jpg 480w,
/static/expo-0a91a902dbd163f2666537874bbb9644-da9dc.jpg 775w&quot;
        sizes=&quot;(max-width: 775px) 100vw, 775px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;Expo는 무엇인가? &lt;a href=&quot;https://expo.io/&quot;&gt;Expo&lt;/a&gt;는 꿈돌이가 춤추던 대전 엑스포가 아니다. 그게 93년이니까 어쩌면 이 글을 보는 분 중에 그 해에 태어난 분들도 있겠다&lt;del&gt;(흠좀무)&lt;/del&gt;. 처음 React-Native를 &lt;code&gt;react-native init&lt;/code&gt;으로 시작하는 것은 다소 자해행위 같은 느낌이 있다. 특히 안드로이드 환경설정하는 것은 매우 귀찮은데, 무언가 해야할 것이 많아서 내가 이러려고 React Native 시작했나 하는 자괴감이 들게 된다. Expo는 이런 귀찮은 작업을 무마해주는 도구로, 애플리케이션 코드만 짜면 Expo 클라이언트 앱을 통해서 바로 코딩 결과를 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;Expo XDE(&lt;a href=&quot;https://github.com/expo/xde/releases&quot;&gt;https://github.com/expo/xde/releases&lt;/a&gt;)를 설치하면 GUI로 프로젝트 생성과 빌드를 클릭 몇번으로 해결할 수 있다. 코딩 결과는 아이폰과 안드로이드용 &lt;a href=&quot;https://expo.io/tools#client&quot;&gt;Expo 클라이언트&lt;/a&gt;를 통해 확인할 수 있다. CLI 선호자를 위해 npm 패키지로 CLI도 제공한다. SDK가 제공하는 다양한 기능을 활용하면 네이티브 모듈과 연결하는 수고도 줄여준다. 이 정도면 종합선물셋트 수준이다. &lt;del&gt;꿈돌이 종합선물셋트!&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;사실 지금 작업 중인 나의 삽질 가득한 개인 프로젝트는 &lt;code&gt;react-native init&lt;/code&gt;으로 시작했다가, Expo로 해봤다가, 다시 &lt;code&gt;react-native init&lt;/code&gt;으로 돌아가긴 했다. 둘을 비교해보면 Expo로 만들면 빌드한 앱 용량이 좀 커지는 편이고, 네이티브 모듈을 연결하려면 결국 eject를 해야 하는 등의 아쉬움이 있다.&lt;/p&gt;
&lt;p&gt;그렇지만 처음 시작할 때 복잡한 설정을 거치지 않아도 되서 이 글을 쓰는 목적에는 잘 부합하기 때문에 여기서는 Expo를 사용한다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 960px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 65.86345381526104%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAYBBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHv2aWUibH/xAAXEAADAQAAAAAAAAAAAAAAAAAAAxQg/9oACAEBAAEFAq0liSxOP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABkQAAIDAQAAAAAAAAAAAAAAAAAxASChkf/aAAgBAQAGPwJ4OeDyn//EABgQAAIDAAAAAAAAAAAAAAAAAAEQIFFh/9oACAEBAAE/IRcQGmD/2gAMAwEAAgADAAAAELcf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8QiP/EABsQAAIBBQAAAAAAAAAAAAAAAAABQRARccHx/9oACAEBAAE/EEFHmdYO7tjbHFP/2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Expo XDE&quot;
        title=&quot;&quot;
        src=&quot;/static/expo-xde-ffad750f8074346720aa0a6534bdc90f-fa9d5.jpg&quot;
        srcset=&quot;/static/expo-xde-ffad750f8074346720aa0a6534bdc90f-30a96.jpg 240w,
/static/expo-xde-ffad750f8074346720aa0a6534bdc90f-288d4.jpg 480w,
/static/expo-xde-ffad750f8074346720aa0a6534bdc90f-fa9d5.jpg 960w,
/static/expo-xde-ffad750f8074346720aa0a6534bdc90f-def20.jpg 996w&quot;
        sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;XDE 최신버전을 내려받고 실행한다. 가입은 GitHub 계정으로 할 수 있다. XDE에서 Project - New Project를 누르고 디렉토리를 지정하면, 프로젝트 스캐폴딩을 부어주고, 의존 모듈도 설치하고, &lt;del&gt;북치고 장구치고 서장이랑 받도 먹고&lt;/del&gt; Expo 클라이언트에서 접속할 수 있는 URL도 알려준다. XDE를 설치하는게 내키지 않는다면 &lt;a href=&quot;https://github.com/react-community/create-react-native-app&quot;&gt;&lt;code&gt;create-react-native-app&lt;/code&gt;&lt;/a&gt;을 써보는 것도 좋다. 그렇지만 이 경우에도 결과물을 확인할 때는 Expo 클라이언트를 사용하게 된다. 이제 문제의 디렉토리를 에디터에서 열고 본론으로 넘어간다.&lt;/p&gt;
&lt;p&gt;초기 설정을 마치고 커밋한 결과는 &lt;a href=&quot;https://github.com/hyunchulkwak/rn-practices/tree/066a4c18d825862f2da94e47c63e07452428447e&quot;&gt;여기&lt;/a&gt;에서 확인할 수 있다.&lt;/p&gt;
&lt;h2&gt;내비게이션의 세계&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/react-community/react-navigation&quot;&gt;&lt;code&gt;react-navigation&lt;/code&gt;&lt;/a&gt;은 React Native 프로젝트에 흔히 사용하는 내비게이션 모듈 중 한가지이다. 이것 외에도 인기있는 패키지가 몇가지 더 있는데 그것이 알고싶다면 여러가지 패키지를 비교한 아래의 글들을 참고하면 좋을 것 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jsdev.kr/t/react-native-1-navigation/2617/3&quot;&gt;react-native의 지옥 1호 : navigation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@kyo504/react-navigation-%EC%93%B0%EC%8B%A4-%EA%B1%B4%EA%B0%80%EC%9A%94-8c7b0e8997f8&quot;&gt;React Navigation…쓰실 건가요?!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/handlebar-labs/navigating-navigation-in-react-native-26c7e4690f94&quot;&gt;Navigating Navigation in React Native&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;여기에 한가지 더 추가하자면 판단기준으로 쓰기는 적절하지 않지만, Facebook에 개설된 &lt;a href=&quot;https://www.facebook.com/groups/react.native.community&quot;&gt;React Native Community 그룹&lt;/a&gt;의 최근 인기도를 보면 &lt;code&gt;react-navigation&lt;/code&gt; 보다 &lt;a href=&quot;https://github.com/wix/react-native-navigation&quot;&gt;&lt;code&gt;react-native-navigation&lt;/code&gt;&lt;/a&gt;의 인기가 좀 더 올라간 것 같기는 하다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 498px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 77.30923694779116%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIBBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe1ajAf/xAAXEAADAQAAAAAAAAAAAAAAAAAAASEg/9oACAEBAAEFAlC5/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGRABAQADAQAAAAAAAAAAAAAAAAEhMUFx/9oACAEBAAE/IeEkTwrDav/aAAwDAQACAAMAAAAQAA//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAgIDAQAAAAAAAAAAAAABABEhMUFRYaH/2gAIAQEAAT8QGTFPLb9iwsC+TeFy8W9kK0dTef/Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;9월&quot;
        title=&quot;&quot;
        src=&quot;/static/poll1-8df3311947d8991feba749e1fb4f0e35-8ea14.jpg&quot;
        srcset=&quot;/static/poll1-8df3311947d8991feba749e1fb4f0e35-6f880.jpg 240w,
/static/poll1-8df3311947d8991feba749e1fb4f0e35-3282d.jpg 480w,
/static/poll1-8df3311947d8991feba749e1fb4f0e35-8ea14.jpg 498w&quot;
        sizes=&quot;(max-width: 498px) 100vw, 498px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  

  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 495px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 70.5050505050505%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAEDBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe1pKUH/xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAEFAl//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAZEAACAwEAAAAAAAAAAAAAAAABMQAQESH/2gAIAQEAAT8hAw4BFXHHX//aAAwDAQACAAMAAAAQk8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAbEAEAAwEAAwAAAAAAAAAAAAABABEhMRBRYf/aAAgBAQABPxC+VQvd+wH0d8D0EbrGCWNybP/Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;10월&quot;
        title=&quot;&quot;
        src=&quot;/static/poll2-792b761c8097079b87abf18e6967753a-14089.jpg&quot;
        srcset=&quot;/static/poll2-792b761c8097079b87abf18e6967753a-cbc74.jpg 240w,
/static/poll2-792b761c8097079b87abf18e6967753a-6915d.jpg 480w,
/static/poll2-792b761c8097079b87abf18e6967753a-14089.jpg 495w&quot;
        sizes=&quot;(max-width: 495px) 100vw, 495px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;h2&gt;react-navigation 적용하기&lt;/h2&gt;
&lt;p&gt;서론이 엄청 길었다. 일단 &lt;code&gt;react-navigation&lt;/code&gt;을 설치한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;yarn add react-navigation&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;일단 아무 것도 없는 황무지에 내비게이션을 붙여보자. &lt;code&gt;react-navigation&lt;/code&gt;은 내비게이션 구조에 따라 &lt;code&gt;StackNavigator&lt;/code&gt;, &lt;code&gt;TabNavigator&lt;/code&gt;, &lt;code&gt;DrawerNavigator&lt;/code&gt;를 제공한다. 예를 들어 첫화면, 소개, 도움말 같이 3개의 화면을 구현해야 한다면, 내비게이터와 각각의 화면을 정의해야 한다. 디렉토리 구조는 대략 이렇게 잡았다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;/navigator
  AppNavigator.js
  index.js
/screens
  Home.js
  About.js
  Help.js
  index.js
App.js&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;우선 내비게이터를 정의해본다. 내가 작업하는 앱에서는 &lt;code&gt;DrawerNavigator&lt;/code&gt;를 쓰고 있었는데, 이 글에서는 &lt;code&gt;TabNavigator&lt;/code&gt;를 써봐야겠다. &lt;a href=&quot;https://reactnavigation.org/docs/intro/quick-start#Creating-a-TabNavigator&quot;&gt;예제 코드&lt;/a&gt;를 참고해서 작성해보았다. TabNavigator API는 이렇다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;TabNavigator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RouteConfigs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; TabNavigatorConfig&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;code&gt;RouteConfigs&lt;/code&gt;에 각 라우팅별로 &lt;code&gt;navigationOptions&lt;/code&gt;를 줄 수 있는데, 여기에 레이블과 아이콘을 설정한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token comment&quot;&gt;// navigation/AppNavigator.js&lt;/span&gt;
Home&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  screen&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Home&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  navigationOptions&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    tabBarLabel&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Home&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    tabBarIcon&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; tintColor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; focused &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Ionicons
        name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;focused &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ios-home&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ios-home-outline&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        size&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        color&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;tintColor&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;위에서 &lt;code&gt;Ionicicons&lt;/code&gt;의 경우에는 &lt;a href=&quot;https://docs.expo.io/versions/latest/guides/icons.html&quot;&gt;Expo에서 제공해주는 &lt;code&gt;@expo/vector-icons&lt;/code&gt;&lt;/a&gt;를 사용한다. 전체 아이콘 목록(&lt;a href=&quot;https://expo.github.io/vector-icons/&quot;&gt;https://expo.github.io/vector-icons/&lt;/a&gt;)도 참고하면 좋겠다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;TabNavigatorConfig&lt;/code&gt;에는 다음과 같이 설정을 추가했다. 각 옵션에 대해서는 &lt;a href=&quot;https://reactnavigation.org/docs/navigators/tab&quot;&gt;문서&lt;/a&gt;에서 살펴볼 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  tabBarPosition&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;bottom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 탭을 하단으로 위치시킨다. ios는 하단, 안드로이드는 상단이 기본값이다.&lt;/span&gt;
  animationEnabled&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  tabBarOptions&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    inactiveTintColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#333&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    activeTintColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#400011&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    style&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#fff&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    labelStyle&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      fontSize&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    indicatorStyle&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      backgroundColor&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#400011&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    showIcon&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 안드로이드는 기본값이 false이므로, 통일을 위해 true로 설정한다.&lt;/span&gt;
    showLabel&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 300px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 177.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAkABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAEEAgMF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB6k2xUWwRIBrzAD//xAAZEAADAAMAAAAAAAAAAAAAAAAAAxQQMEH/2gAIAQEAAQUClSTJJk6u4//EABYRAQEBAAAAAAAAAAAAAAAAABEAIP/aAAgBAwEBPwFnP//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BX//EABgQAAMBAQAAAAAAAAAAAAAAAAABMzAy/9oACAEBAAY/AuETRNa//8QAGRABAQADAQAAAAAAAAAAAAAAAQAwMVFx/9oACAEBAAE/Ieje5BEaRq//2gAMAwEAAgADAAAAEEQSAIPP/8QAFxEAAwEAAAAAAAAAAAAAAAAAABFRIP/aAAgBAwEBPxBqNc//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EF//xAAdEAACAgIDAQAAAAAAAAAAAAAAAREhQXEwMYHw/9oACAEBAAE/EJYoFCtR4Gz7HxWHlpLsy2UQ/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;이럴 수가&quot;
        title=&quot;&quot;
        src=&quot;/static/screenshot1-bcd1fd964275227524990963ba75a421-66854.jpg&quot;
        srcset=&quot;/static/screenshot1-bcd1fd964275227524990963ba75a421-b50f3.jpg 240w,
/static/screenshot1-bcd1fd964275227524990963ba75a421-66854.jpg 300w&quot;
        sizes=&quot;(max-width: 300px) 100vw, 300px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;어서오세요, 안녕히 가세요(?)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 부분까지 마치고 커밋한 결과는 &lt;a href=&quot;https://github.com/hyunchulkwak/rn-practices/tree/6b9fdc99d659f2868062e65ca7a591b163964024&quot;&gt;여기&lt;/a&gt;에서 확인할 수 있다.&lt;/p&gt;
&lt;h2&gt;redux에 상태 떠넘기기&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;redux&lt;/code&gt;와 연결하는 방법은 &lt;a href=&quot;https://reactnavigation.org/docs/guides/redux&quot;&gt;문서&lt;/a&gt;에 잘 소개되어 있기는 하다. 저장소에서 &lt;a href=&quot;https://github.com/react-community/react-navigation/tree/master/examples/ReduxExample&quot;&gt;예제 코드&lt;/a&gt;도 찾아볼 수 있다. 보고 잘 흉내내 본다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://thumbs.gfycat.com/TautHandsomeGreatwhiteshark-size_restricted.gif&quot; alt=&quot;할 수 있어요&quot;&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;redux 스토어와 루트 리듀서를 만든다.&lt;/li&gt;
&lt;li&gt;내비게이션 리듀서를 만든다.&lt;/li&gt;
&lt;li&gt;App.js에서 렌더링했던 &lt;code&gt;AppNavigator&lt;/code&gt;에 &lt;code&gt;navigator&lt;/code&gt; 속성으로 &lt;code&gt;addNavigationHelpers({ dispatch, state })&lt;/code&gt;을 넘겨준다.&lt;/li&gt;
&lt;li&gt;3을 위해서는 AppNavigator를 렌더링하는 부모 컴포넌트를 redux에 연결해주어야 한다.&lt;/li&gt;
&lt;li&gt;4에서 만든 redux에 연결한 컨테이너 컴포넌트를 &lt;code&gt;Provider&lt;/code&gt;에게 &lt;em&gt;순순히&lt;/em&gt; 넘겨준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1번은 스킵하고 2번을 잠시보자. 이렇게 생겼다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; AppNavigator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./AppNavigator&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 아까 걔임..&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; initialState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; AppNavigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStateForAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  AppNavigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getActionForPathAndParams&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Home&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 액션을 반환한다: {type: &apos;Navigation/NAVIGATE&apos;, &apos;routeName&apos;: &apos;Home&apos;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;navigatorReducer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; initialState&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nextState &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; AppNavigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;router&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStateForAction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; nextState &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; navigatorReducer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://reactnavigation.org/docs/routers/api&quot;&gt;Custom Router API&lt;/a&gt;가 사용되어 혼란스러워 보이지만, 초기 상태를 설정하고 라우팅 액션이 들어올 때 마다 새로운 상태를 반환하는 리듀서일 뿐이다. 조금 있다가 이 광경을 Redux 개발자도구로 보면 마음에 평화가 찾아오니 일단 지나가자.&lt;/p&gt;
&lt;p&gt;공식문서의 예제에서는 &lt;code&gt;App&lt;/code&gt; 컴포넌트를 redux에 연결하고, &lt;code&gt;AppNavigator&lt;/code&gt;의 &lt;code&gt;navigator&lt;/code&gt; 속성을 추가해준다. 이후에 &lt;code&gt;Root&lt;/code&gt; 컴포넌트를 새로 만들어서 &lt;code&gt;App&lt;/code&gt; 컴포넌트를 렌더링한다. 나 같은 경우에는 &lt;code&gt;App&lt;/code&gt; 위에 &lt;code&gt;Root&lt;/code&gt;를 두는 대신 &lt;code&gt;NavigatorRoot&lt;/code&gt;를 만들었다. 별 차이는 없다.
그리고 Expo는 최상위 컴포넌트를 기본적으로 App.js에 선언하는데, 이걸 변경하려면 &lt;code&gt;app.json&lt;/code&gt;에서 &lt;code&gt;entryPoint&lt;/code&gt;를 설정하고, 최상위 컴포넌트를 설정하는 파일도 생성해주어야 하니 &lt;code&gt;Root&lt;/code&gt;를 쓰려면 번거롭다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;AppNavigatorWithNavigationState&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; dispatch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; navigator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;AppNavigator
    navigation&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addNavigationHelpers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      dispatch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      state&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;mapStateToProps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; navigator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; navigator &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; NavigatorRoot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mapStateToProps&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;AppNavigatorWithNavigationState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NavigatorRoot &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 300px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 177.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAkABQDASIAAhEBAxEB/8QAGQABAAIDAAAAAAAAAAAAAAAAAAEEAgMF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAB6k2xUWwRIBrzAD//xAAZEAADAAMAAAAAAAAAAAAAAAAAAxQQMEH/2gAIAQEAAQUClSTJJk6u4//EABYRAQEBAAAAAAAAAAAAAAAAABEAIP/aAAgBAwEBPwFnP//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BX//EABgQAAMBAQAAAAAAAAAAAAAAAAABMzAy/9oACAEBAAY/AuETRNa//8QAGRABAQADAQAAAAAAAAAAAAAAAQAwMVFx/9oACAEBAAE/Ieje5BEaRq//2gAMAwEAAgADAAAAEEQSAIPP/8QAFxEAAwEAAAAAAAAAAAAAAAAAABFRIP/aAAgBAwEBPxBqNc//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EF//xAAdEAACAgIDAQAAAAAAAAAAAAAAAREhQXEwMYHw/9oACAEBAAE/EJYoFCtR4Gz7HxWHlpLsy2UQ/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;이럴 수가&quot;
        title=&quot;&quot;
        src=&quot;/static/screenshot1-bcd1fd964275227524990963ba75a421-66854.jpg&quot;
        srcset=&quot;/static/screenshot1-bcd1fd964275227524990963ba75a421-b50f3.jpg 240w,
/static/screenshot1-bcd1fd964275227524990963ba75a421-66854.jpg 300w&quot;
        sizes=&quot;(max-width: 300px) 100vw, 300px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;늘 한결같은 모습에 반해버림&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지금 막 뭔가 대단한 일을 벌인 것 같은데 애석하게도 화면 상의 변화는 없다. 이거 그럼 뭐하러 함!? 이제 준공식을 마쳤으니 삼천포 톨게이트로 차를 보내야겠다. 여기까지 작성하고 커밋한 결과는 &lt;a href=&quot;https://github.com/hyunchulkwak/rn-practices/tree/af04a3741e6108d3a4c8ded0147c53f5b8eef259&quot;&gt;여기&lt;/a&gt;에 있다.&lt;/p&gt;
&lt;h2&gt;React Native Debugger 연결하기&lt;/h2&gt;
&lt;p&gt;redux 개발자도구에서 제대로 redux와 연결되었는지 작동해보고 싶다. &lt;a href=&quot;https://github.com/jhen0409/react-native-debugger&quot;&gt;React Native Debugger&lt;/a&gt;라는 신통방통한 도구가 있어서 써보려고 한다. Electron으로 만들어진 프로그램이라 먼저 &lt;a href=&quot;https://github.com/jhen0409/react-native-debugger/releases&quot;&gt;릴리스 페이지&lt;/a&gt;에 가서 내려받는다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;react-native-debugger-open&lt;/code&gt;를 devDependencies에 추가하고 package.json의 scripts에 아래와 같이 명령을 추가한다. XDE에서 실행하면 React Native Debugger가 잘 작동하지 않아서 cli로 돌아갔다. &lt;del&gt;(이제 와서!?)&lt;/del&gt; React Native Debugger의 가이드를 보면 &lt;code&gt;postinstall&lt;/code&gt;을 사용하게 되어있는데, 제대로 안 찾아봤지만 아마도 메트로 번들러에서 이 명령을 실행하기 때문인 모양인데, Expo는 이 명령을 실행하지 않으니 그냥 &lt;code&gt;start&lt;/code&gt; 명령을 추가하기로 했다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;yarn add --dev react-native-debugger-open exp&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;// package.json
&quot;scripts&quot;: {
  &quot;start&quot;: &quot;yarn run rndebugger &amp;&amp; exp start&quot;,
  &quot;rndebugger&quot;: &quot;rndebugger-open --revert &amp;&amp; rndebugger-open --open --expo&quot;
},&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;code&gt;--expo&lt;/code&gt; 옵션을 주는 이유는 Expo의 경우 원격 디버깅에 19001 포트를 사용하기 때문이다.&lt;/p&gt;
&lt;p&gt;redux 개발자도구에 연결할 수 있도록 store도 약간 수정해야 한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; createStore &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;redux&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; reducer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./reducer&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; store &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createStore&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  reducer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;__REDUX_DEVTOOLS_EXTENSION__ &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;__REDUX_DEVTOOLS_EXTENSION__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; store &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;위와 같이 설정하고 이렇게 실행해본다. 뒤에 &lt;code&gt;--lan&lt;/code&gt; 옵션은 Expo cli 옵션인데, 로컬 ip로 QR코드를 생성해준다. Expo가 제공하는 터널을 통해서 원격 디버깅을 너무나 느리기 때문에 이렇게 하는 편이 낫다. 다만 PC와 테스트 기기가 같은 무선망에 연결되어 있어야 한다. &lt;code&gt;--lan&lt;/code&gt;을 따로 붙이는 이유는 시뮬레이터로 실행한다거나 하는 &lt;a href=&quot;https://docs.expo.io/versions/latest/guides/exp-cli.html&quot;&gt;다른 cli 명령&lt;/a&gt;들도 편의대로 추가할 수 있기 때문이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;$ yarn start --lan&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;위의 명령을 실행하면 맥에서는 React Native Debugger를 잘 설치했으면 자동으로 실행도 된다. 윈도우는 실행까지는 되지 않으니, 미리 실행해놓아야 한다. 결과를 보자 헤헤.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://media.giphy.com/media/3o6fJ6pIggZWMagOti/giphy.gif&quot; alt=&quot;React Native Debugger&quot;&gt;&lt;/p&gt;
&lt;p&gt;참고로 위 화면에서 안드로이드는 실제 기기를 연결했다. 삼성 스마트폰의 경우 &lt;a href=&quot;http://www.samsung.com/sec/support/sidesync/&quot;&gt;SideSync&lt;/a&gt;라는 프로그램을 쓸 수 있다.&lt;/p&gt;
&lt;p&gt;여기까지 마치고 커밋한 결과는 &lt;a href=&quot;https://github.com/hyunchulkwak/rn-practices/tree/8abf5eed559d3dc0bc100d5a55a2d19fab027cbd&quot;&gt;여기&lt;/a&gt;에서 확인할 수 있다.&lt;/p&gt;
&lt;h2&gt;내비게이션 액션 처리&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://reactnavigation.org/docs/navigators/navigation-prop#navigate-Link-to-other-screens&quot;&gt;&lt;code&gt;NavigationActions.navigate()&lt;/code&gt;&lt;/a&gt;를 디스패치해주면, redux를 통해서 내비게이션을 변경할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-js&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; NavigationActions &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react-navigation&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NavigationActions&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; routeName&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Home&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;code&gt;params&lt;/code&gt;의 관리는 물음표인데, 적절한 가이드를 찾지는 못했다. &lt;code&gt;redux&lt;/code&gt;를 사용하지 않을 때는 각 스크린에서 &lt;code&gt;this.props.navigation.state.params&lt;/code&gt;까지 산넘고 물건너 찾아가야 하는 불편함이 있다. 디스패치한 &lt;code&gt;params&lt;/code&gt; 값을 내비게이션 리듀서의 action에서 받을 수도 있기 때문에, 타입이 &lt;code&gt;&apos;Navigation/NAVIGATE&apos;&lt;/code&gt;인 액션을 기준으로 적절히 관리해보고 있다. 이 글을 보시는 분 중에 좋은 방법을 알고 계시는 분이 있다면 댓글 좀 부탁드립니다. (굽신굽신…)&lt;/p&gt;
&lt;p&gt;그나저나 가벼운 마음으로 글을 쓰려고 시작했는데 생각보다 많은 것(?)을 쓰고 말았다. 오늘은 이쯤에서 얼렁뚱땅 마무리를 짓겠다. &lt;em&gt;다음 이 시간까지 안녕~&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Windows에서 프론트엔드 개발환경 설정하기]]></title><description><![CDATA[cmder로 시작해서 Chocolatey를 이용해서 편리하게 개발환경을 구성해봅니다. 이 글은 맥에서 작성되었습니다. (뻥)]]></description><link>https://wanderer.work/articles/windows에서-프론트엔드-개발환경-설정하기/</link><guid isPermaLink="false">https://wanderer.work/articles/windows에서-프론트엔드-개발환경-설정하기/</guid><pubDate>Wed, 06 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;왜 윈도우인가?&lt;/h2&gt;
&lt;p&gt;단도직입적으로, 개발을 위해 어떤 운영체제가 더 나은가는 이 글의 관심사가 아니다. 단지 일하다보면 윈도우에서도 개발환경을 설정해야 하고 그 과정의 고통을 경감시키는 정도를 목표로 하고 있다. 내 입장에서는 맥이나 윈도우나 안되는 시점이 다를 뿐 안될 때는 둘 다 나에게 엿을 준다. 단 거 먹고 힘내라고.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 456px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 73.02631578947368%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAACA//aAAwDAQACEAMQAAAB1F3FwchpYf/EABoQAAICAwAAAAAAAAAAAAAAAAECABIDESH/2gAIAQEAAQUCYmwaY91YQL2f/8QAFhEAAwAAAAAAAAAAAAAAAAAAARAR/9oACAEDAQE/AaF//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/AUdn/8QAGBAAAgMAAAAAAAAAAAAAAAAAADEBICH/2gAIAQEABj8CY5Np/8QAGRABAAMBAQAAAAAAAAAAAAAAAQARITGB/9oACAEBAAE/IR0VF3y2NXdssGjWOagBwqf/2gAMAwEAAgADAAAAEH8//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERMf/aAAgBAwEBPxBQHp//xAAWEQEBAQAAAAAAAAAAAAAAAAABEQD/2gAIAQIBAT8QDA4ITf/EABsQAQADAAMBAAAAAAAAAAAAAAEAESExQVHB/9oACAEBAAE/EHbQXh51xA3QVKQCSq618grHuSrYErjrtjAaAeBU/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;울릉도 특산물, 호박엿&quot;
        title=&quot;&quot;
        src=&quot;/static/dut-63014af1c8905773040b933aea58743e-b6aff.jpg&quot;
        srcset=&quot;/static/dut-63014af1c8905773040b933aea58743e-4d9cd.jpg 240w,
/static/dut-63014af1c8905773040b933aea58743e-b6aff.jpg 456w&quot;
        sizes=&quot;(max-width: 456px) 100vw, 456px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://products.ulleung.go.kr/page.htm?mnu_siteid=products&amp;#x26;mnu_uid=115&amp;#x26;tcg_uid=135&quot;&gt;울릉도 특산물, 호박엿&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;엿도 많이 먹으면 지겹기 때문에 충치예방을 위해 적당히 먹어야 한다. 엿 대신 먹을 수 있는 먹거리를 살펴보자. &lt;del&gt;뭐야, 생생정보통이야?&lt;/del&gt;&lt;/p&gt;
&lt;h2&gt;cmder: 윈도우용 콘솔 에뮬레이터&lt;/h2&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 706px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 67.56373937677054%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBP/EABUBAQEAAAAAAAAAAAAAAAAAAAEA/9oADAMBAAIQAxAAAAHBUoNIif/EABoQAAIDAQEAAAAAAAAAAAAAAAABAhESEwP/2gAIAQEAAQUC0dSPpawzmyEHX//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAAMBAAAAAAAAAAAAAAAAAAAQMUH/2gAIAQEABj8ChCLF/8QAHBAAAgICAwAAAAAAAAAAAAAAAAExUREhQWHh/9oACAEBAAE/IdfRlUZBGyjvC3GT/9oADAMBAAIAAwAAABA8H//EABYRAAMAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxCBf//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EKr/xAAbEAEAAgMBAQAAAAAAAAAAAAABABExgdFRYf/aAAgBAQABPxAGN4C7R00U1mYjdWCdHkXC7nw+T//Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;cmder&quot;
        title=&quot;&quot;
        src=&quot;/static/cmder-site-a8a2a5f3b9ffebbf083d1106aaabdb42-5c192.jpg&quot;
        srcset=&quot;/static/cmder-site-a8a2a5f3b9ffebbf083d1106aaabdb42-d5ba2.jpg 240w,
/static/cmder-site-a8a2a5f3b9ffebbf083d1106aaabdb42-80702.jpg 480w,
/static/cmder-site-a8a2a5f3b9ffebbf083d1106aaabdb42-5c192.jpg 706w&quot;
        sizes=&quot;(max-width: 706px) 100vw, 706px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;처음 윈도우용 git-bash의 답답함에 &lt;a href=&quot;https://conemu.github.io/&quot;&gt;Conemu&lt;/a&gt;를 접하고 투박함에 별짓을 다해보았지만 내 능력으로는 별 소용이 없었다. &lt;a href=&quot;http://cmder.net/&quot;&gt;cmder&lt;/a&gt;는 Conemu를 잘 지지고 볶아 먹음직스러운 요리로 만들어놓았다.&lt;/p&gt;
&lt;p&gt;홈페이지(&lt;a href=&quot;http://cmder.net/&quot;&gt;http://cmder.net/&lt;/a&gt;)에서 다운로드 받을 수 있으며, 풀버전은 Git이 포함되어 있는데, 그 아래에 작은 글씨로 된 &lt;a href=&quot;https://github.com/cmderdev/cmder/releases/download/v1.3.4/cmder.7z&quot;&gt;7z 압축 파일(52mb)&lt;/a&gt;을 내려받는 것을 추천한다. 압축을 해제하고 Cmder.exe를 실행하면 초록빛깔 람다가 명령을 기다린다. Git 설치 마저도 귀찮은 나에게 딱 좋아.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 960px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAQFAv/EABQBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAV2E9rYIwH//xAAZEAADAQEBAAAAAAAAAAAAAAABAgMRADP/2gAIAQEAAQUCO06dsWbiiuSrN4ocH//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAEDAQE/Aaf/xAAXEQEAAwAAAAAAAAAAAAAAAAABAhAR/9oACAECAQE/AWOFf//EABkQAAMBAQEAAAAAAAAAAAAAAAABEQIQMf/aAAgBAQAGPwK3Xos6btKhpGXz/8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBUXH/2gAIAQEAAT8huWJxjhF6Wl8n2az82YkF+QGLVbjLSmz/2gAMAwEAAgADAAAAEFAP/8QAFREBAQAAAAAAAAAAAAAAAAAAMRD/2gAIAQMBAT8QRP/EABcRAAMBAAAAAAAAAAAAAAAAAAEQETH/2gAIAQIBAT8QiG6v/8QAGxABAQADAQEBAAAAAAAAAAAAAREAIUGBYdH/2gAIAQEAAT8Q3uI0QIq+ZVuMSgHF6YBSBqI3FFBUIe/cFAvrrJ+4UGbQZwz/2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;딱 좋아&quot;
        title=&quot;&quot;
        src=&quot;/static/good-632d9787f206953295cfd422ae24ed02-fa9d5.jpg&quot;
        srcset=&quot;/static/good-632d9787f206953295cfd422ae24ed02-30a96.jpg 240w,
/static/good-632d9787f206953295cfd422ae24ed02-288d4.jpg 480w,
/static/good-632d9787f206953295cfd422ae24ed02-fa9d5.jpg 960w,
/static/good-632d9787f206953295cfd422ae24ed02-3a06f.jpg 1280w&quot;
        sizes=&quot;(max-width: 960px) 100vw, 960px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;del&gt;먹으면 잘 싸야 탈이 없다.&lt;/del&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;심화코스: LF 강제하기&lt;/h3&gt;
&lt;p&gt;혼자 일하는 환경이 아니면 맥 사용자와 윈도우 사용자가 만나 CRLF와 LF의 화개장터가 자주 벌어진다. 이걸 막기 위해 나는 이런 방법들을 쓰고 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;git 설정&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global core.eol lf
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; config --global core.autocrlf input
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;프로젝트의 &lt;code&gt;.gitattributes&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;* text=auto&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;프로젝트의 &lt;code&gt;.editorconfig&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;[*]
end_of_line = lf&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1, 2번의 경우 &lt;a href=&quot;https://stackoverflow.com/questions/9976986/force-lf-eol-in-git-repo-and-working-copy&quot;&gt;스택오버플로우 답변&lt;/a&gt;을 참고했고, 3번의 경우 IDE에서 &lt;a href=&quot;http://editorconfig.org/&quot;&gt;EditorConfig&lt;/a&gt;을 사용하는 경우에만 적용된다.&lt;/p&gt;
&lt;h3&gt;심화코스: cmder를 위한 Snazzy&lt;/h3&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 797px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 54.8306148055207%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAALABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHn53FgH//EABUQAQEAAAAAAAAAAAAAAAAAABAB/9oACAEBAAEFAmv/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAADAQEAAAAAAAAAAAAAAAABEBEhMf/aAAgBAQABPyEjK+o//9oADAMBAAIAAwAAABBwP//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/ECf/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAZEAEAAwEBAAAAAAAAAAAAAAABABAxIXH/2gAIAQEAAT8QB0X2O1yxgx2v/9k=&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;cmder-snazzy&quot;
        title=&quot;&quot;
        src=&quot;/static/cmder-snazzy-b1ccbc38fd8fb6fad3e9ba80f7ea4ac6-e375c.jpg&quot;
        srcset=&quot;/static/cmder-snazzy-b1ccbc38fd8fb6fad3e9ba80f7ea4ac6-54608.jpg 240w,
/static/cmder-snazzy-b1ccbc38fd8fb6fad3e9ba80f7ea4ac6-53b88.jpg 480w,
/static/cmder-snazzy-b1ccbc38fd8fb6fad3e9ba80f7ea4ac6-e375c.jpg 797w&quot;
        sizes=&quot;(max-width: 797px) 100vw, 797px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;기본적으로 지원하는 색상도 충분하긴 한데, 나 같은 경우에는 맥에서 iterm, zsh, &lt;a href=&quot;https://github.com/sindresorhus/pure&quot;&gt;pure-prompt&lt;/a&gt;, &lt;a href=&quot;https://github.com/sindresorhus/iterm2-snazzy&quot;&gt;snazzy&lt;/a&gt;를 적용해서 쓰다보니 묘하게 아쉬운 느낌이 들어서 찾아보니 &lt;a href=&quot;https://gist.github.com/mickdekkers/f493f1c623d19af2fbde27ff9d458083&quot;&gt;Conemu용 snazzy 설정&lt;/a&gt;도 있었다. 앞에서 압축을 해제한 cmder 폴더에서 &lt;code&gt;vendor/conemu-maximus5/ConEmu.xml&lt;/code&gt; 파일을 열고, &lt;a href=&quot;https://gist.github.com/mickdekkers/f493f1c623d19af2fbde27ff9d458083&quot;&gt;gist의 xml 내용&lt;/a&gt;에서 &lt;code&gt;name=&quot;Palette1&quot;&lt;/code&gt;을 &lt;code&gt;name=&quot;Palette2&quot;&lt;/code&gt;로 바꿔서 아래처럼 추가했다. 참고로 폰트는 &lt;a href=&quot;https://github.com/mozilla/Fira&quot;&gt;Fira Mono&lt;/a&gt;를 쓰고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-xml&quot;&gt;&lt;code&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Colors&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2017-11-06 20:26:04&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;161206&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Palette1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2017-11-06 20:26:04&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;161206&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;value&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Monokai&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    ...
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;key&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Palette2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2017-11-06 20:26:04&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;161206&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;value&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;string&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Snazzy&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
    ...
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;value&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Count&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;long&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;위 내용을 추가한 후 설정(단축키 Win+Alt+P)에서 Features - Colors를 선택해서 Snazzy로 변경한다. 폰트는 Main에서 변경할 수 있다.&lt;/p&gt;
&lt;h2&gt;Chocolatey&lt;/h2&gt;
&lt;p&gt;그러나 아직 윈도우는 배가 고프다. 설치할 게 많다. node, npm을 필두로 yarn이라던가 즐겨쓰는 에디터도 설치해야 한다. 일하는 백엔드 환경에 따라 추가해야 할 설정도 많다. &lt;del&gt;그렇게 하나씩 설치하다가 집에는 언제 갈 것인가?&lt;/del&gt; 출출한 윈도우에게 초콜렛을 먹이자. 윈도우는 출출할 때 윈도우가 아니야.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chocolatey.org/&quot;&gt;Chocolatey&lt;/a&gt;는 윈도우용 패키지 매니저이다. 맥으로 치면 Homebrew 같은 역할을 한다. &lt;a href=&quot;https://chocolatey.org/install&quot;&gt;설치 안내 페이지&lt;/a&gt;에 가면 윈도우 명령창 또는 파워쉘에서 설치하는 법이 안내되어 있다. 명령창을 관리자 권한으로 실행한 후에 설치 명령을 실행한다.&lt;/p&gt;
&lt;p&gt;이후에 필요한 프로그램 설치는 간단하다. &lt;code&gt;choco install 먹거리&lt;/code&gt;이다. 가령 nodejs를 설치한다면 &lt;code&gt;choco install nodejs&lt;/code&gt;를 실행한다. npm이랑 비슷하게 여러 개를 적어서 설치할 수도 있다. 환경변수 설정 등도 알아서 해주기 때문에 설치를 기다리며 딴짓을 하면 좋다.&lt;/p&gt;
&lt;p&gt;IDE도 설치할 수 있다. 인텔리제이 계열의 IDE도 설치할 수 있는데, 시리얼 번호는 셀프다. 설치할 수 있는 &lt;a href=&quot;https://chocolatey.org/packages&quot;&gt;패키지도 검색&lt;/a&gt;해볼 수 있다. JDK도 있고 Python, Ruby 등 생각할 수 있는 건 왠만큼 다 있다고 보면 되겠다. &lt;del&gt;비밀을 하나 밝히자면 cmder도 있다.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;다양한 명령어는 &lt;code&gt;choco -h&lt;/code&gt;로 도움말을 살펴보자. 설치(install), 삭제(uninstall), 업그레이드(upgrade), 목록(list)은 예측 가능한 단어로 되어있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;λ choco -h
This is a listing of all of the different things you can pass to choco.

Commands

 * list - lists remote or local packages
 * search - searches remote or local packages (alias for list)
 * info - retrieves package information. Shorthand for choco search pkgname --exact --verbose
 * install - installs packages from various sources
 * pin - suppress upgrades for a package
 * outdated - retrieves packages that are outdated. Similar to upgrade all --noop
 * upgrade - upgrades packages from various sources
 * uninstall - uninstalls a package
 * pack - packages up a nuspec to a compiled nupkg
 * push - pushes a compiled nupkg
 * new - generates files necessary for a chocolatey package from a template
 * source - view and configure default sources
 * sources - view and configure default sources (alias for source)
 * config - Retrieve and configure config file settings
 * feature - view and configure choco features
 * features - view and configure choco features (alias for feature)
 * apikey - retrieves or saves an apikey for a particular source
 * setapikey - retrieves or saves an apikey for a particular source (alias for apikey)
 * unpackself - have chocolatey set itself up
 * version - [DEPRECATED] will be removed in v1 - use `choco outdated` or `cup &lt;pkg|all&gt; -whatif` instead
 * update - [DEPRECATED] RESERVED for future use (you are looking for upgrade, these are not the droids you are looking for)&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;h2&gt;NPM 패키지를 위한 &lt;code&gt;windows-build-tools&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nodejs/node-gyp&quot;&gt;node-gyp&lt;/a&gt;을 사용하는 패키지들은 간혹 윈도우에서 빌드를 시도하다가 피보다 붉은 오류를 뿜어내며 퇴근을 방해하곤 한다. 그런 사고를 미연에 방지할 수 있는 것이 바로 &lt;a href=&quot;https://www.npmjs.com/package/windows-build-tools&quot;&gt;&lt;code&gt;windows-build-tools&lt;/code&gt;&lt;/a&gt;이다. 수동으로 이러저러하게 설치하는 법도 있지만, 게으른 나에게 그럴 시간이 있을리가 없다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 778px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 50.128534704370175%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe3uCqP/xAAWEAEBAQAAAAAAAAAAAAAAAAAQAUH/2gAIAQEAAQUCjp//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAEBAQEBAAAAAAAAAAAAAAABABEQIf/aAAgBAQABPyHSamReT1//2gAMAwEAAgADAAAAEIMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhABAAMAAwAAAAAAAAAAAAAAAQARQSFRof/aAAgBAQABPxB1AnoYHYAzyAVZkos4hP/Z&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;나의 윈도우가 행복하지 않아&quot;
        title=&quot;&quot;
        src=&quot;/static/nodegyp-0a198269cdb129f89d828dee243c0ec3-7ad57.jpg&quot;
        srcset=&quot;/static/nodegyp-0a198269cdb129f89d828dee243c0ec3-2fea9.jpg 240w,
/static/nodegyp-0a198269cdb129f89d828dee243c0ec3-d4556.jpg 480w,
/static/nodegyp-0a198269cdb129f89d828dee243c0ec3-7ad57.jpg 778w&quot;
        sizes=&quot;(max-width: 778px) 100vw, 778px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nodejs/node-gyp/issues/629&quot;&gt;행복을 찾아서…&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-none&quot;&gt;&lt;code&gt;λ yarn global add windows-build-tools&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;이 패키지가 설치하는 내용물은 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual C++ Compilers (targeting x86, X64 and ARM)&lt;/li&gt;
&lt;li&gt;Visual C++ headers &amp;#x26; libraries (CRT &amp;#x26; STL)&lt;/li&gt;
&lt;li&gt;Visual C++ build scripts (targeting Windows desktop)&lt;/li&gt;
&lt;li&gt;Microsoft Build Tools 2015 (MSBuild)&lt;/li&gt;
&lt;li&gt;Windows SDK 8.1 (optional, on by default)&lt;/li&gt;
&lt;li&gt;Windows SDK 10 (optional, off by default)&lt;/li&gt;
&lt;li&gt;ATL and MFC (optional, off by default)&lt;/li&gt;
&lt;li&gt;C++ Build tools specific command prompts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그리고 여기에 Python 2.7도 추가로 설치하지만 환경변수로 붙지는 않는다. 이 패키지가 설치한 Python은 탐색기를 열고 &lt;code&gt;%USERPROFILE%\.windows-build-tools&lt;/code&gt;로 이동하면 확인할 수 있다.&lt;/p&gt;
&lt;h2&gt;로컬 서버&lt;/h2&gt;
&lt;p&gt;프로젝트 환경에 &lt;code&gt;webpack-dev-server&lt;/code&gt;나 &lt;code&gt;browsersync&lt;/code&gt; 같은 개발 서버를 잘 설정해 늫으면 그럴 일이 잘 없지만, 가끔은 HTML 정도를 열어보기 위한 로컬 서버가 필요할 때가 있다.  &lt;a href=&quot;https://github.com/johnpapa/lite-server&quot;&gt;&lt;code&gt;lite-server&lt;/code&gt;&lt;/a&gt; 같은 모듈을 쓰는 방법도 있긴한데, 쓰다보면 늘 쓰는 디렉토리만 쓰기 때문에 콘솔로 이동하기가 왠지 귀찮다. 그래서 &lt;a href=&quot;http://fenixwebserver.com/&quot;&gt;Fenix web server&lt;/a&gt;를 쓰곤 한다. 일렉트론으로 만든 노드 서버라고 보면 되겠다. 외부로 공유도 가능해서, 접속 URL도 제공해준다.&lt;/p&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 402px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 80.8457711442786%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAQABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAUBAgP/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAAByqrgaioT/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAMUAiD/2gAIAQEAAQUCt2XNLmcf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAGBAAAwEBAAAAAAAAAAAAAAAAAEKRIEH/2gAIAQEABj8C5BYLMf/EABcQAQEBAQAAAAAAAAAAAAAAAAERIEH/2gAIAQEAAT8hSkU91jP/2gAMAwEAAgADAAAAENPf/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QR//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EAB4QAAEDBAMAAAAAAAAAAAAAAAEAESEQMWHwQVFx/9oACAEBAAE/EHSwHgDHoTKxFrKHKNfUb1//2Q==&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Fenix web server&quot;
        title=&quot;&quot;
        src=&quot;/static/fenix-5cef99f6c815aec72b6f882d9026295f-6b4be.jpg&quot;
        srcset=&quot;/static/fenix-5cef99f6c815aec72b6f882d9026295f-982eb.jpg 240w,
/static/fenix-5cef99f6c815aec72b6f882d9026295f-6b4be.jpg 402w&quot;
        sizes=&quot;(max-width: 402px) 100vw, 402px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;먼저 Web Server - New를 선택해서 이름, 디렉토리, 포트를 지정한다. 목록에 커서를 올리면 우측에 나오는 버튼으로 조작한다. 가장 우측에 녹색이 나오면 실행, 붉은 색이면 종료이다.&lt;/p&gt;
&lt;h2&gt;집사가 필요하다면…&lt;/h2&gt;
&lt;p&gt;맥에서 쓰는 알프레드 같은 걸 원하는 분들이 혹시 있을지 모르겠다. 윈도우 10 같은 경우에는 Win+S를 누르면 바로 검색창을 띄울 수 있기 때문에 이 기능을 자주 쓴다. 만족이 안되는 분이 있다면 또 다른 일렉트론 앱인 &lt;a href=&quot;https://github.com/hainproject/hain&quot;&gt;hain&lt;/a&gt;을 추천해본다.&lt;/p&gt;
&lt;h2&gt;새로운 시작&lt;/h2&gt;
&lt;p&gt;열심히 설치했는데 무언가 잘 안된다면 재부팅 해보자. 그래, 새로운 시작이다. 그래도 안되면 여기 &lt;a href=&quot;https://www.apple.com/kr/macbook-pro/&quot;&gt;손 끝에 닿는 미래&lt;/a&gt;가 있다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Gatsby로 블로그 시작하기]]></title><description><![CDATA[Gatsby로 블로그를 후다닥 시작한 이야기를 떠들어봅니다.]]></description><link>https://wanderer.work/articles/gatsby로-블로그-시작하기/</link><guid isPermaLink="false">https://wanderer.work/articles/gatsby로-블로그-시작하기/</guid><pubDate>Sun, 03 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;시작하기&lt;/h2&gt;
&lt;p&gt;나는 너무나 게으르고 풍요로운 0과 1의 세계를 내가 오염시킬 필요가 없다고 생각해왔기 때문에 블로그 운영에는 관심을 끊고 살았지만, 사실 언제나 마음은 있었다. 오랜만에 또 마음이 동해서 여러 가지 블로그 생성 도구를 둘러보다가 &lt;a href=&quot;https://www.gatsbyjs.org/&quot;&gt;Gatsby&lt;/a&gt;를 써보려고 하니 &lt;a href=&quot;https://github.com/alxshelepenok/gatsby-starter-lumen&quot;&gt;gatsby-starter-lumen&lt;/a&gt; 테마가 그럴싸해보여서 엉겁결에 이러저러한 인스톨과 약간의 테마 수정을 거쳐 이렇게 마크다운 몇자를 적는 일에 이르렀다.&lt;/p&gt;
&lt;h2&gt;Gatsby&lt;/h2&gt;
&lt;p&gt;Gatsby는 &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;로 만든 정적 사이트 생성기이다. &lt;del&gt;위대한 개츠비가 아니다.&lt;/del&gt; &lt;del&gt;갸스비 왁스도 아니야.&lt;/del&gt; 공식 웹사이트에서는 앞에 &lt;strong&gt;겁나 빠른&lt;/strong&gt;을 붙여서 &lt;em&gt;Blazing-fast static site generator for React&lt;/em&gt;라고 소개하고 있다. 문서와 튜토리얼을 잘 제공하고 있으나, 자세한 기능은 부대끼며 알아보기로 했다. 참고로 이 글을 쓰는 시점의 React의 최신 버전은 &lt;code&gt;16.2.0&lt;/code&gt;이지만 Gatsby는 버전 15의 마지막 업데이트인 &lt;code&gt;15.6.2&lt;/code&gt;를 의존하고 있다. 버전 16.x를 적용하려면 &lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-react-next/&quot;&gt;gatsby-plugin-react-next&lt;/a&gt;를 쓸 수 있는 모양인데 해보지는 않았다.&lt;/p&gt;
&lt;p&gt;사실 유명한 정적 사이트 생성기로는 지킬을 비롯해서 많이 있기 때문에 Gatsby가 뭐가 좋은지 아직 잘 모르겠다. React로 되어 있고 위에도 말했지만 테마가 마음에 들었을 뿐이다. 사실 앞으로 Gatsby의 장점을 영영 모를 수도 있다. 블로그를 열심히 운영한 적이 없기 때문이다. 쉰소리는 그만하고 설치로 넘어가자.&lt;/p&gt;
&lt;h2&gt;설치&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;gatsby-cli&lt;/code&gt;를 설치하고 테마를 지정해서 초기화 명령을 하면 알아서 스캐폴딩을 하고 의존 모듈도 내려 받는다. &lt;em&gt;요즘은 다 이러니까 놀랍지가 않다.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;$ yarn global add gatsby-cli
$ gatsby new blog https://github.com/alxshelepenok/gatsby-starter-lumen
$ gatsby develop
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;이렇게 실행하고 나면 &lt;code&gt;localhost:8000&lt;/code&gt;으로 블로그 페이지에 접속할 수 있다. 게시물은 &lt;code&gt;src/pages/articles&lt;/code&gt;에 디렉토리별로 분리되어 있다. &lt;code&gt;src/pages/pages&lt;/code&gt;는 블로그 소개 같은 별도 페이지를 위한 디렉토리이다. 자세한 디렉토리 구조는 &lt;a href=&quot;https://github.com/alxshelepenok/gatsby-starter-lumen&quot;&gt;gatsby-starter-lumen&lt;/a&gt;에서 확인할 수 있다.&lt;/p&gt;
&lt;h2&gt;설정&lt;/h2&gt;
&lt;p&gt;블로그 설정은 &lt;code&gt;gatsby-config.js&lt;/code&gt;를 잘 만져보면 된다. &lt;code&gt;siteMetadata&lt;/code&gt;를 수정해주는 것이 거의 대부분이다. 여기서 &lt;code&gt;author&lt;/code&gt; 항목에 있는 키를 삭제하면 GraphQL이 &lt;code&gt;pageQuery&lt;/code&gt;에 오류가 났다고 난리다. 설정에서 삭제한 항목을 GraphQL 쿼리 보내는 부분을 확인해서 삭제해야 한다. 나같은 경우는 &lt;code&gt;telegram&lt;/code&gt;, &lt;code&gt;vk&lt;/code&gt;를 지웠다. &lt;code&gt;rss&lt;/code&gt; 같은 경우에는 &lt;code&gt;gatsby-plugin-feed&lt;/code&gt; 플러그인이 생성해주기 때문에 &lt;code&gt;/rss.xml&lt;/code&gt;로 작성했다. 트위터와 GitHub 같은 경우에는 아이디만 작성하면 된다.&lt;/p&gt;
&lt;p&gt;이 테마는 댓글로 &lt;a href=&quot;https://disqus.com&quot;&gt;Disqus&lt;/a&gt;도 사용할 수 있는데, &lt;code&gt;disqusShortname&lt;/code&gt;에 Disqus를 등록할 때 쓴 이름을 넣어주면 된다. 자세한 가이드는 &lt;a href=&quot;https://help.disqus.com/customer/portal/articles/466208-what-s-a-shortname-&quot;&gt;여기&lt;/a&gt;에서 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;화면 구성은 React 컴포넌트로 되어 있으므로, React 개발자 도구를 켜고 잘 찾아보면 된다. 스타일시트는 scss로 작성되어 &lt;code&gt;src/assets/scss&lt;/code&gt;에 전역 스타일이 있고 컴포넌트 별로 디렉토리에 자체 스타일이 분리되어 있다. 테마에서는 Roboto를 사용하는데 난 Lato로 바꾸고, 코드 블럭에 쓰려고 Fira Mono를 추가했다. &lt;code&gt;layouts/index.jsx&lt;/code&gt;를 열어보면 &lt;code&gt;typeface-roboto&lt;/code&gt;를 불러오는 부분이 있는데, &lt;a href=&quot;https://github.com/KyleAMathews/typefaces&quot;&gt;typefaces 저장소&lt;/a&gt;를 이용하고 있어서 같은 방식으로 폰트를 설치하고 추가했다.&lt;/p&gt;
&lt;p&gt;내가 선택한 테마에는 &lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-offline/&quot;&gt;gatsby-plugin-offline&lt;/a&gt;이 적용되어 있어서 별도의 작업을 하지 않아도 ServiceWorker가 적용된다. 이 외에도 Gatsby에 적용할 수 있는 &lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-offline/&quot;&gt;여러가지 플러그인들&lt;/a&gt;이 있다. 가령 내 경우에는 &lt;a href=&quot;https://www.gatsbyjs.org/packages/gatsby-plugin-google-analytics/&quot;&gt;gatsby-plugin-google-analytics&lt;/a&gt;를 추가해서 별 고생없이 구글 애널리틱스를 적용할 수 있었다. 장점을 한가지 발견한 것 같다.&lt;/p&gt;
&lt;h2&gt;새 글 작성하기&lt;/h2&gt;
&lt;p&gt;곧 새 글을 쓰려니 단점이 나왔다. 새 글을 작성할 때 마크다운 문서를 자동으로 생성해주는 기능 따위가 없다. &lt;a href=&quot;https://github.com/gatsbyjs/gatsby/issues/2577&quot;&gt;왜 없냐는 이슈&lt;/a&gt;에 일단 그런 건 계획 없다는 답변이 있다. 일단 고대의 마법인 복사-붙여넣기를 시전하고 잘 수정해준다. 이슈를 잘 읽어보면 &lt;a href=&quot;https://github.com/mchandleraz/gatsby-utils&quot;&gt;gatsby-utils&lt;/a&gt;와 &lt;a href=&quot;https://github.com/DSchau/create-gatsby-blog-post&quot;&gt;create-gatsby-blog-post&lt;/a&gt;가 소개되어 있는데 디렉토리 하나 만드는 것은 대수롭지 않으므로 일단 수동으로 했다. &lt;del&gt;이랬다, 저랬다.&lt;/del&gt;&lt;/p&gt;
&lt;h2&gt;빌드와 배포&lt;/h2&gt;
&lt;p&gt;빌드와 배포는 &lt;a href=&quot;https://www.gatsbyjs.org/tutorial/part-one/#deploying-gatsbyjs-websites-on-the-web&quot;&gt;튜토리얼&lt;/a&gt;에 잘 설명되어 있다. 튜토리얼에서는 &lt;a href=&quot;http://surge.sh&quot;&gt;Surge&lt;/a&gt;를 사용해서 배포한다. 요즘 GitHub Pages 말고도 이렇게 무료로 정적 웹사이트 호스팅 하는 서비스들이 있는데 써본 적이 없으니 한번 써보기로 했다. 처음에는 React 공식문서도 쓰고 있다는 &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;에 관심이 있었는데, Gatsby가 안내하는 Surge가 매우 단순해보여서 이쪽으로 실행해보기로 했다. 먼저 Gatsby에서 빌드를 실행한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;$ gatsby build
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;빌드를 마치면 &lt;code&gt;public&lt;/code&gt; 디렉토리에서 빌드를 마친 정적 리소스를 확인할 수 있다. &lt;a href=&quot;http://surge.sh/help/getting-started-with-surge&quot;&gt;Surge를 사용하는 과정&lt;/a&gt;은 웹사이트에서 소개하고 있다. NPM 모듈을 설치하고 실행하면 터미널에서 가입과 로그인을 할 수 있다. 아래에서 &lt;code&gt;public&lt;/code&gt;은 업로드 할 정적 리소스가 있는 디렉토리이다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;$ yarn global add surge
$ surge public
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;
  &lt;span
    class=&quot;gatsby-resp-image-wrapper&quot;
    style=&quot;position: relative; display: block; ; max-width: 786px; margin-left: auto; margin-right: auto;&quot;
  &gt;
    &lt;span
      class=&quot;gatsby-resp-image-background-image&quot;
      style=&quot;padding-bottom: 50.50890585241731%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAAA7UlEQVQoz42Sa26EMAyEuU0XFuy8SQiBbe9/qH60asX+2Ic0iWzweGzH3WTEenVBjTugVozHEDGSY4jOluyNi+t2E5805I9+/EfHifOS8gIp5Urc+fdzdGenH7W/SkhlLqsl1dI4NiTyPiNfhgkMB1lHdZM67B9XXisTBI7oUZd1q20X46yPIeW3ykZ5VD9Mhtm0/bPtX7XdQKkbZZelqQ304sJ8R+7/KqRm7DgXgpjc+S61vRgYsmRBmbJRQPMYmH9jYL89X648e/Qxo3au8CGZfWA9xBgeCcLRYd3gA1w+ok/DPiodcLNRLhIv3//jbPwWqdKKAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
    &gt;
      &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        style=&quot;width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;&quot;
        alt=&quot;Surge를 이용한 배포&quot;
        title=&quot;&quot;
        src=&quot;/static/surge-deployment-6fe2826185ca1cacb3cb383b2351f50f-024ef.png&quot;
        srcset=&quot;/static/surge-deployment-6fe2826185ca1cacb3cb383b2351f50f-2c1d3.png 240w,
/static/surge-deployment-6fe2826185ca1cacb3cb383b2351f50f-2c7d6.png 480w,
/static/surge-deployment-6fe2826185ca1cacb3cb383b2351f50f-024ef.png 786w&quot;
        sizes=&quot;(max-width: 786px) 100vw, 786px&quot;
      /&gt;
    &lt;/span&gt;
  &lt;/span&gt;
  &lt;/p&gt;
&lt;p&gt;가입을 마치자 마자 바로 배포가 진행된다. Surge에서 제공하는 도메인 이름도 수정할 수 있다. 그 외에 별도로 구입한 도메인에 CNAME을 이용해서 쓰는 &lt;a href=&quot;https://surge.sh/help/adding-a-custom-domain&quot;&gt;방법&lt;/a&gt;도 있다. 도메인을 &lt;a href=&quot;http://goddady.com&quot;&gt;GoDaddy&lt;/a&gt;에서 구매했는데, @으로 CNAME 지정이 되지 않아 가이드에 있는 A 레코드를 설정하기는 했다. 테스트하면서 Surge에 올린 다른 페이지는 &lt;code&gt;surge list&lt;/code&gt; 명령으로 조회하고 &lt;code&gt;surge teardown {domain}.surge.sh&lt;/code&gt;를 실행하면 삭제할 수 있다.&lt;/p&gt;
&lt;p&gt;그런데 ServiceWorker를 사용하려면 SSL을 적용해야 하는데, Surge는 별도 도메인에 대한 SSL 적용은 유료로 지원한다. 이런 이유로 다시 Netlify를 확인해보니 무료 계정에 도메인을 따로 사용해도 SSL을 무료로 제공하고 있다. 심지어 복잡한 설정도 없이 클릭 몇 번이면 해결되었다. 가입도 GitHub 계정으로 가능하기 때문에 일사천리로 진행할 수 있었다. 방법은 큰 차이가 없다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot;&gt;
      &lt;pre class=&quot;language-bash&quot;&gt;&lt;code&gt;$ yarn global add netlify-cli
$ &lt;span class=&quot;token function&quot;&gt;cd&lt;/span&gt; public
$ netlify deploy
&lt;/code&gt;&lt;/pre&gt;
      &lt;/div&gt;
&lt;p&gt;&lt;code&gt;netlify-cli&lt;/code&gt;를 설치하고 배포 명령을 실행한 후 터미널의 질문에 잘 답변해주면 된다. 도메인과 HTTPS 적용은 &lt;a href=&quot;https://www.netlify.com/docs/&quot;&gt;문서&lt;/a&gt;에 설명되어 있다. HTTPS의 경우에는 배포 후에 브라우저로 접속해서 해당 사이트의 Settings - Domain Management에서 적용할 수 있다.&lt;/p&gt;
&lt;p&gt;그나저나 점심을 먹고 나서 처음 &lt;code&gt;gatsby new blog ...&lt;/code&gt;를 실행했는데 저녁시간이 되어 버렸다. 과연 내가 계속해서 이 블로그를 잘 쓸 수 있을까? 허허허허허.&lt;/p&gt;</content:encoded></item></channel></rss>