<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>seungjaekim-git.log</title>
        <link>https://velog.io/</link>
        <description>웹 개발자,김승재입니다 ! </description>
        <lastBuildDate>Sun, 18 Dec 2022 10:06:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>seungjaekim-git.log</title>
            <url>https://velog.velcdn.com/images/seungjaekim-git/profile/68abb4ca-0586-48b0-ba14-9ebae45961a5/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. seungjaekim-git.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/seungjaekim-git" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[AWS] SAA-C03 합격 후기]]></title>
            <link>https://velog.io/@seungjaekim-git/AWS-SAA-C03-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@seungjaekim-git/AWS-SAA-C03-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sun, 18 Dec 2022 10:06:00 GMT</pubDate>
            <description><![CDATA[<h1 id="0-서론">0. 서론</h1>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/f0fd5c77-7868-48b1-bc2e-1d0f5e7e012f/image.PNG" alt=""></p>
<p>평소 같이 공부하는 데이터엔지니어 개발자분과 함께 AWS에 대해서 스터디를 하면서,각 서비스별로 다루는 방법을 프리티어로 체험하면서 서로 알게된 내용을 설명하면서 전전긍긍하고 있었다. 그러던 와중, 뜬금없이 같이 공부하던 개발자 분이 이렇게 목표없이 공부하는 것보다 뚜렷한 목표를 잡고 가는게 더 좋을거 같다고 하셔서, 자의 반 +타의 반으로 AWS 시험을 12월 중순에 예약해버렸다. </p>
<p>나도 시험을 준비하는 것에는 찬성을 했던 이유는 </p>
<ul>
<li>프리티어로 커버할 수 없는 서비스를 어떻게 이해해야되는지 막막하기도 했고, </li>
<li>서로 비슷한 서비스들 (SQS VS Kinesis Family, AWS Sheild VS AWS Guard)이 어떻게 다르고, </li>
<li>어떤 관점으로 해당 서비스를 이용하는 이유를 찾기가 너무 불명확했기 때문에, </li>
</ul>
<p>시험을 통해서 위와 같은 요점을 보다 확실하게 짚고 갈 수 있겠다고 생각했기 때문이다. </p>
<p>그렇게 해서 같이 Udemy 강의를 구매하고, 총 3개월의 시간을 꾸준히 시간을 내서 공부하고 결국 합격을 하게 되었다. 이번 글은 SAA 시험은 무엇이며, 내가 이 시험을 준비한 과정/팁과 시험에 대한 후기에 대해서 적어볼려고 한다. </p>
<h1 id="1-saa-시험이란">1. SAA 시험이란</h1>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/5cbbdf5b-358b-47e6-8578-11ed3af9165e/image.png" alt=""></p>
<blockquote>
<p>먼저, <a href="https://aws.amazon.com/ko/certification/certified-solutions-architect-associate/">SAA-C03</a> 이라는 시험은 AWS에서 운영하고 시행되는 자격증시험 중 하나로, 자세한 사항은 주어진 링크를 통해서 확인가능하다. 
해당 시험에서 테스트하는 항목은 다음과 같다.</p>
</blockquote>
<ul>
<li>컴퓨팅, 네트워킹, 스토리지 및 데이터베이스 AWS 서비스는 물론, AWS 배포 및 관리 서비스에 대한 지식과 기술</li>
<li>AWS에서 워크로드를 배포, 관리, 운영한 경험과 보안 제어 및 규정 준수 요구 사항 구현에 대한 지식과 기술</li>
<li>AWS Management Console 및 AWS Command Line Interface(CLI) 사용에 대한 지식 및 기술과 AWS Well-Architected Framework, AWS 네트워킹, 보안 서비스 및 AWS 글로벌 인프라에 대한 이해</li>
<li>주어진 기술 요구 사항에 부합하는 AWS 서비스를 식별하고 AWS 기반 애플리케이션의 기술 요구 사항을 정의하는 능력</li>
</ul>
<h1 id="2-나의-시험-준비-과정">2. 나의 시험 준비 과정</h1>
<blockquote>
<ol>
<li>Udemy 인강 
<a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-saa-c03/?src=sac&amp;kw=saa-c03">Ultimate AWS Certified Solutions Architect Associate SAA-C03</a></li>
</ol>
</blockquote>
<p>나는 시험 준비를 위해서 일단 위의 Udemy 인강을 2개월 동안 하루에 2<del>3 시간씩 보면서 기본적인 AWS 서비스들의 개념을 숙지하였다. 추가로 인강에서 Stephane 강사님의 Hands-on 섹션을 따라해보면서 직접 서비스를 다루는 걸 직접 해보았다. 강의는 총 350개 정도의 Lecture으로 구성되어 있고, 한 강의당 3분 ~ 10분정도 소요된다. 하지만, 하나의 강의를 들어도 내가 이해한것이 정말 맞는지 의심이 되어서 계속 같은 강의를 반복적으로 보아서 저렇게 하루에 2</del>3시간 정도나 쓴거같다. ㄷㄷ </p>
<p>나는 따로 개념 정리 노트 같은 것은 하지는 않았다. 강의에서 주어지는 PDF 슬라이드가 충분히 그 역할을 해주었기 때문이다. 내가 집중해야되는 부분은 서비스 개념과 원리를 이해하는 것이라고 생각해서 스터디 미팅에서 같이 공부하는 분이랑 해당 서비스에 대해서 얘기하고 잘못 이해한 부분이 없는지만 간간히 체크하였다.</p>
<p>(실제로 Global Accelerator가 단순히 CloudFront 서비스의 TCP/UDP 버젼이라고만 했다가 같이 공부하던 개발자 분께 한소리 들었었다 ㅠ) </p>
<p>해당 강의에는 마지막에 샘플 테스트가 하나 있는데, 흠... 장단점을 이야기하자면</p>
<ul>
<li>장점 </li>
</ul>
<ol>
<li>문제해설이 친절하게 다 적혀져 있어서 이해가 편하다.</li>
<li>같은 시험을 다른 문제순서로 반복해서 칠 수 있다.</li>
<li>문제 난이도가 꽤 있어서, 다 이해하면 AWS 서비스에 대해서도 더 잘알게 된다. </li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>솔직히 처음에 풀면 문제가 어려워서 현자타임이 좀 온다 (<del>처음에 거의 반정도만 맞추었는데 그마저도 거의 찍는 느낌으로 했던것</del>)</li>
<li>시험에 출제되는 문제보다 이해를 위해서 푸는 것이기 때문에 시험 합격만이 목적이라면 차라리 밑에 설명할 Examptopics에 나오는 문제를 푸는게 더 좋을거같다.</li>
</ol>
<blockquote>
<ol start="2">
<li>GitHub &amp; 블로그 자료 참고 
<a href="https://github.com/serithemage/AWSCertifiedSolutionsArchitectUnofficialStudyGuide">SAA-C03 정리 자료 링크</a></li>
</ol>
</blockquote>
<p>그 다음으로 한 것은 블로그에 나와있는 정리된 글을 통해서 시험 준비에 도움이 되는 자료를 찾아보면서 내가 놓치거나 까먹었던 부분을 다시 정리하면서 총 정리를 하였다. 위의 링크는 SAA 나오는 개념들을 정리한 깃헙 링크인데, SAA-C02라는 옛 버젼의 시험이여서 개념이 다를거라고 걱정하지 않아도 된다. 똑같이 SAA-C03시험에도 나오는 내용들이다. </p>
<p>그 다음, 여러 합격 후기를 통해서 다른 사람들이 어떻게 준비하여 합격했는지 알아보았는데, 대부분 SAA 관련 Dump 문제를 풀면서 문제 풀이에 대해서 익숙해지라는 것이 대다수의 의견이였다. 일단, 무료로 문제를 제공하는 EXAMTOPICS라는 사이트에서 문제를 대략 200문제 정도 풀었다. 그리고, 단순히 푸는게 아니라 오답노트를 다 적는게 좋다고 하여, 무작정 그들의 추천대로 따라하면서 진행했다. </p>
<blockquote>
<ol start="3">
<li>Examtopics
<a href="https://www.examtopics.com/exams/amazon/aws-certified-solutions-architect-associate-saa-c03/">EXAMTOPIC (SAA-C03) 링크 </a></li>
</ol>
</blockquote>
<p>그리고 대망의 Dump 문제 풀이를 본격적으로 시작했다. 위의 Examtopics 사이트는 여러 시험의 문제은행을 제공하는 서비스으로 일단 무료로 사용할 수 있고, 후기에도 대부분의 시험 문제가 여기에서 출제되었다고 해서 여기로 선택하였다. </p>
<p>문제를 풀다보면 정답을 바로 볼수 있어서 좋았지만, 아마 많은 문제에서 정답과 Discussion에서 나오는 답이 다른 것을 확인 할 수 있을것이다. 나는 이렇게 정답과 유저들의 의견이 갈릴때는 Discussion에서 가장 많이 뽑힌 주장을 1순위로 정답이라고 생각하고 시험을 준비했다. 그럴 수 밖에 없는 이유는 Discussion에서 유저들이 참고자료를 제안하면서 해당 문제의 답을 주장하고 있기 때문이다. 그리고 대부분의 참고자료는 AWS 공식문서이기 때문에 문제와 대조해보면서 생각해보니 그들의 주장이 맞다고 생각하게 되었다. 아마 Examptopics에서 정답을 업데이트하지 않은 건가 ? 라는 생각을 했다.</p>
<p>10문제씩 풀다보면 귀찮은 &quot;로봇아님 인증&quot;을 해야되는데 나는 이게 싫어서 <strong>Contributor Access</strong> 라는 4만원정도의 구독 서비스를 결제해서 편하게 30문제씩 나누어서 문제를 풀었다.
<strong>추가로, 나는 개념정리 노트는 적지 않았지만, 오답노트는 꽤 성실하게 적었다.</strong> 내가 이해 못하거나 문제에서 포인트를 캐치하지 못한 단서를 정리하면서 각 문제별로 포인트를 정리하는게 정말 중요하다고 느끼게 되었는데, 100문제 정도 풀어보니 나머지 100문제는 문제유형과 키워드만 있으면 대부분 답을 유추할 수 있었다. </p>
<blockquote>
<p><em><strong>이 글을 읽는 독자분이 SAA-C03 을 준비하고 계신다면 무조건 오답노트를 적으면서 EXAMTOPICS를 풀라고 추천하고 싶다.</strong></em></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/7bca1da8-6548-4727-94ec-5ea6f43dfa86/image.png" alt=""></p>
<blockquote>
<ol start="4">
<li>시험 관련 Tips</li>
</ol>
<p><strong>- 시험 시간 추가로 30분 받는 법 **
<img src="https://velog.velcdn.com/images/seungjaekim-git/post/94188a59-59df-4d62-b45c-767aabc211be/image.png" alt="">
나는 이것을 몰라서 신청을 못하였지만, AWS Certificate 시험 등록페이지에서 몇가지 Accommodation(편의 지원)을 신청할 수 있다. 관련 옵션중에 &quot;ESL +30min&quot; 라는 옵션을 선택해서 시험을 신청하면 추가적으로 30분을 추가로 받을 수 있다.
**- Examtopics를 신뢰하는 이유</strong>
SAA-C03 시험의 대부분은 개념에 관한 직접적인 정의를 물어보는 것이 아니라, 하나의 시나리오를 기준으로 각각 경제적 요소,확장성,유지보수, 보안 등을 기준으로 최적의 서비스를 물어본다. 그리고 해당 시나리오에 기준이 되는 것이 AWS FAQ에서 나오는 질문들이다. Examtopics의 문제를 확인해보면 FAQ에서 나오는 질문들과 똑같은 문제들도 많았고, ExamTopics 유저들의 답변도 해당 FAQ의 답변을 가져오는 경우가 대다수였다. 그래서 최소한 출제자 기준으로 문제가 선별된 것이라고 생각했기 때문에 이 문제은행만을 이용하여 준비하였다. 
*<em>- <del>밖은 추우니깐 집에서 따뜻하게 온라인 시험 치르는법</del> *</em>
요새 날씨도 너무 추워서 집에서 보는 온라인 시험으로 바꾸어서 시험을 치렀다. 하지만, 해당 방법은 2023년부터는 이제 제공을 안한다고 하니 패스 ... ㅠ </p>
</blockquote>
<h1 id="3-시험-후기">3. 시험 후기</h1>
<p>시험은 총 65문제였고, 130분의 시간이 주어졌지만, 30분 정도 남기고 다 풀었던 것 같다. 그리고, Examtopics에서 문제가 출제된다고 했던 것이 정말이였던게, 65문제 중에서 최소 60문제는 이미 한번 풀어봤던 것 같은 문제들이였다. 그래서 시험을 치르고, 합격 하겠다는 느낌이 바로 와서 좋았다. </p>
<p>하지만, 한편으로는 정말 내가 AWS에 대해서 잘 이해하는 것이 맞는지 의문이 생겼다. 단순히 문제만 풀었던 경우에 대해서만 단순히 이해하고 있었을 뿐 ... 현업에서 내가 클라우드 서비스에 대해서 자신있다고 말하기는 어려울 것같다. 그래서 지금부터 Hands-on 강의에서 나왔던 것을 활용해서 토이프로젝트를 배포 해볼려고 한다. input을 주어졌으니 내 스스로 output을 뽑아야지 진정한 내 지식이 될 것같다.</p>
<p>이 자격증을 신청했을때는, 자의 반 + 타의 반으로 시작해서 솔직히 &quot;이걸 내가 왜 하고 있지?&quot; 라는 생각을 가끔 했었다. 하지만, 돌이켜 보면 지금까지 멀게만 느껴졌던 클라우드 서비스에 대해서 이해도 되고 자신감도 나름 가지게 되어서 만족하는 중 이다. 이 서비스를 이용해서 만들 것을 생각하니 왠지 의욕도 생기고, 무엇보다 뱃지가 귀여워서 좋았다. </p>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/2dfe38e2-4d47-4eea-a7d4-3651d660a58a/image.png" alt=""></p>
<h1 id="4-끝-">4. 끝 ~</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[TYPESCRIPT 문법 정리 2편 ]]></title>
            <link>https://velog.io/@seungjaekim-git/TYPESCRIPT-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-2%ED%8E%B8</link>
            <guid>https://velog.io/@seungjaekim-git/TYPESCRIPT-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-2%ED%8E%B8</guid>
            <pubDate>Fri, 25 Nov 2022 13:57:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 <a href="https://velog.io/@seungjaekim-git/Typescript-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-1%ED%8E%B8">TYPESCRIPT 문법 정리 1편</a>에서 이어지는 Typescript 문법 정리 글입니다. </p>
</blockquote>
<hr>
<h1 id="5-generics">5. Generics</h1>
<blockquote>
<p>Generic을 사용하면 함수나 클래스의 선언 시점이 아닌, 사용 시점에서 타입을 선언할 수 있습니다. 즉, 타입을 좀 더 유동적으로 받아서 처리할 수 있게 되죠. </p>
</blockquote>
<pre><code class="language-typescript">
// 기존 선언 시점에서의 타입 지정
function identity(arg: number): number {
  return arg;
}

// Generic을 활용한 사용시점에서의 타입 선언
function identity&lt;Type&gt;(arg: Type): Type {
  return arg;
}

console.log(identity&lt;number&gt;(1)); // returns 1 
console.log(identity&lt;string&gt;(&#39;1&#39;)); //returns &#39;2&#39;</code></pre>
<blockquote>
<p>위와 같이 기존의 방식보다 Generic을 이용하면, 여러 타입이 들어와도 처리할 수 있는 로직을 구현 가능합니다.
만약, Type 에 String 과 Number만 받고 싶다면 아래와 같이 &quot;extend&quot; 구문을 이용하여 제약을 추가할 수 도 있습니다.</p>
</blockquote>
<pre><code class="language-typescript">function identity&lt;Type extends string | number&gt;(arg: Type): Type {
  return arg; // only string and number can be placed for the type
}</code></pre>
<blockquote>
<p>하지만, Generic 을 사용할 경우, 각각의 고유의 타입이 가지고 있는 bulit-in 유틸리티 함수/변수 (예를 들어 Array.length)를 사용할 때 주의 해야됩니다. 아래의 예제를 한번 보면,</p>
</blockquote>
<pre><code class="language-typescript">function loggingIdentity&lt;Type&gt;(arg: Type): Type {
  console.log(arg.length);
//Property &#39;length&#39; does not exist on type &#39;Type&#39;.
  return arg;
}</code></pre>
<blockquote>
<p>위와 같이 저희는 arg 라는 변수에 length라는 필드가 있는것을 확신할 수 없기 때문에, 다음과 같은 에러가 발생합니다. 그렇기 때문에, 위에서 설명한 &quot;extends&quot;를 활용해서 해당 변수에 다음과같이 제약을 부여하여, 에러를 피해갈 수 있습니다.</p>
</blockquote>
<pre><code class="language-typescript">interface Lengthwise {
  length: number;
}

function loggingIdentity&lt;Type extends Lengthwise&gt;(arg: Type): Type {
  console.log(arg.length); // Now we know it has a .length property, so no more error
  return arg;
}</code></pre>
<blockquote>
<p>이 이외에도 조건부 타입 (Contional Type) 와 같이 삼항연산자 (e.g. T extends U ? X : Y)을 이용하여 타입을 구현 할수도 있지만, 이것까지 활용하진 않을거같기 때문에 저는 패스했습니다. 관심 있는 분들은 <a href="https://www.typescriptlang.org/docs/handbook/2/conditional-types.html">Contional Types</a>을 확인해보시면 좋을거같습니다.</p>
</blockquote>
<hr>
<h1 id="6-type-declarations">6. Type Declarations</h1>
<blockquote>
<p>Type declaration은 변수, 상수, 함수, 또는 클래스가 프로젝트 어딘가에 이미 선언되어 있는 것을 알리는 것입니다. 그리하여, JS 코드로는 컴파일 되지 않고, Typescript 컴파일러에게 타입 정보를 알리기만 한다고 하네요. 예를 들어, JS 코드로 미리 프로젝트에 존재하는 유틸리티 (대표적인 예로 String-utils)에 타입 선언을 위해 사용이 가능하겠네요.</p>
</blockquote>
<h3 id="a-이미-존재하는-string-유틸리티-파일">A. 이미 존재하는 String 유틸리티 파일</h3>
<blockquote>
<p>이해가 안되실수 있을거 같아서 한 가지 예제를 설명하면, 아래의 js 모듈은 string utils는 이미 다른 프로젝트에서 가져온 것이며, 해당 js 모듈을 typescript 프로젝트에서 사용하기 위해서는 타입을 선언(declare)해야됩니다.</p>
</blockquote>
<pre><code class="language-javascript">// node_modules/str-utils/index.js

function strReverse(value) {
    return value.split(&#39;&#39;).reverse().join(&#39;&#39;);
}

function strToLower(value) {
    return value.toLowerCase();
}

function strToUpper(value) {
    return value.toUpperCase();
}

function strRandomize(value) {
    var array = value.split(&#39;&#39;);
    for (var i = array.length - 1; i &gt; 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array.join(&#39;&#39;);
}

function strInvertCase(value) {
    return value
        .split(&#39;&#39;)
        .map(function(c) {
            if (c === c.toLowerCase()) {
                return c.toUpperCase();
            } else {
                return c.toLowerCase();
            }
        })
        .join(&#39;&#39;);
}

module.exports = {
    strReverse,
    strToLower,
    strToUpper,
    strRandomize,
    strInvertCase
};
</code></pre>
<h3 id="b-type-declare-코드-추가">B. Type Declare 코드 추가</h3>
<blockquote>
<p>여기에서 파일의 확장자를 보시면 Declare의 d가 추가된 [파일이름].d.ts 으로 되신것을 확인할 수 있습니다. 해당 파일은 다른 불필요한 로직없이 오직 타입 선언만을 위해서 존재하는 파일을 의미합니다. </p>
</blockquote>
<pre><code class="language-typescript">// str-utils/index.d.ts
declare module &#39;str-utils&#39; {
    type StrUtil = (input: string) =&gt; string;

    export const strReverse: StrUtil;
    export const strToLower: StrUtil;
    export const strToUpper: StrUtil;
    export const strRandomize: StrUtil;
}</code></pre>
<h3 id="c-해당-str-utils를-다른-ts-파일에서-모듈로써-사용가능하게-됨">C. 해당 str-utils를 다른 ts 파일에서 모듈로써 사용가능하게 됨</h3>
<pre><code class="language-typescript">// 타입스크립트로 프로젝트의 어느 파일
import {
    strReverse,
    strToLower,
    strToUpper,
    strRandomize,
    strInvertCase
} from &#39;str-utils&#39;;
</code></pre>
<blockquote>
<p>만약 str-utils/index.d.ts이 존재하지 않는다면, 해당 모듈이 import 되는 시점에 모듈의 매개변수/반환변수 타입이 unknown으로 설정되어, 모듈을 이용하는 부분이 굉장히 까다로워 지게됩니다.</p>
</blockquote>
<hr>
<h1 id="7-module-augmentation">7. Module Augmentation</h1>
<blockquote>
<p>Module Augmentation은 이미 type이 선언된 모듈에 추가적인 타입을 업데이트할 수 있는 타입스크립트의 기능 중 하나입니다. JS에서는 기본적으로 Merging을 지원하지 않지만, Typescript는 Merged Types들이 있기 때문에, 이미 선언된 타입에 추가적인 필드를 추가할 수 있습니다.</p>
</blockquote>
<h3 id="a-타입이-이미-선언된-datewizard-유틸리티-모듈">A. 타입이 이미 선언된 datewizard 유틸리티 모듈</h3>
<blockquote>
<p>이번에도 이해가 난해할 수 있기때문에, 한가지 예를 들어볼려고 합니다.
아래의 코드는 datewizard라는 Date관련 유틸리티 모듈입니다. 하지만, 해당 Datewizard의 DateDetails 인터페이스에는 오직 년/월/일 필드만 있고, 시간관련 필드는 없는 상황입니다.</p>
</blockquote>
<pre><code class="language-typescript">//node_modules/date-wizard/index.d.ts

declare function dateWizard(date: Date, format: string): string;

declare namespace dateWizard {
    interface DateDetails {
        year: number;
        month: number;
        date: number;
    }

    function dateDetails(date: Date): DateDetails;
    function utcDateDetails(date: Date): DateDetails;
}

export = dateWizard;
</code></pre>
<h3 id="b-module-augmentation을-이용해서-시간관련-필드를-추가-가능">B. Module Augmentation을 이용해서 시간관련 필드를 추가 가능</h3>
<blockquote>
<p>다음과 같이 모듈을 호출하여, DateDetails 인터페이스를 한번 더 명시하여 (Merged Types를 활용하여), 시간관련 필드를 추가할 수 있습니다. </p>
</blockquote>
<pre><code class="language-typescript">// module-augmentations/date-wizard/index.d.ts
// This enables module augmentation mode.
import &#39;date-wizard&#39;;

declare module &#39;date-wizard&#39; {
    const pad: (ident: number) =&gt; string;

    interface DateDetails {
        hours: number;
        minutes: number;
        seconds: number;
    }
}
</code></pre>
<hr>
<h1 id="8-type-mapping">8. Type mapping</h1>
<blockquote>
<p>원래는 Type mapping 까지 정리할려고 하였지만, 이 부분까지는 아직 제 실력이 부족하여, 좀 더 기초적인 문법에 익숙해진 뒤에 정리하는게 좋을거같아서 뒤로 미룰려고 합니다 ㅠㅅㅠ 
이 주제에 대해서 궁금하신 분들은 <a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html">Mapped-types</a>를 확인하시면 좋을거 같습니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Typescript 문법 정리 1편 ]]></title>
            <link>https://velog.io/@seungjaekim-git/Typescript-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-1%ED%8E%B8</link>
            <guid>https://velog.io/@seungjaekim-git/Typescript-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-1%ED%8E%B8</guid>
            <pubDate>Thu, 24 Nov 2022 13:37:51 GMT</pubDate>
            <description><![CDATA[<h1 id="👋-0-typescript-소개">👋 0. Typescript 소개</h1>
<p><img src="blob:https://velog.io/1a146479-2e40-4cf7-9cd9-08a9e6c185e2" alt="업로드중.."></p>
<blockquote>
<p>💡 <em>*<em>타입스크립트란 ? *</em></em>
<em>타입스크립트 (Typescript)는 Microsoft에서 개발하고 유지/관리하는 Apache 라이센스가 부여된 오픈 소스입니다. 일반 자바스크립트로 컴파일 되는 자바 스크립트 Superset(상위 호환)으로 2012년 10월 처음 릴리스 되었습니다. 
자바스크립트는 타입 시스템이 없는 동적 프로그래밍 언어로, 자바스크립트 변수는 문자열, 숫자, 불린 등 여러 타입의 값을 가질 수 있습니다. 이를 약한 타입 언어라고 표현할 수 있으며 비교적 유연하게 개발할 수 있는 환경을 제공하는 한편 런타임 환경에서 쉽게 에러가 발생할 수 있는 단점을 가집니다.
그렇기 때문에, 런타임이 아닌 컴파일 환경에서 에러가 발생하는 오류를 사전에 잡아낼 수 있게, 타입스크립트는 Java와 같이 강한 타입 시스템을 제공하며, 체계적이고 높은 코드 품질을 제공할 수 있습니다.</em></p>
</blockquote>
<p>Vue2에서 Vue3으로 버젼이 업데이트 되면서 가장 눈에 들어온 변환점은 바로 타입스크립트와의 호환성이 좋아진 점입니다. 기존 Vue2에서 타입스크립트를 사용하기 위해서는 큰 비용 및 개발 공수가 필요하였는데, 이 점이 개선되어 이번 토이프로젝트에서 사용해보기로 정하게 되었는데요. 저는 타입스크립트를 처음 사용하여 일단 기본적인 문법부터 정리해보기로 하였습니다. </p>
<p>저는 연습과정에서 공식 문서도 읽어보고 하였지만, 직접 써보는게 아무래도 더 이해하기 편할거같아서 아래 두 사이트를 이용하였습니다.</p>
<ul>
<li><p><a href="https://typescript-exercises.github.io/#exercise=1&amp;file=%2Findex.ts">타입스크립트 연습 사이트</a> : 타입스크립트 연습문제가 16문제 주어지는 사이트입니다. 문제도 좋고 답도 편하게 열람할 수 있어서 막힘없이 진행할 수 있어서 좋았습니다. ㅎ 독자님들도 타입스크립트가 처음이라면 추천합니다 👍</p>
</li>
<li><p><a href="https://www.typescriptlang.org/play/index.html">타입스크립트 Playground</a> : 온라인 환경에서 바로 타입스크립트를 연습할 수 있어서 많이 편합니다. </p>
</li>
</ul>
<hr>
<h1 id="1-basic-typings">1. Basic Typings</h1>
<blockquote>
<p>타입스크립트는 변수선언시 다음과 같이 다양한 타입을 선언할 수 있습니다. </p>
</blockquote>
<pre><code class="language-typescript">let isBoolean: boolean; // 참/거짓 값

let num: number; // 숫자 (정수 + 소수 + Infinity + NaN)

let str: string; // 문자열

let alphanumber : string | number // 숫자일수도 문자일수도 ... 

let readonly alphanumber : string // 읽기 전용 타입

let fruits: string[] = [&#39;Apple&#39;, &#39;Banana&#39;, &#39;Mango&#39;]; // 단일 타입으로 이루어진 Array 

let array: (string | number)[] = [&#39;Apple&#39;, 1, 2, &#39;Banana&#39;, &#39;Mango&#39;, 3]; // 두개 이상의 타입으로 구성가능  

let tuple: [string, number] = [&#39;1&#39;,2] //정해진 타입의 고정된 길이(length) 배열

enum Gender { // 열거형 타입
  Male,
  Female
}

let a: any = 123; // 어떤 타입이든 가능 
let u: unknown = 123; // any 타입과 같이 어떤 타입이든 할당 가능 하지만, unknown은 다른 타입에느 할당 불가 

let obj: object = { // 객체 
  isBoolean:boolean = false,
  str:string = &quot;hello&quot;
}; 

// type alias 도 가능
type Types = {
    isBoolean:boolean;
    outofStock?: boolean; // Optional 
    update: (retryTimes: number) =&gt; void; // arrow function field 
    readonly body: string; // 읽기 전용
    [key: string]: string;  // ??? 이건 뭔지 모르겠네요 ㅠ 
};


interface UserInterface { // 인터페이스
  name: string,
  age: number
}

let user1: UserInterface = { // 반복적으로 사용할시 유용
  name: &#39;Paul&#39;,
  age: 21
};

// 함수타입 
function hello(msg: string): void { // 함수의 parameter에도 타입 지정 가능 및 반환 값의 타입도 지정 가능 
  console.log(`Hello ${msg}`);
}

function hello(msg: string): Never { // 절대 발생하지 않을 값 = Never
  throw new Error(message);
}

// 클래스 타입
class User implements UserInterface {
  constructor(public name: string) {}
  getName() {
    return this.name;
  }
}

</code></pre>
<hr>
<h1 id="2-refining-types">2. Refining Types</h1>
<blockquote>
<p>추가적으로 타입 선언과 더불어 해당 타입에 대한 추가적인 규제를 타입스크립트가 제공합니다. 저는 이를 3가지로 크게 정리하였습니다.</p>
</blockquote>
<h3 id="a-타입-추론-type-inference">A. 타입 추론 (Type Inference)</h3>
<pre><code class="language-typescript">
let str = &quot;Hello&quot;; 
str = 1 // TypeError !!! </code></pre>
<blockquote>
<p>위와 같이 str에는 명시적인 타입이 지정되지 않고, hello 라는 문자열 값이 할당되었습니다. 그리하여, 타입스크립트는 str 변수 타입을 문자열으로 추론하여 숫자 1을 재할당 하려 할때 에러가 나오게 됩니다. </p>
</blockquote>
<h3 id="b-타입-단언-type-assertions">B. 타입 단언 (Type Assertions)</h3>
<pre><code class="language-typescript">
interface User {
    type: &#39;user&#39;;
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type: &#39;admin&#39;;
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

export function logPerson(person: Person) {
    let additionalInformation: string = &#39;&#39;;
    if (isAdmin(person)) {
        additionalInformation = (person as Admin).role;
    }
    if (isUser(person)) {
        additionalInformation = (person as User).occupation;
    }
    console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}</code></pre>
<blockquote>
<p>위의 코드를 보면 <strong><em>person as Admin</em></strong>과 <strong><em>person as User</em></strong> 라는 코드으로 각 User와 Admin Interface에 존재하는 고유 필드명을 사용할 수 있게됩니다. 이렇게 타입을 단언하지 않고 person에서 role이나 occupation 필드명을 참조할 경우 에러가 발생됩니다.</p>
</blockquote>
<h3 id="b--not-null-단언-선언">B # Not Null 단언 선언</h3>
<pre><code class="language-typescript">
// Non-null assertion operator
function returnX(x: number | null | undefined) {
  return x!.toFixed(2);
}
</code></pre>
<blockquote>
<p>자료를 찾아보니 변수 뒤에 &quot;!&quot;을 추가함으로 해당 변수가 Null이 아니라고 단언 할 수도 있네요 </p>
</blockquote>
<h3 id="c-타입-가드-type-guard">C. 타입 가드 (Type Guard)</h3>
<pre><code class="language-typescript">interface User {
    type: &#39;user&#39;;
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type: &#39;admin&#39;;
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

export const persons: Person[] = [
    { type: &#39;user&#39;, name: &#39;Max Mustermann&#39;, age: 25, occupation: &#39;Chimney sweep&#39; },
    { type: &#39;admin&#39;, name: &#39;Jane Doe&#39;, age: 32, role: &#39;Administrator&#39; },
    { type: &#39;user&#39;, name: &#39;Kate Müller&#39;, age: 23, occupation: &#39;Astronaut&#39; },
    { type: &#39;admin&#39;, name: &#39;Bruce Willis&#39;, age: 64, role: &#39;World saver&#39; }
];

export function isAdmin(person: Person) : person is Admin{
    return person.type === &#39;admin&#39;;
}

export function isUser(person: Person) : person is User{
    return person.type === &#39;user&#39;;
}

export function logPerson(person: Person) {
    let additionalInformation: string = &#39;&#39;;
    if (isAdmin(person)) {
        additionalInformation = (person as Admin).role;
    }
    if (isUser(person)) {
        additionalInformation = (person as User).occupation;
    }
    console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}
</code></pre>
<blockquote>
<p>위의 코드에서 <em><strong>isAdmin</strong></em> 과 _*<em>isUser *</em>_함수의 반환값을 Admin 과 User 라고 명시적으로 방어하는 것을 확인 할 수 있습니다. 위의 타입 단언 (Type Assertion)과 더불어 같이 사용하면 유용하게 사용될 듯 싶어서 예제코드를 가져와보았습니다. 이 외에도, js에서도 사용되던 instanceof, in, typeof 도 사용할 수 있겠네요.</p>
</blockquote>
<hr>
<h1 id="3-union-types">3. Union Types</h1>
<blockquote>
<p>위의 예제들에서 간간히 보였던 타입 결합 입니다. 두 가지 이상의 타입들을 한가지 변수에 할당 할 수 있습니다. </p>
</blockquote>
<pre><code class="language-typescript">
function printStatusCode(code: string | number) {
  console.log(`My status code is ${code}.`)
}
printStatusCode(404);
printStatusCode(&#39;404&#39;);</code></pre>
<blockquote>
<p>하지만, 이렇게 두 가지 이상의 타입들을 사용 할 경우, 타입 가드 혹은 타입 가드를 사용하지 않으면 모든 타입에 유효한 함수 및 필드명만 사용할 수 있습니다. 아닐경우 아래와 같이 에러가 생깁니다.</p>
</blockquote>
<pre><code class="language-typescript">function printStatusCode(code: string | number) {
  console.log(`My status code is ${code.toUpperCase()}.`) // error: Property &#39;toUpperCase&#39; does not exist ontype &#39;string | number&#39;.
  Property &#39;toUpperCase&#39; does not exist on type &#39;number&#39;
}</code></pre>
<hr>
<h1 id="4-merged-types">4. Merged Types</h1>
<blockquote>
<p>위의 Union Type이 두 가지 이상의 타입을 결합하는 것이라면, Merged type 같은 경우는 같은 이름의 Interface / Namespace 등을 여러변 선언하여 필드를 병합하는 것을 말합니다.</p>
</blockquote>
<pre><code class="language-typescript">
interface Box {
  height: number;
  width: number;
}
interface Box {
  scale: number;
}
let box: Box = { height: 5, width: 6, scale: 10 };
</code></pre>
<blockquote>
<p>위와 같이 Box라는 인터페이스는 원래 <em><strong>height</strong>_과 **_width</em><strong>라는 필드명만 있었지만, _</strong>scale**_이라는 새로운 필드명이 새로 생기는 것을 알 수있습니다.</p>
</blockquote>
<pre><code class="language-typescript">interface Box {
  height: number;
  width: number;
}
interface Box {
      scale: number;
    width: string; // Error: &#39;width&#39; was also declared here.
}

let box: Box = { height: 5, width: 6, scale: 10 };</code></pre>
<blockquote>
<p>하지만, 착각하면 안되는 것이 기존의 필드명과 같은 필드명이 존재할 경우, 값을 재 할당하는 것이 아니기때문에 이 점을 유의하면 좋겠네요 </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[👋Goodbye VueCLI~ Hello Vite!👋]]></title>
            <link>https://velog.io/@seungjaekim-git/Goodbye-VueCLI-...-Hello-Vite</link>
            <guid>https://velog.io/@seungjaekim-git/Goodbye-VueCLI-...-Hello-Vite</guid>
            <pubDate>Tue, 22 Nov 2022 14:36:42 GMT</pubDate>
            <description><![CDATA[<h1 id="✈️-0-들어가면서-">✈️ 0. 들어가면서 ....</h1>
<hr>
<p>2021년 Vue의 개발자(<del>a.k.a 창조주</del>)인 Evan You님이 새로운 Vue3 생태계의 빌드 툴인 Vite 를 소개하였습니다. 그는 Vite는 기존의 Vue CLI으로 프로젝트를 빌드하는 것보다 최대 100배 빠른 속도를 경험할 수 있다고 하였는데요. 제가 Vue3으로 개발하면서 Vite가 무엇인지 너무 모르고 쓰고있다는 생각이 들어서 한번 기존의 Vue CLI와 비교하는 글을 적어보려고 합니다. </p>
<h1 id="📖-1-vite의-소개">📖 1. Vite의 소개</h1>
<hr>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/2d23801c-242f-402e-9a9c-a21c48186261/image.png" alt=""></p>
<p/>

<blockquote>
<p>Vite(프랑스어로 &quot;빠르다(Quick)&quot;를 의미하며, 발음은 &quot;veet&quot;와 비슷한 /vit/ 입니다.)은 빠르고 간결한 모던 웹 프로젝트 개발 경험에 초점을 맞춰 탄생한 빌드 도구이며, 두 가지 컨셉을 중심으로 하고 있습니다. </p>
</blockquote>
<ul>
<li>개발 시 네이티브 ES Module을 넘어 더욱 다양한 기능을 제공합니다. 가령, Hot Module Replacement (HMR)과 같은 것들 말이죠. </li>
<li>번들링 시, Rollup 기반의 다양한 빌드 커맨드를 사용할 수 있습니다. 이는 높은 수준으로 최적화된 정적(Static) 리소스들을 배포할 수 있게끔 하며, 미리 정의된 설정(Pre-configured)을 제공합니다.
...</li>
<li><ul>
<li>Vite 공식 문서 중 Vite 소개글 ... --</li>
</ul>
</li>
</ul>
<p/>

<p>솔직히 위의 말이 이해하기 난해해서, 나름대로 쉽게 정리하자면, </p>
<ul>
<li>Vite는 Vue CLI와 같이 프로젝트의 기초적인 발판 구조(scafolding)와 개발서버(dev Server)를 제공하는 빌드 툴입니다. </li>
<li>하지만, Vite는 개발 환경에서 기존의 Webpack에 의존하는 것이 아니라 브라우져의 네이티브 ES Module을 사용하여 더 빠른 빌드/재빌드 속도를 제공한다. </li>
<li>이 밖에도, &quot;HMR&quot;와 &quot;Rollup&quot; 이라는 빌드 커맨드를 사용하여 더 최적화된 빌드/배포를 경험할 수 있다. </li>
</ul>
<h1 id="💡-2-그래서-vite가-왜-얼마만큼-빠른데-">💡 2. 그래서 Vite가 왜, 얼마만큼 빠른데 ?</h1>
<hr>
<p>위의 소개글을 보고 이해가 되니, 이런 생각이 들더라구요. </p>
<blockquote>
<p>&quot;Vite가 왜 빠르고 ... Vue CLI는 왜 느렸던 것인지 ???&quot;</p>
</blockquote>
<p>확실히 현업에서 프로젝트가 진행됨에 따라 코드량과 정적 파일들이 늘어나면서, 테스트 한번 하기 위해 3분씩 기다리던 기억을 생각하면, 대체 그동안 왜 기존의 Vue CLI의 Webpack 빌드가 느렸던 것인지 궁금해지더라구요 ㅠㅅㅠ (<del>필자는 알아보기 전까지 RAM만 탓하고 있었음 ㅠ</del>)</p>
<p>찾아보니, 이런 빌드속도 차이는 WebPack 과 Vite의 개발서버 아키텍쳐의 차이에서 야기된다고 합니다</p>
<hr>
<h3 id="webpack-개발서버-아키텍쳐">Webpack 개발서버 아키텍쳐</h3>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/355e6e35-b323-4268-a363-6b10a3ba826c/image.png" alt=""></p>
<p>기존의 Vue CLI 방식은 Webpack에 의존하여 프로젝트의 모든 <code>import</code> 와 <code>require</code>을 처리하고 파일들(예를 들어, Sass,typescript...etc)을 변환하여 Javascirpt 번들을 만들었습니다. 그리고, 이러한 일을 서버사이드에서 전부 처리하였기 때문에, 프로젝트에 있는 <code>dependencies</code>가 많아 질 수록, 변화가 더 많을때마다 빌드/재빌드 속도가 더 늘어 난 것이였죠. 물론, 한번 빌드된 후 Webpack도 코드의 변화를 감지하여, 자동으로 브라우저에 빠르게 적용하여 주지만, 현업에서는 처음 빌드할 때가 정말 오래걸리더라구요 ㅠㅠ </p>
<hr>
<h3 id="vite의-개발서버-아키텍쳐">Vite의 개발서버 아키텍쳐</h3>
<p><img src="https://velog.velcdn.com/images/seungjaekim-git/post/c18f3204-dc7a-40ec-a326-5c9fd5878a30/image.png" alt="">
위의 단점을 해결하기 위해 Vite는 서버사이드에서 빌드를 처리하지 않고, 최신 브라우져에 추가된 JS Modules (ES Modules)들을 사용하여, 모든 파일들을 처리하지 않고 필수인 요소(e.g. index.html)들만 처리한뒤 브라우저에서 필요한 요소(예를들어, typescript, Sass 등)들이 생길때마다 on-demand 방식으로 dev server에 요청한다고 합니다. </p>
<p>그리고, 개발하던 와중 코드를 수정하면 Vite의 Hot Module Replacement(HMR)가 이를 감지하고, 자동으로 최소한의 저항만으로 업데이트한다고 합니다. (Webpack처럼요!) </p>
<p>이 아키텍쳐 덕분에 Vite는 더 빠른 개발서버를 제공할 수 있고, 브라우저는 보다 효율적으로 모듈을 처리할 수 있게된 것이죠 ! 최소 10배 ~ 최대 100배나 빠르다니 놀라운 부분이네요 ㅎ </p>
<blockquote>
<p>추가적으로 Vite와 VueCLI의 빌드 속도 밴치마크는 Evan You님의 <a href="https://www.youtube.com/watch?v=xXrhg26VCSc">Vite and VitePress</a> 영상의 6:30 쯤 보시면 보다 확실하게 확인할 수 있을거예여 ! </p>
</blockquote>
<h1 id="💡-3-오호-장점은-알겠어--근데-단점은-없니-">💡 3. 오호! 장점은 알겠어 ~ 근데 단점은 없니 ?</h1>
<hr>
<p>저도 이 부분이 조금 불안해서 찾아보니, 위에서 나온 말처럼 최신 브라우저의 ES Module 기능에 의존하기 때문에 오래된 브라우저(<del>IE 같은 ...</del>)에서는 <code>@vitejs/plugin-legacy</code>를 설치해줘야되고, CommonJS Module을 사용하는 라이브러리같은 경우는 Javascript Module으로 변환할 때 약간의 예외적인 상황이 발생 할 수있다고 하네요. 
그리고, 무엇보다 개발환경와 운영환경에서 다른 번들 툴(Rollup)을 사용해야 되기 때문에 어떤 차이가 발생할 수 있겠죠???</p>
<blockquote>
<p>하지만, 제가 지금 하는게 <strong><em>&quot;개발서버이니깐 &quot;</em></strong> 대부분의 단점은 어느정도 커버가 된다고 생각해요. 최신 브라우저는 프론트엔드 개발하면서 자연스럽게 사용할 것이고, CommonJS Module을 사용하는 라이브러리는 찾기가 힘들가고 하니 ... ㅎㅎ , 단점은 마지막에 말한 점 밖에 없는거 같아요. 애초에 Vite가 조명받는 부분은 개발 단계에서의 Debugging이니깐요 ! </p>
</blockquote>
<blockquote>
<p>Rollup(Vite의 운영 어플리케이션 번들 툴)은 Webpack과 같이 운영을 위한 빌드 기능을 수행한다고 하는데, 아직까지 정확하게 Webpack과 어떤 점이 다른지는 잘 모르겠습니다. 추후에 알게되면 정리해보죠 뭐 ㅎ  </p>
</blockquote>
<h1 id="🖥️-4-그래서-정리를-하자면-">🖥️ 4. 그래서 정리를 하자면 ...</h1>
<hr>
<table>
<thead>
<tr>
<th align="left">Vue CLI 장점</th>
<th align="center">Vue CLI 단점</th>
<th align="right">비고</th>
</tr>
</thead>
<tbody><tr>
<td align="left">빌드환경이 개발과 운영이 같다</td>
<td align="center">프로젝트가 커질 수록 빌드 속도도 늘어난다</td>
<td align="right"></td>
</tr>
<tr>
<td align="left">모든 dependency를 번들링할 수 있다</td>
<td align="center">vue project만 scaffolding 가능</td>
<td align="right"></td>
</tr>
<tr>
<td align="left">p.s. Vue2랑 호환이 된다.</td>
<td align="center"></td>
<td align="right"></td>
</tr>
</tbody></table>
<hr>
<table>
<thead>
<tr>
<th align="left">Vite 장점</th>
<th align="center">Vite 단점</th>
<th align="right">비고</th>
</tr>
</thead>
<tbody><tr>
<td align="left">기존 Webpack보다 10-100배 빠르다</td>
<td align="center">최신 브라우저에서 사용 권장</td>
<td align="right"></td>
</tr>
<tr>
<td align="left">Vue3+ 다른 프로임워크 (React)와도 호환이 된다.</td>
<td align="center">CommonJS 모듈과 호환이 안 맞을수도 있다.</td>
<td align="right"></td>
</tr>
<tr>
<td align="left"></td>
<td align="center">개발이랑 운영환경의 빌드 툴이 다르다 (Rollup)</td>
<td align="right"></td>
</tr>
</tbody></table>
<h1 id="5-마치면서-">5. 마치면서 ...</h1>
<p>제목에는 Vue CLI 는 굿바이라고 했지만, 솔직히 Vite와 Vue CLI 둘 중 어느 것을 사용하는지는 개발자의 마음같아요. 지금 제가 새로운 프로젝트를 <code>vite</code>으로 진행하고 있지만, 기존에 Vue CLI으로 진행한 프로젝트를 Vite으로 바꿀만큼의 메리트는 없을거 같습니다. <del>지금까지 개발하던 환경을 Vite을 바꾸는데 쓸 시간을 고려하면 오히려 역효과일수도 ...</del></p>
<p>하지만, 일단 Vite의 개발자가 Vue의 개발자와 같은 분이니깐 호환성이 잘 맞지 않을까요 ??? Vue 개발자라면 한번 Vite 쓰는거 강추합니다. 그럼 이만 ... ㅎ </p>
<h1 id="📖-6-references">📖 6. References</h1>
<hr>
<ul>
<li><a href="https://vitejs-kr.github.io/guide/why.html">https://vitejs-kr.github.io/guide/why.html</a></li>
<li><a href="https://vuejsdevelopers.com/2020/12/07/vite-vue-cli/?ref=morioh.com&amp;utm_source=morioh.com">https://vuejsdevelopers.com/2020/12/07/vite-vue-cli/?ref=morioh.com&amp;utm_source=morioh.com</a></li>
<li><a href="https://www.vuemastery.com/blog/vite-vs-webpack/">https://www.vuemastery.com/blog/vite-vs-webpack/</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>