<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>기술 여행~ 창작 여행~</title>
    <link>https://shesbe.tistory.com/</link>
    <description>기술 블로그</description>
    <language>ko</language>
    <pubDate>Wed, 3 Jun 2026 03:03:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>개발짜맠</managingEditor>
    <image>
      <title>기술 여행~ 창작 여행~</title>
      <url>https://tistory1.daumcdn.net/tistory/223214/attach/f639b0f305ed43f691b7b2369f0ad295</url>
      <link>https://shesbe.tistory.com</link>
    </image>
    <item>
      <title>Spec-kit 시작하기 #1</title>
      <link>https://shesbe.tistory.com/entry/Spec-kit-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 나같이 늙은 개발자들은 좀 무서울것이다. AI 발전속도 때문에 배워야 하는데, 업무는 바쁘고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신경써서 책임져야 하는 일은 많고..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 좀 볼라 치면 이해는 가는데 잘 안들어오기도 하고..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나랑같이 한번 시작해보자. 나도 잘 모르니까 혹시 엇나가는 부분이 있으면 댓글로 혼내주면 반영하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spec-Kit 은 SDD(Spec Driven Develop) 를 위한 프레임워크(Tool-Kit) 으로 Github 이 공개했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 기반으로 개발을 하는데, 바이브코딩은 맥락 유지의 한계가 있으니 스펙을 정의하고, 그 스펙을 기반으로 LLM 에게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일을 시켜보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Intelij 에서 Cladue Plugin 을 설치한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 파일 &amp;gt; 설정 &amp;gt; 플러그인 &amp;gt; Claude code[beta] 설치&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Intelij 에서 Claude 를 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우측상단의 Claude 아이콘을 누르면 터미널 옆에 새 탭으로 Claude 가 뜬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Claude 터미널에서 아래를 입력한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;&amp;gt; uv tool install specify-cli --from git+https://github.com/github/spec-kit.git


# 당신의 IDE 에 따라 골라주세용~
&amp;gt; specify init . --ai claude --force

&amp;gt; specify init . --ai claude  --force     # Claude Code
&amp;gt; specify init . --ai copilot --force     # GitHub Copilot
&amp;gt; specify init . --ai cursor  --force     # Cursor
&amp;gt; specify init . --ai windsurf --force    # Windsurf
&amp;gt; specify init . --ai gemini  --force     # Gemini CLI&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 지금 Intellij 를 쓰고 있다. 그리고 claude 를 쓰고있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; &lt;span&gt;uv tool &lt;/span&gt;&lt;span style=&quot;color: #0051c2;&quot;&gt;install&lt;/span&gt;&lt;span&gt; specify-cli --from git+&lt;a href=&quot;https://github.com/github/spec-kit.git&quot;&gt;https://github.com/github/spec-kit.git&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;gt; specify init . --ai claude&amp;nbsp; --force&amp;nbsp; &amp;nbsp; &amp;nbsp; # Claude Code&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 입력하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈프로젝트는 빠르지만 , 뭔가 구성이 많은 프로젝트는 프로젝트를 스캔후에 내용을 포함하여 생성되니 유의하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 uvx 가 없다면 아래를 진행하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;macOS / Linux&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;bash&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;vim&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;curl -LsSf https://astral.sh/uv/install.sh | sh&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;powershell&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;powershell
Set-ExecutionPolicy RemoteSigned -scope CurrentUser
powershell -ExecutionPolicy ByPass -c &quot;irm https://astral.sh/uv/install.sh | iex&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다시 명령어를 실행하면,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1775743880491&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CLAUDE.md
.claude/skills/speckit-analyze
.claude/skills/speckit-어쩌구..
...
...
.specify/extensions
.specify/intergrations
....&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 디렉토리와 파일이 생겼을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 버전의 spec-kit 의 경우&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;./claude/command/speckit-clearfy.md 등의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디렉토리에 명령어별 md 파일이 생성되어 , 자신이 직접&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; /speckit-clearfy&amp;nbsp; &quot;유저정보 crud api 개발&quot;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같이 커맨드 중심으로 해줘야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 최신버전의 speckit 은 이걸 AI 사용 룰 답지 못하다고 생각했는지,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커맨드는 그냥 사용자가 치는 맥락을 LLM 이 알아서 이해하고 커맨드 역할을 실행하도록 대체하고, skills 중심으로 업데이트 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거야 말로 희소식이고, 정말 내블로그 라서 하는 소리가 아니고 진짜 예상했던 바다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많이 어렵진 않지만 구성이 조금 복잡하여 sdd 장벽이 높은감이 있었기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음글에서 계속..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>speckit</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/81</guid>
      <comments>https://shesbe.tistory.com/entry/Spec-kit-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-1#entry81comment</comments>
      <pubDate>Thu, 9 Apr 2026 23:40:08 +0900</pubDate>
    </item>
    <item>
      <title>Kinesis 사용기</title>
      <link>https://shesbe.tistory.com/entry/Kinesis-%EC%82%AC%EC%9A%A9%EA%B8%B0</link>
      <description>&lt;h2 data-end=&quot;65&quot; data-start=&quot;33&quot; data-section-id=&quot;1tc1hfa&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-end=&quot;65&quot; data-start=&quot;33&quot; data-section-id=&quot;1tc1hfa&quot; data-ke-size=&quot;size26&quot;&gt;Kinesis 는 Kafka랑 뭐 비슷하겠지&lt;/h2&gt;
