<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>coginner_.log</title>
        <link>https://velog.io/</link>
        <description>우당탕탕 코린이</description>
        <lastBuildDate>Tue, 23 Jul 2024 13:34:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>coginner_.log</title>
            <url>https://velog.velcdn.com/images/coginner_/profile/96784307-c672-47bb-ac1f-ee10b212bf6c/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. coginner_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/coginner_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SQL] Join(hash, nested loop, merge)?]]></title>
            <link>https://velog.io/@coginner_/SQL-Joinhash-nested-loop-merge</link>
            <guid>https://velog.io/@coginner_/SQL-Joinhash-nested-loop-merge</guid>
            <pubDate>Tue, 23 Jul 2024 13:34:35 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터베이스-조인">데이터베이스 조인</h1>
<h2 id="1-해시-조인-hash-join">1. 해시 조인 (Hash Join)</h2>
<p><strong>개요</strong>:  
해시 조인은 대용량 테이블 조인에 적합하며, 두 테이블 중 하나가 메모리에 적합할 때 사용됩니다. 이는 주로 조인 조건이 <code>=</code> (등호)일 때 사용됩니다.</p>
<p><strong>작동 방식</strong>:</p>
<ol>
<li><p><strong>빌드 단계</strong>:  </p>
<ul>
<li>더 작은 테이블을 선택합니다(일반적으로 더 작은 테이블을 메모리에 올리기 쉽기 때문입니다).  </li>
<li>이 테이블의 조인 컬럼을 기반으로 해시 테이블을 생성합니다. 해시 함수는 입력값을 특정 버킷(bucket)으로 매핑합니다. 이 버킷은 실제 메모리 내의 저장 위치를 나타냅니다.  </li>
<li>각 행의 조인 키를 해시 함수에 입력하여 해시 값을 계산하고, 그 해시 값을 사용하여 해당 행을 해시 테이블에 저장합니다.</li>
</ul>
</li>
<li><p><strong>프로브 단계</strong>:  </p>
<ul>
<li>큰 테이블의 각 행을 읽고, 해당 행의 조인 키에 해시 함수를 적용하여 해시 값을 얻습니다.</li>
<li>그 해시 값을 사용하여 해시 테이블에서 일치하는 버킷을 찾습니다.</li>
<li>버킷에서 해당 행이 존재하는지 확인하고, 조인 조건에 부합하는 행이 있다면 두 행을 결합하여 결과 집합에 추가합니다.</li>
</ul>
</li>
</ol>
<p><strong>장점</strong>:</p>
<ul>
<li>매우 빠른 조회가 가능하며, 대량의 데이터를 다룰 때 효율적입니다.</li>
</ul>
<p><strong>단점</strong>:</p>
<ul>
<li>메모리 사용량이 많을 수 있습니다.</li>
<li>해시 테이블을 생성하는 데 시간이 소요될 수 있습니다.</li>
</ul>
<p><strong>예시</strong>:  
고객 정보와 주문 정보를 조인한다고 가정할 때, 고객 정보가 메모리에 올릴 수 있는 크기라면 고객 정보를 해시 테이블로 만들어 주문 정보의 각 행을 탐색하며 일치하는 고객 정보를 찾습니다.</p>
<h2 id="2-중첩-루프-조인-nested-loop-join">2. 중첩 루프 조인 (Nested Loop Join)</h2>
<p><strong>개요</strong>:  
중첩 루프 조인은 가장 기본적이고 직관적인 조인 방법으로, 두 테이블을 비교하여 조인하는 방식입니다. 두 테이블의 모든 조합을 비교하기 때문에 성능은 비교적 떨어질 수 있습니다.</p>
<p><strong>작동 방식</strong>:</p>
<ol>
<li><p><strong>외부 루프</strong>:  </p>
<ul>
<li>첫 번째(외부) 테이블의 각 행을 순차적으로 선택합니다.</li>
</ul>
</li>
<li><p><strong>내부 루프</strong>:  </p>
<ul>
<li>두 번째(내부) 테이블의 각 행을 선택하고, 외부 테이블의 현재 행과 비교합니다.</li>
<li>두 행이 조인 조건을 만족하면 이 두 행을 결합하여 결과에 추가합니다.</li>
</ul>
</li>
</ol>
<p><strong>장점</strong>:</p>
<ul>
<li>구현이 간단하며, 작은 테이블이나 인덱스가 있는 경우 매우 효과적입니다.</li>
</ul>
<p><strong>단점</strong>:</p>
<ul>
<li>두 테이블의 크기가 크면 비효율적이며, 성능이 저하됩니다. 이는 모든 행의 모든 조합을 비교하기 때문입니다.</li>
</ul>
<p><strong>예시</strong>:  
제품 정보와 그 제품의 공급업체 정보를 조인할 때, 각 제품을 하나씩 읽어 해당 제품을 공급하는 공급업체를 하나씩 비교하여 찾습니다.</p>
<h2 id="3-병합-조인-merge-join">3. 병합 조인 (Merge Join)</h2>
<p><strong>개요</strong>:  
병합 조인은 두 테이블이 조인 키로 정렬되어 있을 때 사용하는 조인 방식입니다. 정렬된 데이터를 순차적으로 읽으며 조인을 수행하기 때문에 대용량의 정렬된 데이터를 조인할 때 매우 효율적입니다.</p>
<p><strong>작동 방식</strong>:</p>
<ol>
<li><p><strong>정렬</strong>:  </p>
<ul>
<li>두 테이블이 조인 키로 정렬되어 있어야 합니다. 정렬이 되어 있지 않으면 먼저 정렬합니다.</li>
</ul>
</li>
<li><p><strong>순차 비교</strong>:  </p>
<ul>
<li>각 테이블의 시작 지점에서부터 조인 키를 비교합니다.</li>
<li>두 테이블의 조인 키가 같으면, 해당 행들을 결합하여 결과에 추가합니다. 이후, 두 테이블 모두 다음 행으로 이동합니다.</li>
<li>만약 한 테이블의 조인 키가 더 작다면, 작은 키의 테이블만 다음 행으로 이동하여 비교를 계속합니다.</li>
</ul>
</li>
</ol>
<p><strong>장점</strong>:</p>
<ul>
<li>데이터가 정렬되어 있다면 매우 효율적입니다.</li>
<li>대량의 데이터를 처리할 때 성능이 뛰어납니다.</li>
</ul>
<p><strong>단점</strong>:</p>
<ul>
<li>데이터가 정렬되지 않은 경우, 정렬하는 데 추가적인 비용이 발생합니다.</li>
</ul>
<p><strong>예시</strong>:  
판매 데이터와 고객 데이터를 조인할 때, 두 데이터가 고객 ID로 이미 정렬되어 있다면, 첫 번째 고객부터 순차적으로 비교하여 조인 결과를 생성합니다.</p>
<h2 id="최종-정리">최종 정리</h2>
<p>이 세 가지 조인 방식은 각각의 데이터 크기, 정렬 여부, 인덱스 존재 여부 등에 따라 적절히 선택되어야 합니다. 데이터베이스 엔진은 이러한 정보를 기반으로 최적의 조인 방식을 자동으로 선택하여 쿼리 성능을 최대화합니다. 조인을 잘 이해하고 있으면 SQL 쿼리의 성능을 향상시키는 데 큰 도움이 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OSI 7계층]]></title>
            <link>https://velog.io/@coginner_/OSI-7%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@coginner_/OSI-7%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Wed, 10 Jul 2024 14:29:38 GMT</pubDate>
            <description><![CDATA[<h1 id="osi-7계층-모델">OSI 7계층 모델</h1>
<p>OSI (Open Systems Interconnection) 모델은 네트워크 통신의 표준을 정립한 모델로, 네트워크 시스템 간의 상호 운용성을 보장하기 위해 7개의 계층으로 나누어 설명한다. 각 계층은 특정한 네트워크 기능을 담당하며, 상호 간의 의사소통을 위해 표준화된 인터페이스를 제공한다.</p>
<h2 id="1-물리-계층-physical-layer">1. 물리 계층 (Physical Layer)</h2>
<ul>
<li><strong>역할</strong>: 네트워크 하드웨어와 관련된 모든 것, 즉 물리적인 전송 매체와 신호 변환을 담당.</li>
<li><strong>주요 기능</strong>:<ul>
<li>비트 스트림 전송</li>
<li>전기적, 기계적, 기능적 사양 정의 (케이블, 스위치, 허브 등)</li>
<li>데이터 전송 속도와 물리적 연결 관리</li>
</ul>
</li>
<li><strong>예시</strong>: Ethernet, USB, RS-232</li>
</ul>
<h2 id="2-데이터-링크-계층-data-link-layer">2. 데이터 링크 계층 (Data Link Layer)</h2>
<ul>
<li><strong>역할</strong>: 네트워크 기기 간의 데이터 전송과 오류 검출 및 수정 기능 담당.</li>
<li><strong>주요 기능</strong>:<ul>
<li>프레임화 (Framing): 데이터 단위를 프레임으로 분할</li>
<li>물리 주소 지정 (MAC 주소)</li>
<li>오류 검출 및 수정 (CRC, Parity Bit 등)</li>
<li>흐름 제어</li>
</ul>
</li>
<li><strong>예시</strong>: Ethernet (IEEE 802.3), Wi-Fi (IEEE 802.11), PPP</li>
</ul>
<h2 id="3-네트워크-계층-network-layer">3. 네트워크 계층 (Network Layer)</h2>
<ul>
<li><strong>역할</strong>: 데이터가 여러 네트워크를 통해 목적지에 도달할 수 있도록 경로 결정.</li>
<li><strong>주요 기능</strong>:<ul>
<li>라우팅 (Routing): 경로 설정 및 데이터 전달</li>
<li>논리 주소 지정 (IP 주소)</li>
<li>패킷 포워딩</li>
<li>혼잡 제어</li>
</ul>
</li>
<li><strong>예시</strong>: IP (Internet Protocol), ICMP, ARP</li>
</ul>
<h2 id="4-전송-계층-transport-layer">4. 전송 계층 (Transport Layer)</h2>
<ul>
<li><strong>역할</strong>: 종단 간 (end-to-end) 통신 제공 및 데이터의 신뢰성 있는 전송 보장.</li>
<li><strong>주요 기능</strong>:<ul>
<li>세그멘테이션과 재조립 (Segmentation and Reassembly)</li>
<li>연결 설정, 유지, 해제 (TCP)</li>
<li>흐름 제어와 오류 제어</li>
<li>데이터 전송의 신뢰성 보장</li>
</ul>
</li>
<li><strong>예시</strong>: TCP (Transmission Control Protocol), UDP (User Datagram Protocol)</li>
</ul>
<h2 id="5-세션-계층-session-layer">5. 세션 계층 (Session Layer)</h2>
<ul>
<li><strong>역할</strong>: 통신 세션을 설정, 관리, 종료하는 역할.</li>
<li><strong>주요 기능</strong>:<ul>
<li>세션 설정 및 종료</li>
<li>데이터 교환 관리 (반이중 또는 전이중 모드)</li>
<li>체크포인팅과 복구</li>
</ul>
</li>
<li><strong>예시</strong>: NetBIOS, PPTP</li>
</ul>
<h2 id="6-표현-계층-presentation-layer">6. 표현 계층 (Presentation Layer)</h2>
<ul>
<li><strong>역할</strong>: 데이터의 형식화 및 변환을 담당하여 서로 다른 시스템 간의 데이터 호환성 제공.</li>
<li><strong>주요 기능</strong>:<ul>
<li>데이터 암호화 및 복호화</li>
<li>데이터 압축</li>
<li>데이터 형식 변환 (예: 문자 인코딩, 이미지 포맷 변환)</li>
</ul>
</li>
<li><strong>예시</strong>: JPEG, MPEG, GIF, TLS/SSL</li>
</ul>
<h2 id="7-응용-계층-application-layer">7. 응용 계층 (Application Layer)</h2>
<ul>
<li><strong>역할</strong>: 사용자와 직접 상호작용하는 애플리케이션과 관련된 기능 제공.</li>
<li><strong>주요 기능</strong>:<ul>
<li>네트워크 서비스 요청 및 응답</li>
<li>사용자 인터페이스 제공</li>
<li>데이터 처리 및 애플리케이션 로직 구현</li>
</ul>
</li>
<li><strong>예시</strong>: HTTP, FTP, SMTP, DNS, Telnet</li>
</ul>
<p>이러한 계층화된 접근 방식은 <strong>네트워크 통신의 복잡성을 줄이고</strong>, 각 계층의 <strong>표준화된 인터페이스를 통해 다양한 시스템 간의 상호 운용성을 보장</strong>합니다. 각 계층은 자신의 특정 역할을 수행하며, <strong>다른 계층과 독립적으로 동작</strong>하여 <strong>네트워크 통신의 유연성과 효율성을 높인다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST API ?]]></title>
            <link>https://velog.io/@coginner_/REST-API</link>
            <guid>https://velog.io/@coginner_/REST-API</guid>
            <pubDate>Sat, 13 Aug 2022 16:49:45 GMT</pubDate>
            <description><![CDATA[<h1 id="1-rest-api">1. REST API</h1>
<hr>
<p>REST는 Representation State Transfer라는 용어의 약자로 웹(HTTP)의 장점을 최대한 활용할 수 있는 아키텍처</p>
<h1 id="2-rest-구성">2. REST 구성</h1>
<hr>
<ul>
<li>자원(RESOURCE) - URI</li>
<li>행위(Verb) - HTTP METHOD</li>
<li>표현(Presentations)</li>
</ul>
<h1 id="3-rest의-특정">3. REST의 특정</h1>
<hr>
<p>1) Uniform (유니폼 인터페이스)
Uniform Interface는 URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말합니다.</p>
<p>2) Stateless (무상태성)
REST는 무상태성 성격을 갖습니다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않습니다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 됩니다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해집니다.</p>
<p>3) Cacheable (캐시 가능)
REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능합니다. 따라서 HTTP가 가진 캐싱 기능이 적용 가능합니다. HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능합니다.</p>
<p>4) Self-descriptiveness (자체 표현 구조)
REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것입니다.</p>
<p>5) Client - Server 구조
REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 됩니다.</p>
<p>6) 계층형 구조
REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 합니다.</p>
<h1 id="4-rest-api-디자인-가이드">4. REST API 디자인 가이드</h1>
<hr>
<p>REST API 설계 시 가장 중요한 항목은 다음의 2가지로 요약할 수 있습니다.</p>
<p>첫 번째, <code>URI는 정보의 자원을 표현</code>해야 한다.
두 번째, <code>자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현</code>한다.</p>
<h2 id="4-1-rest-api-중심-규칙">4-1. REST API 중심 규칙</h2>
<hr>
<h4 id="1-uri는-정보의-자원을-표현해야-한다-리소스명은-동사보다는-명사를-사용">1) URI는 정보의 자원을 표현해야 한다. (리소스명은 동사보다는 명사를 사용)</h4>
<pre><code class="language-java">GET /member/delete/1</code></pre>
<p>위와 같은 방식은 REST를 제대로 적용하지 않은 URI입니다. URI는 자원을 표현하는데 중점을 두어야 합니다. <strong><em>delete와 같은 행위에 대한 표현이 들어가서는 안됩</em></strong>니다.</p>
<h4 id="2-자원에-대한-행위는-http-methodget-post-put-delete-등로-표현">2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE 등)로 표현</h4>
<p>위의 잘못 된 URI를 HTTP Method를 통해 수정해보면</p>
<pre><code class="language-java">DELETE /member/1</code></pre>
<p>으로 수정할 수 있습니다.</p>
<p>회원정보를 가져올 떄는 GET, 회원 추가 시의 행위를 표현하고자 할 때는 POST Method를 사용하여 표현합니다.</p>
<p><strong>회원정보를 가져오는 URI</strong></p>
<pre><code class="language-java">GET /member/show/1 (X)
GET /member/1      (O)</code></pre>
<p><strong><em>회원을 추가할 때</em></strong></p>
<pre><code class="language-java">GET /member/insert/2 (X) - GET 메서드는 리소스 생성에 맞지 않습니다.
POST /member/2.      (O)</code></pre>
<p><strong><em>[참고]HTTP METHOD의 알맞은 역할</em></strong>
POST, GET, PUT, DELETE 이 4가지의 Method를 가지고 CRUD를 할 수 있습니다.</p>
<table>
<thead>
<tr>
<th align="center">METHOD</th>
<th align="center">역할</th>
</tr>
</thead>
<tbody><tr>
<td align="center">POST</td>
<td align="center">POST를 통해 해당 URI를 요청하면 리소스를 생성한다.</td>
</tr>
<tr>
<td align="center">GET</td>
<td align="center">GET을 통해 해당 리소스를 제회한다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가저온다.</td>
</tr>
<tr>
<td align="center">PUT</td>
<td align="center">PUT을 통해 리소스를 수정한다.</td>
</tr>
<tr>
<td align="center">DELETE</td>
<td align="center">DELETE를 통해 리소스를 삭제한다.</td>
</tr>
</tbody></table>
<p>다음과 같은 식으로 URI는 자원을 표현하는 데에 집중하고 행위에 대한 정의는 HTTP METHOD를 통해 하는 것이 <code>REST한 API</code>를 설계하는 중심 규칙입니다.</p>
<h2 id="4-2uri-설계-시-주의할-점">4-2.URI 설계 시 주의할 점</h2>
<hr>
<h4 id="1-슬래시-구분자는-계층-관계를-나타내는-데-사용">1) 슬래시 구분자(/)는 계층 관계를 나타내는 데 사용</h4>
<pre><code class="language-java">http://restapi.example.com/houses/apartments
http://restapi.example.com/animals/mammals/whales</code></pre>
<h4 id="2-uri-마지막-문자로-슬래시를-포함하지-않는다">2) URI 마지막 문자로 슬래시(/)를 포함하지 않는다.</h4>
<p>URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 하며 URI가 다르다는 것은 리소스가 다르다는 것이고, 역으로 리소스가 다르면 URI도 달라져야 합니다. REST API는 분명한 URI를 만들어 통신을 해야 하기 때문에 혼동을 주지 않도록 URI 결로의 마자막에는 슬래시(/)를 사용하지 않습니다.</p>
<pre><code class="language-java"> http://restapi.example.com/houses/apartments/ (X)
 http://restapi.example.com/houses/apartments  (0)</code></pre>
