<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>최블랙의 개발로그</title>
    <link>https://choiblack.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 13 Apr 2026 17:57:25 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>최블랙</managingEditor>
    <image>
      <title>최블랙의 개발로그</title>
      <url>https://tistory1.daumcdn.net/tistory/4956655/attach/74a51c5969cf4ce9b090f8ede33630cd</url>
      <link>https://choiblack.tistory.com</link>
    </image>
    <item>
      <title>[Network] REST API</title>
      <link>https://choiblack.tistory.com/60</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;REST API&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckJ9iY/btrtydjMJOM/pmqLV23IbvIIUWUCJqxrX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckJ9iY/btrtydjMJOM/pmqLV23IbvIIUWUCJqxrX0/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;http://www.incodom.kr/REST&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckJ9iY/btrtydjMJOM/pmqLV23IbvIIUWUCJqxrX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckJ9iY%2FbtrtydjMJOM%2FpmqLV23IbvIIUWUCJqxrX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;495&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;http://www.incodom.kr/REST&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;API(Application Programming Interface)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API는 애플리케이션 소프트웨어를 구축하고 통합하는 정의 및 프로토콜 세트로,&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #151515;&quot;&gt;컴퓨터나 시스템과 상호 작용하여 정보를 검색하거나 기능을 수행하고자 할 때, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용자가 원하는 것을 시스템에 전달할 수 있게 지원&lt;/b&gt;&lt;/span&gt;하여 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;시스템이 이 요청을 이해하고 이행하도록 한다&lt;/b&gt;&lt;/span&gt;. &lt;/span&gt;즉, &lt;b&gt;API는 클라이언트와 클라이언트가 얻으려 하는 리소스 사이의 &lt;span style=&quot;color: #ee2323;&quot;&gt;조정자 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;역할&lt;/b&gt;을 한다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 날씨 서비스용 API에서는 사용자가 우편번호를 제공하고 생산자는 (최고 기온, 최저 기온)으로 구성된 응답을 하도록 지정한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;REST API&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;REST API는 &lt;b&gt;REST 아키텍처&lt;/b&gt;의 제약 조건을 준수하는 API를 말한다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;REST&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;정의&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;REST는 '&lt;b&gt;Representational State Transfer&lt;/b&gt;'의 약자로, &lt;span style=&quot;background-color: #ffffff; color: #151515;&quot;&gt;&lt;b&gt;프로토콜이나 표준이 아닌&lt;/b&gt; &lt;b&gt;아키텍처 원칙 세트&lt;/b&gt;이다. API 개발자는 REST를 다양한 방식으로 구현할 수 있다.&lt;/span&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;REST API를 통해 요청이 수행될 때 REST API는 &lt;span style=&quot;background-color: #ffffff; color: #151515;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;리소스 상태(State)에 대한 표현(Representation)을 요청자에게 전송(Transfer)&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자원의 표현(Reprensentation)&lt;/b&gt;은 &lt;span style=&quot;background-color: #ffffff; color: #151515;&quot;&gt;JSON, XML, HTML, XLT 또는 일반 텍스트를 통해 몇 가지 형식으로 전송된다.&lt;/span&gt;&amp;nbsp;이때 자원은 문서, 이미지, DB 등 해당 소프트웨어가 관리하는 모든 것을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 말하면, REST는&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고&lt;/li&gt;
