<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>database on 오늘도 개발을 한다.</title>
    <link>https://cloudsoswift.github.io/post/develop/database/</link>
    <description>오늘도 개발을 한다. (database)</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>ko-kr</language>
    
    <atom:link href="https://cloudsoswift.github.io/post/develop/database/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>[DB] PostgreSQL 알아보기 &#43; PostGIS를 활용한 연산해보기 (w. DBeaver, GiST)</title>
      <link>https://cloudsoswift.github.io/post/develop/database/postgresql-common/</link>
      <pubDate>Wed, 18 Dec 2024 09:12:20 +0900</pubDate>
      
      <guid>https://cloudsoswift.github.io/post/develop/database/postgresql-common/</guid>
      <description>&lt;h1 id=&#34;서론&#34; &gt;서론
&lt;span&gt;
    &lt;a href=&#34;#%ec%84%9c%eb%a1%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/orm712/CS-712&#34;&gt;CS 스터디&lt;/a&gt;에서 12월 17일 발표한 &lt;a href=&#34;https://github.com/orm712/CS-712/blob/main/04-DATABASE/19_PostgreSQL/Readme.md&#34;&gt;PostgreSQL 알아보기&lt;/a&gt;에 대해 정리하고, 이를 실습해본 문서를 블로그에 공유하고자 한다.&lt;/p&gt;
&lt;h1 id=&#34;개요&#34; &gt;개요
&lt;span&gt;
    &lt;a href=&#34;#%ea%b0%9c%ec%9a%94&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;hr&gt;
&lt;h2 id=&#34;postgresql&#34; &gt;&lt;code&gt;PostgreSQL&lt;/code&gt;?
&lt;span&gt;
    &lt;a href=&#34;#postgresql&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;복잡한 데이터 워크로드들을 안전하게 저장 및 확장할 수 있는 기능들을 제공하는 오픈 소스 &lt;code&gt;객체-관계형 데이터베이스 시스템&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;객체-관계형 DB(Object-relational DB, ORD)&lt;/code&gt;: 일반적인 &lt;code&gt;관계형 DB&lt;/code&gt;와 유사하지만, &lt;code&gt;객체지향 개념&lt;/code&gt;이 추가적으로 지원되는 DB. 즉, DB단에서 &lt;code&gt;클래스&lt;/code&gt;, &lt;code&gt;객체&lt;/code&gt; 및 &lt;code&gt;상속&lt;/code&gt;의 개념을 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2001년부터 &lt;code&gt;ACID&lt;/code&gt;를 지원해왔으며, 대부분의 &lt;code&gt;주요 OS들을 지원&lt;/code&gt;함
&lt;ul&gt;
&lt;li&gt;Linux(Debian, Ubuntu, Redhat 등..), macOS, Windows, BSD(OpenBSD, FreeBSD, ..), Solaris&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;지리공간 데이터&lt;/code&gt;를 효과적으로 저장 및 인덱싱하고 관련 쿼리를 지원하는 &lt;a href=&#34;https://postgis.net/&#34;&gt;&lt;code&gt;PostGIS&lt;/code&gt;&lt;/a&gt;, DB단에서 암호화를 수행할 수 있는 기능들을 제공하는 &lt;a href=&#34;https://www.postgresql.org/docs/current/pgcrypto.html&#34;&gt;&lt;code&gt;pgcrypto&lt;/code&gt;&lt;/a&gt;와 같은 다양한 확장 기능들을 사용할 수 있음&lt;/li&gt;
&lt;li&gt;(2023년 기준) &lt;a href=&#34;https://en.wikipedia.org/wiki/SQL:2023&#34;&gt;&lt;code&gt;SQL:2023(*또는 ISO/IEC 9075*)&lt;/code&gt;&lt;/a&gt;의 필수 기능 177개 중 170 이상을 준수하는, &lt;code&gt;가장 표준을 완벽하게 준수하는 관계형 DB&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;기원&#34; &gt;기원
&lt;span&gt;
    &lt;a href=&#34;#%ea%b8%b0%ec%9b%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PostgreSQL&lt;/code&gt;은 버클리 캘리포니아 대학교에서 작성된 &lt;code&gt;POSTGRE&lt;/code&gt; 패키지로부터 파생됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;postgres-프로젝트&#34; &gt;&lt;code&gt;POSTGRES&lt;/code&gt; 프로젝트
&lt;span&gt;
    &lt;a href=&#34;#postgres-%ed%94%84%eb%a1%9c%ec%a0%9d%ed%8a%b8&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Michael_Stonebraker&#34;&gt;마이클 스톤브레이커&lt;/a&gt; 교수가 주도한 프로젝트로, 1986년 구현이 시작됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POSTGRES&lt;/code&gt;는 &lt;code&gt;INGRES&lt;/code&gt;의 후속으로 1986년 개발되기 시작한 DBMS
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.seas.upenn.edu/~zives/cis650/papers/INGRES.PDF&#34;&gt;&lt;code&gt;INGRES&lt;/code&gt;&lt;/a&gt;: 1975년 개발되기 시작한 &lt;code&gt;관계형 DBMS&lt;/code&gt;로, UNIX 운영체제 상에서 동작하며 쿼리 언어로 &lt;code&gt;QUEL&lt;/code&gt;을 사용(이후 SQL도 지원)
&lt;ul&gt;
&lt;li&gt;참고
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dl.acm.org/doi/pdf/10.1145/1499949.1500029&#34;&gt;INGRES—A relational data base system* - by G. D. HELD, M. R. STONEBRAKER and E. WONG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.seas.upenn.edu/~zives/cis650/papers/INGRES.PDF&#34;&gt;The Design and Implementation of Ingres&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INGRES&lt;/code&gt;의 초기 설계로는 스톤브레이커 교수를 포함한 개발진들이 &lt;strong&gt;추가 및 확장하고 싶은 기능들을 &lt;code&gt;INGRES&lt;/code&gt;에 통합할 수 없어&lt;/strong&gt;, 새로운 데이터베이스 시스템인 &lt;code&gt;POSTGRES&lt;/code&gt;를 구축하게 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POSTGRES&lt;/code&gt;의 목표는 크게 다음과 같음 &lt;a href=&#34;https://dsf.berkeley.edu/papers/ERL-M85-95.pdf&#34;&gt;#&lt;/a&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;복잡한 객체&lt;/code&gt;를 더 원활하게 지원할 것
&lt;ul&gt;
&lt;li&gt;기존의 관계형 데이터베이스가 적합하지 않았던 &lt;code&gt;CAD 시스템&lt;/code&gt;, &lt;code&gt;지리 데이터&lt;/code&gt; 등의  환경에 대한 지원&lt;/li&gt;
&lt;li&gt;즉, 이러한 환경에서 사용되는 &lt;code&gt;지오메트리&lt;/code&gt;(&lt;code&gt;Point&lt;/code&gt;, &lt;code&gt;Polygon&lt;/code&gt;, &amp;hellip;)와 같은 타입의 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터 타입, 연산자 및 접근 방법에 대한 &lt;code&gt;사용자 확장성&lt;/code&gt; 제공
&lt;ul&gt;
&lt;li&gt;이 역시, CAD용 &lt;code&gt;기하학 자료형&lt;/code&gt;이나, 매핑 애플리케이션용 &lt;code&gt;위도/경도&lt;/code&gt;와 같은 &lt;code&gt;자료형&lt;/code&gt;과 &lt;code&gt;연산자&lt;/code&gt;를 DBMS에 &lt;code&gt;추가할 수 있는 기능&lt;/code&gt;을 제공하고, 일부 유형에 적합한 &lt;code&gt;액세스 방법&lt;/code&gt;(ex. &lt;code&gt;Point&lt;/code&gt; -&amp;gt; &lt;code&gt;K-D-B 트리&lt;/code&gt;, &lt;code&gt;Polygon&lt;/code&gt; -&amp;gt; &lt;code&gt;R-트리&lt;/code&gt;) 방법을 추가할 수 있도록 하는 것을 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;활성 데이터베이스&lt;/code&gt;(알림 및 트리거)와 &lt;code&gt;포워드/백워드 체이닝&lt;/code&gt;에 대한 추론을 위한 기능 제공
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;활성 데이터베이스&lt;/code&gt; &lt;a href=&#34;https://dl.acm.org/doi/10.1145/311531.311623&#34;&gt;#&lt;/a&gt;: 데이터베이스 내/외부에서 발생하는 &lt;code&gt;이벤트에 대응&lt;/code&gt;할 수 있는 &lt;code&gt;이벤트-기반 구조&lt;/code&gt;를 포함하는 데이터베이스.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;포워드/백워드 체이닝&lt;/code&gt; &lt;a href=&#34;https://www.geeksforgeeks.org/difference-between-backward-and-forward-chaining/&#34;&gt;#&lt;/a&gt;: 데이터 기반 추론에서, &amp;lsquo;알려진 사실에 규칙을 적용해 나가 목표까지 도달하는 추론 기법&amp;rsquo;(&lt;code&gt;포워드 체이닝&lt;/code&gt;)과 &amp;lsquo;목표에서 시작해 역방향으로 알려진 사실에 도달하는 추론 기법&amp;rsquo;(&lt;code&gt;백워드 체이닝&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;버그 리포트 시스템처럼, 특정 이벤트가 발생시 관리자에게 알림을 보내거나(&lt;code&gt;alerter&lt;/code&gt;) 특정 데이터의 업데이트 발생시 일관성 유지를 위해 업데이트를 전파(&lt;code&gt;trigger&lt;/code&gt;) 할 수 있도록 &lt;code&gt;활성 데이터베이스&lt;/code&gt;와 &lt;code&gt;규칙(rule)&lt;/code&gt;을 지원하는 것
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;규칙&lt;/code&gt;의 경우, 일정한 규칙(ex. 수업 일정 DB에서 교수는 N학점 이상 강의를 개설 및 진행하고 &amp;hellip; 와 같은 규칙)을 따르는 테이블이라면, 복잡한 제약 조건들로 이를 강제하는 것이 아니라, 데이터들을 기반으로 이러한 &lt;code&gt;규칙&lt;/code&gt;을 추론하는 방향으로 구현해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;충돌 복구&lt;/code&gt;를 위한 &lt;code&gt;DBMS 코드 간소화&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;대부분의 DBMS는 &lt;em&gt;작성하기 까다롭고, 희귀한 케이스로 가득하며, 테스트 및 디버깅이 힘든&lt;/em&gt; 충돌 복구 코드들이 존재&lt;/li&gt;
&lt;li&gt;게다가 앞선 목표 중 &lt;code&gt;사용자 정의 접근 기법&lt;/code&gt;을 제공하는 것이 있었으므로, &lt;code&gt;충돌 복구 모델&lt;/code&gt;은 &lt;strong&gt;가능한 간단하고 확장하기 쉬워야 함&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;따라서, &lt;code&gt;로그&lt;/code&gt;를 &lt;code&gt;일반 데이터로 취급&lt;/code&gt;해 &lt;code&gt;복구 코드를 단순화&lt;/code&gt;하고, &lt;code&gt;기록 데이터에 대한 접근&lt;/code&gt;을 &lt;code&gt;지원&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;광디스크, 워크스테이션(여러개의 프로세서로 이뤄진), 커스텀 &lt;code&gt;VLSI 칩&lt;/code&gt; 등의 이점을 취할 수 있는 설계
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;VLSI(초고밀도 집적회로) 칩&lt;/code&gt;: 수십억개의 MOS 트랜지스터를 결합해 단일 칩에 올리는 집적 회로 칩&lt;/li&gt;
&lt;li&gt;워크스테이션의 CPU 자원을 활용할 수 있고, 광디스크와 VLSI 칩을 효과적으로 활용할 수 있는 설계를 조사&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;관계형 모델을 가능한 적게 변경(가급적이면 변경 X)
&lt;ul&gt;
&lt;li&gt;많은 사용자들이 관계형 모델에 익숙해질 것이고, 관계형 모델이 데이터를 단순한 테이블 수준으로 강제하고, 관계형 대수 연산을 통해 테이블을 생성할 수 있는, 이른바 &lt;a href=&#34;https://finance.yahoo.com/news/simplifying-big-data-keyark-allows-122000982.html&#34;&gt;&lt;code&gt;스파르탄 단순성(Spartan Simplicity)&lt;/code&gt;&lt;/a&gt;이라는 이점이 있기 때문&lt;/li&gt;
&lt;li&gt;또한, &lt;em&gt;일반적인 계층 구조부터 CAD 데이터와 같은 복잡한 구조&lt;/em&gt;를 &lt;strong&gt;모두 다룰 수 있는&lt;/strong&gt; &lt;em&gt;&lt;code&gt;크고 복잡한 데이터 모델&lt;/code&gt; 보단&lt;/em&gt;, &lt;code&gt;확장 가능한 작고 단순한 모델&lt;/code&gt;을 &lt;strong&gt;기반으로 시스템&lt;/strong&gt;을 구축해야 한다고 생각&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;왜-postgresql을-써야할까&#34; &gt;왜 &lt;code&gt;PostgreSQL&lt;/code&gt;을 써야할까?
&lt;span&gt;
    &lt;a href=&#34;#%ec%99%9c-postgresql%ec%9d%84-%ec%8d%a8%ec%95%bc%ed%95%a0%ea%b9%8c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id=&#34;장점&#34; &gt;장점
&lt;span&gt;
    &lt;a href=&#34;#%ec%9e%a5%ec%a0%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;함수, 데이터 유형, 언어 등을 추가할 수 있는 &lt;code&gt;확장성이 높음&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;구조화되지 않은 데이터 유형 지원&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;XML&lt;/code&gt;, &lt;code&gt;H-Store(키-값 쌍으로 데이터를 저장하는 자료형)&lt;/code&gt;와 같은 다양한 데이터 유형을 지원하며, NoSQL기능을 지원.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;교착 상태가 거의 발생하지 않고 동시 처리가 가능하며 트랜잭션 속도가 빠른 &lt;code&gt;MVCC&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MVCC(Multi-Version Concurrency Control, 다중버전 동시성 제어)&lt;/code&gt;: 동시 접근이 가능한 환경에서, 원본의 스냅샷과 변경중인 데이터를 동시에 유지해 별도의 락이 필요하지 않아 더 빠르게 동작하는 동시성 제어 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;고가용성&lt;/code&gt; 및 &lt;code&gt;서버 오류 복구&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;데이터 암호화, SSL 인증서, 고급 인증 방법과 같은 &lt;code&gt;고급 보안 기능&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;활발한 오픈소스 커뮤니티&lt;/code&gt;가 &lt;code&gt;지속적으로 솔루션을 개선하고 업데이트&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;이외의 추가적인 장점은 &lt;a href=&#34;https://www.postgresql.org/about/&#34;&gt;PostgreSQL: About&lt;/a&gt;의 &lt;code&gt;Why use PostgreSQL?&lt;/code&gt;에 나와 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;단점&#34; &gt;단점
&lt;span&gt;
    &lt;a href=&#34;#%eb%8b%a8%ec%a0%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;SQL Server 및 MySQL과 같은 &lt;code&gt;다른 RDBMS보다 성능이 느림&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;다만 이는 경우에 따라 다름&lt;/li&gt;