&lt;p data-end=&quot;183&quot; data-start=&quot;67&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;183&quot; data-start=&quot;67&quot; data-ke-size=&quot;size16&quot;&gt;처음에 &lt;span&gt;&lt;span&gt;Amazon Kinesis&lt;/span&gt;&lt;/span&gt; 를 붙일 때는 되게 가벼운 마음이었다.&lt;br /&gt;AWS 안에서 해결되고, 따로 브로커 신경 안 써도 되고, 그냥 넣으면 흘러가는 구조니까.&lt;/p&gt;
&lt;p data-end=&quot;265&quot; data-start=&quot;185&quot; data-ke-size=&quot;size16&quot;&gt;비슷한 계열인 &lt;span&gt;&lt;span&gt;Apache Kafka 는 직접 설치 구성해서 오래동안 컨피그 하나하나 설정해가며&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;265&quot; data-start=&quot;185&quot; data-ke-size=&quot;size16&quot;&gt;주키퍼랑 같이 디테일하게 운영해 봤던 관계로, Kinesis 정도야&amp;nbsp;금방 익숙해지겠지 하고 접근했다.&lt;/p&gt;
&lt;p data-end=&quot;265&quot; data-start=&quot;185&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;문제는 실제로 데이터 저장하고 Consumer 를 붙히기 시작하면서 부터 였다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;On-Demand mode&amp;nbsp; 에서 Kinesis 는 초당 처리량에 따라 자동으로 Shard 를 증가시킨다. 그래서 ingest 규모가 커지면 순식간에 Shard 가&amp;nbsp;50개~ 100 개~ 200개~ 막 늘어난다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;이 Shard 수는 개발자가 제어할 수 가없다. 이게 데이터 소비할때 Kafka 와 큰 차이를 만들어 낸다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;Provisoned Mode 는 샤드고정이라 좋기는한데 많이 쓰지 않아도 Shard 수만큼 고정비용을 무조건 내야한다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;또 Provisioned Mode 라 해도 어차피 처리 한계량 ( &lt;b&gt;1 MB/s&lt;/b&gt; 또는 &lt;b&gt;1,000 records/s) &lt;/b&gt;이 있어 트래픽이 많다면 위험할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;이 글에서는 On-Demand 를 사용했을때에 대해 이야기한다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-section-id=&quot;1tc1hfa&quot; data-start=&quot;33&quot; data-end=&quot;65&quot; data-ke-size=&quot;size26&quot;&gt;Kinesis 즉시 소비를 요하는 스트리밍 Queue&lt;/h2&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;Kafka 시나리오를 보자.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;클러스터 노드수, 디스크량, 컨슈머 수 등을 고려하여 Queue 의 파티션을 생성한다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;데이터를 저장하면 고정된 파티션에 저장되고, Consumer 는 파티션 개수만큼 붙어 순차적으로 데이터를 가져온다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;만약 컨슈머 하나가 파티션 2개를 담당하게 되더라도, 파티션 2개만큼 스레드가 생성되 동시에 fetch 하는게 아니라,&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;하나의 스레드가 2개 파티션에서 한번의 fetch 개수 만큼 나눠서 가져와 제어가 가능했다 ( 물론 옵션을 통해 동시 처리 스레드를 늘릴수 있었다. )&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;그런데 Kinesis 는 Shard 가 자동으로 늘어나는 구조라고 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;(게다가, 트래픽 확장을 고려하면 고정모드로 쓰는것도 무서우니)&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;그러니까 Consumer 를 전략적으로 운영할 수 가없는것이다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;Shard 개수만큼 Consumer 의 워커 스레드를 강제로 생성하고 동시에 fetch 한다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;AWS SDK Kinesis 옵션을 살펴보면, 이걸 제한할 옵션도 지원하지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;(최근 버전이었는데 아마 지금도 그럴것이다 )&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;보통 AWS Kinesis SDK 를 사용하니, Shard 수가 250 개라면, 컨슈머가 붙는 순간 컨슈머의 워커 스레드가 250개가 생성되어&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;동시에 fetch 한다...&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;정말 난감한 순간이었다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;보통은 fetch 문제가 아니라, 그걸 가공하여 다음 스텝으로 던져줘야 하므로,&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;다음 스텝의 인프라가 소형이거나 받아줄수 없다면 문제가 될수 밖에 없다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;65&quot; data-start=&quot;33&quot; data-section-id=&quot;1tc1hfa&quot; data-ke-size=&quot;size26&quot;&gt;Message Push, Event 알림, 채팅에 적합&lt;/h2&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;만약 이러한 유형의 비즈니스라면 참 괜찮았을 것이다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;Consume 받은 메시지를 Virtual Thread 로 I/O 를 동시 다발적으로 처리해버리면 아름답게&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;대량의 데이터를 처리할 수 있엇을 것이다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;( 아 물론 개념적으로 말이 그렇다는거다. )&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;그러나 사정상 처리 결과를 받는 최종 목적지가 소형이었고 Queue 를 바꿀수도 없는 상황이라&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;Semapore Global Lock 으로 어쩔수 없이 울며겨자 먹기로 제어를 했다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;컨슈머 스레드의 시작 지점에 Global Lock 개수를 제한하여 대기후, 정해진 스레드만 동작하도록 한것이다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;만약 Kinesis Consumer 를 구현하게 된다면 이게 무슨말이고 어디에 구현해야&amp;nbsp; 되는지 알게 될것이다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;난 분명 이러한 이유로 Kafka 를 사용하려고 했지만 여러 사정상 어쩔수 없이 Kinesis 를 써야만 했다...&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이러한 제약사항에도 불구하고 코드 자체는 아름답게 짰으니 다행이라면 다행일까?&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;이러한 문제로 Shutdown 시 이벤트를 받아 Lock 으로 인한 대기열 스레드가 모두 소진되면 그때서야 종료되도록 처리 했다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;물론 갑자기 서버가 죽으면 날라간다.. ( 뭐 그건 다른 Queue 도... 하지만 좀더 손실 범위가 적으니.. )&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;다들 알겠지만 혹시나 Kinesis 를 선택할때 이러한 특성을 한번쯤 확인해 도움이 되었으면 좋겠다.&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;355&quot; data-start=&quot;332&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AWS</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/80</guid>
      <comments>https://shesbe.tistory.com/entry/Kinesis-%EC%82%AC%EC%9A%A9%EA%B8%B0#entry80comment</comments>
      <pubDate>Thu, 9 Apr 2026 21:33:51 +0900</pubDate>
    </item>
    <item>
      <title>ClickHouse 장점</title>
      <link>https://shesbe.tistory.com/entry/ClickHouse-%EC%9E%A5%EC%A0%90</link>
      <description>&lt;p data-end=&quot;166&quot; data-start=&quot;112&quot; data-ke-size=&quot;size16&quot;&gt;최근 나는 &lt;span&gt;&lt;span&gt;ClickHouse&lt;/span&gt;&lt;/span&gt; 를 쓰고 있다.&lt;/p&gt;
