<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jjo-niixx.log</title>
        <link>https://velog.io/</link>
        <description>싱글벙글</description>
        <lastBuildDate>Tue, 26 Jan 2021 10:36:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jjo-niixx.log</title>
            <url>https://images.velog.io/images/jjo-niixx/profile/cd162608-0056-4355-a7c1-2f65331800f4/말레이시아 배경 사진.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jjo-niixx.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jjo-niixx" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[React, TypeScript, Styled-Components (with CRA)]]></title>
            <link>https://velog.io/@jjo-niixx/React-TypeScript-Styled-Components-with-CRA-i8aukv4e</link>
            <guid>https://velog.io/@jjo-niixx/React-TypeScript-Styled-Components-with-CRA-i8aukv4e</guid>
            <pubDate>Tue, 26 Jan 2021 10:36:30 GMT</pubDate>
            <description><![CDATA[<p>React, TypeScript, Redux Middleware, Styled-Components를 통해 개인 프로젝트를 만들어보려 한다. 이곳에 차근차근 정리해야지 ^_^</p>
<h3 id="1-라이브러리-설치">1. 라이브러리 설치</h3>
<h4 id="타입스크립트">타입스크립트</h4>
<p>타입스크립트로 새로운 create-react-app 프로젝트를 생성하고 싶다면</p>
<pre><code>npx create-react-app &lt;프로젝트&gt; --template typescript</code></pre><h4 id="스타일-컴포넌트">스타일 컴포넌트</h4>
<pre><code>npm install --save @types/styled-components</code></pre><h4 id="스타일-리셋">스타일 리셋</h4>
<pre><code>npm install --save styled-reset</code></pre><h4 id="리액트-라우터-돔">리액트 라우터 돔</h4>
<pre><code>npm install --save @types/react-router-dom</code></pre><h4 id="리덕스">리덕스</h4>
<pre><code>npm install --save @types/redux
npm install --save @types/react-redux</code></pre><h3 id="2-불필요한-파일-삭제">2. 불필요한 파일 삭제</h3>
<ul>
<li>public 내부: index.html의 주석, logo.png, manifest.json, robots.txt</li>
<li>src 내부: App.test.tsx, App.css, index.css, logo.svg, setupTests.ts</li>
</ul>
<h4 id="react-app-envdts-역할">react-app-env.d.ts 역할</h4>
<p>이 파일은 src 폴더 안에 존재하는데 CRA로 만들어진 프로젝트에 특정하는 타입스크립트 타입 유형을 알려준다. 여기에 있는 타입 유형은 bmp, gif, jpeg, jpg, png, webp, svg와 같은 파일의 임포트를 지원해준다.</p>
<pre><code>import logo from &#39;./logo.svg&#39;;</code></pre><p>결국 위와 같은 형태의 임포트를 지원하는 것.</p>
<p>에러를 피하기 위해서 지우지 않는 것을 추천한다.</p>
<h4 id="reportwebvitalsts-역할">reportWebVitals.ts 역할</h4>
<p>CRA 프로젝트의 성능과 responsiveness를 측정하게끔 도와주는 역할을 한다.
<code>to be continue</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP]]></title>
            <link>https://velog.io/@jjo-niixx/HTTP</link>
            <guid>https://velog.io/@jjo-niixx/HTTP</guid>
            <pubDate>Tue, 26 Jan 2021 09:46:15 GMT</pubDate>
            <description><![CDATA[<h2 id="http"><strong>HTTP</strong></h2>
<ul>
<li>HyperText Transfer Protocol</li>
<li>하이퍼텍스트(HTML) 문서를 교환하기 위해 만들어진 protocol(통신 규약).<ul>
<li>즉 웹상에서 네트워크로 서버끼리 통신을 할때 어떠한 형식으로 서로 통신을 하자고 규정해 놓은 “통신 형식” 혹은 “통신 구조” 라고 보면 된다.</li>
<li>프론트앤드 서버와 클라이언트간의 통신에 사용된다.</li>
<li>또한 백앤드와 프론트앤드 서버간에의 통신에도 사용된다.</li>
</ul>
</li>
<li>HTTP는 TCP/IP 기반으로 되어있다.</li>
</ul>
<h2 id="http-핵심-요소"><strong>HTTP 핵심 요소</strong></h2>
<p>HTTP 통신 방식</p>
<ul>
<li>HTTP 기본적으로 요청/응답 (request/response) 구조로 되어있다.<ul>
<li>클라이언트가 HTTP request를 서버에 보내면 서버는 HTTP response를 보내는 구조.</li>
<li>클라이언트와 서버의 모든 통신이 요청과 응답으로 이루어 진다.</li>
<li>HTTP는 Stateless 이다.</li>
</ul>
</li>
<li>Stateless 란 말그대로 state(상태)를 저장하지 않는 다는 뜻.</li>
<li>즉, 요청이 오면 그에 응답을 할뿐, 여러 요청/응답 끼리 연결되어 있지 않다는 뜻이다. 즉 각각의 요청/응답은 독립적인 요청/응답 이다.</li>
<li>예를 들어, 클라이언트가 요청을 보내고 응답을 받은후, 조금 있다 다시 요청을 보낼때, 전에 보낸 요청/응답에 대해 알지 못한다는 뜻이다.</li>
<li>그래서 만일 여러 요청과응답 의 진행과정이나 데이터가 필요할때는 쿠키나 세션 등등을 사용하게 된다.</li>
</ul>
<p>HTTP Request 구조</p>
<ul>
<li>HTTP request 메세지는 크게 3부분으로 구성된다:<ul>
<li>status line</li>
<li>headers</li>
<li>body</li>
</ul>
</li>
</ul>
<p>HTTP Response 구조</p>
<ul>
<li>Response도 request와 마찬가지로 크게 3부분으로 구성되어 있다.<ul>
<li>status line</li>
<li>Headers</li>
<li>Body</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Pattern Matching 알고리즘]]></title>
            <link>https://velog.io/@jjo-niixx/Pattern-Matching-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@jjo-niixx/Pattern-Matching-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sun, 24 Jan 2021 07:48:59 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>하나의 긴 문자열에 배열 안의 단어가 포함되어 있으면 true, 포함되어 있지 않으면 false를 반환하라. 이때 string match 메소드는 사용하지 않도록 한다.</p>
