<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yricog.log</title>
        <link>https://velog.io/</link>
        <description>의미와 가치를 쫓는 개발자 ✨</description>
        <lastBuildDate>Sat, 25 Jan 2025 14:49:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>yricog.log</title>
            <url>https://velog.velcdn.com/images/roong-ra/profile/4bbd2196-c1f7-446b-a4c0-36a9f47338aa/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. yricog.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/roong-ra" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[typeScript] 4. 대수 타입 / 타입 추론 / 타입 단언 ]]></title>
            <link>https://velog.io/@roong-ra/typeScript-4.-%EB%8C%80%EC%88%98-%ED%83%80%EC%9E%85-%ED%83%80%EC%9E%85-%EC%B6%94%EB%A1%A0-%ED%83%80%EC%9E%85-%EB%8B%A8%EC%96%B8</link>
            <guid>https://velog.io/@roong-ra/typeScript-4.-%EB%8C%80%EC%88%98-%ED%83%80%EC%9E%85-%ED%83%80%EC%9E%85-%EC%B6%94%EB%A1%A0-%ED%83%80%EC%9E%85-%EB%8B%A8%EC%96%B8</guid>
            <pubDate>Sat, 25 Jan 2025 14:49:50 GMT</pubDate>
            <description><![CDATA[<h1 id="대수-타입">대수 타입</h1>
<p>대수 타입은 <strong>여러 개의 타입을 합성</strong>하여 새롭게 만들어낸 타입을 뜻한다.
대수 타입의 종류로는 합집합과 교집합 타입이 있다. </p>
<h2 id="1-합집합union-타입">1. 합집합(Union) 타입</h2>
<h3 id="원시타입의-합집합">원시타입의 합집합</h3>
<pre><code>let a: string | number | boolean;

a = 1;
a = &quot;hello&quot;;
a = true;</code></pre><h3 id="배열의-합집합">배열의 합집합</h3>
<pre><code>let arr: (number | string | boolean)[] = [1, &quot;hello&quot;, true];</code></pre><h3 id="객체의-합집합">객체의 합집합</h3>
<pre><code>type Dog = {
  name: string;
  color: string;
};

type Person = {
  name: string;
  language: string;
};

type Union1 = Dog | Person; // 타입에 타입 할당

let union1: Union1 = { // Dog 타입만 사용 
  name: &quot;&quot;,
  color: &quot;&quot;,
};

let union2: Union1 = { // Person 타입만 사용 
  name: &quot;&quot;,
  language: &quot;&quot;,
};

let union3: Union1 = { // 모든 프로퍼티 사용 가능
  name: &quot;&quot;,
  color: &quot;&quot;,
  language: &quot;&quot;,
};</code></pre><blockquote>
<p>이 때, 공통된 <code>name:&quot;&quot;</code> 프로퍼티 하나만 사용하는 것은 합집합 어디에도 포함되지 않는 타입이기 때문에 사용이 불가하다.🙅🏻‍♀️
<img src="https://velog.velcdn.com/images/roong-ra/post/fa50b16c-d780-4a9f-aa28-dd4ca2bd78b9/image.png" alt="">⭐️⭐️ 위 그림에서의 교집합은, <del>프로퍼티의 교집합이 아닌</del> <strong>&quot;값의 교집합&quot;</strong>을 뜻한다. 즉, A와 B 두 타입의 모든 조건을 동시에 충족해야 하므로 <strong>모든 프로퍼티를 포함하는 타입</strong>이 생성되게 된다. </p>
<blockquote>
<p>만약, 공통된 <code>name:&quot;&quot;</code> 프로퍼티를 교집합으로 만들고 싶다면 인터페이스와 상속 개념을 통해 구현해볼 수 있다. </p>
</blockquote>
</blockquote>
<pre><code>interface BaseType { 
    name: string;
}
// BaseType의 프로퍼티를 모두 상속 (name 프로퍼티 자동으로 생김)
interface Dog extends BaseType {
    color: string;
}
interface Person extends BaseType {
    language: string;
}</code></pre><h2 id="2-교집합intersection-타입">2. 교집합(Intersection) 타입</h2>
<p>위에서 설명한 것과 같이, 교집합은 두 타입의 모든 프로퍼티를 포함하는 타입을 생성한다. </p>
<pre><code>type Dog1 = {
  name: &quot;&quot;;
};

type Person1 = {
  age: &quot;&quot;;
};

type Intersection1 = Dog1 &amp; Person1;

let intersectionVar: Intersection1 = {
  name: &quot;&quot;,
  age: &quot;&quot;,
};</code></pre><p>하지만 원시 타입의 교집합은 다르다. 아래 예시를 보면 어떤 값도 number 이면서 동시에 string일 수 없기 때문에 <del><strong>원시 타입의 교집합은 공존할 수 없다.</strong></del> </p>
<pre><code>let variable: number &amp; string; // = never</code></pre><hr>
<h1 id="타입-추론">타입 추론</h1>
<p>타입스크립트는 변수에 타입을 선언하면 프로그램이 실행되기 이전에 타입 검사를 수행하는 점진적 타입 시스템이다. 이 때 타입을 선언하지 않아도 <strong>초기값을 기준으로 자동으로 타입을 추론</strong>해주기도 한다. </p>
<ul>
<li><strong>초기 값이 있을 때</strong> <pre><code>let a = 10;
let b = &quot;hello&quot;;
</code></pre></li>
</ul>
<p>let c = {
  id: 1,
  name: &quot;aaa&quot;,
  profile: {
    nickname: &quot;winter&quot;,
  },
};
let { id, name, profile } = c;</p>
<p>function func(message = &quot;hello&quot;) {
  return &quot;hello&quot;;
}</p>
<pre><code>* **초기 값이 없을 때 (~~any 타입의 진화~~)**</code></pre><p>let d;  // any
d = 10; // 아직 any (값이 할당될 때 any -&gt; number로 진화)
d.toFixed(); // number</p>
<p>d = &quot;string&quot;; // 다시 any (값이 할당될 때 any -&gt; string로 진화)
d.toUpperCase(); // string</p>
<pre><code>* **const로 선언할 때**
  * const는 상수이기 때문에 다른 값이 재할당될 일이 없으므로 할당된 값으로 리터럴 타입 표시 </code></pre><p>const num = 10; // num:10
const str = &quot;hello&quot;; // str:&quot;hello&quot;</p>
<pre><code>* 배열 </code></pre><p>let arr = [1, &quot;string&quot;]; // let arr: (string | number)[]</p>
<pre><code>&gt; 타입 추론 시 범용적으로 변수를 사용할 수 있도록 좀 더 넓은 타입으로 추론해 주는 것을 **&#39;타입 넓히기&#39;** 라고 한다.

---
* 출처 : [한 입 크기로 잘라먹는 타입스크립트](https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8) / [docs](https://ts.winterlood.com/6c9bf87f-6a8f-4e96-95b4-5e12d9f82165#c8a5f8ebaa7d4692a90e3d743bb21dea)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[typeScript] 3. 기본 타입 및 객체 타입의 호환성]]></title>
            <link>https://velog.io/@roong-ra/typeScript-3.-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5%EB%8F%84-%ED%83%80%EC%9E%85-%ED%98%B8%ED%99%98%EC%84%B1</link>
            <guid>https://velog.io/@roong-ra/typeScript-3.-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5%EB%8F%84-%ED%83%80%EC%9E%85-%ED%98%B8%ED%99%98%EC%84%B1</guid>
            <pubDate>Sat, 25 Jan 2025 13:05:17 GMT</pubDate>
            <description><![CDATA[<h1 id="타입-계층도로-보는-기본타입-호환성">타입 계층도로 보는 기본타입 호환성</h1>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/e6e179a7-1f68-4ded-ba1e-3cf3d839718d/image.png" alt=""></p>
<p>타입스크립트의 모든 타입은 집합이며 서로 부모-자식의 관계를 맺는다. 여기서 부모는 슈퍼 타입, 자식은 서브 타입이라 한다. </p>
<ul>
<li>서브 타입의 값을 슈퍼 타입으로 취급하는 것을 <strong>Up Cast(업 캐스트)</strong>라고 하며, 업 캐스트는 <del>모든 상황에 허용</del>된다. </li>
<li>반대로 슈퍼 타입의 값을 서브 타입으로 취급하는 것은 <strong>Down Cast(다운 캐스트)</strong>라 하며, <del>대부분의 상황에서 허용되지 않는다.</del> </li>
</ul>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/ec1c57df-41be-402c-a01d-6c21a46038d6/image.webp" alt=""></p>
<p>위 타입 계층도를 보면서 기본 타입을 살펴보자.</p>
<h2 id="1-unknown-타입">1. Unknown 타입</h2>
<p>unknown 타입은 전체 집합 즉, <strong>최상위 슈퍼 타입</strong>이다. 
때문에 모든 타입의 업 캐스트는 가능하지만, unkown 타입의 다운 캐스트는 불가능하다.</p>
<pre><code>function unknownExam() {
  //  모든 타입의 UpCasting ⭕️
  let a: unknown = 1;
  let b: unknown = &quot;hello&quot;;
  let c: unknown = true;
  let d: unknown = null;
  let e: unknown = undefined;

  // unknown의 DownCasting ❌
  let unknownVar: unknown;
  let num: number = unknownVar;
  let str: string = unknownVar;
  let bool: boolean = unknownVar;
}</code></pre><h2 id="2-never-타입">2. Never 타입</h2>
<p>never 타입은 공집합(=아무것도 없음) 즉, <strong>최하위 서브 타입</strong>이다. 
때문에 never 타입의 업 캐스트는 모두 가능하고, 다른 타입의 다운 캐스트는 모두 불가능하다. </p>
<pre><code>function neverExam() {
  function neverFun(): never {
    while (true) {}
  }

  // never의 UpCasting ⭕️
  let num: number = neverFun();
  let str: string = neverFun();
  let bool: boolean = neverFun();

  // 모든 타입의 DownCasting ❌
  let never1: never = 10;
  let never2: never = &quot;string&quot;;
  let never3: never = true;
}</code></pre><h2 id="3-void-타입">3. Void 타입</h2>
<p>void 타입은 <strong>undefined 타입의 슈퍼 타입</strong>이라는 것을 기억하자. </p>
<pre><code>function voidExam() {
  function voidFun(): void {
    console.log(&quot;hi&quot;);
    return undefined; // return 가능 ⭕️
  }

  // undefined의 UpCasting ⭕️
  let voidVar: void = undefined;
}</code></pre><h2 id="4-any-타입">4. Any 타입</h2>
<p>any 타입은 타입 계층도를 완벽히 무시하는 <strong>치트키 타입</strong>이다. 
모든 타입의 최상위 슈퍼 타입 또는 최하위 서브 타입으로 위치하기도 한다.(never는 제외)
<del>때문에 사용이 권장되지 않음!!</del> 🙅🏻‍♀️</p>
<pre><code>function anyExam() {
  let unknownVar: unknown;
  let anyVar: any;
  let undefinedVar: undefined;
  let neverVar: never;

  // unknown을 any로 DownCationg ⭕️
  anyVar = unknownVar;

  // any를 undefined로 DownCationg ⭕️
  undefinedVar = anyVar;

  // never만 DownCationg ❌
  neverVar = anyVar;
}</code></pre><blockquote>
<p>⭐️ 타입 호환표 <img src="https://velog.velcdn.com/images/roong-ra/post/5314f206-4c84-441f-b668-5545b40a3b03/image.png" alt=""></p>
</blockquote>
<hr>
<h1 id="객체-타입-간의-호환성">객체 타입 간의 호환성</h1>
<p>객체 타입 간에는 추가 프로퍼티가 있는 객체가 서브 타입(자식)이 되고, 공통 프로퍼티만 가지고 있는 객체가 슈퍼 타입(부모)가 된다. 객체 타입 역시 Up Cast는 가능하고 Down Cast는 대체로 불가능하다. </p>
<pre><code>// 슈퍼 타입
type Animal = {
  name: string;
  color: string;
};

// 서브 타입
type Dog = {
  name: string;
  color: string;
  breed: string;
};

let animal: Animal = {
  name: &quot;기린&quot;,
  color: &quot;yellow&quot;,
};

let dog: Dog = {
  name: &quot;돌돌이&quot;,
  color: &quot;brown&quot;,
  breed: &quot;진돗개&quot;,
};

animal = dog; // Up Cast ⭕️
console.log(animal); // { name: &#39;돌돌이&#39;, color: &#39;brown&#39;, breed: &#39;진돗개&#39; }

dog = animal; // Down Cast ❌</code></pre><p>또한 아래와 같이 슈퍼 타입의 변수에 서브 타입을 선언한 변수를 넣어 초기화도 가능하다. </p>
<pre><code>let animalExm: Animal = dog;</code></pre><blockquote>
<p>But, 객체 리터럴로 초기화 시 ts의 <strong>초과 프로퍼티 검사</strong>로 인한 오류가 나니 조심!!</p>
</blockquote>
<pre><code>let animalExm: Animal = {
  name: &quot;돌돌이&quot;,
  color: &quot;brown&quot;,
  breed: &quot;진돗개&quot;, ❌ERROR❌
}</code></pre><hr>
<ul>
<li>출처 : <a href="https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8">한 입 크기로 잘라먹는 타입스크립트</a> / <a href="https://ts.winterlood.com/6c9bf87f-6a8f-4e96-95b4-5e12d9f82165#c8a5f8ebaa7d4692a90e3d743bb21dea">docs</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥다이브] 5. 타입 변환과 단축 평가 ]]></title>
            <link>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-5.-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%8B%A8%EC%B6%95-%ED%8F%89%EA%B0%80</link>
            <guid>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-5.-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98%EA%B3%BC-%EB%8B%A8%EC%B6%95-%ED%8F%89%EA%B0%80</guid>
            <pubDate>Sat, 18 Jan 2025 17:42:24 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://product.kyobobook.co.kr/detail/S000001766445">모던 자바스크립트 딥다이브</a> 책의 내용을 기반으로 작성하였습니다.🌿</p>
</blockquote>
<h1 id="1-타입-변환이란">1. 타입 변환이란?</h1>
<p>자바스크립트의 모든 값에는 타입이 있고, 개발자의 의도에 따라 타입을 변환할 수 있다. 
개발자가 의도적으로 타입을 변환하는 것을 <strong>명시적 타입 변환</strong>(explicit coercion) 또는 <strong>타입 캐스팅</strong>(type casting) 이라 한다. </p>
<p>반대로, 개발자의 의도와는 상관 없이 자바스크립트 엔진이 표현식을 평가하는 도중에 암묵적으로 타입이 자동 변환되기도 한다. 이를 <strong>암묵적 타입 변환</strong>(implicit coercion) 또는 <strong>타입 강제 변환</strong>(type coercion)이라 한다. </p>
<p>명시적 타입 변환이나 암묵적 타입 변환은 기존 원시 값을 직접 변경하진 않는다. 원시 값은 변경 불가능한 값(immutable value)이므로 변경할 수 없다. 타입 변환이란 원시 값을 사용하여 다른 타입의 새로운 원시 값을 생성하는 것이다. </p>
<pre><code>let x = 10;

// 명시적 타입 변환
let str = x.toString();
console.log(typeof str, str); // string, 10 
console.log(typeof x, x); // number, 10 --&gt; 원시 값 변경 X

// 암묵적 타입 변환
let str = x + &#39;&#39;;
console.log(typeof str, str); // string 10
console.log(typeof x, x); // number, 10 --&gt; 원시 값 변경 X</code></pre><h1 id="2-암묵적-타입-변환">2. 암묵적 타입 변환</h1>
<h2 id="문자열-타입으로-변환">문자열 타입으로 변환</h2>
<p><code>1 + &#39;2&#39; // &quot;12&quot;</code> 
위 예제의 + 연산자는 피연산자 중 하나 이상이 문자열이므로 <strong>문자열 연결 연산자</strong>로 동작한다.
문자열 연결 연산자의 모든 피연산자는 모두 문자열 타입이어야 하기 때문에, 위 예제의 1은 문자열 타입으로 자동 타입 변환된다. </p>
<p><code>`1 + 1 = ${1 + 1}` // &quot;1 + 1 = 2&quot;</code>
연산자 표현식 뿐만 아니라, 템플릿 리터럴의 표현식도 문자열로 암묵적 타입 변환된다. </p>
<ul>
<li><p>아래는 자바스크립트 엔진이 문자열 타입으로 암묵적 타입 변환을 수행할 때의 동작이다. </p>
<pre><code>// 숫자 타입
0 + &#39;&#39; // &quot;0&quot;
-0 + &#39;&#39; // &quot;0&quot;
1 + &#39;&#39; // &quot;1&quot;
NaN + &#39;&#39; // &quot;NaN&quot;
Infinity + &#39;&#39; // &quot;Infinity&quot;

// 불리언 타입
true + &#39;&#39; // &quot;true&quot;
false + &#39;&#39; // &quot;false&quot; 

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

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

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

// 객체 타입
({}) + &#39;&#39; // &quot;[object object]&quot;
Math + &#39;&#39; // &quot;[object Math]&quot;
[] + &#39;&#39; // &quot;&quot;
[10,20] + &#39;&#39; // &quot;10,20&quot;</code></pre><h2 id="숫자-타입으로-변환">숫자 타입으로 변환</h2>
<pre><code>1 - &#39;1&#39; // 0
1 * &#39;10&#39; // 10
1 / &#39;one&#39; // NaN</code></pre><p>위 예제와 같이, <strong>산술 연산자</strong>의 모든 피연산자는 모두 숫자 타입이어야 한다. 
이 때 피연산자를 숫자 타입으로 변환할 수 없는 경우의 결과는 <strong>NaN</strong>이 된다. </p>
</li>
</ul>
<p><strong>비교 연산자</strong> 또한 문맥 상 모두 숫자 타입이어야 하므로 암묵적 타입 변환된다. 
<code>&#39;1&#39; &gt; 0 // true</code> </p>
<ul>
<li><p>아래는 단항 연산자(+)의 암묵적 타입 변환 동작 과정이다. </p>
<pre><code>// 문자열 타입
+&#39;&#39; // 0
+&#39;0&#39; // 0
+&#39;1&#39; // 1
+&#39;string&#39; // NaN

// 불리언 타입
+true // 1
+false // 0

// null 타입
+null // 0

// undefined 타입
+undefined // NaN

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

// 객체 타입
+{} // NaN
+[] // 0
+[10,20] // NaN</code></pre></li>
<li><p>객체와 빈 배열이 아닌 배열, undefined는 변환되지 않음 </p>
</li>
</ul>
<h2 id="불리언-타입으로-변환">불리언 타입으로 변환</h2>
<p><code>if(&#39;&#39;) console.log(x);</code> 
if나 for 문과 같은 제어문이나 삼항 조건문의 <strong>조건식</strong>은 <strong>불리언 값</strong>으로 평가되어야 한다. 
때문에 자바스크립트 엔진은 조건식의 평가 결과를 불리언 타입으로 자동 변환한다. </p>
<pre><code>if(&#39;&#39;) console.log(&#39;1&#39;);
if(true) console.log(&#39;2&#39;);
if(0) console.log(&#39;3&#39;);
if(&#39;str&#39;) console.log(&#39;4&#39;);
if(null) console.log(&#39;5&#39;);

// 2 4</code></pre><p>이 때 자바스크립트 엔진은 불리언 타입이 아닌 값을 <strong>Truthy 값(참으로 평가되는 값)</strong> 또는 <strong>Falsy 값(거짓으로 평가되는 값)</strong>으로 구분한다. </p>
<ul>
<li>false로 평가되는 Falsy 값 <ul>
<li>false</li>
<li>undefined</li>
<li>null</li>
<li>0, -0</li>
<li>NaN</li>
<li>&#39;&#39;</li>
</ul>
</li>
</ul>
<h1 id="3-명시적-타입-변환">3. 명시적 타입 변환</h1>
<h2 id="문자열-타입으로-변환-1">문자열 타입으로 변환</h2>
<ol>
<li>String 생성자 함수를 new 연산자 없이 호출 </li>
<li>Object.prototype.toString 메서드 사용</li>
<li>문자열 연결 연산자 사용 </li>
</ol>
<pre><code>  // 1. String 생성자 함수를 new 연산자 없이 호출 
  String(1); // &quot;1&quot;
  String(NaN); // &quot;NaN&quot;
  String(Infinity); // &quot;Infinity&quot;
  String(true); // &quot;true&quot;
  String(false); // &quot;false&quot;

  // 2. Object.prototype.toString 메서드 사용
  (1).toString(); // &quot;1&quot;
  (true).toString(); // &quot;true&quot;

  // 3. 문자열 연결 연산자 사용 
  1 + &#39;&#39;; // &quot;1&quot;
  NaN + &#39;&#39;; // &quot;NaN&quot;
  true + &#39;&#39;; // &quot;true&quot; </code></pre><h2 id="숫자-타입으로-변환-1">숫자 타입으로 변환</h2>
<ol>
<li>Number 생성자 함수를 new 연산자 없이 호출</li>
<li>parseInt, parseFloat 함수를 사용 </li>
<li>+단항 산술 연산자 이용</li>
<li>*산술 연산자 이용</li>
</ol>
<pre><code>  // 1. Number 생성자 함수를 new 연산자 없이 호출
  Number(&#39;0&#39;); // 0
  Number(&#39;-1&#39;); // -1
  Number(true); // 1
  Number(false); // 0

  // 2. parseInt, parseFloat 함수를 사용 
  parseInt(&#39;0&#39;); // 0
  parseInt(&#39;-1&#39;); // -1
  parseFloat(&#39;10.53&#39;); // 10.53

  // 3. + 단항 산술 연산자 이용
  +&#39;0&#39;; // 0
  +&#39;-1&#39;; // -1
  +true; // 1
  +false; // 0

  // 4. * 산술 연산자 이용
  &#39;0&#39; * 1; // 0
  &#39;-1&#39; * 1; // -1
  true * 1; // 1
  false * 1; // 0</code></pre><h2 id="불리언-타입으로-변환-1">불리언 타입으로 변환</h2>
<ol>
<li>Boolean 생성자 함수를 new 연산자 없이 호출</li>
<li>! 부정 논리 연산자를 두번 사용 </li>
</ol>
<pre><code>// 1. Boolean 생성자 함수를 new 연산자 없이 호출
Boolean(&#39;x&#39;); // true
Boolean(&#39;&#39;); // false

Boolean(0); // false
Boolean(1); // true

Boolean(NaN); // false
Boolean(Infinity); // true
Boolean(null); // false
Boolean(undefined); // false

Boolean({}); // true
Boolean([]); // true

// 2. ! 부정 논리 연산자를 두번 사용 
!!&#39;x&#39;; // true
!!&#39;&#39;; // false
!!&#39;false&#39;; // true

!!0; // false 
!!1; // true
!!NaN; // false
!!Infinigy; // true
!!null // false
!!undefined; // false

!!{}; // true
!![]; // true</code></pre><hr>
<h1 id="4-단축-평가-⭐️">4. 단축 평가 ⭐️</h1>
<h2 id="논리-연산자를-사용한-단축-평가">논리 연산자를 사용한 단축 평가</h2>
<p>논리 연산자 <strong>논리합(||) *<em>또는 *</em>논리곱(&amp;&amp;)</strong>은 평가 결과가 <del>불리언 값이 아닐 수도 있다.</del> 
이 두 연산자는 *<em>언제나 2개의 피연산자 중 어느 한쪽으로 평가된다. *</em></p>
<h3 id="논리곱-연산자"><strong>논리곱(&amp;&amp;) 연산자</strong></h3>
<p><code>&#39;Cat&#39; &amp;&amp; &#39;Dog // --&gt; &#39;Dog&#39;</code>
논리곱(&amp;&amp;) 연산자는 좌항에서 우항으로 평가되며, 두 개의 피연산자가 모두 True로 평가될 때 True를 반환한다. 
위 예제에서 &#39;Cat&#39;은 Truthy 값이고 두 번째 피연산자인 &#39;Dog&#39;를 평가한다. 이 때 논리 연산의 결과를 결정하는 두 번째 피연산자인 &#39;Dog&#39; 문자열을 그대로 반환한다. </p>
<h3 id="논리합-연산자"><strong>논리합(||) 연산자</strong></h3>
<p><code>&#39;Cat&#39; || &#39;Dog // --&gt; &#39;Cat&#39;</code>
논리합(||) 연산자는 두 개의 피연산자 중 하나만 true로 평가되어도 true를 반환한다. 
때문에 첫 번째 피연산자인 &#39;Cat&#39;이 Truthy 값이므로 true로 평가된다. 두 번째 피연산자까지 평가해보지 않아도 되므로 연산 결과를 결정한 첫 번째 피연산자, 문자열 &#39;Cat&#39;을 반환한다. </p>
<blockquote>
<p>이를 <strong>단축 평가(short-circuit evaluation)</strong>라고 하는데,
단축 평가는 표현식을 평가하는 도중 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 말한다.</p>
</blockquote>
<pre><code>true || anything // true
false || anything // anything
true &amp;&amp; anything // anything
false &amp;&amp; anything // false</code></pre><ul>
<li><p>단축평가는 if문을 대체할 수 있다. </p>
<pre><code>let done = true;
let message = &#39;&#39;;

// if문 
if(done) message = &#39;완료&#39;;
// 단축평가
message = done &amp;&amp; &#39;완료&#39;; </code></pre><pre><code>let done = false; 
let message = &#39;&#39;;

// if문 --&gt; message 할당해야 하니까 !done 사용
if(!done) message = &#39;미완료&#39;;
// 단축평가 --&gt; 작업이 false이면 두번째 피연산자 반환
message = done || &#39;미완료&#39;;</code></pre></li>
<li><p>객체를 가리키는 변수가 Null 또는 Undefined인지 확인하고 참조하기
객체를 가리키는 변수의 값이 null 또는 undefined인 경우 객체의 프로퍼티를 참조하면 TypeError가 발생하고 프로그램이 강제 종료된다. 이 때 단축평가를 사용하면 에러가 발생하지 않는다. </p>
<pre><code>let elem = null;

let value = elem.value; // TypeError❌
let value = elem &amp;&amp; elem.value; // null👍🏻 --&gt; elem이 falsy값이니까 첫번째 피연산자값 반환</code></pre></li>
<li><p>함수 매개변수에 기본값 설정할 때 
함수 호출 시 인수를 전달하지 않으면 매개변수는 Undefined가 할당된다. 이 때 단축평가를 사용하여 매개변수의 기본값을 설정하여 에러를 방지할 수 있다.</p>
<pre><code>function getStringLength(str){
    str = str || &#39;&#39;;
    return str.length;
}

getStringLength(); // 0
getStringLength(&#39;hi&#39;); // 2

// ES6의 매개변수 기본값 설정도 가능!
function getStringLength(str = &#39;&#39;){
    return str.length;
}</code></pre></li>
</ul>
<h2 id="옵셔널-체이닝-연산자--">옵셔널 체이닝 연산자( ?. )</h2>
<p><strong>옵셔널 체이닝 연산자(?.)</strong>는 ES11에서 도입되었다. 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고, 그렇지 않으면 참조를 이어간다. 옵셔널 체이닝 연산자가 없을 때는 위 예제처럼 단축 평가를 통해 null을 체크했다. </p>
<pre><code>let elem = null;
let value = elem?.value;
console.log(value); // undefined

// 단축 평가 시절..
let value = elem &amp;&amp; elem.value;</code></pre><blockquote>
<p>⭐️ 논리곱(&amp;&amp;) 연산자는 <del>0이나 &#39;&#39;를 객체로 평가할 때도 있기 때문에</del>, 옵셔널 체이닝 연산자(?.)를 사용해 주는 것이 안전하겠다.</p>
</blockquote>
<h2 id="null-병합-연산자--">null 병합 연산자( ?? )</h2>
<p>ES11에 도입된 <strong>null 병합 연산자(??)</strong>는 좌항의 피연산자가 null 또는 undefined인 경우 우항의 피연산자를 반환한다. </p>
<pre><code>let foo = null ?? &#39;default string&#39;;
console.log(foo); // &#39;default string&#39;</code></pre><p>null 병합 연산자는 변수에 기본값을 설정할 때 유용하게 사용된다. 
이전에는 논리합(||) 연산자를 사용했지만 좌항의 피연산자가 Falsy값(false, undefined, null, 0, NaN, &#39;&#39;)이면 우항의 피연산자를 반환한다. 하지만 null 병합 연산자는 null 또는 Undefined가 아니면 좌항의 피연산자를 그대로 반환한다. </p>
<pre><code>let foo1 = &#39;&#39; || &#39;default string&#39;;
console.log(foo1); // &#39;default string&#39;

let foo2 = &#39;&#39; ?? &#39;default string&#39;;
console.log(foo2); // &quot;&quot;</code></pre><blockquote>
<p>⭐️Falsy 값인 0이나 &#39; &#39;도 기본값으로 유효하다면, 논리합(||) 연산자 보다는 null 병합 연산자를 사용하는 것이 낫다.</p>
</blockquote>
<p>앞으로 논리합, 논리곱 연산자보다는 상황에 따라 옵셔널 체이닝 연산자나 null 병합 연산자를 사용하여 안전성을 더 높이도록 해야겠다..!!!🔥</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VSCode] SpringBoot 로컬에서 실행하는 법]]></title>
            <link>https://velog.io/@roong-ra/VSCode-SpringBoot-%EC%84%9C%EB%B2%84-%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@roong-ra/VSCode-SpringBoot-%EC%84%9C%EB%B2%84-%EB%A1%9C%EC%BB%AC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Thu, 09 Jan 2025 15:51:22 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>프로젝트 진행 중에 백엔드를 로컬에서 돌려 테스트할 상황이 생겼는데, 백엔드(java) 세팅은 처음 해보는 거라 생각보다 시간이 많이 걸렸다..ㅎㅎ
그 과정들을 정리해 보았다 😀</p>
</blockquote>
<ul>
<li>실행 환경 : MacOS M3, VSCode </li>
</ul>
<h1 id="1-jdk-설치">1. JDK 설치</h1>
<p>JDK는 Java 애플리케이션을 컴파일하고 실행하는 데 필요한 필수 소프트웨어이다.</p>
<ul>
<li><a href="https://www.oracle.com/java/technologies/downloads/?er=221886">ORACLE JDK 설치 링크</a></li>
<li><a href="https://melodyblue.tistory.com/31">참고 : Mac OS에서 JDK 설치하기</a>
<img src="https://velog.velcdn.com/images/roong-ra/post/cdf04dac-603f-4a45-85d7-2483d573022e/image.png" alt="">
맥북 M3는 ARM64 DMG로 설치해야 호환 가능! </li>
</ul>
<pre><code>$ which java     //java 위치 확인 
$ java --version //java 버전 확인  </code></pre><h1 id="2-gradle-설치">2. gradle 설치</h1>
<p>Gradle은 Java 프로젝트 빌드를 자동화하는 도구로, Java Development Kit (JDK)와 함께 사용되어야 한다.</p>
<pre><code>$ brew install gradle
$ gradle -v   </code></pre><h1 id="3-vscode-extension-설치">3. VSCode Extension 설치</h1>
<ul>
<li><strong>Debugger for Java</strong></li>
<li> Red Hat의 Java™에 대한 언어 지원</li>
<li> 자바용 디버거(Debugger for Java) </li>
<li> 자바용 테스트 러너</li>
<li> 자바용 메이블(Maven for Java) </li>
<li> 자바용 프로젝트 관리자(Project manager for Java) </li>
<li> 비주얼 스튜디오 인텔리코드(Visual Studio IntelliCode)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/2097e1f7-5c30-40d9-adf2-a6448947b297/image.png" alt=""></p>
<h1 id="4-aws-cli-설치-및-세팅">4. aws cli 설치 및 세팅</h1>
<p>계속 아래 에러가 나서 찾아보니 aws cli 설정이 추가로 필요했다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/45d30e59-5cc1-4fed-bc06-1d94f0bf28bf/image.png" alt="">
현재 프로젝트에서는 소스 코드 내 민감정보를 외부 저장소에 저장하기 위해 AWS Parameter Store 사용하고 있다. 때문에 AWS Parameter Store를 통해 데이터를 읽기 위해서는 Credential을 세팅해줘야 했다. 
AWS Configure(AWS CLI) 세팅은 Credential을 세팅하는 방법 중 하나로 맥북에서는 간단히 brew를 통해 설치할 수 있고, Access Key, Secret Key, region name 등을 입력하면 된다. </p>
<pre><code>$ brew install awscli // aws cli 설치
$ which aws           // aws 위치 확인
$ aws --version       // aws 버전 확인</code></pre><pre><code>$ aws configure       // aws 구성 세팅 

AWS Access Key ID [None]: (Access Key 입력)
AWS Secret Access Key [None]: (Secret Key 입력)
Default region name [None]: ap-northeast-2 (서울 리전)
Default output format [None]: text / json / table</code></pre><ul>
<li><a href="https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-AWS-CLI-%EC%84%A4%EC%B9%98-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%89%BD%EA%B3%A0-%EB%B9%A0%EB%A5%B4%EA%B2%8C">참고 : aws cli 설치 &amp; 등록 방법</a><h1 id="5-build--start">5. build &amp; start</h1>
build &amp; start 명령어는 각 프로젝트마다 다르게 적용될 수 있다. 
아래 실행한 명령어는 <code>application-local.yml</code> 파일을 실행할 수 있게 세팅된 것이다.</li>
<li>build<ul>
<li>gradlew : Gradle Wrapper로, 빌드 실행 스크립트 </li>
<li>clean : 이전 빌드에서 생성된 모든 파일 삭제</li>
<li>-x test : 특정 작업(test) 제외<pre><code>$ ./gradlew clean build -x test</code></pre></li>
</ul>
</li>
<li>start<ul>
<li>bootRun : Spring Boot 애플리케이션 실행</li>
<li>--args : bootRun에 인수를 전달하는 옵션</li>
<li>&#39;--spring.profiles.active=local&#39; : application-local.yml 파일 사용<pre><code>$ ./gradlew :프로젝트명:bootRun --args=&#39;--spring.profiles.active=local&#39;</code></pre><blockquote>
<p>로컬 테스트 성공!! 🤩</p>
</blockquote>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[typeScript] 2. 기본 타입의 종류 ]]></title>
            <link>https://velog.io/@roong-ra/typeScript-2.-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85%EC%9D%98-%EC%A2%85%EB%A5%98</link>
            <guid>https://velog.io/@roong-ra/typeScript-2.-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85%EC%9D%98-%EC%A2%85%EB%A5%98</guid>
            <pubDate>Thu, 09 Jan 2025 15:47:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/roong-ra/post/bcbc509d-f2e9-4801-9a76-09f1dd7da61a/image.webp" alt=""></p>
<h2 id="1-원시타입과-리터럴타입">1. 원시타입과 리터럴타입</h2>
<h3 id="원시타입primitive-type">원시타입(Primitive Type)</h3>
<ul>
<li><p>동시에 하나의 값만 저장하는 타입 </p>
</li>
<li><p>number / string / boolean / null / undefined </p>
<pre><code>// number
let num1: number = 123;
let num2: number = -123;
let num3: number = 0.123;
let num4: number = -0.123;
let num5: number = Infinity;
let num6: number = -Infinity;
let num7: number = NaN;

// string
let str1: string = &quot;hello&quot;;
let str2: string = &#39;hello&#39;;
let str3: string = `hello`;
let str4: string = `hello ${num1}`;

// boolean
let bool1: boolean = true;
let bool2: boolean = false;

// null
let null1: null = null;

// undefined
let unde1: undefined = undefined;
</code></pre></li>
</ul>
<blockquote>
<p><code>:number</code> 와 같이 타입을 작성하는 문법을 <strong>타입 주석(annotation)</strong> 이라 한다.</p>
</blockquote>
<blockquote>
<p>만약, <strong>다른 타입의 변수에 null 값을 임시로</strong> 넣고 싶다면 tsconfig.json에서 <strong>&quot;strictNullChecks:false&quot;</strong>를 추가 해주면 된다. &quot;strictNullChecks&quot; 옵션은 &quot;strict&quot;옵션의 하위 호환 버전으로 &quot;strict&quot;옵션을 끄면 &quot;strictNullChecks&quot;도 같이 꺼진다.</p>
</blockquote>
<h3 id="리터럴-타입">리터럴 타입</h3>
<ul>
<li>변수의 타입을 값 그 자체로 정의<pre><code>let numB: 10 = 10;
let strA: &quot;hello&quot; = &quot;hello&quot;;
let boolA: true = true;
</code></pre></li>
</ul>
<pre><code>
## 2. 배열과 튜플
### 배열 </code></pre><p>  // 배열
  let numArr: number[] = [1, 2, 3];
  let strArr: string[] = [&quot;hello&quot;, &quot;im&quot;, &quot;yricog&quot;];
  let boolArr: Array<boolean> = [true, false, true]; // 제네릭 문법</p>
<p>  // 배열 요소의 타입이 다양할 경우
  let multiArr: (number | string)[] = [1, &quot;hello&quot;]; // 유니온 타입</p>
<p>  // 다차원 배열의 타입 정의
  let doubleArr: number[][] = [
    [1, 2, 3],
    [4, 5],
  ];</p>
<pre><code>### 튜플
* 길이와 타입이 고정된 배열 </code></pre><p>  let tup1: [number, number] = [1, 2];
  let tup2: [number, string, boolean] = [1, &quot;2&quot;, true];</p>
<p>  /**</p>
<ul>
<li><p>js로 컴파일하면 일반 배열이기 때문에 배열 메서드 사용 가능!</p>
</li>
<li><p>이 때 push, pop을 사용해도 에러가 나지 않는 것은</p>
</li>
<li><p>길이에 제한을 두지 않기 때문이다.</p>
</li>
<li><p>/
tup1.push(1);
tup1.pop();
tup1.pop();
tup1.pop(); // 정상! </p>
<p>const users: [string, number][] = [
[&quot;이아무개&quot;, 1],
[&quot;김수민&quot;, 2],
[&quot;박나래&quot;, 3],
[&quot;김아라&quot;, 4],
];</p>
<pre><code></code></pre></li>
</ul>
<h2 id="3-객체">3. 객체</h2>
<ul>
<li><p>객체 리터럴 타입 </p>
<ul>
<li>optional property(?) : 옵셔널 속성 </li>
<li>readonly : 읽기 전용 <pre><code>let user: {    // 객체 리터럴 타입
id?: number; // optional property
name: string;
} = {
id: 1,
name: &quot;yricog&quot;,
};
</code></pre></li>
</ul>
<p>user.id;
user = { name: &quot;홍길동&quot; }; // id는 옵셔널 </p>
<p>let config: {
  readonly apiKey: string; // readonly
} = {
  apiKey: &quot;API KEY&quot;,
};</p>
<p>// config.apiKey = &quot;hacked&quot;; 변경 불가능!</p>
</li>
</ul>
<pre><code>&gt; 타입을 object로 지정하면 객체 안에 object만 남는다. 
그래서 user.id 와 같이 속성을 지정하면 없는 속성이 된다.

&gt; 위와 같이 구조를 기준으로 타입을 정의하는 것을 **&#39;구조적 타입 시스템(Property Based Type System)&#39;**이라 한다.

## 4. 타입 별칭과 인덱스 시그니처
### 타입 별칭(type alias)</code></pre><p>  type User = {
    id: number;
    name: string;
    nickname: string;
    birth: string;
    bio: string;
    location: string;
  };</p>
<p>  let user: User = {
    id: 1,
    name: &quot;jenna&quot;,
    nickname: &quot;jj&quot;,
    birth: &quot;1999.01.08&quot;,
    bio: &quot;안녕하세요&quot;,
    location: &quot;서울시&quot;,
  };</p>
<pre><code>### 인덱스 시그니처
* key-value의 타입이 어떠한 규칙을 갖게 됨
* 해당 타입은 검사할 객체가 비어 있어도 괜찮다</code></pre><p>  type CountryCodes = {
    [key: string]: string; // 인덱스 시그니처, 비어있어도 된다
    Korea: number; // 꼭 필요한 값
  };</p>
<p>  let countryCodes: CountryCodes = {
    UnitedState: &quot;us&quot;,    // key가 string이면 어떤걸 추가해도 ok.
    UnitedKingdom: &quot;uk&quot;,
    Korea: &quot;ko&quot;,  // 없으면 에러 
  };</p>
<pre><code>
## 5. Enum 타입
* 여러가지 값들에 각각 이름을 부여해 열거해두고 사용하는 타입 
* 값을 지정하지 않으면 자동으로 0부터 숫자가 값으로 부여된다.
* enum은 type과 다르게 컴파일 시 사라지지 않는다.</code></pre><p>  enum Role {
    ADMIN = 0,
    USER = 1,
    GUEST = 2,
  }</p>
<p>  enum Language {
    korean = &quot;ko&quot;,
    english = &quot;en&quot;,
  }</p>
<p>  const user1 = {
    name: &quot;김이박&quot;,
    role: Role.ADMIN, //0
    language: Language.korean,
  };</p>
<p>  const user2 = {
    name: &quot;홍길동&quot;,
    role: Role.USER, //1
  };</p>
<p>  const user3 = {
    name: &quot;아무개&quot;,
    role: Role.GUEST, //2
  };</p>
<pre><code>
## 6. Any와 Unknown 타입
### any 
* 특정 변수의 타입을 우리가 확실히 모를 때 사용
* 단점 : 타입 검사를 다 통과한 다음에 런타임에 오류를 낸다.
  * 사실상 타입 검사를 안하는 것과 같으며, 그것은 타입스크립트가 가진 이점을 포기한다는 것.
  * ~~최대한 사용하지 말기!!~~ </code></pre><p>  let anyVar: any = 10;</p>
<p>  // 모든 타입 할당 가능 
  anyVar = &quot;hello&quot;;
  anyVar = true;
  anyVar = 1;
  anyVar = {};
  anyVar = () =&gt; {};</p>
<p>  let num: number = 10;
  num = anyVar;        // ❗️ 모든 타입의 값에 할당되어질 수 있다.</p>
<pre><code>
### Unknown
* any처럼 아무 변수에나 할당할 수 없다.
  * ~~any 보다 낫다는 점..~~</code></pre><p>  let unknownVar: unknown;</p>
<p>  // 모든 타입 할당 가능 
  unknownVar = &quot;hello&quot;;
  unknownVar = true;
  unknownVar = 1;
  unknownVar = {};
  unknownVar = () =&gt; {};</p>
<p>  let num: number = 10;
  num = unknownVar;     // 할당 불가❌</p>
<p>  // 타입 정제 후 할당 가능 
  if (typeof unknownVar === &quot;number&quot;) {
    num = unknownVar;
  }</p>
<pre><code>

## 7. Avoid와 Never 타입 
### void
* void(= 공허, 아무것도 없음을 의미하는 타입)
* 오직 **undefined만 할당 가능**하다.
* &quot;strictNullChecks&quot;를 false로 하면 **null 값도 할당 가능 **
  * ~~undefined와 null을 타입으로 명시하면 실제로 undefined와 null을 직접 return 해주어야 한다.~~
* return문이 필요없는 함수에는 void를 사용하자.</code></pre><p>  function func1(): string {
    return &quot;hello&quot;;        // string을 리턴
  }</p>
<p>  function func2(): void {
    console.log(&quot;hello&quot;);  // 그냥 출력문, 아무것도 리턴하지 않음 
  }</p>
<p>  let a: void;
  a = 1;         // 할당 불가❌
  a = &quot;hello&quot;;   // 할당 불가❌
  a = {};        // 할당 불가❌
  a = undefined; // 오직 undefined만 담을 수 있다</p>
<pre><code>### never
* never(= 존재하지 않는, 불가능한 타입)
* 함수가 종료될 수 없어서 **이 함수에 반환값 자체가 있는게 모순이다!** 할 때 사용</code></pre><p>  function func3(): never {
    while (true) {} // 무한 루프
  }</p>
<p>  function func4(): never {
    throw new Error(); // 실행 시 프로그램 종료
  }</p>
<p>  // ❗️변수에 never 타입을 사용할 순 있지만, 아무런 값도 담을 수 없다.
  let b: never;</p>
<pre><code>
---
* 출처 : [한 입 크기로 잘라먹는 타입스크립트](https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8) / [docs](https://ts.winterlood.com/6c9bf87f-6a8f-4e96-95b4-5e12d9f82165#c8a5f8ebaa7d4692a90e3d743bb21dea)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[yml 파일에서 .env 파일 생성하기 & Dockerfile 변수명 분기처리 하기 ]]></title>
            <link>https://velog.io/@roong-ra/yml-%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-.env-%ED%8C%8C%EC%9D%BC-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-Dockerfile-%EB%B3%80%EC%88%98%EB%AA%85-%EB%B6%84%EA%B8%B0%EC%B2%98%EB%A6%AC-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@roong-ra/yml-%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-.env-%ED%8C%8C%EC%9D%BC-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0-Dockerfile-%EB%B3%80%EC%88%98%EB%AA%85-%EB%B6%84%EA%B8%B0%EC%B2%98%EB%A6%AC-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 03 Jan 2025 02:25:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>❗️<strong>문제상황</strong>❗️
현재 진행중인 프로젝트는 Dockerfile를 이용해 Docker Image를 만들어 github action으로 자동배포를 진행한다. 그런데 <code>.env</code> 파일을 세팅하다 보니 두 가지 문제가 생겼다. 하나는 <code>.env</code> 파일은 github에 올라가지 않기 때문에 <strong>yml 파일에서 강제로 만들어 배포해야 한다는 것</strong>이고, 다른 하나는 <strong>Dockerfile에서 각 환경에 따른 분기처리를 위한 세팅</strong>을 해야 한다는 것이었다. </p>
</blockquote>
<p>Docker를 처음 다루어봐서 해결하느라 3일이나 걸렸지만 서버 기동하는 것까지 성공하니 엄청 뿌듯하다! 마지막에는 Docker를 로컬에서 테스트하는 방법도 작성해 보도록 하겠다😀</p>
<h1 id="1-yml-파일에서-env-파일-생성하기">1. yml 파일에서 .env 파일 생성하기</h1>
<p>(yml 파일은 dev와 prod로 구분되어 있지만 dev를 기준으로 작성하도록 하겠다.)
먼저, 배포 시 필요한 환경변수 파일은 <code>.env.development</code>와 <code>.env.production</code> 두 가지이다. 각 파일에는 NEXT_PUBLIC_API_URL 이라는 변수와 api 주소가 저장되어 있다. 해당 변수값을  gihub action secrets에 각 환경별로 저장해준다.</p>
<ul>
<li><p><strong>Secrets 저장</strong> </p>
<ul>
<li>DEV_NEXT_PUBLIC_API_URL</li>
<li>PRD_NEXT_PUBLIC_API_URL</li>
</ul>
</li>
<li><p><strong>yml 파일에 명령어 추가</strong>
```</p>
</li>
<li><p>name: Generate Environment Variables File for Devlopment
  run: |</p>
<pre><code>  echo &quot;NEXT_PUBLIC_API_URL=$DEV_NEXT_PUBLIC_API_URL&quot; &gt;&gt; .env.development</code></pre><p>  env:</p>
<pre><code>  DEV_NEXT_PUBLIC_API_URL: ${{secrets.DEV_NEXT_PUBLIC_API_URL}}</code></pre><p>```</p>
</li>
<li><p><strong>해석</strong></p>
<ul>
<li>name: 개발을 위한 환경변수 파일 생성 </li>
<li>run : &quot;NEXT_PUBLIC_API_URL = $DEV_NEXT_PUBLIC_API_URL&quot; 문구를 <code>.env.development</code> 파일을 생성하여 저장</li>
<li>env : DEV_NEXT_PUBLIC_API_URL 는 secrets의  DEV_NEXT_PUBLIC_API_URL 값을 가져옴 </li>
</ul>
</li>
</ul>
<p>이렇게 하면 <code>.env.development</code> 을 생성하여 <code>NEXT_PUBLIC_API_URL=http://0.00.00.00:8080</code> 처럼 기존 파일과 같은 내용이 저장되고, 코드 내부에서 해당 변수를 사용할 수 있게 된다.</p>
<h1 id="2-dockerfile-변수명-분기처리-하기">2. Dockerfile 변수명 분기처리 하기</h1>
<p><code>.env</code> 파일을 생성한 뒤 <code>package.json</code> 파일 또한 다음과 같이 수정하게 되었다.</p>
<pre><code>&quot;scripts&quot;: {
    &quot;dev&quot;: &quot;env-cmd -f .env.local next dev&quot;,
    &quot;build:dev&quot;: &quot;env-cmd -f .env.development next build&quot;,
    &quot;build:prod&quot;: &quot;env-cmd -f .env.production next build&quot;,
    &quot;start:dev&quot;: &quot;env-cmd -f .env.development next start&quot;,
    &quot;start:prod&quot;: &quot;env-cmd -f .env.production next start&quot;
}</code></pre><p>때문에 <code>Dockerfile</code> 에서는 <strong>script 실행 명령어</strong>와 <strong>파일 복사</strong>하는 부분에서 변수를 사용하여 분기처리 할 수 있도록 수정해 주었다.</p>
<pre><code># Build 
ARG BUILD_ENV
RUN pnpm run build:${BUILD_ENV}

# Copy environment file
ARG ENVIRONMENT
COPY ../.env.${ENVIRONMENT} /app/.env.${ENVIRONMENT}

# Start Next.js 
EXPOSE 3000
ARG BUILD_ENV
ENV BUILD_ENV=${BUILD_ENV}

CMD [&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;pnpm run start:${BUILD_ENV}&quot;]</code></pre><p>해당 변수는 다음과 같이 yml 파일에서 변수 값을 지정하여 사용하면 된다. (Docker 이미지 빌드 시 적용)</p>
<pre><code>- name: Build Docker image
    run: |
          docker build \
            -t project-name:latest \
            -f .docker/Dockerfile \
            --build-arg BUILD_ENV=dev \
            --build-arg ENVIRONMENT=development .</code></pre><h1 id="3-docker-로컬-테스트">3. Docker 로컬 테스트</h1>
<ol>
<li>터미널에서 <code>docker ps</code> 명령어로 실행 중인 컨테이너 있는지 확인 </li>
<li>해당 프로젝트 &amp; 브랜치 이동 </li>
<li><code>docker build -t project-name:latest -f .docker/Dockerfile --build-arg BUILD_ENV=dev --build-arg ENVIRONMENT=development .</code> 로 docker 띄우기 </li>
<li>다시 <code>docker ps</code> 로 확인 <img src="https://velog.velcdn.com/images/roong-ra/post/d1378bb2-7850-4154-b578-defdf144bd0f/image.png" alt="">
<a href="https://www.docker.com/">Docker Desktop</a> 에서도 확인 가능하다!
<img src="https://velog.velcdn.com/images/roong-ra/post/2b200aff-f4fc-47e9-a781-74c35320c0ed/image.png" alt=""></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥다이브] 4. 연산자]]></title>
            <link>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Sun, 22 Dec 2024 17:21:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://product.kyobobook.co.kr/detail/S000001766445">모던 자바스크립트 딥다이브</a> 책의 내용을 기반으로 작성하였습니다.🌿</p>
</blockquote>
<h1 id="연산자">연산자</h1>
<h2 id="1-산술-연산자">1. 산술 연산자</h2>
<p>산술 연산자는 수학적 계산을 수행해 새로운 숫자 값을 만든다. 산술 연산이 불가능할 경우 NaN을 반환한다.
산술 연산자는 피연산자의 개수에 따라 이항 / 단항 산술 연산자로 구분된다. </p>
<h3 id="이항-산술-연산자">이항 산술 연산자</h3>
<ul>
<li>2개의 피연산자를 산술<pre><code>5 + 2; // 7
5 - 2; // 3
5 * 2; // 10
5 / 2; // 2.5
5 % 2; // 1</code></pre><h3 id="단항-산술-연산자">단항 산술 연산자</h3>
</li>
<li>1개의 피연산자를 산술 <code>++, --, +, -</code><pre><code>let x = 1;
x++; // x = x + 1
console.log(x); // 2
</code></pre></li>
</ul>
<p>x--; // x = x - 1
console.log(x); // 1</p>
<pre><code>* 전위 증가/감소```++, --``` 연산자는 피연산자의 값을 먼저 증가/감소 시킨 후 다른 연산을 수행한다. 피연산자의 값을 변경하는 부수 효과가 있는 것으로, **암묵적 할당**이 이뤄지게 된다. </code></pre><p>let x=5, result;</p>
<p>// 선할당 후증가
result = x++;
console.log(result, x); // 5, 6</p>
<p>// 선증가 후할당
result = ++x;
console.log(result, x); // 7, 7</p>
<p>// 선할당 후감소
result = x--;
console.log(result, x); // 7, 6</p>
<p>// 선감소 후할당 
result = --x;
console.log(result, x); // 5, 5</p>
<pre><code>* ```+``` 연산자는 피연산자에 어떠한 효과도 없다. 음수를 양수로 반전하지도 않는다.</code></pre><p>+10; // 10
+(-10); // -10 </p>
<pre><code>* ```-``` 연산자는 피연산자의 부호를 반전한 값을 반환한다. </code></pre><p>-(-10); // 10</p>
<pre><code>* 숫자 타입이 아닌 피연산자에 ```+, -``` 연산자를 사용하면 숫자 타입으로 변환하여 반환한다. 부수 효과는 없다. </code></pre><p>let x = &#39;1&#39;;</p>
<p>console.log(+x); // 1 -&gt; 숫자타입으로 반환 
console.log(x); // &quot;1&quot; -&gt; 문자열 그대로다. 부수효과 없음! </p>
<pre><code>### 문자열 연결 연산자 
```+``` 연산자는 피연산자 중 하나 이상이 문자열인 경우 문자열 연결 연산자로 동작한다. </code></pre><p>&#39;1&#39; + 2; // &#39;12&#39;</p>
<p>// 암묵적 타입 변환 
1 + true // 2 (true = 1)
1 + false // 1 (false = 0)
1 + null // 1 (null = 0)</p>
<p>// undefined는 숫자 타입으로 변환되지 X 
+undefined; // NaN
1 + undefined; // NaN</p>
<pre><code>자바스크립트 엔진은 암묵적으로 불리언 타입을 숫자 타입으로 강제 변환한 뒤 연산을 수행하는데, 이를 **암묵적 타입 변환** 또는 **타입 강제 변환** 이라고 한다. 

---
## 2. 할당 연산자 
할당 연산자는 피연산자의 결과 값을 변수에 할당한다. </code></pre><p>let x;</p>
<p>x = 10; // 10
x += 5; // 15
x -= 5; // 10</p>
<pre><code>할당문은 값으로 평가되는 표현식인 문으로써 할당된 값으로 평가된다. 때문에 할당문 자체를 다른 변수에 할당할 수도 있다. </code></pre><p>let x;
console.log(x = 10); // 10</p>
<p>/* 
 &lt; 연쇄할당 순서 &gt;
    1. c = 0
    2. b = 0
    3. a = 0
*/
let a, b, c;
a = b = c = 0; 
console.log(a, b, c); // 0 0 0</p>
<pre><code>---
## 3. 비교 연산자
비교 연산자는 좌,우항의 피연산자를 비교하여 결과를 불리언 값으로 반환한다. 

### 동등/일치 비교 연산자 
동등 비교 연산자(==)와 일치 비교 연산자(===)는 좌,우항의 피연산자가 같은 값으로 평가되는지를 검증하지만 그 엄격성의 정도가 다르다. 

* x == y : x와 y의 값이 같음 
* x === y : x와 y의 값과 타입이 같음
* x != y : x와 y의 값이 다름
* x !== y : x와 y의 값과 타입이 다름 

**동등 비교 연산자(==)**는 먼저 **암묵적 타입 변환**을 통해 타입을 일치시킨 후 같은 값인지를 비교한다. 이는 편리한 경우도 있지만 결과를 예측하기 어려워 실수하기 쉽다. </code></pre><p>5 == 5; // true
5 == &#39;5&#39;; // true</p>
<p>&#39;0&#39; == &#39;&#39;; // false 
0 == &#39;&#39;; // true
0 == &#39;0&#39;; // true
false == &#39;false&#39;; // false
false == &#39;0&#39;; // true
false == null; // false
false == undefined; // false </p>
<pre><code>**일치 비교 연산자(===)**는 값과 타입 모두 같은 경우에 한하여 true를 반환한다. 때문에 예측하기 쉽다. </code></pre><p>5 === 5; // true
5 === &#39;5&#39;; // false </p>
<pre><code>
NaN은 자신과 일치하지 않는 유일한 값이다. NaN인지 검증하려면 **Number.inNaN**을 사용하자.</code></pre><p>NaN === NaN; // false
Number.isNaN(NaN); // true</p>
<pre><code>JS에는 양의 0과 음의 0이 있는데, 이 둘은 본래 true를 반환한다. 이를 정확히 구분하기 위해서는 **Object.is** 메서드를 사용하자.</code></pre><p>0 === -0; // true
0 == -0; // true </p>
<p>Object.is(-0, +0); // false 
Object.is(NaN, NaN); // true</p>
<pre><code>
### 대소 관계 비교 연산자
대소 관계 비교 연산자는 피연산자의 크기를 비교하여 불리언 값으로 반환한다. </code></pre><p>5 &gt; 0; // true
5 &gt; 5; // false
5 &gt;= 5; // true
5 &lt;= 5; // true</p>
<pre><code>---
## 4. 삼항 조건 연산자 
삼항 조건 연산자는 조건식의 결과에 따라 반환할 값이 결정된다. 
* 조건식 ? 조건식이 True일 때 반환할 값 : 조건식이 False일 때 반환할 값

또한 삼항 조건 연산자는 값으로 평가될 수 있는 표현식인 문이다. 
따라서 if...else 문과 다르게 값처럼 사용될 수 있다. </code></pre><p>let x = 2;
let result = x % 2 ? &#39;홀수&#39; : &#39;짝수&#39;;
console.log(result); // 짝수 </p>
<pre><code>
---
## 5. 논리 연산자 
논리 연산자는 좌,우항의 피연산자를 논리 연산한다. </code></pre><p>// 논리합(||) 연산자 
true || true; // true
true || false; // true
false || true; // true
false || false; // false </p>
<p>// 논리곱(&amp;&amp;) 연산자
true &amp;&amp; true; // true
true &amp;&amp; false; // false
false &amp;&amp; true; // false
false &amp;&amp; false; // false </p>
<p>// 논리 부정(!) 연산자 
!true; // false
!false; // true</p>
<p>// 논리 부정 연산자의 암묵적 타입 변환
!0; // true
!&#39;Hello&#39;; // false </p>
<pre><code>위 예시처럼, 논리 부정 연산자는 암묵적 타입 변환을 해서라도 **언제나 불리언 값을 반환**한다. 하지만 논리합(||) 또는 논리곱(&amp;&amp;) 연산자의 표현식 결과는 **불리언 값이 아닐 수도 있으며**, 2개의 피연산자 중 어느 한쪽으로 평가된다.  (이후 &#39;단축 평가&#39;에서 자세히 알아보자) </code></pre><p>&#39;Cat&#39; &amp;&amp; &#39;Dog&#39;; // &#39;Dog&#39;</p>
<pre><code>### 드 모르간의 법칙 
논리 연산자로 구성된 복잡한 표현식을 가독성 좋은 코드로 변환해보자.</code></pre><p>!(x || y) === (!x &amp;&amp; !y)
!(x &amp;&amp; y) === (!x || !y)</p>
<pre><code>---
## 6. 쉼표 연산자 
쉼표 연산자는 왼쪽부터 차례대로 피연산자를 평가하고, 평가가 끝나면 마지막 피연산자의 결과를 반환한다.</code></pre><p>let x, y, z;
x = 1, y = 2, z = 3; // 3 </p>
<pre><code>---
## 7. 그룹 연산자
소괄호```()```로 피연산자를 감싼 그룹 연산자는 표현식을 가장 먼저 평가한다. 그룹 연산자는 연산자 우선순위가 가장 높다. </code></pre><p>10 * 2 + 3; // 23
10 * (2 + 3); // 50</p>
<pre><code>---
## 8. typeof 연산자
typeof 연산자는 피연산자의 데이터 타입을 문자열로 반환한다. typeof가 반환하는 문자열은 7개의 데이터 타입과 정확히 일치하지는 않는다.  </code></pre><p>typeof &#39;&#39; // string
typeof 1 // number
typeof NaN // number
typeof true // boolean
typeof undefined // undefined
typeof Symbol() // symbol
typeof null // ❌object
typeof [] // object
typeof {} // object
typeof new Date() // object
typeof /test/gi // object
typeof function(){} // function </p>
<pre><code>```typeof null``` 의 결과는 object를 반환하는데, 이는 **자바스크립트의 첫 번째 버그**이다.
(~~기존 코드에 영향을 줄 수 있기 때문에 아직 수정되지 못하고 있다고 한다~~🫢)
때문에 null 타입을 확인할 때는 일치 연산자(===)를 사용하도록 하자.</code></pre><p>let foo = null;
typeof foo === null; // false
foo === null // true </p>
<pre><code>또 하나 주의할 점은, 선언하지 않은 식별자를 typeof로 연산할 때 ```ReferenceError```가 아닌 ```undefined```를 반환한다. </code></pre><p>typeof undeclared; // undefined </p>
<pre><code>---
## 9. 지수 연산자
지수 연산자는 ES7에서 도입된 것으로, 좌항의 피연산자를 밑(base)로, 우항의 피연산자를 지수(exponent)로 거듭 제곱하여 숫자를 반환한다. 지수 연산자가 도입되기 전에는 Math.pow 메서드를 사용했었다. </code></pre><p>2 ** 2; // 4
2 ** 2.5 // 5.6568...
2 ** 0 // 1
2 ** -2 // 0.25</p>
<p>// Math.pow 메서드 예시 
Math.pow(2,2) // 4</p>
<pre><code>음수를 거듭제곱의 밑으로 사용하려면 괄호로 묶어보자. </code></pre><p>-5 ** 2; // SyntaxError
(-5) ** 2; // 25</p>
<pre><code>할당 연산자와 함께 사용 가능한 지수 연산자</code></pre><p>let num = 5;
num **= 2;</p>
<pre><code>지수 연산자는 이항 연산자 중 우선순위가 가장 높다.</code></pre><p>2 * 5 ** 2; // 50 </p>
<h2 id="">```</h2>
<h2 id="10-그-외의-연산자">10. 그 외의 연산자</h2>
<p>그 외 연산자들은 다른 주제와 연관하여 추후 자세히 살펴보도록 하자! </p>
<ul>
<li><code>?.</code> 옵셔널 체이닝</li>
<li><code>??</code> null 병합 연산자</li>
<li><code>delete</code> 프로퍼티 삭제</li>
<li><code>new</code> 생성자 함수 호출 시 인스턴스 생성</li>
<li><code>instanceof</code> 좌변의 객체가 우변의 생성자 함수와 연결된 인스턴스인지 판별</li>
<li><code>in</code> 프로퍼티 존재 확인 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[github] import repository로 레포 가져오기 & 변경사항 업데이트하기]]></title>
            <link>https://velog.io/@roong-ra/github-import-repository%EB%A1%9C-%EB%A0%88%ED%8F%AC-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@roong-ra/github-import-repository%EB%A1%9C-%EB%A0%88%ED%8F%AC-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-%EB%B3%80%EA%B2%BD%EC%82%AC%ED%95%AD-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 15 Dec 2024 09:08:21 GMT</pubDate>
            <description><![CDATA[<h2 id="상황">상황</h2>
<blockquote>
<p>Github Organization에서 repo 생성 후 프로젝트를 진행하는 중에, 작업중인 repo를 개인 Github에서도 확인하고 관리하고 싶어졌다.</p>
</blockquote>
<h2 id="해결책">해결책</h2>
<h3 id="1-github-import-repository">1. Github Import Repository</h3>
<p>먼저 Organization에서 repo를 가져오는 방법은 <code>Fork</code>와 <code>importer</code> 두 가지가 있다. 하지만 <code>Fork</code>는 repo를 가져온 뒤 최신 변경 사항을 업데이트 하기 위해서는 Pull Request를 사용해야 하고, <code>importer</code>는 upstream repo를 origin remote로 등록한 뒤 fetch만 해주면 되었다. 그래서 <code>importer</code> 를 사용하는 것으로 결정! </p>
<p>Github에서 repository를 import하는 과정은 다음과 같다. </p>
<ul>
<li>개인 github에서 오른쪽 상단에 있는 + 버튼을 클릭한 뒤 Import repository로 접속한다. <img src="https://velog.velcdn.com/images/roong-ra/post/fe7f9a05-2fc5-4ab5-b464-6ad010ab80ca/image.png" alt=""></li>
<li>가져올 repository의 URL을 입력한다. (<code>.git</code>으로 끝나는 것 확인) </li>
<li>username과 access token을 입력한다. <img src="https://velog.velcdn.com/images/roong-ra/post/1377b73e-e691-41fd-8fba-591511ddb0d8/image.png" alt=""></li>
<li>아래 Begin import 버튼 누르면 복제 시작! </li>
</ul>
<h3 id="2-최신-변경사항-업데이트-하기">2. 최신 변경사항 업데이트 하기</h3>
<ul>
<li>복제된 repo를 로컬로 clone<ul>
<li><code>git clone (복제된 repository url)</code></li>
</ul>
</li>
<li>원본 repo 주소를 upstream으로 등록<ul>
<li><code>git remote add upstream (원본 repository url)</code></li>
</ul>
</li>
<li>upstream  등록되었는지 확인<ul>
<li><code>git remote -v</code><img src="https://velog.velcdn.com/images/roong-ra/post/d04a5f16-14e9-4558-bfa8-1df63ee92cf5/image.png" alt=""></li>
</ul>
</li>
<li>upstream(원본 저장소) 최신 변경사항 가져오기<ul>
<li>upstream 등록 후 업데이트는 여기서부터만 진행하면 된다!</li>
<li><code>git fetch upstream</code> </li>
</ul>
</li>
<li>변경사항 merge 및 push 하기 <ul>
<li><code>git checkout main</code></li>
<li><code>git merge upstream/main</code></li>
<li><code>git push origin main</code></li>
</ul>
</li>
</ul>
<hr>
<p>이렇게 하면 원본 repository를 복제한 뒤 최신 변경사항 업데이트까지 주기적으로 진행할 수 있다! 😀</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[typeScript] 1. 설치 및 config 옵션 설정하기]]></title>
            <link>https://velog.io/@roong-ra/typeScript-01.-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%A1%A0</link>
            <guid>https://velog.io/@roong-ra/typeScript-01.-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%A1%A0</guid>
            <pubDate>Mon, 02 Dec 2024 13:33:01 GMT</pubDate>
            <description><![CDATA[<h2 id="hello-ts-world">Hello TS World!</h2>
<ol>
<li>초기화 및 설치<ul>
<li><code>npm init</code></li>
<li><code>npm i @types/node</code> : node.js 내장 기능들의 타입 정보 패키지(ex_console)</li>
<li><code>npm i -g typescript</code> : 타입스크립트 컴파일러(tsc) 설치</li>
</ul>
</li>
<li>ts -&gt; js 컴파일<ul>
<li>src/index.ts 파일 생성</li>
<li><code>tsc src/index.ts</code> : 컴파일된 index.js파일 생성</li>
<li><code>node src/index.js</code> : index.js 파일 실행</li>
</ul>
</li>
<li>컴파일과 실행을 동시에<ul>
<li><code>npm i -g tsx</code></li>
<li><code>tsx src/index.ts</code> : 바로 node로 실행</li>
</ul>
</li>
</ol>
<h2 id="컴파일러-옵션-설정하기">컴파일러 옵션 설정하기</h2>
<ol>
<li><p>컴파일러 옵션 파일 생성</p>
<ul>
<li><code>tsc --init</code></li>
</ul>
</li>
<li><p>컴파일 옵션 설정</p>
<pre><code>{
   &quot;compilerOptions&quot;: {
      &quot;target&quot;: &quot;ESNext&quot;,   // js 버전 설정
      &quot;module&quot;: &quot;ESNext&quot;,   // js 모듈 시스템 설정
      &quot;outDir&quot;: &quot;dist&quot;,     // 컴파일된 js파일 위치 설정
      &quot;strict&quot;: true,       // 타입검사 엄격 여부
      &quot;moduleDetection&quot;: &quot;force&quot;, // ts의 파일 모듈 인식 여부 - 개별/전역
      &quot;skipLibCheck&quot;: true  // 타입 정의 파일(.d.ts)의 타입 검사 생략
   },
   &quot;include&quot;: [
      &quot;src&quot;                 // 컴파일할 파일의 범위와 위치 설정
   ]
}
</code></pre><blockquote>
<ul>
<li>ts파일은 전역모듈로 인식되기 때문에, 각각 다른 ts파일이라도 같은 변수명을 사용하면 에러가 난다. (하나의 모듈로 인식) 때문에, <strong>export{}</strong> 같은 모듈시스템을 사용하는 키워드를 사용 해주어야 개별 파일로 인식할 수 있다.</li>
<li><strong>&#39;moduleDetection&#39;</strong> 옵션을 설정한 뒤 같은 변수명이 있는 ts파일을 컴파일하면 js 파일 내부에 &#39;export {};&#39; 코드가 생성된 것을 확인할 수 있다. <img src="https://velog.velcdn.com/images/roong-ra/post/52b1e531-e8ad-4a31-a9ff-614017572c90/image.png" alt=""></li>
</ul>
</blockquote>
</li>
</ol>
<hr>
<ul>
<li>출처 : <a href="https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8">한 입 크기로 잘라먹는 타입스크립트</a> / <a href="https://ts.winterlood.com/6c9bf87f-6a8f-4e96-95b4-5e12d9f82165#c8a5f8ebaa7d4692a90e3d743bb21dea">docs</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥다이브] 3. 데이터 타입]]></title>
            <link>https://velog.io/@roong-ra/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-6%EC%9E%A5</link>
            <guid>https://velog.io/@roong-ra/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-6%EC%9E%A5</guid>
            <pubDate>Mon, 16 Sep 2024 11:26:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://product.kyobobook.co.kr/detail/S000001766445">모던 자바스크립트 딥다이브</a> 책의 내용을 기반으로 작성하였습니다.🌿</p>
</blockquote>
<h1 id="데이터-타입">데이터 타입</h1>
<h2 id="숫자-타입">숫자 타입</h2>
<p>C나 Java의 경우 정수(소수점 이하 없는 숫자)와 실수(소수점 이하 있는 숫자) 구분이 가능한 다양한 숫자 타입을 제공한다. 하지만 자바스크립트는 모든 수를 실수로 처리하며, 정수를 위한 데이터 타입이 존재하지 않는다. </p>
<p>다음과 같은 특별한 값도 표현 가능하다. </p>
<ul>
<li>Infinity : 양의 무한대</li>
<li>-Infinity : 음의 무한대</li>
<li>NaN : 산술 연산 불가(not-a-number) <pre><code>console.log(10 / 0) // Infinity
console.log(10 / -0) // -Infinity
console.log(1 * &#39;string&#39;) //NaN</code></pre><h2 id="문자열-타입">문자열 타입</h2>
문자열은 0개 이상의 16비트 유니코드 문자(UTF-16)의 집합으로 전 세계 대부분의 문자를 표현할 수 있다. 
작은 따옴표(&#39;&#39;), 큰 따옴표(&quot;&quot;) 또는 백틱(``)으로 감싸서 표현 가능하다. <pre><code>var string = &#39;문자열&#39;;</code></pre>자바스크립트의 문자열은 원시 타입이며, 변경 불가능한 값(immutable value)이다. </li>
</ul>
<h2 id="템플릿-리터럴">템플릿 리터럴</h2>
<p>ES6에 도입된 템플릿 리터럴은 백틱을 사용해 표기하며, 멀티라인 문자열 / 표현식 삽입 / 태그드 템플릿 등 편리한 문자열 기능을 제공한다. </p>
<pre><code>var template = `&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;`

var first = &#39;Enna&#39;;
var last = &#39;Kim&#39;;
console.log(`My name is ${first} ${last}.`) // My name is Enna Kim.

console.log(`1 + 2 = ${1 + 2}`) // 1 + 2 = 3</code></pre><h2 id="불리언-타입">불리언 타입</h2>
<p>논리적 참과 거짓을 나타내는 true, false 값</p>
<pre><code>var foo = true;
console.log(foo); //true

foo = false;
console.log(foo); //false</code></pre><h2 id="undefined-타입">undefined 타입</h2>
<p>변수를 선언하면 암묵적으로 undefined로 초기화 된다. 따라서 값을 할당하지 않은 변수를 참조하면 undefined가 반환된다. undefined는 개발자가 의도적으로 할당하기 위한 값이 아니라, 자바스크립트 엔진이 변수를 초기화할 때 사용되는 값이다. 따라서 <del><strong>개발자가 의도적으로 undefined 값을 할당하는 것은 본래 취지와 어긋나므로 권장되지 않는다.</strong></del> </p>
<h2 id="null-타입">null 타입</h2>
<p>null 타입은 변수에 값이 없다는 것을 의도적으로 명시할 때 사용한다. null을 할당하는 것은 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미이며, 자바스크립트 엔진은 참조되지 않는 메모리 공간에 대해 가비지 콜렉터를 수행하게 된다. </p>
<p>또한 함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환하기도 한다. </p>
<h2 id="심벌-타입">심벌 타입</h2>
<p>ES6에서 추가된 7번째 타입으로, <strong>변경 불가능한 원시 타입의 값</strong>이다. 또한 다른 값과 <strong>중복되지 않는 유일무이한 값</strong>이다. 
<code>Symbol</code> 함수를 호출해 생성하며, 생성된 심벌 값은 <strong>외부에 노출되지 않는다</strong>. </p>
<pre><code>var key = Symbol(&#39;key&#39;);
console.log(typeof key); // symbol</code></pre><p>(33장에서 자세히-)</p>
<blockquote>
<p>💡 자바스크립트의 데이터 타입은 크게 원시 타입과 객체 타입으로 분류된다. 자바스크립트는 객체 기반의 언어이며, 자바스크립트를 이루고 있는 거의 모든 것이 객체라는 사실을 기억하자. 
<del>(객체 타입에 대해선 11장에서 자세히 살펴볼 예정)</del></p>
</blockquote>
<h1 id="데이터-타입의-필요성">데이터 타입의 필요성</h1>
<p>자바스크립트 엔진은 <strong>데이터 타입에 따라 정해진 크기의 메모리 공간을 확보</strong>한다. </p>
<p>예를들어, 숫자 100을 2진수로 저장한다고 했을 때 자바스크립트 엔진은 8바이트의 메모리 공간을 확보하고 저장한다. 
반대로 이 값을 참조할 경우, 식별자를 통해 숫자 타입의 값 100이 저장되어 있는 메모리 공간의 선두 메모리셀의 주소를 찾아가 8바이트만큼 읽어오게 된다. 
이처럼 값을 참조하기 위해 한번에 읽어 들여야 할 메모리 공간의 크기(메모리셀의 개수)를 알아야 한다. </p>
<p>또한 메모리에서 읽어들인 2진수를 <strong>데이터 타입에 따라 다르게 해석</strong>될 수 있다. 
예를들어 저장된 값 0100 0001을 숫자로 해석하면 65이지만 문자열로 해석하면 &#39;A&#39;이다. </p>
<blockquote>
<p><strong>데이터 타입이 필요한 이유</strong> </p>
</blockquote>
<ul>
<li>저장 시 메모리 공간의 크기를 결정하기 위해 </li>
<li>값 참조 시 읽어들일 메모리 공간의 크기를 결정하기 위해</li>
<li>2진수를 어떻게 해석할지 결정하기 위해 </li>
</ul>
<h1 id="동적-타이핑">동적 타이핑</h1>
<p>C나 자바같은 언어는 <strong>변수 선언 시 데이터 타입을 선언해야 하는 정적 타입 언어</strong>이다. 정적 타입 언어는 컴파일 시점에 타입 체크를 수행하는데, 만약 타입 체크를 통과하지 못하면 에러를 발생시킨다. 자바스크립트는 이와 다르게 변수 선언 시 타입을 선언하지 않으며 어떤 데이터 타입의 값이라도 자유롭게 할당이 가능하다. </p>
<p>즉, 정적 타입 언어는 변수 선언 시점에 타입이 결정되고 변수의 타입을 결정할 수 없다. 반면에 자바스크립트는 값을 할당하는 시점에 변수의 타입이 동적으로 결정되고 변수의 타입을 언제든지 변경할 수 있다.</p>
<p>다시 말해, 자바스크립트의 변수는 <strong>선언이 아닌 할당에 의해 타입이 결정(타입 추론)</strong>되며 <strong>재할당에 의해 변수의 타입은 언제든지 동적으로 변경 될 수 있다.</strong> 이러한 특징을 <strong>동적 타이핑(dynamic typing)</strong>이라고 한다. </p>
<p>자바스크립트와 같은 동적 타입 언어는 <del><strong>유연성은 높지만 신뢰성은 떨어져</strong></del> 안정적인 프로그램 개발을 위해 주의해야 할 사항이 있다. </p>
<blockquote>
</blockquote>
<ul>
<li>오류 발생 가능성을 낮추기 위해 변수는 필요한 만큼 최소한으로 유지할 것 </li>
<li>변수의 스코프는 최대한 좁게 만들 것 </li>
<li>전역 변수는 최대한 사용하지 않을 것 </li>
<li>변수보다는 상수(const)를 사용할 것 </li>
<li>변수 네이밍은 목적과 의미에 맞게 할 것 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥다이브] 2. 변수 ]]></title>
            <link>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EB%B3%80%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EB%B3%80%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</guid>
            <pubDate>Tue, 10 Sep 2024 17:27:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://product.kyobobook.co.kr/detail/S000001766445">모던 자바스크립트 딥다이브</a> 책의 내용을 기반으로 작성하였습니다.🌿</p>
</blockquote>
<h1 id="변수">변수</h1>
<h2 id="변수란-무엇인가">변수란 무엇인가</h2>
<p>컴퓨터는 CPU를 사용해 연산하고, 메모리를 사용해 데이터를 기억한다.<br>메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체이며, <strong>메모리 셀 하나의 크기는 1바이트(8비트)</strong> 이다. 
컴퓨터는 1바이트 단위로 데이터를 저장하거나 읽어들인다. </p>
<p>각 셀은 고유의 메모리 주소를 갖는다. 메모리 주소는 메모리 공간의 위치를 나타내며, 0부터 메모리 크기만큼 정수로 표현된다.(0x00000000 ~ 0xFFFFFFFF) 
또한, <strong>컴퓨터는 모든 데이터를 2진수로 처리</strong>한다. 메모리에 저장되는 데이터는 데이터의 종류와 상관없이 모두 2진수로 저장된다.</p>
<p><code>10 + 20</code> 이라는 식이 있다. 컴퓨터는 10과 20을 각 메모리셀에 저장하고 그에 대한 연산 결과인 30도 새로운 메모리셀에 저장한다. 이 때 30이라는 결과값을 재사용하기 위해 메모리 공간을 식별하기 위한 이름인 <strong>변수</strong>를 사용한다. 
값에 직접 접근하는 것은 치명적인 오류가 발생할 가능성이 있기 때문에 <strong>자바스크립트는 개발자의 직접적인 메모리 제어를 허용하지 않는다.</strong> <code>var result = 10 + 20</code></p>
<p>변수 이름을 <strong>식별자(identifier)</strong>라고도 한다. 식별자는 값이 저장되어 있는 메모리 주소와 매핑 관계를 맺고, 이 매핑 정보 또한 메모리에 저장된다. 식별자는 값이 아닌 <strong>메모리 주소</strong>를 기억한다. (변수 이름을 비롯한 모든 식별자는 <strong>실행 컨텍스트(execution context)</strong>에 등록된다. 자바스크립트 엔진은 실행 컨텍스트를 통해 식별자와 스코프를 관리한다.)</p>
<p><strong>변수 선언</strong>이란, 변수를 생성하여 값을 저장하기 위한 메모리 공간을 확보하는 것을 말한다. 
변수 선언에 의해 확보된 메모리 공간은 확보가 해제되기 전까지는 아무도 사용할 수 없게 보호된다. 
변수 선언 키워드에는<code>var, let, const</code>가 있다.
자바스크립트 엔진은 변수 선언 시 <strong>선언단계</strong>와 <strong>초기화 단계</strong>를 거쳐 수행된다.</p>
<ul>
<li>선언 단계 : 자바스크립트 엔진에 변수의 존재를 알림</li>
<li>초기화 단계 : 메모리 공간을 확보하고 undefined를 할당하여 초기화</li>
</ul>
<p>때문에 <code>var score;</code> 와 같이 변수를 선언한다면, score에는 암묵적으로 <strong>undefined</strong>가 할당될 것이다. 
만약 초기화 단계를 거치지 않으면 이전에 사용했던 값인 <strong>쓰레기 값(garbage value)</strong>가 남아있을 수 있기 때문에 꼭 초기화 단계를 거치게 된다.</p>
<p>변수 및 모든 식별자 사용 시 선언하지 않은 식별자에 접근하면 <del><strong>ReferenceError(참조 에러)</strong></del>가 발생한다.</p>
<h2 id="변수-선언의-실행-시점과-호이스팅">변수 선언의 실행 시점과 호이스팅</h2>
<pre><code>console.log(score); // undefined

var score; // 변수 선언문 </code></pre><p>위 코드는 변수 선언문보다 변수를 참조하는 코드가 앞에 있지만, <code>ReferenceError(참조 에러)</code>가 발생하지 않고 <code>undefined</code>가 발생한다. 왜 그럴까? </p>
<p>자바스크립트 엔진은 런타임 이전에 먼저 소스코드의 <strong>평가 과정</strong>을 실행한다. 이 때 변수 선언을 포함한 모든 선언문(변수, 함수 선언문, class 등)을 찾아내 먼저 실행하게 된다. 이러한 평가 과정이 끝나면 비로소 런타임 환경에서 <strong>모든 선언문을 제외한 소스코드를 한 줄씩 순차적으로 실행</strong>한다. </p>
<p>이렇게 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 것을 <strong>변수 호이스팅</strong> 이라 한다.</p>
<h2 id="값의-할당">값의 할당</h2>
<pre><code>var score = 80;</code></pre><p>위 코드는 변수 선언과 값의 할당을 하나의 문으로 단축 표현한 것이다. 
하지만 자바스크립트는 변수 선언과 값의 할당을 2개의 문으로 나누어 각각 실행하게 된다. 
코드 평가 과정에서 변수를 선언한 뒤, 런타임 환경에서 값을 할당하는 것이다. </p>
<p>때문에 다음과 같은 식에서 첫번 째 콘솔이 실행될 때는 변수 선언만 된 상태이므로 undefined가 출력된다. </p>
<pre><code>console.log(score); // undefined
var score = 80; // 1. 변수선언 2. 값의 할당
console.log(score) // 80</code></pre><h2 id="값의-재할당">값의 재할당</h2>
<p>재할당이란 이미 값이 할당되어 있는 변수에 새로운 값을 할당하는 것이다. 
만약 값을 재할당 할 수 없으면 변수가 아니라 <strong>상수(constant)</strong>라 한다. </p>
<blockquote>
<p>💡 ES6에서 도입된 <code>const</code> 키워드를 사용하면 재할당이 금지된 상수를 표현할 수 있다. 하지만 <code>const</code>를 반드시 상수만을 위해 사용하지 않는다. (15장에서 더 자세히-!)</p>
</blockquote>
<p>변수에 값을 재할당하면 이전 값이 저장되어 있던 메모리 공간을 지우고 재할당하는 것이 아니라, <strong>새로운 메모리 공간을 확보하고 그 메모리 공간에 새로운 값을 할당</strong>하게 된다. 이 때 더 이상 필요하지 않는 이전 값들은 <del><strong>가비지 콜렉터</strong></del>에 의해 메모리에서 자동 삭제된다.</p>
<blockquote>
<p>💡 <strong>가비지 콜렉터</strong>는 메모리 공간을 주기적으로 검사하여 더 이상 사용되지 않는 메모리를 해제한다. 자바스크립트는 매니지드 언어로써 내장된 가비지 콜렉터를 통해 메모리 누수를 방지한다. </p>
</blockquote>
<ul>
<li>매니지드 언어(managed language) : 메모리의 할당 및 해제 등의 관리 기능을 언어 차원에서 담당하고, 개발자의 직접적인 메모리 제어를 허용하지 않음 (언매니지드 언어 : C언어)</li>
</ul>
<h2 id="식별자-네이밍-규칙">식별자 네이밍 규칙</h2>
<ul>
<li>특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러 기호($) 포함 가능</li>
<li>숫자로 시작하는 것은 허용되지 않음 </li>
<li>예약어는 사용 불가 (ex_await, class, const, if, this...) </li>
<li>대소문자 구별 가능 </li>
</ul>
<pre><code>var first-name; // - 사용불가
var 1st; // 숫자로 시작 불가
var this; // 예약어 사용 불가 </code></pre><h3 id="네이밍-컨벤션">네이밍 컨벤션</h3>
<p>가독성을 좋게 하기 위해 규정한 명명규칙. 
자바스크립트에서는 일반적으로 변수나 함수 이름에는 <strong>카멜 케이스</strong>를, 생성자 함수 및 클래스 이름에는 <strong>파스칼 케이스</strong>를 사용한다.</p>
<pre><code>// 카멜 케이스
var firstName; 

// 스네이크 케이스
var first_name; 

// 파스칼 케이스
var FirstName; 

// 헝가리언 케이스
var strFirstName; // 타입 + 식별자
var $elem = document.getElementById(&#39;myId) // DOM 노드
var observable$ = fromEvent(document, &#39;click&#39;) // RxJS 옵저버블 </code></pre><hr>
<blockquote>
<p>책의 예제를 인용한 것으로 var 키워드를 동일하게 사용하였습니다 :)</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS TechCamp] AWS 핵심 서비스로 웹 애플리케이션 구축하기 - VPC, EC2, AMI]]></title>
            <link>https://velog.io/@roong-ra/AWS-TechCamp-AWS-%ED%95%B5%EC%8B%AC-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A1%9C-%EC%9B%B9-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-VPC-EC2-AMI</link>
            <guid>https://velog.io/@roong-ra/AWS-TechCamp-AWS-%ED%95%B5%EC%8B%AC-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A1%9C-%EC%9B%B9-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-VPC-EC2-AMI</guid>
            <pubDate>Tue, 10 Sep 2024 16:02:24 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>*<em>AWS TechCamp - AWS 핵심 서비스로 웹 애플리케이션 구축하기 *</em></p>
</blockquote>
<p>3일동안 진행되는 온라인 AWS TechCamp를 신청했다. 실무에서 사용해오던 AWS 핵심 서비스들에 대한 깊은 이해와, 아직 사용해보지 않은 서비스들에 대한 지식의 확장을 기대하면서!</p>
<p>모든 과정은 이론+실습으로 진행되며 오전/오후 각각 다른 과정들이 다양한 레벨로 진행된다. 이번 기초 과정은 그동안 실무에서 가장 빈번하게 사용해왔던 서비스들이지만 조금씩 놓치고 있던 부분들이 있어 다시 한번 큰 흐름으로 개념 정리를 해보려고 한다.</p>
<ul>
<li>실습 구성도 아키텍쳐
<img src="https://velog.velcdn.com/images/roong-ra/post/6f7e16b7-d7fc-4c45-9e20-8cf15bc018d3/image.png" alt="AWS 구성도 아키텍쳐"></li>
</ul>
<h1 id="aws-리전과-가용영역">AWS 리전과 가용영역</h1>
<p>AWS는 전세계적으로 호스팅되며, 이 호스팅되는 위치를 지리적 관점으로 구분하고 리전(region)이라 부른다. 각 리전은 완전히 독립되어 있기 때문에 한 리전에서 만든 리소스를 다른 리전에서 사용할 수 없다. 하나의 리전은 고가용성 및 확장성을 위해 물리적으로 분리된 _<strong>최소 3개 이상의 가용 영역(Availability Zone)</strong>_으로 구성된다. (현재 서울에는 총 4개의 가용 영역이 존재한다)</p>
<p>각 가용영역 간 모든 트래픽은 암호화 되며, 서로 100km 이내 거리에 위치한다. 또한 각 가용 영역은 하나 이상의 개별 데이터 센터로 구성되고, 데이터 센터는 보통 50,000~80,000대의 물리적 서버가 존재한다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/b83069f8-7a93-4afb-a602-7a5aa13985b0/image.png" alt=""></p>
<hr>
<h1 id="1-네트워크-구성">1. 네트워크 구성</h1>
<h2 id="vpcvirtual-private-cloud-개요">VPC(Virtual Private Cloud) 개요</h2>
<p>VPC(Virtual Private Cloud)란, 사용자가 정의한 논리적으로 격리된 <strong><em>가상의 프라이빗 네트워크</em></strong> 환경이다. 자체 데이터 센터에서 운영하는 기존 네트워크 환경과 유사하게 사용이 가능하다. 여기서 <em><strong>&#39;논리적으로 격리&#39;</strong></em> 란 예를들어 집 주소 중 A동 303호만 알려주는 격으로, 퍼블릭 주소가 있어야만 앞의 주소를 알려주어 찾아오게 할 수 있다. </p>
<p>이해가 쏙 갔던 강연자님의 인상적인 한 마디 - </p>
<blockquote>
<p>📢 <em>&quot;땅 없이 아파트를 올릴 수 없듯, 네트워크(VPC)를 구성해야 서버(EC2)를 올릴 수 있다!&quot;</em></p>
</blockquote>
<p>VPC는 아래 예시와 같이 구성하게 된다. VPC에는 하나의 리전의 각 가용성 영역 안에 하나의 서브넷이 있고, 각 서브넷 안에 EC2 인스턴스가 있다. 그리고 VPC 리소스와 인터넷 간의 통신을 허용하는 Internet Gateway가 있게 된다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/44fd6045-3a88-4bb5-9fa3-2e6670defa7b/image.png" alt="VPC"></p>
<h2 id="vpc-구성">VPC 구성</h2>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/9727f350-d344-4957-a317-b02672817291/image.png" alt="VPC 구성"></p>
<h3 id="1-ip-주소-범위-설정">1. IP 주소 범위 설정</h3>
<p>VPC의 IP범위는 _<strong>RFC 1918(사설 아이피 대역)</strong>_에 맞춰서 구축해야 한다. 사설 아이피(프라이빗 IP)란 인터넷을 위한 사용이 아닌 사용자간 사용하는 아이피 주소 대역을 말한다. 즉, 네트워크 내부에서 서로의 위치를 찾아갈 때 사용한다. </p>
<blockquote>
<p>📢 다른 집 찾아갈 땐 퍼블릭아이피! 같은 집 안에서는 사설아이피!</p>
</blockquote>
<p><strong>IP 주소 범위 설정 시 주의사항</strong> </p>
<ul>
<li>CIDR(Classless Inter-Domain Routing) 블록 설정<ul>
<li>CIDR : 클래스 없이 네트워크에 유연하고 효율적으로 IP주소를 할당하는 방법 </li>
</ul>
</li>
<li>RFC 1918의 사설 IP 대역 사용 권고 </li>
<li>VPC의 네트워크 범위는 <code>/16~/28</code>까지 가능</li>
<li>CIDR는 생성 후 <del>변경 불가능</del> </li>
<li>향후 직접 연결할 가능성이 있는 네트워크와 주소가 중복되지 않도록 할당이 권고됨 
<img src="https://velog.velcdn.com/images/roong-ra/post/e4fcae95-e3bc-444e-9446-1f9a83d50939/image.png" alt="IPv4 CIDR 블록 설정"></li>
</ul>
<h3 id="2-서브넷-정의">2. 서브넷 정의</h3>
<p>서브넷은 _<strong>VPC의 IP 주소 범위</strong>_이다. VPC 안에는 여러개의 서브넷이 있을 수 있는데, 더 많은 네트워크망을 만들기 위해 서브넷을 나누게 된다. 서브넷은 VPC보다 더 작은 단위이므로 IP범위 또한 더 작은 값을 갖게 된다. 서브넷을 추가하면 _<strong>EC2</strong>_와 같은 리소스를 배포할 수 있다. </p>
<h3 id="3-라우팅-테이블-구성">3. 라우팅 테이블 구성</h3>
<p>네트워크 요청 시 데이터는 _<strong>라우터(목적지)</strong>_로 향하게 되는데 각각 정의된 _<strong>라우팅 테이블(이정표)</strong>_에 따라 작동된다. VPC의 각 서브넷은 라우팅 테이블에 연결되어야 하며, 라우팅 테이블에서는 서브넷에 대한 라우팅을 제어한다. 이 때, 서브넷을 특정 라우팅 테이블과 연결하지 않으면 VPC와 함께 자동으로 제공된 기본 라우팅 테이블과 연결된다. </p>
<p>라우팅 테이블을 통해, 로컬을 타겟으로 하는 IP범위를 갖는 네트워크 요청은 로컬 안에서 찾게 된다. 하지만 그 외의 외부로 통하는 트래픽은 <del>인터넷 게이트웨이</del>라는 관문이 필요하다. </p>
<blockquote>
<p>📢 라우터는 목적지! 라우팅 테이블은 이정표! </p>
</blockquote>
<h3 id="4-internet-gateway-설정">4. Internet Gateway 설정</h3>
<p>Internet Gateway는 VPC를 인터넷에 연결해주어 통신할 수 있게 해주는 장치이다. 외부 인터넷에서 Internet Gateway를 통해 라우팅 테이블에 있는 타겟을 확인하여 퍼블릭 서브넷 안에 있는 인스턴스에 접근이 가능해진다. 혹은 거꾸로! (<del>프라이빗 서브넷은 Internet Gateway와 연결되어 있지 않다</del>)
<img src="https://velog.velcdn.com/images/roong-ra/post/b051a266-2dd7-474e-8a36-4f3149934334/image.png" alt="인터넷 게이트웨이"></p>
<h3 id="5-프라이빗-서브넷과-nat-게이트웨이">5. 프라이빗 서브넷과 NAT 게이트웨이</h3>
<p>위에서 말한 것과 같이 _<strong>Internet Gateway</strong>_는 _<strong>퍼블릭 서브넷</strong>_과만 연결이 가능하다. 기본적으로 프라이빗 서브넷의 라우팅 테이블은 <code>10.0.0.0/16</code> local을 타겟한다. 하지만 프라이빗 서브넷이 인터넷과 아웃바운드 통신이 필요하다면? </p>
<p>_<strong>프라이빗 서브넷</strong>_이 외부 요청에 의한 인바운드는 필요 없더라도, 인스턴스의 주기적인 업데이트와 같은 이유로 아웃바운드 통신만 허용해야되는 경우가 있다. 이 때 퍼블릭 서브넷에서 동작하는 _<strong>NAT 게이트웨이</strong>_가 프라이빗 서브넷에서 외부로 요청하는 아웃바운드 트래픽을 받아 Internet Gateway와 연결한다. </p>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/cd392aaf-cd81-476a-9240-5c8d5b2402f2/image.png" alt="NAT 게이트웨이"></p>
<h3 id="6-vpc-액세스-제어---nacl과-보안-그룹">6. VPC 액세스 제어 - NACL과 보안 그룹</h3>
<ul>
<li>NACL(Network Access Control List, 네트워크 액세스 제어 목록) <ul>
<li>서브넷 단위 방화벽 </li>
<li>Stateless(상태 비저장)</li>
<li>Allow, Deny 설정 가능</li>
</ul>
</li>
<li>보안그룹(Security Group)<ul>
<li>인스턴스 단위 방화벽 </li>
<li>Stateful(상태 저장)</li>
<li>Allow만 설정 가능 </li>
</ul>
</li>
</ul>
<p>_<strong>NACL(또는 네트워크 ACL)</strong>_은 서브넷과 외부 트래픽을 제어하기 위한 방화벽 역할을 담당하는 보안 계층이다. 최소 1개 이상의 서브넷과 연동되어 사용되며 1:N 연동도 가능하다. 포트 및 아이피를 직접 Deny 설정 가능하며, 들어오고 나가는 트래픽을 구분하지 않는다. (NACL에는 규칙에 부여되는 고유 번호가 있는데, 낮은번호부터 우선순위를 갖게 되므로 주의할 것!)</p>
<p>_<strong>보안그룹</strong>_은 기본적으로 모든 설정이 차단되어 있어 필요한 설정을 Allow해주어야 한다. NACL과는 다르게 각각의 리소스 별로 별도의 트래픽을 설정할 수 있다. NACL과 보안그룹 충돌 시에는 보안그룹이 더 높은 우선순위를 갖게 된다. </p>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/e2a45e62-2869-43c5-9f6f-97b7b26f694e/image.png" alt="NACL과 보안그룹"></p>
<blockquote>
<p>📝 <strong>[실습과정]</strong></p>
</blockquote>
<ol>
<li><strong>VPC 생성</strong> : 초기 VPC 생성 시, VPC CIDR 블록 (<code>10.0.0.0/16</code>) 설정 후 1개의 가용영역 안에 1개의 서브넷을 같이 만든다. ( 서브넷 CIDR 블록 :<code>10.0.10.0/24</code> ) </li>
<li><strong>추가 서브넷 생성</strong> : 위에서 만든 VPC 선택 후 다른 가용영역(ex. ap-northeast-2c) 안에 CIDR 블록 (<code>10.0.20.0/24</code>) 을 설정하여 생성 </li>
<li><strong>라우팅 테이블 편집</strong> : 기본 라우팅 테이블이 아닌 사용자 지정 테이블에 인터넷 통신 가능한 경로(ex. <code>0.0.0.0/0</code>) 가 있는지 확인 후 지정</li>
<li><strong>보안 그룹 생성</strong> : 위에서 생성한 vpc 선택 후 인바운드 규칙에 <code>SSH, HTTP</code> 를 추가하여 인스턴스의 보안그룹 생성 </li>
</ol>
<hr>
<h1 id="2-웹-서버-생성">2. 웹 서버 생성</h1>
<h2 id="ec2elastic-compute-cloud-개요">EC2(Elastic Compute Cloud) 개요</h2>
<p><strong>EC2는 AWS에서 제공하는 클라우드 컴퓨팅 서비스</strong>이다. EC2는 온디맨드(필요한 서비스를 실시간 제공) 확장 가능한 컴퓨팅 용량을 임대해주는 서비스로, EC2를 사용하여 원하는 수의 가상 서버를 구축하고 관리할 수 있다. 용량을 추가(스케일 업)하여 트래픽 급증 등의 사용량 많은 작업을 처리하고, 사용량이 감소하면 다시 축소(스케일 다운)할 수 있다. </p>
<ul>
<li>*<em>EC2의 장점 *</em><ul>
<li>용량의 탄력성 </li>
<li>사용한 만큼만 비용 지불</li>
<li>인스턴스 제어 가능 </li>
<li>보안 및 네트워크 구성, 스토리지 관리 용이</li>
</ul>
</li>
</ul>
<h2 id="ec2-구성">EC2 구성</h2>
<h3 id="1-instance">1. Instance</h3>
<p>인스턴스는 _<strong>서버의 컴퓨팅(CPU/RAM)에 해당하는 가상 컴퓨터</strong>_로, CPU 및 메모리, 그래픽카드 등의 연산을 위한 하드웨어 부분을 담당한다. AWS EC2는 각 쓰임새에 맞는 최적화된 다양한 인스턴스 유형을 제공한다.</p>
<ul>
<li><p><strong>인스턴스 유형</strong>
마치 게임에서 힘/민첩/지능 중 어느걸로 할지 결정하는 것처럼, EC2 인스턴스도 유형을 선택하고 사이즈를 골라 사용 목적에 맞게 생성 가능하다. CPU / 메모리 / 그래픽 카드 중 어떤 것에 힘을 실을지 성능 목적에 따라 여러가지 타입이 존재한다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/0300173c-38bc-4425-94c3-a90148a73a95/image.png" alt="인스턴스 타입"></p>
</li>
<li><p><strong>인스턴스 사이즈</strong>
인스턴스의 사이즈는 CPU의 갯수, 메모리 크기 및 성능 등으로 결정된다. CPU나 메모리 사이즈가 클수록 성능이 빨라지고 요금도 더 많이 부과된다. 
아래 예시에서, 아래로 갈수록 사이즈가 커지는 것을 볼 수 있다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/dce7573f-a879-47c3-86ca-445c6463b1b1/image.png" alt="인스턴스 사이즈"></p>
</li>
<li><p><strong>인스턴스 타입 읽는 법</strong></p>
<ul>
<li>인스턴스 패밀리(타입) : ex_범용 애플리케이션 서버용 </li>
<li>인스턴스 세대 </li>
<li>추가 기능(접두사) : 무슨 기반의 CPU 프로세서 사용?</li>
<li>인스턴스 크기(사이즈) 
<img src="https://velog.velcdn.com/images/roong-ra/post/3a739b64-e518-4d78-928c-292ac24464b5/image.png" alt="인스턴스 타입 읽는 법"></li>
</ul>
</li>
</ul>
<h3 id="2-ebselastic-block-storage">2. EBS(Elastic Block Storage)</h3>
<p>서버의 하드디스크에 해당하는 가상 하드디스크로써 _<strong>데이터를 저장하는 역할</strong>_을 한다. 
EBS는 네트워크로 별개로 연결된 서비스이기 때문에 EC2 인스턴스가 종료되어도 별개로 작동한다. </p>
<ul>
<li>*<em>EBS 볼륨 *</em>
EBS 볼륨이란 EBS로 생성한 디스크 하나하나의 저장 단위를 말한다. 
하드 저장 디스크가 SSD,HDD로 나뉘는 것처럼 EBS 볼륨에도 총 5가지의 타입이 있다. <ul>
<li>범용(General Purpose of GP3) : SSD</li>
<li>프로비저닝 된 IOPS(Provisioned IOPS or io2) : SSD</li>
<li>쓰루풋 최적화(Throughput Optimized HDD or st1)</li>
<li>콜드 HDD(SC1)</li>
<li>마그네틱(Standard)</li>
</ul>
</li>
</ul>
<h3 id="3-amiamazon-machine-image">3. AMI(Amazon Machine Image)</h3>
<p>AMI란 EC2 인스턴스의 OS 및 소프트웨어 등 _<strong>설정 상태를 저장하는 기능</strong>_이다. AMI를 이용하여 새 인스턴스를 만들면 이미지에 저장된 설정과 같은 환경의 컴퓨터를 빠르게 생성 가능하다. 빠른 개발 및 배포가 가능한 것이 장점이다.</p>
<blockquote>
<p>📝 <strong>[실습과정]</strong></p>
</blockquote>
<ol>
<li><strong>인스턴스 생성</strong> : OS 이미지 선택 후, 위에서 만든 VPC / 서브넷 / 보안그룹 등을 설정해준다.<ul>
<li>인스턴스 생성 후 퍼블릭 IPv4 주소로 아래와 같은 웹 화면을 확인할 수 있다<img src="https://velog.velcdn.com/images/roong-ra/post/bab0bdaf-dcc2-42da-af47-5f7dd3a6eb48/image.png" alt=""></li>
</ul>
<ol start="2">
<li><strong>AMI 생성</strong> : 이미지로 만들 인스턴스 클릭 후 <strong>작업 메뉴 &gt; 이미지 및 템플릿 &gt; 이미지 생성</strong> 에서 이미지를 생성한다. </li>
<li><strong>AMI 기반 인스턴스 생성</strong> : <strong>EC2 &gt; AMI</strong> 메뉴에서 위에서 만든 AMI 선택 후 <strong>AMI로 인스턴스 시작</strong> 버튼을 눌러 새 인스턴스를 생성한다.  </li>
</ol>
<ul>
<li><del>해당 실습에서 EBS에 대해선 다루지 않았다</del></li>
</ul>
</li>
</ol>
<hr>
<h1 id="3-로드-밸런서-구성">3. 로드 밸런서 구성</h1>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/fc198933-e324-4448-af26-5dc5d94d0a7f/image.png" alt=""></p>
<h2 id="elbelastic-load-balancing-개요">ELB(Elastic Load Balancing) 개요</h2>
<p>로드 밸런서는 부하를 적절하게 분배해주는 장치인데, AWS에서는 로드 밸런서를 ELB라는 서비스를 통해 제공한다. 
ELB는 <strong>둘 이상의 가용영역에서 트래픽을 자동으로 분산</strong>한다. 또한 등록된 대상의 상태를 모니터링하면서 상태가 양호한 대상으로만 트래픽을 라우팅해준다. ELB 사용 시 안정적인 서버 환경을 운영할 수 있다. </p>
<ul>
<li>*<em>ELB 특징 *</em><ul>
<li>네트워크 트래픽 분산을 통한 애플리케이션 확장성 개선</li>
<li>여러 가용 영역을 기반으로 고가용성 제공</li>
<li>트래픽에 따라 자동 조정</li>
<li>트래픽을 받는 대상 : EC2 인스턴스 / 컨테이너 / IP주소 / Lambda 함수 등 </li>
</ul>
</li>
</ul>
<blockquote>
<p>📝 <strong>[실습과정]</strong></p>
</blockquote>
<ol>
<li><strong>로드밸런서 생성하기</strong> 클릭 후 트래픽을 라우팅할 <strong>VPC와 가용영역(서브넷)을 지정</strong>한다. 이 때 가용영역은 2개 이상 선택하는 것이 좋다.</li>
<li><strong>새 보안그룹 생성</strong>에서 위에서 지정한 VPC를 선택하고, <strong>인바운드 규칙으로 HTTP</strong>를 추가해준다.</li>
<li><strong>리스너 및 라우팅</strong> 항목에서 <strong>대상 그룹 생성</strong> 클릭 후 대상 유형으로 <strong>인스턴스</strong>를 선택한다. 이후 <strong>대상 등록</strong>에 보이는 두 개의 인스턴스를 <strong>보류 중인 대상</strong>으로 등록한다.</li>
<li><strong>리스너 및 라우팅</strong>로 돌아와 생성된 대상 그룹을 지정해준다.</li>
<li>웹 서버가 로드 밸런서의 트래픽만 받게 하기 위해서, 해당 서버의 <strong>보안 그룹</strong>의 인바운드 규칙 편집 후 HTTP 소스를 위에서 만든 보안그룹으로 지정해준다.</li>
</ol>
<hr>
<p><strong>참고</strong></p>
<ul>
<li><a href="https://medium.com/harrythegreat/aws-%EA%B0%80%EC%9E%A5%EC%89%BD%EA%B2%8C-vpc-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-71eef95a7098">[AWS]가장쉽게 VPC 개념잡기 - Harry The Great</a></li>
<li><a href="https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-EC2-%EA%B0%9C%EB%85%90-%EC%82%AC%EC%9A%A9-%EA%B5%AC%EC%B6%95-%EC%84%B8%ED%8C%85-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-EBS-AMI">[AWS]EC2 개념 원리 &amp; 사용 세팅 총정리(Instance/EBS/AMI) - Inpa Dev</a></li>
<li><a href="https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-ELB-Elastic-Load-Balancer-%EA%B0%9C%EB%85%90-%EC%9B%90%EB%A6%AC-%EA%B5%AC%EC%B6%95-%EC%84%B8%ED%8C%85-CLB-ALB-NLB-GLB">ELB(Elastic Load Balancer) 구성 &amp; 사용법 가이드 - Inpa Dev</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[딥다이브] 1. 자바스크립트란 ]]></title>
            <link>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@roong-ra/%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Fri, 30 Aug 2024 17:23:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://product.kyobobook.co.kr/detail/S000001766445">모던 자바스크립트 딥다이브</a> 책의 내용을 기반으로 작성하였습니다.🌿</p>
</blockquote>
<h1 id="자바스크립트란">자바스크립트란?</h1>
<h3 id="자바스크립트의-탄생">자바스크립트의 탄생</h3>
<ul>
<li>1995년, <strong>넷스케이프 커뮤니케이션즈</strong>가 브라우저에서 동작하는 경량 프로그래밍 언어를 도입하기 위해 <strong>브렌던 아이크</strong>가 개발</li>
</ul>
<h3 id="자바스크립트의-표준화">자바스크립트의 표준화</h3>
<ul>
<li>1996년, 마이크로소프트는 자바스크립트의 파생 버전인 <strong>JScript</strong>를 인터넷 익스플로러 3.0에 탑재한다. 하지만 <strong>JScript</strong>와 자바스크립트는 적당히 호환되었고, <strong>크로스 브라우징 이슈</strong>가 발생하기 시작한다. </li>
<li>이에 <strong>넷스케이프 커뮤니케이션즈</strong>는 자바스크립트의 파편화를 방지하기 위해 비영리 표준화 기구인 <strong>ECMA 인터내셔널</strong>에 자바스크립트의 표준화를 요청한다. </li>
<li>1997년, 표준화된 <strong>자바스크립트 초판(ECMAScript 1)</strong>이 완성되었고, 상표권 문제로 <strong>ECMAScript</strong>로 명명된다.</li>
<li>1999년, <strong>ECMAScript 3(ES3)</strong>이 공개되고, 이후 10년 만인 2009년 <strong>ECMAScript(ES5)</strong>가 <strong>HTML5</strong>와 함께 출현한다. </li>
<li>2015년, <strong>ECMAScript 6(ES6)</strong>는 let/const 키워드, 화살표 함수, 클래스, 모듈 등과 같은 기능을 대거 도입하게 된다. </li>
</ul>
<h3 id="자바스크립트의-성장의-역사">자바스크립트의 성장의 역사</h3>
<ol>
<li><strong>AJAX (Asynchronous JavaScript and XML)</strong><ul>
<li>1999년, 서버와 브라우저가 비동기 방식으로 데이터를 교환할 수 있는 통신 기능인 <strong>Ajax</strong>가 <strong>XMLHttpRequest</strong>라는 이름으로 등장</li>
<li><strong>Ajax</strong> = <strong>XMLHttpRequest</strong>를 이용해 일부 데이터를 별도로 요청하는 기법</li>
<li>자바스크립트가 <strong>XMLHttpRequest</strong> 객체를 사용하여 서버로 요청을 보내면, 서버는 페이지를 전부 보내는 것이 아니라 필요한 데이터만을 전달 (= Ajax 요청 처리) 👉🏻 <a href="https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-AJAX-%EC%84%9C%EB%B2%84-%EC%9A%94%EC%B2%AD-%EB%B0%8F-%EC%9D%91%EB%8B%B5-XMLHttpRequest-%EB%B0%A9%EC%8B%9D">참고</a></li>
</ul>
</li>
<li><strong>V8 자바스크립트 엔진</strong><ul>
<li>Ajax를 기반으로 동작하는 <strong>구글 맵스</strong>가 데스크톱 앱과 비교해도 손색없는 부드러운 화면 전환 효과를 보여주면서, 자바스크립트로 웹 앱을 구축하려는 시도가 늘었고 더욱 빠른 자바스크립트 엔진의 필요성이 대두되었다.</li>
<li>2008년, <strong>구글의 V8 자바스크립트 엔진</strong>의 등장으로 자바스크립트는 웹 앱 프로그래밍 언어로 정착하게 된다.</li>
</ul>
</li>
<li><strong>Node.js</strong><ul>
<li>2009년, <strong>라이언 달</strong>이 <strong>구글 V8 자바스크립트 엔진</strong>으로 빌드된 자바스크립트 런타임 환경인 <strong>Node.js</strong>를 발표</li>
<li><strong>Node.js</strong>는 브라우저에서만 동작하는 자바스크립트를 브라우저 이외의 환경에서도 동작할 수 있도록 독립시킨 자바스크립트 실행 환경</li>
<li><strong>서버 사이드 애플리케이션</strong> 개발에서 주로 사용 <ul>
<li>브라우저를 벗어나 백엔드 영역에서도 사용 가능한 <strong>범용 프로그래밍 언어</strong>가 된 자바스크립트는 이제 <strong>크로스 플랫폼</strong>을 위한 가장 중요한 언어로 주목받고 있다! </li>
</ul>
</li>
</ul>
</li>
<li><strong>SPA 프레임워크</strong> <ul>
<li>자바스크립트로 개발되는 모던 웹 애플리케이션은, 우수한 성능과 사용자 경험을 제공하는 것이 필수가 되면서 개발 규모와 복잡도도 상승했다. </li>
<li>이러한 필요에 따라, <strong>CBD(Component based development)</strong> 방법론을 기반으로 <strong>SPA</strong>가 대중화되면서 <strong>Angular, React, Vue, Svelte</strong> 등 다양한 프레임워크/라이브러리 등장한다.</li>
</ul>
</li>
</ol>
<h3 id="자바스크립트의-특징">자바스크립트의 특징</h3>
<ul>
<li>자바스크립트는 개발자가 별도의 컴파일 작업을 수행하지 않는 <strong>인터프리터 언어(interpreter language)</strong> 이다. <ul>
<li>대부분 브라우저에서 사용되는 인터프리터는 실행 속도가 느리다는 단점을 극복하기 위해 일부 복잡한 과정을 거치며 소스코드를 컴파일하고 실행한다. 따라서 현재는 컴파일러와 인터프리터의 기술적 구분이 모호해지는 추세이다.
<img src="https://velog.velcdn.com/images/roong-ra/post/2f01dfae-1829-49d1-83e5-7cb1f1f6a46e/image.png" alt=""></li>
</ul>
</li>
<li>자바스크립트는 명령형(절차적), 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 <strong>멀티 패러다임 프로그래밍 언어</strong>이다. <ul>
<li>자바스크립트는 클래스 기반 객체지향 언어보다 효율적이면서 강력한 <strong>프로토타입 기반의 객체지향 언어</strong>이다!
👉🏻<a href="https://80000coding.oopy.io/d486a93b-7619-4006-8431-241a6c10cc45">자바스크립트는 어떤 언어인가?</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ API ] Youtube API 불러오기]]></title>
            <link>https://velog.io/@roong-ra/Youtube-API</link>
            <guid>https://velog.io/@roong-ra/Youtube-API</guid>
            <pubDate>Sun, 22 May 2022 16:00:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>개인 페이지를 만들어 그 안에 뿌려줄 유튜브 API 데이터가 필요할 때 불러오는 방법을 정리해 보았다!</p>
</blockquote>
<h2 id="구글-클라우드-플랫폼-api-key">구글 클라우드 플랫폼 (API Key)</h2>
<ol>
<li><p><a href="https://console.cloud.google.com/apis/library?project=solar-grail-351003">Google Cloud Platform</a> &gt; API 라이브러리 &gt; YouTube Data API v3 &gt; 사용 클릭 ! 
<img src="https://velog.velcdn.com/images/roong-ra/post/1899a73a-dca1-41c9-ace6-10553b7b719f/image.png" alt=""></p>
</li>
<li><p>사용자 인증정보 들어가기 
<img src="https://velog.velcdn.com/images/roong-ra/post/0ee7b739-5577-4ff5-980f-905149d55bb5/image.png" alt=""></p>
</li>
<li><p>키표시 옆 API 키 수정 클릭 ! 
<img src="https://velog.velcdn.com/images/roong-ra/post/fc745dca-9e92-48f7-a874-26d9924ae0b1/image.png" alt=""></p>
</li>
<li><p>API Key 복사 
<img src="https://velog.velcdn.com/images/roong-ra/post/ebe5b7f9-42bf-4b07-8de9-859cce4545c3/image.png" alt=""></p>
</li>
</ol>
<h2 id="youtube-data-api-restful-api">Youtube Data API (Restful API)</h2>
<ol>
<li><p><a href="https://developers.google.com/youtube/v3/docs/search/list?apix_params=%7B%22part%22%3A%5B%22snippet%22%5D%2C%22maxResults%22%3A50%2C%22q%22%3A%22React%22%7D">Youtube Data API</a> &gt; Search &gt; list 클릭 
<img src="https://velog.velcdn.com/images/roong-ra/post/62b5a6ef-1b2e-438a-a884-6e9dfa1d7b8f/image.png" alt=""></p>
</li>
<li><p>옵션 설정</p>
</li>
</ol>
<ul>
<li>part : snippet </li>
<li>q : React</li>
<li>maxResults : 50 
<img src="https://velog.velcdn.com/images/roong-ra/post/bd975f8d-078c-4339-8860-692bd54a6a99/image.png" alt=""></li>
</ul>
<ol start="3">
<li><p>Google OAuth 2.0 클릭해제 (구글에게 허락받는 것) 
<img src="https://velog.velcdn.com/images/roong-ra/post/223aa20d-f501-41ac-b696-d9b77a1f6889/image.png" alt=""></p>
</li>
<li><p>EXECUTE를 클릭하면 API 소스코드를 미리 볼 수 있다. </p>
</li>
<li><p>SHOW CODE를 클릭하고 Restful API 주소를 &#39;&#39; 빼고 안에 내용만 복사한다. 
<img src="https://velog.velcdn.com/images/roong-ra/post/1ceae170-c476-4b3a-8b58-d13de4dfebc5/image.png" alt=""></p>
</li>
<li><p><code>https://youtube.googleapis.com/youtube/v3/search?part=snippet&amp;maxResults=50&amp;q=React&amp;key=[YOUR_API_KEY]</code>
라고 복사된 코드에서 [YOUR_API_KEY] 부분에 구글 클라우드 플랫폼에서 복사한 API Key를 붙여넣어준다. 이렇게!</p>
<blockquote>
<p><code>https://youtube.googleapis.com/youtube/v3/search?part=snippet&amp;maxResults=50&amp;q=React&amp;key=AIzaSyDLgsuoY1CwJn22GRRwQCQlolPq-Z_EONs</code></p>
</blockquote>
</li>
</ol>
<h2 id="📌-결과">📌 결과!!</h2>
<p>위 주소를 그대로 주소창에 붙여넣으면 다음과 같이 소스를 확인할 수 있다. </p>
<ul>
<li>&#39;React&#39; 검색 시 나오는 유튜브 동영상 목록
<img src="https://velog.velcdn.com/images/roong-ra/post/3a91f450-62d2-4ae5-a491-69844733dd8c/image.png" alt=""></li>
</ul>
<hr>
<br>

<h2 id="post-man">Post man</h2>
<ul>
<li>로그인 후 Workspaces의 My Workspace 들어가기 
<img src="https://velog.velcdn.com/images/roong-ra/post/bc4df8e0-0d3b-4394-b8ff-27493a232fd4/image.png" alt=""></li>
<li>New 누르고 Collection 클릭</li>
<li>Get에 위에서 만든 주소를 넣고 Send 버튼을 클릭하면 Youtube API Key의 관리가 가능해진다! 
<img src="https://velog.velcdn.com/images/roong-ra/post/ce2fe2fd-01ed-4553-91f7-83e4f6573a44/image.png" alt=""></li>
</ul>
<br>

<hr>
<h2 id="youtube-api-할당량-초과-에러">Youtube API 할당량 초과 에러</h2>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/4eb758d7-a363-4c78-b41e-b414dfb048b4/image.png" alt="">
위와 같은 에러가 나와 찾아보니, 유튜브 API 일일 할당량 한도를 초과한 것이었다.
유튜브 API에서 제공하는 기본 할당량은 10,000인데, 사용하는 기능에 따라 차감되는 양이 다르다. 그래서 기능에 따라서는10,000번을 사용할 수 없다.
해결방법은 할당량 연장 신청을 하는 것인데,, 나는 연습 중이니 하루 기다리기..!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] Event ]]></title>
            <link>https://velog.io/@roong-ra/React-%EC%9D%B4%EB%B2%A4%ED%8A%B8</link>
            <guid>https://velog.io/@roong-ra/React-%EC%9D%B4%EB%B2%A4%ED%8A%B8</guid>
            <pubDate>Fri, 20 May 2022 02:34:28 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-event">📌 Event</h1>
<ul>
<li><code>onChangeMode={}</code> 값으로 함수를 전달하여 props로 가져와 실행한다.</li>
<li>html 문법은 똑같지 않다. 코드를 작성하면 리액트 개발환경이 최종적으로 브라우저가 이해할 수 있는 html로 컨버팅해주는 것! </li>
</ul>
<pre><code>// ----- Header -----
function Header(props) {
  console.log(&quot;props&quot;, props, props.title);
  return (
    &lt;header&gt;
      &lt;h1&gt;
        &lt;a
          href=&quot;/&quot;
          onClick={(e) =&gt; {
            e.preventDefault();    //기본동작 방지
            props.onChangeMode();  // Header의 props로 전달된 onChangeMode가 가리키는 함수를 호출
          }}
        &gt;
          {props.title}
        &lt;/a&gt;
      &lt;/h1&gt;
    &lt;/header&gt;
  );
}


// ----- Nav -----
function Nav(props) {
  const li = [];
  for (let i = 0; i &lt; props.topics.length; i++) {
    let t = props.topics[i];
    li.push(
      &lt;li key={t.id}&gt;
        &lt;a
          id={t.id}                  // id값 부여
          href={&quot;/read/&quot; + t.id}
          onClick={(e) =&gt; {          // 클릭이벤트
            e.preventDefault();
            props.onChangeMode(e.target.id);   // target: 이벤트를 유발시킨 태그를 가리킴 -&gt; a태그
          }}
        &gt;
          {t.title}
        &lt;/a&gt;
      &lt;/li&gt;
    );
  }
  return (
    &lt;nav&gt;
      &lt;ol&gt;{li}&lt;/ol&gt;
    &lt;/nav&gt;
  );
}


// ----- App -----
function App() {
  const topics = [
    { id: 1, title: &quot;James&quot;, body: &quot;James is ...&quot; },
    { id: 2, title: &quot;Susan&quot;, body: &quot;Susan is ...&quot; },
    { id: 3, title: &quot;Amy&quot;, body: &quot;Amy is ...&quot; },
  ];
  return (
    &lt;div&gt;
      &lt;Header
        title=&quot;Name&quot;
        onChangeMode={() =&gt; {
          alert(&quot;My Friends&quot;);
        }}
      &gt;&lt;/Header&gt;
      &lt;Nav
        topics={topics}
        onChangeMode={(id) =&gt; { 
          alert(id);                // id값을 알림창에 뜨게 하자
        }}
      &gt;&lt;/Nav&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[VSCODE EXTENTION]]></title>
            <link>https://velog.io/@roong-ra/VSCODE-EXTENTION</link>
            <guid>https://velog.io/@roong-ra/VSCODE-EXTENTION</guid>
            <pubDate>Fri, 20 May 2022 01:33:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>VSCode 사용 시 설치하면 편리한 익스텐션 정리! 
이제 없으면 불편하다고 느낄정도. 한번에 정리해놓기 :) </p>
</blockquote>
<h2 id="1-material-theme">1. Material Theme</h2>
<ul>
<li>배경 테마 정하기 </li>
</ul>
<h2 id="2-marterial-icon-theme">2. Marterial Icon Theme</h2>
<ul>
<li>아이콘 테마, 아이콘이 조금 더 생동감 있게 바뀜</li>
</ul>
<h2 id="3-preitter---code-formatter">3. Preitter - Code formatter</h2>
<ul>
<li>코드 포멧팅</li>
<li>ctrl+,  눌러서 setting 창으로 이동 -&gt; tab 2로 변경 </li>
</ul>
<h2 id="4-bracket-pari-colorizer">4. Bracket Pari Colorizer</h2>
<ul>
<li>괄호마다 코드에 색깔을 다르게 줌</li>
</ul>
<h2 id="5-indent-rainbow">5. Indent-rainbow</h2>
<ul>
<li>들여쓰기 된 부분을 레인보우컬로로 하이라이트 표시</li>
<li>코드 읽을 때 도와줌</li>
</ul>
<h2 id="6-auto-rename-tag">6. Auto Rename Tag</h2>
<ul>
<li>앞에 태그를 바꾸면 뒤에 태그를 자동으로 바꿔줌</li>
</ul>
<h2 id="7-css-peek">7. CSS Peek</h2>
<ul>
<li>html에서 css를 금방 찾게해줌</li>
<li>html에서 커맨드를 누른 상태로 클릭하면 정의된 css파일로 이동하게 해줌.</li>
</ul>
<h2 id="8-html-css-support">8. HTML CSS Support</h2>
<ul>
<li>html에서 css의 자동완성을 이용하게 해줌</li>
</ul>
<h2 id="9-live-server">9. Live Server</h2>
<ul>
<li>html이나 css 수정 시 브라우저창에 새로고침하는 것을 없애줌.</li>
<li>커맨드 팔렛트에 &gt; live Server: Open with Live Server 입력하고 숏컷키 후 실행</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] Props]]></title>
            <link>https://velog.io/@roong-ra/React-Props</link>
            <guid>https://velog.io/@roong-ra/React-Props</guid>
            <pubDate>Tue, 17 May 2022 14:55:14 GMT</pubDate>
            <description><![CDATA[<h1 id="props">Props</h1>
<p>img 태그에 src 속성이 있듯이 직접 정의한 나만의 태그(컴포넌트)에 속성을 넣을 수 있는데, 리액트는 그 속성을 <code>props</code> 라고 부른다. 그리고 props에는 객체-Object가 들어온다.</p>
<h2 id="📌-props-기본-사용">📌 Props 기본 사용</h2>
<p>각각의 컴포넌트(사용자 정의 태그)를 만들어준 후, rendering 되는 함수인 App()에 위치시켜 export 해주었다. App()을 보면 컴포넌트 태그 안에 속성을 넣어줬는데, 이 속성 값을 props로 가져와 컴포넌트에서 다음과 같이 출력할 수 있다. </p>
<pre><code>
// 1. Header Component
function Header(props) {
  console.log(&quot;props&quot;, props);
  return (
    &lt;header&gt;
      &lt;h1&gt;{props.title}&lt;/h1&gt;
    &lt;/header&gt;
  );
}

// 2. Contents Component
function Contents(props) {
  return (
    &lt;ul&gt;
      &lt;li&gt;{props.name1}&lt;/li&gt;
      &lt;li&gt;{props.name2}&lt;/li&gt;
      &lt;li&gt;{props.name3}&lt;/li&gt;
    &lt;/ul&gt;
  );
}

// 3. Footer Component
function Footer(props) {
  return (
    &lt;article&gt;
      &lt;p&gt;{props.title}&lt;/p&gt;
    &lt;/article&gt;
  );
}

// --- Export App ---
function App() {
  return (
    &lt;div&gt;
      &lt;Header title=&quot;Fruits&quot;&gt;&lt;/Header&gt;
      &lt;Contents name1=&quot;apple&quot; name2=&quot;banana&quot; name3=&quot;orange&quot;&gt;&lt;/Contents&gt;      
      &lt;Footer title=&quot;Thank you!&quot;&gt;&lt;/Footer&gt;
    &lt;/div&gt;
  );
}

export default App;

</code></pre><h2 id="📌-변수-사용">📌 변수 사용</h2>
<p>컴포넌트 내부에서 변수를 선언한 뒤 중괄호<code>{}</code> 안에 변수명을 넣어 사용할 수 있다. (함수도 마찬가지!) 
변수안에 다양한 요소를 담을 때는 배열요소 안에 객체형식으로 작성하며, 각각 고유의 id 값을 갖는다. 다음은 객체형식의 변수를 props(태그속성) 값으로 넣은 뒤, 컴포넌트에서 빈 변수안에 배열 갯수만큼 태그를 자동 생성하여 출력해준 것이다. </p>
<ul>
<li>반복문 안에서 자동으로 생성된 태그는 리액트가 추적할 때 근거가 있어야 하므로 각각의 태그들은 고유의 key 값을 가져야 한다. </li>
</ul>
<pre><code>// 빈 list 변수 안에 과일명이 들어있는 fruName의 각 값을 차례대로 넣어준다. 
// 그리고 값이 들어간 list 변수를 return 해준다. 

function Contents(props) {
  const list = [];

  for (let i = 0; i &lt; props.name.length; i++) {
    let n = props.name[i];
    list.push(&lt;li key={n.id}&gt;{n.title}&lt;/li&gt;);
  }

  return (
    &lt;nav&gt;
      &lt;ol&gt;{list}&lt;/ol&gt;
    &lt;/nav&gt;
  );
}


// 변수를 선언하고 각 정보에 고유 id값 주기
// 선언한 변수를 {} 안에 넣어 사용 
function App() {
  const fruName = [
    { id: 1, title: &quot;apple&quot; },
    { id: 2, title: &quot;banana&quot; },
    { id: 3, title: &quot;orange&quot; },
  ];

  return (
    &lt;div&gt;
      &lt;Header title=&quot;Fruits&quot;&gt;&lt;/Header&gt;
      &lt;Contents name={fruName}&gt;&lt;/Contents&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] 함수형 vs 클래스형 컴포넌트]]></title>
            <link>https://velog.io/@roong-ra/515-React-%ED%95%A8%EC%88%98%ED%98%95-vs-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Hook</link>
            <guid>https://velog.io/@roong-ra/515-React-%ED%95%A8%EC%88%98%ED%98%95-vs-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Hook</guid>
            <pubDate>Mon, 16 May 2022 03:28:22 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-함수형-vs-클래스형-컴포넌트의-차이점">📌 함수형 vs 클래스형 컴포넌트의 차이점</h2>
<p>리액트 컴포넌트를 선언하는 두 가지 방식에는 함수형과 클래스형이 있다. 클래스형 이후에 함수형이 나왔지만, 클래스형을 쓰던 기업의 프로젝트 유지보수를 위해 개념을 알고 있어야 한다. 최근에는 함수형 + 클래스형의 장점을 넣은 리액트 훅을 사용하는 추세이다.</p>
<p>클래스형 컴포넌트는 로직을 컴포넌트 내에서 구현하기 때문에 더 복잡한 UI를 갖게 된다. 반면에, 함수형 컴포넌트는 props로 데이터를 받아서 UI에 뿌려주기 때문에 상대적으로 단순한 형태를 갖게 되며 재사용성이 높다는 장점이 있다. </p>
<h3 id="클래스형-컴포넌트">클래스형 컴포넌트</h3>
<ul>
<li>class 키워드 필요 </li>
<li>Component로 상속 받음 </li>
<li>render() 메소드 필요 </li>
<li>state, lifeCycle 사용 가능 </li>
<li>this.state 초기값 설정, 변경 가능 </li>
<li>this.props로 데이터 불러옴 </li>
<li>메모리 자원의 많은 사용 </li>
<li>임의 메소드 정의 가능 </li>
</ul>
<h3 id="함수형-컴포넌트">함수형 컴포넌트</h3>
<ul>
<li>state, lifeCycle 사용 불가 (Hook으로 해결)</li>
<li>useState 함수로 state 사용 </li>
<li>props 불러올 필요 없이 바로 호출 </li>
<li>메모리 자원 덜 사용 </li>
<li>컴포넌트 선언이 편리함 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] scaffolding, fonts, 자동 줄바꿈, 함수형 컴포넌트]]></title>
            <link>https://velog.io/@roong-ra/515-React</link>
            <guid>https://velog.io/@roong-ra/515-React</guid>
            <pubDate>Mon, 16 May 2022 03:25:12 GMT</pubDate>
            <description><![CDATA[<h2 id="📌-scaffolding-빠른생성">📌 scaffolding 빠른생성</h2>
<h3 id="--터미널-작성순서--">- 터미널 작성순서 -</h3>
<ol>
<li><p>ls (위치확인)</p>
</li>
<li><p>cd desktop (이동)</p>
</li>
<li><p>npx create-react-app 폴더명 (scaffolding 생성)</p>
</li>
<li><p>cd 폴더명 (생성한 폴더로 이동)</p>
</li>
<li><p>code .  (vscode열기 : 설정필요)</p>
<ul>
<li>vscode에서 code 명령어로 열 수 있도록 환경설정하기 : f1누르고 shell 검색 후 클릭
<img src="https://velog.velcdn.com/images/roong-ra/post/d7b8ea66-4043-483e-a2eb-56c67ef51c74/image.png" alt=""></li>
</ul>
</li>
<li><p>npm install node-sass (사스 다운)</p>
</li>
<li><p>npm install react-router-dom axios prop-types gsap (리액트 실행 시 필요한 요소 한번에 다운로드 : 스펠링 주의)</p>
</li>
<li><p>package.json에서 확인 !</p>
</li>
</ol>
<hr>
<h2 id="📌-fonts-파일-넣기">📌 fonts 파일 넣기</h2>
<p>폰트파일 넣을때는 아래 4가지 확장자를 각각 넣어줘야 한다. </p>
<ul>
<li><strong>EOT(Embedded Open Type)</strong> : Microsoft에서 제안한 웹 글꼴, IE 호환성을 위해서 지원</li>
<li><strong>TTF(True Type Font)</strong> : Mac 및 Windows 운영체제에서 가장 일반적인 글꼴</li>
<li><strong>WOFF(Web Open Font Format)</strong> : 주요 웹 브라우저에서 지원하는 메타 데이터 압축 기능 글꼴 </li>
<li><strong>WOFF2</strong> : WOFF의 개선 버전. WOFF보다 30% 더 압축한 글꼴, 널리 사용되지는 않고 있음 
<img src="https://velog.velcdn.com/images/roong-ra/post/c761fc94-c36c-4a53-9b12-343d4a4adb8e/image.png" alt=""></li>
</ul>
<hr>
<h2 id="📌-자동-줄바꿈-설정하기">📌 자동 줄바꿈 설정하기</h2>
<p><img src="https://velog.velcdn.com/images/roong-ra/post/8341474c-5401-481e-82c6-2fa3132e429e/image.png" alt=""></p>
<pre><code>    &quot;emmet.includeLanguages&quot;: {
        &quot;javascript&quot;: &quot;javascriptreact&quot;
      },
      &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;,
      &quot;[typescriptreact]&quot;: {
        &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
      },
      &quot;[typescript]&quot;: {
        &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;
      },
      &quot;editor.formatOnSave&quot;: true,</code></pre><hr>
<h2 id="📌-함수형-컴포넌트의-사용-props">📌 함수형 컴포넌트의 사용 (Props)</h2>
<h3 id="--props-매개변수로-가져오기">- props 매개변수로 가져오기</h3>
<pre><code>function Info(props){
    return (
        &lt;div&gt;{props.text1}&lt;/div&gt;
        &lt;div&gt;{props.text2}&lt;/div&gt;
        &lt;div&gt;{props.text3}&lt;/div&gt;
        &lt;div&gt;{props.text4}&lt;/div&gt;
    )
}

function Main(){
  &lt;&gt;
    &lt;main&gt;
      &lt;section className=&quot;main__cont&quot;&gt;
        &lt;Info
            text1=&quot;we provide&quot;
            text2=&quot;visual coding&quot;
            text3=&quot;solution&quot;
            text4=&quot;for you webs&quot;
        /&gt;
      &lt;/section&gt;
    &lt;/main&gt;
  &lt;/&gt;
}

</code></pre><h3 id="--객체로-가져오기-수정필요">- 객체로 가져오기 (수정필요...)</h3>
<pre><code>function Info(???){
    return ( 
        &lt;div&gt;{props.text1}&lt;/div&gt; ????
        &lt;div&gt;{props.text2}&lt;/div&gt;
        &lt;div&gt;{props.text3}&lt;/div&gt;
        &lt;div&gt;{props.text4}&lt;/div&gt;
    )
}

const textInfo = {
  text1: &quot;we provide&quot;,
  text2: &quot;visual coding&quot;,
  text3: &quot;solution&quot;,
  text4: &quot;for you webs&quot;,
};

function Main(){
  &lt;&gt;
    &lt;main&gt;
      &lt;section className=&quot;main__cont&quot;&gt;
        &lt;Info
            text1={textInfo.text1}
            text2={textInfo.text2}
            text3={textInfo.text3}
            text4={textInfo.text4}
        /&gt;
      &lt;/section&gt;
    &lt;/main&gt;
  &lt;/&gt;
}

</code></pre><h3 id="--text로-이름-통일">- text로 이름 통일</h3>
<pre><code>function Info({ text }) {
  return &lt;div&gt;{text}&lt;/div&gt;;
}

const textInfo = {
  { text: &quot;we provide&quot; },
  { text: &quot;visual coding&quot; },
  { text: &quot;solution&quot; },
  { text: &quot;for you webs&quot; }
};

function Main(){
  &lt;&gt;
    &lt;main&gt;
      &lt;section className=&quot;main__cont&quot;&gt;
          &lt;div className=&quot;main__inner&quot;&gt;
            {textInfo.map((txt) =&gt; (
              &lt;Info text={txt.text} /&gt;
            ))}
          &lt;/div&gt;
      &lt;/section&gt;
    &lt;/main&gt;
  &lt;/&gt;
}

</code></pre><hr>
<h2 id="📌-함수형-vs-클래스형-컴포넌트의-차이점">📌 함수형 vs 클래스형 컴포넌트의 차이점</h2>
<p>리액트 컴포넌트를 선언하는 두 가지 방식에는 함수형과 클래스형이 있다. 클래스형 이후에 함수형이 나왔지만, 클래스형을 쓰던 기업의 프로젝트 유지보수를 위해 개념을 알고 있어야 한다. 최근에는 함수형 + 클래스형의 장점을 넣은 리액트 훅을 사용하는 추세이다.</p>
<p>클래스형 컴포넌트는 로직을 컴포넌트 내에서 구현하기 때문에 더 복잡한 UI를 갖게 된다. 반면에, 함수형 컴포넌트는 props로 데이터를 받아서 UI에 뿌려주기 때문에 상대적으로 단순한 형태를 갖게 되며 재사용성이 높다는 장점이 있다. </p>
<h3 id="클래스형-컴포넌트">클래스형 컴포넌트</h3>
<ul>
<li>class 키워드 필요 </li>
<li>Component로 상속 받음 </li>
<li>render() 메소드 필요 </li>
<li>state, lifeCycle 사용 가능 </li>
<li>this.state 초기값 설정, 변경 가능 </li>
<li>this.props로 데이터 불러옴 </li>
<li>메모리 자원의 많은 사용 </li>
<li>임의 메소드 정의 가능 </li>
</ul>
<h3 id="함수형-컴포넌트">함수형 컴포넌트</h3>
<ul>
<li>state, lifeCycle 사용 불가 (Hook으로 해결)</li>
<li>useState 함수로 state 사용 </li>
<li>props 불러올 필요 없이 바로 호출 </li>
<li>메모리 자원 덜 사용 </li>
<li>컴포넌트 선언이 편리함 </li>
</ul>
<hr>
<h2 id="리액트-훅hook">리액트 훅(Hook)</h2>
<p>=&gt; 2019년부터 함수형 컴포넌트에 사용할 수 있는 리액트 훅을 지원하고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ CSS ] - vh, vw, em, rem ]]></title>
            <link>https://velog.io/@roong-ra/CSS-%EB%8B%A8%EC%9C%84-vh-vw-em-rem</link>
            <guid>https://velog.io/@roong-ra/CSS-%EB%8B%A8%EC%9C%84-vh-vw-em-rem</guid>
            <pubDate>Sat, 14 May 2022 08:17:51 GMT</pubDate>
            <description><![CDATA[<h1 id="vh--vw">vh / vw</h1>
<blockquote>
<p>📌 Viewport는 웹사이트에서 보여지는 영역을 뜻하며 <code>vh</code>, <code>vw</code>는 현재 실행중인 스크린 크기를 기준으로 상대적인 크기를 반환하는 단위이다. 
예를들어 현재 스크린 높이가 1000px이라면 1vh=10px, 50vh=500px 이 된다. </p>
</blockquote>
<ul>
<li>특징 1) <code>vh</code> 는 width에서, <code>vw</code>는 height에서 사용 가능하다. </li>
<li>특징 2) 실제 보여지는 화면의 상대적 크기를 반환하기 때문에 스크롤바를 포함한 크기를 반환한다. 반면 %는 전체 화면이 아닌 부모 요소의 크기에 비례하기 때문에 스크롤바와 상관이 없다. </li>
</ul>
<h3 id="vh-viewport-height">vh (Viewport height)</h3>
<ul>
<li>100vh = 전체화면 기준 </li>
<li>1vh = Viewport 높이의 1%<pre><code>div{ height: 20vh; }</code></pre></li>
</ul>
<h3 id="vw-viewport-width">vw (Viewport width)</h3>
<ul>
<li>100vw = 전체화면 기준 </li>
<li>1vw = Viewport 너비의 1% <pre><code>div{ width: 20vw; }</code></pre></li>
</ul>
<hr>
<h1 id="em--rem">em / rem</h1>
<blockquote>
<p>📌 <code>em</code>, <code>rem</code> 은 모두 font-size값에 비례한 상대 단위이다. 
예를 들어 font-size가 16px일 때, 1em=16 x 1=16px, 2em=16 x 2=32px 이다. 여기서 기준이 되는 font-size를 변경하면 그에 따른 상대단위 값들도 함께 변경된다. 
<br><code>em</code>, <code>rem</code> 의 차이점은 어떤 font-size를 기준으로 하는가에 따라 발생한다. 
<code>em</code>은 해당 요소의 font-size를 기준으로 하고, <code>rem</code>의 r은 root를 뜻하므로 최상위 요소(html)의 font-size를 기준으로 한다. </p>
</blockquote>
<ul>
<li><h3 id="em">em</h3>
</li>
</ul>
<pre><code>div{ 
    font-size: 20px;
    width: 10em; /*200px*/
}</code></pre><ul>
<li><h3 id="rem">rem</h3>
</li>
<li>html의 font-size가 16px일 때     <pre><code>div{ 
   font-size: 20px;
   width: 10rem; /*160px*/
}</code></pre></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>