<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>moon_happy.log</title>
        <link>https://velog.io/</link>
        <description>DB 일기장</description>
        <lastBuildDate>Thu, 01 Aug 2024 02:19:23 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>moon_happy.log</title>
            <url>https://velog.velcdn.com/images/moon_happy/profile/adf4f140-2415-46e3-ba5a-83a219669cae/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. moon_happy.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/moon_happy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[InfoSphere Data Replication]]></title>
            <link>https://velog.io/@moon_happy/InfoSphere-Data-Replication</link>
            <guid>https://velog.io/@moon_happy/InfoSphere-Data-Replication</guid>
            <pubDate>Thu, 01 Aug 2024 02:19:23 GMT</pubDate>
            <description><![CDATA[<p>InfoSphere Data Replication은 데이터 복제 솔루션입니다.
즉, 실시간으로 데이터를 복제, 동기화, 통합 합니다.
이러한 기능을 구현은 트랜잭션 로그를 통해 데이터의 변경을 구현합니다.</p>
<p>InfoSphere Data Replication는 3가지로 나뉘게 됩니다.</p>
<ul>
<li>CDC</li>
<li>Q Replication</li>
<li>SQL Replication</li>
</ul>
<h2 id="cdc">CDC</h2>
<ul>
<li>커밋된 소스 변경사항을 실시간으로 캡처, 다양한 데이터베이스와 ETL 솔루션에 전송됩니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/7c709061-f474-4e5a-9285-ed5cbcf7dd08/image.png" alt=""></li>
</ul>
<hr>
<h2 id="q-replication">Q Replication</h2>
<ul>
<li>2개의 DB2를 대상으로 커밋된 소스 변경 사항은 MQ 큐를 통해 타겟 시스템으로 전송됩니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/4a1774e2-e7f3-454a-9d7c-25eb39e3da08/image.png" alt=""></li>
</ul>
<hr>
<h2 id="sql-replication">SQL Replication</h2>
<ul>
<li>커밋된 소스 변경 사항은 대상 시스템에 복제되기 전에 관계형 테이블에 스테이징됩니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/43053517-1ba0-4763-89b9-6a5306a87d43/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[새로운 마음으로 글을 써야겠다고 다짐하며]]></title>
            <link>https://velog.io/@moon_happy/%EC%83%88%EB%A1%9C%EC%9A%B4-%EB%A7%88%EC%9D%8C%EC%9C%BC%EB%A1%9C-%EA%B8%80%EC%9D%84-%EC%8D%A8%EC%95%BC%EA%B2%A0%EB%8B%A4%EA%B3%A0-%EB%8B%A4%EC%A7%90%ED%95%98%EB%A9%B0</link>
            <guid>https://velog.io/@moon_happy/%EC%83%88%EB%A1%9C%EC%9A%B4-%EB%A7%88%EC%9D%8C%EC%9C%BC%EB%A1%9C-%EA%B8%80%EC%9D%84-%EC%8D%A8%EC%95%BC%EA%B2%A0%EB%8B%A4%EA%B3%A0-%EB%8B%A4%EC%A7%90%ED%95%98%EB%A9%B0</guid>
            <pubDate>Wed, 29 May 2024 15:06:22 GMT</pubDate>
            <description><![CDATA[<p>저는 데이터베이스 엔지니어로 일하면서 여러 가지 흥미로운 경험을 쌓고 있습니다. 
DBA와는 조금 다른 역할이지만, 그만큼 배워야 할 것들이 많아 재미있기도 합니다.</p>
<p>여기서는 제가 지금까지 해왔던 일들과 앞으로 작성할 글들에 대한 계획을 나눠보려 합니다. 
특히, IBM DB2와 관련된 소프트웨어를 설치하고 구축하면서 겪었던 재미있는 일들을 기록할 예정입니다. 아직은 이중화와 CDC(Change Data Capture) 말고는 크게 해본 것이 없지만, 그동안의 경험을 공유해보려고 합니다.</p>
<p>먼저, DB2를 설치하고 HADR(High Availability Disaster Recovery)을 구성해서 이중화를 구현한 경험을 얘기하려 합니다. 이 과정에서 실제로 금융권에서 진행했던 IBM의 MQ와 연계해 IIDR(IBM InfoSphere Data Replication)에서 Q Replication을 사용하여 
CDC를 구축하고 HA인 TSAMP와 공유 파일시스템인 GPFS를 사용하여 데이터를 이관하는 방법도 소개할 예정입니다.</p>
<p>최근에는 MS-SQL과 PostgreSQL도 업무에 추가되어 이들 데이터베이스를 설치하고 이중화를 구성하는 작업도 진행 중입니다. 
시간이 된다면, 데이터베이스 튜닝이나 실무에서 느꼈던 점들, 실무를 하지 않았다면 알지 못했을 것들을 재미있게 풀어볼까 합니다.</p>
<p>이 블로그를 통해 데이터베이스 엔지니어로서의 여정을 재미있게 나누고, 함께 배워가는 시간을 가질 수 있으면 좋겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/3b5d2aca-c599-4529-b7b5-441c6a70d5b4/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클라우드 컴퓨팅과 IaaS, PaaS, SaaS]]></title>
            <link>https://velog.io/@moon_happy/Iaas-PaaS-SaaS</link>
            <guid>https://velog.io/@moon_happy/Iaas-PaaS-SaaS</guid>
            <pubDate>Wed, 01 Nov 2023 06:09:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/a03ecfae-e548-49ab-89b8-fa8b820db827/image.jpeg" alt=""></p>
<h2 id="클라우드-컴퓨팅클라우드-이란">클라우드 컴퓨팅(클라우드) 이란?</h2>
<p>클라우드 컴퓨팅이란 컴퓨터를 사용한 정보 처리를 자신이 보유한 PC가 아닌, 인터넷 &#39;너머&#39;에 존재하는 클라우드 사업자의 컴퓨터에서 처리하는 서비스를 뜻한다.</p>
<hr>
<h2 id="클라우드의-장점">클라우드의 장점.</h2>
<h3 id="경제성">경제성</h3>
<p>하드웨어와 소프트웨어를 소유하지 않고 사용하고자 하는 기능을, 사용하고자 하는 기간만 서비스로써 사용할 수 있다. 또한, 소프트웨어와 데이터를 클라우드에서 통합 관리함으로써 소프트웨어 업데이트 작업 및 데이터 유지보수의 효율성을 높이고 비용을 절약할 수 있다.</p>
<h3 id="유연성">유연성</h3>
<p>자체 시스템을 구축하는 것에 비해 컴퓨팅 리소스가 필요할 때, 필요한 만큼 확장하고, 필요하지 않을 때는 축소하는 등의 유연한 활용이 가능하다.</p>
<h3 id="가용성">가용성</h3>
<p>클라우드 데이터 센터 안의 일부 하드웨어에 문제가 발생하더라도 서비스를 계속해서 사용 할 수 있도록 구성되어 있다.</p>
<h3 id="빠른-구축-속도">빠른 구축 속도</h3>
<p>자체 시스템을 구축할 경우, 설계 후 하드웨어와 소프트웨어를 설치하기 까지 많은 시간이 걸린다. 반면, 클라우드가 제공하는 하드웨어와 소프트웨어를 이용하면 신속하게 시스템을 구축할 수 있다.</p>
<hr>
<h2 id="iaasinfrastructure-as-a-service">IaaS(Infrastructure as a Service)</h2>
<p>IaaS는 기본적인 컴퓨팅 구조, 즉 서버, 스토리지, 네트워크 등의 IT 인프라를 클라우드로 제공하는 서비스 모델입니다. 사용자는 필요한 만큼의 리소스를 빌려서 사용하고, 사용한 만큼만 비용을 지불합니다. </p>
<p><strong>대표적인 IaaS 제품</strong></p>
<ul>
<li>Amazon Web Services(AWS) EC2</li>
<li>Google Cloud Platform(GCP) Compute Engine</li>
<li>Microsoft Azure Virtual Machines</li>
</ul>
<hr>
<h2 id="paasplatform-as-a-service">PaaS(Platform as a Service)</h2>
<p>PaaS는 개발 플랫폼을 클라우드로 제공하는 서비스 모델입니다. 운영체제, 개발 도구, 데이터베이스 관리 시스템 등 애플리케이션을 개발하고 운영하는 데 필요한 플랫폼을 제공합니다. 사용자는 인프라에 대한 관리를 신경 쓰지 않고, 애플리케이션 개발에만 집중할 수 있습니다.</p>
<p><strong>대표적인 PaaS 제품</strong></p>
<ul>
<li>AWS Elastic Beanstalk</li>
<li>GCP App Engine</li>
<li>Microsoft Azure App Service</li>
</ul>
<hr>
<h2 id="saassoftware-as-a-service">SaaS(Software as a Service)</h2>
<p>SaaS는 소프트웨어를 클라우드로 제공하는 서비스 모델입니다. 사용자는 웹 브라우저를 통해 소프트웨어에 접근하며, 소프트웨어의 설치, 업데이트, 유지보수 등에 대한 부담 없이 서비스를 이용할 수 있습니다.</p>
<p><strong>대표적인 SaaS 제품</strong></p>
<ul>
<li>Google Workspace(Gmail, Google Docs, Google Drive 등)</li>
<li>Microsoft Office 365</li>
<li>Salesforce</li>
</ul>
<p>이러한 서비스 모델들은 클라우드 컴퓨팅의 핵심 요소이며, 각각의 서비스 모델은 사용자의 요구사항과 자원에 따라 선택하여 사용할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RDBMS와 NoSQL의 차이]]></title>
            <link>https://velog.io/@moon_happy/RDBMS%EC%99%80-NoSQL%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@moon_happy/RDBMS%EC%99%80-NoSQL%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Wed, 25 Oct 2023 06:20:54 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/b768acff-4dc2-4679-94b4-3405495cf1a2/image.jpeg" alt=""></p>
