<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Atelier BiCute</title>
    <link>https://bicute.tistory.com/</link>
    <description>[bicute.net] 취미생활과 웹 언어 그리고 다양한 흔적을 기록합니다.</description>
    <language>ko</language>
    <pubDate>Fri, 8 May 2026 15:14:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>BiCute</managingEditor>
    <image>
      <title>Atelier BiCute</title>
      <url>https://tistory1.daumcdn.net/tistory/5270084/attach/5426e75dbcd84ab7afaf4b3aef811794</url>
      <link>https://bicute.tistory.com</link>
    </image>
    <item>
      <title>티스토리 자체 광고 도입 2일차 후기</title>
      <link>https://bicute.tistory.com/286</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Development Tools.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mxj5K/btslMVwi8oR/90A03j2tEEItNDfCQVJgX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mxj5K/btslMVwi8oR/90A03j2tEEItNDfCQVJgX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mxj5K/btslMVwi8oR/90A03j2tEEItNDfCQVJgX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMxj5K%2FbtslMVwi8oR%2F90A03j2tEEItNDfCQVJgX0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;Development Tools.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2023년 06월 27일부터 개별 티스토리 본문 내에 티스토리 자체 광고가 신설되었습니다.&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;/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;/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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어떤 점이 문제인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;① 남들이 모르게 공지를 하기 시작&lt;/h3&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;/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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 내용은 적어는 놓지만 새로운 내용이 없었다는 듯 티는 내지 않는 방식으로요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cat9Mm/btslJHmidux/ZkVEq6KUTRpCbRd2mKuNn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cat9Mm/btslJHmidux/ZkVEq6KUTRpCbRd2mKuNn1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;2160&quot; data-origin-height=&quot;8938&quot; data-filename=&quot;02. 공식 홈 - 찾을수 없음.png&quot; style=&quot;width: 18.3041%; margin-right: 10px;&quot; data-widthpercent=&quot;18.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cat9Mm/btslJHmidux/ZkVEq6KUTRpCbRd2mKuNn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcat9Mm%2FbtslJHmidux%2FZkVEq6KUTRpCbRd2mKuNn1%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;2160&quot; height=&quot;8938&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBVWeE/btslMVJOfEg/qmtkUsS72Mvp8ERnJKBM10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBVWeE/btslMVJOfEg/qmtkUsS72Mvp8ERnJKBM10/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1832&quot; data-origin-height=&quot;1723&quot; data-filename=&quot;03. 이전에 쓴 글 슬그머니 수정.png&quot; data-widthpercent=&quot;81.48&quot; style=&quot;width: 80.5331%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBVWeE/btslMVJOfEg/qmtkUsS72Mvp8ERnJKBM10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBVWeE%2FbtslMVJOfEg%2FqmtkUsS72Mvp8ERnJKBM10%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;1832&quot; height=&quot;1723&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;메인화면 어디에도 보이지 않는 공지 / 5월 게시물을 수정해서 내용을 추가하는 방식으로 공지를 작성&lt;/figcaption&gt;
&lt;/figure&gt;
&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;이것뿐이면 그냥 이번에 어쩌다 보니 카테고리가 안 맞았었고, 특별한 의도 없이 동일한 내용이니 저렇게 공지를 했다고 넘어갈 수도 있었습니다만...&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;② 마음에도 없는 소리를 하기 시작&lt;/h3&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 이를 해결하기 위한 결과가 어떻게 되었는지 보도록 합시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c667Ke/btslMbe4k50/HkZ9cKTSwmFh5m8HK9vQSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c667Ke/btslMbe4k50/HkZ9cKTSwmFh5m8HK9vQSK/img.png&quot; style=&quot;width: 45.2695%; margin-right: 10px;&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;2013&quot; data-origin-height=&quot;1723&quot; data-filename=&quot;09. 현실 - 상단.png&quot; data-widthpercent=&quot;45.8&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c667Ke/btslMbe4k50/HkZ9cKTSwmFh5m8HK9vQSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc667Ke%2FbtslMbe4k50%2FHkZ9cKTSwmFh5m8HK9vQSK%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;2013&quot; height=&quot;1723&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qIEsh/btslNmtM3h3/WFb5Krg2tKjrQQoOeNssWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qIEsh/btslNmtM3h3/WFb5Krg2tKjrQQoOeNssWk/img.png&quot; style=&quot;width: 53.5677%;&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;2382&quot; data-origin-height=&quot;1723&quot; data-filename=&quot;edited_08. 현실 - 하단.png&quot; data-widthpercent=&quot;54.2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qIEsh/btslNmtM3h3/WFb5Krg2tKjrQQoOeNssWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqIEsh%2FbtslNmtM3h3%2FWFb5Krg2tKjrQQoOeNssWk%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;2382&quot; height=&quot;1723&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;상단 광고 뷰 / 하단 광고 뷰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;무분별한 광고로 다른 유저의 사용성을 해치거나, 가독성이 떨어지는 등의 문제가 발생하고 있습니다. 이를 해결하기 위해...&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;광고가 2중으로 겹쳐 나와 본문을 볼 수조차 없고, 내 블로그지만 이게 뭐 하는 페이지인가 싶네요.&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;/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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;③ 공지를 숨겨버리기 시작&lt;/h3&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-1. 티스토리 메인.png&quot; data-origin-width=&quot;3819&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdkIVc/btslKjd7Ij3/JUkxiAZwfq7c4eej45CdN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdkIVc/btslKjd7Ij3/JUkxiAZwfq7c4eej45CdN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdkIVc/btslKjd7Ij3/JUkxiAZwfq7c4eej45CdN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdkIVc%2FbtslKjd7Ij3%2FJUkxiAZwfq7c4eej45CdN1%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;3819&quot; height=&quot;201&quot; data-filename=&quot;01-1. 티스토리 메인.png&quot; data-origin-width=&quot;3819&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-2. 티스토리 피드.png&quot; data-origin-width=&quot;3815&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M0y7s/btslIlcHo5j/BA33pln2tqT6Al7wA68no0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M0y7s/btslIlcHo5j/BA33pln2tqT6Al7wA68no0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M0y7s/btslIlcHo5j/BA33pln2tqT6Al7wA68no0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM0y7s%2FbtslIlcHo5j%2FBA33pln2tqT6Al7wA68no0%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;3815&quot; height=&quot;209&quot; data-filename=&quot;01-2. 티스토리 피드.png&quot; data-origin-width=&quot;3815&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-3. 티스토리 스토리.png&quot; data-origin-width=&quot;3825&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwcJFe/btslKejsNwz/bqg0VZj7WNazmgP16Bz5bK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwcJFe/btslKejsNwz/bqg0VZj7WNazmgP16Bz5bK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwcJFe/btslKejsNwz/bqg0VZj7WNazmgP16Bz5bK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwcJFe%2FbtslKejsNwz%2Fbqg0VZj7WNazmgP16Bz5bK%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;3825&quot; height=&quot;208&quot; data-filename=&quot;01-3. 티스토리 스토리.png&quot; data-origin-width=&quot;3825&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-4. 티스토리 스킨.png&quot; data-origin-width=&quot;3822&quot; data-origin-height=&quot;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn6rgi/btslNmN49BF/kHvY9a9BXTpmLnhYTOBii1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn6rgi/btslNmN49BF/kHvY9a9BXTpmLnhYTOBii1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn6rgi/btslNmN49BF/kHvY9a9BXTpmLnhYTOBii1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn6rgi%2FbtslNmN49BF%2FkHvY9a9BXTpmLnhYTOBii1%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;3822&quot; height=&quot;215&quot; data-filename=&quot;01-4. 티스토리 스킨.png&quot; data-origin-width=&quot;3822&quot; data-origin-height=&quot;215&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;01-5. 티스토리 포럼.png&quot; data-origin-width=&quot;3819&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lr4mw/btslLAMUJFU/Z6LBmJnpgoiA3yMzlVV7k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lr4mw/btslLAMUJFU/Z6LBmJnpgoiA3yMzlVV7k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lr4mw/btslLAMUJFU/Z6LBmJnpgoiA3yMzlVV7k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flr4mw%2FbtslLAMUJFU%2FZ6LBmJnpgoiA3yMzlVV7k1%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;3819&quot; height=&quot;212&quot; data-filename=&quot;01-5. 티스토리 포럼.png&quot; data-origin-width=&quot;3819&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_edited_06. 댓글 - 공지를 노출시켰다 숨겼다.png&quot; data-origin-width=&quot;2895&quot; data-origin-height=&quot;1331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t54Jt/btslJ8w9gfP/DCBkSvvNIwMXEz630aYGwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t54Jt/btslJ8w9gfP/DCBkSvvNIwMXEz630aYGwK/img.png&quot; data-alt=&quot;박살난 민심 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t54Jt/btslJ8w9gfP/DCBkSvvNIwMXEz630aYGwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft54Jt%2FbtslJ8w9gfP%2FDCBkSvvNIwMXEz630aYGwK%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;2895&quot; height=&quot;1331&quot; data-filename=&quot;edited_edited_06. 댓글 - 공지를 노출시켰다 숨겼다.png&quot; data-origin-width=&quot;2895&quot; data-origin-height=&quot;1331&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;박살난 민심 1&lt;/figcaption&gt;
&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;④ 사용자들에게 피해가 가기 시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용은 직접 겪은 내용은 아니니 정확한 판단은 못하겠지만, 이번 광고 덕분에 이미 블로그 운영자들에게도 상당한 피해가 간 거 같습니다.&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;*저 같은 경우에는 블로그를 여러 개 운영하다 보니 기본적으로 몇만 단위 뷰가 발생해서 직접 광고를 클릭한다거나 누가 와서 어느 정도 광고 클릭하며 어그로를 끌어도 경고를 먹지 않는데, 조회수가 아직 얼마 없는 초보 블로거들이나 소규모 블로그에서는 작은 실수라도 경고를 받는 경우가 많습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10. 댓글 - 민심.png&quot; data-origin-width=&quot;3647&quot; data-origin-height=&quot;1671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGX4kc/btslJ9v7j9E/HYmBBai7xHSKd6cossgiKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGX4kc/btslJ9v7j9E/HYmBBai7xHSKd6cossgiKK/img.png&quot; data-alt=&quot;박살난 민심 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGX4kc/btslJ9v7j9E/HYmBBai7xHSKd6cossgiKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGX4kc%2FbtslJ9v7j9E%2FHYmBBai7xHSKd6cossgiKK%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;3647&quot; height=&quot;1671&quot; data-filename=&quot;10. 댓글 - 민심.png&quot; data-origin-width=&quot;3647&quot; data-origin-height=&quot;1671&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;박살난 민심 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충&amp;nbsp;내용을&amp;nbsp;정리해 보면&amp;nbsp;저렇게&amp;nbsp;위와 같이&amp;nbsp;광고를&amp;nbsp;2중으로&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 들어오던 수익이 갑자기 막혀버리면 당연히 분노하겠죠.&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;⑤ 애드센스 수익 창출 및 광고 규정 위반&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정과는 별개로 애초에 애드센스에서는 광고 수익을 제3자 파트너에게 배분하는것을 금지하고있습니다.&lt;/p&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;스크린샷 2023-06-29 오전 9.43.25.png&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/61vlX/btslMbsMA9r/jxw1B4HbHi0DmuTyOGRrLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/61vlX/btslMbsMA9r/jxw1B4HbHi0DmuTyOGRrLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/61vlX/btslMbsMA9r/jxw1B4HbHi0DmuTyOGRrLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F61vlX%2FbtslMbsMA9r%2Fjxw1B4HbHi0DmuTyOGRrLk%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;1524&quot; height=&quot;972&quot; data-filename=&quot;스크린샷 2023-06-29 오전 9.43.25.png&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;출처:&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #9d9d9d;&quot; href=&quot;https://support.google.com/adsense/answer/1348725?hl=ko&amp;amp;sjid=16486267046165910621-AP&quot;&gt;https://support.google.com/adsense/answer/1348725?hl=ko&amp;amp;sjid=16486267046165910621-AP&lt;/a&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-29 오전 9.47.27.png&quot; data-origin-width=&quot;1461&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UN8rV/btslKEoOjtt/f2hCZMwcioxo333kjRSLKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UN8rV/btslKEoOjtt/f2hCZMwcioxo333kjRSLKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UN8rV/btslKEoOjtt/f2hCZMwcioxo333kjRSLKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUN8rV%2FbtslKEoOjtt%2Ff2hCZMwcioxo333kjRSLKk%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;1461&quot; height=&quot;297&quot; data-filename=&quot;스크린샷 2023-06-29 오전 9.47.27.png&quot; data-origin-width=&quot;1461&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;이건&amp;nbsp;뭐...&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;/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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-02 오전 10.24.18.png&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hnpgw/btsl1U56pGq/nU1tzhjS1u6apddkZsdRCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hnpgw/btsl1U56pGq/nU1tzhjS1u6apddkZsdRCk/img.png&quot; data-alt=&quot;자꾸 공지 은근슬쩍 추가함...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hnpgw/btsl1U56pGq/nU1tzhjS1u6apddkZsdRCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHnpgw%2Fbtsl1U56pGq%2FnU1tzhjS1u6apddkZsdRCk%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;1758&quot; height=&quot;206&quot; data-filename=&quot;스크린샷 2023-07-02 오전 10.24.18.png&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;206&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제로 겪은 피해가 있는가?&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;nbsp;&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;생각난 김에 난 어떤가 싶어서 봤더니, 광고가 시작된 어제를 기점으로 아주 그냥 개박살이 났습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중인 블로그 중 하나의 자료입니다. 보통 자고 일어나 아침에 보면 조회수가 4천 정도는 되는데 어제는 광고가 송출되기 전까지 시간이 있었으나 엄청 깎인 편이었고(아마 광고가 시작된 고난 후겠죠?), 오늘은 순수하게 광고가 시작되고난 이후의 페이지 뷰입니다.&amp;nbsp;&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;'처음에는 이놈들 돈 엄청 빼가겠구나, 적게는 20%, 많게는 30% 정도는 영향을 받겠지? 그럼 몇십만 원이야... 어휴...'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정도까지는 생각했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yjGSE/btslJGVgUuu/4nBaxL2anImYDlkdg2lnT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yjGSE/btslJGVgUuu/4nBaxL2anImYDlkdg2lnT0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1616&quot; data-origin-height=&quot;3014&quot; data-filename=&quot;out 5.png&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yjGSE/btslJGVgUuu/4nBaxL2anImYDlkdg2lnT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyjGSE%2FbtslJGVgUuu%2F4nBaxL2anImYDlkdg2lnT0%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;1616&quot; height=&quot;3014&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4qzDC/btslJ2Q8Oow/Uhz9W41vJuoPMeoKvxLl71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4qzDC/btslJ2Q8Oow/Uhz9W41vJuoPMeoKvxLl71/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1616&quot; data-origin-height=&quot;3014&quot; data-filename=&quot;out 6.png&quot; data-widthpercent=&quot;50&quot; style=&quot;width: 49.4186%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4qzDC/btslJ2Q8Oow/Uhz9W41vJuoPMeoKvxLl71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4qzDC%2FbtslJ2Q8Oow%2FUhz9W41vJuoPMeoKvxLl71%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;1616&quot; height=&quot;3014&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;페이지뷰 실환가...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데&amp;nbsp;거의&amp;nbsp;90%가&amp;nbsp;깎였네요???&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 수치면 100만원씩 들어오던 수익이 10만원으로, 200만원씩 들어오던 수익이 20만원으로 줄어들게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;월급을 받던 사람에게 기초수급 금액의 반값도 안되는 돈을 쥐어주면서 살라고 하면 살수 있을까요...?&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폰으로 애드센스를 확인한 김에 폰으로 블로그도 한번 들어와 봤는데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본문이&amp;nbsp;안&amp;nbsp;보이네요.&amp;nbsp;더욱&amp;nbsp;심각해졌습니다...&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결책은?&lt;/h2&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 같은 경우도 계속 무료로 운영하기엔 힘들 거 같은데 한 달에 8,000원에서 20,000원 정도가 적당하지 않을까? 라는 생각은 이전부터 했었고, 이번에 수익 때간다고 했을때 한달에 크게 잡아 8만~20만 원까지도 수익을 때 가더라도 그래도 티스토리만의 장점이 꽤 있다 보니 어느 정도 넘어갈까 생각을 하고 있었습니다만...&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플렛폼 홀더쯤 된다면 유튜브나 다른 여러곳처럼 분명 정상적인 좋은 방법이 있었을것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금처럼 광고를 뽑아내는 코드를 중복으로 2개 넣지 않아도 되는 깔끔한 방법이...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 그냥 구글같은 대형사를 상대하기 귀찮아서 임시방편으로 일을 처리하다보니 이렇게 됐다고밖에 보이지 않습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;04. 카카오 스럽네.png&quot; data-origin-width=&quot;2235&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uu2n8/btslKd57ooY/c85K3twLsXWYY4DfcRP8K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uu2n8/btslKd57ooY/c85K3twLsXWYY4DfcRP8K1/img.png&quot; data-alt=&quot;정말 카카오스럽다 (출처: 카카오)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uu2n8/btslKd57ooY/c85K3twLsXWYY4DfcRP8K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUu2n8%2FbtslKd57ooY%2Fc85K3twLsXWYY4DfcRP8K1%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;2235&quot; height=&quot;618&quot; data-filename=&quot;04. 카카오 스럽네.png&quot; data-origin-width=&quot;2235&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;정말 카카오스럽다 (출처: 카카오)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;05. 도전이 두렵다면 카카오를 떠날때이다.png&quot; data-origin-width=&quot;2199&quot; data-origin-height=&quot;1323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfZ8O2/btslMbsMlbA/SxEnkMkRheRk98iAcniLfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfZ8O2/btslMbsMlbA/SxEnkMkRheRk98iAcniLfK/img.png&quot; data-alt=&quot;가보지 않은길을 가는건 괜찮은데, 남들이 가지 않는길은 가지말자. (출처: 카카오)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfZ8O2/btslMbsMlbA/SxEnkMkRheRk98iAcniLfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfZ8O2%2FbtslMbsMlbA%2FSxEnkMkRheRk98iAcniLfK%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;2199&quot; height=&quot;1323&quot; data-filename=&quot;05. 도전이 두렵다면 카카오를 떠날때이다.png&quot; data-origin-width=&quot;2199&quot; data-origin-height=&quot;1323&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;nbsp;&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;/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;이미 일방문객 3만 이상의 몇몇 분들은 워드프레스로 이전을 시작하고 있던데...&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 떠나야하나 고민이 많아집니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;※ 이 블로그는 지금까지 주2~3회정도의 포스팅을 목표로 헀지만, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;티스토리의 이러한 운영 덕분에 앞으로는 비정기적으로 생각날때마다 글을 작성할 예정입니다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>블로그 관리 (Blog Management)/Tistory Blog</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/286</guid>
      <comments>https://bicute.tistory.com/286#entry286comment</comments>
      <pubDate>Thu, 29 Jun 2023 08:00:24 +0900</pubDate>
    </item>
    <item>
      <title>Asustor NAS에서 Vue.js 앱 호스팅: 서버 측 라우팅 설정하는 방법</title>
      <link>https://bicute.tistory.com/282</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ASUSTOR.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8VT6D/btsjRiAJdhs/lOb4op4xbssWhZa2k3Yqkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8VT6D/btsjRiAJdhs/lOb4op4xbssWhZa2k3Yqkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8VT6D/btsjRiAJdhs/lOb4op4xbssWhZa2k3Yqkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8VT6D%2FbtsjRiAJdhs%2FlOb4op4xbssWhZa2k3Yqkk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;ASUSTOR.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;Asustor NAS를 웹 서버로 사용하고 있다면, Vue.js 앱을 호스팅하여 사용자에게 제공할 수 있습니다.&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;size16&quot;&gt;일반적으로 웹 서버는 요청된 경로에 해당하는 파일이나 디렉토리를 반환하는데, Vue.js 앱의 클라이언트 측 라우팅과 웹 서버의 동작이 일치하지 않아서 문제가 발생할 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들면, 메인 페이지를 거치지 않고 app.myasustor.com/switch와 같은 하위 경로로 직접 접근하는 경우 웹 서버는 해당 경로를 찾지 못하고 &quot;페이지를 찾을 수 없음&quot;과 같은 오류를 반환합니다.&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;이 문제를 해결하기 위해서는 서버 측에서도 라우팅 설정을 추가하여 모든 경로를 Vue.js 앱으로 리다이렉트해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 클라이언트 측에서 라우팅을 처리하면서도&amp;nbsp;서버&amp;nbsp;측에서도&amp;nbsp;올바른&amp;nbsp;파일을&amp;nbsp;반환할&amp;nbsp;수&amp;nbsp;있습니다.&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;Asustor NAS에서 Vue.js 앱을 호스팅하는 경우,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Apache 웹 서버를 사용하므로 .htaccess 파일을 통해 라우팅 설정을 조정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.htaccess 파일은 Apache 웹 서버에서 디렉토리별로 웹 사이트의 설정을 수정할 수 있는 파일입니다.&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;이 글은 Asustor NAS에서 Vue.js 앱을 호스팅하면서 서버 측 라우팅 설정을 추가하는 방법에 대한 글입니다&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;Asustor NAS에서 서버 측 라우팅 설정을 하려면 다음 단계를 따르면 됩니다:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; Asustor NAS에 접속합니다.&lt;br /&gt;&lt;b&gt;2.&lt;/b&gt; 프로젝트의 루트 디렉토리에 .htaccess 파일을 생성하거나 이미 존재한다면 엽니다.&lt;br /&gt;&lt;b&gt;3.&lt;/b&gt; .htaccess 파일에 아래의 코드를 추가합니다:&lt;/p&gt;
