<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sypaik-dev.log</title>
        <link>https://velog.io/</link>
        <description>Frontend Developer</description>
        <lastBuildDate>Mon, 06 Nov 2023 05:29:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sypaik-dev.log</title>
            <url>https://velog.velcdn.com/images/sypaik_dev/profile/cfb56f41-455a-4b06-8896-b0d6f5b21dcb/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sypaik-dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sypaik_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React] react-hook-form]]></title>
            <link>https://velog.io/@sypaik_dev/React-react-hook-form</link>
            <guid>https://velog.io/@sypaik_dev/React-react-hook-form</guid>
            <pubDate>Mon, 06 Nov 2023 05:29:20 GMT</pubDate>
            <description><![CDATA[<h2 id="도입-계기">도입 계기</h2>
<p>로그인 폼과는 달리 회원정보를 입력하는 회원가입 폼에서는 더 많은 입력 필드가 있습니다. 사용자의 입력을 받는 여러 입력 필드가 변경될 때마다 전체 컴포넌트가 리렌더링되는 문제가 발생하고 있었습니다. 입력 필드가 많을수록 이는 성능 문제를 야기할 수 있습니다. 이러한 문제를 해결하기 위해 react-hook-form을 도입하였는데 react-hook-form은 입력 필드의 상태를 직접 관리하고 있어 입력 값이 변경되어도 전체 컴포넌트가 다시 렌더링되지 않습니다. 리렌더링 이슈만을 고려한다면 꼭 react-hook-form을 사용하지않고 useRef를 활용하는 방법도 있지만 유효성 검사를 진행하는 부분이 많다는 점에서 react-hook-form을 사용하게 되었습니다. 그리고 formik과 비교해서 react-hook-form은 가볍고 빠르며 지속적인 업데이트가 이루어진다는 점에서 최종적으로 선정하게 되었습니다.</p>
<h2 id="react-hook-form-알아보기">react-hook-form 알아보기</h2>
<h3 id="useform">useForm</h3>
<p>useForm 훅은 폼을 관리하기 위한 주요 훅입니다. 이를 사용하여 폼의 상태와 유효성 검사를 관리할 수 있습니다.</p>
<h3 id="register">register</h3>
<p>register 함수를 사용하여 입력 요소를 폼에 등록합니다. 입력 요소를 추적하고 값을 검증할 수 있도록 합니다.</p>
<h3 id="handlesubmit">handleSubmit</h3>
<p>handleSubmit 함수는 제출 이벤트를 처리합니다. 이 함수를 폼의 onSubmit 핸들러로 전달하여 제출 이벤트를 처리할 수 있습니다.</p>
<h3 id="errors">errors</h3>
<p>errors 객체는 각 입력 요소의 유효성 검사 오류를 포함합니다. 이를 사용하여 사용자에게 오류 메시지를 표시하거나 폼의 상태를 변경할 수 있습니다.</p>
<h2 id="적용-코드">적용 코드</h2>
<pre><code> &lt;form onSubmit={handleSubmit(onSubmit)}&gt;
      &lt;Input
        label=&#39;이메일&#39;
        id=&#39;email&#39;
        type=&#39;email&#39;
        placeHolder=&#39;이메일 주소를 입력해주세요&#39;
        isError={errors.email?.message}
        errorMsg={errors.email?.message}
        {...emailController.field}
      /&gt;
      &lt;Input
        label=&#39;비밀번호&#39;
        id=&#39;password&#39;
        type=&#39;password&#39;
        placeHolder=&#39;비밀번호를 입력해주세요&#39;
        isError={errors.password?.message || isError}
        errorMsg={errors.password?.message || isError &amp;&amp; message}
        {...passwordController.field}
      /&gt;
      &lt;Button
        type=&#39;submit&#39;
        size=&#39;L&#39;
        text=&#39;로그인&#39;
        isDisabled={!getValues(&#39;email&#39;) || !getValues(&#39;password&#39;)}
      /&gt;
    &lt;/form&gt;</code></pre><p>form 요소는 React Hook Form에서 제공하는 handleSubmit 함수를 사용하여 제출 이벤트를 처리합니다. 이 함수는 실제로 폼이 제출될 때 실행될 함수인 onSubmit을 호출합니다.</p>
<p>Input 컴포넌트는 사용자의 입력을 받는 입력 필드를 나타냅니다. 이메일과 비밀번호 입력 필드가 있으며, 각 입력 필드는 label, id, type, placeHolder 등의 props를 받습니다. isError와 errorMsg props는 유효성 검사 오류가 발생했을 때 표시할 오류 여부와 메시지를 설정합니다. 이러한 입력 필드들은 React Hook Form의 Controller 컴포넌트와 연결되어 해당 필드의 값을 관리하고 유효성 검사를 수행합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[알고리즘] 시간복잡도]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8B%9C%EA%B0%84%EB%B3%B5%EC%9E%A1%EB%8F%84</link>
            <guid>https://velog.io/@sypaik_dev/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%8B%9C%EA%B0%84%EB%B3%B5%EC%9E%A1%EB%8F%84</guid>
            <pubDate>Fri, 29 Sep 2023 13:56:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>자료구조와 알고리즘, <strong>시간복잡도</strong> 대해 공부한 것들을 작성한 글입니다.</p>
</blockquote>
<h1 id="알고리즘이란">알고리즘이란?</h1>
<p>알고리즘은 컴퓨터 과학에서 중요한 개념 중 하나로, <strong>문제를 해결하기 위한 방법</strong>을 의미한다. 입력 데이터를 처리하여 원하는 결과를 생성하는 데 필요한 지침을 제공하며, 주어진 문제를 해결하는 방법을 명확하게 정의한다.
알고리즘의 효율성은 알고리즘이 입력 데이터에 대해 얼마나 빠르게 동작하는지와 밀접한 관련이 있으며, 이와 관련된 주요 개념 중 하나가 시간복잡도이다.</p>
<h1 id="시간복잡도">시간복잡도</h1>
<p>알고리즘에서는 문제를 해결하는 것뿐만 아니라 효율적인 방법으로 문제를 해결하는 것도 중요하다. 다시말해 시간복잡도를 고려해야한다. </p>
<p>시간복잡도는 <strong>문제를 해결하는데 걸리는 시간과 입력의 함수 관계</strong>를 말한다.
입력 크기가 증가하더라도 문제를 해결하는 데 걸리는 시간이 선형적으로 또는 그 이하로 증가하도록 알고리즘이 구성되어야 한다. </p>
<h2 id="시간복잡도-표기-방법">시간복잡도 표기 방법</h2>
<p>시간 복잡도를 나타내기 위한 표기 방법으로는 크게 3가지가 있다.</p>
<ol>
<li>Big-O Notation (빅 오 표기법) | <u>최악</u>의 경우</li>
<li>Big-Ω Notation (빅 오메가 표기법) | <u>최선</u>의 경우</li>
<li>Big-θ Notation (빅 세타 표기법) | <u>평균</u>의 경우</li>
</ol>
<p>이 세가지 중 주로 Big-O 표기법을 사용한다. 이 표기법은 주어진 알고리즘이 얼마나 빨리 실행되는지를 상한으로 제한하여 표현한다. </p>
<h2 id="왜-big-o-표기법을-사용할까">왜 Big-O 표기법을 사용할까</h2>
<p>최선의 경우인 Big-Ω 표기법이나 평균의 경우인 Big-θ 표기법을 사용하지 않고 왜 Big-O 표기법이 널리 사용되는걸까?
왜냐하면 최악의 경우에 대한 보장이 가능하기 때문이다. Big-O 표기법은 알고리즘이 어떤 입력에 대해서도 절대로 더 느리게 실행되지 않을 것임을 보장한다. 따라서 안정성을 보장하고 예측 가능한 성능을 제공하는 데 도움이 된다. 가장 비관적인 상황을 고려하기 때문에 예외적인 경우를 고려하여 시스템을 설계하고 최악의 시나리오에 대비하는 데 도움이 된다.</p>
<h2 id="big-o-표기법이-종류">Big-O 표기법이 종류</h2>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/6c586408-99cb-495c-90d1-d452c0727361/image.png" alt="">
<a href="https://towardsdatascience.com/understanding-time-complexity-with-python-examples-2bda6e8158a7">이미지 출처</a></p>
<h3 id="1-o1---constant-time">1. O(1) - Constant Time</h3>
<ul>
<li>입력크기와 상관없이 항상 일정한 실행 시간을 갖는다.</li>
<li>ex. 배열에서 특정 index의 요소에 접근, 변수에 할당, 산술 연산<pre><code class="language-py">def firt_element(arr):
  print(arr[0])
</code></pre>
</li>
</ul>
<h2 id="입력-크기와-상관없이-항상-1번의-연산만-필요">입력 크기와 상관없이 항상 1번의 연산만 필요</h2>
<pre><code>### 2. O(n) - Linear Time
- 입력크기에 비례하여 시간도 같은 비율로 증가한다.
- ex. 배열의 모든 요소를 한번씩 검사
```py
def linear_search(arr, target):
    for i in range(len(arr)):
        if arr[i] == target:
            return i

## 입력 크기에 직선적으로 비례하여 연산이 필요</code></pre><h3 id="3-olog-n---logarithmic-time">3. O(log n) - Logarithmic Time</h3>
<ul>
<li><p>입력 크기에 대해 로그 형태의 실행 시간을 갖는다.</p>
</li>
<li><p>ex. 이진 탐색 알고리즘 (Binary Search)</p>
<pre><code class="language-py">def binary_search(arr, target):
  left, right = 0, len(arr) - 1

  while left&lt;= right:
      mid = (left + right) // 2
      if arr[mid] == target:
          return mid
      elif arr[mid] &lt; target:
          left = mid + 1
      else:
          right = mid - 1

  return -1
</code></pre>
</li>
</ul>
<h2 id="입력-크기에-대해-로그-시간-복잡도를-가짐">입력 크기에 대해 로그 시간 복잡도를 가짐</h2>
<pre><code>### 4. O(n^2) - Quadratic Time
- 입력 크기에 비례하는 실행 시간을 갖는다.
- ex. 중첩된 반복문을 사용한 정렬 알고리즘 (버블 정렬, 삽입 정렬)
```py
def bubble_sort(arr):
    n = len(arr)

    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] &gt; arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]

# 입력 크기의 제곱에 비례하는 연산이 필요
</code></pre><h3 id="5-on-log-n---quasilinear-time">5. O(n log n) - Quasilinear Time</h3>
<ul>
<li><p>입력 크기에 대해 n * log₂(n)에 비례하는 실행 시간을 갖는다.</p>
</li>
<li><p>대용량 데이터를 다루는 정렬 알고리즘에서 많이 쓰인다.</p>
</li>
<li><p>ex. 병합 정렬(merge sort), 퀵 정렬(quick sort)</p>
<pre><code class="language-py">def merge_sort(arr):
  if len(arr) &gt; 1:
      mid = len(arr) // 2
      left_half = arr[:mid]
      right_half = arr[mid:]

      merge_sort(left_half)
      merge_sort(right_half)

      i = j = k = 0

      while i &lt; len(left_half) and j &lt; len(right_half):
          if left_half[i] &lt; right_half[j]:
              arr[k] = left_half[i]
              i += 1
          else:
              arr[k] = right_half[j]
              j += 1
          k += 1

      while i &lt; len(left_half):
          arr[k] = left_half[i]
          i += 1
          k += 1

      while j &lt; len(right_half):
          arr[k] = right_half[j]
          j += 1
          k += 1
</code></pre>
</li>
</ul>
<h1 id="입력-크기에-대해-on-log-n-복잡도를-가짐">입력 크기에 대해 O(n log n) 복잡도를 가짐</h1>
<pre><code>

### 6. O(2n) - Exponential Time
- 입력 크기가 조금만 커져도 기하급수적으로 증가하는 실행 시간을 갖는다.
- Big-O 표기법 중 가장 느린 시간 복잡도를 갖는다.
- ex. 피보나치 수열을 계산하는 재귀 함수
```py
def fibonacci_recursive(n):
    if n &lt;= 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

# 입력 크기에 기하급수적인 복잡도를 가짐
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 7장. 클래스]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-7%EC%9E%A5.-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-7%EC%9E%A5.-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Fri, 26 May 2023 08:53:14 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스와-인스턴스의-개념-이해">클래스와 인스턴스의 개념 이해</h1>
<h2 id="프로토타입-기반-언어">프로토타입 기반 언어</h2>
<p>먼저, 자바스크립트는 프로토타입 기반의 언어이다. 여기서 프로토타입 기반 언어는 객체지향 패러다임의 한 형태이다. </p>
<p>객체지향 프로그래밍은 데이터와 그 데이터를 처리하는 동작을 하나의 단위로 묶어서 객체라는 개념으로 표현하는 방법론이다. 객체지향 언어는 클래스와 인스턴스를 기반으로 객체를 생성하고 관리하는데 중점을 둔다. 대표적인 객체지향 언어로는 Java, C++, C# 등이 있다.</p>
<p>반면 프로토타입 기반의 자바스크립트에서는 객체를 생성하기 위한 원본이 되는 prototype 객체를 기반으로 새로운 객체(Instance)를 생성한다. 이 새로운 객체는 프로토타입 객체의 속성과 동작을 상속받는다. 상속을 통해 객체는 프로토타입 객체의 메서드와 프로퍼티를 공유하게 된다.</p>
<p>다음은 클래스와 인스턴스의 개념을 이해하기 위한 그림이다.</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/31098be6-9fa8-49e0-b502-ea0e75d0fe5c/image.png" alt=""></p>
<p>Food와 Fruit는 모두 집단, 클래스이다. Food는 Fruit보다 상위의 개념으로 Fruit는 Food보다 하위의 개념으로 Food는 상위클래스(superClass)이고 Fruit는 하위클래스(subClass)이다. 클래스는 하위로 갈수록 상위 클래스의 속성을 상속하면서 더 구체적인 요건이 추가 또는 변경된다.
Fruit 클래스 안에 배, 포도, 딸기, 멜론, 포도는 Fruit의 인스턴스이다. 여기서 인스턴스란 어떤 클래스의 속성을 지니는 실존하는 개체를 일컫는다.</p>
<h2 id="클래스와-인스턴스의-관계">클래스와 인스턴스의 관계</h2>
<p>현실세계에서 클래스와 인스턴스는 집합 개념으로 하나의 인스턴스가 여러 클래스에 속할 수 있지만 프로그래밍 언어에서는 정반대이다. 프로그래밍 언어에서는 하나의 인스턴스는 하나의 클래스만을 바탕으로 만들어진다. 클래스가 먼저 정의돼야만 공통적인 요소를 지니는 개체, 인스턴스들을 생성할 수 있다. </p>
<h1 id="자바스크립트의-클래스">자바스크립트의 클래스</h1>
<h2 id="스태틱-메서드와-프로토타입-메서드">스태틱 메서드와 프로토타입 메서드</h2>
<ul>
<li><p>스태틱 메서드 (Static Method)</p>
<ul>
<li>클래스에 직접 속한 메서드로 인스턴스에 상속되지 않는다. </li>
<li>클래스 레벨에서 호출할 수 있으며, 클래스 이름을 통해 접근한다.</li>
<li>주로 전역적인 기능을 제공하거나, 클래스와 관련된 유틸리티 메서드를 구현하는 데 사용된다.</li>
</ul>
</li>
<li><p>프로토타입 메서드 (Prototype Method)</p>
<ul>
<li>객체의 프로토타입에 속한 메서드이다.</li>
<li>인스턴스에 상속되어 각 인스턴스에서 사용할 수 있다.</li>
<li>프로토타입 체인을 통해 해당 메서드를 찾고 호출할 수 있다.</li>
</ul>
</li>
</ul>
<blockquote>
<p> 💡 <strong>인스턴스 메서드가 대신 프로토타입 메서드!</strong>
객체의 메서드는 해당 객체의 프로토타입 객체에 정의되어 있다. 객체의 프로토타입 체인을 통해 상위 객체의 메서드를 상속받아 사용한다. 따라서 &#39;인스턴스 메서드&#39;라는 용어보다 &#39;프로토타입 메서드&#39;가 프로토타입 기반의 객체 생성 방식을 반영하고 명확하게 설명할 수 있는 용어이다.</p>
</blockquote>
<h3 id="예시-코드">[예시 코드]</h3>
<pre><code class="language-js">var Rectangle = function (width, height) {
    this.width = width;
      this.height = height;
} // 생성자 

Rectangle.prototype.getArea = function () {
    return this.width * this.height;
} // 프로토타입 메서드 

Rectangle.isRectangle = function (instance) {
    return instance instanceof Rectangle &amp;&amp;
      instance.width &gt; 0 &amp;&amp; instance.height &gt; 0;
} // 스태틱 메서드

var rect1 = new Rectangle(3, 4);
console.log(rect1.getArea());
console.log(rect1.isRectangle(rect1)); // 🚨Error
console.log(Rectangle.isRectangle(rect1));</code></pre>
<p>해당 코드에서 두번째 출력값에서 에러가 발생하는데 이유가 무엇일까?
getArea는 프로토타입 메서드로 rect1 인스턴스가 접근할 수 있지만 isRectagle은 스태틱 메서드로 인스턴스가 직접 접근할 수 없다. 해당 스태틱 메서드는 클래스에 직접 속해 있어 인스턴스가 아닌 클래스 이름을 통해 호출되어야 한다.</p>
<blockquote>
<p>💡 <strong>&#39;클래스가 추상적일 수 있고 구체적인 개체가 될 수 있다&#39;</strong>의 의미?
클래스가 추상적인 경우는 구체적인 객체를 생성하기 위한 &#39;템플릿&#39; 또는 &#39;틀&#39;의 역할을 담당하는 목적을 가질 때를 말한다.
반면 클래스가 구체적인 개체가 되는 경우는 클래스 자체를 this로 직접 접근해야만 하는 스태틱 메서드를 호출할 때의 클래스는 그 자체가 하나의 개체로서 취급된다.</p>
</blockquote>
<h1 id="상위-클래스에서의-접근-수단-제공">상위 클래스에서의 접근 수단 제공</h1>
<p>하위 클래스에서 상위 클래스의 프로토타입 메서드에 접근하기 위한 방법은 없을까? 상위 클래스의 메서드에 접근하고 호출하여 실행 결과를 사용하는 방식으로 super 키워드를 흉내낼 수 있다. 다음 예시를 보자.</p>
<pre><code class="language-js">const extendClass = function (SuperClass, SubClass, subMethods){
    SubClass.prototype = Object.create(SuperClass.prototype);
    SubClass.prototype.constructor = SubClass;
    SubClass.prototype.super = function (propName){
        const self = this;
        if (!propName) return function (){
            SuperClass.apply(self, arguments);
        };
        const prop = SuperClass.prototype[propName];
        if (typeof prop !== &quot;function&quot;) return prop;
        return function () {
            return prop.apply(self, arguments);
        };
    }


    if (subMethods){
        for (let method in subMethods){
            SubClass.prototype[method] = subMethods[method];
        }
    }
    Object.freeze(SubClass.prototype);
    return SubClass; 
}



const Rectangle = function (width, height) {
    this.width = width;
    this.height = height;
}

Rectangle.prototype.getArea = function () {
    return this.width * this.height;
}

const Square= extendClass(
    Rectangle,
    function (width){
        this.super()(width, width);
    }, {
        getArea: function (){
            console.log(&#39;size if :&#39;, this.super(&quot;getArea&quot;)());
        }
    }
);
const sq = new Square(10);
sq.getArea();     // size is : 100 (subclass의 메서드 실행)
console.log(sq.super(&quot;getArea&quot;)());   // 100  (superclass의 메서드 실행)</code></pre>
<p>위의 코드에서 Rectangle이라는 상위 클래스와 Square라는 하위 클래스를 생성한다. Rectangle은 width와 height를 인자로 받는 생성자와 getArea 메서드를 가지고 있고 Square는 Rectangle을 상속받아 정사각형을 표현하는 클래스이다.</p>
<p>Square 클래스에서 getArea 메서드를 오버라이드하고 있다. 이 메서드에서는 먼저 하위 클래스의 메서드가 실행되고, 그 후에 this.super(&quot;getArea&quot;)()를 호출하여 상위 클래스의 getArea 메서드를 실행하고 있다. 이를 통해 상위 클래스의 실행 결과를 바탕으로 추가 작업을 수행하고 있다.</p>
<p>예를 들어, sq.getArea()를 호출하면 &#39;size is: 100&#39;이 출력되는데, 이는 하위 클래스인 Square의 getArea 메서드에서 추가 작업한 결과이다. 또한 sq.super(&quot;getArea&quot;)()를 호출하면 100이 반환되는데, 이는 상위 클래스인 Rectangle의 getArea 메서드를 실행한 결과이다.</p>
<p>이를 통해 위의 코드는 상위 클래스의 메서드에 접근하고 호출하여 실행 결과를 사용하는 방식으로 super 키워드를 흉내내고 있습니다.</p>
<h1 id="es6의-클래스-및-클래스-상속">ES6의 클래스 및 클래스 상속</h1>
<h2 id="es5와-es6-클래스-문법-비교">ES5와 ES6 클래스 문법 비교</h2>
<p>아래 코드는 ES5와 ES6의 클래스 문법을 비교하고 있다.</p>
<pre><code class="language-js">const ES5 = function (name) {
    this.name = name;
}
ES5.staticMethod = function () {
    return this.name + &#39;staticMethod&#39;;
}
ES5.prototype.method = function () {
    return this.name + &#39;method&#39;;
}

const ES6 = class {
    // 생성자
    constructor (name) {
        this.name = name;
    }

    // static method : 생성자 함수(클래스)만이 호출할 수 있음.
    static staticMethod () {
        return this.name + &#39;staticMethod&#39;;
    }

    // prototype method
    method () {
        return this.name + &#39;method&#39;;
    }

};
</code></pre>
<p>ES5는 ES5 버전에서 클래스를 생성하기 위해 사용되는 함수 생성자이다. ES5 함수 생성자에는 name이라는 인자를 받으며, this.name 프로퍼티를 초기화한다. ES5.staticMethod은 정적(static) 메서드로, 클래스 자체에 바로 접근하여 호출할 수 있다. ES5.prototype.method는 프로토타입 메서드로, 인스턴스를 통해 호출될 수 있으며, this.name + &#39;method&#39;을 반환한다.</p>
<p>이와 달리, ES6은 ES6 버전에서 도입된 클래스 문법을 사용하여 클래스를 생성한다. ES6 클래스는 생성자 함수로 name을 인자로 받는다. 생성자 함수 내에서는 this.name을 초기화한다. staticMethod는 정적(static) 메서드로, 클래스 자체에 바로 접근하여 호출할 수 있다. 이 정적 메서드도 this.name + &#39;staticMethod&#39;을 반환한다. method은 프로토타입 메서드로, 인스턴스를 통해 호출될 수 있으며, this.name + &#39;method&#39;을 반환한다.</p>
<p>ES6 클래스 문법은 더 간결하고 직관적인 방식으로 클래스를 정의할 수 있게 해준다. 생성자 함수와 프로토타입 메서드를 따로 정의할 필요 없이 클래스 내에서 직접 정의할 수 있다. 또한, 정적 메서드를 static 키워드를 사용하여 간단하게 정의할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 6장. 프로토타입]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-6%EC%9E%A5.-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-6%EC%9E%A5.-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</guid>
            <pubDate>Thu, 18 May 2023 16:45:17 GMT</pubDate>
            <description><![CDATA[<h1 id="프로토타입의-개념-이해">프로토타입의 개념 이해</h1>
<p>constructor, prototype, instance를 이해하기 위해 다음과 같은 그림이 보자.</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/ca4b9fa2-a012-4dd5-b366-b83f4563688c/image.png" alt=""></p>
<pre><code class="language-js">var instance = new Constructor();</code></pre>
<p>어떤 생성자 함수 Constructor를 new 연산자와 함께 호출하면
Constructor에서 정의된 내용을 바탕으로 새로운 인스턴스 instance가 생성된다.
이때 instance에는 <code>__proto__</code>라는 프로퍼티가 자동으로 부여되는데 이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조한다. </p>
<h2 id="prototype과-__proto__-의-관계">prototype과 <code>__proto__</code> 의 관계</h2>
<p>prototype과 <code>__proto__</code> 모두 객체이다.
prototype은 생성자 함수가 정의될 때 사용되는 프로퍼티이다. 생성자 함수로부터 생성된 모든 객체의 공통된 프로퍼티와 메서드를 포함한다. 같은 생성자로부터 생성된 객체는 프로토타입을 공유하여 메모리를 절약할 수 있다.
<code>__proto__</code>는 객체의 프로토타입 객체를 가리키는 내부 프로퍼티이다. 이 프로퍼티를 통해 객체는 자신의 프로토타입 객체에 접근할 수 있다. <code>__proto__</code>를 사용하면 객체는 자신의 프로토타입 객체에 직접 접근할 수 있고, 프로토타입 체인을 따라가면서 상위 프로토타입 객체의 프로퍼티와 메서드를 탐색할 수 있다. </p>
<blockquote>
<p>💡 <strong>주의사항</strong>
<code>__proto__</code>는 비표준 프로퍼티이므로 권장되는 방법이 아니다. ECMAScript 5부터 이 대신 <code>Object.getPrototypeOf</code> 메서드를 사용하여 객체의 프로토타입에 접근하는 것이 권장된다. </p>
</blockquote>
<h3 id="예시-1-person-prototype--proto">[예시 1] Person prototype &amp; proto</h3>
<p>prototype과 <code>__proto__</code>를 이해하기 위한 몇 가지 예를 살펴보자.</p>
<pre><code class="language-js">var Person = function (name) {
    this._name = name;
}

Person.prototype.getName = function() {
    return this._name;
}

var sypaik = new Person(&#39;Sypaik&#39;);
sypaik.__proto__getName()</code></pre>
<p>해당 결과값을 <code>undefined</code> 가 나온다. 
에러가 발생하지 않고 undefined가 나온 것은 이 변수가 <strong>호출할 수 있는 함수</strong>에 해당한다는 것을 의미한다.</p>
<p>➡️ 결론적으로 메서드 내부에서 this에 바인딩된 대상이 잘못 지정되기 때문이다.
Person.prototype.getName 메서드는 this._name 값을 반환하는 역할을 한다. 하지만 <code>sypaik.__proto__getName()</code> 으로 메서드를 호출할 경우, this에 바인딩된 대상은 <code>sypaik.__proto__</code> 즉, <code>Person.prototype</code> 객체가 된다.
Person.prototype 객체에는 *<em>_name *</em> 프로퍼티가 정의되어 있지 않기 때문에 this._name이 undefined를 반환하게 되어 결과값이 undefined가 되는 것이다.</p>
<p>✅ 올바른 방법은 sypaik 객체 자체에 getName 메서드를 호출해야한다. 즉, <code>sypaik.getName()</code> 으로 호출하는 것이다. 이렇게 하면 this는 sypaik 객체에 바인딩되어 this._name은 Sypaik이 반환된다.</p>
<p>만약 <code>__proto__</code> 객체에 name 프로퍼티가 있다면 어떨까?</p>
<pre><code class="language-js">var sypaik = new Person(&#39;Sypaik&#39;);
sypaik.__proto__._name = &#39;Sypaik__proto__&#39;
sypaik.__proto__.getName(); // Sypaik__proto__
sypaik.getName(); // Sypaik</code></pre>
<p><code>__proto__</code> 객체에 name 프로퍼티가 있으면 <code>Sypaik__proto__</code>가 잘 출력되지만 없이도 메서드를 쓸 수 있다.</p>
<blockquote>
<p>💡 <strong><code>__proto__</code>가 생략 가능한 프로퍼티</strong>
proto 프로퍼티는 인스턴스와 생성자 함수의 프로토타입 객체 간의 연결을 나타내는 역할을 한다.
앞선 예시에서 자바스크립트 엔진은 인스턴스에서 메서드 또는 프로퍼티를 찾을 때, 먼저 인스턴스 자체에 해당 메서드 또는 프로퍼티가 있는지 확인하고, 없다면 <code>__proto__</code> 를 통해 프로토타입 체인을 따라 올라가서 찾게 된다. 
따라서 <code>__proto__</code> 프로퍼티의 존재로 인해 인스턴스는 생성자 함수의 프로토타입 객체에 정의된 메서드나 프로퍼티를 마치 자신의 것처럼 접근할 수 있다.</p>
</blockquote>
<h3 id="예시-2-constructor-prototype--proto">[예시 2] Constructor prototype &amp; proto</h3>
<pre><code class="language-js">var Constructor = function (name) {
    this.name = name;
};
Constructor.prototype.method1 = function() {};
Constructor.prototype.property1 = &#39;Constructor Prototype Property&#39;;

var instance = new Constructor(&#39;Instance&#39;);
console.dir(Constructor);
console.dir(instance);
</code></pre>
<p>생성자 함수를 정의하고 해당 생성자 함수의 프로토타입에 메서드와 프로퍼티를 추가한 후 인스턴스를 생성하는 예시이다.</p>
<p>개발자 도구 콘솔에서 해당 코드의 실행한 결과를 확인해보면 다음과 같다.</p>
<p>Constructor의 prototype과 instance의 <code>__proto__</code> 는 동일한 프로토타입 객체를 가리키고 있다. </p>
<h3 id="예시-3-array-prototype--proto">[예시 3] Array prototype &amp; proto</h3>
<pre><code class="language-js">var arr = [1, 2];
console.dir(arr);
console.dir(Array);</code></pre>
<p>arr 변수와 생성자 함수 Array를 개발자 도구를 통해 확인해보면,
배열 리터럴인 arr 변수의 <code>__proto__</code> 의 메서드와 생성자 함수 Array의 prototype의 메서드가 거의 동일함을 확인할 수 있다. 
인스턴스의 <strong>proto</strong> 는 Array.prototype을 참조하는데 <code>__proto__</code>가 생략 가능하도록 설계돼 있어 인스턴스가 메서드를 마치 자신의 것처럼 호출할 수 있다는 것이다.</p>
<h2 id="객체-전용-메서드의-예외사항">객체 전용 메서드의 예외사항</h2>
<p>자바스크립트는 객체 지향 프로그래밍 언어로, 객체는 프로퍼티와 메서드를 가질 수 있는 독립적인 개체인데 <strong>프로토타입</strong> 기반 상속을 지원하기에 객체가 다른 객체로부터 상속받을 수 있다.
객체의 메서드는 해당 객체가 속한 프로토타입 체인에 정의되어 있다. 프로토타입 체인은 해당 객체를 만들 때 사용한 생성자 함수의 프로토타입과 연결된 객체들의 체인이다. 이 체인을 따라 올라가면 해당 메서드를 찾는다. 그러나 기본 데이터 타입들(숫자-Number, 문자열-String)은 객체가 아니며 프로토타입 체인이 없거나 제한적이기 때문에 이러한 메서드를 직접 정의할 수 없다. </p>
<pre><code class="language-js">Object.prototype.getEntries = function() {
  var res = [];
  for (var prop in this) {
    if (this.hasOwnProperty(prop)) {
      res.push([prop, this[prop]]);
    }
  }
  return res;
};

var data = [
  [&#39;object&#39;, {a: 1, b: 2, c: 3}],
  [&#39;number&#39;, 345],
  [&#39;string&#39;, &#39;abc&#39;],
  [&#39;boolean&#39;, false],
  [&#39;func&#39;, function () {}],
  [&#39;array&#39;, [1, 2, 3]]
];

data.forEach(function (datum) {
  console.log(datum[1].getEntries());
});
</code></pre>
<p>해당 코드를 실행해보면, 모든 데이터가 오류 없이 결과를 반환하고 있다. 객체가 아닌 다른 데이터 타입에 대해서는 오류가 발생해야하지만 객체인 경우에만 &#39;getEntries&#39; 메서드를 호출하여 객체의 프로퍼티와 값을 배열로 반환하고, 다른 데이터 타입인 경우는 그냥 넘어가는 동작을 수행한다. 
객체 전용 메서드는 Object.prototype이 아닌 Object에 스태틱 메서드로 추가되어야 한다. 
객체 전용 메서드는 모든 객체가 공통으로 사용할 수 있는 기능을 제공하여 모든 객체의 조상인 Object.prototype에 추가하는 것은 좋지 않다. Object.prototype에 추가된 메서드는 모든 객체에서 호출 가능하기 때문에, 원하지 않는 동작을 초래할 수 있습니다. 따라서 객체 전용 메서드는 Object에 스태틱 메서드로 추가되거나, 다른 방식으로 객체를 인자로 받는 형태로 구현되어야 한다.
또한 생성자 함수인 Object와 인스턴스인 객체 리터럴 사이에는 this를 통한 연결이 불가능하다. <code>this</code>는 주로 함수 내부에서 사용되며, 해당 함수가 메서드로 호출되는 경우 해당 객체를 가리키게 되는데 객체 리터럴을 사용하여 객체를 생성하는 경우에는 <code>this</code>가 해당 객체를 가리키지 않기 때문에 객체 리터럴에서는 <code>this</code>를 사용하여 메서드를 정의할 수 없다. 따라서 this의 사용 대신 대상 인스턴스를 인자로 직접 주입해야하는 방식으로 구현돼 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 5장. 클로저]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-5%EC%9E%A5.-%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-5%EC%9E%A5.-%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Sat, 13 May 2023 15:09:21 GMT</pubDate>
            <description><![CDATA[<h1 id="클로저란">클로저란?</h1>
<p>MDN에서는 클로저에 대해 다음과 같이 정의한다.</p>
<blockquote>
<p>클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다. </p>
</blockquote>
<h2 id="렉시컬-스코프-lexical-scope">렉시컬 스코프 (Lexical Scope)</h2>
<p>렉시컬 스코프(Lexical Scope)는 함수를 어디에 정의했는지에 따라 해당 함수의 상위 스코프를 결정하는 개념이다. 다시 말해, 정적 스코프(static scope)라고도 불린다.</p>
<p>렉시컬 스코프는 함수가 선언된 위치에 기반하여 변수나 함수를 참조할 때 어떤 스코프를 탐색해야 하는지 결정한다. 함수가 정의될 때 함수의 상위 스코프에 대한 참조가 정적으로 결정되며, 이 참조는 렉시컬 환경의 &quot;외부 렉시컬 환경에 대한 참조&quot;라는 내부 슬롯에 저장된다. </p>
<p>예를 들면,</p>
<pre><code class="language-js">function outerFunc() {
    const x = 10;

      function innerFunc() {
        console.log(x); // 10
    }
  innerFunc();
}
outerFunc();
</code></pre>
<p>inner 함수는 outer 함수 내에 정의되어 있어 outer 함수의 변수에 접근할 수 있다. (렉시컬 스코프에 따라 결정) inner 함수가 호출될 때, 렉시컬 스코프는 함수가 정의된 시점에 결정된 상위 스코프를 사용하여 변수 x를 찾는다. inner 함수는 outer 함수 내에 정의되었으므로 outer 함수의 스코프를 상위 스코프로 갖게 된다. 따라서 inner 함수는 x를 참조하여 출력할 수 있다.</p>
<h2 id="클로저의-대표적-예시">클로저의 대표적 예시</h2>
<pre><code class="language-js">const x = 1;

function outer() {
    const x = 10;
      const inner = function () { console.log(x); }
    return inner;
}

const innerFunc = outer();
innerFunc(); // 10;</code></pre>
<p>스코프 체인은 상위 스코프에 대한 참조들의 연결로 구성되며, 클로저는 이러한 스코프 체인을 통해 외부 변수에 접근할 수 있다.</p>
<p>inner 함수는 outer 함수 내부에서 정의되었으며, outer 함수의 실행 도중에 생성되었다. inner 함수는 outer 함수가 반환된 이후에도 innerFunc 변수에 할당되어 계속해서 참조할 수 있다. 이렇게 inner 함수가 outer 함수보다 더 오래 유지되는 경우, inner 함수는 이미 생명주기가 종료한 outer 함수의 변수를 참조할 수 있는데 이를 <strong>클로저</strong> 라고 부른다.</p>
<blockquote>
<p>💡 <strong>왜 전역변수 1을 참조하지 않는걸까?</strong>
클로저는 함수가 정의된 시점의 렉시컬 환경을 유지한다. 따라서 inner 함수가 정의될 때 x를 참조할 때 사용하는 상위 스코프는 outer 함수의 렉시컬 환경이기 때문에 inner 함수는 outer 함수의 <code>x</code>를 우선적으로 참조하게 된다. 
만약, 전역 변수 x를 참조하고 싶다면, inner 함수 내에서 x를 찾지 못하게 outer 함수 내에서 x 변수를 선언하지 않게 되면 상위 스코프인 전역 스코프로 이동하여 전역 변수인 x를 참조할 수 있게 된다.</p>
</blockquote>
<h2 id="클로저의-활용">클로저의 활용</h2>
<p>클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다. 객체의 프라이빗한 상태를 만들고, 외부에서 직접 접근하거나 변경할 수 없도록 하는 것을 의미한다. 즉, 상태를 은닉하고 특정 함수에게만 상태 변경을 허용할 수 있다.</p>
<pre><code class="language-js">const outer = function () {
    const a = 1;
      const inner = function () {
        return ++a;
    }
    return inner;
}
var outer2 = outer();
console.log(outer2()); // 2
console.log(outer2()); // 3</code></pre>
<p>outer2 변수에 outer 함수가 호출되어 반환된 inner 함수가 할당된다. 이후 outer2()를 호출하면 inner 함수가 실행되고 a값이 1에서 2, 2에서 3으로 증가한다. </p>
<h1 id="캡슐화와-정보-은닉">캡슐화와 정보 은닉</h1>
<p>캡슐화는 프로퍼티와 메서드를 하나로 묶는 것을 의미한다.
➡️ 데이터와 기능을 함께 그룹화하여 코드의 가독성과 유지 보수성을 향상시키는 데에 도움을 준다. </p>
<p>생성자 함수 내부에 선언된 지역 변수는 외부에서 직접적으로 참조하거나 변경할 수 없다. 이는 지역 변수가 생성자 함수 내부에서만 유효하기 때문이다.</p>
<pre><code class="language-js">function Counter() {
  let count = 0; // 지역 변수

  function increase() {
    count++;
    console.log(&#39;Increased count:&#39;, count);
  }

  function decrease() {
    if (count &gt; 0) {
      count--;
      console.log(&#39;Decreased count:&#39;, count);
    }
  }

  function getCount() {
    return count;
  }

  return {
    increase: increase, // 클로저로 감싼 함수를 반환
    decrease: decrease,
    getCount: getCount
  };
}

const counter = Counter();
counter.increase(); // Increased count: 1
counter.increase(); // Increased count: 2
counter.decrease(); // Decreased count: 1
console.log(counter.getCount()); // 1
console.log(counter.count); // undefined</code></pre>
<p>Counter 함수 내부에서 counter 변수와 <code>increase</code>, <code>decrease</code>, <code>getCount</code> 함수들이 선언되어 있다. counter 변수와 이 변수에 접근하고 조작하는 함수들이 하나의 단위로 묶여있어 데이터와 기능이 함께 그룹화되어 캡슐화가 이루어진다. 
외부에서는 counter 객체를 통해 <code>increase</code>, <code>decrease</code>, <code>getCount</code> 메서드에 접근하여 count 변수에 간접적으로 접근하고 조작할 수 있다. 
➡️ <code>count</code> 변수가 외부로부터 감춰져 캡슐화되고 해당 변수에 직접적인 접근이 제한되는 효과가 있다. </p>
<h1 id="부분-적용-함수">부분 적용 함수</h1>
<p>부분 적용 함수는 n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억했다가, 나중에 (n-m)개의 인자를 넘기면 비로소 원래 함수의 실행 결과를 얻을 수 있게끔 하는 함수를 말한다. </p>
<blockquote>
<p>💡 ** 부분 적용 함수의 이점**</p>
</blockquote>
<ol>
<li>재사용성 - 원래 함수의 일부 인자를 고정한 후, 해당 부분을 재사용할 수 있다. 그래서 같은 함수를 여러 번 호출하지 않고도 반복되는 코드를 줄일 수 있다.</li>
<li>코드 간소화 - 일부 인자를 미리 고정한 새로운 함수를 생성하여 코드를 간결하고 가독성 좋게 작성할 수 있다.</li>
<li>유연성 - 함수를 더 동적으로 조합하고 활용하라 수 있다.</li>
</ol>
<h2 id="예제1-bind-메서드를-활용한-부분-적용-함수">[예제1] bind 메서드를 활용한 부분 적용 함수</h2>
<pre><code class="language-js">var add = function () {
    console.log(this)
    var result = 0;
    for (var i = 0; i &lt; arguments.length; i++) {
        result += arguments[i];
    }

    return result;
};

var addPartial = add.bind(null, 1, 2, 3, 4, 5);
console.log(addPartial(6, 7, 8, 9, 10)); // 55 출력</code></pre>
<p><code>bind()</code> 메서드는 첫 번째 인자로 함수가 실행될 때의 this 값을 받고, 그 이후의 인자로는 미리 고정할 인자들을 받습니다.</p>
<h2 id="예제2-부분-적용-함수-구현1">[예제2] 부분 적용 함수 구현(1)</h2>
<h2 id="예제3-부분-적용-함수-구현2">[예제3] 부분 적용 함수 구현(2)</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 4장. 콜백함수]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-4%EC%9E%A5.-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-4%EC%9E%A5.-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</guid>
            <pubDate>Sat, 06 May 2023 11:02:37 GMT</pubDate>
            <description><![CDATA[<h1 id="동기와-비동기">동기와 비동기</h1>
<h2 id="동기적인-코드">동기적인 코드</h2>
<p>현재 실행 중인 코드가 완료 된 후에야 다음 코드를 실행하는 방식
CPU의 계산에 의해 즉시 처리가 가능한 대부분의 코드</p>
<h2 id="비동적인-코드">비동적인 코드</h2>
<p>현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어감</p>
<ul>
<li><p>setTimeout : 사용자의 요청에 의해 특정 시간이 경과되기 전까지 어떤 함수의 실행을 보류</p>
</li>
<li><p>addEventListener : 사용자의 직접적인 개입이 있을 때 비로소 어떤 함수를 실행을 보류</p>
</li>
<li><p>XMLHttpRequest : 웹브라우저 자체가 아닌 별도의 대상에 무언가를 요청하고 그에 대한 응답이 왔을 때 비로소 어떤 함수를 실행하도록 대기
웹의 복잡도가 높아지면서 비동기적인 코드의 비중이 높아졌고, 그에 따라 콜백 지옥에 빠지기도 쉬워짐</p>
<h3 id="예제---콜백-지옥">예제 - 콜백 지옥</h3>
<pre><code class="language-js">setTimeout(function (name) {
let coffeeList = name;
console.log(coffeeList); // &quot;에스프레소&quot;

setTimeout(function (name) {
  coffeeList += &#39;, &#39; + name;
  console.log(coffeeList); // &quot;에스프레소, 아메리카노&quot;

  setTimeout(function (name) {
    coffeeList += &#39;, &#39; + name;
    console.log(coffeeList); // &quot;에스프레소, 아메리카노, 카페모카&quot;

    setTimeout(function (name) {
      coffeeList += &#39;, &#39; + name;
      console.log(coffeeList); // &quot;에스프레소, 아메리카노, 카페모카, 카페라떼&quot;
    }, 500, &#39;카페라떼&#39;);
  }, 500, &#39;카페모카&#39;);
}, 500, &#39;아메리카노&#39;);
}, 500, &#39;에스프레소&#39;);</code></pre>
<p>목적 달성에는 지장이 없지만 들여쓰기 수준이 과도하게 깊어짐
값이 전달되는 순서가 &#39;아래에서 위로&#39; 향하고 있어 어색하게 느껴짐</p>
</li>
</ul>
<h3 id="예제---콜백-지옥-해결--기명-함수로-변환">예제 - 콜백 지옥 해결 / 기명 함수로 변환</h3>
<pre><code class="language-js">let coffeeList = &#39;&#39;;

const addEspresso = function (name) {
  coffeeList = name;
  console.log(coffeeList); // &quot;에스프레소&quot;
  setTimeout(addAmericano, 500, &#39;아메리카노&#39;);
};

const addAmericano = function (name) {
  coffeeList += &#39;, &#39; + name;
  console.log(coffeeList); // &quot;에스프레소, 아메리카노&quot;
  setTimeout(addMocha, 500, &#39;카페모카&#39;);
};

const addMocha = function (name) {
  coffeeList += &#39;, &#39; + name;
  console.log(coffeeList); // &quot;에스프레소, 아메리카노, 카페모카&quot;
  setTimeout(addLatte, 500, &#39;카페라떼&#39;);
};

const addLatte = function (name) {
  coffeeList += &#39;, &#39; + name;
  console.log(coffeeList); // &quot;에스프레소, 아메리카노, 카페모카, 카페라떼&quot;
};

setTimeout(addEspresso, 500, &#39;에스프레소&#39;);</code></pre>
<p>코드의 가독성을 높임
함수 선언과 함수 호출만 구분할 수 있다면 위에서부터 아래로 순서대로 읽어 내려가는데 어려움이 없음</p>
<h3 id="예제---비동기-작업의-동기적-표현">예제 - 비동기 작업의 동기적 표현</h3>
<p>ES6(ES2015)에서 Promise, Generator 등이 도입
ES8(ES2017)에서 async / await 이 도입</p>
<h4 id="promise1">Promise(1)</h4>
<pre><code class="language-js">new Promise(function (resolve) {
  setTimeout(function () {
    const name = &#39;에스프레소&#39;;
    console.log(name);
    resolve(name);
  }, 500);
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      const name = prevName + &#39;, 아메리카노&#39;;
      console.log(name);
      resolve(name);
    }, 500);
  });
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      const name = prevName + &#39;, 카페모카&#39;;
      console.log(name);
      resolve(name);
    }, 500);
  });
}).then(function (prevName) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      const name = prevName + &#39;, 카페라떼&#39;;
      console.log(name);
      resolve(name);
    }, 500);
  });
})</code></pre>
<p>new 연산자와 함께 호출한 Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행
그 내부에 resolve 또는 reject 함수를 호출하는 구문이 있을 경우 둘 중 하나가 실행되기 전까지는 then 또는 catch 로 넘어가지 않음</p>
<h4 id="promise2">Promise(2)</h4>
<pre><code class="language-js">const addCoffee = function (name) {
  return function (prevName) {
    return new Promise(function (resolve) {
      setTimeout(function () {
        const newName = prevName ? (prevName + &#39;, &#39; + name) : name;
        console.log(newName);
        resolve(newName);
      }, 500);
    });
  }
};

addCoffee(&#39;에스프레소&#39;)()
  .then(addCoffee(&#39;아메리카노&#39;))
  .then(addCoffee(&#39;카페모카&#39;))
  .then(addCoffee(&#39;카페라떼&#39;))</code></pre>
<p>반복적인 내용을 함수화해서 더욱 짧게 표현</p>
<h4 id="generator">Generator</h4>
<pre><code class="language-js">const addCoffee = function (prevName, name) {
  setTimeout(function () {
    coffeeMaker.next(prevName ? prevName + &#39;, &#39; + name : name);
  }, 500);
};

const coffeeGenerator = function* () {
  const espresso = yield addCoffee(&#39;&#39;, &#39;에스프레소&#39;);
  console.log(espresso);

  const americano = yield addCoffee(espresso, &#39;아메리카노&#39;);
  console.log(americano);

  const mocha = yield addCoffee(americano, &#39;카페모카&#39;);
  console.log(mocha);

  const latte = yield addCoffee(mocha, &#39;카페라떼&#39;);
  console.log(latte);
};

const coffeeMaker = coffeeGenerator();
coffeeMaker.next();</code></pre>
<p>ES6의 Generator를 이용
&#39;*&#39;이 붙은 함수가 Generator
Generator 함수를 실행하면 Iterator가 반환되고, Iterator는 next라는 메서드를 가지고 있음
next 메서드를 호출하면 Generator 함수 내부에서 가장 먼저 등장하는 yield에서 함수의 실행을 멈춤
이후 다시 next 메서드를 호출하면 앞서 멈췄던 부분부터 시작해서 그 다음에 등장하는 yield에서 함수의 실행을 멈춤
비동기 작업이 완료되는 시점마다 next 메서드를 호출하면 Generator 함수 내부의 소스가 위에서부터 아래로 순차적으로 진행 됨</p>
<h4 id="promise--asyncawait">Promise + Async/Await</h4>
<pre><code class="language-js">const addCoffee = function (name) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(name);
    }, 500);
  });
};

const coffeeMaker = async function () {
  let coffeeList = &#39;&#39;;
  const _addCoffee = async function (name) {
    coffeeList += (coffeeList ? &#39;,&#39; : &#39;&#39;) + await addCoffee(name);
  };

  await _addCoffee(&#39;에스프레소&#39;);
  console.log(coffeeList);
  await _addCoffee(&#39;아메리카노&#39;);
  console.log(coffeeList);
  await _addCoffee(&#39;카페모카&#39;);
  console.log(coffeeList);
  await _addCoffee(&#39;카페라떼&#39;);
  console.log(coffeeList);

};

coffeeMaker();</code></pre>
<p>ES8(ES2017)에서 가독성이 뛰어나면서 작성법도 간단한 새로운 기능이 추가
비동기 작업을 수행하고자 하는 함수 앞에 async 표기, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await 표기
await 뒤의 내용이 Promise로 자동 전환, 해당 내용이 resolve 된 이후에야 다음으로 진행</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 3장. this]]></title>
            <link>https://velog.io/@sypaik_dev/JavaScriptthis</link>
            <guid>https://velog.io/@sypaik_dev/JavaScriptthis</guid>
            <pubDate>Fri, 28 Apr 2023 08:06:32 GMT</pubDate>
            <description><![CDATA[<h1 id="this-키워드">this 키워드</h1>
<p>대부분의 경우 <strong>this</strong>의 값은 함수를 호출한 방법에 의해 결정됩니다.
객체는 상태를 나타내는 프로퍼티와 동작을 나타내는 메서드를 하나의 논리적 단위로 묶은 복합적인 자료구조이다.
동작을 나타내는 메서드는 자신이 속한 객체의 상태, 즉 프로퍼티를 참조하고 변경할 수 있어야 한다. 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다. </p>
<h1 id="일반-함수-호출">일반 함수 호출</h1>
<p>기본적으로 this에는 전역 객체가 바인딩된다.</p>
<pre><code class="language-js">function order() {
    console.log(this);
      function count() {
        console.log(this);
    }
      count();
}
order();</code></pre>
<p>전역함수와 중첩 함수를 일반 함수로 호출하면 함수 내부의 this에는 전역 객체인 <strong>window</strong>가 바인딩된다. this는 객체의 프로퍼티나 메서드를 참조하기 위한 자기 참조 변수이므로 객체를 생성하지 않은 일반함수에서는 this는 아무런 의미를 가지지 않는다. </p>
<h2 id="use-strict">use strict</h2>
<p><code>use strict</code> 는 더 엄격한 문법 및 에러 처리를 적용하여 코드의 안전성을 높인다. </p>
<pre><code class="language-js">function order() {
      &#39;use strict&#39;;

    console.log(this); // undefined
      function count() {
        console.log(this); // undefined
    }
      count();
}
order();</code></pre>
<p>함수 내부의 this값은 전역 객체(window 객체 또는 global 객체)가 아닌 <code>undefined</code>가 된다. 이는 this를 의도치 않게 전역 객체에 바인딩되는 것을 방지하기 위함이다.</p>
<blockquote>
<p><code>use strict</code> 는 스크립트 최상단에 있어야 한다! 그렇지 않으면 엄격 모드가 활성화되지 않을 수도 있다.</p>
</blockquote>
<h2 id="콜백함수">콜백함수</h2>
<ul>
<li>setTimeout 함수<pre><code class="language-js">setTimeout(function() {
  console.log(this); // window;
}) // 콜백 함수가 일반 함수로 호출되었으므로 전역 객체가 바인딩된다.</code></pre>
</li>
</ul>
<pre><code class="language-js">const obj = {
    value: 100,
      getName() {
        console.log(this); // {value: 100, getName: f}
    }
      setTimeout(function () {
        console.log(this); // window
          console.log(this.value) // 1
    }, 100)
}</code></pre>
<pre><code class="language-js">const obj = {
    value: 100,
      getName() {
        const that = this;
    setTimeout(function () {
        console.log(that.value); // 100
    }, 100)
    }
};

obj.getName()</code></pre>
<ul>
<li><p>forEach</p>
<pre><code class="language-js">[10, 20, 30].forEach((num) =&gt; {
  console.log(this, num); // widnow, num;
})</code></pre>
</li>
<li><p>addEventListener</p>
<pre><code class="language-js">document.body.querySelector(&#39;.btn&#39;).addEventListener(&#39;click&#39;, function(e) {
  console.log(this, e) // 
})</code></pre>
</li>
</ul>
<h1 id="메서드-호출-암시적-바인딩">메서드 호출 (암시적 바인딩)</h1>
<p>함수가 객체의 프로퍼티 값이면 메서드로서 호출된다. 메서드 내부의 this는 해당 메서드를 소유한 객체, 즉 <strong>해당 메서드를 호출한 객체</strong>에 바인딩된다.</p>
<blockquote>
<p>this에 바인딩될 객체는 호출 시점에 결정된다.  </p>
</blockquote>
<pre><code class="language-js">const aurora = {
    name: &quot;Charlie&quot;,
      getName() {
        return this.name;
    }
};

console.log(aurora.getName()); // Charlie
</code></pre>
<pre><code class="language-js">const bell = {
    name: &quot;Dayeon&quot;;
}

bell.getName = aurora.getName; // getName 메서드를 bell 객체의 메서드로 할당
console.log(bell.getName()); // Dayeon

const getName = aurora.getName; // getName 메서드를 변수에 할당
console.log(getName()) // &#39;&#39; ==&gt; window.name과 같음!</code></pre>
<pre><code class="language-js">const obj = {
    outer: function() {
        console.log(this);
          const inner = function() {
            console.log(this); // 함수의 실행으로 window
        };
          inner();
    }
};
obj.outer();</code></pre>
<h1 id="applycallbind-메서드에-의한-간접-호출-명시적-바인딩">apply/call/bind 메서드에 의한 간접 호출 (명시적 바인딩)</h1>
<p>암시적으로 바인딩되는 this는 바인딩을 쉽게 예측할 수 없는 상황이 있었다. 이러한 문제를 해결하기 위해 명시적으로 this를 고정하는 방법을 알아보자.</p>
<h2 id="call-메서드">call 메서드</h2>
<p>메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.</p>
<pre><code class="language-js">function func() {
    console.log(this.a);
}
const obj = {a: 2};
func.call(obj); // 2
func(obj); // undefined</code></pre>
<p>함수의 this는 전역객체지만 <code>call</code>을 사용하면 구체적인 객체를 this로 지정할 수 있다.</p>
<h2 id="apply-메서드">apply 메서드</h2>
<p>call 메서드와 유사한 기능으로 호출 주체 함수를 즉시 실행하지만 <code>call()</code>은 함수에 전달된 매개변수를 받지만 <code>apply()</code>는 인수들의 배열을 받는다.</p>
<pre><code class="language-js">function func(a, b, c) {
    console.log(this, a, b, c);
}

const obj = {a: 2};

func.call(obj, 10, 20, 30) // {a: 2} 10 20 30
func.apply(obj, [10, 20, 30]) // {a: 2} 10 20 30</code></pre>
<h2 id="bind-메서드">bind 메서드</h2>
<p>apply, call과는 달리 함수를 호출하지 않고 this로 사용할 객체만 전달한다. 즉 call, apply 메서드는 this를 명시적으로 지정하면서 함수 또는 메서드를 호출하지만 bind 메서드는 this 및 함수에 넘길 인수를 일부 지정해서 새로운 함수를 만든다.</p>
<pre><code class="language-js">const jasmine = {
    name: &#39;dh&#39;,
      func(callback) {
        setTimeout(callback.bind(jasmine), 100);
    }
};
jasmine.func(function() {
    console.log(&#39;hi, i&#39;m ${this.name}&#39;); // &quot;hi, i&#39;m dh&quot;
})</code></pre>
<h1 id="생성자-함수-호출">생성자 함수 호출</h1>
<pre><code class="language-js">function movie(year, genre, rating) {
    this.year = year;
      this.genre = genre;
      this.rating = rating;
}

const homeAlone = new movie(1991, &#39;comedy&#39;, 7.7);
const avatar = new movie(2009, &#39;fantasy&#39;, 7.9);
const oneDay = new movie(2011, &#39;romance&#39;, 7);

console.log(homeAlone.year); // 1991
console.log(avatar.genre); // &#39;fantasy&#39;
console.log(oneDay.rating); // 7</code></pre>
<p>어떤 함수를 new 명령어와 함께 생성자로서 동작하게 된다. 객체지향 언어에서는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스라고 한다. 생성자 함수란 new 연산자로 함께 호출해서 인스턴스를 생성하는 함수를 일컫는다. 따라서 생성자는 인스턴스를 만들기 위한 일종의 틀이다. 그리고 생성자 함수로 호출된 경우 this는 새로 만들어진 인스턴스 자신이 된다. </p>
<pre><code class="language-js">function Movie(year, genre, rating) {
  // --- (1)
  console.log(this);

  // --- (2)
    this.year = year;
      this.genre = genre;
      this.rating = rating;
      this.getAge = function() {
        return new Date().getFullYear() - this.year + 1;
    };
  // --- (3)
}

// --- (4)
const homeAlone = new movie(1991, &#39;comedy&#39;, 7.7);
const avatar = new movie(2009, &#39;fantasy&#39;, 7.9);
const oneDay = new movie(2011, &#39;romance&#39;, 7);

console.log(homeAlone.year); // 1991
console.log(avatar.genre); // &#39;fantasy&#39;
console.log(oneDay.rating); // 7</code></pre>
<blockquote>
</blockquote>
<ol>
<li>암묵적으로 인스턴스가 생성되고 this에 바인딩된다.</li>
<li>this에 바인딩되어 있는 인스턴스를 초기화한다.</li>
<li>완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다. </li>
<li>인스턴스 생성하고 Movie 생성자 함수는 암묵적으로 this를 반환한다.</li>
</ol>
<h1 id="화살표-함수">화살표 함수</h1>
<p>화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 화살표 함수는 일반적인 바인딩 규칙을 무시하고 Lexical scope로 this를 바인딩한다. 즉 화살표 함수 내부에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 2장. 실행 컨텍스트]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-2%EC%9E%A5.-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-2%EC%9E%A5.-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 13 Apr 2023 16:08:18 GMT</pubDate>
            <description><![CDATA[<h1 id="실행-컨텍스트란">실행 컨텍스트란?</h1>
<h2 id="stack과-queue">Stack과 Queue</h2>
<p><strong>실행 컨텍스트</strong>
실행할 코드에 제공할 정보들을 모아 놓은 객체</p>
<p><strong>실행 컨텍스트의 동작</strong></p>
<p>1) 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트 구성
2) 컨텍스트들을 call stack에 쌓아 올려둠
3) 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행
4) 전체 코드의 환경과 순서 보장</p>
<pre><code class="language-js">// ------------------------- (1)
var a = 1;
function outer() {
    function inner() {
        console.log(a);
          var a = 3;
// ------------------------- (2)
    }
  inner();// --------------- (3)
  console.log(a);
// ------------------------- (4)
}
outer();
// ------------------------- (5)
console.log(a);
// ------------------------- (6)</code></pre>
<p>실행순서는 (1) - (5) - (3) - (2) - (4) - (6)</p>
<blockquote>
<p>💡 코드 실행 과정 </p>
</blockquote>
<ol>
<li>코드를 실행하는 순간 (1) 전역 컨텍스트가 콜 스택에 담긴다</li>
<li>함수 호출문 outer()을 만나는 순간 해당 함수를 콜 스택에 추가한다.</li>
<li>추가된 함수의 내부로 이동하여 코드들을 순차적으로 실행한다.</li>
<li>(3)에서 inner 함수의 실행 컨텍스트가 콜 스택의 최상단에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수 내부의 코드를 순차적으로 진행한다.
❗모든 코드가 콜스택에 처리되었으면 선입후출(FILO, First In Last Out)로 콜스택에서 실행한다.</li>
<li>실행이 완료된 코드는 콜 스택에서 제거되고 아무것도 남지 않은 상태로 종료된다.</li>
</ol>
<h2 id="활성화된-실행-컨텍스트의-수집-정보">활성화된 실행 컨텍스트의 수집 정보</h2>
<ul>
<li><p>VariableEnvironment</p>
<ul>
<li>environmentRecord (snapshot) </li>
<li>outerEnvironmentReference (snapshot)</li>
</ul>
</li>
<li><p>LexicalEnvironment</p>
<ul>
<li>environmentRecord 
: 함수 안의 코드가 실행되기 전에 현재 컨텍스트와 관련된 코드의 식별자 정보가 저장</li>
<li>outerEnvironmentReference </li>
</ul>
</li>
<li><p>ThisBinding</p>
</li>
</ul>
<h1 id="lexicalenvironment">LexicalEnvironment</h1>
<h2 id="environmentrecord와-호이스팅">environmentRecord와 호이스팅</h2>
<h3 id="호이스팅">호이스팅</h3>
<ul>
<li>호이스팅(hoisting): hoist(끌어 올리다) + ~ing ➡️ 식별자들을 최상단으로 끌어 올려놓자</li>
<li>코드가 실행되기 전임에도 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있음 (자바스크립트 엔진은 식별자들을 최상단으로 끌어 올려 놓은 다음 실제 코드를 실행하는 것으로 생각해도 코드 해석에 문제 없음)</li>
</ul>
<h3 id="매개변수와-변수에-대한-호이스팅">매개변수와 변수에 대한 호이스팅</h3>
<ul>
<li>environmentRecord는 현재 실행될 컨텍스트 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있지, 각 식별자들이 어떤 값이 할당될지에는 관심이 없음</li>
</ul>
<p><strong>매개변수와 변수에 대한 호이스팅(1)</strong></p>
<pre><code class="language-js">function a (x) {     // -- 수집대상 1 (매개변수)
    console.log(x); // (1)
      var x;          // -- 수집대상 2 (변수 선언)
      console.log(x); // (2)
      var x = 2;        // -- 수집대상 3 (변수 선언)
      console.log(x); // (3)
}</code></pre>
<ul>
<li>출력 결과: <code>1, 1, 2</code></li>
</ul>
<p><strong>매개변수와 변수에 대한 호이스팅(2)</strong></p>
<pre><code class="language-js">function a ( ) { 
    var x = 1;     // -- 수집대상 1 (매개변수)
      console.log(x); // (1)
      var x;           // -- 수집대상 2 (변수 선언)
      console.log(x); // (2)
      var x = 2;    // -- 수집대상 3 (변수 선언)
      console.log(x); // (3)
}

a();</code></pre>
<ul>
<li>매개변수를 변수 선언 및 할당과 같다고 간주하여 반환</li>
</ul>
<p><strong>매개변수와 변수에 대한 호이스팅(3)</strong></p>
<pre><code class="language-js">function a () {
    var x;  // --------- 수집 대상 1(매개 변수)의 변수 선언 부분
      var x;  // --------- 수집 대상 2의 변수 선언 부분
      var x;  // --------- 수집 대상 3의 변수 선언 부분
      x = 1;  // --------- 수집 대상 1의 할당 부분
      console.log(x); //   (1)
      console.log(x); //      (2)
      x = 2;  // --------- 수집 대상 3의 할당 부분
      console.log(x); //      (3) 
}
a();</code></pre>
<h3 id="함수-선언의-호이스팅">함수 선언의 호이스팅</h3>
<p><strong>함수 선언의 호이스팅(1)</strong></p>
<pre><code class="language-js">function a() {
    console.log(b); // (1)
      var b = &#39;bbb&#39;;  // 수집 대상 1 (변수 선언)
      console.log(b); // (2)
      function b() {} // 수집 대상 2 (함수 선언)
      console.log(b); // (3)
}
a();</code></pre>
<ul>
<li>출력 결과: <code>function b() {}, bbb, bbb</code></li>
</ul>
<p><strong>함수 선언의 호이스팅(2)</strong></p>
<pre><code class="language-js">function a() {
    var b; // ------------ 수집 대상 1(변수 선언)의 선언 부분
      function b() {} // --- 수집 대상 2(함수 선언)의 전체
      console.log(b); // --- (1)
      b = &#39;bbb&#39;; // -------- 수집 대상 1의 할당 부분
      console.log(b); // --- (2)
      console.log(b); // --- (3)
}
a();</code></pre>
<h2 id="함수-선언문과-함수-표현식">함수 선언문과 함수 표현식</h2>
<ul>
<li><p>함수 선언문: function 정의부만 존재하고 별도의 할당 명령이 없는 것</p>
<ul>
<li>반드시 함수명이 정의되어 있음</li>
<li>호이스팅 시 함수 전체를 끌어 올림</li>
</ul>
</li>
<li><p>함수 표현식: 정의한 함수를 별도의 변수에 할당하는 것</p>
<ul>
<li><p>익명 함수 표현식: 함수명을 정의하지 않음</p>
</li>
<li><p>기명 함수 표현식: 함수명을 정의함</p>
<ul>
<li>외부에서 함수명으로 호출 불가능<ul>
<li>함수 내부에서 재귀함수를 호출하는 용도로 함수명을 쓸 수 있음</li>
<li>호이스팅 시 변수로 취급되어 선언 부분만 끌어 올림</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code class="language-js">function a() { /* ... */ } // 함수 선언문. 함수명 a가 곧 변수명
a(); // 실행 가능

var b = function () { /* ... */ } // 익명 함수 표현식. 변수 b가 곧 함수명
b(); // 실행 가능

var c = function d() { /* ... */ } // 기명 함수 표현식. 변수명은 c, 함수명은 d
c(); // 실행 가능
d(); // 실행 불가능. 에러!
</code></pre>
<h3 id="함수-선언문의-위험성">함수 선언문의 위험성</h3>
<ul>
<li>함수 선언문이 코드 상단에 선언되어 있는 상태에서 동일한 이름의 함수 선언문이 코드 하단에 중복해서 선언될 경우</li>
<li>호이스팅 과정에서 두 함수 선언문이 모두 끌어 올려지고, 상대적으로 하단에 있는 함수 선언문이 코드 전체에 영향을 미치게 된다.</li>
<li>함수 표현식으로 함수를 사용한다면 하단의 함수가 나오기 전까지는 상단에 선언된 함수로 사용되다가 하단의 함수가 나오면 그때부터 하단의 함수로 적용된다.</li>
</ul>
<p><strong>함수 선언문 예제</strong></p>
<pre><code class="language-js">console.log(sum(3, 4)); // (1) : 7을 기대하지만, 3 + 4 = 7이 출력

function sum(x, y) { // -- 상단 함수
  return x + y;
}

var a = sum(1, 2);
console.log(a); // ------- (2) : 3을 기대하지만, 1 + 2 = 3이 출력

function sum(x, y) { // -- 하단 함수
  return `${x} + ${y} = ${x + y}`;
}

var c = sum(1, 2);
console.log(c); // ------- (3) : 1 + 2 = 3이 출력
</code></pre>
<p><strong>함수 표현식 예제</strong></p>
<pre><code class="language-js">// console.log(sum(3, 4)); // (1) : sum의 값이 없어서 undefined를 반환하기 때문에 에러! 

var sum = function (x, y) { // -- 상단 함수
  return x + y;
}

var a = sum(1, 2);
console.log(a); // ------- (2) : 3 출력

var sum = function (x, y) { // -- 하단 함수
  return `${x} + ${y} = ${x + y}`;
}

var c = sum(1, 2);
console.log(c); // ------- (3) : 1 + 2 = 3이 출력</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코어자바스크립트] - 1장. 데이터타입]]></title>
            <link>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-1%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@sypaik_dev/%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-1%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%83%80%EC%9E%85</guid>
            <pubDate>Fri, 07 Apr 2023 07:55:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 글은 코어자바스크립트 1장을 읽고 정리한 글입니다.</p>
</blockquote>
<h1 id="01-데이터-타입의-종류와-배경지식">01. 데이터 타입의 종류와 배경지식</h1>
<p><strong>데이터 타입</strong>
데이터 타입은 크게 기본형과 참조형으로 나누어져 있다. 
기본형과 참조형 모두 복제 
    -&gt; 기본형은 값이 담긴 주솟값을 바로 복제
    -&gt; 참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제</p>
<ul>
<li>Primitive type (기본형/원시형) - Number, String, Boolean, null, undefined, Symbol</li>
<li>Preference type (참조형) - Array, Function, Date, RegExp, Map / WeakMap, Set / WeakSet</li>
</ul>
<p><strong>메모리와 데이터</strong>
컴퓨터는 모든 데이터를 0 또는 1로 표현
<strong>비트</strong> - 0 또는 1로 표현할 수 있는 하나의 메모리 조각
메모리는 수많은 비트들로 구성되어 있는데 각 비트는 고유한 식별자를 통해 위치를 확인할 수 있다.
수많은 비트들을 몇 개씩 묶어 하나의 단위로 나타내면 표현할 수 있는 값도 늘어나고 동시에 검색 시간을 줄일 수 있다.
<strong>바이트</strong> - 8개의 비트로 구성 (총 2^8, 256개)
자바, C/C++과 같은 정적 타입 언어는 메모리 낭비를 최소화하기 위해 데이터 타입별로 메모리 영역이 정해져 있어 형변환이 필요했지만 자바스크립트는 메모리 관리가 자유로워 형변환이 크게 필요없다.</p>
<p><strong>식별자와 변수</strong>
<strong>변수</strong>는 변경 가능한 데이터가 담길 수 있는 공간 또는 그릇
<strong>식별자</strong>는 데이터를 식별하는 데 사용하는 이름, 즉 <strong>변수명</strong></p>
<h1 id="02-변수-선언과-데이터-할당">02. 변수 선언과 데이터 할당</h1>
<p><strong>변수 선언</strong></p>
<pre><code class="language-js">var a;</code></pre>
<p>&lt;변수  선언에 대한 메모리 영역의 변화&gt;
<img src="https://velog.velcdn.com/images/sypaik_dev/post/5e1c8aa7-fa2e-451b-9dce-a952bfbd409c/image.jpg" alt=""></p>
<p>컴퓨터는 메모리에서 비어있는 공간 하나를 확보한다. (1003번)
이 공간에 이름(식별자)를 a로 지정한다.</p>
<p><strong>데이터 할당</strong></p>
<pre><code class="language-js">var a;            // 변수 a 선언
a = &#39;abc&#39;;      // 변수 a에 대한 데이터 할당

var a = &#39;abc&#39;     // 변수 선언과 동시에 데이터 할당</code></pre>
<p>&lt;데이터 할당에 대한 메모리 영역의 변화&gt;
<img src="https://velog.velcdn.com/images/sypaik_dev/post/50c4728d-5516-451a-8354-1ce1c872d4a5/image.jpg" alt=""></p>
<ul>
<li>변수 영역에서 빈 공간을 확보한다. (1003번)</li>
<li>확보한 공간에 이름(식별자)를 a로 지정한다.</li>
<li>데이터 영역의 빈 공간(5004번)에 문자열 &#39;abc&#39;를 저장한다.</li>
<li>변수 영역에서 a라는 식별자를 검색한다.</li>
<li>문자열의 주소 (5004번)을 변수 영역 공간(1003번)에 대입한다.</li>
</ul>
<p>다시 말해, 변수 영역에 저장된 주소에 데이터를 할당하지 않는다!</p>
<blockquote>
<p>💡 왜 데이터를 변수 영역에 직접 대입하고 않고 데이터 영역에 따로 저장하는가?</p>
</blockquote>
<ul>
<li>데이터 변환을 자유롭게 할 수 있고 메모리를 효율적으로 관리하기 위함</li>
<li>만약 직접 대입하면, 데이터 변환 시 확보된 공간을 늘리는 작업이 필요하다.</li>
<li>여유 공간이 없다면 데이터를 전부 옮기고 이동시킨 주소를 각 식별자에 다시 연결하는 등 처리해야할 연산량이 너무 많아진다.
🗸 따라서 변수와 데이터를 각각의 공간으로 저장하는 것이 데이터의 변환을 처리할 때, 최적이다!</li>
</ul>
<p><strong>데이터 변환</strong></p>
<pre><code class="language-js">var a = &#39;abc&#39;
a = &#39;abcdef&#39;;</code></pre>
<p>&lt;문자열 변환에 대한 메모리 영역의 변화&gt;</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/0f0d06f3-0f09-4824-82e8-fa0705bd0e0e/image.jpg" alt=""></p>
<ul>
<li>데이터 영역의 빈 공간(5005번)에 문자열 &#39;abcdef&#39;를 저장한다.</li>
<li>변수 a의 메모리를 찾고 해당 메모리 값을 5005로 교체한다</li>
</ul>
<h1 id="03-기본형-데이터와-참조형-데이터">03. 기본형 데이터와 참조형 데이터</h1>
<p><strong>불변값</strong></p>
<ul>
<li>변수와 상수를 구분 짓는 요소 - 변수 영역 메모리의 변경 가능성</li>
<li>불변성 여부를 구분 짓는 요소 - 데이터 영역 메모리의 변경 가능성</li>
<li>기본형 데이터 - Number, String, Boolean, null, undefined, Symbol ==&gt; <strong>불변값</strong></li>
</ul>
<pre><code class="language-js">var a = &#39;abc&#39;;
a = a + &#39;def&#39;;

var b = 5;
var c = 5;
b = 7;</code></pre>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/41331246-2667-4cb8-b66d-6468e18116ba/image.jpg" alt=""></p>
<p>문자열 값도 숫자도 다른 값으로 변경할 수 없다. 여기서 <strong>변경</strong>은 새로 만드는 동작을 통해서만 이루어진다.</p>
<p><strong>가변값</strong></p>
<pre><code class="language-js">var obj1 = {
    a: 1,
      b: &#39;bbb&#39;
};</code></pre>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/b88b2e50-4b61-462e-8b38-f4976f918e7a/image.jpg" alt=""></p>
<ul>
<li>빈 공간에 obj1을 저장한다.</li>
<li>obj1은 여러 개의 프로퍼티로 이루어진 데이터 그룹이다. 내부의 프로퍼티를 저장하기 위해 별도의 변수 영역을 마련하여 영역의 주소인 @7103 ~ ?을 5002에 저장한다.</li>
<li>@7103과 @7104는 각각 a와 b라는 프로퍼티 이름을 저장한다.</li>
<li>프로퍼티 a와 b에 해당하는 숫자, 문자열의 메모리 주소 @5004, @5005를 저장한다.</li>
</ul>
<blockquote>
<p>💡 기본형 데이터와의 차이는?
-&gt; 객체의 변수인 프로퍼티 영역이 별도로 존재한다는 점이다! 
데이터 영역에 저장된 값은 모두 불변값(숫자, 문자열)이지만 변수에는 다른 값을 얼마든지 대입할 수 있기 때문에 불변하지 않다. (= 가변적이다)</p>
</blockquote>
<p>참조형 데이터의 프로퍼티를 재할당하면 어떻게 될까?</p>
<pre><code class="language-js">var obj1 = {
    a: 1,
      b: &#39;bbb&#39;
};

obj1.a = 2;</code></pre>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/043c52b7-f3b1-4000-b6d8-aa21c8f64e87/image.jpg" alt=""></p>
<p>obj1은 변하지 않고, obj1의 프로퍼티 a가 저장된 주소값만 5004에서 5003으로 교체된다.</p>
<p>참조형 데이터의 프로퍼티에 다시 참조형 데이터를 할당하는 경우를 <strong>중첩객체</strong> 라고 한다.</p>
<pre><code class="language-js">var obj = {
    x: 3,
      arr: [3, 4, 5]
};</code></pre>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/02194011-2d65-4930-bee3-b73aad7a80e5/image.jpg" alt=""></p>
<p>새로 추가된 과정은 먼저,</p>
<ul>
<li>@7104에 저장할 값은 배열로 내부 프로퍼티들을 저장하기 위해 별도의 변수 영역을 확보하고 변수 영역의 주소값을 5003에 저장한다.</li>
<li>배열의 길이가 3으로 3개의 변수 공간을 확보하고 각각 인덱스를 부여한다.</li>
<li>arr 내부의 프로퍼티의 값을 각각 5002, 5004, 5005에 저장한다.</li>
</ul>
<p>만약 중첩 객체의 프로퍼티를 재할당한다면 어떻게 될까?</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/a40e329a-3078-4f1f-a1cf-980ada72365a/image.jpg" alt=""></p>
<p>어떤 데이터에 대해 자신의 주소를 참조하는 변수의 개수를 <strong>참조 카운트</strong>라고 한다.
해당 그림에서 @5003, @8104 ~ 는 참조 카운트가 1이었다가 0이 된다. 참조 카운트가 0인 메모리 주소를 가비지 컬렉터(Garbage Collector, GC)로 수거대상이 된다. 수거 대상이 된 가비지 컬렉터는 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박할 때마다 자동으로 수거 대상들을 수거한다. 수거된 메모리는 다시 빈 공간이 되어 새로운 값을 할당받을 수 있다.</p>
<p><strong>변수 복사 비교</strong>
&lt;변수 복사&gt;</p>
<pre><code class="language-js">var a = 10;
var b = a;

var obj1 = {
    c: 10,
      d: &#39;ddd&#39;
};
var obj2 = obj1;</code></pre>
<p>앞서 본 과정과 마찬가지로 각각 변수 영역의 빈 공간을 확보하고 a, b를 지정한다. 둘은 각각의 공간을 가지고 같은 주솟값을 갖는다.
그리고 참조형 데이터는 ob1, obj2에 해당하는 각각의 변수 영역의 빈 공간을 확보하고 데이터 영역의 묶음 주소는 같은 주솟값을 갖는다.</p>
<p>&lt;객체의 프로퍼티 변경&gt;</p>
<pre><code class="language-js">var a = 10;
var b = a;

var obj1 = {
    c: 10,
      d: &#39;ddd&#39;
};
var obj2 = obj1;

b = 15;
obj2.c = 20;</code></pre>
<p>반면 다음과 같이 객체의 프로퍼티가를 변경했을 때에는 다르게 동작한다.
기본형 데이터를 복사한 변수는 b는 값이 달라져 서로 다른 주솟값을 가진다. 반면 obj1과 obj2는 프로퍼티가 저장된 메모리의 값만 바뀌어 메무리 주솟값만 변경될 뿐 ojb1과 obj2는 같은 주솟값을 가진다.</p>
<p>&lt;객체 자체를 변경했을 때&gt;</p>
<pre><code class="language-js">var a = 10;
var b = a;

var obj1 = {
    c: 10,
      d: &#39;ddd&#39;
};
var obj2 = obj1;

b = 15;
obj2 = {
    c: 20,
      d: &#39;ddd&#39;
}</code></pre>
<p>이와 같이 객체 자체를 변경했을 때에는 객체를 새롭게 만들었기 때문에 obj1 !== obj2가 성립한다.</p>
<blockquote>
<p>💡 참조형 데이터의 &#39;가변값&#39;이 언제를 의미할까?
&#39;가변&#39;은 참조형 데이터 자체를 변경했을 때가 아닌 <strong>내부의 프로퍼티</strong>를 변경했을 때만 성립 가능하다.</p>
</blockquote>
<h1 id="04-불변-객체">04. 불변 객체</h1>
<p>참조형 데이터는 &#39;가변적&#39;이라고 하지만 데이터 자체를 변경한다면 기존 데이터는 변경하지 않는 불변성을 확보할 수 있다.
값으로 전달받은 객체에 변경에 변경을 가하더라도 원본 객체는 변하지 않아야 할 때 -&gt; 불변 객체 필요!</p>
<p><strong>얕은 복사</strong></p>
<ul>
<li>바로 아래 단계의 값만 복사하는 방법</li>
<li>중첩된 객체에서 프로퍼티를 복사할 때 그 주솟값만 복사한다. </li>
<li><blockquote>
<p>원본과 사본 모두 동일한 참조형 데이터의 주소를 가리킨다. </p>
</blockquote>
</li>
<li><blockquote>
<p>사본을 바꾸면 원본도 바뀌고, 원본을 바꾸면 사본도 바뀐다.</p>
</blockquote>
</li>
</ul>
<p><strong>깊은 복사</strong></p>
<ul>
<li>내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법</li>
<li>객체의 프로퍼티 중 그 값이 기본형 데이터일 경우는 그대로 복사되지만 참조형 데이터는 다시 그 내부의 프로퍼티를 복사해야한다.</li>
<li><blockquote>
<p>원본과 사본이 서로 완전히 다른 객체를 참조하게 되어 서로 영향을 주지 않는다.</p>
</blockquote>
</li>
</ul>
<h1 id="05-undefined와-null">05. undefined와 null</h1>
<p>&#39;없음&#39;을 나타내는 값으로 같지만 undefined와 null은 미세하게 다르고 사용하는 목적 또한 다르다.</p>
<p><strong>undefined</strong></p>
<ul>
<li>사용자가 명시적으로 지정하는 경우</li>
<li>값이 존재하지 않아 자바스크립트 엔진이 자동으로 부여하는 경우<ol>
<li>값을 대입하지 않은 변수</li>
<li>객체 내부의 존재하지 않는 프로퍼티에 접근하려고 할 때</li>
<li>return 문이 없거나 호출되지 않는 함수의 실행 결과</li>
</ol>
</li>
</ul>
<p><strong>언제 undefined와 null을 사용할까?</strong></p>
<ul>
<li>직접 undefined를 할당하지 않고 자바스크립트 엔진이 반환하는 경우에만 할당</li>
<li>&#39;비어있음&#39;을 명시적으로 나타내고 싶을 때는 null 사용</li>
</ul>
<p>typeof null은 object로 어떤 변수의 값이 null인지의 여부를 판별하기 위해 typeof는 적절하지 않다.</p>
<pre><code class="language-js">var n = null;
console.log(typeof n);        // object

console.log(n == null)        // true
console.log(n === null)        // true

console.log(n == undefined) // true

console.log(n === undefined) // false</code></pre>
<p>null과 undefined를 비교하기 위해서는 동등 연산자(==)로 비교할 경우 true 값을 반환하기 때문에 일치 연산자(===)를 사용하여 판별해야한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SASS] 개요]]></title>
            <link>https://velog.io/@sypaik_dev/SASS-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@sypaik_dev/SASS-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Mon, 27 Mar 2023 12:11:56 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Sass에 대한 개요와 중첩에 대해 정리한 글입니다.</p>
</blockquote>
<h1 id="sass란">Sass란?</h1>
<p>CSS로 컴파일되는 스타일 시트 확장 언어로 CSS 전처리기의 하나이다. CSS가 동작하기 전에 사용하는 기능으로, 개발은 Sass를 기반으로 한 후, CSS로 컴파일한다.</p>
<p><strong>Sass, SCSS 쓰는 이유</strong>
작업이 고도화될수록 불필요한 선택의 과용, 연산 기능의 한계 등으로 유지관리가 어려워진다. 
➡️ Sass를 통해 네이스팅, 믹스인, 가져오기의 편의 기능을 사용하여 시간을 절약할 수 있다.
➡️ 코드 재사용이 가능하다.</p>
<p><strong>Sass, SCSS의 차이점</strong>
SCSS는 CSS 구문과 완전 호환이 가능하도록 Sass의 모든 기능을 지원하는 CSS의 상위집합이다.</p>
<p>SCSS는 <code>{}</code> (중괄호), <code>;</code>(세미콜론)을 사용하지만 Sass는 존재하지 않고 <strong>mixin</strong> 기능에서 SCSS는 <code>@mixin</code>과 <code>@include</code> 기능을 사용하지만 Sass는 <code>=</code>, <code>+</code> 기호를 사용한다.</p>
<h2 id="파일분리">파일분리</h2>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/92487ccf-b3d8-4f4c-a33f-b01b24f5b59e/image.png" alt=""></p>
<p>코드들을 편리하기 관리하기 위해 <code>_header.scss</code>, <code>_main.scss</code> 프레임 별로 CSS를 분리하고 <code>_variable.scss</code>, <code>_mixin.scss</code> 파일도 따로 분리한다. 그리고 <code>style.scss</code>로 분리했던 파일을 import한다. 
<img src="https://velog.velcdn.com/images/sypaik_dev/post/4f5eed0f-5c91-4427-8278-d750dd90e3a4/image.png" alt=""></p>
<p><strong>언더바_를 사용하는 이유</strong>
언더바(<em>)를 붙이지 않으면 분할된 파일들 모두 컴파일되기 때문에 언더바(</em>)를 붙여 header 파일임을 알려줘 내부에서 <code>@import</code> 형태로 동작하게 된다.</p>
<blockquote>
<p>💡 Sass에서 import할 때 확장명없이 파일명만 사용할 수 있다.</p>
</blockquote>
<p><strong>주석</strong>
CSS의 주석은 <code>/* 주석입니다 */</code>이었지만
Sass(SCSS)는 두 가지 스타일의 주석을 사용한다.</p>
<pre><code>// 컴파일되지 않는 주석
/* 컴파일되는 주석 */</code></pre><h1 id="중첩-nesting">중첩 (Nesting)</h1>
<p>상위 선택자 반복을 피하고 CSS코드를 구조화하여 가독성이 높아지고 유지보수가 편리하다.</p>
<pre><code>ul {
    border: 1px solid #ddd;
    li {
        background-color: pink;
        color: gray;
    }
}</code></pre><pre><code>ul {
  border: 1px solid #ddd;
}
ul li {
  background-color: pink;
  color: gray;
}</code></pre><h2 id="ampersand-상위-선택자-참조">Ampersand (상위 선택자 참조)</h2>
<p><code>&amp;</code>는 상위 부모선택자를 가리킨다.</p>
<ul>
<li><code>&amp;</code> 을 이용하여 after, hover 등의 가상요소, 가상 클래스를 참조할 수 있다.</li>
</ul>
<pre><code>.del-btn {
    color: red;
    &amp;:hover {
        background-color: red;
    }
}</code></pre><pre><code>.del-btn {
  color: red;
}
.del-btn:hover {
  background-color: red;
}</code></pre><ul>
<li><code>&amp;</code> 를 응용하여 같은 클래스명을 가진 선택자들을 중첩시킬 수 있다.</li>
</ul>
<pre><code>.box {
    &amp;-pink {
        background-color: pink;
    }
    &amp;-gray {
        background-color: gray;
    }
    &amp;-blue {
        background-color: blue;
    }
}</code></pre><pre><code>.box-pink {
  background-color: pink;
}
.box-gray {
  background-color: gray;
}
.box-blue {
  background-color: blue;
}</code></pre><h1 id="at-root">@at-root</h1>
<p>중첩에서 벗어나고 싶을 때 사용한다.
⚠️ 중첩 안에서 생성하지만 중첩에서 벗어난다.</p>
<pre><code>.box {
    width: 100px;
    height: 100px;
    @at-root span {
        color: pink;
    }
}</code></pre><pre><code>.box {
  width: 100px;
  height: 100px;
}
span {
  color: pink;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] for in vs for of 반복문]]></title>
            <link>https://velog.io/@sypaik_dev/JavaScript-for-in-vs-for-of-%EB%B0%98%EB%B3%B5%EB%AC%B8</link>
            <guid>https://velog.io/@sypaik_dev/JavaScript-for-in-vs-for-of-%EB%B0%98%EB%B3%B5%EB%AC%B8</guid>
            <pubDate>Fri, 17 Mar 2023 14:24:12 GMT</pubDate>
            <description><![CDATA[<h1 id="for--in">for ... in</h1>
<ul>
<li>객체의 <strong>열거</strong>할 수 있는 속성들을 순회하여 프로퍼티의 <strong>key</strong> 값에 접근한다.</li>
</ul>
<blockquote>
<p>열거 가능한 프로퍼티란?
열거 가능한 값이 true로 설정되어 있어 <strong>key</strong>만 반복할 수 있고 비열거형인 value에는 접근할 수 없다.</p>
</blockquote>
<pre><code>let arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
for (let i in arr) {
    console.log(i);
    }
// 0 1 2

var obj = { a: 1, b: 2, c: 3 }; 
for (var j in obj) { 
    console.log(j); 
} 
// a, b, c</code></pre><blockquote>
<p> for ... in 문에서는 순서에 따라 index를 반환하지 않을 수 있기 때문에 index 순서가 중요한 경우는 사용하지 않는 것이 좋다.
 ⚠️ length 연산자를 사용할 수 없다.</p>
</blockquote>
<h1 id="for--of">for ... of</h1>
<ul>
<li>Iterable한 객체 (Array, Map, Set, String, TypedArray, arguments ... )에 대해 속성값 value를 반복 순회한다.</li>
</ul>
<blockquote>
<p> 일반 객체는 iterable하지 않기 때문에 for of 사용시 TypeError가 발생한다!</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/a61c9864-57b9-4b61-8c0e-714fec742cf5/image.png" alt=""></p>
<p>일반 객체에서는 TypeError 발생!</p>
<pre><code>let obj = [&quot;sypaik&quot;, &quot;developer&quot;];
for (let value of obj) {
    console.log(value);
    }
// &#39;sypaik&#39;, &#39;developer&#39;</code></pre><p>이와 같이 배열에서는 for ... of 반복문을 사용하는 것이 좋다.</p>
<h1 id="for--in문-vs-for--of문">for ... in문 vs for ... of문</h1>
<p><strong>for ... in문</strong></p>
<ul>
<li>객체의 모든 열거 가능한 속성에 대해서 반복한다</li>
<li>Iterable object라면 모두 대상으로 할 수 있다 (배열 포함)</li>
<li><strong>key</strong>를 리턴한다 (배열의 경우, <strong>index</strong> 리턴)<blockquote>
<p>💡 for ... in문은 언제 사용하나?
키-값 쌍의 데이터의 경우 | 특정 값을 가진 key가 있는지 확인하려는 경우 | 객체에 key를 가져오는 작업이 필요한 경우</p>
</blockquote>
</li>
</ul>
<p><strong>for ... of문</strong></p>
<ul>
<li>Symbol.iterator 속성을 가지는 collection만 대상으로 한다.</li>
<li>Iterable object이지만, prototype chain에 의한 Iterable은 제외
(Array, Map, Set, String ...)</li>
<li><strong>value</strong>를 리턴한다</li>
</ul>
<p>따라서! for ... in은 객체(Object)의 key를 순회하고, for ... of는 객체의 value를 순회할 때 사용한다.</p>
<p><strong>Reference</strong>
<a href="https://joooing.tistory.com/entry/Iteration2-for-in%EB%AC%B8-for-of%EB%AC%B8">https://joooing.tistory.com/entry/Iteration2-for-in%EB%AC%B8-for-of%EB%AC%B8</a>
<a href="https://whoyoung90.tistory.com/24">https://whoyoung90.tistory.com/24</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] 선택자 심화]]></title>
            <link>https://velog.io/@sypaik_dev/CSS-%EC%84%A0%ED%83%9D%EC%9E%90-%EC%8B%AC%ED%99%94</link>
            <guid>https://velog.io/@sypaik_dev/CSS-%EC%84%A0%ED%83%9D%EC%9E%90-%EC%8B%AC%ED%99%94</guid>
            <pubDate>Fri, 17 Mar 2023 06:38:45 GMT</pubDate>
            <description><![CDATA[<h1 id="1-가상-클래스-선택자">1. 가상 클래스 선택자</h1>
<ul>
<li>Pseudo Selectors<h2 id="📌-first-child">📌 :first-child</h2>
</li>
<li>자식 요소 중 첫번째 자식 요소를 선택한다.<h2 id="📌-last-child">📌 :last-child</h2>
</li>
<li>자식 요소 중 마지막 자식 요소를 선택한다.<blockquote>
<p>⚠️ body의 직계 자손의 경우, <code>:first-child</code> 선택자가 적용되지만, <code>:last-child</code>는 적용되지 않는다.</p>
</blockquote>
</li>
</ul>
<h2 id="📌-nth-childn">📌 :nth-child(n)</h2>
<ul>
<li><p>자식 요소 중 n번째 자식 요소를 선택한다.</p>
<pre><code>li:nth-child(even) {
  color: pink;
}
li:nth-child(2n+1) {
  color: pink;
}</code></pre><h2 id="📌-nth-of-type">📌 :nth-of-type</h2>
</li>
<li><p>특정 자식 요소 중 n번째를 선택한다.</p>
<pre><code>  &lt;div class=&quot;container&quot;&gt;
    &lt;h1&gt;Hello world&lt;/h1&gt;
    &lt;span&gt;Hello world&lt;/span&gt;
    &lt;p&gt;Hello world&lt;/p&gt;
    &lt;span&gt;HTML&lt;/span&gt;
    &lt;p&gt;CSS&lt;/p&gt;
  &lt;/div&gt;

  &lt;style&gt;
    span:nth-of-type(2) {
      color: pink;
    }
  &lt;/style&gt;
</code></pre></li>
</ul>
<pre><code>![](https://velog.velcdn.com/images/sypaik_dev/post/b80ebc31-d40a-4b6e-9ccd-96e21c8f17a1/image.png)

&gt; ⚠️ nth-child 와 nth-of-type 다른점? ? ?
nth-child는 부모의 **모든** 자식 요소 중 n번째를 나타나는 반면 nth-of-type은 부모의 **특정** 자식 요소 중 n번째를 말한다.

## 📌 :only-of-type
* 자식 요소 중 같은 유형의 자식이 없을 때, 선택한다.</code></pre><pre><code>&lt;div class=&quot;container&quot;&gt;
  &lt;h1&gt;HTML&lt;/h1&gt;
  &lt;h2&gt;CSS&lt;/h2&gt;
  &lt;h3&gt;JavaScript&lt;/h3&gt;
&lt;/div&gt;


&lt;style&gt;
  h2:only-of-type {
    color: pink;
  }</code></pre><p>   </style></p>
<pre><code>## 📌 :not
* 특정 요소를 제외시킬 때, 사용한다.
</code></pre><pre><code>&lt;div class=&quot;container&quot;&gt;
  &lt;p&gt;HTML&lt;/p&gt;
  &lt;p&gt;CSS&lt;/p&gt;
  &lt;p&gt;JavaScript&lt;/p&gt;
&lt;/div&gt;

&lt;style&gt;
  p:not(:first-child) {
    color: pink;
  }
&lt;/style&gt;</code></pre><pre><code>![](https://velog.velcdn.com/images/sypaik_dev/post/e98a9d50-6ac7-4a32-996b-b1a435d1658c/image.png)

## 📌 :root
* 웹 문서에서 가장 상위 요소를 선택할 때, 사용한다.
* 보통 html에서 root는 html을 말하지만 스타일을 적용할 때 :root 가상 클래스의 우선 순위가 더 높다. 
* :root를 이용하여 **최상위** 요소에 변수를 선언하면 모든 요소에서 이 변수를 사용하여 조작하는 데 용이하다.

### :root 변수 선언</code></pre><pre><code> :root {
    --color-yellow: rgb(255, 255, 189);
    --font-size: 12px;
    --box-shadow: 1px 1px 1px #ddd;
  }</code></pre><pre><code>* 웹 문서에서 공통적으로 사용될 속성을 :root 변수에 선언한다. 
&gt;  **--** (하이픈 2개) **속성이름** : **속성값** ; 

### :root 변수 사용</code></pre><pre><code> .container {
    background-color: var(--color-yellow);
    box-shadow: var(--box-shadow);
  }

 span {
    font-size: var(--font-size);
  }</code></pre><pre><code>* 변수를 var로 선언하고 소괄호 안에 속성 값을 넣는다.

![](https://velog.velcdn.com/images/sypaik_dev/post/bbfe0acb-321c-4e70-9dcc-76d2b8ae28e5/image.png)

# 2. 가상 요소 (::)
* 선택자에 추가하는 키워드
* 선택한 요소에 특정한 스타일을 적용할 수 있다.
* 존재하지 않는 요소를 존재하는 것처럼 부여하여 스타일을 적용한다.

&gt; 선택자::가상요소 {속성: 속성값};


## 📌 ::before
* 선택한 요소 바로 앞에 생성되는 자식 요소
## 📌 ::after
* 선택한 요소 바로 뒤에 생성되는 자식 요소

**Content** 
* ::before, ::after와 같이 쓰이는 속성
* HTML 문서에 포함되지 않은 요소를 CSS에서 새롭게 생성시켜 장식용 콘텐츠를 추가할 때 사용한다.
* 빈태그 ```img```, ```br```, ```input```에는 적용할 수 없다.
</code></pre><pre><code>  &lt;ul&gt;
    &lt;li&gt;첫번째&lt;/li&gt;
    &lt;li&gt;두번째&lt;/li&gt;
    &lt;li&gt;세번째&lt;/li&gt;
  &lt;/ul&gt;

  &lt;style&gt;
  li::before {
    content: &quot;#&quot;;
  }

  li::after {
    content: &quot;!&quot;;
  }
&lt;/style&gt;</code></pre><pre><code>
![](https://velog.velcdn.com/images/sypaik_dev/post/390a35d1-c013-4769-a2d0-b55c9e2080de/image.png)
## 📌 ::placeholder
* input 요소나 textarea 요소의 placeholder의 가상 선택자로 선택하여 스타일을 적용할 수 있다.</code></pre><input type="text" placeholder="텍스트를 입력해주세요" />

<style>
   input::placeholder {
     color: pink;
   }
</style>
<p>```</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/70c0a3ac-0794-48f4-a533-47bcc224abe1/image.png" alt=""></p>
<h1 id="3-동적-가상-선택자-">3. 동적 가상 선택자 (:)</h1>
<h2 id="📌-active">📌 :active</h2>
<ul>
<li>클릭하면 활성화<blockquote>
<p>여기서 &quot;활성&quot;은 마우스 버튼을 <strong>누르는 순간</strong>부터 <strong>떼는 시점</strong>까지!</p>
</blockquote>
</li>
</ul>
<p>!codepen[sypaik-dev/embed/MWqNgKj?default-tab=html%2Cresult]</p>
<h2 id="📌-visited">📌 :visited</h2>
<ul>
<li>방문 후의 링크 상태</li>
<li>웹브라우저의 방문기록 정보를 사용</li>
</ul>
<h2 id="📌-disabled">📌 :disabled</h2>
<ul>
<li>비활성화된 상태</li>
</ul>
<h2 id="📌-hover">📌 :hover</h2>
<ul>
<li>커서를 요소에 올려두었을 때</li>
</ul>
<h2 id="📌-focus">📌 :focus</h2>
<ul>
<li>focus 받은 상태</li>
</ul>
<p>!codepen[sypaik-dev/embed/XWPvrmR?default-tab=html%2Cresult]</p>
<blockquote>
<p><code>a</code>, <code>button</code>, <code>input</code>가 포커스의 요소들이다. 
이는 모두 클릭, 입력 등 사용자와 상호작용이 있는 요소들</p>
</blockquote>
<h2 id="📌-checked">📌 :checked</h2>
<ul>
<li>input의 checkbox나 radio가 선택된 상태</li>
</ul>
<p><strong>Reference</strong></p>
<p><a href="https://designer-ej.tistory.com/entry/CSS-root-%EA%B0%80%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-CSS-%EB%B3%80%EC%88%98-%EB%8B%A4%EB%A3%A8%EA%B8%B0">:root 가상 클래스로 CSS 변수 다루기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] 선택자]]></title>
            <link>https://velog.io/@sypaik_dev/CSS-%EC%84%A0%ED%83%9D%EC%9E%90</link>
            <guid>https://velog.io/@sypaik_dev/CSS-%EC%84%A0%ED%83%9D%EC%9E%90</guid>
            <pubDate>Thu, 16 Mar 2023 09:01:04 GMT</pubDate>
            <description><![CDATA[<h1 id="1-선택자란">1. 선택자란?</h1>
<p>HTML 요소를 선택해 style을 정의하는 것을 말한다.
<img src="https://velog.velcdn.com/images/sypaik_dev/post/e089ab80-7b09-4532-890f-db9fd61f6160/image.png" alt=""></p>
<h1 id="1-기본선택자">1. 기본선택자</h1>
<h2 id="📌-전체-선택자-">📌 전체 선택자 (*)</h2>
<ul>
<li>Universal Selector</li>
<li>HTML 문서 내의 모든 요소를 선택한다. (<strong>head</strong> 요소도 포함)
```</li>
<li>{
margin: 0;
padding: 0;
}<pre><code></code></pre></li>
</ul>
<h2 id="📌-타입-선택자">📌 타입 선택자</h2>
<ul>
<li>Type Selector</li>
<li>특정 태그명을 가지는 요소를 선택한다.<pre><code>span {
color: #fff;
}
</code></pre></li>
</ul>
<pre><code>

## 📌 클래스 선택자 (.)
* Class Selector
* class attribute 값과 일치하는 요소를 선택한다.</code></pre><p>.container {
  padding: 20px;
}</p>
<pre><code>## 📌 아이디 선택자 (#)
* Id Selector</code></pre><p>#heading {
  background-color: pink;
}</p>
<pre><code>&gt; ⚠️ Class 선택자와 Id 선택자의 차이? ? ?
클래스는 **중복 사용**이 가능하여 한 페이지 내에 동일한 클래스명이 존재할 수 있지만,
아이디는 중복 사용이 불가능하고 1개의 아이디는 페이지에서 **1번만** 사용가능하다.
따라서! 여러 스타일을 적용할 때에는 클래스(class)를 사용하고, 한가지만 적용할 때에는 아이디(id)를 사용


# 2. 그룹 선택자
* 여러 선택자를 쉼표(,)로 구분하여 선택한다.</code></pre><p>h1,
p {
  margin: 0;
}</p>
<pre><code># 3. 복합 선택자

## 📌 자손 선택자 ( )
* 자식과 자손을 모두 선택할 수 있다.
* 공백을 사용하여 선택한다.</code></pre><pre><code>&lt;section&gt;
  &lt;h1&gt;Hello&lt;/h1&gt;
  &lt;h2&gt;Hello&lt;/h2&gt;
  &lt;p&gt;world&lt;/p&gt;
&lt;/section&gt;

&lt;style&gt;
  section p {
    color: pink;
  }
&lt;/style&gt;</code></pre><pre><code>
![](https://velog.velcdn.com/images/sypaik_dev/post/e291ae41-22d2-4abc-877d-49aed56345f7/image.png)

## 📌 자식 선택자 (&gt;)
* 바로 아래 자식의 요소를 선택한다.</code></pre><pre><code>&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;div&gt;
  &lt;p&gt;Hello World #1&lt;/p&gt;
  &lt;p&gt;Hello World #2&lt;/p&gt;
  &lt;span&gt;&lt;p&gt;Hello World #3&lt;/p&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Hello World #4&lt;/p&gt;

&lt;style&gt;
  div &gt; p {
    color: pink;
  }</code></pre><p>   </style></p>
<pre><code>
![](https://velog.velcdn.com/images/sypaik_dev/post/b8a78199-b62c-4373-8502-61fe37f83220/image.png)

&gt; ⚠️ 자식 선택자는 자손 선택자와 달리 **바로 하위**에 속하는 요소만 선택한다!
자손 선택자는 n 하위에 속하는 요소를 모두 선택할 수 있다는 점에 차이점을 가진다.

## 📌 일반 형제 선택자 (~)
* **뒤**에 있는 **모든 같은 요소**를 동시에 선택한다.</code></pre><pre><code>&lt;h1&gt;과일&lt;/h1&gt;
&lt;h2&gt;딸기&lt;/h2&gt;
&lt;h2&gt;복숭아&lt;/h2&gt;
&lt;h2&gt;귤&lt;/h2&gt;

&lt;style&gt;
  h1 ~ h2 {
    color: pink;
  }
&lt;/style&gt;</code></pre><pre><code>![](https://velog.velcdn.com/images/sypaik_dev/post/c8bdbe49-f684-4bda-9579-14e752a31938/image.png)

&gt; 💡 A ~ B
 A **뒤에 있는** 모든 B를 선택자로 지정한다.

## 📌 인접 형제 선택자 (+)
* **바로 뒤**에 있는 **요소 1개**를 선택한다.</code></pre><pre><code>&lt;h1&gt;과일&lt;/h1&gt;
&lt;h2&gt;딸기&lt;/h2&gt;
&lt;h2&gt;복숭아&lt;/h2&gt;
&lt;h2&gt;귤&lt;/h2&gt;

&lt;style&gt;
  h1 + h2 {
    color: pink;
  }
&lt;/style&gt;</code></pre><pre><code>![](https://velog.velcdn.com/images/sypaik_dev/post/a735e383-455d-4363-b898-2e1434fc70cc/image.png)

# 4. 속성 선택자
## 📌 [속성이름]
* 해당 속성을 가진 요소 모두 선택한다.</code></pre><pre><code>  [title] {
    color: red;
  }</code></pre><pre><code>
## 📌 [속성이름~=&quot;속성값&quot;] 선택자
* 해당 속성을 갖고, 그 값 중에 속성값이 포함되는 요소를 선택한다. (**공백** OK)</code></pre><pre><code>&lt;div class=&quot;btn&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;btn reset&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;reset btn&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;btn-negative&quot;&gt;선택안됨ㅠ&lt;/div&gt;

&lt;style&gt;
  [class~=&quot;btn&quot;] {
    background-color: pink;
  }
&lt;/style&gt;
  }</code></pre><pre><code>

## 📌 [속성이름|=&quot;속성값&quot;] 선택자
* 속성값만 포함하거나, 속성값으로 시작하고 **하이픈 -** 기호가 있는 요소 선택한다</code></pre><pre><code>&lt;div class=&quot;btn&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;btn reset&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;reset btn&quot;&gt;선택안됨ㅠ&lt;/div&gt;
&lt;div class=&quot;btn-negative&quot;&gt;선택됨!&lt;/div&gt;

&lt;style&gt;
  [class|=&quot;btn&quot;] {
    background-color: pink;
  }
&lt;/style&gt;
  }</code></pre><pre><code>
&gt; ⚠️ [속성이름~=&quot;속성값&quot;] 과 [속성이름|=&quot;속성값&quot;] 차이!
전자는 속성값이 하나 이상 포함하거나 속성값이 **공백**을 통해 분리되어 있어야한다. 후자는 속성값이 정확히 &quot;속성값&quot;으로 시작하거나 &quot;**속성값-**&quot;을 포함하는 요소들을 선택한다.



## 📌 [속성이름^=&quot;속성값&quot;] 선택자
* 속성값으로 **시작**하는 요소를 선택한다.</code></pre><pre><code>&lt;div class=&quot;btn&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;btn reset&quot;&gt;선택됨!&lt;/div&gt;
&lt;div class=&quot;reset btn&quot;&gt;선택안됨ㅠ&lt;/div&gt;
&lt;div class=&quot;btn-negative&quot;&gt;선택됨!&lt;/div&gt;

&lt;style&gt;
  [class^=&quot;btn&quot;] {
    background-color: pink;
  }
&lt;/style&gt;
  }</code></pre><pre><code>

## 📌 [속성이름$=&quot;속성값&quot;] 선택자
* 속성값으로 **끝나는** 요소 선택한다.</code></pre><pre><code>&lt;div class=&quot;btn negative&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;btn-negative&quot;&gt;&lt;/div&gt;

 &lt;style&gt;
 [class$=&quot;negative&quot;] {
   background-color: pink;
 }
&lt;/style&gt;</code></pre><pre><code>

## 📌 [속성이름*=&quot;속성값&quot;] 선택자

* 속성값을 포함하는 요소를 **모두** 선택한다.</code></pre><pre><code>&lt;div class=&quot;btn a&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;btnna&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;a-btn&quot;&gt;&lt;/div&gt;

&lt;style&gt;
 [class*=&quot;btn&quot;] {
    background-color: pink;
  }
&lt;/style&gt;</code></pre><pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] Flex]]></title>
            <link>https://velog.io/@sypaik_dev/CSS-Flex</link>
            <guid>https://velog.io/@sypaik_dev/CSS-Flex</guid>
            <pubDate>Sun, 12 Mar 2023 10:13:55 GMT</pubDate>
            <description><![CDATA[<p>CSS Flex에 대한 내용을 정리한 글입니다.</p>
<h1 id="1-flexbox란">1. flexbox란?</h1>
<p>flexbox는 요소를 효율적으로 배치, 정렬할 수 있는 CSS3의 새로운 레이아웃 방식이다.
정렬, 방향, 순서, 크기를 유연하게 조절할 수 있다.
Flexbox 속성을 잘 이용하면 미디어쿼리 없이 다양한 디바이스에 반응하는 반응형 레이아웃을 만들 수 있다.</p>
<h1 id="2-flexbox의-부모요소-속성">2. flexbox의 부모요소 속성</h1>
<h2 id="📌-display-flex">📌 display: flex;</h2>
<ul>
<li>1차원적 레이아웃 -  주 축 (main-axis)과 교차 축(cross-axis)</li>
<li>부모 요소 : flex-container</li>
<li>자식 요소 : flex-item</li>
</ul>
<h2 id="📌-flex-direction">📌 flex-direction</h2>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/499b1afd-de42-4c4e-8f69-ed88a6ca6ee9/image.png" alt="">
<code>flex-direction : row</code>를 기준으로 flex-item의 정렬
<code>flex-basis</code>는 row를 기준으로 width 값으로 설정</p>
<p>• <code>flex-direction : row;</code> <strong>(default)</strong> : flex-items을 왼쪽에서 오른쪽 정렬
• <code>flex-direction : row-reverse;</code> : flex-items을 오른쪽에서 왼쪽 정렬
<img src="https://velog.velcdn.com/images/sypaik_dev/post/6e72f34c-df29-458d-b436-a0583898770f/image.png" alt=""></p>
<p><code>flex-direction : column</code>를 기준으로 flex-item의 정렬
<code>flex-basis</code>는 column을 기준으로 height 값으로 설정</p>
<p>• <code>flex-direction : column;</code>  : flex-items을 위에서 아래로 정렬
• <code>flex-direction : column-reverse;</code> : flex-items을 아래에서 위로 정렬</p>
<blockquote>
<ul>
<li>row / row-reverse는 Items를 수평축으로 표시
→ 주축(main-axis)은 수평, 교차 축(cross-axis)은 수직</li>
</ul>
</blockquote>
<ul>
<li>column / column-reverse는 Items를 수직축으로 표시 
→ 주축(main-axis)은 수직, 교차 축(cross-axis)은 수평</li>
</ul>
<h2 id="📌-justify-content">📌 justify-content</h2>
<p>주 축(main-axis)을 중심으로 Items의 정렬 방법을 설정
• <code>justify-content : flex-start;</code> <strong>(default)</strong> : Items을 시작점(flex-start)으로 정렬
• <code>justify-content : flex-end;</code> : Items을 끝점(flex-end)으로 정렬
• <code>justify-content : center;</code> : Items을 가운데 정렬
• <code>justify-content : space-around;</code> : Items 주위(around)에 균등한 여백을 포함하여 정렬
• <code>justify-content : space-between;</code> : Items의 시작은 시작점에, 끝은 끝점에 두고 Items 사이 사이에 균등한 여백으로 정렬
• <code>justify-content : space-evenly;</code> : Items 양끝과 사이 모두 균등한 여백으로 정렬</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/56a1f61f-1018-4df4-a917-53f4d8f04146/image.png" alt=""></p>
<blockquote>
<p>⚠️ space-around와 space-bewteen의 차이?
<code>space-around</code>에서 around는 주위의 라는 뜻으로 아이템 양 측면에 각각 half-size space와 아이템들 사이에는 half-size space의 2배를 주어 정렬한다.
<code>space-between</code>은 시작지점과 끝지점에 item을 배치하고 items의 사이사이 균등한 공간의 space를 준다.</p>
</blockquote>
<h2 id="📌-align-items-align-content">📌 align-items, align-content</h2>
<p>교차 축(cross-axis)을 중심으로 Items의 정렬 방법을 설정</p>
<blockquote>
<p>align-items과 align-content의 원리는 동일하지만
align-items는 한 줄을 기준으로 정렬하고, align-content는 두 줄부터 정렬할 때 사용
그래서 align-content는 <code>flex-wrap: wrap;</code>인 상태에서 사용한다
(flex-wrap은 뒤에서 더 설명하겠습니다..)</p>
</blockquote>
<p>align-items과 align-content의 원리는 동일하기 때문에 align-items을 기준으로 정렬방법을 살펴보겠습니다.</p>
<p>• <code>align-items: stretch;</code> <strong>(default)</strong> : Container의 교차 축을 중심으로 Items을 늘림
• <code>align-items: flex-start;</code> : 교차 축을 중심으로 Items을 시작점으로 정렬
• <code>align-items: flex-end;</code> : Items을 끝점으로 정렬
• <code>align-items: center;</code> : Items을 가운데 정렬
• <code>align-items: space-around;</code> : Items 주위(around)에 균등한 여백을 포함하여 정렬
• <code>align-items : space-between;</code> : Items의 시작은 시작점에, 끝은 끝점에 두고 Items 사이 사이에 균등한 여백으로 정렬
• <code>align-items : space-evenly;</code> : Items 양끝과 사이 모두 균등한 여백으로 정렬</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/6113d937-66b5-4de8-a006-ee73fc5f3b2c/image.png" alt=""></p>
<blockquote>
<ul>
<li><code>align-items: stretch</code>
Items의 높이가 container의 높이와 같게 변경하여 배치</li>
</ul>
</blockquote>
<h2 id="📌-flex-wrap">📌 flex-wrap</h2>
<p>Items을 여러 행에 나누어 정렬하는 방법
→ Container보다 Items의 합이 더 클 때!
• <code>flex-wrap: nowrap;</code> <strong>(default)</strong> : Items을 한 줄로 표시
• <code>flex-wrap: wrap;</code> : Items을 여러 줄로 표시</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/fba1ffd2-d025-4e91-ae4e-1a7b72f059c9/image.png" alt=""></p>
<ul>
<li><code>flex-wrap: wrap;</code>
Items을 두 줄 이상의 행으로 정렬</li>
</ul>
<h2 id="📌-flex-flow">📌 flex-flow</h2>
<p>flex-direction와 flex-wrap 의 단축 속성
• <code>flex-flow: flex-direction  |  flex-wrap;</code>
• <code>flex-flow: row  nowrap;</code> <strong>(default)</strong></p>
<h2 id="📌-gap">📌 gap</h2>
<p>Items 사이에 일정한 간격을 줌</p>
<h1 id="3-flexbox의-자식요소-속성">3. flexbox의 자식요소 속성</h1>
<h2 id="📌-flex-basis">📌 flex-basis</h2>
<p>Items의 초기 크기 설정
• <code>flex-basis: auto;</code> <strong>(default)</strong> : Items 자신의 width, height 속성값을 사용
• <code>flex-basis: ~px / em;</code> : Items의 단위로 지정 (px / em)
• <code>flex-basis: 0;</code> : Item의 기본 크기를 0으로 설정</p>
<p> <img src="https://velog.velcdn.com/images/sypaik_dev/post/d921f9c3-c605-4aa6-a0ba-1f3a44d90d44/image.png" alt=""></p>
<blockquote>
<ul>
<li><code>flex-basis: auto</code> 의 경우, Item의 기본 크기가 자신의 width, height 값으로 설정되어 content 크기에 따라 Item의 크기가 각각 다르다.</li>
</ul>
</blockquote>
<ul>
<li><code>flex-basis: 0</code> 경우, Item의 기본 크기를 0으로 설정하여 content 크기와 상관없이 flex-grow, flew-shrink 설정 비율에 따라 Item의 크기를 배분한다.
➡️ 왜냐하면, flex-grow는 Item의 flex-basis를 제외한 여백 부분을 비율에 따라 설정하는데 <code>flex-basis : 0</code> 이라면 Item의 기본 크기가 0으로 여백이 100%로 content의 크기와 상관없이 flex-grow 비율대로 Item의 크기를 배분한다. </li>
<li>Item의 width 값이 설정되어 있는 상태에서 flex-basis 값을 주면 width값이 아닌 flex-basis 값이 적용된다!</li>
</ul>
<h2 id="📌-flex-grow">📌 flex-grow</h2>
<p>Item의 증가 너비 비율</p>
<ul>
<li><code>flex-grow: 0</code> <strong>(default)</strong> : 너비가 증가하지 않음</li>
<li><code>flex-grow: 증가 너비</code></li>
</ul>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/07a13065-92c0-44f2-a0db-0476fa9133cb/image.png" alt=""></p>
<h2 id="📌-flex-shrink">📌 flex-shrink</h2>
<p>Item의 감소 너비 비율</p>
<ul>
<li><code>flex-shrink: 1</code> <strong>(default)</strong> : 따로 감소 너비를 설정하지 않을 경우, Item이 flex-basis 보다 작아질 수 있음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/eeb4debf-d814-4a74-87a1-08b6e23953d9/image.png" alt=""></p>
<blockquote>
<p>단, <code>flex-wrap</code>과 <code>flex-shrink</code>은 같이 사용할 수 없다!</p>
</blockquote>
<h2 id="📌-flex">📌 flex</h2>
<p>flex-grow, flex-shrink, flex-basis의 단축 속성</p>
<ul>
<li><code>flex: flew-grow | flew-shrink | flex-basis</code></li>
</ul>
<h2 id="📌-align-self">📌 align-self</h2>
<p>교차 축(cross-axis)을 중심으로 Item의 정렬 방법 + <strong>개별적인</strong> align-item 속성을 주고 싶을 때</p>
<ul>
<li><code>align-self: auto</code> <strong>(default)</strong> : align-items 설정에 상속받음</li>
<li><code>align-self: flex-start | flex-end | center | space - ...</code> : 개별적 align-item 속성 설정</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/438792ed-f3c4-498a-81ee-071023aaa856/image.png" alt=""></p>
<blockquote>
<pre><code>.flex-item:nth-child(4) {
        align-self: center;
      }
.flex-item:nth-child(7) {
        align-self: flex-end;
      } </code></pre></blockquote>
<pre><code>  * 개별적인 Item에 align-items 속성을 줄 수 있음


## 📌 order
Item의 배치 순서
* 수가 **작을수록** 먼저 배치된다

![](https://velog.velcdn.com/images/sypaik_dev/post/311492aa-eb70-405a-84b1-932012c514b7/image.png)
</code></pre><p>.flex-item:nth-child(3) {
        order: -1;
        flex-grow: 1;
 }</p>
<pre><code>

Reference
https://heropy.blog/2018/11/24/css-flexible-box/
https://studiomeal.com/archives/197
https://d2.naver.com/helloworld/8540176</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[HTML | CSS] 개요]]></title>
            <link>https://velog.io/@sypaik_dev/HTML-CSS-%EA%B0%9C%EC%9A%94</link>
            <guid>https://velog.io/@sypaik_dev/HTML-CSS-%EA%B0%9C%EC%9A%94</guid>
            <pubDate>Sat, 04 Mar 2023 14:57:50 GMT</pubDate>
            <description><![CDATA[<p>멋쟁이사자처럼 FE5 첫 수업을 듣고 정리한 글입니다.</p>
<h2 id="1-html-css-javascript">1. HTML, CSS, JavaScript</h2>
<p><strong>HTML</strong>
• HyperText Markup Language
• 마크업 언어로 태그 등을 이용하여 문서나 데이터의 구조를 표시하는 언어
• 웹 콘텐츠의 의미와 구조를 정의 (프로그래밍 언어 X)</p>
<p><strong>CSS</strong>
• Cascading Style Sheets
• 웹의 시각적인 표현</p>
<p><strong>JavaScript</strong>
• 웹 페이지의 기능, 동작</p>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/f3ac0dba-45c5-47a1-b1a1-ecf7133c12d4/image.png" alt="">
[출처: <a href="https://html-css-js.com/%5D">https://html-css-js.com/]</a></p>
<h2 id="2-html-요소">2. HTML 요소</h2>
<p>HTML은 요소(Elements)로 구성되어있다.</p>
<p><strong>태그 (Tag)</strong>
• 열리고 &lt; &gt; 닫히는 &lt;/&gt; 태그 구조
<img src="https://velog.velcdn.com/images/sypaik_dev/post/382d6b68-6eb3-4a84-86ee-0380112b3378/image.png" alt="">
: p 태그로 class 속성명(attribute)와 web-tech라는 속성값으로 이루어진다.</p>
<p><strong>빈요소 / 셀프 크로징 (self-closing)</strong></p>
<p><code>&lt;br /&gt;</code>
<code>&lt;input type=&quot;text&quot; /&gt;</code>
<code>&lt;img src = &quot;&quot; alt = &quot;&quot; /&gt;</code></p>
<p>➡️ 현재는 닫지 않아도 상관없음</p>
<blockquote>
<ul>
<li>마크업 검사 (Markup Validation Service)</li>
</ul>
</blockquote>
<ul>
<li><a href="https://validator.w3.org/">https://validator.w3.org/</a></li>
<li>HTML의 경우, 오류를 알려주지 않고 임의로 결과를 보여주기 때문에 이를 방지하기 위해 사용</li>
</ul>
<h2 id="3-html-문서-구조">3. HTML 문서 구조</h2>
<p> <strong>📌 !DOCTYPE html</strong>
• HTML Living Standard 문서
• 작성 시 완전 표준 모드로 렌더링
• DTD (Document Type Definition)라고 부르고 문서 타입에 대한 정보를 제공
 ⚠️ 다른 DOCTYPE 사용 시, 표준 모드나 호환 모드로 렌더링될 위험이 있음</p>
<p> ** 📌 html**
• HTML 문서의 루트, 최상단 요소
• lang 속성을 통해 주언어를 설정할 수 있음</p>
<blockquote>
<p>주 언어 설정은 검색엔진, 스크린리더, 번역 기능에 영향을 미친다.
특히! 스크린리더가 음성 표현에 사용할 언어를 선택할 때
⚠️ &quot;en&quot; 설정 시, 번역하시겠습니까? 창 뜨니 주의해야한다.</p>
</blockquote>
<p>• 언어코드 (소문자) - 국가코드(대문자)</p>
<pre><code>&lt;html lang=&quot;ko-KR&quot;&gt;</code></pre><p> <strong>📌head</strong>
• HTML 문서의 정보를 설정</p>
<p>** meta**
  • 메타데이터 : 어떤 목적을 위해 만들어진 데이터</p>
<ul>
<li><p>charset</p>
<pre><code>&lt;meta charset=&quot;UTF-8&quot;&gt;</code></pre><p>  문자인코딩 방식으로 국제적인 코드 규약</p>
<ul>
<li><p>http-equiv</p>
<pre><code>&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</code></pre><p> 브라우저 호환성을 위해 작성</p>
</li>
<li><p>name, content</p>
<pre><code>&lt;meta name=&quot;description&quot; content=&quot;Google 지도에서 지역정보를 검색하고 지도를 살펴보거나 운전경로 정보를 검색합니다.&quot;&gt;</code></pre><p>name은 메타데이터의 이름, content는 실제 메타데이터의 요소</p>
</li>
<li><p>viewport</p>
<pre><code>&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;</code></pre></li>
</ul>
<p><strong>title</strong>
• 웹페이지 탭에 보이는 문서 제목 정의</p>
<p><strong>link</strong>
• 현재 문서와 외부 리소스의 관계
• head 요소 내부에만 위치</p>
<pre><code>&lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;</code></pre><p>rel : relations, 현재 문서와 외부 리소스와의 관계
href : hyper-references, 파일의 위치</p>
</li>
</ul>
<p><strong>📌 body</strong>
사용자에게 보이는 영역으로 HTML 문서의 구조 설정</p>
<h2 id="4-css">4. CSS</h2>
<p>• Cascading Style Sheets
• CSS 스타일 적용 시, 우선순위를 가지고 적용하기에 적용되는 과정이 마치 폭포와 같음 (cascade: 폭포)
• 색상, 크기, 폰트, 레이아웃 등을 지정하여 콘텐츠의 구조를 꾸며줌 (웹의 시각적인 표현)</p>
<ul>
<li>작성방법</li>
</ul>
<p><img src="https://velog.velcdn.com/images/sypaik_dev/post/7ed38414-91cb-4272-88db-8e6d9fd5468e/image.png" alt=""></p>
<p>header라는 태그 선택자 안에 color 속성과 royalblue 속성값이 있음</p>
<h2 id="5-css-적용-방법">5. CSS 적용 방법</h2>
<p><strong>📌 인라인 방법</strong></p>
<pre><code>&lt;p style =&quot;color: pink, background-color: gray&quot;&gt;Hello World&lt;/p&gt;</code></pre><p>HTML 태그 자체에 직접 작성하기 때문에 선택자는 필요 X</p>
<p><strong>📌 내부 스타일</strong></p>
<pre><code>&lt;head&gt;
    &lt;style&gt;
    p {
        font-weight: 600
    }
    &lt;/style&gt;
&lt;/head&gt;</code></pre><p>CSS만 따로 작성하기 때문에 선택자가 필요함</p>
<p><strong>📌 외부 스타일</strong></p>
<p> <code>&lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;</code></p>
<p> • <code>&lt;head&gt;</code> 요소 내부에 위치
• HTML, CSS 파일을 분리하기 때문에 가독성과 효율성을 높인다 (권장!)</p>
<p><strong>📌 import</strong></p>
<pre><code>&lt;!-- index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ko-KR&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
    &lt;title&gt;import 적용&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><pre><code>/* style.css */
@import url(&quot;main.css&quot;);
@import url(&quot;font.css&quot;);</code></pre><p>• <code>@import</code> 는 문서 최상단에 위치
• import로 가져오는 CSS 파일은 순차적으로 불러오는 직렬 로딩이기 때문에 CSS 파일이 많아지면 렌더링 프로세스가 지연될 수 있음</p>
<h2 id="6-단위">6. 단위</h2>
<p>• 절대 길이 단위 px
• 상대 길이 단위 %, vw, vh, vmin, vmax, em, rem</p>
<p><strong>px (Pixel, Picture + Element)</strong>
• 고정된 값</p>
<blockquote>
<p>절대 단위인 px은 사용 시 디바이스 별로 크기나 위치가 다르게 보일 수 있는 문제가 있다.</p>
</blockquote>
<p>** %**
• 부모 요소를 기준으로 한 백분율 단위</p>
<p>** vm, vh**
• viewport의 넓이와 높이를 기준으로 한 백분율 단위</p>
<p><strong>vmin, vmax</strong>
• viewport의 넓이, 높이 중 작은 값과 큰 값을 기준으로 한 백분율 단위</p>
<p>** em**
• 부모 요소로부터 상속 받은 요소의 크기를 기준으로 한 배수 단위</p>
<p>** rem**
• root em
• 최상위 요소인 <code>&lt;html&gt;</code>의 기본 글자 폰트 16px을 기준으로 한 배수 단위</p>
<blockquote>
<ul>
<li>em ? rem?
전체적인 폰트 사이즈를 조절하기 위해서는 rem을 기본으로 사용하고, em은 특정 폰트 크기에 따라 조절이 필요할 때 사용
⚠️절대 길이 단위인 px보다 rem, em이 유지 보수에 용이하기 때문에 사용하기를 권장</li>
</ul>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>