<?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[RSS Feed of itsmo.dev]]></title><description><![CDATA[배운 것을 잊지 않기 위해 틈틈히 기록합니다.]]></description><link>https://www.itsmo.dev</link><generator>GatsbyJS</generator><lastBuildDate>Tue, 17 Feb 2026 09:12:42 GMT</lastBuildDate><item><title><![CDATA[Storybook 컴포넌트에 Next.js에서 적용했던 로컬 폰트 그대로 적용하기 (feat. Tailwind)]]></title><description><![CDATA[본 글은 Next.js@14.1.3 + Tailwind@3.3.0 + Storybook@8.0.1 기준으로 작성되었습니다. 버전이 다를 경우 본 설정과 달라질 수 있습니다. Next.js + Tailwind 조합으로 Storybook…]]></description><link>https://www.itsmo.dev/storybook-font/</link><guid isPermaLink="false">https://www.itsmo.dev/storybook-font/</guid><pubDate>Tue, 19 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;본 글은 &lt;a href=&quot;mailto:Next.js@14.1.3&quot;&gt;Next.js@14.1.3&lt;/a&gt; + &lt;a href=&quot;mailto:Tailwind@3.3.0&quot;&gt;Tailwind@3.3.0&lt;/a&gt; + &lt;a href=&quot;mailto:Storybook@8.0.1&quot;&gt;Storybook@8.0.1&lt;/a&gt; 기준으로 작성되었습니다. 버전이 다를 경우 본 설정과 달라질 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://nextjs.org/&quot;&gt;Next.js&lt;/a&gt; + &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt; 조합으로 &lt;a href=&quot;https://storybook.js.org/&quot;&gt;Storybook&lt;/a&gt;을 사용하던 중 컴포넌트에 폰트 적용이 제대로 되지 않는 이슈가 있었다. 현재 페이지의 폰트는 최상위 레이아웃에 Next.js의 &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/optimizing/fonts#local-fonts&quot;&gt;localFont API&lt;/a&gt;를 불러 와 variable 설정 후 className으로 주입, tailwind의 theme extend로 fontFamily를 등록하여 사용하는 방식이다.&lt;/p&gt;
&lt;p&gt;같은 방식으로 Storybook에서도 폰트를 사용하기 위해서는 몇 가지 설정이 필요하다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;보다 자세한 설정은 Storybook 공식문서의 &lt;a href=&quot;https://storybook.js.org/docs/get-started/nextjs#nextjs-font-optimization&quot;&gt;Next.js font optimization&lt;/a&gt;를 참고하자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;기존의-Nextjs-폰트-설정-방식&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%A1%B4%EC%9D%98-Nextjs-%ED%8F%B0%ED%8A%B8-%EC%84%A4%EC%A0%95-%EB%B0%A9%EC%8B%9D&quot; aria-label=&quot;기존의 Nextjs 폰트 설정 방식 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;기존의 Next.js 폰트 설정 방식&lt;/h2&gt;
&lt;p&gt;스토리북 설정에 들어가기 전 현재 프로젝트에서 폰트를 사용하는 방식에 대해서 설명하겠다.&lt;/p&gt;
&lt;p&gt;현재 진행 중인 프로젝트는 특정 상황에서 사용하는 폰트 2가지를 제외하고 전역으로 &lt;a href=&quot;https://github.com/orioncactus/pretendard&quot;&gt;Pretendard&lt;/a&gt; 폰트를 사용하고 있다. 사용할 폰트를 등록하기 위해 폰트를 관리할 fonts.ts파일을 만들고 폰트 최적화를 위해 Next.js의 localFont API를 불러와 각 폰트 정보를 입력해 주었다.&lt;/p&gt;
&lt;p&gt;tailwind에 등록해 사용할 것이기 때문에 폰트를 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/Using_CSS_custom_properties&quot;&gt;CSS 변수&lt;/a&gt;로 등록하고자 variable에 변수 이름을 적어주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/app/fonts.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; localFont &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;next/font/local&apos;&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 keyword&quot;&gt;const&lt;/span&gt; LogoFont &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;localFont&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;
  src&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../public/fonts/Library3AM.woff2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  display&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;swap&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  variable&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;--font-logo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// css 변수로 등록하기 위함&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 keyword&quot;&gt;const&lt;/span&gt; Pretendard &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;localFont&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;
  src&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../public/fonts/PretendardVariable.woff2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  display&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;swap&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  variable&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;--font-pretendard&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// css 변수로 등록하기 위함&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 keyword&quot;&gt;const&lt;/span&gt; Chab &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;localFont&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;
  src&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../../public/fonts/chab.ttf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  display&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;swap&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  variable&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;--font-chab&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// css 변수로 등록하기 위함&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;className으로 폰트를 편하게 적용하도록 tailwind config에서 theme를 추가해 주었다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// tailwind.config.ts&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Config &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;tailwindcss&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; config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Config &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  content&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;&apos;./src/pages/**/*.{js,ts,jsx,tsx,mdx}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;./src/components/**/*.{js,ts,jsx,tsx,mdx}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;./src/app/**/*.{js,ts,jsx,tsx,mdx}&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;
  theme&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    colors&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;
    extend&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 comment&quot;&gt;// ...&lt;/span&gt;
      fontFamily&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        logo&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;&apos;var(--font-logo)&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;
        pretendard&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;&apos;var(--font-pretendard)&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;
        chab&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;&apos;var(--font-chab)&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;&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 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 comment&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 keyword&quot;&gt;default&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 설정한 변수를 Next.js에서 사용될 수 있도록 주입해주어야 한다. 전역 레이아웃에서 변수들을 불러와 주입해주고, 대표로 사용할 폰트 또한 선언해 주자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/app/layout.tsx&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; clsx &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;clsx&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; LogoFont&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Pretendard&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Chab &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;./fonts&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 앞서 fonts.ts에서 export했던 폰트들을 불러온다.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;./globals.css&apos;&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 keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;RootLayout&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;
  children&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; Readonly&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  children&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; React&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ReactNode&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;
  &lt;span class=&quot;token keyword&quot;&gt;return&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;html lang&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ko&quot;&lt;/span&gt; className&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;clsx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LogoFont&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Pretendard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Chab&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&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 operator&quot;&gt;&amp;lt;&lt;/span&gt;body className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;font-pretendard&quot;&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;children&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;body&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;html&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러면 body 아래의 모든 요소들은 Pretendard 폰트로 지정되고, 특정 컴포넌트에서 폰트를 사용하고자 할 때는 &lt;code class=&quot;language-text&quot;&gt;className=&quot;font-logo&quot;&lt;/code&gt;와 같이 사용하면 된다.&lt;/p&gt;
&lt;h2 id=&quot;기존-설정-방식-그대로-Storybook에서-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%EC%A1%B4-%EC%84%A4%EC%A0%95-%EB%B0%A9%EC%8B%9D-%EA%B7%B8%EB%8C%80%EB%A1%9C-Storybook%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;기존 설정 방식 그대로 Storybook에서 사용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;기존 설정 방식 그대로 Storybook에서 사용하기&lt;/h2&gt;
&lt;p&gt;Storybook을 처음 설치하면 루트 디렉토리에 &lt;code class=&quot;language-text&quot;&gt;.storybook&lt;/code&gt;이라는 폴더가 생기고, 그 밑에 &lt;code class=&quot;language-text&quot;&gt;main.ts&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;preview.ts&lt;/code&gt;파일이 위치한다. 이 중 &lt;code class=&quot;language-text&quot;&gt;preview.ts&lt;/code&gt;에는 보여질 story에 대한 기본 설정을 할 수 있는데, &lt;a href=&quot;https://storybook.js.org/docs/writing-stories/decorators&quot;&gt;decorators&lt;/a&gt;라는 옵션을 이용하면 컴포넌트가 렌더링되는 스토리 영역의 디자인을 변경해줄 수 있다. 우리는 이를 이용하여 기존 설정처럼 폰트를 불러와 상위 요소에 변수를 주입시켜줄 것이다. 컴포넌트를 사용해야 하므로 &lt;code class=&quot;language-text&quot;&gt;preview.ts&lt;/code&gt;파일의 확장자를 &lt;code class=&quot;language-text&quot;&gt;preview.tsx&lt;/code&gt;로 변경하고 decorator를 다음과 같이 입력한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .storybook/preview.tsx&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Preview &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;@storybook/react&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; React &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;react&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; Chab&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; LogoFont&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Pretendard &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;../src/app/fonts&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 string&quot;&gt;&apos;../src/app/globals.css&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; clsx &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;clsx&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; preview&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Preview &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  parameters&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    controls&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      matchers&lt;span class=&quot;token operator&quot;&gt;:&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 regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;(background|color)$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;i&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        date&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;Date$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;i&lt;/span&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 comment&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;
  decorators&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;Story&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;div
        className&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;clsx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          Pretendard&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          LogoFont&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          Chab&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;variable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&apos;font-pretendard&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;
      &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Story &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 operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&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;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; preview&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 class=&quot;language-text&quot;&gt;Story&lt;/code&gt;가 실제 렌더링될 컴포넌트 부분이다. 우리는 렌더링될 실제 영역을 div로 한번 감싸 폰트의 변수를 등록해주고, pretendard 폰트를 사용하겠다고 선언해준 것이다.&lt;/p&gt;
&lt;p&gt;다음으로 Storybook에게 우리의 폰트가 어느 위치에 있는지 알려주어야 한다. &lt;code class=&quot;language-text&quot;&gt;main.ts&lt;/code&gt;에 &lt;code class=&quot;language-text&quot;&gt;staticDirs&lt;/code&gt;부분에 폰트가 위치해 있는 폴더를 입력해주자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;typescript&quot;&gt;&lt;pre class=&quot;language-typescript&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .storybook/main.ts&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; StorybookConfig &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;@storybook/nextjs&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; config&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; StorybookConfig &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 comment&quot;&gt;// ...&lt;/span&gt;
  staticDirs&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;
      from&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;../src/components/fonts&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      to&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;src/components/fonts&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;
  &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 keyword&quot;&gt;default&lt;/span&gt; config&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 Storybook을 실행해서 폰트가 제대로 적용되는지 확인해 보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 678px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d8d6b21d0f996da94b2ea776b446bb45/dc057/storybook-font-check.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 30.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABe0lEQVR42k2QP2gUQRSHF7u0IhZBzp2dv7u3d3uXy5mT41ILNjbWkjbYimCIiCacCkJyRQohRSxsTCVYJCAIiohGbJU0imJpJRjEy+e7gRMHPmZ4M/Px3i+5OD+g1+1RzXVoVC2UNihjcd6R1x22yGnaOu0sx2aONNPMFh1qNkdlhlRbzirDmVoqd4bkwlyfxf6A/mCRTvdcFGYitM7jQsD6wOzyZWZuLXHp9jVW19dYuT9k9d6QG8O1yMrdde5sPuDK1WWSmrUo69EiMC5EWcQ6jKDywOl3Dzn1e5/Rz0/8+PyVL9+/8Wc8Zrp+HR0xPj5m780rEu8MZVlQNCoZsSQvytjZRKoneM/Jxzc58X6L6wfP2N19wmhnmxcHb/lw+DGy//olT5/vsfFom8TI526vR3fhPPVGk5ZkORFPRzcygZU8TXA46bbRasmbNkGytcFHQr2grJqxkSTVEnzVjtJJXrVU/ZNNhV52LzWrNZlSQoaR8//oTGrG8BdPeOGTqSz7HQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;폰트가 잘 적용되는 모습이다.&apos; title=&apos;&apos; src=&apos;/static/d8d6b21d0f996da94b2ea776b446bb45/dc057/storybook-font-check.png&apos; srcset=&apos;/static/d8d6b21d0f996da94b2ea776b446bb45/e7570/storybook-font-check.png 170w,
/static/d8d6b21d0f996da94b2ea776b446bb45/f46e7/storybook-font-check.png 340w,
/static/d8d6b21d0f996da94b2ea776b446bb45/dc057/storybook-font-check.png 678w&apos; sizes=&apos;(max-width: 678px) 100vw, 678px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;폰트가 잘 적용되는 모습이다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;폰트가 제대로 출력되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;무언가를 적용하려 할 때는 일단 공식문서를 찬찬히 훑어보는 것이 제일 빠른 길이라고 느낀다. 열심히 블로그 글을 찾다 보면 오래된 버전 기준이라 현재 버전에선 적용이 되지 않거나, 효율적인 방법이 아닌 경우가 종종 생긴다. &lt;del&gt;영어 읽기 싫어서 블로그 글을 찾다 보면 결국 해답은 공식문서에 다 있더라...&lt;/del&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[mise: 런타임을 버전 별로 관리하여 프로젝트마다 버전 설정하기]]></title><description><![CDATA[들어가기 전에: 본 게시글의 모든 명령어는 Windows Subsystem for Linux 2(WSL2) Ubuntu 22.04에서 진행되었습니다. macOS나 여타 Linux…]]></description><link>https://www.itsmo.dev/introduce-mise/</link><guid isPermaLink="false">https://www.itsmo.dev/introduce-mise/</guid><pubDate>Thu, 14 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;들어가기 전에&lt;/strong&gt;: 본 게시글의 모든 명령어는 &lt;strong&gt;Windows Subsystem for Linux 2(WSL2) Ubuntu 22.04&lt;/strong&gt;에서 진행되었습니다. macOS나 여타 Linux 환경에서는 명령어가 다를 수 있습니다.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;진행하는 프로젝트가 많아지면서 프로젝트 별로 개발 버전이 다른 경우가 종종 생긴다. 현재 진행 중인 프로젝트의 &lt;code class=&quot;language-text&quot;&gt;node.js&lt;/code&gt; 버전이 &lt;code class=&quot;language-text&quot;&gt;18&lt;/code&gt; 이라면 새로운 프로젝트는 &lt;code class=&quot;language-text&quot;&gt;node.js&lt;/code&gt; 버전이 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;이라던가, 아니면 오래 전에 개발했던 프로젝트를 열어보려는데 구버전의 런타임을 사용해야만 동작한다던가 하는 경우 말이다.&lt;/p&gt;
&lt;p&gt;사용하는 언어마다 이러한 경우에 대비하여 버전 매니저를 설치하여 사용할 수 있다. &lt;code class=&quot;language-text&quot;&gt;Node.js&lt;/code&gt;의 경우 &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;, &lt;code class=&quot;language-text&quot;&gt;Python&lt;/code&gt;의 경우 &lt;a href=&quot;https://github.com/pyenv/pyenv&quot;&gt;pyenv&lt;/a&gt;, &lt;code class=&quot;language-text&quot;&gt;Ruby&lt;/code&gt;의 경우 &lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;rbenv&lt;/a&gt; 같이 말이다. 그러나 사용하는 언어가 많아진다면 각 언어 별로 버전 매니저를 설치해서 사용하는 것 자체가 피곤해질 수 있다.&lt;/p&gt;
&lt;p&gt;이러한 문제를 해결하기 위해 런타임 언어의 버전을 하나의 명령어로 관리하기 위해 탄생한 툴들이 있다. 이 중 가장 유명한 툴은 &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;asdf&lt;/a&gt;이고, 아래 소개할 툴은 이 &lt;code class=&quot;language-text&quot;&gt;asdf&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;Rust&lt;/code&gt;로 다시 작성한 툴인 &lt;a href=&quot;https://mise.jdx.dev/&quot;&gt;mise&lt;/a&gt;이다.&lt;/p&gt;
&lt;h2 id=&quot;설치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%84%A4%EC%B9%98&quot; aria-label=&quot;설치 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;설치&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;원문 및 보다 자세한 사용법은 &lt;a href=&quot;https://mise.jdx.dev/getting-started.html&quot;&gt;https://mise.jdx.dev/getting-started.html&lt;/a&gt;을 참조할 것.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;1-mise-CLI-설치하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-mise-CLI-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;1 mise CLI 설치하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1. &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt; CLI 설치하기&lt;/h3&gt;
&lt;p&gt;아래의 명령어를 입력하여 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;를 설치한다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://mise.run &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;가 잘 설치되었는지 확인하기 위해 아래의 명령어를 입력해 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ~/.local/bin/mise &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
mise &lt;span class=&quot;token number&quot;&gt;2024&lt;/span&gt;.x.x&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise 2024.x.x&lt;/code&gt; 와 같이 버전이 출력된다면 제대로 설치된 것이다.&lt;/p&gt;
&lt;h3 id=&quot;2-mise-활성화하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-mise-%ED%99%9C%EC%84%B1%ED%99%94%ED%95%98%EA%B8%B0&quot; aria-label=&quot;2 mise 활성화하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2. &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt; 활성화하기&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise activate&lt;/code&gt; 명령어 하나로 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;에 설치된 각 런타임들의 경로를 &lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt;에 간단하게 추가할 수 있다. 해당 명령어가 쉘 시작 시점에 동작하도록 다음 명령어를 통해 각 쉘의 &lt;code class=&quot;language-text&quot;&gt;rc&lt;/code&gt; 파일에 입력하자.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bash&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;eval &quot;$(~/.local/bin/mise activate bash)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.bashrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;zsh&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;eval &quot;$(~/.local/bin/mise activate zsh)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;런타임-설치하고-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%9F%B0%ED%83%80%EC%9E%84-%EC%84%A4%EC%B9%98%ED%95%98%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;런타임 설치하고 사용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;런타임 설치하고 사용하기&lt;/h2&gt;
&lt;p&gt;지금까지 설치한 것은 런타임을 관리하기 위한 툴이다. 이젠 이 툴을 사용하여 사용하고자 하는 런타임을 설치할 것이다. 실제 예시를 들어 사용법을 익혀보자.&lt;/p&gt;
&lt;h3 id=&quot;시나리오&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4&quot; aria-label=&quot;시나리오 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;시나리오&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;node.js&lt;/code&gt;를 활용한 두 개의 프로젝트 A, B가 있다. 프로젝트 A는 &lt;code class=&quot;language-text&quot;&gt;node.js&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;18&lt;/code&gt;버전으로 작업하였고, 프로젝트 B는 &lt;code class=&quot;language-text&quot;&gt;node.js&lt;/code&gt; &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전으로 작업하였다. 두 프로젝트를 오가며 작업해야 해서 두 버전을 모두 설치해 사용해야 한다.&lt;/p&gt;
&lt;p&gt;단, 앞으로 새롭게 진행할 프로젝트들은 모두 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전으로 진행할 것이라고 가정한다.&lt;/p&gt;
&lt;h3 id=&quot;이용-가능한-런타임-확인하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B4%EC%9A%A9-%EA%B0%80%EB%8A%A5%ED%95%9C-%EB%9F%B0%ED%83%80%EC%9E%84-%ED%99%95%EC%9D%B8%ED%95%98%EA%B8%B0&quot; aria-label=&quot;이용 가능한 런타임 확인하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;이용 가능한 런타임 확인하기&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise ls-remote &amp;lt;runtime&gt;&lt;/code&gt; 명령어를 사용하면 해당 런타임에서 설치 가능한 모든 버전이 표시된다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# mise ls-remote &amp;lt;runtime&gt;&lt;/span&gt;
$ mise ls-remote &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
&lt;span class=&quot;token number&quot;&gt;20.10&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;20.11&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;20.11&lt;/span&gt;.1
&lt;span class=&quot;token number&quot;&gt;21.0&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.1&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.2&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.3&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.4&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.5&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.6&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.6&lt;/span&gt;.1
&lt;span class=&quot;token number&quot;&gt;21.6&lt;/span&gt;.2
&lt;span class=&quot;token number&quot;&gt;21.7&lt;/span&gt;.0
&lt;span class=&quot;token number&quot;&gt;21.7&lt;/span&gt;.1
$ &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;런타임-설치하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%9F%B0%ED%83%80%EC%9E%84-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;런타임 설치하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;런타임 설치하기&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise install &amp;lt;runtime&gt;@&amp;lt;version&gt;&lt;/code&gt;명령어를 사용하면 해당하는 버전의 런타임을 설치할 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;version의 경우 정확히 명시하지 않고 &lt;code class=&quot;language-text&quot;&gt;node@20&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;node@latest&lt;/code&gt;와 같이 명시할 수도 있다. &lt;code class=&quot;language-text&quot;&gt;node@20&lt;/code&gt;과 같이 입력할 경우 20버전 중 가장 최신 버전이 설치되고, &lt;code class=&quot;language-text&quot;&gt;node@latest&lt;/code&gt;의 경우 가장 최신 버전의 node가 설치된다.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;아래 명령어를 통해 두 가지 버전의 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;를 설치하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# node 18 설치&lt;/span&gt;
$ mise &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; node@18
mise node@18.19.1 ✓ installed

