<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>언땅에 삽질</title>
    <link>https://digwon.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 29 Jul 2026 04:42:38 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>gwonmin</managingEditor>
    <item>
      <title>[Vue3] 배경지식</title>
      <link>https://digwon.tistory.com/entry/Vue3-%EB%B0%B0%EA%B2%BD%EC%A7%80%EC%8B%9D</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Vue.js는 다른 프론트엔드 프레임워크와 비교해 차별화된 다양한 장점이 있습니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 쉬운 학습&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 초보자도 쉽게 배울 수 있는 간결한 문법과 구조를 가지고 있습니다. 다른 프레임워크에 비해 더 빠르게 익힐 수 있으며, 기본 HTML, CSS, JavaScript 지식만으로도 시작할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 유연성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 컴포넌트 기반의 구조를 가지고 있어, 작은 프로젝트부터 대규모 애플리케이션까지 유연하게 개발할 수 있습니다. 또한, 다른 라이브러리와의 통합이 쉬워, 기존 프로젝트에도 적용하기 용이합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 가볍고 빠른 성능&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 경량화되어 있어 빠른 초기 로딩 속도와 업데이트 성능을 제공합니다. 가상 DOM(Virtual DOM)을 활용하여 불필요한 업데이트를 최소화하고, 최적화된 렌더링 성능을 제공합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 반응형 데이터 바인딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 데이터와 DOM 요소를 쉽게 바인딩할 수 있는 반응형 시스템을 제공합니다. 이를 통해 데이터 변경 시 자동으로 UI가 업데이트되어 개발 편의성이 향상됩니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. 강력한 개발 도구 및 생태계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 공식 Vue CLI, Vue DevTools와 같은 강력한 개발 도구를 제공하며, 커뮤니티에서 다양한 플러그인과 라이브러리를 지원합니다. 이로 인해 생산성이 향상되고, 개발 경험이 더욱 향상됩니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. 활발한 커뮤니티&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 꾸준한 성장세를 보이며 활발한 커뮤니티를 형성하고 있습니다. 개발자들은 문제 해결, 최적화 방법, 새로운 기능에 대한 정보를 손쉽게 얻을 수 있으며, 지속적인 업데이트와 개선이 이루어지고 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 중 Vue.js의&amp;nbsp;주요한&amp;nbsp;장점은&amp;nbsp;&lt;b&gt;컴포넌트&amp;nbsp;기반&amp;nbsp;아키텍처와&amp;nbsp;높은&amp;nbsp;생산성,&amp;nbsp;그리고&amp;nbsp;유연성&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세히 보면 아래와 같은 부가적인 요소를 지원합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 디렉티브 (Directives)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 사용자 정의 디렉티브를 제공하여 DOM과 데이터를 더 쉽게 조작할 수 있습니다. 이를 통해 특정 DOM 요소에 동적으로 속성을 바인딩하거나 이벤트를 처리할 수 있습니다. 가장 일반적인 디렉티브로는 v-bind, v-on, v-if, v-for 등이 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 컴포넌트 (Components)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 재사용 가능한 UI 구성 요소인 컴포넌트를 지원합니다. 이를 통해 애플리케이션의 구조를 모듈화하고 각 기능을 독립적으로 개발 및 유지보수할 수 있습니다. 컴포넌트는 props를 통해 데이터를 전달하고, 이벤트를 통해 상위 컴포넌트와 소통합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Vuex&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vuex는 Vue.js 애플리케이션의 상태 관리 라이브러리로, 애플리케이션의 상태를 중앙 집중식으로 관리할 수 있습니다. 이를 통해 여러 컴포넌트에서 공유되는 데이터와 상태를 효율적으로 관리하고 동기화할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Vue Router&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue Router는 Vue.js 애플리케이션의 라우팅을 관리하는 공식 라이브러리입니다. Vue Router를 사용하면, SPA(Single Page Application)에서 클라이언트 사이드 라우팅을 구현하고 동적 페이지 로딩을 할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. 서버 사이드 렌더링 (SSR)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 서버 사이드 렌더링을 지원하여, 더 빠른 초기 페이지 로딩 속도와 SEO 친화적인 웹 애플리케이션 개발을 가능하게 합니다. Nuxt.js와 같은 프레임워크를 사용하면, Vue.js 애플리케이션의 SSR을 쉽게 구현할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;단점으로는 다음과 같은 것들이 있습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 문서화 부족&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React나 Angular에 비해 Vue.js의 문서화가 부족한 편입니다. 특히 최신 버전에 대한 자세한 문서가 부족하다는 지적도 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 생태계의 상대적인 부족&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React나 Angular에 비해 Vue.js의 생태계가 아직은 상대적으로 부족합니다. 따라서 개발에 필요한 라이브러리나 도구를 찾기 어려울 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 큰 규모의 애플리케이션 개발 시 관리의 어려움&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 규모가 작은 프로젝트나 빠른 프로토타입 개발에는 용이하지만, 큰 규모의 애플리케이션 개발 시에는 관리의 어려움이 있을 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 공식 지원의 한계&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 React나 Angular와 달리 공식적으로 엔터프라이즈 지원을 제공하지 않습니다. 따라서 대규모 기업에서 사용하기에는 조금 불안정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 중 Vue.js의 주요 단점으로는 Angular나 React와 같은 경쟁 프레임워크에 비해 &lt;b&gt;생태계가 덜 발달했다&lt;/b&gt;는 점이 있습니다. 이는 Vue.js의 비교적 최근 출시와 상대적으로 적은 사용자 수 때문입니다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Vue.js&amp;nbsp;3는&amp;nbsp;Vue.js&amp;nbsp;2와&amp;nbsp;비교하여&amp;nbsp;많은&amp;nbsp;변화와&amp;nbsp;개선이&amp;nbsp;있습니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 성능 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3는 Vue.js 2에 비해 더 빠른 렌더링 성능과 작은 번들 사이즈를 제공합니다. 이는 가상 DOM의 개선, 트리 쉐이킹(Tree shaking) 최적화, 정적 속성 호이스팅 등 다양한 최적화 기법 덕분입니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Composition API&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 새로운 Composition API가 도입되었습니다. 이는 기존의 Options API와 병행하여 사용할 수 있으며, 로직 재사용과 코드 구성에 있어 더 유연한 해결책을 제공합니다. Composition API를 사용하면 로직을 더 쉽게 추상화하고 컴포넌트 간에 공유할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 프록시 기반의 반응성 시스템&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3는 ES6 Proxy를 기반으로 한 새로운 반응성 시스템을 도입했습니다. 이로 인해 초기 구동 시간이 개선되고, 디버깅이 더 쉬워졌으며, 객체 중첩에 대한 반응성도 개선되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 향상된 TypeScript 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3는 처음부터 TypeScript와 함께 설계되어, 더 나은 TypeScript 통합 및 개발 경험을 제공합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Custom Renderer API&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 사용자 정의 렌더러 API를 통해 다양한 플랫폼에서 렌더링을 수행할 수 있습니다. 이를 통해 웹뿐만 아니라 네이티브 애플리케이션, WebGL 등 다양한 환경에서 Vue.js를 사용할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. Fragments&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 프래그먼트(Fragments)를 지원하여, 루트(root) 노드를 여러 개 가진 컴포넌트를 작성할 수 있게 되었습니다. 이로 인해 불필요한 컨테이너 요소를 줄이고, 더 깔끔한 마크업 구조를 구성할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;7. 레거시 코드 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 Vue.js 2와의 호환성을 유지하며, Vue.js 2에서 작성된 코드를 Vue.js 3에서도 그대로 사용할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;8. 새로운 디렉티브&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 새로운 디렉티브를 제공하여 더 다양한 UI 구성이 가능해졌습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;9. Devtools 개선&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 개발 도구인 Vue Devtools가 개선되어 더 다양한 디버깅 기능을 제공합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;10. Composition API와 TypeScript의 결합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 3에서는 Composition API와 TypeScript를 결합하여 코드의 가독성과 유지보수성을 높이는 기능을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 중 Vue.js&amp;nbsp;3에서&amp;nbsp;가장&amp;nbsp;큰&amp;nbsp;변화는&amp;nbsp;&lt;b&gt;Composition&amp;nbsp;API&lt;/b&gt;의&amp;nbsp;도입입니다.&amp;nbsp;Composition&amp;nbsp;API는&amp;nbsp;기존의&amp;nbsp;Options&amp;nbsp;API와&amp;nbsp;병행하여&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있으며,&amp;nbsp;로직&amp;nbsp;재사용과&amp;nbsp;코드&amp;nbsp;구성에&amp;nbsp;있어&amp;nbsp;더&amp;nbsp;유연한&amp;nbsp;해결책을&amp;nbsp;제공합니다.&lt;br /&gt;&lt;br /&gt;Composition&amp;nbsp;API를&amp;nbsp;사용하면,&amp;nbsp;관련된&amp;nbsp;기능을&amp;nbsp;더&amp;nbsp;쉽게&amp;nbsp;묶어&amp;nbsp;추상화하고&amp;nbsp;컴포넌트&amp;nbsp;간에&amp;nbsp;공유할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이는&amp;nbsp;큰&amp;nbsp;규모의&amp;nbsp;애플리케이션에서&amp;nbsp;코드&amp;nbsp;구조화와&amp;nbsp;유지&amp;nbsp;관리를&amp;nbsp;향상시키는&amp;nbsp;데&amp;nbsp;큰&amp;nbsp;도움이&amp;nbsp;됩니다.&lt;br /&gt;&lt;br /&gt;또한,&amp;nbsp;Composition&amp;nbsp;API는&amp;nbsp;반응성&amp;nbsp;시스템의&amp;nbsp;개선과&amp;nbsp;함께&amp;nbsp;도입되어,&amp;nbsp;기존&amp;nbsp;Options&amp;nbsp;API에서&amp;nbsp;경험할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;몇&amp;nbsp;가지&amp;nbsp;제약&amp;nbsp;사항을&amp;nbsp;해결하고,&amp;nbsp;더&amp;nbsp;간결하고&amp;nbsp;명확한&amp;nbsp;코드를&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있게&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;이외에도&amp;nbsp;Vue.js&amp;nbsp;3의&amp;nbsp;다양한&amp;nbsp;변화들&amp;nbsp;중&amp;nbsp;프록시&amp;nbsp;기반의&amp;nbsp;반응성&amp;nbsp;시스템,&amp;nbsp;향상된&amp;nbsp;TypeScript&amp;nbsp;지원,&amp;nbsp;프래그먼트(Fragments)&amp;nbsp;등이&amp;nbsp;있지만,&amp;nbsp;가장&amp;nbsp;큰&amp;nbsp;변화는&amp;nbsp;Composition&amp;nbsp;API의&amp;nbsp;도입으로&amp;nbsp;인한&amp;nbsp;개발&amp;nbsp;패러다임의&amp;nbsp;변화라고&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Frontend/Vue3</category>
      <category>vue.js</category>
      <category>vue3</category>
      <category>프론트엔드</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/13</guid>
      <comments>https://digwon.tistory.com/entry/Vue3-%EB%B0%B0%EA%B2%BD%EC%A7%80%EC%8B%9D#entry13comment</comments>
      <pubDate>Mon, 1 May 2023 17:08:29 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] Test-driven Development 란</title>
      <link>https://digwon.tistory.com/entry/TDD-Test-driven-Development-%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;TTD(Test-driven Development)란, 테스트 주도 개발 방법론으로 개발자가 개발하기 전에 테스트 코드를 작성하고 이를 통과하는 코드를 작성하는 방식&lt;/b&gt;입니다. 프론트엔드 개발에서 TTD가 중요한 이유는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. 코드 품질 향상&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD는 코드를 작성하기 전에 테스트를 먼저 수행함으로써, 개발자가 실수를 미리 발견하고 수정할 수 있습니다. 이는 전반적인 코드 품질을 높여주며, 버그 발생 가능성을 줄여줍니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 간결한 코드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD를 사용하면, 코드를 작성하기 전에 먼저 요구 사항을 명확하게 정의하게 됩니다. 이로 인해 필요 이상의 기능이 추가되지 않고, 요구 사항에 부합하는 간결한 코드를 작성할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 명확한 목표&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;테스트 케이스를 먼저 작성함으로써, 개발자는 개발해야 할 기능의 목표를 명확하게 인식할 수 있습니다. 이는 개발 과정에서 방향성을 잃거나 시간을 낭비하는 일을 줄여줍니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 빠른 피드백&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD에서는 코드를 작성하고 바로 테스트를 수행하여 결과를 확인할 수 있습니다. 이를 통해 개발자는 작성한 코드의 동작이 올바른지를 빠르게 확인할 수 있으며, 문제가 발생할 경우 즉시 수정할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. 리팩토링 용이&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD를 사용하면, 이미 테스트 케이스가 구비되어 있기 때문에 리팩토링을 수행할 때 코드의 동작에 대한 검증이 쉽습니다. 이로 인해 개발자는 코드의 구조와 가독성을 개선하는데 더욱 자신감을 가질 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. 유지보수 편리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD는 테스트 케이스가 잘 작성되어 있어야 하므로, 프로젝트의 문서화가 더 잘 이루어집니다. 이는 추후 유지보수를 수행할 때 프로젝트의 구조와 기능을 이해하는 데 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;7. 협업 용이성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; TDD를 사용하면 다른 개발자들과 코드를 공유하고 협업할 때 코드 품질과 안정성이 보장됩니다. 또한, 코드 변경 사항이 테스트를 통과하는지 검증할 수 있으므로, 코드 변경 사항에 대한 자신감을 갖고 협업할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;하지만, 단점도 있습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 초기 투자 비용 증가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD를 도입하면 개발 초기에 많은 시간과 노력이 들어갑니다. 테스트 케이스를 작성하는 것과 테스트 코드를 실행하면서 버그를 해결하는 것이 시간과 노력을 많이 필요로 하기 때문입니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 유지보수 비용 증가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD로 개발된 코드를 유지보수하면서 새로운 기능을 추가하거나 수정하려면 기존의 테스트 케이스도 수정해야 합니다. 이 과정에서 추가적인 시간과 노력이 필요합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 테스트 케이스 작성의 어려움&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발자는 모든 가능한 경우를 고려해야 하는 적절한 테스트 케이스를 작성해야 합니다. 이것은 개발자들이 프로그램을 잘 이해하고 있어야 가능합니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 실제 동작과의 차이&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD에서는 테스트 케이스를 작성하고 테스트 코드를 실행하면서 버그를 찾고 수정합니다. 그러나 이러한 테스트 케이스는 실제 환경에서 발생하는 상황과는 다를 수 있습니다. 따라서 테스트 케이스로 모든 경우를 다루지 않았을 때, 프로그램에서는 버그가 발생할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. 개발 속도의 감소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TDD를 도입하면 개발 초기에 시간과 노력이 많이 들어가기 때문에 개발 속도가 감소할 수 있습니다. 특히 테스트 케이스 작성이나 버그 수정에 시간을 많이 투자하면 개발 속도가 더욱 감소할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프론트엔드&amp;nbsp;TDD를&amp;nbsp;위한&amp;nbsp;대표적인&amp;nbsp;툴로는&amp;nbsp;&lt;b&gt;Jest,&amp;nbsp;Enzyme,&amp;nbsp;Mocha,&amp;nbsp;Karma&amp;nbsp;&lt;/b&gt;등이&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Jest는&amp;nbsp;Facebook에서&amp;nbsp;개발한&amp;nbsp;JavaScript&amp;nbsp;테스트&amp;nbsp;프레임워크이며,&amp;nbsp;&lt;br /&gt;Enzyme은&amp;nbsp;React&amp;nbsp;컴포넌트를&amp;nbsp;위한&amp;nbsp;JavaScript&amp;nbsp;테스트&amp;nbsp;유틸리티입니다.&amp;nbsp;&lt;br /&gt;Mocha는&amp;nbsp;JavaScript&amp;nbsp;테스트&amp;nbsp;러너로,&amp;nbsp;BDD와&amp;nbsp;TDD&amp;nbsp;스타일을&amp;nbsp;지원하며&amp;nbsp;브라우저와&amp;nbsp;Node.js에서&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;br /&gt;Karma는&amp;nbsp;JavaScript&amp;nbsp;테스트&amp;nbsp;러너로,&amp;nbsp;다양한&amp;nbsp;테스팅&amp;nbsp;프레임워크와&amp;nbsp;함께&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;br /&gt;이&amp;nbsp;외에도&amp;nbsp;Jasmine,&amp;nbsp;Ava&amp;nbsp;등&amp;nbsp;다양한&amp;nbsp;테스트&amp;nbsp;프레임워크와&amp;nbsp;라이브러리가&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;이 중 가장&amp;nbsp;점유율이&amp;nbsp;높은&amp;nbsp;프론트엔드&amp;nbsp;TDD&amp;nbsp;툴은&amp;nbsp;&lt;b&gt;Jest&lt;/b&gt;입니다.&amp;nbsp;Jest는&amp;nbsp;Facebook에서&amp;nbsp;개발한&amp;nbsp;JavaScript&amp;nbsp;테스트&amp;nbsp;프레임워크로,&amp;nbsp;React&amp;nbsp;컴포넌트를&amp;nbsp;테스트하는&amp;nbsp;데&amp;nbsp;자주&amp;nbsp;사용됩니다.&amp;nbsp;Jest는&amp;nbsp;인기&amp;nbsp;있는&amp;nbsp;프론트엔드&amp;nbsp;프레임워크&amp;nbsp;및&amp;nbsp;라이브러리와&amp;nbsp;함께&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있으며,&amp;nbsp;간편한&amp;nbsp;설정과&amp;nbsp;사용법으로&amp;nbsp;인기가&amp;nbsp;높아졌습니다.&amp;nbsp;또한,&amp;nbsp;Jest는&amp;nbsp;모의&amp;nbsp;객체(mocking)&amp;nbsp;기능을&amp;nbsp;지원하여&amp;nbsp;테스트&amp;nbsp;코드&amp;nbsp;작성을&amp;nbsp;더욱&amp;nbsp;쉽고&amp;nbsp;간편하게&amp;nbsp;만들어줍니다.&lt;/p&gt;</description>
      <category>Frontend/TDD</category>
      <category>TDD</category>
      <category>프론트엔드</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/12</guid>
      <comments>https://digwon.tistory.com/entry/TDD-Test-driven-Development-%EB%9E%80#entry12comment</comments>
      <pubDate>Mon, 1 May 2023 16:49:55 +0900</pubDate>
    </item>
    <item>
      <title>[Composition API] Typescript 적용하기 (script setup)</title>
      <link>https://digwon.tistory.com/entry/Composition-API-Typescript-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-script-setup</link>
      <description>&lt;h1&gt;Typing Component Props&lt;/h1&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import { defineProps } from 'vue';

