<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[제멋대로맛 초코볼]]></title><description><![CDATA[이것저것 하고 싶은 개발자의 기술블로그]]></description><link>https://ambosing.github.io/</link><generator>GatsbyJS</generator><lastBuildDate>Tue, 30 Apr 2024 08:21:09 GMT</lastBuildDate><author><![CDATA[Ambosing]]></author><item><title><![CDATA[Spring Boot openai starter로 ChatGPT 쉽게 사용하기]]></title><description><![CDATA[스프링 부트 AI 정복해보자구]]></description><link>https://ambosing.github.io/spring/openai/</link><guid isPermaLink="false">https://ambosing.github.io/spring/openai/</guid><category><![CDATA[Spring]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Mon, 11 Mar 2024 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;글을-쓰게-된-동기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B8%80%EC%9D%84-%EC%93%B0%EA%B2%8C-%EB%90%9C-%EB%8F%99%EA%B8%B0&quot; aria-label=&quot;글을 쓰게 된 동기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;글을 쓰게 된 동기&lt;/h2&gt;
&lt;p&gt;스프링으로 ChatGPT API를 사용해서 기능을 사용해야 하는 경우가 생겼습니다..! 그래서 RestTemplate과 WebClient 중 비동기를 사용할 수 있고 Non-Blocking을 지원하는 WebClient로 구현하려고 시도했습니다. 하지만 어떠한 이유 때문인지 WebClient Header에 Api 키를 넣었음에도 불구하고 계속 응답을 BadRequest로 받았습니다.&lt;/p&gt;
&lt;p&gt;그러던 와중에 Spring에서 제공해주는 spring.ai.openai 의존성이 있다는 것을 알게 되었고, 하루 꼬박 걸렸던.. 제 오류는 금방 해결할 수 있어서 다른 분들도 쉽게 할 수 있으면 좋겠다라고 생각해서 이렇게 블로그 글을 남깁니다!&lt;/p&gt;
&lt;h2 id=&quot;spring-ai로-chatgpt-환경설정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spring-ai%EB%A1%9C-chatgpt-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95&quot; aria-label=&quot;spring ai로 chatgpt 환경설정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Spring AI로 ChatGPT 환경설정&lt;/h2&gt;
&lt;h3 id=&quot;dependancy-설정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dependancy-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;dependancy 설정하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dependancy 설정하기&lt;/h3&gt;
&lt;h3 id=&quot;pomxml&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#pomxml&quot; aria-label=&quot;pomxml permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;pom.xml&lt;/h3&gt;
 &lt;div class=&quot;code-header&quot;&gt;
   &lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;xml&quot;&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependencyManagement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;org.springframework.ai&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;spring-ai-bom&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;0.8.0&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;pom&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;import&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;scope&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependencies&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependencyManagement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;gradle&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#gradle&quot; aria-label=&quot;gradle permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Gradle&lt;/h3&gt;
 &lt;div class=&quot;code-header&quot;&gt;
   &lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;gradle&quot;&gt;&lt;pre class=&quot;language-gradle&quot;&gt;&lt;code class=&quot;language-gradle&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;implementation&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation-string&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;org.springframework.ai:spring-ai-bom:0.8.0&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;implementation&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;org.springframework.ai:spring-ai-openai&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.spring.io/spring-ai/reference/getting-started.html#dependency-management&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;스프링 공식 홈페이지&lt;/a&gt;에서는 Gradle에서는 특정한 버전을 써주지 않아도 문제 없다고 하는데 제가 시도했을 때는 위와 같이 버전을 지정해주니 잘 동작했습니다!&lt;br&gt;
제 환경만 그럴 수도 있으니 한 번 빼고 동작해보시는 것도 추천합니다. (버전은 최신 버전 추천!)&lt;/p&gt;
&lt;h2 id=&quot;spring-boot-ai-chatgpt-chat-실행해보기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spring-boot-ai-chatgpt-chat-%EC%8B%A4%ED%96%89%ED%95%B4%EB%B3%B4%EA%B8%B0&quot; aria-label=&quot;spring boot ai chatgpt chat 실행해보기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Spring Boot AI ChatGPT Chat 실행해보기&lt;/h2&gt;
&lt;h3 id=&quot;chat-properties-설정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#chat-properties-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;chat properties 설정하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Chat Properties 설정하기&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;spring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;openai&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;base-url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; base&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;url &lt;span class=&quot;token comment&quot;&gt;# 기본 값 : api.openai.com&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;api-key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;key 입력 &lt;span class=&quot;token comment&quot;&gt;# 필수 &lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;chat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; gpt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 모델 입력 # 필수&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;# 아래는 세부 GPT 모델 설정 값&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;temperature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
          &lt;span class=&quot;token key atrule&quot;&gt;frequencyPenalty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
          &lt;span class=&quot;token key atrule&quot;&gt;presencePenalty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
          &lt;span class=&quot;token key atrule&quot;&gt;maxTokens&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
          &lt;span class=&quot;token key atrule&quot;&gt;topP&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;위에 사용하지 않은 Properties들이 존재하니 아래 링크를 참조하면 좋을 것 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.spring.io/spring-ai/reference/api/clients/openai-chat.html#_connection_properties&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;스프링 AI Propreties&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;spring-boot-ai-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spring-boot-ai-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;spring boot ai 사용하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Spring Boot AI 사용하기&lt;/h2&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 annotation punctuation&quot;&gt;@RestController&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ChatController&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;OpenAiChatClient&lt;/span&gt; chatClient&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token annotation punctuation&quot;&gt;@Autowired&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ChatController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;OpenAiChatClient&lt;/span&gt; chatClient&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;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chatClient &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; chatClient&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 annotation punctuation&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/ai/generate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&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;Map&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@RequestParam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; defaultValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Tell me a joke&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; message&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 class-name&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;generation&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; chatClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&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;// Stream 형식으로 보내주기&lt;/span&gt;
    &lt;span class=&quot;token annotation punctuation&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/ai/generateStream&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&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;Flux&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;ChatResponse&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;generateStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation punctuation&quot;&gt;@RequestParam&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; defaultValue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Tell me a joke&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; message&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;Prompt&lt;/span&gt; prompt &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;Prompt&lt;/span&gt;&lt;span class=&quot;token punctuation&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;UserMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&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;return&lt;/span&gt; chatClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;prompt&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 방법 말고도 아래와 같이 ChatClient를 직접 만들어 사용하는 것도 가능합니다.&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;var&lt;/span&gt; openAiApi &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;OpenAiApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;OPENAI_API_KEY&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Properties에 적었던 설정 값들을 직접 명시하여 생성&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; chatClient &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;OpenAiChatClient&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;openAiApi&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withDefaultOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;OpenAiChatOptions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;builder&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 function&quot;&gt;withModel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gpt-35-turbo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withTemperature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withMaxTokens&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;build&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 class-name&quot;&gt;ChatResponse&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; chatClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&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;Prompt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Generate the names of 5 famous pirates.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Stream 응답으로 보내기&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Flux&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;ChatResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; chatClient&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;token punctuation&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;Prompt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Generate the names of 5 famous pirates.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;소감&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%86%8C%EA%B0%90&quot; aria-label=&quot;소감 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;소감&lt;/h2&gt;
&lt;p&gt;이렇게 Spring Boot에서 제공해주는 AI 의존성에 대해서 알아보았습니다.&lt;br&gt;
생각보다 저는 삽질을 많이 했는데 모든 정보를 공식문서부터 찾아보는 습관이 아직은 되어 있지 않은 것 같아서 이번에 반성을 하게 되었습니다.&lt;br&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;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.spring.io/spring-ai/reference/api/clients/openai-chat.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;스프링 AI Docs&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Java 멀티 스레딩 환경에서 Data Race]]></title><description><![CDATA[아니 이런게 있었다니.. Data Race]]></description><link>https://ambosing.github.io/java/datarace/</link><guid isPermaLink="false">https://ambosing.github.io/java/datarace/</guid><category><![CDATA[Java]]></category><category><![CDATA[MultiThreading]]></category><category><![CDATA[Data Race]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Wed, 08 Nov 2023 15:00:00 GMT</pubDate><content:encoded>&lt;p&gt;오늘은 강의를 듣고 있다가 Data Race라는 용어를 처음들어봐서 이렇게 정리하게 되었습니다.&lt;br&gt;
멀티스레딩 환경에서 발생하는 문제입니다.&lt;br&gt;
일단 이 글에서는 JAVA 기준으로 설명되어 있습니다. :)&lt;/p&gt;
&lt;h2 id=&quot;멀티스레딩-환경에서의-공유자원&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%94%A9-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%EA%B3%B5%EC%9C%A0%EC%9E%90%EC%9B%90&quot; aria-label=&quot;멀티스레딩 환경에서의 공유자원 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;멀티스레딩 환경에서의 공유자원&lt;/h2&gt;
&lt;p&gt;Data Race를 이해하기 위해서는 먼저 멀티스레딩 환경에서 어떤 부분을 공유하고 있는지를 알고 있어야 합니다.&lt;br&gt;
일단 메모리에 있는 Heap영역에 할당된 자원들은 모두 멀티스레딩 환경에서 공유됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;객체들&lt;/li&gt;
&lt;li&gt;Class 멤버 변수&lt;/li&gt;
&lt;li&gt;Static 변수&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;위와 같은 요소들이 공유자원이 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;비순차적-명령어-처리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B9%84%EC%88%9C%EC%B0%A8%EC%A0%81-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%B2%98%EB%A6%AC&quot; aria-label=&quot;비순차적 명령어 처리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;비순차적 명령어 처리&lt;/h2&gt;
&lt;p&gt;비순차적 명령어 처리가 Data Race에 원인이 되므로 이것도 먼저 알아봅시다.&lt;/p&gt;
&lt;p&gt;먼저 비순차적 명령어 처리는 명령어 파이프라인에서 발생하므로 명령어 파이프라인부터 알아봅시다.&lt;/p&gt;
&lt;p&gt;CPU는 병렬적으로 명령어를 실행하는 명령어 파이프라인을 사용합니다.
명령어 파이프라인을 사용하지 않았을 때 아래와 같이 실행시간이 매우 길어지기 때문입니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/83de5a7b5566dbe7195a98d7b25825cd/74e18/2023-11-09-11-21-59.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 29.166666666666668%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRkoAAABXRUJQVlA4ID4AAADwAgCdASoUAAYAPtFUo0uoJKMhsAgBABoJaQAAetCIAAD+8X2J3AkwyGlqA9lTjaySjjp87sqSWmMzQEAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/83de5a7b5566dbe7195a98d7b25825cd/a59e9/2023-11-09-11-21-59.webp 192w,
/static/83de5a7b5566dbe7195a98d7b25825cd/0ca9f/2023-11-09-11-21-59.webp 384w,
/static/83de5a7b5566dbe7195a98d7b25825cd/dc9b9/2023-11-09-11-21-59.webp 768w,
/static/83de5a7b5566dbe7195a98d7b25825cd/74e18/2023-11-09-11-21-59.webp 1047w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/83de5a7b5566dbe7195a98d7b25825cd/a59e9/2023-11-09-11-21-59.webp 192w,
/static/83de5a7b5566dbe7195a98d7b25825cd/0ca9f/2023-11-09-11-21-59.webp 384w,
/static/83de5a7b5566dbe7195a98d7b25825cd/dc9b9/2023-11-09-11-21-59.webp 768w,
/static/83de5a7b5566dbe7195a98d7b25825cd/74e18/2023-11-09-11-21-59.webp 1047w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/83de5a7b5566dbe7195a98d7b25825cd/dc9b9/2023-11-09-11-21-59.webp&quot;
            alt=&quot;명령어 파이프라인 사용 X&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;[혼공운체] 명령어 파이프라인 사용 X&lt;/div&gt;
&lt;p&gt;명령어 파이프라인을 사용하면 아래와 같이 빠르게 실행할 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 533px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/75099e724e34fedb25b3d667019b2492/aaa87/2023-11-09-11-23-14.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlYAAABXRUJQVlA4IEoAAACQAwCdASoUAAsAPtFUo0uoJKMhsAgBABoJaQAAUvnW66uofVYgAP7zwnoASrXTxXAz72WGnkRy1oX2EgsxsSGmNyYr3z/MRwAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/75099e724e34fedb25b3d667019b2492/a59e9/2023-11-09-11-23-14.webp 192w,
/static/75099e724e34fedb25b3d667019b2492/0ca9f/2023-11-09-11-23-14.webp 384w,
/static/75099e724e34fedb25b3d667019b2492/aaa87/2023-11-09-11-23-14.webp 533w&quot;
              sizes=&quot;(max-width: 533px) 100vw, 533px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/75099e724e34fedb25b3d667019b2492/a59e9/2023-11-09-11-23-14.webp 192w,
/static/75099e724e34fedb25b3d667019b2492/0ca9f/2023-11-09-11-23-14.webp 384w,
/static/75099e724e34fedb25b3d667019b2492/aaa87/2023-11-09-11-23-14.webp 533w&quot;
            sizes=&quot;(max-width: 533px) 100vw, 533px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/75099e724e34fedb25b3d667019b2492/aaa87/2023-11-09-11-23-14.webp&quot;
            alt=&quot;명령어 파이프라인 사용 O&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;[혼공운체] 명령어 파이프라인 사용 O&lt;/div&gt;
&lt;p&gt;&lt;mark&gt;비순차적 명령어 처리&lt;/mark&gt;는 명령어 파이프라인에서 사용되는 명령어 병렬처리 기법입니다.
먼저 예시를 보며 이해를 돕겠습니다.&lt;/p&gt;
&lt;p&gt;예를들어 아래와 같은 명령어들로 이루어진 소스 코드가 있다고 해봅시다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/865351e85f66fddb40042cac744a4461/8f82d/2023-11-09-11-28-08.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.541666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlIAAABXRUJQVlA4IEYAAACwAwCdASoUAAgAPtFWo0uoJKMhsAgBABoJZwAAXKPYyDgi9oz0wAD+85PnYt5HdKyUuWBFpn6KVS1PoQzJCJbjOb5HAAAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/865351e85f66fddb40042cac744a4461/a59e9/2023-11-09-11-28-08.webp 192w,
/static/865351e85f66fddb40042cac744a4461/0ca9f/2023-11-09-11-28-08.webp 384w,
/static/865351e85f66fddb40042cac744a4461/dc9b9/2023-11-09-11-28-08.webp 768w,
/static/865351e85f66fddb40042cac744a4461/8f82d/2023-11-09-11-28-08.webp 923w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/865351e85f66fddb40042cac744a4461/a59e9/2023-11-09-11-28-08.webp 192w,
/static/865351e85f66fddb40042cac744a4461/0ca9f/2023-11-09-11-28-08.webp 384w,
/static/865351e85f66fddb40042cac744a4461/dc9b9/2023-11-09-11-28-08.webp 768w,
/static/865351e85f66fddb40042cac744a4461/8f82d/2023-11-09-11-28-08.webp 923w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/865351e85f66fddb40042cac744a4461/dc9b9/2023-11-09-11-28-08.webp&quot;
            alt=&quot;비순차적 명령어 처리 X&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;위는 명령어 처리할 때 3번의 명령어가 1번, 2번 명령어에 의존하고 있기 때문에 3번 명령어를 처리하기 위해 나머지 4, 5, 6 명령어들이 기다리고 있게 됩니다.&lt;/p&gt;
&lt;p&gt;그래서 CPU는 효율적으로 처리하기 위해 아래와 같이 명령어의 순서를 바꿉니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e84056b627cac9bae14408442a69971b/9aca0/2023-11-09-11-30-57.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 42.708333333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlQAAABXRUJQVlA4IEgAAAAwAwCdASoUAAkAPtFUo0uoJKMhsAgBABoJaQAAetHPPgAAAP7xCEJGEmPos35XqH2l6yB6O+esNP/sbQQQXu3/KNUYIqW4AAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/e84056b627cac9bae14408442a69971b/a59e9/2023-11-09-11-30-57.webp 192w,
/static/e84056b627cac9bae14408442a69971b/0ca9f/2023-11-09-11-30-57.webp 384w,
/static/e84056b627cac9bae14408442a69971b/dc9b9/2023-11-09-11-30-57.webp 768w,
/static/e84056b627cac9bae14408442a69971b/9aca0/2023-11-09-11-30-57.webp 777w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/e84056b627cac9bae14408442a69971b/a59e9/2023-11-09-11-30-57.webp 192w,
/static/e84056b627cac9bae14408442a69971b/0ca9f/2023-11-09-11-30-57.webp 384w,
/static/e84056b627cac9bae14408442a69971b/dc9b9/2023-11-09-11-30-57.webp 768w,
/static/e84056b627cac9bae14408442a69971b/9aca0/2023-11-09-11-30-57.webp 777w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/e84056b627cac9bae14408442a69971b/dc9b9/2023-11-09-11-30-57.webp&quot;
            alt=&quot;비순차적 명령어 처리&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이렇게 되면 4, 5, 6 명령어는 기다리지 않고, 바로 실행할 수 있게 됩니다.&lt;/p&gt;
&lt;p&gt;아무 명령어나 순서를 바꾸지는 않고, 코드의 의존성으로 문제가 되지 않을 때만 변경합니다.&lt;/p&gt;
&lt;h2 id=&quot;data-race&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-race&quot; aria-label=&quot;data race permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data Race&lt;/h2&gt;
&lt;p&gt;&lt;mark&gt;Data Race란 &lt;/mark&gt; 여러 프로세스/스레드가 공유된 데이터를 읽고 쓰는 작업을 할 때 실행 순서에 따라서 잘못된 값을 읽거나 쓰게 되는 상황입니다.&lt;/p&gt;
&lt;h3 id=&quot;data-race가-발생하는-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-race%EA%B0%80-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%83%81%ED%99%A9&quot; aria-label=&quot;data race가 발생하는 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data Race가 발생하는 상황&lt;/h3&gt;
&lt;p&gt;말로만 들으면 이해가 잘 되지 않으니 코드 예시를 보면서 Data Race가 발생하는 상황을 봅시다.&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 keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SharedClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 공유 자원&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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;// Thread1&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;increment&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;
            x&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            y&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 comment&quot;&gt;// Thread2&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkForDataRace&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;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;y &gt; x - 데이터 레이스가 감지됨!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;클래스 멤버 변수는 공유 자원으로 여기서 x, y는 공유 자원이 됩니다. 그리고 increment 메서드와 checkForDataRace 메서드는 각각의 스레드로 병렬적으로 실행하게 만들겁니다.&lt;/p&gt;
&lt;p&gt;여기서 이제 메서드들을 한 번 살펴보면 여러 경우로 결과가 나눠지는 경우가 있습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6ff144659b829f710d40035f0f7324e2/0b34d/2023-11-09-13-41-49.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRjgAAABXRUJQVlA4ICwAAACwAgCdASoUAAsAPtFUo0uoJKMhsAgBABoJaQAAeyAA/vKRyNYNXhby/58QAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/6ff144659b829f710d40035f0f7324e2/a59e9/2023-11-09-13-41-49.webp 192w,
/static/6ff144659b829f710d40035f0f7324e2/0ca9f/2023-11-09-13-41-49.webp 384w,
/static/6ff144659b829f710d40035f0f7324e2/dc9b9/2023-11-09-13-41-49.webp 768w,
/static/6ff144659b829f710d40035f0f7324e2/e2c2f/2023-11-09-13-41-49.webp 1152w,
/static/6ff144659b829f710d40035f0f7324e2/f3efb/2023-11-09-13-41-49.webp 1536w,
/static/6ff144659b829f710d40035f0f7324e2/0b34d/2023-11-09-13-41-49.webp 1920w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/6ff144659b829f710d40035f0f7324e2/a59e9/2023-11-09-13-41-49.webp 192w,
/static/6ff144659b829f710d40035f0f7324e2/0ca9f/2023-11-09-13-41-49.webp 384w,
/static/6ff144659b829f710d40035f0f7324e2/dc9b9/2023-11-09-13-41-49.webp 768w,
/static/6ff144659b829f710d40035f0f7324e2/e2c2f/2023-11-09-13-41-49.webp 1152w,
/static/6ff144659b829f710d40035f0f7324e2/f3efb/2023-11-09-13-41-49.webp 1536w,
/static/6ff144659b829f710d40035f0f7324e2/0b34d/2023-11-09-13-41-49.webp 1920w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/6ff144659b829f710d40035f0f7324e2/dc9b9/2023-11-09-13-41-49.webp&quot;
            alt=&quot;case1&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;순차적으로 실행되면 당연히 &lt;code class=&quot;language-text&quot;&gt;Y &gt; X&lt;/code&gt;보다 큰 경우는 없고, &lt;code class=&quot;language-text&quot;&gt;X == Y&lt;/code&gt;라는 결과만 갖게 됩니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;다른 경우가 또 있습니다. 예를 들어, increment를 실행하는 도중에 checkForDataRace 메서드의 조건문이 실행되는 것이죠. 멀티스레딩 환경이기 때문에 병렬적으로 실행이 이루어져 이런 상황도 있습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d855766df6cc80a6aebaf50187ff22a5/0b34d/2023-11-09-13-49-53.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRjgAAABXRUJQVlA4ICwAAACwAgCdASoUAAsAPtFUo0uoJKMhsAgBABoJaQAAeyAA/vKRyNYNXhby/58QAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/d855766df6cc80a6aebaf50187ff22a5/a59e9/2023-11-09-13-49-53.webp 192w,
/static/d855766df6cc80a6aebaf50187ff22a5/0ca9f/2023-11-09-13-49-53.webp 384w,
/static/d855766df6cc80a6aebaf50187ff22a5/dc9b9/2023-11-09-13-49-53.webp 768w,
/static/d855766df6cc80a6aebaf50187ff22a5/e2c2f/2023-11-09-13-49-53.webp 1152w,
/static/d855766df6cc80a6aebaf50187ff22a5/f3efb/2023-11-09-13-49-53.webp 1536w,
/static/d855766df6cc80a6aebaf50187ff22a5/0b34d/2023-11-09-13-49-53.webp 1920w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/d855766df6cc80a6aebaf50187ff22a5/a59e9/2023-11-09-13-49-53.webp 192w,
/static/d855766df6cc80a6aebaf50187ff22a5/0ca9f/2023-11-09-13-49-53.webp 384w,
/static/d855766df6cc80a6aebaf50187ff22a5/dc9b9/2023-11-09-13-49-53.webp 768w,
/static/d855766df6cc80a6aebaf50187ff22a5/e2c2f/2023-11-09-13-49-53.webp 1152w,
/static/d855766df6cc80a6aebaf50187ff22a5/f3efb/2023-11-09-13-49-53.webp 1536w,
/static/d855766df6cc80a6aebaf50187ff22a5/0b34d/2023-11-09-13-49-53.webp 1920w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/d855766df6cc80a6aebaf50187ff22a5/dc9b9/2023-11-09-13-49-53.webp&quot;
            alt=&quot;case2&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;이 경우에는 X만 1증가한 상태라서 &lt;code class=&quot;language-text&quot;&gt;Y &amp;lt; X&lt;/code&gt;가 된 상태인거죠.&lt;br&gt;
그래서 checkForDataRace 메서드의 &lt;code class=&quot;language-text&quot;&gt;Y &gt; X&lt;/code&gt;는 만족하지 않습니다.&lt;/p&gt;
&lt;p&gt;그러면 어떠한 경우에도 &lt;code class=&quot;language-text&quot;&gt;Y &gt; X&lt;/code&gt;는 만족하지 않아서 절대 &lt;code class=&quot;language-text&quot;&gt;System.out.println(&quot;y &gt; x - 데이터 레이스가 감지됨!!&quot;);&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;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataRaceProblem&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&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 punctuation&quot;&gt;]&lt;/span&gt; args&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;SharedClass&lt;/span&gt; sharedClass &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;SharedClass&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;Thread&lt;/span&gt; thread1 &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;Thread&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 punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_VALUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&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;
                sharedClass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;increment&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;// increment Thread&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;Thread&lt;/span&gt; thread2 &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;Thread&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 punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MAX_VALUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&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;
                sharedClass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;checkForDataRace&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;// checkForDataRace Thread&lt;/span&gt;

        thread1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&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;
        thread2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&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;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SharedClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;increment&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;
            x&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            y&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 keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkForDataRace&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;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;y &gt; x - 데이터 레이스가 감지됨!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token 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;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;y &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; 데이터 레이스가 감지됨&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
y &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; 데이터 레이스가 감지됨&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&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;Y &gt; X&lt;/code&gt;를 만족하는 경우가 있다는 것입니다.&lt;/p&gt;
&lt;p&gt;어떻게 이런 결과가 나올 수 있을까요?&lt;br&gt;
그 이유는 바로 &lt;mark&gt;비순차적 명령어 처리&lt;/mark&gt;때문입니다.&lt;br&gt;
increment메서드의 내용을 한 번 다시 봅시다.&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 keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;increment&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;
    x&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    y&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;increment메서드의 안에 x++, y++은 서로 의존적이지 않습니다. 그래서 컴파일러 최적화 과정에서 비순차적 명령어 처리가 충분히 일어날 수 있는 부분입니다. &lt;mark&gt;그래서 x++, y++ 순서대로 처리가 되는 것이 아닌 비순차적 처리 때문에 y++, x++로 처리가 되는 경우가 있어 Data Race가 발생하게 됩니다.&lt;/mark&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/636c7ecc4307ae004dc505430212dd31/0b34d/2023-11-09-14-15-02.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 56.25%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRjgAAABXRUJQVlA4ICwAAACwAgCdASoUAAsAPtFUo0uoJKMhsAgBABoJaQAAeyAA/vKRyNIZOKgxNAAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/636c7ecc4307ae004dc505430212dd31/a59e9/2023-11-09-14-15-02.webp 192w,
/static/636c7ecc4307ae004dc505430212dd31/0ca9f/2023-11-09-14-15-02.webp 384w,
/static/636c7ecc4307ae004dc505430212dd31/dc9b9/2023-11-09-14-15-02.webp 768w,
/static/636c7ecc4307ae004dc505430212dd31/e2c2f/2023-11-09-14-15-02.webp 1152w,
/static/636c7ecc4307ae004dc505430212dd31/f3efb/2023-11-09-14-15-02.webp 1536w,
/static/636c7ecc4307ae004dc505430212dd31/0b34d/2023-11-09-14-15-02.webp 1920w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/636c7ecc4307ae004dc505430212dd31/a59e9/2023-11-09-14-15-02.webp 192w,
/static/636c7ecc4307ae004dc505430212dd31/0ca9f/2023-11-09-14-15-02.webp 384w,
/static/636c7ecc4307ae004dc505430212dd31/dc9b9/2023-11-09-14-15-02.webp 768w,
/static/636c7ecc4307ae004dc505430212dd31/e2c2f/2023-11-09-14-15-02.webp 1152w,
/static/636c7ecc4307ae004dc505430212dd31/f3efb/2023-11-09-14-15-02.webp 1536w,
/static/636c7ecc4307ae004dc505430212dd31/0b34d/2023-11-09-14-15-02.webp 1920w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/636c7ecc4307ae004dc505430212dd31/dc9b9/2023-11-09-14-15-02.webp&quot;
            alt=&quot;case 3&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;data-race-해결-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#data-race-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;data race 해결 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Data Race 해결 방법&lt;/h2&gt;
&lt;p&gt;Data Race의 해결 방법에는 두 가지가 있습니다.&lt;/p&gt;
&lt;details&gt;&lt;summary&gt;&lt;mark&gt;메서드에 Synchroized 키워드 사용하기&lt;/mark&gt;&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;한 번에 하나의 스레드만이 블록 또는 메서드에 진입할 수 있도록 보장합니다.&lt;/li&gt;
&lt;li&gt;임계 영역에 진입하는 스레드는 다른 스레드가 해당 블록 또는 메서드에 접근하지 못하게 합니다.&lt;/li&gt;
&lt;li&gt;락을 사용하여 동기화를 구현하므로 상대적으로 무겁고 오버헤드가 큽니다.&lt;/li&gt;
&lt;li&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 keyword&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;synchronizedMethod&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;br&gt;
&lt;details&gt;&lt;summary&gt;&lt;mark&gt;변수에 Volatile 키워드 사용하기&lt;/mark&gt;&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;변수를 메모리에서 읽거나 쓸 때 항상 메인 메모리를 참조하도록 보장합니다.&lt;/li&gt;
&lt;li&gt;캐시된 값 사용을 방지하여 변수의 일관성을 제공합니다.&lt;/li&gt;
&lt;li&gt;volatile 키워드를 사용한 변수는 원자적으로 읽기 및 쓰기 연산이 수행됩니다.&lt;/li&gt;
&lt;li&gt;단순한 변수의 상태를 보장하며, 복합 연산에 대해서는 synchronized가 더 적합합니다.&lt;/li&gt;
&lt;li&gt;비순차적 명령어 처리하는 경우,&lt;br&gt;
volatile 변수에 대한 쓰기 명령 이전의 명령들은 reordering 이후에도 volatile 변수에 대한 쓰기 명령 이전에 실행되도록 유지됩니다.&lt;br&gt;
volatile 변수에 대한 읽기 명령 이후의 명령들은 reordeing 이후에도 volatile 변수에 대한 읽기 명령 이후에 실행되도록 유지합니다.&lt;br&gt;
-&gt; 즉, 비순차적 명령어 처리가 발생하지 않는 것을 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-header&quot;&gt;
   &lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&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;volatile&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; sharedVal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;method&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;// volatile 명령어 이전에 있는 명령어들은 volatile 명령어 접근 전에 실행되도록 보장&lt;/span&gt;
  read&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sharedVal&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;// volatile 명령어 이후에 있는 명령어들은 volatile 명령어 접근 후에 실행되도록 보장&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;여기서는 두 개의 스레드로 한 메서드를 실행하는 Race Condition이 아니므로 두 메서드에 Synchronize 키워드로 동시 실행을 막지 않아도 됩니다. 그래서 Lock를 덜 잡는 Volatile를 사용해서 Data Race를 해결해보겠습니다.&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 keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SharedClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 변경된 부분&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;volatile&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 변경된 부분&lt;/span&gt;

      &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;increment&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;
          x&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          y&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 keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkForDataRace&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;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;y &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; x&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;y &gt; x - 데이터 레이스가 감지됨!!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token 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;y &gt; x&lt;/code&gt;조건을 만족하지 못해&lt;code class=&quot;language-text&quot;&gt;System.out.println(&quot;y &gt; x - 데이터 레이스가 감지됨!!&quot;);&lt;/code&gt;을 실행하지 않습니다.&lt;/p&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;p&gt;정리하자면, Data Race가 발생하는 이유는 CPU를 효율적으로 활용하기 위해 사용하고 있는 비순차적 명령어 처리가 이유입니다.