&lt;span class=&quot;token comment&quot;&gt;# node 20 설치&lt;/span&gt;
$ mise &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; node@20
mise node@20.11.1 ✓ installed&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;자, 이제 두 버전의 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;를 설치하였으므로 잘 설치되었는지 확인하기 위해 아래 명령어를 입력해보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
zsh: &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; not found: &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;분명 위에서 설치했음에도 불구하고 node를 찾을 수 없다고 나온다. 이는 우리가 node를 설치만 했을 뿐 어떤 버전을 사용한다고 명시하지 않았기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;전역으로-사용할-런타임-버전-설정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%84%EC%97%AD%EC%9C%BC%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%9F%B0%ED%83%80%EC%9E%84-%EB%B2%84%EC%A0%84-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;전역으로 사용할 런타임 버전 설정하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;전역으로 사용할 런타임 버전 설정하기&lt;/h3&gt;
&lt;p&gt;위의 시나리오에서 우리는 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전의 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;를 전역으로 사용한다고 가정하였다. 모든 환경에서 특정 버전을 사용하도록 명시하려면 &lt;code class=&quot;language-text&quot;&gt;mise use -g &amp;lt;runtime&gt;@&amp;lt;version&gt;&lt;/code&gt; 명령어를 사용하면 된다. 이 명령어를 사용할 경우 mise의 전역 설정 파일에 해당 버전을 기록하고, 만약 &lt;strong&gt;설치되어 있지 않은 버전의 런타임일 경우 자동으로 설치&lt;/strong&gt;까지 해준다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ mise use &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; node@20 &lt;span class=&quot;token comment&quot;&gt;# 전역에서 사용할 node버전을 20(20.x.x)으로 설정&lt;/span&gt;
mise ~/.config/mise/config.toml tools: node@20.11.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;설치할 때와 달리 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;의 버전을 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;으로 명시한 이유는 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전의 minor version change가 일어나 새롭게 업데이트하는 경우 버전을 다시 명시해 주어야 하는데, 이는 매우 번거로울 수 있기 때문이다. 혹시나 정확한 버전으로 명시하고 싶은 경우 &lt;code class=&quot;language-text&quot;&gt;node@20.11.1&lt;/code&gt;과 같이 표기하면 된다.&lt;/p&gt;
&lt;p&gt;위와 같이 전역 버전 설정 후 다시 node의 버전을 확인해 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
v20.11.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;우리가 전역으로 설정했던 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전의 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;가 잘 실행되는 것을 볼 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;특정-프로젝트에서-런타임-특정-버전-설정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8A%B9%EC%A0%95-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90%EC%84%9C-%EB%9F%B0%ED%83%80%EC%9E%84-%ED%8A%B9%EC%A0%95-%EB%B2%84%EC%A0%84-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;특정 프로젝트에서 런타임 특정 버전 설정하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;특정 프로젝트에서 런타임 특정 버전 설정하기&lt;/h3&gt;
&lt;p&gt;B프로젝트는 전역으로 설정된 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전의 노드를 사용해도 문제가 없지만. A프로젝트의 경우 &lt;code class=&quot;language-text&quot;&gt;18&lt;/code&gt;버전의 노드가 필요하기 때문에 추가적인 설정이 필요하다. 해당 프로젝트의 경로로 이동해서 다음 명령어를 사용해 버전을 명시하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; projectA &lt;span class=&quot;token comment&quot;&gt;# 해당 프로젝트의 경로로 이동한다.&lt;/span&gt;

$ mise use node@18 &lt;span class=&quot;token comment&quot;&gt;# node 버전을 18로 명시한다.&lt;/span&gt;
mise ~/projectA/.mise.toml tools: node@18.19.1

$ &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# node 버전을 다시 확인한다.&lt;/span&gt;
v18.19.1 &lt;span class=&quot;token comment&quot;&gt;# 18 버전의 node가 사용되고 있음을 확인할 수 있다.&lt;/span&gt;

$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 이전 폴더로 돌아가 node 버전을 확인해 본다.&lt;/span&gt;
v20.11.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;해당 폴더에서 &lt;code class=&quot;language-text&quot;&gt;mise use node@18&lt;/code&gt;명령어를 사용하자 폴더 아래에 .mise.toml이라는 문서가 생성되면서 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;의 버전이 &lt;code class=&quot;language-text&quot;&gt;18&lt;/code&gt;로 변경되었다. 상위 폴더로 돌아가 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt; 버전을 다시 확인해보면 전역으로 설정했던 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전이 호출되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;이와 같이 전역으로 런타임의 특정 버전을 설정할 때에는 &lt;code class=&quot;language-text&quot;&gt;mise use -g&lt;/code&gt;, 특정 로컬에서 버전을 설정할 때에는 &lt;code class=&quot;language-text&quot;&gt;mise use&lt;/code&gt;를 사용하면 된다. 다음은 이 명령어를 사용했을 때 생성되는 &lt;code class=&quot;language-text&quot;&gt;.mise.toml&lt;/code&gt;파일에 대해서 간단하게 알아보자.&lt;/p&gt;
&lt;h3 id=&quot;misetoml-파일-톺아보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#misetoml-%ED%8C%8C%EC%9D%BC-%ED%86%BA%EC%95%84%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;misetoml 파일 톺아보기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;.mise.toml 파일 톺아보기&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;세부 설정 방법은 &lt;a href=&quot;https://mise.jdx.dev/configuration.html&quot;&gt;https://mise.jdx.dev/configuration.html&lt;/a&gt;을 참고.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;.mise.toml&lt;/code&gt; 파일은 &lt;code class=&quot;language-text&quot;&gt;asdf&lt;/code&gt;에서 사용하는 &lt;code class=&quot;language-text&quot;&gt;.tool-versions&lt;/code&gt;파일과 같이 mise에서 사용할 버전을 명시해 둔 파일이다. 해당 파일을 사용하면 사용할 런타임의 버전 설정 외에도 env변수나 Python에서 사용하는 venv 설정 파일의 경로 등을 관리할 수 있다.&lt;/p&gt;
&lt;p&gt;위의 로컬 프로젝트의 버전을 명시할 때 생성됐던 &lt;code class=&quot;language-text&quot;&gt;.mise.toml&lt;/code&gt;파일을 확인해 보자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# cat .mise.toml&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;18&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;[tools]&lt;/code&gt; 안에 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;의 버전이 &lt;code class=&quot;language-text&quot;&gt;18&lt;/code&gt;로 명시되어 있는 것을 확인할 수 있다. 다음은 전역으로 설정한 노드 버전을 확인해 보자. 전역 설정 파일은 기본적으로 &lt;code class=&quot;language-text&quot;&gt;~/.config/mise/config.toml&lt;/code&gt; 에 위치하고 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;toml&quot;&gt;&lt;pre class=&quot;language-toml&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# cat ~/.config/mise/config.toml&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token table class-name&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token key property&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;20&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;앞서 전역으로 사용하기로 명시했던 &lt;code class=&quot;language-text&quot;&gt;20&lt;/code&gt;버전의 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;가 적혀 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;즉 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;는 프로젝트 폴더에 로컬 설정 파일이 있는지 확인하고, 로컬 파일이 있다면 거기에 적힌 런타임의 버전을 실행하고, 로컬 파일이 없다면 전역으로 설정한 런타임의 버전을 실행한다는 사실을 알 수 있다.&lt;/p&gt;
&lt;h2 id=&quot;IDE에서-mise-올바르게-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#IDE%EC%97%90%EC%84%9C-mise-%EC%98%AC%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;IDE에서 mise 올바르게 사용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;IDE에서 mise 올바르게 사용하기&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;세부 설정 방법은 &lt;a href=&quot;https://mise.jdx.dev/ide-integration.html&quot;&gt;https://mise.jdx.dev/ide-integration.html&lt;/a&gt;을 참고.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위와 같이 설정하고 &lt;code class=&quot;language-text&quot;&gt;IntelliJ&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;WebStorm&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;VSCode&lt;/code&gt;와 같은 IDE에서 프로젝트를 실행하면 &lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt;가 없다고 나오며 제대로 동작하지 않을 수 있다. 이는 우리가 &lt;code class=&quot;language-text&quot;&gt;mise activate&lt;/code&gt; 명령어를 쉘의 &lt;code class=&quot;language-text&quot;&gt;rc&lt;/code&gt;파일에서만 진행했기 때문이다. 스크립트 파일이나 IDE는 명령어를 실행할 때 &lt;code class=&quot;language-text&quot;&gt;.bashrc&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;.zshrc&lt;/code&gt;가 아닌 &lt;code class=&quot;language-text&quot;&gt;.bash_profile&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;.zprofile&lt;/code&gt;이 작동한다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;에서 제공하는 &lt;code class=&quot;language-text&quot;&gt;shims&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt;에 등록하는 명령어를 &lt;code class=&quot;language-text&quot;&gt;profile&lt;/code&gt; 파일에 올려 IDE에서 런타임을 올바르게 인식할 수 있도록 하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# bash&lt;/span&gt;
$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;eval &quot;$(mise activate bash --shims)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.bash_profile