&lt;p data-end=&quot;210&quot; data-start=&quot;168&quot; data-ke-size=&quot;size16&quot;&gt;거의 빠돌이 수준이다.&lt;br /&gt;이걸 왜 이제야 썼나 싶을 정도로 만족도가 높다.&lt;/p&gt;
&lt;p data-end=&quot;258&quot; data-start=&quot;212&quot; data-ke-size=&quot;size16&quot;&gt;물론 단점도 있다.&lt;br /&gt;Self-Host 기준으로는 동적 노드 추가가 꽤 불편하다.&lt;/p&gt;
&lt;p data-end=&quot;280&quot; data-start=&quot;260&quot; data-ke-size=&quot;size16&quot;&gt;그래서 지금은 SaaS로 쓰고 있다.&lt;/p&gt;
&lt;p data-end=&quot;318&quot; data-start=&quot;282&quot; data-ke-size=&quot;size16&quot;&gt;그럼에도 불구하고 계속 쓰는 이유?&lt;br /&gt;실제로 써보면 답 나온다.&lt;/p&gt;
&lt;hr data-end=&quot;323&quot; data-start=&quot;320&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;347&quot; data-start=&quot;325&quot; data-section-id=&quot;or76f2&quot; data-ke-size=&quot;size26&quot;&gt;내가 느낀 ClickHouse 장점&lt;/h2&gt;
&lt;hr data-end=&quot;352&quot; data-start=&quot;349&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;388&quot; data-start=&quot;354&quot; data-section-id=&quot;19irjj8&quot; data-ke-size=&quot;size23&quot;&gt;1. Object Storage 기반 구조 (진짜 큼)&lt;/h3&gt;
&lt;p data-end=&quot;474&quot; data-start=&quot;390&quot; data-ke-size=&quot;size16&quot;&gt;기존 &lt;span&gt;&lt;span&gt;OpenSearch&lt;/span&gt;&lt;/span&gt; 나 &lt;span&gt;&lt;span&gt;Apache Solr&lt;/span&gt;&lt;/span&gt; 는&lt;/p&gt;
&lt;p data-end=&quot;496&quot; data-start=&quot;476&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;ldquo;노드 = 데이터 책임&amp;rdquo; 구조다&lt;/p&gt;
&lt;p data-end=&quot;502&quot; data-start=&quot;498&quot; data-ke-size=&quot;size16&quot;&gt;그래서:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;537&quot; data-start=&quot;504&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;523&quot; data-start=&quot;504&quot; data-section-id=&quot;ydmz3z&quot;&gt;노드 늘리면 &amp;rarr; 데이터 리밸런싱&lt;/li&gt;
&lt;li data-end=&quot;537&quot; data-start=&quot;524&quot; data-section-id=&quot;mspwva&quot;&gt;노드 줄이면 &amp;rarr; 위험&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;542&quot; data-start=&quot;539&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;575&quot; data-start=&quot;544&quot; data-ke-size=&quot;size16&quot;&gt;근데 ClickHouse는 (특히 S3 기반 구조에서는)&lt;/p&gt;
&lt;p data-end=&quot;626&quot; data-start=&quot;577&quot; data-ke-size=&quot;size16&quot;&gt;- 노드가 데이터를 들고 있지 않는다&lt;br /&gt;- 필요할 때만 붙였다 떼는 구조가 가능하다&lt;/p&gt;
&lt;p data-end=&quot;632&quot; data-start=&quot;628&quot; data-ke-size=&quot;size16&quot;&gt;그래서:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;668&quot; data-start=&quot;634&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;652&quot; data-start=&quot;634&quot; data-section-id=&quot;15vy38v&quot;&gt;트래픽 많을 때만 노드 늘리고&lt;/li&gt;
&lt;li data-end=&quot;668&quot; data-start=&quot;653&quot; data-section-id=&quot;2otijf&quot;&gt;평소엔 줄여도 문제 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;691&quot; data-start=&quot;670&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비용 효율이 확실히 다르다&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;744&quot; data-start=&quot;693&quot; data-ke-size=&quot;size16&quot;&gt;※ 정확히 말하면 &amp;ldquo;완전한 stateless는 아니지만&amp;rdquo;&lt;br /&gt;실무에서는 거의 그렇게 느껴진다&lt;/p&gt;
&lt;hr data-end=&quot;749&quot; data-start=&quot;746&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;771&quot; data-start=&quot;751&quot; data-section-id=&quot;1j01jt1&quot; data-ke-size=&quot;size23&quot;&gt;2. 데이터 ingest 속도&lt;/h3&gt;
&lt;p data-end=&quot;786&quot; data-start=&quot;773&quot; data-ke-size=&quot;size16&quot;&gt;이건 진짜 써보면 놀란다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;830&quot; data-start=&quot;788&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;801&quot; data-start=&quot;788&quot; data-section-id=&quot;89qeh2&quot;&gt;로그 밀어 넣는 속도&lt;/li&gt;
&lt;li data-end=&quot;816&quot; data-start=&quot;802&quot; data-section-id=&quot;sqw23n&quot;&gt;batch insert&lt;/li&gt;
&lt;li data-end=&quot;830&quot; data-start=&quot;817&quot; data-section-id=&quot;144ixh3&quot;&gt;스트리밍 ingest&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;840&quot; data-start=&quot;832&quot; data-ke-size=&quot;size16&quot;&gt;다 빠르다&lt;/p&gt;
&lt;p data-end=&quot;884&quot; data-start=&quot;842&quot; data-ke-size=&quot;size16&quot;&gt;Kafka 붙여서 써보면&lt;br /&gt;&amp;ldquo;이게 DB 맞나?&amp;rdquo; 싶을 정도로 잘 받아먹는다&lt;/p&gt;
&lt;hr data-end=&quot;889&quot; data-start=&quot;886&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;916&quot; data-start=&quot;891&quot; data-section-id=&quot;uwjedu&quot; data-ke-size=&quot;size23&quot;&gt;3. 컬럼 기반 = 초대용량 쿼리 성능&lt;/h3&gt;
&lt;p data-end=&quot;930&quot; data-start=&quot;918&quot; data-ke-size=&quot;size16&quot;&gt;이건 설명보다 체감이다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;969&quot; data-start=&quot;932&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;944&quot; data-start=&quot;932&quot; data-section-id=&quot;iau00u&quot;&gt;수억 / 수십억 건&lt;/li&gt;
&lt;li data-end=&quot;955&quot; data-start=&quot;945&quot; data-section-id=&quot;apykdo&quot;&gt;group by&lt;/li&gt;
&lt;li data-end=&quot;969&quot; data-start=&quot;956&quot; data-section-id=&quot;12dl6ck&quot;&gt;aggregation&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;980&quot; data-start=&quot;971&quot; data-ke-size=&quot;size16&quot;&gt;그냥 빠르다 (그렇다고 수십억건의 Range 쿼리를 0.0... 초내를 기대하진 말자...)&lt;/p&gt;
&lt;p data-end=&quot;1015&quot; data-start=&quot;982&quot; data-ke-size=&quot;size16&quot;&gt;기존 RDB에서 튜닝하던 감각으로 보면&lt;br /&gt;거의 다른 세계다&lt;/p&gt;
&lt;hr data-end=&quot;1020&quot; data-start=&quot;1017&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1045&quot; data-start=&quot;1022&quot; data-section-id=&quot;1wt7348&quot; data-ke-size=&quot;size23&quot;&gt;4. 엔진 구조 하나로 대부분 커버&lt;/h3&gt;
&lt;p data-end=&quot;1089&quot; data-start=&quot;1047&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse는 단순 DB가 아니라&lt;br /&gt;&amp;ldquo;엔진 선택형 시스템&amp;rdquo;에 가깝다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1162&quot; data-start=&quot;1091&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1107&quot; data-start=&quot;1091&quot; data-section-id=&quot;17g1wa4&quot;&gt;MergeTree &amp;rarr; 기본&lt;/li&gt;
&lt;li data-end=&quot;1143&quot; data-start=&quot;1108&quot; data-section-id=&quot;3ur06b&quot;&gt;Replacing / Aggregating / Summing&lt;/li&gt;
&lt;li data-end=&quot;1153&quot; data-start=&quot;1144&quot; data-section-id=&quot;1ea62i1&quot;&gt;로그성 데이터&lt;/li&gt;
&lt;li data-end=&quot;1162&quot; data-start=&quot;1154&quot; data-section-id=&quot;1ci1g5t&quot;&gt;시계열 집계&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1173&quot; data-start=&quot;1164&quot; data-ke-size=&quot;size16&quot;&gt;이거 하나로&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1207&quot; data-start=&quot;1175&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1182&quot; data-start=&quot;1175&quot; data-section-id=&quot;4ropbp&quot;&gt;로그 분석&lt;/li&gt;
&lt;li data-end=&quot;1191&quot; data-start=&quot;1183&quot; data-section-id=&quot;dwctx9&quot;&gt;통계 시스템&lt;/li&gt;
&lt;li data-end=&quot;1207&quot; data-start=&quot;1192&quot; data-section-id=&quot;15kv2nw&quot;&gt;간단한 데이터 웨어하우스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1220&quot; data-start=&quot;1209&quot; data-ke-size=&quot;size16&quot;&gt;대부분 커버 가능하다&lt;/p&gt;
&lt;p data-end=&quot;1220&quot; data-start=&quot;1209&quot; data-ke-size=&quot;size16&quot;&gt;매뉴얼이 잘되있어 필요한 비즈니스별 엔진 선택을 하면 된다.&lt;/p&gt;
&lt;p data-end=&quot;1220&quot; data-start=&quot;1209&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;1225&quot; data-start=&quot;1222&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1260&quot; data-start=&quot;1227&quot; data-section-id=&quot;dvw5bt&quot; data-ke-size=&quot;size23&quot;&gt;5. Materialized View = 진짜 사기급&lt;/h3&gt;
&lt;p data-end=&quot;1269&quot; data-start=&quot;1262&quot; data-ke-size=&quot;size16&quot;&gt;이건 핵심이다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1329&quot; data-start=&quot;1271&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1290&quot; data-start=&quot;1271&quot; data-section-id=&quot;tcdg64&quot;&gt;Materialized View&lt;/li&gt;
&lt;li data-end=&quot;1317&quot; data-start=&quot;1291&quot; data-section-id=&quot;nid7gm&quot;&gt;Refreshable View (최근 기능)&lt;/li&gt;
&lt;li data-end=&quot;1329&quot; data-start=&quot;1318&quot; data-section-id=&quot;1uryko8&quot;&gt;다양한 집계 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1334&quot; data-start=&quot;1331&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1340&quot; data-start=&quot;1336&quot; data-ke-size=&quot;size16&quot;&gt;실제로:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1374&quot; data-start=&quot;1342&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1358&quot; data-start=&quot;1342&quot; data-section-id=&quot;1lwc4e2&quot;&gt;수백만 ~ 수천만 건 집계&lt;/li&gt;
&lt;li data-end=&quot;1374&quot; data-start=&quot;1359&quot; data-section-id=&quot;d6o8zn&quot;&gt;지속적으로 돌아가는 MV&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1399&quot; data-start=&quot;1376&quot; data-ke-size=&quot;size16&quot;&gt;CPU / Memory 크게 안 튄다&lt;/p&gt;
&lt;p data-end=&quot;1441&quot; data-start=&quot;1401&quot; data-ke-size=&quot;size16&quot;&gt;이게 왜 가능하냐면&lt;br /&gt;&lt;b&gt;insert 시점에 미리 계산해버리기 때문이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무슨 말이냐면... 예를들어 1,000 건의 Row 가 새로 저장되면, 그 데이터를 기준으로 MV 가 수행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-end=&quot;1446&quot; data-start=&quot;1443&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1462&quot; data-start=&quot;1448&quot; data-ke-size=&quot;size16&quot;&gt;단, 하나 짚고 가야 한다&lt;/p&gt;
&lt;p data-end=&quot;1484&quot; data-start=&quot;1464&quot; data-ke-size=&quot;size16&quot;&gt;조회 쿼리는 결국 리소스를 쓴다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1505&quot; data-start=&quot;1486&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1494&quot; data-start=&quot;1486&quot; data-section-id=&quot;1lrevzk&quot;&gt;복잡한 쿼리&lt;/li&gt;
&lt;li data-end=&quot;1505&quot; data-start=&quot;1495&quot; data-section-id=&quot;1x6802f&quot;&gt;대용량 scan&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1526&quot; data-start=&quot;1507&quot; data-ke-size=&quot;size16&quot;&gt;이건 사양 따라 그대로 비용 나간다&lt;/p&gt;
&lt;hr data-end=&quot;1531&quot; data-start=&quot;1528&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-end=&quot;1564&quot; data-start=&quot;1533&quot; data-section-id=&quot;1y0kr8r&quot; data-ke-size=&quot;size23&quot;&gt;6. Full Text Search (최근 추가)&lt;/h3&gt;
&lt;p data-end=&quot;1611&quot; data-start=&quot;1566&quot; data-ke-size=&quot;size16&quot;&gt;최근 버전에서&lt;br /&gt;Tokenizer 기반 Full Text Search가 들어왔다&lt;/p&gt;
&lt;p data-end=&quot;1646&quot; data-start=&quot;1613&quot; data-ke-size=&quot;size16&quot;&gt;아직 SaaS에서는 버전업이 안되었다.&lt;/p&gt;
&lt;hr data-end=&quot;1651&quot; data-start=&quot;1648&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1665&quot; data-start=&quot;1653&quot; data-ke-size=&quot;size16&quot;&gt;이게 의미하는 건 크다&lt;/p&gt;
&lt;p data-end=&quot;1673&quot; data-start=&quot;1667&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이제는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1695&quot; data-start=&quot;1675&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1682&quot; data-start=&quot;1675&quot; data-section-id=&quot;4rmbmt&quot;&gt;로그 검색&lt;/li&gt;
&lt;li data-end=&quot;1695&quot; data-start=&quot;1683&quot; data-section-id=&quot;af1i7p&quot;&gt;간단한 검색 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1722&quot; data-start=&quot;1697&quot; data-ke-size=&quot;size16&quot;&gt;정도는 굳이 외부 검색엔진 안 써도 될 가능성&lt;/p&gt;
&lt;hr data-end=&quot;1727&quot; data-start=&quot;1724&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1736&quot; data-start=&quot;1729&quot; data-ke-size=&quot;size16&quot;&gt;물론 아직은 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;전문 검색엔진 완전 대체하지 못한다. Inverted Index 만 지원할 뿐이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1736&quot; data-start=&quot;1729&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Phase Index ( 주어진 문자열의 순서까지 지켜가며 검색 ) 등은 아직 지원되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;hr data-end=&quot;1776&quot; data-start=&quot;1773&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1791&quot; data-start=&quot;1778&quot; data-ke-size=&quot;size16&quot;&gt;그래도 방향성은 명확하다&lt;/p&gt;
&lt;p data-end=&quot;1821&quot; data-start=&quot;1793&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;ldquo;ClickHouse 하나로 끝내려는 움직임&amp;rdquo;&lt;/p&gt;
&lt;hr data-end=&quot;1826&quot; data-start=&quot;1823&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1833&quot; data-start=&quot;1828&quot; data-section-id=&quot;1m6gdx&quot; data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-end=&quot;1846&quot; data-start=&quot;1835&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1880&quot; data-start=&quot;1848&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1862&quot; data-start=&quot;1848&quot; data-section-id=&quot;1qj9nup&quot;&gt;완벽한 시스템은 아니다&lt;/li&gt;
&lt;li data-end=&quot;1880&quot; data-start=&quot;1863&quot; data-section-id=&quot;1gt35qx&quot;&gt;운영도 쉽다고 말하긴 어렵다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1885&quot; data-start=&quot;1882&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;1889&quot; data-start=&quot;1887&quot; data-ke-size=&quot;size16&quot;&gt;근데&lt;/p&gt;
&lt;p data-end=&quot;1908&quot; data-start=&quot;1891&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;성능 + 유연성 + 확장성&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1910&quot; data-ke-size=&quot;size16&quot;&gt;이 3개를 같이 가져가는 순간&lt;br /&gt;다른 선택지가 잘 안 보인다.&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1910&quot; data-ke-size=&quot;size16&quot;&gt;최근에 Linkedin 댓글에서 QuickWit 엔진에 대한 찬양글을 봐서 관심이 깊었으나.. 일단 먼저 친해진&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1910&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse 랑 좀 더 놀면서 바람을 좀 피워봐야 겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1944&quot; data-start=&quot;1910&quot; data-ke-size=&quot;size16&quot;&gt;QuickWit 찬양글의 핵심중에 하나는 Full Text Search 를 지원한다 였는데, 이제 뭐 Clickhouse 도 지원하니까..&lt;/p&gt;</description>
      <category>ClickHouse</category>
      <category>ClickHouse</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/79</guid>
      <comments>https://shesbe.tistory.com/entry/ClickHouse-%EC%9E%A5%EC%A0%90#entry79comment</comments>
      <pubDate>Thu, 9 Apr 2026 20:55:24 +0900</pubDate>
    </item>
    <item>
      <title>모듈러 모노리스(Modular Monolith) 아키텍처와 도메인 간의 통신, 그리고 헥사고날 아키텍처</title>
      <link>https://shesbe.tistory.com/entry/%EB%AA%A8%EB%86%80%EB%A6%AC%EC%8B%9D-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EA%B0%84%EC%9D%98-%ED%86%B5%EC%8B%A0-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%ED%97%A5%EC%82%AC%EA%B3%A0%EB%82%A0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모듈러 모노리스에서 도메인 간 통신을 어떻게 할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모놀리식은 처음엔 정말 편하다.&lt;br /&gt;빠르게 만들 수 있고, 한 번에 다 돌아간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 규모가 점점커지면 도메인간 의존성이 얽히기 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이문제를 해결하고 나온 마이크로 서비스 아키텍처.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2010년 후반부터 광풍이 일기 시작했고, 대표적으로&amp;nbsp; Netflix 가 자신들의 아키텍처를 공개하면서 많은 기업들이 따라하기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Netflix OSS 기반 MSA 는 구조적으로는 아름다웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 간 경계를 세부적으로 쪼개고, 도메인간 통신은 Client Side Loadbalancing 을 통해 제어했다.&amp;nbsp; (꼭 Netflix OSS 기반, Client Side LB 가&amp;nbsp; 아니라도 대게 마찬가지다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 동적 노드 추가로 언제든 트래픽이 몰리는 도메인을 쉽게 증설할수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 철학으로 따라가다 보면, 서비스를 운영하기 위해 너무나 많은 도메인, 노드를 운영해야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트래픽이 거의 없는 도메인 및 노드도 최소한의 자원은 할당해야 했으며, 당연히 git 으로 관리해야할 프로젝트도 그만큼 늘어났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아름다웠지만, 너무 비싼 녀석이었다... Netflix 만큼 모든 도메인이 많은 트래픽이 많지도 않았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 나의 경우에는 서비스 규모에 비해 복잡한 비즈니스를 구현했어야 하는데, 그러다 보니 100개가 넘는 도메인을 각각 개발하고 관리해야 했다. 글로벌 기업수준도 아닌데 이건...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제점을 보완하기 위해 최근 각광받는 Mono Repo, 그리고 Modular Monolith,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 모듈러 모노리스에 대한 이야기를 해보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(참고로 나는 Mono Repo 스타일은 별로 좋아하지 않는다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인이 늘어나기 시작하면&lt;br /&gt;자연스럽게 이런 코드가 생긴다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Order가 Payment를 직접 호출하고&lt;/li&gt;
