<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://paca94.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://paca94.github.io/" rel="alternate" type="text/html" /><updated>2026-04-01T15:07:59+00:00</updated><id>https://paca94.github.io/feed.xml</id><title type="html">paca94 Develop Blog</title><subtitle>기본을 중요시하는 백엔드 개발자</subtitle><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><entry><title type="html">결제와 주문은 다르다 - 팀원에게 설명했던 이야기</title><link href="https://paca94.github.io/thinking/%EA%B2%B0%EC%A0%9C%EC%99%80-%EC%A3%BC%EB%AC%B8%EC%9D%80-%EB%8B%A4%EB%A5%B4%EB%8B%A4/" rel="alternate" type="text/html" title="결제와 주문은 다르다 - 팀원에게 설명했던 이야기" /><published>2026-04-01T00:00:00+00:00</published><updated>2026-03-31T15:00:00+00:00</updated><id>https://paca94.github.io/thinking/%EA%B2%B0%EC%A0%9C%EC%99%80-%EC%A3%BC%EB%AC%B8%EC%9D%80-%EB%8B%A4%EB%A5%B4%EB%8B%A4</id><content type="html" xml:base="https://paca94.github.io/thinking/%EA%B2%B0%EC%A0%9C%EC%99%80-%EC%A3%BC%EB%AC%B8%EC%9D%80-%EB%8B%A4%EB%A5%B4%EB%8B%A4/"><![CDATA[<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>결제 == 주문? 외주사 코드를 인수하며 마주친 설계 문제와 팀 전체에 설명한 과정
</code></pre></div></div>

<h3 id="배경">배경</h3>

<p>2025년 5월쯤, 현 직장에서 외주사가 개발한 서버를 인수받게 됐다.
서비스는 C2C 거래 마켓으로, 사용자가 직접 상품을 올리고 구매하는 플랫폼이다.</p>

<p>코드를 파악하기 시작하면서 바로 눈에 띄는 문제가 있었고, 곧바로 팀 전체에 설명했다.</p>

<hr />

<h3 id="문제-결제--주문">문제: 결제 == 주문</h3>

<p>외주사 코드에서 <strong>결제와 주문이 하나의 개념</strong>으로 묶여 있었다.
두 개가 별개의 테이블로 존재하긴 했지만, 주문이 결제 ID를 직접 들고 있는 구조였다.
서로 강하게 의존하고 있어서, 사실상 하나나 마찬가지였다.</p>

<p>언뜻 보면 “어차피 결제하면 주문 아닌가?” 싶을 수 있다.
팀원도 처음엔 그렇게 생각했다.</p>

<hr />

<h3 id="왜-분리해야-하는가">왜 분리해야 하는가</h3>

<p><strong>주문(Order)</strong> 은 구매를 <strong>확정하는 행위</strong>다.
무엇을, 얼마에, 누구에게 살지를 확정하는 것이다.</p>

<p><strong>결제(Payment)</strong> 는 그 확정에 대한 <strong>대가를 지불하는 행위</strong>다.
어떤 수단으로, 얼마를, 언제 냈는지를 담는다.</p>

<p>둘은 일어나는 시점도 다르고, 담고 있는 정보도 다르다.</p>

<p>설령 비즈니스 규칙상 항상 1:1로 처리된다 하더라도, <strong>개념 자체가 다르기 때문에</strong> 가급적 분리해야 한다고 생각한다.
주문이 취소되는 이유와 결제가 취소되는 이유는 다르다. 묶어놓으면 필요 이상으로 복잡해진다고 생각한다.</p>

<hr />

<h3 id="팀-전체가-알아야-한다고-생각한-이유">팀 전체가 알아야 한다고 생각한 이유</h3>

<p>설명한 이유는 단순했다.
주문과 결제의 개념이 명확하게 잡혀 있지 않으면, 이후 디자인 작업에서 그 부분이 섞여 혼선이 생길 거라고 생각했다.
개발 단에서만 분리해놓고 다른 직군이 모르고 있으면, 결국 화면 흐름이나 용어가 뒤엉킨 채로 일이 진행된다.</p>

<p>PM과 프론트엔드 개발자는 이야기를 꺼내자마자 바로 이해했다.
디자이너에게는 조금 더 풀어서 설명이 필요했다.</p>

<hr />

<h3 id="쿠팡으로-설명하기">쿠팡으로 설명하기</h3>

<p>기술적인 맥락 없이도 이해할 수 있도록, 쿠팡을 예시로 들었다.</p>

<blockquote>
  <p>쿠팡에서 상품을 장바구니에 담는다.
그리고 <strong>“주문하기” 버튼을 누른다</strong> — 이게 <strong>주문</strong>이다. 무엇을 사겠다는 확정.</p>

  <p>그다음 카드로 돈을 낸다 — 이게 <strong>결제</strong>다. 그 확정에 대한 지불.</p>
</blockquote>

<p>이해한 것 같긴 한데 뭔가 아리송한 대답이 돌아왔다. 그래서 반품 케이스를 추가로 붙였다.</p>

<blockquote>
  <p>쿠팡에서 반품 신청을 해본 적 있지 않냐.