&lt;pre id=&quot;code_1685006658897&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;IfModule mod_rewrite.c&amp;gt;
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
&amp;lt;/IfModule&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;위의 설정은 Vue.js 앱의 라우팅을 처리하기 위한 표준적인 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이 설정은 모든 요청을 index.html로 리다이렉트하여 Vue Router로 처리하도록 지시합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이렇게 설정하면 모든 경로를 Vue.js 앱에서 정상적으로 라우팅할 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4.&lt;/b&gt; .htaccess 파일을 저장하고 종료합니다.&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;위의 단계를 완료하면 Asustor NAS에서 Vue.js 앱의 서버 측 라우팅 설정이 완료됩니다. 이제 메인 페이지 이후에도 /switch와 같은 하위 경로로 직접 접근할 수 있습니다. 이 설정을 통해 사용자들은 메인 페이지를 거치지 않고도 원하는 경로로 직접 이동할 수 있습니다.&lt;/p&gt;</description>
      <category>기술 팁 &amp;amp; 가이드 (Tech Tips &amp;amp; Guides)/Asustor ＆NAS</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/282</guid>
      <comments>https://bicute.tistory.com/282#entry282comment</comments>
      <pubDate>Mon, 19 Jun 2023 08:00:33 +0900</pubDate>
    </item>
    <item>
      <title>자동 커밋 메시지 생성을 위한 aicommits</title>
      <link>https://bicute.tistory.com/284</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Development Tools.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7TSdL/btsjRinakZ5/s9CKT0vlwaEGzXvWOrL4Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7TSdL/btsjRinakZ5/s9CKT0vlwaEGzXvWOrL4Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7TSdL/btsjRinakZ5/s9CKT0vlwaEGzXvWOrL4Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7TSdL%2FbtsjRinakZ5%2Fs9CKT0vlwaEGzXvWOrL4Zk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;Development Tools.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 commit 메시지를 뭘 적어야할지 망설이는 그대들을 위한 Open AI 사용법.&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;aicommits&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Nutlope/aicommits&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;aicommits&lt;/a&gt;는 AI로 git 커밋 메시지를 작성하는 CLI 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 방법은 공식 페이지를 통해 그대로 따라만 해도 되지만, 조금 더 간단히 정리해 보았습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;필요한 것&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;① &lt;b&gt;OpenAI&lt;/b&gt;의 API keys를 사용하기때문에 공식 페이지에서 API Keys를 발급 받을 필요가 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://platform.openai.com/account/api-keys&quot;&gt;API 키 발급은 이곳에서 &amp;gt;&lt;/a&gt;&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;② 이전에는 무료로 사용 가능했지만, 2023.04.01 이후라면 지불 방법에 대한 설정이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://platform.openai.com/account/billing/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Billing 페이지&lt;/a&gt;에서 신용카드를 등록해서 결제가 가능하도록 할 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;※ 저의 경험으로 판단해보자면 AI를 이용한 commit 1회당 약 $0.005048 정도 사용되는것 같습니다.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) &quot;aicommits&quot; 패키지를 설치해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Node.js는 기본적으로 설치되어있다고 가정)&lt;/p&gt;