&lt;span class=&quot;token comment&quot;&gt;# zsh&lt;/span&gt;
$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;eval &quot;$(mise activate zsh --shims)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.zprofile&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;여기서 생소할 수 있는 &lt;code class=&quot;language-text&quot;&gt;shims&lt;/code&gt; 라는 단어가 나오는데, 이 &lt;code class=&quot;language-text&quot;&gt;shims&lt;/code&gt;는 무엇일까?&lt;/p&gt;
&lt;h3 id=&quot;Shims&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#Shims&quot; aria-label=&quot;Shims permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;Shims&lt;/h3&gt;
&lt;p&gt;구글에 Shim을 검색하면 MDN 용어 사전이 튀어나온다. MDN에서는 Shim을 다음과 같이 정의한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;심Shim은 &lt;strong&gt;이미 존재하는 코드의 동작을 바로잡는 데 사용되는 코드 모음&lt;/strong&gt;이며, 보통 문제를 야기시키는 신규 API에 대응한다.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위키백과에서는 Shim을 다음과 같이 정의한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;컴퓨터 프로그래밍에서 shim은 &lt;strong&gt;API 호출을 투명하게 가로채고 전달된 인수를 변경하고 작업 자체를 처리하거나 작업을 다른 곳으로 리디렉션하는 라이브러리&lt;/strong&gt;입니다. Shim을 사용하여 최신 환경에서 이전 API를 지원하거나 이전 환경에서 새 API를 지원할 수 있습니다.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그리고 이 shims이 작성되어 있는 폴더로 이동해 내용을 확인해 보면, 각 파일들이 심볼릭 링크로 연결되어 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c1a9b558cde4ba4687770def857f1552/05113/shims-list.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 28.235294117647058%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABCElEQVR42nWP63KCQAxGeZAqDJUFV1ovsMtFWEBQO33/9zkN2vqn+uObZCaTkxMv1JY3tWcRZ/i6JAg/CAKNL1n6a3zJX330v/NHfE2oUpJM4213JYd9jTWOquopyx5jHTo1LOblUBbe9b1KluH90P8kMo/x6maiqk8M4zeHrKF1F4bhC9Ne0UVHMhSoqSDqDPGlJDrmcmDzHLpc45XVgJVF113Z7irq40gn0Ly5oMU66QR4skTOoMaC1QxcvQBKvBkwQ3ux2snrjTsziq11V9LiRNIK8CyGrbmZqsESxOnN5ilwtstNS9NOfG4LSnnfuYnseGaT96g6I+oNqypDdWLaimG4eQn8Afx4t7BeCwfyAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;shims 폴더의 실제 내용&apos; title=&apos;&apos; src=&apos;/static/c1a9b558cde4ba4687770def857f1552/ca1dc/shims-list.png&apos; srcset=&apos;/static/c1a9b558cde4ba4687770def857f1552/e7570/shims-list.png 170w,
/static/c1a9b558cde4ba4687770def857f1552/f46e7/shims-list.png 340w,
/static/c1a9b558cde4ba4687770def857f1552/ca1dc/shims-list.png 680w,
/static/c1a9b558cde4ba4687770def857f1552/02d09/shims-list.png 1020w,
/static/c1a9b558cde4ba4687770def857f1552/9d567/shims-list.png 1360w,
/static/c1a9b558cde4ba4687770def857f1552/05113/shims-list.png 1443w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;shims 폴더의 실제 내용&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;정리해보면, shims 아래에 있는 파일 이름으로 PATH를 연결하면 해당 명령어를 실행할 때 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;를 통해서 실행되고, &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;가 .mise.toml 파일을 읽어 사용자가 설정한 런타임 버전에 맞게 이를 실행해 준다는 의미가 된다. 즉, IDE에서 런타임을 &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;의 shims를 가리키도록 설정하면, 프로젝트가 바뀌어서 런타임의 버전이 바뀌더라도 IDE의 설정을 다시 건드릴 필요 없이 정상 동작하게 되는 것이다.&lt;/p&gt;
&lt;h3 id=&quot;JetBrains-IDE에서-mise-자동-인식시키기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#JetBrains-IDE%EC%97%90%EC%84%9C-mise-%EC%9E%90%EB%8F%99-%EC%9D%B8%EC%8B%9D%EC%8B%9C%ED%82%A4%EA%B8%B0&quot; aria-label=&quot;JetBrains IDE에서 mise 자동 인식시키기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;JetBrains IDE에서 mise 자동 인식시키기&lt;/h3&gt;
&lt;p&gt;JetBrains IDE는 &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;ruby&lt;/code&gt;와 같은 몇몇 언어들의 경우 &lt;code class=&quot;language-text&quot;&gt;asdf&lt;/code&gt;에서 설치한 런타임 버전들을 자동으로 인식하도록 설정되어 있다(유료 IDE의 힘인가보다.).&lt;/p&gt;
&lt;p&gt;즉, &lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;를 &lt;code class=&quot;language-text&quot;&gt;asdf&lt;/code&gt;의 경로로 생각하도록 &lt;code class=&quot;language-text&quot;&gt;symlink&lt;/code&gt;만 걸어주면 JetBrains의 IDE에서도 SDK를 자동 인식시킬 수 있다.&lt;/p&gt;
&lt;p&gt;다음 명령어를 통해서 심볼릭 링크를 생성하자.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; ~/.local/share/mise ~/.asdf&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Java의 경우에는 해당 명령어를 사용하더라도 자동 인식이 되지 않는 것 같다(Java 환경에서 asdf와 같은 버전 매니저를 많이 사용하지 않아서 그런지…). 따라서 직접 경로를 설정해야 하는데, mise에서 설치한 모든 런타임의 경로는 &lt;code class=&quot;language-text&quot;&gt;~/.local/share/mise/installs&lt;/code&gt;에 위치해 있다.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;IDE를 재시작하면 정상 인식하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h3 id=&quot;마무리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EB%AC%B4%EB%A6%AC&quot; aria-label=&quot;마무리 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mise&lt;/code&gt;는 이 외에도 (아직 실험 기능이긴 하나) 특정 작업을 자동화할 수 있는 &lt;a href=&quot;https://mise.jdx.dev/tasks/&quot;&gt;Tasks&lt;/a&gt;와 같은 기능도 제공한다. 나는 아직까지 IDE를 사용해서 코딩을 하고 있어 큰 필요성은 느끼지 못했으나 만약 CLI로 많은 작업을 하는 사람에게는 크게 유용할 것 같아 보인다.&lt;/p&gt;
&lt;p&gt;여담으로 여태 이 툴의 이름을 &lt;code class=&quot;language-text&quot;&gt;마이스&lt;/code&gt; 혹은 &lt;code class=&quot;language-text&quot;&gt;마이즈&lt;/code&gt;라고 읽었는데, 정확한 발음은 &lt;code class=&quot;language-text&quot;&gt;미즈[MEEZ]&lt;/code&gt;라고 한다. 사실 풀 네임은 mise-en-place[미장플라스]라는데, 기존 이 툴의 이름이었던 &lt;code class=&quot;language-text&quot;&gt;rtx&lt;/code&gt;가 Nvidia의 RTX 그래픽카드 시리즈와 이름이 같아 변경했음에도 검색하기가 여전히 너무 어렵다. 업데이트도 꾸준하고 &lt;code class=&quot;language-text&quot;&gt;asdf&lt;/code&gt;보다 사용성도 좋아 애용하는 툴인데, 하루빨리 유명해져서 구글 검색 가장 위에 떴으면 좋겠다...&lt;del&gt;사실 그러길 바라는 마음에 이 글을 썼다.&lt;/del&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[OOP] 우리는 왜 List list = new ArrayList(); 라고 쓰는가]]></title><description><![CDATA[개요 우리는 왜 인스턴스를 선언할 때 타입을 클래스 대신 인터페이스로 선언할까? import…]]></description><link>https://www.itsmo.dev/interface-as-type/</link><guid isPermaLink="false">https://www.itsmo.dev/interface-as-type/</guid><pubDate>Tue, 25 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;개요&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%9C%EC%9A%94&quot; aria-label=&quot;개요 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;개요&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;우리는 왜 인스턴스를 선언할 때 타입을 클래스 대신 인터페이스로 선언할까? import 두 번 하기 귀찮은데…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Java&lt;/code&gt;와 같은 객체 지향 언어에서 다양한 자료구조를 사용하다 보니 문득 의문이 든다. &lt;code class=&quot;language-text&quot;&gt;ArrayList&lt;/code&gt;나 &lt;code class=&quot;language-text&quot;&gt;HashMap&lt;/code&gt;과 같은 자료구조를 사용할 때, 어째서 우리는 아래와 같이 클래스 대신 인터페이스 타입으로 선언해서 사용할까? 그냥 사용하고자 하는 클래스 그대로 선언하여 사용하면 편하지 않을까?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&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 class-name&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&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 comment&quot;&gt;// 왜 이렇게 쓰지 않을까?&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&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 class-name&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; map &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&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 comment&quot;&gt;// 왜??&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 코드 2번, 5번 줄처럼 list와 map을 선언해도 동작엔 무리가 없다. 그러나 당신이 저런 방식으로 위 인스턴스를 생성해 왔다면, 당신은 &lt;strong&gt;객체지향을 제대로 사용하고 있지 않은 것&lt;/strong&gt;이다.&lt;/p&gt;
&lt;p&gt;이 글에서는 어째서 우리는 인터페이스로 타입을 선언해야 하는지, 객체지향적인 관점에서 확인해 볼 것이다.&lt;/p&gt;
&lt;h2 id=&quot;다형성Polymorphism&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A4%ED%98%95%EC%84%B1Polymorphism&quot; aria-label=&quot;다형성Polymorphism permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;다형성(Polymorphism)&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;💡 &lt;em&gt;多形性 - 하나의 객체가 많은 형(타입)을 가질 수 있는 성질&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;객체지향 언어를 공부한 적이 있는 사람이라면 객체지향의 네 가지 특징인 추상화&lt;code class=&quot;language-text&quot;&gt;Abstraction&lt;/code&gt;, 다형성&lt;code class=&quot;language-text&quot;&gt;Polymorphism&lt;/code&gt;, 상속&lt;code class=&quot;language-text&quot;&gt;Inheritance&lt;/code&gt;, 캡슐화&lt;code class=&quot;language-text&quot;&gt;Encapsulation&lt;/code&gt;에 대해서 한 번쯤은 들어 보았을 것이다. 그중에서도 오늘의 주제는 다형성이 어째서 중요한지를 알려주는 좋은 예시이다.&lt;/p&gt;
&lt;p&gt;객체지향 언어를 처음 공부할 때로 되돌아가 복습해 보자. 다형성이란 무엇인가? 다형성이란, 하나의 객체가 많은 타입을 가질 수 있는 성질을 말한다. 두 클래스가 상속 관계에 있다면, 우리는 조상 클래스 타입으로 자식 객체를 레퍼런스 할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&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;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Animal&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 class-name&quot;&gt;Animal&lt;/span&gt; animal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&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 comment&quot;&gt;// 사람은 동물이다.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;왜 이런 일이 가능할까? 바로 &lt;strong&gt;자식 클래스는 조상 클래스의 모든 기능을 물려받았기 때문&lt;/strong&gt;이다. 즉, 위의 코드처럼 &lt;code class=&quot;language-text&quot;&gt;Animal&lt;/code&gt; 클래스를 상속받고 있는 &lt;code class=&quot;language-text&quot;&gt;Person&lt;/code&gt; 클래스는 &lt;code class=&quot;language-text&quot;&gt;Animal&lt;/code&gt; 클래스가 가지고 있는 모든 기능들을 사용할 수 있으므로 타입을 &lt;code class=&quot;language-text&quot;&gt;Person&lt;/code&gt;이 아닌 &lt;code class=&quot;language-text&quot;&gt;Animal&lt;/code&gt;로 지정하더라도 전혀 문제가 없다. 바로 이 이유가 오늘 문제의 답이다.&lt;/p&gt;
&lt;h2 id=&quot;인터페이스로-타입을-선언하는-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A1%9C-%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%EC%96%B8%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;인터페이스로 타입을 선언하는 이유 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;인터페이스로 타입을 선언하는 이유&lt;/h2&gt;
&lt;p&gt;당신이 열심히 &lt;code class=&quot;language-text&quot;&gt;ArrayList list = new ArrayList();&lt;/code&gt;를 사용해 프로그램을 개발했다고 생각해 보자. 단순히 선언뿐만 아니라, 이 &lt;code class=&quot;language-text&quot;&gt;ArrayList&lt;/code&gt;를 매개변수로 입력받거나 반환하는 메소드도 무수히 만들었다. 어느 날, 당신의 상사이든 클라이언트든 당신이 명령을 거부할 수 없는 어떤 누군가가 와서 이렇게 말한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;😈: 우리 로직에는 ArrayList보다 LinkedList가 효율이 더 좋을 것 같으니 그걸로 바꿔주세요!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;단순히 &lt;code class=&quot;language-text&quot;&gt;ArrayList&lt;/code&gt;를 모두 &lt;code class=&quot;language-text&quot;&gt;LinkedList&lt;/code&gt;로 치환하기만 하면 끝나는 일이라기엔 변경해야 할 사항이 너무나도 많다. 그러나 우리가 &lt;code class=&quot;language-text&quot;&gt;ArrayList&lt;/code&gt;를 클래스가 아닌 인터페이스인 &lt;code class=&quot;language-text&quot;&gt;List&lt;/code&gt;로 선언했다면? 간단히 인스턴스 변수 자체만 &lt;code class=&quot;language-text&quot;&gt;LinkedList&lt;/code&gt;로 변경함으로써 주어진 모든 문제를 깔끔하게 해결할 수 있다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;something&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;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 comment&quot;&gt;//반환 타입이 변경될 때마다 코드를 수정해야 한다.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;something&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;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 인터페이스와 제네릭으로 메소드를 구현한다면 구현체가 변경되더라도 메소드 사용에 문제가 없다.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;낮은-결합도의-중요성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%82%AE%EC%9D%80-%EA%B2%B0%ED%95%A9%EB%8F%84%EC%9D%98-%EC%A4%91%EC%9A%94%EC%84%B1&quot; aria-label=&quot;낮은 결합도의 중요성 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;낮은 결합도의 중요성&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/fd6a04d627616a23a2ab38893da28487/912c7/coupling-and-cohesion.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 101.17647058823529%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADgElEQVR42q2UWXPaSBSF8///SspTlYkrT7GLHY/jJEDCYkCsEhKCFtp36cxpQbCdmXmbrrpY7r76dJdz+12e5+j1egjDEP/HelcUBW5ubrBcLOD6PoRlwbqYsGxYtg0hBI7H43XfEkccuXf143OSJGeg/Om02wiiCOlRIIpCHqaI6JAnFhD4cB0HNsFlWaJgRoX8S5PZyYCCIMDpdHoBttpdRO4GyeIB31aMNM0RTsdYKx0ove8V0Gf0crlJjth5xvNuCTvOqr2YH5cfvAIfug84CA1T7RucQRe552G2VfE4G6G3nWJpHhl5BP5AGX3F4vkJrtKH8FUEWYks/Q0oU3bpbB0tBPMZHMeDsH2Evg4UFvwghud7QF5guBjB0wcItScs+m0YnkCRZTi9BrYJlLWTq5RpmSP4BxNlUVZ7Ml2fdYpZjr0xQTB9xNfJDxwYLew+kjR7iVAWtdVqIbjIZmCY7NwAwbiD3BdXoMsyyLU1VlD2QyRM2Vuu6bNCEnsEumfg4XBAs9lEdAFmlMTq5xdMzAnTda5A7wJMGUBCY/i08p9NMQwD9Xodm80GO92Aoe2wUBZQNjuoqg5N06But9AXCnxq0ea5MZtBpVncD0wDx/UaJyFeA2uw2YgsthG4OiNA1bk0iauIHL7ojYbI1S0SvpzqO6TbDYLNGpGhI5TS2u3OQCnIVquJOE6RRQKBt4M7nyM+WdAcF1JpMcsSrFfwlSns4QAFG6S6Hur0u+cHrNUKwd542+U4jtkYWpTAY2oxazZRVTgxJ4jj5U6fcXp6gHjsojzsMaPP5/EY90x9Phwi3O9fgN1OBycCeqxjzlSlrmTXAzYjZ90j00So68gIcn+yu4Lze7KxYeQKm5EyXYfnbyIMKWwp7sgSTE2BZ7NGzgkpuy6BgX6ukRSqZzF926jmulIGge7vQDlaJaXgiSVcaqqINL4kEDOV18AyMhBbffj7R/roV+CbCDtMuZpVuXITNm+YOef314oIDS/AInOROl+Q2n+hTC5AnrnGK+Dd3R2kfExGYhK0pvYmqyXHTMeBDTnyrjT7Pfg897QtzOkAxuQ7vJ1BkAGbF/S830fAxlbAPv+p1WpoNBqVJhuNOlqcHrlX2f09ah8+oE5r3d6i8ectnz9Wz82Pt+h++oQ/3r/HeDI5A/9ryTmXIydvZ0G9WrwXy8u4/ZuvPPsbCjbh9PX9ltwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;결합도가 낮을 수록, 응집도가 높을 수록 이상적인 코드라고 한다.&apos; title=&apos;&apos; src=&apos;/static/fd6a04d627616a23a2ab38893da28487/ca1dc/coupling-and-cohesion.png&apos; srcset=&apos;/static/fd6a04d627616a23a2ab38893da28487/e7570/coupling-and-cohesion.png 170w,
/static/fd6a04d627616a23a2ab38893da28487/f46e7/coupling-and-cohesion.png 340w,
/static/fd6a04d627616a23a2ab38893da28487/ca1dc/coupling-and-cohesion.png 680w,
/static/fd6a04d627616a23a2ab38893da28487/02d09/coupling-and-cohesion.png 1020w,
/static/fd6a04d627616a23a2ab38893da28487/912c7/coupling-and-cohesion.png 1228w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;결합도가 낮을 수록, 응집도가 높을 수록 이상적인 코드라고 한다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;우리는 위와 같이 인터페이스로 타입을 선언함으로써 클래스 간의 결합도&lt;code class=&quot;language-text&quot;&gt;Coupling&lt;/code&gt;를 낮추었다. 객체지향에서 흔히들 *‘결합도가 낮은 코드가 좋은 코드다’*라고들 말하는데, 위의 경우가 바로 결합도를 낮춤으로써 코드의 재사용성을 높인 케이스라고 할 수 있겠다.&lt;/p&gt;
&lt;h2 id=&quot;결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;결론 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;인터페이스를 구체 클래스의 타입으로 선언하는 것은 낮은 결합도를 보장하기 위한 핵심이다. 프로그램의 규모가 작고 간단히 실습하는 코드에서야 구현체를 직접 타입으로 선언하더라도 동작엔 무리가 없겠지만, 프로그램의 규모가 커질수록 이러한 객체지향적인 설계가 중요해진다. 이러한 다형성은 Spring Framework의 핵심 원리인 DI&lt;code class=&quot;language-text&quot;&gt;Dependency Injection&lt;/code&gt;를 설명하기 위한 특징이므로, 어째서 이렇게 사용해야만 하는지에 대해 정확히 짚고 넘어갈 필요가 있겠다.&lt;/p&gt;
&lt;h2 id=&quot;참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;참고 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://choichumji.tistory.com/165&quot;&gt;다형성: 우리는 왜 List list = new ArrayList(); 라고 쓸까?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[VanilaJS] Web Speech API를 활용한 음성인식 게임 개발 회고]]></title><description><![CDATA[2023년 5월 24일부터 5월 3…]]></description><link>https://www.itsmo.dev/speech-game-memoir/</link><guid isPermaLink="false">https://www.itsmo.dev/speech-game-memoir/</guid><pubDate>Mon, 03 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;2023년 5월 24일부터 5월 30일까지 약 일주일 간 진행한 &lt;a href=&quot;https://github.com/itsmo1031/Speech-To-Game&quot;&gt;&lt;strong&gt;바닐라 자바스크립트 기반 개인 프로젝트&lt;/strong&gt;&lt;/a&gt;를 회고해보고자 한다. 어째서 이 프로젝트가 시작되었는가 하는 이야기부터, 프로젝트를 진행하면서 겪었던 여러 가지 장애들을 되짚어보며 무엇을 습득했는지 톺아보자. &lt;a href=&quot;https://itsmo1031.github.io/Speech-To-Game/&quot;&gt;&lt;strong&gt;결과물 빠르게 구경하기&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;사건의-발단&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%82%AC%EA%B1%B4%EC%9D%98-%EB%B0%9C%EB%8B%A8&quot; aria-label=&quot;사건의 발단 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;사건의 발단&lt;/h2&gt;
&lt;p&gt;자바스크립트 교육이 끝나고, &lt;code class=&quot;language-text&quot;&gt;HTML&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;CSS&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;JS&lt;/code&gt;를 이용한 간단한 자기소개 페이지(추후 포트폴리오로 쓸 용도로) 혹은 원하는 페이지를 만들라는 과제가 주어졌다. 간단히 자기소개 페이지를 제작하면 금방 끝날 일이었지만 바로 이전 과제에서 팀 단위로 짧게나마 소개하는 페이지를 만들기도 했고, 포트폴리오는 추후 &lt;code class=&quot;language-text&quot;&gt;Next.js&lt;/code&gt; 학습 이후에 블로그 개선과 함께 작성할 예정이어서 만들고 싶지 않았다. &lt;del&gt;극 내향인이라 자기소개가 부끄럽기도 했고.&lt;/del&gt;&lt;/p&gt;
&lt;h3 id=&quot;무엇을-만들어-볼까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B4%EC%97%87%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%96%B4-%EB%B3%BC%EA%B9%8C&quot; aria-label=&quot;무엇을 만들어 볼까 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;무엇을 만들어 볼까&lt;/h3&gt;
&lt;p&gt;하지만 그렇다고 다른 번뜩이는 아이디어가 있었는가 하면 그건 또 아니었다. 거진 한 시간 가까이 각종 깃허브, 유튜브를 전전하며 아이디어를 물색하다가 문득 ‘간단한 게임이나 만들어 볼까?’하는 생각이 들었다. 페이지 내용을 억지로 채우지 않아도 되고, CSS와 JS로 그럴듯한 애니메이션과 화면 전환만 만들면 간단하지만 뭔가 있어 보이는 프로젝트가 완성될 것 같았다. 그렇게 당일 만든 간단한 게임은 바로…&lt;/p&gt;
&lt;h4 id=&quot;간단한-키보드-조작-게임-aka-오디션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EB%8B%A8%ED%95%9C-%ED%82%A4%EB%B3%B4%EB%93%9C-%EC%A1%B0%EC%9E%91-%EA%B2%8C%EC%9E%84-aka-%EC%98%A4%EB%94%94%EC%85%98&quot; aria-label=&quot;간단한 키보드 조작 게임 aka 오디션 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;간단한 키보드 조작 게임 a.k.a. 오디션&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 638px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/08fb39b85406042d2aed6b34d5f50d62/d376a/audition.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 70%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAADWklEQVR42hXC628SBwAA8Psj9m3JEqcmS/aItRY7RrEgtBzPO2h5v9930ON9QKkccEApd/QB5VUogjzaWrNqu601VTOn1WVZ3ExqZrIPZvGTH/d5H7bslx/w8uTgUbt41t/4vU/1W+2zbuleo/Ls9ur5/uavw/Kb4+F6logRhXQyWUgvkvH4MBp4OaKfdsifDneBH4+GD1YDL7Zi7x73zg/W337XeH3QfP/w9vvT0Z+P994+PajRRDQWrpTIUuGWSATt08Rfz+++ebT36vQI2NteHdWTJ73ci2bit938L4P8k2Xk/LD1uls4f9D54+x0VE3ngtYeteRfQBG9bDsXPNqiusXY8/s7AEnEcQQ+7tz6uYRV86nv12J9KjXMh15tZ/758O7fvz/sbNJzcq1aPqeE4IAetsGzuylkQAaORz2AzidcBkGTdPcyrnIW3c/YBrl4L+y+m0FOW+QPdXIp6FUp1Q6bORjErGaNxajpFpc6ReLJ/XuAy6KaunpJJZ+en5lWcFkaJey1W4yiGwr+DIp57TaLiM2BOJwY5sMQn8sEYRYwaIe9bmW/swl4HEbuFxe4jLErlz/nXWWScZ/b4ZpmfOnUI93k4igTVcvUzGss6SyoBtn8r1k6kOnijTnU0+k8DkTC0fGLH3116ePPPr0Ii4QP9+uk1cKcuu6YMxw2Iu0iLuWCE2PjYg4r5TVqxTwHxLHrpQ4nVKAIAPUEL1/4ZJIxxmRMKGUC0m+jZFJkXozBAtoMW2GJBuSLWZMht6GxHNbKZvUKgUmnM4H8xRQOeEPJyRkNqFkQmnA1TmPlltOlK1hYZSe7oIKcWkdVwi2CLNytDEWTswqP3+YU3uBIvrkeiQeBKEHx5KhYG+IpcZM/mV4hE9EoHSGriRrlK9SD5Z4nX1XImvPgHSWkMWJaE26Sw1dARSizAoSJtSnIKdAFbqoCnkCAQoUbblXZLKsYwTUDf8sMbxok62pORSemvCozGpnXB1DIwJiyhJaqQM1PKiYwKS8rYRNs0CfWL+iNVsRuDLoNOKoLIVqfW+dymLVmp0CDMcWemzJ0Ruga55hDCRroN05WsEEBvVNf/LZYaieWq+F0LZxphMlGJNvEc+3/Z1t4up7IVtIrFZKqrNVq9MbqYGf0H6BigFAwtiWQAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;현재도 서비스중인, 과거를 주름잡았던 한빛소프트의 리듬게임 ‘오디션’&apos; title=&apos;&apos; src=&apos;/static/08fb39b85406042d2aed6b34d5f50d62/d376a/audition.png&apos; srcset=&apos;/static/08fb39b85406042d2aed6b34d5f50d62/e7570/audition.png 170w,
/static/08fb39b85406042d2aed6b34d5f50d62/f46e7/audition.png 340w,
/static/08fb39b85406042d2aed6b34d5f50d62/d376a/audition.png 638w&apos; sizes=&apos;(max-width: 638px) 100vw, 638px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;현재도 서비스중인, 과거를 주름잡았던 한빛소프트의 리듬게임 ‘오디션’&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;오디션이라는 게임을 아는가? 말도 많고 탈도 많은 게임이지만 나름 많은 팬층을 보유했던, 현재까지 서비스 중인 장수 리듬게임이다. 화면 상에 떠 있는 방향 아이콘을 키보드 방향키에 맞게 입력하여 없애는 방식의 게임인데, 위 게임 로직을 바닐라 자바스크립트로 구현하고, CSS로 다채롭게 꾸미면 나름 괜찮은 스낵 게임이 될 것 같았다. 당시 고안했던 아이디어는 최대한 빠른 시간 안에 일정 레벨까지 도달하는 타임 어택 모드와, 무한한 시간이 주어지고 레벨을 클리어할 때마다 점수를 얻을 수 있지만 한 번이라도 틀리면 그대로 종료되는 무한 모드, 총 두 가지 모드를 구현하는 것이었다. 그러나 이 게임은 프로토타입 제작을 끝으로 취소되었는데, 이유는 단순히 ‘내가 재미가 없어서’였다.&lt;/p&gt;
&lt;h3 id=&quot;프로젝트의-목적이-무엇이냐&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%9D%98-%EB%AA%A9%EC%A0%81%EC%9D%B4-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%83%90&quot; aria-label=&quot;프로젝트의 목적이 무엇이냐 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;프로젝트의 목적이 무엇이냐&lt;/h3&gt;
&lt;p&gt;재미가 없는 것이 제작을 포기한 첫 번째 이유였고, 또 다른 이유는 ‘왜 만들었는가’, 그리고 ‘이 프로젝트를 하면서 무엇을 배웠는가’라는 물음에 적절한 답을 찾지 못해서였다. 내가 지금 이 프로젝트를 하는 이유는 결국 무언가를 배워가기 위함인데, 위의 프로젝트 로직에서 내가 알고 있는 지식 이외에 무언가를 배웠는가? 하면 그렇지 않았다. 결국 흥미는 크게 떨어졌고 나는 다른 아이디어를 찾아 인터넷을 다시 떠돌기 시작했다.&lt;/p&gt;
&lt;h3 id=&quot;Web-API와의-만남&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#Web-API%EC%99%80%EC%9D%98-%EB%A7%8C%EB%82%A8&quot; aria-label=&quot;Web API와의 만남 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;Web API와의 만남&lt;/h3&gt;
&lt;p&gt;구독해두었던 각종 IT 관련 채널들의 영상을 뒤적이다가 &lt;a href=&quot;https://youtu.be/yDhMmmHZONM&quot;&gt;바로 채용되는 웹개발자 포트폴리오 만들기&lt;/a&gt;라는 &lt;a href=&quot;https://www.youtube.com/@codingapple&quot;&gt;코딩애플&lt;/a&gt;님의 영상을 보았다. 약 1분 10초쯤부터 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API&quot;&gt;Web API&lt;/a&gt;에 대한 소개가 나오는데, 해당 부분을 보자마자 속으로 ‘이거다’싶었다. 한 번도 써 보지 않았던 기능이기도 하거니와 서버를 거쳐야만 가능할 것 같았던 기능들이 브라우저 내장 API 만으로 해결되는 모습을 보고, 이걸 이용한 무언가를 바닐라 자바스크립트로 구현한다면 괜찮은 반응이 나올 것 같았다.&lt;/p&gt;
&lt;p&gt;그중에서도 특히 관심 있었던 API는 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Web_Audio_API&quot;&gt;Web Audio API&lt;/a&gt;와 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API&quot;&gt;Web Speech API&lt;/a&gt;였는데, 사용하기엔 둘 다 살짝 문제가 있었다. Audio API는 제일 사용해 보고 싶었으나 제시간 안에 괜찮은 프로덕트가 나오지 못할 것 같았고(특히 구글에서 이 API를 소개하기 위해 &lt;a href=&quot;https://googlechromelabs.github.io/web-audio-samples/&quot;&gt;샘플 페이지&lt;/a&gt;를 만들어 두었는데, 여기에 내가 생각했었던 대부분의 아이디어들이 이미 구현되어 있어서 포기했다.), Speech API는 TTS&lt;code class=&quot;language-text&quot;&gt;Text-To-Speech&lt;/code&gt;, Speech Recognition(음성 인식) 두 기능을 제공하지만 두 기능 모두 이미 널리 사용하고 있는 기술이어서 브라우저로 간단히 구현 가능하다는 사실 말고는 새롭다는 이미지를 주기가 힘들 것 같았다. 그러나 더 찾아보기엔 시간이 촉박했기 때문에, 내가 지금까지 수집했던 정보들을 조합해서 아이디어를 빨리 내야만 했다. 처음 기획했던 게임이라는 주제와 엮어 볼만한 Web API가 무엇이 있을까. 숱한 고민 끝에 나온 답은 바로…&lt;/p&gt;
&lt;h3 id=&quot;음성-인식을-활용한-게임-만들기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9D%8C%EC%84%B1-%EC%9D%B8%EC%8B%9D%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EA%B2%8C%EC%9E%84-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;음성 인식을 활용한 게임 만들기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;음성 인식을 활용한 게임 만들기&lt;/h3&gt;
&lt;p&gt;많은 Web API 후보 중 선택된 것은 바로 Web Speech API의 음성 인식 기능이었다. 짧은 시간 안에 게임을 만들려면 그래픽적인 요소를 최소화해야 했는데, Web Speech API를 사용해서 나온 부산물들이 텍스트인 만큼 이를 그대로 게임 요소로 활용한다면 그래픽은 크게 신경 쓰지 않아도 되겠거니 싶었다. 다음 과제는 도대체 이 텍스트를 어떻게 게임 요소로 활용할 것이냐였는데, 그 문제는 내 무의식의 속삭임이 쉽게 해결해 주었다.&lt;/p&gt;
&lt;h4 id=&quot;-답은-산성비야&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%8B%B5%EC%9D%80-%EC%82%B0%EC%84%B1%EB%B9%84%EC%95%BC&quot; aria-label=&quot; 답은 산성비야 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;???: 답은 산성비야&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/87c559da9e3968941e623638a41fe990/64f58/acid-rain.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 74.70588235294117%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAADVElEQVR42iXM/U8adxwH8PsHt5ZtbZYObVonQdbpttRlrpJIak3GXERNZtoyZB1OHooGqA883MHdccdx973vPcHxcFwtims7QaDiXLfI7cyS1w/vfN55f5BCMgxTIZgMNpnfupK/I6x35IAYc4PoIzo4l9+c47cWpJi7I/hPxfVuaeMt+LUvBi4qoQ7wI2UsKGNhajfIJjdqZLBKbFaIEB5ezQY9mcCP6O8/4RFPPrrSoDYquWevmFBswxXwfh3y348GnEg2DXFMzWdLZFYmUAFPQWyfJTOAxthCplBAKY6gZTYvMpkKpBsC8XDJNTZrH5+13V+YQfAMpEiVY0oSkGVelIAgFDmRKYo0je/tUem0SOMNCX+pEA2ZbAiowEqO0ZGxGxaKFBAChQxljhUZKkWKpHJZBXIqz5VYRqDyHIHDfE6kMYXBJAarQ8L/ZM397V3nxCfLi4sIz8qKXFdEVQCKyAkyABUZMkSWI3M1oaiCQhlQVUhWeLyhUHU+dXx0qMusQux02m2EY8uSpJeVelmpaNXygaYc6kqzJjSrsKWJqjkTiJYGNJnRZFYTiDokg57Z1Zk7MLeDFFid44+JfBPCg3JJr1U0rVrTa6qmmv8kVeRLIq9KkgIFAUh8UUgsTW/NjT932bYXHAjJHjFSm+ZPeOVPWHrLim94+Vgut9TqodZoNg8OVVUnqDLDN/OgVQAvnzycmr93c/7LWyszY4iotdWji1LzXLkygI0B0M4E/Yqov1MOBpT0R5p9xWnvmPq5VD9xOSctVsuY47Pvp+8g/b8GfxvGuWEMTJfDwXB4Zhj9odEbDntDo3tpnLz/9+T9P6eXw55hnF60t39O+h4pMZd93z2JMMkWwM4A2mPR7h6q57OvQbpvYlNdNtUz7zzWh1gfYF2AnvHZ5t5CNPENFpqffLH8HRJe4iMe7flyLbJc3VxVI6uV7cfq1uPS7nrthbcaWama9/+Fl7TIGl94sCaPP416nGm/G4l7cwkfiPvYhI+Ne9ldP4ftp9DUjiYyEp1P+Jn4L5zZxn3FmBcknpFZ9yL1wB10fh774R4yMnX7mn3kI8ftKxOj1+1W61f2W1O2D23WazarZcKsRk1msNitH39h5k+vO25+YLthm777H2Y9kFsD4goDAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;90년대생이라면 모르는 사람이 없는 명작, 학교 컴퓨터실을 주름잡았던 최고의 게임 ‘한컴타자연습 산성비’&apos; title=&apos;&apos; src=&apos;/static/87c559da9e3968941e623638a41fe990/ca1dc/acid-rain.png&apos; srcset=&apos;/static/87c559da9e3968941e623638a41fe990/e7570/acid-rain.png 170w,
/static/87c559da9e3968941e623638a41fe990/f46e7/acid-rain.png 340w,
/static/87c559da9e3968941e623638a41fe990/ca1dc/acid-rain.png 680w,
/static/87c559da9e3968941e623638a41fe990/64f58/acid-rain.png 753w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;90년대생이라면 모르는 사람이 없는 명작, 학교 컴퓨터실을 주름잡았던 최고의 게임 ‘한컴타자연습 산성비’&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;산성비는 화면 위에서 랜덤한 단어가 떨어지고, 떨어지는 단어가 바닥에 닿기 전에 입력 창에 올바르게 입력하여 없애야 하는 간단한 게임이다. 여기서 떨어지는 단어만 음성 인식된 단어들로 바꿔준다면? 무려 세상에 없던 새로운 형식의 음성 인식 기반 게임이 탄생하는 것이었다. 신경 써야 할 그래픽 리소스도 없고, 로직도 생각보다 간단하지 않으며 배워보지 않았던 새로운 기술을 익힐 수 있는 데다가 별다른 서버 없이 &lt;strong&gt;음성 인식&lt;/strong&gt;을 구현했다는 뭔가 있어 보이는 타이틀까지. 그야말로 완벽에 가까운 프로젝트 아이디어가 아닐 수 없었다. 앞으로 내가 할 일은 핵심 로직을 간단하게 구현하고, 그럴듯하게 CSS로 꾸며주고, 약간의 자바스크립트 제어만 해 주는 것이 전부였다. &lt;del&gt;…전부여야 했다.&lt;/del&gt;&lt;/p&gt;
&lt;h2 id=&quot;프로젝트-셋업&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%85%8B%EC%97%85&quot; aria-label=&quot;프로젝트 셋업 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;프로젝트 셋업&lt;/h2&gt;
&lt;p&gt;아이디어가 정해졌으니 이제 본격적으로 프로젝트를 시작할 차례다. 개인 프로젝트이고 볼륨이 크지 않았기에 그냥 손 가는 대로 작업해도 그만이었지만, 배워 가야 하는 입장에서 단순히 아이디어의 구현 만으로는 얻는 것이 크게 없다고 생각했다. 따라서 나는 이번 프로젝트를 Github를 최대한 활용하면서 협업처럼 진행하기로 했다.&lt;/p&gt;
&lt;h3 id=&quot;main-branch에-direct-push-하지-않기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#main-branch%EC%97%90-direct-push-%ED%95%98%EC%A7%80-%EC%95%8A%EA%B8%B0&quot; aria-label=&quot;main branch에 direct push 하지 않기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;main branch에 direct push 하지 않기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/358526c6def10b0fcaae7dc21b562017/93714/branch-protection.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 87.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABrUlEQVR42qVU2XLCMBDLp5SSO/ER56Tc7ZTy/z+0Xa2TFKY3PGgW24OQJZnAtjsyDDccyXZ7wrp0T/QQlbSI1b8R6GZDql4TZmEHynRH6Y2Iy5qCfnuibvNKw+FMrt/P5P+FabeUs6Ag1S1FeUVhZmXeirhwMgNccSJcpuZuBJalqtpLvpcU3w+isqPHRDH03RCFcdEI8wTvibsNWYWUOeHdiYb9mfrdG3fR91DSZit+xZRywymbngK3eibl1uMmd5LJ0Mfc9pxc/WckZS1JC6Hl/uGVuNWBKv6MV4PXExWVlPUDDe+5q73LtXiYcQ/LmlVVK0GYW1qMIfn07AhzMX+oTaoaqoaDqEJ95l+U6WQNw0NWi8+JauU8YbWJ8kixx2dCiLtDIYKAqfDPe+iB4suaz0rcgJtwXRdzXRtcE6VGuvCt6r2PSE3zGmnjXMvczKpCrteXPTTDi5BN8U8ESBleLjNWkGohkJ6OV/u22JluJGWQiBIoY2I8SdNtOfmj1Eq8LXyql0/0E2HCxqtmzcrg40p8gkpYIQUf/yclCFXPV5YwuCFQvkz1/JbfARqtJ/Cos/MxAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;main branch에 protection rule을 걸어 직접 푸쉬를 막고, pull request를 진행해야만 적용될 수 있도록 하였다.&apos; title=&apos;&apos; src=&apos;/static/358526c6def10b0fcaae7dc21b562017/ca1dc/branch-protection.png&apos; srcset=&apos;/static/358526c6def10b0fcaae7dc21b562017/e7570/branch-protection.png 170w,
/static/358526c6def10b0fcaae7dc21b562017/f46e7/branch-protection.png 340w,
/static/358526c6def10b0fcaae7dc21b562017/ca1dc/branch-protection.png 680w,
/static/358526c6def10b0fcaae7dc21b562017/93714/branch-protection.png 777w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;main branch에 protection rule을 걸어 직접 푸쉬를 막고, pull request를 진행해야만 적용될 수 있도록 하였다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;github repository를 혼자 사용할 일이 많다 보니, 브랜치를 만들어 관리한다거나 할 일이 없었다. 그러다 보니 소스코드를 바로 main branch에 직접 푸쉬하는게 기본이었는데, 협업을 하거나 실제 프로젝트를 진행하게 되면 main 브랜치는 라이브 서버에 deploy되는 브랜치로 활용될 확률이 크다. 따라서 main 브랜치는 코드 리뷰가 끝난 코드만이 올라가야 한다. 따라서 이 프로젝트의 레포지토리에는 main branch에 프로텍트를 걸어 다이렉트 푸쉬를 막아 두고 merge 전에 pull request를 요청하도록 하고, 코드 소유자가 해당 pull request를 리뷰해야만 merge될 수 있도록 설정했다.&lt;/p&gt;
&lt;h3 id=&quot;Feature-단위로-커밋하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#Feature-%EB%8B%A8%EC%9C%84%EB%A1%9C-%EC%BB%A4%EB%B0%8B%ED%95%98%EA%B8%B0&quot; aria-label=&quot;Feature 단위로 커밋하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;Feature 단위로 커밋하기&lt;/h3&gt;
&lt;p&gt;평소에는 정말 아무렇게나 커밋하곤 했다. 마치 한글 문서 저장하듯, 이쯤이면 됐겠지 싶은 부분이나 하루 동안 작업한 분량을 기록하듯 커밋을 사용했다. 그러니 나중에 커밋 메시지를 확인했을 때 해당 커밋이 어떤 내용인지, 어떤 부분이 수정되었는지 알기가 어려웠다. 결국 수정했던 부분을 확인하려면 모든 커밋을 확인해야 하는 사태가 일어나는 것이다. 이번 프로젝트에서는 이런 참사가 일어나지 않도록 커밋을 기능 단위로 남기기로 하고, 커밋 메시지 또한 규칙을 지켜 작성하기로 했다.&lt;/p&gt;
&lt;h4 id=&quot;Github-Milestones--Issue-활용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#Github-Milestones--Issue-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;Github Milestones  Issue 활용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;Github Milestones / Issue 활용하기&lt;/h4&gt;
&lt;p&gt;Github Issues 탭의 Milestones를 통해 개발 단계를 나누고, 개발에 필요한 요소들을 Issue로 발행하여 발행된 Issue를 해결하는 방식으로 프로세스를 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/c9085fd8bfb876de397443f14accbb37/74b07/phase.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 61.76470588235294%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAA7DAAAOwwHHb6hkAAABW0lEQVR42o2TzU7DMBCE8yptYjt/dmznx0mR4MCJCxInxLPw8MNsSilRW8rh01peezPj3WSV7dEsrxjfPtE+fiA3DkUVSThTCv4que5Q9j0O788ILw/IwvSEmJ7Q+IkkMm/pZ7Qz47ww3iAtsOmwns1quRQWqKb/hurqgL2x2OsWyg+oU0I1ROiB+UBlvrskEtshKyq/FlF1ZBG3kpfdz3pvApRmXnFd3EE7ZE2gJSrMWbio/bYYDygfUC49dIowMwtP/jqJ9zuPzNgRpZvIMRo7QLf9iqL1ohnW/Uo+Rval+5NM3m0t0Gwtn9hpi506I6pvwrvHprC7R8uB8dKyWeL/LYs6sWsYpaA06dwQS8sjKssucz/nTN5VKG8m5KW/ajlviOOe41gInb9N66XLHMp4WBWK2o1Cvp8KI/+kGfXIPFGRF0N3ye85FKuazdnO3wnmNZ9CLKk7GIcvFuJqbjxMS3sAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Milestones 탭을 활용하여 개발 단계를 나누고, 각 단계마다 Issue를 발행하며 기능별로 개발을 진행했다.&apos; title=&apos;&apos; src=&apos;/static/c9085fd8bfb876de397443f14accbb37/ca1dc/phase.png&apos; srcset=&apos;/static/c9085fd8bfb876de397443f14accbb37/e7570/phase.png 170w,
/static/c9085fd8bfb876de397443f14accbb37/f46e7/phase.png 340w,
/static/c9085fd8bfb876de397443f14accbb37/ca1dc/phase.png 680w,
/static/c9085fd8bfb876de397443f14accbb37/02d09/phase.png 1020w,
/static/c9085fd8bfb876de397443f14accbb37/74b07/phase.png 1238w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;Milestones 탭을 활용하여 개발 단계를 나누고, 각 단계마다 Issue를 발행하며 기능별로 개발을 진행했다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;그저 의식의 흐름대로 개발하다 보면 중간에 샛길로 빠져버려 무엇을 하려 했는지 잊어버리곤 해 헤매는 시간이 많았다. 마일스톤과 이슈를 활용했더니 이런 &lt;del&gt;뻘짓&lt;/del&gt;이 많이 줄었다. 해야 할 일들을 기능 단위로 쪼개 이슈를 발행했고, 발행된 티켓들을 하나씩 해결하면서 마치 탑을 쌓아 나가듯이 개발해 나갔다. 중간중간 새롭게 떠오르는 아이디어들도 바로 적용하지 않고 일단 이슈를 발행한 뒤, 현재 개발하고 있는 기능이 끝난 뒤에 적용 여부를 결정했다. 마치 서류더미를 쌓아 두고 하나씩 일을 처리하는 느낌이었는데, 일일이 이슈를 적어야 한다는 점 빼고는 생산성도 올라가고 작업 흐름도 원활해져서 굉장히 큰 도움이 되었다.&lt;/p&gt;
&lt;h4 id=&quot;커밋-메시지-컨벤션-지키기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%8B%9C%EC%A7%80-%EC%BB%A8%EB%B2%A4%EC%85%98-%EC%A7%80%ED%82%A4%EA%B8%B0&quot; aria-label=&quot;커밋 메시지 컨벤션 지키기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;커밋 메시지 컨벤션 지키기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/4908ffebd5664ce02919e0b06fd9fa4d/4ad28/commit-message.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 28.82352941176471%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAxklEQVR42pWRyRKDIBBE+ZUkZVxBBBG3GKNWLpbl/39NZ1ySY0wOrxgopqcbGNcVzq7A6co/LPuLF/+BoJ6tj5miQ1oOMNWAlGpT9lC2RRBbeNwcE6WIbQ/dzIhUBdb0E+puRDNMuD9n3PoRth4QyHwV9UV2SCgLEqvhUc108SCH3YqpyF3eQmYNBD1FlBQ/CfrCwCe3bqQXwQ5cldS8sVxwKcY70jehIM4R0tBQ2nVdzphI6y3ajhMkP3+GE6rdgKa4ZjXyAktvuw7pzOA8AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;커밋 메시지 만으로도 무엇이 변경되었는지 알 수 있도록 작성했다. 눈에 잘 띄라고 이모지도 넣었다.&apos; title=&apos;&apos; src=&apos;/static/4908ffebd5664ce02919e0b06fd9fa4d/ca1dc/commit-message.png&apos; srcset=&apos;/static/4908ffebd5664ce02919e0b06fd9fa4d/e7570/commit-message.png 170w,
/static/4908ffebd5664ce02919e0b06fd9fa4d/f46e7/commit-message.png 340w,
/static/4908ffebd5664ce02919e0b06fd9fa4d/ca1dc/commit-message.png 680w,
/static/4908ffebd5664ce02919e0b06fd9fa4d/4ad28/commit-message.png 1004w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;커밋 메시지 만으로도 무엇이 변경되었는지 알 수 있도록 작성했다. 눈에 잘 띄라고 이모지도 넣었다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;커밋만큼이나 커밋 메시지도 중요하다. 해당 커밋에서 어떤 내용이 추가/수정되었는지 쉽게 파악이 되어야 팀원들 간에 혼란이 없을 것이다. 따라서 &lt;a href=&quot;https://udacity.github.io/git-styleguide/&quot;&gt;Udacity Git Commit Message Style Guide&lt;/a&gt;를 참고하여 커밋 메시지를 작성했다. 제목은 태그: 제목의 형태로 어떤 변경 사항이 적용되었는지를 표기하고, 본문에는 추가 설명이 필요한 경우 그 내용을 적어 메시지만으로도 무엇이 변경되었는지 쉽게 파악할 수 있도록 작성했다.&lt;/p&gt;
&lt;p&gt;프로젝트가 다 끝난 지금에 와서야 하는 말이지만, 자잘하게 지켜지지 않은 부분이 더 많았다. 한 커밋에 하나 이상의 기능이 추가되기도 하고, 수정된 사항을 메시지에 반영하지 않은 경우도 있었다(readme를 수정하였으나 너무 작은 내용이라 넣지 않았다던가). 협업이었다면 응당 거절당했을 커밋들이지만 이슈 발행도 내가, 처리도 내가 하다 보니 크게 신경 쓰지 않고 넘어갔던 부분이다. 귀찮은 작업이지만 실보다 득이 많은 작업들이므로, 반성하고 다음엔 더 엄격하게 관리하도록 하자.&lt;/p&gt;
&lt;h2 id=&quot;구현-중-마주한-문제들&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B5%AC%ED%98%84-%EC%A4%91-%EB%A7%88%EC%A3%BC%ED%95%9C-%EB%AC%B8%EC%A0%9C%EB%93%A4&quot; aria-label=&quot;구현 중 마주한 문제들 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;구현 중 마주한 문제들&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/f236babcf1a2419bfed0b7ed3e3d5e06/79c97/bug.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 30.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABB0lEQVR42l2Qa3KDMBCDuUmahrcNNg/bhEBgMm2a3v9AqmxIJ+2Pb5Zlba3kqB1WeMzlA/14gzJXaLvjllAbM6PqLlD2ZWb32fOMW3l3RqTNAnd9wM53OHJev9l/wUyfGJYHv+8YuajpJsjmvNGOEHuV3Yiqn7h85b8BUS561FRW/bw5cpuDisOitiiVQ6kdKtnhlCm85ySrQz2RuNBIyhZZZXBMK0SZF6SYt/uMqRhPFg0OscAxkXgjBx4OQi+cgqhGXDZIZb8J5tJQcKLghnfbsC/pKObmhIc9KYl3V7/QXXAovEMblkQpG/8WNV0FYR+X71LqASLAyIyvlEX8z+Gf2KILDn8Ak4S8HtUbLhQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;버그가 우수수… 분명 내가 테스트할 때는 멀쩡했는데!!!&apos; title=&apos;&apos; src=&apos;/static/f236babcf1a2419bfed0b7ed3e3d5e06/ca1dc/bug.png&apos; srcset=&apos;/static/f236babcf1a2419bfed0b7ed3e3d5e06/e7570/bug.png 170w,
/static/f236babcf1a2419bfed0b7ed3e3d5e06/f46e7/bug.png 340w,
/static/f236babcf1a2419bfed0b7ed3e3d5e06/ca1dc/bug.png 680w,
/static/f236babcf1a2419bfed0b7ed3e3d5e06/02d09/bug.png 1020w,
/static/f236babcf1a2419bfed0b7ed3e3d5e06/79c97/bug.png 1205w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;버그가 우수수… 분명 내가 테스트할 때는 멀쩡했는데!!!&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;위와 같이 엄격한 프로세스를 적용해도 프로그래머의 숙명이 그러하듯, 여러 가지 문제가 발생했다. 음성 인식을 하고, 인식된 문장을 단어로 쪼개는 본 프로젝트의 핵심 로직 자체는 Web API로 간단하게 구현이 끝났지만, 자바스크립트의 CSS 및 DOM 제어에서 자꾸 생각지도 못한 버그가 터져 나왔다. 분명 내가 테스트할 때는 정상적으로 동작했는데, 친구들에게 테스트를 부탁하자 기상천외한 버그가 튀어나왔다. 결국 게임 자체는 사나흘 만에 완성되었지만 UI 버그를 잡기 위해 게임 개발 기간만큼의 시간을 소요하는 놀라운 결과가 나왔다. 개발하면서 마주한 다양한 버그들과, 그 버그를 해결하기 위해 어떠한 수정을 했는지 간단하게 회고해 보자.&lt;/p&gt;
&lt;h3 id=&quot;1-스크린-토글이-정상적으로-되지-않았던-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%8A%A4%ED%81%AC%EB%A6%B0-%ED%86%A0%EA%B8%80%EC%9D%B4-%EC%A0%95%EC%83%81%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%90%98%EC%A7%80-%EC%95%8A%EC%95%98%EB%8D%98-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;1 스크린 토글이 정상적으로 되지 않았던 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1. 스크린 토글이 정상적으로 되지 않았던 문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/20e6e4206805214cec132a9bf15af65d/c7a69/bug-page.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 56.470588235294116%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABAElEQVR42qWTS2vCQBSF80esrySTyUsN6WiMunAhLly4EARLoVAQwf+/Pp0zZcTYaKguDhnu45t75xDHD1OoYoa+iNBxJbpeVe2+QKvr4a3nm/NtvuMG8IIYyWgMIVM4DNQV9vzQQCblAuvNFovlCmo6NzHm/oA1gyznNlG9XSAevmNaKoyLAvEgr738Wg+Bv1B+CQnQVNsI5Gqufh9PJrVrWrHG5hsnZKHVyxNal2nEPZf/BaRrYZohUwXySakNyk3sKSAbuebxdMZuf9D6wOfXt3mvR9BGU2gIJ0szVXn8u0A2yHiIIBpcFCYjRHpVSuozY0L/UZStYY+todhD1g+SvEJJGea0SwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;게임을 계속 재시작하다 보면 다음과 같이 화면이 이상해져버리는 문제가 발생했다.&apos; title=&apos;&apos; src=&apos;/static/20e6e4206805214cec132a9bf15af65d/ca1dc/bug-page.png&apos; srcset=&apos;/static/20e6e4206805214cec132a9bf15af65d/e7570/bug-page.png 170w,
/static/20e6e4206805214cec132a9bf15af65d/f46e7/bug-page.png 340w,
/static/20e6e4206805214cec132a9bf15af65d/ca1dc/bug-page.png 680w,
/static/20e6e4206805214cec132a9bf15af65d/02d09/bug-page.png 1020w,
/static/20e6e4206805214cec132a9bf15af65d/9d567/bug-page.png 1360w,
/static/20e6e4206805214cec132a9bf15af65d/c7a69/bug-page.png 2560w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;게임을 계속 재시작하다 보면 다음과 같이 화면이 이상해져버리는 문제가 발생했다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 게임은 &lt;code class=&quot;language-text&quot;&gt;시작 화면&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;게임 화면&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;게임 오버 화면&lt;/code&gt; 총 세 개의 화면으로 이루어져 있다. 이 게임은 게임 오버 화면에서 키를 조작해 페이지 새로 고침 없이 게임을 재시작하거나 타이틀로 돌아갈 수 있다. 물론 SPA&lt;code class=&quot;language-text&quot;&gt;Single Page Application&lt;/code&gt;이기 때문에 실제 페이지 전환은 해당 화면들의 CSS display 속성을 none으로 토글링하게 구현하였다. 문제는, 그 행동을 반복하다 보면 어느 순간 위 사진과 같이 스크린이 이상해진다는 거였다.&lt;/p&gt;
&lt;h4 id=&quot;1번-문제의-원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1%EB%B2%88-%EB%AC%B8%EC%A0%9C%EC%9D%98-%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;1번 문제의 원인 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1번 문제의 원인&lt;/h4&gt;
&lt;p&gt;이 버그는 내가 스크린 토글 기능을 한 메서드로 구현하지 않고 게임이 끝나거나 시작될 때 필요한 스크린들을 토글하도록 구현해놓아서 생긴 일이었다. 한 화면에서 다른 화면으로 이동할 때 어떤 요소들이 토글될지 눈에 보이게끔 메서드를 작성해야 하는데, 그러지 않고 그때그때 잡히는 대로 토글을 해버렸더니 디버깅도 어려운 지경에 이르렀다.&lt;/p&gt;
&lt;h4 id=&quot;해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;해결 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/itsmo1031/Speech-To-Game/commit/866f1aa0cf0cd6db259ee9c39ffe954deab0d506&quot;&gt;해결&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;화면별로 스위치 하는 메서드와 모든 화면을 숨기는 메서드를 만들고, 화면 스위치 메서드를 호출하면 일단 모든 화면을 숨기는 메서드를 호출한 뒤, 필요한 요소들을 다시 보이게 하는 식으로 코드를 변경했다. 화면을 제어하는 부분을 메서드로 빼니 눈에 보기도 좋아졌고, 해당 버그도 해결되었다.&lt;/p&gt;
&lt;h3 id=&quot;2-게임-재시작-시-이전-게임에서-인식되었던-단어들이-출력되는-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EA%B2%8C%EC%9E%84-%EC%9E%AC%EC%8B%9C%EC%9E%91-%EC%8B%9C-%EC%9D%B4%EC%A0%84-%EA%B2%8C%EC%9E%84%EC%97%90%EC%84%9C-%EC%9D%B8%EC%8B%9D%EB%90%98%EC%97%88%EB%8D%98-%EB%8B%A8%EC%96%B4%EB%93%A4%EC%9D%B4-%EC%B6%9C%EB%A0%A5%EB%90%98%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;2 게임 재시작 시 이전 게임에서 인식되었던 단어들이 출력되는 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2. 게임 재시작 시 이전 게임에서 인식되었던 단어들이 출력되는 문제&lt;/h3&gt;
&lt;p&gt;게임을 하다가 단어를 입력하지 못해 게임이 종료된 뒤, 재시작 버튼을 누르면 종료 전에 인식되었던 문장의 단어들이 출력되는 문제가 있었다. 해당 버그는 &lt;a href=&quot;https://github.com/itsmo1031/Speech-To-Game/commit/0a7b9943d201436837b01b16022dc1ce5425782d&quot;&gt;단어를 화면에서 떨어뜨리는 로직을 변경한 커밋&lt;/a&gt; 이후에 발생했다. 기존 로직에서는 음성 인식이 끝났다는 이벤트&lt;code class=&quot;language-text&quot;&gt;recognition.onresult&lt;/code&gt;가 발생하면 단순히 문장을 잘라 배열에 넣어주고, &lt;code class=&quot;language-text&quot;&gt;setInterval&lt;/code&gt;을 통해 1초마다 해당 배열을 감시하면서 배열에 단어가 있을 때마다 랜덤한 시간마다 단어가 출력되도록 딜레이를 설정해 &lt;code class=&quot;language-text&quot;&gt;timeout&lt;/code&gt;을 걸어 주는 방식이었다. 이 로직은 배열이 비어있어도 1초마다 배열을 확인하기 때문에 비효율적이라고 생각했고, 리팩터링 작업을 하면서 배열과 Interval을 사용하지 않고 문장 인식이 끝났을 때 곧바로 모든 단어들에 타임아웃을 설정하는 방식으로 변경했던 것이었다.&lt;/p&gt;
&lt;h4 id=&quot;2번-문제의-원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2%EB%B2%88-%EB%AC%B8%EC%A0%9C%EC%9D%98-%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;2번 문제의 원인 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2번 문제의 원인&lt;/h4&gt;
&lt;p&gt;원인은 &lt;strong&gt;음성 인식 종료 이벤트가 호출되는 시점이 게임이 끝난 시점보다 뒤에 위치할 수 있다&lt;/strong&gt;는데에 있었다. 게임이 끝나기 직전까지 음성 인식이 진행 중일 경우, 게임이 끝난 뒤에 음성 인식 종료 이벤트가 호출되어 단어들의 타임아웃이 설정되는 것이었다. 그래서 게임이 끝나자마자 재시작을 누르면, 설정된 딜레이 이후 단어들이 출력되어버린다. 기존에는 단어들을 배열에 집어넣는 방식이었기에 재시작을 할 때 배열을 비워주기만 하면 간단하게 해결되었지만, 바뀐 로직에서는 배열 없이 곧바로 타임아웃을 호출하므로 버그가 발생했던 것이다.&lt;/p&gt;
&lt;h4 id=&quot;해결-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0-1&quot; aria-label=&quot;해결 1 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/itsmo1031/Speech-To-Game/commit/a259a84bd9d8a9d2fdea7ca351362cd8906bb7fd&quot;&gt;해결&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;단어들에 타임아웃을 설정하기 전에, 게임이 끝났는지의 여부를 판단하는 변수인 &lt;code class=&quot;language-text&quot;&gt;isGameOver&lt;/code&gt;를 확인하여 해당 값이 참이라면 타임아웃을 설정하지 않고 메서드가 종료되도록 로직을 변경하였다. 해결 자체는 간단했지만, 원인을 파악하는 데 가장 많은 시간을 쓴 버그였다. 변경한 로직에 문제가 없다고 자만했던 내 잘못이었다😥.&lt;/p&gt;
&lt;h3 id=&quot;3-게임-도중-화면-크기를-줄일-때-떨어지는-단어-위치가-이상해지는-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%EA%B2%8C%EC%9E%84-%EB%8F%84%EC%A4%91-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0%EB%A5%BC-%EC%A4%84%EC%9D%BC-%EB%95%8C-%EB%96%A8%EC%96%B4%EC%A7%80%EB%8A%94-%EB%8B%A8%EC%96%B4-%EC%9C%84%EC%B9%98%EA%B0%80-%EC%9D%B4%EC%83%81%ED%95%B4%EC%A7%80%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;3 게임 도중 화면 크기를 줄일 때 떨어지는 단어 위치가 이상해지는 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3. 게임 도중 화면 크기를 줄일 때 떨어지는 단어 위치가 이상해지는 문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/a73c373c3e6d2108abead66a226555eb/0eb09/tweet.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 105.29411764705883%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAADQklEQVR42pVU21LaUBTND/YH+taXzvSx07fO9Lkvtj/Qaaej4g0VuSdAQoggchESFAlyEUlEIpckYJCLhK4Ajjp1ptMzyZmTnLP2XnutnRBT0wwFye21X7quDQb3uq4bhoFZVdXxeDx7bZjzWeoNiRDLvH/7ZvP7l5VvX0WxyLIczwtH8XgwRLfabeuoaf6Nn04f7sdjIpPLfvrwbuXzxx+/f2q9fqVWl2+aUqNRrtW7mgbs9HEsojyPReA2+gOjd7fYeD5eIfzyHdFsNtlIxOv1RjDYCEMzqVSK9JP2HTteOF3OUDDk9/tjsdjR0ZGu6TeN5mg4suo2Z0Sj0fB5fcFAMJlIRg+jh9xhLBr1+/y4jo+PY9FYOBx2u91chEunUqWLEsDj0WQ2nYMlSfL5fPv7+4lEAueQbXd317Zu29raAlIsiGGGdbs9oIZYq6urSGbxfzCXtLHh9Xjtdjsy81keFDw47fG6nC7kRy1Op1MQBIZhHA5HgAokk8lup2uBNVVDMUhIh2ikSqfTRVE8z58LQk7ghfxZPifksAXw6ekZAsXj8cxJRrlRLDBoQB7wpEgqn8/b5wMSRKNRRVE4jgOSoekwEwYpn89vs9kgAVj0e31kVqHwIiT0KJwX8HhRvIhErG4BF9QEFSAqRu3yamDca13N6BtwnjDu7lDkSToNhlJdAhjKgU42y2ez2VQyhSJJkkJyBL2Wry21puaiRYmZOfu/MX28AFa7qjhXqFwqo6rEcUIsFLE+Oz07SZ/AqsUCMzSrVqsvwLIsQRI2zCYSSYqioEcwGIrMe+7g4ADiY+1yufCIXZqmJ+MJyC59rl/V0SEkyqIotBGaETbyPB8IBODz3u4eamZZNpc7hbctpdVpd61KH+aZb29vISmsBuFMJguH0NuYYQbYVsrVi2IJVUDn1m27eaMYd4MncP3qanNzE8TQ1Ts7O1gj0PrauvPASVKkJMnAICdaWmk0ZelaU/Un2pfVGjBoese+A1/SxsbG9vY2xx3CmOFwuPxxzD+DpS/mM8Hw06ld1mRZLhTEcrlcKVdKJWuGFktt5kctb6ePDj8GIsaTid7vtzrdjqrpvZ7S7qi63lW14Wj0T8v/AMNqN0bIP+koAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;이 케이스는 위 트윗을 현실로 마주했던 케이스였다.&apos; title=&apos;&apos; src=&apos;/static/a73c373c3e6d2108abead66a226555eb/0eb09/tweet.png&apos; srcset=&apos;/static/a73c373c3e6d2108abead66a226555eb/e7570/tweet.png 170w,
/static/a73c373c3e6d2108abead66a226555eb/f46e7/tweet.png 340w,
/static/a73c373c3e6d2108abead66a226555eb/0eb09/tweet.png 500w&apos; sizes=&apos;(max-width: 500px) 100vw, 500px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;이 케이스는 위 트윗을 현실로 마주했던 케이스였다.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;이 문제는 정말 생각해 본 적도 없는 문제였다. 어느 누가 게임 도중에 화면 크기를 변경한단 말인가! 주변 사람들에게 테스트를 맡겼기에 찾을 수 있었던 버그 아닌 버그였다. 문제는 이걸 해결하기 위해 창 높이가 변경될 때마다 애니메이션을 바꾸도록 로직을 변경해야 했다는 데 있었다.&lt;/p&gt;
&lt;h4 id=&quot;3번-문제의-원인&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3%EB%B2%88-%EB%AC%B8%EC%A0%9C%EC%9D%98-%EC%9B%90%EC%9D%B8&quot; aria-label=&quot;3번 문제의 원인 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3번 문제의 원인&lt;/h4&gt;
&lt;p&gt;이 게임은 단어가 화면 하단까지 떨어지게 되면 끝난다. 단어가 화면에 떨어지도록 하기 위해 CSS의 애니메이션을 이용했다. 애니메이션은 간단히 일정 시간 동안 게임 화면의 맨 위에서 맨 아래로 Y값을 변경하도록 &lt;code class=&quot;language-text&quot;&gt;transform&lt;/code&gt;을 이용했다. 애니메이션 도중에 해당 단어가 입력되면 해당 단어를 DOM에서 삭제하는데, 이때 애니메이션에선 &lt;code class=&quot;language-text&quot;&gt;animationcancel&lt;/code&gt; 이벤트를 발생시킨다. 반대로 단어가 지워지지 않고 화면 끝까지 이동하면 애니메이션이 정상적으로 종료되므로 &lt;code class=&quot;language-text&quot;&gt;animationend&lt;/code&gt; 이벤트를 발생시키는데, 이 이벤트를 이용해서 &lt;code class=&quot;language-text&quot;&gt;animationend&lt;/code&gt; 이벤트가 발생할 때, 즉 단어가 중간에 제거되지 않고 끝까지 내려왔을 때 게임 종료가 되도록 구현한 것이다.&lt;/p&gt;
&lt;p&gt;따라서 이 애니메이션을 정상적으로 동작시키기 위해서는 게임 화면의 높이 값을 알아야 했는데, 이화면 크기 계산을 화면을 구성할 때, 즉 사용자가 페이지에 진입할 때를 기준으로 잡았다. 즉 사용자가 사이트에 접속해서 말 그대로 ‘게임만’ 한다면 문제가 있을 수가 없었고, 사이트에 접속한 이후에 화면의 높이를 줄이거나 늘였다면 게임이 정상적으로 동작하지 않게 보이는 것이었다.&lt;/p&gt;
&lt;h4 id=&quot;해결-2&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0-2&quot; aria-label=&quot;해결 2 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/itsmo1031/Speech-To-Game/commit/0d3bca87e83d407f56439fe0fabb25b0c5220092&quot;&gt;해결&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;기존 로직은 페이지가 로딩될 때 자바스크립트 상에서 &lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt; 태그를 만들고, 그 안에 높이를 계산한 키프레임을 담아 &lt;code class=&quot;language-text&quot;&gt;head&lt;/code&gt; 태그 안에 집어넣는 방식으로 구현되어 있었다. 이 문제를 해결하려면 애니메이션의 키프레임이 동적으로 변경되어야 했으므로 HTML에 id 값을 가진 &lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt; 태그를 미리 선언해 두고, 창 크기가 조절될 때 발생하는 &lt;code class=&quot;language-text&quot;&gt;resize&lt;/code&gt; 이벤트가 호출되면 해당 애니메이션의 키프레임을 새롭게 정의한 후 미리 선언한 &lt;code class=&quot;language-text&quot;&gt;style&lt;/code&gt; 태그에 적용하는 방향으로 로직을 바꾸어서 해결했다.&lt;/p&gt;
&lt;h2 id=&quot;버그가-왜-계속-터졌을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B2%84%EA%B7%B8%EA%B0%80-%EC%99%9C-%EA%B3%84%EC%86%8D-%ED%84%B0%EC%A1%8C%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;버그가 왜 계속 터졌을까 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;버그가 왜 계속 터졌을까&lt;/h2&gt;
&lt;p&gt;물론 버그와 싸우는 것이 프로그래머의 숙명이라지만, 개발 기간의 절반을 버그를 수정하는 데 사용했다는 것은 개발 방식에 큰 문제가 있었다는 뜻이라고 생각한다. 물론 &lt;a href=&quot;#3-%EA%B2%8C%EC%9E%84-%EB%8F%84%EC%A4%91-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0%EB%A5%BC-%EC%A4%84%EC%9D%BC-%EB%95%8C-%EB%96%A8%EC%96%B4%EC%A7%80%EB%8A%94-%EB%8B%A8%EC%96%B4-%EC%9C%84%EC%B9%98%EA%B0%80-%EC%9D%B4%EC%83%81%ED%95%B4%EC%A7%80%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot;&gt;혼자의 힘으로는 절대 찾아낼 수 없었던 버그&lt;/a&gt;도 있었지만, 사전에 체크할 수 있었던 문제들도 여럿 있었다. 왜 이렇게 많은 버그가 발생했을까?&lt;/p&gt;
&lt;h3 id=&quot;OOP의-부재&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#OOP%EC%9D%98-%EB%B6%80%EC%9E%AC&quot; aria-label=&quot;OOP의 부재 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;OOP의 부재&lt;/h3&gt;
&lt;p&gt;일반 사이트였다면 모르겠지만, 내가 만들고자 했던 것은 간단하긴 해도 &lt;strong&gt;게임&lt;/strong&gt;이었다. 게임 제작이야말로 OOP적 설계가 중요한데, 이러한 부분을 배제한 채 개발을 하다 보니 데이터가 중구난방해지고, 결국 여러 곳에서 버그가 터져 나왔다. 위에서 서술한 &lt;a href=&quot;#1-%EC%8A%A4%ED%81%AC%EB%A6%B0-%ED%86%A0%EA%B8%80%EC%9D%B4-%EC%A0%95%EC%83%81%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%90%98%EC%A7%80-%EC%95%8A%EC%95%98%EB%8D%98-%EB%AC%B8%EC%A0%9C&quot;&gt;첫 번째 문제&lt;/a&gt;가 이런 객체지향적 설계의 부재 때문에 발생한 버그의 대표적인 예였다. 스크린에 필요한 요소들을 객체로 묶어 관리했다면 조금 더 효율적으로 개발할 수 있었을 텐데, 아쉬운 부분이 크다.&lt;/p&gt;
&lt;h3 id=&quot;유닛-테스트의-부재&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9C%A0%EB%8B%9B-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%9D%98-%EB%B6%80%EC%9E%AC&quot; aria-label=&quot;유닛 테스트의 부재 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;유닛 테스트의 부재&lt;/h3&gt;
&lt;p&gt;현대 개발에서 테스트는 빠져서는 안 되는 항목이다. 테스트만을 위한 다양한 방법론도 존재하고, 테스팅 라이브러리도 다양하다. 특히 유닛 테스트는 기존 기능이 변경될 때 변경된 기능이 제대로 동작하는지 확인하기에도 용이한데, 이 프로젝트에서는 그러한 유닛 테스트가 전무하다. 그러니 버그가 터져서 버그를 고치면 다른 데서 버그가 터지고, 그걸 고치면 또 다른 데서 버그가 터지는 미치고 팔짝 뛰는 일이 발생하는 것이었다. TDD&lt;code class=&quot;language-text&quot;&gt;Test-Driven Development&lt;/code&gt;까진 아니더라도 유닛 테스트를 작성했다면 &lt;a href=&quot;#2-%EA%B2%8C%EC%9E%84-%EC%9E%AC%EC%8B%9C%EC%9E%91-%EC%8B%9C-%EC%9D%B4%EC%A0%84-%EA%B2%8C%EC%9E%84%EC%97%90%EC%84%9C-%EC%9D%B8%EC%8B%9D%EB%90%98%EC%97%88%EB%8D%98-%EB%8B%A8%EC%96%B4%EB%93%A4%EC%9D%B4-%EC%B6%9C%EB%A0%A5%EB%90%98%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot;&gt;두 번째 문제&lt;/a&gt;와 같은 일은 생기지 않았을 것이다. 다음 프로젝트에서는 꼭 테스트를 도입해야겠다고 다짐하는 계기가 되었다.&lt;/p&gt;
&lt;h2 id=&quot;마치며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A7%88%EC%B9%98%EB%A9%B0&quot; aria-label=&quot;마치며 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;마치며&lt;/h2&gt;
&lt;p&gt;프로젝트는 5월에 끝났으나, 회고 글은 6월에 시작해 7월이 되어서야 모두 작성했다. 이런저런 핑계만 대다가 계속 늦어졌고, 이대로라면 영영 쓰지 않을 것 같아 새 출발 전이 되어서야 급하게 끝마쳤다. 글을 못 쓰는 것은 당연하고, 써야 는다는 사실을 알면서도 글이 마음에 들지 않다는 이유, 쓸 말이 정리되지 않았다는 이유로 미루는 나를 반성한다. 앞으로는 무언가를 공부하고 회고를 쓰는 게 아니라, 회고를 써야 공부를 끝마친다는 각오로 글을 작성해야겠다.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Algorithm] Implementation (구현)]]></title><description><![CDATA[이 포스팅의 목표는 필자가 알고리즘을 공부하며 습득한 내용을 정리하는 데 있습니다. 따라서 틀린 내용이 있을 수 있습니다. 틀린 내용을 발견하신 경우 댓글로 지적해 주시면 감사하겠습니다.…]]></description><link>https://www.itsmo.dev/implementation-algorithm/</link><guid isPermaLink="false">https://www.itsmo.dev/implementation-algorithm/</guid><pubDate>Sat, 28 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;이 포스팅의 목표는 필자가 알고리즘을 공부하며 습득한 내용을 정리하는 데 있습니다. 따라서 틀린 내용이 있을 수 있습니다. 틀린 내용을 발견하신 경우 댓글로 지적해 주시면 감사하겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/e97006b71dc116ce91e140f8802d142a/56d4e/just-do-it.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.47058823529413%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAcydQuWiQ//EABgQAAMBAQAAAAAAAAAAAAAAAAAQEQEC/9oACAEBAAEFAucpCqr/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAIEH/2gAIAQEABj8CIv8A/8QAGRAAAwADAAAAAAAAAAAAAAAAAAERMWGB/9oACAEBAAE/IWpVOstKvTI4cKWU/9oADAMBAAIAAwAAABCbL//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EIj/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAZEAEAAwEBAAAAAAAAAAAAAAABABEhMUH/2gAIAQEAAT8Q04rrRExELSjGVJY1mwfXamCePYu5/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Just Do It&apos; title=&apos;구현 문제를 잘 푸는 법: 그냥 많이 풀어보자.&apos; src=&apos;/static/e97006b71dc116ce91e140f8802d142a/56d4e/just-do-it.jpg&apos; srcset=&apos;/static/e97006b71dc116ce91e140f8802d142a/0b705/just-do-it.jpg 170w,
/static/e97006b71dc116ce91e140f8802d142a/31389/just-do-it.jpg 340w,
/static/e97006b71dc116ce91e140f8802d142a/56d4e/just-do-it.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;구현 문제를 잘 푸는 법: 그냥 많이 풀어보자.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;1-서론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%84%9C%EB%A1%A0&quot; aria-label=&quot;1 서론 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1. 서론&lt;/h2&gt;
&lt;p&gt;구현&lt;code class=&quot;language-text&quot;&gt;Implementation&lt;/code&gt;은 엄밀히 말해 알고리즘은 아니다. 코딩 테스트에서의 구현은 &lt;strong&gt;머릿속에 있는 알고리즘을 소스코드로 바꾸는 과정&lt;/strong&gt;을 말한다. 이렇게만 말하면 &apos;모든 코딩 테스트 문제가 구현 문제 아냐?&apos;하는 의문을 제기할 수 있다. 맞다. 사실 우리가 &apos;코딩 테스트&apos;라고 말하는 모든 유형은 구현 문제다. 그러나 그중에서도 특히 &lt;strong&gt;풀이를 떠올리기는 쉽지만 이를 소스코드로 옮기기 까다로운 문제&lt;/strong&gt;를 구현 유형의 문제라고 분류한다.&lt;/p&gt;
&lt;h2 id=&quot;2-까다로운-문제가-뭐야&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EA%B9%8C%EB%8B%A4%EB%A1%9C%EC%9A%B4-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EB%AD%90%EC%95%BC&quot; aria-label=&quot;2 까다로운 문제가 뭐야 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2. 까다로운 문제가 뭐야?&lt;/h2&gt;
&lt;h3 id=&quot;2-1-구현-방법-자체가-떠오르지-않는-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-1-%EA%B5%AC%ED%98%84-%EB%B0%A9%EB%B2%95-%EC%9E%90%EC%B2%B4%EA%B0%80-%EB%96%A0%EC%98%A4%EB%A5%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;2 1 구현 방법 자체가 떠오르지 않는 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2-1. 구현 방법 자체가 떠오르지 않는 문제&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www,acmicpc.net/&quot;&gt;백준&lt;/a&gt;이나 &lt;a href=&quot;https://programmers.co.kr/&quot;&gt;프로그래머스&lt;/a&gt;와 같은 코딩 테스트 문제 제공 사이트에서 문제를 풀다 보면, 어떻게 풀면 될지 감은 오는데 이걸 어떻게 소스코드로 표현해야 할지 모르겠을 때가 종종 있다. &apos;내 방식대로 풀면 소스코드가 많이 길어질 것 같은데, 이렇게 푸는 게 맞나?&apos;싶을 때도 있고, 단순히 프로그래밍 언어의 숙련도가 부족하거나 라이브러리 사용 경험이 부족해서 건드리지 못하는 경우도 있다.&lt;/p&gt;
&lt;h3 id=&quot;2-2-시간공간-복잡도Big-O가-제한된-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-2-%EC%8B%9C%EA%B0%84%EA%B3%B5%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84Big-O%EA%B0%80-%EC%A0%9C%ED%95%9C%EB%90%9C-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;2 2 시간공간 복잡도Big O가 제한된 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2-2. 시간/공간 복잡도(Big-O)가 제한된 문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 481px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/376bca85e0c64980eca9b1938d52594c/213b2/time.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 30.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyElEQVR42n2Q2U7DMBBF/f8fxU8g8QISkKQodHFQFme8HsalSFXV5kr34dqa5Yx5G0889e88254leCiQS6HcsYjw2bQcmoY8WDLQdh1j/wVeiClj7OnArvtg+LH4EIgxPrT3nnmeceooKyFElmVB3ELSWtF/43YN8vqCP+7PG2x5XWuTcB5ci2uuQ+Ri5xwm66rYI5r4U+Ge/rFv366VUsL4aSLsvwnTqDdIm8jh5iTXuTar25p1GJBWsfXI4hVFMbaQH2V/Qf4FrHbT2ILouI4AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그놈의 시간 복잡도...&apos; title=&apos;문제의 난이도가 올라갈수록 친숙해져야 하는 너란 녀석...&amp;quot;시간 초과&amp;quot;&apos; src=&apos;/static/376bca85e0c64980eca9b1938d52594c/213b2/time.png&apos; srcset=&apos;/static/376bca85e0c64980eca9b1938d52594c/e7570/time.png 170w,
/static/376bca85e0c64980eca9b1938d52594c/f46e7/time.png 340w,
/static/376bca85e0c64980eca9b1938d52594c/213b2/time.png 481w&apos; sizes=&apos;(max-width: 481px) 100vw, 481px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;문제의 난이도가 올라갈수록 친숙해져야 하는 너란 녀석...&amp;quot;시간 초과&amp;quot;&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;또, &apos;풀 수 있을 것 같은데?&apos;하고 호기롭게 도전했다가 막히는 경우도 종종 있다. 이런 코딩 테스트 문제들은 문제의 난이도를 올리기 위해 각종 제약 조건을 거는데, &lt;code class=&quot;language-text&quot;&gt;시간 제약&lt;/code&gt;과 &lt;code class=&quot;language-text&quot;&gt;공간 제약&lt;/code&gt;이 대표적이다. 때문에 내가 생각한 방식대로 풀고, 주어진 예제가 정답임에도 코드 제출을 하면 시간 초과나 메모리 초과라는 씁쓸한 결과가 나오곤 한다. &lt;del&gt;(시간/공간 복잡도에 관한 포스트는 추후에...)&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;완전 탐색&lt;/code&gt; 문제와 &lt;code class=&quot;language-text&quot;&gt;시뮬레이션&lt;/code&gt; 문제가 위에 서술한 까다로운 속성들을 모두 가지고 있는 대표적인 구현 문제라고 할 수 있다. &lt;code class=&quot;language-text&quot;&gt;완전 탐색&lt;/code&gt;은 &lt;strong&gt;모든 경우의 수를 전부 계산하는 방법&lt;/strong&gt;이고, &lt;code class=&quot;language-text&quot;&gt;시뮬레이션&lt;/code&gt;은 &lt;strong&gt;문제에서 제시한 알고리즘을 한 단계씩 그대로 수행하는 방법&lt;/strong&gt;이다.&lt;/p&gt;
&lt;h2 id=&quot;3-극복을-위한-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%EA%B7%B9%EB%B3%B5%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;3 극복을 위한 방법 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3. 극복을 위한 방법&lt;/h2&gt;
&lt;h3 id=&quot;3-1-구현-방법이-떠오르지-않는-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-1-%EA%B5%AC%ED%98%84-%EB%B0%A9%EB%B2%95%EC%9D%B4-%EB%96%A0%EC%98%A4%EB%A5%B4%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;3 1 구현 방법이 떠오르지 않는 이유 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3-1. 구현 방법이 떠오르지 않는 이유&lt;/h3&gt;
&lt;p&gt;어느 문제가 안 그렇겠냐마는, 그중에서도 특히 구현 유형의 문제는 사용하는 언어 자체의 숙련도가 문제 풀이 여부를 좌우한다고 해도 과언이 아니다. 예를 들어, 파이썬&lt;code class=&quot;language-text&quot;&gt;Python&lt;/code&gt;으로 문제 풀이를 할 때 각종 표준 라이브러리에 대한 지식이 없다면, N개의 원소가 들어 있는 리스트에서 R개의 원소를 뽑는 경우를 구해야 하는 순열&lt;code class=&quot;language-text&quot;&gt;Permutations&lt;/code&gt;문제를 만났을 때 당황할 수밖에 없다. 파이썬에서 제공하는 표준 라이브러리인 &lt;code class=&quot;language-text&quot;&gt;itertools&lt;/code&gt; 모듈을 사용하면 간단하게 끝날 일인데 말이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/3466c357e07b4b95b20f18e065132b9f/56d4e/studying-child.jpg&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 66.47058823529413%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAEEA//EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdBzlYw//8QAGRAAAwEBAQAAAAAAAAAAAAAAAQIDABEj/9oACAEBAAEFAqIWVreuMRUiCo/Bv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EAB0QAAEEAgMAAAAAAAAAAAAAAAEAEBEhAxIiQWH/2gAIAQEABj8CHLWPUMYurLGVI6b/xAAYEAADAQEAAAAAAAAAAAAAAAAAAREhMf/aAAgBAQABPyFQqzaEKRdIfB9HA+ckK5dFNaP/2gAMAwEAAgADAAAAEEDP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGRABAAMBAQAAAAAAAAAAAAAAAQARITFh/9oACAEBAAE/EEP8iTe1V7C9qMj49Y4MO5tvSHR6RVU9luI5yUyyperP/9k=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Knowledge is Power&apos; title=&apos;필자는 구현 유형을 정복하기 위해서는 정공법만이 답이라고 생각한다. 공부, 또 공부.&apos; src=&apos;/static/3466c357e07b4b95b20f18e065132b9f/56d4e/studying-child.jpg&apos; srcset=&apos;/static/3466c357e07b4b95b20f18e065132b9f/0b705/studying-child.jpg 170w,
/static/3466c357e07b4b95b20f18e065132b9f/31389/studying-child.jpg 340w,
/static/3466c357e07b4b95b20f18e065132b9f/56d4e/studying-child.jpg 640w&apos; sizes=&apos;(max-width: 640px) 100vw, 640px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;필자는 구현 유형을 정복하기 위해서는 정공법만이 답이라고 생각한다. 공부, 또 공부.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-2-시간과-공간을-정복하기-위해서는&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-2-%EC%8B%9C%EA%B0%84%EA%B3%BC-%EA%B3%B5%EA%B0%84%EC%9D%84-%EC%A0%95%EB%B3%B5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4%EC%84%9C%EB%8A%94&quot; aria-label=&quot;3 2 시간과 공간을 정복하기 위해서는 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3-2. 시간과 공간을 정복하기 위해서는&lt;/h3&gt;
&lt;p&gt;우선, 나는 코딩 테스트에서 메모리 초과가 나는 경우는 드물다고 생각한다. 대부분의 경우 메모리 초과보다 시간 초과가 먼저 발생하기 때문이다. 게다가, 메모리 초과가 자주 날 수 있는 문제는 채점하는 서버에도 부하가 크기 때문에 취업을 위한 코딩 테스트에선 메모리 초과 걱정을 할 필요는 없다고 본다 &lt;del&gt;(물론 이는 내가 C/C++이나 자바가 아닌 파이썬으로 코딩 테스트를 준비해서일 것이다)&lt;/del&gt;. 따라서 나는 공간보다 시간 복잡도를 우선해서 생각하는 편이다.&lt;/p&gt;
&lt;p&gt;코딩 테스트에는 풀이 시간이 제한되어 있다는 점을 직시하고, 코드를 작성하기 전에 시간 복잡도를 우선적으로 고려해야 이 제약을 극복할 수 있겠다. 문제에서 주어진 시간/메모리 제한을 확인하지 않고 문제부터 본 뒤에 &apos;풀 수 있겠는데?&apos;하고 덤볐다간 열심히 작성한 코드도 날리고, 시간도 날리는 불상사가 생기기 때문이다. &lt;del&gt;그렇다. 내 이야기다.&lt;/del&gt;&lt;/p&gt;
&lt;h4 id=&quot;기타-시간-절약-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%B0%ED%83%80-%EC%8B%9C%EA%B0%84-%EC%A0%88%EC%95%BD-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;기타 시간 절약 방법 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;기타 시간 절약 방법&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;나는 파이썬을 이용하여 코딩 테스트를 준비하고 있으므로 파이썬을 기준으로 설명하겠다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&quot;PyPy3-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#PyPy3-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;PyPy3 사용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;PyPy3 사용하기&lt;/h5&gt;
&lt;p&gt;백준과 같은 문제 풀이 사이트에서는 Python3 외에도 PyPy3를 지원하는 경우가 있다. PyPy3는 Python3의 문법을 그대로 지원하면서도 실행 속도는 더 빠르다. 따라서 Python3으로 통과하지 못했던 코드가 PyPy3에서는 통과되는 경우가 종종 있다. 혹시 기업 코딩 테스트를 응시할 때 PyPy3가 따로 존재한다면 이를 응시하는 것도 방법이겠다.&lt;/p&gt;
&lt;h5 id=&quot;input대신-sysstdinreadline-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#input%EB%8C%80%EC%8B%A0-sysstdinreadline-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;input대신 sysstdinreadline 사용하기 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;input()대신 sys.stdin.readline() 사용하기&lt;/h5&gt;
&lt;p&gt;파이썬에서 테스트 케이스를 입력받을 때 흔히 &lt;code class=&quot;language-text&quot;&gt;input()&lt;/code&gt;을 사용하는데, 파이썬 표준 라이브러리인 &lt;code class=&quot;language-text&quot;&gt;sys&lt;/code&gt; 모듈의 &lt;code class=&quot;language-text&quot;&gt;stdin&lt;/code&gt;을 사용하면 입력 속도가 빨라진다.&lt;/p&gt;
&lt;h2 id=&quot;4-결론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%EA%B2%B0%EB%A1%A0&quot; aria-label=&quot;4 결론 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;4. 결론&lt;/h2&gt;
&lt;p&gt;이래저래 장황하게 설명했지만 결국 구현 문제의 핵심은 &lt;strong&gt;숙련&lt;/strong&gt;이라고 생각한다. 위에서 언급한 구현 문제의 특징은 어떤 알고리즘에서든 나타날 수 있는 것이기 때문에, 실제 구현 문제를 만났을 때 당황하지 않도록 관련된 많은 문제를 풀어 보아야겠다.&lt;/p&gt;
&lt;h2 id=&quot;5-참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;5 참고 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;5. 참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;나동빈, 『이것이 취업을 위한 코딩 테스트다 with 파이썬』, 한빛미디어(2020), p104-110.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[[Algorithm] Greedy Algorithm (그리디 알고리즘, 탐욕법)]]></title><description><![CDATA[이 포스팅의 목표는 필자가 알고리즘을 공부하며 습득한 내용을 정리하는 데 있습니다. 따라서 틀린 내용이 있을 수 있습니다. 틀린 내용을 발견하신 경우 댓글로 지적해 주시면 감사하겠습니다.…]]></description><link>https://www.itsmo.dev/greedy-algorithm/</link><guid isPermaLink="false">https://www.itsmo.dev/greedy-algorithm/</guid><pubDate>Sun, 08 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;이 포스팅의 목표는 필자가 알고리즘을 공부하며 습득한 내용을 정리하는 데 있습니다. 따라서 틀린 내용이 있을 수 있습니다. 틀린 내용을 발견하신 경우 댓글로 지적해 주시면 감사하겠습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 427px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/bd607fd9c8b9e446211e0c542f164c2c/86b21/greedy-man.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 150%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHQElEQVR42o1UWVdaWRrlf1RX0okRR0QNMoiAOAGiCARFAUWJIqKITGoEFZyHVokaoyYajRrnMaRinNImXdWrV2etXv1Wv6Oo57P7QGpVdz10dT/sxTn3cvfZ3/72dxiZSQmEAv8VzF+Q9LsgmckJYCfeizL+F2F2ygM8TGMiKyUxvmcz7/+K3xI++H3C2AeC7DTk52ZCzEkFNzUBXFYicjlp4GemgEMP+f8J6UseOxmCzCQI0h5AkpGCcrEAshw2cimxMDsZ+QK6zk79lTDrPwl/I5++yLh3B1kP7kBbJIG3xRpHr8uBoLcDvsYGVBaJIcpKiZNy0pmxav5NGNtwWUlfS6DmZ9z5Bhx6gLOpAeHRIfTazOg1KtGhksJbo0Jfuw0jPZ1w1tVQtffjlbCZCSTmdZyQPiCxk2LISb6PXHYK3K1WvHo+D1+1nKx16nAaMuHIr8dpoBqvXBpMuizosTXCXC5HLrUkj8siEn4G9ZgZZYh5LEKBGDjJ96AukyHY6YHPrEfYyMG7oAbv+svxlv6ej7TgfdCCSJ8BPYZyDHd7oZXmgp/+gEiFWRDlpEcZBcIsUiLhQpCRBF4qE5baGrjqa2HO/hbLDRzsdiqw6lXjYtyEzX4rWQnYScRvwFOnCb0eN3ocNuSlJ8YVirmsKENZKCSqEjF4SfeRz30Ie50BfW4nWgqyyVJDLtmfaUXkVQ9mPfU4mPVgZbINocp8TDjN6Pf7sTA5jurifJJLEyHmZUQZpZRQIeGBQzusLBCjs9mC0d5u9LZZSZeCj+MZKwKNcnSppTgZd8BrLIVNko62Gi0ZDfbj9dICOsxGwk9PQD6fHWXoykqIqkCE7Pt3oZEXIdDeQiPShqnhIbQpRPCreFjyO7DteYTNgBWjtmpiEyaixajHeCiEF3NzCDjsJC+T+VWhSacm2uICsO9+A42iiGauCUoBFyVCPhqrKqiaNNKlkSLsbMaYtRYGQSqpFOVA+jALrZY6TPb1wNNQS6RcFkQxD2OEVaUlYP/xDygrlsbzJ0hhxgNeIStCo7EarWYj9jU5eKbMIfV1RugrlOAk3EW1SomQrwNOQxXJYzFpfGiXG+urSZ1OhZyYh4Vi2ClBXjITrHvfokjIQ0utHt3uDmw+EuFNnYL4PC400f+I2OlQUwF9PhcsqlIizkyGPJ8XZVgtNeSxSUdVJaKMNsXRUIvinGykUwuErFRoi/NhUJXC3mBGLVVUR9XVP6qAIDkRWnkxAp1uqMQCohBzoVYUxBTqSbOlBiJWMsoL6ezSXGklIsKiI8ill4JcIkRbowXTI8NwNjehlpKpZIV07JKgU8jQTWe8XMQnynw+1PL8KKP5sYHYm02QZrGgLimAt80GjVRC95kQUIW6MjnGgiEszEzjicuJxloj5CIhZDwOtIqSeG7VVKFaLoG2lCo0astIg7ESJdwsaJUyuGiXtZI8PH6kgkWrIi3UcL/DjhjazYb4/HoaTKhWKvCoVAav3Qq9vASyPB70StnPjPneNrI65ECovQlyfg6qaIQ6TSq8menC5lgbVunsPqcZXB9oxe6MH/tP+7A25IZNIYZZrUQnFRBo0mGSTtKQw/wz43Z7gnz3sh9nY+146yrFibscF34dFm2lWPTX43y5C9+frOFmPYjIvBtjdj1Ouqrww2AtPvhrcP6kGnvuMrI31YzjhSc/Mf5+fUQO54dx61fjx3A9fpyuw8eAFgvtVThdCOKft2f46+EMrl74cL39FCeLQ3huK8dfusvxD3phfBnRIeJRk+UOPfbn/FHG3y72yN64F7cBDW56dTj2anDo0WCzW4/D/kJyFWSTo4CQHPgp+oqwNfwYB+1KbLkrseFWY8suw+t2DenWivFy0BFlfLnaIwezQVx0VeDgCSWhRD0GJYL0EtjtzsX7rnvktTuTkglwPizEWagQdkUueRbowAUte7rDhAGzkpyvT+IorvDDDvlyc4ollwEBDR/LVjmcFTxMthTjcrIUey4m2fQJcDktw1tKeNj9EC/dRVhzi9CpyqG+DeLt8ii52ZhBZGk4yoi8GCDHUzbszw9gbdCJcYcJq/2NOJmw4HwoDzv0pj4dlGK7p5DsdmZiv19GLqf0eD9UiNfjXfi88wwfN2fIyZAKZ3PuKON4zkvWaVdPwi583l3A570lfNqew6fdJWwMWnE4asLV6jDFIC6XfHg378PZswBu3izgaiWEvZAO15tPyfeHYfz5YOEr4dGME/tTLhwNlCEypsbl+jRuKenZnAeRiUpcrI7Q2Ezi4/YizsLtOB4z4GYjjIuVQXx40Y/rnTD54e0KLjfClHDWS/YnWnAy24WLRR+ulry4oh9fr09Q0nnc7i7jZEyP7aAaN5tUxZtZ+pyWuUEPpeubrTkcjRrJ1Uo/Ll796ae4wv3JVhxNOxFZDFFjB2lJT6iqUXzcClO1E4gsBxB5GcKHtTGqbDoO6tsv6ylcb8yQTztzeP9yLPovtOUIwI+RuzoAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;Greedy Man&apos; title=&apos;그리디 알고리즘은 현재 상황에서 가장 이득이 되는 방향으로 움직인다. 말 그대로 탐욕적으로.&apos; src=&apos;/static/bd607fd9c8b9e446211e0c542f164c2c/86b21/greedy-man.png&apos; srcset=&apos;/static/bd607fd9c8b9e446211e0c542f164c2c/e7570/greedy-man.png 170w,
/static/bd607fd9c8b9e446211e0c542f164c2c/f46e7/greedy-man.png 340w,
/static/bd607fd9c8b9e446211e0c542f164c2c/86b21/greedy-man.png 427w&apos; sizes=&apos;(max-width: 427px) 100vw, 427px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;그리디 알고리즘은 현재 상황에서 가장 이득이 되는 방향으로 움직인다. 말 그대로 탐욕적으로.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;1-서론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EC%84%9C%EB%A1%A0&quot; aria-label=&quot;1 서론 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1. 서론&lt;/h2&gt;
&lt;p&gt;그리디&lt;code class=&quot;language-text&quot;&gt;Greedy&lt;/code&gt; 알고리즘은 단순 무식하게, 현재 상황에서 최선의 선택만을 하는 알고리즘이다. 그리디 알고리즘은 매 순간 최선의 선택만을 하므로, &lt;strong&gt;이후의 상황에 대해서는 전혀 고려하지 않는다&lt;/strong&gt;.&lt;br&gt;
그리디 알고리즘은 모든 상황을 고려하는 것이 아니기 때문에 시간을 크게 절약할 수 있다. 허나 그리디 알고리즘의 유형은 매우 다양하기 때문에, 특정 문제를 만났을 때 이 문제가 그리디 알고리즘으로 해결 가능한지를 파악할 수 있어야 한다.&lt;/p&gt;
&lt;h2 id=&quot;2-그리디-알고리즘의-조건&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%98-%EC%A1%B0%EA%B1%B4&quot; aria-label=&quot;2 그리디 알고리즘의 조건 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2. 그리디 알고리즘의 조건&lt;/h2&gt;
&lt;p&gt;그리디 알고리즘을 사용하기 위해서는 크게 2가지 조건을 만족해야 한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;탐욕스러운 선택 속성(Greedy Choice Property)&lt;/strong&gt;
&lt;blockquote&gt;
&lt;p&gt;현재의 선택이 이후의 선택에 영향을 주지 않아야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;최적 부분 구조(Optimal Substructure)&lt;/strong&gt;
&lt;blockquote&gt;
&lt;p&gt;전체 문제의 최적 해결 방안이 부분 문제의 최적 해결 방안이어야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위 조건이 성립하지 않는다면, 그리디 알고리즘으로 해결할 수 없다.&lt;/p&gt;
&lt;h2 id=&quot;3-그리디-알고리즘의-정당성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%98-%EC%A0%95%EB%8B%B9%EC%84%B1&quot; aria-label=&quot;3 그리디 알고리즘의 정당성 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3. 그리디 알고리즘의 정당성&lt;/h2&gt;
&lt;p&gt;그리디 알고리즘의 &lt;strong&gt;최선의 선택&lt;/strong&gt;이라는 말이 어쩌면 말이 좋게 들릴 수 있겠지만, &lt;strong&gt;현재 상황&lt;/strong&gt;에서의 최선이기 때문에 오히려 함정에 빠질 수 있다. 예를 들어 보자.&lt;/p&gt;
&lt;h3 id=&quot;3-1-최소-경로-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-1-%EC%B5%9C%EC%86%8C-%EA%B2%BD%EB%A1%9C-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;3 1 최소 경로 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3-1. 최소 경로 문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 614px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/52e0582c2f8339e858aedb7828a6037f/c42f5/greedy-graph-ex.png&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 78.82352941176471%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACdElEQVR42o1U2XaiUBD0//8kD3mYHOeMD6Mmg6LGLS4RAfclmkSNoggKWlP3Km55mIHTR+2+FNVd1Ybwj2u/38s4J4CeO0R31oehGzAMA7VaDU9PT7Ic+l+wS9DVxxCz0QDZbA6pVArVahWqqmIymVwDXjHhtdvt0O120Ww2sVwuz2emX1iN36GT3XAwwNvbm2RqWdYBMAAS1IfDIWzblm/LZrOIx+OIRCJ4eXnB5+cnFosFrPUatuOg1+t96+rEcDqdyocrlQpM00Sn00E6nUYymYSiKMjlcjKn67pkUy6XZfi+f9WdBByPxygUCthut99aFixardZ1y8eaaLVUKl2NSgKKZAAWCHGr7m0u+Gw0GhhwjkEuJN4iqAcHfM/H1j0zFTMT8/Q8T/7euBvYS/tUFyNKJBJnQDGjhJJATa/B5m0OTCg5BQ7vzkcHyh8Fj4+P0AwNLu+CVsDdjzv5vf3eRiwWQzQalW6QLSdTKj2URoIg2kxDw2rAnJswVgbClTDUpAq9rkPJK6h/1WW9aTWhL3X8LIfJTkW1rkmmElDj/IpU852WuPXiZrORVsrn89Iyt3WXc69kMsjTHbP5/AC4pXpzKiwPU7lbAYSal9Y4xTG3en3F/Pk5sMVBZYer45OBy8E36TXJ4hhC/TWNfESUIV6y4FbIZwnoU7igLgF3dL1LpScs/rq/h3e0kEOgYrGIDNsajUYnlh7Bujy/ZmyCbbk0dtCux7Xz2m043ASPs2s/PCBOhX9TxRKtYbMTp16Hy/qW53Zc0f1x1qITMZrQhXODfyfsBUOGxTGI9RMMu9wWkdvx4attIkib4GId+/0+/gLzG7eG7BpmQgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;그리디 알고리즘으로 풀 수 없는 문제&apos; title=&apos;A에서 E로 가는 최소 경로를 그리디 알고리즘으로 구해 보자. 그리디로 푼 답과 실제 답이 일치할까?&apos; src=&apos;/static/52e0582c2f8339e858aedb7828a6037f/c42f5/greedy-graph-ex.png&apos; srcset=&apos;/static/52e0582c2f8339e858aedb7828a6037f/e7570/greedy-graph-ex.png 170w,
/static/52e0582c2f8339e858aedb7828a6037f/f46e7/greedy-graph-ex.png 340w,
/static/52e0582c2f8339e858aedb7828a6037f/c42f5/greedy-graph-ex.png 614w&apos; sizes=&apos;(max-width: 614px) 100vw, 614px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;A에서 E로 가는 최소 경로를 그리디 알고리즘으로 구해 보자. 그리디로 푼 답과 실제 답이 일치할까?&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;위와 같은 그래프가 있다고 가정하자. 각 노드 사이의 간선은 다음 노드까지의 거리를 나타낸다. A에서 E로 가는 최소 거리는 얼마인가? 우리는 이미 머릿속에서 모든 경우의 수를 다 더해 보았기 때문에 A-D-E가 최소 경로임을 알지만, 이를 현재 상황만 고려하는 그리디 알고리즘으로 해결한다고 생각해 보고 문제를 들여다 보자.&lt;br&gt;
A에서 B/C/D 각각의 노드로 이동하는 경로 중 최소 경로는 A-C이다. 그리디는 뒷일은 고려하지 않으므로 C로 가는 길을 택할 것이다.&lt;br&gt;
문제는 다음 경로에 있다. C에서 도착지인 E까지 가는 경로는 거리 15짜리 길 단 하나다. 이렇게 되면 그리디 알고리즘은 3+15인 18이 최소 경로라고 답할 것이다.&lt;br&gt;
당연하지만 이 문제는 그리디 알고리즘의 첫 번째 조건을 만족하지 못하기 때문에 그리디 알고리즘으로 풀 수 없다. 첫 번째 선택이 다음 경로 선택에 영향을 주기 때문이다.&lt;/p&gt;
&lt;h3 id=&quot;3-2-거스름돈-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#3-2-%EA%B1%B0%EC%8A%A4%EB%A6%84%EB%8F%88-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;3 2 거스름돈 문제 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;3-2. 거스름돈 문제&lt;/h3&gt;
&lt;p&gt;가장 많이 나오는 그리디 알고리즘 문제의 예로는 거스름돈 문제가 있다. 일례로 N원을 500원, 100원, 50원, 10원 화폐 단위로 거슬러 줄 때, 이 거스름돈으로 N원을 만드는 데 필요한 화폐 개수의 최솟값을 출력하는 문제가 그것이다.&lt;br&gt;
해당 문제는 큰 단위의 화폐부터 차례대로 거슬러 준다면 쉽게 해결이 가능하다. 그러나 이 문제는 거스름돈의 단위를 변경했을 때 그리디 알고리즘의 조건을 만족하지 않는 경우가 생긴다.&lt;br&gt;
예를 들어 800원을 거슬러 줘야 하는데 화폐 단위가 500원, 400원, 100원인 경우를 생각해 보자. 그리디 알고리즘으로 풀이한다면 800원을 거슬러 주기 위해서는 500원 동전 한 개, 100원 동전 세 개로 총 네 개의 동전이 필요한 데 반해 실제 필요한 최소 동전의 개수는 400원 동전 두 개이다.&lt;br&gt;
이 문제는 결국 &lt;strong&gt;큰 단위의 거스름돈이 작은 단위의 거스름돈의 배수가 되지 않기 때문&lt;/strong&gt;에 그리디 알고리즘의 두 번째 조건을 만족하지 못한다. 따라서 이런 경우는 다이나믹 프로그래밍&lt;code class=&quot;language-text&quot;&gt;DP&lt;/code&gt;과 같은 다른 알고리즘으로 해결해야 한다.&lt;/p&gt;
&lt;h2 id=&quot;4-그리디-문제의-판별법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#4-%EA%B7%B8%EB%A6%AC%EB%94%94-%EB%AC%B8%EC%A0%9C%EC%9D%98-%ED%8C%90%EB%B3%84%EB%B2%95&quot; aria-label=&quot;4 그리디 문제의 판별법 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;4. 그리디 문제의 판별법&lt;/h2&gt;
&lt;p&gt;앞서 서술했듯 그리디 알고리즘의 유형이 매우 다양하기 때문에, 문제를 마주쳤을 때 뚜렷한 문제 유형이 파악되지 않으면 그리디 알고리즘으로 풀 수 있는지 의심해봐야 한다. 만약 그리디 알고리즘으로 해결할 수 없을 것 같다면, 이후에 다이나믹 프로그래밍이나 그래프 알고리즘 등으로 풀이가 가능한 지 고민해보자.&lt;/p&gt;
&lt;h2 id=&quot;5-참고&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#5-%EC%B0%B8%EA%B3%A0&quot; aria-label=&quot;5 참고 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;5. 참고&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;나동빈, 『이것이 취업을 위한 코딩 테스트다 with 파이썬』, 한빛미디어(2020), p86-91.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[🎉 블로그 시작]]></title><description><![CDATA[…]]></description><link>https://www.itsmo.dev/blog-start/</link><guid isPermaLink="false">https://www.itsmo.dev/blog-start/</guid><pubDate>Mon, 12 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;1-블로그를-시작하려는-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%A5%BC-%EC%8B%9C%EC%9E%91%ED%95%98%EB%A0%A4%EB%8A%94-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;1 블로그를 시작하려는 이유 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1. 블로그를 시작하려는 이유&lt;/h2&gt;
&lt;p&gt;나는 글 쓰는 데 흥미가 없다. 몰입감 있게 글을 쓰지도 못할뿐더러, 무언가를 기록하는 행위 자체가 무의미하다고 생각했기 때문이다. 중요한 것은 머릿속에 저장해두면 그만이고, 만약 잊어버린다면 그건 나에게 있어 중요한 것이 아니었을 거라는 말도 안 되는 자기합리화가 있었다.&lt;/p&gt;
&lt;h3 id=&quot;1-1-인간은-망각의-동물이거늘&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-1-%EC%9D%B8%EA%B0%84%EC%9D%80-%EB%A7%9D%EA%B0%81%EC%9D%98-%EB%8F%99%EB%AC%BC%EC%9D%B4%EA%B1%B0%EB%8A%98&quot; aria-label=&quot;1 1 인간은 망각의 동물이거늘 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1-1. 인간은 망각의 동물이거늘&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&apos;gatsby-resp-image-figure&apos; style=&apos;margin-bottom: 16px;&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-wrapper&apos; style=&apos;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; &apos;&gt;
      &lt;a class=&apos;gatsby-resp-image-link&apos; href=&apos;/static/d07d6f7d7660a6668daee375ee740765/80c60/the-forgetting-curve.webp&apos; style=&apos;display: block&apos; target=&apos;_blank&apos; rel=&apos;noopener&apos;&gt;
    &lt;span class=&apos;gatsby-resp-image-background-image&apos; style=&quot;padding-bottom: 67.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRk4AAABXRUJQVlA4IEIAAABQAwCdASoUAA4APtFUo0uoJKMhsAgBABoJYwCdAB6SYKxsAAD+6UMPaLnTMBvMsF+lqQWCU8q9Xgai4ZCUQpjQAAA=&apos;); background-size: cover; display: block;&quot;&gt;&lt;/span&gt;
  &lt;img class=&apos;gatsby-resp-image-image&apos; alt=&apos;헤르만 에빙하우스의 망각곡선&apos; title=&apos;헤르만 에빙하우스의 망각곡선 | 출처:https://elearningindustry.com/forgetting-curve-combat&apos; src=&apos;/static/d07d6f7d7660a6668daee375ee740765/4c79d/the-forgetting-curve.webp&apos; srcset=&apos;/static/d07d6f7d7660a6668daee375ee740765/33073/the-forgetting-curve.webp 170w,