반품 신청하면 바로 환불이 되지 않는다.
상품이 회수되고 검수가 끝난 다음에야 환불이 된다.</p>

  <p>즉, <strong>반품 신청은 됐지만 환불은 나중에</strong> 일어난다.
둘이 같은 개념이었다면 이런 흐름 자체가 불가능하다.</p>
</blockquote>

<p>이렇게 설명하니 디자이너도 바로 이해했고, 이후 화면 설계에서도 주문 흐름과 결제 흐름을 자연스럽게 분리해서 작업해줬다.</p>

<p>기술적으로 더 정확한 예시(결제 실패, 가상계좌 등)도 있지만, 비개발자에게는 직접 경험해본 상황을 예시로 드는 것이 가장 빠르게 와닿는다고 생각한다.</p>

<hr />

<h3 id="정리">정리</h3>

<p>이러한 개념을 팀 전체가 공유하는 건 단순히 개발 설계의 문제가 아니라고 생각한다.
개발, 디자인, 기획이 같은 언어로 이야기할 수 있어야 불필요한 혼선 없이 일이 진행된다고 생각한다.</p>

<p>이번 경우엔 <strong>기술 용어 없이 일상적인 비유 하나</strong>로 충분히 전달할 수 있었다.</p>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Thinking" /><category term="설계" /><category term="도메인" /><category term="C2C" /><summary type="html"><![CDATA[결제 == 주문? 외주사 코드를 인수하며 마주친 설계 문제와 팀 전체에 설명한 과정]]></summary></entry><entry><title type="html">Python(Django) Unittest Performance 개선 (with. seeds)</title><link href="https://paca94.github.io/python/Python-Django-Unittest-Performance-%EA%B0%9C%EC%84%A0/" rel="alternate" type="text/html" title="Python(Django) Unittest Performance 개선 (with. seeds)" /><published>2024-11-30T00:00:00+00:00</published><updated>2024-11-29T15:00:00+00:00</updated><id>https://paca94.github.io/python/Python-Django-Unittest-Performance-%EA%B0%9C%EC%84%A0</id><content type="html" xml:base="https://paca94.github.io/python/Python-Django-Unittest-Performance-%EA%B0%9C%EC%84%A0/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">테스트가 계속해서 느려진다! 왜그럴까? (600s -&gt; 70s)</span>
</code></pre></div></div>

<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<p>테스트 개수가 더 늘어나고 있고, 테스트시간이 다시 10분씩 걸리게 되어서 개선방법을 찾아봤다.</p>

<hr />

<h3 id="요약">요약</h3>

<ul>
  <li>느렸던 이유는 각 테스트가 돌 때마다 고정데이터(seed data)를 insert 해서 였음. (500개의 테스트라면 500번 데이터를 삽입함)</li>
  <li>고정 데이터의 경우, unittest fixtures 에 명시하는것이 아닌, test_runner에서 데이터베이스 초기화(setup_databases) 이후 넣으면 된다. ( db 연결을 끊기 전에 데이터를 지워줄 수 있지만, 고정데이터 이므로, 따로 설정하진 않음 )
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Example
</span>
<span class="k">class</span> <span class="nc">TestRunnerBase</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="nb">super</span><span class="p">().</span><span class="n">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="c1"># test db는 항상 존재하는 상황에서 테스트가 진행되므로, keepdb는 항상 True로 해놓는다.
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">keepdb</span> <span class="o">=</span> <span class="bp">True</span>

<span class="k">class</span> <span class="nc">CustomTestRunner</span><span class="p">(</span><span class="n">TestRunnerBase</span><span class="p">,</span> <span class="n">runner</span><span class="p">.</span><span class="n">DiscoverRunner</span><span class="p">):</span>
    <span class="c1"># 아래 메서드를 override 해줬음
</span>    <span class="k">def</span> <span class="nf">setup_databases</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">]:</span>
        <span class="n">result</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">]</span> <span class="o">=</span> <span class="nb">super</span><span class="p">().</span><span class="n">setup_databases</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="n">GlobalTestSetUpManager</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">result</span>

<span class="k">class</span> <span class="nc">CustomXMLTestRunner</span><span class="p">(</span><span class="n">TestRunnerBase</span><span class="p">,</span> <span class="n">XMLTestRunner</span><span class="p">):</span>
    <span class="c1"># 아래 메서드를 override 해줬음
</span>    <span class="k">def</span> <span class="nf">setup_databases</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">]:</span>
        <span class="n">result</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">tuple</span><span class="p">]</span> <span class="o">=</span> <span class="nb">super</span><span class="p">().</span><span class="n">setup_databases</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
        <span class="n">GlobalTestSetUpManager</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">result</span>

<span class="k">class</span> <span class="nc">GlobalTestSetUpManager</span><span class="p">:</span>
    <span class="n">_is_seed_setup</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">False</span>

    <span class="c1"># seeds 파일 내의 데이터를 불러옴
