<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>this_summer.log</title>
        <link>https://velog.io/</link>
        <description>배움을 즐기는 개발자입니다.</description>
        <lastBuildDate>Tue, 07 Mar 2023 12:47:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. this_summer.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/this_summer" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[MongoDB - null data handling]]></title>
            <link>https://velog.io/@this_summer/MongoDB-null-data-handling</link>
            <guid>https://velog.io/@this_summer/MongoDB-null-data-handling</guid>
            <pubDate>Tue, 07 Mar 2023 12:47:49 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>null 데이터에 대한 update 를 진행할 때 주의할 점을 알게 됩니다.</p>
</blockquote>
<h1 id="데이터-생성">데이터 생성</h1>
<pre><code>use test
db.employees.insertOne({
    name: &quot;lake&quot;,
    age: 21,
    dept: &quot;Database&quot;,
    joinDate: new ISODate(&quot;2022-10-01&quot;),
    salary: 400000,
    bonus: null
})


db.employees.insertOne({
    name: &quot;ben&quot;,
    age: 23,
    dept: &quot;Network&quot;,
    joinDate: new ISODate(&quot;2001-10-01&quot;),
    salary: 1000000,
})</code></pre><blockquote>
<p>위와 같은 데이터가 있습니다. 보너스를 지급할 대상이 bonus 필드가 null 인 직원이라 해봅시다.</p>
</blockquote>
<ul>
<li><p>update query </p>
<pre><code>db.employees.updateMany({
  resignationDate: {
      $exists: false
  },
  joinDate: {
      $exists: true
  },
  bonus: null
}, {
  $set: {
      bonus: 10000
  }
})</code></pre><blockquote>
<p>퇴사하지 않았고, bonus 필드가 null 인 유저의 bonus를 10000으로 지정합니다. 결과는요? bonus 필드가 존재하지 않는 경우도 null</p>
</blockquote>
<pre><code class="language-[">{
  _id: ObjectId(&quot;640730ba77ec14b4b106b6c4&quot;),
  name: &#39;lake&#39;,
  age: 21,
  dept: &#39;Database&#39;,
  joinDate: ISODate(&quot;2022-10-01T00:00:00.000Z&quot;),
  salary: 400000,
  bonus: 10000
},
{
  _id: ObjectId(&quot;640730ba77ec14b4b106b6c5&quot;),
  name: &#39;ben&#39;,
  age: 23,
  dept: &#39;Network&#39;,
  joinDate: ISODate(&quot;2001-10-01T00:00:00.000Z&quot;),
  salary: 1000000,
  bonus: 10000
}
]</code></pre>
</li>
<li><p>두 Document 모두 업데이트가 됬습니다. 따라서 이런 경우는 꼭 다음과 같이 쿼리를 해야 합니다.</p>
</li>
</ul>
<pre><code>db.employees.updateMany({
    resignationDate: {
        $exists: false
    },
    joinDate: {
        $exists: true
    },
    bonus: {
        $exists: true
    }
}, {
    $set: {
        bonus: 10000
    }
})

or

db.employees.updateMany({
    $and: [
        { resignationDate: { $exists: false } },
        { joinDate: { $exists: true } },
        { bonus: { $exists: true } },
        { bonus: null } 
    ]
    }, 
    { $set: { bonus: 10000 } }
)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[MongoDB - Replica-set, Sharded Cluster Deployment Tutorial]]></title>
            <link>https://velog.io/@this_summer/MongoDB-Replica-set-Sharded-Cluster-Deployment-Tutorial</link>
            <guid>https://velog.io/@this_summer/MongoDB-Replica-set-Sharded-Cluster-Deployment-Tutorial</guid>
            <pubDate>Tue, 07 Mar 2023 12:34:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>로컬에 Replica-set 을 구축하는 방법, Sharded Cluster 배포하는 방법을 알 수 있습니다.</p>
</blockquote>
<h1 id="구축-환경">구축 환경</h1>
<ul>
<li>Mac OS</li>
</ul>
<h1 id="설치">설치</h1>
<ul>
<li><a href="https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-5.0.15.tgz">MongoDB Community Server Download</a></li>
<li><a href="https://downloads.mongodb.com/compass/mongosh-1.8.0-darwin-x64.zip">MongoDB Shell Download</a></li>
</ul>
<ol>
<li>다운로드 이후, 작업할 디렉토리 생성</li>
</ol>
<pre><code>mkdir -p ~/mongodb-folder
mkdir -p ~/mongodb-folder/mongodb/data{1,2,3}
mkdir -p ~/mongodb-folder/mongodb/config
mkdir -p ~/mongodb-folder/mongodb/log</code></pre><ol start="2">
<li>~/mongodb-folder 로 압축을 풀어줍니다.</li>
</ol>
<h1 id="mongodb-실행">mongodb 실행</h1>
<p>Terminal 3개를 열어서 각각 실행합니다.</p>
<pre><code># Terminal 1번
cd ~/mongodb-folder/mongodb-macos-x86_64-5.0.15/bin

./mongod --replSet rs1 --port 27017 --bind_ip &quot;0.0.0.0&quot; -dbpath ~/mongodb-folder/mongodb/data1 --oplogSize 128
</code></pre><pre><code># Terminal 2번
cd ~/mongodb-folder/mongodb-macos-x86_64-5.0.15/bin

./mongod --replSet rs1 --port 27018 --bind_ip &quot;0.0.0.0&quot; -dbpath ~/mongodb-folder/mongodb/data2 --oplogSize 128</code></pre><pre><code># Terminal 3번
cd ~/mongodb-folder/mongodb-macos-x86_64-5.0.15/bin
./mongod --replSet rs1 --port 27019 --bind_ip &quot;0.0.0.0&quot; -dbpath ~/mongodb-folder/mongodb/data3 --oplogSize 128</code></pre><blockquote>
<p>각 mongodb server 는 port 27017, 27018, 27019 로 실행되며, 각 데이터베이스 데이터 저장 디렉토리는 data1, data2, data3 로 지정합니다.</p>
</blockquote>
<h1 id="replica-set-으로-지정">Replica-set 으로 지정</h1>
<p>replSet 옵션을 주어서 동작시켰지만, replica initiazation 이 안된 상황이라 다음과 같이 에러가 발생합니다. 정상입니다.
<img src="https://velog.velcdn.com/images/this_summer/post/186f14b2-873e-4491-9755-69300c1c2845/image.png" alt=""></p>
<p>Terminal 하나 더 켜서 Shell 을 통해 MongoDB Server 에 접근합니다.</p>
<pre><code>cd ~/mongodb-folder/mongosh-1.8.0-darwin-x64/bin
./mongosh &quot;mongodb://localhost:27017&quot;</code></pre><p>접속이 되면 Replica-set 을 Initialize 합니다.</p>
<pre><code>rs.initiate({
    _id: &quot;rs1&quot;,
    members: [
        { _id: 0, host: &quot;localhost:27017&quot; },
        { _id: 1, host: &quot;localhost:27018&quot; },
        { _id: 2, host: &quot;localhost:27019&quot; },
    ],
});

