<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>긍정루미.log</title>
        <link>https://velog.io/</link>
        <description>개발자 한 발</description>
        <lastBuildDate>Thu, 31 Mar 2022 14:49:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>긍정루미.log</title>
            <url>https://images.velog.io/images/haha-rumi/profile/66bb70a2-b963-4b9f-bef6-58eae9c64f19/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 긍정루미.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/haha-rumi" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[상태 관리]상태 관리 도구의 필요성]]></title>
            <link>https://velog.io/@haha-rumi/%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-%EB%8F%84%EA%B5%AC%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1</link>
            <guid>https://velog.io/@haha-rumi/%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-%EB%8F%84%EA%B5%AC%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1</guid>
            <pubDate>Thu, 31 Mar 2022 14:49:20 GMT</pubDate>
            <description><![CDATA[<p>상태 관리를 알기 위해서는 우선 상태를 알아야 한다.</p>
<h2 id="상태state란">상태(state)란?</h2>
<p>상태랑 프론트엔드에 동적으로 표현되는 데이터로 즉, <strong>변하는 데이터</strong>다. 예로 쇼핑몰에 장바구니를 생각해보면 상품 수량, 주문할 상품 선택에 따라 변경되는 결제 금액 등이 상태다.</p>
<h2 id="상태의-조건">상태의 조건</h2>
<p>자식 컴포넌트들 간의 다이렉트로 데이터 전달은 불가능하고 상태를 관리하는 부모 컴포넌트를 통해서 주고 받는다. 그렇기 때문에 자식 컴포넌트가 많아지면 상태 관리가 복잡해지고 props drilling 이슈가 생긴다.</p>
<h2 id="props-drilling">props drilling</h2>
<p><img src="https://images.velog.io/images/haha-rumi/post/e0398467-1c86-4a97-b535-fd803505f543/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.47.16.png" alt="">
state를 다른 자식 컴포넌트에 전달할 때 props를 이용하여 값을 내려주는데 이때 해당 state값이 필요하지 않는 컴포넌트에도 전달을 하려 내려 받아야하는 것을 props drilling라고 한다.</p>
<h2 id="해결-방법">해결 방법</h2>
<p>이것을 해결하기 위해 상태 과리 도구(라이브러리)를 이용한다. 상태 관리 도구를 사용하면 전역 상태 저장소를 제공하여 어디서든 해당 저장소에 접근할 수 있기 때문에 props drilling도 해결이 가능하다.</p>
<h2 id="상태-도구-라이브러리-종류">상태 도구 라이브러리 종류</h2>
<ul>
<li>Redux</li>
<li>React Context</li>
<li>Recoil</li>
<li>MobX</li>
</ul>
<p>최근에는 Recoil도 인기가 조금 생기기 시작한 것 같지만 여전히 제일 인기가 좋은 라이브러리는 Redux인 것 같다. </p>
<h2 id="참조-자료">참조 자료</h2>
<p><a href="https://hanamon.kr/%ec%83%81%ed%83%9c%ea%b4%80%eb%a6%ac%eb%8f%84%ea%b5%ac-%ed%95%84%ec%9a%94%ec%84%b1/">https://hanamon.kr/%ec%83%81%ed%83%9c%ea%b4%80%eb%a6%ac%eb%8f%84%ea%b5%ac-%ed%95%84%ec%9a%94%ec%84%b1/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 별점 기능 구현]]></title>
            <link>https://velog.io/@haha-rumi/React-%EB%B3%84%EC%A0%90-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@haha-rumi/React-%EB%B3%84%EC%A0%90-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 31 Mar 2022 08:37:28 GMT</pubDate>
            <description><![CDATA[<p>원티드 프리온보딩 기업 과제 중에서 별점 기능 구현이 있어서 정리해 보았다.</p>
<h2 id="아이콘-가져오기">아이콘 가져오기</h2>
<p>이번 프로젝트에서는 <code>react-icon</code> 라이브러리를 사용했다.</p>
<pre><code class="language-javascript">import { ImStarFull } from &quot;react-icons/im&quot;;</code></pre>
<br>

<h2 id="별점-체크를-위한-설정">별점 체크를 위한 설정</h2>
<p>별 5개 만점으로 <strong>Boolean</strong>값을 이용하여 로직을 구현했다. <strong>useState</strong>를 사용하면 모든 기본값을 false로 주었다. 그리고 별점 2일 경우 [true, true, false, false, false]가 되도록한했다.</p>
<pre><code class="language-javascript">// 별점 기본값 설정
const [clicked, setClicked] = useState([false, false, false, false, false]);</code></pre>
<br>

<h2 id="별점-체크-최종-설정">별점 체크 최종 설정</h2>
<p>별 5개가 화면에 보여지도록 하기 위해 더미 배열(array)을 만들어서 map을 이용하여 돌린다. 그러면 클릭한 별의 index값이 el에 찍히게 된다. 가령 별점을 3점으로 줬다면<code>el = index = 3</code>가 된다.</p>
<pre><code class="language-javascript"> // 더미 배열을 통해 항상 별이 총 5개가 나오도록 한다.
const array = [0, 1, 2, 3, 4]

{array.map((el) =&gt; (
            &lt;ImStarFull
              key={el}
              onClick={() =&gt; handleStarClick(el)}
              className={clicked[el] &amp;&amp; &#39;black&#39;}
              size=&quot;35&quot;
            /&gt;))}</code></pre>
<p>그리고 클릭한 별의 el값(3)을 <strong>handleStarClick</strong> 함수로 보내서 클릭된 별 만큼 true로 바뀌도록 한다.  for문을 이용하여 el만큼 돌면서 false를 true로 변경한다.</p>
<pre><code class="language-javascript">const handleStarClick = index =&gt; {
  let clickStates = [...clicked];
  for (let i = 0; i &lt; 5; i++) {
    clickStates[i] = i &lt;= index ? true : false;
  }
   setClicked(clickStates);
 };</code></pre>
<br>

<h2 id="별점-내보내기">별점 내보내기</h2>
<p>마지막으로 filter를 이용하여 true값만 뽑아서 length를 이용해 개수를 확인 후 별점값을 보낸다.</p>
<pre><code class="language-javascript">let score = clicked.filter(Boolean).length;</code></pre>
<br>

<h2 id="css-설정">CSS 설정</h2>
<p>기본 별점 색은 회색이고 마우스를 올리거나 선택이되면 검정색으로 바뀌도록 아래와 같이 CSS를 설정했다.</p>
<pre><code class="language-javascript">const RatingBox = styled.div`
  margin: 0 auto;

  &amp; svg {
    color: #C4C4C4;
    cursor: pointer;
  }
  :hover svg {
    color: black;
  }
  &amp; svg:hover ~ svg {
    color: #C4C4C4;
  }
  .black {
    color: black;
  }
`</code></pre>
<br>

<h2 id="참고-자료">참고 자료</h2>
<p><a href="https://velog.io/@whoyoung90/TIL-35-WECODE-%EB%B3%84%EC%A0%90-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84">https://velog.io/@whoyoung90/TIL-35-WECODE-%EB%B3%84%EC%A0%90-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Network]API 그리고 HTTP API]]></title>
            <link>https://velog.io/@haha-rumi/NetworkAPI-%EA%B7%B8%EB%A6%AC%EA%B3%A0-HTTP-API</link>
            <guid>https://velog.io/@haha-rumi/NetworkAPI-%EA%B7%B8%EB%A6%AC%EA%B3%A0-HTTP-API</guid>
            <pubDate>Thu, 31 Mar 2022 04:11:59 GMT</pubDate>
            <description><![CDATA[<h2 id="api란">API란?</h2>
<p>API는 Application Programming Interface의 약자로 <strong>클라이언트(프로그램)에서 자원을 사용할 수 있도록 서버가 제공하고자 하는 데이터나 기능을 제어할 수 있게 만드는 인터페이스</strong>이다.</p>
<ul>
<li>컴퓨터와 인간을 연결하는 것은 <strong>UI(사용자 인터페이스)</strong></li>
<li>컴퓨터나 소프트웨어를 서로 연결하는 것은 <strong>API</strong></li>
</ul>
<br>
이렇게 API를 이해하고 있었는데 HTTP API라는 용어가 따로 있었다. 조금 혼란이 왔다. 모든 API는 HTTP API가 아닌가...? 하는 그래서 정리를 해봤다.

<h2 id="http-api란">HTTP API란?</h2>
<p>통신 규약 중 하나인 HTTP를 사용하여 프로그램끼리 의사소통을 하는 API다.</p>
<h2 id="http-api가-아닌-api">HTTP API가 아닌 API</h2>
<p><img src="https://images.velog.io/images/haha-rumi/post/5fbbf85c-6bbe-4b76-81ab-85fd45656200/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.10.32.png" alt=""></p>
<p>미세먼지 측정기의 경우, 미세먼지 측정기와 스마트 창문이 IoT 애플리케이션과 통신할 수 있는 API가 있어야 하는데 이때는 HTTP통신이 아닌 저사양/저전력 환경에 적합한 MQTT, CoAP 프로토콜을 사용해야 한다.</p>
<blockquote>
<h3 id="mqtt과-coap-프로토콜">MQTT과 CoAP 프로토콜</h3>
<p>MQTT은 TCP기반의 경량화된 메시지 프로토콜이다.
CoAP은 UDP기반의 저전력 비동기 통신 프로토콜이다.</p>
</blockquote>
<h2 id="참고자료">참고자료</h2>
<p><a href="https://www.youtube.com/watch?v=Jg3FFBLyhK0)">짐코딩 API란 무엇인가?</a>
<a href="https://bentist.tistory.com/37">https://bentist.tistory.com/37</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 배열 안에 객체를 날짜 순으로 정렬하는 방법]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-%EB%B0%B0%EC%97%B4-%EC%95%88%EC%97%90-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%82%A0%EC%A7%9C-%EC%88%9C%EC%9C%BC%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-%EB%B0%B0%EC%97%B4-%EC%95%88%EC%97%90-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%82%A0%EC%A7%9C-%EC%88%9C%EC%9C%BC%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 30 Mar 2022 12:55:51 GMT</pubDate>
            <description><![CDATA[<p>프로젝트르를 진행하면서 최신순으로 정렬하는 구현하기 위해 정리를 하게 되었다.</p>
<h2 id="배열-안-객체에-date값">배열 안 객체에 date값</h2>
<pre><code class="language-javascript">const date = [
    {date: &quot;2021-04-17&quot;},
    {date: &quot;2021-04-21&quot;},
    {date: &quot;2021-04-29&quot;},
    {date: &quot;2021-05-11&quot;},
    {date: &quot;2021-05-21&quot;},
    {date: &quot;2021-06-21&quot;},
]</code></pre>
<h2 id="날짜-순으로-정렬">날짜 순으로 정렬</h2>
<p><code>new Date()</code>를 사용하여 문자열로 입력된 날짜를 날짜 형태로 변환한 후 sort 함수를 이용하여 정렬 반환하는 방식이다.
<br></p>
<ol>
<li>new Date()를 사용하면 아래와 같이 문자열이 날짜형태로 변환된다.
<img src="https://images.velog.io/images/haha-rumi/post/95b48105-5bc1-446b-80d1-b735d764e538/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.52.02.png" alt=""></li>
<li>sort함수를 이용하여 정렬된 배열을 반환한다.<pre><code class="language-javascript">const orderedDate = date.sort((a, b) =&gt; new Date(a.date) - new Date(b.date))</code></pre>
<h2 id="참고자료">참고자료</h2>
<a href="https://dkmqflx.github.io/frontend/2021/04/21/javascript-sortbydate/">https://dkmqflx.github.io/frontend/2021/04/21/javascript-sortbydate/</a>
<a href="https://stackoverflow.com/questions/10123953/how-to-sort-an-object-array-by-date-property">https://stackoverflow.com/questions/10123953/how-to-sort-an-object-array-by-date-property</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] keyup, keydown(feat. keypress)]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-keyup-keydownfeat.-keypress</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-keyup-keydownfeat.-keypress</guid>
            <pubDate>Wed, 30 Mar 2022 12:25:50 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 진행하면서 keyup, keydown을 많이 사용하게 되어서 한 번 정리를 해보았다.</p>
<h2 id="keypress">keypress</h2>
<p><img src="https://images.velog.io/images/haha-rumi/post/28454d50-1bc3-4a08-b1b6-e3da9d77b9cf/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.12.12.png" alt=""></p>
<p>현재 MDN에 keypress를 검색하면 <strong>Deprecated</strong>라고 나온다. 더 이상 keypress 이벤트는 지원되지 않는다라는 의미다. Browser compatibility를 보면 아직 지원을 하는 브라우저들이 많지만 추후 최신 브라우저에서는 사용되지 않을 가능성이 높기 때문에 사용하지 않고 개발하는 것이 좋다.</p>
<p><img src="https://images.velog.io/images/haha-rumi/post/57d0c093-aa3e-4d29-b32e-1c53f38a7c16/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.12.25.png" alt=""></p>
<p>그리고 그 대신에 사용가능한 이벤트를 위와 같이 추천해준다.</p>
<h2 id="keydown">keydown</h2>
<p>사용자가 키보드를 누르면 바로 이벤트가 발생한다. </p>
<h3 id="eventiscomposing">event.isComposing</h3>
<p>한국어처럼 한글자를 완성하는데 여러 번의 keydown이 발생하는 경우에는 중간에 이벤트가 실행되는 경우가 생긴다. 그럴때는 keyup으로 이벤트를 변경하거나 event.isComposing을 사용하면 해결된다.</p>
<pre><code class="language-javascript">input.addEventListener(&#39;keydoen&#39;, (e) =&gt; {
  if (e.isComposing) {
    return;
  }
  if (e.keyCode === 13) {
    onAdd();
  }
})</code></pre>
<h2 id="keyup">keyup</h2>
<p>사용자가 누른 키보드에서 손을 떼면 이벤트가 발생한다.</p>
<h2 id="참고자료">참고자료</h2>
<p>[MDN keypress event]
[MDN keypress event]:<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/keypress_event">https://developer.mozilla.org/en-US/docs/Web/API/Document/keypress_event</a>
드림코딩엘리 브라우저 101 강의</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 이벤트 위임(Event Delegation)]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%9C%84%EC%9E%84Event-Delegation</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%9C%84%EC%9E%84Event-Delegation</guid>
            <pubDate>Tue, 29 Mar 2022 13:44:24 GMT</pubDate>
            <description><![CDATA[<p>이벤트를 공부하면서 버블링을 공부하고 최종적으로 좋은 코드를 위해서는 이벤트 위임이 중요하다는 것을 알게되어 정리를 해보았다.</p>
<h2 id="이벤트-위임이란">이벤트 위임이란?</h2>
<p>하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식이다.</p>
<br>

<h2 id="이벤트-위임-코드-패턴의-장점">이벤트 위임 코드 패턴의 장점</h2>
<ul>
<li>부모 요소에만 이벤트를 등록하기 때문에, 자식 요소에 추가, 삭제가 자유롭다.</li>
<li>메모리 공간의 사용량을 줄일 수 있다.<br>

</li>
</ul>
<h2 id="이벤트-위임-코드">이벤트 위임 코드</h2>
<p>아래의 코드처럼 querySelectorAll을 이용하여 모든 input의 요소를 가져와서 일일이 이벤트를 등록하는 것은 좋은 코드가 아니다. (forEach문으로 모든 input을 돌면서 일일이 이벤트를 추가하는 코드)</p>
<pre><code class="language-javascript">&lt;h1&gt;오늘의 할 일&lt;/h1&gt;
&lt;ul class=&quot;itemList&quot;&gt;
    &lt;li&gt;
        &lt;input type=&quot;checkbox&quot; id=&quot;item1&quot;&gt;
        &lt;label for=&quot;item1&quot;&gt;이벤트 버블링 학습&lt;/label&gt;
    &lt;/li&gt;
    &lt;li&gt;
        &lt;input type=&quot;checkbox&quot; id=&quot;item2&quot;&gt;
        &lt;label for=&quot;item2&quot;&gt;이벤트 캡쳐 학습&lt;/label&gt;
    &lt;/li&gt;
&lt;/ul&gt;

&lt;script&gt;
let inputs = document.querySelectorAll(&#39;input&#39;);
inputs.forEach(function(input) {
    input.addEventListener(&#39;click&#39;, function(event) {
        alert(&#39;clicked&#39;);
    });
});
&lt;/script&gt;</code></pre>
<br>
아래의 코드처럼 input의 상위 요소인 ul태그에 이벤트를 등록하여 일괄적으로 처리하는 것이 좋다. 즉, 부모 안에 있는 자식들에게 공통적으로 무언가 처리를 해야 될 때, 부모 요소에 이벤트를 적용하는 것이 좋은 코드다.

<pre><code class="language-javascript">let itemList = document.querySelector(&#39;.itemList&#39;);
itemList.addEventListener(&#39;click&#39;, function(event) {
    alert(&#39;clicked&#39;);
});</code></pre>
<p>이벤트 위임은 이벤트 버블링을 이용한 방법이다.</p>
<br>

<h2 id="참고자료">참고자료</h2>
<p><a href="https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/">https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] event.preventDefault()]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-event.preventDefault</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-event.preventDefault</guid>
            <pubDate>Tue, 29 Mar 2022 13:22:12 GMT</pubDate>
            <description><![CDATA[<p>종종 코드를 보면 함수에 event.preventDefault()가 적혀있는 것을 종종 보고는 했다. 그래서 정확히 언제 쓰면 좋을 것인지 알아보려고 한다.</p>
<h2 id="eventpreventdefault란">event.preventDefault()란?</h2>
<p>html(브라우저)에서 표준으로 제공하는 태그의 기본 이벤트 발생을 막아주는 메서드다. 즉, 현재 이벤트의 default 동작을 중단해주는 메서드다.</p>
<h2 id="언제-사용하나">언제 사용하나?</h2>
<ol>
<li><code>&lt;a&gt;</code>태그의 경우, href에 연결된 링크를 통해 해당 페이지로 이동하는 기능이 있는데, 해당 링크 페이지로 이동하고 싶지 않을 때 사용한다. </li>
<li><code>&lt;submit&gt;</code>태그의 경우, 값을 전송하면서 해당 페이지를 새로고침하는 기능을 가지고 있는데, 이때 값의 유효성 검사 후 전송이 되도록 하고 싶을 때 사용한다.<h2 id="코드-예시">코드 예시</h2>
<pre><code class="language-javascript">&lt;a href=&quot;https://github.com/Kyeom1997&quot; id=&quot;link&quot;&gt;김형겸의 깃허브&lt;/a&gt;
&lt;script&gt;
 document.querySelector(&#39;#link&#39;).addEventListener(&#39;click&#39;, function(e){
     e.preventDefault();
 });
 // a 태그 클릭 시 preventDefault를 사용했기 때문에 링크값이 있어도 이동하지 않는다.
&lt;/script&gt;</code></pre>
<pre><code class="language-javascript">const onLoginSubmit = (e) =&gt; {
e.preventDefault();
loginForm.classList.add(&quot;hidden&quot;);
const username = loginInput.value;
localStorage.setItem(USERNAME_KEY, username);
paintGreetings(username);
}</code></pre>
<h2 id="참고자료">참고자료</h2>
<a href="https://velog.io/@hang_kem_0531/JS-event.preventDefault-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0">https://velog.io/@hang_kem_0531/JS-event.preventDefault-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 이벤트 버블링(Bubbling) & 캡처링(Capturing)]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81Bubbling-%EC%BA%A1%EC%B2%98%EB%A7%81Capturing</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81Bubbling-%EC%BA%A1%EC%B2%98%EB%A7%81Capturing</guid>
            <pubDate>Tue, 29 Mar 2022 10:44:39 GMT</pubDate>
            <description><![CDATA[<p>Event를 공부하면서 버블링(Bubbling)과 캡처링(Capturing)에 대한 개념이 나와서 정리를 해보기로 했다.</p>
<p><img src="https://images.velog.io/images/haha-rumi/post/06725c78-8910-4dfc-9a26-1cbc0b1f2277/image.png" alt=""></p>
<h2 id="캡처링capturing">캡처링(Capturing)</h2>
<p>window로부터 이벤트가 발생한 요소까지 이벤트를 전파한다. 즉, 이벤트가 하위 요소로 전파되는 단계다. 실제 코드에서 자주 쓰이지는 않지만 개념적으로만 알고있으면 될 것 같다.</p>
<h2 id="버블링bubbling">버블링(Bubbling)</h2>
<p>이벤트가 발생한 요소부터 window까지 이벤트를 전파한다. <strong>한 요소에 이벤트가 발생하면</strong>, 이 요소에 할당된 핸들러가 동작하고 이어서 부모 요소의 핸들러가 동작한다. <strong>가장 최상단의 조상 요소</strong>를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작한다. </p>
<h2 id="버블링-현상-예">버블링 현상 예</h2>
<p>FORM &gt; DIV &gt; P 형태로 중첩된 구조가 있고, 요소 각각에 핸들러가 할당되어 있다.</p>
<pre><code class="language-javascript">&lt;style&gt;
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
&lt;/style&gt;

&lt;form onclick=&quot;alert(&#39;form&#39;)&quot;&gt;FORM
  &lt;div onclick=&quot;alert(&#39;div&#39;)&quot;&gt;DIV
    &lt;p onclick=&quot;alert(&#39;p&#39;)&quot;&gt;P&lt;/p&gt;
  &lt;/div&gt;
&lt;/form&gt;</code></pre>
<p>가장 안쪽의 <code>&lt;p&gt;</code>를 클릭하면 순서대로 다음과 현상이 나타난다.</p>
<ol>
<li><code>&lt;p&gt;</code>에 할당된 onclick 핸들러가 동작.</li>
<li>바깥의 <code>&lt;div&gt;</code>에 할당된 핸들러가 동작.</li>
<li>그 바깥의 <code>&lt;form&gt;</code>에 할당된 핸들러가 동작.</li>
</ol>
<p>document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작한다.</p>
<blockquote>
<h3 id="거의-모든-이벤트는-버블링이-된다">거의 모든 이벤트는 버블링이 된다.</h3>
<p>여기서 키워드는 &#39;거의&#39;이다. Focus 이벤트와 같은 버블링이 되지 않는 이벤트도 있다.</p>
</blockquote>
<h2 id="eventtarget">event.target</h2>
<p>이벤트가 정확히 어디서 발생했는지 등에 대한 정보를 얻을 수 있다. 이벤트가 발생한 가장 안쪽의 요소는 target요소라고 불리고, <code>event.target</code>을 사용해 접근할 수 있다.</p>
<h2 id="eventcurrenttarget과-eventtarget">event.currentTarget과 event.target</h2>
<ul>
<li><p><code>event.target</code>은 실제 이벤트가 시작된 &#39;타깃&#39;요소이다. 버블링이 진행되어도 변하지 않는다.</p>
</li>
<li><p><code>event.currentTarget</code>은 현재 요소로 현재 실행 중인 핸들러가 할당된 요소를 참조한다.</p>
<pre><code class="language-javascript">&lt;body&gt;
&lt;div class=&quot;outer&quot;&gt;
    &lt;button&gt;Click Me&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
  const outer = document.querySelector(&#39;.outer&#39;);![]
  const button = document.querySelector(&#39;button&#39;);

  outer.addEventListener(&#39;click&#39;, event =&gt; {
    console.log(`outer: ${event.currentTarget}, ${event.target}`);
  });
  button.addEventListener(&#39;click&#39;, event =&gt; {
    console.log(`button1 ${event.currentTarget}, ${event.target}`);
  });
&lt;/script&gt;
&lt;/body&gt;</code></pre>
<p>위에 코드에서 <code>button</code>을 클릭하면 console에 아래와 같이 나온다.
<img src="https://images.velog.io/images/haha-rumi/post/99510f72-4992-4070-b33f-416bdd6aedcb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.20.17.png" alt="">
여기서 <strong>event.target</strong> 즉, 이벤트가 시작된 타깃요소는 HTMLButtonElement가 되고, <strong>event.currentTarget</strong>는 <code>.outer</code>의 HTMLDivElement와 HTMLButtonElement가 나타나게 된다.</p>
<h2 id="버블링-중단">버블링 중단</h2>
<p>기본적으로 알고 있는 방법이 이벤트 객체의 메서드인 event.stopPropagation()를 사용하는 방법이다. </p>
</li>
</ul>
<h3 id="eventstoppropagation">event.stopPropagation()</h3>
<p>위에 코드의 button에 event.stopPropagation()를 추가하게 되면 button에서만 핸들링이 일어나고 버블링이 일어나지 않는다.</p>
<pre><code class="language-javascript">button.addEventListener(&#39;click&#39;, event =&gt; {
      console.log(`button1 ${event.currentTarget}, ${event.target}`);
        event.stopPropagation()
    });</code></pre>
<h3 id="eventstopimmediatepropagation">event.stopImmediatePropagation()</h3>
<p>event.stopPropagation()은 위쪽으로 일어나는 버블링은 막아주지만, 다른 핸들러들이 동작하는 건 막지 못 한다.</p>
<pre><code class="language-javascript">    button.addEventListener(&#39;click&#39;, event =&gt; {
      console.log(`button ${event.currentTarget}, ${event.target}`);
      event.stopPropagation()
    });
    button.addEventListener(&#39;click&#39;, event =&gt; {
      console.log(`button2 ${event.currentTarget}, ${event.target}`);
    });</code></pre>
<p>위에 코드처럼 같은 button에 적용된 핸들러가 있을 경우, event.stopPropagation()만으로는 동작을 멈추지 못 한다. 이때 사용되는 것이 event.stopImmediatePropagation()다. 이 메서드를 사용하면 버블링을 멈추고, 요소에 할당된 다른 핸들러의 동작도 막아준다.</p>
<blockquote>
<h3 id="하지만-eventstoppropagation와-eventstopimmediatepropagation의-사용은-위험하다">하지만!! event.stopPropagation()와 event.stopImmediatePropagation()의 사용은 위험하다.</h3>
</blockquote>
<p>내가 마음대로 이벤트를 취소해버리면 다른 부분에서 이 이벤트를 통해 더 의미 있는 일을 할 수도 있고 다른 기능을 추가해놨을 수도 있기 때문이다. 큰규모의 프로젝트 등에서 이것으로 인한 오류가 발행 할 수도 있다. 따라서 조건문을 이용하여 버블링을 막아주는 방법을 사용하면 좋다.</p>
<h3 id="조건문을-이용한-버블링-중단">조건문을 이용한 버블링 중단</h3>
<pre><code class="language-javascript">    outer.addEventListener(&#39;click&#39;, event =&gt; {
      if (event.target !== event.currentTarget) {
        return;
      }
    });</code></pre>
<p>위에 코드처럼 event.target와 event.currentTarget을 이용하여 조건문을 만들어주면 된다.</p>
<h3 id="참고사이트-및-강의">참고사이트 및 강의</h3>
<p><a href="https://ko.javascript.info/bubbling-and-capturing">모던 JavaScript 튜토리얼</a>
[드림코딩엘리 프론트엔드 필수 브라우저 101 강의]:<a href="https://academy.dream-coding.com/courses/browser101">https://academy.dream-coding.com/courses/browser101</a>
[드림코딩엘리 프론트엔드 필수 브라우저 101 강의]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 배열 무작위 정렬(랜덤 정렬)]]></title>
            <link>https://velog.io/@haha-rumi/JavaScript-%EB%B0%B0%EC%97%B4-%EB%AC%B4%EC%9E%91%EC%9C%84-%EC%A0%95%EB%A0%AC%EB%9E%9C%EB%8D%A4-%EC%A0%95%EB%A0%AC</link>
            <guid>https://velog.io/@haha-rumi/JavaScript-%EB%B0%B0%EC%97%B4-%EB%AC%B4%EC%9E%91%EC%9C%84-%EC%A0%95%EB%A0%AC%EB%9E%9C%EB%8D%A4-%EC%A0%95%EB%A0%AC</guid>
            <pubDate>Tue, 29 Mar 2022 08:49:08 GMT</pubDate>
            <description><![CDATA[<p>원티드 프리온보딩 기업 과제를 진행하면서 리스트 정렬 중, 랜덤 정렬 구현을 하는 부분이 있어서 JavaScript 배열 랜점 정렬 방법을 알아보았다.</p>
<h2 id="mathrandom">Math.random()</h2>
<p>Math.random()는 난수를 생성하는 메서드다. 난수는 정의된 범위내(기본 0~1사이)에서 값에 소숫점을 붙여서 무작위로 숫자를 추출한다. 보통 광고나 이미지 등을 랜덤으로 보여줘야 할 때 사용한다.</p>
<pre><code class="language-javascript">Math.random();</code></pre>
<h3 id="mathrandom-최대값-지정">Math.random() 최대값 지정</h3>
<p>난수의 범위 지정은 곱하기 * 기호로 최대값 설정이 가능하다. 최대값 설정은 Math.random()에 원하는 <strong>최대값을 곱해주면</strong> 된다.</p>
<pre><code class="language-javascript">Math.random() * 최대값
Math.random() * 10</code></pre>
<h3 id="mathrandom-최소값-지정">Math.random() 최소값 지정</h3>
<p>최소값을 지정할 경우, 아래와 같이 수식 수정이 필요하다.</p>
<pre><code class="language-javascript">( Math.random() * ( 최대값 - 최소값 )  ) + 최소값</code></pre>
<p>최소값은 + 더하기 기호로 원하는 최소값을 더해주는데, 최대값과 달리 최소값은 <strong>더하기</strong>로 들어가기 때문에 최대값도 동시에 변하게 된다. 따라서 최소값을 지정할 때에는 최대값에도 피해가 가지 않도록 셋팅이 필요하다.</p>
<p><strong>0 ~ 1 → 양변에 10을 곱하면, 0 ~ 10으로 최대값만 변함</strong>
<strong>0 ~ 1 → 양변에 1을 더하면, 1 ~ 2로 최소값과 최대값이 모두 변함</strong></p>
<h4 id="최소값만-지정시-문제점">최소값만 지정시 문제점</h4>
<p>해당 수식에 + 1을 더하면 난수의 생성 범위는 1 ~ 11이 된다.</p>
<pre><code class="language-javascript">( Math.random() * 10 ) + 1</code></pre>
<h2 id="소숫점-삭제">소숫점 삭제</h2>
<p>소숫점을 삭제하고 싶을 때는 Math.floor() 메소드를 사용한다.</p>
<pre><code class="language-javascript">Math.floor( ( Math.random() * 10 ) )</code></pre>
<h2 id="베열-랜덤-정렬">베열 랜덤 정렬</h2>
<pre><code class="language-javascript">const shuffle = () =&gt; ( Math.random() - 0.5 );
const quizs = [0,1,2,3,4,5,6,7,8,9,10];
const shuffled = [...quizs].sort(shuffle);

console.log(&quot;quizs&quot;, quizs)
console.log(&quot;shuffled quizs&quot;, shuffled)</code></pre>
<h3 id="참고-사이트">참고 사이트</h3>
<p><a href="https://codiving.kr/54">https://codiving.kr/54</a>
<a href="https://dasima.xyz/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-math-random-%EB%B2%94%EC%9C%84-%EC%9E%90%EB%A6%BF%EC%88%98/">https://dasima.xyz/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-math-random-%EB%B2%94%EC%9C%84-%EC%9E%90%EB%A6%BF%EC%88%98/</a>
[MDN 공식사이트]:<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/random">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/random</a>
[MDN 공식사이트]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React]Custom Hooks]]></title>
            <link>https://velog.io/@haha-rumi/Custom-Hooks</link>
            <guid>https://velog.io/@haha-rumi/Custom-Hooks</guid>
            <pubDate>Mon, 28 Mar 2022 13:29:56 GMT</pubDate>
            <description><![CDATA[<p>코드스테이츠에서 프로젝트를 진행하면서 드래그 위치에 맞춰 숫자가 카운드되는 Hook을 사용한 적이 있었는데 그때 처음 <strong>Custom Hooks</strong>를 접하게 되었다.</p>
<h2 id="custom-hooks란">Custom Hooks란?</h2>
<p>R개발자가 스스로 커스텀한 훅을 의미하며, 반복되는 로직을 함수로 뽑아내어 재사용이 가능하다.</p>
<h2 id="언제-사용하나">언제 사용하나</h2>
<p>여러 url을 fetch할 때, 여러 input에 의한 상태 변경 등 반복되는 로직을 동일한 함수에서 작동하게 하고 싶을 때 커스텀 훅을 주로 사용한다.</p>
<h2 id="장점">장점</h2>
<ol>
<li>상태관리 로직의 재활용이 가능하다.</li>
<li>클래스 컴포넌트보다 적은 양의 코드로 동일한 로직을 구현할 수 있다.</li>
<li>함수형으로 작성하기 때문에 명료하다.</li>
</ol>
<h2 id="적용">적용</h2>
<blockquote>
<h3 id="주의사항">주의사항</h3>
<p><strong>1. 커스텀 hook 이름 앞에 use를 꼭 붙인다.</strong>
자동적으로 규칙이 맞는지 확인하지 못합니다. 특정 함수에 hook이 호출되는지 알 수 없다.
<strong>2. 각 input별로 같은 함수를 이용하지만 같은 state를 공유하는 것이 아니다.</strong>
hook은 state적인 특성을 갖고있어서 공유하지 않고 완전히 독립적이다.</p>
</blockquote>
<ol>
<li>src 폴더 &gt; hooks 폴더 생성 후, Custom Hook별로 파일을 추가한다.</li>
<li>함수 이름 앞에 use를 붙인다. ex)useInput.js</li>
<li>보통 프로젝트 내의 hooks 디렉토리에 커스텀 훅을 위치시킨다.</li>
<li>커스텀 훅을 작성할 때는 useState와 같은 React 내장 훅을 사용하여 작성할 수 있다.</li>
<li>보통의 함수와 마찬가지로 사용자가 직접 파라미터와 반환 값을 결정할 수 있다.</li>
<li>Rules of Hooks 규칙들을 준수하다.</li>
</ol>
<h2 id="rules-of-hooks">Rules of Hooks</h2>
<ol>
<li>최상위에서만 Hook을 호출해야 한다.
반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하면 안된다.</li>
<li>오직 React 함수 내에서 Hook을 호출해야 한다.
Hook을 일반적인 JavaScript 함수에서 호출하면 안된다.</li>
</ol>
<h2 id="코드-예시">코드 예시</h2>
<pre><code class="language-javascript">const useFetch = ( initialUrl:string ) =&gt; {
    const [url, setUrl] = useState(initialUrl);
    const [value, setValue] = useState(&#39;&#39;);

    const fetchData = () =&gt; axios.get(url).then(({data}) =&gt; setValue(data));

    useEffect(() =&gt; {
        fetchData();
    },[url]);

    return [value];
};

export default useFetch;</code></pre>
<pre><code class="language-javascript">import { useState, useCallback } from &#39;react&#39;;

function useInputs(initialForm) {
  const [form, setForm] = useState(initialForm);
  // change
  const onChange = useCallback(e =&gt; {
    const { name, value } = e.target;
    setForm(form =&gt; ({ ...form, [name]: value }));
  }, []);
  const reset = useCallback(() =&gt; setForm(initialForm), [initialForm]);
  return [form, onChange, reset];
}

export default useInputs;</code></pre>
<h2 id="사용해-본-custom-hooks">사용해 본 Custom Hooks</h2>
<ul>
<li>4주 프로젝트 진행 시, 랜딩페이지 드래그에 따른 숫자 카운팅 Hook</li>
<li>그래그에 따른 FadeIn Hook</li>
</ul>
<h2 id="참고-사이트">참고 사이트</h2>
<ul>
<li>코드스테이츠</li>
<li>[React 공식사이트]:<a href="https://ko.reactjs.org/docs/hooks-custom.html">https://ko.reactjs.org/docs/hooks-custom.html</a>
[React 공식사이트]</li>
<li><a href="https://abangpa1ace.tistory.com/123">https://abangpa1ace.tistory.com/123</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>