</span>    <span class="o">@</span><span class="nb">classmethod</span>
    <span class="k">def</span> <span class="nf">setup_seeds</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">cls</span><span class="p">.</span><span class="n">_is_seed_setup</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="n">cls</span><span class="p">.</span><span class="n">_is_seed_setup</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">call_command</span><span class="p">(</span>
            <span class="s">"loaddata"</span><span class="p">,</span>
            <span class="n">settings</span><span class="p">.</span><span class="n">SEEDS</span><span class="p">,</span>
            <span class="nb">format</span><span class="o">=</span><span class="s">"json"</span><span class="p">,</span>
        <span class="p">)</span>

    <span class="o">@</span><span class="nb">classmethod</span>
    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
        <span class="n">cls</span><span class="p">.</span><span class="n">setup_seeds</span><span class="p">()</span>
</code></pre></div>    </div>
  </li>
  <li>해당 개선으로 jenkins 에서 환경세팅을 제외한 테스트시간이 70초로 줄었다.</li>
</ul>

<hr />

<h3 id="테스트-해봤던-가설">테스트 해봤던 가설</h3>
<ul>
  <li>첫번째 가설: 데이터를 넣는데 시간이 오래걸린다
    <ul>
      <li>setUpTestData ~ TearDown까지 걸리는 시간을 측정해봄
        <ul>
          <li>실험을 잘못하긴 했었는데, 시간 차이가 거의 없었음</li>
        </ul>
      </li>
      <li>결론: 아님. 시간 차이가 거의 나질 않음</li>
    </ul>
  </li>
  <li>두번째 가설: 커넥션을 너무 자주맺어서 해당 시간이 오래걸린다
    <ul>
      <li>django에서 db connection/close 를 하는 부분을 찾아서 걸린시간을 측정해봄</li>
      <li>약 500회정도 커넥션을 맺고 끊었지만, 총시간은 10초도 걸리지 않았다</li>
    </ul>
  </li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="Django" /><category term="Unittest" /><summary type="html"><![CDATA[테스트가 계속해서 느려진다! 왜그럴까? (600s -> 70s)]]></summary></entry><entry><title type="html">로컬에서 AWS 서비스 에뮬레이터를 사용해보자!</title><link href="https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-AWS-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%97%90%EB%AE%AC%EB%A0%88%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90/" rel="alternate" type="text/html" title="로컬에서 AWS 서비스 에뮬레이터를 사용해보자!" /><published>2024-11-29T00:00:00+00:00</published><updated>2024-11-29T11:00:00+00:00</updated><id>https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-AWS-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%97%90%EB%AE%AC%EB%A0%88%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90</id><content type="html" xml:base="https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-AWS-%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%97%90%EB%AE%AC%EB%A0%88%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">로컬에서 사용해보자!</span>
</code></pre></div></div>

<hr />
<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>
<p>celery 테크스펙을 작성하며, DEVOPS에 리소스 요청 전에 테스트하기 위해 찾아봤다.</p>

<hr />

<h3 id="요약">요약</h3>