<p>무지성으로 어디서 쓰고 어떤 환경에서만 쓰는지 알았지 구체적으로 알아야할 필요성을 느꼈습니다.</p>
<blockquote>
</blockquote>
<h3 id="💡차이점">💡차이점</h3>
<p><strong>데이터 구조, 스키마, 일관성, 확장성</strong>이 서로 다릅니다.</p>
<p>RDBMS와 NoSQL모두 데이터베이스 관리 시스템이지만 서로 다른 특징과 장단점을 가지고 있습니다.
<strong>RDBMS</strong>는 데이터의 일관성을 유지하고 무결성을 지키는데 효과적이고 복잡한 쿼리를 지원하는데 장점이 있고, <strong>NoSQL</strong>은 확장성과 성능이 뛰어나며 대규모 데이터와 비정형 데이터 처리에 접합합니다.</p>
<h2 id="rdbms">RDBMS</h2>
<p>데이터베이스를 관리하고 운영하는 소프트웨어입니다. 다양한 데이터가 저정된 데이터베이스에 여러명의 사용자 혹은 응용프로그램에 동시에 접근이 가능하며 데이터를 공유할 수 있어야 합니다.</p>
<p>관계형 데이터베이스는 정해진 스키마에 맞춰서 테이블에 저장되는 점과, 데이터는 관계를 통해서 여러개의 테이블에 분산되어 저장된다는 점입니다. </p>
<h3 id="장점">장점</h3>
<ul>
<li>데이터의 중복이 없다</li>
<li>데이터 무결성을 보장한다</li>
<li>스키마가 명확하게 정의되어 있다</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>데이터 스키마를 사전에 정하면서 추후에 수정이 어려워 유연성이 떨어진다</li>
<li>관계를 가진 테이블끼리 JOIN을 통해서 복잡한 쿼리가 만들어 진다.</li>
<li>대체로 수직적 확장만 가능하다</li>
</ul>
<hr>
<h2 id="nosql">NoSQL</h2>
<p>NoSQL은 비관계형 데이터베이스로 정해진 스키마가 없어 유연한 스키마를 제공하고 관계형 데이터베이스를 제외한 나머지 유형을 말합니다. 최근 웹 어플리케이션이 보편화되고 복잡해지면서 인기가 높아지고 있습니다.</p>
<p>정해진 스키마가 없는 유연한 스키마를 지원하고, RDBMS에 있었던 테이블이나 관계를 형성하는 개념이 없습니다.</p>
<h3 id="장점-1">장점</h3>
<ul>
<li>정해진 스키마가 없어 유연하고 언제든지 저장된 데이터를 조정하고 새로운 필드를 추가할 수 있습니다.</li>
<li>어플리케이션이 필요로 하는 데이터의 형식으로 저장되기 때문에 읽어오는 속도가 빠릅니다.</li>
<li>수직 및 수평 확장이 가능해서 애플리케이션이 발생시키는 모든 읽기와 쓰기 요청 처리가 가능하다.</li>
</ul>
<h3 id="단점-1">단점</h3>
<ul>
<li>데이터의 중복을 지속적으로 확인해야한다</li>
<li>데이터가 여러 컬렉션에 중복되어 있기 때문에 수정이 필요한 경우 모든 컬렉션에서 수행해야 한다.</li>
</ul>
<hr>
<h2 id="rdbms와-nosql의-차이점">RDBMS와 NoSQL의 차이점</h2>
<h3 id="데이터-구조">데이터 구조</h3>
<p><strong>RDBMS</strong>는 정해진 스키마를 바탕으로 테이블을 구성하고 그 테이블에 맞게 데이터가 저장되며, 이러한 테이블들은 서로 관계를 형성하게 됩니다. 하지만 <strong>NoSQL</strong>은 이러한 스키마나 테이블, 관계를 형성하는 개념이 <strong>없이</strong> 데이터를 키-값 저장소, 문서 데이터베이스, 배열 데이터베이스, 그래프 데이터베이스와 같은 <strong>다양한 구조로 저장</strong>합니다.</p>
<h3 id="스키마">스키마</h3>
<p><strong>RDBMS</strong>는 데이터 스키마를 통해 데이터의 구조를 정의합니다. 데이터 스키마는 데이터의 컬럼, 데이터 유형, 제약 조건을 정의합니다. 데이터 스키마는 데이터의 무결성을 보장하는 데 도움이 됩니다. <strong>NoSQL</strong>은 데이터 스키마가 없거나 유연한 데이터 스키마를 사용합니다. 유연한 데이터 스키마는 데이터 구조를 변경하기 쉽게 합니다.</p>
<h3 id="일관성">일관성</h3>
<p><strong>RDBMS</strong>는 데이터의 일관성을 지키는데 효율이 좋습니다. ACID 트랜젝션을 통하여 데이터의 일관성을 보장합니다. 반면 <strong>NoSQL</strong>의 경우 데이터의 일관성을 지키지 않습니다. </p>
<blockquote>
</blockquote>
<p>여기서 데이터의 일관성은 데이터의 상태를 항상 최신 상태로 유지한다는 개념입니다.</p>
<h3 id="확장성">확장성</h3>
<p>RDBMS는 수직적 확장을 통해 더 강력한 서버로 업그레이드 하면서 용량을 늘리게 됩니다. 반면 NoSQL은 수평적 확장으로 여러 서버에 데이터를 분산하여 데이터베이스의 용량을 늘리게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로세스와 스레드]]></title>
            <link>https://velog.io/@moon_happy/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@moon_happy/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C</guid>
            <pubDate>Tue, 24 Oct 2023 11:45:41 GMT</pubDate>
            <description><![CDATA[<p>면접을 준비하면서 프로세스와 스레드의 차이나 의미를 물어보는 질문이 많았습니다.</p>
<h2 id="프로세스">프로세스</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/dbca6cc3-2d67-477f-af29-907f3ad84de0/image.png" alt=""></p>
<ul>
<li>실행중에 있는 프로그램</li>
<li>메모리에 올라와 <strong>실행되고 있는 프로그램의 인스턴스(독릭적인 개체)</strong></li>
<li>스케쥴링의 대상이 되는 작업(task)과 같은 의미로 쓰인다.</li>
<li>운영체제로부터 시스템 자원을 할당받은 작업의 단위</li>
<li>하드디스크에 있는 프로그램을 실행하면, 실행을 위해서 메모리를 할당이 이루어지고, 할당된 메모리공간으로 바이너리 코드가 올라가게된다. 이때부터 프로세스라 불린다.<h3 id="할당받는-시스템-자원의-예">할당받는 시스템 자원의 예</h3>
</li>
<li>CPU시간</li>
<li>운영되기 위해 필요한 주소 공간</li>
<li>Code, Data, Stack, Heap의 구조로 되어 있는 독립된 메모리 영역</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>프로세스는 각각 독립적인 메모리 영역(Code, Data, Stack, Heap)을 할당받는다.</li>
<li>프로세스 내부에는 <strong>하나 이상의 스레드</strong>를 가지고 있는데, 실제로는 스레드 단위로 스케쥴링한다.</li>
<li>각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없다.</li>
<li>한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신을 사용해야한다.</li>
</ul>
<hr>
<h2 id="스레드">스레드</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/10261e49-3d06-43ff-91df-5a57e15bfc21/image.png" alt=""></p>
<ul>
<li><strong>프로세스 내에서 실행되는 여러 흐름의 단위</strong></li>
<li>프로세스의 특정한 수행 경로</li>
<li>프로세스가 할당받은 자원을 이용하는 실행의 단위 </li>
</ul>
<h3 id="특징-1">특징</h3>
<ul>
<li>스레드는 프로세스 내에서 각각 Stack만 따로 할당받고, Code, Data, Heap은 프로세스 내에있는 스레드들과 공유한다.</li>
<li>각각의 스레드는 별도의 레지스터와 스택을 독립적으로 할당받고, Heap은 공유한다</li>
</ul>
<hr>
<h2 id="멀티-프로세스">멀티 프로세스</h2>
<p>하나의 응용프로그램에서 여러 개의 프로세스로 구성하여 각 프로세스가 하나의 작업을 처리하도록 하는것</p>
<h3 id="장점">장점</h3>
<p>여러개의 자식 프로세스중 하나가 이상이 생겨도 그 자식 프로세스만 이상이 생기고 다른 프로세스들에게 영향이 가지 않는다.</p>
<h3 id="단점">단점</h3>
<ul>
<li><p><strong>Context Switching에서의 오버해드</strong></p>
<ul>
<li><strong>Context Switching</strong> 과정에서 캐쉬 메모리 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드가 발생하게 된다.</li>
<li>프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 프로세스 사이에서 공유하는 메모리가 없어, <strong>Context Switching</strong>이 발생하면 캐쉬에 있는 모든 데이터를 초기화하고 다시 캐쉬 정보를 불러와야 한다.</li>
</ul>
</li>
<li><p><strong>프로세스 사이의 어렵고 복잡한 통신 기법(IPC)</strong>
프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없다.</p>
</li>
</ul>
<h4 id="context-switching이란">Context Switching이란</h4>
<ul>
<li>CPU에서 여러 프로세스를 돌아가면서 작업을 처리하는 과정</li>
<li>동작 프로세스가 대기를 하면서 해당 프로세스의 상태(Context)를 보관, 대기하고 있던 다음 순서의 프로세스가 동작하면서 이전에 보관했던 프로세스의 상태를 복구하는 작업</li>
</ul>
<hr>
<h2 id="멀티-스레드">멀티 스레드</h2>
<ul>
<li>하나의 응용프로그램을 여러 개의 스레드로 구성하고 각 스레드로 하여금 하나의 작업을 처리하도록 하는 것</li>
<li>윈도우, 리눅스 등에서 멀티 프로세싱을 지원하고 있지만, 멀티 스레딩을 기본으로 하고 있다.</li>
<li>웹 서버는 대표적인 멀티 스레드 응용 프로그램이다.</li>
</ul>
<h3 id="장점-1">장점</h3>
<ul>
<li><strong>시스템 자원 소모 감소(자원의 효율성 증대)</strong>
프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다.</li>
<li><strong>시스템 처리량 증가(처리 비용 감소)</strong><ul>
<li>스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어든다.</li>
<li>스레드 사이의 작업량이 작아 Context Switching이 빠르다.</li>
</ul>
</li>
<li><strong>간단한 통신 방법으로 프로그램 응답 시간 단축</strong>
스레드는 프로세스 내의 Stack영역을 제외한 모든 메모리를 공유하여 통신의 부담이 적다</li>
</ul>
<h3 id="단점-1">단점</h3>
<ul>
<li>주의 깊은 설계가 필요하다.</li>
<li>디버깅이 까다롭다.</li>
<li>단일 프로세스 시스템의 경우 효과를 보기 어렵다.</li>
<li>다른 프로세스에서 스레드를 제어할 수 없다.</li>
<li>하나의 스레드에 문제가 발생하면 전체 프로세스가 영향을 받는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OS] 1. 운영체제 소개]]></title>
            <link>https://velog.io/@moon_happy/OS-1.-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%86%8C%EA%B0%9C</link>
            <guid>https://velog.io/@moon_happy/OS-1.-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%86%8C%EA%B0%9C</guid>
            <pubDate>Tue, 24 Oct 2023 07:06:31 GMT</pubDate>
            <description><![CDATA[<h2 id="운영체제란">운영체제란</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/78715bac-5b30-485c-9c4f-446036160f83/image.png" alt=""></p>
<p>운영체제는 <strong>응용 프로그램과 하드웨어 사이에 위치</strong>하게 됩니다. 그래서 사용자가 응용 프로그램은 통해서 서비스를 요청하면 응용 프로그램은 운영체제에게 메세지를 전달하고 하드웨어를 조작해달라고 요청하게됩니다. 그렇게 된다면 운영체제는 서비스에 맞는 하드웨어(CPU, 메모리, HDD, 모니터 등)를 작동시켜 서비스를 완수하게 됩니다. </p>
<p><strong>예를 들어</strong> 사용자가 계산기 응용 프로그램을 사용하여 <strong>3+4</strong>에 대한 결과를 요청합니다. 이 요청을 받은 계산기는 프로그램내에서 수식을 계산하는 명령어를 운영체제에 전달하게 됩니다. 운영체제는 CPU와 메모리 등의 하드웨어를 조작하여 <strong>7</strong>이라는 답을 반환합니다.</p>
<p>한문장으로 정리한다면 <strong>운영체제는 하드웨어를 제어하는 소프트웨어이고 유저와 하드웨어 사이를 연결하는 역할을 하여 프로그램의 서비스를 제공하는 소프트웨어입니다.</strong></p>
<h3 id="운영체제-정의">운영체제 정의</h3>
<ul>
<li>컴퓨터 위에서 항상 실행되는 하나의 프로그램</li>
<li><strong>Kernel</strong>로도 정의</li>
<li>하드웨어를 제어하는 소프트웨어</li>
<li>유저와 하드웨어 사이의 연결자</li>
</ul>
<hr>
<h2 id="인터럽트">인터럽트</h2>
<p>인터럽트는 하드웨어가 작동중에 CPU에게 알려주는 신호입니다. 시스템 버스를 통해서 CPU에게 신호를 전송함으로서 어느 시간이던 하드웨어는 인터럽트를 발생시킬 수 있습니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/10003f2f-4776-413c-85ff-34c5a80bdc83/image.png" alt="">
만약 키보드에서 A라는 키를 누르게 되면 메모리에 A누름 명령어가 적재되고 CPU에게 알려줍니다. </p>
<hr>
<h2 id="시스템-버스">시스템 버스</h2>
<p>시스템 버스란 컴퓨터 시스템 내에서 데이터, 주소, 제어 신호를 전송하는 통신경로를 말합니다. CPU, 메모리, 입출력 장치 등의 하드웨어 구성요소간에 데이터 전송을 담당합니다. </p>
<h3 id="데이터-버스">데이터 버스</h3>
<p>CPU와 메모리 간의 데이터 전송을 위한 경로입니다. 데이터 버스를 통해서 프로그램이나 명령어에서 필요한 데이터가 메모리로부터 CPU로 이동하거나, 반대로 CPU의 결과를 메모리에 기록할 수 있습니다.</p>
<h3 id="주소-버스">주소 버스</h3>
<p>CPU가 메모리나 입출력 장치와 통신하기 위해 사용되는 경로입니다. CPU가 원하는 위치(메모리 주소 또는 입출력 장치 주소)를 지정하여 해당 위치에서 읽거나 쓸 수 있습니다.</p>
<h3 id="제어-버스">제어 버스</h3>
<p>시간과 동기화 관련 신호들을 포함하여 컴퓨터 시스템 내에서 다양한 제어 신호를 전달하는 역할을 합니다.
예를 들면 클럭 신호, 인터럽트 신호, 읽기/쓰기 신호 등이 있습니다. </p>
<hr>
<h2 id="저장장치-계층">저장장치 계층</h2>
<p>저장 시스템들은 다음과 같은 기준으로 계층적으로 구성될 수 있습니다.</p>
<ul>
<li>용량</li>
<li>접근 속도
<img src="https://velog.velcdn.com/images/moon_happy/post/e42aa9ca-2175-4597-a6ce-769f261078aa/image.png" alt=""></li>
</ul>
<p>위의 그림은 저장 시스템들을 계층적으로 구성한 것입니다. 위로 올라갈수록 속도는 빨라지고 용량은 작아지게 됩니다. 
hard disk = HDD
solid-state disk = SSD
main memory = 하드웨어 부품인 RAM
cache = CPU에 존재하는 작은 용량의 기억장치, 자주 사용하는 데이터를 저장
registers = CPU에 존재하는 작은 용량의 기억장치, 명령어나 연산에 사용될 피연산자(데이터)를 저장</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4번의 면접을 보면서 느낀점]]></title>
            <link>https://velog.io/@moon_happy/4%EB%B2%88%EC%9D%98-%EB%A9%B4%EC%A0%91%EC%9D%84-%EB%B3%B4%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80%EC%A0%90</link>
            <guid>https://velog.io/@moon_happy/4%EB%B2%88%EC%9D%98-%EB%A9%B4%EC%A0%91%EC%9D%84-%EB%B3%B4%EB%A9%B4%EC%84%9C-%EB%8A%90%EB%82%80%EC%A0%90</guid>
            <pubDate>Sun, 15 Oct 2023 10:41:40 GMT</pubDate>
            <description><![CDATA[<p>일단 지금 대한민국의 경제상황속에서 2달간 신입의 자리로서 면접을 많이 봤다고 생각하고 많은 것을 배웠던 4번의 면접이라고 생각합니다. </p>
<h2 id="🤔-첫번째-면접">🤔 첫번째 면접</h2>
<p>SI회사는 아지니만 SI특성을 가진 부서에서 다른 회사의 인공지능사업등의 데이터파이프라인을 제작하는 부서의 면접을 봤습니다. 
첫번째 면접이다보니 부족한것 투성이었고 지금 생각하면 너무 창피합니다.</p>
<h3 id="부족했던-점">부족했던 점</h3>
<ul>
<li><p><strong>이력서와 포트폴리오의 불일치</strong>
우선 처음 IT직군의 면접을 보면서 엄청나게 긴장을 하고 어떻게 포트폴리오를 수정해야하고 이력서에 기입해야할 사항들을 알지 못하면서 중요한 요점들을 놓쳤던것 같습니다. </p>
</li>
<li><p><strong>사용했던 툴의 정확하지 못했던 지식들</strong>
제가 사용했던 툴들의 기본적인 용어들을 공부해 갔다고 생각했었지만 아직 많이 부족한 저를 보았져</p>
</li>
<li><p><strong>내가 무엇을 하고싶은지의 불확실성</strong>
다시 생각해보면 공고 외 적인 일을 하는 것에 괜찮은지의 물음에 무엇이든 좋다는 식의 답변이 가장 큰 문제였던 것 같습니다. 자기 주관이 뚜렸하게 어떤것을 하고 싶고 어떻게 성장하고 싶은지를 정확하게 정하는게 좋을 것 같습니다.</p>
</li>
<li><p><strong>추상적인 답변들</strong>
너무나도 추상적인 답변들 <strong>&quot;잘할 수 있습니다&quot;</strong>, <strong>&quot;누구보다 열심히 할 수 있습니다&quot;</strong> 이러한 답변들은 제가 생각해도 어떠한 결과물이나 증거도 없이 이러한 답변을 한다는것은 제가 면접관이었어도 안뽑아요</p>
</li>
</ul>
<hr>
<h2 id="🤔-두번째-면접">🤔 두번째 면접</h2>
<p>제가 사용했던 Kafka와 Redis등을 통해서 솔루션 제품에 이용자의 데이터를 전달할수 있는 파이프라인을 관리 운영하는 직군에 지원을 하였습니다. </p>
<h3 id="부족했던-점-1">부족했던 점</h3>
<ul>
<li><p><strong>준비해도 끝이 없는 툴에 대한 답변</strong>
하지만 면접관 분들은 대단한게 준비했던 것을 모조리 피해서 질문 하셔서 아직 부족한 나를 보았져
이런 것을 통해서 여러가지 툴을 사용하는 것도 좋지만 하나의 툴을 집중적으로 사용해보고 탐구하는 것이 좋다고 생각이 됩니다.</p>
</li>
<li><p><strong>포트폴리오와 직군의 업무 일치 부족</strong>
신입도 아닌 준비생이 툴을 많이 써봤다고 해서 입사해서 엄청난 도움이 되는것도 아니고 찍먹충처럼 보일 것 같았습니다.</p>
</li>
</ul>
<p>요번에는 나름 최선을 다해서 사용했던 툴의 기본보다 조금더 DEEP하게 준비를 하면서 긴장도 덜 되었고, 추상적인 답변보다는 근거를 토대로하는 답변을 하려고 노력하였습니다. </p>
<hr>
<h2 id="🤔-세번째-면접">🤔 세번째 면접</h2>
<p>요번에는 포트폴리오와 이력서를 안보시고 면접을 보는 듯한 느낌을 받았습니다.
하지만 IT업계에서 필요한 정보들이나 처세술같은 살아남는 법을 배우는 면접보단 강의 느낌이었습니다.</p>
<h3 id="부족했던-점-2">부족했던 점</h3>
<ul>
<li><strong>내가 무엇을 하고 싶은지의 확신</strong>
요번 면접에서도 이력서를 보면서 어떤일을 하고 싶은지 모르겠다고 하셔서 할 말이 없었습니다. 
과연 돈과 실무경험이 급한 나에게 하나의 직군에만 지원하는게 맞는 것일까 라는 생각이 들었습니다. </li>
</ul>
<p>면접을 하면서 경험에 쓸모 없는 경험은 없다는 말을 체감하는 자리였습니다.</p>
<hr>
<h2 id="🤔-네번째-면접">🤔 네번째 면접</h2>
<p>SI기업으로 DW/DM을 구축하고 BI툴 활용하는 직군의 면접을 진행하였습니다.</p>
<h3 id="부족했던-점-3">부족했던 점</h3>
<ul>
<li>내가 무엇을 하고 싶은지</li>
<li>확실한 자기주장</li>
</ul>
<p>면접을 보면서 공고와 다른 일을 면접때 알게되어서 매우 당황하였습니다.
저는 데이터를 다루는 빅쿼리나 카프카 처럼 데이터의 흐름을 통해서 데이터베이스를 구축하는 것인줄 알았지만 
갑자기 SAP ERP를 다룬다고 해서 매우 당황했습니다. </p>
<hr>
<h2 id="느낀점들">느낀점들</h2>
<ul>
<li><p><strong>무엇을 확고하게 하고 싶은지</strong>
지금까지 백엔드 쪽의 Django로 사이트를 구축하고 데이터의 흐름에 관심을 가지면서 백엔드를 좋아했던 것 같습니다. 그래서 Spring이나 node.js를 하는것도 좋지만 Django를 집중적으로 파고드는게 좋다고 생각이 됩니다.</p>
</li>
<li><p><strong>공고 사이트의 중요성</strong>
원티드, 잡코리아, 인쿠르트, 잡플래닛 등의 여러 채용사이트에서 지원을 했지만 원티드가 최고인것 같습니다. 그것은 면접에서도 차이가 상당했습니다. 
기업이 하고싶은 일이나 명확하게 뽑고 싶은 사람이 정해져있다는 것이 얼마나 중요한지 느꼈습니다.</p>
</li>
<li><p><strong>지원하기전 기업의 사전 조사 필수</strong>
기업이 어떤 사업을 하고 어떤 일을 할 것을 알고 지원하는 것이 면접보는 사람이나 저의 시간을 아끼는 것이라고 생각이 듭니다. </p>
</li>
<li><p><strong>졸업하고의 공백</strong>
집안의 사정으로 인해서 전공과 상관없는 일을 해야했는데 이것은 제가 낭만 가득하게 생각했던 세상과 다르다는 생각이 들었습니다. 
하지만 꾸준하게 공부하고 한다면 알아주는 기업이 있겠죠??</p>
</li>
</ul>
<blockquote>
</blockquote>
<p>앞으로는 Django와 Spring으로 백엔드에 집중적으로 공부하고 데이터베이스에 대해서 자세하게 공부하려고 마음을 먹었습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[BI 도구란]]></title>
            <link>https://velog.io/@moon_happy/BI-%EB%8F%84%EA%B5%AC%EB%9E%80</link>
            <guid>https://velog.io/@moon_happy/BI-%EB%8F%84%EA%B5%AC%EB%9E%80</guid>
            <pubDate>Tue, 03 Oct 2023 14:23:53 GMT</pubDate>
            <description><![CDATA[<p>BI도구는 몇 개월 단위의 장기적인 데이터의 추이를 시각화하거나
집계의 조건을 세부적으로 바꿀 수 있는 대시보드를 만들려고 할 때 적합합니다.</p>
<p>BI도구는 있는 테이블을 그대로 가져올 뿐만 아니라 
시간을 들여 데이터를 분석하기 쉽도록 가공하는 일이 자주 있습니다.</p>
<ul>
<li>유사한 상품을 하나의 그룹으로 정리</li>
<li>IP 주소를 위치 정보로 변환</li>
</ul>
<p>따라서, 시각화에 적합한 데이터 마트를 구축하여 읽고 쓰는것을 대부분 사용합니다.</p>
<hr>
<h2 id="하나의-데이터를-다각적으로-분석하기">하나의 데이터를 다각적으로 분석하기</h2>
<p>대화형 대시보드를 만들기 위해서는 그 바탕이 되는 데이터를 모두 포함하는 하나의 테이블을 작성해야합니다.
그러면서 테이블에서는 다수의 테이블을 만듭니다.</p>
<p>전체 숫자를 파악할 수 있는 것이 적어도 한 개 있고 
그것을 분해하여 주요 지표를 정리한 것이 몇가지 있으면 좋습니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/65fc5550-8eae-4c42-891e-abb197dc26c9/image.png" alt=""></p>
<p>BI도구에서 시각화할 수 있는 내용을 늘리기 위해서 웨어하우스에 있는 테이블을 그대로 사용하려하면 잘 되지 않습니다.
이를 위해서는 배치 처리를 통한 데이터마트 작성이 필요로 합니다.</p>
<p>즉, 알고 싶은 것이 늘어날 때마다 데이터마트에 테이블을 만들고
거기에서 파생되는 다수의 대시보드가 생겨나는 것이 BI도구의 시각화 과정입니다.</p>
<hr>
<h2 id="데이터-마트-만들기">데이터 마트 만들기</h2>
<p>BI도구에 있어서 핵심적인 요소는 OLAP입니다. </p>
<blockquote>
<p>💡 OLAP는 &quot;Online Analytical Processing&quot;의 약자로, 대량의 데이터를 다차원적으로 분석하고 조회하는 기술을 말합니다. 이는 비즈니스 인텔리전스(BI) 분야에서 주로 사용되며, 사용자가 쉽게 원하는 정보를 추출하고 분석할 수 있도록 지원합니다.</p>
</blockquote>
<p>위의 설명과 같이 OLAP는 데이터 집계를 효율적으로 접근하는 방법입니다.
일반적으로 사용되는 RDBSMS 표 형식의 모델링된 데이터를 SQL로 집계합니다.</p>
<p>하지만 OLAP는 다차원 모델의 데이터 구조를 MDX 등의 쿼리 언어로 집계합니다.
그리고 데이터 분석을 위해 만들어진 다차원 데이터를 OLAP큐브 라고 부르고
그것을 크로스 집계 하는 구조가 OLAP입니다.</p>
<blockquote>
</blockquote>
<p>💡 위의 내용에서 나오는 단어의 뜻을 살펴보자면 </p>
<blockquote>
</blockquote>
<ul>
<li>다차원 모델링(Multidimensional Modeling): 데이터를 여러 차원(예: 시간, 지역, 제품 등)으로 구조화하여 복잡한 쿼리와 리포트 작성을 간소화합니다.</li>
<li>OLAP 큐브: 다차원 모델링의 결과물로, 데이터의 다양한 요약 정보나 계산된 값을 빠르게 접근할 수 있는 구조입니다.</li>
<li>MDX(Multidimensional Expressions): OLAP 큐브에서 데이터를 조회하고 조작하기 위한 쿼리 언어입니다.</li>
<li>크로스 집계(Cross-Aggregation): 여러 차원을 통해 집계된 데이터를 분석하는 과정이며, OLAP 시스템이 제공하는 주요 기능 중 하나입니다.</li>
</ul>
<p>예전 같이 컴퓨터의 성능이 좋지 못했을 때는 원하는 데이터로 꾸리는데 오랜 시간이 걸렸기 때문에 
OLAP를 고속화 하려는 아이디어가 필수적이었으며 </p>
<p>그러기 위해서 크로스 집계의 모든 조합을 미리 계산하여 데이터베이스 안에 캐시해두고
쿼리가 실행되면 이미 집계된 결과를 반환하는 방법을 많이 사용하였습니다.</p>
<p>하지만 최근에는 MPP 데이터베이스와 인 메모리 데이터베이스 등이 보급되면서 
위와 같은 방법을 사용 할 필요가 없어졌습니다.</p>
<p>따라서 OLAP 큐브를 위해 특별한 구조를 준비하는 것이 아니라, BI 도구와 MPP 데이터베이스를 조합하여
크로스 집계하는 경우가 증가하고 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[원티드 프리온보딩 백엔드 ]]></title>
            <link>https://velog.io/@moon_happy/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EB%B0%B1%EC%97%94%EB%93%9C</link>
            <guid>https://velog.io/@moon_happy/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EB%B0%B1%EC%97%94%EB%93%9C</guid>
            <pubDate>Mon, 02 Oct 2023 11:32:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/619f4685-5400-4de7-ae1f-04b48ff35be4/image.png" alt=""></p>
<p>요번에 원티드에서 진행하는 프리온보딩 백엔드 챌린지(MySQL)를 신청하면서 
MySQL관련하여 사전과제가 주어졌습니다. </p>
<ol>
<li><p>데이터베이스와 테이블의 차이는 무엇인가요?</p>
<ul>
<li>데이터베이스는 여러개의 테이블의 집합으로 책들이 모여있는 책장과 같습니다.</li>
<li>테이블은 Row와 Column으로 이루어진 데이터들의 집합입니다.</li>
</ul>
</li>
<li><p>MySQL에서 데이터를 조회할 때 사용하는 기본 SQL 명령어를 설명해주세요</p>
<ul>
<li>SELECT : 모든 조건에 부합하는 Row에서 얻고싶은 Column을 선택합니다.</li>
<li>WHERE : FROM에서 정의된 데이터에서 필터링을 하기위해 조건을 만듭니다.</li>
<li>FROM : 해당 SQL문의 데이터를 지정합니다.</li>
<li>HAVING : GROUP BY의 조건절로 주로 집계함수와 함께 사용됩니다.</li>
<li>JOIN : 두 개 이상의 테이블을 특정 Column으로 연결하여 합칩니다.</li>
<li>ORDER BY : 최종적으로 필터링된 데이터의 특정 Column을 기준으로 정렬을 합니다.</li>
</ul>
</li>
<li><p>&#39;Primary Key&#39;와 &#39;Foreign Key&#39;의 차이와 각각의 역할에 대해 설명해주세요.</p>
<ul>
<li>Primary Key : 테이블에서의 각 Row를 고유하게 식별하는데 사용되고 유일성과 최소성을 가지고있다. (공백과 중복을 허용하지 않습니다.)</li>
<li>Foreign Key : 다른 테이블에 기본키를 참조하는 키(공백과 중복을 허용합니다)</li>
</ul>
</li>
<li><p>MySQL에서 &#39;JOIN&#39;이란 무엇이며, &#39;INNER JOIN&#39;과 &#39;LEFT JOIN&#39;의 차이점은 무엇인가요?</p>
<p> 두 개 이상의 테이블을 특정 Column의 값으로 연결하여 합치는 행위 입니다.
 INNER JOIN은 두 테이블의 교집합을 의미하고, LEFT JOIN은 왼쪽 테이블을 기준으로 오른쪽 테이블을 매치시킵니다.</p>
</li>
<li><p>정규화(Normalization)란 무엇이며, 왜 중요한가요?</p>
<p> 정규화는 테이블을 여러 개의 관련 테이블로 분할하고 각 테이블을 관리 가능한 크기로 만드는 프로세스입니다.
 정규화를 통해 데이터베이스의 관리가 수월해지고 쿼리의 성능을 높일수 있습니다.</p>
</li>
</ol>
<p>일주일에 2번으로 2주동안 진행 되는거다보니 시간도 짧고 저녁시간에 해서 좋네요 
하루 끝날때 마다 올릴 예정입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[n-1개의 복제계수에 대해서]]></title>
            <link>https://velog.io/@moon_happy/n-1%EA%B0%9C%EC%9D%98-%EB%B3%B5%EC%A0%9C%EA%B3%84%EC%88%98%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@moon_happy/n-1%EA%B0%9C%EC%9D%98-%EB%B3%B5%EC%A0%9C%EA%B3%84%EC%88%98%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Sat, 23 Sep 2023 15:54:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/633570a8-0a06-471c-869b-c8878b01323d/image.gif" alt=""></p>
<p>최근 n-1개의 복제계수로 토픽을 만들면 어떻게 메세지가 복제가될까라는 고민을 많이 했습니다. (n = 클러스터에서 브로커의 수) </p>
<h2 id="파티션과-복제">파티션과 복제</h2>
<h3 id="파티션">파티션</h3>
<p>파티션이란 <strong>메시지들이 저장되는 곳</strong>입니다. 하나의 토픽은 여러 개의 파티션으로 나뉘어져 있으며, 각각의 메시지는 하나의 파티션에 저장됩니다.</p>
<hr>
<h3 id="복제-계수">복제 계수</h3>
<p>복제 계수는 각 파티션 데이터가 클러스터 내에서 몇 번 복사되어 유지되는지를 결정하는 값입니다. 만약 복제 계수를 2로 설정한다면, 각 파티션 데이터는 두 개의 브로커(서버)에 저장됩니다. 이 때 <strong>한 브로커가 리더 역할을 하고 다른 하나가 팔로워 역할</strong>을 합니다.</p>
<h4 id="복제계수를-설정하는-목적">복제계수를 설정하는 목적</h4>
<ul>
<li>데이터 안전성</li>
<li>시스템 가용성을 확보</li>
</ul>
<p>만약 어떤 한 서버(브로커)에서 장애가 발생하더라도 다른 서버에서 해당 데이터를 가져올 수 있으므로 데이터 손실 없이 서비스를 지속할 수 있습니다.<strong>(고가용성)</strong></p>
<h4 id="복제를-많이-하면-좋을까">복제를 많이 하면 좋을까?</h4>
<p>하지만 모든 것이 장점만 있는 것은 아닙니다. </p>
<ul>
<li><p><strong>저장 공간 증가</strong> : 복제 계수가 증가하면, 같은 데이터를 더 많은 브로커에 저장해야 합니다.</p>
</li>
<li><p><strong>네트워크 대역폭 사용량 증가</strong> : 복제 계수를 늘리면, 원본 데이터와 동일한 크기의 데이터가 추가로 네트워크를 통해 브로커에 전송되어야 하므로, 이는 네트워크 대역폭 사용량의 증가를 의미합니다.</p>
</li>
</ul>
<p>따라서 실질적으로 운영 환경에서는 시스템 요구사항과 사용 가능한 자원 등 여러 요소들을 고려해야합니다.</p>
<hr>
<h2 id="3개의-브로커와-2개의-복제계수">3개의 브로커와 2개의 복제계수</h2>
<p>이번에는 3개의 브로커와 3개의 파티션이 있고 복제 계수가 2인 경우를 예로 들어보겠습니다. 이 경우 각 파티션은 두 개의 브로커에 걸쳐 저장되며, 하나는 리더, 다른 하나는 팔로워 역할을 합니다. 이때 <strong>모든 세 브로커는 활동 상태</strong>입니다.</p>
<h3 id="예시">예시</h3>
<ul>
<li><strong>파티션 1</strong>: 브로커 A(리더), B(팔로워)</li>
<li><strong>파티션 2</strong>: 브로커 B(리더), C(팔로워)</li>
<li><strong>파티션 3</strong>: 브로커 C(리더), A(팔로워)</li>
</ul>
<p>이렇게 설정하면 각각의 데이터가 서버 사이에서 균등하게 분산되고, 만약 한 서버에서 장애가 발생해도 다른 서버에서 데이터를 가져올 수 있어서 내결함성이 향상됩니다.</p>
<p>그리고 여기서는 <strong>ISR</strong>이라는 개념으로 리플리케이션 그룹을 구성하게됩니다.</p>
<h3 id="isr-in-sync-replicas">ISR (In-Sync Replicas)</h3>
<ul>
<li><strong>동기화된 복제본</strong>이라는 뜻</li>
<li>리더 브로커와 동기화된 상태를 유지하는 팔로워 브로커들의 <strong>집합</strong>을 의미합니다.</li>
</ul>
<p>팔로워 브로커가 리더 브로커와 동기화를 유지하기 위해서는 주기적으로 리더에게 데이터를 요청하고 이를 받기 때문에 Kafka 클러스터의 <strong>안정성</strong>과 <strong>데이터 일관성</strong>이 보장됩니다.</p>
<p>왜냐하면, 새로운 메시지가 커밋되고 소비자에게 전달되려면 그 메시지가 모든 ISR의 멤버에게 <strong>반드시 복사</strong>되어야 합니다.</p>
<p>그러면서 만약 한 브로커에서 장애가 발생해도 다른 서버에서 데이터를 가져올 수 있어서 <strong>내결함성</strong>이 향상됩니다. </p>
<p>이러한 과정은 Kafka의 <strong>고가용성</strong>과 <strong>내결함성</strong>을 보장하는 중요한 부분입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ad Hoc 이란]]></title>
            <link>https://velog.io/@moon_happy/Ad-Hoc-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@moon_happy/Ad-Hoc-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sat, 23 Sep 2023 07:16:32 GMT</pubDate>
            <description><![CDATA[<p>빅데이터를 지탱하는 기술 책을 읽다가 Ad Hoc이라는 단어가 종종 등장해서 찾아보면서 정리했습니다.</p>
<h2 id="ad-hoc이란">Ad Hoc이란</h2>
<p>일반적으로 특정한 목적이나 계획에 따라 미리 정의된 쿼리나 분석이 아니라, <strong>필요에 따라 임시로 데이터를 분석하거나 나타내는것</strong>을 의미합니다.</p>
<h3 id="특징">특징</h3>
<ul>
<li><p>비구조적 : 데이터 미리 정의 없이 활용 가능한 분석</p>
</li>
<li><p>즉각적인 요구 : 긴급 문제 해결 및 특별 질문에 활용</p>
</li>
<li><p>유연성 : 유연한 데이터 접근과 빠른 분석 가능</p>
</li>
<li><p>일회성 : <strong>일회성 작업</strong>, 결과물을 재사용하는 경우는 많지 않습니다.</p>
</li>
</ul>
<p>즉, 주기적으로 들어오는 데이터로 시각화하여 모니터링하는 것과는 다르게 데이터 요청에 따라서 <strong>일회성</strong>으로 지표를 보는것이라고 할수 있습니다.</p>
<hr>
<h3 id="해야하는-이유">해야하는 이유</h3>
<ol>
<li><p>Ad Hoc분석은 <strong>데이터를 통한 의사결정의 핵심</strong>이기 때문입니다.</p>
</li>
<li><p>Ad Hoc 분석은 결과 해석과 전략 도출 역량을 향상시켜줍니다.</p>
</li>
</ol>
<hr>
<h3 id="예시">예시</h3>
<h4 id="빅쿼리를-통한-대시보드화">빅쿼리를 통한 대시보드화</h4>
<ul>
<li><p>로그 데이터가 지속적으로 빅쿼리에 적재됩니다.</p>
</li>
<li><p>데이터는 대시보드 도구(예: Tableau, Google Data Studio 등)에서 사용되어 시각화 대시보드를 생성하거나 보고서를 만들기 위해 활용됩니다.</p>
</li>
<li><p>이 시나리오는 주로 실시간 또는 <strong>정기적인 데이터 모니터링</strong> 및 <strong>보고</strong>에 적합합니다. 데이터가 <strong>지속적으로 업데이트</strong>되고 <strong>시각화가 자동화</strong>되므로 사용자는 대시보드를 통해 <strong>지속적인 인사이트</strong>를 얻을 수 있습니다.</p>
</li>
</ul>
<h4 id="빅쿼리를-통한-애드혹-분석">빅쿼리를 통한 애드혹 분석</h4>
<ul>
<li><p>빅쿼리를 사용하여 필요한 시점에 원하는 쿼리를 실행하고 데이터를 추출합니다.</p>
</li>
<li><p>주로 <strong>특정 문제 해결</strong>, <strong>예기치 않은 이벤트 조사</strong> 또는 <strong>비즈니스 의사 결정</strong>을 위한 <strong>일회성 분석</strong>에 활용됩니다.</p>
</li>
<li><p>이 시나리오에서는 쿼리를 통해 데이터를 탐색하고 필요한 <strong>지표를 추출</strong>하며, 결과를 시각적으로 표현하는 대시보드나 보고서를 만들기보다는 분석 결과 자체가 중요합니다.</p>
</li>
</ul>
<p>두 시나리오 모두 빅쿼리를 활용하며, 어떤 시나리오를 선택할지는 사용자의 요구 사항과 목적에 따라 달라집니다. 대시보드화된 분석은 데이터를 지속적으로 모니터링하고 관찰하며, 애드혹 분석은 특정 문제를 해결하거나 질문에 대한 답을 찾는 데 사용됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[행기반 & 열기반 데이터베이스]]></title>
            <link>https://velog.io/@moon_happy/%ED%96%89%EA%B8%B0%EB%B0%98-%EC%97%B4%EA%B8%B0%EB%B0%98-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@moon_happy/%ED%96%89%EA%B8%B0%EB%B0%98-%EC%97%B4%EA%B8%B0%EB%B0%98-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Sat, 23 Sep 2023 05:51:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/068f3f41-ad99-4e60-9391-f643fdc3edef/image.jpeg" alt=""></p>
<ul>
<li>행기반 데이터베이스</li>
<li>열기반 데이터베이스</li>
</ul>
<p>데이터베이스를 공부하다보면 위처럼 두가지 종류의 데이터베이스를 만나게 됩니다.
처음 이 개념을 접했을때 관계형 데이터베이스에서의 행과 열은 알겠는데 이거들을 기반으로 하는 데이터베이스는 무엇일까 라는 궁금증이 있었습니다.</p>
<hr>
<h2 id="👉🏾-행기반-데이터베이스">👉🏾 행기반 데이터베이스</h2>
<p>행기반 데이터베이스는 우리가 일반적으로 사용하는 MySQL, Oracle, PostgreSQL과 같은 전통적인 관계형 데이터베이스를 말합니다.</p>
<ul>
<li><p>기간계 시스템이라고 부르는 <strong>OLTP</strong> 환경(Insert, Update, Delete 작업이 빈번한 환경)에서 유리하게 작용합니다.</p>
</li>
<li><p>데이터를 행단위로 추가하며, 레코드 단위로 읽고 쓰기에 최적화 되어있습니다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/b663dcf3-956c-4576-abd3-79b90e268b89/image.png" alt=""></p>
<ul>
<li><p>데이터의 검색 속도를 향상시키기 위해서 인덱스를 사용하곤 합니다. 인덱스가 없다면 모든 레코드를 불러와야 하고 그러면 데이터의 I/O가 많아져 성능저하가 오게됩니다.</p>
</li>
<li><p>데이터를 불러오는 과정에서 기본적으로 레코드 단위로 데이터가 저장되어있기 때문에 불러올때도 필요없는 데이터도 같이 불러오기 때문에 I/O를 잘생각해야합니다.</p>
</li>
<li><p>데이터를 저장하게 되면 디스크의 마지막에 추가가 됩니다.</p>
</li>
</ul>
<hr>
<h2 id="👇🏾-열기반-데이터베이스">👇🏾 열기반 데이터베이스</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/af90e61a-3647-4738-bda1-3f5caa42a42c/image.png" alt=""></p>
<p>열지향 데이터베이스라고 불리고, 데이터 마트의 역할로 많이 사용합니다.</p>
<ul>
<li><p>분석계 시스템이라고 부르는 OLAP 환경(Select 작업이 빈번한 환경)에서 유리하게 작용합니다.</p>
</li>
<li><p>빅데이터로 취급되는 데이터의 대부분은 디스크 상에 있고 쿼리에 필요한 최소한의 데이터만 가져오면서 지연을 줄일수 있습니다.
즉, 이를 위해서는 &#39;컬럼단위로 데이터 압축&#39;이 필요합니다. </p>
</li>
<li><p>컬럼 단위로 데이터 로드가 가능하기 때문에 디스크의 I/O를 줄이고 높은성능을 가지고 있습니다.</p>
</li>
<li><p>데이터 추가할때 Column별로 추가되어야할 자리를 찾는 과정이 필요합니다.</p>
</li>
<li><p>조회작업의 성능은 행 기반 데이터베이스에 비해 높은 반면에 값을 삽입, 수정, 삭제하는 과정에서는 레코드의 수도 많고, 이에 따라 인덱스가 리빌드 되어야하는 과정이 포함되어 있어 성능이 현저하게 낮습니다.</p>
</li>
</ul>
<p>🔗 <a href="https://chaarlie.tistory.com/674">https://chaarlie.tistory.com/674</a>
책 : 빅데이터를 지탱하는 기술</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[로그파이프라인(카프카 컨슈머 생성)]]></title>
            <link>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EC%B9%B4%ED%94%84%EC%B9%B4-%EC%BB%A8%EC%8A%88%EB%A8%B8-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EC%B9%B4%ED%94%84%EC%B9%B4-%EC%BB%A8%EC%8A%88%EB%A8%B8-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Tue, 12 Sep 2023 07:06:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/be6ad999-ddb2-478d-925c-33b9ac952579/image.png" alt=""></p>