&lt;li&gt;일반적으로 읽기 작업만 수행할 경우, MySQL/MariaDB 대비 PostgreSQL이 느리다고 알려져 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;호환성에 더 주력&lt;/code&gt;, &lt;em&gt;속도 향상을 위해서는&lt;/em&gt; &lt;code&gt;추가 작업&lt;/code&gt;이 필요함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MVCC&lt;/code&gt; 모델로 인해 발생하는 여러 문제점 &lt;a href=&#34;https://www.cs.cmu.edu/~pavlo/blog/2023/04/the-part-of-postgresql-we-hate-the-most.html&#34;&gt;참고 1 - The Part of PostgreSQL We Hate the Most // Blog // Andy Pavlo - Carnegie Mellon University&lt;/a&gt; &lt;a href=&#34;https://techblog.woowahan.com/9478/&#34;&gt;참고 2 - PostgreSQL Vacuum에 대한 거의 모든 것 | 우아한형제들 기술블로그&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;쿼리가 한 튜플을 업데이트하면, DBMS는 모든 컬럼을 새로운 버전에 복사함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dead Tuple&lt;/code&gt;(기존 원본 데이터를 저장하여, 어디에도 참조되지 않는 Tuple)을 정리하는 &lt;code&gt;Vaccum&lt;/code&gt;(Java로 비유하자면 &lt;code&gt;GC&lt;/code&gt;)이 워크로드의 &lt;code&gt;write&lt;/code&gt; 작업 속도를 따라잡지 못할 경우 쿼리 성능 저하(&lt;code&gt;DBMS&lt;/code&gt;는 &lt;code&gt;Dead Tuple&lt;/code&gt;을 메모리에 로드해야 하므로), &lt;code&gt;Dead Tuple&lt;/code&gt;에 의한 부실한 쿼리 플랜 최적화 등이 발생할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;mysql---postgresql로-마이그레이션-하기&#34; &gt;MySQL -&amp;gt; PostgreSQL로 마이그레이션 하기
&lt;span&gt;
    &lt;a href=&#34;#mysql---postgresql%eb%a1%9c-%eb%a7%88%ec%9d%b4%ea%b7%b8%eb%a0%88%ec%9d%b4%ec%85%98-%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PostgreSQL&lt;/code&gt; 생태계에는 다른 데이터베이스에서 자료를 가져올 수 있는 컨버터 툴들이 존재
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL#MySQL&#34;&gt;Converting from other Databases to PostgreSQL - PostgreSQL wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;의 경우 &lt;a href=&#34;https://github.com/dimitri/pgloader&#34;&gt;pgloader&lt;/a&gt;, &lt;a href=&#34;https://pypi.org/project/pg-chameleon/&#34;&gt;pg-chameleon&lt;/a&gt;,  &lt;a href=&#34;https://github.com/lanyrd/mysql-postgresql-converter&#34;&gt;lanyrd/mysql-postgresql-converter&lt;/a&gt;, &lt;a href=&#34;https://github.com/philipsoutham/py-mysql2pgsql&#34;&gt;philipsoutham/py-mysql2pgsql&lt;/a&gt; 등 다양한 툴들이 존재함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하지만 이들을 본인의 경우 사용하기 쉽지 않았음
&lt;ul&gt;
&lt;li&gt;대부분의 툴들이 Linux 환경에서나 원활하게 동작하기 때문(특히, &lt;code&gt;pgloader&lt;/code&gt;와 &lt;code&gt;pg-chameleon&lt;/code&gt;은 Windows를 사실상 지원 X)&lt;/li&gt;
&lt;li&gt;또한, &lt;code&gt;mysqldump&lt;/code&gt;를 통해 MySQL 데이터를 추출한 뒤, &lt;code&gt;pg_store&lt;/code&gt;를 통해 복구하는 방법을 시도하는 사람들도 있었지만 두 DBMS의 규격이 달라 실패&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;따라서 다음과 같이 &lt;code&gt;DBeaver&lt;/code&gt;를 활용해 자료를 CSV로 변환하고, 이를 PostgreSQL에서 import하는 방식으로 마이그레이션을 진행
&lt;ul&gt;
&lt;li&gt;먼저, &lt;code&gt;CSV 파일&lt;/code&gt;로 MySQL 테이블을 export함
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;mysql-export.png&#34; alt=&#34;mysql-export.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후, &lt;code&gt;PostgreSQL&lt;/code&gt; DB의 &lt;code&gt;Schemas&amp;gt;Tables&lt;/code&gt;에서 데이터 가져오기를 수행
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;postgresql-import.png&#34; alt=&#34;postgresql-import.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이때, 사양의 차이로 &lt;code&gt;MySQL&lt;/code&gt;의 &lt;code&gt;지오메트리 타입&lt;/code&gt;이 온전히 옮겨지는 것이 아닌, &lt;code&gt;WKT&lt;/code&gt;의 형태로 옮겨짐
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;point-to-varchar.png&#34; alt=&#34;point-to-varchar.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;컬럼 값을 확인해보면, 아래와 같이 &lt;code&gt;WKT&lt;/code&gt; 포맷으로 varchar 타입의 문자열들이 기록되어 있음을 알 수 있음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;point-to-varchar2.png&#34; alt=&#34;point-to-varchar2.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이를 &lt;code&gt;지오메트리 타입&lt;/code&gt;으로 변환하는 과정을 수행해야 함
&lt;ul&gt;
&lt;li&gt;먼저, 지오메트리 타입 컬럼을 테이블에 추가하는 &lt;a href=&#34;https://postgis.net/docs/AddGeometryColumn.html&#34;&gt;&lt;code&gt;AddGeometryColumn&lt;/code&gt;&lt;/a&gt; 함수를 호출&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;`AddGeometryColumn(varchar table_name, varchar column_name, integer srid, varchar type, integer dimension, boolean use_typmod=true) 함수를 호출
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; addgeometrycolumn(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;geotesttable&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;geotesttable&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;location_geom&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POINT&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;이후, &lt;code&gt;update geotesttable set location_geom = ST_GeomFromText(location);&lt;/code&gt; 문을 통해 기존 컬럼의 &lt;code&gt;WKT&lt;/code&gt;를 기반으로 &lt;code&gt;지오메트리&lt;/code&gt; 데이터를 생성해 컬럼 갱신&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;postgis의-공간-인덱스-및-공간-연산&#34; &gt;PostGIS의 공간 인덱스 및 공간 연산
&lt;span&gt;
    &lt;a href=&#34;#postgis%ec%9d%98-%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4-%eb%b0%8f-%ea%b3%b5%ea%b0%84-%ec%97%b0%ec%82%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;공간 연산&lt;/code&gt;을 수행해보기 전, 먼저 &lt;code&gt;공간 인덱스&lt;/code&gt;를 생성하여 &lt;code&gt;SELECT 쿼리&lt;/code&gt;의 속도를 개선할 수 있도록 해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;공간-인덱스-생성하기&#34; &gt;공간 인덱스 생성하기
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4-%ec%83%9d%ec%84%b1%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://postgis.net/documentation/faq/spatial-indexes/&#34;&gt;참고&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostGIS&lt;/code&gt;에서 &lt;code&gt;공간 인덱스&lt;/code&gt;를 생성하는 구문은 다음과 같음
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CREATE INDEX mytable_geom_x ON mytable USING GIST (geom)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CREATE SPATIAL INDEX&lt;/code&gt; 구문을 사용하던 &lt;code&gt;MySQL&lt;/code&gt;과 다르게, &lt;code&gt;PostGIS&lt;/code&gt;에서는 &lt;code&gt;USING GIST&lt;/code&gt; 구문을 사용함
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;USING GIST&lt;/code&gt;: 인덱스에서 &lt;code&gt;GiST(Generalized Search Tree)&lt;/code&gt; 구조를 사용할 것을 의미
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GiST(Generalized Search Tree)&lt;/code&gt;: 단순한, 일반적인 자료형 뿐만 아니라, &lt;em&gt;지리 정보 시스템, 멀티미디어 시스템&lt;/em&gt; 등 &lt;code&gt;다양한 환경&lt;/code&gt;에서 사용되는 &lt;code&gt;자료 유형&lt;/code&gt;을 지원하기 위해 &amp;lsquo;&lt;strong&gt;확장 가능한&lt;/strong&gt; &lt;code&gt;쿼리&lt;/code&gt; 및 &lt;code&gt;데이터 유형 집합&lt;/code&gt;&amp;lsquo;을 지원하는 &lt;code&gt;인덱스 구조&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;B+ 트리&lt;/code&gt;, &lt;code&gt;R-트리&lt;/code&gt; 등 다양한 트리 구조를 지원함&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cs.cmu.edu/~15721-f24/papers/GiST.pdf&#34;&gt;참고1&lt;/a&gt;, &lt;a href=&#34;https://dsf.berkeley.edu/papers/UW-CS-TR-1274.pdf&#34;&gt;참고2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 키워드를 통해 인덱스를 설정할 경우, &lt;code&gt;기본 인덱스&lt;/code&gt;가 &lt;code&gt;R-트리&lt;/code&gt;로 설정되며, 해당 키워드를 사용하지 않을 경우 &lt;code&gt;표준 PostgreSQL B-트리&lt;/code&gt; 인덱스를 생성함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;공간-연산-사용하기&#34; &gt;공간 연산 사용하기
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%97%b0%ec%82%b0-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PostGIS&lt;/code&gt;와 &lt;code&gt;공간 인덱스&lt;/code&gt;의 성능을 확인하기 위해, 다음 두 가지 케이스를 비교해보려 함
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;공간 인덱스&lt;/code&gt;를 사용해 &lt;code&gt;사전 필터링&lt;/code&gt;을 거친 쿼리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;공간 인덱스&lt;/code&gt;를 사용하지 않는 함수를 사용하는 쿼리&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;참고로 &lt;code&gt;공간 인덱스를 사용하는 함수&lt;/code&gt;는 다음과 같음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;functions-which-use-spatial-index.png&#34; alt=&#34;functions-which-use-spatial-index.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;예시
&lt;ul&gt;
&lt;li&gt;한 점(&lt;code&gt;POINT(128.593317 35.865807)&lt;/code&gt;)으로 부터 5km 떨어진 점들 검색하기
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;약 237만개의 POINT가 기록된 테이블에서 이를 검색하고자 함&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;먼저, 공간 인덱스를 사용하지 않는 &lt;code&gt;ST_DistanceSphere&lt;/code&gt; 함수를 사용해봄&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이 경우, 쿼리는 다음과 같음
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; geotesttable &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; ST_DistanceSphere(ST_GeomFromText(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POINT(128.593317 35.865807)&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;), location_geom) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;위 쿼리에 대해 &lt;code&gt;EXPLAIN&lt;/code&gt;문을 사용해 실행 계획을 살펴보면 &lt;code&gt;공간 인덱스&lt;/code&gt;가 &lt;code&gt;활용되지 않으며&lt;/code&gt;(&lt;code&gt;Seq Scan&lt;/code&gt;), 많은 양의 row들을 살펴봄을 알 수 있음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;query-plan-with-distance-sphere.png&#34; alt=&#34;query-plan-with-distance-sphere.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;또한, 쿼리문을 수행하고 데이터를 가져오는데 약 3초정도 소요됨
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-with-distance-sphere.png&#34; alt=&#34;time-taken-by-query-with-distance-sphere.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-with-distance-sphere2.png&#34; alt=&#34;time-taken-by-query-with-distance-sphere2.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;반면, &lt;code&gt;ST_DWithin(g1, g2, distance)&lt;/code&gt; 함수를 사용할 경우 &lt;code&gt;공간 인덱스를 사용&lt;/code&gt;해 더 빠르게 탐색이 이뤄짐&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ST_DWithin(g1, g2, distance)&lt;/code&gt;는 주어진 두 &lt;code&gt;geometry&lt;/code&gt;(또는 &lt;code&gt;geography&lt;/code&gt;) g1, g2 사이의 거리가 &lt;code&gt;distance&lt;/code&gt;이내인지 &lt;code&gt;여부를 반환&lt;/code&gt;하는 함수
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;추가하자면, &lt;code&gt;ST_DWithin()&lt;/code&gt;에 g1, g2로 &lt;code&gt;geography&lt;/code&gt; 인자가 주어질 경우, &lt;code&gt;지구타원형&lt;/code&gt; 형태를 기준으로 하게 됨
&lt;ul&gt;
&lt;li&gt;따라서 &lt;code&gt;ST_DistanceSphere&lt;/code&gt; 와 동일한 기준 상에서 검색하려면 4번째 선택 인자인 &lt;code&gt;use_spheroid&lt;/code&gt;을 false로 해주어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 경우, 쿼리는 다음과 같음
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; geotesttable &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; ST_DWITHIN(location_geom::geography, ST_GeomFromText(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POINT(128.593317 35.865807)&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;)::geography , &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;이때, 지오메트리 자료형인 &lt;code&gt;location_geom&lt;/code&gt;과 &lt;code&gt;ST_GeomFromText&lt;/code&gt;의 결과값을 &lt;a href=&#34;https://postgis.net/workshops/postgis-intro/geography.html&#34;&gt;&lt;code&gt;geography&lt;/code&gt;&lt;/a&gt; 타입으로 캐스팅 하고 있음을 알 수 있음&lt;/li&gt;
&lt;li&gt;이는 &lt;code&gt;ST_DWITHIN&lt;/code&gt; 함수가 &lt;code&gt;geometry&lt;/code&gt; 값 2개를 인자로 받을 경우, &lt;code&gt;distance&lt;/code&gt;의 단위가 &lt;code&gt;SRID:4326&lt;/code&gt;의 단위인 &lt;code&gt;도(degree)&lt;/code&gt;로 바뀌어버리기 때문에, 미터를 사용하려면 &lt;code&gt;geography&lt;/code&gt; 값 2개를 인자로 주어야 하기 때문임
&lt;ul&gt;
&lt;li&gt;그리고 이렇게 할 경우, &lt;code&gt;공간 인덱스&lt;/code&gt; 역시 하나 더 만들어 주어야 함&lt;/li&gt;
&lt;li&gt;위에서 만들었던 &lt;code&gt;공간 인덱스&lt;/code&gt;는 &lt;code&gt;geometry&lt;/code&gt; 타입인 &lt;code&gt;location_geom&lt;/code&gt;을 기준으로 했기 때문에, &lt;code&gt;geography&lt;/code&gt;로 캐스팅하여 &lt;code&gt;DWITHIN&lt;/code&gt; 함수를 호출할 경우 인덱스를 사용하지 못하기 때문&lt;/li&gt;
&lt;li&gt;따라서 아래 구문을 통해 &lt;code&gt;geography&lt;/code&gt; 형태의 &lt;code&gt;인덱스&lt;/code&gt;를 하나 더 만들어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;INDEX&lt;/span&gt; location_idx_geo  &lt;span style=&#34;color:#66d9ef&#34;&gt;ON&lt;/span&gt; geotesttable  &lt;span style=&#34;color:#66d9ef&#34;&gt;USING&lt;/span&gt; GIST ((location_geom::geography));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;위 쿼리에 대해 &lt;code&gt;EXPLAIN&lt;/code&gt;문을 사용해 실행 계획을 살펴보면, &lt;code&gt;공간 인덱스가 잘 활용되고 있으며&lt;/code&gt;(&lt;code&gt;Index Scan&lt;/code&gt;), 탐색하는 row 갯수도 훨씬 줄어들었음을 알 수 있음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;query-plan-with-dwithin.png&#34; alt=&#34;query-plan-with-dwithin.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;또한, 쿼리 수행도 총 0.4초가량으로 빠르게 이뤄짐
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-with-dwithin.png&#34; alt=&#34;time-taken-by-query-with-dwithin.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-with-dwithin2.png&#34; alt=&#34;time-taken-by-query-with-dwithin2.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;참고&#34; &gt;참고
&lt;span&gt;
    &lt;a href=&#34;#%ec%b0%b8%ea%b3%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dsf.berkeley.edu/papers/ERL-M85-95.pdf&#34;&gt;THE DESIGN OF POSTGRES - Michael Stonebraker and Lawrence A. Rowe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cloud.google.com/learn/postgresql-vs-sql&#34;&gt;PostgreSQL과 SQL Server 비교: 차이점은 무엇인가요? | Google Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cs.cmu.edu/~pavlo/blog/2023/04/the-part-of-postgresql-we-hate-the-most.html&#34;&gt;The Part of PostgreSQL We Hate the Most // Blog // Andy Pavlo - Carnegie Mellon University&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://postgis.net/workshops/postgis-intro/indexing.html&#34;&gt;15. Spatial Indexing — Introduction to PostGIS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://postgis.net/workshops/postgis-intro/geography.html&#34;&gt;18. Geography — Introduction to PostGIS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://postgis.net/docs/ST_DWithin.html&#34;&gt;ST_DWithin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://postgis.net/docs/ST_DistanceSphere.html&#34;&gt;ST_DistanceSphere&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.postgresql.org/docs/9.1/textsearch-indexes.html&#34;&gt;PostgreSQL: Documentation: 9.1: GiST and GIN Index Types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>[DB] 공간 인덱스 알아보기 &#43; 쿼리 성능 개선해보기 (w. SRS, EPSG, SRID)</title>
      <link>https://cloudsoswift.github.io/post/develop/database/spatial-index/</link>
      <pubDate>Wed, 11 Dec 2024 08:12:35 +0900</pubDate>
      
      <guid>https://cloudsoswift.github.io/post/develop/database/spatial-index/</guid>
      <description>&lt;h1 id=&#34;서론&#34; &gt;서론
&lt;span&gt;
    &lt;a href=&#34;#%ec%84%9c%eb%a1%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;hr&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/orm712/CS-712&#34;&gt;CS 스터디&lt;/a&gt;에서 12월 12일 발표 예정인 &lt;a href=&#34;https://github.com/orm712/CS-712/blob/main/04-DATABASE/18_Spatial_Index/Readme.md&#34;&gt;공간 인덱스&lt;/a&gt;에 대해 정리하고, 이를 실습해본 문서를 블로그에 공유하고자 한다.&lt;/p&gt;
&lt;h1 id=&#34;공간-인덱스spatial-index란&#34; &gt;&lt;code&gt;공간 인덱스(Spatial Index)&lt;/code&gt;란?
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4spatial-index%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;공간 데이터(Spatial Data)&lt;/code&gt;를 지원하는 데이터베이스에서 &lt;code&gt;공간 쿼리(Spatial Query)&lt;/code&gt;를 &lt;code&gt;최적화&lt;/code&gt;하기 위해 사용되는 &lt;code&gt;인덱스&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;기존의 &lt;code&gt;인덱스&lt;/code&gt;는 데이터들을 &lt;code&gt;선형 순서&lt;/code&gt;로 정렬해 조회 속도를 최적화하는 반면, &lt;code&gt;2차원/3차원 공간 상의 데이터&lt;/code&gt;들을 정렬하기 위해 &lt;code&gt;R-Tree&lt;/code&gt;와 같은 자료구조를 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;공간-데이터spatial-data&#34; &gt;&lt;code&gt;공간 데이터(Spatial Data)&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0spatial-data&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;2차원&lt;/code&gt; 또는 &lt;code&gt;3차원 공간&lt;/code&gt;에 위치할 수 있는 &lt;code&gt;공간&lt;/code&gt; 또는 &lt;code&gt;지리적 참조&lt;/code&gt; 형태의 데이터&lt;/li&gt;
&lt;li&gt;주로 &lt;code&gt;점&lt;/code&gt;, &lt;code&gt;선&lt;/code&gt;, &lt;code&gt;다각형&lt;/code&gt;과 같은 기하학적 객체들을 말함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;지리 공간 데이터&lt;/code&gt;, &lt;code&gt;위치 기반 서비스&lt;/code&gt; 등에 대한 표준을 개발 및 유지하는 기구인 &lt;a href=&#34;https://www.ogc.org/&#34;&gt;&lt;code&gt;개방형 공간 정보 컨소시엄(OGC)&lt;/code&gt;&lt;/a&gt;에서는 &lt;a href=&#34;https://portal.ogc.org/files/?artifact_id=829&#34;&gt;&lt;code&gt;Simple Feature&lt;/code&gt;&lt;/a&gt;와 2020년 이를 대체하기 위해 발표된 &lt;a href=&#34;https://docs.ogc.org/as/17-087r13/17-087r13.html&#34;&gt;&lt;code&gt;Feature Model&lt;/code&gt;&lt;/a&gt; 등을 꾸준히 개발 중
&lt;ul&gt;
&lt;li&gt;여러 DBMS는 이를 기반으로 한 &lt;code&gt;공간 기능&lt;/code&gt;을 제공 중&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;에서도 OGC의 &lt;code&gt;기하 도형 모델(OpenGIS Geometry Model)&lt;/code&gt;에 대응되는 &lt;code&gt;GEOMETRY&lt;/code&gt;, &lt;code&gt;POINT&lt;/code&gt;, &lt;code&gt;LINESTRING&lt;/code&gt; 등 다양한 타입을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;공간-참조-시스템srs-조사추가필요&#34; &gt;공간 참조 시스템(SRS) #조사추가필요
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%b0%b8%ec%a1%b0-%ec%8b%9c%ec%8a%a4%ed%85%9csrs-%ec%a1%b0%ec%82%ac%ec%b6%94%ea%b0%80%ed%95%84%ec%9a%94&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POINT&lt;/code&gt;, &lt;code&gt;LINESTRING&lt;/code&gt;과 같은 모든 지오메트리 객체가 존재할 수 있는 공간&lt;/li&gt;
&lt;li&gt;하나의 지오메트리 객체는 오직 하나의 &lt;code&gt;공간 참조 시스템&lt;/code&gt;에만 존재할 수 있음
&lt;ul&gt;
&lt;li&gt;이는 각 &lt;code&gt;공간 참조 시스템&lt;/code&gt;마다 좌표가 존재할 수 있는 표면이 다를 수 있기 때문&lt;/li&gt;
&lt;li&gt;예를 들어, &lt;code&gt;A&lt;/code&gt; SRS는 &lt;code&gt;구형&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt; SRS는 &lt;code&gt;평면&lt;/code&gt;이라고 하면 같은 좌표라도 각 SRS마다 다른 위치에 존재하게 됨&lt;/li&gt;
&lt;li&gt;따라서 두 지오메트릭 객체가 동일하기 위해서는 좌표 뿐만 아니라 존재하는 SRS도 동일해야 함
&lt;ul&gt;
&lt;li&gt;이 때문에 보통 다른 &lt;code&gt;SIRD&lt;/code&gt;를 갖는 지오메트리 값 간에는 어떤 연산도 이뤄지지 않고 거부됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;각 &lt;code&gt;SRS&lt;/code&gt;는 고유한 &lt;code&gt;공간 참조 식별자(SRID)&lt;/code&gt;가 존재하며, 이를 통해 어떤 &lt;code&gt;SRS&lt;/code&gt;에 속해있는지 구분함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SRID&lt;/code&gt;와 이에 해당하는 &lt;code&gt;SRS&lt;/code&gt;는 &lt;code&gt;EPSG(유럽 석유 조사 그룹)&lt;/code&gt;에서 제작 및 운영하고 있는 &lt;a href=&#34;https://epsg.org/home.html&#34;&gt;&lt;code&gt;EPSG의 좌표계 식별 데이터셋&lt;/code&gt;&lt;/a&gt;라는 사실상 표준이 정해져 있음&lt;/li&gt;
&lt;li&gt;주로 사용되는 &lt;code&gt;SRS&lt;/code&gt;는 &lt;code&gt;WGS 84(World Geodetic System 1984)&lt;/code&gt;라고 불리는 &lt;code&gt;SRID 4326&lt;/code&gt;, &lt;code&gt;WGS 84&lt;/code&gt;/&lt;code&gt;슈도 메르카토르&lt;/code&gt; 라고도 불리는 &lt;code&gt;SRID 3857&lt;/code&gt;가 주로 사용됨
&lt;ul&gt;
&lt;li&gt;둘의 가장 큰 차이는 &lt;code&gt;3차원 구체를 기반&lt;/code&gt;으로 하는지(&lt;code&gt;4326&lt;/code&gt;), &lt;code&gt;2차원 평면&lt;/code&gt;을 기반으로 하는지(&lt;code&gt;3857&lt;/code&gt;)가 차이&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;epsg4326---wgs-84httpsepsgio4326&#34; &gt;EPSG:4326 - WGS 84&lt;a href=&#34;https://epsg.io/4326&#34;&gt;#&lt;/a&gt;
&lt;span&gt;
    &lt;a href=&#34;#epsg4326---wgs-84httpsepsgio4326&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;경도(longitude)&lt;/code&gt;, &lt;code&gt;위도(latitude)&lt;/code&gt;를 통해 &lt;code&gt;3차원 타원 표면&lt;/code&gt;에서의 좌표를 표현하는 좌표계&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GPS&lt;/code&gt;, &lt;code&gt;Google Earth&lt;/code&gt; 등에서 사용됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;각도(Degree)&lt;/code&gt;를 &lt;code&gt;단위&lt;/code&gt;로 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;epsg3857---wgs-84--pseudo-mercator--spherical-mercatorhttpsepsgio3857&#34; &gt;EPSG:3857 - WGS 84 / Pseudo-Mercator / Spherical Mercator&lt;a href=&#34;https://epsg.io/3857&#34;&gt;#&lt;/a&gt;
&lt;span&gt;
    &lt;a href=&#34;#epsg3857---wgs-84--pseudo-mercator--spherical-mercatorhttpsepsgio3857&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt; 좌표를 통해 &lt;code&gt;WGS 84&lt;/code&gt; 타원체 데이텀(좌표 축의 원점이 되는 기준점)에 &lt;code&gt;메르카토르 투영&lt;/code&gt;을 적용한 좌표계
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;메르카토르 투영&lt;/code&gt;의 일종이기 때문에, 고위도 지역으로 갈수록 왜곡이 심해진다는 특징이 여전히 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google Maps&lt;/code&gt;, &lt;code&gt;OpenStreeMap&lt;/code&gt; 등 웹 지도 도구들에서 사용됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;미터(metres)&lt;/code&gt;를 단위로 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;mysql의-공간-데이터-타입&#34; &gt;MySQL의 공간 데이터 타입
&lt;span&gt;
    &lt;a href=&#34;#mysql%ec%9d%98-%ea%b3%b5%ea%b0%84-%eb%8d%b0%ec%9d%b4%ed%84%b0-%ed%83%80%ec%9e%85&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;에는 크게 &lt;code&gt;단일 지오메트리 값&lt;/code&gt;을 저장할 수 있는 자료형과 &lt;code&gt;지오메트리 값의 집합&lt;/code&gt;을 저장할 수 있는 자료형으로 나뉨&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;wkb와-wkt&#34; &gt;WKB와 WKT
&lt;span&gt;
    &lt;a href=&#34;#wkb%ec%99%80-wkt&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OpenGIS&lt;/code&gt;에서는 &lt;code&gt;기하학적 객체&lt;/code&gt;의 표현을 위해 &lt;code&gt;WKT(Well-Known Text)&lt;/code&gt; 포맷과 &lt;code&gt;WKB(Well-Known Binary)&lt;/code&gt; 포맷을 사용
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;에서는 내부적으로 지오메트리 값을 WKT, WKB가 아닌 다른 포맷을 사용해 저장
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WKB&lt;/code&gt;와 유사하지만 앞의 4바이트가 &lt;code&gt;SRID&lt;/code&gt;를 나타냄
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SRID(공간 참조 식별자)&lt;/code&gt;:  지오메트리 값이 어떤 &lt;code&gt;공간(공간 참조 시스템, SRS)&lt;/code&gt;을 기준으로 하는지 구분하는 식별자. 다른 &lt;code&gt;SIRD&lt;/code&gt;를 갖는 지오메트리 값 간에는 어떤 연산도 이뤄지지 않고 거부됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;wktwell-known-text&#34; &gt;WKT(Well-Known Text)
&lt;span&gt;
    &lt;a href=&#34;#wktwell-known-text&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;지오메트리 값을 &lt;code&gt;ASCII&lt;/code&gt; 형태로 교환하기 위해 설계됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OpenGIS&lt;/code&gt; 사양에서는 &lt;code&gt;WKT&lt;/code&gt;값 작성을 위한 &lt;code&gt;배커스-나우르&lt;/code&gt; 문법을 제공&lt;/li&gt;
&lt;li&gt;자료형에 따라 필요한 점의 갯수는 다르지만 X-Y 좌표 값을 &lt;code&gt;(X Y)&lt;/code&gt; 형태로, 즉 쉼표가 아닌 공백을 통해 구분하는 문법을 공통적으로 사용함
&lt;ul&gt;
&lt;li&gt;예시
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Point&lt;/code&gt; - &lt;code&gt;POINT(15 20)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LINESTRING&lt;/code&gt; - &lt;code&gt;LINESTRING(0 0, 10 10, 20 25, 50 60)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MySQL에는 WKT 형태의 문자열로부터 지오메트리 값을 만들어내는 &lt;code&gt;ST_타입FromText&lt;/code&gt; 함수들이 존재 &lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/gis-wkt-functions.html&#34;&gt;#&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;예시
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POINT&lt;/code&gt; - &lt;code&gt;ST_PointFromText&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEOMERTY&lt;/code&gt; - &lt;code&gt;ST_GeomFromText&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;wkbwell-known-binary&#34; &gt;WKB(Well-Known Binary)
&lt;span&gt;
    &lt;a href=&#34;#wkbwell-known-binary&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;지오메트리 WKB 정보&lt;/code&gt;를 담고있는 &lt;code&gt;BLOB&lt;/code&gt; 형태의 &lt;code&gt;이진 스트림&lt;/code&gt; 형태로 지오메트리 값을 교환하기 위해 사용됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WKB&lt;/code&gt;는 1바이트의 &lt;code&gt;unsigned Integer&lt;/code&gt;(&lt;code&gt;byte order&lt;/code&gt;), 4바이트의 &lt;code&gt;unsigned Integer&lt;/code&gt;(&lt;code&gt;WKB type&lt;/code&gt;), 8바이트의 &lt;code&gt;배정밀도(double precision) 숫자 값&lt;/code&gt;(&lt;code&gt;X, Y 좌표&lt;/code&gt;)들을 사용
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;byte order&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;0일 경우 &lt;code&gt;빅 엔디안&lt;/code&gt;(&lt;code&gt;작은 주소&lt;/code&gt;에서 데이터의 &lt;code&gt;높은 바이트(MSB)&lt;/code&gt;부터 저장하는 방법)
&lt;ul&gt;
&lt;li&gt;만약 &lt;code&gt;0x12345678&lt;/code&gt;을 저장한다면, 앞에서 부터 &lt;code&gt;0x12&lt;/code&gt; / &lt;code&gt;0x34&lt;/code&gt; / &lt;code&gt;0x56&lt;/code&gt; / &lt;code&gt;0x78&lt;/code&gt;을 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;1일 경우 &lt;code&gt;리틀 엔디안&lt;/code&gt;(&lt;code&gt;작은 주소&lt;/code&gt;에서 데이터의 &lt;code&gt;낮은 바이트(LSB)&lt;/code&gt;부터 저장하는 방법)
&lt;ul&gt;
&lt;li&gt;만약 &lt;code&gt;0x12345678&lt;/code&gt;을 저장한다면, 앞에서 부터 &lt;code&gt;0x78&lt;/code&gt; / &lt;code&gt;0x56&lt;/code&gt; / &lt;code&gt;0x34&lt;/code&gt; / &lt;code&gt;0x12&lt;/code&gt;를 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WKB type&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;어떤 지오메트리 유형인지 나타내는 값&lt;/li&gt;
&lt;li&gt;MySQL의 경우 1부터 7까지 각각 &lt;code&gt;Point&lt;/code&gt;, &lt;code&gt;LineString&lt;/code&gt;, &lt;code&gt;Polygon&lt;/code&gt;, &lt;code&gt;MultiPoint&lt;/code&gt;, &lt;code&gt;MultiLineString&lt;/code&gt;, &lt;code&gt;MultiPolygon&lt;/code&gt;, &lt;code&gt;GeometryCollection&lt;/code&gt; 에 대응 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;예시
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POINT(1 -1)&lt;/code&gt;에 대응되는 WKB는 다음 2개의 16진수로 표현되는 21바이트 시퀀스
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0101000000000000000000F03F000000000000F0BF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;이는 &lt;code&gt;01&lt;/code&gt; / &lt;code&gt;01000000&lt;/code&gt; / &lt;code&gt;000000000000F03F&lt;/code&gt; / &lt;code&gt;000000000000F0BF&lt;/code&gt;로 나누어 볼 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;단일-지오메트리-값-자료형&#34; &gt;단일 지오메트리 값 자료형
&lt;span&gt;
    &lt;a href=&#34;#%eb%8b%a8%ec%9d%bc-%ec%a7%80%ec%98%a4%eb%a9%94%ed%8a%b8%eb%a6%ac-%ea%b0%92-%ec%9e%90%eb%a3%8c%ed%98%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GEOMETRY&lt;/code&gt;는 어떤 유형의 지오메트리 값이든 저장할 수 있으며, 나머지 단일 값 유형은 특정 도형의 유형으로 값을 제한함&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;geometry&#34; &gt;GEOMETRY
&lt;span&gt;
    &lt;a href=&#34;#geometry&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;모든 지오메트리 클래스(타입)의 &lt;code&gt;루트 클래스&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;추상 클래스&lt;/code&gt;(인스턴스화 할 수 없음)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEOMETRY&lt;/code&gt;의 하위 클래스들은 &lt;code&gt;GEOMETRY&lt;/code&gt;가 갖는 여러 속성 값들을 갖고있으며, 특정 서브클래스에는 각각 고유한 프로퍼티가 있을 수 있음&lt;/li&gt;
&lt;li&gt;속성 값
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;각 지오메트리 값은 지오메트리 클래스 중 &lt;code&gt;인스턴스화 가능한 클래스&lt;/code&gt; 중 하나에 속해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SRID&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;해당 지오메트리 값의 &lt;code&gt;공간 참조 식별자&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;지오메트리 값과 연관된 &lt;code&gt;공간 참조 시스템(SRS)&lt;/code&gt;을 식별&lt;/li&gt;
&lt;li&gt;MySQL에서 SRID는 0부터 $2^{32} -1$ 사이이며, 지정되지 않을 경우 기본값은 0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;coordinates&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;공간 참조 시스템&lt;/code&gt;상의 좌표 값으로, &lt;code&gt;배정밀도(8바이트)&lt;/code&gt; 숫자로 표현됨&lt;/li&gt;
&lt;li&gt;비어있지 않은 지오메트리는 &lt;code&gt;적어도 한 쌍&lt;/code&gt;의 &lt;code&gt;(X, Y) 좌표가 포함&lt;/code&gt;되어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interior&lt;/code&gt;, &lt;code&gt;boundary&lt;/code&gt;, &lt;code&gt;exterior&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;interior&lt;/code&gt;는 지오메트리가 차지하는 공간, &lt;code&gt;exterior&lt;/code&gt;는 지오메트리가 차지하지 않는 모든 공간, &lt;code&gt;boundary&lt;/code&gt;는 &lt;code&gt;interior&lt;/code&gt;와 &lt;code&gt;exterior&lt;/code&gt; 사이의 경계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MBR(최소 경계 사각형, Minimum Bounding Rectangle)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;최소 및 최대 (X, Y) 좌표로 구성된 경계 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;simple&lt;/code&gt; / &lt;code&gt;nonsimple&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LineString&lt;/code&gt;, &lt;code&gt;MultiPoint&lt;/code&gt;, &lt;code&gt;MultiLineString&lt;/code&gt;유형은 &lt;code&gt;simple&lt;/code&gt;이거나 &lt;code&gt;nonsimple&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;closed&lt;/code&gt; / &lt;code&gt;not closed&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LineString&lt;/code&gt;, &lt;code&gt;MultiLineString&lt;/code&gt; 유형은 &lt;code&gt;closed&lt;/code&gt;이거나, &lt;code&gt;not closed&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;empty&lt;/code&gt; / &lt;code&gt;nonempty&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;지오메트리에 점이 하나도 존재하지 않는 경우 &lt;code&gt;empty&lt;/code&gt;, 그렇지 않은 경우 &lt;code&gt;nonempty&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dimension&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-1&lt;/code&gt;: 비어있는 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;: 길이도, 면적도 없는 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1&lt;/code&gt;: 길이가 0이 아니지만, 면적은 0인 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2&lt;/code&gt;: 면적이 0이 아닌 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Point&lt;/code&gt;는 &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;LineString&lt;/code&gt;은 &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;Polygon&lt;/code&gt;은 2&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MultiXXX&lt;/code&gt; 객체는 이를 이루는 요소들의 차원과 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;point&#34; &gt;POINT
&lt;span&gt;
    &lt;a href=&#34;#point&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;좌표 공간에서 단일 지점을 나타내는 지오메트리&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X, Y 좌표값&lt;/code&gt;을 가지며 &lt;code&gt;0차원&lt;/code&gt; 도형으로 정의되고 &lt;code&gt;boundary&lt;/code&gt;는 비어있는 집합임&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;linestring&#34; &gt;LINESTRING
&lt;span&gt;
    &lt;a href=&#34;#linestring&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;점 사이 &lt;code&gt;선형 보간(Linear Interpolation)&lt;/code&gt;을 사용하는 &lt;code&gt;Curve&lt;/code&gt; 지오메트리
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;선형 보간&lt;/code&gt;: 양 끝점의 값이 주어졌을 때, 그 사이에 위치한 값을 추정하기 위하여 선형 다항식을 사용해 계산하는 방법&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Curve&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1차원&lt;/code&gt;이며, 시작점과 끝점이 같으면 &lt;code&gt;closed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;동일한 점을 2번 지나지 않거나, 시작점과 끝점이 같은 경우 &lt;code&gt;simple&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;closed&lt;/code&gt;인 &lt;code&gt;Curve&lt;/code&gt;의 &lt;code&gt;boundary&lt;/code&gt;는 비어있으며, &lt;code&gt;not closed&lt;/code&gt;인 &lt;code&gt;Curve&lt;/code&gt;의 &lt;code&gt;boundary&lt;/code&gt;는 양 끝점&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;각 &lt;code&gt;점 쌍으로 구성&lt;/code&gt;된 &lt;code&gt;세그먼트의 좌표값&lt;/code&gt;을 가짐&lt;/li&gt;
&lt;li&gt;정확히 두 점으로만 구성되면 &lt;code&gt;Line&lt;/code&gt;, &lt;code&gt;closed&lt;/code&gt; 이며 &lt;code&gt;simple&lt;/code&gt;인 경우 &lt;code&gt;LinearRing&lt;/code&gt;임&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;polygon&#34; &gt;POLYGON
&lt;span&gt;
    &lt;a href=&#34;#polygon&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;다면체&lt;/code&gt;를 나타내는 평면형 &lt;code&gt;Surface&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;하나의 &lt;code&gt;exterior boundary&lt;/code&gt;와 0개 이상의 &lt;code&gt;interior boundary&lt;/code&gt;로 구성되며 각 &lt;code&gt;interior boundary&lt;/code&gt;는 &lt;code&gt;Polygon&lt;/code&gt; 내부의 구멍의 경계를 정의함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Polygon&lt;/code&gt;의 &lt;code&gt;Boundary&lt;/code&gt;는 &lt;code&gt;내/외부 경계&lt;/code&gt;를 구성하는 &lt;code&gt;LinearRing&lt;/code&gt; 객체 집합으로 구성됨&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Polygon&lt;/code&gt;은 교차하는 &lt;code&gt;Ring&lt;/code&gt;이 존재하지 않으며, &lt;code&gt;Boundary&lt;/code&gt;의 &lt;code&gt;Ring&lt;/code&gt;이 점과 교차할 수 있지만, 접선으로만 교차&lt;/li&gt;
&lt;li&gt;&lt;code&gt;interior&lt;/code&gt;로 &lt;code&gt;연결된 Point 집합&lt;/code&gt;을 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;지오메트리-값-집합-자료형&#34; &gt;지오메트리 값 집합 자료형
&lt;span&gt;
    &lt;a href=&#34;#%ec%a7%80%ec%98%a4%eb%a9%94%ed%8a%b8%eb%a6%ac-%ea%b0%92-%ec%a7%91%ed%95%a9-%ec%9e%90%eb%a3%8c%ed%98%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GEOMETRYCOLLECTION&lt;/code&gt;은 모든 유형의 객체 집합을 저장할 수 있으며, 나머지 집합 자료형은 집합 멤버를 특정 도형 유형을 가진 멤버로 제한함&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;multipoint&#34; &gt;MULTIPOINT
&lt;span&gt;
    &lt;a href=&#34;#multipoint&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POINT&lt;/code&gt;로 구성된 지오메트리 집합으로, 각 &lt;code&gt;POINT&lt;/code&gt;들은 연결되거나 정렬되지 않음&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0차원&lt;/code&gt; 지오메트리이며, 이를 구성하는 각 POINT 간의 좌표가 같지 않으면 &lt;code&gt;simple&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boundary&lt;/code&gt;는 비어있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;multilinestring&#34; &gt;MULTILINESTRING
&lt;span&gt;
    &lt;a href=&#34;#multilinestring&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LineString&lt;/code&gt;로 구성된 &lt;code&gt;MultiCurve&lt;/code&gt; 컬렉션&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MultiCurve&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1차원&lt;/code&gt; 지오메트리&lt;/li&gt;
&lt;li&gt;이를 이루는 모든 요소들이 &lt;code&gt;simple&lt;/code&gt;할 때만 &lt;code&gt;simple&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boundary&lt;/code&gt;는 &lt;code&gt;mod 2 union 규칙(홀수-짝수 규칙)&lt;/code&gt;으로 구할 수 있음
&lt;ul&gt;
&lt;li&gt;한 &lt;code&gt;Point&lt;/code&gt;가 홀수 개의 &lt;code&gt;Curve&lt;/code&gt;요소의 경계에 있는 경우 &lt;code&gt;MultiCurve&lt;/code&gt;의 경계에 있다고 할 수 있음&lt;/li&gt;
&lt;li&gt;모든 요소가 &lt;code&gt;closed&lt;/code&gt;이면 &lt;code&gt;closed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boundary&lt;/code&gt;는 비어있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;multipolygon&#34; &gt;MULTIPOLYGON
&lt;span&gt;
    &lt;a href=&#34;#multipolygon&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Polygon&lt;/code&gt;으로 구성된 &lt;code&gt;MultiSurface&lt;/code&gt; 컬렉션&lt;/li&gt;
&lt;li&gt;각 &lt;code&gt;Polygon&lt;/code&gt; 요소는 교차하는 &lt;code&gt;interior&lt;/code&gt;가 없어야 함&lt;/li&gt;
&lt;li&gt;무한한 수의 점에 닿는 &lt;code&gt;Polygon&lt;/code&gt; 요소를 가질 수 없음&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2차원&lt;/code&gt; 지오메트리이며, &lt;code&gt;boundary&lt;/code&gt;는 요소들의 경계들에 대응되는 &lt;code&gt;LineString&lt;/code&gt; 집합&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MultiPolygon&lt;/code&gt;의 경계를 이루는 각 &lt;code&gt;Curve&lt;/code&gt;들은 각각 하나의 &lt;code&gt;Polygon&lt;/code&gt;요소의 경계에 존재해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;geometrycollection&#34; &gt;GEOMETRYCOLLECTION
&lt;span&gt;
    &lt;a href=&#34;#geometrycollection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;0개 이상의 &lt;code&gt;지오메트리&lt;/code&gt;로 이뤄진 컬렉션&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GEOMETRYCOLLECTION&lt;/code&gt;의 모든 요소는 동일한 &lt;code&gt;좌표계(공간 참조 시스템)&lt;/code&gt;에 있어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;공간-인덱스spatial-index&#34; &gt;&lt;code&gt;공간 인덱스(Spatial Index)&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4spatial-index&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;hr&gt;
&lt;h3 id=&#34;공간-인덱스와-비공간-인덱스&#34; &gt;공간 인덱스와 비공간 인덱스
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4%ec%99%80-%eb%b9%84%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;공간 인덱스&lt;/code&gt;는 &lt;code&gt;R-트리 인덱스&lt;/code&gt;를 생성하며, 이를 지원하지 않는 다른 엔진(즉, &lt;code&gt;비공간 인덱스&lt;/code&gt;를 지원하는)의 경우, &lt;code&gt;B-트리 인덱스&lt;/code&gt;를 생성
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;B-트리 인덱스&lt;/code&gt;는 &lt;code&gt;정확한 값을 조회&lt;/code&gt;하는데는 &lt;code&gt;유용&lt;/code&gt;하지만, &lt;code&gt;범위 스캔&lt;/code&gt;에 대해서는 &lt;code&gt;그렇지 않음&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;공간-인덱스&#34; &gt;공간 인덱스
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MySQL&lt;/code&gt;의 &lt;code&gt;스토리지 엔진&lt;/code&gt; 중 &lt;code&gt;InnoDB&lt;/code&gt;와 &lt;code&gt;MyISAM&lt;/code&gt;에서만 &lt;code&gt;공간 인덱스&lt;/code&gt;를 지원&lt;/li&gt;
&lt;li&gt;일반 인덱스를 생성할 때 처럼 &lt;code&gt;CREATE INDEX&lt;/code&gt;문을 사용하되, &lt;code&gt;SPATIAL&lt;/code&gt; 키워드를 사용
&lt;ul&gt;
&lt;li&gt;ex) &lt;code&gt;ALTER TABLE mytable ADD SPATIAL INDEX(geomcolumn);&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;단일 공간 열&lt;/code&gt;에 대해서만 인덱스를 생성할 수 있음&lt;/li&gt;
&lt;li&gt;인덱스로 지정된 열은 &lt;code&gt;NOT NULL&lt;/code&gt;이어야 함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;기본 키&lt;/code&gt;나 &lt;code&gt;유니크 인덱스&lt;/code&gt;에는 허용되지 않음&lt;/li&gt;
&lt;li&gt;&lt;code&gt;옵티마이저&lt;/code&gt;는 &lt;code&gt;SRID&lt;/code&gt;가 제한된 열에 정의된 &lt;code&gt;공간 인덱스&lt;/code&gt;를 사용할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;비공간-인덱스&#34; &gt;비공간 인덱스
&lt;span&gt;
    &lt;a href=&#34;#%eb%b9%84%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/archive-storage-engine.html&#34; title=&#34;18.5 The ARCHIVE Storage Engine&#34;&gt;&lt;code&gt;ARCHIVE&lt;/code&gt;&lt;/a&gt;를 제외한 나머지 &lt;code&gt;공간 열&lt;/code&gt;을 지원하는 &lt;code&gt;스토리지 엔진&lt;/code&gt;에서 사용 가능&lt;/li&gt;
&lt;li&gt;인덱스가 &lt;em&gt;기본키가 아닌 경우&lt;/em&gt; &lt;code&gt;NULL&lt;/code&gt;을 &lt;code&gt;허용&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/innodb-storage-engine.html&#34; title=&#34;Chapter 17 The InnoDB Storage Engine&#34;&gt;&lt;code&gt;InnoDB&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/myisam-storage-engine.html&#34; title=&#34;18.2 The MyISAM Storage Engine&#34;&gt;&lt;code&gt;MyISAM&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/memory-storage-engine.html&#34; title=&#34;18.3 The MEMORY Storage Engine&#34;&gt;&lt;code&gt;MEMORY&lt;/code&gt;&lt;/a&gt;에서만&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;공간-인덱스-사용하기&#34; &gt;공간 인덱스 사용하기
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b0%84-%ec%9d%b8%eb%8d%b1%ec%8a%a4-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;옵티마이저&lt;/code&gt;는 &lt;code&gt;WHERE&lt;/code&gt;절에서 &lt;code&gt;MBRContains()&lt;/code&gt;, &lt;code&gt; MBRWithin()&lt;/code&gt;와 같은 함수를 사용하는 쿼리에 대해, 가용한 &lt;code&gt;공간 인덱스&lt;/code&gt;를 검색에 포함할 수 있는지 조사&lt;/li&gt;
&lt;li&gt;따라서 &lt;code&gt;공간 인덱스&lt;/code&gt;를 사용하는 함수를 통해 탐색할 row의 범위를 줄이면 &lt;code&gt;최적화가 가능&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;예시
&lt;ul&gt;
&lt;li&gt;한 점으로 부터 5km 떨어진 점들 검색하기
&lt;ul&gt;
&lt;li&gt;약 237만개의 POINT가 기록된 테이블에서 이를 검색하고자 함&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ST_DISTANCE()&lt;/code&gt; 또는 &lt;code&gt;ST_DISTANCE_SPHERE()&lt;/code&gt;를 사용할 경우 &lt;code&gt;공간 인덱스&lt;/code&gt;를 &lt;code&gt;사용하지 않고&lt;/code&gt;, 한 점 한 점 모두 연산을 거치기 때문에 비효율적
&lt;ul&gt;
&lt;li&gt;이 경우 쿼리는 다음과 같음&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;35&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;865807&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;593317&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;g1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ST_GeomFromText(CONCAT(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POINT(&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; geotesttable &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; ST_DISTANCE_SPHERE(&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;g1, &lt;span style=&#34;color:#66d9ef&#34;&gt;location&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;위 쿼리를 분석하면, &lt;code&gt;공간 인덱스&lt;/code&gt;가 &lt;code&gt;활용되지 않고&lt;/code&gt; 237만개의 row들을 &lt;code&gt;모두 불러옴&lt;/code&gt;을 알 수 있음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;query-not-using-spatial-index.png&#34; alt=&#34;query-not-using-spatial-index.png&#34;&gt;
&lt;ul&gt;
&lt;li&gt;참고로 &lt;code&gt;explain query&lt;/code&gt;문을 수행시, 실제 DB의 row 갯수와 다른 값이 불러와 질 수 있음
&lt;ul&gt;
&lt;li&gt;이는 &lt;code&gt;explain&lt;/code&gt;문이 &lt;code&gt;INFORMATION_SCHEMA&lt;/code&gt; 테이블에서 제공하는 러프한 추정치를 사용하기 때문&lt;/li&gt;
&lt;li&gt;따라서 &lt;code&gt;ANALYZE TABLE table_name;&lt;/code&gt; 문을 수행해 이를 업데이트 해주면 올바른 값을 불러옴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;해당 쿼리문을 실제로 수행하면, 데이터를 불러오는데 약 &lt;code&gt;20초&lt;/code&gt;가 소요됨
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-wihtout-spatial-index.png&#34; alt=&#34;time-taken-by-query-wihtout-spatial-index.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;query-not-using-spatial-index-mapview.png&#34; alt=&#34;query-not-using-spatial-index-mapview.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이를 최적화하고자, 먼저 각 변이 한 점으로 부터 각각 5km씩 떨어진 정사각형 &lt;code&gt;Polygon&lt;/code&gt;을 만들고, &lt;code&gt;ST_CONTAINS(A, B)&lt;/code&gt; 함수를 사용해 이에 포함되는 점들만 검색
&lt;ul&gt;
&lt;li&gt;이를 위해 먼저 다음과 같은 형태의 &lt;code&gt;Polygon&lt;/code&gt;을 만듦
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;5km-square.png&#34; alt=&#34;5km-square.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;각 변이 가운데 점으로부터 5km씩 떨어진 정사각형&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 &lt;code&gt;공간 인덱스&lt;/code&gt;를 사용하는 지오메트리 함수인 &lt;code&gt;ST_CONTAINS(A, B)&lt;/code&gt;를 사용해 각 점이 해당 &lt;code&gt;Polygon&lt;/code&gt; 내부에 존재하는지 확인
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ST_CONTAINS(A, B)&lt;/code&gt;는 B가 A 내부에 포함되는지 여부를 반환하는 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이후 각 점들에 대해 &lt;code&gt;ST_DISTANCE_SPHERE(A, B) &amp;lt; 5000&lt;/code&gt; 조건을 수행해 기준점과의 거리가 5km 이내인 점들을 불러온다&lt;/li&gt;
&lt;li&gt;이를 모두 반영한 쿼리는 다음과 같다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;35&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;865807&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;593317&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;g1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ST_GeomFromText(CONCAT(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POINT(&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위도&lt;/span&gt;(latitude) &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도는&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;대략&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;111&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;km
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;따라서&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;km&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;당&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위도는&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0090009&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0091&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelat &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0091&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;경도&lt;/span&gt;(longitude) &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도는&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위도에&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;따라&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;달라지며&lt;/span&gt;, &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;적도에서&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;대략&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;111&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;km
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;계산식은&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;111&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; cos(theta &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; pi&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;180&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;한국은&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;북위&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;33&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;38&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;사이에&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;존재하며&lt;/span&gt;, &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위에서&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;선언한&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위도인&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;35&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;8658&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도를&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;기준으로하면&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;경도&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도는&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;대략&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;90&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0345&lt;/span&gt;km
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;따라서&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;km&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;당&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;위도는&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0111069&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;~=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0111&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;도&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;.&lt;span style=&#34;color:#ae81ff&#34;&gt;0111&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplat &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelat &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlat &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lat &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelat &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelng &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;lng &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;onelng &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;p1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ST_GEOMFROMTEXT(CONCAT(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;POLYGON((&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;toplng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlng, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;bottomlat, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;))&amp;#39;&lt;/span&gt;), &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; geotesttable &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; ST_CONTAINS(&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;p1, &lt;span style=&#34;color:#66d9ef&#34;&gt;location&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;and&lt;/span&gt; ST_DISTANCE_SPHERE(&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;g1, &lt;span style=&#34;color:#66d9ef&#34;&gt;location&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;위 쿼리를 &lt;code&gt;explain&lt;/code&gt;문을 통해 분석하면, 설정해놓은 &lt;code&gt;공간 인덱스(idx_location)&lt;/code&gt;를 활용해 범위를 줄여 불러옴을 알 수 있음
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;query-using-spatial-index.png&#34; alt=&#34;query-using-spatial-index.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;쿼리 수행에 걸리는 시간도 20초에서 5초로 확 단축됨
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;time-taken-by-query-with-spatial-index.png&#34; alt=&#34;time-taken-by-query-with-spatial-index.png&#34;&gt;&lt;/li&gt;
&lt;li&gt;&lt;img src=&#34;query-using-spatial-index-mapview.png&#34; alt=&#34;query-using-spatial-index-mapview.png&#34;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;주의사항&#34; &gt;주의사항
&lt;span&gt;
    &lt;a href=&#34;#%ec%a3%bc%ec%9d%98%ec%82%ac%ed%95%ad&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;h3 id=&#34;지오메트리-컬럼-생성시-초기-srid를-신중히-정할-것&#34; &gt;지오메트리 컬럼 생성시 초기 SRID를 신중히 정할 것
&lt;span&gt;
    &lt;a href=&#34;#%ec%a7%80%ec%98%a4%eb%a9%94%ed%8a%b8%eb%a6%ac-%ec%bb%ac%eb%9f%bc-%ec%83%9d%ec%84%b1%ec%8b%9c-%ec%b4%88%ea%b8%b0-srid%eb%a5%bc-%ec%8b%a0%ec%a4%91%ed%9e%88-%ec%a0%95%ed%95%a0-%ea%b2%83&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;어떤 이유인지는 몰라도, 이미 존재하는 컬럼의 &lt;code&gt;SRID&lt;/code&gt;를 변경하려고 하면 변경이 이뤄지지 않음
&lt;ul&gt;
&lt;li&gt;시도해본 구문 목록 (예를 들기 위해 테이블 이름은 &lt;code&gt;table&lt;/code&gt;, 컬럼 이름은 &lt;code&gt;geom&lt;/code&gt;이라고 하겠음)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;UPDATE table SET geom = ST_GeomFromText(ST_AsText(geom), SRID)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE table SET geom = ST_Transform(geom, SRID)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UPDATE table SET geom = ST_SRID(geom, SRID)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;공통적으로 아래와 같은 오류가 발생함
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	ERROR &lt;span style=&#34;color:#ae81ff&#34;&gt;3643&lt;/span&gt; (HY000): The SRID &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the geometry does &lt;span style=&#34;color:#66d9ef&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; the SRID &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the &lt;span style=&#34;color:#66d9ef&#34;&gt;column&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;position&amp;#39;&lt;/span&gt;. The SRID &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the geometry &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, but the SRID &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the &lt;span style=&#34;color:#66d9ef&#34;&gt;column&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;. 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Consider changing the SRID &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the geometry &lt;span style=&#34;color:#66d9ef&#34;&gt;or&lt;/span&gt; the SRID property &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; the &lt;span style=&#34;color:#66d9ef&#34;&gt;column&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이미 존재하는 컬럼의 &lt;code&gt;SRID&lt;/code&gt;는 바꾸는게 불가능하다 판단
&lt;ul&gt;
&lt;li&gt;따라서 변경하고자 하는 &lt;code&gt;SRID&lt;/code&gt;를 갖는 컬럼을 새로 생성한 뒤, 기존 컬럼의 값들을 복사해오고 공간 인덱스도 재설정함&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ADD&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;geom4326 POINT SRID &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UPDATE&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;SET&lt;/span&gt; geom4326 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ST_GeomFromText(ST_AsText(geom), &lt;span style=&#34;color:#ae81ff&#34;&gt;4326&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;ALTER&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;TABLE&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;table&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;DROP&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;COLUMN&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;geom;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;참고&#34; &gt;참고
&lt;span&gt;
    &lt;a href=&#34;#%ec%b0%b8%ea%b3%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Spatial_database&#34;&gt;Spatial database - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Minimum_bounding_rectangle&#34;&gt;Minimum bounding rectangle - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Web_Mercator_projection&#34;&gt;Web Mercator projection - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ismll.uni-hildesheim.de/lehre/spatial-10w/script/ch1.pdf&#34;&gt;Introduction to Spatial Databases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MYSQL Reference Manual
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/spatial-index-optimization.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 10.3.3 SPATIAL Index Optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/explain-output.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 10.8.2 EXPLAIN Output Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/spatial-types.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4 Spatial Data Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/opengis-geometry-model.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4.2 The OpenGIS Geometry Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/gis-data-formats.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4.3 Supported Spatial Data Formats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/fetching-spatial-data.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4.8 Fetching Spatial Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/creating-spatial-indexes.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4.10 Creating Spatial Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/using-spatial-indexes.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 13.4.11 Using Spatial Indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/gis-format-conversion-functions.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 14.16.6 Geometry Format Conversion Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.4/en/spatial-relation-functions-object-shapes.html&#34;&gt;MySQL :: MySQL 8.4 Reference Manual :: 14.16.9.1 Spatial Relation Functions That Use Object Shapes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/blog-archive/spatial-reference-systems-in-mysql-8-0/&#34;&gt;MySQL :: Spatial Reference Systems in MySQL 8.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sco.wisc.edu/2022/01/21/how-big-is-a-degree/#:~:text=Therefore%20we%20can%20easily%20compute,69.4%20miles%20(111.1%20km).&#34;&gt;How Big is a Degree? – State Cartographer&amp;rsquo;s Office – UW–Madison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dbeaver.com/docs/dbeaver/Working-with-Spatial-GIS-data/#labels-on-a-map&#34;&gt;DBeaver Documentation - Working with Spatial GIS data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/1037471/why-the-rows-returns-by-explain-is-not-equal-to-count&#34;&gt;mysql - Why the rows returns by &amp;ldquo;explain&amp;rdquo; is not equal to count()? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/7477003/calculating-new-longitude-latitude-from-old-n-meters&#34;&gt;algorithm - Calculating new longitude, latitude from old + n meters - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://arthur-e.github.io/Wicket/sandbox-gmaps3.html&#34;&gt;Wicket - Lightweight Javascript for WKT [Sandbox]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://m.blog.naver.com/ilsan_ilsan/221497823431&#34;&gt;[오픈소스GIS] WKB, WKT 이해 / postGIS에서의 변환, 입출력 : 네이버 블로그&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ogc.org/as/17-087r13/17-087r13.html#_the_first_part_feature_models&#34;&gt;Features and geometry – Part 1: Feature models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>[DB] SQL Injection 알아보기 (w. PreparedStatement, Stored Procedures)</title>
      <link>https://cloudsoswift.github.io/post/develop/database/sql-injection/</link>
      <pubDate>Sat, 14 Sep 2024 20:29:34 +0900</pubDate>
      
      <guid>https://cloudsoswift.github.io/post/develop/database/sql-injection/</guid>
      <description>&lt;h1 id=&#34;서론&#34; &gt;서론
&lt;span&gt;
    &lt;a href=&#34;#%ec%84%9c%eb%a1%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/orm712/CS-712&#34;&gt;CS 스터디&lt;/a&gt;에서 9월 4일에 발표한 &lt;a href=&#34;https://github.com/orm712/CS-712/blob/main/04-DATABASE/16_SQL-Injection/Readme.md&#34;&gt;&lt;strong&gt;SQL Injection&lt;/strong&gt;&lt;/a&gt;에 대해 정리한 문서를 블로그에 공유하고자 한다.&lt;/p&gt;
&lt;h2 id=&#34;sql-injection에-대해-설명해-주세요&#34; &gt;SQL Injection에 대해 설명해 주세요.
&lt;span&gt;
    &lt;a href=&#34;#sql-injection%ec%97%90-%eb%8c%80%ed%95%b4-%ec%84%a4%eb%aa%85%ed%95%b4-%ec%a3%bc%ec%84%b8%ec%9a%94&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;SQL Injection&lt;/code&gt;이란, &lt;em&gt;데이터베이스를 사용하는&lt;/em&gt; 웹 애플리케이션을 공격하는데 사용되는 &lt;code&gt;코드 인젝션 공격 기법&lt;/code&gt;을 말합니다.&lt;br&gt;
주로 공격자가 &lt;code&gt;입력 필드&lt;/code&gt;에 &lt;code&gt;악성 SQL 문&lt;/code&gt;을 삽입해 실행시키는 방식으로 공격하며, &lt;code&gt;데이터베이스의 정보&lt;/code&gt;를 불법적으로 &lt;code&gt;열람&lt;/code&gt; 또는 &lt;code&gt;조작&lt;/code&gt;할 수 있는 취약점입니다.&lt;br&gt;
&lt;code&gt;Injection&lt;/code&gt; 공격은 오픈소스 웹 애플리케이션 보안 프로젝트인 &lt;a href=&#34;https://owasp.org/&#34;&gt;OWASP&lt;/a&gt;에서 매년 &lt;a href=&#34;https://owasp.org/www-project-top-ten/&#34;&gt;상위 10대 취약점&lt;/a&gt;에서 근 20년간 상위권을 차지하고 있으며, 단순히 신원 위조, 기존 데이터 변조와 같은 공격 뿐만 아니라 관리자 탈취, 데이터 삭제, 시스템 데이터 공개와 같이 &lt;code&gt;시스템에 치명적인 공격&lt;/code&gt;을 불러올 수 있습니다.&lt;/p&gt;
&lt;h3 id=&#34;공격-유형&#34; &gt;공격 유형
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ea%b2%a9-%ec%9c%a0%ed%98%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;SQL Injection&lt;/code&gt;은 기본적으로 &lt;code&gt;데이터 입력&lt;/code&gt; 란에 &lt;code&gt;메타 문자&lt;/code&gt;(&lt;code&gt;&#39;&#39;&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt; 등 SQL문을 이루는 문자들)를 삽입해 기존에 존재하지 않던 SQL 명령을 &lt;code&gt;제어 영역(control plane, SQL 명령어 및 관련 구조가 위치하는 영역. ~= user input)&lt;/code&gt;에 배치하는 방식으로 이뤄집니다.&lt;br&gt;
이러한 구조적 결함은 SQL이 &lt;code&gt;제어 영역&lt;/code&gt;과 &lt;code&gt;데이터 영역(data plane, 실제 데이터 값이 위치하는 영역. ~= SQL Query)&lt;/code&gt;을 구분하지 않고, 단순히 문자열로 된 명령을 실행한다는 점에서 기인합니다.&lt;br&gt;
&lt;code&gt;SQL Injection&lt;/code&gt;은 크게 아래 3가지 유형으로 구분됩니다.&lt;/p&gt;
&lt;h4 id=&#34;에러-기반-sql-인젝션error-based-sql-injection&#34; &gt;에러 기반 SQL 인젝션(Error-based SQL Injection)
&lt;span&gt;
    &lt;a href=&#34;#%ec%97%90%eb%9f%ac-%ea%b8%b0%eb%b0%98-sql-%ec%9d%b8%ec%a0%9d%ec%85%98error-based-sql-injection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;에러 기반 SQL 인젝션&lt;/code&gt;은 데이터베이스 서버에서 발생한 &lt;code&gt;오류 메세지&lt;/code&gt;를 바탕으로 현재 API가 &lt;code&gt;어떤 SQL 명령&lt;/code&gt;을 호출하는지, &lt;code&gt;데이터베이스 구조&lt;/code&gt;는 어떤지 등의 &lt;code&gt;정보&lt;/code&gt;를 얻어내 공격하는 기법입니다.&lt;br&gt;
이는 공격당하는 &lt;code&gt;웹 애플리케이션&lt;/code&gt; 서버가 &lt;em&gt;SQL 쿼리 수행시 발생한&lt;/em&gt; &lt;code&gt;오류&lt;/code&gt;를 &lt;code&gt;HTTP 응답&lt;/code&gt;으로 &lt;code&gt;반환&lt;/code&gt;하도록 동작하는 경우 가능한 공격입니다.&lt;/p&gt;
&lt;h5 id=&#34;예시&#34; &gt;예시
&lt;span&gt;
    &lt;a href=&#34;#%ec%98%88%ec%8b%9c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;img src=&#34;error-based-form.png&#34; alt=&#34;error-based-form.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;위와 같은 입력 폼으로 아이디, 비밀번호를 입력받아 로그인을 수행하는 웹 애플리케이션이 있다고 가정하겠습니다.&lt;br&gt;
위 애플리케이션이 구동되는 Spring 서버에서는 DB에서 일치하는 유저를 불러오기 위해 다음과 같은 코드가 동작하게 됩니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Statement st &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; conn&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;createStatement&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	ResultSet rs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; st&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;executeQuery&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;SELECT * FROM member WHERE userid = &amp;#39;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; ID &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#39; AND userpw =&amp;#39;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; PW &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;즉, DB에서는 다음과 같은 SQL문이 동작하게 될 것입니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; member &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; userid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$ID&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; userpw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$PW&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이때, pw에 &lt;code&gt;&#39;OR 1=1 --&lt;/code&gt;를 입력하거나 &lt;code&gt;extractvalue()&lt;/code&gt; 함수 등을 사용해 DB 정보를 탈취할 수 있습니다.&lt;br&gt;
&lt;code&gt;OR 1=1 --&lt;/code&gt;는 &lt;code&gt;WHERE&lt;/code&gt; 절의 조건을 항상 참이 되도록 하고, 이어지는 조건들을 &lt;code&gt;--&lt;/code&gt;를 통해 &lt;code&gt;주석 처리&lt;/code&gt;하게 됩니다. 따라서 id에 (실제 서비스에 가입된) id중 어떤 것을 입력해도 로그인할 수 있게 됩니다.&lt;br&gt;
&lt;code&gt;extractvalue(xml_frag, xpath_expr)&lt;/code&gt; 함수의 경우 &lt;code&gt;XML&lt;/code&gt;과 &lt;code&gt;XPath 표현식&lt;/code&gt;을 인자로 받아, &lt;code&gt;XML&lt;/code&gt;에서 &lt;code&gt;XPath 표현식&lt;/code&gt;에 일치하는 데이터를 추출 및 반환하는 함수입니다.&lt;br&gt;
이때, &lt;code&gt;두 번째 인수&lt;/code&gt;에 유효하지 않은 XPath 표현식이 사용될 경우 &lt;code&gt;XPATH syntax error&lt;/code&gt;를 통해 해당 인수 값을 &lt;code&gt;출력&lt;/code&gt;하게 되는데, 이것이 &lt;code&gt;SQL 쿼리&lt;/code&gt;일 경우 &lt;code&gt;실행 결과를 에러 메시지에 포함&lt;/code&gt;한다는 점을 활용해 공격에 사용됩니다.&lt;br&gt;
따라서 두 번째 인수에 콜론(&lt;code&gt;&#39;:&#39;&lt;/code&gt; 또는 &lt;code&gt;0x3a&lt;/code&gt;(16진수 표현)을 사용)을 맨 앞에 추가하므로써 항상 유효하지 않은 &lt;code&gt;XPath 표현식&lt;/code&gt;을 만들고, &lt;code&gt;concat()&lt;/code&gt;으로 뒤에 실제 실행할 &lt;code&gt;SQL 쿼리&lt;/code&gt;를 넘겨 정보 탈취를 시도합니다.&lt;br&gt;
가령 PW에 &lt;code&gt;&#39; AND extractvalue(rand(),concat(0x3a,version()))--&lt;/code&gt; 라는 구문을 넣게 된다면 실제 SQL 쿼리 문은 다음과 같게 될것입니다. (&lt;code&gt;version()&lt;/code&gt;은 현재 MySQL 버전을 반환하는 함수입니다.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; member &lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; userid &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; userpw &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; extractvalue(rand(),concat(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;x3a,&lt;span style=&#34;color:#66d9ef&#34;&gt;version&lt;/span&gt;()))&lt;span style=&#34;color:#75715e&#34;&gt;--&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이를 실행하면 아래 그림처럼 서버의 MySQL 버전을 &lt;code&gt;에러와 함께 반환&lt;/code&gt;하게 됩니다.&lt;br&gt;
&lt;img src=&#34;error-alert.png&#34; alt=&#34;error-alert.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;이를 통해 공격자는 &lt;code&gt;DB 버전&lt;/code&gt;, &lt;code&gt;DB 명&lt;/code&gt;, &lt;code&gt;테이블 명&lt;/code&gt;, &lt;code&gt;컬럼 명&lt;/code&gt; 등 다양한 데이터들을 추출할 수 있게 됩니다.&lt;/p&gt;
&lt;h4 id=&#34;union-기반-sql-인젝션union-based-sql-injection&#34; &gt;UNION 기반 SQL 인젝션(Union-based SQL Injection)
&lt;span&gt;
    &lt;a href=&#34;#union-%ea%b8%b0%eb%b0%98-sql-%ec%9d%b8%ec%a0%9d%ec%85%98union-based-sql-injection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;UNION 기반 SQL 인젝션&lt;/code&gt;은 웹 애플리케이션이 &lt;code&gt;DB 질의한 결과&lt;/code&gt;를 &lt;code&gt;HTTP 응답&lt;/code&gt;에 포함해 반환하는 경우, &lt;code&gt;SQL&lt;/code&gt;문을 조작하여 &lt;code&gt;DB 구조 및 데이터&lt;/code&gt;를 &lt;code&gt;탈취&lt;/code&gt;하는 공격 기법입니다.&lt;br&gt;
이때, &lt;em&gt;원래 애플리케이션이 반환할 데이터는 필요하지 않으므로&lt;/em&gt; &lt;code&gt;음수 값&lt;/code&gt;과 같이 DB에 존재하지 않을만한 값을 &lt;code&gt;입력 값으로 전달&lt;/code&gt;하고, 이후 &lt;code&gt;UNION&lt;/code&gt; 또는 &lt;code&gt;UNION ALL&lt;/code&gt;을 이용해 DB의 다른 데이터 값을 추출하는 &lt;code&gt;SQL 쿼리를 덧붙여&lt;/code&gt; 서버에 전달하게 됩니다.&lt;/p&gt;
&lt;h5 id=&#34;union과-union-all&#34; &gt;&lt;code&gt;UNION&lt;/code&gt;과 &lt;code&gt;UNION ALL&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#union%ea%b3%bc-union-all&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;code&gt;UNION&lt;/code&gt;과 &lt;code&gt;UNION ALL&lt;/code&gt;은 &lt;strong&gt;두 개 이상&lt;/strong&gt;의 &lt;code&gt;SELECT 쿼리 결과&lt;/code&gt;를 하나로 합쳐주는 집합 연산자로, 이때 합쳐질 쿼리들은 다음 조건을 만족해야 합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;각 쿼리들은 &lt;code&gt;SELECT&lt;/code&gt;절에서 &lt;code&gt;동일한 갯수&lt;/code&gt;의 &lt;code&gt;열&lt;/code&gt;을 사용해야 한다.&lt;/li&gt;
&lt;li&gt;각 쿼리에서 &lt;code&gt;동일한 순서의 컬럼들&lt;/code&gt;은 서로 호환되는 자료형을 가져야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;또한, &lt;code&gt;UNION&lt;/code&gt;은 쿼리 결과값 통합시 중&lt;code&gt;복된 레코드를 제거&lt;/code&gt;하는 반면, &lt;code&gt;UNION ALL&lt;/code&gt;은 &lt;em&gt;중복 제거 절차 없이&lt;/em&gt; &lt;code&gt;모든 레코드들을 반환&lt;/code&gt;한다는 차이가 있습니다.&lt;/p&gt;
&lt;h5 id=&#34;예시-1&#34; &gt;예시
&lt;span&gt;
    &lt;a href=&#34;#%ec%98%88%ec%8b%9c-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;쇼핑몰 웹 애플리케이션에서 물품의 ID를 사용자로 부터 입력받으면, 해당 물품의 &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;이름&lt;/code&gt;, &lt;code&gt;가격&lt;/code&gt;을 조회하는 API가 있다고 가정하겠습니다.&lt;br&gt;
해당 API가 DB에 요청할 SQL 쿼리는 다음과 같을 것입니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; item_id, item_name, item_price 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; item 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; item_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$item_id&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;또한, 해당 API는 HTTP 응답으로 이름과 가격, 즉 &lt;code&gt;item_name&lt;/code&gt;, &lt;code&gt;item_price&lt;/code&gt;를 반환합니다.&lt;/p&gt;
&lt;p&gt;이러한 상황에서 ID로 &lt;code&gt;-99 UNION ALL SELECT version(), database(), 2--&lt;/code&gt;를 전달한다면 SQL 쿼리는 다음과 같이 바뀌게 됩니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; item_id, item_name, item_price 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; item 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; item_id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;99&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;UNION&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ALL&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;version&lt;/span&gt;(), &lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;당연히 상품 ID가 음수인 상품은 존재하지 않을 것이므로 상품 데이터는 전혀 반환되지 않고 &lt;code&gt;UNION&lt;/code&gt;으로 결합한 &lt;code&gt;SELECT&lt;/code&gt; 쿼리에 포함된 &lt;code&gt;SQL 서버 버전&lt;/code&gt;, &lt;code&gt;DB명&lt;/code&gt;, &lt;code&gt;숫자(컬럼 갯수 및 타입을 맞추기 위한 임의 값)&lt;/code&gt;를 반환하게 됩니다.&lt;/p&gt;
&lt;h5 id=&#34;열-갯수-알아내기&#34; &gt;열 갯수 알아내기
&lt;span&gt;
    &lt;a href=&#34;#%ec%97%b4-%ea%b0%af%ec%88%98-%ec%95%8c%ec%95%84%eb%82%b4%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;그리고 &lt;code&gt;UNION&lt;/code&gt;에서 열의 갯수를 맞춰야 하는 조건 때문에, 현재 쿼리의 컬럼 갯수를 알아야 할 수 있습니다.&lt;br&gt;
이때 &lt;code&gt;ORDER BY&lt;/code&gt; 절을 활용하면, 원래의 &lt;code&gt;SQL 쿼리&lt;/code&gt;의 열 갯수를 알아낼 수 있습니다.&lt;br&gt;
&lt;code&gt;ORDER BY&lt;/code&gt; 절에서 정렬 기준 컬럼을 지정할 때, 열 이름을 직접 기입할 수도 있지만 &lt;code&gt;해당 컬럼의 순번&lt;/code&gt;을 기입할 수도 있습니다.&lt;br&gt;
즉, 위 케이스의 경우 &lt;code&gt;ORDER BY 3&lt;/code&gt;을 기입하면 &lt;code&gt;SQL 쿼리&lt;/code&gt;의 세 번째 컬럼인 &lt;code&gt;item_price&lt;/code&gt;를 기준으로 정렬하게 됩니다.&lt;br&gt;
이러한 순번은 &lt;code&gt;SQL 쿼리가 불러올 컬럼 갯수&lt;/code&gt;만큼 배정되므로 &lt;code&gt;해당 갯수 이상의 숫자&lt;/code&gt;를 기입하게 되면 다음과 같은 &lt;code&gt;오류가 발생&lt;/code&gt;하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;union-alert.png&#34; alt=&#34;union-alert.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;따라서 &lt;code&gt;ORDER BY&lt;/code&gt; 문에 기입할 순번을 하나씩 &lt;code&gt;차례대로 증가&lt;/code&gt;시키다가 &lt;code&gt;DB에서 오류가 발생&lt;/code&gt;하거나 &lt;code&gt;비정상 응답을 반환&lt;/code&gt;하게 되면, 바로 전의 순번이 원래의 SQL문의 &lt;code&gt;컬럼 갯수&lt;/code&gt;와 같게되는 것입니다.&lt;/p&gt;
&lt;h4 id=&#34;블라인드-sql-인젝션blind-sql-injection&#34; &gt;블라인드 SQL 인젝션(Blind SQL Injection)
&lt;span&gt;
    &lt;a href=&#34;#%eb%b8%94%eb%9d%bc%ec%9d%b8%eb%93%9c-sql-%ec%9d%b8%ec%a0%9d%ec%85%98blind-sql-injection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;블라인드 SQL 인젝션&lt;/code&gt;은 &lt;em&gt;상기한 SQL 인젝션들과 달리&lt;/em&gt;, 웹 애플리케이션이 &lt;code&gt;HTTP 응답&lt;/code&gt;에 &lt;code&gt;DB 오류 메시지&lt;/code&gt;나 &lt;code&gt;데이터&lt;/code&gt;를 포함하지 않을때 사용할 수 있는 공격 기법입니다.&lt;br&gt;
즉, &lt;em&gt;서버의 직접적인 응답 대신&lt;/em&gt; &lt;code&gt;알고싶은 정보가 포함된 특정 조건&lt;/code&gt;을 SQL 쿼리에 포함시켰을때 &lt;code&gt;HTTP 응답&lt;/code&gt;의 &lt;code&gt;상태&lt;/code&gt;가 달라지거나, &lt;code&gt;응답에 걸리는 시간&lt;/code&gt;의 차이를 통해 해당 조건이 &lt;code&gt;참인지 거짓인지&lt;/code&gt; 알아내므로써 데이터베이스 내 &lt;code&gt;정보를 유추&lt;/code&gt;하는 공격 기법입니다.&lt;br&gt;
크게 응답의 차이를 통해 유추하는 &lt;code&gt;불린 기반&lt;/code&gt; 방식과 서버의 응답 시간 차이를 통해 유추하는 &lt;code&gt;시간 기반&lt;/code&gt; 방식이 있습니다.&lt;/p&gt;
&lt;h5 id=&#34;블라인드-불린-기반-sql-인젝션blind-boolean-based-sql-injection&#34; &gt;블라인드 불린 기반 SQL 인젝션(Blind Boolean-Based SQL Injection)
&lt;span&gt;
    &lt;a href=&#34;#%eb%b8%94%eb%9d%bc%ec%9d%b8%eb%93%9c-%eb%b6%88%eb%a6%b0-%ea%b8%b0%eb%b0%98-sql-%ec%9d%b8%ec%a0%9d%ec%85%98blind-boolean-based-sql-injection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;code&gt;블라인드 불린 기반 SQL 인젝션&lt;/code&gt;은 &lt;code&gt;SQL 쿼리&lt;/code&gt;의 &lt;code&gt;참/거짓&lt;/code&gt;여부에 따른  &lt;code&gt;HTTP 응답 내용&lt;/code&gt;, &lt;code&gt;상태 코드&lt;/code&gt; 등의 &lt;code&gt;차이가 존재&lt;/code&gt;할 때 이를 통해 &lt;code&gt;정보를 유추&lt;/code&gt;할 수 있는 공격 기법입니다.&lt;/p&gt;
&lt;h6 id=&#34;예시-2&#34; &gt;예시
&lt;span&gt;
    &lt;a href=&#34;#%ec%98%88%ec%8b%9c-2&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;게시판 애플리케이션에서 게시글 id를 URL 인자로 받아 게시물을 불러오는 API를 예시로 들어보겠습니다. 해당 API는 다음과 같은 SQL 쿼리를 요청합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; subject, content, author  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; board  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;$id&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;만약 올바른 게시글 id를 전달받았다면 정상적으로 해당 게시글을 가져올 것이고, 그렇지 않다면 아무것도 반환하지 않을 것입니다.&lt;br&gt;
예를 들어 id를 &lt;code&gt;1 AND 1=0--&lt;/code&gt; 로 넘겼다면 SQL문은 다음과 같게 됩니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; subject, content, author  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; board  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;우리가 넘긴 &lt;code&gt;AND 1=0&lt;/code&gt; 조건 때문에 게시물 조회 &lt;code&gt;SQL 쿼리&lt;/code&gt;는 거짓이 되어 아무 것도 불러올 수 없을 것입니다. 반면 &lt;code&gt;1 AND 1=1 --&lt;/code&gt;을 넘겼다면 정상적으로 게시물을 조회해올 것입니다.&lt;br&gt;
이를 바탕으로 데이터베이스의 이름을 알아내고 싶다고 가정해보겠습니다.&lt;br&gt;
그렇다면 먼저 DB 이름의 길이를 알아내야 하므로, SQL의 &lt;code&gt;LENGTH()&lt;/code&gt;을 활용합니다.&lt;br&gt;
id로 &lt;code&gt;1 AND LENGTH(database()) = 1 --&lt;/code&gt;, &lt;code&gt;1 AND LENGTH(database()) = 2 --&lt;/code&gt;, &amp;hellip; 처럼 점점 값을 증가시키며 응답이 정상적으로 반환될 때 까지 반복합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:참) &amp;lt;- 현재 DB의 이름의 길이는 3임
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이후 한글자 한글자씩 비교하며 DB 이름의 각 자리가 무엇인지 확인합니다. 이때 &lt;code&gt;SUBSTRING()&lt;/code&gt; 함수를 활용합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;SUBSTRING&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;SUBSTRING&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;SUBSTRING&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:참) &amp;lt;- 현재 DB의 이름의 첫 글자는 &amp;#39;c&amp;#39;임
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이를 반복해 알아낸 각 자리의 문자들을 결합하면 DB의 이름을 알아낼 수 있습니다.&lt;/p&gt;
&lt;h5 id=&#34;블라인드-시간-기반-sql-인젝션blind-time-based-sql-injection&#34; &gt;블라인드 시간 기반 SQL 인젝션(Blind Time-Based SQL Injection)
&lt;span&gt;
    &lt;a href=&#34;#%eb%b8%94%eb%9d%bc%ec%9d%b8%eb%93%9c-%ec%8b%9c%ea%b0%84-%ea%b8%b0%eb%b0%98-sql-%ec%9d%b8%ec%a0%9d%ec%85%98blind-time-based-sql-injection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;code&gt;블라인드 불린 기반 SQL 인젝션&lt;/code&gt;은 &lt;code&gt;SQL 쿼리&lt;/code&gt;의 &lt;code&gt;참/거짓&lt;/code&gt;여부에 따른  &lt;code&gt;HTTP 응답 내용&lt;/code&gt;, &lt;code&gt;상태 코드&lt;/code&gt; 등의 차이가 존재를 &lt;code&gt;확인할 수 없지만&lt;/code&gt;, 서버 응답 시간을 제어할 수 있을 경우 사용 가능한 공격 기법입니다.&lt;br&gt;
즉, 기존 &lt;code&gt;SQL 쿼리&lt;/code&gt;에 &lt;code&gt;특정 조건&lt;/code&gt;이 참일 경우 &lt;code&gt;응답을 지연시키는 함수&lt;/code&gt;를 사용해 해당 조건의 참/거짓 여부를 판별하게 됩니다.&lt;br&gt;
응답 시간을 제어하는 함수는 DBMS별로 상이하며, 예시로 들 &lt;code&gt;MySQL&lt;/code&gt;(및 &lt;code&gt;MariaDB&lt;/code&gt;)의 경우 &lt;code&gt;sleep()&lt;/code&gt; 함수를 사용합니다.&lt;/p&gt;
&lt;h6 id=&#34;예시-3&#34; &gt;예시
&lt;span&gt;
    &lt;a href=&#34;#%ec%98%88%ec%8b%9c-3&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;위와 마찬가지로 게시판 애플리케이션에서 게시물 조회 API를 사용한다고 가정하겠습니다.&lt;br&gt;
이때 id로 &lt;code&gt;1 AND if(1=1, sleep(5), false)--&lt;/code&gt; 와 같은 구문을 전달했을 때 기존 &lt;code&gt;SQL 쿼리&lt;/code&gt;에 정상적으로 포함된다면, SQL문은 다음과 같게 됩니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;SELECT&lt;/span&gt; subject, content, author  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;FROM&lt;/span&gt; board  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;WHERE&lt;/span&gt; id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, sleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;), &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;)&lt;span style=&#34;color:#75715e&#34;&gt;--
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이때 if문이 동작하기 때문에 첫 번째 인자로 주어진 조건식인 &lt;code&gt;1=1&lt;/code&gt;이 참이므로, 서버는 &lt;code&gt;5초간 대기&lt;/code&gt; 상태에 있다가 응답하게 될 것입니다.&lt;br&gt;
이를 바탕으로 &lt;em&gt;불린 기반 공격 처럼&lt;/em&gt;, 조건문에 &lt;code&gt;원하는 정보에 대한 조건&lt;/code&gt;을 포함해 API 요청을 반복하므로써 원하는 정보를 알아낼 수 있습니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, sleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;), &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;)&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, sleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;), &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;)&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:거짓)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;AND&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;LENGTH&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;database&lt;/span&gt;())&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, sleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;), &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;)&lt;span style=&#34;color:#75715e&#34;&gt;--+                (결과:참) &amp;lt;- 현재 DB의 이름의 길이는 3임
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;방어법-httpscheatsheetseriesowasporgcheatsheetssql_injection_prevention_cheat_sheethtml&#34; &gt;방어법 &lt;a href=&#34;https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html&#34;&gt;#&lt;/a&gt;
&lt;span&gt;
    &lt;a href=&#34;#%eb%b0%a9%ec%96%b4%eb%b2%95-httpscheatsheetseriesowasporgcheatsheetssql_injection_prevention_cheat_sheethtml&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;이러한 &lt;code&gt;SQL 인젝션&lt;/code&gt;을 방지하기 위해서는 ① &lt;code&gt;문자열들을 연결&lt;/code&gt;해 &lt;code&gt;동적 SQL 쿼리&lt;/code&gt;를 &lt;code&gt;생성하지 않거나&lt;/code&gt;, ② 실행된 쿼리에 &lt;code&gt;악성 SQL 입력&lt;/code&gt;이 &lt;code&gt;포함되지 않도록&lt;/code&gt; 해야 합니다.&lt;/p&gt;