&lt;pre id=&quot;code_1686655642227&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g aicommits&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;Mac의 경우 설치가 안된다면 앞에 sudo를 붙여주세요&lt;/p&gt;
&lt;pre id=&quot;code_1686655658616&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo npm install -g aicommits&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;(2) 다음으로, OpenAI에서 발급한 API 키를 사용하여 &quot;aicommits&quot;를 설정해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 다음 명령어를 실행하여 API 키를 설정하세요&lt;/p&gt;
&lt;pre id=&quot;code_1686655734528&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aicommits config set OPENAI_KEY=********************&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어에서 ******************** 부분에 발급받은 API 키를 입력해야 합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) 이제 자동 커밋을 위한 별칭(alias)을 설정해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 다음 명령어를 실행하세요&lt;/p&gt;
&lt;pre id=&quot;code_1686655784243&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git config --global alias.ac '!git add -A &amp;amp;&amp;amp; aicommits -a'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어는 git ac라고 입력하면 자동으로 변경된 파일들을 스테이징하고, 커밋하고, 푸시해줍니다.&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;/p&gt;
&lt;pre id=&quot;code_1686655812444&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git ac&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-13 오후 8.08.55.png&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNo9p7/btsjPHHtCxF/bgs8Kp8gFo8Ka9hdxfyi71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNo9p7/btsjPHHtCxF/bgs8Kp8gFo8Ka9hdxfyi71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNo9p7/btsjPHHtCxF/bgs8Kp8gFo8Ka9hdxfyi71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNo9p7%2FbtsjPHHtCxF%2Fbgs8Kp8gFo8Ka9hdxfyi71%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;2958&quot; height=&quot;483&quot; data-filename=&quot;스크린샷 2023-06-13 오후 8.08.55.png&quot; data-origin-width=&quot;2958&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 작업한 내용을 기반으로 커밋 메시지를 제안해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-13 오후 8.09.08.png&quot; data-origin-width=&quot;2929&quot; data-origin-height=&quot;505&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QyAlX/btsjS5ABHiF/3nAd5Mw9cTTYKYkh1la9z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QyAlX/btsjS5ABHiF/3nAd5Mw9cTTYKYkh1la9z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QyAlX/btsjS5ABHiF/3nAd5Mw9cTTYKYkh1la9z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQyAlX%2FbtsjS5ABHiF%2F3nAd5Mw9cTTYKYkh1la9z1%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;2929&quot; height=&quot;505&quot; data-filename=&quot;스크린샷 2023-06-13 오후 8.09.08.png&quot; data-origin-width=&quot;2929&quot; data-origin-height=&quot;505&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Yes를 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 &quot;aicommits&quot; 패키지가 실행되어 커밋 메시지를 자동으로 생성하고, 변경된 내용을 스테이징하고 커밋하고, 푸시까지 완료해줍니다.&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;No를 선택하게 되면 새로운 메시지를 제안받을 수도 있습니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;aicommits&quot; 패키지를 사용하면 더욱 효율적으로 Git 작업을 처리할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의사항&lt;/h2&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 개인용 작업에서 사용중인데 매우 만족중입니다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Git</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/284</guid>
      <comments>https://bicute.tistory.com/284#entry284comment</comments>
      <pubDate>Thu, 15 Jun 2023 08:00:14 +0900</pubDate>
    </item>
    <item>
      <title>가볍게 훑어보는 Vue 3</title>
      <link>https://bicute.tistory.com/240</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Vue.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WWkAa/btsjQhB29Ay/NQvjAgpJ4iO96317jvVLX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WWkAa/btsjQhB29Ay/NQvjAgpJ4iO96317jvVLX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WWkAa/btsjQhB29Ay/NQvjAgpJ4iO96317jvVLX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWWkAa%2FbtsjQhB29Ay%2FNQvjAgpJ4iO96317jvVLX0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;Vue.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/274&quot;&gt;#1. Vue 소개&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; Vue 3란 무엇인가?&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Vue&amp;nbsp;3의&amp;nbsp;특징과&amp;nbsp;장점&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/275&quot;&gt;#2. Vue 3 설치 및 설정&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷ &lt;a href=&quot;https://bicute.tistory.com/177&quot;&gt;프로젝트와 파일의 구조와 형식&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/276&quot;&gt;#3. Vue 3 기본 문법&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; Template 문법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/179&quot;&gt;컴포넌트 단위로 스타일 적용하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;디렉티브(Directive)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/181&quot;&gt;데이터 바인딩하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/182&quot;&gt;반복문(v-for) 사용하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/183&quot;&gt;이벤트 핸들링(v-on)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/184&quot;&gt;조건식 v-if, v-show&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;컴포넌트(Component)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/178&quot;&gt;새로운 컴포넌트를 생성하고 추가하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/185&quot;&gt;데이터를 전달할 때는 props&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/225&quot;&gt;사용자 지정 이벤트(Custom Event)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/188&quot;&gt;데이터를 전달하는 또 다른 방법 Slot&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;라우터(Router)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/180&quot;&gt;페이지 전환하기 (라우터 설치부터 사용까지)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/187&quot;&gt;게시물마다 번호를 달아주자 (라우터 파라미터)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;상태&amp;nbsp;관리(State&amp;nbsp;Management)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/195&quot;&gt;Pinia (Vue 상태관리 라이브러리)&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/277&quot;&gt;#4. Vue 3 고급 문법&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Composition&amp;nbsp;API&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷ &lt;a href=&quot;https://bicute.tistory.com/192&quot;&gt;Composition API 사용방법&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Teleport&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Suspense&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Reactive와&amp;nbsp;Ref&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;ToRefs&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;Watch&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷ &lt;a href=&quot;https://bicute.tistory.com/190&quot;&gt;computed, methods, watch 정리&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/191&quot;&gt;라이프사이클 훅(Lifecycle hooks)&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/278&quot;&gt;#5. Vue 3 성능 최적화&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;렌더링&amp;nbsp;최적화&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;로딩&amp;nbsp;속도&amp;nbsp;최적화&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;메모리&amp;nbsp;최적화&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/279&quot;&gt;#6. Vue 3 실전 예제&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;bull; 간단한 CRUD 앱 만들기&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;인증&amp;nbsp;기능&amp;nbsp;추가하기&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;실시간&amp;nbsp;채팅&amp;nbsp;앱&amp;nbsp;만들기&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/280&quot;&gt;#7. Vue 3 스타일 가이드&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/200&quot;&gt;조건에 따라 클래스 적용하기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ▷&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://bicute.tistory.com/236&quot;&gt;작고 빠른 이미터 라이브러리 Mitt&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/240</guid>
      <comments>https://bicute.tistory.com/240#entry240comment</comments>
      <pubDate>Fri, 9 Jun 2023 08:00:00 +0900</pubDate>
    </item>
    <item>
      <title>#7. Vue 3 스타일 가이드</title>
      <link>https://bicute.tistory.com/280</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;White Template (3).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ubXt3/btshxGxRF5e/KWKJ71x56FNQshb8wkfxFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ubXt3/btshxGxRF5e/KWKJ71x56FNQshb8wkfxFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ubXt3/btshxGxRF5e/KWKJ71x56FNQshb8wkfxFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FubXt3%2FbtshxGxRF5e%2FKWKJ71x56FNQshb8wkfxFK%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;2560&quot; height=&quot;1440&quot; data-filename=&quot;White Template (3).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 스타일 가이드란?&lt;/h3&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타일 가이드를 사용하면 다음과 같은 장점을 얻을 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일관성 유지: 스타일 가이드는 모든 개발자가 동일한 코드 스타일을 따르도록 강제합니다. 이렇게 하면 코드가 일관성 있게 유지되므로 읽기 쉬워집니다.&lt;/li&gt;
&lt;li&gt;버그 감소: 일관성 있는 코드 스타일을 따르면 실수를 줄일 수 있습니다. 예를 들어, 잘못된 인덴트, 괄호 누락 등의 문제가 발생할 가능성이 줄어듭니다.&lt;/li&gt;
&lt;li&gt;코드 유지보수성 향상: 스타일 가이드는 코드를 더 읽기 쉽고 이해하기 쉽도록 만듭니다. 따라서 코드의 유지보수성이 향상되고 변경이 쉬워집니다.&lt;/li&gt;
&lt;li&gt;코드 리뷰 용이: 스타일 가이드는 코드 리뷰를 용이하게 만듭니다. 코드가 일관성 있게 작성되면 리뷰어가 코드를 더 쉽게 이해할 수 있으며, 코드 변경에 대한 의견을 쉽게 제시할 수 있습니다.&lt;/li&gt;
&lt;li&gt;개발 시간 절약: 스타일 가이드는 코드 작성에 대한 규칙을 제공하기 때문에 개발자는 이를 준수하기만 하면 됩니다. 이렇게 하면 코드 작성 시간을 줄일 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 스타일 가이드를 사용하면 개발자들 간에 일관성 있게 코드를 작성할 수 있고, 코드 유지보수성을 높일 수 있으며, 개발 시간을 절약할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Vue의 스타일 가이드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js 에서 코드 스타일 가이드는 공식적으로 제공되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 가이드는 개발자들이 일관된 스타일로 코드를 작성할 수 있도록 돕는 것이 목적입니다.&lt;br /&gt;&lt;br /&gt;여기에는&amp;nbsp;주요한&amp;nbsp;스타일&amp;nbsp;가이드&amp;nbsp;규칙이&amp;nbsp;포함되어&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&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;1. 컴포넌트&amp;nbsp;이름은&amp;nbsp;항상&amp;nbsp;여러&amp;nbsp;단어인&amp;nbsp;kebab-case를&amp;nbsp;사용해야합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676730920724&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Bad
Vue.component('mycomponent', {
  // ...
})

// Good
Vue.component('my-component', {
  // ...
})&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 컴포넌트&amp;nbsp;옵션은&amp;nbsp;가능한&amp;nbsp;한&amp;nbsp;알파벳&amp;nbsp;순서대로&amp;nbsp;정렬되어야&amp;nbsp;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676730941189&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Bad
export default {
  name: 'HelloWorld',
  components: {
    ChildComponent,
    AnotherChildComponent,
  },
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  methods: {
    handleClick() {
      console.log('Button clicked!')
    },
    handleInputChange() {
      console.log('Input changed!')
    },
  },
}