<pre><code class="language-jsx">checkString(&quot;abcdabce&quot;, [&quot;abcd&quot;, &quot;abce&quot;]); // returns [true, true]
checkString(&quot;abcababcde&quot;, [&quot;abc&quot;]) // returns [true]
checkString(&quot;i am gonna be a frontend developer&quot;, [&quot;i&quot;, &quot;gonna&quot;, &quot;backend&quot;]); // returns [true, true, false]</code></pre>
<h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙅🏻♀️-나의-첫-번째-풀이">🙅🏻‍♀️ 나의 첫 번째 풀이</h3>
<pre><code class="language-jsx">function checkString(largeStr, smallStr) {
  const length = largeStr.length;
  const arr = smallStr.map((str) =&gt; {
    for (let i = 0; i &lt; length; i++) {
      if (largeStr[i] === str[0]) {
        for (let j = 0; j &lt; str.length; j++) {
          if (largeStr[i + j] !== str[j]) return false;
        }
        return true;
      }
    }
  });
  return arr;
}</code></pre>
<p>결론부터 말하자면 이 풀이는 틀렸다. 그리고 비효율적이다.</p>
<p>largeStr을 하나하나 탐색하며 smallStr의 요소의 0번째 인덱스와 일치하면 그 요소의 길이만큼 탐색을 시작해 단 하나라도 다르면 false를 반환하는 것이다. 여기서 문제는 largeStr에 반복되는 문자열이 있을 경우다.  <code>&quot;abcdabce&quot;</code> 과  <code>[&quot;abcd&quot;, &quot;abce&quot;]</code> 를 비교할 때 <code>[true, false]</code> 가 나온다. 그 이유는 smallStr의 요소의 0번째 인덱스가 largeStr의 일부와 일치하는 곳이 두 부분인데 지금의 로직대로라면 앞 부분과만 비교를 하기 때문이다.</p>
<p>그리고 비교를 할 때마다 largeStr의 처음부터 검색하고 인덱스를 1씩 옮기므로 비효율적이다. 만약에 smallStr의 요소와 largeStr이 일치하지 않더라도 끝까지 하나하나 탐색할 것이다. </p>
<h3 id="🙆🏻♀️-나의-두-번째-풀이">🙆🏻‍♀️ 나의 두 번째 풀이</h3>
<pre><code class="language-jsx">function checkString(largeStr, smallStr) {
  const length = largeStr.length;
  const arr = smallStr.map((str) =&gt; {
    let check = true;
    for (let i = 0; i &lt; length; i++) {
      if (largeStr[i] === str[0]) {
        for (let j = 1; j &lt; str.length; j++) {
          if (largeStr[i + j] !== str[j]) {
            check = false;
            break;
          }
          check = true;
        }
        if (check) return true;
      }
    }
    return check;
  });
  return arr;
}</code></pre>
<blockquote>
<p>break문, continue문</p>
</blockquote>
<ul>
<li>break문을 쓸 때: 가장 가까운 while, do-while, for, 또는 switch문을 종료하고 다음 명령어로 넘어갑니다.</li>
<li>continue를 사용하는 경우, 그것은 가장 안쪽의 while, do-while, for 문을 둘러싼 현재 반복을 종료하고, 다음 반복으로 루프의 실행을 계속합니다. break문과 달리, continue 문은 전체 루프의 실행을 종료하지 않습니다. while 루프에서 그것은 다시 조건으로 이동합니다. for 루프에서 그것은 증가 표현으로 이동합니다.</li>
</ul>
<p>나의 첫 번째 풀이가 비효율적이라는 것은 알지만 최대한 풀이를 활용하고 싶어서 <code>break</code> 를 써보았다. 전처럼 검색하는 문자가 다를 때 바로 리턴하지 않고 check 변수에 false를 할당하며 두 번째 for 문을 빠져나간다. 그리고 리턴되지 않았으니 끝까지 탐색하게 만든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[KMP 알고리즘]]></title>
            <link>https://velog.io/@jjo-niixx/KMP-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@jjo-niixx/KMP-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Fri, 22 Jan 2021 14:50:27 GMT</pubDate>
            <description><![CDATA[<h2 id="kmp-algorithm">KMP Algorithm</h2>
<h3 id="미리-알아야할-개념">미리 알아야할 개념</h3>
<ul>
<li>접두사(prefix)</li>
</ul>
<p>AABAABAC의 접두사: A / AA / AAB / AABA /  AABAA / AABAAB / AABAABA / AABAABAC</p>
<ul>
<li>접미사(suffix)</li>
</ul>
<p>AABAABAC의 접미사: C / AC / BAC / ABAC / AABAC / BAABAC / ABAABAC / AABAABAC</p>
<ul>
<li>pi 배열</li>
</ul>
<p>부분 문자열 중에서 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[0] = 0 → A의 접두사도 되고 접미사도 되는 문자열의 최대 길이 </p>
<p>pi[1] =  1 → AA의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[2] = 0 → AAB의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[3] = 1 → AABA의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[4] = 2 → AABAA의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[5] = 3 → AABAAB의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[6] = 4 → AABAABA의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<p>pi[7] = 0 → AABAABAC의 접두사도 되고 접미사도 되는 문자열의 최대 길이</p>
<h3 id="kmp-알고리즘의-원리">KMP 알고리즘의 원리</h3>
<p>KMP 알고리즘은 검색 과정에서 얻는 정보를 버리지 않고 활용해서 시간을 절약한다. 즉, <strong>불일치가 일어났을 때 지금까지 일치한 글자의 수를 이용해 시도해야할 시작 위치를 빠르게 찾아낸다.</strong></p>
<pre><code class="language-jsx">// 예를 들어 ABCAABAABACAABC(텍스트)에서 AABAABAC(패턴)가 어디에 있는지 찾는다고 가정해보자.

// 보통 하나하나 탐색한다고 하면 이런 식으로 풀이가 진행될 것이다.
A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
A | A | B | A | A | B | A | C

A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
    A | A | B | A | A | B | A | C

A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
        A | A | B | A | A | B | A | C

A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
            A | A | B | A | A | B | A | C</code></pre>
<p>위와 같은 풀이에서 텍스트의 길이가 N, 패턴의 길이가 M이라고 했을 때 텍스트의 각 인덱스에 대해 패턴을 검색하므로 시간 복잡도는 O(NM)이 된다.</p>
<p>이 풀이에서는 검색을 할 때마다 틀린 부분에 집중하며 검색을 한다.</p>
<pre><code class="language-jsx">// KMP 알고리즘을 이용해서 풀면 아래와 같은 탐색을 하면 된다.
A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
A | A | B | A | A | B | A | C

A | B | C | A | A | B | A | A | B | A | C | A | A | B | C |
            A | A | B | A | A | B | A | C</code></pre>
<p>KMP 알고리즘을 이용한다면 위와 같은 풀이로 될 것이고, 시간 복잡도는 O(N+M)이 된다.</p>
<p>이 풀이를 사용해서 얻은 장점은 명확하다. 원래 처럼 인덱스를 하나 하나 옮기며 비교한 것이 아니라 전에 했던 비교를 통해서 알게 된 부분을 활용하고 있다.</p>
<p>첫 번째 검색에서 알게된 사실은 패턴에서 <strong>pi[5] =  4</strong>라는 것과 텍스트와 패턴의 비교에서 <strong>연속하는 AABA</strong>가 매치되었다는 것이다. 텍스트와 패턴이 일치하기 위해서는 AABA 접두사부터 시작해야한다. 그리고 텍스트와 패턴이 일치하는 부분에서 AABA가 존재한다. 그러므로 다음 검색부터는 텍스트 기준 3번 째 인덱스부터 검색을 시작해도 좋다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Even Binary Sorting]]></title>
            <link>https://velog.io/@jjo-niixx/Even-Binary-Sorting</link>
            <guid>https://velog.io/@jjo-niixx/Even-Binary-Sorting</guid>
            <pubDate>Sun, 17 Jan 2021 14:58:59 GMT</pubDate>
            <description><![CDATA[<h3 id="🙅🏻♀️-나의-첫-번째-풀이">🙅🏻‍♀️ 나의 첫 번째 풀이</h3>
<pre><code>function evenBinary(n) {
  const splittedN = n.split(&quot; &quot;);
  const sortedEvenArr = splittedN.filter((num) =&gt; num[2] === `0`).sort();
  let evenArrIdx = 0;
  for (let i = 0; i &lt; splittedN.length; i++) {
    if (splittedN[i][2] === `0`) {
      splittedN.splice(
        splittedN.indexOf(splittedN[i]),
        1,
        sortedEvenArr[evenArrIdx]
      );
      evenArrIdx++;
    }
  }
  return splittedN;
}</code></pre><h3 id="🙆🏻♀️-나의-두-번째-풀이">🙆🏻‍♀️ 나의 두 번째 풀이</h3>
<pre><code>function evenBinary(n) {
  const splittedN = n.split(&quot; &quot;);
  const sortedEvenArr = splittedN.filter((num) =&gt; num[2] === `0`).sort();
  let evenArrIdx = 0;
  for (let i = 0; i &lt; splittedN.length; i++) {
    if (splittedN[i][2] === `0`) {
      splittedN.splice(i, 1, sortedEvenArr[evenArrIdx]);
      evenArrIdx++;
    }
  }
  return splittedN;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저에 URL 입력 후 일어나는 일]]></title>
            <link>https://velog.io/@jjo-niixx/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-URL-%EC%9E%85%EB%A0%A5-%ED%9B%84-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC</link>
            <guid>https://velog.io/@jjo-niixx/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-URL-%EC%9E%85%EB%A0%A5-%ED%9B%84-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC</guid>
            <pubDate>Fri, 15 Jan 2021 04:33:08 GMT</pubDate>
            <description><![CDATA[<p><a href="https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a">이 포스팅을 참고하여 번역한 글입니다.</a></p>
<h3 id="1-브라우저의-주소창에-mapsgooglecom을-입력한다">1. 브라우저의 주소창에 maps.google.com을 입력한다.</h3>
<h3 id="2-브라우저는-mapsgooglecom에-상응하는-ip-주소를-찾기-위해서-dns-기록-캐시를-확인한다">2. 브라우저는 maps.google.com에 상응하는 IP 주소를 찾기 위해서 DNS 기록 캐시를 확인한다.</h3>
<p>DNS(Domain Name System)은 웹사이트의 이름(URL)과 그것이 연결된 IP 주소를 갖고 있는 데이터베이스이다. 모든 URL은 자신만의 IP 주소를 가지고 있다. 이때 IP 주소는 우리가 접속하려하는 웹사이트의 서버를 가지고 있는 컴퓨터에 있다.</p>
<p>DNS의 주목적은 인간 친화적인 저장소이다. 원하는 웹사이트에 IP 주소를 브라우저에 입력해서 접근할 수 있다. 하지만 많은 숫자의 조합으로 되어있는 IP 주소를 모두 기억할 수 있을까? 아닐 것이다. 그러므로 URL을 이용해 웹사이트의 이름을 기억하는 것이 더 쉽고, DNS가 URL을 올바른 IP와 이어주는 일을 담당하게 된다.</p>
<p>DNS 기록을 찾기 위해서 브라우저는 <strong>browser → OS → router → ISP순으로 확인한다.</strong> 흠.. 왜 이렇게 많은 단계에 캐시가 저장되어 있는 것일까? 프라이빗한 정보라면 불안할 수도 있지만, 캐시는 네트워크 트래픽을 통제하고 데이터 전송 시간을 높이는데 필수적으로 필요하기 때문이다.</p>
<h3 id="3-만약에-요청한-url이-캐시에-없다면-isp의-dns-서버는-mapsgooglecom을-갖는-서버의-ip-주소를-찾기-위해-dns-query를-시작한다">3. 만약에 요청한 URL이 캐시에 없다면 ISP의 DNS 서버는 maps.google.com을 갖는 서버의 IP 주소를 찾기 위해 DNS query를 시작한다.</h3>
<p>내 컴퓨터가 maps.google.com을 호스트하는 서버와 통신하기 위해서 IP 주소가 필요하다. DNS 쿼리의 목적은 올바른 IP 주소를 찾을 때까지 인터넷에 있는 많은 DNS 서버를 검색하는 것이다. 이런 식의 검색을 recursive search (반복되는 검색) 라고 한다. 이 검색은 한 DNS 서버에서 다른 DNS 서버로 옮겨가며 IP 주소를 찾을 때까지 혹은 못 찾겠다는 응답을 반환할 때까지 계속하게 된다.</p>
<p>이러한 상황에서 ISP의 DNS 서버를 DNS resursor라고 부른다. 이 서버는 인터넷에 있는 다른 DNS 서버에 물어봄으로써 도메인 이름에 대한 적절한 IP 주소를 찾아야 한다. 이때 다른 DNS 서버는 name server라고 부르는데 웹사이트의 도메인 이름의 구조를 기반으로해서 DNS 검색을 수행하기 때문이다. </p>
<p><img src="https://images.velog.io/images/jjo-niixx/post/a90b63e9-dd57-4c00-b17d-24ad5d2aa49f/0*udK6jZ3PjlhjqW8U.png" alt=""></p>
<p>위 그림은 도메인 구조에 대한 설명이다. 오늘날 우리가 접하는 URL은 대부분 third-level, second-level, top-level 도메인을 가지고 있고, 각 도메인은 DNS 검색 과정 동안 쿼리하는 자신만의 name serer를 가진다.</p>
<p>maps.google.com을 예로 들어보자. 첫 번째로 DNS recursor는 루트 네임 서버에 접촉한다. 루트 네임 서버는 <strong>.com</strong> 도메인 네임 서버로 다시 보낸다. .com 네임 서버는 <strong>google.com</strong> 네임 서버로 다시 보낸다. google.com 네임 서버는 자신의 DNS 기록에서 maps.google.com에 매칭하는 IP 주소를 찾을 것이고 DNS resursor에 반환하게 된다. 그리고 DNS recursor는 브라우저에 IP 주소를 보내게 된다.</p>
<h3 id="4-브라우저는-서버와-tcp-통신을-시작한다">4. 브라우저는 서버와 TCP 통신을 시작한다.</h3>
<p>브라우저가 올바른 IP 주소를 받으면, IP 주소가 일치하는 서버와 정보 전달을 위한 연결을 시도한다. 브라우저는 그러한 연결을 위해 인터넷 프로토콜을 사용한다. 여기에 사용되는 인터넷 프로토콜 중에 TCP가 HTTP 요청을 위채 사용되는 가장 흔한 방법인다.</p>
<p>컴퓨터와 서버간의 데이터 패킷 전송을 위해 TCP 연결이 만들어지는 것이 가장 중요하다. 이 연결은 <strong>TCP/IP three-way handshake</strong>과정을 통해 만들어진다. 이것은 클라이언트와 서버가 연결 하기 위해서 SYN(synchronize), ACK(acknowledge) 메세지를 교환하는 과정을 의미한다.</p>
<ol>
<li>클라이언트 기계는 서버가 새 연결을 위해 열려있는지 물어보며 서버에 SYN 패킷을 보낸다.</li>
<li>만약 서버가 새 연결을 시작할 수 있는 오픈 포트를 가진다면, SYN/ACK 패킷을 사용하여 SYN 패킷의 ACKnowledgement로 응답한다.</li>
<li>클라이언트가 서버로부터 SYN/ACK 패킷을 받을 것이고 서버에 ACK 패킷을 보냄으로써 받았음을 알려줄 것이다.</li>
</ol>
<p>그러면 데이터 전송을 위한 TCP 통신이 이루어진다!!</p>
<h3 id="5-브라우저는-웹-서버에-http-요청을-보낸다">5. 브라우저는 웹 서버에 HTTP 요청을 보낸다.</h3>
<p>자 TCP 연결이 되면 데이터를 전송할 때다. 브라우저는 maps.google.com 페이지에 대해 묻는 GET 요청을 보낼 것이다. 만약에 증명 정보를 입력하거나 폼을 제출한다면 이 요청은 POST가 될 것이다. 이 요청은 브라우저 식별 정보(User-Agent header), 수락에 대한 요청(Accept header), TCP 연결을 유지하도록 요청하는 connection header 등에 대한 추가적인 정보를 가질 수 있다. 또한 브라우저가 도메인 저장소에 갖는 쿠키로부터 가져온 정보를 넘길 수도 있다.</p>
<p>아래 그림은 GET 요청에 대한 예시이다.
<img src="https://images.velog.io/images/jjo-niixx/post/34011a79-050a-4a49-a9e2-8477435f1072/0*SyxEqHOBZElX5laf.png" alt=""></p>
<h3 id="6-서버는-요청을-처리하고-응답을-다시-보낸다">6. 서버는 요청을 처리하고 응답을 다시 보낸다.</h3>
<h3 id="7-서버는-http-응답을-내보낸다">7. 서버는 HTTP 응답을 내보낸다.</h3>
<p>서버 응답은 요청한 페이지와 함께 status code, compression type(Content-Encoding), 페이지를 캐시하는 법(Cache-Control), 프라이빗 정보 등을 담고 있다.</p>
<p>아래 그림은 HTTP 서버 응답에 대한 예시이다.
<img src="https://images.velog.io/images/jjo-niixx/post/c9b89e7e-f222-4278-9040-f4eac1a5ead6/gg.png" alt=""></p>
<h3 id="8-브라우저는-html-컨텐츠를-표시한다">8. 브라우저는 HTML 컨텐츠를 표시한다.</h3>
<p>브라우저는 HTML 내용을 표시한다. 첫 번째로 HTML 뼈대만 렌더한다. 그리고 HTML 태그를 확인하고 이미지, CSS stylesheet, JavaScript 파일과 같은 추가적인 요소에 대한 GET 요청을 내보낸다. static file(js, css, image 등과 같이 개발자가 사전에 미리 서버에 저장 해둔 파일)은 브라우저에 의해 캐시되기 때문에 다음에 동일한 페이지를 방문했을 때 그것들을 다시 fetch할 필요가 없는 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Multiples of 3 or 5]]></title>
            <link>https://velog.io/@jjo-niixx/Multiples-of-3-or-5</link>
            <guid>https://velog.io/@jjo-niixx/Multiples-of-3-or-5</guid>
            <pubDate>Mon, 11 Jan 2021 14:59:32 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>number가 인자로 주어질 때, number 미만의 수 중에서 3과 5의 배수의 합을 구하여라. 이때 각 배수는 딱 한 번씩만 세어진다. number가 음수라면 0을 반환한다.</p>
<pre><code>solution (10) // returns 23</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙆🏻♀️-나의-첫-번째-풀이">🙆🏻‍♀️ 나의 첫 번째 풀이</h3>
<pre><code>function solution(number) {
  let sum = 0;
  if (number &lt; 0) {
    return sum;
  } else {
    for (let i = 1; i &lt; number; i++) {
      if (i % 3 === 0 || i % 5 == 0) {
        sum += i;
      }
    }
    return sum;
  }
}</code></pre><h3 id="✅-첫-번째-풀이-리팩토링">✅ 첫 번째 풀이 리팩토링</h3>
<p>사실 원래 풀이에서 number가 음수일 때를 조건으로 나누었는데 그럴 필요가 없었다. for문에서 i의 시작값을 1로 했고 number가 1보다 작다면 조건에 충족이 되지 않아 연산이 될 이유가 없기 때문이다.</p>
<p>for문에서 if문을 삼항연산자로 바꿀 수 있을 것 같아 바꿔보았다.</p>
<pre><code>function solution(number) {
  let sum = 0;
  for (let i = 1; i &lt; number; i++) {
    i % 3 === 0 || i % 5 == 0 ? (sum += i) : sum;
  }
  return sum;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Calculating with Functions]]></title>
            <link>https://velog.io/@jjo-niixx/Calculating-with-Functions</link>
            <guid>https://velog.io/@jjo-niixx/Calculating-with-Functions</guid>
            <pubDate>Tue, 05 Jan 2021 01:30:30 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>함수 이름에 맞는 숫자 및 연산자가 리턴되게끔 만들어야 한다. 반드시 2개의 숫자, 연산자가 나온다.</p>
