<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Dino_Ground</title>
        <link>https://velog.io/</link>
        <description>공룡의 발자취</description>
        <lastBuildDate>Wed, 27 Jul 2022 13:53:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Dino_Ground</title>
            <url>https://velog.velcdn.com/images/make_w/profile/5375a34c-3490-4ebb-8b57-e04ed4cb656b/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Dino_Ground. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/make_w" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[타입스크립트 타입]]></title>
            <link>https://velog.io/@make_w/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@make_w/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%83%80%EC%9E%85</guid>
            <pubDate>Wed, 27 Jul 2022 13:53:00 GMT</pubDate>
            <description><![CDATA[<h1 id="implicit-type">implicit type</h1>
<pre><code class="language-typescript">// Alias Type
type Info = {
    name: string,
    age?: number,
}

const me : Info = {
    name: &#39;donghyun&#39;,
}

// Argument &amp; Return Type
const info = (name: string, age?: number) : Info =&gt; ({name, age});

console.log(info(&#39;dong&#39;));</code></pre>
<h1 id="readonly">readonly</h1>
<p>원시타입이 아닌 객체에 불변성을 부여할 수 있다?</p>
<pre><code class="language-typescript">type Color = {
    readonly color: string,
    code: number,
}
// fruits에 조작을 가할 수 없고, colors의 color 역시 조작할 수 없다.
const fruits : readonly string[] = [&#39;apple&#39;, &#39;banana&#39;, &#39;lemon&#39;];
const colors : Color = {
    color: &#39;red&#39;,
    code: 123
}</code></pre>
<h1 id="tuple">Tuple</h1>
<pre><code class="language-typescript">const fruits_2 : [string, number, boolean] = [&#39;apple&#39;, 20000, true];
const fruits_1 : readonly [string, number, boolean] = [&#39;apple&#39;, 20000, true];</code></pre>
<h1 id="any">any</h1>
<p>타입스크립트로부터 벗어나고 싶다?! 그럼 any 타입을 명시하라!</p>
<h1 id="unknown--void--never">unknown / void / never</h1>
<pre><code class="language-typescript">// unknown
let count: unknown;
let name: unknown;

if(typeof count === &#39;number&#39;) {
  let total = count + 1;
}
if(typeof count === &#39;string&#39;) {
  let upperCase = name.toUpperCase();
}

// void: 아무것도 return하지 않는 함수, 따로 지정하지는 않음
function apple(): void {
  console.log(&#39;yummy&#39;);
}

// never
function error():never{
  throw new Error(&#39;no!!&#39;);
}

function error(name: string|number){
  if(typeof name === &#39;string&#39;){
    // string type
  } else if (typeof name === &#39;number&#39;) {
    // number type
  } else {
    // never type
  }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스_해시]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4%ED%95%B4%EC%8B%9C</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4%ED%95%B4%EC%8B%9C</guid>
            <pubDate>Tue, 26 Jul 2022 15:48:37 GMT</pubDate>
            <description><![CDATA[<h1 id="완주하지-못한-선수">완주하지 못한 선수</h1>
<pre><code class="language-javascript">function solution(participants, completions) {
    const map = new Map();

    for(const participant of participants) {
      map.set(participant, (map.get(participant) || 0) + 1);
    }

    for(const completion of completions) {
      map.set(completion, map.get(completion) - 1);
    }

    for(const [key, value] of map.entries()){
      if(value === 1) return key;
    }
}</code></pre>
<h1 id="폰켓몬">폰켓몬</h1>
<pre><code class="language-javascript">function solution(nums) {
    const map = new Map();

    for(const num of nums) {
      map.set(num, (map.get(num) || 0) + 1);
    }

    return map.size &gt;= nums.length / 2 ? nums.length / 2 : map.size;
}</code></pre>
<h1 id="위장">위장</h1>
<pre><code class="language-javascript">function solution(clothes) {
    const map = new Map();
    let answer = 1;

    clothes.forEach(v =&gt; {
        map.set(v[1], (map.get(v[1]) || 0) + 1);
    })

    for(const value of map.values()){
        answer *= (value + 1);
    }

    return answer - 1;
}</code></pre>
<h1 id="베스트앨범">베스트앨범</h1>
<pre><code class="language-javascript">function solution(genres, plays) {
    const answer = [];
    const map = new Map();

    genres.forEach((genre, index) =&gt; {
        map.set(genre, (map.get(genre) || 0) + plays[index]);
    })

    const list = [...map.entries()].sort((a, b) =&gt; b[1] - a[1]);

    list.forEach((value, index) =&gt; {
        const play = plays.map((v, i) =&gt; [v, i])
                          .filter((v, i) =&gt; genres[i] === value[0])
                          .sort((a, b) =&gt; b[0] - a[0])
                          .slice(0, 2);

        answer.push(...play.map(v =&gt; v[1]));
    })

    return answer;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Set & Map]]></title>
            <link>https://velog.io/@make_w/Set-Map</link>
            <guid>https://velog.io/@make_w/Set-Map</guid>
            <pubDate>Mon, 25 Jul 2022 15:48:32 GMT</pubDate>
            <description><![CDATA[<h1 id="set-객체">Set 객체</h1>
<p>Set 객체는 중복되지 않는 값들의 집합으로, <strong>배열과 유사</strong>하지만 인덱스와 순서가 없다.
또한 이터러블을 인수로 받아 Set 객체를 생성하며, 이터러블 내 중복된 값은 저장되지 않는다.</p>
<blockquote>
<p>Set 객체가 없었을 때!</p>
</blockquote>
<pre><code class="language-javascript">const set = arr =&gt; arr.filter((v, i, self) =&gt; self.indexOf(v) === i);</code></pre>
<h2 id="set-용법">Set 용법</h2>
<pre><code class="language-javascript">const set = new Set();

1. 개수 확인
set.size();

2. 추가
set.add(1);

3. 여부 확인
set.has(1); 

4. 삭제
set.delete(1);

5. 일괄 삭제
set.clear();</code></pre>
<p>Set 객체는 이터러블이다. 즉, 순환이 가능하다. 순환가능한 배열에 사용가능한 for, forEach 사용이 가능하고, 스프레드 문법, 구조분해할당 역시 가능하다. 추가로 Set 객체가 요소의 순서를 보장하지 않지만 추가된 순서를 따른다. 이는 다른 이터러블과의 호환성을 유지하기 위함이다.</p>
<h2 id="set의-집합-연산">Set의 집합 연산</h2>
<p>Set을 통해 교집합, 합집합, 차집합을 구현할 수 있다.</p>
<pre><code class="language-javascript">const set_a = new Set([1, 2, 3, 4]);
const set_b = new Set([2, 4]);

1. 교집합
console.log(set_a.intersection(set_b)); &gt;&gt; Set(2) {2, 4}
or
console.log(new Set([...set_a].filter(v =&gt; set_b.has(v)))

2. 합집합
console.log(set_a.union(set_b)); &gt;&gt; Set(4) {1, 2, 3, 4}
console.log(new Set([...set_a, ...set_b]))

3. 차집합
console.log(set_a.difference(set_b)); &gt;&gt; Set(2) {1, 3}
console.log(new Set([...set_a].filter(v =&gt; !set_b.has(v)))

4. 상위집합(set_a가 set_b의 상위 집합인가)
console.log(set_a.isSuperset(set_b)); &gt;&gt; true</code></pre>
<h1 id="map-객체">Map 객체</h1>
<p>Map 객체는 키와 값으로 이뤄졌다는 면에서 <strong>객체와 유사</strong>하지만, 객체와 달리 Map 객체는 js의 모든 값을 키로 삼을 수 있고, 이터러블하다는 면에서 객체와 차이를 지닌다.</p>
<h2 id="map-용법">Map 용법</h2>
<pre><code class="language-javascript">const map = new Map();

1. 개수 확인
map.size();

2. 추가
map.set(1);

3. 여부 확인
map.has(1); 

4. 삭제
map.delete(1);

5. 일괄 삭제
map.clear();

6. 순회
map.forEach((value, key) =&gt; {
  console.log(key, value);
}
console.log(map.keys());
console.log(map.values());
console.log(map.entries());     </code></pre>
<blockquote>
<p>모던 자바스크립트 Deep Dive를 읽고 작성한 글입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[useMemo]]></title>
            <link>https://velog.io/@make_w/useMemo</link>
            <guid>https://velog.io/@make_w/useMemo</guid>
            <pubDate>Sun, 24 Apr 2022 12:25:30 GMT</pubDate>
            <description><![CDATA[<p>컴포넌트 최적화를 위한 대표적인 hook 중 하나인 useMemo!</p>
<p>아래 코드는 어려운 계산과 쉬운 계산이 공존하는 코드이다.
어마무시한 for loop를 적용해 계산의 속도를 늦췄다.</p>
<p>문제는 쉬운 계산을 할 때 easyNumer라는 state가 업데이트되어 app 컴포넌트가 재랜더링되는데, 이는 함수가 재실행되는 것과 같아서 변수의 값들이 초기화됨을 의미한다.
결국 바뀌지 않은 hardSum이 다시 할당되면서 무시무시한 hardCalculate가 재실행된다.</p>
<pre><code class="language-javascript">import React, { useState } from &#39;react&#39;;

const hardCalculate = (number) =&gt; {
  console.log(&quot;어려운 계산&quot;);
  for (let i = 0; i &lt; 999999999; i++) {} // thicking time!!
  return number + 10000;
}

const easyCalculate = (number) =&gt; {
  console.log(&quot;쉬운 계산&quot;);
  return number + 10000;
}

function App() {
  const [hardNumber, setHardNumber] = useState(1);
  const [easyNumber, setEasyNumber] = useState(1);

  const hardSum = hardCalculate(hardNumber);
  const easySum = easyCalculate(easyNumber);

  return (
    &lt;&gt;
      &lt;h3&gt;어려운 계산기&lt;/h3&gt;
      &lt;input
        type=&quot;number&quot;
        value={hardNumber}
        onChange={(e) =&gt; {setHardNumber(parseInt(e.target.value))}}
      /&gt;
      &lt;span&gt; + 10000 = {hardSum}&lt;/span&gt;
      &lt;h3&gt;쉬운 계산기&lt;/h3&gt;
      &lt;input
        type=&quot;number&quot;
        value={easyNumber}
        onChange={(e) =&gt; {setEasyNumber(parseInt(e.target.value))}}
      /&gt;
      &lt;span&gt; + 10000 = {easySum}&lt;/span&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>그렇다면 바뀌지 않은 값은 재실행되지 않도록 할 수 있는 방법이 없을까? 즉, 바뀌기 전의 값을 메모리에 저장되어 꺼내쓰도록 구성할 수는 없을까?
이것이 useMemo이다!!</p>
<pre><code class="language-javascript">import React, { useMemo, useState } from &#39;react&#39;;

const hardCalculate = (number) =&gt; {
  console.log(&quot;어려운 계산&quot;);
  for (let i = 0; i &lt; 999999999; i++) {} // thicking time!!
  return number + 10000;
}

const easyCalculate = (number) =&gt; {
  console.log(&quot;쉬운 계산&quot;);
  return number + 10000;
}

function App() {
  const [hardNumber, setHardNumber] = useState(1);
  const [easyNumber, setEasyNumber] = useState(1);

  const hardSum = useMemo(() =&gt; {
    return hardCalculate(hardNumber);
  }, [hardNumber]);

  const easySum = easyCalculate(easyNumber);

  return (
    &lt;&gt;
      &lt;h3&gt;어려운 계산기&lt;/h3&gt;
      &lt;input
        type=&quot;number&quot;
        value={hardNumber}
        onChange={(e) =&gt; {setHardNumber(parseInt(e.target.value))}}
      /&gt;
      &lt;span&gt; + 10000 = {hardSum}&lt;/span&gt;
      &lt;h3&gt;쉬운 계산기&lt;/h3&gt;
      &lt;input
        type=&quot;number&quot;
        value={easyNumber}
        onChange={(e) =&gt; {setEasyNumber(parseInt(e.target.value))}}
      /&gt;
      &lt;span&gt; + 10000 = {easySum}&lt;/span&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>hardSum 변수에 useMemo를 할당해 hardNumber의 값이 변했을 때에만 연산이 되도록하고, 이외에는 캐싱된 값이 쓰일 수 있도록 설계하면 컴포넌트가 랜더링될 때 무의미한 연산을 막을 수 있어 최적화를 이뤄낼 수 있다!</p>
<p>그런데 사실 javascript 즉, 프론트에서 저렇게 1초씩이나 걸리는 연산을 할 일은 그리 많지는 않다. 다행히 useMemo는 연산보다 더 빛을 발하는 곳이 있는데, 객체타입을 변수에 할당할 때이다.</p>
<pre><code class="language-javascript">import React, { useEffect, useState } from &#39;react&#39;;

function App() {
  const [number, setNumber] = useState(0);
  const [isKorea, setIsKorea] = useState(true);

  const location = {
    country: isKorea ? &quot;한국&quot; : &quot;외국&quot;
  }

  useEffect(() =&gt; {
    console.log(&quot;useEffect 호출!!&quot;);
  }, [location]);

  return (
    &lt;&gt;
      &lt;h2&gt;하루에 몇끼 드세요?&lt;/h2&gt;
      &lt;input
        type=&quot;number&quot;
        value={number}
        onChange={(e) =&gt; setNumber(e.target.value)}
      /&gt;
      &lt;hr /&gt;
      &lt;h2&gt;어느 나라에 있어요?&lt;/h2&gt;
      &lt;p&gt;나라: {location.country}&lt;/p&gt;
      &lt;button onClick={() =&gt; setIsKorea(!isKorea)}&gt;비행기 타자&lt;/button&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>변수에 원시타입이 아닌 객체타입을 할당하면 객체는 너무 크기 때문에 바로 변수에 할당되는 것이 아니라 메모리에 담기게 되고, 변수에는 그 메모리의 주소를 할당하게 된다. 그래서 같은 모습을 한 객체라도 비교연산자를 사용해 비교했을 때 false가 나오는 이유이다.
그렇다면 위의 상황도 number가 바뀔 때마다 app 컴포넌트는 리랜더링되는데, 그때 location이라는 변수에 객체가 재할당(주소가 바뀜)되기 때문에, useEffect의 의존성 배열에 위치한 location이 바뀐 것으로 인지해 겉으로는 location이 바뀌지 않았을 지라도 useEffect가 실행되게 된다.</p>
<pre><code class="language-javascript">import React, { useEffect, useMemo, useState } from &#39;react&#39;;

function App() {
  const [number, setNumber] = useState(0);
  const [isKorea, setIsKorea] = useState(true);

  const location = useMemo(() =&gt; {
    return {
      country: isKorea ? &quot;한국&quot; : &quot;외국&quot;
    }
  }, [isKorea]);

  useEffect(() =&gt; {
    console.log(&quot;useEffect 호출!!&quot;);
  }, [location]);

  return (
    &lt;&gt;
      &lt;h2&gt;하루에 몇끼 드세요?&lt;/h2&gt;
      &lt;input
        type=&quot;number&quot;
        value={number}
        onChange={(e) =&gt; setNumber(e.target.value)}
      /&gt;
      &lt;hr /&gt;
      &lt;h2&gt;어느 나라에 있어요?&lt;/h2&gt;
      &lt;p&gt;나라: {location.country}&lt;/p&gt;
      &lt;button onClick={() =&gt; setIsKorea(!isKorea)}&gt;비행기 타자&lt;/button&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>그래서 useMemo를 이용해 memoization하면 location이 바뀌지 않으면 기억된 객체가 사용되기 때문에 컴포넌트 최적화가 이뤄진다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OAuth 2.0]]></title>
            <link>https://velog.io/@make_w/OAuth-2.0</link>
            <guid>https://velog.io/@make_w/OAuth-2.0</guid>
            <pubDate>Sun, 24 Apr 2022 06:54:42 GMT</pubDate>
            <description><![CDATA[<h1 id="oauth의-배경">OAuth의 배경</h1>
<p>3자가 약속을 정하려는 데에 소통의 어려움이 따르듯, 인증과정에 참여하고 있는 3자가 한자리에 모일 수 없는 상황에서 어떻게 하면 서로를 신뢰할 수 있을까를 고민하며 등장한 기술입니다.</p>
<h1 id="oauth의-주체">OAuth의 주체</h1>
<ul>
<li>Resource Owner(User): Resource Server와 Client의 사용자</li>
<li>Client(Mine): 내가 운영하는 어플리케이션</li>
<li>Resource Server(Their): Resource Owner 대신 Client가 접촉해야하는 대상, 데이터를 가지고 있는 서버</li>
<li>Authorization Server: 인증을 전담하는 서버(이후 Resource Server로 통칭)</li>
</ul>
<h1 id="oauth-등록-절차">OAuth 등록 절차</h1>
<p>우선 Client가 Resource Server에 접근하기 위해서는 사전 준비가 필요합니다.</p>
<ul>
<li>Client ID: 나의 어플리케이션 식별자 ID, 외부에 노출</li>
<li>Client Secret: ID에 대한 비밀번호, 노출 X</li>
<li>Authorized redirect URL: Resource Server가 권한을 부여하는 과정에서 전달돼야하는 Authorized Code의 안착점</li>
</ul>
<h1 id="resource-owner의-승인">Resource Owner의 승인</h1>
<p>이제 준비가 완료됐으니 사용자의 허락을 구해야겠습니다.</p>
<p>우선 위의 등록 과정을 통해 Client와 Resource Server 둘 다 Client ID, Client Secret, Authorized redirect URL을 알게 됩니다.</p>
<p>Resource Server가 제공하는 기능 A, B, C, D 중 우리는 B, D를 사용하길 원합니다.
그렇다면 모든 기능에 대해 승인을 얻기보단, 필요한 기능만 승인을 받는 것이 좋겠습니다.</p>
<p>그 후 우리는 Resource Owner에게 B, D의 기능을 사용해야함을 알리고, 유저가 소셜로그인 버튼을 클릭했을 시에 <code>https://resource.server/?clint_id=1&amp;scope=B,D&amp;redirect_uri=https://client/callback</code>로 연결되게 하면 되겠습니다.</p>
<p>그러면 Resource Server가 Resource Owner의 로그인 여부를 체크하고난 후, Client ID와 Redirect URL이 일치하는 지를 확인합니다. 이 모든 것이 같다면 Resource Owner에게 Client가 사용하길 원하는 Scope에 대한 동의를 할 것인지 알리고, 허용을 한다면 Resource Server에 user_id와 동의된 scope가 기록됩니다. </p>
<h1 id="resource-server의-승인">Resource Server의 승인</h1>
<p>Resource Owner의 동의를 확인하자마자 Client에 Access 토큰을 부여하지 않습니다.
3자 간의 일이니 신중해야하는 것이지요.
authorization code(임시 비밀번호)를 담은 location(https://,,,/code=3)을 owner에게 전달하여 이동을 권고합니다. 
그렇게 타고들어온 유저를 통해 Client는 authorization code를 취득하게 됩니다.
이후 Client는 Server에 authorization code와 client_secret 두개의 비밀정보를 담은 주소로 server에 직접 접속합니다. server는 전달 받은 정보를 확인하고, 모두 일치한다면 Access 토큰을 발급하게 됩니다.</p>
<h1 id="access-token-발급">Access Token 발급</h1>
<p>임시비밀번호인 authorization code를 삭제하고, accessToken을 발급하여 Client에 응답해줍니다. Client는 전달 받은 토큰을 저장하고, 이후 Client가 token을 가지고 server에 접근할 때 해당하는 유저가 허용한 scope에 대한 권한을 부여합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 카펫]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B9%B4%ED%8E%AB</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B9%B4%ED%8E%AB</guid>
            <pubDate>Fri, 15 Apr 2022 02:56:06 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/make_w/post/3cf03d6a-fc64-4a1b-a3eb-99d9e0687755/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(brown, yellow) {
    var answer = [];
    let sum = brown + yellow;

    for(let height=3; height &lt;= brown; height++){
        if(sum % height === 0){
            let width = sum / height;
            if((width-2) * (height-2)  === yellow){
                return [width, height]
            }
        }
    }
    return answer;
}</code></pre>
<ul>
<li>for문 조건: 높이값은 최소 3이상이라는 점과 주어진 brown개수를 넘어설 수 없다는 점을 고려!
  (높이의 최대값이 brown이 될 수는 없지만,,)</li>
<li>임의의 높이값으로 sum을 나눴을 때 나머지가 0. 즉, 사각형을 구성할 수 있는지 판별!</li>
<li>yellow의 너비는 항상 테두리 2를 뺀 값이고, yellow의 높이 역시 테두리 2를 뺀 값임을 고려해 yellow의 개수를 유추해내고, 주어진 yellow의 값과 비교해 정답을 찾아낸다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Axios]]></title>
            <link>https://velog.io/@make_w/Axios</link>
            <guid>https://velog.io/@make_w/Axios</guid>
            <pubDate>Sun, 10 Apr 2022 09:37:56 GMT</pubDate>
            <description><![CDATA[<p>fake server인 reqres를 이용해서 Axios 실습해보기!</p>
<h1 id="get">GET</h1>
<pre><code class="language-javascript">// pages/Prac.js
import React from &quot;react&quot;;
import { useDispatch } from &quot;react-redux&quot;;
import { getApi } from &quot;../redux/modules/prac&quot;;

const Prac = () =&gt; {
    const dispatch = useDispatch();

    return(
        &lt;button onClick={() =&gt; {
            dispatch(getApi())
        }}&gt;테스트&lt;/button&gt;
    )
};

export default Prac;


// redux/modules/prac.js
export const getApi = () =&gt; {
    return async function (dispatch, getState, {history}){
        try {
            const response = await axios.get(&#39;https://reqres.in/api/users?page=2&#39;);
            console.log(response.data);
        } catch(err){
            console.log(err);
        }
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/make_w/post/903ef11e-df79-461f-9f6d-d09c31b5b314/image.png" alt=""></p>
<p>이렇게 잘 받아왔다. 그 후에는 redux에 데이터를 전달하기 위해 원하는 형식으로 조정해 dispatch하면 될 것 같다.</p>
<h1 id="post">Post</h1>
<p>회원가입한 회원의 이메일과 패스워드를 post해 토큰을 받아오는 과정이다.</p>
<pre><code class="language-javascript">// redux/modules/prac.js
export const postApi = () =&gt; {
    return async function (dispatch, getState, {history}){
        try {
            const response = await axios.post(&#39;https://reqres.in/api/login&#39;,{
                email: &quot;eve.holt@reqres.in&quot;,
                password: &quot;cityslicka&quot;,
            });
            console.log(response);
        } catch(err){
            console.log(&quot;에러&quot;, err);
        }
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/make_w/post/0a59c44e-16f9-4ec4-b6ce-1b54d9f7278f/image.png" alt=""></p>
<p>이번에는 틀린 정보를 전달해보겠다.
<img src="https://velog.velcdn.com/images/make_w/post/9916e043-fede-4917-999d-7f1c8445bbe7/image.png" alt="">
없는 회원의 정보라 에러메세지를 전달해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 다리를 지나는 트럭]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%EB%A6%AC%EB%A5%BC-%EC%A7%80%EB%82%98%EB%8A%94-%ED%8A%B8%EB%9F%AD</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%EB%A6%AC%EB%A5%BC-%EC%A7%80%EB%82%98%EB%8A%94-%ED%8A%B8%EB%9F%AD</guid>
            <pubDate>Fri, 08 Apr 2022 02:32:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://velog.velcdn.com/cloudflare/make_w/55dea97f-1d1c-415d-8ae2-0dd7f01407f1/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(bridge_length, weight, truck_weights) {
    // 다리배열을 다리 길이보다 하나 작게 0으로 채워서 만들고
    // 마지막 요소에 첫 트럭을 넣는다
    let bridge = Array.from({length: bridge_length - 1}, v =&gt; 0);

    // 트럭 하나가 이미 투입되었고, 1초가 지났다 가정하고 시작!
    bridge.push(truck_weights.shift());
    let time = 1;

    // 다리에 트럭이 없을때 까지 무한루프
    while (bridge.reduce((a, b) =&gt; a + b) &gt; 0) {
        // 다리 제일 앞에 있는 요소를 보내고
        // 버틸 수 있는 다리 무게가 다음 트럭보다 높은지 비교한다.
        // 버틸 수 있으면 다리 마지막 요소에 트럭을 넣고 시간을 경과 시키고
        // 버틸 수 없으면 0을 넣고 시간을 경과 시킨다.
        bridge.shift();
        if (weight - bridge.reduce((a, b) =&gt; a + b) &gt;= truck_weights[0]) {
            bridge.push(truck_weights.shift());
        } else {
            bridge.push(0);
        }
        time++;
    }
    return time;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 프린터]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%94%84%EB%A6%B0%ED%84%B0</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%94%84%EB%A6%B0%ED%84%B0</guid>
            <pubDate>Fri, 08 Apr 2022 02:31:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://velog.velcdn.com/cloudflare/make_w/614e5e95-3480-48af-b6e0-b4d802e1fcd6/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(priorities, location) {
    const dimen_arr = priorities.map((v, i) =&gt; [i, v])

    const stack = []

    while(true){
        let first = dimen_arr.shift()

        if(dimen_arr.some(v =&gt; first[1] &lt; v[1])){
            dimen_arr.push(first)       
        } else {
            stack.push(first[0])
        } 
        if(dimen_arr.length === 0) break;
    }

    return stack.indexOf(location) + 1
}</code></pre>
<ul>
<li>priorities 배열 값에 index를 넣은 이차원 배열을 dimen_arr에 할당 </li>
<li>조건에 맞는 요소를 위치할 stack 빈배열 선언</li>
<li>true while문을 통해 dimen_arr가 빈배열이 될 때까지 루프 수행</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 짝지어 제거하기]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A7%9D%EC%A7%80%EC%96%B4-%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A7%9D%EC%A7%80%EC%96%B4-%EC%A0%9C%EA%B1%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 01 Apr 2022 08:15:39 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://media.vlpt.us/images/make_w/post/27844987-4017-423f-800e-2228e33088e0/image.png" alt=""></p>
<h2 id="✍-나의-풀이-1">✍ 나의 풀이 1</h2>
<pre><code class="language-javascript">function solution(s){
    const newArr = s.split(&#39;&#39;)

     for(let i = 0; i &lt; newArr.length; i++){
        if(newArr[i] === newArr[i+1]){
             newArr.splice(i, 2)
             i = -1
         }
     }
     return newArr.length ? 0 : 1
 }</code></pre>
<ul>
<li>문자열 s를 배열로 변환해 newArr 상수에 할당</li>
<li>newArr의 앞, 뒤 요소가 같다면 splice함수를 통해 제거하고, 다시 i = 0 부터 시작</li>
</ul>
<p><strong>풀이의 문제점</strong>
테스트케이스의 문자열이 짧다면 무리없이 실행되겠지만, 길이가 1,000,000이라면 같은 요소를 만나면 다시 처음으로 돌아가는 방식은 상당히 무리가 된다.</p>
<pre><code class="language-javascript"> function solution(s){
     const newArr = s.split(&#39;&#39;)

     function recur(arr){
         for(let i = 0; i &lt; arr.length; i++){
             if(arr[i] === arr[i+1]){
                 arr.splice(i, 2)
             }
         }
     }

     recur(newArr)

     return newArr.length ? 0 : 1
 }</code></pre>
<p>그래서 재귀함수를 사용해봤다. 몇몇 런타임에러나는 경우는 뭐가 잘못된건지 파악못했지만, 확실히 통과하는 케이스는 빠르게 통과한다. 하지만 효율성에서는 꽝이었다. 여전히 반복문을 처음부터 시작하는 건 똑같아서 그런듯하다.</p>
<p>그래서 <strong>스택</strong>으로 풀이하는 여러 답안을 봤다. </p>
<pre><code class="language-javascript"> const solution = (s) =&gt; {
  if (s.length % 2 != 0) return 0;

  const stack = [];

  for (let i = 0; i &lt; s.length; i++) {
    const b = s.charAt(i);

    if (stack[stack.length - 1] === b) {
      stack.pop();
    } else {
      stack.push(b);
    }
  }
  return stack.length &gt; 0 ? 0 : 1;
};</code></pre>
<ul>
<li>우선 문자열 길이가 홀수라면 최종 반환값 또한 홀수이기 때문에 미리 리턴한다.</li>
<li>stack 이라는 빈배열을 선언과 동시에 할당한다.</li>
<li>조건의 결과에 따라 push, pop을 해서 반복문을 처음부터 돌리는 비효율을 범하지 않는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Promise]]></title>
            <link>https://velog.io/@make_w/Promise</link>
            <guid>https://velog.io/@make_w/Promise</guid>
            <pubDate>Thu, 31 Mar 2022 08:11:04 GMT</pubDate>
            <description><![CDATA[<h1 id="동기--비동기">동기 | 비동기</h1>
<pre><code class="language-javascript">    // 동기적인 경우
    console.log(1);
    console.log(2);
    console.log(3);
    console.log(4);

    // 1
    // 2
    // 3
    // 4

    // 비동기적인 3번째 경우
    console.log(1);
    console.log(2);
    setTimeout(() =&gt; console.log(3), 5000);
    console.log(4);

    // 1
    // 2
    // 4
    // 3</code></pre>
<p>&#39;synchronous하다.&#39; 즉, 동기적이라는 말은 순차적으로 실행됨을 의미하고,
&#39;asynchronous하다.&#39; 즉, 비동기적이라는 말은 병렬적으로 자신의 시간표대로 실행됨을 의미한다. </p>
<h1 id="fetch-api">Fetch API</h1>
<p>Fetch API의 반환값은 &#39;A Promise that resolves to a Response object.&#39;이다.</p>
<pre><code class="language-javascript">    let fetched = fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;)

    // fetch를 통해서 실행한 결과가 성공적일때, then함수가 시행되고 Response 객체를 반환!
    fetched.then(function(reponse){console.log(&#39;result&#39;, response)}
    // result Response {type: &#39;cors&#39;, url:     &#39;https://jsonplaceholder.typicode.com/posts&#39;, redirected: false, status: 200, ok: true, …}</code></pre>
<p>Promise를 사용하는 이유는 비동기적인 작업을 처리할 때 그 작업의 성공 유무를 표준화된 방식을 이용해 처리할 수 있게 한다.
성공했을 때는 then으로 전달된 함수를 실행.
실패했을 때는 catch로 전달된 함수를 실행.</p>
<p>일반적으로 아래와 같이 사용한다.</p>
<pre><code class="language-javascript">    fetch(&#39;https://jsonplaceholder.typicode.com/posts&#39;)
        .then(function(response){
              return response.json()
      // reponse가 json 데이터 타입이라는 것을 js에 알려주는 것
      // 또 Promise를 반환
        })
        .catch(function(reason){
              console.log(&#39;reason&#39;, reason)
        })
        .then(function(data){
              console.log(&#39;data&#39;, data)
        })</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux Reducer는 왜 순수함수인가?]]></title>
            <link>https://velog.io/@make_w/Redux-Reducer%EB%8A%94-%EC%99%9C-%EC%88%9C%EC%88%98%ED%95%A8%EC%88%98%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@make_w/Redux-Reducer%EB%8A%94-%EC%99%9C-%EC%88%9C%EC%88%98%ED%95%A8%EC%88%98%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Wed, 30 Mar 2022 14:49:30 GMT</pubDate>
            <description><![CDATA[<h1 id="순수함수">순수함수</h1>
<p>순수함수란 동일한 인자가 주어졌을 때 항상 동일한 결과를 반환해야 하며 외부의 상태를 변경하지 않는 함수이다. 즉 함수 내 변수 외에 외부의 값을 참조, 의존하거나 변경하지 않아야한다.</p>
<pre><code class="language-javascript">let obj = {val: 20}

const notPureFn = (object, num) =&gt; {
  object.val += num;
}
// 외부 obj 배열의 값을 수정함

const notPureFn = (num) =&gt; {
  object.val += num;
}
// 함수 외부의 변수를 참조함

const notPureFn = (object, num) =&gt; {
  num = 10
  object.val += num;
}
// 함수의 인자를 수정함</code></pre>
<p><strong>그래서 왜 순수함수여야 하는가??</strong></p>
<h1 id="redux의-변경감지-정책">Redux의 변경감지 정책</h1>
<p>Redux Reducer를 통해 우리는 state를 업데이트해왔다.
즉 불변해야한다는 것이 state를 변경하면 안된다는 뜻이 아니라, 수정해서는 안된다는 것이다.</p>
<pre><code class="language-javascript">function counter(state = initialState, action) {
  switch(action.type) {
    case types.INCREMENT:
      return { ...state, number: state.number + 1 };
    case types.DECREMENT:
      return { ...state, number: state.number - 1 };
    default:
      return state;
  }
}</code></pre>
<p>위의 카운터 Reducer를 보면 원본 state를 수정하는 것이 아닌, spread 연산자를 사용해 복사한 후 수정하고 있다. 
복사에는 얕은 복사와 깊은 복사가 있다.</p>
<hr>
<h2 id="얕은-복사shallow-copy와-깊은-복사deep-copy">얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)</h2>
<h3 id="얕은-복사shallow-copy">얕은 복사(Shallow Copy)</h3>
<p>얕은 복사는 참조(주소)값의 복사를 의미한다.</p>
<pre><code class="language-javascript">const obj = { value: 10 }
const newObj = obj

newObj.value = 5;

console.log(obj.value); // 2
console.log(newObj.value); // 2</code></pre>
<p>obj 객체를 새로운 newObj 객체에 할당하였으며 이를 참조 할당이라 부른다.
복사 후 newObj 객체의 value값을 변경하였더니 기존의 obj.value값도 같이 변경된 것을 알 수 있다.
이는 데이터가 그대로 생성되는 것이 아닌 해당 데이터의 참조 값(메모리 주소)를 전달하여 결국 한 데이터를 공유하는 것이다.</p>
<h3 id="깊은-복사deep-copy">깊은 복사(Deep Copy)</h3>
<p>깊은 복사는 값 자체의 복사를 나타내 다른 주소값을 지닌다.</p>
<pre><code class="language-javascript">const obj = { value: 10 }
const newObj = { ...obj }

newObj.value = 5

console.log(obj.value); // 10
console.log(newObj.value); // 5</code></pre>
<p>자바스크립트의 원시 타입(string, number, boolean, undefined, ES6 부터 추가된 symbol)은 깊은 복사가 되며, 이는 독립적인 메모리에 값 자체를 할당하여 생성하는 것이라 볼 수 있다.
깊은 복사를 할 때 주로 사용되는 <code>Object.assign()</code>메소드와 위의 spread 연산자가 있다.</p>
<hr>
<p>이렇게 원본 state를 수정하는 것이 아니라, 주소값이 다른 state 복사해 수정을 하는 이유는 Redux의 변경감지 알고리즘에 있다.
redux는 reducer를 거친 state가 변경됐는지를 검사하기 위해 state 객체의 주소를 비교한다. state의 복제본을 만들어 반환하면 이전의 state와 다른 주소값을 가르키기 때문에 state가 변경되었다고 판단한다. 반대로 state를 복제하는것이 아닌 속성만 수정하여 반환하면 기존의 state 객체와 가리키는 주소값이 같기 때문에 변경감지가 되지 않는다.</p>
<h1 id="redux는-왜-주소값을-비교하는가">Redux는 왜 주소값을 비교하는가?</h1>
<p>변경을 알아차리기위해 바뀐 속성을 찾아나서려면 성능과 복잡성의 문제를 일으킨다. 객체의 속성을 비교하는 것은 깊은 비교라하는데, 이는 복잡하고 무거운 알고리즘을 필요로 한다.
아래는 단순 주소를 비교하는 알고리즘과 속성을 비교하는 알고리즘이다.</p>
<pre><code class="language-javascript">// 객체의 주소 비교
const compareReference = (object1, object2) =&gt; object1 === object2; 

// 객체의 속성 비교 
const compareProps = (object1, object2) =&gt; {
  const object1Keys = Object.keys(object1);
  const object2Keys = Object.keys(object2);
  if (object1Keys.length !== object2Keys.length) {
    return false;
  }
  for (const key of object1Keys) {
    if (typeof object1[key] === &#39;object&#39; &amp;&amp; typeof object2[key] === &#39;object&#39;){
      return compareProps(object1[key], object2[key]);
    } else if (object1[key] !== object2[key]) {
      return false; 
    } 
  } 
  return true; 
}</code></pre>
<p>속성비교는 먼저 키값만을 배열로 만들고, 이들의 키값의 개수가 동일한지 체크하고, 만약 개수가 동일하다면 키에 해당하는 값의 타입을 비교해서 같다면... 아무튼 복잡하다.</p>
<hr>
<h1 id="마무리">마무리</h1>
<p>Redux Reducer는 순수함수(외부의 값을 참조하거나 변경x, 함수 인수를 변경x)여야하고, 순수함수여야하는 이유는 이전 state의 주소값과 리턴된 state의 주소값을 비교해서 변경을 감지하지하기 때문이다.</p>
<hr>
<p>참조 사이트:
<a href="https://velog.io/@recordboy/JavaScript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACShallow-Copy%EC%99%80-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACDeep-Copy">https://velog.io/@recordboy/JavaScript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACShallow-Copy%EC%99%80-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACDeep-Copy</a>
<a href="https://velog.io/@kimu2370/redux%EC%9D%98-reducer%EA%B0%80-%EC%88%9C%EC%88%98%ED%95%A8%EC%88%98%EC%9D%B8-%EC%9D%B4%EC%9C%A0">https://velog.io/@kimu2370/redux%EC%9D%98-reducer%EA%B0%80-%EC%88%9C%EC%88%98%ED%95%A8%EC%88%98%EC%9D%B8-%EC%9D%B4%EC%9C%A0</a>
<a href="https://boxfoxs.tistory.com/406">https://boxfoxs.tistory.com/406</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 타겟 넘버]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84</guid>
            <pubDate>Wed, 30 Mar 2022 13:35:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt="">
<img src="https://images.velog.io/images/make_w/post/8482cd54-9f8d-4dd9-80f2-61ec905657ac/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(numbers, target) {
    let answer = 0;

      dfs(0,0)

    function dfs(depth, sum){
        if(depth === numbers.length){
          if(sum === target){
              answer++
          }
          return
        }
        // 동시 다발적으로 수행
        dfs(depth + 1, sum + numbers[depth])
        dfs(depth + 1, sum - numbers[depth])
    }
    return answer;
}</code></pre>
<p>처음 접하는 재귀함수였는데, 두개나 들어가서 이해하는데 어려움이 있었다.
이제껏 단방향 코드만 짜다가 동시다발적으로 터지는 코드를 접하니 컴퓨터의 위대함을 깨닫는다..</p>
<p><code>dfs(0,0)</code>을 신호탄으로 삼아, 깊이가 5에 다달았을 때 target과 값이 같다면 answer++해주고, 다르다면 그자리에서 함수를 끝내버린다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 기능개발]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B8%B0%EB%8A%A5%EA%B0%9C%EB%B0%9C</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B8%B0%EB%8A%A5%EA%B0%9C%EB%B0%9C</guid>
            <pubDate>Tue, 29 Mar 2022 14:15:38 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://images.velog.io/images/make_w/post/8b2ba106-37be-425f-b795-adc3ad6206d2/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(progresses, speeds) {
    let rest = progresses.map(v =&gt; 100 - v)
    let day = rest.map((v, i) =&gt; Math.ceil(v / speeds[i]))
    // 아래처럼 축소가능,,
    // day = progresses.map((v, i) =&gt; Math.ceil((100 - v) / speeds[i]))

    let answer = []
    let count = 1
    let prev = day[0]

    for(let i = 1; i &lt; day.length; i++){
        if(day[i] &lt;= prev){
            count++
        } else {
            answer.push(count)
            prev = day[i]
            count = 1
        }  
    }
    answer.push(count)

    return answer
}</code></pre>
<ul>
<li>100과 profresses의 각 요소의 차를 rest라는 배열에 할당</li>
<li>rest의 각 요소에 대응되는 speeds의 요소를 나눠준 후, 절대올림을 통해 도출된 소요기간을 day라는 배열에 할당</li>
<li>배열 day의 첫요소를 prev 변수에 할당하여, 순차적으로 비교</li>
<li>마지막 인덱스 요소의 count는 for문이 끝난 시점에 push</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 124나라의 숫자]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-124%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-124%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90</guid>
            <pubDate>Tue, 29 Mar 2022 07:05:04 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://images.velog.io/images/make_w/post/c2a87249-7f88-4d35-a550-38352121f9e7/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(n) {
   const arr = [4, 1, 2]
   let answer = &#39;&#39;

   while(n){
       answer = arr[n%3] + answer
       n = n % 3 === 0 ? (n/3)-1 : Math.floor(n/3)
   }

   return answer 
}</code></pre>
<p>answer에 n을 3으로 나눈 나머지의 인덱스 값을 할당하고, 나머지가 0이라면 몫에서 -1한 값을 n에 재할당하고, 아니라면 절대내림한 값을 재할당해 n이 0이될 때까지 반복문을 실행했다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 멀쩡한 사각형]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%A9%80%EC%A9%A1%ED%95%9C-%EC%82%AC%EA%B0%81%ED%98%95</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%A9%80%EC%A9%A1%ED%95%9C-%EC%82%AC%EA%B0%81%ED%98%95</guid>
            <pubDate>Mon, 28 Mar 2022 03:07:56 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://images.velog.io/images/make_w/post/cac134ad-9ddd-4d19-81db-b15c3b1a1e5d/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(w, h) {
    // 최대공약수 구하기
    let gcd = 1
    for(let i = 2; i &lt;= Math.min(w, h); i++){
        if(w % i === 0 &amp;&amp; h % i === 0){
            gcd = i
        }
    }

    return w * h - (w + h - gcd)
}</code></pre>
<h2 id="✍-최대공배수">✍ 최대공배수</h2>
<pre><code class="language-javascript">function getLCM(w, h){
    let lcm = 1
    while(true){
        if(lcm % w === 0 &amp;&amp; lcm % h === 0) break;
          lcm++
    }
      return lcm
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[DOM]]></title>
            <link>https://velog.io/@make_w/DOM</link>
            <guid>https://velog.io/@make_w/DOM</guid>
            <pubDate>Sun, 27 Mar 2022 06:56:17 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/4bc4059d-c3e3-4964-bc4e-43bb0910120c/%F0%9F%93%9DTIL.png" alt=""></p>
<h1 id="😝-오늘의-토픽-dom">😝 오늘의 토픽 DOM</h1>
<p>먼저 <strong>JavaScript</strong>의 입장에서 HTML은 어떻게 보일까?
단순히 의미없는 문자열로 보이지 않을까??
그럼 무슨 작업을 할 수 있지???
기껏해야 문자열에 사용할 수 있는 메소드 slice, substr, length...</p>
<p>그래서! HTML을 JavaScript가 이해할 수 있는 자료형으로 바꿔줘야할 필요성이 대두!
DOM(Document Object Model)!! 쉽게 말해 HTML같은 문자열만 그득한 문서를 JavaScript가 이해할 수 있는 <strong>객체</strong>로 바꿔주는 것! 이러한 과정을 <strong>PARSE</strong>라고 한다.</p>
<p>그럼 어떤 객체로 바꿔주는데?? 객체에도 종류가 많잖어..
<strong>Node객체</strong>!! 요소 하나하나를 Node로 생각하면 쉬울듯?</p>
<h2 id="node객체">Node객체</h2>
<pre><code class="language-javascript">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;node&quot;&gt;
        &lt;div&gt;안녕 나는 요소야&lt;/div&gt;
        &lt;button&gt;클릭&lt;/button&gt;
        &lt;div&gt;
            &lt;div&gt;하하하&lt;/div&gt;
            호호호
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>JavaScript가 저 HTML을 조작하려면 어떻게 해??
class나 id 그리고 요소이름을 통해 대표적으로 document.querySelector를 통해 해당 요소를 특정한다.
저 메소드는 누가 제공해? DOM이!
<code>const node = document.querySelector(&#39;.node&#39;)</code>이렇게 특정화를 하고,
<code>node.nodeType // 1</code> <code>node.nodeName // div</code> 
즉 우리가 선택한 노드는 타입이 1이고, 이름은 div라는 것이지!
<code>node.parentNode</code>는 body
<code>node.parentNode.childNodes</code>는 NodeList(7) [text, div.node, text, comment, text, script, text]</p>
<p>이밖에도 많지만 Node객체로 변환해주면서, DOM은 이들의 관계나 속성에 조작을 가할 수 있는 메소드나 프로퍼티를 제공한다. JavaScript가 이해할 수 있도록 책임져야지!!</p>
<hr>
<p>Node객체도 종류가 많아! 많대..</p>
<p>-Document Nodes
-Element Nodes
등등
이건 추후에 다뤄봅세</p>
<p>어쨋든 다시 DOM은 JavaScript가 이해할 수 있게 HTML을 Node객체로 변환해주는 것!</p>
<p><strong>DOM은 브라우저에서 보이는 것이냐?</strong>
아니! 브라우저 뷰 포트에 보이는 것은 렌더 트리로 DOM과 CSSOM의 조합인거야.
CSSOM은 대충 감이 온다. CSS도 한낱 문자열이니 얘도 바꿔줘야지.
그래서 왜 보이는 것이 아니냐?
HTML에 p Element를 <code>display: none</code>한다고 사라지냐?
화면에서는 사라지겠지 그런데 남아있잖아. 그래서 보여지는 게 아니라는 것!
p Element에 이름붙여서 호출하면 나올걸?</p>
<p><strong>요약정리</strong>
DOM은 HTML 문서에 대한 인터페이스입니다. 첫째로 뷰 포트에 무엇을 렌더링 할지 결정하기 위해 사용되며,
둘째로는 페이지의 콘텐츠 및 구조, 그리고 스타일이 자바스크립트 프로그램에 의해 수정되기 위해 사용됩니다.
DOM은 원본 HTML 문서 형태와 비슷하지만 몇 가지 차이점이 있습니다.</p>
<p>항상 유효한 HTML 형식입니다.
자바스크립트에 수정될 수 있는 동적 모델이어야 합니다.
가상 요소를 포함하지 않습니다. (Ex. ::after)
보이지 않는 요소를 포함합니다. (Ex. display: none)</p>
<p>참조:
<a href="https://wit.nts-corp.com/2019/02/14/5522">https://wit.nts-corp.com/2019/02/14/5522</a>
<a href="https://www.youtube.com/watch?v=CFgXIJ3RZ50">https://www.youtube.com/watch?v=CFgXIJ3RZ50</a></p>
<p>✍🏻🙆🏻‍♂️</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3월 26일]]></title>
            <link>https://velog.io/@make_w/3%EC%9B%94-26%EC%9D%BC</link>
            <guid>https://velog.io/@make_w/3%EC%9B%94-26%EC%9D%BC</guid>
            <pubDate>Sat, 26 Mar 2022 14:52:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/4bc4059d-c3e3-4964-bc4e-43bb0910120c/%F0%9F%93%9DTIL.png" alt=""></p>
<h1 id="✍🏻-오늘의-정리-목록">✍🏻 오늘의 정리 목록</h1>
<ul>
<li>Button</li>
</ul>
<h1 id="😝-미해결-목록">😝 미해결 목록</h1>
<h2 id="🙆🏻♂️-왜-클릭이-잘-안먹지">🙆🏻‍♂️ 왜 클릭이 잘 안먹지?</h2>
<p><img src="https://images.velog.io/images/make_w/post/569e691b-77fb-488c-82fd-724676c15104/image.png" alt="">
저 체크 svg를 클릭했을 때 배경색과 글자의 style을 변경하도록 구성했는데, 어쩔 때는 적용이되고, 어쩔 때는 안되는 이상한 현상을 발견했다..
그래서 계속 클릭하다가 알게됐다!
<img src="https://images.velog.io/images/make_w/post/b8299764-ec52-411c-aeb4-94f67c363e68/image.png" alt="">
svg에 직접 onClick 속성을 적용한지라, path를 눌렀을 때는 적용이 안되는 것이었다.
그래서 버튼 요소를 둘렀다.
<img src="https://images.velog.io/images/make_w/post/9415909c-e794-455a-9b0c-f7e2ad7c8a20/image.png" alt="">
그랬더니 구욷!ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 오픈 채팅방]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%A4%ED%94%88-%EC%B1%84%ED%8C%85%EB%B0%A9</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%A4%ED%94%88-%EC%B1%84%ED%8C%85%EB%B0%A9</guid>
            <pubDate>Sat, 26 Mar 2022 07:40:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt="">
<img src="https://images.velog.io/images/make_w/post/a30b64f5-1d40-49a3-b5a8-ae77b01dc8a9/image.png" alt="">
<img src="https://images.velog.io/images/make_w/post/8f0a88bb-dd0f-473c-99a3-c3bcb6f45a41/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(record) {
    const users = {}
    const orders = []
    for(let rec of record){
        const [action, username, nickname = &#39;&#39; ] = rec.split(&#39; &#39;)
        if(action === &#39;Enter&#39;){
            users[username] = nickname;
            orders.push([action, username]);
        } else if(action === &#39;Leave&#39;){
            orders.push([action, username]);
        } else {
            users[username] = nickname;
        }
    }

    const result = []
    for(let rec of orders){
        const [action, username] = rec
        if(action === &quot;Enter&quot;){
            result.push(`${users[username]}님이 들어왔습니다.` )
        } else {
            result.push(`${users[username]}님이 나갔습니다.` )
        }
    }

    return result
}</code></pre>
<h2 id="✍-풀이과정">✍ 풀이과정</h2>
<ol>
<li>user의 최종 닉네임을 저장하기 위한 users 객체 선언</li>
<li>user의 행동을 기록할 orders 배열 선언</li>
<li><code>const [action, username, nickname = &#39;&#39; ] = rec.split(&#39; &#39;)</code>
&#39;Leave&#39; 행동에 대해서는 nickname 요소가 없어 디폴트값 할당</li>
<li><code>users[username] = nickname;</code>
해당 username이라는 key가 없을 때는 추가해주고, key가 있을 때는 업데이트해주는 방식</li>
</ol>
<h2 id="✍-중복-제거">✍ 중복 제거</h2>
<pre><code class="language-javascript">function solution(record) {
    const users = {}
    const orders = []
    const text = {
        Enter: &#39;님이 들어왔습니다.&#39;,
        Leave: &#39;님이 나갔습니다.&#39;,
    }

    for(let rec of record){
        const [action, username, nickname = &#39;&#39; ] = rec.split(&#39; &#39;)
        if(action !== &#39;Change&#39;) orders.push([action, username]);
        if(nickname) users[username] = nickname;
    }

    return orders.map(v =&gt; users[v[1]] + text[v[0]])
}</code></pre>
<h2 id="✍-학습요망">✍ 학습요망</h2>
<p><a href="https://kis6473.tistory.com/167">https://kis6473.tistory.com/167</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스: 문자열 압축]]></title>
            <link>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%95%95%EC%B6%95</link>
            <guid>https://velog.io/@make_w/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EC%95%95%EC%B6%95</guid>
            <pubDate>Fri, 25 Mar 2022 05:57:52 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/make_w/post/469b5532-e056-4770-b04b-e9eaecf10fe4/js%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.png" alt=""></p>
<p><img src="https://images.velog.io/images/make_w/post/20bb618d-0f6d-4226-ae61-5420d29cac86/image.png" alt=""></p>
<h2 id="✍-나의-풀이">✍ 나의 풀이</h2>
<pre><code class="language-javascript">function solution(s) {
    const answer = [];
    if(s.length === 1) return 1;
    for(let i = 1; i &lt;= s.length/2; i++){
        let prev = s.substr(0,i);
        let count = 1;
        let str = &#39;&#39;;

        for(let j = i; j &lt; s.length; j += i){
            let cur = s.substr(j,i);
            if(prev === cur) count++;  
            else {
                str += (count &gt; 1 ? count : &#39;&#39;) + prev;
                count = 1;
                prev = cur;
            };
        };

          str += (count &gt; 1 ? count : &#39;&#39;) + prev; 
        answer.push(str.length);
        str = &#39;&#39;;
    };
    return Math.min(...answer);
};</code></pre>
<h2 id="✍-풀이과정">✍ 풀이과정</h2>
<ul>
<li>일단 매개변수 s의 길이가 1이라면 for문이 작동하지 않는다. 그래서 for문을 시작하기 전 길이가 1인 문자열에 대해서는 바로 return했다.</li>
<li>prev(이전값)라는 변수를 설정해 cur(현재값)변수와 비교해나가는 코드를 구성했다.</li>
<li><code>prev === cur</code>이라면 카운트만 해주고, 지속되는 중복을 잡아내기위해 prev를 재할당하지 않았다.</li>
<li><code>prev !== cur</code>이면 앞뒤 문자가 다르다는 것이고, 지속되는 중복이 끝났다는 의미이기도 해서 prev 앞에 count를 붙여 str변수에 할당해주었다.</li>
<li>제일 마지막 cur은 for문 내에서 처리될 수 없기에, for문이 끝난 바로 다시 <code>str += (count &gt; 1 ? count : &#39;&#39;) + prev</code> 작성해 마지막 cur을 str에 반영했다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>