<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>min_amim.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 28 Apr 2023 06:38:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>min_amim.log</title>
            <url>https://images.velog.io/images/min_amim/profile/f9ca6c67-3d88-478d-9caf-d59ac3435315/KakaoTalk_Photo_2021-09-23-12-16-03.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. min_amim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/min_amim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[ci/cd] 빈스톡 배포 에러]]></title>
            <link>https://velog.io/@min_amim/cicd-%EB%B9%88%EC%8A%A4%ED%86%A1-%EB%B0%B0%ED%8F%AC-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@min_amim/cicd-%EB%B9%88%EC%8A%A4%ED%86%A1-%EB%B0%B0%ED%8F%AC-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Fri, 28 Apr 2023 06:38:19 GMT</pubDate>
            <description><![CDATA[<p>분명 workflow에는 문제가 없는데 EB 배포에서 문제 발생..
s3에 버전도 잘 올라감</p>
<p>eb-engine.log</p>
<pre><code>2023/04/26 04:51:38.321202 [INFO] Running command /bin/sh -c /opt/aws/bin/cfn-get-metadata -s arn:aws:cloudformation:ap-northeast-2:409904644833:stack/awseb-e-qa7w3mbtc9-stack/7a28c260-dda4-11ed-aa4b-02dc69b2ef6e -r AWSEBAutoScalingGroup --region ap-northeast-2
2023/04/26 04:51:38.638171 [INFO] Running command /bin/sh -c /opt/aws/bin/cfn-get-metadata -s arn:aws:cloudformation:ap-northeast-2:409904644833:stack/awseb-e-qa7w3mbtc9-stack/7a28c260-dda4-11ed-aa4b-02dc69b2ef6e -r AWSEBBeanstalkMetadata --region ap-northeast-2
2023/04/26 04:51:38.954681 [INFO] checking whether command bundle-log is applicable to this instance...
2023/04/26 04:51:38.954695 [INFO] this command is not applicable to the instance, thus instance shouldn&#39;t execute command
2023/04/26 04:51:38.954699 [INFO] skip command bundle-log for this instance...
2023/04/26 04:51:38.954714 [ERROR] Ignoring not applicable command.
2023/04/26 04:51:38.954718 [INFO] Executing cleanup logic
2023/04/26 04:51:38.954767 [INFO] CommandService Response: {&quot;status&quot;:&quot;FAILURE&quot;,&quot;api_version&quot;:&quot;1.0&quot;,&quot;results&quot;:[{&quot;status&quot;:&quot;FAILURE&quot;,&quot;msg&quot;:&quot;Ignoring not applicable command.&quot;,&quot;returncode&quot;:0,&quot;events&quot;:[]}]}

2023/04/26 04:51:38.954815 [INFO] Platform Engine finished execution on command: bundle-log
</code></pre><p><a href="https://stackoverflow.com/questions/64748899/aws-elasticbeanstalk-command-not-applicable-app-deploy">https://stackoverflow.com/questions/64748899/aws-elasticbeanstalk-command-not-applicable-app-deploy</a></p>
<p>참고해서 2개로 늘려봤는데도 오류남 ㅜ</p>
<pre><code>03:17:11 ERROR: Instance id(s) &#39;i-0bf74eed2a62f78b9,i-09f64687ae5d56016&#39; did not pass health check after command execution. Aborting the operation.
56
03:17:11 ERROR: Failed to deploy application.</code></pre><pre><code>2023/04/27 03:27:37.976894 [ERROR] An error occurred during execution of command [app-deploy] - [start proxy with new configuration]. Stop running the command. Error: copy proxy conf from staging failed with error validate nginx configuration failed with error Command /bin/sh -c /usr/sbin/nginx -t -c /var/proxy/staging/nginx/nginx.conf failed with error exit status 1. Stderr:nginx: [emerg] unexpected &quot;;&quot; in /var/proxy/staging/nginx/nginx.conf:43
nginx: configuration file /var/proxy/staging/nginx/nginx.conf test failed</code></pre><pre><code>Instance id(s) &#39;i-081d08a6433f11a4c&#39; did not pass health check after command execution

![](https://velog.velcdn.com/images/min_amim/post/57e48e6f-9d0b-4e4b-aceb-9ac5df07231a/image.png)
</code></pre><p><img src="https://velog.velcdn.com/images/min_amim/post/57a8cbef-c584-4330-bca1-35a5739ae732/image.png" alt=""></p>
<p>음.. 타겟 그룹이랑 헬스 체크 경로에는 이상 없는 것 같음 뭐가 문젤까</p>
<pre><code>HTTP 502: Bad gateway

Possible causes:

 - The load balancer received a TCP RST from the target when attempting to establish a connection.

 - The load balancer received an unexpected response from the target, such as &quot;ICMP Destination unreachable (Host unreachable)&quot;, when attempting to establish a connection. Check whether traffic is allowed from the load balancer subnets to the targets on the target port.

 - The target closed the connection with a TCP RST or a TCP FIN while the load balancer had an outstanding request to the target. Check whether the keep-alive duration of the target is shorter than the idle timeout value of the load balancer.

 - The target response is malformed or contains HTTP headers that are not valid.

 - The load balancer encountered an SSL handshake error or SSL handshake timeout (10 seconds) when connecting to a target.

 - The deregistration delay period elapsed for a request being handled by a target that was deregistered. Increase the delay period so that lengthy operations can complete.

 - The target is a Lambda function and the response body exceeds 1 MB.

 - The target is a Lambda function that did not respond before its configured timeout was reached.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[CMC] 프로젝트 회고록]]></title>
            <link>https://velog.io/@min_amim/CMC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@min_amim/CMC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Thu, 23 Feb 2023 08:48:22 GMT</pubDate>
            <description><![CDATA[<p>조금 늦은 프로젝트 회고..</p>
<p>동아리에 들어가면서 가장 우선으로 했던 목표는 앱 출시 및 CI/CD 구성이었다.
두 개 다 이루긴 했지만 아쉬운 점도 너무너무너무 많이 존재했다.</p>
<p>먼저 CI/CD를 완성하긴 했지만 보안 문제로 인해 프라이빗 레포로 진행했었다. 포폴을 위해서는 이를 퍼블릭으로 돌려야했는데, 그러면서 발생한 보안 문제를 완전히 해결하지 못했다.</p>
<p>두 번째로 앱을 출시하긴 했지만 실사용자를 얻지 못했고, 단기 프로젝트로 끝났다는 점이 있다.</p>
<p>두 번째는 내가 어떻게 할 수 있는 방법이 없기 때문에 1번 문제 해결 및 테스트 코드 작성을 목표로 리팩토링을 진행해보고자 한다.</p>
<p>그러면 일단 CI/CD 다시 구성한 다음에
코드 리팩토링으로 ...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[cs 스터디] DB Part.3]]></title>
            <link>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.3</link>
            <guid>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.3</guid>
            <pubDate>Wed, 22 Feb 2023 08:34:59 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터베이스">데이터베이스</h1>
<h2 id="jdbc">JDBC</h2>
<p>자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API
이를 통해 DBMS의 종류에 관계 없이 데이터베이스를 연결하고 작업을 처리할 수 있다.</p>
<h2 id="단일키-복합키-index">단일키, 복합키, index</h2>
<p><a href="https://prohannah.tistory.com/175">https://prohannah.tistory.com/175</a></p>
<h2 id="join-연산-속도">join 연산 속도</h2>
<p><strong>조인 연산 알고리즘</strong></p>
<ul>
<li>Neested Loops Join</li>
<li>Hash Join</li>
<li>Sort Merge Join
어떤 알고리즘을 사용할지는 데이터 크기, 결합키(Key), 인덱스와 같은 요인에 따라 옵티마이저가 결정</li>
<li>옵티마이저(Optimizer): 여러 결과 도출 방법 중 가장 성능이 좋은 계획을 선택해주는 도구</li>
</ul>
<p>구동 테이블(Driving Table)이 작을수록, 내부 테이블(Inner Table)의 결합키 필드에 인덱스가 존재하는 경우 가장 성능을 높일 수 있다.</p>
<p><strong>구동테이블</strong>: 조인이 진행될 때 먼저 액세스되어 Access Path를 주도하는 테이블. 즉, 주도적으로 다른 테이블의 결합키에 다가가서 매칭을 시도하는 테이블
<strong>내부테이블</strong>: 구동테이블의 대상이 되는 테이블
<strong>인덱스</strong>: 검색 시 레코드를 Full Scan하지 않고 색인화되어 있는 INDEX 파일을 검색해 검색 속도를 빠르게 해준다.</p>
<p>조인은 실행계획에 변동이 일어나기 가장 쉬운 연산이다. 조인을 대체할 수 있는 다른 수단을 잘 활용하는 것이 좋다. 
ex) <a href="https://schatz37.tistory.com/12">윈도우 함수</a></p>
<p>더 자세한 정보) <a href="https://schatz37.tistory.com/2">https://schatz37.tistory.com/2</a></p>
<h2 id="select-조회-시-칼럼이-많은-데이터가-효율적일까-로우가-많은-데이터가-효율적일까">select 조회 시 칼럼이 많은 데이터가 효율적일까, 로우가 많은 데이터가 효율적일까?</h2>
<h2 id="실행계획-옵티마이저">실행계획, 옵티마이저</h2>
<p>옵티마이저는 사용자가 질의한 SQL문에 대해 최적의 실행 방법을 결정하는 역할 수행한다. 이러한 최적의 실행 방법을 실행계획(Execution Plan)이라고 한다.</p>
<h3 id="옵티마이저">옵티마이저</h3>
<ul>
<li>규칙기반 옵티마이저(RBO, Rule Based Optimizer)</li>
<li><strong>비용기반 옵티마이저(CBO, Cost Based Optimizer)</strong></li>
</ul>
<h3 id="실행계획">실행계획</h3>
<ul>
<li>조인 순서</li>
<li>조인 기법</li>
<li>액세스 기법</li>
<li>최적화 정보</li>
<li>연산</li>
</ul>
<h2 id="복제replication">복제(Replication)</h2>
<blockquote>
<p>두 개 이상의 DBMS를 이용해 Master/Slave의 수직적 구조를 활용해 DB의 부하를 분산시키는 기술</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/min_amim/post/82a257d7-588e-456a-b17a-73fc14f9affb/image.png" alt="">출처: <a href="https://nesoy.github.io/articles/2018-02/Database-Replication">https://nesoy.github.io/articles/2018-02/Database-Replication</a></p>
<ul>
<li>Master DB에는 Insert, Update, Delete 작업 수행</li>
<li>Slave DB는 Select 작업 수행</li>
<li>Select 작업이 시간이 많이 걸리기 때문에 따로 뺀다.</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>Select 성능 향상</li>
<li>데이터 백업</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>데이터 정합성을 보장할 수 없음</li>
<li>Binary Log File 관리<ul>
<li>Master는 Binary Log가 무분별하게 쌓이는 걸 막기 위해 데이터 보관 주기를 설정하지만 Master는 Slave까지 관리하지는 않기 때문에 Master에서 Binary Log File을 삭제했다고 해서 Slave에서 Binary Log가 삭제되지는 않음</li>
</ul>
</li>
<li>Fail Over 불가<ul>
<li>Master에서 에러가 발생한 경우 Slave로 Fail Over하는 기능을 지원하지 않는다. Slave 역시 Master와 Log 위치가 다르면 관리자가 작업해야 한다.</li>
</ul>
</li>
</ul>
<p>더 자세한 내용) <a href="https://velog.io/@zpswl45/DB-Replication-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC">https://velog.io/@zpswl45/DB-Replication-개념-정리</a></p>
<h2 id="파티셔닝샤딩">파티셔닝/샤딩</h2>
<h3 id="파티셔닝partitioning">파티셔닝(Partitioning)</h3>
<blockquote>
<p>데이터베이스를 여러 부분으로 분하라는 것
VLDB(Very large DBMS)와 같이 하나의 DBMS에 너무 큰 테이블이 들어가면서 용량과 성능 측면에서 많은 이슈가 발생할 때 파티셔닝 기법을 이용해 해결할 수 있다.
즉, 큰 테이블이나 인덱스를 작은 팦티션 단위로 나누어 관리하는 것</p>
</blockquote>
<p>데이터가 너무 커져서 조회하는 시간이 길어질 때 또는 관리 용이성, 성능, 가용성 등의 이유로 사용된다.</p>
<p><strong>장점</strong></p>
<ul>
<li>성능(Performance)<ul>
<li>특정 쿼리의 성능을 향상</li>
<li>대용량 Data Write 환경에서 효율적</li>
<li>필요한 데이터만 빠르게 조회 가능</li>
<li>Full Scan에서 데이터 접근의 범위를 줄임으로써 성능 향상</li>
</ul>
</li>
<li>가용성(Availability)<ul>
<li>물리적인 파티셔닝으로 전체 데이터의 훼손 가능성이 줄고 데이터 가용성 향상</li>
<li>파티션 별로 독립적인 백업과 복구 가능</li>
<li>파티션 단위로 Disk I/O를 분산해 경합을 줄이므로 Update 성능 향상</li>
</ul>
</li>
<li>관리용이성(Manageability)</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>테이블 간 Join 비용 증가</li>
<li>테이블과 인덱스를 별도로 파티셔닝할 수 없으므로 테이블과 인덱스를 같이 파티셔닝해야 한다.</li>
</ul>
<h3 id="종류">종류</h3>
<ul>
<li>수평 파티셔닝(Horizontal Partitioning)</li>
<li>수쥑 파티셔닝(Vertical Partitioning)</li>
</ul>
<h4 id="범위">범위</h4>
<ul>
<li>범위 분할(range partitioning)</li>
<li>목록 분할(list partitioning)</li>
<li>해시 분할(hash partitioning)</li>
<li>합성 분할(composite partitioning)</li>
</ul>
<h3 id="샤딩sharding">샤딩(Sharding)</h3>
<blockquote>
<p>같은 테이블 스키마를 가진 데이터를 다수의 데이터베이스에 분산하여 저장하는 기법</p>
</blockquote>
<p>같은 데이터베이스 내에서 하나의 큰 테이블을 쪼개 저장하는 수평 파티셔닝과 달리
샤딩은 하나의 큰 테이블을 쪼개 각각 다른 데이터베이스에 분산 저장하는 기법이다.
샤딩은 수평 파티셔닝의 장점을 모두 갖는다.</p>
<p><strong>장점</strong></p>
<ul>
<li>데이터의 개수를 기준으로 나눠 파티셔닝 한다.</li>
<li>데이터의 개수와 인덱스의 개수가 줄어 성능이 향상된다.</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>데이터베이스 서버 간의 연결 과정이 많아져 비용이 증가할 수 있다.</li>
<li>하나의 서버가 고장나면 데이터의 무결성이 깨질 수 있다.</li>
</ul>
<h2 id="erdentity-relationship-diagram">ERD(Entity Relationship Diagram)</h2>
<blockquote>
<p>개체-관계 모델로, 테이블 간의 관계를 설명해주는 다이어그램이다.
즉, API를 효율적으로 뽑아내기 위한 모델 구조도</p>
</blockquote>
<p>Ref)
<a href="https://velog.io/@fud904/DB-%EC%98%B5%ED%8B%B0%EB%A7%88%EC%9D%B4%EC%A0%80%EC%99%80-%EC%8B%A4%ED%96%89%EA%B3%84%ED%9A%8D">https://velog.io/@fud904/DB-옵티마이저와-실행계획</a>
<a href="https://velog.io/@zpswl45/DB-Replication-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC">https://velog.io/@zpswl45/DB-Replication-개념-정리</a>
<a href="https://code-lab1.tistory.com/202">https://code-lab1.tistory.com/202</a>
<a href="https://velog.io/@kjhxxxx/DataBase-ERD%EB%9E%80">https://velog.io/@kjhxxxx/DataBase-ERD란</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[cs 스터디] DB Part.2]]></title>
            <link>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.2</link>
            <guid>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.2</guid>
            <pubDate>Wed, 22 Feb 2023 07:30:59 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터베이스">데이터베이스</h1>