&lt;li&gt;HTTP Method(POST, GET, PUT, DELETE)를 통해 자원에 대한 CRUD Operation을 적용하는 것&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, REST는 자원 기반의 구조(ROA, Resource Oriented Architecture) 설계의 중심에 리소스가 있고, HTTP 메서드를 통해 리소스를 처리하도록 설계된 아키텍처를 의미한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;구성 요소&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자원(Resource):&amp;nbsp;URI&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 자원은 고유한 Identify가 존재하고, 이 자원은 서버에 존재한다.&lt;/li&gt;
&lt;li&gt;자원을 구별하는 Identifier는 HTTP URI다.&lt;/li&gt;
&lt;li&gt;클라이언트는 URI를 통해 자원을 지정하고 해당 자원의 상태에 대한 조작을 서버에 요청한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;행위(Verb): HTTP Method&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP의 Method(GET, POST, PUT, DELETE)를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;표현(Representation)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 자원의 상태에 대한 조작을 요청하면, 서버는 이에 적절한 응답(Representation)을 보낸다.&lt;/li&gt;
&lt;li&gt;REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타내어 질 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;REST의 특징&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Client-Server Architecture&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트, 서버 및 리소스로 구성되어있으며 요청이 HTTP를 통해 관리되는 클라이언트-서버 아키텍쳐&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Stateless&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP는 Stateelss 프로토콜이기 때문에 HTTP를 통해 관리되는 REST 역시 Stateless를 갖는다.&lt;/li&gt;
&lt;li&gt;요청 간에 클라이언트 정보(context)가 서버에 저장되지 않는다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버는 클라이언트 정보를 신경쓰지 않아도 되기 때문에 단순해진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;각 요청이 분리되어 있고, 서로 연결되지 않는다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 API 서버는 단순하게 클라이언트의 요청만을 처리한다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Cacheable&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP를 그대로 사용하기 때문에 HTTP가 가진 캐싱 기능을 그대로 활용할 수 있다.&lt;/li&gt;
&lt;li&gt;캐시 사용을 통해 클라이언트-서버 간의 상호 작용을 최소화하여 응답시간이 빨라지고, 성능을 향상시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Layered System&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청된 정보를 검색하는 데 관련된 서버(보안, 로드밸런싱 등을 담당)의 각 유형을 클라이언트가 볼 수 없는 계층 구조로 체계화할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API 서버는 비즈니스 로직만을 수행하고 보안, 로드밸런싱, 암호화, 사용자 인증의 서버를 추가하여 구조상의 유연성과 확장성, 보안성을 향상시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Uniform Interface&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URI로 지정한 리소스에 대한 조작을 통일된 인터페이스로 수행한다.&lt;/li&gt;
&lt;li&gt;HTTP를 따르는 모든 플랫폼에서 사용 가능하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 언어나 기술에 종속되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Code-On-Demand(Optional)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청을 받으면 서버에서 클라이언트로 실행 가능한 코드를 전송하여 클라이언트 기능을 확장할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;REST의 장단점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP의 인프라를 그대로 사용하기 때문에 REST API 사용을 위한 &lt;b&gt;별도의 인프라를 구축할 필요가 없다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;HTTP를 따르는 &lt;b&gt;모든 플랫폼에서 사용 가능&lt;/b&gt;하다.&lt;/li&gt;
&lt;li&gt;REST API 메시지를 읽는 것만으로도 &lt;b&gt;메시지가 의도하는 바를 명확하게 파악&lt;/b&gt;할 수 있다.&lt;/li&gt;
&lt;li&gt;Stateless한 특징으로 &lt;b&gt;서버와 클라이언트의 역할이 명확하게 분리&lt;/b&gt;된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTP 메서드 형태가 제한적&lt;/b&gt;이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준이 존재하지 않는다&lt;/b&gt;.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이로 인해 관리의 어렵고, API 디자인 가이드가 존재하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.redhat.com/ko/topics/api/what-is-a-rest-api&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.redhat.com/ko/topics/api/what-is-a-rest-api&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.metafor.kr/165&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.metafor.kr/165&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wallees.wordpress.com/2018/04/19/rest-api-%EC%9E%A5%EB%8B%A8%EC%A0%90/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wallees.wordpress.com/2018/04/19/rest-api-%EC%9E%A5%EB%8B%A8%EC%A0%90/&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Network</category>
      <category>CS</category>
      <category>rest</category>
      <category>REST API</category>
      <category>RESTful</category>
      <category>RESTful API</category>
      <category>네트워크</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/60</guid>
      <comments>https://choiblack.tistory.com/60#entry60comment</comments>
      <pubDate>Thu, 17 Feb 2022 15:14:09 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Virtual Memory (2/2)</title>
      <link>https://choiblack.tistory.com/59</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://choiblack.tistory.com/58?category=995762&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;앞선 포스트&lt;/span&gt;&lt;/a&gt;에서 가상 메모리(Virtual Memory)는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;논리적 메모리와 물리적 메모리을 분리해 &lt;/b&gt;&lt;b&gt;실제 메모리 크기와 상관 없이 가상의 메모리를 사용&lt;/b&gt;하는 것이 장점&lt;b&gt; &lt;/b&gt;이라고 설명했다. 그렇다면 가상 메모리에서 프로세스의 크기가 남은 물리적 메모리의 크기보다 더 클 경우 어떻게 할까?&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Swapping&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;425&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLkcKN/btrrqMbRVtX/dJsoKy58k7HqkVzqKmkJqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLkcKN/btrrqMbRVtX/dJsoKy58k7HqkVzqKmkJqK/img.png&quot; data-alt=&quot; Swapping &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLkcKN/btrrqMbRVtX/dJsoKy58k7HqkVzqKmkJqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLkcKN%2FbtrrqMbRVtX%2FdJsoKy58k7HqkVzqKmkJqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;425&quot; height=&quot;376&quot; data-origin-width=&quot;425&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Swapping &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;swapping이란 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;main memory에 있는 일부 프로세스를 secondary memory(HDD, SSD, Flash 등)으로 내보내고 실행할 프로세스를 secondary memory에서 main memory로 불러오는 작업&lt;/span&gt;&lt;/b&gt;을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;&lt;b&gt;swap out&lt;/b&gt;: secondary memory로 내보내는 과정&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;swap in&lt;/b&gt;: main memory로 불러오는 과정&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;swap time&lt;/b&gt;: swap out time + swap in time&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;swapping은 디스크 액세스가 필요하기 때문에 전체 프로세스를 swapping하는 것은 굉장히 비효율적이다. 따라서 현대 OS는 &lt;b&gt;swap time을 최소화&lt;/b&gt;하는 것이 중요하다.&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;어떻게 Swap time을 최소화할 수 있을까 ?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;프로세스 전체를 swapping하는 것이 아닌, &lt;span style=&quot;color: #EE2323;&quot;&gt;&lt;b&gt;프로세스의 일부만을 swapping해 swap time을 줄일 수 있다&lt;/b&gt;.&lt;/span&gt; 이것을 &lt;b&gt;demad paging&lt;/b&gt;이라고 부른다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Demand Paging&lt;/b&gt;&lt;/h2&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwk4K6/btrrDcAnB0F/dXiEkoJGe8eloVkR4DcCy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwk4K6/btrrDcAnB0F/dXiEkoJGe8eloVkR4DcCy0/img.png&quot; data-alt=&quot; Demand Paging &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwk4K6/btrrDcAnB0F/dXiEkoJGe8eloVkR4DcCy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwk4K6%2FbtrrDcAnB0F%2FdXiEkoJGe8eloVkR4DcCy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;525&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Demand Paging &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;demand paging이란 &lt;span style=&quot;color: #000000;&quot;&gt;프로그램 실행 시작 시에 프로그램 전체를 디스크에서 물리 메모리로 로드하는 것이 아닌,&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;프로그램을 시작하기 위해 필요한 일부만 로드하고 나머지는 필요할 때(on demand) 로드하는 방법&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;장점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;disk I/O가 줄어들어 response time이 줄어든다.&lt;/li&gt;
 &lt;li&gt;프로그램의 일부만 로드해 실행할 수 있기 때문에 메모리 사용량이 줄어들고, 멀티프로그래밍에 용이하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;사용할 페이지가 메모리에 로드되어 있는지 어떻게 알 수 있지 ?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRmk1A/btrrF7x556a/p5UEXvBTEjHdrQ9165XGmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRmk1A/btrrF7x556a/p5UEXvBTEjHdrQ9165XGmk/img.png&quot; data-alt=&quot; Valid-Invalid bit &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRmk1A/btrrF7x556a/p5UEXvBTEjHdrQ9165XGmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRmk1A%2FbtrrF7x556a%2Fp5UEXvBTEjHdrQ9165XGmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;405&quot; data-origin-width=&quot;423&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Valid-Invalid bit &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 프로세스의 page table에는 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;valid-invalid bit&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 가지고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;valid-invalid bit = 1 → valid(해당 페이지가 메모리에 있다)&lt;/li&gt;
 &lt;li&gt;valid-invalid bit = 0 → invalid(해당 페이지가 메모리에 없다)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;참조할 페이지가 메모리에 없다면 ?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;address binding할 때, valid-invalid bit가 0(invalid)이면 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;page fault&lt;/span&gt;&lt;/b&gt;가 발생했다고 말한다.&lt;br&gt;page fault는 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;참조하려는 페이지가 메모리에 존재하지 않는 것&lt;/span&gt;&lt;/b&gt;을 말한다.&lt;br&gt;page fault가 발생하면 &lt;b&gt;OS에게 trap(software interrupt)을 발생&lt;/b&gt;시키고, OS는 page fault를 처리해야 한다.&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;OS가 page fault를 처리하는 방법&lt;/b&gt;&lt;/h4&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5ULhG/btrrDxqNXWc/xaE2DPLaMw5Fcwoqu4fWD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5ULhG/btrrDxqNXWc/xaE2DPLaMw5Fcwoqu4fWD1/img.png&quot; data-alt=&quot; Page Fault &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5ULhG/btrrDxqNXWc/xaE2DPLaMw5Fcwoqu4fWD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5ULhG%2FbtrrDxqNXWc%2FxaE2DPLaMw5Fcwoqu4fWD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;717&quot; height=&quot;598&quot; data-origin-width=&quot;966&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Page Fault &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;1. 메모리 참조가 발생하면 OS는 해당 참조가 잘못된 참조인지, 정상적인 참조인지 먼저 판단한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
 &lt;li&gt;잘못된 참조(Illegal reference) → abort&lt;/li&gt;
 &lt;li&gt;정상 참조 → valid-invalid bit 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;2. valid-invalid bit가 0이라면, trap을 발생시킨다.&lt;br&gt;3. OS는 메모리에서 빈 프레임(frame)을 찾고 (빈 프레임이 없을 경우 victim frame을 찾아 swap out)&lt;br&gt;4. 해당 페이지를 디스크에서 찾아 메모리의 빈 프레임에 swap in 한다.&lt;br&gt;5. 페이지 테이블에 해당 페이지의 레퍼런스를 저장하고 valid-invalid bit를 1로 설정한다.&lt;br&gt;6. 프로세스를 재실행한다.&lt;br&gt;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;background-color: #FFC1C8;&quot;&gt;page fault time = swap page out + swap page in + restart overhead&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;✅ &lt;span style=&quot;color: #F89009;&quot;&gt;demand paging system은 page fault rate를 최소화하는 것이 가장 중요하다 !!&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Page Replacement&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;프로세스가 page를 참조할 때 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;page fault가 발생&lt;/span&gt;&lt;/b&gt;하게 되면, OS는 메모리에서 빈 프레임 찾아 원하는 페이지를 빈 프레임에 로드한다. 이때 만약 메모리에 빈 프레임이 없다면, 사용하지 않는 페이지를 찾아 디스크로 내보내야 한다.&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;page replacement는 메모리에서 사용하지 않는 페이지를 찾아 page out하는 작업을 말한다. &lt;span style=&quot;color: #000000;&quot;&gt;page replacement는 page fault가 최소로 일어나는 페이지를 page out해야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Page Replacement 방법&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKtFjr/btrrxXKRqzN/dCxk6ePAg9COWySTFzGq61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKtFjr/btrrxXKRqzN/dCxk6ePAg9COWySTFzGq61/img.png&quot; data-alt=&quot; Page Replacement &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKtFjr/btrrxXKRqzN/dCxk6ePAg9COWySTFzGq61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKtFjr%2FbtrrxXKRqzN%2FdCxk6ePAg9COWySTFzGq61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;630&quot; height=&quot;439&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;439&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Page Replacement &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;1. 디스크에서 원하는 페이지를 찾는다.&lt;br&gt;2. 빈 프레임을 찾는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b&gt;빈 프레임이 있을 경우&lt;/b&gt; 해당 프레임에 페이지를 로드하고 페이지 테이블을 수정한다.&lt;/li&gt; 
 &lt;li&gt;&lt;b&gt;빈 프레임이 없을 경우 &lt;/b&gt;page replacement algorithm을 통해 희생될 프레임을 찾아 디스크로 swap out한다.&lt;br&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;modify bit를 확인하여 page의 수정이 있을 경우만 swap out한다. (disk I/O를 최소화하기 위함)&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;3. 비워진 프레임에 페이지를 로드하고 페이지 테이블을 수정한다.&lt;br&gt;4. 프로세스를 재실행한다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Page Replacement Algorithm&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;page replacement alogrithm의 목적은 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;page fault 비율을 최소화하는 것&lt;/span&gt;&lt;/b&gt;이다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;FIFO Algorithm&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;가장 간단한 페이지 교체 알고리즘으로 &lt;b&gt;FIFO(first-in first-out)&lt;/b&gt;의 흐름을 가진다.&lt;br&gt;&lt;b&gt;먼저 물리 메모리에 들어온 페이지 순서대로 페이지 교체하는 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;이해하기 쉽고, 프로그램하기도 쉽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;오래된 페이지가 항상 불필요하지 않은 정보를 포함하지 않을 수 있다. (초기 변수 등)&lt;/li&gt;
 &lt;li&gt;처음부터 활발하게 사용되는 페이지를 교체해서 page fault rate를 높일 수 있다.&lt;/li&gt;
 &lt;li&gt;Belady's anomaly: 페이지 프레임 수를 늘려도 되려 page fault가 더 많이 발생하는 모순이 존재한다.&lt;/li&gt;
 &lt;li&gt; &lt;/li&gt;
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBY6CK/btrrxXYl7H0/MZW0v7Ahthk92wDRWNkjpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBY6CK/btrrxXYl7H0/MZW0v7Ahthk92wDRWNkjpk/img.png&quot; data-alt=&quot; Belady's anomaly &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBY6CK/btrrxXYl7H0/MZW0v7Ahthk92wDRWNkjpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBY6CK%2FbtrrxXYl7H0%2FMZW0v7Ahthk92wDRWNkjpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;552&quot; height=&quot;362&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; Belady's anomaly &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Optimal Algorithm&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;앞으로 가장 오랫동안 사용되지 않을 페이지를 찾아 교체하는 알고리즘&lt;/b&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;알고리즘 중 가장 낮은 page fault rate를 보장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;단점&lt;/b&gt; &lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;구현의 어려움이 있다. &lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;→ 모든 프로세스의 메모리 참조의 계획을 미리 파악할 방법이 없음&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Least Recently Used(LRU) Algorithm&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;b&gt;가장 오랫동안 사용되지 않은 페이지를 선택하여 교체하는 알고리즘&lt;/b&gt;&lt;br&gt;대체적으로 FIFO 알고리즘보다 우수하고, OPT 알고리즘보다는 떨어진다.&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;구현 방법&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b&gt;Counter&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;페이지 테이블의 모든 엔트리에 counter를 가짐&lt;/li&gt; 
   &lt;li&gt;해당 페이지가 참조되었을 때 counter에 시간을 업데이트한다.&lt;/li&gt; 
   &lt;li&gt;페이지 교체가 필요할 때, 가장 작은 counter를 가지는 페이지를 교체한다.&lt;/li&gt; 
   &lt;li&gt;단점 
    &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
     &lt;li&gt;가장 작은 counter를 찾기 위해 탐색 시간이 필요하다.&lt;/li&gt; 
     &lt;li&gt;메모리 참조가 일어날 때마다 counter를 업데이트해야 한다.&lt;/li&gt; 
    &lt;/ul&gt; &lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b&gt;Reference bit&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;Counter가 너무 많은 리소스를 요구하기 때문에 이를 최소화한 방법&lt;/li&gt; 
   &lt;li&gt;교체되면 reference bit&amp;nbsp;→ 0, 참조되면 reference bit&amp;nbsp;→ 1&lt;/li&gt; 
   &lt;li&gt;정확한 순서를 알 순 없지만,&amp;nbsp;해당 페이지가 참조되었는지 아닌지 판단할 수 있음&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b&gt;Additional-Reference-Bits&amp;nbsp;Algorithm&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;페이지 테이블의 모든 엔트리에 8 비트 변수를 가짐&lt;/li&gt; 
   &lt;li&gt;해당 페이지가 참조되었을 때, 맨 앞 비트를 1로 바꿔줌&lt;/li&gt; 
   &lt;li&gt;일정한 시간이 지나면, 오른쪽으로 1bit shift&lt;/li&gt; 
   &lt;li&gt;가장 최근에 참조된 페이지의 값이 가장 크기 때문에 가장 작은 페이지가 교체된다.&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;10th edition - Operating System Concepts&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <category>CS</category>
      <category>demand paging</category>
      <category>OS</category>
      <category>page fault</category>
      <category>Page Replacement Algorithm</category>
      <category>Swapping</category>
      <category>virtual memory</category>
      <category>가상 메모리</category>
      <category>운영체제</category>
      <category>페이지 교체 알고리즘</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/59</guid>
      <comments>https://choiblack.tistory.com/59#entry59comment</comments>
      <pubDate>Tue, 25 Jan 2022 12:02:28 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Virtual Memory (1/2)</title>
      <link>https://choiblack.tistory.com/58</link>
      <description>&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  Backgroud&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;프로그램을 실행하기 위해서는 프로그램 코드를 디스크에서 메모리로 가져와야 한다. 만약 물리적인 메모리의 크기보다 프로그램의 크기가 더 크다면 이 프로그램은 실행할 수 없을 것이다. 하지만 실제 프로그램을 보면, 많은 경우에 프로그램 전체가 메모리에 올라갈 필요가 없다는 것을 알 수 있다.&lt;br&gt;이러한 생각으로 메모리에 프로그램의 일부를 로딩해 실행할 수 있는 가상메모리(Virtual Memory) 개념이 등장했다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Virtual Memory(가상 메모리)란 ?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;가상 메모리는 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;논리적 메모리와 물리적 메모리을 분리해 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #141414;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;실제 메모리 크기와 상관 없이 가상의 메모리를 사용하는 방법&lt;/span&gt;&lt;/b&gt;을 말한다.&lt;/span&gt;&lt;br&gt; &lt;br&gt;가상 메모리를 사용함으로써 다음과 같은 이점들을 제공한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;프로그램은 사용 가능한 &lt;b&gt;물리적 메모리 크기에 제약을 받지 않는다&lt;/b&gt;. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;프로그램이 물리적 메모리 크기보다 커져도 실행 가능하다.&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;각 프로그램이 물리적 메모리를 최소한으로 사용하기 때문에 &lt;b&gt;CPU 사용률(Utilization)과 처리량(Thoughput)이 증가&lt;/b&gt;해 더 많은 프로그램을 동시에 실행할 수 있다.&lt;/li&gt; 
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;가상 메모리를 어떻게 사용할까 ?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;프로세스가 논리적 주소를 엑세스할 때, &lt;b&gt;논리적 주소는 물리적 주소로 변환&lt;/b&gt;되어야 한다. 이를 &lt;b&gt;Address Binding&lt;/b&gt;이라고 한다.&lt;br&gt;&lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;Address Binding&lt;/span&gt;&lt;/b&gt;: &lt;b&gt;논리적 주소를 물리적 주소로 변환하는 것&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csyMSS/btrrqlKOUiK/a4mvLTC1lIrPemtZPCto9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csyMSS/btrrqlKOUiK/a4mvLTC1lIrPemtZPCto9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csyMSS/btrrqlKOUiK/a4mvLTC1lIrPemtZPCto9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsyMSS%2FbtrrqlKOUiK%2Fa4mvLTC1lIrPemtZPCto9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1078&quot; height=&quot;433&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;Address binding은 바인딩 시기에 따라 &lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;Complie time binding&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;Load time binding&lt;/span&gt;&lt;/b&gt;, &lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;Run time binding&lt;/span&gt;&lt;/b&gt;으로 나눌 수 있다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Compile time binding&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;&lt;b&gt;컴파일&lt;/b&gt; 시 물리적 주소로 바인딩&lt;/li&gt;
 &lt;li&gt;컴파일러가 주소를 변경할 수 없는 &lt;b&gt;absolute code&lt;/b&gt;를 만든다.&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;주소가 바뀌면 다시 컴파일해야 한다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
 &lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴파일러가 메모리 내용을 다 알고 있어야 해서 상당히 비효율적인 방법이다.&lt;/span&gt;&lt;/li&gt;
 &lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 번 주소가 결정되면 다시 컴파일하기 전까지 고정된 주소 공간을 가지기 때문에 멀티프로그래밍이 불가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwtCRQ/btrroMoJvQc/E6TNrNU0GXjR0GLcR6mlUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwtCRQ/btrroMoJvQc/E6TNrNU0GXjR0GLcR6mlUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwtCRQ/btrroMoJvQc/E6TNrNU0GXjR0GLcR6mlUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwtCRQ%2FbtrroMoJvQc%2FE6TNrNU0GXjR0GLcR6mlUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;547&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Load time binding&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b&gt;프로그램 실행&lt;/b&gt; 시 물리적 주소로 바인딩&lt;/li&gt; 
 &lt;li&gt;컴파일러가 주소를 변경할 수 있는 &lt;b&gt;relocatable code&lt;/b&gt;를 만든다. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;load time에 주소가 변경될 수 있다.&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;주소가 바뀌면 다시 로드해야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로딩될 때마다 코드에 참조된 주소를 다 변경해줘야 하기 때문에 메모리 로딩 시간이 상당히 오래 걸린다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dSFSjl/btrruzIdGl4/3gJOL7mTl1Ka6nscHerfGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dSFSjl/btrruzIdGl4/3gJOL7mTl1Ka6nscHerfGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dSFSjl/btrruzIdGl4/3gJOL7mTl1Ka6nscHerfGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdSFSjl%2FbtrruzIdGl4%2F3gJOL7mTl1Ka6nscHerfGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1061&quot; height=&quot;546&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Run time binding&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b&gt;런타임&lt;/b&gt; 시 물리적 주소로 바인딩&lt;/li&gt; 
 &lt;li&gt;해당 instruction이 실행될 때 &lt;b&gt;MMU(Memory Management Unit)&lt;/b&gt;를 통해 바인딩된다.&lt;/li&gt; 
 &lt;li&gt;MMU는 &lt;b&gt;relocation(base) register&lt;/b&gt;와 &lt;b&gt;limit register&lt;/b&gt;를 통해 논리적 주소를 물리적 주소로 바인딩한다. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;logical addr + relocation register = physical addr&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;주소가 바뀌면 relocation register만 변경하면 된다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;575&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfxWkr/btrrpnCmJu9/n2LOresgHwXUH5ewR0Kb80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfxWkr/btrrpnCmJu9/n2LOresgHwXUH5ewR0Kb80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfxWkr/btrrpnCmJu9/n2LOresgHwXUH5ewR0Kb80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfxWkr%2FbtrrpnCmJu9%2Fn2LOresgHwXUH5ewR0Kb80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1239&quot; height=&quot;575&quot; data-origin-width=&quot;1239&quot; data-origin-height=&quot;575&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h2 style=&quot;text-align: left;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리 할당하는 방법&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;위에서 프로그램을 실행하기 위해서는 메인 메모리로 프로그램 코드를 가져와야 한다고 했다. 그렇다면 어떻게 프로그램에게 메모리를 할당할까? 메모리를 할당하는 방법으로는 크게 &lt;span style=&quot;background-color: #F6E199;&quot;&gt;&lt;b&gt;Contiguous&lt;/b&gt; &lt;b&gt;Allocation&lt;/b&gt;&lt;/span&gt;, &lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;Paging&lt;/span&gt;&lt;/b&gt;이 있다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Contiguous Allocation&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;Contigous allocation은 말 그대로 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;메모리에 프로세스를 연속적으로 할당하는 방법&lt;/span&gt;&lt;/b&gt;이다.&lt;/li&gt;
 &lt;li&gt;프로세스가 필요로 하는 메모리의 크기에 따라 &lt;b&gt;가변적인 파티션 크기&lt;/b&gt;를 가진다.&lt;/li&gt;
 &lt;li&gt;연속적으로 메모리를 할당하기 때문에 메모리에 구멍(hole)이 생기게 된다.&lt;/li&gt;
 &lt;li&gt;프로세스를 메모리에 로딩할 때, 프로세스가 필요로 하는 메모리 크기에 적합한 구멍을 찾아 메모리를 할당한다.&lt;/li&gt;
 &lt;li&gt;OS는 &lt;b&gt;할당된 영역과 남은 영역에 대한 정보&lt;/b&gt;를 유지해야 한다.&lt;/li&gt;
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dk7gs/btrruz2wXtD/7cz0s6p64pRksLmWKbi4bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dk7gs/btrruz2wXtD/7cz0s6p64pRksLmWKbi4bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dk7gs/btrruz2wXtD/7cz0s6p64pRksLmWKbi4bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDk7gs%2Fbtrruz2wXtD%2F7cz0s6p64pRksLmWKbi4bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;974&quot; height=&quot;259&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;259&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;하드웨어(MMU)가 저렴하다. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;relocation register와 limit register만 사용하면 됨&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;알고리즘이 간단하다. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;limit보다 작은지 비교하고 base만 더해주면 됨&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CA96z/btrrqctvpLV/ZGsNADDfiGOXxcIV2oyP10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CA96z/btrrqctvpLV/ZGsNADDfiGOXxcIV2oyP10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CA96z/btrrqctvpLV/ZGsNADDfiGOXxcIV2oyP10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCA96z%2FbtrrqctvpLV%2FZGsNADDfiGOXxcIV2oyP10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;533&quot; height=&quot;405&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;프로세스의 메모리 크기를 키우기 힘들다.&lt;/li&gt; 
 &lt;li&gt;code나 data 영역을 공유할 수 있는 방법이 없다.&lt;/li&gt; 
 &lt;li&gt;&lt;b&gt;외부 단편화(External Fragmentation)이 발생할 수 있다.&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;외부 단편화를 해결하기 위해서는&amp;nbsp;&lt;b&gt;Compaction(압축) &lt;/b&gt;또는 &lt;b&gt;Non-contiguous Allocation &lt;/b&gt;방법이 필요하다.&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #F89009;&quot;&gt;Paging&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;Non-contiguous Allocation&lt;/span&gt;&lt;/b&gt; 방법으로, 논리적 주소 공간과 물리적 주소 공간을 완전히 분리하여 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;사용자에겐 연속적인 주소 공간으로 인식하게 하지만, 실제로는 물리 메모리에 흩어져 할당하는 방법&lt;/span&gt;&lt;/b&gt;이다.&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;물리 메모리는 고정 크기의&lt;/b&gt; &lt;b&gt;Frame&lt;/b&gt;으로 분리되고 &lt;b&gt;논리 메모리는 고정 크기의 Page&lt;/b&gt;로 분리된다.&lt;/li&gt;
 &lt;li&gt;프로세스 당 &lt;b&gt;page table&lt;/b&gt;을 가지며, page table을 통해 &lt;b&gt;논리 주소를 물리 주소로 변환&lt;/b&gt;한다.&lt;/li&gt;
 &lt;li&gt;page table은 &lt;b&gt;main memory&lt;/b&gt;에 저장되고, register에 page table의 &lt;b&gt;위치(Page table base register(PTBR))&lt;/b&gt;와 &lt;b&gt;크기(Page table length register(PTLR))&lt;/b&gt;를 저장한다.&lt;/li&gt;
 &lt;li&gt;OS가 &lt;b&gt;free frame list&lt;/b&gt;를 관리한다.&lt;/li&gt;
