<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>has_log</title>
        <link>https://velog.io/</link>
        <description>예비 프론트엔드 개발자입니다! 피드백 대환영!! 질문 대환영!!</description>
        <lastBuildDate>Mon, 22 Aug 2022 10:20:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>has_log</title>
            <url>https://images.velog.io/images/im_hass_/profile/a0854bc8-e678-42fe-9896-e9122382b66a/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. has_log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/im_hass_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Javascript | 클로저(Closure)]]></title>
            <link>https://velog.io/@im_hass_/Javascript-%ED%81%B4%EB%A1%9C%EC%A0%80Closure</link>
            <guid>https://velog.io/@im_hass_/Javascript-%ED%81%B4%EB%A1%9C%EC%A0%80Closure</guid>
            <pubDate>Mon, 22 Aug 2022 10:20:20 GMT</pubDate>
            <description><![CDATA[<h3 id="📌-자바스크립트의-스코프">📌 <strong>자바스크립트의 스코프</strong></h3>
<blockquote>
<p><strong>자바스크립트는 <a href="https://velog.io/@im_hass_/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84#-%EB%8F%99%EC%A0%81-%EC%8A%A4%EC%BD%94%ED%94%84dynamic-scope-%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84lexical-scope-%EB%98%90%EB%8A%94-%EC%A0%95%EC%A0%81-%EC%8A%A4%EC%BD%94%ED%94%84static-scope">렉시컬 스코프</a>를 따른다.</strong></p>
</blockquote>
<ul>
<li><p>함수를 어디서 호출하는지는 함수의 상위 스코프 결정에 어떠한 영향도 주지 못한다. 즉, 함수의 상위 스코프는 함수를 정의한 위치에 의해 정적으로 결정되고 변하지 않는다.</p>
</li>
<li><p>예제 24-01</p>
<p>  <code>outerFunc</code> 함수 내부에서 중첩 함수 <code>innerFunc</code>가 정의되고 호출되었다. 이때 중첩 함수 <code>innerFunc</code>의 상위 스코프는 외부 함수 <code>outerFunc</code>의 스코프다. 따라서 중첩 함수 <code>innerFunc</code> 내부에서 자신을 포함하고 있는 외부 함수 <code>outerFunc</code>의 <code>x</code>에 접근할 수 있다.</p>
<pre><code class="language-jsx">const x = 1;

function outerFunc() {
  const x = 10;

  function innerFunc() {
    console.log(x);
  }

  innerFunc();
}

outerFunc();

// OUTPUT :
//10</code></pre>
</li>
<li><p>추가 예제
<code>innerFunc</code> 함수가 <code>outerFunc</code> 내부에서 “정의”된 중첩 함수가 아니라면 <code>innerFunc</code> 함수를 <code>outerFunc</code> 함수의 내부에서 호출한다 하더라도 <code>outerFunc</code> 함수의 <code>x</code>에 접근할 수 없다.</p>
<pre><code class="language-jsx">const x = 1;

function outerFunc() {
  const x = 10;

  innerFunc();
}

function innerFunc() {
  console.log(x); // ??
}

outerFunc();

// OUTPUT :
//1</code></pre>
</li>
</ul>
<h3 id="📌-스코프의-실체">📌 <strong>스코프의 실체</strong></h3>
<blockquote>
<p>스코프의 실체는 실행 컨텍스트의 <strong>렉시컬 환경이다.</strong></p>
</blockquote>
<ul>
<li>이 <a href="https://velog.io/@im_hass_/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84#-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BDlexical-environment">렉시컬 환경</a>은 <strong>자신의 “외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Reference)”를 통해 상위 렉시컬 환경과 연결된다.</strong> ⇒ 이것이 스코프 체인이다.
즉, <strong>“함수의 상위 스코프를 결정한다”는 것은 “렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다”는 것</strong>과 같다.</li>
<li><em>⇒ 자신의 렉시컬 환경에서 외부 렉시컬 환경에 대한 참조 부분에 상위 렉시컬 환경의 참조 값이 들어가는 것이 함수의 상위 스코프를 결정하는 과정이다.*</em></li>
</ul>
<h3 id="📌-렉시컬-환경">📌 <strong>렉시컬 환경</strong></h3>
<blockquote>
<p><strong>식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 자료구조다.</strong></p>
</blockquote>
<ul>
<li><p><a href="https://velog.io/@im_hass_/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84#-%EB%A0%89%EC%8B%9C%EC%BB%AC-%ED%99%98%EA%B2%BDlexical-environment">참고</a></p>
</li>
<li><p>실행 컨텍스트 스택이 코드의 실행 순서를 관리한다면, 렉시컬 환경은 스코프와 식별자를 관리한다.</p>
</li>
<li><p>두 개의 컴포넌트로 구성된다.</p>
<ol>
<li><p><strong>환경 레코드(Environment Record)</strong>
스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소.
 환경 레코드는 소스 코드의 타입에 따라 관리하는 내용에 차이가 있다.</p>
</li>
<li><p><strong>외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Reference)</strong>
상위 스코프를 가리킨다. 상위 스코프란 외부 렉시컬 환경, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 <strong>상위 코드의 렉시컬 환경을 말한다.</strong> 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인을 구현한다.</p>
</li>
</ol>
</li>
</ul>
<h3 id="📌-함수-정의-평가">📌 <strong>함수 정의 평가</strong></h3>
<blockquote>
<p>함수 정의란 <strong>함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행 문들 그리고 반환값을 지정하는 것</strong></p>
</blockquote>
<ul>
<li>정의된 함수는 자바스크립트 엔진에 의해 평가되어 함수 객체가 된다.</li>
</ul>
<h3 id="📌-함수-객체의-내부-슬롯-environment">📌 <strong>함수 객체의 내부 슬롯 <code>[[Environment]]</code></strong></h3>
<blockquote>
<p>함수가 정의된 환경(위치)과 호출되는 환경(위치)은 다를 수 있다. 따라서 <strong>렉시컬 스코프가 가능하려면 함수는 자신이 정의된 환경을 기억해야 한다.</strong> 따라서 함수는 (함수 정의가 평가된 시점에) 자신의 내부 슬롯 <code>[[Environment]]</code>에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.</p>
</blockquote>
<ul>
<li><p>이때 자신의 내부 슬롯 <code>[[Environment]]</code>에 저장된 상위 스코프의 참조는 현재 실행 중인 실행 컨텍스트의 렉시컬 환경을 가리킨다.</p>
</li>
<li><p>함수 정의가 평가된 시점은 함수가 정의된 환경, 즉 상위 함수가 평가 또는 실행되고 있는 시점이며, 이때 현재 실행 중인 실행 컨텍스트는 상위 함수(또는 전역 코드)의 실행 컨텍스트이기 때문이다.&quot;</p>
</li>
<li><p><strong>전역에서 정의된 함수 선언문은</strong> 전역 코드가 평가되는 시점에 평가되어 함수 객체를 생성한다. 이때 생성된 <strong>함수 객체의 내부 슬롯 <code>[[Environment]]</code>에는 전역 렉시컬 환경</strong>(전역 코드의 평가 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경)<strong>의 참조가 저장된다.</strong></p>
</li>
<li><p><strong>함수 내부에서 정의된 함수 표현식은</strong> 외부 함수 코드가 실행되는 시점에 평가되어 함수 객체를 생성한다. 이때 <strong>생성된 함수 객체의 내부 슬롯 <code>[[Environment]]</code>에는 외부 함수 렉시컬 환경</strong>(외부 함수 코드 실행 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경)<strong>의 참조가 저장된다.</strong></p>
</li>
<li><p>예제 24-04</p>
<pre><code class="language-jsx">const x = 1;

function foo() {
  const x = 10;

  // 상위 스코프는 함수 정의 환경(위치)에 따라 결정된다.
  // 함수 호출 위치와 상위 스코프는 아무런 관계가 없다.
  bar();
}

// 함수 bar는 자신의 상위 스코프, 즉 전역 렉시컬 환경을 [[Environment]]에 저장하여 기억한다.
function bar() {
  console.log(x);
}

foo();
bar();

// OUTPUT :
//1
//1</code></pre>
</li>
</ul>
<h3 id="📌-함수-코드-평가-과정">📌 <strong>함수 코드 평가 과정</strong></h3>
<blockquote>
<ol>
<li>함수 실행 컨텍스트 생성</li>
<li>함수 렉시컬 환경 생성<ol>
<li>함수 환경 레코드 생성</li>
<li>this 바인딩</li>
<li>외부 렉시컬 환경에 대한 참조 결정</li>
</ol>
</li>
</ol>
</blockquote>
<ul>
<li>그림 24-1 : 예제 24-04에서 foo 함수 내부에서 bar 함수가 호출되어 실행 중인 시점의 실행 컨텍스트<ol>
<li>foo 함수와 bar 함수 모두 전역에서 함수 선언문으로 정의되었다. 따라서 foo 함수와 bar 함수 모두 전역 코드가 평가되는 시점에 평가되어 함수 객체를 생성하고 전역 객체 <code>window</code>의 메서드가 된다.
 이때 생성된 함수 객체의 내부 슬롯 <code>[[Environment]]</code>에는 전역 렉시컬 환경의 참조가 저장된다(아래 그림에서 ①)<ol start="2">
