<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DDIA on Jiho Kim</title><link>https://blog.wlgh7407.com/tags/ddia/</link><description>Recent content in DDIA on Jiho Kim</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 09 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.wlgh7407.com/tags/ddia/index.xml" rel="self" type="application/rss+xml"/><item><title>03 저장소와 검색</title><link>https://blog.wlgh7407.com/posts/books/ddia/260409_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-03-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%99%80-%EA%B2%80%EC%83%89/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate><guid>https://blog.wlgh7407.com/posts/books/ddia/260409_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-03-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%99%80-%EA%B2%80%EC%83%89/</guid><description>&lt;h2 id="-상세-정리"&gt;&lt;a href="#-%ec%83%81%ec%84%b8-%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;📝 상세 정리
&lt;/h2&gt;&lt;h3 id="인트로"&gt;&lt;a href="#%ec%9d%b8%ed%8a%b8%eb%a1%9c" class="header-anchor"&gt;&lt;/a&gt;인트로
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;가장 기본적인 수준에서 데이터베이스는 두가지 작업을 수행한다
&lt;ul&gt;
&lt;li&gt;데이터 저장하기&lt;/li&gt;
&lt;li&gt;데이터 제공하기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이번 장에서는 데이터베이스가 데이터를 저장하는 방법과 데이터를 찾는 방법을 설명하겠다.
&lt;ul&gt;
&lt;li&gt;이걸 왜 알아야 할까?&lt;/li&gt;
&lt;li&gt;저장소 엔진을 직접 구현하는게 아니라 선택하니까, 대략적으로는 알고 고르자.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RDB, NoSQL에 대해서 우선 할건데
&lt;ul&gt;
&lt;li&gt;로그 구조 계열 저장소 엔진&lt;/li&gt;
&lt;li&gt;페이지 지향 계열 저장소 엔진&lt;/li&gt;
&lt;li&gt;을 검토할것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="데이터베이스를-강력하게-만드는-자료구조"&gt;&lt;a href="#%eb%8d%b0%ec%9d%b4%ed%84%b0%eb%b2%a0%ec%9d%b4%ec%8a%a4%eb%a5%bc-%ea%b0%95%eb%a0%a5%ed%95%98%ea%b2%8c-%eb%a7%8c%eb%93%9c%eb%8a%94-%ec%9e%90%eb%a3%8c%ea%b5%ac%ec%a1%b0" class="header-anchor"&gt;&lt;/a&gt;데이터베이스를 강력하게 만드는 자료구조
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;걍 배시로&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_set&lt;span style="color:#f92672"&gt;(){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	echo &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;, &lt;/span&gt;$2&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; database
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;db_get &lt;span style="color:#f92672"&gt;()&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	grep &lt;span style="color:#e6db74"&gt;&amp;#34;^&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;, &amp;#34;&lt;/span&gt; database | sed -e &lt;span style="color:#e6db74"&gt;&amp;#34;s/^&lt;/span&gt;$1&lt;span style="color:#e6db74"&gt;, //&amp;#34;&lt;/span&gt; | tail -n &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;이라는 db를 만들면, 쓰기는 매우매우 빠르다.
&lt;ul&gt;
&lt;li&gt;겹쳐도 걍 뒤에 써버리고, -tail로 하나만 가져오니까.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로깅도 비슷한 느낌인걸 잘 알지 않나?&lt;/li&gt;
&lt;li&gt;이런 append-only 데이터 파일을 &lt;strong&gt;로그(log)&lt;/strong&gt; 라고 한다.
&lt;ul&gt;
&lt;li&gt;로그는 사람이 읽을 수 있는 형식일 필요도 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;암튼 db_set은 빠른데, db_get은 O(N)으로 개느리다.&lt;/li&gt;
&lt;li&gt;그래서 다른 데이터 구조가 필요한데..
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;색인&lt;/strong&gt; 에 대해서 알아보겠다.&lt;/li&gt;
&lt;li&gt;다양한 색인 구조를 살펴보고 여러 색인 구조를 비교해보자.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;색인의 일반적인 개념은 어떤 부가적인 메타데이터를 유지하는 것이다.
&lt;ul&gt;
&lt;li&gt;이는 이정표 역할을 해서, 원하는 데이터의 위치를 찾는데 도움을 준다.&lt;/li&gt;
&lt;li&gt;색인은 기본 데이터 (primary data)에서 파생된 &lt;strong&gt;추가적인&lt;/strong&gt; 구조이다.
&lt;ul&gt;
&lt;li&gt;많은 DB는 색인의 추가/삭제를 허용하고 이는 내용에 영향을 미치지 않는다.&lt;/li&gt;
&lt;li&gt;추가적인 구조의 유지보수는 오버헤드를 발생시킨다.
&lt;ul&gt;
&lt;li&gt;보통 쓰기속도를 느리게 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이것이 저장소시스템에서 중요한 트레이드오프이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="해시-색인"&gt;&lt;a href="#%ed%95%b4%ec%8b%9c-%ec%83%89%ec%9d%b8" class="header-anchor"&gt;&lt;/a&gt;해시 색인
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;key-value 데이터를 색인해보자.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;보통 dictionary type 같은거니까, hash map / hash table 등으로 구현한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;암튼 키를 데이터 파일의 바이트 오프셋(값을 바로 찾을 수 있는 위치)에 매핑해서 인메모리 해시 맵을 유지하는 전략이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;단순하지만, 많이 사용한다고한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;대표적으로 Bitcask (Riak의 기본 저장소 엔진)이 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;전부 메모리에 저장되면 고성능 읽기/쓰기를 보장한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이는 각 키 값이 자주 갱신되는 상황에 매우 적합하다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;키당 쓰기 수가 많지만 고유키가 적어서 메모리에 키 보관이 가능한 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;하지만 이를 추가만 계속 하면 디스크 공간이 부족해질텐데&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이를 위해 특정 크기의 세그먼트로 로그를 나눌 수 있겠다.&lt;/li&gt;
&lt;li&gt;그리고 그 중간과정에 대해 한번씩 정리/압축을 할 수 있겠다. (최신값만 남기기)
&lt;ul&gt;
&lt;li&gt;압축을 컴팩션이라 하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이를 실제로 구현하려면 고려해야할게 많다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;파일 형식, 레코드 삭제, 고장 복구, 부분레코드 쓰기, 동시성 제어 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;추가 전용 로그는 공간 낭비지 않을까? 어차피 금방 찾으면 직접 가서 덮어쓰면 안되나?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;추가와 세그먼트 병합이 훨씬 빠르다 (순차적인 작업이기 때문)
&lt;ul&gt;
&lt;li&gt;특히 하드디스크에서!!
&lt;ul&gt;
&lt;li&gt;자기회전방식이니까.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DB 죽으면 어케 고칠건데!&lt;/li&gt;
&lt;li&gt;조각화되는 데이터파일 문제도 해결 가능 (조각모음)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;제한사항도 물론 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;키가 너무 많으면 안된다.&lt;/li&gt;
&lt;li&gt;범위 질의는 사실상 응답이 불가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="ss테이블과-lsm-트리"&gt;&lt;a href="#ss%ed%85%8c%ec%9d%b4%eb%b8%94%ea%b3%bc-lsm-%ed%8a%b8%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;SS테이블과 LSM 트리
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;세그먼트 파일의 형식에 간단한 변경사항 한가지만 적용해보자.
&lt;ul&gt;
&lt;li&gt;일련의 키-값 쌍을 &lt;strong&gt;키로 정렬하기&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;이 형식을 정렬된 문자열 테이블 (Sorted String Table), 즉 SS테이블 이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이는 해시 색인 로그 세그먼트보다 몇가지 큰 장점이 있는데
&lt;ul&gt;
&lt;li&gt;파일이 사용가능한 메모리보다 크더라도 간단하고 효율적임
&lt;ul&gt;
&lt;li&gt;머지소트하듯이 가져오면 금방 병합된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모든 키의 색인을 유지할 필요가 없다
&lt;ul&gt;
&lt;li&gt;해당 키를 포함하는 범위를 찾아가서 안에서 선형탐색을 해도 된다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;디스크 공간 절약, I/O 대역속 사용 절감
&lt;ul&gt;
&lt;li&gt;위의 아이디어로 블록을 그룹화해서 저장할 수도 있겠다.&lt;/li&gt;
&lt;li&gt;sparse index의 아이디어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="ss테이블-생성과-유지"&gt;&lt;a href="#ss%ed%85%8c%ec%9d%b4%eb%b8%94-%ec%83%9d%ec%84%b1%ea%b3%bc-%ec%9c%a0%ec%a7%80" class="header-anchor"&gt;&lt;/a&gt;SS테이블 생성과 유지
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;근데 데이터를 키로 정렬하기에는.. 유입되는 쓰기는 임의 순서로 발생한다. 어떻게 할까?&lt;/li&gt;
&lt;li&gt;이를 위해 레드블랙트리나 AVL같은 자료구조를 사용하겠다.
&lt;ul&gt;
&lt;li&gt;임의 순서로 키를 삽입하고 정렬된 순서로 키를 다시 읽을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이걸 이용해서 저장소 엔진을 다음과 같이 만들자.
&lt;ul&gt;
&lt;li&gt;쓰기가 들어오면 해당 자료구조(RB트리 / AVL트리 등)에 추가한다.
&lt;ul&gt;
&lt;li&gt;저 트리를 멤테이블이라고도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;멤테이블이 특정 임곗값보다 커지면 SS테이블 파일로 디스크에 기록한다.&lt;/li&gt;
&lt;li&gt;읽기요청이 들어오면 멤테이블 -&amp;gt; 최신 세그먼트 -&amp;gt; 다음 세그먼트&amp;hellip;에서 찾는다.&lt;/li&gt;
&lt;li&gt;가끔 세그먼트 파일을 병합, 컴팩션하는 과정을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이론상 완벽한데, 한가지 문제가 있다.
&lt;ul&gt;
&lt;li&gt;DB가 고장났다면??&lt;/li&gt;
&lt;li&gt;그래서 멤테이블에있는 최신 쓰기가 날라간다면?&lt;/li&gt;
&lt;li&gt;이를 방지하기 위해선 분리된 로그를 디스크에 유지해야한다.
&lt;ul&gt;
&lt;li&gt;SS테이블에 기록할때 버리면 되니까!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="ss테이블에서-lsm-트리-만들기"&gt;&lt;a href="#ss%ed%85%8c%ec%9d%b4%eb%b8%94%ec%97%90%ec%84%9c-lsm-%ed%8a%b8%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;SS테이블에서 LSM 트리 만들기
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;위의 알고리즘은 LevelDB, RocksDB, KV엔진 라이브러리 등에서 사용한다.
&lt;ul&gt;
&lt;li&gt;카산드라랑 HBase에서도 유사한걸 이용한다!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 색인 구조는 Log-Structured Merge-Tree, LSM트리라는 이름으로 발표되었다.
&lt;ul&gt;
&lt;li&gt;이를 기반으로 한 엔진을 LSM 저장소 엔진이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="성능-최적화"&gt;&lt;a href="#%ec%84%b1%eb%8a%a5-%ec%b5%9c%ec%a0%81%ed%99%94" class="header-anchor"&gt;&lt;/a&gt;성능 최적화
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;LSM트리는 DB에 존재하지 않는 키를 찾을 경우 느릴 수 있다.
&lt;ul&gt;
&lt;li&gt;멤테이블부터 가장 오래전 세그먼트까지 거슬러 올라가야하므로..&lt;/li&gt;
&lt;li&gt;그래서 우리는 &lt;strong&gt;블룸 필터&lt;/strong&gt; 를 추가적으로 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;또한 SS테이블을 병합/컴팩션할 순서와 시기를 결정하는 전략도 중요하다
&lt;ul&gt;
&lt;li&gt;크기 계층 컴팩션
&lt;ul&gt;
&lt;li&gt;좀더 작고 새로운 SS테이블을 크고 오래된 테이블에 병합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;레벨 컴팩션
&lt;ul&gt;
&lt;li&gt;키 범위를 더 작은 SS테입블로 나누고 오래된 데이터는 개별 레벨로 이동&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;대표적으로 위 두개가 있고, LevelDB랑 RocksDB는 레벨 컴팩션을 이용한다.&lt;/li&gt;
&lt;li&gt;HBase는 크기계층 컴팩션, 카산드라는 둘다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="b-트리"&gt;&lt;a href="#b-%ed%8a%b8%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;B 트리
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;사실 가장 널리 사용되는 색인구조는 &lt;strong&gt;B 트리&lt;/strong&gt; 이다.
&lt;ul&gt;
&lt;li&gt;1970년에 등장해서 보편적인 색인구조가 됨&lt;/li&gt;
&lt;li&gt;RDBMS의 표준 색인 구현이며, 많은 비관계형 DB에서도 사용&lt;/li&gt;
&lt;li&gt;SS테이블과 같이 키로 정렬돤 KV쌍을 갖지만, 설계 철학이 매우 다름&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로그 구조화 색인은 DB를 수 메가바이트 이상의 가변 크기를 가진 세그먼트로 나누고, 항상 세그먼트를 기록한다.
&lt;ul&gt;
&lt;li&gt;하지만 B트리는 4KB의 고정 크기 블록이나 페이지로 나누고, 한번에 하나의 페이지에 읽기/쓰기 작업을 수행한다.
&lt;ul&gt;
&lt;li&gt;각 페이지는 주소나 위치를 통해 식별할 수 있다. (디스크 위의 포인터 느낌)&lt;/li&gt;
&lt;li&gt;이를 이용해서 페이지 트리를 구성할 수 있다.&lt;/li&gt;
&lt;li&gt;한 페이지는 B 트리의 루트로 지정되고, 색인에서 키를 찾을때 루트에서 하위 페이지로 계속해서 내려간다.&lt;/li&gt;
&lt;li&gt;최종적으로 개별 페이지 / 리프 페이지에 도달하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;B트리에서 한 페이지에서 하위페이지를 참조하는 수를 분기 계수 (Branching Factor) 라고 한다.
&lt;ul&gt;
&lt;li&gt;자식노드의 개수라고 생각하면 되는듯?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;B트리에서 갱신작업을 위해선 리프 페이지를 검색하고 페이지의 값을 바꾼 후 디스크에 다시 기록하는 과정을 거친다.
&lt;ul&gt;
&lt;li&gt;새로운 키를 넣을 여유공간이 없다면 페이지 하나를 두개로 쪼개고, 상위 페이지에서 잘 연결해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;대부분의 DB는 B트리의 깊이가 3~4만 되어도 충분하다.
&lt;ul&gt;
&lt;li&gt;분기계수 500의 4KB, 4단계 트리는 256TB까지 저장 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="신뢰할-수-있는-b트리-만들기"&gt;&lt;a href="#%ec%8b%a0%eb%a2%b0%ed%95%a0-%ec%88%98-%ec%9e%88%eb%8a%94-b%ed%8a%b8%eb%a6%ac-%eb%a7%8c%eb%93%a4%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;신뢰할 수 있는 B트리 만들기
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;B트리는 기본적으로 쓰기 작업때 덮어쓰기를 수행한다.
&lt;ul&gt;
&lt;li&gt;그런데, 페이지를 분할하고 기록하는 타이밍에 DB가 고장난다면? 고아 페이지 (orphan page)가 생겨나게 된다.&lt;/li&gt;
&lt;li&gt;이를 방지하기 위해선 쓰기 전 로그 (write-ahead log, WAL, redo log, 재실행 로그) 라고 하는 데이터구조를 추가한다.
&lt;ul&gt;
&lt;li&gt;이는 트리 페이지에 변경된 내용을 적용하기 전에 변경사항을 기록하는 추가 전용 파일이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다중스레드가 동시에 B트리에 접근하려고 해도 문제다.
&lt;ul&gt;
&lt;li&gt;스레드가 일관성이 깨진 트리에 접근할 수 있기 때문&lt;/li&gt;
&lt;li&gt;따라서 이때 래치(latch, 가벼운 잠금, lock) 으로 트리의 데이터 구조를 보호한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="b-트리-최적화"&gt;&lt;a href="#b-%ed%8a%b8%eb%a6%ac-%ec%b5%9c%ec%a0%81%ed%99%94" class="header-anchor"&gt;&lt;/a&gt;B 트리 최적화
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;WAL대신 쓰기시 복사방식 쓰기&lt;/li&gt;
&lt;li&gt;키를 축약해서 쓰기&lt;/li&gt;
&lt;li&gt;리프 페이지를 연속된 공간에 쓰기&lt;/li&gt;
&lt;li&gt;트리에 포인터 추가&lt;/li&gt;
&lt;li&gt;프랙탈 트리와 같은 변형 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="b-트리와-lsm-트리-비교"&gt;&lt;a href="#b-%ed%8a%b8%eb%a6%ac%ec%99%80-lsm-%ed%8a%b8%eb%a6%ac-%eb%b9%84%ea%b5%90" class="header-anchor"&gt;&lt;/a&gt;B 트리와 LSM 트리 비교
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;B트리가 LSM트리보다 구현 성숙도가 높지만, LSM트리도 관심을 받는중
&lt;ul&gt;
&lt;li&gt;대개 경험적으로 LSM이 쓰기에서 더 빠르고, B트리가 읽기에서 더 빠르다!
&lt;ul&gt;
&lt;li&gt;읽기에서 LSM이 느린 이유는 각 컴팩션 단계의 데이터구조와 SS테이블을 모두 확인해야해서&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="lsm-트리의-장점"&gt;&lt;a href="#lsm-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ec%9e%a5%ec%a0%90" class="header-anchor"&gt;&lt;/a&gt;LSM 트리의 장점
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;B트리 색인은 모든 데이터 조각을 최소한 두번 기록해야 함
&lt;ul&gt;
&lt;li&gt;쓰기 전 로그 / 트리페이지&lt;/li&gt;
&lt;li&gt;심지어 몇바이트만 바꾸더라도 페이지 하나를 통째로 기록해야함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;로그 구조화 색인또한 SS테이블을 병합/컴팩션할때 여러번 쓰는데..
&lt;ul&gt;
&lt;li&gt;이런식으로 DB 쓰기 한번이 DB 수명동안 여러번 쓰기를 진행하게 하는걸 &lt;strong&gt;쓰기 증폭(write amplification)&lt;/strong&gt; 이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;쓰기가 많다면, 병목은 쓰기에서 있을 수 있다.
&lt;ul&gt;
&lt;li&gt;LSM트리는 B트리보다 쓰기 처리량을 높게 유지할 수 있다.&lt;/li&gt;
&lt;li&gt;LSM트리는 압축률이 더 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="lsm-트리의-단점"&gt;&lt;a href="#lsm-%ed%8a%b8%eb%a6%ac%ec%9d%98-%eb%8b%a8%ec%a0%90" class="header-anchor"&gt;&lt;/a&gt;LSM 트리의 단점
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;하지만 컴팩션 과정이 진행중인 읽기/쓰기의 성능에 영향을 줄 수 있다.
&lt;ul&gt;
&lt;li&gt;그래서 이걸 기다리는동안 요청이 대기해야할 수도&lt;/li&gt;
&lt;li&gt;반면에 B트리는 이보다 상황을 예측하기가 쉽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;절대적으로 써야할 양이 많다.
&lt;ul&gt;
&lt;li&gt;디스크의 쓰기 대역폭은 유한하지만, 로깅 테이블과 멤테이블, 컴팩션 스레드가 이 대역폭을 공유해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;컴팩션 설정을 주의깊게 하지 않으면 컴팩션이 유입 쓰기 속도를 따라갈 수가 없다&lt;/li&gt;
&lt;li&gt;B트리는 각 키가 색인의 한곳에만 정확하게 존재하지만, LSM트리는 여러 세그먼트에 있을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="기타-색인-구조"&gt;&lt;a href="#%ea%b8%b0%ed%83%80-%ec%83%89%ec%9d%b8-%ea%b5%ac%ec%a1%b0" class="header-anchor"&gt;&lt;/a&gt;기타 색인 구조
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;지금까지는 KV색인을 봤다. 관계형 모델의 기본 키 (primary key) 색인이 대표적인 KV색인이다.
&lt;ul&gt;
&lt;li&gt;보조 색인에서도 쓸 수 있다.
&lt;ul&gt;
&lt;li&gt;이때 키가 고유하지 않을 수 있다는 문제가 있을 수 있는데, 이는 두가지 방법으로 해결 가능함.
&lt;ul&gt;
&lt;li&gt;색인의 각 값에 일치하는 로우 식별자 목록 만들기&lt;/li&gt;
&lt;li&gt;로우 식별자 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;B트리 / 로그구조화색인 둘다 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="색인-안에-값-저장하기"&gt;&lt;a href="#%ec%83%89%ec%9d%b8-%ec%95%88%ec%97%90-%ea%b0%92-%ec%a0%80%ec%9e%a5%ed%95%98%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;색인 안에 값 저장하기
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;색인에서, value가 될 수 있는건 raw 자체거나 다른곳의 raw를 가리키는 참조다.
&lt;ul&gt;
&lt;li&gt;후자의 경우, raw가 저장된 곳을 heap file 이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;색인 -&amp;gt; 힙이 읽기 성능에 불이익이 커서, 색인 안에 바로 색인된 raw를 저장하기도 한다.
&lt;ul&gt;
&lt;li&gt;이를 클러스터드 색인 (clustered index)이라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클러스터드 색인과 비클러스터드 사이의 절충안으로 커버링 색인, 혹은 포괄열이 있는 색인 등이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="다중-컬럼-색인"&gt;&lt;a href="#%eb%8b%a4%ec%a4%91-%ec%bb%ac%eb%9f%bc-%ec%83%89%ec%9d%b8" class="header-anchor"&gt;&lt;/a&gt;다중 컬럼 색인
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;지금까지의 모든 색인들은 하나의 키값에만 대응해서, 다중컬럼에 대응하기 어렵다.&lt;/li&gt;
&lt;li&gt;일반적으론 결합 색인 (concantenated index) 으로 처리할 수 있겠다.
&lt;ul&gt;
&lt;li&gt;이는 하나의 컬럼에 다른 컬럼을 추가하는 방식으로 하나의 키에 여러 필드를 단순 결합시킨다.&lt;/li&gt;
&lt;li&gt;(성, 이름) 과 같이 묶어서 저장했따면, 성을 기준으로 정렬된 값 찾기, 특정 (성, 이름) 조합 찾기에는 좋지만 특정 이름을 가진 사람을 찾기는 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다차원 색인은 조금 더 일반적인 방식이다.
&lt;ul&gt;
&lt;li&gt;지리공간 데이터 / 위경도에서 많이 쓸텐데 (2차원 범위 쿼리)
&lt;ul&gt;
&lt;li&gt;이건 지금까지의 B트리/LSM트리로는 어렵다!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;한가지 방법은 2차원 위치를 공간-채움-곡선(space-filling curve)로 단일 숫자로 변환해서 B트리 이용하기&lt;/li&gt;
&lt;li&gt;다른 방법은 R트리같은 전문 공간 색인 (specialized spatial index) 사용하기 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;물론 위의 2차원 방법들이 3차원으로 확장되어 색상 (RGB)등으로도 쓸 수 있겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="전문-검색과-퍼지-색인"&gt;&lt;a href="#%ec%a0%84%eb%ac%b8-%ea%b2%80%ec%83%89%ea%b3%bc-%ed%8d%bc%ec%a7%80-%ec%83%89%ec%9d%b8" class="header-anchor"&gt;&lt;/a&gt;전문 검색과 퍼지 색인
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;이제 철자가 틀린 단어와 같이 &lt;strong&gt;유사한&lt;/strong&gt; 키에 대해서도 잘 검색이 되면 좋겠다!
&lt;ul&gt;
&lt;li&gt;이런 애매모호한(fuzzy) 질의는 어떻게 처리할까?
&lt;ul&gt;
&lt;li&gt;전문 검색엔진은 해당 단어의 동의어로 질의를 확장하는 방식으로&lt;/li&gt;
&lt;li&gt;루씬은 편집거리를 활용해서
&lt;ul&gt;
&lt;li&gt;추가적으로 인메모리 색인으로 트라이와 유산한 레벤슈타인 오토마톤으로 진행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="모든-것을-메모리에-보관"&gt;&lt;a href="#%eb%aa%a8%eb%93%a0-%ea%b2%83%ec%9d%84-%eb%a9%94%eb%aa%a8%eb%a6%ac%ec%97%90-%eb%b3%b4%ea%b4%80" class="header-anchor"&gt;&lt;/a&gt;모든 것을 메모리에 보관
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;지금까지의 데이터구조는 모두 디스크 한계에 대한 해결책이었다&lt;/li&gt;
&lt;li&gt;디스크는 읽기/쓰기를 신경써야하지만.. 램이 꽤 싸지고있지 않는가?
&lt;ul&gt;
&lt;li&gt;사실 이 공부를 하고 있는 시점 (26/4)에서 램은 진짜 개비싸졌다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아무튼 저때는 쌌으니까, 인메모리 데이터베이스가 개발됐다.
&lt;ul&gt;
&lt;li&gt;하지만 램은 장비가 재시작되면 데이터가 날라가므로, 보통 이를 허용하는 캐시 용도로만 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하지만 이를 지속적으로 사용하기 위한 인메모리 DB도 있는데,
&lt;ul&gt;
&lt;li&gt;이는 배터리 전원 공급 RAM과 같은 특수 하드웨어를 사용하거나&lt;/li&gt;
&lt;li&gt;디스크에 변경사항의 로그를 기록하거나&lt;/li&gt;
&lt;li&gt;디스크에 주기적인 스냅숏을 기록하거나&lt;/li&gt;
&lt;li&gt;다른 장비에 인메모리 상태를 복제하거나 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관계형 모델의 인메모리 데이터베이스에는 VoltDB, MemSQL, Oracle TimesTen과 같은것들이 있다.&lt;/li&gt;
&lt;li&gt;의외로 인메모리 DB의 장점은 디스크 IO바운드에서 오지 않는다.
&lt;ul&gt;
&lt;li&gt;데이터 구조 자유도 때문! PQ, set 등도 맘껏 쓸 수 있으니&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;언젠가 비휘발성 메모리 (NVM)이 상용화되면 더 발전하지 않을까!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="트랜잭션-처리나-분석"&gt;&lt;a href="#%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98-%ec%b2%98%eb%a6%ac%eb%82%98-%eb%b6%84%ec%84%9d" class="header-anchor"&gt;&lt;/a&gt;트랜잭션 처리나 분석?
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;초창기에 비즈니스 데이터 처리는 상거래(커머셜 트랜잭션)이 대부분이어서 다 트랜잭션이라 불렀는데, 그냥 지금도 논리 단위 형태로의 읽기와 쓰기 그룹을 트랜잭션이라고 한다.&lt;/li&gt;
&lt;li&gt;OLTP (Online Transaction Processing)
&lt;ul&gt;
&lt;li&gt;기본적인 비즈니스 트랜잭션 처리와 유사하게&lt;/li&gt;
&lt;li&gt;댓글 / 액션 / 연락처 등, 일부 키에 대한 적은 레코드를 가지고&lt;/li&gt;
&lt;li&gt;사용자 입력을 기반으로 삽입되거나 갱신되는 접근패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OLAP (Online Analytic Processing)
&lt;ul&gt;
&lt;li&gt;하지만 요새는 데이터분석에도 DB를 사용하기 시작함&lt;/li&gt;
&lt;li&gt;원시 데이터를 반환하는 대신, 많은 레코드를 스캔해 일부 칼럼만 읽어 집계 통계를 계산&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;1990년 전후로 회사들은 OLTP 시스템을 분석 목적으로 사용하지 않고, 개별 데이터베이스를 파기 시작했다.
&lt;ul&gt;
&lt;li&gt;이를 데이터 웨어하우스라고 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="데이터-웨어하우징"&gt;&lt;a href="#%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9b%a8%ec%96%b4%ed%95%98%ec%9a%b0%ec%a7%95" class="header-anchor"&gt;&lt;/a&gt;데이터 웨어하우징
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;OLTP 시스템은 높은 가용성과 낮은 지연시간을 최우선으로 하는데, 분석 쿼리는 비싼 연산이라서 성능을 저하시킬 우려가 컸다.&lt;/li&gt;
&lt;li&gt;그래서 개별 데이터베이스를 만들어서, 분석가들이 마음껏 쿼리를 날릴 수 있도록 했다.
&lt;ul&gt;
&lt;li&gt;이 과정은 Extract -&amp;gt; Transform -&amp;gt; Load의 과정으로 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="oltp-db와-데이터-웨어하우스의-차이점"&gt;&lt;a href="#oltp-db%ec%99%80-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ec%9b%a8%ec%96%b4%ed%95%98%ec%9a%b0%ec%8a%a4%ec%9d%98-%ec%b0%a8%ec%9d%b4%ec%a0%90" class="header-anchor"&gt;&lt;/a&gt;OLTP DB와 데이터 웨어하우스의 차이점
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;SQL은 분석 질의에 적합하기에 데이터 웨어하우스는 보통 관계형 모델을 이용한다.&lt;/li&gt;
&lt;li&gt;하지만 OLTP와 데이터 웨어하우스는 각자 다른 질의 패턴에 맞게 최적화되었기 때문에, 시스템의 내부는 완전히 다르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="분석용-스키마-별-모양-스키마와-눈꽃송이-모양-스키마"&gt;&lt;a href="#%eb%b6%84%ec%84%9d%ec%9a%a9-%ec%8a%a4%ed%82%a4%eb%a7%88-%eb%b3%84-%eb%aa%a8%ec%96%91-%ec%8a%a4%ed%82%a4%eb%a7%88%ec%99%80-%eb%88%88%ea%bd%83%ec%86%a1%ec%9d%b4-%eb%aa%a8%ec%96%91-%ec%8a%a4%ed%82%a4%eb%a7%88" class="header-anchor"&gt;&lt;/a&gt;분석용 스키마: 별 모양 스키마와 눈꽃송이 모양 스키마
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;데이터 분석에서는 트랜잭션 처리에서와 달리 데이터 모델의 다양성이 훨씬 적다.
&lt;ul&gt;
&lt;li&gt;많은 DW들은 별모양 스키마(star schema / dimensional modeling) 라고 알려진 방식을 주로 사용한다.&lt;/li&gt;
&lt;li&gt;이는 사실 테이블을 가운데 두고, 주변에 차원 테이블을 두는 구조이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변형으로는 눈꽃송이 스키마가 있다.
&lt;ul&gt;
&lt;li&gt;별모양 스키마를 더 정규화해서 차원이 하위 차원으로 세분화되는 모양이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="칼럼-지향-저장소"&gt;&lt;a href="#%ec%b9%bc%eb%9f%bc-%ec%a7%80%ed%96%a5-%ec%a0%80%ec%9e%a5%ec%86%8c" class="header-anchor"&gt;&lt;/a&gt;칼럼 지향 저장소
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;테이블에 데이터가 너무 많다면, 효율적으로 저장하고 질의하기 어렵다.&lt;/li&gt;
&lt;li&gt;그런데, 테이블에 칼럼은 보통 100개 이상이지만 일반적으로 DW 쿼리는 한번에 4~5개 컬럼만 접근한다.&lt;/li&gt;
&lt;li&gt;대부분의 OLTP DB는 로우 지향으로 데이터를 배치한다.
&lt;ul&gt;
&lt;li&gt;대신, 모든 값을 하나의 로우에 함께 저장하지 않는 대신 각 칼럼별로 개별 파일에 저장하는 방식을 이용할 수 있겠다.&lt;/li&gt;
&lt;li&gt;이는 각 칼럼 파일에 포함된 로우가 모두 같은 순서임에 의존한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="칼럼-압축"&gt;&lt;a href="#%ec%b9%bc%eb%9f%bc-%ec%95%95%ec%b6%95" class="header-anchor"&gt;&lt;/a&gt;칼럼 압축
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;다행히 칼럼 지향 저장소는 압축에 적합하다.&lt;/li&gt;
&lt;li&gt;여러 압축 기법이 있겠지만. 대표적으로 비트맵 부호화를 보자.
&lt;ul&gt;
&lt;li&gt;칼럼에서 고유 값의 수는 보통 로우 수에 비해 적으므로, 상당히 sparse하겠다.&lt;/li&gt;
&lt;li&gt;따라서 고유값에 대해 1과 0의 비트로 생각하고 압축하면 잘 압축되겠다!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="메모리-대역폭과-벡터화-처리"&gt;&lt;a href="#%eb%a9%94%eb%aa%a8%eb%a6%ac-%eb%8c%80%ec%97%ad%ed%8f%ad%ea%b3%bc-%eb%b2%a1%ed%84%b0%ed%99%94-%ec%b2%98%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;메모리 대역폭과 벡터화 처리
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;분석용 DB 개발자는 디스크&amp;lt;-&amp;gt;메모리 병목 뿐만 아니라 CPU &amp;lt;-&amp;gt; 메모리 병목, 아키텍쳐 최적화 등까지도 신경써야한다.&lt;/li&gt;
&lt;li&gt;CPU 주기, 캐시등에도 신경쓰고, and와 or과 같은 경우 압축된 컬럼 자체에 연산할 수 있게 설계할 수 있다.&lt;/li&gt;
&lt;li&gt;이를 벡터화 처리라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="칼럼-지향-저장소에-쓰기"&gt;&lt;a href="#%ec%b9%bc%eb%9f%bc-%ec%a7%80%ed%96%a5-%ec%a0%80%ec%9e%a5%ec%86%8c%ec%97%90-%ec%93%b0%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;칼럼 지향 저장소에 쓰기
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;칼럼 지향 저장소, 압축 ,정렬은 모두 읽기를 더 빠르게 하지만 쓰기를 어렵게 한다는 단점이 있다.&lt;/li&gt;
&lt;li&gt;이는 LSM트리에서 한 것과 같이 인메모리 저장소와 병합 파일들을 두는 방식으로 최적화 할 수 있겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="정리"&gt;&lt;a href="#%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;정리
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;고수준에서 저장소 엔진은 OLTP와 OLAP 두개로 나뉜다.&lt;/li&gt;
&lt;li&gt;OLTP 측면에서 두가지 관점을 확인했다.
&lt;ul&gt;
&lt;li&gt;로그 구조화 관점&lt;/li&gt;
&lt;li&gt;제자리 갱신 관점&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이번 장에서 선택한 데이터 베이스의 문서를 이해할 수 있는 충분한 어휘와 개념을 갖추었으면 됐다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="질문-사항"&gt;&lt;a href="#%ec%a7%88%eb%ac%b8-%ec%82%ac%ed%95%ad" class="header-anchor"&gt;&lt;/a&gt;❔질문 사항
&lt;/h2&gt;&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;크기압축/레벨압축이 Disjoint Union Set의 그거같은데, 같은 원리인게 맞나? 시간복잡도도 그에 맞춰질라나? 병합시간을 $O(N)$이라고 하면, Union하는데 $O(NlogN), O(N\alpha{(N)})$ 인건가?&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;뭐 대충 아이디어는 맞는데.. 시간복잡도는 그렇게 분석하면 안된댄다.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;질문 LSM 트리에서 컴팩션이 유입 쓰기 속도를 따라가지 못하면 어떤 일이 순서대로 발생하는가? 읽기, 쓰기, 디스크 사용량 각각에 미치는 영향과, 최종적으로 DB가 취하는 조치는?&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;세그먼트가 쌓이면서 읽기 시 확인해야 할 세그먼트 수가 증가해 읽기 성능 저하. 정리되지 않은 세그먼트로 디스크 사용량 급증. 쓰기는 계속 들어오지만 컴팩션이 못 따라오면 결국 DB가 쓰기를 throttle하거나 완전히 stall시킴.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;질문 SSTable 기반 저장소에서 존재하지 않는 키를 조회할 때 왜 느린가? 실제 시스템은 이를 어떻게 완화하는가?&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;멤테이블부터 가장 오래된 세그먼트까지 전부 탐색해야 &amp;ldquo;없다&amp;quot;는 걸 확인할 수 있기 때문. Bloom filter로 완화 — 각 세그먼트마다 유지하며 해당 키가 없음을 확률적으로 빠르게 판별, false negative가 없으므로 &amp;ldquo;없다&amp;quot;고 나오면 해당 세그먼트를 스킵.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;보조 색인이 뭐지?&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;기본 키가 아니라 다른 컬럼으로 검색할경우
SELECT * FROM user WHERE age = 30
위와 같은경우에 age에 색인이 없으면 전체 스캔을 한다.
이런걸 방지하기 위해 age 컬럼에도 빠르게 검색하기 위한 추가 자료구조, 즉 색인을 만들어두는걸 보조 색인을 만들어둔다고 한다.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;명색이 도시공학과인데 R트리가 궁금하다! 지리데이터 조아&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;R트리는 공간을 재귀적으로 bounding rectangle(최소 경계 사각형)으로 감싸는 트리이다.
최소경계 사각형끼리는 겹칠 수 있고, 상위 사각형은 하위 사각형을 포함한다.
-&amp;gt; 아니 근데 그러면 이걸 2차원 세그먼트 트리처럼 관리하면 되는거 아닌가?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;맞긴 하다. 그 아이디어가 k-d트리랑 이어진다. 그런데 페이지 크기에 맞추기, 동적 삽입/삭제, 디스크페이지단위 IO에는 R트리가 더 친화적일 수도 있다.&lt;/li&gt;
&lt;/ul&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert alert-question"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;&lt;/span&gt;
 &lt;span class="alert-title"&gt;예전에 &lt;a class="link" href="https://blog.wlgh7407.com/posts/algorithm/topics/260127_til_approximate-nearest-nighbor-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98/" &gt;ANN&lt;/a&gt;을 약간 공부한 적이 있었는데, 혹시 여기랑 연결될 수 있는 개념이지 않을까?&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;연결된다. 정확히는 R트리는 정확한 범위 내 검색, ANN은 가장 가까운 k개 찾기.
고차원에서는 R트리가 차원의 저주로 망가져서, 이를 해결하고자 ANN이 다른 접근을 쓰는 느낌.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="-참고-자료"&gt;&lt;a href="#-%ec%b0%b8%ea%b3%a0-%ec%9e%90%eb%a3%8c" class="header-anchor"&gt;&lt;/a&gt;🔗 참고 자료
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>02 데이터 모델과 질의 언어</title><link>https://blog.wlgh7407.com/posts/books/ddia/260404_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-02-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AA%A8%EB%8D%B8%EA%B3%BC-%EC%A7%88%EC%9D%98-%EC%96%B8%EC%96%B4/</link><pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate><guid>https://blog.wlgh7407.com/posts/books/ddia/260404_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-02-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AA%A8%EB%8D%B8%EA%B3%BC-%EC%A7%88%EC%9D%98-%EC%96%B8%EC%96%B4/</guid><description>&lt;h2 id="-상세-정리"&gt;&lt;a href="#-%ec%83%81%ec%84%b8-%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;📝 상세 정리
&lt;/h2&gt;&lt;h3 id="인트로"&gt;&lt;a href="#%ec%9d%b8%ed%8a%b8%eb%a1%9c" class="header-anchor"&gt;&lt;/a&gt;인트로
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;데이터 모델은 소프트웨어 개발에서 제일 중요하다&lt;/li&gt;
&lt;li&gt;특히 데이터 모델을 표현하는 방법이 중요한데
&lt;ul&gt;
&lt;li&gt;어떤 데이터를 저장할것인가 (사람 / 조직 등)&lt;/li&gt;
&lt;li&gt;어떤 형태로 저장할것인가 (json / xml 등)&lt;/li&gt;
&lt;li&gt;어떤 장소에 저장할것인가 (램 / 하드디스크 등)&lt;/li&gt;
&lt;li&gt;어떤 방식으로 저장할것인가 (전류 / 빛의파동 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결국 이들을 추상화시키는게 중요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="관계형-모델과-문서-모델"&gt;&lt;a href="#%ea%b4%80%ea%b3%84%ed%98%95-%eb%aa%a8%eb%8d%b8%ea%b3%bc-%eb%ac%b8%ec%84%9c-%eb%aa%a8%eb%8d%b8" class="header-anchor"&gt;&lt;/a&gt;관계형 모델과 문서 모델
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1970년 에드가 코드가 제안한 관계형 모델을 기반으로한 SQL이 젤 잘 알려져있는데&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이는 비즈니스 데이터 처리에 근간을 둔다
&lt;ul&gt;
&lt;li&gt;트랜잭션 처리&lt;/li&gt;
&lt;li&gt;일괄 처리 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;네트워크 모델, 계층 모델등이 대안으로 나왔지만, 결국 관계형 모델이 평정했다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NoSQL의 탄생&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2010년대, Not Only SQL이라는게 유행을 탔는데
&lt;ul&gt;
&lt;li&gt;이는
&lt;ul&gt;
&lt;li&gt;대규모 데이터셋&lt;/li&gt;
&lt;li&gt;높은 쓰기 처리량 달성&lt;/li&gt;
&lt;li&gt;무료 오픈 소프트웨어에 대한 선호도&lt;/li&gt;
&lt;li&gt;특수 질의 동작&lt;/li&gt;
&lt;li&gt;동적인 데이터 모델&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;등을 위해서였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가까운 미래에는 관계형 DB도 다양함을 위해 비관계형 데이터 스토어와 함께 사용될텐데, 이를 다중 저장소 지속성이라 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;객체 관계형 불일치&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;데이터를 관계형 테이블에 저장할때 각 모델 객체 사이에 전환 계층이 필요한데, 이를 임피던스 불일치라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;다대일과 다대다 관계&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;중복된 데이터를 정규화하려면 다대일 관계가 필요한데, 이는 문서 모델에 적합하지 않다.
&lt;ul&gt;
&lt;li&gt;문서 DB에서는 조인에 대한 지원이 약해서&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그러면 다중질의를 만들어서 흉내내야하는데&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;어떤 데이터 모델이 애플리케이션 코드를 더 간단하게 할가?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;문서와 비슷한 구조를 여러 테이블에 나누어 찢는 관계형 기법은 불필요하게 복잡해진다.
&lt;ul&gt;
&lt;li&gt;너무 깊게 중첩되지 않으면 괜찮지만&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;문서 DB와 관계형 DB의 통합&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;대부분의 관계형 DB는 이제 XML도 지원함&lt;/li&gt;
&lt;li&gt;심지어 둘이 점점 비슷해지는중!&lt;/li&gt;
&lt;li&gt;이것이 가야할 올바른 길&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;데이터를 위한 질의 언어&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;SQL은 선언형, IMS와 코다실은 명령형 코드&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="그래프형-데이터-모델"&gt;&lt;a href="#%ea%b7%b8%eb%9e%98%ed%94%84%ed%98%95-%eb%8d%b0%ec%9d%b4%ed%84%b0-%eb%aa%a8%eb%8d%b8" class="header-anchor"&gt;&lt;/a&gt;그래프형 데이터 모델
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;그래프는 정점과 간선이라는 객체로 이루어진다.&lt;/li&gt;
&lt;li&gt;속성 그래프 모델
&lt;ul&gt;
&lt;li&gt;고유식별자 / 유출 / 유입 / 컬렉션 등으로 이루어진 정점과&lt;/li&gt;
&lt;li&gt;고유식별자 / u, v/ 관계 유형 / 컬렉션 등으로 이루어진 간선으로 만든 그래프 데이터 모델&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사이퍼 질의언어
&lt;ul&gt;
&lt;li&gt;속성 그랲를 위한 질의 언어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;트리플 저장소와 스파클
&lt;ul&gt;
&lt;li&gt;트리플 저장소 모델은 속성 그래프 모델과 비슷&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="정리"&gt;&lt;a href="#%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;정리
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;데이터 모델은 광범위한 주제임&lt;/li&gt;
&lt;li&gt;데이터를 한 트리로 크게 관리하고싶었지만, 이는 다대다 관계를 표현하기 어려었음&lt;/li&gt;
&lt;li&gt;하지만 여기에도 애로사항이 있어서 NoSQL도 만들고, 그래프도 만들고&amp;hellip;&lt;/li&gt;
&lt;li&gt;아무튼 세 모델은 각자의 영역에서 훌륭하고, 서로를 흉내낼 수는 있지만 엉망이다.&lt;/li&gt;
&lt;li&gt;게놈데이터모델, 빅데이터스타일 모델, full-text 검색등 여러가지가 더 있지만, 아무튼 다 알고 잘 써야한다는 이야기&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="질문-사항"&gt;&lt;a href="#%ec%a7%88%eb%ac%b8-%ec%82%ac%ed%95%ad" class="header-anchor"&gt;&lt;/a&gt;❔질문 사항
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="-참고-자료"&gt;&lt;a href="#-%ec%b0%b8%ea%b3%a0-%ec%9e%90%eb%a3%8c" class="header-anchor"&gt;&lt;/a&gt;🔗 참고 자료
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>01 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션</title><link>https://blog.wlgh7407.com/posts/books/ddia/260329_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-01-%EC%8B%A0%EB%A2%B0%ED%95%A0-%EC%88%98-%EC%9E%88%EA%B3%A0-%ED%99%95%EC%9E%A5-%EA%B0%80%EB%8A%A5%ED%95%98%EB%A9%B0-%EC%9C%A0%EC%A7%80%EB%B3%B4%EC%88%98%ED%95%98%EA%B8%B0-%EC%89%AC%EC%9A%B4-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98/</link><pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate><guid>https://blog.wlgh7407.com/posts/books/ddia/260329_til_%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A4%91%EC%8B%AC-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%A4%EA%B3%84-01-%EC%8B%A0%EB%A2%B0%ED%95%A0-%EC%88%98-%EC%9E%88%EA%B3%A0-%ED%99%95%EC%9E%A5-%EA%B0%80%EB%8A%A5%ED%95%98%EB%A9%B0-%EC%9C%A0%EC%A7%80%EB%B3%B4%EC%88%98%ED%95%98%EA%B8%B0-%EC%89%AC%EC%9A%B4-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98/</guid><description>&lt;h2 id="-상세-정리"&gt;&lt;a href="#-%ec%83%81%ec%84%b8-%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;📝 상세 정리
&lt;/h2&gt;&lt;h4 id="인트로"&gt;&lt;a href="#%ec%9d%b8%ed%8a%b8%eb%a1%9c" class="header-anchor"&gt;&lt;/a&gt;인트로
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;오늘날 많은 애플리케이션들은 계산 중심이 아닌 데이터 중심적
&lt;ul&gt;
&lt;li&gt;애플리케이션을 제한하는 요소는 CPU 성능이 아닌, 데이터의 양 / 복잡도 등이라는 것
&lt;ul&gt;
&lt;li&gt;데이터를 저장 (DB)&lt;/li&gt;
&lt;li&gt;데이터를 빠르게 읽기 (캐시)&lt;/li&gt;
&lt;li&gt;검색과 색인&lt;/li&gt;
&lt;li&gt;비동기 처리 (스트림)&lt;/li&gt;
&lt;li&gt;주기적으로 분석 (배치 처리)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;위와 같은것들을 진행해야하기 때문!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="데이터시스템에-대한-생각"&gt;&lt;a href="#%eb%8d%b0%ec%9d%b4%ed%84%b0%ec%8b%9c%ec%8a%a4%ed%85%9c%ec%97%90-%eb%8c%80%ed%95%9c-%ec%83%9d%ea%b0%81" class="header-anchor"&gt;&lt;/a&gt;데이터시스템에 대한 생각
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;우리는 DB / 큐 / 캐시 등을 다르게 생각한다.
&lt;ul&gt;
&lt;li&gt;하지만 이걸 &lt;strong&gt;데이터 시스템&lt;/strong&gt;이라고 묶어서 생각하자.&lt;/li&gt;
&lt;li&gt;어차피 분류도 흐려지고 있으니까!
&lt;ul&gt;
&lt;li&gt;메세지큐로 사용하는 데이터스토어인 Redis&lt;/li&gt;
&lt;li&gt;지속성을 보장하는 메세지큐인 Kafka&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;애플리케이션이 단일 도구로는 만족하기 어려울정도로 과도하고 광범위한 요구사항을 가지니까!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아무튼 소프트웨어 시스템에서는 그러면 신뢰성 / 확장성 / 유지보수성이 중요한데&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="신뢰성"&gt;&lt;a href="#%ec%8b%a0%eb%a2%b0%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;신뢰성
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;소프트웨어에 대한 신뢰란?
&lt;ul&gt;
&lt;li&gt;애플리케이션은 사용자가 기대한 기능을 수행한다.&lt;/li&gt;
&lt;li&gt;실수나 예상치 못한 사용법도 허용한다.&lt;/li&gt;
&lt;li&gt;필수적인 사용사례를 충분히 만족한다.&lt;/li&gt;
&lt;li&gt;허가되지 않은 접근, 오남용을 방지한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결함과 장애
&lt;ul&gt;
&lt;li&gt;결함
&lt;ul&gt;
&lt;li&gt;잘못될 수 있는 일&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;장애
&lt;ul&gt;
&lt;li&gt;사용자에게 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결함 확률을 0으로 만드는건 불가능하지만, 결함으로 인해 장애가 발생하지 않게끔 해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="하드웨어-결함"&gt;&lt;a href="#%ed%95%98%eb%93%9c%ec%9b%a8%ec%96%b4-%ea%b2%b0%ed%95%a8" class="header-anchor"&gt;&lt;/a&gt;하드웨어 결함
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;하드디스크 고장 / 램 결함 / 정전 / 네트워크 케이블 이슈 등&lt;/li&gt;
&lt;li&gt;시스템 장애율을 줄이기 위해
&lt;ul&gt;
&lt;li&gt;하드웨어 구성요소에 중복을 추가하기
&lt;ul&gt;
&lt;li&gt;디스크 RAID구성&lt;/li&gt;
&lt;li&gt;이중전원 CPU&lt;/li&gt;
&lt;li&gt;예비전원용 디젤 발전기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이전에는 저정도로 충분했지만&amp;hellip;&lt;/li&gt;
&lt;li&gt;이제는 데이터양과 계산 요구가 늘어나면서 하드웨어 결함률도 증가했다.
&lt;ul&gt;
&lt;li&gt;소프트웨어 내결함성 기술도 사용해야한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="소프트웨어-오류"&gt;&lt;a href="#%ec%86%8c%ed%94%84%ed%8a%b8%ec%9b%a8%ec%96%b4-%ec%98%a4%eb%a5%98" class="header-anchor"&gt;&lt;/a&gt;소프트웨어 오류
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;하드웨어 결함을 무작위적이고 서로 독립적이라고 생각한다.
&lt;ul&gt;
&lt;li&gt;온도같은 약한 상관관계도 있겠지만&lt;/li&gt;
&lt;li&gt;시스템 내 체계적 오류(systematic error)가 있을 수도 있다.
&lt;ul&gt;
&lt;li&gt;잘못된 특정 입력이 있을때 서버 인스턴스가 죽는 버그&lt;/li&gt;
&lt;li&gt;CPU / 메모리 / 디스크 / 네트워크를 과도하게 사용하는 프로세스&lt;/li&gt;
&lt;li&gt;반응이 없거나 잘못된 응답을 반환하는 서비스&lt;/li&gt;
&lt;li&gt;연쇄 장애&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;등의 큰 이슈도 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;여기에는 신속한 해결책은 없다.
&lt;ul&gt;
&lt;li&gt;빈틈없는 테스트, 프로세스 격리, 모니터링, 분석 등으로 열심히 해야지..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="인적-오류"&gt;&lt;a href="#%ec%9d%b8%ec%a0%81-%ec%98%a4%eb%a5%98" class="header-anchor"&gt;&lt;/a&gt;인적 오류
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;사람이 하는일이다보니 오류가 난다
&lt;ul&gt;
&lt;li&gt;사실 운영자 설정 오류가 하드웨어 결함보다 훨씬 많다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="확장성"&gt;&lt;a href="#%ed%99%95%ec%9e%a5%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;확장성
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;증가한 부하에 대처하는 시스템 능력&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="부하-기술하기"&gt;&lt;a href="#%eb%b6%80%ed%95%98-%ea%b8%b0%ec%88%a0%ed%95%98%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;부하 기술하기
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;부하 매개변수라 부르는 몇개의 숫자로 나타내자.
&lt;ul&gt;
&lt;li&gt;웹 서버의 초당 요청수&lt;/li&gt;
&lt;li&gt;데이터베이스의 읽기 대 쓰기 비율&lt;/li&gt;
&lt;li&gt;액티브 유저&lt;/li&gt;
&lt;li&gt;캐시 적중률 등..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;평균적인경우가 중요할수도 있고, 극단적인 케이스가 병목일수도 있고&lt;/li&gt;
&lt;li&gt;트위터의 경우
&lt;ul&gt;
&lt;li&gt;개별 사용자는 많은 사람을, 많은 사람은 개별 사용자를 팔로하는데서 문제가 생김&lt;/li&gt;
&lt;li&gt;읽기가 쓰기에 비해 훨씬 많이 일어나므로, 쓰기 시점에 더 많은 일을 하는것이 바람직하다.
&lt;ul&gt;
&lt;li&gt;미리 캐시로 계산해버렷&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하지만 이러면 팔로워가 많은사람은 쓰기 비용이 너무 커지니까..
&lt;ul&gt;
&lt;li&gt;이럴때는 읽기에 더 많은 일을 시킨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="성능-기술하기"&gt;&lt;a href="#%ec%84%b1%eb%8a%a5-%ea%b8%b0%ec%88%a0%ed%95%98%ea%b8%b0" class="header-anchor"&gt;&lt;/a&gt;성능 기술하기
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;부하 매개변수를 증가시키고, 시스템 자원은 그대로 두면 성능이 어떻게 될까?&lt;/li&gt;
&lt;li&gt;성능이 변하지 않기 위해선 자원을 얼마나 많이 늘려야 할까?&lt;/li&gt;
&lt;li&gt;하둡과 같은 처리 시스템에서는 처리량(throughput)에 관심을 가지고, 온라인 시스템에서는 응답시간에 관심을 가진다.&lt;/li&gt;
&lt;li&gt;응답시간은 평균, 백분위, 꼬리 지연 시간 등으로 목표를 설정한다.
&lt;ul&gt;
&lt;li&gt;이 목표를 서비스 수준 목표(SLO) 혹은 서비스 수준 협약서 (SLA)라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;높은 백분위에서 응답시간의 상당부분은 큐 대기 지연이 차지한다.
&lt;ul&gt;
&lt;li&gt;앞의 느린 요청들 처리를 기다리는 시간&lt;/li&gt;
&lt;li&gt;이를 선두차단이라 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="부하-대응-접근-방식"&gt;&lt;a href="#%eb%b6%80%ed%95%98-%eb%8c%80%ec%9d%91-%ec%a0%91%ea%b7%bc-%eb%b0%a9%ec%8b%9d" class="header-anchor"&gt;&lt;/a&gt;부하 대응 접근 방식
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;용량 확장 (수직 확장)
&lt;ul&gt;
&lt;li&gt;좀더 좋은 장비로 바꾸기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;규모 확장 (수평 확장)
&lt;ul&gt;
&lt;li&gt;다수의 낮은 사양 장비에 부하를 분산하기&lt;/li&gt;
&lt;li&gt;비공유 아키텍쳐&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="유지보수성"&gt;&lt;a href="#%ec%9c%a0%ec%a7%80%eb%b3%b4%ec%88%98%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;유지보수성
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;레거시 시스템 유지보수&amp;hellip;.&lt;/li&gt;
&lt;li&gt;이를 위해선 다음이 중요하다
&lt;ul&gt;
&lt;li&gt;운용성&lt;/li&gt;
&lt;li&gt;단순성&lt;/li&gt;
&lt;li&gt;발전성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="운용성"&gt;&lt;a href="#%ec%9a%b4%ec%9a%a9%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;운용성
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;운영의 편리함 만들기
&lt;ul&gt;
&lt;li&gt;시스템 상태 모니터링 / 서비스 복원&lt;/li&gt;
&lt;li&gt;시스템 장애, 성능 저하 원인 추적&lt;/li&gt;
&lt;li&gt;..등등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="단순성"&gt;&lt;a href="#%eb%8b%a8%ec%88%9c%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;단순성
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;시스템에서 복잡도를 최대한 제거해서 새로운 엔지니어가 시스템을 이애하기 쉽게 만들기&lt;/li&gt;
&lt;li&gt;추상화를 적절히 사용해서 우발적 복잡도를 제거하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="발전성"&gt;&lt;a href="#%eb%b0%9c%ec%a0%84%ec%84%b1" class="header-anchor"&gt;&lt;/a&gt;발전성
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;엔지니어가 이후에 시스템을 쉽게 변경할 수 있게 하기&lt;/li&gt;
&lt;li&gt;애자일 / TDD 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="정리"&gt;&lt;a href="#%ec%a0%95%eb%a6%ac" class="header-anchor"&gt;&lt;/a&gt;정리
&lt;/h4&gt;&lt;p&gt;애플리케이션이 유용하기 위해선 다양한 요구사항을 충족해야한다.
이에는 기능적 요구사항과 비기능적 요구사항이 있다.
여기서 비기능적 요구사항인 신뢰성 / 확장성 / 유지보수성을 살펴봤다.&lt;/p&gt;
&lt;h2 id="질문-사항"&gt;&lt;a href="#%ec%a7%88%eb%ac%b8-%ec%82%ac%ed%95%ad" class="header-anchor"&gt;&lt;/a&gt;❔질문 사항
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="-참고-자료"&gt;&lt;a href="#-%ec%b0%b8%ea%b3%a0-%ec%9e%90%eb%a3%8c" class="header-anchor"&gt;&lt;/a&gt;🔗 참고 자료
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>