<pre><code>seven(times(five())); // must return 35
four(plus(nine())); // must return 13
eight(minus(three())); // must return 5
six(dividedBy(two())); // must return 3
eight(dividedBy(three())); // must return 2</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙆🏻♀️-나의-첫-번째-풀이">🙆🏻‍♀️ 나의 첫 번째 풀이</h3>
<p>우선 리팩토링이 필요할 것 같지만,, 첫 번째 풀이는 이러하다. 숫자 함수는 인자 유무에 따라 리턴 값이 달라진다. 똑같은 로직이지만 인자에 따라 다른 값을 원했기 때문에 <code>operation</code> 함수를 이용했고, 두 가지 경우의 수가 있기 때문에 두 개의 인자를 받게 했다.</p>
<p>결과적으로 <code>&quot;5*6&quot;</code>과 같은 스트링이 <code>operation</code>의 최종 리턴 값으로 나왔는데 <code>eval()</code>을 이용해서 문제를 해결했다.</p>
<blockquote>
<p>💡 eval()
문자로 표현된 JavaScript 코드를 실행하는 함수.</p>
</blockquote>
<p>아마 이 함수는 쓰지 말아야할 것 같다. 방금 찾아보니 이 함수를 쓰는 것은 엄청나게 위험하며 해커가 위험한 코드를 사용할 수 있어 절대 사용하지 말라고 MDN에서 일러준다....</p>
<pre><code>function zero(left) {
  return operation(left, 0);
}
function one(left) {
  return operation(left, 1);
}
function two(left) {
  return operation(left, 2);
}
function three(left) {
  return operation(left, 3);
}
function four(left) {
  return operation(left, 4);
}
function five(left) {
  return operation(left, 5);
}
function six(left) {
  return operation(left, 6);
}
function seven(left) {
  return operation(left, 7);
}
function eight(left) {
  return operation(left, 8);
}
function nine(left) {
  return operation(left, 9);
}