<li>함수가 호출되면 함수 내부로 코드의 제어권이 이동한다. 그리고 함수 코드를 평가하기 시작한다.
이때 함수 렉시컬 환경의 구성요소인 외부 렉시컬 환경에 대한 참조(2-c)에는 함수 객체의 내부 슬롯 <code>[[Environment]]</code>에 저장된 렉시컬 환경의 참조가 할당된다(아래 그림에서 ②, ③)
![함수 객체의 내부 슬롯 [[Environment]]에는 상위 스코프가 저장된다](<a href="https://velog.velcdn.com/images/im_hass_/post/f85a9c3f-454d-4013-9be2-a8f59fd78631/image.png">https://velog.velcdn.com/images/im_hass_/post/f85a9c3f-454d-4013-9be2-a8f59fd78631/image.png</a>)</li>
</ol>
</li>
</ol>
</li>
</ul>
<h3 id="📌-클로저closure">📌 <strong>클로저(Closure)</strong></h3>
<blockquote>
<p><strong>상위 스코프의 식별자를 참조하고, 상위 스코프의 생명 주기보다 긴 생명 주기를 갖는 중첩 함수</strong></p>
</blockquote>
<ul>
<li><p>외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라고 부른다.
  ⇒ 이미 생명 주기가 종료된 외부 함수의 변수를 참조하는 중첩 함수.</p>
</li>
<li><p>클로저는 자바스크립트 고유의 개념이 아니다.
  함수를 일급 객체로 취급하는 함수형 프로그래밍 언어(하스켈, 리스프, 스칼라 등)에서 사용되는 중요한 특성이다.</p>
</li>
<li><p>클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다(MDN 정의).
  “그 함수가 선언된 렉시컬 환경”이란 함수가 정의된 위치의 스코프(상위 스코프)를 의미하는 실행 컨텍스트의 렉시컬 환경을 말한다.</p>
</li>
<li><p>예제 24-05</p>
<ul>
<li><code>outer</code> 함수를 호출(③)하면 <code>outer</code> 함수는 중첩 함수 <code>inner</code>를 반환하고 생명 주기를 마감한다. 즉, <code>outer</code> 함수의 실행이 종료되면 <code>outer</code> 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거된다.</li>
<li>이때 <code>outer</code> 함수의 지역 변수 <code>x</code>와 변수 10을 저장하고 있던 <code>outer</code> 함수의 실행 컨텍스트가 제거되었으므로 <code>outer</code> 함수의 지역 변수 <code>x</code> 또한 생명 주기를 마감한다. 따라서 <code>outer</code> 함수의 지역 변수 <code>x</code>에 접근할 수 있는 방법은 달리 없어 보인다.</li>
<li>그러나 아래 코드의 실행 결과(④)는 <code>outer</code> 함수의 지역 변수 <code>x</code>의 값인 10이다.</li>
<li>이처럼 외부 함수보다 중첩 함수가 더 오래 유지되는 경우, 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 클로저라고 부른다.<pre><code class="language-jsx">const x = 1;
</code></pre>
</li>
</ul>
<p>// ①
function outer() {
  const x = 10;
  const inner = function () {</p>
<pre><code>console.log(x); // ②</code></pre><p>  };
  return inner;
}</p>
<p>// outer 함수를 호출하면 중첩 함수 inner를 반환한다.
// 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다.
const innerFunc = outer(); // ③
innerFunc(); // ④</p>
<p>// OUTPUT : 
//10</p>
<pre><code></code></pre></li>
</ul>
<h3 id="📌-클로저의-스코프-결정">📌 클로저의 스코프 결정</h3>
<ul>
<li><p>그림 24-2 : 전역 함수 객체의 상위 스코프 결정</p>
<ul>
<li>자바스크립트의 모든 함수는 자신의 상위 스코프를 기억한다고 했다.</li>
<li>모든 함수가 기억하는 상위 스코프는 함수를 어디서 호출하든 상관없이 유지된다.</li>
<li>따라서 함수를 어디서 호출하든 상관없이 함수는 언제나 자신이 기억하는 상위 스코프의 식별자를 참조할 수 있으며 식별자에 바인딩된 값을 변경할 수도 있다.
위 예제(예제 24-05)에서 <code>inner</code> 함수는 자신이 평가될 때 상위 스코프를 <code>[[Environment]]</code> 내부 슬롯에 저장한다. 이때 저장된 상위 스코프는 함수가 존재하는 한 유지된다.</li>
<li>위 예제(예제 24-05)에서 <code>outer</code> 함수가 평가되어 함수 객체를 생성할 때(①) 현재 실행 중인 실행 컨텍스트의 렉시컬 환경(전역 렉시컬 환경)을 <code>outer</code> 함수 객체의 <code>[[Environment]]</code> 내부 슬롯에 <strong>(상위 스코프로서)</strong> 저장한다.
<img src="https://velog.velcdn.com/images/im_hass_/post/b2b8621d-2acb-4fdc-8050-8f22a5fd49cd/image.png" alt="전역 함수 객체의 상위 스코프 결정"></li>
</ul>
</li>
<li><p>그림 24-3 : 중첩 함수의 상위 스코프 결정</p>
<ul>
<li><p><code>outer</code> 함수를 호출하면 <code>outer</code> 함수의 렉시컬 환경이 생성되고 앞서 <code>outer</code> 함수 객체의  <code>[[Environment]]</code> <strong>내부 슬롯에 저장된 전역 렉시컬 환경을</strong> <code>outer</code> 함수 렉시컬 환경의 <strong>“외부 렉시컬 환경에 대한 참조”에 할당한다.</strong>
<img src="https://velog.velcdn.com/images/im_hass_/post/9faaa10a-90f2-4e95-83f2-cf2fa0a83147/image.png" alt="중첩 함수의 상위 스코프 결정"></p>
</li>
<li><p>그리고 중첩 함수 <code>inner</code>가 평가된다(②, <code>inner</code> 함수는 함수 표현식으로 정의했기 때문에 런타임에 평가된다). 이때 중첩 함수 <code>inner</code>는 자신의 <code>[[Environment]]</code> 내부 슬롯에 현재 실행 중인 실행 컨텍스트의 렉시컬 환경(<code>outer</code> 함수의 렉시컬 환경)을 상위 스코프로서 저장한다.
<img src="https://velog.velcdn.com/images/im_hass_/post/088e9446-a19b-49b8-9752-449efad63f9c/image.png" alt="중첩 함수의 상위 스코프 결정"></p>
</li>
<li><p><code>outer</code> 함수의 실행이 종료하면 <code>inner</code> 함수를 반환하면서 <code>outer</code> 함수의 생명 주기가 종료된다(③). 즉, <code>outer</code> 함수의 실행 컨텍스트가 실행 컨텍스트 스택에서 삭제된다.
이때 <code>outer</code> 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만 <strong><code>outer</code> 함수의 렉시컬 환경까지 소멸하는 것은 아니다.</strong></p>
</li>
<li><p><code>outer</code> 함수의 렉시컬 환경은 <code>inner</code> 함수의 <code>[[Environment]]</code> 내부 슬롯에 의해 참조되고 있고 <code>inner</code> 함수는 전역 변수 <code>innerFunc</code>에 의해 참조되고 있으므로 가비지 컬렉션의 대상이 되지 않기 때문이다. 가비지 컬렉터는 누군가가 참조하고 있는 메모리 공간을 함부로 해제하지 않는다.
<img src="https://velog.velcdn.com/images/im_hass_/post/384ceb77-a62c-4334-8c54-a370777f9503/image.png" alt="outer 함수의 실행 컨텍스트가 제거되어도 outer 함수의 렉시컬 환경은 유지된다"></p>
</li>
<li><p><code>outer</code> 함수가 반환한 <code>inner</code> 함수를 호출(④)하면 <code>**inner</code> 함수의 실행 컨텍스트가 생성되고 실행 컨텍스트 스택에 푸시된다.** 그리고 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에는 <code>**inner</code> 함수 객체의 <code>[[Environment]]</code> 내부 슬롯에 저장되어 있는 참조값이 할당된다.**
<img src="https://velog.velcdn.com/images/im_hass_/post/2f1323c7-50f0-44bf-aaa5-df405b972540/image.png" alt="외부 함수가 소멸해도 반환된 중첩 함수는 외부 함수의 변수를 참조할 수 있다"></p>
</li>
</ul>
</li>
</ul>
<h3 id="📌-자바스크립트의-클로저">📌 자바스크립트의 클로저</h3>
<blockquote>
<p>자바스크립트의 모든 함수는 상위 스코프를 기억하므로 이론적으로 모든 함수는 클로저다. 하지만 일반적으로 모든 함수를 클로저라고 하지는 않는다.</p>
</blockquote>
<ul>
<li><p>클로저가 되려면 아래 조건이 필요하다.</p>
<ul>
<li>중첩 함수가 상위 스코프의 식별자를 참조해야 한다.
상위 스코프의 식별자를 참조하지 않는다면 대부분의 모던 브라우저는 최적화를 통해 상위 스코프를 기억하지 않는다. 참조하지도 않는 식별자를 기억하는 것은 메모리 낭비이기 때문이다.</li>
<li>외부 함수의 외부로 중첩 함수가 반환 되어야 한다. 즉, 외부 함수보다 중첩 함수의 생명 주기가 길어야 한다.
외부 함수보다 일찍 소멸될 경우, 생명 주기가 종료된 외부 함수의 식별자를 참조할 수 있다는 클로저의 본질에 부합하지 않기 때문이다.</li>
</ul>
</li>
<li><p>예제 24-06 : 클로저가 아닌 것</p>
<pre><code class="language-jsx">function foo() {
  const x = 1;
  const y = 2;

  function bar() { // 상위 스코프의 식별자를 참조하지 않기 때문에 일반적으로 클로저라고 하지 않는다.
    const z = 3;

    console.log(z);
  }

  return bar;
}

const bar = foo();
bar();</code></pre>
</li>
<li><p>예제 24-07 : 클로저가 아닌 것</p>
<pre><code class="language-jsx">function foo() {
  const x = 1;

  // 클로저였지만 곧바로 소멸한다.
  function bar() {
    console.log(x); // 상위 스코프의 식별자를 참조한다.
  }

  bar();
}

foo();</code></pre>
</li>
<li><p>예제 24-08 : 디버깅 모드 : 클로저</p>
<pre><code class="language-jsx">function foo() {
  const x = 1;
  const y = 2;

    // 클로저
  function bar() {
    console.log(x);
  }

  return bar;
}

const bar = foo();
bar();</code></pre>
</li>
</ul>
<h3 id="📌-자유-변수free-variable">📌 <strong>자유 변수(Free Variable)</strong></h3>
<blockquote>
<p> <strong>클로저에 의해 참조되는 상위 스코프의 변수.</strong></p>
</blockquote>
<ul>
<li>만약 클로저인 중첩 함수가 상위 스코프의 식별자 <code>x</code>, <code>y</code> 중 <code>x</code>만 참조하고 있을 경우, 대부분의 모던 브라우저는 최적화를 통해 클로저가 참조하고 있는 식별자만을 기억한다.</li>
<li>클로저란 “함수가 자유 변수에 대해 닫혀있다”라는 의미다. 의역하자면 “자유 변수에 묶여있는 함수”라고 할 수 있다.</li>
</ul>
<h3 id="📌-클로저의-활용">📌 <strong>클로저의 활용</strong></h3>
<blockquote>
<p><strong>상태가 의도치 않게 변경되지 않도록 상태를 안전하게 은닉(Information Hiding)하고 특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용한다.</strong></p>
</blockquote>
<ul>
<li><p>예제 24-09 : 함수가 호출될 때마다 호출된 횟수를 누적하여 출력하는 카운터</p>
<pre><code class="language-jsx">let num = 0; // 카운트 상태 변수

const increase = function () { // 카운트 상태 변경 함수
  // 카운트 상태를 1 증가시킨다.
  return ++num;
};

console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3</code></pre>
<ul>
<li>호출된 횟수(<code>num</code> 변수)가 안전하게 변경하고 유지해야 할 상태다.<ul>
<li>아래 전제 조건이 지켜지지 않을 경우 오류를 발생 시킬 가능성을 내포하고 있다.</li>
<li>카운트의 상태(<code>num</code> 변수의 값)는 <code>increase</code> 함수가 호출되기 전까지 변경되지 않고 유지되어야 한다.</li>
<li>이를 위해 카운트 상태(<code>num</code> 변수의 값)는 <code>increase</code> 함수만이 변경할 수 있어야 한다.</li>
</ul>
</li>
</ul>
</li>
<li><p>예제 24-11 : 클로저를 사용하여 이전 상태를 유지하도록 변경</p>
<pre><code class="language-jsx">const increase = (function () { // 카운트 상태 변경 함수
  let num = 0; // 카운트 상태 변수

  // 클로저
  return function () {
    // 카운트 상태를 1만큼 증가시킨다.
    return ++num;
  }
}());

console.log(increase()); // 1
console.log(increase()); // 2
console.log(increase()); // 3</code></pre>
<ul>
<li>위 코드가 실행되면 즉시 실행 함수가 호출되고, 즉시 실행 함수가 반환한 함수가 <code>increase</code> 변수에 할당된다.</li>
<li><strong><code>increase</code> 변수에 할당된 함수는</strong> 자신이 정의된 위치에 의해 결정된 상위 스코프인 <strong>즉시 실행 함수의 렉시컬 환경을 기억하는 클로저다.</strong></li>
<li>즉시 실행 함수는 호출된 이후 소멸되지만, 즉시 실행 함수가 반환한 클로저는 <code>increase</code> 변수에 할당되어 호출된다.</li>
<li>클로저는 즉시 실행 함수의 렉시컬 환경을 기억하고 있다. 따라서 카운트 상태를 유지하기 위한 자유 변수 <code>num</code>을 언제 어디서 호출하든지 참조하고 변경할 수 있다.
즉시 실행 함수는 한 번만 실행되므로 <code>increase</code>가 호출될 때마다 <code>num</code> 변수가 재차 초기화될 일은 없을 것이다. 또한 <code>num</code> 변수는 은닉된 <code>private</code> 변수이므로 의도 되지 않은 변경을 걱정할 필요가 없다.</li>
</ul>
</li>
</ul>
<h3 id="📌-캡슐화와-정보-은닉">📌 캡슐화와 정보 은닉</h3>
<blockquote>
</blockquote>
<h3 id="📌-클로저를-사용할-때-자주-발생하는-실수">📌 클로저를 사용할 때 자주 발생하는 실수</h3>
<ul>
<li><p>예제 24-20 : var 키워드 사용</p>
<ul>
<li><p>첫 번째 for 문(①)에서 <code>funcs[0]</code>, <code>funcs[1]</code>, <code>funcs[2]</code> 내에 각각 “<code>i</code> 값을 반환하는 <strong>함수”가 저장</strong> 됩니다. 그리고 두 번째 for 문(②)에서 <code>funcs[0]()</code>, <code>funcs[1]()</code>, <code>funcs[2]()</code>를 통해 내부에 저장된 함수를 실행 시키고 있습니다.</p>
</li>
<li><p><code>funcs</code> 배열 내부에 저장된 함수의 상위 스코프는 전역이고, <code>**var</code>로 선언된 <code>i</code>는 전역 변수<strong>입니다. 따라서 <code>return i;</code>에서 <code>i</code>는 **전역 변수 <code>i</code>의 값을 참조</strong>하게 됩니다. 여기서 <strong>두 번째 for 문(②)이 실행되는 시점은 첫 번째 for 문(①)이 이미 끝난 시점</strong>입니다. 첫 번째 for 문(①)이 끝난 시점의 <code>i</code> 값은 3이므로, 똑같은 3을 3번 출력하게 됩니다.</p>
<table>
<thead>
<tr>
<th>for 문 시작</th>
<th>i=0</th>
</tr>
</thead>
<tbody><tr>
<td>1회</td>
<td>0</td>
</tr>
<tr>
<td>2회</td>
<td>1</td>
</tr>
<tr>
<td>3회</td>
<td>2</td>
</tr>
<tr>
<td>for 문 종료</td>
<td>3</td>
</tr>
</tbody></table>
</li>
</ul>
<pre><code class="language-jsx">var funcs = [];

for (var i = 0; i &lt; 3; i++) {
  funcs[i] = function () { return i; }; // ①
}

for (var j = 0; j &lt; funcs.length; j++) {
  console.log(funcs[j]()); // ②
}</code></pre>
</li>
<li><p>예제 24-21 : 클로저를 이용해서 24-20 해결</p>
<pre><code class="language-jsx">var funcs = [];

for (var i = 0; i &lt; 3; i++) {
    funcs[i] = (function (id) { // ①
        return function () {
            return id;
        }
    }(i));
}

for (var j = 0; j &lt; funcs.length; j++) {
    console.log(funcs[j]()); // ②
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | 스코프(Scope)]]></title>
            <link>https://velog.io/@im_hass_/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@im_hass_/Javascript-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Wed, 10 Aug 2022 14:52:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>모던 자바스크립트 Deep Dive 서적을 참고하여 쓰였습니다.</strong></p>
</blockquote>
<h3 id="📌-스코프scope">📌 <strong>스코프(Scope)</strong></h3>
<blockquote>
<p> <strong>식별자가 유효한 범위</strong>
(<strong>자바스크립트 엔진이) 식별자를 검색할 때 사용하는 규칙</strong>
<strong>네임 스페이스</strong></p>
</blockquote>
<ul>
<li>모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다.<ul>
<li><strong>유효하다 = 참조할 수 있다</strong></li>
</ul>
</li>
<li>자바스크립트 엔진은 이름이 같은 두 개의 변수 중에서 어떤 변수를 참조해야 할 것인지를 결정해야 한다.</li>
<li>스코프(유효 범위)를 통해 식별자인 변수 이름의 충돌을 방지하여 같은 이름의 변수를 사용할 수 있게 해준다.</li>
</ul>
<h3 id="📌-키워드">📌 <strong>키워드</strong></h3>
<blockquote>
<p><strong>사전에 정의된 에약어.</strong></p>
</blockquote>
<ul>
<li>특별한 의미를 지니고 있다.</li>
<li>식별자로 사용할 수 없다.</li>
<li><code>var</code>, <code>let</code>, <code>const</code>, <code>function</code> 등</li>
</ul>
<blockquote>
<h3 id="📌-식별자">📌 <strong>식별자</strong></h3>
</blockquote>
<ul>
<li><strong>변수 이름, 함수 이름, 클래스 이름 등</strong></li>
<li>식별자는 어떤 값을 구별할 수 있어야 하므로 유일(Unique)해야 한다.</li>
<li>따라서 식별자인 변수 이름은 중복될 수 없다.</li>
<li>즉, 하나의 값은 유일한 식별자에 연결(Name Binding)되어야 한다.</li>
<li><code>let **text**</code>, <code>function **onClick**</code> 등</li>
</ul>
<blockquote>
<h3 id="📌-식별자-결정">📌 <strong>식별자 결정</strong></h3>
</blockquote>
<ul>
<li><p><strong>자바스크립트 엔진이 이름이 같은 식별자 중 어떤 것을 참조할 것인지 결정하는 것.</strong></p>
</li>
<li><p>스코프를 통해 결정된다.</p>
</li>
<li><p>예제 13-03</p>
<pre><code class="language-jsx">  var x = &#39;global&#39;;

  function foo() {
      var x = &#39;local&#39;;
      console.log(x); // 1
  }

  foo();

  console.log(x); // 2</code></pre>
<ul>
<li>식별자 이름은 동일하지만, 스코프가 다른 별개의 변수다.</li>
<li>만약 스코프라는 개념이 없다면 같은 이름을 갖는 변수는 충돌을 일으키므로 프로그램 전체에서 하나밖에 사용할 수 없다.</li>
</ul>
</li>
</ul>
<h3 id="📌-코드의-문맥context">📌 <strong>코드의 문맥(Context)</strong></h3>
<blockquote>
<p><strong>자바스크립트 엔진은 코드를 실행할 때 코드의 문맥을 고려한다.</strong></p>
</blockquote>
<ul>
<li>코드의 문맥은 렉시컬 환경으로 이루어진다.</li>
<li>코드가 어디서 실행되며 주변에 어떤 코드가 있는지에 따라 동일한 코드도 다른 결과를 만들어 낸다.</li>
</ul>
<h3 id="📌-렉시컬-환경lexical-environment">📌 <strong>렉시컬 환경(Lexical Environment)</strong></h3>
<blockquote>
<p><code>block</code>, <code>function</code>, <code>script</code>를 실행하기 앞서 생성되는 특별한 객체로, 실행할 스코프 범위 안에 있는 <strong>변수와 함수를 프로퍼티로 저장하는 객체.</strong></p>
</blockquote>
<ul>
<li>코드가 어디서 실행되며 주변에 어떤 코드가 있는지를 의미한다.</li>
<li>전역 렉시컬 환경은 코드가 로드되면 곧바로 생성되고, 함수의 렉시컬 환경은 함수가 호출되면 곧바로 생성된다.</li>
<li>(실행 컨텍스트의) 렉시컬 환경을 단반향으로 연결(Chaining)한 것이 <strong><a href="https://www.notion.so/13-Scope-fe2015d5d52b4648857c6b6d4a66477a">스코프 체인</a></strong>이다.</li>
<li>이를 구현한 것이 “실행 컨텍스트”이며, 모든 코드는 실행 컨텍스트에서 평가되고 실행된다.</li>
</ul>
<h3 id="📌-var-키워드">📌 <strong><code>var</code> 키워드</strong></h3>
<blockquote>
<p><code>var</code> 키워드로 선언된 변수는 같은 스코프 내에서 중복 선언이 허용된다.</p>
</blockquote>
<ul>
<li><p>의도치 않게 변수값이 재할당 되어 변경되는 부작용을 발생 시킨다.</p>
</li>
<li><p>예제 13-04</p>
<pre><code class="language-jsx">  function foo() {
      var x = 1;
      var x = 2; // 자바스크립트 엔진에 의해 var 키워드가 없는 것처럼 동작한다.
      console.log(x); // 2
  }
  foo();</code></pre>
</li>
</ul>
<h3 id="📌-let-const-키워드">📌 <strong><code>let</code>, <code>const</code> 키워드</strong></h3>
<blockquote>
<p>같은 스코프 내에서 중복 선언을 허용하지 않는다.</p>
</blockquote>
<ul>
<li><p>예제 13-05</p>
<pre><code class="language-jsx">  function bar() {
      let x = 1;
      let x = 2; // SyntaxError: Identifier &#39;x&#39; has already been declared
  }
  bar();</code></pre>
</li>
</ul>
<h3 id="📌-스코프의-종류">📌 <strong>스코프의 종류</strong></h3>
<blockquote>
<ul>
<li><strong>전역 스코프(Global)</strong><ul>
<li>코드의 가장 바깥 영역</li>
<li>어디서든 참조할 수 있다.</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li><p><strong>지역 스코프(Local)</strong></p>
<ul>
<li>함수 몸체 내부</li>
<li>자신의 지역 스코프와 하위 지역 스코프에서 참조할 수 있다.</li>
</ul>
</li>
<li><p>자신이 선언된 위치에 의해 자신의 스코프가 결정된다.
즉, 전역에서 선언된 변수는 전역 스코프를 갖는 전역 변수이고, 지역에서 선언된 변수는 지역 스코프를 갖는 지역 변수다.</p>
</li>
<li><p>그림 13-2</p>
<ul>
<li><p>전역 변수 <code>x</code>와 <code>inner</code> 함수 내부에서 선언된 <code>x</code> 변수의 이름이 같다.
이때 <code>inner</code> 함수 내부에서 <code>x</code> 변수를 참조하면 <code>inner</code> 함수 내부에 선언된 <code>x</code>를 참조한다.
⇒ 자바스크립트 엔진이 <strong>스코프 체인</strong>을 통해 참조할 변수를 검색했기 때문이다.
<img src="https://velog.velcdn.com/images/im_hass_/post/94ac969b-7ce4-4462-9c17-ce2576663207/image.png" alt="지역 스코프, 전역 스코프 코드 예제"></p>
</li>
<li><p>코드</p>
<pre><code class="language-javascript">// 전역 스코프
var x = &quot;global x&quot;;
var y = &quot;global y&quot;;

function outer() {
// 지역 스코프
var z = &quot;outer&#39;s local z&quot;;

console.log(&quot;1 : &quot; + x);
console.log(&quot;2 : &quot; + y);
console.log(&quot;3 : &quot; + z);

function inner() {
  // 지역 스코프
  var x = &quot;inner&#39;s local x&quot;;

  console.log(&quot;4 : &quot; + x);
  console.log(&quot;5 : &quot; + y);
  console.log(&quot;6 : &quot; + z);
}

inner();
}

outer();

console.log(&quot;7 : &quot; + x);
// console.log(z); // ReferenceError: z is not defined

// 1 : global x
// 2 : global y
// 3 : outer&#39;s local z
// 4 : inner&#39;s local x
// 5 : global y
// 6 : outer&#39;s local z
// 7 : global x</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="📌-함수의-중첩">📌 <strong>함수의 중첩</strong></h3>
<blockquote>
<p>함수 몸체 내부에 함수가 정의된 것</p>
</blockquote>
<h3 id="📌-중첩-함수nested-function">📌 <strong>중첩 함수(Nested Function)</strong></h3>
<blockquote>
<p>함수 몸체 내부에 정의한 함수</p>
</blockquote>
<h3 id="📌-외부-함수outer-function">📌 <strong>외부 함수(Outer Function)</strong></h3>
<blockquote>
<p>중첩 함수를 포함하는 함수</p>
</blockquote>
<h3 id="📌-스코프-체인scope-chain">📌 <strong>스코프 체인(Scope Chain)</strong></h3>
<blockquote>
<p><strong>스코프가 계층적으로 연결된 것.</strong></p>
</blockquote>
<ul>
<li><p>함수는 중첩될 수 있으므로 함수의 지역 스코프도 중첩될 수 있다.</p>
<p>  즉, <strong>스코프가</strong> 함수의 중첩에 의해 <strong>계층적 구조를 갖는다</strong>는 것을 의미한다.</p>
<p>  <strong>모든 스코프는 하나의 계층적 구조로 연결되며, 모든 지역 스코프의 최상위 스코프는 전역 스코프다.</strong></p>
</li>
<li><p>중첩 함수의 지역 스코프는 중첩 함수를 포함하는 외부 함수의 지역 스코프와 계층적 구조를 갖는다.</p>
<p>  이때 외부 함수의 지역 스코프를 중첩 함수의 상위 스코프라 한다.</p>
</li>
</ul>
<h3 id="📌-스코프-체인의-동작">📌 <strong>스코프 체인의 동작</strong></h3>
<blockquote>
</blockquote>
<ol>
<li>해당 변수를 참조하는 코드의 스코프에서 해당 변수가 선언되었는지 검색한다. </li>
<li>해당 변수의 선언이 존재한다면 검색된 변수를 참조하고 검색을 종료한다.</li>
<li>해당 변수의 선언이 존재하지 않는다면 상위 스코프로 이동한다.</li>
<li>변수가 참조되거나 최상위 스코프(전역 스코프)가 될 때까지, 1~3번을 반복한다.</li>
</ol>
<ul>
<li>그림 13-3<ul>
<li>앞의 예제(그림 13-2)에서 지역은 <code>outer</code> 함수의 지역, <code>inner</code> 함수의 지역 2가지가 있다.
<code>inner</code> 함수는 <code>outer</code> 함수의 중첩 함수다.<br>이때 <code>outer</code> 함수가 만든 지역 스코프는 <code>inner</code> 함수가 만든 지역 스코프의 상위 스코프다.
그리고 <code>outer</code> 함수가 만든 지역 스코프의 상위 스코프는 전역 스코프다.</li>
</ul>
</li>
</ul>
<h3 id="📌-앞의-예제그림-13-2에서-스코프-체인의-동작">📌 앞의 예제(그림 13-2)에서 스코프 체인의 동작</h3>
<blockquote>
<ul>
<li><strong><code>console.log(&quot;4 : &quot; + x)</code></strong></li>
</ul>
</blockquote>
<ol>
<li><code>inner</code> 함수의 지역 스코프(<code>x</code> 변수를 참조하는 코드의 스코프)에서 <code>x</code> 변수가 선언되었는지 검색한다.</li>
<li><code>inner</code> 함수 내에는 선언된 <code>x</code> 변수가 존재한다.</li>
<li>검색된 변수를 참조하고 검색을 종료한다.</li>
</ol>
<blockquote>
<ul>
<li><strong><code>console.log(&quot;5 : &quot; + y)</code></strong></li>
</ul>
</blockquote>
<ol>
<li><code>inner</code> 함수의 지역 스코프(<code>y</code> 변수를 참조하는 코드의 스코프)에서 <code>y</code> 변수가 선언되었는지 검색한다.</li>
<li><code>inner</code> 함수 내에는 선언이 존재하지 않으므로 상위 스코프인 <code>outer</code> 함수의 지역 스코프로 이동한다.</li>
<li><code>outer</code> 함수의 지역 스코프에서 <code>y</code> 변수가 선언되었는지 검색한다.</li>
<li><code>outer</code> 함수 내에서도 선언이 존재하지 않으므로 또 다시 상위 스코프인 전역 스코프로 이동한다.</li>
<li>전역 스코프에는 선언된 <code>y</code> 변수가 존재한다.</li>
<li>검색된 변수를 참조하고 검색을 종료한다.</li>
</ol>
<blockquote>
<ul>
<li><strong><code>console.log(&quot;6 : &quot; + z)</code></strong></li>
</ul>
</blockquote>
<ol>
<li><code>inner</code> 함수의 지역 스코프(<code>z</code> 변수를 참조하는 코드의 스코프)에서 <code>z</code> 변수가 선언되었는지 검색한다.</li>
<li><code>inner</code> 함수 내에는 선언이 존재하지 않으므로 상위 스코프인 <code>outer</code> 함수의 지역 스코프로 이동한다.</li>
<li><code>outer</code> 함수 내에는 선언된 <code>z</code> 변수가 존재한다.</li>
<li>검색된 변수를 참조하고 검색을 종료한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/im_hass_/post/51040100-b7d1-4eca-9725-31c2725feeb9/image.png" alt="스코프 체인"></p>
<h3 id="📌-변수-검색identifier-resolution">📌 <strong>변수 검색(Identifier Resolution)</strong></h3>
<blockquote>
<p><strong>자바스크립트 엔진은 변수를 참조할 때 스코프 체인을 이용한다.</strong>
    스코프 체인을 따라 변수를 참조하는 코드의 스코프에서 시작해서 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
    <strong>이를 통해 상위 스코프에서 선언한 변수를 하위 스코프에서도 참조할 수 있다.</strong>
    절대 하위 스코프로 내려가면서 식별자를 검색하는 일은 없다.
    이는 <strong>상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조</strong>할 수 있지만, <strong>하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없다</strong>는 것을 의미한다.</p>
</blockquote>
<ul>
<li>자바스크립트 엔진은 코드(전역 코드, 함수 코드)를 실행하기에 앞서 <strong><a href="">렉시컬 환경(Lexical Environment)</a></strong>자료구조를 생성한다.
변수 선언이 실행되면 변수 식별자가 이 자료구조(렉시컬 환경)에 키(Key)로 등록되고, 변수 할당이 일어나면 이 자료구조의 변수 식별자에 해당하는 값을 변경한다.
변수의 검색도 이 자료구조에서 이루어진다.</li>
</ul>
<h3 id="📌-함수-검색">📌 <strong>함수 검색</strong></h3>
<blockquote>
<p>함수 선언문으로 함수를 정의하면 런타임 이전에 함수 객체가 먼저 생성된다. 그리고 자바스크립트 엔진은 함수 이름과 동일한 이름의 식별자를 암묵적으로 선언하고 생성된 함수 객체를 할당한다.</p>
</blockquote>
<ul>
<li><p>예제 13-06</p>
<pre><code class="language-jsx">// 전역 함수
function foo() {
  console.log(&#39;global function foo&#39;);
}

function bar() {
  // 중첩 함수
  function foo() {
    console.log(&#39;local function foo&#39;);
  }

  foo();
}

bar();
foo();

// Output :
// local function foo
// global function foo</code></pre>
</li>
</ul>
<h3 id="📌-블록-레벨-스코프block-level-scope">📌 <strong>블록 레벨 스코프(Block Level Scope)</strong></h3>
<blockquote>
<p><strong>모든 코드 블록(if, for, while, try/catch 등)과 함수 몸체가 지역 스코프를 만드는 특성</strong>이다.</p>
</blockquote>
<ul>
<li>C나 자바 등 대부분의 프로그래밍 언어가 이를 적용한다.</li>
</ul>
<h3 id="📌-함수-레벨-스코프function-level-scope">📌 <strong>함수 레벨 스코프(Function Level Scope)</strong></h3>
<blockquote>
<p>코드 블록이 아닌 <strong>함수에 의해서만 지역 스코프를 만드는 특성</strong>이다.</p>
</blockquote>
<ul>
<li><p><strong><code>var</code> 키워드</strong>로 선언된 변수는 <strong>오로지 함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정</strong>한다.</p>
</li>
<li><p>예제 13-07</p>
<ul>
<li><p>함수 밖에서 <code>var</code> 키워드로 선언된 변수는 코드 블록 내에서 선언되었다 할지라도 모두 전역 변수다.</p>
<pre><code class="language-jsx">var x = 1;

if (true) {
var x = 10; // 재할당
}

console.log(x); // 10</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="📌-동적-스코프dynamic-scope-렉시컬-스코프lexical-scope-또는-정적-스코프static-scope">📌 <strong>동적 스코프(Dynamic Scope), 렉시컬 스코프(Lexical Scope) 또는 정적 스코프(Static scope)</strong></h3>
<blockquote>
<p><strong>함수가 선언된 곳에 의해 상위 스코프가 결정되는 방식을 의미한다.</strong></p>
</blockquote>
<ul>
<li><p>프로그래밍 언어는 일반적으로 아래 두 가지 방식 중 한 가지 방식으로 함수의 상위 스코프를 결정한다.</p>
<ol>
<li>함수가 호출된 곳</li>
<li>함수가 선언된 곳</li>
</ol>
</li>
<li><p>자바스크립트는 렉시컬 스코프를 따른다.</p>
</li>
<li><p>예제 13-09</p>
<pre><code class="language-jsx">  var x = 1;

  function foo() {
      var x = 10;
      bar();
  }

  function bar() {
      console.log(x);
  }

  foo();
  bar();</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript | 자료형]]></title>
            <link>https://velog.io/@im_hass_/JavaScript-%EC%9E%90%EB%A3%8C%ED%98%95</link>
            <guid>https://velog.io/@im_hass_/JavaScript-%EC%9E%90%EB%A3%8C%ED%98%95</guid>
            <pubDate>Tue, 12 Jul 2022 04:40:57 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-javascript의-타입">📌 JavaScript의 타입</h2>
<blockquote>
<p><strong>JavaScript는 느슨한 타입(loosely typed)의 동적(dynamic) 언어이다.</strong></p>
</blockquote>
<ul>
<li>JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 가능하다. 이것을 동적 타입이라고 한다.</li>
<li>JavaScript의 타입은 원시 값(=기본 타입, 7개)와 객체(=참조 타입, 1개)로 구성된다.</li>
</ul>
<pre><code class="language-javascript">// 동적 타입
let foo = 42 // foo가 숫자
foo = &#39;bar&#39; // foo가 이제 문자열
foo = true // foo가 이제 불리언</code></pre>
<h3 id="원시-값primitive-value">원시 값(Primitive Value)</h3>
<blockquote>
<p>숫자, 문자열, 불리언, null, undefined인 다섯가지 기본 타입은 <strong>더 이상 단순화할 수 없기 때문에 원시적(primitive)</strong>이라 하며, 이러한 값을 가리켜 원시 값이라 한다.</p>
</blockquote>
<table>
<thead>
<tr>
<th>데이터 타입</th>
<th>설명</th>
<th>값</th>
</tr>
</thead>
<tbody><tr>
<td>Boolean</td>
<td>논리적 값</td>
<td>true or false</td>
</tr>
<tr>
<td>Null</td>
<td>비어 있는 값</td>
<td>null</td>
</tr>
<tr>
<td>Undefined</td>
<td>값을 할당하지 않은 변수</td>
<td>undefined</td>
</tr>
<tr>
<td>Number</td>
<td>정수, 실수 등의 숫자와 세 개의 상징적인 값</td>
<td><code>+0</code>(<code>0</code>), <code>-0</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>$-(2^{53} − 1)$ ~ $+(2^{53} − 1)$,</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>-Infinity</code>,</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>+Infinity</code>,</td>
</tr>
<tr>
<td></td>
<td></td>
<td><code>NaN(Not a Number)</code></td>
</tr>
<tr>
<td>BigInt</td>
<td>Number의 안전 한계를 넘는 큰 정수</td>
<td><code>2n</code>, <code>53n</code>, ...</td>
</tr>
<tr>
<td>String</td>
<td>텍스트 데이터를 나타냄, 불변함</td>
<td>&quot;Hi&quot;, &quot;123&quot;, ...</td>
</tr>
<tr>
<td>Symbol</td>
<td>고유하고 변경 불가능한 원시 값, 객체의 속성 키로 사용</td>
<td>&quot;foo&quot;, &quot;a&quot;, &quot;b&quot;, ...</td>
</tr>
</tbody></table>
<h3 id="객체objects">객체(Objects)</h3>
<blockquote>
<p> 식별자로 참조할 수 있는 메모리 상의 값이다.</p>
</blockquote>
<ul>
<li>식별자는 코드 내의 변수, 함수, 혹은 속성을 식별하는 문자열이다.</li>
<li>식별자는 대소문자를 구분한다.</li>
<li>객체 리터럴을 사용해 속성을 초기화, 추가, 제거할 수 있다.</li>
<li>객체 리터럴은 중괄호(<code>{}</code>)로 묶인 0개 이상인 객체의 속성명과 관련 값 쌍 목록이다.</li>
<li>속성 값으로는 다른 객체를 포함해 모든 타입을 사용할 수 있으므로 복잡한 자료구조의 구축이 가능하다.</li>
<li>속성은 &#39;키&#39; 값으로 식별하며, 키 값으로는 문자열 값이나 심볼을 사용할 수 있다.</li>
</ul>
<table>
<thead>
<tr>
<th>데이터 타입</th>
<th>설명</th>
<th>값</th>
</tr>
</thead>
<tbody><tr>
<td>object</td>
<td>두 개 이상의 복잡한 개체를 저장</td>
<td>{</td>
</tr>
<tr>
<td></td>
<td></td>
<td>name: &#39;Smith&#39;,</td>
</tr>
<tr>
<td></td>
<td></td>
<td>age: 32,</td>
</tr>
<tr>
<td></td>
<td></td>
<td>}</td>
</tr>
</tbody></table>
<br>


<h2 id="📌-typeof">📌 <code>typeof</code></h2>
<blockquote>
<p>typeof 연산자를 사용하면 변수의 타입을 알아낼 수 있다.</p>
</blockquote>
<ul>
<li><code>null</code>은 <code>null</code>이 아니라 <code>object</code>라고 나오는데, 명백한 오류이지만 수많은 프로그램들이 <code>object</code>로 취급하며 만들어졌기 때문에 이전 버전에서 오류나는 것을 방지하기 위해 의도적으로 버그를 수정하지 않는다고 한다.</li>
</ul>
<pre><code class="language-javascript">// 원시 값
console.log(typeof true); // boolean
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof 123); // number
console.log(typeof 123n); // bigint
console.log(typeof &quot;hi&quot;); // string
console.log(typeof Symbol(&quot;id&quot;)); // symbol

