<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ksh-code.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 16 Jul 2023 07:48:54 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ksh-code.log</title>
            <url>https://images.velog.io/images/ksh-code/profile/279304cd-d4bd-4335-ae73-4a3097bb3acb/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ksh-code.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ksh-code" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[varchar의 크기를 잘 설정 해야하는 이유 고찰]]></title>
            <link>https://velog.io/@ksh-code/varchar%EC%9D%98-%ED%81%AC%EA%B8%B0%EB%A5%BC-%EC%9E%98-%EC%84%A4%EC%A0%95-%ED%95%B4%EC%95%BC%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EA%B3%A0%EC%B0%B0</link>
            <guid>https://velog.io/@ksh-code/varchar%EC%9D%98-%ED%81%AC%EA%B8%B0%EB%A5%BC-%EC%9E%98-%EC%84%A4%EC%A0%95-%ED%95%B4%EC%95%BC%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EA%B3%A0%EC%B0%B0</guid>
            <pubDate>Sun, 16 Jul 2023 07:48:54 GMT</pubDate>
            <description><![CDATA[<h1 id="배경">배경</h1>
<ul>
<li><p>Real mysql을 읽다 평소에 궁금하던 mysql에서 varchar를 어떻게 다루는지에 대한 설명이 간략히 있었다.</p>
</li>
<li><p>기본적으로 아래 설명과 같이 255byte 까지는 prefix data로 1byte, 이후는 2byte를 사용하는 것은 알고있었다. 잘못 이해하는 경우 문자열의 길이로 오해할 수 있는데, encoding에 의한 byte에 대한 내용이므로 1글자당 4byte를 사용하는 encoding인 경우 약 63글자 정도만 prefix로 1byte만 사용하는 것이다.</p>
<blockquote>
<p>In contrast to CHAR, VARCHAR values are stored as a 1-byte or 2-byte length prefix plus data. The length prefix indicates the number of bytes in the value. A column uses one length byte if values require no more than 255 bytes, two length bytes if values may require more than 255 bytes.</p>
</blockquote>
</li>
<li><p>책에서는 한줄요약 급으로 설명하고 있어서, 실제 Engine layer에서는 어떻게 구현되어 있는지 궁금했다.</p>
</li>
</ul>
<h1 id="한-줄-요약">한 줄 요약</h1>
<ul>
<li>Temp table을 활용하는 경우 Mysql 5.7까지는 char와 동일하게 fixed-length를 사용한다.</li>
</ul>
<h1 id="설명">설명</h1>
<ul>
<li>Mysql 5.7에서는 일부 작은 데이터를 위해 Temp table을 활용할 때, Memory DB를 활용한다.</li>
<li>Memory DB는 varchar를 fixed-length로 활용한다.</li>
</ul>
<h1 id="구현-확인">구현 확인</h1>
<ul>
<li>sql_tmp_table.cc 에서 create_virtual_tmp_table 메서드같은 것을 통해 temp table을 만든다. record length는 아래와 같은 로직으로 설정된다.<pre><code>record_length+= (*field)-&gt;pack_length();</code></pre></li>
<li>pack_length 를 호출하는 것을 통해 record length를 구한다.<pre><code>/*
  pack_length() returns size (in bytes) used to store field data in memory
  (i.e. it returns the maximum size of the field in a row of the table,
  which is located in RAM).
*/
virtual uint32 pack_length() const { return (uint32) field_length; }</code></pre></li>
<li>hp_write.c에서 아래 코드로 메모리 할당한 후 write한다.<pre><code>memcpy(pos,record,(size_t) share-&gt;reclength);</code></pre></li>
</ul>
<h1 id="추가로-알게된-것">추가로 알게된 것</h1>
<ul>
<li>HA_KEYTYPE_VARTEXT1, HA_KEYTYPE_VARTEXT2는 Mysql source code내에서 prefix 길이를 구분하기 위한 enum이다.</li>
<li>Memory DB에서는 HA_KEYTYPE_VARTEXT1 로 통일해서 활용한다.</li>
<li><code>share-&gt;db_low_byte_first=1;                // True for HEAP and MyISAM</code> 에 의해 temp table의 storage engine이 설정된다.</li>
<li>key length도 더 많이 사용할 수 있다.<pre><code>        /*
          For BTREE algorithm, key length, greater than or equal
          to 255, is packed on 3 bytes.
        */</code></pre></li>
</ul>
<h1 id="결론">결론</h1>
<ul>
<li>Mysql8에서는 기본적으로 MemoryDB(heap)을 사용하지 않아서, 구현체가 다를 것이다.</li>
<li>어찌되었건 길이를 너무 늘려서 활용하는 것은 좋지 않다.</li>
</ul>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://dev.mysql.com/doc/refman/5.7/en/char.html">https://dev.mysql.com/doc/refman/5.7/en/char.html</a></li>
<li><a href="https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-tables.html">https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-tables.html</a></li>
<li><a href="https://dev.mysql.com/doc/refman/8.0/en/memory-storage-engine.html">https://dev.mysql.com/doc/refman/8.0/en/memory-storage-engine.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring에 기여하기 위한 여정]]></title>
            <link>https://velog.io/@ksh-code/Spring%EC%97%90-%EA%B8%B0%EC%97%AC%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%9C-%EC%97%AC%EC%A0%95</link>
            <guid>https://velog.io/@ksh-code/Spring%EC%97%90-%EA%B8%B0%EC%97%AC%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%9C-%EC%97%AC%EC%A0%95</guid>
            <pubDate>Mon, 03 Jul 2023 02:14:49 GMT</pubDate>
            <description><![CDATA[<p>글 정리하기에는 시간이 없어서 두서 없이 적어보겠다.</p>
<p>knwon-issue로는 <code>@TransactionalEventListener</code>를 활용하는 메서드에서는 <code>@Async</code>를 붙이지 않으면 오류가 발생하더라도 Debug로 로깅이 된다.</p>
<p><img src="https://velog.velcdn.com/images/ksh-code/post/0e4d99ee-6594-4784-9674-406e8fe2de6f/image.png" alt="">
<img src="https://velog.velcdn.com/images/ksh-code/post/417946f8-9d09-4067-9f5e-b953d52e5a29/image.png" alt=""></p>
<p>단순히 키워드 조합을 통해 검색하더라도 다른 개발자들도 Debug로 로깅이 되는 문제를 마주친 것을 알 수 있다.
해당 글들에서 설명하는 내용은</p>
<ol>
<li>call stack을 분석했을 때, 스프링에서 debug로 로깅하고 있다.</li>
<li>Async 어노테이션을 통해 수정이 가능하다.</li>
<li>혹은 여러 커스텀 로직을 추가해서 다른 처리가 가능하다.</li>
</ol>
<p>인데, 이 수정이 왜 발생했는지 근본적으로 파악해볼 필요가 있다.</p>
<p>github의 blame을 통해 따라가다 보면</p>
<ol>
<li><a href="https://github.com/spring-projects/spring-framework/commit/95110d825715a70dbc7fadc0e3ebd42f44e6bdfb">https://github.com/spring-projects/spring-framework/commit/95110d825715a70dbc7fadc0e3ebd42f44e6bdfb</a> 를 통해 커스텀 콜백을 등록할 수 있게 되는 것</li>
<li>수정 내용, 설명과는 무관하게 error level이 debug level로 바뀐 것</li>
</ol>
<p>을 알 수 있다.</p>
<p>따라서 <a href="https://github.com/spring-projects/spring-framework/pull/30776">https://github.com/spring-projects/spring-framework/pull/30776</a> 로 수정하니 바로 반영되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[(Hard) Minimum Difference in Sums After Removal of Elements]]></title>
            <link>https://velog.io/@ksh-code/Minimum-Difference-in-Sums-After-Removal-of-Elements</link>
            <guid>https://velog.io/@ksh-code/Minimum-Difference-in-Sums-After-Removal-of-Elements</guid>
            <pubDate>Sun, 22 Jan 2023 06:48:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ksh-code/post/bcc5de41-8603-45d5-9690-96c14432e888/image.png" alt="">
3*N 만큼 배열이 구성되어 있을 때, N개의 element를 배열에서 제외한 후
앞의 연속한 N개의 element를 더한 값을 first,
뒤의 연속한 나머지 N개의 element를 더한 값을 second라고 했을 때의
min(first - second)를 정답으로 구하는 문제이다.</p>
<p>시간 제한이 애매해서 어떻게 풀지 고민하다가</p>
<p>N개의 element를 first, second로 각각 구해서 연산해주는 방법을 활용했다.</p>
<p>N+1개의 element에서 first가 생긴다면, 1개의 elemen가 제외되고 큰 element들만 활용된다.
...</p>
<p>second도 같은 원리로 구해준 후 계산해주면 된다.</p>
<pre><code>using ll = long long;
using pii = pair&lt;int,int&gt;;
class Solution {
public:
    long long minimumDifference(vector&lt;int&gt;&amp; nums) {
        int N = nums.size() / 3;
        ll max_data[N*3];

        ll max_num = 0;
        priority_queue&lt;int, vector&lt;int&gt;, greater&lt;int&gt;&gt; lowest;
        for (int i = 2 * N; i &lt; 3 * N; i++) {
            max_num += nums[i];
            lowest.push(nums[i]);
        }
        max_data[2 * N] = max_num;

        for (int i = 2 * N - 1; i &gt;= N; i--) {
            lowest.push(nums[i]);
            max_data[i] = max_data[i + 1] + nums[i];
            max_data[i] -= lowest.top(); lowest.pop();
        }

        ll min_data[N*3];
        ll min_num = 0;
        priority_queue&lt;int&gt; highest;
        for (int i = 0; i &lt; N; i++) {
            highest.push(nums[i]);
            min_num += nums[i];
        }
        min_data[N-1] = min_num;
        for (int i = N; i &lt; 2 * N; i++) {
            highest.push(nums[i]);
            min_data[i] = min_data[i - 1] + nums[i];
            min_data[i] -= highest.top(); highest.pop();
        }
        ll result = 1e18;
        for (int i = N - 1; i &lt; 2 * N; i++) {
            result = min(result, min_data[i] - max_data[i + 1]);
        }
        return result;
    }
};</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[(Hard) Smallest Rotation with Highest Score]]></title>
            <link>https://velog.io/@ksh-code/Smallest-Rotation-with-Highest-Score</link>
            <guid>https://velog.io/@ksh-code/Smallest-Rotation-with-Highest-Score</guid>
            <pubDate>Sat, 14 Jan 2023 08:36:14 GMT</pubDate>
            <description><![CDATA[<p>0 &lt; K 번 rotate하면서 arr[i] &lt;= i 가 가장 많은 k를 구하면 된다.</p>
<p>접근 방법</p>
<ol>
<li>arr[i] &lt;= i 일 때, l~r 구간에서 조건이 성립하는지?(0 &lt;= l, r &lt; K)</li>
<li>l~r 뿐만 아니라 다른 구간까지 나머지 구간까지 구하면 된다.</li>
</ol>
<p>prefix sum으로 풀 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/ksh-code/post/b7446eea-fbe6-4a30-bc4d-1b54a0ab9d7a/image.png" alt=""></p>
<pre><code>class Solution {
public:
    int bestRotation(vector&lt;int&gt;&amp; nums) {

        ios_base::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        int N = nums.size();
        int counts[N]; memset(counts, 0, sizeof counts);
        for (int i = 0; i &lt; N; i++) {
            auto n = nums[i];
            int moves = 0;
            if (n &gt; i) moves = i+1;
            counts[moves]++;
            if (n == 0) continue;

            int next = i;
            if (moves &gt; i) next = N-1;
            moves += next-(n-1);
            if (moves &lt; N) {
                counts[moves]--;
                if (i - moves &gt;= 0) {
                    moves += i - moves + 1;
                    if (moves &lt; N) counts[moves]++;
                }
            }
        }

        int result = 0;
        int tr = 0;
        int index = 0;
        for (int i = 0; i &lt; N; i++) {
            tr += counts[i];
            if (result &lt; tr) {
                index = i;
                result = tr;
            }
        }
        return index;
    }
};</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TDD에 대한 짧은 생각]]></title>
            <link>https://velog.io/@ksh-code/TDD%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A7%A7%EC%9D%80-%EC%83%9D%EA%B0%81</link>
            <guid>https://velog.io/@ksh-code/TDD%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A7%A7%EC%9D%80-%EC%83%9D%EA%B0%81</guid>
            <pubDate>Tue, 11 Oct 2022 05:47:27 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>요즘 TDD, BDD와 같은 방법론에 대해 여러 의견들이 있는 것을 보았다.
그 내용들과 무관하게 TDD를 공부하며 적용하고, 적절한 부분에서 사용하게 된 배경을 공유하고, 피드백을 받음으로, 다른 의견들을 보고 배우고싶어서 부족한 지식이지만 짧은 생각을 글로 남겨본다.</p>
<h1 id="tdd">TDD</h1>
<p>TDD라는 용어를 약 5년전에 용어를 처음 접했다.
그때 보이던 글들에 의해서는 red-green-blue와 같은 사이클을 가지는 개발 프로세스이고, 되게 좋아보였다.
정리해보면 결국은 테스트코드를 먼저 작성하고, 테스트코드를 성공하기 위한 로직을 작성한 후 리팩토링하는 프로세스이다.</p>
<h2 id="tdd적용-사례-1">TDD적용 사례 1</h2>
<p>TDD를 한 번에 모든 업무에 도입하지는 않고, 일부 작업들에 활용했다.
첫 사례로는, 이미 만들어진 시스템에 버그가 발생했고, 이를 해결하는 과정에 적용해본 것이다.</p>
<p>그러면,</p>
<ol>
<li>문제가 되었던 파라매터들을 준비해서 regression test를 작성한다.</li>
<li>의도된대로 실패하는지 확인한다.</li>
<li>해결 후 동작이 잘 되는지 확인한다.</li>
<li>1~3을 반복 이후 로컬 혹은 개발서버에서 실제 유저의 시나리오를 재현하며 동작이 잘 되는지 확인한다.</li>
</ol>
<p>순서로 개발이 끝나게 된다.
이 과정에서는 4번을 가장 마지막에 할 수 있게되어 데이터 세팅, 브라우저 새로고침 등 번거로운 작업을 뒤로 미루게되어 효율적이었다.</p>
<p>즉, 테스트 실행을 IDE에서 간편히 할 수 있는 세팅과의 시너지가 있었다.</p>
<h2 id="tdd적용-사례-2">TDD적용 사례 2</h2>
<p>하지만, 신규 기능을 새로운 구조로 구현할 때는 비효율의 어려움이 있었다.</p>
<p>테스트를 작성하며 새로운 모델, 코드 구조를 작성한다.
=&gt; 작성 중인 코드 혹은 구상중인 코드가 비효율적이라고 판단되는 피드백이 느리다.</p>
<p>머릿속으로 코드 구조를 상상하고, 비효율적이라고 판단되면 다른 구조를 생각하는게 훨씬 빠르고 효율적이다.
=&gt; TDD를 활용하면 무의식적으로 코드 작성에 집중하게 되어, 구조 개선에 집중이 안된다.</p>
<p>라는 결론이 나왔다.</p>
<h2 id="tdd적용-사례-3">TDD적용 사례 3</h2>
<p>리팩토링에서도 TDD의 방법을 따와서 작업하면 효과적이다.
이미 기존 로직들에 테스트 코드가 있다면, 동작이 깨지지 않는 선에서 수정하기가 수월하다.</p>
<p>하지만, 테스트 케이스 및 테스트 코드가 없는 경우는 기존 동작이 유지된다는 100%확신을 할 수 없다.
따라서 테스트 코드를 만들어서 기존 동작을 보장시키고, 내부 구현 최적화를 하는데에는 자신감있게 작업할 수 있어서 좋았다.</p>
<h2 id="결론">결론</h2>
<p>TDD방법론은 이상적인 시나리오를 위해 나왔다고 생각한다.
하지만 현실의 문제는 &#39;시간 = 비용&#39;이다.</p>
<p>따라서 적절히 TDD의 방법론의 방법을 엔지니어링에 적용하니,</p>
<ol>
<li>작업의 자신감</li>
<li>작업의 속도</li>
</ol>
<p>가 장점으로 작용되는 부분이</p>
<ol>
<li>regression test</li>
<li>refactoring</li>
</ol>
<p>에 있었다.</p>
<p>다른 부분들은 딱히 드라마틱한 이점이 없었다.</p>
<h1 id="추후-읽어보면-좋을-글들">추후 읽어보면 좋을 글들</h1>
<ul>
<li><a href="https://martinfowler.com/articles/mocksArentStubs.html">Mockist testing, Classical testing</a></li>
<li><a href="https://martinfowler.com/bliki/UnitTest.html">Unit test</a></li>
<li><a href="https://testing.googleblog.com/2021/06/how-much-testing-is-enough.html">How Much Testing is Enough</a></li>
<li><a href="https://testing.googleblog.com/2021/04/mutation-testing.html">Mutation Testing</a></li>
<li><a href="https://anthonysciamanna.com/2016/02/14/should-private-methods-be-tested.html">SHOULD PRIVATE METHODS BE TESTED</a></li>
<li><a href="https://testing.googleblog.com/2020/12/test-flakiness-one-of-main-challenges.html">Test Flakiness - One of the main challenges of automated testing</a></li>
<li><a href="https://testing.googleblog.com/2021/03/test-flakiness-one-of-main-challenges.html">Test Flakiness - One of the main challenges of automated testing (Part II</a></li>
</ul>
<ul>
<li><a href="https://www.linkedin.com/in/seonghoon-kim-55195915a/">내 소개</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[충남대학교 2022 알고리즘 대회 upsolving]]></title>
            <link>https://velog.io/@ksh-code/%EC%B6%A9%EB%82%A8%EB%8C%80%ED%95%99%EA%B5%90-2022-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8C%80%ED%9A%8C-upsolving</link>
            <guid>https://velog.io/@ksh-code/%EC%B6%A9%EB%82%A8%EB%8C%80%ED%95%99%EA%B5%90-2022-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8C%80%ED%9A%8C-upsolving</guid>
            <pubDate>Tue, 04 Oct 2022 05:05:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ksh-code/post/dfc31846-d383-4656-a5fe-b35f2ba34a70/image.png" alt="">
<img src="https://velog.velcdn.com/images/ksh-code/post/94c3b91a-8445-4d70-a457-233e2d84b9f1/image.png" alt=""></p>
<p>회전 목마 문제 빼고 다 풀었다.
최근 골랜디를 하고 있는데, 효과가 있는 거 같다.</p>
<p>나중에 editorial이 나오면 남은 1문제도 풀어봐야지..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[gcd(m,n)=d ->gcd(m/d,m/n)=1]]></title>
            <link>https://velog.io/@ksh-code/gcdmnd-gcdmdmn1</link>
            <guid>https://velog.io/@ksh-code/gcdmnd-gcdmdmn1</guid>
            <pubDate>Thu, 28 Apr 2022 11:45:33 GMT</pubDate>
            <description><![CDATA[<p>gcd(m,n)=d 이면 gcd(m/d,m/n)&gt;1이라고 가정해보자
그러면 ad | m, ad | n을 만족하는 어떠한 a가 존재해서 서로소가 아니게된다.
따라서 gcd(m/d,m/n)=1이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[7의 배수 증명]]></title>
            <link>https://velog.io/@ksh-code/7%EC%9D%98-%EB%B0%B0%EC%88%98-%EC%A6%9D%EB%AA%85</link>
            <guid>https://velog.io/@ksh-code/7%EC%9D%98-%EB%B0%B0%EC%88%98-%EC%A6%9D%EB%AA%85</guid>
            <pubDate>Thu, 21 Apr 2022 08:35:19 GMT</pubDate>
            <description><![CDATA[<ul>
<li>6k: a(6k) * 1</li>
<li>6k+1: a(6k+1) * 3</li>
<li>6k+2: a(6k+2) * 2</li>
<li>6k+3: a(6k+3) * -1</li>
<li>6k+4: a(6k+4) * -3</li>
<li>6k+5: a(6k+5) * -2</li>
</ul>
<p>을 더한 게 7로 나눠지면 7의 배수이다.</p>
<p>1001을 통해 증명가능하다.</p>
<p>우선 6k+2까지만 보면
100a + 10b + c = 0 mod 7
2a + 3b + c = 0 mod 7</p>
<p>6k+345는 1001이 7의 배수인 것을 이용해서 증명</p>
<p>1001(100<em>a + 10</em>b + c) - 100<em>a - 10</em>b - c = 0 mod 7</p>
<p>-3<em>a-2</em>b-c = 0 mod 7
반복...</p>
<pre><code>def check?(i)
  data = [1,3,2]
  @test = -1
  i.to_s.chars.reverse.map.with_index do |c, index|
    c.to_i * data[index % 3]
  end.inject(:+) % 7 == 0
end
a=0
1.upto(3000000) do |i|
  a=i
  if i % 7 == 0
    p &quot;yes no #{i}&quot; unless check?(i)
  elsif check?(i)
    p &quot;no yes #{i}&quot;
  end
end</code></pre><p>로 답을 확인 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tip] Github]]></title>
            <link>https://velog.io/@ksh-code/Tip-Github</link>
            <guid>https://velog.io/@ksh-code/Tip-Github</guid>
            <pubDate>Wed, 20 Apr 2022 06:32:08 GMT</pubDate>
            <description><![CDATA[<p>ctrl + k or command + k
이후 requesting 입력 -&gt; 자신에게 리뷰 요청온 PR목록 확인 가능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[포모도로]]></title>
            <link>https://velog.io/@ksh-code/%ED%8F%AC%EB%AA%A8%EB%8F%84%EB%A1%9C</link>
            <guid>https://velog.io/@ksh-code/%ED%8F%AC%EB%AA%A8%EB%8F%84%EB%A1%9C</guid>
            <pubDate>Mon, 18 Apr 2022 06:44:57 GMT</pubDate>
            <description><![CDATA[<h2 id="개요">개요</h2>
<ul>
<li>집중력의 농도를 짙게 하기위해 해본다.</li>
<li>우선은 여러 가이드에 따라 5분 집중, 1분 휴식 주기를 반복하며 진행한다.</li>
<li>지치지 않기 위해 적절한 휴식을 도입하기 위함도 있다.</li>
</ul>
<h2 id="리뷰">리뷰</h2>
<p>아직 많이 해보지는 않았지만 5분 집중 구간에 집중력이 높아지며 뭔가 호르몬이 분비되는 느낌을 받는데, 1분 휴식의 alert이 울리면 바로 작업을 멈추고 딴짓을한다. 그러면서 다시 1분 휴식이 지난 후에는 다시 작업을 착수하며 다른 몰입했던 방법(구현)이 아닌 다른 방법을 확인하기도 한다.</p>
<p>평균적인 집중 수치가 유지되며 흥미도 높아졌다.</p>
<p>이후 적응되면 10분정도로 늘려보거나 나에게 맞는 여러가지 시도를 해볼 것이다.</p>
<p>현재는 시간만 조절하고 있다.
이후에 해볼 것들은</p>
<ol>
<li>태스크에 걸리는 시간을 명확히 파악</li>
<li>여러 가지 일들을 switching하며 처리가 어느정도 퍼포먼스가 나오는지 파악</li>
<li>집중을 멈추고 다른 방향으로 구현 방식 및 솔루션을 변경했을 때, 효과가 있는지 파악</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[ruby가 성능상 문제가 될 수 있다?]]></title>
            <link>https://velog.io/@ksh-code/ruby%EA%B0%80-%EC%84%B1%EB%8A%A5%EC%83%81-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8B%A4</link>
            <guid>https://velog.io/@ksh-code/ruby%EA%B0%80-%EC%84%B1%EB%8A%A5%EC%83%81-%EB%AC%B8%EC%A0%9C%EA%B0%80-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8B%A4</guid>
            <pubDate>Mon, 21 Feb 2022 04:11:33 GMT</pubDate>
            <description><![CDATA[<p><a href="https://twitter.com/mmmandel/status/1200585514463698944">https://twitter.com/mmmandel/status/1200585514463698944</a>
로 반증됨.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[트렌드]]></title>
            <link>https://velog.io/@ksh-code/%ED%8A%B8%EB%A0%8C%EB%93%9C</link>
            <guid>https://velog.io/@ksh-code/%ED%8A%B8%EB%A0%8C%EB%93%9C</guid>
            <pubDate>Sat, 16 Oct 2021 11:33:49 GMT</pubDate>
            <description><![CDATA[<p>트렌드를 열심히 따라가기 위해 하는 것들이다.</p>
<ul>
<li>커뮤니티 참여</li>
<li>최신 작성된 글 읽기</li>
<li>괜찮아보이는 책 읽기</li>
</ul>
<h2 id="커뮤니티-참여">커뮤니티 참여</h2>
<ul>
<li>다양한 사람들이 글을 많이 작성하는 커뮤니티에서 내가 원하는 토픽을 읽고, 궁금한 것은 질문하거나 틀린 것은 의견을 제안한다.</li>
</ul>
<p>주로 reddit, velog를 이용하는데, reddit은 offical news를 가장빨리 접할 수 있는 공간이기도 하다. 그리고 오픈소스 maintainer들이 직접 활동을 하기도 해서 다양한 의견을 주고받기에도 좋다.</p>
<ul>
<li>ruby</li>
<li>rails</li>
<li>softwarearchitecture</li>
</ul>
<p>이 것들 중에서는 웬만하면 매일 top rated된 글을 읽으려고 노력한다. 홛동하다보면 얻는 Karama를 쌓아나가는 재미가 쏠쏠하기도 하다.
반대로 잘못된 정보를 말하면 downvote가 막 찍혀서 잘못된 정보구나 알기도 쉽다.</p>
<p>velog는 국내 커뮤니티인데, 빠르게 읽고 국내의 트렌드를 쉽게 접할 수 있어서 좋다.</p>
<h2 id="최신-작성된-글-읽기">최신 작성된 글 읽기</h2>
<p>medium에 원하는 토픽을 구독해서 매일 읽어보려고 노력한다.
가끔 reference를 타고타고 가다보면 좋은 paper나 기업의 기술블로그를 볼 수 있는데, 웹서핑하듯이 다 읽어보는 편이다.
많이 하다보니 이제는 제목만 보고, 읽고싶은 글인지 아닌지 알 수 있게되었다. 괜찮다 생각하는 글은 <a href="https://github.com/KSH-code/awesome-practical-posts">Github</a>에 정리도 한다.</p>
<h2 id="괜찮아보이는-책-읽기">괜찮아보이는 책 읽기</h2>
<p>GoF, DDIA, Clean Architecture, Database Internals 등 좋은 책들은 항상 어디선가에서 레퍼런스로 사용된다.
익숙한 이름이면, 후기도 읽어보고 괜찮은 책이면 일단 사놓는다.
그러면 나중에 아까워서라도 읽게되더라..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[피보나치 수열 - 행렬을 통해 구하기]]></title>
            <link>https://velog.io/@ksh-code/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%97%B4-%ED%96%89%EB%A0%AC%EC%9D%84-%ED%86%B5%ED%95%B4-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ksh-code/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%97%B4-%ED%96%89%EB%A0%AC%EC%9D%84-%ED%86%B5%ED%95%B4-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 08 Oct 2021 01:36:27 GMT</pubDate>
            <description><![CDATA[<p>f1 = 0, f2 = 1 이라면, 0, 1, 1, 2, 3, 5... 일 것이다.</p>
<p>[f1, f2] = [0, 1]이다.</p>
<p>[f2, f3] = A[0, 1]이다.</p>
<p>A를 구하는 것은 원래의 점화식을 생각하면 쉽다.
[
1 0
1 1
]
이다.</p>
<p>그렇다면,
[f3, f4] = A[f2, f3]인데,
[f2, f3]은 풀어서 보면 A*[0,1]이다.</p>
<p>따라서, 결합 법칙과 일반화를 통해 A^n[0,1]을 [fn, fn+1]으로 볼 수 있다.</p>
<p>문제풀기 위해 시간복잡도를 줄이면, A^n은 A^(n/2)의 제곱으로 처리가 가능하다.</p>
<p>그래서 O(logN)이 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] pipe operator]]></title>
            <link>https://velog.io/@ksh-code/JS-pipe-operator</link>
            <guid>https://velog.io/@ksh-code/JS-pipe-operator</guid>
            <pubDate>Tue, 05 Oct 2021 06:48:59 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>흔히 JS를 이용해서 코드르 작성할 때, 함수를 통해 반환하는 값을 다른 함수에 이용하고, 그리고 이 과정을 반복하는 경우가 많다.</p>
<pre><code>const a = pow(30, 2);
const b = pow(a, 30);
const c = pow(a, 30);

or
pow(pow(pow(30, 2), 30), 30));

or
30.pow(2).pow(30).pow(30);</code></pre><p>위와 같이 작성하는 경우</p>
<ol>
<li>깊이가 점점 깊어지는 문제</li>
<li>불필요한 변수가 할당되는 문제</li>
</ol>
<p>가 필연적으로 발생한다.
(1) 은 가독성을 해치므로 문제가 되는데, (2) 는 공감이 잘 가지 않을 수 있다.
하지만 Martin Fowler의 글에서도 설명하지만[1], 변수명 정하는 것은 아주 어려운 일이다. 즉, 시간이 불필요하게 소요될 수 있는 것을 의미한다.</p>
<p>하지만 우리는 fluent interface[2]를 이용해서, 이 문제들을 해결하고 있다.
그런데 fluent interface는 언어레벨에서 제공하는 기능이 아니므로, JS의 native keyword와 조합해서 사용할 수 없는 문제가 있다.</p>
<p>따라서, 특정 값을 연속해서 활용하는 것은 항상 기능 구현하는데에 overhead가 따르게된다.</p>
<h2 id="해결">해결</h2>
<p>아직 정확히 어떤 문법을 사용할지는 정해지지 않아서, 어떤 방식으로 해결할 예정인지만 간략히 설명하겠다.</p>
<pre><code>const result = 30 |&gt; pow(^, 2) |&gt; pow(^, 30) |&gt; pow(^, 30);</code></pre><p>와 같은 코드가 될 예정이다.</p>
<p>풀어서 설명하자면,
<code>|&gt;</code>를 통해 value를 pipe처럼 연속적으로 사용하는 것이다.</p>
<ol>
<li>30이 ^를 통해 불러와져서, 계산됨</li>
<li>(1)에서 계산된 값이 ^로 불러와져서 pow(^, 30)이 계산됨</li>
<li>(2)에서 계산된 값이 ^로 불러와져서 pow(^, 30)이 계산됨</li>
<li>마지막으로 <code>result</code>에 할당됨</li>
</ol>
<h2 id="마무리">마무리</h2>
<p>위 기능을 Babel을 통해 미리 사용하는 것은 가능하다.</p>
<p>하지만, 현재 Stage2상태여서 빨라도 ECMAScript에 1년안에 적용될 내용은 아닌거 같다.</p>
<p>매우 유익한 토론이 진행 중이니, 오픈소스 커뮤니티에서는 어떤 식으로 논의가 진행되는지 확인하면 좋을 것이다.</p>
<h3 id="ref">Ref</h3>
<ol>
<li><a href="https://martinfowler.com/bliki/TwoHardThings.html">https://martinfowler.com/bliki/TwoHardThings.html</a></li>
<li><a href="https://en.wikipedia.org/wiki/Fluent_interface">https://en.wikipedia.org/wiki/Fluent_interface</a></li>
<li><a href="https://github.com/tc39/proposal-pipeline-operator">https://github.com/tc39/proposal-pipeline-operator</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Clean Architecture 리뷰]]></title>
            <link>https://velog.io/@ksh-code/Clean-Architecture-%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@ksh-code/Clean-Architecture-%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Wed, 29 Sep 2021 07:20:24 GMT</pubDate>
            <description><![CDATA[<p>Robert C. Martin의 Clean Architecture를 다 읽었다.
읽기 전 기대했던 내용과는 사뭇 달랐지만, 그래도 어떤 mindset을 통해 software architecture를 가꿔나가야 할지 어느정도의 가이드는 됐다.</p>
<p>우선, 이 책은 입문자 용이 아니다. Design pattern, Object 설계 등 Robert C. Martin의 다른 책들을 읽은 것을 가정하고 설명하기 때문에 모른다면 참고문헌을 알아서 보라고 책에서도 설명한다.</p>
<p>그렇기 때문에 입문자가 읽는다면 용어들의 뜻을 잘 파악하지 못해 잘못된 내용을 이해하거나 이해하는데 시간이 많이 걸릴 수 있다.</p>
<p>이 책에서 강조하는 내용은 세 가지정도로 요약이 가능할 것 같다.</p>
<ol>
<li><p>고수준의 컴포넌트는 저수준에 종속되면 안된다. 저수준은 고수준의 interface를 이용하되, 특정한 내용에 종속되면 안된다. 이를 지키기 위해서는 SOLID principle 중 D를 활용할 수 있다.</p>
</li>
<li><p>세부사항은 언제든지 변경할 수 있는 대비가 돼야하나, over engineering은 하지말자. 만약 데이터베이스를 Mysql을 이용하다가 MongoDB를 이용해야될 때, 모든 코드가 변경돼야하면 어떻게 되는 걸까? 서비스가 웹 기반으로 되어있다가 native application을 지원하도록 변경해야 된다면 어떻게 해야될까? 즉, business rule에 관련된 고수준 컴포넌트는 저수준에 영향을 받으면 안된다. 항상 세부사항이 변경될 수 있는 것을 열어두되 가능성이 없는 것을 고려하기 위해 over engineering은 하지말자</p>
</li>
<li><p>rule을 통해 강제하지 말고 compiler나 linter와 같은 자동도구를 통해 구축한 Architecture를 위반하는 것을 막자. 누군가는 규칙을 몰라서 의도한 architecture를 위반하기 쉽다. 따라서 긴밀하게 코드리뷰를 해야하고 이는 자동화 된 도구를 통해 강제하면 좋다.</p>
</li>
</ol>
<p>어쩌다보니 요약하면서 더 쓰고싶은 말이 많지만 1번만 읽은 내용이라서 정리가 잘 되지 않았다.
다른 책들을 읽어보고 다시 읽어봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Single Responsibility Principle 이해하기]]></title>
            <link>https://velog.io/@ksh-code/Single-Responsibility-Principle-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ksh-code/Single-Responsibility-Principle-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 26 Sep 2021 15:10:11 GMT</pubDate>
            <description><![CDATA[<p>SOLID principle의 첫 원칙인 SRP에 대해 모호했던 부분들이 있었고, 다시 이해하고 헷갈리고를 반복하는 과정이 있었기때문에 간략히 정리해본다.</p>
<p>SRP가 정리된 글들을 종종 읽어보면, 너무 생략해서</p>
<blockquote>
<p>한 기능은 한 역할만 해야한다.</p>
</blockquote>
<p>라고 설명한다.</p>
<p>그렇다면 질문이 추가로 생기게된다.</p>
<p>하나의 기능은 무엇이고 하나의 역할은 무엇일까?
이 질문에 대한 해답을 찾기 전에 SOLID가 무엇을 위함인지를 아는 것이 먼저이다.</p>
<blockquote>
<p>SOLID는 완벽하지도 않고 휴리스틱을 이용하여 해결을 위한 가이드이다. [1]</p>
</blockquote>
<blockquote>
<p>SOLID는 5개의 design principles들을 이용해서 유지보수를 쉽게 도와주고, 기능을 쉽게 이해하도록 도와주고, 개발확장성 쉽게하도록 도와준다. [2]</p>
</blockquote>
<p>간략하게 이 정도면 SOLID가 무엇을 추구하는지는 알게되었다.</p>
<p>다시 원래의 질문으로 돌아와 답변해보자</p>
<p>하나의 기능은 무엇일까?</p>
<p>모듈이다. [3]
하지만 모듈이라는 것은 너무 모호해서 단순히 함수와 데이터 정보를 묶은 Class정도로 이해해도 괜찮다.</p>
<p>그렇다면 첫 질문인 기능의 단위는 해결되고 마지막 질문이 남는데, 이 부분이 가장 실수가 많이 발생하고 연습이 많이 필요한 부분이라고 생각한다.</p>
<p>SRP를 만든 Robert C. Martin(a.k.a uncle bob)의 설명에 의하면 </p>
<blockquote>
<p>하나의 기능은 한 가지의 변화에 대해서만 변경돼야한다.</p>
</blockquote>
<p>이다. 하지만 변화에 대한 이유가 아직까지 모호하다.</p>
<p>코드와 함께 살펴보자</p>
<pre><code>public class Employee {
  public Money calculatePay();
  public void save();
  public String reportHours();
}</code></pre><p>코드는 회사의 관점에서 작성되어 있고,</p>
<ul>
<li>caclulatePay: 지급해야 할 급여 계산</li>
<li>save: 직원의 정보를 저장</li>
<li>reportHours: 근무시간</li>
</ul>
<p>정도로 구성된 클래스가있다.
언뜻보면 Employee클래스는 회사의 구성원에 대한 한 역할만 하는 것으로 이해될 수 있다.
하지만 Bob이 원하는 관점은 다르다.</p>
<p>caculatePay의 기능이 어느날 문제가 생겨서 직원들에게 급여가 잘못 지급되는 문제가 발생했다. 극단적으로 이 책임을 지고 누군가 퇴사를 해야하는 경우가 생기면 누가 퇴사를 해야할까?</p>
<p>애매하다. 그래서 원인을 찾아보니 calculatePay메서드는 기존과 동일하지만 save의 동작이 calculatePay에서 참조하는 변수와 동일해서 예상하지 못한 side-effect이 발생한 것이다.</p>
<p>이를 방지하기 위해 각각의 기능을 클래스로 분리해서 서로 영향이 없게 처리해야한다.</p>
<p>그런데 다시 모호한 부분이 발생한다. 어떠한 기준을 통해 각 기능들을 모듈화할 것인가?
이는 Bob이 방법을 제안한다.</p>
<blockquote>
<p>한 사람 혹은 한 그룹에 의해 변경되는 기능끼리 모아야한다. [3]</p>
</blockquote>
<p>원문에서는 C-level의 결정권자를 통해 설명한다.</p>
<ul>
<li>CFO: calculatePay</li>
<li>COO: reportHours</li>
<li>CTO: save</li>
</ul>
<p>각 메서드별로 변경을 필요로하는 사람이 다르다. 따라서 세 개의 모듈(클래스)로 분리돼야한다.</p>
<h2 id="참고문헌">참고문헌</h2>
<ol>
<li><a href="https://sites.google.com/site/unclebobconsultingllc/getting-a-solid-start">https://sites.google.com/site/unclebobconsultingllc/getting-a-solid-start</a></li>
<li><a href="https://en.wikipedia.org/wiki/SOLID">https://en.wikipedia.org/wiki/SOLID</a></li>
<li><a href="https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html">https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html</a></li>
</ol>
]]></description>
        </item>
    </channel>
</rss>