<h2 id="교착상태dead-lock">교착상태(Dead Lock)</h2>
<blockquote>
<p>두 개 이상의 트랜잭션이 특정 자원의 Lock을 획득한 채 다른 트랜잭션이 소유하고 있는 잠금을 요구하면 아무리 기다려도 상황이 바뀌지 않는 상태가 되는데 이를 교착상태라고 한다. 즉, 여러 개의 트랜잭션들이 실행되지 못하고 서로 무한적 기다리고 있는 상태</p>
</blockquote>
<p>오라클의 경우, 데드락을 감지하면 한쪽 Transaction을 풀어버린다.</p>
<h3 id="데드락-빈도-낮추는-방법">데드락 빈도 낮추는 방법</h3>
<ul>
<li>트랜잭션을 자주 커밋</li>
<li>정해진 순서로 테이블에 접근</li>
<li>읽기 잠금 획득(SELECT ~ FOR UPDATE)의 사용을 피한다.</li>
<li>한 단위의 복수 행을 복수에 연결해서 순서 없이 갱신하면 교착 상태가 발생하기 쉽다. 이 경우에는 테이블의 잠금을 획득해 갱신을 직렬화하면 동시성이 떨어지지만 교착 상태를 피할 수 있다.</li>
<li>Index 설계 (Update시 Index를 타지 않으면 테이블 전체에 Lock이 걸릴 수 있다.)</li>
<li>고립 수준을 낮춘다. (서비스 검토 필요)</li>
</ul>
<h3 id="해결-방안">해결 방안</h3>
<p><a href="https://jaehoney.tistory.com/162">https://jaehoney.tistory.com/162</a></p>
<h2 id="join">JOIN</h2>
<blockquote>
<p>둘 이상의 테이블을 연결해서 데이터를 검색하는 방법</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/min_amim/post/7ae5f8f0-9419-404f-ba42-d50dac1f4b6d/image.png" alt=""></p>
<ul>
<li><p>INNER JOIN: 내부 조인(교집합)</p>
</li>
<li><p>LEFT/RIGHT JOIN: 부분 집합</p>
</li>
<li><p>OUTER JOIN: 외부 조인(합집합)</p>
</li>
<li><p>인덱스를 활용하면, 조인 연산의 비용을 극적으로 낮출 수 있다.</p>
</li>
</ul>
<h2 id="sql-injectionsql-삽입-공격">SQL Injection(SQL 삽입 공격)</h2>
<blockquote>
<p>보안 상의 취약점을 이용해 임의의 SQL 문을 주입하고 실행되게 함으로써 데이터베이스가 비정상적인 행동을 하도록 조작하는 행위
인젝션 공격은 OWASP Top10 중 첫 번째에 속해 있으며, 공격이 비교적 쉬운 편이고 공격에 성공할 경우 큰 피해를 입힐 수 있는 공격이다.
인증 우회, 시스템 명령어 삽입, 입쉘 생성 등이 있다.
2017년 3월에 일어난 &quot;여기어때&quot;의 대규모 개인정보 유출 사건도 SQL Injection으로 인해 피해 발생</p>
</blockquote>
<h3 id="공격-종류-및-방법">공격 종류 및 방법</h3>
<ul>
<li>Error based SQL Injection</li>
<li>UNION based SQL Injection</li>
<li>Blind SQL Injection(1)</li>
<li>Blind SQL Injection(2)</li>
<li>Stored Procedure SQL Injection</li>
<li>Mass SQL Injection</li>
</ul>
<h3 id="대응-방안">대응 방안</h3>
<ul>
<li>입력 값에 대한 검증</li>
<li>Prepared Statement 구문 사용</li>
<li>Error message 노출 금지</li>
<li>웹 방화벽 사용</li>
</ul>
<h2 id="statement-preparestatement">Statement, PrepareStatement</h2>
<blockquote>
<p>자바에서 DB로 쿼리문을 전송할 때, 2가지 인터페이스를 사용할 수 있다.
Statement와 PreparedStatement이다.</p>
</blockquote>
<p><strong>DBMS 쿼리 실행 절차</strong></p>
<pre><code>1. Parsing (Query의 문법적, 의미적 오류 체크, 재사용 가능 SQL 확인, 쿼리실행계획 수립 등)
2. Execution (쿼리를 실행한다.)
3. Fetch(실행된 값을 가져오는 절차이므로 Select 만 해당됨. 반환하는 값이 없는 Insert, Update, Delete는 미해당.)</code></pre><h3 id="statement">Statement</h3>
<ul>
<li>Statement 인터페이스를 구현한 객체를 Connection 클래스의 createStatement() 메소드를 호출함으로써 얻어진다.</li>
<li>Statement 객체가 생성되면 executeQuery() 메소드를 호출해 SQL 문을실행시킬 수 있다.메소드의 인수로 SQL문을 담은 String 객체를 전달한다.</li>
<li>Statement는 정적인 쿼리문을 처리할 수 있으므로, 쿼리문에 값이 미리 입력되어 있어야 한다.</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>테이블, 칼럼에 대한 동적 쿼리 작성이 가능하다. 즉, DDL 작성에 적합하다.</li>
<li>쿼리 실행문을 직접 확인 가능하므로 쿼리 분석이 쉽다.</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>1번 처리 구간을 매 요청마다 실행하므로 Query 처리비용이 많이 든다. 즉, 캐시 처리를 못한다.</li>
<li><strong>SQL Injection으로 인한 공격에 노출된다.</strong></li>
<li>ex) 비밀번호를 확인하는 Where 구문의 변수 부분에 &#39;1234 OR 1 = 1&#39; 같은 구문을 끼워넣을 경우 항상 참이 되므로 악용이 가능하다.</li>
</ul>
<h3 id="preparedstatement">PreparedStatement</h3>
<ul>
<li>Connection 객체의 preparedStatement() 메소드를 이용해 생성한다. 인수로 SQL문을 담은 String 객체가 필요하다.</li>
<li>SQL 문장이 미리 컴파일되고, 실행 시간 동안 인수 값을 위한 공간을 확보할 수 있다는 점에서 Statement 객체와 다르다.</li>
<li>Statement 객체의 SQL은 실행될 때, 매번 서버에서 분석해야 하는 반면 PreparedStatement 객체는 한 번 분석되면 재사용이 용이하다.</li>
<li>각 인수에 대해 위치홀더(placeholder)를 사용해 SQL 문장을 정의할 수 있게 하며, 위치 홀더는 &#39;?&#39;로 표현된다.</li>
<li>동일한 SQL문을 특정 값만 바꾸어서 여러 번 실행해야 할 때, 인수가 많아서 SQL문을 정리해야 할 필요가 있을 때 사용하면 유용하다.</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>1번 처리 구간을 건너뛰고 2번부터 처리하기 때문에 SQL 처리가 빠르다.(Soft Parsing)</li>
<li>1번 구간은 SQL을 분석하는 처리도 하고 있지만, 건너뛰기 때문에 대입된 값은 SQL로 인식하지 않는다. 즉, SQL Injection을 예방할 수 있다.</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>쿼리에 오류가 생긴 경우 분석하기 어렵다. 바인드변수 부분이 &#39;?&#39; 처리되므로 실제 실행된 쿼리를 확인하기 어렵다.</li>
<li>바인드변수는 일부 허용된 위치에서만 사용할 수 있기 때문에 동적 쿼리 작성이 힘들다.</li>
<li>ex) 변수를 활용해 동적으로 테이블을 변경하는 쿼리를 작성해야 하는 경우 Prepared Statement로는 처리가 불가능하다.</li>
</ul>
<h3 id="statement와-preparedstatement의-차이점">Statement와 PreparedStatement의 차이점</h3>
<ul>
<li>Statement: SQL문을 실행할 때마다 매번 구문을 새로 작성하고 해석해야하므로 오버헤드 존재</li>
<li>PreparedStatement: 선처리 방식을 사용하므로 SQL문을 미리 준비해놓고 바인딩 변수(? 연산자)를 사용해서 반복되는 SQL문 쉽게 처리</li>
</ul>
<h2 id="rdbms-nosql">RDBMS, NoSQL</h2>
<h3 id="rdbms">RDBMS</h3>
<blockquote>
<p>관계형 데이터베이스 관리 시스템으로, RDBf란 모든 데이터를 2차원 테이블 형태로 표현하는 DB를 말한다.</p>
</blockquote>
<ul>
<li>관계를 맺고 있는 데이터가 자주 변경되는 경우</li>
<li>변경될 여지가 없고, 명확한 스키마가 사용자와 데이터에 중요한 경우 사용</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>정해진 스키마에 따라 데이터를 저장해야 하므로 명확한 데이터 구조 보장</li>
<li>각 데이터 중복 없이 한 번만 저장</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>테이블 간 관계를 맺고 있어 시스템이 커질 경우 JOIN문이 많은 복잡한 쿼리가 만들어질 수 있다.</li>
<li>성능 향상을 위해서는 Scale-up만을 지원하므로 비용이 기하급수적으로 증가할 수 있다.</li>
<li>스키마로 인해 데이터가 유연하지 못함. 나중에 스키마가 변경될 경우 번거롭고 어렵다.</li>
</ul>
<p>*Scale-up(=수직 스케일링(vertical scaling)): 기존 서버를 보다 높은 사양으로 업그레이드
Scale-out(=수평 스케일링(horizontal scaling)): 장비를 추가해서 확장</p>
<h3 id="nosqlnot-only-sql">NoSQL(Not Only SQL)</h3>
<blockquote>
<p>RDB 형태의 관계형 데이터베이스가 아닌 다른 형태의 데이터 저장 기술</p>
</blockquote>
<ul>
<li><p>RDBMS와 달리 테이블 간 관계를 정의하지 않는다. 따라서 테이블은 그냥 하나의 테이블이며 일반적으로 테이블 간 조인도 불가능하다.</p>
</li>
<li><p>빅데이터의 등장으로 데이터와 트래픽이 기하급수적으로 증가함에 따라 RDBMS의 단점인 성능을 향상시키기 위해 등장</p>
</li>
<li><p>데이터 일관성은 포기하되 비용을 고려해 여러 대의 데이터에 분산해 저장하는 Scale-Out을 목표로 등장</p>
</li>
<li><p>정확한 데이터 구조를 알 수 없거나 변경/확장될 수 있는 경우</p>
</li>
<li><p>읽기를 자주 하지만, 데이터 변경은 자주 없는 경우</p>
</li>
<li><p>데이터베이스를 수평으로 확대해야 하는 경우(막대한 양의 데이터를 다뤄야 하는 경우) 사용</p>
</li>
</ul>
<h4 id="저장-형태">저장 형태</h4>
<ul>
<li>Key-Value: Redis, Riak, Amazon DYnamo DB</li>
<li>Document: MongoDB, CouthDB</li>
<li>Wide Column: HBase, Hypertable</li>
<li>Graph: Neo4J</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>스키마가 없으므로 유연하며 자유로운 데이터 구조를 가질 수 있다.</li>
<li>언제든 저장된 데이터를 조정하고 새로운 필드를 추가할 수 있다.</li>
<li>데이터 분산이 용이하며 성능 향상을 위해 Scale-up 뿐만 아니라 Scale-out도 가능</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>데이터 중복이 발생할 수 있으며, 중복된 데이터가 변경될 경우 모든 컬렉션에서 수정해야 한다.</li>
<li>스키마가 존재하기 않으므로 명확한 데이터 구조를 보장하지 않으며 데이터 구조를 결정하기 어려울 수 있다.</li>
</ul>
<h2 id="ormobject-relational-mapping">ORM(Object Relational Mapping)</h2>
<blockquote>
<p>객체-관계 매핑으로 OOP에서 쓰이는 객체라는 개념을 구현한 클래스와 RDB에서 사용되는 데이터인 테이블을 자동으로 매핑하는 것을 말한다.
객체 모델과 관계형 모델 간에 불일치가 존재하는데 이 객체간의 관계를 바탕으로 SQL을 자동 생성하여 불일치를 해결하는 것</p>
</blockquote>
<p>Object &lt;- 매핑 -&gt; DB 데이터 에서 매핑의 역할을 해준다.</p>
<ul>
<li>SQL 문법 대신 어플리케이션의 개발 언어를 그대로 사용할 수 있게 함으로써, 개발 언어의 일관성과 가독성을 높여준다는 장점을 갖고 있다.</li>
<li>ex) Python-Flask SQLAlchemy, Node.js-Sequlize, Java-Hibernate, JPA</li>
</ul>
<p><strong>장점</strong></p>
<ul>
<li>객체지향적 코드로 더 직관적이고 비즈니스 로직에 집중할 수 있도록 도와준다.<ul>
<li>CRUD를 위한 긴 SQL 문장 작성할 필요 X</li>
<li>SQL의 절차적 접근이 아닌 객체적인 접근으로 생산성 증가</li>
</ul>
</li>
<li>재사용 및 유지보수의 편리성 증가<ul>
<li>매핑 정보가 명확해 ERD를 보는 것에 대한 의존도 낮출 수 있음</li>
<li>ORM은 독립적으로 작성돼있고 해당 객체들은 재사용 가능</li>
</ul>
</li>
<li>DBMS에 대한 종속성 감소<ul>
<li>대부분의 ORM은 DB에 종속적이지 않다.</li>
<li>Object에 집중함으로써 DBMS를 교체하는 극단적 작업에도 비교적 적은 리스크와 시간 소요</li>
<li>구현 방법 뿐 아니라 많은 솔루션에서 자료형 타입에서까지 종속적이지 않다.</li>
</ul>
</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>완벽한 ORM만으로는 구현하기 어렵다.</li>
<li>프로시저가 많은 시스템에서는 ORM의 객체지향적 장점을 활용하기 어렵다.</li>
</ul>
<p>*프로시저: 특정작업을 위한 프로그램의 일부, 함수와 같은 의미</p>
<p>Ref:
<a href="https://velog.io/@yrkim/Database-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-deadlock">https://velog.io/@yrkim/Database-트랜잭션-deadlock</a>
<a href="https://jaehoney.tistory.com/162">https://jaehoney.tistory.com/162</a>
<a href="https://dev-jwblog.tistory.com/94?category=1004261">https://dev-jwblog.tistory.com/94?category=1004261</a>
<a href="https://noirstar.tistory.com/264">https://noirstar.tistory.com/264</a>
<a href="https://velog.io/@dingdoooo/JDBC-Statement-PreparedStatement-%EC%9D%B4%EC%9A%A9%ED%95%98%EA%B8%B0">https://velog.io/@dingdoooo/JDBC-Statement-PreparedStatement-이용하기</a>
<a href="https://iksflow.tistory.com/127">https://iksflow.tistory.com/127</a>
<a href="https://pythontoomuchinformation.tistory.com/528">https://pythontoomuchinformation.tistory.com/528</a>
<a href="https://woooseogi.tistory.com/97">https://woooseogi.tistory.com/97</a>
<a href="https://velog.io/@alskt0419/ORM%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C...-iek4f0o3fg">https://velog.io/@alskt0419/ORM에-대해서...-iek4f0o3fg</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[cs 스터디] DB Part.1]]></title>
            <link>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.1</link>
            <guid>https://velog.io/@min_amim/cs-%EC%8A%A4%ED%84%B0%EB%94%94-DB-Part.1</guid>
            <pubDate>Wed, 22 Feb 2023 05:56:30 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터베이스">데이터베이스</h1>
