<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>say_ye.log</title>
        <link>https://velog.io/</link>
        <description>추진력을 얻는 중</description>
        <lastBuildDate>Sat, 21 Jan 2023 11:50:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>say_ye.log</title>
            <url>https://velog.velcdn.com/images/say_ye/profile/a6800edc-a805-42ba-9514-9093d6999893/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. say_ye.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/say_ye" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[JS] 비트연산을 이용한 2차원 Map Editor 만들기]]></title>
            <link>https://velog.io/@say_ye/JS-Map-Editor-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@say_ye/JS-Map-Editor-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sat, 21 Jan 2023 11:50:20 GMT</pubDate>
            <description><![CDATA[<p>2차원 지형을 표현하는 맵은 어떻게 구현할 수 있을까요?
이번 포스팅에서는 비트연산을 활용하여 2차원 Map Editor를 만드는 방법에 대해 알아보겠습니다.</p>
<h2 id="준비물--map-image-asset">준비물 : map image asset</h2>
<p><img src="https://velog.velcdn.com/images/say_ye/post/be520e68-aed4-4de1-85ac-9353da84d261/image.png" alt=""></p>
<p><a href="https://cupnooble.itch.io/sprout-lands-asset-pack">https://cupnooble.itch.io/sprout-lands-asset-pack</a>
저는 위의 무료 애셋을 사용했습니다.</p>
<p>참고로 예시처럼 sprite 이미지로 저장되어 있는 애셋을 사용하면 코드작성 및 리소스 관리측면에서 편리하고 네트워크 요청을 한번만 보내기 때문에 성능상 유리할 수 있습니다.
만일 타일 이미지가 따로 저장되어있는 애셋을 구했다면 Sprite generator(<a href="https://www.toptal.com/developers/css/sprite-generator">링크</a>) 툴을 이용하여 만들어 사용하기를 권장합니다.</p>
<h2 id="각-타일의-정보를-저장">각 타일의 정보를 저장</h2>
<p>맵 애셋을 준비했으면 각 타일들의 정보를 데이터로 저장해야합니다.
저는 각 타일의 데이터를 <code>key(비트마스크) =&gt; value(sprite상의 좌표)</code> 형식의 Map 데이터로 저장했습니다. </p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/5df5693a-e877-4f38-8604-78a3b2612428/image.png" alt=""></p>
<p>각 맵의 타일모양은 위와같이 3x3 그리드 형식으로 표현될 수 있습니다.
이 타일들을 비트마스크 형식의 데이터로 치환하기위해 빈 곳을 0, 땅을 1이라고 했을 때,
가장 왼쪽위의 타일은
<img src="https://velog.velcdn.com/images/say_ye/post/41e29e2e-25ed-43f9-9e6c-cebce4790beb/image.jpeg" alt="">
000
011
011
이 됩니다. 그리고 sprite 좌표상으로는 0번째 행과, 0번째 열에 있습니다.
그럼 해당 타일에 대한 정보는 <code>000011011 =&gt; [0,0]</code> 이 되는 것입니다.</p>
<pre><code class="language-js">
export const GRASS_COORDINATE = new Map([
  [0b000011011, [0, 0]],
  [0b000111111, [0, 1]],
  [0b000110110, [0, 2]],
  [0b000010010, [0, 3]],
  [0b000011010, [0, 4]],
  [0b000111110, [0, 5]],
  [0b000111011, [0, 6]],
  [0b000110010, [0, 7]],
  [0b000111010, [0, 8]],
  [0b110111011, [0, 9]],
  [0b011011011, [1, 0]],
  [0b111111111, [1, 1]],
  [0b110110110, [1, 2]],
  [0b010010010, [1, 3]],
  [0b011011010, [1, 4]],
  [0b111111110, [1, 5]],
  [0b111111011, [1, 6]],
  [0b110110010, [1, 7]],
  [0b111111010, [1, 8]],
  [0b011111110, [1, 9]],
  [0b011011000, [2, 0]],
  [0b111111000, [2, 1]],
  [0b110110000, [2, 2]],
  [0b010010000, [2, 3]],
  [0b010011011, [2, 4]],
    ...
]);</code></pre>
<p>Map의 key는 이진수 리터럴로 작성합니다. (댓글로 의견주신 superlipbalm님 감사합니다)</p>
<p>여기서 순수 Object가 아닌 Map 타입을 쓴 이유는, Number타입을 key로 사용하기 위해서입니다.
순수 Object는 String, Symbol값만을 key로 가질 수 있습니다. (<code>{1:&#39;hello&#39;}</code> 와 같이 Object를 선언하는것이 가능하지만 이 경우도 key가 String 타입으로 묵시적 형변환 되는 것입니다.)</p>
<h3 id="🤔-타일이-이게-전부인가요">🤔 타일이 이게 전부인가요?</h3>
<p>그런데, 각 맵타일이 3*3 그리드, 즉 9비트짜리 이진수와 대응된다는 점에서 착안하면 훨씬 많은 타일이 있어야하지 않을까요?
비어있는 맵을 제외하면 000000001 ~ 111111111 에 해당하는 타일이 모두 있어 총 2^9-1개의 타일이 있어야 하는거 아닌가?
라는 의문이 들 때쯤, 가져온 map asset을 다시 살펴봅시다.</p>
<p>보아하니 모든 타일들은 두가지 가정을 만족합니다.</p>
<blockquote>
<ol>
<li>중앙 비트(5번째비트)가 1이다.</li>
<li>꼭지점 비트(1,3,5,7번째 비트)가 1인 경우, 해당 비트와 인접한 두개의 비트도 모두 1이다.</li>
</ol>
</blockquote>
<p>이는 타일들이 밟을 수 있는 땅(중앙비트가 1)만을 표현하며, 타일이 이어질때는 항상 면끼리 맞대어서 이어진다는 것을 의미합니다.</p>
<blockquote>
<p>위의 두 가정을 만족하지 못하는 타일 데이터는 asset에 존재하지 않는다. 즉, 빈 땅으로 보여지는 <strong>유효하지 않은 타일</strong>이다.</p>
</blockquote>
<p>위 규칙을 잘 활용하면, 47개의 타일로도 <strong>면으로 인접했을 때 이어지는 맵</strong> 을 충분히 구현해낼 수 있습니다.
참고로 꼭짓점 비트를 기준으로 세어보면 타일의 경우의 수를 쉽게 찾아낼 수 있습니다.
<img src="https://velog.velcdn.com/images/say_ye/post/25880700-cb21-402c-bb00-bfb6aeeffe55/image.jpeg" alt=""></p>
<h2 id="에디터에서의-타일-데이터-저장">에디터에서의 타일 데이터 저장</h2>
<p>그렇다면 현재 편집중인 map 데이터는 어떻게 저장하면 좋을까요?
저는 맵 데이터를 유효한 데이터로 변경하는 전처리를 위해 <code>raw</code>, <code>real</code> 이라는 두가지 배열을 선언하여 사용했습니다.</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/e3eedb0d-f843-4e5c-b141-b7a692a36d10/image.gif" alt=""></p>
<p>가령, 위처럼 맵을 그리면 데이터는 다음과 같이 변합니다. (주변의 비어있는 부분은 편의상 생략했습니다.)</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/b477325a-f970-4ded-91cc-50df6da5ba10/image.png" alt=""></p>
<p><code>raw</code> : 땅과 주변에 이어진 땅의 유무를 모두 가지고 있는 데이터 배열
<code>real</code> : raw 데이터를 유효한 타일 데이터로 변경한 데이터 배열</p>
<h3 id="raw-real-초기화">raw, real 초기화</h3>
<pre><code class="language-js">raw = Array.from(Array(CONSTANT_ROW), () =&gt; Array(CONSTANT_COL).fill(0))
real = Array.from(Array(CONSTANT_ROW), () =&gt; Array(CONSTANT_COL).fill(0))</code></pre>
<p>원하는 맵 에디터의 행, 열만큼 0으로 채운 동일한 Array로 선언합니다.</p>
<h3 id="raw-생성">raw 생성</h3>
<ol>
<li>셀을 클릭하면 해당 셀의 중앙비트를 1로 변경</li>
<li>클릭한 셀의 주변 8개 셀 중에 땅이 있으면 해당 방향의 인접비트를 1로 변경</li>
<li>주변 8개 셀의 마주보는 부분의 비트도 1로 변경</li>
</ol>
<h3 id="real-생성">real 생성</h3>
<p>raw 데이터의 선택셀과 주변 셀을 확인하여 유효 타일로 변환 후 real 배열에 반영
<strong>[유효타일 변환 과정]</strong>
        - 중앙비트가 1이 아닌경우 -&gt; 000000000
        - 모든 꼭짓점을 확인하여 꼭짓점 비트가 1이면서 해당 꼭짓점과 인접한 비트가 1이 아닌경우 해당 꼭짓점비트 0으로 변경</p>
<p>위의 작업들을 처리하기위해 자바스크립트에서 지원하는 몇가지 비트 연산자들을 사용할 수 있었습니다.</p>
<h3 id="비트연산">비트연산</h3>
<ul>
<li><p>n번 비트를 1로 변경
<code>bitData |= 1 &lt;&lt; n-1</code></p>
</li>
<li><p>n번 비트가 1인지 확인
<code>bitData &amp; (1 &lt;&lt; n-1)</code></p>
</li>
<li><p>n번 비트를 0으로 변경
<code>bitData &amp;= ~(1 &lt;&lt; n-1)</code></p>
</li>
<li><p>꼭짓점 비트가 1이면서 꼭짓점 주변 비트가 1이 아닌지 확인
<code>(bitData &amp; (1 &lt;&lt; 꼭짓점인덱스)) &amp;&amp; !(bitData &amp; (1 &lt;&lt; 주변1인덱스) &amp;&amp; bitData &amp; (1 &lt;&lt; 주변2인덱스))</code></p>
</li>
</ul>
<h2 id="sprite-이미지-사용하기">sprite 이미지 사용하기</h2>
<pre><code class="language-js">const [coordX, coordY] = GRASS_COORDINATE.get(bitData)
...
&lt;div style={{ background: `url(grass.png) -${coordY * GRID_SIZE}px -${coordX * GRID_SIZE}px` }} /&gt;</code></pre>
<p>real 데이터 배열을 2중 map을 돌려 bitData로 뽑아내고, 위에서 정의한 <code>GRASS_COORDINATE</code> 를 이용하여 asset상의 좌표로 변환합니다. 
이 좌표와 한 타일의 가로, 세로 픽셀크기에 해당하는 <code>GRID_SIZE</code>를 이용하여 해당하는 맵 이미지를 가져올 수 있습니다.
(<code>GRID_SIZE</code>는 본인이 사용하는 이미지에 맞게 정의해서 사용하면 됩니다.)</p>
<h2 id="소스코드-및-실행화면">소스코드 및 실행화면</h2>
<p><a href="https://playcode.io/1083380">https://playcode.io/1083380</a>
위의 링크를 누르면 react로 구현한 소스코드와 실행화면을 확인해 볼 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 1477 : 휴게소 세우기]]></title>
            <link>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-1477-%ED%9C%B4%EA%B2%8C%EC%86%8C-%EC%84%B8%EC%9A%B0%EA%B8%B0</link>
            <guid>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-1477-%ED%9C%B4%EA%B2%8C%EC%86%8C-%EC%84%B8%EC%9A%B0%EA%B8%B0</guid>
            <pubDate>Tue, 27 Dec 2022 06:34:11 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/1477">문제링크</a></p>
<h3 id="풀이">풀이</h3>
<pre><code class="language-python">import math
import sys

input = sys.stdin.readline
n, m, l = map(int, input().split())
분기점 = [0] + list(map(int, input().split())) + [l]
분기점.sort()

for i in range(m):
  구간길이 = [분기점[i+1] - 분기점[i] for i in range(n+1)]

몇등분 = [1] * len(구간길이)

for _ in range(m):
  등분된길이 = [math.ceil(x / y) for x,y in zip(구간길이, 몇등분)]
  더나눌구간 = 등분된길이.index(max(등분된길이))
  몇등분[더나눌구간] += 1

최대구간길이 = max([math.ceil(x / y) for x,y in zip(구간길이, 몇등분)])
print(최대구간길이)</code></pre>
<h3 id="풀이방법">풀이방법</h3>
<ol>
<li><strong>각 구간길이</strong>와 <strong>각 구간길이를 몇등분할지</strong> 저장하는 배열을 선언한다.</li>
<li>m번의 시행마다 <code>구간길이 / 몇등분</code>을 반올림한 결과가 가장 큰 인덱스의 등분을 +1 증가시킨다.</li>
<li>최종적으로 <code>구간길이 / 몇등분</code> 을 반올림한 결과가 가장 큰 값이 휴게소간 최대거리가 가장 짧은때의 값이된다.</li>
</ol>
<h3 id="채점결과">채점결과</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/aefaffc4-cea2-44c8-9b3c-5139f694486d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 소수점 계산 오차]]></title>
            <link>https://velog.io/@say_ye/JS-%EC%86%8C%EC%88%98%EC%A0%90-%EA%B3%84%EC%82%B0-%EC%98%A4%EC%B0%A8</link>
            <guid>https://velog.io/@say_ye/JS-%EC%86%8C%EC%88%98%EC%A0%90-%EA%B3%84%EC%82%B0-%EC%98%A4%EC%B0%A8</guid>
            <pubDate>Mon, 26 Dec 2022 13:28:54 GMT</pubDate>
            <description><![CDATA[<p>컴퓨터는 숫자를 2진수로 저장하여 계산합니다.
이때 만일 2진수로 변환하고자 하는수가 소수타입이라면 어떻게 될까요?</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/a4f5c3f1-50ee-4507-8c94-7f6d277cb252/image.png" alt=""></p>
<p>0.5 =&gt; 0.1
0.25 =&gt; 0.01
0.75 =&gt; 0.11
0.3 =&gt; 0.0100110011001.....(무한소수)</p>
<p>위의 예시 케이스들을 보면 알 수 있다시피, 2의 제곱 꼴의 합으로 소수를 표현해야 하므로 몇 가지의 케이스(분모가 2의 거듭제곱 꼴)를 제외하고는 소수들을 정확하게 표현하기에는 한계가 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/7c3faf11-9377-4015-8c73-eb2abf752ef9/image.png" alt=""></p>
<p>그래서 이런 문제가 눈앞에서 발생하곤 합니다.</p>
<p>우리의 JS가 또...🤦 라고 생각 할 수 있지만 사실 이는 JS만의 문제는 아닙니다.
<img src="https://velog.velcdn.com/images/say_ye/post/c39d62ae-e8fa-4dd5-aeac-2dde886b63f7/image.png" alt="">
사실 파이썬을 포함한 많은 언어가 이렇습니다.</p>
<p>서치하면서 몇가지 글들을 살펴보니까 JS는 부동소수점 방식을 사용해서 그렇다고 이야기하는데.. 부동소수점 방식이든, 고정소수점 방식이든 둘 다 오차가 발생합니다. 소수부를 이진수로 표현하고자 하기때문에 오차가 나는 것이니까요.</p>
<p>이런 오차를 해결하기 위한 방법으로 어떤것들이 있는지 알아봅시다.</p>
<h3 id="1-tofixed-메서드-사용">1. toFixed 메서드 사용</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/a4eeb620-ddf1-474d-953b-3cf515ee9b38/image.png" alt=""></p>
<p><code>Number.prototype.toFixed()</code> 를 사용하면 파라미터로 주어진 자릿수까지 반올림한 결과를 문자열로 리턴합니다.
문자타입으로 리턴하므로 다음 계산에서 사용하기 위해서는 숫자형으로 변환해야 합니다.</p>
<h3 id="2-정수로-만들어서-계산">2. 정수로 만들어서 계산</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/4989418f-2f30-496a-b27b-e61fc09e4363/image.png" alt="">
10ⁿ(n=소수점 최대 길이) 만큼 곱해줘서 정수로 만들고, 계산 후 마지막에 다시 10ⁿ만큼 나누는 방법입니다.</p>
<h3 id="3-math-모듈을-사용">3. Math 모듈을 사용</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/98d63af4-4410-4a59-80f1-9a6e68deab01/image.png" alt=""></p>
<p><code>Math.ceil</code>, <code>Math.floor</code>, <code>Math.trunc</code>, <code>Math.round</code> 와 같은 정수형 변환 메서드들을 사용하는 방법입니다.
정수로만 변환이 가능하므로 소수 계산을 위해서는 자릿수 보정이 필요합니다.</p>
<p>###</p>
<h3 id="4-decimaljs-같은-라이브러리-사용">4. decimal.js 같은 라이브러리 사용</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/a41c5a00-c0e2-49ef-985e-67f0b3868417/image.png" alt="">
<a href="https://github.com/MikeMcl/decimal.js/blob/master/decimal.mjs#L1260">Source Code</a>
위의 소스코드를 보면 decimal.js 에서 소수점 오차문제를 어떻게 해결하고 있는지 알 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[d3로 동적인 네트워크 차트 그리기 (3) - D3.js - Simulation]]></title>
            <link>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-3-D3.js-%EC%A2%8C%ED%91%9C%EB%A5%BC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-%EA%B3%84%EC%82%B0%ED%95%B4%EC%A3%BC%EB%8A%94-d3.forceSimulation</link>
            <guid>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-3-D3.js-%EC%A2%8C%ED%91%9C%EB%A5%BC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-%EA%B3%84%EC%82%B0%ED%95%B4%EC%A3%BC%EB%8A%94-d3.forceSimulation</guid>
            <pubDate>Fri, 23 Dec 2022 04:58:57 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/say_ye/post/87cb3306-f1a0-4073-bd6d-1df81daa165d/image.gif" alt=""></p>
<p>앞선 포스팅에서 간단한 네트워크 차트를 그려봤습니다.
앞에서는 데이터에 각 노드별 x, y좌표를 직접 설정 해주고, nodes-links를 직접 매핑해 줬습니다.
이번 포스팅에서는 D3의 forceSimulation과 simulation객체의 메서드들을 이용하여 이 과정을 자동화하고, 꿈틀거리며 그래프가 부드럽게 생성되는 애니매이션도 함께 구현해보겠습니다.</p>
<h2 id="simulation">simulation</h2>
<ul>
<li><p><code>d3.forceSimulation(nodes)</code>
nodes 배열을 사용하는 새로운 시뮬레이션을 생성합니다.
시뮬레이션은 자동으로 시작되며, simulation.on(&quot;tick&quot;, callback)을 통해 각 tick마다(default-300회) 실행될 콜백을 지정할 수 있습니다.
만일 시뮬레이션의 실행시점을 직접 조작하고싶다면, <code>simulation.stop()</code>을 호출하고, 원하는 시점에 <code>simulation.tick()</code>을 실행하면 됩니다.</p>
</li>
<li><p><code>simulation.force(name[, force])</code>
  시뮬레이션에 지정된 name과 함께 force를 할당하고, 그 시뮬레이션을 리턴합니다.
  이 때 name은 사용자가 원하는대로 이름 붙이는 값이므로 마음대로 써도 됩니다. (이 name은 메모리에서 내부적으로 forces Map의 key값이 될 뿐입니다)
  (<code>simulation.force(&quot;중력&quot;, d3.forceManyBody())</code> 이렇게 해도 됨)
  하지만 공식문서에서 charge, center, link 와 같은 이름을 사용하기때문에 어느정도 저런 명칭을 사용하는 암묵적인 약속(?)은 있는 듯 합니다.</p>
</li>
<li><p><code>simulation.on(typenames, [listener])</code>
  typenames(<code>&quot;tick&quot;</code> 혹은 <code>&quot;end&quot;</code>)에 해당하는 이벤트에 대한 리스너를 등록합니다.
  <code>tick</code> : 시뮬레이션 내부 타이머의 틱마다 발생합니다.
  <code>end</code> : 시뮬레이션 내부 타이머의 틱이 종료될 때 발생합니다.
  <code>simulation.on(&quot;tick&quot;, callback)</code>을 이용하여, 부드러운 애니매이션을 표현하는게 가능해집니다. 노드의 좌표가 tick마다 조금씩 변경되면서 x,y 속성이 계산되고, 이 때마다 node, links를 그리면 부드러운 애니매이션이 구현되는 것입니다.</p>
</li>
</ul>
<h3 id="nodes-links-data-set">nodes, links data-set</h3>
<p>이제 node에 직접 x, y를 설정하거나 links를 전처리하지 않아도 됩니다.</p>
<pre><code class="language-js">let nodes = [
  { name:&quot;ye&quot; },
  { name:&quot;jun&quot; },
  { name:&quot;mi&quot; },
  { name:&quot;sung&quot; },
]
let links = [
  { source:&quot;ye&quot;, target:&quot;jun&quot; },
  { source:&quot;jun&quot;, target:&quot;mi&quot; },
  { source:&quot;mi&quot;, target:&quot;sung&quot; },
  { source:&quot;sung&quot;, target:&quot;jun&quot; },
]</code></pre>
<h3 id="data-binding-attribute-정의">data-binding, attribute 정의</h3>
<p>node, link selection에 데이터를 바인딩하고, 속성을 정의하는 로직은 기존 방식과 동일합니다.</p>
<pre><code class="language-js">const node = 
      d3.select(&quot;#node&quot;)
        .selectAll(&quot;g&quot;)
        .data(nodes)
        .join(&quot;g&quot;)
        .each(function(d) {
          d3.select(this)
            .append(&quot;circle&quot;)
            .attr(&quot;r&quot;, 5)
            .style(&quot;fill&quot;, &quot;red&quot;);
          d3.select(this)
            .append(&quot;text&quot;)
            .text(d =&gt; d.name);
      })

  const link = 
        d3.select(&quot;#link&quot;)
          .selectAll(&quot;line&quot;)
          .data(links)
          .join(&quot;line&quot;)
          .attr(&quot;stroke&quot;, &quot;black&quot;);

function drawNodes(){
  node.attr(&quot;transform&quot;, d =&gt;&quot;translate(&quot;+[d.x, d.y]+&quot;)&quot; );
}

function drawLines() {
  link
    .attr(&quot;x1&quot;, d =&gt; d.source.x)
    .attr(&quot;y1&quot;, d =&gt; d.source.y)
    .attr(&quot;x2&quot;, d =&gt; d.target.x)
    .attr(&quot;y2&quot;, d =&gt; d.target.y)

}</code></pre>
<h3 id="simulation-객체를-이용한-노드-좌표계산-및-nodes-links-매핑">simulation 객체를 이용한 노드 좌표계산 및 nodes-links 매핑</h3>
<pre><code class="language-js">d3.forceSimulation(nodes)
  .force(&#39;charge&#39;, d3.forceManyBody().strength(-200)) // 1️⃣
  .force(&#39;center&#39;, d3.forceCenter(250, 250)) // 2️⃣
  .force(&#39;link&#39;, d3.forceLink(links).id(d =&gt; d.name)) // 3️⃣
  .on(&quot;tick&quot;, () =&gt; {
    drawNodes();
    drawLines();
}); // 4️⃣</code></pre>
<p>1️⃣ 노드간의 중력을 정의합니다. default값은 -30이며, strength() 메서드를 이용하여 힘의 크기를 정의할 수 있습니다. 음수이면 척력, 양수이면 인력을 의미합니다.
2️⃣ viewport에서 그래프의 중앙 좌표를 설정합니다.
3️⃣ nodes와 매핑될 links 배열을 넘겨, 매핑된 결과 생성합니다. 이 links는 <code>source</code>, <code>target</code> 을 속성으로 가지는 객체의 배열입니다. id() 메서드를 통해 node의 어느 속성을 식별자로 가질지 설정할 수 있습니다. (설정하지않으면 node의 index로 매핑됩니다)
4️⃣ simulation tick마다 실행할 함수를 정의합니다.</p>
<h3 id="코드-실행화면">코드 실행화면</h3>
<p>!codepen[yeynii/embed/rNrVzgN?default-tab=js%2Cresult]</p>
<p>그럼 이렇게 노드 좌표도 자동으로 계산해주면서, 꿈틀거리는(‼️) 네트워크 차트가 완성됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[d3로 동적인 네트워크 차트 그리기 (2) - D3.js - selections & join]]></title>
            <link>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-2-D3.js-selections</link>
            <guid>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-2-D3.js-selections</guid>
            <pubDate>Tue, 20 Dec 2022 08:55:43 GMT</pubDate>
            <description><![CDATA[<h2 id="d3-selections">d3-selections</h2>
<p>selections는 data 기반의 DOM 변형객체입니다.
<code>d3.select</code>, <code>d3.selectAll</code>을 사용하면 html과 svg 요소를 선택하는 selection 객체를 반환합니다.</p>
<p><code>d3.select(selector)</code></p>
<p>selector에 해당하는 첫번째 element와 매칭됩니다.</p>
<p><code>d3.selectAll(selector)</code></p>
<p>selector에 해당하는 모든 element와 매칭됩니다.</p>
<p>여기서 selector는 css에서의 selector string 혹은 해당 파라미터 자체를 의미합니다.</p>
<p><strong><code>d3.select()</code> source</strong></p>
<pre><code class="language-jsx">import {Selection, root} from &quot;./selection/index.js&quot;;

export default function(selector) {
  return typeof selector === &quot;string&quot;
      ? new Selection([[document.querySelector(selector)]], [document.documentElement])
      : new Selection([[selector]], root);
}</code></pre>
<p><strong><code>d3.selectAll()</code> source</strong></p>
<pre><code class="language-jsx">export default function(selector) {
  return typeof selector === &quot;string&quot;
      ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
      : new Selection([array(selector)], root);
}</code></pre>
<p>⇒ 코드 내부적으로 string이 아닌 파라미터가 들어오면 그 파라미터 자체를 select</p>
<p>따라서 리액트에서 다음과 같이 useRef를 이용하여 돔요소를 select할 수 있습니다.</p>
<pre><code class="language-jsx">function App() {
  const svgRef = useRef();

  useEffect(() =&gt; {
    const p = d3
      .select(svgRef.current)
  }, []);

  return (
    &lt;div&gt;
      &lt;svg ref={svgRef} /&gt;
    &lt;/div&gt;
  );
}</code></pre>
<h2 id="join">join</h2>
<p><code>selection.join(enter[, update][, exit])</code>
selection 객체에서 사용할 수 있는 메서드로, data를 기반으로 element를 추가/수정/변경합니다.</p>
<p>join 함수를 사용하는 방법은 두가지가 있는데, 1️⃣파라미터로 string을 넘기거나 2️⃣파라미터로 enter, update, exit 콜백 함수를 넘기는 방법입니다.</p>
<pre><code class="language-js">svg.selectAll(&quot;circle&quot;)
  .data(data)
  .join(&quot;circle&quot;)</code></pre>
<p>위 코드는 아래코드의 축약형입니다.</p>
<pre><code class="language-js">svg.selectAll(&quot;circle&quot;)
  .data(data)
  .join(
    enter =&gt; enter.append(&quot;circle&quot;),
    update =&gt; update,
    exit =&gt; exit.remove()
  )</code></pre>
<p><code>enter</code> : data개수 &gt; dom개수여서, 남아도는 data에 해당하는 selection을 처리하는 방법을 정의
<code>update</code> : data에 대응하는 dom요소가 존재해서, 해당 data selection을 업데이트하는 방법을 정의
<code>exit</code> : data개수 &lt; dom개수여서, 사라진 data selection을 처리하는 방법을 정의</p>
<h2 id="중요-d3select는-추후-생성변경삭제될-element를-가리킬-수-있다">(중요) d3.select는 추후 생성/변경/삭제될 element를 가리킬 수 있다.</h2>
<p>document.querySelectorAll 은 이미 존재하는 element 배열만을 선택하여 반환하지만, d3.selectAll은 현재 매치되는 요소가 존재하지 않으면 빈 <code>Selection</code> 객체를 반환하게 되고, 이 Selection 객체는 추후 binding되는 data와 joining할 element-type에 해당하는 element들로 채워질 가능성이 있습니다.</p>
<p>즉, 지금은 selector에 해당하는 요소가 없더라도 데이터를 binding, joining 하면서 해당 요소를 생성/삭제할 수 있습니다.</p>
<p>예를들어, 다음과 같은 비어있는 svg 태그와 array 가 주어진다면 각 체이닝 시점별 반환 selection은 다음과 같습니다.</p>
<p><strong>html</strong></p>
<pre><code class="language-html">&lt;svg&gt;
&lt;/svg&gt;</code></pre>
<p><strong>js</strong></p>
<pre><code class="language-js">array = [1,2,3]

d3.select(&quot;svg&quot;) //1
  .selectAll(&quot;circle&quot;) // 2
  .data(array) //3
  .join(&quot;circle&quot;) //4; </code></pre>
<ol>
<li><p>container 역할을 할 element를 가리키는 Selection을 반환합니다.</p>
</li>
<li><p>데이터 배열의 요소와 join될 엘리먼트 타입을 선택합니다. 현재는 해당 엘리먼트 타입(circle)에 매치되는 요소가 없으므로, 비어있는 NodeList를 가리키는 Selection을 반환합니다. 
<img src="https://velog.velcdn.com/images/say_ye/post/3787bcd0-4752-4c04-b943-b3b16154f357/image.png" alt=""></p>
</li>
<li><p>join될 data array를 정의합니다. data의 변화를 나타내는<code>_enter</code>, <code>_exit</code> 프로퍼티에 data가 바인딩된 EnterNode 배열이 있는 Selection을 반환합니다.
<img src="https://velog.velcdn.com/images/say_ye/post/861276ee-096e-43ac-9f1e-c3525b85940f/image.png" alt=""></p>
</li>
<li><p>실제 문서의 엘리먼트 타입으로 요소로 생성/변경/삭제하고, 이를 가리키는 Selection을 반환합니다.
<img src="https://velog.velcdn.com/images/say_ye/post/e895f4df-e231-4771-a171-94f2d9f977b3/image.png" alt=""></p>
</li>
</ol>
<p>실행 후 돔은 다음과 같이 변화됩니다.</p>
<pre><code class="language-html">&lt;svg&gt;
  &lt;circle/&gt;
  &lt;circle/&gt;
  &lt;circle/&gt;
&lt;/svg&gt;</code></pre>
<p>이처럼 binding되는 data의 변화에 따라 svg 요소를 생성/변경/제거할 수 있습니다.
d3가 왜 data-driven documents인지 알 수 있는 대목입니다.</p>
<h2 id="간단한-네트워크-차트-그려보기">간단한 네트워크 차트 그려보기</h2>
<p>위에서 알아본 selections, data-join을 이용하여 간단한 네트워크 차트를 만들어봅시다.</p>
<h3 id="nodes-links-데이터-정의">nodes, links 데이터 정의</h3>
<p>우선 네트워크 차트를 그리기 위해서는 각 노드와 간선의 정보가 필요합니다.
이 데이터들을 각각 다음과 같이 <code>nodes</code>, <code>links</code> 로 정의해보겠습니다.</p>
<pre><code class="language-js">let nodes = [
  { x:100, y:100, name:&quot;ye&quot; },
  { x:200, y:300, name:&quot;jun&quot; },
  { x:300, y:200, name:&quot;mi&quot; },
  { x:200, y:400, name:&quot;sung&quot; },
]

let links = [
  { source:&quot;ye&quot;, target:&quot;jun&quot; },
  { source:&quot;jun&quot;, target:&quot;mi&quot; },
  { source:&quot;mi&quot;, target:&quot;sung&quot; },
  { source:&quot;sung&quot;, target:&quot;jun&quot; },
]</code></pre>
<h3 id="links-nodes-매핑-전처리">links-nodes 매핑 전처리</h3>
<p>그리고 각 link의 source, target을 다시 node로 매핑하는 전처리가 필요합니다.</p>
<pre><code class="language-js">links = links.map(link =&gt;
    ({
      source: nodes[nodes.findIndex(node =&gt; link.source === node.name)], 
      target: nodes[nodes.findIndex(node =&gt; link.target === node.name)]
    })
  )</code></pre>
<p>나중에 사용할 <code>d3.forceSimulation()</code> 의 nodes, links 데이터 구조와 mapping을 모방한 방식입니다.
(솔직히 개인적으로는 이 방식이 좋은지는 잘 모르겠습니다.
nodes가 Map 타입이었으면 이터러블하면서도 매핑이 더 효율적이었을 것 같고, links의 source, target type이 string -&gt; node로 변경되는 부분때문에 ts에서 type 정의할 때 살짝 애를 먹었습니다. 처음부터 객체였으면 더 수월했을 것 같습니다.)</p>
<h3 id="html-container-tag-정의">html container tag 정의</h3>
<p>html쪽 태그에서는 svg와 그 내부에 link그룹, node그룹을 표현할 g tags를 정의합니다.</p>
<pre><code class="language-html">&lt;svg width=&quot;500&quot; height=&quot;500&quot;&gt;
  &lt;g id=&quot;link&quot;/&gt;
  &lt;g id=&quot;node&quot;/&gt;
&lt;/svg&gt;</code></pre>
<h3 id="nodes-draw">nodes draw</h3>
<p>node는 g elements(text, circle을 그룹핑하기 위함)로 구성합니다.</p>
<pre><code class="language-js">const node = 
      d3.select(&quot;#node&quot;)
        .selectAll(&quot;g&quot;)
        .data(nodes)
        .join(&quot;g&quot;)
        .each(function(d) {
          d3.select(this)
            .append(&quot;circle&quot;)
            .attr(&quot;r&quot;, 5)
            .style(&quot;fill&quot;, &quot;red&quot;);
          d3.select(this)
            .append(&quot;text&quot;)
            .text(d =&gt; d.name);
        })

function drawNodes(){
  node.attr(&quot;transform&quot;, d =&gt;&quot;translate(&quot;+[d.x, d.y]+&quot;)&quot; );
}</code></pre>
<p>여기서 주의할 점은 each내부 함수에서 this(각 그룹노드를 가리키는)를 사용하고 있기때문에, 이 내부함수를 화살표 함수가 아닌 함수 선언식으로 작성해야합니다.</p>
<p><strong>selection.each</strong> <a href="https://github.com/d3/d3-selection/blob/main/src/selection/each.js">소스코드</a>를 보면, callback함수에 각 node를 this로 바인딩해서 호출하는 구문을 확인할 수 있습니다.</p>
<pre><code class="language-js">// each.js
export default function(callback) {

  for (var groups = this._groups, j = 0, m = groups.length; j &lt; m; ++j) {
    for (var group = groups[j], i = 0, n = group.length, node; i &lt; n; ++i) {
      if (node = group[i]) callback.call(node, node.__data__, i, group);
    }
  }

  return this;
}</code></pre>
<p>하지만 화살표 함수는 this를 가질 수 없기때문에, 자신을 둘러싼 scope의 this를 가리키게 됩니다. 그래서 call, bind, apply와 같이 this를 바인딩하는 methods도 이용할 수 없습니다.</p>
<h3 id="links-draw">links draw</h3>
<p>links는 line elements로 구성합니다.</p>
<pre><code class="language-js">const link = 
      d3.select(&quot;#link&quot;)
        .selectAll(&quot;line&quot;)
        .data(links)
        .join(&quot;line&quot;)
        .attr(&quot;stroke&quot;, &quot;black&quot;);

function drawLines() {
  link
    .attr(&quot;x1&quot;, d =&gt; d.source.x)
    .attr(&quot;y1&quot;, d =&gt; d.source.y)
    .attr(&quot;x2&quot;, d =&gt; d.target.x)
    .attr(&quot;y2&quot;, d =&gt; d.target.y)
}</code></pre>
<h3 id="실행구문">실행구문</h3>
<pre><code class="language-js">drawNodes();
drawLines();</code></pre>
<p>코드 전문과 실행화면은 codepen을 통해서 확인 가능합니다.
!codepen[yeynii/embed/dyjoMNZ?default-tab=js%2Cresult]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[d3로 동적인 네트워크 차트 그리기 (1) - D3.js란?]]></title>
            <link>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-1-D3.js%EB%9E%80</link>
            <guid>https://velog.io/@say_ye/d3%EB%A1%9C-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%B0%A8%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B8%B0-1-D3.js%EB%9E%80</guid>
            <pubDate>Sun, 18 Dec 2022 13:22:06 GMT</pubDate>
            <description><![CDATA[<p>굉장히 오랜만의 포스팅이네요.
그동안 놀았던건 아니고.. 부스트캠프 일정이 엄청 바빴던터라 못올리고 있었습니다....🥲</p>
<p>제가 부스트캠프 팀프로젝트로 했던 <strong>논문 인용관계 시각화</strong> 서비스입니다.
이제 자유의 몸이 되었으니, 위 프로젝트에서 논문 데이터를 어떻게 네트워크 차트로 시각화 했는지 그 과정들을 조금씩 기록해 보겠습니다.</p>
<h2 id="d3js란">D3.js란?</h2>
<blockquote>
<p>Data-driven-documents. 맞춤형의, 인터랙티브한 charts/maps를 웹에 그리기위해 사용되는 자바스크립트 라이브러리</p>
</blockquote>
<h3 id="특징">특징</h3>
<ul>
<li><strong>data-driven modification of HTML and SVG elements</strong>
data 기반으로 html, svg element를 그려 낼 수 있습니다.    </li>
<li><strong>scale functions</strong>
data values ⇒ visual values로 스케일링 하는 함수를 제공합니다.</li>
<li><strong>loading and transforming data (e.g. CSV data)</strong>
csv → js array convert 기능을 제공합니다.    </li>
<li><strong>helpers for generating complex charts such as treemaps, packed circles and networks</strong>
treemaps, packed circles, network graphs and geographic maps 등의 복잡한 차트를 building 할 수 있는 block들을 제공합니다.</li>
<li><strong>a powerful transition system for animating between different chart states</strong>
chart states의 변화를 부드러운 애니매이션으로 표현할 수 있다. 요소가 어떻게 나타날지, 이동할지, 사라질지를 제어할 수 있는 강력하고 간편한 transition 기능을 제공합니다.    </li>
<li><strong>powerful user interaction support, including panning, zooming and dragging</strong>
panning, zooming과 같은 상호작용 기능을 지원합니다.</li>
</ul>
<h3 id="d3를-사용한-이유">D3를 사용한 이유</h3>
<ul>
<li>D3는 Chart.js나 Highcharts와 같이 이미 만들어진 차트를 제공하는 라이브러리가 아닌, 더 작은 단위의 블럭들을 조합시켜 커스텀 차트를 만드는 저수준 라이브러리입니다.</li>
<li>제가 만들고자 했던 네트워크 차트는 동적으로 데이터가 추가되고, 다양한 사용자 인터랙션이 필요했기에 세부적인 기능을 조절하기 위해서는 D3를 사용하는 것이 적합하다고 판단했습니다.</li>
<li>D3가 제공하는 메서드를 이용하면 그래프를 zooming, dragging하는 기능을 아주 쉽게 구현할 수 있습니다.</li>
</ul>
<h3 id="d3를-사용할때-주의해야-할-점">D3를 사용할때 주의해야 할 점</h3>
<ul>
<li>React 베이스에서 D3를 사용해야 했는데, 리액트 렌더링과 d3 렌더링이 같이 일어나면서 각자의 생명주기가 엉켜 사이드이펙트가 발생할 수 있습니다. 어느 시점에 d3에 렌더링을 위임할지, 어떤 state까지 리액트에서 관리할지 잘 고민해서 설계해야 합니다.</li>
<li>매번 네트워크 node와 line의 좌표를 계산하는데 시간이 많이 걸린다고 하는데, 이 계산로직을 어디서, 어떻게 처리할지에 대한 고민이 필요합니다.</li>
</ul>
<p>다양한 방법이 있겠지만.. 저의 경우는 web-worker를 이용하여 서브스레드에서 node, line 좌표 계산 + 메인스레드에서 렌더링 하는 방식으로 계산로직/렌더링로직을 분리해서 병렬처리하는 방법으로 성능개선을 했습니다. 추후 포스팅에서 좀 더 자세히 다뤄보겠습니다.</p>
<h2 id="svg-d3-찍어먹기">svg, D3 찍어먹기</h2>
<p>여기서 끝내기는 좀 아쉬워서.. 차트구현 내용은 아니지만,
제가 로딩스피너로 넣었던 <strong>위상이 변하는 달모양 spinner</strong> 만드는 과정을 알아보며 svg랑도 좀 친해질겸, D3를 찍먹 해봅시다.</p>
<h3 id="svg-하위에서-사용한-태그들">svg 하위에서 사용한 태그들</h3>
<ul>
<li><p><code>&lt;defs&gt;</code>
추후 사용될 그래픽 객체를 저장해두는 태그</p>
</li>
<li><p><code>&lt;pattern&gt;</code>
svg 영역을 채울 패턴을 정의하는 태그
달 표면 그림을 패턴으로 정의하기위해 사용</p>
</li>
<li><p><code>&lt;g&gt;</code>
svg elements를 그룹화하는 태그</p>
</li>
<li><p><code>&lt;circle&gt;</code>
원을 그리는 태그</p>
</li>
<li><p><code>&lt;path&gt;</code>
선을 그리는 태그
<code>d</code> 속성으로 선의 경로를 표현할 수 있습니다. 이 속성에 다양한 형태의 선을 정의하여 그릴 수 있는데, 저는 제가 사용한 두가지 속성 명령어에 대해서만 설명하겠습니다. </p>
<ul>
<li><code>M</code> <code>x</code> <code>y</code>
좌표 x, y로 이동합니다.</li>
<li><code>A</code> <code>rx</code> <code>ry</code> <code>x축 회전각</code> <code>큰 호 플래그</code> <code>쓸기 방향 플래그</code> <code>x</code> <code>y</code>
현재 좌표와 (x, y) 두 점을 지나면서 x축 반지름rx, y축 반지름ry, x축 회전각만큼 기울어진 타원호를 그리며 이동합니다.
이 때, 4가지 경우의 수가 생기는데, 이걸 특정해주는게 두개의 플래그입니다.
<code>큰 호 플래그</code> - 0: 중심각이 180도 미만(작은 호) 1: 중심각이 180도 이상(큰 호)
<code>쓸기 방향 플래그</code> - 0: 음각(반시계방향), 1: 양각(시계방향)
<img src="https://velog.velcdn.com/images/say_ye/post/e1d71a33-7a98-4cd3-b969-b9b47b63911b/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="구현방법">구현방법</h3>
<pre><code class="language-jsx">&lt;circle cx=&quot;50&quot; cy=&quot;50&quot; r=&quot;49&quot; fill=&quot;black&quot; /&gt; &lt;!-- 🌑 --&gt;
&lt;path ref={pathRef} d=&quot;...&quot; fill=&quot;white&quot; /&gt; &lt;!-- 밝은부분 --&gt;
&lt;circle cx=&quot;50&quot; cy=&quot;50&quot; r=&quot;50&quot; fill=&quot;url(#image11)&quot; /&gt; &lt;!-- 반투명한 달 표면 레이어 --&gt;</code></pre>
<p><strong>어두운부분(원)</strong> ⇒ <strong>밝은부분(반원 + 타원 or 반원 - 타원)</strong> ⇒ <strong>달표면 레이어</strong>를 차례로 쌓은다음, path의 d 속성(밝은부분의 궤적)을 100ms마다 변경하는 방법으로 구현했습니다.
우선 달의 밝은부분을 그리기 위해서는 원호, 타원호 궤적 2개가 필요합니다.</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/7851a2eb-fe85-4497-ac51-cd4b8b31ecb6/image.png" alt=""></p>
<p>원호, 타원호 두개와 쓸기방향 플래그를 잘 바꿔가면서 그려주면 되겠군요.</p>
<p><code>M x y</code> <code>A rx ry x-axis-rotation large-arc-flag</code> sweep-flag <code>x y</code> <code>A</code> 안쪽타원 rx <code>ry x-axis-rotation large-arc-flag</code> sweep-flag <code>x y</code></p>
<p><code></code> : 고정값들</p>
<p>접선좌표, 바깥쪽 원의 반지름, 안쪽타원의 ry는 고정값이고, 반원과 안쪽타원의 larg-arc-flag는 모두 0으로 고정이 가능합니다.(180도 궤적이니)
따라서, 반원의 sweep-flag, 안쪽타원의 rx, sweep-flag 세가지만 계산해주면 됩니다.</p>
<p>안쪽 타원의 rx 는 <code>r * cos(t)</code> (아래그림참고),  쓸기 방향 플래그만 🌑 -&gt; 🌓 -&gt; 🌕 -&gt; 🌗 이 시점에 잘 바꿔서 그리면 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/f4dec105-914e-4ec2-84af-671a45f1090a/image.png" alt=""></p>
<p>그림실력이 이게 최선이네요... 저 두꺼운 선이 구의 입체면이라고 생각해주세요.</p>
<p>최종적으로, path를 계산하는 함수는 다음과 같이 만들어졌습니다.</p>
<pre><code class="language-js">const calculateMoonLightPath = (radian: number) =&gt; {
  return `M 50 0
            A 50 50 0 0 ${Math.floor(radian / Math.PI) % 2} 50 100
            A ${50 * Math.cos(radian)} 50 0 0 ${Math.floor((radian / Math.PI) * 2) % 2} 50 0`;
};</code></pre>
<h3 id="코드-전문">코드 전문</h3>
<pre><code class="language-tsx">import * as d3 from &#39;d3&#39;;
import { useEffect, useRef } from &#39;react&#39;;
import styled from &#39;styled-components&#39;;
import theme from &#39;../style/theme&#39;;

const calculateMoonLightPath = (radian: number) =&gt; {
  return `M 50 0
            A 50 50 0 0 ${Math.floor(radian / Math.PI) % 2} 50 100
            A ${50 * Math.cos(radian)} 50 0 0 ${Math.floor((radian / Math.PI) * 2) % 2} 50 0`;
};

const MoonLoader = () =&gt; {
  const pathRef = useRef&lt;SVGPathElement&gt;(null);

  useEffect(() =&gt; {
    let radian = Math.PI;
    const timer = d3.interval(() =&gt; {
      d3.select(pathRef.current).attr(&#39;d&#39;, calculateMoonLightPath(radian));
      radian += Math.PI / 10;
    }, 100);
    return () =&gt; timer.stop();
  }, []);

  return (
    &lt;MoonContainer&gt;
      &lt;svg width=&quot;50&quot; height=&quot;50&quot; viewBox=&quot;0 0 100 100&quot; style={{ filter: &#39;url(#inset-shadow)&#39; }}&gt;
        &lt;defs&gt;
          &lt;pattern id=&quot;image11&quot; x=&quot;0&quot; y=&quot;0&quot; patternUnits=&quot;userSpaceOnUse&quot; height=&quot;100&quot; width=&quot;100&quot;&gt;
            &lt;image x=&quot;0&quot; y=&quot;0&quot; height=&quot;100&quot; width=&quot;100&quot; xlinkHref=&quot;https://www.icalendar37.net/lunar/api/i.png&quot;&gt;&lt;/image&gt;
          &lt;/pattern&gt;
        &lt;/defs&gt;
        &lt;g&gt;
          &lt;circle cx=&quot;50&quot; cy=&quot;50&quot; r=&quot;49&quot; stroke=&quot;0&quot; fill={theme.COLOR.primary4} /&gt;
          &lt;path ref={pathRef} fill={theme.COLOR.offWhite} /&gt;
          &lt;circle cx=&quot;50&quot; cy=&quot;50&quot; r=&quot;50&quot; strokeWidth=&quot;0&quot; fill=&quot;url(#image11)&quot; /&gt;
        &lt;/g&gt;
      &lt;/svg&gt;
    &lt;/MoonContainer&gt;
  );
};

const MoonContainer = styled.div`
  text-align: center;
`;

export default MoonLoader;</code></pre>
<ul>
<li><p><code>d3.select(selector)</code>
selector가 string이면 해당 selector와 매칭되는 첫번째 element와 매칭되며, string이 아니면 파라미터 그 자체(여기서는 path 돔요소)와 매칭되는 Selection을 반환합니다.</p>
</li>
<li><p><code>Selection.attr(&quot;d&quot;, string)</code>
선택요소의 d 속성을 변경합니다.</p>
</li>
<li><p><code>d3.interval(callback, delay)</code>
주어진 delay시간마다 함수를 반복해서 실행합니다.
callback : (elapsed) ⇒ void;
delay : callback을 수행시킬 interval time.</p>
</li>
</ul>
<p>참고) 달의 위상은 ← 방향으로 변해야합니다. 거꾸로 돌리지 않게 조심.... (이거 때문에 유튜브 중등과학 시청함)</p>
<p>위의 방법으로 리액트 + D3코드로 path를 100ms마다 변형시켰습니다
<img src="https://velog.velcdn.com/images/say_ye/post/b5608ab2-d87d-4585-9b2b-f147a2c9cbb6/image.gif" alt=""></p>
<p>그럼.. 잘 돌아갑니다 ^^</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[네부캠에서 상을 받았습니다.]]></title>
            <link>https://velog.io/@say_ye/%EB%B6%80%EC%BA%A0%EC%97%90%EC%84%9C-%EC%83%81%EC%9D%84-%EB%B0%9B%EC%95%98%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@say_ye/%EB%B6%80%EC%BA%A0%EC%97%90%EC%84%9C-%EC%83%81%EC%9D%84-%EB%B0%9B%EC%95%98%EC%8A%B5%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Tue, 06 Sep 2022 15:10:37 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/say_ye/post/c349432e-7e06-44a6-aa6e-e4c429ef0a19/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/de90a53e-7268-4596-bf18-85d529524425/image.png" alt=""></p>
<p>상이라고 하면 좀 거창하긴하지만... 부캠배 줌 배경화면 공모전에서 수상을 했습니다..ㅋㅋ
퀄리티로는 자신이 없었기 때문에 국뽕tv 컨셉으로 특별상 전형을 노려보았구요.. 영광스럽게도 받게 되었네요 
원래 &#39;실제상황&#39; 옆에 &#39;아님&#39; &lt;- 글자가 있는데 사진에서는 깨져서 안보이네요. 허위사실 유포죄로 잡혀간다면 삭제하겠습니다
부상이 따로 있는건 아니고 그냥 기분이가 좋다. 부캠 인스타에 박제될 수 있다 정도..? 그리고 몇몇분들이 웃어주셔서 행복했습니다. 
그럼 이만 마저 슬기로운 부캠생활 보내고 오겠습니다. 아좌자 ~!</p>
<p>멤버십 1주일 후기 : 챌린지에 절여져서 그런가.. 생각보다 할만함 <del>그렇지만 다한건 아님</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] V8 엔진의 메모리 모델]]></title>
            <link>https://velog.io/@say_ye/JS-V8-%EC%97%94%EC%A7%84%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@say_ye/JS-V8-%EC%97%94%EC%A7%84%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Sun, 24 Jul 2022 07:25:08 GMT</pubDate>
            <description><![CDATA[<h1 id="v8-엔진의-메모리-모델">V8 엔진의 메모리 모델</h1>
<h2 id="메모리-구조">메모리 구조</h2>
<p><img src="https://velog.velcdn.com/images/say_ye/post/78fef453-2605-4e1d-990c-94469bcae3f6/image.png" alt="">
V8 엔진의 메모리에서 실행되고 있는 프로그램을 <strong>Resident Set</strong>이라고 하며 크게 <strong>Heap memory</strong>와 <strong>Stack</strong>으로 나누어집니다.</p>
<h3 id="heap-memory">Heap memory</h3>
<p>참조형 데이터의 실체와 동적 데이터가 저장되는 장소입니다.</p>
<ul>
<li><p><code>New space</code> (Young generation)
최근에 만들어진 데이터가 저장되는 장소이며 <code>Minor GC</code>의 타겟이 됩니다. Old 영역에 비해 매우 작아 가비지 컬렉션이 매우 빈번하게 발생됩니다.</p>
</li>
<li><p><code>Old space</code> (Old generation)
New 영역에서 살아남은 객체들이 이동되는 곳입니다. 이후에는 <code>Major GC</code>에 의해 관리됩니다.
<code>Old pointer space</code>(살아남은 객체들이 저장), <code>Old data space</code>(살아남은 리터럴이 저장) 부분으로 나눠집니다.</p>
</li>
<li><p><code>Large object space</code>
다른 영역으로는 감당하지 못하는 매우 큰 객체들이 저장되어 있습니다. 가비지 컬렉터에 의해 이동되지 않습니다.</p>
</li>
<li><p><code>Code space</code>
컴파일러의 의해 컴파일된 코드가 저장되는 장소입니다. 유일하게 실행가능한 데이터가 저장되어있으며, Large object space에 할당 될 수도 있습니다.</p>
</li>
</ul>
<h3 id="stack">Stack</h3>
<p>변수, 함수, 클래스, 함수 프레임과 같은 정적 데이터가 저장됩니다.
함수, 클래스는 미리 스택에 올려놓으며, 변수는 해당 스코프를 만날 때 스택에 올립니다.
스코프를 벗어나면 스택에 올라와있던 변수, 함수, 매개변수등을 해제합니다.
<strong>함수가 종료되어도 아직 외부에서 참조되고 있는 지역변수가 있다면 스택이 아닌 힙으로 이동되어 파기되지 않습니다. 이것이 <code>클로저</code>입니다.</strong></p>
<h2 id="메모리-관리">메모리 관리</h2>
<ul>
<li><p>Minor GC (Scanvenger)<br><img src="https://velog.velcdn.com/images/say_ye/post/e3f6628b-b01f-4f19-8bf1-0fd680662e7f/image.png" alt="">
힙의 <code>New</code> 영역을 관리합니다. 작은 크기의 space를 매우 잦은 주기로 순회합니다.
두 작은 영역으로 나누어져 있고 <code>From-영역</code>, <code>To-영역</code>으로 부릅니다.<br>  <strong>[동작 방식]</strong>
  1️⃣ 새로운 데이터를 <code>From-영역</code>의 빈 공간에 할당하려고 시도합니다.
  2️⃣ 할당할 수 없다면, 스케벤져를 실행시켜 살려야 할 데이터만 <code>From-영역</code> → <code>To-영역</code>으로 이동시킵니다. (이 과정에서 <code>To-영역</code>이 자동으로 압축되어 단편화를 줄입니다.)
  3️⃣ <code>From-영역</code>에 남아있는 데이터를 제거합니다.
  4️⃣ 이제 <code>To-영역</code>을 <code>From-영역</code>처럼 사용합니다.
  5️⃣ 두번의 <code>Minor GC</code> 과정에서 생존한 객체들은 <code>Old 영역</code> 으로 이동합니다.</p>
</li>
<li><p>Major GC
힙의 <code>Old</code> 영역를 관리합니다. <code>Minor GC</code> 보다 긴 주기로 동작합니다.    </p>
<ul>
<li><p>초기의 자바스크립트 : <code>참조 카운팅</code> 방식을 사용했습니다. 누구도 참조하지 않는 데이터를 가비지로 취급합니다.
  이 방식은 <code>순환참조</code>가 발생하는 데이터를 반환하지 못하는 취약점이 존재합니다. 이 경우 <code>메모리 누수</code>가 발생합니다.</p>
</li>
<li><p>최근의 자바스크립트 : <code>Mark Sweep</code> 방식을 채택하여 Mark - Sweep - Compact(디스크 조각 모음) 과정으로 메모리를 관리합니다. Root에서 닿을 수 없는 데이터를 가비지로 취급합니다. <code>Root</code>에서 닿을 수 있는 데이터만 <code>Mark</code> 하고 그 외에는 <code>Sweep</code> 하는 방식입니다.<br><img src="https://velog.velcdn.com/images/say_ye/post/8c47104b-54e9-4b6b-b2a5-4c5f32765d61/image.png" alt="">
<code>Mark</code> : 힙 메모리를 방향 그래프로 간주해 <code>DFS</code> 방식으로 사용중인 객체를 식별합니다.
<code>Sweep</code> : 가비지 컬렉터가 힙 메모리를 순회하면서 활성 상태로 표시되지 않은 객체들의 메모리 주소를 기록합니다.
<code>Compact</code> : 단편화를 줄이기 위한 압축단계입니다.</p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[네이버 부스트캠프 7기 합격했습니다!!!]]></title>
            <link>https://velog.io/@say_ye/%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%ED%87%B4%EC%82%AC%ED%95%98%EA%B3%A0-%EB%B6%80%EC%8A%A4%ED%8A%B8-%EC%BA%A0%ED%94%84%EB%A1%9C-%EA%B0%91%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@say_ye/%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%ED%87%B4%EC%82%AC%ED%95%98%EA%B3%A0-%EB%B6%80%EC%8A%A4%ED%8A%B8-%EC%BA%A0%ED%94%84%EB%A1%9C-%EA%B0%91%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Wed, 13 Jul 2022 12:22:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/say_ye/post/600b3d16-97d3-4240-8c6e-8d27eb0d27da/image.png" alt=""></p>
<p>부스트캠프 선발 과정에 대한 짧은후기 남깁니다.
자세한 내용은 두루뭉술하게 적는점 양해 바랍니다.</p>
<h3 id="서류전형">서류전형</h3>
<p>여타 서류전형이 그렇듯이 주어진 몇 가지 문항에 답을 작성해야 하는데 저는 진정성을 강조했던 것 같습니다.
회사 다니는 거 현타왔던 날 잡고 새벽감성으로다가 구구절절 썼습니다.
솔직히 1년 전에는 적을 말이 없었는데, 5개월 독학 + 7개월 스타트업 굴러보니까 생기더라고요.</p>
<p>그리고 문항에서 언급한 내용을 증명할만한 자료가 있으면 제출하라고 하는데, 저는 그동안 노션에 스터디 정리해둔 거랑 블로그 같이 첨부했습니다.
첨부파일/링크 여부는 선택사항이라는데 솔직히 선발되려면 필수인 듯합니다. 그동안 했던 거 아무리 작은 거라도 쥐어짜 내서 제출하는 것을 추천해 드립니다.</p>
<h3 id="1차-코딩테스트">1차 코딩테스트</h3>
<p>빡 구현 + CS 였습니다.</p>
<h3 id="2차-코딩테스트">2차 코딩테스트</h3>
<p>빡!!!! 구현 이었습니다.
이정도 구현문제면 피지컬 싸움 아닌가 싶을정도로요.
혹시 내년에 지원하실 분들은 피지컬을 기릅시다 ...(?)</p>
<hr>
<p>이제 시작이네요.
멤버십 전환을 목표로 불태워봅시다 야호!!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 11725 트리의 부모 찾기]]></title>
            <link>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-11725-%ED%8A%B8%EB%A6%AC%EC%9D%98-%EB%B6%80%EB%AA%A8-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-11725-%ED%8A%B8%EB%A6%AC%EC%9D%98-%EB%B6%80%EB%AA%A8-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Thu, 16 Jun 2022 12:19:27 GMT</pubDate>
            <description><![CDATA[<p>문제링크
<a href="https://www.acmicpc.net/problem/11725">https://www.acmicpc.net/problem/11725</a></p>
<pre><code class="language-python">from collections import deque
import sys

input = sys.stdin.readline

n = int(input())

graph = list([] for _ in range(n+1))

for i in range(n-1):
  a, b = map(int, input().split())
  graph[a].append(b)
  graph[b].append(a)

rootNode = list([] for _ in range(n+1))
visited = [False] * (n + 1)
queue = deque([1])

while queue:
  current = queue.popleft()
  visited[current] = True
  for v in graph[current]:
    if not visited[v]:
      queue.append(v)
      rootNode[v] = current

for r in rootNode[2:]:
  print(r)</code></pre>
<ul>
<li>접근 방법 : BFS</li>
<li>시간 복잡도 : O(N)</li>
<li>배운점
<img src="https://velog.velcdn.com/images/say_ye/post/83dfd88a-89f7-4403-9a27-5e35c9ae5916/image.png" alt="">
밑의 제출에서는 <code>input()</code>, 위의 제출에서는 <code>sys.stdin.readline()</code>을 사용했는데, 시간이 10배 이상 차이가 났다.
파이썬의 <code>input()</code> 함수는 단순 입력뿐 아니라 1️⃣<strong>개행문자를 제거</strong>하고 2️⃣<strong>prompt message를 전달받아 출력</strong>하는 기능을 포함하고 있어 <code>sys.stdin.readline()</code>보다 시간이 더 오래걸린다고 한다.
그러니 여러줄의 입력을 받을 때는 반드시 <code>input()</code>대신 <code>sys.stdin.readline()</code> 을 사용하자.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] webpack 에 유용한 plugin 설정하기]]></title>
            <link>https://velog.io/@say_ye/JS-webpack-plugin-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@say_ye/JS-webpack-plugin-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 13 Jun 2022 06:44:58 GMT</pubDate>
            <description><![CDATA[<h2 id="plugin">plugin</h2>
<h3 id="html-webpack-plugin"><code>html-webpack-plugin</code></h3>
<blockquote>
<p>css 애셋, js파일을 포함한 html 파일을 생성합니다.</p>
</blockquote>
<p>CSS 애셋과 엔트리 포인트에 명시된 script를 html에 자동으로 추가합니다.
html 파일의 <code>&lt;head&gt;</code> 요소 안에서 css파일은 <code>&lt;link&gt;</code>, js파일은 <code>&lt;script&gt;</code> 태그로 포함합니다.</p>
<pre><code class="language-js">const HtmlWebpackPlugin = require(&#39;html-webpack-plugin&#39;);

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({ template: &#39;index.html&#39; })
  ]
}</code></pre>
<h3 id="mini-css-extract-plugin"><code>mini-css-extract-plugin</code></h3>
<blockquote>
<p>css 파일을 별도 파일로 추출합니다. css 코드가 포함된 js 파일 별로 css파일을 생성합니다.</p>
</blockquote>
<p>개발 모드에서는 해당 플러그인을 사용하지 않는 것이 좋습니다.
css를 수정할 때마다 css 파일을 추출하는 것 보다는 <code>style</code> 요소의 코드로 주입하는 것이 훨씬 빨리 작동하므로 <strong>개발모드</strong>에서는 <code>style-loader</code>를 사용하고, <strong>배포모드</strong>에서 <code>MiniCssExtractPlugin.loader</code>를 사용하는 것이 권장됩니다.</p>
<pre><code class="language-js">const MiniCssExtractPlugin = require(&#39;mini-css-extract-plugin&#39;);

/* 개발 모드 감지 */
const isDevMode = process.env.NODE_ENV.includes(&#39;dev&#39;);

const plugins = [];

/* 배포 모드인 경우 MiniCssExtractPlugin 추가 */
if (!isDevMode) {
  plugins.push(
    new MiniCssExtractPlugin({
      filename: &#39;[name].[contenthash].css&#39;,
      chunkFilename: &#39;[id].[contenthash].css&#39;,
    })
  );
}

module.exports = {
  /* 플러그인 설정 */  
  plugins,
  module: {
    rules: [
    /* 스타일 파일 로더 */
      {
        test: /\.(sa|sc|c)ss$/i,
        exclude: /node_modules/,
        use: [
          isDevMode ? &#39;style-loader&#39; : MiniCssExtractPlugin.loader,
          &#39;css-loader&#39;,
          &#39;sass-loader&#39;,
        ],
      },
    ],
  },

}</code></pre>
<h3 id="webpackdefineplugin"><code>webpack.DefinePlugin</code></h3>
<blockquote>
<p>모든 자바스크립트 코드에서 접근이 가능한 전역 변수를 선언합니다.</p>
</blockquote>
<p>전역변수를 지나치게 사용하면 글로벌 네임스페이스가 너무 많은 변수들로 오염되어 유지보수성을 저해하므로 반드시 필요한 상황에 제한적으로 사용해야합니다.
주로 전역에서 접근할 수 있는 환경변수를 설정할 때 씁니다.</p>
<p><code>dotenv</code> 로 <code>.env</code>에 선언한 환경 변수를 <code>process.env</code>를 세팅한 뒤에
<code>webpack.DefinePlugin</code> 을 사용하면 파일 어디에서든 <code>process.env</code>에 접근 할 수 있습니다.</p>
<pre><code class="language-js">const dotenv = require(&quot;dotenv&quot;);
const webpack = require(&#39;webpack&#39;);

/* .env 파일을 파싱한 객체가 리턴되어 process.env에 세팅 */
dotenv.config();

module.exports = {
  /* 파일 어디서든 process.env 라는 전역변수에 접근할 수 있도록 정의 */
  plugins: [
    new webpack.DefinePlugin({ &#39;process.env&#39;: JSON.stringify(process.env) })
  ]
}</code></pre>
<h3 id="interpolate-html-plugin"><code>interpolate-html-plugin</code></h3>
<blockquote>
<p>html 파일에서 사용할 변수를 설정할 수 있습니다.</p>
</blockquote>
<p>퍼블릭 경로와 환경변수를 <code>%PUBLIC_URL%</code>, <code>%MY_KEY%</code> 과 같은 형식으로 접근할 수 있도록 하는 예시입니다.</p>
<pre><code class="language-js">const InterpolateHtmlPlugin = require(&#39;interpolate-html-plugin&#39;);

module.exports = {
  plugins: [
    new InterpolateHtmlPlugin({ PUBLIC_URL: &#39;&#39;, MY_KEY: process.env.MY_KEY })
  ]
}</code></pre>
<h3 id="clean-webpack-plugin"><code>clean-webpack-plugin</code></h3>
<blockquote>
<p>webpack에 의해 빌드 된 결과물을 자동 정리합니다.</p>
</blockquote>
<pre><code class="language-js">const { CleanWebpackPlugin } = require(&#39;clean-webpack-plugin&#39;);

module.exports = {
  plugins: [
    new CleanWebpackPlugin({
        cleanOnceBeforeBuildPatterns: [
            &#39;**/*&#39;,
              /* dist 폴더 안의 모든 것을 지우도록 설정 */
            path.resolve(process.cwd(), &#39;dist/**/*&#39;),
        ],
    })
  ]
}</code></pre>
<hr>
<p>참고
<a href="https://yamoo9.gitbook.io/webpack">https://yamoo9.gitbook.io/webpack</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[네트워크] TCP/IP]]></title>
            <link>https://velog.io/@say_ye/HTTP-TCPIP</link>
            <guid>https://velog.io/@say_ye/HTTP-TCPIP</guid>
            <pubDate>Sun, 12 Jun 2022 18:48:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/say_ye/post/9b7e72d2-3068-42f8-9a36-3f95ad137815/image.png" alt="">
공부하면서 마주친적은 많은데 미뤄왔던 OSI 7계층입니다. 고작 사진 하나안에 알아야 할게 한가득 있어서 무서웠는데요..
이제 도망칠 곳이 없으므로 한 계층씩 도장깨기하는 심정으로 해치워보려고 합니다.</p>
<p>그래도 네트워크는 초기 설계때부터 지금까지도 본질적으로는 그대로인 부분이 많아 앞으로도 크게 안바뀐다고 합니다. 한번 배워두면 사골마냥 우려먹을 수 있다하니 숨참고 해보겠습니다.</p>
<p>오늘은 이 OSI 7계층에서 4계층에 속하는 TCP, 3계층에 속한 IP에 대해서 알아보겠습니다. </p>
<h1 id="tcpip">TCP/IP</h1>
<p>TCP와 IP가 층을 이루는 패킷 교환 네트워크 프로토콜의 집합입니다.
빈트 서프와 로버트 칸이 1973년경 처음 설계한 방식으로, 오늘날 인터넷상의 트래픽 대부분을 처리하는 프로토콜입니다.
전세계 모든 HTTP 통신은 TCP/IP를 통해 이루어집니다.</p>
<h2 id="ipinternet-protocol">IP(Internet Protocol)</h2>
<blockquote>
<p>전송 중인 정보에 대해 균일한 전송 매커니즘과 공통 형식을 정의합니다.</p>
</blockquote>
<ul>
<li>인터넷의 공통 매커니즘으로, 정보를 교환하기 위한 만국 공통어의 역할을 합니다. </li>
<li>신뢰성 없는(unreliable), 비연결형(connectionless) 패킷 전송 서비스를 제공합니다.
<em><strong>신뢰성 없는</strong> : 패킷이 정상적으로 전송되는 것을 보장하지 않음</em>
<em><strong>비연결형</strong> : IP 패킷이 자립적이며 다른 IP 패킷과 관계가 없음</em></li>
<li>상태를 관리하거나 기억하는 기능이 없습니다.</li>
<li>최대 크기는 약 65KB입니다. </li>
<li>최대 크기 이상의 IP패킷은 작은 덩어리로 분할된 다음 수신부에서 재조합되어야 합니다. </li>
<li>큰 IP 패킷은 여러 개의 작은 이더넷 패킷으로 분할됩니다.</li>
<li>이더넷과 무선 시스템같은 특정 하드웨어 기술은 IP 패킷을 캡슐화하여 전송합니다. </li>
<li>IP 패킷은 <code>IP 패킷 헤더</code> + <code>TCP 세그먼트 헤더</code> + <code>TCP 데이터 조각</code> 으로 구성되어 있습니다.</li>
</ul>
<ul>
<li>IP 패킷
<img src="https://velog.velcdn.com/images/say_ye/post/66b75a47-5219-40f7-8df8-497025235647/image.png" alt="">
<code>Ver</code> : 데이터그램을 생성한 IP 버전
<code>IHL</code> : IP 헤더의 길이
<code>TOS</code> : Type of Service.데이터 그램에 기대되는 QoS를 지시하는 8비트 코드
<code>Total length</code> : 헤더와 데이터 필드를 포함한 전체 데이터그램의 길이
<code>Identification</code>, <code>flags</code>, <code>Fragment offset</code> : 세그먼트의 처리 및 재조립에 사용되는 필드
<code>TTL</code> : Time To Live. 패킷의 출발지에서 초깃값이 설정되고, 각 게이트웨이를 거칠 때마다 값이 1씩 감소되는 1바이트짜리 필드. 0 까지 내려가면 패킷이 폐기
<code>Protocol</code> : 데이터 그램과 관련된 상위 계층 프로토콜을 식별
ex) 6 : TCP, 17 : UDP
<code>Header checksum</code> : 전송 도중 헤더가 손상되지 않았는지 검사하는 용도의 필드
<code>Source address</code> : 근원지 주소
<code>Destination address</code> : 도착지 주소
<code>Options</code> : 경로배정 및 보안 등과 같은 제어 기능에 사용되는 부가정보</li>
</ul>
<h3 id="ipv4-vs-ipv6">IPv4 vs IPv6</h3>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="center">IPv4</th>
<th align="center">IPv6</th>
</tr>
</thead>
<tbody><tr>
<td align="center">길이</td>
<td align="center">32비트</td>
<td align="center">128비트</td>
</tr>
<tr>
<td align="center">품질 제어</td>
<td align="center">품질 보장 곤란</td>
<td align="center">등급별, 서비스 별로 패킷을 구분할 수 있어 품질 보장이 용이</td>
</tr>
<tr>
<td align="center">보안 기능</td>
<td align="center">IPsec 프로토콜 별도 설치</td>
<td align="center">확장 기능에서 기본으로 제공</td>
</tr>
<tr>
<td align="center">자동 네트워킹</td>
<td align="center">곤란</td>
<td align="center">있음</td>
</tr>
<tr>
<td align="center">이동성 지원</td>
<td align="center">곤란(비효율적)</td>
<td align="center">용이(효율적)</td>
</tr>
</tbody></table>
<h2 id="tcptransmission-control-protocol">TCP(Transmission Control Protocol)</h2>
<blockquote>
<p>IP를 사용하여 출발지에서 목적지의 특정 포트까지 임의 길이의 바이트 시퀀스를 전송하기 위한 <strong>안정적인</strong> 매커니즘을 제공합니다.</p>
</blockquote>
<ul>
<li>신뢰성 있는 양방향 스트림을 제공합니다.</li>
<li>데이터는 언제나 보낸 순서에 맞게 도착합니다.</li>
<li>전송 지연이 적고 오류 발생 확률이 낮습니다.</li>
<li>언제든 어떤 크기로든 보낼 수 있습니다.</li>
<li>세그먼트에는 오류 검출 정보가 포함되어 있어, 손상된 세그먼트를 찾아낼 수 있습니다.</li>
<li>TCP 스트림은 세그먼트로 나뉘어 IP 패킷을 통해 전송됩니다.</li>
<li>TCP 커넥션은 <code>발신지 IP주소</code>, <code>발신지 포트</code>, <code>수신지 IP주소</code>, <code>수신지 포트</code> 네 가지 값으로 식별합니다.
이 네가지 값을 동일하게 가지는 커넥션이 여러개일 수 없습니다.</li>
<li>TCP 패킷
 <img src="https://t1.daumcdn.net/cfile/tistory/2730804F52BBE48A04"></img>
 <code>Source Port</code> : 패킷을 송신하는 시스템의 포트번호
 <code>Destination Port</code> : 패킷을 수신할 시스템의 포트번호
 <code>Sequence Number</code> : 세그먼트 데이터의 순서번호
 <code>Acknowledge Number</code> : 상대방으로부터 수신한 데이터의 바로 다음에 수신할 데이터 순서 번호
 <code>Hedaer Length</code> : TCP 헤더의 길이
 <code>Reserved</code> : 미래를 위해 예약된 필드로 항상 0으로 설정
 <code>Flags</code> : 통신 컨트롤을 위한 6개의 제어 플래그<ul>
<li><code>URG</code>(긴급), <code>ACK</code>(확인응답), <code>PSH</code>(삽입), <code>RST</code>(강제연결종료), <code>SYN</code>(연결시작), <code>FIN</code>(종료)</li>
</ul>
</li>
</ul>
<pre><code>`Window Size` : 송신 시스템에서 자신이 수용하는 한 버퍼의 크기
`Checksum` : 데이터가 전송 중에 손실되지 않고 원본과 동일한지 검사
`Urgent Point` : Urgent flag 설정 시 urgent 데이터의 마지막 byte의 일련번호</code></pre><h2 id="tcp-소켓-프로그래밍">TCP 소켓 프로그래밍</h2>
<ul>
<li>TCP 종단 데이터 구조를 생성하고, 원격 서버의 TCP 종단에 그 종단 데이터 구조를 연결하여 데이터 스트림을 읽고 쓸 수 있습니다.</li>
<li>소켓 API는 HTTP 프로그래머에게 TCP와 IP의 세부사항들을 숨깁니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/say_ye/post/d481adbc-2aa3-45d5-a292-1ce474b9dec2/image.png" alt=""></p>
<h2 id="3-way--4-way-handshacking">3-way / 4-way handshacking</h2>
<blockquote>
<p>TCP/IP 프로토콜을 이용한 통신에서 연결, 연결 해제를 확인하는 방법입니다.</p>
</blockquote>
<p>(🧗‍♀️=클라이언트 🧍=서버)</p>
<p><strong>3-way</strong>
🧗‍♀️ : 내 말들려? (SYN, 커넥션 생성요청)
🧍 : 응 넌 들려? (SYN + ACK, 커넥션 요청이 받아들여졌음을 알림)
🧗‍♀️ : 응 나도 들려 (ACK, 커넥션이 잘 맺어졌음을 서버에게 알림)
<code>연결 완료</code></p>
<p><strong>4-way</strong>
🧗‍♀️ : 야 이제 끊을게 (FIN, 커넥션 종료요청)
🧍 : 기다려봐 하던거만 마무리 하고 (ACK, 커넥션 종료요청을 받았음을 알림)
🧍 : 이제 끊어도 돼 (FIN, 커넥션을 종료했음을 클라이언트에게 알림)
🧗‍♀️ : 응 끊을게 (ACK, 커넥션 종료를 확인했음을 서버에게 알림)
<code>연결 해제 완료</code></p>
<h3 id="3-way-handshacking">3-way handshacking</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/6354b31a-5614-4a05-939e-ec485293ec7d/image.png" alt=""></p>
<blockquote>
<p>TCP/IP 프로토콜을 이용하여 통신을 하는 응용프로그램이 데이터를 전송하기 전, 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정입니다.</p>
</blockquote>
<p>  1️⃣ 클라이언트는 서버에 접속을 요청하는 <code>SYN</code> 패킷을 보냅니다.
  2️⃣ 서버는 <code>SYN</code>요청을 받고 요청을 수락한다는 <code>ACK</code> + <code>SYN</code> 플래그를 클라이언트로 보냅니다.
  3️⃣ 클라이언트는 서버에게 <code>ACK</code>를 보내고 연결이 완료됩니다. 이후부터는 데이터가 오갈 수 있게 됩니다.</p>
<h3 id="4-way-handshacking">4-way handshacking</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/c59f7bd8-83a5-4dba-ad4c-cf14b6127ec5/image.png" alt=""></p>
<blockquote>
<p>TCP/IP 프로토콜을 이용하여 통신을 하는 응용프로그램이 데이터를 전송하기 전, 정확한 전송을 보장하기 위해 상대방 컴퓨터와 사전에 세션을 수립하는 과정입니다.</p>
</blockquote>
<p>1️⃣ 클라이언트는 연결을 종료하고자 서버에 <code>FIN</code> 플래그를 보냅니다.
2️⃣ 서버는 <code>FIN</code> 플래그를 받은 뒤 <code>ACK</code> 패킷을 보낸 후 자신이 데이터를 모두 보낼때 까지 기다립니다.
3️⃣ 서버가 연결을 종료할 준비가 되면, <code>FIN</code> 플래그를 클라이언트에 전송합니다.
4️⃣ 클라이언트는 서버에 <code>ACK</code>를 보내 응답합니다. <code>ACK</code>응답을 받은 서버는 연결을 해제합니다.</p>
<hr>
<p>참고
1일 1로그 100일 완성 IT지식
HTTP 완벽가이드
<a href="https://velog.io/@nnnyeong/Network-TCP-3-way-4-way-Handshake">https://velog.io/@nnnyeong/Network-TCP-3-way-4-way-Handshake</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] Symbol]]></title>
            <link>https://velog.io/@say_ye/JS-Symbol</link>
            <guid>https://velog.io/@say_ye/JS-Symbol</guid>
            <pubDate>Thu, 02 Jun 2022 16:03:31 GMT</pubDate>
            <description><![CDATA[<h2 id="symbol이란">Symbol이란?</h2>
<blockquote>
<p>다른 값과 중복되지 않고 변경 불가능한 원시 타입의 값</p>
</blockquote>
<h3 id="문법">문법</h3>
<p><code>Symbol([description])</code></p>
<ul>
<li>[description] : 선택적 문자열. 디버깅에 사용할 수 있는 심볼에 대한 <strong>설명</strong>일 뿐 심볼 자체에 접근하는 용도로는 사용할 수 없습니다.</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li><p>ES6에서 도입된 7번째 데이터 타입입니다.</p>
</li>
<li><p>반드시 Symbol() 함수를 호출하여 생성합니다.</p>
<pre><code class="language-jsx">const mySymbol = Symbol();</code></pre>
</li>
<li><p>객체의 프로퍼티 키로 사용될 수 있는 타입으로, 주로 이름의 <code>충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해</code> 사용합니다.</p>
<pre><code class="language-jsx">  Symbol(&quot;foo&quot;) === Symbol(&quot;foo&quot;); // false</code></pre>
</li>
<li><p>생성된 심벌 값은 외부로 노출되지 않아 확인할 수 없습니다.    </p>
<pre><code class="language-jsx">  const mySymbol = Symbol();
  console.log(mySymbol) // Symbol()</code></pre>
</li>
<li><p>생성자 함수로 객체를 생성하는 문법은 지원하지 않습니다. </p>
<pre><code class="language-jsx">  const mySymbol = new Symbol(); // &lt;- 이게 될거같은데 안됩니다요.</code></pre>
</li>
<li><p>객체처럼 접근하면 암묵적으로 래퍼 객체를 생성합니다.
  래퍼 객체가 뭐냐면.. Symbol은 원시타입이니까 생성된 mySymbol은 객체가 아니잖아요?
  하지만 객체마냥 자연스럽게 프로퍼티, 메서드에 접근할 수 있기도 합니다. 이런식으로 원시타입의 프로퍼티에 접근할 때 원시값을 감싸며 생성되는 임시 객체를 래퍼 객체라고 합니다.</p>
<pre><code class="language-jsx">  const mySymbol = Symbol(&#39;ㅇㅅㅇ&#39;);
  console.log(mySymbol.description) // &#39;ㅇㅅㅇ&#39;
  console.log(mySymbol.toString()) // &#39;Symbol(ㅇㅅㅇ)&#39;</code></pre>
</li>
<li><p>암묵적으로 문자열이나 숫자 타입으로 변환되지 않으며 불리언으로는 변환 가능합니다.</p>
<pre><code class="language-jsx">  const mySymbol = Symbol();
  console.log(mySymbol + &#39;&#39;); // typeError
  console.log(+mySymbol); // typeError
  console.log(!!mySymbol); // true</code></pre>
</li>
</ul>
<h3 id="메서드">메서드</h3>
<ul>
<li><code>Symbol.for(key)</code>
전역 심벌 레지스트리에서 key와 일치하는 심벌 값을 검색하여 해당 key로 저장된 심벌 값이 없으면 심벌 값 생성, 심벌 값이 있으면 해당 심벌 값을 반환합니다.
이를 이용하여 심벌 값을 공유할 수 있습니다.
참고로 <code>Symbol()</code> 로 생성된 심벌 값은 전역 심벌 레지스트리에 등록되지 않습니다.<pre><code class="language-js">const s1 = Symbol(&#39;a&#39;)
const s2 = Symbol.for(&#39;a&#39;)
const s3 = Symbol.for(&#39;a&#39;)
s1 === s2 // false
s2 === s3 // true
s1.description // &#39;a&#39;
s2.description // &#39;a&#39;</code></pre>
</li>
<li><code>Symbol.keyFor(key)</code>
  전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있습니다.<pre><code class="language-jsx">const s1 = Symbol.for(&#39;mySymbol&#39;)
Symbol.keyFor(s1) // mySymbol</code></pre>
</li>
</ul>
<h3 id="사용-예시">사용 예시</h3>
<ul>
<li><p>유일무이한 상수를 정의</p>
<pre><code class="language-jsx">  const Direction = {
      UP: Symbol(&#39;up&#39;),
      DOWN: Symbol(&#39;down&#39;),
      LEFT: Symbol(&#39;left&#39;),
      RIGHT: Symbol(&#39;right&#39;)
  }</code></pre>
<p>  <code>Object.freeze()</code> 랑 같이 쓰면 enum 처럼 쓰는것도 가능합니다.</p>
<pre><code class="language-jsx">  const Direction = Object.freeze({
      UP: Symbol(&#39;up&#39;),
      DOWN: Symbol(&#39;down&#39;),
      LEFT: Symbol(&#39;left&#39;),
      RIGHT: Symbol(&#39;right&#39;)
  })</code></pre>
</li>
<li><p>객체의 프로퍼티키로 사용</p>
<pre><code class="language-jsx">  const obj = {
      [Symbol.for(&#39;mySymbol&#39;)]: 1
  }
  obj[Symbol.for(&#39;mySymbol&#39;)];</code></pre>
<p>  심벌값으로 프로퍼티 키를 만들면 ?</p>
<ul>
<li>다른 프로퍼티 키와 절대 충돌하지 않습니다.(((중요)))</li>
<li><code>for ... in</code> 문, <code>Object.key</code>, <code>Object.getOwnPropertyNames</code> 로 찾을 수 없습니다.</li>
<li>대신 <code>Object.getOwnPropertySymbols</code>로 찾을 수 있습니다.</li>
</ul>
</li>
<li><p>빌트인 객체에 메서드 추가</p>
<pre><code class="language-jsx">  Array.prototype[Symbol.for(&#39;decription&#39;)] = function () { ... }</code></pre>
<p>  이렇게 추가하면 다른 프로퍼티 키와 겹칠까봐 걱정 안해도 됩니다.</p>
</li>
</ul>
<h3 id="빌트인-심벌-값">빌트인 심벌 값</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/4a3a2500-6781-4c3a-ad9b-5e32993dae59/image.png" alt=""></p>
<hr>
<p>참고 링크<br><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 6549 히스토그램에서 가장 큰 직사각형 - python]]></title>
            <link>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-6549-%ED%9E%88%EC%8A%A4%ED%86%A0%EA%B7%B8%EB%9E%A8%EC%97%90%EC%84%9C-%EA%B0%80%EC%9E%A5-%ED%81%B0-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95-python</link>
            <guid>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-6549-%ED%9E%88%EC%8A%A4%ED%86%A0%EA%B7%B8%EB%9E%A8%EC%97%90%EC%84%9C-%EA%B0%80%EC%9E%A5-%ED%81%B0-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95-python</guid>
            <pubDate>Thu, 02 Jun 2022 15:27:39 GMT</pubDate>
            <description><![CDATA[<p>문제 링크
<a href="https://www.acmicpc.net/problem/6549">https://www.acmicpc.net/problem/6549</a></p>
<h3 id="시도-1-메모리-초과">시도 1. 메모리 초과</h3>
<pre><code class="language-python">import sys
sys.setrecursionlimit(10000)

def findArea(heights):
  if len(heights) == 0:
    return 0
  width = len(heights)
  minHeight = min(heights)
  minIndex = heights.index(minHeight)
  return max(findArea(heights[:minIndex]), findArea(heights[minIndex+1:]), minHeight * width)

while True:
  hist = list(map(int, input().split()))
  n = hist[0]
  heights = hist[1:]
  if n == 0 :
    break
  print(findArea(heights))
</code></pre>
<ul>
<li>재귀 스택 제한 초과로 실패<h3 id="시도2-성공">시도2. 성공</h3>
<pre><code class="language-python">import sys
input = sys.stdin.readline
</code></pre>
</li>
</ul>
<p>def maxSize():
    max_size = 0
    stack = []</p>
<pre><code>for i in range(n):
    left = i
    while stack and stack[-1][0] &gt;= heights[i]:
        h, left = stack.pop()
        tmp_size = h * (i - left)
        max_size = max(max_size, tmp_size)
    stack.append([heights[i],left])

for h, point in stack:
    max_size = max(max_size, (n-point)*h)

return max_size</code></pre><p>while True:
    n, *heights = map(int, input().split())
    if n == 0: 
        break
    print(maxSize())</p>
<p>```</p>
<ul>
<li>접근방법 : 스택</li>
<li>시간복잡도 : O(n)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] JSON 정책 문서 정리]]></title>
            <link>https://velog.io/@say_ye/AWS-JSON-%EC%A0%95%EC%B1%85-%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@say_ye/AWS-JSON-%EC%A0%95%EC%B1%85-%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 02 Jun 2022 11:14:25 GMT</pubDate>
            <description><![CDATA[<h2 id="iam-정책">IAM 정책</h2>
<h3 id="정책-유형-자주-사용하는-정책-순">정책 유형 (자주 사용하는 정책 순)</h3>
<ul>
<li>자격 증명 기반 정책(Identity-based-policies)</li>
<li>리소스 기반 정책(Recource-based-policies)</li>
<li>권한 경계(Permissions boundaries)</li>
<li>Organizations SCPs</li>
<li>액세스 제어 목록(ACL: Access control lists)</li>
<li>세션 정책(Session policies)</li>
</ul>
<p>이 중에 ACL을 제외한 모든 IAM의 정책에서 JSON 정책 구조를 사용합니다. </p>
<h3 id="json-정책-문서-구조">JSON 정책 문서 구조</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/99910323-415a-4a47-8e35-183174cb9b0d/image.png" alt="">
최상위 element 안에 다수개의 statement로 이루어져있는 구조입니다.</p>
<pre><code class="language-js">{
  &quot;Version&quot;: &quot;2012-10-17&quot;,
  &quot;Statement&quot;: [
    {
      &quot;Sid&quot;: &quot;FirstStatement&quot;,
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Action&quot;: [&quot;iam:ChangePassword&quot;],
      &quot;Resource&quot;: &quot;*&quot;
    },
    {
      &quot;Sid&quot;: &quot;SecondStatement&quot;,
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Action&quot;: &quot;s3:ListAllMyBuckets&quot;,
      &quot;Resource&quot;: &quot;*&quot;
    },
    {
      &quot;Sid&quot;: &quot;ThirdStatement&quot;,
      &quot;Effect&quot;: &quot;Allow&quot;,
      &quot;Action&quot;: [
        &quot;s3:List*&quot;,
        &quot;s3:Get*&quot;
      ],
      &quot;Resource&quot;: [
        &quot;arn:aws:s3:::confidential-data&quot;,
        &quot;arn:aws:s3:::confidential-data/*&quot;
      ],
      &quot;Condition&quot;: {&quot;Bool&quot;: {&quot;aws:MultiFactorAuthPresent&quot;: &quot;true&quot;}}
    }
  ]
}</code></pre>
<p>밑에서 각 정책 요소들이 어떤 의미를 갖는지 알아본 후 돌아와서 이 규칙이 어떤 의미였는지 평가해봅시다.</p>
<h3 id="json-정책-요소">JSON 정책 요소</h3>
<ul>
<li><p>Version
사용하고자 하는 정책언어의 버전을 지정합니다. 최신버전(<code>2012-10-17</code>)을 사용하는 것이 권장됩니다. 
최신버전 : <code>2012-10-17</code> 구버전 : <code>2008-10-17</code>
ex) <code>&quot;Version&quot;: &quot;2012-10-17&quot;</code></p>
</li>
<li><p>Id
정책 식별자를 지정합니다. ID가 필요한 경우 <code>UUID(GUID)</code> 값이나 그 일부를 ID로 사용하여 고유성을 확보하는 것이 좋습니다.
AWS 서비스중에는 이 요소를 필요로 하거나 고유성 요건을 요구하는 경우가 있습니다.(Amazon SQS또는 Amazon SNS 등)
ex) <code>&quot;Id&quot;: &quot;cd3ad3d9-2776-4ef1-a904-4c229d1642ee&quot;</code></p>
</li>
<li><p>Statement <strong><code>필수</code></strong>
정책 요소의 컨테이너 역할을 합니다. 단일 문 또는 개별 문의 배열을 포함 할 수 있습니다. 
ex) <code>&quot;Statement&quot;: [{...},{...},{...}]</code></p>
</li>
<li><p>Sid
설명문(statement)의 Id입니다.
IAM에서 Sid는 IAM API에 노출되지 않습니다. 따라서 이 ID를 근거로 특정 문을 가져올 수는 없습니다.
AWS 서비스중에는 이 요소를 필요로 하거나 고유성 요건을 요구하는 경우가 있습니다.(Amazon SQS또는 Amazon SNS 등)
ex) <code>&quot;Sid:&quot;1&quot;</code></p>
</li>
<li><p>Effect <strong><code>필수</code></strong>
문의 허용(allow) 또는 명시적 거부(explicit deny) 중 하나를 지정합니다.
허용 : <code>Allow</code> 거부 : <code>Deny</code>
기본적으로 리소스 액세스는 거부된 상태이며 허용하려면 <code>Effect</code> 요소를 <code>Allow</code>로 설정해야합니다.
ex) <code>&quot;Effect&quot;: &quot;Allow&quot;</code></p>
</li>
<li><p>Principal
리소스 기반 정책을 생성하는 경우 리소스에 대한 액세스가 허용되거나 거부되는 <code>보안 주체</code>(계정, 사용자, 역할, 페더레이션 사용자) 를 지정합니다.
보안 주체 이름이나 ARN의 일부를 나타내기 위해 와일드카드(<code>*</code>)를 사용할 수 없습니다. 보안 주체는 항상 특정 사용자가 되어야하기 때문입니다.
다음과 같이 보안 주체를 지정할 수 있습니다.
1️⃣ AWS 계정 및 루트 사용자
AWS 계정 ID 지정
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;arn:aws:iam::AWS-account-ID:root&quot; }</code>
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;AWS-account-ID&quot; }</code>
Canonical ID 지정
<code>&quot;Principal&quot;: { &quot;CanonicalUser&quot;: &quot;canonical-ID&quot; }</code>
2️⃣ IAM 역할
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;arn:aws:iam::AWS-account-ID:role/role-name&quot; }</code>
3️⃣ 역할 세션
수임된 역할 세션 보안 주체
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;arn:aws:sts::AWS-account-ID:assumed-role/role-name/role-session-name&quot; }</code>
웹 자격 증면 세션 보안 주체
<code>&quot;Principal&quot;: { &quot;Federated&quot;: &quot;cognito-identity.amazonaws.com&quot; }</code>
SAML 세션 보안 주체
<code>&quot;Principal&quot;: { &quot;Federated&quot;: &quot;arn:aws:iam::AWS-account-ID:saml-provider/provider-name&quot; }</code>
4️⃣ IAM 사용자
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;arn:aws:iam::AWS-account-ID:user/user-name&quot; }</code>
5️⃣ 페더레이션 사용자 세션
<code>&quot;Principal&quot;: { &quot;AWS&quot;: &quot;arn:aws:sts::AWS-account-ID:federated-user/user-name&quot; }</code>
6️⃣ AWS 서비스
`&quot;Principal&quot;: {
  &quot;Service&quot;: [</p>
<pre><code>  &quot;service-name1.amazonaws.com&quot;,
  &quot;service-name2.amazonaws.com&quot;</code></pre><p> ]
}<code>7️⃣ 모든 보안 주체</code>&quot;Principal&quot;: &quot;*&quot;<code></code>&quot;Principal&quot; : { &quot;AWS&quot; : &quot;*&quot; }`
8️⃣ 배열을 이용하여  여러개의 계정을 지정하기</p>
<pre><code class="language-js">&quot;Principal&quot;: { 
    &quot;AWS&quot;: [
      &quot;arn:aws:iam::123456789012:root&quot;,
      &quot;999999999999&quot;,
      &quot;CanonicalUser&quot;: &quot;79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be&quot;
    ]
}</code></pre>
</li>
<li><p>NotPrincipal
보안 주체 목록에서 예외를 지정할 수 있습니다.
<code>NotPrincipal</code> 을 써야하는 시나리오는 극히 드뭅니다. 따라서 사용을 결정하기 전에 다른 권한 부여 옵션을 살펴보는 것이 바람직합니다.
<em>ex) NotPrincipal 에 명시된 계정들만 제외한 모든 보안주체의 리소스 액세스를 명시적으로 거부하는 예시</em></p>
<pre><code class="language-js">&quot;Effect&quot;: &quot;Deny&quot;,
&quot;NotPrincipal&quot;: {&quot;AWS&quot;: [&quot;arn:aws:iam::444455556666:user/Bob&quot;, &quot;arn:aws:iam::444455556666:root&quot;]},</code></pre>
</li>
<li><p>Action <code>Action 혹은 NotAction 중 하나는 필수</code>
정책이 허용하거나 거부하는 작업 목록을 포함합니다.
<code>&quot;Action&quot;: &quot;작업 접두사:작업 이름&quot;</code>
<em>ex) 단일 액션  / 다수의 액션  / 와일드 카드를 사용한 액션을 명시하는 예시</em></p>
<pre><code class="language-js">&quot;Action&quot;: &quot;sqs:SendMessage&quot;
&quot;Action&quot;: [ &quot;sqs:SendMessage&quot;, &quot;sqs:ReceiveMessage&quot;, &quot;ec2:StartInstances&quot;, &quot;iam:ChangePassword&quot;, &quot;s3:GetObject&quot; ]
&quot;Action&quot;: &quot;s3:*&quot;</code></pre>
</li>
<li><p>NotAction <code>Action 혹은 NotAction 중 하나는 필수</code>
지정된 작업 목록을 제외한 모든 액션을 지정할 수 있습니다.
<em>ex) 사용자가 IAM을 제외한 모든 AWS 서비스에서 작업에 액세스하도록 허용하는 예시</em></p>
<pre><code class="language-js">&quot;Effect&quot;: &quot;Allow&quot;,
&quot;NotAction&quot;: &quot;iam:*&quot;,
&quot;Resource&quot;: &quot;*&quot;</code></pre>
</li>
<li><p>Resource <code>Resource 혹은 NotResource 중 하나는 필수</code>
IAM 권한 정책을 생성하는 경우 작업이 적용되는 리소스 목록을 지정합니다.
<em>ex) s3의 특정 버킷 내 포함된 모든 항목을 나타내는 예시</em></p>
<pre><code class="language-js">&quot;Resource&quot;: &quot;arn:aws:s3:::DOC-EXAMPLE-BUCKET/*&quot;</code></pre>
</li>
<li><p>NotResource
지정된 리소스 목록을 제외한 모든 리소스를 지정할 수 있습니다.
<em>ex) HRBucket 버킷의 Payroll 폴더를 제외하고 모든 s3 리소스에 대한 액세스를 거부하는 예시</em></p>
<pre><code class="language-js">&quot;Effect&quot;: &quot;Deny&quot;,
&quot;Action&quot;: &quot;s3:*&quot;,
  &quot;NotResource&quot;: [
    &quot;arn:aws:s3:::HRBucket/Payroll&quot;,
    &quot;arn:aws:s3:::HRBucket/Payroll/*&quot;
  ]</code></pre>
</li>
<li><p>Condition
정책에서 권한을 부여하는 상황을 지정합니다.
<code>&quot;Condition&quot; : { &quot;{condition-operator}&quot; : { &quot;{condition-key}&quot; : &quot;{condition-value}&quot; }}</code>
<em>condition-operator</em>: 조건 연산자
<em>condition-key</em>: 조건 키
<em>condition-value</em>: 조건 값
<strong>조건 연산자(condition-operaotr)</strong></p>
<table>
<thead>
<tr>
<th align="center">문자열 조건 연산자</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">StringEquals</td>
<td align="center">정확한 일치, 대소문자 구분</td>
</tr>
<tr>
<td align="center">StringNotEquals</td>
<td align="center">불일치</td>
</tr>
<tr>
<td align="center">StringEqualsIgnoreCase</td>
<td align="center">정확한 일치, 대소문자 무시</td>
</tr>
<tr>
<td align="center">StringNotEqualsIgnoreCase</td>
<td align="center">불일치, 대소문자 무시</td>
</tr>
<tr>
<td align="center">StringLike</td>
<td align="center">대소문자 구분 일치, 와일드카드(<code>*</code>, <code>?</code>) 포함 가능</td>
</tr>
<tr>
<td align="center">StringNotLike</td>
<td align="center">대소문자 구분 불일치, 와일드카드(<code>*</code>, <code>?</code>) 포함 가능</td>
</tr>
<tr>
<td align="center"><em>ex) 이름이 johndoe인 사용자를 지정</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot; : {&quot;StringEquals&quot; : { &quot;aws:username&quot; : &quot;johndoe&quot; }}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">숫자 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">NumericEquals</td>
<td align="center">일치</td>
</tr>
<tr>
<td align="center">NumericNotEquals</td>
<td align="center">불일치</td>
</tr>
<tr>
<td align="center">NumericLessThan</td>
<td align="center">미만</td>
</tr>
<tr>
<td align="center">NumericLessThanEquals</td>
<td align="center">이하</td>
</tr>
<tr>
<td align="center">NumericGreaterThan</td>
<td align="center">초과</td>
</tr>
<tr>
<td align="center">NumericGreaterThanEquals</td>
<td align="center">이상</td>
</tr>
<tr>
<td align="center"><em>ex) 한번에 최대 10개까지 객체를 나열할 수 있다고 지정</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {&quot;NumericLessThanEquals&quot;: {&quot;s3:max-keys&quot;: &quot;10&quot;}}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">날짜 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">DateEquals</td>
<td align="center">특정 날짜 일치</td>
</tr>
<tr>
<td align="center">DateNotEquals</td>
<td align="center">특정 날짜 불일치</td>
</tr>
<tr>
<td align="center">DateLessThan</td>
<td align="center">특정 날짜/시간 이전</td>
</tr>
<tr>
<td align="center">DateLessThanEquals</td>
<td align="center">특정 날짜/시간 또는 이전</td>
</tr>
<tr>
<td align="center">DateGreaterThan</td>
<td align="center">특정 날짜/시간 이후</td>
</tr>
<tr>
<td align="center">DateGreaterThanEquals</td>
<td align="center">특정 날짜/시간 또는 이후</td>
</tr>
<tr>
<td align="center"><em>ex) 요청을 생성하는 데 사용된 임시 보안 자격 증명이 2020년 이후에 발급되었음을 지정</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {&quot;DateGreaterThan&quot;: {&quot;aws:TokenIssueTime&quot;: &quot;2020-01-01T00:00:01Z&quot;}}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">불린 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">Bool</td>
<td align="center">부울 일치</td>
</tr>
<tr>
<td align="center"><em>ex) 요청에 SSL을 사용해야 한다고 지정</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {&quot;Bool&quot;: {&quot;aws:SecureTransport&quot;: &quot;true&quot;}}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">이진 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">BinaryEquals</td>
<td align="center">이진 형식의 키 값 일치</td>
</tr>
<tr>
<td align="center"><em>ex) 지정한 키 값을 정책 내 이진 값의 base-64 인코딩 표시와 바이트 단위로 비교</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot; : {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;BinaryEquals&quot;: {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;key&quot; : &quot;QmluYXJ5VmFsdWVJbkJhc2U2NA==&quot;</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">IP 주소 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">IpAddress</td>
<td align="center">지정된 IP주소 또는 범위</td>
</tr>
<tr>
<td align="center">NotIpAddress</td>
<td align="center">지정된 IP주소 또는 범위를 제외한 모든 IP 주소</td>
</tr>
<tr>
<td align="center"><em>ex) IP주소 범위를 지정(CIDR 형식을 따라야 함)</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;IpAddress&quot;: {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;aws:SourceIp&quot;: [</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;203.0.113.0/24&quot;,</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;2001:DB8:1234:5678::/64&quot;</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">]</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">ARN 조건 연산자</td>
<td align="center">설명</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">ArnEquals, ArnLike</td>
<td align="center">ARN 대소문자 구분 일치. 와일드카드(<code>*</code>, <code>?</code>) 포함 가능</td>
</tr>
<tr>
<td align="center">ArnNotEquals, ArnNotLike</td>
<td align="center">ARN 불일치</td>
</tr>
<tr>
<td align="center">모든 서비스가 이 연산자를 사용하여 ARN 비교를 지원하는 것은 아닙니다. ARN 조건 연산자가 작동하지 않으면 문자열 조건 연산자를 사용합니다.</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"><em>ex) aws:SourceArn 값이 arn:aws:sns:REGION:123456789012:TOPIC-ID 와 일치함을 지정</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {&quot;ArnEquals&quot;: {&quot;aws:SourceArn&quot;: &quot;arn:aws:sns:REGION:123456789012:TOPIC-ID&quot;}}</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"><strong>ifExists 조건 연산자</strong></td>
<td align="center"></td>
</tr>
<tr>
<td align="center"><code>Null</code> 조건을 제외한 모든 조건 연산자의 이름 끝에 <code>ifExists</code>를 추가할 수 있습니다.(예: <code>StringLikeIfExists</code>)</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">요청 콘텍스트에 정책 키가 있으면 정책에 지정된 대로 키를 처리하고 키가 없으면 <code>true</code>로 평가합니다.</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"><em>ex) ec2:InstanceType 조건 키가 있는 경우 해당 조건을 검사하고 없는 경우는 true로 평가하는 조건</em></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```jsx</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;Condition&quot;: {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;StringLikeIfExists&quot;: {</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;ec2:InstanceType&quot;: [</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;t1.*&quot;,</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;t2.*&quot;,</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">&quot;m3.*&quot;</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">]}}</td>
<td align="center"></td>
</tr>
</tbody></table>
<pre><code>
__Null 연산자__
`Null` 조건 연산자를 사용하면 조건 키의 유무를 검사할 수 있습니다.
정책문에서는 `true`(키가 부재하며 값이 null임) 또는 `false`(키가 존재하며 값이 null이 아님)을 사용합니다.
_  ex) aws:TokenIssueTime 키가 존재하면 안됨을 나타내는 조건_
```js
&quot;Condition&quot;:{&quot;Null&quot;:{&quot;aws:TokenIssueTime&quot;:&quot;true&quot;}}</code></pre></li>
</ul>
<hr>
<p>참고링크
<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html">https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html</a>
<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html">https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[6.1 강연기록]]></title>
            <link>https://velog.io/@say_ye/6.1-%EA%B0%95%EC%97%B0%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@say_ye/6.1-%EA%B0%95%EC%97%B0%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Wed, 01 Jun 2022 04:57:09 GMT</pubDate>
            <description><![CDATA[<ol>
<li>프로젝트 매니저</li>
</ol>
<ul>
<li>회의때 사람들의 말을 많이 듣고 결론을 정리하기</li>
<li>내가 얘기했던게 틀리는 경우는 빨리 인정하기</li>
<li>현재의 상황, 문제에 대해서만 이야기하기보다는 해결책 방향성까지 같이 얘기하기.</li>
<li>리더의 역량을 쌓는법. 리더의 어려움을 극복한 방법
: 빠른 퍼포먼스를 내는 것 보다는 일을 정리하고 협업하는걸 더 잘하다보니 리더가 되었다.
피플 매니징, 아키텍쳐 설계를 고민. 
사람을 이해하는 법, 사람마다 성향을 파악해서 성향에 맞는 접근</li>
<li>개발자는 지금 현재를 생각하고 매니저는 미래를 생각한다.</li>
</ul>
<ol start="2">
<li>CTO</li>
</ol>
<ul>
<li>CTO로서의 가장 큰 고민
: 어떻게 생각하고있는 바를 구성원과 동기화시킬까. 어떻게 이해 시킬까. 동기화를 위해서는 오버커뮤니케이션도 필요하다고 생각함. 1:1 미팅을 자주 가지려고 함.</li>
<li>이런 사람과 일하고 싶지 않다.
: 지금 하고 있는일에 머무르고자 하는 사람들. 지금 회사의 일에 크게 관심이 없는 분</li>
<li>이런 사람과 일하고 싶다.
: 성장하고자하는 의지가 있는분이 좋다. 성장에 대한 가이드를 주면서 같이 성장해 나갈 수 있다.</li>
<li>커뮤니케이션이 힘든 타입
: 그냥 이전에 하던방식이라 이렇게 하는데요? 라는 마인드</li>
<li>여성 개발자로 일하면서 힘든 점
: 많은 개발조직이 남성분들이 훨씬 많다. 개발문화에서 동떨어진다고 느끼게 된다. 내가 가진 고민들을 상담하거나 롤모델을 찾기가 쉽지않다.
주변에 같이 고민할 수 있는 비슷한 동료들을 많이 만드는게 좋다. 느슨한 연대관계를 많이 만들자.</li>
<li>성장 정체기, 번아웃이 오는 시기를 어떻게 극복하는지
: 예전에 겪었던 작은 성공의 경험, 주변에 존경하는 선배님들이 나를 인정했던 경험 등을 되뇌이기</li>
<li>능력있는 개발자란?
: 신기술을 잘 쓰는 사람이라기 보단 내가 직면한 문제에서 적절한 솔루션을 잘 제시하고 실행하는 사람.</li>
<li>뒤쳐지는 기분이 들 때 멘탈관리는 어떻게 하는지
: 내가 시간이없을 뿐이지~ 들여다보면 잘할거야. 정신승리</li>
<li>개발자의 성장의 기준?
: 초반 : 솔루션들을 익히기, 이후 : 주변 사람들을 움직이기</li>
<li>팀 빌딩 방법
  <strong>1. 애매함은 제거하고 확실한 것부터 시작</strong>
: 확실한 것을 구축하고 나면 다음에 할 일이 보임.
베트남에서는 어떤 음식배달서비스를 만들어야돼? 이런 애매한건(디테일) 처음에 생각하지 않고 명확한 배달 서비스 코어 기능개발부터 착수</li>
<li><ul>
<li><ol start="2">
<li>서비스의 코어가 아닌 기능은 외부 서비스를 활용**
: 이후 다른 솔루션으로 대체할 수 있음을 고려</li>
</ol>
</li>
</ul>
</li>
<li><ul>
<li><ol start="3">
<li>서비스 빌딩 우선, 팀의 외연 확장은 신중히, 나중에**
: 서비스를 초기에 빠르게 구축할 수 있는 방법은 팀이 한 사람처럼 움직이는 것</li>
</ol>
</li>
</ul>
</li>
<li>함께 하고 싶은 개발자나 기획자가 있을 때는 어떻게 하는지?
: 지금 다니는 회사를 왜 선택했는지를 공유하며 어필. 공감</li>
<li>신기술을 도입할 때 고려하는 것
: 신기술의 시스템 도입 여부는 생산성을 우선순위로 둠.
: 이 신기술을 사용하는 개발자를 뽑기 힘들지는 않을 지도 고려함</li>
<li>다른 개발자들을 설득하는 방법.
: 정말 합리적인 제안이었나? 그런데도 불구하고 잘 받아들여지지 않는다면 공론화해서 제안</li>
<li>회사가 요구하는 새로운 시도에 어떻게 대처해야 할까?
: 엔지니어가 가장 많이 해야하는 일은 현실적인 솔루션을 생각하는 것. 구현가능한가?
: 무작정 하지 말자라는 접근보다는 이걸 왜 하려고 하는걸까? 를 구체적으로 파고들기. 전혀 다른 솔루션이 나올수도 있다.</li>
<li>CTO는 면접에서 어떤 질문을 하는지?
: 주니어 - 회사가 어떤 기술을 쓰고 있는지 잘 파악
: 중간급 리더 - 비즈니스적 문제를 기술적인 문제로 치환 할 수 있는지
: 리더 - 맡을 역할에 대해 이해하고 있는지, 해당 역할에 대한 본인의 관점, 이상적인 팀의 모습은 뭐라고 생각하는지 </li>
<li>회사가 it기업인지 아닌지 보다는 회사가 테크영역을 바라보는 관점이 중요</li>
<li>이걸 내가 해도될까? 라는 생각을 덜 했으면 좋겠다. 겁먹지 말자.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[네트워크] 쿠키, 세션, JWT]]></title>
            <link>https://velog.io/@say_ye/HTTP-%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98</link>
            <guid>https://velog.io/@say_ye/HTTP-%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98</guid>
            <pubDate>Tue, 31 May 2022 16:38:11 GMT</pubDate>
            <description><![CDATA[<h2 id="쿠키http쿠키">쿠키(HTTP쿠키)</h2>
<blockquote>
<p>인터넷 사용자가 어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일</p>
</blockquote>
<h3 id="왜-쿠키🍪인가">왜 쿠키(🍪)인가?</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/0cfaa0e8-3e70-4d0a-ab09-8006e8d63a75/image.png" alt=""></p>
<ul>
<li><p>헨젤과 그레텔 동화에서 <strong>자신이 지나온 길을 표시하기 위해 쿠키조각을 바닥에 떨어뜨리는 것</strong> 
= 서버에 요청한 사람이 누구인지 표시하기 위해 클라이언트에 쿠키를 남기는 것</p>
</li>
<li><p>유닉스 운영체제에서 두 프로그램 사이에 전송되는 작은 데이터 패킷을 <strong>매직 쿠키</strong>라 불렀는데, 이를 웹에서 차용해서 사용하기 시작한 것</p>
</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>클라이언트에 저장된다</li>
<li>한 개에 4KB까지 저장 가능하다</li>
<li>이름, 값, 만료날짜, 경로 정보가 들어있다</li>
<li>기본적으로 웹브라우저가 종료되면 삭제되고(세션쿠키), 만료날짜를 지정해주면 만료일이 돼야 삭제된다(지속쿠키)</li>
<li>웹 브라우저에 해당 서버의 쿠키 정보가 있으면 HTTP 요청에 무조건 담아 보낸다</li>
<li>특정 도메인에서 생성된 쿠키는 해당 도메인에서만 사용가능하다.</li>
</ul>
<h2 id="세션http-세션">세션(HTTP 세션)</h2>
<blockquote>
<p>서버에 클라이언트의 상태 정보를 저장해 놓고 이와 매칭되는 쿠키를 클라이언트에게 주어 서버가 클라이언트를 식별할 수 있도록하는 방식</p>
</blockquote>
<h3 id="왜-세션인가">왜 세션인가?</h3>
<ul>
<li>session : 시간, 시즌</li>
<li><code>클라이언트와 서버간에 활성화된 접속 기간</code>이라는 의미이다.</li>
<li>통상적으로는 <code>서버와 클라이언트간의 식별정보를 유효기간을 두고 저장하는 방식</code>을 통틀어서 세션방식이라고 부른다.</li>
</ul>
<h3 id="특징-1">특징</h3>
<ul>
<li>따로 용량의 제한이 없다.</li>
<li>서버에 세션 객체를 생성하며 각 클라이언트마다 고유한 ID값을 부여한다.</li>
<li>쿠키를 사용하여 세션 ID값을 클라이언트에 보낸다.</li>
<li>웹 브라우저가 종료되면 세션쿠키는 삭제된다.</li>
</ul>
<h2 id="쿠키-세션-인증방식">쿠키-세션 인증방식</h2>
<p><img src="https://velog.velcdn.com/images/say_ye/post/2166a926-39c5-471c-afc0-c2c9a7994f40/image.png" alt=""></p>
<h3 id="장점">장점</h3>
<ul>
<li>쿠키는 세션 저장소에 담긴 정보를 가져오기위한 열쇠역할일 뿐, 유의미한 값을 가지고 있지 않다. (중요 정보는 세션 저장소에 있다.)</li>
<li>사용자마다 고유 ID값을 발급받으므로 일일이 모든 회원정보를 확인하며 대조할 필요없이 회원정보에 접근 가능하다.</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>특정 사용자의 HTTP요청을 해커가 가로채서 쿠키를 훔칠 수 있고, 훔친 쿠키를 이용해 요청을 보내면 세션저장소에서 정보를 잘못 뿌려주게된다.
  <strong>해결책) https를 사용해 요청 자체를 탈취해도 안의 정보를 읽기 힘들게 한다.</strong></li>
<li>서버에서 세션 저장소를 사용하므로 추가적인 저장공간이 필요함</li>
<li><em>해결책) 세션에 유효시간을 넣어준다.*</em></li>
</ul>
<h3 id="세션이-만료되었습니다">세션이 만료되었습니다.</h3>
<p><img src="https://velog.velcdn.com/images/say_ye/post/53d40a89-c748-4bdf-9714-ba9d4af05ccb/image.png" alt=""></p>
<p>메이플 해본 사람은 다 아는 <code>세션이 만료되었습니다.</code> 대화창이다.
로그인 후 게임을 한참 하다가 다시 웹으로 돌아오면 위와 같은 대화창이 뜨면서 로그인이 풀린다. 로그인을 한 시점부터 세션만료 대화창이 뜨기까지의 과정을 추측해보자.</p>
<ol>
<li>유저가 로그인을 시도한다.</li>
<li>서버에서는 유저 정보 테이블과 대조하여 일치하는 로그인 정보가 존재하는지 확인한다.</li>
<li>존재한다면 사용자의 정보를 세션 저장소에 저장하고 해당 데이터에 접근하기 위한 고유 세션ID를 발급한다.</li>
<li>세션 ID를 클라이언트에 보내고 이를 쿠키에 저장하도록 한다.</li>
<li>유저는 서버에서 받은 쿠키를 인증이 필요한 요청(ex. 게임 클라이언트 실행) 마다 헤더에 실어 보낸다.</li>
<li>유저로부터 받은 쿠키를 세션 저장소에서 대조한 후 대응되는 유효한 정보가 있는경우 인증이 완료되며 사용자에 맞는 데이터를 보내준다.</li>
</ol>
<p><code>~ 재획 중 ...🍶 ~</code></p>
<ol start="7">
<li>1️⃣ 세션쿠키에 지정된 유효기간이 만료되거나
2️⃣ 쿠키가 삭제되거나
3️⃣ 서버에서 세션을 지워버리면(주로 서버에서 지정한 세션 유효기간이 만료되면)
로그인이 풀리면서 위와같은 대화창이 뜨게된다.</li>
</ol>
<h2 id="jwt">JWT</h2>
<blockquote>
<p>Json Web Token의 약자. 인증에 필요한 정보들을 암호화 시킨 토큰</p>
</blockquote>
<p>JWT 형식
<code>Encoded Header</code> + <code>.</code> + <code>Encoded Payload</code> + <code>.</code> + <code>Verify Signature</code></p>
<p><img src="https://velog.velcdn.com/images/say_ye/post/c445c23d-7fdc-4050-99f9-8883f96cc3f7/image.png" alt="">
<a href="https://jwt.io/">https://jwt.io/</a> 에 접속하면  실습해볼 수 있다 ^-^
꿀팁) jwt 토큰으로 팀즈에서 비밀얘기 할수있음 ㅋ</p>
<h2 id="jwt-기반-인증-방식">JWT 기반 인증 방식</h2>
<p><img src="https://velog.velcdn.com/images/say_ye/post/9a489f30-fbd6-4ad6-b7e4-6c11bf7f2974/image.png" alt=""></p>
<h3 id="장점-1">장점</h3>
<ul>
<li>별도의 저장소 관리가 필요없다. (Stateless)</li>
<li>확장성이 뛰어나고 유지, 보수하는데 유리하다</li>
<li>토큰 기반으로 하는 다른 인증 시스템에 접근 가능 하다. (ex. 페이스북 로그인, 구글 로그인 등)<h3 id="단점-1">단점</h3>
</li>
<li>이미 발급된 jwt에 대해서 돌이킬 수 없다. 세션/쿠키방식은 악의적인 접근이 예상되는 ID의 해당세션을 지워버리면 인증이 만료되지만 jwt방식은 불가능하다.</li>
<li>payload에 넣을 수 있는 정보가 제한적이다. payload는 암호화 되지 않기 때문에 중요 정보는 넣을 수 없다.</li>
<li>JWT의 길이는 세션/쿠키에 비해 길다. 요청이 많아질수록 서버의 자원낭비가 발생한다.
<strong>해결책) Access Token(유효기간 짧음)과 Refresh Token(유효기간 긺)을 함께 발급한다.</strong><pre><code>  → 저장소에 대한 고민이 필요하다... 주로 Access Token은 local storage에,  Refresh Token은 서버사이드에 저장하며, Refresh token 의 index 값을 쿠키나 로컬스토리지에 저장하는 것 같다.
  → 프론트, 서버 모두 구현이 복잡해진다.
  → Access Token이 만료 될 때마다 새롭게 발급하는 과정에서 생기는 HTTP 요청 횟수가 많아 서버의 자원낭비가 발생한다 - 프론트단에서 Access Token payload를 통해 유효기간을 알아내 과정을 단축하자.</code></pre></li>
</ul>
<hr>
<p>참고링크
<a href="https://tansfil.tistory.com/58">https://tansfil.tistory.com/58</a>
<a href="https://jwt.io/">https://jwt.io/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 다이나믹 프로그래밍]]></title>
            <link>https://velog.io/@say_ye/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8B%A4%EC%9D%B4%EB%82%98%EB%AF%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@say_ye/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EB%8B%A4%EC%9D%B4%EB%82%98%EB%AF%B9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Tue, 31 May 2022 12:36:17 GMT</pubDate>
            <description><![CDATA[<h2 id="다이나믹-프로그래밍">다이나믹 프로그래밍</h2>
<blockquote>
<p>한 번 계산한 문제는 다시 계산하지 않도록 하는 알고리즘</p>
</blockquote>
<ul>
<li>이전에 했던 계산을 캐싱해놓고 다시 사용하면서 중복되는 연산을 줄인다.</li>
<li>큰 문제를 작은 문제로 나눌 수 있다.</li>
<li>작은 문제에서 구한 정답은 그것을 포함하는 큰 문제에서도 동일하다.</li>
<li><code>점화식</code>을 찾아내고 구현하는것이 핵심<h3 id="탑다운메모제이션-방식">탑다운(메모제이션) 방식</h3>
<blockquote>
<p>큰 문제를 해결하기 위해 작은 문제를 호출하는 방식</p>
</blockquote>
</li>
</ul>
<pre><code class="language-python"># top-down 방식으로 구현한 피보나치 함수
d = [0] * 100

def fibo(x):
    if x == 1 or x == 2:
        return 1
    if d[x] != 0:
        return d[x]
    dx = fibo(x-1) + fibo(x-2)
    return d[x]

print(fibo(99))</code></pre>
<h3 id="보텀업-방식">보텀업 방식</h3>
<blockquote>
<p>작은 문제부터 답을 내면서 큰 문제에 접근해나가는 방식</p>
</blockquote>
<pre><code class="language-python"># bottom-up 방식으로 구현한 피보나치 함수
d = [0] * 100

d[1] = 1
d[2] = 1
n = 99

for i in range(3, n + 1):
    d[i] = d[i-1] + d[i-2]

print(d[n])</code></pre>
<h3 id="참고">참고</h3>
<p>가능하다면 재귀 함수를 이용하는 탑다운 방식보다는 보텀업 방식으로 구현하는것을 권장한다.재귀함수의 스택 크기가 한정되어 있을 수 있기 때문이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 2294 동전2 - python]]></title>
            <link>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-2294-%EB%8F%99%EC%A0%842-python</link>
            <guid>https://velog.io/@say_ye/%EB%B0%B1%EC%A4%80-2294-%EB%8F%99%EC%A0%842-python</guid>
            <pubDate>Fri, 27 May 2022 16:17:59 GMT</pubDate>
            <description><![CDATA[<p>문제 링크
<a href="https://www.acmicpc.net/problem/2294">https://www.acmicpc.net/problem/2294</a></p>
<p><strong>이것이 코딩 테스트다 with 파이썬</strong> 책에 실린 <code>효율적인 화폐 구성</code> 과 같은 유형의 문제이다.</p>
<h3 id="시도1-성공">시도1. 성공</h3>
<pre><code class="language-python">n, k = map(int, input().split())

coins = []
dp = [100000] * 10001
dp[0] = 0
for _ in range(n):
  coins.append(int(input()))

for i in range(n):
  for j in range(coins[i], k+1):
      dp[j] = min(dp[j - coins[i]]+1, dp[j])

print(dp[k] if dp[k] != 100000 else -1)</code></pre>
<ul>
<li>접근방법 : 다이나믹 프로그래밍</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[네트워크] HTTP]]></title>
            <link>https://velog.io/@say_ye/HTTP</link>
            <guid>https://velog.io/@say_ye/HTTP</guid>
            <pubDate>Fri, 27 May 2022 13:39:11 GMT</pubDate>
            <description><![CDATA[<h2 id="http">HTTP</h2>
<h3 id="http란">HTTP란?</h3>
<blockquote>
<p>HyperText Transfer Protocol. 웹의 구성요소들이 데이터를 주고받기 위해 정의한 통신 프로토콜</p>
</blockquote>
<h3 id="특징">특징</h3>
<ul>
<li>상태가 없다(stateless). 즉, 서버가 클라이언트의 이전 상태를 보존하지 않는다.</li>
<li><blockquote>
<p>이전 상태 정보가 필요한 경우를 위해 쿠키등을 사용할 수 있음.</p>
</blockquote>
</li>
<li>80번 포트를 사용한다.</li>
</ul>
<h3 id="http10">HTTP/1.0</h3>
<ul>
<li>각 요청/응답에 대해서 매번 TCP Connection이 필요하다.</li>
</ul>
<h3 id="http11">HTTP/1.1</h3>
<ul>
<li>persistent connecting 도입. (일정 시간동안 connection을 닫지 않는 방식)</li>
<li>커넥션당 하나의 요청과 응답만 처리한다. 즉, 여러개의 요청과 응답을 한번에 전송할 수 없다.</li>
<li>TCP/IP 통신위에서 동작한다.</li>
<li>리소스의 개수에 비례하여 응답시간이 증가한다.</li>
</ul>
<h3 id="http2">HTTP/2</h3>
<ul>
<li>HTTP 메시지를 사람이 읽을 수 없게 캡슐화 한다.</li>
<li>중복헤더 제거</li>
<li>커넥션당 여러개의 요청과 응답이 처리 가능하다. 즉, 다중요청 및 응답이 가능하다.</li>
<li>TCP/IP 통신위에서 동작한다.</li>
<li>HTTP/1.1보다 약 50%가량 빠르다</li>
</ul>
<h3 id="http3">HTTP/3</h3>
<ul>
<li>UDP를 경유하여 사용되는 QUIC(Quick UDP Internet Connections) 프로토콜을 사용한다.</li>
<li><strong>HOL(Head-Of-Line-Blocking)</strong> 이라는 TCP의 HTTP/2의 주된 문제를 해결하려는 목적
 <em>HOL : 입력포트에서 패킷이 출력 포트로 전달되지 못하고 대기상태에 있는 현상</em></li>
</ul>
<h3 id="https">HTTPS</h3>
<p>HTTP에 데이터 암호화가 추가된 프로토콜 (Secure의 S)</p>
<ul>
<li><p>네트워크 상에서 중간에 제3자가 데이터를 볼 수 없도록 <strong>공개키/개인키 암호화</strong>를 지원한다.</p>
<ul>
<li><p>대칭키</p>
<ul>
<li>암호화에 사용하는 키 = 복호화에 사용하는 키<ul>
<li>송신자 - 수신자가 동일한 대칭키를 가지고 있어야 한다.</li>
<li>키 배송 중에 키가 탈취될 수 있다.</li>
<li>통신하는 사람이 증가할 수록 따로따로 키 교환을 해야하기때문에 관리해야 할 키가 방대하게 많아진다.</li>
</ul>
</li>
<li>공개 암호화 방식에 비해 속도가 빠르다</li>
</ul>
<ul>
<li><p>비대칭키(공개키)</p>
<ul>
<li>암호화에 사용하는키 ≠ 복호화에 사용하는 키</li>
<li>공개키 - 개인키 쌍(암호화키 - 복호화키 쌍)</li>
<li>공개는 키가 공개되어있기 때문에 따로 키교환이나 분배를 할 필요가 없어진다.</li>
<li>개인키를 가지고 있는 수신자만이 암호화된 데이터를 복호화할 수 있다.</li>
<li>대칭키 방식에 비해 속도가 느리다.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>443번 포트를 사용한다.</p>
</li>
<li><p>인증기관에서 검증된 사이트만 https주소를 사용할 수 있기 때문에 신뢰할 수 있는 사이트라는것을 증명한다.</p>
<ul>
<li><p>HTTPS 인증받는법</p>
<ol>
<li>개인 키와 공개 키 쌍을 만들고 조직과 공개 키에 관한 정보를 포함하는 CSR(Certificate Signing Request)을 준비한다.</li>
<li>인증 기관에 연결해 CSR 기반 HTTPS 인증서를 요청한다.</li>
<li>서명된 HTTPS 인증서를 획득하고 웹 서버에 인증서를 설치한다.</li>
</ol>
</li>
<li><p>HTTPS 예
 <img src="https://velog.velcdn.com/images/say_ye/post/bcd06ba2-05c9-42d4-a105-4164ebae2744/image.png" alt=""></p>
<ul>
<li>HTTP 예
<img src="https://velog.velcdn.com/images/say_ye/post/469a137b-cf02-46f0-b7f4-1aa0cb2a46b7/image.png" alt="">
국방부는 https를 사용하지만 국토교통부는 http로 되어있다. 세금이 가성비있게 사용되고있는 모습이다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="http-메시지-구조">HTTP 메시지 구조</h3>
<blockquote>
<p>start-line 시작 라인
header 헤더
message body
empty line 공백 라인(CRLF, 필수)</p>
</blockquote>
<ol>
<li><p>시작라인
 요청 (request-line)
 <strong>HTTP메서드 요청대상 HTTP버전</strong>
 예) <code>GET /search?q=hello&amp;hl=ko HTTP/1.1</code></p>
<ul>
<li><p>HTTP메서드 : GET, POST, PUT, DELETE, ...</p>
</li>
<li><p>요청 대상 : /로 시작하는 절대경로로 작성 (절대경로[?쿼리])</p>
<p>응답 (status-line)</p>
</li>
<li><p><em>HTTP버전 상태코드 상태문구*</em>
예) <code>HTTP/1.1 200 OK</code></p>
</li>
<li><p>상태코드 : 요청의 성공, 실패를 나타내는 코드
  200 : 성공, 400 : 클라이언트 요청 오류, 500 : 서버 내부 오류</p>
</li>
<li><p>상태문구 : 사람이 이해할 수 있는 짧은 상태 설명 글</p>
</li>
</ul>
</li>
<li><p>헤더라인
 요청
 예) <code>Host: www.google.com</code>
 응답
 예) <code>Content-type: text/html;charset=UTF-8</code>
 HTTP전송에 필요한 부가정보가 들어있음.
 (메시지 바디의 내용, 크기, 압축, 인증, 요청 클라이언트 정보, 서버 애플리케이션 정보, 캐시관리 정보 등...)
 key : value 로 되어있다</p>
</li>
<li><p>메시지 바디
 실제 전송할 데이터가 담겨있는 부분</p>
</li>
</ol>
<h3 id="http-methods">HTTP Methods</h3>
<ul>
<li>GET : 데이터 받아오기</li>
<li>POST : 데이터 생성/수정/삭제. (멱등x)</li>
<li>OPTIONS : 요청 URI에서 사용할 수 있는 Method를 받아올 때 사용</li>
<li>PUT : 데이터 생성/수정. 리소스의 모든 속성을 수정하기 위해 사용. POST랑 겹쳐서 잘 안씀. (멱등o)</li>
<li>PATCH : 데이터의 수정. 리소스의 일부분만 수정하기 위해 사용.</li>
<li>DELETE : 데이터 삭제. POST랑 겹쳐서 잘 안씀</li>
</ul>
<h2 id="http-커넥션">HTTP 커넥션</h2>
<p><img src="https://velog.velcdn.com/images/say_ye/post/2498cc74-3228-451d-b18c-ca6781a541ea/image.png" alt=""></p>
<p>HTTP 커넥션은 몇가지 규칙을 제외하고는 TCP 커넥션과 동일합니다.
TCP는 HTTP에게 신뢰할 수 있는 통신 방식을 제공합니다.</p>
<h2 id="http-트랜잭션의-지연">HTTP 트랜잭션의 지연</h2>
<p>HTTP 트랜잭션은 다음과 같은 과정을 거칩니다.</p>
<blockquote>
<p>DNS 찾기 - TCP 연결 - TCP 요청 전송 - 서버단에서의 처리 - TCP 응답 전송</p>
</blockquote>
<p>위에서 보이는 바와 같이 HTTP 요청 과정에서는 TCP 커넥션을 설정하고, 요청을 전송하고, 응답 메시지를 보내는 것에서 많은 시간이 소요됩니다.
따라서 TCP 성능의 특성을 이해하면 HTTP 커넥션 최적화를 잘 해낼 수 있습니다.</p>
<h3 id="tcp-성능에-대한-고려">TCP 성능에 대한 고려</h3>
<p>TCP 네트워크 지연은 하드웨어의 성능, 네트워크와 서버의 전송 속도, 메시지의 크기, 클라이언트와 서버간의 거리, TCP 프로토콜의 기술적인 복잡성에 크게 영향을 받습니다. 
특히, HTTP 프로그래머에게 영향을 주는 가장 일반적인 TCP지연요소는 다음과 같습니다.</p>
<ul>
<li><p><strong>TCP 커넥션의 핸드셰이크 설정</strong>
HTTP 트랜잭션의 상당부분은 커넥션의 생성단계인 핸드셰이크에 의해 지연됩니다.
이러한 지연을 제거하기 위해 HTTP는 이미 존재하는 커넥션을 재활용 합니다.</p>
</li>
<li><p><strong>인터넷의 혼잡을 제어하기 위한 TCP의 느린 시작</strong>
TCP 커넥션은 몇번의 데이터를 주고 받으면서 튜닝을 거쳐 최대 속도 제한을 높여나갑니다.
이 때문에 새롭게 생성된 튜닝되지않은 커넥션은 느립니다.</p>
</li>
<li><p><strong>데이터를 한데 모아 한 번에 전송하기 위한 네이글 알고리즘</strong>
네이글 알고리즘은 네트워크의 효율을 위해, 세그먼트가 최대크기가 되지 않으면 전송을 하지 않다가 전송하기 충분한 만큼의 패킷이 쌓였을 때 함께 전송합니다. 
HTTP 애플리케이션의 성능향상을 위해 HTTP 스택에 TCP_NODELAY 파라미터 설정을 통해 이를 비활성하기도 합니다.</p>
</li>
<li><p><strong>TCP의 편승(piggyback) 확인응답(acknowlegment)을 위한 확인응답 지연 알고리즘</strong>
TCP 커넥션에서는 신뢰성있는 통신을 위해 요청에 대한 확인응답 패킷을 반환하는데, 이 확인응답 패킷은 크기가 작기때문에 주변 송출 데이터 패킷에 같이 실려갈 수 있습니다.
이 때 이 확인 응답이 버퍼에 특정시간동안 머물러 있으면서 송출 데이터 패킷을 찾는 알고리즘에 의해 시간이 지연됩니다.
이 기능은 수정하거나 비활성화 할 수 있습니다.</p>
</li>
<li><p><strong>TIME_WAIT 지연과 포트 고갈</strong>
제한되어있는 수의 포트가 고갈되는 현상에 의해 커넥션이 지연되기도 합니다.</p>
</li>
</ul>
<h3 id="http-커넥션에-대한-고려">HTTP 커넥션에 대한 고려</h3>
<ul>
<li><strong>Connection 헤더에 대한 잘못된 이해</strong></li>
<li><strong>순차적인 트랜잭션 처리에 의한 지연</strong>
리소스를 순차적으로 로드 하는 방식은 물리적/심리적 지연을 야기합니다.</li>
</ul>
<h2 id="http-커넥션의-성능을-향상시키는-기술">HTTP 커넥션의 성능을 향상시키는 기술</h2>
<h3 id="병렬-커넥션">병렬 커넥션</h3>
<p>여러개의 커넥션을 연결하여 HTTP 트랜잭션을 순차적으로 처리하는것이 아닌, 병렬적으로 동시에 처리하는 방법입니다.</p>
<ul>
<li>페이지를 더 빠르게 내려받습니다.
일반적으로 객체가 여러개 있는 웹페이지를 더 빠르게 내려받을 수 있습니다. HTML 페이지를 먼저 내려받고 남은  트랜잭션이 병렬로 로드되어 총 지연시간이 줄어듭니다.</li>
<li>항상 더 빠르지는 않습니다.
네트워크 대역폭이 좁은경우(즉, 데이터 전송 속도가 느린경우) 병렬 커넥션을 생성하는 부하때문에 오히려 더 오래걸릴수도 있습니다.
다수의 커넥션은 메모리를 많이 소모하고 자체적인 성능 문제를 발생시킵니다.</li>
<li>실제로는 순차적인 처리보다 느리더라도 사용자는 심리적으로 더 빠르다고 느낄 수 있습니다.</li>
<li>각 트랜잭션마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소요됩니다.</li>
<li>각각의 새로운 커넥션은 TCP의 느린 시작 때문에 성능이 떨어집니다.</li>
<li>실제로 연결할 수 있는 병렬 커넥션의 수에는 제한이 있습니다. <h3 id="지속-커넥션">지속 커넥션</h3>
처리가 완료된 후에도 계속 연결상태로 있는 TCP 커넥션을 말합니다.
HTTP/1.1버전을 지원하는 기기는 TCP 커넥션을 유지하여 이후의 HTTP 요청에 재사용 할 수 있습니다.</li>
<li>커넥션을 맺기위한 준비작업에 따르는 시간을 절약할 수 있습니다.</li>
<li>TCP의 느린 시작을 피하고 튜닝된 커넥션을 유지합니다.</li>
<li>커넥션의 수를 줄여줍니다.</li>
<li>지속 커넥션을 잘못 관리할 경우, 계속 연결된 상태로 있는 수많은 커넥션이 쌓여 리소스의 불필요한 소모를 발생시킵니다.</li>
</ul>
<h4 id="keep-alive-커넥션">Keep-Alive 커넥션</h4>
<ul>
<li>HTTP/1.0 에서 지원하는 지속 커넥션입니다. 설계상의 문제가 있었기 때문에 HTTP/1.1 명세에서는 빠졌습니다.</li>
<li>커넥션을 유지하기 위해서 요청 혹은 응답에 <code>Connection:Keep-Alive</code> 헤더를 포함시킵니다. 이 헤더가 없으면 메시지가 전송 된 후 서버 커넥션을 끊을 것이라 추정합니다. </li>
<li>keep-alive 동작은 <code>Keep-Alive</code> 헤더의 쉼표로 구분된 옵션 값들로 제어할 수 있습니다.<h3 id=""></h3>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>