<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>scrumptious.log</title>
        <link>https://velog.io/</link>
        <description>There is so much scope for imagination in programming!</description>
        <lastBuildDate>Sat, 07 Aug 2021 06:34:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>scrumptious.log</title>
            <url>https://images.velog.io/images/so_scrumptious/profile/72d16c77-21d3-4741-938f-07c73623b9d8/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. scrumptious.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/so_scrumptious" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[debounce로 화면 크기에 따라 컴포넌트 다르게 렌더링하기]]></title>
            <link>https://velog.io/@so_scrumptious/debounce%EB%A1%9C-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0%EC%97%90-%EB%94%B0%EB%9D%BC-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EB%8B%A4%EB%A5%B4%EA%B2%8C-%EB%A0%8C%EB%8D%94%EB%A7%81%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@so_scrumptious/debounce%EB%A1%9C-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0%EC%97%90-%EB%94%B0%EB%9D%BC-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EB%8B%A4%EB%A5%B4%EA%B2%8C-%EB%A0%8C%EB%8D%94%EB%A7%81%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 07 Aug 2021 06:34:40 GMT</pubDate>
            <description><![CDATA[<h2 id="why--when">Why &amp; When?</h2>
<p>화면 크기에 따라 컴포넌트를 다르게 렌더링하고 싶을 때, </p>
<ol>
<li>resize 이벤트 이용해서 화면 크기를 state로 저장해야 하는 건 알겠는데,</li>
<li>매번 resize 이벤트 호출하면 낭비가 아닌가?에서 시작</li>
<li>debounce 발견!</li>
</ol>
<h2 id="예시">예시</h2>
<p>화면 크기에 따라서 다른 텍스트를 보여주는 버튼을 만들 때</p>
<ul>
<li>width &gt; 768px일 경우
<img src="https://images.velog.io/images/so_scrumptious/post/8b7b22e3-93d6-4adf-9fb5-e651f29dbe70/image.png" alt=""></li>
<li>그 외
<img src="https://images.velog.io/images/so_scrumptious/post/90fc2b2d-945f-4c43-9785-55f0f43aaaa5/image.png" alt=""></li>
</ul>
<h2 id="작성한-코드">작성한 코드</h2>
<h4 id="1-화면-크기를-담는-state를-설정한다">1. 화면 크기를 담는 state를 설정한다.</h4>
<pre><code class="language-javascript">  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });</code></pre>
<blockquote>
<p> window : 현재 스크립트가 작동 중인 창
 window.innerWidth : 브라우저 윈도우의 뷰포트 너비로, 수직 스크롤바가 존재한다면 포함</p>
