<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>pica_pica.log</title>
        <link>https://velog.io/</link>
        <description>한걸음씩</description>
        <lastBuildDate>Tue, 14 Jun 2022 14:21:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>pica_pica.log</title>
            <url>https://images.velog.io/images/pica_pica/profile/9606bce5-7d37-440a-bc49-40f01cff0343/unnamed.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. pica_pica.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/pica_pica" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[모던 자바스크립트 메모 (7~8장)]]></title>
            <link>https://velog.io/@pica_pica/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A9%94%EB%AA%A8-78%EC%9E%A5</link>
            <guid>https://velog.io/@pica_pica/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A9%94%EB%AA%A8-78%EC%9E%A5</guid>
            <pubDate>Tue, 14 Jun 2022 14:21:17 GMT</pubDate>
            <description><![CDATA[<h3 id="7장-연산자">7장 연산자</h3>
<ol>
<li><p>typeof &#39;Hi&#39;(결과: string)  이것도 &#39;타입 연산자&#39;라고 한다.</p>
</li>
<li><p>다음은 문자열 연결 연산자의 결과들을 보여준다.</p>
<ul>
<li>1 + ture -&gt; 2</li>
<li>1 + false -&gt; 1</li>
<li>1 + null -&gt; 1</li>
<li>1 + undefined -&gt; NaN</li>
<li>+undefined -&gt; NaN
즉, true는 1, false와 null은 0, undefined는 숫자로 타입변환이 되지 않는걸 알 수 있다.</li>
</ul>
</li>
<li><p>동등/일치 비교 연산자 중 예외인것이 있는데 주의! (NaN === NaN 은 false로 나온다.)
자신과 일치하지 않는 유일한 값이다. 따라서 숫자가 NaN인지 조사하려면 빌트인 함수 isNaN을 사용한다.</p>
</li>
<li><p>ES6에서 도입된 <strong>Object.is(a, b)를 사용하면 예측 가능한 정확한 예측 비교 결과를 반환</strong>한다. 예를보면 쉽게 알수 있다.
ex) 0 === -0 (true) Object.is(0, -0) (false)  그외에는 일치 비교연산자(===)와 동일.</p>
</li>
</ol>
<h3 id="8장-제어문">8장 제어문</h3>
<p>제어문은 <strong>조건에 따라 코드 블록을 실행하거나 반복실행 할 때 사용</strong>한다.</p>
<ol>
<li>블록문은 0개 이상의 문을 중괄호로 묶은것으로 코드 블록 또는 블록이라고 부르기도 한다.</li>
</ol>
<p><strong>자바스크립트는 블록문을 하나의 실행단위로 취급</strong>한다.
2. 문의 끝에는 일반적으로 세미콜론을 붙이는 것이 맞지만 블록문은 언제나 문의 종료를 의미하는 자체 종결성을 갖기 때문에 블록문의 끝에는 세미콜론을 붙이지 않는다.
3. 레이블 문, 반복문(for, for...in, for...of, while, do...while)또는 switch문의 코드 블록에서 break와 continue를 쓸수 있다. (break는 반복문 탈출, continue는 실행 중단 후 반복문의 증감식으로 이동)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 메모 (4장~6장)]]></title>
            <link>https://velog.io/@pica_pica/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A9%94%EB%AA%A8-4%EC%9E%A56%EC%9E%A5</link>
            <guid>https://velog.io/@pica_pica/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%A9%94%EB%AA%A8-4%EC%9E%A56%EC%9E%A5</guid>
            <pubDate>Sun, 12 Jun 2022 12:44:49 GMT</pubDate>
            <description><![CDATA[<h3 id="4장-변수">4장 변수</h3>
<p>변수란 <strong>하나의 값을 저장하기 위해 확보한 메모리 공간 자체</strong> 또는 <strong>그 메모리 공간을 식별하기 위해 붙인 이름</strong>을 말한다.</p>
<ol>
<li><p>변수에 값을 저장 [할당] &lt;----&gt; 변수의 저장된 값을 읽는것 [참조]</p>
</li>
<li><p>변수이름을 식별자라고도 하는데 <strong>어떤 값을 구별해서 식별할 수 있는 고유한 이름</strong>을 말한다.
(식별자는 값이 아니라 메모리 주소를 기억한다.)</p>
</li>
<li><p>undefined는 <strong>자바스크립트에서 제공하는 원시타입의 값</strong>이다. 변수에 아무값도 지정해주지 않고 선언하였을때 메모리에 이렇게 할당되어 초기화 된다.</p>
</li>
<li><p>자바스크립트 엔진은 변수선언을 2단계에 거쳐서 수행한다.</p>
<ul>
<li><strong>1.선언 단계</strong> : 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.</li>
<li><strong>2.초기화 단계</strong> : 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화 한다.</li>
</ul>
</li>
<li><p>변수 선언문이 <strong>코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징</strong>을 변수 호이스팅이라 한다. 그리고 var, let, const, function, function*, class 키워드를 사용해서 선언하는 모든 식별자(변수, 함수, 클래스 등)는 호이스팅 된다. 즉 모든 선언문은 런타임 이전 단계에서 먼저 실행되기 때문이다.</p>
</li>
<li><p>변수에 값을 할당할 때는 이전값 undefined가 저장되어 있던 메모리 공간을 지우고 그 메모리 공간에 할당 값 80을 새롭게 저장하는것이 아닌 새로운 메모리 공간을 확보하고 그곳에 값을 저장한다.</p>
</li>
<li><p>위의 과정을 통해 안쓰는 메모리 공간(어떤 식별자도 참조하지 않는 메모리 공간)은 <strong>가비지 콜렉터에 의해 메모리에서 자동 해제</strong> 된다.</p>
</li>
<li><p>네이밍 컨벤션</p>
<ul>
<li>카멜 케이스 
ex) firstName, myText</li>
<li>스네이크 케이스
ex) first_name, my_text</li>
<li>파스칼 케이스
ex) FirstName, MyText</li>
</ul>
</li>
</ol>
<h3 id="5장-표현식과-문">5장 표현식과 문</h3>
<ol>
<li>리터럴은 <strong>사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법</strong>을 말한다.
ex) 정수 리터럴  3, 불리언 리터럴 true</li>
<li>표현식은 <strong>값으로 평가될 수 있는 상태</strong>이다. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.
ex) var scope = 50 + 50; (50+50이 100으로 표현되므로 표현식이다.)</li>
<li>자바스크립트는 세미콜론 자동 삽입기능(ASI)이 암묵적으로 수행된다.</li>
</ol>
<h3 id="6장-데이터-타입">6장 데이터 타입</h3>
<ol>
<li><strong>자바스크립트의 숫자 타입은 모든 수를 실수로 처리</strong>한다.
ex) console.log(1 === 1.0) 이는 정수로 표시된다고 해도 사실은 실수라는 것을 의미</li>
<li>es6부터 사용할 수 있는 템플릿 리터럴은 <strong>멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등 편리한 문자열 처리 기능을 제공</strong>한다. 사용하는 방법은 ` 백틱을 이용한다.</li>
<li>자바스크립트의 <strong>변수는 선언이 아닌 할당에 의해 타입이 결정(타입 추론)된다. 그리고 재할당에 의해 변수의 타입은 언제든지 동적으로 변할 수 있다</strong>. --&gt; 동적 타입 언어</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 실행 엔진]]></title>
            <link>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%A4%ED%96%89-%EC%97%94%EC%A7%84</link>
            <guid>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%A4%ED%96%89-%EC%97%94%EC%A7%84</guid>
            <pubDate>Wed, 20 Oct 2021 01:27:36 GMT</pubDate>
            <description><![CDATA[<h3 id="엔진의-종류">엔진의 종류</h3>
<ul>
<li>크롬 - V8</li>
<li>오페라 - V8</li>
<li>파이어폭스 - SpiderMonkey</li>
<li>엣지 - ChakraCore</li>
<li>사파리 - SquirrelFish</li>
</ul>
<h3 id="엔진-작동방식">엔진 작동방식</h3>
<ol>
<li>자바스크립트를 읽는다. (파싱)</li>
<li>읽은 자바스크립트 파일을 기계어로 변환한다. (컴파일)</li>
<li>기계어로 변환된 코드가 실행된다. [기계어로 전환되었기 때문에 실행속도 빠름]</li>
</ol>
<p><strong>또한 엔진은 프로세스 각 단계마다 최적화를 진행, 컴파일이 끝나고 실행중인 코드를 감시하여
이 코드로 흘러가는 데이터를 감시하고 분석결과를 토대로 기계어로 전환된 코드를 다시 최적화 한다. 이런 과정 덕분에 실행속도는 더욱 빠름.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스크롤 이벤트]]></title>
            <link>https://velog.io/@pica_pica/%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%9D%B4%EB%B2%A4%ED%8A%B8</link>
            <guid>https://velog.io/@pica_pica/%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%9D%B4%EB%B2%A4%ED%8A%B8</guid>
            <pubDate>Mon, 27 Sep 2021 08:41:10 GMT</pubDate>
            <description><![CDATA[<p>문제발생 : 검색창 보기의 리스트 아이템을 keyDown키로 하나씩 이동하는데 해당 overflow로 가려진 시점부터 리스트 아이템의 타겟은 계속 내려가지만 스크롤이 그대로 있어서..</p>
<p><img src="https://images.velog.io/images/pica_pica/post/846ca9ee-1000-44a2-ac04-12f435776f50/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-09-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.16.14.png" alt="">
<img src="https://images.velog.io/images/pica_pica/post/19fc84a5-bb9d-4e65-aef2-8cfc19a2190f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-09-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.41.56.png" alt=""></p>
<p>해결
scrollHeight : 스크롤에 가려진것 포함 모든 높이 (사진에 리스트를 포함하는 전체 ul)
clientHeight : 눈에 보여지는 요소의 높이 (사진에 보여지는 리스트만 포함하는 ul)
offsetHeight : border + padding을 포함한 요소의 높이
offsetTop : 가까운 부모에 대한 상대적 픽셀 높이</p>
<p><strong>구성환경(Next.js, Typesciprt)</strong></p>
<ol>
<li>전체를 감싸는 ul에 useRef훅을 사용하여 clientHeight를 받아온다.</li>
<li>자식요소의 li에 useRef훅을 사용하여 offsetTop, offsetHeight를 받아온다.</li>
</ol>
<p>ex) 1번 311px , 2번 offsetTop: 29px, offsetHeight: 34px(각 li의 박스 높이(border, padding을 포함한)라고 생각하면됨)</p>
<p>offsetTop + offsetHeight를 하게 되면 사진에 파란색 테두리의 밑부분 즉 경계선 끝지점의 height 위치를 알수있게 되므로
1번 clientHeight보다 2번의 요소들을 더한값이 크게 되는 순간부터 스크롤 화면에 안보이게 되는 지점이 되는것이다.
이 경계점을 파악하여서 if문을 통한 scroll이벤트 분기문을 걸어서 스크롤을 이동하게 하여 해결.
(고1일때  1번 311px 2번 315px로 4px만큼 안보이게 되므로 4px를 ul의 Ref속성의 scrollTop에 더해주면 된다.)</p>
<p><img src="https://images.velog.io/images/pica_pica/post/8db7f1fe-fa33-46dd-a192-144fb53d1762/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-09-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.36.16.png" alt=""></p>
<p><del>이렇게 직접 구현하지 않고 스크롤이나 키이벤트관련해서 더 쉬운방법은 라이브러리 downShift를 사용하면 되는데 다른 추가적인 기능과 복합적으로 사용해야될 상황이 있어서 직접 만들게 되었다.</del>
downshift는 <a href="https://www.npmjs.com/package/downshift">https://www.npmjs.com/package/downshift</a> 여기서 확인해볼수 있다 (정말 유용한것 같다!)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[오늘의 날짜 구하기]]></title>
            <link>https://velog.io/@pica_pica/%EC%98%A4%EB%8A%98%EC%9D%98-%EB%82%A0%EC%A7%9C-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@pica_pica/%EC%98%A4%EB%8A%98%EC%9D%98-%EB%82%A0%EC%A7%9C-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 13 Sep 2021 09:01:30 GMT</pubDate>
            <description><![CDATA[<h3 id="오늘의-날짜현재-날짜-구하는-함수-모듈---typesciprt">오늘의 날짜(현재 날짜) 구하는 함수 모듈 - typesciprt</h3>
<h4 id="--yyyy-mm-dd-ex-2021-08-22">- YYYY-MM-DD (ex 2021-08-22)</h4>
<pre><code>export const getCurrentDate = (): string =&gt; {
    const YEAR = new Date().getFullYear();
    const MONTH = String(new Date().getMonth() + 1).padStart(2, &#39;0&#39;);
    const DAY = String(new Date().getDate()).padStart(2, &#39;0&#39;);

    return `${YEAR}-${MONTH}-${DAY}`;
};</code></pre><blockquote>
<p>기억에 새겨둘것</p>
</blockquote>
<ol>
<li>padStart - 빈 공간을 첫번째 인자 자릿수 만큼 두번째 인자로 채운다. (String으로 감싸주는 이유는 padStart는 string형식에 적용되기 때문에 number 타입을 string타입으로 형변환 해주기 위해서 사용)</li>
<li>Day(일)은 getDay가 아닌 getDate로 구해야한다. (getDay는 일요일(0)~토요일(6)까지 요일 인덱스를 반환해주기 때문에 취지에 맞지 않음)</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React에 관한 지식!]]></title>
            <link>https://velog.io/@pica_pica/React%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@pica_pica/React%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Wed, 16 Jun 2021 13:40:32 GMT</pubDate>
            <description><![CDATA[<h3 id="1-react란-무엇인가">1. React란 무엇인가?</h3>
<p>spa(single page application) 즉, 단일 페이지 응용 프로그램에서 사용자 인터페이스를 구성하는데 사용되는 오픈 소스 프론트엔드 js 라이브러리 입니다.</p>
<p>주요 특징</p>
<ol>
<li>RealDOM 대신 Virtual DOM을 사용하여 자주 변화되는 웹 페이지의 요소도 아주 빠르게 적용 가능 (성능 향상)</li>
<li>단방향 데이터 흐름(추적하기가 쉽다)</li>
<li>컴포넌트를 활용하여 구성요소 재사용 가능</li>
</ol>
<h3 id="2-jsx란">2. JSX란?</h3>
<p>JSX는 JS XML의 구문 표기법 입니다.
HTML과 같은 문법과 함께 JS를 표현할 수 있습니다.</p>
<pre><code>return (
  &lt;div&gt;
    &lt;p&gt;js 문법안에 html을 작성할 수 있어요!&lt;p&gt;
  &lt;div&gt;
)</code></pre><h3 id="3-state란">3. State란?</h3>
<p>Component의 State는 라이프 사이클 동안 변경될 수 있는 정보를 담고 있는 객체입니다.
그리고 state를 가능한 단순하게 만들고 구성요소의 수를 최소화 하기 위해 노력을 해야 합니다.</p>
<h3 id="4-props란">4. Props란?</h3>
<p>Props는 HTML 태그 속성과 유사한 규칙을 사용하여 React Component에 전달되는 값을 포함하는 단일 값 또는 객체 입니다.
부모 컴포넌트 -&gt; 자식 컴포넌트 로 전달되는 데이터.</p>
<h3 id="5-setstate에서-callback역할은-무엇인가">5. setState에서 callback역할은 무엇인가?</h3>
<p>callback 함수는 setState가 끝난 후 component가 리렌더링 된 후 호출됩니다.
setState는 비동기적으로 동작합니다.</p>
<h3 id="6-list에서-key를-사용하는-이유">6. list에서 key를 사용하는 이유?</h3>
<p>Key는 리스트들을 만들때 포함시켜야하는 특수한 속성입니다. Key는 리스트의 변경사항 추가, 삭제된 항목을 react가 판단할 수 있도록 도와줍니다.
(key에 항목 순서가 바뀌는 경우에는 index를 넣는건 바람직하지 않다. 다른 유일성을 갖는 키로 넣어야함!)</p>
<h3 id="7-ref의-용도">7. ref의 용도</h3>
<p>ref는 DOM의 요소나 component에 직접 접근해야 될 경우 유용하게 사용됩니다.
즉 element의 요소를 직접 컨트롤 하고싶을때, useRef를 사용하여 조작 가능.
(useRef를 사용할때 주의할점은 선언된변수.current 를 해야된다. 즉 current를 붙여야 정상적인 사용 가능)</p>
<h3 id="8-forward-ref란">8. forward ref란?</h3>
<p>ref forwarding은 ref를 자식 컴포넌트에게 전달하는 기능을 담당합니다.
즉 부모의 ref요소를 자식에게 props 형태로 넘겨줄때 사용됨.</p>
<h3 id="9-가상-돔이란-무엇이며-어떻게-동작하나요">9. 가상 돔이란 무엇이며 어떻게 동작하나요?</h3>
<p>가상돔이란 실제 돔의 메모리상에서의 표현입니다.
UI의 표현은 메모리에 유지되고 Render함수와 화면을 표시하는 사이에 Real DOM과 동기화 됩니다.</p>
<h4 id="동작순서">동작순서</h4>
<ol>
<li><p>데이터가 변경 되면 전체 UI는 가상돔 안에서 리렌더링 됩니다.
<img src="https://images.velog.io/images/pica_pica/post/c451e10b-ffec-4392-b19a-5ace225ba8d5/image.png" alt=""></p>
</li>
<li><p>그리고 나서 변경되기전 DOM과 새로운 변경된 DOM의 변경점을 계산
<img src="https://images.velog.io/images/pica_pica/post/4db798b6-7ac6-4d2b-b373-60cba4fa52d6/image.png" alt=""></p>
</li>
<li><p>계산이 완료되면 실제 DOM에서 계산된 변경점들만 업데이트
<img src="https://images.velog.io/images/pica_pica/post/b8e7a86e-4788-4a9c-bc9e-67a720474daf/image.png" alt=""></p>
</li>
</ol>
<h3 id="10-react-hooks의-장점">10. React hooks의 장점</h3>
<ol>
<li>클래스 컴포넌트로 작성할때의 this의 필요성이 사라지므로 코드가 간단해짐</li>
<li>공통 기능을 커스텀 hook으로 만들어서 로직을 재사용할 수 있다.</li>
<li>컴포넌트 자체에서 로직을 분리할 수 있어서 테스트 하기 쉬운 코드를 작성할 수 있다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[로컬스토리지, 세션스토리지, 쿠키]]></title>
            <link>https://velog.io/@pica_pica/%EB%A1%9C%EC%BB%AC%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%EC%84%B8%EC%85%98%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%EC%BF%A0%ED%82%A4</link>
            <guid>https://velog.io/@pica_pica/%EB%A1%9C%EC%BB%AC%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%EC%84%B8%EC%85%98%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%EC%BF%A0%ED%82%A4</guid>
            <pubDate>Sun, 13 Jun 2021 09:11:18 GMT</pubDate>
            <description><![CDATA[<h3 id="1-로컬-스토리지">1. 로컬 스토리지</h3>
<blockquote>
<p>로컬스토리지는 클라이언트에 대한 정보를 영구적으로 저장하는 저장소
ex) 한번 로그인했던 정보를 저장하여 자동 로그인</p>
</blockquote>
<pre><code>localStorage.setItem(&quot;info&quot;, 1) // key = &quot;info&quot;, value = 1
localStorage.getItem(&quot;info&quot;)</code></pre><h3 id="2-세션-스토리지">2. 세션 스토리지</h3>
<blockquote>
<p>세션스토리지는 세션 종료(즉 브라우저를 닫을 경우) 클라이언트에 대한 정보를 삭제하는 저장소
ex) 입력 폼에 대한 정보</p>
</blockquote>
<pre><code>sessionStorage.setItem(&quot;info&quot;, 1) // key = &quot;info&quot;, value = 1
sessionStorage.getItem(&quot;info&quot;)</code></pre><h3 id="3-쿠키">3. 쿠키</h3>
<blockquote>
<p>쿠키는 만료 기한이 존재하는 저장소
ex) 사용자의 로그인 판단 유무를 가지고 있는 데이터 저장, 하루동안 다시보지않음 창</p>
</blockquote>
<pre><code>setCookie(&quot;info&quot;, 1, 10) //3번째 매개변수는 유효기간을 나타낸다 10 -&gt; 10초
getCookie(&quot;info&quot;)</code></pre><p><img src="https://images.velog.io/images/pica_pica/post/5dea09c4-6957-4a4b-9d9b-06a52cc39159/image.png" alt=""></p>
<blockquote>
<p>출처: <a href="https://codepen.io/beaucarnes/pen/KmeRMx?editors=0010">https://codepen.io/beaucarnes/pen/KmeRMx?editors=0010</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPA, 그리고 SSR과 CSR]]></title>
            <link>https://velog.io/@pica_pica/SPA-%EA%B7%B8%EB%A6%AC%EA%B3%A0-SSR%EA%B3%BC-CSR</link>
            <guid>https://velog.io/@pica_pica/SPA-%EA%B7%B8%EB%A6%AC%EA%B3%A0-SSR%EA%B3%BC-CSR</guid>
            <pubDate>Fri, 11 Jun 2021 14:22:29 GMT</pubDate>
            <description><![CDATA[<h3 id="1-spa">1. SPA</h3>
<p>Single Page Application 말그대로 한개의 페이지를 가진 웹 애플리케이션이다.
특징으로는</p>
<ul>
<li>사용자 친화적</li>
<li>초기 렌더링 후 데이터만 받아오기 때문에, 상대적으로 서버 요청이 적음</li>
</ul>
<p><img src="https://images.velog.io/images/pica_pica/post/56b15d35-ef2c-4dc8-b42e-45839e034e1e/image.png" alt=""></p>
<h3 id="2-ssr과-csr">2. SSR과 CSR</h3>
<p>SSR(Server Side Rendering) : 서버 사이드 렌더링으로 페이지를 이동할 때마다 서버에 새로운 페이지에 대한 요청을 하는 방식. 서버에서 렌더링을 마치고 Data가 결합된 HTML파일을 내려주는 형태로, 새로운 페이지로 이동할 때마다 서버에 요청해서 페이지를 받아야 하기 때문에, 사용자는 받아오는 기간에 페이지가 깜빡거리는 현상을 볼 수 있다.</p>
<p>CSR(Client Side Rendering) : 클라이언트 사이드 렌더링으로 최초 요청시에 HTML을 비롯해 CSS, Javascript 등 각종 리소스를 받아온다. 이후에선 필요한 데이터만 서버에 요청하고 나머지는 클라이언트에서 자바스크립트로 컨트롤 된다. (만약 인터넷 환경이 좋지 않다면 유저는 빈 페이지만 보게 될것입니다.)
초기 요청 때 SSR보다 많은 요청을 하기 때문에 렌더링 속도는 느린 편이지만 이후 다른 페이지로 이동시에는 SSR보다 빠른 페이지 전환속도와 나은 사용자 경험을 제공합니다.</p>
<p><img src="https://images.velog.io/images/pica_pica/post/bc931777-1068-4fb2-8e07-2d7880b0ff37/image.png" alt=""></p>
<h3 id="3-seo">3. SEO</h3>
<p>리액트나 뷰를 사용하면 아무래도 직면하는 문제가 SEO(검색 엔진 최적화)입니다..
물론 검색 최적화가 필요없는 사이트라면 고민할 필요가 전혀 없는데, 사용자들이 검색을 통해 이용해야할 사이트라면 이것을 해결해야 합니다.
이를 해결하기 위한 방안은 아래와 같다.</p>
<ol>
<li><p><strong>SSR with Hydration</strong> : Hydration 아키텍처에서는 첫 웹 페이지 렌더는 SSR로 이루어지지만 그 이후부터 전환될 모든 페이지는 CSR로 이루어집니다. 이런 작업은 원래 개발자가 직접해야하는 것이지만 프로그래머가 신경 쓸 필요가 없도록 구현되어있는 프레임워크를 사용할 수도 있습니다.
바로 React기반인 Next.js, Vue기반인 Nuxt.js 이렇게 있습니다. 
(처음에 서버사이드 렌더링을 하고 그 후 다른 페이지들에선 클라이언트 사이드 렌더링을 하는 방식)</p>
</li>
<li><p><strong>Pre-rendering</strong> : Pre-rendering에서는 빌드 타임에 모든 HTML을 렌더링 합니다.
이미 렌더링 되어있으므로 SSR하는데 시간이 필요하지 않아서 요청이 매우 빠를것입니다.
단점으로는 빌드 타임에 모든 페이지 생성을 해야하기 때문에 항상 정적인 컨텐츠에서만 활용이 가능합니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 이진 변환 반복하기]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9D%B4%EC%A7%84-%EB%B3%80%ED%99%98-%EB%B0%98%EB%B3%B5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9D%B4%EC%A7%84-%EB%B3%80%ED%99%98-%EB%B0%98%EB%B3%B5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 30 May 2021 09:11:11 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/b9cfef35-39f3-41ca-b6bf-c53f6e4ff5ff/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>전달받은 s를 temp변수에 담는다.</li>
<li>while문을 통해 temp문자열을 split으로 쪼갠 뒤 filter로 0이 아닌걸로 걸러준 뒤 길이를 구한뒤 length 변수에 담아준다.</li>
<li>원래 temp변수의 길이에서 length 변수를 빼주면 0이 제거된 갯수가 되므로 zeroCount에 더해준다.</li>
<li>이렇게 반복해서 length가 1이되면 빠져나가도록, 아니면 temp변수를 다시 새로운 이진수를 담고 count를 증가</li>
<li>결과적으로 count에는 반복된 횟수 zeroCount에는 0이 제거된 총 갯수가 나온다.</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(s) {
    let count = 1;
    let zeroCount = 0;
    let temp = s;
    while(true) {
        const length = temp.split(&quot;&quot;).filter(item =&gt; item === &#39;1&#39;).length;
        zeroCount += temp.length - length;

        if(length === 1) {
            break;
        } else {
            temp = length.toString(2);
            count ++;
        }
    }

    return [count, zeroCount]
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 최솟값 만들기]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B5%9C%EC%86%9F%EA%B0%92-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B5%9C%EC%86%9F%EA%B0%92-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sat, 29 May 2021 12:50:51 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/2e2a2413-8d9c-4ada-b398-cd115fe3579e/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>최솟값을 만드는 방법은 A의 배열에서 최소값과 B의 배열의 최대값을 픽하여 곱해서 누적해주면 결국 누적값이 최소값이 된다.</li>
<li>그러므로 A를 오름차순으로 sort B를 내림차순으로 sort하여 for문을통해 각 원소를 순차적으로 곱해서 answer에 더해주면 끝</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(A,B){
    var answer = 0;
    A.sort((a,b) =&gt; a-b);
    B.sort((a,b) =&gt; b-a);

    for(let i = 0; i &lt; A.length; i ++) {
        answer += A[i] * B[i];
    }

    return answer;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 숫자의 표현]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90%EC%9D%98-%ED%91%9C%ED%98%84</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90%EC%9D%98-%ED%91%9C%ED%98%84</guid>
            <pubDate>Sat, 29 May 2021 10:21:35 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/46afc365-66f1-47c9-8c8a-dddc5fc4061d/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>연속하는 숫자로 더해과는 과정으로 for문으로 작성했으며, while문을 통해 해당 숫자가 나오는 것을 계속 반복하여 answer에 더해준다.</li>
<li>count는 while문의 stop조건이 되기도 하며, answer를 구하는 과정에서도 사용됨</li>
<li>while문을 다 빠져나오게 되면 결국 n에 주어진 숫자의 연속해서 더해진 숫자의 경우의 수를 answer가 가지게 된다.</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(n) {
    let count = 1;
    let answer = 0;

    while(count &lt;= n) {
        let sum = 0;
        for(let i = count; i &lt;= n; i ++) {
            sum += i;
            if(sum &gt;= n) {
                break;
            }
        }

        (sum === n) &amp;&amp; answer ++;
        count ++;
    }

    return answer;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[디자인패턴 mvc, mvp, mvvm 그리고 flux]]></title>
            <link>https://velog.io/@pica_pica/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-mvc-mvp-mvvm-%EA%B7%B8%EB%A6%AC%EA%B3%A0-flux</link>
            <guid>https://velog.io/@pica_pica/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-mvc-mvp-mvvm-%EA%B7%B8%EB%A6%AC%EA%B3%A0-flux</guid>
            <pubDate>Fri, 28 May 2021 11:35:11 GMT</pubDate>
            <description><![CDATA[<p>개발을 하다보면 피할수 없게되는 <strong>디자인패턴</strong>이 있습니다.</p>
<h3 id="디자인-패턴이란">디자인 패턴이란?</h3>
<blockquote>
<p>sw개발 방법을 공식화 한 것</p>
</blockquote>
<p>네 바로 mvc 패턴입니다.
한마디로 model, view, controller로 각 역할을 분리하여서 유지보수와 개발효율을 증진시킨다는 개념입니다.</p>
<p>이번 기회를 통해 mvc패턴만 아닌 그에따라 파생되어서 나온 mvp, mvvm 더 나아가 flux 까지 알아보도록 하겠습니다.</p>
<h2 id="1-mvc-패턴">1. MVC 패턴</h2>
<p>Model, View, Controller의 앞글자만을 따서 만들어진 단어가 바로 mvc패턴 입니다.
모델은 데이터들을 관리하고, 뷰는 화면을 그려주고, 컨트롤러가 뷰와 모델의 중개자 역할을 맡고 있습니다. 또한 사용자의 입력(input)은 컨트롤러를 통해 처리됩니다.</p>
<p>이렇게 각 하는 역할이 정해져 있기 때문에 각 역할에 맞는 코드를 짜도록 주의 하셔야 합니다.</p>
<p><img src="https://images.velog.io/images/pica_pica/post/f7a31c5a-b614-4c72-92fe-9f92be8c35d7/image.png" alt=""></p>
<ul>
<li>Model : 데이터(데이터 베이스), 어플리케이션에서 사용되는 데이터와 그를 처리하는 부분</li>
<li>View : 모델에 포함된 데이터의 시각화(화면), 모델을 이용하여 화면을 나타냄</li>
<li>Controller : 사용자의 입력(input)을 받아 처리하는 부분</li>
</ul>
<p>장점</p>
<ol>
<li>동시다발적 개발이 가능(프론트엔드와 백엔드)</li>
<li>높은 응집도</li>
<li>개발용이성 (책임이 구분되어 있어 코드 수정이 용이)</li>
</ol>
<p>단점</p>
<ol>
<li>컨트롤러가 다수의 뷰를 선택할 수 있어서 하는일이 너무 많아질 수 있다.</li>
<li>코드 일관성 유지에 노력이 필요함.</li>
<li>뷰와 모델 사이의 의존성이 높다. (높은 의존성은 규모가 커질수록 유지보수가 어려움)</li>
</ol>
<h2 id="2-mvp-패턴">2. MVP 패턴</h2>
<p>Model, View, Presenter로 구성되어 있으며 사용자의 입력은 View를 통해서 입력하게 됩니다.
input이 들어오게 되면 View는 Presenter에 알려줍니다. 그러면 Presenter는 로직을 처리합니다.
한마디로 화면과 로직을 분리하자는 개념입니다.</p>
<p><img src="https://images.velog.io/images/pica_pica/post/45fef06a-83c5-4369-a767-0534e76c7c9e/image.png" alt=""></p>
<ul>
<li>Model : 데이터를 저장하고, 처리하는 역할을 함(비즈니스 로직).</li>
<li>View : 화면을 담당함, Presenter를 이용해 데이터를 주고받기 때문에 매우 의존적임.</li>
<li>Presenter : model과 view사이의 중개자역할, 컨트롤러와 유사하지만 view에 직접 연결되어 1:1로 매칭되는점이 다르다.</li>
</ul>
<p><strong>장점</strong></p>
<ol>
<li>model과 view간의 결합도를 낮추면 새로 추가 및 수정에 대해 해당 부분만 코드 수정하면 되기 때문에 확장성이 좋아지고, 유닛테스트시 테스트코드를 작성하기 편리해진다.</li>
<li>UI, Data각각 파트가 나눠지기 때문에 동시에 쉽고 빠르게 코딩이 가능.</li>
</ol>
<p><strong>단점</strong></p>
<ol>
<li>애플리케이션이 복잡해질수록 view와 presenter사이의 의존성이 강해지는 단점이 존재.</li>
<li>mvc의 controller처럼 presenter도 어느정도 시간이 지나면 비즈니스 로직이 집중되는 경향이 있음.</li>
<li>MVC 패턴의 단점인 View와 Model 사이의 의존성은 해결되었지만,
View와 Presenter가 1:1 로 매칭되기때문에 뷰가 많아짐에 따라서 Presenter도 따라서 같이 생성되게 됨.</li>
</ol>
<h2 id="3-mvvm-패턴">3. MVVM 패턴</h2>
<p>Model, View, ViewModel로 구성되어 있으며 Model과 View는 다른 패턴과 동일합니다.
웹 기술이 점점 진화하면서 우리가 사용하고 있는 하나의 서비스는 엄청나게 크고 복잡한 형태로 되어있습니다. 그렇기 때문에 MVC패턴에는 한계가 있을 수 밖에 없습니다.
즉 모든 데이터를 서버에서 처리하는 것은 매우 많은 서버 비용과 부담이 컸기 때문입니다.
그래서 이를 보완하기 위해 웹 화면상에 데이터를 처리하고 이를 바로 실시간으로 동적으로 화면의 뷰를 변화시킬 수 있도록 하기 위해 탄생한게 바로 MVVM패턴이라고 할 수 있습니다.</p>
<ul>
<li>Model : 도메인 특화 데이터를 처리</li>
<li>View : 유저 인터페이스(UI), HTML/CSS/XML 등으로 작성</li>
<li>ViewModel : 상태와 연산 View의 실제 논리 및 데이터 흐름을 담당, 상태 데이터를 변경하면 즉시 View에 반영된다. (데이터 요소를 바꿀거야! 그리는건 신경 쓰지 않는다.)</li>
</ul>
<p><img src="https://images.velog.io/images/pica_pica/post/9122001e-880b-4345-a947-43251f19e030/image.png" alt=""></p>
<p><strong>장점</strong></p>
<ol>
<li>MVVM 패턴은 View와 Model 사이의 의존성이 없습니다.(MVP와 같음)</li>
<li>Command패턴과 Data Binding을 사용하여 View와 ViewModel 사이의 의존성 또한 없앤 디자인 패턴</li>
</ol>
<p><strong>단점</strong></p>
<ol>
<li>ViewModel의 설계가 쉽지 않다!</li>
</ol>
<h2 id="4-flux-패턴">4. Flux 패턴</h2>
<p>Flux는 MVC모델의 단점을 보안하기 위해 페이스북에서 발표한 아키텍쳐입니다.</p>
<h3 id="1-mvc의-문제점">1. MVC의 문제점</h3>
<ul>
<li>페이스북에서 말하는 MVC의 가장 큰 단점은 바로 양방향 데이터 흐름이라는 것 입니다.</li>
<li>MVC에선 Controller가 Model을 조회하거나 업데이트를 하고, Model이 업데이트 되면 View는 화면에 반영합니다. 또한 View도 Model을 업데이트 할 수가 있어서 Model이 업데이트 되면 다시 업데이트 된 View가 또 다른 Model을 업데이트 하게 됩니다.
이런건 복잡하지 않은 애플리케이션에선 문제가 되지 않을 수 있습니다. 하지만 복잡해진다면 이런 양방향 데이터 흐름은 기능이 추가 될 때마다 더욱더 구조가 어렵게 되어서 개발자도 관리하기가 무척 힘들어 집니다.</li>
</ul>
<p><img src="https://images.velog.io/images/pica_pica/post/363dcaea-c4e3-4d67-acce-3bac39eab46f/image.png" alt=""></p>
<p>페이트북에서 말하는 MVC의 양방향 데이터 흐름으로 인해 예측하기 어려운 버그 중 하나인 알림 버그입니다.
이러한 버그는 로그인 했을 때 알림이 떠 있지만 막상 들어가 보면 아무 알림도 없는 경우가 있습니다. 이 버그를 수정하고 얼마동안은 괜찮지만 나중에 또 업데이트 하고 보면 이러한 버그가 또 발생되는 것을 확인 할 수 있었습니다.</p>
<h3 id="2-flux로-해결">2. Flux로 해결</h3>
<p>그래서 이러한 현상을 해결하고자 Flux패턴이라는 단방향 흐름 패턴을 생각해낸 것입니다.
<img src="https://images.velog.io/images/pica_pica/post/126e620e-7be4-49e4-922b-d1c73c7d7157/image.png" alt=""></p>
<p>Flux의 가장 큰 장점은 단방향 데이터 흐름입니다.
데이터 흐름은 항상 Dispatcher에서 Store로 Store에서 View로 View에서 다시 Action을 통해 Dispatcher 이렇게 흘러가게 됩니다.
이렇게 흘러가게 되면 나중에 디버깅을 할 때에도 어디서 오류가 났는지 어느지점에서 멈췄는지 바로바로 찾아서 해결할 수 있으며, 구조의 흐름도 쉽게 파악 할 수 있습니다.</p>
<ul>
<li><p>Dispatcher 
Flux의 모든 데이터 흐름을 관리하는 허브 역할을 담당합니다.
Action이 발생되면 Dispatcher는 전달된 Action을 확인하고 등록된 콜백함수를 실행하여 Store로 전달하게 됩니다. (Dispatcher는 전체 어플리케이션에서 한 개의 인스턴스만 사용됩니다.)</p>
</li>
<li><p>Store
어플리케이션의 모든 상태변경은 Store에서 결정이 됩니다. Dispatcher로부터 수신받기 위해서는 Dispatcher에 콜백 함수를 등록해야 합니다. Store가 변경되면 View에 변경되었다는 사실을 알려주게 됩니다.</p>
</li>
<li><p>View
View는 화면에 나타내는 것 뿐만 아니라, 자식 View로 데이터를 흘러 보내는 View 컨트롤러의 역할도 합니다.</p>
</li>
<li><p>Action
Dispatcher에서 콜백 함수가 실행 되면 Store가 업데이트 되게 되는데, 이 콜백 함수를 실행 할 때 데이터가 담겨 있는 객체가 인수로 전달 되어야 합니다. 이 전달 되는 객체를 Action이라고 하는데, Action은 대채로 액션 생성자(Action creator)에서 만들어집니다.</p>
</li>
</ul>
<h2 id="후기">후기</h2>
<p>MVC부터 시작해서 다양한 디자인 패턴들이 있다는 것을 알게 되었고, 실제 개발할 때에는 복잡도로 인해서 고생한 경험이 없다보니 잘 몰랐던 개념들이 많았습니다. 이번 기회를 통해 개발할 애플리케이션의 규모와 특성을 고려하여 알맞는 디자인 패턴을 사용해야겠다는 생각이 들었습니다.</p>
<p><em>참고</em></p>
<blockquote>
<p><a href="https://blog.coderifleman.com/2015/06/19/mvc-does-not-scale-use-flux-instead/">https://blog.coderifleman.com/2015/06/19/mvc-does-not-scale-use-flux-instead/</a>
<a href="https://haruair.github.io/flux/docs/overview.html">https://haruair.github.io/flux/docs/overview.html</a>
<a href="https://bestalign.github.io/2015/10/06/cartoon-guide-to-flux/">https://bestalign.github.io/2015/10/06/cartoon-guide-to-flux/</a>
<a href="https://beomy.tistory.com/44?category=676748">https://beomy.tistory.com/44?category=676748</a>
<a href="https://beomy.tistory.com/43?category=676748">https://beomy.tistory.com/43?category=676748</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 다음 큰 숫자]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%EC%9D%8C-%ED%81%B0-%EC%88%AB%EC%9E%90</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%8B%A4%EC%9D%8C-%ED%81%B0-%EC%88%AB%EC%9E%90</guid>
            <pubDate>Thu, 27 May 2021 15:52:42 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/06258f9c-04d3-45b8-ac13-12d339df6a4e/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>주어진 숫자를 2진수로 변환하여 filter함수로 1인것을 추출하여 길이를 구한다.</li>
<li>while문을 이용하여 count변수와 함께 다음 숫자를 하나씩 찾으며 1의 갯수가 같으면 while문 종료 answer에 그 숫자를 리턴해준다.</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(n) {
  //주어진 숫자의 1의 갯수가 담긴 변수
  const currentNumLength = n.toString(2).split(&quot;&quot;).filter(item =&gt; parseInt(item) === 1).length;

  let answer = n;
  let count = 1;

  while(true) {
      //count만큼 더해진 숫자의 1의 갯수가 담긴 변수
      const nextNumLength = (n + count).toString(2).split(&quot;&quot;).filter(item =&gt; parseInt(item) === 1).length;

      if(currentNumLength === nextNumLength) {
          answer = (n+count);
          break;
      } else {
          count++;
      }
  }

  return answer;
}</code></pre><p>다른사람들의 풀이를 보니 정규표현식을 이용한분들도 많고
신기하게 shift를 이용한 풀이법도 있어서 각 풀이법도 적용시켜서 해 보았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 - 깊은복사, 얕은복사]]></title>
            <link>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B9%8A%EC%9D%80%EB%B3%B5%EC%82%AC-%EC%96%95%EC%9D%80%EB%B3%B5%EC%82%AC</link>
            <guid>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B9%8A%EC%9D%80%EB%B3%B5%EC%82%AC-%EC%96%95%EC%9D%80%EB%B3%B5%EC%82%AC</guid>
            <pubDate>Sun, 23 May 2021 14:01:41 GMT</pubDate>
            <description><![CDATA[<p>소개하기 전 처음에 객체 안에 객체를 띤 형태의 obj변수를 만든다.
앞으로 소개할 복사는 이 객체를 통해 예시를 들어보겠습니다.</p>
<pre><code>const obj = {
  apple: 1,
  banana: {
    yellow: &quot;ok&quot;
  },
}</code></pre><h2 id="얕은복사">얕은복사</h2>
<p>객체를 복사할 때 원래값과 복사된 값이 같은 참조를 가리키고 있는것을 말한다.
객체 안에 객체가 있는경우(depth가 1보다 큰 상황)에는 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은복사라고 말한다.</p>
<h3 id="1-스프레드전개-연산자-문법">1. 스프레드(전개 연산자) 문법</h3>
<pre><code>const newObj = { ...obj }

obj.banana.yellow = &quot;no&quot;;

obj === newObj // false
obj.banana.yellow === newObj.banana.yellow // true</code></pre><p> 객체안에 객체는 같은 참조를 가리킨다는것을 알 수 있다.</p>
<h3 id="2-objectassign">2. Object.assign()</h3>
<pre><code>const newObj = Object.assing({}, obj};

obj.banana.yellow = &quot;no&quot;;

obj === newObj // false
obj.banana.yellow === newObj.banana.yellow // true</code></pre><p> 위와 마찬가지로 같은 참조를 가리킨다는것을 알 수 있다.</p>
<h2 id="깊은복사">깊은복사</h2>
<p>객체나 배열을 복사할 때 원래값과 복사된 값이 다른 참조를 가리키고 있는것을 말한다.
한마디로 원본과의 참조가 완전히 절단된 복사 객체를 의미한다.</p>
<h3 id="1-jsonstringify--jsonparse">1. JSON.stringify() + JSON.parse()</h3>
<p>JSON.stringify()는 객체를 json문자열로 변환하는것으로 이 과정에서 원본 객체와의 참조가 모두 끊어진다. 이렇게 문자열로 변환 후 JSON parse()를 이용해 다시 객체를 만들어주게 되면 깊은 복사가 이루어 진다.</p>
<pre><code>const newObj = JSON.parse(JSON.stringifay(obj));

obj.banana.yellow = &quot;no&quot;;

obj === newObj // false
obj.banana.yellow === newObj.banana.yellow // false</code></pre><h3 id="2-lodash-라이브러리-사용">2. lodash 라이브러리 사용</h3>
<pre><code> const deepcopy = require(&quot;lodash.clonedeep&quot;);


const newObj = deepcopy(obj);

obj.banana.yellow = &quot;no&quot;;

obj === newObj // false
obj.banana.yellow === newObj.banana.yellow // false</code></pre><h3 id="3-재귀를-통한-직접-복사">3. 재귀를 통한 직접 복사</h3>
<pre><code>function copyDeep(obj) {
  const result = {};

  for(let key in obj) {
    if(typeof obj[key] === &#39;object&#39;) {
      result[key] = copyDeep(obj[key]);
    } else {
      result[key] = obj[key];
    }
  }

  return result;
}

const newObj = copyDeep(obj);

obj.banana.yellow = &quot;no&quot;;

obj === newObj // false
obj.banana.yellow === newObj.banana.yellow // false</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - N개의 최소공배수]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-N%EA%B0%9C%EC%9D%98-%EC%B5%9C%EC%86%8C%EA%B3%B5%EB%B0%B0%EC%88%98</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-N%EA%B0%9C%EC%9D%98-%EC%B5%9C%EC%86%8C%EA%B3%B5%EB%B0%B0%EC%88%98</guid>
            <pubDate>Fri, 21 May 2021 11:55:44 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/c455fb6e-cfd2-437f-95af-1591f3cfdf85/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>최대공약수를 구하는 함수와 최소공배수를 구하는 함수를 선언한다.</li>
<li>for문을 통해서 주어진 배열의 길이만큼 순회하면서 최소공배수를 구한다.</li>
<li>for문을 순회하면서 구해진 answer의 최소공배수를 return 해준다.</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(arr) {
  //정렬이 안되있을 경우를 대비하여 오름차순으로 정렬해준다.
  arr.sort((a,b) =&gt; a - b);
  //최소공배수를 담을 변수
  let answer = 0;
  answer = lcm(arr[0], arr[1]);
  //주어진 배열의 길이가 1일때는 그대로 그 배열의 원소를 리턴
  if(arr.length === 1) return arr[0];
  //주어진 배열의 길이가 2일때는 처음에 구해진 answer로 리턴
  if(arr.length === 2) return answer;

  for(let i = 2; i &lt; arr.length; i ++) {
    answer = lcm(answer, arr[i]);
  }  

  return answer
}

//최대 공약수
function gcd(num1, num2) {
  return (num1 % num2) === 0 ? num2 : gcd(num2, num1 % num2);
}

/최소 공배수
function lcm(num1, num2) {
  return num1 * num2 / gcd(num1, num2);
} 
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 3차 파일명 정렬]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-3%EC%B0%A8-%ED%8C%8C%EC%9D%BC%EB%AA%85-%EC%A0%95%EB%A0%AC</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-3%EC%B0%A8-%ED%8C%8C%EC%9D%BC%EB%AA%85-%EC%A0%95%EB%A0%AC</guid>
            <pubDate>Wed, 19 May 2021 17:17:28 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/2604e7dd-2a20-4941-a9af-d26b21ee6c2c/image.png" alt="">
<img src="https://images.velog.io/images/pica_pica/post/bd56cae3-d134-459b-a404-19d2cbc07dbb/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>정규표현식을 통해서 /(\d+)/g;를 써서 숫자를 기준으로 잘라낸다.</li>
<li>잘라낸것을 tail을 구분하기 위한 index와 잘린 배열들을 가진 객체로 answer배열에 push한다.</li>
<li>이 추출된 배열을 sort를 통해 첫번째 head는 주어진 단어를 소문자로 바꾸어 비교하고, 두번째 숫자는 parseInt로 숫자로 변환하여 비교하고, 마지막으로 tail은 아까 넣어준 index번호를 통해 비교를 해서 정렬시킨다.</li>
<li>정렬된것을 배열만 추출하여 join해서 return</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(files) {
  const answer = [];
  const reg = /(\d+)/g; 
  for (let i = 0; i &lt; files.length; i++) {
    answer.push({ index: i, value: files[i].split(reg) }); 
  }

  answer.sort((a,b) =&gt; {
    if((a.value[0].toLowerCase() &lt; b.value[0].toLowerCase())) {
      return -1;
    } else if ((a.value[0].toLowerCase() &gt; b.value[0].toLowerCase())) {
      return 1;
    } else {
      if(parseInt(a.value[1]) &lt; parseInt(b.value[1])) {
        return -1
      } else if(parseInt(a.value[1]) &gt; parseInt(b.value[1])) {
        return 1;
      } else {
       if(a.index &lt; b.index) return -1;
       else return 1;
      }
    }

  })

  return answer.map(item =&gt; item.value.join(&quot;&quot;))
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 올바른 괄호]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%AC%EB%B0%94%EB%A5%B8-%EA%B4%84%ED%98%B8</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%AC%EB%B0%94%EB%A5%B8-%EA%B4%84%ED%98%B8</guid>
            <pubDate>Tue, 18 May 2021 15:31:03 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/c73df988-6059-4059-a3fa-63e5bd46d366/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>주어진 문자열을 split을통해 쪼갠다.</li>
<li>for문을 활용해 ( 열린괄호를 만나게되면 count를 증가 그리고 count가 1이상이면서
닫힌괄호를 만나면 카운트 감소</li>
<li>이렇게 for문을 다 거치고나면 count 가 0이면 짝이 다 맞는상태 아니면 짝이 안맞는상태로 판단</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(s) {
  const newArr = s.split(&quot;&quot;);
  let count = 0;

  if(newArr[0] === &#39;)&#39;) return false;

  for(let i = 0; i &lt; newArr.length; i++){
    if(newArr[i]===&#39;(&#39;) {
      count ++;
    } else if(count &gt;= 1 &amp;&amp; newArr[i] === &#39;)&#39;){
      count --; 
    }
  }

  return count === 0 ? true : false;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 - 이벤트 버블링과 이벤트 캡쳐]]></title>
            <link>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%BA%A1%EC%B3%90</link>
            <guid>https://velog.io/@pica_pica/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%BA%A1%EC%B3%90</guid>
            <pubDate>Sun, 16 May 2021 16:47:14 GMT</pubDate>
            <description><![CDATA[<h3 id="이벤트-등록">이벤트 등록</h3>
<p>이벤트 버블링을 알아보기에 앞서서 이벤트 등록을 어떻게 하는지부터 알아야 한다.
여기서 이벤트 등록이란 <strong>웹 애플리케이션에서 사용자의 입력을 받기위해 필요한 기능</strong>이라고 한다.
아래의 코드를 보시면</p>
<pre><code>
&lt;button class=&quot;button&quot;&gt;확인&lt;button&gt;

...


&lt;script&gt;
const button = document.querySelector(&#39;.button&#39;);
button.addEventListener(&#39;click&#39;, sayOk);

function sayOk() {
  console.log(&quot;ok&quot;);
}
&lt;/script&gt;</code></pre><p>button 클래스의 이름을 가진 dom요소를 지정하여 click이벤트를 달아 놓았고 이를 클릭해보면
콘솔창에 ok라는게 찍히는게 확인 됩니다.</p>
<p>이처럼 addEventListener() 웹 api는 웹 개발자들이 화면에 동적인 기능을 추가하기 위해 자연스럽게 사용하게 되는 기본적인 기능입니다. 여기서 브라우저는 어떻게 이벤트의 발생을 감지했을까요?
정답은 바로 브라우저가 앞으로 설명할 2가지 방식을 통해 감지를 하게 됩니다.</p>
<p>이제 본격적으로 이벤트 버블링과 캡쳐를 알아갈 수 있는 단계가 되었습니다!
더 알아보도록 합시다.</p>
<h2 id="1-이벤트-버블링이란">1. 이벤트 버블링이란?</h2>
<p>DOM 요소에서 이벤트가 발생했을 때, 거기에 등록된 이벤트 리스너 함수가 있으면 실행을 시도한다. 그리고 이벤트는 부모 요소를 통해 DOM 트리 위쪽으로 전파(bubbled up)되며 거쳐가는 DOM 요소마다 같은 일(이벤트 리스너 확인 및 실행)이 반복된다. 이 버블링은 최상위 요소인 document까지 진행된다. 이벤트 버블링은 이벤트 위임(delegation) 메카니즘 안에 있다.</p>
<p>한줄 요약 : <strong>DOM 이벤트가 상위 요소(element)로 전파되는 현상</strong></p>
<p><img src="https://images.velog.io/images/pica_pica/post/8b9a3f56-136f-4e9e-b189-460c18566905/image.png" alt=""></p>
<p>코드로 알아보면</p>
<pre><code>&lt;body&gt;
  &lt;div class=&quot;one&quot;&gt;
    &lt;div class=&quot;two&quot;&gt;
      &lt;div class=&quot;three&quot;&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/body&gt;</code></pre><pre><code>const divBlocks = document.querySelectorAll(&#39;div&#39;);
divBlocks.forEach(()=&gt; {
  div.addEventListener(&#39;click&#39;, showClassName);
})

function showClassName(e) {
  console.log(e.currentTarget.className);
}
</code></pre><p>위 코드는 세 개의 div 태그에 모두 클릭 이벤트를 등록하고 클릭 했을 때 logEvent 함수를 실행시키는 코드입니다. 여기서 위 코드에서 최하위 div 태그 </p>
<pre><code>&lt;div class=&quot;three&quot;&gt;&lt;/div&gt;</code></pre><p>를 클릭하면 아래와 같은 결과가 실행됩니다.</p>
<p><img src="https://images.velog.io/images/pica_pica/post/ab2fdfe9-5977-4466-a436-72f5f719e766/image.png" alt=""></p>
<p>왜 하나만 클릭했는데 세개가 찍힐까요?</p>
<p>그 이유는 브라우저가 이벤트를 감지하는 방식 때문입니다.
브라우저는 특정 화면 요서에서 이벤트를 발생했을 때 그 이벤트를 최상위에 있는 화면 요소까지 이벤트를 전파시킵니다. 따라서, three -&gt; two -&gt; one 순서대로 div태그에 등록된 이벤트들이 실행됩니다.
마찬가지로 two를 클릭하면 two -&gt; one 이렇게 실행됩니다.</p>
<p>이렇게 하위에서 상위 요소로 이벤트 전파 방식을 <strong>이벤트 버블링(Event Bubbling)</strong>이라고 합니다.</p>
<h2 id="2-이벤트-캡쳐란">2. 이벤트 캡쳐란?</h2>
<p>이벤트 캡쳐는 이벤트 버블링 설명과 동일하지만, 정 반대의 방향으로 작동하는 방식입니다.</p>
<p>한줄 요약 :  <strong>DOM 이벤트가 하위 요소(element)로 전파되는 현상</strong></p>
<p><img src="https://images.velog.io/images/pica_pica/post/99bb19d3-ecf5-493d-a64b-00bdcd02a68a/image.png" alt=""></p>
<p>코드로 알아보면</p>
<pre><code>&lt;body&gt;
  &lt;div class=&quot;one&quot;&gt;
    &lt;div class=&quot;two&quot;&gt;
      &lt;div class=&quot;three&quot;&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/body&gt;</code></pre><pre><code>const divBlocks = document.querySelectorAll(&#39;div&#39;);
divBlocks.forEach(()=&gt; {
  div.addEventListener(&#39;click&#39;, showClassName, {
    capture: true //default 값은 false
  });
})

function showClassName(e) {
  console.log(e.currentTarget.className);
}
</code></pre><p>addEventListener() api에서 옵션 객체에 capture: true로 설정해 주시면 됩니다.
이렇게 하면 아래와 같이 이벤트 버블링과는 반대의 방향으로 전파되게 됩니다.</p>
<p><img src="https://images.velog.io/images/pica_pica/post/a738a38c-3d2b-41a7-87ca-bcf380d74c95/image.png" alt=""></p>
<h2 id="3-eventstoppropagation">3. event.stopPropagation()</h2>
<p>나는 클릭한것만 나오게 하고싶은데 버블링도싫고 캡쳐도 싫어 하시는 분들을 위한 이벤트 요소입니다.</p>
<pre><code>function showClassName(e) {
  e.stopPropagation();
  console.log(e.currentTarget.className);
}</code></pre><p>이렇게 사용하게 되면 전파현상을 막으면서 본인의 것만 출력하게 할 수 있다.</p>
<blockquote>
<p>참고 사이트
<a href="https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/">https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 3차 압축]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-3%EC%B0%A8-%EC%95%95%EC%B6%95</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-3%EC%B0%A8-%EC%95%95%EC%B6%95</guid>
            <pubDate>Sun, 16 May 2021 15:21:52 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/7ecb22a0-9ab1-42f5-9c25-2285dabea336/image.png" alt="">
<img src="https://images.velog.io/images/pica_pica/post/736f81ae-6165-460d-b792-24ad494340c5/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>각 단어의 색인 번호가 저장된 배열과 주어진 단어를 쪼갠 split배열을 만든다.</li>
<li>각 split된 글자를 순회하면서 그 단어가 색인 배열에 있으면 tempStr에 단어를 붙이며 계속 이어나간 다음 없을때까지 반복한다.</li>
<li>이렇게 나온 tempStr에는 색인배열에 없는 단어이므로 추가시킨다음 그 인덱스번호를 answer배열에 넣고 다음 단어를 진행시킨다.</li>
<li>이렇게 다 순회하고 나면 결과적으로 색인번호로만 주어진 answer배열이 완성된다.</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(msg) {
  const strArr = msg.split(&quot;&quot;);
  //색인배열 1부터 시작이라서 0번째는 아무 문자나 집어넣었다.
  const indexArr = [
    &#39;@&#39;,&#39;A&#39;,&#39;B&#39;,&#39;C&#39;,&#39;D&#39;,&#39;E&#39;,&#39;F&#39;,&#39;G&#39;,
    &#39;H&#39;,&#39;I&#39;,&#39;J&#39;,&#39;K&#39;,&#39;L&#39;,&#39;M&#39;,&#39;N&#39;,
    &#39;O&#39;,&#39;P&#39;,&#39;Q&#39;,&#39;R&#39;,&#39;S&#39;,&#39;T&#39;,&#39;U&#39;,
    &#39;V&#39;,&#39;W&#39;,&#39;X&#39;,&#39;Y&#39;,&#39;Z&#39;
  ]
  const answer = [];

  //카운팅을 해줄 변수
  let index = 0;
  //색인배열에 들어갈 문자열
  let tempStr = &quot;&quot;;
  //for문이 별탈없이 끝까지 진행되었는가 -&gt; 끝부분단어를 색출하는 변수
  let isEnd = true;

  while(index &lt; strArr.length) {
    for(let i = index; i &lt; strArr.length ; i ++) {   
      tempStr += strArr[i];
      if(!indexArr.includes(tempStr)) {
        isEnd = false;
        break;
      }
    }

    //끝부분이 색출되면 그 단어를 그대로 push하고 while문을 종료
    if(isEnd) {
      answer.push(indexArr.indexOf(tempStr));
      break;
    }

    //기존에 주어진 색인에 있는 단어
    if(tempStr.length === 2) {
      answer.push(indexArr.indexOf(tempStr[0]));
      index++;
      indexArr.push(tempStr);

    //기존에서 추가된 색인에 있는 단어
    } else {
      answer.push(indexArr.indexOf(tempStr.slice(0, tempStr.length - 1)));
      index = parseInt(index) + parseInt(tempStr.length - 1);
      indexArr.push(tempStr);
    }

    tempStr = &quot;&quot;;
    isEnd = true;
  }

  return answer;
}</code></pre><p>풀면서 막혔던 부분은
끝부분에 색출될때 예외처리를 해주는 생각이 바로 떠오르지 않아 잠시 고민했지만 변수를 추가하여서 그 여부를 판단하여 처리하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 영어 끝말잇기]]></title>
            <link>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0</link>
            <guid>https://velog.io/@pica_pica/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0</guid>
            <pubDate>Sat, 15 May 2021 18:08:03 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<p><img src="https://images.velog.io/images/pica_pica/post/27b0611e-ec30-4f88-877a-9e7217cca1f8/image.png" alt="">
<img src="https://images.velog.io/images/pica_pica/post/f4e45607-7c10-4dc3-8ad3-3446e5af9bf2/image.png" alt=""></p>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li><p>현재 단어의 끝문자와 다음 단어의 첫문자를 비교, 다음단어가 이전에 나왔는지
탈락자가 생기지 않을때 이 세가지 처리를 해주어야한다.</p>
</li>
<li><p>위의 처리를 해주기 위해 count(몇번째 사람인지) whatTimes(몇번 반복되었는지)
tempArr(각 사람의 현재 외친 단어) stackArr(사람들이 여태까지 외친 단어들)
이렇게 변수를 지정해서 나타내주고 boom 변수는 탈락자가 생기지 않는 상황을 위해 true false로 지정해 주었다.</p>
</li>
<li><p>for문을 words길이만큼 돌면서 현재단어와 다음 올 단어를 각각 비교해서 count와 whatTimes를 적절하게 증가시켜주면 된다.</p>
</li>
</ol>
<h3 id="코드">코드</h3>
<pre><code>function solution(n, words) {
  const tempArr = [];
  const stackArr = [];
  let count = 0;
  let whatTimes = 1; //시작할때부터 1번으로 치기때문에 1로 선언
  let boom = false;

  //맨처음은 비교할게 없으니 그냥 넣어주고 count 증가
  tempArr[0] = words[0];
  stackArr[0] = words[0];
  count++;

  for(let i = 0; i &lt; words.length -1; i ++) {
    if(count === n) {
      count = 0;
      whatTimes++;
    }

    if(words[i][words[i].length -1] === words[i+1][0]) {
      if(stackArr.includes(words[i+1])) {
        count++;
        boom = true;
        break;
      }

      stackArr.push(words[i+1]);
      tempArr[count] = words[i+1];
      count++;
    } else {
      count++;
      boom = true;
      break;
    }
  }

  // 만약 별 탈없이 끝났을때 예외처리
  if(!boom) {
    count = 0;
    whatTimes = 0;
  }

  return [count, whatTimes];
}</code></pre>]]></description>
        </item>
    </channel>
</rss>