<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Choi-HyunHo</title>
        <link>https://velog.io/</link>
        <description>현재 블로그 : https://choi-hyunho.com/</description>
        <lastBuildDate>Wed, 15 Mar 2023 16:14:31 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Choi-HyunHo</title>
            <url>https://velog.velcdn.com/images/hoho_0815/profile/95c9d2b4-f476-4ee6-a2d7-da4005d919a2/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Choi-HyunHo. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hoho_0815" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Tech Blog ➡️ https://choi-hyunho.com/]]></title>
            <link>https://velog.io/@hoho_0815/Tech-Blog</link>
            <guid>https://velog.io/@hoho_0815/Tech-Blog</guid>
            <pubDate>Wed, 15 Mar 2023 16:14:31 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요 Choi Hyun Ho 의 기술 블로그 입니다 
현재는 <a href="https://choi-hyunho.com/">https://choi-hyunho.com/</a> 기록을 하고 있습니다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_스코프]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Tue, 30 Aug 2022 09:01:47 GMT</pubDate>
            <description><![CDATA[<h1 id="13-스코프">13 스코프</h1>
<p><strong>스코프(scpoe : 유효범위)</strong> 는 자바스크립트를 포함한 모든 프로그래밍 언어의 기본이며 중요하다.
특히, 자바스크립트의 스코프는 다른 언어의 스코프와 구별되는 특징이 있다.</p>
<hr>
<h2 id="131-스코프란">13.1 스코프란?</h2>
<blockquote>
<p>모든 식별자(변수이름, 함수이름, 클래스 이름 등)는 <strong>자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정</strong>된다.</p>
</blockquote>
<p>즉, <strong>식별자가 유효한 범위</strong></p>
<blockquote>
<p><strong>코드의 문맥과 환경</strong>
<strong>&quot;코드가 어디서 실행되며 주변에 어떤 코드가 있는지&quot;</strong> 를 <strong>렉시컬 환경</strong> 이라고 부른다.
코드의 문맥은 렉시컬 환경으로 이루어지고, 이를 구현한 것이 <strong>실행 컨텍스트</strong> 이며, 모든 코드는
<strong>실행 컨텍스트에서 평가되고 실행</strong>된다.</p>
</blockquote>
<hr>
<h2 id="132-스코프의-종류">13.2 스코프의 종류</h2>
<p>코드는 <strong>전역(global)</strong> 과 <strong>지역(local)</strong> 로 구분 할 수 있다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
<th>스코프</th>
<th>변수</th>
</tr>
</thead>
<tbody><tr>
<td>전역</td>
<td>코드의 가장 바깥 영역</td>
<td>전역 스코프</td>
<td>전역변수, <strong>어디서든지 참조</strong> 할 수 있다.</td>
</tr>
<tr>
<td>지역</td>
<td>함수 몸체 내부</td>
<td>지역 스코프</td>
<td>지역변수, <strong>자신의 지역 스코프</strong>와 <strong>하위 스코프</strong>에서 유효하다.</td>
</tr>
</tbody></table>
<hr>
<h2 id="133-스코프-체인">13.3 스코프 체인</h2>
<p>스코프는 함수의 중첩에 의해 계층적인 구조를 갖는다. 
이렇게 스코프가 계층적으로 연결된 것을 <strong>스코프 체인</strong> 이라고 한다.</p>
<p>변수를 참조할 때 자바스크립트 엔진은</p>
<ul>
<li>스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여</li>
<li><strong>상위 스코프 방향으로 이동하며 선언된 변수를 검색</strong> 한다.</li>
<li><blockquote>
<p>절대 하위 스코프로 내려가면서 식별자를 검색하는 일은 없다.</p>
</blockquote>
</li>
<li>이를 통해 사위 스코프에서 선언한 변수를 하위 스코프에서도 참조할 수 있다.</li>
</ul>
<hr>
<h2 id="134-함수-레벨-스코프">13.4 함수 레벨 스코프</h2>
<ul>
<li>함수 몸체 내부를 말하고 <strong>지역 스코프</strong> 를 만드는데, 이는 <ul>
<li><strong>코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성</strong> 된다는 의미이다.</li>
</ul>
</li>
<li>C, Java 등을 비롯한 대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 코드 블록
(if, for, while, try/catch 등) 이 지역 스코프를 만드는데<ul>
<li>이러한 특성을 <strong>블록 레벨 스코프</strong>라 한다.</li>
</ul>
</li>
<li>하지만 <code>var</code> 키워드로 선언된 변수는 오로지 함수의 코드 블록 만을 지역 스코프로 인정<ul>
<li>이러한 특성을 <strong>함수 레벨 스코프</strong> 라고 한다.</li>
</ul>
</li>
</ul>
<pre><code class="language-js">var x = 1;

if (true) {
  // var 키워드로 선언된 변수는 함수의 코드 블록만을 지역 스코프로 인정한다.
  // 함수 밖에서 var 키워드로 선언된 변수는 코드 블록 내에서 선언되었다 할지라고 모두 전역 변수다.
  // 따라서 x 는 전역 변수다. 이미 선언된 전역 변수 x 가 있으므로 x 변수는 중복 선언된다.
  // 이는 의도치 않게 변수 값이 변경되는 부작용을 발생시킨다.
  var x = 10;
}

console.log(x); // 10</code></pre>
<pre><code class="language-js">var i = 10;

// for 문에서 선언한 i는 전역 변수다. 이미 선언된 전역 변수 i 가 있으므로 중복 선언된다.
for ( var i = 0; i &lt; 5; i++ ){
    console.log(i); // 0 1 2 3 4
}

// 의도치 않게 변수의 값이 변경되었다.
console.log(i); // 5</code></pre>
<blockquote>
<p><code>var</code> 키워드로 선언된 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정하지만
<strong>ES6 에서 도입된 <code>let</code>, <code>const</code> 키워드는 블록 레벨 스코프를 지원</strong> 한다.</p>
</blockquote>
<hr>
<h2 id="135-렉시컬-스코프">13.5 렉시컬 스코프</h2>
<p><strong>함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정하는 것</strong></p>
<p>자바스크립트는 렉시컬 스코프를 따르므로,</p>
<ul>
<li>함수를 어디서 호출했는지가 아니라,</li>
<li>함수를 어디서 <strong>정의</strong> 했는지에 따라서 <strong>상위 스코프</strong> 를 결정한다.</li>
<li>함수가 호출된 위치는 상위 스코프 결정에 어떠한 영향도 주지 않는다.</li>
</ul>
<p>이처럼 함수의 상위 스코프는 함수 정의가 실행될 때 정적으로 결정된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_함수]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 22 Aug 2022 14:18:31 GMT</pubDate>
            <description><![CDATA[<h1 id="12_함수">12_함수</h1>
<h2 id="121-함수란">12.1 함수란?</h2>
<p>프로그래밍 언어의 함수는 </p>
<ul>
<li><strong>일련의 과정을 문(statement)으로 구현</strong>하고</li>
<li><strong>코드 블록으러 감싸서 하나의 실행 단위로 정의한 것</strong> 이다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/e670aed5-5052-4936-ad36-6d68c3ca396b/image.png" alt=""></p>
<p>각 용어에 대한 간단한 설명은,</p>
<ul>
<li>함수 내부로 입력을 전달받는 변수를 <strong>매개변수(parameter)</strong></li>
<li>입력을 <strong>인수(argument)</strong></li>
<li>출력을 <strong>반환값(return value)</strong></li>
</ul>
<p>함수는 정의만으로 실행되는 것은 아니므로, 실행을 명시적으로 지시해야 한다.
-&gt; 이를 <strong>함수 호출</strong> 이라 한다.</p>
<hr>
<h2 id="122-함수를-사용하는-이유">12.2 함수를 사용하는 이유</h2>
<ul>
<li>함수는 몇 번이든 호출할 수 있으므로 <strong>코드의 재사용</strong> 이라는 측면에서 매우 유용하다.</li>
<li>코드의 중복을 억제하고 재사용성을 높이는 함수는 <strong>유지보수의 편의성</strong> 을 높이고 <strong>코드의 신뢰성</strong> 을 높인다.</li>
</ul>
<hr>
<h2 id="123-함수-리터럴">12.3 함수 리터럴</h2>
<p>함수 리터럴은,</p>
<ul>
<li>function 키워드</li>
<li>함수 이름</li>
<li>매개 변수 목록</li>
<li>함수 몸체</li>
</ul>
<p>위와 같이 구성된다.</p>
<blockquote>
<p>함수 리터럴은 <strong>평가되는 값을 생성</strong> 하며 함수는 <strong>객체</strong> 이다.</p>
</blockquote>
<pre><code class="language-js">// 변수에 함수 리터럴을 할당
const funcAdd = function add(x, y) {
  return x + y;
}</code></pre>
<hr>
<h2 id="124-함수-정의">12.4 함수 정의</h2>
<p>함수를 호출하기 이전에 <strong>인수를 전달받은 매개변수</strong> 와 <strong>실행할 문</strong>들, 그리고 <strong>반환할 값을 지정</strong> 하는 것을 말한다.</p>
<p>함수를 정의하는 방법은,</p>
<ul>
<li>함수 선언문</li>
<li>함수 표현식</li>
<li>function 생성자 함수</li>
<li>화살표 함수(ES6)</li>
</ul>
<br>

<h3 id="1241-함수-선언문">12.4.1 함수 선언문</h3>
<p>함수 선언문은 함수 리터럴과 형태가 동일하다,
단, 함수 리터럴은 함수 이름은 생략 할 수 있으나, <strong>함수 선언문은 함수 이름을 생략 할 수 없다.</strong></p>
<pre><code class="language-js">function add(x, y) {
  return x+y;
}</code></pre>
<br>

<h3 id="1242-함수-표현식">12.4.2 함수 표현식</h3>
<p>함수는 <strong>일급 객체</strong> 이므로 함수 리터럴로 생성한 함수 객체를 <strong>변수에 할당</strong> 할 수 있는데, 
이러한 함수 정의 방식을 <strong>함수 표현식</strong> 이라 한다.</p>
<blockquote>
<p><strong>일급 객체란?</strong>
자바스크립트의 함수는 값처럼 변수에 할당할 수도 있고, 프로퍼티 값이 될 수도 있으며 배열의 요소가 될 수도 있다. <strong>이처럼 값의 성질을 갖는 객체를 일급 객체라 한다.</strong>
<strong>자바스크립트의 함수는 일급 객체다.</strong></p>
</blockquote>
<br>

<h3 id="1243-함수-생성-시점과-호이스팅">12.4.3 함수 생성 시점과 호이스팅</h3>
<p><span style="color:#0000FF">함수 표현식으로 정의한 함수</span> 와 <span style="color:Red">함수 선언문으로 정의한 함수</span> 의 <strong>생성 시점</strong>이 다르다.</p>
<ul>
<li><p><span style="color:#0000FF">함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있다.</span>    </p>
<ul>
<li>함수 선언문으로 정의하면 런타임 이전에 함수 객체가 먼저 생성되고</li>
<li>자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 생성된     함수 객체를 할당한다.
➔ 즉, 런타임 시점에는 이미 함수 객체가 생성되어 있고, 함수 이름과 동일한 식별자에 할당까지 완료된 상태이다. (= 호이스팅)</li>
</ul>
</li>
<li><p><span style="color:Red">함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출할 수 없다.</span> </p>
<ul>
<li>함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문이다.</li>
<li>따라서 함수 표현식은 변수 선언문과 변수 할당문을 한 번에 기술한 축약 표현과 동일하게 동작한다.</li>
<li>변수 선언은 런타임 이전에 실행되어 undefined로 초기화된다.</li>
<li>함수 표현식 이전에 함수를 참조하면 undefined로 평가되는데, 이때 함수를 호출하면 undefined를 호출하는 것과 마찬가지이므로 타입 에러가 발생하니 주의!!
➔ 함수 표현식으로 정의한 함수는 반드시 함수 표현식 이후에 참조 또는 호출해야 타입 에러가 발생하지 않는다.</li>
</ul>
</li>
</ul>
<br>

<h3 id="1244-function-생성자-함수">12.4.4 Function 생성자 함수</h3>
<p>자바스크립트가 기본 제공하는 빌트인 함수인 <code>Function</code> 생성자 함수에 <strong>매개변수 목록</strong> 과 <strong>함수 몸체</strong> 를 문자열로 전달하면서 <code>new</code> 연산자와 함께 호출하면 함수 객체를 생성해서 반환한다.</p>
<blockquote>
<p><strong>생성자 함수는 객체를 생성하는 함수</strong></p>
</blockquote>
<pre><code class="language-js">var add = new Function(&#39;x&#39;, &#39;y&#39;, &#39;return x + y&#39;);</code></pre>
<blockquote>
<p><strong>주의 !!</strong>
Function 생성자 함수로 함수를 생성하는 방식은 일반적이지 않으며 바람직하지도 않다.
클로저를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작한다</p>
</blockquote>
<br>

<h3 id="1245-화살표-함수">12.4.5 화살표 함수</h3>
<p>ES6에서 도입된 화살표 함수(<strong>arrow function</strong>) 은 function 키워드 대신에 화살표( =&gt; ) 를 사용해서 좀 더 간략한 방법으로 함수를 선언 할 수 있다.</p>
<ul>
<li>화살표 함수는 생성자 함수로 사용할 수 없으며</li>
<li>기존 함수와 <strong>this</strong> 바인딩 방식이 다르고,</li>
<li><strong>prototype</strong> 프로퍼티가 없으며</li>
<li><strong>arguments</strong> 객체를 생성하지 않는다.</li>
</ul>
<pre><code class="language-js">var add = (x, y) =&gt; x + y;
console.log(add(2, 5)); // 7</code></pre>
<hr>
<h2 id="125-함수-호출">12.5 함수 호출</h2>
<p>함수는 함수를 가리키는 식별자와 한 쌍의 소괄화() 인 함수 호출 연산자로 호출된다.</p>
<br>

<h3 id="1251-매개변수와-인수">12.5.1 매개변수와 인수</h3>
<p>함수를 실행하기 위해 <strong>필요한 값을 함수 외부에서 내부로 전달할 필요가 있는 경우</strong>, 매개변수를 통해 인수를 전달한다.</p>
<ul>
<li><strong>인수</strong> : 함수를 호출할 때 지정하며, 개수와 타입에 제한이 없다.</li>
<li><strong>매개변수</strong> : 함수를 정의할 때 선언하며, 스코프(유효범위)는 함수 내부이다.</li>
</ul>
<pre><code class="language-js">// 함수 선언문
function add(x, y) {
  return x + y;
}

// 함수 호출
// 인수 1과 2는 매개변수 x와 y에 순서대로 할당되고 함수 몸체의 문들이 실행된다.
var result = add(1, 2);</code></pre>
<br>

<h3 id="1252-인수-확인">12.5.2 인수 확인</h3>
<pre><code class="language-js">function add(x, y) {
  return x + y;
}

console.log(add(2)); // NaN
console.log(add(&#39;a&#39;, &#39;b&#39;)); // &#39;ab&#39;</code></pre>
<p>위 코드는 자바스크립트 문법상 어떠한 문제도 없으므로 자바스크립트 엔진은 아무런 이의 제기없이 실행할 것이다. 이러한 상황이 가능한 이유는,</p>
<ul>
<li>자바스크립트 함수는 매개변수와 인수의 개수가 일치하는지 확인하지 않는다.</li>
<li>자바스크립트는 동적 타입 언어다. 따라서 자바스크립트 함수는 매개변수의 타입을 사전에 지정할 수 없다.</li>
</ul>
<p>그래서 자바스크립트는 함수를 정의할 때 적절한 인수가 전달되었는지 확인할 필요가 있다.</p>
<pre><code class="language-js">function add(x, y) {
  if (typeof x !== &#39;number&#39; || typeof y !== &#39;number&#39;) {
    // 매개변수를 통해 전달된 인수의 타입이 부적절한 경우 에러를 발생시킨다.
    throw new TypeError(&#39;인수는 모두 숫자 값이어야 합니다.&#39;);
  }

  return x + y;
}

console.log(add(2));        // TypeError: 인수는 모두 숫자 값이어야 합니다.
console.log(add(&#39;a&#39;, &#39;b&#39;)); // TypeError: 인수는 모두 숫자 값이어야 합니다.</code></pre>
<br>

<h3 id="1253-매개변수의-최대-개수">12.5.3 매개변수의 최대 개수</h3>
<p>ECMAScirpt 사양에서는 매개변수의 최대 개수에 대해 명시적으로 제한하고 있지는 않지만, 물리적 한계는 있으므로 자바스크립트 엔진마다 매개변수의 최대 개수에 대한 제한은 있다.</p>
<ul>
<li>매개변수는 순서에 의미가 있다.</li>
<li><blockquote>
<p>따라서 매개변수가 많아지면 함수를 호출할 때 전달해야 할 인수의 순서를 고려해야 한다.</p>
</blockquote>
</li>
<li>함수의 매개변수는 코드를 이해하는 데 방해되는 요소이므로,</li>
<li><blockquote>
<p>이상적인 매개변수의 개수는 0개이며</p>
</blockquote>
</li>
<li><blockquote>
<p>최대 3개 이상을 넘지 않는 것을 권장</p>
</blockquote>
</li>
<li>매개변수의 개수가 많다는 것은 함수가 여러가지 일을 한다는 증거이므로 바람직하지 않다.</li>
<li><blockquote>
<p><strong>이상적인 함수는 한 가지 일만 해야 하며</strong> 가급적 작게 만들어야 한다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="1254-반환문">12.5.4 반환문</h3>
<p>함수는 <code>return</code> 키워드와 반환 값으로 이뤄진 반환문을 사용해 실행 결과를 함수 외부로 반환 할 수 있다.</p>
<p>반환문은 두 가지 역할을 하는데,</p>
<ul>
<li>첫째, 반환문은 함수의 실행을 중단하고 함수 몸체를 빠져나간다.</li>
<li><blockquote>
<p>반환문 이후에 다른 문이 존재하면 그 문은 실행되지 않고 무시된다.</p>
</blockquote>
</li>
<li>둘째, 반환문은 return 키워드 뒤에 오는 표현식을 평가에 반환한다.</li>
<li><blockquote>
<p>return 키워드 뒤에 반환값으로 사용할 표현식을 명시적으로 지정하지 않으면 undefined가 반환된다.</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="126-다양한-함수의-형태">12.6 다양한 함수의 형태</h2>
<h3 id="1261-즉시-실행-함수">12.6.1 즉시 실행 함수</h3>
<blockquote>
<p><strong>함수 정의와 동시에 즉시 호출되는 함수</strong></p>
</blockquote>
<ul>
<li>단 한 번만 호출되며 다시 호출 할 수 없다.</li>
</ul>
<pre><code class="language-js">// 즉시 실행 함수는 익명 함수로 사용하는 것이 일반적이다.
(function () {
  var a = 3;
  var b = 5;
  return a*b;
} ());</code></pre>
<br>

<h3 id="1262-재귀-함수">12.6.2 재귀 함수</h3>
<blockquote>
<p>함수가 자기 자신을 호출하는 것</p>
</blockquote>
<ul>
<li>재귀 함수는 자기 자신을 호출하는 행위</li>
<li>재귀 함수는 자신을 <strong>무한 재귀 호출</strong> 하므로 탈출 조건을 만들어야 스택 오버 플로 에러가 발생하지 않는다.</li>
</ul>
<pre><code class="language-js">// 함수 표현식
var factorial = function foo(n) {
  // 탈출 조건: n이 1 이하일 때 재귀 호출을 멈춘다.
  if (n &lt;= 1) return 1;
  // 함수를 가리키는 식별자로 자기 자신을 재귀 호출
  return n * factorial(n - 1);

  // 함수 이름으로 자기 자신을 재귀 호출할 수도 있다.
  // console.log(factorial === foo); // true
  // return n * foo(n - 1);
};

console.log(factorial(5)); // 5! = 5 * 4 * 3 * 2 * 1 = 120</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/92d9fddb-0c06-4692-812e-88a1db644da3/image.png" alt=""></p>
<br>

<h3 id="1263-중첩-함수">12.6.3 중첩 함수</h3>
<blockquote>
<p><strong>중첩 함수 ( = 내부 함수 )</strong></p>
</blockquote>
<ul>
<li><strong>함수 내부에 정의된 함수</strong> </li>
<li>중첩 함수는 <strong>외부 함수 내에서만 호출</strong> 할 수 있다.</li>
<li>일반적으로 중첩 함수는 자신을 포함하는 외부 함수를 돕는 <strong>헬퍼 함수</strong> 의 역할을 한다.</li>
</ul>
<pre><code class="language-js">function outer() {
  var x = 1;

  // 중첩 함수
  function inner() {
    var y = 2;
    // 외부 함수의 변수를 참조할 수 있다.
    console.log(x + y); // 3
  }

  inner();
}

outer();</code></pre>
<br>

<h3 id="1264-콜백-함수">12.6.4 콜백 함수</h3>
<blockquote>
<p><strong>함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수</strong></p>
</blockquote>
<ul>
<li>매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 <strong>고차 함수</strong> 라고 한다.</li>
<li>고차 함수는 콜백 함수를 자신의 일부분으로 합성하며</li>
<li>매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출한다.</li>
</ul>
<pre><code class="language-js">// 외부에서 전달받은 f를 n만큼 반복 호출한다
function repeat(n, f) {
  for (var i = 0; i &lt; n; i++) {
    f(i); // i를 전달하면서 f를 호출
  }
}

var logAll = function (i) {
  console.log(i);
};

// 반복 호출할 함수를 인수로 전달한다.
repeat(5, logAll); // 0 1 2 3 4

var logOdds = function (i) {
  if (i % 2) console.log(i);
};

// 반복 호출할 함수를 인수로 전달한다.
repeat(5, logOdds); // 1 3</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_원시 값과 객체의 비교]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%9B%90%EC%8B%9C-%EA%B0%92%EA%B3%BC-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%9B%90%EC%8B%9C-%EA%B0%92%EA%B3%BC-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Sun, 21 Aug 2022 13:19:26 GMT</pubDate>
            <description><![CDATA[<h1 id="11_원시-값과-객체의-비교">11_원시 값과 객체의 비교</h1>
<p>자바스크립트에서 제공하는 데이터 타입은
크게 <strong>원시 타입(premitive type)</strong> 과 <strong>객체 타입(obejct/reperence type)</strong> 으로 구분 하는데, 둘 사이는 차이점이 존재한다.</p>
<ul>
<li>원시 타입 값은 <strong>변경 불가능 한 값</strong> 이고, 
객체(참조) 타입 값은 <strong>변경 가능한 값</strong> 이다.</li>
<li>원시 타입 값을 변수에 할당하면 변수(확보된 메모리 공간) 에는 <strong>실제 값이 저장</strong>
객체(참조) 타입 값은 변수(확보된 메모리 공간)에는 <strong>참조 값이 저장</strong></li>
<li>원시 타입 값을 갖는 변수를 다른 변수에 할당하면 <strong>원본의 원시 값이 복사되어 전달</strong> 
객체 타입 값을 갖는 변수를 다른 변수에 할당하면 <strong>원본의 참조 값이 복사되어 전달</strong></li>
</ul>
<hr>
<h2 id="111-원시-타입-값">11.1 원시 타입 값</h2>
<h3 id="1111-변경-불가능한-값">11.1.1 변경 불가능한 값</h3>
<blockquote>
<p><strong>원시 타입은</strong>
변경 불가능한 값으로 <strong>읽기 전용(read only)</strong> 값이다.</p>
</blockquote>
<blockquote>
<p>JavaScript에서 원시 값(primitive, 또는 원시 자료형)이란 객체가 아니면서 메서드도 가지지 않는 데이터입니다. 원시 값에는 7종류, string, number (en-US), bigint (en-US), boolean, undefined, symbol, 그리고 null이 존재합니다.
( 출처 : MDN )</p>
</blockquote>
<ul>
<li>원시 값 자체를 변경 불가능하다는 것이지, 변수 값을 변경 할 수 없다는 것이 아님을 유의!</li>
</ul>
<pre><code class="language-js">// const 키워드를 사용 해 선언한 변수는 재할당이 금지된다. 상수는 재할당이 금지된 변수일 뿐이다.
const o = {};

// const 키워드를 사용해 선언한 변수에 할당한 원시 값(상수)은 변경할 수 없다.
// 하지만 const 키워드를 사용해 선언한 변수에 할당한 객체는 변경할 수 있다.
o.a = 1;
console.log(o); // {a: 1}</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/570afc57-b9c9-47af-958a-224c2508b540/image.png" alt=""></p>
<p>원시 값을 할당한 변수에 <strong>새로운 원시 값을 재할당</strong> 하면,</p>
<ul>
<li>메모리 공간에 저장되어 있는 <strong>재할당 이전의 원시 값을 변경하는 것이 아니라</strong>,</li>
<li><strong>새로운 메모리 공간을 확보</strong> 하고 재할당한 원시 값을 저장한 후,</li>
<li><blockquote>
<p>변수가 참조하던 메모리 공간의 주소가 변경된 이유는, 변수에 할당된 원시 값이 변경 불가능한 값이기 때문</p>
</blockquote>
</li>
<li>변수는 <strong>새롭게 재할당한 원시 값을 가리킨다.</strong></li>
<li><blockquote>
<p>이러한 특성을 불변성이라고 한다</p>
</blockquote>
</li>
<li><blockquote>
<p>불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 값을 변경 할 수 있는 방법이 없다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="1112-문자열과-불변성">11.1.2 문자열과 불변성</h3>
<blockquote>
<p><strong>문자열은</strong>
유사 배열 객체로서 배열과 유사하게 각 문장에 접근 할 수 있으나,
<strong>변경 불가능 한 값</strong> 이기 때문에 일부 문자를 변경해도 반영되지 않는다.
원시 타입은 문자열은 <strong>읽기 전용</strong> 이기 때문이다.</p>
</blockquote>
<p>원시 값을 저장하려면 먼저 확보해야 하는 메모리 공간의 크기를 결정해야 한다.</p>
<ul>
<li>이를 위해 원시 타입별로 메모리 공간의 크기가 미리 정해져 있다.</li>
<li>ECMAScript 사양에</li>
<li><blockquote>
<p>문자열 타입(2바이트) 와 숫자 타입(8바이트)</p>
</blockquote>
</li>
<li>이외의 원시 타입은 크기를 명확히 규정하고 있지 않다.</li>
</ul>
<pre><code class="language-js">var str = &#39;string&#39;;

// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
// 하지만 문자열은 원시값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = &#39;s&#39;;

console.log(str); // string</code></pre>
<br>

<h3 id="1113-값에-의한-전달">11.1.3 값에 의한 전달</h3>
<blockquote>
<p>변수에 원시 값을 할당하면, 할당받는 변수에는 <strong>할당되는 변수의 원시 값이 복사되어 전달</strong> 된다.</p>
</blockquote>
<pre><code class="language-js">var score = 90;
var copy = score;

console.log(score); // 90
console.log(copy);  // 90

score = 100

console.log(score); // 100
console.log(copy);  // 100</code></pre>
<p>score 변수와 copy 변수는 숫자 값 100을 갖는다는 점에서는 동일하지만,
score 변수와 copy 변수의 값 100은 <strong>다른 메모리 공간에 저장된 별개의 값</strong>이다.</p>
<p>즉, 값에 의한 전달은 사실 값을 전달하는 것이 아니라 <strong>메모리 주소를 전달</strong>한다.</p>
<blockquote>
<p><strong>중요한 것은</strong>
변수에 원시 값을 갖는 변수를 할당하면, ( 위와 같이 )
<strong>변수 할당 시점</strong> 이든, 두 변수 중 어느 하나의 변수에 값을 <strong>재할당 하는 시점</strong> 이든
두 변수의 원시 값은 <strong>서로 다른 메모리 공간에 저장된 별개의 값</strong> 이 되어
어느 한쪽에서 재할당을 통해 값을 변경하더라도 <strong>서로 간섭할 수 없다.</strong></p>
</blockquote>
<hr>
<h2 id="112-객체">11.2 객체</h2>
<ul>
<li>프로퍼티의 개수가 정해져 있지 않아 <strong>동적으로 추가되고 삭제할 수 있고</strong></li>
<li>프로퍼티의 값에도 제약이 없다.</li>
<li><strong>원시 값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해 둘 수 없고
복합적인 자료구조라서 ,원시 값과는 다른 방식으로 동작하도록 설계되어 있다.</strong></li>
<li>객체를 변경할 때 마다 복사해서 생성 후 변경하면 비용이 많이 든다.</li>
<li>원시 값처럼 이전 값을 복사해서 새롭개 생성한다면</li>
<li><blockquote>
<p>명확하고 신뢰성이 확보되겠지만</p>
</blockquote>
</li>
<li><blockquote>
<p>객체는 크기가 매우 클 수도 있고</p>
</blockquote>
</li>
<li><blockquote>
<p>원시 값처럼 크기가 일정하지도 않으며,</p>
</blockquote>
</li>
<li><blockquote>
<p>프로퍼티 값이 객체일 수도 있어서</p>
</blockquote>
</li>
</ul>
<p>따라서 <strong>메모리를 효율적으로 사용하기 위해,</strong>
그리고 객체를 복사해 생성하는 비용을 절약하여 성능을 향상시키기 위해
-&gt; <strong>객체는 변경 가능한 값으로 설계되어 있다.</strong></p>
<h3 id="1121-변경-가능한-값">11.2.1 변경 가능한 값</h3>
<blockquote>
<p><strong>객체(참조) 타입의 값은 변경 가능한 값 이다.</strong></p>
</blockquote>
<ul>
<li>객체를 할당한 변수는 <strong>재할당 없이 객체를 직접 변경</strong> 할 수 있다.</li>
<li>즉, 재할당 없이 프로퍼티를 <strong>동적으로 추가</strong> 할 수 있고</li>
<li><strong>값을 갱신</strong> 할 수 있으며, <strong>자체를 삭제</strong> 할 수 있다.</li>
</ul>
<br>

<h3 id="얕은-복사와-깊은-복사">얕은 복사와 깊은 복사</h3>
<p>객체를 프로퍼티 값으로 갖는 객체인 경우</p>
<ul>
<li><strong>얕은 복사</strong> 는 <strong>한 단계</strong> 까지만 복사하는 것을 말하고 ➔ 참조 값을 복사</li>
<li><strong>깊은 복사</strong> 는 <strong>객체에 중첩되어 있는 객체</strong> 까지 복사하는 것을 말한다.
➔ 객체에 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 <strong>완전한 복사본</strong>을 만드는 복사</li>
</ul>
<pre><code class="language-js">const o = { x: { y: 1 } };

// 얕은 복사
const c1 = { ...o };       // 스프레드 문법
console.log(c1 === o);     // false
console.log(c1.x === o.x); // true

// lodash의 cloneDeep을 사용한 깊은 복사
// &quot;npm install lodash&quot;로 lodash를 설치한 후, Node.js 환경에서 실행
const _ = require(&#39;lodash&#39;);
// 깊은 복사
const c2 = _.cloneDeep(o);
console.log(c2 === o);     // false
console.log(c2.x === o.x); // false

const v = 1;

// &quot;깊은 복사&quot;라고 부르기도 한다.
const c1 = v;
console.log(c1 === v);     // true

const o = { x: 1 };

// &quot;얕은 복사&quot;라고 부르기도 한다.
const c2 = o;
console.log(c2 === o);     // true</code></pre>
<p>얕은 복사와 깊은 복사로 생성한 객체는 원본과는 다른 객체다.
-&gt; <strong>원본과 복사본은 참조 값이 다른 별개의 객체다.</strong></p>
<br>

<h3 id="1122-참조에-의한-전달">11.2.2 참조에 의한 전달</h3>
<blockquote>
<p>객체를 가리키는 변수(원본 <strong>person</strong>) 을 다른 변수(사본 <strong>copy</strong>)에 할당하면,
<strong>원본의 참조 값이 복사되어 전달</strong> 되는 것</p>
</blockquote>
<pre><code class="language-js">var person = {
  name: &#39;Lee&#39;
};

// 참조값을 복사(얕은 복사)
var copy = person;</code></pre>
<p>위의 코드에서 person과 copy 모두 동일한 객체를 가리키는데
이는 두 개의 식별자가 하나의 객체를 공유 한다는것을 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/b691e536-6114-4c19-b28b-c042102a8c52/image.png" alt=""></p>
<hr>
<h2 id="정리">정리</h2>
<p><strong>값에 의한 전달</strong> 과 <strong>참조에 의한 전달</strong> 은</p>
<ul>
<li>식별자가 기억하는 메모리 공간에 저장되어 있는 값을 복사해서 전달한다는 면에서 동일하지만,</li>
<li><strong>식별자가 기억하는 메모리 공간(변수)에 저장되어 있는 값이 원시 값이냐 참조 값이냐에 차이가 있다.</strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_객체 리터럴]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EA%B0%9D%EC%B2%B4-%EB%A6%AC%ED%84%B0%EB%9F%B4</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EA%B0%9D%EC%B2%B4-%EB%A6%AC%ED%84%B0%EB%9F%B4</guid>
            <pubDate>Sun, 21 Aug 2022 12:43:14 GMT</pubDate>
            <description><![CDATA[<h1 id="10_객체-리터럴">10_객체 리터럴</h1>
<h2 id="101-객체-">10.1 객체 ?</h2>
<blockquote>
<p><strong>객체는</strong> 
객체의 상태를 나타내는 값(프로퍼티) 과 그 값을 참조하고 조작 할 수 있는 동작(메서드) 을 모두 가지고 있는 것</p>
</blockquote>
<ul>
<li>상태(데이터) 와 동작(메서드) 을 하나의 단위로 구조와 할 수 있어 유용하다.</li>
</ul>
<p>자바스크립트는 <strong>객체(object) 기반의 프로그래밍 언어</strong> 이며, 
자바스크립트를 구성하는 것은 대부분 객체이다.</p>
<ul>
<li>원시 값을 제외한 나머지 값(함수, 배열, 표현식 등)은 모두 객체</li>
<li>원시 타입은 단 하나의 값만 나타내지만, 객체 타입은 다양한 타입의 값을 하나의 단위로 구성한 
복합적인 자료구조다.</li>
<li>원시 타입의 값은 변경 불가능한 값이지만, <strong>객체는 변경 가능한 값이다.</strong></li>
<li>객체는 0개 이상의 프로퍼티로 구성된 집합이며, 프로퍼티는 <strong>키(key)</strong> 와 <strong>값(value)</strong> 으로 구성된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/224b9e91-4a61-4d15-8650-bb1dfab9bc6f/image.png" alt=""></p>
<p>자바스크립트에서 사용할 수 있는 모든 값은 프로퍼티 값이 될 수 있다.</p>
<ul>
<li>자바스크립트의 함수는 <strong>일급 객체</strong> 이므로 값이 될 수 있고,</li>
<li><strong>일급 객체</strong> 또한 프로퍼티 값으로 사용 할 수 있다.</li>
</ul>
<blockquote>
<p><strong>일급 객체 ?</strong>
다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. 보통 함수에 매개변수로 넘기기, 수정하기, 변수에 대입하기와 같은 연산을 지원할 때 일급 객체라고 한다. 
(출처 : 위키백과)</p>
</blockquote>
<p>즉, 특정 언어에서 객체를 값으로 취급하는 것을 말한다.
✅ 자바스크립트에서는 함수가 일급객체이다.</p>
<ul>
<li>무명의 리터럴로 생성할 수 있다. (런타임 생성이 가능하다.)</li>
<li>변수나 자료구조(객체, 배열 등)에 저장할 수 있다.</li>
<li>함수의 매개변수에 전달할 수 있다.</li>
<li>함수의 반환값(return)으로도 사용할 수 있다.</li>
</ul>
<p><strong>자바스크립트의 함수는 위 조건을 모두 만족하므로 일급 객체이다.</strong></p>
<hr>
<h2 id="102-객체-리터럴에-의한-객체-생성">10.2 객체 리터럴에 의한 객체 생성</h2>
<blockquote>
<p><strong>객체 리터럴은</strong>
자바스크립트의 <strong>유연함</strong> 과 <strong>강력함</strong> 을 대표하는 <strong>객체 생성 방식</strong>이다.</p>
</blockquote>
<ul>
<li><del>객체를 생성하기 위해 클래스를 먼저 정의하고, new 연산자와 함께 생성자를 호출할 필요가 있다.</del></li>
<li>숫자 값이나 문자열을 만드는 것과 유사하게 리터럴로 객체를 생성한다.</li>
<li>객체 리터럴에 프로퍼티 값을 포함시켜 객체를 생성함과 동시에 프로퍼티를 만들 수 있고,</li>
<li>객체를 생성한 이후에 프로퍼티를 동적으로 추가할 수 있다.</li>
</ul>
<br>

<p>C++이나 자바같은 <strong>클래스 기반 객체지향 언어</strong>는</p>
<ul>
<li>클래스를 사전에 정의하고</li>
<li>필요한 시점에 new 연산자와 함께 생성자를 호출하여 인스턴스(instance)를 생성하는 방식으로 객체를 생성한다.</li>
</ul>
<blockquote>
<p><strong>인스턴스(instance)</strong>
클래스에 의해 생성되어 <strong>메모리에 저장된 실체를 의미</strong></p>
</blockquote>
<p>하지만, 자바스크립트는 <strong>프로토타입 기반 객체 지향 언어</strong> 로, 클래스 기반 객체 지향언어와는 달리 다양한 객체 생성 방법을 지원한다.</p>
<ul>
<li>객체 리터럴</li>
<li>Object 생성자 함수</li>
<li>생성자 함수</li>
<li>Object.create 메서드</li>
<li>클래스(ES6)</li>
</ul>
<blockquote>
<p><strong>프로토타입 기반 객체 지향 언어</strong>
객체지향 프로그래밍의 한 형태의 갈래로 클래스가 없고, 클래스 기반 언어에서 상속을 사용하는 것과는 다르게, 객체를 원형으로 하여 복제의 과정을 통하여 객체의 동작 방식을 다시 사용할 수 있다. 
( 출처 : 위키백과 )</p>
</blockquote>
<p>객체 생성 방법 중에서 가장 간단한 방법은 <strong>객체 리터럴</strong> 이다.</p>
<ul>
<li>중괄호({...}) 내에 0개 이상의 프로퍼티를 정의한다.</li>
<li>변수에 할당되는 시점에 자바스크립트 엔진은 객체 리터럴을 해석해 객체를 생성한다.</li>
</ul>
<blockquote>
<p><strong>리터럴 (literal)</strong>
사람이 이해할 수 있는 문자 또는 약속된 기호를 사용하여 값을 생성하는 표기법</p>
</blockquote>
<pre><code class="language-js">var person = {
    name: &#39;april&#39;,
    sayHello: function () {
      console.log(`Hello! My name is ${this.name}.`);
    }
};
console.log(typeof person); // object
console.log(person);        // {name: &quot;april&quot;, sayHello: ƒ}

// 중괄호 내에 프로퍼티를 정의하지 않으면 빈 객체가 생성된다.
var empty = {};
console.log(typeof empty); // object</code></pre>
<blockquote>
<p><strong>Point</strong>
<strong>객체 리터럴의 중괄호는 코드 블록을 의미하지 않는다.</strong>
따라서 코드블록의 닫는 중괄호 뒤에는 세미콜론(;)을 붙이지 않지만 객체 리터럴의 닫는 중괄호 뒤에는 세미콜론을 붙인다.</p>
</blockquote>
<hr>
<h2 id="103-프로퍼티">10.3 프로퍼티</h2>
<p><strong>객체는 프로퍼티의 집합이며 프로퍼티는 키와 값으로 구성된다.</strong></p>
<pre><code class="language-js">var person = {
  // 프로퍼티 키는 name, 프로퍼티 값은 &#39;april&#39;
  name: &#39;april&#39;,
  // 프로퍼티 키는 age, 프로퍼티 값은 20
  age: 20
};</code></pre>
<p>프로퍼티를 나열 할 때는 쉼표로 구분한다.
프로퍼티 키와 값으로 사용 할 수 있는 값은 아래와 같다.</p>
<ul>
<li>키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌값</li>
<li>값 : 자바스크립트에서 사용할 수 있는 모든 값</li>
</ul>
<hr>
<h2 id="104-메서드">10.4 메서드</h2>
<p>자바스크립트의 함수는 객체(일급 객체) 라서 값으로 취급 할 수 있다.</p>
<ul>
<li>즉, 함수는 값으로 취급 할 수 있기 때문에 <strong>프로퍼티 값</strong> 으로 사용 할 수 있다.</li>
<li>프로퍼티 값이 함수일 경우 일반 함수와 구분하기 위해 <strong>메서드</strong> 라고 부른다.</li>
</ul>
<pre><code class="language-js">var circle = {
  radius: 5, // ← 프로퍼티

  // 원의 지름
  getDiameter: function () { // ← 메서드
    return 2 * this.radius;  // this는 circle을 가리킨다.
  }
};

console.log(circle.getDiameter()); // 10</code></pre>
<hr>
<h2 id="105-프로퍼티-접근">10.5 프로퍼티 접근</h2>
<ul>
<li>마침표 : 프로퍼티 접근 연산자(.) 를 사용하는 <strong>마침표 표기법</strong></li>
<li>대괄호 : 프로퍼티 접근 연산자([...]) 를 사용하는 <strong>대괄호 표기법</strong></li>
</ul>
<pre><code class="language-js">var person = {
  name: &#39;april&#39;
};

// 마침표 표기법에 의한 프로퍼티 접근
console.log(person.name);    // april

// 대괄호 표기법에 의한 프로퍼티 접근
console.log(person[&#39;name&#39;]); // april

// undefined 반환
console.log(person.age)</code></pre>
<hr>
<h2 id="107-프로퍼티-동적-생성">10.7 프로퍼티 동적 생성</h2>
<p>존재하지 않는 값을 프로퍼티에 할당하면</p>
<ul>
<li>동적으로 생성되어 추가되고,</li>
<li>값이 할당된다.</li>
</ul>
<pre><code class="language-js">var person = {
  name: &#39;april&#39;
};

// person 객체에는 age 프로퍼티가 존재하지 않는다.
// 따라서 person 객체에 age 프로퍼티가 동적으로 생성되고 값이 할당된다.
person.age = 20;

console.log(person); // {name: &quot;april&quot;, age: 20}</code></pre>
<hr>
<h2 id="108-프로퍼티-삭제">10.8 프로퍼티 삭제</h2>
<p><strong>delete</strong> 연산자는 객체의 프로퍼티 값을 <strong>삭제</strong>한다.</p>
<pre><code class="language-js">var person = {
  name: &#39;april&#39;
};

// 프로퍼티 동적 생성
person.age = 20;

// person 객체에 age 프로퍼티가 존재한다.
// 따라서 delete 연산자로 age 프로퍼티를 삭제할 수 있다.
delete person.age;

// person 객체에 address 프로퍼티가 존재하지 않는다.
// 따라서 delete 연산자로 address 프로퍼티를 삭제할 수 없다. 이때 에러가 발생하지 않는다.
delete person.address;

console.log(person); // {name: &quot;april&quot;}</code></pre>
<hr>
<h2 id="109-es6에서-추가된-객체-리터럴의-확장-기능">10.9 ES6에서 추가된 객체 리터럴의 확장 기능</h2>
<h3 id="1091-프로퍼티의-축약-표현">10.9.1 프로퍼티의 축약 표현</h3>
<p>객체 리터럴의 프로퍼티는 키와 값으로 구성된다.</p>
<ul>
<li>프로퍼티 값은 변수에 할당된 값, 식별자 표현식일 수도 있다.</li>
</ul>
<blockquote>
<p>ES6에서는 프로퍼티 값으로 변수를 사용하는 경우
<strong>변수 이름</strong>과 <strong>프로퍼티 키</strong>가 <strong>동일한 이름</strong>일 때 <strong>프로퍼티 키를 생략</strong> 할 수 있다.</p>
</blockquote>
<pre><code class="language-js">// ES5
var x = 1, y = 2;
var obj = {
  x: x,
  y: y
};

console.log(obj); // {x: 1, y: 2}



// ES6
let x = 1, y = 2;

// 프로퍼티 축약 표현
const obj = { x, y };

console.log(obj); // {x: 1, y: 2}</code></pre>
<br>

<h3 id="1092-계산된-프로퍼티-이름">10.9.2 계산된 프로퍼티 이름</h3>
<p><strong>문자열</strong> 또는 <strong>문자열로 타입 변환 할 수 있는 값</strong> 으로 평가되는 표현식을 통해
<strong>프로퍼티 키를 동적으로 생성</strong> 할 수 있다.</p>
<ul>
<li>단, 프로퍼티 키로 사용할 표현식을 대괄호([...])로 묶어야 한다.</li>
<li>이를 계산된 프로퍼티 이름라고 한다.</li>
</ul>
<pre><code class="language-js">// ES5
var prefix = &#39;prop&#39;;
var i = 0;
var obj = {};

// 계산된 프로퍼티 이름으로 프로퍼티 키 동적 생성
obj[prefix + &#39;-&#39; + ++i] = i;
obj[prefix + &#39;-&#39; + ++i] = i;
obj[prefix + &#39;-&#39; + ++i] = i;

console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3}


// ES6
const prefix = &#39;prop&#39;;
let i = 0;

// 객체 리터럴 내부에서 계산된 프로퍼티 이름으로 프로퍼티 키 동적 생성
const obj = {
  [`${prefix}-${++i}`]: i,
  [`${prefix}-${++i}`]: i,
  [`${prefix}-${++i}`]: i
};

console.log(obj); // {prop-1: 1, prop-2: 2, prop-3: 3}</code></pre>
<br>

<h3 id="1093-메서드-축약-표현">10.9.3 메서드 축약 표현</h3>
<p>메서드를 정의 할 때 <strong>function</strong> 키워드를 생략 한 축약 표현을 사용할 수 있다.</p>
<pre><code class="language-js">// ES5
var obj = {
  name: &#39;april&#39;,
  sayHi: function() {
    console.log(&#39;Hi! &#39; + this.name);
  }
};

obj.sayHi(); // Hi! april


// ES6
const obj = {
  name: &#39;april&#39;,
  // 메서드 축약 표현
  sayHi() {
    console.log(&#39;Hi! &#39; + this.name);
  }
};

obj.sayHi(); // Hi! april</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_타입변환]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%ED%83%80%EC%9E%85%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%ED%83%80%EC%9E%85%EB%B3%80%ED%99%98</guid>
            <pubDate>Wed, 17 Aug 2022 15:11:40 GMT</pubDate>
            <description><![CDATA[<h1 id="09_타입-변환과-단축-평가">09_타입 변환과 단축 평가</h1>
<h2 id="91-타입-변환-">9.1 타입 변환 ?</h2>
<p>자바스크립트의 모든 값은 타입을 가지는데,</p>
<ul>
<li><p>개발자의 의도에 따라 값의 타입을 변환하는 것을</p>
</li>
<li><blockquote>
<p><strong>명시적 타입 변환</strong>  또는 <strong>타입 캐스팅</strong> 이라고 한다.</p>
</blockquote>
</li>
<li><p>개발자의 의도와는 상관없이 표현식을 평가하는 도중에 자바스크립트 엔진에 의해 <strong>암묵적으롤 타입이 자동 변환되는 것을</strong></p>
</li>
<li><blockquote>
<p><strong>암묵적 타입 변환</strong> 또는 <strong>타입 강제 변환</strong> 이라고 한다.</p>
</blockquote>
</li>
</ul>
<blockquote>
<p><strong>자바스크립트는 가급적 에러를 발생시키지 않도록 암묵적으로 타입 변환을 통해 표현식을 평가</strong></p>
</blockquote>
<ul>
<li>그렇다고 명시적 타입 변환이나 암묵적 타입 변환이나 기존 원시값을 직접 변경하는 것은 아니다.</li>
<li><blockquote>
<p>원시 값은 <strong>변경 불가능한 값</strong> 이다.</p>
</blockquote>
</li>
</ul>
<p>즉, 타입변환이란</p>
<ul>
<li>기존 원시 값을 사용해 다른 타입의 <strong>새로운 값을 생성</strong> 하는 것</li>
</ul>
<hr>
<h2 id="92-암묵적-타입-변환">9.2 암묵적 타입 변환</h2>
<blockquote>
<p>자바스크립트 엔진이 표현식을 평가할 때, <strong>개발자의 의도와 상관없이</strong> 코드의 문맥을 고려해 <strong>암묵적으로 데이터 타입을 강제 변환</strong> 하는 것</p>
</blockquote>
<br>

<h3 id="921-문자열-타입으로-변환">9.2.1 문자열 타입으로 변환</h3>
<ul>
<li><code>+</code> 또는 <code>템플릿 리터럴</code></li>
<li>템플릿 리터럴은 표현식의 평가 결과를 문자열 타입으로 암묵적 변환</li>
<li><strong>문자열 연결 연산자는 코드의 문맥상 모두 문자열 타입</strong> 이어야 한다.</li>
</ul>
<blockquote>
<p>자바스크립트 엔진은 문자열 연결 연산자를 만나면,
-&gt; <strong>문자열 타입이 아닌 값을 문자열 타입으로</strong> 암묵적 타입 변환하여 수행</p>
</blockquote>
<pre><code class="language-js">// 숫자 타입
0 + &#39;&#39;              // &quot;0&quot;
  -0 + &#39;&#39;             // &quot;0&quot;
1+ &#39;&#39;               // &quot;1&quot;
  -1 + &#39;&#39;             // &quot;-1&quot;
NaN + &#39;&#39;            // &quot;NaN&quot;
Infinity + &#39;&#39;       // &quot;Infinity&quot;
  -Infinity + &#39;&#39;      // &quot;-Infinity&quot;

// boolean 타입
true + &#39;&#39;           // &quot;true&quot;
false + &#39;&#39;          // &quot;false&quot;

// null 타입
null + &#39;&#39;           // &quot;null&quot;

// undefined 타입
undefined + &#39;&#39;      // &quot;undefined&quot;

// 심벌 타입
(Symbol()) + &#39;&#39;     // &quot;TypeError&quot;

// 객체 타입
({}) + &#39;&#39;           // &quot;[object Object]&quot;
Math + &#39;&#39;           // &quot;[object Math]&quot;
[] + &#39;&#39;             // &quot;&quot;
[10, 20] + &#39;&#39;       // &quot;10, 20&quot;
(function(){}) + &#39;&#39; // &quot;function()&quot;
Array + &#39;&#39;          // &quot;function Array() {[native code]}&quot;</code></pre>
<br>

<h3 id="922-숫자-타입으로-변환">9.2.2 숫자 타입으로 변환</h3>
<ul>
<li>+, -, / 는 모두 산술 연산자</li>
<li><strong>산술 연산자의 모든 피연산자는 코드 문맥상 모두 숫자 타입</strong> 이어야 한다.</li>
<li>자바스크립트 엔진은 <strong>+</strong> 단항 연산자를 만나면</li>
<li><blockquote>
<p>피연산자가 숫자 타입의 값이 아니면 숫자 타입의 값으로 암묵적 타입 변환을 수행</p>
</blockquote>
</li>
</ul>
<blockquote>
<p>자바스크립트 엔진은 산술 연산자를 만나면,
-&gt; <strong>숫자 타입이 아닌 값을 숫자 타입으로</strong> 암묵적 타입 변환하여 동작
-&gt; 이 때, 숫자 타입으로 변환할 수 없는 경우는 산술 연산을 수행할 수 없으므로 표현식의 결과는 <strong>NaN</strong>이 된다.</p>
</blockquote>
<pre><code class="language-js">// 숫자 타입
+&#39;&#39;               // 0
+&#39;0&#39;              // 0
+&#39;1&#39;              // 1 
+&#39;string&#39;         //  NaN

// boolean 타입
+true             //  1
+false            //  0

// null 타입
+null             //  0

// undefined 타입
+undefined        //  NaN

// 심벌 타입
+Symbol()         //  TypeError

// 객체 타입
+{}               //  NaN
+[]               //  0
+[10, 20]         //  NaN
+(function(){})   //  NaN</code></pre>
<br>

<blockquote>
<p><strong>비교 연산자</strong></p>
</blockquote>
<pre><code class="language-js">&#39;1&#39; &gt; 0 // true</code></pre>
<ul>
<li>비교 연산자는 피연산자의 크기를 비교하므로, <strong>코드의 문맥상 모두 숫자 타입</strong> 이어야 한다.</li>
</ul>
<br>

<h3 id="923-boolean-타입으로-변환">9.2.3 boolean 타입으로 변환</h3>
<ul>
<li><p>if 문과 for 문과 같은 제어문 또는 삼항 조건 연산자의 조건식은</p>
</li>
<li><blockquote>
<p><strong>논리적 참 / 거짓 으로 평가되어야 하는 표현식</strong> 으로</p>
</blockquote>
</li>
<li><blockquote>
<p>조건식의 평과 결과를 <strong>불리언 타입으로 암묵적 타입 변환을 한다.</strong></p>
</blockquote>
</li>
<li><p>자바스크립트 엔진은 불리언 타입이 아닌 값을</p>
</li>
<li><blockquote>
<p>Truthy 값 또는 Falsy 값으로 구분해 각각 true와 false로 암묵적 타입 변환 한다.</p>
</blockquote>
</li>
<li><blockquote>
<p>Truthy 값 또는 Falsy 값 앞에 느낌표(!)를 붙어주면 각각 true와 false로 전달된다.</p>
</blockquote>
</li>
<li><p>false로 평가되는 Falsy 값</p>
</li>
<li><blockquote>
<p>false</p>
</blockquote>
</li>
<li><blockquote>
<p>undefined</p>
</blockquote>
</li>
<li><blockquote>
<p>null</p>
</blockquote>
</li>
<li><blockquote>
<p>0, -0</p>
</blockquote>
</li>
<li><blockquote>
<p>NaN</p>
</blockquote>
</li>
<li><blockquote>
<p>‘’(빈 문자열)</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="93-명시적-타입-변환">9.3 명시적 타입 변환</h2>
<h3 id="931-문자열-타입으로-변환">9.3.1 문자열 타입으로 변환</h3>
<h4 id="1-string-생성자-함수-사용">1. <code>String()</code> 생성자 함수 사용</h4>
<pre><code class="language-js">// 숫자 타입 =&gt; 문자열 타입
String(1);              // &quot;1&quot;
String(NaN);            // &quot;NaN&quot;
String(Infinity);       // &quot;Infinity&quot;

// 불리언 타입 ➔ 문자열 타입
String(true)            // &quot;true&quot;
String(false)           // &quot;false&quot;</code></pre>
<br>

<h4 id="2-objectprototypetostring-메서드를-사용하는-방법">2. Object.prototype.toString 메서드를 사용하는 방법</h4>
<pre><code class="language-js">// 숫자 타입 ➔ 문자열 타입
(1).toString();         // &quot;1&quot;
(NaN).toString();       // &quot;NaN&quot;
(Infinity)toString();   // &quot;Infinity&quot;

// 불리언 타입 ➔ 문자열 타입
(true).toString();      // &quot;true&quot;
(false).toString();     // &quot;false&quot;</code></pre>
<br>

<h4 id="3-문자열-연결-연산자를-이용">3. 문자열 연결 연산자를 이용</h4>
<pre><code class="language-js">// 숫자 타입 ➔ 문자열 타입
1 + &#39;&#39;                  // &quot;1&quot;
NaN + &#39;&#39;                //  &quot;NaN&quot;
Infinity + &#39;&#39;           // &quot;Infinity&quot;

// 불리언 타입 ➔ 문자열 타입
true + &#39;&#39;               // &quot;true&quot;
false + &#39;&#39;              // &quot;false&quot;</code></pre>
<br>

<h3 id="932-숫자-타입으로-변환">9.3.2 숫자 타입으로 변환</h3>
<h4 id="1-number-생성자-함수를-사용">1. Number() 생성자 함수를 사용</h4>
<pre><code class="language-js">// 문자열 타입 ➔ 숫자 타입
Number(&#39;0&#39;);     // 0
Number(&#39;-1&#39;);    // -1
Number(&#39;10.53&#39;); // 10.53

// 불리언 타입 ➔ 숫자 타입
Number(true);    // 1
Number(false);   // 0</code></pre>
<br>

<h4 id="2-parseint-parsefloat-함수-사용-문자열-만">2. parseInt, parseFloat 함수 사용 (문자열 만)</h4>
<pre><code class="language-js">parseInt(&#39;0&#39;);       // 0
parseInt(&#39;-1&#39;);      // -1
parseFloat(&#39;10.53&#39;); // 10.53</code></pre>
<br>

<h4 id="3--단항-산술-연산자를-사용">3. + 단항 산술 연산자를 사용</h4>
<pre><code class="language-js">// 문자열 타입 ➔ 숫자 타입
+&#39;0&#39;;     // 0
+&#39;-1&#39;;    // -1
+&#39;10.53&#39;; // 10.53

// 불리언 타입 ➔ 숫자 타입
+true;    // 1
+false;   // 0</code></pre>
<h4 id="4--산술-연산자-사용">4. * 산술 연산자 사용</h4>
<pre><code class="language-js">// 문자열 타입 ➔ 숫자 타입
&#39;0&#39; * 1;     // 0
&#39;-1&#39; * 1;    // -1
&#39;10.53&#39; * 1; // 10.53

// 불리언 타입 ➔ 숫자 타입
true * 1;    // 1
false * 1;   // 0</code></pre>
<br>

<h3 id="933-boolean-타입으로-변환">9.3.3 boolean 타입으로 변환</h3>
<h4 id="1-boolean-사용">1. Boolean() 사용</h4>
<pre><code class="language-js">// 문자열 타입 ➔ 불리언 타입
Boolean(&#39;x&#39;);       // true
Boolean(&#39;&#39;);        // false
Boolean(&#39;false&#39;);   // true

// 숫자 타입 ➔ 불리언 타입
Boolean(0);         // false
Boolean(1);         // true
Boolean(NaN);       // false
Boolean(Infinity);  // true

// null 타입 ➔ 불리언 타입
Boolean(null);      // false

// undefined 타입 ➔ 불리언 타입
Boolean(undefined); // false

// 객체 타입 ➔ 불리언 타입
Boolean({});        // true
Boolean([]);        // true</code></pre>
<br>

<h4 id="2--부정-논리-연산자를-두-번-사용하는-방법">2. ! 부정 논리 연산자를 두 번 사용하는 방법</h4>
<pre><code class="language-js">// 문자열 타입 ➔ 불리언 타입
!!&#39;x&#39;;       // true
!!&#39;&#39;;        // false
!!&#39;false&#39;;   // true

// 숫자 타입 ➔ 불리언 타입
!!0;         // false
!!1;         // true
!!NaN;       // false
!!Infinity;  // true

// null 타입 ➔ 불리언 타입
!!null;      // false

// undefined 타입 ➔ 불리언 타입
!!undefined; // false

// 객체 타입 ➔ 불리언 타입
!!{};        // true
!![];        // true</code></pre>
<hr>
<h2 id="94-단축-평가">9.4 단축 평가</h2>
<p><strong>타입 변환을 하지 않고 그대로 반환</strong> 하는데 이를 <strong>단축 평가</strong> 라고 한다.</p>
<ul>
<li>단축 평가는 표현식을 평가하는 도중에 평가결과가 확정된 경우</li>
<li><blockquote>
<p><strong>나머지 결과를 생략</strong></p>
</blockquote>
</li>
<li><blockquote>
<p>단축평가를 사용하면 if문 대체</p>
</blockquote>
</li>
<li><blockquote>
<p>삼항 조건 연산자는 <strong>if-else</strong> 문을 대체</p>
</blockquote>
</li>
</ul>
<pre><code class="language-js">단축 평가 표현식    평과 결과
true ¦¦ anything    true
false ¦¦ anything    anything
true &amp;&amp; anything    true
false &amp;&amp; anything    false</code></pre>
<br>

<h3 id="941-논리-연산자를-사용한-단축-평가">9.4.1 논리 연산자를 사용한 단축 평가</h3>
<blockquote>
<p>논리합|| 또는 논리곱&amp;&amp;.</p>
</blockquote>
<ul>
<li><p>표현식의 평가 결과는 불리언 값이 아닐 수도 있다</p>
</li>
<li><p><strong>논리합||</strong> 또는 <strong>논리곱&amp;&amp;</strong>. 연산자 표현식은 언제나 2개의 피연산자 중 어느 한쪽으로 평가된다</p>
</li>
<li><p><strong>논리곱&amp;&amp; 연산자</strong> 는 두 개의 피연산자가 <strong>모두 true로 평가될 때 true</strong> 를 반환.</p>
</li>
<li><blockquote>
<p>좌항에서 우항으로 평가가 진행.</p>
</blockquote>
</li>
<li><p><strong>논리합|| 연산자는</strong></p>
</li>
<li><blockquote>
<p>두 개의 피연산자 중 <strong>하나만 true로 평가되어도 true</strong> 를 반환.</p>
</blockquote>
</li>
</ul>
<pre><code class="language-js">&#39;cat&#39; || &#39;dog&#39;   // cat
false || &#39;dog&#39;   // dog
&#39;cat&#39; || false   // cat

&#39;cat&#39; &amp;&amp; &#39;dog&#39;   // dog
false &amp;&amp; &#39;dog&#39;   // false
&#39;cat&#39; &amp;&amp; false   // false</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive_제어문]]></title>
            <link>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%A0%9C%EC%96%B4%EB%AC%B8</link>
            <guid>https://velog.io/@hoho_0815/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive%EC%A0%9C%EC%96%B4%EB%AC%B8</guid>
            <pubDate>Wed, 17 Aug 2022 14:13:41 GMT</pubDate>
            <description><![CDATA[<h1 id="08_제어문">08_제어문</h1>
<p>제어문은</p>
<ul>
<li>조건에 따라 코드 블록을 실행 하거나(조건문)</li>
<li>반복 실행(반복문) 할 때 사용</li>
</ul>
<p>코드는 위에서 아래로 순차적으로 실행하는데,</p>
<ul>
<li>제어문을 사용하면 코드 실행 흐름을 인위적으로 제어할 수 있다. 하지만 직관적인 코드의 흐름을 혼란스럽게 만들어서 코드의 가독성을 해치는 단점이 있다.</li>
<li><strong>forEach</strong>, <strong>map</strong>, <strong>filter</strong>, <strong>reduce</strong> 같은 함수형 프로그래밍 기법에서는 제어문의 사용을 억제하여 복잡성을 해결하고자 노력한다.</li>
</ul>
<hr>
<h2 id="81-블록문">8.1 블록문</h2>
<blockquote>
<p>0개 이상의 문을 중괄호 <code>{}</code> 로 묶은 것으로 <span style="color:red"> 코드 블록 </span>이라고 부르기도 한다.</p>
</blockquote>
<ul>
<li>자바스크립트에서는 블록문을 <strong>하나의 실행단위</strong> 로 취급한다.</li>
</ul>
<pre><code class="language-js">// 블록문
{
  var foo = 10;
}

// 제어문
var x = 1;
if (x &lt; 10) {
  x++;
}

// 함수 선언문
function sum(a, b) {
  return a + b;
}</code></pre>
<hr>
<h2 id="82-조건문">8.2 조건문</h2>
<blockquote>
<p><span style="color:red">주어진 조건식의 평가 결과에 따라 코드 블록의 실행을 결정</span> 한다.</p>
</blockquote>
<ul>
<li>자바스크립트는 <strong>if-else</strong> 문과 <strong>switch</strong> 두가지 조건문을 제공한다.</li>
</ul>
<br>

<h3 id="821-if-else-문">8.2.1 if-else 문</h3>
<ul>
<li>주어진 조건식에 따른 <strong>참과 거짓</strong>(true / false) 으로 평가</li>
<li>조건식의 개수에 따라 코드 블록을 늘리고 <strong>else if</strong> 문을 사용</li>
<li>대부분의 <strong>if-else</strong> 문은 삼항 조건 연산자로 바꾸어 사용 할 수 있다.</li>
</ul>
<pre><code class="language-js">if (조건식) {
  // 조건식이 참이면 이 코드 블록이 실행
} else {
  // 조건식이 거짓이면 이 코드 블록이 실행
}

if (조건식1) {
  // 조건식1이 참이면 이 코드 블록이 실행
} else if (조건식2) {
  // 조건식2이 참이면 이 코드 블록이 실행
} else {
  // 조건식1, 2 모두 거짓이면 이 코드 블록이 실행
}</code></pre>
<br>

<h3 id="822-switch-문">8.2.2 switch 문</h3>
<ul>
<li>주어진 표현식을 평가하여 <strong>그 값과 일치하는</strong> 표현식을 가지는 <strong>case</strong> 문으로 실행</li>
<li>case 문은</li>
</ul>
<ol>
<li>상황(case) 을 의미하는 표현식을 저장하고</li>
<li>콜론(:) 으로 끝난다.</li>
<li>그 뒤에 실행할 문들을 위치시킨다.</li>
</ol>
<ul>
<li><strong>switch 문의 표현식과 일치하는 case 문이 없다면</strong></li>
<li><blockquote>
<p>default 문으로 이동</p>
</blockquote>
</li>
<li><blockquote>
<p>default 문에서 <strong>break</strong> 문을 생략하는 것이 일반적</p>
</blockquote>
</li>
</ul>
<pre><code class="language-js">switch(표현식) {
  case 표현식1: 
    표현식과 표현식1이 일치하면 실행될 문;
    break;
  case 표현식2: 
    표현식과 표현식2이 일치하면 실행될 문;
    break;
  case 표현식3: 
    표현식과 표현식3이 일치하면 실행될 문;
    break;
  default: 표현식과 일치하는 case문이 없을 때 실행될 문;
}</code></pre>
<blockquote>
<p>__풀 스루(fall through) ? __
switch 문을 탈출하지 않고 switch 문이 끝날 때 까지 
모든 case 문과 default 문을 실행되는 것을 말한다.</p>
</blockquote>
<ul>
<li>풀 스루 예시<pre><code class="language-js">// 월을 영어로 변환한다. (4 -&gt; &#39;April&#39;)
var month = 4;
var monthName;
</code></pre>
</li>
</ul>
<p>switch(month) {
    case 1: monthNAme = &#39;January&#39;;
    case 2: monthNAme = &#39;February&#39;;
    case 3: monthNAme = &#39;March&#39;;
    case 4: monthNAme = &#39;April&#39;;
    case 5: monthNAme = &#39;May&#39;;
    case 6: monthNAme = &#39;June&#39;;
    case 7: monthNAme = &#39;July&#39;;
    case 8: monthNAme = &#39;August&#39;;
    case 9: monthNAme = &#39;September&#39;;
    case 10: monthNAme = &#39;October&#39;;
    case 11: monthNAme = &#39;November&#39;;
    case 12: monthNAme = &#39;December&#39;;
    default: monthName = &quot;Invalid month&quot;
}
console.log(monthName);  // Invaild month</p>
<pre><code>
***

## 8.3 반복문
반복문은
- __조건식의 평가 결과가 참인 경우 코드 블록을 실행__
- 자바스크립트는 __for__, __while__, __do-while__ 문을 제공

&lt;br&gt;

### 8.3.1 for 문
&gt; __조건식이 거짓으로 평가될 때까지 코드 블록을 반복 실행__

- for 문의 변수 선언문, 조건식, 증감식은 모두 옵션이므로 반드시 사용할 필요는 없다.

```js
for (변수 선언문 또는 할당문; 조건식; 증감식) {
  // 조건식이 참인 경우 반복 실행할 문;
}</code></pre><p><img src="https://velog.velcdn.com/images/hoho_0815/post/42e9ad4c-5542-4a7a-befb-9df67fe39719/image.png" alt=""></p>
<br>

<h3 id="832-while-문">8.3.2 while 문</h3>
<blockquote>
<p>주어진 조건식의 평가 결과가 참이면 코드 블록을 계속 실행하며 반복</p>
</blockquote>
<ul>
<li><strong>for</strong> 문은 반복 횟수가 명확할 때 주로 사용</li>
<li><strong>while</strong> 문은 <strong>반복 회수가 불명확할 때 주로 사용</strong></li>
</ul>
<pre><code class="language-js">while(조건식) {
  // 조건식이 참일 때 실행할 문;
}

// 무한 루프
while(true) {
  // ...
}</code></pre>
<ul>
<li>무한 루프를 탈출하기 위해서는 </li>
<li><blockquote>
<p>코드 블록 내의 <strong>if</strong> 문으로 탈출 조건을 만들고,  <strong>break</strong> 문으로 코드 블록을 탈출</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="833-do-while-문">8.3.3 do-while 문</h3>
<blockquote>
<p><strong>코드 블록을 먼저 실행하고 조건식을 평가</strong></p>
</blockquote>
<ul>
<li>따라서 코드 블록은 무조건 한 번 이상 실행</li>
</ul>
<pre><code class="language-js">do {
  //  ...
} while (조건식);</code></pre>
<br>

<h3 id="834-break-문">8.3.4 break 문</h3>
<blockquote>
<p>주 사용은 <strong>반복문</strong> 또는 <strong>switch</strong> 문의 코드 블록을 탈출 할 때 사용</p>
</blockquote>
<br>

<h3 id="835-continue-문">8.3.5 continue 문</h3>
<blockquote>
<p><strong>반복문의 코드 블록을 현 지점에서 중단하고 증감식으로 실행 흐름을 이동</strong></p>
</blockquote>
<ul>
<li><strong>break</strong> 문처럼 반복문을 탈출하지는 않는다.</li>
</ul>
<pre><code class="language-js">var string = &#39;Hello world&#39;;
var search = &#39;l&#39;;
var count = 0;

// 문자열은 유사 배열이므로 for 문으로 순회할 수 있다.
for(var i = 0; i &lt; string.length; i++) {
  // &#39;l&#39; 이 아니면 현 지점에서 실행을 중단하고 반복문의 증감식으로 이동한다.
  if(string[i] !== search) continue;
  count++;
}
console.log(count); // 3

// 참고로 String.prototype.match 메서드를 사용해도 같은 동작을 한다.
const regexp = new RegExp(search, &#39;g&#39;);
console.log(string.match(regexp).length);  // 3</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js - Shallow Routing]]></title>
            <link>https://velog.io/@hoho_0815/Next.js-Shallow-Routing</link>
            <guid>https://velog.io/@hoho_0815/Next.js-Shallow-Routing</guid>
            <pubDate>Sun, 07 Aug 2022 12:51:03 GMT</pubDate>
            <description><![CDATA[<h1 id="dynamic-routes">Dynamic Routes</h1>
<p>[slug] 값은 어떻게 활용할 것 인가? - pages/category/[slug].js</p>
<ul>
<li><strong>slug</strong> 값에 따라서 우리가 원하는 페이지가 다르게 보여져야 합니다.</li>
</ul>
<br>

<h2 id="1-userouter">1. useRouter</h2>
<ul>
<li>Next.js 에서 제공하고 있는 라이브러리</li>
</ul>
<blockquote>
<p>import { useRouter } from &#39;next/router&#39; // 선언
const router = useRouter(); 
const { slug } = router.query;</p>
</blockquote>
<br>

<h3 id="11-categoryjs">1.1 category.js</h3>
<pre><code class="language-js">import { useRouter } from &quot;next/router&quot;;

const CategorySlug = () =&gt; {
    const router = useRouter()
    const { slug } = router.query

    return (
        &lt;h1&gt;Category {slug}&lt;/h1&gt;
    )
}

export default CategorySlug;</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/5fd44d36-36f5-49a8-9d7c-396d9603d792/image.gif" alt=""></p>
<blockquote>
<p><strong>query</strong> 가 있다면 ?
/category/food?from=event
{&quot;slug&quot; : &quot;food&quot;, &quot;from&quot; : &quot;event&quot; }</p>
</blockquote>
<hr>
<h2 id="2-다중-슬러그">2. 다중 슬러그</h2>
<h3 id="21">2.1</h3>
<ul>
<li>pages/[username]/[info].js</li>
<li>const { username, info } = router.query</li>
</ul>
<br>

<h3 id="212-폴더-구조">2.1.2 폴더 구조</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/2a56ef8e-20be-4c6a-8aed-329835a2f84d/image.png" alt=""></p>
<br>

<h3 id="213-infojs">2.1.3 info.js</h3>
<pre><code class="language-js">import { useRouter } from &quot;next/router&quot;;

const userInfo = () =&gt; {
    const router = useRouter()
    const { username, info } = router.query

    return (
        &lt;h1&gt;Username&#39;s {username} {info}&lt;/h1&gt;
    )
}

export default userInfo;</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/87d06d95-e84f-400f-a834-af229f8cd0d0/image.gif" alt=""></p>
<hr>
<h2 id="3-slug-는-배열">3. slug 는 배열</h2>
<ul>
<li>pages/cart/[...slug].js</li>
<li>const { slug } = router.query</li>
</ul>
<br>

<h3 id="311-폴더-구조">3.1.1 폴더 구조</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/0800c32f-38a0-4e2b-a271-dacac5a372eb/image.png" alt="">
<img src="https://velog.velcdn.com/images/hoho_0815/post/b324f38a-4394-4325-bb71-97f8e26ecb95/image.png" alt=""></p>
<hr>
<h2 id="4-옵셔널-slug">4. 옵셔널 slug</h2>
<ul>
<li>저번 포스팅 처럼 <code>pages/cart/[...slug].js</code> 를 <strong>/cart</strong> 로 접근하면 404가 나옵니다.</li>
<li>이유는 해당 폴더의 index.js 가 없기 때문입니다.</li>
<li>하지만 <code>pages/cart/[[...slug]].js</code> 해주면 존재하지 않아도 기본 페이지가 생성 됩니다.</li>
</ul>
<br>

<h3 id="41-폴더-구조">4.1 폴더 구조</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/0b651689-b1c1-4947-acd4-2c89eb82d9d1/image.png" alt="">
<img src="https://velog.velcdn.com/images/hoho_0815/post/fd40671d-3946-428d-b81d-afabee651156/image.png" alt=""></p>
<hr>
<h2 id="5-routerpush">5. router.push</h2>
<p>router 를 사용하면서 페이지 이동이 가능 합니다.</p>
<h3 id="51-코드">5.1 코드</h3>
<pre><code class="language-js">import Link from &quot;next/link&quot;;
import { useRouter } from &quot;next/router&quot;;

const CartSlug = () =&gt; {
    const router = useRouter()
    const { data } = router.query

    return (
        &lt;&gt;
            &lt;h1&gt;CartSlug {JSON.stringify(data)}&lt;/h1&gt;
            &lt;Link href=&quot;/cart/2022/08/07&quot;&gt;
                &lt;a&gt;2022년 8월 7일로&lt;/a&gt;
            &lt;/Link&gt;
            &lt;button onClick={() =&gt; router.push(&#39;/cart/2022/08/10&#39;)}&gt;2022년 8월 10일로&lt;/button&gt;
        &lt;/&gt;
    )
}

export default CartSlug;</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/9c2f2df7-7221-4e52-9ed4-6e235e88c273/image.gif" alt=""></p>
<hr>
<h2 id="6-shallow-routing">6. Shallow Routing</h2>
<ul>
<li>Next.js 에서 페이지를 그릴 때는 pre-render 를 우선적으로 고려 합니다.<blockquote>
<p>getServerSideProps / getStaticProps 등을 다시 실행시키지 않고,
현재 상태를 잃지 않고 <strong>url</strong> 을 바꾸는 방법</p>
</blockquote>
</li>
</ul>
<p>예를 들어, 상태는 유지하면서 url 만 바꾸고 싶은 경우 ?</p>
<ul>
<li>사용자가 어떤 동작을 했고, 그 기록을 <strong>query</strong> 로 남기고 싶을 때</li>
<li><blockquote>
<p><strong>query</strong> 로 남기면 사용자가 새로고침을 해도 유지 됩니다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="61-url-을-바꾸는-3가지-방식">6.1 url 을 바꾸는 3가지 방식</h3>
<ul>
<li>location.replace(&#39;url&#39;) : 로컬 state 유지 안됨 ( 리렌더 )</li>
<li>router.push(url) : 로컬 state 유지 / data fetching 은 일어남</li>
<li>router.push(url, as, { shallow : true }) : 로컬 state 유지 / data fetching X</li>
</ul>
<br>

<h4 id="611-locationreplace">6.1.1 location.replace</h4>
<pre><code class="language-js">import { useRouter } from &quot;next/router&quot;;
import { useState } from &quot;react&quot;;

const userInfo = () =&gt; {
    const router = useRouter()

    const [clicked, setClicked] = useState(false)
    const { status = &#39;initial&#39;} = router.query

    return (
        &lt;&gt;
            &lt;h1&gt;My Info&lt;/h1&gt;
            &lt;h1&gt;click :  {String(clicked)}&lt;/h1&gt;
            &lt;h1&gt;Status : {status} &lt;/h1&gt;
            &lt;button onClick={() =&gt; {
                alert(&#39;change&#39;)
                setClicked(true)
                location.replace(&#39;/username/info?status=change&#39;)
            }}&gt;Edit : (replace)&lt;/button&gt;
        &lt;/&gt;
    )
}

export default userInfo;</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/8d2a720a-2cd5-441c-9e9c-30c1c45b140d/image.gif" alt=""></p>
<ul>
<li>버튼을 누르면 <code>true -&gt; false</code> 가 되는 이유는</li>
<li><strong>url</strong> 을 바꾸기 위해서 페이지를 새로 가져왔기 때문 입니다.</li>
</ul>
</br>

<h4 id="612-routerpush">6.1.2 router.push</h4>
<pre><code class="language-js">import { useRouter } from &quot;next/router&quot;;
import { useState } from &quot;react&quot;;

const userInfo = () =&gt; {
    const router = useRouter()

    const [clicked, setClicked] = useState(false)
    const { status = &#39;initial&#39;} = router.query

    return (
        &lt;&gt;
            &lt;h1&gt;My Info&lt;/h1&gt;
            &lt;h1&gt;click :  {String(clicked)}&lt;/h1&gt;
            &lt;h1&gt;Status : {status} &lt;/h1&gt;
            &lt;button onClick={() =&gt; {
                alert(&#39;change&#39;)
                setClicked(true)
                router.push(&#39;/username/info?status=change&#39;)
            }}&gt;Edit : (push)&lt;/button&gt;
        &lt;/&gt;
    )
}

export async function getServerSideProps(){
    console.log(&#39;server&#39;)

    return {
        props : {},
    }
}

export default userInfo;</code></pre>
<ul>
<li>로컬의 상태는 유지되지만, 서버에서 지속적인 data fetching 은 발생 합니다.
<img src="https://velog.velcdn.com/images/hoho_0815/post/9e621ee3-5623-41f3-9236-2c080f612796/image.gif" alt=""></li>
</ul>
<br>

<h4 id="613-shallow">6.1.3 shallow</h4>
<pre><code class="language-js">import { useRouter } from &quot;next/router&quot;;
import { useState } from &quot;react&quot;;

const userInfo = () =&gt; {
    const router = useRouter()

    const [clicked, setClicked] = useState(false)
    const { status = &#39;initial&#39;} = router.query

    return (
        &lt;&gt;
            &lt;h1&gt;My Info&lt;/h1&gt;
            &lt;h1&gt;click :  {String(clicked)}&lt;/h1&gt;
            &lt;h1&gt;Status : {status} &lt;/h1&gt;
            &lt;button onClick={() =&gt; {
                alert(&#39;change&#39;)
                setClicked(true)
                router.push(&#39;/username/info?status=change&#39;, undefined, {shallow : true})
            }}&gt;Edit : (push)&lt;/button&gt;
        &lt;/&gt;
    )
}

export async function getServerSideProps(){
    console.log(&#39;server&#39;)

    return {
        props : {},
    }
}

export default userInfo;</code></pre>
<ul>
<li>로컬의 값, URL 전부 바뀌고 server 또한 불리지 않습니다.</li>
<li>정말 아무것도 안바뀌고 url 만 바뀐 상황입니다.</li>
<li>물론 동일한 페이지에서 <strong>query</strong> 만 바뀌는 상황만 입니다.</li>
</ul>
<hr>
<h2 id="간단한-예시">간단한 예시</h2>
<h3 id="indexjs">index.js</h3>
<pre><code class="language-js">{noticeList &amp;&amp;
     noticeList.map((item, index) =&gt; {
           return (
                  &lt;Items
                     key={index}
                     onClick={() =&gt; router.push(
                          {pathname : `/setting/notice/[id]`, 
                           query : { id : `${item.notice_id}` }})}
                  &gt;</code></pre>
<h3 id="idjs">[id].js</h3>
<pre><code class="language-js"> const router = useRouter()
 const id = Number(router.query.id);</code></pre>
<ul>
<li>위와 같은 방법으로 변수에 값을 담을 수 있습니다.</li>
</ul>
<hr>
<h2 id="정리">정리</h2>
<ul>
<li>Shallow Routing 은 Dynamic Routes -&gt; slug 를 활용하는 방법</li>
<li>다중 slug -&gt; [user]/[info].js/ , [...slug].js</li>
<li>옵셔널 slug -&gt; [[...slug]].js</li>
<li>Shallow Routing -&gt; router.push(url, as, {shallow : true })</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://fastcampus.co.kr/dev_online_nextjs">https://fastcampus.co.kr/dev_online_nextjs</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js - Routing]]></title>
            <link>https://velog.io/@hoho_0815/Next.js-Routing-09u5wy9z</link>
            <guid>https://velog.io/@hoho_0815/Next.js-Routing-09u5wy9z</guid>
            <pubDate>Thu, 04 Aug 2022 14:51:09 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs---routing">Next.js - Routing</h1>
<p>Next.js 의 Router 는 file-system 기반</p>
<ul>
<li>file-system : 파일을 만들면 그 즉시 라우터로 인지되고 주소가 맵핑이 됩니다.</li>
<li>pages/ </li>
<li>src/pages/</li>
</ul>
<blockquote>
<p>리액트에서는 별도의 Router 를 제공하지 않기 때문에 별도의 라이브러리를 사용해야 하지만, Next.js 는 기본적으로 제공을 합니다.</p>
</blockquote>
<hr>
<h2 id="pages-or-srcpages-둘-중-우선순위는">pages/ OR src/pages 둘 중 우선순위는?</h2>
<ul>
<li>우선순위는 <strong>pages/</strong> 가 우선 입니다.</li>
</ul>
<h3 id="pagesindexjs">pages/index.js</h3>
<pre><code class="language-js">import Link from &#39;next/link&#39;
import { useEffect, useState } from &#39;react&#39;

export async function getStaticProps(){
  console.log(&#39;server&#39;)

  return {
    props : {time : new Date().toISOString()}
  }
}

export default function Home() {

  return (
    &lt;div&gt;
      &lt;h1&gt;&lt;Link href=&quot;/ssg&quot;&gt;SSG로 - pages -&lt;/Link&gt;&lt;/h1&gt;
      &lt;h1&gt;&lt;Link href=&quot;/isr&quot;&gt;ISR로 - pages -&lt;/Link&gt;&lt;/h1&gt;
    &lt;/div&gt;
  )
}</code></pre>
<br>

<h3 id="srcpagesindexjs">src/pages/index.js</h3>
<pre><code class="language-js">import Link from &#39;next/link&#39;
import { useEffect, useState } from &#39;react&#39;

export async function getStaticProps(){
  console.log(&#39;server&#39;)

  return {
    props : {time : new Date().toISOString()}
  }
}

export default function Home() {

  return (
    &lt;div&gt;
      &lt;h1&gt;&lt;Link href=&quot;/ssg&quot;&gt;SSG로&lt;/Link&gt;&lt;/h1&gt;
      &lt;h1&gt;&lt;Link href=&quot;/isr&quot;&gt;ISR로&lt;/Link&gt;&lt;/h1&gt;
    &lt;/div&gt;
  )
}</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/19dcb2c1-6696-475e-9f9e-2398f5fafb86/image.png" alt=""></p>
<ul>
<li>화면에는 <strong>pages</strong> 의 index.js 가 나옵니다.</li>
</ul>
<blockquote>
<p>즉, pages 폴더가 있다면, src 폴더 안의 pages 는 무시가 됩니다.</p>
</blockquote>
<hr>
<h2 id="nested-routes">Nested routes</h2>
<ul>
<li>pages/product/first-item.js =&gt; /product/first-item</li>
<li>pages/settings/my/info.js =&gt; /settings/my/info</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/d4353167-4630-4d24-9ee4-91f4c208806c/image.png" alt="">
<img src="https://velog.velcdn.com/images/hoho_0815/post/5f371537-68da-4f9e-9f1c-4b090dfcba51/image.png" alt=""></p>
<br>

<h3 id="tip-nextjs-는-절대-경로-접근이-가능-합니다">Tip, next.js 는 절대 경로 접근이 가능 합니다.</h3>
<ul>
<li>파일 깊이가 깊어질수록 ../ 을 하는 일이 많아집니다.</li>
<li>하지만 아래 설정을 하면 손쉽게 절대 경로로 접근이 가능 합니다.</li>
</ul>
<h4 id="jsconfigjson">jsconfig.json</h4>
<pre><code class="language-js">{
    &quot;compilerOptions&quot; : {
        &quot;baseUrl&quot; : &quot;src&quot;
    }
}</code></pre>
<h4 id="first-itemjs">first-item.js</h4>
<pre><code class="language-js">// import Hello from &#39;../../src/components/Hello&#39;; // 기존
import Hello from &#39;/src/components/Hello&#39;;

const first_item = () =&gt; {
    return (
        &lt;&gt;
            &lt;h1&gt;first_item&lt;/h1&gt;
            &lt;Hello/&gt;
        &lt;/&gt;
    )
}

export default first_item;</code></pre>
<ul>
<li>위의 이미지 처럼 동일한 결과가 나옵니다.</li>
</ul>
<hr>
<h2 id="nested-routes-주의할점">Nested routes 주의할점</h2>
<p>/product/first-item 까지는 접근이 가능하지만, product 로는 접근이 안될까?</p>
<blockquote>
<p>정답은 그냥 /product 를 입력하면 404 가 나옵니다.
<img src="https://velog.velcdn.com/images/hoho_0815/post/161699af-135e-4f86-bae1-d94e19485ee9/image.png" alt=""></p>
</blockquote>
<ul>
<li>product 에 바로 접근하고 싶으면 해당 <strong>index.js</strong> 가 있어야 합니다.
<img src="https://velog.velcdn.com/images/hoho_0815/post/25be509b-fada-4fbb-9ffc-36ba0b373455/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/6c29d609-111f-46ca-83c0-b5b2537e61a2/image.png" alt=""></p>
<hr>
<h2 id="slug">slug</h2>
<ul>
<li>pages/category/[slug].js =&gt; /category/:slug (ex. /category/food )</li>
<li>pages/[username]/info.js =&gt; /:username/info (ex. /hyunho/info )</li>
</ul>
<blockquote>
<p>대괄호를 하고 어떤 값을 넣으면 그 값의 와일드카드처럼 동작을 합니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/0197ef63-e44d-4c3a-bfb8-c4f9b7d00d1c/image.gif" alt=""></p>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/a9dbe425-fb93-47aa-8799-0de2d5dfa681/image.png" alt=""></p>
<ul>
<li>지금은 slug 를 한 뎁스만 사용했지만 <strong>[...slug].js</strong> 하면 </li>
<li><blockquote>
<p>(ex. /cart/2022/06/24) 무한하게 접근 가능 합니다.</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="정리">정리</h2>
<ul>
<li>Router -&gt; File system 을 토대로 구현</li>
<li>pages/ 혹은 src/pages -&gt; pages/ 가 우선순위, 하나만 가능</li>
<li>프로젝트 설정 -&gt; jsconfig.json(절대경로)</li>
<li>Slug -&gt; 다양한 위계의 Dynamic 제공</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://fastcampus.co.kr/dev_online_nextjs">https://fastcampus.co.kr/dev_online_nextjs</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js - Data Fetching]]></title>
            <link>https://velog.io/@hoho_0815/Next.js-Data-Fetching</link>
            <guid>https://velog.io/@hoho_0815/Next.js-Data-Fetching</guid>
            <pubDate>Wed, 03 Aug 2022 15:53:43 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs---data-fetching">Next.js - Data Fetching</h1>
<p>데이터 가져오기 
-&gt; 화면에 무엇인가를 그리려면 어디선가 <strong>데이터를 가져와야</strong> 합니다.</p>
<hr>
<h2 id="1-ssr-server-side-render">1. SSR (Server Side Render)</h2>
<p>페이지에 대한 요청이 있을 때마다 서버에서 페이지를 만들어 반환 합니다. 서버에서 매번 연산을 해야하며 캐시를 사용하는 것이 상대적으로 어렵기 때문에 SSG에 비해 느립니다. 하지만 항상 최신의 정보를 보여주어야하는 경우, SSR를 사용하는 것이 좋다.</p>
<p>(프론트)서버에서 HTML 파일을 만들어서 보내기 때문에 CSR에 비해 사용자가 더 빠르게 화면을 인식할 수 있습니다. 하지만 이벤트 등 페이지의 동작을 위해서는 hydrate라는 과정을 통해서 JS 코드가 실행되어야 합니다.</p>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/c338faaf-7026-4003-81da-e374ffbb66bb/image.jpeg" alt=""></p>
<ul>
<li><strong>서버</strong>가 그립니다. </li>
<li>그린다 : 데이터를 가져와서 나타낸다.</li>
</ul>
<blockquote>
<p>즉, 서버가 데이터를 가져와서 그린다.</p>
</blockquote>
<br>

<h3 id="12-ssr-을-담당하는-함수">1.2 SSR 을 담당하는 함수</h3>
<blockquote>
<p>getServerSideProps()</p>
</blockquote>
<p>Next.js에서 SSR을 사용하기 위해서는 페이지에서 getServerSideProps() 를 통해 데이터를 받아와야 합니다.</p>
<ul>
<li>빌드타임에만 실행되는 getStaticProps()와는 달리 getServerSideProps()는 페이지에 대한 요청이 있을 때마다 실행된다.</li>
</ul>
<h4 id="예시-1">예시 1</h4>
<pre><code class="language-js">function Page({ data }) {
  // 데이터를 통해 페이지 렌더링...
}

export async function getServerSideProps() {
  // 페이지를 요청할 때마다 매번 실행된다.
    // 데이터를 받아온다.
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page</code></pre>
<h4 id="예시-2">예시 2</h4>
<pre><code class="language-js">export async function getServerSideProps(){
  console.log(&#39;server&#39;)
  return {
    props : {time : new Date().toISOString()}
  }
}

export default function Home({time}) {
  return (
    &lt;div className={styles.container}&gt;
      {time}
    &lt;/div&gt;
  )
}</code></pre>
<ul>
<li>위 코드를 실행시키면 터미널에서 <strong>server</strong> 라는 로그가 지속적으로 발생합니다.</li>
<li>이유는 서버에서 그리기 때문 입니다. </li>
<li>화면 콘솔창에는 찍히지 않습니다!!</li>
<li>페이지에서 props 를 받아서 자유롭게 사용 할 수 있습니다.</li>
</ul>
<blockquote>
<p>즉, <strong>getServerSideProps</strong> 는 서버에서 데이터를 가져왔고, 
그것을 페이지에다가 props 로 전달한 것 입니다. </p>
</blockquote>
<hr>
<h2 id="2-csr--client-side-render-">2. CSR ( Client Side Render )</h2>
<p>Next.js 에서 CSR을 사용하는 경우는 두가지로 나누어볼 수 있다.</p>
<ol>
<li>url을 입력을 통해 pre-rendering 된 페이지를 받고 useEffect()를 통해 데이터를 추가로 불러오는 경우</li>
<li><code>&lt;Link/&gt;</code> 나 router.push()를 통해 페이지 전환이 일어나는 경우이다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/bc910d2d-3c19-4379-b905-606331e435d7/image.jpeg" alt=""></p>
<ul>
<li>SSR 과 정반대로 <strong>클라이언트</strong>가 그립니다.<blockquote>
<p>즉, 클라이언트가 데이터를 가져와서 그립니다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="21-csr-을-권장하는-경우">2.1 CSR 을 권장하는 경우</h3>
<p>페이지를 pre-rendering 할 필요가 없거나, 데이터의 업데이트가 자주 일어난다면 CSR을 사용하는 것을 권장 합니다. 예를 들어 유저 대시보드 페이지는 해당 유저만을 위한 비밀 페이지이기 때문에 SEO가 필요하지 않으며 따라서 pre-rendering할 필요도 없습니다. 또한 데이터가 자주 변경되기때문에 CSR이 적합 합니다.</p>
<br>

<h3 id="22-csr-을-담당하는-함수">2.2 CSR 을 담당하는 함수</h3>
<ul>
<li>따로 존재하지 않습니다.</li>
<li>기존 React 사용법과 동일 합니다.</li>
<li>next.js 의 Link 등...</li>
</ul>
<hr>
<h2 id="3-ssg--static-site-generation-">3. SSG ( Static-Site Generation )</h2>
<p>빌드시 HTML 파일을 미리 렌더링하는 것이 SSG 입니다. 정적인 페이지에 주로 쓰이며, HTML 파일을 미리 생성하기 때문에 서버에서 매번 연산을 하지 않아도 될 뿐 아니라, 별다른 설정 없이 CDN 캐시 사용이 가능하기 때문에 SSR 보다도 훨씬 빠른 속도를 보여줍니다.</p>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/174717d3-d0bd-4db8-a090-714c6a30c854/image.jpeg" alt=""></p>
<p>SSG는 Next.js 의 기본적인 렌더링 방식 입니다. 하지만 백엔드 서버로부터 데이터를 받아서 렌더링하는 경우, 페이지에서 useEffect()를 사용한다면 url을 통한 페이지 접근시 SSG로는 데이터가 필요없는 부분만 구성하고, 데이터를 필요로하는 부분은 CSR로 렌더링하게 됩니다.</p>
<p>페이지에서 데이터를 필요로 하는 부분이 클수록 사용자가 화면을 인식하는데 시간이 오래걸리며 이는 SSG의 장점을 전혀 활용하지 못하게 되는 것을 의미 합니다.</p>
<p>이는 Next.js 에서 제공하는 페이지 단위 함수 getStaticProps()를 통해 해결할 수 있습니다.</p>
<br>

<h3 id="31-ssg-를-담당하는-함수">3.1 SSG 를 담당하는 함수</h3>
<blockquote>
<p>getStaticProps()</p>
</blockquote>
<ul>
<li>yarn dev 를 사용하는 개발환경에서는 제대로 동작하지 않습니다. (SSG 가 SSR 처럼 동작 합니다!)</li>
<li>정확하게 확인하려면 빌드를 한 후 yarn start 를 해야 합니다.</li>
<li><strong>SSG</strong> 에서는 새로고침을 해도 페이지가 변함없이 동일 합니다. ( 콘솔조차 찍히지 않습니다. )</li>
</ul>
<blockquote>
<p>yarn build 를 할 때 페이지를 미리 만들었다는 뜻 입니다.
즉, 빌드하는 타이밍에 데이터를 다 가져와서 보여줄 페이지를 static 한 페이지를 미리 생성한 것입니다.</p>
</blockquote>
<h4 id="예시-1-1">예시 1</h4>
<pre><code class="language-js">function Blog({ posts }) {
  return (
    &lt;ul&gt;
      {posts.map((post) =&gt; (
        &lt;li&gt;{post.title}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  )
}

// getStaticProps 함수는 server-side에서 build 타임에만 실행된다.
export async function getStaticProps() {
  // build 타임에 데이터를 받아온다.
  const res = await fetch(&#39;https://.../posts&#39;)
  const posts = await res.json()

  // { props: { posts } }를 반환함으로써, 
  // Blog 컴포넌트는 빌드타임에 props 로 posts를 받을 수 있다.
  return {
    props: {
      posts,
    },
  }
}

export default Blog</code></pre>
<ul>
<li>보이는 바와 같이 getStaticProps는 빌드타임에 서버로부터 데이터를 받아와 반환하고 </li>
<li>getStaticProps를 사용하는 페이지는 빌드타임에 getStaticProps 로부터 props를 받아올 수 있습니다.</li>
<li>따라서 빌드타임에 데이터에 따른 화면 구성이 가능</li>
</ul>
<h4 id="예시-2-1">예시 2</h4>
<pre><code class="language-js">export async function getStaticProps(){
    console.log(&#39;server&#39;)

    return {
    props : {time : new Date().toISOString()}
    }
}

export default function ssg({time}) {

    return (
        &lt;div&gt;
            &lt;h1&gt;{time}&lt;/h1&gt;
        &lt;/div&gt;
    )
}</code></pre>
<ul>
<li>위의 예시처럼 dev 환경에서는 새로고침하면 시간이 계속 변하지만
(SSR 처럼 node에 로그가 찍힙니다.)</li>
<li>빌드하고 배포한 후 실행하면 정적인 페이지가 만들어집니다. 
(새로고침해도 시간이 화면의 시간이 변하지 않습니다.)
<img src="https://velog.velcdn.com/images/hoho_0815/post/36f3492b-43f2-4ca4-9781-66e34c3cffe4/image.gif" alt=""></li>
</ul>
<br>

<h3 id="32-동적이지도-않고-정적인데-필요한-이유는-">3.2 동적이지도 않고 정적인데 필요한 이유는 ?</h3>
<ul>
<li>SSR 은 항상 접근 할 때 마다, 즉 새로고침 할 때 마다 서버가 동작 합니다</li>
</ul>
<blockquote>
<p>즉, 데이터를 그릴 때 마다 서버가 동작하고 
여러 사용자가 접근한다고 하면 서버의 부하가 많아집니다.</p>
</blockquote>
<ul>
<li>하지만 <strong>SSG</strong> 를 사용하면</li>
</ul>
<blockquote>
<p>정적인 페이지 한정이지만, 그 페이지는 누가 접근해도 빌드할 때 이미 만들어져있는 것을 보여주기 때문에 서버의 부하 없이 서비스를 제공 할 수 있습니다.</p>
</blockquote>
<br>

<h3 id="33-ssg-페이지의-데이터가-변경되면---revalidate">3.3 SSG 페이지의 데이터가 변경되면 ? : revalidate</h3>
<p>빌드 타임에 정적파일을 생성하기 때문에 이후 데이터 변경이 일어나도 페이지에 반영이 되지 않습니다. </p>
<blockquote>
<p>이런 문제를 해결하기 위해 getStaticProps() 에는 revalidate라는 옵션이 존재하며 초 단위로 입력할 수 있다.</p>
</blockquote>
<p>빌드를 통해 페이지가 생성된 후 revalidate 값(초)이 지나기 전 들어오는 요청에 대해서는 기존의 페이지를 반환 합니다. revalidate 값이 지나고 들어오는 최초 요청에 대해서는 기존 페이지를 반환하고 페이지를 새로 빌드 합니다. 이후 들어오는 요청에 대해서는 새로 빌드된 페이지를 반환.(반복) </p>
<blockquote>
<p>즉 revalidate에 10을 입력했다면 10초마다 재빌드 되는 것이 아니라, 10초 이후 요청이 새로 들어왔을 때 재빌드 하여 새로운 페이지를 만드는 것 입니다.</p>
</blockquote>
<pre><code class="language-js">export async function getStaticProps() {
  const res = await fetch(&#39;https://.../posts&#39;)
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js will attempt to re-generate the page:
    // - When a request comes in
    // - At most once every 10 seconds
    revalidate: 10, // 초 단위
  }
}</code></pre>
<ul>
<li>아래 ISR 에서 한번 더 나옵니다.</li>
</ul>
<hr>
<h2 id="4-isr--incremental-static-regeneration-">4. ISR ( Incremental Static Regeneration )</h2>
<ul>
<li><strong>증분 정적 사이트</strong>를 재생성 합니다.</li>
<li>재생성한다 : (특정 주기로) 데이터를 가져와서 다시 그립니다.</li>
</ul>
<blockquote>
<p>즉, (특정 주기로) 정적인 사이트의 데이터를 가져와서 다시 그린다.</p>
</blockquote>
<br>

<h3 id="41-getstaticprops--with-revalidate-">4.1 getStaticProps ( with revalidate )</h3>
<ul>
<li>revalidate 에 얼마 주기로 재생성 될지를 결정 합니다.</li>
<li>SSG 처럼 개발환경이 아닌 빌드 후 배포해서 확인 합니다.</li>
</ul>
<br>

<h4 id="isrjs">isr.js</h4>
<pre><code class="language-js">export async function getStaticProps(){
    console.log(&#39;server&#39;)

    return {
    props : {time : new Date().toISOString()},
    revalidate : 1, // 1 초
    }
}

export default function isr({time}) {

    return (
        &lt;div&gt;
            &lt;h1&gt;{time}&lt;/h1&gt;
        &lt;/div&gt;
    )
}</code></pre>
<ul>
<li>기존 SSG 는 새로고침해도 페이지의 숫자나 값이 동적으로 변하지 않습니다.</li>
<li>하지만 ISR 은 설정한 특정 주기대로 화면을 동적으로 변화시킬 수 있습니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/66d337d5-717c-4a2d-824c-5c61b93cb21c/image.gif" alt=""></p>
<ul>
<li>새로고침을 아무리해도 1초 간격으로 실행이 됩니다.</li>
</ul>
<hr>
<h2 id="정리--data-fetching-">정리 ( Data Fetching )</h2>
<ul>
<li>페이지를 그리는 방식 -&gt; 데이터를 가져와서 그린다.</li>
<li>3 + 1 -&gt; SSR / CSR / SSG / ISR</li>
<li>SSG -&gt; yarn dev 로는 SSR 처럼 동작</li>
<li>필요에 맞춰서 -&gt; SSR은 서버 부하 / SSG + ISR</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://fastcampus.co.kr/dev_online_nextjs">https://fastcampus.co.kr/dev_online_nextjs</a></li>
<li><a href="https://velog.io/@sj_dev_js/Next.js-%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B1%B0%EC%9D%98-%EB%AA%A8%EB%93%A0-%EA%B2%83">https://velog.io/@sj_dev_js/Next.js-%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B1%B0%EC%9D%98-%EB%AA%A8%EB%93%A0-%EA%B2%83</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[패스트캠퍼스] - 김민태의 React 와 Redux로 구현하는 아키텍처와 리스크 관리 (2)]]></title>
            <link>https://velog.io/@hoho_0815/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EA%B9%80%EB%AF%BC%ED%83%9C%EC%9D%98-React-%EC%99%80-Redux%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%A6%AC%EC%8A%A4%ED%81%AC-%EA%B4%80%EB%A6%AC-2</link>
            <guid>https://velog.io/@hoho_0815/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EA%B9%80%EB%AF%BC%ED%83%9C%EC%9D%98-React-%EC%99%80-Redux%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%A6%AC%EC%8A%A4%ED%81%AC-%EA%B4%80%EB%A6%AC-2</guid>
            <pubDate>Wed, 03 Aug 2022 14:25:49 GMT</pubDate>
            <description><![CDATA[<h1 id="안정적인-프로덕트를-위한-아키텍처-설계와-리스크-관리">안정적인 프로덕트를 위한 아키텍처 설계와 리스크 관리</h1>
<h2 id="1-문제는-어디서-발생하는가">1. 문제는 어디서 발생하는가?</h2>
<p>협업과 제품을 만들어나가는 과정에서</p>
<h3 id="11-프로덕트의-문제">1.1 프로덕트의 문제</h3>
<ul>
<li>Scale 이 커져가는 과정에서 주로 발생한다.(즉, 서비스의 규모가 어느정도 될 때)</li>
<li>기업은 리소스가 제한적이며, 시간이 부족하다.</li>
</ul>
<p>이는 스타트업와 일반기업 또한 크게 다르지 않다. 제한된 리소스와 부족한 시간은 둘다 같다.
그나마 차이점은, 스타트업은 시니어 엔지니어가 없는 경우가 주로 있고 실패 비용이 크게 다가오기도 한다.</p>
</br>

<h3 id="12-제한된-리소스란">1.2 제한된 리소스란</h3>
<ul>
<li>인적 자원의 부족 </li>
<li>부족한 시간</li>
</ul>
<blockquote>
<p>이를 해결하기 위해서는 역랑 한계를 <strong>인정</strong> 하고 <strong>드러내야</strong> 한다.</p>
</blockquote>
</br>

<h3 id="13-리스크를-줄이기-위한-노력">1.3 리스크를 줄이기 위한 노력</h3>
<ol>
<li>필요없는 기능 최대한 배제 -&gt; <strong>MVP</strong> 에 집중</li>
<li>클린 코드에 집착 X -&gt; <strong>동작하는 코드가 가장 가치있는 시기가 있다.</strong></li>
</ol>
<br>

<h3 id="14-mvp-란">1.4 MVP 란</h3>
<p>“Minimum Viable Product”, 즉 최소 기능 제품의 줄임말. 최소한의 기능을 가진 제품이라는 뜻이다.</p>
<p>참고 : <a href="https://www.itworld.co.kr/t/61023/%EA%B0%9C%EB%B0%9C%EC%9E%90/212179">https://www.itworld.co.kr/t/61023/%EA%B0%9C%EB%B0%9C%EC%9E%90/212179</a></p>
</br>

<h4 id="141-서비스-관점의-mvp">1.4.1 서비스 관점의 MVP</h4>
<ol>
<li>개발자가 판단한 MVP가 정답인지 의심하라.</li>
<li>직관이 통하는 세계가 존재함을 인정하라. 직관은 과학이 아님을 인정하라.</li>
<li>개발자의 역할은 직관의 실패 리스크를 최소화하며 피봇할 수 있게 지원하는 것이다.</li>
</ol>
</br>

<h4 id="142-기술-관점의-mvp">1.4.2 기술 관점의 MVP</h4>
<ol>
<li>어떤 기술이 적정기술인가?</li>
<li>최대한 포기하라, 포기할 것과 포기하지 못하는 것을 분류하고 검토하라.</li>
<li>기술보다 중요한건 속도다. <strong>언제나 서비스의 생존이 최우선이다.</strong></li>
</ol>
<hr>
<h2 id="2-웹을-설계하는-방식">2. 웹을 설계하는 방식</h2>
<h3 id="21-환경mobile이든-pc이든에-무관한-고려사항">2.1 환경(mobile이든, pc이든)에 무관한 고려사항</h3>
<ul>
<li>웹의 철학과 특징을 고려하기</li>
<li>기술이 서비스 성공의 촉매 역할이 될 수 있다.</li>
<li>모든 것이 공유될 수 있는 자원이 될 수 있다.</li>
<li>외부 서비스 연동 정보를 정리하여 관리하기</li>
</ul>
</br> 

<h3 id="22-디자인과-디테일한-uxui">2.2 디자인과 디테일한 UX/UI</h3>
<ul>
<li>신규 서비스의 어설퍼 보이는 UX는 좋은 이미지를 만들 수 없고, 가치가 하락한다.</li>
<li>발빠른 테스트와 릴리즈를 위한 아키텍처를 처음부터 고려하기</li>
<li>UX의 견고함과 기능이 경합을 벌이면 견고함을 선택하기</li>
</ul>
</br>


<h3 id="23-최신기술을-사용하기">2.3 최신기술을 사용하기</h3>
<ul>
<li>레거시 없는 서비스라는 장점</li>
<li>낮은 브라우저 버전에 목매이지 않기<blockquote>
<p>레거시는 낡은 기술이나 방법론, 컴퓨터 시스템, 소프트웨어를 말합니다.</p>
</blockquote>
</li>
</ul>
<p></br> </p>
<h3 id="24-사용자-로그를-수집하고-분석하기">2.4 사용자 로그를 수집하고 분석하기</h3>
<ul>
<li>로그는 필수, 초기부터 로그를 수집하는 것이 좋음</li>
</ul>
<hr>
<h2 id="3-웹뷰-개발을-설계하는-방식">3. 웹뷰 개발을 설계하는 방식</h2>
<p>현대의 서비스는 대게 앱을 중심으로 서비스를 운영한다.
앱은 안드로이드와 IOS 양강체제 -&gt; 2개의 환경이 제공하는 것을 통해 개발하는 것이 native app
하지만, Native app 형태로만 개발하기에는 많은 비용이 필요하기에 웹 기술을 활용한 하이브리드 형태가 많이 시도되고 발전되어 왔다.</p>
<blockquote>
<p>대부분의 앱은 네이티브 앱 아키텍처에 기반한 웹 기술을 섞어서 사용하고 있다. 
그 중 하나가 웹 뷰</p>
</blockquote>
<br>

<h3 id="31-네이티브-앱-패키징-아키텍처">3.1 네이티브 앱 패키징 아키텍처</h3>
<ol>
<li>네이티브 컨테이너 + 단일 웹뷰</li>
</ol>
<ul>
<li>앱스토어 규약 위반 가능성, 네이티브 기능을 탑재해야 함</li>
<li>모바일 웹 채널을 운영하고 있고 <strong>빠르게 앱을 출시하기를 원할 경우</strong> 유용
ex) 푸시, 카메라, 네이티브 인증(페이스 타임, 지문 인식 등)</li>
</ul>
<ol start="2">
<li>네이티브 + 멀티 웹뷰</li>
</ol>
<ul>
<li>웹 뷰간 <strong>데이터 교환 방법을 초기부터 고안</strong>해야 함</li>
<li>앱에 저장소를 만들고 웹 뷰에게 인터페이스를 제공</li>
</ul>
<ol start="3">
<li>네이티브 + RN</li>
</ol>
<ul>
<li><strong>변화가 많은 지면은 RN 으로 개발, 그 외의 지면은 네이티브 개발</strong></li>
<li>웹뷰 개발 시 존재할 수 있는 사용성 관련 이슈를 방지</li>
<li>역량 있는 네이티브 개발자 필요</li>
</ul>
<br>

<h3 id="32-앱-패키징-아키텍처와-무관한-고려-사항">3.2 앱 패키징 아키텍처와 무관한 고려 사항</h3>
<ol>
<li>네이게이션 룰을 확립</li>
</ol>
<ul>
<li>웹 페이지는 각각의 URL이 존재하지만 네이티브에서는 그렇지 않다.</li>
<li>깊이가 깊은 화면에 직접 접근할 수 있는 방법을 초기에 설계해야 함(Deep Link)<blockquote>
<p>사용자가 어떤 상황에서도 direct 로 접근 할 수 있는 deep link 를 모든 화면에 설계 하는 것이 좋다.</p>
</blockquote>
</li>
</ul>
<br>

<ol start="2">
<li>공개용 웹뷰와 내부용 웹뷰를 분리</li>
</ol>
<ul>
<li>URL이 노출될 경우 보안상 문제가 생길 위험이 있는지 고려하여 웹뷰를 분리</li>
</ul>
<br>

<ol start="3">
<li>보안을 고려</li>
</ol>
<ul>
<li>API 연동 토큰 및 앱 메타 정보 등 서버가 필요로하는 정보를 어떻게 관리할 것 인가</li>
</ul>
<br>

<ol start="4">
<li>개발환경을 구축</li>
</ol>
<ul>
<li>웹뷰 vs 브라우저, 시뮬레이터 vs 실기기의 차이점이 존재함을 인지</li>
<li>개발 단계에서 개발자가 경험할 수 있는 환경을 미리 준비</li>
<li>개발자간 쉽게 방법을 공유할 수 있도록 문서화하고 변경사항을 업데이트</li>
</ul>
<br>

<ol start="5">
<li>런타임 오류를 수집</li>
</ol>
<ul>
<li>특정 기기에서 발생하는 오류일 경우 개발자가 발견하기 어려움</li>
<li>고객 입장에서 개발팀이 원하는 수준의 리포팅을 하는 것은 현실적으로 불가능</li>
</ul>
<br>

<ol start="6">
<li>캐싱을 적극적으로 활용</li>
</ol>
<ul>
<li>모바일 특성상 네트워크 상태가 불안정한 경우에도 동일한 사용자 경험을 제공</li>
<li>프리젠테이션 컴포넌트는 독립적으로 운영</li>
<li>아키텍처를 변경해야 할 여지가 있으므로 충분한 가치가 있는 작업인지 신중히 고려</li>
<li>웹뷰의 생명주기를 알 수 있는 인터페이스 설계
ex) 웹뷰가 캐싱된 데이터로 렌더할지 데이터 페칭이 필요한지 여부를 네이티브에서 제공</li>
</ul>
<hr>
<h2 id="4-신규-개발-관점에서의-리스크">4. 신규 개발 관점에서의 리스크</h2>
<h3 id="41-리스크-종류">4.1 리스크 종류</h3>
<h3 id="411-커뮤니케이션">4.1.1 커뮤니케이션</h3>
<p>무엇이 문제인가 ?</p>
<ul>
<li>회의는 커뮤니케이션의 종료가 아닌 시작이다.</li>
<li>문서를 보고 이해했다는 피드백은 진짜 이해한 것이 아니다.</li>
<li>기획자, 디자이너, 테스트, 개발자는 생각하는 방식이 다르며 이는 자연스러운 것이다.</li>
</ul>
<p>일반적인 개발 진행</p>
<blockquote>
<p>브레인스토밍 -&gt; 기획 -&gt; 디자인 &amp; 백엔드 개발 -&gt; 프론트앤드 개발 -&gt; QA -&gt; 릴리즈</p>
</blockquote>
<p>즉, 같은 문제에 대한 다른 이해는 자연스럽다는 것을 이해하는 것이 문제 해결의 시작이다.
<strong>그러나 이해한다고 해서 모든 문제가 해결되는 것은 아니다.</strong></p>
<br>

<h3 id="412-해결책">4.1.2 해결책</h3>
<h4 id="1-프로젝트-사전을-만들고-지속적으로-운영하며-공유">1. 프로젝트 사전을 만들고 지속적으로 운영하며 공유</h4>
<blockquote>
<p>프로젝트 사전?</p>
</blockquote>
<ol>
<li>압축된 용어는 의미를 포괄 </li>
</ol>
<p>-&gt; 전문적인 일을 할수록 압축된 용어로 커뮤니케이션 비용을 줄인다.
2. 합의를 이루어 용어와 의미의 관계를 1:1 로 만든 사전을 만들어 운영
-&gt; 사전에 당연해 보이는 용어조차 생략해선 안되며 모든 용어가 존재해야 한다.</p>
<br>

<h4 id="2-프로토타입을-만들어라--작동-시켜라">2. 프로토타입을 만들어라 ( 작동 시켜라)</h4>
<ul>
<li>정적인 것은 상상력을 자극한다. -&gt; 즉, 다양한 해석을 낳는다.</li>
<li>제품 개발 전반의 과정 중 70% 를 정적인 결과물을 기반으로 커뮤니케이션 된다.</li>
<li>수 많은 프로토타입 개발 도구가 있다. ( 적극적으로 활용 하자 )</li>
</ul>
<blockquote>
<p><strong>동작하는 제품만이 오해를 막을 수 있는 유일한 방법이다.</strong></p>
</blockquote>
<br>

<h4 id="프로토타입에-대한-오해">프로토타입에 대한 오해</h4>
<ol>
<li>프로토타입은 POC 가 아니다.<blockquote>
<p>POC ? 
새로운 프로젝트가 실제로 실현 가능성이 있는가, 효과와 효용, 기술적인 관점에서부터 검증을 하는 과정을 의미
출처: <a href="https://engineer-mole.tistory.com/35">https://engineer-mole.tistory.com/35</a> [매일 꾸준히, 더 깊이:티스토리]</p>
</blockquote>
</li>
</ol>
<ul>
<li>프로토타입에 사용한 코드를 프로덕션 코드로 가지고 가지 말아야 한다,</li>
<li><blockquote>
<p>프로토타입에 코드가 사용될 필요는 없다.</p>
</blockquote>
</li>
<li><blockquote>
<p><strong>중요한 것은 동작하는 결과물이다.</strong></p>
</blockquote>
</li>
</ul>
<br>

<ol start="2">
<li>디자인이 나온 후 프로토타입을 만든다.</li>
</ol>
<ul>
<li>프로토타입은 가능하다면 모든 단계 만들어야 한다.</li>
<li><strong>이상적이라면 프로토타입의 결과가 기획서, 디자인 이어야 한다.</strong></li>
<li><blockquote>
<p>디자인이 나왔다면 이미 프로토타입을 개발할 타이밍은 지나갔다.</p>
</blockquote>
</li>
</ul>
<br>

<ol start="3">
<li>프로토타입은 정적인 데이터로 만든다.</li>
</ol>
<ul>
<li><strong>프로토타입의 가장 빛나는 가치는 올바른 사용자 흐름 확인이다.</strong></li>
<li>화면을 정적인 데이터로 채우지 마라</li>
<li>웹앱의 데이터는 네트워크를 통해 전달되며 네이트워크는 언제나 예외의 잔치다.</li>
<li>서버 데이터를 이용하고 레이턴시를 프로토타입에 반영하라.</li>
</ul>
<blockquote>
<p>레이턴시란?
&#39;잠복&#39; 혹인 &#39;대기시간&#39; 이라는 사전적 의미를 가진다.
IT 에서는 컴퓨터가 원하는 결과물을 만들어 내기까지 발생하는 지연시간의 총합이라고 볼 수 있다.</p>
</blockquote>
<br>

<ol start="4">
<li>프로토타입은 기획과 디자인을 위한 것이다.</li>
</ol>
<ul>
<li>데이터는 구조(스펙)를 가진다.</li>
<li>구조는 UI 를 구성하는 핵심 요소이다.</li>
<li>백엔드 개발자에게 영감을 주어라</li>
</ul>
<br>

<h4 id="3-네트워크를-묘사해라">3. 네트워크를 묘사해라</h4>
<p>웹앱은 네트워크 어플리케이션이다.</p>
<ul>
<li>화면과 하면 사이, 데이터와 데이터 사이에 비동기 상황이 존재한다.</li>
<li>비동기 상황 처리의 단단함은 서비스의 품질에 직결된다.</li>
</ul>
<hr>
<h2 id="5-유지-개선-관점에서의-리스크-관리">5. 유지, 개선 관점에서의 리스크 관리</h2>
<h3 id="51-legacy">5.1 Legacy</h3>
<blockquote>
<p><strong>레거시 시스템</strong> 은 낡은 기술이나 방법론, 컴퓨터 시스템, 소프트웨어 등을 말한다. 
이는 현대까지도 남아 쓰이는 기술을 부르는 말일 수도 있지만, 더 이상 쓰이지 않더라도 현대의 기술에 영향을 주는 경우도 포함한다. 
출처 : 위키백과</p>
</blockquote>
<h3 id="52-legacy-를-대하는-자세">5.2 Legacy 를 대하는 자세</h3>
<h4 id="존중">존중</h4>
<ul>
<li>모든 코드는 릴리즈 되는 순간 레거시 코드다.</li>
<li><blockquote>
<p><strong>서비스를 생존시킨 레거시 코드는 존중받아 마땅하다.</strong></p>
</blockquote>
</li>
</ul>
<blockquote>
<p>비난 받아 마땅한 코드는 없다. 그러나 개선하기 힘든 코드는 있다.</p>
</blockquote>
<br>

<h3 id="53-개선하기-어려운-코드를-개선하기-위한-전략">5.3 개선하기 어려운 코드를 개선하기 위한 전략</h3>
<p>시각화를 하자 -&gt; 시각화 되지 않은 문제는 불만일 뿐이다.</p>
<br>

<h3 id="54-레거시-코드-분석-실패의-이유">5.4 레거시 코드 분석 실패의 이유</h3>
<ol>
<li>기술 난이도가 높은 코드</li>
</ol>
<p>-&gt; 역량 한계를 인정하고 공개한 후 함께 해결책을 찾아라</p>
<ol start="2">
<li>잘못된 구조로 규모가 커진 코드</li>
</ol>
<p>-&gt; 엔지니어의 역할은 깨끗한 코드를 깨끗하게 유지하는 것이 아니다.
-&gt; 개발자의 역할은 제품을 만드는 것이다.
-&gt; <strong>좋은 코드는 좋은 제품을 만들기 위한 요소 중 하나일 뿐, 필수 조건은 아니다.</strong></p>
<hr>
<h2 id="6-소프트웨어의-생명주기">6. 소프트웨어의 생명주기</h2>
<h2 id="61-제품의-수명은-몇년일까">6.1 제품의 수명은 몇년일까</h2>
<p>프론트엔드는 1년 이상 쓰이는 코드는 많지 않다.</p>
<br>

<h2 id="62-안정적인-프로덕트를-위한-코드-구조와-관리">6.2 안정적인 프로덕트를 위한 코드 구조와 관리</h2>
<h3 id="621-유형">6.2.1 유형</h3>
<p>-&gt; 뒤섞이면 문제가 발생한다.</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Code/Logic/Rule</li>
<li>Domain/Data/State</li>
<li>Effect</li>
</ul>
<br>

<h3 id="622-변형-주기">6.2.2 변형 주기</h3>
<ul>
<li>Design/Visual/Struct</li>
<li>Config</li>
<li><blockquote>
<p>분리가 안 되어 있으면 서버가 바뀔 때마다 코드가 새로 배포되어야 한다.</p>
</blockquote>
</li>
<li>Assets/Information</li>
<li><blockquote>
<p>약관 같은 것들도 Information에 포함이 된다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="623-오너십">6.2.3 오너십</h3>
<ul>
<li>Library</li>
<li>Framework</li>
<li>Service</li>
</ul>
<br>

<h3 id="624-위치">6.2.4 위치</h3>
<ul>
<li>Internal</li>
<li>External</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://fastcampus.co.kr/dev_red_kmt">https://fastcampus.co.kr/dev_red_kmt</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux Toolkit]]></title>
            <link>https://velog.io/@hoho_0815/Redux-Toolkit</link>
            <guid>https://velog.io/@hoho_0815/Redux-Toolkit</guid>
            <pubDate>Wed, 27 Jul 2022 12:25:53 GMT</pubDate>
            <description><![CDATA[<h1 id="redux-toolkit">Redux Toolkit</h1>
<p><a href="https://redux-toolkit.js.org/">https://redux-toolkit.js.org/</a></p>
<h2 id="사용하는-이유">사용하는 이유</h2>
<blockquote>
<p>Redux Toolkit은 Redux를 더 사용하기 쉽게 만들기 위해 Redux에서 공식 제공하는 개발도구 Redux Toolkit은 아래와 같은 Redux의 문제점을 보완하기 위해 등장 하였습니다.</p>
</blockquote>
<br>

<h2 id="기존-리덕스의-문제">기존 리덕스의 문제</h2>
<ul>
<li>저장소 구성의 복잡성</li>
<li>많은 패키지 필요성(의존성) + 미들웨어 등..</li>
<li>한 작업 시 필요한 수 많은 코드양(boilerplate)</li>
</ul>
<br>

<h2 id="redux-toolkit-설치">Redux Toolkit 설치</h2>
<pre><code class="language-html">npm
npm install @reduxjs/toolkit

yarn
yarn add @reduxjs/toolkit</code></pre>
<br>

<h2 id="기존-redux-를-이용한-카운터">기존 redux 를 이용한 카운터</h2>
<pre><code class="language-js">import &#39;./App.css&#39;;
import { createStore } from &#39;redux&#39;;
import { useSelector } from &#39;react-redux&#39;; // useSelector 를 통해 카운터가 스토어의 value 값을 가져온다
import { Provider } from &#39;react-redux&#39;; //  provider 를 통해 애플리케이션에 공급
import { useDispatch } from &#39;react-redux&#39; // 버튼을 눌렀을 때 state 값을 바꾸는 dispatch 


// 초기값
const initialState = {value : 0};

// 스토어
const store = createStore(reducer, initialState);

// 리듀서
function reducer(state, action){
  if(action.type === &#39;up&#39;){
    return {...state, value : state.value + action.step} 
    // 불변하게 코드를 다루기 위해 기존의 코드를 복제 ({...state} 부분)
  }
  return state;
}

// 버튼을 누르면 숫자가 증가하는 카운터
function Counter(){
  const dispatch = useDispatch();
  const count = useSelector(state =&gt; state.value)
  return (
    &lt;div&gt;
      &lt;button onClick={()=&gt;{
        dispatch({type : &#39;up&#39;, step : 2}); 
      }}&gt;+&lt;/button&gt;{count}
    &lt;/div&gt;
  )
}


function App() {
  return (
    &lt;Provider store={store}&gt;
      &lt;div&gt;
        &lt;Counter&gt;&lt;/Counter&gt;
      &lt;/div&gt;
    &lt;/Provider&gt;
  );
}

export default App;</code></pre>
<br>

<h3 id="지금까지는-하나의-store-안에-모든-정보를-담았다">지금까지는 하나의 store 안에 모든 정보를 담았다.</h3>
<p>하지만 프로그램이 커지면 기능별로 작은 스토어를 만들고 싶어질수 있습니다.
이러한 작은 스토어를 <code>slice</code> 라고 부르겠습니다. </p>
<blockquote>
<p>그러면 작은 스토어들을 합쳐서 
리덕스 툴킷이 리덕스가 요구하는 큰 스토어로 알아서 만들어 줍니다.</p>
</blockquote>
<br>

<h3 id="카운터라는-기능을-위한---slice">카운터라는 기능을 위한 - slice</h3>
<pre><code class="language-js">import {createSlice} from &#39;@reduxjs/toolkit&#39;; 

const counterSlice = createSlice({
  name : &#39;counter&#39;, // 슬라이스의 이름
  initialState : {value : 0}, // 스토어는 초기 값이 필요
  reducers : {
    up : (state, action) =&gt; {
      state.value = state.value + action.payload; 
      // up 타입일 때 처리해야하는 리듀서 (dispatch 역할)
    }
  }
});</code></pre>
<ul>
<li>위와 같은 작은 slice 를 모아서 하나의 큰 스토어로 만들때는 <code>configureStore</code> 사용</li>
</ul>
<br>

<h3 id="하나의-큰-스토어---configurestore">하나의 큰 스토어 - configureStore</h3>
<pre><code class="language-js">const store = configureStore({
  // 객체를 전달하고 필수적으로 reducer 전달
  reducer : {
    counter : counterSlice.reducer 
    // up을 포함하여 counterSlice 안에 들어있는 리듀서 여러가지들을 하나로 해준다.
  }
}) </code></pre>
<ul>
<li><code>counterSlice</code> 안에 있는 리듀서들이 있다면, 즉 <strong>up</strong> 말고 down 이나 여러가지가 있을 수 있는데 이것들을 하나로 합쳐서 하나로 만든 리듀서를 자동으로 만들어줍니다.</li>
<li>그렇게 만들어진 리듀서가 <code>counter</code></li>
</ul>
<br>

<h3 id="useselector-사용">useSelector 사용</h3>
<pre><code class="language-js">const count = useSelector(state =&gt; state.value) // 기존 리덕스의 useSelector

const count = useSelector(state =&gt; {
    return state.counter.value // 0
  // count 값은 counterSlice의 전달한 value 초기값
  }) </code></pre>
<br>

<h3 id="dispatch-사용">dispatch 사용</h3>
<pre><code class="language-js">function Counter(){
  const dispatch = useDispatch();
  //const count = useSelector(state =&gt; state.value) // 기존 리덕스의 useSelector
  const count = useSelector(state =&gt; {
    return state.counter.value // count 값은 counterSlice의 전달한 value 초기값
  }) 

  return (
    &lt;div&gt;
      &lt;button onClick={()=&gt;{
        // dispatch({type : &#39;up&#39;, step : 2}); 기존 리덕스
        dispatch(counterSlice.actions.up(2)) 
      }}&gt;+&lt;/button&gt;{count}
    &lt;/div&gt;
  )
}</code></pre>
<br>

<h2 id="전체-코드">전체 코드</h2>
<pre><code class="language-js">import &#39;./App.css&#39;;
import { createStore } from &#39;redux&#39;;
import { useSelector } from &#39;react-redux&#39;; // useSelector 를 통해 카운터가 스토어의 value 값을 가져온다
import { Provider } from &#39;react-redux&#39;; //  provider 를 통해 애플리케이션에 공급
import { useDispatch } from &#39;react-redux&#39; // 버튼을 눌렀을 때 state 값을 바꾸는 dispatch 

import {createSlice, configureStore} from &#39;@reduxjs/toolkit&#39;; 

const counterSlice = createSlice({
  name : &#39;counter&#39;, // 슬라이스의 이름
  initialState : {value : 0}, // 스토어는 초기 값이 필요
  reducers : {
    up : (state, action) =&gt; {
      state.value = state.value + action.payload;
    }
  }
});

const store = configureStore({
  // 객체를 전달하고 필수적으로 reducer 전달
  reducer : {
    counter : counterSlice.reducer 
    // up을 포함하여 counterSlice 안에 들어있는 리듀서 여러가지들을 하나로 해준다.
  }
}) 

function Counter(){
  const dispatch = useDispatch();
  //const count = useSelector(state =&gt; state.value) 기존 리덕스의 useSelector
  const count = useSelector(state =&gt; {
    return state.counter.value // count 값은 counterSlice의 전달한 value 초기값
  }) 

  return (
    &lt;div&gt;
      &lt;button onClick={()=&gt;{
        // dispatch({type : &#39;up&#39;, step : 2}); 기존 리덕스
        dispatch(counterSlice.actions.up(2)) 
      }}&gt;+&lt;/button&gt;{count}
    &lt;/div&gt;
  )
}


function App() {
  return (
    &lt;Provider store={store}&gt;
      &lt;div&gt;
        &lt;Counter&gt;&lt;/Counter&gt;
      &lt;/div&gt;
    &lt;/Provider&gt;
  );
}

export default App;</code></pre>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=9wrHxqI6zuM">https://www.youtube.com/watch?v=9wrHxqI6zuM</a></li>
<li><a href="https://redux-toolkit.js.org/">https://redux-toolkit.js.org/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[지금 시작하는 프론트엔드 개발자를 위한 조언_조은]]></title>
            <link>https://velog.io/@hoho_0815/%EC%A7%80%EA%B8%88-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%A1%B0%EC%96%B8%EC%A1%B0%EC%9D%80</link>
            <guid>https://velog.io/@hoho_0815/%EC%A7%80%EA%B8%88-%EC%8B%9C%EC%9E%91%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%A1%B0%EC%96%B8%EC%A1%B0%EC%9D%80</guid>
            <pubDate>Sun, 17 Jul 2022 12:50:00 GMT</pubDate>
            <description><![CDATA[<h1 id="지금-시작하는-프론트엔드-개발자를-위한-조언">지금 시작하는 프론트엔드 개발자를 위한 조언</h1>
<blockquote>
<p>서적을 읽고 내용과 개인 생각을 정리한 글 입니다.</p>
</blockquote>
<hr>
<h2 id="1-학습--이론과-실전">1. 학습 : 이론과 실전</h2>
<p>프론트엔드 를 시작하려는 많은 개발자들이 커리어 로드맵을 따라 HTML, CSS, JS 를 먼저 배워야만 개발을 시작 할 수 있다고 생각 한다.
-&gt; 물론 언어적 특성과 문법을 아는 것은 개발을 하는데 굉장히 큰 도움이 된다.
( 나도 그랬다... 하고 싶은데 방향을 못 잡아서 이런거 저런거 보다 언어 배우기 부터 했었다.)</p>
<blockquote>
<p>하지만 그것이 개발의 전부는 아니다.</p>
</blockquote>
<br>

<h3 id="11-개발자로서-개발을-학습-할-때-두-가지의-영역">1.1 개발자로서 개발을 학습 할 때 두 가지의 영역</h3>
<h4 id="111-제품을-만드는-영역">1.1.1 제품을 만드는 영역</h4>
<blockquote>
<p>말 그대로 제품을 만들어내는 능력</p>
</blockquote>
<ul>
<li>스펙을 분석해서 적절한 수준의 기술 스택을 선택하여 만들어내서 어딘가에 가치를 만드는 것
ex) 개인 블로그를 누구는 워드프레스, 누군가는 React 를 사용해서 블로그를 만든다.</li>
</ul>
<p>이 영역에서 가장 중요하다고 생각 하는 것은 <strong>&#39;문제를 해결하는 능력&#39;</strong> 이라고 생각 한다.</p>
<ul>
<li>만들어나가는 과정에서 다양한 문제들을 직면하고, 하나씩 해결해나가면서 제품을 만든다.</li>
<li>이게 중요한 이유는 특히 프론트엔드 개발자들은 유저들이 사용하는 제품을 만드는 것이 주된 업무이기 때문이다. </li>
</ul>
<blockquote>
<p>만약 <strong>이론을 아무리 많이 알고 있어도 제품을 만들 수 없다면</strong> 능력을 제대로 활용하기 있다고 보기 어렵고, 오히려 이론을 완벽히 이해했다고 보기 어려운 상태일 수도 있다.</p>
</blockquote>
<br>

<h4 id="112-원리를-이해하는-영역">1.1.2 원리를 이해하는 영역</h4>
<blockquote>
<p>원리를 이해하는 영역은 내가 만든 코드, 혹은 다른 사람이 만든 코드가 어떻게 동작하는지
ex) &#39;자바스크립트 엔진이 어떻게 동작하는가&#39;, &#39;렌더링 엔진은 어떻게 동작하는가&#39; 등</p>
</blockquote>
<p>원리를 이해하는 영역을 모른다고 제품을 만들지 못하는 것은 아니지만,
-&gt; <strong>좋은 제품을 만들기 위해서는 원리를 이해하고 있어야 한다.</strong></p>
<p>원리를 이해해야 디버깅하기 좋은코드, 유지보수 하기 좋은 코드, 성능이 좋은 코드가 나온다.
-&gt; 무엇보다 다른 사람의 코드를 리뷰 할 때도 명확한 이유를 바탕으로 리뷰할 수 있다.
<br></p>
<h3 id="위의-두-가지-영역은-뗄-수-없는-관계다">위의 두 가지 영역은 뗄 수 없는 관계다.</h3>
<p>개발자들에게 위의 영역들은 뗄 수 없는 관계임에도, </p>
<ul>
<li>많은 개발자들이 원리에만 치우쳐 제품을 만들지 않거나</li>
<li>제품에만 치우쳐 원리를 이해하지 못하는 상황이 종종 존재한다.</li>
</ul>
<blockquote>
<p>위와 같은 상황이되면, 프로젝트는 많이 해봤지만 실속은 부족한 사람이 될 수 있고, 
지식은 많지만 경험이 적은 사람이 될 수 있다.</p>
</blockquote>
<hr>
<h2 id="12-솔루션">1.2 솔루션</h2>
<p>제품을 만드는 것만 초점을 맞추다보면 &#39;이 코드가 왜 동작하는지 모르지만 어쨌든 동작은 하는 상태&#39; 가 완성된다.</p>
<p>이를 방지하기 위해서는</p>
<ul>
<li>개발을 하다가 원리가 이해되지 않았던 부분을 키워드별로 정리하고, 프로젝트가 끝나면 블로그나 개별적으로 정리해서 발행하는 습관을 들이면 좋다.</li>
</ul>
<hr>
<h2 id="2-학습--선택과-집중">2. 학습 : 선택과 집중</h2>
<p>이제 막 개발 공부를 시작했다면, 배워야 할 내용이 많다.</p>
<blockquote>
<p>이 말은 개발 시장이 성숙해졌다는 증거이기도 하지만, 
그 만큼 수준 높은 개발자를 요구한다는 것 이다.</p>
</blockquote>
<p>최근 개발을 배우는 학생들에게서 공통적으로 보이는 것은 <strong>조급함</strong> 이며, 굉장히 많은 내용을 <strong>한 번에 습득</strong> 하려다가 중요한 지식을 습득하지 못하는 경우를 많이 본다.</p>
<p>예를 들어, 자바스크립트가 어떻게 동작하는가에 대한 디테일한 지식은 지금 단계의 여러분에게 필요하지 않을 수 있다.</p>
<ul>
<li>오히려, 당장 코드 한 줄이라도 쳐보면서 친해지는 과정을 거치고</li>
<li>버그가 나도 당황하지 않고 에러 로그를 보는 습관을 들이거나</li>
<li>제품 하나가 돌아가기 위해 어떤 일을 해야 하는지 파악하는 등의 일들이 우선시 되야 한다고 생각 한다.</li>
</ul>
<blockquote>
<p><strong>처음부터 너무 많은 지식을 습득해야 할 것 같다고 지레 겁먹지 말자.</strong>
-&gt; 개발에서는 적어도 사용 사례를 이해하고 원리를 이해했을 때 더 이해가 잘된다고 생각하기 때문에, 개발에서의 학습 방법은 지금 내가 프로젝트에서 사용하고 있는 기술 중 모르는 것을 중점적으로 공부하자!</p>
</blockquote>
<hr>
<h2 id="3-비전공자--cs-지식에-대해">3. 비전공자 : CS 지식에 대해</h2>
<p>만약 컴퓨터공학을 전공하지 않았다면 항상 &#39;내가 비전공자 라서&#39; 라는 생각이 들 수 있다.
-&gt; 어떻게 보면 당연하다. 전공을 한 사람이 개발을 잘할 가능성이 높다.</p>
<p><strong>역으로 전공자라면 다른 전공자들은 다 잘하는 것 같은데 유독 나만 못하는게 아닌가, 라는 생각이 들 수 있다.</strong></p>
<h3 id="31-cs-지식은-어떻게-공부할까요-">3.1 CS 지식은 어떻게 공부할까요 ?</h3>
<p>기초 CS 지식을 다루고 있는 책은 많다. </p>
<ul>
<li>&lt;1일 1로그 100일 완성 IT 지식&gt;</li>
<li>&lt;한 권으로 읽는 컴퓨터 구조와 프로그래밍&gt;</li>
</ul>
<p>문제 해결 능력을 키우기 위해서는 코드를 많이 작성하는 것도 중요하지만, 문제와 계속 마주하며 친해지는 것도 중요하다.</p>
<ul>
<li>&lt;알고리즘 문제 해결 전략&gt;</li>
<li>&lt;코딩 인터뷰 완전 분석&gt;</li>
</ul>
<blockquote>
<p>책을 좋아하는 이유는, 저자의 여러 노하우를 흡수할 수 있기 때문이다.</p>
</blockquote>
<br>

<h3 id="32-조급해하지-말자">3.2 조급해하지 말자</h3>
<p>시장은 심플하게 동작한다. 기업은 여러분의 능력이 자사의 문제를 해결하고 비즈니스에 도움이 될 거라고 생각하면 여러분을 채용 한다.</p>
<p>지금 채용에 떨어졌다고 해서 1년 뒤 또는 3년 뒤에 또 떨어진다고 보기는 어렵다.
<strong>계속 도전하면 적절한 상황이 도래했을 때 얼마든지 합격이 가능하다.</strong></p>
<p>만약 기업의 채용 과정에서 탈락했다고 본인의 실력이 부족하다고 생각하지는 않았으면 한다.
회사마다 원하는 인재의 수준이나 상황도 다르기 때문에 &#39;내가 실력이 부족해서 떨어졌구나&#39; 라고 생각하는 건 감정 소모에 불과하다.</p>
<blockquote>
<p>여러분은 스스로 생각하는 것보다 충분히 잘하고 있을 수 있다.</p>
</blockquote>
<hr>
<h2 id="4-블로그--기억은-짧다">4. 블로그 : 기억은 짧다</h2>
<p>이 책의 독자 대부분은 나를 블로그나 강의, 강연을 통해 알게 되었을 테다.
내가 강의, 강연을 시작하게 된 계기는 블로그였다. 내 모든 실무와 관련된 경험은 나의 블로그 속에 녹아있다.</p>
<blockquote>
<p>개발자가 블로그를 해야 하는 이유는 여러 가지가 있겠지만, 가장 중요한 이유는 <strong>우리가 겪는 이슈 대부분은 언젠가 우리의 기억속에서 사라지기 때문이다.</strong>
이렇게 될 경우 훗날 비슷한 이슈를 겪게 될 때 지금까지 한 수고를 반복할 가능성이 높다는 것이다.</p>
</blockquote>
<p>블로그에 작성하면 좋은 점은</p>
<ul>
<li>프로젝트를 하면서 마주했던 문제와</li>
<li>그 문제의 해결 방안이다.</li>
</ul>
<p>블로그의 또 다른 역할은</p>
<ul>
<li>내가 얼마나 많은 지식을 보유하고 있는지를 나타내준다는 것이다.</li>
</ul>
<p>과거 나는 구글 검색엔진의 동작에 대한 글을 작성했다. 글을 써나가면서 구글 검색 엔진의 동작 방식을 깊게 공부했기 때문에 누군가가 내 블로그를 볼 때 &#39;조은 님은 적어도 검색엔진의 동작 방식을 잘알겠구나&#39; 라고 인지할 수 있을 것이다.</p>
<blockquote>
<p>개발자의 실력 증명은 의외로 어렵다.</p>
</blockquote>
<p>내가 네이버에 다녔으니까 나를 뛰어난 개발자라고 부를 수 있을까 ?
우아한 형제들에 다녔으니까 뛰어난 개발자라고 부를 수 있을까 ?</p>
<ul>
<li>내가 거쳐온 회사가 나의 커리어에 도움이 될 수는 있겠지만, 어떤 회사에 다녔다는 사실 자체가 나의 실력을 일방적으로 증명해주지는 못한다.</li>
</ul>
<br>

<h3 id="41-아무튼-글쓰기">4.1 아무튼 글쓰기</h3>
<p>이 글을 읽는 대부분이 글쓰기에 거부감 또는 어색함을 느낄 거라 생각한다.
하지만, 지금은 본인이 충분히 관심만 가진다면 양질의 콘텐츠에 접근하는게 얼마든지 가능하다.</p>
<ul>
<li>&lt;개발자의 글쓰기&gt;</li>
<li>&lt;개발자를 위한 글쓰기 가이드&gt; </li>
</ul>
<p>글쓰기에서 무엇보다 중요한 것은 완성이다.
<strong>지금 좀 마음에 들지 않더라도 혹은 부족하게 느껴져도, 잘못된 내용이 아니라면 발행해야 완성이 되고 글에 생명이 불어넣어진다.</strong></p>
<blockquote>
<p>일단 공개해보자. 의외로 많은 사람이 당신의 글에서 도움을 얻을 것이다.</p>
</blockquote>
<br>

<h3 id="42-블로그의-목표가-취업을-위해서라면">4.2 블로그의 목표가 취업을 위해서라면</h3>
<p>예전에는 취업을 위해 블로그를 운영한다는 사실 자체에 분개했던 적도 있지만, 
모든 것이 스펙이 되어가는 이 시대에는 취업을 위해 블로그를 운영하는 것은 나쁘지 않다고 생각한다.</p>
<blockquote>
<p>오히려 나는 블로그가 더 좋은 직장으로 가기 위한 적절한 전략 중 하나라고 생각한다.</p>
</blockquote>
<p>작성한 블로그의 내용은 면접 질문으로 이어질 가능성이 높다.
<strong>따라서 블로그를 작성할 때는, 어느 정도 본인이 이해하고 있는 내용을 작성하는 것이 중요하다.</strong></p>
<br>

<h3 id="today-i-learned-til">Today I Learned (TIL)</h3>
<p>주변에 많은 취업 준비생들이 작성한다.
작성하는 행위 자체는 나쁘지 않은 습관이지만, 많은 사람이 TIL 을 하나의 업무라고 생각하면서도 결과적으로 그다지 좋은 글을 작성하지 못하는 경우가 종종 있다.</p>
<p><strong>누군가 쓰라고 하니까 쓰기는 하는데 스스로 TIL의 필요성을 인지하지 못하는 것이다,</strong></p>
<h4 id="til-은">TIL 은</h4>
<ol>
<li>기억이 휘발되기 전에 오늘 있었던 일들을 정리 하려는 목적</li>
<li>오늘 공부한 내용을 나중에 다시 갈무리하기 위해 키워드를 수집하려는 목적으로 쓴다.</li>
</ol>
<ul>
<li>따라서 TIL 그 자체로 취업 등에 전략적으로 사용하기는 어렵다.</li>
</ul>
<p>적어도 주니어 개발자, 현업에서 일하는 개발자에게는 업무에서 익힌 내용을 바탕으로 매일 무엇을 공부하고 경험했는지 글로 정리해놓는 게 도움이 될 수 있다.</p>
<h4 id="til-전략">TIL 전략</h4>
<ul>
<li>작성에 30분 이상 쓰지 않는다. 일단 쓰는 데만 집중</li>
<li>공개되지 않은 장소에 올린다. 학습 내용을 공유하고 싶다면 별도 블로그 게시물로 작성</li>
<li>공개된 장소에 업로드한다면 일주일치를 몰아서 올린다.</li>
</ul>
<hr>
<h2 id="5-이력서">5. 이력서</h2>
<p>이력서를 쓰는 방법에 대해서는 많은 글이 존재한다.
하지만 나는 이력서에 어떤 걸 쓰지 말아야 하는가에 집중해보고자 한다.</p>
<blockquote>
<p>좋은 이력서란 추상적인 영역으로 면접관의 주관에 따라 그 형태가 다를 수 있기 때문이다.</p>
</blockquote>
<br>

<h3 id="51-이력서는-카탈로그다">5.1 이력서는 카탈로그다</h3>
<p>이력서는 스스로를 판매하기 위한 내용을 여러 회사에 공유하며 
<strong>&#39;나를 채용하면 당신들 비즈니스에 도움이 될 거야&#39;</strong> 라는 내용을 담은 일종의 카탈로그다.</p>
<p>이력서에 어떤 내용을 담을 때 고민해보면 좋은 내용은</p>
<ol>
<li>다른 사람과 비교할 때 내가 가진 이점</li>
<li>내가 회사의 비즈니스에 어떤 도움을 줄 수 있는지 이다.</li>
</ol>
<br>

<h3 id="511-보편적인-좋은-점을-작성하지-않기">5.1.1 보편적인 좋은 점을 작성하지 않기</h3>
<p>예를 들어 &#39;열정 있는&#39;, &#39;개발을 즐기는&#39;, &#39;어제보다 오늘 더 성장하는&#39; 등의 다양한 키워드를 사용하겠지만 생각해보면 그렇지 않은 개발자는 드물다.</p>
<p><strong>한 줄 평을 작성할 때는 면밀하게 자기 자신에 대해 고민할 필요가 있다.</strong></p>
<p>예를 들어 &#39;열정 있는 개발자&#39; 라고 한다면,</p>
<ul>
<li>일일 커밋을 2 ~ 3 년 동안 했다거나,</li>
<li>지속해서 공부한 내용을 정리했다거나,</li>
<li>토이 프로젝트를 많이 했다거나 하는 액션이 필요하다.</li>
</ul>
<p>액션 없이 말로만 &#39;열정 있는 개발자&#39; 라고 하는 건 무의미하다.</p>
<br>

<h3 id="512-내용을-꾸역꾸역-채우지-않기">5.1.2 내용을 꾸역꾸역 채우지 않기</h3>
<p>이력서에 쓰는 내용은 정제된 언어로, 꼭 필요한 내용 위주로 작성한다.</p>
<blockquote>
<p>서류를 검토하는 사람들은 여러 사람의 이력서를 보기 때문에 필요한 내용만 정리된 이력서를 선호하며, 너무 많은 내용은 노이즈로 인식 할 수 있다.</p>
</blockquote>
<br>

<h3 id="513-클론-코딩-프로젝트-only">5.1.3 클론 코딩 프로젝트 Only</h3>
<p>클론 코딩은 어떤 기술을 학습하는 데 도움을 주며, 방식 자체도 나쁘다고 할 수는 없다.
하지만, 학습을 위해서가 아니라 취업을 위해 클론 코딩을 사용하겠다면 조금은 전략적이 될 필요가 있다.</p>
<ol>
<li>클론 코딩은 말 그대로 클론 코딩이어야 한다.</li>
</ol>
<p>-&gt; 많은 사람이 필요한 부분만 구현하고, 디테일은 놓치는 경우가 많다.</p>
<ol start="2">
<li>목표 기업의 서비스를 클론해보는 것이 취업에 도움을 줄 수 있다.</li>
</ol>
<p>-&gt; 카카오에 지원한다면 카카오에서 제공하는 서비스를 클론해보고
-&gt; 거기에서 UX를 개선한 형태로 프로젝트를 진행해 볼 수 있다.
-&gt; 이것은 당신이 해당 회사에 관심을 가지고 있다는 걸 확실히 어필해준다.</p>
<p>중요한 것은 
<strong>회사가 실제 겪고 있을 문제를 추측함과 동시에, 제품이 가진 문제를 개선하는 경험을 해보는 것이다.</strong></p>
<br>

<h3 id="52-그렇다면-이력서에-어떤-내용을-담을까-">5.2 그렇다면 이력서에 어떤 내용을 담을까 ?</h3>
<blockquote>
<p>이력서에 담아야 하는 건 현재까지 살아온 삶이 아니라, 
앞으로 개발자로서 삶을 잘 영위해나갈 수 있다는 내용이다.</p>
</blockquote>
<p>아래와 같은 내용을 넣으면 좋다.</p>
<ul>
<li>내가 현재 보유하고 있는 기술들과 그 수준</li>
<li>내가 현재 관심을 가지고 있는 내용들</li>
<li>커리어와 직접 연관된 프로젝트의 정보</li>
<li>내가 담당한 부분 기능에 대한 Overview</li>
<li>내가 겪은 문제, 해결 방안</li>
</ul>
<br>

<h4 id="될-수-있다면">될 수 있다면</h4>
<ul>
<li>(가능하다면) 블로그를 통해 내가 가진 지식을 증명</li>
<li>(가능하다면) Github를 통해 프로젝트를 공유</li>
<li>(가능하다면) 지금까지 진행한 커리어에 도움이 되는 프로젝트</li>
<li><blockquote>
<p>혹은 커리어에 직접 도움이 되지 않더라도 관심을 가질 수 있는 프로젝트</p>
</blockquote>
</li>
</ul>
<hr>
<h2 id="6-면접">6. 면접</h2>
<p>어느 회사의 면접을 보느냐에 따라 경험이 다르고, 면접 차수에 따라서도 면접 경험은 달라진다.
A 회사는 기술면접에 무게를 싣는 데 반해, B 회사는 인성 면접에 무게를 싣기도 한다.
또한, 경력인지 신입인지에 따라 면접의 형태는 달라진다.</p>
<h3 id="61-면접이라는-자리">6.1 면접이라는 자리</h3>
<blockquote>
<p>회사 입장에서는 지원자가 우리와 핏(Fit) 이 맞는지 체크하는 시간이며 
동시에 지원자 입장에서는 자기와 핏이 맞는지 체크하는 시간이기도 하다.</p>
</blockquote>
<p>다시말해, 면접을 보러 가는 자리라고 해서 일방적으로 기가 죽을 필요는 없다.</p>
<br>

<h3 id="62-기술-자체에-대해-물어보는-질문">6.2 기술 자체에 대해 물어보는 질문</h3>
<p>기술 면접에서 물어보는 내용 중 순수하게 기술 지식과 관련한 질문은 준비만 잘하면 의외로 쉽게 풀어나갈 수 있다.</p>
<ul>
<li>최근 기술력이 뛰어나다고 평가받는 기업들은 대부분 기술 블로그를 운영하기 때문에 그것을 보는 것도 좋은 전략이 될 수 있다.</li>
<li><strong>면접에서는 보통 그 회사에서 쓰는 기술에 대한 질문이 나올 가능성이 높다.</strong></li>
</ul>
<p>기술 질문에서는 단골로 등장하는 질문이 있기 때문에 그런 것들을 공부해두는 게 좋다.</p>
<br>

<h3 id="63-경험에-대해-물어보는-질문">6.3 경험에 대해 물어보는 질문</h3>
<p>예를 들어, 리액트를 이용해서 에디터를 만들어본 경험이 있는 지원자가 있다면</p>
<ul>
<li>왜 에디터에서 React 를 사용하셨나요? -&gt; React 의 장점과 단점은 어떤 것이 있나요?</li>
<li>에디터 자체는 어떤 식을 구현하셨나요? -&gt; Contenteditable 을 사용하셨나요?</li>
<li>자동 저장 기능도 고려하셨나요? -&gt; 했다면 어떻게 구현하셨나요?</li>
</ul>
<p>경험에 대해 물어보는 질문은 크게 <strong>문제에 대한 정의</strong>와 그 <strong>문제를 해결하는 파트</strong>로 나누어지고,
문제에 대한 정의는 면접관이 대부분 질문을 통해 내리게 된다.</p>
<p>-&gt; 이 질문에 대한 해답을 본인의 경험을 바탕으로 답변한다.</p>
<blockquote>
<p>경험에 대한 질문에서는 꼬리 물기 식의 질문이 많이 나와 심리적 압박감을 느낄 수 있다.
그러나 물어보는 내용 중 답이 정해진 질문은 없기 때문에, 최대한 본인이 알고 경험한 것을 적극 공유하는 것이 좋다.</p>
</blockquote>
<br>

<h3 id="64-회사에-대한-질문">6.4 회사에 대한 질문</h3>
<p>많은 면접에서 &#39;회사에 궁금한 점을 말해보세요&#39; 라는 질문을 던진다.
이 질문은 내가 이 회사에 얼마나 관심이 있는지, 또 기술적으로 얼마나 성장을 원하고 있는 지
어필 할 수 있는 중요한 시간이다.</p>
<h4 id="641-물어보며-좋은-질문들">6.4.1 물어보며 좋은 질문들</h4>
<ul>
<li>면접 중 답변을 못했거나, 애매하게 답했다고 생각되는 지식들</li>
<li>내가 합류할 조직의 서비스에 대한 질문</li>
<li>조직의 기업 문화, 코드 문화에 대한 질문</li>
<li>조직의 일하는 방식에 대한 질문</li>
<li>기술 블로그 중 인상 깊었던 부분</li>
</ul>
<hr>
<p>책을 읽으며,
프론트엔드 개발자가 되고 싶다고 처음 준비할 때 부터 봤다면, 준비하는 방향과 방식이 많이 달랐을 것 같다. 또한 이력서나 면접 부분 등 그리고 전공자이지만 부족하다고 느끼는 CS 지식에 대한 학습 방향까지 이제 막 인턴을 하고있는 지금이라도 읽게 되서 다행이라고 생각한다.</p>
<p>이 게시물을 종종 다시 읽으면서 나의 방향성과 지식들을 풍성하게 채울 수 있는 길을 가도록 노력해야 겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[패스트캠퍼스] - 김민태의 React 와 Redux로 구현하는 아키텍처와 리스크 관리 (1) ]]></title>
            <link>https://velog.io/@hoho_0815/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EA%B9%80%EB%AF%BC%ED%83%9C%EC%9D%98-React-%EC%99%80-Redux%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%A6%AC%EC%8A%A4%ED%81%AC-%EA%B4%80%EB%A6%AC-1</link>
            <guid>https://velog.io/@hoho_0815/%ED%8C%A8%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%8D%BC%EC%8A%A4-%EA%B9%80%EB%AF%BC%ED%83%9C%EC%9D%98-React-%EC%99%80-Redux%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%EB%A6%AC%EC%8A%A4%ED%81%AC-%EA%B4%80%EB%A6%AC-1</guid>
            <pubDate>Tue, 12 Jul 2022 13:00:53 GMT</pubDate>
            <description><![CDATA[<h1 id="1-프론트엔드-개발자의-역할과-필수-소프트-스킬">1. 프론트엔드 개발자의 역할과 필수 소프트 스킬</h1>
<h2 id="1-web-front-end-">1. Web Front End ?</h2>
<h3 id="11-web">1.1 Web</h3>
<blockquote>
<p>개방형 표준 기술</p>
</blockquote>
<br>

<h3 id="12-front">1.2 Front</h3>
<blockquote>
<p>프론트엔드의 프론트는 <strong>가장 앞에있는</strong> 시각적인 요소를 포함하고 사람들을 직접 마주 합니다.</p>
</blockquote>
<ul>
<li>시각적 요소가 많고 그렇기에 주관적인 부분도 많습니다.</li>
<li>개발자가 기술만 알고 있다고 해서 뛰어나다고 평가 받지 않을 수 있으며, UX 같은 부분들도 많이 고려 됩니다.</li>
<li>또한 빠르게 변화가 일어납니다.</li>
</ul>
<br>

<h3 id="13-end">1.3 End</h3>
<blockquote>
<p>프로세스적 관점에서 기획 -&gt; 디자인 -&gt; 백엔드 -&gt; 프론트 등 사이클의 끝에 있습니다.</p>
</blockquote>
<ul>
<li>릴리즈 일자를 선정하나 계획이 변경되고 앞선 부분에서 기간의 조정될 때 프론트가 많은 부담을 가지게 됩니다.</li>
</ul>
<hr>
<h2 id="2-과거-현재-미래의-front">2. 과거, 현재, 미래의 Front</h2>
<h3 id="1992">1992</h3>
<ul>
<li>http의 탄생과 같이 웹이 시작됨</li>
</ul>
<h3 id="2007">2007</h3>
<ul>
<li>아이폰의 탄생, 모바일 생태계로 중심이 이동함 (1년 뒤, 앱스토어를 선보임)</li>
</ul>
<h3 id="2008">2008</h3>
<ul>
<li>구글 크롬이 출시되며 V8 엔진을 선보임. 웹이 발전해야 하는데 가장 병목은 브라우저의 JavaScript 실행 부분이었음 (V8 엔진)</li>
</ul>
<h3 id="2009">2009</h3>
<ul>
<li>JavaScript를 일반 시스템에서 실행하기 위해서 빠른 V8 엔진을 사용한 node JS를 만듬 (지금의 프론트엔드 환경을 만들었다고 평가할 수 있음)</li>
</ul>
<h3 id="2010">2010</h3>
<ul>
<li>node 패키지 매니저인 npm의 등장 (08 ~ 10의 변화가 이후의 FE 10년의 환경의 기반이 됨) </li>
<li>Angular과 knockout JS의 탄생 (이전의 WebApp은 jquery로 만들던 시절이었으며, Angular가 나오며 라이브러리 단계에서 프레임워크로 발전시킴, 보다 큰 앱을 단단하고 아키텍쳐를 가지고 설계될 수 있도록 하였음, knockout JS는 데이터 흐름을 라이브러리나 프레임워크 단계로 내릴 수 있는 설계를 제시함 - Two-Way Binding)</li>
</ul>
<h3 id="2012">2012</h3>
<ul>
<li>TypeScript 출시 </li>
</ul>
<h3 id="2013">2013</h3>
<ul>
<li>React 출시. Angular가 Two-Way binding의 장점과 동시에 단점이 부각되었으며 React는 대비적으로 One-way binding의 장점을 살림 (Virtual DOM 등과 같이)</li>
</ul>
<h3 id="-2020">~ 2020</h3>
<ul>
<li>React, VueJS가 주류로 사용됨. 안정화</li>
</ul>
<hr>
<h2 id="3-front-개발자-유형">3. Front 개발자 유형</h2>
<ol>
<li>System 에 대한 지식이 있는 / 없는 개발자</li>
<li>Graphics(그래픽 시스템) 에 대한 관심이 있는 / 없는 개발자</li>
<li>UX 에 관심이 있는 / 없는 개발자</li>
</ol>
<ul>
<li>나는 어떤 유형의 개발자인가 생각을 해보고 전략을 세워보자!<br>

</li>
</ul>
<h3 id="31-프론트-엔드-개발자의-학습-전략">3.1 프론트 엔드 개발자의 학습 전략</h3>
<ol>
<li>개발자 모두가 알아야 하는 지식</li>
</ol>
<p>-&gt; Network, Memory, performance</p>
<ol start="2">
<li>필요한 상황이 생기면 알고 싶지만 쉽게 배울 수 없는 지식</li>
</ol>
<p>-&gt; Graphics, Math </p>
<ol start="3">
<li>필요하다면 쉽게 배울 수 있는 지식</li>
</ol>
<p>-&gt; JS, TS, React 등 같은 라이브러리 및 프레임워크</p>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://fastcampus.co.kr/">https://fastcampus.co.kr/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리덕스 모듈 만들기]]></title>
            <link>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4-%EB%AA%A8%EB%93%88-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4-%EB%AA%A8%EB%93%88-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Mon, 11 Jul 2022 15:33:35 GMT</pubDate>
            <description><![CDATA[<h1 id="리덕스-모듈-만들기">리덕스 모듈 만들기</h1>
<p>리덕스 모듈이란 다음 항목들이 모두 들어있는 자바스크립트 파일을 의미합니다.</p>
<ul>
<li>액션 타입</li>
<li>액션 생성함수</li>
<li>리듀서</li>
</ul>
<p>리덕스를 사용하기 위해 필요한 위 항목들을 각 다른 파일에 저장 할 수도 있습니다.
하지만, 코드들이 꼭 분리되어 있을 필요는 없습니다.</p>
<blockquote>
<p>그래서 리듀서와 액션 관련 코드들을 하나의 파일에 몰아서 작성 할 것 인데 이것을 <strong>Ducks</strong> 패턴 이라고 부릅니다.</p>
</blockquote>
<ul>
<li>리덕스 관련 코드를 분리하는 방식은 정해져 있는 방식이 없으므로 자유롭게 분리해도 됩니다.</li>
</ul>
<hr>
<h2 id="counter-모듈">counter 모듈</h2>
<h3 id="modulescounterjs">modules/counter.js</h3>
<pre><code class="language-js">/* 액션 타입 만들기 */
// Ducks 패턴을 따를땐 액션의 이름에 접두사를 넣어주세요.
// 이렇게 하면 다른 모듈과 액션 이름이 중복되는 것을 방지 할 수 있습니다.
const SET_DIFF = &#39;counter/SET_DIFF&#39;;
const INCREASE = &#39;counter/INCREASE&#39;;
const DECREASE = &#39;counter/DECREASE&#39;;

/* 액션 생성함수 만들기 */
// 액션 생성함수를 만들고 export 키워드를 사용해서 내보내주세요.
export const setDiff = diff =&gt; ({ 
    type: SET_DIFF, 
    diff
 });

export const increase = () =&gt; ({ 
    type: INCREASE
 });

export const decrease = () =&gt; ({ 
    type: DECREASE
 });

/* 초기 상태 선언 */
const initialState = {
  number: 0,
  diff: 1
};

/* 리듀서 선언 */
// 리듀서는 export default 로 내보내주세요.
export default function counter(state = initialState, action) {
  switch (action.type) {
    case SET_DIFF:
      return {
        ...state,
        diff: action.diff
      };
    case INCREASE:
      return {
        ...state,
        number: state.number + state.diff
      };
    case DECREASE:
      return {
        ...state,
        number: state.number - state.diff
      };
    default:
      return state;
  }
}</code></pre>
<br>

<h2 id="todos-모듈">todos 모듈</h2>
<h3 id="modulestodosjs">modules/todos.js</h3>
<pre><code class="language-js">/* 액션 타입 선언 */
const ADD_TODO = &#39;todos/ADD_TODO&#39;;
const TOGGLE_TODO = &#39;todos/TOGGLE_TODO&#39;;

/* 액션 생성함수 선언 */
let nextId = 1; // todo 데이터에서 사용 할 고유 id
export const addTodo = text =&gt; ({
  type: ADD_TODO,
  todo: {
    id: nextId++, // 새 항목을 추가하고 nextId 값에 1을 더해줍니다.
    text
  }
});
export const toggleTodo = id =&gt; ({
  type: TOGGLE_TODO,
  id
});

/* 초기 상태 선언 */
// 리듀서의 초기 상태는 꼭 객체타입일 필요 없습니다.
// 배열이여도 되고, 원시 타입 (숫자, 문자열, 불리언 이여도 상관 없습니다.
const initialState = [
  /* 우리는 다음과 같이 구성된 객체를 이 배열 안에 넣을 것입니다.
  {
    id: 1,
    text: &#39;예시&#39;,
    done: false
  } 
  */
];

export default function todos(state = initialState, action) {
  switch (action.type) {
    case ADD_TODO:
      return state.concat(action.todo);
    case TOGGLE_TODO:
      return state.map(
        todo =&gt;
          todo.id === action.id // id 가 일치하면
            ? { ...todo, done: !todo.done } // done 값을 반전시키고
            : todo // 아니라면 그대로 둠
      );
    default:
      return state;
  }
}</code></pre>
<br>

<h2 id="루트-리듀서-만들기">루트 리듀서 만들기</h2>
<p>한 프로젝트에 여러 개의 리듀서가 있을 때는 하나의 리듀서로 합쳐서 사용 합니다.
-&gt; 이를 곧, 루트 리듀서라고 부릅니다.</p>
<blockquote>
<p>리듀서를 합치는 작업은 <code>combineReducers</code> 라는 함수를 사용 합니다.</p>
</blockquote>
<h3 id="modulesindexjs">modules/index.js</h3>
<pre><code class="language-js">import { combineReducers } from &#39;redux&#39;;
import counter from &#39;./counter&#39;;
import todos from &#39;./todos&#39;;

const rootReducer = combineReducers({
  counter,
  todos
});

export default rootReducer;</code></pre>
<br>

<h2 id="리덕스-스토어-만들기">리덕스 스토어 만들기</h2>
<p>src 디렉토리 -&gt; index.js</p>
<h3 id="srcindexjs">src/index.js</h3>
<pre><code class="language-js">import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import &#39;./index.css&#39;;
import App from &#39;./App&#39;;
import { createStore } from &#39;redux&#39;;
import rootReducer from &#39;./modules&#39;;

const store = createStore(rootReducer); // 스토어를 만듭니다.
console.log(store.getState()); // 스토어의 상태를 확인해봅시다.

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(
  &lt;React.StrictMode&gt;
    &lt;App /&gt;
  &lt;/React.StrictMode&gt;
);
</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/9515ffe6-0941-414e-92e6-22161cd1e239/image.png" alt=""></p>
<hr>
<h2 id="리액트-프로젝트에-리덕스-적용">리액트 프로젝트에 리덕스 적용</h2>
<p>리액트 프로젝트에 리덕스를 적용 할 때는 <strong>react-redux</strong> 라이브러리를 사용 해야 합니다.</p>
<pre><code class="language-js">yarn add react-redux</code></pre>
<br>

<h3 id="사용법">사용법</h3>
<p>index.js 에서 <strong>Provider</strong> 컴포넌트를 불러와서 App 컴포넌트를 감싸줍니다
그리고, <strong>Provider</strong> 의 props 에 <strong>store</strong> 를 넣어줍니다.</p>
<blockquote>
<p>Provider 로 App 을 감싸게 되면 렌더링 하는 어떤 컴포넌트던지 리덕스 스토어에 접근 할 수 있습니다.</p>
</blockquote>
<pre><code class="language-js">import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import &#39;./index.css&#39;;
import App from &#39;./App&#39;;
import { createStore } from &#39;redux&#39;;
import rootReducer from &#39;./modules&#39;;
import { Provider } from &#39;react-redux&#39;;

const store = createStore(rootReducer); // 스토어를 만듭니다.
console.log(store.getState()); // 스토어의 상태를 확인해봅시다.

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(
  &lt;React.StrictMode&gt;
    &lt;Provider store={store}&gt;
    &lt;App /&gt;
    &lt;/Provider&gt;
  &lt;/React.StrictMode&gt;
);
</code></pre>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://react.vlpt.us/redux/04-make-modules.html">https://react.vlpt.us/redux/04-make-modules.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리덕스 사용 준비]]></title>
            <link>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4-%EC%82%AC%EC%9A%A9-%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4-%EC%82%AC%EC%9A%A9-%EC%A4%80%EB%B9%84</guid>
            <pubDate>Mon, 11 Jul 2022 13:26:23 GMT</pubDate>
            <description><![CDATA[<h1 id="리덕스-사용-준비">리덕스 사용 준비</h1>
<p>리액트 컴포넌트 없이, 리덕스에서 제공되는 기능들을 먼저 연습 해보겠습니다.</p>
<h2 id="설치">설치</h2>
<h3 id="yarn-사용-시">yarn 사용 시</h3>
<pre><code class="language-js">yarn add redux</code></pre>
<hr>
<h2 id="폴더-구조">폴더 구조</h2>
<p>src 안에 -&gt; exercise.js 생성 -&gt; index.js 에 import 
그 후, yarn start</p>
<h3 id="exercisejs">exercise.js</h3>
<pre><code class="language-js">import { createStore } from &#39;redux&#39;;

// createStore는 스토어를 만들어주는 함수입니다.
// 리액트 프로젝트에서는 단 하나의 스토어를 만듭니다.

/* 리덕스에서 관리 할 상태 정의 */
const initialState = {
  counter: 0,
  text: &#39;&#39;,
  list: []
};

/* 액션 타입 정의 */
// 액션 타입은 주로 대문자로 작성합니다.
const INCREASE = &#39;INCREASE&#39;;
const DECREASE = &#39;DECREASE&#39;;
const CHANGE_TEXT = &#39;CHANGE_TEXT&#39;;
const ADD_TO_LIST = &#39;ADD_TO_LIST&#39;;

/* 액션 생성함수 정의 */
// 액션 생성함수는 주로 camelCase 로 작성합니다.
function increase() {
  return {
    type: INCREASE // 액션 객체에는 type 값이 필수입니다.
  };
}

// 화살표 함수로 작성하는 것이 더욱 코드가 간단하기에,
// 이렇게 쓰는 것을 추천합니다.
const decrease = () =&gt; ({
  type: DECREASE
});

const changeText = text =&gt; ({
  type: CHANGE_TEXT,
  text // 액션안에는 type 외에 추가적인 필드를 마음대로 넣을 수 있습니다.
});

const addToList = item =&gt; ({
  type: ADD_TO_LIST,
  item
});

/* 리듀서 만들기 */
// 위 액션 생성함수들을 통해 만들어진 객체들을 참조하여
// 새로운 상태를 만드는 함수를 만들어봅시다.
// 주의: 리듀서에서는 불변성을 꼭 지켜줘야 합니다!

function reducer(state = initialState, action) {
  // state 의 초깃값을 initialState 로 지정했습니다.
  switch (action.type) {
    case INCREASE:
      return {
        ...state,
        counter: state.counter + 1
      };
    case DECREASE:
      return {
        ...state,
        counter: state.counter - 1
      };
    case CHANGE_TEXT:
      return {
        ...state,
        text: action.text
      };
    case ADD_TO_LIST:
      return {
        ...state,
        list: state.list.concat(action.item)
      };
    default:
      return state;
  }
}

/* 스토어 만들기 */
const store = createStore(reducer);

console.log(store.getState()); // 현재 store 안에 들어있는 상태를 조회합니다.

// 스토어안에 들어있는 상태가 바뀔 때 마다 호출되는 listener 함수
const listener = () =&gt; {
  const state = store.getState();
  console.log(state);
};

const unsubscribe = store.subscribe(listener);
// 구독을 해제하고 싶을 때는 unsubscribe() 를 호출하면 됩니다.

// 액션들을 디스패치 해봅시다.
store.dispatch(increase());
store.dispatch(decrease());
store.dispatch(changeText(&#39;안녕하세요&#39;));
store.dispatch(addToList({ id: 1, text: &#39;현호&#39; }));</code></pre>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/0878f267-69bf-4444-9465-d1df091442fa/image.png" alt=""></p>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://react.vlpt.us/redux/03-prepare.html">https://react.vlpt.us/redux/03-prepare.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리덕스의 3가지 규칙]]></title>
            <link>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%9D%98-3%EA%B0%80%EC%A7%80-%EA%B7%9C%EC%B9%99</link>
            <guid>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%9D%98-3%EA%B0%80%EC%A7%80-%EA%B7%9C%EC%B9%99</guid>
            <pubDate>Mon, 11 Jul 2022 12:46:06 GMT</pubDate>
            <description><![CDATA[<h1 id="리덕스의-3가지-규칙">리덕스의 3가지 규칙</h1>
<h2 id="1-하나의-애플리케이션-안에는-하나의-스토어만-존재">1. 하나의 애플리케이션 안에는 하나의 스토어만 존재</h2>
<p>하나의 애플리케이션에서는 단 한개의 스토어를 만들어서 사용 합니다.</p>
<ul>
<li>여러 개의 스토어를 사용하는 것은 가능하기는 하나, 권장하지 않습니다.</li>
<li>특정 업데이트가 너무 빈번하게 일어나거나, 애플리케이션의 특정 부분을 완전히 분리 시킬 때 여러 개의 스토어를 만들 수도 있습니다.</li>
<li>하지만 그렇게 되면, 개발 도구를 활용 하지 못하게 됩니다.</li>
</ul>
<br>

<h2 id="2-상태는-읽기전용-입니다">2. 상태는 읽기전용 입니다.</h2>
<p>리액트에서 <strong>state 를 업데이트 해야 할 때</strong></p>
<ul>
<li>setState 를 사용하고</li>
<li>배열을 업데이트 할 때는 배열 자체에 push 를 직접 하지 않고, concat 같은 함수를 사용하여 기존의 배열은 수정하지 않고, <strong>새로운 배열을 만들어서 교체하는 방식으로 업데이트 합니다.</strong></li>
<li>객체의 경우 기존의 객체는 건들이지 않고 깊은 복사를 하여, spread 연산자 등을 사용하여 업데이트 합니다.</li>
</ul>
<blockquote>
<p>리덕스 또한 기존의 상태는 건들이지 않고, 새로운 상태를 생성하여 업데이트 해주는 방식으로 해야 나중에 개발자 도구를 사용해서 뒤로 돌릴 수도 있고, 다시 앞으로 돌릴 수도 있습니다.</p>
</blockquote>
<p><strong>즉, 기존의 상태를 수정하지 않고 새로운 상태를 생성하여 업데이트 해야 합니다. (교체의 개념)</strong></p>
<ul>
<li>이를 통해 <strong>불변성</strong> 을 유지 할 수 있습니다.</li>
<li><blockquote>
<p>데이터의 변경을 감지 하기 위해서는 내부 데이터까지 전부 찾아야 하는데 시간이 너무 오래 걸립니다.</p>
</blockquote>
</li>
<li><blockquote>
<p>따라서, 기존 상태의 객체를 새로운 객체로 변경하면 객체의 주소가 다르므로 변경을 쉽게 감지하는 것이 가능 합니다.</p>
</blockquote>
</li>
</ul>
<br>

<h2 id="3-리듀서는-순수한-함수여야-합니다">3. 리듀서는 순수한 함수여야 합니다.</h2>
<ul>
<li>리듀서 함수는 이전 상태와 액션 객체를 파라미터로 받습니다.</li>
<li>이전의 상태는 절대로 건들이지 않고, 변화를 일으킨 새로운 상태 객체를 만들어서 반환 합니다.</li>
<li>똑같은 파라미터로 호출된 리듀서 함수는 언제나 똑같은 결과 값을 반환해야만 합니다.</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://react.vlpt.us/redux/02-rules.html">https://react.vlpt.us/redux/02-rules.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리덕스에서 사용되는 키워드]]></title>
            <link>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-%ED%82%A4%EC%9B%8C%EB%93%9C</link>
            <guid>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-%ED%82%A4%EC%9B%8C%EB%93%9C</guid>
            <pubDate>Mon, 11 Jul 2022 12:28:35 GMT</pubDate>
            <description><![CDATA[<h1 id="리덕스에서-사용되는-키워드">리덕스에서 사용되는 키워드</h1>
<h2 id="액션-action">액션 (Action)</h2>
<blockquote>
<p>상태에 어떠한 변화가 필요하게 될 때, 액션이란 것을 발생 시킵니다.</p>
</blockquote>
<ul>
<li><p>이는, 하나의 객체로 표현이되고 <code>type</code> 이라는 필드는 필수로 가지고 있어야 합니다.</p>
<pre><code class="language-js">{
type : &quot;TOGGLE_VALUE&quot;
}</code></pre>
</li>
<li><p><code>type</code> 외의 값들은 개발자 마음대로 넣을 수 있습니다.</p>
<pre><code class="language-js">{
type : &quot;TOGGLE_VALUE&quot;,
data : {
      id : 0,
      text : &#39;리덕스 공부&#39;
}
}</code></pre>
</li>
</ul>
<hr>
<h2 id="액션-생성함수-action-creator">액션 생성함수 (Action Creator)</h2>
<blockquote>
<p>액션을 만드는 함수 입니다. 단순히 파라미터를 받아와서 액션 객체 형태로 만듭니다.</p>
</blockquote>
<pre><code class="language-js">export function addTodo(data){
    return{
      type : &quot;ADD_TODO&quot;,
      data
    };
}

// 화살표 함수로 만들 수 있습니다.
export const changeInput = (text) =&gt; {
  type : &quot;CHANGE_INPUT&quot;,
  text
};</code></pre>
<ul>
<li>액션 함수를 생성하는 이유는, 나중에 컴포넌트에서 쉽게 액션을 발생시키기 위함 입니다.</li>
<li>그래서 보통 함수 앞에 <code>export</code> 키워드를 붙여서 다른 파일에서 불러와서 사용 합니다.</li>
</ul>
<hr>
<h2 id="리듀서-reducer">리듀서 (Reducer)</h2>
<blockquote>
<p><strong>변화를 일으키는 함수</strong> 입니다. 두 가지의 파라미터를 받아 옵니다.</p>
</blockquote>
<pre><code class="language-js">function reducer(state, action){
    // 상태 업데이트 로직
      return state;
}</code></pre>
<ul>
<li>리듀서는 현재의 상태와, 전달 받은 액션을 참고하여 새로운 상태를 만들어서 반환 합니다.</li>
<li><code>useReducer</code> 를 사용 할 때와 똑같은 형태를 가지고 있습니다.<br>

</li>
</ul>
<h3 id="카운터를-위한-리듀서를-만든다면">카운터를 위한 리듀서를 만든다면</h3>
<pre><code class="language-js">function counter(state, action){
    switch (action.type){
      case &#39;INCREASE&#39; :
        return state + 1;

      case &#39;DECREASE&#39; :
        return state - 1;

      default :
        return state;
    }
}</code></pre>
<ul>
<li>리덕스에서는 리듀서의 기존 <code>default</code> 에 기존 <code>state</code> 를 반환하도록 작성 합니다.</li>
<li>리덕스를 사용 할 때는 여러 개의 리듀서를 만들고 이를 합쳐러 루트 리듀서 (Root Reducer) 를 만들 수 있습니다. ( 루트 리듀서 안에 리듀서들은 서브 리듀서 라고 부릅니다. )</li>
</ul>
<hr>
<h2 id="스토어--store-">스토어 ( Store )</h2>
<blockquote>
<p>리덕스는 <strong>하나의 애플리케이션에 하나의 리덕스 스토어</strong>를 만들게 됩니다.</p>
</blockquote>
<ul>
<li>스토어 안에는 현재의 앱 상태와, 리듀서가 들어있고,  몇 가지의 내장 함수들이 있습니다.</li>
</ul>
<hr>
<h2 id="디스패치--dispatch-">디스패치 ( dispatch )</h2>
<blockquote>
<p>스토어의 내장 함수 중 하나 입니다. <strong>액션을 발생 시키는 것</strong> 이라고 이해 할 수 있습니다.</p>
</blockquote>
<ul>
<li>dispatch 라는 함수에는 액션을 파라미터로 전달 합니다.</li>
<li>dispatch(action)</li>
<li>위와 같이 호출을 하면, 스토어는 리듀서 함수를 실행 시켜서 해당 액션을 처리하는 로직이 있다면 참고하여 새로운 상태를 만들어 줍니다.</li>
</ul>
<hr>
<h2 id="구독--subscribe-">구독 ( subscribe )</h2>
<blockquote>
<p>스토어의 내장 함수 중 하나 입니다. 함수 형태의 값을 파라미터로 받아 옵니다.</p>
</blockquote>
<ul>
<li>subscribe 함수에 특정 함수를 전달해주면, 액션이 디스패치 되었을 때 마다 전달해준 함수가 호출 됩니다.</li>
<li>리액트에서 리덕스를 사용하게 될 때 보통 이 함수를 직접 사용하는 일은 별로 없습니다.</li>
<li>대신, react-redux 라이브러리에서 제공하는 <code>connect</code> 또는 <code>useSelector</code> 를 사용하여 리덕스 스토어의 상태에 구독 합니다.</li>
</ul>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://react.vlpt.us/redux/01-keywords.html">https://react.vlpt.us/redux/01-keywords.html</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리덕스(Redux) 란]]></title>
            <link>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4Redux-%EB%9E%80</link>
            <guid>https://velog.io/@hoho_0815/%EB%A6%AC%EB%8D%95%EC%8A%A4Redux-%EB%9E%80</guid>
            <pubDate>Mon, 11 Jul 2022 12:03:48 GMT</pubDate>
            <description><![CDATA[<h1 id="리덕스redux">리덕스(Redux)</h1>
<p>리액트 생태계에서 가장 사용률이 높은 상태관리 라이브러리 입니다.</p>
<h2 id="1-사용하는-이유">1. 사용하는 이유</h2>
<ol>
<li>컴포넌트들의 상태 관련 로직들을 다른 파일들로 분리시켜서 더욱 효율적으로 관리 가능</li>
<li>글로벌 상태 관리도 손쉽게 할 수 있다.</li>
<li>props 드릴링을 막을 수 있다.</li>
</ol>
<blockquote>
<p><strong>Context API</strong> 의 <code>useReducer</code> Hook 을 사용해서 개발하는 흐름은 리덕스를 사용하는 것과 매우 유사 합니다. -&gt; 리덕스에서도 리듀서와 액션이라는 개념을 사용하기 때문!</p>
</blockquote>
<hr>
<h2 id="2-리덕스를-사용하는-것과-context-api-의-차이">2. 리덕스를 사용하는 것과 Context API 의 차이</h2>
<h3 id="21-미들웨어middleware">2.1 미들웨어(Middleware)</h3>
<p><strong>리덕스에는 미들웨어라는 개념이 존재 합니다.</strong></p>
<ul>
<li>리덕스 미들웨어를 사용하면 액션 객체가 리듀서에서 처리되기 전에 원하는 작업을 수행 가능</li>
</ul>
<ol>
<li>특정 조건에 따라 액션이 무시되게 만들 수 있습니다.</li>
<li>액션을 콘솔에 출력하거나, 서버쪽에 로깅 할 수 있습니다.</li>
<li>액션이 디스패치 됐을 때, 이를 수정해서 리듀서에게 전달되도록 할 수 있습니다.</li>
<li>특정 액션이 발생 했을 때, 이에 기반하여 다른 액션이 발생되도록 할 수 있습니다.</li>
<li>특정 액션이 발생 했을 때, 특정 자바스크립트 함수를 실행 시킬 수 있습니다.</li>
</ol>
<blockquote>
<p>미들웨어는 주로 비동기 작업을 처리 할 때 많이 사용 합니다.</p>
</blockquote>
<br>

<h3 id="22-유용한-함수와-hooks">2.2 유용한 함수와, Hooks</h3>
<p>이전에 Context API 와 <code>useReducer</code> 를 사용 할 때는 Context 도 새로 만들고, Context 의 Provider 설정도 하고 각 Context 를 편하게 사용하기 위해 전용 커스텀 Hook 을 따로 만들어서 사용하기도 합니다.
-&gt; <strong>하지만 리덕스에서는 이와 비슷한 작업을 편리하게 해줄 수 있는 기능이 존재 합니다.</strong></p>
<ul>
<li><strong>connect</strong> 함수를 사용하면 리덕스의 상태 또는 액션 생성 함수를 컴포넌의 props로 받을 수 있다.</li>
<li><strong>useSelector</strong>, <strong>useDispatch</strong>, <strong>useStore</strong> 등 여러가지 존재</li>
</ul>
<blockquote>
<p><strong>connect</strong> 함수와 <strong>useSelector</strong> 는 내부적으로 최적화가 잘 이루어져있어서 실제 상태가 바뀔 때만 컴포넌트가 리렌더링 됩니다. 하지만 Context API 는 그러한 최적화가 자동으로 되어있지 않기 때문에 Context가 가지고 있는 상태가 바뀌면 해당 Provider 내부 컴포넌트들이 모두 리렌더링이 됩니다.</p>
</blockquote>
<hr>
<h2 id="3-하나의-커다란-상태">3. 하나의 커다란 상태</h2>
<blockquote>
<p>리덕스는 모든 글로벌 상태를 하나의 커다란 상태 객체에 넣어서 사용하는 것이 필수 입니다.</p>
</blockquote>
<hr>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://react.vlpt.us/redux/">https://react.vlpt.us/redux/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js - 무엇인가]]></title>
            <link>https://velog.io/@hoho_0815/Next.js-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@hoho_0815/Next.js-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Fri, 08 Jul 2022 07:44:21 GMT</pubDate>
            <description><![CDATA[<h2 id="1-nextjs-정의">1. Next.js 정의</h2>
<blockquote>
<p><strong>Next.js</strong> 는 따로 설정을 해주지 않고도 SSR, SEO부터 TypeScript까지 생산에 필요한 많은 기능들을 제공하는 아주 강력한 React 프레임워크 입니다.</p>
</blockquote>
<hr>
<h2 id="2-어디서-만들었나">2. 어디서 만들었나</h2>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/c41713e6-ab29-4e8b-8181-92032da86755/image.png" alt=""></p>
<p>Next.js는 <strong>Vercel</strong>이라는 Frontend Team에서 만들었습니다.</p>
<hr>
<h2 id="3-사용해야-하는-이유">3. 사용해야 하는 이유</h2>
<h3 id="31-ssr">3.1 SSR</h3>
<p>Next.js 를 사용하는 가장 큰 이유 입니다.
이해하기 좋게 먼저 반대 개념인 <strong>SPA</strong> 와 <strong>CSR</strong>에 대해 먼저 정리 하겠습니다.</p>
<h3 id="311-spa-single-page-application">3.1.1 SPA (Single Page Application)</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/92928b42-70be-48a9-a90f-bc428a4465e7/image.png" alt=""></p>
<p>전통적인 웹 페이지 만드는 방식은</p>
<ol>
<li>client 에서 server 로 최초의 요청을 보내고</li>
<li>server 는 요청을 받아 client 에게 응답을 보낸 후, client에서 화면이 보입니다.</li>
<li>이후 client 에서 상호작용이 있을 때 마다, server로 요청을 보내고</li>
<li>server 는 이에 응답하며 페이지가 Reload 됩니다.</li>
</ol>
<ul>
<li><p>하지만 위와 같은 방법인 경우 사용자가 새로운 요청을 보내고 응답을 받을 때 마다, 사용자의 페이지가 Reload 되기 때문에 사용자 경험이나 서버에 부담이가 비용적인 측면에서 좋지 않습니다.</p>
</li>
<li><p><span style="color : brown">위와 같은 방법을 해결 할 수 있는 것이 <strong>SPA</strong> 입니다.</span></p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/4336e7ce-dd89-4066-808d-a4e0610a2ca9/image.png" alt=""></p>
<ul>
<li>SPA 는 필요한 정적 리소소를 최초에 모두 다운로드 합니다.</li>
<li><blockquote>
<p>이후 변경이 있을 때마다 페이지 전체를 Reload 하지 않고 변경된 부분만 갱신 합니다.</p>
<br>
</blockquote>
</li>
</ul>
<h3 id="312-csr-client-side-rendering">3.1.2 CSR (Client Side Rendering)</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/d5d759f6-f807-4515-9f89-8532c90f4586/image.png" alt=""></p>
<p><strong>CSR</strong> 동작 순서는</p>
<ol>
<li>서버에서 브라우저로 응답을 보냅니다.</li>
<li>브라우저에서 <strong>JS</strong> 를 다운 받습니다.</li>
<li>브라우저가 React 를 실행 합니다.</li>
<li>페이지가 보이고 상호작용이 가능 합니다.</li>
</ol>
<h4 id="csr-의-장점">CSR 의 장점</h4>
<ul>
<li>컴포넌트 단위로 UI를 구성하기 때문에 재사용에 용이 합니다.</li>
<li>페이지 전환이 부드럽고 빠릅니다.</li>
<li>변경된 사항만 server로 전달하기 때문에 서버에 부담이 덜하고 비용적인 측면에서 효율적 입니다.</li>
</ul>
<h4 id="csr-의-단점">CSR 의 단점</h4>
<ul>
<li>초기 로딩 때 모든 정적 리소스들을 다운 받아서 초기 페이지 로딩이 느립니다.</li>
<li>SEO가 좋지 않습니다.</li>
</ul>
<br>

<h3 id="313-ssr-server-side-rendering">3.1.3 SSR (Server Side Rendering)</h3>
<p><img src="https://velog.velcdn.com/images/hoho_0815/post/f2879a95-7571-4adc-a344-5153bca34768/image.png" alt=""></p>
<p><strong>SSR</strong> 의 동작 순서는</p>
<ol>
<li>서버는 렌더링할 준비가 된 HTML을 응답을 브라우저에게 보냅니다.</li>
<li>브라우저는 페이지를 렌더링하고 이 때 페이지를 볼 수 있고 이 때, 브라우저가 JS를 다운로드 받습니다.</li>
<li>브라우저가 React를 실행합니다.</li>
<li>페이지를 상호작용 할 수 있습니다.</li>
</ol>
<h4 id="ssr-의-장점">SSR 의 장점</h4>
<ol>
<li>CSR에 비해 초기 렌더링 속도가 빠릅니다.</li>
<li>SEO 가 좋습니다.</li>
</ol>
<h4 id="ssr-의-단점">SSR 의 단점</h4>
<ol>
<li>CSR에 비해 서버와 요청하는 횟수가 많아 서버에 부담이 갈 수 있습니다.</li>
<li>페이지 전환 시 마다 새로고침이 일어납니다.</li>
</ol>
<br>

<h3 id="314-csr-과-ssr-의-차이">3.1.4 CSR 과 SSR 의 차이</h3>
<h4 id="1-사용자에게-더-빨리-보여지는-것---ssr">1. 사용자에게 더 빨리 보여지는 것 -&gt; SSR</h4>
<h4 id="2-view-와-상호작용">2. view 와 상호작용</h4>
<p><strong>CSR</strong> : 최종적으로 로딩이 끝난 후 가능
<strong>SSR</strong> : Page가 먼저 보여지나 JS 와 React 로딩이 끝난 후 가능</p>
<hr>
<h2 id="32-seo-search-engine-optimization">3.2 SEO (Search Engine Optimization)</h2>
<p>검색엔진 최적화 입니다.
기존 리액트에서 사용하는 CSR 방식은 SEO가 좋지 않습니다.
따라서 검색 엔진 최적화를 위해서는 SSR이 중요한 역할을 합니다.</p>
<h3 id="321-검색엔진-최적화를-하는-이유">3.2.1 검색엔진 최적화를 하는 이유</h3>
<p>웹 사이트를 만들고 브라우저에 검색을 했을 때, 사이트가 상단에 위치해야 유입이 많아질 것 입니다.
<strong>하지만 CSR 방식은 검색엔진에 노출이 잘 되지 않습니다.</strong> ( 노출이 안되는 것이 아닙니다!! )</p>
<ul>
<li>ex ) <a href="https://searchadvisor.naver.com/guide/seo-advanced-javascript">네이버 검색엔진</a>
<img src="https://velog.velcdn.com/images/hoho_0815/post/0644fb79-bf26-4b2c-8864-c667502a1d1d/image.PNG" alt=""></li>
</ul>
<blockquote>
<p>검색엔진 봇들은 JavaScript를 해석하기 힘들기 때문에 HTML에서 크롤링하게 됩니다. CSR 방식은 Client 측에서 페이지를 구성하기 전에 HTML에 아무것도 없으므로 데이터를 수집하지 못해 검색엔진에 노출이 어려운 것 입니다.</p>
</blockquote>
<hr>
<h2 id="33-마지막-nextjs-의-작동-방식">3.3 마지막 Next.js 의 작동 방식</h2>
<ol>
<li>사용자가 초기에 Server에 페이지 접속을 요청한 경우 <strong>SSR 방식</strong> 으로 렌더링 될 HTML을 보냅니다.</li>
<li>브라우저는 JS를 다운받고 React 를 실행 합니다.</li>
<li>사용자가 페이지와 상호작용을 하여 다른 페이지로 이동할 경우 <strong>CSR 방식</strong> server 가 아닌 브라우저에서 처리 합니다.</li>
</ol>
<hr>
<h2 id="정리">정리</h2>
<h3 id="nextjs-는">Next.js 는</h3>
<p>Vercel 에서 만든 <strong>SSR</strong>, <strong>SEO</strong> 를 하기 위한 React 의 프레임워크</p>
<ul>
<li>초기에 server 에 페이지 접속을 요청 한 경우 <strong>SSR 방식</strong> 으로 렌더링 될 HTML 을 보내줌으로써 <strong>SEO</strong> 최적화가 되어 검색 엔진에 노출이 됩니다.</li>
<li>페이지와 상호 작용을 할 때는 <strong>CSR</strong> 방식으로 처리함으로 <strong>SPA</strong> 장점을 가지고 있습니다.</li>
</ul>
<br>

<h3 id="csr">CSR</h3>
<p>CSR(Client Side Rendering)은 뼈대가 되는 빈 HTML 과 JS 파일을 전부 가져와 클라이언트(브라우저) 측에서 HTML 을 구성하는 방식이다. 초기에 빈 HTML 파일을 보여준 후 API 요청을 통해 데이터를 받아와 다시 렌더링 하기 때문에 사용자가 화면을 인식하는데 상대적으로 오래걸린다. 하지만 초기 로딩 후 버튼이나 링크를 클릭해 페이지간 전환이 일어날 때 클라이언트에서 화면을 다시 구성하므로 화면 전환 속도가 빠르다.</p>
<br>

<h3 id="ssr">SSR</h3>
<p>SSR(Server Side Rendering)은 서버에서 HTML을 구성하여 클라이언트로 보내주는 방식이다. (여기서 서버란, 프론트엔드가 발전하지 않았던 시절에는 말그대로 백엔드 서버를 의미 했으나, 프론트엔드단이 발전한 현재에는 프론트엔드 서버를 의미한다.) 서버에서 구성한 화면은 유저가 인식할 수 있으나, JS 를 다운받아 실행하기 전에는 이벤트 등이 작동하지 않는다. 따라서 유저의 interaction을 기록했다가 JS 파일을 다운 받은 후 실행시킨다.</p>
<br>

<h3 id="csr-vs-ssr">CSR Vs SSR</h3>
<p>CSR은 최초 화면을 유저에게 보여주기까지의 시간이 SSR 보다 오래걸린다. 또한 검색엔진이 크롤링을 했을 때 빈 HTML 만을 확인할 수 있기 때문에 SEO(검색엔진 최적화)에 불리하다.</p>
<p>SSR은 매번 서버에서 연산을 수행해야하기 때문에 서버에 부하가 더 크다. 또한 화면 전환시 깜빡임이 있다.</p>
<p>이렇게 각각 장단점이 있지만, 초기 로딩과 SEO 측면에서는 SSR의 장점이 두드러진다.</p>
<hr>
<br>

<h2 id="참고">참고</h2>
<ul>
<li><a href="https://vercel.com/">https://vercel.com/</a></li>
<li><a href="https://nextjs.org/">https://nextjs.org/</a></li>
<li><a href="https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8">https://medium.com/walmartglobaltech/the-benefits-of-server-side-rendering-over-client-side-rendering-5d07ff2cefe8</a></li>
<li><a href="https://www.excellentwebworld.com/what-is-a-single-page-application/">https://www.excellentwebworld.com/what-is-a-single-page-application/</a></li>
<li><a href="https://velog.io/@jeff0720/Next.js-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4-%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%8A%B5%EA%B9%8C%EC%A7%80-%ED%95%B4%EB%B3%B4%EB%8A%94-SSR-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95">SSR 개념 이해와 Next.js로 실습까지 해보는 SSR 환경 구축하기</a></li>
<li><a href="https://velog.io/@skypedanny/NextJS-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0#%EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94%E2%99%82%EF%B8%8F">NextJS, 그게 뭔데?</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>