<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>work0ut</title>
        <link>https://velog.io/</link>
        <description>work0ut</description>
        <lastBuildDate>Fri, 24 May 2024 08:34:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>work0ut</title>
            <url>https://velog.velcdn.com/images/dl-ne_w_b_ie/profile/edc92f95-24ec-486a-970c-628f2bda7269/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. work0ut. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dl-ne_w_b_ie" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[알고리즘 정]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%A0%95</guid>
            <pubDate>Fri, 24 May 2024 08:34:32 GMT</pubDate>
            <description><![CDATA[<h2 id="dfs에서의-그래프-유형">DFS에서의 그래프 유형</h2>
<h3 id="1-인접-행렬">1. 인접 행렬</h3>
<pre><code class="language-python"># 변수 선언 및 입력
n, m = tuple(map(int, input().split()))

#index를 1번 부터 사용하기 위해 n+1만큼 할당합니다.
graph = [
    [0 for _ in range(n + 1)]
    for _ in range(n + 1)
]

visited = [False for _ in range(n + 1)]
vertex_cnt = 0

def dfs(vertex):
    global vertex_cnt

    # 해당 정점에서 이어져있는 모든 정점을 탐색해줍니다.
    for curr_v in range(1, n + 1):
        # 아직 간선이 존재하고 방문한 적이 없는 정점에 대해서만 탐색을 진행합니다.
        if graph[vertex][curr_v] and not visited[curr_v]:
            visited[curr_v] = True
            vertex_cnt += 1
            dfs(curr_v)


for i in range(m):
    v1, v2 = tuple(map(int, input().split()))

    # 각 정점이 서로 이동이 가능한 양방향 그래프이기 때문에
    # 각 정점에 대한 간선을 각각 저장해줍니다.
    graph[v1][v2] = 1
    graph[v2][v1] = 1

visited[1] = True
dfs(1)

print(vertex_cnt)</code></pre>
<h3 id="2-인접-리스트">2. 인접 리스트</h3>
<pre><code class="language-python"># 변수 선언 및 입력
n, m = tuple(map(int, input().split()))

#index를 1번 부터 사용하기 위해 m+1만큼 할당합니다.
graph = [[] for _ in range(n + 1)]

visited = [False for _ in range(n + 1)]
vertex_cnt = 0

def dfs(vertex):
    global vertex_cnt

    # 해당 정점에서 이어져있는 모든 정점을 탐색해줍니다.
    for curr_v in graph[vertex]:
        # 아직 간선이 존재하고 방문한 적이 없는 정점에 대해서만 탐색을 진행합니다.
        if not visited[curr_v]:
            visited[curr_v] = True
            vertex_cnt += 1
            dfs(curr_v)


for i in range(m):
    v1, v2 = tuple(map(int, input().split()))

    # 각 정점이 서로 이동이 가능한 양방향 그래프이기 때문에
    # 각 정점에 대한 간선을 각각 저장해줍니다.
    graph[v1].append(v2)
    graph[v2].append(v1)

visited[1] = True
dfs(1)

print(vertex_cnt)</code></pre>
<h3 id="인접-리스트와-인접-행렬의-차이점">인접 리스트와 인접 행렬의 차이점</h3>
<pre><code class="language-python">for curr_v in graph[vertex]:
    if not visited[curr_v]:
        visited[curr_v] = True
        vertex_cnt += 1
        dfs(curr_v)</code></pre>
<p>인접 리스트</p>
<pre><code class="language-python">for curr_v in range(1, n + 1):
    if graph[vertex][curr_v] and 
        not visited[curr_v]:
            visited[curr_v] = True
            vertex_cnt += 1
            dfs(curr_</code></pre>
<p>인접 행렬</p>
<h2 id="도달할-수-있는-정점의-수-구하기">도달할 수 있는 정점의 수 구하기</h2>
<pre><code class="language-python">import sys
import copy

## sys.exit() 디버깅 아예종료
## sys.maxsize = 정수 최대값

n,m = map(int,input().split())
graph = [
    list(map(int,input().split()))
    for i in range(n)
]

visited=[[0 for i in range(n)] for l in range(m)]

dxs, dys = [1,0], [0,1]

def can_go(x,y):
    print(x,y)
    if x&lt;m and x&gt;=0 and y&lt;n and y&gt;=0:
        return True
    if visited[x][y]==0:
        return False
    return False

cnt=0

def dfs(x,y):
        # dx, dy로 이동할 수 있는 방법 경우의 수 작성
    for dx, dy in zip(dxs,dys):
        dx, dy = x + dx, y + dy
        if dx&lt;n and dx&gt;=0 and dy&lt;m and dy&gt;=0:
            if graph[dx][dy]==1:
                graph[dx][dy]=0
                visited[dx][dy]=1
                dfs(dx,dy)

visited[0][0]=1
dfs(0,0)
if visited[-1][-1]==1:
    print(1)
else:
    print(0)</code></pre>
<h2 id="dfs-stack">DFS (Stack)</h2>
<ul>
<li>최대한 깊게 탐색한 후 더이상 도달할 수 없는 상황이라면 이전으로 돌아가는 방식
따라서 , 방문할 수 있는 지점이 있다면 방문하는 함수를 재귀호출. 더 이상 없다면 함수를 종료</li>
</ul>
<p>→ 유의점은 <strong>방문했던 지점을 또 방문</strong>하면 <strong>효율이 떨어지므로 visited라는 배열을 만들어 이전에
방문 여부를 확인</strong>해야함</p>
<p><strong>반드시 재귀함수를 이용</strong>하여 작성함</p>
<h1 id="heapq">Heapq</h1>
<ul>
<li>가장 작은 두 숫자를 계속 빠르게 구해주기 위해 사용</li>
</ul>
<pre><code class="language-python">import heapq

# 변수 선언 및 입력:
n = int(input())
arr = list(map(int, input().split()))

pq = []
ans = 0

# 우선순위 큐에 원소들을 전부 넣어줍니다.
# 작은 숫자 2개를 골라 합치는 것이 항상 유리함을 이용해야 하므로
# 작은 숫자가 먼저 골라질 수 있도록 해야합니다.
for elem in arr:
    heapq.heappush(pq, elem)

# 원소가 2개 이상이면 계속
# 가장 작은 숫자 2개를 골라
# 합치는 것을 반복합니다.
while len(pq) &gt; 1:
    x1 = heapq.heappop(pq)
    x2 = heapq.heappop(pq)

    # 가장 작은 숫자 2개를 더하기 위한 비용을 답에 더해주고,
    # 두 숫자를 합친 결과를 우선순위 큐에 다시 넣어줍니다.
    ans += (x1 + x2)
    heapq.heappush(pq, x1 + x2)

print(ans)</code></pre>
<h1 id="묶음-내-특정-원소를-기준으로-정렬하는-방법">묶음 내 특정 원소를 기준으로 정렬하는 방법</h1>
<pre><code class="language-python">lst = [~~]
# N번째 원소 기준으로 오름차순 정렬시
lst.sort(key=lambda x:x[n-1]

# N번째 원소 기준으로 내림차순 정렬시
lst.sort(key=lambda x:x[n-1], reverse=True)</code></pre>
<h3 id="lambda-란">Lambda 란?</h3>
<pre><code class="language-python">lambda a : b</code></pre>
<ul>
<li>a : 입력 인자</li>
<li>b: 입력 인자를 사용하여 계산할 값 즉, 계산하고 반환되는 값을 의미</li>
</ul>
<h1 id="특정-기준을-만족하는-배열-만들기">특정 기준을 만족하는 배열 만들기</h1>
<h2 id="cmp_to_keycompare">cmp_to_key(compare)</h2>
<pre><code class="language-python">def compare(x, y):
    if x+y &gt; y+x:
        return -1
    elif x+y == y+x:
        return 0
    else:
        return 1</code></pre>
<ol>
<li>양수 return → 두 input의 자리를 변경</li>
<li>음수 return → 두 input의 자리 유지</li>
</ol>
<h2 id="두-가지-방안으로-사용-가능">두 가지 방안으로 사용 가능</h2>
<pre><code class="language-python">arr.sort(key=cmp_to_key(compare))

arr = sorted(l, key=cmp_to_key(compare))</code></pre>
<ul>
<li>Key란 정렬 조건을 의미함<ul>
<li>따라서 compare조건에 따른 정렬 조건을 임의로 만드는</li>
</ul>
</li>
</ul>
<h1 id="동전-개수-최소로-구하기">동전 개수 최소로 구하기</h1>
<p>$O(N)$ </p>
<p><strong>5원 동전 개수를 정하고 차액을 2로 나눌 수 있는지</strong></p>
<pre><code class="language-python">MAX_NUM = n//5

for i in range(0, MAX_NUM + 1):
    remainder = n - 5 * i
    if remainder &gt;= 0 and remainder % 2 == 0:
        ans = min(ans, i + (remainder // 2))
</code></pre>
<p>$O(N^2)$</p>
<p>5원 개수 최대치와 2원 개수 최대치를 모두 탐색</p>
<pre><code class="language-python">M = n//2
m = n//5

for i in range(m,0,-1):
    for l in range(M):
        if (i*5+l*2)==n:
            lst.append(l+i)</code></pre>
<h1 id="xor">XOR</h1>
<ul>
<li><p>arr[i] ^= 1은 arr[i]의 값이 0이면 1로, 1이면 0으로 바꾸는 작업을 수행</p>
<ul>
<li><p><strong>두 비트가 같으면 0을 반환 (0 ^ 0 = 0, 1 ^ 1 = 0)</strong></p>
</li>
<li><p><strong>두 비트가 다르면 1을 반환 (1 ^ 0 = 1, 0 ^ 1 = 1)</strong></p>
<h1 id="1-sys">1. sys</h1>
</li>
</ul>
</li>
<li><p>sys.exit()</p>
<ul>
<li>함수 바로 종료</li>
</ul>
</li>
<li><p>sys.maxsize</p>
<ul>
<li>정수형 값중 최대값</li>
</ul>
</li>
</ul>
<h1 id="2-깔끔한-코드">2. 깔끔한 코드</h1>
<ul>
<li>최소값 리턴</li>
</ul>
<pre><code class="language-python">if current &gt; sub:
    current = sub

---------------------------------------------

current = min(current,sub)</code></pre>
<ul>
<li>배열에서 n개 원소 제외한 값의 경우의 수</li>
</ul>
<pre><code class="language-python"># 총 합을 계산하고, 2중 for문을 통해 해당하는 원소만 골라서 합에서 빼주는 방

a = sum(list)
for i in range(len(list)):
    for l in range(i+1, n):
        del_2_param = a - list[i] - list[l]

---------------------------------------------        

# 나는 원소 한개 빼고 딥카피를 반복함 

for i in range(n):
    sub = copy.deepcopy(lst)
    del sub[i]
    for l in range(len(sub)):
        sub_2 = copy.deepcopy(sub)
        del sub_2[l]
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 헤더 2]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/HTTP-%ED%97%A4%EB%8D%94-2</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/HTTP-%ED%97%A4%EB%8D%94-2</guid>
            <pubDate>Mon, 15 Apr 2024 13:49:56 GMT</pubDate>
            <description><![CDATA[<h1 id="인증">인증</h1>
<h2 id="authorization">Authorization</h2>
<ul>
<li>클라이언트 인증 정보를 서버에 전달</li>
</ul>
<h2 id="www-authenticate">WWW-Authenticate</h2>
<ul>
<li>리소스 접근시 필요한 인증 방법 정의</li>
<li>보통 401 Unauthorized 응답과 함께 사용한다<ul>
<li>WWW-Authenticate : Newauth realm=&quot;apps&quot;, type=1, title=&quot;Login to &quot;apps&quot;&quot;,Basic realm=&quot;simple&quot;</li>
</ul>
</li>
</ul>
<hr>
<p><strong>Newauth realm=&quot;apps&quot;, type=1, title=&quot;Login to &quot;apps&quot;&quot;</strong></p>
<ul>
<li>Newauth라는 사용자 정의 인증 방식을 설명</li>
</ul>
<p>** realm=&quot;apps&quot;**</p>
<ul>
<li>인증이 적용되는 영역, 자원을 의미하며 클라이언트에게 어떤 영역에 대한 인증이 필요한지 알려주는 역할</li>
</ul>
<p><strong>type=1, title=&quot;Login to &quot;apps&quot;&quot;</strong></p>
<ul>
<li>추가적인 인증 정보를 의미하며 구체적인 방법은 서버, app의 문서를 참조해야함</li>
</ul>
<p><strong>Basic realm=&quot;simple&quot;</strong></p>
<ul>
<li>HTTP 기본 인증을 의미하며, 사용자의 이름과 비밀번호를 :로 연결 후 Base64로 인코딩하여 전송함</li>
</ul>
<hr>
<h2 id="stateless-무상태">Stateless (무상태)</h2>
<ol>
<li>HTTP는 무상태 프로토콜</li>
<li>요청과 응답을 주고받으면 연결이 끊어짐</li>
<li>재 요청시 서버는 이전 요청을 기억하지 못함</li>
<li>서로 상태를 유지하지 않음</li>
</ol>
<p><strong>위 특징을 해결하기 위해 착안한 방안</strong></p>
<h2 id="1-쿠키">1. 쿠키</h2>
<h3 id="set-cookie">Set-Cookie</h3>
<ul>
<li>서버에서 클라이언트로 쿠키 전달<h3 id="cookie">Cookie</h3>
</li>
<li>클라이언트가 서버에서 받은 쿠키를 저장 후, HTTP 요청시 서버로 전달<h3 id="생명-주기">생명 주기</h3>
</li>
<li><strong>영속 쿠키</strong></li>
</ul>
<ol>
<li><p>Set-Cookie : expires=sat, OO-DEC-OOOO 00:00:00 GMT</p>
<p> 만료일 지날경우 삭제</p>
</li>
<li><p>Set-Cookie : max-age=3600</p>
<p> 0이나 음수 지정시 쿠키 삭제</p>
</li>
</ol>
<ul>
<li><p><strong>세션 쿠키</strong></p>
<p>  만료 날짜 생략시 브라우저 종료시 까지만 유지</p>
<h3 id="도메인">도메인</h3>
</li>
</ul>
<p><strong>domain=example.org</strong></p>
<ol>
<li>명시 - 명시한 문서 기준 도메인 + 서브 도메인 포함</li>
</ol>
<ul>
<li><p>domain=example.org 쿠키 생성시</p>
<ul>
<li>example.org, dev.example.org도 쿠키 <strong>접근 가능</strong></li>
</ul>
</li>
</ul>
<ol start="2">
<li>생략 - 현재 문서 기준 도메인만 적용</li>
</ol>
<ul>
<li><p>example.org에서 쿠키 생성 후 domain 지정을 생략</p>
<ul>
<li>example.org 에서만 쿠키 접근, dev.example.org는 쿠키 <strong>미접근</strong></li>
</ul>
</li>
</ul>
<h3 id="경로">경로</h3>
<p>경로를 포함한 하위 경로 페이지만 쿠키 접근</p>
<p>ex)</p>
<ul>
<li>path=/home 지정 시,</li>
<li>/home, /home/level1/~ <strong>가능</strong></li>
<li>/hello <strong>불가능</strong></li>
</ul>
<h3 id="보안">보안</h3>
<h4 id="1-secure">1. Secure</h4>
<ul>
<li>쿠키는 http,https 구분하지 않고 전송</li>
<li>Secure 적용시 https인 경우에만 전송한다<h4 id="2-httponly">2. HttpOnly</h4>
</li>
<li>JS에서 접근 불가능함</li>
<li>HTTP 전송에만 사용함<h4 id="3-samesite">3. SameSite</h4>
</li>
<li><strong>요청 도메인과 쿠키에 설정된 도메인이 같은 경우</strong>만 쿠키를 전송한다</li>
</ul>
<h4 id="사용처">사용처</h4>
<ol>
<li>사용자 로그인 세션 관리</li>
<li>광고 정보 트래킹</li>
</ol>
<p><strong>주의 사항</strong></p>
<ul>
<li>보안에 민감한 데이터 저장 지양</li>
</ul>
<h3 id="생명-주기-1">생명 주기</h3>
<h2 id="11-쿠키-미사용시">1.1 쿠키 미사용시</h2>
<ul>
<li>모든 요청과 링크에 사용자 정보를 포함시킨다</li>
</ul>
<p>-&gt; 브라우저 완전히 종료하고 다시 열면 동일한 문제 발생 
-&gt; 요청마다 데이터 낭비가 생길 가능성이 높음</p>
<h2 id="2-캐시">2. 캐시</h2>
<h3 id="캐시가-없을-때의-특징">캐시가 없을 때의 특징</h3>
<ol>
<li>데이터 변경이 없어도 계속 네트워크를 통해 데이터를 다운받아야함</li>
<li>브라우저 로딩 속도가 느림</li>
</ol>
<h3 id="캐시-사용시-특징">캐시 사용시 특징</h3>
<ol>
<li>캐시 유효 시간동안 네트워크를 사용하지 않아도 됨</li>
<li>브라우저 로딩 속도가 빨라짐</li>
</ol>
<pre><code>HTTP/1.1 200 OK
Content-Type: image/jpeg
cache-control: max-age=60 //브라우저 내의 캐시에서의 유효시간 60초를 의미
Content-Length: 34012

--message body--</code></pre><h3 id="캐시-시간-초과">캐시 시간 초과</h3>
<ul>
<li>캐시 유효 시간 만료시 서버에서 데이터를 다시 조회, 캐시를 갱신함</li>
</ul>
<p>이때, 서버에서 기존 데이터를 변경 혹은 유지 두 가지 상황이 나타남</p>
<ol>
<li>데이터를 변경하지 않았을 경우</li>
</ol>
<ul>
<li>클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있음</li>
</ul>
<p>ex)</p>
<pre><code>HTTP/1.1 200 OK
Content-Type: image/jpeg
cache-control: max-age=60의미
Last-Modified : 0000년 00월 00일 00:00:00 // 데이터의 수정 시간을 의미
Content-Length: 34012

--message body--</code></pre><p><strong>Last-Modified</strong>를 기준으로 데이터의 수정 여부를 확인할 수 있음</p>
<p>위처럼 Last-Modified를 <strong>검증 헤더</strong>라고 하는데, 검증 헤더는 <strong>조건부 요청</strong>과 함께 쓰는 경우가 많음</p>
<h3 id="검증-헤더와-조건부-요청">검증 헤더와 조건부 요청</h3>
<ul>
<li>304 Not Modified + 헤더 메타 정보만 응답</li>
<li>응답 헤더 정보로 캐시의 메타 정보를 갱신함, 만약 미갱신시 캐시에 저장돼있는 데이터를 재활용함</li>
<li>이 과정에서 네트워크 다운로드가 발생하긴 하지만 용량이 적은 헤더 정보만을 다운받으므로 매우 실용적인 해결책임</li>
</ul>
<h4 id="검증-헤더">검증 헤더</h4>
<ul>
<li>캐시 데이터와 서버 데이터가 같은지 검증하는 데이터</li>
</ul>
<p>ex) Last-Modified, ETag</p>
<ol>
<li>Last-Modified</li>
</ol>
<ul>
<li>데이터가 수정 됐다면 200 OK, 미변경시 304 Not Modified</li>
</ul>
<ol start="2">
<li>ETag </li>
</ol>
<ul>
<li>데이터를 변경시 이름을 바꾸기 때문에 단순히 ETag를 보내서 같으면 유지, 다르면 다시 다운 받기를 선택할 수 있음
ex) ETag : &quot;v1.0&quot; -&gt; ETag: &quot;v2.0&quot; </li>
</ul>
<h4 id="조건부-요청-헤더">조건부 요청 헤더</h4>
<ul>
<li>검증 헤더로 조건에 따른 분기</li>
</ul>
<p>ex) 
If-Modified-Since: Last-Moidified 사용</p>
<p>If-None-Match : ETag 사용
<strong>조건 만족시 200 OK, 불만족시 304 Not Modified</strong></p>
<h4 id="캐시-제어-헤더">캐시 제어 헤더</h4>
<ol>
<li>Cache-Control - 캐시 제어</li>
</ol>
<hr>
<p><strong>하위 호환</strong></p>
<ol start="2">
<li>Pragma - 캐시 제어</li>
<li>Expires - 캐시 유효 기간</li>
</ol>
<h4 id="cache-control">Cache Control</h4>
<ol>
<li>max-age</li>
</ol>
<ul>
<li>캐시 유효 시간 단위</li>
</ul>
<ol start="2">
<li>no-cache</li>
</ol>
<ul>
<li>데이터는 캐시해도 되지만, 사용할때마다 본 서버에서 검증하기</li>
</ul>
<ol start="3">
<li>no-store</li>
</ol>
<ul>
<li>저장하면 안됨 (개인정보 등)</li>
</ul>
<h4 id="pragma">Pragma</h4>
<p>하위 호환으로, no-cache만을 사용함</p>
<h4 id="expires">Expires</h4>
<p>하위호환으로 캐시 만료일을 지정한다</p>
<ul>
<li>캐시 만료일을 정확한 날짜로 지정함</li>
</ul>
<p>ex) Mon, 01 Jan 1990 00:00:00 GMT</p>
<p>하지만, 현재는 cahce-control의 max-age가 더 유연하므로 사용하지 않음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 관련]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/AWS-%EA%B4%80%EB%A0%A8</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/AWS-%EA%B4%80%EB%A0%A8</guid>
            <pubDate>Tue, 09 Apr 2024 04:50:54 GMT</pubDate>
            <description><![CDATA[<h1 id="리전">리전</h1>
<p>특정 지역에 위치한 서비스 제공하는 <strong>데이터 센터의 집합</strong>을 의미한다</p>
<p>AWS에서 다수의 컴퓨팅 서비스를 제공하기 위해서 대규모 서버 컴퓨터가 필요한데, 한 곳에 전부 몰아서 만들게 된다면 2가지 단점이 부각됨</p>
<ol>
<li>재해 발생시 모든 서비스 마비
ex) 카카오톡 데이터센터 화재</li>
<li>글로벌 서비스의 경우 모든 서버 컴퓨터가 한 대륙에만 위치 할 경우 다른 대륙은 비교적 느린 서비스를 제공 받음</li>
</ol>
<h1 id="가용영역">가용영역</h1>
<p>특정 지역에 위치한 서비스를 제공하는 <strong>데이터 센터의 집합에서 그 중 하나를 의미</strong></p>
<h1 id="vpc">VPC</h1>
<p>Virtual Private Cloud의 약자로 가상의 네트워크 영역을 의미한다</p>
<p>AWS 리전 하나 당 최대 5개의 VPC가 가능하며, 각 리전에는 한 개의 default VPC가 존재함</p>
<h3 id="유의점">유의점</h3>
<ol>
<li><p>VPC는 사설 리소스이기에 사설 IPv4만 할당이 가능하다</p>
</li>
<li><p>총 5개의 아이피 주소를 호스트에 할당 할 수 없음
 2.1 서브넷의 네트워크 대역</p>
<ul>
<li>서브넷 네트워크 자체를 식별하는데 사용하기 때문</li>
</ul>
<p> 2.2 VPC 라우터에 할당</p>
<ul>
<li>VPC 라우터에 할당함으로써 서브넷 내의 인스턴스가 동일한 VPC 내의 다른 네트워크, 리소스, 인터넷과 통신 가능</li>
</ul>
<p> 2.3 Amazon이 제공하는 DNS에 할당</p>
<ul>
<li>각 VPC에 대한 DNS 서비스를 제공함과 동시에 서브넷 범위 내의 미리 정해진 IP 주소에 서비스를 할당</li>
</ul>
<p> 2.4 추후를 대비한 예약</p>
<ul>
<li>현재 사용하지 않지만, 향후 AWS가 새로운 기능을 추가함을 대비</li>
</ul>
<p> 2.5 브로드 캐스트 주소</p>
<pre><code>* 전통적으로 IP 주소 범위의 마지막 주소는 사용하지 않음</code></pre></li>
</ol>
<p><a href="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/13f90ebe-9d50-4971-a302-dbfc37707455/image.png"></a>
VPC 실 사용시 내부에서도 서브넷을 나눠서 사용한다</p>
<ul>
<li>VPC에서 나눠진 서브넷은 다시 나눌 수 없음</li>
</ul>
<h1 id="vpc와-외부-네트워크-통신">VPC와 외부 네트워크 통신</h1>
<p>일반적으로 사설 IP 대역은 공용 IP 대역과 통신이 불가한데 어떻게 통신을 할 수 있을까?</p>
<h2 id="public-subnet">Public Subnet</h2>
<p>외부와 통신이 원활한 VPC 서브넷</p>
<p>AWS에서는 Internet Gateway를 지정함으로써 서브넷을 퍼블릭 서브넷으로 사용할 수 있음</p>
<ul>
<li>네트워크 패킷이 특정 방향으로 이동하게 만드는 방법을 <strong>라우팅</strong>이라고 한다
따라서 Internet Gateway를 지정한다고 해서 외부 네트워크가 통신이 가능한게 아닌, 라우팅 테이블을 설정해줘야 정상적으로 통신이 가능하다</li>
</ul>
<h3 id="destination-target">Destination, Target</h3>
<p>Destination : VPC 주소, VPC로 들어올 때의 주소
Target : Local, 내부VPC 라우터가 보낼 곳</p>
<p>ex)
Destination : 10.0.0.0/16</p>
<ul>
<li>라우팅 테이블 내 규칙이 적용될 대상 네트워크의 IP 주소 범위를 ㅡ이미하며, VPC 내의 <strong>어떤 주소로 향하는 트래픽에 적용</strong>된다</li>
</ul>
<p>Target : Local</p>
<ul>
<li><strong>어떤 주소로 향하던 트래픽을 어디로 전달할 것인지</strong>에 대한 정보이다</li>
</ul>
<h2 id="private-subnet">Private Subnet</h2>
<p>외부와 통신되지 않는 VPC 서브넷</p>
<h3 id="사설-아이피-대역의-장점">사설 아이피 대역의 장점</h3>
<ol>
<li>부족한 아이피 주소 문제 완화</li>
<li>높은 보안성</li>
</ol>
<h4 id="높은-보안성">높은 보안성</h4>
<p><strong>포트포워딩</strong> :하나의 공용 아이피 주소를 가진 공유기가 자신의 포트를 통해 자신의 사설 아이피 주소를 가진 디바이스에게 데이터를 주는 것</p>
<p>사설 아이피를 가진 디바이스에게 데이터를 직접 줄 수 없고 공유기를 거쳐야 하므로 보안성 측면에서 강점을 가지낟</p>
<p>예를 들어 데이터베이스의 사용을 생각해보자</p>
<ol>
<li>Private Subnet은 외부와 통신이 안되면 데이터베이스를 사용할 수 없지 않나</li>
</ol>
<p>-&gt; DB를 사용하는 컴퓨팅 자원을 같은 VPC에 배치 </p>
<ol start="2">
<li>데이터베이스에 원격으로 접속하는 방법은 뭔가</li>
</ol>
<p>-&gt;Mysql Workbench, DataGrip으로 원격 접속하기</p>
<ul>
<li>Database가 Private Subnet에 존재할경우 DataGrip으로 원격 접속이 불가</li>
<li><blockquote>
<p>Bastion host를 사용함으로써 Private Subnet의 자원에 접속할 수 있도록 하기</p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[서버란 무엇인가]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/%EC%84%9C%EB%B2%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/%EC%84%9C%EB%B2%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Thu, 04 Apr 2024 09:29:01 GMT</pubDate>
            <description><![CDATA[<h1 id="서버">서버</h1>
<ul>
<li><p>OS가 다루는 프로세스를 서버라고 칭할 수 있다.</p>
</li>
<li><p>서버와 클라이언트간의 연결을 하는 매개체 역할로 <strong>소켓</strong>이 있는데, 이를 통해 IPC를 수행할 수 있다</p>
</li>
</ul>
<h4 id="ipcinter-process-communication-란">IPC(Inter-Process Communication) 란?</h4>
<ul>
<li>프로세스들간에 서로 데이터를 주고 받는 행위, 방법 또는 경로를 의미한다</li>
</ul>
<h2 id="누구에게-어디로-보낼-것-인가">누구에게 어디로 보낼 것 인가</h2>
<h3 id="ip-port">IP, Port</h3>
<p>데이터를 주고 받기 위해서는 <strong>어디로</strong>에 해당하는 주소가 매우 중요하다
<strong>누구에게</strong>를 식별하기 위해 사용되는 것이 IP주소와 포트번호이다</p>
<p>원래는 IP주소만으로 사용했지만, 컴퓨터 보급량의 증가로 IP 개수의 한계로 이를 해결하기 위해 포트번호를 도입하게 됐다</p>
<blockquote>
</blockquote>
<p>현실에 비유를 해보자면,
기존에 한국은 단독주택(IP)으로 잘 생활하고 있었다
하지만 한국의 땅 크기는 고정돼있고, 인구의 증가로 단독주택에서 아파트를 짓고 아파트 내에서 호수(포트번호)를 나누게 되었다</p>
<h2 id="어떤걸-어떻게-보낼-것-인가">어떤걸 어떻게 보낼 것 인가</h2>
<p>위에서 <strong>어디로</strong>와 <strong>누구에게</strong>를 해결했다면, 다음으로는 <strong>어떤걸</strong>,<strong>어떻게</strong>를 정해야한다</p>
<h3 id="데이터의-송수신-절차">데이터의 송수신 절차</h3>
<h4 id="송신">송신</h4>
<p>Application -&gt; <strong>Sockets</strong> -&gt; 네트워크 스택 -&gt; NIC(랜카드) -&gt; 외부</p>
<pre><code>      write()
    데이터 전송</code></pre><h4 id="수신">수신</h4>
<p>Application &lt;- <strong>Sockets</strong> &lt;- 네트워크 스택 &lt;- NIC(랜카드) &lt;- 외부</p>
<pre><code>                                      Interrupt
                                     데이터 수신</code></pre><h3 id="소켓-socket">소켓 Socket</h3>
<p>송수신 절차 중간에 껴있는 소켓은 무엇이냐
<img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/1d6c9b6d-259b-479b-8798-edca2e19c6cb/image.png" alt=""></p>
<p>그림만 봐도 알 수 있듯이, 다양한 시스템 콜이 일어나는 곳으로 os의 제어를 받는다</p>
<h3 id="소켓의-시스템-콜">소켓의 시스템 콜</h3>
<h3 id="1-socket">1. socket()</h3>
<ul>
<li>소켓의 형태를 만드는 시스템 콜<blockquote>
<p><strong>Input</strong></p>
</blockquote>
</li>
<li><em>domain*</em> - 도메인 선택<ul>
<li>IPv4, Ipv6<blockquote>
<hr>
</blockquote>
</li>
</ul>
</li>
<li><em>type*</em> - 소켓의 종류 선택<ul>
<li>stream, datagram <blockquote>
<hr>
</blockquote>
</li>
</ul>
</li>
<li><em>protocol*</em> - 프로토콜 선택<ul>
<li>tcp, udp<blockquote>
<hr>
</blockquote>
</li>
</ul>
</li>
<li><em>Output*</em>
파일 디스크립터</li>
</ul>
<p><strong>파일 디스크립터</strong></p>
<ul>
<li>OS가 파일 디스크립터를 받았을 때, 데이터를 송수신 하기 위한 소켓을 알려주는 역할을 한다</li>
</ul>
<p><strong>※ 파일 디스크립터를 소켓을 특정해주는 &#39;키&#39;라고 한다면, 그에 대한 &#39;벨류&#39;는 리소스(소켓, 파일)등 에 대한 메타데이터라고 비유할 수 있다</strong></p>
<h3 id="2-bind">2. bind()</h3>
<ul>
<li>생성한 소켓에 IP주소와 Port를 부여하는 시스템 콜<blockquote>
<p><strong>Input</strong></p>
</blockquote>
</li>
<li><em>sockfd*</em> - 바인딩 할 소켓의 파일 디스크립터</li>
<li><em>sockaddr*</em> - 바인딩 할 IP, port를 담은 구조체</li>
<li><em>socklen_t*</em> - 구조체의 메모리 크기</li>
</ul>
<h3 id="3-listen">3. listen()</h3>
<ul>
<li>연결지향 네트워크인 TCP에서만 사용하는 시스템 콜<blockquote>
<p><strong>Input</strong></p>
</blockquote>
</li>
<li><em>sockfd*</em> - 소켓의 파일 디스크립터</li>
<li><em>backlog*</em> - TCP 백로그 큐의 크기</li>
</ul>
<h3 id="4-accept">4. accept()</h3>
<ul>
<li>클라이언트의 요청을 보관해둔 백로그 큐에서 연결을 매칭시켜줌<blockquote>
<p><strong>Input</strong></p>
</blockquote>
</li>
<li><em>sockfd*</em> - 클라이언트의 요청을 받을 소켓의 파일 디스크립터</li>
<li><em>sockaddr*</em> - 백로그 큐에서 빼온 클라이언트의 주소 정보</li>
<li><em>socklen_t*</em> - 구조체의 메모리 크기<blockquote>
</blockquote>
</li>
<li><em>Output*</em>
소켓</li>
</ul>
<p>queue의 자료구조 형태를 가진 백로그 큐에서 저장된 다수의 클라이언트 요청을 순차적으로 처리하면 어쩔 수 없이 <strong>병목현상</strong>이 발생하게됨</p>
<p>이를 <strong>해결하기 위해 accept() 시스템 콜을 사용</strong>한다</p>
<p>기존에 socket()으로 서버 소켓<strong>(클라이언트의 요청을 받을 메인 소켓)</strong>을 생성했다면, accept()를 사용해 클라이언트 소켓<strong>(서버 소켓의 백 로그 큐에 있는 요청을 처리하는 보조 소켓)</strong>을 생성한다.</p>
<p><strong>보조 소켓</strong>을 <strong>병렬 처리에 사용</strong>하기 위해서 fork()라는 시스템 콜을 사용하여 프로세스를 추가로 생성한다</p>
<p>fork를 통해 추가로 생성한 프로세스와, accept를 통해 생성한 소켓을 매칭시켜줘서 병렬처리할 수 있도록한다.</p>
<p><strong>fork와 accept</strong>를 통해 <strong>병렬 처리</strong>를 함으로써 <strong>병목 현상을 해결</strong>함
하지만 병렬 처리를 함으로써 발생하는 오류인 <strong>동시성</strong>은 아직 문제이다</p>
<hr>
<h3 id="소켓의-시스템-콜-정리">소켓의 시스템 콜 정리</h3>
<p><strong>1. socket()</strong></p>
<ul>
<li>소켓의 틀을 결정하고, 파일 디스크립터를 결과값으로 반환</li>
</ul>
<p><strong>2. bind()</strong></p>
<ul>
<li>생성된 소켓에 IP와 Port번호를 부여</li>
</ul>
<p><strong>3. listen()</strong></p>
<ul>
<li>클라이언트의 요청을 보관해둘 백로그 큐를 생성</li>
</ul>
<p><strong>4. accept()</strong></p>
<ul>
<li>소켓이 통신할 준비가 됐다는 것을 알리기 위한 시스템 콜</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 헤더]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/HTTP-%ED%97%A4%EB%8D%94</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/HTTP-%ED%97%A4%EB%8D%94</guid>
            <pubDate>Tue, 26 Mar 2024 02:45:56 GMT</pubDate>
            <description><![CDATA[<h3 id="http-헤더의-변화">HTTP 헤더의 변화</h3>
<blockquote>
<p>1999년 RFC2616 -&gt; 2014년 RFC7230~7235
엔티티 ( 헤더 + 본문) -&gt; 표현 ( 데이터 + 메타데이터)</p>
</blockquote>
<p>서버가 응답 메시지를 보냈을 때를 예시로 들어보자</p>
<pre><code>HTTP/1.1 200 OK
---표현 헤더
Content-Type
Content-Length
---표현 데이터
&lt;html&gt;
  &lt;body&gt;...&lt;/body&gt;
&lt;/html&gt;</code></pre><h3 id="표현-헤더의-종류">표현 헤더의 종류</h3>
<p>표현 헤더의 경우 전송(클라이언트)과 응답(서버) 둘다 사용한다</p>
<ol>
<li>Content-Type : 메시지 바디 형식</li>
<li>Content-Encoding : 표현 데이터의 압축 방식</li>
<li>Content-Language : 표현 데이터의 자연 언어</li>
<li>Content-Length : 표현 데이터의 길이</li>
</ol>
<h3 id="표현-데이터-형식">표현 데이터 형식</h3>
<ol>
<li>Content-Type : html, json, png</li>
<li>Content-Encoding : gzip, deflate, identity</li>
<li>Content-Language : ko, en, en-US</li>
<li>Content-Length : 바이트 단위를 의미</li>
</ol>
<h3 id="협상">협상</h3>
<p>클라이언트가 선호하는 표현 요청으로, Content-Negotiation을 의미</p>
<blockquote>
<p><strong>협상 적용 전</strong></p>
</blockquote>
<p>GET /event</p>
<blockquote>
<p>-&gt;
Content-Language: en
hello</p>
</blockquote>
<hr>
<p><strong>협상 적용 후</strong></p>
<blockquote>
</blockquote>
<p>GET / event
Accept-Language: ko
-&gt;
Content-Language: ko
안녕하세요</p>
<blockquote>
</blockquote>
<p>만약, 원하는 요청이 서버에서 지원하지 않을 경우 <strong>디폴트 값으로 서버는 응답</strong>
서버에서 지원하지 않을 경우를 대비해 <strong>우선순위</strong>를 줄 수 있음</p>
<blockquote>
</blockquote>
<p>ex) Accept-Language: ko-KR, ko;q=0.9, en-US;1=0.8
Language뿐만 아니라, Type에도 적용이 가능하다</p>
<h3 id="전송-방식">전송 방식</h3>
<ol>
<li>단순 전송</li>
<li>압축 전송</li>
<li>분할 전송</li>
<li>범위 전송</li>
</ol>
<h4 id="1-단순-전송">1. 단순 전송</h4>
<p>길이(Content-Length)를 알 수 있을때만 사용</p>
<blockquote>
<p>HTTP/1.1 200 OK
Content-Type : ~
<strong>Content-Length : ~~</strong></p>
</blockquote>
<h4 id="2-압축-전송">2. 압축 전송</h4>
<blockquote>
<p>HTTP/1.1 200 OK
Content-Type : ~
<strong>Content-Encoding : gzip</strong>
Content-Length : ~~</p>
</blockquote>
<h4 id="3-분할-전송">3. 분할 전송</h4>
<blockquote>
</blockquote>
<p>Content-Type : ~
<strong>Transfer-Encoding : chunked</strong>
※ Content-Length 가 필요하지 않음</p>
<p>표현 데이터의 형식을</p>
<hr>
<p>길이
내용
길이
내용</p>
<hr>
<p>위와 같은 형식으로 보내는 방법</p>
<h4 id="4-범위-전송">4. 범위 전송</h4>
<p>응답 중에 오류로 중간에 끊기면 처음부터 보내야 하는 상황이 발생하므로
범위로 끊어서 보내는 방법</p>
<blockquote>
</blockquote>
<p>HTTP/1.1 200 OK
Content-Type : ~
<strong>Content-Rage: bytes a<del>b/b</del>c</strong></p>
<h3 id="표현-데이터가-포함하는-정보">표현 데이터가 포함하는 정보</h3>
<h4 id="1-from---유저-이메일-정보">1. From - 유저 이메일 정보</h4>
<ul>
<li>검색 엔진, 요청에서 사용<h4 id="2-referer---이전-웹-페이지-주소">2. Referer - 이전 웹 페이지 주소</h4>
</li>
<li><strong>유입 경로 분석 가능</strong><h4 id="3-user-agent---유저-애플리케이션-정보">3. User-Agent - 유저 애플리케이션 정보</h4>
</li>
<li>특정 브라우저 오류 발생시 로그 파싱으로 어떤 브라우저인지 확정 가능<h4 id="4-server---오리진-서버의-sw-정보">4. Server - 오리진 서버의 SW 정보</h4>
<h4 id="5-date---메시지-생성-날짜">5. Date - 메시지 생성 날짜</h4>
<h4 id="6-host---도메인">6. Host - 도메인</h4>
</li>
<li>하나의 IP 주소에 여러 도메인이 적용 되어있을 경우 도메인을 특정하기 위해 반드시 필요한 것</li>
</ul>
<h4 id="7-location---리다이렉션">7. Location - 리다이렉션</h4>
<ul>
<li>3xx 응답 결과에 Location 헤더가 있을경우 해당 위치로 자동 리다이렉트<h4 id="8-allow---허용-가능한-http-메서드">8. Allow - 허용 가능한 HTTP 메서드</h4>
</li>
<li>GET, HEAD, PUT<h4 id="9-retry-after---유저가-다음-요청하기까지-대기-시간">9. Retry-After - 유저가 다음 요청하기까지 대기 시간</h4>
</li>
<li>날짜 표기 ( 해당 날짜 이후 가동되도록 ), 초단위 표기 ( 시간 초 이후 가동)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 상태 코드]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/HTTP-%EC%83%81%ED%83%9C-%EC%BD%94%EB%93%9C</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/HTTP-%EC%83%81%ED%83%9C-%EC%BD%94%EB%93%9C</guid>
            <pubDate>Mon, 25 Mar 2024 12:58:06 GMT</pubDate>
            <description><![CDATA[<h1 id="상태-코드란">상태 코드란?</h1>
<p>클라이언트가 보낸 요청의 처리 상태를 서버가 알려주는 기능을 의미
1-- : 요청이 수신되어 처리중
2-- : 요청 정상 처리
3-- : 요청을 완료하려면 추가 행동이 필요
4-- : 클라이언트의 오류
5-- : 서버 오류</p>
<h2 id="1---처리중">1-- (처리중)</h2>
<p>말 그대로 처리중일때 받을 수 있는 상태코드</p>
<h2 id="2---성공">2-- (성공)</h2>
<blockquote>
<p>200 - OK
201 - Created , 생성 완료</p>
</blockquote>
<ul>
<li>요청이 성공하여 새로운 리소스가 생성됨을 의미</li>
<li>ex) post로 등록<blockquote>
</blockquote>
202 - Accepted</li>
<li>요청이 접수됐으나 처리는 완료되지 않음</li>
<li>ex) Batch 처리<blockquote>
</blockquote>
204 - No Content</li>
<li>요청을 성공적으로 수행, 서버가 클라이언트에게 따로 보낼 메세지가 없음</li>
<li>ex) post로 저장처럼 데이터의 변동은 있지만, 환경 변경이 필요 없을 때</li>
</ul>
<hr>
<h2 id="3---리다이렉션">3-- (리다이렉션)</h2>
<p>리다이렉션이란, 클라이언트의 요청으로 인한 서버의 응답에서 location 헤더가 있을 경우, 해당 위치로 자동 이동하는 것</p>
<h3 id="리다이렉션의-종류">리다이렉션의 종류</h3>
<ol>
<li>영구 리다이렉션</li>
<li>일시 리다이렉션</li>
<li>특수 리다이렉션</li>
</ol>
<h3 id="영구-리다이렉션-301-308">영구 리다이렉션 (301, 308)</h3>
<ul>
<li>특정 리소스의 URI가 영구적으로 이동</li>
<li>ex) /members -&gt; /users</li>
</ul>
<p><strong>301 - Moved Permanently</strong></p>
<ul>
<li>리다이렉트시 요청 메서드가 <strong>GET으로 변할수도 있음</strong></li>
</ul>
<p><strong>308 - Permanent Redirect</strong></p>
<ul>
<li>리다이렉트시 요청 메서드와 본문 유지</li>
</ul>
<h4 id="301과-308의-차이점">301과 308의 차이점</h4>
<p>308은 리다이렉션을 해도 기존의 method유지, 301은 GET으로 메소드 변환</p>
<h3 id="일시적인-리다이렉션-302307308">일시적인 리다이렉션 (302,307,308)</h3>
<p>리소스의 URI가 일시적으로 변경되는 것으로 검색 엔진 등에서 URL을 변경하면 안된다</p>
<ul>
<li>주문 완료 후 주문 내역 화면으로 이동</li>
<li>자주 쓰이는 패턴 - Post/Redirect/Get </li>
</ul>
<blockquote>
</blockquote>
<p><strong>302 - Found</strong></p>
<ul>
<li>리다이렉트시 요청 메서드가 <strong>Get으로 변할수도있음</strong><blockquote>
</blockquote>
</li>
<li><em>307 - Temporary Redirect*</em></li>
<li>302와 기능은 동일하지만, 기존 메서드와 본문은 유지된다<blockquote>
</blockquote>
</li>
<li><em>303 - See Other*</em></li>
<li>302와 기능은 같지만 <strong>반드시 메소드가 GET으로 변경됨</strong> </li>
</ul>
<p><strong>정리하자면,</strong></p>
<blockquote>
<ul>
<li>302는 Get으로 변할 수 있음</li>
</ul>
</blockquote>
<ul>
<li>307은 메소드가 변하지 않음</li>
<li>303은 메소드가 Get으로 변함<blockquote>
</blockquote>
303,307을 권장하지만, 현재 이미 많은 앱들이 302를 사용 중</li>
</ul>
<h4 id="prg-postredirectget">PRG (Post/Redirect/Get)</h4>
<p>Post 주문 후 Redirection 시 다시 Post로 인한 재 주문 방지를 위함
따라서, 주문 후 주문 결과 화면을 Get으로 리다이렉트 하게</p>
<blockquote>
<p><strong>기존</strong>
요청 -&gt; DB 저장 -&gt; 응답 -&gt; 새로고침으로 인한 요청 -&gt; DB 주문 -&gt; 응답
위 처럼 진행될 경우 새로고침마다 주문 횟수 증가</p>
</blockquote>
<p><strong>개선</strong>
요청 -&gt; DB 저장 -&gt; 응답 -&gt; 자동 리다이렉트(다른 화면으로 이동, Post에서 Get으로 변환) -&gt;   요청 -&gt; DB 조회 -&gt; 응답</p>
<hr>
<h4 id="특수-리다이렉션">특수 리다이렉션</h4>
<ul>
<li>결과 대신 캐시 사용</li>
</ul>
<h2 id="4---클라이언트-오류">4-- (클라이언트 오류)</h2>
<p>오류의 원인이 클라이언트에 있을 경우로, 재시도를 하더라도 실패함</p>
<h3 id="400-bad-request">400 Bad Request</h3>
<ul>
<li>문법, 메세지 오류<h3 id="401-unauthorized">401 Unauthorized</h3>
</li>
<li>인증 되지 않음<h3 id="403-forbidden">403 Forbidden</h3>
</li>
<li>인증 자격은 있지만, 접근 권한이 불충분</li>
<li>등급에 맞지 않는 리소스 접근<h3 id="404-not-found">404 Not Found</h3>
</li>
<li>권한이 부족한 리소스에 접근</li>
</ul>
<h2 id="5---서버-오류">5-- (서버 오류)</h2>
<p>서버 문제이기 때문에 재시도 하면 성공할 가능성 존재</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 메서드]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/HTTP-%EB%A9%94%EC%84%9C%EB%93%9C</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/HTTP-%EB%A9%94%EC%84%9C%EB%93%9C</guid>
            <pubDate>Sat, 23 Mar 2024 07:01:17 GMT</pubDate>
            <description><![CDATA[<h1 id="uri-설계">URI 설계</h1>
<h3 id="좋은-uri-설계란-무엇인가">좋은 URI 설계란 무엇인가?</h3>
<p>좋은 URI를 설계하기 위한 가장 중요한 점은 리소스를 식별이다</p>
<p>그렇다면 리소스란 뭘까</p>
<blockquote>
<p>회원 명부를 예시로 든다면,
회원을 등록, 수정, 조회, 삭제 등이 있을때
회원을 리소스, 등록, 수정 등을 메소드라고 할 수 있다</p>
</blockquote>
<p>그렇다면 리소스는 어떻게 식별하도록 하는게 좋은 URI 설계일까?
-&gt; 메소드를 배제하고, 오직 리소스만을 식별할 수 있도록 만들어야 한다</p>
<p><strong>리소스를 식별할 수 있는 수단인 메서드</strong>에 대해서 알아보자</p>
<h2 id="http-메서드의-종류">HTTP 메서드의 종류</h2>
<blockquote>
<ol>
<li>GET - 리소스 조회</li>
<li>POST - 요청 데이터 처리 ex) 등록</li>
<li>PUT - 리소스를 대체하며 없을경우 생성한다</li>
<li>PATCH - 리소스 부분 변경</li>
<li>DELETE - 리소스 삭제</li>
</ol>
</blockquote>
<hr>
<ol start="6">
<li>HEAD - 상태줄과 헤더만 조회</li>
<li>OPTIONS - 통신 가능 메소드를 설명</li>
<li>CONNECT - 서버에 대한 터널 설정</li>
<li>TRACE - 메시지 루프백 테스트 수행</li>
</ol>
<h3 id="get">GET</h3>
<ul>
<li>리소스를 조회</li>
<li>서버에 전달하고 싶은 데이터는 query를 통해 전달</li>
<li>메세지 바디를 통해 데이터 전달이 가능하지만, 지원 하지않는 경우가 많아 X<blockquote>
</blockquote>
</li>
<li><em>요청*</em>
GET /numbers/100 HTTP/1.1
Host: localhost:8080</li>
<li><blockquote>
</blockquote>
/numbers/100
{ username : XX, age : OO }<blockquote>
</blockquote>
</li>
<li><em>응답*</em>
HTTP/1.1 200 OK
Content Type:
Content Length
{ username : XX, age : 00 }</li>
</ul>
<h3 id="post">Post</h3>
<ul>
<li>요청 데이터 처리</li>
<li>메시지 바디를 통해 서버로 데이터 전달</li>
<li>서버는 요청 데이터를 처리함</li>
<li>주로 신규 리소스 등록에 사용<blockquote>
</blockquote>
</li>
<li><em>요청*</em>
Post /members HTTP/1.1
Content-Type
{ username : XX, age : 00 }<blockquote>
</blockquote>
</li>
<li><blockquote>
<p>/members/OOO 신규 리소스 식별자 임의의 위치에 생성</p>
</blockquote>
</li>
<li><em>응답*</em>
HTTP/1.1 200 OK
Content Type:
Content Length
Location : /members/OOO  &lt;&lt; 생성 경로 제공
{ username : XX, age : 00 }</li>
</ul>
<h4 id="사용처">사용처</h4>
<h5 id="1-새-리소스-생성">1. 새 리소스 생성</h5>
<ul>
<li>서버에 아직 존재하지 않는 신규 리소스 생성<h5 id="2-요청-데이터-처리">2. 요청 데이터 처리</h5>
</li>
<li>프로세스의 상태가 변경되는 경우
ex) 주문 -&gt; 결제완료 -&gt; 배달시작 -&gt; 배달완료
POST /orders/{orderID}/start-delivery
POST /orders/{orderID}/complete-delivery</li>
</ul>
<hr>
<h3 id="put">PUT</h3>
<p>메시지 바디에서 모든 필드 값이 아닌 일부만 있다면 그 외의 필드값은 삭제하며 메시지 바디 내의 필드값으로 재생성</p>
<p><strong>쉽게 말해 덮어쓰기</strong></p>
<pre><code>PUT /members/100 HTTP/1.1</code></pre><p><strong>POST는 서버가 위치를 관리</strong>하는 것과 다르게 PUT의 경우 위 처럼 <strong>_클라이언트가 리소스 위치를 인지하는 상태에서 URI(members/100)을 지정</strong>해야함</p>
<h3 id="patch">PATCH</h3>
<p>리소스의 부분 변경</p>
<p>메시지에 모든 필드 값이 아닌 일부만 있다면 <strong>그에 해당하는 일부만 값을 변경</strong></p>
<h3 id="delete">DELETE</h3>
<p>리소스 삭제</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP의 특징 및 HTTP 메시지의 형식]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/HTTP%EC%9D%98-%ED%8A%B9%EC%A7%95-%EB%B0%8F-HTTP-%EB%A9%94%EC%8B%9C%EC%A7%80%EC%9D%98-%ED%98%95%EC%8B%9D</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/HTTP%EC%9D%98-%ED%8A%B9%EC%A7%95-%EB%B0%8F-HTTP-%EB%A9%94%EC%8B%9C%EC%A7%80%EC%9D%98-%ED%98%95%EC%8B%9D</guid>
            <pubDate>Tue, 19 Mar 2024 09:38:59 GMT</pubDate>
            <description><![CDATA[<h1 id="http-란">HTTP 란?</h1>
<p>HTTP는 Hyper Text Transfer Protocol의 약자</p>
<h2 id="http-특징">HTTP 특징</h2>
<ul>
<li>클라이언트 서버 구조를 사용한다<blockquote>
<ul>
<li>Request Response 구조를 의미하며, <strong>클라이언트가 서버에 요청(request)</strong>을 하면 <strong>서버가 클라이언트에게 응답(Response)</strong>를 하는 방식을 의미한다</li>
</ul>
</blockquote>
</li>
<li>무상태 프로토콜을 사용하며 비연결성이다<blockquote>
<p><strong>무상태 프로토콜(Stateless)</strong>
  서버가 클라이언트의 상태를 보존하지 않는 경우
  ** 상태 유지**(Stateful)</p>
<pre><code>  서버가 클라이언트의 상태를 보존하는 경우</code></pre></blockquote>
</li>
</ul>
<h3 id="상태-유지">상태 유지</h3>
<blockquote>
<ul>
<li>항상 같은 서버가 유지 되어야함
  클라이언트의 요청에 <strong>이전 상황에 대한 정보가 없기 때문</strong>에 계속 소통하던 서버와의 소통이 이루어져야함</li>
</ul>
</blockquote>
<ul>
<li>ex) 로그인</li>
</ul>
<h3 id="무상태-프로토콜">무상태 프로토콜</h3>
<blockquote>
<ul>
<li>어느 서버든 상관없음
클라이언트 요청에서 <strong>이전 상황에 대한 요청을 모두 보내</strong>기에 같은 기능을 한다면 어떤 서버로 보내든 상관 없음</li>
</ul>
</blockquote>
<ul>
<li>상태 유지보다 많은 데이터를 보내야함</li>
<li>ex) 단순한 서비스 소개 화면</li>
</ul>
<p>→ 중간에  프록시 서버와 원 서버의 연결이 끊길 경우, <strong>무상태 프로토콜은 임의의 같은 기능을 가진 서버로 연결</strong>하면 되지만 <strong>상태 유지의 경우 작업이 불가</strong>함</p>
<h3 id="비-연결성">비 연결성</h3>
<p><strong>일반적</strong>으로 클라이언트와 서버 구조는 한번** TCP/IP 연결시 연결을 유지<strong>함
하지만, 다수의 클라이언트가 하나의 서버와 **연결 후 더 이상 소통하지 않음에도 연결</strong>돼있다면 <strong>자원이 낭비</strong>되므로 나온게 비 연결성이다.</p>
<p><strong>비 연결성</strong>은 요청과 응답 후 TCP/IP <strong>연결을 종료함으로써 서버 자원 낭비를 방지</strong>함</p>
<p>※ HTTP는 기본이 비 연결성이다</p>
<blockquote>
<p><strong>장점</strong></p>
</blockquote>
<ul>
<li>수천명이 서비스를 사용해도 서버에서 동시 처리하는 요청은 수십개 이하
ex) 브라우저 검색시 연속으로 검색을 누르지 않음</li>
<li>서버 자원 사용이 효율적</li>
</ul>
<blockquote>
<p><strong>단점</strong></p>
</blockquote>
<ul>
<li>TCP/IP 재연결시 3 way handshake 시간이 추가됨</li>
<li>요청 시 다양한 자원을 함께 다운로드 해야함 
ex) 연결 - HTML - 종료, 연결 - JS - 종료  ---</li>
</ul>
<p>위 단점을 해결하기 위해 나온 방안이 <strong>지속 연결</strong>이다.</p>
<h3 id="지속-연결">지속 연결</h3>
<p>기존에 HTML, JS 및 데이터를 다운받을때 종류별로 연결과 종료를 했지만,
한 Task는 <strong>한번의 연결 싸이클에 다 응답받을 수 있도록</strong> 하는 방안을 의미
<strong>→ 연결 - HTML - JS - IMG - 종료</strong></p>
<hr>
<h2 id="http-메시지">HTTP 메시지</h2>
<p>HTTP 메시지는 <strong>클라이언트의 요청 메시지, 서버의 응답 메시지</strong>로 나눌 수 있다</p>
<blockquote>
<p><strong>HTTP 메시지는 다음과 같은 형식을 가진다</strong>
시작 라인
헤더
공백라인(CRLF)
메세지 바디</p>
</blockquote>
<p>HTTP 메시지는 <strong>request-line(요청) 과 status-line(응답)</strong> 두 가지로 나뉜다</p>
<p><strong>request-line</strong></p>
<ol>
<li>시작 라인 = method SP request-target SP HTTP-version CRLF**</li>
<li>헤더 = field-name &quot;:&quot; OWS field-value OWS<blockquote>
</blockquote>
</li>
</ol>
<p><strong>request-line</strong></p>
<pre><code>Get /serach?q=hello&amp;hl=ko HTTP/1.1
Host : www.google.com</code></pre><p><strong>status-line</strong></p>
<ol>
<li>시작 라인 = HTTP-version SP status-code SP reason-phrase CRLF</li>
<li>헤더 (metadata of message body)
&amp;nbsp2.1 Content-Type
&amp;nbsp2.2 Content-Length</li>
<li>CRLF</li>
<li>메시지 바디 (실제로 전송할 데이터)</li>
</ol>
<blockquote>
<p><strong>status-line</strong></p>
</blockquote>
<pre><code>HTTP/1.1 200 OK
Content-Type : text/html;charset=UTF-8
Content-Length : 3423
CRLF
&lt;html&gt;
    &lt;body&gt;...&lt;/body&gt;