&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmRZw0/btrrosLjNvn/1rJVMQJ4pjhid1Vc4rQyY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmRZw0/btrrosLjNvn/1rJVMQJ4pjhid1Vc4rQyY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmRZw0/btrrosLjNvn/1rJVMQJ4pjhid1Vc4rQyY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmRZw0%2FbtrrosLjNvn%2F1rJVMQJ4pjhid1Vc4rQyY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;531&quot; data-origin-width=&quot;997&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;1. Transparency(투명성)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;논리 메모리와 물리 메모리가 분리되어 사용자는 논리 메모리만 생각하면 되기 때문에 프로그래밍하기 수월하다.&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;2. No external fragmentation&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;고정된 frame에 비연속적으로 할당하기 때문에 외부 단편화가 발생하지 않는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;하지만, &lt;b&gt;Internal fragmentation(내부 단편화)&lt;/b&gt;가 발생할 수 있다.&lt;/li&gt;
 &lt;li&gt; 예를 들어, 페이지 크기가 1,000B 이고 프로세스 A가 3,002B 의 메모리를 요구한다면, 3개의 프레임(3000B)을 할당하고도 2B를 더 할당해야 하기 때문에 총 4개의 프레임이 필요하다. 결론적으로 4번째 프레임에는 998B(1,000-2)의 여유 공간이 남게 되는 내부 단편화 문제가 발생한다.&lt;/li&gt;
 &lt;li&gt;내부 단편화는 페이지 크기가 작을수록 줄어들지만, page table의 크기가 커져 저장 공간을 더 필요로 하고, page table을 탐색하는 시간이 커지고, 디스크 I/O가 자주 일어나게 되는 문제가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;3. Shared page&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;575&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5acLe/btrrqcf2iTe/RsUykNZQ1OeNcWxGS5oxL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5acLe/btrrqcf2iTe/RsUykNZQ1OeNcWxGS5oxL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5acLe/btrrqcf2iTe/RsUykNZQ1OeNcWxGS5oxL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5acLe%2Fbtrrqcf2iTe%2FRsUykNZQ1OeNcWxGS5oxL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;586&quot; height=&quot;575&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;575&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;위와 같이 프로세스 간에 코드나 데이터를 공유할 때, 물리 메모리에는 한 번만 저장하고 각 프로세스가 같은 메모리를 참조하는 형태로 코드나 데이터를 공유할 수 있다.&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #F6E199;&quot;&gt;4. Memory protection&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;프로세스는 할당된 page table 외부의 메모리에 접근할 수 없다. &lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Paging에서 Address Binding&lt;/b&gt;&lt;/h3&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJRyT6/btrrqnaZ9VS/MeDaJ7n0objlfghdXs4hX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJRyT6/btrrqnaZ9VS/MeDaJ7n0objlfghdXs4hX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJRyT6/btrrqnaZ9VS/MeDaJ7n0objlfghdXs4hX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJRyT6%2FbtrrqnaZ9VS%2FMeDaJ7n0objlfghdXs4hX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;948&quot; height=&quot;243&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;CPU는 instruction을 수행하면서 MMU를 통해 page table에 접근하여 논리적 주소를 물리적 주소로 변환한다. 이때 &lt;b&gt;page table 액세스와 data/instruction 액세스 총 2번의 메모리 액세스가 요구된다&lt;/b&gt;. 매번 메모리를 두번 액세스하는 것은 굉장히 비효율적이고, 속도가 느리기 때문에 &lt;b&gt;translation look aside buffer(TLB)&lt;/b&gt;와 &lt;b&gt;Cache&lt;/b&gt;를 사용해 메모리 액세스를 최소화한다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgBSHG/btrroXD6A4Y/qORIkH5uun8krwxtg9I2HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgBSHG/btrroXD6A4Y/qORIkH5uun8krwxtg9I2HK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgBSHG/btrroXD6A4Y/qORIkH5uun8krwxtg9I2HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgBSHG%2FbtrroXD6A4Y%2FqORIkH5uun8krwxtg9I2HK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;549&quot; height=&quot;326&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;TLB에는 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;최근에 참조한 page table entry&lt;/span&gt;를 저장&lt;/b&gt;하고, Cache에는 &lt;b&gt;&lt;span style=&quot;color: #EE2323;&quot;&gt;최근에 참조한 data나 instruction&lt;/span&gt;을 저장&lt;/b&gt;한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;TLB hit &amp;amp; Cache hit → 0번 memory access&lt;/li&gt;
 &lt;li&gt;TLB miss &amp;amp; Cache hit → 1번 memory access&lt;/li&gt;
 &lt;li&gt;TLB hit &amp;amp; Cache miss → 1번 memory access&lt;/li&gt;
 &lt;li&gt;TLB miss &amp;amp; Cache miss → 2번 memory access&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;10th edition - Operating System Concepts&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <category>Address binding</category>
      <category>CS</category>
      <category>OS</category>
      <category>Paging</category>
      <category>TLB</category>
      <category>virtual memory</category>
      <category>가상 메모리</category>
      <category>운영체제</category>
      <category>페이징</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/58</guid>
      <comments>https://choiblack.tistory.com/58#entry58comment</comments>
      <pubDate>Sun, 23 Jan 2022 09:54:13 +0900</pubDate>
    </item>
    <item>
      <title>[OS] Cache Locality</title>
      <link>https://choiblack.tistory.com/57</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;캐시 지역성(Cache Locality)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;캐시 지역성 원리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시 메모리는 속도가 빠른 장치와 느린 장치간의 속도차에 따른 병목 현상을 줄이기 위한 범용 메모리이다. 이러한 역할을 수행하기 위해서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;CPU 가 어떤 데이터를 원할 것인가&lt;/b&gt;를 어느 정도 예측할 수 있어야 한다. 캐시의 성능은 작은 용량의 캐시 메모리에 CPU 가 이후에 참조할, 쓸모 있는 정보가 어느 정도 들어있느냐에 따라 좌우되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;b&gt;적중률(Hit rate)을 극대화 시키기 위해&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;데이터&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;지역성(Locality)의 원리를 사용한다. 지역성의 전제조건으로 프로그램은 모든 코드나 데이터를 균등하게 Access 하지 않는다는 특성을 기본으로 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;즉,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;b&gt;Locality란 &lt;/b&gt;기억 장치 내의 정보를 균일하게 Access하는 것이 아닌 어느 한 순간에 &lt;b&gt;특정 부분을 집중적으로 참조하는 특성&lt;/b&gt;을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 데이터 지역성은 대표적으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;시간 지역성(Temporal Locality)&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;공간 지역성(Spatial Locality)&lt;/b&gt;&lt;/span&gt;으로 나뉜다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 지역성 : 최근에 참조된 주소의 내용은 곧 다음에 다시 참조되는 특성.&lt;/li&gt;
&lt;li&gt;공간 지역성 : 대부분의 실제 프로그램이 참조된 주소와 인접한 주소의 내용이 다시 참조되는 특성&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/OS#%EC%BA%90%EC%8B%9C%EC%9D%98-%EC%A7%80%EC%97%AD%EC%84%B1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/OS#%EC%BA%90%EC%8B%9C%EC%9D%98-%EC%A7%80%EC%97%AD%EC%84%B1&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Operating System</category>
      <category>cache</category>
      <category>CS</category>
      <category>Locality</category>
      <category>OS</category>
      <category>운영체제</category>
      <category>캐시</category>
      <category>캐시 지역성</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/57</guid>
      <comments>https://choiblack.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 22 Jan 2022 18:24:23 +0900</pubDate>
    </item>
    <item>
      <title>[Spring Security] Authentication과 Authorization</title>
      <link>https://choiblack.tistory.com/56</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Authentication(인증)과 Authorization(인가)&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.jpg&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bACVrK/btrrr4Ifv6F/Ki2wvCGkCN4uMXzeIiQzCk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bACVrK/btrrr4Ifv6F/Ki2wvCGkCN4uMXzeIiQzCk/img.jpg&quot; data-alt=&quot;출처 https://ivorycode.tistory.com/entry/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EC%9D%B8%EA%B0%80Authorization&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bACVrK/btrrr4Ifv6F/Ki2wvCGkCN4uMXzeIiQzCk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbACVrK%2Fbtrrr4Ifv6F%2FKi2wvCGkCN4uMXzeIiQzCk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;854&quot; height=&quot;398&quot; data-filename=&quot;img.jpg&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 https://ivorycode.tistory.com/entry/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EC%9D%B8%EA%B0%80Authorization&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Authentication(인증)이란 ?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;식별 가능한 정보를 이용&lt;/b&gt;하여 서비스에 &lt;b&gt;등록된 유저인지&lt;/b&gt;를 파악하기 위한 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 인증을 통해 등록된 사용자에게만 서비스를 제공한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Authorization(인가)이란 ?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인증된 사용자가 접근하려는 자원에 대한 권한이 있는지 확인&lt;/b&gt;하는 과정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인가에 앞서 인증이 반드시 선행되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Authentication(인증) 방식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 방식에는 크게 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;세션 기반 인증 방식&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;토큰&lt;/b&gt;&lt;b&gt;기반 인증 방식&lt;/b&gt;&lt;/span&gt;, &lt;b&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;OAuth 기반 인증 방식&lt;/b&gt;&lt;/span&gt;이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;(OAuth 기반 인증 방식은 다음 포스트에서 다룰 예정)&lt;/i&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Session(세션) 기반 인증 방식&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션 기반 인증 방식의 핵심은 &lt;b&gt;사용자의 정보를 세션 스토리지에 저장해 서버에서 관리&lt;/b&gt;한다는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Session 이란 ?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;세션이란 일정 시간 동안 &lt;b&gt;같은 사용자(브라우저)로부터 들어오는 일련의 요청을 하나의 상태로 보고 그 상태를 일정하게 유지시키는 기술&lt;/b&gt;을 말한다. 또한, 여기서 일정 시간이란 방문자가 웹 브라우저를 통해 웹 서버에 접속한 시점으로부터 웹 브라우저를 종료함으로써 연결을 끝내는 시점을 말한다. 즉, 방문자가 웹서버에 접속해 있는 상태를 하나의 단위로 보고 세션이라고 칭한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Cookie 란&lt;/span&gt; ?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;b&gt;특정 웹 사이트를 방문했을 때 만들어지는 정보를 담는 파일&lt;/b&gt;을 말하며, 쉽게 말해 &lt;b&gt;상태 정보를 유지&lt;/b&gt;하는 기술이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;동작 방식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M0nKn/btrroMIOeaX/yGIN6pNN0Se9qgsfh17qsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M0nKn/btrroMIOeaX/yGIN6pNN0Se9qgsfh17qsk/img.png&quot; data-alt=&quot;출처 https://k3068.tistory.com/88#spring%25--security%25--%EC%25--%25--%EC%25--%25-C%EB%25-A%25--%25--%EA%25B-%25B-%EB%25B-%25B-%EC%25A-%25--%EC%25-C%BC%EB%25A-%25-C%25--%EC%25--%25B-%EC%25--%25--%25---%25--%EC%BF%25A-%ED%25--%25A-%25--%EB%25B-%25A-%EC%25-B%25-D%EC%25-D%25--%25--%EC%25--%AC%EC%25-A%25A-%ED%25--%25--%EA%25B-%25A-%25--%EC%25-E%25--%EB%25-B%25A--&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M0nKn/btrroMIOeaX/yGIN6pNN0Se9qgsfh17qsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM0nKn%2FbtrroMIOeaX%2FyGIN6pNN0Se9qgsfh17qsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;438&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 https://k3068.tistory.com/88#spring%25--security%25--%EC%25--%25--%EC%25--%25-C%EB%25-A%25--%25--%EA%25B-%25B-%EB%25B-%25B-%EC%25A-%25--%EC%25-C%BC%EB%25A-%25-C%25--%EC%25--%25B-%EC%25--%25--%25---%25--%EC%BF%25A-%ED%25--%25A-%25--%EB%25B-%25A-%EC%25-B%25-D%EC%25-D%25--%25--%EC%25--%AC%EC%25-A%25A-%ED%25--%25--%EA%25B-%25A-%25--%EC%25-E%25--%EB%25-B%25A--&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트가 서버로 로그인 요청을 보낸다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버는 클라이언트가 보낸 사용자 정보(ID, PW)를 확인한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 정보가 유효하면 세션을 생성하고,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세션 ID를 발급해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠키에 담아 요청에 대한 응답을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클라이언트는 인증이 필요한 요청을 할 때마다 헤더에 쿠키 포함해 보낸다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버는 쿠키를 검증하고,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;사용자 인증이 완료되면 &lt;span style=&quot;color: #000000;&quot;&gt;사용자 정보를 가져와&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요청에 대한 응답을 한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;장점&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;보안&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠키가 포함된 요청이 외부에 노출되어도 &lt;b&gt;쿠키(세션 ID)는 유의미한 값을 갖고 있지 않기 때문에 큰 문제를 일으키지 않는다&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세션 저장&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;서버에서 &lt;b&gt;클라이언트의 세션 정보를 메모리나 DB 등의 스토리지에 저장&lt;/b&gt;하고 있으므로, 사용자의 로그인 여부 확인이 용이하고, 경우에 따라서 강제 로그아웃 등의 제재를 가할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보안&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;쿠키 노출 자체는 문제가 없지만 해커가 &lt;b&gt;HTTP 요청을 가로챈다면&lt;/b&gt;(세션 하이재킹), 해당 쿠키로 &lt;b&gt;서버에 부적절한 HTTP 요청을 보낼 수 있다&lt;/b&gt;.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 방지하기 위해 세션의 유효시간을 짧게 가져가거나(궁극적인 해결책은 아님) HTTPS를 사용해 메시지를 암호화하는 방법을 사용해야 함.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세션 저장&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서버에서 클라이언트의 상태를 모두 유지하고 있어야 하므로, &lt;b&gt;사용자가 많아질 경우 스토리지 부하가 심하다&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙 세션 저장소에서 세션을 관리하지 않으면 &lt;b&gt;서버 확장에 어려움&lt;/b&gt;이 있다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트마다 배정되는 서버가 달라질 수 있기 때문에 배정된 서버에 해당 사용자의 정보가 존재하지 않을 수 있음&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중앙 세션 저장소에 장애가 발생하면 시스템 전체에 문제가 될 수 있음(Single Point of Failure)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;토큰 기반 인증 방식&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;토큰 기반 인증 중에 가장 많이 사용하고 있는 JWT 기반 인증 방식에 대해 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;JWT란 ?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;JWT(Json Web Token)란&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #ee2323;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Json 포맷을 이용&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하여&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 사용자 속성 정보를 저장&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하는 Claim 기반의 Web Token&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;이다. JWT는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;토큰 자체를 정보로 사용하는 Self-Contained 방식&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;으로 정보를 안전하게 전달한다. &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;JWT 기반 인증 방식을 사용할 경우 클라이언트는 HTTP request header에 JWT(access token)를 포함해 요청하고 서버는 별도의 인증 과정 없이 헤더에 포함되어 있는 JWT 정보를 통해 인증한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;JWT 구조&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;JWT는 세 파트로 나누어지며 . 을 통해 구분되고 순서대로 &lt;b&gt;Header&lt;/b&gt;, &lt;b&gt;Payload&lt;/b&gt;, &lt;b&gt;Signature&lt;/b&gt;로 구성된다. 또한&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Json 형태인&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;b&gt;각 부분은 Base64로 인코딩&lt;/b&gt;되어&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; 표현된다. &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Base64는 암호화된 문자열이 아니고, 같은 문자열에 대해 항상 같은 인코딩 문자열을 반환한다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwXOWH/btrrqZghORF/5G7grsm1hZEcOcEBroGsmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwXOWH/btrrqZghORF/5G7grsm1hZEcOcEBroGsmk/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;amp;amp;nbsp;https://jwt.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwXOWH/btrrqZghORF/5G7grsm1hZEcOcEBroGsmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwXOWH%2FbtrrqZghORF%2F5G7grsm1hZEcOcEBroGsmk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;689&quot; height=&quot;354&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;amp;amp;nbsp;https://jwt.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;b&gt;1. Header(헤더)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btLHax/btrrotC9k2q/ewnzOed6H33KfOkkIL9efK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btLHax/btrrotC9k2q/ewnzOed6H33KfOkkIL9efK/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;amp;amp;nbsp;https://jwt.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btLHax/btrrotC9k2q/ewnzOed6H33KfOkkIL9efK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtLHax%2FbtrrotC9k2q%2FewnzOed6H33KfOkkIL9efK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;199&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;amp;amp;nbsp;https://jwt.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Header는&amp;nbsp;&lt;b&gt;typ&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;alg&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 가지 정보로 구성된다.&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typ: 토큰의 타입을 지정 e.g., JWT&lt;/li&gt;