&lt;li&gt;Payment가 다시 Inventory를 건드리고&lt;/li&gt;
&lt;li&gt;어느 순간 서로가 서로를 참조한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 단순한 &amp;ldquo;함수 호출&amp;rdquo;이었는데,&lt;br /&gt;나중엔 &lt;b&gt;얽히고설킨 의존성 덩어리&lt;/b&gt;가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 시점에서 대부분 이렇게 생각한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;헥사고날 아키텍처 쓰면 해결되는 거 아니야?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;헥사고날 아키텍처로 도메인을 서로 외부 경계로 바라본다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Port / Adapter 구조를 도입하면&lt;br /&gt;도메인 간 통신을 마치 외부 시스템처럼 다룰 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Order &amp;rarr; PaymentPort (인터페이스)&lt;/li&gt;
&lt;li&gt;PaymentAdapter &amp;rarr; 실제 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 나중에&lt;br /&gt;HTTP, gRPC, 메시지 기반으로 바꾸기도 쉬워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱 봐도 &amp;ldquo;MSA 전환 준비 완료&amp;rdquo; 느낌이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 여기서 함정이 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제는 기술이 아니라 구조다&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Port/Adapter를 쓰면 미래 대비가 된다고 생각한다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 좀더 중요한 요소가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;미래에 시스템을 쪼갤 수 있느냐는&lt;br /&gt;Port가 아니라 &amp;ldquo;도메인 구조&amp;rdquo;가 결정한다.&lt;/b&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;진짜 중요한 4가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 의존 방향은 무조건 단방향&lt;/h3&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;Order &amp;rarr; Payment (O)
Payment &amp;rarr; Order (X)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환 의존이 생기는 순간&lt;br /&gt;그 도메인은 절대 분리할 수 없다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 상태 공유하지 않기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 DB 테이블을 같이 쓰거나&lt;/li&gt;
&lt;li&gt;서로 join해서 데이터 가져오기 시작하면&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 한 몸이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 분리? 거의 불가능하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 느슨한 결합은 이벤트로&lt;/h3&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;OrderCreated &amp;rarr; Payment 처리
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 기반으로 바꾸는 순간&lt;br /&gt;도메인 간 결합도가 확 낮아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 진짜 분리될 도메인만 Port/Adapter&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 걸 Port로 감싸는 건 오버엔지니어링이다. 게다가 CRQS 개념 분리까지 생각하면 Port, Adapter 천국이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 이렇게 생각하자.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;이 도메인은 나중에 진짜 따로 나갈 가능성이 높은가?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결제&lt;/li&gt;
&lt;li&gt;인증&lt;/li&gt;
&lt;li&gt;알림&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 영역만 Port/Adapter로 감싸면 된다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래서 결론은&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈러 모놀리스에서 중요한 건&lt;br /&gt;&amp;ldquo;지금부터 분산 시스템처럼 만드는 것&amp;rdquo;이 아니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나중에 분리할 수 있는 구조를 만드는 것&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 딱 이거다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인 간 통신은 단순하게 Service 호출&lt;/li&gt;
&lt;li&gt;느슨한 결합은 이벤트로 해결&lt;/li&gt;
&lt;li&gt;의존성은 단방향 유지&lt;/li&gt;
&lt;li&gt;상태는 절대 공유하지 않기&lt;/li&gt;
&lt;li&gt;정말 필요한 곳만 Port/Adapter 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한 줄 정리&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;미래를 대비한다는 건 기술을 추가하는 게 아니라,&lt;br /&gt;구조를 망치지 않는 것이다&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모놀리식 아키텍처, 모듈러 모노리스, 헥사고날 아키텍처, Port Adapter, 도메인 설계, MSA 전환, 이벤트 기반 아키텍처&lt;/p&gt;</description>
      <category>Spring</category>
      <category>DDD</category>
      <category>hexagonal architecture</category>
      <category>Modular Monolith</category>
      <category>Monolithic Architecture</category>
      <category>MSA 전환</category>
      <category>Port Adapter</category>
      <category>Spring MSA</category>
      <category>도메인 설계</category>
      <category>모놀리식 아키텍처</category>
      <category>헥사고날 아키텍처</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/78</guid>
      <comments>https://shesbe.tistory.com/entry/%EB%AA%A8%EB%86%80%EB%A6%AC%EC%8B%9D-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%8F%84%EB%A9%94%EC%9D%B8-%EA%B0%84%EC%9D%98-%ED%86%B5%EC%8B%A0-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%ED%97%A5%EC%82%AC%EA%B3%A0%EB%82%A0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98#entry78comment</comments>
      <pubDate>Thu, 9 Apr 2026 17:34:35 +0900</pubDate>
    </item>
    <item>
      <title>AI 시대 경제 시스템 구상</title>
      <link>https://shesbe.tistory.com/entry/AI-%EC%8B%9C%EB%8C%80-%EA%B2%BD%EC%A0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%83%81</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;0. 목표&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다가오는 시대는 AI와 자동화로 인해 인간 노동의 가치가 급격히 낮아질 가능성이 크다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;이 변화 속에서 다음과 같은 문제를 해결해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;노동 가치 하락 시대에서 시민을 보호할 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;AI 기술을 가진 특정 기업의 권력 독점을 방지할 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;국가가 경제 발전의 동기를 잃지 않도록 할 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우주를 단순한 탐사가 아닌, 명확한 산업적 목표로 재정의할 것&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;1. 개요&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 시스템은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;정부, 기업, 시민, 그리고 자원(전력/우주)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이 연결된 구조를 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;정부&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 및 자원 인프라 투자 및 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;토큰 발행 기준 설계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시장 안정화 및 규제&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;기업&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;AI / 로봇 / 기술 제공자&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;토큰을 대가로 생산 활동 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산 결과물을 요청자에게 제공&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;시민&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;생산 요청&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;전력 절약 및 공유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;참여 기반 활동&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;토큰&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;생산 요청권 + 참여 보상 수단&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;전력 및 물리적 자원을 기반으로 발행되는 자산&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;목적&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;생산 &amp;middot; 기술 &amp;middot; 자원 &amp;middot; 토큰이 순환하는 지속 가능한 경제 구조 구축&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;2. 토큰 발생 구조&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;2.1 지구 기반 토큰&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;정부&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;발전소, 전력망, 저장 시스템 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;전력 생산량 기준으로 토큰 발행 정책 설정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시민&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 절약 및 잉여 전력 공유 &amp;rarr; 토큰 획득&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기술을 통해 전력 효율 향상 &amp;rarr; 토큰 보상&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;2.2 우주 자원 기반 토큰&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;정부 / 국제기구&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;초기 탐사 투자&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;자원 소유권 및 가치 기준 정의&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;우주 탐사 및 자원 채굴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;확보한 자원을 기반으로 토큰 발행&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  즉, 우주 탐사는&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;ldquo;위상 경쟁&amp;rdquo;이 아니라&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span&gt;명확한 경제 활동 (자원 확보 산업)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;3. 핵심 구조: 생산의 흐름&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 시스템에서 가장 중요한 것은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;기업의 역할 정의&lt;/span&gt;&lt;/b&gt;&lt;span&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;생산 흐름&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;시민 / 정부 / 기업이 생산을 요청한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;요청자는 토큰을 지불한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업은 기술(AI, 로봇)을 제공하여 생산을 수행한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;정부로부터 전력을 공급받아 생산 활동을 진행한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산된 결과물은 요청자에게 귀속된다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업은 기술 제공의 대가로 토큰을 획득한다&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;핵심 포인트&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기업은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;생산물을 소유하지 않는다&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;기술 제공자이자 실행자&lt;/span&gt;&lt;/b&gt;&lt;span&gt;다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산 결과는 항상 &lt;/span&gt;&lt;b&gt;&lt;span&gt;요청자(시민/정부/기업)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;에게 돌아간다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  즉,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;ldquo;기업 = 소유자가 아니라 생산을 수행하는 기술 주체&amp;rdquo;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;4. 상호작용 구조&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;정부&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;인프라 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;규칙 설계&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시장 안정화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;기업&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기술 개발&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;효율 경쟁&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;시민&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 절약 및 공유&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;토큰 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산 수요 창출&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;자원&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 및 우주 자원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;토큰 가치의 근본 기반&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;5. 경쟁 및 발전 메커니즘&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;5.1 기업 경쟁&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;더 효율적인 기술 개발 &amp;rarr; 더 많은 토큰 확보&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;글로벌 진출 &amp;rarr; 다양한 자원 접근&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;생산 효율을 높이기 위한 지속적 기술 혁신&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;5.2 시민 경쟁&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 절약 및 공유 참여&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;커뮤니티 기반 협력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;토큰 확보를 통한 생산 요청 능력 강화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;5.3 국가 경쟁&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 생산 능력&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;에너지 효율&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우주 자원 확보 능력&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  국가의 인프라 수준이 곧 경제력&lt;/span&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;5.4 글로벌 구조&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기업 간 경쟁은 유지되지만&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;자원과 토큰은 정부와 시민 기반&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;  기업 단독 독점 불가능&lt;/span&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;6. 정부의 핵심 역할&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;6.1 인프라 투자자&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;전력 생산 및 저장 시스템 구축&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우주 탐사 기반 시설 투자&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;6.2 규칙 설계자&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;토큰 발행 기준 정의&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기업 참여 조건 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시민 보상 구조 설계&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;6.3 시장 안정 장치&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;토큰 가치 급변 시 개입&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;전력 수급 조절&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시스템 붕괴 방지&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;7. 장점&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기업 권력 독점 구조 방지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시민 참여 기반 경제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;국가 경제 주권 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;기술 발전 동기 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;환경 절약과 경제적 보상 연결&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우주 탐사의 명확한 산업화&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;8. 고려사항&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;토큰 발행과 자원 간 균형 유지&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;정부 개입과 시장 자율성의 균형&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;국가 간 자원 격차 문제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;우주 자원에 대한 국제 규범 필요&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시스템 투명성 확보&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 구조는 기존 자본주의를 부정하는 것이 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오히려&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span&gt;자본주의를 &amp;ldquo;자원 기반&amp;rdquo;으로 재구성하는 시도&lt;/span&gt;&lt;/b&gt;&lt;span&gt;다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기업은 소유가 아니라 기술로 경쟁하고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;시민은 참여를 통해 권한을 얻으며&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;정부는 시스템을 설계하고 안정화한다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우주는 더 이상 막연한 미래가 아니라&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span&gt;명확한 경제 활동의 영역&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div contenteditable=&quot;false&quot;&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이것은 아직 완성된 답이 아니라,&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span&gt;하나의 방향성이다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 분명한 것은,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;AI 시대에는 기존 경제 구조만으로는&lt;/span&gt;&lt;br /&gt;&lt;span&gt;지속 가능하지 않다는 점이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>없음</category>
      <category>AI</category>
      <category>llm</category>
      <category>디스토피아</category>
      <category>미래</category>
      <category>미래 경제</category>
      <category>산업</category>
      <category>우주</category>
      <category>유토피아</category>
      <category>자원</category>
      <category>토큰</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/77</guid>
      <comments>https://shesbe.tistory.com/entry/AI-%EC%8B%9C%EB%8C%80-%EA%B2%BD%EC%A0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%83%81#entry77comment</comments>
      <pubDate>Tue, 7 Apr 2026 17:07:53 +0900</pubDate>
    </item>
    <item>
      <title>ClickHouse 로 시계열 통계 구축</title>
      <link>https://shesbe.tistory.com/entry/ClickHouse-%EB%A1%9C-%EC%8B%9C%EA%B3%84%EC%97%B4-%ED%86%B5%EA%B3%84-%EA%B5%AC%EC%B6%95</link>
      <description>&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h1&gt;ClickHouse로 대규모 시계열 집계 파이프라인 설계하기&lt;/h1&gt;