<ul>
  <li>Docker를 띄우거나, localstack을 pip으로 설치하여, 로컬에서 에뮬레이팅 할 수 있다.</li>
  <li>awscli 명령어와 호환된다. endpoint_url을 변경하여 요청하면, localstack에서 해당 동작이 일어난다.
    <ul>
      <li>Command Example
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>aws <span class="nt">--endpoint-url</span><span class="o">=</span>http://127.0.0.1:4566 sqs get-queue-attributes <span class="nt">--queue-url</span> &lt;http://127.0.0.1:4566/000000000000/default.fifo&gt; <span class="nt">--attribute-names</span> All
<span class="o">{</span>
    <span class="s2">"Attributes"</span>: <span class="o">{</span>
        <span class="s2">"ApproximateNumberOfMessages"</span>: <span class="s2">"1"</span>,
        <span class="s2">"ApproximateNumberOfMessagesNotVisible"</span>: <span class="s2">"0"</span>,
        <span class="s2">"ApproximateNumberOfMessagesDelayed"</span>: <span class="s2">"0"</span>,
        <span class="s2">"CreatedTimestamp"</span>: <span class="s2">"1659342190"</span>,
        <span class="s2">"DelaySeconds"</span>: <span class="s2">"0"</span>,
        <span class="s2">"LastModifiedTimestamp"</span>: <span class="s2">"1659342190"</span>,
        <span class="s2">"MaximumMessageSize"</span>: <span class="s2">"262144"</span>,
        <span class="s2">"MessageRetentionPeriod"</span>: <span class="s2">"345600"</span>,
        <span class="s2">"QueueArn"</span>: <span class="s2">"arn:aws:sqs:ap-northeast-2:000000000000:default.fifo"</span>,
        <span class="s2">"ReceiveMessageWaitTimeSeconds"</span>: <span class="s2">"0"</span>,
        <span class="s2">"VisibilityTimeout"</span>: <span class="s2">"1800"</span>,
        <span class="s2">"FifoQueue"</span>: <span class="s2">"true"</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li>boto3에서 endpoint_url을 설정하여, localstack에 동작시킬 수 있다.
    <ul>
      <li>Code Example
        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">client</span> <span class="o">=</span> <span class="n">boto3</span><span class="p">.</span><span class="n">client</span><span class="p">(</span>
    <span class="s">"sqs"</span><span class="p">,</span>
    <span class="n">aws_access_key_id</span><span class="o">=</span><span class="s">"fake"</span><span class="p">,</span>
    <span class="n">aws_secret_access_key</span><span class="o">=</span><span class="s">"fake"</span><span class="p">,</span>
    <span class="n">endpoint_url</span><span class="o">=</span><span class="s">"&lt;http://localhost:4566&gt;"</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">client</span><span class="p">.</span><span class="n">create_queue</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><a href="https://docs.localstack.cloud/aws/feature-coverage/">링크</a>에서 어떤 서비스들에 대해 에뮬레이팅 할 수 있는지 볼 수 있다. ( + 구현 정도 )</li>
  <li>테스트 환경에서 localstack을 활용하면, 기존에 테스트하기 힘들었던 sqs와 같은 aws service와 엮여있는 부분에 대해 테스트 할 수 있다.</li>
</ul>

<p>아래의 내용으로 docker compose로 실행시키고 해당 url로 요청하면 된다.</p>

<div class="language-docker highlighter-rouge"><div class="highlight"><pre class="highlight"><code>version: '3.1'

services:
  localstack:
    container_name: celery-localstack
    image: localstack/localstack-full
    ports:
        - "4566-4599:4566-4599"
        - "8080:8080"
    environment:
        - DEFAULT_REGION=ap-northeast-2
        - DEBUG=1
        - START_WEB=1
        - DATA_DIR=/tmp/localstack/data
        - DOCKER_HOST=unix:///var/run/docker.sock
        - HOST_TMP_FOLDER=/tmp/localstack
        - EXTRA_CORS_ALLOWED_ORIGINS=*
    volumes:
        - ".tmp/localstack:/var/lib/localstack"
        - "/var/run/docker.sock:/var/run/docker.sock"
    network_mode: 'bridge'
</code></pre></div></div>

<hr />

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

<ul>
  <li>배달의민족 사용사례
    <ul>
      <li><a href="https://techblog.woowahan.com/2638/">LocalStack을 활용한 Integration Test 환경 만들기 - 우아한형제들 기술블로그</a></li>
    </ul>
  </li>
  <li><a href="https://localstack.cloud/">로컬스택</a></li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="AWS" /><category term="AWS" /><category term="LocalStack" /><summary type="html"><![CDATA[로컬에서 사용해보자!]]></summary></entry><entry><title type="html">로컬에서 DynamoDB를 써보자</title><link href="https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-DynamoDB%EB%A5%BC-%EC%8D%A8%EB%B3%B4%EC%9E%90/" rel="alternate" type="text/html" title="로컬에서 DynamoDB를 써보자" /><published>2024-11-29T00:00:00+00:00</published><updated>2024-11-29T11:00:00+00:00</updated><id>https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-DynamoDB%EB%A5%BC-%EC%8D%A8%EB%B3%B4%EC%9E%90</id><content type="html" xml:base="https://paca94.github.io/aws/%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-DynamoDB%EB%A5%BC-%EC%8D%A8%EB%B3%B4%EC%9E%90/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">로컬에서 DynamoDB 사용해보기</span>
</code></pre></div></div>
<hr />

<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<p>비동기에서 데이터 저장을 DynamoDB로 할 예정이라 관련 정보를 찾아봤었다.</p>

<hr />

<h3 id="요약">요약</h3>

<p>아래 참고자료에 있는 링크로 접속하여, docker compose를 가져와서 실행한 후, endpoint_url만 변경해주면 된다.</p>

<ul>
  <li><strong>Python Code Example</strong>
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">client</span> <span class="o">=</span> <span class="n">boto3</span><span class="p">.</span><span class="n">client</span><span class="p">(</span>
    <span class="s">"dynamodb"</span><span class="p">,</span>
    <span class="n">aws_access_key_id</span><span class="o">=</span><span class="s">"fake"</span><span class="p">,</span>
    <span class="n">aws_secret_access_key</span><span class="o">=</span><span class="s">"fake"</span><span class="p">,</span>
    <span class="n">endpoint_url</span><span class="o">=</span><span class="s">"&lt;http://localhost:4566&gt;"</span><span class="p">,</span>
<span class="p">)</span>
</code></pre></div>    </div>
  </li>
  <li><strong>AWS CLI Example</strong>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aws dynamodb describe-table <span class="nt">--table-name</span><span class="o">=</span>test-serverless <span class="nt">--endpoint-url</span> &lt;http://localhost:18000&gt;
</code></pre></div>    </div>
  </li>
  <li>결과
    <div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
    </span><span class="nl">"Table"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
        </span><span class="nl">"AttributeDefinitions"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nl">"AttributeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"id"</span><span class="p">,</span><span class="w">
                </span><span class="nl">"AttributeType"</span><span class="p">:</span><span class="w"> </span><span class="s2">"S"</span><span class="w">
            </span><span class="p">},</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nl">"AttributeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"sort"</span><span class="p">,</span><span class="w">
                </span><span class="nl">"AttributeType"</span><span class="p">:</span><span class="w"> </span><span class="s2">"S"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">],</span><span class="w">
        </span><span class="nl">"TableName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"test-serverless"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"KeySchema"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nl">"AttributeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"id"</span><span class="p">,</span><span class="w">
                </span><span class="nl">"KeyType"</span><span class="p">:</span><span class="w"> </span><span class="s2">"HASH"</span><span class="w">
            </span><span class="p">},</span><span class="w">
            </span><span class="p">{</span><span class="w">
                </span><span class="nl">"AttributeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"sort"</span><span class="p">,</span><span class="w">
                </span><span class="nl">"KeyType"</span><span class="p">:</span><span class="w"> </span><span class="s2">"RANGE"</span><span class="w">
            </span><span class="p">}</span><span class="w">
        </span><span class="p">],</span><span class="w">
        </span><span class="nl">"TableStatus"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ACTIVE"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"CreationDateTime"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-08-18T18:37:41.370000+09:00"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"ProvisionedThroughput"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"LastIncreaseDateTime"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1970-01-01T09:00:00+09:00"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"LastDecreaseDateTime"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1970-01-01T09:00:00+09:00"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"NumberOfDecreasesToday"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
            </span><span class="nl">"ReadCapacityUnits"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
            </span><span class="nl">"WriteCapacityUnits"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w">
        </span><span class="p">},</span><span class="w">
        </span><span class="nl">"TableSizeBytes"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
        </span><span class="nl">"ItemCount"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w">
        </span><span class="nl">"TableArn"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:dynamodb:ddblocal:000000000000:table/test-serverless"</span><span class="p">,</span><span class="w">
        </span><span class="nl">"BillingModeSummary"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
            </span><span class="nl">"BillingMode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"PAY_PER_REQUEST"</span><span class="p">,</span><span class="w">
            </span><span class="nl">"LastUpdateToPayPerRequestDateTime"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2022-08-18T18:37:41.370000+09:00"</span><span class="w">
        </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div>    </div>
  </li>