&lt;li&gt;alg: 알고리즘 방식을 지정하며, 서명(Signature) 및 토큰 검증에 사용 e.g., HS256(SHA256) 또는 RSA&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Payload(페이로드)&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUEYY7/btrrqlRpFhB/HI3H7520IulCJaxN5RsLQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUEYY7/btrrqlRpFhB/HI3H7520IulCJaxN5RsLQ1/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;amp;amp;nbsp;https://jwt.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUEYY7/btrrqlRpFhB/HI3H7520IulCJaxN5RsLQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUEYY7%2FbtrrqlRpFhB%2FHI3H7520IulCJaxN5RsLQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;428&quot; height=&quot;226&quot; data-origin-width=&quot;428&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;amp;amp;nbsp;https://jwt.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Payload에는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;토큰에서 사용할 정보의 조각들인&amp;nbsp;클레임(Claim)&lt;/b&gt;&lt;/span&gt;이 담겨 있다. 클레임은 Json(Key/Value) 형태로 다수의 정보를 넣을 수 있으며, &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;b&gt;등록된(registered) 클레임&lt;/b&gt;, &lt;b&gt;공개(public) 클레임&lt;/b&gt;, &lt;b&gt;비공개(private) 클레임&lt;/b&gt;으로 세 종류가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;등록된 클레임(Registered Claim)&lt;br /&gt;&lt;/b&gt;등록된 클레임은&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;들로, 모두 선택적으로 작성이 가능하며 사용할 것을 권장한다.&lt;br /&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;iss: 토큰 발급자(issuer)&lt;/li&gt;
&lt;li&gt;sub: 토큰 제목(subject)&lt;/li&gt;
&lt;li&gt;aud: 토큰 대상자(audience)&lt;/li&gt;
&lt;li&gt;exp: 토큰 만료 시간(expiration), NumericDate 형식으로 되어 있어야 함 ex) 1480849147370&lt;/li&gt;
&lt;li&gt;nbf: 토큰 활성 날짜(not before), 이 날이 지나기 전의 토큰은 활성화되지 않음&lt;/li&gt;
&lt;li&gt;iat: 토큰 발급 시간(issued at), 토큰 발급 이후의 경과 시간을 알 수 있음&lt;/li&gt;
&lt;li&gt;jti: JWT 토큰 식별자(JWT ID), 중복 방지를 위해 사용하며, 일회용 토큰(Access Token) 등에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;공개 클레임(Public Claim)&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;공개 클레임은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사용자 정의 클레임&lt;/b&gt;으로, &lt;b&gt;공개용 정보를 위해 사용&lt;/b&gt;된다 충돌 방지를 위해 URI 포맷을 이용한다.&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;pre id=&quot;code_1642834982706&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;https://choiblack.tistory.com/&quot;:true
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;비공개 클레임(Private Claim)&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;등록된 클레임도아니고, 공개된 클레임들도 아닙니다. 양 측간에 (보통 클라이언트&amp;harr;서버) 협의 하에 사용되는 정보를 저장한다. 공개 클레임과 달리 이름이 중복되어 충돌될 수 있어 사용에 유의해야 한다.&lt;/span&gt;&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;
&lt;pre id=&quot;code_1642835123946&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;username&quot;:&quot;choiblack&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. Signature(서명)&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;427&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chfCmG/btrrqa3pmui/vmuhrAEt6EBvZopFvZmVL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chfCmG/btrrqa3pmui/vmuhrAEt6EBvZopFvZmVL0/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;amp;amp;nbsp;https://jwt.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chfCmG/btrrqa3pmui/vmuhrAEt6EBvZopFvZmVL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchfCmG%2Fbtrrqa3pmui%2FvmuhrAEt6EBvZopFvZmVL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;427&quot; height=&quot;253&quot; data-origin-width=&quot;427&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;amp;amp;nbsp;https://jwt.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Signature&lt;/span&gt;은 &lt;b&gt;토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드&lt;/b&gt;이다. &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;서명(Signature)은 위에서 만든 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Header&lt;/span&gt;와 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Payload&lt;/span&gt;의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀 키를 이용해 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Header&lt;/span&gt;에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Access token과 Refresh token&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;access token과 refresh token 모두 사용자가 로그인을 하고 인증됐을 경우 서버에서 secret key를 사용해서 발급하는 토큰이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;access token은 &lt;b&gt;클라이언트가 서버 resource를 사용하기 위한 접근용 토큰&lt;/b&gt;으로 만료 기간을 10~15분으로 짧게 두어 자주 발급받게 한다. 이렇게 함으로써 만약 access token이 도난당하더라도 금방 만료되어 안정성이 유지된다.&lt;/li&gt;
&lt;li&gt;refresh token은 access token이 만료됐을 때 &lt;b&gt;access token을 재발급받기 위한 인증용 토큰&lt;/b&gt;이다. 평소의 요청에는 request에 포함되지 않으며 오직 access token을 재발급받는 용도로만 사용한다. 만료 기간은 자동 로그인 기능을 몇 달로 지정할 것인가에 따라 조절하고, 만료 기간이 끝나면 사용자에게 로그인을 다시 요청한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;동작 방식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odlow/btrrpnIYP8A/PFxuCjc8X9AmyoNgdcvRYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odlow/btrrpnIYP8A/PFxuCjc8X9AmyoNgdcvRYk/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;amp;amp;nbsp;https://k3068.tistory.com/90&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odlow/btrrpnIYP8A/PFxuCjc8X9AmyoNgdcvRYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fodlow%2FbtrrpnIYP8A%2FPFxuCjc8X9AmyoNgdcvRYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;463&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;463&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;amp;amp;nbsp;https://k3068.tistory.com/90&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트가 서버로 로그인 요청을 보낸다.&lt;/li&gt;
&lt;li&gt;서버는 클라이언트가 보낸 사용자 정보(ID, PW)가 유효하다면, 서버에서 secret key를 사용해 토큰(access token, refresh token)을 발급한다.&lt;/li&gt;
&lt;li&gt;JWT를 클라이언트(브라우저)에게 전달하고 클라이언트의 로컬 스토리지(세션 스토리지, 쿠키)에 토큰을 저장한다.&lt;/li&gt;
&lt;li&gt;클라이언트는 모든 request 메시지 헤더에 access token을 포함해 전송한다.&lt;/li&gt;
&lt;li&gt;서버는 클라이언트가 보낸 access token을 검증한다.&lt;/li&gt;
&lt;li&gt;access token이 유효하다면, 해당하는 response를 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;토큰 저장&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;토큰을 클라이언트에 저장하기 때문에 &lt;b&gt;서버 리소스의 부담이 없다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 서버에서든 동일한 secret key만 가지고 있으면 토큰을 검증할 수 있기 때문에 &lt;b&gt;서버 확장에 용이&lt;/b&gt;하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;보안&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;버에서 클라이언트의 상태를 저장하고 있지 않아 &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;b&gt;토큰을 무력화하기 어렵다&lt;/b&gt;. 따라서 악의적인 사용자는 만료 기간이 지나기 전까지 정보 탈취가 가능하다.&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;access token의&lt;b&gt; 만료 기간을 최대한 짧게&lt;/b&gt; 해 피해를 최소화해야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;refresh token이 도난될 경우 계속해서 access token을 발급해 악용할 가능성이 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;refresh token을 클라이언트가 아닌 서버에 저장해 access token이 만료되었을 때만 사용한다. &lt;i&gt;(세션 방식과 같은 문제가 발생함)&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Payload&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;payload를 따로 암호화하지 않아 디코딩하면 누구나 정보를 확인할 수 있기 때문에 &lt;b&gt;중요한 정보를 payload에 넣을 수 없다&lt;/b&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;토큰 길이&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;일반적으로 payload에 필요한 정보를 저장하는 경우가 많아 &lt;b&gt;토큰의 길이가 길어져 Message가 무거워질 수 있다&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://k3068.tistory.com/88#spring%25--security%25--%EC%25--%25--%EC%25--%25-C%EB%25-A%25--%25--%EA%25B-%25B-%EB%25B-%25B-%EC%25A-%25--%EC%25-C%BC%EB%25A-%25-C%25--%EC%25--%25B-%EC%25--%25--%25---%25--%EC%BF%25A-%ED%25--%25A-%25--%EB%25B-%25A-%EC%25-B%25-D%EC%25-D%25--%25--%EC%25--%AC%EC%25-A%25A-%ED%25--%25--%EA%25B-%25A-%25--%EC%25-E%25--%EB%25-B%25A--&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://k3068.tistory.com/88#spring%25--security%25--%EC%25--%25--%EC%25--%25-C%EB%25-A%25--%25--%EA%25B-%25B-%EB%25B-%25B-%EC%25A-%25--%EC%25-C%BC%EB%25A-%25-C%25--%EC%25--%25B-%EC%25--%25--%25---%25--%EC%BF%25A-%ED%25--%25A-%25--%EB%25B-%25A-%EC%25-B%25-D%EC%25-D%25--%25--%EC%25--%AC%EC%25-A%25A-%ED%25--%25--%EA%25B-%25A-%25--%EC%25-E%25--%EB%25-B%25A--&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://brownbears.tistory.com/439&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://brownbears.tistory.com/439&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://millo-l.github.io/Session-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D%EB%B0%A9%EC%8B%9D/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://millo-l.github.io/Session-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D%EB%B0%A9%EC%8B%9D/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://mangkyu.tistory.com/56&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mangkyu.tistory.com/56&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velopert.com/2389&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velopert.com/2389&lt;/a&gt;&lt;/p&gt;</description>
      <category>Spring/Spring Security</category>
      <category>authentication</category>
      <category>Authorization</category>
      <category>jwt</category>
      <category>security</category>
      <category>Spring</category>
      <category>세션 기반 인증</category>
      <category>인가</category>
      <category>인증</category>
      <category>토큰 기반 인증</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/56</guid>
      <comments>https://choiblack.tistory.com/56#entry56comment</comments>
      <pubDate>Sat, 22 Jan 2022 17:35:44 +0900</pubDate>
    </item>
    <item>
      <title>[Database] Database Scan</title>
      <link>https://choiblack.tistory.com/55</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Database Scan&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;앞선 인덱스 포스팅에서&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;항상&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;테이블 풀 스캔이 느린 것만은 아니라고 말했다. 어떤 경우에는 인덱스 스캔보다 테이블 풀 스캔이 빠른 경우도 있다. 데이터베이스의 데이터를 스캔하는 방법에는 여러가지 종류가 있고, 어떤 방법이 가장 최적의 방법이라고 말할 수 없다. 다양한 방법 중 적합한 방법을 적용하여 데이터베이스 성능을 높이는 것이 중요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 스캔 방법에 대해 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Table Full Scan&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oRM5F/btrq9WSKKav/SFXpK5rEJyjkRo0ez2Awek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oRM5F/btrq9WSKKav/SFXpK5rEJyjkRo0ez2Awek/img.png&quot; data-alt=&quot;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oRM5F/btrq9WSKKav/SFXpK5rEJyjkRo0ez2Awek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoRM5F%2Fbtrq9WSKKav%2FSFXpK5rEJyjkRo0ez2Awek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;688&quot; height=&quot;457&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스를 거치지 않고 테이블에 있는 모든 레코드를 읽는 방법&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;다중 블록 단위로 메모리에 옮겨지며, 이 블록들은 순차적으로 읽혀진다.&lt;br /&gt;(&lt;b&gt;Sequential access + Multi Block I/O&lt;/b&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;일반적으로 블록들은 서로 인접해 있기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;한 번의 I/O로 처리 가능&lt;/b&gt;하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;한 번에 액세스하는 블록의 양을 정의하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;DB_FILE_MULTIBLOCK_READ_COUNT를 지정한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Optimizer가 Table Full Scan을 선택하는 경우&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적용 가능한 인덱스가 없을 때&lt;/li&gt;
