<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hyes-y-tag.log</title>
        <link>https://velog.io/</link>
        <description>나도 하고 싶다, 개발.</description>
        <lastBuildDate>Wed, 18 May 2022 17:52:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hyes-y-tag.log</title>
            <url>https://images.velog.io/images/hyes-y-tag/profile/62ef2810-9d85-48df-ab42-3ed400a4b093/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hyes-y-tag.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hyes-y-tag" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Elice_AI_4기] 18주차 내용 정리- ① CNN]]></title>
            <link>https://velog.io/@hyes-y-tag/EliceAI4%EA%B8%B0-18%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC-CNN</link>
            <guid>https://velog.io/@hyes-y-tag/EliceAI4%EA%B8%B0-18%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC-CNN</guid>
            <pubDate>Wed, 18 May 2022 17:52:46 GMT</pubDate>
            <description><![CDATA[<p>CNN 가즈아~!</p>
<h1 id="cnnconvolutional-neural-network">CNN(Convolutional Neural Network)</h1>
<h2 id="🧐-이미지-데이터">🧐 이미지 데이터</h2>
<h3 id="✍-이미지-데이터">✍ 이미지 데이터?</h3>
<ul>
<li>이미지 데이터는 사진 또는 그림 등의 이미지를 컴퓨터에 저장한 데이터를 의미</li>
<li><code>*.jpg</code>, <code>*.png</code> 등의 확장자를 가진 파일</li>
<li>Pixel(<code>Pictures Elements</code>) 로 이루어진 2차원 데이터</li>
<li>각 Pixel은 색상이나 밝기 정보를 가짐</li>
<li>색상은 RGB 3채널로 표현되며 각 채널은 8비트의 수로 이루어짐</li>
<li>흑백 이미지의 경우 Pixel은 밝기 정보만 가지고 있으며 255: 흰색, 0: 검은색</li>
</ul>
<h3 id="✍-딥러닝을-활용한-이미지-처리-사례">✍ 딥러닝을 활용한 이미지 처리 사례</h3>
<ul>
<li>사물 인식(Object Detection) ex&gt; 자율 주행, 안면 인식 등</li>
<li>이미지 캡셔닝(Image Captioning) </li>
<li>이미지 합성 ex&gt; 딥페이크</li>
<li>화질 개선 ex&gt; super resolution, NVIDIA DLSS</li>
<li>etc,.</li>
</ul>
<h3 id="✍-이미지-처리-기법except-딥러닝">✍ 이미지 처리 기법(except 딥러닝)</h3>
<ul>
<li><p>형태 변환
ex&gt; crop(잘라내기) / rotate(회전) / resize(사이즈 재정의) / shearing(전단 변환) / rescale(비율 변환)</p>
</li>
<li><p>색상 변환
ex&gt; brightness(밝기 조절) / contrast(대조 변환) / grayscale(흑백 변환)</p>
</li>
<li><p>필터
ex&gt; sharpening / blur / edge-detection</p>
</li>
<li><p>Python의 경우 <code>Pillow</code> 혹은 <code>OpenCV</code> 로 이미지 전처리 가능</p>
</li>
</ul>
<h2 id="🧐-cnn-convolutional-neural-network">🧐 CNN (Convolutional Neural Network)</h2>
<h3 id="✍-cnn-등장-배경">✍ CNN 등장 배경</h3>
<ul>
<li>초기 모델인 Perceptron 의 경우 Fully Connected Layer(FC Layer)로 구성</li>
<li>FC Layer =&gt; 1차원 데이터 처리</li>
<li>이미지 데이터(2차원)를 1차원으로 바꾸면 공간 정보가 소실됨</li>
<li>2차원 데이터를 그대로 유지하면서 학습할 수 있는 CNN 등장</li>
</ul>
<h3 id="✍-cnn-구성-요소">✍ CNN 구성 요소</h3>
<ul>
<li>Convolutional Layer ⭐⭐</li>
<li>Pooling Layer</li>
<li>Classifier (FC Layer)</li>
</ul>
<h3 id="1-convolutional-layer-⭐⭐">1. Convolutional Layer ⭐⭐</h3>
<h4 id="convolution-연산"><strong>Convolution</strong> 연산</h4>
<p>2차원의 5 X 5 이미지 데이터와 3 X 3 커널(필터)이 있다고 할 때
<img src="https://velog.velcdn.com/images/hyes-y-tag/post/fcfce1e9-2700-45e2-88cc-a0ec70d1a803/image.png" alt=""></p>
<p>아래와 같은 연산이 진행됨</p>
<pre><code class="language-python"># stride: 1
result[0][0] = 
    image[0][0] * kernel[0][0] +
    image[0][1] * kernel[0][1] +
    image[0][2] * kernel[0][2] +
    image[1][0] * kernel[1][0] + 
    ... +
    image[2][2] * kernel[2][2]
result[0][1] = 
    image[0][1] * kernel[0][0] +
    image[0][2] * kernel[0][1] +
    image[0][3] * kernel[0][2] +
    ... +
    image[2][3] * kernel[2][2]
 ...</code></pre>
<p>이런 연산 방식을 <strong>convolution</strong> 연산이라고 하며 
이미지 데이터와 커널의 convolution 연산을 통해 나온 결과 =&gt;  <strong>feature map</strong></p>
<ul>
<li>RGB 채널에 연산을 수행할 경우 각 채널별로 convolution 연산을 수행한 후 결과를 더해서 하나의 feature map 생성</li>
<li>커널(필터)이 n개인 경우 feature map도 n개 생성</li>
<li>커널 =&gt; 학습 가능 =&gt; 커널의 각 값들이 가중치가 됨</li>
</ul>
<h4 id="convolutional-layer">Convolutional Layer</h4>
<ul>
<li><p>학습 가능한 커널들로 이루어진 Layer</p>
</li>
<li><p>layer와 layer 내부 커널을 통해 이미지의 특정 feature를 추출할 수 있음</p>
</li>
<li><blockquote>
<p>특정 feature를 추출하도록 커널 학습 가능</p>
</blockquote>
</li>
<li><p><strong>Hyperparameter</strong></p>
<ul>
<li><code>stride</code> : 커널의 이동 폭<ul>
<li><code>padding</code> : 이미지의 padding 
(convolution 연산 수행시 feature map 크기가 줄어듦을 방지)</li>
</ul>
</li>
</ul>
</li>
<li><p>하나의 커널이 픽셀 간 정보를 보며, 이미지 전체 영역을 학습하기 때문에 이미지 특징을 잘 뽑아낼 수 있음</p>
</li>
<li><p>커널이 가진 parameter를 이미지의 모든 영역에서 공유하기 때문에 
FC Layer에 비해 parameter 수가 현저히 적으며 <strong>과적합 방지</strong>에 유리함</p>
</li>
<li><p>Convolution 또한 선형 연산이기 때문에 비선형성을 추가하기 위해 활성화 함수(주로 <code>ReLU</code>) 를 사용</p>
</li>
</ul>
<h3 id="2-pooling-layer">2. Pooling Layer</h3>
<ul>
<li><p>역할 : Feature Map 사이즈를 줄여서 Parameter 개수를 줄이는 것 -&gt; 과적합 조절</p>
</li>
<li><p>이미지나 Feature Map을 겹치지 않는 영역으로 분할한 후
각 영역의 최대값 / 평균값 을 계산하여 새로운 Feature Map을 구성
( MaxPooling / Average Pooling)</p>
</li>
<li><p>일반적으로 Max Pooling 을 사용</p>
</li>
<li><p>Feature Map의 채널이 여러 개인 경우 각 채널 별로 Pooling 연산 수행</p>
</li>
<li><p>Global Average Pooling / Global Max Pooling
: 전체 Feature Map에서 하나의 평균값 / 최대값 을 계산
=&gt; 여기선 Global Average Pooling을 많이 사용</p>
</li>
</ul>
<h3 id="3-classifier-분류기">3. Classifier (분류기)</h3>
<ul>
<li>역할 : 이미지를 <strong>분류</strong> 하기 위해 Feature Map을 1차원으로 변환하여 FC Layer에 통과 시켜 분류를 수행</li>
</ul>
<br>

<h3 id="✍-cnn-모델-구성">✍ CNN 모델 구성</h3>
<ul>
<li>convolutional Layer와 pooling layer는 짝꿍!</li>
<li>conv + pool 로 feature map을 뽑아낸 후 Dense(fc layer) 로 이미지 분류</li>
</ul>
<p><code>Input Layer</code> - (<code>Convolutional Layer</code> - ... - <code>Pooling Layer</code>) (repeat)  - <code>Dense Layer</code> - ... - <code>Output Layer</code></p>
<br>

<h3 id="✍-대표적인-cnn-모델">✍ 대표적인 CNN 모델</h3>
<ul>
<li><p><strong>LeNet</strong>(1990) =&gt; 우편번호 인식을 위한 모델</p>
</li>
<li><p><strong>AlexNet</strong>(2012) =&gt; imageNet challenge 우승 -&gt; 기존 모델 성능을 큰 폭으로 상회
  =&gt; 딥러닝 모델 학습에 GPU를 활용</p>
</li>
<li><p><strong>VGGNet</strong>(2014) =&gt; 커널 사이즈를 모두 <strong>3 x 3</strong>으로 통일
parameter 수 증가를 억제하면서 모델 층을 더 많이 쌓을 수 있게 됨
(층이 많을수록 성능이 향상됨)</p>
</li>
<li><p><strong>ResNet</strong>(2015) =&gt; layer 개수를 최대 152개로 늘림
=&gt; 이전 모델의 문제 : layer 개수가 많아지면 역전파시 <strong>vanishing gradient</strong>(기울기 소실) 문제 발생 
=&gt; <strong>residual connection</strong> 으로 해결</p>
</li>
</ul>
<blockquote>
<p>🤷‍♀️ <strong>Residual Connection ?</strong>
convolutional layer을 우회하는 연결 
=&gt; 입력 feature map이 우회로를 통과하여 convolutional layer의 feature map과 더해짐
=&gt; 기울기가 항상 1 이상이 되어 기울기 소실 문제 해결
<img src="https://velog.velcdn.com/images/hyes-y-tag/post/f3f27b11-1747-4e69-93b0-4f114c29dba3/image.png" alt=""></p>
</blockquote>
<ul>
<li>이미지 분류 작업 외</li>
<li><blockquote>
<p><strong>YOLO</strong> / <strong>R-CNN</strong> (객체인식) , <strong>U-Net</strong> (이미지 분할) 등</p>
</blockquote>
</li>
</ul>
<br>
<br>
<br>


<blockquote>
<p>출처: 엘리스 학습 자료 및 강의</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Elice_AI_4기] 17주차 내용 정리- 딥러닝 기초]]></title>
            <link>https://velog.io/@hyes-y-tag/EliceAI4%EA%B8%B0-17%EC%A3%BC%EC%B0%A8-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B3%B5%EC%8A%B5</link>
            <guid>https://velog.io/@hyes-y-tag/EliceAI4%EA%B8%B0-17%EC%A3%BC%EC%B0%A8-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B3%B5%EC%8A%B5</guid>
            <pubDate>Mon, 16 May 2022 17:53:19 GMT</pubDate>
            <description><![CDATA[<p>밀린 React, Express, Pandas를 뒤로하고..
17주차 복습 시작!</p>
<h1 id="🤷♀️-딥러닝">🤷‍♀️ 딥러닝?</h1>
<blockquote>
<p>인공지능(Artificial Inteligence) </p>
<blockquote>
<p>머신러닝(Machine Learning)</p>
<blockquote>
<p>딥러닝(Deep Learning)</p>
</blockquote>
</blockquote>
</blockquote>
<p>딥러닝은 <strong>인공신경망</strong>에 기반하여 컴퓨터에게 사람의 사고방식을 가르치는 방법으로 보통 모델의 <code>입력층(Input Layer)</code> 과 <code>출력층(Output Layer)</code> 사이에 존재하는 <code>히든 레이어(Hidden Layer)</code> 가 3층 이상일 때 <strong>딥러닝</strong> 이라고 한다.</p>
<ul>
<li>인공신경망 : 사람의 신경 시스템을 모방<ul>
<li>특징 : 모델 <strong>스스로</strong> 데이터의 특성을 학습 =&gt; 지도/비지도 학습 모두 가능 </li>
</ul>
</li>
</ul>
<h2 id="🧐-퍼셉트론perceptron">🧐 퍼셉트론(Perceptron)</h2>
<ul>
<li><p>사람의 <strong>뉴런</strong> 과 같은 역할을 하는 모델로 초기 형태의 신경망</p>
</li>
<li><p>등장 배경: <strong>명시적 프로그래밍</strong>의 한계(모든 조건을 고려할 수 없음)
  =&gt; 모델 스스로 데이터를 판단할 수 있는 기술이 필요</p>
</li>
<li><p>구조: 입력값과 각각의 가중치를 곱하여 더한 후 <code>bias</code>를 더한 값을 활성함수(activation)에 넣음 
<img src="https://velog.velcdn.com/images/hyes-y-tag/post/2797b15d-97f5-4d9d-a1ad-64311be24777/image.png" alt=""></p>
</li>
<li><p>activation function의 경우 <code>step function</code>으로 일정 값을 넘으면 1, 그렇지 않으면 0 형태의 값을 가짐</p>
</li>
</ul>
<h3 id="✍-단층-퍼셉트론single-layer-perceptron">✍ 단층 퍼셉트론(Single Layer Perceptron)</h3>
<ul>
<li>입력층과 출력층으로만 이루어진 단층 퍼셉트론으로 논리회로 구현 및 선형 분류 가능
ex&gt; <code>AND</code> Gate, <code>OR</code> Gate, <code>NAND</code> Gate, <code>NOR</code> Gate , ...</li>
</ul>
<h3 id="✍-다층-퍼셉트론multi-layer-perceptron">✍ 다층 퍼셉트론(Multi Layer Perceptron)</h3>
<ul>
<li><code>XOR</code> Gate 와 같이 선형 분류로 해결할 수 없는 비선형적 문제 발생
ex&gt; XOR</li>
</ul>
<table>
<thead>
<tr>
<th>x1</th>
<th>x2</th>
<th>output</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
</tbody></table>
<p>=&gt; 단층 퍼셉트론을 여러층으로 쌓아 비선형적 문제 해결
=&gt; <code>XOR</code>의 경우 <code>NAND</code> 와 <code>OR</code> 을 결합하여 구현 가능</p>
<ul>
<li>입력층, 출력층 외에 쌓여져 있는 여러 층을 <code>Hidden Layer</code>라고 함</li>
<li>이 <code>Hidden Layer</code> 가 3층 이상이면 <strong>딥러닝</strong></li>
</ul>
<h2 id="🧐-딥러닝-모델">🧐 딥러닝 모델</h2>
<h3 id="✍-구성-요소">✍ 구성 요소</h3>
<ul>
<li><code>Node/Unit</code> : 각 층을 구성하는 요소</li>
<li><code>Weight</code> : 각 노드를 연결하는 강도(=가중치)</li>
<li><code>Layer</code> : 모델을 구성하는 층</li>
</ul>
<h3 id="✍-학습-방법">✍ 학습 방법</h3>
<ul>
<li><p><code>Loss Function</code> 을 <strong>최소화</strong>하기 위해 최적화 알고리즘 <code>Optimizer</code>을 적용</p>
</li>
<li><p><code>예측값과 실제값간의 오차값</code>을 줄이기 위해 <code>오차값을 최소화하는 인자를 찾는 알고리즘</code>을 적용
  <img src="https://velog.velcdn.com/images/hyes-y-tag/post/11e1a484-9827-49fa-bfe4-8c9fcfeff298/image.png" alt=""></p>
</li>
<li><p><code>loss function</code> : 예측값과 실제값 간 오차값
ex&gt; MAE, MSE, RMSE, Cross entropy</p>
</li>
<li><p>기본적인 최적화 알고리즘 : <code>GD(Gradient Descent)</code></p>
<ul>
<li>손실함수의 값을 최소화하기 위해 특정 가중치의 기울기(Gradient)를 이용하는 방법<ul>
<li><code>W(t+1) = W(t) - lr * dLoss(W)</code></li>
</ul>
</li>
<li>W(t) : t번째 가중치</li>
<li>lr: 학습률(Learning Rate)</li>
<li>dLoss(W): 해당 가중치에서 손실함수의 기울기(미분)</li>
</ul>
</li>
<li><p>각 가중치의 기울기 구하는 방법 : <strong>역전파(Back Propagation)</strong></p>
<ul>
<li><code>역전파(Back Propagation)</code> : 목표 값과 모델이 예측한 output 값의 오차를 구하여 다시 뒤로 전파하면서 변수 값을 갱신하는 알고리즘<ul>
<li><code>순전파(Forward Propagation)</code> : 입력값을 바탕으로 출력값을 계산하는 과정</li>
</ul>
</li>
</ul>
</li>
</ul>
<br>

<h2 id="🧐-딥러닝의-문제점">🧐 딥러닝의 문제점</h2>
<blockquote>
</blockquote>
<ol>
<li>학습 속도 문제</li>
<li>기울기 소실 문제</li>
<li>초기값 설정 문제</li>
<li>과적합 문제</li>
</ol>
<h3 id="✍-학습-속도-문제">✍ 학습 속도 문제</h3>
<ul>
<li><p>원인 
데이터 개수가 <strong>많아지면서</strong> 전체 데이터를 사용하여 손실함수를 계산할 때 계산량이 증가 =&gt;  속도가 낮아짐</p>
</li>
<li><p>해결 방법
전체 데이터가 아닌 <strong>부분 데이터</strong>를 활용하여 손실 함수를 계산
=&gt; <code>SGD(Stochastic Gradient Descent)</code></p>
</li>
<li><p>SGD(Stochastic Gradient Descent)</p>
<ul>
<li>전체 데이터(batch)가 아닌 일부 데이터(mini-batch)에 대해 손실함수 계산 <ul>
<li>정확도는 떨어지지만 계산 속도가 빠름 =&gt; 많은 step 진행 가능</li>
<li>한계 
1) mini-batch에 따른 Gradient 방향에 대한 문제 발생
2) Learning Rate가 너무 크거나 작은 경우 최적값 찾기가 어려움</li>
</ul>
</li>
</ul>
</li>
<li><p>다양한 최적화 알고리즘 등장</p>
<ul>
<li><code>SGD</code>의 <code>Gradient 방향</code> 해결 : <code>Momentum</code> -&gt; <code>Adam</code><ul>
<li><code>SGD</code>의 <code>Learning Rate</code> 관련 문제 해결: <code>AdaGrad</code> -&gt; <code>RMSProp</code> -&gt; <code>Adam</code></li>
</ul>
</li>
</ul>
</li>
<li><p><code>Adam</code> : <code>Momentum</code>의 장점과 <code>RMSProp</code>의 장점을 결합한 최적화 알고리즘</p>
</li>
</ul>
<h3 id="✍-기울기-소실-문제">✍ 기울기 소실 문제</h3>
<ul>
<li>원인
더 깊고 넓은 망을 학습시키면서 역전파시 <strong>출력값과 멀어질 경우</strong> 학습이 잘 안되는 문제 발생 -&gt; <code>sigmoid</code> 사용시 역전파할때 <strong>기울기가 0</strong>인 값을 전달하며 중간값 소실 -&gt; 기울기 소실 문제가 반복되며 학습 제대로 안됨</li>
<li>해결 방법
<code>activation function</code> 으로 <code>sigmoid</code> 대신 </li>
<li><em><code>ReLU</code>*</em>(내부 히든층) / <strong><code>tanh</code></strong> (외부 출력층) 사용</li>
</ul>
<h3 id="✍-초기값-설정-문제">✍ 초기값 설정 문제</h3>
<ul>
<li><p>원인
초기값을 잘못 설정할 경우 성능 차이가 크게 발생</p>
</li>
<li><p>해결 방법
활성화 함수의 <strong>입력값</strong>이 너무 커지거나 작아지게 하면 안됨</p>
<ul>
<li><ol>
<li>표준 정규분포 / 표준편차를 0.01로 하는 정규 분포로 초기화</li>
</ol>
</li>
<li><ol start="2">
<li><code>Xavier</code> 초기화 방법 + <code>Sigmoid</code>
<code>Xavier</code> : 표준 정규분포를 입력개수의 제곱근으로 나누어줌</li>
</ol>
</li>
</ul>
<p>🚩 ReLU 함수에는 Xavier초기화가 적합하지 않음
레이어를 거칠수록 값이 0에 수렴</p>
<ul>
<li><ol start="3">
<li><code>He</code> 초기화 방법 + <code>ReLU</code>
<code>He</code> : 표준 정규분포를 입력개수의 절반의 제곱근으로 나누어줌</li>
</ol>
</li>
</ul>
</li>
</ul>
<p><strong>Sigmoid, tanh 에는 Xavier, ReLU 에는 He가 효율적</strong></p>
<h3 id="✍-과적합-문제">✍ 과적합 문제</h3>
<ul>
<li>원인
train data에 과적합하여 실제 데이터에 대한 예측 성능 저하</li>
<li>해결 방법</li>
<li><ol>
<li>정규화(Regularization) : 기존 손실함수에 <strong>규제항</strong>을 더해 최적값 찾기 가능<ul>
<li>1) L1 정규화 (Lasso Regularization)
가중치의 <strong>절댓값의 합</strong>을 규제항으로 정의
작은 가중치가 거의 0으로 수렴함 -&gt; 몇 개의 중요한 가중치만 남음     </li>
<li>2) L2 정규화 (Ridge Regularization)
가중치의 <strong>제곱의 합</strong>을 규제항으로 정의
큰 값을 가진 가중치를 제약하는 효과</li>
</ul>
</li>
</ol>
</li>
</ul>
<ul>
<li><ol start="2">
<li>드롭아웃(Dropout) : 각 layer마다 <strong>일정 비율의 뉴런(node)을 임의로 drop</strong>
-&gt; 학습되는 노드와 가중치들이 매번 달라짐</li>
</ol>
<ul>
<li>다른 정규화 기법과 상호 보완적으로 사용 가능
-&gt; backpropagation 할때 신호를 끊음</li>
</ul>
</li>
<li><ol start="3">
<li>배치 정규화(Batch Normalization) 
: normalization을 input data 뿐만 아니라 <strong>hidden layer의 input에도 적용</strong></li>
</ol>
<ul>
<li>layer마다 정규화를 진행해서 <strong>초기화 중요도 감소</strong></li>
<li>과적합 억제(Dropout, L1, L2 정규화 필요성 감소)</li>
<li>핵심은 학습 속도의 향상</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p>출처: <code>/*elice*/</code> 수업 자료</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[엘리스 AI 4기] 2차 프로젝트 회고]]></title>
            <link>https://velog.io/@hyes-y-tag/%EC%97%98%EB%A6%AC%EC%8A%A4-AI-4%EA%B8%B0-2%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@hyes-y-tag/%EC%97%98%EB%A6%AC%EC%8A%A4-AI-4%EA%B8%B0-2%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 13 May 2022 16:00:17 GMT</pubDate>
            <description><![CDATA[<p>어제 끝난 것 같은데 벌써 일주일이나 됐네,, 잊어버리기 전에 얼른 회고해야징</p>
<h2 id="엘리스-ai-4기-2차-프로젝트---2팀-문해한-하루">엘리스 AI 4기 2차 프로젝트 - 2팀 문해한 하루</h2>
<p><strong>1차</strong>는 프로젝트의 전반적인 구조가 정해져있었고(주제, 기본 MODEL) 각 팀별로 좀 더 색다른 기능을 추가하는 형식이었다면
<strong>2차</strong>는 이제 너희가 알아서 해라!! 방식으로 진행이 되었다.
(1차는 2주, 2차는 3주 동안 진행)</p>
<p>큰 주제는 <strong>「데이터 분석 웹 서비스 with Kaggle」</strong> 였는데 
요 &quot;데이터 분석&quot; 이라는 단어가 굉장히 다양하게 해석되어서 애를 먹었었다.</p>
<blockquote>
<p>데이터를 분석하는 서비스? 
데이터를 분석해서 그 결과를 근거로 서비스를 제공?</p>
</blockquote>
<p>어쨌든,
우리는 <strong><em>kaggle 데이터를 분석하여 우리 서비스의 근거로 사용하자!</em></strong> 
이렇게 결정했고
kaggle의 literacy, GDP, Education Statistics 자료를 활용하여
문해력 트레이닝 서비스, <strong>문해한 하루</strong> 를 만들게 되었다.</p>
<h2 id="😵-기획-좀-누가-해주세요">😵 기획 좀,, 누가 해주세요,,</h2>
<p>호기롭게 주제를 정했으나 
기능을 추리고, 와이어프레임을 제작하고 DB 스키마 및 API를 설계하는데 정말 3주를 다썼다. 마지막 주까지 스키마랑 API를 고칠 줄은 몰랐는데 ,,</p>
<p>서비스에서 제공할 크고 작은 기능을 정하는 것부터 화면 설계까지 하려니 일주일은 턱없이 모자랐고, 진행하면서 꾸준히 수정을 했고, 정말 정신이 없었다.</p>
<p>개발팀마다 기획이 왜 있는지 이번에 몸소 체험했다. 
<em>3차엔 기획 파트 팀원이 계시겠지요? ㅠㅠ</em></p>
<h2 id="😵-restful-그게-뭔데">😵 RESTful.. 그게 뭔데</h2>
<p>프로젝트 하면서 가장 피곤하게 했던 바로 API..
<strong>RESTful</strong>에 대해 정확히 알지 못한 상태에서 endpoint를 나름의 규칙대로 작성하기 시작했는데 그 규칙이 너무 내맘대로였을까? 마지막 주에 코치님의 코드 리뷰를 통해 endpoint를 모조리 수정하게 되었다.
덕분에 RESTful의 느낌을 살짝 맛보긴 했지만 프론트파트 팀원들에게 미안했다. ㅠㅠ 
API 문서도 기존에 노션으로 관리를 하다가 마지막 주에 <code>Swagger</code>로 옮겼는데 
10개 정도의 MVP 별 라우터를 <code>Yaml</code> 파일에 모조리 작성하면서 </p>
<p>** 아, API 문서 정리는 그때 그때 하자 ** </p>
<p>라고 수 백번 생각했던 것 같다. ㅎㅎ</p>
<h2 id="😵-mongodb-제발">😵 MongoDB 제발,,</h2>
<p>프로젝트 스택은 <code>React</code>, <code>express</code>, <code>MongoDB</code> 가 메인이었는데 
백엔드 파트의 주된 이슈는 이 <code>MongoDB</code>에서 일어났다.</p>
<h4 id="1-nosql을-rdbms처럼-쓰고자-하는-굳은-의지">1. NoSQL을 RDBMS처럼 쓰고자 하는 굳은 의지</h4>
<blockquote>
<p><em>신에게는 <code>virtual schema</code>와 <code>populate</code>가 남아있습니다.</em></p>
</blockquote>
<p>굳이 왜 NoSQL을 쓰는지 이해가 안 갈 정도로 Document끼리 관계 설정을 해서 사용했던 것 같다.
1차에는 기능이 엄청 많지 않은 프로젝트여서 MongoDB 좋은데?! 하면서 썼었는데, 기능이 조금 더 많아지니 아주 골치 아팠다.
이렇게밖에 쓰지 못하는 나의 문제이지만 NoSQL,, 너무 어렵다.</p>
<h4 id="2-아직은-어려운-mongodb">2. 아직은 어려운 MongoDB</h4>
<p>문법도 문법이고, 다양한 기능을 custom하기에 지식이 너무 짧아 오류 핸들링이나 기능 추가시 시간을 좀 잡아 먹었던 것 같다.</p>
<h2 id="😵-docker--docker-">😵 Docker ? Docker !</h2>
<p>배포는 <code>docker</code>로 했고, 다른 백엔드 팀원께서 맡아서 해주셔서 옆에서 구경만 했지만.. 옆에서 보는 것도 어렵고 그냥 어려움.
그치만 배포하시면서도 <code>docker</code>에 대해 친절하게 설명해주시고 엘리스에서 제공해 준 <code>docker</code> 강의도 있기 때문에! 이 부분은 계속 공부해보려고 한다.</p>
<br>

<h2 id="🧐-노력한-부분">🧐 노력한 부분</h2>
<h3 id="🔥-좀더-효율적인-로직-구현실패">🔥 좀더 효율적인 로직 구현(실패)</h3>
<p>populate를 줄이고, 처리 속도를 높이는 쪽으로 고민을 많이 해봤으나 막바지에 다다르니 구현에 초점이 맞춰져서 효율은 조금 포기했다.
그래도 쓸데없는 동기적 로직을 <code>Promise.all</code> 로 많이 개선했고
어떻게 하면 좋을지에 대한 고민을 한 것만으로도 나름.. 개발에 대한 나의 마음가짐의 발전이라고 생각한다.</p>
<h3 id="🔥-백엔드에서-다뤄야-할-부분에-대한-고민">🔥 백엔드에서 다뤄야 할 부분에 대한 고민</h3>
<p>서비스에서 제공하는 기능같은 경우 백엔드 혼자서 오롯이 해낼 수 있는 건 없다. 프론트에서 같이 작업을 해줘야하기 때문에 서비스에서 제공하는 기능 외에 어떤 부분을 더 개선할 수 있을지 고민을 많이 했다.</p>
<h4 id="1-로그-작성">1. 로그 작성!</h4>
<p>물론 라이브러리와 구글의 많은 개발자님들이 다 해주었지만 <code>winston</code>과 <code>morgan</code>을 이용해 운영 중 발생할 이슈에 대비해 로그를 찍도록 구현을 해봤다. 실제 운영하는 서비스에선 로그가 굉장히 중요한 데이터라고 하니 작은 프로젝트에서도 로그를 찍는건 꼭 포함할 예정이다.</p>
<h4 id="2-새로운-기술-적용">2. 새로운 기술 적용</h4>
<ul>
<li>개인적으로 캐시를 주로 다루는 <code>Redis</code>를 사용해보고 싶었고 <code>Redis</code>를 사용하면 데이터가 캐싱이 되어있는 경우 응답 속도가 훨씬 빠르다고 해서 프로젝트에 적용해보고 싶었으나 <code>Redis</code>를 적용할만한 기능이 딱히 없어서 사용을 하진 않았다. (우리가 제공하는 기능에서는 웬만한건 DB도 빠를거라고 하셨음)
하지만 어떻게든 써보려고 많이 찾아봤고 (ㅋㅋ) 꽤 흥미로운 점이 많아서 <code>Redis</code>는 다음 프로젝트때는 꼭 사용해보려고 한다.</li>
<li><code>elastic search</code> 같은 경우는 이미 한번 해본적이 있지만 ..
<del><em>있었는데요,, 없습니다,,</em></del>
그래서 이번 프로젝트에 적용하기엔 남은 기간이 짧아 이 기술은 나머지 공부한 후에 다음 프로젝트나 개인 프로젝트 할 때 한번 사용해보려고 한다.</li>
</ul>
<br>

<h2 id="🤦♀️-도전은-어렵고-개발도-어려워">🤦‍♀️ 도전은 어렵고 개발도 어려워</h2>
<p>올해도 역시나(앞으로 당분간) 나의 모토는 <strong>&quot;도전&quot;</strong> 이었기에
겁없이 팀장을 자처했으나 팀에 크게 도움이 되었는지는 잘 모르겠다. 
팀원 개개인의 역량이 출중하셨으나 그런 팀원들을 잘 받쳐주지 못한 것 같고 
여러 상황에 대해 팀장으로써 올바르게 대처하지 못한 것 같아 개인적으로 아쉬움이 많이 남는 프로젝트였다.</p>
<p>그렇지만 부족한 만큼 배운 것도 많기 때문에 다음엔 더 좋은 모습으로 프로젝트에 임할 수 있을 거라고 믿는다. 😂</p>
<p><strong>회고 끝!</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[node.js] kakao 로그인 unlink API 요청시 401 에러..! ]]></title>
            <link>https://velog.io/@hyes-y-tag/node.js-kakao-%EB%A1%9C%EA%B7%B8%EC%9D%B8-unlink-API-%EC%9A%94%EC%B2%AD%EC%8B%9C-401-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@hyes-y-tag/node.js-kakao-%EB%A1%9C%EA%B7%B8%EC%9D%B8-unlink-API-%EC%9A%94%EC%B2%AD%EC%8B%9C-401-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Sat, 30 Apr 2022 17:50:08 GMT</pubDate>
            <description><![CDATA[<p>소셜 로그인 유저가 탈퇴할 경우 
우리 프로젝트와 유저의 kakao로 이어진 연결을 끊어주기 위해 unlink(by Admin Key)를 사용하였고 역시나 마주한 오류.</p>
<h2 id="🧐-kakao-login-unlink-">🧐 kakao Login Unlink ?</h2>
<blockquote>
</blockquote>
<p>연결 끊기는 앱과 사용자 카카오계정의 연결을 끊는 기능입니다.</p>
<pre><code class="language-bash"># URL
POST /v1/user/unlink HTTP/1.1
Host: kapi.kakao.com
Authorization: KakaoAK ${APP_ADMIN_KEY}
&gt;
# Header
Authorization: KakaoAK ${APP_ADMIN_KEY}
&gt;
# Parameter
target_id_type:    String    #회원번호 종류, user_id로 고정
target_id:    Long    #연결을 끊을 사용자의 회원번호
&gt;
# Response 
id:    Long    # 연결 끊기에 성공한 사용자의 회원번호</code></pre>
<blockquote>
</blockquote>
<p>출처: Kakao Developers (<a href="https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#unlink">https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#unlink</a>)</p>
<p>연결 끊기는 두 가지 방식이 존재하며</p>
<blockquote>
</blockquote>
<ol>
<li>연결시 발급한 access token</li>
<li>kakao에서 주는 앱 admin key</li>
</ol>
<p>프로젝트의 탈퇴 로직상 access_token 사용은 번거로워서 admin key를 이용하는 방식으로 진행을 했다. </p>
<p>근데 401에러 두둥-</p>
<h2 id="😵-무엇이-문제였을까">😵 무엇이 문제였을까?</h2>
<p>axios.post에 알뜰살뜰히 정보를 넣어 보냈건만 401에러라니,, 
아무래도 데이터가 안넘어가는듯 해서 <code>parameter</code>를 객체로도 바꿔보고, <code>json</code>으로도 바꿔보고 갖은 삽질을 해보다가 결국 검색을 해보았고
kakao 데브톡에도 관련 오류에 대한 글이 있어 찬찬히 살펴보던 중 실마리를 발견했다!</p>
<blockquote>
</blockquote>
<p>parameter의 형식을 바꿔보세요~!</p>
<br>

<h2 id="👏-axiospost의-params를-urlsearchparams-객체로-설정하면-된다">👏 axios.post의 params를 URLSearchParams 객체로 설정하면 된다!</h2>
<p>또 <code>axios</code> ! 
지난 이슈에서도 정리를 했었지만 
<code>axios.post</code> 의 두번째 인자인 <code>params</code> 에는 <strong>객체</strong> 혹은 <strong><code>URLSearchParams</code> 객체</strong>가 들어갈 수 있다.</p>
<p><del>_까맣게 잊어버리고 처음에 또 json으로 삽질한 나 자신,,,정신채려,, _</del></p>
<p>객체로도 보냈던 것 같은데 계속 401오류가 났지만 <code>URLSearchParams</code> 객체에 담아서 보내니 바로 성공이 되었다.</p>
<p><code>URLSearchParams</code> 객체에 추가를 하면 url에 querystring의 형태로 추가가 되는 것 같은데 <code>axios</code>도 그렇지 않나? 이 부분은 좀더 찾아봐야 할 것 같다.</p>
<h2 id="결론">결론!</h2>
<p><strong>axios.post로 요청을 보낼 때 데이터 타입을 신경쓰자!</strong>
<code>formData</code>, <code>URLSearchParams</code>, 객체 이렇게 세 가지를 고려하면 될 것 같다.
객체를 제외한 두가지 타입은 잘 넘어오는걸 확인했으니
프로젝트 끝나고 나서 한번 params에 객체를 넣어 test를 해봐야겠다.</p>
<p>생각해보니
<code>formData</code> 를 객체에 넣어서(<code>{ formData }</code>) 보낼 때도 <code>multipart</code> 오류가 났었다. 😂</p>
<p>앞으론 까먹지 않고 제대로 넣을게 axios.. 미안
kakao도 미안,, ㅋㅋ</p>
<blockquote>
</blockquote>
<p>출처:
axios 러닝 가이드 - <a href="https://yamoo9.github.io/axios/guide/form-format.html#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80">https://yamoo9.github.io/axios/guide/form-format.html#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80</a>
Axios 공식 문서 - <a href="https://axios-http.com/kr/docs/req_config">https://axios-http.com/kr/docs/req_config</a>
kakao Login API Docs (unlink) - <a href="https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#unlink">https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#unlink</a>
URLSearchParams 설명 - <a href="https://developer.mozilla.org/ko/docs/Web/API/URLSearchParams">https://developer.mozilla.org/ko/docs/Web/API/URLSearchParams</a></p>
<p><em>늘 감사합니다,, 글을 써주시는 모든 분들</em> 😍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[node.js] axios.post 요청시 headers, params가 안보내진다면? ]]></title>
            <link>https://velog.io/@hyes-y-tag/node.js-axios.post-%EC%9A%94%EC%B2%AD%EC%8B%9C-headers-params%EA%B0%80-%EC%95%88%EB%B3%B4%EB%82%B4%EC%A7%84%EB%8B%A4%EB%A9%B4</link>
            <guid>https://velog.io/@hyes-y-tag/node.js-axios.post-%EC%9A%94%EC%B2%AD%EC%8B%9C-headers-params%EA%B0%80-%EC%95%88%EB%B3%B4%EB%82%B4%EC%A7%84%EB%8B%A4%EB%A9%B4</guid>
            <pubDate>Sat, 23 Apr 2022 14:57:36 GMT</pubDate>
            <description><![CDATA[<p>소셜 로그인(kakao) 구현 코드를 보던 중 </p>
<pre><code class="language-js">axios
  .post(`${url}?grant_type=${grantType} ... `, 
           { 
              headers: {
                  &quot;Content-type&quot;: &quot;...&quot;,
                }
});</code></pre>
<p>저 axios 첫번째 인자의 길이가 생각보다 길어서 수정을 했는데 거기서 또 오류를 맞이했다.</p>
<p>1작성 1오류,,?</p>
<h3 id="🧐-axios가-뭐지">🧐 axios가 뭐지?</h3>
<p><code>axios</code>는 <strong>Javascript</strong>로 API 통신을 한다 하면 대표적으로 등장하는 <br> <strong>promise</strong>기반 <strong>HTTP 클라이언트</strong> 이다.</p>
<p>참고 문서: <a href="https://axios-http.com/kr/docs/intro">Axios Docs</a></p>
<br>

<p>리액트에 대해 아무것도 모르는 채로 프로젝트에 적용해야 했었을 때가 있었는데 그때 폭풍 검색으로 처음 접한 <code>axios</code></p>
<p>이제는 API 통신이 필수인 시대여서 <code>js</code>로 진행하는 프로젝트시 도움을 많이 받고 있다.</p>
<h3 id="😵-문제가-무엇인가">😵 문제가 무엇인가..</h3>
<p>무튼 문제가 무엇이냐
<br></p>
<p>일단 <code>axios</code>의 기본 사용방법은 아래와 같고</p>
<pre><code class="language-js">axios({ method, url[, data , ... ]})
// 혹은
axios.post(url[, data, config, ...])</code></pre>
<p><code>axios</code>로 카카오와 통신하는 코드를 작성했고
그 코드는 아래와 같았는데</p>
<pre><code class="language-js">axios
  .post(url + &#39;엄청 긴 params&#39;, { header });</code></pre>
<p>아래 코드 형식으로 수정을 했더니</p>
<pre><code class="language-js">axios.post(url, { header, params });</code></pre>
<p>에러가 나는것이었다! 😵</p>
<br>

<p><code>header</code>와 <code>params</code>를 같이 넣는 것은 문제가 아니었고 분명 고치기 전에는 잘 동작을 하는 코드였다.</p>
<p><code>python</code>으로 kakao 로그인 구현했을 때도 같은 형식으로 넣어서 보냈기 때문에 <code>params</code>를 <code>data</code>로도 해보고 json형식으로도 해보고 삽질을 좀 하다가 검색을 해보니...</p>
<h3 id="👏-axios의-두번째-인자에--혹은-null을-넣어주면-해결이-된다">👏 axios의 두번째 인자에 {} 혹은 null을 넣어주면 해결이 된다!</h3>
<p>바로 해결이 됩니다. </p>
<pre><code class="language-js">// 최종 수정 코드
axios.post(url, {}, { headers: ~, params: {}});</code></pre>
<p>일단 </p>
<blockquote>
</blockquote>
<p><code>params</code>는 객체 혹은 <code>URLSearchParams</code> 객체여야 한다</p>
<p>는 것이 공식 문서에 나와있기 때문에 json으로 바꿨던 삽질은 잘못된 방식이었고</p>
<p><strong>왜!!!</strong> 
쿼리 파라미터가 포함된 url로 요청을 보낼 땐 
두번째 위치에 <code>header</code>가 있어도 제대로 동작하다가 
<code>params</code>를 나누면 빈 객체를 넣으라는 건지 모르겠다.</p>
<p>합리적 의심은</p>
<blockquote>
</blockquote>
<p>※ 지극히 주관적인 생각입니다.
※ 혹시 아시는 분이 계시다면 말씀해주세요 ㅠ.ㅠ</p>
<blockquote>
</blockquote>
<p>전자는 <code>url</code>에서 원하는 파라미터를 다 찾았기 때문에 OK
후자는 <code>url</code>에서 원하는 파라미터가 없어서 <code>config</code>(세번째 인자)로 갔는데 세 번째 인자가 없어서 Failed</p>
<p>이지만 내 생각이라서,,ㅋ ㅋ ㅋ</p>
<h3 id="아무튼-결론">아무튼 결론!</h3>
<p><code>axios.post</code>로 요청 보낼 때 잘 작성한것 같은데 오류가 난다면?
두 번째 인자에 빈 객체 혹은 <code>null</code>을 한 번 넣어서 보내보자!</p>
<p>그래도 안되면 다른 부분에서 문제가 있는걸로,,</p>
<p>이유는 다시 열심히 찾아보고 알게 된다면 수정하겠습니다😥</p>
<blockquote>
<p>출처:
같은 문제를 겪으신 선생님의 글 <a href="https://okky.kr/article/620647">https://okky.kr/article/620647</a>
Axios 공식문서 <a href="https://axios-http.com/kr/docs/post_example">https://axios-http.com/kr/docs/post_example</a></p>
</blockquote>
<p><em>늘 감사합니다,, 글을 써주시는 모든 분들</em> 😍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] console.log가 두번 실행된다고?]]></title>
            <link>https://velog.io/@hyes-y-tag/React-useEffect%EA%B0%80-%EB%91%90%EB%B2%88-%EC%8B%A4%ED%96%89%EB%90%9C%EB%8B%A4%EA%B3%A0</link>
            <guid>https://velog.io/@hyes-y-tag/React-useEffect%EA%B0%80-%EB%91%90%EB%B2%88-%EC%8B%A4%ED%96%89%EB%90%9C%EB%8B%A4%EA%B3%A0</guid>
            <pubDate>Fri, 22 Apr 2022 14:21:03 GMT</pubDate>
            <description><![CDATA[<p>프로젝트에 소셜 로그인 기능을 구현하기 위해 백엔드부터 프론트까지 열심히 구현중이시던 팀원분이 이슈를 가져오셨다.
<br></p>
<p>테스트의 로직은</p>
<blockquote>
</blockquote>
<p>프론트에서 카카오에 인가코드 요청
-&gt; 받아온 인가 코드를 백엔드에 전달
-&gt; 백엔드에서 카카오에 토큰 요청(redirect url, 인가코드 이용)
-&gt; 토큰을 프론트로 !</p>
<p>이런 흐름이었는데 프론트에서 백엔드에 인가 코드를 전달하는 과정에서 
한번만 실행 되어야 할 <code>useEffect</code>속 <code>console.log</code>가 콘솔창에 두번씩 찍히는 사실을 발견하게 되었다.</p>
<p>useEffect 내에 백엔드와 통신하는 코드가 있으니
당연히 오류가 나버림.</p>
<p><em><strong>useEffect</strong>야,, 정신 차려,,</em></p>
<h3 id="🧐-왜-useeffect가-두번-실행될까">🧐 왜 useEffect가 두번 실행될까?</h3>
<pre><code class="language-js">useEffect(() =&gt; {},[])</code></pre>
<p>위의 코드와 같이 <code>useEffect</code> <strong>2번째 인자에 빈 배열</strong>을 넣어주게 되면 컴포넌트가 처음 렌더링 될때만 실행된다.</p>
<p><del><em>그치만 두 번 실행됐어요..</em></del></p>
<p>여러 가지 시도를 해보다가 똑똑한 구글님에게 여쭤보니 답이 금방 나왔다!</p>
<blockquote>
</blockquote>
<p>프로젝트의  <code>src/index.js</code>에서
<code>&lt;React.StrictMode&gt;</code> 태그로 <code>&lt;app/&gt;</code>이 감싸져있으면
개발모드에서 (개발 단계시 오류를 잘 잡기위해) 두 번씩 렌더링됩니다.</p>
<blockquote>
</blockquote>
<p>출처: <a href="https://www.inflearn.com/questions/510296">https://www.inflearn.com/questions/510296</a></p>
<pre><code class="language-js">// src/index.js
import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import &#39;./index.css&#39;;
import App from &#39;./App&#39;;
import reportWebVitals from &#39;./reportWebVitals&#39;;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(
  &lt;React.StrictMode&gt;  // &lt;- 이거요!
    &lt;App /&gt;
  &lt;/React.StrictMode&gt;   // &lt;- 이겁니다!
);</code></pre>
<p>그렇습니다! 저 부분을 지우면 두 번씩 실행되는 문제가 해결이 됩니다!
👏👏👏
<del>useEffect 오해해서 미안,,</del></p>
<h3 id="🧐-strict-mode가-뭘까">🧐 Strict Mode가 뭘까?</h3>
<p><code>StrictMode</code>는 리액트에서 제공하는 검사 도구라고 생각하면 될 것 같다.
개발 모드일때만 디버그를 하며 
해당 태그로 감싸져 있는 부분은 자손까지 검사를 한다!
안전하지 않은 생명주기를 가진 컴포넌트라든지, 권장되지 않는 부분이 있다든지 배포 후 문제가 될만한 이슈들을 미리 잡는 모드라고 보면 되겠다.</p>
<p><code>create-react-app</code>으로 리액트 앱을 생성하면 기본적으로 생성되는 태그라고 한다!</p>
<p>자세한 설명은 <a href="https://ko.reactjs.org/docs/strict-mode.html">react strict mode의 공식문서</a> 를 참고 ✍</p>
<br>


<h3 id="결과는">결과는?</h3>
<p>로직엔 전 - 혀 문제가 없었다! 저 부분을 지우니 바로 동작해버림 ㅎㅎ</p>
<p>앞으로 <code>console.log()</code> 가 두 번씩 찍힌다면 바로 위 두 방법을 사용해보자!
안 되면 또 열심히 검색하지 뭐,, ㅎㅎ</p>
<br>

<blockquote>
</blockquote>
<p>출처: 
인프런 커뮤니티 <a href="https://www.inflearn.com/questions/510296">https://www.inflearn.com/questions/510296</a>
리액트 공식문서 <a href="https://ko.reactjs.org/docs/strict-mode.html">https://ko.reactjs.org/docs/strict-mode.html</a>
짤막글 -<a href="https://velog.io/@kysung95/%EC%A7%A4%EB%A7%89%EA%B8%80-react-strict-%EB%AA%A8%EB%93%9C%EB%9E%80">https://velog.io/@kysung95/%EC%A7%A4%EB%A7%89%EA%B8%80-react-strict-%EB%AA%A8%EB%93%9C%EB%9E%80</a></p>
<p><em>늘 감사합니다,, 글을 써주시는 모든 분들</em> 😍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Git] 다른 브랜치로 Commit 해야 한다면?]]></title>
            <link>https://velog.io/@hyes-y-tag/Git-%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-Commit-%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%A9%B4</link>
            <guid>https://velog.io/@hyes-y-tag/Git-%EB%8B%A4%EB%A5%B8-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%A1%9C-Commit-%ED%95%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%A9%B4</guid>
            <pubDate>Thu, 21 Apr 2022 16:52:39 GMT</pubDate>
            <description><![CDATA[<p>지금은 엘리스 2차 프로젝트 중...
기계처럼 코드를 치다 보니 다른 브랜치에 커밋 해야하는 파일을 무려 6개나 작성해버렸다,, !   </p>
<p>1차때는 변경 사항이 날라간지도 모른채 신나게 <code>checkout</code> 을 했지만 
사람은 발전을 해야한다.</p>
<h3 id="🧐-로컬-변경-사항을-건드리지-않고-브랜치-전환하는-방법">🧐 로컬 변경 사항을 건드리지 않고 브랜치 전환하는 방법</h3>
<pre><code class="language-bash">git stash
git checkout &lt;변경할 브랜치&gt;
git stash pop</code></pre>
<p><code>git stash</code>는 워킹 디렉터리에서 수정한 파일을 저장하는 명령어이고
아래와 같은 경우에 해당하는 파일을 저장할 수 있다.</p>
<blockquote>
</blockquote>
<p>1) Modified이면서 Tracked 상태인 파일</p>
<ul>
<li>Tracked 상태인 파일을 수정한 경우</li>
<li>Tracked: 과거에 이미 commit하여 스냅샷에 넣어진 관리 대상 상태의 파일<blockquote>
</blockquote>
2) Staging Area에 있는 파일(Staged 상태의 파일)</li>
<li>git add 명령을 실행한 경우
Staged 상태로 만들려면 git add 명령을 실행해야 한다.
git add는 파일을 새로 추적할 때도 사용하고 수정한 파일을 Staged 상태로 만들 때도 사용한다. <blockquote>
</blockquote>
출처: <a href="https://gmlwjd9405.github.io/2018/05/18/git-stash.html">https://gmlwjd9405.github.io/2018/05/18/git-stash.html</a></li>
</ul>
<p><code>git stash pop</code> 은 말 그대로 저장한 파일을 꺼내오는 명령어이다.
<code>stash</code>가 파일을 저장하는 stack의 역할을 한다고 생각하면 될 것 같다.</p>
<p><code>pop</code> 외에 <code>stash</code>에 남겨놓고 불러오기만 하고 싶다면 </p>
<pre><code class="language-bash">git stash apply</code></pre>
<p>위 명령어를 수행한 뒤 stash를 삭제하고 싶다면</p>
<pre><code class="language-bash">git stash drop</code></pre>
<p>를 사용하면 된다.</p>
<br>