<h4 id="3-하이픈-은-uri-가독성을-높이는데-사용">3) 하이픈(-)은 URI 가독성을 높이는데 사용</h4>
<p>URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI경로를 사용하게 된다면 하이픈을 사용해 가독성을 높을 수 있습니다.</p>
<h4 id="4-밑줄_은-uri에-사용하지-않는다">4) 밑줄(_)은 URI에 사용하지 않는다.</h4>
<p>글꼴에 따라 다르긴 하지만 밑줄은 보기 어렵거나 밑줄 때문에 문자가 가려지기도 합니다. 이런 문제를 피하기 위해 밑줄 대신 하이픈(_)을 사용하는 것이 좋습니다.(가독성)</p>
<h4 id="5-uri-경로에는-소문자가-적합하다">5) URI 경로에는 소문자가 적합하다.</h4>
<p>URI 경로에 대문자 사용은 피하도록 해야 합니다. 대소문제에 따라 다른 리소스로 인식하게 되기 때문입니다. RFC 3986(URI 문법 형식)은 URI 스키마와 호스트를 제회하고는 대소문자를 구별하도록 규정하기 때문입니다.</p>
<pre><code class="language-java">RFC 3986 is the URI (Unified Resource Identifier) Syntax document</code></pre>
<h4 id="6-파일-확장자는-uri에-포함하지-않는다">6) 파일 확장자는 URI에 포함하지 않는다.</h4>
<pre><code class="language-java">    http://restapi.example.com/members/soccer/345/photo.jpg (X)</code></pre>
<p>REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않습니다. Accept header를 사용하도록 합니다.</p>
<pre><code class="language-java">    GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg</code></pre>
<h2 id="4-3리소스-간의-관계를-표현하는-방법">4-3.리소스 간의 관계를 표현하는 방법</h2>
<hr>
<p>REST 리소스 간에는 연관 관계가 있을 수 있고, 이런 경우 다음과 같은 표현방법으로 사용합니다.</p>
<pre><code class="language-java">    /리소스명/리소스 ID/관계가 있는 다른 리소스명

    ex)    GET : /users/{userid}/devices (일반적으로 소유 ‘has’의 관계를 표현할 때)</code></pre>