rs.status;</code></pre><p><img src="https://velog.velcdn.com/images/this_summer/post/96ea0cd6-926f-4181-8dc1-7a83f94ad16d/image.png" alt=""></p>
<ul>
<li>Initiate 를 실행하는 Mongodb Server 는 최초 Secondary 이지만 곧 Primary 가 됩니다.</li>
</ul>
<h1 id="sharded-cluster-배포">Sharded Cluster 배포</h1>
<p>Ref : <a href="https://github.com/minhhungit/mongodb-cluster-docker-compose">https://github.com/minhhungit/mongodb-cluster-docker-compose</a></p>
<p>Docker Compose 를 통해 Local 에 배포하도록 하겠습니다. Git Clone 을 ~/mongodb-folder 에 해줍니다.</p>
<pre><code>cd ~/mongodb-folder
git clone https://github.com/minhhungit/mongodb-cluster-docker-compose.git</code></pre><ol>
<li>docker compose up<pre><code>cd ~/mongodb-folder/mongodb-cluster-docker-compose
docker compose up -d</code></pre></li>
<li>config server 와 shard 설정을 해줍니다.<pre><code>docker-compose exec configsvr01 sh -c &quot;mongosh &lt; /scripts/init-configserver.js&quot;
</code></pre></li>
</ol>
<p>docker-compose exec shard01-a sh -c &quot;mongosh &lt; /scripts/init-shard01.js&quot;
docker-compose exec shard02-a sh -c &quot;mongosh &lt; /scripts/init-shard02.js&quot;
docker-compose exec shard03-a sh -c &quot;mongosh &lt; /scripts/init-shard03.js&quot;</p>
<pre><code>3. router 초기화</code></pre><p>docker-compose exec router01 sh -c &quot;mongosh &lt; /scripts/init-router.js&quot;</p>
<pre><code>4. router 로 접속</code></pre><p>docker-compose exec router01 mongosh --port 27017</p>
<pre><code>
5. sh.status() 로 상태 확인
![](https://velog.velcdn.com/images/this_summer/post/3c7fb5cb-6767-4887-9550-83a703b189c5/image.png)

&gt; 위처럼 구성해도 직접 sharding 을 활성화하지 않으면, partition 되어 데이터가 저장되지 않습니다. 따라서 직접 활성화를 해줘야 합니다.

6. 데이터 베이스 생성 및 샘플 데이터 insert</code></pre><p>use test
db.abc.insertOne({ a: 1, b:2})
sh.status()</p>
<pre><code>&gt; test database 생성 후, abc 로 데이터를 하나 넣고, sh.status() 를 확인합니다.
database section 을 확인하면 아래에 빨간 영역이 false 로 되어있을겁니다.
![](https://velog.velcdn.com/images/this_summer/post/79d1deed-c8f2-4b4e-9e21-85a72679e0fb/image.png)

7. sharding 활성화</code></pre><p>sh.enableSharding(&quot;test&quot;)
sh.status()</p>
<pre><code>&gt; sharding 을 활성화하면 partitioned 가 true 로 변경된걸 확인할 수 있습니다. 데이터는 Collection 단위로 분산할 수 있고, Collection 에 대한 Sharding 도 설정해줘야 합니다.

8. Collection Sharding 설정
</code></pre><p>db.abc.createIndex({a: 1})
sh.shardCollection(&quot;test.abc&quot;, {a: 1})</p>
<pre><code>&gt; shard 를 설정하기 위해서는 index 가 필요합니다.
위처럼 Collection 에 Shard 를 지정하면 a 컬럼에 대한 range shard 로 설정이 됩니다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[MongoDB 개념 정리]]></title>
            <link>https://velog.io/@this_summer/MongoDB-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@this_summer/MongoDB-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 06 Mar 2023 10:43:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>MongoDB 의 유래, 특징, 배포 방식과 차이점 및 전략에 대해서 알 수 있습니다.</p>
</blockquote>
<h1 id="유래">유래</h1>
<ol>
<li>빅 데이터가 등장하면서 데이터의 양이 급격히 증가했고 기존의 SQL 데이터베이스 시스템은 대규모 데이터 처리에 한계</li>
<li>분산 처리의 필요성</li>
<li>기존 SQL 데이터베이스 시스템의 정해진 데이터 스키마를 따라야 제약이 유연성과 확장성을 제한하였고, 이에 유연성과 확장성의 필요성이 대두</li>
</ol>
<blockquote>
<p>따라서, 이러한 이유로 MongoDB는 대규모 데이터 처리와 분산 처리에 특화되어 있으며, 유연성과 확장성이 높은 NoSQL 데이터베이스 시스템으로 개발되었습니다.</p>
</blockquote>
<h1 id="특징">특징</h1>
<h3 id="스키마-자유도">스키마 자유도</h3>
<p>MongoDB는 스키마 자유도가 높습니다. 즉, 데이터베이스에 저장되는 문서의 구조나 필드를 미리 정의할 필요가 없습니다. 이는 데이터베이스의 유연성을 높여주며, 데이터베이스 설계와 관리를 단순화합니다.</p>
<h3 id="샤딩sharding-지원">샤딩(Sharding) 지원</h3>
<p>MongoDB는 대규모 데이터 처리를 위해 샤딩(Sharding)이라는 기능을 제공합니다. 이를 통해 데이터를 분산하여 저장하고 처리할 수 있으며, 이를 통해 데이터베이스의 처리 속도와 확장성을 높일 수 있습니다.</p>
<h3 id="다양한-인덱싱indexing-기능">다양한 인덱싱(Indexing) 기능</h3>
<p>MongoDB는 다양한 인덱싱(Indexing) 기능을 제공합니다. 이를 통해 데이터베이스의 검색 속도를 높일 수 있으며, 데이터베이스의 성능을 개선할 수 있습니다.</p>
<h3 id="복제replication-기능">복제(Replication) 기능</h3>
<p>MongoDB는 데이터베이스의 가용성을 높이기 위한 복제(Replication) 기능을 제공합니다. 이를 통해 데이터베이스 서버가 다운되었을 때에도 다른 서버에서 데이터베이스를 계속 사용할 수 있습니다.</p>
<h3 id="풍부한-쿼리query-기능">풍부한 쿼리(Query) 기능</h3>
<p>MongoDB는 SQL과 비슷한 쿼리(Query) 언어를 사용하여 데이터베이스를 쉽게 조작할 수 있습니다. 이를 통해 데이터베이스의 검색과 조작이 용이해지며, 데이터베이스의 활용성을 높일 수 있습니다.</p>
<h3 id="유연한-저장소storage-엔진">유연한 저장소(Storage) 엔진</h3>
<p>MongoDB는 유연한 저장소(Storage) 엔진을 사용합니다. 이를 통해 데이터베이스의 처리 속도와 확장성을 높일 수 있습니다.</p>
<h3 id="오픈소스">오픈소스</h3>
<p>MongoDB는 오픈소스 데이터베이스 시스템으로, 누구나 무료로 사용할 수 있으며, 커뮤니티에서 지속적으로 업데이트 및 개선 작업이 이루어지고 있습니다.</p>
<h1 id="배포-방식">배포 방식</h1>
<blockquote>
<p>Replica-set, sharded cluster 2가지 방식이 존재합니다.</p>
</blockquote>
<h3 id="replica-set">Replica-set</h3>
<p><img src="https://velog.velcdn.com/images/this_summer/post/8e654a46-1c8a-4676-8459-ec128893cd74/image.png" alt="">
MongoDB에서 Replica Set은 데이터베이스의 가용성과 안정성을 높이기 위한 분산 시스템입니다. Replica Set은 데이터베이스의 복제 기능을 이용하여 여러 대의 서버에 데이터를 저장하고, 서버 중 한 대에 문제가 생길 경우에도 다른 서버에서 데이터를 제공할 수 있도록 구성됩니다.</p>
<h4 id="replica-set-의-구성-요소">Replica-set 의 구성 요소</h4>
<ul>
<li>Primary Node(주 서버)<blockquote>
<p>Replica Set 중 한 대의 서버로, 쓰기 작업을 처리하는 역할(configuration 설정이 필요)을 합니다.
데이터베이스의 변경 작업은 Primary Node에서만 처리됩니다.</p>
</blockquote>
</li>
<li>Secondary Node(보조 서버)<blockquote>
<p>Replica Set에 속한 서버 중 Primary Node 이외의 모든 서버를 말합니다.
Secondary Node는 Primary Node에서 데이터를 복제하여 데이터베이스의 읽기 작업을 처리합니다.
Secondary Node 중 한 대에 문제가 생겨도 다른 Secondary Node에서 데이터를 읽어올 수 있습니다.</p>
</blockquote>
</li>
<li>Arbiter Node(판정 서버)<blockquote>
<p>Replica Set에 속한 서버 중 한 대로, 데이터를 저장하지 않고 단지 Primary Node의 선출을 판정하는 역할을 합니다.
Arbiter Node는 Replica Set의 안정성을 높이기 위해 사용됩니다.
Replica Set은 Primary Node와 Secondary Node 간의 데이터 복제 기능을 이용하여 데이터베이스를 복제하고, 동기화합니다. Primary Node에서 발생한 쓰기 작업은 Secondary Node로 전달되어 복제되며, Secondary Node에서 발생한 데이터 변경 작업은 Primary Node로 전달되지 않습니다.</p>
</blockquote>
</li>
</ul>
<h3 id="replica-set-의-장점과-단점">Replica-set 의 장점과 단점</h3>
<h4 id="장점">장점</h4>
<ul>
<li>데이터베이스의 가용성을 높일 수 있습니다.</li>
<li>데이터베이스의 안정성을 높일 수 있습니다.</li>
<li>데이터 복제 기능을 이용하여 데이터를 백업할 수 있습니다.</li>
<li>데이터베이스의 확장성을 높일 수 있습니다.<h4 id="단점">단점</h4>
</li>
<li>write 분산 처리가 불가능합니다.</li>
</ul>
<h3 id="shared-cluster">Shared Cluster</h3>
<p><img src="https://velog.velcdn.com/images/this_summer/post/662af2d1-2349-4306-ae5d-2a3cb22fb7ff/image.png" alt=""></p>
<blockquote>
<p>MongoDB의 Sharded Cluster는 대규모 데이터 처리를 위한 분산 데이터베이스 시스템입니다. Sharded Cluster는 데이터베이스의 샤딩(Sharding)과 Replica Set 기능을 사용하여 여러 대의 서버에 데이터를 분산하여 저장하고, 필요에 따라서 데이터베이스를 확장할 수 있습니다.</p>
</blockquote>
<h4 id="sharded-cluster의-구성요소">Sharded Cluster의 구성요소</h4>
<ul>
<li>Config Server<blockquote>
<p>Sharded Cluster의 구성 정보를 저장하는 서버입니다.
Config Server는 Replica Set으로 구성되어 있습니다.</p>
</blockquote>
</li>
<li>Shard Server<blockquote>
<p>Sharded Cluster에 속한 서버 중 데이터를 저장하는 서버입니다.
각각의 Shard Server는 Replica Set으로 구성되어 있습니다.</p>
</blockquote>
</li>
<li>Query Router<blockquote>
<p>Sharded Cluster와 클라이언트 간의 데이터 통신을 담당하는 서버입니다.
Query Router는 클라이언트의 쿼리(Query)를 분석하여 적절한 Shard Server에 전달합니다.</p>
</blockquote>
</li>
</ul>
<p>Sharded Cluster는 데이터베이스의 샤딩(Sharding)을 사용하여 데이터를 분산 저장합니다. 샤딩을 사용하면 데이터베이스의 처리 속도를 높일 수 있습니다. 각각의 Shard Server는 Replica Set으로 구성되어 있으며, Replica Set 간의 데이터 복제는 MongoDB의 쓰기 작업과 동기화됩니다. 이를 통해 데이터베이스의 안정성과 가용성을 높일 수 있습니다.</p>
<p>Sharded Cluster는 다음과 같은 장점을 가지고 있습니다.</p>
<h3 id="shared-cluster-의-장점과-단점">Shared Cluster 의 장점과 단점</h3>
<h4 id="장점-1">장점</h4>
<ul>
<li>데이터베이스의 확장성을 높입니다. Shard Server를 추가하면 데이터베이스의 처리 속도를 높일 수 있습니다.</li>
<li>데이터베이스의 가용성을 높입니다. 각각의 Shard Server는 여러 개의 서버로 구성되어 있기 때문에, 한 대의 서버에 문제가 생겨도 다른 서버에서 데이터를 제공할 수 있습니다.</li>
<li>데이터베이스의 안정성을 높입니다. Replica Set을 사용하여 데이터베이스의 복제 기능을 이용하면 데이터베이스의 안정성이 높아집니다.</li>
</ul>
<h4 id="단점-1">단점</h4>
<ul>
<li>성능 하락<blockquote>
<p>replica-set 배포 방식에 비해 성능이 떨어집니다. 데이터가 분산되어 있어, 특히 Range Query 에서 큰 성능 하락을 경험할 수 있습니다.</p>
</blockquote>
</li>
<li>장애 복구 비용 증가<blockquote>
<p>데이터가 분산되어 있는 만큼 장애에 복구하는데 들어가는 리소스가 상승합니다.</p>
</blockquote>
</li>
<li>운영 비용 증가<blockquote>
<p>Sharded Cluster는 여러 대의 Shard Server와 Config Server, Query Router 등으로 구성되어 있으므로, 단일 서버에 비해 더욱 복잡한 구성을 가지고 있습니다. 따라서, Sharded Cluster의 관리는 단일 서버에 비해 더욱 복잡합니다.</p>
</blockquote>
</li>
</ul>
<h1 id="배포-전략">배포 전략</h1>
<p>배포 전략을 고려할때 데이터의 증가나 요구 사항들을 면밀하게 검토해야 합니다. 하지만 <em><strong>가장 최우선적으로 Replica-set</strong></em> 을 사용하여 운영하는 방식을 고려해야 합니다. </p>
<p><em><strong>데이터의 증가</strong>_가 크고, **_Write 가 압도적으로 많아</em>**서 꼭!! 꼭!! Sharded Cluster 방식을 고려해야 할때, 도입하는게 좋습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MySQL - Query Optimization]]></title>
            <link>https://velog.io/@this_summer/MySQL-Query-Optimization</link>
            <guid>https://velog.io/@this_summer/MySQL-Query-Optimization</guid>
            <pubDate>Thu, 23 Feb 2023 13:17:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이번 포스트를 보게 되면 MySQL 에서 Index 를 사용하는 방법에 대해서 배울수 있습니다.</p>