// 객체
console.log(typeof Math); // object

// 함수
console.log(typeof console.log); // function</code></pre>
<br>

<h2 id="📌-참고">📌 참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures">mdn 한글 공식 문서</a></li>
<li><a href="https://webclub.tistory.com/240#:~:text=%EC%A6%89%2C%20%EC%88%AB%EC%9E%90%2C%20%EB%AC%B8%EC%9E%90%EC%97%B4%2C%20%EB%B6%88%EB%A6%AC%EC%96%B8,%EA%B0%80%EB%A6%AC%EC%BC%9C%20%EC%9B%90%EC%8B%9C%EA%B0%92%EC%9D%B4%EB%9D%BC%20%ED%95%A9%EB%8B%88%EB%8B%A4.">원시값 참고</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 기본 개념 정리]]></title>
            <link>https://velog.io/@im_hass_/JavaScript-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@im_hass_/JavaScript-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 11 Jul 2022 14:04:55 GMT</pubDate>
            <description><![CDATA[<h3 id="📌-javascript">📌 JavaScript</h3>
<blockquote>
<p>객체(Object) 기반의 스크립트 프로그래밍 언어로, 웹페이지에 생동감을 불어넣기 위해 만들어졌다.</p>
</blockquote>
<ul>
<li>페이지의 내용이 — 가만히 정적인 정보만 보여주는 것이 아니라 — 주기적으로 갱신되거나, 사용자와 상호작용이 가능하거나, 애니메이션이 적용된 2D/3D 그래픽일 경우 등에 사용된다.</li>
<li><a href="%EC%A0%95%EB%A6%AC%EC%A4%91">비동기</a> 기반으로 작동한다.</li>
<li><a href="%EC%A0%95%EB%A6%AC%EC%A4%91">싱글 스레드</a>이다.</li>
</ul>
<br>

<h3 id="📌-ecmascript">📌 ECMAScript</h3>
<blockquote>
<p>JavaScript를 표준화하기 위해 만들어진, 표준화된 스크립트 프로그래밍 언어.</p>
</blockquote>
<br>

<h3 id="📌-nodejs">📌 Node.js</h3>
<br>

<h3 id="📌-호이스팅hosting">📌 호이스팅(Hosting)</h3>
<blockquote>
<p>코드에 선언된 변수 및 함수를 유효한 코드 범위의 상단으로 끌어 올린다.</p>
</blockquote>
<br>

<h3 id="📌-싱글-스레드">📌 싱글 스레드</h3>
<blockquote>
<p>한 번에 한 가지 일 밖에 처리할 수 없다는 것을 의미한다.</p>
</blockquote>
<br>

<h3 id="📌-비동기-콜백">📌 비동기 콜백</h3>
<br>

<h3 id="📌-자료형">📌 자료형</h3>
<blockquote>
<p>JavaScript의 타입은 원시 값(=기본 타입, 7개)와 객체(=참조 타입, 1개)로 구성된다.</p>
</blockquote>
<p><a href="https://velog.io/@im_hass_/JavaScript-%EC%9E%90%EB%A3%8C%ED%98%95">자료형 참고</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[후기] 스파로스 아카데미 1기 최종 합격 후기]]></title>
            <link>https://velog.io/@im_hass_/%EC%8A%A4%ED%8C%8C%EB%A1%9C%EC%8A%A4-%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8-1%EA%B8%B0-%EC%B5%9C%EC%A2%85-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@im_hass_/%EC%8A%A4%ED%8C%8C%EB%A1%9C%EC%8A%A4-%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8-1%EA%B8%B0-%EC%B5%9C%EC%A2%85-%ED%95%A9%EA%B2%A9-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Fri, 08 Jul 2022 09:01:22 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.spharosacademy.com/home">스파로스 아카데미 공식 홈페이지</a></p>
<blockquote>
<p><strong>스파로스 아카데미 1기 최종 합격 후기입니다!!</strong>
2022.07.08.</p>
</blockquote>
<p>1기라 정보가 없어서 걱정됐는데 다행히 합격할 수 있었습니다. ㅎㅎ 다음 기수분들께 도움이 되도록 잊기 전에 미리 직성해봅니다.
만약 합격자 분이시라면 카카오톡 오픈채팅에 합격생들 방이 있으니 들어오셔서 소통하면 좋을 것 같아요 ^~^!</p>
<h3 id="참고-스펙">참고 스펙(?)</h3>
<ul>
<li>전공 졸업자</li>
<li>프론트엔드 지원</li>
<li>정보처리기사 보유</li>
<li>수상 경험 없음</li>
<li>프로젝트 경험 있음(학과 프로젝트)</li>
<li>코테 잘 못함(백준 실5)</li>
</ul>
<h2 id="지원-절차">지원 절차</h2>
<ol>
<li><p><strong>서류지원</strong>
 6/25(토), 오후 12시까지</p>
</li>
<li><p><strong>서류전형</strong>
 6/27(월), 서류전형 발표</p>
</li>
<li><p><strong>코딩테스트</strong>
 7/2(토), 백엔드(Java), 프론트엔드(Javascript)</p>
</li>
<li><p><strong>인터뷰</strong>
 7월 1주차 예정</p>
</li>
<li><p><strong>최종합격</strong>
 18주 동안 교육 진행</p>
</li>
</ol>
<p>우선 진행이 정말 빠릅니다... 일처리를 쉬지 않고 하시는 듯.
서류 결과부터 코테, 인터뷰까지 2주만에 전부 끝났습니다. 전부 미리미리 준비하시는 것을 추천드립니다.
내용을 자세하게 써도 될지 몰라서 두루뭉술하게 말하는 점 양해 부탁드립니다.</p>
<h3 id="1-서류-지원">1. 서류 지원</h3>
<p>서류는 희망하는 직무 분야와 개인 정보 등을 입력하고, 자신이 생각하는 기술 스택 수준을 1, 2, 3단계로 선택합니다.
저는 프론트엔드를 지원했고 Lv3 4개?, Lv2 2개, Lv1 1개 정도 했던 것 같아요! 입과 전이라 잘 모르겠으나 지원과정에서는 별로 의미 없는 느낌이었습니다.
그리고 3가지 선택 사항과 1가지 필수 사항 입력 칸이 주어집니다. 저는 선택사항도 필수 사항도 있는대로 다 적었습니다! 작성 양식에 맞춰서 최대한 자세히 적었어요.</p>
<ol>
<li><strong>SW 관련 경험(교육, 대회 등)</strong>
 특강 들은 교육 2가지 적었습니다.</li>
<li><strong>SW 관련 자격사항(수상, 자격증)</strong>
 정보처리기사 자격증을 적었습니다. 슬프게도 수상 경험은 없네요 ㅎㅎ...</li>
<li><strong>SW 관련 프로젝트 경험</strong>
 학부생 때 했던 프로젝트 한 가지와 개인적으로 했던 프로젝트 한 가지, 친구와 진행 중인 프로젝트 한 가지 해서 총 3가지를 적었네요.
개인적으로 학부생 치고는 되게 적다고 생각했는데, 면접 때 프로젝트 경험이 많다고 말씀하셔서 의외였습니다.</li>
<li><strong>본 교육 프로그램의 지원 동기 또는 학습하고 싶은 내용 (필수입력)</strong>
 어떤 개발자가 되고 싶은지와 이 프로그램에서 학습하고 싶은 내용을 엮어서 썼던 것 같습니다.</li>
