<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Seunghyo.log</title>
        <link>https://velog.io/</link>
        <description>꼬꼬마 개발자 구승효입니다!</description>
        <lastBuildDate>Fri, 10 Jun 2022 21:22:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Seunghyo.log</title>
            <url>https://images.velog.io/images/ashley_ku/profile/acb9ccba-5a66-4138-b560-aa633d0f2129/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Seunghyo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ashley_ku" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Prettier가 코드에 'value'란 값을 추가할 때]]></title>
            <link>https://velog.io/@ashley_ku/Prettier%EA%B0%80-%EC%BD%94%EB%93%9C%EC%97%90-value%EB%9E%80-%EA%B0%92%EC%9D%84-%EC%B6%94%EA%B0%80%ED%95%A0-%EB%95%8C</link>
            <guid>https://velog.io/@ashley_ku/Prettier%EA%B0%80-%EC%BD%94%EB%93%9C%EC%97%90-value%EB%9E%80-%EA%B0%92%EC%9D%84-%EC%B6%94%EA%B0%80%ED%95%A0-%EB%95%8C</guid>
            <pubDate>Fri, 10 Jun 2022 21:22:03 GMT</pubDate>
            <description><![CDATA[<p>TS와 React를 이용한 프로젝트를 진행하다가 어느 순간 부터 Prettier가 import 쪽 코드를 변경하는 것을 확인했다.</p>
<pre><code class="language-js">import { hello } from &#39;test&#39; // 가 원래 코드라면
import { value Hello } from &#39;test&#39; // 처럼 나오는 것이다!</code></pre>
<p>원래 아래와 같이 써야 맞는 건가 싶었지만, <code>Duplicate identifier &#39;value&#39;</code> 라는 오류가 발생했다.</p>
<p>Extension Host를 재시작하니 문제가 해결됐다.
ctrl(or command) + shift + P 후에</p>
<blockquote>
<p>Developer: Restart Extension Host</p>
</blockquote>
<p>를 입력하여 재시작하면 된다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[힙이란 뭘까?]]></title>
            <link>https://velog.io/@ashley_ku/%ED%9E%99%EC%9D%B4%EB%9E%80-%EB%AD%98%EA%B9%8C</link>
            <guid>https://velog.io/@ashley_ku/%ED%9E%99%EC%9D%B4%EB%9E%80-%EB%AD%98%EA%B9%8C</guid>
            <pubDate>Fri, 11 Mar 2022 20:32:02 GMT</pubDate>
            <description><![CDATA[<p>최대 / 최소 원소를 빠르게 찾을 수 있는 자료구조</p>
<p>O(log N)</p>
<ul>
<li><p>힙 구성 (Heapify)</p>
</li>
<li><p>삽입 (insert)</p>
</li>
<li><p>삭제 (remove)</p>
</li>
<li><p>정렬 (heapsort) → 최악의 결과가 정렬의 최선의 경우일 경우</p>
</li>
<li><p>우선 순위 큐 (priority queue) → 우선 순위에 의해 나온다</p>
</li>
</ul>
<h3 id="파이썬에서-heapq-적용하기">파이썬에서 heapq 적용하기</h3>
<pre><code class="language-python">import heapq

heapq.heapify(L) # 리스트 L 로부터 min heap 구성
m = heapq.heappop(L) # min heap L 에서 최솟값 삭제 (반환)
heapq.heappush(L, x) # min heap L 에 원소 x 삽입</code></pre>
<h3 id="프로그래머스에서-예시-풀기">프로그래머스에서 예시 풀기</h3>
<p>더 맵게</p>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/42626">https://programmers.co.kr/learn/courses/30/lessons/42626</a></p>
<pre><code class="language-python">import heapq

def solution(scoville, K):
    answer = 0
    heapq.heapify(scoville) # mean heap 의 형태

    # 두 가지 조건이 있으니까 이렇게 true 하고 아래에 추가하는 게 가독성 UP
    while True: 
        min1 = heapq.heappop(scoville)
        if min1 &gt;= K:
            break
        elif len(scoville) == 0: # 모든 음식 경우의 수가 K 보다 낮을 경우
            answer = -1
            break
        min2 = heapq.heappop(scoville)
        new_scoville = min1 + 2 * min2
        heapq.heappush(scoville, new_scoville)
        answer += 1

    return answer</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[getElementsById vs. querySelector]]></title>
            <link>https://velog.io/@ashley_ku/getElementsById-vs.-querySelector</link>
            <guid>https://velog.io/@ashley_ku/getElementsById-vs.-querySelector</guid>
            <pubDate>Tue, 08 Mar 2022 18:58:54 GMT</pubDate>
            <description><![CDATA[<p>HTML의 요소를 가져올 때 getElementsById()를 이용하기도 하고, 때로는 querySelector()를 이용하기도 합니다. 이 두개는 무엇이 다르고 무엇이 같을까요?</p>
<h2 id="단일-결과인-경우">단일 결과인 경우</h2>
<h3 id="getelementbyid">getElementById()</h3>
<p>먼저 getElementById()를 살펴봅시다.</p>
<p>특정 id값을 찾고, 해당 요소를 리턴합니다. 해당 요소가 없다면 <code>null</code>을 반환합니다.</p>
<h3 id="queryselector">querySelector()</h3>
<p>querySelector는 일치하는 요소들 중 가장 첫 번째로 나온 엘리먼트를 리턴합니다. 일치하는 요소가 없다면 <code>null</code> 을 반환합니다.</p>
<h2 id="다수-결과인-경우">다수 결과인 경우</h2>
<p>두 개의 함수 모두 여러 개의 결과를 가져올 수 있습니다. 다만, 다수의 결과를 포함해야 하니 이 상황에 더욱 적합한 getElementByClassName과 querySelectorAll로 비교합시다.</p>
<p>많이들 알고 계시겠지만, (스포하자면) 둘 다 index로 결과에 접근할 수 있습니다! 유사 배열이기 때문입니다.</p>
<p>간단한 HTML, JavaScript 코드를 작성해서 직접 확인해봅시다.</p>
<pre><code class="language-html">&lt;div class=&quot;App&quot;&gt;
    &lt;div id=&quot;one&quot; class=&quot;test&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;two&quot; class=&quot;test&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;three&quot; class=&quot;test&quot;&gt;&lt;/div&gt;
&lt;/div&gt;</code></pre>
<pre><code class="language-jsx">const testQuery = document.querySelectorAll(&#39;.test&#39;);
const testElement = document.getElementsByClassName(&#39;test&#39;);

console.log(&#39;testQuery&#39;, testQuery);
console.log(&#39;testElement&#39;, testElement);</code></pre>
<h3 id="getelementbyclassname">getElementByClassName</h3>
<p>특정 className을 가진 요소를 찾고, 해당 요소를 <code>NodeList</code> 로 리턴합니다.</p>
<p><img src="https://images.velog.io/images/ashley_ku/post/429f5e16-aa9c-40b0-8414-f2c84ed1c0e5/image.png" alt=""></p>
<p>HTMLCollection은 구성요소를 이름과 인덱스로 동시에 직접 노출합니다.</p>
<p>순수 숫자 인덱스와 띄어쓰기는 지원하지 않습니다. testElement.one 과 같은 접근은 가능하지만, testElement.1 과 같은 접근, 그리고 ‘o ne’과 같은 이름도 사용할 수 없습니다.</p>
<p>물론 testElement[1] 과 같은 배열의 인덱스로 접근은 가능합니다.</p>
<p><a href="https://developer.mozilla.org/ko/docs/Web/API/HTMLCollection">https://developer.mozilla.org/ko/docs/Web/API/HTMLCollection</a></p>
<p>대신 namedItem() 같은 메소드를 이용할 수는 있습니다.</p>
<h3 id="queryselectorall">querySelectorAll</h3>
<p>일치하는 요소들 모두를 <code>HTMLCollection</code> 으로 리턴 합니다.</p>
<p><img src="https://images.velog.io/images/ashley_ku/post/e4c279c0-d104-4587-9940-5c6626b8d7f1/image.png" alt=""></p>
<p>NodeList 이기 때문에 forEach 등 NodeList에서만 사용할 수 있는 여러 메소드를 사용할 수 있습니다. 하지만, 요소에 인덱스로만 접근이 가능합니다.</p>
<p>결과물은 정적으로, DOM이 변경될 경우에도 collection의 내용에는 영향을 주지 않습니다.</p>
<h3 id="결론">결론</h3>
<p>querySelector보다 getElementID가 더 빠릅니다. 벤치마크 테스트를 실행하면, getElementById가 약 1.2배 더 빠르다고 합니다.</p>
<p>지원하는 브라우저의 범위도 더 넓습니다.</p>
<p> (출처 - <a href="https://bobbohee.github.io/2021-02-12/getelementbyid-versus-queryselector">https://bobbohee.github.io/2021-02-12/getelementbyid-versus-queryselector</a>)</p>
<p>하지만, querySelector는 나중에 나온 기능이기 때문에, 지원 범위는 적어도 구체적인 요소를 선택할 때 더 좋을 수 있습니다. (요소를 선택할 때 구체적인 조건을 넣을 수 있기 때문에)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Data Attributes]]></title>
            <link>https://velog.io/@ashley_ku/Data-Attributes</link>
            <guid>https://velog.io/@ashley_ku/Data-Attributes</guid>
            <pubDate>Tue, 08 Mar 2022 16:17:27 GMT</pubDate>
            <description><![CDATA[<p>HTML5는 데이터에 대한 확장 가능성을 염두에 두고 디자인 되었습니다.</p>
<p>추가적인 조작을 하지 않고도 의미론적 표준 HTML 요소에 추가 정보를 저장할 수 있습니다.</p>
<h3 id="문법">문법</h3>
<p>간단하게 사용할 수 있습니다.</p>
<p>어느 엘리먼트에나 data- 로 시작하는 속성 무엇이든 사용할 수 있습니다.</p>
<p>화면에 보이지 않게 추가 정보를 엘리먼트에 담아 놓을 수도 있습니다.</p>
<p><strong>HTML</strong></p>
<pre><code class="language-html">&lt;div
    id=&quot;test&quot;
    data-colums=&quot;3&quot;
    data-index=&quot;1&quot;&gt;
    안녕하세요.
&lt;/div&gt;</code></pre>
<p><strong>자바스크립트</strong></p>
<p>자바스크립트에서 접근하는 방법도 간단합니다.</p>
<p>data 속성을 가져오기 위해서는 data-뒤에 붙인 이름을 사용하게 됩니다.</p>
<pre><code class="language-jsx">// dataset 객체에서 읽어올 수 있습니다.
const test = document.querySelector(&quot;#test&quot;);
console.log(test.dataset.columns); // 3
console.log(test.dataset.index); // 1

// 각 값은 변경될 수 있습니다.
test.dataset.index = 2;
console.log(test.dataset.index); 2;</code></pre>
<p><strong>CSS</strong></p>
<p>HTML의 속성이기 때문에 CSS에서도 이에 접근할 수 있습니다.</p>
<pre><code class="language-css">/* 색상을 바꿀 수 있습니다. */

#test[data-columns=&quot;3&quot;] {
    color: red;
}

/* 요소의 값을 보여줄 수 있습니다. */
#test::before {
    content: attr(data-contents);
}</code></pre>
<p>ex) 이런 예시도 있어요 - <a href="https://jsbin.com/ujiday/2/edit?html,output">https://jsbin.com/ujiday/2/edit?html,output</a></p>
<h3 id="아쉬운점">아쉬운점</h3>
<p>구 버전 IE 등 일부 구 브라우저에서는 해당 기능을 지원하지 않습니다.</p>
<p>이럴 경우에는 getAttribute()를 통해 데이터 속성에 접근할 수 있습니다.</p>
<p>노출 되고 접근 가능하지 않기 때문에 크롤러가 해당 정보를 수집하지 못합니다.</p>
<p>JS의 그냥 객체에 정보를 저장하는 것 보다 성능이 저조할 수 있습니다.</p>
<p>(메타 데이터를 이용하는 데에는 도움이 될 수 있겠네요!)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2022.02.27]]></title>
            <link>https://velog.io/@ashley_ku/2022.02.27</link>
            <guid>https://velog.io/@ashley_ku/2022.02.27</guid>
            <pubDate>Sun, 27 Feb 2022 20:58:42 GMT</pubDate>
            <description><![CDATA[<h3 id="사이드-프로젝트">사이드 프로젝트</h3>
<p>사이드 프로젝트를 위한 아이스 브레이킹 및 주제 디벨롭 시간을 가졌습니다.
다른 분이 아이스 브레이킹을 위한 여러 주제를 준비해오셔서 더 빠르게 속 깊은 이야기를 나눌 수 있었습니다. 빠르게 다른 사람의 성향을 대강이나마 파악할 수 있는 좋은 방법인 것 같아 다른 프로젝트를 하게 된다면 같은 방법을 이용해보고 싶습니다.</p>
<p>주제는 조금 더 고민해보고 디벨롭 할 때 도움이 될 수 있으면 좋을 것 같습니다.</p>
<h3 id="fixed와-sticky">fixed와 sticky</h3>
<p>비슷한 점이 있지만, fixed는 말 그대로 해당 위치에 <code>고정</code> 됩니다.
반면에 sticky는 스크롤을 따라 움직이다, 특정 부분 부터는 <code>fixed 처럼 고정</code> 됩니다.</p>
<p>sticky를 지원하지 않는 브라우저(ex. IE라던가 IE라던가 IE같은...)를 고객이 이용할 경우에는 문제가 발생합니다. 물론 이를 직접 개발하는 방법이 있습니다.</p>
<p>특정 viewport 도달할 경우에는 fixed를, 그 이전에는 fixed를 지정해주지 않는 방법으로 sticky를 구현하는 방법이 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2022.02.22 콩데이]]></title>
            <link>https://velog.io/@ashley_ku/2022.02.22-%EC%BD%A9%EB%8D%B0%EC%9D%B4</link>
            <guid>https://velog.io/@ashley_ku/2022.02.22-%EC%BD%A9%EB%8D%B0%EC%9D%B4</guid>
            <pubDate>Sun, 27 Feb 2022 19:14:59 GMT</pubDate>
            <description><![CDATA[<h3 id="알고리즘-풀이">알고리즘 풀이</h3>
<p>프로그래머스에서 알고리즘 커뮤러닝을 듣고 있습니다.
알고리즘 문제를 딱  열었을 때 느껴지는 첫인상이 중요합니다.</p>
<ul>
<li>문제의 크기</li>
<li>문제에 걸린 제약</li>
<li>조건이 무엇인지</li>
</ul>
<h4 id="해시-hash">해시 (Hash)</h4>
<p>사용해야 하는 index 값이 int 형태가 아닌 string 형태일 경우 사용되는 자료구조.</p>
<ul>
<li>get
  get(x)는 x라는 key에 대응되는 value를 돌려줍니다. 딕셔너리 값에 찾으려는 값이 없을 경우, 디폴트 값을 넣어 없을 때 가져오게 할 수도 있습니다.
  ex) ex_dict.get(&#39;값이 있는 key&#39;, &#39;값이 없는 결과&#39;) =&gt; <code>값이 없는 결과</code></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[em과 rem]]></title>
            <link>https://velog.io/@ashley_ku/em%EA%B3%BC-rem</link>
            <guid>https://velog.io/@ashley_ku/em%EA%B3%BC-rem</guid>
            <pubDate>Sat, 12 Feb 2022 18:26:43 GMT</pubDate>
            <description><![CDATA[<p>CSS에서 px 외에도 자주 쓰이는 단위가 있습니다.</p>
<p>바로, em과 rem입니다. 반응형 웹 디자인이 유행하면서 해당 단위가 애용되고 있습니다. 이들은 <code>상대 단위</code> 라고 불립니다.</p>
<h3 id="상대-단위">상대 단위</h3>
<p>상대 단위는 기준이 있고, 유동적으로 바뀌는 길이를 나타냅니다.</p>
<p>각 부분 별 퍼센트를 나타내는 <code>%</code> 도 있고, 화면 상의 너비나 높이를 나타내는 <code>vw</code>, <code>vh</code> 도 있습니다.</p>
<p>em과 rem의 기준점은 그렇다면 무엇일까요? CSS에서 각 font-size의 값에 따라 결정됩니다. 브라우저에서는 em과 rem을 보고 계산되어 화면에 그리게 됩니다.</p>
<h3 id="em-vs-rem">em vs. rem</h3>
<p>그렇다면, em과 rem의 차이를 한 번 살펴봅시다.</p>
<ul>
<li><p>rem</p>
<p>  rem에서의 r은 root 를 뜻합니다. 최상위 요소(root: html)의 font-size에 따라 값이 뼌한다고 보면 됩니다.</p>
</li>
<li><p>em</p>
<p>  em에서는 해당 단위가 사용되고 있는 요소의 font-size 속성 값이 기준이 됩니다.</p>
<p>  여러 상위 요소를 가지고 있을 때 계산이 어렵기 때문에 계산이 복잡할 수 있습니다.</p>
</li>
</ul>
<h3 id="em과-rem-혼용하기">em과 rem 혼용하기</h3>
<p>em 보다는 가급적 rem을 우선적으로 사용하는 것이 위에서 언급한 문제 때문에 권장 됩니다. 하지만 상대적인 font-size를 여러 개 사용하고 싶을 때 두 가지를 혼용할 수 있습니다.</p>
<p>아래에서의 예를 봅시다.</p>
<pre><code class="language-css">.example {
    margin-right: 0.2em;
    font-size: 3rem;
}</code></pre>
<p>현재 html 문서의 글자 크기의 3배가 example의 크기가 됩니다. 여기서의 margin-right는 이 3배가 된 example의 0.2배가 된다는 뜻입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#11: 외관 변경하기 (불편함 주의)]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti12-%EC%99%B8%EA%B4%80-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-%EB%B6%88%ED%8E%B8%ED%95%A8-%EC%A3%BC%EC%9D%98</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti12-%EC%99%B8%EA%B4%80-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0-%EB%B6%88%ED%8E%B8%ED%95%A8-%EC%A3%BC%EC%9D%98</guid>
            <pubDate>Fri, 11 Jun 2021 07:14:06 GMT</pubDate>
            <description><![CDATA[<p>이번 편에서는 UI 불편함을 max로 만들 수 있는 편이니, UI와 UX에 관심이 많은 분은 속이 더부룩해질 수 있습니다.</p>
<h3 id="문제의-첫-번째-페이지모바일-뷰">문제의 첫 번째 페이지(모바일 뷰)</h3>
<p><img src="https://images.velog.io/images/ashley_ku/post/ec7a9744-8249-4610-b2c0-46d4b4ecbc9b/image.png" alt=""></p>
<blockquote>
<p><del>살..살려줘..</del></p>
</blockquote>
<p>장담컨대, 이 세상의 모든 한국인을 불편하게 만들 수 있는 페이지이다.
여러 가지 방법이 있지만, 첫 번째 페이지에서는 &#39;내&#39; 라는 말을 빼 주는 것으로 쇼부 보기로 했다.</p>
<p>귀찮은 건 아니고, 다시 보니 어투를 살짝 바꾸는 게 좋다는 생각이 들었다.</p>
<h3 id="문제의-두-번째-페이지모바일-뷰">문제의 두 번째 페이지(모바일 뷰)</h3>
<p><img src="https://images.velog.io/images/ashley_ku/post/b09c2d4d-fd0c-46da-a316-f91d648f72bf/image.png" alt=""></p>
<p>문제도 가독성이 떨어지고..
선택지도 가독성이 떨어진다..</p>
<p>이걸 고쳐보도록 하자.</p>
<h4 id="내용-수정하기">내용 수정하기</h4>
<p>기본 중의 기본은 역시 다시 한 번 글을 다듬는 것이었다. 한국말은 아 다르고 어 다르기 때문에, 최대한 말을 깔끔하게 볼 수 있도록 했다.</p>
<h4 id="행간-늘리기">행간 늘리기</h4>
<p>문제의 행간이 매우 좁아, 피로도를 늘리는 주범인 것 같았다.
행간은 css로 간단하게 늘려줄 수 있다.
line-height 속성을 이용해서 늘려주었다.</p>
<p><code>line-height: 140%;</code></p>
<h4 id="글에-엔터-넣어주기">글에 엔터 넣어주기</h4>
<p>js를 생각하고 엔터를 넣어주려 했는데, 처참히 실패했다.
<img src="https://images.velog.io/images/ashley_ku/post/a11a61a3-8224-490e-87af-969be5ea0372/image.png" alt=""></p>
<p>슬래시가 두 번 들어갔지만, 뭔가 해보려 했던 흔적이다.. 🤔
처참하게 안 된다는 것을 깨닫고, 다시 시작해본다.</p>
<p><code>\n</code>을 직접 읽고.. split을 하고.. <code>&lt;br /&gt;</code>을 넣어준 다음 붙여준다는 것이 학계의 정설이었다.</p>
<h3 id="절망적인-결과-페이지-모바일-뷰">절망적인 결과 페이지 (모바일 뷰)</h3>
<p><img src="https://images.velog.io/images/ashley_ku/post/65b25e42-ecd1-4cd5-86f1-59c0eb441c92/image.png" alt=""></p>
<p>이걸 보고 있을 누군가에게 웃음을 주었다면 그저.. 행복합니다.^^..
분명히 PC 뷰에서는 멀쩡했는데.. 그랬는데 말입니다..
변명은 그만하고 고치러 가봅니다.</p>
<h4 id="배보다-큰-배꼽">배보다 큰 배꼽</h4>
<p>일단 판에서 튀어나가는 것은, 기본 height를 고정해두었기 때문입니다.
css에서 <code>height: auto;</code>로 설정해 안의 콘텐츠들의 길이만큼 늘어나도록 해주었습니다.</p>
<h4 id="화면이-작을-때는-소셜-아이콘의-크기-줄이기">화면이 작을 때는 소셜 아이콘의 크기 줄이기</h4>
<p>줄여주었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#10: 로딩창 구현하기]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti11-%EB%A1%9C%EB%94%A9%EC%B0%BD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti11-%EB%A1%9C%EB%94%A9%EC%B0%BD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 11 Jun 2021 07:13:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>??: 근데 이거.. 결과는 아직 구현이 안됐나요?</p>
</blockquote>
<p>배포해둔 서비스를 주변 사람들에게 살짝쿵 공유를 했는데, 결과가 안나온다는 말을 들었다.</p>
<p>무료 서버를 사용하다보니 이따금 로딩 시간이 길어지거나, 무한 로딩에 걸리는 일이 있었던 것..</p>
<p>사용자의 편의성을 높이기 위해 로딩창을 구현해보기로 했다.
로딩이 너무 오래 걸릴 경우를 대비해, 문구도 추가하도록 해보자.</p>
<h3 id="로딩-애니메이션-구현하기">로딩 애니메이션 구현하기</h3>
<p>마침 배경도, 글씨체도 레트로 느낌 낭낭하겠다.. 로딩창에서 팩맨이 있었으면 했다.</p>
<p>팩맨이 냠냠 거리는 것은 생각보다 어렵진 않았는데, 반원을 겹쳐 만들고 위 아래로 흔들흔들 거리게 만들면 된다.</p>
<p>하트를 먹는 모습으로 구현하기로 했다.</p>
<p>코드로 보면 다음과 같다.
팩맨의 윗 얼굴, 아랫 얼굴을 구분해서 만들어주도록 한다.
결과적으로 똥그란 얼굴을 만들기 위해서는, height가 width의 반이어야 한다.</p>
<pre><code class="language-jsx">const PacmanTop = styled.div`
  position: relative;
  background-color: #3bc9db;
  height: 70px;
  width: 140px;
  border-radius: 70px 70px 0 0;
  z-index: 10;
  animation: ${spin1} 0.7s infinite;
`;

const PacmanBottom = styled.div`
  position: relative;
  background-color: #3bc9db;
  height: 70px;
  width: 140px;
  border-radius: 0 0 70px 70px;
  z-index: 10;
  animation: ${spin2} 0.7s infinite;
`;</code></pre>
<p>위에 작성한 animation을 함께 본다.
살짜쿵 살짜쿵 움직이는 애니메이션임을 확인할 수 있다.</p>
<pre><code class="language-jsx">
const spin1 = keyframes`
    from  {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(-35deg);
    }
`;

const spin2 = keyframes`
    from  {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(35deg);
    }
`;
</code></pre>
<p>이제 여기까지 따라했다면, 팩맨이 입을 우물우물 거리는 애니메이션은 완성했다.</p>
<p>하트를 만들어 보자.
하트는 가상요소를 이용해 만들어야 한다. 정사각형에다가 반원을 모서리에 붙여 하트 모양처럼 만들어주는 원리를 이용한다.</p>
<p>하트를 만들엇다면, 이동은 left의 위치를 먼 곳에서 가까운 곳으로 이동시켜주면 된다.</p>
<h3 id="로딩-시-문구-정하기">로딩 시 문구 정하기</h3>
<p>이 프로젝트는 롤에 의한, 롤을 위한, 롤에 대한 프로젝트 이기 때문에 로딩에 나오는 문구도 롤과 관련된 문구가 랜덤으로 나오길 바랐다.</p>
<p>개인적으로 게임 로딩 문구 중에서는 하스스톤 로딩 문구가 재밌는 것 같다.</p>
<p>(참고로 항상 적절한 상대라는데.. 가끔 투기장에서 사기 덱을 만날 때마다 허무하다.)</p>
<p><img src="https://images.velog.io/images/ashley_ku/post/efb87ad1-470a-4bc6-97ae-9c16d88cbdec/image.png" alt=""></p>
<p>이런 느낌의 고퀄 이미지는 아니더라도, 문구에 아이디어만 첨가하려고 했다.</p>
<p>정한 문구들은 다음과 같다.</p>
<pre><code class="language-text">    &quot;누누 눈 굴리는 중&quot;,
    &quot;아무무 친구 만드는 중&quot;,
    &quot;스웨인 새 모이 주는 중&quot;,
    &quot;룰루 깔깔 대는 중&quot;,
    &quot;나서스 농사 짓는 중&quot;,
    &quot;베인 앞구르기 연습 중&quot;,</code></pre>
<p>내가 좋아하는 스웨인을 넣어주고, 다른 친구들과 함게 넣어주었다.
랜덤 함수를 이용해서 랜덤한 상태가 뜨도록 했다.</p>
<h3 id="너무-오랜-시간이-걸릴-경우">너무 오랜 시간이 걸릴 경우</h3>
<p>몽고 DB, 백 엔드, 프론트 엔드 모두 무료 서버에 있어 시간이 꽤나 오래 걸리는 서비스이기 때문에.. 너무 오랜 시간이 걸릴 경우를 위해서 setTimeout 함수를 이용해 <code>다시 시도해달라</code>는 문구를 추가하기로 했다.</p>
<pre><code> setTimeout(() =&gt; {
    if (통신이 안됐다면) setLoading(&quot;너무 오래 걸리면, 다시 시도해주시겠어요?&quot;);
  }, 5000);</code></pre><p>이제 프로젝트의 거진 마지막이 다다라서, 모바일 뷰에서의 css를 약간 수정해주면 프로젝트 마무리가 될 것 같다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#9: 공유 버튼 만들기]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti10-%EA%B3%B5%EC%9C%A0-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti10-%EA%B3%B5%EC%9C%A0-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Fri, 11 Jun 2021 07:12:58 GMT</pubDate>
            <description><![CDATA[<p>각종 MBTI 테스트의 핵심은 친구들에게 공유를 하며 느낄 수 있는 즐거움이 아닐까?</p>
<p>바아아로 공유 버튼 만들기로 한다.</p>
<h4 id="기본-세팅">기본 세팅</h4>
<p>index.html 파일에 기본적으로 해주어야 하는 세팅이다.</p>
<ul>
<li>og:url: 공유하는 링크 주소</li>
<li>og:title: 공유 할 제목</li>
<li>og:description: 공유 할 내용</li>
<li>og:image: 공유할 이미지</li>
</ul>
<pre><code class="language-html">    &lt;meta property=&quot;og:url&quot; content=&quot;https://mbti-with-lol.netlify.app/&quot; /&gt;
    &lt;meta property=&quot;og:title&quot; content=&quot;MBTI로 찰떡 챔피언 찾기&quot; /&gt;
    &lt;meta
      property=&quot;og:description&quot;
      content=&quot;내가 몰랐던 나의 인생 챔피언 찾기&quot;
    /&gt;
    &lt;meta property=&quot;og:image&quot; content=&quot;./thumbnail.png&quot; /&gt;</code></pre>
<p>이걸 적으면, 공유 화면에서 이쁘게 뜨는 것을 볼 수 있다.
결과 화면은 다음과 같다.</p>
<p><img src="https://images.velog.io/images/ashley_ku/post/eb0068a2-c57d-4815-850d-fe092559db87/image.png" alt=""></p>
<p>이러한 테스트는 참고로 <a href="https://developers.facebook.com/tools/debug/">Facebook 공유 디버거</a>에서도 할 수 있다!
링크만 적어주면 미리 어떻게 보일지 알 수 있다.</p>
<p>물론, 나에게 복사해서 알아보는 방법도 있다.ㅎㅎ..</p>
<h3 id="sns-공유-하는-법-알아보기">SNS 공유 하는 법 알아보기</h3>
<p>나는 Social이라는 컴포넌트를 미리 만들어 놓았다.
각 사이트에서 제공하는 공유 이미지가 조금씩 다르기 때문에 원하는 대로 만들기 위함이었다.
최종적으로 선택한 SNS는 다음과 같다.</p>
<ul>
<li>facebook</li>
<li>twitter</li>
<li>kakaotalk</li>
<li>그냥 링크 복사</li>
</ul>
<p>차례로 구현 방법을 살펴 보자.</p>
<h4 id="facebook-twitter">facebook, twitter</h4>
<p>사실 facebook과 twitter는 매우 날로 기능을 구현했다.
각 아이콘 컴포넌트에 onClick 메소드로 다음과 같은 코드를 추가해주면 된다.</p>
<pre><code class="language-js">// twitter
window.open(
    &quot;https://www.twitter.com/intent/tweet?&amp;url=주소&quot;
);

// facebook
window.open(
    &quot;https://www.facebook.com/sharer/sharer.php?&amp;u=주소&quot;
);
</code></pre>
<p><img src="https://1.bp.blogspot.com/-J0I5sc9fwEw/WmWQXWJL70I/AAAAAAAAs98/ZFH2q102ZUQIRzd-AB00vJDo4IZ_53c0wCLcBGAs/s1600/bobrosspainting.jpg" alt=""></p>
<h4 id="kakaotalk">kakaotalk</h4>
<p>먼저, 카카오 developers 홈페이지에 가서 앱을 등록해준 후, 카카오 링크에서 템플릿 빌더 바로가기를 누른다. 원하는 템플릿을 고르는데, 나는 FEED를 골라 주었다.</p>
<p><a href="https://ellismin.com/2020/09/share-kakao/">리액트에서 구현하는 방법</a>은 이 분 블로그가 많이 도움이 되었다.</p>
<p>리액트에서 script를 대체 어떻게 사용할 수 있을까 고민이 많았는데,
<code>const script = document.createElement(&quot;script&quot;);</code>
와 같은 느낌으로 만들어서 쓸 수도 있었다..!</p>
<p>그 아래에서는 kakaotalk에서 제공하는 가이드라인..을 잘 따르면 된다. <del>(이 시리즈에서만 4번째 하는 말)</del></p>
<p><img src="https://images.velog.io/images/ashley_ku/post/c2bd2dbb-32a7-48ad-8583-80f38f236723/image.png" alt=""></p>
<p>잘 도착하긴 하는데 이거.. 이미지가 영 별로라서 나중에 바꿔주어야 될 것 같다.</p>
<h4 id="clipboard">clipboard</h4>
<p>드래그 한 부분을 복사할 수 있는 원리를 이용한다.
<code>execCommand(&quot;copy&quot;);</code>를 이용해서 개발하였다.</p>
<p>복사가 되었을 경우 안내 메시지는 그냥 글자를 추가해주는 것으로 결정했다.</p>
<pre><code class="language-jsx">const Link = (props) =&gt; {
  const textInput = useRef();
  const [clicked, setClicked] = useState(false);

  const copy = () =&gt; {
    const el = textInput.current;
    el.select();
    document.execCommand(&quot;copy&quot;);
  };

  const onClick = () =&gt; {
    setClicked(true);
    copy();
  };

  return (
    &lt;StyledDiv&gt;
      &lt;input
        type=&quot;text&quot;
        value=&quot;복사하고자 하는 주소&quot;
        ref={textInput}
        readOnly
      &gt;&lt;/input&gt;
      &lt;StyledButton onClick={onClick}&gt;링크 복사&lt;/StyledButton&gt;
      {clicked &amp;&amp; &lt;P&gt;복사됨&lt;/P&gt;}
    &lt;/StyledDiv&gt;
  );</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#8: 결과 집계를 해보자]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti9-%EA%B2%B0%EA%B3%BC-%EC%A7%91%EA%B3%84%EB%A5%BC-%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti9-%EA%B2%B0%EA%B3%BC-%EC%A7%91%EA%B3%84%EB%A5%BC-%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Fri, 11 Jun 2021 06:16:54 GMT</pubDate>
            <description><![CDATA[<p>사람들이 어떤 성격을 가지고 있는지 나중에 그래프로 보여줄 수 있다면 좋을 것 같아 결과 집계를 위한 서버 코드를 조금 더 추가하기로 결정 했다.</p>
<h3 id="집계하기">집계하기</h3>
<p>구성한 로직은 다음과 같다.</p>
<blockquote>
<ol>
<li>애초에 저장을 카운트 된 숫자로 한다.</li>
<li>불러온 다음에 해당 숫자를 + 1 하는 식으로 집계한다.</li>
<li>total로 나누어 확률로 반환한다.</li>
</ol>
</blockquote>
<h4 id="기억-너머로-가버린-update-deprecated">기억 너머로 가버린 update: deprecated</h4>
<p><img src="https://images.velog.io/images/ashley_ku/post/91f37f0c-3e62-4cba-8729-6f1038c5f4ec/image.png" alt=""></p>
<p>update를 이용해 코드 작성 중, 이런 메시지가 떠서 updateOne을 사용했다.
경우에 따라 updateOne, updateMany, bulkWrite 중에서 선택해 사용하면 될 듯하다.</p>
<h4 id="결과적으로">결과적으로,</h4>
<p>집계 로직이 비효율적일 수 있으나, 비교적 간단한 코드를 이용해서 개발할 수 있다는 장점이 있었다.
해당 함수는 기존 결과 보기 창에 추가하여 활용해줄 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#7: 페이지 전환 기능을 구현하자]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti7-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%84%ED%99%98-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EA%B5%AC%ED%98%84%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti7-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%A0%84%ED%99%98-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EA%B5%AC%ED%98%84%ED%95%98%EC%9E%90</guid>
            <pubDate>Fri, 11 Jun 2021 06:16:02 GMT</pubDate>
            <description><![CDATA[<p>페이지를 전환하는 방법에는 여러가지가 있겠지만, 간편하게 context를 이용해서 페이지 전환 기능을 구현했다.</p>
<h4 id="srccontextspagejs">src/contexts/page.js</h4>
<pre><code class="language-js">import { createContext } from &quot;react&quot;;

const PageContext = createContext({
  status: &quot;start&quot;,
  action: () =&gt; {},
});

export default PageContext;
</code></pre>
<h4 id="srcappjsx">src/App.jsx</h4>
<pre><code class="language-jsx">...
  const [page, setPage] = useState(&quot;ready&quot;);
  return (
    &lt;PageContext.Provider value={{ status: page, action: onClick }}&gt;
      &lt;Reset /&gt;
      &lt;StyledDiv className=&quot;App&quot;&gt;
        &lt;Template /&gt;
      &lt;/StyledDiv&gt;
    &lt;/PageContext.Provider&gt;
  );
</code></pre>
<p>과 같은 느낌으로, onClick에는 적당한 페이지 넘김 함수를 넣어주었다. 각 페이지 별로, 넘기게 되면 onClick으로 setPage를 이용해 page를 바꿔주는 느낌으로 구현했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#6: 프론트 작업을 시작해보자]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti6-%ED%94%84%EB%A1%A0%ED%8A%B8-%EC%9E%91%EC%97%85%EC%9D%84-%EC%8B%9C%EC%9E%91%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti6-%ED%94%84%EB%A1%A0%ED%8A%B8-%EC%9E%91%EC%97%85%EC%9D%84-%EC%8B%9C%EC%9E%91%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 08 Jun 2021 15:38:11 GMT</pubDate>
            <description><![CDATA[<h3 id="질문과-결과-페이지-문구-작성-완료">질문과 결과 페이지 문구 작성 완료</h3>
<p>가장 오래 걸려서 이에 대해 자세하게 적고 싶지만.. </p>
<p>많은 정보를 얻고자 각각의 mbti에 대해 적은 글들을 수도 없이 읽고, 적었다 지웠다를 반복했다. 이 프로젝트를 진행하면서 빼박 INFP였던 내가(사회 생활할 때는 생존형 E이다) 사실은 N이 아닌 S가 아닐까 하는 생각도 들었다.</p>
<h3 id="배경-이미지-적용하기">배경 이미지 적용하기</h3>
<p>개발을 시작하기에 앞서 괜찮은 배경 이미지를 찾고자 했다.
상업적 이용이 가능한 소스를 판매하는 사이트를 찾다가 iStock에서 $12를 주고 적당한 이미지를 구입했다.</p>
<p>개인적으로 픽셀 아트를 좋아해서, 픽셀 아트 느낌이 나는 이미지를 선택했다.</p>
<p>사용한 옵션은 다음과 같다.</p>
<ul>
<li>background-size: 화면에 꽉 차도록</li>
<li>background-attachment: 나중에 중간에 스크롤이 길어지더라도 뒤의 배경 이미지는 고정되게끔</li>
</ul>
<pre><code class="language-jsx">const StyledDiv = styled.div`
  width: 100%;
  height: 100vh;
  background-image: url(&quot;background-source.jpg&quot;);
  background-size: cover;
  background-attachment: fixed;
`;
</code></pre>
<h3 id="폰트-적용하기">폰트 적용하기</h3>
<p>이미지를 적용 했다면, 어울리는 폰트를 찾아 적용해주는 것이 인지상정!
<img src="https://smtmap.com/wp-content/uploads/2020/07/%EC%9D%B8%EC%A7%80%EC%83%81%EC%A0%95.jpg" alt="img"></p>
<p>상업적 무료 폰트 이용은 역시 <a href="https://noonnu.cc/">눈누</a>가 사용하기 편한 것 같다.
요새는 기업에서, 지자체에서 풀어주는 무료 폰트가 낭낭해서 정말 좋다.</p>
<p>참고로, 둥근모꼴을 굉장히 좋아하기 때문에 이번에도 둥근모꼴을 사용하기로 했다.
배경이랑도 찰떡이다!</p>
<p>적용하는 방법은 굉장히 쉽다.
위의 사이트에서, 혹은 원하는 폰트의 웹 폰트를 가져와 아래 경로에 붙인다.</p>
<h4 id="루트indexcss">루트/index.css</h4>
<pre><code class="language-css">@font-face {
  font-family: &quot;DungGeunMo&quot;;
  src: url(&quot;https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_six@1.2/DungGeunMo.woff&quot;)
    format(&quot;woff&quot;);
  font-weight: normal;
  font-style: normal;
}
</code></pre>
<h4 id="사용할-컴포넌트">사용할 컴포넌트</h4>
<pre><code class="language-jsx">const P = styled.p`
  font-family: DungGeunMo;
  font-size: 50px;
`;</code></pre>
<p>요렇게 정리만 해준다면 사용해주기 굉장히 용이해진다.</p>
<h3 id="결과-화면">결과 화면</h3>
<p><img src="https://images.velog.io/images/ashley_ku/post/dc7df6e4-f97f-43ef-80d5-dcf0f5214825/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#5: API 서버를 배포해보자]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti5-API-%EC%84%9C%EB%B2%84%EB%A5%BC-%EB%B0%B0%ED%8F%AC%ED%95%B4%EB%B3%B4%EC%9E%90-4jriwyay</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti5-API-%EC%84%9C%EB%B2%84%EB%A5%BC-%EB%B0%B0%ED%8F%AC%ED%95%B4%EB%B3%B4%EC%9E%90-4jriwyay</guid>
            <pubDate>Tue, 08 Jun 2021 12:53:42 GMT</pubDate>
            <description><![CDATA[<p>삽질기는 계속 되고 있다.</p>
<p>이번에는 무료 PaaS로 알려진 Heroku와 Netlify를 이용하여 배포를 했다.빠르게 배포하고 싶었기 때문에 이미 잘 구현된 서비스를 이용한 셈이다.</p>
<p>(물론! 다음에 시간이 충분하다면, 직접 배포하고자 하는 마음이 있다.)</p>
<hr>
<p>왜 다른 두 가지 서비스를 이용했냐면 이유는 아래와 같다.</p>
<ol>
<li><strong>Heroku는 특정 폴더를 선택해 배포할 수 없다.</strong>
Netlify는 이 특정 폴더 설정이 가능하다. <br /></li>
</ol>
<p>-&gt; 나는 하나의 Repository에 클라이언트와 서버를 모두 구현했기에 Client를 Heroku에 배포하긴 어려워보였다. <br />
-&gt; 나중에 다른 개발자 분과 이야기하다 깨달은 건데, 패키지 설정을 잘 해주면 될 것 같기도 하다..!</p>
<ol start="2">
<li><strong>Netlify는 정적인 사이트를 위한 서비스이다.</strong></li>
</ol>
<p>-&gt; 서버를 배포하기에는 어려워 보였다.</p>
<p>그래서 결국 선택한 것이 다음과 같다.</p>
<blockquote>
<ul>
<li>Server: Heroku</li>
</ul>
</blockquote>
<ul>
<li>Client: Netlify</li>
</ul>
<p><del>누가 저렇게 끔찍한 혼종을 만들어 냈단 말인가.. 바로 나다..</del></p>
<p>Heroku와 Netlify로 배포하는 방법은 기존에 많은 분들이 알려주었기 때문에, 가이드를 자세하게 적지는 않을 예정이다.</p>
<p>Github에 올려둔 프로젝트는 매우 편하게 각 사이트에서 자동 배포까지 설정할 수 있기 때문에, *<em>나처럼 시간이 조금 촉박한 프로젝트를 하거나, 배포를 직접 하고 싶지 않거나 어려운 경우 *</em>이용하면 좋을 것 같다는 생각이 들었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#4: 백부터 개발 시작]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti4-%EB%B0%B1%EB%B6%80%ED%84%B0-%EA%B0%9C%EB%B0%9C-%EC%8B%9C%EC%9E%91</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti4-%EB%B0%B1%EB%B6%80%ED%84%B0-%EA%B0%9C%EB%B0%9C-%EC%8B%9C%EC%9E%91</guid>
            <pubDate>Tue, 08 Jun 2021 08:05:18 GMT</pubDate>
            <description><![CDATA[<p>지난 번 글에서 적었다시피, 어떻게 개발을 해야하나 고민이 많았는데 질문은 대강 마무리 되었고, 추천 챔피언의 경우 LCK에서 프로 선수들의 MBTI를 조사한 바 있는데, 그것을 기반하고, 개인적인 경험과 주변의 경험을 바탕으로 결정하였다.</p>
<p>또한 추가적으로 유저의 반응을 수집하기 위해서..
결국 서버를 만드는 것이 최종적으로 결정되게 되었다.</p>
<img src="https://c.files.bbci.co.uk/16620/production/_91408619_55df76d5-2245-41c1-8031-07a4da3f313f.jpg" width="300">

<p><del>산 너머 산이다.</del></p>
<p>MySQL을 사용해볼까 잠시 고민하긴 했지만, 쿼리가 복잡하지 않을 예정이고 그냥 빠르게 값만 읽어오는 것이 주 기능이기 때문에 <strong>MongoDB</strong>를 이용한 NoSQL을 접해보기로 했다. 서버는 전에 이용했던 Express를 쓸까 잠시 고민하다가 Koa를 이용해보기로 했다.</p>
<p>Express의 개발자 분들이 Koa를 최근에 만들었다기에.. 안 써볼 수 없었다. 사실 오랜만의 백 작업이라 조금 쫄깃하다.</p>
<p>본격적으로 코딩 시작이다!</p>
<h2 id="mongodb">MongoDB</h2>
<h3 id="작업-시작하기">작업 시작하기</h3>
<p>마침, MongoDB Atlas를 무료로 이용할 수 있다고 하여 사용해보기로 했다.
Atlas 자체의 가이드가 매우 이해하기 쉽게 되어있어 처음 해보아도 잘 따라할 수 있었다.</p>
<ol>
<li>cluster 생성</li>
<li>uset 생성</li>
<li>접근을 위한 IP 추가</li>
<li>cluster에 연결하기</li>
</ol>
<h3 id="schema-만들기">Schema 만들기</h3>
<p>명세를 위한 스키마를 만들기로 했다.
가이드는 <a href="https://jun-choi-4928.medium.com/node-js-express-mongodb-tutorial-signup-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-7095aece3b99">이 블로그 글</a>을 보고 참고했고, 따라하려고 했다.</p>
<p>이 프로젝트는 총 두 개의 스키마를 가질 예정이다.</p>
<ul>
<li>스키마 1: MBTI 결과의 정보를 담고 있는 스키마</li>
<li>스키마 2: 유저의 반응을 저장할 스키마</li>
</ul>
<p>데이터베이스를 관리하는 데 다양한 방법이 있으나, 결과 페이지는 항상 16개로 고정되어 있고, 수정 작업을 하지 않을 계획이기 때문에 그냥 하나에 다 때려박을 생각이다. (그리고 나중에 알아보니 NoSQL은 조인 대신 이렇게 하나에 모아서 사용 한다고 한다.)</p>
<h4 id="modelsmbtijs">models/mbti.js</h4>
<pre><code class="language-jsx">const mongoose = require(&quot;mongoose&quot;);
const Schema = mongoose.Schema;

const MbtiSchema = new Schema({
  mbti: {
    type: String,
  },
  comment: {
    type: String,
  },
  description: {
    type: String,
  },
  recommendation: {
    type: [String],
  },
  lck: {
    type: [String],
  },
  friend: {
    type: [String],
  },
});

module.exports = mongoose.model(&quot;Mbti&quot;, MbtiSchema);
</code></pre>
<p>필요한 정보는 mbti 종류, 각 mbti에 대한 코멘트, 자세한 설명, 추천 챔피언, lck 선수명, 같이 하면 좋을 친구, 결과 이미지 링크로 정했다. (이미지가 지금은 없으므로, 스키마에 포함하지는 않았다.)
그림 그리는 분을 수배해보거나 최악의 상황에는 직접 그려야 될지도 모른다는 생각이 든다..</p>
<h3 id="구조">구조</h3>
<p>백엔드 구조는 다음과 같았다. 크게 controller/model/route로 나누어 관리할 예정이다. 
mbti의 경우 16개로 틀이 고정되어 있기도 하고, MongoDB Atlas를 이미 사용하고 있기 때문에 GUI 환경에서 추가해주려고 한다. 추가하는 코드를 작성했다가 .. 굳이 필요하지 않을 것 같아 지운 것은 안 비밀이다.</p>
<ul>
<li><strong>model</strong>: Schema 정의</li>
<li><strong>api</strong>: api안에 라우터와 라우터에서 사용될 controller를 함께 넣었다.</li>
</ul>
<h4 id="apimbtiindexjs">api/mbti/index.js</h4>
<pre><code class="language-jsx">const Router = require(&quot;koa-router&quot;);
const mbti = new Router();
const controller = require(&quot;./mbti.controller&quot;);

mbti.get(&quot;/:mbti&quot;, controller.readMbti);

module.exports = mbti;
</code></pre>
<h4 id="apimbtimbticontrollerjs">api/mbti/mbti.controller.js</h4>
<pre><code class="language-js">const Mbti = require(&quot;../../models/mbti&quot;);

exports.readMbti = async (ctx, next) =&gt; {
  const { mbti } = ctx.params;
  let result;
  try {
    result = await Mbti.find({ mbti }).exec();
    ctx.status = 200;
    ctx.body = result[0];
  } catch (error) {
    ctx.status = 500;
    ctx.body = { message: error };
  }
};
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#3: 문제 만들기가 가장 어려워]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti3-%EB%AC%B8%EC%A0%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B0%80-%EA%B0%80%EC%9E%A5-%EC%96%B4%EB%A0%A4%EC%9B%8C</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti3-%EB%AC%B8%EC%A0%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0%EA%B0%80-%EA%B0%80%EC%9E%A5-%EC%96%B4%EB%A0%A4%EC%9B%8C</guid>
            <pubDate>Mon, 07 Jun 2021 16:05:01 GMT</pubDate>
            <description><![CDATA[<h3 id="context를-이용해보자">Context를 이용해보자</h3>
<p>설계를 어떻게 할 까 고민 중에 서버와의 통신 없이 프론트엔드 상에서 정적으로 질문 리스트를 보여주기로 했다.</p>
<p>Context를 도입하기로 결정한 이유는 전역에 두 가지 정보를 가지고 있고 싶었기 때문이다.</p>
<ul>
<li>현재 취합된 설문조사 결과</li>
<li>현재 하고 있는 질문</li>
</ul>
<p>질문 부분은 reactRouter를 보면 해결될지, 이 부분은 한 번 확인해보면 좋을 것 같다.</p>
<h3 id="질문지-구성하기">질문지 구성하기</h3>
<p>질문지 구성하는 것이 가장 오래 걸릴 것이다. 현재도 이미 가장 오래 걸리고 있다. 정말 100% 딱 맞을 순 없지만 어느정도는 그럴듯한 서비스를 만들고자 했더니 생긴 고민이다.</p>
<p>아뿔싸..! 이걸 만들어주려는 친구는 MBTI 박사라고 하지만 나는 평소에 MBTI에는 전혀 관심이 없는 산업공학과 척척학사였다. <del>(이럴수가)</del></p>
<p>특히나 N/S와 P/J에 대한 질문지를 작성하는 부분이 가장 어려웠다. 그래서 이전에 비슷한 프로젝트를 하신 분들의 질문들을 많이 보려고 했다. 찾다보면 이런 질문들을 분석해둔 분의 블로그도 있다.</p>
<p>이 부분에 대해서 결과와 질문을 공개하고 싶은데. 그러면 흥미가 떨어질 테니 일단은 내 머리를 좀 더 쥐어짜볼 계획이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#2: 프론트 작업 간만 보기]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti2-%ED%94%84%EB%A1%A0%ED%8A%B8-%EC%9E%91%EC%97%85-%EA%B0%84%EB%A7%8C-%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti2-%ED%94%84%EB%A1%A0%ED%8A%B8-%EC%9E%91%EC%97%85-%EA%B0%84%EB%A7%8C-%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sun, 06 Jun 2021 17:10:09 GMT</pubDate>
            <description><![CDATA[<p>개발한 순서대로 어떻게 진행해왔는지 공부하고, 생각한 내용을 정리하고자 합니다.</p>
<h3 id="reset-css">reset-CSS</h3>
<p>리액트에서 리액트스럽게(..!) 사용할 수 있는 방법을 찾다가 <code>styled-reset</code>란 라이브러리를 발견해서 사용해주었다. App.jsx(tsx)에서 다음과 같이 가장 상위에 추가해서 사용하면 된다.</p>
<pre><code class="language-jsx">import React from &quot;react&quot;;
import { Reset } from &quot;styled-reset&quot;;

function App() {
  return (
    &lt;&gt;
      &lt;Reset /&gt;
      &lt;div className=&quot;App&quot;&gt;
        &lt;header className=&quot;App-header&quot;&gt;
        &lt;/header&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;
</code></pre>
<h3 id="interface">interface</h3>
<p>interface란, 그야말로 interface이다. (다른 언어에도 있는)
재사용 되는 곳에 사용할 수 있는데 이를 리액트에서도 사용할 수가 있다.</p>
<p>type을 사용할 수 있지만, 둘 중에 하나 일관적으로 사용하면 된다.
객체를 이용할 때 interface를 이용해 선언해 type을 정해주기로 했다.</p>
<h4 id="interface-vs-type">interface vs. type</h4>
<p>interface에서 사용할 수 있는 기능들은 type에서도 사용 가능하다.
하지만, type은 같은 이름으로 여러 번 선언하는 것이 불가한 반면, interface는 선언적 확장이 가능하다.</p>
<p>이는 새로운 속성을 추가하는 방향으로도 사용될 수 있다..!</p>
<h3 id="styled-components">Styled-components</h3>
<p><code>CSS-in-JS</code>를 이번에도 사용했다. 저번 프로젝트 때 사용했을 때 편했던 느낌이 있어서.. 고대로 도입을 해주었다.
props를 받아와서 설정을 해주는 점이 편했기 때문인데, 이번에 사용을 하다보니 어려운 점을 발견했다.</p>
<p>상위 div에 hover 되었을 때, 하위 태그의 색을 변경해주고 싶었는데 그 설정에 대해 고민을 하다가 찾은 방법은 다음과 같았다.</p>
<ul>
<li>하위 태그에 className을 설정한다.</li>
<li>상위 태그에서 CSS로 하위 해당 class에 효과를 준다.</li>
</ul>
<p>코드로 표현하면 아래와 같았다.
나의 경우, svg로 되어있는 로고를 white 색상으로 바꿔주고 싶었다.</p>
<pre><code class="language-jsx">const test = styled.div`
  &amp;:hover .logo {
    fill: white;
  }
}</code></pre>
<h3 id="리액트에서-svg-사용하기">리액트에서 svg 사용하기</h3>
<p>리액트에서 svg 파일을 사용하는데에는 여러가지 방법이 있다.</p>
<ol>
<li>Img에 소스로 넣기</li>
<li>ReactComponent 이용하기</li>
<li>라이브러리를 이용하여 component로 사용하기</li>
</ol>
<p>지난 프로젝트에서는 path의 d 값을 따로 객체로 저장한 다음에 불러오는 식으로 설정을 했는데, 이번에는 2번 방법을 이용하기로 했다.
사용하는 방법은 굉장히 쉬운데, 코드로 표현하면 다음과 같다.</p>
<pre><code class="language-jsx">import { ReactComponent as Facebook } from &quot;../Icons/svg/facebook.svg&quot;;
&lt;Facebook fill=&quot;blue&quot;/&gt;</code></pre>
<p>이 방법이 1번 보다 좋은 이유는 width나 위에 Fill처럼 svg에 지정해 주고 싶은 옵션을 넣어줄 수 있다는 점이다. :-) 좋은 방법 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[롤 mbti#1 : 기획, 스택 결정하기]]></title>
            <link>https://velog.io/@ashley_ku/%EB%A1%A4-mbti-%EB%A7%8C%EB%93%A4%EA%B8%B01-%EC%9D%B4%EA%B1%B8-%EC%99%9C-%ED%95%98%EC%A7%80</link>
            <guid>https://velog.io/@ashley_ku/%EB%A1%A4-mbti-%EB%A7%8C%EB%93%A4%EA%B8%B01-%EC%9D%B4%EA%B1%B8-%EC%99%9C-%ED%95%98%EC%A7%80</guid>
            <pubDate>Sat, 05 Jun 2021 06:49:11 GMT</pubDate>
            <description><![CDATA[<p>친구가 롤을 시작했다.
롤이 나온지도 10년이 지났는데, 내가 하는 걸 보고 친구가 협곡에 빠져버렸다.
빠져 나올 수 없는 늪에 친구를 같이 끌어당긴 것 같아 미안한 마음이 들었다.</p>
<p><img src="https://images.velog.io/images/ashley_ku/post/1db8e3ab-36d3-43a0-a69a-5dc2d0142097/image.png" alt="롤이 하고 싶은 친구"></p>
<p>친구가 어떤 챔피언을 할 지 고민하길래 하고 싶은 것을 해보라고 말하고 싶었지만.. 아뿔싸! 롤에는 챔피언이 100개 이상 존재했다. <del>그리고 진성 탑 유저인 나는 친구에게 차마 -탑신봉자-를 추천할 수는 없었다.</del></p>
<p>그래서 MBTI 잘알, 롤 초보 친구를 위한 <strong>mbti 사이트</strong>를 만들어보기로 했다.</p>
<h3 id="사전-조사">사전 조사</h3>
<p>작년에 MBTI 붐이 왔고, 롤에 이를 접목한 시도가 있었음을 확인했다. 두 가지 사이트가 존재했다. 이 글을 읽고 계시는 분 중 관심 있으신 분이 있다면 한 번 들어가서 결과를 확인해보셔도 즐거울 것이라 생각한다.</p>
<ul>
<li><p><a href="https://next.op.gg/mbti">OP.GG의 mbti 페이지</a>
  : 롤 유저라면 모두 아는 오피지지에서 만든 페이지이다. 롤 챔피언 추천이라기 보다는, 롤 플레이 스타일에 대한 결과를 얻을 수 있었다.</p>
</li>
<li><p><a href="https://lolmbti.netlify.app/">다른 개발자 분이 만든 mbti 페이지</a>
  : 롤 챔피언의 스토리를 기반으로, 나의 mbti와 챔피언의 스토리의 적합도에 알맞은 결과를 얻을 수 있다.</p>
</li>
</ul>
<p>나는 롤 잘알 친구를 설득해 용병으로 꼬드겨, 각 챔피언의 일반적인 플레이스타일과 접목시켜 mbti 기반 롤 챔피언 추천 서비스를 만들어보기로 결정했다.</p>
<h3 id="스택-결정">스택 결정</h3>
<p>그래서 어떤 것을 어떻게 만들어볼까? 고민을 시작해보았다.
사실 mbti 자체는 정적으로 동작하게 만들어도 충분히 가능하지만, 나는 나중에 통계를 기반으로<del>(물론 많은 사람들이 사용해준다는 긍정적 가정 하에)</del> 결과를 공유하고 싶은 마음이 있어 백 엔드도 구현하기로 결정했다.</p>
<p>리액트에 TS를 배워 적용해보고 싶었다. 해당 프로젝트는 나 혼자 진행하기 때문에 많은 컴포넌트는 필요 없지만 storybook이 평소에 궁금해서 추가하기로 했다.</p>
<p>[Front-End]</p>
<ul>
<li>React.js</li>
<li><del>TypeScript</del> 시간 부족으로 Javascript로 변경되었다.</li>
<li>Storybook</li>
<li>Styled-components</li>
</ul>
<p>[Back-End]</p>
<ul>
<li><del>TypeScript</del> 시간 부족으로 Javascript로 변경되었다.</li>
<li>Koa</li>
<li><del>MySQL</del> MongoDB로 변경되었다.</li>
</ul>
<p>[ETC]</p>
<ul>
<li>Git</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[this]]></title>
            <link>https://velog.io/@ashley_ku/this</link>
            <guid>https://velog.io/@ashley_ku/this</guid>
            <pubDate>Mon, 17 May 2021 16:23:43 GMT</pubDate>
            <description><![CDATA[<p>이번 장에서는 this에 대해 살펴봅니다.</p>
<ul>
<li>this가 어떻게 쓰이는지</li>
<li>함수와 객체(메서드)가 어떻게 구분되는지</li>
</ul>
<p>를 중심으로 살펴봅니다.</p>
<h1 id="여러-상황-속에서의-this">여러 상황 속에서의 this</h1>
<p>this는 실행컨텍스트가 생성될 때 함께 결정됩니다.</p>
<p>이전 장에서 보았듯이 생성 컨텍스트는 함수를 호출할 때 생성되기 때문에, 결국 this는 함수를 호출할 때 결정됩니다.</p>
<p>전역 공간, 메서드 내부, 함수 내부, 콜백 함수 내부, 생성자 함수 내부에서의 this를 차례로 살펴보겠습니다.</p>
<h2 id="1-전역-공간">1. 전역 공간</h2>
<p>전역 공간의 this는 <code>전역 객체</code>를 기킵니다.</p>
<p>전역 객체는 <strong>런타임 환경에 따라</strong> 다릅니다.</p>
<ul>
<li>브라우저: window</li>
<li>Node.js: global</li>
</ul>
<p>사실 자바스크립트의 모든 변수는 특정 객체의 프로퍼티로 동작하며, 특정 함수 호출 시 LE(Lexical Environment)를 조회하여 일치하는 프로퍼티를 반홥합니다.</p>
<p>전역변수를 선언하면 자바스크립트 엔진은 전역객체의 프로퍼티로 할당하기 때문에 전역 변수인 a를 window.a 와 this.a로 호출했을 때 같은 결과를 볼 수 있습니다. 그냥 a만 작성하였을 때도 같은 결과를 볼 수 있는 까닭은, 스코프 체인에서 a를 찾다가 마지막 전역 LE (전역 객체)에서 프로퍼티 a를 발견해서 반환하기 때문입니다. 이 경우 생략되었다고 볼 수 있습니다.</p>
<h3 id="이걸-이용해서-삭제-하면-어떻게-해요">이걸 이용해서 삭제 하면 어떻게 해요?</h3>
<p>전역 객체의 프로퍼티로 할당한 경우 삭제가 되지만, 전역 변수로 선언한 경우는 삭제가 되지 않습니다. 이를 통해 사용자가 삭제 하는 것을 방지할 수 있습니다. 전역 변수 선언시 전역객체 프로퍼티로 선언하며 <code>configurable: false</code>로 지정해주기 때문입니다. 이를 통해 변경 및 삭제를 막을 수 있습니다.</p>
<h2 id="2-메서드-호출-시-메서드-내부의-this">2. 메서드 호출 시 메서드 내부의 this</h2>
<h3 id="함수냐-메서드냐">함수냐 메서드냐</h3>
<p>함수와 메서드는 <strong>모두 미리 정의한 동작을 수행하는 코드 묶음</strong>입니다. 이 둘의 구분은 <code>독립성</code>으로 확인할 수 있습니다.</p>
<ul>
<li>함수: 그 자체로 독립적인 기능을 수행</li>
<li>메서드: 자신을 호출한 대상 객체에 관한 동작 수행</li>
</ul>
<p>코드로 살펴보면 다음과 같습니다.</p>
<pre><code class="language-js">// 함수
var func = function(x) {
    console.log(this, x);
}
// 함수 호출
func(1); </code></pre>
<pre><code class="language-jsx">// 메서드
var obj = {
    method: func
};
// 메서드 호출
obj.method(2);</code></pre>
<p>즉, 메서드는 객체의 메서드로서 호출할 경우 메서드로 동작하고 있습니다. 그렇지 않을 경우 일반 함수(func)으로 동작하는 것을 확인할 수 있습니다.</p>
<h3 id="함수로서-호출할-때-그-내부에서의-this">함수로서 호출할 때 그 내부에서의 this</h3>
<ul>
<li><p><strong>함수 내부에서의 this</strong></p>
<p>  함수로 호출할 떄는 this가 지정이 되지 않습니다. 호출 주체(여기서는 객체)에 대한 정보가 this에 담기기 때문입니다. this가 지정되지 않은 경우에는 전역 객체를 가리키기 때문에 함수에서의 this는 전역 객체를 가리키게 됩니다.</p>
</li>
<li><p><strong>메서드 내부함수에서의 this</strong></p>
<p>  호출한 함수 프로퍼티 앞의 객체를 가리킵니다.</p>
<p>   (점 표기법의 경우 마지막 점 바로 앞의 명시된 객체를 의미합니다.)</p>
</li>
<li><p><strong>메서드 내부 함수에서의 this를 우회하는 방법</strong></p>
<p>  JS의 설계 때문에 우회적으로 변수를 활용해 this를 사용할 수 있습니다.</p>
<pre><code class="language-jsx">  var obj = {
      var outer : function () {
          var self = this; // _, _this, that 등이 변수로 쓰임
          var innerFunc = function () {
              console.log(this); // Window {..} 전역
              console.log(self); // outer: f    
          }        
      }
  }</code></pre>
</li>
<li><p><strong>this를 바인딩하지 않는 화살표 함수</strong></p>
<p>  ES6에서는 함수 내부의 this가 전역개체를 바라보는 것을 해결하기 위해 this를 바인딩하지 않는 화살표 함수가 나왔습니다. 화살표 함수는 this 바인딩 과정이 빠져, 가장 가까운 상위 스코프의 this를 활용할 수 있습니다.</p>
</li>
</ul>
<h2 id="콜백함수-내부에서의-this">콜백함수 내부에서의 this</h2>
<ul>
<li><p><strong>콜백 함수</strong>란?</p>
<p>  함수의 제어권을 다른 함수(또는 메서드)에 넘겨주는 경우.</p>
<p>  제어권을 넘겨준 함수를 콜백 함수라고 합니다.</p>
</li>
</ul>
<p>콜백함수에서는 제어권을 가지는 함수가 콜백 함수에서의 this를 결정하며, 만약 지정하지 않은 경우에는 기본적인 함수와 마찬가지로 전역 객체를 바라보게 됩니다.</p>
<h2 id="생성자-함수-내부에서의-this">생성자 함수 내부에서의 this</h2>
<ul>
<li><p><strong>생성자 함수</strong>란?</p>
<p>  공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수</p>
</li>
</ul>
<p>생성자 함수 내부의 this는, 각 인스턴스 객체를 가리킵니다.</p>
<h1 id="명시적으로-this-바인딩하기">명시적으로 this 바인딩하기</h1>
<p>이 외에도 call, apply, bind 함수를 이용하여 명시적으로 대상을 바인딩 할 수 있습니다.</p>
<p>차례대로 살펴보겠습니다.</p>
<h2 id="call">call</h2>
<p><code>Function.prototype.call(thisArg[, arg1[,...]])</code></p>
<p>메서드의 호출 주체인 함수를 즉시 실행합니다.</p>
<p>call 메서드의 <strong>첫번째 인자를 this로 바인딩</strong>하고, 이후가 호출할 함수의 매개변수가 됩니다.</p>
<pre><code class="language-jsx">var func = function (a, b, c) {
    console.log(this, a, b, c);
};

func(1, 2, 3) // Window{..} 1 2 3
func.call({ x : 1 }, 4, 5, 6}; // { x : 1 } 4 5 6</code></pre>
<h3 id="apply">apply</h3>
<p><code>Function.prototype.apply(thisArg[, arg1[,...]])</code></p>
<p>call 메서드와 기능적으로 동일하나, 두 번째 인자를 <strong>배열로 받아 매개변수로 지정</strong>한다는 점에서 차이가 있습니다.</p>
<pre><code class="language-jsx">var func = function (a, b, c) {
    console.log(this, a, b, c);
};

func.apply({x: 1}, [4, 5, 6]); // {x: 1} 4 5 6</code></pre>
<h3 id="callapply의-활용">call/apply의 활용</h3>
<ul>
<li><p>유사 배열객체(array-like object)에 배열 메서드 적용</p>
<pre><code class="language-jsx">  var obj = {
  0: &#39;a&#39;,
      1: &#39;b&#39;,
      2: &#39;C&#39;,
      length: 3
  };

  Array.prototype.push.call(obj, &#39;d&#39;); // 3 자리에 d들어감
  var arr = Array.prototype.slice.call(obj); // 얕은 복사 - [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;];</code></pre>
<ul>
<li><p>arguments, NodeList에 배열 메서드 적용</p>
</li>
<li><p>문자열에 배열 메서드 적용</p>
</li>
<li><p>Array.from 메서드</p>
<p>  유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환할 수 있습니다.</p>
</li>
</ul>
</li>
<li><p>생성자 내부에서 다른 생성자 호출</p>
</li>
<li><p>여러 인수를 묶어 하나의 배열로 전달하고 싶을 때</p>
</li>
</ul>
<h3 id="bind">bind</h3>
<p><code>Function.prototype.bind(thisArg, [, arg1,...]])</code></p>
<p>ES5에 추가된 기능으로, call과 비슷하지만 즉시 호출하지는 않고 넘겨받은 <strong>this 및 인수들을 바탕으로 새로운 함수를 반환</strong>하는 메서드입니다.</p>
<pre><code class="language-jsx">var func = function (a, b, c, d) {
    console.log(this, a, b, c, d);
};

func(1, 2, 3, 4); // 전역

var bindFunc1 = func.bind({ x: 1 });
bindFunc1(5, 6, 7, 8); // { x: 1} 5 6 7 8

var bindFunc2 = func.bind({ x: 1}, 4, 5);
bindFunc2(6, 7); // { x: 1 } 4 5 6 7</code></pre>
<ul>
<li>name프로퍼티를 사용하여 원본 함수를 추적할 수 있습니다.</li>
</ul>
<pre><code class="language-jsx">console.log(func.name); // func
console.log(bindFunc2.name); // bound func</code></pre>
<h3 id="콜백함수-내에서의-this">콜백함수 내에서의 this</h3>
<p>콜백함수와 함께 thisArg를 인자로 받는 메서드는 다음과 같습니다.</p>
<ul>
<li>forEach, map, filter, some, every, find, findIndex, flatMap, from, forEach(Set, Map에 해당)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 렌더링 동작과정]]></title>
            <link>https://velog.io/@ashley_ku/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@ashley_ku/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Tue, 11 May 2021 09:31:33 GMT</pubDate>
            <description><![CDATA[<h4 id="0-html-css-다운로드">0) HTML, CSS 다운로드</h4>
<h4 id="1-다운로드-정보-기반으로-domdocument-object-model--cssomcss-object-model-생성">1) 다운로드 정보 기반으로 DOM(Document Object Model) &amp; CSSOM(CSS Object Model) 생성</h4>
<p>HTML과 CSS는 단순한 텍스트이기 때문에 연산과 관리가 유리하도록 Object Model로 만들게 됩니다. 모든 HTML 파싱이 끝나지 않았더라도, 이후의 과정을 수행하여 미리 보여줄 수 있는 내용을 출력하기도 합니다.</p>
<h4 id="2-render-tree-생성">2) Render Tree 생성</h4>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f765bc6e-fb1a-4b6e-91db-2439aebda379/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210511%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210511T092518Z&X-Amz-Expires=86400&X-Amz-Signature=48463bdab2dfe5c6ea164158e592be58740bd40d5e9a1d6412dcaeafe9f2c4ae&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22" alt="img"></p>
<p>DOM 과 CSSOM tree에 기반하여 Render Tree를 생성합니다. DOM에다가 CSSOM 의 스타일 정보가 설정되는 과정입니다. 실제 표현되는 노드들로 트리가 구성되게 됩니다.</p>
<p>안 보이게 하는 방법 중 <code>display: none;</code>은 공간을 차지하지 않기 때문에 Render tree에 포함되지 않고, <code>visibility: invisible</code>은 보이지 않지만 공간은 차지하기 때문에  Render tree에 포함됩니다.</p>
<h4 id="3-layout">3) Layout</h4>
<p>브라우저에서의 Viewport 내에서 노드들의 위치와 크기를 계산합니다. Layout 단게에서는 브라우저 화면에서의 위치와, 크기를 계산합니다. %, vh, vw와 같은 상대적인 속성을 px로 변환하는 단계라고 볼 수 있습니다.</p>
<h4 id="4-paint">4) Paint</h4>
<p>Layout 계산을 했으니 이제 실제 화면을 그리기 위해서 텍스트, 색, 이미지, 그림자 효과 등이 처리됩니다. 당연히 단순한 색상 보다는 그라데이션이나 그림자 효과 같은 것은 paint 과정이 더 오래 걸립니다.</p>
<ul>
<li><p><strong>Reflow</strong> (Layout)</p>
<p>  액션이나 이벤트에 따라 레이아웃 수치를 다시 결정하는 것을 reflow라고 합니다.</p>
<ul>
<li>페이지 초기 렌더링, 윈도우 리사이징(viewport 변경), 노드 추가 또는 제거, 요소의 위치 또는 크기 변경, 폰트나 텍스트 또는 이미지 크기 변경</li>
</ul>
</li>
<li><p><strong>Repaint</strong> (Paint)</p>
<p>  Reflow과정만 하면 실제로 반영이 안되기 때문에 Render tree를 화면에 다시 그려주는 paint 과정이 필요합니다. 색상 변경과 같은 paint과정만 필요한 것은 repaint만 수행됩니다.</p>
</li>
<li><p>Reflow, Repaint 줄이기</p>
<p>  1) 사용하지 않는 노드에는 visibility: invisible보다는 display: none 사용</p>
<p>  2) Reflow, Repaint가 발생하는 속성 피하기</p>
<p>  3) 영향을 주는 노드 줄이기 (ex. position: absolute || fixed)</p>
<p>  4) 프레임 줄이기 (조금 더 버벅거리더라도)</p>
</li>
<li><p>Virtual DOM이 필요한 이유</p>
<p>  실제의 DOM에 적용하기 전에 변화가 생긴다면 Virtual DOM에 적용시킨 뒤 최종적인 결과를 실제 DOM으로 전달합니다. 30개의 엘리먼트가 변했을 경우에, 30번 바뀌는 것 대신 한 번만 변경하면 되는 것입니다. 이는 React가 DOM보다 빠르지는 않지만 유지보수가 가능하고 충분히 빠르기에 사용되는 이유입니다. (손수 코드를 작성하는 것보다 나와있는 프레임워크를 사용하는 것이 편하기 때문에)</p>
</li>
</ul>
<h4 id="references">References</h4>
<ul>
<li>박스여우님: <a href="https://boxfoxs.tistory.com/408">브라우저 렌더링 동작과정 및 성능최적화</a></li>
<li>Velopert님: <a href="https://velopert.com/3236">왜 Virtual DOM인가?</a></li>
<li>구글 developers: <a href="https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=ko">렌더링 트리 생성, 레이아웃 및 페인트</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>