이러한 Data Race를 해결하기 위해서는 Synchronized, Volatile을 적용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;참고한 사이트&lt;br&gt;
Volatile : &lt;a href=&quot;https://ttl-blog.tistory.com/238&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;말랑님 블로그&lt;/a&gt;&lt;br&gt;
Data Race : &lt;a href=&quot;https://www.udemy.com/course/java-multi-threading/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Udemy 강의&lt;/a&gt;&lt;br&gt;
명령어 파이프라인 : 혼자 공부하는 컴퓨터 구조 및 운영체제&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Lazy Evaluation 지연 계산법]]></title><description><![CDATA[지연 계산법 너는 무엇이냐!]]></description><link>https://ambosing.github.io/others/lazy_evaluation/</link><guid isPermaLink="false">https://ambosing.github.io/others/lazy_evaluation/</guid><category><![CDATA[Others]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Tue, 19 Sep 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가며&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EB%A9%B0&quot; aria-label=&quot;들어가며 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가며&lt;/h2&gt;
&lt;p&gt;Lazy Evaluation은 예전에 조건문에서 두 개의 조건이 존재할 때 AND에서는 앞 조건이 False라고 하는 경우 뒤 조건을 안하는 경우를 Early Termination이라고 들은 적이 있었습니다. 그 때 비슷한 최적화의 형태로 Lazy Evaluation가 있다고 들었었는데요.&lt;br&gt;
뭔가 다른 건가 싶기도 했었습니다. 한참 데이터 쪽으로 공부하고 있을 때 spark에 대해서 공부한 적이 있었는데요. spark는 Lazy Evaluation을 지원해서 좋다고 합니다. 아니 그래서 뭐가 좋은건지도 모르지 말고 이번에는 공부하면서 블로그에 정리하려고 합니다. &lt;del&gt;역시 공부는 호기심&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;참고:&lt;br&gt;
&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%8A%90%EA%B8%8B%ED%95%9C_%EA%B3%84%EC%82%B0%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Lazy Evaluation 정의&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://edykim.com/ko/post/introduction-to-lodashs-delay-evaluation-by-filip-zawada/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;그림 동작 및 예제 : edykim님 블로그&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;lazy-evaluation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lazy-evaluation&quot; aria-label=&quot;lazy evaluation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lazy Evaluation&lt;/h2&gt;
&lt;p&gt;컴퓨터 프로그래밍에서 &lt;mark&gt;느긋한 계산법(Lazy Evaluation)&lt;/mark&gt;은 계산의 결과값이 필요할 때까지 계산을 늦추는 기법입니다. 반대말로는 Eager Evaluation(즉시 연산, 조급한 연산)이 존재합니다.&lt;/p&gt;
&lt;p&gt;먼저 장단점을 알면 편하므로 장단점을 정리해보겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;장점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%A5%EC%A0%90&quot; aria-label=&quot;장점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;장점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;효율성&lt;/strong&gt;: 필요한 값만 계산하므로 불필요한 연산을 피할 수 있습니다. 예를 들어, 무한한 리스트에서 처음 10개의 요소만 필요한 경우, lazy evaluation을 사용하면 실제로 10개의 요소만 계산됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;모듈화와 조합성&lt;/strong&gt;: 계산을 나중에 실행하게 되면, 프로그램의 여러 부분을 더 쉽게 조합하거나 재사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;무한한 자료구조&lt;/strong&gt;: Lazy evaluation을 사용하면 무한한 크기의 자료구조를 생성하고, 필요한 부분만 사용할 수 있습니다. 예를 들어, Haskell(프로그래밍 언어)에서 무한한 리스트를 정의하고 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;가능한 결과 생성&lt;/strong&gt;: Lazy evaluation은 아직 계산되지 않은 결과를 표현할 수 있어, 연산의 가능한 결과를 모두 나열하고 나중에 특정 결과를 선택할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;단점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%8B%A8%EC%A0%90&quot; aria-label=&quot;단점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;예측하기 어려운 성능&lt;/strong&gt;: 연산이 언제 실행될지 예측하기가 어렵기 때문에, 프로그램의 성능을 예측하거나 분석하기가 어려울 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;메모리 사용&lt;/strong&gt;: 연산이 아직 실행되지 않았다는 것을 표시하기 위한 내부 데이터 구조가 추가적인 메모리를 사용할 수 있습니다. 이로 인해 메모리 사용이 증가할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;디버깅 어려움&lt;/strong&gt;: Lazy evaluation의 동작 방식 때문에, 오류를 디버깅하기가 어려울 수 있습니다. 오류의 원인이 되는 코드와 오류가 실제로 발생하는 시점 사이에 시간 차이가 있을 수 있기 때문입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;부작용&lt;/strong&gt;: 부작용(side-effects)를 가진 연산과 lazy evaluation이 혼합될 때, 부작용의 발생 시점과 순서를 예측하기 어려울 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이렇게 장단점을 알아봤습니다. 그런데 이 장점 중 왜 효율적일까, 무한한 자료구조는 어떻게 하는 걸까에 대해서 중점적으로 알아보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;lazy-evaluation은-어떻게-효율적으로-동작하는걸까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lazy-evaluation%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94%EA%B1%B8%EA%B9%8C&quot; aria-label=&quot;lazy evaluation은 어떻게 효율적으로 동작하는걸까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lazy Evaluation은 어떻게 효율적으로 동작하는걸까&lt;/h2&gt;
&lt;p&gt;자바 예제부터 보겠습니다.
아래의 자바 코드는 정수의 List에서 10보다 작은 것 중 3개만 가져오는 코드입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&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;final&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;Integer&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 class-name&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stream&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 function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;모르는 사람이 처음 위의 코드를 접했을 때 위 코드 동작 방식을&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;반복을 통해 Array에서 요소들 중 10보다 작은 값을 구하고&lt;/li&gt;
&lt;li&gt;그 중 3개만 가져옵니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;라고 생각할 수 있지만 그렇지 않습니다.&lt;br&gt;
그렇지 동작하지 않는 이유를 알기 위해 출력해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&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;final&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;Integer&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 class-name&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stream&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 function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &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 class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;i: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; &amp;lt; 10&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;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;i&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
i&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
i&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
i&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
i&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위는 출력해본 결과입니다! 이를 통해 조건에 맞는 것을 찾으면 종료한다는 것을 알 수 있습니다.&lt;br&gt;
이 동작을 그림으로 표현한 것이 있어서 가져왔습니다.&lt;br&gt;
출처는 맨 위에 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://farm1.staticflickr.com/499/19802991361_f410fb2ae6_o.gif?w=660&amp;#x26;ssl=1&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;위 코드를 그림으로 나타낸것입니다.
그림을 보면 출력 결과와 같이 동작한다는 것을 알 수 있습니다.&lt;br&gt;
어찌보면 3개를 취했을 때 반복문이 종료되므로 더 효율적으로 종료될 수 있는 것입니다!&lt;/p&gt;
&lt;p&gt;이를 메모리 관점에서는 동작이 다르겠지만 로직 처리쪽으로만 본다면 아래의 코드처럼 나타낼 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&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;final&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;Integer&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 class-name&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&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;final&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;Integer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; newList &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 keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&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; i&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 class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;list[i]: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; &amp;lt; 10&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&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 number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        newList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&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;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newList&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&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;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newList&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;출력결과&lt;/p&gt;
&lt;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;list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;출력결과를 보면 동일한 것을 알 수 있습니다.&lt;br&gt;
Lazy Evaluation을 통해 조건을 만족하면 반복문이 종료되는 것을 알 수 있습니다.&lt;br&gt;
이를 통해 효율성을 챙기는 것입니다.&lt;/p&gt;
&lt;p&gt;그럼 이번에는 메모리 관점으로 어떻게 무한한 자료구조를 쓸 수 있는지 보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;lazy-evaluation은-어떻게-무한한-자료구조를-만들-수-있을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lazy-evaluation%EC%9D%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%AC%B4%ED%95%9C%ED%95%9C-%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;lazy evaluation은 어떻게 무한한 자료구조를 만들 수 있을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lazy Evaluation은 어떻게 무한한 자료구조를 만들 수 있을까?&lt;/h2&gt;
&lt;p&gt;아래는 파이썬의 제너레이터로 작성한 자료구조와 리스트 컴프리헨션으로 만든 리스트의 메모리를 비교한 것입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; sys

&lt;span class=&quot;token comment&quot;&gt;# 제너레이터&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;generate_numbers&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;for&lt;/span&gt; x &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000000&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;yield&lt;/span&gt; x


gen &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; generate_numbers&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getsizeof&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gen&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 string&quot;&gt;&quot;bytes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1000000&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sys&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getsizeof&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numbers&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 string&quot;&gt;&quot;bytes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;출력 결과&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token number&quot;&gt;112&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bytes&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;8448728&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;bytes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;출력결과를 보면 알 수 있듯이 Lazy Evaluation을 활용한 제너레이터는 리스트로 만든 결과와는 다르게 메모리 차이가 큽니다.
이는 Lazy Evaluation이 무한한 자료구조를 가질 수 있다는 단서가 됩니다!!&lt;/p&gt;
&lt;p&gt;제너레이터의 동작을 보면, 제너레이터는 순차적으로 값이 필요할 때 생성하는 프로세스, 매커니즘에 가깝습니다.
그래서 다음 값이 필요할 때 값에 대한 연산을 하고 가져오기 때문에 메모리를 신경쓰지 않고 자료구조를 만들 수 있는 겁니다!&lt;/p&gt;
&lt;p&gt;즉 정리하자면, 리스트로 만든 자료구조는 미리 100만개의 정수 자료형을 메모리에 올리는 것이고 제너레이터는 100만 개를 처리할 프로세스를 만들고 그걸 메모리에 올린 뒤 필요할 때 가져다 쓰는 방식이라고 이해하시면 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;lazy-evaluation이-쓰이는-곳&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lazy-evaluation%EC%9D%B4-%EC%93%B0%EC%9D%B4%EB%8A%94-%EA%B3%B3&quot; aria-label=&quot;lazy evaluation이 쓰이는 곳 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Lazy Evaluation이 쓰이는 곳&lt;/h2&gt;
&lt;p&gt;Lazy evaluation은 다양한 컴퓨팅 분야에서 사용되며, 특히 다음과 같은 곳에서 사용됩니다!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;함수형 프로그래밍 언어&lt;/mark&gt;: Haskell(프로그래밍 언어)은 lazy evaluation을 기본 평가 전략으로 사용하는 가장 잘 알려진 함수형 프로그래밍 언어입니다. 여기서 lazy evaluation은 무한한 자료구조 생성, 고차원 함수 조합 등 다양한 표현력을 제공합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;스트림 처리&lt;/mark&gt;: Java 8 이후의 Stream API나 Python의 generator와 같은 프로그래밍 언어의 특성에서 lazy evaluation이 사용됩니다. 이들은 필요할 때만 데이터를 처리하도록 설계되었습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;데이터베이스 시스템&lt;/mark&gt;: 데이터베이스 쿼리의 최적화에서 lazy evaluation이 사용될 수 있습니다. 예를 들면, 특정 조건에 맞는 첫 번째 항목만 필요한 경우 전체 데이터셋을 스캔하지 않고, 조건을 만족하는 첫 번째 항목을 찾자마자 종료할 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;빅 데이터 처리&lt;/mark&gt;: Apache Spark와 같은 빅 데이터 처리 프레임워크에서는 transformation 작업을 lazy하게 처리하고, 실제로 action이 호출될 때만 연산을 수행합니다. 이렇게 하면 연산의 최적화와 재사용이 가능합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;AI 및 기계 학습 프레임워크&lt;/mark&gt;: Tensorflow나 PyTorch와 같은 딥러닝 프레임워크에서는 연산 그래프를 먼저 정의하고, 실제로 데이터가 흐를 때만 연산을 수행합니다. 이는 lazy evaluation의 일종으로 볼 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;mark&gt;웹 브라우저 렌더링&lt;/mark&gt;: 웹 페이지의 컨텐츠 중 일부는 사용자가 스크롤하거나 특정 액션을 취할 때까지 로드되지 않을 수 있습니다. 이러한 “lazy loading”은 웹 페이지의 초기 로딩 시간을 단축하고 자원 사용을 최적화하는데 도움을 줍니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;p&gt;이렇게 Lazy Evaluation을 알아보았는데요. 저도 이렇게 알아보면서 많이 알게되었습니다.&lt;br&gt;
아무래도 대부분 프로그래밍하실 때는 Eager Evaluation을 생각하고 계실텐데요.&lt;br&gt;
이렇게 Lazy Evaluation으로 동작하는 것인지, Eager Evaluation으로 동작할지 한 번씩은 고민해보는 게 좋을 것 같네요!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[[Python] 파이썬 위치인자, 키워드인자]]></title><description><![CDATA[파이썬에서 파라미터 위치, 키워드로 고정시켜보기!]]></description><link>https://ambosing.github.io/python/position_keyword_parameter/</link><guid isPermaLink="false">https://ambosing.github.io/python/position_keyword_parameter/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Mon, 11 Sep 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;파이썬에는 함수의 파라미터를 키워드로 받을 수 있는 키워드인자, 위치로 받을 수 있는 위치 인자가 있습니다.&lt;br&gt;
이 두 개의 기능을 잘못 쓰게 되면 함수를 사용할 때 정말 헷갈리게 되는데요.&lt;br&gt;
이 부분을 책이 잘 설명해놓고 있어서 제가 약간 각색하여 정리해보려고 합니다!&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조하였습니다.&lt;br&gt;
만약 문제 발생시 글을 삭제처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;예시-코드-소개&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%88%EC%8B%9C-%EC%BD%94%EB%93%9C-%EC%86%8C%EA%B0%9C&quot; aria-label=&quot;예시 코드 소개 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;예시 코드 소개&lt;/h2&gt;
&lt;p&gt;여기에 있는 글을 이해하시기 쉽게 먼저 예제코드를 소개하려고 합니다.&lt;/p&gt;
&lt;p&gt;예제코드는 한 숫자를 다른 숫자로 나누는 코드입니다.&lt;br&gt;
그래서 어떤 경우에는 ZeroDivisionError 예외를 무시하고 무한대를 반환하고 싶고, 어떨 때는 Overflow 예외를 무시하고 대신 0을 반환하고 싶다고 합시다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_overflow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_zero_division&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;try&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; number &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; divisor
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; OverflowError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; ignore_overflow&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 number&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; ZeroDivisionError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; ignore_zero_division&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 builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;inf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ignore_overflow=true한 경우&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ignore_zero_division=true한 경우&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# inf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;키워드-인자-사용할-때-주의점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B8%EC%9E%90-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C-%EC%A3%BC%EC%9D%98%EC%A0%90&quot; aria-label=&quot;키워드 인자 사용할 때 주의점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;키워드 인자 사용할 때 주의점&lt;/h2&gt;
&lt;p&gt;저희가 평소 사용하는 인자는 위치인자인데요.&lt;br&gt;
위치로 인자를 결정하다보면 함수를 사용할 때 어떤 값으로 들어가는지 함수의 정의를 봐야 알 수 있는 경우가 많습니다.&lt;br&gt;
이를 보완하기 위해 나온 것이 키워드 인자인데요.&lt;br&gt;
키워드 인자는 명시적으로 인자의 이름을 정해준다는 장점이 있으나, 함수를 사용하는 부분에서 키워드를 작성하다 보니 코드가 길어지는 단점이 존재합니다.&lt;br&gt;
또한, 키워드 인자를 쓰면 주의할 사항이 있는데요. 바로 위치인자 뒤에 키워드 인자가 와야 한다는 것입니다. 바로 코드로 보시죠!!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 1. 에러&lt;/span&gt;
result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 2. 에러&lt;/span&gt;
result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 3. 정상&lt;/span&gt;
result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 4. 정상&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;함수는 기존 예시코드 함수를 사용했습니다!&lt;br&gt;
첫 번째 문제 코드의 경우, 키워드 인자를 사용했지만 함수 정의에서 ignore_zero_division가 있는데 인자에서는 값을 정해주지 않아 오류가 발생했습니다. 이 경우 아래와 같이 함수의 기본값을 정해주면 에러가 발생하지 않습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# ignore_zero_division에 기본값 False 적용&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_overflow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 번째 문제 코드의 경우에는 &lt;mark&gt;위치 인자가 키워드 인자 뒤에 와서 오류가 발생&lt;/mark&gt;합니다.
나머지 경우는 정상적으로 잘 동작합니다.&lt;/p&gt;
&lt;h2 id=&quot;키워드-인자-잘-사용하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B8%EC%9E%90-%EC%9E%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0&quot; aria-label=&quot;키워드 인자 잘 사용하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;키워드 인자 잘 사용하기!&lt;/h2&gt;
&lt;p&gt;키워드 인자는 선택적인 사항이므로 호출하는 쪽에서 명확성을 위해 키워드 인자를 꼭 쓸 수 없는 것이 문제입니다!&lt;br&gt;
복잡한 함수의 경우 호출자가 키워드만 사용하는 인자를 통해 의도를 명확히 밝히도록 요구하는 편이 좋습니다.&lt;br&gt;
키워드만 사용하는 인자는 키워드를 반드시 사용해 지정하게 하여, 위치 기반으로 지정할 수 없게 만드는 게 좋습니다.&lt;/p&gt;
&lt;p&gt;다음은 safe_division 함수가 키워드만 사용하는 인자만 받도록 만든 코드입니다.&lt;br&gt;
인자 목록에 있는 &lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt;기호는 위치 인자의 마지막과 키워드만 사용하는 인자의 시작을 구분해줍니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# divisor 전까지 위치 인자 / ignore부터 키워드 인자&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 기본값을 통해 인자를 꼭 받지 않아도 수정&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                  ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 파라미터 중 마지막 두 개의 파라미터는 ignore 옵션을 기본값으로 False 정해주었습니다!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;이제 이 함수를 호출하면 함수의 뒤에 두 개의 인자는 키워드 인자를 사용해야 합니다.&lt;br&gt;
위치 인자를 사용하게 되면 아래처럼 에러가 발생합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&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;# safe_division(1.0, 10**500, True, False)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# TypeError: safe_division() takes 2 positional arguments but 4 were given&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 정상 동작&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;위치-인자로-고정하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9C%84%EC%B9%98-%EC%9D%B8%EC%9E%90%EB%A1%9C-%EA%B3%A0%EC%A0%95%ED%95%98%EA%B8%B0&quot; aria-label=&quot;위치 인자로 고정하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;위치 인자로 고정하기!&lt;/h2&gt;
&lt;p&gt;이번에 수정한 safe_division 함수에도 문제가 있습니다.&lt;br&gt;
호출하는 쪽에서 이 함수의 앞에 있는 두 필수 파라미터&lt;code class=&quot;language-text&quot;&gt;(number, divisor)&lt;/code&gt;를 호출하면서 위치와 키워드를 혼용할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.4&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;divisor&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; number&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.4&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;나중에 요구 사항이 바뀌거나 원하는 스타일이 바뀌어서 맨 앞의 두 인자 이름을 변경할 수도 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# number -&gt; numerator, divisor -&gt; denominator 변경&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numerator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; denominator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;# 변경&lt;/span&gt;
                    ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 단순한 파라미터 이름 변경만으로도 number와 divisor 인자를 키워드로 호출하는 기존 호출 코드가 에러가 발생합니다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&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;
    safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;number&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; divisor&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
TypeError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; got an unexpected keyword argument &lt;span class=&quot;token string&quot;&gt;&apos;number&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;파이썬 3.8에는 위치로만 지정하는 인자가 존재합니다.&lt;/strong&gt;&lt;br&gt;
위치로만 지정하는 인자는 반드시 위치만 사용해 인자를 지정해야 하고 키워드 인자로는 쓸 수 없습니다.&lt;/p&gt;
&lt;p&gt;다음은 safe_division 함수를 처음 두 인자를 위치로만 지정하는 인자로 지정합니다.&lt;br&gt;
인자 목록의 &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; 기호는 위치로만 지정하는 인자의 끝을 표시합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numerator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; denominator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 변경&lt;/span&gt;
                    ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위치로만 지정하는 인자를 키워드를 사용해 지정하면 에러가 발생합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 1. 정상 동작&lt;/span&gt;
safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numerator&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; denominator&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 2. 에러 발생&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## 출력 결과&lt;/span&gt;
safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numerator&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; denominator&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 2. 에러 발생&lt;/span&gt;
TypeError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; safe_division&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; got some positional&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;only arguments passed &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; keyword arguments&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;numerator, denominator&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;만드는 API의 스타일이나 필요에 따라 두 인자 전달 방식을 모두 사용하면 가독성을 높이고 잡음도 줄일 수 있습니다.&lt;br&gt;
예를 들어, 다음 코드에서는 결과를 표시할 때 얼마나 많은 자릿수를 사용할지 결정하고자 반올림할 위치를 지정하는 인자를 safe_division에 추가할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;safe_division_e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numerator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; denominator&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    ndigits&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token 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;
                    ignore_overflow&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    ignore_zero_division&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        fraction &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; numerator &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; denominator         &lt;span class=&quot;token comment&quot;&gt;# 변경&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fraction&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ndigits&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;# 변경&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; OverflowError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; ignore_overflow&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 number&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; ZeroDivisionError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; ignore_zero_division&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 builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;inf&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위 함수에서 ndigits는 위치나 키워드를 사용해 전달할 수 있는 선택적인 파라미터이므로 어떤 방식으로든 함수 호출에 사용할 수 있습니다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division_e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division_e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; safe_division_e&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ndigits&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;정리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EB%A6%AC&quot; aria-label=&quot;정리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정리&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;키워드로만 지정해야 하는 &lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt; 인자를 사용하면 호출하는 쪽에서 특정 인자를 반드시 키워드를 사용해 호출하도록 강제할 수 있습니다.&lt;/li&gt;
&lt;li&gt;위치로만 지정해야 하는 &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt; 인자를 사용하면 호출하는 쪽에서 키워드를 사용해 인자를 지정하지 못하게 만들 수 있습니다.&lt;/li&gt;
&lt;li&gt;인자 목록에서 &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt; 사이에 있는 파라미터는 키워드를 사용해 전달해도 되고 위치를 기반으로 전달해도 됩니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Docker compose로 띄운 Kafka Log를 docker bindmount 사용해서 로컬에서 보기]]></title><description><![CDATA[Docker!!!!!!!!!!! 너무 편해요..!]]></description><link>https://ambosing.github.io/docker/docker_compose_volumes_establish_kafka/</link><guid isPermaLink="false">https://ambosing.github.io/docker/docker_compose_volumes_establish_kafka/</guid><category><![CDATA[Docker]]></category><category><![CDATA[Kafka]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Wed, 30 Aug 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;하게-된-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%98%EA%B2%8C-%EB%90%9C-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;하게 된 이유 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;하게 된 이유&lt;/h2&gt;
&lt;p&gt;카프카를 배워보려고 강의를 듣다가 VirtualBox와 Ubuntu로 설치하는 것이 힘들어보여서 Docker로 설치하였습니다.&lt;/p&gt;
&lt;p&gt;그러다 보니 강의 개발 환경과 많이 달라졌었는데요. 강의에서 Kafka Log를 보는 일도 있다고 해서 이 때마다 로그를 확인하러 가기가 너무 시간이 오래 걸릴 것 같아서 로그를 docker bindmount을 사용해 로컬에서 바로 볼 수 있도록 해보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;해결-과정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0-%EA%B3%BC%EC%A0%95&quot; aria-label=&quot;해결 과정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결 과정&lt;/h2&gt;
&lt;p&gt;먼저 로컬에 logs라는 디렉터리를 먼저 만들어줬습니다.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;mkdir logs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;이제 이 디렉토리를 도커 안에 있는 kafka log가 쌓이는 폴더와 연결해주겠습니다.&lt;/p&gt;
&lt;p&gt;그러려면 일단 &lt;code class=&quot;language-text&quot;&gt;confluentinc/cp-kafka&lt;/code&gt; 이 이미지 안에 어디에 로그가 쌓이는지 알아야 하는데요.&lt;/p&gt;
&lt;p&gt;구글링 후에 &lt;code class=&quot;language-text&quot;&gt;/var/lib/kafka/data&lt;/code&gt; 여기에 쌓인다는 걸 알게 되었습니다.
그럼 이제 docker compose 파일을 수정해주도록 하겠습니다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2&apos;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;zookeeper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; confluentinc/cp&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;zookeeper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;latest
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_SERVER_ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_CLIENT_PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2181&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_TICK_TIME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_INIT_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_SYNC_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;ports&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 string&quot;&gt;&quot;22181:2181&quot;&lt;/span&gt;

  &lt;span class=&quot;token key atrule&quot;&gt;kafka&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; confluentinc/cp&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;kafka&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;7.1.2
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&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; zookeeper
    &lt;span class=&quot;token key atrule&quot;&gt;ports&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 string&quot;&gt;&quot;29092:29092&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_BROKER_ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_ZOOKEEPER_CONNECT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zookeeper:2181&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_ADVERTISED_LISTENERS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//kafka&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9092&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;PLAINTEXT_HOST&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//localhost&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;29092&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_LISTENER_SECURITY_PROTOCOL_MAP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;PLAINTEXT_HOST&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;PLAINTEXT
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_INTER_BROKER_LISTENER_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# 이부분 추가&lt;/span&gt;
		&lt;span class=&quot;token key atrule&quot;&gt;volumes&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; ./logs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/var/lib/kafka/data&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 도커 컴포즈를 띄워보면..&lt;/p&gt;
&lt;p&gt;아래와 같은 에러가 발생합니다..!&lt;br&gt;
&lt;strong&gt;&lt;a href=&quot;https://stackoverflow.com/questions/75499821/command-usr-local-bin-dub-path-var-lib-kafka-data-writable-failed-in-kafka&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Command [/usr/local/bin/dub path /var/lib/kafka/data writable] FAILED ! in Kafka&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;해결 방법을 모색한 결과, root 권한을 넣어주면 잘 된다는 얘기가 있어서&lt;/p&gt;
&lt;p&gt;아래와 같이 Root 권한을 추가해주었습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root 권한을 추가한 docker compose 파일&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;2&apos;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;zookeeper&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; confluentinc/cp&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;zookeeper&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;latest
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_SERVER_ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_CLIENT_PORT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2181&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_TICK_TIME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_INIT_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;ZOOKEEPER_SYNC_LIMIT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;ports&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 string&quot;&gt;&quot;22181:2181&quot;&lt;/span&gt;

  &lt;span class=&quot;token key atrule&quot;&gt;kafka&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; confluentinc/cp&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;kafka&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;7.1.2
		&lt;span class=&quot;token comment&quot;&gt;# Root 권한 &lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; root
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&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; zookeeper
    &lt;span class=&quot;token key atrule&quot;&gt;ports&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 string&quot;&gt;&quot;29092:29092&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_BROKER_ID&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_ZOOKEEPER_CONNECT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;zookeeper:2181&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_ADVERTISED_LISTENERS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//kafka&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;9092&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;PLAINTEXT_HOST&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//localhost&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;29092&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_LISTENER_SECURITY_PROTOCOL_MAP&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;PLAINTEXT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;PLAINTEXT_HOST&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;PLAINTEXT
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_INTER_BROKER_LISTENER_NAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; PLAINTEXT
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Docker bindmount&lt;/span&gt;
		&lt;span class=&quot;token key atrule&quot;&gt;volumes&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; ./logs&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/var/lib/kafka/data&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 잘 되더군요!&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;docker compose up&lt;/code&gt;을 통해 이제 도커 컨테이너를 띄우고 logs 디렉터리를 확인해보겠습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/25f5559428bbf56248d28901f6fa47e6/fab06/2023-08-31-22-13-18.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 38.020833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRkAAAABXRUJQVlA4IDQAAADwAgCdASoUAAgAPtFUo0uoJKMhsAgBABoJaWkfADdYAAD+8YnLISh82LwupIXsY0GvUgAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/25f5559428bbf56248d28901f6fa47e6/a59e9/2023-08-31-22-13-18.webp 192w,
/static/25f5559428bbf56248d28901f6fa47e6/0ca9f/2023-08-31-22-13-18.webp 384w,
/static/25f5559428bbf56248d28901f6fa47e6/dc9b9/2023-08-31-22-13-18.webp 768w,
/static/25f5559428bbf56248d28901f6fa47e6/e2c2f/2023-08-31-22-13-18.webp 1152w,
/static/25f5559428bbf56248d28901f6fa47e6/f3efb/2023-08-31-22-13-18.webp 1536w,
/static/25f5559428bbf56248d28901f6fa47e6/fab06/2023-08-31-22-13-18.webp 2000w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/25f5559428bbf56248d28901f6fa47e6/a59e9/2023-08-31-22-13-18.webp 192w,
/static/25f5559428bbf56248d28901f6fa47e6/0ca9f/2023-08-31-22-13-18.webp 384w,
/static/25f5559428bbf56248d28901f6fa47e6/dc9b9/2023-08-31-22-13-18.webp 768w,
/static/25f5559428bbf56248d28901f6fa47e6/e2c2f/2023-08-31-22-13-18.webp 1152w,
/static/25f5559428bbf56248d28901f6fa47e6/f3efb/2023-08-31-22-13-18.webp 1536w,
/static/25f5559428bbf56248d28901f6fa47e6/fab06/2023-08-31-22-13-18.webp 2000w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/25f5559428bbf56248d28901f6fa47e6/dc9b9/2023-08-31-22-13-18.webp&quot;
            alt=&quot;2023 08 31 22 13 18&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&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;#%EB%B0%B0%EC%9A%B4-%EC%A0%90&quot; aria-label=&quot;배운 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;배운 점&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;docker compose에 root 권한을 줄 수 있습니다.&lt;/li&gt;
&lt;li&gt;docker compose에 docker bindmount을 추가하는 방법을 깨달았습니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[파이썬에서 타임존 트러블 슈팅]]></title><description><![CDATA[세상에 이렇게 혼란스러운 일은 없었다..! 이 시간은 UTC인가 KST인가 아니면 또 다른 무엇인가]]></description><link>https://ambosing.github.io/python/timezone_ts/</link><guid isPermaLink="false">https://ambosing.github.io/python/timezone_ts/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Fri, 25 Aug 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;회사에서 Timezone을 UTC를 KST로 조작할 일이 있었습니다!&lt;br&gt;
그래서 간단하게 해결할 방법으로 timezone을 KST로 조작해주었습니다.&lt;br&gt;
하지만 예상하는 날짜 값이 도출된 것이 아니라 예상 날짜 값보다 하루가 전 날이 나왔습니다.&lt;/p&gt;
&lt;h2 id=&quot;왜-예상대로-안됐을까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EC%98%88%EC%83%81%EB%8C%80%EB%A1%9C-%EC%95%88%EB%90%90%EC%9D%84%EA%B9%8C&quot; aria-label=&quot;왜 예상대로 안됐을까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 예상대로 안됐을까&lt;/h2&gt;
&lt;p&gt;먼저 일단 예제로 제가 구성한 코드를 보시는 게 이해가 더 빠르실 거라 먼저 코드를 보여드리겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; datetime &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; timedelta
&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; dateutil &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; tz

local_tz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tz&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;gettz&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Asia/Seoul&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;astimezone&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;local_tz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; timedelta&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;days&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strftime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%Y-%m-%d&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;09&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;저는 일단 처음 15시로 되어 있던 시간을 KST(+9시간)을 함으로써 다음 날이 되게 하려고 했습니다.&lt;br&gt;
하지만 1번과 같이 보시다시피 &lt;code class=&quot;language-text&quot;&gt;2023-07-23 15:00:00+09:00&lt;/code&gt; 이런 결과가 나왔습니다.&lt;br&gt;
그래서 2번에서 날짜를 하나 빼서 날짜만 String 값으로 변경해보니 예상했던 결과인 &lt;code class=&quot;language-text&quot;&gt;2023-07-23&lt;/code&gt;이 아닌 &lt;code class=&quot;language-text&quot;&gt;2023-07-22&lt;/code&gt;가 나왔습니다.&lt;/p&gt;
&lt;h2 id=&quot;해결-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;해결 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결 방법&lt;/h2&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;local_tz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tz&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;gettz&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Asia/Seoul&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 1&lt;/span&gt;
a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;replace&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tzinfo&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;tz&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;UTC&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;- 해결 방법&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 2&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;astimezone&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;local_tz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 3&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; timedelta&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;days&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;strftime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%Y-%m-%d&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 comment&quot;&gt;# 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 1&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 2&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;09&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;00&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 3&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;07&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;처음에 Datetime을 초기화해주고 &lt;code class=&quot;language-text&quot;&gt;a = a.replace(tzinfo=tz.UTC)&lt;/code&gt;를 통해 타임존을 replace해주니 위 출력결과 처럼 &lt;code class=&quot;language-text&quot;&gt;#1&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;#2&lt;/code&gt;처럼 변했습니다.&lt;br&gt;
이 상태에서 KST로 timezone을 변경해주고 하루를 빼주니 원하는 결과가 나왔습니다.&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;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;
&lt;p&gt;사실 이런 사소한 오류들이 원하는 로직처럼 흘러가지 않는 경우가 있습니다.&lt;br&gt;
특히나 날짜를 가지고 데이터 조작을 하거나 데이터 쿼리 조건을 날린다던지 그랬을 때 쿼리는 또 정상적으로 작동은 합니다만 집계하는 데이터와 전체 데이터의 날짜 범위가 맞지 않는 경우가 발생합니다..!&lt;br&gt;
이런 에러들은 테스트 코드를 통해 잡지 않는 이상 어렵다고 생각합니다. 하지만 이제 일이라는게 언제나 테스트 코드를 짤 수는 없을 수도 있으므로..!&lt;/p&gt;
&lt;p&gt;이번에 파이썬에서 처음에 알게 되어 다른 분들에게 제 글이 도움이 되었으면 합니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Airflow Backfill 트러블 슈팅]]></title><description><![CDATA[Airflow]]></description><link>https://ambosing.github.io/airflow/backfill_trouble_shooting/</link><guid isPermaLink="false">https://ambosing.github.io/airflow/backfill_trouble_shooting/</guid><category><![CDATA[Airflow]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Sat, 05 Aug 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;문제-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%EC%83%81%ED%99%A9&quot; aria-label=&quot;문제 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제 상황&lt;/h2&gt;
&lt;p&gt;기존 원본 데이터는 크롤링을 통해서 수집하고 있는 상황이었는데 Airflow를 이용한 배치 시스템 자체를 이후에 적용했습니다.&lt;br&gt;
그래서 Airflow에 있는 Backfill 기능을 사용해 기존 원본 데이터를 채웠습니다만..!&lt;br&gt;
데이터가 원하는대로 들어가지 않았습니다..&lt;br&gt;
예시로 들면, 2023-07-23 데이터와 2023-07-24 데이터의 차이가 원래 1000이라고 한다면 막상 2023-07-24 변화량 값의 데이터는 모두 다 기본값인 0으로 들어가 있었던 거죠.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;물론 이렇게 구현하지 않았을 수도 있었겠지만.. 저는 하루의 데이터 집계의 저장과 변화량 데이터를 한 번에 구현했었습니다. &lt;br&gt;만약 하루 집계 데이터와 변화량 데이터를 분리한다면 집계한 데이터를 먼저 Backfill을 실행하고, 변화량 데이터를 나중에 Backfill을 실행했다면 문제가 발생하지 않았을 겁니다만!  &lt;br&gt;위와 같이 실행한다고 하더라도 집계한 데이터의 Backfill을 먼저 실행하고 그 다음 변화량 데이터를 Backfill해야 하는 순서상의 의존은 변하지 않기 때문에 이대로 따로 분리하지는 않았습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/66029/2023-08-13-10-03-26.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmYAAABXRUJQVlA4IFoAAAAwBACdASoUAAcAPtFUo0uoJKMhsAgBABoJYwC7IE5/+An3Lzt7c8kY+gAA/vOryC4Y52rrRZ/jL4fp+e36WGFDtrvvoADPklZexmlJAiQFCNFDxQBQbyQAAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/a59e9/2023-08-13-10-03-26.webp 192w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/0ca9f/2023-08-13-10-03-26.webp 384w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/dc9b9/2023-08-13-10-03-26.webp 768w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/e2c2f/2023-08-13-10-03-26.webp 1152w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/66029/2023-08-13-10-03-26.webp 1412w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/a59e9/2023-08-13-10-03-26.webp 192w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/0ca9f/2023-08-13-10-03-26.webp 384w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/dc9b9/2023-08-13-10-03-26.webp 768w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/e2c2f/2023-08-13-10-03-26.webp 1152w,
/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/66029/2023-08-13-10-03-26.webp 1412w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/d844fdb3d44b1e2b5cb3e9b2bf23e55b/dc9b9/2023-08-13-10-03-26.webp&quot;
            alt=&quot;2023 08 13 10 03 26&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;단순화한 현재 Airflow의 taskflow&lt;/div&gt;