&lt;a id=&quot;user-content-clickhouse로-대규모-시계열-집계-파이프라인-설계하기&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#clickhouse%EB%A1%9C-%EB%8C%80%EA%B7%9C%EB%AA%A8-%EC%8B%9C%EA%B3%84%EC%97%B4-%EC%A7%91%EA%B3%84-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EC%84%A4%EA%B3%84%ED%95%98%EA%B8%B0&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #59636e; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실시간 통계 API를 위한 멀티 테넌트 분석 아키텍처&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 ClickHouse인가&lt;/h2&gt;
&lt;a id=&quot;user-content-왜-clickhouse인가&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EC%99%9C-clickhouse%EC%9D%B8%EA%B0%80&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;MySQL 같은 RDB는 트랜잭션 처리에 최적화되어 있다. 행 단위로 데이터를 읽고 쓰는 구조이기 때문에, 수천만 건의 로그를 집계하는 분석 쿼리에는 태생적으로 불리하다. 테넌트 수가 늘고 데이터 규모가 커질수록 이 한계는 선명하게 드러난다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse는 열 지향(columnar) 스토리지를 기반으로 하며, 집계 연산에 특화된 엔진들을 제공한다. 같은 쿼리를 RDB 대비 수십 배 빠르게 처리하는 것이 가능하다. 분석용 파이프라인의 핵심 저장소로 적합한 이유다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;전체 파이프라인 구조&lt;/h2&gt;
&lt;a id=&quot;user-content-전체-파이프라인-구조&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EC%A0%84%EC%B2%B4-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EA%B5%AC%EC%A1%B0&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;excel&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;Raw Ingest
    &amp;darr;
