<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bu-geon.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 05 Jun 2022 02:08:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>bu-geon.log</title>
            <url>https://velog.velcdn.com/images/bu-geon/profile/56c12637-e1e4-4192-bc0a-b9fabe658833/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. bu-geon.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bu-geon" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[모아데이터 프로젝트 후기]]></title>
            <link>https://velog.io/@bu-geon/%EB%AA%A8%EC%95%84%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@bu-geon/%EB%AA%A8%EC%95%84%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Sun, 05 Jun 2022 02:08:19 GMT</pubDate>
            <description><![CDATA[<h3 id="담당-개발-내용">담당 개발 내용</h3>
<p>: 모아 데이터 프로젝트의 StepChart 파트</p>
<h3 id="개발-진행-상황">개발 진행 상황</h3>
<p>: Step 차트를 왜 1분 단위로 그려야하는 지 솔직히 이해할 수가 없었다. 그래서 하루치 데이터에 대해서는 10분 단위로 자르고(솔직히 10분 단위도 적어보인다.) 24시간 동안 10분 간격으로 걸음 수를 차트에 기록하였다. 아마 대부분의 다른 조에서는 주어진 json을 그대로 사용했을 거 같지만, 나는 아이폰의 건강 데이터처럼 하루치의 걸음 수에 대해서는 특정 시간별로 몇 걸음을 걸었는지 보여주고 싶어서 추가적으로 데이터를 가공했다.</p>
<pre><code class="language-js">export const useStepsdata = (data: IUserInfo[]): IDailyStepsData =&gt; {
  const [stepsData, setStepsData] = useState&lt;IDailyStepsData&gt;({})

  useEffect(() =&gt; {
    const sortedData = data.sort((a, b) =&gt; dayjs(a.crt_ymdt).diff(b.crt_ymdt, &#39;s&#39;))

    const stepsRecords = sortedData.reduce((acc: IDailyStepsData, cur: IUserInfo) =&gt; {
      acc[dayjs(cur.crt_ymdt).format(&#39;YYYY-MM-DD&#39;)] = {
        totalDistances: Math.max(cur.distance, acc[dayjs(cur.crt_ymdt).format(&#39;YYYY-MM-DD&#39;)]?.totalDistances ?? 0),
        totalSteps: Math.max(cur.steps, acc[dayjs(cur.crt_ymdt).format(&#39;YYYY-MM-DD&#39;)]?.totalSteps ?? 0),
        records: [...(acc[dayjs(cur.crt_ymdt).format(&#39;YYYY-MM-DD&#39;)]?.records ?? []), cur],
      }

      return acc
    }, {})

    setStepsData(stepsRecords)
  }, [data])

  return stepsData
}
</code></pre>
<p>하루치 데이터에 대해서는 24시간을 10분 단위로 잘라서 144개의 칼럼에 해당 시간에 걸을 수만을 저장했다. 걸음을 누적데이터로 보여주는 것보다 그 구간에 걸은 수만큼을 보여주는게 좀더 좋을 것 같아서 이렇게 했는데, 막상 그래프가 이쁘지 않아서, 괜히 한거 같기도 하고, 이렇게 작업하자고 먼저 제안을 했었는데, 괜히 나때문에 팀원들한테까지 피해를 끼친것 같아 마음이 씁쓸하다. 솔직히 차트를 그리는데 쓰일 데이터 자료구조를 어느정도까지 추상화해야할지 많은 고민을 했었는데, 프로젝트 당시 내 실력으로는 저게 제일 타당하다고 생각해서 아래와 같이 짰는데, 난해하다.</p>
<pre><code class="language-js"> const targetDateData = Array.from({ length: 144 }, (_, i) =&gt; ({ x: i, y: 0 }))

    stepsData[dayjs(startDate).format(&#39;YYYY-MM-DD&#39;)]?.records.forEach((record, i) =&gt; {
        const hourIndex = Math.floor((dayjs(record.crt_ymdt).hour() * 60 + dayjs(record.crt_ymdt).minute()) / 10)
        const currenStep = record.steps - (stepsData[dayjs(startDate).format(&#39;YYYY-MM-DD&#39;)]?.records[i - 1]?.steps || 0)
        targetDateData[hourIndex].y = currenStep
})</code></pre>
<h3 id="개발-완료-후-회고">개발 완료 후 회고</h3>
<p>: 차트의 기간을 하루, 1주일, 특정 시간 구간, 크게 이렇게 3가지로 나누고 작업을 했는데, 데이터 가공을 할때 자료구조를 잘못 생각했는지, 막상 데이터를 뿌려줄때 추가적인 작업이 많이 필요해서 깔끔하게 차트의 데이터를 뿌릴 수 없어서 많은 아쉬움이 있었다. 현재 이 글을 쓰는 시점이, 모아데이터 프로젝트를 완료하고 시간이 어느 정도 흐른 뒤에 쓰는 중인데, 지금은 자신있게 차트를 그릴 수 있는데 반해서 모아 데이터 프로젝트를 진행할때에는 차트를 짜맞추기식으로 하다보니 원하는 수준의 깔끔함을 추구할 수 없어서 많은 아쉬움이 남는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.31)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.31</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.31</guid>
            <pubDate>Tue, 31 May 2022 15:47:14 GMT</pubDate>
            <description><![CDATA[<h2 id="event-loop">Event Loop</h2>
<p>자바 스크립트는 <strong>싱글스레드</strong>다. 그말인즉슨, 한번에 한 가지 일(task)만 실행할 수 있다는 말이다. 워낙 실행하는 속도가 빠르기 때문에 별로 큰 문제자체는 아니다. 하지만 특정 task를 수행할때 특정 시간(예를 들면 1분 이상이라던지..)을 기다려야 한다면 큰 문제가 될 것이다. 5G를 보급하고 있는 시대에 해당 시간만큼 브라우저가 멈춰야한다면 사람들은 서비스를 쳐다도 보지 않고 떠날것이다. (자바스크립트는 브라우저의 메인 스레드를 이용해서 실행하고, 따라서 해당 시간만큼 UI를 그리는 작업을 포함해서 모인 작업이 올 스탑된다.)</p>
<p>이러한 문제점을 해결하기 위해서 브라우저는 Web API를 제공해준다.(DOM API, setTimeout, HTTP requests 등)  Web API를 통해서 우리는 싱글스레드인 자바스크립트를 비동기적으로, 그리고 논블락킹을 유지할 수 있게된다.</p>
<p>자바스크립트 엔진에서는 함수가 실행되면 <strong>call stack</strong>에 쌓이게 된다. <strong>call stack</strong>에 쌓인 함수는 first in, last out의 순서로 작업이 수행된다. 
<img src="https://res.cloudinary.com/practicaldev/image/fetch/s--44yasyNX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://devtolydiahallie.s3-us-west-1.amazonaws.com/gid1.6.gif" alt="call stack"></p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_n4m4HH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif2.1.gif" alt=""></p>
<p><strong>call stack</strong>이 비어 있으면, <strong>event look</strong>는 <strong>callback queue</strong>에 작업이 남아있는지 확인하고, 작업이 남아있다면 call stack으로 이동시킨다.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b2BtLfdz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif4.gif" alt=""></p>
<pre><code class="language-js">
const foo = () =&gt; console.log(&quot;First&quot;);
const bar = () =&gt; setTimeout(() =&gt; console.log(&quot;Second&quot;), 500);
const baz = () =&gt; console.log(&quot;Third&quot;);

bar();
foo();
baz();</code></pre>
<p>위의 코드가 <strong>call stack</strong>과 <strong>web api</strong>, <strong>queue</strong>에서 어떤 순서로 머물다가 이벤트 루프에 의해서 다시 call stack을 거쳐 실행되는지 잘 생각해보고, 동작 과정을 잘 이해하길 바란다, 나놈.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BLtCLQcd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif14.1.gif" alt=""></p>
<h4 id="회고">회고</h4>
<p>아침에 진짜 죽을듯이 아프고, 토하면서 겨우 걸어가서 요로결석 진단받고 돌깨고 치료하고 오는데 그렇게 가뿐할 수가 없었다. 저녁에는 모의면접에서 나의 무지가 들어날까 노심초사하다가 막상 끝나니 현실적인 면접자의 내 위치를 파악할 수 있어서 그렇게 개운할 수가 없었다. 물론 면접은 어렵다. 본디 공부에 어울리는 사람은 아니라서 당연히 어려울수밖에 없다. 좀 더 deep하게 준비할 것이 전체적인 피드백이라고 생각한다. 내가 경험한 것에 대한 장단점을 추리고, 거기서 내 자신을 피드백하며 시간의 흐름축을 따라 내 능력과 연봉이 함께 증가하길 바란다. 좋은 기회를 제공해주신 준혁님과 수영님에게 감사함을 멀리서나마 보내고 싶다. 모의면접에 나온 내용들에 대해서는 따로 준비해서 내 언어로 바꿔두도록 하자. 언제든지 자신있게 말할수 있게. 프론트엔드 개발자로 성장하게 된다면, 오늘 모의면접도 많은 영양분으로 작용할 것이다. + 유명한 라이브러리의 소스코드를 보면서 리액트로 왜 이렇게 짜는지 생각해보고 많은 사람들이 짜는 방식에 대해 고려해보기</p>
<h4 id="찾아보고-확실하게-이해해야-할-것">찾아보고 확실하게 이해해야 할 것</h4>
<ol>
<li><p>callback vs Promise 차이</p>
</li>
<li><p>CORS 관련(브라우저 스펙이고, response 헤더가 하는 역할 등)</p>
</li>
<li><p>useCallback, useMemo, useRef 훅은 언제, 왜, 어떤 기준으로 사용할 것인가</p>
</li>
<li><p>이벤트 캡처링 vs 버블링</p>
</li>
<li><p>렉시컬 스코프와 클로저</p>
</li>
<li><p>브라우저 동작 과정, 그리고 가져온 static 파일(HTML)을 어떻게, 어떤 순서로 그리는가.</p>
</li>
<li><p>웹 스토리지, 쿠키 등의 의미 및 용도 차이점</p>
</li>
<li><p>Https 동작 방식에 대한 이해</p>
</li>
<li><p>CSR vs SSR 각 각에 대한 설명 및 언제 사용하고, 언제 각 각의 렌더링이 이득일지에 대한 이해</p>
</li>
<li><p>this</p>
</li>
<li><p>Redux 등의 동작 방식 <a href="https://ko.redux.js.org/tutorials/fundamentals/part-1-overview/#data-flow">공식 문서</a></p>
</li>
<li><p>함수형 컴포넌트의 진득한 이해</p>
</li>
<li><p>useState 등이 어떻게 동작되는지 뜯어보기</p>
</li>
<li><p>웹팩에 대한 경험은 해볼 수록 좋다.</p>
</li>
<li><p>useEffect의 훅이 어떻게 동작하는가. 뎁스 등을 비교하는 방식</p>
</li>
<li><p>여러개의 useEffect가 있을지 각각 몇번 찍히는 지에 대해 생각해보기. -&gt; 리렌더링이 어떠한 과정으로 진행되고, 어떤 값들을 달라지고 유지되는지</p>
<pre><code class="language-js">const App = () =&gt; {
const [,setValue] = useState(1);

const intValue = 1;
const obj = {};
useEffect(() =&gt; {
  setTimeout(() =&gt; {
  setValue(prev =&gt; prev + 1)
}
}, [])

useEffect(() =&gt; {
console.log(intValue)
}, [intValue])

useEffect(() =&gt; {
  console.log(obj)
}, [obj])

return &lt;div&gt;Good&lt;/div&gt;
}</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.24)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.24</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.24</guid>
            <pubDate>Tue, 24 May 2022 13:55:52 GMT</pubDate>
            <description><![CDATA[<h4 id="css-관련">css 관련</h4>
<ul>
<li><p>웹 폰트 문제점
  <img src="https://velog.velcdn.com/images/bu-geon/post/6ec2198f-ff52-47e4-b4a8-46518efc16cb/image.png" alt=""> 웹 폰트로 &#39;Not&#39;을 강조하려고 했지만 로딩이 늦어져서&#39; Not&#39;이 없는 상태로 노출됨. 짧은 시간이지만 의미가 와전되어서 정반대의 내용으로 사용자에게 전달될 수 있음</p>
</li>
<li><p>웹 폰트 최적화</p>
<ol>
<li>WOFF 형식의 폰트로 용량 자체를 줄이기</li>
<li>font-display 형식 표기: 웹 폰트의 로딩 상태에 따른 동작을 설정 가능
 <code>font-display: blcok</code> - 웹 폰트가 로동되지 않았을 때는 텍스트 렌더링 x(최대 3초만), 웹 폰트 로딩이 완료되면 웹 폰트를 적용
<img src="https://velog.velcdn.com/images/bu-geon/post/e27cef78-926d-401c-821f-0866656a3070/image.png" alt=""></li>
</ol>
<p>  <strong><code>font-display: swap</code></strong> - FOUT 방식과 동일하게 작동. 폴백 폰트로 글자를 렌더링하고, 웹 폰트 로딩 완료시 폰트 적용(항상 텍스트가 보임)
  <img src="https://velog.velcdn.com/images/bu-geon/post/fe76cfb8-c8af-47af-84b0-edace7aa8e63/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>button 태그에 텍스트를 넣든 넣지않든, 웹 접근성?을 위해서 <code>aria-label</code> 속성은 꼭 입력하도록 하자</li>
<li><code>&lt;address&gt;</code>: 기존에 <code>&lt;address&gt;</code>는 주로 작성자의 연락처만 나타내는 요소였지만, 최신에는 임의의 연락처도 포함이 가능해졌다. 단, 연락처 외의 정보(출판일 등)를 담아서는 안된다. <code>&lt;address&gt;</code> 요소의 콘텐츠가 제공하는 연락처 정보는 현재 맥락에 적절한 아무 형태나 취할 수 있으며, 물리적 주소, URL, 이메일 주소, 전화번호, SNS 식별자, 좌표 등 어떠한 정보라도 포함할 수 있습니다. 반드시 포함해야 하는 정보는 연락처가 가리키는 개인, 조직, 단체의 이름이다.<pre><code class="language-html">// 예제 1
&lt;p&gt;Contact the author of this page:&lt;/p&gt;
</code></pre>
</li>
</ul>
<address>
  <a href="mailto:jim@rock.com">jim@rock.com</a><br>
  <a href="tel:+13115552368">(311) 555-2368</a>
</address>

<p>// 예제 2</p>
<address>
  You can contact author at <a href="http://www.somedomain.com/contact">
  www.somedomain.com</a>.<br>
  If you see any bugs, please <a href="mailto:webmaster@somedomain.com">
  contact webmaster</a>.<br>
  You may also want to visit us:<br>
  Mozilla Foundation<br>
  331 E Evelyn Ave<br>
  Mountain View, CA 94041<br>
  USA
</address>
```
- `<legend>`: 주로 fieldset, 차트나 그래프 등의 캡션을 정의할 때 사용
```html
<form action="/examples/media/action_target.php" method="get">
    <fieldset>
        <legend>학사 관리 로그인</legend>
        이름 : <input type="text" name="st_name"><br>
        학번 : <input type="text" name="st_id"><br>
        학과 : <input type="text" name="department"><br>
        <button type="submit">제출하기</button>
    </fieldset>
</form>
```

<h4 id="성능테스트-방법">성능테스트 방법</h4>
<ol>
<li>Chrome의 검사 -&gt; Performance 탭에서 새로고침시 성능테스트 가능</li>
<li>Lighthouse 시크릿 모드로 성능 테스트하면 score랑 개선 가능한 것들을 알려줌</li>
</ol>
<h4 id="유용한-도구">유용한 도구</h4>
<ul>
<li>storybook</li>
<li>chromatic</li>
<li>zeplin</li>
<li>code climate</li>
</ul>
<h4 id="코딩스타일">코딩스타일</h4>
<p><img src="https://velog.velcdn.com/images/bu-geon/post/f6694244-0cfb-43d9-bad1-363309a12b2c/image.png" alt="">
그저 감탄뿐이었던 코드. 기존에 나라면 const symbolIcon따로 지정후 sybolIcon[symbol]로 다시 접근했겠지만, 생성과 동시에 바로 필요한 값만 변수에 저장이 가능하다. 리액트를 사용하는 프론트엔드 개발자라면 변수에 컴포넌트를 담을 수 있는 만큼 이 정도 센스있는 코딩을 해야한다. 진짜 이건 나도 인쇄해서 걸어두고 싶다.</p>
<h4 id="경제">경제</h4>
<ul>
<li>IRP 연금저축 계좌 가입시 연말정산에서 이득볼수 있는 금액이 크다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.22)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.22</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.22</guid>
            <pubDate>Sun, 22 May 2022 15:45:59 GMT</pubDate>
            <description><![CDATA[<h4 id="강의-회고">강의 회고</h4>
<ol>
<li><code>redux/toolkit</code> 사용시, <code>useSelector(() =&gt; {fn()})</code>이런식으로 쓰는 것보다 <code>useSelector(fun())</code> 이렇게 쓰도록 하자. 캐싱에서 이득을 볼 수 있음</li>
<li><code>resetState: () =&gt; INITIAL_STATE</code> is good</li>
<li>프론트엔드 개발자는 잔잔바리 업무에도 늘 최적화를 신경써야 한다.</li>
<li>debounce를 하더라도 aixos 갓 요청을 날린상태면 cancel을 시키는게 훨씬 효율적으로 보인다.</li>
<li>css attribute <code>all</code>속성: CSS all 단축 속성은 요소의 <span style="color: red"><strong>unicode-bidi (en-US), direction (en-US), CSS 사용자 지정 속성을 제외</strong></span>한 모든 속성을 초기화합니다. 초깃값, 상속값, 아니면 다른 스타일시트 출처의 값으로 설정할 수 있습니다. 출처: <a href="https://developer.mozilla.org/ko/docs/Web/CSS/all">MDN</a></li>
<li><strong><code>D3.js</code></strong>가 대장격 모듈이고 거기서 파생된 웹차트 라이브러리가 대부분이다. 그 중에서 <strong><code>victory.js</code></strong>가 설명이 잘 되어있고, 커스텀이 용이하다.</li>
<li><span style="color: orange"><strong>swagger</strong></span>를 이용시 백엔드와 소통하기가 좋다. 단, CORS는 해결해주지 못한다.</li>
<li><span style="color: blue"><strong>postman</strong></span> 이용시 CORS 문제도 없고, 미리 api를 통해 호출된 값을 확인할 수 있어서 좋다. <a href="https://www.postman.com/">포스트맨-신촌을 못가</a></li>
<li>Javascript는 부동소수점 문제때문에 소수점 연산시 예상치 못한 결과를 야기한다. <code>bigNumber.js</code>와 같은 라이브러리를 이용하자 -&gt; 기본 세팅 필수적으로 보임</li>
<li>간단한 연산 결과 테스트는 jest를 이용하면 터미널에서 빠르게 확인가능</li>
</ol>
<h4 id="생각">생각</h4>
<ul>
<li>코딩을 할때, 늘 확실하게 하고 넘어가는 습관을 들이자. &#39;일단 이렇게 해두고, 다른거 해결하고 와서 해야지&#39;라는 마인드로 매번 코딩하다가 놓칠때가 많다. 빠르게 하려고 인라인 스타일 쓰는 습관 버리고, 간단한 것이라도 확실하게 css module에 넣도록 하자. </li>
<li>react 프로젝트시 프론트에 서버를 붙이는 것만으로 ssr이라고 할 수 있을까?</li>
<li>세상은 넓고, 개발 쩔게 잘하는 사람은 나이를 불문하고 참 많다. 더 열심히 하자 안그러면, 내가 너무 불리하다.</li>
<li>pyScript가 생겼다던데, 몇년 뒤에 javascript 무너뜨리고 pyScript가 그 자리를 꿰찰수 있을까..</li>
<li>갑자기 코딩하는게 힘들다. 손에 잘 안잡힌다 엉엉엉</li>
<li>시간날때 express 라이브러리 써서 간단한 서버 구현해보자</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.19)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.19</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.19</guid>
            <pubDate>Thu, 19 May 2022 13:56:19 GMT</pubDate>
            <description><![CDATA[<h3 id="typescript-enum-type">Typescript Enum type</h3>
<p>Enum 타입(열거형 타입)은 주로 상수들의 집합을 정의하는데 사용한다. Enum 타입을 이용하면 의도를 문서화하거나 특정 그룹으로 구분되는 집합을 더 쉽게 만들어서 관리할 수 있다. 숫자열거형과, 문자열열거형 타입을 제공한다.</p>
<h4 id="numeric-enums">Numeric enums</h4>
<pre><code class="language-typescript">enum Food {
  pizza,
  chicken,
  hamburger,
}</code></pre>
<p>초기화없이 사용할 경우 가장 첫번째 값으로 0부터 차례대로 대입된다.<code>(pizza=0, chicken=1, hamburger=2)</code> 원하는 값이 있으면, 선언적으로 값을 대입할수있는데, 따로 값을 대입하지 않으면 +1씩 자동으로 증가한다.</p>
<pre><code class="language-typescript">enum Food {
  pizza = 3,
  chicken = 100,
  hamburger, // 101
}</code></pre>
<p>사용법은 간단한데, 열거형 자체에서 프로퍼티로 접근해서 사용하면 된다.</p>
<pre><code class="language-typescript">enum Role {
  ADMIN,
  READ_ONLY,
  AUTHOR
}

const person = {
  name: &#39;GOD&#39;,
  age: 10001,
  role: Role.ADMIN
}

if (person.role === Role.ADMIN) {
  console.log(&#39;is admin!&#39;);
}</code></pre>
<h4 id="string-enums">String enums</h4>
<p>문자열 열거형도 사용이 가능하다. 대신 숫자형처럼 자동으로 증가하는 기능은 없다. String enum 타입이 Numeric enum 타입보다 좋은 점은 직렬화가 잘 되어 있어서, 의미를 바로 알 수 있다는 점이다.(숫자만으로는 이게 뭘 뜻하는지 알기 어려울수도 있음)</p>
<pre><code class="language-typescript">enum Direction {
  UP = &#39;UP&#39;,
  DOWN = &#39;DOWN&#39;,
  LEFT = &#39;LEFT&#39;,
  RIGHT = &#39;RIGHT&#39;
}</code></pre>
<h3 id="제네릭-타입generic-type">제네릭 타입(Generic type)</h3>
<p>설명을 뭐라고 해야할지 모르겠다..</p>
<pre><code class="language-typescript">function getParam&lt;Type&gt;(arg: Type): Type {
  return arg;
}

const myGetParam: &lt;Type&gt;(arg: Type) =&gt; Type = getParm;</code></pre>
<p><code>getParam</code> 함수는 제네릭 타입으로 정의된 함수이다. 제네릭 타입이 애니와 다른점은 만일 <code>Type</code>대신에 <code>any</code>를 사용했다면, 인수로 <code>number</code>타입이 들어와도 리턴 값으로 <code>string</code> 타입등 다른 타입을 반환해도 상관이 없다. 하지만 제너릭 타입을 사용하게 되면 유저가 넘긴 인수의 타입을 캡처하고, 이 정보를 반환 타입으로 다시 사용할 수 있게 된다.(즉, 인수와 리턴의 타입이 같다는 것을 보장)</p>
<pre><code class="language-typescript">const promise: Promise&lt;string&gt; = new Promise((resolve, reject)=&gt; {
  setTimeout(() =&gt; {
      resolve(&#39;Finished&#39;);
  }, 1500);
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.18)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.18</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.18</guid>
            <pubDate>Wed, 18 May 2022 14:27:59 GMT</pubDate>
            <description><![CDATA[<p>일반적으로 리액트 프로젝트를 진행하다가 에러가 발생할 경우 전체 프로젝트가 올 스탑한다. 그리고 흰 화면만 멍하니 쳐다볼 뿐..</p>
<h3 id="에러-경계error-boundaries">에러 경계(Error Boundaries)</h3>
<p>에러 경계는 하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하며, 깨진 컴포넌트 트리 대신 폴백 UI를 보여주는 React 컴포넌트다.
에러 경계는 렌더링 도중 생명주기 메서드 및 그 아래에 있는 전체 트리에서 에러를 잡아낼 수 있다.</p>
<h4 id="에러-경계가-포착하지-못하는-에러">에러 경계가 포착하지 못하는 에러</h4>
<ol>
<li>이벤트 핸들러</li>
<li>비동기적 코드(setTimeout, requestAnimationFrame 콜백)</li>
<li>서버 사이드 렌더링</li>
<li>자식에서가 아닌 에러 경계 자체에서 발생하는 에러</li>
</ol>
<p>에러 경계는 자바스크립트의 catch {} 구문과 유사하게 동작하지만 컴포넌트에만 적용된다. 오직 <strong>클래스 컴포넌트</strong>만 에러 경계과 될 수 있다.(똥..💩💩 hook으로 추가해주려고 한단다..)</p>
<p>React 측의 주장: 손상된 UI를 완전히 제거하는 것보다 그대로 남겨두는 것이 더 좋지 않다.
예를 들어 메신저와 같은 제품에서 손상된 UI를 그대로 남겨두면 누군가가 잘못된 사람에게 메시지를 보내게 될 가능성이 있습니다. 마찬가지로 결제 앱의 예를 들면 잘못된 금액을 보여주는 것이 아무 것도 렌더링하지 않는 것보다 더 나쁩니다.</p>
<p>근데 어이없는게, 에러 경계는 함수형 컴포넌트에서는 제공을 하지 않는다. 그래서 우리는 react-error-boundary 라이브러리를 통해서 class 컴포넌트를 배제해서 레거시하지 않게 보일 수 있다.
<a href="https://www.npmjs.com/package/react-error-boundary?activeTab=dependencies">react-error-boundary</a></p>
<p>이 라이브러리를 이용하면 <code>&lt;ErroBoundary&gt;</code>를 이용해서 간단하게 에러 경계를 명시할 수 있다.</p>
<pre><code class="language-js">import {ErrorBoundary} from &#39;react-error-boundary&#39;

function ErrorFallback({error, resetErrorBoundary}) {
  return (
    &lt;div role=&quot;alert&quot;&gt;
      &lt;p&gt;Something went wrong:&lt;/p&gt;
      &lt;pre&gt;{error.message}&lt;/pre&gt;
      &lt;button onClick={resetErrorBoundary}&gt;Try again&lt;/button&gt;
    &lt;/div&gt;
  )
}

const ui = (
  &lt;ErrorBoundary
    FallbackComponent={ErrorFallback}
    onReset={() =&gt; {
      // reset the state of your app so the error doesn&#39;t happen again
    }}
  &gt;
    &lt;ComponentThatMayError /&gt;
  &lt;/ErrorBoundary&gt;
)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.17)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.17</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.17</guid>
            <pubDate>Tue, 17 May 2022 17:06:11 GMT</pubDate>
            <description><![CDATA[<p>React에 어느정도 적응을 하면서, 간단한 구현정도는 쉽게 할수 있게 됐다. 하지만 정확한 라이프사이클을 이해하지 못해서 그런지, hook을 남발하게 되면서 불필요한 리렌더링을 남발하는거 같아서 라이프사이클을 간략하게 정리해보고자 한다.</p>
<h3 id="라이프-사이클feat-react">라이프 사이클(feat. React)</h3>
<p><img src="https://velog.velcdn.com/images/bu-geon/post/365ab0fb-72d3-4a70-a392-a9a8ab7f4e19/image.png" alt="">
우선 간략하게 리액트의 lifecycle을 살펴보자면, 하나의 컴포넌트가 내 자신의 삶이라고 가정할때 리액트의 라이프 사이클을 내 삶과 비유하면 아래와 같다.</p>
<ol>
<li><code>Initialization</code>: 내가 태어나기전, 부모님이 지어준 나의 이름, 내가 태어날 지역, 나를 낳아주신 부모님 기타 등등이 정해진다.</li>
<li><code>Mounting</code>: 나(컴포넌트)의 탄생</li>
<li><code>Updating</code>: 내가 커가면서 변하게 되는 것들.. 태어난 지역에서 이사를 간다던지.. 개명을 한다던지.. 친구가 생긴다던지.. 부모님이 돌아가신다던지 ㅠ</li>
<li><code>Unmounting</code>: 죽음(컴포넌트 지워짐) R.I.P</li>
</ol>
<h3 id="리액트-hooks-라이프-사이클feat-함수형-컴포넌트">리액트 Hooks 라이프 사이클(feat. 함수형 컴포넌트)</h3>
<p><img src="https://velog.velcdn.com/images/bu-geon/post/536f2c27-e61e-4d3b-8216-3eef39b52cc0/image.png" alt="">
<img src="https://velog.velcdn.com/images/bu-geon/post/f3b03771-cb27-41be-bb2b-7797477a4ba5/image.png" alt=""></p>
<p>| <a href="https://reactjs.org/docs/hooks-reference.html">https://reactjs.org/docs/hooks-reference.html</a></p>
<h4 id="회고">회고</h4>
<p>술을 먹지말자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.16)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.16</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.16</guid>
            <pubDate>Mon, 16 May 2022 14:43:11 GMT</pubDate>
            <description><![CDATA[<h2 id="corscross-origin-resurce-sharing">CORS(Cross-Origin Resurce Sharing)</h2>
<p>영어로 무슨말인지 모르겠는가? 한글로는 교차 출처 리소스 공유라고 한다. Of cors(course)! 한글로도 무슨 말이지 모르겠다. 공공데이터 포털에서 제공하는 api를 일반 여타 다른 api들처럼 쓰려고 하면 cors와의 첫 만남이 될 것이다.
<img src="https://velog.velcdn.com/images/bu-geon/post/da9adfca-a3fd-4107-91fe-d8312d55e14b/image.png" alt="fuckCors">
이론이 너무 어렵지만, 대충 웹 어플리케이션은 자신의 출처(도메인, 포로토콜, 포트)와 다른 리소스가 요청할때 교차 출처 HTTP 요청을 실행한다고 한다.</p>
<p><img src="https://velog.velcdn.com/images/bu-geon/post/f5a603be-81f2-4424-80f9-f1f267aa09ce/image.png" alt="">
일반적으로 Host 뒤에 포트 번호가 생략되어 있지만, <code>protocol + host + port</code>까지를 서버의 출처(Origin)이라고 한다.(포트가 생략되어 있다면 보통 80이라고 가정한다.) 즉, Cross-Origin은 한글로 교차 출처로 받아들이기 보다는 서버가 같은 출처가 아니라고 받아들이는게 더 편할거 같다.</p>
<h3 id="cors-해결-방법">CORS 해결 방법</h3>
<ol>
<li>별도 서버를 구축해서 서버를 중간에 두고 요청</li>
<li>cra로 생성한 react 프로젝트라면 package.json에 proxy를 설정하여 구축.</li>
</ol>
<h4 id="회고">회고</h4>
<p>아침에 눈을 뜨고 기분좋은 노래와 오늘도 힘차게 시작하는 코딩, 하지만 그 끝은 늘 광기와 분노뿐인거 같다. 모두 내가 실력이 부족하고, 아는게 없어서 그러겠지만.. 어쩌겠는가.. 우매한 인간이 프로그래머가 되려면 겪어야될 업인것을....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.15)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.15</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.15</guid>
            <pubDate>Sun, 15 May 2022 15:07:35 GMT</pubDate>
            <description><![CDATA[<h3 id="강의-회고">강의 회고</h3>
<ul>
<li>html 태그에서 <code>user-select</code>속성을 <code>none</code>으로 설정시 원하지 않는 텍스트 드래그 등을 방지할수있다.</li>
<li>git은 대소문자를 구분하지 않는다. 따라서 디렉토리명이나 파일명을 바꿀때 완전히 다른 이름으로 바꿨다가 수정하던지, git config 설정을 해주면 된다. <code>git config core.ignorecase false</code></li>
<li>axios 자체가 Promise 객체를 리턴하므로 추가 작업을 하는 것이 아니라면 굳이 asyn/await를 쓸 필요가 없다.(뭘 좀 쓰려면 함수가 어떤 구조인지 정도는 확인하자.)</li>
<li>scss의 <code>@include</code>는 코드를 그 위치에 그대로 두는 것이나 다름없다. 따라서 <code>@include</code> 보다는 필요한 것만 가져올 수 있는 <code>@use</code>를 사용하는 습관을 기르자.</li>
<li><code>font-family</code> 속성을 줄때 한글 영어 동시 지원하는 것을 앞쪽으로 배치해야, 한글과 영어가 따로따로 스타일이 적용되는 것을 막을 수 있다.</li>
<li><code>&lt;aside&gt;</code>태그는 본문이랑 상관없을때 쓴다.</li>
<li><code>&lt;dl&gt;</code>: definition list(용어를 정의하는 목록), <code>&lt;dt&gt;</code>:definition term(용어의 명칭), <code>&lt;dd&gt;</code>: definition description(용어의 설명 또는 값)<pre><code class="language-html">&lt;dl&gt;
&lt;dt&gt;사과&lt;/dt&gt;
&lt;dd&gt;맛있어&lt;/dd&gt;
&lt;/dl&gt;</code></pre>
<ul>
<li>태그의 속성중 <code>filter</code>, <code>backdrop-filter</code> 속성에 <code>blur()</code> 값을 줘서 간단하고 쉽게, 남들보다 본새나는 스타일을 만들어낼 수 있다.</li>
<li>router 쓸때 검색 query를 주소(?)에 같이 넣어주는것이 훨씬 용이하다.(주소에 쿼리스트링 추가)</li>
<li>api 요청할때 <code>try-catch-finally</code>는 꼭 쓰자</li>
<li><code>text-transform</code> 속성을 주면 전부 대문자, 소문자 등 간다낳게 조작이 가능하다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.13)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.13</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.13</guid>
            <pubDate>Fri, 13 May 2022 17:00:11 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/bu-geon/post/cfee8c85-ad18-432b-9d84-7b1228af887b/image.gif" alt=""></p>
<h3 id="회고">회고</h3>
<p>아직 완성은 아니지만, 미리 배포 테스트를 하기 위해서 빌드를 해봤다. 처음에는 코드도 깔끔하게 짜려고 설계도 하고 했었는데, 시간이 지날수록 여기저기서 터지는 버그를 잡으려고 왔다갔다 하다보니 코드가 점점 지저분해진다. ㅠ
검색 쿼리 바뀔때마다 api를 call해서 디바운싱 구현해보려고 했는데, 두뇌의 한계다. 포탈로 모달 띄우는건 성공했는데 모달 영역밖 클릭하면 모달창 닫게끔 구현하려고 하는데 타입스크립트때문에 한계에 봉착했다. 슬픈 타입인생 ㅠ</p>
<h3 id="non-null-assertion-typescript">Non null Assertion (TypeScript)</h3>
<p><img src="https://velog.velcdn.com/images/bu-geon/post/f59f35f2-44db-48be-94ae-b300de366995/image.png" alt="">
modal창을 root에 붙이기위해 react portal을 사용하던 중 typescript에러가 발생했다. <code>creatPortal</code>의 두번째 인자로 Element 형식이 들어가야하는데, <code>document.getElementById(&#39;root&#39;)</code>에서 null이 발생할수도 있다고 판단해서 생기는 오류 같았다. null이 발생할 수 있는 곳의 후미에 <code>!</code>를 붙이게되면 null이 들어오지 않는다고, 단언(?)할 수 있다.  <code>document.getElementById(&#39;root&#39;)!</code> non-null assertion을 통해서 해당 오류를 해결할 수 있었지만, 뭔가 깔끔하게 해결한거 같지 않다. 또, 찾아보니까 eslint 등에서도 추천하는 방법은 아닌데, 다행스럽게도(?) 내가 설정한 린트에서는 통과해줘서 일단 써먹긴했다. 타입스크립트를 정확히 이해하지 못해서 그런거 같은데, 시간이 있을때 좀더 이론적으로 알아봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.12)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.12</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.12</guid>
            <pubDate>Thu, 12 May 2022 14:28:11 GMT</pubDate>
            <description><![CDATA[<h3 id="infinite-scroll">Infinite Scroll</h3>
<p>방대한 양의 데이터를 한번에 가져오려면 용량도 너무 크고, 시간도 오래 걸린다. 따라서, 화면에 보여줄수 있는 적당한 단위로 나눠서 차례차례 가져오는 방법을 주로 사용한다. 주로 <code>pagination</code>과 <code>infinite scroll</code>을 사용하는데, 모바일 웹과 일반 웹의 경계가 많이 허문 요즘에는 <code>infinite scroll</code>이 더 선호되는듯 하다.</p>
<h4 id="scroll-event">Scroll Event</h4>
<p><img src="https://blog.kakaocdn.net/dn/vBXH4/btrfgY2TCCk/ZgElTamOYbguTUHsrtBmBK/img.png" alt="offset">
단순하게 스크롤 이벤트가 동작할때, client에게 실제로 보여주는 부분과 scroll로 감쳐진 부분을 더해서 전체 스크롤의 크기와 같은지 비교하는 방식이다. 구현하는 것은 간단하지만, scroll 이벤트시 많은 동작이 발생하기때문에, 디바운싱 혹은 쓰로틀링 같은 기법을 동원해서 빈번한 이벤트의 빈도를 핸들링할 수 있어야 한다.</p>
<h4 id="intersectionobserver--useref">IntersectionObserver &amp; useRef</h4>
<p>IntersectionObserver와 useRef를 활용한 방식은 react에서 사용하는 기법인데, 스크롤 최하단의 마지막 요소나, 연속적인 리스트 요소 아래에 인위적인 DOM을 하나 두워서 IntersectionObserver 객체가 client에게 보여질때 비동기 방식을 이용해서 추가적으로 데이터를 받아오는 동작을 트리거한다.</p>
<p><strong>IntersectionObserver 생성</strong></p>
<pre><code>
let options = {
  root: document.querySelector(&#39;#scrollArea&#39;),
  rootMargin: &#39;0px&#39;,
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);</code></pre><p><code>IntersectionObserver()</code> 생성자에 전달되는 options 객체는 observer 콜백이 호출되는 상황을 조작한다.</p>
<p><code>root</code>
대상 객체의 가시성을 확인할 때 사용되는 뷰포트 요소(대상 객체의 조상 요소) 기본값은 브라우저 뷰포트, root 값이 null 이거나 지정되지 않을 때 기본값으로 설정
<code>rootMargin</code>
root 가 가진 여백. 이 속성의 값은 CSS의 margin 속성과 유사합니다. e.g. &quot;10px 20px 30px 40px&quot; (top, right, bottom, left). 이 값은 퍼센티지가 될 수 있다. root 요소의 각 측면의 bounding box를 수축시키거나 증가시키며, 교차성을 계산하기 전에 적용된다. 기본값은 0입니다.
<code>threshold</code>
observer의 콜백이 실행될 대상 요소의 가시성 퍼센티지를 나타내는 단일 숫자 혹은 숫자 배열입니다. 만일 50%만큼 요소가 보여졌을 때를 탐지하고 싶다면, 값을 0.5로 설정하면 됩니다. 혹은 25% 단위로 요소의 가시성이 변경될 때마다 콜백이 실행되게 하고 싶다면 [0, 0.25, 0.5, 0.75, 1] 과 같은 배열을 설정하세요.
기본값은 0이며(이는 요소가 1픽셀이라도 보이자 마자 콜백이 실행됨을 의미합니다). 1.0은 요소의 모든 픽셀이 화면에 노출되기 전에는 콜백을 실행시키지 않음을 의미.</p>
<h4 id="회고">회고</h4>
<p>비동기적으로 작동할때 에러를 찾아내는 것은 너무 힘들다. 순서가 뒤죽박죽이라서 정확한 에러의 원인을 찾기가 애매하다. 
오늘은 인피니트 스크롤과 input에서 검색 query를 현재 onChange 이벤트가 발생할때마다 api를 call하기 때문에 성능을 개선하고자 디바운싱을 해보려 했는데 실패했다. 인피니트 스크롤은 일단 구현은 했는데, 마지막 요소에서 다음 페이지만 불러와야하지만, 스크롤 속도가 빠르면 여러 페이지를 연속적으로 콜한다. 또한. 다음 페이지가 있는지 검사를 한 후에 api를 call 해야 하는데, 이 부분이 제대로 동작하지 않는지 다음페이지가 없어도 계속해서 page를 증가시켜가며 call을해서 수정이필요하다.
디바운싱은 조금이나마 높아졌던 리액트에 대한 내 자신감을 완적히 꺽어놨다. 이론은 쉽게 이해한데 반해서 구현할 방법이 도무지 떠오르지 않았다. 비동기적으로 그리고 리액트가 동작하는 방식을 아직 정확히 습득하지 못했기 때문인듯한데, 너무 암울하다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.11)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.11</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.11</guid>
            <pubDate>Wed, 11 May 2022 15:20:28 GMT</pubDate>
            <description><![CDATA[<h3 id="recoilroot">RecoilRoot</h3>
<p>recoil의 상태를 전역으로 사용하기위해서 전역에 <code>RecoilRoot</code>를 선언해줘야 한다. 루트 컴포넌트가 제일 좋은 장소이긴 하지만, 사용하는 scope에 따라서 적절하게 배분해주는 것이 더 효율적으로 보인다.</p>
<pre><code>import { RecoilRoot } from &#39;recoil&#39;;

function App() {
  return (
    &lt;RecoilRoot&gt;
      ~
    &lt;/RecoilRoot&gt;
  );
}</code></pre><h3 id="atom">Atom</h3>
<p><code>atom</code>은 쉽게 얘기하면 <code>state</code>다.(실제로는 상태의 일부를 나타낸다.) atoms는 <code>ReccoulRoot</code>의 하위에서는 어떤 컴포넌트에서든 읽고 쓸 수 있다. atom의 값을 읽는 컴포넌트들은 암묵적으로 <code>atom</code>을 구독하고 있다. 따라서, <code>atom</code>에 변화가 있으면 해당 <code>atom</code>을 구독하는 모든 컴포넌트들이 re-render된다.</p>
<pre><code>const textState = atom({
  key: &#39;textState&#39;, // unique ID (with respect to other atoms/selectors)
  default: &#39;&#39;, // default value (aka initial value)
});</code></pre><p>컴포넌트가 atom을 읽고 쓰게 하기 위해서는 <code>useRecoilState()</code>를 아래와 같이 사용하면 된다.</p>
<pre><code>function CharacterCounter() {
  return (
    &lt;div&gt;
      &lt;TextInput /&gt;
      &lt;CharacterCount /&gt;
    &lt;/div&gt;
  );
}

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) =&gt; {
    setText(event.target.value);
  };

  return (
    &lt;div&gt;
      &lt;input type=&quot;text&quot; value={text} onChange={onChange} /&gt;
      &lt;br /&gt;
      Echo: {text}
    &lt;/div&gt;
  );
}</code></pre><p>recoil에서는 <code>useResetRecoil(state)</code>을 통해서 상태를 기본값으로 쉽게 초기화할 수 있다. 멘토님께서는 이를 더 편하게 관리하기 위해서 customHook을 만들어서 사용중이시던데, 아직 익숙하지 않아서 좀더 이건 코드를 볼 필요가 있을것 같다.</p>
<h3 id="debounce-vs-throttling">Debounce vs Throttling</h3>
<p>보통 검색을 위해 사용하는 input에서는 onChange 이벤트를 통해서 api를 호출하게 되는데, 타이핑할때마다 api를 호출하게되면 같은 작업을 빈번하게 실행하게 되어 성능 저하 이슈가 발생할 수 있다.
따라서, 작업을 일정간격으로 조절해서 api를 한번만 호출하게끔 제어를 한다. 가장 대표적인 방법이 디바운싱과 쓰로틀링이다.
<img src="https://esstudio.site/uploads/throttle_debounce.gif" alt="디바운싱쓰로틀링">
초록색 선이 작업이 발생되는 빈도라면, 디바운싱과 쓰로틀링(빨간색 선)을 거치면서 설정한 시간에 따라서 작업을 수행하게된다.</p>
<ul>
<li><strong>debounce</strong>: 세팅한 시간 간격동안 발생하는 이벤트 중에서 처음 또는 마지막 이벤트만 실행시키는 방식이다.<pre><code>let timer;
if (timer) clearTimeout(timer);
timer = setTimeout(() =&gt; {
~
});
</code></pre></li>
</ul>
<pre><code>
- **throttle**: 이벤트가 동작하면 동작 실행 후 일정 간격동안에 들어오는 이벤트는 무시하는 방식이다.</code></pre><p>let timer;
if (!timer) {
  timer = setTimeout(() =&gt; {
    timer = null;
      ~
  }, ms)
}</p>
<p>```</p>
<h4 id="회고">회고</h4>
<p>무한스크롤을 하는 방법이 대체적으로 3가지가 있고, 요새는 주로 2가지 방식이 쓰이는거 같다. 내가 좀더 이해하기 쉬운 방식으로 짜보려고하는데 잘 안되어서 눈물이난다. 이게 슬퍼서 흐르는 눈물인지, 모니터 많이봐서 흐르는 눈물인지 분간할 수가 없네 떼잉..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.10)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.10</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.10</guid>
            <pubDate>Tue, 10 May 2022 15:08:03 GMT</pubDate>
            <description><![CDATA[<h3 id="generator">generator</h3>
<p>MDN에 쓰여있는 기본 사용 형태</p>
<pre><code>function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

var g = gen(); // &quot;Generator { }&quot;</code></pre><p>generator 함수는 <code>*</code>을 붙여서 일반함수와 구분을 주는데, arrow function 형태로는 사용이 불가능하다. 주로 사용하는 메소드로는 <code>Generator.prototype.next()</code>가 있는데 yield된 값을 반환해준다.</p>
<p>제너레이터 함수는 함수의 실행을 yield된 지점에서 멈추고, 다시 재개할 수 있다. yield된 시점에서 값을 반환(<code>{ value: value, done: true|false }</code>하고, 이를 이용해서 원하는 값을 하나씩 꺼내 사용할 수 있는 장점이 있다. 배열과 달리 값을 미리 만들어놓지 않으므로, 불필요한 메모리를 세이브할 수 있는 장점이 있다. 따라서 필요한 순간에 값을 계산해서 전달하기 때문에 메모리 측면에서 효율적이라고 한다. 함수내에서는 yield 키워드만 사용할 수 있는 것이 아니고 return 키워드를 통해서 일반 함수와 같이 제너레이터함수의 종료도 명시가 가능하다.</p>
<pre><code>function* testGenerator() {
  console.log(&#39;첫번째&#39;);
  yield 1;
  console.log(&#39;두번째&#39;);
  yield 2;
  console.log(&#39;세번째&#39;);
  console.log(&#39;네번째&#39;);
  yield 3;
  console.log(&#39;다섯번째&#39;);
  return &#39;finished&#39;;
}

const tGen = testGenerator(); // 제너레이터 객체 생성
console.log(tGen.next()); 
// 첫번째
// {value: 1, done: false}
console.log(tGen.next()); 
// 두번째
// { value: 2, done: false }
console.log(tGen.next());
// 세번째
// 네번째
// {value: 3, done: false}
console.log(tGen.next());
// 다섯번째
// {value: &#39;finished&#39;, done: false}
</code></pre><h3 id="회고">회고</h3>
<ul>
<li>githubID: <strong><span style="color:  #00254d">begin0dev</span></strong> 이 분 코드 스타일 참고하자(&quot;이 코드 어떻게 합칠지 생각해보시면 재밌을거에요.&quot; ??)</li>
<li>쓰로틀링, 디바운싱의 간격은 300ms가 적당한데, 가능하면 서버 파트랑 얘기해보는 것도 좋다.(터지면 서버에서 노발대발하니까)</li>
<li><strong><span style="color: #960000">type으로 any쓸꺼면 Typescript 왜 쓰냐고!!!</span></strong></li>
<li><strong>js 커링을 공부해보자.</strong></li>
<li>클라이언트랑 서버는 서로 믿으면 안된다.</li>
<li>깃에 올리는 파일중에 공개되지 않았으면 하는 값들은, <code>.env</code>에 환경변수로 설정해서 사용하자
<code>js: process.env.REACT_APP_변수명</code>
<code>.env: REACT_APP_변수=값</code>
참고로 <code>REACT_APP_</code> 는 예약어이므로 꼭 prefix로 변수명 앞에 붙여줘야한다.</li>
<li>리코일을 사용할 때, 가능하면 <code>atom</code>정도에서 끝내고, 백번 양보해서 <code>selector</code>에서는 인간적으로 끝내자.</li>
<li>visual 관련된건 css에서 처리해라 ➔ 엄청 긴 코드가 한줄로 변하는 매직이 발생하기도 한다. 고로 html이랑 css 공부도 게을리하면 안된다. FE개발자라면</li>
<li>다국어지원, BabelEDIT: 이건 나만 알꺼임</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.09)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.09</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.09</guid>
            <pubDate>Mon, 09 May 2022 02:20:08 GMT</pubDate>
            <description><![CDATA[<h3 id="typescript-설치">TypeScript 설치</h3>
<p>새로운 프로젝트 생성</p>
<pre><code>npx create-react-app my-app --template typescript</code></pre><pre><code>yarn create react-app my-app --template typescript</code></pre><p>기존 프로젝트에 씌우기</p>
<pre><code>npm install --save typescript @types/node @types/react @types/react-dom @types/jest</code></pre><pre><code>yarn add typescript @types/node @types/react @types/react-dom @types/jest</code></pre><p>기존의 ~.js -&gt; ~.tsx 후 restart your development server</p>
<h3 id="axios">axios</h3>
<h4 id="axios란">axios란?</h4>
<p><strong>Promise API를 활용하는 <span style="color: orange">HTTP 비동기 통신 라이브러리</span></strong></p>
<ul>
<li>GET 요청<pre><code>onst axios = require(&#39;axios&#39;);
</code></pre></li>
</ul>
<p>// 지정된 ID를 가진 유저에 대한 요청
axios.get(&#39;/user?ID=12345&#39;)
  .then(function (response) {
    // 성공 핸들링
    console.log(response);
  })
  .catch(function (error) {
    // 에러 핸들링
    console.log(error);
  })
  .then(function () {
    // 항상 실행되는 영역
  });</p>
<p>// 선택적으로 위의 요청은 다음과 같이 수행될 수 있습니다.
axios.get(&#39;/user&#39;, {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // 항상 실행되는 영역
  });  </p>
<p>// async/await 사용을 원한다면, 함수 외부에 <code>async</code> 키워드를 추가하세요.
async function getUser() {
  try {
    const response = await axios.get(&#39;/user?ID=12345&#39;);
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}</p>
<pre><code>
### Array.at()
ES 몇에 추가된지는 정확히 모르겠지만, 양수, 음수를 모두 이용해서 해당 인덱스에 해당하는 값에 바로 접근이 가능하다. 음수를 대입시 뒤에서부터 접근을 할 수 있어서, 유용해 보인다.</code></pre><p>const array = [1, 2, 3, 4, 5]</p>
<p>console.log(array[array.length - 1]
// expected: 5
console.log(array.at(-1))
// exptected: 5
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.08)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.08</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.08</guid>
            <pubDate>Sun, 08 May 2022 16:01:38 GMT</pubDate>
            <description><![CDATA[<h3 id="typescript-기본-형태">TypeScript 기본 형태</h3>
<pre><code>interface 이름 {
    변수명: type
}</code></pre><h3 id="오늘의-팁">오늘의 팁</h3>
<ol>
<li>데드라인은 늘 여유기간을 확보하자(테스트, 에러 핸들링에 많은 시간이 소요될 수도 있다.)</li>
<li><code>localStorage</code>대용으로 <code>store.js</code>라이브러리가 유용</li>
<li>기본 alert사용 금지 ➔ <span style="color: red">alert 발동되면 js 코드가 멈춤</span>, <code>seetAlert</code> 라이브러리 추천</li>
<li>프론트엔드 개발자라면 유저 사용성을 늘 고려하자.</li>
<li><code>useMemo</code>의 Dependency도 <code>useMemo</code>를 사용해줘야한다.</li>
<li><code>useMemo</code>는 주로 변수용, <code>useCallback</code>은 함수용으로 사용(둘다 연산량이 많지 않으면 자제하는 것이 좋다.)</li>
<li>if문 거대하게 하지말것 ➔ 거대해진다면 역 조건문 고민해볼것</li>
<li><code>setTimeout</code> - <code>clearTimeout</code>은 늘 쌍으로 선언하자(unMount시에 꼭 clearTimeout해줘야함)</li>
<li><code>context</code>의 대안으로 <span style="color: blue"><strong><code>redux</code></strong></span>나 <span style="color: purple"><strong><code>recoil</code></strong></span>을 추천(context는 퍼포먼스가 썩 좋지는 않다. recoil 사용시에 key값을 &#39;#&#39;으로 사용해주면 구분하기 좋다.)</li>
<li>면접관이 &quot;form enter키 반응하도록 해주세요~&quot;라고 질문했을때 onSumbit 안쓰면 그냥 프론트 때려쳐라</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.05)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.05</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.05</guid>
            <pubDate>Thu, 05 May 2022 12:07:30 GMT</pubDate>
            <description><![CDATA[<h4 id="git-branch-이동">git branch 이동</h4>
<ul>
<li><code>git switch [-c] branch_name</code></li>
<li><code>git checkout [-b] branch_name</code></li>
</ul>
<p>둘다 깃 branch를 이동할때 쓰이며, switch는 -c 옵션을, checkout은 -b 옵션을 통해서 branch를 생성하면서 이동이 가능</p>
<h4 id="git-switch-span-stylecolor-redvsspan-git-checkout">git switch <span style="color: red">vs</span> git checkout</h4>
<h4 id="git-branch-관련명령어">git branch 관련명령어</h4>
<ul>
<li><code>git branch --all</code>: remote의 모든 branch 확인</li>
<li><code>git branch --merged</code>: merged된 상태의 브랜치만 확인</li>
<li><code>git branch --no-merged</code>: merged되지 않은 상태의 브래치만 확인</li>
<li><code>git branch -d branch_name</code>: local의 branch 제거</li>
<li><code>git push origin --delete branch_name</code>: local에서 제거한 branch를 remote에 반영</li>
<li><code>git branch --move current_name new_name</code>: branch 이름 변경</li>
<li><code>git push --set-upstream origin new_branch_name</code>: remote의 branch이름 변경 반영</li>
<li><code>git log master..branch_name</code>: master branch와 원하는 branch사이의 log 확인</li>
</ul>
<h4 id="좀더-git이-익숙해지면-활용해보기-좋은-명령어">좀더 git이 익숙해지면 활용해보기 좋은 명령어</h4>
<ul>
<li><code>git blame</code></li>
<li><code>git bisect [good|bad|reset]</code></li>
<li><code>git reset --hard HEAD</code>: local에서 작업한 내용 초기화</li>
</ul>
<h4 id="회고">회고</h4>
<p>local에서 작업을 할때, 스스로 너무 지저분하게 작업하고 있는 것에 대해 반성을 한다. git의 branch기능을 이용해서 기능 단위별로 잘 나누고, 필요에 따라서는 commit도 잘게 나눌 필요가 있다고 생각이 들었다. 특정 기능을 구현하는 중에 막히게 되면, 따른 기능을 구현하려고 하는 경향이 있는데, 하나의 branch에서 작업하는 습관을 고치려고 노력해봐야 겠다.😩
또, lint 등의 프로젝트 foundation?을 잡아두고 협업을 하고 있는 것은 처음인데, 팀원들과 어느정도 형태는 비슷해져서 좋은데 아직 내가 너무 익숙하지 못해서 많이 벅차다.😭😭</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.04)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.04</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.04</guid>
            <pubDate>Wed, 04 May 2022 13:14:14 GMT</pubDate>
            <description><![CDATA[<h4 id="css만으로-x-버튼-만들기">css만으로 x 버튼 만들기</h4>
<p>다양한 svg 파일은 무료로 쉽게 구할수 있지만, 간단한 모양은 css만으로 쉽게 해결이 가능하다. <code>::before</code>속성과 <code>::after</code>를 이용해서 얇은 막대모양을 만들어 각각 45도, -45도 회전해서 x모양을 만들수 있다.</p>
<iframe width="100%" height="300" src="//jsfiddle.net/Bugeon/5d1Ltx3m/60/embedded/result,html,css" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>


<h4 id="react-router-이용해서-뒤로가기">react-router 이용해서 뒤로가기</h4>
<p>react-router v6 설치</p>
<pre><code>npm install react-router-dom@6</code></pre><p><code>react-router-dom-v6</code>에서는 <strong>useNavigate Hook</strong>을 이용하면 페이지 이동을 편하게 할 수 있다. <code>useNavigate()</code>가 리턴하는 함수를 이용해서 페이지를 이동할 수 있는데 아래와 같은 인자를 받는다.</p>
<pre><code class="language-js">declare function useNavigate(): NavigateFunction;

interface NavigateFunction {
  (
    to: To,
    options?: { replace?: boolean; state?: any }
  ): void;
  (delta: number): void;
}</code></pre>
<p>The navigate function has two signatures:</p>
<ol>
<li>Either pass a To value (same type as <Link to>) with an optional second { replace, state } arg or</li>
<li>Pass the delta you want to go in the history stack. For example, navigate(-1) is equivalent to hitting the back button.</li>
</ol>
<pre><code class="language-js">import { useNavigate } from &quot;react-router-dom&quot;;

function SignupForm() {
  const navigate = useNavigate();

  async function handleSubmit(event) {
    event.preventDefault();
    await submitForm(event.target);
    navigate(&quot;../success&quot;, { replace: true });
  }

  return &lt;form onSubmit={handleSubmit}&gt;{/* ... */}&lt;/form&gt;;
}</code></pre>
<h4 id="box-shadow-테스트하기-좋은-사이트">box-shadow 테스트하기 좋은 사이트</h4>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders/Box-shadow_generator">box-shadow generator</a></p>
<h4 id="하루-회고">하루 회고</h4>
<p>어머니, 전 css가 무섭습니다. 🫣</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL(22.05.03)]]></title>
            <link>https://velog.io/@bu-geon/TIL22.05.03</link>
            <guid>https://velog.io/@bu-geon/TIL22.05.03</guid>
            <pubDate>Tue, 03 May 2022 14:48:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/bu-geon/post/aa3311c3-6440-4037-b2c0-7aeea3644085/image.jpg" alt=""></p>
<h3 id="회고">회고</h3>
<ul>
<li>리액트 사용할 때 DOM에 직접 접근해서 값을 바꾸는 행위는 미친짓이다. 지양하자!!</li>
<li>email 정규식은 <a href="https://www.w3resource.com/javascript/form/email-validation.php">w3h 표준 정규식</a>을 사용하는게 마음이 편하다. -&gt; (<code>e.target.validity.valid</code>로도 browser에서 유효성 검사가 가능)</li>
<li><code>e.target</code>(이벤트 버블링 발생)보다는 <code>e.currentTarget</code>(이벤트 리스너가 달린 요소)을 사용하자</li>
<li>image 파일은 용량이 작으면 강제로 html에 포함된다.(용량이 1메가가 넘으면 일단 패서라도 용량을 줄이자, 애플 개발자가 아니라면)</li>
<li><code>:focus-within</code> 속성은 포커스를 받은 대상을 포함하는 요소를 나타낸다.(주로 Form 강조하기 위해 사용)</li>
<li><code>pointer-events</code> 속성은 포인터 이벤트의 대상 여부를 결정한다.</li>
<li>디자인이 귀찮거든 <a href="dribbble.com">dribbble.com</a>에서 슥 하자.</li>
<li>input 태그 사용시 <code>data-lpignore</code> 등으로 브라우저마다 자동으로 제어되는(암호완성 기능 등) 것을 방지할 수 있다.</li>
</ul>
<h3 id="유용한-react-라이브러리">유용한 React 라이브러리</h3>
<ul>
<li><a href="https://github.com/streamich/react-use">react-use</a></li>
<li><a href="https://github.com/JedWatson/classnames">classnames</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[원티드 프리온보딩 코스 - FE]]></title>
            <link>https://velog.io/@bu-geon/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EC%BD%94%EC%8A%A4-FE</link>
            <guid>https://velog.io/@bu-geon/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EC%BD%94%EC%8A%A4-FE</guid>
            <pubDate>Tue, 26 Apr 2022 21:17:18 GMT</pubDate>
            <description><![CDATA[<h3 id="원티드-프리온보딩-코스를-도입한-이유">원티드 프리온보딩 코스를 도입한 이유</h3>
<p> 원티드 프리온보딩 코스의 체계적인 커리큘럼을 통해 개발자로서 기본기를 다지고, 실력을 키우고 싶습니다. 스스로 또는 동료들과 문제를 해결하는 능력을 키우며, 개발자로서 꾸준하게 성장 가능한 습관을 들이고 싶습니다. 이를 통해서 첫 번째로, 제가 원하는 기능을 구현할 수 있는 구현력을 키우고 싶습니다. 처음에는 구글링을 통한 지식 습득으로 시작하겠지만, 제 것으로 만들어서 다양하게 활용하고 새로운 기능도 만들 줄 아는 개발자가 되고 싶습니다. 또한, 다양한 사람과의 협업 프로젝트를 통해 실제 어플리케이션을 개발해보고 싶습니다. 여러 팀원과 많이 소통하면서, 프로젝트를 조율할 줄 아량을 키우고 싶고, 이를 통해 현업에서도 원활하게 의견을 제시하는 팀원이 될 수 있다고 생각합니다. 마지막으로 원티드 프리온보등 프론트엔드 코스를 성실히 임한 후에는 개발자로서의 경력을 쌓을 것입니다. 함께 했던 동기들과 지속적인 교류를 통해 수료 후에도 함께 성장하는 개발자가 되겠습니다.</p>
<h3 id="지원을-희망하는-기업">지원을 희망하는 기업</h3>
<ul>
<li>그립컴퍼니</li>
<li>아이지에이웍스</li>
<li>메인메타</li>
<li>KB헬스케어</li>
<li>테스시스템</li>
<li>케어닥</li>
<li>블록체인글로벌</li>
<li>모아데이타</li>
<li>슬릭</li>
<li>휴먼스케이프</li>
</ul>
<h3 id="지원할-기업을-해당-기업으로-선정한-이유">지원할 기업을 해당 기업으로 선정한 이유</h3>
<p>기업의 존속여부는 회사와 구성원들에게 중요한 포인트라고 생각합니다. 기술의 발전속도가 급격해진 만큼 기업도 시장에서 도태되기 쉽습니다. 기업의 존속은 시장 경쟁력을 갖춤과 동시에 앞으로의 비전도 긍정적인 것을 뜻한다고 생각합니다. 블록체인 및 건강과 연관되어 있는 기술은 앞으로도 꾸준히 우리의 삶에 녹아들고, 경쟁우위를 선점하기 위해 구성원 모두가 끊임없이 발전할 수 있다고 생각합니다. 이를 통해 위의 회사들은 앞으로 시장을 점유하는데 충분한 이점을 가지고 있다고 생각하여 선정하게 되었습니다.</p>
]]></description>
        </item>
    </channel>
</rss>