<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>steel_hyuk___2.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 21 May 2023 14:31:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>steel_hyuk___2.log</title>
            <url>https://images.velog.io/images/steel_hyuk___2/profile/9faff1e4-d720-4810-bfb4-beebbfa55457/IMG_52360-w3copy67.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. steel_hyuk___2.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/steel_hyuk___2" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[TIL] 네트워크 계층]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5-y1wsvq9x</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5-y1wsvq9x</guid>
            <pubDate>Sun, 21 May 2023 14:31:44 GMT</pubDate>
            <description><![CDATA[<p>IP datagram 형식</p>
<table>
<thead>
<tr>
<th>version</th>
<th>header length</th>
<th>type of service</th>
<th>length</th>
</tr>
</thead>
<tbody><tr>
<td>16-bit identifier</td>
<td></td>
<td>flags</td>
<td>fragment offset</td>
</tr>
<tr>
<td>time to live</td>
<td>upper layer</td>
<td>headerchecksum</td>
<td></td>
</tr>
<tr>
<td>32 bit 출발지 IP주소</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>32 bit 목적지 IP주소</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>옵션</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>데이터 (가변 길이, 주로 TCP 또는 UDP segment)</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- version (4bit)  : IP 프로토콜 버전</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- header length (4bit) : 헤더의 길이 (bytes)</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- type of service (8bit) : 데이터 타입</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- length (16bit) : 전체 데이터그램 길이 (bytes)</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- TTL (time to live) (8bit) : 남아있는 최대 hop수</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- upper layer (8bit) : payload를 전달할 상위 계층 프로토콜</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- identifier, flags, fragment offset : 단편화 / 재결합을 위해 사용</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- identifer (16bit) : 쪼갠 데이터의 번호</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- flags (3bit) : 내 뒤에 다른 조각이 있는가 ?</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- fragment offset (13bit) : 몇 번 byte에서 시작하는가 ?</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- header checksum (16bit) : 데이터에 에러가 있는지 확인 (header의 에러만 확인)</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>IP 단편화와 재결합</strong></p>
<ul>
<li>네트워크 링크에는 MTU(Maximum Transmission Unit), 즉 frame의 최대 크기가 존재<ul>
<li>링크 종류에 따라 MTU도 다르다</li>
</ul>
</li>
<li>큰 IP datagram은 네트워크 내에서 쪼개진다 (단편화)<ul>
<li>한 datagram이 여러 개로</li>
<li>최종 목적지에서 재결합된다</li>
<li>IP 헤더의 비트들을 이용해 관련 조각들을 식별하고 순서를 맞춤</li>
</ul>
</li>
</ul>
<p><strong>IP 주소 체계</strong></p>
<ul>
<li>IP 주소 : 호스트, 라우터의 인터페이스를 위한 32-bit 식별값 (IPv4)</li>
<li>네트워크를 나타내는 부분과 네트워크 안의 호스트를 나타내는 부분으로 나누어짐.</li>
<li>인터페이스 : 호스트 / 라우터와 물리 링크 간의 연결<ul>
<li>라우터는 보통 복수의 인터페이스 보유</li>
<li>호스트는 한 개 또는 두 개의 인터페이스 보유</li>
</ul>
</li>
</ul>
<p><strong>서브넷</strong></p>
<ul>
<li>IP 주소에서 subnet 부분이 동일한 장치 인터페이스들</li>
<li>중계 라우터 없이도 서로 물리적으로 도달할 수 있음</li>
<li>subnet을 결정하려면, 호스트 / 라우터에서 각 인터페이스를 분리하여, 섬처럼 격리된 네트워크를 만든다.</li>
<li>격리된 각 네트워크를 subnet이라고 부른다.</li>
<li>subnet mask: IP 주소에서 네트워크 주소와 호스트 주소를 구분하는 것  ex) /24</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/1f8cd4f5-c9cf-44ea-90b4-f7e65a073fd5/image.png" alt=""></p>
<ul>
<li>Class A : 1~127.x.x.x</li>
<li>Class B : 128 ~ 191.x.x.x</li>
<li>Class C : 192 ~ 223.x.x.x</li>
</ul>
<p>Host ID 영역을 더 잘게 쪼개서 관리할 수도 있다.</p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/a0644473-c306-452a-964d-729a0b7bb06e/image.png" alt=""></p>
<p><strong>CIDR (Classless InterDomain Routing)</strong></p>
<ul>
<li>주소의 subnet 부분을 임의의 길이로 설정 (cf. 고전적 클래스 주소 체계)</li>
<li>주소 형식: a.b.c.d/x, 여기에서 x는 주소에서 subnet 부분의 bit 수를 나타냄</li>
</ul>
<p>Q. 호스트는 어떻게 IP 주소를 얻는가 ?</p>
<ul>
<li>고정 IP : 관리자가 수동으로 시스템 파일에 설정 (허가받은 주소만을 사용)</li>
<li>DHCP (Dynamic Host Configuration Protocol)<ul>
<li>서버로부터 주소를 동적으로 얻음</li>
<li>“plug-and-play”</li>
<li>사용중인 주소의 대여기간을 갱신할 수 있다.</li>
<li>주소 재사용을 허용한다 (연결되어 있을 때만 주소를 점유할 수 있음)</li>
</ul>
</li>
</ul>
<p>DHCP 동작 개요</p>
<ul>
<li>호스트가 “DHCP discover” 메시지를 <strong>브로드캐스트</strong></li>
<li>DHCP 서버가 “DHCP offer” 메시지로 응답</li>
<li>호스트는 IP 주소를 요청한다 : “DHCP request” 메시지</li>
<li>DHCP 서버는 응답에 대한 응답을 보낸다 : “DHCP ack” 메시지</li>
</ul>
<p>⇒ DHCP client-server 시나리오</p>
<p>DHCP는 할당된 IP 주소 이상의 정보를 제공함</p>
<ul>
<li>첫 번째 hop 라우터(=디폴트 게이트웨이)의 주소</li>
<li>DNS server의 이름과 IP 주소</li>
<li>network mask</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 네트워크 계층]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Thu, 18 May 2023 04:50:14 GMT</pubDate>
            <description><![CDATA[<p>네트워크 계층에서 가장 중요한 것 ! 주소 ! address !</p>
<p>주소를 어떻게 찾아갈 것인가 ?</p>
<ul>
<li>송신 호스트에서 수신 호스트로 segment 전달</li>
<li>송신측에서는 segment를 datagram으로 캡슐화함</li>
<li>수신측은 트랜스포트 계층에 segment 전달</li>
<li>네트워크 계층 프로토콜은 모든 호스트, 라우터에 존재</li>
<li>라우터는 지나가는 모든 IP datagram의 헤더를 검사한다</li>
</ul>
<p>ㅁ 포워딩 : 라우터의 입력으로 들어오는 패킷을 적절한 출력으로 보냄 (데이터 영역)</p>
<p>ㅁ 라우팅 : 패킷이 출발지에서 목적지까지 거칠 경로를 결정 (제어 영역)</p>
<ul>
<li><p>각각의 모든 라우터들에 위치한 라우팅 알고리즘 요소들이 제어 영역에서 상호작용함.</p>
<p>  <img src="https://velog.velcdn.com/images/steel_hyuk___2/post/7268d76e-361a-44b8-8f77-862eb237812a/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p>때로는 별개의 제어기가 지역 제어 에이전트(CA)와 상호작용함</p>
</li>
<li><p>네트워크가 발전하면서 서비스 모델을 적용함.</p>
<ul>
<li>송신측에서 수신측으로 datagram을 전송하는 채널(connection)에 어떤 서비스 모델을 적용할 것인가?</li>
<li>개별 datagram에 대한 서비스 예: 전달 보장, 40msec 이하의 지연시간 보장</li>
<li>datagram 흐름에 대한 서비스 예: datagram 순서 보장, 최소 대역폭 보장, packet간 간격 변화의 제한</li>
<li>= QoS (Quality of Service)</li>
</ul>
</li>
</ul>
<p>현재의 네트워크 구조는 QoS를 거의 지원하지 못함.</p>
<table>
<thead>
<tr>
<th>네트워크 구조</th>
<th>서비스 모델</th>
<th>대역폭</th>
<th>손실</th>
<th>순서</th>
<th>시간</th>
<th>혼잡 피드백</th>
</tr>
</thead>
<tbody><tr>
<td>인터넷</td>
<td>best effort</td>
<td>none</td>
<td>no</td>
<td>no</td>
<td>no</td>
<td>no</td>
</tr>
<tr>
<td>ATM</td>
<td>CBR (constant bit rate)</td>
<td>constant rate</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td>no congestion</td>
</tr>
<tr>
<td>ATM</td>
<td>VBR (variable bit rate)</td>
<td>guaranteed rate</td>
<td>yes</td>
<td>yes</td>
<td>yes</td>
<td>no congestion</td>
</tr>
<tr>
<td>ATM</td>
<td>ABR (available bit rate)</td>
<td>guatanteed minimum</td>
<td>no</td>
<td>yes</td>
<td>no</td>
<td>yes</td>
</tr>
<tr>
<td>ATM</td>
<td>UBR (unspecified bit rate)</td>
<td>none</td>
<td>no</td>
<td>yes</td>
<td>no</td>
<td>no</td>
</tr>
</tbody></table>
<p>ATM (Asynchronous Transfer Mode) - 비동기 전송 방식</p>
<p><strong>라우터 구조</strong></p>
<ul>
<li>라우팅, 제어영역 (소프트웨어) : msec 시간 수준에서 동작</li>
<li>포워딩, 데이터 영역 (하드웨어) : nsec 시간 수준에서 동작</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/a60ff65f-ee01-4971-baa0-fbed0fa7a119/image.png" alt=""></p>
<p><strong>입력 포트</strong></p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/26c50665-5dc5-4aa5-ae9e-a079698d8e54/image.png" alt=""></p>
<ul>
<li><p>라인 종단 : 물리 계층 (bit 레벨의 수신)</p>
</li>
<li><p>링크 계층 프로토콜 : 예) Ethernet</p>
</li>
<li><p>decentralized switching</p>
<ul>
<li>헤더의 값을 이용해 입력 포트 메모리의 forwarding table에서 출력 포트를 검색</li>
<li>목표 : 회선속도로 입력포트 처리를 완료</li>
<li>큐잉 : 스위치 구조로의 전달 속도보다 datagram이 빨리 도착하면 발생</li>
<li>목적지 기반 전송 : 목적지 IP 주소에만 기반하여 전송 (전통적 방식)</li>
<li>일반적인 전송 : 헤더 필드 값들의 여러 조합에 기반하여 전송</li>
</ul>
</li>
<li><p>목적지 기반 전송 (Destination-based forwarding)</p>
</li>
</ul>
<table>
<thead>
<tr>
<th>목적지 주소 범위</th>
<th>링크 인터페이스</th>
</tr>
</thead>
<tbody><tr>
<td>11001000 00010111 00010000 00000000 부터 11001000 00010111 00010111 11111111</td>
<td>0</td>
</tr>
<tr>
<td>11001000 00010111 00011000 00000000 부터 11001000 00010111 00011000 11111111</td>
<td>1</td>
</tr>
<tr>
<td>11001000 00010111 00011001 00000000 부터 11001000 00010111 00011111 11111111</td>
<td>2</td>
</tr>
<tr>
<td>그 외</td>
<td>3</td>
</tr>
</tbody></table>
<p>ㅁ 최장 프리픽스 대응 (longest prefix matching)</p>
<p>주어진 목적지 주소에 대해서 forwarding table을 검색할 때, 목적지 주소에 들어맞는 최장의 주소 프리픽스를 사용한다.</p>
<p>ex)</p>
<table>
<thead>
<tr>
<th>목적지 주소 범위</th>
<th>링크 인터페이스</th>
</tr>
</thead>
<tbody><tr>
<td>11001000 00010111 00010<strong>* <strong>**</strong></strong></td>
<td>0</td>
</tr>
<tr>
<td>11001000 00010111 00011000 <strong>****</strong></td>
<td>1</td>
</tr>
<tr>
<td>11001000 00010111 00011<strong>* <strong>**</strong></strong></td>
<td>2</td>
</tr>
<tr>
<td>그 외</td>
<td>3</td>
</tr>
</tbody></table>
<p>DA: 11001000 00010111 00010110 10100001
DA: 11001000 00010111 00011000 10101010 어느 인터페이스로 ?</p>
<p><strong>스위치 구조</strong> </p>
<ul>
<li>입력 버퍼의 패킷을 적절한 출력 버퍼로 전달</li>
<li>Memory 방식 / Bus 방식 / Interconnection network (Crossbar, HyperCube, …) 방식</li>
</ul>
<p>ㅁ 메모리를 통한 스위칭</p>
<ul>
<li>초창기의 라우터들</li>
<li>CPU의 직접 제어에 의한 스위칭을 하는 전통적 컴퓨터</li>
<li>Packet이 시스템 메모리에 복사된다</li>
<li>속도가 메모리 대역폭에 의해 제약받는다</li>
</ul>
<p>ㅁ 버스를 통한 스위칭</p>
<ul>
<li>datagram을 공유 버스를 통해 입력 포트 메모리에서 출력 포트 메모리로 전달</li>
<li>어느 한 순간에 하나의 데이터만 버스를 사용할 수 있음</li>
<li>bus contention: 스위칭 속도는 버스의 대역폭에 의해 제약을 받음</li>
</ul>
<p>ㅁ Interconnection network를 통한 스위칭</p>
<ul>
<li>버스 대역폭 제한을 극복</li>
</ul>
<p>입력 포트 큐잉</p>
<ul>
<li>스위치 구조가 입력 포트보다 느리면 입력 큐에 큐잉 발생<ul>
<li>입력 버퍼가 넘치면 손실 발생 !</li>
</ul>
</li>
<li>bus contention</li>
<li>Head-of-the-Line (HOL) 차단 : 큐 앞쪽의 datagram 때문에 그 큐의 다른 datagram이 전달되지 못함</li>
</ul>
<p><strong>출력 포트</strong></p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/ead85201-7740-461e-a5a6-16b43538bb64/image.png" alt=""></p>
<ul>
<li>스위치 구조에서 datagram이 전송 속도 이상으로 도착하면 버퍼링 필요</li>
<li>버퍼가 overflow되면 데이터 유실됨.</li>
<li>스케줄링 정책으로 전송할 datagram을 큐에서 선택</li>
</ul>
<p>ㅁ 스케줄링 메커니즘</p>
<ul>
<li><p>스케줄링 : 링크로 보낼 다음 패킷을 선택하는 것</p>
</li>
<li><p>FIFO 스케줄링 : 큐에 도착한 순서대로 전송</p>
<ul>
<li>폐기 정책 : 큐가 꽉 찼을 때 패킷이 도착하면 ?<ul>
<li>tail drop : 새로 도착하는 패킷을 버림</li>
<li>priority: 우선순위에 의해 버림</li>
<li>random: 무작위로 선택해서 버림</li>
</ul>
</li>
</ul>
</li>
<li><p>priority 스케줄링 : 가장 우선순위가 높은 큐의 패킷을 전송 (동일 우선순위 내에서는 FIFO)</p>
<ul>
<li>다른 우선순위의 다중 class</li>
<li>starbation 문제 발생</li>
</ul>
</li>
<li><p>Round Robin 스케줄링 : 순환적으로 class queue들을 스캔해서 각 클래스에서 패킷을 하나씩 전송한다.</p>
</li>
<li><p>WFQ (Weighted Fair Queuing) 스케줄링 : 일반화된 Round Robin</p>
<ul>
<li>각 클래스는 각 사이클에 가중치를 감안한 서비스를 받는다.</li>
</ul>
</li>
</ul>
<p>Q1. 패킷이 유실되는 건 괜찮은가?</p>
<p>Q2. 우선순위는 어디서 정해지고 어디에 저장되는가?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 웹과 HTTP]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%EC%9B%B9%EA%B3%BC-HTTP</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%EC%9B%B9%EA%B3%BC-HTTP</guid>
            <pubDate>Mon, 15 May 2023 02:21:59 GMT</pubDate>
            <description><![CDATA[<ul>
<li>웹 페이지는 객체들로 구성된다.</li>
<li>객체는 HTML 파일, JPEG 이미지, 오디오 파일 등이다.</li>
<li>웹 페이지는 보통 참조 객체들이 포함된 기본 HTML 파일이다.</li>
<li>각 객체는 URL로 참조한다. ( <a href="http://www.abc.com/abc/abc.pic.gif">www.abc.com/abc/abc.pic.gif</a> )</li>
</ul>
<p>HTTP : hypertext transfer protocol</p>
<ul>
<li><p>웹의 애플리케이션 계층 프로토콜</p>
</li>
<li><p>client / server 모델</p>
<ul>
<li>client: 객체를 (HTTP 프로토콜로) 요청하고 받고 표시하는 브라우저</li>
<li>server: 요청에 의해 객체를 (HTTP 프로토콜로) 보내주는 웹 서버</li>
</ul>
</li>
<li><p>TCP를 사용</p>
<ol>
<li>클라이언트가 서버 80번 포트에 TCP 연결 요청</li>
<li>서버는 TCP 연결 요청을 수락</li>
<li>브라우저 (HTTP 클라이언트)와 웹 서버 (HTTP 서버) 사이에 HTTP 메시지 (애플리케이션 계층 프로토콜 메시지) 교환</li>
<li>TCP 연결 닫음</li>
</ol>
</li>
<li><p>캐싱을 지원 : 서버 부하 감소</p>
</li>
<li><p>HTTP는 비상태 (stateless)</p>
<ul>
<li><p>서버는 클라이언트의 과거 요청에 대한 정보를 유지하지 않는다.</p>
</li>
<li><p>상태(state)를 유지하는 프로토콜은 복잡하다</p>
<ul>
<li><p>과거 이력(상태) 관리 필요</p>
</li>
<li><p>서버나 클라이언트가 다운되거나 교체되면 상태에 대한 정보가 일관성을 잃게 됨.</p>
<p>⇒ 과거 히스토리를 갖고 있는건 http를 이용해서 관리하는 것이 아니라 쿠키를 이용함.</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>상태를 유지하는 방법</p>
<ul>
<li>프로토콜의 양단: 다수의 트랜잭션에 걸쳐서 송수신측에 상태를 유지함</li>
<li>쿠키: http 메시지를 통해 상태 전달</li>
</ul>
<p>사용자 - 서버 상태 : 쿠키(cookies)</p>
<p>네 가지 요소</p>
<ul>
<li>HTTP 응답 메시지의 쿠키 헤더 라인</li>
<li>다음 HTTP 요청 메시지의 쿠키 헤더 라인</li>
<li>사용자 호스트에 저장된 쿠키 파일 (브라우저가 관리)</li>
<li>웹 사이트 백엔드의 데이터베이스</li>
</ul>
<p>쿠키의 용도</p>
<ul>
<li>권한 확인</li>
<li>추천</li>
<li>사용자 세션 상태</li>
</ul>
<p>HTTP 요청 메시지</p>
<ul>
<li><p>두 종류의 HTTP 메시지: 요청(request), 응답(response)</p>
</li>
<li><p>HTTP 요청 메시지: ASCII (사람이 읽을 수 있는 포맷)</p>
</li>
<li><p>POST 방식</p>
<ul>
<li>웹 페이지에는 종종 서식 입력이 포함되어 있다.</li>
<li>입력은 개체 body를 통해 서버로 업로드</li>
</ul>
</li>
<li><p>URL 방식</p>
<ul>
<li>GET 방식을 사용</li>
<li>입력은 요청라인의 URL 필드를 통해 업로드</li>
</ul>
</li>
</ul>
<p>HTTP/1.0</p>
<ul>
<li>GET</li>
<li>POST</li>
<li>HEAD<ul>
<li>요청된 객체의 헤더만 전송(서버 정보 확인, 상태체크, 버전, 최종 수정일자 확인 등 관리 목적)</li>
</ul>
</li>
</ul>
<p>HTTP/1.1</p>
<ul>
<li>GET, POST, HEAD</li>
<li>PUT, PATCH : 수정</li>
<li>DELETE : 삭제</li>
<li>TRACE, CONNECT, OPTIONS</li>
</ul>
<p>HTTP 연결</p>
<ul>
<li>비지속연결 (non-persistent) HTTP<ul>
<li>한 TCP 연결을 통해 최대 한 객체만 전송</li>
<li>여러 객체를 받으려면 여러 연결이 필요하다</li>
<li>객체당 2 RTT(Round Trip Time) 필요</li>
<li>비지속연결 http 응답시간 = 2RTT + 파일 전송 시간</li>
<li>각 TCP 연결에 따른 OS의 과부하</li>
<li>브라우저는 참조된 객체들을 가져오기 위해 TCP 연결 여러 개를 병렬적으로 열 수 있다.</li>
</ul>
</li>
<li>지속연결 (persistent) HTTP<ul>
<li>한 TCP 연결을 통해 여러 객체를 전송</li>
<li>서버는 응답을 보내고도 연결을 닫지 않는다</li>
<li>같은 클라이언트 / 서버 사이의 이후의 HTTP 메시지들은 이 연결을 통해 전송된다.</li>
<li>클라이언트는 참조된 객체를 발견하면 바로 요청한다. (커넥션을 새로 만들 필요가 없으니 기존 커넥션으로 요청)</li>
<li>모든 참조 객체들에 대해 RTT 정도만 필요하다.</li>
</ul>
</li>
</ul>
<p>HTTP 응답의 상태 코드</p>
<ul>
<li>200 OK</li>
<li>40n 클라이언트 문제</li>
<li>50n 서버 문제</li>
</ul>
<p>웹 캐시 (Web caches, proxy server)</p>
<ul>
<li>기점서버의 개입 없이 클라이언트의 요구를 서비스<ul>
<li>브라우저가 캐시를 사용하도록 설정</li>
<li>브라우저는 모든 HTTP 요청을 캐시로 보냄<ul>
<li>캐시에 객체가 있으면, 그걸 전송</li>
<li>없으면, 캐시가 기점서버에 객체를 요청하고 그것을 클라이언트에 돌려줌</li>
</ul>
</li>
</ul>
</li>
<li>캐시는 서버와 클라이언트 역할을 동시에 수행</li>
<li>캐시는 주로 ISP에 의해 설치된다. (대학, 기업, 가정 ISP)</li>
<li>웹 캐시 사용 이유 ?<ul>
<li>클라이언트 요청에 대한 응답 시간 감소</li>
<li>기관 접속 링크의 트래픽 감소</li>
</ul>
</li>
<li>총 지연시간 = 인터넷 지연 + 접속지연 + LAN 지연</li>
</ul>
<p>조건부 GET : 캐시의 객체가 최신이면 객체를 보내지 말라</p>
<ul>
<li>객체 전송 지연 없음</li>
<li>링크 사용률 감소</li>
<li>캐시 : 캐시된 객체의 날짜를 http요청에 명시</li>
<li>서버 : 캐시의 객체가 최신이면 응답에 객체를 보내지 않음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] DB INDEX]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-DB-INDEX</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-DB-INDEX</guid>
            <pubDate>Sun, 14 May 2023 09:57:23 GMT</pubDate>
            <description><![CDATA[<p>데이터베이스의 테이블에 대한 검색 속도를 향상시켜주는 도구</p>
<p>테이블의 특정 컬럼에 인덱스를 생성하면, 해당 컬럼의 데이터를 정렬한 후 별도의 메모리 공간에 데이터의 물리적 주소와 함께 저장한다. (물리적 주소와 컬럼의 값 - key, value의 한 쌍)</p>
<p>장점: 테이블 검색 속도 및 성능 향상 ⇒ 시스템 전반적인 부하 감소</p>
<p>인덱스에 의해 데이터들은 정렬된 형태를 갖는다. Where문으로 특정 조건의 데이터를 찾기 위해서 테이블의 전체를 조건과 비교해야 하는 풀 스캔 작업과 비교해서, 인덱스는 데이터들이 정렬되어 있기 때문에 조건에 맞는 데이터를 빠르게 찾을 수 있다. </p>
<p>⇒ ORDER BY, MIN/MAX 역시도 이미 정렬되어 있기 때문에 빠르게 수행 가능</p>
<p>단점</p>
<ol>
<li>인덱스를 관리하기 위한 추가 작업 필요</li>
<li>추가 저장 공간 필요</li>
<li>잘못 사용하는 경우 외려 성능 저하</li>
</ol>
<p>인덱스를 항상 정렬된 상태로 유지해야 하기 때문에 인덱스가 적용된 컬럼에 삽입, 삭제, 수정 작업을 수행하면 추가 작업이 필요하다. (인덱스의 추가도 추가적으로 필요)</p>
<p>인덱스의 수정이 필요할 때는 기존의 인덱스를 사용하지 않는다는 작업을 수행하고 새로운 인덱스를 추가함.</p>
<p>⇒ 수정 작업이 많은 경우 실제 데이터에 비해 인덱스가 과도하게 커지는 문제점 발생 (추가 저장 공간 많이 필요)</p>
<p>전체 데이터의 10~15% 이상의 데이터를 처리하거나, 데이터의 형식에 따라 성능 낮아질 수 있음. (나이나 성별 같이 값의 범위가 적은 컬럼의 경우, 인덱스를 읽고 나서 다시 많은 데이터를 조회해야 하기 때문에 비효율적이다.)</p>
<p>인덱스를 사용하면 좋은 경우</p>
<p>데이터의 범위가 넓고 중복이 적고 조회가 많거나 정렬된 상태가 유용한 컬럼에 사용하는 것이 좋다.</p>
<p>Clustered Index : MySQL이 자동으로 설정하는 Index</p>
<ol>
<li>해당 테이블에 Auto increments 값으로 Primary Key가 있다면 해당 컬럼이 Clustered Index</li>
<li>없다면, 컬럼 중에 Unique 컬럼이 Clustered Index</li>
<li>없다면, MySQL이 내부적으로 Hidden Clustered Index Key (row ID)를 만들어 사용</li>
</ol>
<p>위 세 가지 경우의 공통점은 ?</p>
<p>⇒ count(*)와 distinct key한 값이 동일하다는 것.</p>
<p>⇒ 그 이유는 모든 row를 통틀어 중복이 적으면 적을수록 Index는 높은 효율을 자랑한다.</p>
<p>Non Clustered Index : 개발자가 설정하는 모든 Index</p>
<p>멀티 컬럼 Index의 경우 최대 16개의 컬럼을 사용할 수 있고, 테이블 당 인덱스의 개수는 최대 64개까지 지정이 가능 (Clustered Index까지 65개)</p>
<p>⇒ 멀티 컬럼 인덱스는 단일 컬럼 인덱스보다 비효율적이기 때문에 사용에 신중해야 한다.</p>
<p>Index를 설정했지만 Full scan으로 동작하는 경우</p>
<ul>
<li>컬럼의 가공<ul>
<li>index로 설정된 컬럼의 값을 알고 있다해도 가공된 컬럼 값은 알 수가 없다. 때문에 우항에 연산을 옮겨야 한다.</li>
</ul>
</li>
<li>부정형 (! =)<ul>
<li>부정형의 경우 해당 데이터를 제외한 모든 데이터를 검색하라는 뜻이기 때문에 풀스캔</li>
</ul>
</li>
<li>like 앞 %<ul>
<li>B+Tree는 데이터의 첫 글자를 기준으로 정렬하기 때문에</li>
</ul>
</li>
<li>count(*)<ul>
<li>개수는 모든 데이터를 다 돌아야만 알 수 있다.</li>
</ul>
</li>
</ul>
<p>자료구조</p>
<ol>
<li>해시 테이블 : key와 value를 한 쌍으로 데이터를 저장하는 자료구조</li>
</ol>
<p>(key, value)로 쌍을 표현하며, key값을 이용해 대응되는 value값을 구하는 방식.</p>
<p>해시 충돌이라는 변수를 제외하면 O(1)의 매우 빠른 시간만에 데이터를 탐색할 수 있다.</p>
<p>그렇지만, Index에서 해시 테이블은 사용되지 않음. why ?</p>
<p>⇒ 해시 테이블은 등호 연산에 최적화되어 있다. 데이터베이스에서는 부등호 연산이 자주 사용되기 때문에.</p>
<ol>
<li>B- Tree : 탐색 성능을 높이기  위해 균형 있게 높이를 유지하는 Balanced Tree의 일종</li>
</ol>
<p>모든 leaf node가 같은 level로 유지되도록 밸런스를 맞춘다.</p>
<p>자식 node의 개수가 2개 이상이며, node 내의 key가 1개 이상일 수 있다.</p>
<ul>
<li>node의 key 수가 k개라면, 자식 node의 수는 k+1개</li>
<li>node의 key는 반드시 정렬된 상태</li>
<li>자식 node들의 key는 현재 node의 key를 기준으로 크기 순으로 나뉘게 됨.</li>
<li>root node는 항상 2개 이상의 자식 node를 가짐 (root node = leaf node 제외)
  <img src="https://velog.velcdn.com/images/steel_hyuk___2/post/54f5d1d6-7f59-4d2a-804f-c033f08f1869/image.png" alt=""></li>
</ul>
<pre><code>노랑 : 자식 node를 가리키는 포인터

숫자 담긴 네모 : key

숫자 : data(value)</code></pre><p>B-Tree의 탐색</p>
<p>B-Tree의 삽입</p>
<ul>
<li>key의 개수 / 2 + 1 번째 값을 올림</li>
</ul>
<p>B-Tree의 삭제</p>
<ul>
<li>삭제할 key가 leaf node에 있는 경우<ul>
<li>현재 node의 key 수가 최소보다 큰 경우 (14)</li>
<li>현재 node의 key 수가 최소이고, 왼쪽 또는 오른쪽 형제 node의 key수가 최소보다 큰 경우 (10)<ul>
<li>삭제할 위치를 Parent로 바꿈</li>
<li>왼쪽 형제 node의 key 수가 최소보다 크다면 Lmax로, 오른쪽에서 그렇다면 Rmin으로 Parent.</li>
</ul>
</li>
<li>현재 node와 왼쪽, 오른쪽 형제 node의 key수가 최소, 부모 node의 key 수가 최소보다 큰 경우 (16)<ul>
<li>값을 삭제하고 parent를 부모 node에서 분할하여 형제 node와 병합</li>
</ul>
</li>
<li>현재 node와 왼쪽, 오른쪽 형제 node, 부모 node 모두 key 수가 최소인 경우<ul>
<li>하단 설명(현재 node와 자식 node 모두 key 수가 최소인 경우)과 동일</li>
</ul>
</li>
</ul>
</li>
<li>삭제할 key가 leaf node를 제외한 node에 있는 경우<ul>
<li>현재 node 또는 자식 node의 key수가 최소보다 큰 경우 (15)<ul>
<li>K의 Lmax또는 Rmin과 자리를 바꾸고 삭제</li>
</ul>
</li>
<li>현재 node와 자식 node 모두 key 수가 최소인 경우 (4)<ul>
<li>트리를 재구조화해야한다.</li>
<li>K를 삭제, K의 양쪽 자식을 하나로 합친다 (a)</li>
<li>K의 parent를 K의 형제 node에 병합 (b)</li>
<li>a를 b의 자식이 되도록 연결</li>
<li>b의 key 수가 최대보다 크면 key 삽입 과정과 동일하게 분할</li>
<li>b의 key 수가 최소보다 작다면 a생성 이후부터 동일 과정 반복</li>
</ul>
</li>
</ul>
</li>
</ul>
<ol>
<li>B+ Tree : 오직 leaf node에만 데이터를 저장하고 leaf node가 아닌 node에서는 자식 포인터만 저장</li>
</ol>
<p>leaf node끼리는 Linked list로 연결되어있다. </p>
<p>B- Tree는 어느 한 데이터 탐색은 효율적이지만, 모든 데이터 순회에는 모든 노드를 방문해야하므로 단점을 개선</p>
<p>leaf node를 제외하고 데이터를 저장하지 않기 때문에 메모리 확보, 하나의 node에 더 많은 포인터를 가질 수 있기 때문에 트리의 높이가 낮아짐, 검색 효율</p>
<p>풀스캔의 경우 B+Tree는 leaf node에만 데이터가 저장되고 연결리스트로 연결되어 있기 때문에 선형 시간 소모, B-Tree는 모든 노드 확인</p>
<p>반면, B- Tree는 최상의 경우 특정 Key를 root node에서 찾을 수 있지만, B+Tree의 경우 반드시 leaf node까지 가야함.</p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/669e3ede-bdb3-49ba-a651-9d5f507e21ec/image.png" alt=""></p>
<p>B+ Tree의 삽입</p>
<p>B+ Tree의 삭제</p>
<ul>
<li>B- Tree의 경우와 동일하나 B+ Tree는 leaf가 아닌 node에 중복값이 존재하기 때문에 해당 key를 노드보다 오른쪽에 있으면서 가장 작은 값으로 바꿔주어야 한다.</li>
</ul>
<p>B+ Tree의 수정</p>
<ul>
<li>삭제 후 삽입</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Error] AdminJS 연동 중 Invalid hook call 에러]]></title>
            <link>https://velog.io/@steel_hyuk___2/Error-AdminJS-%EC%97%B0%EB%8F%99-%EC%A4%91-Invalid-hook-call-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@steel_hyuk___2/Error-AdminJS-%EC%97%B0%EB%8F%99-%EC%A4%91-Invalid-hook-call-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Tue, 04 Apr 2023 05:50:52 GMT</pubDate>
            <description><![CDATA[<p>AdminJS를 Nest.js 프로젝트에 연동하는 과정 중 다음과 같은 에러가 발생하였다. 
<img src="https://velog.velcdn.com/images/steel_hyuk___2/post/df6df768-e616-48a5-8972-46edf2d98a4f/image.png" alt=""></p>
<p>Invalid hook call 에러에 대해 알아보니, React에서 유효하지 않은 상황에서 hook을 사용하려고 할 때 발생하는 에러였다.</p>
<p>때문에 에러를 해결하기 위해서는 hook 사용에 대한 react 지침을 따르고 있는지 확인하라는 답변을 ChatGPT에게서 얻을 수 있었다.</p>
<p>하지만 나는 서버에서 AdminJS를 호출하였을 뿐이고 hook은 adminJS가 react로 구현되어 내부적으로 호출을 하는 부분이었기에 매우 난처한 상황이었다.</p>
<p>계속 서칭을 해보니, adminjs의 패키지의 버전 의존성이 문제였다. adminjs의 react 버전을 확인해보니 16.3.0 버전이었는데, 내 프로젝트에서 react와 react-dom 18.1.0 버전을 설치하니 문제가 해결되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Error] zsh: command not found: nest]]></title>
            <link>https://velog.io/@steel_hyuk___2/Error-zsh-command-not-found-nest</link>
            <guid>https://velog.io/@steel_hyuk___2/Error-zsh-command-not-found-nest</guid>
            <pubDate>Tue, 28 Mar 2023 02:17:42 GMT</pubDate>
            <description><![CDATA[<p>Nestjs를 설치하고도 nest 커맨드가 작동을 하지 않았다.</p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/50f75112-573e-4bee-b4c3-b2c5b81ef112/image.png" alt=""></p>
<p>당연히 프로젝트를 시작할 수도 없었다.</p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/de23c844-a199-48bd-a2c6-657ec1723059/image.png" alt=""></p>
<p>npx를 사용하여 문제를 해결했다.</p>
<pre><code>npx @nestjs/cli new project</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] DNS]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-DNS</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-DNS</guid>
            <pubDate>Tue, 28 Mar 2023 00:51:59 GMT</pubDate>
            <description><![CDATA[<h3 id="dns-domain-name-system">DNS (Domain Name System)</h3>
<p>도메인 주소를 IP 주소로 바꿔주는 시스템</p>
<p>ex) 
사람을 식별하는 방법</p>
<ul>
<li>주민번호, 이름, 여권번호
인터넷 호스트, 라우터 식별하는 방법</li>
<li>IP주소 - datagram에 주소를 부여하기 위해 사용</li>
<li>&quot;이름&quot; (<a href="http://www.abc.com">www.abc.com</a>) - 사람이 사용</li>
</ul>
<p>IP 주소와 이름을 어떻게 매핑할 것인가 ?
=&gt; DNS</p>
<ul>
<li>분산된 데이터베이스: 여러 계층의 name server들로 구현됨</li>
<li>애플리케이션 계층 프로토콜: 호스트와 네임서버들은 주소-이름 변환을 위해 통신함</li>
</ul>
<p>DNS 서비스</p>
<ul>
<li>호스트 이름과 IP주소의 변환</li>
<li>host aliasing
ㅁ 정식이름(canonical name), 별칭(alias name)을 관리</li>
<li>부하 분산
ㅁ 중복된 웹 서버들: 여러 IP주소가 하나의 이름에 연관되어 있음.</li>
</ul>
<p>중앙집중식의 문제?</p>
<ul>
<li>서버의 고장이 전체를 마비시킴</li>
<li>트래픽의 양</li>
<li>중앙집중 DB까지의 거리</li>
<li>유지관리</li>
</ul>
<p>-&gt; 확장성이 없다 =&gt; 분산식의 서버를 사용</p>
<p>분산 계층 데이터베이스
<img src="https://velog.velcdn.com/images/steel_hyuk___2/post/41efc488-7cec-42e7-8764-1210ea6c446c/image.png" alt="">
클라이언트가 <a href="http://www.amazon.com%EC%9D%98">www.amazon.com의</a> IP 주소를 찾는 과정</p>
<ol>
<li>클라이언트는 root server에 질의해 com DNS server를 알아낸다</li>
<li>클라이언트는 .com DNS server에 질의해 amazon.com DNS server를 알아낸다</li>
<li>클라이언트는 amazon.com DNS server에 질의해 <a href="http://www.amazon.com%EC%9D%98">www.amazon.com의</a> IP 주소를 알아낸다.</li>
</ol>
<h4 id="root-name-server">Root name server</h4>
<ul>
<li>지역 name server가 이름을 변환하고자 할 때 접속한다</li>
<li>root name server
ㅁ 매핑 정보를 모르면 책임 서버에 접속
ㅁ 매핑 정보를 얻는다
ㅁ 지역 네임 서버에 그 정보를 돌려준다</li>
</ul>
<p>전세계에 13개의 logical root name server가 있다.</p>
<h4 id="tld-서버-책임-dns-서버">TLD 서버, 책임 DNS 서버</h4>
<p>최상위 레벨 도메인(Top-Level Domain) 서버</p>
<ul>
<li>com, org, net, edu, aero, jobs, museums 등과 최상위 국가 도메인(ex. uk, fr, ca, kr)을 책임진다</li>
<li>Network Solutions 사가 .com TLD 서버를 관리함</li>
<li>Educause 사가 .edu TLD 서버를 관리함</li>
</ul>
<p>책임 (authoritative) DNS 서버</p>
<ul>
<li>각 기관은 자신의 DNS server를 가지고, 기관 내 호스트 들의 이름-IP 매핑을 제공한다</li>
<li>기관에서 자체적으로 관리하거나, 또는 인터넷 서비스 제공자가 관리한다</li>
</ul>
<h4 id="로컬-dns-name-server">로컬 DNS name server</h4>
<ul>
<li>계층 구조에 정확히 들어맞지는 않는다</li>
<li>각 ISP에 하나씩 있다
ㅁ default name server라고도 한다</li>
<li>호스트가 DNS 질의를 하면, 로컬 DNS 서버에 보내진다.
ㅁ 캐시에 최근의 이름-주소 변환 쌍을 보관하고 있음
ㅁ 프록시 역할을 하여, 질의를 DNS 계층 구조에 전달함</li>
</ul>
<p>반복적 질의 (iterated query)</p>
<ul>
<li>질의를 받은 서버는 다음에 접속할 서버의 이름을 돌려준다</li>
<li>난 모르지만 이 서버에 물어보시라 ~</li>
</ul>
<p>재귀적 질의 (recursive query)</p>
<ul>
<li>질의를 받은 네임서버는 주소를 알아내서 돌려준다</li>
<li>상위 계층에 과부하 ?</li>
</ul>
<p>캐싱과 갱신</p>
<ul>
<li>네임 서버가 매핑 정보를 얻으면, 그것을 캐시에 저장한다
ㅁ 캐시의 정보는 일정시간(TTL) 후에 무효화된다.
ㅁ TLD server는 로컬 네임 서버에 캐싱된다</li>
<li>캐싱된 내용은 낡은 정보일수도,,, (best effort 방식의 이름-주소 변환)
ㅁ 만일 해당 이름의 호스트가 ip 주소를 바꾸면 TTL이 만료될 때까지 찾지 못할 수 있음</li>
<li>갱신 / 통보 매커니즘이 IETF 표준으로 제안됨 : RFC 2136</li>
</ul>
<p>DNS 레코드
DNS: 자원레코드 (resource records, RR)가 저장된 분산 DB
RR 형식 : (name, value, type, ttl)</p>
<ul>
<li>type=A
ㅁ name: 호스트 이름
ㅁ value: IP 주소</li>
<li>type=NS
ㅁ name: 도메인 (예: foo.com)
ㅁ value: 이 도메인의 책임 네임 서버의 이름</li>
<li>type=CNAME
ㅁ name: 별칭
ㅁ 예를 들어 <a href="http://www.ibm.com%EC%9D%80">www.ibm.com은</a> 사실 servereast.backup2.ibm.com
ㅁ value: 정식 이름</li>
</ul>
<p>DNS protocol, messages</p>
<ul>
<li>query, reply 메시지는 같은 형식을 사용함</li>
<li>UDP 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] OSI 7계층과 TCP / IP 5계층]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-OSI-7%EA%B3%84%EC%B8%B5%EA%B3%BC-TCP-IP-5%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-OSI-7%EA%B3%84%EC%B8%B5%EA%B3%BC-TCP-IP-5%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Mon, 12 Dec 2022 10:42:55 GMT</pubDate>
            <description><![CDATA[<h3 id="osi-7-layer">OSI 7 Layer</h3>
<p>(Open systems Interconnection)</p>
<p><strong>배경</strong></p>
<p>1980년대 컴퓨터 통신망이 확산되면서 여러 통신망이 공존하는 상황이었다.</p>
<p>통신규격 통일의 필요성을 느낀 ISO (국제 표준화기구)에서는 1984년 OSI 참조 모델을 발표한다.</p>
<p>이 모델은 서로 다른 컴퓨터 기기 간에 네트워크를 형성할 수 있도록 규정한 네트워크 모델 표준안이다.</p>
<p><strong>계층화</strong></p>
<p>모듈들이 계층을 이루도록 역할과 책임을 세분화 하는 것</p>
<p>ex) 항공 (매표소 - 수하물 - 게이트 - 활주로 - 비행기)</p>
<p>why? ⇒ </p>
<p>복잡한 시스템의 구조를 분리해서 명확하게 한다.</p>
<p>모듈화로 시스템의 관리와 갱신을 용이하게 한다.</p>
<p><em>너무 세부화된 계층은 오히려 기능을 복잡하게 만들 수 있다.</em></p>
<p>각 계층은 (                           ) 서비스를 구현한다.</p>
<ul>
<li>계층 자체의 내부 동작을 통해</li>
<li>하위 계층에서 제공되는 서비스에 의존하여</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/503b195a-f199-4d17-ba9d-060a1fdb6f07/image.png" alt=""></p>
<p>너무 세부화된 계층은 기능을 복잡하게 만듦 ⇒ OSI 7 계층은 이론적으로만 남게 됨.</p>
<p>실제로는 TCP/IP 프로토콜 계층을 사용함.</p>
<p>OSI : 서로 다른 컴퓨터 기기 간에 네트워크를 형성할 수 있도록 규정한 네트워크 모델 표준안</p>
<p>TCP/IP : 인터넷 프로토콜을 사용해서 인터네트워킹을 가능하게 하는 프로토콜의 suit </p>
<hr>
<h3 id="응용-계층-application-layer---7-계층">응용 계층 (Application Layer) - 7 계층</h3>
<p>사용자와 가장 밀접한 계층으로 인터페이스 역할</p>
<p>응용 프로세스 간의 정보 교환을 담당</p>
<p>예 : 전자메일, 웹, 문자 메시지, p2p파일 공유, 네트워크 게임, 비디오 스트리밍, 실시간 화상회의, SNS, 검색, …</p>
<p>서로 다른 종단 시스템에서 실행됨</p>
<p>프로세스 : 호스트에서 실행되는 프로그램</p>
<ul>
<li>한 호스트 내에서 두 프로세스는 IPC(Inter-process-communication)을 통해 통신</li>
<li>다른 호스트에 있는 프로세스들은 메시지를 교환함으로써 통신</li>
</ul>
<p>소켓 : 어플리케이션 프로세스를 그 밑에 있는 tcp/ip 프로토콜과 연결해주는 부분</p>
<ul>
<li>프로세스는 소켓을 통해 메시지를 주고 받는다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/e91594c8-5a99-4b32-9e54-0068073d9bad/image.jpeg" alt=""></p>
<p>메시지를 받기 위해 프로세스는 식별자가 필요하다. </p>
<p>호스트는 고유의 32-bit IP 주소를 가짐</p>
<p>(IP 주소만으로는 호스트 내에서 실행되는 프로세스를 식별할 수 없음)</p>
<p>⇒ 식별자 : port number</p>
<p>서버의 port number와 클라이언트의 port number는 별개다.</p>
<p>애플리케이션마다 중요하게 생각하는 것이 다름</p>
<ul>
<li>데이터 신뢰성<ul>
<li>어떤 응용은 100% 신뢰성 있는 데이터 전송을 요구한다. (파일전송)</li>
<li>다른 응용은 약간의 손실을 허용한다. (오디오)</li>
</ul>
</li>
<li>시간(timing)<ul>
<li>어떤 응용은 낮은 지연시간에서만 효과적</li>
</ul>
</li>
<li>처리율 (throughput)<ul>
<li>bps</li>
<li>어떤 응용은 최소한의 처리율이 충족되어야 함.</li>
<li>어떤 응용은 탄력적 응용 (이메일 : 1초 후에 도착하든지 2초 후에 도착하든지 상관없음)</li>
</ul>
</li>
<li>security<ul>
<li>암호화, 데이터 무결성 …</li>
</ul>
</li>
</ul>
<p>이러한 성격에 따라 소켓은 TCP 소켓 ? UDP 소켓 ? 어떤 걸 만들어야할지 제일 먼저 고민해야 함.</p>
<p>ㅁ 표현 계층 (Presentation Layer) - 6계층</p>
<p>데이터를 어떻게 표현할지 결정하는 역할 (데이터의 형식 결정)</p>
<p>송신자에게서 온 데이터를 해석하기 위한 데이터 부호화, 변화 담당</p>
<p>데이터 암호화 복호화</p>
<p>ㅁ 세션 계층 (Session Layer) - 5계층</p>
<p>통신 장치 간 상호작용 및 동기화 제공</p>
<hr>
<h3 id="전송-계층-transport-layer---4계층">전송 계층 (Transport Layer) - 4계층</h3>
<p>전송 계층의 주소 : IP + Port number </p>
<p>서로 다른 호스트의 프로세스들 간에 논리적 통신을 제공한다.</p>
<p>전송계층 프로토콜은 종단시스템에서 수행된다.</p>
<ul>
<li><p>송신측 : 메시지를 세그먼트로 쪼개서 네트워크 계층에 전달</p>
</li>
<li><p>수신측 : 세그먼트를 메시지로 재조립해서 애플리케이션 계층에 전달</p>
</li>
<li><p>UDP (User Datagram Protocol)</p>
<ul>
<li><p>best-effort service</p>
<ul>
<li>사라지거나 순서가 바뀌어 전달될 수 있다.</li>
</ul>
</li>
<li><p>비연결형</p>
<ul>
<li>송수신측 사이에 handshaking 없음</li>
</ul>
</li>
<li><p>스트리밍 멀티미디어 서비스, DNS, …</p>
<ul>
<li>손실을 허용하고 전송률에 민감함</li>
</ul>
</li>
<li><p>UDP segment header</p>
<ul>
<li>source port #, destination port #</li>
<li>length : 헤더를 포함한 UDP segment의 바이트 단위 길이</li>
<li>checksum : 에러가 있는지 없는지 체크하기 위한 정보</li>
</ul>
</li>
<li><p>송수신 프로세스 간의 비신뢰적 전송 (에러가 있다는 사실만 알려줌 ⇒ 응용 계층에서 알아서 해결)</p>
</li>
<li><p>제공하지 않는 것 : 신뢰성, 흐름 제어, 혼잡 제어, 시간보장, 처리율보장, 보안, 연결 설정</p>
</li>
<li><p>사용하는 이유 ? 단순하기 때문. 최대한 빨리빨리 !</p>
<p>대부분의 서비스에서 TCP를 사용. DNS 등 UDP 사용</p>
<p>예전에는 스트리밍 서비스에서 유실을 어느 정도 허용했기에 UDP를 사용했지만 요새는 TCP 사용 (버퍼 이용)</p>
</li>
</ul>
</li>
</ul>
<p>신뢰있게 데이터를 전송하는 원리 (Reliable Data Transfer)</p>
<ul>
<li>ACK<ul>
<li>acknowledgements (ACK) : 수신측이 받은 패킷이 OK라고 송신측에게 알림</li>
<li>negative acknowledgements (NAKs): 그 반대</li>
</ul>
</li>
<li>timeout</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/37785215-441c-4560-b318-6893dcf58788/image.jpeg" alt=""></p>
<ul>
<li><p>ACK / NAK가 손상되면 ?</p>
</li>
<li><p>송신측은 수신측에서 일어나는 일을 알 수 없다. 무작정 재전송하는 것도 불가 (중복 가능성)</p>
</li>
<li><p>⇒ 중복 처리 : 패킷에 순서번호를 추가</p>
</li>
<li><p>파이프라인 기법</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/e2e6c6f7-4668-41d2-96f3-ac0aaf279377/image.jpeg" alt=""></p>
<pre><code>   - in-flight로 전송하는 것을 허용
   - 순서 번호의 범위 증가
- go-back-n : 오류 난 곳부터 다시 받음
- selective repeat : 오류난 부분만 다시 받음</code></pre><ul>
<li>TCP (Transmission Control Protocol)<ul>
<li>송수신 프로세스 간의 신뢰성 있는 전송 (재전송)</li>
<li>흐름제어 : 수신측이 처리할 수 있는 속도에 맞춰 송신</li>
<li>혼잡제어 : 망이 혼잡해지면 송신측 속도를 낮춤<ul>
<li>AIMD : 처음에 패킷을 하나씩 보내고 문제 없다면 window 크기(단위 시간 내에 보내는 패킷의 수)를 점차 늘림</li>
<li>패킷 전송에 실패하거나 일정 시간이 넘으면 패킷의 보내는 속도를 줄임</li>
</ul>
</li>
<li>제공하지 않는 것 : 시간보장, 처리율 보장, 보안</li>
<li>연결지향형 서비스 : client-server 간 연결 설정 필요</li>
<li>guaranteed service</li>
<li>TCP segment<ul>
<li>source port #, destination port #</li>
<li>sequence number : 세그먼트 내 데이터의 첫 바이트의 번호</li>
<li>acknowledgement number : 상대로부터 기대하는 다음 바이트의 번호</li>
<li>checksum</li>
</ul>
</li>
<li>TCP Timeout 설정<ul>
<li>RoundTripTime을 고려(이것보다 길게)</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="네트워크-계층-network-layer---3계층">네트워크 계층 (Network Layer) - 3계층</h3>
<p>네트워크 계층의 주소 : IP Address</p>
<p>라우팅 기능을 맡고 있는 계층</p>
<p>목적지까지 가장 안전하고 빠르게 데이터를 보낼 최적의 경로를 설정</p>
<p>송신 호스트에서 수신 호스트로 segment 전달</p>
<p>송신측에서는 segment를 datagram으로 캡슐화함</p>
<p>수신측은 트랜스포트 계층에 segment 전달</p>
<p>네트워크 계층의 두 가지 주요 기능</p>
<ul>
<li>routing<ul>
<li>패킷이 출발지에서 목적지까지 거칠 경로를 결정</li>
</ul>
</li>
<li>forwarding<ul>
<li>라우터의 입력으로 들어오는 패킷을 적절한 출력으로 보냄</li>
</ul>
</li>
</ul>
<p>네트워크 계층의 두 가지 영역</p>
<ul>
<li>제어 영역<ul>
<li>네트워크 전반의 로직</li>
<li>어떤 경로를 거칠지 결정</li>
</ul>
</li>
<li>데이터 영역<ul>
<li>개개의 라우터마다의 지역적 기능</li>
<li>라우터의 입력 포트에 도착한 datagram이 출력포트에 전달될 방법을 결정</li>
<li>forwarding 기능</li>
</ul>
</li>
</ul>
<p>각각의 라우터는 forwarding table을 가짐.</p>
<p>IP datagram 형식</p>
<ul>
<li>version, 헤더길이, 데이터 타입, time to live (남아있는 최대 hop수), upper layer(payload를 전달할 상위 계층 프로토콜), 전체 데이터그램 길이, (fragment offset, 16-bit identifier, flags)(단편화와 재결합을 위해 사용), checksum(헤더에 대해서만 오류확인), 출발지 IP 주소, 목적지 IP 주소, 옵션(타임스탬프, 거쳐간 경로 기록, 경유할 라우터 목록)</li>
</ul>
<p>단편화와 재결합</p>
<ul>
<li>네트워크 링크에는 MTU(max transfer size) 즉 frame의 최대 크기가 존재</li>
<li>큰 IP datagram은 네트워크 내에서 쪼개진다 (단편화)</li>
<li>쪼개진 datagram은 목적지에서 재결합된다.</li>
</ul>
<hr>
<h3 id="데이터-링크-계층-data-link-layer---2계층">데이터 링크 계층 (Data-Link Layer) - 2계층</h3>
<p>데이터링크 계층의 주소 : MAC Address</p>
<p>물리적인 연결을 통해 인접한 두 장치 간의 신뢰성 있는 정보 전송을 담당</p>
<p>주요 역할 : 프레이밍, 흐름 제어, 오류 제어, 접근 제어, 동기화</p>
<ul>
<li>흐름 제어 : 인접한 송수신 노드 간의 보조 맞추기</li>
<li>오류 검출<ul>
<li>신호 감쇄나 노이즈 등으로 인해 오류가 발생한다</li>
<li>수신측에서 오류의 존재를 검출한다 ⇒ 송신측에 재전송을 요구하거나 frame을 버린다</li>
</ul>
</li>
<li>오류 정정 : 수신 측이 비트 오류를 인식하면 재전송 없이 오류를 정정한다</li>
</ul>
<p>링크 계층은 랜카드에 상당 부분 구현됨. (모든 호스트에 각각 구현)</p>
<hr>
<h3 id="물리-계층-physical-layer---1계층">물리 계층 (Physical Layer) - 1계층</h3>
<p>전기적, 기계적, 기능적인 특성을 이용해 데이터를 전송</p>
<p>데이터를 전송하는 역할을 할 뿐, 알고리즘이나 오류제어의 기능이 없음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] Mysql Int() 괄호 안 숫자의 의미]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-Mysql-Int-%EA%B4%84%ED%98%B8-%EC%95%88-%EC%88%AB%EC%9E%90%EC%9D%98-%EC%9D%98%EB%AF%B8</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-Mysql-Int-%EA%B4%84%ED%98%B8-%EC%95%88-%EC%88%AB%EC%9E%90%EC%9D%98-%EC%9D%98%EB%AF%B8</guid>
            <pubDate>Fri, 18 Nov 2022 02:52:46 GMT</pubDate>
            <description><![CDATA[<p>Mysql에서는 데이터 타입을 선언할 때 괄호 안에 자릿수를 선언한다. (20)이면 20자리, (100)이면 100자리까지 넣겠다는 의미이다. 하지만 int나 bigint에서는 괄호 안의 숫자는 <strong>Zerofill</strong>이라는 옵션을 추가로 사용할 때만 의미가 있다. 그것이 무슨 이야기인지 테스트를 해보았다.</p>
<pre><code>CREATE TABLE test (
    int_1 INT(1),
    zero_1 INT(1) ZEROFILL,
    int_5 INT(5),
    zero_5 INT(5) ZEROFILL,
    int_11 INT(11),
    zero_11 INT(11) ZEROFILL
);</code></pre><p>Zerofill 옵션을 설정한 필드와 그렇지 않은 필드들의 자릿수를 다르게 하여 선언하였다.</p>
<pre><code>INSERT INTO test VALUES (1, 1, 1, 1, 1, 1);
INSERT INTO test VALUES (12345, 12345, 12345, 12345, 12345, 12345);
INSERT INTO test VALUES (1234567890, 1234567890, 1234567890, 1234567890, 1234567890, 1234567890);</code></pre><p>테스트할 데이터를 여러 개 넣고 확인을 해보았다.</p>
<pre><code>SELECT * FROM test;</code></pre><p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/b6bb6ea4-9b21-4857-9193-8a98801fdcbe/image.png" alt=""></p>
<p>Zerofill 옵션은 입력된 값의 자릿수를 일관되게 맞추려는 목적으로 사용되고 해당 컬럼에 입력된 값의 자릿수가 지정된 자릿수보다 작다면 좌측부터 0으로 채워진다. 지정한 자릿수보다 크다면 아무런 영향을 받지 않는다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 순열과 조합]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%EC%88%9C%EC%97%B4%EA%B3%BC-%EC%A1%B0%ED%95%A9</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%EC%88%9C%EC%97%B4%EA%B3%BC-%EC%A1%B0%ED%95%A9</guid>
            <pubDate>Tue, 15 Nov 2022 05:06:07 GMT</pubDate>
            <description><![CDATA[<h3 id="순열-permutation">순열 (Permutation)</h3>
<p>순열은 n개 중에 r개를 뽑는 경우의 수를 구할 때 <strong>순서를 고려하여</strong> 뽑는 개념이다.
순서를 고려한다는 말은 배열 <code>[1, 2, 3]</code>과 배열 <code>[2, 1, 3]</code>을 다른 것으로 본다는 말이다.</p>
<p>배열 <code>[1, 2, 3, 4]</code> 를 중에 3개를 순열로 뽑는 경우 (4P3), 다음과 같은 결과값이 나온다.</p>
<p><code>[[1,2,3], [1,2,4], [1,3,2], [1,3,4], [1,4,2], [1,4,3],
    [2,1,3], [2,1,4], [2,3,1], [2,3,4], [2,4,1], [2,4,3],
    [3,1,2], [3,1,4], [3,2,1], [3,2,4], [3,4,1], [3,4,2],
    [4,1,2], [4,1,3], [4,2,1], [4,2,3], [4,3,1], [4,3,2]]</code></p>
<p>그 값을 구하는 방법을 쫓아가보자.</p>
<blockquote>
<p>n = 4, r = 3</p>
</blockquote>
<ol>
<li>먼저 1을 선택하고 r을 1 뺀다.</li>
<li>나머지 <code>[2, 3, 4]</code> 중에서 순열을 구한다. (n = 3, r = 2)</li>
<li>위의 순서로 <code>[3, 4]</code>의 배열, <code>[4]</code>의 배열에서의 순열까지 구한다.</li>
<li>앞서 선택해둔 값에 차례로 합친다.</li>
<li>순서를 고려하기 때문에 1~4의 과정을 똑같이 2, 3, 4를 먼저 선택하는 방법으로 진행한다.</li>
</ol>
<h4 id="코드">코드</h4>
<pre><code class="language-javascript">const getPermutations = (array, num) =&gt; {
  const results = [];
  if (num === 1) {
    return array.map((value) =&gt; [value]); // 탈출 조건
  }

  array.forEach((fixed, idx, origin) =&gt; {
    const rest = [...origin.slice(0, idx), ...origin.slice(idx + 1)]; // 해당하는 fixed를 제외한 나머지 배열
    const permutations = getPermutations(rest, num - 1); // 나머지에 대한 순열을 구함
    const attached = permutations.map((permutation) =&gt; [fixed, ...permutation]); // 순열에 대해 떼 놓은 fixed 값 붙이기
    results.push(...attached); // 결과 배열에 쌓기
  });
  return results;
}</code></pre>
<h3 id="조합-combination">조합 (Combination)</h3>
<p>조합은 n개 중에 r개를 뽑는 경우의 수를 구할 때 <strong>순서를 고려하지 않고</strong> 뽑는 개념이다.
마찬가지로 순서를 고려하지 않는다는 것은 배열 <code>[1, 2, 3]</code>과 배열 <code>[2, 1, 3]</code>을 같은 것으로 취급한다.</p>
<p>순열에서와 같은 예시로 조합을 구하면, 다음과 같은 결과값이 나온다.</p>
<p><code>[[1,2,3], [1,2,4], [1,3,4], [2,3,4]]</code></p>
<p>조합을 구하는 순서</p>
<blockquote>
<p>n = 4, r = 3</p>
</blockquote>
<ol>
<li>먼저 1을 선택하고 r을 1 뺀다.</li>
<li>나머지 <code>[2, 3, 4]</code> 중에서 조합을 구한다. (n = 3, r = 2)</li>
<li>그 각각을 선택해둔 선택해둔 값에 붙인다.</li>
<li>순서를 고려하지 않기 때문에 1을 제외한 배열에서부터 1~3 과정을 빈 배열이 될 때까지 반복한다.</li>
</ol>
<h4 id="코드-1">코드</h4>
<p>조합의 코드는 나머지 배열을 구하는 코드만 변경하면 된다.</p>
<pre><code class="language-javascript">const getCombinations = (array, num) =&gt; {
  const results = [];
  if (num === 1) {
    return array.map((value) =&gt; [value]); // 탈출 조건
  }

  array.forEach((fixed, idx, origin) =&gt; {
    const rest = origin.slice(idx + 1); // 해당하는 fixed를 제외한 나머지
    const combinations = getCombinations(rest, num - 1); // 나머지에 대한 순열을 구함
    const attached = combinations.map((combination) =&gt; [fixed, ...combination]); // 순열에 대해 떼 놓은 fixed 값 붙이기
    results.push(...attached); // 결과 배열에 쌓기
  });
  return results;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] ++와 +=1의 속도 차이]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%EC%99%80-1%EC%9D%98-%EC%86%8D%EB%8F%84-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%EC%99%80-1%EC%9D%98-%EC%86%8D%EB%8F%84-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 30 Oct 2022 08:22:00 GMT</pubDate>
            <description><![CDATA[<p>프로그래머스 코딩테스트 문제를 푸는 도중 분명 속도적으로 더 개선할 수 있는 부분이 없다고 생각이 드는데 효율성 검사에서 하나를 통과하지 못하는 상황을 겪게 되었다. </p>
<p>한참을 고뇌하던 중 문득 ++ 증감연산자를 +=1 할당연산자로 바꾸자 효율성 테스트를 통과할 수 있었다. </p>
<p>왜 이런 일이 일어나는 것인지 궁금하여 이런저런 글들을 비교해보았지만 명확하게 답을 제시해주는 글을 찾을 수가 없었다. </p>
<p>그 원인은 차차 알아보기로 하고 우선 어느 정도의 속도 차이가 나는지 알아보고 싶었다.</p>
<pre><code class="language-javascript">const allocationTest = (x) =&gt; {
    console.time(&#39;allocation&#39;);
    for (let i=0; i&lt;x; i+=1){}
    console.timeEnd(&#39;allocation&#39;);
}</code></pre>
<pre><code class="language-javascript">const increaseTest = (x) =&gt; {
    console.time(&#39;increase&#39;);
    for (let i=0; i&lt;x; i++){}
    console.timeEnd(&#39;increase&#39;);
}</code></pre>
<p>실행시간을 비교할 수 있는 함수를 작성하여 테스트를 해보았다.</p>
<p><img src="https://velog.velcdn.com/images/steel_hyuk___2/post/d3af616c-8bd8-459c-bb68-87e375ec8003/image.png" alt="">
<img src="https://velog.velcdn.com/images/steel_hyuk___2/post/3c946581-9fdd-4fc7-a460-feef072e20a6/image.png" alt=""></p>
<p>위의 사진에서 볼 수 있는 것처럼 오차를 확인하기 위해 반복하는 횟수를 늘려보고 여러 번 반복실행을 해보았으나 때에 따라 상황이 다르게 나타나는 것을 확인할 수가 있다. 여기서 유추해볼 수 있는 점은 두 경우의 속도 차이는 없다고 보는 것이 맞는 것 같다. 차이가 있다면 천억번 이상의 반복에서의 성능차이라고 보이는 상황이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정산 회고]]></title>
            <link>https://velog.io/@steel_hyuk___2/%EC%A0%95%EC%82%B0-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@steel_hyuk___2/%EC%A0%95%EC%82%B0-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 16 Oct 2022 11:05:06 GMT</pubDate>
            <description><![CDATA[<p>거의 두 달을 괴롭히던 정산 개편 작업이 끝났다. 날짜는 정해져있는데 페스티벌 등등 다른 일정들이 몰아쳐서 날 괴롭게 했던 정산이 끝이 난 것이다. </p>
<p>기존의 코드를 처음 열었을 때는 충격 그 자체,,, 그렇게 복잡한 코드에 주석 한 마디 달려있는 것이 없고 로직마다 뭉텅이가 너무 길어서 코드가 한 눈에 들어오지 않을 뿐더러 수정하기가 상당히 난해한 상태였다. 먼저 코드 각각이 무슨 역할을 하는지 파악하며 주석을 작성해두고 기능 별로 함수로 묶어 가독성을 높였다. </p>
<p>코드를 다 작성하고 로컬 환경, dev, staging 서버에서까지 테스트가 잘 끝나고 실서버에 배포한 후 정산서 일괄 생성을 시켰는데 ,,,, 두둥 ... ! 서버가 다운되고 다시 시작되는... 식은 땀이 줄줄 흐르고 오함마로 뒤통수를 맞은 것마냥 정신이 몽롱해졌다. 다행인건 사용자가 접근할 수 없는 요청이었다는 것... </p>
<p>숨을 고르고 문제를 파악하려보니 promise.all에 한 번에 너무 많은 것을 실행시켜 실행시간을 초과하여 문제가 발생하고 있었다. 이 문제를 해결하기 위해 알아보니 setTimeout을 통해 해결할 수가 있었다. 예전 setTimeout을 공부할 때, 다음 이벤트 사이클에 실행시킨다는 말에 대해 정확히 이해할 수 없었는데 이 문제를 해결하면서 깨달을 수가 있었다. </p>
<p>작업들을 작업 큐에 등록하고 서버 뒷단에서 처리하게 하고 값을 리턴해버려 응답을 마치게 했다. 덕분에 서버는 문제 없이 돌아가고 정산서는 순차대로 생성되었다. </p>
<p>자바스크립트의 동작 원리를 이해하는 것이 개발을 하는 것에 도움이 될 수 있다는 것을 깨닫게 해준 뜻 깊은 경험이었다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] REST API ?]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-REST-API</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-REST-API</guid>
            <pubDate>Wed, 02 Mar 2022 03:38:03 GMT</pubDate>
            <description><![CDATA[<p><strong>REST API (RESTful API)</strong></p>
<p>REST API란 REST 아키텍처의 제약 조건을 준수하는 애플리케이션 프로그래밍 인터페이스를 뜻합니다. 그렇다면 REST API에 대해 알기 위해서는 REST 아키텍처의 제약 조건이 무엇인지, API(application programming interface)가 무엇인지 알아야 할 것 같습니다.</p>
<h3 id="restrepresentational-state-transfer">REST(Representational State Transfer)</h3>
<p>REST란 자원을 이름으로 구분하여 해당 자원의 상태(정보)를 주고받는 모든 것을 의미합니다. 구체적으로 HTTP URI를 통해 자원(Resource)을 명시하고, HTTP method를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미합니다.</p>
<h4 id="rest의-장단점">REST의 장단점</h4>
<p><strong>장점</strong></p>
<ul>
<li>HTTP 프로토콜의 인프라를 그대로 사용하므로 별도의 인프라 구축 불필요</li>
<li>HTTP 표준 프로토콜을 따르는 모든 플랫폼에서 사용 가능</li>
<li>의도하는 바를 쉽게 파악할 수 있음</li>
<li>서버와 클라이언트의 역할을 명확하게 분리</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>표준 부재</li>
<li>HTTP method 형태가 제한적</li>
<li>구형 브라우저가 제대로 지원해주지 못하는 부분 존재</li>
</ul>
<h4 id="rest-특징">REST 특징</h4>
<ol>
<li>Server-Client 구조
자원이 있는 쪽이 서버, 자원을 요청하는 쪽이 클라이언트가 되어 서버는 API를 제공하고 비즈니스 로직 처리 및 저장을 책임지고, 클라이언트는 사용자 인증이나 context(세션, 로그인 정보) 등을 직접 관리하고 책임집니다.</li>
<li>Stateless (무상태)
HTTP 프로토콜은 Stateless 프로토콜이므로 REST 역시 무상태성을 갖습니다. 클라이언트의 context를 서버에 저장하지 않기 때문에 구현이 단순해집니다. 서버는 각각의 요청을 완전히 별개의 것으로 인식하고 처리합니다.</li>
<li>캐시 처리 가능
HTTP가 가진 특징 중 하나인 캐싱 기능을 적용할 수 있어 대량의 요청을 효율적으로 처리할 수 있습니다.</li>
<li>계층화
클라이언트는 REST API 서버만을 호출합니다. REST API 서버는 다중 계층으로 구성할 수 있어 구조상의 유연성을 줄 수 있고, 로드밸런싱, 공유 캐시 등을 통해 확장성과 보안성을 향상시킬 수 있습니다.</li>
<li>인터페이스 일관성</li>
</ol>
<h3 id="api-application-programming-interface">API (Application Programming Interface)</h3>
<p>API란 데이터와 기능의 집합을 제공하여 컴퓨터 프로그램 간 상호작용을 촉진하며, 서로 정보를 교환가능하도록 하는 것입니다.</p>
<h3 id="rest-api">REST API</h3>
<h4 id="rest-api-설계-기본-규칙">REST API 설계 기본 규칙</h4>
<ol>
<li>URI는 정보의 자원을 표현</li>
</ol>
<ul>
<li>동사보다는 명사, 대문자보다는 소문자</li>
<li>도큐먼트 이름으론 단수 명사, 컬렉션, 스토어 이름으로는 복수 명사
ex) <code>GET /Member/1</code> -&gt; <code>GET /members/1</code></li>
</ul>
<ol start="2">
<li>자원에 대한 행위는 HTTP method로 표현</li>
</ol>
<ul>
<li>URI에 HTTP method가 들어가면 안됨
ex) <code>GET /members/delete/1</code> -&gt; <code>DELETE /members/1</code></li>
<li>URI의 행위에 대한 동사 표현이 들어가면 안됨
ex) <code>GET /members/insert/1</code> -&gt; <code>POST /members/1</code></li>
</ul>
<ol start="3">
<li>경로 부분 중 변하는 부분은 유일한 값으로 대체
ex) id는 하나의 특정 리소스를 나타내는 고유한 값</li>
</ol>
<h4 id="rest-api-설계-규칙">REST API 설계 규칙</h4>
<ol>
<li><code>/</code>는 계층 관계를 나타낼 때 사용</li>
<li>URL 마지막 문자로 <code>/</code> 사용하지 않음</li>
<li><code>-</code>은 URI 가독성을 높이는데 사용</li>
<li><code>_</code>은 URI에 사용하지 않음</li>
<li>URI 경로에는 소문자가 적합</li>
<li>파일 확장자는 URI에 포함하지 않음</li>
<li>리소스 간 연관 관계가 있는 경우 : /리소스명/리소스ID/관계가 있는 리소스명
ex) <code>GET /users/{userid}/devices</code></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] Symbol]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-Symbol</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-Symbol</guid>
            <pubDate>Sun, 27 Feb 2022 08:22:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 모던 자바스크립트 deep dive 교재를 참고하여 작성합니다</p>
</blockquote>
<h3 id="symbol">Symbol</h3>
<p>자바스크립트에는 7가지의 원시 타입이 있습니다. 
<code>String, Number, Boolean, undefined, null, object, Symbol</code>
앞의 여섯 가지 타입은 많이 접하고 사용을 했지만 <code>Symbol</code>에 대해서 잘 알지 못 하여 관련된 내용을 정리합니다.</p>
<p><code>Symbol</code>은 ES6에서 도입된 7번째 데이터 타입으로 변경 불가능한 원시 타입의 값입니다. 심벌 값은 <strong>다른 값과 중복되지 않는 유일무이한 값</strong>입니다. 따라서 주로 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용합니다.</p>
<h4 id="생성">생성</h4>
<p>심벌 값은 Symbol 함수를 호출하여 생성합니다. 다른 원시값들은 리터럴 표기법을 사용하여 값을 생성할 수 있지만 심벌 값은 불가능합니다. 생성된 심벌 값은 외부로 노출되지 않아 확인할 수 없으며, 다른 값과 절대 중복되지 않는 유일무이한 값입니다.</p>
<pre><code class="language-javascript">const mySymbol = Symbol();

console.log(typeof mySymbol); // symbol

// 외부로 노출되지 않아 확인할 수 없음
console.log(mySymbol); // Symbol()

const mySymbol1 = Symbol(&#39;abc&#39;);
const mySymbol2 = Symbol(&#39;abc&#39;);

// 심벌 값에 대한 설명이 같더라도 유일무이한 값을 가짐
console.log(mySymbol1 === mySymbol2); // false</code></pre>
<p>심벌 값은 암묵적으로 문자열이나 숫자 타입으로 변환되지 않지만, 불리언 타입으로는 타입이 변환됩니다.</p>
<pre><code class="language-javascript">const mySymbol = Symbol();

console.log(mySymbol + &#39;&#39;); // TypeError
console.log(+mySymbol); // TypeError
console.log(!!mySymbol); // true</code></pre>
<h4 id="symbolfor">Symbol.for</h4>
<p>Symbol.for 메서드는 인수로 전달받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색합니다.</p>
<pre><code class="language-javascript">// 전역 심벌 레지스트리에 abc라는 키로 저장된 심벌 값이 없으면 새로 생성
const s1 = Symbol.for(&#39;abc&#39;);
// 전역 심벌 레지스트리에 abc라는 키로 저장된 심벌 값이 있으면 반환
const s2 = Symbol.for(&#39;abc&#39;);

console.log(s1 === s2); // true</code></pre>
<h4 id="symbolkeyfor">Symbol.keyFor</h4>
<p>Symbol.keyFor 메서드를 사용하면 전역 심벌 레지스트리에 저장된 심벌 값을 추출할 수 있습니다.</p>
<pre><code class="language-javascript">const s1 = Symbol.for(&#39;abc&#39;);

console.log(Symbol.keyFor(s1)); // abc

// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리로 관리되지 않음
const s2 = Symbol(&#39;def&#39;);

console.log(Symbol.keyFor(s2)); // undefined</code></pre>
<h3 id="symbol의-쓰임">Symbol의 쓰임</h3>
<pre><code class="language-javascript">const Direction = {
  UP: 1,
  DOWN: 2,
  RIGHT: 3,
  LEFT: 4
}</code></pre>
<p>위 코드의 객체 같은 경우에 값에는 특별한 의미가 없고 상수 이름 자체에 의미가 있습니다. 이런 경우에 문제는 상수 값이 변경될 수 있으며, 다른 값과 중복될 수가 있습니다. 이럴 때 무의미한 상수 대신 심벌 값을 사용할 수 있습니다.</p>
<pre><code class="language-javascript">const Direction = {
  UP: Symbol(&#39;up&#39;),
  DOWN: Symbol(&#39;down&#39;),
  RIGHT: Symbol(&#39;right&#39;),
  LEFT: Symbol(&#39;left&#39;)
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 클로저]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Thu, 10 Feb 2022 10:49:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 모던 자바스크립트 deep dive 교재를 참고하여 작성합니다</p>
</blockquote>
<p>클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합입니다.</p>
<p>상당히 난해한 정의입니다. 여기서 핵심적인 표현은 <strong>함수가 선언된 렉시컬 환경</strong>입니다.</p>
<pre><code class="language-javascript">const x = 1;

function outer() {
    const x = 10;

    function inner() {
        console.log(x); // 10
    }
    inner();
}
outer();</code></pre>
<pre><code class="language-javascript">const x = 1;

function outer() {
    const x = 10;
    inner();
}
function inner() {
    console.log(x); // 1
}
outer();</code></pre>
<p>위의 코드 예시처럼 outer 함수 내부에서 inner 함수가 정의되고 호출했을 때와 inner 함수가 outer 함수 외부에서 선언되고 내부에서 호출되었을 때의 결과는 다르게 나타납니다. 이러한 현상이 발생하는 이유는 자바스크립트가 <strong>렉시컬 스코프</strong>를 따르는 프로그래밍 언어이기 때문입니다.</p>
<p>그렇다면 렉시컬 스코프가 무엇일까요 ?</p>
<blockquote>
<p>자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정합니다. 이를 렉시컬 스코프(정적 스코프)라고 합니다.</p>
</blockquote>
<pre><code class="language-javascript">const x = 1;

function foo() {
    const x = 10;
    bar();
}
function bar() {
    console.log(x);
}
foo(); // 1
bar(); // 1</code></pre>
<p>foo 함수와 bar 함수는 모두 전역에서 정의된 전역 함수입니다. 함수의 상위 스코프는 어디서 정의했느냐에 따라 결정되므로 foo 함수와 bar 함수의 상위 스코프는 모두 전역입니다. 함수의 호출 위치는 상위 스코프 결정에 어떠한 영향도 주지 않습니다. </p>
<p>스코프의 실체는 실행 컨텍스트의 렉시컬 환경입니다. 이 렉시컬 환경은 자신의 외부 렉시컬 환경에 대한 참조를 통해 상위 렉시컬 환경과 연결됩니다. 따라서 함수의 스코프를 결정한다는 것은 <code>렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다는 것</code>입니다. </p>
<blockquote>
<p>즉 렉시컬 환경의 <code>외부 렉시컬 환경에 대한 참조</code>에 저장할 참조값, 즉 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정됩니다. 이것이 바로 렉시컬 스코프입니다.</p>
</blockquote>
<p>함수가 정의된 환경과 호출되는 환경은 다를 수 있습니다. 따라서 렉시컬 스코프가 가능하려면 함수는 자신이 호출되는 환경과는 상관없이 자신이 정의된 환경, 즉 상위 스코프를 기억해야 합니다. 이를 위해 <strong>함수는 자신의 내부 슬롯에 상위 스코프의 참조를 저장</strong>합니다.</p>
<pre><code class="language-javascript">const x = 1;

// 1
function outer() {
    const x = 10;
    const inner = function () {
        console.log(x);
    }; // 2
    return inner;
}

const innerFunc = outer(); // 3
innerFunc(); // 4 </code></pre>
<p>outer 함수를 호출(3)하면 outer 함수는 중첩 함수 inner를 반환하고 생명 주기를 마감합니다. 즉, outer 함수의 실행이 종료되면 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거됩니다. 이때 outer 함수의 지역 변수 x와 변수 값 10을 저장하고 있던 outer 함수의 실행 컨텍스트가 제거되었으므로 outer 함수의 지역 변수 x 또한 생명 주기를 마감합니다.</p>
<p>하지만 위 코드의 실행 결과(4)는 outer 함수의 지역 변수 x의 값인 10입니다. 이처럼 <strong>외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있습니다. 이러한 중첩 함수를 클로저</strong>라고 합니다.</p>
<p>글의 처음에 언급한 <strong>함수가 선언된 렉시컬 환경</strong>이란 함수가 정의된 위치의 스코프, 즉 상위 스코프를 의미하는 실행 컨텍스트의 렉시컬 환경을 말합니다. outer 함수의 실행이 종료되면 inner 함수를 반환하면서 outer 함수의 생명 주기가 종료되어 outer 함수의 실행 컨텍스트가 실행 컨텍스트 스택에서 제거되지만, <strong>outer 함수의 렉시컬 환경까지 소멸하는 것은 아닙니다.</strong> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 함수형 프로그래밍]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Mon, 07 Feb 2022 05:48:13 GMT</pubDate>
            <description><![CDATA[<h3 id="함수형-프로그래밍">함수형 프로그래밍</h3>
<p>함수형 프로그래밍은 <strong>깔끔하고 유지보수가 용이한 소프트웨어를 만들기 위해 최대한 효과적으로 함수를 사용하는 프로그래밍 방식</strong>을 의미한다. 함수형 프로그래밍은 <strong>자료처리를 수학적 함수의 계산으로 취급하고, 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임</strong>이다. </p>
<p>함수형 프로그래밍을 구현하기 위해서는 아래와 같은 개념들을 알 필요가 있다. </p>
<h3 id="순수함수-pure-function">순수함수 (Pure function)</h3>
<p>순수함수란 결과가 오로지 입력 매개변수에 의해서만 좌우되며 아무런 부작용을 일으키지 않는, 즉 <strong>반환값 이외의 외부 영향이 없는 함수</strong>이다.</p>
<ul>
<li>동일한 입력에는 항상 같은 값을 반환해야 한다.</li>
<li>함수의 실행은 프로그램의 실행에 영향을 미치지 않아야 한다.</li>
<li>함수 내부에서 인자의 값을 변경하거나 프로그램 상태를 변경하는 Side Effect가 없어야 한다.</li>
</ul>
<pre><code class="language-javascript">let num = 1;

function add(a) {
    return a + num;
}</code></pre>
<p>위의 코드는 <code>add</code>라는 함수 안에서 전역변수 <code>num</code>을 참조하기 때문에 순수함수가 아니다.</p>
<pre><code class="language-javascript">function add(a, b) {
    return a+b;
}
const result = add(2, 3);</code></pre>
<p>위의 코드에서는 <code>add</code> 함수가 프로그램 실행에 영향을 미치지 않고 입력 값에 대해서만 값의 변환이 있으므로 순수함수다.</p>
<blockquote>
<p>순수함수는 프로그램의 변화 없이 입력값에 대한 결과를 예상할 수 있어 테스트가 용이하다.</p>
</blockquote>
<h3 id="불변성-immutablility">불변성 (Immutablility)</h3>
<p>함수형 프로그래밍에서 데이터는 변하지 않는 불변성을 유지해야 한다. 데이터의 변경이 필요한 경우, 원본 데이터 구조를 변경하지 않고 복사본을 만들어 변경하고 복사본을 사용하여 작업을 진행한다.</p>
<pre><code class="language-javascript">let onetwo = { one: 1, two: 2 };

function func(obj) {
    obj.one = obj.one + 1;
    return obj;
}</code></pre>
<p>위의 코드는 전역으로 선언된 객체의 속성을 변경하므로 불변성을 지키지 못 한다.</p>
<pre><code class="language-javascript">let onetwo = { one: 1, two: 2 };

function func(obj) {
    return {...obj, one: obj.one + 1};
}</code></pre>
<h3 id="일급-객체">일급 객체</h3>
<ul>
<li>변수나 데이터 구조 안에 담을 수 있다</li>
<li>파라미터로 전달할 수 있다</li>
<li>반환값으로 사용할 수 있다</li>
<li>할당에 사용된 이름과 관계없이 고유한 구별이 가능하다</li>
<li>동적으로 프로퍼티 할당이 가능하다</li>
</ul>
<p>일급 함수는 <strong>독립적으로 취급이 가능한 &#39;물자체(thing in itself)&#39; 함수</strong>이다. 일급 함수를 기술하는 방법으로는 <strong>데이터형 함수</strong>가 있다. 다른 데이터처럼 함수를 변수에 할당할 수 있다는 의미다. 자바스크립트에서 함수는 객체이므로 일급 함수로 불린다.</p>
<h3 id="고차함수">고차함수</h3>
<p><strong>함수를 인수로 받거나 함수를 반환하는 함수</strong>를 고차함수라고 한다.</p>
<ul>
<li>함수를 인자로서 전달할 수 있어야 한다</li>
<li>함수의 반환값으로 또 다른 함수를 사용할 수 있다</li>
</ul>
<pre><code class="language-javascript">const addInform = (name) =&gt; (age) =&gt; age + name;
const name = addInform(&#39;은혁&#39;);

console.log(name(&#39;97&#39;)); // 97은혁</code></pre>
<h3 id="장단점">장단점</h3>
<h4 id="장점">장점</h4>
<ol>
<li>높은 수준의 추상화를 제공한다</li>
<li>함수 단위의 코드 재사용이 수월하다</li>
<li>불변성을 지향하기 때문에 프로그램의 동작을 예측하기 쉬워진다</li>
</ol>
<h4 id="단점">단점</h4>
<ol>
<li>코드의 가독성이 좋지 않을 수 있다</li>
<li>함수형 프로그래밍에서는 반복이 for문이 아닌 재귀를 통해 이루어지는데 재귀적 코드 스타일은 무한루프에 빠질 수 있다</li>
<li>순수함수를 사용하는 것은 쉬울 수 있지만 조합하는 것은 쉽지 않다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] shallow copy vs deep copy]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-shallow-copy-vs-deep-copy</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-shallow-copy-vs-deep-copy</guid>
            <pubDate>Sat, 05 Feb 2022 10:12:37 GMT</pubDate>
            <description><![CDATA[<h3 id="shallow-copy-얕은-복사">shallow copy (얕은 복사)</h3>
<pre><code class="language-javascript">const obj1 = { a: 1, b: 2 };
const obj2 = obj1;

console.log(obj1 === obj2); // true</code></pre>
<p>위의 코드처럼 객체를 대입하여 할당하는 경우 참조에 의한 할당이 이루어지기 때문에 둘은 같은 주소 값을 같게 된다. 이러한 것이 얕은 복사이다.</p>
<pre><code class="language-javascript">const obj1 = { a: 1, b: 2 };
const obj2 = obj1;

obj2.a = 3;
console.log(obj1.a); // 3</code></pre>
<p>때문에 이처럼 obj2의 프로퍼티를 수정했을 때, obj1의 프로퍼티의 값도 변경이 된다. 변경이 되는 것이 아니라 하나의 값이 변경되었고 그 값을 두 변수에서 참조하는 것이다.</p>
<h3 id="deep-copy-깊은-복사">deep copy (깊은 복사)</h3>
<p>주소를 복사하는 것이 아니라 새로운 객체에 프로퍼티만 복사하는 방식이 깊은 복사이다.</p>
<pre><code class="language-javascript">const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1 };

obj2.a = 3;

console.log(obj1 === obj2); // false
console.log(obj1.a) // 1</code></pre>
<pre><code class="language-javascript">const obj1 = { a: 1, b: 2 };
const obj2 = Object.assign({}, obj1);

obj2.a = 3;

console.log(obj1 === obj2); // false
console.log(obj1.a) // 1</code></pre>
<p>깊은 복사는 완전하게 깊은 복사가 되지는 않는다. 객체의 프로퍼티로 객체를 갖는다면 프로퍼티의 객체는 얕은 복사가 된다.</p>
<pre><code class="language-javascript">const obj1 = { a: { b: 1, c: 2 }, d: 3 };
const obj2 = { ...obj1 };

obj2.a.b = 4;

console.log(obj1 === obj2); // false
console.log(obj1.a.b) // 4</code></pre>
<p>때문에 완벽한 deep copy를 위해서는 상황에 맞게 신경을 잘 써주어야 한다.</p>
<pre><code class="language-javascript">const obj1 = { a: { b: 1, c: 2 }, d: 3 };
const obj2 = { ...obj1, a: { ...obj1.a } };

obj1.a.b = 4;

console.log(obj1 === obj2); // false
console.log(obj1.a.b); // 1</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 프로토타입 객체]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Wed, 26 Jan 2022 02:58:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 모던 자바스크립트 deep dive 교재를 참고하여 작성합니다</p>
</blockquote>
<h3 id="프로토타입-객체">프로토타입 객체</h3>
<p>프로토타입은 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용된다. 프로토타입은 어떤 객체의 상위 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드 포함)을 제공한다. 프로토타입을 상속받은 하위 객체는 상위 객체의 프로퍼티를 자신의 프로퍼티처럼 자유롭게 사용할 수 있다. </p>
<h3 id="상속-inheritance">상속 (Inheritance)</h3>
<p>상속은 객체지향 프로그래밍의 핵심 개념으로, 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다. JS는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다. </p>
<blockquote>
<pre><code class="language-javascript">function Circle(radius) {
    this.radius = radius;
    this.getArea = function () {
        return Math.PI * this.radius ** 2;
    }
}
const circle1 = new Circle(1);
const circle2 = new Circle(2);
</code></pre>
</blockquote>
<p>console.log(circle1.getArea === circle2.getArea); // false
console.log(circle1.getArea()); // 3.14......
console.log(circle1.getArea()); // 12.56......</p>
<pre><code>
위의 예제에서 Circle 생성자 함수는 인스턴스를 생성할 때마다 동일한 동작을 하는 getArea 메서드를 중복 생성하고 모든 인스턴스가 중복 소유한다. 하지만 getArea 메서드는 하나만 생성하여 공유하여 사용하는 것이 좋다는 것은 당연한 이치이다. 이때 프로토타입을 사용하여 해결할 수가 있다.

&gt;```javascript
function Circle(radius) {
    this.radius = radius;
}
&gt;
Circle.prototype.getArea = function () {
    return Math.PI * this.radius ** 2;
};
&gt;
const circle1 = new Circle(1);
const circle2 = new Circle(2);
&gt;
console.log(circle1.getArea === circle2.getArea); // true
console.log(circle1.getArea()); // 3.14......
console.log(circle1.getArea()); // 12.56......</code></pre><p>Circle 생성자 함수가 생성한 모든 인스턴스가 getArea 메서드를 공유해서 사용할 수 있도록 프로토타입에 추가한다. 프로토타입은 Circle 생성자 함수의 prototype 프로퍼티에 바인딩되어 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] this란 무엇인가]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-this%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-this%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Tue, 25 Jan 2022 10:57:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📚 모던 자바스크립트 deep dive 교재를 참고하여 작성합니다</p>
</blockquote>
<h3 id="this">this</h3>
<p>객체지향 프로그래밍에서 객체는 상태를 나타내는 <strong>프로퍼티</strong>와 동작을 나타내는 <strong>메서드</strong>를 하나의 논리적인 단위로 묶은 복합적인 자료구조이다. 메서드는 자신이 속한 객체의 상태, 즉 프로퍼티를 참조하고 변경할 수 있어야 한다. 이때 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면 먼저 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다. 이때 <strong>자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수가 this</strong>이다.</p>
<p>this는 자바스크립트 엔진에 의해 암묵적으로 생성되며 코드 어디에서든 참조할 수 있다. 함수를 호출하면 argument 객체와 this가 암묵적으로 함수 내부에 전달된다. 함수 내부에서 argument 객체를 지역 변수처럼 사용할 수 있는 것처럼 this도 지역 변수처럼 사용할 수 있따. 단, <strong>this가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정</strong>된다.</p>
<blockquote>
<p>argument 객체 : 함수를 호출할 때 넘긴 인자들이 배열 형태로 저장된 객체</p>
<pre><code class="language-javascript">function sum (a, b) {
    console.log(arguments);
    return a+b;
}
sum(1, 2);
// Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]</code></pre>
</blockquote>
<pre><code>
&gt; this 바인딩 : 식별자와 값을 연결하는 과정
예를 들어 변수 선언은 변수 이름(식별자)와 확보된 메모리 공간의 주소를 바인딩하는 것이다. this 바인딩은 this와 this가 가리킬 객체를 바인딩하는 것.


자바나 C++ 같은 클래스 기반 언어에서 this는 언제나 클래스가 생성하는 인스턴스를 가리킨다. 하지만 자바스크립트의 this는 함수가 호출되는 방식에 따라 this에 바인딩될 값, 즉 this 바인딩이 동적으로 결정된다.

&gt;```javascript
// 전역
console.log(this); // window
&gt;
// 일반 함수
function square(number) {
    console.log(this); // window
    return number * number;
}
&gt;
// 메서드 내부
const obj = {
    name: &#39;Kim&#39;,
    getName() {
        console.log(this); // { name: &quot;Kim&quot;, getName: f }
        return this.name;
    }
}
&gt;
// 생성자 함수 내부
function func(name) {
    this.name = name;
    console.log(this); // func { name: &quot;kim&quot; }
}
const me = new func(&#39;kim&#39;);</code></pre><p>위의 코드에서 보여주는 것처럼 전역, 일반 함수 내부에서 this는 전역 객체 window를 가리킨다. 메서드 내부에서 this는 메서드를 호출한 객체를 가리키고 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다. 하지만 this는 일반적으로 객체의 메서드 내부 또는 생성자 내부에서만 의미가 있어서 strict mode가 적용된 일반 함수 내부의 this는 undefined가 바인딩된다.</p>
<h3 id="call-vs-apply-vs-bind">call vs apply vs bind</h3>
<p>call, apply, bind는 모두 Function.prototype의 메서드다. 즉 이 세 메서드는 모든 함수가 상속받아 사용할 수 있다. 위에서 이야기한 this를 window가 아닌 다른 객체로 바꿔주는 함수가 call, apply, bind이다.</p>
<h4 id="call--apply">call &amp; apply</h4>
<p>call, apply 메서드는 this로 사용할 객체와 인수 리스트를 인수로 전달받아 함수를 호출한다.</p>
<blockquote>
<pre><code class="language-javascript">function getThisBinding() {
    return this;
}
</code></pre>
</blockquote>
<p>// this로 사용할 객체
const thisArg = { a: 1 };</p>
<blockquote>
</blockquote>
<p>console.log(getThisBinding()); // window</p>
<blockquote>
</blockquote>
<p>// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
console.log(getThisBinding.call(thisArg)); // {a:1}
console.log(getThisBinding.apply(thisArg)); // {a:1}</p>
<pre><code>
call, apply 메서드의 본질적인 기능은 함수를 호출하는 것이다. call 과 apply 메서드는 함수를 호출하면 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩한다. call과 apply 메서드는 호출할 함수에 인수를 전달하는 방식만 다를 뿐, 동일하게 동작한다. 

&gt;```javascript
function getThisBinding() {
    console.log(arguments);
    return this;
}
&gt;
// this로 사용할 객체
const thisArg = { a: 1 };
&gt;
console.log(getThisBinding()); // window
&gt;
// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
// call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
// {a:1}
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달
console.log(getThisBinding.apply(thisArg, [1, 2, 3])); 
// Arguments(3) [1, 2, 3, callee: f, Symbol(Symbol.iterator): f]
// {a:1}</code></pre><h4 id="bind">bind</h4>
<p>Function.prototype.bind 메서드는 apply, call 메서드와 달리 함수를 호출하지 않고 this로 사용할 객체만 전달한다.</p>
<blockquote>
<pre><code class="language-javascript">function getThisBinding() {
    return this;
}
</code></pre>
</blockquote>
<p>// this로 사용할 객체
const thisArg = { a: 1 };</p>
<blockquote>
</blockquote>
<p>// bind 메서드는 함수에 this로 사용할 객체를 전달, 함수 호출 x
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisArg)()); // {a:1}</p>
<pre><code>
bind 메서드는 메서드의 this와 메서드 내부의 중첩함수 또는 콜백함수의 this가 불일치하는 문제를 해결하기 위해 유용하게 사용된다.
&gt;```javascript
const person = {
    name: &#39;Kim&#39;,
    foo(callback) {
        setTimeout(callback, 1000);
    }
};
person.foo(function () {
    console.log(`My name is ${this.name}.`); // My name is .
    // 일반 함수로 호출된 콜백함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
    // 브라우저 환경에서 window.name은 브라우저 창의 이름을 나타내는 빌트인 프로퍼티이며 기본값은 &#39;&#39;이다.
    // Node.js 환경에서 this.name은 undefined다.
});</code></pre><p>콜백함수가 호출되기 이전 시점에서 this는 foo 메서드를 호출한 객체인 person 객체를 가리킨다. 하지만 person.foo의 콜백함수가 일반함수로 호출된 시점에서 this는 전역 객체 window를 가리킨다. 때문에 콘솔에 찍히는 것은 &#39;&#39;값이 되는 것이다. </p>
<p>따라서 콜백함수 내부의 this를 외부 함수 내부의 this와 일치시켜야 하는데, 이때 bind 메서드를 사용한다.</p>
<blockquote>
<pre><code class="language-javascript">const person = {
    name: &#39;Kim&#39;,
    foo(callback) {
        // bind 메서드로 callback 함수 내부의 this 바인딩을 전달
        setTimeout(callback.bind(this), 1000);
    }
};
person.foo(function () {
    console.log(`My name is ${this.name}.`); // My name is Kim.
});</code></pre>
</blockquote>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] C와 Javacript에서 배열의 차이점]]></title>
            <link>https://velog.io/@steel_hyuk___2/TIL-C%EC%99%80-Javacript%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@steel_hyuk___2/TIL-C%EC%99%80-Javacript%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Fri, 21 Jan 2022 01:15:33 GMT</pubDate>
            <description><![CDATA[<h3 id="배열">배열</h3>
<p>일반적으로 배열이라는 자료구조의 개념은 동일한 크기의 메모리 공간이 빈틈 없이 연속적으로 나열된 자료구조이다. 배열은 연속적인 메모리 로케이션들의 묶음을 사용하여 값을 저장하는데 사용한다. 중요한 것은 <strong>연속적</strong>이고 빈틈 없이 <strong>인접</strong>하다는 것이다. </p>
<h3 id="c">C</h3>
<p>C언어에서 <code>int arr[4];</code> 를 선언하고 메모리의 첫 주소가 <code>1201</code>으로 시작하는 메모리 블록을 포착했다고 가정하자. 이 때, arr[2]를 읽으려고 한다면 아주 간단한 연산을 통해 arr[2]의 메모리 주소를 찾을 수가 있다. <code>1201 + (2 * 4) = 1209</code> 이렇게 말이다. 이런 배열은 인덱스를 통해 효율적으로 요소에 접근할 수가 있다. 하지만 정렬되지 않은 배열에서 특정한 요소를 검색하는 경우에는 배열의 모든 요소를 처음부터 특정 요소를 발견할 때까지 차례대로 검색해야 한다. 또한 배열의 요소를 삽입, 삭제를 할 경우에 연속성을 유지하기 위해 요소를 이동시켜야 한다.</p>
<h3 id="javascript">Javascript</h3>
<p>Javascript의 배열은 위에서 살펴본 배열의 의미와는 다르다. 배열의 요소를 위한 각각의 메모리 공간은 동일한 크기를 갖지 않아도 되고 연속적으로 이어져 있지 않을 수 있다. 그 이유는 Javascript에서의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체이기 때문이다. </p>
<blockquote>
</blockquote>
<pre><code class="language-javascript">const array = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;];
console.log(Object.getOwnPropertyDescriptors(array));
/*
{
    0: {value: &#39;a&#39;, writable: true, enumerable: true, configurable: true}
    1: {value: &#39;b&#39;, writable: true, enumerable: true, configurable: true}
    2: {value: &#39;c&#39;, writable: true, enumerable: true, configurable: true}
    length: {value: 3, writable: true, enumerable: false, configurable: false}
}
*/</code></pre>
<p>위의 예시처럼 자바스크립트 배열은 인덱스를 나타내는 값을 프로퍼티 키로 가지며 length 프로퍼티를 갖는 특수한 객체다. 자바스크립트 배열의 요소는 사실 <strong>프로퍼티 값</strong>인 것이다. 자바스크립트 배열은 <strong>해시테이블</strong>로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 면에서 느릴 수밖에 없는 구조적인 단점이 있다. 하지만 특정 요소를 검색하거나 요소를 삽입, 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있다. </p>
<h4 id="해시-테이블">해시 테이블</h4>
<p>검색하고자 하는 키값을 입력 받아서 해시함수를 돌려서 반환받은 해시코드를 배열의 인덱스로 환산해서 데이터에 접근하는 자료구조 </p>
]]></description>
        </item>
    </channel>
</rss>