/static/d07d6f7d7660a6668daee375ee740765/719ab/the-forgetting-curve.webp 340w,
/static/d07d6f7d7660a6668daee375ee740765/4c79d/the-forgetting-curve.webp 680w,
/static/d07d6f7d7660a6668daee375ee740765/80c60/the-forgetting-curve.webp 1000w&apos; sizes=&apos;(max-width: 680px) 100vw, 680px&apos; style=&apos;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&apos; loading=&apos;lazy&apos; decoding=&apos;async&apos;&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&apos;gatsby-resp-image-figcaption&apos;&gt;헤르만 에빙하우스의 망각곡선 | 출처:https://elearningindustry.com/forgetting-curve-combat&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;하지만 인간은 망각의 동물. 중요한 것도 잊어버리는 것이 사람이 아닌가. 물론 나에게도 예외는 아니었다. 숙지했 &lt;del&gt;(다고 생각했)&lt;/del&gt; 던 알고리즘도 시간이 지나면 잊어버려 다시 머리를 싸매고, 며칠 후에 똑같은 짓을 반복한다. 분명 과거의 나는 중요하다고 생각해서 똑똑히 외워 두었을 텐데... 이런 적이 한두 번이 아니다 보니 결국 내 &quot;외우면 된다&quot; 신조에 금이 가기 시작했다.&lt;/p&gt;
&lt;h3 id=&quot;1-2-기록의-필요성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-2-%EA%B8%B0%EB%A1%9D%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1&quot; aria-label=&quot;1 2 기록의 필요성 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1-2. 기록의 필요성&lt;/h3&gt;
&lt;h4 id=&quot;어떻게-하면-잊어버리지-않을-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%9E%8A%EC%96%B4%EB%B2%84%EB%A6%AC%EC%A7%80-%EC%95%8A%EC%9D%84-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;어떻게 하면 잊어버리지 않을 수 있을까 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 하면 잊어버리지 않을 수 있을까?&lt;/h4&gt;
&lt;p&gt;나의 한계이자 인간의 한계인 망각. 이 크나큰 단점을 극복하기 위해선 결국 어딘가에 저장해야 했다. 컴퓨터에 저장 장치가 있듯이, 나에게 있어 내가 얻은 지식을 저장해 둘 수단은 결국 기록이었다. 다행히 오늘날 기록할 수단은 무궁무진했다. 노트 필기부터 시작해서 블로그와 음성 녹음, 영상 촬영까지. 내가 공부하고자 찾아보던 모든 것들이 결국은 기록 수단이었다. 그중에서도 나는 블로그를 나의 메인 기록 수단으로 선택했다.&lt;/p&gt;
&lt;h3 id=&quot;1-3-그래서-왜-블로그인데&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-3-%EA%B7%B8%EB%9E%98%EC%84%9C-%EC%99%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%9D%B8%EB%8D%B0&quot; aria-label=&quot;1 3 그래서 왜 블로그인데 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;1-3. 그래서 왜 블로그인데?&lt;/h3&gt;
&lt;p&gt;개인 공부를 위해서라면 간단히 노트에 필기하는 것만으로도 톡톡한 효과를 누릴 수 있을 터였다. 블로그는 모든 사람에게 공개된 만큼 뭔가 잘 써야만 할 것 같은 강박에 사로잡히기 십상이고, 결국 핵심 내용을 설명하기 위해 포장만 늘어지게 할 것이 뻔했다. 그럼에도 내가 블로그를 택한 이유는 다음과 같다.&lt;/p&gt;
&lt;h4 id=&quot;글쓰기-실력의-향상&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EC%93%B0%EA%B8%B0-%EC%8B%A4%EB%A0%A5%EC%9D%98-%ED%96%A5%EC%83%81&quot; aria-label=&quot;글쓰기 실력의 향상 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;글쓰기 실력의 향상&lt;/h4&gt;
&lt;p&gt;글쓰기야 뭐 노트 필기로도 충분히 향상될 수 있는 것 아니냐는 사람들이 있을 수도 있다. 그러나 노트 필기는 나만 알아보면 그만이지만 블로그는 모든 사람을 상대로 공개되는 글이기 때문에 글에 기승전결이 있어야 한다. 내가 어째서 글을 쓰게 되었고 그래서 얻은 것이 무엇인지에 대한 기록. 그런 논리정연한 글을 쓴다면 글쓰기 실력이 조금은 늘지 않을까?&lt;/p&gt;
&lt;h4 id=&quot;재야의-고수들의-피드백&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%AC%EC%95%BC%EC%9D%98-%EA%B3%A0%EC%88%98%EB%93%A4%EC%9D%98-%ED%94%BC%EB%93%9C%EB%B0%B1&quot; aria-label=&quot;재야의 고수들의 피드백 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;재야의 고수들의 피드백&lt;/h4&gt;
&lt;p&gt;내 글을 보고 지식과 영감을 얻어 가는 분들도 계시겠지만, 반대로 댓글을 통해 새로운 지식을 주시는 재야의 고수님들 또한 계실 것이다. 그러한 피드백은 내 사고를 넓혀 줄 것이다. 이런 고급 피드백은 노트 필기로는 얻기 힘들 것이다.&lt;/p&gt;
&lt;h4 id=&quot;as-is-portfolio&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#as-is-portfolio&quot; aria-label=&quot;as is portfolio permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;as-is portfolio&lt;/h4&gt;
&lt;p&gt;기록이 쌓이면 결국 그 자체로 포트폴리오가 된다. 개발자로서 블로그를 해야 하는 이유이기도 하다. 블로그를 통해 기록하고, 기록을 통해 나를 나타내는 것. 내가 블로그를 통해 이루고 싶은 궁극적인 목표이다.&lt;/p&gt;
&lt;h2 id=&quot;2-앞으로의-계획&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-%EC%95%9E%EC%9C%BC%EB%A1%9C%EC%9D%98-%EA%B3%84%ED%9A%8D&quot; aria-label=&quot;2 앞으로의 계획 permalink&quot; class=&quot;heading-anchor before&quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;15&quot; height=&quot;15&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z&quot;/&gt;&lt;/svg&gt;&lt;/a&gt;2. 앞으로의 계획&lt;/h2&gt;
&lt;p&gt;블로그를 개설하긴 했지만 사실 나는 나만의 블로그를 만들고 싶었다. 명색이 개발자인데 다른 사람이 만든 테마를 가져다 쓰자니 자존심이 허락하지 않았다. 그렇게 며칠간 블로그를 만들기 위해 삽질하다가, 핵심을 놓치고 있다는 생각이 문득 들었다. 기록하기 위해 블로그를 시작하려는 건데, 블로그를 만든답시고 기록은 뒷전이 되어버린 것이다.&lt;br&gt;
블로그 만들기가 하루아침에 되는 것도 아니고, 신경 써야 할 부분이 한두 군데가 아닌 데다가 그걸 빠르게 만들 정도로 실력이 좋지도 못했다. 메타인지가 필요한 시점이었다. 결국 나는 나만의 블로그 만들기를 미뤄 두고 제일 마음에 들었던 &lt;a href=&quot;https://github.com/devHudi&quot;&gt;Hudi&lt;/a&gt;님의 &lt;a href=&quot;https://github.com/devHudi/gatsby-starter-hoodie&quot;&gt;gatsby-starter-hoodie&lt;/a&gt; 테마를 사용하기로 했다.&lt;br&gt;
따라서 앞으로 블로그를 운영하면서 중장기적인 목표로 &lt;strong&gt;블로그 테마 만들기&lt;/strong&gt; 를 도전해 보려고 한다. 이 목표가 헛되지 않도록 꾸준히 공부하고 기록해야겠다.&lt;/p&gt;</content:encoded></item></channel></rss>