<h2 id="인덱스">인덱스</h2>
<h3 id="인덱스란">인덱스란?</h3>
<p>데이터베이스 테이블에 대한 검색 성능의 속도를 높여주는 자료구조
특정 칼럼에 인덱스를 생성하면 해당 칼럼의 데이터들을 정렬한 후 별도의 메모리 공간에 칼럼의 값과 물리적 주소를 함께 저장</p>
<h3 id="장단점">장단점</h3>
<h4 id="장점">장점</h4>
<ul>
<li>테이블 검색 속도 및 성능 향상에 따른 전반적인 시스템 부하 감소</li>
<li>데이터들이 정렬된 형태를 갖게 됨에 따라 &#39;Full Table Scan&#39; 작업 없이 조건에 맞는 데이터를 빠르게 찾을 수 있음</li>
<li>ORDER BY, MIN/MAX와 같은 경우도 마찬가지로 빠르게 수행 가능</li>
</ul>
<p><strong>Where 절의 효율성</strong>
Index를 사용하지 않는 경우 </p>
<ul>
<li>Where 절을 이용할 때 레코드의 처음부터 끝까지 다 읽어서 검색 조건과 맞는지 비교해야 한다.(Full Table Scan)
Index를 사용하는 경우</li>
<li>테이블이 정렬되어 있기 때문에 해당 조건에 맞는 데이터를 빠르게 찾을 수 있다.</li>
</ul>
<p><strong>Order by 절의 효율성</strong>
Index를 사용하는 경우 Order by에 의한 Sort 과정을 피할 수 있다.
Order by는 정렬과 동시에 메모리에서 정렬이 이루어지고 메모리보다 더 큰 작업이 필요하다면 디스크 I/O도 추가적으로 발생되는 등 부하가 괴장히 많이 걸리는 작업이다.
하지만 인덱스를 사용하면 이미 정렬이 되어있기 때문에 이런 전반적인 자원의 소모가 필요하지 않다.</p>
<p><strong>MIN, MAX의 효율적인 처리</strong>
시작값과 끝값만 가져오면 되기 때문에 훨씬 효율적이다.</p>
<h4 id="단점">단점</h4>
<ul>
<li>인덱스를 관리하기 위해 DB의 약 10%에 해당하는 저장공간이 필요하다.</li>
<li>정렬된 상태를 계속 유지시켜줘야 한다.<ul>
<li>= 데이터 값이 바뀌는 부분에 악영향을 미친다.</li>
<li>데이터가 추가되거나 값이 바뀌면 INDEX 테이블 내에 있는 값들을 재정렬해야 한다.</li>
</ul>
</li>
<li>잘못 사용할 경우 오히려 성능이 저하될 수 있다.<ul>
<li>테이블의 전체 데이터 중 10~15% 이하의 데이터를 처리하는 경우에만 효율적이다.</li>
<li>값의 범위(range)가 적은 칼럼의 경우, 인덱스를 읽은 후 다시 많은 데이터를 조회해야 하기 때문에 비효율적</li>
</ul>
</li>
</ul>
<h4 id="해시-테이블">해시 테이블</h4>
<blockquote>
<p>칼럼 값과 물리적 주소를 (key, value)의 한 쌍으로 저장
하지만 해시 테이블은 등호(=) 연산에 최적화되어 있는 반면 DB는 부등호(&lt;. &gt;) 연산이 더 자주 사용됨
해시 테이블 내 데이터들은 정렬되어 있지 않아 특정 기준보다 크거나 작은 값을 빠르게 찾을 수 없어 실제 인덱스에서 잘 사용하지 않음</p>
</blockquote>
<h4 id="b-tree">B-Tree</h4>
<p><img src="https://velog.velcdn.com/images/min_amim/post/12c9a9e8-8297-4bf2-a56b-f6ff01d29c7d/image.jpeg" alt="">출처: <a href="http://www.btechsmartclass.com/data_structures/b-trees.html">http://www.btechsmartclass.com/data_structures/b-trees.html</a></p>
<p>여러 유형 중 가장 많이 사용되는 구조
Binary search tree와 유사하지만 한 노드 당 자식 노드가 2개 이상 가능하다.
균형이진트리의 연속이기에 균형을 유지하며, 따라서 아무리 최악의 경우라도 O(logN)의 검색 성능을 보여준다.
그러나 처음 생성 당시는 균형 트리지만 테이블 갱신의 반복을 통해 서서히 균형이 무너지고, 성능이 악화된다.
어느 정도 균형을 자동으로 회복하는 기능이 있지만, 갱신 빈도가 높은 테이블에 작성되는 인덱스 같은 경우 인덱스 재구성을 통해 트리의 균형을 되찾는 작업이 필요하다.</p>
<p>이 중에서도 <strong>B*Tree</strong>와 <strong>B+Tree</strong>가 가장 많이 사용된다.</p>
<p><strong>B*Tree</strong>
<img src="https://velog.velcdn.com/images/min_amim/post/60e1f71a-4399-4fc6-b09a-ca7a252f7dba/image.png" alt=""></p>
<ul>
<li>대부분의 DBMS, 특히 오라클에서 중점적으로 사용하고 있는 보편적인 인덱스
Root(기준) / Branch(중간) / Leaf(말단) Node로 구성되며 계층적 구조를 갖는다.
특정 칼럼에 인덱스를 생성하는 순간 칼럼의 값들을 정렬한다. 
오라클 서버에서 풀 스캔보다 인덱스 스캔이 유리하다고 판단했을 때, 생성된 인덱스가 정렬한 순서가 중간쯤 되는 데이터를 root 블록으로 지정하고 root 블록을 기준으로 가지가 되는 branch 블록을 지정하며 마지막으로 잎에 해당하는 leaf 블록에 인덱스의 키가 되는 데이터와 데이터의 물리적 주소 정보인 rowid를 저장한다.</li>
</ul>
<p><strong>B+Tree</strong>
B-Tree의 확장 개념으로, internal 혹은 branch node에 key와 data를 담을 수 있는 B-Tree와 달리 브랜치 노드에 key만 담아두고 data는 담지 않는다.
오직 리프 노드에만 key와 data를 저장하고, 리프 노드끼리 Linked list로 연결돼 있다.
MySQL의 DB engine이 B+Tree</p>
<p><strong>장점</strong></p>
<ul>
<li>리프 노드를 제외하고 데이터를 담아두지 않기 때문에 메모리를 더 확보함으로써 더 많은 key들을 수용할 수 있다. 하나의 노드에 더 많은 key들을 담을 수 있기 때문에 트리의 높이는 더 낮아진다.(cache hit을 높일 수 있다.)</li>
<li>풀 스캔 시, B+Tree는 리프 노드에 데이터가 모두 있기 때문에 한 번에 선형탐색만 하면 된다. -&gt; B-Tree에 비해 빠르다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/min_amim/post/68712d3b-d32e-4caa-bc30-cf2071c009a1/image.png" alt=""></p>
<p>참고:
<a href="https://zorba91.tistory.com/293">https://zorba91.tistory.com/293</a>
<a href="https://choicode.tistory.com/27">https://choicode.tistory.com/27</a></p>
<p>더 자세한 사항 알아보기
<a href="https://ssocoit.tistory.com/217">https://ssocoit.tistory.com/217</a>
<a href="https://3catpapa.tistory.com/201">https://3catpapa.tistory.com/201</a></p>
<h3 id="정규화normalization">정규화(Normalization)</h3>
<p>이상현상이 있는 릴레이션을 분해하여 이상현상을 없애는 과정</p>
<p><strong>장점</strong></p>
<ul>
<li>DB 변경 시 이상 현상(Anomaly)을 제거할 수 있다.</li>
<li>정규화된 DB 구조에서는 새로운 데이터 형의 추가로 인한 확장 시, 그 구조를 변경하지 않아도 되거나 일부만 변경해도 된다.</li>
<li>DB와 연동된 응용 프로그램에 최소한의 영향만을 미치게 되어 응용 프로그램의 생명을 연장시킨다.</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>릴레이션의 분해로 인해 릴레이션 간의 JOIN 연산이 많아진다.</li>
<li>질의에 의한 응답 시간이 느려질수도 있다. 데이터의 중복 속성을 제거하고 결정자에 의해 동일한 의미의 일반 속성이 하나의 테이블로 집약되므로 한 테이블의 데이터 용량이 최소화되는 효과가 있다.</li>
<li>따라서 데이터를 처리할 때 속도가 빨라질 수도, 느려질 수도 있다.</li>
<li>조인이 많이 발생해 성능 저하가 나타나면 반정규화(De-normalization)를 적용할 수도 있다.</li>
</ul>
<h4 id="제1-정규화">제1 정규화</h4>
<p>테이블의 칼럼이 원자값(Atomic Value)을 갖도록 테이블 분해</p>
<h4 id="제2-정규화">제2 정규화</h4>
<p>제1 정규화를 진행한 테이블에 대해 완전 함수 종속을 만족하도록 테이블을 분해하는 것
<strong>완전 함수 종속</strong>: 어떤 속성이 기본키에 대해 완전히 종속인 경우로, 기본키의 부분집합이 결정자가 되어서는 안된다.
<strong>부분 함수 종속</strong>: 어떤 속성이 기본키가 아닌 다른 속성에 종속되거나, 기본키가 여러 속성으로 구성되어 있을 경우 기본키를 구성하는 속성 중 일부만 종속될 때</p>
<h4 id="제3-정규화">제3 정규화</h4>
<p>제2 정규화를 진행한 테이블에 대해 이행적 종속을 없애도록 테이블을 분해하는 것
<strong>이행적 종속</strong>: A-&gt;B, B-C가 성립할 때 A-&gt;C가 성립되는 것</p>
<h4 id="bcnf-정규화">BCNF 정규화</h4>
<p>제3 정규화를 진행한 테이블에 대해 모든 결정자가 후보키가 되도록 테이블을 분해하는 것</p>
<h4 id="제4-정규화">제4 정규화</h4>
<p>BCNF를 진행한 테이블에 대해서 함수 종속이 아닌 다치 종속(MVD: Multi Valued Dependency)을 제거
<strong>다치 종속</strong>: 하나의 릴레이션에서 두 개의 속성이 2:N 대응되는 경우</p>
<h4 id="제5-정규화">제5 정규화</h4>
<p>제4 정규화를 만족한 테이블에 대해서 후보키를 통하지 않는 조인 종속(JD: Join Dependency)를 제거
조인 종속이 존재하는 릴레이션이 사용하기 편하므로, 이는 지나치게 이상적인 정규형이다.
<strong>조인 종속</strong>: 테이블을 분해한 결과를 다시 조인했을 때 원래의 테이블과 동일하게 복원되는 제약 조건으로, 다치 종속의 개념을 더 일반화한 것</p>
<p>일반적으로는 제3정규형이나 BCNF에 속하도록 릴레이션을 분해한다.</p>
<h3 id="트랜잭션">트랜잭션</h3>
<h4 id="트랜잭션이란">트랜잭션이란?</h4>
<ul>
<li>데이터베이스의 상태를 변화시키기 위해 수행하는 작업 단위</li>
<li>한꺼번에 모두 수행되어야 할 일련의 연산들</li>
</ul>
<h4 id="트랜잭션-특징">트랜잭션 특징</h4>
<ul>
<li>데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위다.</li>
<li>사용자가 시스템에 대한 서비스 요구 시 시스템이 응답하기 위한 상태 변환 과정의 작업단위이다.</li>
<li>하나의 트랜잭션은 Commit되거나 Rollback된다.</li>
</ul>
<h4 id="트랜잭션의-성질acid">트랜잭션의 성질(ACID)</h4>
<p><strong>원자성(Atomicity)</strong></p>
<ul>
<li>트랜잭션의 연산은 DB에 모두 반영되거나 아예 반영되지 않아야 한다.</li>
<li>트랜잭션 내의 모든 명령은 반드시 완벽히 수행되어야 하며, 모두가 완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 한다.</li>
</ul>
<p><strong>일관성(Consistency)</strong></p>
<ul>
<li>트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 DB 상태로 변환한다.</li>
<li>시스템이 가지고 있는 고정요소는 트랜잭션 수행 전과 트랜잭션 수행 완료 후의 상태가 같아야 한다.</li>
</ul>
<p><strong>독립성, 격리성(Isolation)</strong></p>
<ul>
<li>둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수 없다.</li>
<li>수행 중인 트랜잭션은 완전히 완료될 때까지 다른 트랜잭션에서 수행 결과를 참조할 수 없다.</li>
</ul>
<p><strong>영속성, 지속성(Durability)</strong></p>
<ul>
<li>성공적으로 완료된 트랜잭션의 결과는 시스템이 고장나더라도 영구적으로 반영되어야 한다.</li>
</ul>
<h4 id="트랜잭션-격리-수준">트랜잭션 격리 수준</h4>
<p><strong>MySQL의 격리 수준</strong></p>
<ul>
<li>READ UNCOMMIT(커밋되지 않은 읽기) = 레벨 0<ul>
<li>SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 계층</li>
<li>트랜잭션에 처리 중이거나, 아직 Commit되지 않은 데이터를 다른 트랜잭션이 읽는 걸 허용함</li>
<li>DB의 일관성을 유지하는 것이 불가능</li>
<li>Dirty Read 발생</li>
</ul>
</li>
<li>READ COMMITTED(커밋된 읽기) = 레벨 1<ul>
<li>SELECT 문장이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기</li>
<li>Commit이 이루어진 트랜잭션만 조회 가능</li>
<li>기본적으로 사용하는 Isolation Level</li>
<li>Non-Repeatable Read 발생</li>
</ul>
</li>
<li>REPEATABLE READ(반복 가능한 읽기) = 레벨 2<ul>
<li>트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층</li>
<li>트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장</li>
<li>다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대해 수정 불가능</li>
<li>MySQL DBMS에서 기본으로 사용</li>
<li>Non-Repeatable Read 발생 X</li>
<li>즉, 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된 것만 보게 된다.</li>
<li><strong>Phantom Read 발생</strong></li>
</ul>
</li>
<li>SERIALIZABLE(직렬화 가능) = 레벨 3<ul>
<li>트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층</li>
<li>가장 엄격한 격리 수준으로 완벽한 읽기 일관성 모드 </li>
<li>다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대해 수정 및 입력 불가능</li>
</ul>
</li>
</ul>
<p><strong>Dirty Read</strong></p>
<ul>
<li>어떤 트랜잭션에서 아직 실행이 끝나지 않은 다른 트랜잭션에 의한 변경사항을 보게 되는 경우</li>
<li>커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상</li>
</ul>
<p><strong>Non-Repeatable Read</strong></p>
<ul>
<li>한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 일관성이 깨진 현상</li>
<li>한 트랜잭션에서 똑같은 SELECT를 수행했을 때 항상 같은 결과를 반환해야 한다는 Repeatable Read 정합성에 어긋남</li>
</ul>
<p><strong>Phantom Read</strong></p>
<ul>
<li>한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상</li>
<li>트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타남</li>
</ul>
<table>
<thead>
<tr>
<th align="left">격리 수준</th>
<th>DIRTY READ</th>
<th align="center">NON-REPEATABLE READ</th>
<th align="right">PHANTOM READ</th>
</tr>
</thead>
<tbody><tr>
<td align="left">READ UNCOMMITTED</td>
<td>O</td>
<td align="center">O</td>
<td align="right">O</td>
</tr>
<tr>
<td align="left">READ COMMITTED</td>
<td></td>
<td align="center">O</td>
<td align="right">O</td>
</tr>
<tr>
<td align="left">REPEATABLE READ</td>
<td></td>
<td align="center"></td>
<td align="right">O(InnoDB는 발생 X)</td>
</tr>
<tr>
<td align="left">SERIALIZATION</td>
<td></td>
<td align="center"></td>
<td align="right"></td>
</tr>
</tbody></table>
<p>Ref:
<a href="https://coding-factory.tistory.com/226">https://coding-factory.tistory.com/226</a>
<a href="https://joont92.github.io/db/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80-isolation-level/">https://joont92.github.io/db/트랜잭션-격리-수준-isolation-level/</a>
<a href="https://zzang9ha.tistory.com/381">https://zzang9ha.tistory.com/381</a>
<a href="https://dar0m.tistory.com/225">https://dar0m.tistory.com/225</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 영어 끝말잇기(Lv.2)]]></title>
            <link>https://velog.io/@min_amim/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0Lv.2</link>
            <guid>https://velog.io/@min_amim/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0Lv.2</guid>
            <pubDate>Thu, 16 Feb 2023 10:03:07 GMT</pubDate>
            <description><![CDATA[<pre><code>import java.util.ArrayList;
import java.util.List;

public class Shiritori {
    public int[] solution(int n, String[] words) {

        /**
         * 가장 먼저 탈락하는 사람의 번호와 몇 번째 차례에 탈락하는지 return
         */

        int[] answer = new int[2];

        List&lt;String&gt; arr = new ArrayList&lt;&gt;();
        answer[0] = 0;
        answer[1] = 0;

        arr.add(words[0]);

        for(int i = 1; i &lt; words.length; i++) {

            String now = words[i];
            String previous = words[i - 1];

            if(arr.contains(now) || now.charAt(0) != previous.charAt(previous.length() - 1)) {
                answer[0] = (i % n) + 1;
                answer[1] = (i / n) + 1;
            }

            arr.add(now);
        }
        return answer;
    }
}
</code></pre><p>실패.. ㅇㅅㅇ</p>
<pre><code>import java.util.ArrayList;
import java.util.List;

public class Shiritori {
    public int[] solution(int n, String[] words) {

        /**
         * 가장 먼저 탈락하는 사람의 번호와 몇 번째 차례에 탈락하는지 return
         */

        int[] answer = new int[2];

        List&lt;String&gt; arr = new ArrayList&lt;&gt;();
        answer[0] = 0;
        answer[1] = 0;

        arr.add(words[0]);

        for(int i = 1; i &lt; words.length; i++) {

            String now = words[i];
            String previous = words[i - 1];

            if(arr.contains(now) || now.charAt(0) != previous.charAt(previous.length() - 1)) {
                answer[0] = (i % n) + 1;
                answer[1] = (i / n) + 1;
                break;
            }

            arr.add(now);
        }
        return answer;
    }
}
</code></pre><p>마지막에 break; 넣어주니까 통과</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동시성 문제와 스레드 로컬]]></title>
            <link>https://velog.io/@min_amim/%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C%EC%99%80-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@min_amim/%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C%EC%99%80-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C</guid>
            <pubDate>Wed, 28 Dec 2022 15:38:24 GMT</pubDate>
            <description><![CDATA[<h3 id="동시성-이슈란">동시성 이슈란?</h3>
<blockquote>
<p>두 개 이상의 스레드가 동시에 같은 자원에 접근해 값을 <strong>변경</strong>할 때 발생할 수 있는 문제를 의미한다.</p>
</blockquote>
<p>스프링 컨테이너는 싱글턴 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리한다.
따라서 멀티 스레드 환경에서 여러 스레드가 같은 인스턴스 필드에 접근하면서 트래픽이 많아질 때 동시성 문제가 발생할 수 있다.</p>
<p>지역 변수의 경우 스레드마다 각각 다른 메모리 영역이 할당되므로 동시성 문제가 발생하지 않는다.
같은 인스턴스의 필드 또는 static과 같은 공용 필드에 접근할 때 주로 발생한다.</p>
<h3 id="싱글톤-패턴singleton-pattern">싱글톤 패턴(Singleton pattern)</h3>
<blockquote>
<p>최초 한 번만 메모리를 할당하고(static) 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴이다.</p>
</blockquote>
<p>생성자가 여러 번 호출되더라도 실제로 생성되는 객체는 하나이고, 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.</p>
<p>고정된 메모리 영역을 얻으면서 한 번 생성한 객체를 사용하기 때문에 요청이 많은 곳에서 사용하면 효율을 높일 수 있다.</p>
<h3 id="thread">Thread</h3>
<blockquote>
<p>프로세스란 실행 중인 하나의 어플리케이션을 말하고, 스레드는 한 프로세스 내에서 동작되는 여러 실행 흐름이다.</p>
</blockquote>
<p>즉, 프로세스는 운영체제로부터 할당받는 작업 단위이며, 스레드는 프로세스가 할당받은 자원을 이용하는 실행의 단위다.</p>
<h3 id="threadlocal">ThreadLocal</h3>
<blockquote>
<p>해당 스레드만 접근할 수 있는 별도의 내부 저장소를 제공한다. 따라서 같은 인스턴스의 스레드 로컬 필드에 접근해도 문제가 발생하지 않는다.</p>
</blockquote>
<p>이 때 스레드 로컬에 저장된 값을 제거해주지 않으면 다른 사용자의 값에 접근할 수 있기 때문에 꼭 ThreadLocal.remove()를 이용해 값을 제거해줘야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 기초]]></title>
            <link>https://velog.io/@min_amim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@min_amim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Mon, 25 Oct 2021 06:09:27 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트 기초 공부하기</p>
