<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nily</title>
    <description>The latest articles on DEV Community by Nily (@nily).</description>
    <link>https://dev.to/nily</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F920088%2F6b61774e-63d6-4c4c-b80c-2bdfcc0846b8.jpeg</url>
      <title>DEV Community: Nily</title>
      <link>https://dev.to/nily</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nily"/>
    <language>en</language>
    <item>
      <title>React vs Angular</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Wed, 14 Feb 2024 08:36:02 +0000</pubDate>
      <link>https://dev.to/nily/angular-vs-react-58c4</link>
      <guid>https://dev.to/nily/angular-vs-react-58c4</guid>
      <description>&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt;와 &lt;strong&gt;Angular&lt;/strong&gt;를 비교해 놓은 글들은 이미 상당히 많다.&lt;/p&gt;

&lt;p&gt;그래서 나는, Angular를 현업에서 쓰면서 내가 겪은 React와의 차이점에 대해 글을 써보려고 한다🤓&lt;/p&gt;

&lt;p&gt;가장 크게 느끼는 차이는 data binding 방식이다.&lt;/p&gt;

&lt;p&gt;Angular는 React와 다르게, &lt;a href="https://www.angular.kr/guide/two-way-binding"&gt;two-way binding&lt;/a&gt;이 가능하다.&lt;/p&gt;

&lt;p&gt;즉, &lt;strong&gt;부모 ↔️ 자식 컴포넌트 사이에 데이터를 공유&lt;/strong&gt;할 수 있다는 것이다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagd6ynhhx1pzqpg8uu59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagd6ynhhx1pzqpg8uu59.png" alt="dataBinding" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React는 부모에서 자식으로 데이터를 전달하는 방식이었다면, &lt;strong&gt;Angular에선 자식에서 부모로 데이터를 전달 하는 것이 가능&lt;/strong&gt;하다. &lt;/p&gt;

&lt;p&gt;하지만, two-way binding에도 단점은 존재한다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;데이터가 변화함에 따라 view와 model도 그 상태를 감지해야 하기 때문에 &lt;strong&gt;memory 사용량이 단방향보다 크다&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;간결한 코드로 가독성이 높아서 복잡해보이지 않을 수 있지만, 코드의 결합도가 높아져 &lt;strong&gt;디버깅이 어려울 수 있다&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;실제로, 특정 컴포넌트에 간단한 기능을 추가하기 위해 코드를 분석하는 과정에서 컴포넌트 전체 데이터 흐름을 파악하는데 꽤 오래 걸린 적이 종종 있었다.&lt;/p&gt;




&lt;p&gt;두번째로 느낀 차이는, Angular는 배워야 할 개념이 꽤 많다는 것이다.&lt;br&gt;
(= learing curve가 높다😅)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;modules&lt;/li&gt;
&lt;li&gt;dependency injection&lt;/li&gt;
&lt;li&gt;services&lt;/li&gt;
&lt;li&gt;templates&lt;/li&gt;
&lt;li&gt;RxJS&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;따지고 보면, &lt;strong&gt;Angular는 framework이고 React는 View만 담당하는 library&lt;/strong&gt;이기 때문에 당연한 걸지도 모른다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://angular.io/tutorial/first-app/first-app-lesson-09"&gt;service&lt;/a&gt;를 사용하면서 &lt;strong&gt;typescript에서 class의 구조&lt;/strong&gt;를 더 잘 이해하게 되고, &lt;a href="https://angular.io/guide/rx-library"&gt;RxJS&lt;/a&gt;를 통해서도 처음에 헷갈렸던 비동기를 자유자재로 사용할 수 있게 되었다.&lt;/p&gt;

&lt;p&gt;배워야 할 것들이 많은 만큼, 한 번 그 개념을 이해하고 자주 사용하면서 오픈 소스 라이브러리 등 새로운 코드를 분석하는데 있어서 전체 흐름을 파악하는데 아주 많은 도움이 되었다.&lt;/p&gt;




&lt;p&gt;현재는 Angular보다 React가 점유율이 더 높고, 그만큼 커뮤니티나 생태계가 활성되어 있어서 많은 기업에서 사용중이다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mrsxqszsuvo1ljm4xjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mrsxqszsuvo1ljm4xjq.png" alt="Image description" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;어떤 개발팀에서는 Angular에서 React로 전환하고 있다는 글도 보았다. (&lt;a href="https://medium.com/29cm/%EC%83%81%ED%92%88-%EC%83%81%EC%84%B8-react%EC%A0%84%ED%99%98%EA%B8%B0-e79f16e5cf4e"&gt;link&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;나도 지금은 떠났지만, 이전 회사의 개발팀에 React로 전환하자는 의견을 내기도 했었다.(팀 내부에서 여러가지 이유로 진행하진 못했지만😭)&lt;/p&gt;

&lt;p&gt;React냐 Angular냐 여전히 프론트엔드 개발 생태계에서 자주 회자되는 이슈인 만큼, 자주 관심을 가지고 찾아봐야 겠다.&lt;/p&gt;




&lt;p&gt;&lt;small&gt;출처&lt;/small&gt;&lt;br&gt;
&lt;small&gt;&lt;a href="https://www.clickittech.com/developer/react-vs-angular/"&gt;https://www.clickittech.com/developer/react-vs-angular/&lt;/a&gt;&lt;/small&gt;&lt;br&gt;
&lt;small&gt;- &lt;a href="https://www.simform.com/blog/angular-vs-react/"&gt;https://www.simform.com/blog/angular-vs-react/&lt;/a&gt;&lt;/small&gt;&lt;br&gt;
&lt;small&gt;- &lt;a href="https://borstch.com/blog/understanding-angulars-two-way-data-binding"&gt;https://borstch.com/blog/understanding-angulars-two-way-data-binding&lt;/a&gt;&lt;/small&gt;&lt;br&gt;
&lt;small&gt;- &lt;a href="https://www.simplilearn.com/tutorials/angular-tutorial/angular-service"&gt;https://www.simplilearn.com/tutorials/angular-tutorial/angular-service&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>react</category>
      <category>framework</category>
      <category>library</category>
    </item>
    <item>
      <title>Deploying a Static Site (feat.Vite, gh-pages)</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Mon, 15 Jan 2024 03:47:26 +0000</pubDate>
      <link>https://dev.to/nily/deploying-a-static-site-featvite-gh-pages-19pb</link>
      <guid>https://dev.to/nily/deploying-a-static-site-featvite-gh-pages-19pb</guid>
      <description>&lt;p&gt;다시 React 공부를 시작했다.&lt;/p&gt;

&lt;p&gt;간단한 토이 프로젝트를 만들어 &lt;strong&gt;gh-pages&lt;/strong&gt;로 간단히 배포하려고 했는데, 여기서 이슈가 발생했다. &lt;/p&gt;

&lt;p&gt;배포후 확인해보니 &lt;strong&gt;404 not found error&lt;/strong&gt;가 뜨는 것!&lt;/p&gt;

&lt;p&gt;구글링 하다가 vite 관련 &lt;a href="https://stackoverflow.com/a/76110734"&gt;해결방법&lt;/a&gt;을 찾았는데 vite에 익숙해질겸 해서, 우선 creae-react-app으로 만들어진 프로젝트를 vite로 migration하는 것 부터 시작했다.&lt;/p&gt;