Materialized Views (실시간 변환)
    &amp;darr;
MINUTE 집계 테이블
    &amp;darr;
HOUR / DAY / MONTH 집계 테이블 (계층적 롤업)
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;핵심은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;한 번 적재, 다단계 집계&quot;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다. 원본 데이터를 그대로 쌓아두는 것이 아니라, Materialized View가 ingest 시점에 바로 변환하여 각 시간 단위 집계 테이블로 흘려보낸다. 쿼리 시점의 부하를 적재 시점으로 분산시키는 구조다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테이블 엔진 선택&lt;/h2&gt;
&lt;a id=&quot;user-content-테이블-엔진-선택&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%97%94%EC%A7%84-%EC%84%A0%ED%83%9D&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SummingMergeTree &amp;mdash; 일반 집계용&lt;/h3&gt;
&lt;a id=&quot;user-content-summingmergetree--일반-집계용&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#summingmergetree--%EC%9D%BC%EB%B0%98-%EC%A7%91%EA%B3%84%EC%9A%A9&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SummingMergeTree는 동일한 Primary Key를 가진 row를 백그라운드에서 자동으로 합산한다. INSERT가 발생하면 일단 별도 파트로 저장되고, 이후 백그라운드 프로세스가 같은 Key의 파트들을 병합하며 값을 누적한다. 카운트, 합계 같은 단순 집계 지표를 저장하는 테이블에 적합하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;멀티 테넌트 환경에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;SharedSummingMergeTree를 사용한다. ClickHouse Cloud나 Shared 클러스터 구성에서 여러 노드가 스토리지를 공유하는 방식이다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ReplacingMergeTree &amp;mdash; Top-N 랭킹용&lt;/h3&gt;
&lt;a id=&quot;user-content-replacingmergetree--top-n-랭킹용&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#replacingmergetree--top-n-%EB%9E%AD%ED%82%B9%EC%9A%A9&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ReplacingMergeTree는 같은 Key에 대해 가장 최근 row만 남긴다. &quot;최신 값으로 교체&quot;가 필요한 순위 데이터에 적합하다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Top-N 테이블은&lt;span&gt;&amp;nbsp;&lt;/span&gt;SharedReplacingMergeTree와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Refreshable Materialized View&lt;/b&gt;를 조합해 구성한다. Refreshable MV가 주기적으로 집계 결과를 다시 계산하고, 결과를 Top-N 테이블에 덮어쓰는 방식이다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORDER BY 설계&lt;/h2&gt;
&lt;a id=&quot;user-content-order-by-설계&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#order-by-%EC%84%A4%EA%B3%84&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;crmsh&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;ORDER BY (tenantId, code, timestamp, statValue)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;시계열 데이터라고 해서 무조건 시간을 앞에 두는 것이 최선은 아니다. ClickHouse의 Primary Key는 ORDER BY와 동일하게 구성되며, 앞에 배치된 컬럼일수록 범위 스캔이 효율적으로 동작한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;실제 쿼리 패턴을 보면 &quot;어떤 지표를&quot; &amp;rarr; &quot;어느 기간에&quot; 순으로 조건이 걸리는 경우가 압도적이다. 지표 코드(code)를 시간(timestamp)보다 앞에 두는 이유다. 시간 필터는&lt;span&gt;&amp;nbsp;&lt;/span&gt;PARTITION BY를 통한 파티션 프루닝으로 처리하면 충분하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SummingMergeTree의 단편화 문제&lt;/h2&gt;
&lt;a id=&quot;user-content-summingmergetree의-단편화-문제&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#summingmergetree%EC%9D%98-%EB%8B%A8%ED%8E%B8%ED%99%94-%EB%AC%B8%EC%A0%9C&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;SummingMergeTree를 실제로 운용하면 반드시 마주치는 문제가 있다. 백그라운드 merge가 완료되기 전까지는 같은 Key의 row가 여러 파트에 분산되어 존재한다. 즉, 쿼리 시점에 아직 합산되지 않은 중간 상태 데이터가 함께 읽힐 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FINAL 키워드는 왜 쓰면 안 되나&lt;/h3&gt;
&lt;a id=&quot;user-content-final-키워드는-왜-쓰면-안-되나&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#final-%ED%82%A4%EC%9B%8C%EB%93%9C%EB%8A%94-%EC%99%9C-%EC%93%B0%EB%A9%B4-%EC%95%88-%EB%90%98%EB%82%98&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;oxygene&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;SELECT * FROM stats_table FINAL WHERE ...&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;FINAL은 쿼리 시점에 강제로 merge를 수행해 정확한 값을 반환한다. 언뜻 깔끔한 해결책처럼 보이지만, 내부적으로 전체 데이터를 재정렬하고 병합하는 작업이 발생한다. 대용량 테이블에서는 쿼리 하나가 시스템 전체에 부하를 줄 수 있다. 특히 여러 테넌트가 동시에 쿼리를 날리는 멀티 테넌트 환경에서는 사용하기 어렵다.&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;View + GROUP BY로 해결&lt;/h3&gt;
&lt;a id=&quot;user-content-view--group-by로-해결&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#view--group-by%EB%A1%9C-%ED%95%B4%EA%B2%B0&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;sql&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;CREATE VIEW v_stats AS
SELECT
    tenantId,
    code,
    timestamp,
    sum(value) AS value