// Good
export default {
  name: 'HelloWorld',
  components: {
    AnotherChildComponent,
    ChildComponent,
  },
  data() {
    return {
      message: 'Hello, World!'
    }
  },
  methods: {
    handleClick() {
      console.log('Button clicked!')
    },
    handleInputChange() {
      console.log('Input changed!')
    },
  },
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Prop&amp;nbsp;이름은&amp;nbsp;항상&amp;nbsp;camelCase로&amp;nbsp;작성되어야&amp;nbsp;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676730983750&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Bad
props: {
  'first-name': String,
}

// Good
props: {
  firstName: String,
}&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 컴포넌트의&amp;nbsp;인스턴스를&amp;nbsp;생성하기&amp;nbsp;위해&amp;nbsp;new&amp;nbsp;키워드를&amp;nbsp;사용하지&amp;nbsp;마세요.&lt;/p&gt;
&lt;pre id=&quot;code_1676731012923&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Bad
const vm = new Vue({
  el: '#app',
  // ...
})

// Good
const vm = Vue.createApp({
  // ...
}).mount('#app')&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 데이터&amp;nbsp;속성은&amp;nbsp;가능한&amp;nbsp;한&amp;nbsp;초기값을&amp;nbsp;제공해야합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676731043060&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Bad
data() {
  return {
    message: undefined
  }
}

// Good
data() {
  return {
    message: '',
  }
}&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;이외에도&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;/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;자세한 내용은 아래 의 Vue.js 공식 홈페이지에서 참조할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 홈페이지 스타일 가이드: &lt;a href=&quot;https://vuejs.org/style-guide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://vuejs.org/style-guide/&lt;/a&gt;&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;※ 스타일 가이드는 어디까지나 권장일뿐, 반드시 따라야 할 필요는 없습니다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/280</guid>
      <comments>https://bicute.tistory.com/280#entry280comment</comments>
      <pubDate>Wed, 7 Jun 2023 08:00:27 +0900</pubDate>
    </item>
    <item>
      <title>Apple WWDC23 요약</title>
      <link>https://bicute.tistory.com/283</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Apple-WWDC23-event-announcement-hero_big.jpg.large_2x.jpg&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;1102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n69pE/btsiNcPXOlk/wf60SDYs0jEgT6G60Er4pk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n69pE/btsiNcPXOlk/wf60SDYs0jEgT6G60Er4pk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n69pE/btsiNcPXOlk/wf60SDYs0jEgT6G60Er4pk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn69pE%2FbtsiNcPXOlk%2Fwf60SDYs0jEgT6G60Er4pk%2Fimg.jpg&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;1960&quot; height=&quot;1102&quot; data-filename=&quot;Apple-WWDC23-event-announcement-hero_big.jpg.large_2x.jpg&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;1102&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Apple WWDC(WorldWide Developers Conference)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apple이 매년 6월경 캘리포니아에서 개최하는 대규모 개발자 회의.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;WWDC23 - Code new worlds.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멋진 코딩 신세계.&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;15형 MacBook Air with M2&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 10.21.12.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dj8XWe/btsiSRpTgBM/X2MGCdbPMk7JeI5slZUDBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dj8XWe/btsiSRpTgBM/X2MGCdbPMk7JeI5slZUDBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dj8XWe/btsiSRpTgBM/X2MGCdbPMk7JeI5slZUDBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdj8XWe%2FbtsiSRpTgBM%2FX2MGCdbPMk7JeI5slZUDBK%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 10.21.12.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;15.3&quot; 리퀴드 레티나 디스플레이 (최대 밝기 500 nits)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M2 프로세서&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;두께: 11.5mm / 무게: 1.5kg&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;18시간의 배터리 타임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6개의 스피커 사운드 시스템&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팬리스(무소음) 디자인&lt;br /&gt;8-Core CPU / 10-core GPU&lt;br /&gt;1080p 카메라&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격: $1,299 부터 시작 / 교육용은 $1,199 부터 시작&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6월 13일 화요일부터 고객, Apple Store 위치 및 Apple 공인 대리점에 도착하기 시작&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Mac Studio / Mac Pro Apple Silicon&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LTLAJ/btsiNa5GHpv/DTQV4e6cQNBJqcHhKGP250/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LTLAJ/btsiNa5GHpv/DTQV4e6cQNBJqcHhKGP250/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.13.41.png&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LTLAJ/btsiNa5GHpv/DTQV4e6cQNBJqcHhKGP250/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLTLAJ%2FbtsiNa5GHpv%2FDTQV4e6cQNBJqcHhKGP250%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;3840&quot; height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUi5Gb/btsiOkz0X1c/yVAqtWo8V23fdpzQ2LenuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUi5Gb/btsiOkz0X1c/yVAqtWo8V23fdpzQ2LenuK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.16.18.png&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUi5Gb/btsiOkz0X1c/yVAqtWo8V23fdpzQ2LenuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUi5Gb%2FbtsiOkz0X1c%2FyVAqtWo8V23fdpzQ2LenuK%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;3840&quot; height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Mac Studio&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고대역폭 HDMI를 탑재 (최대 8K 해상도와 240Hz 프레임 속도를 지원)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;M2 Ultra를 통해 최대 6개의 Pro Display XDR을 지원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wi-Fi 6E / Bluetooth 5.3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전면: USB-C 포트 2개와 SD 카드 슬롯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒷면: Thunderbolt 4 포트 4개, 10Gb 이더넷 포트, 향상된 HDMI 포트 및 USB-A 포트 2개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;M2 ULTRA Spec&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.12.17.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HsvpP/btsiQk0lYNL/hykCH3SSTEW1wDtltOznPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HsvpP/btsiQk0lYNL/hykCH3SSTEW1wDtltOznPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HsvpP/btsiQk0lYNL/hykCH3SSTEW1wDtltOznPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHsvpP%2FbtsiQk0lYNL%2FhykCH3SSTEW1wDtltOznPK%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.12.17.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crSpVW/btsiQIfLS53/Cby5brZNHFxZmSkofBIvwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crSpVW/btsiQIfLS53/Cby5brZNHFxZmSkofBIvwk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.16.46.png&quot; data-widthpercent=&quot;50&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crSpVW/btsiQIfLS53/Cby5brZNHFxZmSkofBIvwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrSpVW%2FbtsiQIfLS53%2FCby5brZNHFxZmSkofBIvwk%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;3840&quot; height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ng0ch/btsiQ5IDNYA/50qKaovfJggn1hAFPnRdrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ng0ch/btsiQ5IDNYA/50qKaovfJggn1hAFPnRdrK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.16.54.png&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ng0ch/btsiQ5IDNYA/50qKaovfJggn1hAFPnRdrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fng0ch%2FbtsiQ5IDNYA%2F50qKaovfJggn1hAFPnRdrK%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;3840&quot; height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac Studio 가격:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$1,999 부터 시작 / 교육용: $1,799 부터 시작&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;Mac Pro 가격:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac Pro(타워 인클로저): $6,999 부터 시작 / 교육용: $6,599 부터 시작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mac Pro(랙 인클로저): $7,499 부터 시작 / 교육용: $6,999 부터 시작&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;br /&gt;6월 13일 화요일부터 고객, Apple Store 위치 및 Apple 공인 대리점에 도착하기 시작&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;iOS17&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.34.54.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lzxtZ/btsiSRciNUP/aAi1JuD7xOSYLyCg9XcqQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lzxtZ/btsiSRciNUP/aAi1JuD7xOSYLyCg9XcqQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lzxtZ/btsiSRciNUP/aAi1JuD7xOSYLyCg9XcqQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlzxtZ%2FbtsiSRciNUP%2FaAi1JuD7xOSYLyCg9XcqQK%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.34.54.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FaceTime은 오디오 및 비디오 메시지, 반응을 추가하고 Apple TV로 확장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 모습과 메시지에 대한 대규모 업데이트 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AirDrop 및 NameDrop으로 더 쉽게 공유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 수정 및 받아쓰기 개선으로 더 지능적인 입력 제공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StandBy는 iPhone이 충전되는 동안 한 눈에 알아볼 수 있는 정보를 표시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ @&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;iPadOS&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.43.37.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cquWKZ/btsiOfeBRBj/T8zEPXrUHtytaoGdMiUSk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cquWKZ/btsiOfeBRBj/T8zEPXrUHtytaoGdMiUSk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cquWKZ/btsiOfeBRBj/T8zEPXrUHtytaoGdMiUSk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcquWKZ%2FbtsiOfeBRBj%2FT8zEPXrUHtytaoGdMiUSk1%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.43.37.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&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;더욱 쉬워진 PDF 작업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;향상된 커뮤니케이션 도구&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;건강 앱이 iPad로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ @&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MacOS&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.57.08.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfJSzG/btsiFN4aGCs/mXzmAoJDF57y4c5r1bRPy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfJSzG/btsiFN4aGCs/mXzmAoJDF57y4c5r1bRPy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfJSzG/btsiFN4aGCs/mXzmAoJDF57y4c5r1bRPy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfJSzG%2FbtsiFN4aGCs%2FmXzmAoJDF57y4c5r1bRPy0%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 2.57.08.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&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;놀라운 새 화면 보호기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하이브리드 및 원격 Pro 워크플로 향상&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ @&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;watchOS&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 10.23.18.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eggq0d/btsiQ5vbuI9/pngcWGpsZEdRoK732RqfPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eggq0d/btsiQ5vbuI9/pngcWGpsZEdRoK732RqfPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eggq0d/btsiQ5vbuI9/pngcWGpsZEdRoK732RqfPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feggq0d%2FbtsiQ5vbuI9%2FpngcWGpsZEdRoK732RqfPk%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 10.23.18.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게&amp;nbsp;추가된&amp;nbsp;시계&amp;nbsp;페이스&lt;br /&gt;사이클링&lt;br /&gt;하이킹&lt;br /&gt;정신&amp;nbsp;건강&lt;br /&gt;시력&amp;nbsp;건강&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+@&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Apple Vision Pro&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-06 오전 4.02.19.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beCStQ/btsiQ59Im4s/0NYeSrw8crKIoKXKKctuC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beCStQ/btsiQ59Im4s/0NYeSrw8crKIoKXKKctuC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beCStQ/btsiQ59Im4s/0NYeSrw8crKIoKXKKctuC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeCStQ%2FbtsiQ59Im4s%2F0NYeSrw8crKIoKXKKctuC0%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;스크린샷 2023-06-06 오전 4.02.19.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Apple-WWCD23-Vision-Pro-with-battery-230605_big.jpg.large_2x.jpg&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;1102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj2Ixb/btsiOfr6kII/mJT0kusmUyZvZ0RhkCPeZk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj2Ixb/btsiOfr6kII/mJT0kusmUyZvZ0RhkCPeZk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj2Ixb/btsiOfr6kII/mJT0kusmUyZvZ0RhkCPeZk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj2Ixb%2FbtsiOfr6kII%2FmJT0kusmUyZvZ0RhkCPeZk%2Fimg.jpg&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;1960&quot; height=&quot;1102&quot; data-filename=&quot;Apple-WWCD23-Vision-Pro-with-battery-230605_big.jpg.large_2x.jpg&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;1102&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;몰입형 환경&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;/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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>애플 제품 (Apple Products)</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/283</guid>
      <comments>https://bicute.tistory.com/283#entry283comment</comments>
      <pubDate>Tue, 6 Jun 2023 03:30:35 +0900</pubDate>
    </item>
    <item>
      <title>#6. Vue 3 실전 예제</title>
      <link>https://bicute.tistory.com/279</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;White Template (2).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Rrbv/btshyyZZ5tD/uf1WrkFimnJRB8PdHCUT5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Rrbv/btshyyZZ5tD/uf1WrkFimnJRB8PdHCUT5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Rrbv/btshyyZZ5tD/uf1WrkFimnJRB8PdHCUT5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Rrbv%2FbtshyyZZ5tD%2Fuf1WrkFimnJRB8PdHCUT5k%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;2560&quot; height=&quot;1440&quot; data-filename=&quot;White Template (2).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 간단한 CRUD 앱 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 CRUD는 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete)의 약자로 데이터베이스나 서버에서 데이터를 다룰 때 가장 많이 사용하는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 예제에서는 간단한 할 일 목록을 다루는 CRUD 기능을 구현해 볼 것입니다&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) 먼저 src/components 폴더 안에 TodoList.vue 컴포넌트를 만듭니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676724696183&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;h2&amp;gt;할 일 목록&amp;lt;/h2&amp;gt;
        &amp;lt;ul&amp;gt;
            &amp;lt;li v-for=&quot;(todo, index) in todos&quot; :key=&quot;index&quot;&amp;gt;
                {{ todo }}
                &amp;lt;button @click=&quot;deleteTodo(index)&quot;&amp;gt;삭제&amp;lt;/button&amp;gt;
                &amp;lt;button @click=&quot;editTodo(index)&quot;&amp;gt;수정&amp;lt;/button&amp;gt;
            &amp;lt;/li&amp;gt;
        &amp;lt;/ul&amp;gt;
        &amp;lt;div&amp;gt;
            &amp;lt;input type=&quot;text&quot; v-model=&quot;newTodo&quot; /&amp;gt;
            &amp;lt;button v-if=&quot;!editing&quot; @click=&quot;addTodo&quot;&amp;gt;추가&amp;lt;/button&amp;gt;
            &amp;lt;button v-if=&quot;editing&quot; @click=&quot;cancelEdit&quot;&amp;gt;취소&amp;lt;/button&amp;gt;
            &amp;lt;button v-if=&quot;editing&quot; @click=&quot;updateTodo&quot;&amp;gt;수정&amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    data() {
        return {
            todos: [&quot;Vue.js 배우기&quot;, &quot;할 일 목록 만들기&quot;, &quot;CRUD 기능 추가하기&quot;],
            newTodo: &quot;&quot;,
            editing: false,
            editedIndex: null,
        };
    },
    methods: {
        addTodo() {
            if (this.newTodo) {
                if (this.editing) {
                    this.updateTodo();
                } else {
                    this.todos.push(this.newTodo);
                    this.newTodo = &quot;&quot;;
                }
                this.editing = false;
                this.editedIndex = null;
            }
        },
        deleteTodo(index) {
            this.todos.splice(index, 1);
        },
        editTodo(index) {
            this.newTodo = this.todos[index];
            this.editing = true;
            this.editedIndex = index;
        },
        updateTodo() {
            if (this.newTodo &amp;amp;&amp;amp; this.editedIndex !== null) {
                this.todos.splice(this.editedIndex, 1, this.newTodo);
                this.newTodo = &quot;&quot;;
                this.editing = false;
                this.editedIndex = null;
            }
        },
        cancelEdit() {
            this.newTodo = &quot;&quot;;
            this.editing = false;
            this.editedIndex = null;
        },
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 컴포넌트는 할 일 목록을 표시하고, 새로운 할 일을 추가하거나 삭제하는 기능을 가지고 있습니다. data 속성에서 todos 배열에 기본 할 일 목록을 설정하고, newTodo 변수에 새로 추가할 할 일을 저장합니다. methods에서는 addTodo 함수를 통해 새로운 할 일을 todos 배열에 추가하고, deleteTodo 함수를 통해 선택한 할 일을 삭제합니다.&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;(2) 이제 src/views 폴더 안에 HomeView.vue 컴포넌트를 만듭니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676724744757&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;TodoList /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import TodoList from '@/components/TodoList.vue';

export default {
  name: 'HomeView',
  components: {
    TodoList,
  },
};
&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;이 컴포넌트는 TodoList.vue 컴포넌트를 불러와서 HomeView 컴포넌트 안에 표시합니다.&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;br /&gt;(3) 마지막으로 src/router/index.js 파일을 열고, 다음과 같이 코드를 수정합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676724838137&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
  ]
})