&lt;h4 id=&#34;prepared-statement-사용하기&#34; &gt;Prepared Statement 사용하기
&lt;span&gt;
    &lt;a href=&#34;#prepared-statement-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;준비된 구문(Prepared Statement)&lt;/code&gt;, 또는 &lt;code&gt;파라미터화 된 쿼리(Parameterized Query)&lt;/code&gt;를 사용하게 되면 &lt;code&gt;동적 쿼리&lt;/code&gt;보다 쿼리를 작성 및 이해하는데 쉬우며, 개발자가 먼저 SQL 쿼리를 정의한 뒤 이후에 각 매개변수들을 쿼리에 전달하도록 합니다.&lt;br&gt;
또한 DB 쿼리가 이러한 형태를 띄는 경우 DB는 사용자 입력에 상관없이 항상 코드와 데이터를 구분합니다. 그리고 공격자가 SQL 명령을 삽입해도 쿼리의 원래 의도를 변경할 수 없도록 보장합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 코드 예시
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 매개변수로 사용될 해당 인자는 꼭 검증하는 것이 좋습니다.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;String custname &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; request&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getParameter&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;customerName&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;String query &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;SELECT account_balance FROM user_data WHERE user_name = ? &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PreparedStatement pstmt &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; connection&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;prepareStatement&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; query &lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pstmt&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;setString&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; custname&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ResultSet results &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; pstmt&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;executeQuery&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Java의 &lt;code&gt;PreparedStatement&lt;/code&gt;, C# .NET의 &lt;code&gt;OleDbCommand&lt;/code&gt; 등이 이를 구현하고 있으며 이외에도 Ruby, PHP, Perl 등 다양한 언어에 &lt;code&gt;Prepared Statement&lt;/code&gt; 구현체가 존재합니다.&lt;br&gt;
또한 &lt;code&gt;SQL 인젝션&lt;/code&gt;과 유사한 &lt;code&gt;HQL 인젝션&lt;/code&gt;이 존재하는 SQL 추상화 계층인 &lt;code&gt;HQL(Hibernate Query Language)&lt;/code&gt;에도 &lt;code&gt;Prepared Statement&lt;/code&gt; 형태의 구현체가 존재합니다.&lt;/p&gt;
&lt;h4 id=&#34;stored-procedures-사용하기&#34; &gt;Stored Procedures 사용하기
&lt;span&gt;
    &lt;a href=&#34;#stored-procedures-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;code&gt;저장 프로시저 (Stored procedure)&lt;/code&gt;란 DBMS에 저장되어 재사용 및 공유할 수 있는 일련의 &lt;code&gt;SQL 쿼리 집합&lt;/code&gt;입니다.&lt;br&gt;