</ol>
<h3 id="2-서류-지원">2. 서류 지원</h3>
<p>문자로 결과를 받았습니다! 서류 합격을 못 하면 코테도 못 친다니 좋은지 나쁜지 모르겠네요...</p>
<h3 id="3-코딩-테스트">3. 코딩 테스트</h3>
<p>프론트엔드는 JS, 백엔드는 Java로 코테를 칩니다.
코테는 검색, 외부 IDE 금지이고 프로그래머스를 이용해서 시행되니 프로그래머스로 연습하시면 좋을 듯 합니다!
3문제 2시간이었습니다. 저는 2솔 했습니다.
난이도는 쉬운 편이었습니다.
백준 브3~1/실5, 프로그래머스 Lv1 쉬운 문제 수준이라 느꼈습니다.</p>
<h3 id="4-인터뷰">4. 인터뷰</h3>
<p>대망의 인터뷰... 코테를 토요일에 쳤는데, 불과 2일 만인 월요일에 결과가 나왔습니다... 그리고 2일 후에 면접을 보래요...
사실 이때 여행 중이어서... 진짜 식겁했습니다... 이렇게 빨리 나올줄이야... 최소 목요일에 나올 줄 알았는데...
부랴부랴 면접 준비하면서, 놀면서 바쁘게 시간을 보냈습니다... 친구들이 연습 시켜줘서 많이 도움이 됐어요!!
기술 질문과 인성 질문이 있었습니다. 자세한건... 말씀드려도 되는지 모르겠으니 생략하겠습니다.
1분 자기소개, 지원동기, 마지막 하고 싶은 말, 했던 프로젝트 정리 등을 했습니다.
프로젝트는 간단한 소개, 인원/역할, 사용 기술, 진행하며 생긴 문제점, 해결 방법, 결과를 정리했습니다!
zoom으로 진행했고 20분 보는거 였는데, 대답도 제대로 했는지 기억이 안 나고... 10분 만에 끝나버려서 사실 아 망했다.. 하고 있었습니다.</p>
<h3 id="5-최종-합격">5. 최종 합격</h3>
<p>결과가 언제 나오나... 일처리가 이렇게 빠른거 보니, 뭔가 이번주에 나올 것 같다.. 라고 생각은 하고 있었는데
웬걸...? 바로 다음날 결과가 나왔습니다. 세상에 ㄷㄷ...
문자와 메일로 결과 전달 받았습니다.
망했다 생각했는데 합격한거 보고 너무 놀라고 신기해서 손이 달달달 거렸네요 ㅋㅋㅋ</p>
<h2 id="후기">후기</h2>
<p>가능한 매주 회고록을 작성하고 싶은데... 갈려나갈지 어떻게 될지 모르겠네요 ㅎㅎ.
궁금한 점은 메일이나 댓글 부탁드립니다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Frontend 기본 개념 정리]]></title>
            <link>https://velog.io/@im_hass_/Frontend%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@im_hass_/Frontend%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 03 Jul 2022 09:55:34 GMT</pubDate>
            <description><![CDATA[<h3 id="📌-htmlhypertext-markup-language">📌 HTML(HyperText Markup Language)</h3>
<blockquote>
<p><strong>웹 브라우저가 이해할 수 있도록 작성된 언어</strong>로서, 다른 위치나 페이지로 이동할 수 있게 만들어진 <strong>하이퍼텍스트를 마크업</strong> 하여, 데이터를 어디에 어떻게 표현할지 구조를 만들어내는 마크업 언어.</p>
</blockquote>
<ul>
<li>웹 브라우저란, HTML 파일을 구동할 수 있는 프로그램이다. 대표적으로 크롬, 파이어폭스, 사파리, 웨일 등이 있다.</li>
</ul>
<br>

<h3 id="📌-csscascading-style-sheets">📌 CSS(Cascading Style Sheets)</h3>
<blockquote>
<p>사용자에게 <strong>문서를 표시하는 방법</strong>을 지정하는 언어.</p>
</blockquote>
<ul>
<li>문서란 일반적으로 HTML을 말한다.</li>
<li>위에서 정한 스타일이 아래에 있는 요소들에게도 전파된다는 의미로 Cascading(폭포)이 사용된다.</li>
</ul>
<br>

<h3 id="📌-javascript">📌 JavaScript</h3>
<blockquote>
<p>객체(Object) 기반의 스크립트 프로그래밍 언어로, 웹페이지에 생동감을 불어넣기 위해 만들어졌다.</p>
</blockquote>
<ul>
<li><a href="https://velog.io/@im_hass_/JavaScript-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC">기본 개념 참고</a></li>
<li>페이지의 내용이 — 가만히 정적인 정보만 보여주는 것이 아니라 — 주기적으로 갱신되거나, 사용자와 상호작용이 가능하거나, 애니메이션이 적용된 2D/3D 그래픽일 경우 등에 사용된다.</li>
<li><a href="%EC%A0%95%EB%A6%AC%EC%A4%91">비동기</a> 기반으로 작동한다.</li>
<li><a href="%EC%A0%95%EB%A6%AC%EC%A4%91">싱글 스레드</a>이다.</li>
</ul>
<h4 id="html-css-javascript-관계">HTML, CSS, JavaScript 관계</h4>
<ul>
<li><p><strong>[구조] HTML</strong> : 웹 문서의 기본적인 골격을 담당.</p>
</li>
<li><p><strong>[표현] CSS</strong> : 각 요소들의 레이아웃, 스타일링을 담당.</p>
</li>
<li><p><strong>[동작] JavaScript</strong> : 동적인 요소(사용자와의 인터렉션)을 담당.</p>
</li>
</ul>
<br>

<h3 id="📌-css-우선-순위">📌 CSS 우선 순위</h3>
<blockquote>
<p><strong><code>!important</code> &gt; 인라인 &gt; 내부 &gt; 외부 &gt; 웹 브라우저 기본값</strong> 순서로 우선 적용된다.</p>
</blockquote>
<p><strong>1. <code>!important</code></strong>
<strong>2. 인라인 스타일</strong>
<strong>3. 내부 스타일(선택자)</strong></p>
<ul>
<li><strong>같은 선택자일 경우, 뒤쪽에 선언된 것</strong>이 우선된다.</li>
<li><strong>다른 선택자일 경우, 명시도*가 높은 것</strong>이 우선된다.<ol>
<li>id 선택자</li>
<li>속성 선택자</li>
<li>class 선택자</li>
<li>tag(type) 선택자</li>
</ol>
</li>
</ul>
<p><strong>4. 외부 스타일(import)</strong>
<strong>5. 웹 브라우저 기본값</strong></p>
<p><strong>※ 명시도 :</strong> 적용 범위가 좁아서 명확하게 정해진 것.</p>
<br>

<h3 id="📌-브라우저의-동작렌더링-과정">📌 브라우저의 동작(렌더링 과정)</h3>
<blockquote>
<p><strong>DOM트리 구축 → CSSOM 트리 구축 → JS 실행 → 렌더 트리 구축 → 렌더 트리의 위치 크기 계산 → 화면에 그리기</strong></p>
</blockquote>
<p><strong>1. HTML 파싱 후, DOM 트리를 구축한다.</strong>
<strong>2. CSS 파싱 후, CSSOM 트리를 구축한다.</strong>
<strong>3. JS를 실행한다.</strong>
<strong>4. DOM 트리와 CSSOM 트리를 조합하여, 렌더 트리를 구축한다.</strong>
<strong>5. 뷰포트를 기준으로 렌더 트리의 각 노드가 가지는 정확한 위치와 크기를 계산한다.</strong>
<strong>6. 계산한 위치, 크기를 기반으로 화면에 그린다.</strong></p>
<p>※ 3에서 HTML 중간에 스크립트가 있다면 HTML 파싱이 중지된다.
※ 4에서 <code>display: none;</code> 속성과 같이 화면에 안 보이고 공간 차지가 없는 것은 렌더 트리로 구축되지 않는다.</p>
<br>

<h3 id="📌-local-storage-session-storage-cookie">📌 Local Storage, Session Storage, Cookie</h3>
<h4 id="공통점">공통점</h4>
<blockquote>
<p>클라이언트 상에서 key/value 쌍을 저장할 수 있는 메커니즘으로 value는 반드시 문자열이어야 한다.</p>
</blockquote>
<ul>
<li>모두 <a href="https://github.com/baeharam/Must-Know-About-Frontend/blob/main/Notes/security/sop.md">동일 출처 정책(SOP)</a>을 따르기 때문에 다른 도메인에서 접근할 수 없다.</li>
</ul>
<p><strong>※ 출처(Origin) :</strong> URL 체계(http, https), 호스트(naver.com), 포트(5000, 80) 등.</p>
<h4 id="local-storage">Local Storage</h4>
<blockquote>
<p>일정 시간 또는 영구적으로 값을 저장하고 싶은 경우 사용할 수 있는 Web Storage.</p>
</blockquote>
<ul>
<li>Web Storage API이다.</li>
<li>JS로 데이터 조작이 가능하다(서버에서 조작이 불가능하다).</li>
<li>네트워크 요청 시 서버로 전송되지 않는다.</li>
<li>브라우저를 재시작해도 데이터가 남아있다.</li>
<li>다른 창과 브라우저를 통해서도 접근할 수 있다.</li>
<li>모바일에서도 사용할 수 있다.</li>
</ul>
<h4 id="session-storage">Session Storage</h4>
<blockquote>
<p>현재 브라우저 내에서만 유지하고 싶은 경우 사용할 수 있는 Web Storage.</p>
</blockquote>
<ul>
<li>Web Storage API이다.</li>
<li>브라우저가 닫히면 데이터가 사라진다.</li>
<li>다른 창과 브라우저를 통해서 공유가 불가능하다.</li>
</ul>
<h4 id="cookie">Cookie</h4>
<blockquote>
<p>웹사이트 접속 시 그 사이트가 사용하는 서버를 통해 로컬에 저장되는 작은 데이터 파일.</p>
</blockquote>
<ul>
<li>서버에서 설정 할 수 있다.</li>
<li>설정에 따라 지속 시간(만료일)이 다르다.</li>
<li>서버와의 세션 관리 등에 사용된다(세션 쿠키).</li>
<li>서버와 통신할 때 HTTP헤더에 포함되어 전송된다.</li>
<li>JS로도 조작할 수 있는데, httponly 특성을 붙여 조작을 막는다. 제 3자의 수정 또는 XSS를 막는다.</li>
</ul>
<h4 id="요약">요약</h4>
<table>
<thead>
<tr>
<th></th>
<th>Local Storage</th>
<th>Session Storage</th>
<th>Cookie</th>
</tr>
</thead>
<tbody><tr>
<td>생성자</td>
<td>클라이언트</td>
<td>클라이언트</td>
<td>클라이언트/서버</td>
</tr>
<tr>
<td>지속 시간(만료일)</td>
<td>명시적으로 지울때까지</td>
<td>탭/윈도우 닫을 때까지</td>
<td>설정 여부에 따름</td>
</tr>
<tr>
<td>용량</td>
<td>5MB, 10MB</td>
<td>5MB</td>
<td>4KB</td>
</tr>
<tr>
<td>서버와의 통신</td>
<td>통신하지 않음</td>
<td>통신하지 않음</td>
<td>통신함</td>
</tr>
<tr>
<td>취약점</td>
<td>XSS 공격</td>
<td>XSS 공격</td>
<td>XSS, CSRF 공격</td>
</tr>
</tbody></table>
<br>

<h3 id="📌-가비지-컬렉션garbage-collection">📌 가비지 컬렉션(Garbage Collection)</h3>
<blockquote>
<p>프로그램에서 더 이상 사용되지 않는 메모리를 자동으로 정리하는 것.</p>
</blockquote>
<ul>
<li>특정 때에 특정 방식으로 필요없는 정보들 즉, 가비지들을 쓸어 담아 버린다.</li>
<li>지워야할 것들을 100퍼센트 잡아내지는 못하기 때문에, 프로그래머가 신경쓸 필요가 있다.</li>
<li>메모리를 관리하지 않으면 메모리 누수가 발생할 수 있고, 속도저하, 예기치 못한 종료, 느린 응답 속도 등과 같은 많은 문제가 발생할 수 있다.</li>
</ul>
<h3 id="📌">📌</h3>
<blockquote>
<p>...</p>
</blockquote>
<br>

<h2 id="참고">참고</h2>
<ul>
<li><a href="https://github.com/Im-hass/TIL">TIL</a></li>
<li><a href="https://github.com/Im-hass/Must-Know-About-Frontend#computer-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%A0%84%EB%B0%98">프론트엔드 전반 지식</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | 정규 표현식(정규식)]]></title>
            <link>https://velog.io/@im_hass_/Javascript-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D%EC%A0%95%EA%B7%9C%EC%8B%9D</link>
            <guid>https://velog.io/@im_hass_/Javascript-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D%EC%A0%95%EA%B7%9C%EC%8B%9D</guid>
            <pubDate>Fri, 01 Jul 2022 08:57:58 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-정의">📌 정의</h2>