</blockquote>
<h1 id="data-insert">Data Insert</h1>
<p>데이터 증가에 따른 query 속도를 비교하기 위해서, 100만건을 우선적으로 insert 해보겠습니다.</p>
<pre><code class="language-sql">create table POST
(
    id int auto_increment,
    memberId int not null,
    contents varchar(100) not null,
    createdDate date not null,
    createdAt datetime not null,
    constraint POST_id_uindex
        primary key (id)
);</code></pre>
<p>우선 테이블을 생성합니다.</p>
<p>저는 EasyRandom 을 통해서 코드를 통해 Database 에 memberid 3으로 100만건 insert 을 진행합니다.</p>
<blockquote>
<p>100만건 insert 시간 : 29.261983939</p>
</blockquote>
<h1 id="select-query">Select Query</h1>
<pre><code class="language-sql">select createdDate, memberId, count(id)
from POST
where memberId = 3 and createdDate between &#39;2019-01-01&#39; and &#39;2019-12-31&#39;
group by memberId, createdDate;</code></pre>
<p>데이터는 1970-01-01 부터 2022-02-01 까지 데이터로 총 100만건이 insert 되었습니다.</p>
<p>따라서 위 쿼리를 실행해보면 결과는 다음과 같습니다.</p>
<blockquote>
<p>select query 시간 : 1.002 sec 
cpu usage : max 40%</p>
</blockquote>
<p>좀 더 확실한 비교를 위해서 memberId 4, 5로 100만건씩 insert 하고 Select Query 속도를 비교해보겠습니다.</p>
<p><strong>memberid 4으로 100만건 insert</strong></p>
<blockquote>
<p>select query 시간 : 1.730 sec
cpu usage : max 60%</p>
</blockquote>
<p><strong>memberid 5으로 100만건 insert</strong></p>
<blockquote>
<p>select query 시간 : 2.095 sec
cpu usage : max 70%</p>
</blockquote>
<p>query 시간이 초단위가 넘어가면 사고입니다. 데이터가 증가함에 따라 cpu 사용률과 query 속도가 말도 안되게 느려집니다.</p>
<h1 id="index">index</h1>
<p>시작전에 명심해야 될 건 다음과 같습니다.</p>
<blockquote>
<p>index 거는 작업은 부하가 크다!!!!!!!!!!!</p>
</blockquote>
<p>*<em>1. createdDate Column 에 index 를 거는 경우
*</em></p>
<pre><code class="language-sql">CREATE INDEX IDX_CREATED_DATE ON POST
    (createdDate);</code></pre>
<p><img src="https://velog.velcdn.com/images/this_summer/post/36f56ed9-d37d-41ac-a37f-e0731ae42043/image.png" alt=""></p>
<p>range type 으로 생성된 index 를 탔지만, 여전히 결과는 다음과 같습니다.</p>
<blockquote>
<p>select query 시간 1.300 sec
cpu usage : max 53%</p>
</blockquote>
<p>여전히 대장애급 속도입니다.</p>
<p>*<em>2. memberId 에도 index 를 걸면?
*</em></p>
<pre><code class="language-sql">CREATE INDEX IDX_MEMBER_ID ON POST
    (memberId);</code></pre>
<p><img src="https://velog.velcdn.com/images/this_summer/post/4ccffc74-ca2c-4a96-bcc9-79014ffc9589/image.png" alt=""></p>
<p>IDX_CREATED_DATE, IDEX_MEMBER_ID 를 타게 됩니다. 하지만 결과는?</p>
<blockquote>
<p>select query 시간 0.971 sec
cpu usage : max 32%</p>
</blockquote>
<p>이 결과는 Database 운영 안정성에 심각하게 위험합니다.</p>
<p>위처럼 대량의 데이터를 대상으로 Select Query 을 실행하는 경우는 성능 개선이 필요합니다. </p>
<blockquote>
<p><em><strong>성능을 개선하기 위해서는 Database Engine 에서 DISK 에 대한 I/O 를 최소화하는 것이 좋습니다.</strong></em></p>
</blockquote>
<p>*<em>3. createDate, memberId 순으로 복합키를 걸어버리면?
*</em></p>
<pre><code class="language-sql">CREATE INDEX IDX_CREATED_DATE_MEMBER_ID ON POST
    (createdDate, memberId);</code></pre>
