<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>k-moovie.log</title>
        <link>https://velog.io/</link>
        <description>mv 의 Velog</description>
        <lastBuildDate>Sat, 22 Jan 2022 13:59:13 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. k-moovie.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/k-moovie" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[💡 무중단 배포를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sat, 22 Jan 2022 13:59:13 GMT</pubDate>
            <description><![CDATA[<h1 id="무중단-배포">무중단 배포</h1>
<h2 id="무중단-배포란">무중단 배포란?</h2>
<p>![](<a href="https://images.velog.io/images/k-moovie/post/7a8ec251-1b51-4622-8b18-a0de57beb76a/image.png">https://images.velog.io/images/k-moovie/post/7a8ec251-1b51-4622-8b18-a0de57beb76a/image.png</a></p>
<blockquote>
<p>운영 중인 서비스를 중단하지 않고 신규 소프트웨어를 배포하는 기술</p>
</blockquote>
<ul>
<li><p>서비스 중인 인스턴스가 하나일 때 새 버전의 서비스를 배포하는 과정은 다음과 같다</p>
<ul>
<li><img src="https://images.velog.io/images/k-moovie/post/2e1f72e8-3364-4e81-bdb9-7ea829069894/image.png" alt=""></li>
</ul>
<blockquote>
<p>v1을 종료한 뒤 v2를 실행하기까지의 시간을 다운타임(downtime)이라고 한다</p>
</blockquote>
</li>
<li><p><strong>로드밸런서</strong>를 통해 연결된 두 개 이상의 인스턴스에 트래픽을 제어해 배포</p>
</li>
<li><p>고가용성(HA)의 시스템 인프라가 구성되어 있을 때 사용 가능</p>
</li>
</ul>
<h2 id="reverse-proxy-load-balancing">Reverse Proxy, Load Balancing</h2>
<ul>
<li>여러 대의 서버 인스턴스가 있어야 무중단 배포를 할 수 있다</li>
<li>동일한 IP로 여러 대의 서버 인스턴스에 접근하려면 클라이언트와 서버 사이를 중계하는 역할이 필요하다</li>
<li>새 버전의 서비스를 가지는 인스턴스로 연결을 전달하는 역할이 필요하다</li>
</ul>
<h3 id="reverse-proxy">Reverse Proxy</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/f33dc993-c3e4-44a5-a5ee-d08afc23e49d/image.png" alt=""></p>
<ul>
<li>프록시는 클라이언트가 자신(프록시)을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 것이다</li>
<li>리버스 프록시는 클라이언트가 서버를 호출할 때 리버스 프록시를 호출하며, 서버의 요청을 리버스 프록시가 받아 클라이언트에게 전달한다<ul>
<li>이는 서버가 누구인지 감추는 역할을 한다</li>
<li>클라이언트는 리버스 프록시 서버를 먼저 호출하여 실제 서버의 IP를 알 수 없다</li>
</ul>
</li>
</ul>
<h3 id="load-balancing">Load Balancing</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/d3f1ee8d-5efa-4799-8dd7-cc6e5c8f8b17/image.png" alt=""></p>
<ul>
<li>여러 서버가 분산 처리하는 것</li>
<li>하나의 서버에서 받아야할 요청을 여러 개의 서버로 분산</li>
</ul>
<h2 id="rolling-배포">Rolling 배포</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/b46958a0-022a-4f6d-8db8-3a8d6363c3a9/image.png" alt=""></p>
<ul>
<li>일반적인 배포 방식</li>
<li>서버를 한 대씩 구 버전에서 새 버전으로 교체하는 전략</li>
<li>서비스 중인 서버 한 대를 제외하고 그 자리에 새 버전의 서버를 추가</li>
<li>구 버전에서 새 버전으로 트래픽을 점진적으로 전환</li>
</ul>
<h2 id="carany-배포">Carany 배포</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/38ee2655-40b5-4517-8593-f8bd17db045d/image.png" alt=""></p>
<ul>
<li>일산화탄소 및 유독가스에 민감한 카나리아 새를 옆에 두고 광부들이 일을하는 것에 유래</li>
<li>새 처럼 위험을 빠르게 감지할 수 있는 배포 기법</li>
<li>구 버전의 서버와 새 버전의 서버를 구성, 일부 트래픽을 새 버전으로 분산하여 오류 여부 판단</li>
<li>분산 결과에 따라 새 버전이 운영환경을 대체하거나 롤백함</li>
</ul>
<h2 id="blue-green-배포">Blue-green 배포</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/5e204187-dc98-4678-ba79-b8ef6500b52d/image.png" alt=""></p>
<ul>
<li>구 버전에서 새 버전으로 일제히 전환하는 전략</li>
<li>구 버전의 서버와 새 버전의 서버들을 동시에 구성</li>
<li>배포 시점이 되면 트래팍을 일제히 전환</li>
<li>배포 중 오류 발생 시 빠른 롤백이 가능</li>
<li>시스템 자원이 두 배로 필요함</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://velog.io/@znftm97/%EB%AC%B4%EC%A4%91%EB%8B%A8-%EB%B0%B0%ED%8F%AC%EB%A5%BC-%EC%9C%84%ED%95%9C-%ED%99%98%EA%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0">무중단 배포란? 무중단 배포를 위한 환경 이해하기
</a></li>
<li><a href="https://firework-ham.tistory.com/23">배포 전략: Rolling, Blue/Green, Canary</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 Quartz Scheduler를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/Quartz-Scheduler%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/Quartz-Scheduler%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 21 Jan 2022 08:44:13 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/2664f978-8146-4fd2-9ad3-a84689f89730/image.png" alt=""></p>
<h1 id="quartz-scheduler">Quartz Scheduler</h1>
<h2 id="quartz-scheduler-란">Quartz Scheduler 란?</h2>
<blockquote>
<p>배치 프로그램을 <strong>일정 시간, 주기적</strong>으로 동작하도록 만든 라이브러리</p>
</blockquote>
<ul>
<li>Spring Batch와 혼용하기 쉬우나 각각의 <strong>차이</strong>는 다음과 같다<ul>
<li>Quartz Scheduler: <strong>언제</strong> 실행시킬 것인가?</li>
<li>Spring Batch: <strong>무엇</strong>을 실행할 것인가?<ul>
<li><a href="https://jojoldu.tistory.com/324">참고: 이동욱님의 Spring Batch 가이드 시리즈</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="quartz-scheduler의-특징">Quartz Scheduler의 특징</h2>
<ul>
<li><strong>DB 기반</strong>으로 스케줄러 간의 <strong>Clustering 기능</strong>을 제공</li>
<li>In-memory Job Scheduler도 제공</li>
<li>Admin UI을 제공하지 않음</li>
<li>스케줄링 실행에 대한 History는 보관하지 않음</li>
</ul>
<h2 id="quartz-scheduler-구성-요소">Quartz Scheduler 구성 요소</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/33e85cee-2f96-44e1-b1f2-61b24d5e9480/image.png" alt=""></p>
<h3 id="job">Job</h3>
<ul>
<li>Quartz API에서 단 하나의 메서드를 가진 execute(JobExecutionContext) Job interface를 제공</li>
<li>Quartz에서 수행해야 하는 실제 작업을 이 메서드에서 구현</li>
</ul>
<h3 id="jobdatamap">JobDataMap</h3>
<ul>
<li>Job 인스턴스가 실행할 때 사용할 수 있게 원하는 정보를 담을 수 있는 객체</li>
</ul>
<h3 id="jobdetail">JobDetail</h3>
<ul>
<li>Job을 실행시키기 위한 정보를 담고있는 객체<ul>
<li>이름, 그룹, JobDataMap 속성 등 지정</li>
</ul>
</li>
<li>Trigger가 Job을 수행할 때 이 정보를 기반으로 스케줄링 함</li>
</ul>
<h3 id="trigger">Trigger</h3>
<ul>
<li>Job을 실행시킬 스케줄링 조건<ul>
<li>반복 횟수, 시작 시간</li>
</ul>
</li>
<li>Tigger와 Job의 관계<ul>
<li>1 Trigger = 1 Job: 반드시 하나의 Trigger는 하나의 Job을 지정할 수 있다</li>
<li>N Trigger = 1 Job: 하나의 Job을 여러 시간으로 실행 시킬 수 있다.</li>
</ul>
</li>
</ul>
<h3 id="jobstore">JobStore</h3>
<ul>
<li><p>JDBCJobStore</p>
<ul>
<li>default 값으로 메모리에 스케줄 정보를 저장</li>
<li>시스템 문제 발생 시 스케줄 데이터가 날라감</li>
</ul>
</li>
<li><p>RAMJobStore</p>
<ul>
<li>스케줄 정보를 DB에 저장</li>
<li>시스템이 셧다운 되더라도 스케줄 정보가 유지되므로 시스템 재시작시 다시 Job을 실행</li>
</ul>
</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://advenoh.tistory.com/51">Quartz Job Scheduler란?</a></li>
<li><a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=beanpole2020&amp;logNo=221463397399">Java용 작업 스케줄러 - Quartz</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 CORS를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/CORS%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/CORS%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 18 Jan 2022 05:58:33 GMT</pubDate>
            <description><![CDATA[<h1 id="cors">CORS</h1>
<h2 id="cors란">CORS란?</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/ef342d82-cd50-484a-b0bf-2a681612bad4/image.png" alt=""></p>
<blockquote>
<p>SOP의 시나리오와 CORS 시나리오를 설명한 사진</p>
</blockquote>
<ul>
<li><strong>Cross-Origin Resource Sharing</strong> (교차 출처 리소스 공유)</li>
<li>한 출처에서 실행 중인 웹 어플리케이션이 <strong>다른 출처의 선택한 자원에 접근할 수 있는 권한</strong>을 부여하도록 브라우저에 알려주는 체제</li>
<li>출처는 <strong>도메인, 프로토콜, 포트</strong>가 모두 동일함을 뜻함</li>
<li><strong>브라우저</strong>에서는 <strong>동일 출처 정책 (SOP)</strong> 로 인해 다른 출처 간 <strong>자원(데이터) 이동이 금지</strong></li>
</ul>
<h2 id="sop-same-origin-policy">SOP (Same-Origin Policy)</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/4b011804-b32f-4bcd-82e5-6342f637fa64/image.png" alt=""></p>
<blockquote>
<p>CORS를 알아보기 전 먼저 SOP에 대해 알아보자</p>
</blockquote>
<ul>
<li>교차 출처 정책으로 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한함</li>
<li>XMLHttpRequest(fetch() 와 같은)요소를 사용할 때 상호작용을 통제<ul>
<li>Chrome의 개발자 도구에서 Fetch/XHR 항목
<img src="https://images.velog.io/images/k-moovie/post/f05d6266-da73-4855-a35b-487772655093/image.png" alt=""></li>
</ul>
</li>
</ul>
<h2 id="sop-cors에서-origin-출처-이란">SOP, CORS에서 Origin (출처) 이란?</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/f3678e7b-b957-4b39-9902-6d80244bcfa1/image.png" alt=""></p>
<ul>
<li>출처는 <strong>Protocol, Host, Port</strong>가 <strong>모두 동일</strong>할 때 <strong>동일 출처</strong>라고 한다.</li>
<li>위의 예시에서 <strong>https는 443포트</strong>를 사용함으로 <strong>생략 가능</strong>하다.</li>
<li><code>https://velog.io:443/@k-moovie</code> 는 동일 출처이다</li>
</ul>
<h2 id="cors란-1">CORS란?</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/3a769bff-1a83-48f2-8ad8-116a49b0af11/image.png" alt=""></p>
<ul>
<li><p>웹 기술이 발전함에 따라 브라우저에서 다른 사이트의 자원(이미지와 같은)을 요청할 수 있다.</p>
</li>
<li><p>기본적으로 웹 클라이언트 어플리케이션이 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 request를 보낸다</p>
</li>
<li><p>이 때 브라우저는 <code>request header</code>의 <code>Origin</code>필드에 요청을 보내는 출처를 함께 담아 보낸다.</p>
<blockquote>
<p>Origin: <a href="https://velog.io/@k-moovie">https://velog.io/@k-moovie</a></p>
</blockquote>
</li>
<li><p>이후 서버에서 응답을 보낼 때 <code>response header</code>의 <code>Access-Control-Allow-Origin</code> 필드에 &#39;이 리소스를 접근하는 것이 허용된 출처&#39;를 전송한다.</p>
</li>
<li><p>브라우저는 자신이 보낸 <code>Origin</code>과 서버에서 온 응답의 <code>Access-Control-Allow-Origin</code>를 비교해 같다면 허용한다.</p>
</li>
</ul>
<h2 id="cors의-다양한-시나리오">CORS의 다양한 시나리오</h2>
<h3 id="preflight-request">Preflight Request</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/8e020861-9a01-46f9-8060-e4e2d840d141/image.png" alt=""></p>
<ul>
<li>일반적으로 웹 어플리케이션을 개발할 때 흔히 마주하는 시나리오</li>
<li><strong>예비 요청과</strong> <strong>본 요청</strong>으로 두 번 전송<pre><code class="language-http"></code></pre>
</li>
</ul>
<p>OPTIONS <a href="https://velog.io/@k-moovie">https://velog.io/@k-moovie</a></p>
<p>Accept: <em>/</em>
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: velog.io
Origin: <a href="https://velog.io">https://velog.io</a>
Referer: <a href="https://velog.io/@k-moovie/user">https://velog.io/@k-moovie/user</a>
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site</p>
<pre><code>- 예비 요청은 method가 OPTIONS로 전송된다
  - 본 요청에 사용할 다른 정보를 (method, header 등) 같이 전송한다.

```http
OPTIONS https://velog.io/@k-moovie 200 OK

Access-Control-Allow-Origin: https://velog.io
Content-Encoding: gzip
Content-Length: 699
Content-Type: text/xml; charset=utf-8
Date: Sun, 24 May 2020 11:52:33 GMT
P3P: CP=&#39;ALL DSP COR MON LAW OUR LEG DEL&#39;
Server: Apache
Vary: Accept-Encoding
X-UA-Compatible: IE=Edge</code></pre><ul>
<li>서버는 예비 요청의 응답으로 Access-Control-Allow-Origin을 반환한다.</li>
</ul>
<h3 id="simple-request">Simple Request</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/24352cc5-9c1e-4828-a46c-be6db4435fdb/image.png" alt=""></p>
<ul>
<li>서버에 곧바로 요청을 보내는 것으로 서버는 다른 출처의 요청을 가리지 않으므로 사용 시 주의가 필요하다</li>
<li>Preflight Request에서 예비 요청을 제거한 것</li>
<li>아래의 제한 사항이 있다<blockquote>
<ul>
<li>요청의 메소드는 <code>GET, HEAD, POST</code> 중 하나여야 한다.</li>
<li><code>Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width</code>를 제외한 헤더를 사용하면 안된다.</li>
<li><code>Content-Type</code>를 사용하는 경우에는 <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code>, <code>text/plain</code>만 허용된다.</li>
</ul>
</blockquote>
</li>
</ul>
<h3 id="credentialed-request">Credentialed Request</h3>
<ul>
<li>다른 출처 간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법</li>
<li>기본적으로 브라우저가 제공하는 비동기 리소스 요청 API인 XMLHttpRequest 객체나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다</li>
<li>요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션</li>
<li>아래와 같은 제한 사항이 있다<blockquote>
<ul>
<li><code>Access-Control-Allow-Origin</code>에는 <code>*</code>를 사용할 수 없으며, 명시적인 URL이어야한다.</li>
<li>응답 헤더에는 반드시 <code>Access-Control-Allow-Credentials: true</code>가 존재해야한다.</li>
</ul>
</blockquote>
</li>
</ul>
<h2 id="더-알아보기">더 알아보기</h2>
<h3 id="spring에서-cors를-해결하는-방법">Spring에서 CORS를 해결하는 방법</h3>
<ul>
<li>Servlet Filter를 사용하여 커스텀한 Cors 설정</li>
<li>WebMvcConfiguer를 구현한 Configuration 클래스를 만들어서 addCorsMappings()를 재정의</li>
<li>Spring Security에서 CorsConfigurationSource를 Bean으로 등록하고 config에 추가</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTTP/CORS">교차 출처 리소스 공유 (CORS)</a></li>
<li><a href="https://evan-moon.github.io/2020/05/21/about-cors/">CORS는 왜 이렇게 우리를 힘들게 하는걸까?</a></li>
<li><a href="https://www.youtube.com/watch?v=bW31xiNB8Nc">웹개발 짜증유발자! CORS가 뭔가요?</a></li>
<li>[**CORS 우회를 위한 자바스크립트(POST) 실험</li>
<li>*](<a href="https://www.youtube.com/watch?v=5dm9sQ8MLqs">https://www.youtube.com/watch?v=5dm9sQ8MLqs</a>)</li>
<li>[**[10분 테코톡] 🌳 나봄의 CORS</li>
<li>*](<a href="https://www.youtube.com/watch?v=-2TgkKYmJt4&amp;t=133s">https://www.youtube.com/watch?v=-2TgkKYmJt4&amp;t=133s</a>)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡Index를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/Index%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/Index%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Mon, 17 Jan 2022 13:44:17 GMT</pubDate>
            <description><![CDATA[<h1 id="index">Index</h1>
<h2 id="index란">Index란?</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/f3895505-4587-47b5-8a07-ebdc194e601d/image.png" alt=""></p>
<ul>
<li>추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 <strong>검색 속도를 향상</strong>시키기 위한 자료구조</li>
<li>자주 조회되는 Column에 대한 <strong>Index Table을 따로 만들어</strong> SELECT 문 수행 시 Index Table에 있는 값으로 결과를 조회 </li>
<li>만약 Index를 적용하지 않은 컬럼을 조회할 시. Full Scan이 수행</li>
<li>주로 <strong>B+tree</strong>로 구성된 구조를 사용</li>
</ul>
<h2 id="index-사용-시-주의할-점">Index 사용 시 주의할 점</h2>
<ul>
<li><strong>항상 정렬된 상태를 유지</strong>하기 때문에 원하는 값을 탐색하는 것은 빠르다</li>
<li>새로운 값을 추가하거나 삭제, 수정하는 경우에는 쿼리문 실행 속도가 느려짐<ul>
<li>INSERT: 테이블에는 입력 순서대로 저장, 인덱스 테이블에는 정렬하여 저장하기 때문에 성능 저하 발생</li>
<li>UPDATE: 인덱스에는 UPDATE가 없어서, DELETE 후 INSERT하는 작업을 수행해 부하 발생</li>
<li>DELETE: 테이블에서만 삭제되고 인덱스 테이블에는 남아있어 쿼리 수행 속도 저하</li>
</ul>
</li>
<li>데이터의 중복이 높은 컬럼 (<strong>cardinality가 낮은 컬럼</strong>)을 인덱스로 생성 시 <strong>불리함</strong><ul>
<li>선택하는 데이터가 많아질수록 Full scan에 가까워진다</li>
</ul>
</li>
</ul>
<h2 id="primary-index-vs-secondary-index">Primary Index vs Secondary Index</h2>
<h3 id="primary-index">Primary Index</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/35c1dd02-60c3-4cb8-bb70-c7f2cd8c7915/image.png" alt=""></p>
<ul>
<li>기본키를 포함하는 인덱스 (키의 순서가 레코드의 순서를 결정)</li>
<li>정렬된 파일</li>
<li>Clustering Index라고도 불림<h3 id="secondary-index">Secondary Index</h3>
<img src="https://images.velog.io/images/k-moovie/post/51fab060-05a2-4e07-b287-acbb6071e8cb/image.png" alt=""></li>
<li>기본 인덱스 이외의 인덱스 (키의 순서가 레코드의 순서를 의미하지 않음)</li>
</ul>
<h2 id="b-tree">B-+tree</h2>
<h3 id="b-tree-1">B-tree</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/050b6e52-f336-4bd6-b049-1431a01aebbc/image.png" alt=""></p>
<ul>
<li>노드의 자료수가 N이라면 자식의 수는 N+1이어야 한다. </li>
<li>각 노드의 자료는 정렬된 상태여야 한다.</li>
<li>노드의 자료Dk의 왼쪽 서브트리는 Dk보다 작은 값들이고 오른쪽 서브트리는 Dk보다 큰 값들이어야 한다.</li>
<li>Root 노드는 적어도 2개이상의 자식을 가져야 한다.</li>
<li>Root 노드를 제외한 모든 노드는 적어도 M/2개의 자료를 가지고 있어야 한다.</li>
<li>외부 노드로 가는 경로의 길이는 모두 같다. </li>
<li>외부노드는 모두 같은 레벨에 있다</li>
<li>입력자료는 중복될 수 없다. </li>
</ul>
<h3 id="btree">B+tree</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/6e80e172-b12d-4e8f-bc8e-e157b0ea7338/image.png" alt=""></p>
<ul>
<li>B-tree의 각 노드에서는 key 뿐만 아니라 data도 들어갈 수 있다. <ul>
<li>여기서 data는 disk block으로의 포인터가 될 수 있다.</li>
</ul>
</li>
<li>B+tree는 각 node에서는 key만 들어가야 한다.<ul>
<li>B+tree에서는 data는 오직 leaf에만 존재한다.</li>
</ul>
</li>
<li>B+tree는 B-tree와는 달리 add, delete가 leaf에서만 이루어진다.</li>
<li>B+ tree는 leaf node 끼리 linked list로 연결되어 있다.</li>
</ul>
<h2 id="더-알아보기">더 알아보기</h2>
<h3 id="index를-생성하는데-hash와-btree-중-btree를-사용할까">Index를 생성하는데 Hash와 B+tree 중 B+tree를 사용할까?</h3>
<ul>
<li>Hash Table의 경우 O(1)의 시간복잡도를 보장해 B+tree보다 빠르다</li>
<li>SELECT 질의의 조건에는 부등호(&lt;, &gt;) 연산을 포함한다</li>
<li>Hash Table의 경우 등호(=)를 제외한 부등호 연산의 경우 부적합하다</li>
</ul>
<h3 id="여러-column의-index-사용">여러 Column의 Index 사용</h3>
<ul>
<li>인덱스의 모든 컬럼을 사용할 필요는 없다. (누락이 가능하다)</li>
<li>아래와 같이 Index가 잡혀있다.<blockquote>
<p>Index: A, B, C</p>
</blockquote>
</li>
</ul>
<ul>
<li><p>아래 쿼리문은 실행 계획 분석 시 <strong>인덱스를 사용했다</strong>.</p>
<blockquote>
<p>explain SELECT * 
FROM EXAMPLE
WHERE
A = &#39;EXAMPLE&#39;
AND C = true;</p>
</blockquote>
</li>
<li><p>아래 쿼리문은 실행 계획 분석 시 인덱스를 <strong>사용하지 않았다</strong>.</p>
<blockquote>
<p>explain SELECT * 
FROM EXAMPLE
WHERE
B = &#39;2002-07-30&#39;
AND C = true;</p>
</blockquote>
</li>
<li><p>조회 쿼리 사용 시 인덱스를 사용하려면 최소한 <strong>첫번째 인덱스 조건은 조회 조건에 포함</strong>되어야한다.</p>
</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://github.com/WeareSoft/tech-interview/blob/master/contents/db.md#index%EB%9E%80">Tech Interview</a></li>
<li><a href="https://jojoldu.tistory.com/243">[mysql]인덱스 정리 및 팁</a></li>
<li><a href="https://lssang.tistory.com/29">클러스터드 인덱스 / 넌클러스터드 인덱스 / primary 인덱스</a></li>
<li><a href="https://lng1982.tistory.com/144">클러스터드 인덱스와 넌 클러스터드 인덱스</a></li>
<li><a href="https://jungwoong.tistory.com/34">[MSSQL]인덱스의 내부 동작방식</a></li>
<li><a href="https://kay0426.tistory.com/70">Clustered Index와 Secondary Index</a></li>
<li><a href="https://wangin9.tistory.com/entry/B-tree-B-tree">[파일구조] B tree 와 B+ tree</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 Process와 Thread를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/Process%EC%99%80-Thread%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/Process%EC%99%80-Thread%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sun, 16 Jan 2022 05:49:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/5f764670-1e6c-4583-9133-bb2c9ae35763/image.png" alt=""></p>
<h1 id="process와-thread">Process와 Thread</h1>
<p><img src="https://images.velog.io/images/k-moovie/post/c8e60cbc-9abf-4eec-94f7-af0f45619698/image.png" alt=""></p>
<h2 id="process">Process</h2>
<ul>
<li>실행 중인 프로그램</li>
<li>디스크로부터 메모리에 적재되어 CPU의 할당을 받을 수 있음</li>
<li>코드, 데이터, 스택, 힙을 각각 할당 받음</li>
<li>한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, inter-process communication)을 사용해야 한다. <ul>
<li>Ex. 파이프, 파일, 소켓 등을 이용한 통신 방법 이용</li>
</ul>
</li>
</ul>
<h2 id="thread">Thread</h2>
<ul>
<li>프로세스의 실행 단위 (경량 프로세스)</li>
<li>같은 프로세스의 코드, 데이터, 힙 영역을 공유</li>
<li>각각의 프로세스는 별도의 레지스터와 스택을 갖는다</li>
</ul>
<h2 id="pcb">PCB</h2>
<ul>
<li>Process Control Block</li>
<li>특정 프로세스에 대한 중요한 정보를 저장</li>
<li>프로세스의 생성과 동시에 고유한 PCB 생성</li>
<li>프로세스는 CPU를 할당 받아 작업을 수행</li>
<li>인터럽트와 같은 상황에서 CPU를 반납하는데 이 때 작업의 진행 상황을 PCB에 저장</li>
</ul>
<blockquote>
<p>프로세스 식별자(Process ID, PID) : 프로세스 식별번호
프로세스 상태 : new, ready, running, waiting, terminated 등의 상태를 저장
프로그램 카운터 : 프로세스가 다음에 실행할 명령어의 주소
CPU 레지스터
CPU 스케쥴링 정보 : 프로세스의 우선순위, 스케줄 큐에 대한 포인터 등
메모리 관리 정보 : 페이지 테이블 또는 세그먼트 테이블 등과 같은 정보를 포함
입출력 상태 정보 : 프로세스에 할당된 입출력 장치들과 열린 파일 목록
어카운팅 정보 : 사용된 CPU 시간, 시간제한, 계정번호 등</p>
</blockquote>
<h2 id="문맥교환-context-swicthing">문맥교환 (Context Swicthing)</h2>
<blockquote>
<p>프로세스의 상태 정보를 저장하고 복원하는 일련의 과정
즉, 동작 중인 프로세스가 대기하면서 해당 프로세스의 상태를 보관하고, 대기하고 있던 다음 순번의 프로세스가 동작하면서 이전에 보관했던 프로세스 상태를 복구하는 과정을 말함
→ 프로세스는 각 독립된 메모리 영역을 할당받아 사용되므로, 캐시 메모리 초기화와 같은 무거운 작업이 진행되었을 때 오버헤드가 발생할 문제가 존재함</p>
</blockquote>
<h2 id="📚-더-알아보기">📚 더 알아보기</h2>
<h3 id="스택을-스레드마다-독립적으로-할당하는-이유">스택을 스레드마다 독립적으로 할당하는 이유</h3>
<ul>
<li>스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을 저장</li>
<li>스택 메모리 공간이 독립적이라는 것은 독립적인 함수 호출이 가능하다는 것이고 이는 독립적인 실행 흐름이 추가되는 것</li>
<li>스레드의 정의에 따라 독립적인 실행 흐름을 추가하기 위한 최소 조건으로 독립된 스택을 할당</li>
</ul>
<h3 id="pc-register-를-스레드마다-독립적으로-할당하는-이유">PC Register 를 스레드마다 독립적으로 할당하는 이유</h3>
<ul>
<li>PC 값은 스레드가 명령어의 어디까지 수행하였는지를 나타냄</li>
<li>스레드는 CPU 를 할당받았다가 스케줄러에 의해 다시 선점당한다. </li>
<li>명령어가 연속적으로 수행되지 못하고 어느 부분까지 수행했는지 기억해야함</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/master/OS">Interview_Question_for_Beginner</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡TCP 3-way-handshake를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/TCP-3-way-handshake%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/TCP-3-way-handshake%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sun, 16 Jan 2022 04:24:07 GMT</pubDate>
            <description><![CDATA[<h1 id="tcp-3-way-handshake">TCP 3-way-handshake</h1>
<h2 id="tcp-3-way-handshake-란">TCP 3-way-handshake 란?</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/2f6ec8cb-80e3-44be-8b63-68083acb8ee8/image.png" alt="">
<img src="https://images.velog.io/images/k-moovie/post/987a1927-4c73-41cd-b293-15983e2b6947/image.png" alt=""></p>
<ul>
<li>TCP는 연결 지향적</li>
<li><strong>오류제어, 흐름제어, 혼잡제어</strong>, 타이머 재전송 등의 기능 제공</li>
<li>송신측과 수신측 사이에 <strong>전용의 데이터 전송 송로(Session)</strong> 을 만든다</li>
<li>TCP와 IP를 함께 사용하는데, <strong>IP</strong>가 <strong>데이터의 배달</strong>을 처리한다면 <strong>TCP</strong>는 <strong>패킷을 추적 및 관리</strong>한다.</li>
<li>전송 제어 프로토콜(TCP)에서 통신을 하는 장치간 서로 연결이 잘 되었는지 확인하는 과정</li>
</ul>
<h2 id="용어-정리">용어 정리</h2>
<ul>
<li><p>SYN: Synchronized sequence number</p>
<ul>
<li>Sequence Number를 랜덤으로 설정하여 세션을 연결하는 데 사용하며, 초기에 Sequence Number를 전송</li>
</ul>
</li>
<li><p>ACK: Acknowledgement</p>
<ul>
<li>Sequence Number를 랜덤으로 설정하여 세션을 연결하는 데 사용하며, 초기에 Sequence Number를 전송</li>
</ul>
</li>
<li><p>CLOSED: 포트가 닫힌 상태</p>
</li>
<li><p>LISTEN: 포트가 열린 상태로 연결 요청 대기 중</p>
</li>
<li><p>SYN_RCV: SYNC 요청을 받고 상대방의 응답을 기다리는 중</p>
</li>
<li><p>ESTABLISHED: 포트 연결 상태</p>
</li>
</ul>
<h2 id="tcp-3-way-handshake-동작-과정">TCP 3-way-handshake 동작 과정</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/e0cdd48e-b572-4fae-845d-bd8055ee938b/image.png" alt=""></p>
<h3 id="a---b-syn">A -&gt; B: SYN</h3>
<ul>
<li>접속 요청 프로세스 A가 연결 요청 메시지 전송 SYN(10)</li>
<li>송신자가 최초로 데이터를 전송할 때 Sequence Number를 임의의 랜덤 숫자로 지정하고, SYN 플래그 비트를 1로 설정한 세그먼트를 전송한다.</li>
<li><strong>PORT 상태</strong> - B: LISTEN, A: CLOSED</li>
</ul>
<h3 id="b---a-syn--ack">B -&gt; A: SYN + ACK</h3>
<ul>
<li>접속 요청을 받은 프로세스 B가 요청을 수락했으며, 접속 요청 프로세스인 A도 포트를 열어 달라는 메시지 전송 (SYN + ACK)</li>
<li>서버는 Acknowledgement Number 필드를 (10+1)로 지정하고, SYN과 ACK 플래그 비트를 1로 설정한 세그먼트를 전송한다.</li>
<li><strong>PORT 상태</strong> - B: SYN_RCV, A: CLOSED</li>
</ul>
<h3 id="a---b-ack">A -&gt; B: ACK</h3>
<ul>
<li><strong>PORT 상태</strong> - B: SYN_RCV, A: ESTABLISHED</li>
<li>마지막으로 접속 요청 프로세스 A가 수락 확인을 보내 연결을 맺음 (ACK)
이때, 전송할 데이터가 있으면 이 단계에서 데이터를 전송할 수 있다.</li>
<li><strong>PORT 상태</strong> - B: ESTABLISHED, A: ESTAB</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><p><a href="https://gmlwjd9405.github.io/2018/09/19/tcp-connection.html">[Network] TCP 3-way handshaking과 4-way handshaking
</a></p>
</li>
<li><p><a href="https://asfirstalways.tistory.com/356">[TCP] 3-way-handshake &amp; 4-way-handshake</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡Dispatcher Servlet을 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/Dispatcher-Servlet%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/Dispatcher-Servlet%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 14:58:02 GMT</pubDate>
            <description><![CDATA[<h1 id="dispatcher-servlet이란">Dispatcher Servlet이란?</h1>
<blockquote>
<p>Servlet Container에서 HTTP프로토콜을 통해 들어오는 모든 요청을 프레젠테이션 계층의 제일 앞에 둬서 중앙 집중식으로 처리해주는 프론트 컨트롤러(Front Controller)</p>
</blockquote>
<ul>
<li>dispatch는 &#39;보내다&#39; 라는 사전적 의미를 가진다</li>
<li>클라이언트로부터 요청을 받으면 Tomcat과 같은 서블릿 컨테이너가 요청을 받음</li>
<li>이때 제일 먼저 서버로 들어오는 모든 요청을 처리하는 프론트 컨트롤러를 스프링에서 Dispatcher Servlet이라고 함</li>
<li>공통처리 작업을 Dispatcher Servlet이 처리한 후, 세부 컨트롤러로 작업을 위임함</li>
</ul>
<h1 id="기존-servlet-vs-front-controller-pattern">기존 Servlet VS Front Controller Pattern</h1>
<h2 id="기존의-servlet">기존의 Servlet</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/dee6a1d4-06b5-4a51-87d8-12c06763408c/image.png" alt=""></p>
<ul>
<li>요청 url 당 servlet을 생성</li>
<li>해당 Controller에게 요청을 보내는 코드를 따로 작성</li>
<li>중복되는 로직이 있을 시 소스 중복 발생
예를 들어 서블릿에서 처리한 결과를 JSP에 넘기기 위해, RequestDispatcher에 forward를 해주는 로직은 매번 필요한 작업이었다.
<img src="https://images.velog.io/images/k-moovie/post/8ad74cff-6ed1-4cef-93ec-e87357400a4a/image.png" alt=""></li>
</ul>
<h2 id="front-controller-패턴-적용">Front Controller 패턴 적용</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/6261657c-72c1-4e87-b522-bad9ef941aea/image.png" alt=""></p>
<ul>
<li>하나의 Servlet에서 요청을 받아들여 적절한 Controller로 요청을 위임함</li>
<li>한 곳에서 모든 사용자의 요청을 컨트롤할 수 있음</li>
<li>사용자의 모든 요청에 대해 인코딩, 에러 등 에 대한 처리를 한 곳에서 관리할 수 있음</li>
</ul>
<h1 id="dispatcher-servlet">Dispatcher Servlet</h1>
<p><img src="https://images.velog.io/images/k-moovie/post/14423af4-b306-4f1d-bda5-60192fb332aa/image.png" alt=""></p>
<ul>
<li>모든 요청을 한 곳에서 받아 필요한 처리를 함</li>
<li>그 후 요청에 맞는 handler로 요청을 Dispatch함</li>
<li>Handler의 실행 결과를 HTTP Response 형태로 만듦</li>
</ul>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://insight-bgh.tistory.com/201">[Spring Framework] Dispatcher-Servlet 이란?</a></li>
<li><a href="https://devmoony.tistory.com/102">[Spring MVC] Dispatcher Servlet 이란?</a></li>
<li><a href="https://yoonbing9.tistory.com/79">Spring MVC의 핵심! FrontController 패턴과 DispatcherServlet</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡브라우저에서 사이트 접속 시 일어나는 상황을 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EC%A0%91%EC%86%8D-%EC%8B%9C-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%83%81%ED%99%A9%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-%EC%82%AC%EC%9D%B4%ED%8A%B8-%EC%A0%91%EC%86%8D-%EC%8B%9C-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%83%81%ED%99%A9%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 05:40:24 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/c280496d-40ec-408d-8d1d-a8038e400c06/image.png" alt=""></p>
<h1 id="브라우저에서-wwwexamplecom-접속시">브라우저에서 <a href="http://www.example.com">www.example.com</a> 접속시</h1>
<h2 id="1-브라우저-주소창에-wwwexamplecom을-입력한다">1. 브라우저 주소창에 <a href="http://www.example.com%EC%9D%84">www.example.com을</a> 입력한다.</h2>
<h2 id="2-브라우저는-ip-주소를-찾기-위해-dns-캐시를-확인한다">2. 브라우저는 IP 주소를 찾기 위해 DNS 캐시를 확인한다.</h2>
<ul>
<li>DNS(Domain Name System)는 웹 사이트의 이름(URL)과 그것이 연결된 IP 주소를 가지고 있는 데이터베이스</li>
<li>모든 URL은 자신만의 IP 주소를 가지고 있다.</li>
<li>DNS 기록을 찾기 위해서 브라우저는 다음 순서로 DNS Lookup을 수행한다.<pre><code class="language-plaintext">1. Browser에 내장된 정보
2. OS의 hosts file
3. Router
4. ISP</code></pre>
</li>
</ul>
<h2 id="3-요청한-url이-캐시에-없다면-isp의-dns-서버는-wwwexamplecom을-가지는-ip-주소를-찾기-위해-dns-query를-수행한다">3. 요청한 URL이 캐시에 없다면 ISP의 DNS 서버는 <a href="http://www.example.com%EC%9D%84">www.example.com을</a> 가지는 IP 주소를 찾기 위해 DNS Query를 수행한다.</h2>
<ul>
<li>올바른 IP 주소를 찾을때 까지 recursive search를 수행한다.</li>
<li>이 과정은 한 DNS 서버에서 다른 DNS 서버로 옮겨가며 IP 주소를 찾을 때까지 혹은 못 찾는다는 응답을 반환할 때 까지 계속된다.</li>
<li>이때 <strong>root domain에서 부터 sub domain 순</strong>으로 찾는다.</li>
</ul>
<h3 id="도메인의-구조">도메인의 구조</h3>
<p><img src="https://www.beusable.net/blog/wp-content/uploads/2021/02/image-13.png" alt="도메인 구조"></p>
<h4 id="1단계-최상위-도메인tld-top-level-domain">1단계: 최상위 도메인(TLD, Top-Level Domain)</h4>
<ul>
<li>도메인 레벨 중 가장 높은 단계의 도메인</li>
<li>도메인의 목적, 종류, 국적을 가진다.</li>
</ul>
<h4 id="2단계-차상위-도메인sld-second-level-domain">2단계: 차상위 도메인(SLD, Second-Level Domain)</h4>
<ul>
<li>호스트, <strong>서브 도메인</strong></li>
<li>URL로 전송하거나 계정 내의 IP 주소나 디렉토리로 포워딩되는 도메인 이름의 확장자</li>
</ul>
<h4 id="3단계-도메인-이름domain-name">3단계: 도메인 이름(Domain Name)</h4>
<ul>
<li>임의로 지정할 수 있는 사이트의 이름</li>
</ul>
<p><img src="https://images.velog.io/images/k-moovie/post/96dee4cc-8d38-46d3-bb27-91000519f339/image.png" alt=""></p>
<h2 id="4-브라우저는-서버와-tcp-통신을-시작한다">4. 브라우저는 서버와 TCP 통신을 시작한다.</h2>
<ul>
<li>IP 주소가 일치하는 서버와 정보 전달을 위한 연결을 시도</li>
<li>컴퓨터와 서버간의 데이터 패킷 전송을 위해 TCP 연결 수립.</li>
<li>이 연결은 TCP/IP three-way handshake 과정을 통해 만들어진다.</li>
<li>이것은 클라이언트와 서버가 연결 하기 위해서 SYN(synchronize), ACK(acknowledge) 메세지를 교환하는 과정을 의미.</li>
</ul>
<h3 id="tcpip-three-way-handshake">TCP/IP Three-way handshake</h3>
<ul>
<li>클라이언트 기계는 서버가 새 연결을 위해 열려있는지 물어보며 서버에 SYN 패킷을 보낸다.</li>
<li>만약 서버가 새 연결을 시작할 수 있는 오픈 포트를 가진다면, SYN/ACK 패킷을 사용하여 SYN 패킷의 ACKnowledgement로 응답한다.</li>
<li>클라이언트가 서버로부터 SYN/ACK 패킷을 받을 것이고 서버에 ACK 패킷을 보냄으로써 받았음을 알려줄 것이다.</li>
<li>그러면 데이터 전송을 위한 TCP 통신이 이루어짐.</li>
</ul>
<h2 id="5-브라우저는-웹-서버에-http-요청을-보낸다">5. 브라우저는 웹 서버에 HTTP 요청을 보낸다.</h2>
<ul>
<li>TCP 연결이 되면 데이터를 전송할 때다. 브라우저는 <a href="http://www.example.com">www.example.com</a> 페이지에 대해 묻는 GET 요청을 보낼 것이다.</li>
</ul>
<h2 id="6-서버는-요청을-처리하고-응답을-다시-보낸다">6. 서버는 요청을 처리하고 응답을 다시 보낸다.</h2>
<h2 id="7-서버는-http-응답을-내보낸다">7. 서버는 HTTP 응답을 내보낸다.</h2>
<ul>
<li>서버 응답은 요청한 페이지와 함께 status code, compression type(Content-Encoding), 페이지를 캐시하는 법(Cache-Control), 프라이빗 정보 등을 담고 있다.</li>
</ul>
<h2 id="8-브라우저는-html-컨텐츠를-표시한다">8. 브라우저는 HTML 컨텐츠를 표시한다.</h2>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://github.com/ksundong/backend-interview-question">Backend-Interview-Question</a></li>
<li><a href="https://velog.io/@jjo-niixx/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-URL-%EC%9E%85%EB%A0%A5-%ED%9B%84-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC">브라우저에 URL 입력 후 일어나는 일</a></li>
<li><a href="https://www.beusable.net/blog/?p=4507">데이터 분석을 위한 기초, URL 이해하기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡Cookie, Session, Token을 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/Cookie-Session-Token%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/Cookie-Session-Token%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 05:38:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/c93582e2-9627-47d7-bf69-03be50dc3c50/image.png" alt=""></p>
<h1 id="cookie-session-token">Cookie, Session, Token</h1>
<h2 id="backgrounds">Backgrounds</h2>
<h3 id="인증authentication">인증(Authentication)</h3>
<ul>
<li>유저가 누구인지 확인하는 절차, 회원가입하고 로그인 하는 것</li>
</ul>
<h3 id="인가authorization">인가(Authorization)</h3>
<ul>
<li>유저에 대한 권한을 허락하는 것</li>
</ul>
<h3 id="cookie와-session이-필요한-이유">Cookie와 Session이 필요한 이유</h3>
<ul>
<li>HTTP 프로토콜은 비연결성(Connectionless), 무상태성(Stateless)을 지향한다. 때문에 클라이언트와 서버의 통신이 종료된 후 연결을 끊고 데이터 상태 정보를 유지하지 않는다.</li>
<li>이는 매 페이지를 이동할 때마다 로그인을 다시 하거나 상품을 선택했는데 구매 페이지에는 선택한 상품의 정보가 없는 것을 뜻한다.</li>
<li>따라서 웹 서버가 사용자의 상태 정보를 기억하기 위해 쿠키와 세션을 사용한다.</li>
</ul>
<h2 id="cookie">Cookie</h2>
<ul>
<li>쿠키는 세션에 비해 보안적인 측면에서 좋지 않다.</li>
<li>서버에 저장되지 않고 브라우저(사용자의 컴퓨터)에 저장되기에 서버 자원의 낭비를 방지할 수 있으며 빠르다.</li>
<li>브라우저가 종료되어도 쿠키에 설정한 만료 시간이 지나지 않으면 자동으로 삭제되지 않는다.</li>
<li>쿠키는 보안이 중요하지 않고 브라우저가 종료되어도 유지할 수 있는 정보에 사용된다.</li>
<li>활용 예: 주로 팝업창 &quot;오늘 다시는 보지 않기&quot; 로그인시 &quot;id 기억하기&quot; 체크, 비로그인시 장바구니 넣기</li>
</ul>
<h2 id="session">Session</h2>
<ul>
<li>클라이언트에서 관리하는 쿠키에 비해서 서버에 저장하는 세션은 보안이 좋다.</li>
<li>서버 자원을 사용하기 때문에 사용자가 많을 경우 자원을 많이 소모할 수 있다.</li>
<li>세션은 브라우저가 종료되면 자동으로 삭제된다. (만료기간 설정 가능)</li>
<li>세션은 주로 보안이 중요한 로그인 정보를 유지하는데 사용한다.</li>
</ul>
<h2 id="session-vs-token">Session vs Token</h2>
<h3 id="세션-기반-인증">세션 기반 인증</h3>
<ul>
<li><ol>
<li>유저가 로그인을 한다.</li>
</ol>
</li>
<li><ol start="2">
<li>로그인이 성공하면 서버는 메모리나 DB에 세션을 저장하고, 서버가 클라이언트(웹 브라우저)에 세션 ID를 전송하여 쿠키(Cookie)에 저장한다.</li>
</ol>
</li>
<li><ol start="3">
<li>브라우저는 로그인이 되었는지 확인하기 위해 매 요청시 Request에 Session ID를 쿠키에 담아 전송한다</li>
</ol>
</li>
<li><ol start="4">
<li>서버는 Session ID가 일치하는지 확인한 후 일치하면 요청에 응답한다.</li>
</ol>
</li>
</ul>
<h3 id="세션-기반-인증-장점">세션 기반 인증 장점</h3>
<ul>
<li>서버 쪽에서 사용자의 로그인 상태에 확인이 쉽고 분명하다.</li>
<li>서버 쪽에서 세션 정보를 관리하기 때문에 클라이언트의 변조에 영향 받기 어렵고 데이터의 손상 우려가 없어 상대적으로 안전하다.</li>
<li>토큰 방식에 Signature 등 부가적인 정보가 없기에 Server-Clinet간 주로 받는 데이터가 적다.</li>
</ul>
<h3 id="세션-기반-인증-단점">세션 기반 인증 단점</h3>
<ul>
<li>대규모 서비스로의 스케일업을 위해서는 메모리에 저장되는 세션 정보로 인한 메모리 성능 부하가 있을 수 있다. Redis나 Memcached 등의 메모리 관리 시스템이 필요하다.</li>
<li>메모리에 저장된 세션 정보는 휘발성이기에 서버 재부팅시 사라질 수 있으며 많은 정보를 저장하는데 한계가 있다. 그렇다고 하드디스크나 DB에 저장하기에는 작업이 느리고 무겁다</li>
<li>쿠키는 단일 도메인, 서브 도메인에서만 작동하기 때문에 여러 도메인에서 사용할 경우 관리를 해줘야 한다.
세션 정보를 메모리에 저장하기에 부담이 있다.</li>
</ul>
<h3 id="토큰-기반-인증-jwt---json-web-token">토큰 기반 인증 (JWT - JSON Web Token)</h3>
<ul>
<li><ol>
<li>토큰 기반 인증은 인증받은 사용자들에게 토큰을 발급하고, 서버에 요청을 할 때 헤더에 토큰을 함께 보내 유효성을 검사하는 방식이다.</li>
</ol>
</li>
<li><ol start="2">
<li>사용자가 로그인을 하면 서버측에서 계정 정보를 검증한다.</li>
</ol>
</li>
<li><ol start="3">
<li>검증이 완료되면, 서버측에서 클라이언트에게 signed token을 발급하고 클라이언트는 이를 저장한다. (signed token은 정상적으로 발급된 토큰임을 증명하는 signature가 있다는 것)</li>
</ol>
</li>
<li><ol start="4">
<li>클라이언트는 서버에 요청 시 저장된 Token을 Header에 포함시켜 보낸다.</li>
</ol>
</li>
<li><ol start="5">
<li>서버는 Token 정보를 검증하고 해당 유저에 권한을 인가한다.</li>
</ol>
</li>
</ul>
<h3 id="토큰-기반-인증-장점">토큰 기반 인증 장점</h3>
<ul>
<li>클라이언트가 토큰 정보를 갖고 있기 때문에 서버를 스케일업하는데 부담이 적다.</li>
<li>클라이언트 세션 관리에 대한 서버의 메모리 부담을 줄일 수 있다.</li>
<li>다양한 도메인에 대응하는데 부담이 적다.</li>
</ul>
<h3 id="토큰-기반-인증-단점">토큰 기반 인증 단점</h3>
<ul>
<li>토큰 정보가 탈취될 수도 있어도 무효화할 수 없다. 보안에 취약하다.</li>
<li>토큰에 Signature 등의 부가적인 정보가 담겨 있기에 서버-클라이언트 간 주고 받는 데이터가 세션 기반의 인증보다 많다.</li>
<li>토큰 인증을 위해 Database에서 매번 조회해야 하므로 DB 성능 부하가 있을 수 있다.</li>
</ul>
<h2 id="로드-밸런싱을-수행하는-웹-서버의-경우-세션을-어떻게-관리할까">로드 밸런싱을 수행하는 웹 서버의 경우 세션을 어떻게 관리할까?</h2>
<h3 id="1-스티키-세션-sticky-session">1. 스티키 세션 (Sticky Session)</h3>
<ul>
<li>로드 밸런서가 쿠키가 없는 요청이라면 쿠키 값을 등록하고 웹서버를 지정한다.</li>
<li>쿠키가 있다면 해당 요청이 쿠키에 지정된 서버로 보낸다.</li>
</ul>
<h4 id="단점">단점</h4>
<ul>
<li>로드밸런싱이 잘 동작하지 않을 수 있다.</li>
<li>고정된 세션을 사용하기에 특정 서버만 과부하가 올 수 있다.</li>
<li>특정 서버 Fail시 해당 서버에 붙어 있는 세션들이 소실될 수 있다.</li>
</ul>
<h3 id="2-세션-클러스터링-session-clustering">2. 세션 클러스터링 (Session Clustering)</h3>
<ul>
<li>클러스터링은 여러 대의 컴퓨터들이 연결되어 하나의 시스템처럼 동작하도록 만드는 것이다.</li>
<li>즉, 각 서버의 세션에 모든 세션 저장소의 세션 객체를 복제한다.</li>
</ul>
<h4 id="단점-1">단점</h4>
<ul>
<li>매번 세션 객체를 복제하는데 오버헤드가 발생한다.</li>
</ul>
<h3 id="3-세션-스토리지-분리-별도의-세션-저장소-사용---redis-mongodb-dynamodb">3. 세션 스토리지 분리 (별도의 세션 저장소 사용 - Redis, MongoDB, DynamoDB..)</h3>
<ul>
<li>별도의 세션 저장소를 사용한다. 세션 저장소가 하나이기에 세션을 서버간 복제를 할 필요가 없다.</li>
<li>서버가 아무리 늘어난다 해도 세션 스토리지에 대한 정보만 각각의 서버에 입력해주면 세션을 공유할 수 있다. 또한, 트래픽이 몰리는 현상을 고려하지 않아도 된다.</li>
<li>하나의 서버가 장애가 발생해도 별도의 세션 저장소가 존재하기 때문에 서비스를 계속 제공할 수 있다. (가용성 확보)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡HTTP와 HTTPS를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/HTTP%EC%99%80-HTTPS%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/HTTP%EC%99%80-HTTPS%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 05:36:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/cc2f5944-fee8-4a3b-9b7a-02fd82581e58/image.png" alt=""></p>
<h1 id="http와-https">HTTP와 HTTPS</h1>
<h2 id="http">HTTP</h2>
<ul>
<li>Hyper Text Transfer Protocol</li>
<li>웹 상에서 클라이언트와 서버 간에 request/response로 정보를 주고 받을 수 있는 프로토콜</li>
<li>TCP/UDP를 사용하며, 80번 포트 사용.</li>
</ul>
<h2 id="https">HTTPS</h2>
<ul>
<li>Hyper Text Transfer Protocol over Secure Socket Layer</li>
<li>웹 통신 프로토콜인 HTTP의 보안이 강화된 버전의 프로토콜</li>
<li>TCP/IP의 포트로 443번 포트 사용.</li>
<li>네트워크 상에서 열람, 수정이 불가능하므로 안전하다.</li>
<li>암호화를 하는 과정이 웹 서버에 부하를 준다.</li>
<li>HTTPS는 설치 및 인증서를 유지하는데 추가 비용이 발생한다.</li>
<li>HTTP에 비해 느리다.</li>
</ul>
<h2 id="https가-필요한-이유">HTTPS가 필요한 이유</h2>
<ul>
<li>클라이언트인 웹 브라우저가 서버에 HTTP를 통해 웹 페이지나 이미지 정보를 요청하면 서버는 이 요청에 응답하여 요구하는 정보를 제공. 이때 웹 페이지(HTML)는 텍스트이고, HTTP를 통해 이런 텍스트 정보를 교환하는 것이다.</li>
<li>주고받는 텍스트 정보에 주민등록번호나 비밀번호와 같이 민감한 정보가 포함된 상태에서 네트워크 상에서 중간에 제3자가 정보를 가로챈다면 보안상 큰 문제가 발생한다.</li>
<li>즉, 중간에서 정보를 볼 수 없도록 주고받는 정보를 암호화하는 방법인 HTTPS를 사용하는 것이다.</li>
</ul>
<h2 id="https-동작-방법">HTTPS 동작 방법</h2>
<ul>
<li>애플리케이션 서버(A)를 만드는 기업은 HTTPS를 적용하기 위해 공개키와 개인키를 만든다.</li>
<li>신뢰할 수 있는 CA 기업을 선택하고, 그 기업에게 내 공개키 관리를 부탁하며 계약을 한다.<blockquote>
<p>CA란? : Certificate Authority로, 공개키를 저장해주는 신뢰성이 검증된 민간기업
계약 완료된 CA 기업은 해당 기업의 이름, A서버 공개키, 공개키 암호화 방법을 담은 인증서를 만들고, 해당 인증서를 CA 기업의 개인키로 암호화해서 A서버에게 제공한다.</p>
</blockquote>
</li>
<li>A서버는 암호화된 인증서를 갖게 되었다. 이제 A서버는 A서버의 공개키로 암호화된 HTTPS 요청이 아닌 요청이 오면, 이 암호화된 인증서를 클라이언트에게 건내준다.</li>
<li>클라이언트는 main.html 파일을 달라고 A서버에 요청했다고 가정하자. HTTPS 요청이 아니기 때문에 CA기업이 A서버의 정보를 CA 기업의 개인키로 암호화한 인증서를 받게 된다.</li>
<li>CA 기업의 공개키는 브라우저가 이미 알고있다. (세계적으로 신뢰할 수 있는 기업으로 등록되어 있기 때문에, 브라우저가 인증서를 탐색하여 해독이 가능한 것)</li>
<li>브라우저는 해독한 뒤 A서버의 공개키를 얻게 되었다. 이제 A서버와 통신할 대는 얻은 A서버의 공개키로 암호화해서 요청을 날리게 된다.</li>
<li>HTTPS도 무조건 안전한 것은 아니다. (신뢰받는 CA 기업이 아닌 자체 인증서 발급한 경우 등)</li>
<li>이때는 HTTPS지만 브라우저에서 주의 요함, 안전하지 않은 사이트와 같은 알림으로 주의 받게 된다.</li>
</ul>
<h2 id="http-헤더">HTTP 헤더</h2>
<h3 id="general-header">General Header</h3>
<ul>
<li>request, response에서 모두 사용 가능한 일반 목적의 헤더.</li>
</ul>
<h4 id="주요-항목들">주요 항목들</h4>
<ul>
<li>Date: HTTP 메시지를 생성한 일시 (RFC 1123에서 규정)</li>
<li>Connection: 클라이언트와 서버 간 연결에 대한 옵션 설정(다소 모호한 복잡성 있음)<ul>
<li>Connection: close, 현재 HTTP 메시지 직후에 TCP 접속을 끊는다는 것을 알림</li>
<li>Connection: Keep-Alive, 현재 TCP 커넥션을 유지</li>
</ul>
</li>
<li>Cache-Control: 브라우저가 관리하는 캐시 관리, 보통 GET 요청에만 사용.<ul>
<li>Cache-Control: no-store, 아무것도 캐싱하지 않음.</li>
<li>Cache-Control: no-cache, 모든 캐시를 사용하기 전에 서버에 판단을 요청.</li>
<li>Cache-Control: must-revalidate, 만료된 캐시만 서버에 판단을 요청.</li>
</ul>
</li>
<li>Pragma: HTTP/1.1 버전의 Cache-Control 헤더가 생기기 전 그것과 동일한 역할을 하는 대용 헤더.</li>
<li>Trailer: Trailer 헤더는 수신자로 하여금 어떠한 HTTP 헤더가 Chunked 방식의 트레일러로 사용될 것인지를 알게 해주는 헤더</li>
</ul>
<h3 id="entity-header">Entity Header</h3>
<ul>
<li>request, response에서 모두 사용 가능한 Entity(콘텐츠, 본문, 리소스 등)에 대한 설명 헤더.</li>
</ul>
<h4 id="주요-항목들-1">주요 항목들</h4>
<ul>
<li>Content-Type: 해당 개체에 포함되는 미디어 타입 정보<ul>
<li>컨텐츠의 타입(MIME 미디어 타입) 및 문자 인코딩 방식(EUC-KR,UTF-8 등)을 지정</li>
<li>타입 및 서브타입(type/subtype)으로 구성</li>
<li>Content-Type: text/html; charset-latin-1 =&gt; 해당 개체가 html으로 표현된 텍스트 문서이고, iso-latin-1 문자 인코딩 방식으로 표현됨</li>
</ul>
</li>
<li>Content-Language: 해당 개체와 가장 잘 어울리는 사용자 언어(자연언어)</li>
<li>Content-Encoding: 해당 개체 데이터의 압축 방식<ul>
<li>Content-Encoding: gzip, deflate</li>
<li>만일 압축이 시행되었다면, Content-Encoding 및 Content-Length 2개 항목을 토대로 압축 해제 가능</li>
</ul>
</li>
<li>Content-Length: 전달되는 해당 개체의 바이트 길이 또는 크기(10진수)<ul>
<li>응답 메시지 Body의 길이를 지정하거나, 특정 지정된 개체의 길이를 지정함</li>
</ul>
</li>
<li>Content-Location: 해당 개체가 실제 어디에 위치하는가를 알려줌</li>
<li>Content-Disposition: 응답 Body를 브라우저가 어떻게 표시해야 할지 알려주는 헤더<ul>
<li>inline인 경우 웹페이지 화면에 표시되고, attachment인 경우 다운로드</li>
<li>Content-Disposition: inline</li>
<li>Content-Disposition: attachment; filename=&#39;filename.csv&#39;</li>
<li>다운로드되길 원하는 파일은 attachment로 값을 설정하고, filename 옵션으로 파일명까지 지정해줄 수 있다.</li>
<li>파일용 서버인 경우 이 태그를 자주 사용</li>
</ul>
</li>
<li>Content-Security-Policy: 다른 외부 파일들을 불러오는 경우, 차단할 소스와 불러올 소스를 명시<ul>
<li>XSS 공격에 대한 방어 가능 (허용한 외부 소스만 지정 가능)</li>
<li>Content-Security-Policy: default-src https;://example.com, https를 통해서만 파일을 가져옴</li>
<li>Content-Security-Policy: default-src &#39;self&#39;, 자신의 도메인의 파일들만 가져옴</li>
<li>Content-Security-Policy: default-src &#39;none&#39;, 파일을 가져올 수 없음</li>
</ul>
</li>
<li>Location: 리소스가 리다이렉트(redirect)된 때에 이동된 주소, 또는 새로 생성된 리소스 주소<ul>
<li>300번대 응답이나 201 Created 응답일 때 어느 페이지로 이동할지를 알려주는 헤더</li>
<li>새로 생성된 경우에 HTTP 상태 코드 201 Created가 반환됨</li>
<li>HTTP/1.1 302 Found Location: /<ul>
<li>이런 응답이 왔다면 브라우저는 / 주소로 redirect한다.</li>
</ul>
</li>
</ul>
</li>
<li>Last-Modified: 리소스를 마지막으로 갱신한 일시</li>
</ul>
<h3 id="request-header">Request Header</h3>
<ul>
<li>요청 헤더는 HTTP 요청 메시지 내에서만 나타나며 가장 방대함.</li>
</ul>
<h4 id="주요-항목들-2">주요 항목들</h4>
<ul>
<li>Host: 요청하는 호스트에 대한 호스트명 및 포트번호 (필수)<ul>
<li>Host 필드에 도메인명 및 호스트명 모두를 포함한 전체 URI(FQDN) 지정 필요</li>
<li>이에 따라 동일 IP 주소를 갖는 단일 서버에 여러 사이트가 구축 가능</li>
</ul>
</li>
<li>User-Agent: 클라이언트 소프트웨어(브라우저, OS) 명칭 및 버전 정보</li>
<li>From: 클라이언트 사용자 메일 주소<ul>
<li>주로 검색엔진 웹 로봇의 연락처 메일 주소를 나타냄</li>
<li>때로는, 이 연락처 메일 주소를 User-Agent 항목에 두는 경우도 있음</li>
</ul>
</li>
<li>Cookie: 서버에 의해 Set-Cookie로 클라이언트에게 설정된 쿠키 정보</li>
<li>Referer: 바로 직전에 머물었던 웹 링크 주소</li>
<li>If-Modified-Since: 제시한 일시 이후로만 변경된 리소스를 취득 요청</li>
<li>Authorization: 인증 토큰(JWT/Bearer 토큰)을 서버로 보낼 때 사용하는 헤더<ul>
<li>토큰의 종류(Basic, Bearer 등) + 실제 토큰 문자를 전송</li>
</ul>
</li>
<li>Origin<ul>
<li>서버로 POST 요청을 보낼 때, 요청이 어느 주소에서 시작되었는지 나타냄</li>
<li>여기서 요청을 보낸 주소와 받는 주소가 다르면 CORS 에러가 발생</li>
<li>응답 헤더의 Access-Control-Allow-Origin와 관련</li>
</ul>
</li>
<li>다음 4개는 주로 HTTP 메세지 Body의 속성 또는 내용 협상용 항목들<ul>
<li>Accept: 클라이언트 자신이 원하는 미디어 타입 및 우선순위를 알림<ul>
<li>Accept: <em>/</em> =&gt; 어떤 미디어 타입도 가능</li>
<li>Accept: image/* =&gt; 모든 이미지 유형</li>
</ul>
</li>
</ul>
</li>
<li>Accept-Charset: 클라이언트 자신이 원하는 문자 집합</li>
<li>Accept-Encoding: 클라이언트 자신이 원하는 문자 인코딩 방식</li>
<li>Accept-Language: 클라이언트 자신이 원하는 가능한 언어</li>
<li>각각이 HTTP Entity Header 항목 중에 Content-Type, Content-Type charset-xxx, Content-Encoding, Content-Language과 일대일로 대응됨</li>
</ul>
<h3 id="response-header">Response Header</h3>
<ul>
<li>특정 유형의 HTTP 요청이나 특정 HTTP 헤더를 수신했을 때, 이에 응답하는 헤더.</li>
</ul>
<h4 id="주요-항목들-3">주요 항목들</h4>
<ul>
<li>Server: 서버 소프트웨어 정보</li>
<li>Accept-Range</li>
<li>Set-Cookie: 서버측에서 클라이언트에게 세션 쿠키 정보를 설정 (RFC 2965에서 규정)</li>
<li>Expires: 리소스가 지정된 일시까지 캐시로써 유효함</li>
<li>Age: 캐시 응답. max-age 시간 내에서 얼마나 흘렀는지 알려줌(초 단위)</li>
<li>ETag: HTTP 컨텐츠가 바뀌었는지를 검사할 수 있는 태그</li>
<li>Proxy-authenticate</li>
<li>Allow: 해당 엔터티에 대해 서버 측에서 지원 가능한 HTTP 메소드의 리스트를 나타냄<ul>
<li>때론, HTTP 요청 메세지의 HTTP 메소드 OPTIONS에 대한 응답용 항목<ul>
<li>OPTIONS: 웹서버측 제공 HTTP 메소드에 대한 질의</li>
</ul>
</li>
<li>Allow: GET,HEAD =&gt; 웹 서버측이 제공 가능한 HTTP 메서드는 GET,HEAD 뿐임을 알림 (405 Method Not Allowed 에러와 함께)</li>
</ul>
</li>
<li>Access-Control-Allow-Origin: 요청을 보내는 프론트 주소와 받는 백엔드 주소가 다르면 CORS 에러가 발생<ul>
<li>서버에서 이 헤더에 프론트 주소를 적어주어야 에러가 나지 않는다.</li>
<li>Access-Control-Allow-Origin: <a href="http://www.example.com">www.example.com</a><ul>
<li>프로토콜, 서브도메인, 도메인, 포트 중 하나만 달라도 CORS 에러가 난다.</li>
</ul>
</li>
<li>Access-Control-Allow-Origin: *<ul>
<li>만약 주소를 일일이 지정하기 싫다면 *으로 모든 주소에 CORS 요청을 허용되지만 그만큼 보안이 취약해진다.</li>
<li>유사한 헤더로 Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Headers 등이 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://jeong-pro.tistory.com/89">Http와 Https 이해와 차이점 그리고 오해(?)</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡OSI 7계층을 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/OSI-7%EA%B3%84%EC%B8%B5%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/OSI-7%EA%B3%84%EC%B8%B5%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 05:30:02 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/k-moovie/post/74a0b613-37da-4566-83d8-8e30753c538e/image.png" alt=""></p>
<h1 id="osi-7-layers">OSI 7 Layers</h1>
<p><img src="https://images.velog.io/images/k-moovie/post/8175f595-a323-4af6-b7d5-b184b4d36db6/image.png" alt=""></p>
<h2 id="osi-7계층이란">OSI 7계층이란?</h2>
<ul>
<li><strong>Open System Interconnection</strong>의 약자</li>
<li>국제표준화기구(ISO)에서 개발한 모델로, 컴퓨터 네트워크 프로토콜 디자인과 통신을 계층으로 나누어 설명한 것.</li>
<li>각 계층은 <strong>하위 계층의 기능만을 이용</strong>하고, <strong>상위 계층에게 기능을 제공</strong>.</li>
<li>&#39;프로토콜 스택&#39; 혹은 &#39;스택&#39;은 이러한 계층들로 구성되는 프로토콜 시스템이 구현된 시스템을 가리키는데, 프로토콜 스택은 하드웨어나 소프트웨어 혹은 둘의 혼합으로 구현될 수 있다.</li>
</ul>
<h2 id="물리-physical-계층">물리 (Physical) 계층</h2>
<blockquote>
<p>케이블, 리피터, 허브</p>
</blockquote>
<ul>
<li>전기적인 신호(데이터)로 변환해서 주고받음.</li>
<li>네트워크의 기본 하드웨어 전송 기술.</li>
<li>전송 단위는 <strong>Bit</strong> 이다.</li>
</ul>
<h2 id="데이터-링크-datalink-계층">데이터 링크 (DataLink) 계층</h2>
<blockquote>
<p>브릿지, 스위치, 이더넷</p>
</blockquote>
<ul>
<li><strong>같은 네트워크</strong>에 있는 <strong>여러 대의 컴퓨터</strong>들이 데이터를 주고 받기 위해 필요한 모듈 (<strong>1홉 통신</strong>을 담당)</li>
<li>P2P (Point to Point) 간 신뢰성있는 전송을 보장하기 위한 계층으로 CRC 기반의 <strong>흐름제어</strong>와 <strong>오류제어</strong>가 필요.</li>
<li>주소 값은 물리적으로 할당, 이는 네트워크 카드가 만들어질 때 부터 맥 주소(Mac address)가 정해져 있다는 뜻.</li>
<li>전송 단위는 <strong>Frame</strong> 이다.</li>
</ul>
<h2 id="네트워크-network-계층">네트워크 (Network) 계층</h2>
<blockquote>
<p>라우터, IP</p>
</blockquote>
<ul>
<li>여러 개의 노드를 거칠때 마다 경로를 찾아주는 역할 (<strong>2홉 이상의 통신</strong>-멀티 홉 통신을 담당)</li>
<li>다양한 길이의 데이터를 네트워크를 통해 전달하고, 그 과정에서 전송 계층이 요구하는 <strong>서비스 품질(QoS)</strong>을 제공하기 위한 기능적, 절차적 수단 제공.</li>
<li><strong>흐름제어, 오류제어, 라우팅, 세그멘테이션, 인터네트워킹</strong>을 수행.</li>
<li>전송 단위는 <strong>Packet</strong>이다.</li>
</ul>
<h2 id="전송-transport-계층">전송 (Transport) 계층</h2>
<blockquote>
<p>TCP, UDP
데이터를 받고자 하는 프로세스들은 포트 번호를 가져야한다.
포트 번호는 하나의 컴퓨터에서 동시에 실행되고 있는 프로세스들이 서로 겹치지 않게 가져야하는 정수 값.
송신자는 데이터를 보낼 때 데이터를 받을 수신자 컴퓨터에 있는 프로세스의 포트 번호를 붙여서 전송.</p>
</blockquote>
<ul>
<li>양 끝단(End to end)의 사용자들이 <strong>신뢰성있는 데이터를 주고 받는 역할</strong>.</li>
<li>상위 계층들이 데이터 전달의 유효성이나 효율성을 생각하지 않도록 해줌.</li>
<li>시퀀스 넘버 기반의 오류 제어 방식을 사용한다.</li>
<li>전송 계층은 특정 연결의 유효성을 제어하고, 일부 프로토콜은 상태 개념이 있고(stateful), 연결 기반(connection oriented)이다. (이는 전송 계층이 패킷들의 전송이 유효한지 확인하고 전송 실패한 패킷들을 다시 전송한다는 것을 뜻한다.)</li>
<li>TCP의 경우 혼잡 제어 제공</li>
<li>전송 단위는 <strong>TCP - Segment, UDP - Datagram</strong>이다.</li>
</ul>
<h2 id="세션-session-계층">세션 (Session) 계층</h2>
<blockquote>
<p>API, Socket</p>
</blockquote>
<ul>
<li>양 끝단의 응용 프로세스가 통신을 관리하기 위한 방법을 제공한다.
동시 송수신 방식(duplex), 반이중 방식(half-duplex), 전이중 방식(Full Duplex)의 통신과 함께, 체크 포인팅과 유휴, 종료, 다시 시작 과정 등을 수행한다.</li>
</ul>
<h2 id="표현-presentation-계층">표현 (Presentation) 계층</h2>
<blockquote>
<p>JPEG, MPEG 등</p>
</blockquote>
<ul>
<li>코드 간의 번역을 담당하여 사용자 시스템에서 데이터의 형식상 차이를 다루는 부담을 응용 계층으로부터 덜어 준다.</li>
<li>MIME 인코딩이나 암호화 등의 동작이 이 계층에서 이루어진다.</li>
</ul>
<h2 id="응용-application-계층">응용 (Application) 계층</h2>
<blockquote>
<p>HTTP, FTP, DNS 등</p>
</blockquote>
<ul>
<li>응용 프로세스와 직접 관계하여 일반적인 응용 서비스를 수행한다.</li>
<li>일반적인 응용 서비스는 관련된 응용 프로세스들 사이의 전환을 제공한다.</li>
</ul>
<h2 id="오류-제어-흐름-제어-혼잡-제어">오류 제어, 흐름 제어, 혼잡 제어?</h2>
<h3 id="오류-제어-error-control">오류 제어 (Error Control)</h3>
<ul>
<li>호스트 간의 데티어 전송이 일어날 때 데이터의 오류에 관련된 제어 역할</li>
<li>오류 검출, 복구(재전송) 등의 기법</li>
</ul>
<h3 id="흐름-제어">흐름 제어</h3>
<p><img src="https://images.velog.io/images/k-moovie/post/09e3b2fa-79a1-4e44-8506-05fbf831dbda/image.png" alt="">
<img src="https://images.velog.io/images/k-moovie/post/6667e11d-0273-49d4-a9cd-7ed573475ba7/image.png" alt="">
<img src="https://images.velog.io/images/k-moovie/post/100242a6-09aa-4bb7-b4ff-97fbed9cee26/image.png" alt=""></p>
<ul>
<li>송신부와 수신부의 데이터 처리 속도 차이를 해결하는 역할</li>
<li>송신부가 수신부 보다 속도가 빠르면 수신부의 데이터에 문제가 발생</li>
<li>Stop and wait: 매번 전송한 패킷에 대해 확인응답을 받아야만 그 다음 패킷을 전송하는 방법</li>
<li>Sliding window: 수신 측에서 설정한 윈도우 크기만큼 송신 측에서 확인 응답 없이 세그먼트를 전송할 수 있게 하여 데이터 흐름을 동적으로 조절하여 제어하는 방법</li>
</ul>
<h3 id="혼잡-제어">혼잡 제어</h3>
<ul>
<li>혼잡 제어는 송신측과 <strong>네트워크의</strong> 데이터처리 속도 차이를 해결하기 위한 기법</li>
<li>송신된 패킷이 네트워크 상의 라우터가 처리할 수 있는 양을 넘어서 혼잡하게 되면 데이터가 손실될 수 있기 때문에 송신측의 전송량을 제어</li>
<li>합 증가/곱 감소(AIMD), 슬로우 스타트(Slow Start) </li>
</ul>
<h2 id="osi-7-layers-장단점">OSI 7 Layers 장단점</h2>
<h3 id="장점">장점</h3>
<ul>
<li>각 계층이 독립되어있기 때문에 다른 계층에 영향없이 수정 가능</li>
<li>인터페이스의 표준화</li>
<li>단순한 구조, 설계 용이</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>7개의 계층을 거쳐야해서 지연 시간 발생</li>
<li>각 계층 마다 헤더 등의 정보를 추가하는 오버헤드 증가</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=1pfTxp25MA8&amp;t=2s">[10분 테코톡]히히의 OSI 7 Layer</a></li>
<li><a href="http://wiki.hash.kr/index.php/OSI_7_%EA%B3%84%EC%B8%B5">OSI 7 계층 - 해시넷</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💡 시간 복잡도를 학습해 보자]]></title>
            <link>https://velog.io/@k-moovie/%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@k-moovie/%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84%EB%A5%BC-%ED%95%99%EC%8A%B5%ED%95%B4-%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 14 Jan 2022 05:25:32 GMT</pubDate>
            <description><![CDATA[<h1 id="알고리즘의-복잡도">알고리즘의 복잡도</h1>
<ul>
<li>시간 복잡도: 알고리즘의 실행 속도</li>
<li>공간 복잡도: 알고리즘이 사용하는 메모리 사이즈<blockquote>
<p>컴퓨터 저장장치 성능의 향상에 따라 시간 복잡도의 중요성이 증가</p>
</blockquote>
</li>
</ul>
<h2 id="알고리즘-성능-표기법">알고리즘 성능 표기법</h2>
<ul>
<li>Big O(빅-오) 표기법: O(N)<ul>
<li>알고리즘 <strong>최악의 실행 시간</strong>을 표기</li>
<li>가장 일반적으로 사용</li>
<li>아무리 최악의 상황이라도, 이 정도의 성능은 보장한다는 의미</li>
</ul>
</li>
<li>Ω(오메가) 표기법: Ω (N)<ul>
<li>알고리즘 최상의 실행 시간을 표기</li>
</ul>
</li>
<li>Θ(세타) 표기법: Θ(N)<ul>
<li>알고리즘의 평균 실행 시간을 표기</li>
</ul>
</li>
</ul>
<h2 id="big-o-표기법">Big-O 표기법</h2>
<h3 id="on">O(N)</h3>
<ul>
<li><p>입력 n에 따라 결정되는 시간 복잡도 함수</p>
</li>
<li><p>표현식에 가장 큰 영향을 미치는 n의 단위로 표기</p>
<blockquote>
<p>$$O(1) &lt; O(logn) &lt; O(n) &lt; O(nlogn) &lt; O(n^2) &lt; O(2^n) &lt; O(n!)$$</p>
</blockquote>
</li>
</ul>
<p><img src="https://images.velog.io/images/k-moovie/post/b394c87d-523b-4b6d-b318-beb772b6b8cf/image.png" alt=""></p>
<h3 id="예시">예시</h3>
<blockquote>
<p>$$2n^2 + 3n$$</p>
</blockquote>
<ul>
<li>만약 시간 복잡도 함수가 위와 같다면, 시간 복잡도는 $$O(N^2)$$</li>
<li>가장 높은 차수는 $$2n^2$$</li>
<li>상수는($$\mathbf{2}n^2$$에서 $$2$$) 실제 큰 영향이 없으므로 무시</li>
</ul>
<h2 id="중요-알고리즘의-시간-복잡도">중요 알고리즘의 시간 복잡도</h2>
<p>  <img src="https://images.velog.io/images/k-moovie/post/7aa095a6-ed24-4cca-ad06-11478be329c3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2022년에 적는 2021년 회고 💾]]></title>
            <link>https://velog.io/@k-moovie/2022%EB%85%84%EC%97%90-%EC%A0%81%EB%8A%94-2021%EB%85%84-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@k-moovie/2022%EB%85%84%EC%97%90-%EC%A0%81%EB%8A%94-2021%EB%85%84-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 02 Jan 2022 07:17:22 GMT</pubDate>
            <description><![CDATA[<h1 id="올해는-무슨-일을-했을까">올해는 무슨 일을 했을까?</h1>
<ul>
<li>한국전자통신연구원(ETRI) 동계 연구연수생</li>
<li>졸업작품 프로젝트 수행과 발표</li>
<li>부스트캠프 웹·모바일 6기 챌린지와 멤버십</li>
</ul>
<p>2021년을 회고하면서 들었던 생각은 나에게 부족한 것을 알 수 있는 한 해였다는 것이다. 다양한 활동을 수행했지만 부족한 부분을 느꼈고, 더 성장할 수 있을 것 같다.</p>
<h2 id="생애-첫-인턴-etri">생애 첫 인턴, ETRI</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/da3b2727-9f58-4244-b178-70d13ce22cbd/B437F2B6-9D94-4938-8B67-378A7B6A3938_1_105_c.jpeg" alt=""></p>
<blockquote>
<p>대전은 겨울에 눈이 정말 많이 온다. 집가는 길은 스케이트장 같다. 🏂</p>
</blockquote>
<p>정말 정말 정말 바빴던(프로젝트 5개를 소화한) 3학년 2학기를 끝낸지 한달 채 안되는 시기지만 나는 대전에 잠시 거주할 집을 알아보고 있었다. 
왜냐하면 작년 11월 한국전자통신연구원에 지원한 동계연구연수생으로 선발되었기 때문이다. 처음 자취를 한다는 설렘과 혼자 타지에서 인턴 생활을 한다는 두려움으로 대전으로 올라가게 되었다. </p>
<p>ETRI에서 인턴은 정말 좋았다. 연구원의 근무 분위기를 잠시 체험할 수 있었는데 장점이 꽤 많았다.</p>
<ul>
<li>연구원은 유연근무제를 시행하고 있어 어느 정도의 출퇴근의 자유가 보장된다.</li>
<li>비교적 자유로운 분위기 속에서 일할 수 있었다.</li>
<li>장비가 좋다... (<del>미개봉 그래픽카드가 벽돌처럼 쌓여져 있다.</del>)</li>
</ul>
<p>ETRI에서는 휴먼포즈추정에서 발생한 데이터를 기록하고 수정하는 응용프로그램을 제작했다. 어떻게 보면 레거시한 기술로 응용프로그램을 제작해서 레퍼런스를 찾기 힘들었다. 하지만 OpenCV, OpenGL 등 학교에서는 다뤄보지 못한 프레임워크를 사용해 개발하는 것은 좋은 경험이었다. </p>
<h2 id="생각보다-힘든-4학년-1학기의-시작">생각보다 힘든 4학년 1학기의 시작</h2>
<p><img src="https://images.velog.io/images/k-moovie/post/d8e26401-4f4d-4ad8-9442-d6faa990eac7/image.png" alt=""></p>
<blockquote>
<p>4학년을 하고 있는 학교 선배들이나 동기들은 입버릇처럼 하는 말이있다. 
&quot;3학년 2학기 때는 진짜 자퇴하고 싶었다.&quot; </p>
</blockquote>
<p>프로젝트를 아무리 적게 잡아도 한 학기에 3개의 프로젝트를 수행한다.하지만 나는 하나의 프로젝트를 더 수행했기 때문에 &#39;정말 이것보다 힘든학기는 없을거야&#39;, &#39;4학년땐 워라벨이라는 것을 챙겨보자&#39;라고 다짐했었다. 그래서 ETRI에서 막 돌아온 3월은 균형있는 학교생활을 했다.</p>
<p>하지만, 프로젝트가 실질적으로 시작되는 4월은 현실을 깨닫기 시작했다. 특히 졸업작품을 4학년 1학기에 제작하는데 올해는 작년과 다르게 1학기에 평가한다고 했다. 이 말은 실질적 개발기간이 2달이라는 말이다...
그때부터 학교는 나의 집이되었다.</p>
<p>Spring Boot기반의 MSA 구조의 Backend API서버 제작을 맡았다. MSA 구조는 작은 서비스들이 모여 큰 서비스를 제공하기 때문에 
서비스 도메인을 잘 나눠야한다. 또한, 작은 서비스들을 관리하기 때문에 서비스들의 정보를 관리하는 모듈, 요청을 분석해 알맞은 서비스에 전달하는 모듈 등 초기 환경설정에 정말 많은 시간을 갈아 넣었다.</p>
<p><img src="https://images.velog.io/images/k-moovie/post/38f3f08b-63f1-418e-ac20-71b7993def98/image.png" alt=""></p>
<blockquote>
<p>백엔드 아키텍처이다. Composite service 부분을 제외하면 다 MSA 환경 세팅에 관련된 모듈이다.</p>
</blockquote>
<p>많은 우여곡절 끝에 프로젝트를 완성했으며, 학습보다는 구현에 중점을 둔 프로젝트여서 아쉬웠다.</p>
<ul>
<li>Spring Boot에 대해 더 깊게 공부해보고 싶다.</li>
<li>MySQL을 기반으로 아키텍처를 구성했지만 좀 더 알맞는 DB를 적용했으면 좋았을 것 같다. </li>
<li>MSA는 Spring Boot에 익숙치 않은 나에겐 과한 기술 스택이라 느껴졌다.</li>
<li>발표 후 피드백은 고생은 많이 한 것 같으나 발표 자료에서 흔적이 느껴지지 않는다고 했다. 😭</li>
</ul>
<h2 id="부스트캠프-웹·모바일-6기">부스트캠프 웹·모바일 6기</h2>
<p>ETRI에서 인턴을 할 때도, 4학년 1학기를 이겨낼 때도 대기업에서 주관하는 공채와 인턴은 빠짐없이 넣었었다. 하지만 미흡한 코테실력과 글 적는 능력 덕분인지 다 떨어졌다. </p>
<p>그러던 도중 네이버커넥트 재단에서 주최하는 부스트캠프 웹·모바일 6기에 지원했는데 합격했다.
<img src="https://images.velog.io/images/k-moovie/post/7b062bb9-84fb-473c-9512-a708d6fad29e/image.png" alt=""></p>
<blockquote>
<p>자소서의 템플릿을 만드는 것은 정말 좋다. 하지만 기업은 생각보다 다양한 질문을 요구한다. 특히 지원 동기는 회사마다 다르게 적는게 좋아보이더라</p>
</blockquote>
<p>부스트캠프의 모든 과정은 쉽지 않았다. 하지만 정말 배우는게 많았으며 정리하면 다음과 같다.</p>
<ul>
<li>학교 밖 사람들은 정말 다양하다. 고수분들이 너무 많아 이분들께서 공유하는 지식들은 큰 도움이되었다.</li>
<li>웹 풀스택과정을 수행했다. 프론트엔드에 집중된 느낌을 받았지만 웹을 이해하는데 좋은 경험이었다.</li>
<li>백엔드를 희망하는 사람들과 팀을 하면 백엔드와 관련된 재밌는 프로젝트를 수행할 수 있다. (무중단배포, CI/CD 자동화 등등)</li>
<li>부캠에서 배운 mongoDB는 NoSQL로 읽기 속도가 빨라 사용했지만 네트워킹 데이에서 만난 현직 개발자분께서 말씀하시는 DB 선정과정을 들어보니 성급하게 mongoDB를 사용했다고 느꼈다. </li>
<li>부캠사람들은 부지런하다.</li>
<li>개발자에게 있어 최고의 복지는 사람이라고 하는 이유를 조금이나마 알게되었다. 함께하면 좋은 사람들이 많았다.</li>
</ul>
<h2 id="올해의-나는">올해의 나는?</h2>
<h3 id="개발분야">개발분야</h3>
<ul>
<li>학습과 구현이 있을 때는 구현을 중점으로 하는 개발을 해왔다. 내년에는 성장가능한 학습을 목표로하고 싶다.</li>
<li>JS와 Python만 사용해 주력인 Java에 소홀했다. Spring Boot와 함께 같이 공부하자.</li>
<li>학습 후 기록은 정말 힘들지만 필요하다.</li>
<li>kotlin을 사용하는 기업은 점점 늘어나는거 같다. 시간이 된다면 해보자.</li>
<li>혼자서 하는 것과 여럿이서 하는 것은 확연한 차이를 보인다. 이왕이면 마음맞는 사람끼리 해보자.</li>
</ul>
<h3 id="일상">일상</h3>
<ul>
<li>운동을 시작했었다. (꾸준히해보자)</li>
<li>일과 일상 속의 균형을 찾아보자.</li>
<li>&#39;취업하면 해야지&#39;가 점점 늘어난다.😭</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨터알고리즘 정리]]></title>
            <link>https://velog.io/@k-moovie/%EC%BB%B4%ED%93%A8%ED%84%B0%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@k-moovie/%EC%BB%B4%ED%93%A8%ED%84%B0%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 12 Oct 2020 05:03:11 GMT</pubDate>
            <description><![CDATA[<h1 id="컴퓨터알고리즘-정리">컴퓨터알고리즘 정리</h1>
<h2 id="1장-서론">1장. 서론</h2>
<ul>
<li><p>알고리즘 이란?</p>
<p>문제를 해결하거나 함수를 계산하기 위해 좇아야할 모호함이 없는 간단한 명령들로 구성된 일련의 순서적 단계.</p>
<blockquote>
<p><strong><em>#알고리즘의 조건</em></strong></p>
<ol>
<li><p>외부에서 0개 이상의 입력을 받아들여, 하나 이상의 출력을 생성한다. </p>
</li>
<li><p>각 단계가 단순해야 하며 모호하지 않아야 한다.</p>
</li>
<li><p>한정된 수의 작업 후에는 반드시 끝나야 한다.</p>
</li>
<li><p>모즌 명령이 수행 가능해야 한다.</p>
</li>
<li><p>효율적이여야 한다.</p>
</li>
</ol>
</blockquote>
<blockquote>
<p> <strong><em>#알고리즘의 생성</em></strong></p>
<ol>
<li>설계</li>
<li>표현</li>
<li>정확성 섬증</li>
<li>효율분석</li>
</ol>
</blockquote>
</li>
</ul>
<ul>
<li><p>큐 (Queue)</p>
<p>한 쪽 끝에서 삽입이 행해지고, 다른 쪽 끝에서 삭제가 행해지는 리스트.</p>
<p>삽입이 일어나는 쪽을 rear, 삭제가 일어나는 쪽을 front라고 하며, 선입선출(FIFO) 구조를 가진다. </p>
</li>
</ul>
<ul>
<li><p>스택 (Stack)</p>
<p>리스트의 한 쪽 끝에서만 삽입과 삭제가 수행되는 리스트.</p>
<p>후입선출(LIFO) 구조를 가진다. </p>
</li>
</ul>
<ul>
<li><p>그래프 (Graph)</p>
<p>정점(Vertex), 간선(Edge)의 집합으로 구성되며 $G=(V,E)$ 로 표시된다.</p>
<p><strong>방향그래프</strong>는 하나의 간선이 방향을 가지며 정점 u에서 정점 v로 가는 간선은 $&lt;u,v&gt;$ 로 표시한다.</p>
<p><strong>무방향 그래프</strong>는 방향이 존재하지 않으며 정점 u에서 정점 v로 가는 간선은 $(u,v)$ 로 표시한다.</p>
<p>자기 자신을 잇는 간선을 <strong>루프</strong>라고 한다. </p>
<p><strong>차수</strong>는 정점에 부수된(포함된) 간선의 개수. 방향그래프는 외향차수, 내향차수를 가진다. </p>
<p><strong>경로</strong>는 정점 $v_1$ 에서 $v_n$ 까지 연결된 정점들의 순차열이다. </p>
<p><strong>길이</strong>는 경로상에 존재하는 간선의 개수이다. </p>
<p><strong>단순 경로</strong>는 경로상의 정점들이 모두 다른 것을 의미한다.</p>
<p><strong>사이클</strong>은 시작 정점과 끝 정점이 같은 경로를 사이클이라 한다.</p>
<p><strong>단순 사이클</strong>은 시작 정점과 끝 정점을 제외한 모든 정점이 다른 것을 의미한다. </p>
</li>
</ul>
<ul>
<li><p>신장 부분 그래프 (Spanning Subgraph)</p>
<p>정점의 개수가 같은 부분 그래프.</p>
</li>
</ul>
<ul>
<li><p>완정 그래프 (Complete Graph)</p>
<p>모든 정점끼리 간선으로 연결된 그래프.</p>
</li>
</ul>
<ul>
<li><p>트리 (Tree)</p>
<p><strong>연결된 무사이클 무방향</strong> 그래프.</p>
<p><strong>조상</strong>과 <strong>자손</strong>이 있으며, 부모가 같은 노드들을 <strong>동기</strong>라고 한다. 또한, 자식이 없으면 <strong>잎 노드</strong>하고 한다.</p>
<p>노드 $x$의 자식의 개수를 $x$ 의 <strong>차수</strong>라고 한다.</p>
<p>뿌리 $r$ 에서 노드 $x$ 까지의 경로의 길이를 <strong>깊이</strong>라고 하며, 가장 큰 길이를 <strong>높이</strong>라고 한다.</p>
<p>깊이가 같은 노드들을 동일한 <strong>수준</strong>에 있다고 한다. (수준은 0부터 시작)</p>
</li>
</ul>
<ul>
<li><p>순서 트리</p>
<p>각 자식에 순서가 부여된 트리.</p>
<p>오른쪽, 왼쪽 자식을 구별하지 않는다.</p>
</li>
</ul>
<ul>
<li><p>이진나무</p>
<p>각 노드의 자식이 2개 이하인 순서 트리.</p>
</li>
</ul>
<ul>
<li><p>전 이진 트리</p>
<p>모든 노드의 차수가 0이거나 2인 이진 트리.</p>
</li>
</ul>
<ul>
<li><p>포화 이진 트리</p>
<p>모든 <strong>잎</strong>의 깊이가 같은 이진 트리.</p>
<p>노드의 개수: $2^{h+1}-1$</p>
<p>잎 노드: $2^h$</p>
<p>잎이 아닌 노드: $2^h-1$</p>
</li>
</ul>
<ul>
<li><p>완전 이진 트리</p>
<p>포화 이진 트리의 잎 노드들을 오른쪽으로 부터 제거하여 얻어지는 트리.</p>
<p>노드의 범위: $2^h\le n\le2^{h+1}-1$</p>
<p>트리의 높이: $ \lfloor\ lgn \rfloor\ $</p>
</li>
</ul>
<ul>
<li><p>욕심쟁이 방법 (Greedy method)</p>
<p>어떤 문제에 대한 해를 구할려면 일련의 선택 과정을 거쳐야한다.</p>
<p><strong>각 선택과정마다 그 단계에서 최선이라고 볼 수 있는 선택을 행해나가면 결과적으로 전체적인 최적 해를 구할 수 있을 것</strong>이라는 희망적 전략을 취하는 방법.</p>
<p>참고. p.28의 배낭 문제.</p>
</li>
</ul>
<ul>
<li><p>시간 복잡도</p>
<p>수행시간: 알고리즘이 수행하는 기본 연산의 수행 횟수를 세는 방법. ($\text{각 명령문 수행 횟수} \times \text{각 명령문 수행 시간}$)</p>
</li>
</ul>
<ul>
<li><p>점근 성능의 표기법</p>
<blockquote>
<p>$f(n)$: 실행 시간</p>
<p>$g(n)$:$f(n)$ 의 최고 차수 일 때,</p>
<p><strong>점근적 상향</strong>: $n\ge n_0$ 인 모든 $n$ 에 대하여 $f(n) \le c \cdot g(n)$ 을 만족하는 양의 상수 $c, n_0$ 이 존재하면 $f(n) = O(g(n))$ 이다.</p>
<p><strong>점근적 하향</strong>: $n\ge n_0$ 인 모든 $n$ 에 대하여 $f(n) \ge c \cdot g(n)$ 을 만족하는 양의 상수 $c, n_0$ 이 존재하면 $f(n) = \Omega (g(n))$ 이다.</p>
<p><strong>점근적 평균</strong>: $n\ge n_0$ 인 모든 $n$ 에 대하여 $c_1 \cdot g(n) \le f(n) \le c_2 \cdot g(n)$ 을 만족하는 양의 상수 $c_1, c_2 ,n_0$ 이 존재하면  $f(n) = \Theta(g(n))$ 이다. </p>
</blockquote>
</li>
</ul>
<ul>
<li><p>점근 성능 표기의 성질</p>
<blockquote>
<p>$f_1(n) = O(g_1(n)), f_2(n) = O(g_2(n))$ 이라 하자.</p>
<p>(1) $f_1(n) + f_2(n) = max(O(g_1(n)), O(g_2(n)))$ 이다.</p>
<p>(2) $f_1(n) \cdot f_2(n) = O(g_1(n))\cdot O(g_2(n))$ 이다. # for문에서 사용</p>
</blockquote>
</li>
</ul>
<ul>
<li><p>순환과 점화 관계</p>
<p>$T(n)=T({n \over 2}) + O(1)$ 와 같이 안 값이 자신을 포함한 수식으로 표현되는 것을 점화 관계라고 한다.</p>
<p>$$
T(n) = C_2 + T\left({n \over 2}\right)\</p>
<pre><code> = C_2 + C_2 + T\left({n \over 4}\right)\\
 = C_2 + C_2 + C_2 + T\left({n \over 8}\right)\\
 = (k-1)c_2 + T\left({n \over 2^{k-1}}\right)\\
 = kC_2 + T(1)\\
 = C_1 + kC_2\\
 = C_1 + log_2n\\</code></pre><p>$$</p>
</li>
</ul>
<ul>
<li><p>점화식에 대한 폐쇄형
$$
T(n) = \begin{cases}</p>
<pre><code>    \Theta(1),\ n = 1\\
    T(n-1) + \Theta(1), \ n \ge 2
   \end{cases}\\</code></pre><p>\text{폐쇄형:}T(n) = \Theta(n)
$$</p>
<p>$$
T(n) = \begin{cases}</p>
<pre><code>    \Theta(1),\ n = 1\\
    T(n-1) + \Theta(n), \ n \ge 2
   \end{cases}\\</code></pre><p>\text{폐쇄형:}T(n) = \Theta(n^2)
$$</p>
<p>$$
T(n) = \begin{cases}</p>
<pre><code>    \Theta(1),\ n = 1\\
    T({n \over 2}) + \Theta(1), \ n \ge 2
   \end{cases}\\</code></pre><p>\text{폐쇄형:}T(n) = \Theta(log\ n)
$$</p>
</li>
</ul>
<p>  $$
  T(n) = \begin{cases}
          \Theta(1),\ n = 1\
          T({n \over 2}) + \Theta(n), \ n \ge 2
         \end{cases}\</p>
<p>  \text{폐쇄형:}T(n) = \Theta(n)
  $$</p>
<p>  $$
  T(n) = \begin{cases}
          \Theta(1),\ n = 1\
          2T({n \over 2}) + \Theta(1), \ n \ge 2
         \end{cases}\</p>
<p>  \text{폐쇄형:}T(n) = \Theta(n)
  $$</p>
<p>  $$
  T(n) = \begin{cases}
          \Theta(1),\ n = 1\
          2T({n \over 2}) + \Theta(n), \ n \ge 2
         \end{cases}\</p>
<p>  \text{폐쇄형:}T(n) = \Theta(nlog\ n)
  $$</p>
<h2 id="2장-정렬">2장. 정렬</h2>
<ul>
<li><p>정렬</p>
<p>자료가 저장되는 위치: <strong>내부 정렬</strong>과 <strong>외부 정렬</strong>로 나누어진다. </p>
<p>정렬 방식: <strong>비교 기반 정렬 알고리즘</strong>과 <strong>그렇지 않은 알고리즘</strong>으로 나누어진다.</p>
</li>
</ul>
<ul>
<li><p>안정적 알고리즘</p>
<p>동일한 키를 갖는 각 레코드쌍 A, B에 대하여, 정렬 전에 A가 B의 앞에 있었고 정렬 후에도 이 순서 그대로 유지되는 것이 보장된다.</p>
</li>
</ul>
<ul>
<li><p>선택 정렬</p>
<blockquote>
<p>$n$ 개의 키 중에서 가장 작은 것을 찾아서 그 키와 첫째 키인 $A[0]$와 자리바꿈을 한다.</p>
<p>다음에는 남아있는 키들 중에서 가장 작은 키를  찾아서 그 원소와 $A[1]$의 자리를 바꾼다.  </p>
</blockquote>
<pre><code class="language-pseudocode">void SelectionSort (int A[], int n) {
    int i, j, MinINdex;
    for(i = 0; i &lt; n-1; i++) {
        MinIndex = i;
        for(j = MinIndex+1; j &lt; n; j++) {
            if(A[MinIndex] &gt; A[j])
                MinIndex = j;
        }
        if(MinIndex != i)
            Swap(&amp;A[i], &amp;A[MinIndex]);
    }
}</code></pre>
<p>레코드 수가 작을 경우에 효율적.</p>
<p>시간 복잡도는 $O(n^2)$ 으로 <strong>불안정한 알고리즘</strong>이다. </p>
</li>
</ul>
<ul>
<li><p>버블 정렬</p>
<blockquote>
<p>먼저 $n$ 개의 키가 왼쪽으로부터 오른쪽으로 검색되면서 모든 인접한 두 개의 키가 서로 비교된다.</p>
<p>인접한 두 개의 키 중에서 왼쪽의 키가 더 크면 오른쪽의 키와 자리를 바꾼다. </p>
<p>$n - 1$ 회 거치면 배열 전체가 오름차순으로 정렬된다. </p>
</blockquote>
<pre><code class="language-pseudocode">void BubbleSort(int A[], int n) {
    int i, Sorted; # 자리바꿈이 일어났는지 확인하기 위한 변수
    Sorted = FALSE; 
    while (!Sorted) {
        Sorted = TRUE;
        for(i = 1;i &lt; n; i++) {
            if (A[i-1] &gt; A[i]) {
                Swap(&amp;A[i-1], &amp;A[i]);
                Sorted = FALSE;
            }
        }
    }
}</code></pre>
<p> 시간 복잡도는 $O(n^2)$ 으로 <strong>안정한 알고리즘</strong>이다. </p>
</li>
</ul>
<ul>
<li><p>삽입 정렬</p>
<blockquote>
<p>삽입 정렬의 $i$ 번째 단계가 시작될 때에 배열의 맨 처음 $i-1$ 개의 키인 $A[0:i-2]$ 는 이미 정렬되어 있다. 여기에 $A[i-1]$을 삽입하여 $A[0:i-1]$ 이 정렬되도록 하는 것이 $i$ 번째 단계의 목표이다. </p>
<p>$A[i-1]$ 자리에 있던 키가 제자리를 찾을 때까지 키를 오른쪽으로 한 자리씩 옮기고, 원래 $A[i-1]$ 을 빈 자리에 삽입한다.</p>
</blockquote>
<pre><code class="language-pseudocode">void InsertionSort(int A[], int n) {
    int i, j, Value;
    for(i =2; i &lt;= n; i++) {
        Value = A[i];
        j = i;
        while(A[j-1] &gt; Value) {
            A[j] = A[j-1];
            j--;
        }
        A[j] = Value;
    }
}</code></pre>
<p> A[0]는 알고리즘을 간결하게 하기 위한 더미(dummy) 키를 넣는다. </p>
<p>시간 복잡도는 $O(n^2)$ 으로 <strong>안정한 알고리즘</strong>이다. </p>
</li>
</ul>
<ul>
<li><p>쉘 정렬</p>
<blockquote>
<p>배열을 부분배열로 나누어 그 각각에 삽입 정렬을 실행한다.
각 부분배열은 거리가 일정하게 떨어져 있는 원소들로 구성한다.</p>
<p>한 번의 비교 후에 키가 일정한 자리만큼 이동하게 되므로 키는 일반적으로 좀 더 빨리 제자리에 접근한다. </p>
<p>각 부분배열의 정렬이 끝나면 전체배열에 다시 삽입 정렬을 적용한다. </p>
</blockquote>
<pre><code class="language-pseudocode">void ShellSort(int A[], int n) {
    int h, i, j, Value;
    h = 1;
    do h = 3 * h + 1; while (h &lt; n);
    do {
        h = h / 3;
        for(i = h; i &lt; n; i++) {
            Value = A[i];
            j = i;
            while(A[j-h] &gt; Value) {
                A[j] = A[j-h];
                j -= h;
                if (j &lt;= h-1)
                    break;
            }
        }
        A[j] = Value;
    } while (h &gt; 1)
}</code></pre>
<p>시간 복잡도는 $O(n^{3 \over 2})$ 으로 <strong>불안정한 제자리 알고리즘</strong>이다. </p>
<p>순열 h는 $h_{i+1} = 3h_{i}+1$ 이다.</p>
</li>
</ul>
<ul>
<li><p>퀵 정렬</p>
<blockquote>
<p>정렬한 기들을 배열 내에서 적당히 이동시키면서 다음의 두 조건이 만족되도록 배열을 오른쪽 부분배열과 왼쪽 부분배열로 나눈다.</p>
<ol>
<li>왼쪽 부분배열에 있는 모든 키들은 오른쪽 부분배열의 가장 작은 키보다 작다.</li>
<li>오른쪽 부분배열에 있는 모든 키들은 왼쪽 부분배열의 가장 큰 값보다 크다.</li>
</ol>
<p>정렬할 배열은 분할원소(pivot)을 기준으로 두 개의 부분배열로 나눈다. (보통 배열의 첫째 키를 pivot으로 사용한다.)</p>
<p>pivot을 기준으로 오른쪽은 pivot보다 큰 원소를 찾으며, 왼쪽은 pivot보다 작은 원소를 찾는다. </p>
<p>이 두키의 자리를 서로 바꾸고 검색을 계속한다. </p>
<p>엇갈리는 지점이 나타나면 검색을 중단하고 pivot을 넣는다. </p>
</blockquote>
<pre><code class="language-pseudocode">void Partition (int A[], int Left, int Right ) { 
    int PartElem, Value;
    PartElem = Left;
    Value = A[PartElem];
    do {
        do {  } while (A[ ++Left] &lt; Value);
         do {  } while (A[ --Right] &gt; Value);
         if (Left &lt; Right) Swap (&amp;A[Left], &amp;A[Right]);
         else break;
    } while (1);
    A[PartElem] = A[Right];
     A[Right] = Value;
     return Right;
}</code></pre>
<pre><code class="language-pseudocode">void QuickSort (int A[], int Left, int Right ) { 
    int Middle;
     if (Right &gt; Left) {
         Middle = Partition (A, Left, Right + 1);
         QuickSort (A, Left, Middle – 1);
         QuickSort (A, Middle + 1, Right);
     }
 }</code></pre>
<p>시간 복잡도는 $O(n\ logn))$ 으로 <strong>불안정한 정렬 알고리즘</strong>이다. </p>
<p>순열 h는 $h_{i+1} = 3h_{i}+1$ 이다.</p>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>