&lt;p&gt;(요즘은 cra보다 가볍고 빠른 vite를 사용하는 추세인 것 같다. &lt;a href="https://semaphoreci.com/blog/vite"&gt;관련 링크&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/how-to-migrate-from-create-react-app-to-vite/"&gt;migration&lt;/a&gt;하는 과정은 크게 어렵지 않았다.&lt;/p&gt;




&lt;p&gt;하지만 vite로 migration 후, 위 해결 방법을 적용해도 빈 페이지가 나오는 이슈는 여전히 있었다😅&lt;/p&gt;

&lt;p&gt;다른 방법들을 다 적용해봐도 해결을 못하고 있던 중에, &lt;strong&gt;React Router path&lt;/strong&gt;와 관련되어 있다는 것을 찾았다. (&lt;a href="https://blog.devgenius.io/how-to-deploy-your-vite-react-app-to-github-pages-with-and-without-react-router-b060d912b10e"&gt;관련 링크&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;vite.config.ts&lt;/code&gt; 파일에 &lt;strong&gt;basename은 &lt;code&gt;/repoName/&lt;/code&gt;으로 설정되어있는데, router의 basename은 추가로 설정하지 않았기 때문에&lt;/strong&gt; &lt;code&gt;/&lt;/code&gt;로 되어 있다는 게 원인이었다.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&amp;lt;repoName&amp;gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;viteTsconfigPaths&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;    
      &lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;따라서, router의 basename을 아래와 같이 조건에 맞는 path로 변경해주면 된다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RouterProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...];&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/repoName/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RouterProvider&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;import.meta.env.DEV&lt;/code&gt;는 Vite에 내장된 환경변수로, dev 모드일 때 값을 return 한다.&lt;/p&gt;




&lt;p&gt;이 이슈를 해결하기 위해, 때문에 꼬박 하루를 사용했다. &lt;/p&gt;

&lt;p&gt;초반엔 당연히 배포 설정 문제일 거라 생각하고 gh-pages 관련 이슈 위주로 찾아봤었다. router path 문제였을 줄이야...&lt;/p&gt;

&lt;p&gt;위 블로그에도 나와있지만, 404 not found error 메시지가 화면에 뜨는데 console에선 어떤 에러도 보이지 않아서 더욱 의심하지 않았던 것 같다.&lt;/p&gt;

&lt;p&gt;나와 같은 이슈를 겪는 사람들에게 도움이 되길 바라며..!!🤓&lt;/p&gt;

</description>
      <category>vite</category>
      <category>ghpages</category>
      <category>deploy</category>
      <category>react</category>
    </item>
    <item>
      <title>Popper.js with Framework</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sun, 30 Jul 2023 10:31:11 +0000</pubDate>
      <link>https://dev.to/nily/popperjs-with-angular-3c87</link>
      <guid>https://dev.to/nily/popperjs-with-angular-3c87</guid>
      <description>&lt;p&gt;새로운 feature 기능이 들어가면서, 기존에 사용하던 popover에 UI에 이슈가 생겼다.&lt;/p&gt;

&lt;p&gt;우리 팀은 &lt;strong&gt;&lt;a href="https://valor-software.com/ngx-bootstrap/#/documentation"&gt;ngx-bootstrap&lt;/a&gt;&lt;/strong&gt;을 사용중인데, popover에 component를 넣는 방식을 사용하자 간헐적으로 그 위치가 맞지 않고 덜덜거렸다. &lt;br&gt;
(&lt;strong&gt;+&lt;/strong&gt; 기존의 popover도 hover시, 다른 popover의 position에 영향을 미치는 버그는 있었다😂)&lt;/p&gt;

&lt;p&gt;열심히 구글링한 결과, ngx-bootstrap의 고질적인 이슈로, 버그가 수정되지 않고 계속 있는 것 같았다. &lt;/p&gt;

&lt;p&gt;시니어분께 상황을 공유하니 이참에 새로운 popover 라이브러리로 갈아타는게 어떻겠냐고 의견을 주셨다. 기존에 있던 버그 + 현재 발생한 이슈를 동시에 다 해결할 수 있는 방법이었다.&lt;/p&gt;

&lt;p&gt;여러 패키지들을 조사한 결과, &lt;a href="https://popper.js.org/"&gt;poppper.js&lt;/a&gt;가 가장 대중적이고 널리 쓰이는 듯 했다. &lt;/p&gt;

&lt;p&gt;해당 패키지를 바로 Angular에 적용하면 되는 줄 알았는데, &lt;br&gt;
알고보니 popper.js는 &lt;strong&gt;순수 Javascript 모듈이기 때문에 Angular에서 사용 가능하게 wrapping 된 버전&lt;/strong&gt;(= Angular 구조에 맞게 popper.js를 사용할 수 있도록 해놓은 것)을 또 찾아야 했다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 Tip:&lt;/strong&gt; Angular 관련 모듈을 검색할 땐, &lt;code&gt;ng&lt;/code&gt; or &lt;code&gt;ngx&lt;/code&gt;를 앞에 붙여 찾으면 더 쉽게 찾을 수 있다.&lt;/p&gt;

&lt;p&gt;ex) &lt;code&gt;ng popper&lt;/code&gt;, &lt;code&gt;ngx popper&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;검색 결과, &lt;a href="https://github.com/MrFrankel/ngx-popper"&gt;ngx-popper&lt;/a&gt;를 쓰기로 결정했다.&lt;/p&gt;

&lt;p&gt;ngx-popper의 &lt;code&gt;package-lock.json&lt;/code&gt;을 보면 아래와 같이 popper.js에 dependency가 걸려있다. 최소 &lt;code&gt;1.14.3&lt;/code&gt; 버전을 사용해야 하는것.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"popper.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.14.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resolved"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://registry.npmjs.org/popper.js/-/popper.js-1.14.3.tgz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"integrity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;우리 서비스는 popper.js &lt;code&gt;1.12.9&lt;/code&gt; 버전을 사용중이었기 때문에 버전을 올려야했다. dependency가 걸리는 패키지들까지 업데이트 후 적용하니 잘 동작하는 걸 확인할 수 있었다.&lt;/p&gt;




&lt;p&gt;이번 일을 통해, 아래와 같이 2가지 사항을 배울 수 있었다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 사용하는 Framework에 맞게 라이브러리를 wrapping 하여 사용하기&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;2. 새로운 라이브러리를 추가할 땐, dependency 반드시 확인하기&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;시니어 분께서 "사용하는 Framework에 맞게 라이브러리를 wrapping 하여 사용하기"는 나중에 시간 될 때 한 번 꼭 해보라고 추천도 해주셨다.&lt;/p&gt;

