<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>daekim.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 04 Jan 2023 03:31:06 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>daekim.log</title>
            <url>https://velog.velcdn.com/images/dev_kdh/profile/963a3cb1-753f-4d9b-a02a-1137583ee1ab/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. daekim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_kdh" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[TIL] 6일차 - MySQL]]></title>
            <link>https://velog.io/@dev_kdh/TIL-6%EC%9D%BC%EC%B0%A8-MySQL-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-6%EC%9D%BC%EC%B0%A8-MySQL-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Wed, 04 Jan 2023 03:31:06 GMT</pubDate>
            <description><![CDATA[<p>mysql 문제를 풀면서 가장 오랫동안 고민을 했던 문제다.
with recursive를 통해 가상테이블을 만든 후 join을 통해 문제를 해결할 수 있었다.</p>
<h2 id="입양-시간-구하기2"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/59413">입양 시간 구하기(2)</a></h2>
<p>처음에는 입양시간 별 횟수를 구하는 쿼리는 작성했다.</p>
<pre><code class="language-sql">SELECT HOUR(DATETIME) as HOUR, count(*) as COUNT
from ANIMAL_OUTS
group by HOUR
order by HOUR</code></pre>
<p>결과는 다음과 같다.</p>
<img src="https://velog.velcdn.com/images/dev_kdh/post/067b04e1-de9c-432e-aa37-e05c67b2feaa/image.png" width="60%">

<p>위 결과를 보면 0<del>6시와 20</del>23시에는 입양을 하지 않아 데이터가 존재하지 않는다. 그래서 해당 시간의 데이터를 만들어서 출력을 해야했다. 다양한 시도를 하는 과정에서 with recursive라는 것을 알게 되었다.</p>
<blockquote>
<h3 id="📌-with-recursive">📌 WITH RECURSIVE</h3>
<p>WITH RECURSIVE 구문은 가상 테이블을 생성하면서 가상 테이블 자신의 값을 참조하여 값을 결정할 때 사용된다.</p>
</blockquote>
<p>해당 구문을 사용하여 데이터가 존재하지 않는 부분을 채워넣은 가상테이블을 하나 만들었다.</p>
<pre><code class="language-sql">with recursive time as (
    select 0 as HOUR // 초기값 설정
    union
    select HOUR + 1
    from time
    where HOUR &lt; 23 // recursive 탈출 조건
) // 0~23시까지의 가상테이블(time) 생성

SELECT b.HOUR, count(a.DATETIME) as COUNT
from ANIMAL_OUTS a
right join time b
on HOUR(a.DATETIME) = b.HOUR
group by b.HOUR
order by b.HOUR</code></pre>
<br>
위와 같이 작성해주면 입양이 되지 않는 시간대의 count도 0으로 출력이 된다.
<img src=https://velog.velcdn.com/images/dev_kdh/post/a6d11d73-d27e-4c37-9e9f-2993dc47f70a/image.png width="60%">



<h2 id="참고">참고</h2>
<p><a href="https://horang98.tistory.com/10">https://horang98.tistory.com/10</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 5일차 - MySQL]]></title>
            <link>https://velog.io/@dev_kdh/TIL-5%EC%9D%BC%EC%B0%A8-MySQL-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-5%EC%9D%BC%EC%B0%A8-MySQL-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sun, 01 Jan 2023 07:13:14 GMT</pubDate>
            <description><![CDATA[<p>IT 직군을 준비하다 보니 코딩테스트에서 mysql을 사용하는 경우도 있어서 mysql 공부도 조금씩 하고 있다.
쉬운 문제들은 괜찮았지만 점점 난이도가 높아지고 있다보니 정리의 필요성이 느껴졌다.
이번에는 두 개 이상의 조건이 있어서 이들을 조회하는 경우를 정리해보았다.</p>
<h2 id="즐겨찾기가-가장-많은-식당-정보-출력하기"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/131123">즐겨찾기가 가장 많은 식당 정보 출력하기</a></h2>
<p>이 문제에서는 음식의 종류별로 구분하고 그 안에서 즐겨찾기 수가 가장 많은 식당을 조회하는 문제였다. 처음에는 select문을 두 번 사용하지 않고 구하는 방법을 고민했다.</p>
<pre><code class="language-sql">SELECT a.FOOD_TYPE, a.REST_ID, a.REST_NAME, a.FAVORITES
from REST_INFO a
left join REST_INFO b
on a.FOOD_TYPE = b.FOOD_TYPE AND a.FAVORITES &lt; b.FAVORITES
where b.FOOD_TYPE IS null
order by a.FOOD_TYPE desc</code></pre>
<p>같은 테이블을 join하여 on에서 음식의 타입<code>FOOD_TYPE</code>이 같은 것들 중 즐겨찾기 수<code>FAVORITES</code>가 가장 많은 것을 골라내었다. 
<code>b.FAVORITES</code>가 <code>NULL</code> 이라면 <code>a.FAVORITES</code>가 최대값이기 때문에 최대값을 가진 row값을 추출을 할수가 있다.
where은 a테이블에서 값을 찾게 한다. 
<img src="https://velog.velcdn.com/images/dev_kdh/post/6db8a67d-1f68-4a80-bf5f-8502b650b394/image.png" alt=""></p>
<p>해당 방법이 가장 처음 시도한 방법이었다. 결과는 통과였지만 문제에서는 <code>group by</code>를 요구하는 문제였기 때문에 <code>group by</code>를 사용하는 방법을 다시 고민해보았다. 나머지 두가지 방법은 <code>select</code>문을 두번 사용하는 방법이다.</p>
<p>먼저 join을 사용하여 구하는 방식이다. 위의 방식과 유사하나 최대값을 구하는 부분이 <code>select</code>를 통해 해결된다.</p>
<pre><code class="language-sql">SELECT a.FOOD_TYPE, a.REST_ID, a.REST_NAME, a.FAVORITES
from REST_INFO a
join (
    SELECT FOOD_TYPE, Max(FAVORITES) as FAVORITES
    from REST_INFO
    group by FOOD_TYPE
) b
on a.FOOD_TYPE = b.FOOD_TYPE AND a.FAVORITES = b.FAVORITES
order by a.FOOD_TYPE desc</code></pre>
<p><code>join</code>의 <code>select</code>문을 통해 <code>group by</code>를 사용하여 <code>FOOD_TYPE</code>별 <code>FAVORITIES</code>의 최대값을 구해서 새로운 테이블을 만든다. 그 후에 원래의 테이블과 <code>join</code>하여 필요한 튜플을 구해준다.</p>
<p>마지막 방법은 <code>where</code>에서 <code>in</code>을 사용하여 구하는 방법이다. </p>
<pre><code class="language-sql">SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
from REST_INFO
where FAVORITES in (
    select Max(FAVORITES)
    from REST_INFO
    group by FOOD_TYPE
)
group by FOOD_TYPE 
order by FOOD_TYPE desc</code></pre>
<p><code>join</code>을 사용하지 않고 <code>group by</code>를 두 번 사용한다.</p>
<p>쉬운듯 쉽지 않은 복잡한 mysql이다. 공부를 많이 해야할 것 같다!</p>
<h2 id="참고">참고</h2>
<p><a href="https://helloino.tistory.com/120">https://helloino.tistory.com/120</a>
<a href="https://yoo-hyeok.tistory.com/98">https://yoo-hyeok.tistory.com/98</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 4일차 - Jacoste 알고리즘]]></title>
            <link>https://velog.io/@dev_kdh/TIL-4%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-4%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sat, 31 Dec 2022 07:58:15 GMT</pubDate>
            <description><![CDATA[<h3 id="삼각-달팽이"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/68645">삼각 달팽이</a></h3>
<pre><code class="language-js">function solution(n) {
    let ret = Array.from({length: n}, (v, idx) =&gt; {
        let arr = [];
        for (let i = 0; i &lt;= idx; i++) arr.push(0);
        return arr;
    })
    let x = -1;
    let y = 0;
    let cnt = 1;
    let line = -1;
    while (n-- &amp;&amp; ++line &gt;= 0) {
        for (let j = 0; j &lt;= n; j++) {
            line % 3 === 0 ? ++x : line % 3 === 1 ? ++y : (--x, --y)
            ret[x][y] = cnt++;
        }
    }
    return [].concat(...ret);
}</code></pre>
<p>여기서 중요한건 가장 마지막줄이다.</p>
<pre><code class="language-js">return [].concat(...ret);</code></pre>
<p>이 부분이 굉장히 인상적이었다.</p>
<p>처음에는 <code>reduce</code>에 <code>spread operator(...)</code>를 사용했었는데 소요시간이 2800ms까지 나왔었다.</p>
<pre><code class="language-js">return ret.reduce((acc, cur) =&gt; [...acc, ...cur]);</code></pre>
<p>고민을 하다가 <code>concat()</code>으로 바꿔보니 소요시간이 900ms까지 줄어들었다. 이 부분은 <code>forEach</code>를 통해 새로운 배열을 만드는 경우와 비슷했다.</p>
<pre><code class="language-js">return ret.reduce((acc, cur) =&gt; acc.concat(cur));</code></pre>
<p>그래서 찾아보다 보니 <code>flat()</code>이라는 함수가 있어서 이를 사용했고 결과가 90ms까지 줄어드는 것을 확인할 수 있었다.</p>
<pre><code class="language-js">return ret.flat();</code></pre>
<p>하지만... 구글링을 하던 중에 놀라운 사실을 또 하나 보게 되었다. <code>flat()</code>은 느리다는 내용의 글이었다. 간편하게 쓸 수 있는 <code>flat()</code>은 브라우저에 최적화가 되어있지 않은 상태이기 때문에 <code>[].concat()</code>이 더 유리하다!
해서 수정한 코드가 다음과 같다.</p>
<pre><code class="language-js">return [].concat(...ret);</code></pre>
<p>결과는 20ms였다.
<code>2800ms</code>에서 <code>20ms</code>까지 줄어들었다.</p>
<p>이중배열을 단일배열로 만드는 하나의 과정만 최적화시켰을 뿐인데 소요시간이 이렇게나 줄어들었다.
정말 javascript는 신기한 언어다.</p>
<h2 id="참고">참고</h2>
<p><a href="https://velog.io/@milkcoke/Javascript-Array.flat-%EC%9D%80-%EB%8A%90%EB%A6%AC%EB%8B%A4">https://velog.io/@milkcoke/Javascript-Array.flat-%EC%9D%80-%EB%8A%90%EB%A6%AC%EB%8B%A4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42gg] Next.js 이미지 최적화로 인한 문제 해결]]></title>
            <link>https://velog.io/@dev_kdh/42gg-Next.js-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@dev_kdh/42gg-Next.js-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Mon, 31 Oct 2022 08:53:43 GMT</pubDate>
            <description><![CDATA[<p>오랜만에 42gg 다같이 모여서 작업했다.
그런데...!!</p>
<p>잘나오던 이미지가 안나오기 시작했다. 왜일까? 왜 안나올까?</p>
<h2 id="📌-why">📌 WHY</h2>
<p>uri부터 확인해보니 우리가 넣어주지 않는 쿼리문이 붙어서 동작을 하고 있었다.
쿼리문이 있어서 이미지를 찾지 못하고 있던 것이다!!</p>
<p>원인을 찾아보니 Nextjs에서 이미지를 최적화하면서 발행하는 문제였다. 이미지 url에 쿼리문이 추가되어 이미지를 찾지 못했다.</p>
<p>이미지가 뜨지 않는 문제뿐만 아니라, 결과입력 모달창 등에서 뜨지 않는 이미지가 가장 앞쪽에 덮여 있어서 버튼이 눌리지 않는 등의 문제가 발생했다.</p>
<blockquote>
</blockquote>
<img width="503" alt="image url 쿼리" src="https://user-images.githubusercontent.com/73281190/198961337-d15c2f4b-f98b-4d2f-bf82-4f0e33d66c38.png">
<img width="740" alt="images 에러" src="https://user-images.githubusercontent.com/73281190/198961600-ceb278a4-cd39-47a4-8d3e-167280b38b02.png">


<br>

<h2 id="🛠-해결해보자">🛠 해결해보자</h2>
<p>Next.js는 이미지를 사용할 때 html의 img태그가 아닌 next/image를 import해서 사용할 수 있다. 이것을 사용하게 되면 기본적으로 optimize 옵션이 활성화 된다. 이것이 활성화되면서 이미지가 최적화되고, 원본이미지의 url이 아닌 nextjs에서 생성한 url로 바뀌게 된다. next/image로 요청이 들어오면 내부적으로 imageOptimizer라는 함수를 실행시켜 결과물을 리턴시켜주는 과정을 거쳐서 발생하는 문제였다.</p>
<p>우선은 최적화 과정을 하지 않도록 해주었다.</p>
<pre><code class="language-js"> &lt;Image
   src={userImageUri}
   alt=&#39;prfImg&#39;
   layout=&#39;fill&#39;
   objectFit=&#39;cover&#39;
   sizes=&#39;30vw&#39;
   quality=&#39;30&#39;
   unoptimized={true} // 해당 옵션을 넣어주면 이미지 최적화를 하지 않는다.
 /&gt;</code></pre>
<p>조금 아쉬운 부분😔은 모든 image 태그에 unoptimized 옵션을 추가해줘야 했는데, 이 부분을 config에서 처리해주고 싶어서 다양한 시도를 했지만 아직 처리해주지 못했다. 우선은 급한대로 모든 태그에 추가해준 상태이고 좀 더 찾아볼 필요가 있다!</p>
<h2 id="⚙️최종-처리">⚙️최종 처리!</h2>
<p>DB에서 cdn을 포함한 외부 url을 백엔드에서 S3서버에 올려 내부 uri로 바꿔 보내주었다. 하여 외부 ur를 사용할 때 발생한 Nextjs의 최적화 문제가 사라졌다. 이전에 처리했던 unoptimized 옵션은 다시 제거해주었다!</p>
<h3 id="참고">참고</h3>
<ul>
<li><a href="https://yeoulcoding.me/289">https://yeoulcoding.me/289</a></li>
<li><a href="https://velog.io/@hhhminme/Next.js%EC%97%90%EC%84%9C-Nextimage%EC%97%90%EC%84%9C-%EC%99%B8%EB%B6%80-%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EB%AA%BB%EA%B0%80%EC%A0%B8%EC%98%A4%EB%8A%94-%EB%AC%B8%EC%A0%9C%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-loader-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0">https://velog.io/@hhhminme/Next.js%EC%97%90%EC%84%9C-Nextimage%EC%97%90%EC%84%9C-%EC%99%B8%EB%B6%80-%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-%EB%AA%BB%EA%B0%80%EC%A0%B8%EC%98%A4%EB%8A%94-%EB%AC%B8%EC%A0%9C%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-loader-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 3일차 - Jacoste 알고리즘]]></title>
            <link>https://velog.io/@dev_kdh/TIL-3%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-3%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sun, 23 Oct 2022 06:56:04 GMT</pubDate>
            <description><![CDATA[<p>세번째 알고리즘 스터디!
혼자할 때보다 훨씬 많이 배워가는 중이다. 혼자할 때는 풀고 나면 끝이었는데, 스터디를 함께하면서 부족했던 부분, 내가 생각하지 못했던 부분을 다시 살펴보고 의견을 나눠보면서 더 깊게 배울 수 있었다.</p>
<p>이번에 푼 문제는 타겟넘버, 주차 요금 계산, [3차] 압축 세 문제를 풀었다.
물론 1레벨은 생략!</p>
<h3 id="타겟-넘버"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43165">타겟 넘버</a></h3>
<p>타겟 넘버 문제는 깊이 탐색을 하며 재귀함수를 사용하는 문제였다. 오랜만에 재귀함수를 사용하다 보니 함수가 완성될 때까지 많은 고민을 했다. 두시간 걸려서 만들었는데 만들고 보니 별 거 아니었다. 풀었을 때는 나름 잘 했다고 생각했는데, 스터디를 하다보니 굉장이 복잡한 코드라고 느껴졌다. 공부를 하면서 훨씬 간단하게 만들 수 있음을 알게 되었다. 그래도 만족스러운 코드다! 아무런 참고도 없이 혼자 재귀를 해냈다는데 칭찬!!</p>
<pre><code class="language-js">function solution(numbers, target) {
    let cnt = 0;
    let sum = 0;

    function rec(arr, goal)
    {
        if (arr.length === 0 &amp;&amp; goal === 0)
            return 0;
        else if (arr.length === 0 &amp;&amp; goal !== 0)
            return 1;
        rec(arr.slice(0, -1), goal + arr[arr.length - 1]) === 0 ? cnt++ : cnt;
        rec(arr.slice(0, -1), goal - arr[arr.length - 1]) === 0 ? cnt++ : cnt;
        return 1;
    }
    rec(numbers, target);
    return cnt;
}</code></pre>
<h3 id="주차-요금-계산"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/92341">주차 요금 계산</a></h3>
<p>주차요금. OUT이 없을 때 23:59에 아웃을 추가해주면 다양한 경우의 수를 생각하지 않고 해결할 수 있는 문제였다. 왜... 난 생각해내지 못했던 걸까??? 여전히 나는 C언어에서 벗어나지 못하고 있다고 생각하지만, 요즘은 차츰차츰 메소드를 사용하는 횟수도 늘어나고 뭔가 자바스크립트에 가까워지고 있다고 느껴진다. 좀 더 노력해보자.</p>
<h3 id="압축"><a href="https://school.programmers.co.kr/learn/courses/30/lessons/17684">압축</a></h3>
<p>무난하게 풀어보았다. 시간복잡도를 고민하기는 했어야해서 시간이 걸리긴 했지만, 큰 문제는 없었다.</p>
<h3 id="마무리">마무리</h3>
<p>요즘 알고리즘 풀면서 가장 많이 신경쓰는 부분이 시간복잡도이다. 뭔가 효휼적으로 코드를 작성하고 싶은 마음에 이중루프문을 가지게 될만한 코드는 최대한 자재하려고 하다보니, 알고리즘을 푸는데 시간도 더 오래 걸리는 것 같기도 하고..? 근데 재밌다..!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 2일차 - Jacoste 알고리즘]]></title>
            <link>https://velog.io/@dev_kdh/TIL-2%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-2%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sat, 22 Oct 2022 04:52:11 GMT</pubDate>
            <description><![CDATA[<p>2일차 알고리즘 스터디!
문제가 꽤나 어려웠다. 생각보다 안풀려고 고생을 많이했다.
카카오 문제는 어렵다는 생각에 두려움부터 갖고 시작해서 그런가 더 어려운거 같기도 하고...?</p>
<p>오늘은 스터디하면서 많이 혼났다.
C언어처럼 알고리즘 풀려고 스터디하는게 아닌데 자꾸 C언어로 문제를 풀고 말아버린다.</p>
<p>c언어로 풀 수 있기는 하지만, 이를 다시 메서드로 바꾸고 자바스크립트 코드처럼 리팩토링 해야하는데 그 과정을 하지 않아서 문제가 있어보인다. 시간 내서 공부를 다시 해야할 필요가 있다.</p>
<p>프린터, 뉴스클러스터링, K진수에서 소수 개수 구하기 세 문제 풀었다.</p>
<h3 id="🎰-k진수에서-소수-개수-구하기">🎰 K진수에서 소수 개수 구하기</h3>
<p>소수 개수 구하기 문제가 가장 의아했다. 시간 복잡도를 많이 생각해보려고 했는데 결과적으로 내 코드가 가장 느리게 풀렸다. 왜일까?</p>
<pre><code class="language-js">function solution(n, k) {
  let knum = n.toString(k).split(&#39;0&#39;);
  let tmp;
  let cnt = 0;

  for (let i = 0; i &lt; knum.length; i++) {
    if (+knum[i] === 2) {
      cnt++;
      continue;
    }
    if (+knum[i] % 2 === 0 || +knum[i] === 1 || knum[i] === &#39;&#39;) continue;
    tmp = 3;
    while (tmp &lt;= Math.sqrt(+knum[i])) {
      if (+knum[i] % tmp === 0) break;
      tmp += 2;
    }
    if (tmp &gt; Math.sqrt(+knum[i])) cnt++;
  }
  return cnt;
}</code></pre>
<p>이중 루프가 당연히 필요하다고만 생각하고 풀었었는데, 다른 스터디원들의 코드를 보니 아니었다. 혼자만 복잡하게 생각하고 문제를 풀었었다. 아래는 동료의 코드이다.</p>
<pre><code class="language-js">function solution(n, k) {
    const checkPrime = (num) =&gt; {
        if (num === 2 || num === 3) return true
        for (let i = 2; i &lt;= Math.sqrt(num); i++) {
            if (num % i === 0) return false;
        }
        return true
    }
    return n.toString(k)
            .split(&#39;0&#39;)
            .filter((x) =&gt; x !== &#39;1&#39; &amp;&amp; x !== &#39;&#39; &amp;&amp; checkPrime(+x))
            .length;
}</code></pre>
<p>동료의 코드에서 보면 시간복잡도 O(n)을 가지는 filter메소드 조건 내부에 for문이 존재하기 때문에 결국 내 코드와 같이 이중 루프문을 가진다고 생각을 했는데, 제일 느렸다.</p>
<p>그래서!! 그래서!! 내 코드를 하나씩 다 뜯어봤다. 줄어든 결과!!
<img src="https://velog.velcdn.com/images/dev_kdh/post/3cd3e7d8-e154-45c4-8a1d-d4e1de445d60/image.png" width="40%" style="float:left;"><img src="https://velog.velcdn.com/images/dev_kdh/post/3990a0d1-ee00-4081-8cb9-c3691d89ded1/image.png" width="40%">
<img src="https://velog.velcdn.com/images/dev_kdh/post/682eb862-ade9-413a-817c-f64982347b66/image.png" width="40%" style="float:left;"><img src ="https://velog.velcdn.com/images/dev_kdh/post/7cc63f7b-3c5e-4e32-8451-0a849d5a6993/image.png" width="40%"></p>
<p>왼쪽 위 결과는 초기 코드의 결과 값이다. 동료의 결과값은 12.96ms가 나왔는데 난 10배 이상 느렸다. 다양한 고민을 해보고 처음에 줄인 것은 while문의 조건에서 Math.sqrt함수 사용을 줄여보는 것이었다.
for문에 들어오자마자 변수를 하나 만들어주고 Math.sqrt값을 변수에 저장시켜놓고 while문의 조건에 변수를 넣는 방법을 사용했더니 130대에서 70대까지 줄어들었다.
그 뒤로 고민을 한참 하다보니 값을 저장해주는 부분의 위치를 내리면 될 것 같았다. 그래서 for문 시작 부분에서 while문 위로 옮겼더니 40대까지 줄어들었다!</p>
<p>이후에 정말 다양한 고민을 했지만 아무리 생각해도 로직상 시간이 더 줄어들 부분이 없었다. 동료의 코드에서 보아도 로직상 문제가 없는데, 심지어 while문도 나는 홀수만 확인해서 더 빨라야하는데 동료코드보다 4배는 더 드렸으니 말이다.
그러다가 갑자기 문득 눈에 띈게 +knum[i]였다. +를 통해 number로 암묵적 타입 변환을 시켜주는데, 타입 변환이 계속해서 일어나다보니 느려진 것이었다. 이 부분까지 고쳐주고 나나 5.77ms라는 약 25배 이상 빨라진 경이로운 결과를 만들어낼 수 있었다!!</p>
<p>최종 코드는 다음과 같다.</p>
<pre><code class="language-js">function solution(n, k) {
    let knum = n.toString(k).split(&#39;0&#39;);
    let num = 0;
    let tmp;
    let cnt = 0;
    let sqrt = 0;

    for(let i = 0; i &lt; knum.length; i++)
    {
        num = +knum[i];
        if (num === 2)
        {
            cnt++;
            continue;
        }
        if (num % 2 === 0 || num === 1 || num === &#39;&#39;)
            continue;
        sqrt = Math.sqrt(num);
        for (tmp = 3;tmp &lt;= sqrt; tmp += 2)
            if (num % tmp === 0)
                break;
        if (tmp &gt; sqrt)
            cnt++;
    }
    return cnt;
}</code></pre>
<p>물론 여전히 c의 모습은 벗어나지 못했다.
메서드를 사용해서 줄이는 연습은 차차 진행할 예정이다. 물론... 여유롭게 진행은 안되지만 추후에..!!</p>
<p>지난주 스터디 결과였는데 시간 복잡도 관련해서 계속 마음에 걸렸던 문제였다. 다행이 원인을 찾고 타입 변환과 시간복잡도 등 이미 알고 있던 부분도 제대로 인지하지 못하고 있음을 깨닫게 되었고, 이번 경험으로 큰 성장을 하게 되었다! 타입 변환 앞으로도 지켜보겠어...!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 09장. 타입 변환과 단축 평가]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-09%EC%9E%A5.-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%8B%A8%EC%B6%95-%ED%8F%89%EA%B0%80</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-09%EC%9E%A5.-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%8B%A8%EC%B6%95-%ED%8F%89%EA%B0%80</guid>
            <pubDate>Sat, 15 Oct 2022 07:07:16 GMT</pubDate>
            <description><![CDATA[<h2 id="🛠91-타입-변환이란">🛠9.1 타입 변환이란?</h2>
<p>자바스크립트의 값에는 타입이 존재하고 이 타입은 변경이 가능하다. 개발자가 의도적으로 값의 타입을 변환하는 것을 <strong>명시적 타입 변환</strong> 또는 <strong>타입 캐스팅이</strong>라고 한다. 개발자의 의도와는 상관없이 자바스크립트에 의해 변하는 것을 <strong>암묵적 타입 변환</strong> 또는 <strong>타입 강제 변환</strong>이라고 한다.</p>
<p>명시적 타입 변환은 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 드러난다.
암묵적 타입 변환은 표현식을 에러 없이 평가하기 위해 피연산자의 값을 암묵적으로 타입 변환해 새로운 타입의 값을 만들어 단 한 번 사용하고 버린다.
따라서 자신이 작성한 코드에서 암묵적 타입 변환이 발생하는지, 발생한다면 어떤 타입의 어떤 값으로 변환되는지, 그리고 타입 변환된 값으로 표현식이 어떻게 평가될 것인지 예측 가능해야한다.
중요한 것은 코드를 예측할 수 있어야 한다는 것이다. 동료가 작성한 코드를 정확히 이해할 수 있어야하고 자신이 작성한 코드도 동료가 쉽게 이해할 수 있어야 한다. </p>
<h2 id="🤐92-암묵적-타입-변환">🤐9.2 암묵적 타입 변환</h2>
<p>표현식을 평가할 때 개발자의 의도와는 상관없이 코드의 문맥을 고려해 암묵적으로 데이터 타입을 강제 변환할 때가 있다. 문자열, 숫자, 불리언과 같은 원시 타입 중 하나로 타입을 자동 변환한다.</p>
<h3 id="921-문자열-타입으로-변환">9.2.1 문자열 타입으로 변환</h3>
<p>피연산자 중 하나 이상이 문자열이면 &#39;+&#39;연산자는 문자열 연결 연산자로 동작한다. 모든 피연산자를 문자열 타입으로 암묵적 변환시켜 하나의 문자열로 만든다. </p>
<pre><code class="language-js">1 + &#39;2&#39; // 12
`1 + 1 = ${1 + 1}` // 1 + 1 = 2

// 숫자 타입
0 + &#39;&#39; // &quot;0&quot;
-0 + &#39;&#39; // &quot;0&quot;
1 + &#39;&#39; // &quot;1&quot;
-1 + &#39;&#39; // &quot;-1&quot;
NaN + &#39;&#39; // &quot;NaN&quot;
Infinity + &#39;&#39; // &quot;Infinity&quot;
-Infinity + &#39;&#39; // &quot;-Infinity&quot;

// 불리언 타입
true + &#39;&#39; // &quot;true&quot;
false + &#39;&#39; // &quot;false&quot;

//null 타입
null + &#39;&#39; // &quot;null&quot;

//undefined 타입
undefined + &#39;&#39; // &quot;undefined&quot;

//심벌 타입
(Symbol()) + &#39;&#39; // TypeError: Cannot convert a Symbol value to a string

//객체 타입
({}) + &#39;&#39; // &quot;[Object Object]&quot;
Math + &#39;&#39; // &quot;[object Math]&quot;
[] + &#39;&#39; // &quot;&quot;
[10, 20] + &#39;&#39; // &quot;10,20&quot;
(function(){}) + &#39;&#39; // &quot;function(){}&quot;
Array + &#39;&#39; // &quot;function Array() { [native code] }&quot;</code></pre>
<h3 id="922-숫자-타입으로-변환">9.2.2 숫자 타입으로 변환</h3>
<p>산술 연산자의 역할은 숫자값을 만드는 것이다. 피연산자를 숫자타입으로 변환할 수 없는 경우에는 표현식의 결과는 NaN이 된다. 빈 문자열, 빈 배열, null, false는 0으로, true는 1로 반환된다. 객체와 빈 배열이 아닌 배열, undefined는 NaN이 반환된다.</p>
<pre><code class="language-js">//문자열 타입
+&#39;&#39; // 0
+&#39;0&#39; // 0
+&#39;1&#39; // 1
+&#39;string&#39; // NaN

//불리언 타입
+true // 1
+false // 0

//null 타입
+null // 0

//undefined 타입
+undefined // NaN

//심벌 타입
+Symbol() // TypeError: Cannot convert a Symbol value to a number

//객체 타입
+{} //NaN
+[] //0
+[10, 20] // NaN
+(function(){}) //NaN</code></pre>
<h3 id="923-불리언-타입으로-변환">9.2.3 불리언 타입으로 변환</h3>
<p>자바스크립트 엔진은 불리언 타입이 아닌 값을 Truthy값(참으로 평가되는 값) 또는 Falsy값(거짓으로 평가되는 값)으로 구분한다. 즉, 제어문의 조건식과 같이 불리언 값으로 평가되어야 할 문맥에서 Truthy값은 true로, Falsy값은 false로 변환된다. 다음 값들은 false로 평가되는 Falsy값이다.</p>
<blockquote>
<ul>
<li>false</li>
</ul>
</blockquote>
<ul>
<li>undefined</li>
<li>null</li>
<li>0, -0</li>
<li>NaN</li>
<li>&#39;&#39;(빈 문자열)
위의 값들은 isFalsy()로 실행시키면 모두 true를 반환한다.</li>
</ul>
<h2 id="👌93-명시적-타입-변환">👌9.3 명시적 타입 변환</h2>
<p>표준 빌트인 생성자 함수(String, Number, Boolean)를 사용하는 방법과 암묵적 타입 변환을 이용하는 방법 등이 있다.</p>
<h3 id="931-문자열-타입으로-변환">9.3.1 문자열 타입으로 변환</h3>
<ol>
<li>String 생성자 함수를 new 연산자 없이 호출하는 방법
 String(NaN) -&gt; &quot;NaN&quot;</li>
<li>Object.prototype.toString 메서드를 사용하는 방법
 (Infinity).toString() -&gt; &quot;Infinity&quot;</li>
<li>문자열 연결 연산자를 사용하는 방법
 true + &#39;&#39;; -&gt; &quot;true&quot;</li>
</ol>
<h3 id="932-숫자-타입으로-변환">9.3.2 숫자 타입으로 변환</h3>
<ol>
<li>Number 생성자 함수를 new연산자 없이 호출하는 방법
 Number(&#39;0&#39;); -&gt; 0</li>
<li>parseInt, parseFloat함수를 사용하는 방법(문자열만 숫자타입으로 변환가능)
 parseInt(&#39;0&#39;); -&gt; 0
 parseFloat(&#39;12.34&#39;); -&gt; 12.34</li>
<li>+단항 산술 연산자를 이용하는 방법
 +&#39;-1&#39; -&gt; -1
 +true -&gt; 1</li>
<li>*산술 연산자를 이용하는 방법
 &#39;0&#39; * 1 -&gt; 0
 false * 1 -&gt; 0</li>
</ol>
<h3 id="933-불리언-타입으로-변환">9.3.3 불리언 타입으로 변환</h3>
<ol>
<li>Boolean 생성자 함수를 new 연산자 없이 호출하는 방법
 Bollean(&#39;&#39;) -&gt; false
 Boolean(&#39;x&#39;) -&gt; true
 Boolean(&#39;false&#39;) -&gt; true
 Boolean(&#39;null&#39;) -&gt; false
 Boolean(&#39;Infinity&#39;) -&gt; true</li>
<li>!부정 논리 연산자를 두번 사용하는 방법
 !!0 -&gt; false
 !!&#39;&#39; -&gt; false
 !!{} -&gt; true
 !!NaN -&gt;false
 !!undefined -&gt;flase</li>
</ol>
<h2 id="✅94-단축-평가">✅9.4 단축 평가</h2>
<h3 id="941-논리-연산자를-사용한-단축평가">9.4.1 논리 연산자를 사용한 단축평가</h3>
<p>논리곱(&amp;&amp;) 연산자는 두 개의 피연산자가 모두 true로 평가될 때 true를 반환한다. 논리곱 연산자는 좌하에서 우항으로 평가가 진행된다.</p>
<pre><code class="language-js">&#39;Cat&#39; &amp;&amp; &#39;Dog&#39; // &quot;Dog&quot;</code></pre>
<p>첫번째 피연산자 &#39;Cat&#39;은 true로 평가된다. 하지만 두번째 피연산자를 평가하지 않으면 위의 식을 평가할 수 없다. 따라서 논리곱 연산자는 연산의 결과를 결정하는 두번째 피연산자, 즉 문자열 &#39;Dog&#39;를 그대로 반환한다.</p>
<pre><code class="language-js">&#39;Cat&#39; || &#39;Dog&#39; // &quot;Cat&quot;</code></pre>
<p>논리합(||)연산자는 두개의 피 연산자 중 하나만 true로 평가되어도 true를 반환한다. 첫번째 피연산자 &#39;Cat&#39;은 true로 평가되는데, 이 시점에서 표현식을 평가할 수 있어서 첫번째 피연산자 &#39;Cat&#39;을 그대로 반환한다.</p>
<p>논리곱(&amp;&amp;) 논리합(||) 연산자는 논리 연산의 결과를 결정하는 피연산자를 타입 변환하지 않고 그대로 반환한다. 이를 단축 평가(short-circuit evalutaion)라고 한다. 단축 평가는 표현식을 평가하는 도중에 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다. 
단축평가를 사용하면 if문을 대체할 수 있다. 조건이 Truthy값일 때는 논리곱(&amp;&amp;) 연산자로, 조건이 Falsy값일때는 논리합(||) 연산자로 if문을 대체할 수 있다.</p>
<pre><code class="language-js">let done = true;
let message = &#39;&#39;;

if (done) message = &#39;완료&#39;;
// 논리합 연산자 사용하여 if문 대체
message = done &amp;&amp; &#39;완료&#39;;

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

let done = false;
let message = &#39;&#39;;

if (!done) message = &#39;미완료&#39;;
// 논리곱 연산자 사용하여 if문 대체
message = done || &#39;미완료&#39;;</code></pre>
<p>단축평가는 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조하는 경우와 함수 매개변수에 기본값을 설정할 때 에러를 발생시키지 않게 하기 위해 유용하게 사용할 수 있다.</p>
<pre><code class="language-js">let str = null;
let value = str &amp;&amp; str.value; //null

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

function getLength(s){
  s = s || &#39;&#39;;
  return s.length;
}</code></pre>
<h3 id="942-옵셔널-체이닝-연산자">9.4.2 옵셔널 체이닝 연산자</h3>
<p>ES11에서 도입된 옵셔널 체이닝 연산자 &#39;?.&#39;는 좌항의 피연산자가 null또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 이어간다. 이전에는 논리곱(&amp;&amp;) 연산자를 사용했지만 이를 쉽게 처리할 수 있게 되었다.</p>
<pre><code class="language-js">let str = null;
let value =  str?.value;
console.log(value); //undefined;

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

let str = &#39;&#39;;
let len = str?.length;
console.log(len);//0</code></pre>
<h3 id="943-null-병합-연산자">9.4.3 null 병합 연산자</h3>
<p>ES11에서 도입된 null 병합 연산자 ??는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환한다. null 병합 연산자는 ??는 변수에 기본값을 설정할 때 유용하다. 이전에는 논리합(||)연산자를 사용하여 평가했지만 이를 쉽게 할 수 있게 되어싿.</p>
<pre><code class="language-js">let str = null ?? &#39;default str&#39;; 
console.log(str); // &quot;default str&quot;

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

let str = &#39;&#39; ?? &#39;default str&#39;;
console.log(str); // &quot;&quot;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 08장. 제어문]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-08%EC%9E%A5.-%EC%A0%9C%EC%96%B4%EB%AC%B8</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-08%EC%9E%A5.-%EC%A0%9C%EC%96%B4%EB%AC%B8</guid>
            <pubDate>Sat, 15 Oct 2022 05:30:57 GMT</pubDate>
            <description><![CDATA[<p>제어문(control flow statement)은 조건에 따라 코드 블록을 실행(조건문)하거나 반복 실행(반복문)할 때 사용한다. 제어문을 사용하면 코드의 실행 흐름을 인위적으로 제어할 수 있다. 코드는 일반적으로 위에서 아래로 순차적으로 진행되지만 제어문은 코드의 흐름을 제어해 가독성을 해치키도 한다. 이는 추후 고차함수를 통해 해결할 수 있다.</p>
<h2 id="🧱81-블록문">🧱8.1 블록문</h2>
<p>블록문(block statement/compound statement)은 0개 이상의 문을 중괄호&#39;{}&#39;로 묶은 것으로, 코드 블록 또는 블록이라고 부른다. 자바스크립트는 블록문을 하나의 실행 단위로 취업한다. 블록문의 끝에는 세미콜론을 붙이지 않는다.</p>
<h2 id="🔧82-조건문">🔧8.2 조건문</h2>
<p>조건문(conditional statement)은 주어진 조건식(condition expression)의 평가 결과에 따라 코드 블록(블록문)의 실행을 결정한다. 조건식은 불리언 값으로 평가될 수 있는 식이다.</p>
<p>if ... else문은 주어진 저건식의 평가 결과, 논리적 참 거짓에 따라 실행할 코드블록을 결정한다. 평가 결과가 true이면 if 아니면 그 다음의 else if나 else문의 코드가 실행된다. 이러한 if ... else문은 삼항 조건 연산자로도 바꿔 쓸 수 있다.</p>
<pre><code class="language-js">if (num &gt; 0) kind = &#39;양수&#39;
else if (num &lt; 0) kind = &#39;음수&#39;
else kine = &#39;0&#39;;
// 삼항연산자 변환
kind = num &gt; 0 ? &#39;양수&#39; : (num &lt; 0 ? &#39;음수&#39; : &#39;0&#39;);</code></pre>
<p>switch문은 주어진 표현식을 평가하여 그 값과 일치하는 표현식을 갖는 case 문으로 실행 흐름을 옮긴다. case문은 상황을 의미하는 표현식을 지정하고 콜론으로 마친다. 일치하는 case 문이 없다면 default문을 실행시키나, default문은 선택사항이다.</p>
<pre><code class="language-js">let num = 3;
let name;
switch (num) {
  case 1: name = &#39;one&#39;;
    break;
  case 2: name = &#39;two&#39;;
    break;
  case 3: name = &#39;three&#39;;
    break;
  default: name = &#39;other&#39;;
}
console.log(name); //three</code></pre>
<p>break문을 통해 해당 case일때 switch문을 빠져나가도록 해준다. 그렇지 않으면 항상 other이 출력되게 된다.</p>
<h2 id="🔁83-반복문">🔁8.3 반복문</h2>
<p>반복문(loop statement)은 조건식의 평가 결과가 참인 경우 코드 블록을 실행한다. 그 후 조건식을 다시 평가하여 여전히 참이면 코드 블록을 다시 실행하며 조건식이 거짓일 때까지 반복한다.</p>
<pre><code class="language-js">for (let i = 0; i &lt; 2; i++) // 변수 선언; 조건식; 증감식 / 조건식이 참이면 코드블록 실행
  console.log(i);
// 1 2
let i = 0;
while (i &lt; 2) //조건식이 참이면 코드블록 실행
  console.log(i++);
// 1 2</code></pre>
<p>위와 같이 반복문을 사용할 수 있으며 내부에 중첩하여 사용할 수도 있다. 조건식에 아무것도 없거나 항상 true인 경우 무한루프가 진행된다. 내부에서 break문이나 continue문을 사용하여 제어할 수도 있다.</p>
<h2 id="🚫84-break-문">🚫8.4 break 문</h2>
<p>break문은 레이블 문, 반복문 등의 코드 블록을 탈출한다. </p>
<pre><code class="language-js">//foo 라는 식별자가 붙은 레이블 블록문
foo: for (let i = 0; i &lt; 100; i++) {
    for (let j = 100; j &gt; 0; j--)
      if (i === j)
        break foo; // i와 j가 같아지면 foo 식별자가 붙은 for문 탈출 (바깥 for문 탈출)
}</code></pre>
<h2 id="♻️85-continue-문">♻️8.5 continue 문</h2>
<p>continue문은 반복문의 코드 블록 실행을 현 지점에서 중단하고 반복문의 증감식으로 실행 흐름을 이동시킨다. </p>
<pre><code class="language-js">for (let i = 0; i &lt; 100; i++)
{
  if (i % 2 === 0)
    continue; //짝수이면 continue에 의해 console.log를 실행시키지 않고 for문의 증감식으로 올라간다.
  console.log(i); // 홀수만 출력시키게 된다.
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 07장.  연산자]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-07%EC%9E%A5.-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-07%EC%9E%A5.-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Sat, 15 Oct 2022 04:50:57 GMT</pubDate>
            <description><![CDATA[<p>연산자는 하나 이상의 표현식을 대상으로 산술, 할당, 비교, 논리, 타입, 지수 연산 등을 수행해 하나의 값을 만든다. 피연산자는 연산의 대상이 되어야 하므로 값으로 평가할 수 있어야 한다. 연산자는 값으로 평가된 피연산자를 연산해 새로운 값을 만든다.</p>
<h2 id="➕71-산술연산자">➕7.1 산술연산자</h2>
<p>산술 연산자(arithmetic operator)는 피연산자를 대상으로 수학적 계산을 수행해 새로운 숫자 값을 만든다. 산술 연산이 불가능한 경우, NaN을 반환한다.
이항 산술 연산자는 2개의 피연산자를 산술하여 숫자 값을 만든다. 피연산자의 값을 변경하는 부수효과는 없고 새로운 값을 만들어낸다. +, -, *, /, % 등이 있다.
단항 산술 연산자는 1개의 피연산자를 산술하여 숫자값을 만든다. ++, --, +, - 등이 있다.(-는 음수 양수 변경)
문자열 연결 연산자(+)는 피연산자 중 하나 이상이 문자열인 경우 연결 연산자로 동작하여 암묵적 타입 변환을 통해 문자열로 연결하여 반환한다. 9장의 타입 변환과 단축 평가에서 추가로 살펴볼 수 있다.</p>
<h2 id="🟰72-할당-연산자">🟰7.2 할당 연산자</h2>
<p>할당 연산자(assignment operator)는 우항에 있는 피연산자의 평가 결과를 좌항에 있는 변수에 할당한다. 할당 연산자는 좌항의 변수에 값을 할당하므로 변수 값이 변하는 부수 효과가 있다.
할당문은 값으로 평가되는 표현식인 문으로서 할당된 값으로 평가된다. </p>
<h2 id="73-비교-연산자">&gt;=&lt;7.3 비교 연산자</h2>
<p>비교 연산자(comparison operator)는 좌항과 우항의 피연산자를 비교한 다음 그 결과를 불리언 값으로 반환한다. 주로 조건문에서 사용된다.
동등 비교(==) 연산자는 좌항과 우항의 피연산자를 비교할 때 먼저 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교한다. 타입이 다르더라도 암묵적 타입 변환후 같은 값이면 true를 반환하게 된다. 부동등 비교 연산자(!=)는 그 반대이다. 
일치 비교(===) 연산자는 좌항과 우항의 피연산자가 타입도 같고 값도 같은 경우에 한하여 true을 반환한다. 불일치 비교(!==) 연산자는 그 반대이다.</p>
<blockquote>
<p>NaN은 자기자신과 일치하지 않는 유일한 값이다.
숫자 0은 양과 음의 0이 있는데 true가 된다.</p>
</blockquote>
<p>대소 관계 비교 연산자는 피연산자의 크기를 비교하여 불리언 값을 반환한다. &gt;, &lt;, &gt;=, &lt;= 등이 있다.</p>
<h2 id="🥉74-삼항-조건-연산자">🥉7.4 삼항 조건 연산자</h2>
<p>삼항 조건 연산자(ternary operator)는 조건식의 평가 결과에 따라 반환할 값을 결정한다. 유일한 삼항 연산자이며, 부수효과는 없다. 다음과 같이 사용한다.</p>
<blockquote>
<p>조건식 ? 조건식이 true일 때 반환할 값 : false일 때 반환할 값
let result = score &gt;= 80 ? &#39;pass&#39; : &#39;fail&#39;;</p>
</blockquote>
<p>삼항 조건 연산자의 첫번째 피연산자는 조건식이므로 삼항 조건 연산자 표현식은 조건문이다. 또한 값으로 표현할 수 있는 표현식인 문이다. 삼항 조건 연산자 표현식은 값처럼 다른 표현식의 일부가 될 수 있어 유용하게 사용할 수 있다.</p>
<h2 id="⚔75-논리-연산자">⚔7.5 논리 연산자</h2>
<p>논리 연산자(logical operator)는 우항과 좌항의 피연산자(부정 논리 연산자의 경우 우항의 피연산자)를 논리 연산한다. 논리부정(!)연산자는 불리언 값을 반환한다. 
논리합(||) 또는 논리곱(&amp;&amp;) 연산자는 불리언 값이 아닐 수도 있으며, 언제나 2개의 피연산자 중 어느 한쪽으로 평가된다.</p>
<h2 id="🧘76-쉼표-연산자">🧘7.6 쉼표 연산자</h2>
<p>쉼표(,) 연산자는 왼쪽 피연산자로부터 차례대로 피연산자를 평가하고 마지막 피연산자의 평가가 끝나면 마지막 피연산자의 평가 결과를 반환한다.</p>
<h2 id="👨👩👧👦77-그룹-연산자">👨‍👩‍👧‍👦7.7 그룹 연산자</h2>
<p>소괄호로 피연산자를 감싸는 그룹 연산자는 자신의 피연산자인 표현식을 가장 먼저 평가한다. 따라서 그룹 연산자를 사용하여 연산자의 우선순위를 조절할 수 있다. 그룹 연산자는 연산자 우선순위가 가장 높다.</p>
<h2 id="🗂78-typeof-연산자">🗂7.8 typeof 연산자</h2>
<p>typeof 연산자는 피연산자의 데이터 타입을 문자열로 반환한다. typeof 연산자는 7가지 문자열 string, number, boolean, undefined, symbol, object, function 중 하나를 반환한다. null은 object로 반환한다. 이는 자바스크립트의 첫번째 버그이지만, 기존 코드에 영향을 줄 수 있기 때문에 수정되지 못하고 있다. 이 상황에서는 일치 연산자(===)을 활용할 수 있다. 선언하지 않은 식별자의 경우에는 undefined가 반환된다.</p>
<h2 id="📈79-지수-연산자">📈7.9 지수 연산자</h2>
<p>ES7에서 도입된 지수 연산자는 좌항의 피연산자를 밑으로, 우항의 피연산자를 지수로 거듭제곱하여 숫자값을 반환한다. 지수 연산자는 이항 연산자 중 우선순위가 가장 높다.</p>
<blockquote>
</blockquote>
<pre><code class="language-js">3 \*\* 3;      // 9
Math.pow(3,2); // 9
(-3) \*\* 3;   //9 음수를 밑으로 사용할 때는 ()로 묶어준다.
1 * 3 ** 3;    // 9</code></pre>
<h2 id="🧐710-그-외-연산자">🧐7.10 그 외 연산자</h2>
<blockquote>
<p>?. 옵셔널 체이닝 연산자
?? null 병합 연산자
delete 프로퍼티 삭제
new 생성자 함수를 호출할 때 사용하여 인스턴스를 생성
instanceof 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별
in 프로퍼티 존재 확인
위 연산자들은 9, 10 ,17, 19장 등 해당 장에서 세부적으로 살펴볼 예정이다.</p>
</blockquote>
<h2 id="🪄711-연산자의-부수효과">🪄7.11 연산자의 부수효과</h2>
<p>대부분의 연산자는 다른 코드에 영향을 주지 않는다. 하지만 할당연산자(=), 증가/감소연산자(++/--), delete 연산자는 다른 코드에 영향을 주기도 한다.</p>
<h2 id="🥇712-연산자-우선순위">🥇7.12 연산자 우선순위</h2>
<p>연산자 우선순위란 여러 개의 연산자로 이뤄진 문이 실행될 때 연산자가 실행되는 순서를 말한다. 우선순위가 높을수록 먼저 실행된다. 연산자는 종류가 많아 연산자 우선순위를 모두 기억하기 어렵고 실수하기도 쉽다. 연산자 우선순위가 가장 높은 그룹 연산자를 사용하여 우선순위를 명시적으로 조절하는 것이 좋다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/a98c0315-2b04-4db8-aacb-dee26d357ed5/image.png" alt=""></p>
<h5 id="사진-참고-httpstoma0912tistorycom66">사진 참고 <a href="https://toma0912.tistory.com/66">https://toma0912.tistory.com/66</a></h5>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 06장.  데이터 타입]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-06%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-06%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</guid>
            <pubDate>Sat, 15 Oct 2022 04:06:57 GMT</pubDate>
            <description><![CDATA[<p>c언어를 하며 다양한 타입에 대해 공부했었다. 자바스크립트는 c언어와는 조금 다른 타입 종류를 가지고 있었다.
데이터 타입은 줄여서 타입이라고 표현한다. 타입은 값의 종류를 말한다. 자바스크립트는 7개의 타입이 존재하고 원시타입과 객체타입으로 분류할 수 있다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/9e660975-60fb-4168-ac43-fb15c0ae38bc/image.png" alt=""></p>
<h2 id="🔢61-숫자-타입">🔢6.1 숫자 타입</h2>
<p>자바스크립트는 하나의 숫자타입만 존재한다. 숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다. 모든 수를 실수로 처리하며, 정수만 표현하기 위한 데이터 타입은 존재하지 않는다. 정수, 실수, 2진수, 8진수, 16진수 리터럴은 모두 64비트 부동소수점 형식의 2진수로 저장된다. 2, 8, 16진수를 표현하는 값을 참조하면 모두 10진수로 해석된다. 
또한 세가지의 특별한 값도 존재한다.</p>
<blockquote>
<ul>
<li>Infinity : 양의 무한대</li>
</ul>
</blockquote>
<ul>
<li>-Infinity : 음의 무한대</li>
<li>NaN : 산술 연산 불가(not-a-number) 
자바스크립트는 대소문자를 구분하므로 NaN을 Nan 등으로 표현하면 에러가 발생한다.</li>
</ul>
<h2 id="🔤62-문자열-타입">🔤6.2 문자열 타입</h2>
<p>문자열 타입은 9개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현할 수 있다. 문자열은 작은 따옴표, 큰 따옴표 또는 백틱(``)으로 감싼다. 일반적으로는 작은 문자열을 사용한다.
따옴표 를 사용하는 이유는 키워드나 식별자 같은 토큰과 구분하기 위해서이다. 감싸주지 않으면 스페이스와 같은 공백문자를 포함시킬 수 없다.
자바스크립트의 문자열은 원시 타입이기에 변경 불가능한 값이다. 문자열이 생성되면 그 문자열은 변경할 수 없다.</p>
<h2 id="📇63-템플릿-리터럴">📇6.3 템플릿 리터럴</h2>
<p>템플릿 리터럴은 멀티라인 문자열, 표현식 삽입, 태그드 탬플릿 등 편리한 문자열 처리기능을 제공한다. 템플릿 리터럴은 런타임에 일반 문자열로 변환되어 처리된다. 템플릿 리터럴은 일반 문자열과 비슷해 보이지만 따옴표 대신 백틱을 사용해 표현한다.
일반 문자열 내에는 개행이 허용되지 않는다. 하지만 백슬래시로 시작하는 이스케이프 시퀀스를 사용하면 개행 등을 추가할 수 있다. 또한 문자열 연산자 &#39;+&#39;를 통해 연결할 수 있다. 또한 ${}을 통해 표현식을 넣어줄 수 도 있다.</p>
<blockquote>
</blockquote>
<pre><code class="language-js">let str = `good`;
console.log(`${str} 템플릿` + &#39;리터럴&#39;); // good 템플릿리터럴</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/f5d89f3b-eca5-4899-ad47-3c7ed976630a/image.png" alt=""></p>
<h2 id="✅64-불리언-타입">✅6.4 불리언 타입</h2>
<p>불리언 타입의 값은 논리적 참, 거짓을 나타내는 true와 false 뿐이다. 조건문에서 자주 사용한다.</p>
<h2 id="🫙65-undefined-타입">🫙6.5 undefined 타입</h2>
<p>undefined 타입의 값은 Undefined가 유일하다. 선언된 변수는 암묵적으로 undefined로 초기화된다. 선언한 이후 값을 할당하지 않은 변수는 undefined가 반환된다. 자바스크립트에서는 값을 할당하지 않은 변수에 undefined 값을 할당하여 변수의 실체를 명확히한다.</p>
<h2 id="␀66-null-타입">␀6.6 null 타입</h2>
<p>null타입의 값도 null이 유일히다. 대소문자를 구별하므로 Null, NULL등과 다르다. 변수에 값이 없다는 것을 의도적으로 명시하고 싶을 때는 null을 할당해준다. 또한 이전에 사용되던 변수에 null을 할당하면 더이상 값을 참조하지 않겠다는 의미가 된다. 해당 메모리에는 가비지 컬렉션이 수행된다.
함수가 유요한 값을 반환할 수 없는 경우에도 명시적으로 null을 반환하기도 한다. 예를 들어 HTML 요소를 검색해 반환하는 document.querySelector 메서드에서 검색할 수 없는 경우 null을 반환한다.</p>
<h2 id="🔗67-심벌-타입">🔗6.7 심벌 타입</h2>
<p>심벌(symbol)은 ES6에서 추가된 7번째 타입으로, 변경 불가능한 원시 타입의 값이다. 심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다. 주로 이름이 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.</p>
<h2 id="🧺68-객체-타입">🧺6.8 객체 타입</h2>
<p>자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체이다. 이전의 6가지 데이터 타입 이외의 값은 모두 객체타입니다.</p>
<h2 id="📌69-데이터-타입의-필요성">📌6.9 데이터 타입의 필요성</h2>
<h3 id="691-데이터-타입에-의한-메모리-공간의-확보와-참조">6.9.1 데이터 타입에 의한 메모리 공간의 확보와 참조</h3>
<p>값은 메모리에 저장하고 참조할 수 있어야 한다. 메모리에 값을 저장하려면 먼저 필요한 크기를 결정하고 그만큼의 공간을 확보해야한다. 해당 크기는 데이터 타입에 의해 결정되기 때문에 데이터 타입이 중요하다. 더불어 값을 참조하는데도 저장된 메모리 공간의 선두 메모리 셀의 주소와 읽어들여야 하는 크기를 할 수 있다.</p>
<h3 id="692-데이터-타입에-의한-값의-해석">6.9.2 데이터 타입에 의한 값의 해석</h3>
<p>메모리에서 읽어들인 데이터는 2진수이며 이를 해석하기 위해 타입이 필요하다. 0100 0001의 같은 값이라도 숫자는 65, 문자열은 &#39;A&#39;로 해석이 된다.</p>
<h2 id="🔮610-동적-타이핑">🔮6.10 동적 타이핑</h2>
<h3 id="6101-동적-타입-언어와-정적-타입-언어">6.10.1 동적 타입 언어와 정적 타입 언어</h3>
<p>c나 자바 같은 정적 타입 언어는 변수를 선언할 때 변수에 할당할 수 있는 데이터 타입을 사전에 선언해야한다. 이를 명시적 타입 선언이라고 한다. 이렇게 정적 타입언어는 변수의 타입을 변경할 수 없으며, 선언한 타입에 맞는 값만 할당할 수 있다. 컴파일 시점에 타입 체크를 수행하여 에러를 발생시켜 프로그램의 실행자체를 막는다. 하여 런타임에 발생하는 에러를 줄인다.
자바스크립트는 정적 타입 언어와 달리 어떠한 타입의 값이라도 자유롭게 할당할 수 있다. 선언이 아닌 할당에 의해 타입이 결정(타입 추론)된다. 그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다. 이러한 특징을 동적 타이핑이라고 하며, 정적 타입 언어와 구분하기 위해 동적 타입 언어라고 한다.</p>
<h3 id="6102-동적-타입-언어와-변수">6.10.2 동적 타입 언어와 변수</h3>
<p>동적 타입 언어는 변수에 어떤 데이터 타입의 값이라도 자유롭게 할당할 수 있다. 그렇기 때문에 복잡한 프로그램에서는 변화하는 변수 값을 추적하기 어려울 수 있다. 또한 변수의 값을 확인하기 전까지는 타입을 확신할 수도 없다. 더불어 개발자의 의도와는 상관없이 암묵적으로 타입이 변환되기도 해서 프로그램의 오류를 발생시키기도 한다. 결국 동적 타입 언어는 유연성은 높지만 신뢰성은 떨어진다.</p>
<blockquote>
<ul>
<li>변수는 필요한 경우에 한해 제한적으로 사용한다.</li>
</ul>
</blockquote>
<ul>
<li>변수의 유효 범위(스코프)는 최대한 좁게 만들어 변수의 부작용을 줄인다.</li>
<li>전역변수는 최대한 사용하지 않는다.</li>
<li>변수보다는 상수를 사용해 값의 변경을 억제한다.</li>
<li>변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다.</li>
</ul>
<ul>
<li>컴퓨터가 이해하는 코드는 어떤 바보도 쓸 수 있다. 하지만 휼륭한 프로그래머는 사람이 이해할 수 있는 코드를 쓴다. &lt;리팩토링&gt;의 저자, 마틴 파울러</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 1일차 - Jacoste 알고리즘]]></title>
            <link>https://velog.io/@dev_kdh/TIL-1%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@dev_kdh/TIL-1%EC%9D%BC%EC%B0%A8-Jacoste-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Fri, 14 Oct 2022 06:55:34 GMT</pubDate>
            <description><![CDATA[<p>취업 준비를 시작했다.
가장 먼저 떠오른, 그리고 가장 먼저 시작한 코테...!</p>
<p>42gg 팀원들과 알고리즘 스터디팀을 만들어서 공부를 시작했다.</p>
<p>나는 아직 c에서 벗어나지 못해서 모든 코드가 c에 맞춰져 있다.
그러나 친구들과 함께 코드를 공유하면서 다양한 코드와 기능들을 보면서 배우고 있다! 신기해 신기해!!</p>
<h2 id="🪄-정규표현식-b-그리고-b">🪄 정규표현식 &#39;\b&#39; 그리고 &#39;\B&#39;</h2>
<pre><code class="language-js">str.replace(/\b[a-z]/g, (c) =&gt; c.toUpperCase());</code></pre>
<p>\b, \B는 주로 단어 검색에 유용하다. 명칭은 단어 경계(word boundary)이다.
/b는 문자(\w에 해당, 영문자, 숫자, &#39;_&#39;)와 비문자(\W에 해당) 부분의 경계를 의미한다.
띄워쓰기는 비문자에 해당하므로 /b를 사용해 단어의 경계를 정하고 원하는 결과를 만들 수 있다!!</p>
<p>\B는 비문자와 비문자 사이의 경계, 또는 문자와 문자 사이의 경계를 의미한다. 사실 찾아보니 조금 복잡해보이기도 하고, \b 이외의 상황인것 같기도하다. 좀 더 공부를 해보도 다음에 기회가 있다면 추가적으로 포스팅해야겠다.</p>
<h2 id="📈-정렬-📉">📈 정렬 📉</h2>
<p>c언어로 알고리즘 공부를 할 당시 sort함수를 구현했던 기억이 있어서 이번에도 함수를 직접 구현해서 사용해봤다.</p>
<pre><code class="language-js">arr.sort(function compare(a, b) {
    if (a &gt; b) return 1;  // 현재 상태는 오름차순
    if (a &lt; b) return -1; // +, - 를 바꾸면 내림차순
    return 0;
});</code></pre>
<p>그냥 당연히 머릿속에 떠올랐는데, 자바스크립트는 sort함수를 제공해준다. 다만 인자가 string이면 1 과 10을 구분하지 못하는 문제가 있어 이렇게 구현해준다고 한다.
그러나..!! 이 함수를 화살표 함수로 간단하게도 만들 수 있었다!</p>
<pre><code class="language-js">arr.sort((a, b) =&gt; a - b); //오름차순
arr.sort((a, b) =&gt; b - a); //내림차순</code></pre>
<p>이게 무슨 일이람...? 이거 수지팍도 지난번에 알려준 내용이다. 다들 알고 나만 몰랐네? 그러나 이번 기회에 배웠다ㅎㅎㅎㅎㅎ</p>
<h2 id="📌-나머지">📌 나머지</h2>
<p>다들 다양한 메서드 함수를 잘 사용했다. .reduce() .join(), .split() 등 많은 함수들이 있었다. 이런 기능들을 사용 해본적이 없어서 그냥 절차적으로 머릿속에 그려지는 기능들을 모두 직접 구현했었는데, 친구들을 보며 함수들 공부가 필요하다는 생각이 들었다. 부지런히 공부해야겠다!!</p>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://choonse.com/2022/06/01/1033/">https://choonse.com/2022/06/01/1033/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 05장. 표현식과 문]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-05%EC%9E%A5.-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-05%EC%9E%A5.-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8</guid>
            <pubDate>Fri, 14 Oct 2022 04:13:02 GMT</pubDate>
            <description><![CDATA[<p>개념을 이해한다는 것은 바로 용어를 정확히 이해하고 설명할 수 있다는 것이다. 용어의 의미를 정확히 설명할 수 없다면 개념을 제대로 이해하지 못한 경우가 많다. 너무 좋은 말이다. 그래서 이전까지 &#39;값&#39;이라는 용어를 많이 사용했는데 이 의미부터 확인해보고 넘어가자.</p>
<h2 id="💰51-값">💰5.1 값</h2>
<p>값(value)은 식(표현식)이 평가되어 생성된 결과를 말한다. 평가란 식을 해석해서 값을 생성하거나 참조하는 것을 의미한다. 변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙이 이름이고, 변수에 할당되는 것이 값이다. 값은 다양한 방법으로 생성할 수 있다. 가장 기본적인 방법은 리터럴을 사용하는 것이다.</p>
<h2 id="📍52-리터럴">📍5.2 리터럴</h2>
<p>리터럴(literal)은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법(notation)을 말한다. 리터럴은 사람이 이해할 수 있는 문자 또는 미리 약속된 기호로 표기한 코드이다. 런타임에 리터럴을 평가해 값을 생성한다. 다음과 같이 다양한 종류의 값을 생성할 수 있다.</p>
<blockquote>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/f3c966bb-4c73-40fd-b5b3-11ea4b9682d1/image.png" alt=""></p>
</blockquote>
<h2 id="📝53-표현식">📝5.3 표현식</h2>
<p>표현식(expression)은 값으로 평가될 수 있는 문(statement)이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다. 리터럴도 표현식이다. 표현식은 리터럴, 식별자(변수, 함수 등의 이름), 연산자, 함수 호출 등의 조합으로 이뤄질 수 있다. 다음과 같이 다양한 표현식이 있지만 값으로 평가된다는 점에서 모두 동일하다. 즉, 값으로 평가될 수 있는 문은 모두 표현식이다. 표현식과 표현식이 평가된 값은 동등한 관계, 동치라고 한다. 수식 1 + 2 = 3에서 1 + 2는 3과 동치다. </p>
<h2 id="🚪54-문">🚪5.4 문</h2>
<p>문(statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위다. 문의 집합으로 이루어진 것이 바로 프로그램이며, 문을 작성하고 순서에 맞게 나열하는 것이 프로그램이다. 문은 여러 토큰으로 구성되는데, 토큰이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 의미한다. 예를 들어 키워드, 식별자, 연산자, 리터럴, 세미콜론 등 특수기호는 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소이므로 모드 토큰이다.
문을 명령문이라고도 부른다. 문은 컴퓨터에 내리는 명령이다. 문이 실행되면 명령이 실행되고 무슨 일인가가 일어나게 된다. 문은 선언문, 할당문, 조건문, 반복문 등이 있다.</p>
<h2 id="55-세미콜론과-세미콜론-자동-삽입기능">;5.5 세미콜론과 세미콜론 자동 삽입기능</h2>
<p>세미콜론(;)은 문의 종료를 나타낸다. 즉, 자바스크립트 엔진은 세미콜론으로 문이 종료한 위치를 파악하고 순차적으로 하나씩 문을 실행한다. 따라서 문을 끝낼 때는 세미콜론을 붙여야 한다.
하지만 문의 끝에 붙이는 세미콜론은 옵션이므로 생략이 가능하다. 이는 자바스크립트엔진이 세미콜론을 자동으로 붙여주는 세미콜론 자동 삽입기능(ASI - Automatic Semicolon insertion)이 암묵적으로 수행되기 때문이다.</p>
<blockquote>
<p>이 같은 경우와 같이 제대로 동작하지 않는 경우가 있기 때문에 세미콜론을 붙이는 것이 좋다고 생각한다.</p>
</blockquote>
<pre><code class="language-js">function foo () {
  return
      {}
  // ASI =&gt; return; {};
  // 개발자 =&gt; return {};
}</code></pre>
<h2 id="56-표현식인-문과-표현식이-아닌-문">5.6 표현식인 문과 표현식이 아닌 문</h2>
<pre><code class="language-js">// 변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다.
var x;
//1, 2, 1 + 2, x = 1 + 2는 모두 표현식이다.
// x = 1 + 2는 표현식이면서 완전한 문이기도 하다.
x = 1 + 2;</code></pre>
<p>문에는 표현식인 문과 표현식이 아닌 문이있다. 표현식인 문은 값으로 평가될 수 있는 문이고, 표현식이 아닌 문은 값으로 평가될 수 없는 문이다. 표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것이다. 표현식이 아닌 문은 값으로 평가할 수 없어 변수에 할당하면 에러가 발생한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 04장. 변수]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-04%EC%9E%A5.-%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-04%EC%9E%A5.-%EB%B3%80%EC%88%98</guid>
            <pubDate>Sat, 08 Oct 2022 03:40:49 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트를 공부할 환경설정이 다 끝났다.
이제 본격적으로 언어 공부를 시작해보자.</p>
<h2 id="🔖41-변수란-무엇인가-왜-필요한가">🔖4.1 변수란 무엇인가? 왜 필요한가?</h2>
<p>다음과 같은 자바스크립트 코드를 실행하면 어떻게 동작할까?</p>
<blockquote>
<p>10 + 20</p>
</blockquote>
<p>자바스크립트 엔진이 자바스크립트 코드를 계산(평가)하려면 먼저 10, 20, + 라는 기호(리터럴, 연산자)의 의미를 알고 있어야하며, 10 + 20이라는 식(표현식)의 의미도 해석(파싱)할 수 있어야 한다.
컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다. 메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체 이다. 각 셀은 고유의 메모리 주소를 갖는다. 모든 데이터는 2진수로 처리 되고, 메모리에 저장되는 데이터는 데이터의 종류와 상관없이 모두 2진수로 저장된다.
위의 식을 연산하면 연산 결과가 필요하고 이 결과를 사용하려면 결과가 저장된 메모리 공간에 직접 접근해야한다. 하지만 메모리 주소를 통해 값에 직접 접근하는 것은 치명적 오류를 발생시킬 가능성이 높은 위험한 작업이다. 실수로 운영체제가 사용하고 있는 값을 변경하면 시스템을 멈추게 하는 치명적인 오류가 발생할 수 있다. 하여 자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.</p>
<p>프로그래밍 언어는 기억하고 싶은 값을 메모리에 저장하고, 저장된 값을 읽어 들여 재사용하기 위해 <strong><em>변수</em></strong>라는 메커니즘을 제공한다. </p>
<blockquote>
<p>변수는 하나의 값을 저장하기 위해 확보한 메모리 공간 제체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다. 값을 가리키는 상징적인 이름이다.</p>
</blockquote>
<p>변수는 프로그래밍 언어의 컴파일러 도는 인터프리터에의해 값이 저장된 메모리 공간의 주소로 치환되어 실행된다. 따라서 개발자가 직접 메모리 주소를 통해 값을 저장하고 참조할 필요가 없고 변수를 통해 안전하게 값에 접근할 수 있다. 
 처음의 코드를 변수를 사용해 작성할 수 있다.</p>
<blockquote>
<p>var result = 10 + 20</p>
</blockquote>
<p> 메모리 공간에 저장된 값을 식별할 수 있는 고유의 이름을 변수이름(<strong>변수명</strong>)이라 한다. 그리고 변수에 저장된 값을 <strong>변수 값</strong>이라고 한다. 변수에 값을 저장하는 것을 <strong>할당</strong>(대입, 저장)이라하고, 변수에 저장된 값을 읽어들이는 것을 <strong>참조</strong>라고 한다.
변수 이름을 통해 변수에 저장된 값의 의미를 명확히 알 수 있다.따라서 좋은 변수명은 가독성을 높이는 부수적인 효과가 있다.</p>
<blockquote>
<p>개발자의 의도를 나타네는 명확한 네이밍은 코드를 이해하기 쉽게 만들며, 협업과 품질 향상에 도움을 준다. 변수명은 심사숙고해서 짓도록 하자.</p>
</blockquote>
<h2 id="🔍42-식별자">🔍4.2 식별자</h2>
<p>변수 이름을 <strong>식별자</strong>라고도 한다. 식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다. 식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺으며, 이 매핑 정보도 메모리에 저장되어야 한다.
이처럼 식별자는 메모리 주소를 기억하고 있다. 메모리 주소에 붙인 이름이라고도 할 수 있다. 변수, 함수, 클래스 등의 이름은 모두 식별자이며 네이밍 규칙을 준수해야 한다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/7a98a17f-4488-4591-be28-f6eba5a269fe/image.png" alt=""></p>
<h2 id="📌43-변수-선언">📌4.3 변수 선언</h2>
<p>변수 선언(variable declaration)이란 변수를 생성하는 것이다. 값을 저장하기 위한 메모미 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 해준다.
변수를 사용하려면 반드시 선언이 필요하다. 변수를 선언할 때는 var, let, const 키워드를 사용한다.</p>
<pre><code class="language-js">var score;</code></pre>
<p>위와 같이 변수 이름을 등록하고 값을 저장할 메모리 공간을 확보한다. 확보된 메모리 공간에는 자바스크립트 엔진에 의해 undefinde라는 값이 암묵적으로 할당되어 초기화된다. 일반적으로 초기화initialization란 변수가 선언된 이후 최초로 값을 할당하는 것을 말한다.</p>
<blockquote>
<p>선언단계 : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
초기화 단계 : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefinde를 할당해 초기화한다.</p>
</blockquote>
<p>초기화 단계를 거치지 않으면 확보된 메모리 공간에는 이전에 다른 애플리케이션이 사용했던 값이 남아있을 수 있다. 이러한 값을 쓰레기 값(garbage value)라고 한다. 암묵적 초기화를 수행하므로 이러한 위험으로부터 안전한다.</p>
<p>변수를 포함한 식별자를 사용하려면 반드시 선언이 필요하다. 선언하지 않은 식별자에 접근하면 참조에러(ReferenceError)가 발생한다.</p>
<h2 id="🪄44-변수-선언의-실행-시점과-변수-호이스팅">🪄4.4 변수 선언의 실행 시점과 변수 호이스팅</h2>
<pre><code class="language-js">console.log(score); // undefined

var score; // 변수선언문</code></pre>
<p>해당 코드는 인터프리터에 의해 한 줄씩 순차적으로 실행되면서 참조에러가 발생할 것으로 보이지만, undefined가 출력된다. 그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런터임이 아니라 그 이전 단계에서 먼저 실행되기 때문이다. </p>
<p>코드를 실행하기에 앞서 먼저 소스코드의 평가과정을 거치면서 소스코드를 실행하기 위한 준비를 한다. 이때 소스코드 실행을 위한 준비 단계인 소스코드의 평가 과정에서 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내 먼저 실행한다. 그리고 소스코드의 평가 과정이 끝나면 비로소 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행한다.
즉, 변수 선언이 소스코드의 어디에 있든 상관없이 다른 코드보다 먼저 실행한다. 따라서 변수 선언이 소스코드의 어디에 위치하는지와 상관없이 어디서든지 변수를 참조할 수 있다.</p>
<p>이처럼 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 <strong>변수 호이스팅</strong>이라고 한다.</p>
<h2 id="📎45-값의-할당">📎4.5 값의 할당</h2>
<p>변수에 값을 할당할 때는 할당 연산자 &#39;=&#39;을 사용한다. 할당 연산자는 우변의 값을 좌변의 변수에 할당한다.</p>
<pre><code class="language-js">var score; //변수 선언
score = 80; //값의 할당
------------
var score = 80; // 변수 선언과 값의 할당 - 하나의 문으로 표현</code></pre>
<p>변수 선언은 소스코드가 순차적으로 실행되는 시점인 런타임 이전에 먼저 실행되지만, 값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행된다.</p>
<pre><code class="language-js">console.log(score); //undefined
var score = 80;
console.log(score); // 80</code></pre>
<h2 id="✏️46-값의-재할당">✏️4.6 값의 재할당</h2>
<p>재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것을 말한다.</p>
<pre><code class="language-js">var score = 80; // 변수 선언과 값의 할당
score = 90; // 값의 재할당</code></pre>
<p>재할당은 변수에 저장된 값을 다른 값으로 변경한다. 그래서 변수라고 하는 것이다. 만약 값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없다면 변수가 아니라 상수라한다. 상수는 한번 정해지면 변하지 않는 값이다. 다시 말해 상수는 단 한 번만 할당할 수 있는 변수다.</p>
<blockquote>
<p>const키워드를 사용해 선언한 변수는 재할당이 금지된다. 즉, const 키워드는 단 한 번만 할당할 수 있는 변수를 선언한다. 따라서 const키워드를 사용하면 상수를 표현할 수 있다.</p>
</blockquote>
<p>변수에 값을 재할당하면 score 변수의 값은 이전 값 80에서 재할당한 값 90으로 변경된다. 처음 값을 할당했을 때와 마찬가지로 이전 값 80이 저장되어 있던 메모리에 90을 새롭게 저장하는 것이 아니라, 새로운 메모리 공간을 확보하고 그 메모리 공간에 숫자 값 90을 저장한다. 이전의 undefined와 80은 더이상 필요하지 않아 가비지 콜렉터에 의해 메모리에서 자동 해제된다.</p>
<h2 id="📝47-식별자-네이밍-규칙">📝4.7 식별자 네이밍 규칙</h2>
<blockquote>
<p>식별자는 특수문자를 제외한 문자, 숫자, 언더스코더, 달러 기호를 포함할 수 있다.
단, 식별자는 특수문자를 제외한 문자, 언더스코어, 달러 기호로 시작해야한다. 숫자로 시작하는 것은 허용하지 않는다.
예약어는 식별자로 사용할 수 없다. 예약어는 프로그래밍 언어에서 사용되고 있거나 사용될 예정인 단어이다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/7beb67bd-3dbf-4b26-ab4c-2ff8dcc4d267/image.png" alt=""></p>
</blockquote>
<p>변수는 쉼표(,)로 구분하여 하나의 문에서 여러 개를 한번에 선언할 수 있다. 하지만 가독성이 나빠지므로 권장하지 않는다. 또한 ES5부터 유니코드 문자를 허용하지만, 알파벳 외의 유니코드 문자로 명명된 식별자를 사용하는 것은 바람직하지 않아 권장하지 않는다.
자바스크립트는 대소문자를 구분하므로 대소문자가 다른 변수는 별개의 변수이다. 또한 변수명은 변수의 존재 목적을 쉽게 이해할 수 있도록 의미를 명확히 표현해야 한다. 변수 선언에 별도의 주석이 필요하다면 변수의 존재 목적을 명확히 드러내지 못하는 것이다.
네이밍 컨벤션은 하나 이상의 영어단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 구칙이다.</p>
<pre><code class="language-js">var firstName; // camelCase
var first_name; // snake_case
var FirstName; // PascalCase
var strFirstName; // typeHungarianCase</code></pre>
<p>일반적으로 변수나 함수의 이름에는 카멜케이스를, 생성자 함수, 클래스의 이름에는 파스칼 케이스를 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[42gg] AWS 도메인 연결하기]]></title>
            <link>https://velog.io/@dev_kdh/42gg-AWS-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_kdh/42gg-AWS-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 30 Sep 2022 01:20:54 GMT</pubDate>
            <description><![CDATA[<p>42gg의 마지막 단계는 도메인과 서버를 연결하여 접속할 수 있도록 만들어주는 단계다.
처음 접하는 개념들이고 처음해보는 상태라 일단 쭉 따라가보면서 서버를 연결해보았다.</p>
<hr>
<h2 id="📁-ec2-인스턴스-생성">📁 EC2 인스턴스 생성</h2>
<p>EC2는 Elastic Compute Cloud의 약자로 AWS에서 제공하는 클라우드 컴퓨팅 서비스다.
이 서비스를 통해서 아마존이 각 세계에 구축한 데이터 센터의 서버용 컴퓨터들의 자원을 원격으로 사용할 수 있다.
EC2의 특징은 다음과 같다.</p>
<blockquote>
<p>용량을 늘리거나 줄일 수 있다. (탄력성)
 사용한만큼 지불하므로 저렴하다.
 사용자가 인스턴스를 완전히 제어할 수 있다.
 보안 및 네트워크 구성, 스토리지 관리 효과적이다.</p>
</blockquote>
<h3 id="1-인스턴스-이름-설정">1. 인스턴스 이름 설정</h3>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/4a0dae15-7fa7-4b65-a67f-eb868dc76e2e/image.png" alt=""></p>
<h3 id="2-인스턴스-유형-설정">2. 인스턴스 유형 설정</h3>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/d568b624-f150-48e9-b14d-4cacef046011/image.png" alt=""></p>
<h3 id="3-키페어-생성">3. 키페어 생성</h3>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/be3710c1-bf84-4805-aecd-b8c274b5fcd5/image.png" alt=""></p>
<h3 id="4-네트워크-설정">4. 네트워크 설정</h3>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/0141427a-f6c9-4487-8001-916c79c3b6b5/image.png" alt=""></p>
<p>모든 설정이 끝나면 인스턴스 시작을 눌러 인스턴스를 생성해준다. 생성된 인스턴스는 인스턴스 페이지에서 확인할 수 있다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/896c6e05-2b35-415b-bfac-062514061a35/image.png" alt=""></p>
<p>그 후 인스턴스에게 탄력적 IP를 생성해주어야 한다. 왼쪽의 탄력적 IP주소 할당을 통해 새 IP를 할당해 놓은 후, 만들어준 인스턴스에 들어가서 탄력적 IP주소를 연결해준다. 이 후 이 아이피 주소를 AWS도메인 연결에 사용할 수 있다.</p>
<hr>
<h2 id="🗃-route53-호스팅-영역">🗃 Route53 호스팅 영역</h2>
<p>Route53이란 AWS에서 제공하는 DNS(Domain Name Service)이다. Route53은 이외에도 모니터링, L4(SLB), GSLB(Global Server Load Balancing) 등의 기능을 부가적으로 제공한다.</p>
<h3 id="1-호스팅-영역-생성">1. 호스팅 영역 생성</h3>
<p>도메인 이름에 구매한 도메인 주소를 입력한 후 퍼블릭 호스팅 영역으로 설정 후 아래쪽에 ‘호스팅 영역 생성&#39; 버튼으로 이동한다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/3b6e3c8c-aa25-439b-932d-f64429af489b/image.png" alt=""></p>
<h3 id="2-네임서버-변경">2. 네임서버 변경</h3>
<p>고데디페이지 내 제품으로 이동 후 구매한 도메인 리스트에서 DNS관리로 들어간다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/b46ac356-5df0-4b98-8924-36e0d14a6a00/image.png" alt=""></p>
<p>네임서버를 찾아 변경을 누르면 아래와 같은 창이 뜨고, ‘내 자신의 네임서버 입력(고급)’을 클릭하여 이동한다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/af1b5d73-9bc1-4a0c-be15-4738a037fc3a/image.png" alt=""></p>
<p>내 고유 네임서버 입력 창에서 네임서버 추가를 눌러 ns값 4개를 입력해준다(마지막에 붙어있는 ‘.’은 제거하고 입력. 두번째 사진에서 ns값 확인할 수 있다.). 입력 되면 기존의 네임서버에 추가된 4개로 변경이 된다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/3d341239-1e28-4aaa-ab99-20cbc37a1c4f/image.png" alt=""></p>
<p>레코드 세트 중 사진에 표시된 것과 같이 ns로 시작하는 값 4개를 복사하여 고데디 네임서버 변경 창에 추가해준다. 
<img src="https://velog.velcdn.com/images/dev_kdh/post/29672abd-7d0a-45aa-a61b-e12e4f6f8b76/image.png" alt=""></p>
<h3 id="3-레코드-생성">3. 레코드 생성</h3>
<p>AWS 페이지에서 래코드 생성을 눌러 A유형(EC2의 IP와 도메인을 연결)을 추가해준다. 아래 창에 EC2의 탄력적 IP주소를 입력하고 레코드 생성을 해준다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/0f72465c-d621-4f65-9cc2-2753639ce1c0/image.png" alt=""></p>
<p>A유형을 추가하고 나서 CNAME을 추가한다. 레코드 생성을 누르고 유형을 CNAME으로 변경 후 EC2에서 퍼블릭IPv4 DNS값을 입력해준다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/f853c5a6-a64f-4933-a6b9-bc6ec10e2729/image.png" alt=""></p>
<h3 id="4-s3-버킷-만들기">4. S3 버킷 만들기</h3>
<p>Amazon S3란, Simple Storage Service의 약자로 인터넷용 스토리지이다.
REST 인터페이스를 통해 저장, 삭제, 조회가 가능하고 주로 이미지 파일, 정적 리소스 등을 S3에 올려놓고 사용한다. 내구성이 좋아 데이터 유실 가능성이 거의 없다고 한다.</p>
<blockquote>
<ol>
<li>일반 구성 : 이름을 도메인 네임으로 설정, 리전은 서울로 설정<ol start="2">
<li>객체 소유권 : ACL비활성화</li>
<li>퍼블릭 액세스 차단 설정 체크 해제</li>
<li>버전관리 및 기본 암호화 비활성화</li>
</ol>
</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/dev_kdh/post/5d452394-747e-48f2-b021-473b31fd25ad/image.png" alt=""></p>
<p>버킷을 만들었다면 버킷에 들어가 정책을 생성해주자.</p>
<blockquote>
<p><a href="https://zzang9ha.tistory.com/358">https://zzang9ha.tistory.com/358</a>
해당 사이트를 참고하여 정책을 생성했다. 마지막 부분에서 문제가 자꾸 발생했는데, *로 입력하고 정책 저장 전 ARN으로 수정해주면 잘 된다.</p>
</blockquote>
<hr>
<p>여기까지 왔다면 드디어 서버 올리고 배포하면 된다.</p>
<h2 id="📨-배포하기">📨 배포하기</h2>
<h3 id="1-파일-빌드하기">1. 파일 빌드하기</h3>
<blockquote>
<p>npm run build</p>
</blockquote>
<p>client에서 만들어놓은 파일들을 버킷에 올려야한다. 그 전에 빌드를 해준다.</p>
<h3 id="2-s3-버킷에-업로드하기">2. S3 버킷에 업로드하기</h3>
<p>위에서 생성해준 S3버킷에 들어가면 파일을 업로드 할 수 있게 된다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/a9441967-d3b5-4525-ac98-10daacdb1f12/image.png" alt="">
버킷 내부로 들어오면 다음 사진과 같은 페이지가 뜬다. 현재 페이지에서 업로드해주면 된다.
NextJs를 사용하는 경우 빌드하면 out폴더가 생성되는데, 해당 폴더 내부의 모든 파일을 업로드해준다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/d645dac5-933a-4ebc-b5cd-802c292215d4/image.png" alt="">
지금은 파일이 업로드 되어 있는 상태이며, 업데이트 시 모든 파일을 삭제하고 다시 업로드해주면 된다.</p>
<blockquote>
<p>삭제하면 되돌릴 수 없기 때문에 꼭꼭 다시 한 번 확인하도록 하자.</p>
</blockquote>
<p>파일을 업로드 했는데도 서버에 적용이 안 되는 경우가 있다. CDN(Content delivery network) 때문인데, 그럴 때 아래 단계를 거치면 된다.</p>
<h3 id="4-cloudfront-무효화">4. CloudFront 무효화</h3>
<p>CloudFront의 배포 페이지에 들어가보면 위에서 배포해놓은 리스트가 뜬다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/853dea6c-55f5-4da9-86b2-a31976c1717a/image.png" alt=""></p>
<p>무효화할 ID를 선택한 뒤 무효화 탭으로 들어가 무효화를 진행해준다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/394da0a5-987b-403f-8c00-34d76172930a/image.png" alt=""></p>
<p>모든 파일에 대해 무효화를 생성할 것이기 때문에 아래와 같이 /*을 입력한 뒤 &#39;무효화 생성&#39; 버튼을 클릭한다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/928650a5-ca2f-4041-b826-b8ee617422aa/image.png" alt=""></p>
<p>마지막으로 해당 ID의 설정은 다음과 같이 편집해주었다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/91644054-5994-4a6f-8bf4-e11e16e72299/image.png" alt=""></p>
<p>난생 처음으로 프로젝트에 참여했고, 프론트 개발을 해봤고, 서버까지 올리고 배포해보았다. 아직 뒤죽박죽 정리가 되지 않은 느낌이 있어 공부의 필요성이 많이 느껴진다. 얼른 익숙해질 수 있도록 해야겠다.</p>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://seoyeonhwng.medium.com/aws-ec2%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-acf6b7041908">https://seoyeonhwng.medium.com/aws-ec2%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-acf6b7041908</a></li>
<li><a href="https://zzang9ha.tistory.com/358">https://zzang9ha.tistory.com/358</a></li>
<li><a href="https://velog.io/@tamagoyakii/AWS-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%84%9C%EB%B2%84-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8%ED%95%98%EA%B8%B0">https://velog.io/@tamagoyakii/AWS-클라이언트-서버-업데이트하기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MSA] MicroService Architecture]]></title>
            <link>https://velog.io/@dev_kdh/MSA-MicroService-Architecture</link>
            <guid>https://velog.io/@dev_kdh/MSA-MicroService-Architecture</guid>
            <pubDate>Mon, 22 Aug 2022 12:49:36 GMT</pubDate>
            <description><![CDATA[<p>프로젝트-X 두번째 멘토링에서 MSA에 대해 짧은 세미나가 진행될 예정이다. 
하여 조금이나마 예습을 해보고 참여를 하려고 한다.</p>
<h2 id="📌-msamicroservice-architecture">📌 MSA(MicroService Architecture)</h2>
<p>MSA는 하나의 큰 애플리케이션을 여러 개의 작은 애플리케이션으로 쪼개어 변경과 조합이 가능하도록 만든 형태를 말한다. </p>
<h3 id="✅-msa의-등장---monolithic-architecture">✅ MSA의 등장 -&gt; Monolithic Architecture</h3>
<p>모놀리식 아키텍처는 마이크로서비스(MSA) 아키텍처에 반대되는 개념으로, 애플리케이션의 모든 구성 요소가 한 프로젝트에 통합되어 있는 형태를 말한다. 웹 개발을 예로 들면 웹 프로그램을 개발하기 위해 모듈별로 개발을 하고, 개발이 완료된 웹 어플리케이션을 하나의 결과물로 패키징하여 배포되는 형태를 말한다. 이런 어플리케이션을 모놀리식 어플리케이션이라 하며, 웹의 경우 WAR파일로 빌드되어 WAS에 배포하는 형태를 말한다. 주로 소규모 프로젝트에서 사용된다.</p>
<p>아직 많은 소프트웨어가 Monolithic 형태로 구현되어 있고, 소규모 프로젝트에는 Monolithic Architecture가 훨씬 합리적입니다. 간단한 Architecture이고, 유지보수가 용이하기 때문이다.</p>
<p>하지만 일정 규모 이상의 서비스, 혹은 수백명의 개발자가 투입되는 프로젝트에서 Monolithic Architecture은 뚜렷한 한계가 있다.</p>
<ul>
<li><p>부분 장애가 전체 서비스의 장애로 확대될 수 있다. 
개발자의 잘못된 코드 배포 또는 갑작스런 트래픽 증가로 인해 성능에 문제가 생겼을 때, 서비스 전체의 장애로 확대될 수 있다.</p>
</li>
<li><p>부분적인 *Scale-out(여러 server로 나누어 일을 처리하는 방식)이 어렵다.
Monolithic Architecture에서는 사용되지 않는 다른 모든 서비스가 Scale-out되어야 하기 때문에 부분 Scale-out이 어렵다.</p>
</li>
</ul>
<ul>
<li>서비스의 변경이 어렵고, 수정 시 장애의 영향도 파악이 힘들다. 
여러 컴포넌트가 하나의 서비스에 강하게 결합되어 있기 때문에 수정에 대한 영향도 파악이 힘들다.</li>
</ul>
<ul>
<li>배포 시간이 오래 걸린다. 
최근 어플리케이션 개발 방법은 CI/CD를 통한 개발부터 배포까지 빠르게 반영하는 추세이다. 그러나 규모가 커짐에 따라 작은 변경에도 높은 수준의 테스트 비용이 발생하기도 하며, 많은 사람이 하나의 시스템을 개발하여 배포하기 때문에 영향을 줄 수 밖에 없다.</li>
</ul>
<ul>
<li>한 Framework와 언어에 종속적이다.
Spring framework를 사용할 경우, blockchain 연동 모듈을 추가할 때 node.js를 사용하는 것이 일반적이며 강세이다. 그러나 java를 이용하여 해당 모듈을 작성할 수 밖에 없다. 선정했던 framework가 Spring이기 때문이다.</li>
</ul>
<p>이러한 Monolithic Architecture의 문제점들을 보완하기 위해 MSA가 등장하게 되었다. 기존의 특정한 물리적인 서버에 서비스를 올리던 on-promise 서버 기반의 Monolithic Architecture에서 이제는 클라우드 환경을 이용하여 서버를 구성하는 MicroService Architecture로 많은 서비스들이 전환되고 있다. </p>
<br>

<h3 id="✅-msa의-특징">✅ MSA의 특징</h3>
<p>MSA는 API를 통해서만 상호작용할 수 있다. 즉, 마이크로 서비스는 서비스의 end-point(접근점)을 API 형태로 외부에 노출하고, 실질적인 세부 사항은 모두 추상화한다. 내부의 구현 로직, 아키텍처와 프로그래밍 언어, 데이터베이스, 품질 유지 체계와 같은 기술적인 사항들은 서비스 API에 의해 철저하게 가려진다. </p>
<p>제대로 설계 된 마이크로서비스는 하나의 비즈니스 범위에 맞춰 만들어지므로 하나의 기능만 수행한다. 즉, 어플리케이션 출시처럼 하나의 목표를 향해 일하지만 자기가 개발하는 서비스만 책임진다. 그리고 여러 어플리케이션에서 재사용할 수 있어야 한다.</p>
<p>어플리케이션은 항상 기술 중립적 프로토콜을 사용해 통신하므로 서비스 구현 기술과는 무관하다. 따라서 마이크로서비스 기반의 어플리케이션을 다양한 언어와 기술로 구축할 수 있다는 것을 의미한다. </p>
<p>마이크로서비스는 SOA에서 사용되는 집중화된 관리 체계를 사용하지 않는다. 마이크로서비스 구현체의 공통적인 특징 중 하나는 ESB(Enterprise Service Bus)와 같은 무거운 제품에 의존하지 않는다는 점이다. REST 등 가벼운 통신 아키텍처, 또는 Kafka 등을 이용한 message stream을 주로 사용한다. </p>
<h3 id="✅-msa의-장점">✅ MSA의 장점</h3>
<ul>
<li><p>배포(deployment) 관점
서비스 별 개별 배포가 가능하다.(배포 시 전체 서비스의 중단이 없음)
요구사항을 신속하게 반영하여 빠르게 배포할 수 있다.</p>
</li>
<li><p>확장(scaling) 관점
특정 서비스에 대한 확장성이 용이하다.
클라우드 사용에 적합한 아키텍쳐이다.</p>
</li>
<li><p>장애(failure) 관점
장애가 전체 서비스로 확장될 가능성이 적다.
부분적 장애에 대한 격리가 수월하다.</p>
</li>
<li><p>이외에도, 신기술의 적용이 유연하고, 서비스를 polyglot하게 개발/운영 할 수 있다.</p>
<br>

</li>
</ul>
<h3 id="✅-msa의-단점">✅ MSA의 단점</h3>
<p>전체 서비스/프로젝트가 커질수록 복잡도가 기하급수적으로 늘어날 수 있다.</p>
<ul>
<li>성능 - 서비스 간 호출 시 API를 사용하기 때문에 통신 비용이나 Latency가 늘어나게 된다.</li>
<li>테스트 / 트랜잭션 - 서비스가 분리되어 있기 때문에 테스트와 트랜잭션의 복잡도가 증가하고 많은 자원을 필요하게 된다.</li>
<li>데이터 관리 - 데이터가 여러 서비스에 걸쳐 분산되기 때문에 한번에 조회하기 어렵고 데이터의 정합성 또한 관리하기 어렵다.</li>
</ul>
<br>

<p>MSA 공부해야할 부분이 많았다. 좀 더 상세한 내용들은 참고페이지를 보도록하자..!!</p>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://wooaoe.tistory.com/57">https://wooaoe.tistory.com/57</a></li>
<li><a href="https://velog.io/@tedigom/MSA-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-MSA%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-3sk28yrv0e">https://velog.io/@tedigom/MSA-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-1-MSA%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-3sk28yrv0e</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 03장. 자바스크립트 개발 환경과 실행 방법]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-03%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD%EA%B3%BC-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-03%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD%EA%B3%BC-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 20 Aug 2022 09:09:35 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트로 개발하기 위해 환경을 구축해두어야한다. 지금부터 간단하게 살펴보도록 하자!</p>
<h2 id="🛠-31-자바스크립트-실행-환경">🛠 3.1 자바스크립트 실행 환경</h2>
<p>모든 브라우저는 자바스크립트를 해석하고 실행할 수 있는 자바스크립트 엔진을 내장하고 있다. Node.js도 브라우저와 동일하게 동작한다. 다만 Node.js는 ECMAScript 이외에 추가로 제공하는 기능은 호환되지 않는다.    브라우저는 HTML, CSS, 자바스크립트를 실행해 웹페이지를 브라우저 화면에 렌더링 하는 것이 주 목적이지만, Node.js는 브라우저 외부에서 자바스크립트 실행 환경을 제공하는 것이 주 목적이기 때문이다.
브라우저는 클라이언트 사이드 Web API를 지원한다. Node.js는 ECMAScript와 Node.js 고유의 API를 지원한다. 이를 기반으로 자바스크립트 개발 환경을 구축하고 자바스크립트를 실행하는 방법을 확인한다. 브라우저 환경, Node.js 환경에서 실행하는 방법 등을 확인해보자!</p>
<blockquote>
<ul>
<li>웹크롤링 : 서버에서 웹사이트의 콘텐츠를 수집하기 위해 웹사이트에서 HTML 문서를 가져온 다음, 이를 가공해서 필요한 데이터만 추출하는 경우가 있다. 이를 웹 크롤링이라 한다. -&gt; 브라우저는 파싱된 HTML 요소를 선택하거나 조작하는 기능을 제공해준다(DOM API).</li>
</ul>
</blockquote>
<h2 id="🌐-32-웹-브라우저">🌐 3.2 웹 브라우저</h2>
<h3 id="✅-321-개발자-도구">✅ 3.2.1 개발자 도구</h3>
<p>브라우저가 제공하는 개발자 도구는 웹 애플리케이션 개발에 필수적인 도구이다. 단축키를 통해 열 수 있다.</p>
<blockquote>
<ul>
<li>윈도우 : F12 또는 Ctrl + Shift + I</li>
</ul>
</blockquote>
<ul>
<li>macOS : command ⌘ + option ⌥ + I </li>
</ul>
<p>개발자 도구는 웹 개발에 유용하고 다양한 기능을 제공해준다.</p>
<blockquote>
<ul>
<li>Elements : 로딩된 웹페이지의 DOM과 CSS를 편집하여 렌더링된 뷰를 확인해 볼 수 있다. 단, 편집한 내용이 저장되지는 않는다. 웹페이지가 의도된 대로 렌더링되지 않았다면 이 패널을 확인하여 힌트를 얻을 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>Console : 로딩된 웹페이지의 에러를 확인하거나 자바스크립트 소스코드에 작성한 console.log메서드의 실행 결과를 확인할 수 있다.</li>
<li>Sources : 로딩된 웹페이지의 자바스크립트 코드를 디버깅할 수 있다.</li>
<li>Network : 로딩된 웹페이지에 관련된 네트워크 요청 정보와 성능을 확인할 수 있다.</li>
<li>Application : 웹 스토리지, 세션, 쿠키를 확인하고 관리할 수 있다.</li>
</ul>
<h3 id="✅-322-콘솔">✅ 3.2.2 콘솔</h3>
<p>개발자 도구의 Console패널은 자바스크립트 코드에서 에러가 발생해 애플리케이션이 정상적으로 동작하지 않을 때 가장 우선적으로 살펴야 하는 곳이다. 에러가 아니더라도 콘솔은 매우 유용한다. 구현 단계에서 디버깅을 실행하는 것보다 간편하게 코드의 실행결과를 확인하면서 개발을 진행하기 위해 콘솔을 사용하는 경우가 많다. 
콘솔은 자바스크립트 코드를 입력해 그 결과를 확인할 수 있는 REPL(Read Eval Print Loop: 입력 수행 출력 반복) 환경으로 사용할 수도 있다. 여러줄을 입력하려면 Shift키를 누른상태에서 엔터를 치면 여러줄 입력이 가능하다.</p>
<h3 id="✅-323-브라우저에서-자바스크립트-실행">✅ 3.2.3 브라우저에서 자바스크립트 실행</h3>
<p>브라우저는 HTML 파일을 로드하면 script 태그에 포함된 자바스크립트 코드를 실행한다. 만약 자바스크립트 코드 내에서 콘솔메서드(console.log())가 호출되었다면 콘솔에 실행결과가 출력될 것이다.</p>
<h3 id="✅-324-디버깅">✅ 3.2.4 디버깅</h3>
<p>개발자 도구에는 자바스크립트 코드를 디버깅할 수 있는 Sources 패널이 존재한다. 에러가 발생하면 그 위치에 빨간 밑줄이 표시되고, 그 위에 마우스를 올려보면 에러 정보가 표시된다. 해당 에러 정보를 통해 에러를 찾고 수정할 수 있다.</p>
<h2 id="🎛-nodejs">🎛 Node.js</h2>
<p>클라이언트 사이드, 즉 브라우저에서 동작하는 간단한 웹 애플리케이션은 브라우저만으로도 개발할 수 있다. 하지만 프로젝트의 규모가 커지면 React, Angular, Lodash와 같은 프레임워크나 라이브러리를 도입하고, Babel, Webpack, ESLint등의 도구를 사용하게 된다. 이때 Node.js와 npm이 필요하다.</p>
<h3 id="🌱-331-nodejs--npm">🌱 3.3.1 Node.js &amp; npm</h3>
<p>2009년 발표한 Node.js는 크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경이다. 브라우저에서만 동작하던 자바스크립트를 브라우저 이외의 환경에서 동작시킬 수 있는 자바스크립트 실행 환경이 Node.js이다.
npm(node package manager)은 자바스크립트 패키지 매니저이다. Node.js에서 사용할 수 있는 모듈들을 패키지화해서 모아둔 저장소 역할과 패키지 설치 및 관리를 위한 CLI를 제공한다. </p>
<h3 id="🌱-332-nodejs-설치">🌱 3.3.2 Node.js 설치</h3>
<p>Node.js의 웹사이트(<a href="http://nodejs.org)%EC%97%90">http://nodejs.org)에</a> 접속하여 설치할 수 있다.
LTS버전은 장기적으로 안정된 지원이 보장된다. 반변 Current버전은 최신 기능을 제공하지만 업데이트가 발생하는 버전으로 안정적이지 않을 수 있다. 실제 개발 환경이라면 LTS 버전을 설치하는 것이 좋다.</p>
<h3 id="🌱-333-nodejs-repl">🌱 3.3.3 Node.js REPL</h3>
<p>Node.js가 제공하는 REPL을 사용하면 간단한 자바스크립트 코드를 실행해 결과를 확인해 볼 수 있다. 프롬프트가 &#39;&gt;&#39;로 변경되면 자바스크립트 코드를 실행해볼 수 있다. 터미널에서도 확인할 수 있다. Ctrl + C 키를 두 번 입력하면 Node.js가 종료된다.</p>
<br>
<br>
- vs코드는 생략.. ㅎㅎ


]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 02장. 자바스크립트란??]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-02%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-02%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Sat, 20 Aug 2022 04:45:49 GMT</pubDate>
            <description><![CDATA[<p>모든 공부는 기초가 잘 되어있어야 한다. 프론트엔드의 기초. 기본 언어인 자바스크립트에 대해 알아가보도록 하자.</p>
<h2 id="21-자바스크립트의-탄생">2.1 자바스크립트의 탄생</h2>
<p>1995년, 시장 점유율 90%를 차치하고 있던 넷스케이프 커뮤니케이션즈에서 웹페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는 경량 프로그래밍 언어를 도입하기로 결정한다. 이때 탄생한 것이 바로 브랜던 아이크가 개발한 자바스크립트이다.</p>
<h2 id="22-자바스크립트의-표준화">2.2 자바스크립트의 표준화</h2>
<p>1996년 8월, MS에서 자바스크립트의 파생버전인 JScript를 인터넷 익스플로러(v3.0)에 탑재한다. 이후 두 회사는 자사 브라우저에서만 동작하는 기능을 추가하기 시작한다. 이로 인해 브라우저에 따라 웹페이지가 정상적으로 동작하지 않는 <strong>크로스 브라우징 이슈</strong>가 발생하게 되고, 모든 브라우저에서 정상적으로 동작하는 웹페이지를 개발하기가 어려워졌다.
이런 문제점 때문에 표준화된 자바스크립트의 필요성이 대두되고 1997년 7월 컴퓨터 시스템의 표준을 관리하는 비영리 표준화 기구인 ECMA 인터내셔널에서 표준화된 자바스크립트 초판(ECMAScript 1)이 출시된다. 이후 여러 번화를 거쳐가며 범용 프로그래밍 언어로 거듭나게 된다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/d872ddfd-3c3f-4ee6-ba33-1b42fadf7255/image.png" alt=""></p>
<h2 id="23-자바스크립트의-역사">2.3 자바스크립트의 역사</h2>
<p>초창기 자바스크립트는 웹페이지의 보조적인 기능을 수행하기 위해 한정적인 용도로만 사용되었다. 대부분의 로직은 주로 웹 서버에서 실행되었고, 브라우저는 서버로부터 전달받은 HTML과 CSS를 단순히 헨더링하는 수준이었다.</p>
<blockquote>
<p>렌더링이란 HTML, CSS, 자바스크립트로 작성된 문서를 해석하여 브라우저에 시각적으로 출력하는 것을 말한다. 또는 서버에서 데이터를 HTML로 변환하여 브라우저로 전달하는 과정(SSR)을 가리키기도 한다.</p>
</blockquote>
<h3 id="✅-231-ajax">✅ 2.3.1 Ajax</h3>
<p>1999년, 자바스크립트를 이용해 서버와 브라우저가 비동기방식으로 데이터를 교환할 수 있는 통신기능인 AJAX가 XMLHttpRequest라는 이름으로 등장했다.
이전 웹페이지는 완전한 HTML코드를 서버로부터 전송받아 웹페이지 전체를 렌더링하는 방식으로 동작했다. 이런 방식은 변경할 필요가 없는 부분까지 렌더링하게 되며 화면이 순간적으로 깜빡이기도 한다. 어쩔 수 없는 한계로 받아지는 부분이었지만, AJAX의 출현으로 이를 해결할 수 있게 된다.
Ajax는 웹 페이지 전체를 렌더링하지 않고, 필요한 부분만 서버로부터 데이터를 전송받아 렌더링 하게 해준다. Ajax를 이용하면 백그라운드 영역에서 서버와 통신하여, 그 결과를 웹 페이지의 일부분에만 표시할 수 있다.</p>
<h3 id="✅-232-jquery">✅ 2.3.2 jQuery</h3>
<p>2006년 jQuery이 출시됐다. 제이쿼리는 자바스크립트 언어를 간편하게 사용할 수 있도록 단순화시킨 오픈 소스 기반의 자바스크립트 라이브러리로 DOM을 쉽게 제어할 수 있게 해준다. 덕분에 크로스 브라우징 이슈도 어느정도 해결할 수 있게 되었다.</p>
<blockquote>
<p>DOM이란 문서 객체 모델(DOM, Document Object Model)로 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스다. 이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법을 제공해준다.</p>
</blockquote>
<h3 id="✅-233-v8-자바스크립트-엔진">✅ 2.3.3 V8 자바스크립트 엔진</h3>
<p>구글 맵스를 통해 웹 애플리케이션 프로그래밍 언어로서의 가능성이 확인되면서, 더욱 빠르게 동작하는 자바스크립트 엔진의 필요성이 대두되었고 2008년 V8엔진이 등장한다.
V8은 구글이 도입한 오픈소스 자바스크립트 엔진이다. C++로 작성되었으며 구글 크롬, 크로미움 웹 브라우저, NodeJS를 지원한다. 환경과 상호작용하고 프로그램을 실행하기 위한 바이트코드를 생성하는 역할을 담당한다. 처음 V8은 웹 브라우저의 성능 향상 메커니즘으로 도입되었으며 시간이 지나면서 다른 엔진보다 훨씬 향상된 인터프리터가 되었다.
V8의 등장으로 자바스크립트는 데스크톱 애플리케이션과 유사한 사용자 경험을 제공할 수 있는데 웹 애플리케이션 프로그래밍 언어로 정착하게 된다.</p>
<h3 id="✅-234-nodejs">✅ 2.3.4 Node.js</h3>
<p>Node.js는 2009년 구글 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경이다. 브라우저의 자바스크립트 엔진에서만 동작하던 자바스크립트를 브라우저 이외의 환경에서도 동작할 수 있도록 자바스크립트 엔진을 브라우저에서 독립시켰다. 주로 서버 사이드 애플리케이션 개발에 사용되며, 이에 필요한 모듈, 파일시스템, http 등 빌트인 API를 제공한다.
Node.js는 비동기 I/O를 지원하며 단일 스레드 이벤트 루프 기반으로 동작하여 요청 처리 성능이 좋다. 따라서 데이터를 실시간으로 처리하기 위해 I/O가 빈번히 발생하는 SPA에 적합니다.</p>
<blockquote>
<p>서버 사이드 렌더링(SSR) &amp; 클라이언트 사이드 렌더링(CSR)</p>
</blockquote>
<ul>
<li><a href="https://miracleground.tistory.com/165">https://miracleground.tistory.com/165</a></li>
</ul>
<h3 id="✅-235-spa-프레임워크">✅ 2.3.5 SPA 프레임워크</h3>
<p>SPA는 &#39;Single Page Application&#39;의 약자로 단일 페이지로 구성된 웹 애플리케이션을 말한다. SPA가 등장하기 전 웹 애플리케이션을 구성하던 방식인 서버 사이드 렌더링(SSR)의 경우, 화면에 보여질 리소스를 서버로 요청하고, 서버로부터 받아온 리소스를 렌더링 했다.
하지만 SPA의 경우 렌더링의 역할을 서버에게 넘기지 않고 브라우저에서 처리하는 방식이다. 웹 애플리케이션에 필요한 모든 정적 리소스를 최초에 한번 다운로드 하고, 이후 새로운 페이지 요청 시 페이지 갱신에 필요한 데이터만을 전달받아 페이지를 갱신하게 된다.
Angular, React, Vue.js, Svelte 등 다양한 SPA 프레임워크/라이브러리 등이 있다.</p>
<h2 id="24-자바스크립트와-ecmascript">2.4 자바스크립트와 ECMAScript</h2>
<p>ECMAScript는 자비스크립트의 표준 사양인 ECMA0-262를 뜻하며, 프로그래밍 언어의 값, 타입, 객체와 프로퍼티, 함수, 표준 빌트인 객체 등 핵심 문법을 규정한다. 
자바스크립트는 프로그래밍 언어로 ECMAScript와 브라우저가 별도 지원하는 클라이언트 사이드 Web API, 즉 DOM, BOM, Canvas, XMLHttpRequest, fetch, requestAnimationFrame, SVG, Web Storage, Web Component, Web Worker 등을 아우르는 개념이다.</p>
<h2 id="25-자바스크립트의-특징">2.5 자바스크립트의 특징</h2>
<p>자바스크립트는 HTML, CSS와 함께 웹을 구성하는 요소 중 하나로 웹 브라우저에서 동작하는 유일한 프로그래밍 언어이다. 기본 문법은 C, 자바와 유사하고 셀프에서는 프로토타입 기반 상속을, 스킴에서는 일급함수의 개념을 차용했다.
자바스크립트는 개발자가 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어다. 또한 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어다. 객체지향 언어가 아니라고 오해를 받기도 하지만, 자바스크립트는 클래스 기반 객체지향 언어보다 효율적이면서 강력한 프로토타입 기반의 객체지향 언어이다.</p>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://ko.wikipedia.org/wiki/ECMA%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8">https://ko.wikipedia.org/wiki/ECMA%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8</a></li>
<li><a href="http://www.tcpschool.com/ajax/ajax_intro_basic">http://www.tcpschool.com/ajax/ajax_intro_basic</a></li>
<li><a href="https://ui.toast.com/weekly-pick/ko_20210909">https://ui.toast.com/weekly-pick/ko_20210909</a></li>
<li><a href="https://jongminfire.dev/spa-single-page-application-%EB%9E%80">https://jongminfire.dev/spa-single-page-application-%EB%9E%80</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ELK] Elasticsearch, Logstash, Kibana]]></title>
            <link>https://velog.io/@dev_kdh/ELK-Elasticsearch-Logstash-Kibana</link>
            <guid>https://velog.io/@dev_kdh/ELK-Elasticsearch-Logstash-Kibana</guid>
            <pubDate>Thu, 18 Aug 2022 07:34:36 GMT</pubDate>
            <description><![CDATA[<p>프로젝트-X 두번째 멘토링을 하며 멘토님께서 ELK에 대해 설명해주셨다.
그래서 ELK에 대해 정리해보려 한다.</p>
<h2 id="📌-elk란">📌 ELK란??</h2>
<ul>
<li>데이터 처리 관련 오픈소스 솔루션인 엘라스틱 서치(Elasticsearch) + 로그스태시(Logstash) + 키바나(Kibana)를 같이 연동하여 사용한다는 의미로, ELK 혹은 ELK 스택(ELK Stack), 엘라스틱 스택(Elastic Stack)이라고 한다.<br></li>
<li>Elasticsearch (로그 저장 및 검색)<blockquote>
<ul>
<li>ElasticSearch는 Lucene 기반으로 개발한 분산 검색엔진으로, Logstash를 통해 수신된 데이터를 저장소에 저장하는 역할을 담당한다.</li>
<li>데이터를 중심부에 저장하여 예상되는 항목을 검색하고 예상치 못한 항목을 밝혀낼 수 있다.</li>
<li>정형, 비정형, 위치정보, 메트릭 등 원하는 방법으로 다양한 유형의 검색을 수행하고 결합할 수 있다.</li>
</ul>
</blockquote>
</li>
<li>Logstash (로그 수집 엔진)<blockquote>
<ul>
<li>오픈소스 서버측 데이터 처리 파이프라인으로, 다양한 소스에서 동시에 데이터를 수집하고 변환하여 stash 보관소로 보낸다.</li>
<li>수집할 로그를 선정해서, 지정된 대상 서버(ElasticSearch)에 인덱싱하여 전송하는 역할을 담당하는 소프트웨어</li>
</ul>
</blockquote>
</li>
<li>Kibana (로그 시각화 및 관리)<blockquote>
<ul>
<li>데이터를 시각적으로 탐색하고 실시간으로 분석 할 수 있다.</li>
<li>시각화를 담당하는 HTML + Javascript 엔진이라고 보면 된다.</li>
</ul>
</blockquote>
</li>
</ul>
<ul>
<li><p>세 모듈은 각자의 독립된 기술이라 일부만 사용할 수 있다. 하지만 서로 호환이 잘되고 함께 사용하면 시너지가 좋기 때문에 같이 구축된다. 세 기술을 함께 쓰기 때문에 ELKstack 이라고도 한다.
<img src="https://velog.velcdn.com/images/dev_kdh/post/afb431a2-c9c7-422b-9e0d-a085161b72c5/image.png" alt=""></p>
<br>
## ✅ ELK 장점
</li>
<li><p>가격</p>
<blockquote>
<p>ELK는 Elastic이라는 회사에서 제공하는 오픈소스이다. ELK 자체는 무료이기 때문에 다른 시스템에 비해 가격적인 측면에서 장점을 가진다.</p>
</blockquote>
</li>
<li><p>접근성 &amp; 사용성</p>
<blockquote>
<p>ELK는 오픈소스를 내려받아 설치하는 것으로 구축이 완료된다. 그 외의 별도의 추가적인 개발 과정이 필요 없기 때문에 접근성이 뛰어나다. 또한 다른 유사 시스템들에 비해 사용성이 쉬운 편이다.</p>
</blockquote>
</li>
<li><p>속도</p>
<blockquote>
<p>ELK 중 데이터 보관 및 분석 역할을 담당하는 Elasticsearch는 거의 실시간 (Real-Time)에 가깝게 데이터를 처리할 수 있다.</p>
</blockquote>
</li>
<li><p>유연성</p>
<blockquote>
<p>ELK는 세 가지의 모듈을 함께 구축한다. 해당 기능을 담당할 수 있다면 얼마든지 모듈을 유연하게 변경할 수 있다. Logstash를 쓰지 않아도 데이터 수집 역할만 할 수 있다면 경우에 따라 다른 것으로 대체할 수 있다.</p>
</blockquote>
</li>
</ul>
<h2 id="❎-elk-단점">❎ ELK 단점</h2>
<ul>
<li>초기 데이터 구성 및 이관 문제<blockquote>
<p>기존에 보유한 데이터를 엘라스틱 서치로 이관하는 경우 심각한 성능 저하 문제 발생, 많은 양의 데이터 이관 용도로는 사용이 힘들다.</p>
</blockquote>
</li>
<li>커널 변수의 불필요한 사용<blockquote>
<p>커널의 cgroup에 해당하는 변수를 참조하는 내용이 있어 해당 변수가 없는 커널의 경우 오류가 발생할 수 있다. 또한 커널 컴파일 환경에 따라 불필요한 커널 변수로 인해 프로그램이 중단되는 문제도 야기시킬 수 있다.</p>
</blockquote>
</li>
<li>원활하지 못한 시간대(Timezone) 처리<blockquote>
<p>3개의 스택(로그스태시-&gt;엘라스틱서치-&gt;키바나)로 데이터가 넘어가는 과정에서 시간대 일관성이 깨지는 문제가 있다. 3개 솔루션 모두 기본 시간대가 UTC라는 점을 인지하고, 시간대 설정이 가능한 경우 일관성을 유지하려는 노력으로 극복할 수는 있다.</p>
</blockquote>
</li>
</ul>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://captcha.tistory.com/44">https://captcha.tistory.com/44</a></li>
<li><a href="https://go-coding.tistory.com/98">https://go-coding.tistory.com/98</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML, CSS 기초]]></title>
            <link>https://velog.io/@dev_kdh/HTML-CSS-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@dev_kdh/HTML-CSS-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 17 Aug 2022 10:28:42 GMT</pubDate>
            <description><![CDATA[<h2 id="📌html">📌HTML</h2>
<h3 id="✅-html은-markup-language언어이다">✅ html은 Markup language언어이다.</h3>
<blockquote>
<p>우리가 보는 웹페이지가 어떻게 구조화되어 있는지 브라우저로 하여금 알 수 있도록 하는 마크업 언어다.
Markup : 기계용 &lt;-&gt; Markdown : 사람용
웹 페이지는 여러가지 요소가 합쳐져서 만들어진다. 그 중 HTML은 structure, 즉 구조를 담당하고 있으며, 웹 페이지가 어떻게 구성 될 것이가에 대한 정보를 담고 있다. 사람의 몸으로 비유면 뼈 정도의 역할을 한다고 볼 수 있다. CSS는 살과 가죽, JavaScript는 근육과 뇌의 역할을 한다고 이해하면 좋을 것 같다.</p>
</blockquote>
<h3 id="✅-html의-구조와-문법">✅ html의 구조와 문법</h3>
<ul>
<li><p>html에 css와 javascript를 적용할 수 있다.</p>
<blockquote>
<ul>
<li>CSS 적용하기
<code>&lt;link href=&quot;main.css&quot; rel=&quot;stylesheet&quot;&gt;</code>
link 태그는 외부 소스를 연결시킬 때 사용한다. link 태그의 href 속성은 외부 소스의 경로를 명시하고, rel 속성은 현재 문서와 연결 된 소스 사이의 관계를 명시한다.</li>
<li>JavaScript 포함하기
<code>&lt;script src=&quot;javascript.js&quot;&gt;&lt;/script&gt;</code>
script 태그는 보통 JavaScript 코드를 포함시킬 때 사용한다. src 속성에 파일을 입력해주면 완 성 !</li>
</ul>
</blockquote>
</li>
<li><p>Opening tag / closing tag / self-closing tag</p>
<blockquote>
<ul>
<li>Opening tag : <code>&lt;div&gt;</code> <del>~</del></li>
<li>closing tag : <del>~</del> <code>&lt;/div&gt;</code></li>
<li>self-closing tag : <code>&lt;img src=&quot;~&quot;&gt; &lt;input type = &quot;~&quot;&gt;</code></li>
</ul>
</blockquote>
</li>
<li><p>html 요소(Element)</p>
<blockquote>
<ul>
<li>div : 한 줄 차지</li>
<li>span : contents의 크기만큼 차지</li>
<li>ul (unordered list) : 번호 없는 리스트.</li>
<li>ol (ordered list) : 번호 붙은 리스트.</li>
<li>li (list item) : 위의 리스트 안에 들어가는 item. ul/ol 없이 단독으로 사용할 수 없다.</li>
</ul>
</blockquote>
</li>
<li><p>input type</p>
<blockquote>
<p>자주 사용되는 input의 type 5가지 !</p>
<ul>
<li>text : 텍스트 입력받기.
<code>&lt;input type=&quot;text&quot; placeholder=&quot;type here&quot;&gt;
&lt;input type=&quot;password&quot; placeholder=&quot;type here&quot;&gt;</code> // 입력값 안보임!</li>
<li>radio : 그룹을 설정해서 선택하기.
<code>&lt;input type=&quot;radio&quot; name=&quot;그룹이름&quot; value=&quot;값&quot;&gt;</code> 내용</li>
<li>checkbox : 무작정 체크하기.
<code>&lt;input type=&quot;checkbox&quot;&gt;</code> 로그인 정보 저장하기</li>
<li>email : 이메일 입력받기
<code>&lt;input type=&quot;email&quot;&gt;</code></li>
<li>name : 이름 입력받기(input 창 위에 name 표시)
<code>&lt;input type=&quot;name&quot;&gt;</code></li>
<li>password : 비밀번호 입력하기(별표나 동그라미로 표시)
<code>&lt;input type=&quot;password&quot;&gt;</code></li>
<li>tel : 전화번호 입력받기.
<code>&lt;input type=&quot;tel&quot;&gt;</code></li>
</ul>
</blockquote>
</li>
<li><p>스타일 지정</p>
<blockquote>
<ul>
<li>id (이름표) : &quot;#&quot; 으로 선택. 한 문서에 하나만! 특정 요소에 이름을 붙일 때 사용.</li>
<li>class (반) : &quot;.&quot; 으로 선택. 동일한 값을 갖는 요소가 많음. 스타일의 분류에 사용.</li>
<li>우선순위 id &gt; class &gt; 태그 순으로 적용</li>
</ul>
</blockquote>
</li>
</ul>
<h2 id="css">CSS</h2>
<ul>
<li>CSS는 Cascading Style Sheets 의 약자이다. 페이지를 알아보기 쉽게, 보기 좋게 만들기 위해 사용한다.<blockquote>
<ul>
<li>인라인 스타일 : <code>&lt;a style=&#39;color: red;&#39;&gt;&lt;/a&gt;</code></li>
<li>내부 스타일 시트 : <code>&lt;style&gt;</code>body{width:300px;} <code>&lt;/style&gt;</code></li>
<li>외부 스타일 시트 : <code>&lt;link href=&quot;main.css&quot; rel=&quot;stylesheet&quot;&gt;</code></li>
</ul>
</blockquote>
</li>
<li>css 단위<blockquote>
<ul>
<li>절대 단위 px, pt 등
: 인쇄와 같이 화면 사이즈가 정해져있을 때 주로 사용한다.</li>
<li>상대 단위 %, em, rem, ch, vw, vh 등
: 일반적으로 root 기반의 rem을 많이 사용한다. 화면의 너비나 높이에 따른 상대적인 크기가 중요할 경우 유동적인 사이즈 변환을 위해 사용한다.</li>
</ul>
</blockquote>
</li>
<li>css 글꼴<blockquote>
<ul>
<li>color : hex(16진법) 혹은 주요색상</li>
<li>글꼴 : &quot;글꼴1&quot;, &quot;글꼴2&quot;, &quot;글꼴3&quot; -&gt; (fallback) 지원하지 않은 형식일 경우 오른쪽 글꼴로 넘어간다. 
font-weight 굵기
font-decoration 밑줄
font-spacing 자간
font-height 행간
font-align 정렬 등등</li>
</ul>
</blockquote>
</li>
<li>margin, padding, border<blockquote>
<ul>
<li>(바깥) -&gt; margin -&gt; border -&gt; padding -&gt; content
<img src="https://velog.velcdn.com/images/dev_kdh/post/94c2406c-a516-4952-a0c4-102c743fa437/image.png" alt=""></li>
</ul>
</blockquote>
</li>
</ul>
<ul>
<li>box크기<blockquote>
<ul>
<li>content-box : content 영역을 기준으로 +padding +border크기를 정한다. (최종 크기가 넘어갈 수 있다!)</li>
<li>border-box : margin을 제외하고 border크기를 기준으로 padding과border 값에 영향을 받지 않고 원하는 대로 설정할 수 있다.
사용 예시: box-sizing:border-box
<img src="https://velog.velcdn.com/images/dev_kdh/post/e3434133-51a3-422b-97d1-61f646f10e2a/image.png" alt=""></li>
</ul>
</blockquote>
</li>
</ul>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://studiomeal.com/archives/197">https://studiomeal.com/archives/197</a></li>
<li><a href="https://studiomeal.com/archives/533">https://studiomeal.com/archives/533</a></li>
<li><a href="http://jun.hansung.ac.kr/cwp/htmls/HTML%20Input%20Types.html">http://jun.hansung.ac.kr/cwp/htmls/HTML%20Input%20Types.html</a></li>
<li><a href="https://velog.io/@tamagoyakii/TIL-3%EC%9D%BC%EC%B0%A8-HTML-CSS-%EA%B8%B0%EC%B4%88">https://velog.io/@tamagoyakii/TIL-3%EC%9D%BC%EC%B0%A8-HTML-CSS-%EA%B8%B0%EC%B4%88</a></li>
<li><a href="https://velog.io/@pearpearb/TIL-3-HTML-CSS-%EC%9E%85%EB%AC%B8">https://velog.io/@pearpearb/TIL-3-HTML-CSS-%EC%9E%85%EB%AC%B8</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트] 01장. 프로그래밍]]></title>
            <link>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-01%EC%9E%A5.-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@dev_kdh/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-01%EC%9E%A5.-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Sat, 13 Aug 2022 03:28:26 GMT</pubDate>
            <description><![CDATA[<p>프로젝트 경험이 있다. 프론트엔드를 담당했다.
하지만 아직 자바스크립트를 사용할 줄 모른다. 그래서 동료들과 함께 자바스크립트를 공부하기로 했다.
모던 자바스크립트 딥다이브가 유명하다고 한다. 하여 이 책으로 공부하기로 했다. 두께가 어마어마하다. 마치 전공 책을 보는 느낌인데, 이 책을 다 볼 수 있을까 싶지만, 프론트엔드 개발자로 성장하기 위해 꼭 다 보고야 말겠다!!</p>
<p>굳이 책을 봐야해?? 라는 질문을 할 수 있는데, 아무래도 실력 있는 개발자가 되기 위해서는 그만큼 탄탄한 기본 지식이 있어야 한다고 생각한다. 그 첫걸음이 바로 이 책이 되지 않을까 싶다. 공부 열심히 해야겠다. 갈 길이 멀다.</p>
<h2 id="11-프로그래밍이란">1.1 프로그래밍이란?</h2>
<p>프로그래밍이란 컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션이다.
해결해야할 문제 또는 요구사항을 명확히 이해한 후 적절한 문제해결 방안을 정의해야한다. 프로그래밍은 0과 1밖에 알지 못하는 기계가 실행할 수 있도록 정확하고 상세하게 요구사항을 설명하는 작업이다. 이 때 필요한 것이 Computational thinking(컴퓨팅 사고)이다. 논리적, 수학적 사고가 필요하며, 해결 과제를 작은 단위로 분해하고 패턴화해서 추출하며, 모든 개념이 평가 가능하도록 정의해야 한다.</p>
<h2 id="12-프로그래밍-언어">1.2 프로그래밍 언어</h2>
<p>프로그래밍이란 컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션이다. 해결해야 할 문제 또는 요구사항을 명확히 이해한 후 적절한 문제 해결 방안을 정의해야 한다.
프로그래밍은 0과 1밖에 알지 못하는 기계가 실행할 수 있도록 정확하고 상세하게 요구사항을 설명하는 작업이다. 이때 필요한 것이 Computational thinking(컴퓨팅 사고)이다. 논리적, 수학적 사고가 필요하며, 해결 과제를 작은 단위로 분해하고 패턴화해서 추출하며, 모든 개념이 평가 가능하도록 정의해야 한다.</p>
<blockquote>
<ul>
<li>컴파일러와 인터프티터의 차이
<img src="https://velog.velcdn.com/images/dev_kdh/post/642ad4c5-0966-4e57-82cc-beb6e1de4388/image.png" alt=""><br>
</li>
</ul>
</blockquote>
<ul>
<li>컴파일러와 인터프리터의 방식 비교
<img src="https://velog.velcdn.com/images/dev_kdh/post/30c51673-521d-4d16-bdc7-3434f475297e/image.png" alt=""></li>
</ul>
<h2 id="13-구문과-의미">1.3 구문과 의미</h2>
<p>프로그래밍 언어는 구문(syntax)과 의미(semantics)의 조합으로 표현된다.
언어는 문법에 맞는 문장을 구성하는 것과 더불어 의미를 가지고 있어야 언어의 역할을 충실히 수행할 수 있다. 프로그래밍 언어도 해당 문법에 부합하는 것은 물론이고 수행하고자 하는 요구사항(문제)이 해결되어야 의미가 있다.</p>
<p>결국 프로그래밍은 요구사항의 집합을 분석해서 적절한 자료구조와 함수의 집합으로 변환한 후, 그 흐름을 제어하는 것이다!</p>
<h2 id="참고">참고</h2>
<ul>
<li>모던 자바스크립트 DeepDive - 자바스크립트의 기본 개념과 동작 원리</li>
<li><a href="https://just-my-blog.tistory.com/31">https://just-my-blog.tistory.com/31</a></li>
<li><a href="https://velog.io/@andthensome/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0">https://velog.io/@andthensome/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>