&lt;code&gt;Stored Procedure&lt;/code&gt;가 항상 &lt;code&gt;SQL 인젝션&lt;/code&gt;으로 부터 안전하지 않지만, 특정 표준 &lt;code&gt;Stored Procedure&lt;/code&gt;를 사용하면 &lt;code&gt;Parameterized Query&lt;/code&gt;를 사용하는 것과 동일한 효과를 갖게 됩니다.&lt;br&gt;
다만, &lt;code&gt;Stored Procedure&lt;/code&gt;를 사용할 경우 오히려 시스템이 노출될 경우의 위험을 증가시킬 수 있습니다.&lt;br&gt;
가령 &lt;code&gt;db_datareader&lt;/code&gt;, &lt;code&gt;db_datawriter&lt;/code&gt;, &lt;code&gt;db_owner&lt;/code&gt;세 가지 기본 역할이 존재하는 &lt;code&gt;MS SQL Server&lt;/code&gt;에서는 &lt;code&gt;Stored Procedure&lt;/code&gt; 실행을 위해 &lt;code&gt;실행 권한(Execute right)&lt;/code&gt;이 필요하며, 만약 이 세가지 역할만 사용하는 서비스라면 웹앱이 &lt;code&gt;db_owner&lt;/code&gt; 역할로 실행되어야 &lt;code&gt;Stored Procedure&lt;/code&gt;를 사용할 수 있게 됩니다.&lt;br&gt;
따라서 사용자에게 읽기 접근 권한만 할당하기 위해 &lt;code&gt;db_datareader&lt;/code&gt; 역할을 할당하는게 불가능해지며, 공격자는 DB에 대한 모든 권한을 얻게 됩니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;String custname &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; request&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;getParameter&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;customerName&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Stored Procedure를 호출할 때, 매개변수들을 인자로 전달한다.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  CallableStatement cs &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; connection&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;prepareCall&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{call sp_getAccountBalance(?)}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  cs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;setString&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; custname&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ResultSet results &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; cs&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;executeQuery&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// … result set handling
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SQLException se&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// … logging and error handling
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h5 id=&#34;입력-허용-목록을-통한-유효성-검사&#34; &gt;입력 허용 목록을 통한 유효성 검사
&lt;span&gt;
    &lt;a href=&#34;#%ec%9e%85%eb%a0%a5-%ed%97%88%ec%9a%a9-%eb%aa%a9%eb%a1%9d%ec%9d%84-%ed%86%b5%ed%95%9c-%ec%9c%a0%ed%9a%a8%ec%84%b1-%ea%b2%80%ec%82%ac&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;만약 사용자 입력에 의해 변경될 값이 &lt;code&gt;테이블 이름&lt;/code&gt;, &lt;code&gt;컬럼 명&lt;/code&gt; 처럼 &lt;code&gt;바인드 변수&lt;/code&gt;를 할당할 수 없는 위치라면 쿼리를 재설계 하거나, 설명할 &lt;code&gt;입력 유효성 검사&lt;/code&gt;를 수행하는 것이 알맞은 방어책 입니다.&lt;br&gt;