</ul>

<hr />

<h3 id="참고자료">참고자료</h3>
<ul>
  <li><a href="https://docs.aws.amazon.com/ko_kr/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html">컴퓨터에 로컬로 DynamoDB 배포</a></li>
  <li>+localstack <a href="/aws/로컬에서-AWS-서비스-에뮬레이터를-사용해보자/">로컬에서 AWS 서비스 에뮬레이터를 사용해보자!</a></li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="AWS" /><category term="AWS" /><category term="DynamoDB" /><category term="Python" /><summary type="html"><![CDATA[로컬에서 DynamoDB 사용해보기]]></summary></entry><entry><title type="html">Python Unittest Performance 개선 (with. hashlib)</title><link href="https://paca94.github.io/python/Python-Unittest-Performance-%EA%B0%9C%EC%84%A0/" rel="alternate" type="text/html" title="Python Unittest Performance 개선 (with. hashlib)" /><published>2024-11-29T00:00:00+00:00</published><updated>2024-11-29T11:00:00+00:00</updated><id>https://paca94.github.io/python/Python-Unittest-Performance-%EA%B0%9C%EC%84%A0</id><content type="html" xml:base="https://paca94.github.io/python/Python-Unittest-Performance-%EA%B0%9C%EC%84%A0/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">Pycharm Profile 기능을 활용하여, 유닛테스트 속도 개선</span>
</code></pre></div></div>

<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<hr />

<p>faker사용시, 도메인을 동일하게 설정하고, email 호출하여 랜덤 생성시, 중복되는 문제가 있어서 관련 메서드를 작성하고 있었는데, 너무 느려서 확인해봤다.</p>

<h3 id="요약">요약</h3>

<hr />

<ul>
  <li>테스트 데이터를 만들기 위해 UserFactory를 호출하는데, 비밀번호 생성을 위해 <code class="language-plaintext highlighter-rouge">django.contrib.auth.hashers.make_password</code>를 호출하고 있음.</li>
  <li><code class="language-plaintext highlighter-rouge">django.contrib.auth.hashers.make_password</code>는 내부적으로 <code class="language-plaintext highlighter-rouge">hashlib.pbkdf2_hmac</code>를 호출하고 있었고, 해당 메서드가 사용시간의 80%를 점유함</li>
  <li>factory에서 필요한 상황이 아니라면, make_password를 호출하지 않도록 개선.</li>
  <li>프로파일 결과에서 해당 메서드가 오래걸리는것을 확인</li>
</ul>

<hr />

<ul>
  <li>
    <p>Pycharm Profile
<img src="/assets/image/2024/1129/profile.png" alt="profile" /></p>
  </li>
  <li>UserFactory 에서 옵션을 통해, make_password 호출 여부를 결정할 수 있도록 개선</li>
  <li>개선 결과
| stage   | before  | after     |
| ——- | ——- | ——— |
| local   | 1m33sec | 23sec     |
| jenkins | 11min   | 8min 7sec |</li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="Unittest" /><summary type="html"><![CDATA[Pycharm Profile 기능을 활용하여, 유닛테스트 속도 개선]]></summary></entry><entry><title type="html">Js sort ㅋㅋ</title><link href="https://paca94.github.io/javascript/Js-sort-%E3%85%8B%E3%85%8B/" rel="alternate" type="text/html" title="Js sort ㅋㅋ" /><published>2024-11-08T00:00:00+00:00</published><updated>2024-11-08T01:00:00+00:00</updated><id>https://paca94.github.io/javascript/Js-sort-%E3%85%8B%E3%85%8B</id><content type="html" xml:base="https://paca94.github.io/javascript/Js-sort-%E3%85%8B%E3%85%8B/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">JS sort... 네?</span>
</code></pre></div></div>