&lt;h2 id=&quot;원인-파악하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9B%90%EC%9D%B8-%ED%8C%8C%EC%95%85%ED%95%98%EA%B8%B0&quot; aria-label=&quot;원인 파악하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;원인 파악하기&lt;/h2&gt;
&lt;p&gt;이유는 요구사항이 전날 데이터를 기준으로 데이터 차이의 결과를 구해야 했는데 이 때 오늘 데이터는 하루 전날 데이터를 의존하게 됩니다.&lt;br&gt;
저는 병렬로 실행하는 CeleryExecutor를 사용하고 있었고, Backfill의 실행 순서는 랜덤으로 실행이 됩니다.&lt;br&gt;
하지만 이 사실을 모른 저는 Backfill을 진행했고, 위와 같은 문제 상황에 마주한 것입니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ca23d25ee92ab7042475562e52e611fa/a0063/2023-08-11-17-57-40.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 23.4375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmAAAABXRUJQVlA4IFQAAACwAwCdASoUAAUAPtFYpEuoJSOhsAgBABoJYwCdACHEl3hhD6L40AD+6uz5RTBoBGFJ1IfK6vObdYM0vbZlhRi8cidBYwuEnO10EwMQeLzr3ClvAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ca23d25ee92ab7042475562e52e611fa/a59e9/2023-08-11-17-57-40.webp 192w,
/static/ca23d25ee92ab7042475562e52e611fa/0ca9f/2023-08-11-17-57-40.webp 384w,
/static/ca23d25ee92ab7042475562e52e611fa/dc9b9/2023-08-11-17-57-40.webp 768w,
/static/ca23d25ee92ab7042475562e52e611fa/e2c2f/2023-08-11-17-57-40.webp 1152w,
/static/ca23d25ee92ab7042475562e52e611fa/f3efb/2023-08-11-17-57-40.webp 1536w,
/static/ca23d25ee92ab7042475562e52e611fa/a0063/2023-08-11-17-57-40.webp 1602w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ca23d25ee92ab7042475562e52e611fa/a59e9/2023-08-11-17-57-40.webp 192w,
/static/ca23d25ee92ab7042475562e52e611fa/0ca9f/2023-08-11-17-57-40.webp 384w,
/static/ca23d25ee92ab7042475562e52e611fa/dc9b9/2023-08-11-17-57-40.webp 768w,
/static/ca23d25ee92ab7042475562e52e611fa/e2c2f/2023-08-11-17-57-40.webp 1152w,
/static/ca23d25ee92ab7042475562e52e611fa/f3efb/2023-08-11-17-57-40.webp 1536w,
/static/ca23d25ee92ab7042475562e52e611fa/a0063/2023-08-11-17-57-40.webp 1602w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ca23d25ee92ab7042475562e52e611fa/dc9b9/2023-08-11-17-57-40.webp&quot;
            alt=&quot;2023 08 11 17 57 40&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;Backfill했을 때 시간 순서상이 아닌 랜덤&lt;/div&gt;
위와 같이 진행이 된다면 2023-07-24에 Dag를 실행할 때 어제 집계데이터가 없으므로 변화량 데이터를 정확하게 나오지 않게 됩니다.  
&lt;p&gt;이제 원인을 알았으니!! 해결을 해보러 갑시다!&lt;/p&gt;
&lt;h2 id=&quot;해결하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0&quot; aria-label=&quot;해결하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;해결하기!&lt;/h2&gt;
&lt;p&gt;Backfill은 실행순서가 랜덤으로 실행되므로 날짜 순으로 실행하게 만든다면 문제가 해결될 것입니다.&lt;br&gt;
그래서 Backfill을 순서대로 실행시키게 만들겠습니다.&lt;br&gt;
DAG의 default_args를 &lt;code class=&quot;language-text&quot;&gt;depends_on_past = True&lt;/code&gt;로 만든다면 Backfill은 순서대로 실행하게 됩니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; DAG&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    dag_id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;backfill_chronologically&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    start_date &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; datetime&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&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;
    default_args &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;depends_on_past&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 DAG를 수정하고 실행하니 문제가 없이 동작하였습니다!!&lt;/p&gt;
&lt;p&gt;혹시나 다른 좋은 방법이 있다면 댓글로 알려주시면 감사하겠습니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Airflow Execution Date 트러블 슈팅]]></title><description><![CDATA[헷갈릴만한 Execution Date와 Time Window]]></description><link>https://ambosing.github.io/airflow/execution_date/</link><guid isPermaLink="false">https://ambosing.github.io/airflow/execution_date/</guid><category><![CDATA[Airflow]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Sat, 05 Aug 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;문제-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%EC%83%81%ED%99%A9&quot; aria-label=&quot;문제 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제 상황&lt;/h2&gt;
&lt;p&gt;회사에서 배치 프로세스 작업으로 일단위 데이터 집계를 하기 위해 Airflow를 사용하고 있습니다. 저는 Execution Date를 당연하게 배치 프로세스의 작업 시간이라고 생각하고 스케줄링을 했었습니다..!
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/b2072/2023-08-07-14-30-49.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 47.91666666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlwAAABXRUJQVlA4IFAAAABQAwCdASoUAAoAPtFUo0uoJKMhsAgBABoJaSzAAAIFdQw/AAD+8X2fE3sP38WR6CGjwa1+Ar+Nq6/VfvhvJngfVcRddyrGUiJKSK0HnOcCAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/a59e9/2023-08-07-14-30-49.webp 192w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/0ca9f/2023-08-07-14-30-49.webp 384w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/dc9b9/2023-08-07-14-30-49.webp 768w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/e2c2f/2023-08-07-14-30-49.webp 1152w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/b2072/2023-08-07-14-30-49.webp 1212w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/a59e9/2023-08-07-14-30-49.webp 192w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/0ca9f/2023-08-07-14-30-49.webp 384w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/dc9b9/2023-08-07-14-30-49.webp 768w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/e2c2f/2023-08-07-14-30-49.webp 1152w,
/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/b2072/2023-08-07-14-30-49.webp 1212w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/ee8b4a71c0aa09df04bc0783cf3ad1c0/dc9b9/2023-08-07-14-30-49.webp&quot;
            alt=&quot;결과 그림&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;br&gt;
그렇지만 무슨일인지 원하는 대로 동작이 되지 않고, 오늘이 만약 8월 6일이면 전날 데이터인 8월 5일 데이터를 집계할 줄 알았지만 8월 4일의 데이터를 집계하고 있었습니다.&lt;br&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/aa4a2d418f9d20ae338a412f8788008c/2a579/2023-08-07-14-32-12.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 46.35416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlYAAABXRUJQVlA4IEoAAABwAwCdASoUAAkAPtFUo0uoJKMhsAgBABoJaQAAUz4ZaV5eYAAA/vUeOoodP+4FPC6n6ll1S3fSNO5jzbUnZHeCUQ5qdECSuWAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/aa4a2d418f9d20ae338a412f8788008c/a59e9/2023-08-07-14-32-12.webp 192w,
/static/aa4a2d418f9d20ae338a412f8788008c/0ca9f/2023-08-07-14-32-12.webp 384w,
/static/aa4a2d418f9d20ae338a412f8788008c/dc9b9/2023-08-07-14-32-12.webp 768w,
/static/aa4a2d418f9d20ae338a412f8788008c/e2c2f/2023-08-07-14-32-12.webp 1152w,
/static/aa4a2d418f9d20ae338a412f8788008c/2a579/2023-08-07-14-32-12.webp 1213w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/aa4a2d418f9d20ae338a412f8788008c/a59e9/2023-08-07-14-32-12.webp 192w,
/static/aa4a2d418f9d20ae338a412f8788008c/0ca9f/2023-08-07-14-32-12.webp 384w,
/static/aa4a2d418f9d20ae338a412f8788008c/dc9b9/2023-08-07-14-32-12.webp 768w,
/static/aa4a2d418f9d20ae338a412f8788008c/e2c2f/2023-08-07-14-32-12.webp 1152w,
/static/aa4a2d418f9d20ae338a412f8788008c/2a579/2023-08-07-14-32-12.webp 1213w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/aa4a2d418f9d20ae338a412f8788008c/dc9b9/2023-08-07-14-32-12.webp&quot;
            alt=&quot;실제 결과&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;왜-이런-문제가-발생할까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EC%9D%B4%EB%9F%B0-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EB%B0%9C%EC%83%9D%ED%95%A0%EA%B9%8C&quot; aria-label=&quot;왜 이런 문제가 발생할까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 이런 문제가 발생할까?&lt;/h2&gt;
&lt;p&gt;바로 Execution Date를 제가 잘못 알고 있었기 때문입니다.&lt;br&gt;
Execution Date는 제가 생각한대로 실행하고 있지 않았습니다.&lt;br&gt;
제가 착각한 부분은 실행 시각과 execution_date의 시간이 같은 줄 알고 프로그래밍을 했습니다..!&lt;br&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/0ed6f/2023-08-07-14-33-49.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 32.8125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAACQAwCdASoUAAcAPtFWo0uoJKMhsAgBABoJZQBU4Aex/X1ccYXAAP7zrljMziaoIg9hOp3uaHbh/otWgZz4DZkG2JkcPOwIuK6wUPrvX9Q4dUR1G4sAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/a59e9/2023-08-07-14-33-49.webp 192w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/0ca9f/2023-08-07-14-33-49.webp 384w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/dc9b9/2023-08-07-14-33-49.webp 768w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/e2c2f/2023-08-07-14-33-49.webp 1152w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/0ed6f/2023-08-07-14-33-49.webp 1203w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/a59e9/2023-08-07-14-33-49.webp 192w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/0ca9f/2023-08-07-14-33-49.webp 384w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/dc9b9/2023-08-07-14-33-49.webp 768w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/e2c2f/2023-08-07-14-33-49.webp 1152w,
/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/0ed6f/2023-08-07-14-33-49.webp 1203w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/1f6bc42e9e3ad6180ae687a7d5ae7fca/dc9b9/2023-08-07-14-33-49.webp&quot;
            alt=&quot;내가 생각한 결과&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;제가 생각했던 execution_date&lt;/div&gt;
&lt;p&gt;8월 6일 00시에 실행하는 Execution Time은 print를 해보니 8월 5일 00시에 찍혀있었습니다.&lt;br&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3c3164ee56825098252580d708aeccaf/c47e4/2023-08-07-14-34-26.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 28.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlQAAABXRUJQVlA4IEgAAABwAwCdASoUAAYAPtFUo0uoJKMhsAgBABoJZwAAYc1yWjXtBAAA/u2xBH+V0opBwmOjX+v8vp3jyNV8rUJVzauUjQJuGnCaAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/3c3164ee56825098252580d708aeccaf/a59e9/2023-08-07-14-34-26.webp 192w,
/static/3c3164ee56825098252580d708aeccaf/0ca9f/2023-08-07-14-34-26.webp 384w,
/static/3c3164ee56825098252580d708aeccaf/dc9b9/2023-08-07-14-34-26.webp 768w,
/static/3c3164ee56825098252580d708aeccaf/e2c2f/2023-08-07-14-34-26.webp 1152w,
/static/3c3164ee56825098252580d708aeccaf/c47e4/2023-08-07-14-34-26.webp 1179w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/3c3164ee56825098252580d708aeccaf/a59e9/2023-08-07-14-34-26.webp 192w,
/static/3c3164ee56825098252580d708aeccaf/0ca9f/2023-08-07-14-34-26.webp 384w,
/static/3c3164ee56825098252580d708aeccaf/dc9b9/2023-08-07-14-34-26.webp 768w,
/static/3c3164ee56825098252580d708aeccaf/e2c2f/2023-08-07-14-34-26.webp 1152w,
/static/3c3164ee56825098252580d708aeccaf/c47e4/2023-08-07-14-34-26.webp 1179w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/3c3164ee56825098252580d708aeccaf/dc9b9/2023-08-07-14-34-26.webp&quot;
            alt=&quot;실제 실행했던 결과&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;실제 execution_date&lt;/div&gt;
&lt;p&gt;Airflow에는 TimeWindow라는 처리해야할 데이터의 기간인 개념이 있습니다.&lt;br&gt;
예를 들어, 8월 5일날 이커머스의 일일 매출을 집계하는 배치 작업이 있다고 합시다.&lt;br&gt;
일일 매출을 계산하려면 4일이 끝나고 8월 5일 자정에 &lt;code class=&quot;language-text&quot;&gt;08/04 00:00:00 ~ 08/04 23:59:59&lt;/code&gt;까지의 발생한 매출을 계산해야 합니다!&lt;br&gt;
여기서 작업 대상이 되는 데이터는 8월 4일의 데이터(=&lt;code class=&quot;language-text&quot;&gt;execution_date&lt;/code&gt;)가 되고, 실제 작업이 실행되는 시간은 8월 5일 0시가 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5426666439fba28e6637854a738746b9/0157a/2023-08-07-14-35-06.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 26.041666666666668%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRloAAABXRUJQVlA4IE4AAACQAwCdASoUAAUAPtFUpEuoJKOhsAgBABoJZwC7AB7HXyqzlKAAAP7zz8ua8RKfJyOLWbmr04CDKKnHGsqAGWN5m2zjXm2ziYpocA86AAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/5426666439fba28e6637854a738746b9/a59e9/2023-08-07-14-35-06.webp 192w,
/static/5426666439fba28e6637854a738746b9/0ca9f/2023-08-07-14-35-06.webp 384w,
/static/5426666439fba28e6637854a738746b9/dc9b9/2023-08-07-14-35-06.webp 768w,
/static/5426666439fba28e6637854a738746b9/e2c2f/2023-08-07-14-35-06.webp 1152w,
/static/5426666439fba28e6637854a738746b9/0157a/2023-08-07-14-35-06.webp 1186w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/5426666439fba28e6637854a738746b9/a59e9/2023-08-07-14-35-06.webp 192w,
/static/5426666439fba28e6637854a738746b9/0ca9f/2023-08-07-14-35-06.webp 384w,
/static/5426666439fba28e6637854a738746b9/dc9b9/2023-08-07-14-35-06.webp 768w,
/static/5426666439fba28e6637854a738746b9/e2c2f/2023-08-07-14-35-06.webp 1152w,
/static/5426666439fba28e6637854a738746b9/0157a/2023-08-07-14-35-06.webp 1186w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/5426666439fba28e6637854a738746b9/dc9b9/2023-08-07-14-35-06.webp&quot;
            alt=&quot;Time window&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;즉, &lt;code class=&quot;language-text&quot;&gt;execution_date&lt;/code&gt;는 해당 Task가 처리해야 할 데이터 기간의 시작 시점인 8월 4일을 의미합니다.&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;execution_date&lt;/code&gt;라는 이름을 직역하면 실행 날짜가 되기 때문에 그 의미와 실제 의미가 달라서 혼란이 유발 됐었습니다..&lt;/p&gt;
&lt;h2 id=&quot;어떻게-해결해야-할까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EA%B2%B0%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C&quot; aria-label=&quot;어떻게 해결해야 할까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;어떻게 해결해야 할까?&lt;/h2&gt;
&lt;h3 id=&quot;1-execution_date-이해에-따라-수정&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#1-execution_date-%EC%9D%B4%ED%95%B4%EC%97%90-%EB%94%B0%EB%9D%BC-%EC%88%98%EC%A0%95&quot; aria-label=&quot;1 execution_date 이해에 따라 수정 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. execution_date 이해에 따라 수정&lt;/h3&gt;
&lt;p&gt;이건 해결방법 중 가장 쉬운 방법이지만 저만 오해가 풀린 걸 수도 있으므로 언젠가 코드를 유지보수할 다른 분들께서 또 오해의 소지가 있기 때문에 이 방법 스킵하도록 하겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;2-execution_date를-대체하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#2-execution_date%EB%A5%BC-%EB%8C%80%EC%B2%B4%ED%95%98%EA%B8%B0&quot; aria-label=&quot;2 execution_date를 대체하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. execution_date를 대체하기&lt;/h3&gt;
&lt;p&gt;execution_date를 대체하는 것이 좋은 방법이라고 생각됩니다.&lt;br&gt;
&lt;a href=&quot;https://cwiki.apache.org/confluence/display/AIRFLOW/AIP-39+Richer+scheduler_interval&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;confluence의 AIP39&lt;/a&gt;에 보면 execution_date가 너무 오해에 소지가 있으니 새로운 이름을 명칭하는 내용이 있습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 472px; &quot;
    &gt;
      &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 88.54166666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmYAAABXRUJQVlA4IFoAAAAwBACdASoUABIAPtFgqU+oJSOiKAgBABoJaQAAMX/MNDY7y8Zx4RGPtYAA/vPD9cf76UVebCfOlvmu+cjIhyLQFQ8XVgP0IxlA/PYKJ4RrENdOmps70N0AAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/8ed9c23270835b7160b796f3fa9800f8/a59e9/2023-08-08-10-48-18.webp 192w,
/static/8ed9c23270835b7160b796f3fa9800f8/0ca9f/2023-08-08-10-48-18.webp 384w,
/static/8ed9c23270835b7160b796f3fa9800f8/1fc91/2023-08-08-10-48-18.webp 472w&quot;
              sizes=&quot;(max-width: 472px) 100vw, 472px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/8ed9c23270835b7160b796f3fa9800f8/a59e9/2023-08-08-10-48-18.webp 192w,
/static/8ed9c23270835b7160b796f3fa9800f8/0ca9f/2023-08-08-10-48-18.webp 384w,
/static/8ed9c23270835b7160b796f3fa9800f8/1fc91/2023-08-08-10-48-18.webp 472w&quot;
            sizes=&quot;(max-width: 472px) 100vw, 472px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/8ed9c23270835b7160b796f3fa9800f8/1fc91/2023-08-08-10-48-18.webp&quot;
            alt=&quot;2023 08 08 10 48 18&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;새로운 명칭이름&lt;/div&gt;
이 위에 표에는 없지만 execution_date와 같은 날짜를 가리키는 logical_date도 존재합니다.
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bc07d0151b78d83ed8e897d5a315b79b/df6ec/2023-08-07-14-35-53.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAAAwAwCdASoUAAcAPtFWo0uoJKMhsAgBABoJZwAAUp/h5XgAAP7zmbeq/JpASWUU+niAezktXMAkMGtrH347wB7u9qTMehxoQKyROIsXa8bXru4ndwIAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/bc07d0151b78d83ed8e897d5a315b79b/a59e9/2023-08-07-14-35-53.webp 192w,
/static/bc07d0151b78d83ed8e897d5a315b79b/0ca9f/2023-08-07-14-35-53.webp 384w,
/static/bc07d0151b78d83ed8e897d5a315b79b/dc9b9/2023-08-07-14-35-53.webp 768w,
/static/bc07d0151b78d83ed8e897d5a315b79b/e2c2f/2023-08-07-14-35-53.webp 1152w,
/static/bc07d0151b78d83ed8e897d5a315b79b/f3efb/2023-08-07-14-35-53.webp 1536w,
/static/bc07d0151b78d83ed8e897d5a315b79b/df6ec/2023-08-07-14-35-53.webp 1780w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/bc07d0151b78d83ed8e897d5a315b79b/a59e9/2023-08-07-14-35-53.webp 192w,
/static/bc07d0151b78d83ed8e897d5a315b79b/0ca9f/2023-08-07-14-35-53.webp 384w,
/static/bc07d0151b78d83ed8e897d5a315b79b/dc9b9/2023-08-07-14-35-53.webp 768w,
/static/bc07d0151b78d83ed8e897d5a315b79b/e2c2f/2023-08-07-14-35-53.webp 1152w,
/static/bc07d0151b78d83ed8e897d5a315b79b/f3efb/2023-08-07-14-35-53.webp 1536w,
/static/bc07d0151b78d83ed8e897d5a315b79b/df6ec/2023-08-07-14-35-53.webp 1780w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/bc07d0151b78d83ed8e897d5a315b79b/dc9b9/2023-08-07-14-35-53.webp&quot;
            alt=&quot;interval Time&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt; 다양한 Date&lt;/div&gt;
&lt;p&gt;위와 같이 이외에도 airflow에 정해진 date들이 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; pendulum&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DateTime 형식
date_time_start &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;data_interval_start&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;execution_date 대신 logical_date나 data_interval_start로 변경하여 코드를 수정하는 이 방법이 조금 더 좋아보여 이렇게 수정하였습니다.&lt;/p&gt;
&lt;h2 id=&quot;깨달은-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B9%A8%EB%8B%AC%EC%9D%80-%EC%A0%90&quot; aria-label=&quot;깨달은 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;깨달은 점&lt;/h2&gt;
&lt;p&gt;새로운 기술을 도입할 때 실보다 바늘이 많다고 생각하여 도입을 했지만, 오해할 만한 여지를 계속 내버려두고 데이터 체크를 하지 않았다면 장기적인 에러로 발전했을 것 같습니다..&lt;br&gt;
앞으로도 제 로직이 정확하다고 할지라도 테스트는 무조건 진행해야 한다고 생각합니다.&lt;br&gt;
이번처럼 execution_date가 제가 생각한 방향과 다르게 동작할 수 있으므로.. ㅠㅠ&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Amazon-linux2 Docker Compose Airflow 설치와 Git Action 배포 자동화]]></title><description><![CDATA[으어어.. 에러가 났떤 지난날들]]></description><link>https://ambosing.github.io/airflow/install_deploy/</link><guid isPermaLink="false">https://ambosing.github.io/airflow/install_deploy/</guid><category><![CDATA[Airflow]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Mon, 31 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전에&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84%EC%97%90&quot; aria-label=&quot;들어가기 전에 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전에&lt;/h2&gt;
&lt;p&gt;저는 회사에서 데이터를 배치하는 작업을 많이 했었습니다. 그 중에 처음으로 도전한 것은 바로 예전 학생 때 프로젝트했던 Linux Cron 배치 작업으로 배치 데이터를 프로세싱 중이었는데요.&lt;br&gt;
이것보다 더 좋은 것이 없을까하는 생각이 매번 들긴 했었습니다. 그 당시에만 해도 모든 서버를 온프레미스로 돌리고 있는 상황이었습니다!&lt;br&gt;
이렇게 하다보니 컴퓨터가 꺼지거나 배치 작업이 돌아가지 않을 때는 운영팀의 보고를 통해서만 받게 되었습니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e373f73b0c15e7a4d4d103a7b40c30e5/84f9f/2023-08-01-14-59-32.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31.770833333333332%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmwAAABXRUJQVlA4IGAAAACwAwCdASoUAAYAPtFWpEuoJKOhsAgBABoJZwAD42IN75/p79QgAAD+x1/zRYSa57p4jh/afp/nnBFwmOoC21xjSIbzjxbAyXE2KPq1Hl526FBCb910qRqZyBDn04AAAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/e373f73b0c15e7a4d4d103a7b40c30e5/a59e9/2023-08-01-14-59-32.webp 192w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/0ca9f/2023-08-01-14-59-32.webp 384w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/dc9b9/2023-08-01-14-59-32.webp 768w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/e2c2f/2023-08-01-14-59-32.webp 1152w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/f3efb/2023-08-01-14-59-32.webp 1536w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/84f9f/2023-08-01-14-59-32.webp 1552w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/e373f73b0c15e7a4d4d103a7b40c30e5/a59e9/2023-08-01-14-59-32.webp 192w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/0ca9f/2023-08-01-14-59-32.webp 384w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/dc9b9/2023-08-01-14-59-32.webp 768w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/e2c2f/2023-08-01-14-59-32.webp 1152w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/f3efb/2023-08-01-14-59-32.webp 1536w,
/static/e373f73b0c15e7a4d4d103a7b40c30e5/84f9f/2023-08-01-14-59-32.webp 1552w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/e373f73b0c15e7a4d4d103a7b40c30e5/dc9b9/2023-08-01-14-59-32.webp&quot;
            alt=&quot;기존이미지&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt; 온프레미스 당시 인프라&lt;/div&gt;
&lt;p&gt;회사에서 AWS 사용해보기로 결정이 됐습니다.  기존에 있던 배치 시스템을 변경할 기회였습니다.&lt;br&gt;
그래서 AWS에서 배치 작업을 더 좋게 처리하는 방법이 없을까하다가 Lambda + EventBridge로 처리하게 했었습니다.&lt;br&gt;
이번엔 Severless 서비스인 Lambda를 사용하니깐 컴퓨터가 문제일 경우는 없었습니다만 만약 데이터의 정합성의 문제로 에러가 발생한다면 기존의 배치 작업을 다시 돌려야하는 문제가 생겼습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1b85444b25498e5002dd7c6d234316e8/da9ed/2023-08-01-15-56-08.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.625%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmwAAABXRUJQVlA4IGAAAADQAwCdASoUAAgAPtFipk0oJiOiMAgBABoJQApgWZQEz6JrwXASOgAA/v5hO5mI8DVfEvop7ZGEBe06CFhYaRQZ6cixN64DP4iBpz1nABoSE4WnMxHURDXEvyP7A3paAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/1b85444b25498e5002dd7c6d234316e8/a59e9/2023-08-01-15-56-08.webp 192w,
/static/1b85444b25498e5002dd7c6d234316e8/0ca9f/2023-08-01-15-56-08.webp 384w,
/static/1b85444b25498e5002dd7c6d234316e8/dc9b9/2023-08-01-15-56-08.webp 768w,
/static/1b85444b25498e5002dd7c6d234316e8/e2c2f/2023-08-01-15-56-08.webp 1152w,
/static/1b85444b25498e5002dd7c6d234316e8/da9ed/2023-08-01-15-56-08.webp 1277w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/1b85444b25498e5002dd7c6d234316e8/a59e9/2023-08-01-15-56-08.webp 192w,
/static/1b85444b25498e5002dd7c6d234316e8/0ca9f/2023-08-01-15-56-08.webp 384w,
/static/1b85444b25498e5002dd7c6d234316e8/dc9b9/2023-08-01-15-56-08.webp 768w,
/static/1b85444b25498e5002dd7c6d234316e8/e2c2f/2023-08-01-15-56-08.webp 1152w,
/static/1b85444b25498e5002dd7c6d234316e8/da9ed/2023-08-01-15-56-08.webp 1277w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/1b85444b25498e5002dd7c6d234316e8/dc9b9/2023-08-01-15-56-08.webp&quot;
            alt=&quot;2023 08 01 15 56 08&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt; AWS 당시 인프라&lt;/div&gt;
&lt;p&gt;그러다가 데이터 엔지니어링에 대해 관심을 가지고 있었습니다. 그 중 Airflow라는 기술이 있었는데요. Airflow는 이전에 했던 배치 시스템의 단점들을 보완하고 있었습니다..!&lt;br&gt;
그래서 이번 글에서는 Airflow를 설치하는 방법과 Git Action으로 AWS EC2에 배포하는 방법을 알아보겠습니다.&lt;br&gt;
&lt;del&gt;왜 AWS EC2냐고 하면 .. 제가 쓰고 있는 환경이라서..&lt;/del&gt;&lt;/p&gt;
&lt;h4 id=&quot;참고한-글&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%ED%95%9C-%EA%B8%80&quot; aria-label=&quot;참고한 글 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고한 글&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;https://airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Airflow 공식문서&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;docker-compose로-airflow-설치하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#docker-compose%EB%A1%9C-airflow-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;docker compose로 airflow 설치하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Docker compose로 Airflow 설치하기&lt;/h2&gt;
&lt;p&gt;저는 Docker compose로 로컬(윈도우)에 설치를 해주었습니다. 로컬 설치과정은 쉽기 때문에 이번 설치 과정은 Amazon linux 환경에서 진행된다는 점을 알고계시면 좋을 것 같습니다. Docker compose로 설치를 진행하도록 하겠습니다!&lt;/p&gt;
&lt;h4 id=&quot;amazon-linux2-환경에서-docker-설치하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#amazon-linux2-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-docker-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;amazon linux2 환경에서 docker 설치하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Amazon linux2 환경에서 Docker 설치하기&lt;/h4&gt;
&lt;p&gt;Amazone-linux2에 도커를 설치합니다.&lt;br&gt;
sudo는 언제나 필수입니다! (안그러면 권한 없다고 에러를 냅니다! ㅠㅠ)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; amazon-linux-extras &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그런 다음 도커를 시작합니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;현재 사용자를 docker 그룹에 추가합니다. 이를 통해 sudo를 사용하지 않고도 Docker를 실행할 수 있습니다&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;usermod&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-aG&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token environment constant&quot;&gt;$USER&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;amazon-linux2에서-docker-compose-설치&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#amazon-linux2%EC%97%90%EC%84%9C-docker-compose-%EC%84%A4%EC%B9%98&quot; aria-label=&quot;amazon linux2에서 docker compose 설치 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Amazon linux2에서 Docker Compose 설치&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;-&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;uname&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;실행 권한을 부여해줍니다&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chmod&lt;/span&gt; +x /usr/local/bin/docker-compose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;도커 컴포즈가 잘 설치되었는지 확인해봅니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;윈도우에서는 &lt;code class=&quot;language-text&quot;&gt;docker compose&lt;/code&gt;이었는데 리눅스에서는 &lt;code class=&quot;language-text&quot;&gt;docker-compose&lt;/code&gt;입니다!&lt;/p&gt;
&lt;h4 id=&quot;github-repository를-하나-생성&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#github-repository%EB%A5%BC-%ED%95%98%EB%82%98-%EC%83%9D%EC%84%B1&quot; aria-label=&quot;github repository를 하나 생성 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Github Repository를 하나 생성&lt;/h4&gt;
&lt;p&gt;Github에 들어가 먼저 Repository를 하나 생성해줍니다.&lt;br&gt;
저는 Airflow라고 먼저 해주었습니다!&lt;/p&gt;
&lt;p&gt;그런 다음 amazon linux에 Git을 설치합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;아래 명령을 실행해 yum을 업데이트 합니다.&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 function&quot;&gt;sudo&lt;/span&gt; yum update&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;명령어를 실행해 git을 설치합니다.&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 function&quot;&gt;sudo&lt;/span&gt; yum &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;마지막으로 git이 잘 설치되었는지 확인합니다.&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 function&quot;&gt;git&lt;/span&gt; version&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 아까 만들었던 Git Repository를 Clone 받습니다.&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;git&lt;/span&gt; clone &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;Git 주소&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;h4 id=&quot;amazon-linux2에-docker-compose로-airflow-설치하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#amazon-linux2%EC%97%90-docker-compose%EB%A1%9C-airflow-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0&quot; aria-label=&quot;amazon linux2에 docker compose로 airflow 설치하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Amazon-linux2에 Docker-compose로 Airflow 설치하기&lt;/h4&gt;
&lt;p&gt;먼저 Airflow 폴더를 만들고 폴더에서 작업하겠습니다.&lt;br&gt;
저는 GitRepository 이름이 airflow라고 가정하겠습니다.&lt;br&gt;
curl 명령어를 통해 docker-compose.yaml 파일을 fetching해 주겠습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; airflow
&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; airflow

&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-LfO&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;https://airflow.apache.org/docs/apache-airflow/2.6.3/docker-compose.yaml&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 진행하면 현재 진행한 폴더에 yaml 파일이 생기실 겁니다!&lt;br&gt;
docker-compose에 포함되어 있는 기능은 이렇습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;airflow-scheduler&lt;/strong&gt; : 모든 DAG와 task들을 모니터링합니다. task들의 종속성들이 완료되면 task들을 트리거 시킵니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;airflow-webserver&lt;/strong&gt; : airflow를 UI로 볼수 있는 웹사이트입니다. 기본적으로 URL은 &lt;a href=&quot;http://localhost:8080&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://localhost:8080&lt;/a&gt; 입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;airflow-worker&lt;/strong&gt; : 스케줄러가 부여한 작업을 실행하는 작업자입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;airflow-triggerer&lt;/strong&gt; : Triggerer는 연기 가능한 작업에 대한 이벤트 루프를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;airflow-init&lt;/strong&gt; : airflow 서비스를 초기화합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;postgres&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;redis&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이외에도 flower는 있지만 이건 설명을 넘어가겠습니다!&lt;br&gt;
또한, 몇 개의 디렉토리는 컨테이너에 마운트됩니다. 그래서 정해진 디렉토리는 컨테이너와 동기화됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;./dags&lt;/strong&gt; : DAG 파일을 여기에 놓으면 Airflow에서 인식합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;./logs&lt;/strong&gt; : 스케줄러와 task 실행한 로그들이 담깁니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;./config&lt;/strong&gt; : 커스텀한 log parser를 추가할 수 있습니다. 그리고 airflow_local_settings.py를 추가하여 클러스터 정책을 구성할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;./plugins&lt;/strong&gt; : 커스텀한 plugin들을 여가에 추가할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그래서 위와 같은 디렉토리들은 필수적으로 구성되어야 합니다.&lt;br&gt;
폴더들을 모두 만들어줍시다!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; ./dags ./logs ./plugins ./config
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AIRFLOW_UID=&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; .env&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;다른 OS에서는 이렇게 진행했을 때 경고가 나올 수도 있습니다.&lt;br&gt;
그럴 때는 따로 .env 파일을 추가하여&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;AIRFLOW_UID&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 docker compose 명령어를 사용하여 airflow를 설치해봅시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Linux, mac&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; up airflow-init
&lt;span class=&quot;token comment&quot;&gt;# window&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose up airflow-init&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;docker compose가 초기화 되면 이런 메시지를 보실 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;txt&quot;&gt;&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;airflow-init_1       | Upgrades done
airflow-init_1       | Admin user airflow created
airflow-init_1       | 2.6.3
start_airflow-init_1 exited with code 0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;그리고 웹에 로그인할 계정이 만들어집니다.&lt;br&gt;
id : &lt;code class=&quot;language-text&quot;&gt;airflow&lt;/code&gt;&lt;br&gt;
pw : &lt;code class=&quot;language-text&quot;&gt;airflow&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;이제 모든 docker compose로 설치한 모든 서비스를 시작해봅시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Linux, mac&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;docker-compose&lt;/span&gt; up 
&lt;span class=&quot;token comment&quot;&gt;# window&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; compose up &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정상적으로 잘 동작했는지 docker ps 명령어를 통해 알아봅시다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt;
CONTAINER ID   IMAGE                  COMMAND                  CREATED          STATUS                    PORTS                              NAMES
247ebe6cf87a   apache/airflow:2.6.3   &lt;span class=&quot;token string&quot;&gt;&quot;/usr/bin/dumb-init …&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes ago    Up &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;/tcp                           compose_airflow-worker_1
ed9b09fc84b1   apache/airflow:2.6.3   &lt;span class=&quot;token string&quot;&gt;&quot;/usr/bin/dumb-init …&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes ago    Up &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;/tcp                           compose_airflow-scheduler_1
7cb1fb603a98   apache/airflow:2.6.3   &lt;span class=&quot;token string&quot;&gt;&quot;/usr/bin/dumb-init …&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes ago    Up &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; minutes &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;.0.0:8080-&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;/tcp             compose_airflow-webserver_1
74f3bbe506eb   postgres:13            &lt;span class=&quot;token string&quot;&gt;&quot;docker-entrypoint.s…&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt; minutes ago   Up &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt; minutes &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;5432&lt;/span&gt;/tcp                           compose_postgres_1
0bd6576d23cb   redis:latest           &lt;span class=&quot;token string&quot;&gt;&quot;docker-entrypoint.s…&quot;&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; hours ago     Up &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt; minutes &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;healthy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;.0.0:6379-&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6379&lt;/span&gt;/tcp             compose_redis_1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;status에 보면 정상적인 서비스들은 healthy라고 나오게 됩니다.&lt;br&gt;
그런다음에 이제 &lt;a href=&quot;http://localhost:8080&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;http://localhost:8080&lt;/a&gt; 으로 들어가시게 되면 아래와 같이 로그인 창이 뜹니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/64f1d4cde6de05bdc60172dceec540a7/fad02/2023-08-07-14-29-41.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.375%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRkAAAABXRUJQVlA4IDQAAACwAgCdASoUAAcAPtFUpEuoJKOhsAgBABoJaQAAeyAA/vJUrzl2CkiQQ8VwxE0X8z7VsBAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/64f1d4cde6de05bdc60172dceec540a7/a59e9/2023-08-07-14-29-41.webp 192w,
/static/64f1d4cde6de05bdc60172dceec540a7/0ca9f/2023-08-07-14-29-41.webp 384w,
/static/64f1d4cde6de05bdc60172dceec540a7/dc9b9/2023-08-07-14-29-41.webp 768w,
/static/64f1d4cde6de05bdc60172dceec540a7/e2c2f/2023-08-07-14-29-41.webp 1152w,
/static/64f1d4cde6de05bdc60172dceec540a7/f3efb/2023-08-07-14-29-41.webp 1536w,
/static/64f1d4cde6de05bdc60172dceec540a7/fad02/2023-08-07-14-29-41.webp 2539w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/64f1d4cde6de05bdc60172dceec540a7/a59e9/2023-08-07-14-29-41.webp 192w,
/static/64f1d4cde6de05bdc60172dceec540a7/0ca9f/2023-08-07-14-29-41.webp 384w,
/static/64f1d4cde6de05bdc60172dceec540a7/dc9b9/2023-08-07-14-29-41.webp 768w,
/static/64f1d4cde6de05bdc60172dceec540a7/e2c2f/2023-08-07-14-29-41.webp 1152w,
/static/64f1d4cde6de05bdc60172dceec540a7/f3efb/2023-08-07-14-29-41.webp 1536w,
/static/64f1d4cde6de05bdc60172dceec540a7/fad02/2023-08-07-14-29-41.webp 2539w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/64f1d4cde6de05bdc60172dceec540a7/dc9b9/2023-08-07-14-29-41.webp&quot;
            alt=&quot;airflow 화면&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