<p><img src="https://velog.velcdn.com/images/this_summer/post/82451a36-97e5-48c2-9d65-be78e1eee0e5/image.png" alt=""></p>
<p>생성된 index 를 optimizer 가 Query Plan 에서 잘 사용하는 것을 볼 수 있습니다. 결과는?</p>
<blockquote>
<p>select query 시간 0.082 sec
cpu usage :  max 3%</p>
</blockquote>
<p>편안합니다. 속도가 엄청 개선됬네요.</p>
<p>다시 말하지만, <strong>query optimization</strong> 에서 중점을 둬야 하는 것은 데이터베이스의 <strong>DISK I/O 를 최소화</strong>하는 것입니다.</p>
<p>실제 createDate, memberId 로 index 를 생성하면 자료구조는 <strong>B+tree</strong> 구조로 클러스터링 되어 생성이 됩니다. 클러스터링 된 데이터의 각 테이블은 아래처럼 구성됩니다.
<img src="https://velog.velcdn.com/images/this_summer/post/75e2e0b4-9b38-406b-b70e-cf5b5348b6ab/image.png" alt=""></p>
<p>createDate, memberId, pk인 id 3가지에 대한 정보가 index table 에 포함되게 됩니다.</p>
<p>따라서 <strong>composite index</strong> 를 통해서 접근하여 필요한 정보가 모두 <strong>index table</strong>에 <strong>존재</strong>하기 때문에 <strong>disk i/o</strong> 가 <strong>발생하지 않고</strong> 속도가 위처럼 <strong>개선</strong>이 되는거죠. 이런 방식을 <em><strong>covering index</strong></em> 라고 합니다. 만약 <strong>count(id) 가 아닌 다른 필드</strong>로 카운팅을 하면 속도가 어떻게 되는지 보겠습니다.</p>
<pre><code class="language-sql">explain select createdDate, memberId, count(createdAt)
from POST
where memberId = 3 and createdDate between &#39;2019-01-01&#39; and &#39;2019-12-31&#39;
group by memberId, createdDate;</code></pre>
<p>다른 필드인 createdAt 에 대해서 counting 을 하게 되면 실제 query 실행 계획은 이전과 동일합니다.</p>
<p><img src="https://velog.velcdn.com/images/this_summer/post/890990fb-882d-4a5b-8493-dde67c6407b3/image.png" alt="">
하지만 결과는?</p>
<blockquote>
<p>select query 시간 : 0.447 sec
cpu usage : max 24%</p>
</blockquote>
<p>속도가 많이 느려졌습니다. 이유는 다음과 같습니다.</p>
<blockquote>
<p>실제 Search Query 실행은 <strong>Full Scanning</strong> 이 아닌 <strong>Range Scanning</strong> 으로 돌지만, 이전의 query 와 차이점이 있다면 covering index 로 돌지 않고, disk 에 직접 접근하게 됩니다. 따라서 속도가 무척 느려지죠.</p>
</blockquote>
<h1 id="index-의-trade-off">index 의 trade off</h1>
<p>Search Query 속도를 개선했습니다. 그럼 Insert Query 에는 어떤 영향이 있는지 테스트를 해보도록 하겠습니다.</p>
<p><strong>memberId 6 으로 100만건 insert</strong></p>
<blockquote>
<p>100만건 insert 시간 : 53.370179892</p>
</blockquote>
<p>무려 거의 2배 가까이 증가했습니다.</p>
<h1 id="마무리">마무리</h1>
<blockquote>
<p><strong>index</strong> 를 사용을 한다는 것은 <strong>search query</strong> 의 성능을 높히기 위함이나 반대로 <strong>insert, delete, update query 에 성능을 저하</strong>시키는 것을 항상 명심하고 사용해야 합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Computer Science - Thread, Coroutine]]></title>
            <link>https://velog.io/@this_summer/Computer-Science-Thread-Coroutine</link>
            <guid>https://velog.io/@this_summer/Computer-Science-Thread-Coroutine</guid>
            <pubDate>Wed, 15 Feb 2023 11:12:39 GMT</pubDate>
            <description><![CDATA[<h1 id="process">Process</h1>
<p><a href="https://velog.io/@this_summer/Computer-Science-Process-Thread">이전 포스팅</a>에서 Process 와 Thread 에서 간단히 다뤄봤습니다. 이이서, Process, Thread 에 대해서 잠깐 다시 짚고, Concurrency, Parallelism 그리고 Coroutine 까지 다뤄보겠습니다.
<img src="https://velog.velcdn.com/images/this_summer/post/f95e2d40-335c-48b4-b581-62ea026c13b6/image.png" alt="https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<p>Process 는 독립된 메모리 영역을 할당받고, Process 내에서 실행되는 Thread 는 Process 의 Heap 영역을 공유하며, 고유한 Stack 영역을 할당받게 됩니다.</p>
<p>Process 는 최초 실행될때, OS 로 부터 특정 Physical Memory 영역과 Virtual Memory 영역을 할당 받는다고 했는데, 그럼 Process 가 점점 더 많은 메모리를 필요로 하는 경우, 어떻게 될까요?</p>
<blockquote>
<p><strong>동적 메모리 할당</strong></p>
</blockquote>
<p>프로세스는 메모리가 부족한 경우, 운영 체제에 메모리를 동적으로 요구할 수 있습니다. 운영 체제는 필요에 따라 프로세스에 추가 물리적 메모리를 할당합니다. 만약 운영 체제에 사용 가능한 물리적 메모리가 충분하지 않으면 페이징 또는 스왑과 같은 기술을 사용하여 추가 메모리를 할당할 수 있습니다.</p>
<blockquote>
<p><strong>Page file 또는 swap space</strong></p>
<p>Windows 및 Linux 와 같은 일부 운영 체제는 프로세스가 현재 사용 가능한 것보다 더 많은 메모리를 필요로 할 때 추가 물리적 메모리를 할당하기 위해 Paging 또는 Swapping 이라는 기술을 사용합니다. 운영 체제는 페이지 파일이나 스왑 공간에 프로세스 메모리의 일부를 일시적으로 디스크에 저장하고 필요에 따라 검색할 수 있습니다. 이를 통해 물리적으로 사용할 수 있는 메모리보다 더 많은 메모리를 사용할 수 있으며, 디스크에 읽고 쓰는 오버헤드로 인해 성능이 저하됩니다.</p>
</blockquote>
<h1 id="concurrency">Concurrency</h1>
<blockquote>
<p>concurrency(동시성)은 다수의 Task 를 평등하게 나눠서 실행하는 것. </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/this_summer/post/13e89228-1957-4463-9269-4c374a9e9069/image.png" alt="출처 : https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<p>10분짜리 Task 가 두개가 있다고 가정합니다.</p>
<p><img src="https://velog.velcdn.com/images/this_summer/post/fde0efd3-2cb3-450a-883e-ad5842e45a65/image.png" alt="출처 : https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<p>Concurrency 하게 실행된다 ~ 라는 것은 Task 1, Task 2 가 마치 동시에 실행되는 것처럼 보인다. 라는 말입니다.</p>
<p>다시 말해 쉽게 생각하면 Single Core 컴퓨터가 있다고 생각할때, 여러 개의 프로그램이 실행되야 되는 경우, 실질적으로 CPU는 한 시점에 하나의 프로그램만 실행하고 있지만, 빠른 전환으로 여러 개를 실행하는 것처럼 실행된다라는 의미입니다.</p>
<h1 id="parallelism">Parallelism</h1>
<blockquote>
<p>Parallelism(병렬성)은 다수의 Task를 한번에 실행하는 것.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/this_summer/post/10fe5010-cde3-4781-8d43-4f6e22446cdd/image.png" alt="출처 : https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<p>위와 동일한 Task 들이 Parallelism 하게 실행된다라는 것은 실질적으로 동시에 실행되는 것처럼 보이는 것이 아닌 병렬적으로 실행된다 라는 의미입니다.</p>
<p>예로서, 목수 한명이 두개의 집을 짓는 경우 1번 집, 2번 집을 돌아가면서 짓는 것은 동시성이지만, 목수 두명이 각 각의 집을 짓는 것은 Parallelism, 즉 병렬성이다 라고 볼 수 있습니다.</p>
<h1 id="coroutine-">Coroutine ?</h1>
<blockquote>
<p>코루틴(coroutine)은 읽기 쉽고 유지보수 가능한 방식으로 비동기 비차단 코드를 작성하는 데 사용할 수 있는 가볍고 협력적인 실행 스레드이다. 독립적으로 동시에 실행되는 기존 스레드와 달리 코루틴은 _<strong>협력적으로 실행</strong>_되며, 이는 코루틴이 한 번에 하나씩 실행되고 필요에 따라 다른 코루틴에 제어를 제공한다는 것을 의미한다.</p>
</blockquote>
<p>프로그래밍에서 코루틴은 종종 I/O 바운드 및 CPU 바운드 연산, 네트워크 프로그래밍, 이벤트 구동 프로그래밍과 같은 작업에 사용된다. <strong>여러 스레드를 생성하고 관리하는 오버헤드 없이 여러 태스크를 효율적으로 실행할 수 있는 방식으로 코드를 구성하는 방법을 제공</strong>합니다.</p>
<blockquote>
</blockquote>
<p>코루틴은 <strong>Python, Lua, Kotlin</strong>과 같은 일부 프로그래밍 언어로 구현되며 특별한 키워드나 라이브러리를 사용하여 만들 수 있다. 전통적인 스레드 기반 동시성에 대한 인기 있는 대안이며 <strong>성능 향상, 리소스 사용 감소, 읽기 쉽고 유지 관리 가능한 코드</strong> 등 많은 이점을 제공한다</p>
<h1 id="coroutine-과-thread-의-차이">Coroutine 과 Thread 의 차이</h1>
<p>코루틴과 스레드는 모두 프로그램에서 동시성을 처리하는 방법이지만 몇 가지 주요 차이점이 있습니다.</p>
<blockquote>
<p><strong>Task 의 단위</strong> : Thread 는 Task 단위가 Thread 이지만, Coroutine 의 Task 단위는 Object 입니다. 아래에서 자세하게 다루겠습니다.</p>
</blockquote>
<blockquote>
<p><strong>실행</strong>: 스레드는 독립적으로 동시에 실행되는 반면 코루틴은 협력적으로 실행되므로 한 번에 하나씩 실행되고 필요에 따라 다른 코루틴에 제어를 제공한다. 따라서 코루틴이 스레드보다 가볍고 리소스 집약적이지 않다.</p>
</blockquote>
<blockquote>
<p><strong>동기화</strong>: 스레드는 공유 데이터에 대한 액세스를 조정하기 위해 잠금, 세마포어, 모니터와 같은 동기화 메커니즘을 필요로 하며, 코루틴은 간단한 함수 호출과 데이터 공유를 통해 통신하고 조정할 수 있다.</p>
</blockquote>
<blockquote>
<p><strong>오버헤드</strong>: 스레드에는 더 많은 메모리와 CPU 시간이 필요하기 때문에 스레드를 만들고 관리하는 것이 코루틴을 만들고 관리하는 것보다 리소스 집약적일 수 있다.</p>
</blockquote>
<blockquote>
<p><strong>디버깅</strong>: 다중 스레드의 실행 흐름과 상태를 추적하는 것이 더 어렵기 때문에 다중 스레드 코드를 디버깅하는 것은 코루틴을 디버깅하는 것보다 더 어려울 수 있다.</p>
</blockquote>
<blockquote>
<p><strong>가독성</strong>: 코루틴은 비동기 코드를 이해하고 수정하기 쉬운 방식으로 구조화하는 방법을 제공하기 때문에 코드를 더 읽기 쉽고 유지할 수 있다.</p>
</blockquote>
<p>일반적으로 코루틴은 <strong>I/O 바운드이거나 외부 소스의 결과를 기다려야 하는 작업에 적합</strong>한 반면 스레드는 <strong>병렬 처리를 활용할 수 있는 CPU 바운드 작업에 더 적합</strong>한 선택입니다. 코루틴과 스레드 중에서 선택할 수 있는 항목은 응용프로그램의 특정 요구사항과 시스템에서 사용할 수 있는 리소스에 따라 달라집니다.</p>
<p><img src="https://velog.velcdn.com/images/this_summer/post/2018f81d-1323-44d0-8d5b-01c23abd763c/image.png" alt="출처 : https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<p>그림을 보면서 다시 설명해보겠습니다.</p>
<p>위의 그림은 Single Core 인 CPU 에서 Thread 의 Context Switching 이 발생하는 예시입니다. </p>
<ol>
<li>Thread A 에서 Thread B 로 컨텍스트 스위칭</li>
<li>Thread A 는 Thread B 가 완료까지 Blocking, 즉 Thread A 의 자원은 사용 불가 상태</li>
<li>Thread B 가 완료되면, Thread A 가 다시 시작</li>
</ol>
<p><strong>그럼 Coroutine 은?</strong>
<img src="https://velog.velcdn.com/images/this_summer/post/963403a0-0bae-4f96-8283-52ddfbf48866/image.png" alt="출처 : https://aaronryu.github.io/2019/05/27/coroutine-and-thread/"></p>
<ol>
<li>Thread A 가 Task 1 (Object) 를 수행하다가 작업 전환</li>
<li>Thread A 는 수행하던 Task 1 의 상태를 저장하고 Task 2 로 교체</li>
<li>Task 2 가 완료되면, Thread A 는 다시 Task 1 으로 교체하여 작업 수행</li>
</ol>
<p>즉 Thread 는 작업의 전환에서 컨텍스트 스위칭이 발생하지만, Coroutine 의 경우 수행하던 Object 만 교체하면 동일 Thread 에서 다른 작업을 수행할 수 있음으로, Thread Level 의 컨텍스트 스위칭이 필요없습니다. 그래서 Coroutine 을 Lightweight Thread(경량 스레드) 라고 부릅니다.</p>
<h1 id="references">References</h1>
<p><a href="https://aaronryu.github.io/2019/05/27/coroutine-and-thread/">https://aaronryu.github.io/2019/05/27/coroutine-and-thread/</a>
<a href="https://jslee-tech.tistory.com/42">https://jslee-tech.tistory.com/42</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Network - subnet mask]]></title>
            <link>https://velog.io/@this_summer/Network-subnet-mask</link>
            <guid>https://velog.io/@this_summer/Network-subnet-mask</guid>
            <pubDate>Tue, 14 Feb 2023 14:13:34 GMT</pubDate>
            <description><![CDATA[<h1 id="subnet">Subnet</h1>
<blockquote>
<p>서브넷은 IP 네트워크를 더 작은 네트워크 세그먼트로 분할하는 논리적 분할입니다. 이를 통해 네트워크 관리자는 대규모 네트워크를 보다 작고 관리하기 쉬운 섹션으로 분할하여 네트워크 보안, 트래픽 흐름 및 리소스 할당을 보다 효과적으로 제어할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>IP 네트워킹에서 서브넷은 서브넷 마스크에 의해 정의되며, 서브넷 마스크는 IP 주소를 네트워크 주소와 호스트 주소의 두 부분으로 나누는 데 사용됩니다. 네트워크 주소는 서브넷을 식별하고 호스트 주소는 서브넷 내의 특정 장치를 식별합니다. 네트워크 관리자는 서브넷을 사용하여 네트워크 트래픽의 흐름을 제어하고, 네트워크 보안을 개선하고, IP 주소를 보존할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>예를 들어 IP 주소 범위가 192.168.1.0/24인 네트워크를 생각해 보면 이 네트워크에는 256개의 IP 주소가 있습니다. 네트워크 관리자는 이 네트워크를 각각 고유한 서브넷 마스크를 가진 더 작은 서브넷으로 분할하여 특정 IP 주소 범위를 네트워크의 여러 부서 또는 섹션에 할당할 수 있으므로 네트워크 리소스 및 보안을 보다 효과적으로 제어할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>서브넷화는 대규모 네트워크를 보다 효과적이고 효율적으로 관리하는 데 도움이 되므로 네트워크 관리자에게 중요한 도구입니다.</p>
</blockquote>
<h1 id="ip-address">IP Address</h1>
<blockquote>
<p>IP 주소(Internet Protocol Address) 는 32비트 숫자입니다. IP 주소는 TCP/IP 네트워크에서 호스트(컴퓨터 또는 프린터나 라우터와 같은 기타 장치)를 고유하게 식별합니다.</p>
</blockquote>
<blockquote>
<p>일반적으로 192.168.123.132와 같이 마침표로 구분된 4개의 숫자가 있는, 점으로 분리된 10진수 형식으로 표시됩니다. </p>
</blockquote>
<h1 id="subnet-mask">Subnet Mask</h1>
<blockquote>
<p>서브넷 마스크는 IP 주소를 네트워크 주소와 호스트 주소의 두 부분으로 나누는 데 사용되는 32비트 숫자입니다. 서브넷 마스크는 IP 주소와 함께 사용하여 서브넷 또는 더 큰 네트워크 내의 더 작은 네트워크를 정의합니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/this_summer/post/11e3f5b9-7460-4917-b815-ed90b7a10164/image.png" alt=""></p>
<ul>
<li>Mac OS 에서 TCP/IP 섹션으로 가면 IPv4 주소, 서브넷 마스크, 라우터 주소를 알 수 있습니다.</li>
<li>Subnet Mask 255.255.255.0 를 IPv4 주소에 AND 연산하면 Network Address 와 Host Address 를 구분할 수 있습니다. AND 연산의 결과는 Network Address, Subnet Mask 기준 0으로 채워진 범위는 Host Address</li>
</ul>
<p><img src="https://velog.velcdn.com/images/this_summer/post/06f2f82b-d979-4a3c-a4d1-f6d47bbc0a4f/image.png" alt=""></p>
<h1 id="subnetting">Subnetting</h1>
<blockquote>
<p>네트워크를 효율적으로 관리하기 위해서, 네트워크를 더 작고 관리하기 쉬운 하위 네트워크로 나누는 프로세스입니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/this_summer/post/4f45488c-63b4-467e-a314-529aa84fe9f6/image.png" alt=""></p>
<p>Subnet Mask 에 따라 IP 주소의 범위가 나눠집니다.</p>
<ul>
<li>255.255.255.128 의 경우<ul>
<li>255.255.255.128 -&gt; 1111 1111 1111 1111 1111 1111 1000 0000</li>
<li>0의 개수가 7개 즉 2^7 개의 주소를 할당받는 서브넷으로 구성합니다. 이 값은 128이 되구요. 전체 할당할 수 있는 host 갯수 256을 128 로 나누면 2 가 나옵니다. 따라서 해당 Subnet Mask 를 사용하여 Subnetting 을 하면 2개의 Subnet 으로 나눌수 있습니다.</li>
</ul>
</li>
</ul>
<ul>
<li><p>255.255.255.192 의 경우</p>
<ul>
<li>255.255.255.192 -&gt; 1111 1111 1111 1111 1111 1111 1100 0000</li>
<li>0의 개수가 6개 2^6 개의 주소를 할당받는 서브넷으로 구성. 이 값은 64. 전체 256/64 = 4. 즉 4개의 Subnet 으로 나눌수 있음.</li>
</ul>
</li>
<li><p>255.255.255.224 로 다시 해볼까요</p>
</li>
<li><p>255.255.255.224 -&gt; 1111 1111 1111 1111 1111 1111 1110 0000</p>
</li>
<li><p>0이 5개 2^5개의 주소 범위를 가지는 서브넷을 구성. 256/32 = 8, 즉 8개의 서브넷으로 나눠질 수 있습니다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Computer Science - Process, Thread]]></title>
            <link>https://velog.io/@this_summer/Computer-Science-Process-Thread</link>
            <guid>https://velog.io/@this_summer/Computer-Science-Process-Thread</guid>
            <pubDate>Tue, 14 Feb 2023 00:34:45 GMT</pubDate>
            <description><![CDATA[<p>개발을 하다보면 Process 와 Thread 에 대한 말이 참 많습니다. 다. Process 와 Thread 을 이해하는 것이 왜 업무적으로 중요한지 정리해볼까 합니다.</p>
<h1 id="span-stylecolorindianredprocessspan"><span style="color:indianRed">Process</span></h1>
<blockquote>
<p>프로세스(process) 는 실행중에 있는 프로그램을 의미합니다.
프로그램은 컴퓨터에서 실행될 때 특정 작업을 수행하는 일련의 명령어들의 집합입니다.
따라서 실행중에 있는 프로그램, 즉 프로세스 의미는 메모리에 적재되어 일련의 명령어들이 수행되고 있는 상태를 이야기합니다.</p>
</blockquote>
<h3 id="span-stylecolorskyblueprocess-and-threadspan"><span style="color:skyblue">Process and Thread</span></h3>
<p><img src="https://velog.velcdn.com/images/this_summer/post/5263390a-1a1c-475c-ac91-bbb1ba5aba48/image.png" alt=""></p>
<blockquote>
<ul>
<li>프로세스는 독립된 메모리 영역을 할당</li>
</ul>
</blockquote>
<ul>
<li>code</li>
<li>data</li>
<li>heap</li>
<li>stack</li>
</ul>
<blockquote>
<ul>
<li>프로세스는 독립된 자원을 할당받음으로, 다른 프로세스의 자원에 접근하기 위해서는 IPC(Inter-process communication, 파이프, 파일, 소켓) 방식을 사용</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>스레드는 프로세스 내에서 실행되는 실행 단위</li>
</ul>
</blockquote>
<ul>
<li>그림에서는 stack 만 그렸지만, program counter, stack, register 의 집합으로 구성</li>
<li>스레드는 프로세스의 stack 영역을 할당받고, 프로세스의 나머지 영역 code, data, heap 영역은 공유</li>
</ul>
<blockquote>
<p>프로세스와 스레드를 비교하자면, 프로세스는 회사, 스레드는 직원과 같습니다.
회사는 사무실(독립된 자원)을 할당받고, 직원는 노트북과 같은 업무을 위한 자산(스택)을 
할당받고 사무실은 공유하여 사용합니다.
다수의 직원은 공유된 영역을 사용하기에, 직원이 사용한 흔적은 고스란히 다른 직원에게 영향을 끼칩니다. 공유된 영역에서 직원들은 프로젝트에 대한 이야기나 업무에 대한 이야기를 합니다. 반면 회사와 회사의 협업에 있어서는 외부의 미팅을 잡거나, 다른 회사로 가거나 하는 번거로운 작업이 필요합니다.</p>
</blockquote>
<h3 id="span-stylecolorskyblueprocess-and-virtual-memoryspan"><span style="color:skyblue">Process and Virtual Memory</span></h3>
<blockquote>
<p>가상 메모리(Virtual memory)는 운영 체제가 실제보다 더 많은 양의 메모리에 접근할 수 있다는 착각을 주기 위해 사용하는 메모리 관리 기술입니다. 사용 가능한 총 물리적 메모리 양이 모든 프로세스의 결합된 메모리 요구 사항보다 적더라도 각각의 가상 주소 공간을 가진 여러 프로세스가 동시에 실행할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>가상 메모리는 프로세스의 메모리를 고정된 크기의 페이지 <em>(일반적으로 4KB, Architecture 따라 8KB, 16KB 를 사용하기도 함)</em> 로 분할하여 작동합니다. 각 페이지에는 가상 주소가 할당되며, 이 주소는 프로세스에서 페이지 내용에 액세스하는 데 사용됩니다. 가상 주소는 운영 체제에서 실제 물리적 메모리 위치에 해당하는 물리적 주소로 변환됩니다. 가상 주소와 물리적 주소의 매핑은 운영 체제에서 관리합니다.</p>
</blockquote>
<blockquote>
<p>프로세스가 현재 실제 메모리에 없는 페이지에 액세스해야 하는 경우 페이지 오류(Page Fault)가 발생합니다. 그런 다음 운영 체제는 하드 드라이브와 같은 보조 스토리지에서 필요한 페이지를 검색하여 물리적 메모리로 가져옵니다. 사용 가능한 물리적 메모리가 없는 경우 운영 체제는 새 페이지를 위한 공간을 확보하기 위해 다른 페이지로 전환하도록 선택할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>가상 메모리는 필요에 따라 메모리의 일부를 물리적 메모리로 페이징함으로써 프로세스가 물리적으로 사용 가능한 것보다 더 많은 메모리에 액세스할 수 있게 합니다. 또한 프로세스가 다른 프로세스에 속하는 메모리에 액세스하는 것을 방지하는 메모리 보호 기능도 제공합니다. 그러나 가상 메모리는 RAM의 메모리에 액세스하는 것에 비해 보조 스토리지에 들어오고 나가는 페이징이 느릴 수 있기 때문에 성능 비용이 수반됩니다</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/this_summer/post/090bfcca-de4d-49dd-bb51-8ffec00a6c5d/image.png" alt=""></p>
<ul>
<li>그림으로 설명하자면 위와 같습니다. 실제로 프로세스가 할당받는 메모리는 Physical Memory 와 2차 메모리인 HDD 가 됩니다.</li>
<li>프로세스가 실제 메모리에 없는 페이지, 즉 파란색 섹션에 존재하지 않는 페이지에 접근하는 경우, 즉 빨간색 섹션인 HDD (보조 스토리지) 에 접근하게 되는 경우 Physical Memory 에 접근하는 성능보다 느리기때문에, 속도가 느려집니다.</li>
</ul>
<h3 id="span-stylecolorskyblueprocess-를-많이-실행해서-cpu-자원이-부족하면span"><span style="color:skyblue">Process 를 많이 실행해서 CPU 자원이 부족하면?</span></h3>
<blockquote>
<p>CPU 리소스가 애플리케이션의 요구 사항을 처리하기에 충분하지 않으면 속도 저하, 지연 또는 애플리케이션 충돌과 같은 성능 문제가 발생할 수 있습니다. 이 문제는 애플리케이션에 시스템에서 사용할 수 있는 것보다 더 많은 CPU 시간이 필요하거나 다른 프로세스가 동일한 CPU 리소스를 놓고 경쟁(Race Condition)하는 경우에 발생할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>CPU에 과부하가 걸리면 운영 체제는 다양한 스케줄링 기법을 사용하여 CPU를 사용하는 프로세스의 우선순위를 정할 수 있는데, 이로 인해 현재 실행되지 않는 프로세스의 지연 및 대기 시간이 발생하여 응용 프로그램이 느리거나 응답하지 않을 수 있습니다.</p>
</blockquote>
<ul>
<li>어플리케이션 충돌로 인해 데이터 손상 또는 시스템 불안정과 같은 시스템의 다른 문제가 발생할 수도 있으며, 시스템 및 사용자 환경에 미치는 영향을 최소화하기 위해 가능한 한 빨리 애플리케이션 충돌을 식별하고 해결하는 것이 중요합니다. (생각보다 자주 자원 고갈되서 충돌됨)
가장 좋은 방법은 어플리케이션을 모니터링하다가, 특정 Threshhold 이상의 Resource 을 차지하는 경우, Scale up, out 을 자동화하는 구성을 설정하는 것이 좋습니다.</li>
</ul>
<h1 id="span-stylecolorindianrednextspan"><span style="color:indianRed">Next</span></h1>
<p>Multi-Process and Multi-Thread</p>
<h1 id="span-stylecolorindianredreferecespan"><span style="color:indianRed">Referece</span></h1>
<blockquote>
<ul>
<li><a href="https://www.youtube.com/watch?v=x-Lp-h_pf9Q">https://www.youtube.com/watch?v=x-Lp-h_pf9Q</a></li>
</ul>
</blockquote>
<ul>
<li><a href="https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html">https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Part 1. Postgresql, 내가 널 왜 써야 하니?]]></title>
            <link>https://velog.io/@this_summer/Part-1.-Postgresql-%EB%82%B4%EA%B0%80-%EB%84%90-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8B%88</link>
            <guid>https://velog.io/@this_summer/Part-1.-Postgresql-%EB%82%B4%EA%B0%80-%EB%84%90-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8B%88</guid>
            <pubDate>Sun, 12 Feb 2023 07:53:18 GMT</pubDate>
            <description><![CDATA[<p>업무적으로 사용하는 Database 는 Postgresql 입니다. 입사 이후로 사용해와서, 왜 우리는 Postgresql 을 사용하나? 라는 고민을 던져본 적이 없었던 것 같네요. 그래서 오늘은 이 부분에 대한 고민을 해보려 합니다.</p>
<p>먼저 다양한 데이터베이스 타입 중 왜 RDB 인가, RDB 의 장점이 무엇인가에 대해 알아보겠습니다.</p>
<h1 id="relational-database"><em>Relational DataBase</em></h1>
<p>우선 Relational Database의 장점을 정리해보겠습니다.</p>
<h3 id="structured-data-storage">Structured Data Storage</h3>
<blockquote>
<p>Table, Row, Column 을 사용한 구조화된 데이터 저장
이를 통한 체계적이고 효율적인 방식으로 데이터를 구성, 검색 및 조작이 가능</p>
</blockquote>
<h3 id="scalability">Scalability</h3>
<blockquote>
<p>필요에 따라 대용량 데이터를 효과적인 방법으로 Scale Up, Down 이 용이. 대부분의 Database 는 Scale up, down 이 어렵진 않음.</p>
</blockquote>
<h3 id="data-integrity">Data Integrity</h3>
<blockquote>
<p>Data Integrity, Accuracy 을 보장하기 위해 제약 조건과 규칙을 적용하는데, 이를 통해 Data 의 Inconsistency 와 error 을 방지</p>
</blockquote>
<h3 id="queryability">Queryability</h3>
<blockquote>
<p>SQL 을 통한 유연하고 효과적인 데이터 조작 및 검색</p>
</blockquote>
<h3 id="data-normalization">Data Normalization</h3>
<blockquote>
<p>Data Normalization 프로세스를 따름으로 Data Redundancy 을 줄이고, Data Consistency 을 개선</p>
</blockquote>
<h3 id="mature-technology">Mature Technology</h3>
<blockquote>
<p>수십년동안 신뢰성, 안정성이 개선되어 왔고, 많은 회사에서 사용하고 있음이 성숙한 기술임을 입증</p>
</blockquote>
<h1 id="postgresql"><em>Postgresql</em></h1>
<p>왜 Postgresql 을 써야 하나? 어떤 이점이 개발자들이 Postgesql 을 선택하게 할까요?</p>
<ul>
<li>복잡한 쿼리에 탁월</li>
<li>대용량 데이터 관리에 적합</li>
<li>Catalog 기반임으로 확장이 용이</li>
<li>Table, Column 에 단순히 데이터를 저장만 하지 않고, 데이터 형식, 인덱스 형식, 함수형 언어를 정</li>
<li>ORDMBS</li>
<li>MVCC</li>
<li>ACID 를 준수</li>
<li>동시 연결성이 높음</li>
<li>NoSQL 및 <a href="https://www.postgresql.org/docs/8.2/datatype.html">다양한 데이터 형식</a> 지원 (JSON, hstore, XML 포함해서 등등)</li>
<li>커뮤니티 활성 Level 이 높음</li>
<li>높은 안정성과 신뢰성을 제공</li>
</ul>
<p>여기서 모르는 내용이 몇가지 있어 정리해보겠습니다.</p>
<h3 id="1-다른-database-에-비교해서-왜-복잡한-쿼리에-탁월한가"><em>1. 다른 Database 에 비교해서 왜 복잡한 쿼리에 탁월한가?</em></h3>
<p>Postgresql 은 복잡한 쿼리를 어떻게 실행하기에 다른 DBMS 에 비해 탁월하다고 평가할까요?</p>
<ul>
<li>Query Optimizer</li>
<li>Indexing</li>
<li>MVCC</li>
<li>Cost-Based Optimization</li>
<li>User-Defined Functions</li>
</ul>
<h4 id="query-optimizer">Query Optimizer</h4>
<blockquote>
<p>PostgreSQL에는 쿼리를 분석하고 가장 효율적인 실행 계획을 결정할 수 있는 강력한 Query Optimizer Tool 이 있습니다. Optimizer Tool 은 테이블의 데이터 분포, 인덱스의 존재 및 여러 작업의 비용과 같은 다양한 요소를 고려하여 쿼리를 실행하는 가장 좋은 방법을 결정합니다.</p>
</blockquote>
<h4 id="indexing">Indexing</h4>
<blockquote>
<p>PostgreSQL은 B-tree, Hash, GiST, GIN, SP-GiST 를 포함한 광범위한 인덱스 유형을 지원하므로 효율적인 데이터 검색이 가능합니다. Query Optimizer Tool 는 이러한 인덱스를 사용하여 쿼리를 실행하는 데 필요한 데이터를 신속하게 찾을 수 있으므로 데이터 검색에 필요한 시간을 줄일 수 있습니다.</p>
</blockquote>
<h4 id="mvcc">MVCC</h4>
<blockquote>
<p>PostgreSQL은 MVCC를 사용하여 데이터에 대한 동시 액세스를 관리하므로 여러 트랜잭션이 동일한 데이터에 동시에 액세스하고 수정할 수 있습니다. 그래서 다른 트랜잭션에 의해 차단되지 않고 여러 행과 테이블에 액세스해야 하는 복잡한 쿼리를 지원합니다.</p>
</blockquote>
<h4 id="cost-based-optimization">Cost-Based Optimization</h4>
<blockquote>
<p>Postgresql 은 Cost-Based Optimization model 을 사용하는데, 이 model 은 서로 다른 작업을 실행하는 데 드는 비용을 추정하고 추정 비용이 가장 낮은 계획을 선택합니다. 따라서 데이터 크기, 인덱스 존재 및 테이블의 데이터 분포와 같은 요인을 고려하여 쿼리 실행 방법에 대한 정보에 입각한 결정을 내립니다.</p>
</blockquote>
<h4 id="user-defined-functions">User-Defined Functions</h4>
<blockquote>
<p>PostgreSQL은 User-Defined Functions 을 지원하며, User-Defined Functions 와 쿼리에서 사용할 수 있는 Function 를 만드는 데 사용할 수 있습니다. 이를 통해 사용자는 데이터베이스의 기능을 확장하고 특정 사용 사례에 최적화된 Custom Function 을 만들 수 있습니다.</p>
</blockquote>
<h3 id="2-catalog-기반"><em>2. Catalog 기반</em></h3>
<blockquote>
<p>Postgresql 의 Catalog 는 Database Object 를 정의하고 관리하는 필수적인 요소입니다. 개발자는 Catalog 를 통해서 custom data type, index type, custom function 등 다양한 customization 이 가능하고, 이는 postgresql 을 더 확장성 있게 사용할 수 있도록 합니다.</p>
</blockquote>
<h3 id="3-ordbms"><em>3. ORDBMS</em></h3>
<blockquote>
<p>데이터 모델링 유연성: ORDBMS는 배열, 집합, 객체와 같은 복잡한 데이터 유형을 사용할 수 있게 하여 데이터 모델링에 더 많은 유연성을 제공합니다.</p>
</blockquote>
<blockquote>
<p>상속: ORDBMS는 상속을 지원하여 개발자가 객체의 클래스와 하위 클래스를 정의할 수 있게 함으로써 데이터 구성을 개선하고 중복성을 줄일 수 있습니다.</p>
</blockquote>
<blockquote>
<p>성능 향상: ORDBMS는 특정 유형의 데이터에 대해 쿼리를 최적화하고 조인 및 기타 복잡한 작업의 필요성을 줄여 성능을 향상시킬 수 있습니다.</p>
</blockquote>
<blockquote>
<p>확장성: ORDBMS는 사용자 지정 데이터 유형, 기능 및 연산자를 정의하고 관리하기 위한 프레임워크를 제공하므로 데이터베이스의 기능을 쉽게 확장할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>객체 지향 프로그래밍과의 통합: ORDBMS는 객체 지향 프로그래밍 언어와의 자연스러운 통합을 제공하여 개발자가 데이터베이스에서 직접 객체를 저장하고 검색할 수 있도록 합니다.</p>
</blockquote>
<h1 id="conclusion">Conclusion</h1>
<p>Postgresql 이 장점을 고려해보니, 내가 속해있는 조직이 Postgresql 을 사용하는 이유는 딱히 명확하지 않습니다. Postgresql 을 사용한다고 해서 큰 이점을 얻고 있다 라는 생각이 드는 부분이 없다고 판단이 들기 때문입니다. </p>
<p>복잡한 데이터 구조를 사용하나? <span style="color: indianRed"><strong>아니요</strong></span>
특정한 데이터 타입을 정의해서 사용해야 하나? <span style="color: indianRed"><strong>아니요</strong></span>
객체 지향적인 모델을 사용하여 데이터베이스와 통합하나? <span style="color: indianRed"><strong>아니요</strong></span></p>
<p>하지만, Postgresql 의 라이센싱 비용이나, 높은 수준의 커뮤니티 활성화는 Postgresql 을 메인 DBMS 로 선택함에 있어 큰 요인으로 작용했을거라 생각한다.</p>
<h1 id="references">References</h1>
<ul>
<li><a href="https://www.integrate.io/ko/blog/postgresql-vs-mysql-the-critical-differences-ko/">PostgreSQL과 MySQL 비교: 주요 차이점</a></li>
<li><a href="https://postgresql.kr/blog/pg_phantom_read.html">Phantom read</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터베이스 선택시 고려 사항]]></title>
            <link>https://velog.io/@this_summer/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A0%ED%83%9D%EC%8B%9C-%EA%B3%A0%EB%A0%A4-%EC%82%AC%ED%95%AD</link>
            <guid>https://velog.io/@this_summer/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%A0%ED%83%9D%EC%8B%9C-%EA%B3%A0%EB%A0%A4-%EC%82%AC%ED%95%AD</guid>
            <pubDate>Sat, 11 Feb 2023 11:00:06 GMT</pubDate>
            <description><![CDATA[<h2 id="업무에-사용할-데이터베이스를-검토할때-어떤-부분을-고려해야-하는가">업무에 사용할 데이터베이스를 검토할때 어떤 부분을 고려해야 하는가?</h2>
<h3 id="span-stylecolorindianredscalabilityspan"><span style="color:indianred">Scalability</span></h3>
<blockquote>
<p>Scalability 은 애플리케이션에 대한 수요가 증가함에 따라 증가하는 데이터와 사용자를 처리할 수 있는 데이터베이스 관리 시스템의 기능입니다. Scalability 는 데이터베이스를 선택할 때 중요한 고려 사항입니다. 데이터베이스가 시간이 지남에 따라 예상되는 데이터 증가를 수용하고 데이터와 사용자의 양이 증가함에 따라 우수한 성능을 제공할 수 있도록 보장하기 때문입니다.</p>
</blockquote>
<p>확장성에는 다음과 같은 여러 가지 유형이 있습니다</p>
<h4 id="span-stylecolorskybluevertical-scalabilityspan"><span style="color:skyblue">Vertical Scalability</span></h4>
<blockquote>
<p>기존 서버에 처리 능력이나 스토리지와 같은 리소스를 추가하여 데이터 증가를 수용하는 것을 의미합니다.</p>
</blockquote>
<h4 id="span-stylecolorskybluehorizontal-scalabilityspan"><span style="color:skyblue">Horizontal Scalability</span></h4>
<blockquote>
<p>이는 여러 서버에 분산되고 데이터 양을 늘릴 수 있도록 데이터베이스 클러스터에 서버를 추가하는 것을 의미합니다.</p>
</blockquote>
<h4 id="span-stylecolorskyblueread-scalabilityspan"><span style="color:skyblue">Read Scalability</span></h4>
<blockquote>
<p>데이터베이스가 성능에 영향을 미치지 않고 쿼리와 같이 증가하는 읽기 작업을 처리할 수 있는 기능을 말합니다.</p>
</blockquote>
<h4 id="span-stylecolorskybluewrite-scalabilityspan"><span style="color:skyblue">Write Scalability</span></h4>
<blockquote>
<p>이는 데이터베이스가 성능에 영향을 미치지 않고 데이터 삽입, 업데이트 및 삭제와 같이 증가하는 쓰기 작업을 처리할 수 있는 기능을 의미합니다.</p>
</blockquote>
<p>확장성이 중요한 이유는 데이터와 사용자의 양이 증가함에 따라 데이터베이스가 지속적으로 우수한 성능을 제공할 수 있도록 지원하기 때문입니다. 또한 확장성이 높은 데이터베이스 관리 시스템은 마이그레이션할 필요 없이 데이터베이스가 시간이 지남에 따라 예상되는 데이터 증가를 수용할 수 있습니다.</p>
<p><strong><em>Postgresql</em></strong> 를 포함하여 데이터 증가를 처리하는 데 적합한 여러 데이터베이스 관리 시스템이 있습니다. <strong><em>SQL, MySQL</em></strong> 및 <em><strong>Microsoft SQL Server</strong></em>. 이러한 각 데이터베이스에는 고유한 장단점이 있으므로 특정 요구사항을 기준으로 각 데이터베이스를 평가하는 것이 중요합니다.</p>
<h3 id="span-stylecolorindianredperformancespan"><span style="color:indianred">Performance</span></h3>
<blockquote>
<p>데이터베이스는 데이터 양이 증가하더라도 성능이 우수해야 합니다. 여기에는 데이터베이스의 응답성 뿐만 아니라 쿼리 및 데이터 작업 속도와 같은 요소가 포함됩니다. </p>
<p><a href="https://benchant.com/ranking/database-ranking">Database Benchmark Ranking 비교</a></p>
</blockquote>
<p>Database Performance Metric 종류는 다음과 같습니다.</p>
<span style="color:MediumSlateBlue">

<ol>
<li>Read Latency</li>
<li>Write Latency</li>
<li>Throughput</li>
<li>Concurrency</li>
</ol>
</span>

<p>데이터베이스는 목적성을 가지고 설계되었기에 요구사항에 맞는 데이터베이스 선택이 가능합니다.</p>
<p>예를 들어 위 Metric 중 High Concurrency 가 요구되는 상황이라면?</p>
<ul>
<li>Amazon DynamoDB 및 Google Cloud Bigtable과 같은 데이터베이스는 대규모 동시 워크로드를 처리, 많은 동시 연결을 처리하도록 최적화된 데이터베이스를 선택</li>
</ul>
<p>Read, Write Latency 를 최우선으로 고려</p>
<ul>
<li>Benchmark 결과로 빠른 Latency 를 가지는 Couchbase Server CE v7.0.0 를 고려</li>
</ul>
<p>높은 Throughput 이 필요하면?</p>
<ul>
<li>ScyllaDB v4.5.1 를 고려</li>
</ul>
<h3 id="span-stylecolorindianreddata-modelingspan"><span style="color:indianred">Data Modeling</span></h3>
<blockquote>
<p>데이터베이스가 애플리케이션에 필요한 데이터 모델링 접근 방식을 지원하는지? 데이터 간의 복잡한 관계를 저장할 수 있는 기능, 다양한 데이터 유형에 대한 지원, 데이터에 대한 제약 조건을 적용할 수 있는 기능과 같은 요소를 고려합니다.</p>
</blockquote>
<p>데이터의 구조에 따라 Database 를 선택하는 것이 중요합니다. 간단히 데이터의 구조에 따른 데이터베이스 유형을 다뤄보겠습니다.</p>
<h4 id="span-stylecolorskybluerelational-databasespan"><span style="color:skyblue">Relational Database</span></h4>
<p>행과 열이 있는 테이블에 데이터를 저장하고 엄격한 스키마를 적용합니다. 따라서 <span style="color:salmon">표로 쉽게 표현할 수 있는 구조화된 데이터</span>에 적합합니다. </p>
<ul>
<li>MySQL</li>
<li>PostgreSQL</li>
<li>Oracle</li>
</ul>
<h4 id="span-stylecolorskybluenosql-databasespan"><span style="color:skyblue">NoSQL Database</span></h4>
<p> <span style="color:salmon">키-값 쌍, 문서 및 그래프 구조를 포함한 다양한 형식의 데이터</span>를 저장합니다. Relational Database 보다 유연한 경우가 많기 때문에 보다 동적이고 비정형적인 데이터를 사용할 수 있습니다. </p>
<ul>
<li>MongoDB</li>
<li>Cassandra</li>
<li>CouchDB</li>
</ul>
<h4 id="span-stylecolorskybluecolumnar-databasespan"><span style="color:skyblue">Columnar Database</span></h4>
<p> 행이 아닌 열에 데이터를 저장하므로 데이터를 보다 효율적으로 저장하고 검색할 수 있습니다. 데이터를 집계하여 분석하는 경우가 많은 <span style="color:salmon">빅데이터 및 데이터 웨어하우징 애플리케이션에 적합</span>합니다. </p>
<ul>
<li>Apache Cassandra</li>
<li>HBase</li>
</ul>
<h4 id="span-stylecolorskybluetime-series-databasespan"><span style="color:skyblue">Time-series Database</span></h4>
<p>TimeStamp 가 찍힌 데이터를 처리하도록 최적화되어 시간 경과에 따른 데이터의 효율적인 저장 및 검색을 가능하게 합니다. <span style="color:salmon">데이터가 높은 빈도로 생성되고 시간이 지남에 따라 분석되는 IoT 및 금융 데이터</span>에 적합합니다. </p>
<ul>
<li>IncludeDB</li>
<li>TimescaleDB</li>
</ul>
<h4 id="span-stylecolorskybluegraph-databasespan"><span style="color:skyblue">Graph Database</span></h4>
<p>데이터를 노드 및 에지로 그래프 구조에 저장하므로 관계가 복잡한 데이터를 효율적으로 저장하고 검색할 수 있습니다. Social Network Data, Recommendation Systems 및 Fraud Detection 에 적합합니다. </p>
<ul>
<li>Neo4j</li>
<li>Amazon Neptune</li>
</ul>
<p>각 유형의 데이터베이스에는 고유한 장단점이 있으며, 최선의 선택은 저장되는 데이터의 특정 요구사항과 데이터베이스에 대해 실행되는 쿼리에 따라 달라집니다.</p>
<h3 id="span-stylecolorindianredcostspan"><span style="color:indianred">Cost</span></h3>
<blockquote>
<p>Licensing, Support, Maintenace 등 포함한 Cost 가 고려되어야 합니다.</p>
</blockquote>
<h3 id="span-stylecolorindianredease-of-usespan"><span style="color:indianred">Ease of Use</span></h3>
<blockquote>
<p>Database 사용성은 매우 중요합니다. 잘 작성된 Document, 유저 친화적 인터페이스, 간편한 배포, 관리를 고려해야 합니다.</p>
</blockquote>
<h3 id="span-stylecolorindianredinteroperabilityspan"><span style="color:indianred">Interoperability</span></h3>
<blockquote>
<p>다양한 Program Language 및 Library 유무, Data Exporting, Importing 기능을 고려해봅니다.</p>
</blockquote>
<h3 id="span-stylecolorindianredcommunity-and-supportspan"><span style="color:indianred">Community and Support</span></h3>
<blockquote>
<p>Database 의 커뮤니티 활성화 Level 이 추후 운영 간의 필요한 정보를 제공받을 수 있기에 충분히 고려되어야 합니다.</p>
</blockquote>
<h3 id="span-stylecolorindianredflexibilityspan"><span style="color:indianred">Flexibility</span></h3>
<blockquote>
<p>시간이 지남에 따라 요구사항이 변화는 항상 존재합니다. 따라서 Database 를 확장할 수 있는 기능과 스키마 변경의 용이성과 같은 요소를 고려해야 합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[주니어 개발자의 회고]]></title>
            <link>https://velog.io/@this_summer/%EC%A3%BC%EB%8B%88%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@this_summer/%EC%A3%BC%EB%8B%88%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 07 Feb 2023 07:38:04 GMT</pubDate>
            <description><![CDATA[<h1 id="나는-어떤-사람인가">나는 어떤 사람인가?</h1>
<p>나는 단순히 게임이 좋아서, 재밌어서 컴퓨터공학과로 진로를 정했다. 온전히 우연이였다.
대학교 1학년에서 알려주는 C 언어는 내가 사고하는 방식으로는 전혀 이해하지 못하였다.
C 언어의 반복문, 배열, 포인터 등 너무나 어려웠고, 자퇴를 고민하게 되었다.
교수님께 상담 요청을 드렸고, 그 끝내 휴학을 하게 되었다.</p>
<p>군대를 갈까 고민을 했던 와중, 어머니께서 언어 연수 제안을 해주셨고, 운이 좋게도 나는
누나가 살고 있는 캘리포니아로 어학 연수를 가게 되었다. 1년 동안 어학 연수를 통해서 500명을
넘는 사람들을 만나게 되었고, 사람들과 어울리면서 각자의 삶을 열심히 사는 모습을 보게되었다.</p>
<p>나는 뭘하고 있었는가 라는 고민을 하게 되었고, 한국에 돌아가서 군대부터 가야겠다라는 생각을 하게 되었다. 하지만 미국 생활에 몸이 적응하지 못했는지, 좋은 컨디션으로 돌아오진 못했다.
병원을 다니면서 치료했고, 한국에 돌아와서 8개월 만에 군입대를 하게 된다. 심지어 베이비붐 세대라 그런가 군입대도 쉽지 않았다. 군대 가려면 운이 좋아야했다.</p>
<p>지금은 사라진 306 보충대로 입대를 했고, 운이 안 좋으면 간다는 강원도 철원에 6사단 훈련소에 배치를 받게 된다. 그리고 GOP 대대로 입대를 한다. 많은 남성들이 비슷하겠지만 21개월동안의 군 생활은 전역 이후의 삶에 동기부여가 되었다.</p>
<p>전역을 하고, 학교로 복학했을때, 11학번이였던 나는 15년에 복학한다. 학교 복학 이후 나는 학업에 충실하기로 했다. 도서관에서 살다싶이 했고, 공부가 재밌어졌던 시기였다. 4학년 마지막 졸업 프로젝트를 진행하면서, 개발이라는 것에 흥미가 생겼다. 사실 졸프 하기전까지 개발 공부를 하나도 안해서, 개발자로 취업하는 길이 꽤 막막했다. 쌓아온 포폴도 없었고, 뭘로 시작해야되는지 하나도 몰랐다. </p>
<h1 id="개발자로-첫-발걸음-ssafy">개발자로 첫 발걸음, SSAFY</h1>
<p>2019년에 졸업을 했다. 다들 취업을 하려면 알고리즘을 해야된다 해서 알고리즘 공부를 시작했다. 진짜 하나로 모르겠었다. 공부를 하면서도 과연 이것만 해서 취업이 되나 싶을 정도로 걱정이 많았다. 그 시기에 아는 동생이 1기로 들어간 Ssafy 2기 공고가 열렸다. 그 친구가 1기를 하다 삼성에 취업을 했기에 아 나도 이 과정에서 개발자로 성장할 수 있지 않을까 라는 생각이 들었다.</p>
<p>서류 전형을 통과하고 면접을 봤다. 알바 이런 면접이랑은 다르게 생에 첫 제대로 된 면접을 봤던 기억이다. 엄청 떨렸고, 나는 간절했다. 면접에 대한 아무런 정보 없이, 내가 왜 개발자의 길을 선택하게 됬는지, 어떤 개발자가 되고 싶은지 어필했고, 합격했다.</p>
<p>지금의 Ssafy 의 교육 과정이 많이 바뀐거 같은데, 내가 2기로 속해있을때, 전반기, 후반기로 나뉘어서 전반기에는 웹 개발자 (Java, Spring, Vue.js), 알고리즘에 집중했고, 후반기에는 실제 프로젝트 개발에 집중했다. 전반기를 통해서, 웹 전반적인 생태계를 배워서, 간단한 프로젝트는 개발할 수 있는 실력이 되었다. 후반기에서 몇가지 프로젝트를 진행했는데, 지금 생각해보면 나는 전반기에 배운 내용에서 더 발전하지 못하고 있었던 것 같다. 익숙한 내용으로 개발하려고 했고, 현재 코드에서 답답한게 뭔지 고민해보려고 하지도 않았다. 사실 그렇게 고민 안했던 이유를 생각해보면, 자만이였다. 그 시기에 나는 Naver, Kakao, Coupang, Line 등 모든 신입 개발자들이 서류만 내면 떨어지는 굴직한 기업에 서류, 알고리즘 테스트 통과하고 면접을 봤기에 그랬던게 아닌가 싶다. 그렇게 자만하던 시기에 카카오 Sumer Tech Intership 에 합격까지 했다.</p>
<h1 id="카카오-인턴십">카카오 인턴십</h1>
<p>설레는 마음으로 판교로 와서, 첫 출근을 했다. 첫 일주일은 온보딩 Week 였다. 너무나 알아야할게 많았고, 내가 과연 할 수 있을까라는 생각이 들었다. 나도 모르게 어영부영 일주일이 지나갔고, 팀 시니어 분들께서 시간을 내어 인턴 프로젝트에 대해서 설명해주셨다. 버스 데이터를 통해서 버스의 혼잡도를 예측하는 서비스를 하는 프로젝트였다. 기술 스택은 Scala, Apache Spark Framework 였다. 언어만 익히기에도 부족한 시간에 Apache Spark Framework 를 익히는건 나한테는 무리였다. 어떻게 프로젝트를 완성하고, 결과를 냈지만, 프로젝트 결과는 좋지 않았고, 팀원에게 좋은 인상을 주지 못했기에 나는 인턴십에서 탈락했다.</p>
<h1 id="인턴십-회고">인턴십 회고</h1>
<p>카카오 인턴십을 2020년 7월에 했는데, 지금 거의 3년이라는 시간이 지나서 회고를 하게 된다. 사실 팀원분들은 애초에 쉽지 않은 프로젝트를 주신게 맞다. 지금 와서 생각해보면, 신입 개발자에게 필요한 역량이 어떤것인지, 잘 성장할 수 있을지를 보는 과정이였다라는 생각이 든다. Apache Spark Framework 를 처음 사용하는 시니어 개발자를 데리고 와서 했었더라도, 쉽지 않은 프로젝트였을꺼라 생각한다.</p>
<p>지금 와서 내가 생각해보면 내가 인턴십에서 떨어진 이유들은 정체, 찾아서 도전해보지 못함, 자기 위안이였다고 본다. 나는 실제로 서비스할 수 있는 데이터를 도출해내는데 목표를 잡았었다. 그래서 코드가 느려도, 읽기 힘들어도 위안하였다. 하지만 거기서 좀 더 포커싱을 옮겨서 실제로 업무할때 사용하게 될 Apache Spark Framework 를 더 잘 사용하는 법, 예를 들어 데이터 프로세싱 과정의 속도를 개선하는, 더 가독성이 있는 코드를 작성하는 노력을 들였다면, 물어보기 전에 먼저 찾아보고 여러 데이터 프로세싱 방식 중에 지금 상황에 어떤 방식을 적용해야 되는지 고민을 미리했다면 결과는 달라졌을꺼라 생각한다.</p>
<h1 id="42seoul">42Seoul</h1>
<p>인턴십 탈락 이후 서울에서 생활하기 위해서는 난 공부할 돈이 필요했다. 카카오 인턴십을 하는 동안 모은 돈으로 취업할때까지 생활하기는 어려울거라 보았다. 그래서 또 다른 교육 과정을 찾아 공부도 하면서 취업 준비를 할 수 있는 곳을 알아보았다. 42Seoul 은 너무 적합한 교육 과정이였고, 해당 교육 과정에 지원하여 또 교육 과정에 입소하였다. 42Seoul 은 자기 주도형 개발 교육 과정이다. 강사도 교수도 존재하지 않고, 팀원을 구성해 서로 서로 도와가며 프로젝트를 완료해내는 그런 과정이다. 이 과정을 통해서 사실 리눅스 환경에 대한 기초를 닦을수 있었다. 교육 과정을 진행하면서 취업 과정도 반복했다. 그러다 몇 회사에 합격했고, 결국 현재 재직하고 있는 직장으로 오게 되었다.</p>
<h1 id="첫-직장">첫 직장</h1>
<p>첫 직장의 이미지는 자유로움 그 자체였다. 일단 첫 직장, 안정적인 월급을 주는 회사에 입사했다는 것 만으로 너무 벅찼다. 첫 몇달은 팀에서 사용하는 기술을 익히는데 바빴다. AWS 환경은 나한테 너무 낯설었고, VPC, Subnet, Load balancer, API Gateway 등 모르는 것 들 천지였다.  3달정도가 지날쯔음 프로젝트를 맡게 되었고, 제품들의 알림을 발송하는 시스템 개발을 담당하게 되었다. 첫 프로젝트라 시간을 쏟고 잘 해보려고 노력했다. 프로젝트 개발 이후 각 제품에 해당 시스템이 포함되어 지속적으로 릴리즈가 되었다. </p>
<p>해당 프로젝트가 끝난 후, 그룹에서 제공하는 제품들의 데모 프로젝트를 담당하게 되었다. 코드 개발 뿐만 아니라 배포까지 담당하였다. 책임감이 컸고, 또 잘해보려고 노력했다. 프로젝트가 잘 마무리 되었다. </p>
<p>이 프로젝트 이후 나는 잘 하고 있구나라는 자기 위안을 했다. 또 이전에 개발한 알림 시스템에 도 큰 문제가 없이 동작했다. 그래서 나는 또 내 코드는 문제가 없다라고 자만했다. 또한 나는 담당하는 업무 이외에 일에 대해서는 크게 관심을 가지지 않았다. 팀원이 무슨 일을 하던, 내가 맡은 일에만 책임감을 가지고 업무를 처리했다. 이런 여러 나의 문제점은 나의 성장에 발목을 잡게 되었다.</p>
<h1 id="회고">회고</h1>
<p>비록 늦었지만 지금이라도 나는 스스로에 대한 회고를 하고자 한다. 
나의 문제점과 개선 방법에 대해서 고민하고자 한다.</p>
<ul>
<li>세상에 문제가 없는 코드는 없다. 문제없이 잘 동작하는 코드는 존재할지 몰라도, 개선이 필요없는 코드는 없다. </li>
<li>담당하는 일 뿐만 아니라, 팀원들이 진행하는 일에 관심을 가지지 않으면, Take over 하는 과정이 쉽지 않다. 항상 팀원들이 하는 일에 관심을 가지고 기울여볼 필요가 있다.</li>
<li>입사 이후에 회사에서 일적으로 배우는 것에만 그쳤고, 위안했다. 하지만 이러한 위안은 나를 크게 성장시킬수 없다. 시간을 할애하여 기술적인 변화에 관심을 가져야 한다.</li>
</ul>
<p>어떻게 개선할 것 인가?</p>
<ul>
<li>1주일에 한번은 코드 개선 여부에 대한 필요성을 검토한다.</li>
<li>매 스크럼에 팀원들이 공유하는 내용에 대한 노트를 작성한다. 코드 개발의 경우, 어떤 부분에서 추가되었고, 개선되었는지 확인한다.</li>
<li>주 2회 Quality 있는 Blog Posting 을 하며, 기존 팀 내에서 사용하는 기술에 대한 심화 스터디, 새로운 부분에 대한 스터디 두 가지 내용에 대한 포스팅을 진행한다. 해당 스터디를 진행하며 만약 코드가 생성되었으면 Github 에 코드 내용을 첨부한다.</li>
</ul>
<p>개발자의 꾸준함은 중요하다. 그 꾸준함을 지키기 위해 노력한다 라는 말 뿐만 아니라, 나의 노력의 증거를 산출하고자 한다.</p>
<h1 id="이-글을-읽으시는-분들께">이 글을 읽으시는 분들께</h1>
<p>개발을 시작한지 2년이 조금 안된 주니어 개발자로서 개발을 시작하게 된 계기와 지금까지 어떤 개발자로 지내오고 있었는가, 왜 성장하는 개발자가 되지 못했는가에 대한 회고입니다. 따끔한 말 혹은 따뜻한 말 모두 환영합니다. 이 세상의 모든 주니어 개발자들의 성장을 응원합니다.</p>
]]></description>
        </item>
    </channel>
</rss>