interface Props {
  name: string
  count?: number
}

const props = defineProps&amp;lt;Props&amp;gt;()
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Props는 상위 컴포넌트(부모)에서 하위 컴포넌트(자식)로 데이터를 넘겨줄 때 사용합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Props Default Values&lt;/h2&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import { defineProps, withDefaults } from 'vue';

interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps&amp;lt;Props&amp;gt;(), {
  msg: 'hello',
  labels: () =&amp;gt; ['one', 'two']
})
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;default props값을 지정하는 방법입니다.&lt;/p&gt;
&lt;h1&gt;Typing Component Emits&lt;/h1&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
// runtime
const emit = defineEmits(['change', 'update'])

// type-based
const emit = defineEmits&amp;lt;{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}&amp;gt;()
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Emits는 하위 컴포넌트(자식)에서 상위 컴포넌트(부모)로 이벤트, 데이터를 넘겨줄 때 사용합니다.&lt;/p&gt;
&lt;h1&gt;Typing ref()&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref는 초기값으로 타입을 추론하는 기능이 기본적으로 내장되어 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;import { ref } from 'vue'

// inferred type: Ref&amp;lt;number&amp;gt;
const year = ref(2023)

// =&amp;gt; TS Error: Type 'string' is not assignable to type 'number'.
year.value = '2023'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명시적인 타입 선언은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;//1. type Ref 선언해 적용하는 방식
import { ref } from 'vue'
import type { Ref } from 'vue'