그리고 로그인을 하고 나면 이러한 example DAGs가 존재합니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a5fa026affac6522d8ad3b418fbd31f2/58bdf/2023-08-24-09-20-12.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 43.22916666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRjwAAABXRUJQVlA4IDAAAACwAgCdASoUAAkAPtFUo0uoJKMhsAgBABoJaQAAeyAA/vG8UfVX4mABsyU7ODyAAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/a5fa026affac6522d8ad3b418fbd31f2/a59e9/2023-08-24-09-20-12.webp 192w,
/static/a5fa026affac6522d8ad3b418fbd31f2/0ca9f/2023-08-24-09-20-12.webp 384w,
/static/a5fa026affac6522d8ad3b418fbd31f2/dc9b9/2023-08-24-09-20-12.webp 768w,
/static/a5fa026affac6522d8ad3b418fbd31f2/e2c2f/2023-08-24-09-20-12.webp 1152w,
/static/a5fa026affac6522d8ad3b418fbd31f2/f3efb/2023-08-24-09-20-12.webp 1536w,
/static/a5fa026affac6522d8ad3b418fbd31f2/58bdf/2023-08-24-09-20-12.webp 2340w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/a5fa026affac6522d8ad3b418fbd31f2/a59e9/2023-08-24-09-20-12.webp 192w,
/static/a5fa026affac6522d8ad3b418fbd31f2/0ca9f/2023-08-24-09-20-12.webp 384w,
/static/a5fa026affac6522d8ad3b418fbd31f2/dc9b9/2023-08-24-09-20-12.webp 768w,
/static/a5fa026affac6522d8ad3b418fbd31f2/e2c2f/2023-08-24-09-20-12.webp 1152w,
/static/a5fa026affac6522d8ad3b418fbd31f2/f3efb/2023-08-24-09-20-12.webp 1536w,
/static/a5fa026affac6522d8ad3b418fbd31f2/58bdf/2023-08-24-09-20-12.webp 2340w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/a5fa026affac6522d8ad3b418fbd31f2/dc9b9/2023-08-24-09-20-12.webp&quot;
            alt=&quot;airflow example DAGs&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
엄청나게 많은 example DAGs가 보이는데요. 만약 example DAGs가 필요없다면 제거해줄 수 있습니다.&lt;/p&gt;
&lt;p&gt;docker-compose.yml 파일에서 AIRFLOW__CORE__LOAD_EXAMPLES가 true로 설정돼있는 것을 false로 변경하였습니다.&lt;br&gt;
&lt;code class=&quot;language-text&quot;&gt;AIRFLOW__CORE__LOAD_EXAMPLES: &apos;false&apos;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;그러고 나면 DAGs 페이지에 example DAG들이 모두 사라진 걸 알 수 있습니다.
이로써 일단 EC2에 Docker Compose를 사용해서 Airflow를 띄웠습니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 627px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/585e10669a034ff6775a6e693af81345/faefd/2023-08-24-11-07-24.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 128.125%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRtwAAABXRUJQVlA4INAAAACwBACdASoUABoAPtFaqU2oJSQiKAqpABoJQBhoAqpXge1obNZGpp5vc1RU2koAAP7wrq+UZOlF+0/YQkTXSGSHkuiQTuyVM+CtVlFdt/y5V0bD52nM9xg6JpngUd0Pe9e+9HVQZrL39+gQaJDKNLYd8fCwsLhubz6byUREfsmaX6sPsRsXtQ+TtsiY4QXfPuYV22Vbde3gREy5L0icKlPnD8FTUStxinDauNBt9NyRHvUSVWkpAN9ioGStXFf2U9bcWBx2HnwRtB+RkosoAAAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/585e10669a034ff6775a6e693af81345/a59e9/2023-08-24-11-07-24.webp 192w,
/static/585e10669a034ff6775a6e693af81345/0ca9f/2023-08-24-11-07-24.webp 384w,
/static/585e10669a034ff6775a6e693af81345/faefd/2023-08-24-11-07-24.webp 627w&quot;
              sizes=&quot;(max-width: 627px) 100vw, 627px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/585e10669a034ff6775a6e693af81345/a59e9/2023-08-24-11-07-24.webp 192w,
/static/585e10669a034ff6775a6e693af81345/0ca9f/2023-08-24-11-07-24.webp 384w,
/static/585e10669a034ff6775a6e693af81345/faefd/2023-08-24-11-07-24.webp 627w&quot;
            sizes=&quot;(max-width: 627px) 100vw, 627px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/585e10669a034ff6775a6e693af81345/faefd/2023-08-24-11-07-24.webp&quot;
            alt=&quot;2023 08 24 11 07 24&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt; 현재 구축한 인프라 &lt;/div&gt;
&lt;p&gt;이제 EC2에는 모두 설정을 해놓았으니 Github Action을 통해 배포자동화를 시켜보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;git-action-배포-자동화&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#git-action-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94&quot; aria-label=&quot;git action 배포 자동화 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Git Action 배포 자동화&lt;/h2&gt;
&lt;p&gt;먼저 Git Action에서 EC2를 접근하기 위해서는 SSH 키와 HOST Address가 필요합니다.&lt;br&gt;
이를 먼저 안전하게 저장하기 위해 Github Secrets로 저장해봅시다.&lt;/p&gt;
&lt;p&gt;Github에 접속해 Airflow파일들이 담겨있는 Repository를 선택합니다.&lt;br&gt;
그런 다음 아래와 같이 github settings 클릭합니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/670fa4c6b628b7fdf1b563ba48345e26/bf53a/2023-08-25-09-10-13.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 5.208333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRjwAAABXRUJQVlA4IDAAAACwAgCdASoUAAEAPtFWpEuoJKOhsAgBABoJaQAAeyAA/vDxbWZnaVdC59m5wbcUAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/670fa4c6b628b7fdf1b563ba48345e26/a59e9/2023-08-25-09-10-13.webp 192w,
/static/670fa4c6b628b7fdf1b563ba48345e26/0ca9f/2023-08-25-09-10-13.webp 384w,
/static/670fa4c6b628b7fdf1b563ba48345e26/dc9b9/2023-08-25-09-10-13.webp 768w,
/static/670fa4c6b628b7fdf1b563ba48345e26/bf53a/2023-08-25-09-10-13.webp 1131w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/670fa4c6b628b7fdf1b563ba48345e26/a59e9/2023-08-25-09-10-13.webp 192w,
/static/670fa4c6b628b7fdf1b563ba48345e26/0ca9f/2023-08-25-09-10-13.webp 384w,
/static/670fa4c6b628b7fdf1b563ba48345e26/dc9b9/2023-08-25-09-10-13.webp 768w,
/static/670fa4c6b628b7fdf1b563ba48345e26/bf53a/2023-08-25-09-10-13.webp 1131w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/670fa4c6b628b7fdf1b563ba48345e26/dc9b9/2023-08-25-09-10-13.webp&quot;
            alt=&quot;2023 08 25 09 10 13&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Settings에 들어오면 메인화면 좌측에 메뉴가 나옵니다.&lt;br&gt;
여기서 빨간색으로 칠해진 버튼을 누르면 드롭다운이 됩니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 425px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/499f4eef4bc763868e975acb3e812e61/b5bcc/2023-08-25-09-19-36.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 222.39583333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRm4AAABXRUJQVlA4IGIAAABwBACdASoUACwAPtFep0+oJSMiJWsxABoJaQAAKeV8llx+IP1B8O0bDBBgAAD+8hexqy3tDmlp4gueylMrjLPu9BUVOunba2CB8ZsoE5kW1WpGiJxRVIzz4Kn5wuKvsAAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/499f4eef4bc763868e975acb3e812e61/a59e9/2023-08-25-09-19-36.webp 192w,
/static/499f4eef4bc763868e975acb3e812e61/0ca9f/2023-08-25-09-19-36.webp 384w,
/static/499f4eef4bc763868e975acb3e812e61/b5bcc/2023-08-25-09-19-36.webp 425w&quot;
              sizes=&quot;(max-width: 425px) 100vw, 425px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/499f4eef4bc763868e975acb3e812e61/a59e9/2023-08-25-09-19-36.webp 192w,
/static/499f4eef4bc763868e975acb3e812e61/0ca9f/2023-08-25-09-19-36.webp 384w,
/static/499f4eef4bc763868e975acb3e812e61/b5bcc/2023-08-25-09-19-36.webp 425w&quot;
            sizes=&quot;(max-width: 425px) 100vw, 425px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/499f4eef4bc763868e975acb3e812e61/b5bcc/2023-08-25-09-19-36.webp&quot;
            alt=&quot;2023 08 25 09 19 36&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;그 다음은 버튼을 눌러줍니다!
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/39897e9ce9941e7cdf72ae3972618bf1/f4b45/2023-08-25-09-27-28.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.91666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRmIAAABXRUJQVlA4IFYAAACwAwCdASoUAA8APtFYpEwoJSOiMAgBABoJaQAAW+jH0x7xeMoUAAD+9g81UzyUC1c3oxSKBkTxyjZGAm48DSmPIttNtqh1UipvopkeevFO9FvYgQAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/39897e9ce9941e7cdf72ae3972618bf1/a59e9/2023-08-25-09-27-28.webp 192w,
/static/39897e9ce9941e7cdf72ae3972618bf1/0ca9f/2023-08-25-09-27-28.webp 384w,
/static/39897e9ce9941e7cdf72ae3972618bf1/dc9b9/2023-08-25-09-27-28.webp 768w,
/static/39897e9ce9941e7cdf72ae3972618bf1/e2c2f/2023-08-25-09-27-28.webp 1152w,
/static/39897e9ce9941e7cdf72ae3972618bf1/f4b45/2023-08-25-09-27-28.webp 1473w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/39897e9ce9941e7cdf72ae3972618bf1/a59e9/2023-08-25-09-27-28.webp 192w,
/static/39897e9ce9941e7cdf72ae3972618bf1/0ca9f/2023-08-25-09-27-28.webp 384w,
/static/39897e9ce9941e7cdf72ae3972618bf1/dc9b9/2023-08-25-09-27-28.webp 768w,
/static/39897e9ce9941e7cdf72ae3972618bf1/e2c2f/2023-08-25-09-27-28.webp 1152w,
/static/39897e9ce9941e7cdf72ae3972618bf1/f4b45/2023-08-25-09-27-28.webp 1473w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/39897e9ce9941e7cdf72ae3972618bf1/dc9b9/2023-08-25-09-27-28.webp&quot;
            alt=&quot;2023 08 25 09 27 28&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;그러면 Secret키를 등록할 수 있습니다.&lt;br&gt;
여기에 이제 AWS SSH 키와 연결할 AWS HOST를 등록시켜주면 됩니다!
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/a6480e87bfc5058cc43daffb44092f21/096fc/2023-08-25-09-29-50.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 52.60416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRj4AAABXRUJQVlA4IDIAAACwAgCdASoUAAsAPtFUo0uoJKMhsAgBABoJaQAAeyAA/vKaoolIWg1+D9G/IIlnYXQAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/a6480e87bfc5058cc43daffb44092f21/a59e9/2023-08-25-09-29-50.webp 192w,
/static/a6480e87bfc5058cc43daffb44092f21/0ca9f/2023-08-25-09-29-50.webp 384w,
/static/a6480e87bfc5058cc43daffb44092f21/dc9b9/2023-08-25-09-29-50.webp 768w,
/static/a6480e87bfc5058cc43daffb44092f21/096fc/2023-08-25-09-29-50.webp 1065w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/a6480e87bfc5058cc43daffb44092f21/a59e9/2023-08-25-09-29-50.webp 192w,
/static/a6480e87bfc5058cc43daffb44092f21/0ca9f/2023-08-25-09-29-50.webp 384w,
/static/a6480e87bfc5058cc43daffb44092f21/dc9b9/2023-08-25-09-29-50.webp 768w,
/static/a6480e87bfc5058cc43daffb44092f21/096fc/2023-08-25-09-29-50.webp 1065w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/a6480e87bfc5058cc43daffb44092f21/dc9b9/2023-08-25-09-29-50.webp&quot;
            alt=&quot;2023 08 25 09 29 50&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Git Action은 Yaml 파일을 통해 설정합니다.&lt;br&gt;
.github/workflows 폴더 아래 파일이 위치해야 Github에서 워크플로우로 인식을 하도록 약속이 돼 있습니다!&lt;br&gt;
이제 .github/workflows에 하나의 yaml 파일을 등록해 줍니다.&lt;br&gt;
내용은 아래처럼 작성하시면 push 했을 때나 PR이 Closed 되었을 때 동작합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; CI to AWS EC2 Airflow

&lt;span class=&quot;token key atrule&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;branches&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 string&quot;&gt;&quot;main&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;branches&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 string&quot;&gt;&quot;main&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;types&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;closed&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;token key atrule&quot;&gt;workflow_dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;jobs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Send to ec2&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;airflow
    &lt;span class=&quot;token key atrule&quot;&gt;runs-on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ubuntu&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;latest

    &lt;span class=&quot;token key atrule&quot;&gt;steps&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 key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; SSH Commands
        &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; appleboy/ssh&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;action@v1.0.0
        &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;host&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; secrets.AWS_SSH_HOST &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 key atrule&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ec2&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;user
          &lt;span class=&quot;token key atrule&quot;&gt;key&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; secrets.AWS_SSH_KEY &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 key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;script_stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;true&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;command_timeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 200m
          &lt;span class=&quot;token key atrule&quot;&gt;script&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 scalar string&quot;&gt;
            cd ~/your-airflow-repository
            sudo chown -R $USER:$USER .
            git pull origin main
            docker-compose down
            docker-compose up -d&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;# 이 부분은 슬랙이라 추가적으로 슬랙으로 배포를 열람받고 싶은 분은 WEBHOOK 등록해서 쓰시면 됩니다.&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; action&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;slack
        &lt;span class=&quot;token key atrule&quot;&gt;uses&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 8398a7/action&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;slack@v3
        &lt;span class=&quot;token key atrule&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;status&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; job.status &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 key atrule&quot;&gt;author_name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 배포 결과
          &lt;span class=&quot;token key atrule&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; repo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;commit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;eventName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;workflow
        &lt;span class=&quot;token key atrule&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;SLACK_WEBHOOK_URL&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; secrets.SLACK_WEBHOOK_URL &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;# required&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; always()&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 Git Action을 통해 배포 자동화를 해보았습니다.&lt;br&gt;
보통 개발을 하실 때 로컬에서 개발하시고 실제 서버에 배포하실텐데요.&lt;br&gt;
보통 개발 하시는 구조가 이럴 것이라고 생각해서 한 번 만들어봤습니다!&lt;br&gt;
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/36ae084ee11fba7eae484a7f693f97e3/c25ec/2023-08-25-11-20-02.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 40.10416666666667%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRm4AAABXRUJQVlA4IGIAAADQAwCdASoUAAgAPtFWpEuoJKOhsAgBABoJZwBTAFvGN/UPvIJKDAAA/vT0rTiMak6ooGwbP8emB8yGPuYbHmOATezDu2VdJdaFWm+Yv7FEmhKE1zjA91T/CxKBVDX51xYAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/36ae084ee11fba7eae484a7f693f97e3/a59e9/2023-08-25-11-20-02.webp 192w,
/static/36ae084ee11fba7eae484a7f693f97e3/0ca9f/2023-08-25-11-20-02.webp 384w,
/static/36ae084ee11fba7eae484a7f693f97e3/dc9b9/2023-08-25-11-20-02.webp 768w,
/static/36ae084ee11fba7eae484a7f693f97e3/e2c2f/2023-08-25-11-20-02.webp 1152w,
/static/36ae084ee11fba7eae484a7f693f97e3/f3efb/2023-08-25-11-20-02.webp 1536w,
/static/36ae084ee11fba7eae484a7f693f97e3/c25ec/2023-08-25-11-20-02.webp 1797w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/36ae084ee11fba7eae484a7f693f97e3/a59e9/2023-08-25-11-20-02.webp 192w,
/static/36ae084ee11fba7eae484a7f693f97e3/0ca9f/2023-08-25-11-20-02.webp 384w,
/static/36ae084ee11fba7eae484a7f693f97e3/dc9b9/2023-08-25-11-20-02.webp 768w,
/static/36ae084ee11fba7eae484a7f693f97e3/e2c2f/2023-08-25-11-20-02.webp 1152w,
/static/36ae084ee11fba7eae484a7f693f97e3/f3efb/2023-08-25-11-20-02.webp 1536w,
/static/36ae084ee11fba7eae484a7f693f97e3/c25ec/2023-08-25-11-20-02.webp 1797w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/36ae084ee11fba7eae484a7f693f97e3/dc9b9/2023-08-25-11-20-02.webp&quot;
            alt=&quot;2023 08 25 11 20 02&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt; 현재 구축한 인프라 &lt;/div&gt;
&lt;p&gt;제 포스팅이 Airflow를 사용하시는 분들에게 도움이 됐으면 좋겠네요!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[파이썬 함수에서 예외 처리 잘하기]]></title><description><![CDATA[try!! 파이썬 예외 try!!]]></description><link>https://ambosing.github.io/python/function_except/</link><guid isPermaLink="false">https://ambosing.github.io/python/function_except/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Sat, 29 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;이전에 도커로 웹 크롤링을 도커 위에서 하나의 사이트마다 24시간 동안 돌리기 위해 크롤링 구조를 새로 짠 적이 있습니다. 그 때에 예외 처리는 어떻게 하는 것이 좋을까라는 생각을 많이 했었습니다.&lt;br&gt;
크롤링 같은 경우 에러가 발생한 경우 그 에러 상황을 재현하기가 쉽지 않을 때가 존재합니다..! 해당 URL의 게시물이 사라진 경우.. 또한, 어디에서 에러가 발생했는지 쉽지 않습니다.&lt;br&gt;
그래서 이번에는 예외 처리를 훌륭하게 해보려고 시도했습니다. 그래도 이번에 이렇게 책에서 나온것처럼 처리한 것 같아서 다행입니다..!&lt;br&gt;
다른 분들도 파이썬에서 예외처리를 잘하고 싶다면 이번에 나오는 예제를 잘 참고해보시는 것이 좋을 듯 합니다!!&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조 + 저의 생각을 합쳐서 나온 게시글입니다.&lt;br&gt;
만약 저작권의 문제 발생하거나 잘못된 부분이 있는 경우, 글을 삭제/수정처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;-함수에서-예외가-발생했을-때-none을-반환하는-것의-문제점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%ED%95%A8%EC%88%98%EC%97%90%EC%84%9C-%EC%98%88%EC%99%B8%EA%B0%80-%EB%B0%9C%EC%83%9D%ED%96%88%EC%9D%84-%EB%95%8C-none%EC%9D%84-%EB%B0%98%ED%99%98%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90&quot; aria-label=&quot; 함수에서 예외가 발생했을 때 none을 반환하는 것의 문제점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;❌ 함수에서 예외가 발생했을 때 None을 반환하는 것의 문제점!&lt;/h2&gt;
&lt;p&gt;갑자기 이게 무슨 이야기인지 싶으실 겁니다.&lt;br&gt;
바로 아래 예제를 확인하시면 이해가 더 잘 되실 겁니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;careful_divide&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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;try&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; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; ZeroDivisionError&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 boolean&quot;&gt;None&lt;/span&gt;


x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; careful_divide&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; result &lt;span class=&quot;token keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;잘못된 입력&apos;&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;함수에서 예외가 발생했을 때 예외 처리로 None을 리턴하는 방식이 있다고 합니다.&lt;br&gt;
보통 코드를 이렇게 쓰지는 않긴 합니다만..! 만약 None으로 쓰고계셨다면 이제 쓰지 않으시는 걸 추천합니다!&lt;br&gt;
그 이유는 바로 현재 함수를 호출하고 있는 호출자에서 if 조건에서 따로 처리를 해주고 있는 모습으로 보입니다.&lt;br&gt;
그런데 이렇게 처리하는 방법은 실수가 유발되기 쉽습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; careful_divide&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;잘못된 입력&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 이 코드가 실행되는데, 사실 이 코드가 실행되면 안된다!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드에서는 result 값이 0으로 반환받게 됩니다.&lt;br&gt;
이렇게 되면 if문 안의 결과가 False로 되어 print를 실행하게 됩니다. 다른 함수와 같은 경우에도 비슷합니다. False를 반환하는 값이라면 이와 같은 실수가 발생할 수 있게 되는거죠.&lt;/p&gt;
&lt;p&gt;그러면 어떻게 해야 예외를 잘 처리할 수 있을까요?&lt;/p&gt;
&lt;h2 id=&quot;-exception에서-다시-한-번-예외를-발생시켜-호출한-쪽에서-처리하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-exception%EC%97%90%EC%84%9C-%EB%8B%A4%EC%8B%9C-%ED%95%9C-%EB%B2%88-%EC%98%88%EC%99%B8%EB%A5%BC-%EB%B0%9C%EC%83%9D%EC%8B%9C%EC%BC%9C-%ED%98%B8%EC%B6%9C%ED%95%9C-%EC%AA%BD%EC%97%90%EC%84%9C-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0&quot; aria-label=&quot; exception에서 다시 한 번 예외를 발생시켜 호출한 쪽에서 처리하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;✅ Exception에서 다시 한 번 예외를 발생시켜 호출한 쪽에서 처리하기&lt;/h2&gt;
&lt;p&gt;말 그대로 함수에서 예외를 처리를 한 번 하고, 다시 한 번 예외를 발생시켜 처리하는 방법입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;careful_divide&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token triple-quoted-string string&quot;&gt;&quot;&quot;&quot;a를 b로 나눈다.

    Raises:
        ValueError: b가 0이어서 나눗셈을 할 수 없을 때
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&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; a &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; b
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; ZeroDivisionError &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;잘못된 입력&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; careful_divide&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;잘못된 입력&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;결과는 %.1f 입니다&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이렇게 하면 기존의 None은 반환했을 때와 달리 if문 자체를 쓰지 않아도 돼서 실수를 없앨 수 있습니다.&lt;/p&gt;
&lt;p&gt;근데 이제 굳이 이렇게까지 try-except를 두 번씩 쓰면서 함수의 Main부분에서 예외처리를 할 필요가 있을까라는 생각이 들게 됩니다..!
&lt;del&gt;저도 처음에 불편해서 했던 생각..&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;코드의 Main 함수에서 예외처리를 하는 것을 최상위 예외라고 합니다.
그러면 최상위 예외를 왜 쓰면 좋은지를 알아보기 전에 커스텀한 예외를 써야하는 이유에 대해서 알아보겠습니다!
&lt;del&gt;그래야 예제가 이해가 되고.. 또.. 예외를 더 잘할 수 있다구요!&lt;/del&gt;&lt;/p&gt;
&lt;h2 id=&quot;새로운-예외-계층-구조를-정의하는-것이-좋은-이유&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%98%88%EC%99%B8-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%A0%95%EC%9D%98%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%B4-%EC%A2%8B%EC%9D%80-%EC%9D%B4%EC%9C%A0&quot; aria-label=&quot;새로운 예외 계층 구조를 정의하는 것이 좋은 이유 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;새로운 예외 계층 구조를 정의하는 것이 좋은 이유&lt;/h2&gt;
&lt;p&gt;파이썬 언어와 표준 라이브러리에는 이미 예외 계층 구조가 내장되어 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# my_module.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determine_weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;volume&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; density&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; density &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; ValueError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;밀도는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 내장된 예외&lt;/span&gt;
    &lt;span class=&quot;token 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;경우에 따라 내장된 예외인 ValueError를 사용하는 편이 타당할 때도 있습니다.&lt;br&gt;
하지만, API의 경우 새로운 예외 계층 구조를 정의하는 편이 훨씬 강력합니다.&lt;br&gt;
모듈에 최상위 Exception을 정의하고 모듈이 발생시키는 다른 모든 예가 이 최상위 예외를 상속하게 만듦으로써 API에서 발생하는 예외의 계층 구조를 만들 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# my_module.py&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Exception&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 triple-quoted-string string&quot;&gt;&quot;&quot;&quot;이 모듈에서 발생할 모든 예외의 상위 클래스.&quot;&quot;&quot;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InvalidDensityError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Error&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 triple-quoted-string string&quot;&gt;&quot;&quot;&quot;밀도 값이 잘못된 경우.&quot;&quot;&quot;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;InvalidVolumeError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Error&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 triple-quoted-string string&quot;&gt;&quot;&quot;&quot;부피 값이 잘못된 경우.&quot;&quot;&quot;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determine_weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;volume&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; density&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; density &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; InvalidDensityError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;밀도는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; volume &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; InvalidVolumeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;부피는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; volume &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        density &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; volume&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이번에는 이렇게 새로운 예외 계층을 정의하면 어떤 점이 좋은지 알아보겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;-새로운-예외-계층을-정의하면-api를-잘못-사용한-경우를-더-쉽게-이해할-수-있습니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%98%88%EC%99%B8-%EA%B3%84%EC%B8%B5%EC%9D%84-%EC%A0%95%EC%9D%98%ED%95%98%EB%A9%B4-api%EB%A5%BC-%EC%9E%98%EB%AA%BB-%EC%82%AC%EC%9A%A9%ED%95%9C-%EA%B2%BD%EC%9A%B0%EB%A5%BC-%EB%8D%94-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4&quot; aria-label=&quot; 새로운 예외 계층을 정의하면 api를 잘못 사용한 경우를 더 쉽게 이해할 수 있습니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;✅ 새로운 예외 계층을 정의하면 API를 잘못 사용한 경우를 더 쉽게 이해할 수 있습니다.&lt;/h3&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;try&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;
    weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; my_module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;determine_weight&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; my_module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidDensityError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
    logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;호출 코드에 버그가 있음&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ERROR&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;호출 코드에 버그가 있음
Traceback &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;most recent call last&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;C:\Users\user\PycharmProjects\issueKeyword\test.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;module&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; determine_weight&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;C:\Users\user\PycharmProjects\issueKeyword\test.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; determine_weight
    &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; InvalidVolumeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;부피는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
InvalidVolumeError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 부피는 &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;보다 커야 합니다&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/131391e36d8285e28d097ce87f695892/8cb6d/2023-07-30-23-07-33.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 83.33333333333334%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRlAAAABXRUJQVlA4IEQAAABwAwCdASoUABEAPtFcqE4oJSQiKAqpABoJaQAALkDSxgC3HzAA/vYJVBEXV6p+dxfc5w2iAgRqAKat+0ckShNuQsAAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/131391e36d8285e28d097ce87f695892/a59e9/2023-07-30-23-07-33.webp 192w,
/static/131391e36d8285e28d097ce87f695892/0ca9f/2023-07-30-23-07-33.webp 384w,
/static/131391e36d8285e28d097ce87f695892/dc9b9/2023-07-30-23-07-33.webp 768w,
/static/131391e36d8285e28d097ce87f695892/e2c2f/2023-07-30-23-07-33.webp 1152w,
/static/131391e36d8285e28d097ce87f695892/f3efb/2023-07-30-23-07-33.webp 1536w,
/static/131391e36d8285e28d097ce87f695892/8cb6d/2023-07-30-23-07-33.webp 1576w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/131391e36d8285e28d097ce87f695892/a59e9/2023-07-30-23-07-33.webp 192w,
/static/131391e36d8285e28d097ce87f695892/0ca9f/2023-07-30-23-07-33.webp 384w,
/static/131391e36d8285e28d097ce87f695892/dc9b9/2023-07-30-23-07-33.webp 768w,
/static/131391e36d8285e28d097ce87f695892/e2c2f/2023-07-30-23-07-33.webp 1152w,
/static/131391e36d8285e28d097ce87f695892/f3efb/2023-07-30-23-07-33.webp 1536w,
/static/131391e36d8285e28d097ce87f695892/8cb6d/2023-07-30-23-07-33.webp 1576w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/131391e36d8285e28d097ce87f695892/dc9b9/2023-07-30-23-07-33.webp&quot;
            alt=&quot;예외 처리 구조 &quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
이렇게 하면 기존에 있었던 InvalidVolumeError를 통해 에러가 발생했구나를 바로 알 수 있고, 에러를 처리하기 쉬워집니다.&lt;/p&gt;
&lt;p&gt;그럼 이제 이렇게 커스텀한 예외 구조 계층을 만들어봤으니 다시 최상위 예외가 있으면 왜 좋은지 알아봅시다!@&lt;/p&gt;
&lt;h2 id=&quot;-최상위-예외와-커스텀한-예외-구조-계층을-쓰면-좋은-점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%B5%9C%EC%83%81%EC%9C%84-%EC%98%88%EC%99%B8%EC%99%80-%EC%BB%A4%EC%8A%A4%ED%85%80%ED%95%9C-%EC%98%88%EC%99%B8-%EA%B5%AC%EC%A1%B0-%EA%B3%84%EC%B8%B5%EC%9D%84-%EC%93%B0%EB%A9%B4-%EC%A2%8B%EC%9D%80-%EC%A0%90&quot; aria-label=&quot; 최상위 예외와 커스텀한 예외 구조 계층을 쓰면 좋은 점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;❓ 최상위 예외와 커스텀한 예외 구조 계층을 쓰면 좋은 점&lt;/h2&gt;
&lt;h3 id=&quot;-최상위-예외가-있으면-예상치-못한-예외를-처리가-가능하고-api-코드의-버그를-발견할-때-도움이-됩니다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%B5%9C%EC%83%81%EC%9C%84-%EC%98%88%EC%99%B8%EA%B0%80-%EC%9E%88%EC%9C%BC%EB%A9%B4-%EC%98%88%EC%83%81%EC%B9%98-%EB%AA%BB%ED%95%9C-%EC%98%88%EC%99%B8%EB%A5%BC-%EC%B2%98%EB%A6%AC%EA%B0%80-%EA%B0%80%EB%8A%A5%ED%95%98%EA%B3%A0-api-%EC%BD%94%EB%93%9C%EC%9D%98-%EB%B2%84%EA%B7%B8%EB%A5%BC-%EB%B0%9C%EA%B2%AC%ED%95%A0-%EB%95%8C-%EB%8F%84%EC%9B%80%EC%9D%B4-%EB%90%A9%EB%8B%88%EB%8B%A4&quot; aria-label=&quot; 최상위 예외가 있으면 예상치 못한 예외를 처리가 가능하고 api 코드의 버그를 발견할 때 도움이 됩니다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;✅ 최상위 예외가 있으면 예상치 못한 예외를 처리가 가능하고, API 코드의 버그를 발견할 때 도움이 됩니다.&lt;/h3&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;determine_weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;volume&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; density&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; density &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; InvalidDensityError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;밀도는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; volume &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; InvalidVolumeError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;부피는 0보다 커야 합니다&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; volume &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        density &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; volume

&lt;span class=&quot;token keyword&quot;&gt;try&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;
    weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; my_module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;determine_weight&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; my_module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;InvalidDensityError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
    logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;호출 코드에 버그가 있음&apos;&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;현재 코드의 최상위 부분에서는 InvalidDensityError, 즉 밀도만 따로 weight를 0으로 처리하고 있을 뿐, 따로 부피에 대해서는 예외를 처리해주지 않고 있습니다.&lt;br&gt;