이때, &lt;code&gt;테이블&lt;/code&gt; 또는 &lt;code&gt;컬럼 명&lt;/code&gt;을 사용자 매개변수 값을 통해 전달 받을 경우, 해당 값이 다른 테이블의 다른 컬럼을 이름을 가질 수도 있습니다.&lt;br&gt;
이러한 경우 근본적으로 이를 막도록 &lt;code&gt;코드를 재작성&lt;/code&gt; 하는것이 좋지만, 이는 현실적으로 쉽지 않습니다.
따라서 사용자 매개변수를 &lt;code&gt;예상 가능한 테이블&lt;/code&gt;에 매핑하여 &lt;code&gt;유효하지 않은 사용자 입력&lt;/code&gt;이 쿼리에 &lt;code&gt;포함되는 것을 막아야&lt;/code&gt; 합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;String tableName&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 사용자 매개변수 값에 따라 tableName을 코드에서 지정합니다.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;PARAM&lt;span style=&#34;color:#f92672&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Value1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; tableName &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fooTable&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Value2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; tableName &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;barTable&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; InputValidationException&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unexpected value provided&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                  &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; for table name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;추가로, 꼭 동적 쿼리를 사용해야 한다면 동적 쿼리에 SQL 구문을 삽입할 수 없도록 &lt;code&gt;API&lt;/code&gt; 또는 &lt;code&gt;StoredProcedure&lt;/code&gt;의 매개변수를 가능한 문자열이 아닌 타입으로 받는것이 좋습니다.&lt;br&gt;
즉, 예를 들어 &lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt; 등으로 받게 된다면 안전하게 사용자로부터 입력을 받는것이 가능합니다.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;String&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;someMethod&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;sortOrder&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;String&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;SQLquery&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;some SQL ... order by Salary &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;sortOrder&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ASC&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DESC&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;);&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;`&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;참고&#34; &gt;참고
&lt;span&gt;
    &lt;a href=&#34;#%ec%b0%b8%ea%b3%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/types-of-sql-injection-sqli/&#34;&gt;Types of SQL Injection (SQLi) - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://brightsec.com/blog/sql-injection-attack/&#34;&gt;SQL Injection Attack: How It Works, Examples and Prevention (brightsec.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/ko/docs/Glossary/SQL_Injection&#34;&gt;SQL 인젝션 (SQL Injection) - MDN Web Docs 용어 사전: 웹 용어 정의 | MDN (mozilla.org)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html&#34;&gt;SQL Injection Prevention - OWASP Cheat Sheet Series&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/&#34;&gt;SQL Injection Cheat Sheet | Invicti&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://owasp.org/www-community/attacks/SQL_Injection&#34;&gt;SQL Injection | OWASP Foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://owasp.org/www-community/attacks/Blind_SQL_Injection&#34;&gt;Blind SQL Injection | OWASP Foundation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.boannews.com/media/view.asp?idx=128286&amp;amp;page=1&amp;amp;mkind=&amp;amp;kind=5&amp;amp;skind=J&amp;amp;search=title&amp;amp;find=&#34;&gt;[카드뉴스] ‘오래된 위협, 그러나 여전히 강력한’ SQL 인젝션 (boannews.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bugbountyclub.com/pentestgym/view/53&#34;&gt;Error 기반 SQL 인젝션 | Pentest Gym | 버그바운티클럽 (bugbountyclub.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bugbountyclub.com/pentestgym/view/54&#34;&gt;UNION 기반 SQL 인젝션 | Pentest Gym | 버그바운티클럽 (bugbountyclub.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bugbountyclub.com/pentestgym/view/55&#34;&gt;Blind SQL 인젝션 | Pentest Gym | 버그바운티클럽 (bugbountyclub.com)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>[DB] DB Locking 알아보기</title>
      <link>https://cloudsoswift.github.io/post/develop/database/db-locking/</link>
      <pubDate>Mon, 26 Feb 2024 01:13:22 +0900</pubDate>
      
      <guid>https://cloudsoswift.github.io/post/develop/database/db-locking/</guid>
      <description>&lt;h2 id=&#34;서론&#34; &gt;서론
&lt;span&gt;
    &lt;a href=&#34;#%ec%84%9c%eb%a1%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/orm712/CS-712&#34;&gt;CS 스터디&lt;/a&gt;에서 2월 20일에 발표한 &lt;strong&gt;DB Locking&lt;/strong&gt;에 대해 정리한 문서를 블로그에 공유하고자 한다.&lt;/p&gt;
&lt;h2 id=&#34;db-locking이란&#34; &gt;DB Locking이란?
&lt;span&gt;
    &lt;a href=&#34;#db-locking%ec%9d%b4%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;&lt;em&gt;병행 트랜잭션이 가능한 환경에서&lt;/em&gt;, 변경중인 record를 다른 transaction들이 접근하지 못하도록 막음으로써, 병행 수행 문제를 해결하려는 접근 방법입니다.&lt;br&gt;
이러한 Locking을 위한 규약(Protocol)으로는 &lt;code&gt;Shared Locking Protocol&lt;/code&gt;, &lt;code&gt;2PLP(2-Phase Locking Protocol)&lt;/code&gt;, &lt;code&gt;Multiple Granularity Locking Protocol&lt;/code&gt; 이 있습니다.&lt;/p&gt;
&lt;h3 id=&#34;병행-트랜잭션concurrent-transaction-이란&#34; &gt;병행 트랜잭션(Concurrent Transaction) 이란?
&lt;span&gt;
    &lt;a href=&#34;#%eb%b3%91%ed%96%89-%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98concurrent-transaction-%ec%9d%b4%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;동시에 실행되고 있는 둘 이상의 트랜잭션을 의미합니다.&lt;/p&gt;
&lt;h4 id=&#34;병행-트랜잭션의-장점&#34; &gt;병행 트랜잭션의 장점
&lt;span&gt;
    &lt;a href=&#34;#%eb%b3%91%ed%96%89-%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%98-%ec%9e%a5%ec%a0%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h5 id=&#34;db의-공용도sharability-제고&#34; &gt;DB의 공용도(Sharability) 제고
&lt;span&gt;
    &lt;a href=&#34;#db%ec%9d%98-%ea%b3%b5%ec%9a%a9%eb%8f%84sharability-%ec%a0%9c%ea%b3%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;h5 id=&#34;응답시간response-time-단축&#34; &gt;응답시간(Response Time) 단축
&lt;span&gt;
    &lt;a href=&#34;#%ec%9d%91%eb%8b%b5%ec%8b%9c%ea%b0%84response-time-%eb%8b%a8%ec%b6%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;h5 id=&#34;시스템-활용도system-utilization-증대&#34; &gt;시스템 활용도(System Utilization) 증대
&lt;span&gt;
    &lt;a href=&#34;#%ec%8b%9c%ec%8a%a4%ed%85%9c-%ed%99%9c%ec%9a%a9%eb%8f%84system-utilization-%ec%a6%9d%eb%8c%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;h4 id=&#34;병행-트랜잭션의-동시성-문제&#34; &gt;병행 트랜잭션의 동시성 문제
&lt;span&gt;
    &lt;a href=&#34;#%eb%b3%91%ed%96%89-%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%98-%eb%8f%99%ec%8b%9c%ec%84%b1-%eb%ac%b8%ec%a0%9c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;병행 트랜잭션의 병행 수행률이 상승할수록, 아래와 같은 병행 문제들의 발생률도 상승합니다. &lt;br&gt;
설명의 편의를 위해 병행 실행되는 트랜잭션 두 가지를 아래에서 T1, T2라고 부르도록 하겠습니다.&lt;/p&gt;
&lt;h5 id=&#34;갱신-분실lost-update&#34; &gt;갱신 분실(Lost Update)
&lt;span&gt;
    &lt;a href=&#34;#%ea%b0%b1%ec%8b%a0-%eb%b6%84%ec%8b%a4lost-update&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;img src=&#34;Lost-Update.png&#34; alt=&#34;Lost-Update.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;두 트랜잭션이 병렬로 같은 데이터를 읽고 갱신하는 과정에서, 한 트랜잭션이 다른 트랜잭션의 갱신 값을 덮어쓰는 문제입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예시) T1이 연산 후 갱신 작업을 수행한 뒤, 이후에 T2가 갱신된 값이 아닌 이전의 값을 기준으로 연산 후 갱신 작업을 수행해 T1의 갱신이 무효화 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&#34;모순적-읽기inconsistent-read&#34; &gt;모순적 읽기(Inconsistent Read)
&lt;span&gt;
    &lt;a href=&#34;#%eb%aa%a8%ec%88%9c%ec%a0%81-%ec%9d%bd%ea%b8%b0inconsistent-read&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;두 트랜잭션이 병렬로 같은 데이터를 읽고 갱신하는 과정에서, 데이터 불일치가 발생하는 문제입니다.&lt;/p&gt;
&lt;h6 id=&#34;dirty-read&#34; &gt;Dirty Read
&lt;span&gt;
    &lt;a href=&#34;#dirty-read&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;&lt;img src=&#34;Dirty-Read.png&#34; alt=&#34;Dirty-Read.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;격리성 수준이 &lt;code&gt;Read Uncommitted&lt;/code&gt; 이하인 환경에서 발생가능한 문제로, 한 트랜잭션이 다른 트랜잭션으로부터 &lt;strong&gt;커밋되지 않은 값을 읽어 발생&lt;/strong&gt;하는 문제입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예시) T1이 커밋되기 전, 중간에 T2가 T1에서 작업하던 데이터(&lt;em&gt;T1의 &lt;strong&gt;수정&lt;/strong&gt;이 &lt;strong&gt;반영되지 않은&lt;/strong&gt;&lt;/em&gt;)을 읽고 작업을 수행해 T1 연산 이전의 값으로 T2가 수행되게 됩니다. 이는 정확하지 않거나 일관되지 않은 결과를 야기할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h6 id=&#34;non-repeatable-read&#34; &gt;Non-repeatable Read
&lt;span&gt;
    &lt;a href=&#34;#non-repeatable-read&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;&lt;img src=&#34;Non-repeatable-Read.png&#34; alt=&#34;Non-repeatable-Read.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;같은 데이터를 한 트랜잭션 내에서 읽었음에도, 둘의 값이 다른 문제입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예시) T1이 한 데이터를 두 번 읽을 때, 중간에 T2가 해당 데이터의 값을 변경한 뒤 커밋하게 되면 두 번째로 읽었을 때의 값은 처음 읽었던 값과 다르게 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h6 id=&#34;phantom-read&#34; &gt;Phantom Read
&lt;span&gt;
    &lt;a href=&#34;#phantom-read&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;&lt;img src=&#34;Phantom-Read.png&#34; alt=&#34;Phantom-Read.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;같은 조건에 대한 검색을 한 트랜잭션 내에서 수행했음에도, 다시 읽으려 할 때 이전에 존재하던 값이 없어지거나, 새로운 값이 추가로 검색되는 문제입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예시) T1이 한 데이터를 두 번 읽을 때, 중간에 T2가 해당 데이터를 삭제한 뒤 커밋하게 되면 두 번째로 읽었을 때 해당 데이터는 존재하지 않게 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h5 id=&#34;연쇄적-롤백cascading-rollback&#34; &gt;연쇄적 롤백(Cascading Rollback)
&lt;span&gt;
    &lt;a href=&#34;#%ec%97%b0%ec%87%84%ec%a0%81-%eb%a1%a4%eb%b0%b1cascading-rollback&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;img src=&#34;Cascading-Rollback.png&#34; alt=&#34;Cascading-Rollback.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;한 트랜잭션이 갱신한 데이터를 다른 트랜잭션이 또 다시 갱신한 뒤, 앞선 트랜잭션을 롤백하려할 때 이후 실행했던 트랜잭션도 롤백해야 하나 이미 해당 트랜잭션은 완료되어 롤백이 불가능한 문제입니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;예시) T1이 한 데이터를 갱신한 뒤, T2이 해당 데이터를 또 갱신한 뒤 완료처리한 상태에서 T1을 롤백하려 하면 T2이 처리한 부분에 대해서는 롤백이 불가능하게 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;transaction-schedule이란&#34; &gt;Transaction Schedule이란?
&lt;span&gt;
    &lt;a href=&#34;#transaction-schedule%ec%9d%b4%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;트랜잭션들이 연산을 실행하는 순서를 의미합니다.&lt;br&gt;
스케줄의 개수는 &lt;code&gt;Interleaving(트랜잭션을 쪼개서 수행하는 것)&lt;/code&gt;이 가능한 경우 거의 무한대이고, 허용되지 않으면 $n!$ 개 입니다.&lt;br&gt;
병행 수행상 문제가 야기되느냐 그렇지 않느냐에 따라 직렬/비직렬 스케줄로 나뉩니다.&lt;/p&gt;
&lt;h4 id=&#34;직렬-스케줄serial-schedule&#34; &gt;직렬 스케줄(serial Schedule)
&lt;span&gt;
    &lt;a href=&#34;#%ec%a7%81%eb%a0%ac-%ec%8a%a4%ec%bc%80%ec%a4%84serial-schedule&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;스케줄에 포함된 모든 트랜잭션이 하나씩 실행되는 스케줄을 의미합니다.&lt;br&gt;
병행 수행의 문제가 발생하지 않으나, 병행 트랜잭션으로 실행되지 않게 됩니다.&lt;/p&gt;
&lt;h4 id=&#34;비직렬-스케줄non-serial-schedule&#34; &gt;비직렬 스케줄(non-serial Schedule)
&lt;span&gt;
    &lt;a href=&#34;#%eb%b9%84%ec%a7%81%eb%a0%ac-%ec%8a%a4%ec%bc%80%ec%a4%84non-serial-schedule&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;스케줄에 포함된 모든 트랜잭션이 서로 interleaved되는 스케줄을 의미합니다.&lt;br&gt;
같은 트랜잭션 내 작업이라도 쪼개서 수행될 수 있기 때문에 쪼개진 작업이 실행되는 시점에 따라 잘못된 결과를 얻을 수 있습니다.&lt;/p&gt;
&lt;h5 id=&#34;직렬-가능-스케줄serializable-schedule&#34; &gt;직렬 가능 스케줄(serializable Schedule)
&lt;span&gt;
    &lt;a href=&#34;#%ec%a7%81%eb%a0%ac-%ea%b0%80%eb%8a%a5-%ec%8a%a4%ec%bc%80%ec%a4%84serializable-schedule&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;어떤 직렬 스케줄과 &lt;strong&gt;동등&lt;/strong&gt;한 비직렬 스케줄을 의미합니다.&lt;br&gt;
&lt;strong&gt;모든 충돌 직렬 가능 스케줄&lt;/strong&gt;은 &lt;strong&gt;뷰 직렬 가능 스케줄&lt;/strong&gt;이지만, &lt;em&gt;&lt;strong&gt;역은 성립하지 않습니다&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;h6 id=&#34;충돌-직렬-가능-스케줄&#34; &gt;충돌 직렬 가능 스케줄
&lt;span&gt;
    &lt;a href=&#34;#%ec%b6%a9%eb%8f%8c-%ec%a7%81%eb%a0%ac-%ea%b0%80%eb%8a%a5-%ec%8a%a4%ec%bc%80%ec%a4%84&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;비직렬 스케줄 S에 대해 &lt;strong&gt;충돌 동등&lt;/strong&gt;한 직렬 스케줄 S&amp;rsquo;가 존재하면, S를 &lt;code&gt;충돌 직렬 가능 스케줄&lt;/code&gt; 이라고 합니다.&lt;/p&gt;
&lt;h6 id=&#34;뷰-직렬-가능-스케줄&#34; &gt;뷰 직렬 가능 스케줄
&lt;span&gt;
    &lt;a href=&#34;#%eb%b7%b0-%ec%a7%81%eb%a0%ac-%ea%b0%80%eb%8a%a5-%ec%8a%a4%ec%bc%80%ec%a4%84&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;비직렬 스케줄 S에 대해 &lt;strong&gt;뷰 동등&lt;/strong&gt;한 직렬 스케줄 S&amp;rsquo;가 존재하면, S를 &lt;code&gt;뷰 직렬 가능 스케줄&lt;/code&gt; 이라고 합니다.&lt;/p&gt;
&lt;h5 id=&#34;스케줄-동등&#34; &gt;스케줄 동등
&lt;span&gt;
    &lt;a href=&#34;#%ec%8a%a4%ec%bc%80%ec%a4%84-%eb%8f%99%eb%93%b1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;h6 id=&#34;결과result-동등&#34; &gt;결과(result) 동등
&lt;span&gt;
    &lt;a href=&#34;#%ea%b2%b0%ea%b3%bcresult-%eb%8f%99%eb%93%b1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;결과가 동일한 스케줄을 의미합니다.&lt;/p&gt;
&lt;h6 id=&#34;충돌conflict-동등&#34; &gt;충돌(conflict) 동등
&lt;span&gt;
    &lt;a href=&#34;#%ec%b6%a9%eb%8f%8cconflict-%eb%8f%99%eb%93%b1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;충돌 연산의 순서가 동일한 스케줄을 의미합니다.&lt;/p&gt;
&lt;h6 id=&#34;뷰view-동등&#34; &gt;뷰(view) 동등
&lt;span&gt;
    &lt;a href=&#34;#%eb%b7%b0view-%eb%8f%99%eb%93%b1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;스케줄 S1, S2에 포함된 트랜잭션이 같고 아래 조건을 만족하는 경우를 의미합니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;S1에서 $T_i$가 $x$의 초기 값을 읽는다면, S2에서도 그러해야 합니다.&lt;/li&gt;
&lt;li&gt;S1에서 $T_i$의 모든 read(x)가 $T_j$가 write한 x값을 읽는다면, S2에서도 그러해야 합니다.&lt;/li&gt;
&lt;li&gt;S1에서 $T_i$가 write(x)를 마지막으로 수행하면, S2에서도 그러해야 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;lock-이란&#34; &gt;Lock 이란?
&lt;span&gt;
    &lt;a href=&#34;#lock-%ec%9d%b4%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;DB상의 데이터 항목에 대한 잠금장치입니다.&lt;br&gt;
Lock이 걸린 데이터 항목은 Lock을 건 트랜잭션만 접근할 수 있습니다.&lt;br&gt;
Lcok은 Lock을 건 트랜잭션에 의해서만 Unlock할 수 있습니다.&lt;/p&gt;
&lt;h4 id=&#34;lock의-종류&#34; &gt;Lock의 종류
&lt;span&gt;
    &lt;a href=&#34;#lock%ec%9d%98-%ec%a2%85%eb%a5%98&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h5 id=&#34;공용-로크shared-lock-s-lock&#34; &gt;공용 로크(Shared Lock, S-Lock)
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%b5%ec%9a%a9-%eb%a1%9c%ed%81%acshared-lock-s-lock&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;다른 트랜잭션이 해당 데이터를 Read 할 수 있습니다.&lt;/p&gt;
&lt;h5 id=&#34;전용-로크exclusive-lock-x-lock&#34; &gt;전용 로크(Exclusive Lock, X-Lock)
&lt;span&gt;
    &lt;a href=&#34;#%ec%a0%84%ec%9a%a9-%eb%a1%9c%ed%81%acexclusive-lock-x-lock&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;다른 트랜잭션이 해당 데이터를 Read/Write 할 수 없습니다.&lt;/p&gt;
&lt;h4 id=&#34;로크-단위lock-granularity&#34; &gt;로크 단위(Lock granularity)
&lt;span&gt;
    &lt;a href=&#34;#%eb%a1%9c%ed%81%ac-%eb%8b%a8%ec%9c%84lock-granularity&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;row, table, database 등 Locking할 자원의 크기를 말합니다.&lt;br&gt;
단위의 크기가 커질수록 병행성 수준은 낮아지고, 병행 제어 기법은 간단해집니다.&lt;/p&gt;
&lt;h4 id=&#34;로크-호환성-lock-compatibility&#34; &gt;로크 호환성 (Lock Compatibility)
&lt;span&gt;
    &lt;a href=&#34;#%eb%a1%9c%ed%81%ac-%ed%98%b8%ed%99%98%ec%84%b1-lock-compatibility&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;이미 자원에 특정 Lock이 설정되어 있는 경우, 다른 트랜잭션도 해당 자원에 대해 Lock을 설정할 수 있는지 여부를 말합니다.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구 분&lt;/th&gt;
&lt;th&gt;Request S-lock&lt;/th&gt;
&lt;th&gt;Request X-lock&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S-locked data item&lt;/td&gt;
&lt;td&gt;ok&lt;/td&gt;
&lt;td&gt;not ok&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;X-locked data item&lt;/td&gt;
&lt;td&gt;not ok&lt;/td&gt;
&lt;td&gt;not ok&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;locking-protocol&#34; &gt;Locking Protocol
&lt;span&gt;
    &lt;a href=&#34;#locking-protocol&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;아래 설명된 Protocol들 이외에도 기본적인 Locking Protocol은 다음과 같습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;트랜잭션 T가 x에 대해 read(x)/write(x) 연산을 하려면 먼저 lock(x) 연산을 실행해야 한다.&lt;/li&gt;
&lt;li&gt;트랜잭션 T가 실행한 lock(x)에 대해서는 T가 모든 실행(Task)을 종료하기 전에 unlock(x) 연산을 수행해야 한다.&lt;/li&gt;
&lt;li&gt;트랜잭션 T는 &lt;em&gt;다른 트랜잭션에 의해 lock이 걸려있는&lt;/em&gt; x에 대해 &lt;strong&gt;lock(x)&lt;/strong&gt; 를 &lt;strong&gt;실행할 수 없다&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;트랜잭션 T는 &lt;em&gt;자신이 lock을 걸지않은 x&lt;/em&gt;에 대해 &lt;strong&gt;unlock(x)&lt;/strong&gt; 을 &lt;strong&gt;실행할 수 없다&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;shared-locking-protocol공용-로킹-규약&#34; &gt;&lt;code&gt;Shared Locking Protocol(공용 로킹 규약)&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#shared-locking-protocol%ea%b3%b5%ec%9a%a9-%eb%a1%9c%ed%82%b9-%ea%b7%9c%ec%95%bd&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;트랜잭션 T는 &lt;strong&gt;read(x)&lt;/strong&gt; 전 반드시 &lt;mark style=&#34;background: #ADCCFFA6;&#34;&gt;lock-S(x)&lt;/mark&gt; 또는 &lt;mark style=&#34;background: #FFB86CA6;&#34;&gt;lock-X(x)&lt;/mark&gt;를 실행해야 함.&lt;/li&gt;
&lt;li&gt;트랜잭션 T는 &lt;strong&gt;write(x)&lt;/strong&gt; 전 반드시 &lt;mark style=&#34;background: #FFB86CA6;&#34;&gt;lock-X(x)&lt;/mark&gt;를 실행해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이러한 규약 때문에 공용 로킹 규약은 &lt;strong&gt;&lt;code&gt;직렬가능성(serializability)&lt;/code&gt;&lt;/strong&gt; 을 보장하지 못합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;직렬가능성(serializability)&lt;/code&gt;&lt;/strong&gt; : 비직렬 스케줄을 직렬 스케줄로 변환할 수 있는지를 의미합니다.
&lt;ul&gt;
&lt;li&gt;lock과 unlock이 병렬로 수행될 수 있으므로 병행 처리되는 트랜잭션들이 서로 간섭할 수 있어 직렬 가능성이 보장되지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;2plp2-phase-locking-protocol-2단계-로킹-규약&#34; &gt;&lt;code&gt;2PLP(2-Phase Locking Protocol, 2단계 로킹 규약)&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#2plp2-phase-locking-protocol-2%eb%8b%a8%ea%b3%84-%eb%a1%9c%ed%82%b9-%ea%b7%9c%ec%95%bd&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;lock만 가능한 Phase와 unlock만 가능한 phase를 나누어 로킹을 수행하는 규약입니다.&lt;br&gt;
&lt;code&gt;직렬가능성&lt;/code&gt;을 &lt;strong&gt;보장&lt;/strong&gt;하지만, &lt;strong&gt;&lt;code&gt;Deadlock&lt;/code&gt;&lt;/strong&gt; 문제가 존재하는 규약입니다.&lt;br&gt;
변형으로는 &lt;code&gt;Strict 2PLP&lt;/code&gt;, &lt;code&gt;Rigorous 2PLP&lt;/code&gt;가 존재하며, 상용 DBMS에서는 이 둘 중 하나를 사용합니다.&lt;/p&gt;
&lt;h5 id=&#34;1-단계growing-phase&#34; &gt;1 단계(Growing Phase)
&lt;span&gt;
    &lt;a href=&#34;#1-%eb%8b%a8%ea%b3%84growing-phase&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;트랜잭션은 계속해 lock을 획득할 수 있으나, unlock 연산은 실행할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;2-단계shrink-phase&#34; &gt;2 단계(Shrink Phase)
&lt;span&gt;
    &lt;a href=&#34;#2-%eb%8b%a8%ea%b3%84shrink-phase&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;unlock 연산만 실행할 수 있으며, 일단 Lock을 해제하면 더 이상 lock을 획득할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id=&#34;strict-2plp엄격-2단계-로킹-규약&#34; &gt;Strict 2PLP(엄격 2단계 로킹 규약)
&lt;span&gt;
    &lt;a href=&#34;#strict-2plp%ec%97%84%ea%b2%a9-2%eb%8b%a8%ea%b3%84-%eb%a1%9c%ed%82%b9-%ea%b7%9c%ec%95%bd&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;ul&gt;
&lt;li&gt;2PLP에 &amp;lsquo;모든 &lt;strong&gt;X-lock&lt;/strong&gt;은 &lt;em&gt;트랜잭션 완료시까지&lt;/em&gt; &lt;strong&gt;unlock 할 수 없다&lt;/strong&gt;&amp;lsquo;는 규칙이 추가된 형태입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;구현이 어려우나 성능이 높고&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;연쇄 복귀 문제(Cascading Rollback)&lt;/code&gt;&lt;/strong&gt; 가 발생하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id=&#34;rigorous-2plp엄밀-2단계-로킹-규약&#34; &gt;Rigorous 2PLP(엄밀 2단계 로킹 규약)
&lt;span&gt;
    &lt;a href=&#34;#rigorous-2plp%ec%97%84%eb%b0%80-2%eb%8b%a8%ea%b3%84-%eb%a1%9c%ed%82%b9-%ea%b7%9c%ec%95%bd&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;ul&gt;
&lt;li&gt;2PLP에 &amp;lsquo;모든 &lt;strong&gt;lock&lt;/strong&gt;은 &lt;em&gt;트랜잭션 완료시까지&lt;/em&gt; &lt;strong&gt;unlock 할 수 없다&lt;/strong&gt;&amp;lsquo;는 규칙이 추가된 형태입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;구현은 쉬우나 성능이 낮다&lt;/strong&gt;는 단점이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;multiple-granularity-locking-protocol다중-단위-로킹-규약&#34; &gt;&lt;code&gt;Multiple Granularity Locking Protocol(다중 단위 로킹 규약)&lt;/code&gt;
&lt;span&gt;
    &lt;a href=&#34;#multiple-granularity-locking-protocol%eb%8b%a4%ec%a4%91-%eb%8b%a8%ec%9c%84-%eb%a1%9c%ed%82%b9-%ea%b7%9c%ec%95%bd&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;병행성 수준을 감소시키지 않기 위해, 필요 이상의 크기로 locking 하지 않는 방법입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;로킹 계층 트리 : DB -&amp;gt; 구역(Area) -&amp;gt; 파일(File) -&amp;gt; 레코드(Record)
&lt;img src=&#34;Multi-Granularity-tree-Hiererchy.png&#34; alt=&#34;Multi-Granularity-tree-Hiererchy.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;DB: 모든 파일을 포함하는 데이터베이스입니다. 데이터베이스는 여러 파일로 구성됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;구역(Area): 파일들로 이뤄진 데이터베이스 내 특정 영역입니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;파일(File): 관련된 레코드들의 그룹입니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;레코드(Record): DB 테이블에서 하나의 행입니다. 레코드는 여러 필드로 구성됩니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;optimistic-lockpessimistic-lock란&#34; &gt;Optimistic Lock/Pessimistic Lock란?
&lt;span&gt;
    &lt;a href=&#34;#optimistic-lockpessimistic-lock%eb%9e%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;h3 id=&#34;낙관적-로크optimistic-lock&#34; &gt;낙관적 로크(Optimistic Lock)
&lt;span&gt;
    &lt;a href=&#34;#%eb%82%99%ea%b4%80%ec%a0%81-%eb%a1%9c%ed%81%acoptimistic-lock&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;다른 트랜잭션과 충돌하지 않는다고 가정하고, 별도의 Locking 없이 자원에 접근하는 것을 말합니다.&lt;br&gt;
병행 제어를 위해 아래 세 과정을 수행하며, 각 과정마다 Start(T), Validation(T), Finish(T) 세 가지의 &lt;strong&gt;&lt;code&gt;타임스탬프&lt;/code&gt;&lt;/strong&gt; 를 사용합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;타임스탬프&lt;/code&gt;&lt;/strong&gt; : 시스템에서 &lt;strong&gt;트랜잭션&lt;/strong&gt;을 &lt;strong&gt;유일하게 식별&lt;/strong&gt;하기 위해 부여한 &lt;strong&gt;식별자(identifier)&lt;/strong&gt; 로, 트랜잭션이 &lt;strong&gt;시스템에 들어온 순서대로&lt;/strong&gt; 부여합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;과정&#34; &gt;과정
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%bc%ec%a0%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;판독 단계(Read Step)&lt;/code&gt; : 트랜잭션에 필요한 자료를 DB로 부터 읽어 &lt;strong&gt;Local Working Area에 복사&lt;/strong&gt;합니다. 이후 &lt;strong&gt;모든 갱신은 사본을 대상&lt;/strong&gt;으로 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;확인 단계(Validation Step)&lt;/code&gt;: &lt;strong&gt;직렬(Serialization) 가능성 위반 여부&lt;/strong&gt;를 &lt;strong&gt;검사&lt;/strong&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;기록 단계(Write Step)&lt;/code&gt;: 확인 단계를 통과하면 &lt;strong&gt;DB에 반영&lt;/strong&gt;하고, &lt;em&gt;통과하지 못했다면 실행 결과는 취소&lt;/em&gt;하고 트랜잭션은 복귀합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;비관적-로크pessimistic-lock&#34; &gt;비관적 로크(Pessimistic Lock)
&lt;span&gt;
    &lt;a href=&#34;#%eb%b9%84%ea%b4%80%ec%a0%81-%eb%a1%9c%ed%81%acpessimistic-lock&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;다른 트랜잭션과 충돌한다고 가정하고, 트랜잭션을 처리하기 전에 자원에 대해 Locking을 시도하는것을 말합니다.&lt;/p&gt;
&lt;h4 id=&#34;과정-1&#34; &gt;과정
&lt;span&gt;
    &lt;a href=&#34;#%ea%b3%bc%ec%a0%95-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;자원에 대해 Lock을 겁니다.&lt;/li&gt;
&lt;li&gt;트랜잭션을 실행합니다.&lt;/li&gt;
&lt;li&gt;자원에 대해 Unlock을 수행합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;트랜잭션이-비정상-종료된-경우-lock을-해제할-해결책이-있는가-없다면-직접-해결-가능한가&#34; &gt;트랜잭션이 비정상 종료된 경우 Lock을 해제할 해결책이 있는가? 없다면 직접 해결 가능한가?
&lt;span&gt;
    &lt;a href=&#34;#%ed%8a%b8%eb%9e%9c%ec%9e%ad%ec%85%98%ec%9d%b4-%eb%b9%84%ec%a0%95%ec%83%81-%ec%a2%85%eb%a3%8c%eb%90%9c-%ea%b2%bd%ec%9a%b0-lock%ec%9d%84-%ed%95%b4%ec%a0%9c%ed%95%a0-%ed%95%b4%ea%b2%b0%ec%b1%85%ec%9d%b4-%ec%9e%88%eb%8a%94%ea%b0%80-%ec%97%86%eb%8b%a4%eb%a9%b4-%ec%a7%81%ec%a0%91-%ed%95%b4%ea%b2%b0-%ea%b0%80%eb%8a%a5%ed%95%9c%ea%b0%80&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;잘 설계된 DBMS에서는 Lock이 오랫동안 유지되어 Deadlock과 같은 상황을 발생시키지 않도록 여러 대비책을 갖고 있으며, 대부분의 DBMS에서는 Lock 관리를 위한 기능을 제공합니다.&lt;/p&gt;
&lt;h3 id=&#34;lock-timeout&#34; &gt;Lock Timeout
&lt;span&gt;
    &lt;a href=&#34;#lock-timeout&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;Lock을 걸 때, 타임아웃을 설정해 일정시간이 지나면 자동으로 Lock을 해제하도록 합니다.&lt;/p&gt;
&lt;h3 id=&#34;deadlock-detection&#34; &gt;Deadlock Detection
&lt;span&gt;
    &lt;a href=&#34;#deadlock-detection&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;교착상태가 발생하면 사후에 트랜잭션들 중 하나를 강제종료(&lt;code&gt;rollback&lt;/code&gt;) 시키는 조치를 취하는 방식입니다.&lt;/p&gt;
&lt;h3 id=&#34;일반적인-회복-방법&#34; &gt;일반적인 회복 방법
&lt;span&gt;
    &lt;a href=&#34;#%ec%9d%bc%eb%b0%98%ec%a0%81%ec%9d%b8-%ed%9a%8c%eb%b3%b5-%eb%b0%a9%eb%b2%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;이외에도 Redo, Undo와 같은 회복 방법을 통해 트랜잭션으로 손상된 부분을 회복시킬 수 있습니다.&lt;/p&gt;
&lt;h4 id=&#34;redo-media-recovery&#34; &gt;Redo (Media Recovery)
&lt;span&gt;
    &lt;a href=&#34;#redo-media-recovery&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;비소멸장치(디스크, 테이프 등)의 내용 손상에 대한 회복 기법입니다.&lt;br&gt;
가장 최근의 복제본(dump)을 적재시키고, 해당 복제본 이후의 변경을 log를 이용해 재실행하여 DB를 복원합니다.&lt;/p&gt;
&lt;h4 id=&#34;undo&#34; &gt;Undo
&lt;span&gt;
    &lt;a href=&#34;#undo&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;log를 이용해 모든 변경을 취소시키므로써 DB를 복원합니다.&lt;/p&gt;
&lt;h4 id=&#34;소멸-장치의-정보-회복&#34; &gt;소멸 장치의 정보 회복
&lt;span&gt;
    &lt;a href=&#34;#%ec%86%8c%eb%a9%b8-%ec%9e%a5%ec%b9%98%ec%9d%98-%ec%a0%95%eb%b3%b4-%ed%9a%8c%eb%b3%b5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h5 id=&#34;log-이용-회복&#34; &gt;Log 이용 회복
&lt;span&gt;
    &lt;a href=&#34;#log-%ec%9d%b4%ec%9a%a9-%ed%9a%8c%eb%b3%b5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;트랜잭션이 Write 연산을 실행하거나, 트랜잭션의 시작/완료/철회와 같은 특별 활동시 기록되는 Log를 활용해 회복하는 방법입니다.&lt;br&gt;
Log는 &lt;code&gt;On-line log(실행중인 트랜잭션에 대한 로그)&lt;/code&gt;, &lt;code&gt;Archival log(누적되는 로그를 안정 저장장치에 저장한 것)&lt;/code&gt;로 나뉩니다.&lt;/p&gt;
&lt;h6 id=&#34;지연-갱신deferred-update의-회복&#34; &gt;지연 갱신(Deferred Update)의 회복
&lt;span&gt;
    &lt;a href=&#34;#%ec%a7%80%ec%97%b0-%ea%b0%b1%ec%8b%a0deferred-update%ec%9d%98-%ed%9a%8c%eb%b3%b5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;트랜잭션이 부분 완료될 때 까지 DB 변경내역을 log에 전부 기록한 뒤, 부분 완료되면 보류시킨 Output 연산을 log를 사용해 처리합니다.&lt;br&gt;
트랜잭션 &lt;strong&gt;실행 중 장애가 발생&lt;/strong&gt;했다면 &lt;strong&gt;처음부터 다시 실행&lt;/strong&gt;하고, &lt;strong&gt;완료 후 장애가 발생&lt;/strong&gt;했다면 &lt;strong&gt;Log을 사용해 트랜잭션을 Redo&lt;/strong&gt; 합니다.&lt;/p&gt;
&lt;h6 id=&#34;즉시-갱신immediate-update의-회복&#34; &gt;즉시 갱신(Immediate Update)의 회복
&lt;span&gt;
    &lt;a href=&#34;#%ec%a6%89%ec%8b%9c-%ea%b0%b1%ec%8b%a0immediate-update%ec%9d%98-%ed%9a%8c%eb%b3%b5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h6&gt;&lt;p&gt;트랜잭션이 실행되는 동안 발생한 변경 내용을 DB에 그대로 반영해 처리합니다.&lt;br&gt;
트랜잭션 &lt;strong&gt;실행 중 장애가 발생&lt;/strong&gt;했다면 해당 &lt;strong&gt;트랜잭션에 대한 Undo&lt;/strong&gt;를 실행하고, &lt;strong&gt;완료 후 장애가 발생&lt;/strong&gt;했다면 &lt;strong&gt;트랜잭션을 Redo&lt;/strong&gt; 합니다.&lt;/p&gt;
&lt;h5 id=&#34;검사시점check-point-회복&#34; &gt;검사시점(Check Point) 회복
&lt;span&gt;
    &lt;a href=&#34;#%ea%b2%80%ec%82%ac%ec%8b%9c%ec%a0%90check-point-%ed%9a%8c%eb%b3%b5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;&lt;em&gt;Log를 이용할 경우&lt;/em&gt; Redo/Undo 대상 트랜잭션을 찾기위해 &lt;strong&gt;log 전체를 조사&lt;/strong&gt;하거나,&lt;strong&gt;불필요한 Redo를 반복&lt;/strong&gt;한다는 &lt;strong&gt;문제를 해결&lt;/strong&gt;하기 위해 일정 간격으로 &lt;strong&gt;CheckPoint를 설치&lt;/strong&gt;해 이를 사용하는 기법입니다.&lt;br&gt;
Log를 차례로 검사하며 트랜잭션의 start를 만났다면 해당 트랜잭션을 Undo-list에, 트랜잭션의 commit을 만났다면 Undo-list에서 삭제하고 Redo-list에 추가합니다. 이후 Undo-list의 트랜잭션을 log에 기록된 역순으로 Undo를, Redo-list의 트랜잭션을 log에 기록된 순서로 Redo를 수행합니다.&lt;/p&gt;
&lt;h5 id=&#34;그림자-페이징shadow-paging-기법&#34; &gt;그림자 페이징(Shadow Paging) 기법
&lt;span&gt;
    &lt;a href=&#34;#%ea%b7%b8%eb%a6%bc%ec%9e%90-%ed%8e%98%ec%9d%b4%ec%a7%95shadow-paging-%ea%b8%b0%eb%b2%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;p&gt;트랜잭션을 실행하는 동안 2개의 page table을 유지하는 방법입니다.&lt;br&gt;
current page table은 write 연산을 실행할 때 변경하며, shadow page table은 트랜잭션 실행 직전의 상태를 유지합니다.&lt;br&gt;
트랜잭션 완료 전 장애가 발생한 경우 shadow page table을 복사해 실행 직전으로 복귀시킵니다.&lt;/p&gt;
&lt;h2 id=&#34;참고-자료&#34; &gt;참고 자료
&lt;span&gt;
    &lt;a href=&#34;#%ec%b0%b8%ea%b3%a0-%ec%9e%90%eb%a3%8c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;전공과목 강의자료&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Isolation_(database_systems)&#34;&gt;Isolation (database systems) - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/dbms-dirty-read-in-sql/&#34;&gt;Dirty Read in SQL - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/concurrency-problems-in-dbms-transactions/&#34;&gt;Concurrency problems in DBMS Transactions - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.jidum.com/jidums/view.do?jidumId=282&#34;&gt;동시성제어개요 - 지식덤프&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/serializability-in-dbms/&#34;&gt;Serializability in DBMS - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch05.html&#34;&gt;Chapter 5. Locking - Hibernate Community Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/lock-based-concurrency-control-protocol-in-dbms/&#34;&gt;Lock Based Concurrency Control Protocol in DBMS - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.ibm.com/docs/en/db2/11.5?topic=overview-optimistic-locking&#34;&gt;Optimistic locking - IBM Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://help.sap.com/doc/saphelp_nw73ehp1/7.31.19/en-us/47/dc35af5bc33b8be10000000a421937/content.htm?no_cache=true&#34;&gt;How Optimistic Locks Work - SAP Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://magicsoftware.my.salesforce-sites.com/PublicKnowledge/articles/bl_Reference/Physical-Locks-xpa-3x&#34;&gt;Reference: Physical Locks (Magic xpa 3.x) - Salesforce&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/multiple-granularity-locking-in-dbms/&#34;&gt;Multiple Granularity Locking in DBMS - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html&#34;&gt;MySQL :: MySQL 8.0 Reference Manual :: 17.7.1 InnoDB Locking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.umsl.edu/~joshik/msis480/chapt06.htm&#34;&gt;6 Database Management - University of Missouri–St. Louis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>[자료구조] B Tree와 B&#43;tree 알아보기</title>
      <link>https://cloudsoswift.github.io/post/develop/database/b-tree-b&#43;tree/</link>
      <pubDate>Sun, 18 Feb 2024 09:58:46 +0900</pubDate>
      
      <guid>https://cloudsoswift.github.io/post/develop/database/b-tree-b&#43;tree/</guid>
      <description>&lt;h1 id=&#34;서론&#34; &gt;서론
&lt;span&gt;
    &lt;a href=&#34;#%ec%84%9c%eb%a1%a0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://github.com/orm712/CS-712&#34;&gt;CS 스터디&lt;/a&gt;에서 2월 13일에 발표한(정확히는 나는 2일 뒤인 15일에 발표했다.) &lt;strong&gt;B 트리와 B+ 트리&lt;/strong&gt;에 대해 정리한 문서를 블로그에 공유하고자 한다.&lt;/p&gt;
&lt;h1 id=&#34;b-tree와-btree는-무엇일까&#34; &gt;B-Tree와 B+Tree는 무엇일까
&lt;span&gt;
    &lt;a href=&#34;#b-tree%ec%99%80-btree%eb%8a%94-%eb%ac%b4%ec%97%87%ec%9d%bc%ea%b9%8c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;h2 id=&#34;b-트리-b-tree&#34; &gt;B 트리 (B-Tree)
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac-b-tree&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;&lt;img src=&#34;B-tree-architecture.png&#34; alt=&#34;B-tree-architecture.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;이진 트리를 확장해 한 노드가 가질 수 있는 자식 노드의 갯수가 2개 이상인 &lt;code&gt;자가 균형 이진 검색 트리(Self Balancing Binary Search Tree)&lt;/code&gt;의 일종이며, 각 노드가 갖고있는 키 들은 정렬되어 있습니다.&lt;br&gt;
다른 자체 균형 이진 검색 트리와 달리, B 트리는 DB, File System과 같이 큰 데이터 블록을 읽고 써야하는 스토리지 시스템에 적합합니다.&lt;/p&gt;
&lt;h3 id=&#34;b-트리의-성질&#34; &gt;B 트리의 성질
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ec%84%b1%ec%a7%88&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;차수 m(&lt;em&gt;노드 중 가장 많은 자식을 갖는 노드의 자식 수&lt;/em&gt;)을 갖는 B 트리는 아래와 같은 성질을 만족합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 노드는 최대 m개의 자식이 존재합니다.&lt;/li&gt;
&lt;li&gt;모든 내부 노드는 최소 ⌈m/2⌉ 개의 자식이 존재합니다.&lt;/li&gt;
&lt;li&gt;루트 노드는 (&lt;em&gt;리프가 아닌 한&lt;/em&gt;) 최소 2개의 자식이 존재합니다.&lt;/li&gt;
&lt;li&gt;k개의 자식이 있는 &lt;em&gt;리프가 아닌&lt;/em&gt; 노드는 k-1 개의 키를 갖고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;b-트리의-노드들&#34; &gt;B 트리의 노드들
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%eb%85%b8%eb%93%9c%eb%93%a4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;B 트리를 이루는 노드는 내부 노드, 루트 노드, 리프 노드로 구성됩니다.&lt;/p&gt;
&lt;h4 id=&#34;내부-노드-internal-node&#34; &gt;내부 노드 (Internal Node)
&lt;span&gt;
    &lt;a href=&#34;#%eb%82%b4%eb%b6%80-%eb%85%b8%eb%93%9c-internal-node&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;em&gt;적어도 하나의 자식&lt;/em&gt;을 갖는 노드로, &lt;em&gt;리프 노드와 루트 노드를 제외&lt;/em&gt;한 &lt;strong&gt;모든 노드&lt;/strong&gt;입니다.&lt;br&gt;
이들은 일반적으로 하위 포인터, 데이터 포인터, 검색 키의 순서 집합으로 표현됩니다.&lt;br&gt;
모든 &lt;code&gt;내부 노드&lt;/code&gt;는 최대 U개에서 최소 L개의 자식을 포함합니다. 따라서 &lt;code&gt;내부 노드&lt;/code&gt; 내 요소 수는 &amp;lsquo;하위 포인터 수 - 1&amp;rsquo; 입니다. (요소 수는 L-1 보다 높고, U-1 보다 낮습니다.)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;따라서 U는 2L 또는 2L - 1 이고, 각 &lt;code&gt;내부 노드&lt;/code&gt;들은 &lt;strong&gt;최소 절반&lt;/strong&gt; 이상 채워져 있습니다.
&lt;ul&gt;
&lt;li&gt;이는 두 &lt;em&gt;절반이 가득 찬&lt;/em&gt; 내부 노드를 하나의 노드로 &lt;strong&gt;병합하거나&lt;/strong&gt;, 하나의 완전한 노드를 두 개의 정상적인 노드로 &lt;strong&gt;나눌 수 있음&lt;/strong&gt;을 의미합니다.&lt;/li&gt;
&lt;li&gt;이러한 점을 통해, B 트리는 새 값을 삽입하거나 삭제하고 &lt;em&gt;B 트리 속성을 유지하도록&lt;/em&gt; 트리를 조절할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;내부-노드의-구조&#34; &gt;내부 노드의 구조
&lt;span&gt;
    &lt;a href=&#34;#%eb%82%b4%eb%b6%80-%eb%85%b8%eb%93%9c%ec%9d%98-%ea%b5%ac%ec%a1%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h5&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$pt_0$&lt;/th&gt;
&lt;th&gt;$k_0$&lt;/th&gt;
&lt;th&gt;$pt_1$&lt;/th&gt;
&lt;th&gt;$pr_0$&lt;/th&gt;
&lt;th&gt;$k_1$&lt;/th&gt;
&lt;th&gt;$pt_2$&lt;/th&gt;
&lt;th&gt;$pr_1$&lt;/th&gt;
&lt;th&gt;&amp;hellip;&lt;/th&gt;
&lt;th&gt;$k_{K-1}$&lt;/th&gt;
&lt;th&gt;$pt_K$&lt;/th&gt;
&lt;th&gt;$pr_{K-1}$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;$pt_i$ : 하위 서브 트리의 루트 노드를 가리키는 포인터&lt;/li&gt;
&lt;li&gt;$pr_i$ : 데이터를 갖고 있는 레코드를 가리키는 포인터&lt;/li&gt;
&lt;li&gt;$k_i$: zero-based 노드 인덱스 $i$의 검색 키&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;또한, 각 내부 노드의 키는 해당 노드의 서브 트리를 나누는 기준 값으로 사용됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;만약 내부 노드에 3가지 자식 노드(&lt;em&gt;또는 트리&lt;/em&gt;)가 있는 경우, 내부 노드에는 최소 2개의 키(예시로 $a_1$, $a_2$)가 있어야 합니다.
&lt;ul&gt;
&lt;li&gt;가장 왼쪽 서브 트리의 모든 값은 $a_1$보다 작고, 중간의 서브 트리의 모든 값은 $a_1$ 보다 크고 $a_2$보다 작으며, 가장 오른쪽 서브 트리의 모든 값은 $a_2$보다 큽니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;루트-노드-root-node&#34; &gt;루트 노드 (Root Node)
&lt;span&gt;
    &lt;a href=&#34;#%eb%a3%a8%ed%8a%b8-%eb%85%b8%eb%93%9c-root-node&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;루트 노드의 자식 수는 내부 노드와 동일한 상한이 존재하지만, 하한은 존재하지 않습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;전체 트리에 L-1 보다 적은 요소가 존재한다면, 루트 노드는 트리에서 자식이 전혀 없는 유일한 노드가 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;리프-노드-leaf-node&#34; &gt;리프 노드 (Leaf Node)
&lt;span&gt;
    &lt;a href=&#34;#%eb%a6%ac%ed%94%84-%eb%85%b8%eb%93%9c-leaf-node&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;실질적인 데이터 객체/청크를 갖는 노드입니다. 모든 리프 노드들은 &lt;strong&gt;같은 레벨에 존재&lt;/strong&gt;해야 합니다.&lt;/p&gt;
&lt;h3 id=&#34;b-트리의-장점&#34; &gt;B 트리의 장점
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ec%9e%a5%ec%a0%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;h4 id=&#34;정렬되어있는-키&#34; &gt;정렬되어있는 키
&lt;span&gt;
    &lt;a href=&#34;#%ec%a0%95%eb%a0%ac%eb%90%98%ec%96%b4%ec%9e%88%eb%8a%94-%ed%82%a4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;저장된 키들이 정렬되어 있어, 순차적인 순회에 유용합니다.&lt;/p&gt;
&lt;h4 id=&#34;동일한-삽입삭제검색-시간-복잡도&#34; &gt;동일한 삽입/삭제/검색 시간 복잡도
&lt;span&gt;
    &lt;a href=&#34;#%eb%8f%99%ec%9d%bc%ed%95%9c-%ec%82%bd%ec%9e%85%ec%82%ad%ec%a0%9c%ea%b2%80%ec%83%89-%ec%8b%9c%ea%b0%84-%eb%b3%b5%ec%9e%a1%eb%8f%84&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;기존의 이진 탐색 트리와 달리, 한 노드에 저장할 수 있는 키의 수가 많아 트리는 더 얕은 높이를 가질 수 있게 되었습니다.&lt;br&gt;
이러한 계층형 인덱스를 사용하므로써 디스크 I/O가 줄어들어 더 낮은 삽입/삭제/검색 시간 복잡도를 가집니다.
이러한 점 때문에 B 트리는 대용량 데이터 셋, 실시간 애플리케이션에 적합합니다.&lt;br&gt;
특히 DB에서 B 트리 인덱스를 사용하면 검색 성능을 크게 향상 시킬 수 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;DBMS에서는 인덱스 키 - PK가 매칭이 되어있는 B 트리를 만들어두고 이를 사용합니다.
&lt;ul&gt;
&lt;li&gt;인덱스를 통해 PK를 찾고, 찾은 PK를 통해 레코드를 찾습니다.&lt;/li&gt;
&lt;li&gt;DBMS가 PK를 통해 레코드를 찾으려면, 테이블 전체를 뒤져 검색 해야하지만, B 트리 인덱스를 활용하면 트리를 몇 단계 탐색하므로써 PK를 찾을 수 있고 그 PK를 통해 레코드를 찾아올 수 있으므로 속도가 더 빠릅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;자체-균형&#34; &gt;자체 균형
&lt;span&gt;
    &lt;a href=&#34;#%ec%9e%90%ec%b2%b4-%ea%b7%a0%ed%98%95&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;B 트리는 &lt;code&gt;자체 균형 이진 검색 트리(Self Balancing Binary Search Tree)&lt;/code&gt;의 일종이므로 항상 최적의 높이를 유지하고자 지속적으로 스스로 균형을 맞추려고 합니다.&lt;br&gt;
따라서 기존의 이진 검색 트리의 경우 작업이 최악의 경우(&lt;em&gt;트리가 한쪽으로 쏠린 경우&lt;/em&gt;) O(N)의 시간 복잡도를 가졌지만, B 트리는 작업이 최악의 경우에도 O(logN)의 시간복잡도를 유지하도록 보장합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;자체 균형 이진 검색 트리(Self Balancing Binary Search Tree)&lt;/code&gt; : 임의의 아이템 삽입/삭제 이후 자동으로 높이를 낮게 유지하는 노드 기반의 이진 검색 트리를 의미합니다. 대표적인 예시로 AVL 트리, B 트리, RBT 등이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;b-트리의-단점&#34; &gt;B 트리의 단점
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%eb%8b%a8%ec%a0%90&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;h4 id=&#34;더많은-디스크-공간-사용&#34; &gt;더많은 디스크 공간 사용
&lt;span&gt;
    &lt;a href=&#34;#%eb%8d%94%eb%a7%8e%ec%9d%80-%eb%94%94%ec%8a%a4%ed%81%ac-%ea%b3%b5%ea%b0%84-%ec%82%ac%ec%9a%a9&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;균형 유지를 위해 추가적인 포인터 및 헤더 정보를 유지해야 하므로 더 많은 공간을 사용합니다.&lt;/p&gt;
&lt;h4 id=&#34;다른-자료-구조에-비해-느린-속도&#34; &gt;다른 자료 구조에 비해 느린 속도
&lt;span&gt;
    &lt;a href=&#34;#%eb%8b%a4%eb%a5%b8-%ec%9e%90%eb%a3%8c-%ea%b5%ac%ec%a1%b0%ec%97%90-%eb%b9%84%ed%95%b4-%eb%8a%90%eb%a6%b0-%ec%86%8d%eb%8f%84&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;삽입/삭제 연산 이후 균형 유지를 위해 회전, 병합과 같은 재배치 작업을 수행할 수 있으며, 이 과정에서 오버헤드가 발생할 수 있습니다.&lt;/p&gt;
&lt;h2 id=&#34;b-트리-b-tree-1&#34; &gt;B+ 트리 (B+ Tree)
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac-b-tree-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;&lt;img src=&#34;B-plus-tree-architecure.png&#34; alt=&#34;B-plus-tree-architecure.png&#34;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;위는 분기 인자 b=4이며, 1~7 범위의 키와 $d_1$ ~ $d_7$의 데이터 값들을 연결하는 b+ 트리 예시 입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;B 트리의 변종 중 하나로, 각 노드가 키-값 쌍이 아닌 &lt;strong&gt;키만 포함&lt;/strong&gt;하며(인덱스 인트리) 하단에 &lt;strong&gt;링크드 리프 노드&lt;/strong&gt;들로 이뤄진 &lt;strong&gt;추가적인 레벨&lt;/strong&gt;(데이터 엔트리)이 붙어있는 B 트리로 볼 수 있습니다.&lt;br&gt;
노드 당 m개 이하의 자식이 있는 &lt;code&gt;다항 트리(m-ary tree)&lt;/code&gt; 라고도 일컬어지며, &lt;code&gt;분기 인자(branching factor, 각 노드 당 자식의 수)&lt;/code&gt; $b$ 를 기준으로 삽입/삭제/검색 작업이 $O(log_b{N})$ 의 시간 복잡도를 가집니다.&lt;br&gt;
B+ 트리의 핵심 가치는 &lt;code&gt;블록 지향 스토리지(block-oriented storage)&lt;/code&gt;(&lt;em&gt;특히 파일 시스템&lt;/em&gt;)에서 &lt;strong&gt;효율적인 검색&lt;/strong&gt;이 가능하도록 데이터를 저장하는 것입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이진 검색 트리와 달리, B+ 트리는 팬아웃이 매우 높아 트리 내 요소를 찾는데 필요한 I/O 작업 횟수를 줄일 수 있기 때문입니다.&lt;br&gt;
B+ 트리는 MS SQL, Oracle, SQLite 등의 RDBMS에서 &lt;strong&gt;테이블 인덱스&lt;/strong&gt;를 구현하는데 활용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;b-트리의-성질-1&#34; &gt;B+ 트리의 성질
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ec%84%b1%ec%a7%88-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;p&gt;분기 인자가 $b$ 이며, 높이 h인 b+ 트리는 다음과 같은 성질을 갖습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;저장된 레코드는 최대 $n_{max} = b^h - b^{h-1}$ 개여야 합니다.&lt;/li&gt;
&lt;li&gt;저장된 레코드는 최소 $n_{min} = 2\lceil {b\over2} \rceil^{h-1} - 2\lceil {b\over2}\rceil^{h-2}$ 개여야 합니다.&lt;/li&gt;
&lt;li&gt;트리를 저장하기 위한 공간 복잡도는 O(n) 입니다.&lt;/li&gt;
&lt;li&gt;레코드를 삽입/삭제/검색하는데 $O(log_b n)$의 시간 복잡도를 갖습니다.&lt;/li&gt;
&lt;li&gt;B+ 트리 구조는 레코드 수가 증가/감소 함에 따라 확장/수축 할 수 있으며, 크기에 제한이 없습니다.&lt;/li&gt;
&lt;li&gt;리프 노드들이 링크드 리스트 형태로 이어져 있어 빠른 &lt;code&gt;중위 순회(in-order traversal)&lt;/code&gt;가 가능합니다.&lt;/li&gt;
&lt;li&gt;리프 노드에서 부모 노드가 갖고 있는 키를 &lt;strong&gt;중복적&lt;/strong&gt;으로 가질 수 있습니다(&lt;code&gt;Key Duplication&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;b-트리의-장점-1&#34; &gt;B+ 트리의 장점
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ec%9e%a5%ec%a0%90-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;h4 id=&#34;순서대로-탐색이-가능&#34; &gt;순서대로 탐색이 가능
&lt;span&gt;
    &lt;a href=&#34;#%ec%88%9c%ec%84%9c%eb%8c%80%eb%a1%9c-%ed%83%90%ec%83%89%ec%9d%b4-%ea%b0%80%eb%8a%a5&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;B 트리의 경우 모든 데이터 포인터가 리프 노드에 있지 않기 때문에 순서대로 연결된 리스트를 만들 수 없지만, B+ 트리의 경우 모든 데이터 포인터가 리프 노드에 존재하므로 순서대로 연결된 리스트를 만들 수 있습니다. 이를 통해 범위 쿼리나 정렬된 데이터가 필요한 작업들을 쉽게 수행할 수 있습니다.&lt;br&gt;
이러한 점 때문에, B+ 트리는 DB 시스템 인덱스를 구축하는데 유용합니다.&lt;/p&gt;
&lt;h4 id=&#34;정렬되어있는-키-1&#34; &gt;정렬되어있는 키
&lt;span&gt;
    &lt;a href=&#34;#%ec%a0%95%eb%a0%ac%eb%90%98%ec%96%b4%ec%9e%88%eb%8a%94-%ed%82%a4-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h4 id=&#34;자체-균형-1&#34; &gt;자체 균형
&lt;span&gt;
    &lt;a href=&#34;#%ec%9e%90%ec%b2%b4-%ea%b7%a0%ed%98%95-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h4 id=&#34;동일한-삽입삭제검색-시간-복잡도-1&#34; &gt;동일한 삽입/삭제/검색 시간 복잡도
&lt;span&gt;
    &lt;a href=&#34;#%eb%8f%99%ec%9d%bc%ed%95%9c-%ec%82%bd%ec%9e%85%ec%82%ad%ec%a0%9c%ea%b2%80%ec%83%89-%ec%8b%9c%ea%b0%84-%eb%b3%b5%ec%9e%a1%eb%8f%84-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;h3 id=&#34;b-트리의-단점-1&#34; &gt;B+ 트리의 단점
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%eb%8b%a8%ec%a0%90-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h3&gt;&lt;h4 id=&#34;b-트리-대비-더-높은-메모리-사용&#34; &gt;B 트리 대비 더 높은 메모리 사용
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac-%eb%8c%80%eb%b9%84-%eb%8d%94-%eb%86%92%ec%9d%80-%eb%a9%94%eb%aa%a8%eb%a6%ac-%ec%82%ac%ec%9a%a9&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h4&gt;&lt;p&gt;&lt;em&gt;키, 값(데이터 포인터)을 각 노드에 저장&lt;/em&gt;하는 B 트리와 달리, B+ 트리는 내부 노드에는 키만 저장하고 리프 노드 층에 데이터를 저장하기 때문에 &lt;em&gt;키의 개수에 비례해&lt;/em&gt; &lt;strong&gt;추가적인 메모리가 필요&lt;/strong&gt;합니다.&lt;/p&gt;
&lt;h1 id=&#34;b-tree가-b-tree에-비해-반드시-좋다고-할-수-있을까-그렇지-않다면-어떤-단점이&#34; &gt;B+ Tree가 B Tree에 비해 반드시 좋다고 할 수 있을까? 그렇지 않다면 어떤 단점이?
&lt;span&gt;
    &lt;a href=&#34;#b-tree%ea%b0%80-b-tree%ec%97%90-%eb%b9%84%ed%95%b4-%eb%b0%98%eb%93%9c%ec%8b%9c-%ec%a2%8b%eb%8b%a4%ea%b3%a0-%ed%95%a0-%ec%88%98-%ec%9e%88%ec%9d%84%ea%b9%8c-%ea%b7%b8%eb%a0%87%ec%a7%80-%ec%95%8a%eb%8b%a4%eb%a9%b4-%ec%96%b4%eb%96%a4-%eb%8b%a8%ec%a0%90%ec%9d%b4&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;&lt;img src=&#34;B-tree-and-B+tree.png&#34; alt=&#34;B-tree-and-B+tree.png&#34;&gt;&lt;br&gt;
&lt;em&gt;웬만한 경우&lt;/em&gt; &lt;strong&gt;B+ 트리&lt;/strong&gt;가 B 트리 보다 &lt;strong&gt;더 빠르게 검색&lt;/strong&gt;할 수 있기 때문에 좋다고 할 수 있습니다. &lt;br&gt;
B+ 트리는 &lt;em&gt;B 트리와 달리&lt;/em&gt; 내부 노드에 값(데이터)을 저장하지 않으므로써 내부 노드에 저장되는 키의 수, 즉 &lt;strong&gt;&lt;code&gt;팬아웃&lt;/code&gt;을 최대화&lt;/strong&gt; 했고, 이를 통해 &lt;strong&gt;트리의 높이를 최소화&lt;/strong&gt; 하기 때문입니다.&lt;br&gt;
또한 &lt;strong&gt;&lt;code&gt;범위 검색 작업&lt;/code&gt;&lt;/strong&gt; 을 &lt;strong&gt;효율적&lt;/strong&gt;으로 진행할 수 있습니다. &lt;strong&gt;리프 노드가 서로 연결&lt;/strong&gt;되어 있기 때문입니다.&lt;br&gt;
그리고 삽입/삭제 작업이 &lt;strong&gt;리프 노드에서 수행&lt;/strong&gt;되어 &lt;strong&gt;더 쉽고 시간 소모가 적습니다&lt;/strong&gt;.&lt;br&gt;
하지만, B 트리의 경우 &lt;em&gt;특정 노드를 자주 사용하는 경우&lt;/em&gt; &lt;strong&gt;더 빠를 수&lt;/strong&gt; 있습니다. 자주 사용되는 &lt;strong&gt;노드를 &lt;code&gt;상승&lt;/code&gt;&lt;/strong&gt; 시킬 수 있기 때문에, 원하는 데이터에 도달하는데 필요한 비교 작업이 적어지기 때문입니다.&lt;/p&gt;
&lt;h1 id=&#34;db에서-굳이-rbt와-같은-트리를-사용하지-않고-b-treebtree를-사용하는-이유는&#34; &gt;DB에서 굳이 RBT와 같은 트리를 사용하지 않고, B-Tree/B+Tree를 사용하는 이유는?
&lt;span&gt;
    &lt;a href=&#34;#db%ec%97%90%ec%84%9c-%ea%b5%b3%ec%9d%b4-rbt%ec%99%80-%ea%b0%99%ec%9d%80-%ed%8a%b8%eb%a6%ac%eb%a5%bc-%ec%82%ac%ec%9a%a9%ed%95%98%ec%a7%80-%ec%95%8a%ea%b3%a0-b-treebtree%eb%a5%bc-%ec%82%ac%ec%9a%a9%ed%95%98%eb%8a%94-%ec%9d%b4%ec%9c%a0%eb%8a%94&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;더 빠르기 때문&lt;/strong&gt;입니다.&lt;br&gt;
이를 설명하려면 먼저 RBT, 즉 &lt;code&gt;레드-블랙 트리(Red-Black Tree)&lt;/code&gt;의 구조에 대해 알아야 합니다.&lt;br&gt;
RBT는 B 트리/B+ 트리와 마찬가지로 &lt;code&gt;자가 균형 이진 검색 트리(Self Balancing Binary Search Tree)&lt;/code&gt; 의 일종으로, 각각의 노드가 &lt;strong&gt;레드&lt;/strong&gt; 또는 &lt;strong&gt;블랙&lt;/strong&gt;의 색상 속성을 갖습니다.&lt;br&gt;
루트 노드와 모든 리프 노드들은 블랙이며, 레드 노드의 양 자식 노드들은 모두 블랙이라는 특징 때문에, RBT는 블랙과 레드가 번갈아 나오는 형태를 띄게 됩니다(물론 &lt;em&gt;블랙 다음에 블랙이 나올 수도&lt;/em&gt; 있습니다).&lt;br&gt;
이러한 특징 때문에 &lt;em&gt;루트 노드로 부터&lt;/em&gt; &lt;mark style=&#34;background: orange;&#34;&gt;가장 먼 리프 노드까지의 거리&lt;/mark&gt;가 &lt;mark style=&#34;background: skyblue;&#34;&gt;가장 가까운 리프 노드까지의 거리&lt;/mark&gt;의 &lt;strong&gt;2배 보다 항상 짧다&lt;/strong&gt;는 특성을 지니고, 이 때문에 삽입/삭제/탐색에 있어 B 트리와 마찬가지로 $O(logN)$의 시간 복잡도를 갖게 됩니다.&lt;br&gt;
하지만, &lt;strong&gt;RBT&lt;/strong&gt;는 일반적인 BST와 같이 &lt;strong&gt;자식을 둘 밖에&lt;/strong&gt; 가질 수 없으나 &lt;strong&gt;B 트리&lt;/strong&gt;는 &lt;strong&gt;둘 이상&lt;/strong&gt; 가질 수 있기 때문에 훨씬 &lt;strong&gt;트리 높이가 짧아지고&lt;/strong&gt; &lt;strong&gt;더 적은 디스크 I/O 작업을 수행&lt;/strong&gt;해 결과적으로 더 빠른 속도로 탐색을 진행할 수 있습니다.&lt;br&gt;
또한 &lt;em&gt;B 트리의 경우&lt;/em&gt; 내부 노드의 두 개 이상의 키들을 &lt;strong&gt;&lt;code&gt;배열&lt;/code&gt;&lt;/strong&gt; 로 다루므로 RBT가 하위 노드들을 참조해 탐색하는 것 보다 &lt;strong&gt;더 빠른 접근 속도&lt;/strong&gt;를 갖게 됩니다.&lt;br&gt;
이러한 차이 때문에 DB에서 B 트리/B+ 트리를 사용하게 됩니다.&lt;/p&gt;
&lt;h1 id=&#34;오름차순으로-정렬된-인덱스가-있다고-할-때-내림차순-정렬을-시도할-경우-성능이-어떻게-될까-b-treebtree의-구조를-기반으로&#34; &gt;오름차순으로 정렬된 인덱스가 있다고 할 때, 내림차순 정렬을 시도할 경우 성능이 어떻게 될까? (B-Tree/B+Tree의 구조를 기반으로)
&lt;span&gt;
    &lt;a href=&#34;#%ec%98%a4%eb%a6%84%ec%b0%a8%ec%88%9c%ec%9c%bc%eb%a1%9c-%ec%a0%95%eb%a0%ac%eb%90%9c-%ec%9d%b8%eb%8d%b1%ec%8a%a4%ea%b0%80-%ec%9e%88%eb%8b%a4%ea%b3%a0-%ed%95%a0-%eb%95%8c-%eb%82%b4%eb%a6%bc%ec%b0%a8%ec%88%9c-%ec%a0%95%eb%a0%ac%ec%9d%84-%ec%8b%9c%eb%8f%84%ed%95%a0-%ea%b2%bd%ec%9a%b0-%ec%84%b1%eb%8a%a5%ec%9d%b4-%ec%96%b4%eb%96%bb%ea%b2%8c-%eb%90%a0%ea%b9%8c-b-treebtree%ec%9d%98-%ea%b5%ac%ec%a1%b0%eb%a5%bc-%ea%b8%b0%eb%b0%98%ec%9c%bc%eb%a1%9c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;h2 id=&#34;b-트리의-경우&#34; &gt;B 트리의 경우
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ea%b2%bd%ec%9a%b0&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;B 트리의 경우 내림차순 정렬을 시도할 경우, 모든 노드들을 역순으로 하나 하나 탐색해야 합니다. 따라서 B+ 트리 대비 낮은 성능을 보입니다.&lt;/p&gt;
&lt;h2 id=&#34;b-트리의-경우-1&#34; &gt;B+ 트리의 경우
&lt;span&gt;
    &lt;a href=&#34;#b-%ed%8a%b8%eb%a6%ac%ec%9d%98-%ea%b2%bd%ec%9a%b0-1&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h2&gt;&lt;p&gt;B+ 트리의 경우 내림차순 정렬을 시도할 경우, 리프 노드만 역순으로 탐색하면 되고, 리프 노드들이 링크드 리스트 형태를 띄고 있으므로 순차 접근에 최적화 되어있어 더 높은 성능을 보입니다.&lt;/p&gt;
&lt;h1 id=&#34;참고-문서&#34; &gt;참고 문서
&lt;span&gt;
    &lt;a href=&#34;#%ec%b0%b8%ea%b3%a0-%eb%ac%b8%ec%84%9c&#34;&gt;
        &lt;svg viewBox=&#34;0 0 28 23&#34; height=&#34;100%&#34; width=&#34;19&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34;&gt;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34; fill=&#34;none&#34; stroke-linecap=&#34;round&#34; stroke-miterlimit=&#34;10&#34; stroke-width=&#34;2&#34;/&gt;&lt;/svg&gt;
    &lt;/a&gt;
&lt;/span&gt;
&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree&#34;&gt;Self-balancing binary search tree - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.baeldung.com/cs/self-balancing-bts&#34;&gt;Self-Balancing Binary Search Trees | Baeldung on Computer Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/B-tree&#34;&gt;B-tree - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/introduction-of-b-tree-2/&#34;&gt;Introduction of B-Tree - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/B%2B_tree&#34;&gt;B+ tree - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/introduction-of-b-tree/&#34;&gt;Introduction of B+ Tree - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geeksforgeeks.org/difference-between-b-tree-and-b-tree/&#34;&gt;Difference between B tree and B+ tree - GeeksforGeeks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.baeldung.com/cs/b-trees-vs-btrees&#34;&gt;The Difference Between B-trees and B+trees | Baeldung on Computer Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://tech.kakao.com/2018/06/19/mysql-ascending-index-vs-descending-index/&#34;&gt;MySQL Ascending index vs Descending index - tech.kakao.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Red%E2%80%93black_tree&#34;&gt;Red–black tree - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.allegro.tech/2023/11/how-does-btree-make-your-queries-fast.html&#34;&gt;How does B-tree make your queries fast? - allegro.tech&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
  </channel>
</rss>
