<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>berry-io-europa.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 02 Aug 2025 05:26:38 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>berry-io-europa.log</title>
            <url>https://velog.velcdn.com/images/berry-io-europa/profile/d0224658-3ce3-4ba8-8b0e-de761a5f90ab/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. berry-io-europa.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/berry-io-europa" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Kubernetes] ConfigMap과 Secret의 차이는 인코딩 뿐일까?]]></title>
            <link>https://velog.io/@berry-io-europa/Kubernetes-ConfigMap%EA%B3%BC-Secret%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EC%9D%B8%EC%BD%94%EB%94%A9-%EB%BF%90%EC%9D%BC%EA%B9%8C</link>
            <guid>https://velog.io/@berry-io-europa/Kubernetes-ConfigMap%EA%B3%BC-Secret%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EC%9D%B8%EC%BD%94%EB%94%A9-%EB%BF%90%EC%9D%BC%EA%B9%8C</guid>
            <pubDate>Sat, 02 Aug 2025 05:26:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 기본적인 쿠버네티스 지식이 있는 사람들을 대상으로 작성된 문서입니다.</p>
</blockquote>
<h1 id="configmap과-secret">ConfigMap과 Secret</h1>
<p>쿠버네티스의 ConfigMap과 Secret은 주로 애플리케이션의 설정 값을 저장하기 위해 사용된다. 생성과 사용법도 크게 다르지 않다.</p>
<pre><code class="language-yaml">apiVersion: v1
kind: ConfigMap
metadata:
  name: berry
data:
  name: Berry
  nationality: Korean
  age: &quot;32&quot;
  simple_key_val: |
    desksetup.keyboard=keychron
    desksetup.mouse=logitec</code></pre>
<p>ConfigMap은 일반적인 설정 데이터를 저장할 때 사용된다. 도메인주소, 포트 번호, 환경 변수 등이 그 예이다.</p>
<pre><code class="language-yaml">apiVersion: v1
kind: Secret
metadata:
  name: berry
type: Opaque
data:
  secretname: YmVycnktaW8tZXVyb3BhCg==
  password: dGVzdDEyMzQK</code></pre>