이럴 때 &lt;mark&gt;라이브러리에 있는 Exception을 사용하면 모든 예외 상황에 대해서 처리해서 프로세스가 종료되지 않게 할 수 있고 로그를 찍어 에러를 쉽게 파악할 수 있습니다.&lt;/mark&gt;&lt;br&gt;
그리고 Exception의 Stack trace를 통해 따로 InvalidVolumeError에 대한 예외 처리를 InvalidDensityError와 같이 weight = 0으로 처리를 따로 해줄 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;제가-사용했던-커스텀한-예외-계층과-최상위-예외&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%9C%EA%B0%80-%EC%82%AC%EC%9A%A9%ED%96%88%EB%8D%98-%EC%BB%A4%EC%8A%A4%ED%85%80%ED%95%9C-%EC%98%88%EC%99%B8-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EC%B5%9C%EC%83%81%EC%9C%84-%EC%98%88%EC%99%B8&quot; aria-label=&quot;제가 사용했던 커스텀한 예외 계층과 최상위 예외 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;제가 사용했던 커스텀한 예외 계층과 최상위 예외&lt;/h3&gt;
&lt;p&gt;그리고 저 같은 경우에는 따로 제가 만든 예외 계층을 사용하여 어디에서 에러가 발생했는지를 확실하게 알기 위해 각각의 위치에서 제가 만든 다른 예외 계층을 사용했습니다.&lt;/p&gt;
&lt;p&gt;제가 사용했던 코드의 예시를 잠깐 드리면..!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;board_page_crawling&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;try&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;except&lt;/span&gt; TimeoutException&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;raise&lt;/span&gt; SeleniumError&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;Selenium 크롤링 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;에서 도중 Timeout 발생&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Crawling&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;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        crawling_list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; board_page_crawling&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        insert&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;crawling_list&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; SeleniumError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Selenium에서 에러 발생&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; InsertError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Insert에서 에러 발생&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;except&lt;/span&gt; Exception&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        logging&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exception&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;알 수 없는 오류 발생&apos;&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;이런식으로 사용했었습니다. 이렇게 사용하니 에러 파악이 예전보다 손 쉬워졌고 따로 로그DB를 만들어 컬럼에 Type을 붙여 어떤 함수에서 발생했는지 특정할 수 있었습니다. 그리고 특정 웹사이트 게시물에 대해서 에러가 발생해도 프로세스는 종료되지 않고 크롤링을 이어나갈 수 있었습니다.&lt;/p&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;모듈에서 사용할 최상위 예외를 정의하면 API 프로세스를 종료되지 않고 보호할 수 있습니다.&lt;/li&gt;
&lt;li&gt;자신이 사용하는 예외 계층과 최상위 예외를 같이 사용하면 API 코드의 버그를 쉽게 찾을 수 있습니다.&lt;/li&gt;
&lt;li&gt;파이썬 Exception을 최상위 예외에 예외 처리를 해준다면 예상치 못한 경우에 대해서도 로그를 남기고 프로세스가 종료되지 않게 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[파이썬에서 정렬을 잘 사용하는 법]]></title><description><![CDATA[파이썬 sort(), sorted(), key, cmp_to_key]]></description><link>https://ambosing.github.io/python/sort/</link><guid isPermaLink="false">https://ambosing.github.io/python/sort/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Mon, 24 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;코딩테스트 문제를 풀다가 정렬 문제를 마주한 적이 있습니다..!&lt;br&gt;
정렬에서는 sort, key 정도만 알고 있었는데 그 이상의 것들로 푸시는 분들도 있더라구요..!&lt;br&gt;
이번에는 거기서 영감을 받고, 현재 읽고 있는 책 내용에도 존재해서 이번에는 정렬에 대해서 조금 더 깊이 알아보려고 합니다!&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조하였습니다.&lt;br&gt;
만약 문제 발생시 글을 삭제처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;sort와-sorted&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sort%EC%99%80-sorted&quot; aria-label=&quot;sort와 sorted permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;sort와 sorted&lt;/h2&gt;
&lt;p&gt;파이썬 리스트에는 리스트를 제자리에서(in-place) 수정하는 내장 &lt;mark&gt;list.sort()&lt;/mark&gt; 메서드가 존재합니다! 또한, iterable로부터 새로운 정렬된 리스트를 만드는 &lt;mark&gt;sorted()&lt;/mark&gt; 내장 함수도 존재합니다.&lt;/p&gt;
&lt;p&gt;먼저 sorted() 내장 함수 사용법을 봅시다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&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 number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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;sorted()메서드와는 달리 sort() 함수는 리스트에만 존재합니다.&lt;br&gt;
list.sort() 메서드를 사용해서 제자리(in-place)에서 수정할 수 있습니다.&lt;br&gt;
list.sort()는 None을 반환합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&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;&gt;&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
a
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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;일반적으로 list.sort()는 sorted()보다는 불편합니다..!
하지만 원래 목록이 필요하지 않다면, 새로운 리스트를 하나 더 만드는 sorted()보다 효율적입니다.(공간복잡도가 낮아집니다!)
(sorted()는 새로운 리스트를 반환하므로)&lt;/p&gt;
&lt;p&gt;또 다른 점은 list.sort() 메서드가 리스트에게만 정의된다는 것입니다. 이와 달리, sorted() 함수는 모든 iterable을 받아들입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;D&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;E&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;복잡한-기준을-사용할-때는-key-파라미터를-사용하자&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%B3%B5%EC%9E%A1%ED%95%9C-%EA%B8%B0%EC%A4%80%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C%EB%8A%94-key-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90&quot; aria-label=&quot;복잡한 기준을 사용할 때는 key 파라미터를 사용하자 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;복잡한 기준을 사용할 때는 key 파라미터를 사용하자!&lt;/h2&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Tool&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; weight

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__repr__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&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 string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;Tool(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token conversion-option punctuation&quot;&gt;!r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&apos;&lt;/span&gt;&lt;/span&gt;

tools &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;수준계&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.5&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;해머&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.25&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;스크류드라이버&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;끌&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 코드가 있다고 가정합시다!&lt;br&gt;
기본적인 list.sort()를 사용하면 어떤 기준으로 정렬할 지 모르기 때문에 에러가 발생합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;Traceback &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;most recent call last&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;C:\Users\user\PycharmProjects\issueKeyword\test.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;module&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
TypeError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&amp;lt;&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; supported between instances of &lt;span class=&quot;token string&quot;&gt;&apos;Tool&apos;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Tool&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;정렬을 사용하고 싶은 애트리뷰트가 객체에 들어 있는 경우가 많습니다. 이런 상황을 지원하기 위해 sort에는 key라는 파라미터가 존재합니다.&lt;br&gt;
key는 함수여야 하고, 정렬 중인 리스트의 원소가 전달되어야 합니다.&lt;br&gt;
다음은 이름으로 Tool들을 정렬해 보겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;미정렬:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;정렬: &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&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;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;수준계&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;해머&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.25&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;스크류드라이버&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;끌&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.25&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;&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;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;끌&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.25&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;수준계&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;스크류드라이버&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;해머&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.25&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;이번에는 Weight로 정렬하는 람다 함수를 만들어서 sort의 key 파라미터로 전달해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;무게순 정렬:&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&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;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;끌&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.25&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;스크류드라이버&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;해머&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.25&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;수준계&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.5&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;그렇다면 weight로 먼저 정렬한 다음에 name으로 정렬하고 싶다면 어떻게 해야 할까요..!?&lt;br&gt;
-&gt; 바로 키에 Tuple 타입을 사용하는 겁니다.&lt;/p&gt;
&lt;p&gt;튜플은 기본적으로 비교가 가능하며 자연스러운 순서가 정해져 있습니다. 이는 sort에 필요한 &lt;code class=&quot;language-text&quot;&gt;__lt__&lt;/code&gt;정의가 들어 있다는 말과 동일합니다.&lt;/p&gt;
&lt;p&gt;먼저 weight로 정렬하고 그 후 name으로 정렬해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;power_tools &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;드릴&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;원형 톱&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;착암기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&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;
    Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;연마기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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;
power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;power_tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;드릴&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;연마기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;원형 톱&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;착암기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;숫자 값의 경우 &lt;code class=&quot;language-text&quot;&gt;- 연산자&lt;/code&gt;를 사용해 정렬 방향을 변경할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&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;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&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;# weight에 - 연산자 (역순 정렬)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;power_tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;착암기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;원형 톱&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;드릴&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;연마기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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;모든 타입에 부호 반전을 사용할 수는 없습니다. name을 반전시켜서 앞처럼 역순 정렬 해보려고 해도 실패하고 맙니다..!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;Traceback &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;most recent call last&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;C:\Users\user\PycharmProjects\issueKeyword\test.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;module&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  File &lt;span class=&quot;token string&quot;&gt;&quot;C:\Users\user\PycharmProjects\issueKeyword\test.py&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; line &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
TypeError&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bad operand &lt;span class=&quot;token builtin&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; unary &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;str&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;파이썬은-stable-정렬을-제공한다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%9D%80-stable-%EC%A0%95%EB%A0%AC%EC%9D%84-%EC%A0%9C%EA%B3%B5%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;파이썬은 stable 정렬을 제공한다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;파이썬은 Stable 정렬을 제공한다..!&lt;/h2&gt;
&lt;p&gt;파이썬은 Stable 정렬 알고리즘을 제공합니다.&lt;br&gt;
아니 갑자기 왜 Stable 정렬이냐구요..?&lt;br&gt;
이유는 바로 뒤에 나옵니다!
리스트 타입의 sort 메서드는 key 함수가 반환하는 값이 서로 같은 경우 리스트에 들어 있던 원래 순서를 그대로 유지해줍니다!&lt;br&gt;
이는 같은 리스트에 대해 서로 다른 기준으로 sort를 여러 번 호출해도 된다는 뜻입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# power_tools.sort(key=lambda x: (x.weight, -x.name))&lt;/span&gt;

power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reverse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# name 기준 내림차순&lt;/span&gt;
power_tools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;weight&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# weight 기준 오름차순&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;power_tools&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;연마기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;드릴&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;원형 톱&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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; Tool&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;착암기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;40&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;파이썬의 Stable한 정렬 덕분에 아까 에러가 발생했던 (weight, -name)에 대한 정렬 결과를 위 코드처럼 두 번 정렬함으로써 결과를 도출할 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;cmp_to_key&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cmp_to_key&quot; aria-label=&quot;cmp_to_key permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;cmp_to_key&lt;/h2&gt;
&lt;p&gt;파이썬에서 key 파라미터로 해결되지 않고, 두 변수를 변경시켜 정렬을 해야하는 경우가 있습니다. 그럴 때는 functools의 cmp_to_key를 사용하면 됩니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; functools &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cmp_to_key

&lt;span class=&quot;token comment&quot;&gt;# 구식 비교 함수&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b  &lt;span class=&quot;token comment&quot;&gt;# a &amp;lt; b 이면 음수 반환, a == b 이면 0 반환, a &gt; b 이면 양수 반환&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 키 함수로 변환&lt;/span&gt;
key_func &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cmp_to_key&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;compare&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 이제 sort나 sorted와 함께 사용할 수 있습니다&lt;/span&gt;
my_list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
my_list&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;key_func&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;my_list&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 출력: [1, 2, 5, 7, 9]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;cmp_to_key-예시&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cmp_to_key-%EC%98%88%EC%8B%9C&quot; aria-label=&quot;cmp_to_key 예시 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;cmp_to_key 예시&lt;/h2&gt;
&lt;p&gt;프로그래머스의 가장 큰 수라는 문제에서 cmp_to_key를 활용하여 문제를 풀 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;문제-설명&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%A0%9C-%EC%84%A4%EB%AA%85&quot; aria-label=&quot;문제 설명 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문제 설명&lt;/h3&gt;
&lt;p&gt;0 또는 양의 정수가 주어졌을 때, 정수를 이어 붙여 만들 수 있는 가장 큰 수를 알아내 주세요.&lt;/p&gt;
&lt;p&gt;예를 들어, 주어진 정수가 [6, 10, 2]라면 [6102, 6210, 1062, 1026, 2610, 2106]를 만들 수 있고, 이중 가장 큰 수는 6210입니다.&lt;/p&gt;
&lt;p&gt;0 또는 양의 정수가 담긴 배열 numbers가 매개변수로 주어질 때, 순서를 재배치하여 만들 수 있는 가장 큰 수를 문자열로 바꾸어 return 하도록 solution 함수를 작성해주세요.&lt;/p&gt;
&lt;h3 id=&quot;제한-사항&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%9C%ED%95%9C-%EC%82%AC%ED%95%AD&quot; aria-label=&quot;제한 사항 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;제한 사항&lt;/h3&gt;
&lt;p&gt;numbers의 길이는 1 이상 100,000 이하입니다.
numbers의 원소는 0 이상 1,000 이하입니다.
정답이 너무 클 수 있으니 문자열로 바꾸어 return 합니다.&lt;/p&gt;
&lt;h3 id=&quot;입출력-예&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88&quot; aria-label=&quot;입출력 예 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;입출력 예&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;numbers&lt;/th&gt;
&lt;th&gt;return&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;[6, 10, 2]&lt;/td&gt;
&lt;td&gt;“6210”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[3, 30, 34, 5, 9]&lt;/td&gt;
&lt;td&gt;“9534330”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; functools &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; cmp_to_key


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;cmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    ab&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ba &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; a
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; ab &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; ba&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 number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; ab &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; ba&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 operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;solution&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;cmp_to_key&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;cmp&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; reverse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;numbers&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;이 문제의 해결 방법은 numbers 리스트에 있는 값들을 적절히 조합하여 가장 큰 수를 만드는 문제입니다.&lt;br&gt;
이 때, cmp_to_key를 사용하여 함수를 정의해 a + b, b + a의 대소 비교를 통해 정렬을 구현한 적이 있습니다!!&lt;/p&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;list.sort()를 사용하면 제자리에서(in-place)로 정렬을 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;sorted() 메서드를 사용하면 편리하지만 새로운 리스트를 반환하므로 비효율적입니다. 하지만 다른 iterable 객체를 모두 정렬시킬 수 있습니다.&lt;/li&gt;
&lt;li&gt;sort 메서드의 key 파라미터를 사용하면 리스트의 각 원소 대신 비교에 사용할 객체를 반환하는 도우미 함수를 제공할 수 있습니다.&lt;/li&gt;
&lt;li&gt;key 함수에서 튜플을 반환하면 여러 정렬 기준을 하나로 엮을 수 있습니다. &lt;code class=&quot;language-text&quot;&gt;- 연산자&lt;/code&gt;를 사용하면 숫자 타입인 경우 역순 정렬을 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;부호를 바꿀 수 없는 타입의 경우, 여러 정렬 기준을 조합하려면 각 정렬 기준마다 reverse 값으로 정렬 순서를 지정하면서 sort 메서드를 여러 번 사용해야 합니다. 이 때 &lt;mark&gt;정렬 기준의 우선순위가 점점 높아지는 순서로 sort를 호출해야 합니다.&lt;/mark&gt;&lt;/br&gt;ex) 정렬 기준 (a, b, c) -&gt; sort(key=c), sort(key=b), sort(key=a)&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[파이썬에서 대입식을 통해 코드 중복을 없애는 방법 feat. 왈러스(Walrus)]]></title><description><![CDATA[파이썬 3.8에서 나온 신기능이라구!]]></description><link>https://ambosing.github.io/python/walrus/</link><guid isPermaLink="false">https://ambosing.github.io/python/walrus/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Wed, 19 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;책을 읽다가 새로운 기능인 왈러스를 알게되었는데, 이 기능을 다른 분들도 알게 된다면 좋을 것 같아서 정리해봅니다!&lt;br&gt;
아!! 이 기능은 &lt;mark&gt;파이썬 3.8이상&lt;/mark&gt;부터 사용가능합니다!&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조하였습니다.&lt;br&gt;
만약 문제 발생시 글을 삭제처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;중복이-되는-문제-상황&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A4%91%EB%B3%B5%EC%9D%B4-%EB%90%98%EB%8A%94-%EB%AC%B8%EC%A0%9C-%EC%83%81%ED%99%A9&quot; aria-label=&quot;중복이 되는 문제 상황 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;중복이 되는 문제 상황&lt;/h2&gt;
&lt;p&gt;주스 바에서 사용할 신선한 과일 바구니를 관리한다고 해봅시다!
고객이 레모네이드를 주문했다면 과즙을 낼 레몬이 바구니에 최소 하나는 있어야 합니다. 다음 코드는 레몬의 개수를 읽어와서 그 값이 0이 아닌지 확인하는 코드입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;fresh_fruit &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;사과&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;바나나&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;레몬&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;make_lemonade&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&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;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;out_of_stock&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;

count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;레몬&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    make_lemonade&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    out_of_stock&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;이 코드는 문제점이 있습니다. count 변수는 if 문의 첫 번째 블록 안에서만 쓰인다는 것입니다.&lt;br&gt;
파이썬에서는 이런 식으로 값을 가져와서 그 값이 0이 아닌지 검사한 후 사용하는 패턴이 자주 발생합니다.&lt;/p&gt;
&lt;h2 id=&quot;왈러스대입식을-활용한-해결-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%88%EB%9F%AC%EC%8A%A4%EB%8C%80%EC%9E%85%EC%8B%9D%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot;왈러스대입식을 활용한 해결 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왈러스(대입식)을 활용한 해결 방법&lt;/h2&gt;
&lt;p&gt;왈러스(대입식)이 추가되면서 이런 유형의 코드를 제대로 처리할 수 있게 되었습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;레몬&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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;
	make_lemonade&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;한 줄 더 짧기도 하지만, count가 if 문의 첫 번째 블록에서만 의미가 있다는 점이 명확히 보이기 때문에 이 코드가 더 읽기 쉽습니다.&lt;/p&gt;
&lt;h2 id=&quot;if-elif-else-깊게-내포-시키는-문제&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#if-elif-else-%EA%B9%8A%EA%B2%8C-%EB%82%B4%ED%8F%AC-%EC%8B%9C%ED%82%A4%EB%8A%94-%EB%AC%B8%EC%A0%9C&quot; aria-label=&quot;if elif else 깊게 내포 시키는 문제 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;if, elif, else 깊게 내포 시키는 문제!&lt;/h2&gt;
&lt;p&gt;파이썬에는 유연한 switch/case 문이 없다는 점도 파이썬을 처음 접한 프로그래머들을 자주 당황하게 만드는 원인 중 하나입니다.
파이썬에서 이런 유형의 기능을 흉내 내는 일반적인 스타일은 if, elif, else 문을 깊게 내포시키는 방법이 있습니다.&lt;/p&gt;
&lt;p&gt;예를 들어, 현재 주스 바에서 만들 수 있는 주스 중 가장 좋은 주스를 고객에게 제공한다고 합시다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;바나나&lt;/li&gt;
&lt;li&gt;애플 주스&lt;/li&gt;
&lt;li&gt;레모네이드&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;위의 순서대로 제공하는 로직입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    pieces &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slice_bananas&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_smoothies&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pieces&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;사과&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_cider&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;레몬&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_lemonade&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;아무것도 없음&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;왈러스-연산자를-사용하여-해결&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%88%EB%9F%AC%EC%8A%A4-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%ED%95%B4%EA%B2%B0&quot; aria-label=&quot;왈러스 연산자를 사용하여 해결 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왈러스 연산자를 사용하여 해결!&lt;/h2&gt;
&lt;p&gt;앞에서 봤던 if-else 중첩은 코드를 보는 사람을 어렵게 합니다..!&lt;br&gt;
그래서 이 코드도 왈러스(대입식) 연산자를 사용하여 해결해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;바나나&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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 number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    pieces &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slice_bananas&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_smoothies&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pieces&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;사과&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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 number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_cider&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;레몬&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&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;
    to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_lemonade&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    to_enjoy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;아무것도 없음&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;왈러스 연산자를 사용하면 switch/case문 같은 다중 선택 전용 구문과 거의 비슷한 느낌이 드는 우아한 해법을 만들 수 있습니다.&lt;/p&gt;
&lt;h2 id=&quot;왈러스-연산자로-do-while-만들기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%88%EB%9F%AC%EC%8A%A4-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A1%9C-do-while-%EB%A7%8C%EB%93%A4%EA%B8%B0&quot; aria-label=&quot;왈러스 연산자로 do while 만들기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왈러스 연산자로 Do-While 만들기&lt;/h2&gt;
&lt;p&gt;파이썬에는 Do-While 루프가 없습니다!&lt;/p&gt;
&lt;p&gt;먼저 예를 들겠습니다. 신선한 과일이 배달돼서 이 과일을 모두 주스로 만든 후 병에 담기로 했다고 합시다.
다음은 while 루프로 이 로직을 구현한 코드입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;bottles &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;
fresh_fruit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pick_fruit&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;# 1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; fruit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&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;
        batch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_juice&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fruit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        bottles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;extend&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    fresh_fruit &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pick_fruit&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;# 2&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bottles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 fresh_fruit = pick_fruit() 호출을 두 번하므로 반복적입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;호출의 이유&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;루프 직전에 초기화&lt;/li&gt;
&lt;li&gt;루프의 끝에서 배달받은 신선한 과일을 다시 선택&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;왈러스 연산자를 사용하면 while 루프에서 매번 fresh_fruit 변수에 대입하고 조건을 검사할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;bottles &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 keyword&quot;&gt;while&lt;/span&gt; fresh_fruit &lt;span class=&quot;token operator&quot;&gt;:=&lt;/span&gt; pick_fruit&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;for&lt;/span&gt; fruit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; fresh_fruit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&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;
        batch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; make_juice&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fruit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        bottles&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;extend&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;batch&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bottles&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;대입식에서는 왈러스 연산자(:=)를 사용해 하나의 식 안에서 변수 이름에 값을 대입하면서 이 값을 평가할 수 있고, 중복을 줄일 수 있습니다.&lt;/li&gt;
&lt;li&gt;파이썬에서는 Switch/case 문이나 Do/While 루프를 쓸 수 없지만, 대입식을 사용하면 이런 기능을 더 깔끔하게 흉내 낼 수 있습니다.&lt;/li&gt;
&lt;li&gt;대입식, 즉 왈러스 연산자(:=) 파이썬 3.8이상부터 사용할 수 있다는 걸 꼭 기억하세요!!&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[반복문 파이썬스럽게 쓰는 방법]]></title><description><![CDATA[파이썬 반복문, 너는 다 알고 있니 ? 아니.. 그러면 드루와]]></description><link>https://ambosing.github.io/python/iterate_like_python/</link><guid isPermaLink="false">https://ambosing.github.io/python/iterate_like_python/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Sun, 09 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;다른 언어들도 각각의 특성에 맞게 반복문이 특징이 있을 때가 있는데요.&lt;br&gt;
파이썬은 매우 특이한 케이스라고 저는 생각합니다..!&lt;br&gt;
그래서 이번에는 특이하다고 생각되는 반복문을 조금 더 파이썬스럽게 쓸 수 있는 방법들을 알아보고자 합니다&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조하였습니다.&lt;br&gt;
만약 문제 발생시 글을 삭제처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;range보단-enumerate&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#range%EB%B3%B4%EB%8B%A8-enumerate&quot; aria-label=&quot;range보단 enumerate permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;range보단 enumerate!&lt;/h2&gt;
&lt;p&gt;range 내장 함수는 어떤 정수 집합을 반복하는 루프가 필요할 때 유용합니다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 0 1 2 3 4 5 6 7 8 9 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;리스트를 반복하면서 리스트의 몇 번째 원소를 처리 중인지를 알아야 할 때가 있습니다.&lt;br&gt;
예를 들어, 아이스크림 맛의 선호도 순위를 출력하고 싶다고 합시다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;flavor_list &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;바닐라&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;초콜릿&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;피칸&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;딸기&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flavor_list&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;
    flavor &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; flavor_list&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;flavor&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 조금 투박해 보입니다..!&lt;br&gt;
일단 list의 길이를 알아야 하고, 인덱스를 사용해 배열 원소에 접근해야 합니다.&lt;br&gt;
이렇게 단계가 여러 개이므로 코드의 가독성이 떨어집니다.&lt;/p&gt;
&lt;p&gt;파이썬은 이런 문제를 해결할 수 있는 &lt;mark&gt;enumerate&lt;/mark&gt; 내장함수를 제공합니다.&lt;br&gt;
enumerate는 이터레이터를 &lt;strong&gt;지연 계산 제너레이터(lazy generator)&lt;/strong&gt; 로 감쌉니다.
enumerate는 인덱스와 다음 값으로 이뤄진 쌍을 넘겨줍니다. &amp;#x3C;= yield 시키는 것과 동일!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;it &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flavor_list&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&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;# (0, &apos;바닐라&apos;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# (1, &apos;초콜릿&apos;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;enumerate가 넘겨주는 각 쌍을 for문에서 간결하게 언패킹할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flavor &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flavor_list&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;flavor&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 바닐라
&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 초콜릿
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 피칸
&lt;span class=&quot;token number&quot;&gt;4&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;enumerate는 두 번째 파라미터로 어디부터 수를 세기 시작할지 지정할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; flavor &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flavor_list&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;flavor&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 바닐라
&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 초콜릿
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 피칸
&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 딸기&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;mark&gt;이 부분에서 주의할점은 1부터 센다고 해서 인덱스 0을 빼고 반복하는 것이 아니라 인덱스에만 +1되는 것을 주의하세요!&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;&lt;del&gt;저는 착각하고 사용해서 당함…&lt;/del&gt;&lt;/p&gt;
&lt;h2 id=&quot;여러-이터레이터를-한-번에-zip으로&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%97%AC%EB%9F%AC-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%ED%84%B0%EB%A5%BC-%ED%95%9C-%EB%B2%88%EC%97%90-zip%EC%9C%BC%EB%A1%9C&quot; aria-label=&quot;여러 이터레이터를 한 번에 zip으로 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;여러 이터레이터를 한 번에 zip으로!&lt;/h2&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;names &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;Cecilia&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;남궁민수&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;毛泽东&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
counts &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 builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; n &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; names&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;names&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;counts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Cecilia&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;남궁민수&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;毛泽东&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 number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위와 같이 주어졌을 때, 가장 긴 이름과 가장 긴 이름의 길이를 구하고 싶다고 해봅시다.&lt;/p&gt;
&lt;p&gt;우리는 바로 위에서 enumerate를 배웠으니 enumerate를 써봅시다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;longest_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;
max_count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;names&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; counts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; max_count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        longest_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name
        max_count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; count

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;longest_name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;max_count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
Cecilia
&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;enumerate를 사용하니깐 깔끔해보이긴 하지만 아직 counts의 인덱싱이 마음에 들지 않습니다.&lt;br&gt;
이 때 코드를 더 깔끔하게 만들 수 있는 것이 &lt;strong&gt;zip&lt;/strong&gt;이라는 내장 함수입니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;zip은 둘 이상의 이터레이터를 지연 계산 제너레이터를 사용해 묶어줍니다!&lt;/mark&gt;&lt;br&gt;
zip 제너레이터는 각 이터레이터의 다음 값이 들어 있는 튜플을 반환하고, for문에서는 이를 바로 언패킹 할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;names&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; counts&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; count &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; max_count&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        longest_name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name
        max_count &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; count&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제는 인덱싱 없이 코드가 아주 깔끔해졌습니다.&lt;/p&gt;
&lt;p&gt;zip에서는 주의할 점이 있는데요.&lt;br&gt;
바로 서로 다른 길이의 이터레이터가 입력으로 주어졌을 때입니다.
names에 하나의 길이를 추가한다고 했을 때, names의 길이는 4가 되고 counts의 길이는 3이 됩니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;names&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Rosalind&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# len(names) : 3 -&gt; 4&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;names&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; counts&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; 
Cecilia&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;
남궁민수&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
毛泽东&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;결과를 보시면 3개까지만 출력하는 것을 볼 수 있습니다.
&lt;mark&gt;zip은 자신이 감싼 이터레이터 중 어느 하나가 끝날 때까지 튜플을 내놓습니다. 따라서 출력은 가장 짧은 입력의 길이와 같습니다.&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;만약 긴 이터레이터의 뒷부분을 찍고 싶다면 itertools 내장 모듈에 있는 zip_longest를 사용하면 됩니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; itertools
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; itertools&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zip_longest&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;names&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; counts&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
Cecilia&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;
남궁민수&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
毛泽东&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
Rosalind&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;for나-while-뒤에-else-블록-사용하지-않기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#for%EB%82%98-while-%EB%92%A4%EC%97%90-else-%EB%B8%94%EB%A1%9D-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EA%B8%B0&quot; aria-label=&quot;for나 while 뒤에 else 블록 사용하지 않기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;for나 while 뒤에 else 블록 사용하지 않기!&lt;/h2&gt;
&lt;p&gt;파이썬에서는 반복문이 반복 수행하는 내부 블록 바로 다음에 else 블록을 추가할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Else block!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Else block!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
Loop &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
Loop &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
Loop &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
Else block!
Loop &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
Loop &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;for/else의 else 부분은 루프가 정상적으로 완료되어야 동작 하는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p&gt;빈 이터레이터나 반복문 조건이 처음부터 False였을 경우에도 else 블록이 바로 실행됩니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;token keyword&quot;&gt;in&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;이 줄은 실행되지 않음&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;For Else block!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;이 줄은 실행되지 않음&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;While Else block!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt;
For Else block!
While Else block!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이런 방식으로 동작하는 이유는 break를 했을 때는 동작하지 않고, 모든 반복이 끝날 때만 동작하는 경우가 유용하기 때문입니다!
이렇게 작성하면 가독성이 떨어지고 직관적이지 않습니다.&lt;/p&gt;
&lt;p&gt;이를 위해 해결할 방법 중 첫 번째는 원하는 조건을 찾자마자 빠르게 함수를 반환하는 방식입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;check&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;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&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 boolean&quot;&gt;False&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; check&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;if block!&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;두 번째 방법은 루프 안에서 원하는 대상을 찾았는지 나타내는 결과 변수를 도입하는 것입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;check2&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;
    is_not_break &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Loop&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            is_not_break &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; is_not_break


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; check2&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;if block!&apos;&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;파이썬에서 루프와 같은 간단한 구성 요소는 그 자체로 의미가 명확해야 합니다.
따라서 루프 뒤에 else 블록이 직관적이지 않기 때문에 되도록 사용하지 않는게 좋아보입니다!!&lt;/p&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;enumerate를 사용하면 이터레이터에 대해 루프를 돌면서 이터레이터에서 가져오는 원소의 인덱스까지 얻는 코드를 간결하게 작성할 수 있습니다!&lt;/li&gt;
&lt;li&gt;zip 내장 함수를 사용해 여러 이터레이터를 같이 이터레이션할 수 있습니다.&lt;/li&gt;
&lt;li&gt;입력 이터레이터의 길이가 서로 다르면 zip은 가장 짧은 이터레이터 길이까지만 튜플을 내놓고 더 긴 이터레이터의 나머지 원소는 무시합니다.&lt;/li&gt;
&lt;li&gt;서로 다른 이터레이터에 대해 더 긴 이터레이터까지 루프를 수행하려면 itertools 내장 모듈의 zip_longest 함수를 사용하면 됩니다!&lt;/li&gt;
&lt;li&gt;for/while 뒤에 오는 else 블록은 루프가 반복되는 도중에 break를 만나지 않은 경우에만 실행됩니다.&lt;/li&gt;
&lt;li&gt;for/while - else는 동작이 직관적이지 않고 혼동을 야기할 수 있으므로 else 블록을 사용하지 않는 게 좋습니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[파이썬에서 문자열 출력 잘하는 법]]></title><description><![CDATA[아니 이거 너무 좋은걸..?]]></description><link>https://ambosing.github.io/python/string_good/</link><guid isPermaLink="false">https://ambosing.github.io/python/string_good/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Sun, 09 Jul 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;파이썬을 사용하면서 문자열 가공을 가장 많이 처리할 겁니다. 어떤 언어보다도 문자열 처리하기가 제일 좋은 이유가 있기 때문이죠!&lt;br&gt;
그래서 이번에 파이썬에서 다양한 문자열 출력 방법이 있는데 그중 어떤 것이 왜 가장 좋은지 한 번 알아봅시다.&lt;br&gt;
결론이 급하신 분들은 맨 마지막 인터폴레이션만 보시면 될 것 같습니다!&lt;/p&gt;
&lt;p&gt;이번 글은 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001834494&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 코딩의 기술&lt;/a&gt;을 보고 참조하였습니다.&lt;br&gt;
만약 문제 발생시 글을 삭제처리 하도록 하겠습니다!&lt;/p&gt;
&lt;h2 id=&quot;-c-스타일-형식-문자열-출력-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-c-%EC%8A%A4%ED%83%80%EC%9D%BC-%ED%98%95%EC%8B%9D-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%B6%9C%EB%A0%A5-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot; c 스타일 형식 문자열 출력 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🥉 C 스타일 형식 문자열 출력 방법&lt;/h2&gt;
&lt;p&gt;C 스타일 형식 문자열은 파이썬에서 문자열을 형식화하는 방법 중 하나입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0b10111011&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0xc5f&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;이진수: %d, 십육진수: %d&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&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;# 이진수: 187, 십육진수: 3167&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;형식 문자열은 연산자 왼쪽에 있는 값을 끼워 넣을 자리를 표현하기 위해 %d 같은 형식 지정자를 사용합니다.&lt;br&gt;
파이썬의 형식 지정자 문법은 printf 함수에서 비롯됐습니다.&lt;/p&gt;
&lt;p&gt;하지만 이런 C 스타일 형식 문자열은 &lt;code class=&quot;language-text&quot;&gt;문제점&lt;/code&gt;이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;문제점 1. 형식화 식에서 오른쪽에 있는 tuple 내 데이터 값의 순서를 바꾸거나 값의 타입을 바꾸면 타입 변환이 불가능하므로 오류가 발생할 수 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my_var&apos;&lt;/span&gt;
value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.234&lt;/span&gt;
formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;%-10s = %.2f&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# my_var = 1.23&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# key와 value 순서 변경&lt;/span&gt;
reordered_tuple &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;%-10s = %.2f&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&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;/p&gt;
&lt;p&gt;&lt;strong&gt;문제점 2. 형식화를 하기 전에 값을 살짝 변경해야 한다면 식을 읽기가 매우 어렵습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;pantry &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 string&quot;&gt;&apos;아보카도&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.25&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 string&quot;&gt;&apos;바나나&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.5&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 string&quot;&gt;&apos;체리&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&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;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pantry&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;#%d: %-10s = %.2f&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&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;# #0: 아보카도      = 1.25&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# #1: 바나나     = 2.50&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# #2: 체리     = 15.00&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pantry&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;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;#%d: %-10s = %d&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&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 builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&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;이렇게 할 경우 형식화 식에 있는 tuple의 길이가 너무 길어져서 여러 줄에 나눠 써야 하는데, 가독성이 나빠집니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;문제점 3. 형식화 문자열에서 같은 값을 여러 번 사용하고 싶다면 튜플에서 같은 값을 여러 번 반복해야 합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;template &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;%s는 음식을 좋아해. %s가 요리하는 모습을 봐요.&apos;&lt;/span&gt;
name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;철수&apos;&lt;/span&gt;
formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; template &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;- 반복되는 부분&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&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;/p&gt;
&lt;p&gt;&lt;strong&gt;문제점 4. 형식화 식에 딕셔너리를 사용하면 문장이 번잡스러워집니다.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;각 키를 최소 두 번 반복하게 되고, 키에 해당하는 값이 변수에 들어 있다면 변수 이름까지 세 번 이상 같은 이름을 반복해서 사용할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;soup &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lentil&apos;&lt;/span&gt;
formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Today\&apos;s soup is %(soup)s.&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;soup&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; soup&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# soup가 4번 반복됨&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 문제점들이 있기 때문에 C 형식화 문자열 출력 방법을 추천하지 않습니다..!&lt;/p&gt;
&lt;h2 id=&quot;-내장-함수-format과-strformat-문자열-출력-방법&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98-format%EA%B3%BC-strformat-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%B6%9C%EB%A0%A5-%EB%B0%A9%EB%B2%95&quot; aria-label=&quot; 내장 함수 format과 strformat 문자열 출력 방법 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🥈 내장 함수 format과 str.format 문자열 출력 방법&lt;/h2&gt;
&lt;p&gt;파이썬 3부터는 더 표현력이 좋은 고급 문자열 형식화 기능이 도입됐습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1234.5678&lt;/span&gt;
formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;,.2f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my 문자열&apos;&lt;/span&gt;
formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;b&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;^20s&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; formatted&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 1,234.57&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# *        my 문자열        *&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;format을 이용한 방법도 형식 지정자를 붙일 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;{:&amp;lt;10} = {:.2f}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;%.2f%%&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12.5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# C 형식에서 %를 표현할 경우&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;{} replaces {{}}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.23&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;# my_var     = 1.23&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 12.50%&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# 1.23 replaces {}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;형식화한 값의 출력 순서를 변경할 수도 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;{1} = {0}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;문제점 1. 형식화를 하기 전에 값을 변경해야 경우에는 코드 읽기가 어려워집니다.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pantry&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
    new_style &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#{}: {:&amp;lt;10s} = {}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&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 builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&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 keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;new_style&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# #1: 아보카도       = 1&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# #2: 바나나        = 2&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# #3: 체리         = 15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;문제점 2. 딕셔너리의 Key가 반복되는 경우의 중복을 줄여주지는 못합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# C 스타일&lt;/span&gt;