&lt;p&gt;Angular 구조를 이해하고 라이브러리가 프레임 워크 안에서 어떻게 동작하는지 알 수 있을것 같았다. (&lt;a href="https://medium.com/angular-in-depth/wrapping-commonjs-library-in-angular-8-directive-on-the-example-of-mark-js-976cbcd5d10a"&gt;관련 링크&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;시간 될때 꼭 해보고 포스팅까지 해보는 걸로💪🏻&lt;/p&gt;

</description>
      <category>popper</category>
      <category>angular</category>
      <category>npm</category>
      <category>package</category>
    </item>
    <item>
      <title>Angular version upgrade v4 to v12 - part 2: performance</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 06 May 2023 12:17:45 +0000</pubDate>
      <link>https://dev.to/nily/angular-version-upgrade-v4-to-v12-part-2-performance-12ib</link>
      <guid>https://dev.to/nily/angular-version-upgrade-v4-to-v12-part-2-performance-12ib</guid>
      <description>&lt;p&gt;Angular 업그레이드로 인해 서비스의 성능이 얼만큼 개선되었는지 궁금했다.&lt;/p&gt;

&lt;p&gt;크롬에서 제공하는 &lt;a href="https://developer.chrome.com/docs/lighthouse/overview/"&gt;lighthouse&lt;/a&gt;라는 툴을 이용해 성능을 비교해봤다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[v4]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33trbgweqi1m5gvdxvsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33trbgweqi1m5gvdxvsj.png" alt="v4 performance" width="800" height="924"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[v12]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4axl59xc75rzri2vzp1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4axl59xc75rzri2vzp1.png" alt="v12 performance" width="800" height="876"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;performance의 측정 항목은 아래의 5가지 metric으로 정의된다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First Contentful Paint&lt;/li&gt;
&lt;li&gt;Largest Contentful Paint&lt;/li&gt;
&lt;li&gt;Total Blocking Time&lt;/li&gt;
&lt;li&gt;Cumulative Layout Shift&lt;/li&gt;
&lt;li&gt;Speed Index&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;performance 점수는 33에서 60으로 &lt;strong&gt;약 1.8배 상승&lt;/strong&gt;했다.&lt;br&gt;
각 항목에 어떤 변화가 있었는지는 아래 표로 정리해 보았다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;v4&lt;/th&gt;
&lt;th&gt;v12&lt;/th&gt;
&lt;th&gt;차이&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First Contentful Paint&lt;/td&gt;
&lt;td&gt;1.3s&lt;/td&gt;
&lt;td&gt;1.8s&lt;/td&gt;
&lt;td&gt;+ 38%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Largest Contentful Paint&lt;/td&gt;
&lt;td&gt;16.4s&lt;/td&gt;
&lt;td&gt;4.2s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;- 74%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Blocking Time&lt;/td&gt;
&lt;td&gt;1,290ms&lt;/td&gt;
&lt;td&gt;90ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;- 93%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cumulative Layout Shift&lt;/td&gt;
&lt;td&gt;0.008&lt;/td&gt;
&lt;td&gt;0.007&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;- 12%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Index&lt;/td&gt;
&lt;td&gt;7.7s&lt;/td&gt;
&lt;td&gt;2.4s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;- 68%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;가장 많은 변화가 있었던 항목은 &lt;strong&gt;Total Blocking Time&lt;/strong&gt;과 &lt;strong&gt;Largest Contentful Paint&lt;/strong&gt;였다. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;TBT:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds. &lt;br&gt;
마우스 클릭, 화면 탭 또는 키보드 누름과 같은 &lt;strong&gt;사용자 입력으로부터 페이지가 응답하지 못하도록 차단된 총 시간&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;LCP:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LCP measures when the largest content element in the viewport is rendered to the screen. This approximates when the main content of the page is visible to users.&lt;br&gt;
&lt;strong&gt;가장 큰 컨텐츠를 렌더링 하는데 걸리는 시간&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lighthouse는 검사 조건에 따라 점수의 변동성이 있긴 하지만, 여러번 검사를 실시한 결과 전반적으로 performance가 향상된 것을 확인할 수 있었다.&lt;br&gt;
(4에서 12까지 버전이 확 높아진 만큼, 성능 개선은 당연한 것 일수도..)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg642spljiq0l4jccrly1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg642spljiq0l4jccrly1.png" alt="Image description" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;검사 보고서를 보면, 어떤 부분에서 &lt;strong&gt;더 성능을 향상할 수 있는지 제안&lt;/strong&gt;까지 해준다.&lt;/p&gt;

&lt;p&gt;성능 최적화를 위해 단순히 프레임 워크 업그레이드에 의존하는 것이 아니라, Lighthouse등 여러 tool등의 도움을 받아 꾸준히 점검하고 시간을 투자해야 한다는 것을 또 깨닫는 경험이었다.&lt;/p&gt;




&lt;p&gt;Angular12의 feature들 참고:&lt;br&gt;
&lt;a href="https://blog.angular.io/angular-v12-is-now-available-32ed51fbfd49"&gt;관련 링크&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>upgrade</category>
      <category>lighthous</category>
      <category>performance</category>
    </item>
    <item>
      <title>Angular version upgrade v4 to v12 - part1</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 08 Apr 2023 08:53:10 +0000</pubDate>
      <link>https://dev.to/nily/angular-version-upgrade-v4-to-v12-19cg</link>
      <guid>https://dev.to/nily/angular-version-upgrade-v4-to-v12-19cg</guid>
      <description>&lt;p&gt;때는 작년 3월, 우리 팀에서 계속 미뤄왔던 Angular 버전 업그레이드를 진행하기로 했다. v4를 사용하고 있었으니 현재 버전(v16)과 꽤 차이가 나는 것...&lt;/p&gt;

&lt;p&gt;시니어 개발자 분께서 말씀하시길 꾸준히 업그레이드를 해왔어야 하는데, 계속 미루느라 기술 부채가 되어버렸다고 했다.😅&lt;/p&gt;

&lt;p&gt;목표는 &lt;strong&gt;v12&lt;/strong&gt;까지 업그레이드 하는것이었다.&lt;br&gt;
한 번에 12까지 갈 수 없으니 각 버전별로 branch를 만들고 차근차근 올려보기로 했다. 한 스프린트 내에 하긴 무리라고 판단되어 기간도 넉넉히 2-3 스프린트 정도로 잡았다.&lt;/p&gt;

&lt;p&gt;가장 큰 이슈는 dependency가 걸리는 package들이 꽤 많아, &lt;strong&gt;버전 업그레이드 시 사용할 수 없는 패키지들이 생긴다&lt;/strong&gt;는 것이었다.&lt;/p&gt;

&lt;p&gt;Angular 공식 페이지에 &lt;a href="https://update.angular.io/" rel="noopener noreferrer"&gt;업데이트 가이드&lt;/a&gt;는 잘 되어있다.&lt;/p&gt;

&lt;p&gt;ex)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5zqkqm7qbqa2ucx6xkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5zqkqm7qbqa2ucx6xkd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;내 주요 업무는 dependency가 걸리는 package들을 변경하는 것이었다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. CSV 다운로드 모듈 변경&lt;/strong&gt;&lt;br&gt;
 패키지 이름에서 알 수 있듯이, 현재 사용중인 angular2-csv는 Angular6까지 밖에 지원하지 않았다.&lt;/p&gt;

&lt;p&gt;Angular 최신버전까지 지원 + 비교적 최근까지 업데이트 되어있음 + 깃헙 스타 갯수 까지 적절한 조건이면서, 안정적인 패키지를 찾는 일이 쉽진 않았다.&lt;/p&gt;

&lt;p&gt;여기서 한가지 팁은, &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npmjs&lt;/a&gt;에서 Angular 관련패키지를 검색하고 싶다면 앞에 &lt;code&gt;ng&lt;/code&gt; or &lt;code&gt;ngx&lt;/code&gt;를 붙이면 더 정확한 검색 결과를 얻을 수 있다. &lt;/p&gt;

&lt;p&gt;ex) &lt;code&gt;ng csv download&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;한참 검색하다가, 이전에 사용하던 패키지를 fork 해서 Angular 최신 버전까지 지원 하는 걸 발견했다.🙌&lt;/p&gt;

&lt;p&gt;패키지를 교체하고 이제 이전과 동일하게 잘 동작하는지 확인하는 과정을 거쳤다.&lt;br&gt;
우리 서비스에 CSV 다운로드 하는 기능을 지원하는 곳이 꽤 많이 있었기에, 전반적으로 다 꼼꼼하게 확인이 필요했다. &lt;/p&gt;

&lt;p&gt;다운로드시 column header 순서가 이전과 달라져서, 그 부분만 로직을 추가하니 잘 동작했다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Renderer =&amp;gt; Renderer2&lt;/strong&gt;&lt;br&gt;
Angular4 이후로 Renderer에서 Renderer2로 변경되면서 이전 모듈에 depdency가 걸리는 패키지들이 있었다.&lt;/p&gt;

&lt;p&gt;이 중에 하나 이슈가 있었던 건, 고객 정보 영역에 사용하던 필드 수정 / 편집이 가능한 패키지였다. Renderer2로 모듈이 변경되면서, 현재 사용중인 라이브러리를 대체할 수 있는 것을 찾지 못했다. 기존 기능과 동일하게 동작하지 않거나, UI가 너무 달라지는 등 적합한 패키지가 없었다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78fopwjnate2p98nz5c0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78fopwjnate2p98nz5c0.png" alt="inline-editor"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;그리고 사실, 해당 부분은 UI 개선이 곧 이루어질 계획이 있었기에 이번 기회에 &lt;strong&gt;라이브러리에 의존하지 않고 component를 직접 구현하는 것이 낫겠다&lt;/strong&gt;는 의견이 나왔다.&lt;/p&gt;

