<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발하는 리트리버</title>
    <link>https://choq.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 24 Jun 2026 12:10:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>devQ</managingEditor>
    <image>
      <title>개발하는 리트리버</title>
      <url>https://tistory1.daumcdn.net/tistory/6244532/attach/77ae5023be05452487bce096894a9be3</url>
      <link>https://choq.tistory.com</link>
    </image>
    <item>
      <title>딥러닝 뿌리 ANN, 그리고 DNN</title>
      <link>https://choq.tistory.com/153</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XSy9y/dJMcaglzPZh/Z1qXtwMKj1iM7cgtw05hNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XSy9y/dJMcaglzPZh/Z1qXtwMKj1iM7cgtw05hNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XSy9y/dJMcaglzPZh/Z1qXtwMKj1iM7cgtw05hNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXSy9y%2FdJMcaglzPZh%2FZ1qXtwMKj1iM7cgtw05hNk%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;452&quot; height=&quot;455&quot; data-origin-width=&quot;1192&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. ANN, Artificial Neural Network (인공 신경망)&lt;/b&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;span style=&quot;color: #000000; text-align: start;&quot;&gt;w&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) 곱해서 모두 더하고 편향(b)을 더한뒤 출력을 낸다. 이를 식으로 나타내면 아래와 같다.&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-origin-width=&quot;480&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUrnpN/dJMcabq4Fy9/bDW0N57p6m75kUn41DFTdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUrnpN/dJMcabq4Fy9/bDW0N57p6m75kUn41DFTdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUrnpN/dJMcabq4Fy9/bDW0N57p6m75kUn41DFTdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUrnpN%2FdJMcabq4Fy9%2FbDW0N57p6m75kUn41DFTdk%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;446&quot; height=&quot;67&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;72&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 style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위 식을 조금 더 있어빌리티(?) 하게 정리하면 이렇게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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-origin-width=&quot;386&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGcoyZ/dJMcaci9qbT/eUkywZxpzoWwdnF48enh5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGcoyZ/dJMcaci9qbT/eUkywZxpzoWwdnF48enh5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGcoyZ/dJMcaci9qbT/eUkywZxpzoWwdnF48enh5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGcoyZ%2FdJMcaci9qbT%2FeUkywZxpzoWwdnF48enh5k%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;386&quot; height=&quot;116&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;116&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;가중치란 말 그대로 해당 입력을 얼마나 중요하게 볼지를 의미하고, f(..) 함수가 '비선형성'을 담당한다. 여기서는 관계를 학습하게 해준다 정도로 보면 될것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 구조는 세 부분으로 보면된다. 데이터를 받는 &lt;b&gt;입력층&lt;/b&gt;, 데이터를 가공하는 &lt;b&gt;은닉층&lt;/b&gt;, 그리고 결과가 나오는 &lt;b&gt;출력층&lt;/b&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;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O9tSj/dJMcabq4Fot/q479B9xGlxhThyztG6v7uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O9tSj/dJMcabq4Fot/q479B9xGlxhThyztG6v7uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O9tSj/dJMcabq4Fot/q479B9xGlxhThyztG6v7uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO9tSj%2FdJMcabq4Fot%2Fq479B9xGlxhThyztG6v7uK%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;449&quot; height=&quot;183&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;324&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;b&gt;'순전파', &lt;/b&gt;그리고 예측한 값과 실제값을 비교해서 얼마나 다른지를 계산한다. 이를 &lt;b&gt;'손실계산'&lt;/b&gt;, 그리고 이 손실을 줄이기 위해서 출력층에서 부터 입력층으로 계산하는것 &lt;b&gt;'역전파'&lt;/b&gt; 라고한다. 이렇게 순전파에서 부터 손실계산하고 역전파 하는 하나의 싸이클을 반복학습이고, 이 반복학습을 통해서 &lt;b&gt;&lt;i&gt;가중치(w)&lt;/i&gt;&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;&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;b&gt;2. DNN, Deep Nueral Networks (심층 신경망)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 조금더 딥하게 진행하는 것이다. &amp;nbsp;ANN에 비해서 은닉층이 더 두터워진것을 확인할 수 있다. 여기서의 딥(Deep)이 딥러닝의 어원이라고 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 깊게 들어갈 수록 단계적으로 학습을 하는것으로 보면된다. 예를들어 첫번째 층에서는 선, 모서리 같은 패턴을 잡고 두 번째 층에서는 눈, 코, 입 같은 부분들의 패턴을 잡으면서 더 뒤로가면서 그것들을 조합해서 '얼굴'을 만들어내는 것이다. ANN 에서는 하기 어려운 복잡한 패턴들을 이러한 단계들을 통해서 확인할 수 있게 되는 것이다.&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-origin-width=&quot;924&quot; data-origin-height=&quot;306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zdjgl/dJMcah5Vz5J/RucG4Dxi3qTLNkNjFVhsIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zdjgl/dJMcah5Vz5J/RucG4Dxi3qTLNkNjFVhsIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zdjgl/dJMcah5Vz5J/RucG4Dxi3qTLNkNjFVhsIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZdjgl%2FdJMcah5Vz5J%2FRucG4Dxi3qTLNkNjFVhsIK%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;447&quot; height=&quot;148&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;306&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;이런 DNN에 단점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선은 계산 비용이다. 여기서야 은닉층이 3개에, 4개의 노드들 정도로 이루어져있지만 이런 층들이 많아지면 계산 비용이 증가하기 마련이다. 그리고 층이 깊어질수록 앞쪽 층 학습이 어렵다는 단점도 있다. 그리고 과적합 위험도 있는데 이는 훈련데이터에만 너무 학습이 되어버려서 실제 데이터 분석에 이슈가 생기는 것을 의미한다.&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>AI</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/153</guid>
      <comments>https://choq.tistory.com/153#entry153comment</comments>
      <pubDate>Wed, 17 Jun 2026 22:03:48 +0900</pubDate>
    </item>
    <item>
      <title>[FE] safari에서 sticky 이슈 in &amp;lt;table&amp;gt;</title>
      <link>https://choq.tistory.com/152</link>
      <description>&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-origin-width=&quot;1196&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HokGS/dJMcah5QbkU/ovgxLDq1rjLm6OeJzNRzNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HokGS/dJMcah5QbkU/ovgxLDq1rjLm6OeJzNRzNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HokGS/dJMcah5QbkU/ovgxLDq1rjLm6OeJzNRzNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHokGS%2FdJMcah5QbkU%2FovgxLDq1rjLm6OeJzNRzNk%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;536&quot; height=&quot;538&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;1200&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;테이블 컴포넌트에서 Footer 쪽을 &lt;b&gt;sticky&lt;/b&gt;로 해두었다. 그래서 &amp;nbsp;테이블 내부를 스크롤해도 언제든 하단에 있는 페이지네이션을 볼 수 있게 말이다. 하지만 어느날 날아든 청천병력과도 같은 이야기..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;safari에서 테이블 푸터쪽이 안보인데요..!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 개발할때는 크롬 기반만 지원한다고 공포(?) 하고 개발을 진행했어서 예전이면 그냥 크롬을 쓰라고 할만 하지만, 요즘은 이런 이슈들 해결하는 턱이 너무나 가벼워져서 기꺼이 확인하러 길을 떠났다.. 그래서 사파리로 들어가보니 하단 Footer 쪽에 아예 보이지 않고 있었다. 혹시 z-index 로 인해 가려진건가 싶었지만 그런것도 아니었다.&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;CSS&lt;/b&gt; 적용 차이가 있다는데에 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크롬은 &lt;b&gt;Blink엔진&lt;/b&gt;, 그리고 사파리는 &lt;b&gt;WebKit 엔진&lt;/b&gt;을 사용하는데, 이 과정에서 동일한 CSS라도 지원 범위나 동작이 달라질 수 있다. 이번 문제도 이와 같은 내용이었다. 전자에서는 thead, tbody, tfoot 과 같은 섹션에 position: sticky 가 정상 작동을 한다. 하지만 사파리의 Webkit에서는 정상적인 지원을 해주지 않는다. (또륵).&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;그러면 foot쪽에 sticky를 적용할 수 없다면 어떻게 해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 td 쪽에 직접 적용해주는 방법을 사용하면 된다. foot 관련된 sticky 속성을 &lt;b&gt;td&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;&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;추가적으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Blink는 원래 Webkit을 사용했으나 크롬 생태계에서 더 알맞는 구조를 만들기 위해서 Webkit을 포크하여 그때부터 별도 개발이 시작되었다고 한다. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;글 크롬(Chrome), 마이크로소프트 엣지(Edge), 오페라(Opera), 웨일(Whale) 등 대부분의 브라우저가 사용중이고 애플쪽에서만 Webkit을 사용중이다. &lt;s&gt;앱이나 웹이나 통일이 안되어 개발자로서 너무 행복하다^^&lt;/s&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이런 사례 외에도 종종 CSS 관련 이슈가 있으니..&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;사파리에서만..? 이라고 한다면 주변 CSS부터 의심하고 확인하면&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;금방 답을 확인할 수 있지 않나 싶다.&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/152</guid>
      <comments>https://choq.tistory.com/152#entry152comment</comments>
      <pubDate>Wed, 10 Jun 2026 22:14:19 +0900</pubDate>
    </item>
    <item>
      <title>[ML] 시계열 데이터</title>
      <link>https://choq.tistory.com/151</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;시계열의 정의&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시계열.. 시계..열? watch..?&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;/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개의 구성 요소로 나눠볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추세(trend), 계절성(seasonality), 잡음(noise)&lt;/b&gt; 이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yx4V5/dJMcagFOm9B/XiFg8R1eQAsrcZBThJrxnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yx4V5/dJMcagFOm9B/XiFg8R1eQAsrcZBThJrxnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yx4V5/dJMcagFOm9B/XiFg8R1eQAsrcZBThJrxnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYx4V5%2FdJMcagFOm9B%2FXiFg8R1eQAsrcZBThJrxnK%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;797&quot; height=&quot;368&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;684&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;표를 기준으로 전체적으로 우상향하는 '추세', 1년 주기로 오르락 내리락하는 &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;&lt;b&gt;추세&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 장기적으로 어느 방향으로 흘러가나를 보여주는 성분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 표 처럼 일정하게 오르내리는 선형(linear), 갈수록 가팔라지는 지수형(exponential), 점점 완만해지는 감쇠형(damped)의 케이스로 추세가 나온다.&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;&lt;b&gt;계절성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고정된 주기로 반복되는 패턴을 말한다. 여기서 헷갈리면 안되는건 고정된 주기인 1월 ~ 12월의 날씨 패턴은 계절성이라고 볼 수 있지만, 좋았다가 나빠졌다가 하는 경기, 부동산 사이클과 같이 주기가 일정하지 않은 '순환'은 계절성으로 보지 않는다.&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;&lt;b&gt;잡음&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추세와 계절성을 덜어낸 불규칙한 부분이다. 이상적인 잡음 데이터는 white noise라고 한다. 이는 모델링의 품질을 진단하는 잣대가 된다. 모델이 추세와 계절성을 잘 잡아냈다면 남은 잡음에서는 더 이상 관측 가능한 패턴이 남아있지 않아야한다. 잡음에서 패턴이 발견된다면 그건 모델이 놓친 부분이 있다는 신호로 인지할 수 있겠다.&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-origin-width=&quot;1342&quot; data-origin-height=&quot;1068&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/us5M3/dJMcadoFaqW/zTelFKsFcqSdTSn0vfDqok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/us5M3/dJMcadoFaqW/zTelFKsFcqSdTSn0vfDqok/img.png&quot; data-alt=&quot;각각의 데이터로 분리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/us5M3/dJMcadoFaqW/zTelFKsFcqSdTSn0vfDqok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fus5M3%2FdJMcadoFaqW%2FzTelFKsFcqSdTSn0vfDqok%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;631&quot; height=&quot;502&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;1068&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;목표&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시계열 분석은 결론적으로 과거를 분석해서 미래를 예측하는데 목표를 두고 있다. 과거에 있었던 내용들의 원인을 확인하고 미래를 예측하면서 이전과는 다른 이상치들을 탐지한다.&lt;/p&gt;</description>
      <category>기타 개발</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/151</guid>
      <comments>https://choq.tistory.com/151#entry151comment</comments>
      <pubDate>Fri, 5 Jun 2026 20:25:21 +0900</pubDate>
    </item>
    <item>
      <title>Context로 모달&amp;middot;토스트를 관리할 때 생긴 리렌더링 이슈</title>
      <link>https://choq.tistory.com/150</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://choq.tistory.com/148&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://choq.tistory.com/148&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1777015966361&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Context로 Modal을 함수처럼 사용하는 방법&quot; data-og-description=&quot;Toast, Modal을 화면에서 보여줄 일은 서비스를 개발하다 보면 매우 빈번한 일이다.컴포넌트를 공통으로 만들고 해당되는 화면에서 상태값을 추가하고, 컴포넌트를 연결해서 구현하는 과정을 무의&quot; data-og-host=&quot;choq.tistory.com&quot; data-og-source-url=&quot;https://choq.tistory.com/148&quot; data-og-url=&quot;https://choq.tistory.com/148&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b23rec/dJMb8SpKwYh/uMpwKEcaI2zcKRmVnfBdjk/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231,https://scrap.kakaocdn.net/dn/6DyjD/dJMb9g5dH1p/ujbMpRIIluqnL5dhGKEUJK/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231,https://scrap.kakaocdn.net/dn/m7U7X/dJMb8SpKwYg/4agUdvkfSsS4kD0FzjQwu1/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231&quot;&gt;&lt;a href=&quot;https://choq.tistory.com/148&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://choq.tistory.com/148&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b23rec/dJMb8SpKwYh/uMpwKEcaI2zcKRmVnfBdjk/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231,https://scrap.kakaocdn.net/dn/6DyjD/dJMb9g5dH1p/ujbMpRIIluqnL5dhGKEUJK/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231,https://scrap.kakaocdn.net/dn/m7U7X/dJMb8SpKwYg/4agUdvkfSsS4kD0FzjQwu1/img.png?width=333&amp;amp;height=231&amp;amp;face=0_0_333_231');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Context로 Modal을 함수처럼 사용하는 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Toast, Modal을 화면에서 보여줄 일은 서비스를 개발하다 보면 매우 빈번한 일이다.컴포넌트를 공통으로 만들고 해당되는 화면에서 상태값을 추가하고, 컴포넌트를 연결해서 구현하는 과정을 무의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;choq.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;254&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD8ha1/dJMcajoogE9/QpF5mwCk3z30FSWUkzTX8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD8ha1/dJMcajoogE9/QpF5mwCk3z30FSWUkzTX8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD8ha1/dJMcajoogE9/QpF5mwCk3z30FSWUkzTX8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD8ha1%2FdJMcajoogE9%2FQpF5mwCk3z30FSWUkzTX8k%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;254&quot; height=&quot;227&quot; data-origin-width=&quot;254&quot; data-origin-height=&quot;227&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;b&gt;modal&lt;/b&gt;을 &lt;b&gt;context&lt;/b&gt;로 추가한 이후에 해당 방식이 맘에 들어 &lt;b&gt;toast&lt;/b&gt; 메세지까지 추가하는 직업을 진행했다. ModalProvider, ToastProvider 2개의 provider로 나누는 것보다는 하나로 관리하는게 좋을것 같아서 &lt;b&gt;OverlayProvider&lt;/b&gt; 를 새로 만들어서 모달과 토스트를 한번에 사용가능하게끔 작업했다. (작명은 토스의 overlay를 참고했다) 그리고 provider 내부에서는 useState 를 가지고 모달과 토스트 값을 각각 관리해주게끔 작업했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1777016164428&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;OverlayProvider&amp;gt;