&lt;/html&gt;</code></pre><ul>
<li>SP : Space</li>
<li>CRLF : Enter</li>
<li>OWS : 띄어쓰기 허용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[URI 및 웹 브라우저 요청의 흐름]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/URI-%EB%B0%8F-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD%EC%9D%98-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/URI-%EB%B0%8F-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD%EC%9D%98-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Mon, 18 Mar 2024 10:36:06 GMT</pubDate>
            <description><![CDATA[<h2 id="uri">URI</h2>
<blockquote>
<p><strong>Uniform Resource Identifier의 약자</strong>
Uniform : 리소스를 식별하는 통일된 방식
Resource : URI로 식별할 수 있는 모든 자원
Identifier : 다른 항목과 구분하는데 필요한 정보</p>
</blockquote>
<h3 id="identifier의-종류">Identifier의 종류</h3>
<h4 id="1-url-locator">1. URL (Locator)</h4>
<ul>
<li>리소스의 위치<h4 id="2-urn-name">2. URN (Name)</h4>
</li>
<li>리소스의 이름</li>
</ul>
<p>URL(위치)는 변할 수 있지만, URN(이름)은 잘 변하지 않기에 <strong>URN(이름)</strong>만으로 실제 리소스를 찾는 방법이 보편화 되지 않아 <strong>잘 사용하지 않는다</strong></p>
<p>따라서, <strong>URI를 URL과 동치</strong>로 보는게 편하다고 한다</p>
<h2 id="url의-구조">URL의 구조</h2>
<blockquote>
<p>Scheme://[userinfo@]host[:port][/path][?query][#fragment]
Https://<a href="http://www.google.com:443/search?q=hello&amp;hl=ko">www.google.com:443/search?q=hello&amp;hl=ko</a></p>
</blockquote>
<h3 id="scheme">Scheme</h3>
<ul>
<li>주로 프로토콜을 사용</li>
</ul>
<blockquote>
<p><strong>※ 프로토콜 이란?</strong>
어떤 방식으로 자원에 접근할 것인가에 대한 규칙</p>
</blockquote>
<h3 id="host">host</h3>
<ul>
<li>호스트 명. 즉, <strong>DNS 혹은 IP 주소</strong>를 의미</li>
</ul>
<h3 id="port">Port</h3>
<ul>
<li><strong>프로토콜(http,https) 사용시 생략</strong>할 경우 알아서 배정되므로 일반적으로 생략함</li>
</ul>
<h3 id="path">path</h3>
<ul>
<li><strong>리소스 경로</strong>를 의미</li>
</ul>
<h3 id="query">query</h3>
<ul>
<li><p><strong>key=value 형태</strong>를 가지며 문법은 ?key=value&amp;key=value 이다</p>
</li>
<li><p>다른 이름으로 query parameter, query string 등이 있다</p>
<h3 id="fragment">fragment</h3>
</li>
<li><p>서버에 전송하는 정보가 아닌, <strong>html 내부 책갈피</strong>(원하는 위치로 가는 표식)을 의미</p>
</li>
</ul>
<hr>
<h2 id="웹-브라우저-요청-흐름">웹 브라우저 요청 흐름</h2>
<ol>
<li>클라이언트가 HTTP 요청 메세지를 생성한다</li>
<li>Socket 라이브러리를 통해 전달<ul>
<li>TCP/IP 주소, 데이터</li>
</ul>
</li>
<li>HTTP 메세지를 포함한 TCP/IP 패킷 생성</li>
<li>서버에 메세지 도착시, TCP/IP를 제외한 HTTP 메시지만을 사용</li>
</ol>
<h3 id="http-요청-메세지">HTTP 요청 메세지</h3>
<blockquote>
<p>GET/search?q=hello&amp;hl=ko HTTP/1.1
Host: <a href="http://www.google.com">www.google.com</a></p>
</blockquote>
<h3 id="http-응답-메세지">HTTP 응답 메세지</h3>
<blockquote>
<p><strong>메세지 헤더</strong>
HTTP/1.1 200 OK
Content-Type: text/html:charset=UTF-8
Content-Length:3423
<strong>메세지 바디</strong></p>
</blockquote>
<p>응답 메세지를 받은 후 <strong>메세지 바디의 HTML 정보</strong>를 통해 우리가 검색 후 보이는 <strong>웹 화면을 렌더링</strong>한다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터넷 네트워크]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%99%80-URI-%EB%B0%8F-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD%EC%9D%98-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC%EC%99%80-URI-%EB%B0%8F-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%9A%94%EC%B2%AD%EC%9D%98-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Mon, 18 Mar 2024 10:03:20 GMT</pubDate>
            <description><![CDATA[<h1 id="인터넷-네트워크">인터넷 네트워크</h1>
<p>인터넷에서 컴퓨터 둘 즉, <strong>클라이언트(사용자)</strong>와 <strong>서버</strong>는 어떻게 통신을 할까?</p>
<p>클라이언트와 서버를 연결하는 <strong>노드(프록시)들의 집합</strong>을 <strong>인터넷</strong>이라고 한다</p>
<p>어느 노드를 통해야 적절히 연결이 되는지 첫 연결시엔 알 수 없기에
우리는 집 주소처럼 컴퓨터마다 IP 주소를 부여한다</p>
<blockquote>
<p>예를 들어,
광진구에 위치한 A와 성동구에 위치한 B가 있다고 가정 할 경우
A (광진구) - 화양동, 성수동, 군자동 - B(성수 1가 2동)</p>
</blockquote>
<hr>
<h2 id="ip">IP</h2>
<p>IP는 인터넷 프로토콜(Internet Protocol)의 약자로, <strong>패킷 이라는 통신 단위로 데이터를 전달</strong>한다</p>
<h3 id="패킷">패킷</h3>
<p>IP가 전달하는 패킷은 <strong>출발지 IP, 목적지 IP</strong>, 기타 정보와 <strong>보내고자 하는 데이터</strong>를 담고 있다</p>
<h3 id="패킷-전달">패킷 전달</h3>
<p>클라이언트에서 패킷을 전달하면 <strong>목적지 IP로 다양한 노드들을 통해 도달</strong>하게 된다
서버가 정상적으로 패킷을 받게 된다면, <strong>서버에서 제대로 받았는지에 대한 패킷</strong>을 통과한 노드의 역순으로 전달하여 <strong>오류 여부를 확인</strong>한다</p>
<h3 id="ip의-한계">IP의 한계</h3>
<p><strong>비 연결성</strong></p>
<ul>
<li>패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷이 전송되는 경우</li>
</ul>
<p>*<em>비 신뢰성 *</em></p>
<ul>
<li>중간에 패킷이 사라지거나 패킷의 용량이 클때 분할해서 보낸 순서가 섞여서 되 돌아 오는 경우</li>
</ul>
<p><strong>프로그램 구분</strong></p>
<ul>
<li>같은 IP를 사용하는 서버에서 통신하는 어플리케이션이 둘 이상일 경우</li>
</ul>
<h2 id="tcp">TCP</h2>
<p>전송 제어 프로토콜 (Transmission Control Protocol)의 약자로 세 가지 특징이 있으며, 신뢰할 수 있는 프로토콜이기에 현재 대부분 TCP를 사용한다</p>
<h4 id="1-tcp-3-way-handshake-가상-연결">1. TCP 3 way handshake (가상 연결)</h4>
<blockquote>
<p><strong>클라이언트와 서버의 연결 과정</strong>
클라이언트 ---SYN---&gt; 서버
클라이언트 &lt;---SYN+ACK--- 서버
클라이언트 ---ACK---&gt; 서버
클라이언트 ---데이터---&gt; 서버</p>
</blockquote>
<p>SYC : 접속 요청
ACK : 요청 수락</p>
<p>※ 클라이언트가 서버에 ACK 전송시, 데이터도 같이 전송 가능함</p>
<h4 id="2-데이터-전달-보증">2. 데이터 전달 보증</h4>
<ul>
<li>서버가 회신을 통해 데이터를 정상적으로 받음을 알림<h4 id="3-순서-보장">3. 순서 보장</h4>
</li>
<li>용량이 큰 패킷을 분할 전송시 순서가 바뀌어 도착했다면 서버에서 알림을 보냄</li>
</ul>
<h2 id="udp">UDP</h2>
<p>사용자 데이터그램 프로토콜(User Datagram Protocol)의 약자로 I<strong>P의 상위호환, TCP의 하위호환</strong>으로 볼 수 있다.</p>
<blockquote>
<p>IP에서 port와 체크섬 기능이 추가된 정도이며 TCP의 3가지 기능은 없음</p>
</blockquote>
<blockquote>
<p>TCP는 용량이 크기에 최적화에 한계가 있지만, UDP는 기능이 부족한 대신 단순하고 빠르다는 특징이 있음</p>
</blockquote>
<h3 id="port">Port</h3>
<p>클라이언트가 한번에 <strong>둘 이상의 서버와 연결시 필요</strong>한 기능
예를 들어, 클라이언트가 둘 이상의 데이터를 보낼때, 각 데이터가 어느 서버에 매칭되는지를 알려주는 것 이라고 생각하면 된다</p>
<h3 id="dns">DNS</h3>
<p>서버의 IP가 변경됐을 경우, 접근에 오류가 생길 것을 방지하기 위해
전화번호부 형태로 만들어진 기능</p>
<blockquote>
<p>예시로
<a href="http://www.google.com">www.google.com</a> - 200.200.200.2
<a href="http://www.naver.com">www.naver.com</a> - 300.300.300.3</p>
</blockquote>
<ul>
<li>위와 같을경우, IP가 변경되도 전화번호부 상의 <strong>IP를 업데이트</strong>를 해준다면
클라이언트는 DNS로만 접근하기 때문에 <strong>오류 없이 접근이 가능</strong>하다</li>
</ul>
<hr>
<h2 id="인터넷-프로토콜-스택의-4-계층">인터넷 프로토콜 스택의 4 계층</h2>
<h3 id="1-어플리케이션-계층">1. 어플리케이션 계층</h3>
<pre><code>HTTP, FTP
ex) 웹브라우저, 게임, 채팅 프로그램 등</code></pre><h3 id="2-전송-계층">2. 전송 계층</h3>
<pre><code>TCP, UDP</code></pre><h3 id="3-인터넷-계층">3. 인터넷 계층</h3>
<pre><code>IP</code></pre><h3 id="4-네트워크-인터페이스-계층">4. 네트워크 인터페이스 계층</h3>
<pre><code>LAN 드라이버, LAN 장비</code></pre><p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/17e6bb60-c343-4eb7-8738-c9a625ec2f8c/image.png" alt=""></p>
<h3 id="메세지의-전송-과정">메세지의 전송 과정</h3>
<ol>
<li>프로그램이 메세지를 생성</li>
<li>Socket 라이브러리를 통해 전달</li>
<li>메세지 데이터를 포함한 TCP 정보 생성</li>
<li>TCP 데이터를 포함한 IP 패킷을 생성</li>
<li>랜카드를 통해 서버로 전달</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[DDP 분산 데이터 병렬 처리]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/DDP-%EB%B6%84%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%91%EB%A0%AC-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/DDP-%EB%B6%84%EC%82%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%91%EB%A0%AC-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sun, 04 Jun 2023 14:58:07 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python">def Trainer:
    def __init__(self, args):
      self.ngpus_per_nodes = torch.cuda.device_count()    
      self.node_rank = args.rank    
      self.dist_backend = args.dist_backend    
      self.master_addr = os.environ.get(&quot;MASTER_ADDR&quot;, &quot;localhost&quot;)    
      self.master_port = os.environ.get(&quot;MASTER_PORT&quot;, &quot;8888&quot;)    
      self.dist_url = f&quot;{args.dist_url}{self.master_addr}:{self.master_port}&quot;

def init_distributed(self):
        if self.distributed:
            if torch.cuda.is_available():
                self.gpu    = self.local_rank % self.ngpus_per_node
                self.device = torch.device(self.gpu)
                if self.distributed:
                    self.local_rank = self.gpu
                    self.rank =  self.gpu
                    print(f&#39;rank {self.rank} is running...&#39;)
                    dist.init_process_group(backend=self.dist_backend, init_method=self.dist_url,
                                            world_size=self.world_size, rank=self.rank)
                    dist.barrier()
                    self.setup_for_distributed(self.is_main_process())
        else:
            self.device = torch.device(&#39;cpu&#39;)

if self.distributed:
            self.model = torch.nn.parallel.DistributedDataParallel(self.model, device_ids=[self.local_rank], output_device=self.local_rank,find_unused_parameters=True, static_graph=True)

for b, batch in enumerate(self.train_dataloader):
                for key in batch:
                    batch[key] = batch[key].to(self.local_rank)
                y = self.model(batch)
</code></pre>
<p>다수의 GPU를 사용하여 VRAM을 초과하는 batch_size를 선택했을 경우 사용할 수 있는 방법이다.</p>
<p>그냥 GPU 많이 써서 학습 시킨다고 생각하면 될듯</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VMware 설치 및 ubuntu 설치]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/VMware-%EC%84%A4%EC%B9%98-%EB%B0%8F-ubuntu-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/VMware-%EC%84%A4%EC%B9%98-%EB%B0%8F-ubuntu-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Sun, 28 May 2023 14:58:18 GMT</pubDate>
            <description><![CDATA[<h1 id="1-vmware-다운받기">1. VMware 다운받기</h1>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/066baccc-dde5-478a-8c60-b68a12f23724/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/112c266e-c57b-46f0-8943-8784bb74e837/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/9495d278-f778-4602-8b6d-b5a681e6a4d2/image.png" alt=""></p>
<h1 id="2-ubuntusio-다운-받기">2. Ubuntu.sio 다운 받기</h1>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/302c15d0-3fab-40b6-aa85-90c5f90d236a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/7695fbe9-8cf8-4ec1-a293-c3deb70221c8/image.png" alt=""></p>
<h1 id="3-vmware에-ubuntu-설치">3. Vmware에 Ubuntu 설치</h1>
<h2 id="31-create-to-virtual-machine">3.1 create to Virtual machine</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/fef16197-9330-4a7e-b69b-035e7b52a54c/image.png" alt=""></p>
<h2 id="32-ubuntu-iso-파일설치">3.2 ubuntu iso 파일설치</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/5acce520-1edd-495a-834f-6204f8db3d83/image.png" alt=""></p>
<h3 id="321-iso파일이-완전하게-설치되지-않았을-경우-오류-발생">3.2.1 iso파일이 완전하게 설치되지 않았을 경우 오류 발생</h3>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/62be826e-8c3d-4262-88c4-46750c8c0ae1/image.png" alt=""></p>
<h2 id="33-이름-비밀번호-자유지정">3.3 이름, 비밀번호 자유지정</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/074aab91-a583-4753-b72d-5ca745541e6a/image.png" alt=""></p>
<h2 id="34-virtual-machine-이름-짓기">3.4 virtual machine 이름 짓기</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/ff34b26d-db5b-4ec1-bda0-383099a0ec31/image.png" alt=""></p>
<h2 id="35-vm-리소스-할당">3.5 VM 리소스 할당</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/e6cf9536-28c8-4b05-a279-9c95a17c8777/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/0797e14e-8efe-4f07-897c-30e80dbdc1bf/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Backchannel Prediction]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/Backchannel-Prediction</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/Backchannel-Prediction</guid>
            <pubDate>Sun, 21 May 2023 12:31:06 GMT</pubDate>
            <description><![CDATA[<h3 id="오늘은-내-연구실에서-하는-분야를-소개해보고자-한다">오늘은 내 연구실에서 하는 분야를 소개해보고자 한다.</h3>
<h1 id="backchannel-이란">Backchannel 이란?</h1>
<h4 id="백채널이하-bc은-대화에서-짧고-빠른-반응을-의미한다">백채널(이하 BC)은 대화에서 짧고 빠른 반응을 의미한다.</h4>
<h4 id="청자의-bc를-통해-화자는-청자가-잘-이해하고있는지-공감되는지의-여부를-확인할-수-있다">청자의 BC를 통해 화자는 청자가 잘 이해하고있는지, 공감되는지의 여부를 확인할 수 있다.</h4>
<h4 id="대화에서-적절한-타이밍에-적절한-bc를-사용하는-것은-대화를-조금-더-풍부하게-만들어준다">대화에서 적절한 타이밍에 적절한 BC를 사용하는 것은 대화를 조금 더 풍부하게 만들어준다.</h4>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/57900ffc-cadc-4a00-94d4-8d1de5ec04a8/image.png" alt=""></p>
<p>위의 예시는 현재 모델을 학습시키는데에 사용하는 방식을 의미한 것이다.</p>
<p>음성은 BC발생 직전 1.5초를 사용하며 텍스트 정보의 경우엔 5, 10, 20등 다양한 길이를 사용한다.</p>
<p>실증에서 사용하기 위하여 AI가 적절한 BC를 생성해내기 위한 학습을 하고자한다.</p>
<p>현재 이 Task의 문제점은 다음과 같다.</p>
<ol>
<li>현재 대화에 중요한 시각적인 정보를 사용하지 않는다는 점</li>
<li>음성과 텍스트간의 연관성을 찾지 않고 별개의 feature들을 통해 학습을 한다.</li>
</ol>
<p>따라서 위 두가지를 해결하여 실증에서 AI가 적절한 BC를 생성해내기 위한 분류 및 생성을 하고자한다.</p>
<p>이 Task에서 다뤄지는 논문은 2개가 있다</p>
<blockquote>
<h3 id="1-bpm_mt">1. BPM_MT</h3>
<pre><code>MFCC와 KoBERT를 사용하여 Concat을 통한 Loss와,
Sentiment dictionary와 대조를 시켜 만든 Sentiment Loss를 9:1의 비율로 Sum하여 학습시킨다.
이 논문은 Sentiment를 사용하여 성능을 높히고, text의 길이를 늘릴수록 성능이 좋다는 것을 보였다</code></pre><h3 id="2-ortega">2. Ortega</h3>
<pre><code>Ortega는 단순한 CNN 모델로써, Audio, text CNN을 통하고, 
listener embedding 총 3개의  feature를 concat한 후 Linear-Softmax를 통하여 Classifier를 한다.
이 논문은 BC 생성에 음성데이터의 중요도와 음성/텍스트의 길이에 따른 성능의 변화 추이를 보였다.</code></pre></blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[CE,BCE,BCEwithlogitloss의 차이]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/CEBCEBCEwithlogitloss%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/CEBCEBCEwithlogitloss%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 14 May 2023 14:42:18 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python">import torch
import torch.nn as nn
import torch.nn.functional as F

#1
torch.nn.functional.cross_entropy(input, target, weight=None, size_average=None,
ignore_index=- 100, reduce=None, reduction=&#39;mean&#39;, label_smoothing=0.0)

#2
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction=&#39;mean&#39;)

#3
torch.nn.BCEWithLogitsLoss(weight=None, size_average=None, reduce=None, reduction=&#39;mean&#39;, pos_weight=None)</code></pre>
<p>첫번째의 CrossEntropyLoss의 경우 클래스의 개수에 맞게 output 차원을 추출한다
ex) class가 4개일경우 출력값은 (batch_size,4)가 되어야한다.</p>
<ul>
<li>Softmax를 모듈 자체에서 지원하기 때문에 출력값을 바로
loss = F.cross_entropy(logit,label) 를 사용하면된다.</li>
</ul>
<p>두번째의 BinaryCrossEntropyLoss의 경우 이진분류이기 때문에 softmax가 따로 없으므로
Sigmoid를 통과 시킨 후 비교를해야한다</p>
<ul>
<li>loss = nn.BCELoss(torch.sigmoid(logit),label)</li>
<li>Batch_size 가 1인경우 - nn.sigmoid(logit)</li>
<li>Batch_size 가 2이상인경우 - torch.sigmoid(logit) 을 사용해야한다.</li>
</ul>
<p>세번째의 BCEWithLogitLoss의 경우 CrossEntropy에 softmax가 내장되어있는 것 처럼
BCE에 Sigmoid가 추가된 모듈이다</p>
<ul>
<li>내가 알기로는 (batch_size,1)의 경우 
BCEWithLogitLoss(logit,label) 대신 torch.sigmoid(logit)을 사용해야 
오류가 없었던 것으로 기억한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Class Imbalance 해결 방안]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/Class-Imbalance-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/Class-Imbalance-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88</guid>
            <pubDate>Sun, 07 May 2023 14:52:52 GMT</pubDate>
            <description><![CDATA[<p>내가 찾아본 해결방안은</p>
<ol>
<li>Hierarchical Classification</li>
<li>Focal loss</li>
<li>Statistical algorithm
인데, 이 포스팅에서는 1번을 알아보자.</li>
</ol>
<h2 id="1-hierarchical-classification">1. Hierarchical Classification</h2>
<p>Hierarchical Classification 알고리즘은, 크게 클래스를 나누고 각 클래스 내부에서 2~n차적으로 클래스를 또 나누는 방법이다.
위의 알고리즘 방법으로 3가지가 있는데 다음과 같다</p>
<h4 id="1top-downflat-classification-approach">1.Top-down(Flat Classification) approach</h4>
<h4 id="2local-classifiers-approach">2.Local classifiers approach</h4>
<h4 id="3big-bang-classifiers-approach">3.Big-bang classifiers approach</h4>
<h3 id="1top-down-approach">1.Top-down approach</h3>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/3d516eda-7c7a-4498-90a9-41631469007b/image.png" alt=""></p>
<p>가장 간단한 방법으로, 클래스의 계층을 무시하고 Leaf node의 클래스만 예측하는 방식이다. 이 방식은 train/test시에 기존의 일반적인 classification algorithm처럼 작동한다. 하지만, 이방식은 계층 분류 문제에 대한 간접적인 치팅??힌트?를 제공한다고 볼 수 있다. Leaf class에 할당될경우, 부모 클래스에 자동으로 힌트를 준다고 볼 수 있기 때문이다.
이 방법의 단점으로는 클래스 계층에 존재하는 부모-자녀 클래스 관계에 대한 정보를 확인하지않고 많은 수의 클래스(모든 리프 클래스)를 구별하기 위해 classifier를 구축해야 하는 심각한 단점을 가지고 있습니다.</p>
<h3 id="2local-classifiers-approach-1">2.Local classifiers approach</h3>
<p>노드당 각각의 Local classifier의 접근 방식은 클래스 계층의 각 노드에 대해 하나의 이진 분류기 학습하는 방식으로 구성된다.</p>
<h4 id="21-local-classifier-per-node-approach">2.1 Local Classifier Per Node Approach</h4>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/f2390b4f-fd62-49c9-9cee-af46d23cd668/image.png" alt="">
클래스 계층의 각 상위 노드에 대해 Multi-class classifier가 자식 노드를 구별하도록 훈련되는 방식이다.</p>
<h4 id="22-local-classifier-per-level-approach">2.2 Local Classifier Per Level Approach</h4>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/89152f92-1b13-42d0-9e8e-2a46b88e431f/image.png" alt="">
Per Level 방식은 클래스 계층의 각 Level에 대해 하나의 다중 클래스 분류기를 학습하는 방식으로 구성된다.</p>
<h3 id="3big-bang-classifiers-approach-1">3.Big-bang classifiers approach</h3>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/fa97e709-87f7-4d31-8991-61b85f3c7167/image.png" alt="">
Hierarchical Classification방법으로 2번의 Local 방안을 사용하여 해결할 수 있지만, 모든 클래스에 대해 단일 글로벌 모델을 학습하는 것은 일반적으로 글로벌 분류 모델의 전체 크기가 상당히 작다는 이점이 있습니다, 모든 로컬 분류기 접근법에 의해 학습된 모든 로컬 모델의 총 크기와 비교하여.
글로벌 분류기 접근 방식에서는 분류 알고리듬을 단일 실행하는 동안 클래스 계층 전체를 고려하여 훈련 세트에서 단일(상대적으로 복잡한) 분류 모델이 구축됩니다. 테스트 단계에서 사용되는 경우 각 테스트 예제는 잠재적으로 모든 계층 수준의 클래스를 테스트 예제에 할당할 수 있는 프로세스인 유도 모형에 의해 분류됩니다.</p>
<h4 id="나머지-class-imbalance를-해결하는-방안은-다음-포스팅에-확인해보도록-하자---임시-저장이-안된-나머지------사라졌다-----">나머지 Class Imbalance를 해결하는 방안은 다음 포스팅에 확인해보도록 하자 . . 임시 저장이 안된 나머지 . . .. . . 사라졌다 . . .. . .</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[pydub.AudioSemgent를 사용한 필요한 시간대의 Audio추출하기]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/pydub.AudioSemgent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%ED%95%84%EC%9A%94%ED%95%9C-%EC%8B%9C%EA%B0%84%EB%8C%80%EC%9D%98-Audio%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/pydub.AudioSemgent%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%ED%95%84%EC%9A%94%ED%95%9C-%EC%8B%9C%EA%B0%84%EB%8C%80%EC%9D%98-Audio%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 09 Apr 2023 14:30:45 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-python">import os
import pandas as pd
from pydub import AudioSegment
from tqdm import tqdm

def main():

   #파일이 tsv일경우 delimiter을 &#39;\t&#39;로 해줌으로써 탭 기준으로 불러올 수 있음
   file_name=pd.read_csv(&#39;file_name.tsv&#39;,delimiter=&#39;\t&#39;,encoding=&#39;utf-8&#39;)
   #파일이 csv일경우
   file_name=pd.read_csv(&#39;file_name.csv&#39;,encoding=&#39;utf-8&#39;)

    path=&#39;/path/of/audiodata_folder&#39;
    file_list = os.listdir(path) #path 내의 파일들을 리스트로 변환

    for i in tqdm(file_list): # tqdm을 통해 로딩바를 만듦으로써 진행상황을 확인할 수 있음

        dir=os.path.join(path,i) # /path/of/audiodata_folder/audiofile_name

        sound = AudioSegment.from_file(dir) #원본 audio file 지정

        for j in range(len(file_name)): #파일의 인덱스개수 만큼

            #tsv파일에서 시작시간과, 종료시간을 불러오는것
            start = file_name.iloc[j,2]
            end = file_name.iloc[j,3]
            #인덱스가 j일때의 2열,3열 값을 불러오기

            #자르고자 하는 시간 정의 ms기준이므로 10000을 곱해줘야 sec기준이 된다
            StartTime=float(start)*1000
            Endtime=float(end)*1000

            #자르고자 하는 시간대를 정의
            extract=sound[StartTime:Endtime]
            extract.export(&#39;/save_file/path/custom_file_name&#39;, format=&quot;wav&quot;)

main()</code></pre>
<blockquote>
<p>a=/data/datasets
b=folder</p>
</blockquote>
<p>os.path.join(a,b) #a와b사이에 쉼표 사용시에
/data/datasets/folder 와같이 슬래쉬가 자동생성됨
os.path.join(a+b) #a와b사이에 더하기 시에
/data/datasetsfolder 가되므로</p>
<blockquote>
</blockquote>
<ul>
<li>+를 사용할경우
a=/data/datasets/
b=folder</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>,를 사용할경우
a=/data/datasets
b=folder
를 사용하도록 하자</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Transformer code 분석]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/Transformer-code-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/Transformer-code-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Sun, 02 Apr 2023 14:19:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/6c5002d5-4a7b-4fd6-93cb-1bdf2b54cde0/image.png" alt=""></p>
<blockquote>
<h4 id="cross-attention을-구현하기-위한-초석으로">Cross Attention을 구현하기 위한 초석으로</h4>
</blockquote>
<h4 id="나동빈님의-코드를-분석하며-개인적으로-정리하는-글입니다">나동빈님의 코드를 분석하며 개인적으로 정리하는 글입니다.</h4>
<pre><code class="language-python">import torch.nn as nn


class MultiHeadAttentionLayer(nn.Module):
    def __init__(self, hidden_dim, n_heads, dropout_ratio, device):
        super().__init__()

        assert hidden_dim % n_heads == 0

        self.hidden_dim = hidden_dim # 임베딩 차원
        self.n_heads = n_heads # 헤드(head)의 개수 ( 논문은 8개 )
        self.head_dim = hidden_dim // n_heads # 각 헤드(head)에서의 임베딩 차원

        self.fc_q = nn.Linear(hidden_dim, hidden_dim)
        # Query 값에 적용될 FC 레이어
        self.fc_k = nn.Linear(hidden_dim, hidden_dim)
        # Key 값에 적용될 FC 레이어
        self.fc_v = nn.Linear(hidden_dim, hidden_dim)
        # Value 값에 적용될 FC 레이어

        self.fc_o = nn.Linear(hidden_dim, hidden_dim)
        self.dropout = nn.Dropout(dropout_ratio)
        self.scale = torch.sqrt(torch.FloatTensor([self.head_dim])).to(device)

    def forward(self, query, key, value, mask = None):

        batch_size = query.shape[0]

        # query: [batch_size, query_len, hidden_dim]
        # key: [batch_size, key_len, hidden_dim]
        # value: [batch_size, value_len, hidden_dim]

        Q = self.fc_q(query)
        K = self.fc_k(key)
        V = self.fc_v(value)

        # Q: [batch_size, query_len, hidden_dim]
        # K: [batch_size, key_len, hidden_dim]
        # V: [batch_size, value_len, hidden_dim]

        # hidden_dim → n_heads X head_dim 형태로 변형
        # n_heads(h)개의 서로 다른 어텐션(attention) 컨셉을 학습하도록 유도
        Q = Q.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
        K = K.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
        V = V.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)

        # Q: [batch_size, n_heads, query_len, head_dim]
        # K: [batch_size, n_heads, key_len, head_dim]
        # V: [batch_size, n_heads, value_len, head_dim]

        # Attention Energy 계산
        energy = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale

        # energy: [batch_size, n_heads, query_len, key_len]

        # 마스크(mask)를 사용하는 경우
        if mask is not None:
            # 마스크(mask) 값이 0인 부분을 -1e10으로 채우기
            energy = energy.masked_fill(mask==0, -1e10)

        # 어텐션(attention) 스코어 계산: 각 단어에 대한 확률 값
        attention = torch.softmax(energy, dim=-1)

        # attention: [batch_size, n_heads, query_len, key_len]

        # 여기에서 Scaled Dot-Product Attention을 계산
        x = torch.matmul(self.dropout(attention), V)

        # x: [batch_size, n_heads, query_len, head_dim]

        x = x.permute(0, 2, 1, 3).contiguous()

        # x: [batch_size, query_len, n_heads, head_dim]

        x = x.view(batch_size, -1, self.hidden_dim)

        # x: [batch_size, query_len, hidden_dim]

        x = self.fc_o(x) # x: [batch_size, query_len, hidden_dim]

        # x: [batch_size, query_len, hidden_dim]

&gt;         return x, attention</code></pre>
<blockquote>
<h4 id="풍부한-관점에서-feature을-보기-위해-multiheadattention을-채택">풍부한 관점에서 feature을 보기 위해 MultiHeadAttention을 채택</h4>
<p>Head가 사람, Attention이 시각이라고 생각했을때 다양한 사람이 보는 시각이 다 다르기 때문에 좋은 특징공간을 찾을 수 있을거라 생각함</p>
</blockquote>
<blockquote>
<h2 id="positionwise">Positionwise</h2>
<p><img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/dc91f000-9807-4917-836e-9ab3ed1414fd/image.png" alt=""></p>
</blockquote>
<pre><code class="language-python">class PositionwiseFeedforwardLayer(nn.Module):
    def __init__(self, hidden_dim, pf_dim, dropout_ratio):
        super().__init__()

        self.fc_1 = nn.Linear(hidden_dim, pf_dim)
        self.fc_2 = nn.Linear(pf_dim, hidden_dim)

        self.dropout = nn.Dropout(dropout_ratio)

    def forward(self, x):

        # x: [batch_size, seq_len, hidden_dim]

        x = self.dropout(torch.relu(self.fc_1(x)))

        # x: [batch_size, seq_len, pf_dim]

        x = self.fc_2(x)

        # x: [batch_size, seq_len, hidden_dim]

        return x</code></pre>
<blockquote>
<p>위치별 특징을 적용시키기 위한 것으로 서로 다른 주기를 가지는 sin, cos을 채택
동일 column이어도, pos값이 다를경우 다른 값이 되므로 겹치는 정보를 갖는것을 방지</p>
</blockquote>
<blockquote>
<h3 id="encoderlayer">EncoderLayer</h3>
</blockquote>
<pre><code class="language-python">class EncoderLayer(nn.Module):
    def __init__(self, hidden_dim, n_heads, pf_dim, dropout_ratio, device):
        super().__init__()

        self.self_attn_layer_norm = nn.LayerNorm(hidden_dim)
        self.ff_layer_norm = nn.LayerNorm(hidden_dim)
        self.self_attention = MultiHeadAttentionLayer(hidden_dim, n_heads, dropout_ratio, device)
        self.positionwise_feedforward = PositionwiseFeedforwardLayer(hidden_dim, pf_dim, dropout_ratio)
        self.dropout = nn.Dropout(dropout_ratio)

    # 하나의 임베딩이 복제되어 Query, Key, Value로 입력되는 방식
    def forward(self, src, src_mask):

        # src: [batch_size, src_len, hidden_dim]
        # src_mask: [batch_size, src_len]

        # self attention
        # 필요한 경우 마스크(mask) 행렬을 이용하여 어텐션(attention)할 단어를 조절 가능
        _src, _ = self.self_attention(src, src, src, src_mask)

        # dropout, residual connection and layer norm
        src = self.self_attn_layer_norm(src + self.dropout(_src))

        # src: [batch_size, src_len, hidden_dim]

        # position-wise feedforward
        _src = self.positionwise_feedforward(src)

        # dropout, residual and layer norm
        src = self.ff_layer_norm(src + self.dropout(_src))

        # src: [batch_size, src_len, hidden_dim]

        return src</code></pre>
<blockquote>
<p>src 번역하는 문장 즉, input을 통과시키는 layer을 의미</p>
</blockquote>
<pre><code class="language-python">class Encoder(nn.Module):
    def __init__(self, input_dim, hidden_dim, n_layers, n_heads, pf_dim, dropout_ratio, device, max_length=100):
        super().__init__()

        self.device = device

        self.tok_embedding = nn.Embedding(input_dim, hidden_dim)
        self.pos_embedding = nn.Embedding(max_length, hidden_dim)

        self.layers = nn.ModuleList([EncoderLayer(hidden_dim, n_heads, pf_dim, dropout_ratio, device) for _ in range(n_layers)])

        self.dropout = nn.Dropout(dropout_ratio)

        self.scale = torch.sqrt(torch.FloatTensor([hidden_dim])).to(device)

    def forward(self, src, src_mask):

        # src: [batch_size, src_len]
        # src_mask: [batch_size, src_len]

        batch_size = src.shape[0]
        src_len = src.shape[1]

        pos = torch.arange(0, src_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)

        # pos: [batch_size, src_len]

        # 소스 문장의 임베딩과 위치 임베딩을 더한 것을 사용
        src = self.dropout((self.tok_embedding(src) * self.scale) + self.pos_embedding(pos))

        # src: [batch_size, src_len, hidden_dim]

        # 모든 인코더 레이어를 차례대로 거치면서 순전파(forward) 수행
        for layer in self.layers:
            src = layer(src, src_mask)

        # src: [batch_size, src_len, hidden_dim]

        return src # 마지막 레이어의 출력을 반환</code></pre>
<blockquote>
<p>encoder는 layer을 6개 쌓으므로 encoder layer와 structure을 구분해서 구현</p>
</blockquote>
<pre><code class="language-python">class DecoderLayer(nn.Module):
    def __init__(self, hidden_dim, n_heads, pf_dim, dropout_ratio, device):
        super().__init__()

        self.self_attn_layer_norm = nn.LayerNorm(hidden_dim)
        self.enc_attn_layer_norm = nn.LayerNorm(hidden_dim)
        self.ff_layer_norm = nn.LayerNorm(hidden_dim)
        self.self_attention = MultiHeadAttentionLayer(hidden_dim, n_heads, dropout_ratio, device)
        self.encoder_attention = MultiHeadAttentionLayer(hidden_dim, n_heads, dropout_ratio, device)
        self.positionwise_feedforward = PositionwiseFeedforwardLayer(hidden_dim, pf_dim, dropout_ratio)
        self.dropout = nn.Dropout(dropout_ratio)

    # 인코더의 출력 값(enc_src)을 어텐션(attention)하는 구조
    def forward(self, trg, enc_src, trg_mask, src_mask):

        # trg: [batch_size, trg_len, hidden_dim]
        # enc_src: [batch_size, src_len, hidden_dim]
        # trg_mask: [batch_size, trg_len]
        # src_mask: [batch_size, src_len]

        # self attention
        # 자기 자신에 대하여 어텐션(attention)
        _trg, _ = self.self_attention(trg, trg, trg, trg_mask)

        # dropout, residual connection and layer norm
        trg = self.self_attn_layer_norm(trg + self.dropout(_trg))

        # trg: [batch_size, trg_len, hidden_dim]

        # encoder attention
        # 디코더의 쿼리(Query)를 이용해 인코더를 어텐션(attention)
        _trg, attention = self.encoder_attention(trg, enc_src, enc_src, src_mask)

        # dropout, residual connection and layer norm
        trg = self.enc_attn_layer_norm(trg + self.dropout(_trg))

        # trg: [batch_size, trg_len, hidden_dim]

        # positionwise feedforward
        _trg = self.positionwise_feedforward(trg)

        # dropout, residual and layer norm
        trg = self.ff_layer_norm(trg + self.dropout(_trg))

        # trg: [batch_size, trg_len, hidden_dim]
        # attention: [batch_size, n_heads, trg_len, src_len]

        return trg, attention</code></pre>
<blockquote>
<p>trg 즉 번역 이후의 문장을 의미하며 decoder엔 6개의 layer가 들어감</p>
</blockquote>
<pre><code class="language-python">class Decoder(nn.Module):
    def __init__(self, output_dim, hidden_dim, n_layers, n_heads, pf_dim, dropout_ratio, device, max_length=100):
        super().__init__()

        self.device = device

        self.tok_embedding = nn.Embedding(output_dim, hidden_dim)
        self.pos_embedding = nn.Embedding(max_length, hidden_dim)

        self.layers = nn.ModuleList([DecoderLayer(hidden_dim, n_heads, pf_dim, dropout_ratio, device) for _ in range(n_layers)])

        self.fc_out = nn.Linear(hidden_dim, output_dim)

        self.dropout = nn.Dropout(dropout_ratio)

        self.scale = torch.sqrt(torch.FloatTensor([hidden_dim])).to(device)

    def forward(self, trg, enc_src, trg_mask, src_mask):

        # trg: [batch_size, trg_len]
        # enc_src: [batch_size, src_len, hidden_dim]
        # trg_mask: [batch_size, trg_len]
        # src_mask: [batch_size, src_len]

        batch_size = trg.shape[0]
        trg_len = trg.shape[1]

        pos = torch.arange(0, trg_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)

        # pos: [batch_size, trg_len]

        trg = self.dropout((self.tok_embedding(trg) * self.scale) + self.pos_embedding(pos))

        # trg: [batch_size, trg_len, hidden_dim]

        for layer in self.layers:
            # 소스 마스크와 타겟 마스크 모두 사용
            trg, attention = layer(trg, enc_src, trg_mask, src_mask)

        # trg: [batch_size, trg_len, hidden_dim]
        # attention: [batch_size, n_heads, trg_len, src_len]

        output = self.fc_out(trg)

        # output: [batch_size, trg_len, output_dim]

        return output, attention</code></pre>
<blockquote>
<h3 id="전체적인-transformer의-structure">전체적인 Transformer의 structure</h3>
</blockquote>
<pre><code class="language-python">class Transformer(nn.Module):
    def __init__(self, encoder, decoder, src_pad_idx, trg_pad_idx, device):
        super().__init__()

        self.encoder = encoder
        self.decoder = decoder
        self.src_pad_idx = src_pad_idx
        self.trg_pad_idx = trg_pad_idx
        self.device = device

    # 소스 문장의 &lt;pad&gt; 토큰에 대하여 마스크(mask) 값을 0으로 설정
    def make_src_mask(self, src):

        # src: [batch_size, src_len]

        src_mask = (src != self.src_pad_idx).unsqueeze(1).unsqueeze(2)

        # src_mask: [batch_size, 1, 1, src_len]

        return src_mask

    # 타겟 문장에서 각 단어는 다음 단어가 무엇인지 알 수 없도록(이전 단어만 보도록) 만들기 위해 마스크를 사용
    def make_trg_mask(self, trg):

        # trg: [batch_size, trg_len]

        &quot;&quot;&quot; (마스크 예시)
        1 0 0 0 0
        1 1 0 0 0
        1 1 1 0 0
        1 1 1 0 0
        1 1 1 0 0
        &quot;&quot;&quot;
        trg_pad_mask = (trg != self.trg_pad_idx).unsqueeze(1).unsqueeze(2)

        # trg_pad_mask: [batch_size, 1, 1, trg_len]

        trg_len = trg.shape[1]

        &quot;&quot;&quot; (마스크 예시)
        1 0 0 0 0
        1 1 0 0 0
        1 1 1 0 0
        1 1 1 1 0
        1 1 1 1 1
        &quot;&quot;&quot;
        trg_sub_mask = torch.tril(torch.ones((trg_len, trg_len), device = self.device)).bool()

        # trg_sub_mask: [trg_len, trg_len]

        trg_mask = trg_pad_mask &amp; trg_sub_mask

        # trg_mask: [batch_size, 1, trg_len, trg_len]

        return trg_mask

    def forward(self, src, trg):

        # src: [batch_size, src_len]
        # trg: [batch_size, trg_len]

        src_mask = self.make_src_mask(src)
        trg_mask = self.make_trg_mask(trg)

        # src_mask: [batch_size, 1, 1, src_len]
        # trg_mask: [batch_size, 1, trg_len, trg_len]

        enc_src = self.encoder(src, src_mask)

        # enc_src: [batch_size, src_len, hidden_dim]

        output, attention = self.decoder(trg, enc_src, trg_mask, src_mask)

        # output: [batch_size, trg_len, output_dim]
        # attention: [batch_size, n_heads, trg_len, src_len]

        return output, attention</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ubuntu Conda 환경 구성하기]]></title>
            <link>https://velog.io/@dl-ne_w_b_ie/Ubuntu-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dl-ne_w_b_ie/Ubuntu-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Mar 2023 12:35:31 GMT</pubDate>
            <description><![CDATA[<h1 id="1-conda설치-파일-주소-복사하기">1. Conda설치 파일 주소 복사하기</h1>
<p><a href="https://www.anaconda.com/products/distribution">https://www.anaconda.com/products/distribution</a>
<img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/9a03634f-a1d9-4815-b45f-335efa272645/image.png" alt=""></p>
<h1 id="2-터미널-열기">2. 터미널 열기</h1>
<p>좌측 상단 메뉴 - 터미널 - 새터미널 혹은 Ctrl+ Shift + `</p>
<h1 id="3-다운받고자-하는-폴더-가기">3. 다운받고자 하는 폴더 가기</h1>
<blockquote>
<p>$ cd /data/<del>~</del>
$ wget 위에서 복사한 링크주소 붙여넣기
$ ls<br>$ bash 파일명</p>
</blockquote>
<blockquote>
<p>Welcome to Anaconda3 2022.10
In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue</p>
</blockquote>
<p>ENTER 입력 후 안내문은 Enter꾹 누르다보면 </p>
<blockquote>
<p>Please answer &#39;yes&#39; or &#39;no&#39;:&#39;</p>
</blockquote>
<p>이 문구가 뜬 후 yes를 입력하면 설치가 되게됩니다.</p>
<blockquote>
<p>Anaconda3 will now be installed into this location:
/home/rlaalsrl0922/anaconda3</p>
</blockquote>
<ul>
<li>Press ENTER to confirm the location</li>
<li>Press CTRL-C to abort the installation</li>
<li>Or specify a different location below
[/home/rlaalsrl0922/anaconda3] &gt;&gt;&gt; </li>
</ul>
<p>따로 위치를 지정하고 싶으시다면 해당하는 위치를 입력하시면 되고, 아니라면 Enter 누르시면 설치가됩니다.</p>
<h1 id="4-anaconda-실행">4. Anaconda 실행</h1>
<blockquote>
<p>$ conda activate base</p>
</blockquote>
<p>입력시에 conda가 실행됩니다.</p>
<h4 id="41-가상환경-만들기">4.1 가상환경 만들기</h4>
<p>한가지 프로젝트만 진행하는게 아니기 때문에 다양한 환경을 세팅하기 위해선 base를 기반으로 환경을 만들어줍니다.</p>
<blockquote>
<p>conda create -n &lt;환경 이름&gt;</p>
</blockquote>
<h4 id="42-가상환경-지우기">4.2 가상환경 지우기</h4>
<blockquote>
<p>$ conda env remove -n &lt;환경 이름&gt;</p>
</blockquote>
<h4 id="43-가상환경-리스트">4.3 가상환경 리스트</h4>
<blockquote>
<p>$ conda env list</p>
</blockquote>
<h4 id="44-yaml파일을-통한-가상환경-만들기">4.4 yaml파일을 통한 가상환경 만들기</h4>
<blockquote>
<p>$ conda create -n &lt;환경 이름&gt; -f &lt;yaml 파일 이름&gt;</p>
</blockquote>
<p> 💡 경고문구 발생시 (To initialize your shell, run)</p>
<pre><code>To initialize your shell, run

    $ conda init &lt;SHELL_NAME&gt;

Currently supported shells are:
  - bash
  - fish
  - tcsh
  - xonsh
  - zsh
  - powershell

See &#39;conda init --help&#39; for more information and options.

IMPORTANT: You may need to close and restart your shell after running &#39;conda init&#39;.con</code></pre><blockquote>
<h4 id="1---vim-bashrc">1.  $ vim ~/.bashrc</h4>
<p>1번 입력시 아래와 같은 화면이 나옵니다</p>
</blockquote>
<h4 id="2">2. <img src="https://velog.velcdn.com/images/dl-ne_w_b_ie/post/689e782a-0570-4d74-8bf7-7d708d12eedd/image.png" alt=""></h4>
<h4 id="3-e-누르기">3. E 누르기</h4>
<h4 id="4-환경변수-설정">4. 환경변수 설정</h4>
<pre><code>맨 아랫줄에 export PATH=/콘다설치주소/bin/:$PATH</code></pre><h4 id="5-파일저장">5. 파일저장</h4>
<pre><code>:wq
작성 후 enter</code></pre><h4 id="6-활성화되는지-확인하기">6. 활성화되는지 확인하기</h4>
<p>터미널 재실행 후 
conda activate 하면 실행될겁니당</p>
]]></description>
        </item>
    </channel>
</rss>