export default router&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 라우터 모듈을 초기화하고, 라우트를 정의합니다. / 경로에서 HomeView 컴포넌트를 렌더링하도록 설정합니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 인증 기능 추가하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서 인증(Authentication) 기능을 구현하기 위해서는 일반적으로 토큰 기반 인증 방식을 사용합니다. 이 방식은 사용자가 로그인하면 서버에서 토큰을 발급하고, 이후 요청에서는 발급된 토큰을 사용하여 사용자를 인증하는 방식입니다.&lt;br /&gt;&lt;br /&gt;이를 구현하기 위해서는 먼저 로그인 폼을 구현하고, 로그인 요청을 처리하는 API를 작성해야 합니다. 그리고 로그인 요청이 성공하면, 서버에서 발급한 토큰을 클라이언트에 저장하고, 이후 요청에서는 토큰을 포함하여 보내야 합니다. 또한, 토큰이 만료된 경우에는 새로운 토큰을 발급받아야 합니다.&lt;br /&gt;&lt;br /&gt;다음은 Vue.js에서 인증 기능을 구현하는 예제입니다.&lt;br /&gt;실제로 서버와 통신을 하는것이 아니기에 사용자 정보를 하드코딩하여 인증 기능을 구현하고, 사용자 정보가 배열에서 확인되면 로그인이 가능한 형식으로 작성되어있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676725487216&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h2&amp;gt;로그인&amp;lt;/h2&amp;gt;
    &amp;lt;form @submit.prevent=&quot;login&quot;&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;아이디&amp;lt;/label&amp;gt;
        &amp;lt;input type=&quot;text&quot; v-model=&quot;username&quot;&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;label&amp;gt;비밀번호&amp;lt;/label&amp;gt;
        &amp;lt;input type=&quot;password&quot; v-model=&quot;password&quot;&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;button type=&quot;submit&quot;&amp;gt;로그인&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
    &amp;lt;div v-if=&quot;error&quot;&amp;gt;{{ error }}&amp;lt;/div&amp;gt;
    &amp;lt;div v-else-if=&quot;token&quot;&amp;gt;토큰: {{ token }}&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      username: '',
      password: '',
      token: null,
      error: null,
    };
  },
  methods: {
    async login() {
      try {
        // 사용자 정보
        const users = [
          { id: 1, username: 'admin', password: 'admin1234' },
          { id: 2, username: 'user1', password: 'password1' },
          { id: 3, username: 'user2', password: 'password2' },
        ];

        // 사용자 정보 확인
        const user = users.find(u =&amp;gt; u.username === this.username &amp;amp;&amp;amp; u.password === this.password);
        if (user) {
          // 토큰 발급
          const token = '1234567890';
          this.token = token;
          this.error = null;
          // 토큰을 localStorage에 저장
          localStorage.setItem('token', token);
        } else {
          this.token = null;
          this.error = '아이디 또는 비밀번호가 일치하지 않습니다.';
          localStorage.removeItem('token');
        }
      } catch (error) {
        this.error = error.message;
      }
    },
  },
  mounted() {
    // 페이지가 로드될 때 localStorage에서 토큰을 확인
    const token = localStorage.getItem('token');
    if (token) {
      this.token = token;
    }
  },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 사용자 정보를 하드코딩하여 users 배열에 저장합니다. 로그인 요청이 들어오면, 배열에서 사용자 정보를 확인하고, 사용자 이름과 비밀번호가 일치하는 경우, 하드코딩된 토큰을 발급하고, 발급된 토큰을 클라이언트에 저장합니다. 이후 페이지가 로드될 때, 저장된 토큰을 확인하고, 토큰이 있을 경우 화면에 토큰을 출력합니다.&lt;br /&gt;&lt;br /&gt;실제 애플리케이션에서는 이 부분을 서버에서 처리해야 하며, 데이터베이스와 연동하여 실제 사용자 정보를 확인해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;token 또한 하드코딩이 아닌, this.token = data.token 처럼 서버에서 암호화되어 받아온 값을 지정해 줍니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 실시간 채팅 앱 만들기&lt;/h3&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가볍게 만드는 만큼 임시로 localStorage를 활용하여, 서버를 사용하지 않고 채팅을 구현하는식으로 작성해 보았습니다.&lt;br /&gt;&lt;br /&gt;다음은 localStorage를 활용하여 실시간 채팅 애플리케이션을 구현한 예제입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1676730121281&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div class=&quot;chat-container&quot;&amp;gt;
        &amp;lt;div class=&quot;chat&quot; ref=&quot;chat1&quot;&amp;gt;
            &amp;lt;div v-if=&quot;!username1&quot;&amp;gt;
                &amp;lt;h2&amp;gt;사용자1의 이름을 입력하세요&amp;lt;/h2&amp;gt;
                &amp;lt;input
                    type=&quot;text&quot;
                    v-model=&quot;tempUser1&quot;
                    v-on:keyup.enter=&quot;updateUser1&quot;
                    placeholder=&quot;이름 입력&quot;
                    :disabled=&quot;username1&quot; /&amp;gt;
                &amp;lt;button @click=&quot;updateUser1&quot; :disabled=&quot;username1&quot;&amp;gt;확인&amp;lt;/button&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div v-else&amp;gt;
                &amp;lt;h2&amp;gt;{{ username1 }}&amp;lt;/h2&amp;gt;
                &amp;lt;div v-for=&quot;(message, index) in messages&quot; :key=&quot;index&quot;&amp;gt;
                    &amp;lt;div
                        :class=&quot;{
                            'other-message': message.username !== username1,
                            'my-message': message.username === username1,
                        }&quot;&amp;gt;
                        &amp;lt;strong&amp;gt;{{ message.username }}:&amp;lt;/strong&amp;gt;
                        {{ message.text }}
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;form @submit.prevent=&quot;sendMessage(username1)&quot;&amp;gt;
                    &amp;lt;input
                        type=&quot;text&quot;
                        v-model=&quot;text1&quot;
                        placeholder=&quot;메시지를 입력하세요&quot; /&amp;gt;
                    &amp;lt;button type=&quot;submit&quot;&amp;gt;보내기&amp;lt;/button&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;chat&quot; ref=&quot;chat2&quot;&amp;gt;
            &amp;lt;div v-if=&quot;!username2&quot;&amp;gt;
                &amp;lt;h2&amp;gt;사용자2의 이름을 입력하세요&amp;lt;/h2&amp;gt;
                &amp;lt;input
                    type=&quot;text&quot;
                    v-model=&quot;tempUser2&quot;
                    v-on:keyup.enter=&quot;updateUser2&quot;
                    placeholder=&quot;이름 입력&quot;
                    :disabled=&quot;username2&quot; /&amp;gt;
                &amp;lt;button @click=&quot;updateUser2&quot; :disabled=&quot;username2&quot;&amp;gt;확인&amp;lt;/button&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div v-else&amp;gt;
                &amp;lt;h2&amp;gt;{{ username2 }}&amp;lt;/h2&amp;gt;
                &amp;lt;div v-for=&quot;(message, index) in messages&quot; :key=&quot;index&quot;&amp;gt;
                    &amp;lt;div
                        :class=&quot;{
                            'other-message': message.username !== username2,
                            'my-message': message.username === username2,
                        }&quot;&amp;gt;
                        &amp;lt;strong&amp;gt;{{ message.username }}:&amp;lt;/strong&amp;gt;
                        {{ message.text }}
                    &amp;lt;/div&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;form @submit.prevent=&quot;sendMessage(username2)&quot;&amp;gt;
                    &amp;lt;input
                        type=&quot;text&quot;
                        v-model=&quot;text2&quot;
                        placeholder=&quot;메시지를 입력하세요&quot; /&amp;gt;
                    &amp;lt;button type=&quot;submit&quot;&amp;gt;보내기&amp;lt;/button&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
    data() {
        return {
            username1: null,
            text1: &quot;&quot;,
            username2: null,
            text2: &quot;&quot;,
            messages: [],
        };
    },
    methods: {
        updateUser1() {
            this.username1 = this.tempUser1;
        },
        updateUser2() {
            this.username2 = this.tempUser2;
        },
        sendMessage(username) {
            const message = {
                username,
                text: username === this.username1 ? this.text1 : this.text2,
            };
            this.messages.push(message);
            localStorage.setItem(&quot;messages&quot;, JSON.stringify(this.messages));
            if (username === this.username1) {
                this.text1 = &quot;&quot;;
            } else {
                this.text2 = &quot;&quot;;
            }
        },
        handleStorage(e) {
            if (e.key === &quot;messages&quot;) {
                this.messages = JSON.parse(e.newValue) || [];
            }
        },
    },
    mounted() {
        window.addEventListener(&quot;storage&quot;, this.handleStorage);
        this.messages = JSON.parse(localStorage.getItem(&quot;messages&quot;)) || [];
    },
    unmounted() {
        window.removeEventListener(&quot;storage&quot;, this.handleStorage);
    },
};
&amp;lt;/script&amp;gt;
&amp;lt;style scoped&amp;gt;
.chat-container {
    display: flex;
    justify-content: space-between;
    width: 800px;
    margin: 0 auto;
}

.chat {
    width: 45%;
    height: 500px;
    border: 1px solid #ccc;
    padding: 10px;
    overflow-y: scroll;
}

.other-message {
    margin-bottom: 10px;
    padding: 10px;
    background-color: #eee;
}

.my-message {
    margin-bottom: 10px;
    padding: 10px;
    background-color: #e6f2ff;
    text-align: right;
}
&amp;lt;/style&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;HTML 템플릿에서는 채팅방을 나타내는 두 개의 div를 정의합니다. v-if 지시자를 사용하여 사용자 이름이 없는 경우 이름을 입력 받는 폼을 표시하고, 사용자 이름이 있는 경우 채팅을 표시합니다. 이름을 입력 받을 때는 v-on:keyup.enter 지시자를 사용하여 Enter 키를 누르면 updateUser1 또는 updateUser2 메서드가 호출됩니다. 사용자 이름을 업데이트하면 username1 또는 username2 데이터가 갱신됩니다.&lt;br /&gt;&lt;br /&gt;sendMessage 메서드는 사용자 이름을 매개변수로 받으며, 메시지를 messages 데이터 배열에 추가합니다. localStorage에 messages 데이터를 저장합니다. 사용자 이름이 username1이면 text1을, username2이면 text2를 사용하여 메시지를 가져옵니다. 마지막으로 사용자 이름이 username1이면 text1을, username2이면 text2를 비웁니다.&lt;br /&gt;&lt;br /&gt;handleStorage 메서드는 localStorage에서 messages 데이터를 가져와 messages 배열을 갱신합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 리스너를 등록하여 localStorage가 갱신될 때마다 handleStorage 메서드가 호출되도록 합니다.&lt;br /&gt;&lt;br /&gt;Vue.js 컴포넌트의 라이프사이클 훅을 사용하여 이벤트 리스너를 등록 및 해제합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마운트시 mounted()에서 localStorage에서 messages 데이터를 가져옵니다.&lt;br /&gt;&lt;br /&gt;CSS 스타일 시트는 채팅방의 레이아웃과 메시지 스타일을 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 메시지에 대해 other-message 또는 my-message 클래스를 추가하여 메시지 스타일을 구분합니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/279</guid>
      <comments>https://bicute.tistory.com/279#entry279comment</comments>
      <pubDate>Mon, 5 Jun 2023 08:00:57 +0900</pubDate>
    </item>
    <item>
      <title>#5. Vue 3 성능 최적화</title>
      <link>https://bicute.tistory.com/278</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;White Template (1).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ3Sux/btsht0XVnju/VGrJRtyZHeFQZZ8FYzCihk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ3Sux/btsht0XVnju/VGrJRtyZHeFQZZ8FYzCihk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ3Sux/btsht0XVnju/VGrJRtyZHeFQZZ8FYzCihk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ3Sux%2Fbtsht0XVnju%2FVGrJRtyZHeFQZZ8FYzCihk%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;2560&quot; height=&quot;1440&quot; data-filename=&quot;White Template (1).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 렌더링 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 렌더링을 최적화하는 몇 가지 방법은 다음과 같습니다:&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 가상 DOM 활용&lt;/b&gt;&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;Vue에서 가상 DOM을 활용하면 실제 DOM을 추상화하여 변경된 부분만 업데이트할 수 있습니다. 아래는 가상 DOM을 사용하여 성능을 개선하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676720640553&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&quot;item in items&quot; :key=&quot;item&quot;&amp;gt;{{ item }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
  &amp;lt;button @click=&quot;shuffle&quot;&amp;gt;Shuffle&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      items: [1, 2, 3, 4, 5]
    };
  },
  methods: {
    shuffle() {
      this.items = this.shuffleArray(this.items);
    },
    shuffleArray(array) {
      // 배열을 셔플하는 함수
      let m = array.length,
          t, i;
      while (m) {
        i = Math.floor(Math.random() * m--);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
      }
      return array;
    }
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 key 속성을 사용하여 각각의 li 요소를 고유하게 식별할 수 있도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 Vue가 변경된 부분을 추적하여 성능을 향상시킬 수 있습니다.&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;&amp;nbsp;&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 컴포넌트를 작은 단위로 분할하면 부분적으로 렌더링할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 컴포넌트를 분할하여 성능을 개선하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676720701859&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- ParentComponent.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;child-component :items=&quot;items&quot; /&amp;gt;
    &amp;lt;button @click=&quot;shuffle&quot;&amp;gt;Shuffle&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import ChildComponent from &quot;./ChildComponent.vue&quot;;

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      items: [1, 2, 3, 4, 5]
    };
  },
  methods: {
    shuffle() {
      this.items = this.shuffleArray(this.items);
    },
    shuffleArray(array) {
      // 배열을 셔플하는 함수
      let m = array.length,
          t, i;
      while (m) {
        i = Math.floor(Math.random() * m--);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
      }
      return array;
    }
  }
};
&amp;lt;/script&amp;gt;