<p>이직도중 W사 코테를 보던 도중, 결과를 순서대로 반환해야해서, sort를 썼었음.</p>

<p>일부 실패 뜨길래, 일단 다른것부터 해야해서 미뤄뒀고, 왜 그런 결과가 나오는지 시험 끝나고, GPT에 물어가며 검토하다가 알게됨.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">t</span><span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">13</span><span class="p">];</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">sort</span><span class="p">());</span>
<span class="c1">// output: [1, 13, 3]</span>
</code></pre></div></div>

<p>아…. 이건 좀ㅋㅋㅋㅋㅋㅋ</p>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="JavaScript" /><category term="JavaScript" /><category term="Algorithm" /><summary type="html"><![CDATA[JS sort... 네?]]></summary></entry><entry><title type="html">MagicMock으로 호출시마다 결과를 다르게 주기 (with generator)</title><link href="https://paca94.github.io/python/MagicMock%EC%9C%BC%EB%A1%9C-%ED%98%B8%EC%B6%9C%EC%8B%9C%EB%A7%88%EB%8B%A4-%EA%B2%B0%EA%B3%BC%EB%A5%BC-%EB%8B%A4%EB%A5%B4%EA%B2%8C-%EC%A3%BC%EA%B8%B0-generator/" rel="alternate" type="text/html" title="MagicMock으로 호출시마다 결과를 다르게 주기 (with generator)" /><published>2024-11-03T00:00:00+00:00</published><updated>2024-11-03T11:00:00+00:00</updated><id>https://paca94.github.io/python/MagicMock%EC%9C%BC%EB%A1%9C-%ED%98%B8%EC%B6%9C%EC%8B%9C%EB%A7%88%EB%8B%A4-%EA%B2%B0%EA%B3%BC%EB%A5%BC-%EB%8B%A4%EB%A5%B4%EA%B2%8C-%EC%A3%BC%EA%B8%B0-generator</id><content type="html" xml:base="https://paca94.github.io/python/MagicMock%EC%9C%BC%EB%A1%9C-%ED%98%B8%EC%B6%9C%EC%8B%9C%EB%A7%88%EB%8B%A4-%EA%B2%B0%EA%B3%BC%EB%A5%BC-%EB%8B%A4%EB%A5%B4%EA%B2%8C-%EC%A3%BC%EA%B8%B0-generator/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">generator 활용하기</span>
</code></pre></div></div>
<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<p>테스트 작성하다가 알게되었다.</p>

<hr />
<h3 id="요약">요약</h3>
<p><code class="language-plaintext highlighter-rouge">~.side_effect</code>에 리스트로 반환할 값들을 할당해주면 된다.</p>

<hr />
<h3 id="내용">내용</h3>
<ul>
  <li>만약, side_effect에 크기 2를 가진 iterator를 썼다면, 그 이후 요청부터는 StopIteration이 발생한다.</li>
  <li>split_temp.py
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">OriginAny</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">running</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">"origin_run!"</span>