<p>만약에 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있습니다. 예를 들어 사용자가 &#39;좋아하는&#39;디바이스 목록을 표현해야 할 경우 다음과 같은 형태로 사용될 수 있습니다.</p>
<pre><code class="language-java">    GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)</code></pre>
<h2 id="4-4-자원을-표현하는-collection과-document">4-4. 자원을 표현하는 Collection과 Document</h2>
<hr>
<p>Collection 과 Document에 대해 알면 URI 설계가 한 층 더 쉬워집니다.
DOCUMENT는 단순히 문서로 이해해도 되고, 한 객체라고 이해해도 됩니다. 컬렉션은 문서들의 집합, 객체들의 집합이라고 생각하면 이해하는데 좀 더 편합니다. 컬렉션과 도큐먼트는 모두 리소스라고 표현할 수 있으며 URI에 표현됩니다. 예를 들어보면 </p>
<pre><code class="language-java">    http:// restapi.example.com/sports/soccer</code></pre>
<p>위 URI를 보면 sports라는 컬렉션과 soccer라는 도큐먼트로 표현되고 있다고 생각하면 됩니다. 좀 더 예를 들어보자면</p>
<pre><code class="language-java">    http:// restapi.example.com/sports/soccer/players/13</code></pre>
<p>sports, players 컬렉션과 soccer, 13(13번인 선수)를 의미하는 도큐먼트로 URI가 이루어지게 됩니다. 여기서 중요한 점은 <strong>컬렉션은 복수</strong>로 사용되고 있다는 점입니다.
좀 더 직관적인 REST API를 위해서는 컬렉션과 도큐먼트를 사용할 때 단수 복수도 지켜준다면 좀 더 이해하기 쉬운 URI를 설계할 수 있습니다.</p>
<h1 id="5-http-응답-상태-코드">5. HTTP 응답 상태 코드</h1>
<p>마지막으로 응답 상태코드를 간단히 살펴보도록 하겠습니다. 잘 설계된 REST API는 URI만 잘 설계된 것이 아닌 그 리소스에 대한 응답을 잘 내어주는 것까지 포함되어야 합니다. 정확한 응답의 상태코드만으로도 많은 정보를 전달할 수 있기 떄문에 응답의 상태코드 값을 명확히 돌려주는 것은 생각보다 중요한 일이 될 수 있습니다. 혹시 200이나 4XX관련 특정 코드 정도만 사용하고 있다면 처리 상태에 대한 좀 더 명확한 상태코드 값을 사용할 수 있기를 권장합니다.</p>
<table>
<thead>
<tr>
<th align="center">상태코드</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">200</td>
<td align="center">클라이언트의 요청을 정상적으로 수행함</td>
</tr>
<tr>
<td align="center">201</td>
<td align="center">클라이언트가 어떠한 리소스 생성을 요청,</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">해당 리소스가 성공적으로 생성된(POST를 통한 리소스 생성 작업 시)</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">상태코드</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">400</td>
<td align="center">클라이언트의 요청이 부적절 할 경우 사용하는 응답 코드</td>
</tr>
<tr>
<td align="center">401</td>
<td align="center">클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용하는 응답 코드</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">(로그인 하지 않은 유저가 로그인 했을 때, 요청 가능한 리소스를 요청 했을 때)</td>
</tr>
<tr>
<td align="center">403</td>
<td align="center">유저 인등상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용하는 응답 코드</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">(403 보다는 400이나 404를 사용할 것을 권고, 403 자체가 리소스가 존재한다는 뜻이기 때문에)</td>
</tr>
<tr>
<td align="center">405</td>
<td align="center">클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">상태코드</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">301</td>
<td align="center">클라이언트가 요청한 리소스에 대한 URI가 변경 되었을 때 사용하는 응답 코드</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">(응답시 Location header에 변경된 URI를 적어 줘야 합니다.)</td>
</tr>
<tr>
<td align="center">500</td>
<td align="center">서버에 문제가 있을 경우 사용하는 응답 코드</td>
</tr>
</tbody></table>
<hr>
<p>[출처] </p>
<p><a href="https://meetup.toast.com/posts/92">REST API 제대로 알고 사용하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[061 오류를 검출하고 수정하는 알고리즘]]></title>
            <link>https://velog.io/@coginner_/061-%EC%98%A4%EB%A5%98%EB%A5%BC-%EA%B2%80%EC%B6%9C%ED%95%98%EA%B3%A0-%EC%88%98%EC%A0%95%ED%95%98%EB%8A%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@coginner_/061-%EC%98%A4%EB%A5%98%EB%A5%BC-%EA%B2%80%EC%B6%9C%ED%95%98%EA%B3%A0-%EC%88%98%EC%A0%95%ED%95%98%EB%8A%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Wed, 15 Jun 2022 18:19:40 GMT</pubDate>
            <description><![CDATA[<h1 id="오류-검출과-수정">오류 검출과 수정</h1>
<hr>
<blockquote>
<p>오류를 검출하고 수정까지 할 수 있게 하는, 신중하게 제어된 여분의 정보를 추가하는 과정</p>
</blockquote>
<br>

<h2 id="체크섬checksum-알고리즘">체크섬(checksum) 알고리즘</h2>
<hr>
<ul>
<li>중복 검사의 한 형태로, 오류 정정을 통해, 공간(전자 통신)이나 시간(기억 장치) 속에서 송신된 자료의 무결성을 보호하는 단순한 방법이다.</li>
</ul>
<ul>
<li>체크섬은 나열된 데이터를 더하여 체크섬 숫자를 얻고, 정해진 비트수의 모듈라로 정해진 비트수로 재구성 한다. </li>
<li>단순 덧셈 방식과 순환 중복 검사의 계산 방식과는 차이가 있으나,<ul>
<li>많은 경우 순환 중복 검사의 결과를 체크섬이라고 말하므로 단순 덧셈만을 의미하지는 않는다.</li>
</ul>
</li>
</ul>
<ul>
<li>기본적인 메시지 구성 요소(보통 비트)를 추가하여 결과값을 저장함으로써 동작한다.</li>
</ul>
<h3 id="체크섬의-예">체크섬의 예</h3>
<ul>
<li>다음과 같이 4 바이트의 데이터가 있다고 치자: 0x25, 0x62, 0x3F, 0x52</li>
<li>1 단계: 모든 바이트를 덧셈하면 0x118이 된다.</li>
<li>2 단계: 캐리 니블을 버림으로써 0x18을 만든다.</li>
<li>3 단계: 0x18의 2의 보수를 얻음으로써 0xE8을 얻는다. - 이것이 체크섬 바이트이다.</li>
<li>체크섬 바이트를 테스트하려면 원래 그룹의 바이트에 체크섬 바이트까지 모두 더하면 0x200이 된다.</li>
<li>다시 캐리 니블을 버림으로써 0x00이 된다. 0x00이라는 뜻은 오류가 없다는 뜻이다. (하지만 오류가 있어도 우연히 0x00이 될 수도 있다.)</li>
</ul>
<br>

<h2 id="페리티-코드">페리티 코드</h2>
<hr>
<ul>
<li>패리티  비트(parity  bit)를  사용하여  만드는  코드</li>
<li>패리티  비트는  데이터의  에러  검출을  위해  데이터에  추가되는  여분의 한 비트로서 시스템의 설계 기준에 따라 데이터 시작의 한 비트나 데이터 끝의 한 비트를 사용</li>
</ul>
<h3 id="패리티-비트">패리티 비트</h3>
<ul>
<li>정보의 전달 과정에서 오류가 생겼는지를 검사하기 위해 추가된 비트이다.</li>
<li>문자열 내 1비트의 모든 숫자가 짝수 또는 홀수인지를 보증하기 위해 전송하고자 하는 데이터의 각 문자에 1 비트를 더하여 전송하는 방법<ul>
<li>2가지 종류의 패리티 비트(홀수, 짝수)가 있다.</li>
</ul>
</li>
</ul>
<ul>
<li>짝수(even) 패리티<ul>
<li>전체 비트에서 1의 개수가 짝수가 되도록 패리티 비트를 정하는 것인데, 이를테면 데이터 비트에서 1의 개수가 홀수이면 패리티 비트를 1로 정한다.</li>
</ul>
</li>
<li>홀수(odd) 패리티<ul>
<li>전체 비트에서 1의 개수가 홀수가 되도록 패리티 비트를 정하는 방법이다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/66cb5951-b026-4700-8bdc-006b27966319/image.png" alt=""></p>
<ul>
<li><p>7비트의 0010110라는 데이터에서 짝수 패리티가 되게 하기 위해서는 1의 패리티 비트를 붙여 10010110로 한다.</p>
<ul>
<li>같은 데이터에 대해 홀수 패리티 비트가 되게 하려면 0의 패리티 비트를 붙인다.</li>
</ul>
</li>
<li><p>이렇게 패리티 비트를 정하여 데이터를 보내면 받는 쪽에서는 수신된 데이터의 전체 비트를 계산하여 패리티 비트를 다시 계산함으로써 데이터 오류 발생 여부를 알 수 있다.</p>
</li>
<li><p><strong><em>패리티 비트는 오류 발생 여부만 알 수 있지 오류를 수정할 수는 없다.</em></strong></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[060 ZIP 파일로 압축할 때]]></title>
            <link>https://velog.io/@coginner_/060-ZIP-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EC%95%95%EC%B6%95%ED%95%A0-%EB%95%8C</link>
            <guid>https://velog.io/@coginner_/060-ZIP-%ED%8C%8C%EC%9D%BC%EB%A1%9C-%EC%95%95%EC%B6%95%ED%95%A0-%EB%95%8C</guid>
            <pubDate>Wed, 15 Jun 2022 17:32:33 GMT</pubDate>
            <description><![CDATA[<h1 id="압축">압축</h1>
<hr>
<blockquote>
<p>압축의 목표는 같은 정보를 더 적은 비트로 인코딩하는 것이다.</p>
</blockquote>
<ul>
<li>압축의 기본 아이디어는 군더더기 정보, 즉 연결 부분의 반대쪽에서 데이터를 수신했을 때 재현하거나 유추할 수 있는 정보는 저장하거나 보내지 않는 것이다.</li>
</ul>
<h2 id="인코딩">인코딩</h2>
<blockquote>
<p>사용자가 입력한 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것</p>
</blockquote>
<ul>
<li>넓은 의미의 컴퓨터는 이러한 신호를 입력받고 처리하는 기계를 뜻한다.<ul>
<li>신호 처리 시스템을 통해 이렇게 처리된 정보를 사용자가 이해할 수 있게 된다.</li>
</ul>
</li>
</ul>
<h3 id="문자-인코딩의-구성">문자 인코딩의 구성</h3>
<ul>
<li>문자 정보는 정보를 표현하기 위한 글자들의 집합을 정의한 것</li>
<li>직접적으로 사용되지 않을 수도 있고 한 문자 집합을 여러 문자 인코딩에서 쓸 수도 있다.</li>
<li>특히 집합 안의 문자들에 음수가 아닌 정수들을 배정한 것을 부호화된 문자 집합(coded character set, CCS)라 한다.</li>
</ul>
<h4 id="문자-인코딩-형태character-encoding-form-cef">문자 인코딩 형태(character encoding form, CEF)</h4>
<ul>
<li>특정한 문자 집합 안의 문자들을 컴퓨터 시스템에서 사용할 목적으로 일정한 범위 안의 정수(코드값)들로 변환하는 방법이다.<ul>
<li>유니코드 코드 포인트를 8비트 숫자의 집합으로 나타내는 UTF-8이나, 16비트 숫자의 집합으로 나타내는 UTF-16, 그리고 대부분의 일반적인 문자 인코딩들이 포함</li>
</ul>
</li>
</ul>
<h4 id="문자-인코딩-구조character-encoding-scheme-ces">문자 인코딩 구조(character encoding scheme, CES)</h4>
<ul>
<li>문자 인코딩 형태로 변환된 코드값을 옥텟 기반의 시스템에서 사용하기 위하여 옥텟들로 변환하는 방법이다.<ul>
<li>대부분의 문자 인코딩 형태는 이 과정에서 아무런 일도 일어 나지 않으며, 8비트 이상의 숫자를 사용하는 UTF-16과 같은 문자 인코딩 형태의 경우 엔디안을 지정해 주는 것으로 충분하다.<ul>
<li>여기에는 ISO 2022와 같은 복합 인코딩이나, SCSU와 같은 압축 방법 등이 속한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="퍼센트-인코딩">퍼센트 인코딩</h4>
<ul>
<li>퍼센트 인코딩(percent-encoding)은 URL에 문자를 표현하는 문자 인코딩 방법이다.<ul>
<li>알파벳이나 숫자 등 몇몇 문자를 제외한 값은 옥텟 단위로 묶어서, 16진수 값으로 인코딩한다.</li>
</ul>
</li>
</ul>
<br>

<h2 id="허프먼-코딩부호화huffman-coding">허프먼 코딩(부호화)(Huffman coding)</h2>
<blockquote>
<p>무손실 압축에 쓰이는 엔트로피 부호화의 일종으로, 데이터 문자의 등장 빈도에 따라서 다른 길이의 부호를 사용하는 알고리즘</p>
</blockquote>
<ul>
<li>문자들의 빈도로부터 접두 부호(어떤 한 문자에 대한 부호가 다른 부호들의 접두어가 되지 않는 부호)를 만들어 내는 알고리즘으로, 적게 나오는 문자일수록 더 긴 부호를 쓰고 많이 나올수록 더 짧은 부호를 쓴다.</li>
</ul>
<h2 id="무손실-압축">무손실 압축</h2>
<ul>
<li>비손실 압축 또는 무손실 압축은 데이터 압축의 일종</li>
<li>원래의 정보를 그대로 보존해야 하기 때문에, 정보 엔트로피의 한계가 그대로 반영된다.<ul>
<li>정보 엔트로피의 한계란 개별 정보의 확률값에 의하여 계산되는 값이 아닌, 전체 신호의 상관관계를 반영한 한계값</li>
</ul>
</li>
</ul>
<ul>
<li>일반적으로 파일 데이터 압축에 사용하는 gzip을 비롯한 알고리즘들이 이에 해당한다.<ul>
<li>오디오나 이미지 압축에서 사용하는 무손실 압축 기술들은 각각의 신호 특성에 맞추어서 최적화가 된 것</li>
<li>범용성을 가지는 데이터 압축 기술에 비하여 조금 더 압축률을 끌어 올릴 수 있다.</li>
</ul>
</li>
</ul>
<br>

<h2 id="손실-압축">손실 압축</h2>
<ul>
<li>데이터를 압축하여 자료를 받는 곳에 압축으로 풀어서 원래의 것과 다르게 보여주는 것을 말하지만 어떠한 부분에서는 충분히 유용한 방식<ul>
<li>멀티미디어 데이터를 압축하는 데에 가장 많이 사용된다.</li>
</ul>
</li>
</ul>
<h3 id="손실-압축의-개념">손실 압축의 개념</h3>
<ul>
<li>주관적으로 중요한 정보들을 최대한 보존하는 것을 목표로 하며, 이를 위해 사람들이 잘 느끼지 못하거나 둔감한 정보는 손실시킨다.<ul>
<li>영상 압축의 경우에는 고주파 성분을 손실 시키거나, 색차 정보를 손실시키는 방식을 주로 사용</li>
<li>오디오의 경우에는 사람에게 잘 들리지 않는 소리를 손실시키는 방법을 사용</li>
</ul>
</li>
</ul>
<h3 id="지각-부호화perceptual-coding">지각 부호화(Perceptual Coding)</h3>
<ul>
<li>인식(지각)에 영향을 주지 않는 요소를 제거하여, 원 데이터를 압축하는 기술<ul>
<li>인간 감각의 불완전한 특징을 활용하는 부호화</li>
</ul>
</li>
</ul>
<ul>
<li>주로, 오디오 신호에 대해 심리음향적 효과를 이용한 오디오 신호 압축을 의미함<ul>
<li>심리음향 이론을 이용하여, 신호 중복성 및 무관성을 제거한 오디오 압축 코딩 기술</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>오히려 불필요한 정보가 추가되어 크기가 더 커지는 경우도 있는데<ul>
<li>더 이상 압축할 정보가 없는데도 압축 알고리즘을 거듭하는 경우가 그렇다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[035 운영체제가 일하는 법]]></title>
            <link>https://velog.io/@coginner_/035-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%EC%9D%BC%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@coginner_/035-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%EC%9D%BC%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Wed, 08 Jun 2022 01:15:35 GMT</pubDate>
            <description><![CDATA[<h1 id="프로세서는">프로세서는</h1>
<blockquote>
<p>컴퓨터가 켜졌을 떄 영구 기억 장치에 저장된 약간의 명령어를 실행해서 작동을 시작하도록 구성</p>
</blockquote>
<ul>
<li>플래시 메모리에서 읽은 멸령어는 최종적으로 유용한 작업을 하기에 충분한 코드가 로드될 때까지 더욱더 많은 명령어를 읽는다.<ul>
<li>이 과정을 <code>부트스트래핑bootstrapping</code>이라고 불렀는데, 지금은 <code>부팅booting</code>이라고 한다.</li>
<li><code>부팅</code> 과정에는 메모리와 다른 구성 요소를 점검해서 올바르게 작동하는지 확인하는 절차가 포함된다.</li>
</ul>
</li>
</ul>
<ul>
<li>운영체제는 일단 실행되면 간단한 작업 사이클을 집중적으로 수행하는데, 실행할 준비가 됐거나 관심이 필요한 각 애플리케이션에 차례로 통제권을 준다.</li>
<li>프로세서가 이 프로세스 각각에 차례로 관심을 갖고 처리하게 하고, 필요에 따라 프로세스 간에 초점을 전환한다.</li>
<li>각 프로그램은 짧은 시간조각을 할당 받는데, 시간 조각은 프로그램이 시스템 서비스를 요천하거나 프로그램에 할당된 시간이 다 되면 끝난다.</li>
</ul>
<ul>
<li>운영체제는 각 이벤트에 대해 필요한 어떤 일이든 수행하며, 보통은 그런 이벤트가 발생했다는 사실을 해당 이벤트를 처리해야 하는 애플리케이션에 전달한다.<ul>
<li>예를 들어 사용자가 메뉴에서 종료를 선택하거나 닫기 버튼을 클랙해서 애플리케이션을 종료하면 OS는 애플리케이션에 곧 끝나야 된다고 통보해서 애플리케이션이 남은 일을 정리할 기회를 준다.</li>
<li>그러고 나서 OS는 프로그램이 사용하던 모든 자원을 회수하고, 화면에 창이 노출될 다른 애플리케이션에 창을 다시 그려야 한다고 알려준다.</li>
</ul>
</li>
</ul>
<h1 id="시스템-콜">시스템 콜</h1>
<ul>
<li>운영체제는 하드웨어와 다른 소프트웨어 간의 인터페이스를 제공한다.<ul>
<li>OS는 애플리케이션이 구축될 수 있는 <code>플랫폼platform</code>을  제공한다.</li>
<li>추상화의 또 다른 예로, 구현상 들쑥날쑥한 부분이나 관련 없는 세부 사항을 감추는 인터페이스 또는 외관을 제공한다.</li>
</ul>
</li>
</ul>
<ul>
<li>OS는 이러한 서비스를 표준화된 방식 또는 합의된 방식으로 이용할 수 있게 하고, 애플리케이션은 운영체제의 특정 부분에 통제권을 넘겨주는 특별한 명령어를 실행함으로써 서비스를 요청한다.<ul>
<li>OS에 서비스를 요청하는 이 진입점을 <code>시스템 콜system call</code>이라고 하며, 시스템 콜의 세부 명세에서 그 운영체제가 무엇인지를 규정한다.</li>
</ul>
</li>
</ul>
<h1 id="디바이스-드라이버">디바이스 드라이버</h1>
<blockquote>
<p>운영체계와 프린터나 마우스 같은 특정 종류의 하드웨어 장치 간에 가교 역할을 하는 코드</p>
</blockquote>
<ul>
<li>드라이버 코드는 특정 장치가 어떤 일을 하도록 하는 방법을 자세히 알고 있다.</li>
</ul>
<ul>
<li>디바이스 드라이버는 특정 장치의 즉이한 속성에서 시스템의 나머지 부분을 분리한다.<ul>
<li>드라이버 인터페이스는 OS가 서로 다른 장치에 균일한 방식으로 접근하도록해서 장치를 전환하기 쉽게 해준다.</li>
<li>실제로는 OS가 추상적이거나 이상화된 장치에 포괄적인 요청을 하고, 드라이버가 특정 장치에 맞게 요청을 구체적으로 구현한다.</li>
<li>범용 OS는 많은 디바이스 드라이버가 있다.</li>
<li>부팅 시에 시스템에 현재 가용 장치에 필요한 드라이버를 불러오는 작업도 이루어진다.</li>
<li>새로운 장치가 갑자기 연결되는 일도 흔한데, 보통은 새로운 드라이버를 찾을 필요가 없다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/241cef8b-e36a-4e99-a11f-21da3101bfb0/image.png" alt=""></p>
<ul>
<li>위 그림은 디바이스 드라이버, 운영체제, 시스템 콜, 애플리케이션 간의 관계를 보여준다.</li>
</ul>
<h1 id="다양한-디지털-장치와-os">다양한 디지털 장치와 OS</h1>
<ul>
<li>기술 발달 덕분에 장치들은 전반적으로 앞에서 살펴봤던 범용 컴퓨터와 비슷한 모습을 띠고 있다.<ul>
<li>성능이 좋은 프로세서와 용량이 큰 메모리가 내장되어 있고, 카메라 렌즈와 디스플레이 같은 주변 장치가 여러 개 달려있다.</li>
</ul>
</li>
</ul>
<ul>
<li>사용환경이 특수한 경우가 아니라면 자신만의 전용 시스템을 개발하거나 값비싼 상용 제품의 라이선스를 얻는 것보다 리눅스에서 불필요한 부분을 뺀 버전을 사용하는 편이 더 쉽고 저렴하다.<ul>
<li>별도의 OS를 만들기보다는 범용 OS를 사용하는 방식이 더 타당하다.</li>
</ul>
</li>
</ul>
<h3 id="리눅스의-장점">리눅스의 장점</h3>
<ul>
<li>견고하다.</li>
<li>개조하기 용이하다.</li>
<li>이식 가능하다</li>
<li>무료이다.<h3 id="리눅스의-단점">리눅스의 단점</h3>
</li>
<li>GPL 같은 라이센스에 따라 결과물 코드 일부를 공개해야 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[034 가상 운영체제와 가상 머신]]></title>
            <link>https://velog.io/@coginner_/034-%EA%B0%80%EC%83%81-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EC%99%80-%EA%B0%80%EC%83%81-%EB%A8%B8%EC%8B%A0</link>
            <guid>https://velog.io/@coginner_/034-%EA%B0%80%EC%83%81-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EC%99%80-%EA%B0%80%EC%83%81-%EB%A8%B8%EC%8B%A0</guid>
            <pubDate>Tue, 07 Jun 2022 16:11:12 GMT</pubDate>
            <description><![CDATA[<h1 id="운영체제란">운영체제란?</h1>
<blockquote>
<p>간단한 프로그램과 마찬가지로 그저 하나의 프로그램이고, 그런 프로그램과 같은 종류의 프로그래밍 언어로 작성되며 대부분 C나 C++로 구현</p>
</blockquote>
<ul>
<li>초기 운영체제는 메모리도 작고 작업이 단순했기 때문에 크기도 작았다.</li>
<li>초창기의 운영체제는 한번에 한 개의 프로그램만 실행했으므로 스와핑이 제한적으로 이루어졌다.</li>
<li>지금은 운영체제가 매우 크고 복잡한데, 그만큼 다양하고 복잡한 일을 처리하기 때문이다.</li>
</ul>
<ul>
<li>많은 운영체제의 조상 격인 유닉스 운영체제는 1975년 두 명이 작성했고 C와 어셈블리 언어 9000행으로 이루어져 있었다.</li>
<li>오늘날 리눅스는 1천만 행이 훨씬 넘고, 수십 년간 수천 명이 작업한 결과물이다.</li>
<li>윈도우 10은 정확한 규모가 공개된 적은 없지만 5천만 행정도로 추측된다.
→ 운영체자가 어떤 구성 요소를 포함해야 하는지에 대한 관점도 유닉스 시절과 차이가 있다.</li>
</ul>
<ul>
<li>운영체제는 단지 프로그램이므로 이론상으로는 모든 사람이 직접 작성할 수 있다.</li>
<li>하드웨어 개발 시 원래 의도했던 것과는 다른 운영체제를 실행하기도 한다.<ul>
<li><code>멀티 부트multiple boot</code> 기능은 애플에서도 <code>부트 캠프Boot Camp</code>라는 이름으로 지원하는데, 맥OS 대신 윈도우를 실행하면서 시스템을 시작할 수 있다.</li>
</ul>
</li>
</ul>
<ul>
<li><p>심지어 다른 운영체제의 관리하에 특정한 운영체제를 <code>가상 운영체제virtual operating system</code>로 실행 가능하다.</p>
<ul>
<li><code>VM웨어VMware</code>, <code>버추얼박스VirtualBox</code>, <code>젠Xen</code> 같은 가상 운영체제 프로그램은 호스트 OS에서 어떤 OS를 게스트 OS로 실행할 수 있게 해준다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/8d922828-673c-4d59-bf01-28ca41e6e4d1/image.png" alt=""></p>
</li>
<li><p>위 그림은 호스느 OS에서 가상 OS가 어떻게 실행되는지를 도식화한 것으로, 게스트 OS는 호스트 OS 입장에서 보면 보통의 애플리케이션이다.</p>
</li>
</ul>
<h1 id="가상-머신-virtual-machine">가상 머신 Virtual Machine</h1>
<blockquote>
<p>컴퓨터인 것처럼 작동하는 프로그램
소프트웨어로만 존재하지만 마치 하드웨어인 것처럼 작동 방식을 모방하는 프로그램</p>
</blockquote>
<h2 id="가상-머신의-예시">가상 머신의 예시</h2>
<ul>
<li>자바 스크립트 프로그램을 해석하기 위한 가상 머신</li>
<li>자바 프로그램용 가상 머신</li>
<li>안드로이드용 가상 머신</li>
</ul>
<p>→ VM이 사용되는 이유는 물리적 장비를 만드는 것보다 프로그램을 작성해서 배포하는 것이 더 쉽고 유연</p>
<h2 id="클라우드-컴퓨팅-cloud-computing">클라우드 컴퓨팅 Cloud Computing</h2>
<ul>
<li>저장 공간과 네트워크 대역폭이 출분한 물리적 컴퓨터를 대량으로 보유하고, 그 자원을 이용하여 이용자에게 컴퓨팅 성능을 제공</li>
</ul>
<ul>
<li><code>아마존 웹 서비스Amazon Web Service</code>, 즉 <code>AWS</code>는 최대 클라우드 컴퓨팅 제공 업체이다.</li>
<li><code>마이크로소프트 애저Microsoft Azure</code>와 <code>구글 클라우드 플랫폼Google Cloud Platform</code>이 그 뒤를 잇는다.<ul>
<li>이러한 업체들 모두 고객의 작업량 변화에 맞게 서비스의 성능과 용량을 늘리거나 줄여 제공한다.</li>
<li>개별 사용자가 사용 규모를 즉각 확대하거나 축소할 수 있을 만큼 충분한 컴퓨팅 자원을 보유하고 있기에 가능하다.</li>
</ul>
</li>
</ul>
<ul>
<li>대표적인 예로 넷플릭스 같은 대형 업체를 비롯해서 많은 회사가 자체 서버를 운영하는 것보다 클라우드 컴퓨팅을 활용하는데, 서비스의 규모가 클수록 클라우드 컴퓨팅을 이용하는 것이 <strong>경제적, 적응성, HR 필요성 감소 등에 유리</strong>하기 때문이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JWT( JSON WEB TOKEN ) 란?]]></title>
            <link>https://velog.io/@coginner_/JWT-JSON-WEB-TOKEN-%EB%9E%80</link>
            <guid>https://velog.io/@coginner_/JWT-JSON-WEB-TOKEN-%EB%9E%80</guid>
            <pubDate>Thu, 02 Jun 2022 04:58:46 GMT</pubDate>
            <description><![CDATA[<h1 id="1jwtjson-web-token">1.JWT(JSON WEB TOKEN)</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/97d49210-6b14-4d2a-9d9c-36d6eeeb73fd/image.webp" alt=""></p>
<ul>
<li><code>JWT</code>는 <strong><code>JSON Web Token</code>의 약자</strong>로 전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON입니다.</li>
<li>전자 서명은 <strong>JSON 의 변조</strong>를 체크 할 수 있게되어 있습니다.</li>
<li><code>JWT</code>는 <strong>속성 정보 (Claim)</strong>를 JSON 데이터 구조로 표현한 토큰으로 <strong>RFC7519</strong> 표준 입니다.</li>
<li><code>JWT</code>는 <strong>서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증</strong>합니다.</li>
<li>이때 사용되는 JSON 데이터는 URL-Safe 하도록 URL에 포함할 수 있는 문자만으로 만듭니다.</li>
<li><code>JWT</code>는 <code>HMAC 알고리즘</code>을 사용하여 <strong>비밀키 또는 RSA</strong>를 이용한 <strong>Public Key/ Private Key</strong> 쌍으로 서명할 수 있습니다.</li>
</ul>
<p><br><br></p>
<h1 id="2jwsjson-web-signature-와-jwejson-web-encryption">2.JWS(JSON WEB SIGNATURE) 와 JWE(JSON WEB ENCRYPTION)</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/31e3e946-9e5b-4236-888e-542e9dceb2f0/image.webp" alt=""></p>
<h2 id="jwsjson-web-signature">JWS(JSON Web Signature)</h2>
<ul>
<li><code>JWS(JSON Web Signature)</code>는 JSON 데이터 구조를 사용하는 서명 표준이며,</li>
<li>간단히 말하면 <strong>“JSON으로 전자 서명을하여 URL-safe 문자열로 표현한 것”</strong>입니다. </li>
</ul>
<h2 id="jwejson-web-encryption"><code>JWE(JSON Web Encryption)</code></h2>
<ul>
<li><code>JWE(JSON Web Encryption)</code>는 JSON 데이터 구조를 사용하는 암호화 방법입니다.</li>
<li><code>JWE(JSON Web Encryption)</code>는 <strong>“JSON을 암호화하여 URL-safe 문자열로 표현한 것”</strong> 입니다.</li>
</ul>
<p><br><br></p>
<h1 id="3jwt-토큰-구성">3.JWT 토큰 구성</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/7d44fbe0-f1f2-46ce-91b6-5aea0e0c1bf0/image.png" alt=""></p>
<ul>
<li><code>JWT</code>는 세 파트로 나누어지며, 각 파트는 점으로 구분하여 <code>xxxxx.yyyyy.zzzzz</code>로 표현됩니다. 순서대로 <strong>헤더 (Header), 페이로드 (Payload), 서명 (Sinature)</strong>으로 구성합니다.</li>
<li><code>Base64 인코딩</code>의 경우 <code>“+”, “/”, “=”</code>이 포함되지만 JWT는 <strong>URI에서 파라미터로 사용할 수 있도록 URL-Safe 한  Base64url 인코딩을 사용</strong>합니다.</li>
</ul>
<ul>
<li><strong>헤더(Header)</strong>는 토큰의 타입과 해시 암호화 알고리즘으로 구성되어 있습니다.<ul>
<li>첫째는 <strong>토큰의 유형 (JWT)</strong>을 나타내고,</li>
<li>두 번째는 <strong>HMAC, SHA256 또는 RSA와 같은 해시 알고리즘</strong>을 나타내는 부분입니다.</li>
</ul>
</li>
</ul>
<ul>
<li><p><strong>페이로드(Payload)</strong>는 토큰에 담을 클레임(claim) 정보를 포함하고 있습니다. 페이로드(Payload)에 담는 정보의 한 ‘조각’ 을 클레임이라고 부르고, 이는 name / value 의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임들을 넣을 수 있습니다.</p>
<ul>
<li>클레임의 정보는 등록된 (registered) 클레임, 공개 (public) 클레임, 비공개 (private) 클레임으로 세 종류가 있습니다.</li>
</ul>
</li>
<li><p>마지막으로 <strong>서명(Sinature)</strong>은 secret key를 포함하여 암호화되어 있습니다.</p>
</li>
</ul>
<p><br><br></p>
<h1 id="4jwt-process">4.JWT PROCESS</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/32323f4e-682d-44a4-8a8d-e3bfafac807e/image.webp" alt=""></p>
<blockquote>
<ol>
<li>사용자가 id와 password를 입력하여 로그인을 시도합니다.</li>
<li>서버는 요청을 확인하고 secret key를 통해 Access token을 발급합니다.</li>
<li>JWT 토큰을 클라이언트에 전달 합니다.</li>
<li>클라이언트에서 API 을 요청할때  클라이언트가 Authorization header에 Access token을 담아서 보냅니다.</li>
<li>서버는 JWT Signature를 체크하고 Payload로부터 사용자 정보를 확인해 데이터를 반환합니다.</li>
<li>클라이언트의 로그인 정보를 서버 메모리에 저장하지 않기 때문에 토큰기반 인증 메커니즘을 제공합니다.</li>
</ol>
</blockquote>
<ul>
<li>인증이 필요한 경로에 접근할 때 서버 측은 Authorization 헤더에 유효한 JWT 또는 존재하는지 확인합니다.</li>
<li><code>JWT</code>에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스과 같은 서버와의 커뮤니케이션 오버 헤드를 최소화 할 수 있습니다.</li>
<li><code>Cross-Origin Resource Sharing (CORS)</code>는 쿠키를 사용하지 않기 때문에 <code>JWT</code>를 채용 한 인증 메커니즘은 두 도메인에서 API를 제공하더라도 문제가 발생하지 않습니다.</li>
<li>일반적으로 <code>JWT</code> 기반의 인증 시스템은 위와 같은 프로세스로 이루어집니다.
처음 사용자를 등록할 때 <code>Access token</code>과 <code>Refresh token</code>이 모두 발급되어야 합니다.</li>
</ul>
<p><br><br></p>
<h1 id="5jwt-장점과-단점">5.JWT 장점과 단점</h1>
<hr>
<h2 id="jwt-장점">JWT 장점</h2>
<ul>
<li><code>JWT</code>의 주요한 장점은 <strong>사용자 인증에 필요한 모든 정보가 토큰 자체에 포함되기 때문에 별도의 인증 저장소가 필요없다</strong>는 것입니다.</li>
<li>분산 마이크로 서비스 환경에서 중앙 집중식 인증 서버와 데이터베이스에 의존하지 않는 쉬운 인증 및 인가 방법을 제공합니다.</li>
<li>개별 마이크로 서비스에는 토큰 검증과 검증에 필요한 비밀 키를 처리하기 위한 미들웨이가 필요한데, 검증은 서명 및 클레임과 같은 몇 가지 매개 변수를 검사하는 것과 토큰이 만료되는 경우로 구성됩니다.</li>
<li>토큰이 올바르게 서명되었는지 확인하는 것은 CPU 사이클을 필요로하며 IO 또는 네트워크 액세스가 필요하지 않으며 최신 웹 서버 하드웨어에서 확장하기가 쉽습니다.</li>
</ul>
<h2 id="jwt-단점">JWT 단점</h2>
<ul>
<li>토큰은 클라이언트에 저장되어 데이터베이스에서 사용자 정보를 조작하더라도 토큰에 직접 적용할 수 없습니다.</li>
<li>더 많은 필드가 추가되면 토큰이 커질 수 있습니다.</li>
<li>상태 비저장(stateless) 애플리케이션에서 토큰은 거의 모든 요청에 대해 전송되므로 데이터 트래픽 크기에 영향을 미칠 수 있습니다.</li>
</ul>
<hr>
<p>출처 : <a href="http://www.opennaru.com/opennaru-blog/jwt-json-web-token/">http://www.opennaru.com/opennaru-blog/jwt-json-web-token/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인증(Authentication)과 권한 부여(Authorization - 인가)]]></title>
            <link>https://velog.io/@coginner_/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EA%B6%8C%ED%95%9C-%EB%B6%80%EC%97%ACAuthorization-%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@coginner_/%EC%9D%B8%EC%A6%9DAuthentication%EA%B3%BC-%EA%B6%8C%ED%95%9C-%EB%B6%80%EC%97%ACAuthorization-%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Thu, 02 Jun 2022 02:11:49 GMT</pubDate>
            <description><![CDATA[<ul>
<li>스프링 시큐리티의 동작을 이해하기 위해서는 가장 중요한 용어인 <strong><code>인증(Authentication)</code></strong>과 <strong><code>권한 부여(Authorization - 인가)</code></strong>에 대한 이해이다. </li>
</ul>
<ul>
<li><strong><code>인증(Authentication)</code></strong>은 쉽게 말해서 &#39;자신을 증명하는 것&#39;이다.<ul>
<li>다시 말해서 자기 스스로가 무언가 자신을 증명할 만한 자료를 제시하는 것이다.</li>
</ul>
</li>
<li>반면에 <strong><code>권한 부여(Authorization - 인가)</code></strong>는 권한부여남에 의해서 자격이 부여된다.</li>
</ul>
<ul>
<li>시큐리티의 개념을 어떤 회사에 방문하는 장면으로 비유하면 아래 그림과 유사하다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/ba6a9a22-86f9-49ac-8dce-d873b6bb24d7/image.jpg" alt=""></p>
<ul>
<li>엔지니어 A는 B 회사에 고장 난 데이터베이스를 고치기 위해서 방문했다. 예약을 한 상태에서 방문한 A시는 우선 회사 입구에서 <strong>&#39;본인을 인증&#39;</strong>할 것을 요구받는다. 출입증을 검사하는 직원은 A의 신분을 확인한다. 인증이란 이처럼 본인이 무엇인가를 증명하는 행위라고 보면 된다.</li>
</ul>
<ul>
<li>회사 내부에 들어간 A씨는 다시 담당자를 만나서 데이터베이스의 접근 권한 등의 정보를 얻어야 한다.<ul>
<li>이 과정을 <code>인가</code>혹은 <code>권한 부여(Authorization)</code>라고 볼 수 있다.</li>
</ul>
</li>
<li>권한 부여 과정에서 A시는 데이터베이스를 조회하거나 수정할 수 있는 권한이 부여된다.</li>
</ul>
<ul>
<li>스프링 시큐리티의 내부에도 이와 비슷한 구조를 가지고 있다. </li>
<li><strong>스프링 시큐리티에서 가장 중요한 역할을 하는 존재가 인증을 담당하는 <code>AuthenticationManager(인증 매니저)</code>라는 존재이다.</strong></li>
<li><code>AuthenticationManager</code>는 다양한 방식의 인증을 처리할 수 있도록 아래와 같은 구조로 설계되어 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/2d4087af-cadd-48cd-bdee-384aeeec5cd2/image.jpg" alt=""></p>
<ul>
<li><code>ProviderManager</code>는 인증에 대한 처리를 <code>AuthenricationProvider</code>라는 타입의 객체를 이용해서 처리를 위임한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/99e9fa46-6062-47c0-98e3-2301f4e77c70/image.jpg" alt=""></p>
<ul>
<li><code>AuthenricationProvider(인증 제공자)</code>는 실제 인증 작업을 진행한다.<ul>
<li>이때 인증된 정보에는 권한에 대한 정보를 같이 전달하게 되는데 이 처리는 <code>UserDetailsService</code>라는 존재와 관련이 있다.</li>
<li><code>UserDetailsService</code> 인터페이스 구현체는 실제로 사용자의 정보와 사용자가 가진 권한의 정보를 처리해서 반환하게 된다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/f222c768-18d9-461b-84f1-059768a0188d/image.jpg" alt=""></p>
<ul>
<li><p>개발자가 스프링 시큐리티를 커스터마이징 하는 방식은 크게 <code>AuthenricationProvider</code>를 직접 구현하는 방식과 실제 처리를 담당하는 <code>UserDetailsService</code>를 구현하는 방식으로 나누어진다.</p>
</li>
<li><p>대부분의 경우에는 <code>UserDetailsService</code>를 구현하는 형태를 사용하는 것만으로도 충분하지만, 새로운 프로토콜이나 인증 구현 방식을 직접 구현하는 경우에는 <code>AuthenticationProvider</code> 인터페이스를 직접 구현해서 사용한다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[H2 버전에 따른 SyntaxError]]></title>
            <link>https://velog.io/@coginner_/H2-%EB%B2%84%EC%A0%84%EC%97%90-%EB%94%B0%EB%A5%B8-SyntaxError</link>
            <guid>https://velog.io/@coginner_/H2-%EB%B2%84%EC%A0%84%EC%97%90-%EB%94%B0%EB%A5%B8-SyntaxError</guid>
            <pubDate>Tue, 31 May 2022 08:04:51 GMT</pubDate>
            <description><![CDATA[<p>강의를 들으면서 강의 상의 버전과 현재 버전 차이로 인해서 H2 데이터 베이스에서 Entity로 테이블을 생성하지 못하는 에러가 발생했다.</p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/b6fd0a01-8ac2-4f10-8264-b76a9717e8d5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/79c38596-c614-49aa-a201-24d4c34f5038/image.png" alt=""></p>
<p>처음에 어디서 문제인지 파악하는 과정에서 이것저것 검색도 해봤는데 H2가 버전업이 되면서 예약어 관련 문제라는 것을 봤고 어디가 문제일지 파악하는 과정에서 <strong><code>설마 User가 예약어라 에러가 나는건 아니겠지</code></strong> 하고 넘어갔는데, <strong>그 설마가 맞았다.</strong></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/74e7c9eb-8ef5-4d3b-b207-91222b8db102/image.png" alt=""></p>
<p>그래서 클래스 위에</p>
<pre><code class="language-java">@Table(name = &quot;Users&quot;)</code></pre>
<p>어노테이션을 추가하고 테이블 명을 설정한다음 실행하니까 에러가 발생하지 않았고 테이블도 생성 되었다.</p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/b442d80a-ad09-4d09-86bb-ad5de84240b9/image.png" alt=""></p>
<p><del><em>아니 이게 버전때문에 이렇게 에러가 생길줄 알았나....
그리고 강의좀 다시 찍어서 재배포좀 해주지....</em></del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[022 10개 도시를 최단거리로 여행하는 법]]></title>
            <link>https://velog.io/@coginner_/022-10%EA%B0%9C-%EB%8F%84%EC%8B%9C%EB%A5%BC-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC%EB%A1%9C-%EC%97%AC%ED%96%89%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@coginner_/022-10%EA%B0%9C-%EB%8F%84%EC%8B%9C%EB%A5%BC-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC%EB%A1%9C-%EC%97%AC%ED%96%89%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Mon, 30 May 2022 18:04:22 GMT</pubDate>
            <description><![CDATA[<h1 id="1알고리즘-복잡도complexity">1.알고리즘 <strong>&#39;복잡도(complexity)&#39;</strong></h1>
<hr>
<blockquote>
<h2 id="복잡도란">복잡도란</h2>
<ul>
<li>알고리즘의 성능을 나타내는 척도</li>
<li>크게 시간 복잡도, 공간 복잡도로 나눌 수 있다.</li>
</ul>
</blockquote>
<h2 id="1시간-복잡도">1.시간 복잡도</h2>
<ul>
<li>특정한 크기의 입력에 대해 알고리즘이 얼마나 오래 걸리는지를 의미한다.</li>
<li>알고리즘을 위해 필요한 연산의 횟수</li>
<li>복잡도를 표현하기 위해 빅오 표기법을 사용한다.</li>
<li>최악의 경우에 대한 연산 횟수가 가장 중요하다.</li>
<li>N의 범위에 따라 시간 복잡도를 계산하고 사용할 수 있는 알고리즘을 선택하는 방법도 있다.</li>
</ul>
<h3 id="-빅오-표기법-o-big-o">※ 빅오 표기법 (O, big-O)</h3>
<blockquote>
<p>빅오란 입력값이 무한대로 향할때 함수의 상한을 설명하는 수학적 표기 방법이다.</p>
</blockquote>
<ul>
<li>빅오는 점근적 실행 시간을 표기할 때 가장 널리 쓰이는 수학적 표기 방법이여, 여기서 점근적 실행 시간이란 간단하게 N이라는 입력값이 무한대로 커질때의 실행 시간의 추이를 의미한다.</li>
<li>따라서 충분히 큰 입력값에서의 알고리즘의 효율성에 따라 수행 시간이 크게 차이가 날 수 있다.</li>
</ul>
<table>
<thead>
<tr>
<th align="center">빅오 표기법</th>
<th align="center">표현</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">O(1)</td>
<td align="center">상수</td>
<td align="center">입력값에 상관없이 일정한 실행시간을 최고!의 알고리즘</td>
</tr>
<tr>
<td align="center">O(logN)</td>
<td align="center">로그</td>
<td align="center">로그는 매우 큰 입력값에서도 크게 영향을 받지 않는 편이다.</td>
</tr>
<tr>
<td align="center">O(N)</td>
<td align="center">선형</td>
<td align="center">알고리즘을 수행하는데 걸리는 시간은 입력값에 비례,  <strong>모든 입렵값을 적어도 한 번 이상은 살펴봐야 한다.</strong></td>
</tr>
<tr>
<td align="center">O(NlogN)</td>
<td align="center">로그 선형</td>
<td align="center">병합 정렬등의 대부분 효율이 좋은 알고리즘이 이에 해당, 아무리 좋은 알고리즘이라 할지라도 n log n 보다 빠를 수 없다.</td>
</tr>
<tr>
<td align="center">O(N^2)</td>
<td align="center">다항</td>
<td align="center">버블 정렬 같은 비효율저긴 정렬 알고리즘이 이에 해당 한다.</td>
</tr>
<tr>
<td align="center">O(2^N)</td>
<td align="center">지수</td>
<td align="center">피보나치의 수를 재귀로 계산하는 알고리즘이 이에 해당 한다. n^2와 혼동되는 경우가 있는데 2^n이 훨씬 더 크다.</td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/coginner_/post/9d861bb2-2a60-4e52-acd1-34cec1cabbdf/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/87d1137d-4ac6-4717-bb6d-27797151dee1/image.png" alt=""></p>
<h2 id="2공간-복잡도">2.공간 복잡도</h2>
<ul>
<li>특정한 크기의 입력에 대해 알고리즘이 얼마나 많은 메모리를 차지하는지를 의미한다.</li>
<li>알고리즘을 위해 필요한 메모리의 양</li>
</ul>
<p><br><br></p>
<h1 id="2-p-vs-np">2. P vs NP</h1>
<hr>
<h2 id="1다항-시간-알고리즘polynomial-time-algorithms">1.다항 시간 알고리즘(Polynomial-Time Algorithms)</h2>
<ul>
<li><p>다항 시간(합리적인 시간)안에 풀 수 있는 문제.</p>
</li>
<li><p>모든 문제가 다항 시간안에 해결되지 않는다.</p>
<ul>
<li>Ex) 튜링의 <code>&quot;Halting Problem(정지 문제)&quot;</code> : 정지 문제란 </li>
</ul>
<blockquote>
<p>프로그램을 설명한 것과 처음 입력값이 주어졌을 때, 이 프로그램에 입력값을 넣고 실행한다면 이 프로그램이 계산을 끝내고 멈출지 아니면 영원히 계속 계산할지 판정하라.</p>
</blockquote>
<ul>
<li>1936년 앨런 튜링이 모든 가능한 입력값에 대해 정지 문제를 풀 수 있는 일반적인 알고리즘은 존재하지 않는다는 것을 증명했다.</li>
</ul>
</li>
</ul>
<h2 id="2클래스-p">2.클래스 P</h2>
<ul>
<li>다항 시간내에 해결되는 알고리즘을 가지고 있는 <strong>결정(decision) 문제의 클래스</strong> <ul>
<li><strong>어떤 상수 k에 대해 O(N^K) 시간에 풀 수 있는 문제</strong></li>
</ul>
</li>
<li>O(P(N)) - 이때 P(N)은 N상의 다항시간</li>
<li><strong>항상 올바른 답을 계산</strong>하는 방법</li>
<li>다항시간내에 해결되지 않으면 비효율적</li>
</ul>
<h2 id="3클래스-np">3.클래스 NP</h2>
<ul>
<li><strong>&#39;비결정적인 다항시간&#39; 상에 존재(stand)</strong></li>
<li>주로 <strong>&quot;추측&quot; or &quot;평행선화(parallelize)&quot;방식으로 계산</strong></li>
<li>다항 시간에 &quot;확인할 수 있는&quot; 문제로 구성<ul>
<li>해의 &quot;후보&quot;가 주어지면 문제 입력 크기에 대한 다항 시간에 그 후보가 올바른 해인지 확인할 수 있음을 의미</li>
</ul>
</li>
<li>이 방식의 문제점은 &quot;속도(quickly)&quot;</li>
</ul>
<blockquote>
<ul>
<li>4.P ⊆ NP (아직 증명X)</li>
<li>NP-complete(완비) 문제는 NP에서 가장 어려운 문제이다.</li>
<li>대부분의 전문적인 문제는 P or NP-complete 문제이다.</li>
<li>NP-complete 문제 : P로 해결 가능하지만 NP로 해결되지 않는 문제(미제문제)</li>
</ul>
</blockquote>
<p><br><br></p>
<h1 id="3여행하는-외판원-문제traveling-salesman-problem">3.여행하는 외판원 문제(Traveling-Salesman-Problem)</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/936fe452-feb4-484a-94eb-d17b668695c7/image.png" alt=""></p>
<h2 id="1여행하는-외판원-문제tsp">1.여행하는 외판원 문제(TSP)</h2>
<blockquote>
<p>외판원 문제 또는 순회 외판원 문제는 초합 최적화 문제의 일종이다. 이 문제는 NP-난해에 속하며, 흔히 <code>계산 복잡도 이론</code>에서 해를 구하기 어려운 문제의 대표적인 예로 많이 다룬다.</p>
</blockquote>
<ul>
<li>외판원은 자신이 사는 도시에서 출발해서 어떤 순서로든 다른 도시를 모두 방문하고 나서 다시 출발점으로 돌아와야 한다.<ul>
<li>여기서 목표는 각 도시를 정확히 한 번씩(반복 없이) 방문하고,</li>
<li>전체 여행한 거리를 최소로 만드는 것이다.
⇒ 그래프 이론의 용어로 엄밀하게 정의한다면, <code>&quot;각 변에 가중치가 주어진 완전 그래프(weighted complete graph)에서 가장 작은 가중치를 가지는 해밀턴 순회를 구하라&quot;</code> 라고 표현할 수 있고, 반드시 시작점으로 돌아와야 한다는 제약 조건을 없애도 계산 복잡도는 변하지 않는다.</li>
</ul>
</li>
</ul>
<ul>
<li>외판원 순회 알고리즘은 무식하게 풀 수 있다. 무조건 0번 도시에서 출발한다고 가정해도 경로의 길이는 다르지 않다.</li>
<li>그러면 남은 도시들을 어떤 순서로 방문할지를 정하기만 하면 된다.</li>
<li><strong>남은 n-1개의 도시를 나열하는 방법으로는 <code>(n-1)!</code>가지</strong>가 있다.</li>
<li>그래서 재귀 호출을 통해 쉽게 외판원 순회 알고리즘을 설계할 수 있다.</li>
<li>그러나 보통 n!의 풀이는 사용하지 않는다. 12!만 해도 479,001,600라는 엄청난 수를 지니기 때문이다.</li>
</ul>
<h2 id="2외판원-순회-알고리즘을-더-빠르고-효율적으로-구하는-방법은">2.외판원 순회 알고리즘을 더 빠르고 효율적으로 구하는 방법은?</h2>
<ul>
<li>모든 정점을 한 번씩 방문하는(출발 정점 제외) 최단 순환 경로를 탐색하는데 <strong>최적의 효율로 탐색</strong>하기 위해서 사용한다.</li>
</ul>
<h3 id="dp-메모제이션">DP 메모제이션</h3>
<ul>
<li><code>(n-1)!</code>의 모든 경로를 조사하지 않고 중복된 경로를 제거하는 <strong>dp 메모제이션 기법을 사용하면 된다.</strong><ul>
<li>동일한 하위 문제의 반복을 막아줌으로써 더 높은 효율로 연산이 이루어지게 해준다. 중복되는 경로의 조사를 제거해주는 것이다.</li>
</ul>
</li>
</ul>
<ul>
<li>예를 들어, 피보나치 함수는 dp 메모제이션 기법을 통해 O(2^n)의 복잡도를 O(N)까지 줄여준다. **그렇다고 무조건 dp 메모제이션을 적용하면 각 문제의 성질이 다르기 때문에 O(n)으로 줄어든다는 뜻은 아니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/89112966-0940-4fa0-b935-71aa423fdee2/image.png" alt=""></p>
<h3 id="비트마스킹">비트마스킹</h3>
<ul>
<li>비트마스킹을 사용하면 bit연산이기 때문에 다른 자료구조(boolean배열)을 사용하는 것보다 훨씬 빠르게 동작되고 코드도 간결해진다.</li>
<li><strong>가장 큰 장점은 N이 16개인 경우 2^16가지의 경우를 16bit로 표현이 가능하다.</strong></li>
</ul>
<p>⇒ 정리하면 TSP(외판원 순회)는 최단 순환 경로를 탐색해야하는데 <strong>1) N! 의 중복 경로를 제거해주는 DP 메모제이션 기법을 사용</strong>한다. 그래도 2^N의 모든 경우의 수를 표현해야 하기 때문에 그만큼의 공간복잡도가 필요하다. <strong>2) 메모리 사용량도 줄이고 성능 향상을 위해서 2^N의 경우의 수를 Nbit로 표현할 수 있는 비트마스킹으로 사용</strong>한다.</p>
<p>⇒ 올라가야 할 계단의 수를 100 개에서 1개로 줄여주는 설계 방법 이라고 보면 된다.</p>
<h3 id="그렇다면-왜-한-정점만-탐색해도-될까">그렇다면 왜 한 정점만 탐색해도 될까?</h3>
<ul>
<li>DP 메모제이션 기법으로 엄청나게 시간을 단축 할 수 있는 것은 그만큼 중복되는 경로가 많기 때문이다.</li>
<li><strong>이 순회 경로는 싸이클로 n개의 정점 중 어느 정점에서 탐색을 시작해도 결과는 똑같다</strong>는 것을 알아야 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/0e6c2566-85c2-4bc0-b2eb-a4690f7118cb/image.png" alt=""></p>
<ul>
<li>어차피 최적 경로 싸이클은 어디서 시작해도 똑같이 나오기 때문에 한 정점에서만 탐색해줘도 된다.<blockquote>
<ul>
<li>1번에서 출발 :  1 → 2 → 5 → 3 → 4 → 1</li>
<li>2번에서 출발 : 2 → 5 → 3 → 4 → 1 → 2</li>
<li>3번에서 출발 : 3 → 4 → 1 → 2 → 5 → 3</li>
</ul>
</blockquote>
</li>
</ul>
<hr>
<h1 id="알고리즘-참고-영상강추-">알고리즘 참고 영상(강추) :</h1>
<p><a href="https://www.youtube.com/watch?v=EdIKIf9mHk0&amp;list=PLOmdoKois7_FK-ySGwHBkltzB11snW7KQ">[youtube] hungarian dance - sorting algorithms</a></p>
<h1 id="참고-링크-">참고 링크 :</h1>
<p><a href="https://thkim-study.tistory.com/29">[알고리즘] 복잡도란 무엇인가</a>
<a href="https://codermun-log.tistory.com/235">빅오 표기법 (O, big-O)</a>
<a href="https://ko.wikipedia.org/wiki/%EC%A0%95%EC%A7%80_%EB%AC%B8%EC%A0%9C">정지 문제</a>
<a href="https://chayan-memorias.tistory.com/201">P와 NP</a>
<a href="https://loosie.tistory.com/272">여행하는 외판원 문제(TSP)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹의 인증 및 인가]]></title>
            <link>https://velog.io/@coginner_/%EC%9B%B9%EC%9D%98-%EC%9D%B8%EC%A6%9D-%EB%B0%8F-%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@coginner_/%EC%9B%B9%EC%9D%98-%EC%9D%B8%EC%A6%9D-%EB%B0%8F-%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Mon, 30 May 2022 10:04:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>💡 인증과 인가는 한글로 보나 영어 (Authentication vs. Authorization) 로 보나 비슷해 보일 뿐 아니라 실제 많이 혼동되어 사용되고 있지만 명확히 다른 의미를 가지고 있습니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/coginner_/post/2c4a8b07-94fe-41d2-a079-b7a9938dd14b/image.png" alt=""></p>
<p>출처: <a href="https://aboutssl.org/authentication-vs-authorization/">https://aboutssl.org/authentication-vs-authorization/</a></p>
<h3 id="인증authentication--사용자-신원을-확인하는-행위">인증(Authentication) : 사용자 신원을 확인하는 행위</h3>
<h3 id="인가authorization--사용자-권한을-확인하는-행위">인가(Authorization) : 사용자 권한을 확인하는 행위</h3>
<h3 id="예를-들면">예를 들면,</h3>
<ul>
<li>인증: 회사 출입을 위한 출입증 확인 혹은 생체정보 (지문, 홍채) 인식</li>
<li>인가: 회사 건물 내 접근 권한 관리<ol>
<li>방문자 → 회의실만 접근 가능</li>
<li>직원 → 회의실, 사무실 접근 가능</li>
<li>관리자 → 회의실, 사무실, 서버실, 물품보관실 접근 가능</li>
</ol>
</li>
</ul>
<h3 id="웹에서의-인증-및-인가">웹에서의 인증 및 인가</h3>
<ul>
<li><p>인증: 로그인을 통해 본인임을 확인 (주로, 아이디와 패스워드 이용)</p>
</li>
<li><p>인가: 주로 역할에 따른 사용 권한 관리</p>
<p>  예) 웹 카페 사이트에서 회원 랭킹 별 가능한 첨부파일 크기를 다르게 부여</p>
<p>  <img src="https://velog.velcdn.com/images/coginner_/post/0a71fca1-0259-4abf-af92-8386c7ad65a7/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링의 주요 특징]]></title>
            <link>https://velog.io/@coginner_/%EC%8A%A4%ED%94%84%EB%A7%81%EC%9D%98-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</link>
            <guid>https://velog.io/@coginner_/%EC%8A%A4%ED%94%84%EB%A7%81%EC%9D%98-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</guid>
            <pubDate>Fri, 27 May 2022 08:01:29 GMT</pubDate>
            <description><![CDATA[<h1 id="스프링의-주요-특징">스프링의 주요 특징</h1>
<blockquote>
<ul>
<li>POJO 기반의 구성</li>
<li>의존성 주입(DI)을 통한 객체 간의 관계 구성</li>
<li>AOP(Aspect-Oriented-Programming) 지원</li>
<li>편리한 MVC 구조</li>
<li>WAS의 종속적이지 않은 개발 환경</li>
</ul>
</blockquote>
<hr>
<h2 id="1pojo-기반의-구성">1.POJO 기반의 구성</h2>
<ul>
<li>스프링의 성격 자체가 가벼운(light-weight) 프레임워크지만, 그 내부에는 객체 간의 관계를 구성할 수 있는 특징을 가지고 있다. </li>
<li>스프링은 다른 프레임워크들과 달리 이 관계를 구성할 때 별도의 API 등을 사용하지 않는 <code>POJO(Plain Old Java Object)</code>의 구성 만으로 가능하도록 제작되어 있다. 쉽게 말해서 일반적인 <strong>Java 코드를 이용해서 객체를 구성하는 방식을 그대로 스프링에서 사용할 수 있다.</strong></li>
</ul>
<ul>
<li>이것이 중요한 이유는 코드를 개발할 때 개발자가 <strong>특정한 라이브러리나 컨테이너의 기술에 종속적이지 않다</strong>는 것을 의미하기 때문이다.</li>
<li>개발자는 가장 일반적인 형태로 코드를 작성하고 실행할 수 있기 때문에 <strong>생산성에서도 유리하고 코드에 대한 테스트 작업 역시 좀 더 유연하게 할 수 있다</strong>는 장점이 생긴다.</li>
</ul>
<hr>
<h2 id="2의존성-주입di과-스프링">2.의존성 주입(DI)과 스프링</h2>
<ul>
<li>스프링에 대한 얘기를 하면서 빠지지 않는 개념이 <code>&#39;의존성 주입&#39;</code>이라는 개념이다.</li>
</ul>
<ul>
<li><code>의존성(Dependency)</code>이라는 것은 <strong>하나의 객체가 다른 객체 없이 제대로 된 역할을 할 수 없다</strong>는 것을 의미한다.</li>
<li><code>의존성</code>은 <strong>하나의 객체가 다른 객체의 상태에 따라 영향을 받는 것</strong>을 의미한다. 흔히 A 객체가 B 객체 없이 동작이 불가능한 상황을 &#39;A가 B에 의존적이다&#39;라고 표현한다.</li>
</ul>
<ul>
<li><code>주입(Injection)</code>은 말 그대로 외부에서 &#39;밀어 넣는 것&#39;을 의미한다.</li>
<li><strong>필요한 객체를 얻는 방식에 따라서 주체가 능동적인지 수동적인지에 대한 차이</strong>가 있다.</li>
</ul>
<ul>
<li>의존성과 주입을 결합해서 생각해 보면 &#39;어떤 객체가 필요한 객체를 외부에서 밀어 넣는다&#39;는 의미가 된다.</li>
<li>그렇다면 &#39;왜 외부에서 객체를 주입하는 방식&#39;을 사용하는지 알아볼 필요가 있다.</li>
</ul>
<ul>
<li>예를 들어 음식점에서 직접 식재료를 사지 않고, 대행업체에서 배송해 주는 것을 사용하는 경우에 얻는 장점이 무엇인가에 대해서 고민해보면 역시 &#39;편리하다&#39;, &#39;장사에만 집중할 수 있다&#39;와 같은 장점들을 생각해 볼 수 있다.</li>
<li>이것을 코드에 대입해서 살펴보면 &#39;주입을 받는 입장에서는 어떤 객체인지 신경 쓸 필요가 없다&#39;, &#39;어떤 객체에 의존하든 자신의 역할은 변하지 않는다&#39;를 그림으로 표현하면 다음과 같은 형태가 될 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/2645f71c-d051-4b8c-9189-f44373c01558/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/c0a3abe7-a851-4e09-868e-ba847e3f6c0f/image.png" alt=""></p>
<ul>
<li><code>&#39;의존성 주입&#39;</code> 방식을 사용하려면 두번째 그림의 오른쪽 도형처럼 추가적인 하나의 존재가 필요하게 된다. 이 존재는 의존성이 필요한 객체에 필요한 객체를 찾아서 <code>&#39;주입&#39;</code>하는 역할을 하게 된다.</li>
</ul>
<ul>
<li>스프링은 이러한 구조를 만드는 데 적합한 구조로 설계되어 있다. </li>
<li>스프링에서는 <code>&#39;ApplicationContext&#39;</code>라는 존재가 필요한 객체들을 생성하고, 필요한 객체들을 주입하는 역할을 해 주는 구조이다.</li>
<li><strong>따라서</strong> 스프링을 이용하면 개발자들은 기존의 프로그래밍과 달리 객체와 객체를 분리해서 생성하고, 이러한 객체들을 엮는(wiring) 작업을 하는 형태의 개발을 하게 된다.</li>
</ul>
<ul>
<li>스프링에서는 <code>ApplicationContext</code>가 관리하는 객체들을 <code>&#39;빈(Bean)&#39;</code>이라는 용어로 부르고, 빈과 빈 사이의 의존관계를 처리하는 방식으로 XML 설정, 어노테이션 설정, Java 설정 방식을 이용할 수 있다.</li>
</ul>
<hr>
<h2 id="3aop의-지원">3.AOP의 지원</h2>
<ul>
<li>좋은 개발환경의 중요 원칙은 <strong>&#39;개발자가 비즈니스 로직에만 집중할 수 있게 한다.&#39;</strong>이다.</li>
</ul>
<ul>
<li>이 목표를 이루기 위해 몇 가지 중요 원칙이 있지만, 가장 쉽게 생각할 수 있는 것이 <code>&#39;반복적인 코드의 제거&#39;</code>라고 할 수 있다.</li>
<li>스프링은 프레임워크를 이용한 개발에도 이러한 반복적인 코드를 줄이고, 비즈니스 로직에만 집중할 수 있는 방법을 제공한다.</li>
</ul>
<ul>
<li>대부분의 시스템이 공통으로 가지고 있는 보안이나 로그, 트랜잭션과 같이 비즈니스 로직은 아니지만, <strong>반드시 처리가 필요한 부분</strong>을 스프링에서는 <code>&#39;횡단 관심사(cross-concern)&#39;</code>라고 한다.</li>
<li>스프링은 이러한 횡단 관심사를 분리해서 제작하는 것이 가능한데, <code>AOP(Aspect Oriented Programming)</code>는 <strong>관점지향 프로그래밍</strong>이라고도 불리며 이러한 횡단 관심사를 모듈로 분리하는 프로그래밍의 패러다임이다.</li>
<li>관점 지향은 쉽게 말해 <code>어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것</code>이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/58219993-c7fb-4e06-835b-2c4e56a34bc4/image.png" alt=""></p>
<ul>
<li>스프링은 <code>AOP</code>를 <code>AspectJ</code>의 문법을 통해서 작성할 수 있는데, 이를 통해서 개발자는<blockquote>
<p>1) 핵심 비즈니스 로직에만 집중해서 코드를 개발할 수 있게 되었고,</p>
<p>2) 각 프로젝트마다 다른 관심사를 정용할 때 코드의 수정을 최소화시킬 수 있었으며</p>
<p>3) 원하는 관심사의 유지 보수가 수월한 코드를 구성할 수 있다.</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="4트랜잭션의-지원">4.트랜잭션의 지원</h2>
<ul>
<li>데이터베이스를 이용할 때 반드시 신경 써야 하는 부분은 하나의 업무가 여러 작업으로 이루어지는 경우의 트랜잭션 처리이다.</li>
<li>이 트랜잭션 처리는 상황에 따라서 복잡하게 구성될 수도 있고, 아닐 수도 있는데, 그때마다 코드를 이용해서 처리하는 작업은 개발자에게는 상당히 피곤한 일이다.</li>
<li>스프링은 이런 트랜잭션의 관리를 <code>어노테이션(@)</code>이나 <code>XML</code>로 설정할 수 있기 때문에 개발자가 매번 상황에 맞는 코드를 작성할 필요가 없도록 설계되었다.</li>
</ul>
<hr>
<h3 id="출처">출처:</h3>
<p><a href="https://engkimbs.tistory.com/746">https://engkimbs.tistory.com/746</a> [새로비:티스토리]
코드로 배우는 스프링 웹프로젝트 / 구멍가게 코딩단</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[예외 처리]]></title>
            <link>https://velog.io/@coginner_/%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@coginner_/%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Thu, 26 May 2022 11:23:05 GMT</pubDate>
            <description><![CDATA[<h1 id="1예외처리">1.예외처리</h1>
<h2 id="11-jpa-표준-예외-정리">1.1 JPA 표준 예외 정리</h2>
<ul>
<li><p>JPA 표준 예외들은 <code>javax.persistence.PersistenceException</code>의 자식 클래스다. 그리고 이 예외 클래스는 <code>RuntimeException</code>의 자식이다. 따라서 JPA 예외는 모두 언체크 예외다.</p>
</li>
<li><p>JPA 표준 예외는 크게 2가지로 나눌 수 있다.</p>
<blockquote>
<ul>
<li>트랜잭션 록백을 표시하는 예외</li>
<li>트랜잭션 롤백을 표시하지 않는 예외</li>
</ul>
</blockquote>
</li>
<li><p><strong>트랜잭션 롤백을 표시하는 예외</strong>는 심각한 예외이므로 복구해선 안된다. 이 예외가 발생하면 트랜잭션을 강제로 커밋해도 트랜잭션이 커밋되지 않고 대신에 <code>javax.persistence.RollbackException</code> 예외가 발생한다. 반면에 <strong>트랜잭션 롤백을 표시하지 않는 예외</strong>는 심각한 예외가 아니다. 따라서 개발자가 트랜잭션을 커밋할지 롤백할지를 판단하면 된다.</p>
</li>
</ul>
<br>

<h4 id="트랜잭션-롤백을-표시하는-예외">트랜잭션 롤백을 표시하는 예외</h4>
<p><img src="https://velog.velcdn.com/images/coginner_/post/8f5a5a55-04ff-427c-86b9-bb40eedee77c/image.png" alt=""></p>
<br>

<h4 id="트랜잭션-롤백을-표시하지-않는-예외">트랜잭션 롤백을 표시하지 않는 예외</h4>
<p><img src="https://velog.velcdn.com/images/coginner_/post/88bed2e0-ebc8-4aa9-9cee-7bee1ac0c5da/image.png" alt=""></p>
<hr>
<br>

<h2 id="12-스프링-프레임워크의-jpa-예외-변환">1.2 스프링 프레임워크의 JPA 예외 변환</h2>
<ul>
<li>서비스 계층에서 데이터 접근 계층의 구현 기술에 직접 의존하는 것은 좋은 설계라 할 수 없다. 이것은 예외도 마찬가지인데, 예를 들어 서비스 계층에서 JPA의 예외를 직접 사용하려면 JPA에 의존하게 된다. 스프링 프레임워크는 이런 문제를 해결하려고 <strong>데이터 접근 계층에 대한 예외를 추상화</strong>해서 개발자에게 제공한다. </li>
</ul>
<h4 id="jpa-예외를-스프링-예외로-변경">JPA 예외를 스프링 예외로 변경</h4>
<p><img src="https://velog.velcdn.com/images/coginner_/post/d5c3bbe1-eb57-4877-aef6-6bcf1457e5b7/image.png" alt=""></p>
<ul>
<li>추가로 표 15.4를 보면 JPA 표준 명세상 밸상할 수 있는 다음 두 예외도 추상화 해서 제공한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/09e24c03-fc93-4a6f-a356-32155ae9eb11/image.png" alt=""></p>
<hr>
<br>

<h2 id="13-스프링-프레임워크에-jpa-예외-변환가-적용">1.3 스프링 프레임워크에 JPA 예외 변환가 적용</h2>
<ul>
<li><p>JPA 예외를 스프링 프레임워크가 제공하는 추상화된 예외로 변경하려면 <code>PersistenceExceptionTranslationPostProcessor</code>를 스프링 빈으로 등록하면 된다.</p>
</li>
<li><p>이것은 <code>@Repository</code> 어노테이션을 사용한 곳에 예외 변환 AOP를 적용해서 JPA 예외를 스프링 프레임워크가 추상화한 예외로 변환해준다. 설정 방법은 다음과 같다.</p>
</li>
</ul>
<pre><code class="language-java">&lt;bean class=&quot;org.springframework.dao.annotation, PersistenceExceptionTranslationPostProcessor&quot;/&gt;</code></pre>
<ul>
<li>JavaConfig를 사용하면 다음처럼 등록한다.</li>
</ul>
<pre><code class="language-java">@Bean
public PersistenceExceptionTranslationPostProcessor
    exceptionTranslation() {
    return new PersistenceExceptionTranslationPostProcessor();
}</code></pre>
<p><img src="https://velog.velcdn.com/images/coginner_/post/94d8f97f-a911-430f-a314-55fad51f918e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/3708af96-4f97-400a-9073-5c9d86a97d1b/image.png" alt=""></p>
<ul>
<li><p>findMember() 메소드는 엔티티를 조회하려고 getSingleResult() 메소드를 사용했다. 이 메소드는 조회된 결과가 없으면 <code>javax.persistence.NoResultException</code>이 발생한다. 이 예외가 <code>findMember()</code> 메소드를 빠져 나갈 때 <code>PersistenceExceptionTranslationPostProcessor</code>에서 등록한 AOP 인터셉터가 동작해서 해당 예외를 <code>org.springframework.dao.EmptyResultDataAccessException</code> 예외로 변환해서 반환한다. 따라서 이 메소드를 호출한 클라이언트는 스프링 프레임워크가 추상화한 예외를 받는다.</p>
</li>
<li><p>만약 예외를 변환하지 않고 그대로 반환하고 싶으면 다음처럼 throws 절에 그대로 반환할 JPA 예외나 JPA 예외의 부모 클래스를 직접 명시하면 된다. 예를 들어 예제 15.2와 같이 예외를 명시하면 해당 예외를 그대로 반환한다. 참고로 <code>java.lang.Exception</code>를 선언하면 모든 예외의 부모이므로 예외를 변환하지 않는다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/358178bc-8eb7-4be0-a1ca-34b3830ad59e/image.png" alt=""></p>
<h2 id="14트랜잭션-롤백-시-주의사항">1.4트랜잭션 롤백 시 주의사항</h2>
<ul>
<li><p>트랜잭션을 롤백하는 것은 데이터베이스의 반영사항만 롤백하는 것이지 수정한 자바 객체까지 원상태로 복구해주지는 않는다. 예를 들어 엔티티를 조회해서 수정하는 중에 문제가 있어서 트랜잭션을 롤백하면 데이터베이스의 데이터는 원래대로 복구되지만 객체는 수정된 상태로 영속성 컨텍스트에 남아 있다. 따라서 트랜잭션이 롤백된 영속성 컨텍스트를 그대로 사용하는 것은 위험하다. 새로운 영속성 컨텍스트를 생성해서 사용하거나 <code>EntityManager.clear()</code>를 호출해서 영속성 컨텍스트를 초기화한 다음에 사용해야 한다.</p>
</li>
<li><p>스프링 프레임워크는 이런 문제를 예방하기 위해 영속성 컨텍스트의 범위에 따라 다른 방법을 사용한다.</p>
</li>
<li><p>기본 전략인 트랜잭션당 영속성 컨텍스트 전략은 문제가 발생하면 트랜잭션 AOP 종료 시점에 트랜잭션을 롤백하면서 영속성 컨텍스트도 함께 종료하므로 문제가 발생하지 않는다.</p>
</li>
<li><p>문제는 OSIV처럼 영속성 컨텍스트의 범위를 트랜잭션 범위보다 넓게 사용해서 여러 트랜잭션이 하나의 영속성 컨텍스트를 사용할 때 발생한다. 이때는 트랜잭션을 롤백해서 영속성 컨텍스트에 이상이 발생해도 다른 트랜잭션에서 해당 영속성 컨텍스트를 그대로 사용하는 문제가 있다. 스프링 프레임워크는 영속성 컨텍스트의 범위를 트랜잭션의 범위보다 넓게 설정하면 트랜잭션 롤백시 영속성 컨텍스느를 초기화(EntityManager.clear())해서 잘못된 영속성 컨텍스트를 사용하는 문제를 예방한다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/54b2ed58-6dd4-443a-9d08-85c9b7513b91/image.png" alt=""></p>
<h4 id="출처---자바-orm-표준-jpa-프로그래밍-저자-김영한">출처 - 자바 ORM 표준 JPA 프로그래밍. 저자 김영한</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[restAPI의 put 과 patch]]></title>
            <link>https://velog.io/@coginner_/restAPI%EC%9D%98-put-%EA%B3%BC-patch</link>
            <guid>https://velog.io/@coginner_/restAPI%EC%9D%98-put-%EA%B3%BC-patch</guid>
            <pubDate>Thu, 26 May 2022 06:42:32 GMT</pubDate>
            <description><![CDATA[<h4 id="출처--httpstecobletechcoursecokrpost2020-08-17-put-vs-patch">출처 : <a href="https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/">https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/</a></h4>
<hr>
<h1 id="들어가며">들어가며</h1>
<blockquote>
<p>Http Method 중 특히 <strong>자원(Entity)를 수정하는 용도</strong>로 사용하는 <strong>&quot;Put&quot;</strong>과 <strong>&quot;Patch&quot;</strong></p>
</blockquote>
<ul>
<li><p>웹 API를 설계할 때, 최대한 Http 표준을 따라서 용도에 맞는 Http Method를 사용해야 한다는 것은 아마 많은 개발자들이 인지하고 있을 것이다.</p>
</li>
<li><p>개발자들 중에는 Put과 Patch의 차이를 크게 생각하지 않고 아무거나 선택하거나 혼용하여 API를 만드는 사람도 있다.</p>
</li>
<li><p>정말로 두 메서드를 구별없이 사용해도 괜찮은 걸까!?</p>
</li>
<li><p>여기 지하철 노선 정보를 수정하는 자바스크립트 코드가 있다.</p>
</li>
</ul>
<blockquote>
<p>지하철 노선(Line)은 이름(name), 첫 차 시간(startTime), 마지막 차 시간(endTime), 배차간격(intervalTime)을 상태로 갖는다.</p>
</blockquote>
<pre><code class="language-java">const updateSubwayLine = () =&gt; {
  // 수정할 노선 정보
  const updatedSubwayLine = {
    name: $subwayLineNameInput.value,  // 노선이름
    startTime: $subwayLineStartTime.value,  // 첫 차 시간
    endTime: $subwayLineEndTime.value,  // 마지막 차 시간
    intervalTime: $subwayIntervalTime.value  // 배차간격
  }

  // 노선 정보를 수정하는 API 호출
  request(`/lines/${$activeSubwayLineItem.dataset.id}`, {
    method: &#39;PUT&#39;,
    headers: {
      &#39;Content-Type&#39;: &#39;application/json&#39;
    },
    body: JSON.stringify({
      ...updatedSubwayLine
    })
  })
  .then(() =&gt; {
    subwayLineModal.toggle()
    $activeSubwayLineItem.querySelector(&#39;.line-name&#39;).innerText = updatedSubwayLine.name
  })
  .catch(error =&gt; alert(ERROR_MESSAGE.COMMON))
}</code></pre>
<ul>
<li><p>이 updateSubwayLine 함수가 실행되면 ‘Put’ 메서드로 노선 정보를 수정하는 API가 호출되고, 요청으로 전달된 데이터에 따라 데이터베이스에 저장된 노선의 정보가 변경될 것이다.</p>
</li>
<li><p>그렇다면 위의 함수에서 ‘Put’을 ‘Patch’로 바꾼다면 어떨까? Put으로 요청을 보냈을 때와 같은 변경이 이루어질까?</p>
</li>
</ul>
<h4 id="그렇다">그렇다!</h4>
<ul>
<li><p>‘Put’과 ‘Patch’가 같은 결과를 도출하기 때문에 둘 다 자원을 “수정하는 역할”을 한다고 말할 수 있을 것이다. 하지만 이 코드에는 두 메서드가 같은 결과를 보여주게 하는 함정이 숨어있다.</p>
</li>
<li><p>실제로 ‘Put’과 ‘Patch’는 서로 대체재 관계가 아니다. 둘은 애초에 엄연히 다른 정의와 규약을 가지고 있고, 실제 사용할 때도 멱등성과 관련한 차이를 보이기 때문이다.</p>
</li>
<li><p>그렇다면 Put과 Patch 정의와 각각을 사용한 예시 코드를 통해 차이를 한번 이해해보자. 그리고 위에서 말한 함정이 무엇이었는지도 함께 알아보자.</p>
</li>
</ul>
<hr>
<h1 id="http-method---put">HTTP Method - PUT</h1>
<blockquote>
<p>The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.</p>
</blockquote>
<ul>
<li>RFC 문서에 따르면 PUT 메서드는 요청한 URI에 payload(ex. Request Body)에 있는 자원으로 대체(replace)하는 메서드이다. 여기서 대체하는 메서드라는 것은 대상을 저장하기도, 변경한다는 것을 의미한다.결국 PUT 메서드는 상황에 따라 다르게 동작하게 되는데 이를 두 가지 경우로 나누어 살펴보도록 하자.</li>
</ul>
<h3 id="요청한-uri-아래에-자원이-존재하지-않는-경우">요청한 URI 아래에 자원이 존재하지 않는 경우</h3>
<ul>
<li>자원이 존재하지 않는 경우는 단순하다. POST와 마찬가지로 새로운 자원으로써 저장하고 클라이언트에게 Http Status Code를 <code>201(Created)</code> 응답을 보내주면 된다.</li>
</ul>
<h3 id="요청한-uri-아래에-자원이-존재하는-경우">요청한 URI 아래에 자원이 존재하는 경우</h3>
<ul>
<li>payload에 담긴 정보를 이용해서 새로운 자원을 만들어 기존에 존재하던 자원을 대체한다.그리고 해당 요청이 잘 적용되었다는 것을 클라이언트에게 <code>200(ok)</code> 혹은 <code>204(no content)</code>를 이용해서 알려주면 된다.</li>
</ul>
<h2 id="put을-사용하는-코드">PUT을 사용하는 코드</h2>
<ul>
<li>PUT의 정의를 가장 잘 설명하는 예시가 주변에서 흔히 볼 수 있는 “좋아요”와 “싫어요”(혹은 추천/비추천) 기능이라고 생각한다. 좋아요와 싫어요 정보를 갖고 있는 Like 엔티티가 다음과 같이 구성되어있다.</li>
</ul>
<pre><code class="language-java">@Entity
public class Like {

  @Id
  private Long id;

  private Long articleId;

  private Long userId;

  private LikeType likeType;   //** liked or disliked

  ...
}</code></pre>
<ul>
<li><p>Like 엔티티는 articleId(어떤 게시물에 대한건지), userId(누가 좋아요를 한건지), 그리고 type(좋아요/싫어요)를 상태로 가지고 있다.</p>
</li>
<li><p>클라이언트에서 액션을 받을 때에도 이 세 정보가 모두 필요하다. 유저가 처음으로 좋아요(혹은 싫어요)를 눌렀다면, 생성이 되어야할 것이고, 기존에 누른적이 있다면 다른 타입으로 토글(수정)되거나, 취소가 되어야 한다.</p>
</li>
<li><p>이런 경우는 다음과 같이 PUT Method를 이용해서 Like 자원의 온전한 생성과, 수정을 표현할 수 있다.</p>
</li>
</ul>
<pre><code class="language-java">// LikeController.java
...
@PutMapping  //** PUT Method
public ResponseEntity&lt;Void&gt; updateLike(
    @RequestParam Long articleId,
    @LoginUser User user,
    @RequestBody LikeRequest request  //** LikeType
) {
    articleService.update(articleId, user.getId(), request.getLikeType());
    return ResponseEntity.noContent().build();
}
...

// LikeService.java
...
@Transactional
public void update(Long articleId, Long userId, LikeType likeType) {
    Like like = likeRepository.findByArticleIdAndUserId(articleId, userId)
      .map(l -&gt; l.setType(likeType))
      .orElse(new Like(articleId, userId, likeType));

    likeRepository.save(like);
}</code></pre>
<ul>
<li>LikeService에서 payload로 전달받은, articleId와 userId를 사용해서 식별가능한 데이터가 있는지 확인한 후 있으면, body에 있는 새로운 type으로 수정한다. 만약 식별가능한 데이터가 없다면, payload에 있는 데이터들로 새로운 엔티티를 만들어 데이터베이스에 저장하게된다. 이렇게하면 PUT 메서드 정의와 규약을 지키면서도 도메인 요구사항에 맞는 API를 만들 수 있다.</li>
</ul>
<h1 id="http-method---patch">HTTP Method - PATCH</h1>
<blockquote>
<p>This specification defines the new HTTP/1.1 [RFC2616] method, PATCH, which is used to apply partial modifications to a resource.</p>
</blockquote>
<ul>
<li>RFC 문서에 따르면 PATCH 요청은 자원에 대한 부분적인 수정을 적용하기 위한 HTTP 메서드이다.</li>
</ul>
<h3 id="주의점">주의점</h3>
<h4 id="put-메서드를-사용하는-클라이언트는-해당-자원의-상태를-모두-알고-있다고-가정되어야-한다">PUT 메서드를 사용하는 클라이언트는 해당 자원의 상태를 모두 알고 있다고 가정되어야 한다.</h4>
<ul>
<li><p>PUT 메서드는 요청 경로에 자원이 존재하는 경우 해당 자원을 payload 정보와 교체하는 메서드이다. 즉, PUT 메서드를 사용할 때 전송하는 payload만으로 자원의 전체 상태를 나타낼 수 있어야 한다. 새로운 자원을 생성해야 하는 경우 완전한 상태의 자원을 저장해야 하고 새로운 자원으로 대체하는 경우 대체하는 자원이 완전한 상태를 가지고 있어야 하기 때문이다.</p>
</li>
<li><p>만약 PUT의 정의대로 전달 받은 payload가 기존 정보를 대체하도록 구현한 경우 payload 정보가 불완전한 상태로 전송된다면 일부 entity의 field값들은 null로 변경될 수 있다.</p>
</li>
</ul>
<h2 id="patch를-사용하는-코드">Patch를 사용하는 코드</h2>
<ul>
<li>처음 들었던 예시로 다시 돌아가서 지하철노선(Line)이 가지고 있는 네 가지 필드 중 이번에는 이름(name)과 배차간격(intervalTime) 필드만 변경이 가능하다고 가정해보겠다. 클라이언트에서는 기존처럼 모든 필드를 요청에 실을 필요없이 아래처럼 name과 intervalTime에 대한 정보만 body에 담아서 보내면 된다.</li>
</ul>
<pre><code class="language-java">...
body: JSON.stringify({
  name: &quot;변경된 노선 이름&quot;,
  intervalTime: 100
})
...</code></pre>
<ul>
<li><p>PUT의 경우, URL에 담긴 정보로 엔티티를 식별할 수 없다면 생성까지 해야하기 때문에 엔티티에 필요한 모든 정보를 payload에 실어 보내야 한다.</p>
</li>
<li><p>하지만 PATCH는 부분 수정을 위한 데이터만 요청의 payload로 보내기 때문에 아래와 같이 body를 받는 DTO를 별도로 만들어 주어야 하고, 이 부분 데이터를 받는 DTO로는 새로운 엔티티를 생성할 수 없고 오직 부분 수정을 위한 데이터로써의 준비를 마치게 된다.</p>
</li>
</ul>
<pre><code class="language-java">public UpdateLineNameAndIntervalTime {

    private String name;
    private int intervalTime;

    public UpdateLineNameAndIntervalTime() {}

    public UpdateLineNameAndIntervalTime(String name, int intervalTime) {
        this.name = name;
        this.intervalTime = intervalTime;
    }
}</code></pre>
<ul>
<li>클라이언트에서 PATCH 요청을 보낸 뒤, 이어서 호출 되는 함수를 보자.</li>
</ul>
<pre><code class="language-java">// LineService.java
...
@Transactional
public void updateLine(final Long id, final UpdateLineNameAndIntervalTime request) {
    Line line = lineRepository.findById(id)
        .orElseThrow(NoSuchElementException::new);

    line.update(request);
}
...

// Line.java
public void update(final UpdateLineNameAndIntervalTime request) {
    this.name = request.getName();
    this.intervalTime = request.getIntervalTime();
}</code></pre>
<h1 id="결론">결론</h1>
<ul>
<li><p>PUT과 PATCH는 HTTP 메서드이지만 규약일 뿐 특정 행동을 강제할 수 없다.</p>
</li>
<li><p>하지만 이러한 규약은 모두가 동의한 약속이고 클라이언트와 서버 간의 통신에서 혼란이 발생하지 않도록 정의를 잘 알고 사용하는 것이 좋다.</p>
</li>
<li><p>PUT과 PATCH의 차이점으로 멱등성에 대한 이야기도 많이 있다.</p>
</li>
<li><p>PUT은 멱등성을 지키지만 PATCH는 멱등성을 지키지 못한다는 것이다. 멱등성에 대한 이야기 만으로도 하나의 글을 작성할 수 있을 만큼 그 내용이 방대하기 때문에 아쉽게도 이번 글에서는 다루지 않았다.</p>
</li>
<li><p>만약 멱득성의 차이를 알아보고 싶다면 아래 참고에 추가한 PUT과 PATCH의 멱등성을 보길 추천한다.</p>
</li>
</ul>
<hr>
<h4 id="출처--httpstecobletechcoursecokrpost2020-08-17-put-vs-patch-1">출처 : <a href="https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/">https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/</a></h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[Controller, Service, Repository]]></title>
            <link>https://velog.io/@coginner_/Controller-Service-Repository</link>
            <guid>https://velog.io/@coginner_/Controller-Service-Repository</guid>
            <pubDate>Wed, 25 May 2022 17:00:21 GMT</pubDate>
            <description><![CDATA[<h1 id="controller">Controller</h1>
<hr>
<ul>
<li>MVC의 컨트롤러가 모여 있는 곳이다.</li>
<li>컨트롤러는 서비스 계층을 호출하고 결과를 뷰(JSP)에 전달한다.</li>
</ul>
<h1 id="service">Service</h1>
<hr>
<ul>
<li>서비스 계층에는 비즈니스 로직이 있고 트랜잭션을 시작한다.</li>
<li>서비스 계층은 데이터 접근 계층인 리포지토리를 호출한다.</li>
</ul>
<h1 id="repository">Repository</h1>
<hr>
<ul>
<li>JPA를 직접 사용하는 곳은 리포지토리 계층이다.</li>
<li>엔티티 매니저를 사용해서 엔티티를 저장하고 조회한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[010 비트 모아 데이터]]></title>
            <link>https://velog.io/@coginner_/%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4-010-%EB%B9%84%ED%8A%B8-%EB%AA%A8%EC%95%84-%EB%8D%B0%EC%9D%B4%ED%84%B0</link>
            <guid>https://velog.io/@coginner_/%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4-010-%EB%B9%84%ED%8A%B8-%EB%AA%A8%EC%95%84-%EB%8D%B0%EC%9D%B4%ED%84%B0</guid>
            <pubDate>Sun, 22 May 2022 18:48:59 GMT</pubDate>
            <description><![CDATA[<h1 id="이진수2진수">이진수(2진수)</h1>
<blockquote>
<p>1946년 개발된 컴퓨터인 에니악(ENIAC)은 사람에게 익숙한 10진법을 사용하도록 설계되었으니 전기회로는 전압이 불안정해서 전압을 10단계로 나누어 처리하는데 한계가 있었다. 그래서 1950년에 개발된 에드박(EDVAC)은 단 두 가지 단계, 전기가 흐르면 1, 흐르지 않으면 0, 만으로 작동하도록 설계되었고 매우 성공적이었다.
 그 이후로 지금까지 대부분의 컴퓨터는 2진 체계로 설계되었기 때문에, 2진법을 알지 못하면 컴퓨터의 동작원리나 데이터 처리방식을 온전히 이해할 수 없다.</p>
</blockquote>
<ul>
<li>컴퓨터는 2진수(0과 1) 밖에 모르기 때문에 10진수 숫자 25를 저장할때 2진수 11001로 바꾸어 저장된다.<h2 id="십진수">십진수</h2>
</li>
<li>10의 거듭제곱의 합을 줄여 표기한 것</li>
<li>0 ~ 9까지의 숫자를 이용해 수를 표현하는 것<ul>
<li>10은 9보다 큰 숫자를 표현하기 위해 사용</li>
</ul>
</li>
</ul>
<h2 id="이진수">이진수</h2>
<blockquote>
<p>→ 0과 1로 이루어진 일련의 비트를, 수로 해석할 수 있다는 점은, 여러 개의 항목에 이진 레이블을 차례로 할당할 수 있음을 뜻한다.</p>
</blockquote>
<ul>
<li>기수가 10 대신 2이고 사용되는 숫자가 0과 1뿐<ul>
<li>그래서 2진수 1에 1을 더하면 2가 아닌 10이 되고, 2진수 11에 1을 더하면 12가 아닌 100이 된다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/cba4067c-8fc7-4623-8dea-64566ec56a05/image.png" alt=""></p>
<h2 id="이진수-→-십진수">이진수 → 십진수</h2>
<ul>
<li>이진수를 십진수로 변환하기는 쉽다.</li>
<li>비트가 1인 자릿값에 해당하는 2의 거듭제곱을 합산하기만 하면된다.<h2 id="십진수-→-이진수">십진수 → 이진수</h2>
</li>
<li>십진수를 이진수로 변환하는 것은 까다롭지만, 어렵지 않다.</li>
<li>십진수를 2로 나누는 것을 반복한다.</li>
<li>나눌 때마다 0 또는 1이 되는 나머지 값을 적고, 몫은 다음 나누기를 위한 값으로 사용한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/7d388a79-26fe-4d24-a38a-503c65c3f48f/image.png" alt=""></p>
<ul>
<li>또는 원래 수에서 2의 거듭제곱을 하나씩 내려가면서 뺌으로써 십진수를 이진수로 변환할 수 있다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/ec0f5023-829d-47f7-a3f6-d03accfd7381/image.png" alt=""></p>
<h1 id="바이트">바이트</h1>
<blockquote>
<p>바이트는 1956년 컴퓨터 설계자인 베르너 부흐홀츠(Werner Buchholz)가 만든 단어이다.</p>
</blockquote>
<ul>
<li>보든 최신 컴퓨터에서 <strong>데이터 처리와 메모리 구성의 기본 단위는 8비트(bit)</strong>로, 컴퓨터가 값을 저장할 수 있는 <strong>최소단위</strong></li>
<li>그러나 1 비트는 너무 작은 단위이기 떄문에 1비트 8개의 묶어서 <strong>바이트(byte)</strong>라는 단위로 정의해서 <strong>데이터의 기본 단위</strong>로 사용<ul>
<li>단일 바이트로는 256개의 구별되는 값을 인코딩 가능<ul>
<li>0 ~ 255 사이의 정수 또는 7비트 아스키코드 문자 집합 중 하나의 문자이거나, 뭔가 다른 것</li>
</ul>
</li>
</ul>
</li>
<li>이 외에도 바이트 9개를 묶은 &#39;<strong>워드(word)</strong>&#39;라는 단위가 있는데, <strong>&#39;워드(word)&#39;는 &#39;CPU가 한 번에 처리할 수 있는 데이터의 크기&#39;</strong>를 의미</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/6305cb68-afa7-43d5-bc83-bb4810fbc1b2/image.png" alt=""></p>
<h2 id="십육진수16진수">십육진수(16진수)</h2>
<blockquote>
<p>만일 비트별로 다른 종류의 정보를 인코딩 한다면, 2진수는 10진수 형태보다 세 배 이상 길어서 너무 많은 공강을 차지하므로 <strong>십육진수hexadecimal</strong>라는 대안 표기법을 일반적으로 사용한다.</p>
</blockquote>
<ul>
<li>1~ 4비트로 표현할 수 있는 값의 개수</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/262dedf8-fd97-4b58-8969-9b6d93c38d5d/image.png" alt=""></p>
<ul>
<li>16진수는 16을 기수로 사용하여 16개의 숫자로 표시한다.<ul>
<li>0 ~ 9, A ~ F 를 이용하여 각 16진 숫자가 네 개의 비트를 표현한다.</li>
<li>2, 8, 10, 16 진법에 사용되는 기호</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/coginner_/post/3c597b07-0af2-4b50-9bfe-21321e08a028/image.png" alt=""></p>
<ul>
<li>8진수는 2진수 3자리를, 16진수는 2진수 4자리를 각각 한자리로 표현할 수 있기 때문에 자리수가 짧아져서 알아보기 쉽고 서로 간의 변환방법 또한 매우 간단 </li>
</ul>
<ul>
<li>프로그래머가 아니라면 16진수를 볼 수 있는 곳은 많지 않다.<ul>
<li>예를 들면 웹페이지의 색상에 16진수가 사용된다.<ul>
<li>각 바이트는 <span style="color:red">적색의 양</span>, <span style="color:yellowgreen">녹색의 양</span>, <span style="color:skyblue">청색의 양</span>을 표현하는 데 쓰인다.<ul>
<li>이 방법을 RGB 인코딩이라고 한다.</li>
<li>적색의 양 x 녹색의 양 x 청색의 양 = 255 x 255 x 255개를 표현 가능</li>
</ul>
</li>
</ul>
</li>
<li>또한 유나코드 코드표에서도 문자를 식별하고자 16진수를 사용한다.</li>
</ul>
</li>
</ul>
<ul>
<li>16진수는 뒤에 &#39;네트워크&#39; 주제에서 다룰 이더넷 주소에서도 볼 수 있고,<ul>
<li>&#39;웹&#39;에 쓰이는 URL에서 특수 문자를 표현하는 데도 사용</li>
</ul>
</li>
</ul>
<h4 id="컴퓨터의-32비트와-64비트란">컴퓨터의 32비트와 64비트란?</h4>
<ul>
<li>컴퓨터는 내부적으로 데이터를 다양한 크기의 덩어리 단위로 조작</li>
<li>이런 덩어리는 수와 주소를 포함<ul>
<li>수 : 32비트와 64비트가 편리하게 사용</li>
<li>주소 : 메모리상에 있는 정보의 위치<ul>
<li>여기서 관련된 것은 후자인 주소 속성</li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="비트와-바이트에-대한-논의">비트와 바이트에 대한 논의</h1>
<ul>
<li>기억해야 할  가장 중요한 사실은 비트 모음의 의미가 <strong>상황에 따라 결정</strong><ul>
<li>보이는 것만 가지고 비트의 의미 식별 불가<ul>
<li>참 또는 거짓을 나타내는 비트 한개와 사용하지 않는 비트 일곱 개</li>
<li>작은 정수 또는 # 같은 아스키코드 문자를 저장한 것</li>
<li>다른 체계에서 문자 한 개의 일부</li>
<li>2바이트, 4바이트, 8바이트로 표현되는 큰 수의 일부</li>
<li>사진이나 음악 작품의 일부분</li>
<li>프로세서가 실행할 명령어의 일부</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA]]></title>
            <link>https://velog.io/@coginner_/JPA</link>
            <guid>https://velog.io/@coginner_/JPA</guid>
            <pubDate>Sat, 21 May 2022 05:22:32 GMT</pubDate>
            <description><![CDATA[<h1 id="jpa란">JPA란?</h1>
<ul>
<li>서로 지양하는 바가 다른 2개 영역(객체지향 프로그래밍(OOP) 언어와 관계형 데이터베이스(SQL))을 <strong>중간에서 패러다임 일치</strong>를 시켜주기 위한 기술<ul>
<li><strong>개발자</strong>는 <em><strong>객체지향적 프로그래밍을 하고</strong></em>,</li>
<li><strong>JPA</strong>가 이를 관계형 데이터 베이스에 맞게 <strong><em>SQL을 대신 생성하고 실행</em></strong></li>
<li><blockquote>
<p>개발자는 항상 객체 지향적으로 코드를 표현할 수 있으니 더는 <strong>SQL에 종속적인 개발을 하지 않아도 된다.</strong></p>
</blockquote>
<ul>
<li>그렇기에 생산성이 향상되고 코드의 유지 보수가 편해지는 장점이 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="spring-data-jpa">Spring Data JPA</h1>
<ul>
<li><p>JPA는 인터페이스로서 자바 표준명세서이다.</p>
<ul>
<li><p>인터페이스인 JPA를 사용하기 위해서는 구현체가 필요하고, 대표적으로 Hibernate, Eclipse Link 등이 있다.</p>
</li>
<li><p><strong>하지만</strong> Spring에서 JPA를 사용할 때는 이 구현체들을 직접 다르지 않고 구현체들을 좀 더 쉽게 사용하고자 추상화시킨 Spring Data JPA라는 모듈을 이용하여 JPA 기술을 쓴다. 이들의 관계는 다음과 같다.</p>
<blockquote>
<p>JPA ← Hibernate ← Spring Data JPA</p>
<blockquote>
<p>실질적으로 Hibernate를 쓰는 것과 Spring Data JPA를 쓰는 것 사이에 큰 차이는 없다.</p>
</blockquote>
</blockquote>
</li>
<li><p>이렇게 한 단계 더 감싸놓은 Spring Data JPA가 등장한 이유는 두가지가 있다.</p>
<blockquote>
<p>구현체 교체의 용이성
저장소 교체의 용이성</p>
</blockquote>
</li>
</ul>
<h2 id="구현체-교체의-용이성">구현체 교체의 용이성</h2>
<ul>
<li>Hibernate 외에 다른 구현체로 쉽게 교체하기 위함</li>
</ul>
<h2 id="저장소-교체의-용이성">저장소 교체의 용이성</h2>
<ul>
<li>관계형 데이터베이스 외에 다른 저장소로 쉽게 교체하기 위함</li>
</ul>
</li>
</ul>
<hr>
<p><img src="https://velog.velcdn.com/images/coginner_/post/9d53c774-68e7-4acf-a0f1-ec93fd07ccb2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/2480c514-5d18-47e5-a1e1-ae5b95ffe203/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/9b2f5465-f4fe-4e60-8fb6-4791f31da2d7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/407d0819-14f6-4da6-9f2b-bd1a09193f48/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/coginner_/post/4b5fdcaa-0fb4-49f7-9a2a-2747fe9a9add/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1-17. 객체지향 퀴즈]]></title>
            <link>https://velog.io/@coginner_/1-17.-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%80%B4%EC%A6%88</link>
            <guid>https://velog.io/@coginner_/1-17.-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%80%B4%EC%A6%88</guid>
            <pubDate>Thu, 19 May 2022 04:29:07 GMT</pubDate>
            <description><![CDATA[<h1 id="퀴즈--객체지향">퀴즈 : 객체지향</h1>
<p>객체지향에서 배운 개념과 문법을 이용해서 다음 요구조건을 만족하는 클래스를 작성하시요. 여러분이 게임을 만든다고 생각해보세요.</p>
<p>요구사항</p>
<ol>
<li>사람은 자식, 부모님, 조부모님이 있다.</li>
<li>모든 사람은 이름, 나이, 현재 장소정보(x,y좌표)가 있다.</li>
<li>모든 사람은 걸을 수 있다. 장소(x, y좌표)로 이동한다.</li>
<li>자식과 부모님은 뛸 수 있다. 장소(x, y좌표)로 이동한다.</li>
<li>조부모님의 기본속도는 1이다. 부모의 기본속도는 3, 자식의 기본속도는 5이다.</li>
<li>뛸때는 속도가 기본속도대비 +2 빠르다.</li>
<li>수영할때는 속도가 기본속도대비 +1 빠르다.</li>
<li>자식만 수영을 할 수 있다. 장소(x, y좌표)로 이동한다.</li>
</ol>
<p>위 요구사항을 만족하는 클래스들을 바탕으로, Main 함수를 다음 동작을 출력(<code>System.out.println</code>)하며 실행하도록 작성하시오. 이동하는 동작은 각자 순서가 맞아야 합니다.</p>
<ol>
<li>모든 종류의 사람의 인스턴스는 1개씩 생성한다.</li>
<li>모든 사람의 처음 위치는 x,y 좌표가 (0,0)이다.</li>
<li>모든 사람의 이름, 나이, 속도, 현재위치를 확인한다.</li>
<li>걸을 수 있는 모든 사람이 (1, 1) 위치로 걷는다.</li>
<li>뛸 수 있는 모든 사람은 (2,2) 위치로 뛰어간다.</li>
<li>수영할 수 있는 모든 사람은 (3, -1)위치로 수영해서 간다.</li>
</ol>
<hr>
<p><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></p>
<h1 id="퀴즈-객체지향---정답-예시">퀴즈: 객체지향 - 정답 예시</h1>
<h2 id="humanjava">Human.java</h2>
<pre><code class="language-java">    public class Human {
        String name;
        int age;
        int speed;
        int x, y;

        public Human(String name, int age, int speed, int x, int y) {
            this.name = name;
            this.age = age;
            this.speed = speed;
            this.x = x;
            this.y = y;
        }

        public Human(String name, int age, int speed) {
            this(name, age, speed, 0, 0);
        }

        public String getLocation() {
            return &quot;(&quot; + x + &quot;, &quot; + y + &quot;)&quot;;
        }
        protected void printWhoAmI() {
            System.out.println(&quot;My name is &quot; + name + &quot;. &quot; + age + &quot; aged.&quot;);
        }
    }</code></pre>
<h2 id="walkablejava">Walkable.java</h2>
<pre><code class="language-java">    public interface Walkable {
        void walk(int x, int y);
    }</code></pre>
<h2 id="runnablejava">Runnable.java</h2>
<pre><code class="language-java">    public interface Runnable {
        void run(int x, int y);
    }</code></pre>
<h2 id="swimmablejava">Swimmable.java</h2>
<pre><code class="language-java">    public interface Swimmable {
        void swim(int x, int y);
    }</code></pre>
<h2 id="grandparentjava">GrandParent.java</h2>
<pre><code class="language-java">    public class GrandParent extends Human implements Walkable {
        public GrandParent(String name, int age) {
            super(name, age, 1);
        }

        @Override
        public void walk(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;walk speed: &quot; + speed);
            this.x = x;
            this.y = y;
            System.out.println(&quot;Walked to &quot; + getLocation());
        }
    }</code></pre>
<h2 id="parentjava">Parent.java</h2>
<pre><code class="language-java">    public class Parent extends Human implements Walkable, Runnable{
        public Parent(String name, int age) {
            super(name, age, 3);
        }

        @Override
        public void run(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;run speed: &quot; + (speed + 2));
            this.x = x;
            this.y = y;
            System.out.println(&quot;Ran to &quot; + getLocation());
        }

        @Override
        public void walk(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;walk speed: &quot; + speed);
            this.x = x;
            this.y = y;
            System.out.println(&quot;Walked to &quot; + getLocation());
        }
    }</code></pre>
<h2 id="childjava">Child.java</h2>
<pre><code class="language-java">    public class Child extends Human implements Walkable, Runnable, Swimmable{
        public Child(String name, int age) {
            super(name, age, 5);
        }

        @Override
        public void swim(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;swimming speed: &quot; + (speed + 1));
            this.x = x;
            this.y = y;
            System.out.println(&quot;Swum to &quot; + getLocation());
        }

        @Override
        public void run(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;run speed: &quot; + (speed + +2));
            this.x = x;
            this.y = y;
            System.out.println(&quot;Ran to &quot; + getLocation());
        }

        @Override
        public void walk(int x, int y) {
            printWhoAmI();
            System.out.println(&quot;walk speed: &quot; + speed);
            this.x = x;
            this.y = y;
            System.out.println(&quot;Walked to &quot; + getLocation());
        }
    }</code></pre>
<h2 id="mainjava">Main.java</h2>
<pre><code class="language-java">    public class Main {
        public static void main(String[] args) {
            Human grandParent = new GrandParent(&quot;할아버지&quot;, 70);
            Human parent = new Parent(&quot;엄마&quot;, 50);
            Human child = new Child(&quot;나&quot;, 20);

            Human[] humans = { grandParent, parent, child };
            for (Human human : humans) {
                System.out.println(human.name + &quot;, 나이: &quot; + human.age + &quot;, 속도: &quot; + human.speed + &quot;, 장소: &quot; + human
                        .getLocation());
            }
            System.out.println(&quot;&lt;활동 시작&gt;&quot;);
            for (Human human : humans) {
                if (human instanceof Walkable) {
                    ((Walkable) human).walk(1, 1);
                    System.out.println(&quot; - - - - - - &quot;);
                }
                if (human instanceof Runnable) {
                    ((Runnable) human).run(2, 2);
                    System.out.println(&quot; - - - - - - &quot;);
                }
                if (human instanceof Swimmable) {
                    ((Swimmable) human).swim(3, -1);
                    System.out.println(&quot; - - - - - - &quot;);
                }
            }
        }
    }</code></pre>
<blockquote>
<p>💡 구현하는 방법은 여러가지 입니다. 꼭 예시가 정답은 아닙니다. 다만, 여러분이 짠 코드와 비교해보면서 어떤 코드가 어떤 점에서 더 좋은지 생각해보세요.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[1-16. 객체지향언어 (5) 추상클래스, 인터페이스]]></title>
            <link>https://velog.io/@coginner_/1-16.-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%96%B8%EC%96%B4-5-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@coginner_/1-16.-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%96%B8%EC%96%B4-5-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Thu, 19 May 2022 04:22:31 GMT</pubDate>
            <description><![CDATA[<h1 id="1-추상클래스abstract-class">1) 추상클래스(abstract class)</h1>
<h2 id="추상클래스란"><strong>추상클래스란</strong>?</h2>
<p>추상클래스는 추상메소드를 선언할 수 있는 클래스를 의미합니다. 또한 추상클래스는 클래스와는 다르게 상속받는 클래스 없이 그 자체로 인스턴스를 생성할 수는 없습니다.</p>
<ul>
<li><p>먼저 <strong>추상메소드에</strong> 대해서 알아보겠습니다.</p>
</li>
<li><p>추상메소드는 설계만 되어있으며 수행되는 코드에 대해서는 작성이 안된 메소드입니다. </p>
</li>
<li><p>이처럼, 미완성으로 남겨두는 이유는 상속받는 클래스 마다 반드시 동작이 달라지는 경우에 상속받는 클래스 작성자가 반드시 작성하도록하기 위함입니다.</p>
</li>
<li><p>추상 메소드 형식</p>
<blockquote>
<p>👉 abstract 리턴타입 메소드이름();</p>
</blockquote>
</li>
</ul>
<ul>
<li><p><strong>[코드스니펫] 추상클래스 예제 - Main 함수</strong></p>
<pre><code class="language-java">  public class Main {
      public static void main(String[] args) {

      }
  }</code></pre>
</li>
</ul>
<pre><code class="language-java">abstract class Bird {
    private int x, y, z;

    void fly(int x, int y, int z) {
        printLocation();
        System.out.println(&quot;이동합니다.&quot;);
        this.x = x;
        this.y = y;
        if (flyable(z)) {
            this.z = z;
        } else {
            System.out.println(&quot;그 높이로는 날 수 없습니다&quot;);
        }
        printLocation();
    }

    abstract boolean flyable(int z);

    public void printLocation() {
        System.out.println(&quot;현재 위치 (&quot; + x + &quot;, &quot; + y + &quot;, &quot; + z + &quot;)&quot;);
    }
}

class Pigeon extends Bird {
    @Override
    boolean flyable(int z) {
        return z &lt; 10000;
    }
}

class Peacock extends Bird {
    @Override
    boolean flyable(int z) {
        return false;
    }
}

public class Main {
    public static void main(String[] args) {
        Bird pigeon = new Pigeon();
        Bird peacock = new Peacock();
        System.out.println(&quot;-- 비둘기 --&quot;);
        pigeon.fly(1, 1, 3);
        System.out.println(&quot;-- 공작새 --&quot;);
        peacock.fly(1, 1, 3);
        System.out.println(&quot;-- 비둘기 --&quot;);
        pigeon.fly(3, 3, 30000);
    }
}</code></pre>
<ul>
<li><code>fly(x, y, z)</code> 함수는 <code>Bird</code> 를 상속받는 모든 클래스에서 동일한 동작을 합니다. 다만, 그 안에서 호출된 <code>flyable(z)</code> 의 동작만 그것을 구현하는 자식 클래스에서 구현한대로 동작하는 것입니다.</li>
<li>공작새(peacok)는 새이지만 전혀 날 수가 없죠? 그래서 공작새의 <code>flyable()</code> 은 항상 <code>false</code> 를 리턴해서 언제나 x,y 좌표로만 움직입니다. 반면에, 비둘기(pigeon)는 일정 높이까지는 날아갈 수 있기 때문에 그 기준(여기서는 10000)이 되기 전까지는 z좌표로도 움직일 수 있습니다. 이것을 새의 종류마다 중복코드 없이 구현하려면 추상클래스와 추상메소드를 이용해서 이렇게 구현할 수 있습니다. 이렇게 코드를 짜면, 중복코드가 없으면서도 새의 종류마다 주어진 위치까지 날 수 있는지를 판단할 수 있는 유연성을 허용하며 구현할 수 있습니다.</li>
</ul>
<blockquote>
<p>💡 Tip: interface의 메소드 또는 abstract class 의 abstract method 처럼 구현하는 클래스에서 직접 구현해야하는 경우 IntelliJ IDEA에서 <code>command</code> + <code>N</code> (window는 <code>alt</code> + <code>insert</code>)을 눌러서 <code>implement methods</code>를 선택하면 자동으로 코드완성이 됩니다. 혹은 class 선언 부분에 빨간줄이 그어진다면 <code>alt</code> + <code>enter</code> 로도 추천이 가능합니다. 이렇게 IDEA의 shortcut과 자동완성 기능을 잘 활용하면 코드를 빠르게 작성할 수 있으니 강의에서 다루지 않는 것이라도 찾아서 활용해보세요.</p>
</blockquote>
<h1 id="2-인터페이스interface">2) 인터페이스(interface)</h1>
<ul>
<li><p><strong>인터페이스는</strong> 객체의 특정 행동의 특징을 정의하는 간단한 문법입니다. 인터페이스는 함수의 특징(method signature)인 접근제어자, 리턴타입, 메소드 이름만을 정의합니다. 함수의 내용은 없습니다. 인터페이스를 구현하는 클래스는 인터페이스에 존재하는 함수의 내용(<code>{}</code> 중괄호 안의 내용)을 반드시 구현해야합니다.</p>
</li>
<li><p>인터페이스 형식</p>
<blockquote>
<p>👉 interface 인터페이스명{</p>
<pre><code>  public abstract void 추상메서드명();</code></pre><p>  }</p>
</blockquote>
<p>→ 인터페이스의 메소드는 추상메소드, static메소드, default 메소드 모두 허용됩니다.
  (JDK 1.8부터)</p>
</li>
<li><p><strong>[코드스니펫] 인터페이스 예제 - Main 함수</strong></p>
<pre><code class="language-java">  public class Main {
      public static void main(String[] args) {

      }
  }</code></pre>
</li>
</ul>
<pre><code class="language-java">interface Bird {
    void fly(int x, int y, int z);
}

class Pigeon implements Bird{
    private int x,y,z;

    @Override
    public void fly(int x, int y, int z) {
        printLocation();
        System.out.println(&quot;날아갑니다.&quot;);
        this.x = x;
        this.y = y;
        this.z = z;
        printLocation();
    }
    public void printLocation() {
        System.out.println(&quot;현재 위치 (&quot; + x + &quot;, &quot; + y + &quot;, &quot; + z + &quot;)&quot;);
    }
}

public class Main {

    public static void main(String[] args) {
        Bird bird = new Pigeon();
        bird.fly(1, 2, 3);
//        bird.printLocation(); // compile error
    }
}</code></pre>
<ul>
<li>interface인 <code>Bird</code> 타입으로 선언한 <code>bird</code> 변수는 실제로 <code>Pigeon</code> 객체이지만, interface인 <code>Bird</code> 에 선언되지 않은 <code>printLocation()</code> 이라는 함수는 호출할 수 없습니다. interface type 으로 선언되어있는 부분에서는 실제 객체가 무엇이든지, interface에 정의된 행동만 할 수 있습니다.</li>
</ul>
<blockquote>
<p>💡 @Override
이 부분을 보고 생각나는게 있으신가요?! 앞에서 배웠던 메소드 오버라이딩의 개념이 abstract method, interface의 함수를 구현하는 데에도 사용됩니다.</p>
</blockquote>
<h1 id="3-인터페이스-vs-추상클래스">3) 인터페이스 vs 추상클래스</h1>
<ul>
<li><p>인터페이스</p>
<ol>
<li>구현하려는 객체의 동작의 명세</li>
<li>다중 상속 가능</li>
<li>implements를 이용하여 구현</li>
<li>메소드 시그니처(이름, 파라미터, 리턴 타입)에 대한 선언만 가능</li>
</ol>
</li>
<li><p>추상클래스</p>
<ol>
<li>클래스를 상속받아 이용 및 확장을 위함</li>
<li>다중 상속 불가능 , 단일 상속</li>
<li>extends를 이용하여 구현</li>
<li>추상메소드에 대한 구현 가능</li>
</ol>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>