old_template &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;Today\&apos;s soup is %(soup)s, &apos;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;buy one get two %(oyster)s oysters, &apos;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;and our special entrée is %(special)s.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
old_formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; template &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;soup&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;lentil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;oyster&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;tongyoung&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;special&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;schnitzel&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 comment&quot;&gt;# Format 함수 &lt;/span&gt;
new_template &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;Today\&apos;s soup is {soup}, &apos;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;buy one get two {oyster} oysters, &apos;&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;and our special entrée is {special}.&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
new_formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; new_template&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    soup&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;lentil&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    oyster&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;tongyoung&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    special&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;schnitzel&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&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%8F%B4%EB%A0%88%EC%9D%B4%EC%85%98%EC%9D%84-%ED%86%B5%ED%95%9C-%ED%98%95%EC%8B%9D-%EB%AC%B8%EC%9E%90%EC%97%B4&quot; aria-label=&quot; 인터폴레이션을 통한 형식 문자열 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🥇 인터폴레이션을 통한 형식 문자열&lt;/h2&gt;
&lt;p&gt;앞의 문제들을 한 번에 완전히 해결하기 위해 파이썬 3.6부터는 인터폴레이션(interpolation)을 형식 문자열(짧게 f-문자열이라고 부릅니다.)이 도입됐습니다.&lt;/p&gt;
&lt;p&gt;이 새로운 언어 문법에서는 형식 문자열 앞에 f 문자를 붙여야 합니다.&lt;br&gt;
f-문자열은 형식 문자열의 표현력을 극대화하고, 앞에서 설명한 문제점인 형식화 문자열에서 키와 값을 불필요하게 중복 지정해야 하는 경우를 없애줍니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;my_var&apos;&lt;/span&gt;
value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.234&lt;/span&gt;

formatted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;key&lt;span class=&quot;token conversion-option punctuation&quot;&gt;!r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;&amp;lt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token format-spec&quot;&gt;.2f&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;formatted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# &apos;my_var&apos;   = 1.23&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;{}안에 !r은 무엇일까요?&lt;br&gt;
!r은 raw String을 의미합니다! {} 안에 있는 표현식을 raw String으로 출력해줍니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;값을 약간 변경하고 싶을 때도 간결한 구문으로 표기할 수 있으므로, 앞에서 설명한 문제점(&lt;code class=&quot;language-text&quot;&gt;형식화를 하기 전에 값을 살짝 변경해야 한다면 식을 읽기가 매우 어렵습니다&lt;/code&gt;)을 해결할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pantry&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;# C 형식&lt;/span&gt;
	old_style &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#%d: %-10s = %d&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&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 builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&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;# format&lt;/span&gt;
	new_style &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;#{}: {:&amp;lt;10s} = {}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
			i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
			item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&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 builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&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;# interpolation&lt;/span&gt;
	f_string &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;#&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&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 format-spec&quot;&gt;&amp;lt;10s&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;count&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
			
	&lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt; old_style &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; new_style &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; f_string&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;파이썬 식을 형식 지정자 옵션에 넣을 수도 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;places &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
number &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1.23456&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-interpolation&quot;&gt;&lt;span class=&quot;token string&quot;&gt;f&apos;내가 고른 숫자는 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;number&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;places&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&lt;/span&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;값을 문자열로 형식화해야 하는 상황을 만나게 되면 다른 대안 대신 f-문자열을 택하면 될 것 같습니다!&lt;/p&gt;
&lt;h2 id=&quot;요약&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%94%EC%95%BD&quot; aria-label=&quot;요약 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;요약&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;% 연산자를 사용하는 C 스타일 형식화 문자열은 여러 가지 단점과 번잡성이라는 문제가 있습니다.&lt;/li&gt;
&lt;li&gt;str.format 메서드도 C 스타일 형식 문자열의 문제점을 그대로 가지고 있으므로, 가능하면 str.format 사용을 피하는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;f-문자열은 값을 문자열 안에 넣는 새로운 구문으로, C 스타일 형식화 문자열의 가장 큰 문제점을 해결해줍니다.&lt;/li&gt;
&lt;li&gt;f-문자열은 간결하지만, 위치 지정자 안에 임의의 파이썬 식을 직접 포함시킬 수 있으므로 매우 강력합니다.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[파이썬에서의 코드 악취 대응하기]]></title><description><![CDATA[으..~ 냄새! 얼른 제거하자!]]></description><link>https://ambosing.github.io/python/cleancode/</link><guid isPermaLink="false">https://ambosing.github.io/python/cleancode/</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Wed, 14 Jun 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;들어가기-전&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%A0%84&quot; aria-label=&quot;들어가기 전 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;들어가기 전&lt;/h2&gt;
&lt;p&gt;파이썬을 사용하면서 어떻게 하면 파이썬을 더욱 이쁘게 사용할 수 있을까?&lt;br&gt;
내가 정말 파이썬스럽게 코드를 짜고 있는 것인가라는 의문이 들었습니다..ㅠ&lt;br&gt;
그래서 이번에는 파이썬에서 악취나는 코드들을 살펴보고 그에 대한 해결 방안을 찾아보면서 파이썬에서의 클린 코드를 한층 업그레이드 해보려고 합니다!&lt;/p&gt;
&lt;h2 id=&quot;중복된-코드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A4%91%EB%B3%B5%EB%90%9C-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;중복된 코드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;중복된 코드&lt;/h2&gt;
&lt;p&gt;가장 흔한 코드는 역시 중복된 코드입니다! 먼저 중복된 코드를 보시고 나쁜 점을 살펴봅시다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 중복된 코드 예시&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 사각형의 넓이 계산&lt;/span&gt;
length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
rectangle_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; length &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; width
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;넓이:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rectangle_area&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 삼각형의 넓이 계산&lt;/span&gt;
base &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
triangle_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; base &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; height
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;넓이:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; triangle_area&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 원의 넓이 계산&lt;/span&gt;
radius &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
circle_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3.14&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; radius &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; radius
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;넓이:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; circle_area&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;넓이&lt;/code&gt;를 출력하는 부분이 중복되고 있습니다.&lt;/p&gt;
&lt;p&gt;중복된 코드의 나쁜 점은 다음과 같습니다&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;유지 보수의 어려움&lt;/mark&gt;: 중복된 코드가 있는 경우, 해당 코드의 수정이 필요한 경우 여러 곳에서 수정해야 합니다. 이는 시간 소모적이며, 실수로 일부 수정을 빠뜨리는 등의 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;코드의 가독성 저하&lt;/mark&gt;: 중복된 코드가 있는 경우, 같은 동작을 하는 코드가 여러 곳에 반복되므로 코드가 복잡해지고 가독성이 떨어집니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;오류 발생 가능성&lt;/mark&gt;: 중복된 코드는 여러 곳에서 동일한 동작을 수행하므로, 하나의 버그가 여러 곳에 영향을 미칠 수 있습니다. 또한, 중복된 코드의 복사 및 붙여넣기 작업 시 실수로 오타가 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;이러한 문제를 해결하기 위해 함수와 반복문을 사용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt; 함수로 중복 제거 &lt;/mark&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculate_square_area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;side&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; side &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; side

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculate_rectangle_area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&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; length &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; width

&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculate_triangle_area&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;base&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; height&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 number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; base &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; height

side &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
square_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculate_square_area&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;side&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

length &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;
width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
rectangle_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculate_rectangle_area&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; width&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

base &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;
triangle_area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculate_triangle_area&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;base&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; height&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;mark&gt; 반복문으로 중복 제거 &lt;/mark&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;shapes &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 string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;side&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&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 string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rectangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;width&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&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 string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;triangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;base&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;height&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&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;

areas &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 keyword&quot;&gt;for&lt;/span&gt; shape &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; shapes&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;square&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;side&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;side&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;rectangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;length&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;width&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;type&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;triangle&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        area &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;base&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;height&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    areas&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;area&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;areas&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예시에서는 도형의 종류와 해당 도형의 속성을 딕셔너리로 나타내고, 함수와 반복문을 사용하여 중복을 제거했습니다. 이를 통해 코드의 가독성이 향상되고, 유지 보수가 용이해집니다.&lt;/p&gt;
&lt;h2 id=&quot;중첩된-리스트-컴프리헨션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A4%91%EC%B2%A9%EB%90%9C-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98&quot; aria-label=&quot;중첩된 리스트 컴프리헨션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&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;#%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98&quot; aria-label=&quot;리스트 컴프리헨션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;리스트 컴프리헨션&lt;/h3&gt;
&lt;p&gt;리스트 컴프리헨션은 기존의 리스트를 사용하여 간단하게 새로운 리스트를 생성하는 방법입니다.&lt;/p&gt;
&lt;p&gt;먼저 각각의 컴프리헨션 생성 방법부터 보겠습니다!&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 기존 방식&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
squared_numbers &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 keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    squared_numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squared_numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 리스트 컴프리헨션 사용&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
squared_numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squared_numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드는 1부터 5까지의 숫자를 제곱하여 새로운 리스트를 생성하는 예시입니다. 리스트 컴프리헨션을 사용하면 반복문을 사용하지 않고도 간결하게 표현할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;집합-컴프리헨션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A7%91%ED%95%A9-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98&quot; aria-label=&quot;집합 컴프리헨션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;집합 컴프리헨션&lt;/h3&gt;
&lt;p&gt;집합 컴프리헨션은 리스트 컴프리헨션과 유사하지만, 중복된 원소를 가지지 않는 집합(set)을 생성합니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 기존 방식&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
unique_numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&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;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    unique_numbers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;unique_numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 집합 컴프리헨션 사용&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
unique_numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;num &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;unique_numbers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드는 중복된 숫자를 제거하여 집합을 생성하는 예시입니다. 집합 컴프리헨션을 사용하면 반복문을 사용하지 않고도 간단하게 중복을 제거할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;딕셔너리-컴프리헨션&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC-%EC%BB%B4%ED%94%84%EB%A6%AC%ED%97%A8%EC%85%98&quot; aria-label=&quot;딕셔너리 컴프리헨션 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;딕셔너리 컴프리헨션&lt;/h3&gt;
&lt;p&gt;딕셔너리 컴프리헨션은 리스트나 집합과 유사하게, 기존의 딕셔너리를 사용하여 새로운 딕셔너리를 생성하는 방법입니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 기존 방식&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
squared_dict &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 keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    squared_dict&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; num&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squared_dict&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 딕셔너리 컴프리헨션 사용&lt;/span&gt;
numbers &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
squared_dict &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; num&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; numbers&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squared_dict&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드는 1부터 5까지의 숫자를 키(key)로 하고, 해당 숫자의 제곱을 값(value)으로 갖는 딕셔너리를 생성하는 예시입니다. 딕셔너리 컴프리헨션을 사용하면 반복문을 사용하지 않고도 간단하게 딕셔너리를 생성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;파이썬은 컴프리헨션을 통해 반복문 코드를 한 줄로 줄일 수 있습니다!&lt;br&gt;
또한, 컴프리헨션은 중첩되게 사용될 수도 있습니다.&lt;br&gt;
중첩된 컴프리헨션은 파이썬에서 컴프리헨션을 중첩하여 사용하는 방법입니다. 중첩된 컴프리헨션은 다양한 데이터 구조를 생성하거나 조작할 수 있는 강력한 기능이지만, 가독성과 유지 보수 측면에서 주의해야 할 점이 있습니다.&lt;br&gt;
아래의 예시 코드를 통해 중첩된 컴프리헨션을 보여드리고, 단점에 대해 알려드리겠습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# 중첩된 컴프리헨션 예시&lt;/span&gt;
matrix &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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&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 number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&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 number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&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;
flattened_matrix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; matrix &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flattened_matrix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 중첩된 컴프리헨션에서의 단점&lt;/span&gt;
matrix &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 number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&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 number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&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 number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&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;
squared_matrix &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;num&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; num &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; row&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; row &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; matrix&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;squared_matrix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 예시 코드에서 첫 번째는 중첩된 컴프리헨션을 사용하여 2차원 리스트인 &lt;code class=&quot;language-text&quot;&gt;matrix&lt;/code&gt;를 1차원 리스트인 &lt;code class=&quot;language-text&quot;&gt;flattened_matrix&lt;/code&gt;로 만드는 예시입니다. 두 번째는 &lt;code class=&quot;language-text&quot;&gt;matrix&lt;/code&gt;의 각 요소들을 제곱하여 새로운 2차원 리스트인 &lt;code class=&quot;language-text&quot;&gt;squared_matrix&lt;/code&gt;를 생성하는 예시입니다.&lt;/p&gt;
&lt;p&gt;중첩된 컴프리헨션의 단점은 다음과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;가독성 저하&lt;/mark&gt;: 중첩된 컴프리헨션을 사용하면 코드가 복잡해지고 가독성이 저하될 수 있습니다. 특히, 여러 단계의 중첩된 컴프리헨션이 있을 경우 이해하기 어려워질 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;디버깅 어려움&lt;/mark&gt;: 중첩된 컴프리헨션에서 오류가 발생한 경우, 오류를 찾고 수정하기가 어려울 수 있습니다. 오류 발생 지점을 정확히 파악하기 어려우며, 오류가 발생한 중첩 구문을 해체하고 분리하는 작업이 번거로울 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;유지 보수의 어려움&lt;/mark&gt;: 중첩된 컴프리헨션에서 코드를 수정하거나 기능을 추가하려는 경우, 복잡한 구조로 인해 수정이 어려울 수 있습니다. 새로운 기능을 추가하기 위해 중첩된 컴프리헨션을 수정해야 하므로 코드의 일부를 재구성해야 할 수도 있습니다.&lt;/p&gt;
&lt;p&gt;따라서, 중첩된 컴프리헨션을 사용할 때는 코드의 가독성과 유지 보수 가능성을 고려해야 합니다. 너무 복잡한 구조의 중첩된 컴프리헨션은 가독성을 저하시킬 수 있으며, 필요한 경우에는 중첩된 컴프리헨션을 분리하여 가독성을 개선하는 것이 좋습니다.&lt;/p&gt;
&lt;h2 id=&quot;함수-마지막에는-return-문이-하나만-있어야-한다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%95%A8%EC%88%98-%EB%A7%88%EC%A7%80%EB%A7%89%EC%97%90%EB%8A%94-return-%EB%AC%B8%EC%9D%B4-%ED%95%98%EB%82%98%EB%A7%8C-%EC%9E%88%EC%96%B4%EC%95%BC-%ED%95%9C%EB%8B%A4&quot; aria-label=&quot;함수 마지막에는 return 문이 하나만 있어야 한다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;함수 마지막에는 return 문이 하나만 있어야 한다?&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;하나의 입구, 하나의 출구&lt;/code&gt; 아이디어는 어셈블리어와 포트란 언어로 프로그래밍하던 시절에 나온 조언을 잘못 해석한 데서 비롯된 것입니다.&lt;/p&gt;
&lt;p&gt;이러한 언어들은 서브루틴의 어떤 위치에도 진입이 가능하고, 서브루틴 내부에서 어떤 부분이 실행되었는지 디버깅을 하기 어렵게 되어 있습니다.&lt;/p&gt;
&lt;p&gt;하지만 파이썬에서나 현재의 프로그래밍 언어들은 함수나 메서드마다 return 문을 하나씩만 유지하려면, 여러 return 문을 유지하는 경우와 비교해 일련의 난해한 if-else 문이 필요하므로 훨씬 더 혼란스럽습니다.&lt;/p&gt;
&lt;p&gt;즉! 결론은 함수나 메서드에 return 문이 둘 이상 있어도 괜찮습니다.&lt;/p&gt;
&lt;h2 id=&quot;플래그-인수는-나쁘다&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%94%8C%EB%9E%98%EA%B7%B8-%EC%9D%B8%EC%88%98%EB%8A%94-%EB%82%98%EC%81%98%EB%8B%A4&quot; aria-label=&quot;플래그 인수는 나쁘다 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;플래그 인수는 나쁘다?&lt;/h2&gt;
&lt;p&gt;무조건적으로 나쁜 것은 아닙니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flagArgument&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; flagArgument&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# 특정 코드 실행&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&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;br&gt;
그러나 파이썬의 sorted() 함수는 하나의 정렬 함수에서 오름차순으로 정렬할지, 내림차순으로 정렬하지 결정할 수 있습니다!&lt;/p&gt;
&lt;p&gt;&lt;mark&gt; 바로 플래그 변수를 통해서죠! &lt;/mark&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Student&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; grade&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; age&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;grade &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; grade
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; age
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__repr__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&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 builtin&quot;&gt;repr&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;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;grade&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

student_objects &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    Student&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&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;
    Student&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&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;
    Student&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;dave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;student_objects&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;lambda&lt;/span&gt; student&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; student&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;age&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# sort by age&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 string&quot;&gt;&apos;dave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&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 string&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&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;위와 같은 예시 클래스가 주어졌다고 했을 때, 우리는 플래그 변수를 sorted()함수 전달해 오름차순으로 정렬할지, 내림차순으로 정렬할지 결정할 수 있습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;student_tuples&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;itemgetter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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; reverse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&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;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&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 string&quot;&gt;&apos;jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&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 string&quot;&gt;&apos;dave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;student_objects&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;itemgetter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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; reverse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&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;dave&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;jane&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;B&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&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 string&quot;&gt;&apos;john&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;A&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;15&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;reverse의 값을 False로 지정하지 않아도 기본값은 False입니다.&lt;/p&gt;
&lt;p&gt;그래서 결론은 &lt;code class=&quot;language-text&quot;&gt;플래그 변수가 무조건적으로 나쁜 것은 아니다&lt;/code&gt;입니다.&lt;/p&gt;
&lt;h2 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;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;마무리&lt;/h2&gt;
&lt;p&gt;이렇게 파이썬에 해당되는 코드 악취에 대해서와 오해에 대해서 정리해보았습니다.&lt;br&gt;
제 파이썬 코드 실력도 한 단계 향상됐으면 좋겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;참고하며-도움을-받은-글&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%ED%95%98%EB%A9%B0-%EB%8F%84%EC%9B%80%EC%9D%84-%EB%B0%9B%EC%9D%80-%EA%B8%80&quot; aria-label=&quot;참고하며 도움을 받은 글 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고하며 도움을 받은 글&lt;/h3&gt;
&lt;p&gt;책 - 클린 코드, 이제는 파이썬이다.&lt;br&gt;
&lt;a href=&quot;https://docs.python.org/ko/3/howto/sorting.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;파이썬 Document&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[스프링부트 kotest, mockk]]></title><description><![CDATA[스프링부트 테스트 정복해보자구]]></description><link>https://ambosing.github.io/spring/kotest/</link><guid isPermaLink="false">https://ambosing.github.io/spring/kotest/</guid><category><![CDATA[Spring]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Thu, 01 Jun 2023 15:00:00 GMT</pubDate><content:encoded>&lt;p&gt;저번에는 테스트를 하는 이유와 좋은 테스트를 하기 위한 조건, 맛보기로 JUnit을 알아보았는데요.&lt;br&gt;
그래도 역시 제가 생각하기엔 코틀린을 사용하시는 분들이라면 kotest를 사용할 것 같습니다.&lt;br&gt;
그래서 이번엔 kotest에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;tdd-bdd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tdd-bdd&quot; aria-label=&quot;tdd bdd permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TDD, BDD&lt;/h2&gt;
&lt;p&gt;kotest를 알아보기 앞서 TDD와 BDD의 차이를 알아보겠습니다.&lt;br&gt;
이 차이를 알아보는 것이 앞으로 테스트를 작성하는데 도움이 될 것이기 때문입니다!&lt;/p&gt;
&lt;p&gt;아래는 TDD와 BDD의 주요 차이를 마크다운 표로 정리한 것입니다 : )&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;TDD (Test-Driven Development)&lt;/th&gt;
&lt;th&gt;BDD (Behavior-Driven Development)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;목적&lt;/td&gt;
&lt;td&gt;코드 품질 향상&lt;/td&gt;
&lt;td&gt;소프트웨어 동작 및 행위 강조&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;중심&lt;/td&gt;
&lt;td&gt;개발자 중심&lt;/td&gt;
&lt;td&gt;동작 중심&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트&lt;/td&gt;
&lt;td&gt;단위 테스트&lt;/td&gt;
&lt;td&gt;기능/행위 테스트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트 작성 방식&lt;/td&gt;
&lt;td&gt;코드 기반&lt;/td&gt;
&lt;td&gt;자연어 스타일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트 프레임워크&lt;/td&gt;
&lt;td&gt;다양한 테스트 프레임워크 선택 가능&lt;/td&gt;
&lt;td&gt;다양한 BDD 프레임워크 선택 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트 구조화&lt;/td&gt;
&lt;td&gt;테스트 스위트, 테스트 그룹 등으로 구조화&lt;/td&gt;
&lt;td&gt;시나리오, 스토리 등으로 구조화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테스트 실행 시점&lt;/td&gt;
&lt;td&gt;개발 단계 초기에 작성 및 실행&lt;/td&gt;
&lt;td&gt;요구사항 및 동작 명세 이해 후 작성 및 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;대상&lt;/td&gt;
&lt;td&gt;코드의 동작 검증&lt;/td&gt;
&lt;td&gt;시스템의 행위 및 기능 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;TDD와 BDD는 접근 방식과 테스트 작성 방법 등에서 차이가 있지만, 상호 보완적인 요소도 많이 가지고 있습니다. 일부 개발자들은 TDD와 BDD를 함께 사용하여 개발하는 경우도 있습니다.&lt;/p&gt;
&lt;p&gt;TDD를 했을 때 장점도 분명하지만 아무래도 작성하기 힘들고, 귀찮다는 것이 현실입니다. 그래서 BDD를 사용하면 조금 더 쉽게 테스트를 작성할 수 있습니다.&lt;/p&gt;
&lt;p&gt;BDD로 테스트를 작성하는 것은 기획서를 읽어봤을 때 요구사항을 충족시키는 방향으로 작성하면 돼서 TDD보다 작성하기 수월합니다.&lt;/p&gt;
&lt;p&gt;그래서 실무에서는 이렇게 사용한다고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bb8f6a79079496234c9f88d25d30f20a/92c1e/2023-06-02-13-36-06.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.895833333333336%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRpAAAABXRUJQVlA4IIQAAACwAwCdASoUAAwAPtFWpUwoJKOiMAgBABoJaQAAXAekzVip9wkAAAD+9ZXDjq8AlasikVYOg/2NmpuxroPf6lqi23S+Ey4dhvqKIX58MnqsHIlDeMbtiw/SqdAQxXx4D7HZmrxrcaas4vJ6tbuNTG9U8r3Fcn6o2ZYbHPVzIARk/eJeAAA=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/bb8f6a79079496234c9f88d25d30f20a/a59e9/2023-06-02-13-36-06.webp 192w,
/static/bb8f6a79079496234c9f88d25d30f20a/0ca9f/2023-06-02-13-36-06.webp 384w,
/static/bb8f6a79079496234c9f88d25d30f20a/dc9b9/2023-06-02-13-36-06.webp 768w,
/static/bb8f6a79079496234c9f88d25d30f20a/e2c2f/2023-06-02-13-36-06.webp 1152w,
/static/bb8f6a79079496234c9f88d25d30f20a/92c1e/2023-06-02-13-36-06.webp 1222w&quot;
              sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/bb8f6a79079496234c9f88d25d30f20a/a59e9/2023-06-02-13-36-06.webp 192w,
/static/bb8f6a79079496234c9f88d25d30f20a/0ca9f/2023-06-02-13-36-06.webp 384w,
/static/bb8f6a79079496234c9f88d25d30f20a/dc9b9/2023-06-02-13-36-06.webp 768w,
/static/bb8f6a79079496234c9f88d25d30f20a/e2c2f/2023-06-02-13-36-06.webp 1152w,
/static/bb8f6a79079496234c9f88d25d30f20a/92c1e/2023-06-02-13-36-06.webp 1222w&quot;
            sizes=&quot;(max-width: 768px) 100vw, 768px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/bb8f6a79079496234c9f88d25d30f20a/dc9b9/2023-06-02-13-36-06.webp&quot;
            alt=&quot;BDD와 TDD의 경계&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;위의 그림과 같이 BDD와 TDD는 상호보완적으로 그려지는데요. 이는 BDD와 TDD를 함께 활용할 수 있음을 의미합니다.
&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 569px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7e71ce66ae10baa0dc97f0510f78f42c/fa7e8/2023-06-02-13-38-46.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRnAAAABXRUJQVlA4IGQAAAAQBACdASoUAA8APtFUo0uoJKMhsAgBABoJQBXDhCqfGP4v02HbVbQ9gAD+9gfWh8VHvGDuL2DBQ8DKw5TDTip9coDsSAzGcjT5aUS3Ut7DxZyOJw5uBDDG0BoEAKEZ9OlJUAAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/7e71ce66ae10baa0dc97f0510f78f42c/a59e9/2023-06-02-13-38-46.webp 192w,
/static/7e71ce66ae10baa0dc97f0510f78f42c/0ca9f/2023-06-02-13-38-46.webp 384w,
/static/7e71ce66ae10baa0dc97f0510f78f42c/fa7e8/2023-06-02-13-38-46.webp 569w&quot;
              sizes=&quot;(max-width: 569px) 100vw, 569px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/7e71ce66ae10baa0dc97f0510f78f42c/a59e9/2023-06-02-13-38-46.webp 192w,
/static/7e71ce66ae10baa0dc97f0510f78f42c/0ca9f/2023-06-02-13-38-46.webp 384w,
/static/7e71ce66ae10baa0dc97f0510f78f42c/fa7e8/2023-06-02-13-38-46.webp 569w&quot;
            sizes=&quot;(max-width: 569px) 100vw, 569px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/7e71ce66ae10baa0dc97f0510f78f42c/fa7e8/2023-06-02-13-38-46.webp&quot;
            alt=&quot;테스트 피라미드&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;보통은 Integration 테스트에는 BDD를 사용하게 되고 TDD는 유닛테스트에서 사용한다고 합니다.&lt;/p&gt;
&lt;h2 id=&quot;kotest&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#kotest&quot; aria-label=&quot;kotest permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Kotest&lt;/h2&gt;
&lt;p&gt;Kotest는 코틀린(Kotlin) 프로그래밍 언어로 작성된 테스트 프레임워크입니다. 테스트 프레임워크는 개발자가 소프트웨어의 품질을 검증하기 위해 작성하는 테스트 코드를 관리하고 실행하는 데 도움을 주는 도구입니다.&lt;/p&gt;
&lt;p&gt;Kotest는 코틀린의 강력한 기능을 활용하여 테스트 코드를 작성하고 실행하는 데 유연성과 간편함을 제공합니다. 다양한 기능을 제공하여 단위 테스트, 통합 테스트, 행위 주도 개발(Behavior-Driven Development, BDD) 스타일의 테스트 등을 지원합니다.&lt;/p&gt;
&lt;p&gt;Kotest는 다양한 확장 기능을 제공하여 테스트 환경을 커스터마이징하고 확장할 수 있습니다. 예를 들어, MockK를 사용하여 모의 객체(mock object)를 생성하고 테스트에 활용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;Kotest는 개발자 커뮤니티와 지속적으로 발전하고 있으며, 코틀린 생태계에서 인기 있는 테스트 프레임워크 중 하나입니다.&lt;/p&gt;
&lt;h3 id=&quot;간단한-tdd-예제-코드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EB%8B%A8%ED%95%9C-tdd-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;간단한 tdd 예제 코드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;간단한 TDD 예제 코드&lt;/h3&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;StringSpec
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shouldBe

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; CalculatorTest &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;StringSpec&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 string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;더하기 테스트&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; calculator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Calculator&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;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        result shouldBe &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;빼기 테스트&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; calculator &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Calculator&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;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subtract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        result shouldBe &lt;span class=&quot;token number&quot;&gt;2&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;class&lt;/span&gt; Calculator &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;subtract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드에서는 &lt;code class=&quot;language-text&quot;&gt;Calculator&lt;/code&gt; 클래스의 &lt;code class=&quot;language-text&quot;&gt;add&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;subtract&lt;/code&gt; 메서드를 테스트하는 예제입니다. &lt;code class=&quot;language-text&quot;&gt;StringSpec&lt;/code&gt;을 상속받은 테스트 스펙에서 테스트 케이스를 작성하고, &lt;code class=&quot;language-text&quot;&gt;shouldBe&lt;/code&gt; 함수를 사용하여 예상 결과와 실제 결과를 비교합니다.&lt;/p&gt;
&lt;h3 id=&quot;간단한-bdd-예제-코드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EB%8B%A8%ED%95%9C-bdd-%EC%98%88%EC%A0%9C-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;간단한 bdd 예제 코드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;간단한 BDD 예제 코드&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BehaviorSpec
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shouldBe

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; BankAccountTest &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BehaviorSpec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;잔고가 100인 계좌&quot;&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 keyword&quot;&gt;val&lt;/span&gt; bankAccount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BankAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;`when`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;100을 입금하면&quot;&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;
            bankAccount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;잔고는 200이어야 한다&quot;&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;
                bankAccount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;balance shouldBe &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token function&quot;&gt;`when`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;50을 출금하면&quot;&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;
            bankAccount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withdraw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;잔고는 50이어야 한다&quot;&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;
                bankAccount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;balance shouldBe &lt;span class=&quot;token number&quot;&gt;50&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;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BankAccount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;initialBalance&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&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;var&lt;/span&gt; balance&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; initialBalance

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deposit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        balance &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; amount
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;withdraw&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;amount&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        balance &lt;span class=&quot;token operator&quot;&gt;-=&lt;/span&gt; amount
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;위의 코드에서는 &lt;code class=&quot;language-text&quot;&gt;BankAccount&lt;/code&gt; 클래스를 BDD 스타일로 테스트하는 예제입니다. &lt;code class=&quot;language-text&quot;&gt;BehaviorSpec&lt;/code&gt;을 상속받은 테스트 스펙에서 &lt;code class=&quot;language-text&quot;&gt;given&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;when&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;then&lt;/code&gt;을 사용하여 테스트 시나리오를 구조화합니다. 각 시나리오에서 예상 결과와 실제 결과를 &lt;code class=&quot;language-text&quot;&gt;shouldBe&lt;/code&gt; 함수로 비교합니다.&lt;/p&gt;
&lt;p&gt;BDD는 Behavior Spec이나 Feature Spec으로 많이 작성합니다.&lt;/p&gt;
&lt;h3 id=&quot;간단한-spring-web-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EB%8B%A8%ED%95%9C-spring-web-test&quot; aria-label=&quot;간단한 spring web test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;간단한 Spring Web Test&lt;/h3&gt;
&lt;p&gt;Kotest와 Mockk를 사용하여 Controller, Service, 그리고 Repository 레이어의 테스트 코드를 작성하는 예제입니다. 프레임워크는 Spring Boot를 사용했습니다&lt;/p&gt;
&lt;p&gt;아래와 같이 &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;UserService&lt;/code&gt; 그리고 &lt;code class=&quot;language-text&quot;&gt;UserRepository&lt;/code&gt;의 간단한 코드가 있다고 가정하고 테스트 코드를 작성하겠습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; name&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; UserRepository &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&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 keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; userRepository&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepository&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;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; User&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 keyword&quot;&gt;return&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&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 annotation builtin&quot;&gt;@RestController&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; userService&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserService&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 annotation builtin&quot;&gt;@GetMapping&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/user/{id}&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@PathVariable&lt;/span&gt; id&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Int&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ResponseEntity&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;User&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ResponseEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;notFound&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 function&quot;&gt;build&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; ResponseEntity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이제 각 레이어에 대한 테스트 코드를 작성해 봅시다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UserControllerTest:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shouldBe
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mockk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;every
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mockk&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mockk
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HttpStatus
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ResponseEntity

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; UserControllerTest&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;StringSpec&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;val&lt;/span&gt; userService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mockk&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserService&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;val&lt;/span&gt; userController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userService&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;만약 유저가 존재한다면 getUser()메서드는 user객체를 반환합니다. &quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mockUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        every &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&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; returns mockUser

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statusCode shouldBe HttpStatus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OK
        response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;body shouldBe mockUser
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;만약 유저가 존재하지 않다면 getUser() 메서드는 404 에러 메시지를 전달합니다.&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        every &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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; returns &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;statusCode shouldBe HttpStatus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NOT_FOUND
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;UserServiceTest:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; UserServiceTest&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;StringSpec&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;val&lt;/span&gt; userRepository &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mockk&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;UserRepository&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;val&lt;/span&gt; userService &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserService&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;userRepository&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getUser() 메서드는 userId에 맞는 user를 반환해야 합니다.&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mockUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        every &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&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; returns mockUser

        userService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; shouldBe mockUser
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getUser() 메서드는 존재하지 않는 유저에 대해서 null을 반환합니다.&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        every &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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; returns &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;

        userService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; shouldBe &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;UserRepositoryTest:&lt;/strong&gt;