<p>앞에서의 포스팅을 과정을 거쳐서 브로커의 토픽에 메세지(로그)들이 적재가 되었습니다.</p>
<p>이렇게 적재된 메세지들을 이제 컨슈머를 통해서 소비를하고 원하는 목적지에 배달을 해야하는데요 
구현한 컨슈머를 통해서 포스팅을 진행하겠습니다.</p>
<h2 id="🦮-bigquery-consumer">🦮 BigQuery Consumer</h2>
<p>BigQuery로 가는 &quot;user2&quot; 토픽의 메세지들은 모든로그를 취급합니다.
그러면서 BigQuery로 적재된 로그 데이터를 통해서 분석가들이 사용자를 분석하거나 그거에 맞는 모델을 만들기 위해서 사용하는 데이터 마트의 역할을 하게됩니다.</p>
<h3 id="code">Code</h3>
<pre><code class="language-python">from kafka import KafkaConsumer
import json
from google.cloud import bigquery
from google.oauth2 import service_account


credentials = service_account.Credentials.from_service_account_file(&#39;GCP 키파일 경로&#39;)
client = bigquery.Client(credentials=credentials)
table_id = &quot;빅쿼리 테이블 아이디&quot;

# Kafka 처리를 위한 consumer 생성
consumer = KafkaConsumer(
    &#39;토픽 이름&#39;,
    bootstrap_servers=[&#39;IP:PORT&#39;, &#39;IP:PORT&#39;, &#39;IP:PORT&#39;],
    value_deserializer=lambda x: json.loads(x.decode(&#39;utf-8&#39;))
)
# 로그 데이터를 처리하여 BigQuery에 저장하는 함수
def insert_data_bigquery(log_data):
    errors = client.insert_rows_json(table_id, [log_data])
    if errors == []:
        print(&quot;새 행이 추가되었습니다.&quot;)
    else:
        print(&quot;다음 에러가 발생했습니다: &quot;, errors)

for msg in consumer:
    log_data = msg.value
    insert_data_bigquery(log_data)</code></pre>
<h3 id="info">Info</h3>
<ol>
<li><p><strong>빅쿼리 연결</strong>
우선적으로 빅쿼리와 연결을 먼저 진행해야합니다.
처음에는 insert_data_bigquery함수안에 했지만 그것을 밖으로 빼서 함수가 작동할때마다 연결하는 시간을 단축시켰습니다.</p>
</li>
<li><p><strong>카프카 연결</strong>
카프카 연결을 위해서 브로커들의 아이피와 포트, 토픽이름을 작성하고, 들어온 메세지에 대한 직렬화를 했습니다.
브로커의 아이피와 포트를 모두 쓴 이유는 카프카 클러스터의 한 브로커가 장애가 발생하더라도, 컨슈머는 다른 브로커와 연결하여 계속해서 데이터를 수신하여 장애에 대처하기 위함입니다.</p>
</li>
<li><p><strong>메세지 빅쿼리에 insert</strong>
가져온 메세지를 빅쿼리에 넣기 위해서 테이블의 ID를 통해서 연결을 합니다. 
만약 <code>client.insert_rows_json(table_id, [log_data])</code> 이 과정에서 에러가 없다면 <code>errors</code>라는 변수가 비어있기 때문에 추가됐다고 출력을 하고 아니라면 에러의 내용을 출력하여 대처할수 있습니다.</p>
</li>
</ol>
<hr>
<h2 id="🦮-redis-consumer">🦮 Redis Consumer</h2>
<p>Redis로 가는 메세지들은 &quot;user2&quot; 로그로 향하는 메세지들중 <code>info</code>라는 키값에 <code>search</code> 또는 <code>movie_detail</code>이라면 &quot;user3&quot; 라는 토픽에도 추가로 향하게 됩니다.</p>
<h3 id="redis로-가는이유">Redis로 가는이유</h3>
<ul>
<li>순위 집계 : Redis의 Sorted Set을 통해서 기능을 구현하였습니다.</li>
<li>사용자에게 빠르게 정보전달</li>
<li>다른 데이터베이스의 부하를 분산</li>
</ul>
<h3 id="code-1">Code</h3>
<pre><code class="language-python">from kafka import KafkaConsumer
import json
import redis

redis_client = redis.Redis(host=&#39;IP&#39;, port=6379, db=0)

# Kafka 처리를 위한 consumer 생성
consumer = KafkaConsumer(
    &#39;토픽 이름&#39;,
    bootstrap_servers=[&#39;IP:PORT&#39;, &#39;IP:PORT&#39;, &#39;IP:PORT&#39;],
    value_deserializer=lambda x: json.loads(x.decode(&#39;utf-8&#39;))
)

def insert_data_redis(key, log_data):
    if key == &#39;popularity&#39;:
        # 상세페이지 본 순위 
        redis_client.zincrby(key, 1, log_data[&#39;action_data&#39;]) # sorted set의 개념을 활용(순위)

        # 최근 본 상세페이지 기능 구현
        user_key = log_data[&#39;user_id&#39;] # 최근 본 영화 구현을 위해
        value=f&#39;{log_data[&quot;action_data&quot;]}&#39; # 최근 본 영화 구현을 위해
        redis_client.lpush(user_key, value)  # 리스트의 왼쪽에 movie_id 값 추가
        redis_client.ltrim(user_key, 0, 9) # 최근 본 영화를 10개만 보여주기위해서 밀어내면서 뒤에오는것은 삭제 
    else:
        redis_client.zincrby(key, 1, log_data[&#39;action_data&#39;])

    print(f&quot;레디스에 데이터 추가됨: {key} -&gt; {log_data[&#39;action_data&#39;]}&quot;)

for msg in consumer:
    log_data = msg.value

    if log_data[&#39;info&#39;]==&#39;movie_detail&#39;:
         insert_key=&#39;popularity&#39;       
    else:
         insert_key=&#39;search&#39;

    insert_data_redis(insert_key ,log_data)
</code></pre>
<h3 id="info-1">Info</h3>
<ol>
<li><p><strong>Redis 연결</strong>
우선적으로 Redis와 연결을 먼저 진행해야합니다.</p>
</li>
<li><p><strong>카프카 연결</strong>
빅쿼리 컨슈머와 같은 방식으로 카프카의 토픽과 연결합니다.</p>
</li>
<li><p><strong>들어온 메세지 처리</strong>
아래쪽의 반복문을 통해서 메세지가 들어오게되고 이때 조건문을 통해서 아래와 같이 키값을 다르게 했습니다.</p>
</li>
</ol>
<ul>
<li><code>info</code>라는 키의 값이 <code>movie_detail</code> 이라면 <code>insert_key</code>는 <code>popularity</code></li>
<li><code>info</code>라는 키의 값이 <code>search</code> 이라면 <code>insert_key</code>는 <code>search</code></li>
</ul>
<ol start="4">
<li>*<em>함수에서 insert_key를 통해서 구분하기 *</em>
함수에 키와 데이터가 들어가게 되면 아래와 같이 기능이 나눠집니다.</li>
</ol>
<ul>
<li><p>*<em>클릭한 영화에대한 순위 *</em>
<code>key</code>가 <code>popularity</code>라면 sorted set을 통해서 들어온 <code>log_data[&#39;action_data&#39;]</code>의 영화아이디 값을 1씩 증가합니다.</p>
</li>
<li><p><strong>사용자가 최근 클릭한 영화</strong>
사용자의 최근 본 영화는<code>user_key</code>라는 리스트에 방금 본 영화의 아이디인 <code>value</code>를 추가합니다. 이 때, Redis의 LPUSH 명령어를 사용하여 리스트의 가장 왼쪽(즉, 맨 앞)에 새로운 요소를 추가하게 됩니다.</p>
</li>
<li><p><strong>검색어 순위</strong>
<code>key</code>가 <code>search</code>라면 sorted set을 통해서 들어온 <code>log_data[&#39;action_data&#39;]</code>의 검색어 값을 1씩 증가합니다.</p>
</li>
</ul>
<hr>
<blockquote>
</blockquote>
<p>운영을 할때는 추가됐다는 출력문을 삭제하고, 디버깅을 통해서 이상유무를 빠르게 아는 방법으로 변경하는것이 좋겠습니다.</p>
<blockquote>
</blockquote>
<p>그리고 하드코딩으로 작성했던 IP와 PORT를 환경변수나 설정파일을 통해서 관리를 해야합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java 면접준비]]></title>
            <link>https://velog.io/@moon_happy/Java-%EB%A9%B4%EC%A0%91%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@moon_happy/Java-%EB%A9%B4%EC%A0%91%EC%A4%80%EB%B9%84</guid>
            <pubDate>Mon, 11 Sep 2023 13:54:13 GMT</pubDate>
            <description><![CDATA[<h3 id="자바의-특징">자바의 특징</h3>
<ul>
<li>독립적인 운영<ul>
<li>JVM에서 동작하기 때문에 운영체제에 독립적</li>
</ul>
</li>
<li>객체지향 프로그래밍언어(Object Oriented Programing)<ul>
<li>계층 구조, 캡슐화, 상속, 추상화, 다형성 등을 구현한 객체지향언어</li>
</ul>
</li>
<li>메모리를 자동으로 관리<ul>
<li>가비지컬렉터를 이용해서 불필요한 메모리를 자동으로 제거</li>
</ul>
</li>
<li>오픈소스<ul>
<li>풍부한 라이브러리</li>
</ul>
</li>
<li>멀티스레드 구현<ul>
<li>고통 스레드 API를 통해서 운영체제와 관계없이 멀티스레드 구현</li>
</ul>
</li>
</ul>
<hr>
<h3 id="객체지향언어">객체지향언어</h3>
<ul>
<li>추상화(Abstraction)<ul>
<li>공통의 속성이나 기능을 묶어서 표현하는 방법</li>
<li>예) 동물을 대표하는 Animal Class</li>
</ul>
</li>
<li>캡슐화(Encapsulation)<ul>
<li>높은 응집도(동일한 클래스만 변경)와 낮은 결합도(다른 클래스 간섭 배제)를 유지하는 설계방법</li>
<li>데이터 캡슐화 : 필드와 메소드를 클래스로 묶는 방법</li>
<li>은닉화 : 외부에서 객체 상태 변경에 제한을 두는 방법(접근제어)<ul>
<li>예 : Animal Class는 Human Class에서 접근 불가</li>
</ul>
</li>
</ul>
</li>
<li>상속(Inheritance)또는 일반화 (Generalization)<ul>
<li>자식 클래스가 부모 클래스를 물려받고 확장하는 개념<ul>
<li>예 : Animal Class 를 Dog Class가 상속해서 부모 클래스의 변수와 메서드를 사용</li>
</ul>
</li>
</ul>
</li>
<li>다형성 (Polymorphism)<ul>
<li>동일 요청에 대해 서로 다른 방식으로 응답할 수 있는 방법</li>
<li>Overriding : 상속 받은 메소드를 재정의</li>
<li>Overloading : 동일 클래스의 동일한 메소드가 매개변수의 타입이나 개수에 따라 다르게 동작</li>
</ul>
</li>
</ul>
<hr>
<h3 id="oop의-원칙">OOP의 원칙</h3>
<p>5대 원칙으로 SOLID라고 한다</p>
<ul>
<li>S : 단일 책임 원칙<ul>
<li>SRP : Single Responsibility Principle</li>
<li>객체는 단 하나의 책임만 가져야 한다</li>
</ul>
</li>
<li>O : 개방 - 폐쇄의 원칙<ul>
<li>OCP : Open Closed Priciple</li>
<li>기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계해야한다</li>
</ul>
</li>
<li>L : 리스코프 치환 원칙<ul>
<li>LSP : Liskov Substitution Principle</li>
<li>자식 클래스는 자신의 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다</li>
</ul>
</li>
<li>I : 인터페이스 분리 원칙<ul>
<li>ISP : Interface Segregarion Priciple</li>
<li>클래스는 자신과 관련 없는 인터페이스는 구현하지 않는다.</li>
</ul>
</li>
<li>D : 의존 역전 원칙<ul>
<li>DIP : Dependency Iversion Priciple</li>
<li>상위 모듈은 하위 모듈에 종속되면 안되고, 둘 다 추상화에 의존해야 한다.<ul>
<li>예 : 상위 모듈인 자동차를 만드는데 하위 모듈인 스노우 타이어를 참조하지 말고, 상위 모듈인 타이어를 추상화 해서 사용한다 .</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="oop를-사용하는-이유">OOP를 사용하는 이유</h3>
<ul>
<li>코드의 재사용성 증가</li>
<li>유지보수의 용이성</li>
<li>간결한 코드</li>
<li>높은 확장성</li>
<li>강한 응집력과 약한 결합력</li>
<li>보안성 향상</li>
<li>소프트웨어 생산성 향상</li>
</ul>
<hr>
<h3 id="접근제어의-종류">접근제어의 종류</h3>
<p>접근제어 : 클래스, 인터페이스, 멤버 변수, 메서드의 접근 범위를 제어하는 것</p>
<ul>
<li>public : 모든곳에서 접근 가능</li>
<li>protected : 같은 패키지 내의 클래스와 상속받은 클래스에서 접근 가능</li>
<li>default : 같은 패키지 내에서만 접근 가능</li>
<li>private : 클래스 내부에서만 접근 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/f584033d-336f-4ecc-8a00-3462d820588c/image.png" alt=""></p>
<hr>
<h3 id="jvm-메모리-영역">JVM 메모리 영역</h3>
<ul>
<li>Method Area<ul>
<li>클래스가 로딩될 때 할당</li>
<li>패키지, 클래스, 인터페이스, 생성자, 메소드, 필드, static 변수등을 저장</li>
<li>모든 스레드가 공유</li>
</ul>
</li>
<li>Heap Area<ul>
<li>런타임 시에 동적으로 할당</li>
<li>new 키워드로 생성된 객체와 배열이 저장되는 영역</li>
<li>Heap 영역에 생성된 객체와 배열은 Stack 영역의 변수에서 참조</li>
<li>Garbage Collector가 참조하지 않는 메모리를 제거</li>
</ul>
</li>
<li>Stack Area<ul>
<li>스레드마다 존재, 스레드가 시작될 대 할당</li>
<li>지역변수, 파라미터, 리턴값, 연산에 사용되는 값 등이 생성되는 영역</li>
<li>메소드를 호출할 때마다 개별적으로 스택이 생성되며 종료시 해제된다</li>
<li>선입후출이 구조를 가진다</li>
<li>기본 타입 변수는 Stack 영역에 직접 값을 가진다</li>
<li>참조 타입 변수는 Method 영역이나 Heap 영역의 참조 주소를 가진다</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/cf227056-7582-4ab5-a7b0-e417db826e9c/image.png" alt=""></p>
<hr>
<h3 id="static과-non-static-차이">Static과 non-Static 차이</h3>
<ul>
<li>Static<ul>
<li>클래스당 하나의 멤버가 생성되며, 클래스 멤버라고 부른다</li>
<li>클래스 로딩시에 자동으로 멤버가 생성</li>
<li>Method 메모리 영역에 저장</li>
<li>동일 클래스의 모든 객체들에 공유</li>
<li>전역 변수와 함수를 만들 때 활용</li>
</ul>
</li>
<li>non-Static<ul>
<li>객체마다 멤버가 생성되며, 인스턴스 멤버라고 부른다</li>
<li>객체 생성 시에 멤버가 생성</li>
<li>Heap 메모리 영역에 저장</li>
<li>객체 내에서만 멤버가 활용</li>
</ul>
</li>
</ul>
<hr>
<h3 id="추상-클래스와-인터페이스의-차이">추상 클래스와 인터페이스의 차이</h3>
<ul>
<li><p>추상 클래스는 추상 메서드가 하나 이상 포함되는 클래스로 상속을 통해서 사용
  추상 클래스에는 일반 변수와 메서드도 정의가 가능
  추상 클래스는 일부 구현된 설계도로 상속 받아서 확장하게된다</p>
</li>
<li><p>인터페이스는 추상 메서드로 구성되고 다중 상속이 가능
  인터페이스는 기본 설계도로 구현은 모두 따로 해야한다 </p>
</li>
</ul>
<hr>
<h3 id="list-map-set의-차이">List, Map, Set의 차이</h3>
<ul>
<li>List<ul>
<li>순서와 중복이 허용</li>
<li>배열의 크기가 가변적</li>
<li>데이터가 커지면 속도저하</li>
<li>인덱스로 원소를 접근</li>
</ul>
</li>
<li>Map<ul>
<li>Key, Value 한쌍으로 저장, 순서가 없다</li>
<li>Key는 중복될 수 없다</li>
<li>Value는 중복 허용</li>
<li>별도 인덱스가 없다</li>
<li>검색속도가 빠르다</li>
</ul>
</li>
<li>Set<ul>
<li>순서가 없고, 중복을 허용하지 않는다</li>
<li>별도 인덱스가 없다</li>
<li>검색속도가 빠르다</li>
</ul>
</li>
</ul>
<hr>
<h3 id="프로세스와-스레드의-차이">프로세스와 스레드의 차이</h3>
<p>먼저 프로그램이란 어떤 작업을 하기 위해서 실행할 수 있는 파일을 의미
프로그램이 실행되면 메모리에 올라가며, 프로세스와 스레드에서 작업이 이루어진다 </p>
<ul>
<li>순서 : 프로그램 → 프로세스 → 스레드</li>
<li>프로세스 (Process)<ul>
<li>컴퓨터에서 실행되고 있는 프로그램</li>
<li>메모리에서 실행되고있는 프로그램의 인스턴스</li>
<li>운영 체제로 부터 시스템 자원을 할당 받는 단위</li>
</ul>
</li>
<li>스레드 (Thread)<ul>
<li>프로세스가 할당 받은 자원을 이용하는 실행 단위</li>
<li>하나의 프로세스에 여러 스레드가 존재, Heap을 통해 공유 가능</li>
</ul>
</li>
<li>자바 스레드(Java Thread)<ul>
<li>자바 스레드는 JVM에 의해 실해되는 단위 코드 블록</li>
<li>멀티 스레드 구현을 통해 성능 향상</li>
</ul>
</li>
<li>멀티 프로세스<ul>
<li>하나의 프로그램을 여러 개의 프로세스로 구성, 각각의 프로세스가 개별 작업을 빠르게 처리</li>
<li>문제 발생 시에 다른 프로세스에 영향을 주지 않음</li>
<li>프로세스 간에 통신 비용이 크고 복잡</li>
</ul>
</li>
<li>멀티 스레스<ul>
<li>하나의 프로그램을 여러 개의 스레드로 구성하여, 각각의 스레드가 개별 작업을 빠르게 처리</li>
<li>자원의 효율성 증대</li>
<li>처리 비용 감소 및 응답 시간 단축</li>
<li>자원을 공유하면서 동기화 문제 발생 가능</li>
</ul>
</li>
</ul>
<hr>
<h3 id="직렬화serialization-역직렬화deserialization">직렬화(Serialization), 역직렬화(Deserialization)</h3>
<ul>
<li>직렬화<ul>
<li>자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에도 사용할수 있도록, 바이트 형태로 데이터를 변환하는 기술</li>
<li>객체 데이터를 파일로 저장하거나 Stream 데이터로 전송</li>
</ul>
</li>
<li>역직렬화<ul>
<li>직렬화된 데이터를 다시 자바 객체 형태로 만드는 과정</li>
<li>저장된 파일을 읽거나 전송된 Stream 데이터를 원래 형태로 복원</li>
</ul>
</li>
</ul>
<hr>
<h3 id="병렬처리">병렬처리</h3>
<p>멀티 코어 환경에서 하나의 작업을 각각의 코어가 분할해서 처리하는 방법
작업을 분산해서 처리하기 때문에 빠른 처리가 가능</p>
<ul>
<li>동시성<ul>
<li>싱글 코어를 이용한 멀티 작업은 멀티 스레드가 번갈아 가며 실행되고 병령처리는 아니다</li>
<li>싱글 코어에서는 병렬 처리 보다는 순차 처리가 유리</li>
</ul>
</li>
<li>병렬성<ul>
<li>멀티코어를 이용해서 동시에 멀티 작업을 처리</li>
<li>데이터 병렬성 : 전체 데이터를 서브 데이터로 나눠서 병렬처리하는 방법</li>
<li>작업 병렬성 : 서로 다른 작업을 병렬로 처리하는 방법</li>
</ul>
</li>
</ul>
<hr>
<h3 id="string-stringbuffer-stringbuilder">String, StringBuffer, StringBuilder</h3>
<ul>
<li>String<ul>
<li>메모리 영역에 생성되며 변경이 불가능</li>
<li>문자열이 변경되면, 기존 객체는 남아있고 새로운 인스턴스 생성</li>
<li>잦은 문자열 변경은 성능저하를 불러와, 변경이 적은경우에 사용</li>
<li>멀티 스레드 환경에서 동기화가 가능</li>
</ul>
</li>
<li>StringBuffer / StringBuilder<ul>
<li>String과 달리 가변적으로 사용</li>
<li>문자열 변경이 발생하면, 기존의 버퍼 크기를 늘린다</li>
<li>잦은 문자열 변경에 유효</li>
<li>StringBuffer는 멀티 스레드환경에서 동기화를 지원, StringBuilder에 비해 성능이 떨어진다</li>
</ul>
</li>
<li>결론<ul>
<li>String : 문자열 변경이 적은경우</li>
<li>StringBuffer : 문자열 변경이 잦은 멀티 스레드 환경</li>
<li>StringBuilder : 문자열 변경이 잦은 싱글 스레드환경</li>
</ul>
</li>
</ul>
<hr>
<h3 id="제너릭">제너릭</h3>
<p>클래스나 메서드 등의 타입을 지정하지 않고, 외부에서 유동적으로 지정
제너릭을 활용하면 효율적이고 안정적인 프로그래밍 가능</p>
<ul>
<li>용도에 맞는 객체 생성이 가능</li>
<li>타입을 별도로 변환할 필요가 없다</li>
<li>컬렉션 클래스에서 제너릭을 사용해서, 컴파일 과정에서 미리 타입 체크가 가능</li>
</ul>
<hr>
<h3 id="박싱-언박싱">박싱, 언박싱</h3>
<p>자바의 기본 자료형 (Primiticve Type)에는 Wrapper Class가 있습니다
기본 자료형을 객체로 사용하기 위해, 포장하는 클래스가 Wrapper Class
그리고 컬렉션, 제너릭 등에서는 Wrapper Class만 사용가능
기본 자료형을 Wrapper Class로 변경하면 박싱, 반대면 언박싱</p>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/bd380abb-ccd8-4cda-82dd-bf2945eb4d07/image.png" alt=""></p>
<hr>
<h3 id="대용량-트래픽-처리방법">대용량 트래픽 처리방법</h3>
<p>대규모 트래픽 처리의 핵심은 분산입니다
거기에 어플리케이션과 디비, 서버 등의 성능향상도 필수</p>
<ul>
<li>서버분산<ul>
<li>로드 벨런싱 : 스위치를 통해 여러대의 서버로 분산 (온프레미스 환경)</li>
<li>오토 스케일링 : 어플리케이션을 모니터링해서 서버의 용량을 자동으로 저정(클라우드 환경)</li>
</ul>
</li>
<li>서버 성능<ul>
<li>scale up : 서버의 cpu나 메모리등 성능을 향상</li>
<li>scale out : 서버의 대수를 증가</li>
</ul>
</li>
<li>어플리케이션 개선<ul>
<li>뷰나 데이터 등 서비스 기능에 따른 캐싱 설정</li>
<li>코드 품질 개선 및 비효율 프로세스 제거</li>
</ul>
</li>
<li>디비 개선<ul>
<li>레플리카 : Master DB에는 쓰기, Slave DB에는 읽기 기능을 부여해서 분산</li>
<li>디비 정규화, 쿼리 튜닝, 설정 개선</li>
<li>로그나 통계 빅데이터는 NoSQL 활용</li>
</ul>
</li>
<li>파일서버<ul>
<li>Static : Image, JS, CSS 등 정적 파일 별도 서버 구성 (CDN)</li>
<li>Upload : 별도 업로드 서버 구성(CDN)</li>
</ul>
</li>
<li>WEB or WAS 개선<ul>
<li>서버 설정이나 기능 확장을 통해 성능 개선</li>
</ul>
</li>
<li>마이크로 서비스<ul>
<li>RestAPI 시스템을 구축해서 서비스별로 트래픽을 분산</li>
</ul>
</li>
<li>분산 캐시 서버 활용<ul>
<li>Memcached, Redis 등으로 요청 분산</li>
<li>Akamai CDN을 적용해서 캐싱 웹페이지 제공</li>
</ul>
</li>
<li>부하 테스트 정책<ul>
<li>코드나 뭐리 작성후에 일정 수준의 부하 테스트를 통과하지 못하면 배포 금지</li>
<li>TPS(Transaction Per Second)나 응답 시간 등을 기준</li>
</ul>
</li>
</ul>
<hr>
<h3 id="가비지-컬렉터-garbage-collector">가비지 컬렉터 (Garbage Collector)</h3>
<p>자바의 핵심 기능 중에 하나가 바로 JVM을 통한 메모리 관리입니다.</p>
<p>가비지 컬렉션 기능을 통해서 사용하지 않는 메모리 공간을 자동으로 해제합니다
보통의 프로젝트에서는 기본 가비지 컬렉터를 사용합니다.</p>
<p>하지만 기능이나 성능 이슈가 있는 프로젝트는 가비지 컬렉터를 선택할 수 있습니다.
예전의 가비지 컬렉션의 동작 단계는 아래와 같습니다.
이후에 나온 가비지 컬렉터는 다른 방식으로 수행이 됩니다.</p>
<ul>
<li>Mark<ul>
<li>메모리 영역을 스캔하며 사용하지 않는 객체를 식별</li>
</ul>
</li>
<li>Sweep<ul>
<li>사용하지 않는 객체의 메모리를 수거하고, 사용하는 객체만 남겨둔 상테</li>
</ul>
</li>
<li>Compacrion<ul>
<li>사용하는 객체들은 모으는 단계, 메모리 단편화와 오버헤드 방지를 위한 작업</li>
</ul>
</li>
<li>Stop the World<ul>
<li>일시 정지 상태에서 가비지 컬렉션 작업을 진행</li>
</ul>
</li>
</ul>
<h4 id="가비지-컬렉터의-종류">가비지 컬렉터의 종류</h4>
<ul>
<li>Serial GC<ul>
<li>하나의 스레드가 메모리 관리를 순차적으로 수행</li>
<li>메모리와 CPU 리소스가 부족할때 사용</li>
<li>Mark-Sweep-Compaction 단계를 수행</li>
<li>처리 속도가 느리고 Stop-the-world 상태가 길어서 상용 서비스에 비추천</li>
</ul>
</li>
<li>Parallel GC<ul>
<li>멀티코어를 지원하고 여러 스레드에서 수행</li>
<li>Mark-Sweep-Compaction 단계를 여러 스레드에서 빠르게 수행</li>
<li>Stop the World 시간 단축</li>
</ul>
</li>
<li>Parallel Old GC<ul>
<li>Parallel GC 에서 Old 영역의 방식을 차별화</li>
<li>Old 영역은  Mark-Sweep-Compaction 단계를 수행</li>
</ul>
</li>
<li>CMS GC (Concurrent Mark Sweep)<ul>
<li>어플리케이션의 응답 속도가 중요한 경우 사용</li>
<li>중간중간 Stop the world를 해제해서 정지 시간 최소화</li>
<li>다른 GC 방식 보다 메모리와 CPU 사용량 증가</li>
<li>Initial Mark -&gt; Concurrent Mark -&gt; Remark -&gt; Concurrent Sweep</li>
<li>Compaction은 메모리 단편화가 심한 경우에만 수행</li>
</ul>
</li>
<li>G1 GC (Garbage First)<ul>
<li>Java 7부터 사용 가능</li>
<li>대용량 메모리와 멀티코어 환경에서 효율적으로 동작</li>
<li>CMS GC를 대체하기 위한 용도</li>
<li>메모리를 동일 사이즈의 여러 리전으로 구분해서 사용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[주키퍼는 뭘까]]></title>
            <link>https://velog.io/@moon_happy/%EC%A3%BC%ED%82%A4%ED%8D%BC%EB%8A%94-%EB%AD%98%EA%B9%8C</link>
            <guid>https://velog.io/@moon_happy/%EC%A3%BC%ED%82%A4%ED%8D%BC%EB%8A%94-%EB%AD%98%EA%B9%8C</guid>
            <pubDate>Mon, 11 Sep 2023 13:41:32 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/65928e91-b41c-4dc5-aefc-84b7ff3a7bdd/image.png" alt=""></p>
<h2 id="개발배경">개발배경</h2>
<p>분산 시스템에서는 클러스터간의 통신이나 데이터를 처리하는데 있어서 고민이 많이 있었습니다.</p>
<blockquote>
</blockquote>
<h3 id="분산-시스템에서의-고민거리">분산 시스템에서의 고민거리</h3>
<ul>
<li>분산된 시스템 같의 정보를 어떻게 공유할 것인가</li>
<li>클러스터에 있는 서버들의 상태를 어떻게 체크할 것인가</li>
<li>분산된 서버들 간에 동기화를 위해 잠금(Lock)을 어떻게 처리할 것인가 </li>
</ul>
<p>이러한 고민과 분산 시스템을 처리해주고 관리의 필요성이 생겼습니다.</p>
<p>분산된 서버들끼리 통신할 때 리소스를 공유하려다 보면 자원 점유 문제가 발생하는데, 이를 처리하기 위한 대표적인 해결책으로 리소스 락을 볼 수 있습니다. 이 리소스는 Lock, Unlock하는데도 관리해주는 시스템이 필요합니다.</p>
<p>코디네이션 서비스는 분산 시스템 내에서 중요한 상태 정보나 설정 정보 등을 유지하기 때문에 코디네이션 시스템의 장애는 전체 시스템 장애로 이어지는 장애 전파 특성이 있습니다.</p>
<p>따라서 고가용성을 제공하는 것이 필수입니다. </p>
<hr>
<h2 id="🧸-주키퍼란">🧸 주키퍼란</h2>
<h3 id="분산-코디네이션-서비스">분산 코디네이션 서비스</h3>
<p>다수의 노드에서 수행되는 분산 처리 어플리케이션은 단일 노드에서 수행되는 어플리케이션보다 매우 고려해야할 요소가 많은데, 그 중 가장 주요한 것은 <strong>부분 실패(Partial Failure)</strong>다.</p>
<p>한 노드 안에서 프로그램이 수행될 때는 걱정하지 않아도 될 요소인 네크워크를 통해서 메시지가 전송되는 부분이 종종 문제가 된다. 특히 메세지를 전송하고 네트워크가 끊겼을 때 송신자는 수신자가 메세지를 성공적으로 수신했는지조차 알 수 없게 된다. 어쩌면 메시지를 받고 처리를 하고 나서 응답을 못준 것일 수도 있고, 메세지 전송 자체가 실패된 것일 수도 있다. 작업이 성공한 것인지 실패한 것인지 여부조차 알 수 없는 것이다.</p>
<p>주키퍼는 이러한 <strong>부분 실패를 안전하게 처리하기 위한 분산 처리 도구를 제공</strong>한다.</p>
<h3 id="주키퍼의-3가지-특징">주키퍼의 3가지 특징</h3>
<ul>
<li><strong>클러스터링</strong> : 주키퍼는 홀수로 구성된 클러스터로 구성합니다.클러스터의 과반수 이상이 정상적으로 동작하면, 주키퍼는 정상적으로 작동합니다.</li>
<li><strong>데이터베이스</strong> : 주키퍼는 키-값 기반의 데이터베이스를 제공합니다. 주키퍼는 데이터베이스를 사용하여 분산 시스템의 구성, 동기화, 상태 관리등을 수행합니다. </li>
<li><strong>복제</strong> : 주키퍼는 데이터베이스의 모든 데이터를 복제합니다. 따라서, 주키퍼 클러스터의 일부 서버가 장애가 발생하더라고, 데이터의 손실 없이 시스템을 유지할 수 있습니다.</li>
</ul>
<p>이러한 특징으로 유명한 분산 솔루션에서 많이 사용합니다.</p>
<ul>
<li>Kafka</li>
<li>HBase(NoSQL)<br>

</li>
</ul>
<p>분산 시스템을 코디네이션하는 용도로 사용하기 위해서는 다음과 같은 사항을 고려해야 합니다.</p>
<ul>
<li>Data Access가 빨라야합니다.</li>
<li>자체적으로 장애 대응이 필요합니다.</li>
</ul>
<h2 id="🦆-장점">🦆 장점</h2>
<p>주키퍼는 클러스터링 기능을 자체적으로 지원하며, 이러한 코디네이션 서비스 시스템에 있어서 아주 쉽게 적용이 가능하다는 장점이 있으며 기능은 간단합니다.</p>
<ul>
<li><p>설정관리
클러스터의 설정 정보를 최신으로 유지하기 위한 시스템</p>
</li>
<li><p>클러스터 관리
클러스터의 서버가 추가되거나 제외될 때 그 정보를 클러스터 내 서버들이 공유하기 위한 시스템입니다.</p>
</li>
<li><p>리더 채택
다중 어플리케이션 주 어떤 노드를 리더로 산출할 지 정하는 로직을 만듭니다.</p>
</li>
<li><p>락, 동기화
클러스터에서 쓰기 연산이 빈번할 경우 클러스터 전체를 동기화를 통해 데이터 불일치를 방지합니다.</p>
</li>
</ul>
<p>분산 시스템에서 어떤 노드에게 연산을 시킬지 결정하는 것도 하나의 역할이라고 볼 수 있습니다. 여러 노드들 중 유휴 상태인 노드를 찾는 로직을 어떤식으로 할지 정하는 리더 채택이 그 역할을 합니다.</p>
<hr>
<h2 id="🎈-주키피의-구조">🎈 주키피의 구조</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/ae4dc3eb-164b-45a3-80ee-057fae0abba7/image.png" alt=""></p>
<h3 id="구성">구성</h3>
<ol>
<li><p>Request Processor : Write 요청 처리</p>
</li>
<li><p>Zab (Zookeeper Atomic Broadcast Protocol) : Request Processor에서 처리한 요청을 트랜잭션을 생성하여 모든 서버에게 전파한다. [Leader-Propose] -&gt; [Follower-Accept] -&gt; [Leader-Commit] 단계로 구성된다.</p>
</li>
<li><p>In-memory DB : Znode의 정보가 저장되며, 로컬 파일시스템에 Replication을 구성할 수 있다.</p>
</li>
</ol>
<br>


<p>코디네이션 서비스 시스템은 분산 시스템의 일부분이 되어 동작하기 때문에 앞서 말한 것처럼 코디네이션 시스템이 중단되면 분산 시스템도 중단되는 장애 전파가 발생하게 됩니다.</p>
<p>Zookeeper는 안정성을 확보하기 위해 다수의 Server를 사용하는 서버 클러스터 구조를 이용합니다. 이는 k8s와 유사한 구조로 서버 클러스터는 1개의 Leader와 N개의 Follower로 구성되어 있고, 이를 주키퍼 앙상블(Zookeeper Ensemble)이라고도 합니다.</p>
<p>순서는 Client(여기서는 Kafka)가 주키퍼 서버들로 이뤄진 앙상블(Ensemble)에 접근하여 Znode의 데이터를 읽거나 데이터를 업데이트합니다. 앙상블 내 주키퍼 서버들은 조율된 상태이고, 항상 동일한 데이터를 가지고 있어 어느 서버에서 데이터를 읽어도 같은 데이터로 불러오게 됩니다.</p>
<p>Client(Kafka)가 어떤 설정값 혹은 메타데이터를 주키퍼에 쓸 때 아래와 같이 동작합니다.</p>
<ul>
<li>특정 서버에 접속하여 서버 데이터 업데이트</li>
<li>해당 서버는 Leader 서버에 데이터가 업데이트 되었음을 전송</li>
<li>Leader 서버는 업데이트 신호를 받고, 다른 Follower 서버들에게 브로드캐스트(Broadcast) 형식으로 전송</li>
<li>나머지 Follower 서버들도 데이터 업데이트</li>
</ul>
<p>위 4가지 과정을 통해 주키퍼는 데이터를 항상 일관성 있게 유지하도록 합니다.</p>
<hr>
<h2 id="🥂-주키퍼-데이터-모델znode">🥂 주키퍼 데이터 모델(Znode)</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/c20e37f3-f42b-4c3d-82b8-cc6d410b42d6/image.jpeg" alt=""></p>
<p> 상태 정보들은 주키퍼의 지노드(znode)라고 불리는 곳에 Key-Value 형태로 저장하며, 지노드에 저장된 것을 이용하여 분산 어플리케이션들은 서로 데이터를 주고받게 된다.</p>
<p>Znode를 일반 컴퓨터의 파일이나 폴더 개념으로 생각하면 쉽습니다.</p>
<p>지노드(Znode)는 우리가 알고 있는 일반적인 디렉토리와 비슷한 형태로서 자식노드를 가지고 있는 계층형 구조로 구성되어 있다.</p>
<hr>
<h2 id="🗳️-투표하다quorum">🗳️ 투표하다(Quorum)</h2>
<p>Leader가 새로운 트랜잭션을 수행하기 위해서는 자신을 포함하여 과반수 이상의 서버의 합의를 얻어야 한다. </p>
<p>주키퍼는 3대 혹은 5대 이상의 홀수로 구성하는데, 그 이유는 Quorum 기반 알고리즘으로 이루어져 있기 때문이다.</p>
<p>여기서 쿼럼은 다른말로 &quot;정족수&quot;라고 번역이 되는데, 어떤 의사 결정을 하는 합의체(주키퍼 앙상블)이 뭔가에 대한 의사를 체결하기 위한 최소한의 인원수를 뜻한다. (과반수 이상이 필요한것) </p>
<p>그 이유는 분산 코디네이션 환경에서 예상치 못한 장애가 발생하더라도 분산 시스템의 일관성을 유지시키기 위해서 사용한다.</p>
<h3 id="예시">예시</h3>
<p>앙상블이 주키퍼 서버 3대로 구성이 되어 있다면 쿼럼은 2 (과반수 이상)이 되기 때문에 주키퍼 장비가 1대가 장애가 생겨도 정상 동작</p>
<p>앙상블이 주키퍼 서버 5대로 구성이 되어 있다면 쿼럼은 3 (과반수 이상)이 되기 때문에 주키퍼 장비가 2대가 장애가 생겨도 정상 동작</p>
<p>즉,  홀수로 주키퍼 서버로 구성하는 이유는 3대를 쓰나 4대를 쓰나 과반수 이상이 되는것은 한대로 동일하기 때문에 홀수개의 서버로 구성한다.</p>
<hr>
<h2 id="🦦-kafka에서의-주키퍼는">🦦 Kafka에서의 주키퍼는</h2>
<p>우리가 분산 시스템에 반드시 필요로 하는 것이 코디네이터 서비스 시스템이라는 것을 알았고, 그 대표적인 것이 주키퍼라는 것을 알았습니다. 그렇다면 카프카에서 주키퍼는 어떤 용도로 사용될까요? </p>
<p>카프카의 주키퍼 클라이언트는 카프카의 브로커를 관리하고 조정하는 데 사용합니다. </p>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/673fe22f-862c-4e7a-b916-2133213fc7a9/image.png" alt="">
카프카는 메세지를 주고 받는 Pub/Sub 외에는 아무것도 하지않는 분산 처리 플랫폼입니다.
따라서 브로커 상태를 저장하지 않기 때문에 <strong>상태 관리를 위해서만</strong> 주키퍼를 사용합니다.</p>
<p>이 때 Producer와 Consumer는 카프카의 브로커 정보를 가지고 있습니다. 만약 동적으로 브로커의 상태가 변경(스케일 아웃 되는 등)되는 경우 이를 주키퍼가 Producer와 Consumer에게 알려줍니다.</p>
<p>일반적으로 카프카 메시지 브로커와 Zookeeper는 1:1로 구성되며 만약 Producer가 특정 카프카 브로커로 메시지를 생산했을 때 이를 실패하면 주키퍼가 다른 정상 서버로 Producer와 Consumer에게 브로커를 알리는 방식으로 운영됩니다.</p>
<p>🔗
<a href="https://zookeeper.apache.org/doc/r3.1.2/zookeeperOver.html">https://zookeeper.apache.org/doc/r3.1.2/zookeeperOver.html</a>
<a href="https://xangmin.tistory.com/169">https://xangmin.tistory.com/169</a>
<a href="https://dreamcoding.tistory.com/88">https://dreamcoding.tistory.com/88</a>
<a href="https://blog.neonkid.xyz/302">https://blog.neonkid.xyz/302</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[로그파이프라인 (카프카 클러스터 구축)]]></title>
            <link>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EC%B9%B4%ED%94%84%EC%B9%B4-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EC%B9%B4%ED%94%84%EC%B9%B4-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Mon, 11 Sep 2023 08:54:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/17b610dc-6f44-4f10-94ba-0dc62966ea2f/image.png" alt="">
이제 Logstash가 보낸 로그를 카프카의 원하는 토픽으로 가게 됩니다.
카프카는 실제 인스턴스에 하나씩 카프카를 설치해서 클러스터를 구성하는게 맞지만 
서비스의 규모와 비용을 생각해서 docker-compose를 통해서 클러스터를 구축하였습니다.</p>
<p>카프카에 대한 설명은 저의 블로그에 정리를 했습니다.</p>
<blockquote>
</blockquote>
<p>🔗 
카프카 개념 : <a href="https://velog.io/@moon_happy/Kafka%EB%8A%94-%EB%AD%90%EB%9E%8C">https://velog.io/@moon_happy/Kafka%EB%8A%94-%EB%AD%90%EB%9E%8C</a>
주키퍼 개념 : </p>
<h2 id="클러스터-구성-docker-compose">클러스터 구성 (docker-compose)</h2>
<pre><code class="language-python">version: &#39;3.7&#39;
services:

  zk1:
    container_name: zookeeper1
    image: wurstmeister/zookeeper:latest
    restart: always
    hostname: zk1
    ports:
      - &quot;2181:2181&quot;
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181
    volumes:
      - &quot;~/zk-cluster/zk1/data:/data&quot;

  zk2:
    container_name: zookeeper2
    image: wurstmeister/zookeeper:latest
    restart: always
    hostname: zk2
    ports:
      - &quot;2182:2181&quot;
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181
    volumes:
      - &quot;~/zk-cluster/zk2/data:/data&quot;

  zk3:
    container_name: zookeeper3
    image: wurstmeister/zookeeper:latest
    restart: always
    hostname: zk3
    ports:
      - &quot;2183:2181&quot;
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zk1:2888:3888;2181 server.2=zk2:2888:3888;2181 server.3=zk3:2888:3888;2181
    volumes:
      - &quot;~/zk-cluster/zk3/data:/data&quot;

  kafka1:
    container_name: kafka1
    image: wurstmeister/kafka:latest
    restart: on-failure
    depends_on:
      - zk1
      - zk2
      - zk3
    ports:
      - &quot;9092:9092&quot;
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ADVERTISED_HOST_NAME: IP
      BOOTSTRAP_SERVERS: IP:9092,IP:9093, IP:9094
      KAFKA_ZOOKEEPER_CONNECT: &quot;zk1:2181,zk2:2182,zk3:2183&quot;
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2

  kafka2:
    container_name: kafka2
    image: wurstmeister/kafka:latest
    restart: on-failure
    depends_on:
      - zk1
      - zk2
      - zk3
    ports:
      - &quot;9093:9092&quot;
    volumes:
       - /var/run/docker.sock:/var/run/docker.sock
    environment:
      KAFKA_BROKER_ID: 2
      KAFKA_ADVERTISED_HOST_NAME: IP
      BOOTSTRAP_SERVERS: IP:9092, IP:9093, IP:9094
      KAFKA_ZOOKEEPER_CONNECT: &quot;zk1:2181,zk2:2182,zk3:2183&quot;
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2

  kafka3:
    container_name: kafka3
    image: wurstmeister/kafka:latest
    restart: on-failure
    depends_on:
      - zk1
      - zk2
      - zk3
    ports:
      - &quot;9094:9092&quot;
    volumes:
       - /var/run/docker.sock:/var/run/docker.sock
    environment:
      KAFKA_BROKER_ID: 3
      KAFKA_ADVERTISED_HOST_NAME: IP
      BOOTSTRAP_SERVERS: IP:9092, IP:9093, IP:9094
      KAFKA_ZOOKEEPER_CONNECT: &quot;zk1:2181,zk2:2182,zk3:2183&quot;
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 2

  kafka-ui:
    image: provectuslabs/kafka-ui
    container_name: kafka-ui
    ports:
      - &quot;10000:8080&quot;
    restart: always
    environment:
      - KAFKA_CLUSTERS_0_NAME=local
      - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=:IP:9092,IP:9093,IP:9094
      - KAFKA_CLUSTERS_0_ZOOKEEPER=zk1:2181,zk2:2182,zk1:2183</code></pre>
<h3 id="⚙️-주키퍼">⚙️ 주키퍼</h3>
<p>주키퍼는 3개로 클러스터를 구성하였습니다.
주키퍼는 분산 시스템에서 사용되는 오픈소스 서비스로, Kafka에서 메타데이터를 관리하는데 사용됩니다.</p>
<p>각각의 주키퍼는 고유한 ID(ZOO_MY_ID)와 다른 인스턴스들에 대한 정보(ZOO_SERVERS)를 가지며, 별도의 포트(2181~2183)에서 실행됩니다.</p>
<h3 id="⚙️-카프카">⚙️ 카프카</h3>
<p>카프카 브로커는 메세지를 받아서 저장하고 전달하는 역할을 합니다.
여기서도 3개의 컨테이너를 브로커로 생성하고 고가용성을 확보했습니다.</p>
<h3 id="⚙️-카프카-ui">⚙️ 카프카 UI</h3>
<p>웹 기반 인터페이싱으로 카프카 클러스터 상태를 모니터링하고 메시지 데이터 등을 조회할 수 있습니다.</p>
<hr>
<h2 id="🤔-토픽-생성">🤔 토픽 생성</h2>
<p>저는 토픽을 2개로 하고 파티션은 3개 복제계수는 3개로 모든 브로커에 적재될 수 있도록 구성하였습니다.</p>
<ul>
<li><p>user2 : 모든 로그가 향하고 컨슈머를 통해서 BigQuery로 향합니다.
BigQuery에서는 분석가가 분석을하고 모델을 만드는 데이터마트의 역할을 하게됩니다.</p>
</li>
<li><p>user3 : Logstash에서 모든 로그중에서 info라는 Key에서 value가 <code>search</code>또는 <code>movie_detail</code>이면 user3로 오게됩니다. 
이 토픽에 들어온 메세지들은 컨슈머를 통해서 Redis로 가며, Redis에서 집계와 사용자의 기록을 빠르게 보여주기위해서 구축하였습니다.</p>
</li>
</ul>
<h3 id="🤔-2개로-구성한-이유">🤔 2개로 구성한 이유</h3>
<p>일반적으로, Kafka를 사용할 때는 Java를 통해 컨슈머를 구현하고, 하나의 토픽을 생성하여 여기에 파티션을 만들어 컨슈머를 분리합니다. 이렇게 하면 메시지의 순서를 보장하면서도 병렬 처리의 장점을 활용할 수 있습니다.</p>
<p>그런데 이 선택은 새로운 도전과 고민을 가져왔습니다. 
Python은 GIL(Global Interpreter Lock) 때문에 멀티스레딩이 제한적이며, 일반적으로 싱글 스레드 환경에서 가장 잘 동작합니다. </p>
<p>따라서 Java와 같은 높은 처리량과 낮은 지연 시간을 구현하기 위해서 목적지가 다르게 토픽을 2개로 만들고 2개의 컨슈머를 만들어 하나의 토픽만 집중할 수 있었으며 싱글스레딩 문제를 해결하였습니다.</p>
<p>하지만 이렇게 했을때 메세지들의 순서는 보장되지 않습니다.</p>
<h3 id="🤔-순서를-보장하지-않은-이유">🤔 순서를 보장하지 않은 이유</h3>
<blockquote>
</blockquote>
<p>프로듀서의 역할을 하는 Logstash에서 브로커에 메세지를 전달할때 
파티션을 지정하지 않았기 때문에 라운드 로빈방식으로 3개의 파티션에 균등하게 적재됩니다. </p>
<blockquote>
</blockquote>
<p>이렇게 되면 같은 시간에 전송된 메시지라도 서로 다른 파티션에 저장될 수 있습니다. 
이 경우, offset 기준으로 메시지를 가져오는 컨슈머는 파티션 간 메시지 순서를 알 수 없습니다.</p>
<p><em><strong>하지만 순서를 보장하지 않은 이유는 순서가 상관이 없기 때문입니다.</strong></em></p>
<blockquote>
</blockquote>
<p>메세지 순서를 보장하기 위한 방법</p>
<ul>
<li>메시지에 키를 지정하여 파티셔너를 통해 메시지를 적절한 파티션으로 분배합니다. </li>
<li>단일 파티션으로 토픽을 생성합니다.</li>
</ul>
<p>만약 티켓팅이나 품절이 빠른 쇼핑몰이라면 순서가 매우 중요하기 때문에 순서를 보장해야하지만 </p>
<p>요번 프로젝트에서 로그를 수집하는 목적은 2가지 였습니다.</p>
<ol>
<li>들어온 로그를 통해서 집계</li>
<li>들어온 로그를 통해서 사용자들의 행동을 분석하고 추천</li>
</ol>
<p>그렇기 때문에 순서를 보장하지 않았습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[로그파이프라인(로그를 Logstash로)]]></title>
            <link>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EB%A1%9C%EA%B7%B8%EB%A5%BC-Logstash%EB%A1%9C</link>
            <guid>https://velog.io/@moon_happy/%EB%A1%9C%EA%B7%B8%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8%EB%A1%9C%EA%B7%B8%EB%A5%BC-Logstash%EB%A1%9C</guid>
            <pubDate>Mon, 11 Sep 2023 07:21:24 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/83463cbb-60e4-4aca-b07d-b3f0b6a8a062/image.png" alt=""></p>
<p>앞 포스팅에서 설명했듯이 로그가 파일의 형식으로 남게 됩니다.
이렇게 생성된 로그를 Logstash가 가져가 알맞은 형태로 맞추고 원하는 곳으로 output하게 됩니다.</p>
<p>Logstash에 관한 설명은 다음에 올리겠습니다.</p>
<p>Logstash에는 3가지의 단계로 구성이 됩니다.</p>
<ol>
<li>input : 로그 또는 이벤트 데이터를 수집하는 부분입니다.</li>
<li>filter : 수집된 데이터를 처리하고 변환하는 부분입니다. </li>
<li>output : 처리된 데이터를 전송하는 부분입니다. </li>
</ol>
<p>Logstash를 사용하게 된 이유는 분석가의 역할을하는 팀원이 어떤툴로 분석을 진행할지 정해지지 않은 상태였기 때문입니다. </p>
<ul>
<li>BigQuery에 적재하면 BigQuery ML을 통해서 분석</li>
<li>ELK stack을 통해서 분석 </li>
</ul>
<p>그러면서 input과 output에는 다양한 플러그인을 지원하면서 유연하게 툴을 변경이 가능하다는 장점이 있었고, filter 플러그인을 사용하여 데이터 파싱, 필드 추가 및 제거, 변환 등 다양한 작업이 가능하여 Logstash를 사용하게 되었습니다.</p>
<h2 id="🗒️-logstashconf">🗒️ Logstash.conf</h2>
<pre><code class="language-python">input {
  file {
    path =&gt; &quot;파일 경로&quot;
    start_position =&gt; &quot;end&quot;
    sincedb_path =&gt; &quot;마지막 위치를 기록하는 파일의 경로&quot;
  }
}

filter {
  grok {
    match =&gt; { &quot;message&quot; =&gt; &quot;INFO,%{TIMESTAMP_ISO8601:log_timestamp},%{INT:user_id:int},%{DATA:action_data},%{GREEDYDATA:info}&quot; } 
  }

  mutate {
    remove_field =&gt; [ &quot;message&quot;, &quot;log&quot;, &quot;event&quot;, &quot;@version&quot;, &quot;host&quot;, &quot;movie_rating&quot;, &quot;@timestamp&quot; ]
  }
}

output {

  kafka {
    codec =&gt; json
    bootstrap_servers =&gt; &quot;브로커들의 IP와 PORT&quot;
    topic_id =&gt; &quot;토픽 이름&quot;
  }

  if &quot;search&quot; in [info] or &quot;movie_detail&quot; in [info] {
    kafka {
      codec =&gt; json
      bootstrap_servers =&gt; &quot;브로커들의 IP와 PORT&quot;
      topic_id =&gt; &quot;토픽 이름&quot;
    }
  }
}</code></pre>
<h3 id="🦤-input">🦤 Input</h3>
<ul>
<li>input부분에서는 Django에서 생성되는 모든 로그파일에서 input되게 됩니다.</li>
</ul>
<p>input의 형태를 file로 지정하고 파일의 경로와 <code>start_position</code>을 통해서 파일의 처음부터 할건지 아니면 마지막부터 할건지 정해야 합니다.
저는 서비스를 시작과 동시에 Logstash를 구동했기 때문에 end로 하였습니다.</p>
<p>TCP나 UDP로 하지않고 file로 한 이유는 로그파일을 10개가 넘어가게 된다면 삭제가 아닌 구글 스토리지로 가게되면서 로그파일을 장기적으로 보관하고 분석을 하기위해서 file로 로그파일을 남기면서 그것을 바로 가져오게 했습니다.</p>
<p>sincedb_path 부분은 파일에서 어디까지 읽었는지 추적하여 로그 데이터의 중복 처리를 방지하는 데 사용합니다.
그러면서 Logstash를 재시작하면 이전에 읽었던 위치에서 계속해서 로그를 읽을수 있습니다.</p>
<h3 id="🦤-filter">🦤 Filter</h3>
<ul>
<li>filter 부분에서는 로그 데이터를 분석하고 변환하는 작업이 이루어집니다.</li>
</ul>
<h4 id="grok">grok</h4>
<p>Grok은 원시 텍스트 데이터를 구조화된 데이터로 변환하기 위해 사용됩니다.</p>
<p>Grok 패턴은 %{SYNTAX:SEMANTIC} 형식으로 되어 있으며, SYNTAX 부분에는 정규표현식 이름이 들어가고 SEMANTIC 부분에는 해당 정규표현식에 일치하는 값이 할당될 필드 이름이 들어갑니다. </p>
<p>위 설정에서는 message 필드의 값을 분석하여 log_timestamp, user_id, action_data, info라는 네 개의 필드로 분리하고 있습니다.</p>
<h4 id="mutate">mutate</h4>
<p>Mutate를 사용해서 특정 필드를 추가하거나 삭제하는 등의 작업을 할 수 있습니다.
저는 remove_field를 통해서 output에서 stdout에 나왔던 필요없는 부분을 제거하였습니다.</p>
<h3 id="🦤-output">🦤 Output</h3>
<p>output은 메세지 큐를 미들웨어로 사용해서 다양한 데이터베이스나 스토리지로 로그데이터를 적재하는것을 목표로 하였습니다.
그중 카프카를 사용해서 가용성과 안정성을 높이는 결정을 하였습니다.</p>
<ul>
<li>모든 로그는 json형태로 user2라는 토픽으로 가게됩니다. </li>
<li>그 중 info라는 key에 value가 search 또는 movie_detail 이라면 user3 토픽으로 가게됩니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MQ ( 정의와 메세지브로커)]]></title>
            <link>https://velog.io/@moon_happy/MQ-%EC%A0%95%EC%9D%98%EC%99%80-%EB%A9%94%EC%84%B8%EC%A7%80%EB%B8%8C%EB%A1%9C%EC%BB%A4</link>
            <guid>https://velog.io/@moon_happy/MQ-%EC%A0%95%EC%9D%98%EC%99%80-%EB%A9%94%EC%84%B8%EC%A7%80%EB%B8%8C%EB%A1%9C%EC%BB%A4</guid>
            <pubDate>Sun, 10 Sep 2023 07:42:23 GMT</pubDate>
            <description><![CDATA[<p>카프카를 공부하면서 메세지큐의 정의를 공부하다가 메세지브로커와 이벤트브로커로 나뉜다는것을 알았습니다.
그러면서 프로젝트를 진행하면서 어떤 메세지큐를 써야할지 고민하면서 공부했던 내용을 작성합니다.</p>
<h2 id="🦧-메세지-큐">🦧 메세지 큐</h2>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/c78c732a-ce6d-482e-a8fb-c3f4cd215ab4/image.png" alt=""></p>
<p>RabbitMQ, Redis, Kafka 같은 기술을 메시지 플랫폼이라고 한다.</p>
<p>메시지 플랫폼은 2가지 종류로 나뉘어진다.</p>
<ol>
<li>메시지 브로커</li>
<li>이벤트 브로커</li>
</ol>
<p>Kafka와 RabbitMQ는 모두 메세지 큐 안에서 정의가 됩니다.</p>
<h3 id="메세지-큐">메세지 큐</h3>
<p>메시지 큐는 메시지 기반의 통신 프로토콜에서 사용되는 방식으로, 프로세스나 스레드 간에 메시지를 교환하는데 사용됩니다. 이러한 메시지 큐는 비동기적인 통신을 가능하게 하며, 시스템 간의 결합도를 낮추고 확장성을 높이는데 도움이 됩니다.</p>
<h3 id="구성">구성</h3>
<ul>
<li>프로듀서 : 메세지를 생성하고 보내는 역할을 합니다.</li>
<li>큐 : 메세지를 저장하는 저장소의 개념으로 대기하는 공간입니다. 일반적으로 FIFO으로 처리됩니다.</li>
<li>컨슈머 : 큐에서 메세지를 가져와 소비하는 역할을 합니다.</li>
</ul>
<h3 id="작동-패턴">작동 패턴</h3>
<h4 id="1️⃣-point-to-point-p2p">1️⃣ Point-to-Point (P2P)</h4>
<ul>
<li>각 메시지가 하나의 컨슈머에게 전달됩니다.</li>
<li>만약 여러 컨슈머가 있으면, 그들 중 하나만 해당 메시지를 받게 됩니다.</li>
<li>JMS (Java Message Service) API에서 지원하는 Queue가 이 패턴에 해당합니다.</li>
</ul>
<h4 id="2️⃣publishsubscribe-pubsub">2️⃣Publish/Subscribe (Pub/Sub)</h4>
<ul>
<li>발행된 모든 메시징이 모든 구독자에게 전달됩니다.</li>
<li>한 번 발행된 메세징은 여러 컨슈머에게 동일하게 전달될 수 있습니다.</li>
<li>JMS API에서 지원하는 Topic이 이 패턴에 해당합니다.</li>
</ul>
<blockquote>
<h3 id="장점">장점</h3>
</blockquote>
<ol>
<li><strong>비동기 처리:</strong> 비동기적으로 데이터를 전달할 수 있습니다. 이는 서비스가 다른 서비스의 처리를 기다리지 않아도 됩니다.</li>
<li>*<em>분산처리 : *</em> 메시지 큐는 여러 컨슈머가 동일한 큐에서 작업을 가져와 동시에 처리할 수 있도록 지원합니다.</li>
<li><strong>탄력성:</strong> 메시지 큐는 프로듀서와 컨슈머 사이의 중간 계층 역할을 하므로, 한쪽이 실패해도 전체 시스템에 영향을 미치는 것을 최소화합니다.</li>
<li><strong>메세징 보증:</strong> &quot;At least once&quot; 또는 &quot;Exactly once&quot; 같은 메세징 전달 보증 방식을 제공하면서 메세징이 정확하게 전달되거나 소실되거나 중복될 가능성 없이 안전하게 처리됩니다.</li>
<li><strong>순서 보장:</strong> 일부 메세징 시스템(예: Apache Kafka)은 특정 조건 하에서 메세징 순서를 보장하는 기능을 제공합니다.</li>
<li><strong>디커플링 (Decoupling):</strong> 프로듀서와 컨슈머 사이에 의존성 없이 개발 및 운영 가능함으로써 유연한 아키텍처 설계가 가능합니다.</li>
<li><strong>백로그 관리</strong>: 만약 소비자가 일정량 이상의 데이터 처리에 문제가 생겼다면, 해당 데이터들은 자동으로 Queue 내부에 저장되어 나중에 다시 처리될 수 있습니다.</li>
</ol>
<hr>
<h2 id="🦧-메세지브로커">🦧 메세지브로커</h2>
<ul>
<li>메시지를 받아서 처리하면 메세지가 삭제됩니다.</li>
<li>손실되면 안되는 요청을 처리할 때에는 주의해야합니다.</li>
</ul>
<p>대표적인 메세지 브로커는 RabbitMQ가 있습니다.</p>
<h3 id="rabbitmq">RabbitMQ</h3>
<ul>
<li><strong>RabbitMQ</strong>는 <strong>AMQP 프로토콜</strong>을 구현한 메시지 브로커이다</li>
<li>구성이 쉽고 안정적입니다.</li>
<li>프로젝트의 규모가 작고 확장의 계획이 없다면 RabbitMQ가 적당하다.</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li><strong>AMQP 프로토콜</strong>
Client와 Middleware broker간의 메시지를 주고받기 위한 프로토콜</li>
</ul>
<h4 id="🦦-구성">🦦 구성</h4>
<ul>
<li>생산자(Producer) : 요청을 보내는 역할을 합니다</li>
<li>소비자(Consumer) : Producer로부터 메세지를 받아 처리하는 역할을 합니다</li>
<li>exchange : 메세지를 전달하고자 하는 목적지(큐)에 전달하는 역할을 합니다</li>
<li>큐(queue) : 메세지를 쌓는 역할을 합니다</li>
</ul>
<blockquote>
</blockquote>
<p>카프카와 다른점은 바로 queue로 들어가기 전, exchange라는 하나의 단계를 더 거친다는 것입니다.
RabbitMQ에서 메시지는 곧바로 queue에 들어가지 않고 exchage에게 전달하면 exchange가 queue에 메시지를 넣는 역할을 수행한다.</p>
<blockquote>
</blockquote>
<h4 id="🦦-rabbitmq는-amqp를-구현합니다">🦦 RabbitMQ는 AMQP를 구현합니다.</h4>
<p>AMQP(Advanced Message Queuing Protocol, 어드밴스트 메시지 큐잉 프로토콜)는 메시지 지향 미들웨어를 위한 개방형 표준 응용 계층 프로토콜입니다.</p>
<h4 id="🦦-차별점">🦦 차별점</h4>
<ol>
<li>Broker 중심적인 형태로 publisher와 consumer간의 보장되는 메시지 전달에 초점</li>
<li>클러스터 구성이 쉽고 Manage UI가 제공되며 플러그인도 제공되어 확장성 뛰어남</li>
<li>데이터 처리보단, 관리적 측면이나 다양한 기능 구현을 위한 서비스를 구축할 때 사용</li>
</ol>
<hr>
<h2 id="🦧-이벤트브로커">🦧 이벤트브로커</h2>
<ul>
<li>메시지 브로커와 다르게 이벤트가 삭제되지 않는다는 특징이 있다.</li>
<li>서비스에서 발생하는 이벤트를 DB에 저장하듯이 이벤트 브로커의 큐에 저장한다.</li>
</ul>
<p>대표적인 이벤트브로커로 Kafka가 있습니다.</p>
<h3 id="kafka">Kafka</h3>
<ul>
<li>오픈 소스 프로젝트로 운영되고 있는 분산 이벤트 스트리밍 플랫폼입니다.</li>
<li>이벤트 브로커의 역할을 수행하며, 대용량 데이터를 실시간으로 신뢰성 있게 처리하도록 설계되었습니다.</li>
<li>대부분 3개 이상의 브로커로 클러스터를 구축하며 주키퍼와 함께 구축한다.</li>
<li>서비스의 규모가 크고 규모를 확장할 계획이 있다면 Kafka가 적합하다.</li>
</ul>
<blockquote>
</blockquote>
<p>위의 특징들 때문에 로그 수집, 실시간 분석, 스트림 처리 등 다양한 분야에서 활용되며, 복잡한 분산 시스템에서도 고성능과 확장성을 유지할 수 있습니다.</p>
<h4 id="🦦-구성-1">🦦 구성</h4>
<ul>
<li>Producer: 데이터를 생성하여 브로커에 데이터를 적재합니다.</li>
<li>Consumer: 브로커에서 데이터를 가져와 소비합니다.</li>
<li>Broker: Kafka 시스템에서 서버를 말하고, 메시지(또는 이벤트)를 저장하고 전달합니다.</li>
<li>Topic: 메시지가 저장되는 카테고리 또는 버킷입니다. 각 토픽은 하나 이상의 파티션으로 나뉘어집니다.</li>
<li>Partition: 토픽을 나누는 하위 단위로, 각 파티션 내에서 메시지 순서가 보장됩니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kafka는 뭐람]]></title>
            <link>https://velog.io/@moon_happy/Kafka%EB%8A%94-%EB%AD%90%EB%9E%8C</link>
            <guid>https://velog.io/@moon_happy/Kafka%EB%8A%94-%EB%AD%90%EB%9E%8C</guid>
            <pubDate>Sat, 09 Sep 2023 07:38:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/moon_happy/post/76d56fcf-f6da-4c1d-831e-88a421be06bc/image.png" alt=""></p>
<p>프로젝트를 진행하면서 카프카를 처음공부하고 적용해보면서 흥미로웠습니다.
배울때는 유튜브에 데브원영님이 완전 상세하고 친절하게 설명해주셔서 어렵지는 않았습니다.
🔗 <a href="https://www.youtube.com/channel/UCPdTFQUHzAzFobngtw1sFKg">https://www.youtube.com/channel/UCPdTFQUHzAzFobngtw1sFKg</a></p>
<h2 id="🦦-개발배경">🦦 개발배경</h2>
<p>처음에는 소스어플리케이션과 타겟어플리케이션이 단방향으로 많이 진행이 되었습니다.
하지만 소스어플리케이션과 타겟어플리케이션이 증가하면서 데이터들을 전송하는 라인이 많아지면서 복잡해져
관리가 필요했습니다.</p>
<ul>
<li>데이터의 전송라인이 많아지면 배포와 장애에 대응이 어렵다</li>
<li>데이터를 전송할때 프로토콜과 포멧의 파편화가 심해졌습니다. → 추후 포멧의 변경시 유지보수에 어려움
<img src="https://velog.velcdn.com/images/moon_happy/post/147ba54a-cf5a-4266-870d-f1b7e192d523/image.png" alt=""></li>
</ul>
<p>위와같은 이유로 카프카가 개발되었습니다. 
즉, 소스어플리케이션과 타겟어플리케이션의 커플링을 약하게 하기 위해서 나왔습니다.</p>
<h2 id="🧑💻-카프카란">🧑‍💻 카프카란</h2>
<p>Apache Kafka는 실시간 데이터 스트림 처리를 위한 오픈소스 플랫폼입니다. LinkedIn에서 개발되었습니다.</p>
<p>카프카에는 크게 5가지의 기능을 제공합니다.</p>
<ol>
<li><p><strong>Publish-Subscribe</strong> 모델: Kafka는 메시지를 주제(topic)별로 분류하고, 생산자(producer)가 메시지를 생성하여 특정 주제에 게시(publish)하면, 그 주제를 구독(subscribe)하는 소비자(consumer)들이 메시지를 받아 처리하는 방식을 지원합니다.</p>
</li>
<li><p><strong>분산처리</strong>: Kafka는 클러스터 형태로 구성될 수 있으며, 여러 서버에 걸쳐 데이터 스트림을 분산 저장하고 처리할 수 있습니다. 이를 통해 높은 확장성과 내구성을 보장합니다.</p>
</li>
<li><p><strong>실시간 처리</strong>: Kafka는 대용량의 실시간 데이터 스트림을 빠르게 처리할 수 있습니다. 따라서 로그 수집, 실시간 분석 등 다양한 사용 사례에서 활용됩니다.</p>
</li>
<li><p><strong>내결함성(Fault-tolerance)</strong>: Kafka 클러스터 내에서 각 메세지와 상태들은 복제(replication)되어 저장되므로, 한 노드가 실패해도 데이터 손실 없이 운영이 가능합니다.</p>
</li>
<li><p><strong>영속성(Persistence)</strong>: Kafka에서 모든 메세지는 디스크에 영속적으로 저장되며, 사용자 설정에 따라 일정 시간 동안(또는 용량이 충분한 한 계속해서) 보관됩니다.</p>
</li>
</ol>
<blockquote>
</blockquote>
<p>💡 Kafka의 이러한 특징들 때문에 많은 기업들이 실시간 로그처리나 스트리밍 데이터 처리 등의 목적으로 Kafka를 활용하고 있습니다.</p>
<p>카프카에는 각종 데이터를 닮는 토픽이라는 개념이 있는데 쉽게 이야기해서 큐라고 생각하면 좋습니다.</p>
<ul>
<li>프로듀서 : 카프카의 토픽에 데이터를 넣는역할</li>
<li>컨슈머 : 카프카의 토픽에서 데이터를 가져가는 역할</li>
</ul>
<p>이 둘은 라이브러리로 되어있어 어플리케이션에서 구현 가능</p>
<hr>
<h2 id="🧑💻-토픽과-파티션">🧑‍💻 토픽과 파티션</h2>
<p>카프카에서 토픽은 메시지(이벤트)를 구분하는 단위입니다. 
하나의 토픽은 여러 개의 파티션으로 구성될 수 있으며, 각 파티션은 메시지를 저장하는 물리적인 파일입니다. 카프카 프로듀서는 토픽에 메시지를 발행하고, 카프카 소비자는 토픽에서 메시지를 소비합니다.</p>
<h3 id="파티션이-하나일때">파티션이 하나일때</h3>
<p>하나의 토픽은 여러개의 파티션으로 구성이 가능합니다.
첫번째 파티션은 0번부터 시작하고 하나의 파티션은 큐와같이 내부의 데이터가 파티션의 끝부터 쌓이게 됩니다.</p>
<p>이때 컨슈머는 메세지가 오래된 순서대로 가져가게 됩니다. 
그리고 카프카는 이벤트 브로커 이기때문에 컨슈머가 메세지를 가져가도 사라지지 않습니다.
<img src="https://velog.velcdn.com/images/moon_happy/post/52b7ab76-697a-4cbc-9fe3-f93ebdd82556/image.png" alt=""></p>
<p>남은 메세지는 또 다른 컨슈머가 붙었을때 그 컨슈머가 가져갈 수 있습니다.</p>
<ul>
<li>이때 새로 붙은 컨슈머는 원래의 컨슈머와 그룹이 달라야하고, auto.offset.reset=earliest여야한다</li>
</ul>
<h3 id="파티션이-두개일때">파티션이 두개일때</h3>
<p><img src="https://velog.velcdn.com/images/moon_happy/post/c6022c9b-f430-4ce0-b2d7-63a8e0e08566/image.png" alt=""></p>
<ul>
<li>키값이 없고, 기본 파티셔너를 사용할 경우 RR(라운드 로빈)방식으로 파티션에 할당되게 됩니다.</li>
<li>키를 있다면, 기본 파티셔너를 사용할 경우 키의 해시값을 구하고, 특정 파티션에 할당 됩니다.</li>
</ul>
<h3 id="파티션을-생성할때-고려해야하는-사항들">파티션을 생성할때 고려해야하는 사항들</h3>
<ol>
<li>파티션을 늘리는것은 가능하지만 줄이는것은 불가능합니다.</li>
<li>파티션당 저장할 수 있는 메시지의 파티션 크기 제한에 의해 결정됩니다.
파티션 크기 제한을 초과하는 메시지는 해당 파티션에 저장되지 않습니다.</li>
<li>예상 트래픽을 처리할 수 있을 만큼 충분히 커야합니다.
만약 파티션 수가 적으면 각 파티션에 너무 많은 메세지가 전송되어 성능이 저하될 수 있습니다.</li>
<li>파티션당 메세지 보유 기간을 고려해야합니다.</li>
</ol>
<hr>
<h2 id="🧑💻-프로듀서">🧑‍💻 프로듀서</h2>
<ul>
<li>프로듀서는 토픽에 해당하는 메세지를 생성하는 역할을 합니다.</li>
<li>특정 토픽에 메세지를 Publish</li>
<li>만약 생성에 실패하더라도 재시도 하는 기능이 있습니다.</li>
</ul>
<pre><code class="language-java">public class Producer {
    public static void main(String[] args) throws I0Exception {
    Properties configs = new Properties( );
    configs.put(&quot;bootstrap.servers&quot;, &quot;localhost: 9092&quot;);
    configs.put(&quot;key .serializer&quot;,&quot;org .apache.kafka.common.serialization.StringSerializer&quot;);
    configs.put(&quot;value.serializer&quot;,&quot;org. apache.kafka.common.serialization.StringSerializer&quot;);

    KafkaProducer &lt; String, String &gt; producer = new KafkaProducer &lt; String, String &gt; (configs) ;

    ProducerRecord record = new ProducerRecord &lt; String, String &gt; (&quot;click_ log&quot;, &quot;Login&quot;);

    producer. send (record);

    producer. close();
    }
}</code></pre>
<p>위의 예제에서는 click_log라는 토픽에 login이라는 메세지만 선언을 해주었지만 
사이에 파티션의 키를 설정하여 파티션 지정이 가능하게 됩니다.
이때 따로 설정을 하지 않고 파라미터의 개수에 따라서 자동으로 오버로딩되어 인스턴스를 생성하게 됩니다.</p>
<p>토픽에서 설명했듯이 파티션의 키값을 설정하지 않았다면 round robin방식으로 균일하게 파티션에 저장이되지만 따로 설정을 하였다면 카프카는 키를 특정한 hash값으로 변경시켜 파티션과 1:1 매칭을 시켜줍니다.</p>
<p>하지만 메세지를 보내는 도중 파티션의 수를 늘리게 된다면 매칭을 깨지게 되면서 키와 파티션의 연결은 보장되지 않습니다.(키-파티션의 일관성 보장 X)</p>
<hr>
<h2 id="🧑💻-브로커">🧑‍💻 브로커</h2>
<ul>
<li>카프카가 설치되어있는 서버를 이야기 합니다.</li>
<li>대부분의 클러스터는 3개의 브로커로 구성합니다.</li>
</ul>
<p>그리고 토픽을 생성할때 partition과 replication의 수를 설정하게 됩니다. </p>
<ul>
<li>partition의 수는 생성될 파티션의 수이고 </li>
<li>replication의 수는 몇개의 서버에 파티션을 복제할것인지의 수이고 브로커의 수를 넘어갈 수 없습니다.</li>
</ul>
<p>즉, partition1, replication3이면 세개의 서버에 같은 파티션 하나가 생성되게 됩니다.</p>
<p>그리고 토픽을 만들때 하나의 브로커에 들어가서 만들게 되는데 그곳의 partition이 leader partition이 되고, 나머지 두개의 파티션은 follower partition이라고 합니다.</p>
<ul>
<li>리더와 팔로우 파티션을 합쳐서 ISR(In Sync Replica)라고 볼수 있습니다.</li>
</ul>
<h3 id="replication을-사용하는이유">replication을 사용하는이유</h3>
<ul>
<li>partition의 고가용성을 위해 사용합니다.</li>
<li>1개만 만들게 된다 어떠한 장애로인해 브로커가 사용이 안된다면 해당 파티션은 복구할수 없습니다.</li>
<li>2개를 만들게 되었다면 하나의 브로커가 터지더라고 팔로우 파티션이 리더를 계승합니다.</li>
</ul>
<blockquote>
</blockquote>
<p>하지만 무작정많으면 좋지않습니다
⇒ 1 partition, 6 replication은 많아서 좋지만 브로커의 리소스 사용량도 늘어나게 됩니다.</p>
<h3 id="파티션의-ack의-의미">파티션의 ack의 의미</h3>
<ul>
<li>리더 : 프로듀서가 토픽의 파티션에 데이터를 전달할때 전달받는 주체<ul>
<li>프로듀서에는 ack라는 상세옵션 존재</li>
<li>ack를 통해 고가용성을 유지, partition의 replication에 관련</li>
<li>ack는 0,1,all 중 하나를 골라 사용</li>
<li>0 : 프로듀서는 leader partition에 데이터를 전송하고 응답값 X, 데이터가 잘갔는지, 나머지 파티션에 복제가 되었는지 모른다. 즉, 속도는 빠르지만 데이터의 유실 가능성이 있다</li>
<li>1 : 응답값 O, 하지만 나머지 파티션에 복제 되었는지 알수 없다. 하지만 이것도 다른데이터에 복제가 안되었는데 리더 파티션이 터지게 된다면 데이터의 유실가능성이 있다.</li>
<li>all : 모든 응답값 O, 데이터 유실 X, 속도가 현저히 느리다</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🧑💻-컨슈머">🧑‍💻 컨슈머</h2>
<ul>
<li>카프카 컨슈머는 기본적으로 토픽의 데이터를 가져옵니다.</li>
<li>즉 파티션에 저장된 데이터를 가져오게 됩니다.</li>
<li>데이터를 가져오는것을 폴링이라고 합니다.</li>
</ul>
<h3 id="컨슈머의-역할">컨슈머의 역할</h3>
<ul>
<li>Topic의 partition으로 부터 polling합니다.</li>
<li>Partition offset의 위치를 기록합니다.(commit)<ul>
<li>offset : 파티션에 있는 데이터의 번호를 뜻합니다.</li>
</ul>
</li>
<li>Consumer group을 통해 병렬처리 합니다.</li>
</ul>
<h3 id="컨슈머는-몇개까지-가능한가">컨슈머는 몇개까지 가능한가</h3>
<ul>
<li><p>만약 두개의 파티션이 존재하고 하나의 컨슈머가 있다면 하나의 컨슈머가 두개의 파티션을 할당하여 데이터를 가져올수 있습니다.</p>
</li>
<li><p>컨슈머가 두개라면 각각의 파티션 하나를 할당하여 데이터를 가져올수 있습니다.</p>
</li>
<li><p>하지만 파티션의 수보다 컨슈머 그룹에 컨슈머가 많다면 즉, 2개의 파티션에 3개의 컨슈머가 있다면 하나의 컨슈머는 동작하지않습니다.</p>
</li>
</ul>
<blockquote>
<p>컨슈머는 파티션의 수보다 같거나 적어야 합니다. </p>
</blockquote>
<h3 id="컨슈머의-그룹이-다르다면">컨슈머의 그룹이 다르다면</h3>
<ul>
<li>컨슈머 그룹마다 파티션의 수보다 같거나 적고, 그룹이 다르다면 정상적으로 실행이 됩니다.</li>
<li>각 파티션에 특정 offset을 읽고 있어도 다른 컨슈머 그룹에는 영향이 없습니다.</li>
</ul>
<blockquote>
</blockquote>
<p>__consumer_offset토픽에는 컨슈머 그룹별로 토픽별로 offset을 나누어 저장하기 때문입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[List 와 set의 차이]]></title>
            <link>https://velog.io/@moon_happy/List-%EC%99%80-set%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@moon_happy/List-%EC%99%80-set%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sat, 26 Aug 2023 06:28:05 GMT</pubDate>
            <description><![CDATA[<p>최근 기술면접을 준비하면서 궁금한것이 생겼었습니다.
그것은 데이터들을 하나로 모으는 컬렉션 자료형이지만 List와 set의 차이점이었습니다.</p>
<h2 id="🤔-차이점">🤔 차이점</h2>
<p>둘의 차이점은 크게 3가지가 있습니다.</p>
<ul>
<li>순서</li>
<li>중복</li>
<li>연산</li>
</ul>
<p>이러한 차이점을 상세하게 알아보겠습니다.</p>
<h3 id="순서">순서</h3>
<p>파이썬에서 코딩 테스트나 코드를 작성하였을때 모두들 경험을 해보셨을것입니다.</p>
<ul>
<li>list 순서 ⭕️</li>
<li>set 순서 ❌</li>
</ul>
<p>list와 set에 같은 데이터를 넣었을때 출력을 해보면 
list는 순서가 보장이되고, set은 순서의 보장이 되지 않는점이 있었습니다.</p>
<p>그렇다면 set은 왜 순서가 보장이 안되는 것일까요?
그것은 set이 해시 테이블을 기반으로 구현이 되었기 때문입니다.</p>
<blockquote>
</blockquote>
<p>해시 테이블 : 키와 값이 쌍으로 저장하는 자료구조로, 키에 대한 값을 
빠르게 찾을 수 있는 장점이 있습니다.</p>
<blockquote>
</blockquote>
<p>💡 추후에 해시 테이블에 관한 게시물을 작성하겠습니다.</p>
<h3 id="중복">중복</h3>
<ul>
<li>list 중복 ⭕️</li>
<li>set 중복 ❌</li>
</ul>
<p>중복이 안되는 것또한 경험을 통해서 해보셨을것입니다.
이것또한 set은 해시테이블의 속성때문에 중복을 허용하지않기 때문입니다.</p>
<h3 id="연산">연산</h3>
<p>연산에서도 list와 set이 차이를 보입니다.</p>
<ul>
<li>list : 덧셈, 뺄셈, 곱셈, 나눗셈, 인덱싱, 슬라이싱, 연결, 정렬, 검색, 삽입, 삭제등의 연산</li>
<li>set : 덧셈, 뺄셈, 곱셈, 나눗셈, 인덱싱, 슬라이싱, 연결, 검색, 삽입, 삭제등의 연산</li>
</ul>
<p>이것또한 set은 해시테이블을 기반으로 만들어 졌기 때문에 list는 set보다 다양한 연산을 지원합니다.</p>
<h2 id="🤔set이-구현되는-순서">🤔Set이 구현되는 순서</h2>
<p>위의 차이를 설명하면서 해시테이블때문에 그렇다고 많이 말씀드렸는데 set은 어떻게 구현이 되는것일까요?</p>
<ol>
<li>set에 &quot;문어&quot;라는 값이 들어갑니다.</li>
<li>해시 함수에 &quot;문어&quot;라는 값의 해시값을 계산합니다.<pre><code class="language-python">def hash(value):
 result = 0
 for char in value:
     result += ord(char)
 return result % 100</code></pre>
이것은 제가 임의로 만든 해시함수로 &quot;문어&quot;라는 요소가 들어가게 되면 연산을 통해서 6567이라는 해시 값이 나옵니다.</li>
<li>해시 테이블에 맞춰 해시값에 해당하는 인덱스에 저장합니다.
위에서 나온 6567을 받아 해시테이블의 크기가 만약 100이라면 65에 해당하는 인덱스에 문어가 저장이되게 됩니다.<pre><code>{
 65: 문어,
}</code></pre></li>
</ol>
<h2 id="🤔-언제-뭘-어떻게-써야할까">🤔 언제 뭘 어떻게 써야할까</h2>
<h3 id="set">set</h3>
<ul>
<li>중복의 요소를 제거하거나, 고유한 요소만을 저장해야하는 상황</li>
<li>집합과 같은 구조를 구현해야하는 상황</li>
<li>수학적 연산을 해야하는 상황</li>
</ul>
<h3 id="list">list</h3>
<ul>
<li>인덱싱, 슬라이싱, 연결, 등의 연산을 수행해야 하는 상황</li>
<li>요소의 순서를 유지해야하는 상황 </li>
</ul>
]]></description>
        </item>
    </channel>
</rss>