&amp;lt;!-- ChildComponent.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&quot;item in items&quot; :key=&quot;item&quot;&amp;gt;{{ item }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  props: {
    items: Array
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 ParentComponent와 ChildComponent로 컴포넌트를 분할하여, ChildComponent에서는 items 배열을 렌더링하도록 하였습니다. 이렇게 하면 shuffle 메서드가 호출될 때에도 ChildComponent만 업데이트되므로, 전체 페이지를 다시 렌더링할 필요가 없어서 성능이 향상됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3) v-if 대신 v-show 사용&lt;/b&gt;&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;Vue에서 v-if는 조건부 렌더링을 할 때 사용되는데, 컴포넌트를 다시 렌더링하는 과정이 필요하기 때문에 성능이 저하될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 v-show를 사용하면 CSS를 이용하여 요소를 숨기고 보여줄 수 있어서, 렌더링 성능을 개선할 수 있습니다.&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;아래는 v-show를 사용하여 성능을 개선하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676720772356&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button @click=&quot;toggle&quot;&amp;gt;Toggle&amp;lt;/button&amp;gt;
    &amp;lt;div v-show=&quot;show&quot;&amp;gt;Hello, World!&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      show: true
    };
  },
  methods: {
    toggle() {
      this.show = !this.show;
    }
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 v-show를 사용하여 조건부 렌더링을 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 컴포넌트를 다시 렌더링하는 과정이 필요없어서 성능이 향상됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(4) 계산된 속성(computed) 사용하기&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;계산된 속성을 사용하면 템플릿에서 반복적으로 로직을 처리하지 않고, 미리 계산된 값을 재사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 중복 계산을 줄이고, 렌더링 속도를 개선할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676720864688&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    {{ fullName }}
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe',
    };
  },
  computed: {
    fullName() {
      return `${this.firstName} ${this.lastName}`;
    },
  },
};
&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 로딩 속도 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 로딩 속도를 최적화하는 몇 가지 방법은 다음과 같습니다:&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) Vue 컴포넌트 코드를 비동기적으로 로드하는 방법&lt;/b&gt;&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;/p&gt;
&lt;pre id=&quot;code_1676721190706&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const MyComponent = () =&amp;gt; import('./MyComponent.vue');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;import()&lt;/span&gt; 함수를 사용하여 MyComponent.vue 파일을 비동기적으로 로드할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 사용하면 사용자가 컴포넌트가 필요한 시점에만 로드하도록 할 수 있습니다.&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;&amp;nbsp;&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 크기를 최적화하고 이미지를 적절히 압축하여 로딩 속도를 개선할 수 있습니다. 이미지 크기를 최적화하는 방법으로는 이미지 포맷 변경, 이미지 사이즈 조정, 이미지 크롭 등이 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676722399932&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;image.jpg&quot; alt=&quot;image&quot; width=&quot;300&quot; height=&quot;200&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3) 최적화된 라이브러리 사용&lt;/b&gt;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 파일 크기를 줄이고 로딩 속도를 개선할 수 있습니다. 최적화된 라이브러리는 보통 ***.min.js 형식의 파일 이름을 가지고 있습니다&lt;/p&gt;
&lt;pre id=&quot;code_1676722503572&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js&quot;&amp;gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 메모리 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 메모리 최적화를 위한 몇 가지 방법은 다음과 같습니다:&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 메모리 누수 방지&lt;/b&gt;&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;Vue 컴포넌트의 생명주기 훅을 이용하여 메모리 누수를 방지할 수 있습니다. 예를 들어, 이벤트 리스너를 등록할 때 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;mounted&lt;/span&gt; 훅에서 등록하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;unmounted&lt;/span&gt; 훅에서 제거할 수 있습니다. 예를 들어, 다음과 같이 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676722840410&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button @click=&quot;startCountdown&quot;&amp;gt;Start&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      countdownInterval: null,
      count: 10
    }
  },
  methods: {
    startCountdown() {
      this.countdownInterval = setInterval(() =&amp;gt; {
        this.count -= 1
      }, 1000)
    },
    stopCountdown() {
      clearInterval(this.countdownInterval)
    }
  },
  mounted() {
    window.addEventListener('beforeunload', this.stopCountdown)
  },
  unmounted() {
    window.removeEventListener('beforeunload', this.stopCountdown)
  }
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시에서 mounted 훅에서 window 객체의 beforeunload 이벤트에 대한 리스너를 등록하고, unmounted 훅에서 해당 리스너를 제거합니다. 이렇게 함으로써 컴포넌트가 삭제될 때 이벤트 리스너도 함께 제거되므로 메모리 누수가 발생하지 않습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2) v-cloak 디렉티브의 사용&lt;/b&gt;&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;Vue 애플리케이션이 초기화되는 동안 렌더링 지연이 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 v-cloak 디렉티브를 사용하면 초기화되기 전에는 화면에 나타나지 않도록 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 코드:&lt;/p&gt;
&lt;pre id=&quot;code_1676723108042&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div v-cloak&amp;gt;
    {{ message }}
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      message: 'Hello, world!'
    }
  }
}
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
[v-cloak] {
  display: none;
}
&amp;lt;/style&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;이 외에도 위에서 언급한 v-if와 v-show의 적절한 사용, watch와 computed 속성의 적절한 사용, v-for를 사용할 때 key 속성 사용 등도메모리 최적화와 성능을 높이는데 도움을 줍니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/278</guid>
      <comments>https://bicute.tistory.com/278#entry278comment</comments>
      <pubDate>Fri, 2 Jun 2023 08:00:25 +0900</pubDate>
    </item>
    <item>
      <title>#4. Vue 3 고급 문법</title>
      <link>https://bicute.tistory.com/277</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;White Template.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCFoms/btshynYLPvs/1cK3BJ3B4zvv0OqoiCwSj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCFoms/btshynYLPvs/1cK3BJ3B4zvv0OqoiCwSj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCFoms/btshynYLPvs/1cK3BJ3B4zvv0OqoiCwSj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCFoms%2FbtshynYLPvs%2F1cK3BJ3B4zvv0OqoiCwSj0%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;2560&quot; height=&quot;1440&quot; data-filename=&quot;White Template.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Composition&amp;nbsp;API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue 3에서 새롭게 도입된 Composition API는 Vue.js의 고급 기능 중 하나로, Options API와 달리 코드의 구조화와 재사용성을 높일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API는 Vue.js의 함수형 프로그래밍과 React Hooks와 같은 아이디어를 결합하여, 컴포넌트 로직을 보다 작고 독립적인 단위로 분리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Composition API를 사용하여 구현된 간단한 Counter 애플리케이션 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676717276708&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- Counter.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Counter: {{ counter }}&amp;lt;/h1&amp;gt;
    &amp;lt;button @click=&quot;increment&quot;&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;button @click=&quot;decrement&quot;&amp;gt;Decrement&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { reactive, toRefs } from &quot;vue&quot;;