이것은 보통 데이터베이스와 연결되는 객체이므로, 해당 데이터베이스에서 제공하는 테스트 도구나 라이브러리를 사용하는 것이 일반적입니다. Mocking은 이 경우에는 적합하지 않을 수 있습니다.&lt;/p&gt;
&lt;p&gt;추가로, 레포지토리 테스트는 데이터베이스의 연결 상태, 쿼리의 정확성 등에 대한 테스트를 주로 담당하므로 mocking이 아닌 실제 데이터베이스 환경에서의 테스트가 필요할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;실제-db-연결하는-repository-test&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%8B%A4%EC%A0%9C-db-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-repository-test&quot; aria-label=&quot;실제 db 연결하는 repository test permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;실제 DB 연결하는 Repository Test&lt;/h3&gt;
&lt;p&gt;아래는 Spring Boot와 Kotest를 사용하여 &lt;code class=&quot;language-text&quot;&gt;UserRepository&lt;/code&gt;의 테스트를 작성하는 예시입니다!
이번에는 StringSpec이 아닌 FunSpec으로 작성해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FunSpec
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shouldBe
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;beans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;factory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Autowired
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;autoconfigure&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;orm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;jpa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataJpaTest
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SpringBootTest
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ContextConfiguration

&lt;span class=&quot;token annotation builtin&quot;&gt;@DataJpaTest&lt;/span&gt;
&lt;span class=&quot;token annotation builtin&quot;&gt;@ContextConfiguration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;UserRepository&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&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 function&quot;&gt;UserRepositoryTest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Autowired&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; userRepository&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; UserRepository&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;FunSpec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getUser() 메서드는 userId에 맞는 user를 반환해야 합니다.&quot;&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 keyword&quot;&gt;val&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 

        &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// DB에도 User(1, &quot;John Doe&quot;)객체가 있다고 가정합니다.&lt;/span&gt;
        result shouldBe user
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;getUser() 메서드는 존재하지 않는 유저에 대해서 null을 반환합니다.&quot;&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 keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userRepository&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        result shouldBe &lt;span class=&quot;token keyword&quot;&gt;null&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;이 예제에서는 Kotest의 &lt;code class=&quot;language-text&quot;&gt;FunSpec&lt;/code&gt;을 사용하여 테스트를 작성했습니다. &lt;code class=&quot;language-text&quot;&gt;FunSpec&lt;/code&gt;은 각 테스트를 &lt;code class=&quot;language-text&quot;&gt;test&lt;/code&gt; 함수 내부에 작성하며, 이는 각 테스트를 독립적으로 정의할 수 있게 해줍니다.&lt;/p&gt;
&lt;p&gt;또한, Kotest의 matchers 중 하나인 &lt;code class=&quot;language-text&quot;&gt;shouldBe&lt;/code&gt;를 사용하여 테스트 결과를 검증합니다. 이 matcher는 첫 번째 인자가 두 번째 인자와 같아야 함을 의미합니다.&lt;/p&gt;
&lt;p&gt;마지막으로, &lt;code class=&quot;language-text&quot;&gt;@DataJpaTest&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;@ContextConfiguration&lt;/code&gt; 애노테이션을 사용하여 JPA 관련 설정을 로드하고 &lt;code class=&quot;language-text&quot;&gt;UserRepository&lt;/code&gt; 인터페이스를 통해 데이터베이스와의 상호작용을 테스트합니다.&lt;/p&gt;
&lt;h3 id=&quot;간단한-통합-bdd-통합-테스트&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EA%B0%84%EB%8B%A8%ED%95%9C-%ED%86%B5%ED%95%A9-bdd-%ED%86%B5%ED%95%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8&quot; aria-label=&quot;간단한 통합 bdd 통합 테스트 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;간단한 통합 BDD 통합 테스트&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;core&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;style&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BehaviorSpec
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; io&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;matchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shouldBe
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;beans&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;factory&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;annotation&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Autowired
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;autoconfigure&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;orm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;jpa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;DataJpaTest
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;autoconfigure&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;web&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;AutoConfigureMockMvc
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SpringBootTest
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;http&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HttpStatus
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;web&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MockMvc
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;web&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MockMvcRequestBuilders&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;web&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;servlet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;MockMvcResultMatchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status

&lt;span class=&quot;token annotation builtin&quot;&gt;@SpringBootTest&lt;/span&gt;
&lt;span class=&quot;token annotation builtin&quot;&gt;@AutoConfigureMockMvc&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;UserControllerIntegrationTest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Autowired&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; mockMvc&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; MockMvc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BehaviorSpec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;Given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UserController&apos;s `/user/{id}` endpoint&quot;&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 function&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;유저가 존재할 때&quot;&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 keyword&quot;&gt;val&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// DB에 있다고 가정합니다!&lt;/span&gt;

            &lt;span class=&quot;token function&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UserId에 해당하는 유저를 반환합니다.&quot;&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 keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mockMvc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;perform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/user/1&quot;&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 function&quot;&gt;andExpect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&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;isOk&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;andReturn&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;val&lt;/span&gt; responseBody &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;contentAsString
                responseBody shouldBe &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{\&quot;id\&quot;:1,\&quot;name\&quot;:\&quot;John Doe\&quot;}&quot;&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 function&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;유저가 존재하지 않을때&quot;&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 function&quot;&gt;Then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;404 상태코드를 보냅니다.&quot;&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 keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mockMvc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;perform&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/user/2&quot;&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 function&quot;&gt;andExpect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;status&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;isNotFound&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;andReturn&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;

                result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status shouldBe HttpStatus&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;NOT_FOUND&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;value&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 예제에서는 Spring Boot의 &lt;code class=&quot;language-text&quot;&gt;MockMvc&lt;/code&gt;를 사용하여 HTTP 요청을 가상으로 수행하고 응답을 검증합니다. 이를 이용하여 &lt;code class=&quot;language-text&quot;&gt;UserController&lt;/code&gt;의 &lt;code class=&quot;language-text&quot;&gt;/user/{id}&lt;/code&gt; 엔드포인트에 GET 요청을 보내고, 사용자가 존재하는 경우와 존재하지 않는 경우에 대해 적절한 응답이 반환되는지 확인합니다.&lt;/p&gt;
&lt;p&gt;BDD 스타일의 테스트에서는 &lt;code class=&quot;language-text&quot;&gt;Given&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;When&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Then&lt;/code&gt;을 이용하여 테스트의 전제조건, 실행할 액션, 그리고 예상 결과를 명시하게 됩니다. 이는 테스트 코드를 읽는 사람이 테스트의 목적과 내용을 이해하는데 도움을 줍니다.&lt;/p&gt;
&lt;p&gt;마지막으로, 이 테스트는 실제 데이터베이스에 의존하며 서버를 실행하지 않고 MVC 레이어만을 테스트하기 때문에 통합 테스트에 가깝습니다. 통합 테스트에서는 개별적인 유닛 테스트보다는 더 넓은 범위의 코드를 테스트하게 됩니다.&lt;/p&gt;
&lt;h2 id=&quot;끝으로&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%81%9D%EC%9C%BC%EB%A1%9C&quot; aria-label=&quot;끝으로 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;끝으로&lt;/h2&gt;
&lt;p&gt;저의 글을 통해서 kotest에 대해서 조금이라도 알게되셨다면 좋겠습니다.&lt;br&gt;
아직은 미숙하지만 앞으로도 좋은 글을 통해서 찾아볼 수 있었으면 좋겠습니다!&lt;/p&gt;
&lt;h3 id=&quot;참고하며-도움을-받은-글&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B0%B8%EA%B3%A0%ED%95%98%EB%A9%B0-%EB%8F%84%EC%9B%80%EC%9D%84-%EB%B0%9B%EC%9D%80-%EA%B8%80&quot; aria-label=&quot;참고하며 도움을 받은 글 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고하며 도움을 받은 글&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://veluxer62.github.io/tutorials/getting-started-with-kotest/&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;남경호님의 kotest 글&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://kotest.io/docs/assertions/assertions.html&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;Kotest docs:Assertions&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://tv.kakao.com/channel/3693125/cliplink/414004682&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;ifkakao-2020: kotest가 있다면 TDD 묻고 BDD로 가!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;저도 공부하면서 적은것이라 행여나 잘못된 것이 있으면 알려주세요!&lt;br&gt;
잘못된 지식을 전파하고 싶지 않습니다!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[스프링부트 테스트 이론 & 맛보기 편]]></title><description><![CDATA[스프링부트 테스트 정복해보자구]]></description><link>https://ambosing.github.io/spring/test/</link><guid isPermaLink="false">https://ambosing.github.io/spring/test/</guid><category><![CDATA[Spring]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Thu, 01 Jun 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;테스트-코드의-필요성을-느꼈을-때&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1%EC%9D%84-%EB%8A%90%EA%BC%88%EC%9D%84-%EB%95%8C&quot; aria-label=&quot;테스트 코드의 필요성을 느꼈을 때 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테스트 코드의 필요성을 느꼈을 때&lt;/h2&gt;
&lt;p&gt;회사에서 개발을 하고 있다가 기존 기획과 달라지는 부분이 있어서 기능을 다시 새롭게 만들어야 하는 부분이 있었습니다. 이렇게 수정하면서 리팩토링도 같이 진행을 했었는데 변경된 수정 사항이 엣지 케이스에 동작을 하지 않고 오류가 발생하는 경우가 발생했습니다!&lt;br&gt;
앞으로는 이러한 일이 더 빈번하게 일어날텐데 어떻게 해야할까 고민하던 중에 예전에 리팩토링 책을 읽었을 때 리팩토링을 할 때는 언제나 테스트 코드가 존재해야한다고 들었던 것이 기억이 났습니다.&lt;/p&gt;
&lt;h2 id=&quot;우리는-왜-테스트-코드를-작성하는가&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9A%B0%EB%A6%AC%EB%8A%94-%EC%99%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%98%EB%8A%94%EA%B0%80&quot; aria-label=&quot;우리는 왜 테스트 코드를 작성하는가 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;우리는 왜 테스트 코드를 작성하는가?&lt;/h2&gt;
&lt;p&gt;바로 이러한 장점들이 있기 때문!!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;품질 확인&lt;/strong&gt;: 테스트 코드는 소프트웨어의 기능이 예상대로 작동하는지 확인하게 해줍니다. 이를 통해 개발자는 버그나 예상치 못한 동작을 빠르게 발견하고 수정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;회귀 테스트&lt;/strong&gt;: 테스트 코드는 새로운 기능을 추가하거나 기존 코드를 변경했을 때 이전에 작동하던 기능이 여전히 잘 작동하는지 확인하는 데 도움이 됩니다. 이를 회귀 테스트라고 하며, 테스트 코드가 없다면 이러한 테스트를 수동으로 수행해야 할 수도 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;리팩토링&lt;/strong&gt;: 코드베이스를 정리하거나 개선하는 작업을 리팩토링이라고 합니다. 테스트 코드는 개발자가 리팩토링하는 동안 기능이 여전히 올바르게 작동하는지 확인하는 데 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;문서화&lt;/strong&gt;: 테스트 코드는 종종 코드의 사용법을 설명하는 데 사용됩니다. 개발자가 어떻게 API를 사용해야 하는지 또는 특정 기능이 어떻게 동작하는지 이해하려면 테스트 코드를 읽을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;신뢰성&lt;/strong&gt;: 테스트 코드는 사용자와 다른 개발자에게 소프트웨어의 신뢰성을 보여주는 좋은 방법입니다. 테스트 커버리지가 높을수록 코드의 신뢰성이 높다고 간주되며, 이는 개발자와 사용자 모두에게 중요한 특성입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개발 속도 증가&lt;/strong&gt;: 처음에는 테스트 코드를 작성하는 데 시간이 들 수 있지만, 장기적으로 보면 개발 과정을 가속화할 수 있습니다. 테스트 코드를 통해 빠르게 버그를 발견하고 수정할 수 있으며, 코드 변경의 영향을 쉽게 이해할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이러한 이유들로 인해 많은 개발자와 조직들이 테스트 코드 작성을 중요하게 여기며, 테스트 주도 개발(TDD)과 같은 방법론을 따르기도 합니다.&lt;/p&gt;
&lt;h2 id=&quot;테스트를-작성할-때-꼭-tdd는-해야할까&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%95%A0-%EB%95%8C-%EA%BC%AD-tdd%EB%8A%94-%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C&quot; aria-label=&quot;테스트를 작성할 때 꼭 tdd는 해야할까 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;테스트를 작성할 때 꼭 TDD는 해야할까?&lt;/h2&gt;
&lt;p&gt;언제나 테스트 코드를 작성할 때면 테스트 주도 개발(TDD:Test Driven Development)가 따라오고는 합니다..! 과연 TDD는 꼭 해야하는 걸까요?&lt;/p&gt;
&lt;p&gt;테스트 주도 개발(TDD)는 소프트웨어 개발의 하나로, 테스트를 먼저 작성하고 그 테스트를 통과하는 코드를 작성하는 방법을 가르킵니다. 이는 테스트의 중요성을 강조하며, 테스트가 요구 사항의 정의와 동시에 품질을 보장하는 역할을 수행한다는 것을 나타냅니다.&lt;/p&gt;
&lt;p&gt;그러나 &lt;mark&gt;TDD가 항상 적절한 것은 아닙니다. TDD의 적용 여부는 여러 요인에 따라 달라집니다!&lt;/mark&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;프로젝트의 복잡성&lt;/strong&gt;: 복잡한 프로젝트에서는 TDD가 매우 유용할 수 있습니다. 테스트를 먼저 작성함으로써 요구 사항을 명확히 이해하고, 코드의 구조와 설계를 개선하며, 향후 버그를 줄일 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트의 수명&lt;/strong&gt;: 장기 프로젝트에서는 TDD가 유용합니다. 코드 변경에 따른 회귀 테스트를 자동화하고, 리팩토링을 용이하게 하며, 코드베이스의 유지 보수를 돕습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;팀의 경험&lt;/strong&gt;: TDD는 적절히 수행하려면 경험이 필요합니다. 팀원들이 TDD에 익숙하지 않다면, 이를 배우고 적용하는데 시간이 필요하며 이로 인해 초기 개발 속도가 느려질 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프로토타입 개발&lt;/strong&gt;: 빠르게 프로토타입을 만들어야 하는 경우에는 TDD가 항상 가장 좋은 방법이 아닐 수 있습니다. 이러한 경우에는 프로토타입이 만족스러운 결과를 보일 때까지 빠르게 반복하는 것이 중요하며, 이후에 안정된 버전을 개발하는 동안 TDD를 적용할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이처럼 TDD는 유용한 도구이지만, 항상 적용해야 하는 것은 아닙니다. 프로젝트의 특성과 요구 사항, 팀의 경험 등을 고려하여 TDD가 적절한지를 판단해야 합니다.&lt;/p&gt;
&lt;h2 id=&quot;코틀린-스프링부트-라이브러리&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC&quot; aria-label=&quot;코틀린 스프링부트 라이브러리 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;코틀린 스프링부트 라이브러리&lt;/h2&gt;
&lt;p&gt;스프링 부트에서 Kotlin을 사용하여 테스트를 작성할 때 주로 사용하는 테스트 라이브러리는 &lt;strong&gt;JUnit&lt;/strong&gt;, &lt;strong&gt;Mockito&lt;/strong&gt;, 그리고 &lt;strong&gt;Spring Boot Test&lt;/strong&gt;입니다. 이 라이브러리들을 사용하면 단위 테스트, 통합 테스트, 그리고 애플리케이션의 전체 라이프사이클을 테스트 할 수 있습니다.&lt;br&gt;
먼저 JUnit부터 간단히 알아봅시다!&lt;/p&gt;
&lt;h3 id=&quot;junit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#junit&quot; aria-label=&quot;junit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;JUnit&lt;/h3&gt;
&lt;p&gt;Java 진영의 대표적인 Test Framework&lt;br&gt;
단위 테스트(Unit Test)를 위한 도구를 제공합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;단위 테스트란?
&lt;ul&gt;
&lt;li&gt;코드의 특정 모듈이 의도된대로 동작하는지 테스트하는 절차를 의미합니다.&lt;/li&gt;
&lt;li&gt;모든 함수와 메소드에 대한 각각의 테스트 케이스를 작성하는 것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;어노테이션을 기반으로 테스트를 지원합니다.&lt;br&gt;
단정문(Assert)으로 테스트 케이스의 기대값에 대해 수행 결과를 확인할 수 있습니다.&lt;br&gt;
JUnit5는 Spring Boot 2.2버전부터 사용합니다.&lt;br&gt;
JUnit5는 Jupiter, Platform, Vintage 모듈로 구성됩니다.&lt;/p&gt;
&lt;h4 id=&quot;junit-lifecycle-annotation&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#junit-lifecycle-annotation&quot; aria-label=&quot;junit lifecycle annotation permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;JUnit LifeCycle Annotation&lt;/h4&gt;
&lt;p&gt;JUnit5는 아래와 같은 테스트 라이프 사이클을 가지고 있습니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;@Test&lt;/td&gt;
&lt;td&gt;테스트용 메소드를 표현하는 어노테이션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@BeforeEach&lt;/td&gt;
&lt;td&gt;각 테스트 메소드가 시작되기 전에 실행되어야 하는 메소드를 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@AfterEach&lt;/td&gt;
&lt;td&gt;각 테스트 메소드가 시작된 후 실행되어야 하는 메소드를 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@BeforeAll&lt;/td&gt;
&lt;td&gt;테스트 시작 전에 실행되어야 하는 메소드를 표현 (static 처리 필요)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@AfterAll&lt;/td&gt;
&lt;td&gt;테스트 종료 후에 실행되어야 하는 메소드를 표현 (static 처리 필요)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;예시-코드&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%98%88%EC%8B%9C-%EC%BD%94%EB%93%9C&quot; aria-label=&quot;예시 코드 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;예시 코드&lt;/h4&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; com&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;example&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Test

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;junit&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;jupiter&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;api&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;springframework&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;boot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;test&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SpringBootTest

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; TestLifeCycle &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token annotation builtin&quot;&gt;@BeforeEach&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;beforeEach&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## beforeEach 호출&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;println&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 annotation builtin&quot;&gt;@AfterEach&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;afterEach&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## afterEach 호출&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;println&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 annotation builtin&quot;&gt;@Test&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test1&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## test1 시작&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;println&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 annotation builtin&quot;&gt;@Test&lt;/span&gt;
	&lt;span class=&quot;token annotation builtin&quot;&gt;@DisplayName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Test 2&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test2&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## test2 시작&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;println&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 annotation builtin&quot;&gt;@Test&lt;/span&gt;
	&lt;span class=&quot;token annotation builtin&quot;&gt;@Disabled&lt;/span&gt;
	 &lt;span class=&quot;token comment&quot;&gt;// Disabled Annotation : 테스트를 실행하지 않게 설정하는 어노테이션&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test3&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## test3 시작&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;println&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;companion&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token annotation builtin&quot;&gt;@BeforeAll&lt;/span&gt;
		&lt;span class=&quot;token annotation builtin&quot;&gt;@JvmStatic&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 코틀린에서 BeforeAll을 사용하려면 이 어노테이션을!&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;beforeAll&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## BeforeAll호출 &quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;println&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 annotation builtin&quot;&gt;@AfterAll&lt;/span&gt;
		&lt;span class=&quot;token annotation builtin&quot;&gt;@JvmStatic&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;afterAll&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 function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;## afterAll 호출&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;출력-결과&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%B6%9C%EB%A0%A5-%EA%B2%B0%EA%B3%BC&quot; aria-label=&quot;출력 결과 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;출력 결과&lt;/h4&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;## BeforeAll호출 &lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## beforeEach 호출&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## test1 시작&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## afterEach 호출&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## beforeEach 호출&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## test2 시작&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## afterEach 호출&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;## afterAll 호출&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 499px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/43f71ca1d3ddcd36e91640f39583d6d5/aa66f/2023-06-02-13-06-47.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 49.479166666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRkQAAABXRUJQVlA4IDgAAABQAwCdASoUAAoAPtFUo0uoJKMhsAgBABoJZwAAW+o9WUExAAD+4vwds6PpEjNRVlHBkxnCknQAAA==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/43f71ca1d3ddcd36e91640f39583d6d5/a59e9/2023-06-02-13-06-47.webp 192w,
/static/43f71ca1d3ddcd36e91640f39583d6d5/0ca9f/2023-06-02-13-06-47.webp 384w,
/static/43f71ca1d3ddcd36e91640f39583d6d5/aa66f/2023-06-02-13-06-47.webp 499w&quot;
              sizes=&quot;(max-width: 499px) 100vw, 499px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/43f71ca1d3ddcd36e91640f39583d6d5/a59e9/2023-06-02-13-06-47.webp 192w,
/static/43f71ca1d3ddcd36e91640f39583d6d5/0ca9f/2023-06-02-13-06-47.webp 384w,
/static/43f71ca1d3ddcd36e91640f39583d6d5/aa66f/2023-06-02-13-06-47.webp 499w&quot;
            sizes=&quot;(max-width: 499px) 100vw, 499px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/43f71ca1d3ddcd36e91640f39583d6d5/aa66f/2023-06-02-13-06-47.webp&quot;
            alt=&quot;테스트 실행 결과&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
테스트 3는 Disable Annotation 때문에 실행이 되지 않았습니다!&lt;/p&gt;
&lt;h2 id=&quot;좋은-테스트를-위한-이론&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A2%8B%EC%9D%80-%ED%85%8C%EC%8A%A4%ED%8A%B8%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9D%B4%EB%A1%A0&quot; aria-label=&quot;좋은 테스트를 위한 이론 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;좋은 테스트를 위한 이론!&lt;/h2&gt;
&lt;p&gt;본격적으로 테스트를 하기 전에 우리는 먼저 알아야되는 것들이 있습니다.&lt;br&gt;
예를들어, BDD라던가 FIRST라던가.. 말이죠!&lt;br&gt;
이를 먼저 이해하는 것이 좋은 테스트를 작성할 때 도움이 될 겁니다!&lt;/p&gt;
&lt;h3 id=&quot;bddbehavior-driven-development-행위주도개발&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bddbehavior-driven-development-%ED%96%89%EC%9C%84%EC%A3%BC%EB%8F%84%EA%B0%9C%EB%B0%9C&quot; aria-label=&quot;bddbehavior driven development 행위주도개발 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;BDD(Behavior Driven Development, 행위주도개발)&lt;/h3&gt;
&lt;p&gt;BDD란 행위 주도 개발입니다!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BDD는 TDD를 근간으로 파생된 개발 방법입니다.&lt;/li&gt;
&lt;li&gt;TDD에서 한발 더 나아가 테스트 케이스 자체가 요구사항이 되도록 하는 개발 방법입니다.&lt;/li&gt;
&lt;li&gt;개발자, 테스터 및 비즈니스 이해 관계자 간의 의사 소통을 강화하고, 기능의 동작과 예상 결과를 예측 가능하게 만듭니다.&lt;/li&gt;
&lt;li&gt;테스트 주도 개발(Test-Driven Development, TDD) 및 도메인 주도 설계(Domain-Driven Design, DDD)과 같은 다른 개발 방법론과도 잘 조합될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;bdd-패턴-및-요소&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bdd-%ED%8C%A8%ED%84%B4-%EB%B0%8F-%EC%9A%94%EC%86%8C&quot; aria-label=&quot;bdd 패턴 및 요소 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;BDD 패턴 및 요소&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;스토리 (Story): BDD에서는 비즈니스 요구사항을 “스토리”로 표현합니다. 이는 사용자의 관점에서 소프트웨어 기능에 대한 설명이며, 주어진 상황에서 어떤 행동이 기대되는지를 나타냅니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;시나리오 (Scenario): 각 스토리에는 하나 이상의 시나리오가 포함됩니다. 시나리오는 특정한 상황에서 소프트웨어의 기능과 행위에 대한 구체적인 예시를 제시합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Given-When-Then 구조: BDD에서 시나리오는 “Given-When-Then” 구조로 작성됩니다. 이 구조는 다음과 같이 세 가지 부분으로 나뉩니다&lt;br&gt;
Given: 테스트 환경의 초기 상태를 설정합니다.&lt;br&gt;
When: 사용자의 특정한 행동이 발생했을 때를 정의합니다.&lt;br&gt;
Then: 예상되는 결과를 기술합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;kotlin&quot;&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token annotation builtin&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;`BDD behavior driven development`&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;// given&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;calculatorService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10.0&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 function&quot;&gt;willReturn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// when&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; calculatorService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;20.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// then&lt;/span&gt;
    Assert&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;30.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; CoreMatchers&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;`is`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&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;h3 id=&quot;first&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#first&quot; aria-label=&quot;first permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;FIRST&lt;/h3&gt;
&lt;p&gt;FIRST는 소프트웨어 테스트를 효과적으로 설계하고 구성하기 위한 가이드라인을 제공하는 약어입니다. FIRST는 “Fast, Independent, Repeatable, Self-validating, Timely”의 첫 글자로 구성됩니다. 각각의 원칙은 다음과 같은 의미를 가지고 있습니다..!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;mark&gt;Fast (빠르게)&lt;/mark&gt;: 테스트는 빠르게 실행되어야 합니다. 테스트가 느리게 실행되면 개발자들이 테스트를 자주 실행하지 않을 수 있으며, 이는 버그를 빠르게 식별하고 수정하기 어렵게 만들 수 있습니다. 빠른 테스트는 빠른 피드백과 빠른 개발을 가능하게 합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Independent (독립적으로)&lt;/mark&gt;: 각 테스트는 다른 테스트와 독립적으로 실행되어야 합니다. 한 테스트가 다른 테스트에 의존하면 테스트 간에 상호작용이 생기고, 테스트를 이해하고 유지 관리하기가 어려워집니다. 독립적인 테스트는 테스트의 신뢰성을 높이고, 수정 및 재구성이 용이하게 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Repeatable (반복 가능하게)&lt;/mark&gt;: 테스트는 어떤 환경에서도 반복 가능해야 합니다. 테스트가 실행될 때마다 동일한 결과가 나와야 하며, 외부 요소에 의해 영향을 받지 않아야 합니다. 반복 가능한 테스트는 버그를 신속하게 재현하고, 테스트 환경을 변경할 때도 안정적으로 동작합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Self-validating (자체 검증 가능하게)&lt;/mark&gt;: 테스트는 자동으로 판단 가능해야 합니다. 테스트가 수동으로 실행되거나 개발자의 주관에 의존하는 것은 신뢰성과 일관성을 저하시킬 수 있습니다. 자체 검증 가능한 테스트는 예상된 결과를 자동으로 확인하고 판단합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Timely (적시에)&lt;/mark&gt;: 테스트는 적시에 작성되어야 합니다. 테스트는 개발 과정의 초기부터 작성되어야 하며, 개발과 함께 진행되어야 합니다. 테스트를 미루면 버그를 발견하고 수정하는 데 더 많은 비용과 시간이 소요될 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;FIRST 원칙을 따르는 테스트는 신뢰성이 높고 유지 보수가 쉬우며, 효과적인 소프트웨어 개발을 지원합니다. 이러한 원칙을 따르면 테스트의 품질과 가치를 높일 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;right-bicep&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#right-bicep&quot; aria-label=&quot;right bicep permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Right-BICEP&lt;/h3&gt;
&lt;p&gt;“RIGHT-BICEP”는 소프트웨어 테스트를 설계하는 데 사용되는 기법 중 하나입니다. 이 기법은 테스트 케이스를 작성하고 실행할 때 고려해야 할 다양한 요소를 나타내는 약어입니다. 각 알파벳은 다음과 같은 의미를 가지고 있습니다!!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Right: 올바른 결과를 얻는지 확인합니다. 이는 소프트웨어가 예상대로 동작하고 정확한 출력을 생성하는지 확인하는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;BICEP:
&lt;ul&gt;
&lt;li&gt;&lt;mark&gt;Boundary conditions (경계 조건)&lt;/mark&gt;: 입력 데이터의 경계 값을 테스트하여 소프트웨어가 경계 조건에서 올바르게 작동하는지 확인합니다. 이는 최소값, 최대값, 경계값 등과 같이 입력 범위의 경계에 해당하는 값을 테스트하는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Incorrect values (잘못된 값)&lt;/mark&gt;: 잘못된 또는 부적절한 값으로 소프트웨어를 테스트하여 예외 상황이나 오류 처리 기능을 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Inverse relationships (역 관계)&lt;/mark&gt;: 입력 값 사이의 역 관계를 테스트하여 소프트웨어가 정확한 상호 작용을 수행하는지 확인합니다. 예를 들어, A와 B라는 입력 값이 서로 역 관계에 있을 때, A를 변경하면 B에도 적절한 변화가 있는지 테스트합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Cross-check results (결과 교차 확인)&lt;/mark&gt;: 소프트웨어의 다른 부분 또는 동일한 기능의 대안 구현을 사용하여 결과를 교차 확인합니다. 이를 통해 독립적인 구현 간의 결과 일치성을 검증할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Performance characteristics (성능 특성)&lt;/mark&gt;: 소프트웨어의 성능 요구사항에 맞게 테스트를 수행하여 응답 시간, 처리량, 자원 사용 등과 같은 성능 특성을 확인합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;RIGHT-BICEP 기법을 사용하면 다양한 시나리오와 테스트 케이스를 고려하여 소프트웨어를 더 철저하게 테스트할 수 있습니다. 이를 통해 소프트웨어의 정확성, 예외 처리, 상호 작용, 일관성, 성능 등을 평가하고 개선할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;correct&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#correct&quot; aria-label=&quot;correct permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;CORRECT&lt;/h3&gt;
&lt;p&gt;테스트 이론 중 “CORRECT”는 소프트웨어 테스트를 계획하고 수행하는 데 도움이 되는 가이드라인을 제공하는 메모 기법입니다. 이 기법은 테스트 케이스를 작성하고 검증할 때 고려해야 할 다양한 요소를 나타냅니다. “CORRECT”는 다음과 같은 의미를 가지는 약어입니다&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;mark&gt;Conformance (일치)&lt;/mark&gt;: 소프트웨어가 요구사항과 규격에 따라 정확하게 동작하는지 확인합니다. 이는 소프트웨어가 정확한 입력에 대해 올바른 결과를 생성하는지를 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Ordering (순서)&lt;/mark&gt;: 소프트웨어의 동작이 올바른 순서로 이루어지는지 확인합니다. 이는 시간, 우선순위, 종속성 등과 같은 다양한 상황에서 소프트웨어가 예상된 순서로 동작하는지를 테스트합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Range (범위)&lt;/mark&gt;: 소프트웨어가 허용된 범위 내에서 정확한 결과를 생성하는지 확인합니다. 이는 입력값의 범위, 데이터 타입의 제약 등과 같은 다양한 조건에서 소프트웨어가 올바른 동작을 수행하는지를 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Reference (참조)&lt;/mark&gt;: 소프트웨어의 동작이 외부 참조나 연관된 구성 요소와 일치하는지 확인합니다. 이는 외부 라이브러리, API, 데이터베이스 등과 같은 참조 요소와의 상호작용을 테스트하여 예상된 동작을 수행하는지를 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Errors (오류)&lt;/mark&gt;: 소프트웨어의 오류 처리 기능을 평가합니다. 이는 잘못된 입력, 예외 상황, 예측할 수 없는 상황 등에 대한 소프트웨어의 오류 처리 능력을 확인하는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Combinations (조합)&lt;/mark&gt;: 다양한 입력 값의 조합에 대해 소프트웨어가 예상된 동작을 수행하는지 확인합니다. 이는 입력값의 조합이 다양한 경우에 대한 테스트를 수행하여 소프트웨어의 동작을 검증하는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;mark&gt;Tests (테스트)&lt;/mark&gt;: 모든 테스트 케이스가 적절하게 작성되어 소프트웨어를 충분히 커버하는지 확인합니다. 이는 테스트 커버리지를 확인하고 빠뜨린 테스트 케이스가 없는지를 평가합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;CORRECT 기법은 테스트의 완전성과 정확성을 높이기 위해 다양한 측면을 고려하여 테스트를 계획하고 수행하는 데 도움을 줍니다. 이를 통해 소프트웨어의 신뢰성과 품질을 향상시킬 수 있습니다.&lt;/p&gt;
&lt;p&gt;저도 공부하면서 적은것이라 행여나 잘못된 것이 있으면 알려주세요! 잘못된 지식을 전파하고 싶지 않습니다!&lt;/p&gt;
&lt;p&gt;kotest에 대해서 조금 더 알고 싶다면
&lt;a href=&quot;https://ambosing.github.io/spring/kotest&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;초코볼의 kotest&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Python 정규표현식 정복하기!]]></title><description><![CDATA[정규표현식에 대해 알아보자]]></description><link>https://ambosing.github.io/others/regex/</link><guid isPermaLink="false">https://ambosing.github.io/others/regex/</guid><category><![CDATA[Others]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Tue, 09 May 2023 15:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;왜-정규표현식을-알아야-하나&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%99%9C-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%84-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%98%EB%82%98&quot; aria-label=&quot;왜 정규표현식을 알아야 하나 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;왜 정규표현식을 알아야 하나!?&lt;/h2&gt;
&lt;p&gt;정규표현식은 문자열을 가공할 때 많이 사용됩니다.&lt;br&gt;
정규표현식을 모르고 사용했을 때 문자열을 파싱하는게 매우 어려웠습니다..&lt;br&gt;
그러므로 모르고 고생하지 말고 이번에 제대로 정복해봅시다!&lt;/p&gt;
&lt;h2 id=&quot;정규표현식&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D&quot; aria-label=&quot;정규표현식 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규표현식&lt;/h2&gt;
&lt;h3 id=&quot;정규표현식이란&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%B4%EB%9E%80&quot; aria-label=&quot;정규표현식이란 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규표현식이란?&lt;/h3&gt;
&lt;p&gt;정규표현식(Regular Expression)은 문자열 패턴을 검색하거나 변경하기 위한 문자열 표현 방법입니다. 문자열 패턴은 일련의 문자열과 특수 문자(메타 문자)로 정의됩니다. 이러한 패턴은 문자열에서 일치하는 문자열 또는 패턴을 찾거나 변경하는 데 사용됩니다.&lt;/p&gt;
&lt;h4 id=&quot;-정규표현식의-장점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%98-%EC%9E%A5%EC%A0%90&quot; aria-label=&quot; 정규표현식의 장점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🟢 정규표현식의 장점&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;유연성&lt;/strong&gt;: 정규표현식은 다양한 문자열 패턴을 정의할 수 있으므로, 문자열을 검색하거나 변경할 때 매우 유연합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;표현력&lt;/strong&gt;: 정규표현식은 간결하고 강력합니다. 간단한 패턴에서부터 복잡한 패턴까지 표현할 수 있으며, 이를 통해 효과적인 문자열 처리를 가능하게 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;효율성&lt;/strong&gt;: 정규표현식은 문자열 처리를 위해 최적화되어 있으므로, 매우 빠르게 문자열을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;다양한 언어에서 지원&lt;/strong&gt;: 대부분의 프로그래밍 언어와 Unix/Linux 명령어에서 정규표현식을 지원하므로, 다양한 환경에서 사용할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;-정규표현식의-단점&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%98-%EB%8B%A8%EC%A0%90&quot; aria-label=&quot; 정규표현식의 단점 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;🔴 정규표현식의 단점&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;학습 곡선&lt;/strong&gt;: 정규표현식은 처음에는 이해하기 어려울 수 있습니다. 복잡한 패턴을 작성하려면 일정한 수준의 학습이 필요합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;가독성&lt;/strong&gt;: 매우 복잡한 정규표현식은 이해하기 어려울 수 있습니다. 따라서 코드를 작성할 때 가독성이 저하될 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;불안정성&lt;/strong&gt;: 매우 복잡한 정규표현식은 정규표현식 엔진에서 불안정성을 유발할 수 있습니다. 이는 처리 속도가 느리거나, 충돌이 발생할 수 있음을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;적용 범위&lt;/strong&gt;: 정규표현식은 특정한 패턴을 찾는 데 효과적이지만, 모든 문제에 적용할 수 있는 것은 아닙니다. 때로는 다른 방법이 더 효과적일 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;정규표현식을-쓸-때-유용한-곳&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D%EC%9D%84-%EC%93%B8-%EB%95%8C-%EC%9C%A0%EC%9A%A9%ED%95%9C-%EA%B3%B3&quot; aria-label=&quot;정규표현식을 쓸 때 유용한 곳 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규표현식을 쓸 때 유용한 곳&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;문자열 검색&lt;/strong&gt;: 특정한 문자열을 찾는데 매우 유용합니다. 예를 들어, 이메일 주소, 전화번호, URL 등의 패턴을 검색할 때 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;문자열 대체&lt;/strong&gt;: 문자열에서 특정한 문자열을 다른 문자열로 대체할 때 유용합니다. 예를 들어, 특정한 단어나 문장을 다른 단어나 문장으로 대체할 때 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;입력 유효성 검사&lt;/strong&gt;: 입력값이 특정한 규칙을 만족하는지 검사할 때 사용됩니다. 예를 들어, 이메일 주소나 비밀번호 등의 입력값이 유효한지 검사할 때 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로그 분석&lt;/strong&gt;: 로그 파일에서 특정한 패턴을 검색하거나, 원하는 정보를 추출할 때 사용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;데이터 추출&lt;/strong&gt;: 문자열에서 특정한 데이터를 추출할 때 매우 유용합니다. 예를 들어, HTML 태그에서 특정한 데이터를 추출하는데 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;파일 이름 필터링&lt;/strong&gt;: 특정한 파일 이름 패턴을 필터링할 때 사용됩니다. 예를 들어, 특정한 확장자를 가진 파일이나 특정한 파일 이름 패턴을 가진 파일을 찾을 때 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;자주-쓰이는-정규표현식-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%9E%90%EC%A3%BC-%EC%93%B0%EC%9D%B4%EB%8A%94-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;자주 쓰이는 정규표현식 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;자주 쓰이는 정규표현식 패턴&lt;/h2&gt;
&lt;p&gt;먼저 자주쓰이는 패턴을 학습하고 그 패턴이 어떻게 구성되어 있는지 보겠습니다.&lt;br&gt;
정규표현식 기호 모음은 아래에 서술했으니 아래로 가시면 확인하실 수 있습니다!&lt;/p&gt;
&lt;h3 id=&quot;-전화번호-정규표현식-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot; 전화번호 정규표현식 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;📞 전화번호 정규표현식 패턴&lt;/h3&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

