<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>cha-cha.log</title>
        <link>https://velog.io/</link>
        <description>노트북이 좋아</description>
        <lastBuildDate>Sun, 25 Feb 2024 14:26:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. cha-cha.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sing_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[API]]></title>
            <link>https://velog.io/@sing_/API</link>
            <guid>https://velog.io/@sing_/API</guid>
            <pubDate>Sun, 25 Feb 2024 14:26:41 GMT</pubDate>
            <description><![CDATA[<p>드디어 API를 직접 만들어보고 이 개념을 명확하게 이해한 것 같다
나에게 API란... 예전에 인턴하면서 &#39;API 쓰면 좋아요~ 우리 회사 API 가능해요~~&#39; 홍보하던 &#39;붙여 쓰는 프로그램&#39;이었는데 실제로 배워보니 내 생각과 완전히 다르고 깊은 개념이었다..!</p>
<hr>
<h2 id="api란">API란?</h2>
<p>Application Programming Interface
여러 프로그램들과 데이터베이스, 기능들의 상호 통신 방법을 규정하고 도와주는 매개체</p>
<p>하나의 프로그램에서 다른 프로그램으로 <strong>데이터</strong>를 주고받기 위한 방법</p>
<p>API = 메뉴판
메뉴판에 적힌 메뉴들을 주문해봄
식당 주인과 음식을 주고받기 위한 방법</p>
<p>웹서비스의 예시)
코드를 짜서 웹툰 보내주는 프로그램(웹 서버)을 만듦
나는 A B C 웹툰을 보여줄 수 있다고 메뉴판을 만들어둘 수 있음</p>
<p>여기서 &#39;방법&#39;이 무엇인가?
방법 = 코드</p>
<h2 id="유저가-api를-동작시킬-수-있는-방법은">유저가 API를 동작시킬 수 있는 방법은?</h2>
<p><img src="https://velog.velcdn.com/images/sing_/post/6c64496c-3777-4bf7-851c-f36d9fb4ad87/image.png" alt="">
프로그램 주인이 app.get으로 코드를 짜놓고 이 API를 알려주면 됨</p>
<p>API가 꼭 가져야 할 내용이 있는데 </p>
<ol>
<li>요청 방식(데이터를 달라고 할 건지, 보낼건지 - get post put delete등)</li>
<li>무슨 자료를 요청할지</li>
<li>파라미터(자료요청에 필요한 추가 정보 - 쿼리스트링)</li>
</ol>
<p>이러한 요소들을 가지고 코트를 짜서 데이터에 대한 요청을 하는 것</p>
<h2 id="api의-종류">API의 종류</h2>
<ol>
<li>public
 누구나 사용 가능한 공개 API</li>
<li>private
 사내 프로그램들끼리 사용하는 API</li>
<li>partner API
 미리 정한 사람들만 사용할 수 있는 API</li>
</ol>
<hr>
<p><a href="https://www.youtube.com/watch?v=ckSdPNKM2pY&amp;pp=ygUQ7L2U65Sp7JWg7ZSMIEFQSQ%3D%3D">출처 - 코딩애플</a>

사실 이거 정리해놓은 지난 주까지만 해도 직접 제대로 다뤄보지 않아 잘 몰랐는데 이번에 다시 공부하면서 정리한 거 보니까 이해가 쏙쏙된다 역시 직접 해봐야해
앞으로는 모르겠으면 일단 코드부터 치면서 이해해보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML 통신과 JSON 통신의 차이]]></title>
            <link>https://velog.io/@sing_/MR-HTML-%ED%86%B5%EC%8B%A0%EA%B3%BC-JSON-%ED%86%B5%EC%8B%A0%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@sing_/MR-HTML-%ED%86%B5%EC%8B%A0%EA%B3%BC-JSON-%ED%86%B5%EC%8B%A0%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 25 Feb 2024 14:15:13 GMT</pubDate>
            <description><![CDATA[<h3 id="html-통신과-json-통신의-차이">HTML 통신과 JSON 통신의 차이</h3>
<p>이번 주 코치님께 코드리뷰를 받고 res.send() 코드에 대해 더 알아보는게 좋겠다는 피드백을 받았다. 그래서 내가 쓴 코드를 보니 res.json과 res.send가 혼용되어 있었던 것
그래서 제대로 알아봤다 ! </p>
<hr>
<pre><code class="language-jsx">User
    res.status(400).json({ message: error.message });
  }
});

// GET 요청 처리하는 라우터 - 관리자 조회
router.get(&#39;/&#39;, async (req, res) =&gt; {
  const admins = await Admin.find({});
  res.json(admins);
});

// Delete 요청 처리하는 라우터 - 관리자 삭제
router.delete(&quot;/:_id&quot;, async (req, res) =&gt; {
  const { _id } = req.params;
  await Admin.deleteOne({ _id });
  res.send(&quot;ok&quot;);</code></pre>
<p>일단 결론 먼저.
HTML통신과 JSON 통신에는 데이터를 전송하는 방식에 차이가 존재함</p>
<h3 id="데이터-형식용도">데이터 형식&amp;용도</h3>
<ul>
<li><p>HTML 통신은 주로 HTML 문서를 전송 = 웹페이지의 내용 표현</p>
<p>  주로 웹 페이지의 내용을 서버에서 클라이언트로 전송하는 데 사용. 따라서 웹 페이지의 구조, 텍스트, 이미지 등을 포함</p>
</li>
<li><p>JSON 통신은 HSON 형식의 데이터를 주고 받는 것을 의미</p>
<p>  =주로 웹 애플리케이션에서 데이터를 전송하고 수신하는데 사용</p>
<p>  주로 API를 통해 데이터를 요청하고 응답하는 데 사용</p>
</li>
</ul>
<h3 id="구조">구조</h3>
<ul>
<li><p>HTML통신은 일반적으로 HTML 태그를 사용하여 문서의 구조를 정함</p>
<p>  이는 웹 브라우저에서 렌더링되어 사용자에게 표시됨</p>
</li>
<li><p>JSON 통신은 키-값 쌍으로 구성된 데이터 객체를 사용하여 데이터를 표현</p>
<p>  JS를 통해 쉽게 파싱할 수 있으며 웹 애플리케이션에서 데이터를 처리하는데 사용됨</p>
</li>
</ul>
<h3 id="클라이언트-서버-상호작용">클라이언트-서버 상호작용</h3>
<ul>
<li>HTML 통신은 클라이언트가 서버에 HTML 페이지를 요청하고, 서버는 HTML 페이지를 응답</li>
<li>JSON 통신은 클라이언트가 서버에 데이터를 요청하고 서버는 해당 데이터를 JSON 형식으로 응답하는 방식으로 이루어짐</li>
</ul>
<p>⇒ 위 라우터는 웹 애플리케이션을 만드는 상황이므로 JSON 통신 사용해야함</p>
<p><code>res.json()</code> 은 Express에서 클라이언트에게 JSON 형식의 데이터를 보내는 메서드</p>
<p>→ 객체나 배열 등 JavaScript 객체를 JSON 형식으로 변환하여 클라이언트에게 전송</p>
<p><code>res.send()</code> 는 Express에서 클라이언트에게 다양한 형식의 데이터를 보내는 메서드</p>
<p>→ 주로 HTML, 텍스트, XML 등 다양한 형식의 데이터를 전송할 때 사용</p>
<p>JSON 데이터를 전송할 때 사용하기도 하지만 <code>res.json()</code> 사용하는 것이 일반적으로 좀 더 적합함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[error] listen EADDRINUSE address already in use 포트번호]]></title>
            <link>https://velog.io/@sing_/error-listen-EADDRINUSE-address-already-in-use-%ED%8F%AC%ED%8A%B8%EB%B2%88%ED%98%B8</link>
            <guid>https://velog.io/@sing_/error-listen-EADDRINUSE-address-already-in-use-%ED%8F%AC%ED%8A%B8%EB%B2%88%ED%98%B8</guid>
            <pubDate>Sun, 25 Feb 2024 14:11:52 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sing_/post/28dc3233-6080-4d77-8ef5-db74abd0ed77/image.png" alt=""></p>