<blockquote>
<p>💡 <strong>문자열에서 특정 문자 조합을 찾기 위한 패턴이다.</strong></p>
</blockquote>
<ul>
<li>Javascript에서는 <strong>정규 표현식도 객체</strong>이다.</li>
</ul>
<h2 id="📌-메서드">📌 메서드</h2>
<ul>
<li><p><code>RegExp</code>의 <code>exec()</code>와 <code>test()</code> 메서드를 사용할 수 있다.</p>
</li>
<li><p><code>String</code>의 <code>match()</code>, <code>matchAll()</code>, <code>replace()</code>, <code>replaceAll()</code>, <code>search()</code>, <code>split()</code>에 사용할 수 있다.</p>
</li>
</ul>
<h2 id="📌-생성">📌 생성</h2>
<p>정규 표현식을 만드는 두 가지 방법이 있다.</p>
<ol>
<li><strong>정규 표현식 리터럴 :</strong> 슬래시로 패턴 감싸기 <code>/패턴/</code><ul>
<li>이 방식은 스크립트를 불러올 때 컴파일된다.</li>
<li><strong>바뀔 일이 없는 패턴</strong>의 경우 리터럴을 사용하면 성능이 향상될 수 있다.</li>
</ul>
</li>
<li><strong>RegExp 객체 :</strong> 생성자 호출 <code>new RegExp(&#39;패턴&#39;)</code><ul>
<li>생성자 함수를 사용하면 정규 표현식이 런타임에 컴파일된다.</li>
<li><strong>바뀔 수 있는 패턴이나, 사용자 입력 등 외부 출처에서 가져오는 패턴</strong>의 경우 이것을 사용하면 된다.</li>
</ul>
</li>
</ol>
<pre><code class="language-js">// 1. 정규 표현식 리터럴
const re1 = /ab+c/;

// 2. RegExp 객체 생성자 호출
const re2 = new RegExp(&#39;ab+c&#39;);</code></pre>
<h2 id="📌-패턴">📌 패턴</h2>
<p>정규 표현식 패턴은 문자, 문자와 특수 문자 등의 조합으로 구성될 수 있다.</p>
<blockquote>
<p><strong><code>-</code> : 범위(어디에서 어디까지)</strong></p>
</blockquote>
<ul>
<li><code>a-z</code> : a에서 z까지를 의미</li>
<li><code>0-9</code> : 0에서 9까지를 의미</li>
<li><code>ㄱ-ㅎ</code> : ㄱ에서 ㅎ까지를 의미</li>
<li><code>ㅏ-ㅣ</code> : ㅏ에서 ㅣ 까지를 의미</li>
<li><code>가-힣</code> : &#39;가&#39;에서 &#39;힣&#39;까지를 의미</li>
</ul>
<blockquote>
<p><strong><code>[]</code> : 괄호 안에 문자중 1개</strong></p>
</blockquote>
<ul>
<li><code>[a-z]</code> : a에서 z중 하나.</li>
<li><code>[abc]d</code> : ad, bd, bd를 의미</li>
</ul>
<blockquote>
<p><strong><code>[^]</code> : 괄호안의 문자 부정(제외)</strong></p>
</blockquote>
<ul>
<li><code>[^a-z]</code> : a ~ z를 제외한 모든 문자</li>
<li><code>[^0-9]</code> : 숫자를 제외한 모든 문자</li>
</ul>
<blockquote>
<p><strong><code>^</code> : 문자열의 처음</strong></p>
</blockquote>
<ul>
<li><code>^[a-zA-Z]</code> : 영문자로 시작해야함</li>
</ul>
<blockquote>
<p><strong><code>$</code> : 문자열의 끝</strong></p>
</blockquote>
<ul>
<li><code>[a-zA-Z]$</code> : 영문자로 끝나야함</li>
<li><code>^[a-zA-Z]$</code> : 영문자로 시작하고, 영문자로 끝나야함</li>
</ul>
<blockquote>
<p><strong><code>|</code> : 또는(OR)</strong></p>
</blockquote>
<ul>
<li><code>[a-z|A-Z]</code> : a ~ z 또는 A ~ Z 의미(영어 전체)</li>
<li><code>[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]</code> : ㄱ ~ ㅎ 또는 ㅏ ~ ㅣ 또는 가 ~ 힣 의미(한글 전체)</li>
</ul>
<blockquote>
<p><strong><code>*</code> : 0회 이상(여러개)</strong></p>
</blockquote>
<ul>
<li><code>^[a-zA-Z]*$</code> : 여러개의 문자가 모두 영문자여야 함</li>
<li><code>^[0-9]*$</code> : 여러개의 문자가 모두 숫자여야 함</li>
<li><code>^[a-zA-Z0-9]*$</code> : 여러개의 문자가 모두 영문자나 숫자여야 함</li>
</ul>
<blockquote>
<p><strong><code>{m, n}</code> : m회 이상, n회 이하</strong></p>
</blockquote>
<ul>
<li><code>^[a-zA-Z]*${1, 10}</code> : 영문자 1자 이상, 10자 이하</li>
</ul>
<h2 id="📌-플래그옵션를-활용한-고급-탐색">📌 플래그(옵션)를 활용한 고급 탐색</h2>
<ul>
<li>Javascript에 <code>replace()</code>는 있지만 <code>replaceAll()</code>은 없다.</li>
<li>이때 플래그를 활용하면 전역 탐색이나 대소문자 무시와 같은 <strong>특성을 지정</strong>할 수 있다.</li>
<li>플래그는 <strong>단독</strong>으로 사용할 수도 있고, <strong>순서 상관 없이 한번에 여럿</strong>을 지정할 수도 있다.</li>
<li><code>gi</code>가 가장 자주 쓰인다.</li>
</ul>
<pre><code class="language-js">// 1. 정규 표현식 리터럴
const re1 = /pattern/flags;

// 2. RegExp 객체 생성자 호출
const re2 = new RegExp(&#39;pattern&#39;, &#39;flags&#39;);</code></pre>
<blockquote>
<p><strong><code>g</code>    : 전역 탐색</strong></p>
</blockquote>
<ul>
<li>패턴과 일치하는 모든 부분을 찾는다.</li>
</ul>
<pre><code class="language-js">const re1 = /[1]/;
const str1 = &#39;010-1111-2222&#39;;
console.log(str1.replace(re1, 3)); // 030-1111-2222

const re2 = /[1]/g;
// 또는
// const re1 = new RegExp(&#39;1&#39;, &#39;g&#39;);
const str2 = &#39;010-1111-2222&#39;;
console.log(str2.replace(re2, 3)); // 030-3333-2222</code></pre>
<blockquote>
<p><strong><code>i</code>    : 대소문자를 구분하지 않음</strong></p>
</blockquote>
<ul>
<li>대소문자를 구분하지 않고 일치하는걸로 간주한다.</li>
</ul>
<pre><code class="language-js">const re1 = /[a]/;
const str1 = &#39;A&#39;;
console.log(str1.replace(re1, &#39;b&#39;)); // A

const re2 = /[a]/i;
// 또는
// const re2 = new RegExp(&#39;A&#39;, &#39;i&#39;);
const str2 = &#39;A&#39;;
console.log(str2.replace(re2, &#39;b&#39;)); // B</code></pre>
<blockquote>
<p><strong><code>d</code> : 부분 문자열 일치에 대해 인덱스 생성</strong></p>
</blockquote>
<blockquote>
<p><strong><code>m</code>    : 여러 줄에 걸쳐 탐색</strong></p>
</blockquote>
<blockquote>
<p><strong><code>s</code>    : 개행 문자가 .과 일치함</strong></p>
</blockquote>
<blockquote>
<p><strong><code>u</code>    : &quot;unicode&quot;, 패턴을 유니코드 코드 포인트의 시퀀스로 간주함</strong></p>
</blockquote>
<blockquote>
<p><strong><code>y</code>    : &quot;접착&quot; 탐색, 대상 문자열의 현재 위치에서 탐색을 시작함</strong></p>
</blockquote>
<h2 id="📌-참고">📌 참고</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions">MDN 공식 문서 - 정규 표현식</a></li>
<li><a href="https://curryyou.tistory.com/208">정규표현식 생기초</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level1. 신규 아이디 추천]]></title>
            <link>https://velog.io/@im_hass_/Javascript-Level1.-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</link>
            <guid>https://velog.io/@im_hass_/Javascript-Level1.-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</guid>
            <pubDate>Wed, 29 Jun 2022 12:12:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>Javascript, Lv1, 구현</strong></p>
</blockquote>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/72410">문제 링크</a></p>
<h2 id="문제">문제</h2>
<ul>
<li><p>문제 그대로하면 되는 구현 문제이다.</p>
</li>
<li><p>카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 return해준다.</p>
</li>
<li><p>카카오 아이디의 규칙 :</p>
<ul>
<li>아이디의 길이는 3자 이상 15자 이하여야 합니다.</li>
<li>아이디는 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용할 수 있습니다.</li>
<li>단, 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없습니다.</li>
</ul>
</li>
<li><p>아래 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해준다.</p>
<ul>
<li>1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.</li>
<li>2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.</li>
<li>3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.</li>
<li>4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.</li>
<li>5단계 new_id가 빈 문자열이라면, new_id에 &quot;a&quot;를 대입합니다.</li>
<li>6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
  만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.</li>
<li>7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.</li>
</ul>
</li>
</ul>
<h2 id="접근-방법">접근 방법</h2>
<ul>
<li>정규식을 사용하면 편하게 풀 수 있다.</li>
<li>정규식 참고 : <a href="">정리중</a></li>
<li>순서대로 하나씩 구현해나간다.</li>
<li>메소드 체이닝을 사용하면 더 보기 좋게 구현할 수 있다.</li>
</ul>
<h2 id="주의-사항">주의 사항</h2>
<ul>
<li><h2 id="코드">코드</h2>
<pre><code class="language-javascript">function solution(new_id) {
  var answer = new_id;
  const upperReg = /[A-Z]/;
  const symbolReg = /[~|!|@|#|$|%|^|&amp;|*|(|)|=|+|[|\]|{|}|:|?|,|&lt;|&gt;|\/]/; // ~!@#$%^&amp;*()=+[{]}:?,&lt;&gt;/

  if (new_id.length &lt; 3 || new_id.length &gt; 15 ||
      new_id[0] === &quot;.&quot; || new_id[new_id.length - 1] === &quot;.&quot; ||
      upperReg.test(new_id) ||
      symbolReg.test(new_id)) {
      // id 길이가 3보다 작거나 15보다 클 경우
      // 처음이나 끝에 마침표가 들어갈 경우
      // 대문자가 있을 경우
      // 허용되지 않는 특수문자가 들어갈 경우
      answer = changeId(new_id);
  }

  return answer;
}
</code></pre>
</li>
</ul>
<p>function changeId(id) {
  // 1단계 모든 대문자 -&gt; 소문자로 치환
  id = id.toLowerCase();</p>
<p>  // 2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
  id = id.replace(/[~|!|@|#|$|%|^|&amp;|*|(|)|=|+|[|]|{|}|:|?|,|&lt;|&gt;|/]/g, &quot;&quot;);</p>
<p>  // 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
  id = id.replace(/[.]{2,}/g, &quot;.&quot;);</p>
<p>  // 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
  id = id.replace(/^[.]|[.]$/g, &quot;&quot;);</p>
<p>  // 5단계 new_id가 빈 문자열이라면, new_id에 &quot;a&quot;를 대입합니다.
  if (id.length === 0) id += &quot;a&quot;;</p>
<p>  // 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
  //      만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
  if (id.length &gt;= 16) id = id.slice(0, 15).replace(/[.]$/g, &quot;&quot;);</p>
<p>  // 7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
  if (id.length &lt;= 2) {
    let add = id[id.length - 1];
    while (id.length &lt; 3) {
      id += add;
    }
  }</p>
<p>  return id;
}</p>
<p>```</p>
<h2 id="다른-사람-풀이">다른 사람 풀이</h2>
<ul>
<li><p>정규식, repeat
{% capture code %}
{% highlight javascript linenos %}
function solution(new_id) {
  const answer = new_id</p>
<pre><code>  .toLowerCase() // 1
  .replace(/[^\w-_.]/g, &#39;&#39;) // 2
  .replace(/\.+/g, &#39;.&#39;) // 3
  .replace(/^\.|\.$/g, &#39;&#39;) // 4
  .replace(/^$/, &#39;a&#39;) // 5
  .slice(0, 15).replace(/\.$/, &#39;&#39;); // 6</code></pre><p>  const len = answer.length;
  return len &gt; 2 ? answer : answer + answer.charAt(len - 1).repeat(3 - len);
}
{% endhighlight %}
{% endcapture %}
{% include fix_linenos.html code=code %}
{% assign code = nil %}</p>
</li>
<li><p>정규 표현식만 사용
{% capture code %}
{% highlight javascript linenos %}
const solution = new_id =&gt;
  new_id.toLowerCase()</p>
<pre><code>    .replace(/[^\w-_.]/g, &quot;&quot;)
    .replace(/\.+/g, &quot;.&quot;)
    .replace(/^\.|\.$/g, &quot;&quot;)
    .replace(/^$/, &quot;a&quot;)
    .match(/^.{0,14}[^.]/)[0]
    .replace(/^(.)$/, &quot;$1$1$1&quot;)
    .replace(/^(.)(.)$/, &quot;$1$2$2&quot;);</code></pre><p>{% endhighlight %}
{% endcapture %}
{% include fix_linenos.html code=code %}
{% assign code = nil %}</p>
</li>
</ul>
<h2 id="참고">참고</h2>
<p>- </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 표기법]]></title>
            <link>https://velog.io/@im_hass_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%91%9C%EA%B8%B0%EB%B2%95</link>
            <guid>https://velog.io/@im_hass_/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%91%9C%EA%B8%B0%EB%B2%95</guid>
            <pubDate>Mon, 27 Jun 2022 07:54:14 GMT</pubDate>
            <description><![CDATA[<h1 id="알고리즘-표기법">알고리즘 표기법</h1>
<blockquote>
<p><strong>핵심 단어</strong></p>
</blockquote>
<ul>
<li><strong>Big O</strong></li>
<li><strong>Big Ω(Omega)</strong></li>
<li><strong>Big θ(Theta)</strong></li>
</ul>
<h2 id="big-o"><strong>Big O</strong></h2>
<ul>
<li>컴퓨터 과학에서 “대략”을 나타내는 공식적인 개념.</li>
<li><strong>최악의 경우(실행 시간의 상한 = 제일 느린 경우)에 대한 시간 복잡도</strong>를 나타내는 표현이다.</li>
</ul>
<table>
<thead>
<tr>
<th>표기</th>
<th>알고리즘 예시</th>
</tr>
</thead>
<tbody><tr>
<td>O(n^k)</td>
<td>-</td>
</tr>
<tr>
<td>O(2&amp;n)</td>
<td>-</td>
</tr>
<tr>
<td>O(n^3)</td>
<td>-</td>
</tr>
<tr>
<td>O(n^2)</td>
<td>bubble sort(거품 정렬),</td>
</tr>
<tr>
<td></td>
<td>insertion sort(삽입 정렬),</td>
</tr>
<tr>
<td></td>
<td>selection sort(선택 정렬)</td>
</tr>
<tr>
<td>O(n log n)</td>
<td>merge sort(병합/합병 정렬),</td>
</tr>
<tr>
<td></td>
<td>Quick sort(퀵 정렬)</td>
</tr>
<tr>
<td>O(n)</td>
<td>linear search(선형 탐색)</td>
</tr>
<tr>
<td>O(log n)</td>
<td>binary search(이진 탐색)</td>
</tr>
<tr>
<td>O(1)</td>
<td>-</td>
</tr>
</tbody></table>
<h2 id="big-ωomega"><strong>Big Ω(Omega)</strong></h2>
<ul>
<li>Big-O와 반대되는 개념으로 <strong>최선의 경우(실행 시간의 하한 = 제일 빠른 경우)에 대한 시간 복잡도</strong>를 나타내는 표현이다.</li>
</ul>
<table>
<thead>
<tr>
<th>표기</th>
<th>알고리즘 예시</th>
</tr>
</thead>
<tbody><tr>
<td>Ω(n^2)</td>
<td>selection sort(선택 정렬)</td>
</tr>
<tr>
<td>Ω(n log n)</td>
<td>merge sort(병합/합병 정렬)</td>
</tr>
<tr>
<td>Ω(n)</td>
<td>insertion sort(삽입 정렬),</td>
</tr>
<tr>
<td></td>
<td>bubble sort(거품 정렬)</td>
</tr>
<tr>
<td>Ω(log n)</td>
<td>-</td>
</tr>
<tr>
<td>Ω(1)</td>
<td>linear search(선형 탐색),</td>
</tr>
<tr>
<td></td>
<td>binary search(이진 탐색)</td>
</tr>
</tbody></table>
<h2 id="big-θtheta">Big θ(Theta)</h2>
<ul>
<li>알고리즘의 상한선과 하한선이 같을 때, 즉 <strong>평균에 대한 시간 복잡도</strong>를 나타내는 표현이다.</li>
</ul>
<table>
<thead>
<tr>
<th>표기</th>
<th>알고리즘 예시</th>
</tr>
</thead>
<tbody><tr>
<td>θ(n^2)</td>
<td>selection sort(선택 정렬)</td>
</tr>
<tr>
<td>θ(n log n)</td>
<td>merge sort(병합/합병 정렬)</td>
</tr>
<tr>
<td>θ(n)</td>
<td>-</td>
</tr>
<tr>
<td>θ(log n)</td>
<td>-</td>
</tr>
<tr>
<td>θ(1)</td>
<td>-</td>
</tr>
</tbody></table>
<h2 id="big-o-big-ωomega-big-θtheta-표기법-예시">Big O, Big Ω(Omega), Big θ(Theta) 표기법 예시</h2>
<ul>
<li><p><strong>탐색, 정렬, 자료구조, 메서드 별 예시</strong></p>
<ul>
<li><p><strong>탐색 알고리즘</strong></p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/4446d831-b203-41d4-9745-ae798c9b560c/%EC%8B%9C%EA%B0%84%EB%B3%B5%EC%9E%A1%EB%8F%84.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220627%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220627T075325Z&X-Amz-Expires=86400&X-Amz-Signature=99774356f50adf975b88c6d2b1cfb440f31602517784e03ca993eaaca034917c&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22%25EC%258B%259C%25EA%25B0%2584%25EB%25B3%25B5%25EC%259E%25A1%25EB%258F%2584.png%22&x-id=GetObject" alt="시간복잡도.png"></p>
</li>
<li><p><strong>정렬 알고리즘</strong></p>
<p>  <img src="https://user-images.githubusercontent.com/77854486/135040140-8a4750f9-65f8-43f4-bb65-c4c67cd8b123.png" alt="https://user-images.githubusercontent.com/77854486/135040140-8a4750f9-65f8-43f4-bb65-c4c67cd8b123.png"></p>
</li>
<li><p><strong>자료 구조, 메서드</strong></p>
<p>  <img src="https://user-images.githubusercontent.com/77854486/135039681-3e9cc7b4-1fc0-4f08-aff0-c2a7acc81da3.png" alt="https://user-images.githubusercontent.com/77854486/135039681-3e9cc7b4-1fc0-4f08-aff0-c2a7acc81da3.png"></p>
</li>
</ul>
</li>
</ul>
<h2 id="참고">참고</h2>
<p>- </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java | Lv1 신고 결과 받기]]></title>
            <link>https://velog.io/@im_hass_/JavaLv1-%EC%8B%A0%EA%B3%A0-%EA%B2%B0%EA%B3%BC-%EB%B0%9B%EA%B8%B0</link>
            <guid>https://velog.io/@im_hass_/JavaLv1-%EC%8B%A0%EA%B3%A0-%EA%B2%B0%EA%B3%BC-%EB%B0%9B%EA%B8%B0</guid>
            <pubDate>Sun, 26 Jun 2022 12:11:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>Lv1, Java, Failed</strong></p>
</blockquote>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/92334">문제 링크</a></p>
<h2 id="문제-풀이">문제 풀이</h2>
<ul>
<li>각 유저는 한 번에 한 명의 유저를 신고할 수 있다.</li>
<li>신고 횟수는 제한이 없고, 서로 다른 유저를 계속해서 신고할 수 있다.</li>
<li>동일한 유저가 신고한 것은 1회로 처리한다.</li>
<li>모든 신고내용을 취합하여 마지막에 처리한다.</li>
<li>k번 이상 신고된 유저는 게시판 이용이 정지된다.</li>
<li>id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 return한다.</li>
</ul>
<h2 id="주의-사항">주의 사항</h2>
<ul>
<li>자료 구조를 활용하면 쉽게 풀 수 있는 문제이다.</li>
<li>set을 사용해 동일한 유저가 신고한 것은 1번만 저장하도록 한다.</li>
</ul>
<h2 id="전체-코드">전체 코드</h2>
<pre><code class="language-java">import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

class Solution {
  public static int[] solution(String[] id_list, String[] report, int k) {
    int[] answer = new int[id_list.length];
    // id_list[] = 전체 유저 목록
    // report[] : &quot;신고유저 신고당한유저&quot;, ...
    // k : k번 이상 신고되면 정지

    Map&lt;String, HashSet&lt;String&gt;&gt; map = new HashMap&lt;&gt;(); // &lt;(key: 유저 id), (value: key를 신고한 사람(중복x))&gt;
    Map&lt;String, Integer&gt; idxMap = new HashMap&lt;&gt;(); // &lt;(key : 유저 id), (value: id_list에서 유저 index)&gt;

    // Map 초기화
    for (int i = 0; i &lt; id_list.length; i++) {
      String name = id_list[i];
      map.put(name, new HashSet&lt;&gt;()); // (유저 아이디, []) 추가
      idxMap.put(name, i); // (유저 아이디, 유저 인덱스) 추가
    }

    // 신고 기록 저장
    for (String s : report) {
      String[] str = s.split(&quot; &quot;); // [신고자 id, 신고한 id]
      String from = str[0]; // 신고자 id
      String to = str[1]; // 신고한 id
      map.get(to).add(from); // key(유저 id)를 찾아서 value(key를 신고한 사람)를 추가함.
    }

    // 이용 정지 메일 발송
    for (int i = 0; i &lt; id_list.length; i++) {
      HashSet&lt;String&gt; send = map.get(id_list[i]); // 해당 유저를 신고한 사람들의 정보
      if (send.size() &gt;= k) { // 해당 유저가 k번 이상 신고되었을 경우
        for (String name : send) {
          answer[idxMap.get(name)]++; // idxMap에서 해당 유저의 index를 가져와서 값을 증가
        }
      }
    }

    return answer;
  }
}</code></pre>
<h2 id="참고">참고</h2>
<ul>
<li><a href="https://jangcenter.tistory.com/116">https://jangcenter.tistory.com/116</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨팅 사고]]></title>
            <link>https://velog.io/@im_hass_/1.-%EC%BB%B4%ED%93%A8%ED%8C%85-%EC%82%AC%EA%B3%A0</link>
            <guid>https://velog.io/@im_hass_/1.-%EC%BB%B4%ED%93%A8%ED%8C%85-%EC%82%AC%EA%B3%A0</guid>
            <pubDate>Sat, 25 Jun 2022 14:24:21 GMT</pubDate>
            <description><![CDATA[<h2 id="1-2진법">1) 2진법</h2>
<blockquote>
<p><strong>핵심 단어</strong></p>
</blockquote>
<ul>
<li>컴퓨터 과학</li>
<li>2진법</li>
<li>비트</li>
<li>바이트</li>
</ul>
<blockquote>
<p><strong>컴퓨터 과학이란?</strong></p>
</blockquote>
<ul>
<li><strong>문제 해결(입력을 전달받아 출력을 만들어내는 과정)에 대한 학문.</strong></li>
<li>이러한 입력과 출력을 표현하기 위해, 약속(표준)이 필요하다. 따라서 <strong>컴퓨터 과학의 가장 첫 번째 개념</strong>은 어떻게 표현하는지에 대한 <strong>표현 방법</strong>이다.</li>
</ul>
<blockquote>
<p><strong>2진법</strong></p>
</blockquote>
<ul>
<li><p>0과 1로만 데이터를 표현하는 것.</p>
</li>
<li><p><strong>각 자리수가 2의 거듭제곱을 의미한다.</strong></p>
<p>  $011(2진법)$ = $0<em>4 + 0</em>2 + 0*1$</p>
</li>
</ul>
<blockquote>
<p><strong>비트(bit)</strong></p>
</blockquote>
<ul>
<li>컴퓨터에서 2진법 하나의 자릿수를 표현하는 단위.</li>
<li>컴퓨터에서는 트랜지스터를 사용해 표현.</li>
</ul>
<blockquote>
<p><strong>바이트(byte)</strong></p>
</blockquote>
<ul>
<li><p><strong>1byte(바이트) == 8개의 비트 == $2^8$ == 256bit(비트)</strong></p>
<ul>
<li>1킬로 바이트(KB) == 1000바이트(byte)</li>
<li>1메가 바이트(MB) == 1000킬로 바이트(KB) == 100만 바이트(byte)</li>
<li>1기가 바이트(GB) == 1000메가 바이트(MB) == 10억 바이트(byte)</li>
<li>1테라 바이트(TB) == 1000기가 바이트(GB) = 1조 바이트(byte)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/im_hass_/post/bb8e8059-0c2e-429b-bd18-8390343fded7/image.png" alt="데이터 용량 단위"></p>
</li>
</ul>
<br />

<h2 id="2-정보의-표현">2) 정보의 표현</h2>
<blockquote>
<p><strong>핵심 단어</strong></p>
</blockquote>
<ul>
<li>ASCII</li>
<li>유니코드</li>
<li>RGB</li>
</ul>
<blockquote>
<p><strong>ASCII(아스키코드, American Standard Code for Information Interchange)</strong></p>
</blockquote>
<ul>
<li>문자(기호)를 표현하는 방법.</li>
<li>128개의 부호로 정의되어 있다.</li>
<li>A == 65(아스키 코드(10진수)) == <strong>1000001</strong>(2진법)</li>
<li>a == 97(아스키 코드(10진수))
  <img src="https://velog.velcdn.com/images/im_hass_/post/4201719b-e198-451d-a91d-d2f0d3a9597e/image.png" alt="A~Z 아스키 코드 값"></li>
</ul>
<blockquote>
<p><strong>유니코드(Unicode)</strong></p>
</blockquote>
<ul>
<li><p>아스키코드로는 충분하지 않기 때문에 더 다양한 다른 문자들도 표현 가능하도록 지원하는 표준.</p>
<p>  이모티콘 까지 표현 가능.</p>
</li>
<li><p>😂(기쁨의 눈물) == 128,514(아스키코드(10진수)) == <strong>11111011000000010</strong>(2진법)</p>
</li>
</ul>
<blockquote>
<p><strong>RGB(Red, Green, Blue)</strong></p>
</blockquote>
<ul>
<li><p>스크린의 수많은 작은 점들은 빨간색, 초록색, 파란색을 띄고 있다. 이러한 작은 점을 <strong>픽셀</strong>이라고 부른다.</p>
</li>
<li><p><em>각각의 픽셀은 세 가지 색을 서로 다른 비율로 조합*</em>하여 특정한 색을 갖는다.</p>
</li>
<li><p><em>이 숫자들을 표현하는 방식을 RGB*</em>라고 한다.</p>
</li>
<li><p>노란색 이미지는 72, 73, 33으로 정의되는 무수히 많은 픽셀들의 RGB코드로 표현할 수 있다.</p>
</li>
<li><p>영상 또한 수많은 그림을 빠르게 연속적으로 이어 붙여 놓은 것이기 때문에 숫자로 표현할 수 있다.</p>
</li>
<li><p>음악도 각 음표를 숫자로 표현할 수 있다.</p>
</li>
</ul>
<br />

<h2 id="3-알고리즘">3) 알고리즘</h2>
<blockquote>
<p><strong>핵심 단어</strong></p>
</blockquote>
<ul>
<li>알고리즘</li>
<li>의사코드</li>
</ul>
<blockquote>
<p><strong>알고리즘(Algorithms)</strong></p>
</blockquote>
<ul>
<li><strong>입력에서 받은 자료를 출력 형태로 만드는 처리 과정.</strong></li>
<li>입력값을 출력값의 형태로 바꾸기 위해 어떤 명령어들이 수행되어야 하는지에 대한 <strong>규칙들의 순서적 나열</strong>.</li>
<li>이 일련의 순서적 규칙들을 어떻게 나열하는지에 따라 알고리즘의 종류가 달라진다.</li>
<li>알고리즘의 평가할 때는 <strong>정확성</strong>도 중요하지만, <strong>효율성</strong>도 중요하다.<ul>
<li>효율성은 작업을 완료하기까지 얼마나 시간과 노력을 덜 들일 수 있는지에 대한 것.</li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>의사코드</strong></p>
</blockquote>
<ul>
<li><p>컴퓨터가 수행할 작업을 프로그램 언어가 아니라 사람이 사용하는 언어로 알고리즘의 논리적 절차를 작성한 코드.</p>
</li>
<li><p>생각을 간결하게 정리한 코드와 비슷한 구문.</p>
</li>
<li><p>필요한 행동이나 조건을 잘 설정하여 컴퓨터가 수행해야 하는 일을 절차적으로 파악할 수 있게 도와준다.
<img src="https://velog.velcdn.com/images/im_hass_/post/4b05e35d-465a-499d-a156-343f4a5f964c/image.png" alt="의사코드 예시"></p>
</li>
<li><p><strong>함수(functions) :</strong>
<code>Pick up</code>, <code>Open to</code>, <code>Look at</code>, <code>Call</code>, <code>Quit</code>
함수는 컴퓨터에게 (이 경우 사람에게) 무엇을 할지 알려주는 동사와 같다.</p>
</li>
<li><p><strong>조건 :</strong>
<code>If</code>, <code>Else if</code>, <code>Else</code>
여러 선택지 중 하나를 고르는 것.</p>
</li>
<li><p><strong>불리언(Boolean) :</strong>
<code>Smith is on page</code>, <code>Smith is earlier in book</code>, <code>Smith is later in book</code>
답이 Yes(예)/No(아니오) 혹은 True(참)/False(거짓) 또는 2진법 0/1로 나오는 질문.</p>
</li>
<li><p><strong>루프(loop) :</strong>
<code>Go back to line 3</code>
뭔가를 계속해서 반복하는 순환.</p>
</li>
</ul>
<br />
]]></description>
        </item>
        <item>
            <title><![CDATA[Java, S4 | 1065번 한수]]></title>
            <link>https://velog.io/@im_hass_/Java-1065%EB%B2%88-%ED%95%9C%EC%88%98</link>
            <guid>https://velog.io/@im_hass_/Java-1065%EB%B2%88-%ED%95%9C%EC%88%98</guid>
            <pubDate>Thu, 23 Jun 2022 14:55:40 GMT</pubDate>
            <description><![CDATA[<h1 id="1065번-한수">1065번 한수</h1>
<blockquote>
<p>실버4, Java</p>
</blockquote>
<p><a href="https://www.acmicpc.net/problem/1065">문제 링크</a></p>
<h2 id="문제-풀이">문제 풀이</h2>
<ul>
<li><strong>한수 :</strong> 해당 정수의 각 자리가 등차수열을 이룰 경우</li>
<li><strong>등차수열 :</strong> 연속된 두 개의 수의 차이가 일정한 수열</li>
<li>N이 주어졌을 때, 1보다 크거나 같고, N보다 작거나 같은 한수의 개수를 출력</li>
<li>N이 1 ~ 1,000보다 작거나 같은 수이기 때문에 1000, 100, 10, 1의 자리일 경우로 나누어 검사하였다.</li>
</ul>
<h2 id="정답-코드">정답 코드</h2>
<pre><code class="language-java">import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//20분
//14204KB    120ms
public class Main_S4_1065_한수 {
  public static void main(String[] args) throws NumberFormatException, IOException {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    int N = Integer.parseInt(in.readLine());
    int res = 0; // 한수의 개수
    for (int i = 1; i &lt;= N; i++) { // 1 ~ N까지 한수인지 확인
      int X = i;
      if (X == 1000) { // X가 1000일 경우
        continue; // 등차수열 아님, 패스
      } else if (X &gt;= 100) { // X가 100의 자릿수일 경우
        int x100 = X / 100; // 100의 자릿값
        X %= 100;
        int x10 = X / 10; // 10의 자릿값
        X %= 10;
        int x1 = X; // 1의 자릿값
        if (x10 - x100 == x1 - x10) { // 각 자리가 등차수열일 경우
          res++;
        }
      } else if (X &gt;= 10) { // X가 10의 자릿수일 경우
        res++;
      } else { // X가 1의 자릿수일 경우
        res++;
      }
    }

    System.out.println(res);
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level2. 타겟넘버]]></title>
            <link>https://velog.io/@im_hass_/Javascript-Level2.-%ED%83%80%EA%B2%9F%EB%84%98%EB%B2%84</link>
            <guid>https://velog.io/@im_hass_/Javascript-Level2.-%ED%83%80%EA%B2%9F%EB%84%98%EB%B2%84</guid>
            <pubDate>Thu, 04 Nov 2021 13:35:59 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a><br><a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a><br><a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a><br><a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a>  </p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="타겟-넘버">타겟 넘버</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/43165">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p>n개의 음이 아닌 정수가 있습니다. 이 수를 적절히 더하거나 빼서 타겟 넘버를 만들려고 합니다. 예를 들어 [1, 1, 1, 1, 1]로 숫자 3을 만들려면 다음 다섯 방법을 쓸 수 있습니다.</p>
<pre><code class="language-jsx">-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3</code></pre>
<p>사용할 수 있는 숫자가 담긴 배열 numbers, 타겟 넘버 target이 매개변수로 주어질 때 숫자를 적절히 더하고 빼서 타겟 넘버를 만드는 방법의 수를 return 하도록 solution 함수를 작성해주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>주어지는 숫자의 개수는 2개 이상 20개 이하입니다.</li>
<li>각 숫자는 1 이상 50 이하인 자연수입니다.</li>
<li>타겟 넘버는 1 이상 1000 이하인 자연수입니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>numbers</th>
<th>target</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>[1, 1, 1, 1, 1]</td>
<td>3</td>
<td>5</td>
</tr>
</tbody></table>
<hr>
<h3 id="분류">분류</h3>
<ul>
<li>완전 탐색</li>
</ul>
<p><br><br></p>
<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>numbers를 이용해 만들 수 있는 모든 값을 탐색하고, 그 중 target 값과 일치할 때 count를 센다.</p>
</blockquote>
<ol>
<li>배열로 만들 수 있는 모든 경우의 수를 탐색한다.
매개 변수로 탐색할 배열, 목표값, 인덱스 값, 누적할 값을 넘긴다.</li>
</ol>
<pre><code class="language-jsx">function dfs(numbers, target, index, total) {
  // numbers : 탐색할 배열
  // target : 목표값
  // index : 1씩 증가하며 numbers의 값을 탐색한다.
  // total : 누적 계산 값, 값을 +하거나 -한다.
}</code></pre>
<ol start="2">
<li>재귀의 종료 조건은 numbers를 끝까지 탐색했을 때이다.
그때 target과 total이 같으면 1을 반환하여 count를 증가 시킨다.</li>
</ol>
<pre><code class="language-jsx">function dfs(numbers, target, index, total) {
  if(numbers.length === index) {
    return target === total ? 1 : 0;
  }
}</code></pre>
<ol start="3">
<li><p>경우의 수를 탐색한다. 2가지 경우가 있다.</p>
<ul>
<li><p>이전 값에 값을 새로운 값을 더하는 경우</p>
</li>
<li><p>이전 값에 값을 새로운 값을 빼는 경우</p>
<p>target과 같거나 다를 때, 값을 반환 받을 count 변수를 만들고 재귀를 돌며 개수를 누적 해준다.</p>
<p>재귀를 돌 때마다 index를 증가 시켜 주고, 이전 값에 다음 값(<code>numbers[index]</code>)을 더하는 경우와 빼는 경우를 탐색한다.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="language-jsx">function dfs(numbers, target, index, total) {
  // 생략...

  let count = 0;

  count += dfs(numbers, target, index + 1, total + numbers[index]);
  count += dfs(numbers, target, index + 1, total - numbers[index]);

  return count;
}</code></pre>
<br>

<h2 id="제출">제출</h2>
<pre><code class="language-jsx">function dfs(numbers, target, index, total) {
  // numbers : 탐색할 배열
  // target : 목표값
  // index : 1씩 증가하며 numbers의 값을 탐색한다.
  // total : 누적 계산 값, 값을 +하거나 -한다.
  // 종료 조건은 numbers를 끝까지 탐색했을 때이고, 그때 target과 total이 같으면 count를 증가한다.

  if(numbers.length === index) {
    return target === total ? 1 : 0;
  }

  let count = 0;

  count += dfs(numbers, target, index + 1, total + numbers[index]);
  count += dfs(numbers, target, index + 1, total - numbers[index]);

  return count;
}

function solution(numbers, target) {
  // 모든 경우의 수를 탐색하여, 값이 target이 되었을 때 count++, 종료되면 count 반환
  return dfs(numbers, target, 0, 0);
}</code></pre>
<p><br><br></p>
<h1 id="3-결과">3. 결과</h1>
<pre><code class="language-jsx">테스트 1 〉    통과 (25.59ms, 32.1MB)
테스트 2 〉    통과 (17.70ms, 32.1MB)
테스트 3 〉    통과 (0.22ms, 30.3MB)
테스트 4 〉    통과 (1.77ms, 31.7MB)
테스트 5 〉    통과 (2.43ms, 32MB)
테스트 6 〉    통과 (0.39ms, 30.3MB)
테스트 7 〉    통과 (0.34ms, 30MB)
테스트 8 〉    통과 (2.54ms, 32MB)</code></pre>
<p><strong>- 정확성 :</strong> 100.0
<strong>- 합계 :</strong> 100.0 / 100.0</p>
<p><br><br></p>
<h1 id="4-참고">4. 참고</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level2. 행렬의 곱셈]]></title>
            <link>https://velog.io/@im_hass_/Level2.-%ED%96%89%EB%A0%AC%EC%9D%98-%EA%B3%B1%EC%85%88</link>
            <guid>https://velog.io/@im_hass_/Level2.-%ED%96%89%EB%A0%AC%EC%9D%98-%EA%B3%B1%EC%85%88</guid>
            <pubDate>Tue, 02 Nov 2021 08:11:20 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a>
<a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a>
<a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a>
<a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a></p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="행렬의-곱셈">행렬의 곱셈</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/12949">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p>2차원 행렬 arr1과 arr2를 입력받아, arr1에 arr2를 곱한 결과를 반환하는 함수, solution을 완성해주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>행렬 arr1, arr2의 행과 열의 길이는 2 이상 100 이하입니다.</li>
<li>행렬 arr1, arr2의 원소는 -10 이상 20 이하인 자연수입니다.</li>
<li>곱할 수 있는 배열만 주어집니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>arr1</th>
<th>arr2</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>[[1, 4], [3, 2], [4, 1]]</td>
<td>[[3, 3], [3, 3]]</td>
<td>[[15, 15], [15, 15], [15, 15]]</td>
</tr>
<tr>
<td>[[2, 3, 2], [4, 2, 4], [3, 1, 4]]</td>
<td>[[5, 4, 3], [2, 4, 1], [3, 1, 1]]</td>
<td>[[22, 22, 11], [36, 28, 18], [29, 20, 14]]</td>
</tr>
</tbody></table>
<br>
<br>

<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>arr1과 arr2를 이용하여 행렬 곱셈을 수행한다.</p>
</blockquote>
<p>행렬의 곱셈은 아래와 같이 2X3, 3X2 배열이 예시로 있을 경우</p>
<ul>
<li><p>배열1</p>
<table>
<thead>
<tr>
<th>2X3</th>
<th>[0]</th>
<th>[1]</th>
<th>[2]</th>
</tr>
</thead>
<tbody><tr>
<td>[0]</td>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
<tr>
<td>[1]</td>
<td>d</td>
<td>e</td>
<td>f</td>
</tr>
</tbody></table>
</li>
<li><p>배열2</p>
<table>
<thead>
<tr>
<th>3X2</th>
<th>[0]</th>
<th>[1]</th>
</tr>
</thead>
<tbody><tr>
<td>[0]</td>
<td>A</td>
<td>D</td>
</tr>
<tr>
<td>[1]</td>
<td>B</td>
<td>E</td>
</tr>
<tr>
<td>[2]</td>
<td>C</td>
<td>F</td>
</tr>
</tbody></table>
</li>
</ul>
<p>다음과 같이 계산한다.</p>
<table>
<thead>
<tr>
<th>2X2</th>
<th>[0]</th>
<th>[1]</th>
</tr>
</thead>
<tbody><tr>
<td>[0]</td>
<td>aA + bB + cC</td>
<td>aD + aE + aF</td>
</tr>
<tr>
<td>[1]</td>
<td>dA + eB + fC</td>
<td>dD + eE + fF</td>
</tr>
</tbody></table>
<p>결과로 나오는 행렬은 (배열1의 세로(행) 길이 X 배열2의 가로(열) 길이) 크기로 생성된다.</p>
<ol>
<li>우선 행렬의 결과를 담을 2차원 배열(<code>answer</code>)을 초기화 해준다.</li>
</ol>
<pre><code class="language-jsx">let answer = new Array(arr1.length);

for(let i = 0; i &lt; answer.length; i++) {
  answer[i] = new Array(arr2[0].length).fill(0);
}</code></pre>
<ol start="2">
<li><p>반복되어야 하는 순서가 중요하다. </p>
<p> 우선 반복되어야 하는 것은 다음과 같다.</p>
<ul>
<li><p>arr1의 세로 ⇒ arr1 한 줄씩</p>
</li>
<li><p>arr2의 가로 ⇒ arr2 한 줄씩, 각각의 내용</p>
</li>
<li><p>arr1의 가로 ⇒ arr1 한 줄씩, 각각의 내용</p>
<p>첫 번째 반복문(<code>i</code>)은 arr1의 세로 인덱스를 제어할 수 있고</p>
<p>두 번째 반복문(<code>j</code>)은 arr2의 가로 인덱스를 제어할 수 있다.</p>
<p>그렇다면 마지막으로 arr1의 가로 인덱스와 arr2의 세로 인덱스를 제어해 줄 반복문(<code>k</code>)을 하나 더 추가한다.</p>
<p>arr1 가로 길이와 arr2 세로 길이가 같아야 식이 성립할 수 있는데, 제한 조건으로 항상 계산할 수 있는 식이 오기 때문에 따로 처리할 필요는 없다.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="language-jsx">for(let i = 0; i &lt; arr1.length; i++) { // arr1의 세로만큼 반복 : answer의 세로, arr1의 세로 인덱스 제어
  for(let j = 0; j &lt; arr2[0].length; j++) { // arr2의 가로만큼 반복 : answer의 가로, arr2의 가로 인덱스 제어
    for(let k = 0; k &lt; arr1[0].length; k++) { // arr1의 가로만큼 반복 : arr1의 가로, arr2의 세로 인덱스 제어
      answer[i][j] = &quot;계산한 값&quot;;
    }
  }
}</code></pre>
<ol start="3">
<li><p>arr1의 가로와 arr2의 세로를 제어하기 위해서 k를 이용한다.</p>
<p> 앞서 말했듯이, 각각이 제어할 수 있는 인덱스가 정해져 있다.</p>
<ul>
<li><p><code>i</code> : arr1의 세로 인덱스</p>
</li>
<li><p><code>j</code> : arr2의 가로 인덱스</p>
</li>
<li><p><code>k</code> : arr1의 가로, arr2의 세로 인덱스</p>
<p>그대로 식에 넣기만 하면 된다.</p>
<p><code>answer[i][j]</code>에 계속 더해주는 이유는 아래 예시에서 알 수 있다.</p>
<p><code>answer[0][0]</code>에 저장되는 값은 <code>arr1[0][0] * arr2[0][0]</code>, <code>arr1[0][1] * arr2[1][0]</code>, <code>arr1[0][2] * arr2[2][0]</code> 이 세 가지 값을 더한 값이기 때문이다.</p>
</li>
</ul>
</li>
</ol>
<pre><code class="language-jsx">answer[i][j] += arr1[i][k] * arr2[k][j];

// 계산 예시
// answer[0][0] = 
// 1:    (arr1[0][0] * arr2[0][0]) + 
// 2:    (arr1[0][1] * arr2[1][0]) + 
// 3:    (arr1[0][2] * arr2[2][0]);

// answer[0][1] = 
//    (arr1[0][0] * arr2[0][1]) + 
//    (arr1[0][1] * arr2[1][1]) + 
//    (arr1[0][2] * arr2[2][1]);

// answer[1][0] = 
//    (arr1[1][0] * arr2[0][0]) + 
//    (arr1[1][1] * arr2[1][0]) + 
//    (arr1[1][2] * arr2[2][0]);

// answer[1][1] = 
//    (arr1[1][0] * arr2[0][1]) + 
//    (arr1[1][1] * arr2[1][1]) + 
//    (arr1[1][2] * arr2[2][1]);</code></pre>
<br>

<h2 id="제출">제출</h2>
<pre><code class="language-jsx">function solution(arr1, arr2) {
  let row1 = arr1.length;
  let col1 = arr1[0].length;
  let col2 = arr2[0].length;

  let answer = new Array(arr1.length);

  for(let i = 0; i &lt; answer.length; i++) {
    answer[i] = new Array(arr2[0].length).fill(0);
  }

  // let count = 0;

  for(let i = 0; i &lt; row1; i++) { // arr1의 세로만큼 반복 : answer의 세로, arr1의 세로 인덱스 제어
    for(let j = 0; j &lt; col2; j++) { // arr2의 가로만큼 반복 : answer의 가로, arr2의 가로 인덱스 제어
      for(let k = 0; k &lt; col1; k++) { // arr1의 가로만큼 반복 : arr1의 가로, arr2의 세로 인덱스 제어
        answer[i][j] += arr1[i][k] * arr2[k][j];
        // console.log(`arr1[${i}][${k}] : ${arr1[i][k]}`);
        // console.log(`arr2[${k}][${j}] : ${arr2[k][j]}`);
        // console.log(`answer[${i}][${j}] : ${answer[i][j]}`);
        // count += 1;
      }

      // console.log();
    }

    // console.log();
  }

  // console.log(&quot;전체 계산 횟수&quot;, count);

  return answer;
}</code></pre>
<br>

<h2 id="다른-사람의-풀이-및-해석">다른 사람의 풀이 및 해석</h2>
<pre><code class="language-jsx">function solution(arr1, arr2) {
  return arr1.map((row) =&gt; // arr1의 세로 반복
    arr2[0].map((x, y) =&gt; // arr2의 가로 반복
      // reduce(콜백 함수, 초기값)
      row.reduce(
        (a, b, c) =&gt; {
          return a + b * arr2[c][y];
        }, 0)
        // 콜백으로 arr1의 가로 요소 반복
          // a : 누적 값
          // b : arr1의 가로 요소
          // c : arr2 세로 인덱스 제어
          // =&gt; b * arr2[c][y] : 계산한 값
    )
  );
}</code></pre>
<br>
<br>

<h1 id="3-결과">3. 결과</h1>
<hr>
<pre><code class="language-jsx">테스트 1 〉    통과 (3.37ms, 33.3MB)
테스트 2 〉    통과 (6.23ms, 34.4MB)
테스트 3 〉    통과 (7.45ms, 34.8MB)
테스트 4 〉    통과 (3.30ms, 33.1MB)
테스트 5 〉    통과 (6.61ms, 34.6MB)
테스트 6 〉    통과 (7.50ms, 34.3MB)
테스트 7 〉    통과 (1.67ms, 30.5MB)
테스트 8 〉    통과 (0.44ms, 30.7MB)
테스트 9 〉    통과 (0.37ms, 30.6MB)
테스트 10 〉    통과 (5.81ms, 34.1MB)
테스트 11 〉    통과 (3.44ms, 33.1MB)
테스트 12 〉    통과 (0.47ms, 30.6MB)
테스트 13 〉    통과 (7.29ms, 34.2MB)
테스트 14 〉    통과 (7.61ms, 34.5MB)
테스트 15 〉    통과 (4.39ms, 32.9MB)
테스트 16 〉    통과 (5.48ms, 33.6MB)</code></pre>
<p><strong>- 정확성 :</strong> 100.0</p>
<p><strong>- 합계 :</strong> 100.0 / 100.0</p>
<br>
<br>

<h1 id="4-참고">4. 참고</h1>
<hr>
<ul>
<li><a href="https://velog.io/@sso/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-JavaScript-%ED%96%89%EB%A0%AC%EC%9D%98-%EA%B3%B1%EC%85%88">행렬의 곱셈</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level2. 피보나치 수]]></title>
            <link>https://velog.io/@im_hass_/Level2.-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98</link>
            <guid>https://velog.io/@im_hass_/Level2.-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98</guid>
            <pubDate>Tue, 02 Nov 2021 08:05:47 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a><br><a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a><br><a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a><br><a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a>  </p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="피보나치-수">피보나치 수</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/12945">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p>피보나치 수는 F(0) = 0, F(1) = 1일 때, 1 이상의 n에 대하여 F(n) = F(n-1) + F(n-2) 가 적용되는 수 입니다.</p>
<p>예를들어</p>
<ul>
<li>F(2) = F(0) + F(1) = 0 + 1 = 1</li>
<li>F(3) = F(1) + F(2) = 1 + 1 = 2</li>
<li>F(4) = F(2) + F(3) = 1 + 2 = 3</li>
<li>F(5) = F(3) + F(4) = 2 + 3 = 5</li>
</ul>
<p>와 같이 이어집니다.</p>
<p>2 이상의 n이 입력되었을 때, n번째 피보나치 수를 1234567으로 나눈 나머지를 리턴하는 함수, solution을 완성해 주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>n은 2 이상 100,000 이하인 자연수입니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>n</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td>5</td>
<td>5</td>
</tr>
</tbody></table>
<h3 id="입출력-예-설명">입출력 예 설명</h3>
<p>피보나치수는 0번째부터 0, 1, 1, 2, 3, 5, ... 와 같이 이어집니다.</p>
<hr>
<h3 id="분류">분류</h3>
<ul>
<li>다이나믹 프로그래밍</li>
</ul>
<p><br><br></p>
<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>다이나믹 프로그래밍을 이용하여 계산 결과를 memoization한다.</p>
</blockquote>
<p>피보나치 수열을 구현하는 방법에는 크게 3가지가 있다.</p>
<ol>
<li>재귀</li>
<li>동적 프로그래밍(top-down, bottom-up)</li>
<li>반복문</li>
</ol>
<p>해당 문제는 동적 프로그래밍 bottom-up 방식을 사용하여 해결할 수 있다.</p>
<h3 id="주의할-점">주의할 점</h3>
<ol>
<li><p>시간 초과</p>
<ul>
<li>처음에는 일반적인 재귀로 문제를 풀었는데, 테스트 케이스 7번부터 시간 초과가 발생한다.</li>
<li>다음으로는 동적 프로그래밍 top-down 방식으로 문제를 풀었는데, top-down 방식도 재귀를 이용한 것이므로 시간 초과가 발생하였다.</li>
<li>마지막으로 동적 프로그래밍 bottom-up 방식을 이용하여 문제를 해결하였다.</li>
</ul>
</li>
<li><p><code>1234567</code>으로 나누는 위치</p>
<ul>
<li><p>동적 프로그래밍 bottom-up 방식을 이용했는데, 최종 반환할 때 나머지 연산을 하였더니 테스트 케이스 7번부터 실패가 발생한다.</p>
<p>  실패하는 이유는 for문으로 피보나치 수열을 계산하는 와중에, 결과가 자료형의 크기를 초과하여 정확한 값을 계산하지 못하기 때문이다.</p>
<p>  그러므로 계산을 한 결과에 바로바로 나머지 연산을 해준 값을 저장하면 자료형을 초과하지 않은 계산 결과가 출력될 수 있다.</p>
</li>
</ul>
</li>
</ol>
<br>

<h3 id="제출">제출</h3>
<pre><code class="language-jsx">// // 재귀: 실패
// function fibo(n) {
//     if(n === 0) return 0;
//     if(n === 1) return 1;
//     return fibo(n - 1) + fibo(n - 2);
// }

// // 동적 계획법(top-down): 실패
// function fibo(n, d = []) {
//     if(n &lt; 2) return n;
//     if(d[n]) return d[n];

//     d[n] = fibo(n - 1) + fibo(n - 2);

//     return d[n] % 1234567;
// }

function solution(n) {
    let arr = [0, 1];

    // 동적 계획법(bottom-up): 성공
    for(let i = 2; i &lt;= n; i++) {
        arr[i] = (arr[i - 1] + arr[i - 2]) % 1234567; // 나누는 위치 주의
    }

    return arr[n];
}</code></pre>
<p><br><br></p>
<h1 id="3-채점-결과">3. 채점 결과</h1>
<pre><code class="language-jsx">테스트 1 〉    통과 (0.05ms, 29.2MB)
테스트 2 〉    통과 (0.05ms, 30.3MB)
테스트 3 〉    통과 (0.04ms, 30.1MB)
테스트 4 〉    통과 (0.04ms, 29MB)
테스트 5 〉    통과 (0.04ms, 30.3MB)
테스트 6 〉    통과 (0.04ms, 30.2MB)
테스트 7 〉    통과 (0.25ms, 30MB)
테스트 8 〉    통과 (0.10ms, 30.3MB)
테스트 9 〉    통과 (0.07ms, 30.3MB)
테스트 10 〉    통과 (0.15ms, 30.4MB)
테스트 11 〉    통과 (0.11ms, 30.3MB)
테스트 12 〉    통과 (0.12ms, 30MB)
테스트 13 〉    통과 (4.72ms, 34.3MB)
테스트 14 〉    통과 (4.51ms, 34.6MB)</code></pre>
<ul>
<li><strong>정확성 :</strong> 100.0</li>
<li><strong>합계 :</strong> 100.0 / 100.0</li>
</ul>
<p><br><br></p>
<h1 id="4-참고">4. 참고</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level2. 소수 찾기]]></title>
            <link>https://velog.io/@im_hass_/Level2.-%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@im_hass_/Level2.-%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Tue, 02 Nov 2021 07:59:49 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a>
<a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a>
<a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a>
<a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a></p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="소수-찾기">소수 찾기</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/42839">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p>한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.</p>
<p>각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>numbers는 길이 1 이상 7 이하인 문자열입니다.</li>
<li>numbers는 0~9까지 숫자만으로 이루어져 있습니다.</li>
<li>&quot;013&quot;은 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>numbers</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>&quot;17&quot;</td>
<td>3</td>
</tr>
<tr>
<td>&quot;011&quot;</td>
<td>2</td>
</tr>
</tbody></table>
<h3 id="입출력-예-설명">입출력 예 설명</h3>
<p><strong>입출력 예 #1</strong></p>
<p>[1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다.</p>
<p><strong>입출력 예 #2</strong></p>
<p>[0, 1, 1]으로는 소수 [11, 101]를 만들 수 있습니다.</p>
<ul>
<li>11과 011은 같은 숫자로 취급합니다.</li>
</ul>
<hr>
<h3 id="분류">분류</h3>
<ul>
<li>완전 탐색</li>
<li>DFS</li>
</ul>
<br>
<br>

<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>종이 조각으로 만들 수 있는 모든 경우의 수를 탐색하고, 그중 소수를 찾아서 개수를 세면 된다.</p>
</blockquote>
<p>소수는 1과 자기 자신으로만 나누어지는 수이다.</p>
<ol>
<li><p>numbers가 문자열로 들어오므로, 한 문자씩 분리해서 배열에 저장해준다.</p>
</li>
<li><p>만들 수 있는 모든 경우를 완전 탐색한다.</p>
<p> 재귀를 사용하여 구현할 수 있다.</p>
<p> 매개 변수로 아래 값들을 전달한다.</p>
<ul>
<li><code>set</code> : 값 저장에 사용.</li>
<li><code>arr</code> : 고정된 문자열을 제외한 값이 담긴 배열.</li>
<li><code>fixed</code> : 고정된 문자열(각각의 경우에 해당).</li>
</ul>
</li>
<li><p>탐색하며 만들어낸 숫자가 소수일 경우 Set에 저장한다.</p>
<p> 소수임을 확인하는 함수를 만들어 검사한다.</p>
</li>
<li><p>Set에 저장된 값의 개수가 즉, 만들 수 있는 소수의 개수이다.</p>
</li>
</ol>
<h3 id="주의할-점">주의할 점</h3>
<ul>
<li><p><strong>중복은 제외되는 것에 주의.</strong></p>
<p>  11과 011은 같은 숫자로 취급한다.</p>
<p>  Set을 이용하면 중복되는 값은 한 번만 저장한다.</p>
</li>
<li><p><strong>문자형 자료를 사용해 완전 탐색하는 것에 주의</strong></p>
<p>  소수 검사를 하거나 값을 저장할 때, 정수로 형변환이 필요하다.</p>
<p>  소수 검사는 자동 형 변환이 되기 때문에 괜찮을 수 있어도 값을 저장할 때 문자열로 저장하면, &quot;011&quot;, &quot;11&quot; 상태로 저장되기 때문에 중복이 발생해 버린다.</p>
</li>
</ul>
<br>

<h2 id="제출">제출</h2>
<pre><code class="language-jsx">function isPrime(n) {
    if (n &lt; 2) return false;
    for (let i = 2; i &lt;= Math.sqrt(n); i++) {
        if (n % i === 0) return false;
    }
    return true;
}

function dfs(set, arr, fixed) {
    if (arr.length &gt;= 1) {
        for (let i = 0; i &lt; arr.length; i++) {
            let newFixed = fixed + arr[i];
            let copyArr = [...arr];
            copyArr.splice(i, 1);

            if (isPrime(parseInt(newFixed))) {
                set.add(parseInt(newFixed));
            }

            dfs(set, copyArr, newFixed);
        }
    }
}

function solution(numbers) {
    let nums = numbers.split(&quot;&quot;);
    let set = new Set();

    dfs(set, nums, &#39;&#39;);

    console.log(set);

    return set.size;
}</code></pre>
<br>

<br>

<h1 id="3-결과">3. 결과</h1>
<hr>
<pre><code class="language-jsx">테스트 1 〉    통과 (4.62ms, 30.3MB)
테스트 2 〉    통과 (7.83ms, 33MB)
테스트 3 〉    통과 (4.61ms, 30.4MB)
테스트 4 〉    통과 (6.91ms, 32.1MB)
테스트 5 〉    통과 (11.95ms, 33.7MB)
테스트 6 〉    통과 (4.60ms, 30.2MB)
테스트 7 〉    통과 (4.84ms, 30.4MB)
테스트 8 〉    통과 (12.34ms, 33.7MB)
테스트 9 〉    통과 (4.66ms, 30.3MB)
테스트 10 〉    통과 (10.11ms, 33.2MB)
테스트 11 〉    통과 (8.66ms, 32.4MB)
테스트 12 〉    통과 (4.78ms, 30.3MB)</code></pre>
<p><strong>- 정확성 :</strong> 100.0</p>
<p><strong>- 합계 :</strong> 100.0 / 100.0</p>
<br>

<br>

<h1 id="4-참고">4. 참고</h1>
<hr>
<ul>
<li><a href="https://sumin-k.medium.com/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-javascript-%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0-1fdcdca4f59b">https://sumin-k.medium.com/알고리즘-javascript-완전-탐색-소수-찾기-1fdcdca4f59b</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level2. 124 나라의 숫자]]></title>
            <link>https://velog.io/@im_hass_/Level2.-124-%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90</link>
            <guid>https://velog.io/@im_hass_/Level2.-124-%EB%82%98%EB%9D%BC%EC%9D%98-%EC%88%AB%EC%9E%90</guid>
            <pubDate>Tue, 02 Nov 2021 07:51:25 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a>
<a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a>
<a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a>
<a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a></p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="124-나라의-숫자">124 나라의 숫자</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/12899">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p>124 나라가 있습니다. 124 나라에서는 10진법이 아닌 다음과 같은 자신들만의 규칙으로 수를 표현합니다.</p>
<ol>
<li>124 나라에는 자연수만 존재합니다.</li>
<li>124 나라에는 모든 수를 표현할 때 1, 2, 4만 사용합니다.</li>
</ol>
<p>예를 들어서 124 나라에서 사용하는 숫자는 다음과 같이 변환됩니다.</p>
<table>
<thead>
<tr>
<th>10진법</th>
<th>124 나라</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>4</td>
<td>11</td>
</tr>
<tr>
<td>5</td>
<td>12</td>
</tr>
<tr>
<td>6</td>
<td>14</td>
</tr>
<tr>
<td>7</td>
<td>21</td>
</tr>
<tr>
<td>8</td>
<td>22</td>
</tr>
<tr>
<td>9</td>
<td>24</td>
</tr>
<tr>
<td>10</td>
<td>41</td>
</tr>
</tbody></table>
<p>자연수 n이 매개변수로 주어질 때, n을 124 나라에서 사용하는 숫자로 바꾼 값을 return 하도록 solution 함수를 완성해 주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>n은 500,000,000이하의 자연수 입니다.</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>n</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>4</td>
<td>11</td>
</tr>
</tbody></table>
<br>
<br>

<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>10진법을 3진법으로 변환하는데, 나머지가 0일 때만 계산이 달라진다.</p>
</blockquote>
<p>10진법, 3진법, 124 나라 간의 변환이다.</p>
<table>
<thead>
<tr>
<th>10진법</th>
<th>3진법</th>
<th>124나라</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>10</td>
<td>4</td>
</tr>
<tr>
<td>4</td>
<td>11</td>
<td>11</td>
</tr>
<tr>
<td>5</td>
<td>12</td>
<td>12</td>
</tr>
<tr>
<td>6</td>
<td>20</td>
<td>14</td>
</tr>
<tr>
<td>7</td>
<td>21</td>
<td>21</td>
</tr>
<tr>
<td>8</td>
<td>22</td>
<td>22</td>
</tr>
<tr>
<td>9</td>
<td>100</td>
<td>24</td>
</tr>
<tr>
<td>10</td>
<td>101</td>
<td>41</td>
</tr>
</tbody></table>
<p>위 표에서 알 수 있듯이, 나머지가 0일 때를 제외하곤 3진법과 동일하게 변경된다.</p>
<p>나머지가 0으로 나누어질 때, 몫을 -1 하고 나머지는 4가 되면 제대로 값이 나온다.</p>
<ol>
<li>우선 10진법을 3진법으로 변환하는 것을 구현한다.
 나머지는 먼저 나온 나머지가 나중에 출력 되어야 하므로 배열에 저장해두고 <code>reverse()</code> 메서드를 사용하여 뒤에서부터 출력해주었다.
계산이 끝나고 n이 0이 아닐 때는 출력 되도록 배열에 추가하였다.</li>
</ol>
<pre><code class="language-jsx">  function solution(n) {
    let value = 0;
    let reminder = 0;
    let answer = [];

    while(n &gt; 1) {
      value = Math.floor(n / 3);
      reminder = n % 3;

      answer.push(reminder);

      n = Math.floor(n / 3);
    }

    if(n &gt; 0) answer.push(n);

    return answer.reverse().join(&quot;&quot;);
  }</code></pre>
<ol start="2">
<li>여기서 이제 n을 3으로 나누었을 때, 나머지가 0인 경우만 처리해주면 된다.</li>
</ol>
<pre><code class="language-jsx">function solution(n) {
  let value = 0;
  let reminder = 0;
  let answer = [];

  while(n &gt; 1) {
    value = Math.floor(n / 3);
    reminder = n % 3;

    **if(reminder === 0) {
      n -= 1;
      reminder = 4;
    }**

      answer.push(reminder);

    n = Math.floor(n / 3);
  }

  if(n &gt; 0) answer.push(n);

  return answer.reverse().join(&quot;&quot;);
}</code></pre>
<br>

<h2 id="제출">제출</h2>
<pre><code class="language-jsx">function solution(n) {
  let answer = [];
  let value = 0;
  let reminder = 0;

  while(n &gt; 1) {
    value = Math.floor(n / 3);
    reminder = n % 3;

    if(reminder === 0) {
      n -= 1;
      reminder = 4;
    }

    answer.push(reminder);

    n = Math.floor(n / 3);
  }

  if(n &gt; 0) answer.push(n);

  return answer.reverse().join(&quot;&quot;);
}</code></pre>
<br>

<h2 id="다른-사람의-풀이-및-해석">다른 사람의 풀이 및 해석</h2>
<pre><code class="language-jsx">function change124(n) {
  return n === 0 ? &#39;&#39; : change124(parseInt((n - 1) / 3)) + [1, 2, 4][(n - 1) % 3];
}</code></pre>
<p>재귀를 사용하여 구현하였다.</p>
<p>나는 n이 0보다 클 때 출력을 해주었는데, 여기선 삼항 연산자를 사용하여 0일 때 출력을 안 하는 것으로 하였다.</p>
<p>그리고 n을 3으로 나눌 때, (n - 1)을 해주는 것은 n을 나눈 &quot;몫&quot;은 -1을 해도 같은 값이 나오기 때문이다.</p>
<p>예를 들어 n = 13일 경우, <code>13 / 3 ⇒ 4</code> == <code>12 / 3 ⇒ 4</code> == <code>14 / 3 ⇒ 4</code> 동일하다.</p>
<p>마지막으로 몫 뒤에 나머지 값들을 붙여준다.</p>
<p>나머지 값은 [1, 2, 4] 배열에서 (n - 1) % 3의 인덱스에 있는 숫자가 나오게 된다. 여기서 -1을 해주는 이유는 인덱스가 0부터 시작하기 때문이다.</p>
<ul>
<li>n = 10인 경우 아래와 같다.<br>몫 : 10 ⇒ (10 - 1) / 3 ⇒ 3<br>  (재귀) 3 ⇒ (3 - 1) / 3 ⇒ 0 ⇒ &#39;&#39;<br>나머지 : 10 ⇒ (10 - 1) % 3 ⇒ 0 ⇒ &#39;&#39;<br>  (재귀) 3 ⇒ (3 - 1) % 3 ⇒ 2 ⇒ 4  </li>
</ul>
<br>
<br>

<h1 id="3-결과">3. 결과</h1>
<hr>
<pre><code class="language-jsx">정확성  테스트
테스트 1 〉    통과 (0.05ms, 30.3MB)
테스트 2 〉    통과 (0.05ms, 30.2MB)
테스트 3 〉    통과 (0.06ms, 30.1MB)
테스트 4 〉    통과 (0.07ms, 30.1MB)
테스트 5 〉    통과 (0.06ms, 30.2MB)
테스트 6 〉    통과 (0.06ms, 30.2MB)
테스트 7 〉    통과 (0.08ms, 30.2MB)
테스트 8 〉    통과 (0.05ms, 30.3MB)
테스트 9 〉    통과 (0.06ms, 29.8MB)
테스트 10 〉    통과 (0.08ms, 30.2MB)
테스트 11 〉    통과 (0.14ms, 30.2MB)
테스트 12 〉    통과 (0.06ms, 29.9MB)
테스트 13 〉    통과 (0.06ms, 30.2MB)
테스트 14 〉    통과 (0.10ms, 30.1MB)

효율성  테스트
테스트 1 〉    통과 (0.08ms, 30.1MB)
테스트 2 〉    통과 (0.08ms, 30.2MB)
테스트 3 〉    통과 (0.06ms, 30.1MB)
테스트 4 〉    통과 (0.09ms, 30.2MB)
테스트 5 〉    통과 (0.09ms, 29.9MB)
테스트 6 〉    통과 (0.09ms, 30.1MB)</code></pre>
<p><strong>- 정확성 :</strong> 70.0
<strong>- 효율성 :</strong> 30.0</p>
<p><strong>- 합계 :</strong> 100.0 / 100.0</p>
<br>
<br>

<h1 id="4-참고">4. 참고</h1>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript | Level1. 로또의 최고 순위와 최저 순위]]></title>
            <link>https://velog.io/@im_hass_/Level1.-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EC%A0%95%EC%88%98%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0</link>
            <guid>https://velog.io/@im_hass_/Level1.-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EC%A0%95%EC%88%98%EB%A1%9C-%EB%B0%94%EA%BE%B8%EA%B8%B0</guid>
            <pubDate>Tue, 02 Nov 2021 07:35:34 GMT</pubDate>
            <description><![CDATA[<p><a href="#1-%EB%AC%B8%EC%A0%9C">1. 문제</a>
<a href="#2-%ED%92%80%EC%9D%B4">2. 풀이</a>
<a href="#3-%EA%B2%B0%EA%B3%BC">3. 결과</a>
<a href="#4-%EC%B0%B8%EA%B3%A0">4. 참고</a></p>
<h1 id="1-문제">1. 문제</h1>
<hr>
<h2 id="로또의-최고-순위와-최저-순위">로또의 최고 순위와 최저 순위</h2>
<p><a href="https://programmers.co.kr/learn/courses/30/lessons/77484">문제 링크</a></p>
<h3 id="문제-설명">문제 설명</h3>
<p><code>로또 6/45</code>(이하 &#39;로또&#39;로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다.</p>
<table>
<thead>
<tr>
<th>순위</th>
<th>당첨 내용</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>6개 번호가 모두 일치</td>
</tr>
<tr>
<td>2</td>
<td>5개 번호가 일치</td>
</tr>
<tr>
<td>3</td>
<td>4개 번호가 일치</td>
</tr>
<tr>
<td>4</td>
<td>3개 번호가 일치</td>
</tr>
<tr>
<td>5</td>
<td>2개 번호가 일치</td>
</tr>
<tr>
<td>6(낙첨)</td>
<td>그 외</td>
</tr>
</tbody></table>
<p>로또를 구매한 민우는 당첨 번호 발표일을 학수고대하고 있었습니다. 하지만, 민우의 동생이 로또에 낙서를 하여, 일부 번호를 알아볼 수 없게 되었습니다. 당첨 번호 발표 후, 민우는 자신이 구매했던 로또로 당첨이 가능했던 최고 순위와 최저 순위를 알아보고 싶어 졌습니다.</p>
<p>알아볼 수 없는 번호를 <code>0</code>으로 표기하기로 하고, 민우가 구매한 로또 번호 6개가 <code>44, 1, 0, 0, 31 25</code>라고 가정해보겠습니다. 당첨 번호 6개가 <code>31, 10, 45, 1, 6, 19</code>라면, 당첨 가능한 최고 순위와 최저 순위의 한 예는 아래와 같습니다.</p>
<table>
<thead>
<tr>
<th>당첨 번호</th>
<th>31</th>
<th>10</th>
<th>45</th>
<th>1</th>
<th>6</th>
<th>19</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td>최고 순위 번호</td>
<td>31</td>
<td>0→10</td>
<td>44</td>
<td>1</td>
<td>0→6</td>
<td>25</td>
<td>4개 번호 일치, 3등</td>
</tr>
<tr>
<td>최저 순위 번호</td>
<td>31</td>
<td>0→11</td>
<td>44</td>
<td>1</td>
<td>0→7</td>
<td>25</td>
<td>2개 번호 일치, 5등</td>
</tr>
</tbody></table>
<ul>
<li>순서와 상관없이, 구매한 로또에 당첨 번호와 일치하는 번호가 있으면 맞힌 걸로 인정됩니다.</li>
<li>알아볼 수 없는 두 개의 번호를 각각 10, 6이라고 가정하면 3등에 당첨될 수 있습니다.<ul>
<li>3등을 만드는 다른 방법들도 존재합니다. 하지만, 2등 이상으로 만드는 것은 불가능합니다.</li>
</ul>
</li>
<li>알아볼 수 없는 두 개의 번호를 각각 11, 7이라고 가정하면 5등에 당첨될 수 있습니다.<ul>
<li>5등을 만드는 다른 방법들도 존재합니다. 하지만, 6등(낙첨)으로 만드는 것은 불가능합니다.</li>
</ul>
</li>
</ul>
<p>민우가 구매한 로또 번호를 담은 배열 lottos, 당첨 번호를 담은 배열 win_nums가 매개변수로 주어집니다. 이때, 당첨 가능한 최고 순위와 최저 순위를 차례대로 배열에 담아서 return 하도록 solution 함수를 완성해주세요.</p>
<hr>
<h3 id="제한-사항">제한 사항</h3>
<ul>
<li>lottos는 길이 6인 정수 배열입니다.</li>
<li>lottos의 모든 원소는 0 이상 45 이하인 정수입니다.<ul>
<li>0은 알아볼 수 없는 숫자를 의미합니다.</li>
<li>0을 제외한 다른 숫자들은 lottos에 2개 이상 담겨있지 않습니다.</li>
<li>lottos의 원소들은 정렬되어 있지 않을 수도 있습니다.</li>
</ul>
</li>
<li>win_nums은 길이 6인 정수 배열입니다.</li>
<li>win_nums의 모든 원소는 1 이상 45 이하인 정수입니다.<ul>
<li>win_nums에는 같은 숫자가 2개 이상 담겨있지 않습니다.</li>
<li>win_nums의 원소들은 정렬되어 있지 않을 수도 있습니다.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="입출력-예">입출력 예</h3>
<table>
<thead>
<tr>
<th>lottos</th>
<th>win_nums</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[44, 1, 0, 0, 31, 25]</td>
<td>[31, 10, 45, 1, 6, 19]</td>
<td>[3, 5]</td>
</tr>
<tr>
<td>[0, 0, 0, 0, 0, 0]</td>
<td>[38, 19, 20, 40, 15, 25]</td>
<td>[1, 6]</td>
</tr>
<tr>
<td>[45, 4, 35, 20, 3, 9]</td>
<td>[20, 9, 3, 45, 4, 35]</td>
<td>[1, 1]</td>
</tr>
</tbody></table>
<h3 id="입출력-예-설명">입출력 예 설명</h3>
<p><strong>입출력 예 #1</strong></p>
<p>문제 예시와 같습니다.</p>
<p><strong>입출력 예 #2</strong></p>
<p>알아볼 수 없는 번호들이 아래와 같았다면, 1등과 6등에 당첨될 수 있습니다.</p>
<table>
<thead>
<tr>
<th>당첨 번호</th>
<th>38</th>
<th>19</th>
<th>20</th>
<th>40</th>
<th>15</th>
<th>25</th>
<th>결과</th>
</tr>
</thead>
<tbody><tr>
<td>최고 순위 번호</td>
<td>0→38</td>
<td>0→19</td>
<td>0→20</td>
<td>0→40</td>
<td>0→15</td>
<td>0→25</td>
<td>6개 번호 일치, 1등</td>
</tr>
<tr>
<td>최저 순위 번호</td>
<td>0→21</td>
<td>0→22</td>
<td>0→23</td>
<td>0→24</td>
<td>0→26</td>
<td>0→27</td>
<td>0개 번호 일치, 6등</td>
</tr>
</tbody></table>
<p><strong>입출력 예 #3</strong></p>
<p>민우가 구매한 로또의 번호와 당첨 번호가 모두 일치하므로, 최고 순위와 최저 순위는 모두 1등입니다.</p>
<br>
<br>

<h1 id="2-풀이">2. 풀이</h1>
<hr>
<blockquote>
<p>0일 경우 0의 개수를 세고, 0이 아니라면 그 중 로또 번호와 일치하는 것이 있는지 찾고 있다면 맞힌 개수를 1씩 증가 시킨다.</p>
</blockquote>
<p>예전에 풀었을 때는 정렬하고, 그 중 옳은 개수, 틀린 개수 다 세어가며 출력했었다. 오랜만에 푸니 전혀 다른 방식으로 풀어지고 코드가 훨씬 간결해졌다.</p>
<ol>
<li><p>우선 등수를 처리하기 위한 배열을 선언했다.</p>
<p> 맞힌 개수를 셀 것이므로 <code>맞힌 개수 == 배열의 인덱스</code>가 되는 것이다.</p>
<p> 그렇다면 0개(6등), 1개(6등), 2개(5등), 3개(4등), 4개(3등), 5개(2등), 6개(1등). 즉 값에는 등수를 적어주면 된다.</p>
</li>
</ol>
<pre><code class="language-jsx">//////////// 0, 1, 2, 3, 4, 5, 6 // 맞힌 개수
let prize = [6, 6, 5, 4, 3, 2, 1]; // 등수</code></pre>
<ol start="2">
<li><p>최고 등수일 경우 0을 전부 맞는 수로 치면 되고, 최저 등수일 경우 0을 전부 틀린 숫자로 치면 된다. 0의 개수를 세는 변수와 맞힌 것의 개수를 세는 변수를 만들고, 배열의 각 값을 탐색한다.</p>
<p> 만약 0이 아니라면, 당첨 번호 중 일치하는 것이 있는지 찾고, 일치하면 맞힌 개수를 추가해준다.</p>
</li>
</ol>
<pre><code class="language-jsx">let corrent = 0; // 맞힌 개수
let zeroCnt = 0; // 0의 개수

lottos.filter(v =&gt; {
  if(v === 0) zeroCnt++;
  else {
    if(win_nums.includes(v)) {
      corrent++;
    }
  }
});</code></pre>
<ol start="3">
<li>등수를 반환한다.<pre><code class="language-jsx">return [prize[corrent + zeroCnt], prize[corrent]];</code></pre>
</li>
</ol>
<h2 id="제출">제출</h2>
<pre><code class="language-jsx">function solution(lottos, win_nums) {
  let prize = [6, 6, 5, 4, 3, 2, 1]; // 등수
  /////////////0, 1, 2, 3, 4, 5, 6 // 맞힌 개수에 따른 등수

  let corrent = 0; // 맞힌 개수
    let zeroCnt = 0; // 0의 개수

  lottos.filter(v =&gt; {
      if(v === 0) zeroCnt++;
      else {
        if(win_nums.includes(v)) {
          corrent++;
        }
      }
  });

  return [prize[corrent + zeroCnt], prize[corrent]];
}</code></pre>
<br>
<br>

<h1 id="3-결과">3. 결과</h1>
<hr>
<pre><code class="language-jsx">테스트 1 〉    통과 (0.07ms, 30.3MB)
테스트 2 〉    통과 (0.12ms, 30.4MB)
테스트 3 〉    통과 (0.08ms, 30.2MB)
테스트 4 〉    통과 (0.08ms, 30.4MB)
테스트 5 〉    통과 (0.10ms, 30.4MB)
테스트 6 〉    통과 (0.11ms, 30MB)
테스트 7 〉    통과 (0.08ms, 30.4MB)
테스트 8 〉    통과 (0.07ms, 30.2MB)
테스트 9 〉    통과 (0.08ms, 30.1MB)
테스트 10 〉    통과 (0.06ms, 30.4MB)
테스트 11 〉    통과 (0.11ms, 30.2MB)
테스트 12 〉    통과 (0.07ms, 30.4MB)
테스트 13 〉    통과 (0.07ms, 30.2MB)
테스트 14 〉    통과 (0.08ms, 30.3MB)
테스트 15 〉    통과 (0.10ms, 30.2MB)</code></pre>
<p><strong>- 정확성 :</strong> 100.0</p>
<p><strong>- 합계 :</strong> 100.0 / 100.0</p>
<br>
<br>

<h1 id="4-참고">4. 참고</h1>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 접근성 | 웹 콘텐츠 접근성 지침 (WCAG, Web Content Accessibility Guidelines)]]></title>
            <link>https://velog.io/@im_hass_/%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</link>
            <guid>https://velog.io/@im_hass_/%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</guid>
            <pubDate>Sat, 23 Oct 2021 09:00:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>아직 작성중인 글입니다!</strong></p>
</blockquote>
<h1 id="웹-접근성">웹 접근성</h1>
<blockquote>
<p><strong>웹 접근성이란?</strong>
웹 사이트, 도구, 기술이 장애가 있는 사용자들이 사용할 수 있도록 설계 및 개발된 것을 말한다. - W3C 웹 접근성 -</p>
</blockquote>
<p>과거에는 웹이 각각의 브라우저에 따라 다른 방식으로 만들어져서 웹 접근성이 좋지 못하였고, 신체적 장애나 상황적 장애에 의해 웹을 사용하는데 어려움이 있었다.</p>
<p>이러한 문제를 줄이고자 W3C에서 전 세계 개인 및 단체와 협력하여 W3C 프로세스를 통해 WCAG(Web Content Accessibility Guidelines, <a href="https://www.w3.org/WAI/standards-guidelines/wcag/">참고</a>)라는 웹 접근성 표준을 제공하고 있다. 이제는 웹을 개발할 때 웹 접근성을 지키는 것이 무엇보다 중요해졌다.</p>
<h3 id="wcag가-필요한-사람">WCAG가 필요한 사람</h3>
<ul>
<li>웹 콘텐츠 개발자(페이지 작성자, 사이트 설계자 등)</li>
<li>웹 저작 도구 개발자</li>
<li>웹 접근성 평가 도구 개발자</li>
<li>모바일 접근성을 포함한 웹 접근성 표준을 원하거나 필요로 하는 기타 사용자</li>
</ul>
<h3 id="wcag-발표-현황">WCAG 발표 현황</h3>
<ul>
<li>WCAG 2.0은 2008년 12월 11일에 출판되었다.</li>
<li>WCAG 2.1은 2018년 6월 5일에 출판되었다.</li>
<li>WCAG 2.2는 2021년에 출판될 예정이다.</li>
</ul>
<p>WCAG 2.0과 WCAG 2.1은 안정적이고 참조 가능한 기술 표준이다.
2.0의 내용은 2.1에 모두 포함되어 있고, 2.1도 마찬가지로 2.2에 모두 포함될 예정이라고 한다.</p>
<br>

<hr>
<h1 id="웹-접근성-원칙-및-지침">웹 접근성 원칙 및 지침</h1>
<p>웹 접근성은 크게 4가지 원칙과 각 원칙을 다루는 12개의 지침*으로 이루어진다. 그리고 각 지침들은 작성자가 노력해야 하는 기본 목표를 <strong>성공 기준(Success Criteria)</strong>으로 제공한다.
성공 기준은 <strong>A급(최하위), AA급, AAA급(최상위)</strong>라는 세 가지 준수 수준으로 나누어 진다.</p>
<p>이 글에서는 Level AA까지만 다룬다.</p>
<ul>
<li>WCAG21 원칙 및 지침 <a href="https://www.w3.org/TR/WCAG21/#perceivable">원본</a></li>
<li>참고 <a href="http://www.kwacc.or.kr/WAI/wcag21/">한국어 번역본</a></li>
</ul>
<h2 id="🔎-1-인지-가능인식의-용이성">🔎 1. 인지 가능(인식의 용이성)</h2>
<blockquote>
<p>정보 및 사용자 인터페이스 구성 요소는 사용자가 인지할 수 있도록 표시되어야 한다.</p>
</blockquote>
<h3 id="11-대체-텍스트">1.1 대체 텍스트</h3>
<blockquote>
<p>텍스트가 아닌 콘텐츠는 그 의미나 용도를 인식할 수 있도록 대체 텍스트를 제공해야 한다.</p>
</blockquote>
<p><em>Level A</em>
<strong>1.1.1 Non-text Content</strong>
 사용자에게 제공되는 모든 비 텍스트 콘텐츠(Non-text Content)*는 아래 상황을 제외하고 동일한 목적으로 사용되는 텍스트 대체 내용이 있다.</p>
<ul>
<li><strong>Controls, Input :</strong> 비 텍스트 콘텐츠가 컨트롤 또는 사용자 입력을 허용하는 것일 경우(<a href="#41-Compatible">지침 4.1.2 참고</a>)</li>
<li><strong>Time-Based Media :</strong> 비 텍스트 콘텐츠가 시간 기반 미디어인 경우(<a href="#12-%EC%8B%9C%EA%B0%84-%EA%B8%B0%EB%B0%98-%EB%AF%B8%EB%94%94%EC%96%B4">지침 1.2 참고</a>)</li>
<li><strong>Test :</strong> 텍스트가 유효하지 않은 테스트 또는 연습인 경우</li>
<li><strong>Sensory :</strong> 비 텍스트 콘텐츠가 특정한 감각 경험을 만들기 위한 것일 경우</li>
<li><strong>CAPTCHA :</strong> 비 텍스트 콘텐츠가 사용자가 실제 사람인지 컴퓨터 프로그램인지를 구별하기 위해 사용되는 것일 경우</li>
<li><strong>Decoratio, Formatting, Invisible :</strong> 비 텍스트 콘텐츠의 내용이 순수한 장식이거나 시각적 형식으로만 사용되거나 사용자에게 표시되지 않는 것일 경우</li>
</ul>
<p><strong>※ 비 텍스트 콘텐츠(non-text content) :</strong> ASCII Art(문자의 패턴), 이모티콘, 리츠피크(문자 대체 사용), 및 텍스트를 나타내는 이미지 등을 의미한다.</p>
<h3 id="12-시간-기반-미디어">1.2 시간 기반 미디어</h3>
<blockquote>
<p>시간 기반 미디어(Time-based Media)*에 대한 대인을 제공한다.</p>
</blockquote>
<p><em>Level A</em>
<strong>1.2.1 Audio-only* and Video-only*(Prerecorded)</strong>
제공된 오디오 또는 비디오가 텍스트에 대한 대체 미디어이고 명확하게 레이블이 지정된 경우를 제외하고, 오디오 또는 비디오를 대체할 자막, 영상, 오디오 등이 제공된다.</p>
<p><em>Level A</em>
<strong>1.2.2 Captions(Prerecorded)</strong>
제공된 미디어의 오디오가 텍스트에 대한 대체 미디어이고 명확하게 레이블이 지정된 경우를 제외하고, 미리 기록된 모든 항목에 대한 캡션이 제공된다.</p>
<p><em>Level A</em>
<strong>1.2.3 Audio Description or Media Alternative(Prerecorded)</strong>
제공된 미디어가 텍스트에 대한 대체 미디어이고, 명확하게 레이블이 지정된 경우를 제외하고, 비디오 콘텐츠의 오디오에 대한 설명이나 대체 미디어가 제공된다.</p>
<p><em>Level AA</em><br><strong>1.2.4 Captions(Live)</strong>
라이브로 실행되는 모든 오디오 콘텐츠에 캡션(설명)이 제공된다.</p>
<p><em>Level AA</em><br><strong>1.2.5 Audio Description(Prerecorded)</strong>
사전 녹음된 비디오 콘텐츠의 모든 항목에 대한 오디오 설명이 제공된다.</p>
<p><strong>※ Time-based Media :</strong> 오디오 클립, MIDI 시퀀스, 동영상 크립, 애니메이션 과 같이 시간에 따른 변화가 중요한 미디어
<strong>※ Audio-only :</strong> 오디오만 포함하는 시간 기반 프레젠테이션(비디오 및 상호 작용 없음)
<strong>※ Video-only :</strong> 비디오만 포함하는 시간 기반 프레젠테이션(오디오 및 상호 작용 없음)</p>
<h3 id="13-적응성">1.3 적응성</h3>
<blockquote>
<p>콘텐츠는 정보나 구조의 손실 없이 다른 방법들(예: 보다 간단한 레이아웃)로 표시될 수 있도록 제작되어야 한다.</p>
</blockquote>
<p><em>Level A</em><br><strong>1.3.1 Info and Relationships</strong><br>프레젠테이션(presentation)*을 통해 전달되는 정보/구조/관계는 프로그래밍 방식으로 결정*되거나 텍스트로 이용 가능해야 한다.<br>이 성공 기준의 목적은 정보와 관계를 보장하는 것이다.<br>사용자가 보는(인식하는) 콘텐츠의 정보/구조/관계를 다른 방식(정보 추출, 텍스트)으로도 이용 가능해야 한다는 것이다. 예를 들어 데이터 테이블이 있는데, 중요한 정보를 이미지를 넣어 표시하거나, 색깔을 입혀 표시하는 등의 방식은 누군가 이용할 수 없는 정보가 될 것이다.</p>
<p><em>Level A</em><br><strong>1.3.2 Meaningful Sequence</strong><br>콘텐츠가 표시되는 순서가 의미에 영향을 미치는 경우, 프로그래밍 방식으로 올바른 읽기 순서가 결정되어야 한다.</p>
<p><em>Level A</em><br><strong>1.3.3 Sensory Characteristics</strong><br>콘텐츠를 이해하고 작동하기 위해 제공된 지시문은 모양/색상/크기/시각적 위치/방향/소리 등과 같은 감각적인 특성에만 전적으로 의존해서는 안 된다. 1.3.1의 예시에서 말하는 것과 같다.</p>
<p><em>Level AA</em><br><strong>1.3.4 Orientation</strong><br>특정 디스플레이 방향이 필수적*(고정적)일 필요가 없다면, 콘텐츠는 세로/가로 같이 한 방향으로 보거나 작동되도록 제한하지 않는다.</p>
<p><em>Level AA</em><br><strong>1.3.5 Identify Input Purpose</strong><br>사용자에 관한 정보를 수집하는 각 입력필드의 목적이 아래와 같은 경우 프로그래밍 방식으로 결정되어야 한다.</p>
<ul>
<li>입력 필드가 사용자 인터페이스 구성요소를 위한 입력 목적 절(section)에서 식별 목적으로 사용될 때 : ex) name, nickname, barthday, sex 등 <a href="http://www.kwacc.or.kr/WAI/wcag21/#input-purposes">참고</a></li>
<li>콘텐츠가 서식(form) 입력 데이터에 대해 예상되는 의미를 식별할 수 있도록 지원하는 기법을 사용하여 실행될 때</li>
</ul>
<p><strong>※ 프레젠테이션(Presentation) :</strong> 사용자가 인식할 수 있는 형태로 콘텐츠를 렌더링하는 것<br><strong>※ 프로그래밍 방식으로 결정되는/가능한(programmatically determined) :</strong> 개발자가 설정(제공)해주는 데이터로 인해 소프트웨어에 의해 결정되거나 결정 가능한 것. 보조 공학을 포함한 다른 사용자 에이전트가 정보를 추출하여 사용자에게 다른 형식으로 제시할 수 있도록 제공된다.<br><strong>※ 필수적인(essential) :</strong> 해당 사항이 제거된다면, 콘텐츠의 정보 또는 기능이 근본적으로 변경될 수 있고, 정보와 기능이 다른 방식으로는 준수될 수 없는 경우 필수적인 것으로 한다.</p>
<h3 id="14-식별-가능">1.4 식별 가능</h3>
<blockquote>
<p>배경으로부터 전경을 분리하는 것을 포함하여, 콘텐츠는 사용자가 더 쉽게 보고 들을 수 있도록 제작되어야 한다.</p>
</blockquote>
<p><em>Level A</em><br><strong>1.4.1 Use of color</strong><br>정보 전달, 동작 표시, 반응 유발 등 시각적 요소를 구별하는 방법으로 색상만 사용해서는 안 된다.(<a href="#13-%EC%A0%81%EC%9D%91%EC%84%B1">지침 1.3 참고</a>)</p>
<p><em>Level A</em><br><strong>1.4.2 Audio Control</strong><br>웹 페이지에 있는 어떤 오디오가 3초 이상 자동으로 재생되는 경우, 해당 오디오를 일시정지 또는 중단할 수 있는 메커니즘*이나 오디오 음량을 전체 시스템 음량과는 별도로 제어할 수 있는 메커니즘을 제공해야 한다.<br>다른 성공 기준의 충족 여부와 관계없이, 웹 페이지에 있는 모든 콘텐츠는 이 성공 기준을 준수해야 한다.(<a href="#525-%EB%B6%88%EA%B0%84%EC%84%AD">준수 사항 5.2.5 참고</a>)</p>
<p><em>Level AA</em><br><strong>1.4.3 Contrast(Minimum)</strong><br>아래의 경우를 제외하고, 텍스트와 텍스트 이미지*의 시각적 표현을 위한 명도대비율은 최소한 4.5:1 이상이어야 한다.</p>
<ul>
<li><strong>커다란 텍스트(Large Text) :</strong> 최소 18pt 또는 14pt의 볼드체, 또는 중국어, 일본어 및 한국어 글꼴과 같은 크기를 산출하는 글꼴은, 최소한 3:1 이상이어야 한다.</li>
<li><strong>부수적인(Incidental) :</strong> 비활성 사용자 인터페이스 구성요소의 일부, 순수한 장식, 사용자에게 보이지 않는, 또는 의미 있는 다른 시각적 콘텐츠를 포함하고 있는 그림의 일부인 텍스트 또는 텍스트 이미지에는 어떤 명도대비 요구사항도 없다.</li>
<li><strong>로고 타입(Logotypes) :</strong> 로고 또는 상표명에 포함된 텍스트에는 어떤 명도대비 요구사항도 없다.</li>
</ul>
<p><em>Level AA</em><br><strong>1.4.4 Resize text</strong>  </p>
<p><em>Level AA</em><br><strong>1.4.5 Images of Text</strong>  </p>
<p><strong>※ 메커니즘(mechanism) :</strong> 결과(result) 성취를 위한 과정이나 기법
<strong>※ 텍스트 이미지(image of text) :</strong> 특정 시각적인 효과를 달성하기 위해 텍스트가 아닌 형식(ex. 이미지)으로 렌더링된 텍스트</p>
<br>

<h3 id="🔎-2-작동-가능운용의-용이성">🔎 2. 작동 가능(운용의 용이성)</h3>
<blockquote>
<p>사용자 인터페이스 구성 요소가 작동 가능해야 한다.</p>
</blockquote>
<br>


<h3 id="🔎-3-이해-가능이해의-용이성">🔎 3. 이해 가능(이해의 용이성)</h3>
<blockquote>
<p>정보 및 사용자 인터페이스 구성 요소의 작동이 이해 가능해야 한다.</p>
</blockquote>
<br>

<h3 id="🔎-4-견고성">🔎 4. 견고성</h3>
<blockquote>
<p>보조 기술을 포함한 다양한 사용자 에이전트만으로도 컨텐츠에 접근할 수 있어야 한다.</p>
</blockquote>
<br>

<h3 id="⚠-5-준수">⚠ 5. 준수</h3>
<blockquote>
<p>준수 요구사항에 대한 설명이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git branch]]></title>
            <link>https://velog.io/@im_hass_/Git-branch</link>
            <guid>https://velog.io/@im_hass_/Git-branch</guid>
            <pubDate>Mon, 11 Oct 2021 08:47:31 GMT</pubDate>
            <description><![CDATA[<ol>
<li><a href="#%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95">기본 사용 방법</a>
1-1. <a href="#%EB%B3%B4%EA%B8%B0-%EC%83%9D%EC%84%B1-%EC%88%98%EC%A0%95-%EC%82%AD%EC%A0%9C">보기, 생성, 수정, 삭제</a>
1-2. <a href="#%EB%B3%80%EA%B2%BD">변경</a>
1-3. <a href="#%EB%B3%91%ED%95%A9">병합</a></li>
</ol>
<br>

<h2 id="기본-사용-방법">기본 사용 방법</h2>
<h3 id="보기-생성-수정-삭제">보기, 생성, 수정, 삭제</h3>
<pre><code class="language-bash"># 브랜치 보기
$ git branch

# 브랜치 생성
$ git branch [브랜치명]

# 브랜치 수정
$ git branch -m [브랜치명] [바꿀이름]

# 브랜치 삭제
$ git branch -d [브랜치명]</code></pre>
<h3 id="변경">변경</h3>
<p>워킹 디렉터리의 소스를 특정 커밋 또는 특정 브랜치로 변경한다.</p>
<pre><code class="language-bash"># 특정 브랜치로 워킹 디렉터리 변경
$ git checkout [브랜치명]

# 특정 커밋으로 워킹 디렉터리 변경
$ git checkout [Commit ID]

# 특정 파일을 해당 브랜치 또는 커밋 상태로 변경 (원복)
# 충돌 방지를 위해 브랜치명을 확인하고, 
# 파일 추가 및 수정한 뒤 커밋해야 한다.
$ git checkout [돌아갈 Commit ID] -- [파일 경로]

# 브랜치 생성 및 체크아웃을 같이 할 경우
$ git checkout -b develop</code></pre>
<h3 id="병합">병합</h3>
<p>다른 두개의 브랜치 소스를 병합한다.</p>
<pre><code class="language-bash">$ git checkout master # 병합할 브랜치
$ git merge develop # 병합될 브랜치

# 또는
$ git merge master:develop</code></pre>
]]></description>
        </item>
    </channel>
</rss>