FROM stats_table
GROUP BY tenantId, code, timestamp;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;쿼리 소비자가 항상 View를 통해 조회하도록 하면, View의 GROUP BY가 단편화된 데이터를 투명하게 합산해준다. FINAL보다 훨씬 빠르고, 테이블 구현 세부사항을 API 레이어로부터 완전히 분리할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 시간 단위별로 테이블을 분리하는가&lt;/h2&gt;
&lt;a id=&quot;user-content-왜-시간-단위별로-테이블을-분리하는가&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EC%99%9C-%EC%8B%9C%EA%B0%84-%EB%8B%A8%EC%9C%84%EB%B3%84%EB%A1%9C-%ED%85%8C%EC%9D%B4%EB%B8%94%EC%9D%84-%EB%B6%84%EB%A6%AC%ED%95%98%EB%8A%94%EA%B0%80&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가장 먼저 드는 의문은 &quot;그냥 하나의 테이블에 다 넣고 쿼리할 때 GROUP BY로 조절하면 안 되나?&quot; 다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;기술적으로는 가능하다. 하지만 분 단위 원본 데이터를 그대로 보관하면서 월 단위 집계 쿼리를 날리는 상황을 생각해보면 문제가 명확해진다. 하루 1억 건의 분 단위 데이터가 쌓이는 환경에서 &quot;이번 달 집계&quot;를 구하려면 수십억 건을 매번 스캔해야 한다. 멀티 테넌트 환경에서 이런 쿼리가 동시에 수십 개 날아온다면 시스템은 버티기 어렵다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테이블을 시간 단위별로 분리하는 이유는 세 가지다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스토리지 효율.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;분 단위 데이터는 빠르게 만료시키고, 시간/일/월 단위로 올라갈수록 오래 보존한다. 하나의 테이블로 관리하면 TTL 정책을 세밀하게 적용하기 어렵다. 테이블을 분리하면 각 단위별로 독립적인 보존 정책을 가질 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿼리 성능.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;월간 집계 쿼리는 월 테이블만 읽으면 된다. 분 단위 테이블에는 접근조차 하지 않는다. 테이블 자체의 크기가 작으니 스캔 비용이 줄고, 캐시 효율도 높아진다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;집계 정확성.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;분 단위 데이터로부터 시간 단위를 실시간으로 계산하면 SummingMergeTree의 단편화 문제가 중첩된다. 각 단위별로 이미 집계된 테이블을 별도로 유지하면, 상위 단위 쿼리는 항상 이미 정리된 데이터를 읽는다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결국 &quot;저장은 한 번, 집계는 미리&quot;라는 원칙이 테이블 분리로 이어진다. 적재 시점에 Materialized View가 각 집계 단위 테이블로 동시에 흘려보내기 때문에, 운영 복잡도 증가 없이 각 단위별 최적화된 테이블을 유지할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;계층적 롤업&lt;/h2&gt;
&lt;a id=&quot;user-content-계층적-롤업&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EA%B3%84%EC%B8%B5%EC%A0%81-%EB%A1%A4%EC%97%85&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;집계 단위마다 별도 테이블을 두고, 데이터 흐름은 아래와 같이 구성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 단위반영 대상&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
&lt;td&gt;MINUTE&lt;/td&gt;
&lt;td&gt;MINUTE / HOUR / DAY / MONTH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot;&gt;
&lt;td&gt;HOUR&lt;/td&gt;
&lt;td&gt;HOUR / DAY / MONTH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
&lt;td&gt;DAY&lt;/td&gt;
&lt;td&gt;DAY / MONTH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot;&gt;
&lt;td&gt;MONTH&lt;/td&gt;
&lt;td&gt;MONTH&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;분 단위 원본 데이터가 있다면 모든 집계 테이블에 반영된다. 시간 단위 데이터만 있다면 HOUR 이상에만 반영된다. 지표마다 어떤 granularity를 지원하는지는 메타데이터로 관리하며, 파이프라인은 이를 참조해 해당 테이블에만 적재한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;고카디널리티 지표: Dual-Path 설계&lt;/h2&gt;
&lt;a id=&quot;user-content-고카디널리티-지표-dual-path-설계&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EA%B3%A0%EC%B9%B4%EB%94%94%EB%84%90%EB%A6%AC%ED%8B%B0-%EC%A7%80%ED%91%9C-dual-path-%EC%84%A4%EA%B3%84&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;고유값이 많은(High-Cardinality) 지표&lt;/b&gt;는 단순 SUM으로 처리할 수 없다. 기간을 나눠 집계한 값들을 다시 합산하면 중복이 발생하기 때문이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 파이프라인을 두 갈래로 나눈다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;Raw Ingest
    ├─&amp;rarr; [단기 TTL] Raw 집계 테이블  ──&amp;rarr;  Top-N Ranking 테이블 (장기 보존)
    └─&amp;rarr; [일반] 집계 테이블
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Raw 집계 테이블은 짧은 TTL로 원본에 가까운 데이터를 유지한다. Refreshable Materialized View가 이 데이터를 주기적으로 읽어 Top-N을 계산하고, 결과를&lt;span&gt;&amp;nbsp;&lt;/span&gt;SharedReplacingMergeTree&lt;span&gt;&amp;nbsp;&lt;/span&gt;기반의 랭킹 테이블에 저장한다. 랭킹 테이블은 긴 보존 기간을 가지며, API가 직접 서빙한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TTL 이중 관리&lt;/h2&gt;
&lt;a id=&quot;user-content-ttl-이중-관리&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#ttl-%EC%9D%B4%EC%A4%91-%EA%B4%80%EB%A6%AC&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;보존 기간이 다른 데이터가 한 파이프라인 안에 공존할 때, TTL 컬럼을 목적에 따라 분리하면 유연하게 관리할 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;background-color: #f6f8fa; color: #1f2328;&quot;&gt;&lt;code&gt;ingestTtlDate Date,  -- 단기 만료 (ingest 원본 데이터 정리용)
ttlDate       Date,  -- 장기 보존 (집계 결과, 랭킹 데이터)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ingestTtlDate는 빠르게 만료시켜 스토리지를 확보하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;ttlDate는 장기 보존이 필요한 집계 결과에 적용한다. 하나의 TTL 정책으로 모든 데이터를 관리하려 하면, 어느 한쪽이 너무 짧거나 너무 길어지는 딜레마가 생긴다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메타데이터 기반 확장&lt;/h2&gt;
&lt;a id=&quot;user-content-메타데이터-기반-확장&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B8%B0%EB%B0%98-%ED%99%95%EC%9E%A5&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;새 지표를 추가할 때마다 코드를 수정하고 배포하는 구조는 운영 부담이 크다. 지표의 속성(어떤 집계 단위를 지원하는지, 어떤 테이블을 참조하는지 등)을 메타데이터로 정의하고, 파이프라인과 API가 이를 참조해 동적으로 동작하면 코드 변경 없이 지표를 추가할 수 있다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse 테이블 구조 자체는 범용적으로 유지하되, 지표의 의미와 동작 방식은 메타데이터가 결정하는 구조다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;a id=&quot;user-content-정리&quot; style=&quot;background-color: #000000; color: #0969da;&quot; href=&quot;https://github.com/MarkMoonK8/tech/blob/main/clickhouse-timeseries.md#%EC%A0%95%EB%A6%AC&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제접근&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
&lt;td&gt;RDB 집계 성능 한계&lt;/td&gt;
&lt;td&gt;ClickHouse 열 지향 스토리지로 전환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot;&gt;
&lt;td&gt;SummingMergeTree 단편화&lt;/td&gt;
&lt;td&gt;View + GROUP BY 레이어&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
&lt;td&gt;FINAL 성능 비용&lt;/td&gt;
&lt;td&gt;View로 추상화, FINAL 미사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot;&gt;
&lt;td&gt;고카디널리티 지표&lt;/td&gt;
&lt;td&gt;Dual-Path + Refreshable MV&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffffff;&quot;&gt;
&lt;td&gt;TTL 정책 충돌&lt;/td&gt;
&lt;td&gt;컬럼 분리 (ingestTtlDate / ttlDate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f6f8fa;&quot;&gt;
&lt;td&gt;지표 확장성&lt;/td&gt;
&lt;td&gt;메타데이터 기반 동적 구성&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ClickHouse는 분석 워크로드에서 강력하지만, SummingMergeTree의 단편화나 FINAL의 숨겨진 비용처럼 직접 부딪혀봐야 알 수 있는 특성들이 있다. 설계 단계에서 이 특성들을 이해하고 구조에 반영하는 것이 안정적인 파이프라인의 출발점이다.&lt;/p&gt;</description>
      <category>ClickHouse</category>
      <category>ClickHouse</category>
      <category>clickhouse mergetree</category>
      <category>metrialized view</category>
      <category>MV</category>
      <category>summingmergetree</category>
      <category>시계열</category>
      <category>통계</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/76</guid>
      <comments>https://shesbe.tistory.com/entry/ClickHouse-%EB%A1%9C-%EC%8B%9C%EA%B3%84%EC%97%B4-%ED%86%B5%EA%B3%84-%EA%B5%AC%EC%B6%95#entry76comment</comments>
      <pubDate>Thu, 12 Mar 2026 15:20:36 +0900</pubDate>
    </item>
    <item>
      <title>React CRA</title>
      <link>https://shesbe.tistory.com/entry/React-CRA</link>
      <description>&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Backend 개발자인 제가 React 를 구성해보고 싶어 열심히 공부하고 테스트해가며 배운것들을 매우 심플하게 정리합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;검색하면 서로 너무너무 다른 방식으로 예제나 코드들이 설명되고 있어 했갈리더 군요.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 너무 복잡한 바람에 그냥 매우 간단한 요점만 기재합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;세부적으로 파고듬은 전반적으로 이해한 후에 진행하는걸로 !&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;사전 설치&amp;nbsp; (맥 기준 )&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1701090488980&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install node
brew install npm
brew install yarn
brew install npx (맞나?)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;React 로 프로젝트를 구성할 때 전반적인 구성요소&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;React 를 처음부터 구성하려면 여러가지 세팅을 해야한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NPM 및 Yarn&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그냥 패키지 매니저다. Ruby 나 Python 도 NPM 을 이용해 라이브러리들을 가져온다.&lt;/li&gt;
&lt;li&gt;Spring 의 Maven 혹은 Gradle 이라고 보면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Babel
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최신 브라우저의 자바스크립트 기능 및 문법이 과거 브라우저에선 통하지 않기에, 여러분이 작성한 코드를 컴파일시 자동으로 구버전 자바스크립트 ( ES5 등 ) 으로 변환해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;WebPack
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트를 보기좋고 깔끔하게 관리하려면 디렉토리등 구조적으로 작성해야 하는데, 배포할땐 단하나의 파일로 만들어 로딩 회수도 줄이고 Javascript Minified 도 하는등의 역할을 해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ESLint
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SonaLint 를 아는가? 똑같다. 그냥 문법문제가 있는것들을 콘솔상에서 Warning 으로 알려준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TypeScript
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java&amp;nbsp; 변수에 String, integer 등의 형선을 생각하자. 개념상 똑같다. 타입을 지정해서 프로젝트를 좀더 안전하게 관리하자 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;TailWind
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React 의 HTML 객체에 스타일을 적용할때 아래와 같이 작성해야 하는데, 기존문법처럼 작성하면 인식해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1701089606704&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- 기본 
&amp;lt;div className=&quot;[{&quot;div&quot;, &quot;h2&quot;, &quot;span&quot;}]&quot;&amp;gt;&amp;lt;/div&amp;gt;
- TailWind 가 아래 문법도 지원
&amp;lt;div class=&quot;div h2 span&quot;&amp;gt;&amp;lt;/div&amp;gt;

* 좀더 HTML 작성스럽게 지원한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;React CRA&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;React CRA 는 뭐냐?&amp;nbsp; React 가 히스토리를 아는 프론트엔드 개발자들은 구성하기 쉽겠지만&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;나같이 Jquery 이후에 손 안대본 개발자나 처음부터 시작하는 사람은 라이브러리 종류도 많고 세팅법도 어려워서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;페이스북이 BolilerPlate 를 만들어 두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난 그것도 모르고 이걸로 시작했다가 웹팩 설정 어딨어. Tsconfig 어딨어 등 한참 해맸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cra 프로젝트는 이렇게 만든다.&lt;/p&gt;
&lt;pre id=&quot;code_1701090101520&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx create-react-app my-app --template typescript&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 my-app 폴더가 생기며 프로젝트가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;npx command not found 뜨는 친구들은 검색해서 설치하고 오시길&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm 이랑 이런거 정도는 설치 간단하니까 설치하고 오자 .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;CRA 는 설정파일을 내부에 숨겨서 관리하고 있다.&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;현시점에 이르러 딸랑 React 만가지고 프로젝트를 개발하기는 어렵다. 그래서 위에 열거한 것과 같은 라이브러리의 도움을&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;받아 프로젝트를 세팅하고 개발해야 하는데, 숙련자도 시간이 걸리고, 초보자는 너무 어려워 페이스북 형아들이 다 알아서 세팅해두고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;배포한 보일러플레이트 인 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; CRA 는 아래같은 패키지 및 설정들을 내포하고 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Webpack&lt;/li&gt;
&lt;li&gt;EsLint&lt;/li&gt;
&lt;li&gt;Tailwind&lt;/li&gt;
&lt;li&gt;Babel&lt;/li&gt;
&lt;li&gt;기타 등등 또 뭐있을것이다 나도 아직 다 몰라서 확인한것은 이것들이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript 는 내포 안하고 있더라. 그래서 위에 첨 만들때 typescript 로 지정한 것이다.&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;설정 꺼내기&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1701090281367&quot; class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt; yarn eject&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이러면 숨겨진 설정파일들이 튀어나온다. 다시 되돌리진 못하니까 신중히 하라는 글들 많이 봤을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 난 너무 궁금해서 해봤지만 별거 없었다. 웹팩, eslint, 뭐 이런 설정들이 튀어 나오더라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 페북 형아들이 이렇게 해둔건 &lt;b&gt;&quot; 야 범용적으로 다 설정 해놨는데 뭐여 걍써 얼마나 대단한 설정 납신다고&quot;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 인거 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 내 생각도 같다. 뜬금없이 엄청 레거시한 프로젝트랑 지금 우리가 만드는 프로젝트를 병합하는 상황이 아니라면 별로 그럴일은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 없을거 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 또 설정 override 도 지원하는거 같으니 개발자로서 당연히 찜찜한 걱정이 들겠지만 시원하게 CRA 로 시작해보길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나도 프린이라 지금 시작하고있어서 잘 모르는 부분이 많아 잘못된 정보가 있을까 걱정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이글을 보는 프린이 나와 함께 프른이가 되도록 같이 해보도록 하자.&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <category>babel</category>
      <category>CRA</category>
      <category>eslint</category>
      <category>react</category>
      <category>React 초보</category>
      <category>tailwind</category>
      <category>TypeScript</category>
      <category>webpack</category>
      <author>개발짜맠</author>
      <guid isPermaLink="true">https://shesbe.tistory.com/74</guid>
      <comments>https://shesbe.tistory.com/entry/React-CRA#entry74comment</comments>
      <pubDate>Mon, 27 Nov 2023 22:28:36 +0900</pubDate>
    </item>
  </channel>
</rss>