</blockquote>
<h4 id="2-useeffect로-resize-이벤트가-있으면-변경된-화면-크기를-state에-저장하는-함수를-호출하도록-한다">2. useEffect로 resize 이벤트가 있으면 변경된 화면 크기를 state에 저장하는 함수를 호출하도록 한다.</h4>
<pre><code class="language-javascript">  useEffect(() =&gt; {
    window.addEventListener(&#39;resize&#39;, handleResize);
    return () =&gt; {
      window.removeEventListener(&#39;resize&#39;, handleResize);
    };
  }, []);</code></pre>
<blockquote>
<p>resize 이벤트는 document view의 크기가 변경될 때 발생</p>
</blockquote>
<blockquote>
<p>useEffect훅에서 함수를 반환하면 컴포넌트가 unmount될 때 clean-up 함수가 실행된다. useEffect에 빈 배열을 전달하면, 컴포넌트가 처음 mount될 때와 unmount될 때 실행되는데, 컴포넌트가 unmount될 때 이벤트 리스너를 삭제하지 않으면 컴포넌트가 자주 리렌더링될 경우 메모리 누수가 발생하므로 리스너를 삭제하도록 한다.</p>
</blockquote>
<h4 id="3-debounce를-이용해서-resize-이벤트가-일어날-때마다-state를-변경하는-것이-아니라-마지막-resize-이벤트가-실행되고-1초가-지나면-그때서야-state를-변경하도록-한다딱-한번">3. debounce를 이용해서 resize 이벤트가 일어날 때마다 state를 변경하는 것이 아니라 마지막 resize 이벤트가 실행되고 1초가 지나면 그때서야 state를 변경하도록 한다(딱 한번!).</h4>
<pre><code class="language-javascript">  const handleResize = debounce(() =&gt; {
    setWindowSize({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  }, 1000);</code></pre>
<blockquote>
<p>Debounce : 동일 이벤트가 반복적으로 시행되는 경우 마지막 이벤트가 실행되고 나서 일정 시간 동안 해당 이벤트가 다시 실행되지 않으면 그때서야 해당 이벤트의 콜백 함수를 한번만 실행</p>
</blockquote>
<h4 id="4-화면-크기state에-따라-보여줄-텍스트를-다르게-리턴">4. 화면 크기(state)에 따라 보여줄 텍스트를 다르게 리턴</h4>
<pre><code class="language-javascript">
  return (
          &lt;StyledButton type=&quot;primary&quot; ghost onClick={showModal}&gt;
            {windowSize.width &gt; 768 ? &#39;+ Add a Card&#39; : &#39;+ New&#39;}
          &lt;/StyledButton&gt;
        )</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[input 작성 중에 enter키 눌렀을 때 form이 전송되지 않도록 하기]]></title>
            <link>https://velog.io/@so_scrumptious/antdreact-input-%EC%9E%91%EC%84%B1-%EC%A4%91%EC%97%90-enter%ED%82%A4-%EB%88%8C%EB%A0%80%EC%9D%84-%EB%95%8C-form%EC%9D%B4-%EC%A0%84%EC%86%A1%EB%90%98%EC%A7%80-%EC%95%8A%EB%8F%84%EB%A1%9D-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@so_scrumptious/antdreact-input-%EC%9E%91%EC%84%B1-%EC%A4%91%EC%97%90-enter%ED%82%A4-%EB%88%8C%EB%A0%80%EC%9D%84-%EB%95%8C-form%EC%9D%B4-%EC%A0%84%EC%86%A1%EB%90%98%EC%A7%80-%EC%95%8A%EB%8F%84%EB%A1%9D-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 31 Jul 2021 02:40:48 GMT</pubDate>
            <description><![CDATA[<h3 id="문제---난-아직-쓰는-중이라고-전송하지-말라고">문제 - 난 아직 쓰는 중이라고 전송하지 말라고</h3>
<p>stackoverflow에서 아래와 같이 해결하라는 글을 봤는데 keyCode는 deprecated되어서 다시 찾아보았다.</p>
<pre><code class="language-javascript">onKeyDown={(e)=&gt; e.keyCode == 13 ? e.preventDefault(): &#39;&#39;}</code></pre>
<h3 id="해결---keyboardeventkey">해결 - <strong>KeyboardEvent.key</strong></h3>
<pre><code class="language-javascript">&lt;Input
    onKeyDown={(e) =&gt; (e.key === &#39;Enter&#39; ? e.preventDefault() : &#39;&#39;)}
    placeholder=&quot;Title&quot;
    allowClear
/&gt;</code></pre>
<p>참고
<a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key">https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key</a> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[map, filter, includes 다시 이해하기]]></title>
            <link>https://velog.io/@so_scrumptious/map-filter-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B8%B0</link>
            <guid>https://velog.io/@so_scrumptious/map-filter-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B8%B0</guid>
            <pubDate>Wed, 14 Jul 2021 13:53:26 GMT</pubDate>
            <description><![CDATA[<h3 id="구현-의도">구현 의도</h3>
<p>cards는 여러 card 객체들로 이루어진 배열이다.
[{}, {}, {}] 요렇게 생긴!!
cateIdArr의 각 요소의 값을 category_id로 가지고 있는 card만을 필터하려고 했다.
필터를 하면 원치 않는 객체가 빠진 [{}] 이 모양 그대로 유지되어야하는데 자꾸 배열 안에 또 배열 안에 객체가 하나씩 들어있는 구조로 출력되었다...;;;</p>
<h3 id="수정-전-코드">수정 전 코드</h3>
<h4 id="1-첫-번째-시도">1) 첫 번째 시도</h4>
<pre><code>    cateIdArr = [3, 4]

    const arr = cateIdArr.map((cateId) =&gt;
      cards.filter((card) =&gt; card.category_id === cateId)
    );
    console.log(&#39;arr &#39;, arr);</code></pre><p>출력 결과 
<img src="https://images.velog.io/images/so_scrumptious/post/c661b12e-a9d9-4ae1-aef9-84c0843f9202/image.png" alt=""></p>
<h4 id="map-filter">map(), filter()</h4>
<p><em>map과 filter는 모두 배열을 리턴한다!</em>
map이 forEach와 달리 배열을 리턴하는 것은 알고 있었는데, filter가 배열을 리턴하는 지 몰랐기 때문에 왜 배열 안에 각 배열이 들어간 구조로 데이터가 출력되는지 이해할 수 없었다.
역시 MDN을 잘봐야 ㅠㅠ..</p>
<h4 id="2-두-번째-시도-당연히-안됨-ㅠ">2) 두 번째 시도.. 당연히 안됨 ㅠ</h4>
<pre><code>     const arr = cateIdArr.map((cateId) =&gt;
      cards.filter((card) =&gt; card.category_id.includes(cateId))
    );</code></pre><p>출력 결과
<img src="https://images.velog.io/images/so_scrumptious/post/1b46b454-5b16-4a52-a1b7-a4d35d9cc0e4/image.png" alt=""></p>
<h4 id="includes">includes()</h4>
<ol>
<li><strong>배열</strong>이 특정 요소를 포함하고 있는지 판별하고, 결과를 true 또는 false 로 반환한다.</li>
<li>하나의 <strong>문자열</strong>이 다른 문자열에 포함되어 있는지_(대소문자 구분)_를 판별하고, 결과를 true 또는 false 로 반환한다.</li>
</ol>
<h3 id="수정-후-코드">수정 후 코드</h3>
<pre><code>  const arr = cards.filter((card) =&gt; cateIdArr.includes(card.category_id));
  console.log(&#39;arr &#39;, arr);</code></pre><p><img src="https://images.velog.io/images/so_scrumptious/post/dc897786-ef48-4cab-909f-9ce6d21ef4d7/image.png" alt=""></p>
<ol>
<li>각 카드의 category_id가 cateIdArr에 있는지 확인하려면 includes를 쓸 수 없다(includes는 배열이나 문자열에만 쓴다).
category_id는 배열이나 문자열이 아니기 때문에 배열인 cateIdArr가 category_id를 갖고 있는지 확인한다.</li>
<li>위의 조건이 true인 카드들만 filter</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[CouchCoding 포트폴리오 프로젝트 #1]]></title>
            <link>https://velog.io/@so_scrumptious/CouchCoding-%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</link>
            <guid>https://velog.io/@so_scrumptious/CouchCoding-%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</guid>
            <pubDate>Wed, 23 Jun 2021 12:13:28 GMT</pubDate>
            <description><![CDATA[<h3 id="couchcoding-멘토링-서비스로-포트폴리오-만들기">CouchCoding 멘토링 서비스로 포트폴리오 만들기</h3>
<p>몇 차례의 클론코딩 끝에 코딩이란 무엇인가 간신히 알게 된(?) 후에도 간단한 todo 리스트 조차 만들지 못하는 나를 발견했다! 프로젝트를 처음부터 스스로 해봐야 코딩 실력이 늘 수 있다고 판단했다(클론코딩은 사실 너무 우울하고 슬펐다). </p>
<p>그래서 지난 4월 알게 된 카우치코딩에서 리액트로 게시판을 만드는 프로젝트를 했다. 정말 많이 배웠다(클론 코딩의 저주에서 벗어나 활기찬 나로 돌아왔다!). &#39;나 이젠 진짜 개발자 한다!!&#39;를 외치며 이번엔 취업을 하기 위한 포트폴리오 프로젝트를 시작한다. 무려 <em>협업_으로..</em> 개발자로 성장하는 좋은 기회가 될 것 같다!</p>
<h3 id="무엇을-만들까">무엇을 만들까</h3>
<p>운동을 좋아한다! 내가 하는 운동에 대해 다른 사람들에게 열정적으로 떠드는 것도. 크로스핏, 필라테스, 요가 이것들은 정말 다 좋은데 무엇을 하는 운동인지 사람들이 정확히 모르는 경우가 많다. 나는 더 말하고 싶다고! 크로스핏 동작을 맞추는 간단한 퀴즈 웹사이트를 만들기로 했다. 이 동작들을 내가 크로스핏 시작하기 전에 모두 봤다면 애초에 시작을 안했을텐데...</p>
<h3 id="나의-역할--기술-스택">나의 역할 / 기술 스택</h3>
<p>우리 팀은 총 3명으로, Front-end / Back-end / Project Manager 역할을 각각 담당한다. 여기서 카우치코딩의 멘토님이 PM으로서 팀을 이끌어주시고, 나는 프론트엔드 개발을 담당한다.
이전의 내 프로젝트에 이어 ReactJS와 AntDesign, StyledComponent를 사용한다. 프로젝트가 끝나면 기술을 사용하는데 더 익숙해질 것이다. 나 자신아 기운내!!</p>
<h3 id="화면기획서">화면기획서</h3>
<p>화면 기획은 Whimsical이라는 툴을 사용해서 아이디어를 화면에 그려나갔다. 
<img src="https://images.velog.io/images/so_scrumptious/post/a9368646-4383-4730-995c-2a5d11ab3e2e/image.png" alt=""></p>
<h4 id="배운-것">배운 것</h4>
<p>프로젝트 아이템이 아쉽게도(?) only 내 머릿속에서 나온 아이디어였기 때문에, 기획자의 입장에서 기획자 - 개발자 간 커뮤니케이션을 어떻게 하는지 간접적으로나마 경험할 수 있었다. 
회의를 통해 의견을 교환하고, 그 과정을 통해 프로젝트의 의도가 뭐였는지 돌아가서 다시 한번 기능에 대해 고민하고 수정하는 부분이 재미있었다. 내 머릿속으로는 이해가 이렇게 잘가는데 내 말은 이렇게 나온다니..? 나 자신에게 매우 어이없었지만 커뮤니케이션의 중요성을 다시 한번 깨닫는 시간이었다.</p>
<h3 id="기능명세서일부">기능명세서(일부)</h3>
<p><img src="https://images.velog.io/images/so_scrumptious/post/8a780405-04b4-4d26-a490-ccfbc7ca13ba/%EA%B8%B0%EB%8A%A5%EC%83%98%ED%94%8C.PNG" alt=""></p>
<h4 id="배운-것-1">배운 것</h4>
<p>화면 기획서를 만들면서 구체화된 사항들을 기능명세서를 작성하며 수정하는 경우도 있었고, 그 반대의 경우도 있었다. 개인적으로 나는 개념을 이미지나 도표로 이해하는 visual person이 아니기 때문에 커뮤니케이션을 하는 데 있어 기능명세서를 작성해 본 것이 더욱 도움이 되었다. (+ notion 잘 쓰고 싶다)</p>
<h3 id="db명세서">DB명세서</h3>
<p><img src="https://images.velog.io/images/so_scrumptious/post/718d25a5-61b6-41a0-9926-bc9bd458fcd6/image.png" alt=""></p>
<h4 id="배운-것-2">배운 것</h4>
<p>화면 기획서를 보면서 백엔드 담당 개발자 분과 함께 회의를 통해(절대적 도움을 받음) 작성했다. 다시 한번 커뮤니케이션의 중요성을 느꼈다. 
&#39;내가 만든 퀴즈/카드만 보기&#39; 기능이 있는데, 여기서 쿠키, 세션, 토큰의 차이점에 대한 이야기가 나와서 회의가 끝나고 자세히 알아보았다.</p>
<h3 id="api명세서일부">API명세서(일부)</h3>
<p><img src="https://images.velog.io/images/so_scrumptious/post/f9315833-81d3-4360-a150-cf3636da33dd/api%EB%AA%85%EC%84%B8%EC%83%98%ED%94%8C.PNG" alt=""></p>
<h4 id="배운-것-3">배운 것</h4>
<ul>
<li>put과 patch의 차이점</li>
<li>REST API 설계 규칙</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>