<h3 id="var-const-let">var, const, let</h3>
<p>var: 함수 스코프를 가져 블록과 관계 없이 접근 가능
const, let: 블록 스코프를 가져 블록 밖에서는 변수에 접근 불가능</p>
<p>const: 한 번 값을 할당하면 다른 값 할당 불가, 초기화할 때 값을 할당해줘야 함(상수)
let: 변수</p>
<h3 id="객체-리터럴">객체 리터럴</h3>
<p>객체의 메서드에 함수를 연결할 때 콜론과 function을 붙이지 않아도 된다.
속성명과 변수명이 동일한 경우에는 한 번만 써도 된다.
객체의 속성명은 동적으로 생성할 수 있다.</p>
<h3 id="화살표-함수">화살표 함수</h3>
<p>function 선언 대신 &#39;=&gt;&#39; 기호로 함수 선언
기존 function과 this 바인드 방식이 다름
화살표 함수는 상위 스코프의 this를 그대로 물려받는다.</p>
<h3 id="클래스">클래스</h3>
<p>클래스 기반이 아닌 프로토타입 기반으로 동작
문법을 보기 좋게 클래스로 바꾼 것</p>
<h2 id="프로미스">프로미스</h2>
<p>ES2015부터 자바스크립트와 노드의 API 대신 프로미스 기반으로 재구성
중요한 객체!</p>
<ol>
<li>프로미스 객체 생성<pre><code>const promise = new Promise((resolve, reject) =&gt; {
if (condition) {
resolve(&#39;성공&#39;);
} else {
reject(&#39;실패&#39;);
}
});
</code></pre></li>
</ol>
<p>promise
 .then((message) =&gt; {
  console.log(message); //성공(resolv)한 경우 실행
 })
 .catch((error) =&gt; {
  console.error(error); //실패(reject)한 경우 실행
 })
 .finally(() =&gt; {
  console.log(&#39;무조건&#39;);
 });</p>
<pre><code>- 실행은 바로 하되 결괏값은 나중에 받는 객체
- 결괏값은 실행 완료 후 then이나 catch 메서드를 통해 받음
- new Promise는 바로 실행되지만 결괏값은 then을 붙였을 때 받게 됨
- then이나 catch에서 다른 then이나 catch를 붙일 수 있다
- 이전 then의 return 값을 다음 then의 매개변수로 넘긴다

### async/await
프로미스를 사용한 코드를 한 번 더 줄여준다.</code></pre><p>async function findAndSaveUser(Users){
 try {
  let user = await Users.findOne({});
  user.name = &#39;zero&#39;;
  user = await user.save();
  user = await Users.findOne({ gender: &#39;m&#39;});
 } catch(error) {
    console.error(error);
   }
}</p>
<p>```</p>
<p>코드 예제: [Node.js 교과서 개정2판], 조현영 참고</p>
]]></description>
        </item>
    </channel>
</rss>