<p>Secret은 비밀번호, API 키, 인증서 등 외부에 노출되면 안되는 민감정보를 저장하는데 사용된다. 일반 텍스트로 저장하는 것이 아닌 base64로 인코딩 된 데이터를 저장하여 옆에서 슬쩍 봤을 때는(?) 바로 값을 알기 힘들다.</p>
<p>하지만 암호화(encrypted)가 아닌, 인코딩(encoded)되었다는 점에서 정말 데이터 보호가 안전하다고는 할 수 없다. 기본적으로 쿠버네티스에서 Secret 리소스를 암호화하진 않는다. 그래서 encrypt at rest를 권장한다.(<a href="https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/">링크</a>)</p>
<p>물론 secret이 TLS나 dockercred 등을 저장할 수 있고 자잘한 차이점이 있긴 하지만 기본적으로 보안 측면에서 큰 차이가 보이진 않는다.</p>
<h2 id="base64가-끝">Base64가 끝?</h2>
<p>ConfigMap과 Secret 모두 환경변수로 선언하거나 파일로 마운트하여 사용할 수 있다는 점에서 매우 유사하다. 단지 base64 하나 먹이려고 Secret을 나눈 것인가에 대한 생각이 들어 더 자세히 찾아보니... 아주 중요한 차이점이 있었다.</p>
<p>바로 Secret이 노드 내에 저장되는 방식에서의 차이점이다.</p>
<h3 id="tmpfs">tmpfs</h3>
<p><img src="https://velog.velcdn.com/images/berry-io-europa/post/44975c66-5e58-48a3-a952-967173ddb731/image.png" alt=""></p>
<p>굉장히 익숙한 단어이다. 
<code>df -h</code>라는 익숙한 명령어를 치면 보이는 unix-like의 OS에서 거의 볼 수 있는 파일시스템이다.</p>
<p>tmpfs는 RAM 기반의 휘발성 파일 시스템으로 데이터가 디스크에 물리적으로 기록되지 않고 메모리(RAM)에만 존재한다.</p>
<h3 id="secret은-마운트되어-사용될-때-tmpfs에-저장된다">Secret은 마운트되어 사용될 때 tmpfs에 저장된다.</h3>
<p>secret이 파드에서 마운트되어 사용될 때 해당 파드가 위치한 노드의 tmpfs에 저장된다.
이로 인해 노드가 재부팅되거나 파드가 삭제되면 tmpfs에 저장된 Secret 데이터는 자동으로 사라져 ConfigMap에 비해서 훨씬 안전하다.</p>
<p>물론 volume에 마운트 될 때만의 차이점이긴 하지만 단지 base64로 인코딩한 것 이외에 이런 차이가 있다는 것을 알고 조금 놀랐다. 많은 포스트에서 이 얘기가 없기 때문이다.</p>
<p>민감 정보는 꼭! Secret에 두고 쓰자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] GIL 간단설명]]></title>
            <link>https://velog.io/@berry-io-europa/Python-GIL-%EA%B0%84%EB%8B%A8%EC%84%A4%EB%AA%85</link>
            <guid>https://velog.io/@berry-io-europa/Python-GIL-%EA%B0%84%EB%8B%A8%EC%84%A4%EB%AA%85</guid>
            <pubDate>Sun, 01 Dec 2024 07:54:02 GMT</pubDate>
            <description><![CDATA[<h1 id="python의-gil이란">Python의 GIL이란...</h1>
<p>GIL은 Global Interpreter Lock의 줄임말이다.</p>
<p>이것의 정체는 정확히는 &#39;뮤텍스&#39;이다. 이 뮤텍스는 한번에 오직 하나의 스레드만이 파이썬 인터프리터에 대한 control을 할 수 있게 제한한다.</p>
<p>즉, 진정한 의미의 멀티스레딩이 불가하다는 것이다.</p>
<h1 id="왜-gil을-사용할까">왜 GIL을 사용할까?</h1>
<h2 id="python의-gc">Python의 GC</h2>
<p>공식 파이썬 implementation은 <a href="https://github.com/python/cpython">CPython</a>이다.</p>
<p>이 CPython은 Garbage Collection을 수행할 때, Reference Count(RC)를 본다.</p>
<p>파이썬에서 모든 데이터는 객체이며 각 객체는 변수에 의해서 참조된다.</p>
<p>예를 들어 아래 코드를 보자</p>
<pre><code class="language-python">a = [1, 2, 3]  # 1
b = a          # 2</code></pre>
<ol>
<li><p><code>[1, 2, 3]</code>객체는 변수 <code>a</code>에 의해 참조된다. 여기서 RC는 1이다.</p>
</li>
<li><p><code>[1, 2, 3]</code> 객체는 이제 변수 &#39;b&#39;에 의해서도 참조된다. 이제 RC는 2가 된다.</p>
</li>
</ol>
<p>그럼 Garbage Collect가 일어나도록 해보자.</p>
<pre><code class="language-python">a = [1, 2, 3]
b = a

a = &#39;a&#39;    # 3
b = &#39;b&#39;    # 4</code></pre>
<ol start="3">
<li><p>변수 <code>a</code>가 str 객체 <code>a</code>를 참조하게 되면서 <code>[1, 2, 3]</code>의 RC는 1로 줄어든다.</p>
</li>
<li><p>변수 <code>b</code> 또한 str 객체 <code>b</code>를 참조하게 되면서 <code>[1, 2, 3]</code>의 RC는 0이 된다. 이제 <code>[1, 2, 3]</code>은 언제든지 GC가 될 수 있다.</p>
</li>
</ol>
<h2 id="critical-section-문제">Critical Section 문제</h2>
<p>OS를 공부하신 분이라면 모두 들어봤을 멀티스레딩의 <a href="https://en.wikipedia.org/wiki/Critical_section">critical section</a>을 생각해 봐야 한다.</p>
<p>RC의 값을 변경하는 것이 바로 Critical Section이 된다. 여러개의 스레드가 동일한 객체를 참조한다고 해보자. 당연히 이 값을 업데이트 하는데 문제가 있을 것 같다는 생각이 든다.</p>
<p>CPython에서는 이 문제를 해소하기 위해 GIL을 사용하는 것이다. 결론적으로 보면 <strong>GC를 제대로 하기 위해서 GIL을 사용</strong>하는 것이다.</p>
<h1 id="gil의-문제점">GIL의 문제점</h1>
<p>앞에서도 말했듯이 우리가 원하는 진정한 멀티스레딩(여러개의 코어에서 각각 스레드가 돌아가는)을 구현하려면 GIL은 당연히 문제가 된다.</p>
<p>특히 CPU-bounded 한 task를 수행하는데 성능에 큰 지장을 준다. 이때문에 이를 과도한 통제라고 하는 시각도 적지 않다.</p>
<p>하지만 파이썬을 사용한다고 무조건 GIL을 사용해야 하는 것은 아니다. <a href="https://www.jython.org/">Jython</a>이나 <a href="https://ironpython.net/">IronPython</a> 같은 파이썬 구현체는 GIL을 사용하지 않음으로써 멀티스레딩을 구현할 수 있도록 한다.</p>
<h1 id="앞으로-gil의-운명">앞으로 GIL의 운명</h1>
<p>성능적으로 이슈가 많다는 것을 당연히 파이썬재단에서도 알고 있다. 그래서 그런지 파이썬 3.13이 올해 release하면서 <a href="https://docs.python.org/3/whatsnew/3.13.html#free-threaded-cpython">GIL을 선택적으로 사용할 수 있도록 해주는 experimental feature</a>가 추가되었다.</p>
<p>멀리 내다보았을 때 아무래도 싱글스레드를 고집할 수 없기 때문에 GIL은 언젠가는 사라질 듯 하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Algorithm] Moore's Voting Algorithm]]></title>
            <link>https://velog.io/@berry-io-europa/Moores-Voting-Algorithm</link>
            <guid>https://velog.io/@berry-io-europa/Moores-Voting-Algorithm</guid>
            <pubDate>Sat, 27 Jul 2024 08:50:57 GMT</pubDate>
            <description><![CDATA[<p><code>Moore&#39;s Voting algorithm</code>은 어떤 배열이 있을 때 과반수 이상 나타나는 원소를 구하는 알고리즘이며 <code>Boyer-Moore majority vote algorithm</code>이라고도 한다.</p>
<h2 id="기본-아이디어">기본 아이디어</h2>
<p>배열 내에 과반 이상을 차지하는 값이 있다면 투표의 마지막에는 해당 원소가 최후의 승자가 될 것이라는 아이디어를 기반으로 고안되었다.</p>
<p>크게 2 단계로 이루어져 있는데,</p>
<ol>
<li>투표를 통해서 후보를 가려낸다. (후보와 같은 값이면 vote에 1을 더하고 아니면 1을 뺀다.)</li>
<li>실제 해당 후보가 과반 이상 나타났는지 확인한다.</li>
</ol>
<p>만약 무조건 과반 이상 나타나는 원소가 있다고 가정하면 2번째 단계는 건너뛰어도 된다.</p>
<h2 id="예시1">예시#1</h2>
<p>철수, 영희, 민수, 은지, 지원 5사람이 저녁 메뉴를 투표를 통해 정하기로 하였다. 과반의 표를 얻는 메뉴가 선정된다.
투표 결과는 다음과 같다.</p>
<table>
<thead>
<tr>
<th>철수</th>
<th>영희</th>
<th>민수</th>
<th>은지</th>
<th>지원</th>
</tr>
</thead>
<tbody><tr>
<td>일식</td>
<td>일식</td>
<td>중식</td>
<td>일식</td>
<td>한식</td>
</tr>
</tbody></table>
<p>위의 결과를 보면 일식이 3표로 <code>5/2=2.5</code> 이상을 차지하는 <i>과반</i>의 값이라고 볼 수 있다. 이를 해당 알고리즘을 통해서 순서대로 살펴보자.</p>
<ol>
<li>철수가 일식에 투표했다. 후보는 일식이며, vote 수는 1이다.</li>
<li>영희가 일식에 투표했다. 후보와 같은 값이기 때문에 vote에 1을 더해 2가 된다.</li>
<li>민수가 중식에 투표했다. 후보가 다른 값이기 때문에 vote에 1을 빼서 1이 된다.</li>
<li>은지가 일식에 투표했다. 후보가 같은 값이기 때문에 vote에 1을 더해 2가 된다.</li>
<li>지원이 한식에 투표했다. 후보가 다른 값이기 때문에 vote에 1을 빼서 1이 된다.</li>
</ol>
<p>마지막에 후보로 나온 일식이 과반 이상이 나왔을 것이라고 예상한다.
실제로 과반 이상이 나왔는지 확인해보자.</p>
<table>
<thead>
<tr>
<th>일식</th>
<th>일식</th>
<th>중식</th>
<th>일식</th>
<th>한식</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>2</td>
<td>2</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td>투표 순서대로 일식일 경우에 count를 1씩 더해준 결과가 위 표에 나타나있다.</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>최종 일식에 투표한 사람 수가 3이므로 과반(2.5)이므로 일식이 <code>majority element</code>라고 할 수 있다.</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h2 id="예시2">예시#2</h2>
<p>이번엔 다른 예시를 들어보자.</p>
<table>
<thead>
<tr>
<th>철수</th>
<th>영희</th>
<th>민수</th>
<th>은지</th>
<th>지원</th>
</tr>
</thead>
<tbody><tr>
<td>일식</td>
<td>한식</td>
<td>한식</td>
<td>일식</td>
<td>일식</td>
</tr>
</tbody></table>
<p>이번에는 아무도 중식에 투표하지 않았다. 최종적으로 일식이 과반이지만 중간에 한식이 2표가 있다. 처음에는 일식이 후보겠지만 바로 뒤에 한식이 2번 연속으로 오면서 vote가 음수가 될 것이다. 하지만 이 알고리즘은 vote가 0이 되면 바로 후보를 교체한다.</p>
<ol>
<li>철수가 일식에 투표했다. 후보는 일식이며, vote 수는 1이다.</li>
<li>영희가 한식에 투표했다. 후보가 다른 값이기 때문에 vote에 1을 빼서 0이 된다.</li>
<li>민수가 한식에 투표했다. vote가 0이기 때문에 후보를 한식으로 변경하고 vote를 1로 초기화한다.</li>
<li>은지가 일식에 투표했다. 후보가 다른 값이기 때문에 vote에 1을 빼서 0이 된다.</li>
<li>지원이 일식에 투표했다. vote가 0이기 때문에 후보를 일식으로 변경하고 vote를 1로 초기화한다.</li>
</ol>
<p>이번에도 마지막에 일식이 후보이고 최종 과반인지 확인해보니 3이므로 메뉴는 일식으로 결정되었다.</p>
<table>
<thead>
<tr>
<th>일식</th>
<th>한식</th>
<th>한식</th>
<th>일식</th>
<th>일식</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</tbody></table>
<h2 id="코드">코드</h2>
<pre><code class="language-python">def moore_voting_algorithm():
    nums = [1, 1, 2, 3, 1]
    # 변수 초기화
    candidate = nums[0]
    vote = 0

    for num in nums:
        # vote가 0이면 후보를 교체한다.
        if vote == 0:
            candidate = num
            vote = 1
        else:
            # 현재 값이 후보와 같은 값이면 vote에 1을 더한다.
            if num == candidate:
                vote += 1
            # 현재 값이 후보와 다른 값이면 vote에 1을 뺀다.
            else:
                vote -= 1

    occurrences = 0
    for num in nums:
        if num == candidate:
            occurrences += 1

    if occurrences &gt; len(nums)//2:
        print(f&quot;{candidate}은 과반을 획득했습니다.&quot;)
    else:
        print(&quot;과반을 획득한 원소는 없습니다.&quot;)</code></pre>
]]></description>
        </item>
    </channel>
</rss>