<p>에러는 이제 알아보겠는데 아직 해결 코드를 못 외워서 아카이빙용으로 쓰는 글!</p>
<hr>
<p>&#39;포트 번호 사용 중&#39;이라는 에러</p>
<p>해결방안 -&gt; 똑같이 사용 중인 포트의 PID 번호 알아내고 kill</p>
<p><code>lsof -i :[포트번호]</code>
<code>kill -9 [PID번호]</code>
<code>npm start</code> 해서 서버 실행하면 정상 작동</p>
<hr>
<p>프로젝트 하는데 유독 맥 사용하는 나와 어떤 한 분께 이 에러가 자주 발생한다
맥에서 자주 발생하는 에러인가..?? 🧐</p>
<p>책상에 적어놓고 보다가 이럴거면 벨로그에 남기는게 나을 것 같아 써놓는 글!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[cd: string not in pwd]]></title>
            <link>https://velog.io/@sing_/cd-string-not-in-pwd</link>
            <guid>https://velog.io/@sing_/cd-string-not-in-pwd</guid>
            <pubDate>Sun, 18 Feb 2024 06:48:03 GMT</pubDate>
            <description><![CDATA[<p>간단한 에러를 마주했다
아카이빙용으로 쓰는 글</p>
<hr>
<p><img src="https://velog.velcdn.com/images/sing_/post/ce316de4-e075-426a-8e31-03685c93e5cb/image.png" alt=""></p>
<h2 id="😱-문제-상황">😱 문제 상황</h2>
<p>vscode로 실습 중에 발생한 오류</p>
<p>공부 중 폴더명에 대한 생각 없이 폴더를 한 번 정리하고 nodemon으로 서버 열려고 하니 동작안됨</p>
<h2 id="🫶-해결">🫶 해결</h2>
<p>역시 해결은... 간단했다!</p>
<p><code>cd: string not in pwd</code></p>
<p>폴더명에 띄어쓰기가 포함되었을 때 실행되는 오류인 것</p>
<p>해결 방법은 1. 역슬래시 붙이기 2. 폴더명을 따옴표로 감싸주기 </p>
<p><code>cd 2/ nodejs</code>
혹은
<code>cd &quot;2 nodejs&quot;</code></p>
<p>그러나 나한텐 쉽게 바꿀 수 있는 폴더명이어서 공백을 하이픈으로 대체했다</p>
<h2 id="-폴더명-짓기-규칙">+) 폴더명 짓기 규칙</h2>
<p>추가적으로 폴더 명명 규칙을 찾아보니 정설로 굳어진 것은 없지만, 대부분 <strong>공백, 하이픈, 언더스코어를 사용하기보단 대문자로 구분(카멜케이스) 사용을 권장</strong>하는 것 같다 !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[익명 함수와 선언적 함수의 차이]]></title>
            <link>https://velog.io/@sing_/%EC%9D%B5%EB%AA%85-%ED%95%A8%EC%88%98%EC%99%80-%EC%84%A0%EC%96%B8%EC%A0%81-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@sing_/%EC%9D%B5%EB%AA%85-%ED%95%A8%EC%88%98%EC%99%80-%EC%84%A0%EC%96%B8%EC%A0%81-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 18 Feb 2024 06:34:30 GMT</pubDate>
            <description><![CDATA[<p>while 반복문 - 조건을 중심으로 반복할 때
for 반복문 - 횟수를 중심으로 또는 배열 등을 중심으로 반복할 때 사용</p>
<p>그런데<strong>익명 함수와 선언적 함수는 사용하는 상황이 비슷</strong>함
편하고 손에 익은 걸 사용하면 되는데, 최근에는 안전 등의 이유로 많은 개발자가 익명 함수를 선호하는 편</p>
<blockquote>
<p>왜 익명 함수가 안전하다고 하는 걸까? 
어떤 차이가 있기에?</p>
</blockquote>
<h2 id="익명-함수">익명 함수</h2>
<p>익명함수 -&gt; 순차적인 코드 실행에서 코드가 해당 줄을 읽을 때 생성됨</p>
<p>따라서 다음과 같은 코드가 있다면 위에서 아래로 차례대로 코드가 실행되면서 익명함수라는 변수에 &#39;2번째 익명 함수입니다.&#39;를 호출하는 함수가 할당됨</p>
<pre><code class="language-js">let 익명함수

익명함수 = function () {
    console.log(&#39;1번째 익명 함수입니다.&#39;)
}

익명함수 = function () {
    console.log(&#39;2번째 익명 함수입니다.&#39;)
}

익명함수()

//출력: 2번째 익명함수입니다</code></pre>
<h2 id="선언적-함수">선언적 함수</h2>
<p>선언적 함수는 순차적인 코드 실행이 일어나기 전에 생성됨
따라서 선언적 함수는 같은 블록이라면 어디에서 함수를 호출해도 상관없음
다음 코드와 같이 선언적 함수를 생성하기 전에 함수를 호출해도 함수가 이미 생성된 상태이므로 아무 문제 없이 실행됨</p>
<pre><code class="language-js">선언적 함수() //호출! 테스트를 위해 생성 전에 입력해본 것

function 선언적 함수 () {
    console.log(&#39;1번째 선언적 함수입니다.&#39;)
}
function 선언적 함수 () {
    console.log(&#39;2번째 선언적 함수입니다.&#39;)
}

//출력: 2번째 선언적 함수입니다.</code></pre>
<p>선언적 함수도 입력한 순서대로 생성되고 같은 이름이라면 덮어쓰므로 코드를 실행했을 때 &quot;2번째 선언적 함수입니다.&quot;를 출력하는 모습을 볼 수 있음</p>
<h2 id="선언적-함수와-익명-함수의-조합-상황">선언적 함수와 익명 함수의 조합 상황</h2>
<p>두 가지 상황이 조합된 경우에는 <strong>선언적 함수는 먼저 생성되고, 이후에 순차적인 코드 진행을 시작하면서 익명 함수를 생성</strong></p>
<pre><code class="language-js">//예시

//익명 함수를 두 번 생성
함수 = function () {
    console.log(&#39;익명 함수입니다.&#39;)
}

//선언적 함수를 두 번 생성하고 할당함
function 함수 () {
    console.log(&#39;선언적 함수입니다.&#39;)
}

//함수를 호출
함수()</code></pre>
<p>익명함수는 코드를 읽을 때와 &#39;같은&#39; 순서로 함수가 선언되지만
선언적 함수는 코드를 읽는 순서와 다른 순서로 함수가 선언됨</p>
<p>따라서 함수를 같은 이름으로 덮어쓰는 건 위험한 일이기에 안전하게 사용 가능한 익명 함수를 선호</p>
<h2 id="블록이-다른-경우-선언적-함수의-사용">블록이 다른 경우 선언적 함수의 사용</h2>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
    &lt;title&gt;&lt;/title&gt;
        &lt;script&gt;
            선언적함수()

            function 선언적함수 () {
            console.log(&#39;1번째 선언적 함수입니다.&#39;)
            }
        &lt;/script&gt;
        &lt;script&gt;
            function 선언적함수 () {
            console.log(&#39;2번째 선언적 함수입니다.&#39;)
            }
        &lt;/script&gt;
        &lt;script&gt;
            선언적함수()
        &lt;/script&gt;
    &lt;/head&gt;
&lt;body&gt;&lt;/body&gt;

&lt;!-- 출력: 1번째 선언적 함수입니다. \n 2번째 선언적 함수입니다. --&gt;</code></pre>
<p><strong>블록이 나눠진 경우에 선언적 함수의 실행 흐름을 예측하는 것이 훨씬 힘들어짐</strong>
다른 프로그래밍 언어들은 일반적으로 선언적 함수 형태로 함수를 많이 사용하지만, 자바스크립트는 이처럼 블록이 예상하지 못하게 나뉘는 문제 등이 발생할 수 있어 익명 함수를 더 많이 사용</p>
<p>과거 자바스크립트는 var 키워드를 사용하여 변수를 선언했지만 이것은 전역 변수이므로 덮어쓰는 문제가 발생. 따라서 모던 자바스크립트는 let 키워드와 const 키워드를 이용해 변수와 상수를 선언하고 위험을 원천적으로 차단하기 위해서 오류를 발생시킴</p>
<hr>
<p>차이를 명확하게 구분하면서 공부하는 것이 필요하다 !! 대충 알고 넘어가면 나중에 헷갈리거더라거,,</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[나머지 매개변수와 전개 연산자의 차이]]></title>
            <link>https://velog.io/@sing_/%EB%82%98%EB%A8%B8%EC%A7%80-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EC%99%80-%EC%A0%84%EA%B0%9C-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@sing_/%EB%82%98%EB%A8%B8%EC%A7%80-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98%EC%99%80-%EC%A0%84%EA%B0%9C-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 18 Feb 2024 06:30:22 GMT</pubDate>
            <description><![CDATA[<p>프로젝트를 앞두고 자바스크립트 복습을 하던 중 궁금해진 것</p>
<pre><code class="language-javascript">function sample(...items) {
console.log(items)    
}

const array = [1, 2, 3, 4];

console.log(array)
console.log(...array)</code></pre>
<blockquote>
<p>둘 간의 차이가 정확히 무엇인지</p>
</blockquote>
<blockquote>
<p>나머지 매개변수의 자리라는 것 자체가 &#39;배열&#39;을 만들어주는 건데 <strong>array를 넣으면 [[1, 2, 3, 4]]가 되어야 하고, ...array를 넣으면 [1, 2, 3, 4] 가 되어야하는 것</strong>이 아닌가?</p>
</blockquote>
<p>의문이 생긴 이유는 후에 알아보니 <code>console.log()</code>를 <code>sample()</code>로 착각해서 생긴 것이었다! 하지만 의문을 풀기 위해 다시 공부하며 정리가 잘 되었으니 블로그에 남겨보자</p>
<hr>
<h2 id="나머지-매개변수-rest-parameter">나머지 매개변수 Rest Parameter</h2>
<pre><code class="language-js">function sum(...numbers) { // numbers는 배열로 처리됨 }</code></pre>
<ul>
<li>함수 정의 시에 사용되며 <strong>함수의 매개변수</strong>로 선언됨</li>
<li>매개변수의 목록 끝에 ...를 붙이고 그 뒤에 나머지 인자들을 모아 배열로 처리</li>
<li>함수 호출 시 전달되는 인자 중 명시된 매개변수 외의 나머지 인자들을 배열로 묶어주는 역할을 함<h2 id="전개-연산자-spread-operator">전개 연산자 Spread Operator</h2>
<pre><code class="language-js">const numbers = [1, 2, 3];
console.log(...numbers); // 1 2 3</code></pre>
</li>
<li>배열이나 객체를 해체하거나 전달할 때 사용됨
= 배열이나 객체의 요소를 분리하거나 병합할 때 사용됨</li>
<li>함수 호출 시에는 배열이나 객체를 해체하여 각 요소를 개별 인자로 전달하는데 사용될 수 있음<h2 id="차이점">차이점</h2>
</li>
<li><strong>나머지 매개변수는 함수 정의 시 사용</strong>되며, 함수의 매개변수 목록의 끝에 위치함</li>
<li><strong>전개 연산자는 함수 호출 시 사용</strong>되며, 인자를 전개하거나 배열/객체를 해체하는데 사용됨</li>
</ul>
<p>풀어서 설명하면 이 예시에서</p>
<pre><code class="language-js">function sample(...items) {
console.log(items)    
}

const array = [1, 2, 3, 4];

console.log(array)
console.log(...array)</code></pre>
<p>함수를 호출할 때 <code>array</code>와 전개 연산자 <code>...array</code>는 배열을 전달하느냐, 배열 안의 각 요소를 &#39;전달&#39;하느냐의 차이
<strong>즉, 전달에 관한 이야기</strong></p>
<p>이러한 상황에서 함수 정의 시 사용되는 <code>...items</code>는 전달된 매개변수를 &#39;배열&#39;로 받는 것이고 <code>items</code>는 그냥 인수 그 자체로 받는 것</p>
<p>따라서 
<code>console.log(array)</code>는 [1, 2, 3, 4]
<code>console.log(...array)</code>는 1, 2, 3, 4</p>
<p>이 상황에서 만약 <code>sample(...items)</code>의 인수로 <code>array</code>와 <code>...array</code>를 각각 전달한다면</p>
<p><code>sample(array)</code>일 때 
인수로는 [1, 2, 3, 4]를 전달하고
<code>...items</code>는 전달된 매개변수를 배열 items의 요소(배열 items를 만듦)로 받기 때문에 
items = [[1, 2, 3, 4]]가 되는 것, 
그래서 출력은 [[1, 2, 3, 4]]</p>
<p><code>sample(...array)</code>는 
전개연산자를 통해 1, 2, 3, 4를 전달했고
<code>...itms</code>는 전달된 매개변수를 역시 배열로 만들어 받기 때문에
출력은 [1, 2, 3, 4]</p>
<hr>
<p>혹시 또 헷갈리면 찾아와서 보려고 길게 적었으나
정리하자면 
나머지 매개변수는 들어온 매개변수를 배열로 &#39;받음&#39;의 문제
전개연산자는 배열을 풀어서 배열의 각 요소를 인수로 &#39;전달&#39;할 때 사용!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 19장 프로토타입]]></title>
            <link>https://velog.io/@sing_/%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-19%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@sing_/%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-19%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</guid>
            <pubDate>Sun, 11 Feb 2024 10:36:09 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트를 지칭할 때 <strong>프로토타입 기반의 객체 지향 프로그래밍 언어</strong>라는 말을 들어본 적 있을 것이다</p>
<p>나도 공식 문서에서 메서드를 찾아볼 때 array.prototype.~~  중 항상 &#39;prototype&#39;은 무슨 뜻일까? 궁금했던 기억이 있다</p>
<p>오늘은 그 &#39;프로토타입&#39;에 관해 배우는 날!</p>
<hr>
<p>자바스크립트는 객체 기반의 프로그래밍 언어이며 <strong>자바스크립트를 이루고 있는 거의 모든 것이 객체</strong>
원시 타입을 제외한 나머지 값들(함수, 배열, 정규 표현식 등)은 모두 객체</p>
<h2 id="객체-지향-프로그래밍">객체 지향 프로그래밍</h2>
<p>프로그램을 명령어 또는 함수의 목록으로 보는 전통적인 명령형 프로그래밍의 절차지향적 관점에서 벗어나 여러 개의 독립적 단위, 즉 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임</p>
<p>객체 지향 프로그래밍은 실세계의 &#39;실체&#39; 개념을 프로그래밍에 접목하려는 것이서 시작한다. 실세계의 사물들은 각 개별적인 속성을 가지고 있고, 이로써 다른 사람이나 사물과 구분된다.</p>
<p>프로그래밍에 이를 접목시켜보면 &quot;이름&quot;과 &quot;속성&quot;에 관심이 있다고 친다
다양한 속성 중에서 프로그램에 필요한 속성만 간추려 표현하는 것을 <strong>추상화</strong>라고 하는데,
이 속성을 갖는 객체를 자바스크립트로 표현하면 </p>
<pre><code class="language-js">const person = {
    name: &#39;Lee&#39;,
    address: &#39;Seoul&#39;
};

console.log(person);</code></pre>
<p>이때 주체인 프로그래머는 이름과 주소 속성으로 표현된 객체(object)인  person을 다른 객체와 구별하여 인식할 수 있음</p>
<p>이처럼 속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합적인 자료구조를 객체라고 하며, 객체지향 프로그래밍은 독립적인 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임임</p>
<p>만약 원이라는 개념을 객체로 만들어보면 원에는 &#39;반지름&#39;이 있고 이것으로 지름, 둘레, 넓이 등을 구할 수 있음
이때 반지름은 &#39;상태를 나타내는 데이터&#39;이며 지름, 둘레, 넓이를 구하는 것은 &#39;동작&#39;이다.</p>
<p>이처럼 객체지향프로그래밍은 객체의 <strong>상태</strong>를 나태내는 데이터와 상태 데이터를 조작할 수 있는 <strong>동작</strong>을 하나의 논리적인 단위로 묶어 생각함
-&gt; <strong>객체는 상태 데이터와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조</strong></p>
<p>이때 객체의 상태 데이터를 프로퍼티, 동작을 메서드라고 함</p>
<h2 id="상속과-프로토타입">상속과 프로토타입</h2>
<p>상속은 객체지향 프로그래밍의 핵심 개념으로, 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받을 수 있다</p>
<p>이는 코드의 재사용적 관점에서 매우 유용함
<strong>생성자 함수가 생성할 모든 인스턴스가 공통적으로 사용할 프로퍼티나 메서드를 프로토타입에 미리 구현해 두면 생성자 함수가 생성할 모든 인스턴스는 별도의 구현 없이 상위(부모) 객체인 프로토타입의 자산을 공유하여 사용 가능</strong></p>
<pre><code class="language-js">// 생성자 함수
function Circle(radius) {
  this.radius = radius;
}

// Circle 생성자 함수가 생성한 모든 인스턴스가 getArea 메서드를
// 공유해서 사용할 수 있도록 프로토타입에 추가한다.
// 프로토타입은 Circle 생성자 함수의 prototype 프로퍼티에 바인딩되어 있다.
Circle.prototype.getArea = function () {
  return Math.PI * this.radius ** 2;
};

// 인스턴스 생성
const circle1 = new Circle(1);
const circle2 = new Circle(2);

// Circle 생성자 함수가 생성한 모든 인스턴스는 부모 객체의 역할을 하는
// 프로토타입 Circle.prototype으로부터 getArea 메서드를 상속받는다.
// 즉, Circle 생성자 함수가 생성하는 모든 인스턴스는 하나의 getArea 메서드를 공유한다.
console.log(circle1.getArea === circle2.getArea); // true

console.log(circle1.getArea()); // 3.141592653589793
console.log(circle2.getArea()); // 12.566370614359172</code></pre>
<p>Circle 생성자 함수가 생성한 모든 인스턴스는 자신의 상위 객체 역할을 하는 Circle.prototype의 모든 프로퍼티와 메서드를 상속 받음
<strong>getArea 메서드</strong>는 <strong>딱 한 번 생성되어 프로토타입인 Circle.prototype의 메서드</strong>로 할당되어있다
따라서 Circle 생성자 함수가 생성하는 모든 인스턴스는 getArea 메서드를 상속받아 사용할 수 있음
즉, 자신의 상태를 나타내는 radius 프로퍼티만 개별적으로 소유하고 내용이 동일한 메서드는 상속을 통해 공유하여 사용</p>
<h2 id="프로토타입-객체">프로토타입 객체</h2>
<p>프로토타입 객체란 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구현하기 위해 사용됨
프로토타입은 어떤 객체의 상위(부모) 객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드 포함)을 제공</p>
<p><strong>모든 객체는 [ [Prototype]] 이라는 내부 슬롯을 가지며, 이 안에 저장되는 프로토타입은 객체 생성 방식에 의해 결정됨</strong>
<strong>모든 객체는 하나의 프로토타입을 가지고, 모든 프로토타입은 생성자 함수와 연결되어 있다</strong>
<img src="https://user-images.githubusercontent.com/80154058/144704014-2f03263c-d4cc-4704-84cb-b1650afd5d48.png" alt="image"></p>
<h3 id="_-_-proto__-접근자-프로퍼티">_ _ proto__ 접근자 프로퍼티</h3>
<p><strong><code>__proto__</code>는 접근자 프로퍼티</strong>
모든 객체는 [ [Prototype]] 내부 슬롯에는 직접 접근할 수 없지만, 위 그림처럼 <code>__proto__</code> 접근자 프로퍼티를 통해 자신의 프로토타입에 간접적으로 접근할 수 있음</p>
<p>내부 슬롯은 프로퍼티가 아니기에 직접 접근하거나 호출할 수 없지만, 간접적으로 접근할 수 있음</p>
<p>Object.prototype의 접근자 프로퍼티인 <code>__proto__</code>는 접근자 함수 ([ [GET]], [ [SET]] 프로퍼티에 어트리뷰트에 할당된 함수)를 통해 프로토타입을 취득하거나 할당함</p>
<p><strong><code>__proto__</code>는 상속을 통해 사용됨</strong></p>
<p><code>__proto__</code> 접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아니아  Object.prototype의 프로퍼티
-&gt; 모든 객체는 상속을 통해 Object.prototype.<code>__proto__</code> 접근자 프로퍼티를 사용 가능함</p>
<p>모든 객체는 프로토타입의 계층 구조인 프로토타입 체인데 묶여있는데, 프로토타입 체인의 최상위 객체는 Object.prototype이며 이 객체의 프로퍼티와 메서드는 모든 객체에 상속됨</p>
<p><strong><code>__proto__</code> 접근자 프로퍼티를 통해 프로토타입에 접근하는 이유</strong> 
프로토타입에 접근하기 위해 접근자 프로퍼티를 사용하는 이유는 <strong>상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서</strong>임</p>
<pre><code class="language-js">const parent = {};
const child = {};

// child의 프로토타입을 parent로 설정
child.__proto__ = parent;
// parent의 프로토타입을 child로 설정
parent.__proto__ = child; // TypeError: Cyclic __proto__ value</code></pre>
<p>이렇게 하면 서로가 자신의 프로토타입이 되는 비정상적인 프로토타입이 만들어짐</p>
<p>프로토타입은 단방향 링크드 리스트로 구현되어 <strong>프로퍼티 검색 방향이 반드시 한쪽 방향으로만 흘러가야 함</strong>
그러나 순환 참조하는 프로토타입 체인이 발생하면 프로토타입 체인에서 프로퍼티를 검색할 때 무한 루프에 빠짐
따라서 아무런 체크 없이 무조건적으로 프로토타입을 교체할 수 없도록 <code>__proto__</code> 접근자 프로퍼티를 통해 프로토타입에 접근하고 교체하도록 구현되어 있음</p>
<p><strong><code>__proto__</code> 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않음</strong>
직접 상속을 통해 Object.prototype을 상속받지 않느 ㄴ객체를 생성할수도 있기 때문에 <code>__proto__</code> 접근자 프로퍼티를 사용할 수 없는 경우가 있음
따라서</p>
<ul>
<li>프로토타입의 참조를 취득하고 싶은 경우 -&gt; Object.getPrototypeOf 메서드 사용을 권장</li>
<li>프로토타입을 교체하고 싶은 경우 -&gt; Object.setPrototypeOf 메서드 사용을 권장<h3 id="함수-객체의-prototype-프로퍼티">함수 객체의 prototype 프로퍼티</h3>
함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킴</li>
</ul>
<pre><code class="language-js">// 함수 객체는 prototype 프로퍼티를 소유한다.
(function () {}).hasOwnProperty(&#39;prototype&#39;); // -&gt; true

// 일반 객체는 prototype 프로퍼티를 소유하지 않는다.
({}).hasOwnProperty(&#39;prototype&#39;); // -&gt; false</code></pre>
<p>prototype 프로퍼티는 생성자 함수가 생성할 객체의 프로토타입을 가리킴
따라 생성자 함수로서 호출할 수 없는 함수로 정의한 메서드는 prototype 프로퍼티를 소유하지 않으며 프로토타입도 생성하지 않음</p>
<p>모든 객체가 가지고 있는 <code>__proto__</code> 접근자 프로퍼티와 함수 객체만이 가지고 있는 prototype 프로퍼티는 결국 동일한 프로토타입을 가리킴
하지만 이들의 주체와 용도는 다름!</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>소유</th>
<th>값</th>
<th>사용 주체</th>
<th>사용 목적</th>
</tr>
</thead>
<tbody><tr>
<td><code>__proto__</code> 접근자 프로퍼티</td>
<td>모든 객체</td>
<td>프로토타입의 참조</td>
<td>모든 객체</td>
<td>객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용</td>
</tr>
<tr>
<td>prototype 프로퍼티</td>
<td>constructor</td>
<td>프로토타입의 참조</td>
<td>생성자 함수</td>
<td>생성자 함수가 자신이 생성할 객체(인스턴스)의 프로토타입을 할당하기 위해 사용</td>
</tr>
<tr>
<td>### 프로토타입의 constructor 프로퍼티와 생성자 함수</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>모든 프로토타입은 constructor 프로퍼티를 가짐</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>이 constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킴</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><strong>이 연결은 생성자 함수가 생성될 때(=함수 객체가 생성될 때) 이루어짐</strong></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-js">// 생성자 함수
function Person(name) {
  this.name = name;
}

const me = new Person(&#39;Lee&#39;);

// me 객체의 생성자 함수는 Person이다.
console.log(me.constructor === Person);  // true</code></pre>
<p><img src="https://velog.velcdn.com/images/kozel/post/a49c1424-8ee6-4970-820e-adec1360c86a/image.jpeg" alt="">
me 객체에는 constructor 프로퍼티가 없지만 me 객체의 프로토타입인 Person.prototype에는 constructor 프로퍼티가 있음
따라서 me 객체는 프로토타입인 Person.prototype의 constructor 프로퍼티를 상속 받아 사용할 수 있는 것</p>
<h2 id="리터럴-표기법에-의해-생성된-객체의-생성자-함수와-프로토타입">리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입</h2>
<p>리터럴 표기법에 의한 객체 생성 방식은 <strong>명시적으로 new 연산자와 함께 생성자 함수를 호출하여 인스턴스를 생성하지 않는 객체 생성 방식임</strong></p>
<p>[[리터럴]]의 예시)</p>
<pre><code class="language-js">// 객체 리터럴
const obj = {};

// 함수 리터럴
const add = function (a, b) { return a + b; };

// 배열 리터럴
const arr = [1, 2, 3];

// 정규표현식 리터럴
const regexp = /is/ig;</code></pre>
<p>리터럴 표기법에 의해 생성된 객체도 프로토타입이 존재하지만, <strong>프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수는 없다</strong></p>
<pre><code class="language-js">// obj 객체는 Object 생성자 함수로 생성한 객체가 아니라 객체 리터럴로 생성했다.
const obj = {};

// 하지만 obj 객체의 생성자 함수는 Object 생성자 함수다.
console.log(obj.constructor === Object); // true</code></pre>
<p>왜일까? 
Object 생성자 함수에 인수를 전달하지 않거나 undefined 또는 null을 인수로 전달하면서 호출하면 내부적으로는 추상 연산 OrdinaryObjectCreate를 호출하여 Object.prototype을 프로토타입으로 갖는 빈 객체를 생성함</p>
<p>이처럼 Object 생성자 함수 호출과 객체 리터럴의 평가는 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성하는 점에서 동일하나 세부 내용은 다르다.<br>따라서 객체 리터럴에 의해 생성된 객체는 Object 생성자 함수가 생성한 객체가 아니다.</p>
<p>==함수 객체의 경우 역시 차이가 명확한데
함수 선언문과 함수 표현식을 평가하여 함수 객체를 생성한 것은 Function 생성자 함수가 아니다. constructor 프로퍼티를 통해 확인해보면 foo 함수의 생성자 함수는 Function 생성자 함수다==</p>
<ul>
<li><input disabled="" type="checkbox"> 240204 제대로 이해하지 못함!</li>
</ul>
<pre><code class="language-js">// foo 함수는 Function 생성자 함수로 생성한 함수 객체가 아니라 함수 선언문으로 생성했다.
function foo() {}

// 하지만 constructor 프로퍼티를 통해 확인해보면 함수 foo의 생성자 함수는 Function 생성자 함수다.
console.log(foo.constructor === Function); // true</code></pre>
<p>리터럴 표기법에 의해 생성된 객체도 상속을 위해서는 프로토타입이 필요함
다라서 리터럴 표기법에 의해 생성된 객체도 가상적인 생성자 함수를 가짐</p>
<p>프로토타입은 생성자 함수와 더불어 생성되며 prototype, constructor 프로퍼티에 의해 연결되어있기 때문</p>
<p>=&gt; 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 pair으로 존재함</p>
<p>리터럴 표기법에 의해 생성한 객체도 생성자 함수로 생성한 객체와 본질적인 면에서 큰 창는 없으므로, 프로토타입의 constructor 프로퍼티를 통해 연결되어 있는 생성자 함수를 리터럴 표기법으로 생성한 객체를 생성자 함수로 생각해도 큰 무리는 없음</p>
<table>
<thead>
<tr>
<th>리터럴 표기법</th>
<th>생성자 함수</th>
<th>프로토 타입</th>
</tr>
</thead>
<tbody><tr>
<td>객체 리터럴</td>
<td>Object</td>
<td>Object.prototype</td>
</tr>
<tr>
<td>함수 리터럴</td>
<td>Function</td>
<td>Function.prototype</td>
</tr>
<tr>
<td>배열 리터럴</td>
<td>Array</td>
<td>Array.prototype</td>
</tr>
<tr>
<td>정규 표현식 리터럴</td>
<td>RegExp</td>
<td>RegExp.prototype</td>
</tr>
<tr>
<td>## 프로토타입의 생성 시점</td>
<td></td>
<td></td>
</tr>
<tr>
<td>객체는 리터럴 표기법 또는 생성자 함수에 의해 생성되므로 결국 모든 객체는 생성자 함수와 연결되어 있음</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성됨</strong>
생성자 함수는 단독으로 존재할 수 없고, 언제나 쌍으로 존재하기 때문</p>
<p>생성자 함수는 두 종류가 있다</p>
<ul>
<li>사용자 정의 생성자 함수</li>
<li>빌트인 생성자 함수<h3 id="사용자-정의-생성자-함수와-프로토-타입-생성-시점">사용자 정의 생성자 함수와 프로토 타입 생성 시점</h3>
생성자 함수로서 호출할 수 있는 함수(=constructor)는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입이 같이 생성되고, 생성된 프로토타입의 프로토타입은 언제나 Object.prototype임
(화살표 같은 non-constructor은 프로토타입이 생성되지 않음)<h3 id="빌트인-생성자-함수와-프로토타입-생성-시점">빌트인 생성자 함수와 프로토타입 생성 시점</h3>
Object, String, Number, Function, Array, RegExp, Date, Promise 등과 같은 빌트인 생성자 함수도 생성되는 시점에 프로토타입이 생성된됨</li>
</ul>
<p><strong>모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성되고 생성된 프로토타입은 빌트인 생성자 함수의 prototype 프로퍼티에 바인딩</strong>됨</p>
<p>전역 객체는 코드가 실행되기 이전에 자바스크립트 엔진에 의해 생성되는 특수한 객체로, 표준 빌트인 객체인 Object도 전역 객체의 프로퍼티이며 전역 객체가 생성되는 시점에 생성됨. </p>
<p>이처럼 객체가 생성되기 이전에 생성자 함수와 프로토타입은 이미 객체화 되어 존재하고, <strong>이후 생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성된 객체의 [[Prototype]] 내부 슬롯에 할당됨.</strong></p>
<h2 id="객체-생성-방식과-프로토타입의-결정">객체 생성 방식과 프로토타입의 결정</h2>
<p>객체 생성에는 객체 리터럴/Object 생성자 함수/ 생성자 함수/Object.create메서드/클래스(ES6) 등 다양한 방식이 있음.
그러나 세부적인 방식의 차이는 있으나 추상 연산 OrdinaryObjectCreate에 의해 생성된다는 공통점이 있음</p>
<p>추상 연산 OrdinaryObjectCreate의 객체 생성 과정</p>
<ol>
<li>빈 객체를 생성</li>
<li>객체에 추가할 프로퍼티 목록이 인수로 전달된 경우 프로퍼티를 객체에 추가</li>
<li>인수로 전달받은 프로토타입을 자신이 생성한 객체의 [[Prototype]] 내부 슬롯에 할당</li>
<li>생성한 객체 반환
 -&gt; 즉, 프로토타입은 추상연상 </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[궁금증] 서버를 열 때 사용되는 언어는 JS인데, 왜 Node.js로 서버를 연다고 할까?]]></title>
            <link>https://velog.io/@sing_/%EA%B6%81%EA%B8%88%EC%A6%9D-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%97%B4-%EB%95%8C-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-%EC%96%B8%EC%96%B4%EB%8A%94-Java-Script%EC%9D%B8%EB%8D%B0-%EC%99%9C-Node.js%EB%A1%9C-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%97%B0%EB%8B%A4%EA%B3%A0-%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@sing_/%EA%B6%81%EA%B8%88%EC%A6%9D-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%97%B4-%EB%95%8C-%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94-%EC%96%B8%EC%96%B4%EB%8A%94-Java-Script%EC%9D%B8%EB%8D%B0-%EC%99%9C-Node.js%EB%A1%9C-%EC%84%9C%EB%B2%84%EB%A5%BC-%EC%97%B0%EB%8B%A4%EA%B3%A0-%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Fri, 09 Feb 2024 08:24:21 GMT</pubDate>
            <description><![CDATA[<h2 id="궁금증">궁금증</h2>
<p>이번 주에는 서버를 배우고 있다
게시판 CRUD하는 법을 배우고 있는데,,,
아직 개념 정립이 완전히 되지 않아 문득 든 질문!</p>
<blockquote>
<p>🧐 서버를 열 때는 JavaScript 파일을 작성하는데 왜 Node.js로 서버를 연다고 말할까?
각자의 명확한 역할이 무엇이지?</p>
</blockquote>
<p>왜일까...?
이것을 알아보려면 먼저 Node.js와 JavaScript가 어떤 관계에 놓여있는지부터 살펴보아야 한다</p>
<h2 id="먼저-nodejs와-javascript의-관계">먼저, Node.js와 JavaScript의 관계</h2>
<p>Node.js와 브라우저 안에서 실행되던 언어인 JavaScript를 브라우저 밖에서도 실행하게 도와주는 &#39;런타임 환경&#39;</p>
<h3 id="nodejs란">Node.js란?</h3>
<p>Node.js는 <strong>V8엔진 + libuv(event loop) +Node.js API</strong>으로 구성되어 있다</p>
<p>각 구성요소를 살펴보면</p>
<ul>
<li><p><strong>V8엔진</strong>
코드를 해석하고 실행하는 것을 담당</p>
</li>
<li><p><strong>libuv(event loop)</strong>
싱글스레드로 작동하는 이벤트루프
C로 작성됨
동기/비동기 작업에 대한 이벤트가 발생했을 때 해당 이벤트에 할당된 콜백 함수들을 각종 큐에서 정해진 순서에 맞게 꺼내어 엔진에게 전달하는 역할</p>
</li>
<li><p><strong>Node.js API: JS/C/C++ 기반의 라이브러리</strong>
Node.js에서 제공하는 독자적인 비동기/동기의 API들
브라우저가 아닌 일반 환경에서 실행되기 때문에 <strong>브라우저의 Web API와는 다른 라이브러리들이 포함되어 있음</strong>
예를 들면 <code>fs</code>, <code>path</code> 등</p>
</li>
</ul>
<p>-&gt; 이 부분에서 세 번째, Node.js가 제공하는 각종 라이브러리가 서버를 실행할 수 있도록 하는 역할을 담당하는 것!</p>
<h3 id="브라우저는-서버를-실행할-수-없다">브라우저는 서버를 실행할 수 없다</h3>
<p>Node.js가 서버를 실행할 수 있도록 하는 역할을 한다는 것은 알았다</p>
<p>그러나 여기서 다시 발생한 의문은</p>
<blockquote>
<p>브라우저와 Node.js가 둘 다 &#39;실행환경&#39;아닌가..? 브라우저에서는 서버를 열 수 없나? </p>
</blockquote>
<p>여기서 브라우저와 Node.js와의 차이가 명확해진다</p>
<p>브라우저는 똑같이 자바스크립트의 실행환경을 제공하지만, 웹 페이지를 표시하고 사용자와 상호작용하는데 &#39;사용&#39;되는 클라이언트 측의 환경인 반면
서버는 데이터를 저장하고 처리하며 클라이언트에게 제공하는 역할
따라서 브라우저는 클라이언트 측, 서버는 백엔드 측이라고 말할 수 있다</p>
<h3 id="서버를-실행할-수-있게-해주는-nodejs의-기능">서버를 실행할 수 있게 해주는 Node.js의 기능</h3>
<p>Node.js는 자바스크립트의 런타임 환경인 동시에 서버를 열 수 있는 여러 가지 모듈을 제공한다</p>
<p>예를 들면,</p>
<p><strong>- HTTP 모듈</strong>
Node.js에는 HTTP 모듈이 내장되어 있다
*HTTP 모듈: http 서버와 클라이언트를 생성하는 것과 관련된 모든 기능을 담당하는 Node.js의 가장 기본적인 모듈</p>
<p><strong>- Express.js</strong>
Node.js의 웹 애플리케이션을 더욱 쉽게 작성할 수 있도록 만들어주는 웹 프레임워크
*프레임워크: Framework(프레임워크)는 어떤 어플리케이션을 개발하기 위해 필요한 기본적인 클래스와. 라이브러리등이 모두 포함되어있는 환경</p>
<p>*<em>- 파일시스템 모듈 *</em>
파일 시스템에 접근하고 파일을 읽고 쓸 수 있도록 하는 모듈</p>
<p>이 외에도 Node.js에서는 기타 등등의 라이브러리, 모듈을 제공하고, 이것들을 사용해 서버를 열고 관리할 수 있는 것!</p>
<h3 id="-nodejs와-같은-레벨의-개념-서버를-열-수-있는-다른-도구들">+) Node.js와 같은 레벨의 개념. 서버를 열 수 있는 다른 도구들</h3>
<p>첫 언어가 JavaScript이고 아직 다른 언어들에 대해 몰라서 조금 더 찾아본 것
Node.js 외에도 서버를 열 수 있는 Java Servlets, Django, Ruby on Rails, Go(Golang) 등의 도구가 있다</p>
<h3 id="결론-따라서-nodejs로-서버를-연다는-말은">결론. 따라서 Node.js로 서버를 연다는 말은</h3>
<p> = Node.js를 사용하여 서버를 실행하고, 그 안에서 JavaScript 코드를 실행하여 서버를 구동한다</p>
<p>결국 JavaScript로 작성되는 코드를 실행할 때 Node.js가 그 밑바탕의 결정적인 역할을 한다</p>
<p><strong>자바스크립트만으로는 서버를 열 수 없고 Node.js가 모듈, 기능을 제공하여 서버를 &#39;실행&#39;하는 역할을 하기에 Node.js로 서버를 연다고 말하는 것!</strong></p>
<hr>
<p>의문점 해결 완료 !!!! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Book] 그림과 작동 원리로 쉽게 이해하는 서버의 기초]]></title>
            <link>https://velog.io/@sing_/%EC%B1%85-%EA%B7%B8%EB%A6%BC%EA%B3%BC-%EC%9E%91%EB%8F%99-%EC%9B%90%EB%A6%AC%EB%A1%9C-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EC%84%9C%EB%B2%84%EC%9D%98-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@sing_/%EC%B1%85-%EA%B7%B8%EB%A6%BC%EA%B3%BC-%EC%9E%91%EB%8F%99-%EC%9B%90%EB%A6%AC%EB%A1%9C-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EB%8A%94-%EC%84%9C%EB%B2%84%EC%9D%98-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Mon, 05 Feb 2024 10:14:53 GMT</pubDate>
            <description><![CDATA[<p>지난 주부터 Node.js와 백엔드 기초에 들어갔는데 처음 들어보는 개념에 머리가 핑핑 돌아서 기초를 다루는 책을 빌렸다!</p>
<p>수업에서 다루는 내용인 1장, 2장 위주로 발췌독! 기본적인 내용만 아주 조금 읽은 거라, 평가를 하긴 어렵지만 그림이 있으니 이해가 편했다</p>
<hr>
<h1 id="1장---서버란">1장 - 서버란</h1>
<h2 id="01-서버란">01 서버란</h2>
<p>server = serve(제공하다) + er(~하는 사람, 물건)
<strong>컴퓨터에서 서버란 네트워크 상에서 클라이언트에게 정보를 제공하는 작업을 수행하는 컴퓨터 시스템</strong>이다</p>
<p>서버는 아주 일상적으로 사용되는데 크롬이나 사파리 같은 웹 브라우저를 사용해 포털사이트에서 다양한 정보를 검색할 때도 서버를 사용하는 것</p>
<p>이때
<strong>클라이언트 = 웹 브라우저</strong>
<strong>서버 = 검색 서비스를 제공하는 업체의 컴퓨터</strong> </p>
<h2 id="02-클라이언트서버-시스템">02 클라이언트/서버 시스템</h2>
<p><strong>서버의 처리는 클라이언트의 요청에서 시작</strong>된다</p>
<p><strong>클라이언트로부터 요청(request)을 받아서 처리를 시작하고, 서비스를 제공(응답, response)</strong>한다</p>
<p>서버가 클라이언트에 대해 서비스를 제공할 때 서버와 클라이언트 사이에는 밑의 순서에 따라 처리가 된다</p>
<ol>
<li><strong>클라이언트</strong>는 서버에 무언가의 서비스를 <strong>요청</strong></li>
<li><strong>서버는 요청에 따라 맞춰 처리를 수행</strong></li>
<li><strong>서버는 처리 결과를 클라이언트로 반환</strong></li>
<li><strong>클라이언트는 처리 결과를 받음</strong></li>
</ol>
<p>웹서비스를 예로 든다면
클라이언트는 safari , <strong>현재 요청한 서비스는 구글 사이트를 열어달라</strong>는 것.
이때 <strong>서버는 구글 사이트의 구성파일이 있는 컴퓨터</strong>라고 생각해볼수 있다!</p>
<p>이에 맞춰 순서를 적용해서 생각해보면 </p>
<ol>
<li>클라이언트는 서버에 무언가의 서비스를 요청
 -&gt; 사파리는 서버에 &#39;구글 사이트의 데이터를 달라&#39;고 요청</li>
<li>서버는 요청에 따라 맞춰 처리를 수행
 -&gt; 서버는 구글 사이트의 파일(데이터)을 찾음</li>
<li>서버는 처리 결과를 클라이언트로 반환
 -&gt; 서버는 구글 사이트의 파일(데이터)을 사파리에 반환</li>
<li>클라이언트는 처리 결과를 받음
 -&gt; 사파리는 구글 사이트의 파일을 받아서 화면에 표시</li>
</ol>
<p>이렇게 <strong>서버와 클라이언트로 구성된 시스템을 &#39;클라이언트/서버 시스템&#39;</strong> 이라고 부르는데, 
클라이언트/서버 시스템은 서버에서 데이터를 일원적으로 보다 쉽게 관리할 수 있어 대부분의 컴퓨터 시스템에서 사용되고 있다</p>
<h2 id="03-다양한-서버">03 다양한 서버</h2>
<p>서버의 역할은 <strong>서비스</strong>에 따라 결정된다</p>
<p>컴퓨터의 서버는 <strong>역할</strong>이 다양하고, 그 역할을 결정하는 것이 <strong>서비스</strong>
휴대폰으로 하는 카카오톡이나 트위터, 웹이나 메일 역시 서비스임
이때 클라이언트는 휴대폰이나 노트북, 탭이라는 &#39;단말기&#39;나 &#39;브라우저&#39;등 다양한 것이 클라이언트가 될 수 있고
서버의 서비스를 받고 있는 것
-&gt; 따라 수많은 서비스가 있는 만큼 다양한 서비스가 존재한다</p>
<p><strong>네트워크 상에서 전달되는 정보는 모두 무언가의 서비스</strong>이다
따라 서버를 생각할 때 서비스의 이름을 앞에 붙여 &#39;ㅇㅇ서버&#39;라고 생각해보면 됨</p>
<p>예를 들어 웹서비스를 웹 클라이언트에 제공하는 컴퓨터는 &#39;웹서버&#39;
메일을 송수신하는 서비스를 메일 클라이언트에 제공하는 컴퓨너는 &#39;메일 서버&#39;
+) 웹서버는 HTTP서버나 HTTPS, 메일 서버는 SMTP서버나 POP 서버로 불리기도 하는데 이는 서비스를 제공하는 방법에 따라 다소 다르게 부르는 명칭일 뿐 본질적으로 크게 다르지 않다</p>
<h2 id="04-서버-소프트웨어">04 서버 소프트웨어</h2>
<p>서버를 구축하기 위해서는 <strong>컴퓨터에 소프트웨어를 설치하고 기동</strong>해보면 된다
데스크탑, 노트북 등으로 서버를 구축할 수 있다</p>
<p><strong>서버 소프트웨어</strong>
서버 소프트웨어 = 서비스를 제공하기 위한 기능을 가진 소프트웨어
예를들어 메일 서비스를 제공하는 소프트웨어는 메일 서버 소프트웨어이며 이 소프트웨어가 작동하고 있는 컴퓨터가 메일 서버인 것</p>
<p>서버는 결국 &#39;서버 소프트웨어가 제공하는 기능&#39;이다
따라서 PC나 휴대폰에서도 여러 어플리케이션 소프트웨어를 동시에 작동시킬 수 있는 것처럼
한 대의 컴퓨터에서 여러 서버 소프트웨어를 실행시킬 수도 있게 된다</p>
<h2 id="05-구축할-서버의-종류와-서버-소프트웨어-선정">05 구축할 서버의 종류와 서버 소프트웨어 선정</h2>
<p>구축할 <strong>서버의 종류는 사용자의 &#39;요구&#39;에 따라 결정</strong>되는데,</p>
<p>쉽게 말해
메일을 송신하고 싶다는 요구가 있다면 -&gt; 메일 서버
데이터를 공유하고 싶다는 요구가 있다면 -&gt; 데이터를 한 곳에서 관리하는 파일서버 
이런 식으로 생각할 수있다</p>
<p>이렇게 구축할 서버의 종류가 결정되면 그 다음 단계는 <strong>어떤 서버 소프트웨어를 설치할 것인가</strong>
서버 소프트웨어는 일반적으로 사용하는 것들이 정해져있기에 그 중에 알맞은 것을 고르면 된다</p>
<h2 id="07-서버와-네트워크">07 서버와 네트워크</h2>
<hr>
<p>서버와 클라이언트 사이의 정보에 대한 가교 역할을 하는 기술이 &#39;네트워크&#39;
<strong>모든 서버는 네트워크를 통해 서비스, 즉 데이터를 제공</strong>
서버는 네트워크에 연결되지 않으면 데이터를 제공할 수 없고, 클라이언트 역시 네트워크에 연결되지 않으면 데이터를 받을 수 없다</p>
<p><strong>네트워크라는 용어는 원래 &#39;무언가와 무언가를 연결&#39;</strong> 을 뜻하는데
예를 들어, 역과 역을 연결하는 철도 노선, 회사나 조직 등에서 사람과 사람을 연결하는 것도 네트워크이다
이 책에서 다루는 네트워크는 <strong>컴퓨터와 컴퓨터를 연결하는 컴퓨터 네트워크</strong></p>
<p><strong>철도 노선</strong>은 <strong>승객</strong>을 <strong>기차</strong>에 태워 <strong>옮김</strong>
<strong>전송망</strong>는 <strong>정보</strong>를 <strong>전파</strong>에 실어 <strong>전달</strong>
<strong>컴퓨터 네트워크</strong>는 <strong>데이터</strong>를 <strong>케이블</strong>에 실어 <strong>전달</strong>함(케이블은 무선LAN에서는 전파)</p>
<p>구체적으로, 컴퓨터 네트워크에는 &#39;인터넷&#39;이라는 것이 있다
인터넷은  inter-<strong>network</strong>라는 용어에서 시작했고, 전 세계에 산재한 네트워크를 연결한 거대한 컴퓨터 네트워크를 의미한다</p>
<blockquote>
<p><strong>internet 더 알아보기</strong></p>
<p>수많은 클라이언트 컴퓨터와 서버 컴퓨터, 그리고 이들로 구성된 네트워크들의 집합체</p>
<p><a href="https://tcpschool.com/webbasic/intro">참고자료 - TCP SCHOOL</a></p>
</blockquote>
<p>덧붙여 </p>
<p>클라이언트와 서버 사이에는 네트워크가 있고, 네트워크를 통해 데이터를 전달하는데
클라이언트와 서버는 물리적인 거리가 가까울 수도 있고, 멀 수도 있다
즉, <strong>물리적 거리와는 관계가 없다</strong>
하지만 반드시 <strong>네트워크로 연결 되어 있음</strong></p>
<hr>
<h1 id="2장---네트워크-기초-지식">2장 - 네트워크 기초 지식</h1>
<h2 id="01-네트워크-기술을-이해하자">01 네트워크 기술을 이해하자</h2>
<p>모든 서버는 네트워크를 사용해서 데이터를 제공한다</p>
<p>일반적으로 말하는 LAN은 </p>
<ul>
<li>케이블을 사용해 데이터를 전송하는 유선 LAN </li>
<li>전파를 사용해서 데이터를 전송하는 무선LAN
으로 나뉘는데, 이 중 <strong>서버를 연결할 때는</strong> <strong>유선 LAN이 기본</strong></li>
</ul>
<p>속도와 품질 측면에서 유선 LAN이 월등하기 때문에 무선 LAN은 클라이언트 측에서만 사용
이 장에서 다룰 것은 서버에서 사용하는 유선 LAN</p>
<p>컴퓨터가 네트워크에 연결할 때는 통신 기능이 필요함
이 장에서는 이것을 계층적으로 분류한 OSI 참조 모델을 기반으로 설명할 것</p>
<h2 id="02-프로토콜이란">02 프로토콜이란</h2>
<p>프로토콜 = 통신할 때의 약속</p>
<p>네트워크 세계에서는 통신을 할 때 데이터가 이해할 수 있도록 잘 갔는지, 잘 도달했는지 등등을 위해 &#39;약속&#39;이 있는데, 그것이 바로 프로토콜</p>
<p>가장 가까이 있는 예시로는 https가 있다
HTTPS는 &#39;HyperText Transfer Protocol Secure&#39;의 약어로 웹서버와 웹브라우저 사이에서 안전하게 데이터를 전달할 때 사용하는 프로토콜(통신 약속)</p>
<p>웹브라우저는 URL 맨 앞에 &#39;https&#39;라는 문자열을 붙임으로써 &#39;HTTPS로 결정된 약속에 따라 데이터를 전송할게요&#39;라고 말하는 것!</p>
<p>네트워크에 연결된 컴퓨터는 보낼 데이터를 &#39;패킷&#39;이라는 작은 단위로 나누어서 보냄
프로토콜에서는 이 패킷을 확실하게 보내기 위해 필요한 다양한 기능들을 정의한다</p>
<p>예를들어 누군가에게 택배를 보낼 때는 화물표가 필요하고,
마찬가지로 패킷에는 &#39;HEADER&#39;이라는 이름의 화물표를 붙이다
헤더에는 통신 상대가 되는 컴퓨터의 정보, 데이터 전체 중 패킷의 순서 등 다양한 정보가 포함되는데 이것은 프로토콜에서는 어떻게 통신 상대나 패킷의 순서를 표시할지 미리 서로 <strong>약속</strong>하는 것</p>
<h2 id="03-osi-참조-모델---컴퓨터의-통신-기능을-7개의-층으로-나눈-것">03 OSI 참조 모델 - 컴퓨터의 통신 기능을 7개의 층으로 나눈 것</h2>
<p>네트워크에 존재하는 수많은 프로토콜 중, 사용자가 인터넷을 할 때 컴퓨터가 사용하는 프로토콜은 와이파이, IP, TCP, UDP 등의 여섯가지 정도</p>
<p>이들을 OSI 참조 모델이라 불리는 개념에 대입해보면 네트워크에 대한 이해도를 높일 수 있다</p>
<h4 id="osi-참조-모델osi-7계층">OSI 참조 모델(OSI 7계층)</h4>
<ul>
<li>통신 기능의 역할을 계층적으로 분류한 개념</li>
<li>각 층의 역할은 서로 다르며 별도로 작동한다</li>
<li>이렇게 분류해서 인접한 층의 작동이 서로 영향을 주지 않게 함으로써,</li>
<li>결과적으로 층별로 문제를 해결할 수 있게 됨</li>
</ul>
<blockquote>
<p><strong>OSI 7계층 보충 설명</strong></p>
<p>네트워크에서 통신이 일어나는 일련의 과정들을 7단계로 나눈 것</p>
<p>Open Systems Interconnection의 약자로, ISO(국제표준화기구)에서 컴퓨터 네트워크 프로토콜 디자인과 통신을 계층으로 나누어 설명한 모델</p>
<p>이렇게 나눈 이유는 <strong>흐름을 직관적으로 볼 수 있고, 이상이 생겼을 때 그 단계만 고칠 수 있기 때문</strong></p>
</blockquote>
<p><a href="https://velog.velcdn.com/images/sing_/post/7b0d2db0-3f29-4c96-accc-612b681e815a/image.png"></a></p>
<ul>
<li><p>송신
  데이터를 송신하는 컴퓨터는 <strong>위쪽 층부터 아래쪽 층으로 각 프로토콜들에 기반에 데이터를 처리하며 네트워크로 흘려보낸다</strong>!</p>
</li>
<li><p>수신
  데이터를 받은 컴퓨터는 송신과 반대로 <strong>아래쪽 층부터 위쪽 층으로 송신 소스의 컴퓨터와 같은 층의 프로토콜에 기반해 데이터를 처리하고 원래 데이터로 되돌린다</strong></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[zsh: command not found: $]]></title>
            <link>https://velog.io/@sing_/zsh-command-not-found</link>
            <guid>https://velog.io/@sing_/zsh-command-not-found</guid>
            <pubDate>Thu, 01 Feb 2024 22:48:55 GMT</pubDate>
            <description><![CDATA[<h2 id="😱-문제-상황">😱 문제 상황</h2>
<p>vscode로 실습 중에 발생한 오류</p>
<p>환경변수를 수정하면 발생하는 문제라고 하는데, 나는 환경변수를 만졌던 건 아니어서 경로에 code 파일 다시 저장해보고 다양한 방법 시도해봐도 해결이 안됨</p>
<h2 id="🫶-해결">🫶 해결</h2>
<p>해결은... 간단했다!</p>
<p><strong>$ 기호는 명령어가 아니라 뒤에 오는 텍스트가 명령임을 나타내는 단순한 기호</strong>라고 한다..!
$를 빼고 명령어만 입력하면 되는 것</p>
<p>정확히는, 일반적으로 $ 기호는 명령어를 입력할 준비가 되었다는 프롬프트를 표시하는데 사용이 됨</p>
<hr>
<p><a href="https://sugaris.tistory.com/28#google_vignette">참고 링크  - 티스토리 슈가는 설탕</a></p>
<p>즉 $는 명령어에 포함된 것이 아니라 책에서 이 줄이 명령어임을 알려준 것
근데 난 자꾸만 $를 치고 있던 것이다
요즘은 이런 어이없는 종류의 시행착오를 가끔 겪는데, 겪을 때마다 해결하고 나면 헛웃음이 난다ㅋㅋㅋ
하지만 아예 모르는 상태에서의 삽질은 초보의 특권이라 생각하며 즐기는 중 후후 ,,,</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[npm] npm error - ENOENT, Missing script: "start", EJSONPARSE]]></title>
            <link>https://velog.io/@sing_/npm-npm-error-ENOENT-Missing-script-start-EJSONPARSE</link>
            <guid>https://velog.io/@sing_/npm-npm-error-ENOENT-Missing-script-start-EJSONPARSE</guid>
            <pubDate>Wed, 31 Jan 2024 13:26:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sing_/post/71c61412-a3da-45fc-9bcd-6b751a5a9f15/image.png" alt="">
<del>근데 터미널 진짜 언제 봐도 이쁜 것 같다</del></p>
<h2 id="😱-문제-상황">😱 문제 상황</h2>
<p>npm install 하고 에러발생과 해결 발생과 해결을 반복
특히 ENOENT는 여러 번 본 에러 같아서 기록해두면 좋을 것 같아서 남기기로 했다</p>
<h2 id="🫶-해결">🫶 해결</h2>
<h3 id="code-enoent">code ENOENT</h3>
<p>내가 <strong>현재 위치한 디렉토리에 package.json 파일 없어서 발생하는 문제</strong>
즉, npm i로 깔아달라고 말했는데 &quot;뭘깔까???&quot;가 없는 상태
이건 위치를 이동하거나 npm init으로 json파일 만들어주면 해결됨</p>
<h3 id="missing-script-start">Missing script: &quot;start&quot;</h3>
<p>npm start를 입력했는데 <strong>package.json에 start 스크립트 명령어가 없어서 발생한 문제</strong></p>
<h3 id="code-ejsonparse">code EJSONPARSE</h3>
<p><strong>package.json 파일에 불필요한 주석이나 콤마가 들어가면 발생하는 오류</strong>
따라 주석처리, 쉼표, 괄호 등등 간단하게 확인하면 됨
참고로 나는 &quot;start&quot;: &quot;&quot; 추가하고 전 줄에 쉼표 찍는 것을 깜빡해서 발생한 오류였다!</p>
<hr>
<p>빨리 실습 하고 싶은데 자꾸 에러가 나서 조급했는데 금방 해결되는 것이어서 다행이다
구글 감사합니다 
에러 대처법을 써주시는 모든 분들께도 언제나
언제나 언제나 감사합니다
TT</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 34장 이터러블]]></title>
            <link>https://velog.io/@sing_/%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-34%EC%9E%A5-%EC%9D%B4%ED%84%B0%EB%9F%AC%EB%B8%94</link>
            <guid>https://velog.io/@sing_/%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-34%EC%9E%A5-%EC%9D%B4%ED%84%B0%EB%9F%AC%EB%B8%94</guid>
            <pubDate>Mon, 29 Jan 2024 07:59:36 GMT</pubDate>
            <description><![CDATA[<h2 id="용어-정리">용어 정리</h2>
<p>이터러블은 처음 들어보는데다 헷갈리는 용어 꽤 많이 나와서 한 번 정리하고 시작!</p>
<ul>
<li><strong>이터레이션 iteration</strong>
  단어의 뜻 그 자체로는 &#39;반복&#39;
  개발 용어로는    어떠한 데이터 컬렉션을 순회하거나 반복하는 것</li>
<li><strong>이터러블 iterable</strong>
  직역하면 반복 가능한, 순회할 수 있는
  이터레이터를 반환하는 <code>[Symbol.iterator]()</code>를 가진 값</li>
<li><strong>이터레이터</strong>
  <code>{value, done}</code> 객체를 리턴하는 <code>next()</code>를 가진 값</li>
<li><strong>이터러블 프로토콜</strong>&amp;<strong>이터레이터 프로토콜</strong>
  이터러블을 for of, 전개 연산자 등과 함께 동작하도록 한 규약<h1 id="이터러블">이터러블</h1>
이터러블은</li>
<li><strong>이터러블 프로토콜을 준수한 객체</strong></li>
<li><strong>Symbol.iterator을 프로퍼티 키로 사용한 메서드를 직접 구현하거나, 프로토타입 체인을 통해 상속받은 객체</strong></li>
<li>for ... of 문으로 순회할 수 있으며 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용이 가능함</li>
</ul>
<p>ES6 이전에는 데이터 컬렉션(배열, 문자열, 유사배열객체, DOM 컬렉션 등)은 통일된 규약 없이 나름의 구조를 가지고 다양한 방법으로 순회
-&gt; ES6에서 <strong>순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 for ... of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상</strong>으로 사용할 수 있도록 일원화</p>
<h3 id="이터레이션-프로토콜">이터레이션 프로토콜</h3>
<p>이터레이션 프로토콜에는 두 가지가 있음</p>
<ol>
<li><strong>이터러블 프로토콜</strong>
 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속 받은 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환. 이러한 규약이 이터러블 프로토콜</li>
<li><strong>이터레이터 프로토콜</strong>
 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환. 이터레이터는 next 메서드를 소유하며, next 메서드를 호출하면 이터러블을 순회하며 value와 done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환
 이러한 규약이 이터레이터 프로토콜</li>
</ol>
<p>각각의 프로토콜을 만족하는 객체를 이터러블, 이터레이터라고 함</p>
<h3 id="이터러블의-정의와-설명">이터러블의 정의와 설명</h3>
<p>어떤 객체가 Symbol.iterator을 프로퍼티 키로 사용한 메서드를 직접 구현하거나, 프로토타입 체인을 통해 상속 받은 Symbol.iterator 메서드를 호출했을 때, 이터레이터 인스턴스가 반환됨. 그 해당 객체가 이터러블
즉, <strong>이터러블 프로토콜</strong>을 준수하면 <strong>이터러블</strong>이 반환됨. </p>
<h3 id="이터레이터의-정의와-설명">이터레이터의 정의와 설명</h3>
<p>이터러블이 Symbol.iterator 메서드를 호출해 반환된 <strong>이터레이터가 next 메서드를 소유</strong>하고, <strong>next 메서드를 호출하면 이터러블을 순회하며 value와 done 프로퍼티를 갖는 이터레이터 리절트 객체가 반환</strong>될 때 이것이 이터레이터
<strong>이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할</strong>
![[Screen Shot 2024-01-29 at 15.18.44.png]]</p>
<h3 id="빌트인-이터러블">빌트인 이터러블</h3>
<p>자바스크립트는 Array와 같이 이터레이션 프로토콜을 준수한 객체인 빌트인 이터러블을 제공함</p>
<table>
<thead>
<tr>
<th align="center"><strong>빌트인 이터러블</strong></th>
<th align="center"><strong>Symbol.iterator 메서드</strong></th>
</tr>
</thead>
<tbody><tr>
<td align="center">Array</td>
<td align="center">Array.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">String</td>
<td align="center">String.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">Map</td>
<td align="center">Map.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">Set</td>
<td align="center">Set.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">TypedArray</td>
<td align="center">TypedArray.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">arguments</td>
<td align="center">argument[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">Dom 컬렉션</td>
<td align="center">NodeList.prototype[Symbol.iterator]  <br>HTMLCollection.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td align="center">빌트인 이터러블을 제외하고도 직접 일반 객체를 이터러블 프로토콜을 준수하도록 구현하여 이터러블로 만들 수 있음</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">### 이터레이터</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```js</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">// 배열은 이터러블 프로토콜을 준수한 이터러블이다.</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">const array = [1, 2, 3];</td>
<td align="center"></td>
</tr>
</tbody></table>
<p>// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array<a href="">Symbol.iterator</a>;</p>
<p>// Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖는다.
console.log(&#39;next&#39; in iterator); // true</p>
<pre><code>이터레이터의 next 메서드는 이터러블의 각 요소를 순회하기 위한 포인터의 역할을 함
즉, 즉, next 메서드를 호출하면 이터러블을 순차적으로 한 단곘기 순회하며 순회 결과를 나타내는 이터레이터 리절트 객체를 반환

```js
// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다. 이터레이터는 next 메서드를 갖는다.
const iterator = array[Symbol.iterator]();

// next 메서드를 호출하면 이터러블을 순회하며 순회 결과를 나타내는 이터레이터 리절트 객체를
// 반환한다. 이터레이터 리절트 객체는 value와 done 프로퍼티를 갖는 객체다.
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }</code></pre><p>이터레이터 리절트 객체의 value 프로퍼티는 현재 순회중인 이터러블의 값을 나타내며 done 프로퍼티는 이터러블의 순회 완료 여부를 나타냄</p>
<h2 id="for--of-문">for ... of 문</h2>
<p>for ... of문은 이터러블을 순회하면서 이터러블의 요소를 변수에 할당함</p>
<pre><code class="language-js">//syntax
for (변수선언문 of 이터러블) { ... }

// for in 문의 형식과 매우 유사
// for (변수선언문 in 객체) { ... }</code></pre>
<p>for ... of 문은 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 <strong>next 메서드가 반환한 이터레이터 리절트 객체의 value 프로퍼티 값을 for ... of 문의 변수에 할당</strong>
그리고 <strong>이터레이터 리절트 객체의 done 프로퍼티 값이 false이면 이터러블의 순회를 계속하고 true이면 순회를 중단</strong></p>
<pre><code class="language-js">//for ... of문의 예시
for (const item of [1, 2, 3]) {
  // item 변수에 순차적으로 1, 2, 3이 할당된다.
  console.log(item); // 1 2 3
}</code></pre>
<p>예시 for ... of문의 내부 동작을 for 문으로 표현하면 다음과 같음</p>
<pre><code class="language-js">// 이터러블
const iterable = [1, 2, 3];

// 이터러블의 Symbol.iterator 메서드를 호출하여 이터레이터를 생성한다.
const iterator = iterable[Symbol.iterator]();

for (;;) {
  // 이터레이터의 next 메서드를 호출하여 이터러블을 순회한다. 이때 next 메서드는 이터레이터 리절트 객체를 반환한다.
  const res = iterator.next();

  // next 메서드가 반환한 이터레이터 리절트 객체의 done 프로퍼티 값이 true이면 이터러블의 순회를 중단한다.
  if (res.done) break;

  // 이터레이터 리절트 객체의 value 프로퍼티 값을 item 변수에 할당한다.
  const item = res.value;
  console.log(item); // 1 2 3
}</code></pre>
<h2 id="이터러블과-유사-배열-객체">이터러블과 유사 배열 객체</h2>
<p><strong>유사 배열 객체</strong>
(마치 배열 처럼) <strong>인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체</strong></p>
<ul>
<li>length 프로퍼치를 갖기 때문에 for 문으로 순회할 수 있고</li>
<li>인덱스를 나타내는 숫자 형식의 문자열을 프로퍼티 키로 가지므로 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있음</li>
</ul>
<pre><code class="language-js">// 유사 배열 객체
const arrayLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3
};

// 유사 배열 객체는 length 프로퍼티를 갖기 때문에 for 문으로 순회할 수 있다.
for (let i = 0; i &lt; arrayLike.length; i++) {
  // 유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있다.
  console.log(arrayLike[i]); // 1 2 3
}</code></pre>
<p>유사 배열 객체는 일반 객체. 즉, Symbol.iterator 메서드가 없음
따라서  for ... of문으로 순회할 수 없음</p>
<p>유사 배열 객체 중 유사 배열 객체이면서 이터러블인 것도 있음</p>
<ul>
<li>arguments, NodeList, HTMLCollection
  (ES6 이후 Symbol.iterator 메서드를 구현하여 이터러블이 되었고 여전히 length 프로퍼티를 가지며 인덱스로 접근 가능)</li>
</ul>
<p>모든 유사 배열 객체가 이터러블은 아님. 그러나 <strong>ES6에서 도입된 Array.from 메서드를 사용하여 배열로 간단히 변환 가능함</strong>
Array.from 메서드는 유사 배열 객체 또는 이터러블을 인수로 전달 받아 배열로 변환하여 반환</p>
<h2 id="이터레이션-프로토콜의-필요성">이터레이션 프로토콜의 필요성</h2>
<p>한마디로, **데이터 소비자가 데이터 공급자를 효율적으로 사용하기 위한 인터페이스로서의 역할</p>
<p><strong>이터러블</strong>은 for ... of문, 스프레드 문법, 배열 디스트럭처링 할당과 같은 데이터 소비자에 의해 사용되므로 <strong>데이터 공급자의 역할을 한다</strong>고 할 수 있음</p>
<p>다양한 데이터 공급자가 각자의 순회 방식을 가진다면 데이터 소비자는 여러 순회 방식을 모두 지원해야하므로 비효율적이지만, 이터레이션 프로토콜을 준수하도록 규정하면 그 한 가지만 지원하면됨. </p>
<p>![[Screen Shot 2024-01-29 at 15.18.31.png]]</p>
<h2 id="사용자-정의-이터러블">사용자 정의 이터러블</h2>
<h3 id="사용자-정의-이터러블-구현">사용자 정의 이터러블 구현</h3>
<p>이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면 사용자 정의 이터러블이 됨</p>
<pre><code class="language-js">// 피보나치 수열을 구현한 사용자 정의 이터러블
const fibonacci = {
  // Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수한다.
  [Symbol.iterator]() {
    let [pre, cur] = [0, 1];
    const max = 10; // 수열의 최대값

    // next 메서드는 이터레이터 리절트 객체를 반환한다.
    return {
      next() {
        [pre, cur] = [cur, pre + cur];
        // 이터레이터 리절트 객체를 반환한다.
        return { value: cur, done: cur &gt;= max };
      },
    }
  },
};

// 이터러블인 fibonacci 객체를 순회할 때마다 next 메서드가 호출한다.
for (const num of fibonacci) {
  console.log(num); // 1 2 3 5 8
}</code></pre>
<p>Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수하게 했고, Symbol.iterator 메서드가 next 메서드를 갖는 이터레이터를 반환하도록 했고, next 메서드가 이터레이터 리절트 객체를 반환하도록 했음 -&gt; 이터러블의 조건 만족</p>
<h3 id="이터러블을-생성하는-함수">이터러블을 생성하는 함수</h3>
<p>이터러블을 생성하는 함수를 구현하면 훨씬 자유롭게 활용이 가능함
앞의 예시에서 수열의 최대값을 외부에서 전달할 수 있도록 이터러블 생성 함수를 만들어볼 수 있음.</p>
<pre><code class="language-javascript">// 피보나치 수열을 구현한 사용자 정의 이터러블을 반환하는 함수.
// 수열의 최대값을 인수로 전달받는다.
const fibonacciFunc = function(max) {
  let [pre, cur] = [0, 1];

  // Symbol.iterator 메서드를 구현한 이터러블을 반환한다.
  return {
    [Symbol.iterator]() {
      return {
        next() {
          [pre, cur] = [cur, pre + cur];
          return { value: cur, done: cur &gt;= max };
        },
      }
    },
  }
};

// 이터러블을 반환하는 함수에 수열의 최대값을 인수로 전달하면서 호출한다.
// fibonacciFunc(10)은 이터러블을 반환한다.
for (const num of fibonacciFunc(10)) {
  console.log(num); // 1 2 3 5 8
}</code></pre>
<h3 id="이터러블이면서-이터레이터인-객체를-생성하는-함수">이터러블이면서 이터레이터인 객체를 생성하는 함수</h3>
<p>이터러블 = 이터레이터를 반환하는 <code>[Symbol.iterator]()</code>를 가진 값
이터레이터 =  <code>{value, done}</code> 객체를 리턴하는 <code>next()</code>를 가진 값</p>
<p>앞의 예제를 보면 &#39;이터러블&#39;을 반환함. 이 상태에서 이터레이터를 반환하려면</p>
<pre><code class="language-js">const iterable = fibonacciFunc(5);
const iterator = iterable[Symbol.iterator]();</code></pre>
<p>이터러블의 Symbol.iterator 메서드를 호출해야함</p>
<p>그러나 이터러블이면서 이터레이터인 객체를 생성하면 Symbol.iterator 메서드를 호출하지 않아도 됨. 다음 객체는 Symbol.iterator 메서드와 next 메서드를 소유한 이터러블이면서 동시에 이터레이터임</p>
<pre><code class="language-js">//간단한 예시
const a = 

// 이터러블이면서 이터레이터인 객체. 이터레이터를 반환하는 Symbol.iterator 메서드와
// 이터레이션 리절트 객체를 반환하는 next 메서드를 소유한다.
{
  [Symbol.iterator]() { return this; },
  next() {
    return { value: any, done: boolean };
  }
}</code></pre>
<pre><code class="language-js">//앞의 피보나치 예시에 적용해보기 

// 이터러블이면서 이터레이터인 객체를 반환하는 함수
const fibonacciFunc = function (max) {
  let [pre, cur] = [0, 1];

  // Symbol.iterator 메서드와 next 메서드를 소유한 이터러블이면서 이터레이터인 객체를 반환
  return {
    [Symbol.iterator]() { return this; },
    // next 메서드는 이터레이터 리절트 객체를 반환
    next() {
      [pre, cur] = [cur, pre + cur];
      return { value: cur, done: cur &gt;= max };
    }
  };
};

// iter는 이터러블이면서 이터레이터다.
let iter = fibonacciFunc(10);

// iter는 이터러블이므로 for...of 문으로 순회할 수 있다.
for (const num of iter) {
  console.log(num); // 1 2 3 5 8
}

// iter는 이터러블이면서 이터레이터다
iter = fibonacciFunc(10);

// iter는 이터레이터이므로 이터레이션 리절트 객체를 반환하는 next 메서드를 소유한다.
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: 5, done: false }
console.log(iter.next()); // { value: 8, done: false }
console.log(iter.next()); // { value: 13, done: true }</code></pre>
<h3 id="무한-이터러블과-지연-평가">무한 이터러블과 지연 평가</h3>
<p>무한 이터러블을 생성하는 함수를 정의 -&gt; 이를 통해 무한 수열을 간단하게 구현 가능함</p>
<pre><code class="language-js">// 무한 이터러블을 생성하는 함수
const fibonacciFunc = function () {
  let [pre, cur] = [0, 1];

  return {
    [Symbol.iterator]() { return this; },
    next() {
      [pre, cur] = [cur, pre + cur];
      // 무한을 구현해야 하므로 done 프로퍼티를 생략한다.
      return { value: cur };
    }
  };
};

// fibonacciFunc 함수는 무한 이터러블을 생성한다.
for (const num of fibonacciFunc()) {
  if (num &gt; 10000) break;
  console.log(num); // 1 2 3 5 8...4181 6765
}

// 배열 디스트럭처링 할당을 통해 무한 이터러블에서 3개의 요소만 취득한다.
const [f1, f2, f3] = fibonacciFunc();
console.log(f1, f2, f3); // 1 2 3</code></pre>
<p>무한을 구현하기 위해 done 프로퍼티는 생략되었음</p>
<p>이 예제에서는 지연 평가를 통해 데이터를 생성하는데 
<strong>지연 평가</strong>란 <strong>데이터가 필요한 시점 이전까지는 데이터를 생성하지 않고 있다가 데이터가 필요한 시점이 되면 그때야 비로소 데이터를 생성하는 기법</strong>
즉, <strong>평가가 필요할 때까지 평가를 늦추는 기법</strong>
지연 평가를 사용하면 따라서 빠른 실행 속도를 기대할 수 있고, 불필요한 메모리를 생성하지 않으며, 무한도 표현할 수 있음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 41장 타이머]]></title>
            <link>https://velog.io/@sing_/olx6y5pg</link>
            <guid>https://velog.io/@sing_/olx6y5pg</guid>
            <pubDate>Mon, 29 Jan 2024 03:39:39 GMT</pubDate>
            <description><![CDATA[<h2 id="호출-스케줄링">호출 스케줄링</h2>
<p><strong>호출 스케줄링</strong>
일정 시간이 경과된 이후에 함수 호출을 예약하기 위해 타이머 함수를 사용하는 것</p>
<h3 id="자바스크립트-타이머-함수의-종류">자바스크립트 타이머 함수의 종류</h3>
<p>타이머 생성용  <code>setTimeout</code>, <code>setInterval</code>
제거용 <code>clearTimeout</code>,  <code>clearInterval</code></p>
<h2 id="타이머-함수">타이머 함수</h2>
<h3 id="settimeout--cleartimeout">setTimeout / clearTimeout</h3>
<p><code>setTimeout</code></p>
<pre><code class="language-js">setTimeout(functionRef, delay, param1, param2)</code></pre>
<p>각 매개변수는</p>
<ul>
<li><p><code>func</code> 
  타이머가 만료된 뒤 호출될 콜백 함수</p>
</li>
<li><p><code>delay</code> 몇 초 뒤에 실행될지 / 단위는 ms임
  설정한 시간이 끝나도 콜백 함수가 즉시 호출되는 것이 보장되지는 않음
  <strong><code>delay</code> 시간은 태스크 큐에 콜백 함수를 등록하는 시간을 지연할 뿐임!</strong>
  또한, delay가 4ms 이하인 경우 <strong>최소 지연시간 4ms</strong>가 지정됨</p>
</li>
<li><p><code>param1</code>, <code>param2</code>, ...
  호출 스케줄링된 콜백 함수에 전달해야할 인수가 존재하는 경우 세 번째 이후의 인수로 전달 가능함</p>
</li>
</ul>
<p><code>setTimeout</code>함수는 생성된 타이머를 식별할 수 있는 고유한 타이머 id를 반환하는데,
이것은 브라우저 환경인 경우 숫자 / Node.js 환경인 경우 객체
-&gt; 이렇게 반환한 타이머 id를 <code>clearTimeout</code> 함수의 인수로 전달하여 타이머를 취소할 수 있음
즉, <strong><code>clearTimeout</code> 함수는 호출 스케줄링을 취소</strong></p>
<h3 id="setinterval--clearinterval">setInterval / clearInterval</h3>
<pre><code class="language-js">setInterval(functionRef, delay, param1, param2)</code></pre>
<p><code>setInterval</code> 함수의 콜백 함순느 두 번째 인수로 전달받은 시간이 경과할 때마다 반복 실행되도록 호출 스케줄링됨
매개변수는 setTimeout 함수와 동일함</p>
<p><code>setTimeout</code>과 마찬가지로 <code>setInterval</code> 함수는 생성된 타이머를 식별할 수 있는 고유한 id를 반환하며 이는 브라우저 환경에서는 숫자, Node.js 환경에서는 객체</p>
<p><code>setInterval</code> 함수가 반환한 타이머 id를 <code>clearInterval</code> 함수의 인수로 전달하여 타이머를 취소할 수 있음 
즉, <strong><code>clearInterval</code> 함수는 호출 스케줄링을 취소</strong></p>
<h2 id="디바운스와-스로틀">디바운스와 스로틀</h2>
<p>짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법
ex) <code>scroll</code>, <code>mousemove</code> 등의 이벤트에 바인딩한 이벤트 핸들러 같은 경우</p>
<p>디바운스와 스로틀을 사용하면 <strong>이벤트 핸들러의 호출 빈도가 확연하게 줄어들기에 이벤트를 처리할 때 유용</strong>함</p>
<p>이러한 디바운스와 스로틀을 구현에 타이머 함수가 사용됨</p>
<h3 id="디바운스">디바운스</h3>
<p>짧은 시간 간격으로 발생하는 이벤트를 그룹화해서 마지막에 한 번만 이벤트 핸들러가 호출되도록 함
ex) 텍스트 입력 필드에서 input 이벤트가 짧은 시간 간격으로 연속해서 발생하는 경우</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;input type=&quot;text&quot;&gt;
  &lt;div class=&quot;msg&quot;&gt;&lt;/div&gt;
  &lt;script&gt;
    const $input = document.querySelector(&#39;input&#39;);
    const $msg = document.querySelector(&#39;.msg&#39;);

    const debounce = (callback, delay) =&gt; {
      let timerId;
      // debounce 함수는 timerId를 기억하는 클로저를 반환한다.
      return (...args) =&gt; {
        // delay가 경과하기 이전에 이벤트가 발생하면 이전 타이머를 취소하고
        // 새로운 타이머를 재설정한다.
        // 따라서 delay보다 짧은 간격으로 이벤트가 발생하면 callback은 호출되지 않는다.
        if (timerId) clearTimeout(timerId);
        timerId = setTimeout(callback, delay, ...args);
      };
    };

    // debounce 함수가 반환하는 클로저가 이벤트 핸들러로 등록된다.
    // 300ms보다 짧은 간격으로 input 이벤트가 발생하면 debounce 함수의 콜백 함수는
    // 호출되지 않다가 300ms 동안 input 이벤트가 더 이상 발생하면 한 번만 호출된다.
    $input.oninput = debounce(e =&gt; {
      $msg.textContent = e.target.value;
    }, 300);
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>input 이벤트는 사용자가 텍스트 입력 필드에 값을 입력할 때마다 연속해서 발생
만약 이벤트 핸들러에서 그 입력된 값으로 무거운 처리를 한다했을 때, 입력 중에 매번 그 처리를 하는 것은 비효율점
따라서 <strong>입력 마무리 시 한 번만 처리를 하거나 요청을 전송하는 것이 필요</strong>한데, 그것을 알 수는 없음
그래서 일정 시간 동안 텍스트 입력 필드에 값을 입력하지 않으면 입력 완료로 간주
-&gt; debounce 함수가 반환한 함수는 debounce 함수에 두번째 인수로 전달한 시간보다 짧은 간격으로 이벤트가 발생하면 이전 이벤트를 취소하고 새로운 타이머를 재설정
따라서 delay보다 짧은 간격으로 이벤트가 연속해서 발생하면 debounce 함수의 첫 번째 인수로 전달한 콜백함수는 호출되지 않다가 delay 동안 input 이벤트가 더 이상 발생하지 않으면 한 번만 호출됨</p>
<p>=&gt; 짧은 시간 간격으로 이벤트가 연속해서 발생하면 이벤트 핸들러를 호출하지 않다가 일정 시간 동안 이벤트가 더 이상 발생하지 않으면 이벤트 핸들러가 한 번만 호출되도록 하는 디바운스는 resize 이벤트 처리나 input 요소에 입력된 값으로 ajax 요청하는 입력 필드 자동완성 UI 구현, 버튼 중복 클릭 방지 처리 등에 유용하게 사용</p>
<h3 id="스로틀">스로틀</h3>
<p>짧은 시간 간격으로 연속해서 발생하는 이벤트를 그룹화하여 일정 시간 단위로 이벤트 핸들러가 호출되도록 호출 주기를 만듦</p>
<p>예) scroll 이벤트가 짧은 시간 간격으로 연속해서 발생하는 경우</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;style&gt;
    .container {
      width: 300px;
      height: 300px;
      background-color: rebeccapurple;
      overflow: scroll;
    }

    .content {
      width: 300px;
      height: 1000vh;
    }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class=&quot;container&quot;&gt;
    &lt;div class=&quot;content&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div&gt;
    일반 이벤트 핸들러가 scroll 이벤트를 처리한 횟수:
    &lt;span class=&quot;normal-count&quot;&gt;0&lt;/span&gt;
  &lt;/div&gt;
  &lt;div&gt;
    스로틀 이벤트 핸들러가 scroll 이벤트를 처리한 횟수:
    &lt;span class=&quot;throttle-count&quot;&gt;0&lt;/span&gt;
  &lt;/div&gt;

  &lt;script&gt;
    const $container = document.querySelector(&#39;.container&#39;);
    const $normalCount = document.querySelector(&#39;.normal-count&#39;);
    const $throttleCount = document.querySelector(&#39;.throttle-count&#39;);

    const throttle = (callback, delay) =&gt; {
      let timerId;
      // throttle 함수는 timerId를 기억하는 클로저를 반환한다.
      return (...args) =&gt; {
        // delay가 경과하기 이전에 이벤트가 발생하면 아무것도 하지 않다가
        // delay가 경과했을 때 이벤트가 발생하면 새로운 타이머를 재설정한다.
        // 따라서 delay 간격으로 callback이 호출된다.
        if (timerId) return;
        timerId = setTimeout(() =&gt; {
          callback(...args);
          timerId = null;
        }, delay);
      };
    };

    let normalCount = 0;
    $container.addEventListener(&#39;scroll&#39;, () =&gt; {
      $normalCount.textContent = ++normalCount;
    });

    let throttleCount = 0;
    // throttle 함수가 반환하는 클로저가 이벤트 핸들러로 등록된다.
    $container.addEventListener(&#39;scroll&#39;, throttle(() =&gt; {
      $throttleCount.textContent = ++throttleCount;
    }, 100));
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>throttle 함수가 반환한 함수는 throttle 함수에 두 번째 인수로 전달한 시간이 경과하기 이전에 이벤트가 발생하면 아무것도 하지 않다가 delay 시간이 경과했을 때 이벤트가 발생하면 콜백 함수를 호출하고 새로운 타이머를 재설정
따라 delay 시간 간격으로 함수가 호출됨</p>
<p>스로틀은 scroll 이벤트나 무한 스크롤 UI 구현 등에 유용하게 사용됨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 48장 모듈]]></title>
            <link>https://velog.io/@sing_/%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-48%EC%9E%A5-%EB%AA%A8%EB%93%88</link>
            <guid>https://velog.io/@sing_/%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-48%EC%9E%A5-%EB%AA%A8%EB%93%88</guid>
            <pubDate>Mon, 29 Jan 2024 03:34:57 GMT</pubDate>
            <description><![CDATA[<h2 id="모듈">모듈</h2>
<p>애플리케이션을 구성하는 개별적 요소 
일반적으로 모듈은 <strong>기능</strong>을 기준으로 <strong>파일 단위</strong>로 분리함
이때 모듈이 성립하려면 모듈은 자신만의 <strong>파일 스코프</strong>를 가질 수 있어야함</p>
<p>모듈은 애플리케이션과 분리되는 개별적 존재인데, 모듈은 재사용되어야 의미가 있음. 그때 필요한 것이 import와 export</p>
<p><strong>export</strong> 
공개가 필요한 자산에 한정하여 선택적으로 공개하는 것</p>
<p><strong>import</strong>
모듈 사용자가 모듈이 공개한 자산 중 일부 또는 전체를 선택하여 자신의 스코프 내로 불러들여 재사용하는 것</p>
<h2 id="자바스크립트와-모듈">자바스크립트와 모듈</h2>
<p>자바스크립트는 웹페이지의 단순 보조 기능을 처리하기 위한 제한적 용도를 위해 탄생함
따라서 <strong>다른 언어와 다르게 모듈의 성립을 위한 파일 스코프, import, export를 지원하지 않음</strong></p>
<p>자바스크립트는 파일마다 독립적인 파일 스코프를 갖지 않으므로, 자체적으로 모듈 시스템을 사용할 수 없었고
그러한 상황에서 제안된 것이 CommonJS와 AMD.
따라서 브라우저 환경에서 모듈을 사용하기 위해서는 CommonJS 또는 AMD를 구현한 모듈 로더 라이브러리를 사용해야하는 상황이 됨 </p>
<p>현재는 <strong>Node.js는 기본적으로 CommonJS 사양을 따르고, 따라서 모듈 시스템을 지원함</strong>
-&gt; <strong>Node.js 환경에서는 파일별로 독립적인 파일 스코프(모듈 스코프)를 가짐</strong></p>
<h2 id="es6-모듈esm">ES6 모듈(ESM)</h2>
<p>ES6에서는 클라이언트 사이드 자바스크립트에서도 동작하는 모듈 기능을 추가</p>
<p><strong>사용법</strong>
script 태그에 type=&quot;module&quot; 어트리뷰트를 추가하면 로드된 자바스크립트 파일이 모듈로서 동작
(ESM 파일의 확장자는 mjs를 사용할 것이 권장되고, ESM에는 기본적으로 strict mode가 적용됨)</p>
<pre><code class="language-js">&lt;script type=&quot;module&quot; src=&quot;app.mjs&quot;&gt;&lt;script&gt;</code></pre>
<h3 id="모듈-스코프">모듈 스코프</h3>
<p><strong>ESM은 독자적인 모듈 스코프를 가짐</strong>
<strong>일반 자바스크립트 파일은 script 태그로 분리해서 로드해도 독자적 모듈 스코프를 가지지 않음</strong></p>
<p>(1) 일반 자바스크립트</p>
<p>script로 foo.js와 bar.js를 로드한 상황에서
foo.js에서 선언된 변수 <code>x = &#39;foo&#39;;</code>를  bar.js에서 <code>x=&#39;bar&#39;;</code>으로 재할당하고 <code>console.log(window.x);</code>한다면 foo가 아닌 bar이 출력됨</p>
<p>즉, <strong>하나의 전역을 공유하고 의도치 않게 x의 값이 덮어써짐</strong></p>
<p>(2) ESM</p>
<p>반면 ESM은 파일 자체의 독자적 모듈 스코프를 제공하기에 모듈 내에 var 키워드로 선언한 변수x는 전역 변수가 아니고 window 객체의 프로퍼티도 아님</p>
<p>모듈 내에서 선언한 식별자는 <strong>모듈 스코프가 다르기에 모듈 외부에서는 참조할 수 없음</strong></p>
<h3 id="export-키워드">export 키워드</h3>
<p>모듈 내부에서 선언한 식별자를 외부에 공개하여 다른 모듈들이 재사용할 수 있게 하려면 export 키워드를 사용함</p>
<p>export키워드는 선언문 앞에 사용하며, 이로써 변수, 함수, 클래스 등 모든 식별자를 export할 수 있음</p>
<pre><code class="language-js">// lib.mjs
// 변수의 공개
export const pi = Math.PI;

// 함수의 공개
export function square(x) {
  return x * x;
}

// 클래스의 공개
export class Person {
  constructor(name) {
    this.name = name;
  }
}</code></pre>
<p>export할 대상을 하나의 객체로 구성하여 한 번에 export할 수도 있음</p>
<pre><code class="language-js">// lib.mjs
const pi = Math.PI;

function square(x) {
  return x * x;
}

class Person {
  constructor(name) {
    this.name = name;
  }
}

// 변수, 함수 클래스를 하나의 객체로 구성하여 공개
export { pi, square, Person };</code></pre>
<h3 id="import-키워드">import 키워드</h3>
<p>다른 모듈에서 공개한 식별자를 자신의 모듈 스코프 내부로 로드하기 위해 사용하는 키보드
다른 모듈이 export한 식별자 이름으로 import해야하며, <strong>ESM이 경우 파일 확장자를 생략할 수 없음</strong></p>
<pre><code class="language-js">// app.mjs
// 같은 폴더 내의 lib.mjs 모듈이 export한 식별자 이름으로 import한다.
// ESM의 경우 파일 확장자를 생략할 수 없다.
import { pi, square, Person } from &#39;./lib.mjs&#39;;

console.log(pi);         // 3.141592653589793
console.log(square(10)); // 100
console.log(new Person(&#39;Lee&#39;)); // Person { name: &#39;Lee&#39; }</code></pre>
<pre><code class="language-js">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;script type=&quot;module&quot; src=&quot;app.mjs&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>이 예제에서 app.mjs는 반드시 script로 로드해야하지만, lip.mjs는 app.mjs의 import문에 의해 로드되고 있으므로 script 태그로 로드하지 않아도 됨</p>
<p>export와 마찬가지로 모듈이 export한 식별자 이름을 일일이 지정하지 않고 하나의 이름으로 한 번에 import할 수도 있음
이때 import되는 식별자는 as 뒤에 지정한 이름의 객체에 프로퍼티로 할당됨</p>
<pre><code class="language-js">// app.mjs
// lib.mjs 모듈이 export한 모든 식별자를 lib 객체의 프로퍼티로 모아 import한다.
import * as lib from &#39;./lib.mjs&#39;;

console.log(lib.pi);         // 3.141592653589793
console.log(lib.square(10)); // 100
console.log(new lib.Person(&#39;Lee&#39;)); // Person { name: &#39;Lee&#39; }</code></pre>
<p>모듈이 export한 식별자 이름을 변경하여 import할 수도 있음</p>
<pre><code class="language-js">// app.mjs
// lib.mjs 모듈이 export한 식별자 이름을 변경하여 import한다.
import { pi as PI, square as sq, Person as P } from &#39;./lib.mjs&#39;;

console.log(PI);    // 3.141592653589793
console.log(sq(2)); // 4
console.log(new P(&#39;Kim&#39;)); // Person { name: &#39;Kim&#39; }</code></pre>
<p>모듈에서 하나의 값만 export한다면 <code>default</code> 키워드를 사용할 수 있음
이 키워드를 사용하는 경우 기본적으로 이름 없이 하나의 값을 export함</p>
<pre><code class="language-js">// lib.mjs
export default x =&gt; x * x;</code></pre>
<p>이러한 경우 <code>var</code>, <code>let</code>, <code>const</code> 키워드는 사용이 불가능하며 <code>default</code> 키워드와 함께 export한 모듈은 {} 없이 임의의 이름으로 바로 import함</p>
<pre><code class="language-js">// app.mjs
import square from &#39;./lib.mjs&#39;;

console.log(square(3)); // 9</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] 10813번: 공 바꾸기 - Java Script]]></title>
            <link>https://velog.io/@sing_/%EB%B0%B1%EC%A4%80-10813%EB%B2%88-%EA%B3%B5-%EB%B0%94%EA%BE%B8%EA%B8%B0-Java-Script</link>
            <guid>https://velog.io/@sing_/%EB%B0%B1%EC%A4%80-10813%EB%B2%88-%EA%B3%B5-%EB%B0%94%EA%BE%B8%EA%B8%B0-Java-Script</guid>
            <pubDate>Wed, 24 Jan 2024 06:36:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sing_/post/139381e8-a2b3-4b1d-9144-2e83742566a5/image.png" alt=""></p>
<h2 id="문제">문제</h2>
<p>도현이는 바구니를 총 N개 가지고 있고, 각각의 바구니에는 1번부터 N번까지 번호가 매겨져 있다. 바구니에는 공이 1개씩 들어있고, 처음에는 바구니에 적혀있는 번호와 같은 번호가 적힌 공이 들어있다.</p>
<p>도현이는 앞으로 M번 공을 바꾸려고 한다. 도현이는 공을 바꿀 바구니 2개를 선택하고, 두 바구니에 들어있는 공을 서로 교환한다.</p>
<p>공을 어떻게 바꿀지가 주어졌을 때, M번 공을 바꾼 이후에 각 바구니에 어떤 공이 들어있는지 구하는 프로그램을 작성하시오.</p>
<h2 id="입력">입력</h2>
<p>첫째 줄에 N (1 ≤ N ≤ 100)과 M (1 ≤ M ≤ 100)이 주어진다.</p>
<p>둘째 줄부터 M개의 줄에 걸쳐서 공을 교환할 방법이 주어진다. 각 방법은 두 정수 i j로 이루어져 있으며, i번 바구니와 j번 바구니에 들어있는 공을 교환한다는 뜻이다. (1 ≤ i ≤ j ≤ N)</p>
<p>도현이는 입력으로 주어진 순서대로 공을 교환한다.</p>
<h2 id="출력">출력</h2>
<p>1번 바구니부터 N번 바구니에 들어있는 공의 번호를 공백으로 구분해 출력한다.</p>
<h2 id="예제">예제</h2>
<p><strong>입력</strong></p>
<pre><code>5 4
1 2
3 4
1 4
2 2</code></pre><p><strong>출력</strong></p>
<pre><code>3 1 4 2 5</code></pre><hr>
<h2 id="풀이">풀이</h2>
<pre><code class="language-javascript">const fs = require(&#39;fs&#39;);
const input = fs.readFileSync(&quot;/dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);//제출용
const input = fs.readFileSync(&quot;10813/example.txt&quot;).toString().trim().split(&quot;\n&quot;);//풀이용

//바구니 N개와 공 바꿀 횟수 M번
let NM = input[0].split(&#39; &#39;).map(Number)
const N = NM[0],
    M = NM[1];

//바구니에 각 공 넣음
let answer = [];
for(let i = 0; i &lt; N; i++) { 
    answer.push(i+1)
}

//공을 바꾸기
for (let j = 1; j &lt;= M; j++) {
    let arr = input[j].split(&#39; &#39;).map(Number)
        ,k = arr[0] //k번째 바구니
        ,q = arr[1] //q번째 바구니
        ,k_value = answer[k-1];//k번째 바구니의 지금 담겨있는 값
    answer[k-1] = answer[q-1];
    answer[q-1] = k_value;
}

console.log(answer.join(&#39; &#39;))</code></pre>
<hr>
<h2 id="잘-몰랐던-부분과-배운-것">잘 몰랐던 부분과 배운 것</h2>
<p>값을 바꿔치기해야하는 법을 잘 몰라서 k_value 부분에서 많이 헤매었다! </p>
<p>1) 값을 교환할 때는 임시 변수를 만들어주는 방식으로 간단하게 해결 가능
2) 간단한 방식으로 변수 배열 split하여 변수 할당 가능</p>
<pre><code class="language-javascript">let [k, q] = input[j].split(&#39; &#39;).map(Number)</code></pre>
<p>3) 임시 변수에는 대개 <code>temp</code> 혹은 <code>tmp</code>라는 이름을 붙임</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VSCode] JavaScript 디버그 모드 오류]]></title>
            <link>https://velog.io/@sing_/VSCode-JavaScript-%EB%94%94%EB%B2%84%EA%B7%B8-%EB%AA%A8%EB%93%9C-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@sing_/VSCode-JavaScript-%EB%94%94%EB%B2%84%EA%B7%B8-%EB%AA%A8%EB%93%9C-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Tue, 23 Jan 2024 23:50:17 GMT</pubDate>
            <description><![CDATA[<h2 id="😱-문제-상황">😱 문제 상황</h2>
<p>중단점만 사용하고 있던 디버그 모드에 대해서 배운 후 테스트를 진행하려는데 내 마음대로 안 돌아가는 듯한 느낌!</p>
<p>어디가 마음대로 되지 않았냐 하면 <strong>실행 시켜도 variables, watct(조사식) 변화 없음</strong>
<img src="https://velog.velcdn.com/images/sing_/post/9f428d86-bbe1-479e-911c-d04d72c86b9c/image.png" alt=""></p>
<h2 id="🫶-해결">🫶 해결</h2>
<p>two 변수를 <strong><code>const</code>로 선언해놓고 재할당</strong>하려했기에 생긴 문제
에러가 나는 변수 앞에 중단점을 찍고 실행하면 제대로 실행이 된다
<img src="https://velog.velcdn.com/images/sing_/post/9abf4c96-6d8d-478f-be95-314ac3d93934/image.png" alt=""></p>
<p>왼쪽 변수, 조사식, 콜 스택 창에만 집중하고 DEBUG CONSOLE을 전혀 보지 않은 것이 문제의 원인</p>
<h2 id="➕-추가-정보">➕ 추가 정보</h2>
<h3 id="디버그-모드-사용-방법">디버그 모드 사용 방법</h3>
<p><strong>1. variables</strong>
local, global 등 변수에 정해진 값을 세밀하게 알 수 있음</p>
<p><strong>2. watch</strong>
관찰하려는 변수 이름을 입력해서 볼 수 있는 기능
변수만 가능할 뿐 아니라 문장도 사용할 수 있음(ex. <code>two === 2</code>라고 입력하면 <code>:true</code> 라고 알려줌)</p>
<p><strong>3. call stack</strong>
콜스택을 확인 가능</p>
<p><strong>4. loaded scripts</strong>
로딩된 모든 스크립트 확인 가능 </p>
<p><strong>5. breakpoints</strong>
break!
point를 걸어놓으면 거기까지만 코드가 실행됨
여러 개 걸고 체크박스 해제하며 테스트 가능</p>
<p><strong>6. 실행 메뉴</strong>
<img src="https://velog.velcdn.com/images/sing_/post/fc432513-dae1-4358-9099-958a31ee4485/image.png" alt=""></p>
<ul>
<li>맨 왼쪽 : 다음 중단점까지 실행</li>
<li>점 위에 화살표 있는 세 개: 단위 실행 / 단계 정보 / 단계 출력 <ul>
<li>단위 실행 step over: 중단점과 관계 없이 한 단위씩 차례로 실행, 다른 함수 호출하면 건너뛰기됨 </li>
<li>단계 정보 step into: 중단점과 관계 없이 한 단위씩 차례로 실행, 다른 함수 호출하면 들어가서 디버깅 </li>
<li>단계 출력 step out: 디버깅 중인 함수를 끝내고 바로 밖으로 나옴</li>
</ul>
</li>
<li>새로고침: 말 그대로 새로고침, 코드 바꿨을 때 새로고침하는 것</li>
<li>네모: 디버그 모드 중단</li>
</ul>
<h2 id="참고자료">참고자료</h2>
<p><a href="https://learn.microsoft.com/ko-kr/visualstudio/debugger/navigating-through-code-with-the-debugger?view=vs-2022&amp;tabs=csharp">microsoft - Visual Studio 디버거를 사용하여 코드 탐색</a>
<a href="https://learn.microsoft.com/ko-kr/visualstudio/debugger/debugging-absolute-beginners?view=vs-2022&amp;tabs=csharp">microsoft - 절대 초보자를 위한 디버그</a></p>
<hr>
<p>한 20분 구글링했는데도 마땅한 해결방법이 없어 당황했는데 
아싸 이제 console.log 복붙하면서 안 찍어봐도 된다!</p>
<hr>
<p>+)</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> Jan 25, 2024
당시에는 해결이 됐는데 또 문제가 발생했다. 
타입에 대한 확인을 했음에도 계속 오류가 발생함
<code>Java script debug terminal</code>로 실행하면 오류가 나는데 열심히 찾아봐도 아직 이유를 모르겠다ㅠㅠ
일단 방법을 디버깅할 때  node.js - run current file로 선택하면 문제없이 디버깅 된다 ! 
이유를 알게 되면 추가할 것</li>
<li><em>-&gt; 정확한 이유라기보다 해결방법을 찾음. 중단점에 대한 이해가 부족했다. 이 글을 쓸 때만 해도 &#39;중단점&#39;이 앞의 코드를 실행해서 멈추고 그 앞까지의 결과를 보는 것이라고 생각했는데 
디버그의 의미는 거기까지는 문제없이 실행, 그리고 그 다음에 하나하나 넘겨가며 내 의도와 다른 변수, 인수 등을 체크하는 것이다. 이 사실을 알고 난 이후부터는 디버그가 내 의도와 다르게 동작한다고 느낀 적은 없다. 의문점 해결~!*</em></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 22장 This]]></title>
            <link>https://velog.io/@sing_/vtosip7h</link>
            <guid>https://velog.io/@sing_/vtosip7h</guid>
            <pubDate>Tue, 23 Jan 2024 00:32:37 GMT</pubDate>
            <description><![CDATA[<h1 id="this">this</h1>
<p>자신이 속한 객체, 자신이 생성할 인스턴스를 가리키는 자기 참조 변수</p>
<p>자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있음</p>
<p>this가 가리키는 값, 즉 <strong>this 바인딩은 함수 호출 방식에 의해 동적으로 결정됨</strong></p>
<pre><code class="language-javascript">function Circle(radius) {
  // 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
  ????.radius = radius;
}

Circle.prototype.getDiameter = function () {
  // 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
  return 2 * ????.radius;
};

// 생성자 함수로 인스턴스를 생성하려면 먼저 생성자 함수를 정의해야 한다.
const circle = new Circle(5);</code></pre>
<p>여기서 생성자 함수의 호출로 인해 빈 객체에 radius:5가 들어가게 되는 것</p>
<p>this가 instance 자신이 되었기 때문</p>
<h3 id="함수-호출-방식에-따른-this-바인딩">함수 호출 방식에 따른 this 바인딩</h3>
<pre><code class="language-javascript">// this 바인딩은 함수 호출 방식에 따라 동적으로 결정된다.
const foo = function () {
  console.dir(this);
};

// 동일한 함수도 다양한 방식으로 호출할 수 있다.

// 1. 일반 함수 호출
// foo 함수를 일반적인 방식으로 호출
// foo 함수 내부의 this는 전역 객체 window를 가리킨다.
foo(); // window

// 2. 메서드 호출
// foo 함수를 프로퍼티 값으로 할당하여 호출
// foo 함수 내부의 this는 메서드를 호출한 객체 obj를 가리킨다.
const obj = { foo };
obj.foo(); // obj

// 3. 생성자 함수 호출
// foo 함수를 new 연산자와 함께 생성자 함수로 호출
// foo 함수 내부의 this는 생성자 함수가 생성한 인스턴스를 가리킨다.
new foo(); // foo {}

// 4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
// foo 함수 내부의 this는 인수에 의해 결정된다.
const bar = { name: &#39;bar&#39; };

foo.call(bar);   // bar
foo.apply(bar);  // bar
foo.bind(bar)(); // bar</code></pre>
<h4 id="일반-함수-호출">일반 함수 호출</h4>
<p>일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함)의 내부에는 this 전역 객체가 바인딩됨</p>
<p>메서드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메서드의 this 바인딩과 일치시키기 위해서는 </p>
<pre><code class="language-javascript">var value = 1;

const obj = {
  value: 100,
  foo() {
    // this 바인딩(obj)을 변수 that에 할당한다.
    const that = this;

    // 콜백 함수 내부에서 this 대신 that을 참조한다.
    setTimeout(function () {
      console.log(that.value); // 100
    }, 100);
  }
};

obj.foo();</code></pre>
<p>or </p>
<p>this를 명시적으로 바인딩하기위해 Function.prototype.apply, Function.prototype.call, Function.prototype.bind 메서드를 사용</p>
<p>or </p>
<p>화살표 함수를 사용해서 this 바인딩을 일치시킬 수도 있음</p>
<pre><code class="language-javascript">var value = 1;

const obj = {
  value: 100,
  foo() {
    // 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다.
    setTimeout(() =&gt; console.log(this.value), 100); // 100
  }
};

obj.foo();</code></pre>
<p>화살표 함수 내부의 this는 상위 스코프의 this를 가리키는 특징이 있기 때문</p>
<h4 id="메서드-호출">메서드 호출</h4>
<p>메서드 호출했을 때 메서드 이름 앞의 (.) 앞에 기술한 객체가 바인딩</p>
<p>주의점은 메서드를 소유한 객체가 아닌 메서드를 &#39;호출&#39;한 객체에 반영됨</p>
<pre><code class="language-javascript">const anotherPerson = {
  name: &#39;Kim&#39;
};
// getName 메서드를 anotherPerson 객체의 메서드로 할당
anotherPerson.getName = person.getName;

// getName 메서드를 호출한 객체는 anotherPerson이다.
console.log(anotherPerson.getName()); // Kim

// getName 메서드를 변수에 할당
const getName = person.getName;

// getName 메서드를 일반 함수로 호출
console.log(getName()); // &#39;&#39;
// 일반 함수로 호출된 getName 함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
// 브라우저 환경에서 window.name은 브라우저 창의 이름을 나타내는 빌트인 프로퍼티이며 기본값은 &#39;&#39;이다.
// Node.js 환경에서 this.name은 undefined다.</code></pre>
<p>프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 마찬가지로 해당 메서드를 호출한 객체에 바인딩</p>
<h4 id="생성자-함수-호출">생성자 함수 호출</h4>
<p>생성자 함수 내부의 this에는 생성자 함수가 미래에 생성할 인스턴스가 바인딩됨</p>
<pre><code class="language-javascript">// 생성자 함수
function Circle(radius) {
  // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20</code></pre>
<p>즉, <code>console.log(circle1.getDiameter());</code>을 통해 생성자 함수 내부의 this는 circle1이 되는 것</p>
<h4 id="callapplybind-메서드에-의한-간접호출">call/apply/bind 메서드에 의한 간접호출</h4>
<p>세 가지 메서드는 Function.prototype의 메서드</p>
<p>apply, call - 함수를 호출하는 메서드로 apply와 call 메서드는 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩</p>
<p>둘의 차이점은 오직 &#39;인수를 전달하는 방식&#39;으로 apply는 호출할 함수의 인수를 배열로 묶어 전달하고, call은 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달 </p>
<pre><code class="language-javascript">function getThisBinding() {
  console.log(arguments);
  return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };

// getThisBinding 함수를 호출하면서 인수로 전달한 객체를 getThisBinding 함수의 this에 바인딩한다.
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다.
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// {a: 1}

// call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// {a: 1}</code></pre>
<p>bind 메서드 - 함수를 호출하는 메서드가 아니고, 첫 번째 인수를 전달한 값으로 this 바인딩이 교체된 함수를 해롭게 생성해 반환함</p>
<pre><code class="language-javascript">function getThisBinding() {
  return this;
}

// this로 사용할 객체
const thisArg = { a: 1 };

// bind 메서드는 첫 번째 인수로 전달한 thisArg로 this 바인딩이 교체된
// getThisBinding 함수를 새롭게 생성해 반환한다.
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야 한다.
console.log(getThisBinding.bind(thisArg)()); // {a: 1}</code></pre>
<p>간단하게 정리해서는</p>
<p>일반 함수 호출 - 전역 객체</p>
<p>메서드 호출 - 메서드를 호출한 객체</p>
<p>생성자 함수 호출 - 생성자 함수가 (미래에) 생성할 인스턴스
Function.prototype.apply/call/bind 메서드에 의한 간접 호출 - 메서드에 첫 번째 인수로 전달한 객체</p>
<pre><code class="language-javascript">const person = {
  name: &#39;Lee&#39;,
  foo(callback) {
    // bind 메서드로 callback 함수 내부의 this 바인딩을 전달
    setTimeout(callback.bind(this), 100);
  }
};

person.foo(function () {
  console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 45장 프로미스]]></title>
            <link>https://velog.io/@sing_/%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-45%EC%9E%A5-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4</link>
            <guid>https://velog.io/@sing_/%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-45%EC%9E%A5-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4</guid>
            <pubDate>Mon, 22 Jan 2024 09:15:24 GMT</pubDate>
            <description><![CDATA[<p>비동기 처리를 위한 방법으로는 세 가지가 있다</p>
<ol>
<li>콜백 함수</li>
<li>프로미스</li>
<li>async - awiat</li>
</ol>
<p>오늘은 그 두번째 프로미스에 대해 알아볼 것!</p>
<hr>
<h2 id="비동기-처리를-위한-콜백-패턴의-단점">비동기 처리를 위한 콜백 패턴의 단점</h2>
<p>비동기 처리를 위해 사용하는 콜백 패턴의 단점은 크게 두 가지가 있음
<strong>콜백 헬</strong>과 <strong>에러 처리의 한계</strong>가 그것</p>
<h3 id="1-콜백-헬-callback-hell">1. 콜백 헬 callback hell</h3>
<pre><code class="language-javascript">let g = 0;

// 비동기 함수인 setTimeout 함수는 콜백 함수의 처리 결과를 외부로 반환하거나
// 상위 스코프의 변수에 할당하지 못한다.
setTimeout(() =&gt; { g = 100; }, 0);
console.log(g); // 0</code></pre>
<p>이 예시처럼 비동기 함수 내부의 비동기로 동작하는 코드에서 처리 결과는 외부로 반환하거나 상위 스코프의 변수에 할당할 수 없음
따라서 <strong>비동기 처리 결과(서버의 응답 등)에 대한 후속 처리는 비동기 함수 내부에서 수행해야함</strong>
이때 비동기 함수에 비동기 처리 결과에 대한 후속 처리를 수행하는 콜백 함수를 전달하는 것이 일반적임</p>
<p>이처럼 콜백 함수를 통해 비동기 처리 결과에 대한 후속 처리를 수행하는 비동기 함수가/
비동기 결과를 가지고 또 다시 비동기 함수를 호출
-&gt; 콜백 함수 호출이 중첩되어 복잡도가 높아지는 현상 발생
이것이 <strong>콜백 헬</strong></p>
<pre><code class="language-javascript">get(&#39;/step1&#39;, a =&gt; {
  get(`/step2/${a}`, b =&gt; {
    get(`/step3/${b}`, c =&gt; {
      get(`/step4/${c}`, d =&gt; {
        console.log(d);
      });
    });
  });
});</code></pre>
<h3 id="2-에러-처리의-한계">2. 에러 처리의 한계</h3>
<pre><code class="language-javascript">try {
  setTimeout(() =&gt; { throw new Error(&#39;Error!&#39;); }, 1000);
} catch (e) {
  // 에러를 캐치하지 못한다
  console.error(&#39;캐치한 에러&#39;, e);
}</code></pre>
<p>코드 설명</p>
<p>try코드 블록에 포함된 문에서 에러가 발생하면 해당 에러는 catch 문의 변수에 전달되고 catch 코드 블록이 실행됨</p>
<p>이 코드의 try 블록은 <code>setTimeout</code> 함수를 사용하여 <strong>1초 후 에러를 발생시키는 비동기 작업</strong>을 하고 있음</p>
<p><code>throw</code>: throw 키워드는 예외를 발생시킬 때 사용됨
<code>new Error(&#39;Error message&#39;)</code>: Error는 JavaScript에서 기본적으로 제공되는 내장 객체로, 에러를 나타냄. &#39;Error message&#39;는 에러 객체를 생성하면서 에러 메시지를 설정하는 것입니다. 에러 메시지는 해당 예외가 발생한 이유를 설명하는 문자열</p>
<p>그러나 비동기 작업을 수행하고 있기 때문에 <code>catch</code>블록은 예외를 잡아내지 못함</p>
<h2 id="프로미스의-생성">프로미스의 생성</h2>
<p><strong>Promise 생성자 함수</strong></p>
<ul>
<li>new와 함께 호출하면 Promise 객체를 생성</li>
<li>Promise 생성자 함수는 비동기 처리를 수행할 콜백 함수를 인수로 전달받는데 이 콜백 함수는 resolve와 reject 함수를 인수로 전달받음</li>
<li>비동기 처리가 성공하면 처리 결과를 resolve 함수에 인수로 전달하여 호출, 실패하면 reject 함수에 에러를 인수로 전달하여 호출</li>
</ul>
<pre><code class="language-javascript">// 프로미스 생성
const promise = new Promise((resolve, reject) =&gt; {
  // Promise 함수의 콜백 함수 내부에서 비동기 처리를 수행한다.
  if (/* 비동기 처리 성공 */) {
    resolve(&#39;result&#39;);
  } else { /* 비동기 처리 실패 */
    reject(&#39;failure reason&#39;);
  }
});</code></pre>
<p>프로미스는 비동기 처리의 진행에 세 가지 상태 정보를 가짐</p>
<ol>
<li>pending - 비동기 처리가 아직 수행되지 않은, 프로미스가 생성된 직후 기본 상태</li>
<li>fulfilled - 비동기 처리가 수행됐고, 성공한 상태. resolve 함수 호출하면 상태가 변경됨</li>
<li>rejected - 비동기 처리가 수행됐고, 실패한 상태. reject 함수 호출하면 상태가 변경됨</li>
</ol>
<p>fulfilled 또는 rejected는 setteld 상태라고 함
즉, settled 상태는 비동기 처리가 수행된 상태</p>
<p>pending 상태에서는 settled 상태로 변화할 수 있찌만, settled 상태가 되면 더는 다른 상태로 변화할 수 없음</p>
<p><strong>주의: 프로미스는 객체!</strong>
프로미스는 비동기 처리 상태와 더불어 비동기 처리 결과도 상태로 가짐</p>
<p><img src="https://velog.velcdn.com/images/sing_/post/0993107a-b2f3-46e1-acad-3f2ec761982b/image.png" alt=""></p>
<p>여기서 fulfilled는 비동기 처리 상태에 한 정보이며, 1은 비동기 처리 결과인 1을 값으로 가짐</p>
<p>따라 즉, <strong>프로미스는 비동기 처리 상태와 처리 결과를 관리해는 객체</strong></p>
<h2 id="프로미스의-후속-처리-메서드">프로미스의 후속 처리 메서드</h2>
<h3 id="promiseprototypethen">Promise.prototype.then</h3>
<p><code>then</code>메서드는 두 개의 콜백 함수를 인수로 전달 받음
언제나 프로미스를 반환</p>
<p>첫 번째 콜백 함수는 비동기 처리가 성공했을 때 호출되는 성공 처리 콜백 함수
두 번째 콜백 함수는 비동기 처리가 실패했을 때 호출되는 실패 처리 콜백 함수</p>
<pre><code class="language-javascript">// fulfilled
new Promise(resolve =&gt; resolve(&#39;fulfilled 반환&#39;))
  .then(v =&gt; console.log(v), e =&gt; console.error(e)); // fulfulled 반환 -&gt; 처리 결과 값을 인수로 전달 받음

// rejected
new Promise((_, reject) =&gt; reject(new Error(&#39;에러&#39;)))
  .then(v =&gt; console.log(v), e =&gt; console.error(e)); // Error: 에러 반환 -&gt; 프로미스의 에러를 인수로 전달 받음</code></pre>
<h3 id="promiseprototypethen-1">Promise.prototype.then</h3>
<p><code>catch</code> 메서드는 한 개의 콜백 함수만을 인수로 전달받고
catch 메서드의 콜백 함수는 프로미스가 rejected 상태인 경우에만 호출됨</p>
<pre><code class="language-javascript">// rejected
new Promise((_, reject) =&gt; reject(new Error(&#39;rejected&#39;)))
  .catch(e =&gt; console.log(e)); // Error: rejected</code></pre>
<h3 id="promiseprototypefinally">Promise.prototype.finally</h3>
<p><code>finally</code>메서드는 한 개의 콜백 함수를 인수르 전달 받음
프로미스의 성공과 실패에 관계없이 무조건 한 번 호출되고
<strong>프로미스의 상태와 상관없이 공통적으로 수행해야 할 처리 내용이 있을 때 유용</strong>
finally 역시 언제나 프로미스를 반환함</p>
<h2 id="프로미스의-에러-처리">프로미스의 에러 처리</h2>
<p>비동기 처리에서 발생하는 에러는 (1) then 메서드의 두 번째 콜백 함수로 처리하거나 (2) catch 메서드를 사용하여 처리 가능</p>
<ol>
<li>then<pre><code class="language-javascript">const wrongUrl = &#39;https://jsonplaceholder.typicode.com/XXX/1&#39;;
</code></pre>
</li>
</ol>
<p>// 부적절한 URL이 지정되었기 때문에 에러가 발생한다.
promiseGet(wrongUrl).then(
  res =&gt; console.log(res),
  err =&gt; console.error(err)
); // Error: 404</p>
<pre><code>2. catch
```javascript
const wrongUrl = &#39;https://jsonplaceholder.typicode.com/XXX/1&#39;;

// 부적절한 URL이 지정되었기 때문에 에러가 발생한다.
promiseGet(wrongUrl)
  .then(res =&gt; console.log(res))
  .catch(err =&gt; console.error(err)); // Error: 404</code></pre><p>then메서드 사용 이후 catch 메서드 사용하면 비동기 처리에서 발생한 에러 뿐 아니라 then 메서드 내부에서 발생한 에러까지 모두 캐치 가능
또한, then 메서드에 두 번째 콜백 함수를 전달하는 것보다 catch 메서드를 사용하는 것이 가독성이 좋고 명확함
-&gt; 따라 에러 처리는 catch 메서드에서 하는 것이 권장됨</p>
<h2 id="프로미스-체이닝">프로미스 체이닝</h2>
<p>then, catch, finally 후속 처리 메서드는 콜백 함수가 반환한 프로미스를 반환
콜백 함수가 프로미스가 아닌 값을 반환하더라도 그 값을 암묵적으로 resolve 또는 reject하여 프로미스를 생성해 반환함 
따라서 then, catch, finally 후속 처림 메서드는 언제나 프로미스를 반환하므로 연속적으로 호출할 수 있음. 이것을 <strong>프로미스 체이닝</strong>이라고 함</p>
<p>따라서 프로미스는 프로미스 체이닝을 통해 비동기 처리 결과를 전달받아 후속 처리를 하므로 비동기 처리를 위한 콜백 패턴에서 발생하던 콜백헬이 발생하지 않음</p>
<h2 id="프로미스의-정적-메서드">프로미스의 정적 메서드</h2>
<p>Promise는 주로 생성자 함수로 사용되지만, 함수도 객체이므로 메서드를 가질 수 있음
Promise는 5가지 정적 메서드를 제공</p>
<h3 id="promiseresolvepromisereject">Promise.resolve/Promise.reject</h3>
<p>이미 존재하는 값을 래핑하여 프로미스를 생성하기 위해 사용하는 메서드
<code>Promise.resolve</code> 메서드는 인수로 전달받은 값을 resolve하는 프로미스를 생성
<code>Promise.reject</code> 메서드는 인수로 전달받은 값을 reject하는 프로미스를 생성</p>
<h3 id="promiseall">Promise.all</h3>
<p>여러 개의 비동기 처리를 모두 병렬 처리할 때 사용</p>
<pre><code class="language-javascript">const requestData1 = () =&gt; new Promise(resolve =&gt; setTimeout(() =&gt; resolve(1), 3000));
const requestData2 = () =&gt; new Promise(resolve =&gt; setTimeout(() =&gt; resolve(2), 2000));
const requestData3 = () =&gt; new Promise(resolve =&gt; setTimeout(() =&gt; resolve(3), 1000));

Promise.all([requestData1(), requestData2(), requestData3()])
  .then(console.log) // [ 1, 2, 3 ] ⇒ 약 3초 소요
  .catch(console.error);</code></pre>
<p><code>Promise.all</code>= 메서드는 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받고,
전달받은 모든 프로미스가 모두 fulfilled 상태가 되면 모든 처리 결과를 배열에 저장해 새로운 프로미스를 반환</p>
<p>인수로 전달받은 배열의 모든 프로미스가 모두 fulfilled 상태가 되면 종료
-&gt; Promise.all 메서드가 종료하는 데 걸리는 시간은 가장 늦게 fulfilled 상태가 되는 프로미스의 처리 시간보다 조금 더 길다</p>
<p>이때! 첫번째 프로미스가 가장 늦게 fulfilled 상태가 되더라도, 첫번째 프로미스가 resolve한 처리 결과부터 차례대로 배열에 저장해 그 배열을 resolve하는 새로운 프로미스를 반환
=즉, 처리순서가 보장됨</p>
<p>인수로 전달받은 배열의 프로미스가 하나라도 rejected 상태가 되면 즉시  종료</p>
<h3 id="promiserace">Promise.race</h3>
<p><code>Promise.all</code> 메서드와 동일하게 프로미스를 요소로 가지는 배열 등의 이터러블을 인수로 전달받지만, 모든 프로미스가 fulfilled 상태가 되는 것을 기다리지 않고 가장 먼저 fulfilled 상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환</p>
<p><code>Promise.all</code>과 동일하게 메서드에 전달된 프로미스가 하나라도 rejected 상태가 되면 에러를 reject하는 새로운 프로미스를 즉시 반환</p>
<h3 id="promiseallsettled">Promise.allSettled</h3>
<p>프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받음
그리고 전달받은 프로미스가 모두 settled 상태가 되면 처리 결과를 배열롸 반환</p>
<h2 id="마이크로태스크-큐">마이크로태스크 큐</h2>
<p><strong>프로미스의 후속 처리 메서드의 콜백 함수는 태스크 큐가 아니라 마이크로 태스크 큐에 저장됨</strong>
마이크로태스크 큐는 태스크 큐보다 우선 순위가 높음
즉, 이벤트 루프는 콜 스택이 비면 먼저 마이크로태스크 큐에서 대기하고 있는 함수를 가져와 실행함
이후 마이크로태크스 큐가 비면 태스크 큐에서 대기하고 있는 함수를 가져와 실행함</p>
<h2 id="fetch">fetch</h2>
<p><code>fetch</code> 함수는 XMLHttlRequest 객체와 마찬가지로 HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 웹 API </p>
<p><code>fetch</code> 함수에는 HTTP 요청을 전송할 URL과 HTTP 요청 메서드, HTTP 요청 헤더, 페이로드 등을 설정한 객체를 전달함</p>
<pre><code class="language-javascript">//syntax

fetch(&#39;https://jsonplaceholder.typicode.com/todos/1&#39;)
  .then(response =&gt; console.log(response));</code></pre>
<p><code>fetch</code> 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환하므로 후속 처리 메서드 then을 통해 프로미스가 resolve한 Response 객체를 전달받을 수 있음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모던 자바스크립트 Deep Dive 42장 비동기 프로그래밍]]></title>
            <link>https://velog.io/@sing_/%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-42%EC%9E%A5-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@sing_/%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-42%EC%9E%A5-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Mon, 22 Jan 2024 04:38:50 GMT</pubDate>
            <description><![CDATA[<h2 id="비동기-처리">비동기 처리</h2>
<h3 id="함수를-호출하면-발생하는-일">함수를 호출하면 발생하는 일</h3>
<ol>
<li>함수 코드가 평가되어 함수 실행 컨텍스트가 생성됨</li>
<li>생성된 함수 실행 컨텍스트는 실행 컨텍스트 스택(=콜스택)에 푸시되고, 함수 코드 실행</li>
<li>함수 코드의 실행이 종료하면 함수 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거</li>
</ol>
<p>자바스크립트 엔진은 <strong>한 번에 하나의 태스크만 실행하는 싱글 스레드</strong> 방식으로 동작함
=동시에 두 개 이상의 함수를 실행할 수 없고
=처리에 시간이 걸리는 태스크를 실행하는 경우 <strong>블로킹(작업 중단)</strong>이 발생함</p>
<p><strong>동기 처리 방식 예시</strong></p>
<pre><code class="language-javascript">// sleep 함수는 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
function sleep(func, delay) {
  // Date.now()는 현재 시간을 숫자(ms)로 반환한다.(&quot;30.2.1. Date.now&quot; 참고)
  const delayUntil = Date.now() + delay;

  // 현재 시간(Date.now())에 delay를 더한 delayUntil이 현재 시간보다 작으면 계속 반복한다.
  while (Date.now() &lt; delayUntil);
  // 일정 시간(delay)이 경과한 이후에 콜백 함수(func)를 호출한다.
  func();
}

function foo() {
  console.log(&#39;foo&#39;);
}

function bar() {
  console.log(&#39;bar&#39;);
}

// sleep 함수는 3초 이상 실행된다..
sleep(foo, 3 * 1000);
// bar 함수는 sleep 함수의 실행이 종료된 이후에 호출되므로 3초 이상 블로킹된다.
bar();
// (3초 경과 후) foo 호출 -&gt; bar 호출</code></pre>
<p>이 예제에서 sleep 함수는 3초 후에 foo 함수를 호출
따라 bar 함수는 3초동안 호출되지 못하고 블로킹됨
이처럼 현재 실행 중인 태스크가 종료할 때까지 다음에 실행될 태스크가 대기하는 방식이 동기 처리</p>
<p><strong>비동기 처리 방식 예시</strong>
같은 상황을 비동기 방식으로 처리하는 예제</p>
<pre><code class="language-javascript">function foo() {
  console.log(&#39;foo&#39;);
}

function bar() {
  console.log(&#39;bar&#39;);
}

setTimeout(foo, 3*1000);
bar();

//출력결과:
//bar
//(3초 후) foo</code></pre>
<p>앞의 예시와 동일하게 일정 시간 경과 이후 콜백함수를 호출하지만
setTimeout함수 이후의 bar 함수의 실행을 블로킹하지 않음
이처럼 현재 실행 중인 태스크가 종료 되지 않은 상태라 해도 다음 태스크를 바로 실행하는 방식이 비동기 처리</p>
<p>비동기 처리를 수행하는 함수는 <strong>콜백 패턴</strong>을 사용하는데, 여기서 발생하는 여러 단점을 보완하고자 &#39;프로미스 Promise&#39;가 사용됨</p>
<p>타이머 함수인 setTimeout과 setInterval, HTTP요정, 이벤트 핸들러는 비동기처리 방식으로 동작하는데 비동기처리는 이벤트 루프와 태스크 큐와 깊은 관련이 있음</p>
<h2 id="이벤트-루프와-태스크-큐">이벤트 루프와 태스크 큐</h2>
<p>자바스크립트는 싱글 스레드로 동작하지만, 브라우저의 동작을 살펴보면 여러 태스크가 동시에 동작하는 것처럼 느껴짐. </p>
<p>이러한 자바스크립트의 <strong>동시성</strong>을 지원하는 것이 바로 <strong>이벤트 루프</strong></p>
<p>이벤트 루프는 브라우저에 내장되어 있는 기능 중 하나</p>
<p>대부분의 자바스크립트 엔진은 크게 콜 스택과 힙으로 구분할 수 있음</p>
<ul>
<li>콜 스택 call stack
소스코드 평가 과정에서 생성된 실행 컨택스트가 추가되고 제거되는 스택 자료구조인 <strong>실행 컨택스트 스택</strong></li>
<li>힙 heep
객체가 저장되는 메모리 공간으로, 실행 컨텍스트는 힙에 저장된 객체를 참조함</li>
</ul>
<p>자바스크립트 엔진은 태스크가 요청되면 콜 스택을 통해 요청된 작업을 순차적으로 <strong>실행</strong>만을 담당함
비동기 처리에서 소스코드의 평가와 실행을 제외한(자바스크립트 엔진의 역할)
모든 처리는 자바스크립트 엔진을 구동하는 <strong>환경</strong>인 브라우저 또는 Node.js가 담당</p>
<p>이를 위해서 브라우저 환경은 태스크 큐와 이벤트 루프를 제공</p>
<ul>
<li>태스크 큐 task queue
비동기 함수의 콜백 함수 또는 이벤트 핸들러가 일시적으로 보관되는 영역</li>
<li>이벤트 루프 event loop
콜 스택에 현재 실행 중인 실행 컨텍스트가 있는지, 태스크 큐에 대기 중인 함수(콜백 함수, 이벤트 핸들러 등)가 있는지 반복해서 확인</li>
<li><em>만약 콜 스택이 비어있고 태스크 큐에 대기 중인 함수가 있다면 이벤트 루프는 순차적(선입선출 FIFO)으로 태스크 큐에 대기 주인 함수를 콜 스택으로 이동시킴*</em></li>
</ul>
<p>쉽게 말해, 비동기 함수의 콜백 함수는 태스크 큐에 푸시되어 대기하다가 콜 스택이 비게 되면(=전역 코드 및 명시적으로 호출된 함수의 종료) 이벤트 루프를 통해 콜 스택에 푸시 되어 실행됨</p>
<p>주의할 것이, 브라우저에 내장된 <strong>자바스크립트 엔진은 싱글 스레드 방식으로 동작</strong>하고 <strong>브라우저는 멀티 스레드로 동작</strong>!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1월 3일의 TIL]]></title>
            <link>https://velog.io/@sing_/1%EC%9B%94-3%EC%9D%BC%EC%9D%98-TIL</link>
            <guid>https://velog.io/@sing_/1%EC%9B%94-3%EC%9D%BC%EC%9D%98-TIL</guid>
            <pubDate>Wed, 03 Jan 2024 12:11:27 GMT</pubDate>
            <description><![CDATA[<p>기록용 TIL...
복습만 해도 하루가 정말 후딱 간다 ㅠㅠ ㅠ !!!
매일 쓸 수도 있고 깃헙으로 옮길수도 공개나 비공개로 전환할 수도 있고?! </p>
<p>좋은 TIL에 대한 글을 읽었지만 코드를 분석하는 것이 아니라 암기와 적용 수준이라 그냥 빽빽이처럼 쓰기로함^.^</p>
<p>아직은 공부법을 찾아가는 중이라 일단 벨로그에 남겨봄.. 모르면 빠르게 검색이라도 하자 !!!!!</p>
<hr>
<h2 id="html-클론-코딩으로-홈페이지-만들기">html 클론 코딩으로 홈페이지 만들기</h2>
<h3 id="-html-">[ html ]</h3>
<h4 id="span태그"><code>&lt;span&gt;</code>태그</h4>
<p><code>&lt;div&gt;</code>와<code>&lt;p&gt;</code>와 함께 웹페이지 <strong>일부</strong>의 스타일을 바꾸기 위해 사용
span 태그 내부에 객체가 들어가면 <strong>그 객체의 크기만큼 공간이 할당됨</strong>
span 태그로 요소를 감싸면 CSS나 javascript로 그 부분을 변형시키는 것이 가능해짐 </p>
<h4 id="ul태그와-ol태그"><code>&lt;ul&gt;</code>태그와 <code>&lt;ol&gt;</code>태그</h4>
<p><code>&lt;ol&gt;</code>태그는 oldered list = 순서가 있는 목록
<code>&lt;ul&gt;</code>태그는 unordered list = 순서가 필요 없는 목록
+) <code>&lt;dl&gt;</code>태그는 definition list = 사전처럼 용어를 설명하는 목록</p>
<h4 id="태그-안에-각-항목들을-나열할-때는-li-태그를-사용">태그 안에 각 항목들을 나열할 때는 <code>&lt;li&gt;</code> 태그를 사용</h4>
<pre><code class="language-html">  ex)
  &lt;ol&gt;
    &lt;li&gt;하하
    &lt;li&gt;히히
    &lt;li&gt;호호
  &lt;/ol&gt;</code></pre>
<p>  출력 화면은</p>
<ol>
<li>하하</li>
<li>히히</li>
<li>호호</li>
</ol>
<p>  +) 여기 li태그 안에 꼭 텍스트가 들어가야하는 것이 아님! 
  이미지도 들어갈 수 있음 <code>&lt;li&gt;&lt;img src=&quot;./img/thumb-1.png&quot;&gt;&lt;li&gt;</code> 이런 식으로</p>
<h4 id="article태그"><code>&lt;article&gt;</code>태그</h4>
<p>독립적으로 배포 가능하거나 재사용할 수 있는 콘텐츠를 묶는 영역으로 사용
ex) 게시판 글, 뉴스 기사, 블로그 글, 댓글 등</p>
<h4 id="form태그"><code>&lt;form&gt;</code>태그</h4>
<pre><code>&lt;form&gt;
    &lt;input 
    type=&quot;email&quot;
    name=&quot;email&quot; 
    placeholder=&quot;이메일을 입력해 주세요&quot; 
    required/&gt;
  &lt;/form&gt;</code></pre><p>폼 입력 받을 때 사용하는 태그</p>
<h3 id="-css-">[ CSS ]</h3>
<h4 id="position">Position</h4>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/position">설명링크</a>
브라우저 전체 화면(viewport)을 기준으로 요소가 배치됨
position 속성은 html 요소가 어떻게 배치되는가를 결정하는데, 이 속성의 값을 fixed로 지정해주면 고정 배치가 적용됨</p>
<pre><code class="language-html">.alpha {
  position: fixed;
}</code></pre>
<ul>
<li><p>static
기본값. 자연스러운 흐름에서의 &#39;원래 위치&#39;에 위치하게 함</p>
</li>
<li><p>fixed
화면을 위아래로 스크롤하더라도 브라우저 화면의 특정 부분에 고정되어 움직이지 않도록 하는 것
부모 요소나 자신을 기준으로 하는 것이 아니라 &#39;viewport&#39;를 기준으로 배치함 
아래 예시는 &#39;하단에서 8px, 우측으로부터 16px&#39; 떨어지도록 한 것</p>
<pre><code>div:nth-of-type(2) {
position: fixed;
bottom: 8px;
right: 16px; }</code></pre></li>
<li><p>absolute
해당 요소는 배치 기준을 자신이 아닌 상위 요소에서 찾음 
DOM 트리를 따라 올라가다가 position 속성이 static이 아닌 첫 번째 상위 요소가 해당 요소의 배치 기준으로 설정
대개 부모 요소 기준을 따르도록 할 때 사용하마</p>
</li>
<li><p>relative
원래 위치로부터 지정한 값만큼 상대적으로 이동시켜 배치</p>
</li>
</ul>
<h4 id="z-index">z-index</h4>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/z-index">설명링크</a>
겹친 요소의 순서 지정
(포토샵의 &#39;레이어&#39;와 비슷하다고 이해하면 됨)
맨 위로 올라오게 하려면 1 사용</p>
<pre><code>z-index: 0;
z-index: 3;
z-index: 289;
z-index: -1; </code></pre><h4 id="padding">padding</h4>
<p>구역 안쪽 여백 설정
위를 기준으로 시계 방향으로 생각하면 됨
padding: 위 오른쪽 아래 왼쪽 ;</p>
<pre><code>/* 네 면 모두 적용 */
padding: 1em;

/* 세로방향 | 가로방향 */
padding: 5% 10%;

/* 위 | 가로방향 | 아래 */
padding: 1em 2em 2em;

/* 위 | 오른쪽 | 아래 | 왼쪽 */
padding: 5px 1em 0 2em;

/* 전역 값 */
padding: inherit;
padding: initial;
padding: unset;</code></pre><p>padding은 요소 &#39;안쪽&#39; 빈 공간인 반면
margin은 요소 주위의 여백을 설정</p>
<h4 id="display-inline-block">display: inline-block</h4>
<p>inline 요소는 x축 정렬 형태로 출력(줄바꿈 현상 x 한 줄에 출력됨), 공간을 만들 수 있고 상하 배치 작업 가능</p>
<p>block 요소는 y축 정렬 형태로 출력(줄바꿈 현상 o), 공간을 만들 수 없고 상하 배치 작업 불가능</p>
<p>inline-block은 일종의 하이브리드
기본적으로 inlie 요소처럼 줄바꿈 없이 출력되지만,
block 요소처럼 width와 height 속성 지정, margin과 padding 속성으로 상하 간격 지정이 가능함</p>
<p>none;을 입력하면 요소가 완전히 사라진 것처럼 보이게 만듦</p>
<h4 id="css-요소의-우선순위">css 요소의 우선순위</h4>
<p>1) 순서
나중에 적용한 속성값의 우선순위가 더 높음  </p>
<pre><code class="language-css">/* &lt;p&gt;Hello World&lt;/p&gt; */
p { color: red; }
p { color: blue; ]
</code></pre>
<p>2) 디테일
더 구체적으로 작성된 선택자의 우선순위가 더 높음</p>
<pre><code class="language-css">header p {color: red; }
p { color: blue; }
</code></pre>
<p>3) 선택자 </p>
<p>style &gt; id &gt; class &gt; type 순으로 우선순위가 높음</p>
<pre><code class="language-css">&lt;h3 style=&quot;color: pink&quot; id=&quot;color&quot; class=&quot;color&quot;&gt; color &lt;/h3&gt;

#color { color: blue; }
.color { color: red; }
h3 {color: green; }
</code></pre>
<h4 id="white-space">white-space</h4>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/white-space">설명링크</a>
CSS white-space 속성은 요소가 공백 문자를 처리하는 법</p>
<ul>
<li><p>normal
연속 공백을 하나로 합치고, 개행 문자( \ r \ n)도 다른 공백 문자와 동일하게 봄
자동줄바꿈됨</p>
</li>
<li><p>nowrap
연속 공백을 하나로 합침. 줄 바꿈은 <br> 요소에서만 일어남</p>
</li>
<li><p>pre
연속 공백 유지. 줄 바꿈은 개행 문자와 <br> 요소에서만 일어남</p>
</li>
<li><p>pre-wrap
연속 공백 유지. 줄 바꿈은 개행 문자와 <br> 요소에서 일어나며, 한 줄이 너무 길어서 넘칠 경우 자동으로 줄을 바꿈</p>
</li>
<li><p>pre-line
연속 공백을 하나로 합침. 줄바꿈은 개행 문자와 <br> 요소에서 일어나며, 한 줄이 너무 길어서 넘칠 경우 자동으로 줄을 바꿈</p>
</li>
</ul>
<h4 id="line-height">line-height</h4>
<p>행간 조정
정확히 말하면 박스의 높이를 만들어주는 것</p>
<h4 id="max-width">max-width</h4>
<p>width의 한계를 설정해줌
width의 크기는 max-width를 넘을 수 없음</p>
<h4 id="focus">:focus</h4>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/:focus">추가링크</a>
CSS:focus 는 양식의 입력 칸 등(ex: 이메일 등) 포커스 받은 요소를 나타냄
사용자가 요소를 클릭 또는 탭하거나, 키보드 탭 키로 &#39;선택&#39;했을 때 효과가 발동함</p>
<pre><code>/* Selects any &lt;input&gt; when focused */
input:focus {
  color: red;
}</code></pre><h2 id="실습-강의">실습 강의</h2>
<h3 id="javascript">[JavaScript]</h3>
<h4 id="foreach메서드">forEach메서드</h4>
]]></description>
        </item>
    </channel>
</rss>