&lt;li&gt;넓은 범위의 데이터 액세스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;적용 가능한 인덱스가 존재하더라도 처리 범위가 넓어 테이블 풀 스캔이 더 적은 비용이 든다면 테이블 풀 스캔을 적용할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;병렬처리 액세스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병렬처리는 테이블 풀 스캔을 더욱 효과적으로 수행하기 때문에 병렬처리로 수행되는 실행 계획을 수립할 때는 항상 테이블 풀 스캔을 선택함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;'FULL' 힌트를 적용했을 때
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FULL 힌트가 적절하지 않다면 옵티마이저가 이를 무시할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Index Range Scan&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEhIF8/btrrbTg6qyU/r13bFTVkSTjr7M4LCqI2Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEhIF8/btrrbTg6qyU/r13bFTVkSTjr7M4LCqI2Q0/img.png&quot; data-alt=&quot;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEhIF8/btrrbTg6qyU/r13bFTVkSTjr7M4LCqI2Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEhIF8%2FbtrrbTg6qyU%2Fr13bFTVkSTjr7M4LCqI2Q0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;699&quot; height=&quot;399&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 선두 컬럼이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;가공되지 않은 상태&lt;/b&gt;로 조건절에 있어야 가능&lt;/li&gt;
&lt;li&gt;인덱스에서 일정량을 스캔하면서 얻은 ROWID로 테이블 레코드를 찾음&lt;/li&gt;
&lt;li&gt;단일 블록 단위로 메모리에 옮겨지며, 이 블록들은 랜덤하게 읽혀진다.&lt;br /&gt;(&lt;b&gt;Random access + Single Block I/O&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;Sequential access + Multi Block I/O가 좋아도 소량의 데이터를 찾을 때 테이블 전체를 스캔하는 것은 비효율적이기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;대용량 테이블에서 소량의 데이터를 찾을 때&lt;/b&gt;는 반드시 인덱스를 사용해야 함&lt;/li&gt;
&lt;li&gt;반대로 대량의 데이터를 찾을 때는 레코드 별로 매번 I/O call이 필요하기 때문에 테이블 풀 스캔보다 불리함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Index Unique Scan&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boZTfM/btrq9YiJ0Gq/q1yKS2CEvzi2sL7nvn6Yr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boZTfM/btrq9YiJ0Gq/q1yKS2CEvzi2sL7nvn6Yr1/img.png&quot; data-alt=&quot;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boZTfM/btrq9YiJ0Gq/q1yKS2CEvzi2sL7nvn6Yr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboZTfM%2Fbtrq9YiJ0Gq%2Fq1yKS2CEvzi2sL7nvn6Yr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;710&quot; height=&quot;402&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단 하나의 ROWID를 추출해 레코드를 찾는 방법&lt;/li&gt;
&lt;li&gt;인덱스가 PK나 Unique index로 생성되어 있어야 하며, 인덱스를 구성하는 모든 컬럼들이 모두 조건절에서 '=' 비교되어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Index Loose Scan&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cahq20/btrrd6l0Fzw/hJFEdI1uIGiKjo2GlfwGo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cahq20/btrrd6l0Fzw/hJFEdI1uIGiKjo2GlfwGo0/img.png&quot; data-alt=&quot;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cahq20/btrrd6l0Fzw/hJFEdI1uIGiKjo2GlfwGo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcahq20%2Fbtrrd6l0Fzw%2FhJFEdI1uIGiKjo2GlfwGo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;695&quot; height=&quot;401&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스에서 필요한 부분만 선택하여 스캔하는 방법&lt;/li&gt;
&lt;li&gt;인덱스 레인지 스캔과 비슷하게 동작하지만 중간마다 필요하지 않은 키 값은 무시함&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반적으로&amp;nbsp;group by&amp;nbsp;또는 min, max&amp;nbsp;등의 함수에 대해 최적화할 때 사용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1642594602681&quot; class=&quot;routeros&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select dept_no, min(emp_no)
from dept_emp
where dept_no between 'd002' and 'd004'
group by dept_no;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dept_emp 테이블은 (dept_no, emp_no) 컬럼으로 다중 컬럼 인덱스를 구성하고 있다고 가정하며, 이 인덱스는 (dept_no, emp_no)를 기준으로 정렬이 되어 있다. 즉 특정 dept_no 그룹 별로 처음에 있는 emp_no만 읽으면 된다. 즉, 인덱스에서 where 조건을 만족하는 범위 전체를 다 스캔할 필요가 없다는 것을 옵티마이저는 알고 있으므로 중간 중간 조건에 맞지 않으면 건너 뛴다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;677&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfRJP3/btrrbT2rq8T/4M9inbTlOsdX97xSh3sXQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfRJP3/btrrbT2rq8T/4M9inbTlOsdX97xSh3sXQk/img.png&quot; data-alt=&quot;출처: https://steady-coding.tistory.com/546&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfRJP3/btrrbT2rq8T/4M9inbTlOsdX97xSh3sXQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfRJP3%2FbtrrbT2rq8T%2F4M9inbTlOsdX97xSh3sXQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;370&quot; height=&quot;860&quot; data-origin-width=&quot;291&quot; data-origin-height=&quot;677&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://steady-coding.tistory.com/546&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Index Full Scan&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DvT9y/btrrcOMTxic/rAskU4qUyYFlbVl94y6FK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DvT9y/btrrcOMTxic/rAskU4qUyYFlbVl94y6FK1/img.png&quot; data-alt=&quot;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DvT9y/btrrcOMTxic/rAskU4qUyYFlbVl94y6FK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDvT9y%2FbtrrcOMTxic%2FrAskU4qUyYFlbVl94y6FK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;678&quot; height=&quot;390&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 선두 컬럼이 조건절에 없으면, 인덱스 레인지 스캔이 불가능하기 때문에 옵티마이저는 테이블 풀 스캔을 고려함&lt;/li&gt;
&lt;li&gt;하지만 대용량 테이블이라 테이블 풀 스캔에 대한 부담이 크면 인덱스를 활용할 필요가 있음&lt;/li&gt;
&lt;li&gt;인덱스의 전체 크기는 테이블의 전체 크기보다 훨씬 적기 때문에 인덱스 레인지 스캔을 할 수 없을 때, 테이블 풀 스캔보다는 인덱스 풀 스캔이 더 좋을 수 있음&lt;/li&gt;
&lt;li&gt;인덱스 풀 스캔을 통해 대부분의 레코드를 필터링하고 일부만 테이블 액세스하는 상황이라면 인덱스 풀 스캔이 유리함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1642594602685&quot; class=&quot;n1ql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select *
from emp
where salary &amp;gt; 9000
order by emp_no;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;emp 테이블은 (emp_no, salary)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컬럼으로 다중 컬럼 인덱스를 구성하고 있다고 가정하면, 조건절 선두에 인덱스 선두 컬럼인 emp_no가 없어서 인덱스 레인지 스캔이 불가능하다. salary &amp;gt; 9000인 레코드가 전체 테이블에서 아주 작은 일부라면 테이블 풀 스캔보다 인덱스 풀 스캔이 유리할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 인덱스 풀 스캔은 인덱스 레인지 스캔을 하지 못한 차선책이기 때문에 salary 컬럼이 선두 컬렁니 인덱스를 생성하는 것이 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&quot;&gt;https://velog.io/@jooh95/DB-Scan-%EC%A2%85%EB%A5%98-%EC%A0%95%EB%A6%AC&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://imnkj.tistory.com/49&quot;&gt;https://imnkj.tistory.com/49&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://steady-coding.tistory.com/546&quot;&gt;https://steady-coding.tistory.com/546&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://wiki.gurubee.net/pages/viewpage.action?pageId=12517471&quot;&gt;http://wiki.gurubee.net/pages/viewpage.action?pageId=12517471&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Database</category>
      <category>CS</category>
      <category>DB</category>
      <category>scan</category>
      <category>데이터베이스</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/55</guid>
      <comments>https://choiblack.tistory.com/55#entry55comment</comments>
      <pubDate>Wed, 19 Jan 2022 21:18:55 +0900</pubDate>
    </item>
    <item>
      <title>[Database] Transaction과 Isolation Levels</title>
      <link>https://choiblack.tistory.com/54</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Transaction이란 ❔❔&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;트랜잭션(Transaction)은 &lt;b&gt;데이터베이스의 상태를 변환하는 하나의 논리적 기능을 수행하기 위한 작업의 단위&lt;/b&gt; 또는 &lt;b&gt;한꺼번에 모두 수행되어야 할 일련의 연산&lt;/b&gt;들을 의미한다. 하&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;나의 트랜잭션은 &lt;/span&gt;&lt;b&gt;Commit&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;되거나 &lt;/span&gt;&lt;b&gt;Rollback&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;트랜잭션의 특성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;트랜잭션은 다음의 &lt;b&gt;ACID&lt;/b&gt;라는 4가지 특성을 만족해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원자성(Atomicity)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션의 작업들이 &lt;u&gt;모두 수행되거나 전혀 수행되지 않아야 한다&lt;/u&gt;. 트랜잭션이 부분적으로 수행된다면 데이터베이스에 반영되지 않아야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-일관성consistency&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#%EC%9D%BC%EA%B4%80%EC%84%B1consistency&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;일관성(Consistency)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 완료된 다음의 상태에서도 트랜잭션이 일어나기 전의 상황과 동일하게 &lt;u&gt;데이터의 일관성을 보장&lt;/u&gt;해야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-고립성isolation&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#%EA%B3%A0%EB%A6%BD%EC%84%B1isolation&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;고립성(Isolation)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;각각의 트랜잭션은 서로 간섭없이 독립적으로 수행&lt;/u&gt;되어야 한다. 둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수 없다. &lt;u&gt;수행 중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다&lt;/u&gt;.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-지속성durability&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#%EC%A7%80%EC%86%8D%EC%84%B1durability&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;지속성(Durability)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;트랜잭션이 정상적으로 종료된 다음에는 영구적으로 데이터베이스에 작업의 결과가 저장&lt;/u&gt;되어야 한다. 소프트웨어나 하드웨어가 고장나더라도 완료된 트랜잭션은 영구적으로 반영이 되어야 한다. 그러므로 recovery system이 필수적이다. 보통 database log를 통해 복구한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;트랜잭션의 상태&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KzNHJ/btrq58STlVX/BtKqKJdDrvtQWltjp3tLlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KzNHJ/btrq58STlVX/BtKqKJdDrvtQWltjp3tLlk/img.png&quot; data-alt=&quot;출처: https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#transaction&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KzNHJ/btrq58STlVX/BtKqKJdDrvtQWltjp3tLlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKzNHJ%2Fbtrq58STlVX%2FBtKqKJdDrvtQWltjp3tLlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;520&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#transaction&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Active&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랜잭션의 활동 상태&lt;/b&gt;. 트랜잭션이 실행중이며 동작중인 상태를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-failed&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#failed&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;Failed&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랜잭션 실패 상태&lt;/b&gt;. 트랜잭션이 더이상 정상적으로 진행 할 수 없는 상태를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-partially-committed&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#partially-committed&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;Partially Committed&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랜잭션의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Commit&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령이 도착한 상태&lt;/b&gt;. 트랜잭션의&lt;span&gt;&amp;nbsp;&lt;/span&gt;commit 이전&lt;span&gt;&amp;nbsp;&lt;/span&gt;sql문이 수행되고&lt;span&gt;&amp;nbsp;&lt;/span&gt;commit만 남은 상태를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-committed&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#committed&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;Committed&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랜잭션 완료 상태&lt;/b&gt;. 트랜잭션이 정상적으로 완료된 상태를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-aborted&quot; href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#aborted&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;b&gt;Aborted&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;트랜잭션이 취소 상태&lt;/b&gt;. 트랜잭션이 취소되고 트랜잭션 실행 이전 데이터로 돌아간 상태를 말한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;Partially Committed와 &lt;b&gt;Committed의 차이점&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Commit&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;요청이 들어오면 &lt;/span&gt;Partial Commited&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태가 된다. 이후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Commit&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;을 문제없이 수행할 수 있으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Committed&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태로 전이되고, &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;만약 오류가 발생하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Failed&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상태가 된다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;즉,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Partial Commited&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Commit&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;요청이 들어왔을때&lt;/b&gt;를 말하며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Commited&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Commit&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;b&gt;을 정상적으로 완료한 상태&lt;/b&gt;를 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;트랜잭션 동시 실행(Concurrent Execution)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 시스템에서 여러 개의 트랜잭션이 동시에 실행될 수 있다. 동시 실행을 하게 되면 프로세서와 디스크 utilization이 높아져 &lt;b&gt;트랜잭션 throuput&lt;/b&gt;(단위 시간 당 트랜잭션 처리 수)&lt;b&gt;이 증가&lt;/b&gt;하고 &lt;b&gt;average response time&lt;/b&gt;(응답이 오는 데까지 걸리는 시간)&lt;b&gt;을 줄일 수 있다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;따라서 데이터베이스는 Consistency(일관성)를 보장하면서 Concurrency(동시성)을 지원해야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;  Consistnecy와 Concurrency 간의 tradeoff가 존재함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; Consistency를 보장하기 위해서는 Concurrency가 떨어지고, Concurrency를 보장하면 Consistency가 떨어진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Transaction Isolation Levels(트랜잭션 격리 수준)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말한 것과 같이 데이터베이스는 Consistency를 보장하면서 Concurrency를 지원해야 한다. 하지만 Consistency와 Concurrency 사이에는 tradeoff가 존재한다.&amp;nbsp;이는&lt;b&gt; 트랜잭션 간의 Isolation(고립성)을 어떻게 지원하느냐에 따라 달라진다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transaction Isolation Levels이란 동시에 여러 트랜잭션이 실행될 때, &lt;b&gt;트랜잭션끼리 얼마나 서로 고립되어 있는지를 나타내는 수준&lt;/b&gt;이다. 데이터베이스는 Isolation의 정도에 따라 4가지의 level을 지원한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Read Uncommitted&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Read Committed&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reapeatable Read&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Serializable&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nAcVV/btrrbSIW8Un/1CqgPo02FT4kFZXUClxczK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nAcVV/btrrbSIW8Un/1CqgPo02FT4kFZXUClxczK/img.png&quot; data-alt=&quot;출처: &amp;amp;amp;nbsp;https://hleee.medium.com/%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-3287d4bcc64d&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nAcVV/btrrbSIW8Un/1CqgPo02FT4kFZXUClxczK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnAcVV%2FbtrrbSIW8Un%2F1CqgPo02FT4kFZXUClxczK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;875&quot; height=&quot;324&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: &amp;amp;nbsp;https://hleee.medium.com/%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-3287d4bcc64d&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래로 내려갈수록 Isolation과 Consistency는 높아지고 Concurrency과 Throuput은 떨어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 3가지 지표의 개념을 짚고 넘어간다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;4ebe&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;Dirty read&lt;/b&gt;: 추가/수정/삭제 중에 &lt;b&gt;커밋 되지 않은 데이터 조회를 허용&lt;/b&gt;함으로써, 트랜잭션이 종료되면 더 이상 존재하지 않거나, 롤백되었거나, 저장 위치가 바뀌었을 수도 있는 데이터를 읽어들이는 경우를 말한다.&lt;/li&gt;
&lt;li id=&quot;c0e3&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;Non-repeatable read&lt;/b&gt;: &lt;span style=&quot;color: #000000;&quot;&gt;하나의 트랜잭션이 같은 값을 조회할 때 값이 다른 &lt;/span&gt;경우를 말한다.&lt;/li&gt;
&lt;li id=&quot;5753&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;Phantom read&lt;/b&gt;: &lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;있던 데이터가 사라지거나 없던 데이터가 생기는 경우 말한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Read Uncommitted&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;커밋되지 않은 데이터에 접근 가능한 수준&lt;/b&gt;으로, 네 가지 Isolation level 중 트랜잭션의 Isolation을 가장 덜 지원하는 가장 느슨한 형태이다. Read uncommitted&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;는 &lt;b&gt;Dirty read&lt;/b&gt;를 유발한다. 하지만 Lock을 유지하는 데에 드는 비용이 제일 적고, Deadlock에 빠질 위험이 적어 성능은 뛰어나다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;따라서 Read uncommitted는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;150e&quot; data-selectable-paragraph=&quot;&quot;&gt;Consistency를 위해 되도록이면 &lt;b&gt;사용하지 않는 것이 이상적&lt;/b&gt;이며,&lt;/li&gt;
&lt;li id=&quot;c160&quot; data-selectable-paragraph=&quot;&quot;&gt;사용하더라도 수정되지 않을 데이터를 조회하거나 몇몇 행이 제대로 조회되지 않아도 무관할 만큼 거대한 양의 데이터를 집계하는 데에만 사용하는 것이 바람직하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;589&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UfbfY/btrq9WLxrXc/IEec0f9ymLkvVX0iGpf8hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UfbfY/btrq9WLxrXc/IEec0f9ymLkvVX0iGpf8hk/img.png&quot; data-alt=&quot;출처: https://private-space.tistory.com/97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UfbfY/btrq9WLxrXc/IEec0f9ymLkvVX0iGpf8hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUfbfY%2Fbtrq9WLxrXc%2FIEec0f9ymLkvVX0iGpf8hk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;589&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://private-space.tistory.com/97&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Read Committed&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Read Uncommitted&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;보다는 높은 격리 수준으로, &lt;b&gt;커밋이 완료된 데이터에 대해서만 조회를 허용&lt;/b&gt;하기 때문에 Dirty read를 방지할 수 있다. 하지만 하나의 트랜잭션이 같은 값을 조회할 때 값이 달라질 수 있는 &lt;b&gt;Non-repeatable read가 발생&lt;/b&gt;할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;따라서 Read committed는&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;dcaf&quot; data-selectable-paragraph=&quot;&quot;&gt;Dirty read를 방지할 수 있다는 점에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Read uncommitted의 한계를 보완하지만,&lt;/li&gt;
&lt;li id=&quot;4cc9&quot; data-selectable-paragraph=&quot;&quot;&gt;Lock이 발생하는만큼 속도나 성능에 있어서는 좀 더 느려질 수 있으며 Deadlock도 발생할 수 있다.&lt;/li&gt;
&lt;li id=&quot;24f8&quot; data-selectable-paragraph=&quot;&quot;&gt;또한 트랜잭션 간 Isolation을 완전히 보장하지 못해 non-repeatable read, phantom read가 발생할 수 있다.&lt;/li&gt;
&lt;li id=&quot;95b4&quot; data-selectable-paragraph=&quot;&quot;&gt;일반 애플리케이션에는 큰 문제가 없을 수 있어도 뱅킹 서비스처럼 데이터의 Integrity(무결성)가 중요하다면 적합하지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (1).png&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVVnTo/btrrcunlZci/q5v2GkobiIxOALd9hTjDk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVVnTo/btrrcunlZci/q5v2GkobiIxOALd9hTjDk1/img.png&quot; data-alt=&quot;출처: https://private-space.tistory.com/97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVVnTo/btrrcunlZci/q5v2GkobiIxOALd9hTjDk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVVnTo%2FbtrrcunlZci%2Fq5v2GkobiIxOALd9hTjDk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;893&quot; height=&quot;787&quot; data-filename=&quot;img (1).png&quot; data-origin-width=&quot;893&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://private-space.tistory.com/97&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Repeatable Read&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션이 시작되고 종료되기 전까지 한 번 조회한 값은 계속 같은 값이 조회&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;되는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 수준으로, 트랜잭션 시작 전에 커밋된 데이터에 한해서만 조회되기 때문에 Non-repeatable read를 방지할 수 있다. Repeatable read는 데이터 수정에는&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;Consistency를 보장하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;추가/삭제에는 Consistency가&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;보장되지 않기 때문에&lt;/b&gt; &lt;b&gt;Phantom read가 발생&lt;/b&gt;할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Repeatable read는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;c43a&quot; data-selectable-paragraph=&quot;&quot;&gt;non-repeatable read를 방지할 수 있다는 점에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Read committed의 단점을 보완하지만,&lt;/li&gt;
&lt;li id=&quot;eb40&quot; data-selectable-paragraph=&quot;&quot;&gt;Lock이 적용되는 범위가 넓어져 성능과 속도가 느려지고,&lt;/li&gt;
&lt;li data-selectable-paragraph=&quot;&quot;&gt;데이터 추가/삭제에서의 Isolation을 보장하지 못해 Phantom read가 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (2).png&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;874&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ccA7EN/btrq7bJBnVr/vOnwIwKqgbENWncDrSVDvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ccA7EN/btrq7bJBnVr/vOnwIwKqgbENWncDrSVDvK/img.png&quot; data-alt=&quot;출처: https://private-space.tistory.com/97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ccA7EN/btrq7bJBnVr/vOnwIwKqgbENWncDrSVDvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FccA7EN%2Fbtrq7bJBnVr%2FvOnwIwKqgbENWncDrSVDvK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;896&quot; height=&quot;874&quot; data-filename=&quot;img (2).png&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;874&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://private-space.tistory.com/97&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Serializable&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;Serializable&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;은 한 트랜잭션을 &lt;b&gt;다른 트랜잭션으로부터 완전히 분리&lt;/b&gt;하여 &lt;b&gt;가장 높은 수준의 Isolation을 보장&lt;/b&gt;하지만 &lt;b&gt;Concurrency와 Throuput은 가장 떨어진다&lt;/b&gt;. 작업 중인 트랜잭션이 완전히 종료될 때까지 다른 어떤 작업도 허용하지 않아 Dirty read, Non-repeatable read, Phantom read를 완벽히 방지한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;Reference&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&lt;a href=&quot;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#transaction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/Database#transaction&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/226&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://coding-factory.tistory.com/226&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pjh3749.tistory.com/225&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://pjh3749.tistory.com/225&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://private-space.tistory.com/97&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://private-space.tistory.com/97&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bubble-dev.tistory.com/entry/DB-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98?category=1156684&quot;&gt;https://bubble-dev.tistory.com/entry/DB-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98?category=1156684&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dar0m.tistory.com/225&quot;&gt;https://dar0m.tistory.com/225&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://joont92.github.io/db/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-isolation-level/&quot;&gt;https://joont92.github.io/db/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-isolation-level/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hleee.medium.com/%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-3287d4bcc64d&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hleee.medium.com/%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-3287d4bcc64d&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Database</category>
      <category>CS</category>
      <category>DB</category>
      <category>transaction</category>
      <category>TRANSACTION ISOLATION LEVEL</category>
      <category>데이터베이스</category>
      <category>트랜잭션</category>
      <category>트랜잭션 격리 수준</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/54</guid>
      <comments>https://choiblack.tistory.com/54#entry54comment</comments>
      <pubDate>Wed, 19 Jan 2022 10:48:00 +0900</pubDate>
    </item>
    <item>
      <title>[Database] Clustered Index와 Non-clustered Index</title>
      <link>https://choiblack.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;https://choiblack.tistory.com/52&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;앞선 포스트&lt;/a&gt;에서 Index(인덱스)에 대해 자세히 알아보았다. 인덱스는 크게 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Clsutered Index&lt;/b&gt;&lt;/span&gt;와&amp;nbsp; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Non-clustered Index&lt;/b&gt;&lt;/span&gt;로 나눌 수 있다. 이 두 종류의 인덱스에 대해 자세히 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Clustered Index와 Non-clustered Index&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Clustered Index&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCc4CY/btrqT1r9l6A/1P9Kk6O5hljMMPgTVj0KWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCc4CY/btrqT1r9l6A/1P9Kk6O5hljMMPgTVj0KWk/img.png&quot; data-alt=&quot;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCc4CY/btrqT1r9l6A/1P9Kk6O5hljMMPgTVj0KWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCc4CY%2FbtrqT1r9l6A%2F1P9Kk6O5hljMMPgTVj0KWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;686&quot; height=&quot;247&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clustered Index&lt;span style=&quot;color: #222426;&quot;&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;테이블의 레코드를 지정된 컬럼에 대해 물리적으로 재배열&lt;/b&gt;&lt;span style=&quot;color: #222426;&quot;&gt;한다. &lt;/span&gt;Clustered Index는 &lt;b&gt;테이블 당 한 개&lt;/b&gt;만 존재할 수 있고, &lt;b&gt;primary key 제약조건을 지정하는 컬럼&lt;/b&gt;에 대해 자동으로 Clustered Index를 생성한다. 이렇기 때문에 우리가 일반적으로 테이블을 생성할 때 특정 컬럼에 primary key 제약조건을 지정했다면, 데이터가 자동으로 정렬되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clustered Index를 생성한 컬럼을 기준으로 테이블의 데이터가 정렬되어 있기 때문에 &lt;b&gt;속도면에서 우수한 성능&lt;/b&gt;을 보인다. 하지만 데이터의 추가/수정/삭제 시 매번 레코드를 정렬해야 하기 때문에 &lt;b&gt;추가/수정/삭제의 성능이 저하&lt;/b&gt;된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Clustered Index의 문제점&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xGD51/btrqNLRgAs7/jkHVEjd4kzQHFoHJRkUJ2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xGD51/btrqNLRgAs7/jkHVEjd4kzQHFoHJRkUJ2k/img.png&quot; data-alt=&quot;출처: https://gwang920.github.io/database/clusterednonclustered/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xGD51/btrqNLRgAs7/jkHVEjd4kzQHFoHJRkUJ2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxGD51%2FbtrqNLRgAs7%2FjkHVEjd4kzQHFoHJRkUJ2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;851&quot; height=&quot;224&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://gwang920.github.io/database/clusterednonclustered/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 위 테이블에서 (ID=2, NAME=넬, Birth=1980)을 추가하면, 아래와 같이 추가될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwEGs8/btrqMbi3CIV/fEbKQFRn2IirjzexfmERE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwEGs8/btrqMbi3CIV/fEbKQFRn2IirjzexfmERE1/img.png&quot; data-alt=&quot;출처: https://gwang920.github.io/database/clusterednonclustered/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwEGs8/btrqMbi3CIV/fEbKQFRn2IirjzexfmERE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwEGs8%2FbtrqMbi3CIV%2FfEbKQFRn2IirjzexfmERE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;853&quot; height=&quot;273&quot; data-origin-width=&quot;864&quot; data-origin-height=&quot;276&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://gwang920.github.io/database/clusterednonclustered/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말한거와 같이 Clustered Index로 지정한 컬럼을 기준으로 데이터를 정렬하기 때문에 ID=2인 데이터를 추가할 경우 ID가 2보다 큰 데이터는 한 칸씩 아래로 이동하고, ID=2인 데이터가 해당 위치에 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 테이블은 3개의 데이터만 이동하면 되지만 만약 ID가 2보다 큰 데이터가 10만, 100만 건 이상 있다고 가정한다면, Insert에 소모되는 비용이 굉장히 커질 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 &lt;b&gt;Primary Key를 어떤 컬럼으로 선택하는가에 따라 데이터베이스의 성능이 좌우된다&lt;/b&gt;.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;왜 우리는 ID를 PK로 설정하고 auto_increment 옵션을 설정하는가 ❔❔&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 보통 DB를 설계할 때 정수형의 ID를 PK로 설정하고 auto_increment 옵션을 설정한다. 우리가 왜 정수형의 ID를 PK로 설정하고 이를 auto_increment 옵션을 주는지 알아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1642337777844&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;create table user (
    email varchar(100) primary key,
    password varchar(100) not null
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 email과 password 필드를 가지고 email을 PK로 하는 user 테이블이 있다고 가정해보자. 이 테이블을 만든 사람은 '이메일은 유저를 식별할 수 있는 필드이기 때문에 PK로 사용할 수 있어!'라고 생각했을 것이다. 하지만 email이 PK이기 때문에 email 컬럼을 통해 clustered index가 생성될 것이다. 이때 a로 시작하는 email을 가진 user를 추가하게 되면, 해당 email보다 사전상 뒤에 나타나는 email을 가진 레코드는 한 칸씩 아래로 이동하고 이 레코드가 해당 위치에 추가될 것이다. &lt;b&gt;대용량 테이블에서 이러한 작업은 극심한 성능 저하를 일으킬 것이다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제점은 추가할 레코드의 PK를 현재 테이블에 있는 레코드의 PK 보다 큰 값으로 설정한다면, 해결할 수 있을 것이다. &lt;b&gt;따라서 우리는 ID라는 별도의 필드를 PK로 설정하고 auto_increament 옵션을 주어 clustered index에서 발생할 수 있는 문제점을 해결한 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Clustered Index 구조&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMcjXJ/btrqRTHMpXl/cZYVdKK52QAV7379zFNO20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMcjXJ/btrqRTHMpXl/cZYVdKK52QAV7379zFNO20/img.png&quot; data-alt=&quot;출처: https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMcjXJ/btrqRTHMpXl/cZYVdKK52QAV7379zFNO20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMcjXJ%2FbtrqRTHMpXl%2FcZYVdKK52QAV7379zFNO20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;299&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clustered Index를 구성하기 위해 &lt;b&gt;레코드를 해당 컬럼으로 정렬&lt;/b&gt;한 후에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;루트 페이지를 만들게 된다. Clustered Index는&lt;span&gt;&amp;nbsp;&lt;/span&gt;루트 페이지와&lt;span&gt;&amp;nbsp;&lt;/span&gt;리프 페이지로 구성되며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;리프 페이지는 데이터 그 자체&lt;/b&gt;이다. 즉, &lt;b&gt;Index 자체에 데이터가 포함&lt;/b&gt;된다. Index Page를&lt;span&gt;&amp;nbsp;&lt;/span&gt;키 값과&lt;span&gt;&amp;nbsp;&lt;/span&gt;데이터 페이지 번호로 구성&lt;span style=&quot;color: #222426;&quot;&gt;하고, 검색하고자하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;데이터의&lt;span&gt;&amp;nbsp;&lt;/span&gt;키 값으로&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;페이지 번호를 검색하여 데이터를 찾는다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Clustered Index 특징 정리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블 당 1개만 허용&lt;/li&gt;
&lt;li&gt;물리적으로 레코드를 재배열한다.&lt;/li&gt;
&lt;li&gt;PK 설정 시 해당 컬럼에 대해 자동으로 Clustered Index가 생성된다.&lt;/li&gt;
&lt;li&gt;인덱스의 리프 페이지가 곧 데이터이다. 즉, 테이블 자체가 인덱스이기 때문에 따로 인덱스 페이지를 만들지 않는다.&lt;/li&gt;
&lt;li&gt;Non-clustered Index보다 속도면에서 우수한 성능을 보이지만, 데이터 추가/수정/삭제 시 매번 정렬을 수행해야 하기 때문에 추가/수정/삭제의 성능이 떨어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Non-clustered Index&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PksPQ/btrqQeFyfRc/qfErMZVP4KbKWHUEKlB7pK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PksPQ/btrqQeFyfRc/qfErMZVP4KbKWHUEKlB7pK/img.png&quot; data-alt=&quot;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PksPQ/btrqQeFyfRc/qfErMZVP4KbKWHUEKlB7pK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPksPQ%2FbtrqQeFyfRc%2FqfErMZVP4KbKWHUEKlB7pK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;592&quot; height=&quot;293&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Non-clustered Index는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;물리적으로 레코드를 정렬하지 않은 상태&lt;/b&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;데이터 페이지가 구성&lt;/b&gt;된다. 즉, 테이블의 레코드는 그대로두고 &lt;b&gt;지정된 컬럼에 대해 정렬된 인덱스&lt;/b&gt;를 만든다. 물리적으로 레코드를 정렬하지 않기 때문에&amp;nbsp;&lt;b&gt;Clustered Index보다 속도면에서 성능이 떨어지지만, 추가/수정/삭제의 성능은 더 뛰어나다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Non-clustered Index는&amp;nbsp;&lt;b&gt;unique 제약 조건을 설정한 컬럼&lt;/b&gt;에 대해 자동으로 Non-clustered Index를 생성한다. 따라서 &lt;b&gt;테이블 당 여러개 존재 가능&lt;/b&gt;하다. 하지만 함부로 남용하면 오히려 시스템 성능이 저하될 수 있다. &lt;i&gt;(성능 저하 문제는&lt;span&gt;&lt;a href=&quot;https://choiblack.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; Database Scan 포스트&lt;/a&gt;에서 설명&lt;/span&gt;)&lt;/i&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Non-clustered Index 구조&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvIBF2/btrqOfLstEm/UT4I9V4711hNK1zOKkRHnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvIBF2/btrqOfLstEm/UT4I9V4711hNK1zOKkRHnk/img.png&quot; data-alt=&quot;출처: https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvIBF2/btrqOfLstEm/UT4I9V4711hNK1zOKkRHnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvIBF2%2FbtrqOfLstEm%2FUT4I9V4711hNK1zOKkRHnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;337&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;Non-clustered Index는 &lt;b&gt;데이터 페이지를 건들지 않고, 별도의 장소에 인덱스 페이지&lt;/b&gt;를 생성한다. Non-clustered Index의 인덱스 페이지는 키 값과 위치 포인터(ROWID)로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;ROWID는 '파일그룹번호-데이터페이지번호-데이터페이지오프셋'으로 구성되는 포인팅 정보.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;우선 인덱스 페이지의 리프 페이지에 &lt;b&gt;인덱스로 구성한 컬럼을 정렬&lt;/b&gt;하고 위치 포인터(ROWID)를 생성한다. 위치 포인터는 Clustered Index와 달리 &lt;b&gt;'페이지 번호 + #오프셋'&lt;/b&gt;이 기록되어 바로 데이터 위치를 가리킨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;(2, indexTest2)를 찾는다고 가정해보면, 루트 페이지에서 101번 리프 페이지로 이동하고 101번 리프 페이지에 데이터 페이지가 102, 데이터 페이지 오프셋이 2으로 되어 있기 때문에 102번 페이지의 두 번째의 데이터를 가져온다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Non-clustered Index 특징 정리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레코드는 정렬되지 않고, 인덱스 페이지만 정렬된다.&lt;/li&gt;
&lt;li&gt;한 테이블에 여러 개의 Non-clustered Index를 생성할 수 있다.&lt;/li&gt;
&lt;li&gt;unique 제약조건 설정 시 자동으로 Non-clustered Index가 생성된다.&lt;/li&gt;
&lt;li&gt;물리적으로 테이블이 정렬되어 있지 않기 때문에 Clustered Index보다 속도면에서 성능은 떨어지지만, 데이터의 입력, 수정, 삭제 성능은 더 뛰어나다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;인덱스를 생성할 때 데이터 페이지는 그냥 둔 상태에서 별도의 인덱스 페이지를 따로 만들기 때문에 추가적인 용량이 필요하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Clustered Index &amp;amp; Non-clustered Index&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LAP9y/btrqOg4Jijm/UFt8V6Wk1iq4J6zrkvFjnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LAP9y/btrqOg4Jijm/UFt8V6Wk1iq4J6zrkvFjnK/img.png&quot; data-alt=&quot;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LAP9y/btrqOg4Jijm/UFt8V6Wk1iq4J6zrkvFjnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLAP9y%2FbtrqOg4Jijm%2FUFt8V6Wk1iq4J6zrkvFjnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;493&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;493&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Multiple-column Index&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bREuAR/btrq0RJzQRD/aOYhF3dRKxvSAkpJRLzyMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bREuAR/btrq0RJzQRD/aOYhF3dRKxvSAkpJRLzyMk/img.png&quot; data-alt=&quot;출처: https://steady-coding.tistory.com/546&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bREuAR/btrq0RJzQRD/aOYhF3dRKxvSAkpJRLzyMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbREuAR%2Fbtrq0RJzQRD%2FaOYhF3dRKxvSAkpJRLzyMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;488&quot; height=&quot;823&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://steady-coding.tistory.com/546&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 컬럼 인덱스는 &lt;b&gt;두 개 이상의 컬럼을 조합하여 생성한 인덱스&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다중 컬럼 인덱스에서 중요한 것은 &lt;b&gt;인덱스의 두 번째 컬럼은 첫 번째 컬럼에 의존해서 정렬되어 있다&lt;/b&gt;는 것이다. 즉, 두 번째 컬럼은 첫 번째 컬럼의 값이 같은 레코드에서만 정렬되어 있다. 따라서 다중 컬럼 인덱스에서는 &lt;b&gt;컬럼의 순서&lt;/b&gt;가 상당히 중요하다. '=' 조건과 같이 개수가 적은 데이터를 조회하는 컬럼을 앞에 설정하고, 범위 검색과 같이 개수가 많은 데이터를 조회하는 컬럼을 뒤쪽에 설정해야 효율적이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한, 다중 컬럼 인덱스는 단일 컬럼 인덱스보다 추가/수정/삭제 시 더 비효율적이기 때문에 가급적으로 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추가/수정/삭제를 하지 않는 컬럼을 선정&lt;/b&gt;하는 것이 좋다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;언제 Multiple-column Index를 사용해야 할까 &lt;/b&gt;&lt;b&gt;❔❔&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 조회 시 &lt;b&gt;단일 컬럼 인덱스를 여러 개 사용해야 하는 경우가 많다면 다중 컬럼 인덱스를 고려&lt;/b&gt;해볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에를 들어 A, B 컬럼을 조건절에 포함한 검색을 자주한다고 가정해보자,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;A, B 컬럼 각각 인덱스를 설정할 경우 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옵티마이저는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;A 컬럼과 B 컬럼 중 어떤 컬럼이 더 빠르게 검색되는지(레코드 수가 적은지) 판단하고 더 빠른 컬럼의 인덱스를 통해 레코드를 탐색하고 이 레코드에서 B 컬럼을 탐색한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;A, B 컬럼 복합 인덱스를 설정할 경우&lt;/b&gt; 인덱스에 A와 B 컬럼의 정보가 있기 때문에 바로 탐색이 가능하므로 위의 방식보다 빠르다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 where 절에 B 컬럼만 사용할 경우 이 복합 인덱스는 B가 A에 의존적으로 정렬되기 때문에 해당 인덱스를 탐색하지 않는다. (where 절에 A 컬럼만 사용할 경우는 인덱스를 탐색한다.)&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;어떤 컬럼으로 인덱스를 만들어야 할까 ❔❔&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Cardinality(카디널리티)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;카디널리티는 &lt;b&gt;전체 행에 대한 특정 컬럼의 중복 수치를 나타내는 지표&lt;/b&gt;이다. 예를 들어, 테이블의 '성별' 컬럼이 '남자'와 '여자'로 구성된다면, 성별 컬럼의 카디널리티는 2가 된다. 반대로 주민등록번호 같이 개인별 고유한 값을 가지는 컬럼의 카디널리티는 테이블에 저장된 레코드의 개수가 된다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;✅&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;즉, 중복도가 '낮으면' 카디널리티가 높고, 중복도가 '높으면' 카디널리티가 낮다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;오라클에서는 아래와 같은 쿼리로 특정 컬럼의 카디널리티를 구할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1642400710398&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select count(distinct gender) from user;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Selectivity(선택도)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;선택도는 &lt;b&gt;데이터의 집합에서 특정 값을 얼마나 잘 골라낼 수 있는지에 대한 지표&lt;/b&gt;이다. 선택도가 1이라는 뜻은 모든 값이 고유하다는 의미이다. 선택도는 카디널리티로부터 계산할 수 있다. 선택도는 카디널리티에 비례한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;✅&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 선택도 또한 중복도가 '낮으면' 선택도가 높고, 중복도가 '높으면' 선택도가 낮다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1642400840963&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Selectivity = Cardinarlity / Total Number of Records&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;선택도는 어떤 컬럼으로 인덱스를 생성하면 좋을지 고를 때 자주 사용&lt;/b&gt;한다. &lt;b&gt;선택도가 높은&lt;/b&gt; 컬럼에 인덱스를 생성하면 인덱스가 특정 레코드를 잘 골라내서 &lt;b&gt;인덱스의 효율이 높아진다&lt;/b&gt;. 따라서 Primary Key, Candidate Key, Unique Key는 거의 1에 가까운 선택도를 가지기 때문에 이러한 컬럼으로 인덱스를 생성할 경우 효율적이다. 반대로 선택도가 낮은 컬럼에 인덱스를 생성할 경우 인덱스 효율이 떨어지고, 최악의 경우 Table Full Scan이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;✅ &lt;/b&gt;&lt;/span&gt;&lt;/b&gt;데이터베이스에서 인덱스의 선택도를 높이는 방법은 간단하다.&amp;nbsp;&lt;b&gt;두 개 이상의 컬럼을 조합해 인덱스를 생성하면, 조합된 인덱스 키의 카디널리티가 증가하고 선택도가 증가하여 효율적인 인덱스를 만들 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;https://gwang920.github.io/database/clusterednonclustered/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gwang920.github.io/database/clusterednonclustered/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@gillog/SQL-Clustered-Index-Non-Clustered-Index&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NkZ6r6z2pBg&amp;amp;t=646s&quot;&gt;https://www.youtube.com/watch?v=NkZ6r6z2pBg&amp;amp;t=646s&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://itholic.github.io/database-cardinality/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://itholic.github.io/database-cardinality/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hbase.tistory.com/195&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hbase.tistory.com/195&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://steady-coding.tistory.com/546&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://steady-coding.tistory.com/546&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://code-factory.tistory.com/24&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://code-factory.tistory.com/24&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS/Database</category>
      <category>Cardinality</category>
      <category>clustered index</category>
      <category>CS</category>
      <category>DB</category>
      <category>Multiple-column Index</category>
      <category>Non-clustered Index</category>
      <category>Selectivity</category>
      <category>데이터베이스</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/53</guid>
      <comments>https://choiblack.tistory.com/53#entry53comment</comments>
      <pubDate>Mon, 17 Jan 2022 16:24:00 +0900</pubDate>
    </item>
    <item>
      <title>[Database] Index</title>
      <link>https://choiblack.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Index란 우리가 실생활에서 자주 접해볼 수 있는 단어이다. 우리는 책에서 원하는 내용을 찾기 위해서 책의 처음부터 끝까지 원하는 내용을 찾아보는 것이 아니라 목차나 인덱스에서 원하는 내용을 먼저 찾은 뒤 해당 내용이 있는 페이지를 찾아간다. 이와 같은 방식으로 데이터베이스에서도 인덱스를 사용한다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Database에서 Index 란 ❔❔&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brCD9F/btrqNfcZlVl/LlIPW7x2Pr7gyVYysQICX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brCD9F/btrqNfcZlVl/LlIPW7x2Pr7gyVYysQICX0/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://mangkyu.tistory.com/96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brCD9F/btrqNfcZlVl/LlIPW7x2Pr7gyVYysQICX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrCD9F%2FbtrqNfcZlVl%2FLlIPW7x2Pr7gyVYysQICX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;865&quot; height=&quot;453&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://mangkyu.tistory.com/96&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에서 인덱스란 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에서 데이터 조회 요청을 하면, DB 서버 프로세스는 메모리(DB 버퍼 캐시)를 먼저 확인한다. 메모리에는 자주 사용되는 테이블이 캐싱되어 있는데, 메모리에 원하는 데이터가 없는 경우 디스크에서 데이터 파일을 복사해온 후 조회한 데이터를 찾아 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 인덱스를 사용하지 않은 컬럼을 조회할 경우 전체 테이블 블록을 가져와 탐색하는 &lt;b&gt;Table Full Scan&lt;/b&gt;을 해야 한다. &lt;b&gt;Table Full Scan은 테이블 전체를 비교하여 탐색하기 때문에 비교적 속도가 느리다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;(항상 풀 스캔이 느린 것만은 아니다. &lt;i&gt;&lt;a href=&quot;https://choiblack.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Database Scan 포스트&lt;/a&gt;에서 설명&lt;/i&gt;)&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &lt;b&gt;인덱스를 사용하여 Table Full Scan을 최소화해 조회 속도를 향상시키는 것이 중요하다&lt;/b&gt;.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;인덱스 관리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS는 인덱스를 항상 최신의 &lt;b&gt;정렬된 상태로 유지&lt;/b&gt;해야 원하는 값을 빠르게 탐색할 수 있다. 그렇기 때문에 인덱스가 적용된 컬럼에 Insert(삽입), Update(수정), Delete(삭제)가 수행된다면 &lt;b&gt;추가적인 연산이 발생하고 그에 따른 오버헤드가 발생한다&lt;/b&gt;.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Insert: 새로운 데이터에 대한 인덱스 추가&lt;/li&gt;
&lt;li&gt;Update: 기존의 인덱스를 사용하지 않음 처리하고, 수정된 데이터에 대한 인덱스 추가&lt;/li&gt;
&lt;li&gt;Delete: 삭제하는 데이터의 인덱스를 사용하지 않음 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;인덱스의 장점과 단점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;조건 검색 Where 절의 효율성&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 컬럼 입장에서 테이블의 레코드는 순서가 없이 저장된다. 이때 Where 절의 특정 조건에 맞는 데이터를 찾기 위해서 테이블의 처음부터 끝까지 풀 스캔을 하면서 조건에 부합하는지 비교해야 한다. 하지만 &lt;b&gt;인덱스는 데이터가 정렬되어 있기 때문에 &lt;/b&gt;Where 절의 조건에 맞는 데이터를 빠르게 찾아낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;정렬 Order by 절의 효율성&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스를 사용하지 않을 경우 전체 테이블을 대상으로 Order by에 의한 정렬을 해야 한다. 하지만 인덱스를 사용할 경우 &lt;b&gt;이미 정렬되어 있기 때문에 &lt;/b&gt;정렬에 필요한 자원을 소모할 필요가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Min, Max의 효율성&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Min, Max 또한 인덱스를 사용하지 않을 경우 Table Full Scan을 해야 한다. 하지만 &lt;b&gt;인덱스는 정렬되어 있기 때문에&lt;/b&gt; 레코드의 시작값(Min) 또는 끝값(Max)를 가져오면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스를 관리하기 위해 DB의 약 10%에 해당하는 &lt;b&gt;추가 저장 공간&lt;/b&gt;이 필요하다.&lt;/li&gt;
&lt;li&gt;인덱스를 관리하기 위해 &lt;b&gt;추가 작업&lt;/b&gt;이 필요하다&lt;/li&gt;
&lt;li&gt;인덱스를 잘못 사용할 경우 오히려 &lt;b&gt;성능이 저하될 수 있다&lt;/b&gt;.&lt;br /&gt;&lt;i&gt;(이유는 &lt;a href=&quot;https://choiblack.tistory.com/55&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;i&gt;&lt;i&gt;Database Scan 포스트&lt;/i&gt;&lt;/i&gt;&lt;/a&gt;에서 설명)&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;인덱스를 사용하면 좋은 경우&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인덱스를 효율적으로 사용하기 위해서는 &lt;b&gt;데이터가 거의 중복되지 않는 컬럼(Cardinality가 낮음 컬럼)&lt;/b&gt;이나 &lt;b&gt;조건절&lt;/b&gt; &lt;b&gt;또는 Order by 절에 자주 사용되는 컬럼&lt;/b&gt;을 인덱스로 생성하는 것이 좋다. 또한 규모가 작은 테이블에 인덱스를 사용할 경우 Table Full Scan과 차이가 크지 않기 때문에 &lt;b&gt;규모가 큰 테이블&lt;/b&gt;에 인덱스를 사용하는 것이 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;규모가 큰 테이블&lt;/li&gt;
&lt;li&gt;Insert, Update, Delete가 자주 발생하지 않는 컬럼&lt;/li&gt;
&lt;li&gt;Join이나 Where, Order by에 자주 사용되는 컬럼&lt;/li&gt;
&lt;li&gt;데이터의 중복도가 낮은 컬럼(Cardinality가 낮은 컬럼)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;인덱스의 자료구조&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인덱스를 구현하는 대표적인 자료구조인 해시 테이블과 B+트리에 대해 간단하게 알아보자.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;Hash Table&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블은 (Key, Value) 형태로 데이터를 저장해 &lt;b&gt;Key를 이용하여 데이터를 빠르게 가져올 수 있다는 장점&lt;/b&gt;이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xJE1f/btrqLwG8k4Z/tlqgcecnzrMXbIaFbWkqyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xJE1f/btrqLwG8k4Z/tlqgcecnzrMXbIaFbWkqyk/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://mangkyu.tistory.com/96&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xJE1f/btrqLwG8k4Z/tlqgcecnzrMXbIaFbWkqyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxJE1f%2FbtrqLwG8k4Z%2FtlqgcecnzrMXbIaFbWkqyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;351&quot; height=&quot;257&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://mangkyu.tistory.com/96&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블 기반의 인덱스는 (컬럼의 값, 데이터 위치)를 (Key, Value)로 사용하여 컬럼의 값으로 생성된 해시를 통해 인덱스를 구현한다. 해시 테이블의 시간복잡도는 &lt;b&gt;O(1)로 굉장히 빠른 검색을 지원&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 해시 테이블의 경우 &lt;b&gt;등호(=) 연산에만 특화&lt;/b&gt;되어 있기 때문에 인덱스에서 사용이 제한적이다. Key 값을 생성하는 해시 함수는 값이 조금이라도 달라지면 완전히 다른 해시 값을 생성하기 때문에 &lt;b&gt;부등호 연산(&amp;lt;, &amp;gt;)이 자주 사용되는 데이터베이스 검색에는 적합하지 않다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 이유로 데이터베이스의 인덱스에서는 B+트리가 일반적으로 사용된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;B+Tree&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/erwWl4/btrqJ7Olhz8/2aV8IqHGj9KL7uuN6LQql1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/erwWl4/btrqJ7Olhz8/2aV8IqHGj9KL7uuN6LQql1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/erwWl4/btrqJ7Olhz8/2aV8IqHGj9KL7uuN6LQql1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FerwWl4%2FbtrqJ7Olhz8%2F2aV8IqHGj9KL7uuN6LQql1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1125&quot; height=&quot;383&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;383&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리프노드는 인덱스와 데이터(ROWID)를 가지고 있고, 내부노드는 인덱스만 갖는다.&lt;/li&gt;
&lt;li&gt;리프노드들은 연결되어 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B+트리는 &lt;b&gt;리프노드들이 모두 연결되어 있기 때문에 데이터베이스에서 자주 사용되는 부등호 연산에 적합한 자료구조&lt;/b&gt;이다. B+트리의 시간복잡도는 &lt;b&gt;O(logN)&lt;/b&gt;으로 해시 테이블보다 탐색 시간이 오래 걸리지만, 부등호 연산에 적합하기 때문에 데이터베이스의 인덱스에서는 B+트리를 주로 사용한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://mangkyu.tistory.com/96&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mangkyu.tistory.com/96&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://lovefor-you.tistory.com/183&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://lovefor-you.tistory.com/183&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hoon93.tistory.com/53&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://hoon93.tistory.com/53&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://wedul.site/403&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://wedul.site/403&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://coding-factory.tistory.com/746&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://coding-factory.tistory.com/746&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=9ZXIoh9PtwY&amp;amp;t=313s&quot;&gt;https://www.youtube.com/watch?v=9ZXIoh9PtwY&amp;amp;t=313s&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NkZ6r6z2pBg&amp;amp;t=646s&quot;&gt;https://www.youtube.com/watch?v=NkZ6r6z2pBg&amp;amp;t=646s&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/Database</category>
      <category>CS</category>
      <category>DB</category>
      <category>index</category>
      <category>scan</category>
      <category>데이터베이스</category>
      <category>스캔</category>
      <category>인덱스</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/52</guid>
      <comments>https://choiblack.tistory.com/52#entry52comment</comments>
      <pubDate>Fri, 14 Jan 2022 22:55:18 +0900</pubDate>
    </item>
    <item>
      <title>[Kubernetes] Objects</title>
      <link>https://choiblack.tistory.com/51</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kubernetes Objects&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Pod&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;193&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yNmZW/btrqvAajpm2/y46hr5ZKszPrTzB0OsK560/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yNmZW/btrqvAajpm2/y46hr5ZKszPrTzB0OsK560/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yNmZW/btrqvAajpm2/y46hr5ZKszPrTzB0OsK560/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyNmZW%2FbtrqvAajpm2%2Fy46hr5ZKszPrTzB0OsK560%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;158&quot; height=&quot;204&quot; data-origin-width=&quot;193&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가장 작은 배포 단위&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;쿠버네티스는 컨테이너를 직접 관리하지 않고 Pod으로 감싸서 관리함&lt;/li&gt;
&lt;li&gt;전체 클러스터에서 Pod 별로 고유한 IP 할당&lt;/li&gt;
&lt;li&gt;하나의 Pod 안에 여러 개의 컨테이너가 속할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;ReplicaSet&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csmF4w/btrqnkUB3Be/PhwhlKIG9dQXzmY7IKhMLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csmF4w/btrqnkUB3Be/PhwhlKIG9dQXzmY7IKhMLk/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csmF4w/btrqnkUB3Be/PhwhlKIG9dQXzmY7IKhMLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsmF4w%2FbtrqnkUB3Be%2FPhwhlKIG9dQXzmY7IKhMLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;346&quot; height=&quot;203&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 Pod를 관리&lt;/li&gt;
&lt;li&gt;새로운 Pod은 Template을 참고하여 생성&lt;/li&gt;
&lt;li&gt;새로운 Pod을 생성하거나 기존의 Pod을 제거하여 원하는 Replica 수를 유지함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Deployment&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ezgif.com-gif-maker (1).gif&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;286&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MHDTp/btrqpsEE2t9/QQX2lDftE4Cjfe9JINpTgK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MHDTp/btrqpsEE2t9/QQX2lDftE4Cjfe9JINpTgK/img.gif&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MHDTp/btrqpsEE2t9/QQX2lDftE4Cjfe9JINpTgK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/MHDTp/btrqpsEE2t9/QQX2lDftE4Cjfe9JINpTgK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;455&quot; height=&quot;250&quot; data-filename=&quot;ezgif.com-gif-maker (1).gif&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;286&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배포 버전 관리&lt;/li&gt;
&lt;li&gt;무중단 배포를 위해 내부적으로 ReplicaSet을 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Service&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ClusterIP&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCSi8l/btrqptDyCFi/HdkgYSZnuIbJyqhBPeNDDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCSi8l/btrqptDyCFi/HdkgYSZnuIbJyqhBPeNDDK/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCSi8l/btrqptDyCFi/HdkgYSZnuIbJyqhBPeNDDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCSi8l%2FbtrqptDyCFi%2FHdkgYSZnuIbJyqhBPeNDDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;258&quot; height=&quot;218&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클러스터 내부에서 사용하는 프록시&amp;nbsp;&amp;rarr; 클러스터 내부의 Pod들을 로드밸런서하는 서비스&lt;/li&gt;
&lt;li&gt;Pod은 동적이지만, 서비스는 고유 IP를 가짐
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;Pod이 업데이트될 때, 자신의 IP를 유지한 상태로 업데이트되는 것이 아니라 현재 Pod을 삭제하고 새로운 Pod을 생성하는 매커니즘이기 때문에 요청받을 고유한 IP가 필요함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NodePort&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjiZ6O/btrqnjO0oxw/JGWadQk2kFsbG3l536dun1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjiZ6O/btrqnjO0oxw/JGWadQk2kFsbG3l536dun1/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjiZ6O/btrqnjO0oxw/JGWadQk2kFsbG3l536dun1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjiZ6O%2FbtrqnjO0oxw%2FJGWadQk2kFsbG3l536dun1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;846&quot; height=&quot;390&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노드(host)에 노출되어 외부에서 접근 가능한 서비스
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ClusterIP는 내부에서만 통신할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모든 노드에 동일한 포트로 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LoadBalancer&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTLRYD/btrqpt4EWkz/FomdbMksk2wg1RvZkouWkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTLRYD/btrqpt4EWkz/FomdbMksk2wg1RvZkouWkK/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTLRYD/btrqpt4EWkz/FomdbMksk2wg1RvZkouWkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTLRYD%2Fbtrqpt4EWkz%2FFomdbMksk2wg1RvZkouWkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;744&quot; height=&quot;354&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 IP 주소를 외부에 노출&lt;/li&gt;
&lt;li&gt;각각의 Node에 트래픽 분산&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Ingress&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ubQJA/btrqtVM7rNO/vdfjs2WSrfjPkld7S1C6QK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ubQJA/btrqtVM7rNO/vdfjs2WSrfjPkld7S1C6QK/img.png&quot; data-alt=&quot;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;amp;index=7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ubQJA/btrqtVM7rNO/vdfjs2WSrfjPkld7S1C6QK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FubQJA%2FbtrqtVM7rNO%2Fvdfjs2WSrfjPkld7S1C6QK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;699&quot; height=&quot;583&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;amp;amp;index=7&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인 또는 경로별 내부의 ClusterIP를 연결하여 라우팅
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 도메인에 대해 모두 NodePort나 LB를 만들면 자원이 낭비됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;index=7&quot;&gt;https://www.youtube.com/watch?v=-gIyfII5eak&amp;amp;list=PLIUCBpK1dpsNf1m-2kiosmfn2nXfljQgb&amp;amp;index=7&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DevOps/Kubernetes</category>
      <category>kubernetes</category>
      <category>object</category>
      <category>쿠버네티스</category>
      <author>최블랙</author>
      <guid isPermaLink="true">https://choiblack.tistory.com/51</guid>
      <comments>https://choiblack.tistory.com/51#entry51comment</comments>
      <pubDate>Tue, 11 Jan 2022 19:38:10 +0900</pubDate>
    </item>
  </channel>
</rss>