&lt;span class=&quot;token comment&quot;&gt;# 한국 휴대폰 전화번호 정규표현식 패턴&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

&lt;span class=&quot;token comment&quot;&gt;# 한국 휴대폰 전화번호 정규표현식 패턴&lt;/span&gt;
pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;010[-]?(\d{3,4})[-]?(\d{4})&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# 텍스트에서 한국 휴대폰 전화번호 찾기&lt;/span&gt;
text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;안녕하세요! 저의 전화번호는 010-1234-5678입니다.&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;찾은 전화번호:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&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;# 찾은 전화번호: 010-1234-5678&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;전화번호를 찾지 못했습니다.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 코드는 대시(-)나 공백 문자를 구분자로 사용한 경우도 포함한 휴대폰 전화번호를 찾을 수 있습니다. 텍스트에서 찾은 전화번호를 출력하거나 다른 작업을 수행할 수 있습니다.&lt;/p&gt;
&lt;p&gt;이걸 이제 하나씩 뜯어보겠습니다!물론이죠. 정규표현식은 복잡해 보일 수 있지만, 각 부분을 따로 살펴보면 이해하기 쉽습니다. 아래에서 해당 정규표현식 패턴을 하나씩 설명하겠습니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;010[-]?(\d{3,4})[-]?(\d{4})&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt;: Python에서 정규표현식 앞에 &lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt; 문자를 붙이는 것은 이 문자열이 raw string임을 나타냅니다. 이것은 문자열 내에서 역슬래시&lt;code class=&quot;language-text&quot;&gt;\&lt;/code&gt;가 이스케이프 문자로 해석되지 않게 하기 위함입니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;&apos;010&lt;/code&gt;: 문자열이 ‘010’으로 시작해야 함을 나타냅니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&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;code class=&quot;language-text&quot;&gt;?&lt;/code&gt;는 바로 앞의 문자나 그룹이 0번 또는 1번 나타남을 의미합니다. 즉, 이 표현식은 대시 &lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt;가 없거나 한 번만 나타날 수 있음을 나타냅니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;(\d{3,4})&lt;/code&gt;: &lt;code class=&quot;language-text&quot;&gt;\d&lt;/code&gt;는 숫자를 의미하고, &lt;code class=&quot;language-text&quot;&gt;{3,4}&lt;/code&gt;는 앞의 문자가 3번 또는 4번 반복될 수 있음을 의미합니다. 따라서 이 부분은 3자리 또는 4자리 숫자를 의미합니다. 괄호 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;는 이 부분을 그룹으로 만들어서, 나중에 이 부분을 따로 참조할 수 있게 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&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;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;(\d{4})&lt;/code&gt;: 이 부분은 4자리 숫자를 의미합니다. 마찬가지로 괄호 &lt;code class=&quot;language-text&quot;&gt;()&lt;/code&gt;는 이 부분을 그룹으로 만들어서, 나중에 이 부분을 따로 참조할 수 있게 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;따라서 이 정규표현식은 ‘010’으로 시작하고, 그 다음에는 대시 &lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt;가 없거나 있을 수 있고, 그 다음에는 3자리 또는 4자리 숫자가 있으며, 다시 대시 &lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt;가 없거나 있을 수 있고, 마지막으로 4자리 숫자가 있는 문자열을 찾습니다.&lt;/p&gt;
&lt;h3 id=&quot;-이메일-정규표현식-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot; 이메일 정규표현식 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;✉ 이메일 정규표현식 패턴&lt;/h3&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

email_pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;r&apos;^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$&apos;&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;is_valid_email&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;email_pattern&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; email&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 boolean&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&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 boolean&quot;&gt;False&lt;/span&gt;


&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; is_valid_email&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;example@example.com&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Valid email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# Valid email&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Invalid email&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이메일 주소의 정규표현식 패턴을 하나씩 설명해보겠습니다.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;email_pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;r&apos;^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\.[a-zA-Z]{2,})?$&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;^&lt;/code&gt;: 문자열의 시작&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;[a-zA-Z0-9._%+-]+&lt;/code&gt;: 1글자 이상의 영문 대소문자, 숫자, 밑줄(_), 마침표(.), 퍼센트(%), 더하기(+), 하이픈(-)으로 이루어진 문자열&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;@&lt;/code&gt;: @ 기호&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;[a-zA-Z0-9.-]+&lt;/code&gt;: 1글자 이상의 영문 대소문자, 숫자, 마침표(.), 하이픈(-)으로 이루어진 문자열&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;\.&lt;/code&gt;: 마침표(.) 문자&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;[a-zA-Z]{2,}&lt;/code&gt;: 2글자 이상의 영문 대소문자로 이루어진 문자열 (TLD)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;(?:\.[a-zA-Z]{2,})?&lt;/code&gt;: &lt;code class=&quot;language-text&quot;&gt;[a-zA-Z]{2,}&lt;/code&gt; 패턴을 또 반복하는데, &lt;code class=&quot;language-text&quot;&gt;?&lt;/code&gt;는 0회 또는 1회 반복을 의미합니다. 이를 통해 도메인 이름이 &lt;code class=&quot;language-text&quot;&gt;co.kr&lt;/code&gt;과 같은 형태일 경우도 매칭할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt;: 문자열의 끝&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 패턴을 사용하여 검증하려는 이메일 주소가 정규표현식 패턴과 일치하는지 검사할 때는 re 모듈의 search()나 match() 메서드 등을 사용할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;수식-분리하기&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%88%98%EC%8B%9D-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0&quot; aria-label=&quot;수식 분리하기 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;수식 분리하기&lt;/h3&gt;
&lt;p&gt;이번에는 제가 코딩테스트 문제를 풀다가 마주했던 문제에 대해서 잠시 설명하겠습니다.&lt;br&gt;
수식이 &lt;code class=&quot;language-text&quot;&gt;100-200*300-500+20&lt;/code&gt;으로 주어졌을 때 &lt;code class=&quot;language-text&quot;&gt;[&apos;100&apos;, &apos;-&apos;, &apos;200&apos;, &apos;*&apos;, &apos;300&apos;, &apos;-&apos;, &apos;500&apos;, &apos;+&apos;, &apos;20&apos;]&lt;/code&gt;으로 분리하는 과정이 필요했습니다.&lt;br&gt;
이 때도 정규표현식을 생각하지 못해서 상당히 어렵게 구현했습니다.&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

expression &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;100-200*300-500+20&apos;&lt;/span&gt;

tokens &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;split&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;r&apos;(\D)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; expression&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tokens&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# [&apos;100&apos;, &apos;-&apos;, &apos;200&apos;, &apos;*&apos;, &apos;300&apos;, &apos;-&apos;, &apos;500&apos;, &apos;+&apos;, &apos;20&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;정규표현식에서 괄호는 그룹을 나타내는 역할을 합니다. 따라서 괄호로 괄호로 둘러싼 부분은 하나의 그룹으로 처리되며, &lt;code class=&quot;language-text&quot;&gt;split()&lt;/code&gt; 메소드는 그룹을 포함한 구분자를 기준으로 문자열을 분리합니다.&lt;/li&gt;
&lt;li&gt;위 코드에서는 &lt;code class=&quot;language-text&quot;&gt;\D&lt;/code&gt;를 그룹으로 둘러싸서 하나의 그룹으로 처리하였습니다. 따라서 숫자와 숫자가 아닌 문자가 번갈아가면서 그룹을 처리되게 하며, &lt;code class=&quot;language-text&quot;&gt;split()&lt;/code&gt; 메소드는 이를 구분자로 문자열을 분리합니다.&lt;/li&gt;
&lt;li&gt;결과적으로 리스트의 요소는 숫자와 숫자가 아닌 문자가 번갈아가면서 저장됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/67257&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;위의 코딩테스트 문제&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;파이썬-정규표현식-re-모듈&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-re-%EB%AA%A8%EB%93%88&quot; aria-label=&quot;파이썬 정규표현식 re 모듈 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;파이썬 정규표현식 re 모듈&lt;/h2&gt;
&lt;p&gt;Python에서 정규표현식을 사용하기 위해서는 re 모듈을 import하여 사용합니다. 이 모듈에서 제공하는 메서드들과 각 메서드의 예시를 함께 정리해보겠습니다.&lt;/p&gt;
&lt;h3 id=&quot;문자열의-시작부분부터-패턴이-매치되는지-확인하는-함수rematch&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%98-%EC%8B%9C%EC%9E%91%EB%B6%80%EB%B6%84%EB%B6%80%ED%84%B0-%ED%8C%A8%ED%84%B4%EC%9D%B4-%EB%A7%A4%EC%B9%98%EB%90%98%EB%8A%94%EC%A7%80-%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94-%ED%95%A8%EC%88%98rematch&quot; aria-label=&quot;문자열의 시작부분부터 패턴이 매치되는지 확인하는 함수rematch permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문자열의 시작부분부터 패턴이 매치되는지 확인하는 함수(re.match)&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;re.match(pattern, string)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdef&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(0, 3), match=&apos;abc&apos;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdefabc&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(0, 3), match=&apos;abc&apos;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdefabcabc&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(0, 3), match=&apos;abc&apos;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ababcdef&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 comment&quot;&gt;# None&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이 함수는 매치되면 match 객체를 반환하고, 그렇지 않으면 None을 반환합니다.&lt;/p&gt;
&lt;h3 id=&quot;문자열-전체에서-패턴이-매치되는-부분을-찾는-함수research&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%A0%84%EC%B2%B4%EC%97%90%EC%84%9C-%ED%8C%A8%ED%84%B4%EC%9D%B4-%EB%A7%A4%EC%B9%98%EB%90%98%EB%8A%94-%EB%B6%80%EB%B6%84%EC%9D%84-%EC%B0%BE%EB%8A%94-%ED%95%A8%EC%88%98research&quot; aria-label=&quot;문자열 전체에서 패턴이 매치되는 부분을 찾는 함수research permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문자열 전체에서 패턴이 매치되는 부분을 찾는 함수(re.search)&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;re.search(pattern, string)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdef&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(0, 3), match=&apos;abc&apos;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdefabc&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(0, 3), match=&apos;abc&apos;&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ababcdefabc&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 comment&quot;&gt;# &amp;lt;re.Match object; span=(2, 5), match=&apos;abc&apos;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;처음으로 매치되는 부분의 match 객체를 반환합니다. 매치되는 부분이 없으면 None을 반환합니다.&lt;/p&gt;
&lt;h3 id=&quot;문자열-전체에서-패턴에-매치되는-모든-부분을-찾아-리스트로-반환하는-함수refindall&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%A0%84%EC%B2%B4%EC%97%90%EC%84%9C-%ED%8C%A8%ED%84%B4%EC%97%90-%EB%A7%A4%EC%B9%98%EB%90%98%EB%8A%94-%EB%AA%A8%EB%93%A0-%EB%B6%80%EB%B6%84%EC%9D%84-%EC%B0%BE%EC%95%84-%EB%A6%AC%EC%8A%A4%ED%8A%B8%EB%A1%9C-%EB%B0%98%ED%99%98%ED%95%98%EB%8A%94-%ED%95%A8%EC%88%98refindall&quot; aria-label=&quot;문자열 전체에서 패턴에 매치되는 모든 부분을 찾아 리스트로 반환하는 함수refindall permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문자열 전체에서 패턴에 매치되는 모든 부분을 찾아 리스트로 반환하는 함수(re.findall)&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;re.findall(pattern, string)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdefabcabc&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 comment&quot;&gt;# [&apos;abc&apos;, &apos;abc&apos;, &apos;abc&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;문자열-내에서-패턴에-매치되는-부분을-다른-문자열로-교체하는-함수resub&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4%EC%97%90%EC%84%9C-%ED%8C%A8%ED%84%B4%EC%97%90-%EB%A7%A4%EC%B9%98%EB%90%98%EB%8A%94-%EB%B6%80%EB%B6%84%EC%9D%84-%EB%8B%A4%EB%A5%B8-%EB%AC%B8%EC%9E%90%EC%97%B4%EB%A1%9C-%EA%B5%90%EC%B2%B4%ED%95%98%EB%8A%94-%ED%95%A8%EC%88%98resub&quot; aria-label=&quot;문자열 내에서 패턴에 매치되는 부분을 다른 문자열로 교체하는 함수resub permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;문자열 내에서 패턴에 매치되는 부분을 다른 문자열로 교체하는 함수(re.sub)&lt;/h3&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;re.sub(pattern, repl, string)&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;code-header&quot;&gt;
	&lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
	&lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sub&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;123&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcdefabcabc&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 comment&quot;&gt;# &apos;123def123123&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;p&gt;이 외에도 다른 함수들이 많지만 나머지는 &lt;a href=&quot;https://docs.python.org/3/library/re.html?highlight=re#module-re&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;python Document&lt;/a&gt;를 보시면 될 것 같습니다.&lt;/p&gt;
&lt;h2 id=&quot;정규식-플래그&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%EC%8B%9D-%ED%94%8C%EB%9E%98%EA%B7%B8&quot; aria-label=&quot;정규식 플래그 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규식 플래그&lt;/h2&gt;
&lt;p&gt;파이썬 &lt;code class=&quot;language-text&quot;&gt;re&lt;/code&gt; 모듈에서 사용되는 주요 정규식 플래그는 다음과 같습니다&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;플래그&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;re.IGNORECASE&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;re.I&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;대소문자를 구분하지 않습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;re.MULTILINE&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;re.M&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;^&lt;/code&gt;와 &lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt; 메타문자를 각각 문자열의 시작과 끝, 그리고 개행문자로 구분된 각 줄의 시작과 끝으로 인식합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;re.DOTALL&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;re.S&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; 메타문자가 개행문자를 포함한 모든 문자와 매치되도록 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;re.VERBOSE&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;re.X&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;정규표현식을 더 읽기 쉽게 만들 수 있도록 해주며, 라인을 분리하고 주석을 추가하는 것이 가능합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;re.ASCII&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;re.A&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\b&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\B&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\d&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\D&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\s&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\S&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\w&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;\W&lt;/code&gt; 등과 같은 특수 문자 시퀀스가 ASCII 문자에 대해서만 작동하도록 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;각 플래그는 &lt;code class=&quot;language-text&quot;&gt;re.compile(pattern, flags)&lt;/code&gt; 형식의 선택적 &lt;code class=&quot;language-text&quot;&gt;flags&lt;/code&gt; 매개변수로 전달할 수 있으며, &lt;code class=&quot;language-text&quot;&gt;re.match()&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;re.search()&lt;/code&gt; 등의 메소드에서도 사용될 수 있습니다. 또한 플래그를 &lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt; 연산자를 사용하여 결합할 수 있습니다. 예를 들어, 대소문자를 구분하지 않으며 여러 줄의 텍스트를 처리하려면 다음과 같이 사용할 수 있습니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;I &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;M&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
matches &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ABC\nabc\nAbC&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;matches&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# [&apos;ABC&apos;, &apos;abc&apos;, &apos;AbC&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;정규식-특정-문자-숫자-매칭-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%EC%8B%9D-%ED%8A%B9%EC%A0%95-%EB%AC%B8%EC%9E%90-%EC%88%AB%EC%9E%90-%EB%A7%A4%EC%B9%AD-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;정규식 특정 문자 숫자 매칭 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규식 특정 문자 숫자 매칭 패턴&lt;/h2&gt;
&lt;p&gt;정규식에서 특정 문자나 숫자를 매치하는 데 사용되는 주요 패턴들은 다음과 같습니다&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;패턴&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;모든 숫자와 일치합니다. &lt;code class=&quot;language-text&quot;&gt;[0-9]&lt;/code&gt;와 동일합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\D&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;숫자를 제외한 모든 문자와 일치합니다. &lt;code class=&quot;language-text&quot;&gt;[^0-9]&lt;/code&gt;와 동일합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;공백 문자(스페이스, 탭, 줄바꿈 등)와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\S&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;공백 문자를 제외한 모든 문자와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\w&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;모든 알파벳 문자, 숫자, 밑줄과 일치합니다. &lt;code class=&quot;language-text&quot;&gt;[a-zA-Z0-9_]&lt;/code&gt;와 동일합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\W&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\w&lt;/code&gt;에 해당하는 문자를 제외한 모든 문자와 일치합니다. &lt;code class=&quot;language-text&quot;&gt;[^a-zA-Z0-9_]&lt;/code&gt;와 동일합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;문자열이나 행의 시작 부분과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;문자열이나 행의 끝 부분과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;[abc]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;괄호 안의 문자 중 하나와 일치합니다. &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt; 중 어느 하나와 일치하는 패턴을 의미합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;[^abc]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;괄호 안의 문자들을 제외한 모든 문자와 일치합니다. &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;c&lt;/code&gt;를 제외한 모든 문자와 일치하는 패턴을 의미합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;[a-z]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;지정된 범위 내의 문자 중 하나와 일치합니다. 이 경우 소문자 &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;z&lt;/code&gt;까지 모든 문자와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;[A-Z]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;지정된 범위 내의 문자 중 하나와 일치합니다. 이 경우 대문자 &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;Z&lt;/code&gt;까지 모든 문자와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;[0-9]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;지정된 범위 내의 문자 중 하나와 일치합니다. 이 경우 숫자 &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;에서 &lt;code class=&quot;language-text&quot;&gt;9&lt;/code&gt;까지 모든 숫자와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이러한 패턴들을 조합하여 복잡한 문자열 검색 및 처리 작업을 수행할 수 있습니다. 예를 들어, 이메일 주소나 전화번호와 같은 특정 패턴을 가진 문자열을 찾거나, 텍스트에서 특정 형태의 정보를 추출하는 데 이러한 패턴들이 사용됩니다.&lt;/p&gt;
&lt;h2 id=&quot;정규식-갯수-반복-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%EC%8B%9D-%EA%B0%AF%EC%88%98-%EB%B0%98%EB%B3%B5-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;정규식 갯수 반복 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규식 갯수 반복 패턴&lt;/h2&gt;
&lt;p&gt;정규식에서 검색 기준을 설정하는데 사용되는 주요 패턴들은 다음과 같습니다&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;패턴&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 0번 이상 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 1번 이상 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 0번 또는 1번 등장하는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;{n}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 정확히 &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;번 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;{n,}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;번 이상 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;{,n}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;번 이하 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;{n,m}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;앞선 문자나 그룹이 최소 &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;번 이상, 최대 &lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;번 이하 반복되는 것과 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;a|b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; 또는 &lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt;와 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이러한 패턴들은 텍스트에서 특정 패턴을 가진 문자열을 찾거나 텍스트를 분석하는 데 사용됩니다. 예를 들어, 이메일 주소의 형식이나 전화번호와 같은 특정 패턴을 찾을 때 사용할 수 있습니다. 또한 텍스트에서 특정 형식의 데이터를 추출하는 데도 사용됩니다.&lt;/p&gt;
&lt;p&gt;아래는 이 패턴들을 사용한 예제입니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

&lt;span class=&quot;token comment&quot;&gt;# &apos;+&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a+&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;aaaaaa&apos;, &apos;a&apos;, &apos;aaa&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;*&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a*&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;aaaaaa&apos;, &apos;&apos;, &apos;&apos;, &apos;&apos;, &apos;&apos;, &apos;a&apos;, &apos;aaa&apos;, &apos;&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;?&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;a&apos;, &apos;a&apos;, &apos;a&apos;, &apos;a&apos;, &apos;a&apos;, &apos;a&apos;, &apos;&apos;, &apos;a&apos;, &apos;a&apos;, &apos;a&apos;, &apos;&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;{n}&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a{2}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;aa&apos;, &apos;aa&apos;, &apos;aa&apos;, &apos;aa&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;{n,}&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a{2,}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;aaaaaa&apos;, &apos;aaa&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;{,n}&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a{,2}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;&apos;, &apos;aa&apos;, &apos;aa&apos;, &apos;aa&apos;, &apos;&apos;, &apos;&apos;, &apos;aa&apos;, &apos;a&apos;, &apos;&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;{n,m}&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a{2,4}&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;aaaaaabcaaa&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 comment&quot;&gt;# [&apos;aaaa&apos;, &apos;aaa&apos;]&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;|&apos;를 사용한 예제&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;findall&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;a|b&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;abcd&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 comment&quot;&gt;# [&apos;a&apos;, &apos;b&apos;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;정규식-그룹화-패턴&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#%EC%A0%95%EA%B7%9C%EC%8B%9D-%EA%B7%B8%EB%A3%B9%ED%99%94-%ED%8C%A8%ED%84%B4&quot; aria-label=&quot;정규식 그룹화 패턴 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;정규식 그룹화 패턴&lt;/h2&gt;
&lt;p&gt;정규식에서 그룹을 생성하고 참조하는 데 사용되는 주요 패턴들은 다음과 같습니다&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;패턴&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;( )&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;괄호 안의 패턴을 그룹으로 만들어줍니다. 이를 통해 패턴의 일부분을 하나의 단위로 취급할 수 있게 해줍니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;\n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;번째 그룹에 해당하는 부분과 동일한 문자열에 일치합니다. &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;은 1부터 시작하는 그룹의 인덱스입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(?P&amp;lt;name&gt; )&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;이름이 &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;인 그룹을 생성합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;(?P=name)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;이름이 &lt;code class=&quot;language-text&quot;&gt;name&lt;/code&gt;인 그룹에 해당하는 부분과 동일한 문자열에 일치합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;아래는 이 패턴들을 사용한 예제입니다:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; re

&lt;span class=&quot;token comment&quot;&gt;# &apos;( )&apos;를 사용한 예제&lt;/span&gt;
pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;(a)(b)(c)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;abc&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&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;# &apos;abc&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&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;# &apos;a&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&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;# &apos;b&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&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;# &apos;c&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;\n&apos;를 사용한 예제&lt;/span&gt;
pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;(a)\\1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;aa&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&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;# &apos;aa&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&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;# &apos;a&apos;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# &apos;(?P&amp;lt;name&gt; )&apos;와 &apos;(?P=name)&apos;을 사용한 예제&lt;/span&gt;
pattern &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;(?P&amp;lt;first&gt;a)(?P=first)&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;aa&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&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;# &apos;aa&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;group&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;first&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 comment&quot;&gt;# &apos;a&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;이러한 패턴들은 텍스트에서 특정 패턴을 가진 문자열을 찾거나 텍스트를 분석하는 데 사용됩니다. 예를 들어, 이메일 주소의 형식이나 전화번호와 같은 특정 패턴을 찾을 때 사용할 수 있습니다. 또한 텍스트에서 특정 형식의 데이터를 추출하는 데도 사용됩니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;끝으로 마지막 정규표현식을 연습할 수 있는 간단한 문제와 문제집을 남겨놓고 가겠습니다.&lt;br&gt;
&lt;a href=&quot;https://www.acmicpc.net/problem/1264&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;백준 모음의 개수&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.acmicpc.net/problem/14405&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;백준 피카츄&lt;/a&gt;&lt;br&gt;
&lt;a href=&quot;https://www.acmicpc.net/workbook/view/6082&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;정규표현식 문제집&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;참고 게시글: &lt;a href=&quot;https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%A0%95%EA%B7%9C%EC%8B%9D-RegExp-%EB%88%84%EA%B5%AC%EB%82%98-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;인파님 블로그&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[마크다운 문법 모음집]]></title><description><![CDATA[블로그 디자인하려고 올린 게시글]]></description><link>https://ambosing.github.io/others/markdown/</link><guid isPermaLink="false">https://ambosing.github.io/others/markdown/</guid><category><![CDATA[Others]]></category><dc:creator><![CDATA[Ambosing]]></dc:creator><pubDate>Mon, 27 Mar 2023 15:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;small&gt;개인적으로 마크다운 문법 정리 및 블로그 디자인을 하기 위해 올린 게시글입니다.&lt;/small&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h1 id=&quot;this-is-a-h1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#this-is-a-h1&quot; aria-label=&quot;this is a h1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;del&gt;This is a H1&lt;/del&gt;&lt;/h1&gt;
&lt;p&gt;&lt;small&gt;게시글 제목이 h1이니까 내용 안에서 소제목 작성할땐 h2부터 사용할 것&lt;/small&gt;&lt;/p&gt;
&lt;h2 id=&quot;this-is-a-h2&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#this-is-a-h2&quot; aria-label=&quot;this is a h2 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;This is a H2&lt;/h2&gt;
&lt;h3 id=&quot;this-is-a-h3&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#this-is-a-h3&quot; aria-label=&quot;this is a h3 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;This is a H3&lt;/h3&gt;
&lt;h4 id=&quot;this-is-a-h4&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#this-is-a-h4&quot; aria-label=&quot;this is a h4 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;This is a H4&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;첫번째&lt;/li&gt;
&lt;li&gt;두번째
&lt;ol&gt;
&lt;li&gt;두번째 안의 첫번째&lt;/li&gt;
&lt;li&gt;두번째 안의 두번째
&lt;ol&gt;
&lt;li&gt;두번째 안의 두번째 안의 첫번째&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;세번째&lt;/li&gt;
&lt;li&gt;네번째&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;빨강&lt;/li&gt;
&lt;li&gt;분홍&lt;/li&gt;
&lt;li&gt;보라
&lt;ul&gt;
&lt;li&gt;녹색
&lt;ul&gt;
&lt;li&gt;파랑&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검정&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;1단계
&lt;ul&gt;
&lt;li&gt;2단계
&lt;ul&gt;
&lt;li&gt;3단계
&lt;ul&gt;
&lt;li&gt;4단계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a first blockquote.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a second blockquote.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a third blockquote.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;이것은 인용구입니다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;첫번째 각주&lt;sup id=&quot;fnref-1&quot;&gt;&lt;a href=&quot;#fn-1&quot; class=&quot;footnote-ref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;
두번째 각주&lt;sup id=&quot;fnref-2&quot;&gt;&lt;a href=&quot;#fn-2&quot; class=&quot;footnote-ref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;각주는 어디에 작성하든 페이지 맨 밑에 표시됨, 가로선도 알아서 들어감&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ol이랑 ul 섞어 쓰려면 들여쓰기 두번씩 해야됨&lt;/li&gt;
&lt;li&gt;순서있는 항목
&lt;ul&gt;
&lt;li&gt;그 안에 순서 없는 항목1
&lt;ul&gt;
&lt;li&gt;그 안에 또 순서 없는 항목&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;순서 없는 항목2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;순서 있는 항목2
&lt;ol&gt;
&lt;li&gt;그 안에 순서 있는 항목1
&lt;ol&gt;
&lt;li&gt;그 안에 또 순서 있는 항목&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;그 안에 순서 있는 항목2&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;한줄 &lt;code class=&quot;language-text&quot;&gt;this is code&lt;/code&gt; 코드&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; is code block&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;code-header&quot;&gt;
   &lt;span class=&quot;red btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;yellow btn&quot;&gt;&lt;/span&gt;
   &lt;span class=&quot;green btn&quot;&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; is code block too&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;기울임꼴&lt;/em&gt;
&lt;em&gt;기울임꼴&lt;/em&gt;
&lt;strong&gt;강조하기&lt;/strong&gt;
&lt;strong&gt;강조하기&lt;/strong&gt;
&lt;del&gt;취소선&lt;/del&gt;
&lt;em&gt;&lt;strong&gt;기울이면서 강조하기&lt;/strong&gt;&lt;/em&gt;
&lt;em&gt;&lt;strong&gt;기울이면서 강조하기&lt;/strong&gt;&lt;/em&gt;
&lt;mark&gt;형광펜 배경&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;&lt;sub&gt;아래첨자&lt;/sub&gt;텍스트
&lt;sup&gt;위첨자&lt;/sup&gt;텍스트&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;테이블1&lt;/th&gt;
&lt;th&gt;테이블2&lt;/th&gt;
&lt;th&gt;테이블3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;내용1&lt;/td&gt;
&lt;td&gt;내용2&lt;/td&gt;
&lt;td&gt;내용3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내용1&lt;/td&gt;
&lt;td&gt;내용2&lt;/td&gt;
&lt;td&gt;내용3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;내용1&lt;/td&gt;
&lt;td&gt;내용2&lt;/td&gt;
&lt;td&gt;내용3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;이건 줄바꿈 안한 문장&lt;/p&gt;
&lt;p&gt;줄 바꿈을 하기 위해서는 앞줄 마지막에서 &lt;strong&gt;2칸이상&lt;/strong&gt;을 띄어쓰기해야 한다.&lt;br&gt;
이렇게&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;리스트에서 줄바꿈 하려면 앞줄 마지막을 2칸 이상 띄우고,&lt;br&gt;
다음 줄도 2칸 이상 들여쓰기 해야함&lt;br&gt;
이렇게!&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- 표시되지 않을 주석 --&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d9c170bc6185d663e6c13f49d45919e8/0c8fb/2023-03-29-14-49-13.webp&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 66.66666666666666%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/webp;base64,UklGRl4AAABXRUJQVlA4IFIAAABQAwCdASoUAA0APtFUo0uoJKMhsAgBABoJZwDDNCHhVhc3HAD+8dMKnsLDvXnbxvt8GHD9EDGaWOgl0iNmEq00rW4nrTnL9M69Xv3xu/cSccAA&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;picture&gt;
          &lt;source
              srcset=&quot;/static/d9c170bc6185d663e6c13f49d45919e8/a59e9/2023-03-29-14-49-13.webp 192w,
/static/d9c170bc6185d663e6c13f49d45919e8/0ca9f/2023-03-29-14-49-13.webp 384w,
/static/d9c170bc6185d663e6c13f49d45919e8/0c8fb/2023-03-29-14-49-13.webp 640w&quot;
              sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
              type=&quot;image/webp&quot;
            /&gt;
          &lt;source
            srcset=&quot;/static/d9c170bc6185d663e6c13f49d45919e8/a59e9/2023-03-29-14-49-13.webp 192w,
/static/d9c170bc6185d663e6c13f49d45919e8/0ca9f/2023-03-29-14-49-13.webp 384w,
/static/d9c170bc6185d663e6c13f49d45919e8/0c8fb/2023-03-29-14-49-13.webp 640w&quot;
            sizes=&quot;(max-width: 640px) 100vw, 640px&quot;
            type=&quot;image/webp&quot;
          /&gt;
          &lt;img
            class=&quot;gatsby-resp-image-image&quot;
            src=&quot;/static/d9c170bc6185d663e6c13f49d45919e8/0c8fb/2023-03-29-14-49-13.webp&quot;
            alt=&quot;2023 03 29 14 49 13&quot;
            title=&quot;&quot;
            loading=&quot;lazy&quot;
            decoding=&quot;async&quot;
            style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
          /&gt;
        &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;source&quot;&gt;이미지랑 이미지 캡션넣기&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;링크 걸기
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/ihoneymon/652be052a0727ad59601&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;마크다운 문법 참고 사이트1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;마크다운 문법 참고 사이트2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;첫번째 각주&lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn-2&quot;&gt;두번째 각주 - 각주를 여러줄로 넣고 싶으면,&lt;br&gt;
앞줄 끝에는 2칸, 뒷줄 앞에는 4칸의&lt;br&gt;
공백을 넣을것!&lt;a href=&quot;#fnref-2&quot; class=&quot;footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item></channel></rss>