<span class="k">class</span> <span class="nc">CallingAny</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">work</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">org</span> <span class="o">=</span> <span class="n">OriginAny</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">org</span><span class="p">.</span><span class="n">running</span><span class="p">()</span>
</code></pre></div>    </div>
  </li>
  <li>test.py
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 위 예제 수정
</span>
<span class="k">class</span> <span class="nc">TestCallingAny_work_메서드_호출시</span><span class="p">:</span>
    <span class="o">@</span><span class="n">patch</span><span class="p">(</span><span class="s">"split_temp.OriginAny"</span><span class="p">,</span> <span class="n">new_callable</span><span class="o">=</span><span class="n">AnyMock</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">test_any</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mock_origin_any</span><span class="p">:</span> <span class="n">AnyMock</span><span class="p">):</span>
        <span class="n">instance</span> <span class="o">=</span> <span class="n">mock_origin_any</span><span class="p">.</span><span class="n">return_value</span>
        <span class="n">instance</span><span class="p">.</span><span class="n">running</span><span class="p">.</span><span class="n">side_effect</span> <span class="o">=</span> <span class="p">[</span><span class="s">"mock_run!"</span><span class="p">,</span> <span class="s">"mock_run2!"</span><span class="p">]</span>
        <span class="n">calling_any</span> <span class="o">=</span> <span class="n">CallingAny</span><span class="p">()</span>
        <span class="n">result</span> <span class="o">=</span> <span class="n">calling_any</span><span class="p">.</span><span class="n">work</span><span class="p">()</span>
        <span class="n">result2</span> <span class="o">=</span> <span class="n">calling_any</span><span class="p">.</span><span class="n">work</span><span class="p">()</span>

        <span class="k">assert</span> <span class="n">mock_origin_any</span><span class="p">.</span><span class="n">mock_calls</span> <span class="o">==</span> <span class="p">[</span><span class="n">call</span><span class="p">(),</span> <span class="n">call</span><span class="p">().</span><span class="n">running</span><span class="p">(),</span> <span class="n">call</span><span class="p">(),</span> <span class="n">call</span><span class="p">().</span><span class="n">running</span><span class="p">()]</span>
        <span class="k">assert</span> <span class="n">result</span> <span class="o">==</span> <span class="s">"mock_run!"</span>
        <span class="k">assert</span> <span class="n">result</span> <span class="o">==</span> <span class="s">"mock_run2!"</span>
</code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="Unittest" /><summary type="html"><![CDATA[generator 활용하기]]></summary></entry><entry><title type="html">Python은 Dict를 재활용한다</title><link href="https://paca94.github.io/python/Python%EC%9D%80-Dict%EB%A5%BC-%EC%9E%AC%ED%99%9C%EC%9A%A9%ED%95%9C%EB%8B%A4/" rel="alternate" type="text/html" title="Python은 Dict를 재활용한다" /><published>2024-11-02T00:00:00+00:00</published><updated>2024-11-02T11:00:00+00:00</updated><id>https://paca94.github.io/python/Python%EC%9D%80-Dict%EB%A5%BC-%EC%9E%AC%ED%99%9C%EC%9A%A9%ED%95%9C%EB%8B%A4</id><content type="html" xml:base="https://paca94.github.io/python/Python%EC%9D%80-Dict%EB%A5%BC-%EC%9E%AC%ED%99%9C%EC%9A%A9%ED%95%9C%EB%8B%A4/"><![CDATA[<!-- ```yaml
환경변수 설정
``` -->

<hr />
<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>
<p><a href="/python/dict는-언제-리사이즈될까/">dict는 언제 리사이즈될까</a> 를 찾아보다가 함꼐 알게된 부분</p>

<hr />

<h3 id="요약">요약</h3>
<ol>
  <li>python 에서 dict(<code class="language-plaintext highlighter-rouge">PyDictObject</code>)가 삭제된다면, 해당 dict는 파이썬 내부의 free_list로 이동한다</li>
  <li>free_list에는 최대 80(<code class="language-plaintext highlighter-rouge">PyDict_MAXFREELIST</code>)개까지 저장이 가능하며, 그 개수를 넘어가면 메모리를 해제한다</li>
  <li>PyDictObject 내부의 PyDictKeysObject는 삭제된다면, 해당 데이터의 크기가 기본 사이즈일 경우, 파이썬 내부의 keys_free_list로 동한다</li>
  <li>해당 리스트 또한 최대 80(<code class="language-plaintext highlighter-rouge">PyDict_MAXFREELIST</code>)개까지 저장 가능하며, 그 개수를 넘어가면 메모리를 해제한다.</li>
  <li>free_list / keys_free_list의 경우 old gc가 돌 때 메모리에서 해제된다.</li>
</ol>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">&gt;&gt;&gt;</span> <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="mi">4315419008</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">del</span> <span class="n">d</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d2</span> <span class="o">=</span> <span class="p">{}</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">d2</span><span class="p">)</span>
<span class="mi">4315419008</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d3</span> <span class="o">=</span> <span class="p">{}</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">del</span> <span class="n">d2</span>
<span class="o">&gt;&gt;&gt;</span> <span class="k">del</span> <span class="n">d3</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d4</span> <span class="o">=</span> <span class="p">{}</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">d4</span><span class="p">)</span>
<span class="mi">4315419136</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">d5</span> <span class="o">=</span> <span class="p">{}</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">id</span><span class="p">(</span><span class="n">d5</span><span class="p">)</span>
<span class="mi">4315419008</span>
</code></pre></div></div>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="CPython" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">instance Mock method 모킹</title><link href="https://paca94.github.io/python/instance-Mock-method-%EB%AA%A8%ED%82%B9/" rel="alternate" type="text/html" title="instance Mock method 모킹" /><published>2024-11-02T00:00:00+00:00</published><updated>2024-11-02T11:00:00+00:00</updated><id>https://paca94.github.io/python/instance-Mock-method-%EB%AA%A8%ED%82%B9</id><content type="html" xml:base="https://paca94.github.io/python/instance-Mock-method-%EB%AA%A8%ED%82%B9/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">객체 method 모킹하기</span>
</code></pre></div></div>
<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<p>테스트 작성하다가 알게되었다.</p>

<hr />
<h3 id="요약">요약</h3>
<p>아래처럼 instance에 대해 mock으로 만들고, 테스트 인라인에서 method를 patch해주려면 아래처럼 해야한다.</p>

<hr />
<h3 id="내용">내용</h3>

<ul>
  <li>split_temp.py
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">class</span> <span class="nc">OriginAny</span><span class="p">:</span>
  <span class="k">def</span> <span class="nf">running</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">return</span> <span class="s">"origin_run!"</span>

<span class="k">class</span> <span class="nc">CallingAny</span><span class="p">:</span>
  <span class="k">def</span> <span class="nf">work</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">org</span> <span class="o">=</span> <span class="n">OriginAny</span><span class="p">()</span>
    <span class="k">return</span> <span class="n">org</span><span class="p">.</span><span class="n">running</span><span class="p">()</span>
</code></pre></div>    </div>
  </li>
  <li>test.py
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">AnyMock</span><span class="p">(</span><span class="n">MagicMock</span><span class="p">):</span>
  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">any</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">:</span> <span class="nb">any</span><span class="p">):</span>
    <span class="nb">super</span><span class="p">().</span><span class="n">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">)</span>
    <span class="bp">self</span><span class="p">.</span><span class="n">mock_add_spec</span><span class="p">(</span><span class="n">spec</span><span class="o">=</span><span class="n">OriginAny</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">TestCallingAny_work_메서드_호출시</span><span class="p">:</span>
  <span class="o">@</span><span class="n">patch</span><span class="p">(</span><span class="s">"split_temp.OriginAny"</span><span class="p">,</span> <span class="n">new_callable</span><span class="o">=</span><span class="n">AnyMock</span><span class="p">)</span>
  <span class="k">def</span> <span class="nf">test_any</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mock_origin_any</span><span class="p">:</span> <span class="n">AnyMock</span><span class="p">):</span>
    <span class="n">instance</span> <span class="o">=</span> <span class="n">mock_origin_any</span><span class="p">.</span><span class="n">return_value</span>
    <span class="n">instance</span><span class="p">.</span><span class="n">running</span><span class="p">.</span><span class="n">return_value</span> <span class="o">=</span> <span class="s">"mock_run!"</span>
    <span class="n">calling_any</span> <span class="o">=</span> <span class="n">CallingAny</span><span class="p">()</span>
    <span class="n">result</span> <span class="o">=</span> <span class="n">calling_any</span><span class="p">.</span><span class="n">work</span><span class="p">()</span>

    <span class="k">assert</span> <span class="n">mock_origin_any</span><span class="p">.</span><span class="n">mock_calls</span> <span class="o">==</span> <span class="p">[</span><span class="n">call</span><span class="p">(),</span> <span class="n">call</span><span class="p">().</span><span class="n">running</span><span class="p">()]</span>
    <span class="k">assert</span> <span class="n">result</span> <span class="o">==</span> <span class="s">"mock_run!"</span>
</code></pre></div>    </div>
  </li>
</ul>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="Django" /><category term="Unittest" /><summary type="html"><![CDATA[객체 method 모킹하기]]></summary></entry><entry><title type="html">unittest 시, 데이터는 setUpTestData에서!</title><link href="https://paca94.github.io/python/unittest%EC%8B%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94-setUpTestData%EC%97%90%EC%84%9C/" rel="alternate" type="text/html" title="unittest 시, 데이터는 setUpTestData에서!" /><published>2024-11-02T00:00:00+00:00</published><updated>2024-11-02T11:00:00+00:00</updated><id>https://paca94.github.io/python/unittest%EC%8B%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94-setUpTestData%EC%97%90%EC%84%9C</id><content type="html" xml:base="https://paca94.github.io/python/unittest%EC%8B%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%8A%94-setUpTestData%EC%97%90%EC%84%9C/"><![CDATA[<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">유닛테스트 퍼포먼스 약간 향상</span>
</code></pre></div></div>

<hr />
<h3 id="찾아보거나알게된배경">찾아보거나 알게된 배경</h3>

<p>테스트 러닝타임이 너무 오래걸려서, 해당 시간을 줄일 방법이 없을까 하다가 데이터를 각 테스트 method가 아닌 setUpTestData에서 만들면 되겠다 싶어서 진행해봤다.</p>

<hr />
<h3 id="요약">요약</h3>
<p><strong>공통되는 데이터를 만들 때는 setUpTestData에서 데이터를 만들어주는게 훨씬 낫다</strong></p>

<hr />
<h3 id="내용">내용</h3>
<ol>
  <li>기존에 setup이나 테스트 안에서 데이터 만들어주는 부분이 있으면, 쿼리시간때문에 테스트시간이 길어진다 가정하고 있었음</li>
  <li>하나는 기존대로 test 내에서 각 데이터들을 만들어주게 유지</li>
  <li>하나는 기존에서 데이터를 만들어주는 부분에 대해서 setupTestData로 빼도록 함</li>
  <li>각 동일한 테스트에 대해 10개까지 늘린 후(복붙), 테스트 속도 비교 진행
    <blockquote>
      <p>로컬에서 실행시, 2.9s -&gt; 1.9s 로 감소</p>
    </blockquote>
  </li>
</ol>

<ul>
  <li>before code:
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="k">def</span> <span class="nf">test_asdf</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="n">item</span> <span class="o">=</span> <span class="n">generate_any_item</span><span class="p">()</span>
</code></pre></div>    </div>
  </li>
  <li>after code:
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="o">@</span><span class="nb">classmethod</span>
  <span class="k">def</span> <span class="nf">setUpTestData</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
    <span class="n">cls</span><span class="p">.</span><span class="n">item</span> <span class="o">=</span> <span class="n">generate_any_item</span><span class="p">()</span>

  <span class="k">def</span> <span class="nf">test_asdf</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="p">...</span>
</code></pre></div>    </div>
  </li>
</ul>

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

<hr />

<p>직접해봄</p>]]></content><author><name>paca94</name><email>jihwan.dev@gmail.com</email></author><category term="Python" /><category term="Python" /><category term="Django" /><category term="Unittest" /><summary type="html"><![CDATA[유닛테스트 퍼포먼스 약간 향상]]></summary></entry></feed>