export default {
  setup() {
    const state = reactive({
      counter: 0
    });

    const increment = () =&amp;gt; {
      state.counter++;
    };

    const decrement = () =&amp;gt; {
      state.counter--;
    };

    return { ...toRefs(state), increment, decrement };
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 함수를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;state&lt;/span&gt; 객체를 생성하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;toRefs&lt;/span&gt; 함수를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;state&lt;/span&gt; 객체를 reactive한 ref 객체로 변환합니다. 이후 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;increment&lt;/span&gt;와 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;decrement&lt;/span&gt; 함수를 정의하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;return&lt;/span&gt; 문에서 ref 객체와 함수를 합쳐서 반환합니다.&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;Composition API를 사용하면, Options API보다 더욱 직관적이고 간결한 코드를 작성할 수 있으며, 기능 단위별로 코드를 분리하여 재사용성을 높일 수 있습니다. 또한, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;computed&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 등의 함수를 사용하여 상태와 동작을 정의하므로, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Teleport&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js&amp;nbsp;3에서&amp;nbsp;도입된&amp;nbsp;Teleport는&amp;nbsp;컴포넌트를&amp;nbsp;DOM의&amp;nbsp;특정&amp;nbsp;위치로&amp;nbsp;이동시키는&amp;nbsp;기능을&amp;nbsp;제공합니다.&amp;nbsp;이&amp;nbsp;기능은&amp;nbsp;모달,&amp;nbsp;드롭다운,&amp;nbsp;툴팁&amp;nbsp;등의&amp;nbsp;UI&amp;nbsp;컴포넌트에서&amp;nbsp;유용하게&amp;nbsp;사용될&amp;nbsp;수&amp;nbsp;있습니다.&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;Teleport를&amp;nbsp;사용하면,&amp;nbsp;하위&amp;nbsp;컴포넌트에서&amp;nbsp;생성된&amp;nbsp;DOM&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래는&amp;nbsp;Teleport를&amp;nbsp;사용하여&amp;nbsp;모달&amp;nbsp;창을&amp;nbsp;구현한&amp;nbsp;간단한&amp;nbsp;예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676717524972&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button @click=&quot;showModal = true&quot;&amp;gt;Show Modal&amp;lt;/button&amp;gt;

    &amp;lt;teleport to=&quot;#modal&quot;&amp;gt;
      &amp;lt;div v-if=&quot;showModal&quot; class=&quot;modal&quot;&amp;gt;
        &amp;lt;h1&amp;gt;Modal Title&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;Modal Content&amp;lt;/p&amp;gt;
        &amp;lt;button @click=&quot;showModal = false&quot;&amp;gt;Close Modal&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/teleport&amp;gt;

    &amp;lt;div id=&quot;modal&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

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

export default {
  setup() {
    const showModal = ref(false);

    return { showModal };
  }
};
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
.modal {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: white;
  padding: 20px;
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 Teleport를 사용하여 모달 컴포넌트를 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;#modal&lt;/span&gt; 위치로 이동시킵니다. 이때, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;teleport&lt;/span&gt; 태그에 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;to&lt;/span&gt; 속성으로 이동시킬 위치를 지정합니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;v-if&lt;/span&gt; 디렉티브를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;showModal&lt;/span&gt; 변수에 따라 표시되거나 숨겨집니다. 이때, 모달 컴포넌트는 Teleport를 사용하여 이전 위치와 상태를 유지한 채 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;#modal&lt;/span&gt; 위치로 이동됩니다.&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;Teleport를 사용하면, Vue.js의 컴포넌트 기반 설계와 함께 UI 컴포넌트를 더욱 유연하게 구현할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Suspense&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js&amp;nbsp;3에서&amp;nbsp;도입된&amp;nbsp;Suspense는&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;향상시킬&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;Suspense는 템플릿 내부에서 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;fallback&lt;/span&gt; 영역을 지정하여 로딩 상태를 표시하고, 비동기 컴포넌트가 준비되면 해당 컴포넌트를 렌더링하는 방식으로 동작합니다.&lt;br /&gt;&lt;br /&gt;아래는&amp;nbsp;Suspense를&amp;nbsp;사용하여&amp;nbsp;비동기&amp;nbsp;컴포넌트를&amp;nbsp;로딩하는&amp;nbsp;예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676717641116&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;suspense&amp;gt;
      &amp;lt;template #default&amp;gt;
        &amp;lt;AsyncComponent /&amp;gt;
      &amp;lt;/template&amp;gt;

      &amp;lt;template #fallback&amp;gt;
        &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;
      &amp;lt;/template&amp;gt;
    &amp;lt;/suspense&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
const AsyncComponent = () =&amp;gt; import(&quot;./AsyncComponent.vue&quot;);

export default {
  components: {
    AsyncComponent
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;suspense&lt;/span&gt; 태그로 비동기 컴포넌트를 래핑합니다. 이때, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;fallback&lt;/span&gt; 영역을 템플릿으로 지정하여 로딩 상태를 표시합니다. 비동기 컴포넌트는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;import&lt;/span&gt; 함수를 사용하여 동적으로 로딩됩니다.&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;Suspense를 사용하면, Vue.js의 컴포넌트 기반 설계와 함께 비동기 컴포넌트를 더욱 쉽게 구현할 수 있습니다. 이를 통해 초기 로딩 속도를 향상시키는 등 앱의 성능을 최적화할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Reactive와&amp;nbsp;Ref&lt;/h3&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;span style=&quot;background-color: #ffffff; color: #777777;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;&lt;/span&gt;Reactive&lt;/b&gt;&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;Vue.js 3에서 도입된 Reactive는 Vue.js의 반응성 시스템을 활용하여, 객체나 배열의 상태를 추적하고 업데이트할 수 있도록 하는 기능입니다.&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;Reactive는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;computed&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt;와 함께 사용하여 데이터의 상태 변화를 감지하고 이를 뷰에 반영할 수 있습니다. 이를 통해 데이터와 뷰가 실시간으로 동기화되어, 뷰의 상태 변화를 쉽게 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Reactive를 사용하여 객체의 상태를 추적하는 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676717798198&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;{{ user.name }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;{{ user.age }}&amp;lt;/p&amp;gt;
    &amp;lt;button @click=&quot;incrementAge&quot;&amp;gt;Increment Age&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

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

export default {
  setup() {
    const user = reactive({
      name: &quot;Alice&quot;,
      age: 25
    });

    const incrementAge = () =&amp;gt; {
      user.age++;
    };

    return { user, incrementAge };
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 함수를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;user&lt;/span&gt; 객체를 생성하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;name&lt;/span&gt;과 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;age&lt;/span&gt; 속성을 추가합니다. 이후 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;incrementAge&lt;/span&gt; 함수를 정의하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;return&lt;/span&gt; 문에서 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;user&lt;/span&gt; 객체와 함수를 반환합니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;user&lt;/span&gt; 객체의 속성은 반응성을 가지며, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;incrementAge&lt;/span&gt; 함수에서 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;user.age++&lt;/span&gt;와 같이 속성을 수정하면 해당 속성이 변경되고 이를 사용하는 뷰에 자동으로 반영됩니다.&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;Reactive를 사용하면, Vue.js의 반응성 시스템을 활용하여 데이터와 뷰를 더욱 효율적으로 관리할 수 있습니다. 이를 통해 코드의 가독성과 유지보수성을 높일 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #777777;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;bull;&amp;nbsp;&lt;/span&gt;Ref&lt;/b&gt;&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;Vue.js 3에서 도입된 Ref는 객체의 속성을 추적하고 수정할 수 있도록 하는 기능입니다. &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;Ref&lt;/span&gt;는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;와 함께 사용되어, 반응성 있는 데이터를 관리하는 데 유용하게 사용됩니다.&lt;br /&gt;&lt;br /&gt;Ref를&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;Ref를&amp;nbsp;사용하여&amp;nbsp;Vue.js의&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;Ref를&amp;nbsp;사용하여&amp;nbsp;숫자를&amp;nbsp;관리하는&amp;nbsp;예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676717942857&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;{{ count }}&amp;lt;/p&amp;gt;
    &amp;lt;button @click=&quot;increment&quot;&amp;gt;Increment&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

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

export default {
  setup() {
    const count = ref(0);

    const increment = () =&amp;gt; {
      count.value++;
    };

    return { count, increment };
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수를 생성합니다. &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수의 초기값은 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;0&lt;/span&gt;으로 설정됩니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;increment&lt;/span&gt; 함수에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count.value&lt;/span&gt;를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수의 값을 증가시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count.value&lt;/span&gt;는 Ref 객체의 속성으로, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수가 가리키는 Ref 객체의 값을 반환합니다.&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;Ref를 사용하면, Vue.js의 반응성 시스템을 활용하여 데이터와 뷰를 더욱 효율적으로 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, Ref를 사용하여 기본 타입 변수를 관리하면, Vue.js의 반응성 시스템을 우회하여 성능을 향상시킬 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;reactive와 Ref의 차이점, 어떤것을 사용하면 좋은가&lt;/b&gt;&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;와 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;는 모두 Vue.js 3에서 도입된 반응성 시스템을 사용하기 위한 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 두 함수는 다른 방식으로 동작하며, 사용하는 시기와 용도가 다릅니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;는 객체 또는 배열을 반응성 데이터로 변환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reactive로 생성한 객체의 속성은 반응성을 가지며, 객체의 속성이 변경될 때 Vue.js의 반응성 시스템을 통해 뷰를 업데이트합니다. 이 때, reactive로 생성된 데이터 객체는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하여 생성된 변수와 달리 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;.value&lt;/span&gt; 프로퍼티를 사용하지 않습니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수는 기본 타입 변수를 반응성 데이터로 변환합니다. ref로 생성한 변수는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;.value&lt;/span&gt; 프로퍼티를 사용하여 변수의 값을 읽거나 수정할 수 있습니다. ref로 생성한 변수는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 함수를 사용하여 생성한 객체와 달리 Vue.js의 반응성 시스템과 함께 사용할 수 없으며, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 함수를 사용하여 객체나 배열을 생성할 때는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하여 기본 타입 변수를 생성하는 것이 일반적입니다.&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;b&gt;객체나 배열과 같은 참조 타입의 데이터를 반응성 데이터로 관리할 때&lt;/b&gt;는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 함수를, &lt;b&gt;기본 타입 변수를 반응성 데이터로 관리할 때&lt;/b&gt;는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하는 것이 좋습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# ToRefs&lt;/h3&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;toRefs&lt;/span&gt;는&amp;nbsp;Vue&amp;nbsp;3의&amp;nbsp;Composition&amp;nbsp;API에서&amp;nbsp;사용되는&amp;nbsp;함수&amp;nbsp;중&amp;nbsp;하나로,&amp;nbsp;객체를&amp;nbsp;받아&amp;nbsp;객체의&amp;nbsp;프로퍼티들을&amp;nbsp;각각&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;&amp;nbsp;객체로&amp;nbsp;만들어&amp;nbsp;리턴해줍니다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;toRefs&lt;/span&gt;&amp;nbsp;함수를&amp;nbsp;사용하면,&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt;&amp;nbsp;객체에서&amp;nbsp;프로퍼티를&amp;nbsp;추출하여&amp;nbsp;각각의&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;&amp;nbsp;객체로&amp;nbsp;만들&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이렇게&amp;nbsp;생성된&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;&amp;nbsp;객체들은&amp;nbsp;이전에&amp;nbsp;설명한&amp;nbsp;것과&amp;nbsp;같이&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;.value&lt;/span&gt;를&amp;nbsp;사용하여&amp;nbsp;접근해야합니다.&lt;br /&gt;&lt;br /&gt;아래는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;toRefs&lt;/span&gt;를 사용하는 예시입니다:&lt;/p&gt;
&lt;pre id=&quot;code_1676718510461&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { toRefs, reactive } from 'vue';

const state = reactive({
  person: {
    firstName: 'John',
    lastName: 'Doe',
    age: 30
  }
});

const refs = toRefs(state.person);

console.log(refs.firstName.value); // John
console.log(refs.lastName.value); // Doe
console.log(refs.age.value); // 30&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;코드에서&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;toRefs&lt;/span&gt;&amp;nbsp;함수는&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;person&lt;/span&gt;&amp;nbsp;객체를&amp;nbsp;받아서,&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;firstName&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;lastName&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;age&lt;/span&gt;&amp;nbsp;속성을&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt;&amp;nbsp;객체로&amp;nbsp;분해합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 분해한 ref 객체들을 refs 객체에 저장한 후, 템플릿에서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;refs.firstName&lt;/span&gt;, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;refs.lastName&lt;/span&gt;, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;refs.age&lt;/span&gt;와 같이 사용할 수 있습니다.&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #777777;&quot;&gt;&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;Watch&lt;/span&gt;&lt;/h3&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 객체나 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 객체의 변화를 감시하고, 변화가 감지되면 지정된 콜백 함수를 실행하는 함수입니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수는 다양한 형태의 인수를 받을 수 있습니다. 가장 간단한 형태는 watch(source, callback, options)입니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;source&lt;/span&gt;는 감시 대상이 되는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 객체나 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 객체를 지정하고, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;callback&lt;/span&gt;은 속성 값이 변경될 때 실행되는 콜백 함수를 지정합니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;options&lt;/span&gt;은 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수의 동작을 설정하는 객체입니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수를 사용한 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676718988105&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;Count: {{ count }}&amp;lt;/p&amp;gt;
    &amp;lt;button @click=&quot;incrementCount&quot;&amp;gt;Increment&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { ref, watch } from &quot;vue&quot;;

export default {
  setup() {
    const count = ref(0);

    const incrementCount = () =&amp;gt; {
      count.value++;
    };

    watch(count, (newValue, oldValue) =&amp;gt; {
      console.log(`count changed from ${oldValue} to ${newValue}`);
    });

    return { count, incrementCount };
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하여 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수를 생성하고, 초깃값을 0으로 설정합니다. &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;incrementCount&lt;/span&gt; 함수에서는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;count.value&lt;/span&gt;를 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;1&lt;/span&gt; 증가시킵니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&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;&amp;nbsp;&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 객체나 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;reactive&lt;/span&gt; 객체에서 속성 값의 변경을 감지하고, 해당하는 로직을 수행할 때 유용하게 사용할 수 있습니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수를 사용한 또다른 예시입니다:&lt;/p&gt;
&lt;pre id=&quot;code_1676719214261&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const count = ref(0);

const handleCountChange = (newVal, oldVal) =&amp;gt; {
  console.log(`count changed: ${oldVal} -&amp;gt; ${newVal}`);
};

watch(
  // 첫 번째 인수: 감시할 대상
  count,
  // 두 번째 인수: 대상이 변화할때 실행할 콜백 함수
  handleCountChange
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수를 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;ref&lt;/span&gt; 함수를 사용하여 생성하고, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;handleCountChange&lt;/span&gt; 함수를 정의한 후, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수에서 감시 대상으로 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수를 전달하였습니다. 이때, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수에서는 감시 대상을 첫 번째 인수로, 콜백 함수를 두 번째 인수로 전달하였습니다.&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수의 값이 변경될 때마다 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;handleCountChange&lt;/span&gt; 함수가 실행되며, 콘솔에는 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;count&lt;/span&gt; 변수의 이전 값과 최신 값을 출력합니다. 이와 같이 Composition API에서도 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;watch&lt;/span&gt; 함수를 사용하여 감시 대상을 지정하고, 변경 시 실행할 콜백 함수를 등록할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/277</guid>
      <comments>https://bicute.tistory.com/277#entry277comment</comments>
      <pubDate>Wed, 31 May 2023 08:00:45 +0900</pubDate>
    </item>
    <item>
      <title>#3. Vue 3 기본 문법</title>
      <link>https://bicute.tistory.com/276</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;White Template (11).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efjMNe/btshyzEAMkg/cm30DqY0kG7XqUOLpgCU9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efjMNe/btshyzEAMkg/cm30DqY0kG7XqUOLpgCU9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efjMNe/btshyzEAMkg/cm30DqY0kG7XqUOLpgCU9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefjMNe%2FbtshyzEAMkg%2Fcm30DqY0kG7XqUOLpgCU9K%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;2560&quot; height=&quot;1440&quot; data-filename=&quot;White Template (11).png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# Template 문법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서는 HTML과 유사한 형태의 템플릿 문법을 사용하여 UI를 작성합니다. 템플릿 문법은 Vue.js의 핵심 요소 중 하나이며, 다음과 같은 기능을 제공합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보간(Interpolation): 중괄호({{}})를 사용하여 데이터 값을 표시할 수 있습니다. 이를 통해 Vue.js는 데이터와 UI를 자동으로 동기화할 수 있습니다.&lt;/li&gt;
&lt;li&gt;디렉티브(Directive): v- 접두사를 사용하여 Vue.js의 특수한 기능을 사용할 수 있습니다. 예를 들어, v-if 디렉티브를 사용하여 조건부 렌더링을 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;이벤트(Event): v-on 접두사를 사용하여 이벤트 핸들러를 등록할 수 있습니다. 예를 들어, v-on:click 디렉티브를 사용하여 클릭 이벤트를 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;속성(Attribute): v-bind 접두사를 사용하여 HTML 속성을 동적으로 바인딩할 수 있습니다. 예를 들어, v-bind:href 디렉티브를 사용하여 링크의 href 속성을 동적으로 변경할 수 있습니다.&lt;/li&gt;
&lt;li&gt;반복(Loop): v-for 접두사를 사용하여 배열의 요소를 반복하여 UI를 생성할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Vue.js의 템플릿 문법을 사용한 간단한 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714260133&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;h1&amp;gt;{{ message }}&amp;lt;/h1&amp;gt;
  &amp;lt;button v-on:click=&quot;count++&quot;&amp;gt;Click me&amp;lt;/button&amp;gt;
  &amp;lt;p v-if=&quot;count &amp;gt; 0&quot;&amp;gt;You clicked {{ count }} times.&amp;lt;/p&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&quot;item in items&quot;&amp;gt;{{ item }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;&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;Vue.js에서는 템플릿 문법을 사용하여 UI를 작성하고, 데이터와 UI를 자동으로 동기화할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 디렉티브(Directive)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서 디렉티브(Directive)는 v- 접두사를 가지는 특별한 속성으로, Vue.js의 기능을 활용하여 HTML 요소를 제어하고 데이터를 렌더링하는데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디렉티브는 Vue.js의 핵심 요소 중 하나이며, 다양한 기능을 제공합니다. 대표적인 디렉티브는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;v-if: 조건부 렌더링을 수행하는 디렉티브로, 지정한 조건에 따라 해당 요소를 표시하거나 숨깁니다.&lt;br /&gt;※ 참고: &lt;a href=&quot;https://bicute.tistory.com/184&quot;&gt;조건식 v-if, v-show&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;v-for: 반복문을 수행하는 디렉티브로, 지정한 데이터 소스를 반복하여 요소를 생성합니다.&lt;br /&gt;&lt;span&gt;※&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;참고: &lt;a href=&quot;https://bicute.tistory.com/182&quot;&gt;반복문(v-for) 사용하는 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;v-bind: 데이터를 HTML 속성에 바인딩하는 디렉티브로, 동적으로 속성 값을 변경할 수 있습니다.&lt;/li&gt;
&lt;li&gt;v-model: 양방향 데이터 바인딩을 수행하는 디렉티브로, 입력 요소와 데이터를 자동으로 동기화합니다.&lt;br /&gt;※&amp;nbsp;참고: &lt;a href=&quot;https://bicute.tistory.com/181&quot;&gt;데이터 바인딩하는 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;v-on: 이벤트 핸들러를 등록하는 디렉티브로, 지정한 이벤트가 발생하면 해당 함수를 실행합니다.&lt;br /&gt;※&amp;nbsp;참고: &lt;a href=&quot;https://bicute.tistory.com/183&quot;&gt;이밴트 핸들링(v-on)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Vue.js에서 디렉티브를 사용한 간단한 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714360692&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;app&quot;&amp;gt;
  &amp;lt;p v-if=&quot;isDisplayed&quot;&amp;gt;Hello, Vue.js!&amp;lt;/p&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&quot;item in items&quot;&amp;gt;{{ item }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
  &amp;lt;input v-bind:value=&quot;message&quot; v-on:input=&quot;updateMessage&quot;&amp;gt;
  &amp;lt;p&amp;gt;{{ message }}&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서는 v-if, v-for, v-bind, v-on 디렉티브를 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-if 디렉티브는 isDisplayed 값에 따라 p 요소를 표시하거나 숨깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-for 디렉티브는 items 배열의 요소를 반복하여 li 요소를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-bind 디렉티브는 message 값을 input 요소의 value 속성에 동적으로 바인딩합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v-on 디렉티브는 input 이벤트가 발생하면 updateMessage 메소드를 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 양방향 데이터 바인딩이 수행되며, input 요소와 message 데이터가 자동으로 동기화됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 컴포넌트(Component)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서 컴포넌트(Component)는 재사용 가능한 UI 모듈로, HTML, CSS, JavaScript를 포함하는 독립적인 기능 단위입니다. 컴포넌트는 애플리케이션을 더 작고 유지보수 가능한 조각으로 분해하여 코드 재사용성을 높이는데 사용됩니다. Vue.js는 컴포넌트 기반 아키텍처를 기본으로 하며, 다음과 같은 특징을 가집니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각각의 컴포넌트는 독립적인 스코프를 가지므로, 이름 충돌을 방지할 수 있습니다.&lt;/li&gt;
&lt;li&gt;컴포넌트는 데이터, 이벤트, 라이프사이클 훅 등을 가지며, 이를 통해 컴포넌트 간의 통신과 상호작용을 수행할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Vue.js는 전역 컴포넌트 레지스트리를 제공하므로, 애플리케이션 전체에서 사용 가능한 컴포넌트를 등록할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Vue.js는 지역 컴포넌트를 통해 필요한 컴포넌트만 로드하여 불필요한 리소스 낭비를 최소화할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Vue.js에서 컴포넌트를 사용한 간단한 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714463569&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- MyComponent.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h2&amp;gt;{{ title }}&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;{{ content }}&amp;lt;/p&amp;gt;
    &amp;lt;button v-on:click=&quot;updateContent&quot;&amp;gt;Update Content&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  data() {
    return {
      title: &quot;My Component&quot;,
      content: &quot;This is my component&quot;
    };
  },
  methods: {
    updateContent() {
      this.content = &quot;Content updated!&quot;;
    }
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서는 MyComponent.vue 파일에 컴포넌트를 정의하고 있습니다. 컴포넌트는 &amp;lt;template&amp;gt; 요소 내에서 UI를 정의하고, &amp;lt;script&amp;gt; 요소 내에서 데이터와 메소드를 정의합니다. 컴포넌트는 export default로 내보내며, 다른 파일에서 이 컴포넌트를 임포트하여 사용할 수 있습니다.&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;Vue.js에서는 다음과 같이 컴포넌트를 등록하고 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714498873&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Welcome to my app!&amp;lt;/h1&amp;gt;
    &amp;lt;my-component&amp;gt;&amp;lt;/my-component&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import MyComponent from &quot;./MyComponent.vue&quot;;

export default {
  components: {
    &quot;my-component&quot;: MyComponent
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서는 App.vue 파일에서 MyComponent를 임포트하여 등록하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록된 컴포넌트는 &amp;lt;my-component&amp;gt; 태그를 사용하여 App.vue에서 사용할 수 있습니다. 이를 통해 애플리케이션에서 재사용 가능한 UI 모듈을 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트는 다른 컴포넌트 내부에 중첩하여 사용할 수도 있습니다. 이를 통해 컴포넌트의 재사용성을 높이고, 복잡한 UI를 구성할 수 있습니다. 컴포넌트 간의 통신은 데이터와 이벤트를 사용하여 수행됩니다. 데이터는 부모 컴포넌트에서 자식 컴포넌트로 전달되며, 이벤트는 자식 컴포넌트에서 부모 컴포넌트로 전달됩니다. 이를 통해 부모-자식 관계의 컴포넌트 간의 상호작용을 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js는 컴포넌트 기반 아키텍처를 기본으로 하며, 이를 통해 코드의 재사용성과 유지보수성을 높이는데 큰 도움이 됩니다. Vue.js에서는 전역 또는 지역 컴포넌트를 등록하여 필요한 컴포넌트만 로드하여 불필요한 리소스 낭비를 최소화할 수 있습니다. 이를 통해 더 효율적인 애플리케이션을 개발할 수 있습니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/178&quot;&gt;새로운 컴포넌트를 생성하고 추가하는 방법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bicute.tistory.com/179&quot;&gt;컴포넌트 단위로 스타일 적용하기&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 라우터(Router)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서 라우터(Router)는 SPA(Single Page Application)에서 URL 경로를 사용하여 페이지를 변경하거나 컴포넌트를 로드하는데 사용됩니다. Vue.js는 vue-router 라이브러리를 통해 라우팅 기능을 제공하며, 라우터는 Vue.js의 핵심 요소 중 하나입니다. Vue.js에서 라우터를 사용하면 URL 경로에 따라 다른 컴포넌트를 로드하고 애플리케이션의 네비게이션을 제어할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라우터는 Vue.js의 컴포넌트 기반 아키텍처와 잘 결합되어 있으며, 컴포넌트를 라우팅에 사용할 수 있습니다. Vue.js에서 라우팅은 다음과 같은 구성요소로 구성됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라우터: URL 경로와 컴포넌트 간의 매핑을 관리하는 Vue.js의 핵심 요소입니다.&lt;/li&gt;
&lt;li&gt;라우트: URL 경로와 로드할 컴포넌트를 지정하는 구성요소입니다.&lt;/li&gt;
&lt;li&gt;컴포넌트: URL 경로에 따라 로드할 Vue.js 컴포넌트입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 Vue.js에서 라우터를 사용한 간단한 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714574847&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// router/index.js
import { createRouter, createWebHistory } from &quot;vue-router&quot;;
import Home from &quot;../views/Home.vue&quot;;
import About from &quot;../views/About.vue&quot;;

const routes = [
  {
    path: &quot;/&quot;,
    name: &quot;Home&quot;,
    component: Home
  },
  {
    path: &quot;/about&quot;,
    name: &quot;About&quot;,
    component: About
  }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서는 Vue.js에서 라우터를 정의하고 있습니다. createRouter 함수를 사용하여 라우터를 생성하고, history 객체를 사용하여 브라우저의 히스토리를 관리합니다. routes 배열에는 URL 경로와 로드할 컴포넌트를 지정하여 매핑합니다. 각 라우트는 path, name, component 속성을 가지며, 각각 URL 경로, 이름, 로드할 컴포넌트를 지정합니다.&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;Vue.js에서는 다음과 같이 라우터를 등록하고 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676714604892&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Welcome to my app!&amp;lt;/h1&amp;gt;
    &amp;lt;router-link to=&quot;/&quot;&amp;gt;Home&amp;lt;/router-link&amp;gt;
    &amp;lt;router-link to=&quot;/about&quot;&amp;gt;About&amp;lt;/router-link&amp;gt;
    &amp;lt;router-view&amp;gt;&amp;lt;/router-view&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { createApp } from &quot;vue&quot;;
import router from &quot;./router&quot;;
import App from &quot;./App.vue&quot;;

createApp(App).use(router).mount(&quot;#app&quot;);
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제에서는 App.vue에서 라우터를 사용하고 있습니다. &amp;lt;router-link&amp;gt; 태그를 사용하여 URL 경로를 지정하고, router-view 태그를 사용하여 현재 URL 경로에 맞는 컴포넌트를 렌더링합니다. 이를 통해 애플리케이션에서 라우팅을 구현할 수 있습니다.&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;Vue.js에서 라우팅을 구현할 때, 라우터에서 지원하는 여러가지 기능을 사용할 수 있습니다. 예를 들어, 동적 URL 매칭, 중첩 라우팅, 프로그래밍 방식 라우팅 등이 가능합니다. 또한, Vue.js에서는 라우터 외에도 상태 관리를 위한 Vuex 라이브러리를 제공합니다. Vuex를 사용하면 컴포넌트 간의 데이터 공유와 상태 관리를 보다 효율적으로 수행할 수 있습니다.&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;Vue.js에서는 vue-router 라이브러리를 사용하여 라우팅을 구현할 수 있습니다. vue-router는 Vue.js에서 많이 사용되는 라이브러리로, 간단하게 설정할 수 있으며 많은 기능을 제공합니다. 이를 통해 Vue.js에서 라우팅을 구현할 수 있습니다.&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://bicute.tistory.com/180&quot;&gt;페이지 전환하기 (라우터 설치부터 사용까지)&lt;/a&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;# 상태 관리(State Management)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue.js에서 상태 관리(State Management)는 애플리케이션 전체에서 사용되는 데이터를 관리하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 관리는 애플리케이션의 규모가 커지고 복잡해질수록 필요한 기능입니다.&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;Vue의 상태 관리는 Vuex를 사용했었으나, 현재는 공식적으로 Pinia를 사용하라고 권고하고 있습니다.&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;Pinia는 Vue.js 상태 관리 라이브러리 중 하나입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vuex와 마찬가지로 상태 관리를 위한 솔루션으로, 컴포넌트 간에 데이터를 공유하고 업데이트하는 데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vuex와 비슷한 기능을 가지고 있지만, 사용하기 더 간단하고 직관적인 API를 제공한다는 점에서 차이가 있습니다.&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;Pinia는 Vue 3의 Composition API를 기반으로 작성되었으며, 상태 저장소를 쉽게 만들고 액세스 할 수 있는 기능을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vuex와는 달리 모듈화된 구성요소를 사용하지 않으며, 훨씬 더 직관적이고 단순한 방식으로 상태를 관리할 수 있습니다.&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;Pinia는 다음과 같은 주요 개념으로 구성됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;Store&lt;/span&gt;: 상태를 저장하고 관리하는 곳입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;State&lt;/span&gt;: 상태 값입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;Getter&lt;/span&gt;: 상태 값을 계산하는 메서드입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;Action&lt;/span&gt;: 상태를 변경하는 메서드입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Pinia를 사용하는 간단한 예제 코드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676715594071&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () =&amp;gt; ({
    count: 0,
  }),
  getters: {
    doubleCount() {
      return this.count * 2
    },
  },
  actions: {
    increment() {
      this.count++
    },
  },
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제 코드에서는 useCounterStore라는 이름의 저장소를 정의하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 저장소에는 count라는 상태 값과 doubleCount라는 게터, 그리고 increment라는 액션 메서드가 포함되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 저장소를 사용하려면 컴포넌트에서 다음과 같이 가져와 사용하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676715626989&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;Count: {{ counter.count }}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Double Count: {{ counter.doubleCount }}&amp;lt;/p&amp;gt;
    &amp;lt;button @click=&quot;counter.increment&quot;&amp;gt;Increment&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { useCounterStore } from './store'

export default {
  setup() {
    const counter = useCounterStore()

    return {
      counter,
    }
  },
}
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 컴포넌트에서 useCounterStore()를 호출하면 store 객체를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 store 객체를 통해 count나 doubleCount 등의 상태 값을 읽어오거나 increment 등의 액션 메서드를 호출할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 Pinia의 기본적인 사용 방법입니다.&lt;br /&gt;&lt;br /&gt;※ 참고: &lt;a href=&quot;https://bicute.tistory.com/195&quot;&gt;Pinia (Vue 상태관리 라이브러리)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 도구 (Development Tools)/Vue</category>
      <author>BiCute</author>
      <guid isPermaLink="true">https://bicute.tistory.com/276</guid>
      <comments>https://bicute.tistory.com/276#entry276comment</comments>
      <pubDate>Mon, 29 May 2023 08:00:44 +0900</pubDate>
    </item>
  </channel>
</rss>