<p>stash를 다루는 더 자세한 방법은 위 출처의 글을 보면 좋을 것 같다.
내 6개 파일의 은인,,
<br></p>
<h3 id="결과는">결과는?!</h3>
<p>완벽하게 수행되었다. 
git을 쓰다보면 &#39;아니,, 왜이렇게 어렵고 복잡해?!&#39; 하는 경우가 많은데
git은 잘못이 없다. 잘못은 내 짧은 지식,,, ㅠㅠ
앞으로 <code>checkout</code>으로 코드를 날리는 일은 없을 것이라 믿으며 🔥</p>
<br>
<br>

<blockquote>
<p>출처: 
🍬 <a href="https://gmlwjd9405.github.io/2018/05/18/git-stash.html">https://gmlwjd9405.github.io/2018/05/18/git-stash.html</a>
🍬 <a href="http://daplus.net/git-%EC%BB%A4%EB%B0%8B%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EB%A1%9C%EC%BB%AC-%EB%B3%80%EA%B2%BD-%EC%82%AC%ED%95%AD%EC%9D%84-%EB%8B%A4%EB%A5%B8-git-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90-%EC%96%B4/">http://daplus.net/git-%EC%BB%A4%EB%B0%8B%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EB%A1%9C%EC%BB%AC-%EB%B3%80%EA%B2%BD-%EC%82%AC%ED%95%AD%EC%9D%84-%EB%8B%A4%EB%A5%B8-git-%EB%B8%8C%EB%9E%9C%EC%B9%98%EC%97%90-%EC%96%B4/</a></p>
</blockquote>
<p><em>늘 감사합니다,, 글을 써주시는 모든 분들</em> 😍</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Elice AI_4기] 4주차 내용 정리]]></title>
            <link>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-4%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-4%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 22 Feb 2022 15:59:16 GMT</pubDate>
            <description><![CDATA[<h1 id="4주차-학습-내용-정리">4주차 학습 내용 정리</h1>
<p><span style="color: gray; font-style: italic;">2022.02.08 - 2022.02.12</span>
<span style="color: gray; font-style: italic;">몰랐던 것 위주로 정리</span></p>
<pre><code> - javascript(심화)
     - 비동기
    - 이벤트 루프
    - Promise
    - async/ await
    - http, rest API
    - fetch API</code></pre><h2 id="🚩-javscript---">🚩 Javscript . . .</h2>
<h3 id="1-자바스크립트-제어-흐름">1. 자바스크립트 제어 흐름</h3>
<ul>
<li><p>Javascript는 다른 멀티스레드 프로그래밍 언어와 다른 방식으로 <code>비동기</code> 동작을 처리함</p>
</li>
<li><p>Javascript 엔진은 하나의 메인 스레드로 구성 (= 싱글 스레드)</p>
<blockquote>
<p>관련 내용 : <a href="https://chanyeong.com/blog/post/44">자바스크립트는 왜 싱글 쓰레드일까?</a></p>
</blockquote>
</li>
<li><p><code>조건문</code>, <code>반복문</code>, <code>함수 호출</code> 등은 동기적으로 실행</p>
</li>
<li><p><code>Promise</code>, <code>Callback 호출 함수</code> 등은 비동기적으로 실행</p>
</li>
</ul>
<h3 id="🧐-동기-vs-비동기">🧐 동기 vs 비동기</h3>
<ul>
<li><p><strong>동기적으로 실행한다?</strong> → 한 동작이 수행을 완료할 때까지 기다렸다가 끝나면 다음 동작을 수행하는 실행 방식
코드와 실제 제어 흐름이 동일</p>
</li>
<li><p><strong>비동기적으로 실행한다?</strong> → 동작이 끝나기 전에 다음 동작을 수행하는 실행 방식
코드와 실제 제어 흐름이 상이
비동기 작업을 기다리는 동안 메인 스레드는 다른 작업 처리</p>
</li>
</ul>
<h3 id="2-이벤트-루프">2. 이벤트 루프</h3>
<ul>
<li>Javascript 엔진은 비동기 처리를 제공하지 않음!!</li>
<li>But!! 비동기 처리 역할을 하는 <strong>함수</strong> 존재 → <code>비동기 API</code></li>
<li>종류 : <code>setTimeout</code>, <code>XMLHttpRequest</code>, <code>fetch</code> 등의 Web API / 파일 처리, 암호화 API (node)</li>
</ul>
<pre><code class="language-javascript">setTimeout(()=&gt;{
    console.log(&#39;1초 뒤 실행&#39;);
}, 1000)

console.log(&#39;그다음 실행?&#39;);

// 그다음 실행?
// 1초 뒤 실행</code></pre>
<ul>
<li><p>비동기 처리 모듈은 Javascript 엔진 외부에 존재</p>
</li>
<li><p><code>이벤트 루프</code>, <code>태스크 큐(Task queue)</code> , <code>잡 큐(Job queue)</code> 등으로 구성</p>
</li>
<li><p>이벤트 루프 : 브라우저 혹은 node와 같이 자바스크립트가 구동되는 환경과 자바스크립트 사이에 상호 연동 하기 위한 장치
(비동기 동작을 처리하기 위한 장치)
<a href="https://meetup.toast.com/posts/89">javascript and event-loop</a></p>
</li>
<li><p>태스크 큐(Task Queue) : 콜백 함수 혹은 비동기 함수들이 들어가는 곳, 콜스택이 비워지는 경우 <code>FIFO</code> 방식으로 태스크 큐의 자원들이 콜스택으로 들어감!</p>
</li>
<li><p>잡 큐(Job Queue) : 주로 Promise가 들어가며 태스크 큐보다 우선권을 가지고 있음
태스크 큐는 콜스택과 관련이 있다면 잡 큐는 execution context 와 관련이 있음! 
(확인 필요) execution context stack이 다 비워지면 잡 큐의 자원을 수행</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Elice AI_4기] 3주차 내용 정리]]></title>
            <link>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-3%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-3%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 04 Feb 2022 03:49:06 GMT</pubDate>
            <description><![CDATA[<h1 id="3주차-학습-내용-정리">3주차 학습 내용 정리</h1>
<p><span style="color: gray; font-style: italic;">2022.01.25 - 2022.01.29</span>
<span style="color: gray; font-style: italic;">몰랐던 것 위주로 정리</span></p>
<pre><code> - javascript(기초)
 - javascript(심화)</code></pre><h2 id="🚩-javascript기초">🚩 Javascript(기초)</h2>
<h3 id="1-dom-document-object-model">1. DOM (Document Object Model)</h3>
<ul>
<li><code>문서 객체 모델</code>이라고도 하며 객체 지향 모델로써 구조화된 문서를 표현하는 형식</li>
<li><code>HTML</code> , <code>XML</code> 의 <strong>프로그래밍 인터페이스</strong></li>
<li><code>DOM</code>을 이용하여 프로그래밍 언어가 문서의 스타일 등을 변경할 수 있음</li>
<li>프로그래밍 언어와 독립적</li>
<li><strong>트리</strong> 구조로 되어있음</li>
</ul>
<h4 id="🥕-종류">🥕 종류</h4>
<ol>
<li>Core DOM : 모든 문서 타입을 위한 DOM</li>
<li>HTML DOM : HTML 문서를 위한 DOM</li>
<li>XML DOM : XML 문서를 위한 DOM</li>
</ol>
<h4 id="🥕-document-객체">🥕 Document 객체</h4>
<ul>
<li>Document = 웹 페이지</li>
<li>웹 페이지 내 <code>HTML</code> 요소에 접근할 때는 반드시 <em>Document</em> 객체를 이용</li>
</ul>
<h4 id="🥕-document-메서드">🥕 Document 메서드</h4>
<ul>
<li><p><code>HTML</code>요소 선택/생성, 이벤트 핸들러 추가, 객체 선택시 사용</p>
</li>
<li><p><code>HTML</code>요소 선택
  -<code>document.getElementById()</code> : 해당 id의 요소를 선택
  -<code>document.getElementsByClassName()</code> : 해당 클래스의 요소들을 선택
  -<code>document.getElementsByName()</code> : 해당 name값을 가지는 요소들을 선택
  -<code>document.querySelector()</code> : 해당 선택자를 가지는 요소를 하나 선택
  -<code>document.querySelectorAll()</code> : 해당 선택자를 가지는 요소를 전체 선택</p>
</li>
<li><p><code>HTML</code> 요소 생성
  -<code>document.createElement()</code> : 지정된 html 요소 생성
  -<code>document.write()</code> : html 출력 스트림을 통해 텍스트 출력
  -<code>document.선택 메서드.innerHTML</code> : 선택 메서드로 얻어온 태그 밑에 추가(createElement보다 간편함)</p>
</li>
<li><p>이벤트 핸들러 추가
  -<code>요소.onclick = function(){}</code>
  -<code>요소.addEventListener(이벤트속성, 실행함수)</code></p>
<br/>

</li>
</ul>
<h3 id="2-node-객체">2. Node 객체</h3>
<ul>
<li><code>HTML DOM</code>에서 정보를 저장하는 계층적 단위</li>
<li>Node Tree : Node들의 집합, Node간 관계를 표현</li>
</ul>
<h4 id="🥕-종류-1">🥕 종류</h4>
<ul>
<li>문서 노드(document node) : <code>HTML</code> 문서 전체를 나타내는 노드</li>
<li>요소 노드(element node) : 속성 노드를 가질 수 있는 유일한 노드(html의 모든 요소)</li>
<li>주석 노드(comment node) : 문서의 주석</li>
<li>속성 노드(attribute node) : 요소 노드에 관한 정보를 가진 노드(모든 html 요소의 속성, 자식 노드에는 포함되지 않음)</li>
<li>텍스트 노드(text node) : 문서의 모든 텍스트</li>
</ul>
<h4 id="🥕-노드-정보">🥕 노드 정보</h4>
<ul>
<li><code>요소.nodeName</code> 과 같이 사용 가능</li>
<li><code>nodeName</code> : 노드 이름 반환</li>
<li><code>nodeValue</code> : 노드 값 반환</li>
<li><code>nodeType</code> : 숫자값 반환, 요소 노드(1), 속성 노드(2), 텍스트 노드(3), 주석 노드(8), 문서 노드(9)</li>
</ul>
<br/>

<h3 id="3-이벤트">3. 이벤트</h3>
<ul>
<li>웹 브라우저가 알려주는 html 요소에 대한 사건의 발생</li>
<li>이벤트 타입 : 발생한 이벤트의 종류</li>
<li>이벤트 핸들러 : 이벤트가 발생했을 때 그 처리를 담당하는 함수</li>
</ul>
<br/>

<h2 id="🚩-javascript심화">🚩 Javascript(심화)</h2>
<blockquote>
</blockquote>
<p>✔ 어려움 주의</p>
<h3 id="0-자바스크립트-실행-과정">0. 자바스크립트 실행 과정</h3>
<ul>
<li><p><code>javascript</code> → 인터프리터 언어(but 컴파일 언어의 특징도 가지고 있음)
  -인터프리터 언어 : 코드를 한 줄씩 읽고 실행
  -컴파일 언어 : 전체 코드를 읽고 실행</p>
</li>
<li><p><code>javascript</code> - 싱글 스레드 환경에서 비동기 동작 처리</p>
</li>
<li><p>실행 시 코드가 없어도 <code>this</code>/<code>variable object</code>/<code>scope chain</code> 을 초기화
  -<code>scope</code> : 코드가 현재 실행되는 환경, 맥락을 의미
  -<code>this</code> : 레퍼런스 변수( window(global_scope 환경에서), object(객체에 속한 메서드 실행시) 를 의미)
  -<code>this</code>/<code>variable object</code>/<code>scope chain</code> 세 개를 통틀어 <strong>실행 환경(execution context)</strong> 라고 함</p>
</li>
<li><p>콜스택 : 실행 환경이 쌓이면서 생기는 부분</p>
</li>
</ul>
<h3 id="1-실행-컨텍스트execution-context">1. 실행 컨텍스트(Execution Context)</h3>
<ul>
<li>자바스크립트 언어 스펙(명세)에 명시되어 있는 개념</li>
<li>자바스크립트 코드가 실행되는 환경</li>
<li>코드에서 참조하는 변수, 객체(함수 포함), <code>this</code> 등에 대한 레퍼런스가 존재</li>
<li>전역에서 시작하며 함수가 호출될 때 콜스택에 쌓이게 됨</li>
</ul>
<h4 id="🥕-종류-2">🥕 종류</h4>
<ul>
<li>전역 실행 컨텍스트(Global Execution Context) → 자바스크립트 실행 시 만들어짐</li>
<li>함수 실행 컨텍스트(Function Execution Context) → 함수 실행 시 만들어짐</li>
</ul>
<h3 id="2-this">2. this</h3>
<h4 id="🥕-dynamic-binding동적-바인딩">🥕 Dynamic Binding(동적 바인딩)</h4>
<ul>
<li><p><code>this</code>가 함수의 호출 환경에 따라 동적으로 세팅되는 것</p>
</li>
<li><p>함수 호출 환경
  1.함수 호출 - 함수 직접 호출
  2.메서드 호출 - 객체의 메서드 호출
  3.생성자 호출 - 생성자 함수를 호출
  4.간접 호출 - <code>call</code>, <code>apply</code>등으로 함수를 직접 호출
  5.그 외 - 콜백함수(특정 동작 이후 불려지는 함수/ 다른 함수의 인자로 보내지는 함수) 호출</p>
</li>
<li><p><code>bind</code> / <code>apply</code> / <code>call</code> 등으로 <code>this</code>가 가리키는 것을 조작 가능</p>
</li>
</ul>
<p>✅ <strong>화살표 함수</strong>를 사용하는 경우 <code>this</code>는 <strong>함수가 생성된 환경</strong>을 가리키도록 <strong>고정</strong>
(<code>this</code> = 호출된 함수를 둘러싼 실행 컨텍스트)
✅ <strong>일반 함수</strong>를 사용하는 경우 <code>this</code>는 <strong>함수가 호출된 환경</strong>을 가리키며 동적으로 변경 가능
(<code>this</code> = 새롭게 생성된 실행 컨텍스트)</p>
<h3 id="3-closure-함수">3. Closure 함수</h3>
<ul>
<li>일급 객체 : 변수와 같이 대상을 다룰 수 있는 객체
✔ <code>javascript</code>에서는 함수도 일급 객체</li>
</ul>
<p>✅ 함수의 일급 객체 성질</p>
<ul>
<li>함수를 다른 함수의 인자로 넘기면, 다른 함수 내부에서 그 함수를 호출 가능</li>
<li>함수 안에 함수를 선언하면 리턴을 통해 외부에서도 사용 가능</li>
<li>함수의 실행이 끝나도 내부 변수 유지 가능</li>
</ul>
<h4 id="🥕-closure-함수">🥕 closure 함수</h4>
<ul>
<li>함수의 일급 객체 성질을 이용</li>
<li>함수가 생성될 때 함수 내부에서 사용되는 변수들이 외부에 존재하는 경우 그 변수들은 함수의 스코프에 저장</li>
<li>함수와 함수가 사용하는 변수들을 저장한 공간을 <strong>클로저</strong>라고 함</li>
<li>팩토리함수 :  함수를 생성해서 리턴하는 함수</li>
<li>내부에서 선언한 변수는 계속 살아있음</li>
</ul>
<h3 id="4-es6-rest-spread-operator">4. ES6 Rest, Spread Operator</h3>
<h4 id="🥕-rest-operator">🥕 Rest Operator</h4>
<ul>
<li>함수의 인자, 배열, 객체 중 나머지 값을 묶어서 사용</li>
<li>항상 마지막에 위치</li>
<li>객체의 rest operator 는 객체로 저장</li>
<li>배열의 rest operator 는 배열로 저장</li>
</ul>
<pre><code class="language-javascript">// Rest Operator 예제

function Rest(arg, ...rest){
    console.log(&quot;arg:&quot;, arg);
    console.log(&quot;rest:&quot;, rest);
  }

Rest(1, 2, 3, 4);
// arg: 1
// rest: (3) [2, 3, 4]

function sumArray(sum, arr) {
    if (arr.length === 0) return sum;
    const [head, ...tail] = arr;
    return sumArray(sum + head, tail);
  }

sumArray(0, [1, 2, 3, 4, 5]);
// 15</code></pre>
<h4 id="🥕-spread-operator">🥕 Spread Operator</h4>
<ul>
<li>묶인 배열 혹은 객체를 펼침</li>
<li>✨등장 순서✨에 따라 객체의 필드가 덮어씌워질 수 있음</li>
</ul>
<pre><code class="language-javascript">// Spread Operator 예제

function Spread(x, y, z){
    console.log(x);
      console.log(y);
      console.log(z);
}

Spread(...[1, 2, 3]);
// 1
// 2
// 3

let o = {
  name: &quot;Daniel&quot;,
  age: 23,
  address: &quot;Street&quot;,
  job: &quot;Software Engineer&quot;,
}
let o2 = { ...o, name: &quot;Tom&quot;, age: 24 }
let o3 = { name: &quot;Tom&quot;, age: 24, ...o }
o2.name // Tom
o2.job // Software Engineer
o3.name // Daniel</code></pre>
<ul>
<li>iterable 성질을 가진 객체는 spread operator로 합칠 수 있음</li>
<li>iterable 성질이 없는 경우(ex.일반 객체) 에러 발생</li>
<li>spread operator 로 객체를 복사할 때 객체나 배열 필드의 경우 reference만 복사됨
( deep copy를 하기 위해선 별도의 작업 필요 )</li>
</ul>
<br/>

<h3 id="5-자바스크립트의-변수-정의-과정">5. 자바스크립트의 변수 정의 과정</h3>
<h4 id="🥕-자바스크립트-엔진">🥕 자바스크립트 엔진</h4>
<ul>
<li>자바스크립트 코드를 읽어 실행하는 프로그램</li>
<li>코드는 엔진을 통해 파싱되고 실행된다</li>
<li><code>chrome</code> 브라우저의 경우 <code>v8</code>엔진(made by google) 사용<br/></li>
<li><code>node.js</code> : 브라우저 외의 환경에서 자바스크립트 코드를 실행하도록 하는 프로그램</li>
<li><code>node.js</code> 는 여러 프로그램으로 구성되며 <code>v8</code>사용</li>
<li>같은 코드를 실행해도 브라우저와 <code>node.js</code>의 실행 결과가 다를 수 있음<br/>

</li>
</ul>
<h4 id="🥕-자바스크립트-코드-실행">🥕 자바스크립트 코드 실행</h4>
<ul>
<li>코드 실행 전 실행 컨텍스트(두단계) 생성</li>
<li>생성 단계 → 변수 선언 읽음</li>
<li>실행 단계 → 변수 값 할당</li>
</ul>
<h4 id="🥕-렉시컬-환경-lexical-environment">🥕 렉시컬 환경 (Lexical Environment)</h4>
<ul>
<li><p>함수의 렉시컬 환경 → 함수가 사용하는 변수들을 둘러싼 환경</p>
</li>
<li><p>특정 변수의 값은 함수의 렉시컬 환경 안에서 찾을 수 있음</p>
</li>
<li><p>실행 컨텍스트 안에 정의된 <code>variable object</code> 로 이해할 수 있음</p>
<br/>
</li>
<li><p>생성단계 → 함수 선언문 / 표현식/ 변수 등을 실행 컨텍스트에 저장</p>
<ul>
<li>변수의 경우 실행 컨텍스트의 렉시컬 환경 구성</li>
<li>함수 선언문 외에 변수는 값이 저장되지 않음</li>
</ul>
</li>
<li><p>실행단계 → 변수에 값을 할당하는 구문을 만나면 실행 컨텍스트에 값을 저장 → 한 줄씩 읽어나가며 실행</p>
<br/>

</li>
</ul>
<h3 id="6-hoisting">6. Hoisting</h3>
<ul>
<li>인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것</li>
<li>변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는 것</li>
<li>선언과 초기화를 <strong>함께</strong> 수행하는 경우, <u>선언 코드까지 실행</u>해야 변수가 초기화된 상태가 됨</li>
</ul>
<br/>

<h4 id="🥕-변수-선언-타입별-hoisting">🥕 변수 선언 타입별 hoisting</h4>
<p>✔ 생성 단계에서</p>
<p><code>var</code> → <code>undefined</code> 로 초기화
<code>let</code>, <code>const</code> → 초기화되지 않음 → <code>hoisting</code> 발생하지 않음</p>
<p>✔ 선언 타입별 특징
<code>var</code> , <code>let</code> → 변수에 재할당 가능
<code>const</code> → 재할당 불가능</p>
<p><code>var</code> → 함수 스코프
<code>let</code>, <code>const</code> → 블록 스코프</p>
<h4 id="🥕-hoisting-참고">🥕 <a href="https://developer.mozilla.org/ko/docs/Glossary/Hoisting">hoisting 참고</a></h4>
<br/>

<h3 id="7-자바스크립트-내장-객체">7. 자바스크립트 내장 객체</h3>
<h4 id="🥕-globalthis">🥕 globalThis</h4>
<ul>
<li>전역 객체를 지칭하는 변수</li>
<li>브라우저: <code>window</code> / node : <code>global</code></li>
<li>환경별 차이를 통일하여 하나의 변수로 서로 다른 전역 객체를 가리키게함</li>
</ul>
<h4 id="🥕-window">🥕 window</h4>
<ul>
<li>DOM document를 포함하는 창을 나타내는 객체</li>
<li>전역 스코프에서 선언된 변수는 모두 window의 property</li>
</ul>
<h4 id="🥕-document">🥕 document</h4>
<ul>
<li>브라우저에 로드된 웹페이지</li>
<li>문서의 title, URL 등의 정보를 얻음</li>
<li>element 생성, 검색 등의 기능 제공</li>
<li>동적으로 원소 생성</li>
</ul>
<h4 id="🥕-number">🥕 Number</h4>
<ul>
<li>number 원시타입(primitive value)을 감싸는 객체</li>
<li>유의미한 상수값, 숫자를 변환하는 메서드 등을 제공한다</li>
<li><code>NaN</code> : Not a Number</li>
<li><code>isNaN()</code> : 전역함수, 입력값을 숫자로 변환했을 때 NaN 이 되는지 검사</li>
</ul>
<h4 id="🥕-math">🥕 Math</h4>
<ul>
<li>기본적인 수학 연산 메서드, 상수 다루는 객체</li>
<li><code>BigInt</code> 타입과 호환 x, <code>Number</code> 타입만을 인자로 다룬다</li>
</ul>
<h4 id="🥕-date">🥕 Date</h4>
<ul>
<li>특정 시점의 날짜를 표시하기 위한 객체</li>
<li>날짜 관련 작업을 위한 여러 메서드 포함</li>
<li><code>Date.getDay()</code> → 요일을 0(일) - 6(토) 로 구한다 (연월일시분초밀리초 다 가능)</li>
<li><code>setDate()</code> → 시간 설정</li>
<li><code>toDateString()</code> → 특정 포맷의 문자열 반환</li>
<li><code>getTime()</code> → 1970.1.1 시점부터 흐른 시간을 밀리초 단위로 반환</li>
<li><code>Date.now()</code> → 현재 시간의 밀리초(실시간)</li>
<li><code>a = new Date();</code> → 생성 시점의 시간 정보</li>
<li>Date 객체로 타임존 정보 획득 가능</li>
<li>문자열로 된 시간을 Date 객체로 변환하면, Date 객체가 생성</li>
</ul>
<h4 id="🥕-string">🥕 String</h4>
<ul>
<li>문자열 원시타입의 래퍼 객체</li>
<li>여러 메서드 포함</li>
<li><code>includes()</code> → 문자열 검색에 성공시 true, 실패시 false 반환</li>
<li><code>toUpperCase()</code> → 대문자 변환</li>
<li><code>replace()</code> → 문자열 검색해서 타겟 문자열로 변환</li>
<li><code>split()</code> → 특정 문자열 기준으로 분리, 없을 시 글자별로 분리</li>
<li><code>indexOf()</code> → 특정 문자열을 검색하여 인덱스 리턴, 없을 시 -1</li>
</ul>
<h4 id="🥕-json">🥕 json</h4>
<ul>
<li>json 객체와 관련된 메서드를 담은 객체</li>
<li><code>JSON.stringify()</code> → 객체를 json문자열로</li>
<li><code>JSON.parse()</code> → json문자열을 객체로</li>
</ul>
<hr>

<p>✅ 정리</p>
<p>✏ <code>closure</code>, <code>Lexical environment</code> 등 <code>javascript</code>의 전반적인 실행 환경 개념에 대해 이해를 완벽하게 하지 못함
✏ <code>bind</code>의 개념도 다시 학습 필요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Elice AI_4기] 2주차 내용 정리]]></title>
            <link>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-2%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-2%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 03 Feb 2022 08:35:38 GMT</pubDate>
            <description><![CDATA[<h1 id="2주차-학습-내용-정리">2주차 학습 내용 정리</h1>
<p><span style="color: gray; font-style: italic;">2022.01.18 - 2022.01.22</span>
<span style="color: gray; font-style: italic;">몰랐던 것 위주로 정리</span></p>
<pre><code> javascript(기초)</code></pre><h2 id="🚩-javascript">🚩 Javascript</h2>
<ul>
<li>이미지 슬라이드 효과, 팝업 효과 등의 기능을 포함한 </li>
<li><em>동적인 웹사이트*</em> 제작시 사용되는 프로그래밍 언어</li>
</ul>
<h3 id="1-변수-선언">1. 변수 선언</h3>
<p>🥕 <code>var</code> <code>let</code> <code>const</code> 를 사용하여 변수 선언 가능</p>
<ul>
<li><code>var</code> : 이미 선언된 변수라도 재선언 가능</li>
<li><code>let</code> : 이미 선언되어 있다면 재선언 불가, 초기화는 가능</li>
<li><code>const</code> : 재선언, 재할당 불가능(상수(변하지 않는 값)에 사용)<pre><code>ex&gt;
var num;   // 변수 선언
</code></pre></li>
</ul>
<p>// 변수 선언 및 초기화
var num = 1;<br>let cnt = 1;
const pi = 3.14;</p>
<pre><code>&lt;br/&gt;

### 2. 데이터 타입
- `String` : 문자열
- `Number` : 숫자(정수(음수 포함), 실수)
- `Function` : 함수
- `Array` : 배열
- `Object` : 객체
- `Boolean` : 논리값(true/false)
- `undefined` : 정의되지 않음 (변수가 선언되고 초기화는 이루어지지 않은 경우)
- `null` : 널(의도적으로 빈 데이터로 초기화한 경우)

✔ 문자열의 경우 큰따옴표 혹은 작은 따옴표가 데이터에 포함이라면 앞에 `\` 를 붙임
✔ 주석은 한 줄일 경우 `//` 여러 줄일 경우 `/* */` 사용

&lt;br/&gt;

🥕 함수 생성 방법
- 변수 초기화로 함수 지정
- 함수 키워드로 직접 생성

```javascript
var myfunc = function(){
  return &quot;my func!&quot;;
}

myfunc();  // my func!</code></pre><pre><code class="language-javascript">function myfunc(){
  return &quot;my func!&quot;;
}

myfunc();  // my func!</code></pre>
<p>🥕 객체(Object)</p>
<ul>
<li>프로퍼티와 메서드, 데이터로 이루어짐</li>
<li>여러 종류의 데이터 삽입 가능</li>
</ul>
<pre><code class="language-javascript">var student = {
  name: &quot;sun&quot;,
  age: &quot;20&quot;,
  family: [&#39;moon&#39;, &#39;star&#39;, &#39;earth&#39;],
  message: function(num1, num2){ return `${num1} + ${num2} = ${num1 + num2} 입니다` }
} 
// name, age, family 는 프로퍼티, message는 메서드
// 문자열 안에 변수 넣을 경우 백틱으로 감싼 문자열 안에 ${변수} 형식으로 작성

console.log(student.name) // sun
console.log(student[&#39;family&#39;]) // 배열 리턴
console.log(student.message(1, 2)) // 1 + 2 = 3 입니다</code></pre>
<br/>

<h3 id="3-자바스크립트의-데이터-타입별-프로퍼티-메서드">3. 자바스크립트의 데이터 타입별 프로퍼티/ 메서드</h3>
<p>🥕 문자열 프로퍼티 / 메서드</p>
<ul>
<li><code>String.length</code> : 문자열 길이 반환</li>
<li><code>String.charAt(index)</code> : 문자열의 해당 인덱스의 글자 반환</li>
<li><code>String.split()</code> : 괄호 안에 주어진 값을 기준으로 분리 후 배열로 반환(아무것도 없는 경우 글자별로 나눔)</li>
<li><code>String.match(정규표현식)</code> : 정규 표현식에 해당하는 부분을 배열로 리턴</li>
</ul>
<blockquote>
</blockquote>
<p>✔ <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions">정규 표현식</a>
✔ <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">더 많은 문자열 메서드 및 프로퍼티</a></p>
<p>🥕 배열 프로퍼티 / 메서드</p>
<ul>
<li><code>Array.length</code> : 배열 길이 반환</li>
<li><code>Array.push</code> : 배열 맨 뒤에 요소 삽입</li>
<li><code>Array.pop</code> : 배열 맨 뒤 요소 제거</li>
<li><code>Array.unshift</code> : 배열 맨 앞에 요소 삽입</li>
<li><code>Array.shift</code> : 배열 맨 앞에 요소 제거</li>
<li><code>Array.splice(index, cnt)</code> : 해당 index로부터 cnt개수만큼을 제거</li>
<li><code>Array.join()</code> : 배열을 콤마(기본값)를 기준으로 이어붙임, 공백으로 잇고 싶은 경우 괄호 안에 &#39; &#39;를 입력</li>
<li><code>Array.sort()</code> : 배열을 정렬(기본값 → 유니코드 값으로 정렬) 
숫자의 오름차순, 내림차순 등으로 배열하기 위해선 매개변수로 함수를 넘겨주어야 함<pre><code class="language-javascript">function compareNumbers(a, b) {
  return a - b;
}
// 오름차순 정렬, 내림차순으로 하고 싶을 때는 return b - a;
</code></pre>
</li>
</ul>
<p>arr.sort(compareNumbers)</p>
<pre><code>&gt;
✔ 정렬 방식 참고 블로그 https://hianna.tistory.com/409
✔ [더 많은 배열 메서드 및 프로퍼티](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)

🥕 그 외
- `Math.abs(num)` : num의 절댓값 반환
- `Math.ceil(num)` : num의 올림값 반환
- `Math.floor(num)` : num의 내림값 반환
- `Math.random()` : 0에서 1 사이에 랜덤값 반환
- `parseInt(sth)` : sth를 정수로 변경(값이 숫자인 문자열인 경우)
- `parseFloat(sth)` : sth를 실수로 변경(값이 숫자인 문자열인 경우)

&lt;br/&gt;

✔ 콘솔로 입력 받을 경우
```javascript
//콘솔을 통해 값을 입력 받기 위해서는 readline 모듈 사용
const readline = require(&quot;readline&quot;);

//readline 모듈을 이용해 입출력을 위한 인터페이스 객체 생성
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

//rl 변수는 아래와 같이 이용
  rl.on(&quot;line&quot;, (line) =&gt; { 
      // 한 줄씩 입력받은 후 실행할 코드
     // 입력된 값은 line에 저장된다.
      rl.close(); // close가 없으면 입력을 무한히 받는다.
  });
  rl.on(&#39;close&#39;, () =&gt; {
    // 입력이 끝난 후 실행할 코드
  })</code></pre><br/>

<h3 id="4-연산자">4. 연산자</h3>
<h4 id="1-산술-연산자">1. 산술 연산자</h4>
<ul>
<li><code>+, -, *, /, %(나머지)</code></li>
<li>문자 &lt;연산자&gt; 숫자(or 문자) 형태일 때 <code>+</code>를 제외한 다른 연산은 문자가 숫자로 바뀜<pre><code class="language-javascript">// ex&gt;
let a = &quot;5&quot;;
let b = 3;
</code></pre>
</li>
</ul>
<p>console.log(a+b); // 53
console.log(a-b); // 2
console.log(a*b); // 15
console.log(a/b); // 1.66666..
console.log(a%b); // 2</p>
<pre><code>
#### 2. 증감 연산자(++, --)
- `num++`, `num--`, `++num`, `--num` 이 있음
- 기호가 앞에 붙은 경우 먼저 1씩 더한 후 코드 실행 
- 뒤에 붙은 경우 코드 먼저 실행 후 1씩 더함
```javascript
// ex&gt;
let num = 3;

console.log(++num); // 4
console.log(num++); // 4(위에서 더했음) =&gt; num = 5
console.log(++num); // 6</code></pre><h4 id="3-비교-연산자">3. 비교 연산자</h4>
<ul>
<li><code>==, ===, !=, !==, &gt;, &gt;=, &lt;, &lt;=</code></li>
<li><code>==</code> : 값이 같다(같지 않다 <code>!=</code>)</li>
<li><code>===</code> : 데이터 타입과 값이 같다(같지 않다 <code>!==</code>)</li>
<li><code>&gt;, &gt;=, &lt;, &lt;=</code> </li>
</ul>
<p>✔ 두 값을 비교할 때 <code>==</code>은 데이터 타입을 동일하게 만든 뒤 비교,
 <code>===</code> 은 데이터 타입까지 동일한지 비교</p>
<p><img src="https://images.velog.io/images/hyes-y-tag/post/8be43d2f-9032-46eb-867e-9b6965c137e1/%EC%A1%B0%EA%B1%B4%EC%97%B0%EC%82%B0%EC%9E%90%EC%A7%A4.png" alt=""></p>
<h4 id="4-논리-연산자">4. 논리 연산자</h4>
<ul>
<li><code>&amp;&amp;(and), ||(or)</code></li>
</ul>
<br/>

<h3 id="5-조건문--반복문">5. 조건문 / 반복문</h3>
<h4 id="1-조건문">1. 조건문</h4>
<p>🥕 if문 / switch문</p>
<pre><code class="language-javascript">/* if (조건) { 수행할 명령 } 
else if (조건) { 수행할 명령 } 
else { 수행할 명령 } */
const num = 10;

if (num &gt; 10) { console.log(&quot;10보다 큽니다&quot;);}
else if ( num == 10) { console.log(&quot;10입니다&quot;);}
else { console.log(&quot;10보다 작습니다&quot;);}
// 10입니다

/* switch(비교대상) { 
    case (value) : 
        비교 대상이 value일때 수행할 명령 
        break;(안하면 멈추지 않고 다음 케이스로 또 넘어감)
    ...
    default :
        위에서 매치되는 케이스가 없는 경우 수행할 명령
  } */

switch(num){
  case 10:
    console.log(&quot;10입니다&quot;);
    break;
  case 0:
    console.log(&quot;0입니다&quot;);
    break;
  default:
    console.log(&quot;10도 아니고 0도 아닙니다&quot;);
}
// 10입니다</code></pre>
<h4 id="2-반복문">2. 반복문</h4>
<p>🥕 for문 / while문 / do-while문</p>
<pre><code class="language-javascript">// for (초기값; 조건 ; 증감 표시) { 수행할 명령 }
for (let i = 0; i &lt; 10; i++) {
  if (i % 3 == 0) console.log(i);
} // 3, 6, 9


// while (조건) { 수행할 명령 }
var i = 0
while (i &lt; 5) {
  console.log(i);
  i++;
} // 0, 1, 2, 3, 4


// do { 수행할 명령 } while(조건)
var num = 5;
do { console.log(num)} while ( num &lt; 5 ); 
// 5
</code></pre>
<p>✅ 연산이 python과 살짝 다른 점이 있어 헷갈렸음 
    → javascript는 형변환을 통해 두 비교 대상의 타입을 맞춘 뒤에 연산 수행
✅ 변수 선언할 때 <code>var</code>, <code>let</code>, <code>const</code> 를 상황에 맞게 사용해야 할듯</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Elice AI_4기] 1주차 내용 정리]]></title>
            <link>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-1%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hyes-y-tag/Elice-AI4%EA%B8%B0-1%EC%A3%BC%EC%B0%A8-%EB%82%B4%EC%9A%A9-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 16 Jan 2022 15:28:45 GMT</pubDate>
            <description><![CDATA[<h1 id="1주차-학습-내용-정리">1주차 학습 내용 정리</h1>
<p><span style="color: gray; font-style: italic;">2022.01.11 - 2022.01.15</span>
<span style="color: gray; font-style: italic;">몰랐던 것 위주로 정리</span></p>
<pre><code>- 1. html
- 2. css
- 3. git</code></pre><h2 id="🚩-html">🚩 HTML</h2>
<h3 id="1-웹사이트-제작시-고려-사항">1. 웹사이트 제작시 고려 사항</h3>
<ol>
<li><code>웹 표준</code> : 웹에서 요구하는 공식 표준이나 기술 규격을 만족하는지 여부</li>
<li><code>웹 접근성</code> : 장애 여부와 상관 없이 모두가 웹사이트를 이용할 수 있는지 여부</li>
<li><code>크로스 브라우징</code> : 모든 브라우저와 기기에서 웹사이트가 제대로 작동하는지 여부</li>
</ol>
<br/>

<h3 id="2-html-태그-참고">2. HTML 태그 참고</h3>
<p>✅ html 학습 사이트 → <a href="https://w3schools.com/">https://w3schools.com/</a> </p>
<p>✅ <code>img</code>태그의 속성중 <code>alt</code>는 꼭 작성! (웹사이트 reader에 필요)</p>
<br/>

<h2 id="🚩-css">🚩 CSS</h2>
<h3 id="1-모션-효과">1. 모션 효과</h3>
<h4 id="0-prefix">0. prefix</h4>
<p>🥕 다른 버전의 브라우저에서 실행할 때 사용(최신 버전에 맞추는 경우 필요 없음)
    - <code>-webkit-</code> : 크롬, 사파리
    - <code>-moz-</code> : 파이어폭스
    - <code>-ms-</code> : 익스플로러 9.0
    - <code>-o-</code> : 오페라</p>
<h4 id="1-transform">1. transform</h4>
<p>🥕 사용 방법</p>
<p>   <code>transform: function();</code></p>
<p>🥕 속성</p>
<p>   ✔ <code>rotate(angle)</code> : 입력한 각도만큼 회전(평면적, 음수 가능)
   ✔ <code>scale(width, height)</code> : 입력한 숫자의 비율만큼 확대(축소할 땐 0&lt;n&lt;1, <code>scaleX()</code>, <code>scaleY()</code>로 따로 사용 가능)
   ✔ <code>skew(x_angle, y_angle)</code> : x축, y축 기준으로 회전(입체적, <code>skewX</code>, <code>skewY</code> 사용 가능)
   ✔ <code>translate(x, y)</code> : 입력한 좌표값으로 위치 선정
   ✔ <code>matrix(scaleX, skewY, skewX, scaleY, translateX, translateY)</code> : 한꺼번에 사용</p>
<h4 id="2-transition">2. transition</h4>
<p>🥕 사용 방법</p>
<p><code>transition-property : value;</code>
<code>:hover</code>와 주로 같이 쓰임</p>
<p>🥕 속성</p>
<p>   ✔ <code>transition-property</code> : 효과를 적용하는 css 속성</p>
<pre><code>   transition-property: width; /*너비에 적용*/</code></pre><p>   ✔ <code>transition-duration</code> : 효과 적용 시간 </p>
<pre><code>   transition-duration : 1s; /*1초 지속*/</code></pre><p>   ✔ <code>transition-timing-function</code> : 효과 속도 </p>
<pre><code>   transition-timing-function : linear; /*일정한 속도로 효과 적용*/</code></pre><p>   ✔ <code>transition-delay</code> : 효과 적용까지 걸리는 시간 </p>
<pre><code>   transition-delay: 2s; /*2초 후 효과 적용*/</code></pre><p>   ✔ <code>transition</code> : 한꺼번에 적용 </p>
<pre><code>   transition : width 1s linear 2s;</code></pre><p>   ✅ <code>transition</code>의 경우 꼭 4가지 속성 다 적용하지 않아도 되며 숫자가 하나이거나 먼저 나오는 숫자는 무조건 <code>duration</code>에 적용
   ✅ transition을 모든 css속성에 적용할 경우 <code>transition-property: all;</code> 로 설정</p>
<h4 id="3-animation">3. animation</h4>
<p>🥕 사용 방법</p>
<p><code>animation-property: value;</code>
<code>@keyframes</code>와 함께 사용</p>
<p>🥕 속성
   ✔ <code>animation-name</code> : 애니메이션 이름 지정</p>
<pre><code>   animation-name: widthStretch; /*애니메이션 이름: widthStretch*/</code></pre><p>   ✔ <code>animation-duration</code> : 효과 적용 시간(default: 0s) </p>
<pre><code>   animation-duration : 1s; /*1초 지속*/</code></pre><p>   ✔ <code>animation-timing-function</code> : 효과 속도 </p>
<pre><code>   animation-timing-function : linear; /*일정한 속도로 효과 적용*/</code></pre><blockquote>
<p><code>timing-function</code> 속성 값</p>
</blockquote>
<ol>
<li><p><code>linear</code> : 애니메이션 효과가 처음부터 끝까지 일정한 속도로 진행됩니다.</p>
</li>
<li><p><code>ease</code> : 기본값으로, 애니메이션 효과가 천천히 시작되어, 그다음에는 빨라지고, 마지막에는 다시 느려집니다.</p>
</li>
<li><p><code>ease-in</code> : 애니메이션 효과가 천천히 시작됩니다.</p>
</li>
<li><p><code>ease-out</code> : 애니메이션 효과가 천천히 끝납니다.</p>
</li>
<li><p><code>ease-in-out</code> : 애니메이션 효과가 천천히 시작되어, 천천히 끝납니다.</p>
</li>
<li><p><code>cubic-bezier(n,n,n,n)</code> : 애니메이션 효과가 사용자가 정의한 cubic-bezier 함수에 따라 진행됩니다.
<em>출처</em>: <em>[TCP School]</em>
<a href="http://www.tcpschool.com/css/css3_transform_animation">http://www.tcpschool.com/css/css3_transform_animation</a></p>
<p>✔ <code>animation-delay</code> : 효과 적용까지 걸리는 시간 </p>
<pre><code>animation-delay: 2s; /*2초 후 효과 적용*/</code></pre><p>✔ <code>animation-iteration-count</code>: 애니메이션 반복 횟수</p>
<pre><code>animation-iteration-count: infinite /*애니메이션 반복횟수 무한*/</code></pre><p>✔ <code>animation-direction</code> : 애니메이션 진행 방향</p>
<pre><code>animation-direction : alternate;</code></pre><blockquote>
<p><code>direction</code> 속성값</p>
</blockquote>
</li>
</ol>
<ul>
<li><p>alternate : from → to → from</p>
</li>
<li><p>normal : from → to, from → to</p>
</li>
<li><p>reverse: to → from, to → from</p>
<p>✔ <code>animation</code> : 한꺼번에 사용</p>
</li>
</ul>
<p>ex&gt;</p>
<pre><code class="language-css">.example {
    animation: widthStretch 1s linear 2s infinite alternate;
}

@keyframes widthStretch {
    from {
            width: 300px;
        }
        to {
            width: 600px;
        }
}</code></pre>
<h3 id="2-미디어-쿼리">2. 미디어 쿼리</h3>
<ul>
<li>PC뿐만 아니라 태블릿이나 모바일에도 대응하는 웹사이트(반응형/적응형)를 만들기 위해 사용</li>
</ul>
<p>🥕 사용 방법
<code>@media</code> 속성 이용
html페이지에서 meta태그 작성</p>
<pre><code class="language-html">&lt;!-- width는 화면 너비 설정, device-width는 디바이스별 화면너비 자동 설정 --&gt;
&lt;!-- intial-scale은 웹페이지 초기화면배율 --&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</code></pre>
<p>🥕 예시</p>
<pre><code class="language-css">.example {
    width: 300px;
        background-color: yellow;
        font-size: 10px;
}

/* 화면 너비가 320px - 800px 일때 적용 */
@media (min-width: 320px) and (max-width:800px){
    .example {
            width: 100px;
                font-size: 5px;
                background-color: none;
        }
}</code></pre>
<p>🥕 고려사항</p>
<ul>
<li>미디어 쿼리 정상적으로 출력되는지 확인하기 위해서는 <code>크롬 개발자도구</code> 혹은 <code>Troy Labs(결과물이 서버에 등록되어있는 경우)</code> 사용</li>
<li>viewport 태그 꼭 사용</li>
<li>기본 css 속성을 상속받기 때문에 상속받지 않으려면 <code>property: none;</code> 입력</li>
</ul>
<h3 id="3-css-태그-참고">3. CSS 태그 참고</h3>
<p>✅ css 학습 사이트 → <a href="https://w3schools.com/">https://w3schools.com/</a> </p>
<p>✅ 참고 사이트 </p>
<ol>
<li>TCP School
<a href="http://www.tcpschool.com/css/css3_transform_animation">http://www.tcpschool.com/css/css3_transform_animation</a></li>
<li>css 태그 확인 사이트
<a href="https://htmlcheatsheet.com/css/">https://htmlcheatsheet.com/css/</a></li>
<li>브라우저별 css 기능 지원 여부 확인
<a href="https://caniuse.com/">https://caniuse.com/</a><br/>
## 🚩 git

</li>
</ol>
<h3 id="1-특징">1. 특징</h3>
<ul>
<li>버전 관리(형상 관리)도구</li>
<li>분산 작업에 용이</li>
<li>svn보다 속도 빠름</li>
<li>데이터 보장</li>
<li>오픈 소스</li>
<li><code>staging area</code>라는 특수 공간이 있음</li>
</ul>
<h3 id="2-명령어">2. 명령어</h3>
<ul>
<li><code>git init</code> : 현재 디렉토리에 .git이라는 파일 생성</li>
<li><code>git status</code> : staging area의 file 상태 확인</li>
<li><code>git log</code> : 커밋 내역 확인</li>
<li><ul>
<li><code>git log -p</code>: 각 commit의 <code>diff</code> 결과 보여줌</li>
</ul>
</li>
<li><ul>
<li><code>git log --n</code> : 상위 n개의 commit만 보여줌</li>
</ul>
</li>
<li><ul>
<li><code>git log --stat</code> : 각 commit에서 수정된 파일의 통계 정보</li>
</ul>
</li>
<li><ul>
<li><code>git log --pretty=oneline</code> : 각 commit을 한 줄로 출력</li>
</ul>
</li>
<li><ul>
<li><code>git log --graph</code> : commit간 연결된 관계를 아스키 그래프로 출력</li>
</ul>
</li>
<li><ul>
<li><code>git log --graph --all</code> : 그림으로 볼 수 있음</li>
</ul>
</li>
<li><ul>
<li><code>git log -S function_name</code> :  코드에서 추가되거나 제거된 내용 중 특정 텍스트(ex&gt;function_name)가 포함되어 있는지 검사</li>
</ul>
</li>
<li><code>git diff</code> : commit 파일 중 변경된 사항 비교</li>
</ul>
<p>🥕🥕</p>
<ul>
<li><code>git add .</code> : staging area로 모두 추가 (.은 모든 파일, .대신 파일이름 입력 가능)</li>
<li><code>git commit -m &quot;message&quot; *file*</code> : commit 메시지와 함께 파일 커밋 (<em>file</em>은 생략 가능 파일별로 커밋 메시지를 다르게 할 경우에는 파일이름 작성)</li>
<li><code>git reset HEAD *file*</code> : <code>git add</code> 취소</li>
<li><code>git branch</code> : 브랜치 확인</li>
<li><code>git branch *branch_name*</code> : 이름이 branch_name인 브랜치 생성</li>
<li><code>git checkout *branch_name*</code> : 해당 브랜치로 이동</li>
<li><code>git checkout *snapshot hash*</code> : 해당 스냅샷으로 이동</li>
<li><code>git merge *merged_branch*</code> : 해당 브랜치로 병합</li>
<li><code>git branch -d *branch_name*</code> : merge된 브랜치 삭제</li>
</ul>
<p>🥕🥕</p>
<ul>
<li><code>git clone *url*</code> : 원격 git 저장소의 프로젝트 url을 clone(clone할 경우 &#39;origin&#39;이란 이름으로 저장소 생성)</li>
<li><code>git remote</code> : 현재 프로젝트에 저장된 원격 저장소 확인( -v를 붙이면 단축이름도 확인 가능)</li>
<li><code>git remote add *nickname* *url*</code> : 별칭(대부분 origin) 지정해서 원격저장소 추가</li>
<li><code>git remote show *origin*</code> : 원격 저장소 보기(위에 지정한 닉네임을 계속 사용)</li>
<li><code>git remote rename *origin* *change*</code> : 별칭 변경(origin → change)</li>
<li><code>git remote rm *origin*</code> : 해당 원격저장소 삭제</li>
<li><code>git fetch *origin* *master*</code> : 로컬에 없는 리모트 저장소 내용을 모두 가져옴</li>
<li><code>git merge *origin*/*master*</code> : 가져온 내용 병합</li>
<li><code>git pull *origin* *master*</code> : fetch + merge</li>
<li><code>git push *origin* *master*</code> : 커밋내용 원격 저장소에 반영 (브랜치이름(master) 앞에 &#39;+&#39;표시 붙이면 충돌 무시하고 강제 푸시)</li>
</ul>
<p>🟠 &#39;*&#39; 기호는 변경될 수 있는 부분을 뜻하므로 작성시에는 제외!
🟠 github에 업로드하는 경우에는 일반적으로
<code>add</code> → <code>status</code>로 확인 →     <code>commit</code> → <code>push</code></p>
<p>여러 사람이 clone해서 변경 사항이 있는 경우
<code>fetch</code> + <code>merge</code> (<code>pull</code>) → <code>add</code>  → ... → <code>push</code></p>
<p>github에서 fork한 리포지토리 동기화
<code>git remote -v</code> → <code>git remote add upstream &lt;원본url&gt;</code> → <code>fetch(upstream)</code> → <code>merge(upstream/master)</code> → <code>push(origin master)</code></p>
<br/>

<h3 id="3-참고">3. 참고</h3>
<p>✅ git 문서 <a href="https://git-scm.com/book/en/v2">https://git-scm.com/book/en/v2</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2021 NIPA AI 온라인 교육 수료 후기]]></title>
            <link>https://velog.io/@hyes-y-tag/2021-NIPA-AI-%EC%98%A8%EB%9D%BC%EC%9D%B8-%EA%B5%90%EC%9C%A1-%EC%88%98%EB%A3%8C-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@hyes-y-tag/2021-NIPA-AI-%EC%98%A8%EB%9D%BC%EC%9D%B8-%EA%B5%90%EC%9C%A1-%EC%88%98%EB%A3%8C-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 09 Dec 2021 14:39:39 GMT</pubDate>
            <description><![CDATA[<h2 id="엘리스-코딩-2021-ai-온라인-실무-기본응용-교육과정-수강-후기">[엘리스 코딩] 2021 AI 온라인 실무 기본/응용 교육과정 수강 후기</h2>
<p>올해 개발자라는 꿈에 가까워지기 위해 여러 활동을 하였는데 그중 하나가 바로 &quot;<strong>2021 NIPA AI 온라인 교육</strong>&quot; 이었다.</p>
<p>무료 강의에, 정보통신산업진흥원 이수증 발급(취준생에겐 꼭 필요한..) , 관련 자격증 취득도 지원해 준다 하니 안 할 이유가 없었다!</p>
<p>교육 기간이 2021.06.15 - 2021.12.17 이고 아슬아슬하게 수료를 했지만 꽤 유익했기 때문에 후기를 남겨보고자 한다.</p>
<p><a href="https://2021nipa.elice.io/explore">2021 NIPA AI 온라인 교육</a> <a href="https://2021nipa.elice.io/explore">https://2021nipa.elice.io/explore</a>
<br/></p>
<hr>
<blockquote>
</blockquote>
<ol>
<li>교육 과정
 1-1. 기본 교육과정<pre><code>1-2. 응용 교육과정</code></pre></li>
<li>수강 혜택</li>
<li>장/단점</li>
</ol>
<h4 id="1-교육-과정">1. 교육 과정</h4>
<p><strong>1-1. 기본 교육과정</strong></p>
<p>처음 교육을 시작하기 전 <strong>AI 교육 역량 평가</strong>를 진행하는데 평가에서 만점을 받으면 바로 응용 과정을 수강할 수 있다.
총 6문제에 30분의 시간이 주어지며
Pandas , matplotlib, numpy 라이브러리를 다뤄보았다면 충분히 100점 맞을 수 있는 난이도였지만 나는 하나를 아쉽게 틀려서 기본 과정부터 수강하게 되었다.</p>
<p><img src="https://images.velog.io/images/hyes-y-tag/post/6fec3f20-69e2-44e8-83fb-fa149efef99b/%EA%B8%B0%EB%B3%B8%EA%B3%BC%EC%A0%95-1.png" alt=""></p>
<p><img src="https://images.velog.io/images/hyes-y-tag/post/c07f3929-d63a-4c30-8352-5111dc5be563/%EA%B8%B0%EB%B3%B8%EA%B3%BC%EC%A0%95-2.png" alt=""></p>
<p>파이썬을 어느 정도 다룰줄 알았기 때문에 난이도는 크게 어렵지 않았다
오히려 &#39;기본 과정이라 쉽기만 하겠지?&#39; 라고 생각했는데 프로젝트를 진행하면서 </p>
<p><strong>&#39;데이터 분석은 이렇게 진행하는구나&#39;, 
&#39;산업에서 이렇게 활용이 되는구나&#39;</strong> </p>
<p>라는 깨달음이 더 컸던 교육 과정이었다
<br/>
<strong>1-2. 응용 교육과정</strong></p>
<p>응용 교육과정에서는 머신러닝과 딥러닝을 중점적으로 배웠는데 머신러닝에 필요한 통계 이론을 최근에 배워서 이해하기 더 수월했다.
이론만 배웠을 땐 &#39;이걸 언제 다 계산하지..?&#39; 하고 정신이 아찔했으나 이미 똑똑한 사람들이 다 프로그램을 만들어 놨더라 🤣</p>
<p><img src="https://images.velog.io/images/hyes-y-tag/post/f1d646a9-e138-4d0e-92bb-87b1ec436f45/%EC%9D%91%EC%9A%A9%EA%B3%BC%EC%A0%95-1.png" alt=""></p>
<p>&#39;응용 과정&#39;이지만 머신러닝/딥러닝의 기초를 가르치는 느낌이고 
그럼에도 쌩초보에겐 너무 어려웠던 교육이었다. 
그렇지만 개념 외에도 산업별로 AI가 어떻게 사용되고 있는지 사례도 배웠고 난이도 있는 프로젝트도 함께 해주셔서 AI에 한번 새끼 발가락 발톱만큼 담궈봤다.. 고 할 수는 있을 것 같다.
<img src="https://images.velog.io/images/hyes-y-tag/post/a5571045-ba49-4f0c-afb6-93628c06c3d9/AI.png" alt="">
↑ 응용 과정 프로젝트 실습 화면( Jupyter Notebook 사용)
<br/></p>
<h4 id="2-수강-혜택">2. 수강 혜택</h4>
<p>수강 하면 이런 혜택이~!</p>
<blockquote>
</blockquote>
<p>1) 수강생 교육비 전액 지원
2) 정보통신산업진흥원 이수증 발급
3) 인공지능 자격증 취득 지원</p>
<p>취준생의 입장에서 이수증과 자격증은 하나하나가 굉장히 소중하기 때문에 당연히!! 이런 혜택을 놓칠 수 없었다..
<br/></p>
<h4 id="3-장단점">3. 장/단점</h4>
<p>일단! 장점은 
<em>1) 따로 IDE를 설치할 필요가 없다</em></p>
<p>&#39;엘리스&#39;라는 교육 플랫폼의 특징이기도 하다!
매번 이런 교육을 들으면 코드 작성을 위한 프로그램 설치가 굉장히 번거로웠는데 따로 설치하는 것 없이 바로 실습이 가능해서 좋았다</p>
<p><em>2) 초보에겐 얻을 수 있는게 많다</em></p>
<p>전공자라면 약간의 아이디어를 얻어갈 수 있을까? 잘 모르겠지만
비전공자인 내 입장에선 AI를 가볍게 겪을 수 있었던 좋은 경험이 되었다. 
다른 거 하느라고 시간을 많이 쏟지 못했지만 각잡고 공부하면 더 얻을게 많았을 유익한 교육이었다.</p>
<p><em>3) 쏠쏠한 이벤트가 많았다</em></p>
<p>참여를 많이 못하긴 했지만 각자 진행한 데이터 분석 프로젝트를 올려서 대회를 한다거나 수료하면 상품을 주는 등의 알찬 이벤트가 많았다! </p>
<p>단점은
<em>1) 이미 완성된 프로젝트에 숟가락 얹기</em></p>
<p>프로젝트가 이미.. 다 완성되어있고 실행을 해보는 수준이었다. 물론 당장 뭘 할 수 있는 실력이 안되었고 개인적으로 공부를 더 해야겠지만 실습의 비율이 조금 적다고 느끼긴 했다! 단 몇 줄이라도 혼자 적어보면 기억에 잘 남을텐데 그 부분이 아쉬웠다.
<br/></p>
<hr>
<p>💕 총평</p>
<blockquote>
</blockquote>
<p>초보자에게는 굉장히 유익한 강의!
전공자라도 AI에 대한 기초를 다시 한 번 다지고 싶다면 추천!
그 이상의 실력을 키우고 싶다면 다른 교육을,,!</p>
<p>2022년에도 같은 교육을 진행한다면 관심 있는 분들이 많이 참여하셨으면 좋겠다! 
<strong>무료강의</strong>에 이 정도 퀄리티라면 당연히! 추천이고
전공이 IT관련인데 학부 강의 듣기 전에 기초를 다지고 싶다면 더욱 더 추천이다! 
물론 진행을 한다면..😂 한다면 다시 한번 더 들을 의향이 있다 :-)</p>
<p>이제 인공지능 자격증 시험이 남았는데 취득해서 유종의 미를 거둘 수  있길-!</p>
]]></description>
        </item>
    </channel>
</rss>