<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>daen_h.log</title>
        <link>https://velog.io/</link>
        <description>오늘보다 나은 내일을 위해 노력하는 개발자.</description>
        <lastBuildDate>Thu, 03 Aug 2023 08:55:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>daen_h.log</title>
            <url>https://velog.velcdn.com/images/daen_h/profile/adc7e4bf-439d-4662-9afb-7a5caafd9319/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. daen_h.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/daen_h" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[DB] MVCC]]></title>
            <link>https://velog.io/@daen_h/DB-MVCC</link>
            <guid>https://velog.io/@daen_h/DB-MVCC</guid>
            <pubDate>Thu, 03 Aug 2023 08:55:19 GMT</pubDate>
            <description><![CDATA[<p>Lock 기법에서는 read/read lock 끼리만 block을 하지 않아, 이 때만 서로 다른 트랜잭션이 동시에 특정 데이터접근이 가능했다.
그러나 트랜잭션 처리량이 적어 성능적인 이슈가 있었고 </p>
<p><em>*<em>이를 해결하고자 MVCC가 등장하였다.
*</em></em></p>
<blockquote>
<p>Keyword
MVCC, Locking read</p>
</blockquote>
<h1 id="mvccmulti-version-concurrency-control">MVCC(Multi Version Concurrency Control)</h1>
<ul>
<li>데이터를 읽을떄, <span style="color:red; background-color: #fff5b1"><strong>특정시점을 기준으로 가장 최근에 commit된 데이터</strong></span>를 읽는다
특정시점은 isolation level에 따라 다르다.</li>
<li>데이터 변화(wirte operation)에 대한 이력을 관리한다
history를 저장하는 추가적인 저장공간이 필요 (굳이 말하자면 단점..?)</li>
<li>read-lock과 write-lock끼리 block하지 않는다.
트랜잭션 처리량 증가로 성능 향상.</li>
</ul>
<h2 id="isolation-level에-따른-mvcc-동작">isolation level에 따른 MVCC 동작</h2>
<p>아래 상황을 살펴보자.</p>
<ul>
<li>x의 초기값은 10이다.</li>
<li>tx2에 의해서 x = 50 write 작업이 이루어 졌다. 아직 commit 전이기 때문에 DB 적용 X</li>
<li>MVCC는 commit 된 데이터만 읽기 때문에 tx1의 read는 x = 10.</li>
<li>그 후에 tx2에서 commit, DB에 x=50이 적용.<center><img src = "https://velog.velcdn.com/images/daen_h/post/2d14d7c8-9b84-483e-937c-7b50c2998aae/image.png" width = "700" height = "400"></center>

</li>
</ul>
<p>그럼 tx1의 두번째 read는 어떤 값을 읽어올까?
<em><strong>Isolation level에 따라 다르다.</strong></em></p>
<h4 id="read-committed">read committed</h4>
<ul>
<li>read하는 시간을 기준으로 그전에 commit된 데이터를 읽는다 (x=50)</li>
<li>mysql, postgresql 모두 동일</li>
</ul>
<h3 id="repetable-read">repetable read</h3>
<ul>
<li>tx 시작 시간을 기준으로 그전에 commit된 데이터를 읽는다. (x=10)</li>
<li>tx1 시작은 commit 전에 이루어졌으므로 x의 초기값을 읽는다.</li>
<li>mysql, postgresql 모두 동일</li>
</ul>
<h3 id="serializable">serializable</h3>
<ul>
<li>MySQL에서는 MVCC로 동작하기 보다는 lock으로 동작한다.</li>
<li>postgreSQL에서는 SSI(Serializable Snapshot Isolation) 기법이 적용된 MVCC로 동작</li>
<li>mysql, postgresql 결과는 동일, 동작방식 다름</li>
</ul>
<h3 id="read-uncommitted">read uncommitted</h3>
<ul>
<li>MVCC는 commit된 데이터를 읽기 때문에, 이 level에서는 보통 MVCC가 적용되지 않는다.</li>
<li>postgreSQL에서는 read uncommitted level이 존재하지만 read commited level처럼 동작한다.</li>
</ul>
<h2 id="mvcc에서-이상현상-해결-방법">MVCC에서 이상현상 해결 방법.</h2>
<p>MVCC를 사용할 때도 Lost-update, write-skew와 같은 이상현상이 발생한다.
postgreSQL과 MySQL의 해결방식이 조금은 다른데 알아보도록 하자.</p>
<h3 id="postgresql">PostgreSQL</h3>
<h4 id="lost-update">Lost-update</h4>
<p>PostgreSQL에서는 read committed level에서 Lost-update가 발생한다.</p>
<blockquote>
<p>PostgreSQL는 Update에 참여하는 <span style="color:red; background-color: #fff5b1"><strong>모든 트랜잭션이 repeatable read</strong></span>를 사용할 경우,
Lost-update문제를 해결할 수 있다.<br>
<strong>postgreSQL에서는 repeatable read level에서
같은 데이터에 먼저 update한 tx가 commit 되면 나중 tx는 rollback 된다.(first-updater-win)</strong></p>
</blockquote>
<h3 id="mysql">MYSQL</h3>
<h4 id="lost-update-1">Lost-update</h4>
<p>mysql에서는 lost update를 방지하기 위해서는 repeatable read만 가지고는 해결되지 않는다.
<em><strong>Locking read를 함께 사용해야 한다.</strong></em></p>
<blockquote>
<p><strong>Locking read</strong></p>
</blockquote>
<ul>
<li>read를 하면서도 read lock과 함께 write lock도 함께 획득하게 되는 것.</li>
<li>sql 쿼리문에 FOR UPDATE를 붙여줌으로 써 Locking read가 적용된다.(exclusive lock 획득)</li>
<li>FOR SHARE를 붙여줄 수도 있다.(shared lock 획득)</li>
<li>Locking read는 가장 최근의 commit된 데이터를 읽는다.
isolation level과는 무관.<pre><code class="language-sql">SELECT balance FROM account WHERE id=&#39;x&#39; FOR UPDATE or (FOR SHARE)</code></pre>
</li>
</ul>
<ul>
<li>Lost-update 외에도 write skew 이상 현상이 발생 할 수 있는데<blockquote>
<p><em>*<em>Repeatable Read 격리 수준에서 write skew를 피하기 위해서는
MySQL, PostgreSQL Locking Read를 사용해야 한다. *</em></em></p>
</blockquote>
</li>
</ul>
<p><strong>Reference</strong>
<a href="https://www.youtube.com/watch?v=0PScmeO3Fig&amp;t=2s">쉬운코드 - MVCC 1,2 편</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] 동시성 제어 기법 - Lock]]></title>
            <link>https://velog.io/@daen_h/lock</link>
            <guid>https://velog.io/@daen_h/lock</guid>
            <pubDate>Thu, 03 Aug 2023 04:19:38 GMT</pubDate>
            <description><![CDATA[<p><strong>동시성 제어</strong>는 다중 접속 데이터베이스 환경에서 동시에 여러 트랜잭션이 실행 될 때, 이상 현상이 발생하지 않도록 트랜잭션의 실행 순서를 제어하는 것이다. 트랜잭션들이 실행 될 때, 같은 데이터에 대해서 동시에 read/wirte operation이 있다면 예상치 못한 동작이 발생할 수 있다.</p>
<p><em><strong>이것을 해결하는 방법이 바로 Lock(잠금 기법)이다.</strong></em></p>
<blockquote>
<p><em><strong>Keyword</strong></em>
write lock, read lock, 2PL, S2PL, SS2PL</p>
</blockquote>
<h1 id="lock잠금-기법">Lock(잠금 기법)</h1>
<p>데이터마다 lock이 있어서, 데이터를 변경하거나 읽으려면 lock을 취득해야 한다.
만약 lock을 취득하지 못하면 lock을 취득할 때 까지 기다려야 한다.</p>
<h3 id="write-lockexclusive-lock">write-lock(exclusive lock)</h3>
<ul>
<li>read / write(insert, modify, delete) 할 때 사용한다.</li>
<li>다른 트랜잭션이 같은 데이터를 read/write 하는 것을 허용하지 않는다.</li>
<li>exclusive하기 때문에, write-lock에 걸린 데이터는 lock이 풀리기 전까지 어떤 트랜잭션도 접근하지 못한다.</li>
</ul>
<h3 id="read-lockshared-lock">read-lock(shared lock)</h3>
<ul>
<li>read 할 때 사용한다.</li>
<li>다른 트랜잭션이 같은 데이터를 read 하는 것은 허용한다.</li>
<li>read lock을 가지고 있는데, 같은 데이터에 대해서 다른 트랜잭션이 write하려고 하면
read lock이 안전하게 데이터를 읽을 수 있도록 보호하는 역할을 한다.</li>
</ul>
<center><img src = "https://velog.velcdn.com/images/daen_h/post/a1c9168b-ef00-48c4-8507-1d7bc7b78d3b/image.png" width = "700" height = "400"></center>

<blockquote>
<p><strong>하지만 Lock만을 사용해서는 Serializablilty를 보장할 수 없다.</strong>
예시를 하나 살펴보자.</p>
</blockquote>
<center><img src = "https://velog.velcdn.com/images/daen_h/post/28e28261-0c7a-4090-81af-3465ab8207a6/image.png" width = "700" height = "400"></center>

<blockquote>
<ul>
<li><strong>tx1</strong> : x와 y의 합을 x에 저장하는 작업 수행</li>
</ul>
</blockquote>
<ul>
<li><p><strong>tx2</strong> : x와 y의 합을 y에 저장하는 작업 수행<br>
위의 작업을 serial하게 실행하게되면 결과는</p>
</li>
<li><p><strong>serial schedule #1 (tx1 - tx2)</strong>
x = 300, y = 500</p>
</li>
<li><p><strong>serial schedule #2 (tx2 - tx1)</strong>
x = 400, y = 300</p>
</li>
<li><p>tx1, tx2를 동시에 실행시킨 결과는 x = 300, y =300이다.</p>
<blockquote>
<p>serial schedule #1, #2와 결과값이 다르므로 아래의 schedule은 Nonserializable하다.<br>
이상현상이 발생한 이유는
tx2가 먼저 실행 되었으므로, tx1에서 y값을 읽어올 때는 업데이트 된 y=300을 읽어와야 한다.
그러나 tx1의 read(y)는 y의 초기값 200을 읽어왔기 때문에 문제가 발생.<br></p>
</blockquote>
</li>
</ul>
<center><img src = "https://velog.velcdn.com/images/daen_h/post/5af7934d-19a5-4ebf-99d3-8f06c297dfe8/image.png" width = "700" height = "400"></center>

<blockquote>
<p><em><strong>결과값이 달라지는 이상현상을 <span style="color: blue;">unlock</span>과 <span style="color: tomato;">write/read lock</span> operation 순서를 바꿈으로써 해결한다.</strong></em></p>
</blockquote>
<ul>
<li>tx2가 먼저 실행되었기 때문에, 빨간색 박스의 unlock과 write-lock 순서를 바꿔 해결할 수 있었다.</li>
<li>tx1이 먼저 실행되었다면, 노란색 박스의 unlock과 write-lock의 순서를 바꿔주어야 한다.<center><img src = "https://velog.velcdn.com/images/daen_h/post/03c92120-37cc-40e7-ade8-ace0cfca35b0/image.png" width = "700" height = "400"></center>

</li>
</ul>
<h2 id="2pl-protocol-two-phase-locking">2PL protocol (two-phase locking)</h2>
<p>트랜잭션에서 모든 locking operation이 최초의 unlock operation 보다 먼저 수행되도록 하는 것을 말한다.
위에서 처럼 이상현상을 해결하기 위해 unlock과 lock의 위치를 바꾸면 아래와 같이 2개의 phase가 형성된다.</p>
<center><img src = "https://velog.velcdn.com/images/daen_h/post/5e2e8254-c95b-458b-9bf5-db71a51653c1/image.png" width = "700" height = "400"></center>

<ul>
<li><strong>Expanding phase</strong>
오직 잠금(lock)을 획득 할 수만 있고, 해제는 할 수 없다.</li>
<li><strong>Shrinking phase</strong>
오직 잠금을 해제만 할 수있고, 새로운 lock을 획득 할 수는 없다.</li>
</ul>
<blockquote>
<p><em><strong>2PL 프로토콜은 Serializability(직렬화)를 보장한다.</strong></em>
<em><strong>하지만 2PL 프로토콜은 dead-lock(교착상태)가 발생할 수 있다.</strong></em>
교착상태에 빠지면 외부에서 강제로 트랜잭션을 중단하거나,잠금을 해제하지 않는 이상
무한정 대기 상태로 남게 된다.<br>
해결방법으로는 Timeout-based 기법, DeadLock Prevention 기법이 있다.
이부분은 추가적인 공부가 필요함.</p>
</blockquote>
<h3 id="s2plstric-2pl">S2PL(Stric 2PL)</h3>
<ul>
<li><strong>strict schedule</strong>을 보장하는 2PL
rollback시 이상현상이 발생하지 않기 위해서 권장되는 가장 엄격한 schedule.</li>
<li>recoverability(회복성) 보장</li>
<li>write-lock을 commit/rollback 이 될때 반환(unlock)한다.<h3 id="ss2pl--rigorous-2pl-strong-strict-2pl">SS2PL / rigorous 2PL (strong strict 2PL)</h3>
</li>
<li>S2PL과 마찬가지로 strict schedule을 보장한다.</li>
<li>S2PL과 차이점이 있다면 write/read-lock 모두 commit/rollback 이 될때 반환(unlock)한다.</li>
</ul>
<blockquote>
<p>초창기에는 동시성 제어를 구현하기 위해 lock기법을 사용했다.
<strong>serializability</strong>를 보장하기 위해서 2PL 프로토콜을 사용하였고,
<strong>recoverability</strong>를 보장하기 위해서 S2PL, SS2PL을 사용하였다.</p>
</blockquote>
<p><em><strong>지금은 성능을 올리기 위해서 MVCC (Multiversion concurrency control)이 사용되고 있다.</strong></em></p>
<p><strong>Reference</strong>
<a href="https://www.youtube.com/watch?v=0PScmeO3Fig&amp;t=2s">쉬운코드 - LOCK을 활용한 concurrency control 기법</a>
<a href="https://medium.com/pocs/%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-%EA%B8%B0%EB%B2%95-%EC%9E%A0%EA%B8%88-locking-%EA%B8%B0%EB%B2%95-319bd0e6a68a">동시성 제어 기법 — 잠금(Locking) 기법</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB]이상현상, 트랜잭션 격리 수준(isolation level) ]]></title>
            <link>https://velog.io/@daen_h/transaction-isolation-level</link>
            <guid>https://velog.io/@daen_h/transaction-isolation-level</guid>
            <pubDate>Wed, 02 Aug 2023 15:14:13 GMT</pubDate>
            <description><![CDATA[<h2 id="isolation이-안될-때-나타날-수-있는-여러-현상들">isolation이 안될 때 나타날 수 있는 여러 현상들</h2>
<p>다중 사용자 데이터베이스 환경에서 여러 트랜잭션이 동시에 실행될 때, 서로 다른 트랜잭션 간의 간섭으로 인해 이상 현상이 발생할 수있다. 동시성 제어는 트랜잭션이 올바르게 실행되고 데이터베이스의 무결성을 유지하는데 필수적이다.
그렇게 하기 위해서는 이상 현상에 대해서 파악하고 있어야 한다.</p>
<p><em><strong>지금부터 이상 현상들에 대해서 알아보도록 하자.</strong></em></p>
<h3 id="1-dirty-read">1. Dirty read</h3>
<p>트랜잭션B가 데이터를 변경(write)하고 커밋하지 않은 시점에서, 트랜잭션 A가 변경된 데이터를 읽어오는 것을 말한다.
이 때, 트랜잭션B에 이슈가 발생하여 변경된 데이터를 커밋하지 않고 롤백하는 상황에서 문제가 된다.
아래 그림을 살펴보자.
<img src="https://velog.velcdn.com/images/daen_h/post/04bca7f5-4b55-47fc-9f60-b9bcf767b894/image.png" width="200" height="300"></p>
<blockquote>
<ol>
<li>tx-A가 실행되기 위해 read(x)</li>
<li>tx-B를 실행하기 위해 write(y)</li>
<li><span style=" background-color: #fff5b1"><strong>x에 y를 더하기 위해 tx-A의 read(y) =&gt; 70</strong></span> <span style="color: red; background-color: #fff5b1"><strong>(3번이 dirty read가 된다)</strong></span></li>
<li>x = x+y 값을 적용하기 위해 tx-A의 wirte(x) 후 commit</li>
<li>tx-B에서 문제가 발생하여 y가 초기값인 20으로 rollback<br>
<em><strong>rollback으로 y=70이라는 데이터는 유효하지 않은 데이터가 되었으므로,
그 데이터를 읽어 나온 결과인 x=80도 유효하지 않은 데이터가 된다.</strong></em></li>
</ol>
</blockquote>
<h3 id="2-non-repeatable-read">2. Non-repeatable read</h3>
<p>하나의 트랜잭션 내에서 같은 데이터를 같은 조건으로 여러번 조회 했을때, 서로 다른 데이터를 가져오는 것을 말한다.
이는 isolation 관점에서 보면 일어나면 안되는 현상이다.
isolation 속성의 의미는 <em><strong>&#39;여러 트랜잭션이 동시에 실행되어도, 각각의 트랜잭션은 독립적으로 실행되야한다.&#39;</strong></em> 이기 때문.
<img src="https://velog.velcdn.com/images/daen_h/post/fa0aafe1-97cd-4a4f-9b49-5d5a2c7b1122/image.png" width="20%" height="50%"></p>
<h3 id="3-phantom-read">3. Phantom read</h3>
<p>하나의 트랜잭션 내에서 같은 조회 쿼리를 두 번 실행했을 때,
첫번째 조회 결과에서 없던 레코드가 생성되거나 있었던 레코드가 없어지는 것을 말한다.
<img src="https://velog.velcdn.com/images/daen_h/post/29b45bf8-190f-4ff5-9643-ad6e134f26db/image.png" width="20%" height="50%"></p>
<blockquote>
<ol>
<li>tx-A에서 v=10인 데이터를 read(v=10) (t1만 조회)</li>
<li>tx-B에서 t2.v를 10으로 바꾸기 위해 write(t2.v=10) 후, commit</li>
<li>tx-A에서 두번째로 v=10인 데이터를 read(v=10) 후 commit (t1, t2 조회)<br>
Tx-B에 의해서 Tx-A의 처음 조회와, 두번째 조회의 결과가 달라졌다.<br>
<em><strong>Non-repeatable read 와 Phantom read의 차이점은 무엇일까?</strong></em></li>
</ol>
</blockquote>
<ul>
<li><span style=" background-color: #fff5b1"><strong>Non Repeatable Read</strong></span>은
하나의 레코드의 값이 한 트랜잭션 내에서 다르게 조회될 수 있음을 말한다.</li>
<li><span style=" background-color: #fff5b1"><strong>Phantom read</strong></span>
하나의 트랜잭션 내에서 조회 쿼리 결과의 레코드의 수가 달라질 수 있음을 말한다.</li>
</ul>
<h1 id="isolation-level">Isolation level</h1>
<p>이상 현상들을 모두 발생하지 않게 만들 수 있지만, 그렇게 하기엔 제약사항이 너무 많아져서 동시 처리 가능한 트랜잭션 수가 줄어들게 된다. 결국 DB의 전체 처리량이 하락하게 된다.(perfomance 하락)
때문에 <span style=" background-color: #fff5b1"><strong>일부 이상 현상은 허용하는 몇 가지 level을 만들어서 사용자가 필요에 따라서 적절하게 선택할 수 있도록 하자.</strong></span>
바로 이 아이디어가<span style="color: red"> <em><strong>Isolation level</strong></em></span> 이다.
<img src="https://velog.velcdn.com/images/daen_h/post/944b8347-3d3d-4269-8b0f-ddb12a3c8ce8/image.png" width="70%" height="50%"></p>
<ul>
<li><strong>Read uncommitted</strong>는 데이터 처리량은 가장 높지만, 자유도가 높아 안정성이 낮다.</li>
<li><strong>Read committed</strong>는 대부분의 DBMS에서 default로 사용되고 있는 isolation level이다.</li>
<li><strong>Serializable</strong>은 이상현상이 아예 일어나지 않는 수준으로, 거의 사용되지는 않는다.</li>
<li>isolation level이 엄격해 질수록 동시성은 줄어들어, 트랜잭션 처리량이 가장 낮다.</li>
<li>어플리케이션 설계자는 isolation level을 통해 전체 처리량과 데이터 일관성 사이에서어느 정도 거래를 할 수 있다<blockquote>
<p>즉 <strong>데이터 처리량</strong>과 <strong>데이터 일관성</strong>은 서로 <em><strong>trade-off</strong></em> 관계에 있다.</p>
</blockquote>
</li>
</ul>
<p>이외의 이상 현상에는 다음 4가지가 추가적으로 더 존재한다.</p>
<ul>
<li>Dirty write</li>
<li>Lost update</li>
<li>Read skew</li>
<li>Write skew</li>
</ul>
<p>또한 isolation level중 snapshot level도 존재하는데 이는 다음에 따로 정리해보도록 하겠다.</p>
<p><strong>Referance</strong>
<a href="https://www.youtube.com/@ez.">쉬운코드(yotube) - 데이터베이스 시리즈 (Isolation level 편)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동시성 제어(Concurrency control) 2편]]></title>
            <link>https://velog.io/@daen_h/%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-concurrency-control-2%ED%8E%B8</link>
            <guid>https://velog.io/@daen_h/%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-concurrency-control-2%ED%8E%B8</guid>
            <pubDate>Wed, 02 Aug 2023 05:22:04 GMT</pubDate>
            <description><![CDATA[<h1 id="recoverablilty">Recoverablilty</h1>
<p>Concurrency control은 Serializable과 Recoverablilty를 제공하기 위한 것이다.
1편에서는 Serializable에 대해서 다뤄보았고, 이번에는 Recoverablilty에 대해서 알아보자.</p>
<blockquote>
<p><em><strong>Keyword</strong></em>
recoverable schedule, cascadeless schedule, strict schedule</p>
</blockquote>
<h2 id="unrecoverable-schedule">unrecoverable schedule</h2>
<p><img src="https://velog.velcdn.com/images/daen_h/post/9b6e6358-47fa-4468-a38c-97860bff5701/image.png" alt=""></p>
<ol>
<li>tx1 이상없이 수행되어 commit 완료. (DB에 영구적으로 적용)</li>
<li>그러나 tx2는 오류가 발생하여 rollback.(H의 balance = 200만원)</li>
<li>tx1가 H_balace를 읽어올 때, tx2의 write(H_balance = 230만원) operation을 참조했기 때문에, tx1도 유효하지 않은 작업이므로 rollback을 시켜야한다. </li>
</ol>
<blockquote>
<p><em><strong>그러나, tx1는 이미 commit된 상태이므로, durability 속성 때문에 rollback할 수 없다.</strong></em></p>
</blockquote>
<p>이렇게 schedule 내에서 commit된 트랜잭션이(tx1),
rollback된 트랜잭션(tx2)의 write 했던 데이터를 읽은 경우를 의미한다.
<strong>unrecoverable schedule</strong>은 rollback을 해도 이전 상태로 회복이 불가능 할 수 있기 때문에 DBMS가 허용하면 안된다</p>
<p>그럼 DBMS는 어떤 schedule만을 허용해야 할까??
바로 <span style="color: #2D3748; background-color: #fff5b1"><strong>recoverable schedule</strong></span>이다.</p>
<h2 id="recoverable-schedule">recoverable schedule</h2>
<p>rollback할 때 이전 상태로 온전히 돌아갈 수 있기 때문에 DBMS는 <span style="color: red; background-color: #fff5b1"><strong>recoverable schedule</strong></span>만 허용해야 한다.
recoverable schedule에서 rollback 시에는, cascading rollback이 발생한다.
<img src="https://velog.velcdn.com/images/daen_h/post/fece346f-84e0-42a2-b1b5-f76f10d614b6/image.png" alt=""></p>
<h3 id="cascading-rollback">cascading rollback</h3>
<p>어떤 경우에 cascading rollback이 발생할 수 있을까?</p>
<blockquote>
<ol>
<li>tx1가 H_balance=230만원을 read한다.</li>
<li>이 때, tx1가 read한 H_balance는 tx2가 write한 데이터이다.</li>
<li>write operation을 수행한 tx2가 commit/rollback 하기 전까지 tx1는 commit하지 않아야 한다.<br>
<em><strong>schedule 내에서 그 어떤 트랜잭션도 자신이 read한 데이터를 write한 트랜잭션이 먼저 commit/rollback 하기 전까지는 commit을 하지 않는 경우에 발생한다.</strong></em></li>
</ol>
</blockquote>
<ul>
<li>하나의 트랜잭션이 rollback하면 의존성이 있는 다른 트랜잭션도 rollback 해야한다.</li>
</ul>
<p>하지만 여러 트랜잭션의 롤백이 연쇄적으로 일어나면 처리하는 비용이 많이 든다.</p>
<p><em><strong>이 문제를 어떻게 해결할 수 있을까?</strong></em></p>
<blockquote>
<p>데이터를 write한 트랜잭션이 commit/rollback 한 뒤에 데이터를 읽는 schedule만 허용하자.
<img src="https://velog.velcdn.com/images/daen_h/post/51577b25-370a-46bf-aa22-e66165675d7c/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>tx2에서 문제가 발생되게 되면 rollback을 시키고, 아무일도 없었던것 처럼 tx1만 완료된다.
<img src="https://velog.velcdn.com/images/daen_h/post/bc8bf9cc-e1f0-4a0b-94c6-e43db8ed4652/image.png" alt=""></p>
</blockquote>
<h4 id="cascadeless-schedule">cascadeless schedule</h4>
<blockquote>
<blockquote>
<p>schedule 내에서 어떤 트랜잭션도 
<span style="color: red; background-color: #fff5b1"><strong>commit 되지 않은 transaction들이 wirte한 데이터</strong></span>는 읽지 않는 경우를 의미한다.</p>
</blockquote>
</blockquote>
<p>cascadeless schedule도 어떤 상황에서는 문제가 있을 수 있다.</p>
<blockquote>
<p><strong>상황설명</strong><br>
<span style="color: red;">사장 H가 3만원이던 피자를 2만원으로 낮추려는데</span>
<span style="color: blue;">직원 K도 동일한 피자의 가격을 실수로 1만원으로 낮추려 했을 때.</span></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/daen_h/post/9ee3f4a3-bf44-46ab-92ed-6d19808746e4/image.png" alt=""></p>
<blockquote>
<ol>
<li>직원 K가 1만원으로 가격을 변경함. 아직 commit은 하지 않음.</li>
<li>사장 H도 2만원으로 가격을 변경하고 commit</li>
<li>tx1에서 이슈가 발생해서 rollback.</li>
<li>최종적으로 피자의 가격은 결국 3만원으로 원복됨. (tx2의 결과가 사라짐)<br>
<em><strong>이 schedule은 cascadeless schedule이지만 tx2의 결과가 사라지는 문제가 발생한다.</strong></em></li>
</ol>
</blockquote>
<p>위의 문제를 해결하기 위해서는 cascadeless schedule에 조금 더 보완이 필요하다.</p>
<h2 id="strict-schedule">Strict schedule</h2>
<blockquote>
<p>schedule 내에서 어떤 트랜잭션도 
<span style="color: red; background-color: #fff5b1"><strong>commit 되지 않은 transaction들이 wirte한 데이터</strong></span>는 <span style="color: blue; background-color: #fff5b1"><strong>쓰지도, 읽지도</strong></span> 않는 경우를 의미한다.
strict schedule이 발생하기 위해서는 tx1가 먼저 commit/rollback 작업이 이루어져서 끝나고 난 뒤에 tx2가 실행되어야 한다.
이러한 strict schedule의 형태는 rollback이 쉽다는 장점이 있다.
<img src="https://velog.velcdn.com/images/daen_h/post/d492a134-ddb6-43f8-b31a-d3037ca5ce15/image.png" alt=""></p>
</blockquote>
<p>결론은??
Serializable과 Recoverablilty에 대한 개념을 잘 잡아놓자.</p>
<blockquote>
<p><em><strong>Concurrency control은 Serializable과 Recoverablilty를 제공하기 위한 것이다.</strong></em></p>
</blockquote>
<p><strong>Reference</strong>
<a href="https://www.youtube.com/@ez.">쉬운코드(yotube) - 데이터베이스 시리즈 (Concurrency control 2편)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB] 동시성 제어(Concurrency control) 1편]]></title>
            <link>https://velog.io/@daen_h/DB-%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-Concurrency-control-1%ED%8E%B8</link>
            <guid>https://velog.io/@daen_h/DB-%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%A0%9C%EC%96%B4-Concurrency-control-1%ED%8E%B8</guid>
            <pubDate>Tue, 01 Aug 2023 15:37:30 GMT</pubDate>
            <description><![CDATA[<h1 id="concurrency-control">Concurrency control</h1>
<p>성능을 고려하여 여러 트랜잭션들을 동시에 실행 시키고, 데이터베이스의 일관성(consistency)을 해치지 않으며, 원하는 결과를 얻기 위해 트랜잭션을 제어하는 것을 의미한다.
Concurrency control에 대해 이해하기 위해서는, <strong>Schedule</strong>(serial schedule, nonserial schedule, <strong>Conflict</strong>(Conflict equivalent, Conflict serializable)에 대해서 알아야한다. 하나씩 차근차근히 정리하면서 알아가보자.</p>
<p><strong><em>한 가지 케이스에 대해서 살펴보자</em></strong></p>
<blockquote>
<p><em><strong>Keyword</strong></em>
schedule, conflict, conflict equivalent, conflict serializable</p>
</blockquote>
<blockquote>
<p><strong>K가 H에게 20만원을 이체할 때, H도 ATM에서 본인 계좌에 30만원을 입금한다.</strong>
이런 경우 2가지 트랜잭션으로 나눌 수 있다.</p>
</blockquote>
<ol>
<li><span style="color: red">20만원 이체 트랜잭션 (<strong>트랜잭션A</strong>)</span></li>
<li><span style="color: blue">30만원 입금 트랜잭션 (<strong>트랜잭션B</strong>)</span>
위의 2가지 트랜잭션을 실행 시킬 때, 여러 형태의 실행이 가능할 수 있다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/daen_h/post/b0cf96b6-f7ca-4546-b39c-e91f52150e4e/image.png" alt=""></p>
<h2 id="schedule">Schedule</h2>
<p>트랜잭션이 실행 될 때, 각 step은(read, write) <span style="color: #2D3748; background-color: #fff5b1"><strong>operation</strong></span>이라 칭한다.
<strong>Schedule</strong>은 여러 트랜잭션들이 실행될 때, 각 트랜잭션에 속한 operation들의 실행 순서를 의미한다.</p>
<ul>
<li><strong>case1, case2는 트랜잭션이 겹치지 않고 한번에 하나씩 실행되는 <span style="color: #2D3748; background-color: #fff5b1">serial schedule.</span></strong></li>
<li><strong>case3, case4는 두개의 트랜잭션이 동시에 실행되는 <span style="color: #2D3748; background-color: #fff5b1">nonserial schedule.</span></strong></li>
<li>serial이든 nonserial이든 각 트랜잭션 내의 operations들의 순서는 바뀌지 않는다.</li>
</ul>
<blockquote>
<p><strong>operation 간소화</strong> 
Schedule1 : rA(K)-wA(K)-rA(H)-wA(H)-c1-rB(H)-wB(H)-c2 (결과: 250만원)
Schedule2: rB(H)-wB(H)-c2-rA(K)-wA(K)-rA(H)-wA(H)-c1     (결과: 250만원)
Schedule3: rA(K)-wA(K)- rB(H)-wB(H)-c2-rA(H)-wA(H)-c1    (결과: 250만원)
Schedule4: rA(K)-wA(K)-rA(H)-rB(H)-wB(H)-c2-wA(H)-c1     (<span style="color: tomato"><strong>결과: 220만원</strong></span>)</p>
</blockquote>
<h3 id="serial-schedule">serial schedule</h3>
<p>한 번에 하나의 트랜잭션만 실행되기 때문에 좋은 성능을 낼 수 없고, 현실적으로 사용할 수 없는 방식이다.</p>
<h3 id="nonserial-schedule">nonserial schedule</h3>
<p>트랜잭션들이 겹쳐서 실행되기 때문에, 동시성이 높아져 같은 시간 동안 더 많은 트랜잭션들을 처리할 수 있다.
현실적으로 사용해야하는 방식.</p>
<h2 id="conflict">Conflict</h2>
<p>성능상의 이유로 nonserial schedule을 사용하면서 이상한 결과(case4)가 나오지 않기 위한 아이디어는 ?</p>
<blockquote>
<p>serial schedule과 동일한(equivalent) nonserial schedule을 실행하자.</p>
</blockquote>
<p><span style="color: tomato"><strong>&#39;schedule이 동일하다&#39;</strong></span>의 의미가 무엇인지 정의하기 위해 나온 개념이 바로 <strong>Conflict</strong>이다.
두 operation이 아래 3가지 조건을 만족 했을 때, conflict operations 라고 할 수 있다.</p>
<ul>
<li>두 operation이 서로 다른 트랜잭션에 속해야 한다.</li>
<li>같은 데이터에 접근해야 한다.</li>
<li>최소 하나는 write operation.<blockquote>
<p>스케줄 3을 예시로 들어보면.
Schedule3: rA(K)-wA(K)-<span style="color: red">rB(H)</span>-<span style="color: green">wB(H)</span>-c2-<span style="color: green">rA(H)</span>-<span style="color: red">wA(H)</span>-c1
rB(H)-wA(H) / wB(H)-rA(H) / wB(H)-wA(H) 총 3가지의 conflict가 존재한다</p>
</blockquote>
</li>
</ul>
<p>Conflict operation은 순서가 바뀌면 결과도 바뀌게 된다.</p>
<h3 id="conflict-equivalent">Conflict equivalent</h3>
<p>두가지 schedule을 비교했을 때 아래 조건을 만족하면 <span style="color: #2D3748; background-color: #fff5b1"><strong>Conflict equivalent</strong></span>하다고 말한다.</p>
<ul>
<li><strong>비교하는 두 schedule은 같은 종류의 트랜잭션들을 가져야한다.</strong> 
ex) 트랜잭션A, 트랜잭션B</li>
<li><strong>conflicting operations의 순서는 양쪽 schedule 모두 동일해야 한다.</strong>
rB(H)-wA(H) / wB(H)-rA(H) / wB(H)-wA(H) 3개의 conflicting operations의 순서가 동일하게 실행되야 한다.</li>
</ul>
<p>위의 두 조건을 만족한다면 위에서 말한 <span style="color: tomato"><strong>&#39;schedule이 동일하다&#39;</strong></span>라고 할 수 있다.</p>
<h3 id="conflict-serializable">Conflict serializable</h3>
<p>nonserial schedule을 serial schedule과 비교했을 때, Conflict equivalent을 만족하면 Conflict serializable이라 한다.</p>
<blockquote>
<p>결과적으로 
Schedule3은 Conflict serializable 하고,
Schedule4는 Conflict serializable 하지 못하다. (Lost update가 발생했기 때문)</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/daen_h/post/0b7e0be2-a593-4236-a18f-f585b781bed1/image.png" alt=""></p>
<p><em><strong>결과적으로 Conflict serializable한 nonserial schedule 이란 ??</strong></em></p>
<blockquote>
<p>nonserial schedule을 사용함으로써 <span style="color: red; background-color: #fff5b1"><strong>성능적인 문제도 해결함</strong></span>과 동시에,
<span style="color: red; background-color: #fff5b1"><strong>serial schedule과 동일한 결과</strong></span>를 얻을 수 있는 scheudle.</p>
</blockquote>
<p>Concurrency control이 제공하는 serializable에 대해서 알아보았고
recoverability는 2편에서 이어집니다...~</p>
<p><strong>Reference</strong>
<a href="https://www.youtube.com/@ez.">쉬운코드(yotube) - 데이터베이스 시리즈 (Concurrency control 1편)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DB]Transaction]]></title>
            <link>https://velog.io/@daen_h/Transaction</link>
            <guid>https://velog.io/@daen_h/Transaction</guid>
            <pubDate>Tue, 01 Aug 2023 07:26:51 GMT</pubDate>
            <description><![CDATA[<h1 id="transaction">Transaction</h1>
<ul>
<li>단일한 논리적인 작업 단위</li>
<li>논리적인 이유로 여러 SQL문들을 <span style="color: #2D3748; background-color: #fff5b1"><strong>하나의 작업으로 묶어서 나눠질 수 없게 만든 것.</strong></span></li>
<li>transaction의 SQL문 중 일부만 성공한다해서 DB에 반영되지 않음.</li>
<li><span style="color: #2D3748; background-color: #fff5b1"><strong>모든 SQL문이 성공해야 의미가 있는 작업.</strong></span></li>
</ul>
<h4 id="-예시---a가-b에게-20만원을-이체하는-과정">* 예시 - A가 B에게 20만원을 이체하는 과정</h4>
<pre><code class="language-sql">START TRANSACTION

UPDATE account SET balance = balance - 200000 where id=&#39;A&#39;
UPDATE account SET balance = balance + 200000 where id=&#39;B&#39;

// 지금까지 작업한 내용을 DB에 영구적으로 저장하는 명령어 + 트랜잭션 종료
COMMIT;
// 지금까지 작업들을 모두 취소하고 transaction 이전 상태로 되돌리는 명령어 + 트랜잭션 종료
ROLLBACK;


select * from account;</code></pre>
<h3 id="commit">COMMIT</h3>
<ul>
<li>작업이 완료된 SQL 쿼리문의 결과를 DB에 영구적으로 저장하고, 트랜잭션을 종료시키는 명령어.</li>
</ul>
<h3 id="rollback">ROLLBACK</h3>
<ul>
<li>작업이 완료된 SQL 쿼리문의 결과를 취소하고 이전의 상태로 되돌리는 명령어 + 트랜잭션 종료.</li>
</ul>
<h3 id="autocommit">AUTOCOMMIT</h3>
<ul>
<li>각각의 SQL문을 자동으로 트랜잭션 처리 해주는 개념.</li>
<li>SQL문이 성공적으로 실행되면 자동으로 commit.</li>
<li>실행 중에 문제가 있었다면 자동으로 rollback.</li>
<li>MYSQL에서는 autocommit = enabled가 default.</li>
<li>다른 DBMS에서도 대부분 같은 기능을 제공.<blockquote>
<pre><code class="language-sql">START TRANSACTION // 이 sql문을 실행과 동시에 autocommit은 off 된다
COMMIT or ROLLBACK // 이 명령어를 실행시켜 트랜잭션이 종료되면 원래의 autocommit 상태로 원복</code></pre>
</blockquote>
</li>
</ul>
<h4 id="일반적인-트랜잭션-사용-패턴">일반적인 트랜잭션 사용 패턴</h4>
<ol>
<li>트랜잭션 시작(begin)</li>
<li>데이터를 읽거나 쓰거나의 SQL문들을 포함해서 로직을 수행</li>
<li>일련의 과정들이 문제없이 동작했다면 트랜잭션을 commit</li>
<li>중간에 문제가 발생했다면 트랜잭션을 rollback</li>
</ol>
<h2 id="acid">ACID</h2>
<h3 id="atomicity원자성">Atomicity(원자성)</h3>
<ul>
<li>ALL or NOTHING (모두 성공해서 진행되거나, 아무일도 일어나지 않거나)</li>
<li>트랜잭션은 논리적으로 쪼개질 수 없는 작업 단위이기 때문에, 내부의 SQL문들이 모두 성공해야 한다.</li>
<li>중간에 SQL문이 실패하면 지금까지의 작업을 모두 취소하여 아무일도 없었던 것처럼 rollback 한다.<blockquote>
<p>commit 또는 rollback 실행 시 DB에 저장하거나, 이전상태로 되돌리는 작업은 DBMS가 담당.
개발자는 언제 commit 또는 rollback 할지를 챙겨야 한다.</p>
</blockquote>
</li>
</ul>
<h3 id="consistency일관성">Consistency(일관성)</h3>
<ul>
<li>트랜잭션은 DB 상태를 consistent 상태에서 또 다른 consistent 상태로 바꿔줘야 한다.</li>
<li>constraints, trigger 등을 통해 DB에 정의된 rules을 트랜잭션이 위반했다면 rollback 해야한다.</li>
<li>트랜잭션이 DB에 정의된 rule을 위반했는지 DBMS가 commit 전에 확인하고 알려준다.</li>
<li>그 외에 application 관점에서 transaction이 consistent하게 동작하는지는 개발자가 챙겨야 한다.</li>
</ul>
<h3 id="span-stylecolor-red-background-color-fff5b1isolation고립성격리성span"><span style="color: red; background-color: #fff5b1">Isolation(고립성,격리성)</span></h3>
<h4 id="트랜잭션끼리-고립되어야-하는-이유">트랜잭션끼리 고립되어야 하는 이유</h4>
<p><img src="https://velog.velcdn.com/images/daekuenhan/post/e4b6c884-9f9e-4ded-9a72-0dd50a72277a/image.png" alt=""></p>
<ul>
<li>J가 H에게 20만원을 보내기위해 J의 통장에서 20만원을 차감했다.<span style="color: red;">(1번 트랜잭션 시작)</span></li>
<li>H의 통장에 20만원을 입금하기위해 read를 한 상황.</li>
<li>그 순간 H가 ATM기기에서 자신의 통장에 30만원을 입금을 한다.<span style="color: blue;">(2번 트랜잭션 시작)</span></li>
<li>그래서 자신의 통장을 read를 한 후, 30만원을 입금시켜 write까지 하게 되었다. <span style="color: blue;">(2번 트랜잭션 완료)</span> </li>
<li>2번 트랜잭션 완료 후, J가 보낸 20만원을 H의 통장에 write하여 입금을 완료한다.<span style="color: red;">(1번 트랜잭션 완료)</span></li>
</ul>
<p><strong>결과적으로</strong> <span style="color: #2D3748; background-color: #fff5b1">1번 트랜잭션 중간에 2번 트랜잭션이 영향을 주게 되어, 30만원이 사라지는 결과를 초래하게 되었다.</span></p>
<ul>
<li>여러 transaction들이 동시에 실행될 때도 혼자 실행되는 것처럼 동작하게 만들어야 한다.</li>
<li><span style="color: #2D3748; background-color: #fff5b1"><strong>DBMS는 여러 종류의 isolation level을 제공한다. 이유는?</strong></span><ol>
<li>isolation level이 높으면 높을수록 엄격하게 분리한다.
하지만 엄격할수록 <span style="color: red">동시성이 떨어지기 때문에, DB 서버의 성능은 낮아진다.</span></li>
<li>isolation level이 낮아지면 <span style="color: blue">동시성 향상으로 성능은 높아진다.</span>
하지만 트랜잭션끼리 영향을 받을 확률이 증가하여 이상한 결과가 나타날 수 있다.</li>
</ol>
</li>
<li>개발자는 isolation level 중에 어떤 level로 transaction을 동작시킬지 설정할 수 있다.</li>
<li><span style="color: #2D3748; background-color: #fff5b1"><strong>concurrency control의 주된 목표가 isolation이다.</strong></span></li>
</ul>
<h3 id="durability지속성-영존성">Durability(지속성, 영존성)</h3>
<ul>
<li>commit된 트랜잭션은 DB에 영구적으로 저장한다.
  즉, DB system에 문제(power fail or DB crash)가 생겨도 commit된 트랜잭션은 DB에 남아 있는다.<ul>
<li>&#39;영구적으로 저장한다&#39; 라고 할 때는 일반적으로 &#39;비휘발성 메모리(HDD, SSD, ..)에 저장함&#39;을 의미</li>
<li>기본적으로 트랜잭션의 durability는 DBMS가 보장한다.</li>
</ul>
</li>
</ul>
<h4 id="참고사항">참고사항</h4>
<ol>
<li>transaction을 어떻게 정의해서 쓸지는 개발자가 정하는 것. 구현하려는 기능과 ACID 속성을 이해해야 transaction을 잘 정의할 수 있다.</li>
<li>transaction의 ACID와 관련해서 개발자가 챙겨야 하는 부분들이 있습니다. DBMS가 모든 것을 알아서 해주는 것은 아니다.</li>
</ol>
<p><strong>Reference</strong>
<a href="https://www.youtube.com/@ez.">쉬운코드(yotube) - 데이터베이스 시리즈 (Transaction, ACID)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MySQL] 접속방법]]></title>
            <link>https://velog.io/@daen_h/MySQL-%EC%A0%91%EC%86%8D%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@daen_h/MySQL-%EC%A0%91%EC%86%8D%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 01 Aug 2023 07:24:37 GMT</pubDate>
            <description><![CDATA[<h3 id="mysql-socket-접속-tcpip-접속-차이">mysql socket 접속, TCP/IP 접속 차이</h3>
<p>MySQL 서버에 접속하는 방법에는 두 가지가 있습니다</p>
<ul>
<li>소켓(socket) 접속
  소켓 접속은 주로 보안성과 성능을 강조할 때, 특히 로컬 환경에서 MySQL 서버에 접속할 때 좋은 선택<blockquote>
<p>로컬 머신에서 실행되기 때문에 네트워크 오버헤드가 거의 없으며 속도가 빠르고 성능이 우수함.
원격 호스트에서는 사용할 수 없으며, 클라이언트와 서버가 같은 머신에 있어야 함.</p>
</blockquote>
</li>
</ul>
<ul>
<li>TCP/IP 접속
  TCP/IP 접속은 원격 접속을 허용하고 네트워크를 통해 다양한 호스트에서 접속할 수 있으므로, 분산 환경에서 유용<blockquote>
<p>원격 머신에서도 접속이 가능하므로, 클라이언트와 서버가 다른 호스트에 있어도 통신할 수 있음.
  로컬 소켓 접속에 비해 속도가 느릴 수 있으며, 네트워크 지연으로 인해 약간의 성능 저하가 발생할 수 있음.</p>
</blockquote>
</li>
</ul>
<h3 id="mysql을-homebrew로-설치-했을-경우-config-파일-경로">mysql을 homebrew로 설치 했을 경우 config 파일 경로.</h3>
<blockquote>
<p>/opt/homebrew/etc 경로에 my.cnf 파일 존재</p>
</blockquote>
<p>2장, 3장은 config와 접속 및 권한설정에 관한 주제로 이루어져 있다.
실제로 데이터베이스를 운영하면서 적용해봐야 도움이되는 주제라고 생각되어 정독하고 지나간 챕터이다.
1회독을 한 후 직접 데이터베이스를 활용하면서 한번 더 읽어볼 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Web storage, Cookie]]></title>
            <link>https://velog.io/@daen_h/Web-storage-Cookie</link>
            <guid>https://velog.io/@daen_h/Web-storage-Cookie</guid>
            <pubDate>Tue, 01 Aug 2023 07:22:19 GMT</pubDate>
            <description><![CDATA[<p>LocalStorage, SessionStorage, Cookie는 비슷하지만 데이터의 성격에 따라 잘 선택해서 사용해야하는 저장소이다.
정리하지 않으면 햇갈리는 경우가 있기때문에 한번 정리해보고자 한다.</p>
<h1 id="web-storage브라우저-저장소">Web Storage(브라우저 저장소)</h1>
<ul>
<li>해당 도메인과 관련된 데이터들을 서버가 아닌 클라이언트(웹브라우저)에 저장할 수 있는 기능이다.</li>
<li>데이터는 key-value 쌍으로 이루어져 있으며, key를 통해 데이터를 조회할 수 있다.</li>
<li>도메인 단위로 접근이 제한된다.</li>
<li>영구저장소(LocalStorage), 임시저장소(SessionStorage) 두가지를 통해 데이터의 지속성을 구분하고, 용도에 맞게 활용할 수 있다.</li>
</ul>
<h3 id="localstorage">LocalStorage</h3>
<ul>
<li>도메인마다 storage가 생성되다.</li>
<li>도메인이 같으면 전역으로 공유가 가능.</li>
<li>브라우저를 종료하고 다시 실행해도 데이터가 유지된다.</li>
</ul>
<h3 id="sessionstorage">SessionStorage</h3>
<ul>
<li>도메인마다 storage가 생성된다.</li>
<li>도메인이 같더라도 브라우저가 다르면 데이터 공유가 되지 않는다.(브라우저 컨텍스트가 다르기 때문)</li>
<li>브라우저를 종료하면 데이터가 삭제된다.</li>
</ul>
<h1 id="cookie">Cookie</h1>
<ul>
<li>클라이언트 로컬에 저장되니는 작은 데이터 파일이다.</li>
<li>클라이언트에 300개까지 쿠키 저장 가능하고, 하나의 도메인당 20개의 값을 가질 수 있다. 하나의 쿠기 값은 4KB까지 저장한다.</li>
<li>Response Header에 Set-Cookie 속성을 사용하여 클라이언트에 쿠키를 만들 수 있다.</li>
<li>쿠키는 브라우저가 Request 시에 Request Header를 넣어서 자동으로 서버에 전송한다.</li>
<li>브라우저 저장소지만 백엔드와 연관이 있어 쿠키의 정보를 백엔드에서 확인할 수 있다.</li>
</ul>
<h2 id="web-storage-vs-cookie">Web Storage VS Cookie</h2>
<ul>
<li>쿠키는 매번 서버로 전송된다
웹사이트에서 쿠키를 설정하면 이후 모든 요청은 쿠키 정보를 포함해 서버로 전송된다. 하지만 web storage는 데이터가 클라이언트에만 존재하고 서버로 전송되지는 않는다. 때문에 web storage를 사용하면 네트워크 트래픽 비용을 줄여준다.</li>
<li>Web Storage는 영구 데이터 저장이 가능하다.
쿠키는 expired 시간을 지정하여 데이터가 사라지게 된다. 만약 expired time을 지정하지 않으면 세션쿠키가 된다. 영구적인 쿠키를 원한다면 expired 시간을 굉장히 길게 설정하여 만들 수 있다.
하지만 Web Storage는 expired time을 설정하는 것이 없이, 영구적으로 데이터를 저장할 수 있다.</li>
<li>Web Storage는 용량의 제한이 없다.
하지만 쿠키는 최대 300개, 도메인당 20개, 하나의 쿠키는 최대 4KB로 제한되어 있다.</li>
<li>Web Storage는 객체 형태로 데이터를 저장할 수 있다.</li>
</ul>
<h4 id="reference">Reference</h4>
<p><a href="https://www.inflearn.com/course/%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%A0%EB%86%8D%EC%B6%95-%EC%BD%94%EC%8A%A4/dashboard">[인프런x코드캠프] 부트캠프에서 만든 고농축 백엔드 코스</a></p>
]]></description>
        </item>
    </channel>
</rss>