const year: Ref&amp;lt;string | number&amp;gt; = ref('2023')

year.value = 2023 // ok!

//2. ref() 에 override 하는 방식
// resulting type: Ref&amp;lt;string | number&amp;gt;
const year = ref&amp;lt;string | number&amp;gt;('2023')

year.value = 2023 // ok!

---------------------------------------------
// 초기값을 지정하지 않으면 type에 undefined가 자동으로 포함
const n = ref&amp;lt;number&amp;gt;()
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Typing reactive()&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reactive도 초기값으로 타입을 추론하는 기능이 내장되어 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { reactive } from 'vue'

// inferred type: { title: string }
const book = reactive({ title: 'Vue 3 Guide' })
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명시적인 타입 선언은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import { reactive } from 'vue'

interface Book {
  title: string
  year?: number
}

const book: Book = reactive({ title: 'Vue 3 Guide' })
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Typing computed()&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;computed는 getter의 리턴값을 기준으로 타입을 추론하는 기능이 내장되어 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;import { ref, computed } from 'vue'

const count = ref(0)

// inferred type: ComputedRef&amp;lt;number&amp;gt;
const double = computed(() =&amp;gt; count.value * 2)

// =&amp;gt; TS Error: Property 'split' does not exist on type 'number'
const result = double.value.split('')
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명시적인 타입 선언은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;const double = computed&amp;lt;number&amp;gt;(() =&amp;gt; {
  // type error if this doesn't return a number
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Typing Event Handlers&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type을 명시하지 않으면 event의 인수는 any 타입을 갖습니다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
function handleChange(event) {
  // `event` implicitly has `any` type
  console.log(event.target.value)
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;input type=&quot;text&quot; @change=&quot;handleChange&quot; /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 tsconfig.json에서 &amp;ldquo;strict&amp;rdquo;: true 또는 &amp;ldquo;noImplicitAny&amp;rdquo;: true가 사용되는 경우에는 타입 오류가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 다음과 같이 명시적으로 타입을 선언해줍시다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;function handleChange(event: Event) {
  console.log((event.target as HTMLInputElement).value)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Typing Provide, Inject&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Provide 와 Inject는 일반적으로 독립적인 컴포넌트로부터 수행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Inject된 값을 올바르게 입력하기 위해 Vue는 Symbol을 확장하는 interface 유형인 InjectionKey interface를 제공합니다. 이는 Inject된 값과 provider 간에 타입을 동기화 하는데 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;import { provide, inject } from 'vue'
import type { InjectionKey } from 'vue'

const key = Symbol() as InjectionKey&amp;lt;string&amp;gt;

provide(key, 'foo') // providing non-string value will result in error

const foo = inject(key) // type of foo: string | undefined
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 컴포넌트에서 사용할 수 있도록 Injection key를 별도의 파일에 배치하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;string Injection key를 사용하는 경우, Inject 값 유형은 unknown이 되기 때문에 generic type을 통해 명시적으로 선언해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;const foo = inject&amp;lt;string&amp;gt;('foo') // type: string | undefined
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Inject 값은 아직 undefined가 될 수 있습니다. 왜냐하면 provider가 런타임에 undefined를 제공하지 않는다는 보장이 없기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 두번째 인자로 default value를 입력하면 undefined를 제거할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;const foo = inject&amp;lt;string&amp;gt;('foo', 'bar') // type: string
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값이 항상 제공된다고 확신하는 경우 값을 강제로 캐스팅할 수도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;const foo = inject('foo') as string
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Typing Template Refs&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Template refs는 명시적인 generic 타입과 함께 초기값 null로 만들어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import { ref, onMounted } from 'vue'

const el = ref&amp;lt;HTMLInputElement | null&amp;gt;(null)

onMounted(() =&amp;gt; {
  el.value?.focus()
})
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;input ref=&quot;el&quot; /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄격한 타입 체크를 위해 el.value에 접근할 때 optional chaining 또는 type guard를 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 마운트되기 전까지는 초기 ref 값이 null이고, 참조된 element가 v-if에 의해 마운트 해제된 경우에도 null로 설정될 수 있기 때문입니다.&lt;/p&gt;
&lt;h1&gt;Typing Component Template Refs&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트에 포함된 public method를 사용하기 위해 template ref를 선언해야 하는 경우가 있습니다. 예를 들어, 아래와 같이 모달을 여는 메서드가 있는 MyModal 자식 컴포넌트가 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;!-- MyModal.vue --&amp;gt;
&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import { ref } from 'vue'

const isContentShown = ref(false)
const open = () =&amp;gt; (isContentShown.value = true)

defineExpose({
  open
})
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MyModal의 인스턴스 type을 가져오려면 먼저 typeof를 통해 type을 가져온 다음 TS의 내장 InstanceType 유틸리티를 사용해 인스턴스 type을 추출해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import MyModal from './MyModal.vue'

const modal = ref&amp;lt;InstanceType&amp;lt;typeof MyModal&amp;gt; | null&amp;gt;(null)

const openModal = () =&amp;gt; {
  modal.value?.open()
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678606389237&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;TypeScript with Composition API | Vue.js&quot; data-og-description=&quot;&quot; data-og-host=&quot;vuejs.org&quot; data-og-source-url=&quot;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&quot; data-og-url=&quot;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/beokDf/hyRTKEmSob/aEpIN85dgjq4XVM856tUd0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vuejs.org/guide/typescript/composition-api.html#typing-component-props&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/beokDf/hyRTKEmSob/aEpIN85dgjq4XVM856tUd0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;TypeScript with Composition API | Vue.js&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vuejs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Vue3</category>
      <category>composition api</category>
      <category>fe</category>
      <category>Frontend</category>
      <category>script setup</category>
      <category>Typescript</category>
      <category>vue</category>
      <category>vue3</category>
      <category>웹개발</category>
      <category>프론트엔드</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/11</guid>
      <comments>https://digwon.tistory.com/entry/Composition-API-Typescript-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-script-setup#entry11comment</comments>
      <pubDate>Sun, 12 Mar 2023 16:34:44 +0900</pubDate>
    </item>
    <item>
      <title>[Typescript] Type Guard</title>
      <link>https://digwon.tistory.com/entry/Typescript-Type-Guard</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Type Guard란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 타입을 특정 영역으로 제한&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 타입을 더 한정되게 좁혀 나가는 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에 따르면, &lt;b&gt;타입가드는 특정 스코프 내에서 사용되는 타입을 런타임에 체크&lt;/b&gt;하는 일종의 표현입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Type Guard 사용해야 하는 상황&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Union type을 사용할 시 발생하는 오류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유니온 타입을 사용해 코드를 작성하면 타입스크립트 컴파일러는 &amp;ldquo;타입체크&amp;rdquo;를 수행할 수 없다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;//JS코드

function add(a, b) {
    return a + b;
}

// 실행결과가 예상과 다를 순 있어도, 컴파일도중에 오류가 발생하진 않는다.

//TS코드

function add(a: number | string, b: number | string): number | string {
        return a + b;
}

//코드 작성중 TS 컴파일러가 오류를 체크해준다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 타입스크립트가 알려주는 오류.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &amp;ldquo;타입체크&amp;rdquo; 문제를 해결하기 위해 유니온 타입으로 표현된 요소가 갖고있는 타입을 검사하는 코드를 따로 삽입해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Type Guard 구현하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 공식 문서에서 소개하고 있는 방법&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
  // 
}

const pet = getSmallPet();
 
if (isFish(pet)) {
  pet.swim();
} else {
  pet.fly();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 그 외 방법들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &amp;lsquo;typeof&amp;rsquo; 연산자 유니온 타입이 string, number 등 기본 타입으로만 구성되어 있을 경우에 사용한다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;function add(a: number | string, b: number | string): number | string {
   
   //타입가드: a와 b 가 number일 경우
   
   if (typeof a === 'number' &amp;amp;&amp;amp; typeof b === 'number') {
        return a + b}
   
   //타입가드 a와 b가 string일 경우
   
   else if (typeof a === 'string' &amp;amp;&amp;amp; typeof b === 'string') {
        return a + b 
    }

    else {return 'a and b should have same type'}
}

//위의 코드의 두개의 if문이 type guard 역할을 수행한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 타입가드가 필요없는 예시&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;type CheeseBurger = {
    numBread: number;
    numCheese: number;
}

type BeefBurger = {
    numBread: number;
    numBeef: number;
}

// 재료를 알려주는 함수
// parameter가 union type으로 되어있다.

function sayIngredient (burger: CheeseBurger | BeefBurger) {
    console.log('number of bread : ' + burger.numBread)
    }
    

 //numBread는 CheeseBurger와 BeefBurger 전부 가지고있는 요소이다.
 // 그래서 TS 컴파일러가 이미 알고있기때문에
 // Type Guard가 필요없다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &amp;lsquo;typeof&amp;rsquo;는 내가 정의한 커스텀 타입에는 사용할 수 없다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;// burger매개변수는 유니온타입이 지정되어있다.

function sayIngredient (burger: CheeseBurger | BeefBurger) {

//BeefBurger일때만 실행되는 코드.
// 커스텀타입은 typeof로 체크해줄수 없다.

if (typeof burger === 'BeefBurger') {
        console.log('number of beef : ' + burger.numBeef
    }

console.log('number of bread : ' + burger.numBread)
    }
// 아래와 같은 오류 메시지 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;typeof의 반환값은 기본 내장 타입으로 구성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 커스텀 타입 타입가드 성분을 추적하는 &amp;lsquo;in&amp;rsquo; 활용하기.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function sayIngredient (burger: CheeseBurger | BeefBurger) {
    console.log('number of bread : ' + burger.numBread)
    
    //타입가드 numCheese와 numBeef요소의 존재로
    // CheeseBurger인지 BeefBurger인지 검사한다.
    
    if('numCheese' in burger) {
        console.log('number of cheese : ' +  burger.numCheese)
    } else if ('numBeef' in burger) {
        console.log('number of beef : ' + burger.numBeef)
        }
    
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스 유니온타입 타입가드 &amp;rsquo;instanceof&amp;rsquo; 활용하기.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;class Burger {
    public setMenu = 'french fries and coke'

}

class SideMenu {
    public beverage = 'coke or cider'
}

const order1 = new Burger()
const order2 = new SideMenu()

//burger와 sideMenu의 유니온타입을 
//매개변수의 타입으로 지정한 함수

function checkPlusOrder (order: Burger | SideMenu) {
    if (order instanceof Burger){
        console.log(order.setMenu);
    }
    if (order instanceof SideMenu){
        console.log(order.beverage);
    }
}
//instanceof를 이용하여 order가 어떤 class에 속하는지 체크한다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- discriminated union 사용하기 유니온 타입에 들어가는 &amp;ldquo;구분대상&amp;rdquo;의 개별요소에 구분을 위한 성분을 집어넣고, switch문을 타입가드로 이용한다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;// interface에 kind라는 구분용 요소를 넣어놓았다.

interface Burger {
    kind: &quot;burger&quot;;
    setMenu: string;
}

interface SideMenu {
    kind: &quot;sideMenu&quot;;
    beverage: string;
}

function checkPlusOrder(order: Burger | SideMenu) {
    switch (order.kind) {
        case &quot;burger&quot;:
            console.log(order.setMenu);
            break;
        case &quot;sideMenu&quot;:
            console.log(order.beverage);
            break;
    }
}
//switch문과 기존의 interface에 심어놓은 구분용변수  &quot;kind&quot;
//를 이용하여 type guard를 구현하였다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;nbsp;enum 타입 타입가드&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;enum Color {
  Red = &quot;red&quot;,
  Blue = &quot;blue&quot;,
}

enum Size {
  Big = &quot;big&quot;,
  Small = &quot;small&quot;,
}

const isColorEnum = (something: Color | Size): something is Color =&amp;gt;
  (something as Color).Red !== undefined; // Error: Property 'Red' does not exist on type 'Color'.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넘어올 수 있는 타입인 Color와 Size는 모두 enum이기 때문에, something은 red, blue, big, small 중 하나다. 따라서 애초에 something에는 Red 라는 프로퍼티가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 작성하면 정상 동작한다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;enum Color {
  Red = &quot;red&quot;,
  Blue = &quot;blue&quot;,
}

enum Size {
  Big = &quot;big&quot;,
  Small = &quot;small&quot;,
}

const isColorEnum = (something: Color | Size): something is Color =&amp;gt;
  Object.values(Color).includes(something as Color);

console.log(isColorEnum(Color.Red)); // true
console.log(isColorEnum(Size.Small)); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- falsy value(null 등)을 걸러낼 때&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;type Car = {
  color: string,
  price: number,
};

type Person = {
  name: string,
  age: number,
  height: number,
};

function logSomething(something: Car | Person | null) {
  if (something) {
    // something: Car | Person
  } else {
    // something: null;
  }
}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Frontend/Typescript</category>
      <category>fe</category>
      <category>Frontend</category>
      <category>js</category>
      <category>TS</category>
      <category>Type</category>
      <category>TypeGuard</category>
      <category>Typescript</category>
      <category>웹개발</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/10</guid>
      <comments>https://digwon.tistory.com/entry/Typescript-Type-Guard#entry10comment</comments>
      <pubDate>Sun, 12 Mar 2023 16:31:17 +0900</pubDate>
    </item>
    <item>
      <title>[Typescript] Enum</title>
      <link>https://digwon.tistory.com/entry/Typescript-Enum</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;enum이란&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;enum은 Typescript가 자체적으로 구현하는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;enum은 여러 값들에 미리 이름을 정의하여 열거해 사용하는 타입입니다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;enum Auth {
    admin = 0, // 관리자를 0으로 표현
    user = 1,  // 회원은 1로 표현
    guest = 2  // 게스트는 2로 표현
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;필요성과 존재 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 분야별 종류를 정의하여 명확하게&amp;nbsp;사용하기 위해&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 사용자 권한을 관리자 = 0, 회원 = 1, 게스트 = 2로 관리할 경우, 개발자는 관리자 === 0 이라는 점을 기억하고 코딩해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;// 관리자 여부를 숫자로 체크한다.
if (userType !== 0) {
    alert(&quot;관리자 권한이 없습니다&quot;);
}

// 만약 회원 타입이 20종류가 넘어간다면???
// 관리하는 분야가 회원, 게시물, 언어타입 등등 더 늘어난다면?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 enum으로 정의해두면, 사용자 권한 분야만 따로 모아 정의하고, 의미를 명확히 파악해 사용할 수 있습니다. 자동완성까지 되므로 코딩이 편해지고, 실수도 줄어들며, 가독성도 좋아집니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// 회원 권한을 enum으로 정의
enum Auth {
    admin = 0, // 관리자
    user = 1,  // 회원
    guest = 2  // 게스트
}

// Auth.admin(==0) 으로 의미있게 값 체크 가능
if (userType !== Auth.admin) {
    alert(&quot;관리자 권한이 없습니다&quot;);
}

// 누가 코드를 읽어도, 관리자 여부를 체크하는 코드임을 이해할 수 있다!
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 하드코딩 실수를 줄이기 위해서.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;enum을 사용하면 하드코딩을 막고, 실수를 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 언어 종류를 정의해야하는 경우, 직접 'ko', 'en' 을 하드코딩하면 실수하기도 쉽고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'ko' 였는지, 'KO' 였는지, 'ko-KR' 이었는지 등을 매번 찾아봐야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, enum으로 정의해두면 이런 하드코딩의 폐해를 막을 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;// 언어 종류 관리
enum Languages {
    korean = 'ko', // 문자열을 입력할 수도 있다.
    english = 'en',
    japanese = 'jp',
    chiense = 'cn'
}

// setLanguage(&quot;ko-kr&quot;) // 하드코딩은 이런 실수를 유발한다.
setLanguage(Languages.korean) // enum 사용시, 의미파악이 쉽고 자동완성까지 된다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기초 문법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. enum은 기본으로 0부터 1씩 증가하는 값을 갖는다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;enum Auth {
    admin, // 0 : 별도로 값을 지정해주지 않으면 0부터 시작한다
    user,  // 1 : 이전 값에 1씩 더해진다.
    guest  // 2 : 이전 값에 1씩 더해진다.
}

console.log(Auth.admin);  // 0
console.log(Auth.user);   // 1
console.log(Auth.guest);  // 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 숫자 값을 지정할 수 있다.&lt;/b&gt; (정의되지 않은 값은 이전 값에서 1씩 증가한다.)&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;/*** 2. 숫자 값을 지정해줄 수 있다. 정의되지 않으면 이전 값에서 1씩 증가한다. ***/
enum Articles {
    notice = 100, // 값을 직접 지정 가능
    board = 300,  // 값을 직접 지정 가능
    comment       // 자동으로 앞의 300에 +1 더해줌 =&amp;gt; 301
}

console.log(Articles.notice);  // 100
console.log(Articles.board);   // 300
console.log(Articles.comment); // 301
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 문자열을 지정할 수&amp;nbsp;있다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;/*** 3. 문자열을 지정해 줄수 있다. ***/
enum Languages {
    korean = 'ko',
    english = 'en',
    japanese = 'jp',
    chiense = 'cn'
}

console.log(Languages.korean);   // &quot;ko&quot;
console.log(Languages.english);  // &quot;en&quot;
console.log(Languages.japanese); // &quot;jp&quot;
console.log(Languages.chiense);  // &quot;cn&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JS 객체와의 차이점&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;enum은 한번 생성되면, 속성 추가 및 수정이 불가하다. 객체는 생성 이후에도 속성을 추가하고 변경할 수 있다.&lt;/li&gt;
&lt;li&gt;enum은 속성 값으로 숫자, 문자열만 할당할 수 있다. 객체는 온갖 것을 다 넣을 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, enum은 JS객체보다 더 엄격하게 타입을 정의하여 사용할 때 유용하다. (이게 타입스크립트를 사용하는 이유 중 하나이기도 하다)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;참고: TypeScript enum을 사용하지 않는 게 좋은 이유&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678605405558&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.&quot; data-og-description=&quot;들어가며 안녕하세요. LINE Growth Technology UIT 팀의 Keishima(@pittanko_pta)입니다.&amp;nbsp;이번 글에서는 TypeScript의&amp;nbsp;enum을 사용하지 않는 편이 좋은 이유를 Tree-shaking 관점에서 소개하겠습니...&quot; data-og-host=&quot;engineering.linecorp.com&quot; data-og-source-url=&quot;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/&quot; data-og-url=&quot;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dAqqeT/hyRTYo9ZGB/ubtkVSM7lfPKmwiKHAqCP0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/fWUti/hyRTNVmky2/6k6qbAuz8ktmthFmJ64cK0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/bm6D6Z/hyRTXjoUpZ/LtXHrfxkYKM9VHmjrPHF20/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dAqqeT/hyRTYo9ZGB/ubtkVSM7lfPKmwiKHAqCP0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/fWUti/hyRTNVmky2/6k6qbAuz8ktmthFmJ64cK0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/bm6D6Z/hyRTXjoUpZ/LtXHrfxkYKM9VHmjrPHF20/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;들어가며 안녕하세요. LINE Growth Technology UIT 팀의 Keishima(@pittanko_pta)입니다.&amp;nbsp;이번 글에서는 TypeScript의&amp;nbsp;enum을 사용하지 않는 편이 좋은 이유를 Tree-shaking 관점에서 소개하겠습니...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;engineering.linecorp.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tree-shaking 관점에서 보았을 때 아래와 같은 순서로 사용하시길&amp;nbsp;추천하며 글을 마치겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Union Types &amp;gt; const enum &amp;gt; enum&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>Frontend/Typescript</category>
      <category>Enum</category>
      <category>Frontend</category>
      <category>Typescript</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/9</guid>
      <comments>https://digwon.tistory.com/entry/Typescript-Enum#entry9comment</comments>
      <pubDate>Sun, 12 Mar 2023 16:17:58 +0900</pubDate>
    </item>
    <item>
      <title>[Typescript] type과 Interface</title>
      <link>https://digwon.tistory.com/entry/Typescript-type%EA%B3%BC-Interface</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서 타입(Type)과 인터페이스(Interface)는 유사한 점이 매우 많고, 여러 경우에 자유롭게 혼용되어 사용 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;interface AnimalInterface {
  species: string
  height: number
  weight: number
}

const tiger: AnimalInterface = {
  species: 'tiger',
  height: 200,
  weight: 300
}

type AnimalType = {
  species: string,
  height: number,
  weight: number
}

const lion: AnimalType = {
  species: 'lion',
  height: 180,
  weight: 400
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 둘의 차이와 한계를 이해하고 &lt;b&gt;표준화해 사용&lt;/b&gt;하는 것이 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공식문서에서 특별한 경우를 제외하고 type보다 interface 사용을 권장!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 저는 interface 위주로 정리하겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;확장하는 방법(상속)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;interface AnimalInterface {
  species: string
  height: number
  weight: number
}

interface AfricaAnimal extends AnimalInterface {
  continent: string
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface는 extends로 확장&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;type AnimalType = {
  species: string,
  height: number,
  weight: number
}

type AfricaAnimal = AnimalInterface &amp;amp; {
  continent: string
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type은 &amp;amp;로 확장&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선언적 확장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface는 선언적 확장이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type은 새로운 속성을 추가하기 위한 선언적 확장이 불가능합니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;interface Animal {
  weight: number;
}

interface Animal {
  height: number;
}

const tiger: Animal = {
  weight: 100,
  height: 200,
};
console.log(tiger);

type _Animal = {
  weight: number;
};

type _Animal = {//error : 식별자가 중복됨
  height: string;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;interface는 객체에만 사용 가능&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;// 객체 타입 선언 가능
type AnimalType = {
  name: string
}
//리터럴 타입 선언 가능
type AnimalOnlyString = string

// 객체만 선언 가능
interface AnimalInterface {
  name: string
}

//리터럴 타입으로 확장 불가능
interface AnimalInterface extends string {} //error
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;computed value 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type만 가능&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;type names = 'firstName' | 'lastName'

type NameTypes = {
  [key in names]: string
}

const yc: NameTypes = { firstName: 'hi', lastName: 'yc' }

interface NameInterface {
  // error
  [key in names]: string
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;type VS interface 확장시 성능 비교&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말씀드리면 &lt;b&gt;interface가 훨씬 좋습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface는 확장시 속성간 충돌을 피하기 위해 단순한 객체 타입을 만듭니다. 왜냐하면 interface는 객체만 오기 때문에 단순히 합치기만 하면 되기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 type은 재귀적으로 순회하면서 속성을 merge하는데, interface와 다르게 type은 원시 타입이 올수도 있으므로 충돌이 나서 제대로 merge되지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, interface를 합성할 경우 이는 캐시가 되지만, type은 그렇지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type은 합성에 대한 유효성을 판단하기 전에 모든 구성요소에 대한 type을 체크하기 때문에 컴파일 시에 상대적으로 성능이 좋지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678605157989&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Differences Between Type Aliases and Interfaces in TypeScript 4.6&quot; data-og-description=&quot;Type aliases and interfaces are very similar, so which one should I use?&quot; data-og-host=&quot;betterprogramming.pub&quot; data-og-source-url=&quot;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&quot; data-og-url=&quot;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://betterprogramming.pub/differences-between-type-aliases-and-interfaces-in-typescript-4-6-6489246d4e48&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Differences Between Type Aliases and Interfaces in TypeScript 4.6&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Type aliases and interfaces are very similar, so which one should I use?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;betterprogramming.pub&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Typescript</category>
      <category>Frontend</category>
      <category>Interface</category>
      <category>Type</category>
      <category>Typescript</category>
      <category>web</category>
      <category>웹개발</category>
      <category>웹개발 기초</category>
      <category>프론트엔드</category>
      <category>프론트엔드 기초</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/8</guid>
      <comments>https://digwon.tistory.com/entry/Typescript-type%EA%B3%BC-Interface#entry8comment</comments>
      <pubDate>Sun, 12 Mar 2023 16:13:58 +0900</pubDate>
    </item>
    <item>
      <title>[TypeScript] 잘 사용하기</title>
      <link>https://digwon.tistory.com/entry/TypeScript%EC%9E%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;정확한 타입 지정하기 (any 사용 피하기)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;any 변수의 데이터 유형을 알고 있는 경우 any를 사용하지 마세요. 새 변수를 선언할 때마다 데이터 유형을 정의하는 것이 좋습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;strict 모드 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES5에서 use strict 기능이 추가됐습니다. tsconfig.js 파일에서 strict 환경설정을 찾을 수 있습니다. 이는 선언되지 않은 변수를 사용하거나 타입 지정을 하지 않거나 예약어를 변수이름으로 사용하려고 시도하는 등의 실수를 제한합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;변수는 let, 상수는 const 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 var는 똑같은 변수명으로 다시 선언해도 오류가 발생하지 않습니다. 타입스크립트는 어떠한 오류를 보여주지 않지만 예상치 못한 결과로 끝나게 됩니다. 이를 막기 위해 let, const을 사용해야 합니다. let, const은 블록스코프 변수입니다. 재선언이 불가하고 같은 변수명으로 다른 스코프에서 사용할 수 있으며 각각 다른 변수로 다룰 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;고정길이 배열에 튜플(tuple) 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;let marks: number[] = [1, 2, 3];
marks = []; // success
marks = [1]; // success
marks = [1, 2, 3, 4, 5]; // success

// 배열의 길이가 일정한 경우 심각한 논리적 오류 야기 가능성 존재
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;let marks: [number, number] = [1, 2]; //tuple of 2 number
marks = [2, 3]; // success
marks = [1]; // syntax error
marks = [1, 2, 3, 4, 5]; // syntax error
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;반복적인 데이터 유형에서 타입 별칭(type aliases)사용&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;let man: {name: string, age: number} = {name = &quot;john&quot;, age=30};
let woman: {name: string, age: number} = {name = &quot;Anne&quot;, age=32};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;type Details = {name: string, age: number}; // defining type alias
let man: Details = {name = &quot;john&quot;, age=30}; // using type alias
let woman: Details = {name = &quot;Anne&quot;, age=32};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;any 와 unknown 중에 선택해서 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통점: 모든 타입의 값 할당 가능.&lt;/p&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;let variable: unknown //any로 바꿔도 결과는 같음

variable = true // OK (boolean)
variable = 1 // OK (number)
variable = 'string' // OK (string)
variable = {} // OK (object)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차이점:&lt;/p&gt;
&lt;pre class=&quot;vhdl&quot;&gt;&lt;code&gt;let variable: unknown

let anyType: any = variable
let booleanType: boolean = variable
// Error: Type 'unknown' is not assignable to type 'boolean'.(2322)
let numberType: number = variable
//  Error: Type 'unknown' is not assignable to type 'number'.(2322)
let stringType: string = variable
//  Error: Type 'unknown' is not assignable to type 'string'.(2322)
let objectType: object = variable
//  Error: Type 'unknown' is not assignable to type 'object'.(2322)

// unknown 타입으로 선언된 변수는 any를 제외한 다른 타입으로 선언된 변수에 할당 불가
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;let variable: unknown

variable.foo.bar // Error: Object is of type 'unknown'.(2571)
variable[0] // Error
variable.trigger() // Error
variable() // Error
new variable() // Error

// unknown 타입으로 선언된 변수는 프로퍼티에 접근 불가, 메소드 호출 불가, 인스턴스 생성 불가
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스 멤버를 위한 액세스 수정자 사용하기 타입스크립트는 클래스 속성에 대한 액세스 수정자가 제공됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;private: 클래스 내부에서만 접근 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;protected: 클래스 내부나 하위 클래스를 통해서만 접근 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public: 어디에서나 액세스 가능&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;class Employee {
  protected name: string;
  private salary: number;
  
  constructor(name: string, salary: number) {
    this.name = name;
    this.salary = salary
  }

  public getSalary(){
    return salary
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Developer extends Employee{
  viewDetails(){
    console.log(this.salary); // error: property 'salary' is private
    console.log(this.getSalary()); // success
  }
}
// getSalary 메소드를 사용하지 않으면 salary 접근 불가
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Developer extends Employee{
  viewDetails(){
    console.log(this.name);
  }
}
// name은 하위 클래스 통해 접근 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;불필요한 주석 피하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수와 함수의 이름은 항상 직관적인 이름을 쓰려고 시도하세요. 소스 코드 라인에 주석하지 마세요. 디버깅에선 허용하지만 주석처리된 소스코드를 푸시하지 않도록 주의하세요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Linter 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드베이스를 오염시키고 싶지 않다면 lint 툴을 사용하는 것은 정말 중요합니다. 팀에서 일할 때 이건 특히 중요합니다. 모든 개발자가 동일한 규칙 하에 있도록 linter를 사용해야 합니다. ESLint를 사용하세요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;code formatter 사용하기&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 code formatter를 사용하면 코딩의 효율성을 높일 수 있습니다. VS code를 사용한다면 Prettier를 적용하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처: &lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://medium.com/@warkiringoda/typescript-best-practices-2021-a58aee199661&quot;&gt;https://medium.com/@warkiringoda/typescript-best-practices-2021-a58aee199661&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/Typescript</category>
      <category>fe</category>
      <category>Frontend</category>
      <category>Typescript</category>
      <category>웹개발</category>
      <category>웹개발 기초</category>
      <category>프론트엔드</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/7</guid>
      <comments>https://digwon.tistory.com/entry/TypeScript%EC%9E%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0#entry7comment</comments>
      <pubDate>Sun, 19 Feb 2023 23:19:05 +0900</pubDate>
    </item>
    <item>
      <title>[TypeScript] 동작 원리, 장점과 단점</title>
      <link>https://digwon.tistory.com/entry/TypeScript-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EB%8B%A8%EC%A0%90</link>
      <description>&lt;h1&gt;- 동작원리&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4yk2B/btrZV7LHT5j/gc8hV1rJ71KGtTcNQrY7k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4yk2B/btrZV7LHT5j/gc8hV1rJ71KGtTcNQrY7k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4yk2B/btrZV7LHT5j/gc8hV1rJ71KGtTcNQrY7k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4yk2B%2FbtrZV7LHT5j%2Fgc8hV1rJ71KGtTcNQrY7k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;701&quot; height=&quot;310&quot; data-origin-width=&quot;701&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;텍스트를 컴파일러 프로그램이 파싱해 AST라는 자료 구조로 변환
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AST(Abstract Syntax Tree) : 추상 문법 트리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;컴파일러 프로그램이 AST를 바이트 코드로 변환&lt;/li&gt;
&lt;li&gt;런타임 프로그램에 바이트 코드를 입력해 평가받은 결과 출력&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;- 장점&lt;/h1&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;정적 타입 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;TypeScript는 &lt;b&gt;정적 타입을 지원&lt;/b&gt;하므로 컴파일 단계에서 오류를 포착 할 수 있다. (tsc라는 명령어로 타입 스크립트 파일 컴퍼일 &amp;rarr; 자바스크립트로 출력 &amp;rarr; 문법 에러 catch) 또한, tsconfig.js 파일에 명시된 ECMA 버전으로 자동 변환 가능. 명시적인 정적 타입 지정은 개발자의 의도를 명확하게 코드로 기술 할 수 있다. 이는 코드의 가독성을 높이고 예측할 수 있게 하며 디버깅을 쉽게 한다.&lt;/p&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;function sum(a: number, b: number) {
  return a + b;
}

sum('x', 'y');
// error TS2345: Argument of type '&quot;x&quot;' is not assignable to parameter of type 'number'.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;강력한 객체지향 프로그래밍 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;b&gt;인터페이스, 제너릭&lt;/b&gt; 등과 같은 강력한 객체지향 프로그래밍 지원은 크고 복잡한 프로젝트의 코드 기반을 쉽게 구성할 수 있도록 돕고 Java, C# 등의 클래스 기반 객체지향 언어에 익숙한 개발자가 자바스크립트 프로젝트를 수행하는 데 진입 장벽을 낮추는 효과도 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;interface Options { color: string; volume: number }
let options = {} as Options;
options.color = &quot;red&quot;;
options.volume = 11;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제너릭&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;type StringArray = Array&amp;lt;string&amp;gt;;
type NumberArray = Array&amp;lt;number&amp;gt;;
type ObjectWithNameArray = Array&amp;lt;{ name: string }&amp;gt;;

// @errors: 2345
interface Backpack&amp;lt;Type&amp;gt; {
  add: (obj: Type) =&amp;gt; void;
  get: () =&amp;gt; Type;
}

// 이 줄은 TypeScript에 `backpack`이라는 상수가 있음을 알리는 지름길이며
// const backpack: Backpack&amp;lt;string&amp;gt;이 어디서 왔는지 걱정할 필요가 없습니다.
declare const backpack: Backpack&amp;lt;string&amp;gt;;

// 위에서 Backpack의 변수 부분으로 선언해서, object는 string입니다.
const object = backpack.get();

// backpack 변수가 string이므로, add 함수에 number를 전달할 수 없습니다.
backpack.add(23);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ES6/ ES Next 지원&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VL37o/btrZJcuOCHm/yblrH6XsKYK9QB5W6RAVwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VL37o/btrZJcuOCHm/yblrH6XsKYK9QB5W6RAVwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VL37o/btrZJcuOCHm/yblrH6XsKYK9QB5W6RAVwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVL37o%2FbtrZJcuOCHm%2FyblrH6XsKYK9QB5W6RAVwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;547&quot; height=&quot;453&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 스크립트는 ES Next 문법을 사용해도 tsconfig.js에 지정된 자바스크립트 버전으로 자동 변환이 가능하기 때문에 개발자는 최신 자바스크립트의 편리한 기능들을 호환성 걱정 없이 사용할 수 있다.(일부 모듈에서는 여전히 Babel 필요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;타입을 강제화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 변수에 값을 넣을 때 타입을 엄격하게 체크하지 않는 &amp;lsquo;세미 타입&amp;rsquo; 언어이기 때문에 변수에 입력된 값의 타입을 보고 타입 추론을 활용해 자동으로 형변환을 한다. 개발자 입장에서 코딩은 편리하지만 개발자들 간의 소통 문제로 버그를 발생시킬 여지가 있다. 하지만 타입 스크립트는 모든 객체에 타입을 강제화하여 타입으로 발생하는 문제를 원천 차단한다.&lt;/p&gt;
&lt;h1&gt;- 단점&lt;/h1&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;개발 공수 증가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;타입 스크립트는 타입 강제화를 위해 코드 타입을 지정해야 하기 때문에 개발 공수가 증가합니다. 만약 타입을 지정하지 않는다면 타입을 추론해야 하는데 타입을 추론하기 힘든 경우, 컴파일러에게 알려주는 형 변환을 하거나, 제너릭을 사용해 어떤 타입이 들어오더라도 동작할 수 있도록 선언해야 합니다.&lt;/p&gt;</description>
      <category>Frontend/Typescript</category>
      <category>fe</category>
      <category>Frontend</category>
      <category>Typescript</category>
      <category>웹개발</category>
      <category>웹개발 기초</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/6</guid>
      <comments>https://digwon.tistory.com/entry/TypeScript-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EB%8B%A8%EC%A0%90#entry6comment</comments>
      <pubDate>Sun, 19 Feb 2023 21:09:39 +0900</pubDate>
    </item>
    <item>
      <title>[Composition API] Vue3 Slots 사용하기(script setup)</title>
      <link>https://digwon.tistory.com/entry/Composition-API-Vue3-Slots-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0script-setup</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용 배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트 템플릿과 자식 컴포넌트 템플릿 사이 데이터(slot content) 통신 후 화면 랜더링을 원할 경우 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 파일 구조&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-25 at 2.59.59 PM.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsx8XN/btrUYqYh8Wz/hiAaJKj4vqOSj5FClsDCkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsx8XN/btrUYqYh8Wz/hiAaJKj4vqOSj5FClsDCkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsx8XN/btrUYqYh8Wz/hiAaJKj4vqOSj5FClsDCkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsx8XN%2FbtrUYqYh8Wz%2FhiAaJKj4vqOSj5FClsDCkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;374&quot; height=&quot;273&quot; data-filename=&quot;Screenshot 2022-12-25 at 2.59.59 PM.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 파일 구조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독자분들의 이해를 돕기 위해 프로젝트 생성 시 자동으로 구성되는 프로젝트 구조를 그대로 사용하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 구현 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(App.vue와 main.js 파일은 전혀 손대지 않았습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 부모 컴포넌트 템플릿 -&amp;gt; 자식 컴포넌트 템플릿 방향으로 데이터를 전송하는 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 자식 컴포넌트인 HelloWorld.vue 파일입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672487944178&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HelloWorld.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;hello&quot;&amp;gt;
    &amp;lt;button @click=&quot;buttonClick&quot;&amp;gt;
      &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
    &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
import { defineEmits } from &quot;vue&quot;;

const emit = defineEmits([&quot;submit&quot;]);

function buttonClick() {
  emit(&quot;submit&quot;, &quot;data&quot;);
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 8.55.43 PM.png&quot; data-origin-width=&quot;287&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFmkvb/btrUXpynT8K/EsKNe1oHS8tRarrwytiMFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFmkvb/btrUXpynT8K/EsKNe1oHS8tRarrwytiMFK/img.png&quot; data-alt=&quot;버튼 클릭 전 페이지 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFmkvb/btrUXpynT8K/EsKNe1oHS8tRarrwytiMFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFmkvb%2FbtrUXpynT8K%2FEsKNe1oHS8tRarrwytiMFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;287&quot; height=&quot;301&quot; data-filename=&quot;Screenshot 2022-12-31 at 8.55.43 PM.png&quot; data-origin-width=&quot;287&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼 클릭 전 페이지 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼 클릭 -&amp;gt; 부모 컴포넌트 HomeView.vue로 data 전송&lt;/p&gt;
&lt;pre id=&quot;code_1672487693945&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HomeView.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;home&quot;&amp;gt;
    &amp;lt;img alt=&quot;Vue logo&quot; src=&quot;../assets/logo.png&quot; /&amp;gt;
    &amp;lt;HelloWorld @submit=&quot;emitTest&quot;&amp;gt;{{ data }}&amp;lt;/HelloWorld&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
import { ref } from &quot;vue&quot;;
// @ is an alias to /src
import HelloWorld from &quot;@/components/HelloWorld.vue&quot;;

const data = ref(null);
function emitTest(e) {
  data.value = e;
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트 HomeView.vue -&amp;gt; 자식 컴포넌트 HelloWorld.vue로 slot content로 data를 넘겨주는 로직입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 9.11.45 PM.png&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mGtj2/btrU6YZ4vcr/bDOSBsj0moZdFftbBiitbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mGtj2/btrU6YZ4vcr/bDOSBsj0moZdFftbBiitbk/img.png&quot; data-alt=&quot;버튼 클릭 후 페이지 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mGtj2/btrU6YZ4vcr/bDOSBsj0moZdFftbBiitbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmGtj2%2FbtrU6YZ4vcr%2FbDOSBsj0moZdFftbBiitbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;321&quot; height=&quot;311&quot; data-filename=&quot;Screenshot 2022-12-31 at 9.11.45 PM.png&quot; data-origin-width=&quot;321&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;버튼 클릭 후 페이지 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼 내부에 data가 생겼다면 성공입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 자식 컴포넌트 템플릿 -&amp;gt; 부모 컴포넌트 템플릿 방향으로 데이터를 전송하는 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 자식 컴포넌트인 HelloWorld.vue 파일입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672490609537&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HelloWorld.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;hello&quot;&amp;gt;
    &amp;lt;slot :text=&quot;msg&quot;&amp;gt;&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
const msg = &quot;message&quot;;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;slot props로 msg 데이터를 text라는 변수로 전달합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672490751333&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HomeView.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;home&quot;&amp;gt;
    &amp;lt;img alt=&quot;Vue logo&quot; src=&quot;../assets/logo.png&quot; /&amp;gt;
    &amp;lt;HelloWorld v-slot=&quot;slotProps&quot;&amp;gt;{{ slotProps.text }}&amp;lt;/HelloWorld&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
// @ is an alias to /src
import HelloWorld from &quot;@/components/HelloWorld.vue&quot;;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;v-slot을 사용해 자식 컴포넌트에서 넘어온 데이터를 slotProps로 불러옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트에서 text라는 변수로 전달했으니 slotProps.text로 접근합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 9.47.21 PM.png&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kzSUG/btrU2KnVjbs/nFBBJ2mRXGSEIkxqb1vvG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kzSUG/btrU2KnVjbs/nFBBJ2mRXGSEIkxqb1vvG0/img.png&quot; data-alt=&quot;페이지 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kzSUG/btrU2KnVjbs/nFBBJ2mRXGSEIkxqb1vvG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkzSUG%2FbtrU2KnVjbs%2FnFBBJ2mRXGSEIkxqb1vvG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;268&quot; height=&quot;301&quot; data-filename=&quot;Screenshot 2022-12-31 at 9.47.21 PM.png&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;페이지 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면에 message 가 보이면 성공입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 결론&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;slot은 부모 컴포넌트에서 자식 컴포넌트의 엘리먼트를 지정할 경우 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모에 따라 자식 컴포넌트가 영향을 받기 때문에 컴포넌트 재사용성을 높이기 위해 활용이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 설명은 아래의 공식 문서를 참고하세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vuejs.org/guide/components/slots.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://vuejs.org/guide/components/slots.html&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/Vue3</category>
      <category>composition api</category>
      <category>fe</category>
      <category>Frontend</category>
      <category>script setup</category>
      <category>Slots</category>
      <category>vue3</category>
      <category>웹개발</category>
      <category>웹개발 기초</category>
      <category>프론트엔드</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/5</guid>
      <comments>https://digwon.tistory.com/entry/Composition-API-Vue3-Slots-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0script-setup#entry5comment</comments>
      <pubDate>Sat, 31 Dec 2022 21:57:40 +0900</pubDate>
    </item>
    <item>
      <title>[Composition API] Vue3 Emit 사용하기(script setup)</title>
      <link>https://digwon.tistory.com/entry/Composition-API-Vue3-Emit-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0script-setup</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용 배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Emit는 하위 컴포넌트(자식)에서 상위 컴포넌트(부모)로 이벤트로 데이터를 넘겨줄 경우 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 파일 구조&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kA6vc/btrUusWFCUj/i5WmBjsnpdoKbKF7kScWD0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;프로젝트 파일 구조&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-25 at 2.59.59 PM.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JmVQQ/btrU1NSDyqz/Z3feIPH5zahn1DIX3QqD10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JmVQQ/btrU1NSDyqz/Z3feIPH5zahn1DIX3QqD10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JmVQQ/btrU1NSDyqz/Z3feIPH5zahn1DIX3QqD10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJmVQQ%2FbtrU1NSDyqz%2FZ3feIPH5zahn1DIX3QqD10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;374&quot; height=&quot;273&quot; data-filename=&quot;Screenshot 2022-12-25 at 2.59.59 PM.png&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kA6vc/btrUusWFCUj/i5WmBjsnpdoKbKF7kScWD0/img.png&quot; data-lightbox=&quot;lightbox&quot; data-alt=&quot;프로젝트 파일 구조&quot;&gt;&lt;/span&gt;프로젝트 파일 구조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독자분들의 이해를 돕기 위해 프로젝트 생성 시 자동으로 구성되는 프로젝트 구조를 그대로 사용하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 구현 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(App.vue와 main.js 파일은 전혀 손대지 않았습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트인 HelloWorld.vue 파일부터 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.40.33 PM.png&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwcaDg/btrUYPKiYsC/faDCZXQ1R7N1xLzgAGha70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwcaDg/btrUYPKiYsC/faDCZXQ1R7N1xLzgAGha70/img.png&quot; data-alt=&quot;자식 컴포넌트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwcaDg/btrUYPKiYsC/faDCZXQ1R7N1xLzgAGha70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwcaDg%2FbtrUYPKiYsC%2FfaDCZXQ1R7N1xLzgAGha70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;432&quot; height=&quot;339&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.40.33 PM.png&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자식 컴포넌트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1672486238553&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HelloWorld.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;hello&quot;&amp;gt;
    &amp;lt;button @click=&quot;buttonClick&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
import { defineEmits } from &quot;vue&quot;;

const emit = defineEmits([&quot;submit&quot;]);

function buttonClick() {
  emit(&quot;submit&quot;, &quot;data&quot;);
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버튼을 클릭하면 &quot;data&quot;가 이벤트로 전달되는 로직입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.37.30 PM.png&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bolzjA/btrU3739hvs/SNYk3Tnhat49FKU5v2T160/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bolzjA/btrU3739hvs/SNYk3Tnhat49FKU5v2T160/img.png&quot; data-alt=&quot;페이지 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bolzjA/btrU3739hvs/SNYk3Tnhat49FKU5v2T160/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbolzjA%2FbtrU3739hvs%2FSNYk3Tnhat49FKU5v2T160%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;297&quot; height=&quot;315&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.37.30 PM.png&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;페이지 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지에 Submit 버튼을 누르면 부모 컴포넌트로 데이터가 넘어갑니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.31.45 PM.png&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bq9luQ/btrUYpyb4uC/ycAH6bdSpTPVptM39lYsv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bq9luQ/btrUYpyb4uC/ycAH6bdSpTPVptM39lYsv1/img.png&quot; data-alt=&quot;부모 컴포넌트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bq9luQ/btrUYpyb4uC/ycAH6bdSpTPVptM39lYsv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbq9luQ%2FbtrUYpyb4uC%2FycAH6bdSpTPVptM39lYsv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;325&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.31.45 PM.png&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;부모 컴포넌트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1672486319830&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//HomeView.vue

&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;home&quot;&amp;gt;
    &amp;lt;img alt=&quot;Vue logo&quot; src=&quot;../assets/logo.png&quot; /&amp;gt;
    &amp;lt;HelloWorld @submit=&quot;emitTest&quot; /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
// @ is an alias to /src
import HelloWorld from &quot;@/components/HelloWorld.vue&quot;;

function emitTest(data) {
  console.log(data);
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1672479159605&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;HelloWorld @submit=&quot;emitTest&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@submit을 통해 하위 컴포넌트에서 넘어오는 데이터를 받아 emitTest 함수의 파라미터 값으로 전달합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1672479364793&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function emitTest(data) {
  console.log(data);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과가 아래와 같이 나오면 성공입니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.38.14 PM.png&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;18&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SJbVm/btrUZXO0gqv/F43m2jOw2nkpkrPzP0xhTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SJbVm/btrUZXO0gqv/F43m2jOw2nkpkrPzP0xhTK/img.png&quot; data-alt=&quot;console.log 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SJbVm/btrUZXO0gqv/F43m2jOw2nkpkrPzP0xhTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSJbVm%2FbtrUZXO0gqv%2FF43m2jOw2nkpkrPzP0xhTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;609&quot; height=&quot;27&quot; data-filename=&quot;Screenshot 2022-12-31 at 6.38.14 PM.png&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;18&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;console.log 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 결론&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 예제로 Emit을 구현해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에는 Vuex라는 상태관리 라이브러리가 존재하지만, 프로젝트의 구조에 따라 Emit을 사용해야 하는 경우가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 정도 Emit에 대한 개념이 잡히셨다면 아래의 공식 문서에서 심화 예제로 공부해보시는 것을 추천드립니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vuejs.org/guide/components/events.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://vuejs.org/guide/components/events.html&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/Vue3</category>
      <category>composition api</category>
      <category>EMIT</category>
      <category>script setup</category>
      <category>vue3</category>
      <author>gwonmin</author>
      <guid isPermaLink="true">https://digwon.tistory.com/4</guid>
      <comments>https://digwon.tistory.com/entry/Composition-API-Vue3-Emit-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0script-setup#entry4comment</comments>
      <pubDate>Sat, 31 Dec 2022 18:51:21 +0900</pubDate>
    </item>
  </channel>
</rss>