.. {children}...
&amp;lt;/OverlayProvider&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;그렇게 useOverlay 훅 내부에서 showToast, showModal 함수를 사용해서 페이지 단에서 바로 원하는 기능을 구현할 수 있었다. 깔끔하게 상황 종료.&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;가 혹시 있지 않을까 하는 생각이 들었다. children 부모에서 useState 값들이 바뀌게 되면 내부 자식들이 리렌더링 같이 될 수 있기 때문이다. 이 의심이 확신으로 바뀌는데에는 긴 시간이 필요하지 않았다. &lt;b&gt;useOverlay&lt;/b&gt; 훅을 사용하는 곳을 찾아서 &lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;console.log('rerendering check')&lt;/i&gt; &lt;/span&gt;&lt;/b&gt;를 추가해두었다. 그리고 해당 화면에서 토스트를 호출했는데 해당 콘솔이 찍혀나오는것을 확인할 수 있었다. 호출 시에 리렌더링이 되고 있었던 것이다. &amp;nbsp;provider쪽 value 를 &lt;b&gt;useMemo&lt;/b&gt;로 묶어주는 방식으로 처리해도 리렌더링은 계속해서 발생했다. 그래서 provider에서 역할을 아예 분리시키는 방식으로 목표를 정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1777016800413&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function OverlayProvider({ children }: OverlayProviderProps) {
  const portalRef = useRef&amp;lt;OverlayPortalHandle&amp;gt;(null);

  const showToast = useCallback(
    (message: string | ReactNode, duration = TOAST_DURATION) =&amp;gt; {
      portalRef.current?.showToast(message, duration);
    },
    [],
  );

  const showModal = useCallback((options: ShowModalOptions) =&amp;gt; {
    portalRef.current?.showModal(options);
  }, []);

  const closeModal = useCallback(() =&amp;gt; {
    portalRef.current?.closeModal();
  }, []);

  const overlayValue = useMemo(
    () =&amp;gt; ({
      showToast,
      showModal,
      closeModal,
    }),
    [showToast, showModal, closeModal],
  );

  return (
    &amp;lt;OverlayContext.Provider value={overlayValue}&amp;gt;
      {children}
      {createPortal(&amp;lt;OverlayPortalLayer ref={portalRef} /&amp;gt;, document.body)}
    &amp;lt;/OverlayContext.Provider&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ref&lt;/b&gt;를 이용해서 프로바이더 자체는 아래 &lt;b&gt;&amp;lt;OverlayPortalLayer /&amp;gt;&lt;/b&gt; 쪽 일을 시키는 업무를 전담하게 했고 상태값 관리는 아예 배제시켰다. &lt;b&gt;&amp;lt;OverlayPortalLayer /&amp;gt;&lt;/b&gt;&amp;nbsp;컴포넌트 쪽에서 &lt;b&gt;useState&lt;/b&gt; 이용해서 값을 변경하는 방식으로 진행했다. 그래서 값이 바뀌어서 리렌더링 되더라도 다른 부분에 영향 없이 해당 컴포넌트 자식들만 리렌더가 되게끔 했다. 이렇게 수정하고 나서는 토스트나 모달을 호출해도 해당 페이지에서 리렌링이 발생하지 않았다..!! (토스트를 호출해도 console.log 가 찍히지 않음)&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;토스트 메세지 호출을 단순화 하기 위해서 시작했던 작업이었는데&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;리렌더링 관련한 문제까지 직면하면서 일이 커진 느낌이었지만..&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;결국 손쉬운 호출과 리렌더링 이슈 모두 잡았으니 해피엔딩인것으로..&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/150</guid>
      <comments>https://choq.tistory.com/150#entry150comment</comments>
      <pubDate>Fri, 24 Apr 2026 20:56:28 +0900</pubDate>
    </item>
    <item>
      <title>한글 번역 막기</title>
      <link>https://choq.tistory.com/149</link>
      <description>&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-origin-width=&quot;144&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZIPi0/dJMcahD6oVo/8drofkYXkVNwncdJ7LUNok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZIPi0/dJMcahD6oVo/8drofkYXkVNwncdJ7LUNok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZIPi0/dJMcahD6oVo/8drofkYXkVNwncdJ7LUNok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZIPi0%2FdJMcahD6oVo%2F8drofkYXkVNwncdJ7LUNok%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;144&quot; height=&quot;138&quot; data-origin-width=&quot;144&quot; data-origin-height=&quot;138&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 data-ke-size=&quot;size16&quot;&gt;&quot;대처하다&quot; 라는 있으면 안되는 텍스트가 화면에서 표기되고 있다는 내용이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저런 텍스트를 넣은 적이 있나 싶어서 IDE 해당 텍스트를 검색했다. &amp;nbsp;&quot;no result found...&quot; 흠?&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-origin-width=&quot;281&quot; data-origin-height=&quot;93&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nD475/dJMcafsLn3Q/sqW9YP29rajuOdxBT7KfCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nD475/dJMcafsLn3Q/sqW9YP29rajuOdxBT7KfCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nD475/dJMcafsLn3Q/sqW9YP29rajuOdxBT7KfCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnD475%2FdJMcafsLn3Q%2FsqW9YP29rajuOdxBT7KfCK%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;281&quot; height=&quot;93&quot; data-origin-width=&quot;281&quot; data-origin-height=&quot;93&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 data-ke-size=&quot;size16&quot;&gt;해당 내용을 체크하고 자리로 와서 로컬에서 크롬 번역기능을 실행했다. 당연히 DAY 같은 영어는 한국어로 번역되는데 전혀 상관없는 '조건' 이런 텍스트가 '대처하다'로 뜬금없이 번역되는걸 확인해볼 수 있었다. 단어 외에도 문장의 어감이 바뀌는 케이스도 확인할 수 있었다.&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;그렇다고 크롬 번역 이슈입니다~ 라고만 답을 해서 보낼 수 는 없엇다. 그래서 다른 프로젝트와의 차이점을 체크하던 중에 html 태그에서 이질적인 부분을 발견했다. &lt;b&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #b80a18; text-align: start;&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color: #b80a18; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #bd0f1e; text-align: start;&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;&quot;en&lt;/span&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;&quot;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;&lt;b&gt;&amp;gt;&lt;/b&gt; 이라고 되어있는 부분이었다. 이 부분이 &quot;기본 언어는 영어다&quot; 라고 명시해주고 있었던것..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&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;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;그래서 이 부분을 &lt;b&gt;ko&lt;/b&gt; 로 변경해주고 나니, 한글 부분은 크롬 한국어 번역에서 변환되지 않고 필요한 영어부분만 번역되는것을 확인했다. 이 서비스의 경우 다국어를 지원해주지 않고 한국어로만 서비스했기에 별다른 사이드 이펙트 없이 해당 방법으로 해결 할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;프런트 작업을 하면서 &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;이 부분은 신경을 별로 쓰지 않고 개발했었는데 &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #2b303b; text-align: start;&quot;&gt;접근성, 언어등과 연결될때는 체크를 하고 진행해야겠다...!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/149</guid>
      <comments>https://choq.tistory.com/149#entry149comment</comments>
      <pubDate>Mon, 20 Apr 2026 22:23:50 +0900</pubDate>
    </item>
    <item>
      <title>Context로 Modal을 함수처럼 사용하는 방법</title>
      <link>https://choq.tistory.com/148</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brhCGo/dJMcacJABuP/XYSGhPxISN6aDQmK1TQFx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brhCGo/dJMcacJABuP/XYSGhPxISN6aDQmK1TQFx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brhCGo/dJMcacJABuP/XYSGhPxISN6aDQmK1TQFx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrhCGo%2FdJMcacJABuP%2FXYSGhPxISN6aDQmK1TQFx0%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;333&quot; height=&quot;231&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Toast, Modal&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지에서 매번 사용할때마다 &lt;b&gt;useState&lt;/b&gt; 상태값을 추가해줘야 하는건가? 매번 isOpen 만들어서... 흠&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;pre id=&quot;code_1776413010384&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [isOpen, setIsOpen] = useState(false);

&amp;lt;Modal open={isOpen} ... /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보여주고 안보여주고를 체크해야 하니 모달이나 토스트 메세지를 표기할때마다 화면에는 &lt;b&gt;useState&lt;/b&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;Modal을 오픈하는 &lt;b&gt;'함수'&lt;/b&gt; 로서 작동하면 사용하기 편해지지 않을까 하는 생각을 했다. 그래서 Modal을 관리하는, Toast를 관리하는 &lt;b&gt;context&lt;/b&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;b&gt;1. Provider 설정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 context와 마찬가지로 루트 컴포넌트에 만든 Provider로 감싸준다.&lt;/p&gt;
&lt;pre id=&quot;code_1776413568389&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
  return (
    &amp;lt;ToastProvider&amp;gt;
      ....
    &amp;lt;/ToastProvider&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;b&gt;2. 관련 Provider 작성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 매 페이지에 작성했던 상태관리를 이 쪽에서 관리를 한다. 보여줄지 말지, 모달의 옵션(타이틀, 버튼 등)을 설정해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1776413674373&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Context
export interface ModalContextType {
  showModal: (options: ShowModalOptions) =&amp;gt; void
  closeModal: () =&amp;gt; void
}

export const ModalContext = createContext&amp;lt;ModalContextType | null&amp;gt;(null)

// Provider
export function ModalProvider({ children }: ModalProviderProps) {
  const [isModalOpen, setIsModalOpen] = useState(false)
  const [modalOptions, setModalOptions] = useState&amp;lt;ShowModalOptions&amp;gt;({})

  const showModal = useCallback((options: ShowModalOptions) =&amp;gt; {
    setModalOptions(options)
    setIsModalOpen(true)
  }, [])

  const closeModal = useCallback(() =&amp;gt; {
    setIsModalOpen(false)
    modalOptions.onClose?.()
  }, [modalOptions])

  const handleClose = useCallback(() =&amp;gt; {
    closeModal()
  }, [closeModal])

  return (
    &amp;lt;ModalContext.Provider value={{ showModal, closeModal }}&amp;gt;
      {children}
      &amp;lt;Modal
        isOpen={isModalOpen}
        onClose={handleClose}
        ...
      &amp;gt;
        {modalOptions.content}
      &amp;lt;/Modal&amp;gt;
    &amp;lt;/ModalContext.Provider&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&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;b&gt;3. 화면에서 호출할 hook 작성&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1776414001937&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function useModal() {
  const context = useContext(ModalContext)
  return context
}&lt;/code&gt;&lt;/pre&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;b&gt;4. 화면에서 사용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 상태관리없이 useModal 훅을 이용해서 원하는 모달을 함수처럼 열수 있게 된다! 매번 따라오는 useState 로 부터 해방감을 느낄 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1776414070775&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { showModal, closeModal } = useModal()

const openModal = () =&amp;gt; {
  showModal({
    title: 'temp모달',
    ....
  })
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;원래 목표했던 바는 아니지만&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 변경하면서&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;페이지 간 이동하면서의 토스트와 모달도&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간편하게 사용가능해졌다..&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/148</guid>
      <comments>https://choq.tistory.com/148#entry148comment</comments>
      <pubDate>Fri, 17 Apr 2026 20:30:25 +0900</pubDate>
    </item>
    <item>
      <title>error Cannot read properties of null (reading 'edgesOut') 빌드 오류 해결하기</title>
      <link>https://choq.tistory.com/147</link>
      <description>&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-origin-width=&quot;1254&quot; data-origin-height=&quot;1254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNT5Lr/dJMcahjM6C7/ngLRwYLnIjotQDyq14pOxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNT5Lr/dJMcahjM6C7/ngLRwYLnIjotQDyq14pOxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNT5Lr/dJMcahjM6C7/ngLRwYLnIjotQDyq14pOxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNT5Lr%2FdJMcahjM6C7%2FngLRwYLnIjotQDyq14pOxK%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;278&quot; height=&quot;278&quot; data-origin-width=&quot;1254&quot; data-origin-height=&quot;1254&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;error&amp;nbsp;Cannot&amp;nbsp;read&amp;nbsp;properties&amp;nbsp;of&amp;nbsp;null&amp;nbsp;(reading&amp;nbsp;'edgesOut')&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨리 처리해야하는 이슈였는데 갑자기 오류가 발생하니 손이 덜덜 했던 기억이 있다. 분명 어제 퇴근하기 전까지만 해도 정상적으로 빌드가 진행되었는데 갑자기 이게 무슨 일인가.. 다급하게 검색을 진행했는데 나와는 별로 상관없는 케이스 뿐이었다. styled components 설치 때문에 발생한 케이스가 대부분이었다. 내 프로젝트에서 그런 라이브러리는 키우지 않아요..&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;lock 파일을 Dockerfile 에 추가해주고 npm ci 로 변경해주니 다시 이전과 같은 정상 빌드가 진행되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1776146962211&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Dockerfile
// 기존
COPY package.json ./
RUN npm install  

// 변경
COPY package.json package-lock.json ./
RUN npm ci&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;package.json&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. ^(caret) 사용.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 사용으로 npm install 로 최신 다운로드를 진행하는 경우 그때마다 버전이 바뀌는 케이스가 발생할 수가 있다.&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;b&gt;2. 간접의존성&lt;/b&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. merge시 lockfile 깨짐&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lockfile이 설정되어있더라도 머지할때 잘못되서 해당 lockfile이 깨진 상태로 올라갈 수 있다고 한다.&amp;nbsp;&lt;br /&gt;(가끔 lockfile 누가 올렸다가 빌드 실패한 경우가 있었던것 같은데 이런 케이스였지 않았나 싶다..)&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;빌드쪽 코드를 소홀히 다룬 대가를 치루기전에..&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;미리미리 세팅을 잘해서 저와 같이&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;긴장초초불안한 상황을 만나지 않기를 바랍니다&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/147</guid>
      <comments>https://choq.tistory.com/147#entry147comment</comments>
      <pubDate>Tue, 14 Apr 2026 20:24:01 +0900</pubDate>
    </item>
    <item>
      <title>하네스 엔지니어링 알아보기</title>
      <link>https://choq.tistory.com/146</link>
      <description>&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;행복한 골든 리트리버와 화려한 하네스.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUGLNL/dJMcagrv9pP/3MfXQXbRwoucXDvDKS3cpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUGLNL/dJMcagrv9pP/3MfXQXbRwoucXDvDKS3cpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUGLNL/dJMcagrv9pP/3MfXQXbRwoucXDvDKS3cpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUGLNL%2FdJMcagrv9pP%2F3MfXQXbRwoucXDvDKS3cpK%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;203&quot; height=&quot;305&quot; data-filename=&quot;행복한 골든 리트리버와 화려한 하네스.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1536&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 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;말을 길들이는 하네스가 AI에게로 넘어온건 그만큼 AI를 길들이기 위해서 사용하는것이다. 이러한 개념을 처음 붙인 &lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;HashiCorp 공동창립자 Mitchell Hashimoto 라는 사람은 26년도 2월 초에 아래와 같이 정의했다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;&quot;에이전트가 실수할 때마다, 그 실수가 다시 발생하지 않도록 하는것&quot;&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;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;GPT, CLAUDE 등 여러 친구들이 코딩에 도사가 된 상황이다. '~기능을 만들어줘' 한마디면 원하는 결과물을 가져다 준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;여기서 이슈가 &amp;nbsp;등장한다. 여러 모델들이 결과물을 만들어낼때마다 가지 각색의 방법과 디자인으로 만들어준다. 또 기존 프로젝트 위에서 진행할때는 기존 레거시를 무시한채로 독자적으로 만들어버리는 경우도 있다. 이건 저런 모델들이 한계를 보이는 걸까? 절대 그렇지 않다. 이건 사람에게도 똑같다. 뛰어난 개발자라고 한들 문서나, 현재 프로젝트에 대한 정보 등이 없다면 좋은 결과물을 만들어내는데 한계가 존재하는 것과 같은 이치이다. 그래서 저런 모델들에게 참고할 만한 배경을 제공해서 원하는 방향으로만 가게 하는것이 &lt;b&gt;'하네스'&lt;/b&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;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;하네스 엔지니어링을 프런트엔드 코드에는 어떻게 적용할 수 있을지 생각해봤다.&lt;/span&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;b&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;1. 규칙 정하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;curorrules 나 AGENTS.md 등을 사용해서 프로젝트의 컨벤션을 언급해둔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;아래와 같이 파일이 만들어질때 어떤식으로 무엇을 이용해서 만들지 정해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1775524277882&quot; class=&quot;php&quot; data-ke-language=&quot;php&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 예시
# AGENTS.md
- 컴포넌트는 항상 /components/{기능명}/index.tsx 구조로 생성
- 스타일은 Tailwind만, CSS 파일 생성 금지&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;2. 검증하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;만들어진 코드가 잘 돌아가는지 검증이 필요하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;ESLint rules이나, Vitest, RTL 등의 테스트 도구등을 사용해서 정상적으로 동작하는지 확인이 필요하다.&lt;/span&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;b&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;3. 피드백하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;그 이후에 이제 Lighthouse CI라든가, 코드 리뷰 등을 통해서 재확인 및 피드백을 진행하는 게 필요하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;단일 개발자로서 하네스엔지니어링을 시작해보려고 한다면 &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;피드백까지는 힘들더라도 규칙을 정해서 제한하고, &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&quot;&gt;해당 작업들을 검증하는 첫번째와 두번째 단계까지의 적용은&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: oklch(0.373 0.034 259.733); text-align: start;&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;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>FUTURE⭐️</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/146</guid>
      <comments>https://choq.tistory.com/146#entry146comment</comments>
      <pubDate>Tue, 7 Apr 2026 10:19:43 +0900</pubDate>
    </item>
    <item>
      <title>[FE] 스크롤이 튕기는 이유와 해결 방법</title>
      <link>https://choq.tistory.com/145</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;무제.gif&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFsMFu/dJMcagxUm9d/RiOjjkkIL6otsNsKB2nom0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFsMFu/dJMcagxUm9d/RiOjjkkIL6otsNsKB2nom0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFsMFu/dJMcagxUm9d/RiOjjkkIL6otsNsKB2nom0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bFsMFu/dJMcagxUm9d/RiOjjkkIL6otsNsKB2nom0/img.gif&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;531&quot; height=&quot;299&quot; data-filename=&quot;무제.gif&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;608&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;b&gt;시작&lt;/b&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;color: #000000; text-align: start;&quot;&gt;이 동작은 크게 두 가지로 나뉜다. 첫째는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모멘텀 스크롤(Momentum Scrolling)&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로, 손가락을 떼도 관성에 의해 콘텐츠가 계속 움직이는 현상이다. 물리학의 관성 법칙을 UI에 적용한 것으로, 인어셔 스크롤(Inertia Scrolling)이라고도 부른다. 둘째는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;고무줄 스크롤(Rubber Band Scrolling)&lt;/b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&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;하지만 언제나 자연스러움을 주는건 아니다. 위에 공유한 나의 box 스크롤 내용이 그렇다. 스크롤이 끝에 다다랐을때 전체 박스가 조금 더 튕기다가 제영역으로 돌아가는 현상을 확인 할 수 있다. 위에서 말한 고무줄 스크롤에 해당되는 현상이겠다. 여기서는 어색하게 만드는 케이스라고 볼 수 있겠다. 더욱이 튕기는 순간 border radius 가 없어져서 보여지는 바람에 더욱 이상하게 비춰진다. 뭔가 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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1773106458279&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;overscroll-behavior: none&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;해결방법은 css로 해당 효과들을 지워주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;모멘텀.. 동역학 수업에서나.. 들어봤던ㅎ;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/145</guid>
      <comments>https://choq.tistory.com/145#entry145comment</comments>
      <pubDate>Tue, 10 Mar 2026 10:38:57 +0900</pubDate>
    </item>
    <item>
      <title>[FE] Cursor로 코드 분석해서 Flow Chart 자동 생성하기 (Mermaid 활용)</title>
      <link>https://choq.tistory.com/144</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbh2Ia/dJMcahcv5Bb/Ki1eTx6aCP6oGP0q51Nsz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbh2Ia/dJMcahcv5Bb/Ki1eTx6aCP6oGP0q51Nsz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbh2Ia/dJMcahcv5Bb/Ki1eTx6aCP6oGP0q51Nsz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdbh2Ia%2FdJMcahcv5Bb%2FKi1eTx6aCP6oGP0q51Nsz1%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;329&quot; height=&quot;328&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;930&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 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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 코드정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;ldquo;현재 프로젝트 코드를 기반으로 사용자 흐름을 분석해서 mermaid 형식의 md 파일로 플로우 차트를 만들어줘.&amp;rdquo;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;한마디로 끝내고 넘어가쟈. 내 프로젝트에서 사용되는 라우팅 방식을 파악해서 md 파일로 뽑아달라고 요청한다. &amp;nbsp;그러면 빠른 시일 내에 아래와 같이 md 파일을 하나 뽑아준다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773029210546&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;flowchart LR
  E[&quot;/home&quot;] --&amp;gt;|예측하기| F[&quot;/list&quot;]
  F --&amp;gt;|선택 완료| E
  E --&amp;gt;|프로필| G[&quot;/profile&quot;]
  E2[&quot;/home?isEnd=true&quot;] --&amp;gt;|결과 확인| K[&quot;/result&quot;]&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;b&gt;2. 시각화&lt;/b&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;&lt;a href=&quot;https://mermaid.js.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://mermaid.js.org/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1773029260686&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Mermaid&quot; data-og-description=&quot;Create diagrams and visualizations using text and code.&quot; data-og-host=&quot;mermaid.js.org&quot; data-og-source-url=&quot;https://mermaid.js.org/&quot; data-og-url=&quot;https://mermaid.js.org&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Py9uL/dJMb8XkdsJT/mXPVa5fYidZ9dDuE1eA4eK/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420&quot;&gt;&lt;a href=&quot;https://mermaid.js.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mermaid.js.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Py9uL/dJMb8XkdsJT/mXPVa5fYidZ9dDuE1eA4eK/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Mermaid&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Create diagrams and visualizations using text and code.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mermaid.js.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 페이지로 들어가서 (free trial 만으로 충문하다.) &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;사이트의 &lt;b&gt;Live Editor&lt;/b&gt;에 코드를 입력하면 즉시 시각적인 플로우 차트가 렌더링되기 때문에, 코드 기반 흐름을 빠르게 확인할 수 있다. 위 코드를 붙여 넣으면 아래와 같이 시각적인 데이터를 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tRkBG/dJMcai3vXuW/mecJG2NQCqsb2JY7UBCnq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tRkBG/dJMcai3vXuW/mecJG2NQCqsb2JY7UBCnq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tRkBG/dJMcai3vXuW/mecJG2NQCqsb2JY7UBCnq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtRkBG%2FdJMcai3vXuW%2FmecJG2NQCqsb2JY7UBCnq1%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;612&quot; height=&quot;480&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;480&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;b&gt;/home&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;&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;후에 코드나 페이지별로 작업될때마다 md를 업데이트 해주는.. 게있어도 좋을것 같다는 생각이 든다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘의 현명하게 '해줘' 하기&lt;/p&gt;</description>
      <category>Front-end</category>
      <author>devQ</author>
      <guid isPermaLink="true">https://choq.tistory.com/144</guid>
      <comments>https://choq.tistory.com/144#entry144comment</comments>
      <pubDate>Mon, 9 Mar 2026 13:17:56 +0900</pubDate>
    </item>
  </channel>
</rss>