&lt;p&gt;사실 좋은 라이브러리가 있다면, 가져다쓰는 것도 좋지만 이벤트나 method, property등 내부 요소가 한정적이기 때문에 그 확장성이 제한적이라는 단점도 있다.&lt;/p&gt;

&lt;p&gt;자체 component로 만들어 쓴다면, 확장성 뿐만 아니라 패키지 의존성을 낮출 수 있기 때문에 해당 부분은 기존 기능과 동일하게 공통 component로 분리하는 작업도 같이 진행했다. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. style-loader 제거&lt;/strong&gt;&lt;br&gt;
추후 v14까지 업그레이드를 위해 CSS파일 load방식도 변경하기로 했다. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;글로벌 css파일은 angular.json의 styles에 추가&lt;/li&gt;
&lt;li&gt;각 component.ts의 css파일 styleUrls에 추가&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[변경 전]&lt;br&gt;
&lt;code&gt;component.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader!quill/dist/quill.core.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader!quill/dist/quill.snow.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[변경 후]&lt;br&gt;
&lt;code&gt;angular.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules/quill/dist/quill.core.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules/quill/dist/quill.snow.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[변경 전]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style-loader!./exampleComponent.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[변경 후]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./exampleComponent.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./exampleComponent.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 때, 한가지 이슈가 있었다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;styleUrls로 css파일 load시 &lt;strong&gt;parent component의 css child component에 적용되지 않는 것&lt;/strong&gt;!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;css 선택자에 &lt;code&gt;::ng-deep&lt;/code&gt;을 사용하여 해결할 수 있지만, 권장하지 않는 방법이었다. (&lt;a href="https://stackoverflow.com/questions/36527605/how-to-style-child-components-from-parent-components-css-file" rel="noopener noreferrer"&gt;참고 링크&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;구글링하다 찾은 방법은, encapsulation 속성을 사용하는 것이었다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ViewEncapsulation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;....&lt;/span&gt;
    &lt;span class="na"&gt;encapsulation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ViewEncapsulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;None&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;위에 언급한 이슈들 외에도, 자잘한 이슈들이 많이 있었다. 아마 버전 업그레이드 후기2탄을 작성해야 할 수도...&lt;/p&gt;

&lt;p&gt;v4에서 v12로 가는 건 쉬운일은 아니었다. &lt;/p&gt;

&lt;p&gt;패키지 뿐만 아니라, 사용 모듈이 변경되면 이전과 방식이 달라져 또 일일이 확인해야하고, ivy엔진으로 인한 build 에러, UI 깨지는 이슈 등 전체 서비스 기능에 영향을 미치는 부분이라 시간도 꽤 오래 걸렸다.&lt;/p&gt;

&lt;p&gt;또 업그레이드를 진행하는 동안 약 한달 넘게 정식 배포를 하지도 않아서, 업그레이드 후 최종 배포하는 날 심장이 두근두근 했던 게 생각난다. &lt;/p&gt;

&lt;p&gt;사용자가 직접적으로 큰 변화를 느낄 순 없었겠지만, 개인적으로 매우 뿌듯했다. 버전 업하면서 Renderer나 encapsultaion등 Angular에 대한 더 깊은 지식도 생기고 여러 패키지들을 살펴보며 보는 눈(?)이 생겼다고 해야하나 여러모로 많이 배울 수 있는 기회였다.&lt;/p&gt;

&lt;p&gt;프레임 워크를 최신 버전으로 꾸준히 유지한다면, 그 다음 버전으로 가는 것은 크게 어렵지 않다고 한다. (그 사이 구조적으로 큰 변화가 생기거나 사이즈가 큰 feature가 추가되는 것이 아니라면)&lt;/p&gt;

&lt;p&gt;개인 프로젝트를 진행할 땐, 버전의 중요성을 크게 깨닫지 못했었던 같다. 항상 최신버전의 최신 기능들을 모두 사용할 수 있다보니 불편함도 없었다.&lt;/p&gt;

&lt;p&gt;v16까지 업그레이드 하는 날을 기대하며..🤩🤩&lt;/p&gt;

</description>
      <category>angular</category>
      <category>version</category>
      <category>upgrade</category>
    </item>
    <item>
      <title>E2E Testing with Jest &amp; Puppeteer</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 01 Apr 2023 11:59:50 +0000</pubDate>
      <link>https://dev.to/nily/e2e-testing-with-jest-puppeteer-2c6m</link>
      <guid>https://dev.to/nily/e2e-testing-with-jest-puppeteer-2c6m</guid>
      <description>&lt;p&gt;입사후, 온보딩 프로젝트가 끝나고 정식으로 처음맡았던 일이 바로 &lt;strong&gt;E2E 테스트&lt;/strong&gt; 관련 일이었다.&lt;/p&gt;

&lt;p&gt;기존에 &lt;strong&gt;nightwatch&lt;/strong&gt;로 동작하던 것을 &lt;strong&gt;jest + puppeteer&lt;/strong&gt; 환경으로 변경하고 Test case를 추가하는 것!!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://jestjs.io/docs/26.x/getting-started"&gt;jest&lt;/a&gt;: 테스트 가능한 자바스크립트 라이브러리&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/puppeteer/puppeteer#usage"&gt;puppeteer&lt;/a&gt;: &lt;strong&gt;headless Chrome&lt;/strong&gt; 이나 &lt;strong&gt;Chromium&lt;/strong&gt;을 컨트롤하기 위한 Node.js 라이브러리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;headless browser&lt;/strong&gt;란?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A headless browser is a web browser without a graphical user interface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;출처: &lt;a href="https://en.wikipedia.org/wiki/Headless_browser"&gt;Wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GUI가 없이 작동되는(= 렌더링) 브라우저 라고 이해하면 된다.&lt;/p&gt;




&lt;p&gt;jest에 대한 일반적인 내용 보단, Test case를 작성하면서 겪었던 문제와 경험 위주로 작성해보려고 한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;이슈1:&lt;/strong&gt; test 시작 전, &lt;a href="https://jestjs.io/docs/api#beforeallfn-timeout"&gt;&lt;code&gt;beforeAll&lt;/code&gt;&lt;/a&gt;안의 함수들이 모두 실행되지 않고 테스트가 시작되므로 error발생.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;beforeAll&lt;/code&gt; 안에 workspace에서 로그인후 해당 상담사의 상태를 체크하고, &lt;code&gt;online&lt;/code&gt;이 아니라면 &lt;code&gt;online&lt;/code&gt;으로 변경해주는 함수가 있었다.   &lt;/p&gt;

&lt;p&gt;상담사 상태가 온라인이어야만, 그 다음 test case들이 정상적으로 실행되기 때문에 반드시 beforeAll 함수 안에서 실행되어야만 했는데,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;기다려주지 않고 다음 case들이 실행되어 그 이후 case들은 당연히 error가 발생하는 문제&lt;/strong&gt;였다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nf"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.....&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AGENT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AGENT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;checkUserState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;jest문서에서 해결책을 찾을 수 있었다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Optionally, you can provide a timeout (in milliseconds) for specifying how long to wait before aborting. The default timeout is 5 seconds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;default timeout이 5초이기 때문에, 아래와 같이 setTimeout 시간을 명시적으로 설정해주면 해결할 수 있었다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;이슈 2:&lt;/strong&gt; 각각 다른 브라우저 2개에서 연관된 테스트 실행시, error 발생.&lt;/p&gt;

&lt;p&gt;유저와 상담사간 상담이 진행되는 test case이기 때문에 브라우저 2개가 필요했다. &lt;/p&gt;

&lt;p&gt;workspace와 채팅앱 화면을 왔다갔다 하며 테스트가 진행되어야 하는데, 채팅앱에서 workspace으로 화면에 접근이 되지 않았다.&lt;/p&gt;

&lt;p&gt;알고보니, tc를 진행할 &lt;strong&gt;browser에 focus&lt;/strong&gt;를 줘야 하는 것이었다.&lt;/p&gt;

&lt;p&gt;browser를 컨트롤 하는 부분이므로, puppeteer의 &lt;a href="https://pptr.dev/api/puppeteer.page.bringtofront"&gt;bringToFront&lt;/a&gt; method를 이용하면 된다.&lt;br&gt;
(각각 다른 브라우저 뿐만 아니라, 한 브라우저 내의 tab 전환도 가능하다.)&lt;/p&gt;




&lt;p&gt;입사전 혼자 프로젝트를 진행할 땐, 테스트의 중요성을 잘 깨닫지 못해서 테스트 코드는 우선 순위에서 밀려나 작성하지 않았던 경우가 대부분이었다.&lt;/p&gt;

&lt;p&gt;서비스 제품을 개발하는 팀에선, 테스트 코드가 필수인 걸 알게 됐다.&lt;br&gt;
특히, 큰 feature들이 추가되는 경우라면 기존 로직이 동일하게 동작하는지 side effect이 없는지 등 에러를 방지할 수 있기 때문이다.&lt;/p&gt;

&lt;p&gt;E2E 테스트와 더불어, unit 테스트 기반의 TDD를 실천하는 우리 개발팀이 될 수 있길 바라며...💪🏻&lt;/p&gt;

</description>
      <category>testing</category>
      <category>jest</category>
      <category>puppeteer</category>
      <category>e2e</category>
    </item>
    <item>
      <title>Why Lodash?</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 18 Mar 2023 08:43:02 +0000</pubDate>
      <link>https://dev.to/nily/why-lodash-2690</link>
      <guid>https://dev.to/nily/why-lodash-2690</guid>
      <description>&lt;p&gt;&lt;strong&gt;lodash&lt;/strong&gt;는 현재 회사의 온보딩 교육 과정에서 처음 접했던 라이브리러리 였다. &lt;/p&gt;

&lt;p&gt;회사의 기술 스택을 전반적으로 경험해 볼 수 있는 프로젝트 였는데, 시니어 개발자 분께서 프론트엔드에서 가장 널리 쓰이고 있는 것이니, 꼭 익숙해지라고 하셨던 생각이 난다.&lt;/p&gt;

&lt;p&gt;아래 설문조사에 따르면, lodash가 1위를 차지한 것을 볼 수 있다.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkz6qlzt61fuq0okzvmoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkz6qlzt61fuq0okzvmoo.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;출처: &lt;a href="https://2022.stateofjs.com/en-US/other-tools/" rel="noopener noreferrer"&gt;https://2022.stateofjs.com/en-US/other-tools/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;이젠 필수가 되어버린 lodash를 쓰며 느낀 장점들을 써보려고 한다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 코드의 가독성이 좋아진다&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;함수 이름이 직관적이고, 코드를 간결하게 쓸 수 있기 때문에 그 흐름이 비교적 쉽게 이해된다.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2]&lt;/span&gt;
&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// [2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. native 함수에서 가능하지 않았던 것들이 가능해진다.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;예를 들어, native javascript의 &lt;code&gt;.forEach()&lt;/code&gt;, &lt;code&gt;.map()&lt;/code&gt;같이 Array에서만 가능했던 method들에 Object type도 적용할 수 있다.&lt;/li&gt;
&lt;li&gt;함수의 확장성이 높아져서 그 활용도가 높다는 것이다.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jenny&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;hasDog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// 'Jenny'&lt;/span&gt;
&lt;span class="c1"&gt;// 20&lt;/span&gt;
&lt;span class="c1"&gt;// true&lt;/span&gt;

&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// name&lt;/span&gt;
&lt;span class="c1"&gt;// age&lt;/span&gt;
&lt;span class="c1"&gt;// hasDog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;개인적으로 가장 큰 장점이라고 느꼈던 부분이다.🤩&lt;/p&gt;

&lt;p&gt;일하면서 가장 자주 썼던 함수들은 &lt;strong&gt;native함수에서 복잡하게 구현하지 않아도 되는 것들&lt;/strong&gt;이다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_.filter()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_.clone()&lt;/code&gt; / &lt;code&gt;_.cloneDeep()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_.isEqual()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_.remove()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_.orderBy()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;아래 항목들은 구글링으로 찾아본 장점들이다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Cross-browser compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;브라우저에 상관없이 동일하게 동작&lt;/strong&gt;하기 때문에 호환성 이슈를 신경쓰지 않아도 된다. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. 에러 처리에 있어 안전하다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;[native JS]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="mi"&gt;00123&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Milk&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="mi"&gt;01020&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Bread&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="mi"&gt;12232&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;Eggs&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productCodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// productCodes -&amp;gt; [‘00123’, ‘01020’, ‘11232’]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;이 때, &lt;code&gt;products&lt;/code&gt;가 항상 Array 타입을 유지한다는 보장이 없다면?
👉 &lt;code&gt;productCodes&lt;/code&gt;는 Error를 발생시키게 된다.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;SomeAPI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;//-&amp;gt; null&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productCodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;//-&amp;gt; Uncaught TypeError: Cannot read property 'map' of null&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lodash의 &lt;code&gt;_.map&lt;/code&gt;을 사용한다면?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productCodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;products&lt;/code&gt;가 &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt; 이어도 &lt;code&gt;_.map&lt;/code&gt;을 사용했기 때문에 empty Array를 return하게 된다.&lt;/p&gt;

&lt;p&gt;API로 부터 정상적인 값을 받지 못해도, &lt;code&gt;productCodes&lt;/code&gt;가 Array type으로 유지 되기 때문에 에러가 발생하진 않는다.&lt;/p&gt;




&lt;p&gt;구글링 하면서 보다 보니, 굳이 lodash를 사용하지 않아도 된다는 의견의 글들도 여럿 보았다. (&lt;a href="https://thejs.dev/jmitchell/its-time-to-let-go-of-lodash-nqc" rel="noopener noreferrer"&gt;관련 링크&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;이미 너무 익숙해져 버린 lodash... 자주 사용하는 method만 계속 쓰는 습관이 있는데 이외에도, 더 유용한 method들이 있다면 적극 사용하도록 노력해야겠다.&lt;/p&gt;

</description>
      <category>lodash</category>
      <category>javascript</category>
    </item>
    <item>
      <title>[Typescript] Study TS with me (2) - Generics</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sun, 12 Mar 2023 13:57:48 +0000</pubDate>
      <link>https://dev.to/nily/typescript-study-ts-with-me-2-generics-4obh</link>
      <guid>https://dev.to/nily/typescript-study-ts-with-me-2-generics-4obh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Generics allow creating 'type variables' which can be used to create classes, functions &amp;amp; type aliases that &lt;strong&gt;don't need to explicitly define the types that they use&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Generics makes it easier to write reusable code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;제네릭은 &lt;strong&gt;Java&lt;/strong&gt;나 &lt;strong&gt;C++&lt;/strong&gt; 같은 정적 타입 언어에선 이미 널리 쓰이고 있는 기능이라고 한다. &lt;strong&gt;다양한 타입에서 작동&lt;/strong&gt;한다는 장점이 있기 때문에 component를 만들때 유용하게 쓰일 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Function&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 함수를 호출하는 순간 Type이 결정됨.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// number&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Class&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleImage&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="na"&gt;_title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="na"&gt;_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;){}&lt;/span&gt;

  &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simpleImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SimpleImage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sample image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.1 Generic Constraints&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Lengthwise&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logginIdentity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Lengthwise&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 제네릭 함수의 타입이 제한되어 있기 때문에, 모든 타입에 대해선 동작하지 않음.&lt;/span&gt;
&lt;span class="nf"&gt;logginIdentity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Error&lt;/span&gt;

&lt;span class="c1"&gt;// length property가 있는 type을 전달해야 함.&lt;/span&gt;
&lt;span class="nf"&gt;logginIdentity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.2 Using Type Parameters in Generic Constraints&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// obj에 존재하는 property만 가져오도록&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;f&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Error: f는 x에 존재하지 않는 property&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;scss에서 많이 쓰이는 디자인 패턴인 &lt;strong&gt;mixins&lt;/strong&gt;을 만드는데도 &lt;strong&gt;Generic&lt;/strong&gt;이 쓰였다고 하니, 나중에 기회가 되면 또 포스팅 해봐야 겠다. (&lt;a href="https://www.typescriptlang.org/docs/handbook/mixins.html"&gt;참고 링크&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;[출처]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/ko/docs/handbook/2/generics.html"&gt;https://www.typescriptlang.org/ko/docs/handbook/2/generics.html&lt;/a&gt;
-&lt;a href="https://www.w3schools.com/typescript/typescript_basic_generics.php"&gt;https://www.w3schools.com/typescript/typescript_basic_generics.php&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Agile Team - How do we work?</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 15 Oct 2022 07:13:19 +0000</pubDate>
      <link>https://dev.to/nily/agile-team-how-do-we-work-33o7</link>
      <guid>https://dev.to/nily/agile-team-how-do-we-work-33o7</guid>
      <description>&lt;p&gt;현재 직장인 Agile 팀 일한지 1년 5개월째, 이번 글은 약 1년 동안 느낀 애자일 조직 문화를 주제로 써보려고 한다.&lt;/p&gt;

&lt;p&gt;입사 전, "애자일" 이라는 단어만 들었을 땐 무슨 개발 용어인줄 알았다. 현재 팀에 합류한 뒤 온보딩 과정에서 애자일 방법론에 대한 교육을 받았을 때, 적지 않은 충격을 받았던 기억이 난다.&lt;/p&gt;

&lt;p&gt;이전 회사에선 워터폴 방식으로 업무를 했었기도 했고, 모든 개발팀은 다 그런식으로 일하는 줄 알았기 때문이다.&lt;/p&gt;

&lt;p&gt;애자일과 워터폴은 프로젝트 방법론으로, 조직의 특성에 맞게 알맞은 방식을 채택하여 사용한다. SaaS(Software as a service) 제품을 개발하는 우리는 팀의 특성에 맞게 애자일 방식을 채택하여 운영중이다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DBN6miZ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msgw61dg54cxapnh5oou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DBN6miZ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msgw61dg54cxapnh5oou.png" alt="Image description" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;출처: &lt;a href="https://hackr.io/blog/agile-vs-waterfall"&gt;https://hackr.io/blog/agile-vs-waterfall&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;간단히 설명하자면,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Waterfall: 전체 개발 주기가 정해져 있고 작업이 순차적으로 진행됨.&lt;/li&gt;
&lt;li&gt;Agile: 짧은 개발 주기가 반복되고, 완성도의 차이는 있지만 결과물을 빠르게 볼 수 있음.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;우리 팀은 애자일 방법론 중에서도, &lt;a href="https://www.wrike.com/project-management-guide/faq/what-is-scrum-in-agile/"&gt;Scrum&lt;/a&gt;이라는 방식을 사용하고 있다.&lt;/p&gt;

&lt;p&gt;우리 팀이 일하는 방식을 하루 일과를 통해 알아보자🙌&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10:30am - 데일리 미팅&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j1slflN5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3wmzleollpj4xhwj87t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j1slflN5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v3wmzleollpj4xhwj87t.png" alt="image" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;어제 한 일을 서로 짧게 공유하고, 오늘 todo를 정한다. (+ 이슈가 있었다면 이슈 공유도 한다)&lt;/li&gt;
&lt;li&gt;이번 스프린트의 todo는 화이트 보드에 각 이슈별로 포스트 잇으로 정리되어 있다&lt;/li&gt;
&lt;li&gt;작업이 완료된 이슈는 todo 에서 done으로 옮긴다&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다들 각자 할일이 명확하게 정해져 있기 때문에 하루 일정을 자유롭게 사용하면 된다.&lt;/p&gt;

&lt;p&gt;나는 보통 코드 리뷰할 일이 있다면, 오전에 리뷰를 요청드려서 오전 시간을 보내는 편이다.&lt;br&gt;
(우리 팀은 PR이 아닌 1:1 또는 1:2 코드 리뷰를 하기 때문에 시간이 꽤 소요된다)&lt;/p&gt;

&lt;p&gt;점심 시간은 자유롭게 편한 시간에 사용하고, 오후 업무를 시작한다.&lt;/p&gt;

&lt;p&gt;오후 일정도 특별한 일은 없고, 데일리 미팅 때 정한 todo를 이어서 하면 된다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sprint planning&lt;/strong&gt;&lt;br&gt;
2주 주기로 있는 스프린트 회의는 PO(Product Owner)의 주도 하에 앞으로 2주동안의 계획을 짠다. &lt;/p&gt;

&lt;p&gt;기획, 개발 팀은 필수로 참여하고, 영업/마케팅 팀은 영업적 측면에서 고객의 요구사항 등 필요한 기능들을 전달한다.&lt;/p&gt;

&lt;p&gt;돌아가면서 짧게 회고를 하고, 각 이슈에 대한 내용을 공유하며 해당 이슈에 대한 estimation을 한다.&lt;/p&gt;

&lt;p&gt;작업이 어느 정도 소요될지를 정하는 단계이며 스프린트 회의의 핵심이라고 할 수 있다.&lt;/p&gt;

&lt;p&gt;1d, 3d 등 day 기준으로 estimation이 이루어지고, 디테일한 일정은 개발팀끼리 따로 2차 플래닝 때 정한다.&lt;/p&gt;

&lt;p&gt;2차 플래닝 때는, estimation이 된 이슈를 가지고 세부 계획을 짠다.&lt;br&gt;
만약 2d(1d = 6h) 기준 짜리 작업이 있다면, 시간 단위(h)로 또 일정을 세운다.&lt;/p&gt;

&lt;p&gt;ex) &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3h - 기능 분석&lt;/li&gt;
&lt;li&gt;3h- API 작업 (query 추가, schema 변경)&lt;/li&gt;
&lt;li&gt;3h - UI (style, 레이아웃)&lt;/li&gt;
&lt;li&gt;3h - 테스트 및 이슈 처리&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  장점
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;2주라는 짧은 기간동안 작업한 것들을 상용에 배포시키기 때문에 성취감이 잘 느껴진다. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;미리 2주동안의 계획이 있기 때문에, 급하게 요청받을 일이나 계획에 없던 작업이 생길일이 거의 없다. &lt;br&gt;
(크리티컬한 버그를 급하게 수정해야 할 일이 아니라면)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;각자 주도하에 todo만 잘 해낸다면, 일정이 자유롭다.&lt;br&gt;
(회사의 분위기에 따라 다르겠지만, 만약 오늘 6h가 걸리는 일을 3h 만에 끝냈다면? 그냥 퇴근해도 아무런 문제가 없다!!)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;기획, 디자인 일정에 영향을 받지 않는다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;만약, 워터폴 방식이라면 기획이 늦어지면 디자인, 개발을 진행하기 어렵다.&lt;/li&gt;
&lt;li&gt;애자일 방식은, 기능 단위로 기획-디자인-개발-테스트-배포가 진행되기 때문에 기획 + 디자인이 완료된 다른 기능 개발을 시작하면 된다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  단점
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;2주 스프린트가 계속 반복되기 때문에 일의 강도가 높은 편이다.

&lt;ul&gt;
&lt;li&gt;이 부분도 팀마다 다를 순 있겠지만 보통 일정이 여유로울 때도 있고 빡빡(?)할 때도 있는데, 일정한 강도의 업무가 계속 이어져서 지치기 쉽다.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(최근 팀에 합류한 동료의 말에 따르면, 처음에 적응하기 어려웠다고 한다)&lt;/p&gt;




&lt;p&gt;보통 스프린트 플래닝 하는 날엔, 하루 종일 플래닝을 하기 때문에 끝나고 나면 기가 엄청 빨릴 때도 있다😅😅&lt;/p&gt;

&lt;p&gt;그래도 지금까지 경험하기에 단점보다 장점이 훨씬 많고, 개인적으로도 잘 맞는 업무 방식이기 때문에 충분히 만족하고 추천할 만한 개발 방법론이라고 생각한다.&lt;/p&gt;

&lt;p&gt;이번에 이렇게 글을 작성하면서, 다시 한번 이상적인 애자일 팀에서 일하고 있다는 생각이 들었다. 시니어 분들이 이미 애자일에 경험이 많으신 분들이라 시스템화가 잘 되어있고, 항상 더 효율적인 업무 방식을 고민하시기 때문이다.&lt;/p&gt;

&lt;p&gt;애자일 방식을 채택하지 않은 팀에 간다면 적응하기 힘들 정도로, 잘 적응이 되었고 애자일의 스크럼 이외에도 더 좋거나 공유하고 싶은 개발 방법론이 있는지 알아봐야겠다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[Javascript] Performance of Set and Array</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 08 Oct 2022 06:57:32 +0000</pubDate>
      <link>https://dev.to/nily/javascript-performance-of-set-and-array-7</link>
      <guid>https://dev.to/nily/javascript-performance-of-set-and-array-7</guid>
      <description>&lt;p&gt;이번주 회사에서 코드 리뷰를 하면서 기술 블로그로 쓰기 딱 좋은 주제가 생겼다.&lt;/p&gt;

&lt;p&gt;object의 property 값이 중복되는지 체크하는 부분이었는데, 내가 작성한 로직은 아래와 같다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Array에 해당 property 값들을 담아 놓음&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lodash.com/docs/4.17.15"&gt;lodash&lt;/a&gt;의 &lt;code&gt;_.uniq()&lt;/code&gt;로 Array에서 중복 값 제외&lt;/li&gt;
&lt;li&gt;object와 Array의 length 비교 (length가 다르다면 중복 값이 존재함)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;리뷰해주는 동료분께서, 중복값을 체크하려면 Set을 써도 되지 않겠냐고 의견을 주셨다. 한동안 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set"&gt;Set&lt;/a&gt;을 안쓰고 있어서 기억 저편에 있었다😅&lt;/p&gt;

&lt;h4&gt;
  
  
  Set을 사용하는 경우 로직:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Set에 해당 property 값들을 담아 놓음 (Set은 uniq한 값들만 저장됨)&lt;/li&gt;
&lt;li&gt;object와 Array의 length 비교&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Array와 가장 큰 차이는 중복값을 체크하는 코드가 필요없다는 것!!!&lt;br&gt;
그러다 문득 Array와 Set의 퍼포먼스가 어느정도 차이가 나는지 궁금해졌다.&lt;/p&gt;



&lt;p&gt;Array를 사용한 경우:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isDuplicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use Array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isDuplicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use Array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--siRaSpdu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbgi74ku54g0kuse7bbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--siRaSpdu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbgi74ku54g0kuse7bbd.png" alt="image" width="376" height="38"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set을 사용한 경우:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isDuplicate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use Set&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isDuplicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use Set&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tjrt-cqH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nl207qgmg563zebqo4lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tjrt-cqH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nl207qgmg563zebqo4lc.png" alt="image" width="396" height="34"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;데이터의 수가 100개 미만인 지금 상황과 같은 경우, Set이 Array보다 약 0.01 ms 정도 빨랐다.&lt;br&gt;
현재 코드에선 거의 차이가 안나는 수준이긴 하다.&lt;/p&gt;

&lt;p&gt;그런데 만약 데이터가 1k, 10k 정도로 많아진다면?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Array&lt;/th&gt;
&lt;th&gt;Set&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1k&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TsGDcd8H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nduwvlera6sm8rang472.png" alt="Image description" width="424" height="42"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fbw9nVMF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q82vwkqc43p5zvo0ffho.png" alt="image" width="358" height="38"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10k&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpVsbwEf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/acnifcxgkm86vqwdjd2o.png" alt="Image description" width="384" height="32"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HMRYK61R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/je34xhyclcxdx4cl4l8a.png" alt="image" width="362" height="42"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100k&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1wM8Rd25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b932mj0h584up7u57xlg.png" alt="Image description" width="448" height="30"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PCfNSPFK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nztfognih93g75zt59tj.png" alt="Image description" width="424" height="42"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;1,000개 까지는 눈에 띄게 차이가 나지 않지만, 10만개 이상의 많은 데이터의 경우 38ms 정도 차이가 난다. 이 땐, Set을 사용하는 것이 퍼포먼스 측면으로는 더 낫다고 볼 수 있겠다.&lt;/p&gt;

&lt;p&gt;❗️이건 &lt;strong&gt;Array&lt;/strong&gt;의 &lt;code&gt;push + lodash _.uniq() + Array.length&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Set&lt;/strong&gt;의 &lt;code&gt;add + Set.size&lt;/code&gt; 조합을 비교한 경우이기 때문에, &lt;br&gt;
데이터 삭제, index 추출 등 Array와 Set의 퍼포먼스는 각각 다 다를 수 있다.&lt;/p&gt;

&lt;p&gt;현재 해당 기능의 로직상 10만개 이상의 데이터가 들어오는 경우는 거의 없지만, 코드의 가독성 측면에서 Set을 사용하는 게 더 낫다고 결론이 나왔다.😌😌&lt;/p&gt;

&lt;p&gt;잊고 있었던 Set을 다시 상기 시키고, Array와 Set을 비교해 글까지 작성하게 해준 이번 코드 리뷰였다. 매일 배우는 즐거움과 성장할 기회가 주어지는 개발자라는 내 직업이 너무 행복함을 다시 한 번 느꼈다🥰&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>array</category>
      <category>set</category>
    </item>
    <item>
      <title>Today I learned - Problem Solving Skills</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 01 Oct 2022 07:37:08 +0000</pubDate>
      <link>https://dev.to/nily/today-i-learned-problem-solving-skills-318p</link>
      <guid>https://dev.to/nily/today-i-learned-problem-solving-skills-318p</guid>
      <description>&lt;h3&gt;
  
  
  효율적인 문제해결 과정이란 무엇일까?
&lt;/h3&gt;

&lt;p&gt;흔히 말하는 "삽질"을 줄이고 눈 앞에 닥친 문제를 어떻게 하면 빨리 해결할 수 있는지 현업에서 겪은 일을 통해 깨달은 3가지 방법을 소개하려고 한다.&lt;/p&gt;

&lt;p&gt;최근 dropdown typeahead 기능을 구현하는 작업을 했다. 부모 component로 부터 option값들을 전달받아야 했는데, object로 부터 빈 array만 받아오는 것이었다.&lt;/p&gt;

&lt;p&gt;빈 값만 전달받기 때문에 dropdown에 뿌려줄 목록은 안나오는 상황이었고, 그 부분에서 막혀 계속 헤매고 있었다. 답답해서 시니어 개발자 분께 여쭤보니 일단 모든 곳에 로그를 찍어보라고 하셨다.&lt;/p&gt;

&lt;p&gt;문제 원인은 생각보다 너무 단순했다. &lt;strong&gt;value change 이벤트를 받을 때 값이 변경&lt;/strong&gt;되기 때문에 그 때 option 값들을 할당해주면 되는데, &lt;strong&gt;component가 init 될 때만 값을 받아와서&lt;/strong&gt; 당연히 빈 값만 셋팅 되었던 거였다.&lt;/p&gt;

&lt;p&gt;첫번째 depth에서 선택한 값에 따라 2depth, 3depth의 dropdown 옵션들이 달라지는 로직이기 때문에 이벤트가 어디서 오는지 파악하고, &lt;strong&gt;로그만 찍어봤어도 바로 해결&lt;/strong&gt;되었을 문제...!!&lt;/p&gt;

&lt;p&gt;이 사건으로 깨달은 나의 개선해야할 점을 정리해 봤다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;막연한 가정하지 않기&lt;/li&gt;
&lt;li&gt;일단 모르겠으면, console log 찍어보기&lt;/li&gt;
&lt;li&gt;다른 사람이 작성한 코드를 참고할 땐, 제대로 분석하고 그 흐름을 이해해서 필요에 맞게 쓰기&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  1. 막연한 가정하지 않기
&lt;/h4&gt;

&lt;p&gt;이 상황에선 이렇게 데이터가 출력되겠지, 여기선 아직 데이터 set 안됐겠지 등 암묵적으로 가정하고 문제를 해결하려고 했기 때문에 삽질한 시간이 더 길어졌다.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. 일단 모르겠으면, console log 찍어보기
&lt;/h4&gt;

&lt;p&gt;옆자리 시니어 개발자 분께서 제일 강조하신 말씀이다..ㅎㅎㅎ "막연한 가정하지 않기" 와 이어지는 부분으로, 일단 log를 찍어보고 데이터의 흐름을 파악하는게 중요하다고 말씀하셨다.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. 다른 사람이 작성한 코드를 참고할 땐, 제대로 분석하고 그 흐름을 이해해서 필요에 맞게 쓰기
&lt;/h4&gt;

&lt;p&gt;이번에 작업한 부분은 &lt;a href="https://formly.dev/"&gt;formly&lt;/a&gt;라는 라이브러리로, JSON 데이터를 인식해 form UI 형태로 만들어주는 걸 사용중이었다. formly에서 typeahead가 가능한 dropdown을 구현하기 위해 &lt;a href="https://stackblitz.com/edit/angular-ngx-formly?file=app%2Fapp.component.ts"&gt;해당 코드&lt;/a&gt;를 참고해서 적용했다. &lt;/p&gt;

&lt;p&gt;RxJs의 Subject와 Observable을 변수로 이용해서 사용하는데, 사실 동작하는데만 초점을 맞추고 그냥 아무 생각없이 가져와서 어떻게든 우리 코드에 우겨넣으려고(?)했던 것 같다.&lt;br&gt;
 참고한 코드를 분석해서 왜 이건 이런식으로 썼을지 고민은 하지 않고 기능을 구현하는데 급급했다. &lt;/p&gt;

&lt;p&gt;이런 부분에서 약간 꾸지람을 들었다.😅😅 (동작 원리를 제대로 파악하고 있지 않는데 어떻게 활용해서 그 코드를 쓸 수 있겠냐고...)&lt;/p&gt;

&lt;p&gt;주니어 개발자로서, 매 순간 과정에서 배워야 할 점이 생긴다. 이번에 깨달은 문제 해결 방법 3가지를 새기면서, 앞으로는 같은 문제가 생겨도 더 쉽게 접근하고 해결할 수 있기를 바래본다.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>problemsolving</category>
      <category>angular</category>
      <category>frontend</category>
    </item>
    <item>
      <title>[Typescript] Study TS with me (1) - basic type</title>
      <dc:creator>Nily</dc:creator>
      <pubDate>Sat, 24 Sep 2022 07:24:11 +0000</pubDate>
      <link>https://dev.to/nily/typescript-study-ts-with-me-1-basic-type-2i2n</link>
      <guid>https://dev.to/nily/typescript-study-ts-with-me-1-basic-type-2i2n</guid>
      <description>&lt;p&gt;평소 일하면서 Typescript를 쓰면서도, type/enum/interface 등 왜 저런 코드로 쓰는지를 생각하지 않고 그냥 사용한 적이 많았다. 이렇게 코드를 작성한 이유가 있겠지 하면서 이전 코드를 복붙하거나 의문을  가졌던 적이 별로 없다.&lt;/p&gt;

&lt;p&gt;최근에 팀에 새로 합류한 분의 온보딩 스터디 프로젝트를 같이 리뷰하는 시간을 가졌는데, class 구현부터 Typescript를 적극적으로 사용한 걸 보면서 그 동안의 나를 반성하게 되었다.😂 &lt;/p&gt;

&lt;p&gt;다시 기초부터 차근차근 공부하면서, type 선언 정도로만 ts를 쓰는 수준이 아닌 ts의 장점을 제대로 활용하는 코드를 쓰고 싶어 이렇게 ts스터디를 시작하게 되었다.&lt;/p&gt;

&lt;h5&gt;
  
  
  String Literal Types
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;문자열 자체를 type으로 선언해서 사용
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;All&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;selectAll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;other&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Union Types
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;2개 이상의 선언된 type을 사용할 수 있음&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Union Type은 평소에 익숙하게 사용중이다. 보통 여러개 string type을 가질 때 사용했다. 아래 예제처럼 서로 다른 type들도 Union Type으로 선언해 사용할 수 있다는 걸 알았다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;printId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Discriminated Union Types
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;각각 다른 Type별로 동일한 property 이름을 가지고 있음&lt;/li&gt;
&lt;li&gt;해당 property로 Type별로 구분이 가능함
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Square&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Triangle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;triangle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Circle&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Square&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Triangle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// discriminate type&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;square&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// discriminate type&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Enum Types
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;여러개의 상수를 하나의 type으로 묶어 관리할 수 있음.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Direction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 시작하는 숫자를 할당해 줄 수 있음(default는 0) &lt;/span&gt;
  &lt;span class="nx"&gt;Down&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;구글링 하다보니, Enum typ은 안정성이 떨어진다는 얘기가 꽤 많았다.&lt;/p&gt;

&lt;p&gt;[이유]&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;transfile 되면서, bundler(rollup)에서 TreeShaking을 할 수 없음. &lt;br&gt;
&lt;a href="https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/"&gt;관련 링크&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Tree-Shaking&lt;/code&gt;, &lt;code&gt;const enum&lt;/code&gt; 등 설명할 개념이 많아서 이건 다음편으로..&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;number일 경우, type이 보장되지 않음&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;DAYS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Mon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Tue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Wed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Thur&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Fri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Sat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Sun&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DAYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DAYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Wed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// error지만 compile시 error가 발생하지 않음!(= type이 보장되지 않는다)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enum type은 Union Type으로 대체 가능하기 때문에 Union Type을 사용하는 것이 권장되는 분위기 였다.&lt;/p&gt;

&lt;p&gt;하지만 팀의 개발 환경이나 가독성 측면에서 Enum을 사용하는 것이 더 나을 때도 있으니 충분히 설명 가능한 이유가 있다면 채택해서 사용해도 큰 문제는 없다는 글도 봤다. &lt;/p&gt;

&lt;p&gt;TMI:&lt;br&gt;
 사실 우리 팀에서도 Enum Type을 꽤 사용중이다.😅😅 팀에서 굉장히 논리적인 이유로 뭐든 것을 설명하시는 시니어 개발자 분이 계신데, 다음에 출근해서 물어봐야겠다. (엄청난 합리적인 이유가 있을 것으로 예상되는...)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