function operation(left, num) {
  return left ? Math.floor(eval(num + left)) : num;
}

function plus(right) {
  return &quot;+&quot; + right;
}
function minus(right) {
  return &quot;-&quot; + right;
}
function times(right) {
  return &quot;*&quot; + right;
}
function dividedBy(right) {
  return &quot;/&quot; + right;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Roman Numerals Decoder]]></title>
            <link>https://velog.io/@jjo-niixx/Roman-Numerals-Decoder</link>
            <guid>https://velog.io/@jjo-niixx/Roman-Numerals-Decoder</guid>
            <pubDate>Sat, 02 Jan 2021 12:56:20 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>로마 숫자를 정수로 변환 해야한다. 여기서 각 자리 문자의 변환값이 내림차순이라면 +, 오름차순이라면 -</p>
<pre><code>Symbol    Value
 I          1
 V          5
 X          10
 L          50
 C          100
 D          500
 M          1,000</code></pre><pre><code>solution(&#39;XXI&#39;); // should return 21
solution(&#39;IV&#39;); // should return 4</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙆🏻♀️-첫-번째-풀이">🙆🏻‍♀️ 첫 번째 풀이</h3>
<p>각 자리의 문자를 숫자로 변환하는 것을 고민했는데 역시나 이럴 때는 객체만한 것이 없는 것 같다.</p>
<p>일단 split한 인자의 value를 구해서 더했는데, 이 문제의 핵심은 오름차순인 경우에는 어떻게 처리할 것인가다. 단순히 이전 인덱스의 값이 더 작다면 빼고, 아니면 더하는 로직을 구현했다.</p>
<p>여기서 사실 splitted는 필요 없다. string 또한 index를 가지기 때문에 for문으로 한 요소씩 loop할 수 있다. 항상 for문을 쓰면 split을 습관적으로 쓴다는 것이 문제.. 명심하자.</p>
<pre><code>function solution(roman) {
   const value = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
   const splitted = roman.split(&quot;&quot;);
  let result = 0;
  for (let i = 0; i &lt; splitted.length; i++) {
    if (value[splitted[i]] &lt; value[splitted[i + 1]]) {
      result -= value[splitted[i]];
    } else result += value[splitted[i]];
  }
  return result;
}</code></pre><h3 id="✅-첫-번째-풀이-리팩토링">✅ 첫 번째 풀이 리팩토링</h3>
<pre><code>function solution(roman) {
  const value = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
  let result = 0;
  for (let i = 0; i &lt; roman.length; i++) {
    value[roman[i]] &lt; value[roman[i + 1]]
      ? (result -= value[roman[i]])
      : (result += value[roman[i]]);
  }
  return result;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Where my anagrams at?]]></title>
            <link>https://velog.io/@jjo-niixx/Where-my-anagrams-at</link>
            <guid>https://velog.io/@jjo-niixx/Where-my-anagrams-at</guid>
            <pubDate>Sun, 20 Dec 2020 07:18:22 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<blockquote>
<p>💡 <strong>anagram</strong>이란 무엇일까?
두 개의 단어가 서로 똑같은 문자를 가지고 있을 때 서로의 anagram이라 일컫는다.</p>
</blockquote>
<p>word의 문자와 똑같은 문자로 구성된 words의 요소를 찾아라. 이때 문자의 종류는 똑같아야 하지만 순서는 달라도 된다.</p>
<pre><code>anagrams(&#39;abba&#39;, [&#39;aabb&#39;, &#39;abcd&#39;, &#39;bbaa&#39;, &#39;dada&#39;]) =&gt; [&#39;aabb&#39;, &#39;bbaa&#39;]

anagrams(&#39;racer&#39;, [&#39;crazer&#39;, &#39;carer&#39;, &#39;racar&#39;, &#39;caers&#39;, &#39;racer&#39;]) =&gt; [&#39;carer&#39;, &#39;racer&#39;]

anagrams(&#39;laser&#39;, [&#39;lazing&#39;, &#39;lazy&#39;,  &#39;lacer&#39;]) =&gt; []</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙆🏻♀️-첫-번째-풀이">🙆🏻‍♀️ 첫 번째 풀이</h3>
<p>맨 처음에 sortedWord와 sortedWords를 만들 때 join을 이용하지 않고 각각의 배열을 비교했다. 그랬더니 문자 구성이 같더라도 두 배열은 다르다는 결과값이 나왔다. 그 이유는 두 배열이 똑같이 생겼더라도 다른 주소를 참조했기 때문이다. 그래서 join을 사용하여 타입을 바꿔버렸더니 비교가 한층 수월했다.</p>
<p>다시 한 번 기억하자. <strong>두 배열을 서로 비교할 때는 많은 고려사항이 따른다. 적극적으로 타입을 바꾸려는 노력을 하자.</strong></p>
<pre><code>function anagrams(word, words) {
  let result = [];
  const sortedWord = word.split(&quot;&quot;).sort().join(&quot;&quot;);
  for (let i = 0; i &lt; words.length; i++) {
    let sortedWords = words[i].split(&quot;&quot;).sort().join(&quot;&quot;);
    if (sortedWord === sortedWords) {
      result.push(words[i]);
    }
  }
  return result;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[클로저]]></title>
            <link>https://velog.io/@jjo-niixx/%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@jjo-niixx/%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Sat, 19 Dec 2020 14:24:24 GMT</pubDate>
            <description><![CDATA[<h2 id="클로저">클로저</h2>
<p>어떤 함수 A에서 선언한 변수 b를 참조하는 내부함수 C를 외부로 전달할 경우 A의 실행 컨텍스트가 종료된 이후에도 변수 b가 사라지지 않는 현상 - 코어 자바스크립트 👍</p>
<p>클로저 정의 from 다양한 서적</p>
<p>✔️ 클로저는 함수와 그 함수가 선언될 당시의 lexical environment의 상호관계에 따른 현상
✔️ 자신을 내포하는 함수의 컨텍스트에 접근할 수 있는 함수
✔️ 함수가 특정 스코프에 접근할 수 있도록 의도적으로 그 스코프에서 정의하는 것
✔️ 함수를 선언할 때 만들어지는 유효범위가 사라진 후에도 호출할 수 있는 함수
✔️ 이미 생명 주기상 끝난 외부 함수의 변수를 참조하는 함수
✔️ 자유변수가 있는 함수와 자유변수를 알 수 있는 환경의 결합</p>
<h2 id="클로저-활용-사례">클로저 활용 사례</h2>
<ul>
<li>콜백 함수 내부에서 외부 데이터를 사용하고자 할 때</li>
<li>접근 권한 제어(정보 은닉)</li>
<li>부분 적용 함수</li>
<li>커링 함수</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[어떤 개발자가 되고 싶은가]]></title>
            <link>https://velog.io/@jjo-niixx/%EC%96%B4%EB%96%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EB%90%98%EA%B3%A0-%EC%8B%B6%EC%9D%80%EA%B0%80</link>
            <guid>https://velog.io/@jjo-niixx/%EC%96%B4%EB%96%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EB%90%98%EA%B3%A0-%EC%8B%B6%EC%9D%80%EA%B0%80</guid>
            <pubDate>Thu, 17 Dec 2020 05:03:13 GMT</pubDate>
            <description><![CDATA[<p>최근 구직 활동에 박차를 가하고 있다. 위코드에서 공부하는 동안 놓친 개념도 많기 때문에 웹과 자바스크립트, 리액트 책을 구매해서 기본기를 다지는 중이다. 위코드 동기들과 함께 취업 준비를 하면서 정말 재밌고 지치지 않는 하루하루를 보내고 있다. 역시 <strong>함께 할 수 있ABILITY</strong></p>
<p>지원을 하고, 코테를 치르고, 과제를 하고, 또 지원하는 하루하루의 연속이고, 최근에는 정말 감사하게도 여러 군데에서 연락을 주셔서 면접도 바쁘게 보러 다니고 있다. 어쩌면 내 인생에서 마주치기도 힘든, 각자의 위치에서 최고의 자리에 오른 분들과 서로의 가치관, 인생에 대해서 몇 시간씩 이야기를 나눌 기회가 정말 소중하고 감사하다.</p>
<p>어제 본 면접에서 기술이 아닌 나에 대한 질문이 대부분이었다. 사실 기술 면접인 줄 알고 개념 정독 및 알고리즘 문제를 준비했는데.. 예상을 빗나갔지만, 면접관분들이 편안한 분위기를 조성해주셔서 나도 지인들과 대화를 하듯이 면접을 진행했다. 개인적으로 나는 말주변이 없는 편이라서 기술 질문보다 나에 대한 질문을 더 어려워하는 것 같다. 아무래도 면접이라 긴장을 해서인지 평소에 생각하던 것도 갑자기 적절한 단어가 생각 안 나던지 더듬거리거나 투머치 토커가 되기도 한다. 그래서 어제 받은 질문 중 앞으로 개발자로 살아가면서 생각해볼 만한 것들에 대해서 차분히 생각해봐야겠다.</p>
<h2 id="어떤-개발자가-되고-싶은가">어떤 개발자가 되고 싶은가</h2>
<h3 id="혼자-걸어가면-빨리-가지만-함께-걸어가면-멀리간다">혼자 걸어가면 빨리 가지만 함께 걸어가면 멀리간다.</h3>
<p>함께 하는 개발자가 되고 싶다. 팀 미션이 성공적으로 이루어지려면 각자의 위치에서 본인의 몫을 훌륭히 수행해야 하지만 그 이전에 나와 함께 가는 사람들도 어려움 없이 따라오는지 계속해서 살펴보아야 한다. 나는 그 사람들에게 잘 걸을 수 있는 비법을 공유하고, 힘들 때 북돋아 주고, 함께 더 좋은 방법을 생각하는 개발자가 되고 싶다.</p>
<p>이런 개발자가 되기 위해서 갖춰야 하는 조건은 무엇일까? 누가 뭐래도 본인의 프로그래밍 실력이 일순위일 것 같다. 끊임없이 부딪히고 받아들이고 탐구하며 단단한 실력을 만들자. 내가 맡은 부분은 어떻게든 소화를 해내는 능력은 갖추어야 한다. 그래야만 나조차도 주변을 살필 여유가 생기고 사람들도 나를 신뢰할 수 있을 것이다.</p>
<p>나는 위코드 생활을 하면서 이런 개발자가 되어야겠다고 다짐을 했던 것 같다. 동기들과 협업을 진행하면서 프로젝트 결과물을 완성할 때마다 서로의 성장하는 속도에 놀라곤 했었다. 하루에 12시간 넘게 붙어서 공부하면서 선의의 경쟁을 하고, 함께 에러 상황을 고민해주고, 새로운 개념을 서로 가르쳐주고 적용을 하면서 시너지를 발휘했고, 항상 한계를 뛰어 넘었다.</p>
<p>몇 년 후의 나는 어떤 개발자가 되어 있을까. 내가 바라던 대로 함께 하는 개발자가 되어있을까. 아마도 그럴 것이다. 혹은 더욱더 대단한 개발자..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Split Strings]]></title>
            <link>https://velog.io/@jjo-niixx/Split-Strings</link>
            <guid>https://velog.io/@jjo-niixx/Split-Strings</guid>
            <pubDate>Thu, 17 Dec 2020 03:37:45 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>매개변수 str를 2문자씩 짝지어라. 이때 str가 홀수 길이라면 짝지을 때 2번째 문자는 빈칸이므로 _로 대체해라</p>
<pre><code>For example:
  solution(&#39;abc&#39;) // should return [&#39;ab&#39;, &#39;c_&#39;]
  solution(&#39;abcdef&#39;) // should return [&#39;ab&#39;, &#39;cd&#39;, &#39;ef&#39;]</code></pre><h2 id="문제-풀이">문제 풀이</h2>
<h3 id="🙆🏻♀️-첫-번째-풀이">🙆🏻‍♀️ 첫 번째 풀이</h3>
<p>쉬운 편이었던 것 같은데 이 풀이가 나오기 전에 크리티컬한 실수를 했다.</p>
<p>for문에서 i를 2씩 증가시키고 싶어서 <code>i+2</code>를 한 것..! 이렇게 하면 i에 2를 더하기만 하지 할당은 하지 않아서 결과적으로 내가 원하는 숫자를 얻을 수 없고 i는 계속 0으로 나올 것이다.</p>
<p>for 문에서 관례처럼 사용하는
<code>i=i+1</code> =&gt; <code>i+=1</code> =&gt; <code>i++</code>
이 과정을 통해 만들어지는 것을 명심하자 ^_^</p>
<pre><code>function solution(str) {
  let result = [];
  for (let i = 0; i &lt; str.length; i += 2) {
    if (i === str.length - 1) {
      result.push(str.slice(i) + &quot;_&quot;);
    } else {
      result.push(str.slice(i, i + 2));
    }
  }
  return result;
}</code></pre><h2 id="모범-답안">모범 답안</h2>
<h3 id="👍-첫-번째-모범-답안">👍 첫 번째 모범 답안</h3>
<pre><code>function solution(str){
  var i = 0;
  var result = new Array();
  if (str.length % 2 !== 0) {
    str = str + &#39;_&#39;;
  }
  while (i &lt; str.length) {
      result.push(str[i] + str[i+1]);
      i += 2;
    }
  return result;
}</code></pre><p>✔️ new Array()를 써서 빈 배열을 만들어 result에 할당했다.
✔️ str가 홀수라면 str+&quot;_&quot;로 해버려서 그 후의 연산을 쉽게 했다.
✔️ 내가 했듯이 slice 메소드를 굳이 쓸 필요가 없다. 그저 현재 인덱스, 다음 인덱스의 요소를 푸쉬!</p>
<h3 id="✌️-두-번째-모범-답안">✌️ 두 번째 모범 답안</h3>
<pre><code>function solution(s){
   return (s+&quot;_&quot;).match(/.{2}/g)||[]
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[var vs let, const]]></title>
            <link>https://velog.io/@jjo-niixx/var-vs-let-const</link>
            <guid>https://velog.io/@jjo-niixx/var-vs-let-const</guid>
            <pubDate>Wed, 16 Dec 2020 07:32:11 GMT</pubDate>
            <description><![CDATA[<p>JavaScript 를 공부하고 있는데 var, let, const도 확실하게 구분 못하는 내 자신을 보면서 반성을 많이 하게 된다.. ^_^</p>
<p>이번에 확실하게 짚고 넘어가자!</p>
<h2 id="var">var</h2>
<h4 id="var의-첫-번째-문제-함수-스코프"><strong>var의 첫 번째 문제: 함수 스코프</strong></h4>
<p>함수 스코프를 지니기 때문에 for 문, while 문, switch 문, if 문 내부에서 정의된 변수가 반복문이 끝난 이후에도 계속 남는 문제가 있다.</p>
<h4 id="var의-두-번째-문제-호이스팅"><strong>var의 두 번째 문제: 호이스팅</strong></h4>
<p>변수를 정의하기 전에 사용해도 에러가 발생하지 않음 (undefined로 나옴)</p>
<blockquote>
<p>호이스팅
&#39;끌어올리다&#39;라는 의미로, 변수 정보를 수집하는 과정을 쉬운 방법으로 대체한 가상의 개념</p>
</blockquote>
<p>자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다. 그렇기 때문에 변수 수집 과정을 모두 마쳐도 실행컨텍스트가 관여할 코드들은 실행되지 전의 상태</p>
<pre><code>console.log(myVar) // undefined
var myVar = 1;
위 코드를 호이스팅 후에는 아래와 같이 된다고 생각하자.

var myVar = undefined;
console.log(myVar); // undefined
myVar = 1;
var 변수는 호이스팅 결과로 가장 최상단에서 선언되고 undefined로 초기화된다. 그러므로 1로 할당 하기 전에 사용하면 undefined가 나온다는 사실!</code></pre><h4 id="var의-세-번째-문제-재정의-가능">var의 세 번째 문제: 재정의 가능</h4>
<p>변수를 정의한다는 것은 이전에 없던 변수를 생성한다는 의미이다. 하지만 var는 이전에 있던 변수도 재정의 할 수 있음 → 직관적이지 않음, 버그로 이어질 확률</p>
<h4 id="var의-네-번째-문제-재할당-가능">var의 네 번째 문제: 재할당 가능</h4>
<p>상수처럼 쓸 값도 무조건 재할당 가능한 변수로 만들어짐 → 코드 복잡, 가독성 떨어짐</p>
<h2 id="let--const-공통점">let &amp; const 공통점</h2>
<h4 id="블록-스코프">블록 스코프</h4>
<h4 id="재정의-불가능">재정의 불가능</h4>
<h4 id="호이스팅">호이스팅</h4>
<p>변수가 정의된 시점보다 먼저 변수를 사용하면 에러가 발생함 (참조 에러)</p>
<blockquote>
<p><strong>let과 const도 호이스팅? 이 된다!</strong>
변수가 할당되는 과정은 3단계를 거친다. 선언, 초기화, 할당
var는 선언(호이스팅)과 동시에 초기화가 되는 반면, let과 const는 선언과 초기화가 분리된다.
그리고 var와는 다르게 임시적 사각지대가 존재하게 된다.</p>
</blockquote>
<blockquote>
<p><strong>임시적 사각지대(Temporal Dead Zone)란?</strong>
임시적 사각지대는 변수 초기화 전에 사용하는 것을 막는다.
EX) let, const, class</p>
</blockquote>
<pre><code>const foo = 1;
{
  console.log(foo); // 참조에러
  const foo = 2;
}</code></pre><p>만약 두 번째 foo가 호이스팅되지 않았다면 참조 에러는 발생하지 않고 첫 번째 foo의 값을 출력될 것이다. 하지만 두 번째 foo의 호이스팅 때문에 출력된 값은 두 번째 foo를 참조하게 되어 참조에러가 발생하는 것이다.</p>
<h2 id="let-vs-const-다른-점">let vs const 다른 점</h2>
<h4 id="let은-재할당-가능-but-const는-재할당-불가능">let은 재할당 가능 but const는 재할당 불가능</h4>
<p>재할당 불가능한 변수는 프로그램의 복잡도를 상당히 낮춰주기 때문에 되도록이면 const를 사용하는 것이 좋음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML Critical Rendering Path]]></title>
            <link>https://velog.io/@jjo-niixx/HTML-Critical-Rendering-Path</link>
            <guid>https://velog.io/@jjo-niixx/HTML-Critical-Rendering-Path</guid>
            <pubDate>Tue, 15 Dec 2020 05:27:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jjo-niixx/post/9e3f466e-76ad-4250-898e-f37e61c06ff9/CRP-Sequence-Copy.png" alt=""></p>
<h2 id="critical-rendering-path">Critical Rendering Path</h2>
<p>브라우저가 서버에서 페이지에 대한 HTML 응답을 받으면 화면에 표시되기 전에 많은 단계를 거쳐야 한다. 브라우저가 페이지의 초기 출력을 위해 실행해야하는 이 순서를 <strong>Critical Renderting Path</strong>라고 한다.</p>
<h2 id="crp의-단계">CRP의 단계</h2>
<ol>
<li>DOM 트리 구축 (Constructing the DOM Tree)</li>
<li>CSSOM 트리 구축 (Constructing the CSSOM Tree)</li>
<li>JavaScript 실행 (Running JavaScript)</li>
<li>Render Tree 생성 (Creating the Render Tree)</li>
<li>레이아웃 생성 (Generating the Layout)</li>
<li>페인팅 (Painting)</li>
</ol>
<h3 id="dom-트리-구축">DOM 트리 구축</h3>
<p><img src="https://images.velog.io/images/jjo-niixx/post/137fba04-f97a-4bf4-98d9-4fecf692a8b0/understanding-the-critical-rendering-path-1.png" alt="">
DOM(Document Object Model) 트리는 완전히 구문 분석된 HTML 페이지의 Object 표현이다. </p>
<p>루트 요소 <code>html</code>로 시작하여 페이지의 각 element/text에 대한 노드가 만들어진다. 각 노드에는 해당 요소의 전체 특성이 포함된다.</p>
<h3 id="cssom-트리-구축">CSSOM 트리 구축</h3>
<p><img src="https://images.velog.io/images/jjo-niixx/post/3f169795-57f0-47ec-be56-cc96106152a5/understanding-the-critical-rendering-path-2.png" alt="">
CSSOM(CSS Object Model)은 DOM과 연관된 스타일의 Object 표현이다. 이것은 DOM과 비슷한 방식으로 표현되지만 명시적 또는 암시적 선언과 상속 여부에 관계없이 각 노드의 관련 스타일로 표시된다.</p>
<h3 id="javascript-실행">JavaScript 실행</h3>
<p>JavaScript는 <strong>&quot;파서 차단 리소스(parser blocking resource)&quot;</strong>로 간주된다. 즉, HTML 문서 자체의 구문 분석은 JavaScript에 의해 차단된다.</p>
<p>파서가 내부 태그이든 외부 태그이든 <code>&lt;script&gt;</code> 태그에 도달하면 (외부 태그 인 경우) fetch를 중단하고 실행한다. 따라서 문서 내의 요소를 참조하는 JavaScript 파일이 있는 경우 해당 문서가 표시된 후에 배치 해야 한다.</p>
<h3 id="render-tree-생성">Render Tree 생성</h3>
<p><img src="https://images.velog.io/images/jjo-niixx/post/75f6398a-cf6f-4904-8445-9c26eeea4071/understanding-the-critical-rendering-path-3.png" alt="">
렌더링 트리는 DOM과 CSSOM의 조합이다. 페이지에서 최종적으로 렌더링 될 내용을 나타내는 트리다. 즉, 표시되는 내용만 캡쳐하가 때문에 display:none을 사용하여 CSS로 숨겨진 요소는 포함하지 않는다.</p>
<h3 id="레이아웃-생성">레이아웃 생성</h3>
<p>레이아웃은 뷰포트의 크기에 관련된 CSS 스타일에 대한 컨텍스트에 의해 뷰포트의 크기를 결정한다. 비율 또는 뷰포트 단위. 뷰포트 크기는 문서 헤드에 제공된 메타 뷰포트 태그에 의해 결정되거나, 태그가 제공되지 않으면 기본 뷰포트 너비 인 980px가 사용된다.</p>
<h3 id="페인팅">페인팅</h3>
<p>마지막으로 Painting 단계에서 페이지의 가시적인 내용을 픽셀로 변환하여 화면에 표시 할 수 있다.</p>
<p>페인트 단계에서 처리에 걸리는 시간은 DOM의 크기와 적용되는 스타일에 따라 다르다. 어떤 스타일은 다른 스타일보다 더 많은 작업을 필요로 한다. 예를 들어, 복잡한 그래디언트 배경 이미지는 단순한 단색 배경색보다 더 많은 시간을 필요로 한다.</p>
<p><a href="https://blog.asamaru.net/2017/05/04/understanding-the-critical-rendering-path/">출처로 이동하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Korean Number]]></title>
            <link>https://velog.io/@jjo-niixx/Korean-Number</link>
            <guid>https://velog.io/@jjo-niixx/Korean-Number</guid>
            <pubDate>Sun, 13 Dec 2020 09:39:46 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p>/*
자연수의 4자리마다 한글 단위를 추가한 문자열을 반환하는 함수를 작성해주세요. 예를 들어 123456789는 1억2345만6789를 반환해야 합니다. 10345는 1만0345가 아닌 1만345를 반환해야 합니다. 12340000는 1234만0이 아닌 1234만을 반환해야 합니다.</p>
<p>  조건
    입력은 0 이상, 1조 미만의 정수입니다.
*/</p>
<pre><code>function toKoreanNumber(number) {
// 코드 고!!!!
};

toKoreanNumber(1234), &quot;1234&quot;
toKoreanNumber(12340000), &quot;1234만&quot;
toKoreanNumber(12345), &quot;1만2345&quot;
toKoreanNumber(10345), &quot;1만345&quot;
toKoreanNumber(1234567890), &quot;12억3456만7890&quot;</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙅🏻♀️-첫-번째-풀이">🙅🏻‍♀️ 첫 번째 풀이</h3>
<pre><code>function toKoreanNumber(number) {
  let format = &quot;xxxx만xxxx억xxxx조xxxx&quot;
  let numberToString = number.toString()

  for (let i = numberToString.length-1; i &gt; -1; i--) {
    format = format.replace(&quot;x&quot;, numberToString[i])   
  }
  console.log(format.split(&quot;&quot;).reverse().join(&quot;&quot;))
};</code></pre><h3 id="🙆🏻♀️-두-번째-풀이">🙆🏻‍♀️ 두 번째 풀이</h3>
<pre><code>function toKoreanNumber(number) {
  const loop = Math.ceil(`${number}`.length / 4);
  const won = [&quot;&quot;, &quot;만&quot;, &quot;억&quot;, &quot;조&quot;];
  let result = &quot;&quot;;

  for (let i = 0; i &lt; loop; i++) {
    result = (number % 10000 ? (number % 10000) + won[i] : &quot;&quot;) + result;
    number = parseInt(number / 10000);
  }
  return result;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[정규 표현식]]></title>
            <link>https://velog.io/@jjo-niixx/%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D</link>
            <guid>https://velog.io/@jjo-niixx/%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D</guid>
            <pubDate>Sun, 13 Dec 2020 08:45:10 GMT</pubDate>
            <description><![CDATA[<h2 id="정규-표현식-만들기">정규 표현식 만들기</h2>
<p>정규식 리터럴(슬래쉬&quot;/&quot;로 감싸는 패턴)을 사용하거나 <code>RegExo</code> 객체의 생성자 함수를 호출해서 정규 표현식을 만들 수 있다.</p>
<pre><code>var re = /ab+c/;</code></pre><pre><code>var re = new RegExp(&quot;ab+c&quot;);</code></pre><h2 id="정규-표현식-패턴">정규 표현식 패턴</h2>
<h3 id="단순-패턴-사용하기">단순 패턴 사용하기</h3>
<pre><code>/abc/ - 문자열에서 정확히 &#39;abc&#39;라는 문자들이 순서대로 나타나야 대응
/ab*c/ - &#39;a&#39; 문자 뒤에 0개 이상의 &#39;b&#39; 문자가 나타나고 바로 뒤에 &#39;c&#39; 문자가 나타나는 문자 조합에 대응</code></pre><h3 id="특수-문자-사용하기">특수 문자 사용하기</h3>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D">MDN으로 확인하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[LeetCode] Single Number]]></title>
            <link>https://velog.io/@jjo-niixx/LeetCode-Single-Number</link>
            <guid>https://velog.io/@jjo-niixx/LeetCode-Single-Number</guid>
            <pubDate>Sat, 12 Dec 2020 13:09:21 GMT</pubDate>
            <description><![CDATA[<p><a href="https://leetcode.com/problems/single-number/">문제 확인하기</a></p>
<h2 id="문제">문제</h2>
<p>nums 숫자 배열 매개 변수를 받는다. 이때 한 개의 요소 빼고 다른 요소들은 두 번씩 등장한다. 한 개만 등장하는 요소를 구하라.</p>
<pre><code>Input: nums = [2,2,1]
Output: 1
Example 2:

Input: nums = [4,1,2,1,2]
Output: 4
Example 3:

Input: nums = [1]
Output: 1</code></pre><h2 id="문제-풀이">문제 풀이</h2>
<h3 id="🙆🏻♀️-첫-번째-풀이">🙆🏻‍♀️ 첫 번째 풀이</h3>
<p>한 줄로 풀어버리는 스킬을 쓰려했지만.. 생각나지 않았다. </p>
<p>result라는 빈 배열을 만들었다. 그리고 만약에 nums의 요소가 result에 없다면 추가하고, 있다면 result에서 해당 요소의 인덱스를 검색해 제거하는 로직을 짜보았다.</p>
<pre><code>var singleNumber = function(nums) {
    let result = [];
    for (let i = 0; i &lt; nums.length; i++) {
        if (result.indexOf(nums[i])&lt;0) {
          result.push(nums[i])
        }
      else {
        result.splice(result.indexOf(nums[i]),1)
      }
    }
  return result[0]
};</code></pre><blockquote>
<p>항상 헷갈리는 <strong>splice vs slice</strong></p>
</blockquote>
<ul>
<li>Array​.prototype​.slice(start[, end])
slice() 메소드는 <strong>begin부터 end 전까지의 복사본</strong>을 새로운 배열 객체로 반환한다. 이 메소드는 <strong>원본 배열을 수정하지 않는다</strong>.</li>
<li>Array​.prototype​.splice(start[, deleteCount[, item1[, item2[, ...]]]])
splice() 메소드는 배열의 기존 요소를 <strong>삭제</strong> 또는 <strong>교체</strong>하거나 새 요소를 <strong>추가</strong>하여 배열의 내용을 변경한다. 이 메소드는 <strong>원본 배열 자체</strong>를 수정한다.</li>
</ul>
<h2 id="모범-답안">모범 답안</h2>
<h3 id="☝️-첫-번째-모범-답안">☝️ 첫 번째 모범 답안</h3>
<pre><code>let singleNumber = function(nums){
    let result = 0;
    for(let i = 0; i &lt; nums.length; i++){
       result = result ^ nums[i]
    }
    return result
}
singleNumber([4,1,2,1,2])</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[방문 길이]]></title>
            <link>https://velog.io/@jjo-niixx/%EB%B0%A9%EB%AC%B8-%EA%B8%B8%EC%9D%B4</link>
            <guid>https://velog.io/@jjo-niixx/%EB%B0%A9%EB%AC%B8-%EA%B8%B8%EC%9D%B4</guid>
            <pubDate>Wed, 09 Dec 2020 08:37:13 GMT</pubDate>
            <description><![CDATA[<p><a href="https://programmers.co.kr/learn/courses/30/lessons/49994">문제 확인하기</a></p>
<h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙅🏻♀️-첫-번째-풀이">🙅🏻‍♀️ 첫 번째 풀이</h3>
<pre><code>function solution(dirs) {
  let arr = dirs.split(&quot;&quot;);
  let start = [0, 0];
  let result = [];
  let notDuplArr = [];

  for (let i = 0; i &lt; dirs.length; i++) {
    switch (dirs[i]) {
      case &quot;U&quot;:
        start[1] = start[1] + 1;
        break;
      case &quot;D&quot;:
        start[1] = start[1] - 1;
        break;
      case &quot;R&quot;:
        start[0] = start[0] + 1;
        break;
      case &quot;L&quot;:
        start[0] = start[0] - 1;
        break;
    }
    if (start[0] &gt;= -5 &amp;&amp; start[0] &lt;= 5 &amp;&amp; start[1] &gt;= -5 &amp;&amp; start[1] &lt;= 5) {
      result.push([...start]);
    }
  }
  return [...new Set(result.map((el) =&gt; el.join(&quot;&quot;)))].length + 1;
}</code></pre><h2 id="모범-답안">모범 답안</h2>
<h3 id="👍-첫-번째-풀이">👍 첫 번째 풀이</h3>
<pre><code>function solution(dirs) {
  var ansObj = {};
  var currentX = 0;
  var currentY = 0;
  for (var i = 0; i &lt; dirs.length; i++) {
  //첫 시작점을 위해 currentX, Y를 nextX, Y로 할당
    var nextX = currentX;
    var nextY = currentY;
    var key = &quot;key&quot;;
    //방향성을 나타내야하는데 key를 만들 때 방향을 넣어서 더해줌
    if (dirs[i] === &quot;U&quot;) {
      nextY = currentY + 1;
      key = key + currentX + currentY + nextX + nextY;
    }
    if (dirs[i] === &quot;R&quot;) {
      nextX = currentX + 1;
      key = key + currentX + currentY + nextX + nextY;
    }
    if (dirs[i] === &quot;D&quot;) {
      nextY = currentY - 1;
      key = key + nextX + nextY + currentX + currentY;
    }
    if (dirs[i] === &quot;L&quot;) {
      nextX = currentX - 1;
      key = key + nextX + nextY + currentX + currentY;
    }
    if (nextX &lt; -5 || nextX &gt; 5 || nextY &lt; -5 || nextY &gt; 5) {
      //do nothing
    } else {
    // 선을 키로 잡아 1을 할당함
      ansObj[key] = 1;
      // 다음 점을 현재 점으로 옮겨주고 다시 스따뜨
      currentX = nextX;
      currentY = nextY;
    }
  }
  return Object.keys(ansObj).length;
}</code></pre><h2 id="to-be-continued-😁">to be continued 😁</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[Directions Reduction]]></title>
            <link>https://velog.io/@jjo-niixx/Directions-Reduction</link>
            <guid>https://velog.io/@jjo-niixx/Directions-Reduction</guid>
            <pubDate>Fri, 04 Dec 2020 06:17:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jjo-niixx/post/435c94e8-f3f5-4000-a0db-f42526ffc1b3/Screen-Shot-2016-03-28-at-7.51.42-AM.png" alt=""></p>
<p><a href="https://www.codewars.com/kata/550f22f4d758534c1100025a/train/javascript">Directions Reduction 문제 확인하기</a></p>
<h2 id="문제">문제</h2>
<p>배열 안에 반대하는 방향이 <strong>이어서</strong> 등장한다면 그 요소들을 제거할 수 있다. 예를 들어 북쪽으로 한 걸음 가고, 바로 남쪽으로 한 걸음 간다면 제자리이기 때문. 이 규칙에 따라 제거할 요소들을 삭제한 결과를 리턴해야 한다.</p>
<pre><code>For example: 

  [&quot;NORTH&quot;, &quot;SOUTH&quot;, &quot;SOUTH&quot;, &quot;EAST&quot;, &quot;WEST&quot;, &quot;NORTH&quot;,     &quot;WEST&quot;] // =&gt; returns [&quot;WEST&quot;]
  or
  { &quot;NORTH&quot;, &quot;SOUTH&quot;, &quot;SOUTH&quot;, &quot;EAST&quot;, &quot;WEST&quot;, &quot;NORTH&quot;, &quot;WEST&quot; }; // =&gt; returns { &quot;WEST&quot; }
  or
  [North, South, South, East, West, North, West] // =&gt; returns [West]

  [&quot;NORTH&quot;, &quot;WEST&quot;, &quot;SOUTH&quot;, &quot;EAST&quot;] // =&gt; returns [&quot;NORTH&quot;, &quot;WEST&quot;, &quot;SOUTH&quot;, &quot;EAST&quot;]</code></pre><h2 id="나의-풀이">나의 풀이</h2>
<h3 id="🙆🏻♀️-첫-번째-풀이">🙆🏻‍♀️ 첫 번째 풀이</h3>
<p>복잡해 보여서 포기하려 했는데 천천히 살펴보니 별거 아니였다.. 훗.. </p>
<p>일단 처음 보고 배열의 요소를 하나하나 살펴보아야 하기 때문에 loop을 써야겠다고 생각했다. 한번 반복으로 끝내는 것이 아니라 배열에 원하는 조건이 없을 때까지 반복해야 하므로 <code>while loop</code>을 사용했다.</p>
<p>두 개의 반대되는 방향이 붙어있을 경우에 <code>splice</code>로 그 요소들을 없애고 인덱스 넘버(i)를 처음으로 되돌렸다. 배열의 끝까지 요소들을 살펴보고 원하는 조건이 없을 때는 인덱스 넘버를 하나씩 증가시켰다.</p>
<pre><code>function dirReduc(arr){
  // arr.splice(start, 제거할 요소수)
  let i = 0;
  while(i &lt; arr.length) {
    if(arr[i]===&quot;NORTH&quot; &amp;&amp; arr[i+1]===&quot;SOUTH&quot; ||
       arr[i]===&quot;SOUTH&quot; &amp;&amp; arr[i+1]===&quot;NORTH&quot; ||
       arr[i]===&quot;EAST&quot; &amp;&amp; arr[i+1]===&quot;WEST&quot; ||
       arr[i]===&quot;WEST&quot; &amp;&amp; arr[i+1]===&quot;EAST&quot;) {
      arr.splice(i,2)
      i=0;
    }
    else {
      i++
    }
  }
  return arr
}</code></pre><h2 id="모범-답안">모범 답안</h2>
<h3 id="☝️-첫-번째-모범-답안">☝️ 첫 번째 모범 답안</h3>
<pre><code>function dirReduc(plan) {
  var opposite = {
    &#39;NORTH&#39;: &#39;SOUTH&#39;, &#39;EAST&#39;: &#39;WEST&#39;, &#39;SOUTH&#39;: &#39;NORTH&#39;, &#39;WEST&#39;: &#39;EAST&#39;};
  return plan.reduce(function(dirs, dir){
      if (dirs[dirs.length - 1] === opposite[dir])
        dirs.pop();
      else
        dirs.push(dir);
      return dirs;
    }, []);
}</code></pre><p><strong>✔️</strong> 짝지어야할 두 단어를 key와 value로 만들어 <strong>객체</strong>로 할당했다.
<strong>✔️</strong> 연산이 마무리 되고 한 가지 배열이 나와야 하므로 <strong>reduce</strong> 메소드를 사용했다.
EX) arr.reduce(callback( accumulator, currentValue, [, index[, array]] )[, initialValue])
<strong>✔️</strong> 축적이 되는 배열(dirs)을 만들게 되는데 그 배열의 마지막 요소(dirs[dirs.length - 1])가 현재 요소(dir)에 대응하는 밸류와 일치하면 삭제한다. </p>
]]></description>
        </item>
    </channel>
</rss>