<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sangmin0310-afk.log</title>
        <link>https://velog.io/</link>
        <description>프린이</description>
        <lastBuildDate>Thu, 02 Jan 2025 12:00:05 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sangmin0310-afk.log</title>
            <url>https://velog.velcdn.com/images/sangmin0310-afk/profile/27a0a89e-57bd-4c9c-9bbd-c6fe2a6e1449/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sangmin0310-afk.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sangmin0310-afk" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[this (챕터 1)]]></title>
            <link>https://velog.io/@sangmin0310-afk/this-%EC%B1%95%ED%84%B0-1</link>
            <guid>https://velog.io/@sangmin0310-afk/this-%EC%B1%95%ED%84%B0-1</guid>
            <pubDate>Thu, 02 Jan 2025 12:00:05 GMT</pubDate>
            <description><![CDATA[<h1 id="상황에-따라-달라지는-this">상황에 따라 달라지는 this</h1>
<p>자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정됩니다.</p>
<blockquote>
<p>이것을 쉽게 말하자면 this는 함수를 호출할 때 결정된다고 할 수 있습니다.</p>
</blockquote>
<h3 id="전역-공간에서-this">전역 공간에서 this</h3>
<pre><code>전역 공간에서의 this
console.log(this);
console.log(window);
console.log(this===window); // true </code></pre><p>JavaScript에서 다음 코드가 실행될 때 this === window가 true로 나올까요?</p>
<p>브라우저 환경에서 스크립트가 전역 컨텍스트에서 실행될 때, this는 전역 객체를 참조합니다.
브라우저에서는 전역 객체가 <code>window</code>입니다.</p>
<p>따라서, 전역 스코프에서 this는 자동으로 <code>window</code>와 동일합니다.</p>
<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/85a3401c-096e-41a1-957c-80906ca10c22/image.jpg" alt=""></p>
<pre><code>전역변수와 전역객체(1)
var a = 1;
console.log(a); //1
console.log(window.a); //1
console.log(this.a); //1</code></pre><p>var로 선언한 변수의 특징
전역 컨텍스트에서 var로 선언된 변수는 기본적으로 전역 객체(<code>window</code>)의 프로퍼티로 추가됩니다.</p>
<blockquote>
<p>var a = 1;은 <strong>window.a = 1;</strong>과 동일한 효과를 가집니다.</p>
</blockquote>
<p><strong>console.log(a);</strong>
자바스크립트는 변수를 검색할 때 <strong>스코프 체인(scope chain)</strong> 을 사용합니다.
a는 전역 컨텍스트에서 선언되었으므로 a의 값은 1입니다.</p>
<p><strong>console.log(window.a);</strong>
전역 컨텍스트에서 선언된 변수 a는 전역 객체인 <code>window</code>의 프로퍼티로 저장됩니다.
따라서 <code>window.a</code>는 1을 출력하게 됩니다.</p>
<p><strong>console.log(this.a);</strong>
전역 컨텍스트에서 this는 <strong>전역 객체(window)</strong>를 참조합니다.
따라서 <code>this.a</code>는 <code>window.a</code>와 동일하며 1을 출력합니다.</p>
<pre><code>전역변수와 전역객체(2)
var a = 1;
window.b = 2;
console.log(a, window.a, this.a); //111
console.log(b, window.b, this.b); //222

window.a = 3;
b = 4;
console.log(a, window.a, this.a); //333
console.log(b, window.b, this.b); //444</code></pre><p><strong>var a = 1;</strong>
전역 컨텍스트에서 var로 선언된 변수는 전역 객체(window)의 프로퍼티로 등록됩니다. window.a도 1로 설정됩니다.</p>
<p><strong>window.b = 2;</strong>
b가 명시적으로 window 객체의 프로퍼티로 추가됩니다.
이는 전역 변수 b와 동일하게 작동합니다.</p>
<p>a는 var로 선언되었기 때문에 a와 window.a는 동일합니다.</p>
<p>this.a도 전역 컨텍스트에서 this가 window를 참조하므로 동일하게 1입니다.
b는 window.b = 2;로 명시적으로 설정되었으므로 b, window.b, this.b는 모두 2입니다.</p>
<p><strong>window.a = 3;</strong>
전역 객체의 프로퍼티 a를 3으로 덮어씁니다.
이는 var a로 선언된 변수 a에도 영향을 미칩니다(같은 메모리 위치를 참조).</p>
<p><strong>b = 4;</strong>
b는 이미 window.b로 존재하는 상태였으므로 b = 4;는 단순히 window.b의 값을 업데이트합니다.</p>
<p>a는 window.a = 3;에 의해 값이 3으로 변경되었습니다.
따라서 a, window.a, this.a는 모두 3입니다.</p>
<p>b는 b = 4;에 의해 값이 4로 업데이트되었습니다.
따라서 b, window.b, this.b는 모두 4입니다.</p>
<h4 id="전역변수-선언과-전역객체의-프로퍼티-할당-사이에-전혀-다른경우">전역변수 선언과 전역객체의 프로퍼티 할당 사이에 전혀 다른경우</h4>
<pre><code>var a = 1;
delete window.a; //false
console.log(a, window.a, this.a); //111</code></pre><p><strong>var a = 1;</strong>
전역 컨텍스트에서 var로 선언된 변수 a는 전역 객체(window)의 프로퍼티로 추가됩니다.
window.a = 1과 동일하게 작동합니다.</p>
<p><strong>delete window.a;</strong>
delete 연산자는 객체의 프로퍼티를 삭제할 수 있는 연산자입니다.
하지만 var로 선언된 전역 변수는 <strong>configurable 속성이 false</strong> 로 설정되기 때문에 삭제할 수 없습니다.</p>
<p><strong>이유:</strong>
var로 선언된 변수는 전역 객체의 비설정 가능(non-configurable) 속성이 됩니다.
이 때문에 delete 연산자는 false를 반환하며 실제로 a가 삭제되지 않습니다.
window.a는 여전히 존재하며 값은 1로 유지됩니다.</p>
<p>console.log(a, window.a, this.a);
a: 전역 변수 a의 값은 여전히 1입니다.
window.a: delete 연산자가 실패했기 때문에 window.a의 값도 1입니다.
this.a: 전역 컨텍스트에서 this는 window를 참조하므로 this.a는 window.a와 동일하며 값이 1입니다.</p>
<pre><code>window.c = 3;
delete window.c; //true
console.log(c, window.c, this.c); // Uncaught ReferenceError: c is not defined</code></pre><p>delete window.c;
delete 연산자는 객체의 프로퍼티를 삭제합니다.
window.c는 명시적으로 추가된 설정 가능(configurable) 속성이므로 삭제가 가능합니다.
delete window.c;는 true를 반환하고, window.c가 삭제됩니다.</p>
<p>console.log(c, window.c, this.c);
<strong>c</strong>
window.c가 삭제되었기 때문에 더 이상 전역 객체의 프로퍼티로 존재하지 않습니다.
c는 정의되지 않은 변수로 간주되어 ReferenceError가 발생합니다.</p>
<p><strong>window.c</strong>
window.c도 삭제되었으므로, 해당 프로퍼티는 존재하지 않습니다.
undefined로 평가되지만 코드가 ReferenceError에서 멈추기 때문에 출력되지 않습니다.</p>
<p><strong>this.c</strong>
전역 컨텍스트에서 this는 window를 참조합니다.
window.c가 삭제되었으므로 this.c도 undefined입니다.
마찬가지로 코드가 ReferenceError에서 멈추기 때문에 출력되지 않습니다.</p>
<h3 id="메서드로서-호출할-때-그-메서드-내부에서의-this">메서드로서 호출할 때 그 메서드 내부에서의 this</h3>
<p>어떤 함수를 실행하는 방법은 여러 가지가 있는데, 가장 일반적인 방법 두 가지는 
함수로서  호출하는 경우와 메서드로서 호출하는 경우입니다.</p>
<p>프로그래밍 언어에서 함수와 메서드는 미리 정의한 동작을 수행하는 코드 뭉치로
이 둘을 구분하는 유일한 차이는 <code>독립성</code>에 있습니다.</p>
<p>흔히 메서드를 &#39;객체의 프로퍼티에 할당된 함수&#39;로 이해하곤 합니다. 
어떤 함수를 객체의 프로퍼티에 할당한다고 해서 그 자체로서 무조건 메서드가 된는 것이 
아니라 객체의 메서드로서 호출할 경우에만 메서드로 동작하고 그렇지 않으면 함수로 동작합니다.</p>
<pre><code>함수로서 호출, 메서드로서 호출
var func = function(x) {
    console.log(this, x);
};
func(1);  //window{...}1

var obj = {
    method: func
};
obj.method(2);  //{method: f} 2</code></pre><p>함수 func가 호출되었을 때 아무 객체도 명시적으로 함수 호출에 연결되지 않았습니다.
기본적으로 전역 컨텍스트에서 함수가 호출될 경우 this는 전역 객체(window)를 참조합니다.
브라우저 환경에서는 전역 객체가 window입니다.</p>
<p>this는 window, 매개변수 x는 1로 설정됩니다.</p>
<p>func가 객체 obj의 프로퍼티 method로 할당되었습니다.
obj.method는 func를 참조합니다.</p>
<p>obj.method(2)를 호출하면 this는 호출하는 객체(obj)를 참조합니다.
자바스크립트의 메서드 호출 규칙에 따르고 매개변수 x는 2로 전달됩니다.</p>
<p><strong>요약</strong>
독립적으로 호출된 함수(func(1))
this는 기본적으로 전역 객체(window)를 참조합니다.
결과: window {...} 1</p>
<p>객체의 메서드로 호출된 함수(obj.method(2))
this는 호출한 객체(obj)를 참조합니다.
결과: { method: f } 2</p>
<pre><code>메서드로서 호출 - 점 표기법, 대괄호 표기법
var obj = {
    method: function(x) {console.log(this, x); }
};
obj.method(1); //{method:f} 1
obj[&#39;method&#39;](2); //{method:f} 2</code></pre><p>obj 객체의 method 프로퍼티는 함수입니다.
obj.method(1)을 호출하면 자바스크립트의 메서드 호출 규칙에 따라 this는 호출한 객체 obj를 참조합니다.
매개변수 x는 1로 전달됩니다.</p>
<p>배열 표기법([])은 점 표기법(.)과 동일한 결과를 가져오고 함수 참조를 가져옵니다.
obj 를 호출하면 자바스크립트의 메서드 호출is는 호출한 객체 obj를 참조합니다.
매개변수 x는 2로 전달됩니다.</p>
<h4 id="메서드-내부에서의-this">메서드 내부에서의 this</h4>
<p>this에는 호출한 주체에 대한 정보가 담깁니다. 어떤 함수를 메서드로서 호출하는 경우 
호출 주체는 바로 함수명(프로퍼티명)앞의 객체입니다. </p>
<p>점 표기법의 경우 마지막 점 앞에 명시된 객체가 곧 this가 되는 것입니다.</p>
<pre><code>var obj = {
    methodA: function () { console.log(this);},
    inner: {
        methodB: function () { console.log(this);}
    }
};
obj.methodA(); //{methodA: f, inner: {...}} (===obj)
obj[&#39;methodA&#39;](); //{methodA: f, inner: {...}} (===obj)

obj.inner.methodB(); // {methodB: f} (===obj.inner)
obj.inner[&#39;methodB&#39;](); // {methodB: f} (===obj.inner)
obj[&#39;inner&#39;].methodB(); // {methodB: f} (===obj.inner)
obj[&#39;inner&#39;][&#39;methodB&#39;](); // {methodB: f} (===obj.inner)</code></pre><p><strong>obj.methodA()</strong>
methodA가 호출될 때 자바스크립트의 메서드 호출 규칙에 따라 <strong>this는 methodA를 호출한 객체인 obj</strong>를 참조합니다.</p>
<p><strong>obj<a href="">&#39;methodA&#39;</a></strong>
점 표기법(.)과 배열 표기법([])은 속성 접근 방식만 다를 뿐 동작은 동일합니다.
obj<a href="">&#39;methodA&#39;</a>는 obj.methodA()와 동일한 메서드 호출이므로 <strong>this는 obj</strong>를 참조합니다.</p>
<p><strong>obj.inner.methodB()</strong>
methodB가 inner 객체의 메서드로 호출되었습니다.
자바스크립트의 메서드 호출 규칙에 따라 <strong>this는 methodB를 호출한 객체인 obj.inner</strong>를 참조합니다.</p>
<p><strong>obj.inner<a href="">&#39;methodB&#39;</a></strong>
배열 표기법으로 methodB를 호출했지만 동작은 점 표기법과 동일합니다.
<strong>this는 obj.inner</strong>를 참조합니다.</p>
<p><strong>obj[&#39;inner&#39;].methodB()</strong>
배열 표기법으로 inner 객체를 참조한 뒤 점 표기법으로 methodB를 호출합니다.
호출 방식은 이전과 동일하며 <strong>this는 obj.inner</strong>를 참조합니다.</p>
<p><strong>obj[&#39;inner&#39;]<a href="">&#39;methodB&#39;</a></strong>
배열 표기법만 사용했을 뿐 호출 방식은 여전히 동일합니다.
<strong>this는 obj.inner</strong>를 참조합니다.</p>
<h3 id="함수-내부에서의-this">함수 내부에서의 this</h3>
<p>더글라스 크락포드가 이를 설계상의 오류로 지적한 이유는 함수 내부에서 의도치 않게 전역 객체를 참조하게 되어 전역 상태를 오염시키거나 예기치 않은 동작을 초래할 수 있기 때문입니다.</p>
<p>이러한 문제를 해결하기 위해 ES6에서는 <strong>화살표 함수(Arrow Function)</strong>를 도입하여 this가 함수가 선언된 Lexical Environment를 참조하도록 설계되었습니다.</p>
<p>화살표 함수는 this를 명시적으로 바인딩하지 않으며 대신 외부 스코프의 this를 상속받아 이러한 설계상의 문제를 완화합니다.</p>
<h3 id="메서드의-내부함수에서의-this">메서드의 내부함수에서의 this</h3>
<p><strong>메서드 내부에서 정의된 함수에서의 this</strong>는 자바스크립트 초심자들이 자주 혼란스러워하는 지점입니다. </p>
<p>this가 가리키는 값은 예측과 달리 동작할 수 있는데 이는 앞서 설명한 &quot;설계상의 오류&quot;로 인해 발생하며 this라는 단어 자체의 느낌에 의존하면 잘못된 예측을 하게 됩니다. </p>
<p>그러나 우리는 이미 함수를 메서드로 호출할 때와 함수로 호출할 때 this가 무엇을 가리키는지를 알고 있기 때문에 내부 함수 역시 이를 함수로 호출했는지 메서드로 호출했는지만 파악하면 this의 값을 정확히 맞출 수 있습니다. </p>
<p>innerFunc를 함수로 호출한 결과와 obj2.innerMethod를 메서드로 호출한 결과에서의 this가 무엇을 가리키는지 예상해보고 실제 결과와 비교하는 것이 중요합니다.</p>
<pre><code>내부함수에서의 this
var obj1 = {
    outer: function(){
        console.log(this);
        var innerFunc = function(){
            console.log(this);
        }
        innerFunc();

        var obj2 = {
            innerMethod: innerFunc
        };
        obj2.innerMethod();
     }
};
obj1.outer();</code></pre><p><strong>obj1.outer() 호출:</strong>
obj1 객체의 outer 메서드를 호출합니다.
outer 메서드 내에서 console.log(this)가 실행되는데 이때의 this는 obj1 객체를 가리킵니다.</p>
<p>첫 번째 console.log(this)는 obj1 객체를 출력합니다.</p>
<p><strong>innerFunc() 호출 (첫 번째):</strong>
innerFunc() 함수는 outer 메서드 내에서 정의되었고 innerFunc()를 호출하는 코드 innerFunc()가 실행됩니다.
innerFunc()는 함수로서 호출되었으므로 this는 전역 객체(브라우저에서는 window 객체)를 가리킵니다.</p>
<p>두 번째 console.log(this)는 전역 객체(window 또는 global)를 출력합니다.</p>
<p><strong>obj2.innerMethod() 호출:</strong>
obj2 객체가 생성되었고 그 객체의 innerMethod에 innerFunc를 할당한 뒤 obj2.innerMethod()를 호출합니다.
innerMethod는 메서드로서 호출되었으므로 this는 obj2 객체를 가리킵니다.</p>
<p>세 번째 console.log(this)는 obj2 객체를 출력합니다.</p>
<h3 id="메서드의-내부-함수에서의-this를-우회하는-방법">메서드의 내부 함수에서의 this를 우회하는 방법</h3>
<p>this에 대한 구분은 명확히 할 수 있지만 그 결과는 this라는 단어가 주는 인상과 다릅니다. </p>
<p>호출 주체가 없을 때, 자동으로 전역 객체를 바인딩하는 대신 호출 당시의 주변 환경에서 this를 상속받아 사용할 수 있다면 더 자연스러울 것입니다. </p>
<p>자바스크립트 설계상 스코프 체인과의 일관성을 유지하려면 변수를 검색할 때 가장 가까운 스코프의 Lexical Environment(L.E)를 먼저 찾고 없으면 상위 스코프를 탐색하는 방식처럼 this도 현재 컨텍스트에 바인딩된 대상이 없으면 직전 컨텍스트의 this를 바라보도록 동작하는 것이 설득력 있는 방식이었습니다. </p>
<p>이렇게 하면 this에 대한 예측 가능성을 높이고 코드의 직관성을 강화할 수 있습니다.</p>
<pre><code>내부함수에서의 this를 우회하는 방법
var obj = {
    outer: function () {
        console.log(this);
        var innerFunc1 = function () {
            console.log(this);
        };
        innerFunc();

        var self = this;
        var innerFunc2 = function () {
            console.log(self);
        };
        innerFunc2();
     }
};
obj.outer();</code></pre><p><strong>obj.outer() 호출</strong>
obj.outer()를 호출하면 outer 함수가 실행됩니다. 
이때 this는 obj를 참조합니다. console.log(this)는 obj를 출력합니다.</p>
<p><strong>innerFunc1 호출</strong>
여기서 innerFunc1 함수는 일반 함수로 호출됩니다. 자바스크립트에서 <strong>일반 함수로 호출된 함수의 this</strong>는 전역 객체(브라우저에서는 window 객체, Node.js에서는 global)를 참조합니다.</p>
<p>만약 strict mode가 활성화되면 this는 undefined가 되지만 적용되지 않으므로 window 객체를 출력합니다.</p>
<blockquote>
<p>strict mode: strict mode는 코드의 오류를 줄이고 안전하게 실행되도록 하는 기능으로 JavaScript에서 use strict를 코드 상단에 추가하여 활성화됩니다. 
주요 특징은 변수 선언을 강제하고 읽기 전용 속성에 값을 할당할 수 없으며 예약어를 변수명으로 사용할 수 없고 this가 undefined일 때 오류를 발생시킨다는 점입니다.</p>
</blockquote>
<p><strong>self 변수 사용</strong>
self는 this를 obj로 저장 self는 obj를 참조합니다. innerFunc2 함수에서 self를 사용하여 this를 유지합니다. </p>
<p><strong>innerFunc2 호출</strong>
innerFunc2는 self를 사용하므로 self는 obj를 참조하고 self가 그대로 출력됩니다. 
console.log(self)는 obj를 출력합니다.</p>
<pre><code>this를 바인딩하지 않는 함수(화살표 함수)
var obj = {
    outer: function () {
        console.log(this);
        var innerFunc = () =&gt; {
            console.log(this);
        };
        innerFunc();
     }
};
obj.outer();</code></pre><p><strong>화살표 함수(innerFunc) 호출</strong>
innerFunc는 화살표 함수입니다. 
화살표 함수는 자기 자신만의 this를 가지지 않고 자신이 정의된 환경에서의 this를 그대로 상속받습니다. 
화살표 함수 내에서의 this는 outer 함수가 호출될 때의 this, obj를 참조하게 됩니다.
그래서 console.log(this)는 여전히 obj를 출력합니다.</p>
<h3 id="콜백-함수-호출-시-그-함수-내부에서의-this">콜백 함수 호출 시 그 함수 내부에서의 this</h3>
<pre><code>콜백 함수 내부에서의 this
setTimeout(function () {console.log(this); }, 300);

[1, 2, 3, 4, 5].forEach(function (x) {
    console.log(this, x);
});

document.body.innerHTML += &#39;&lt;button id = &quot;a&quot;&gt; 클릭 &lt;/button&gt;&#39;;
document.body.querySelector(&#39;#a&#39;)
    .addEvetListener(&#39;click&#39;, function (e) {
        console.log(this, e);
     });</code></pre><p><strong>setimeout 함수 호출</strong>
setTimeout 함수는 타이머를 설정하여 지정된 시간(여기서는 300ms 후)에 주어진 함수를 실행합니다.</p>
<p>일반 함수로 호출된 function() 내부에서의 this는 글로벌 객체(브라우저에서는 window 객체, Node.js에서는 global)를 참조합니다. </p>
<p>setTimeout은 기본적으로 전역 컨텍스트에서 실행되기 때문입니다.</p>
<p>console.log(this)는 전역 객체(window 또는 global)를 출력하게 됩니다.</p>
<p><strong>forEach 메서드 사용</strong>
forEach 메서드는 배열의 각 요소에 대해 주어진 함수를 실행하는 메서드입니다.</p>
<p>forEach에 전달된 일반 함수에서 this는 forEach를 호출한 객체(여기서는 전역 객체 window 또는 global)를 참조합니다.</p>
<p>forEach는 배열의 메서드이지만 function을 일반 함수로 사용했기 때문에 this는 배열 객체를 참조하지 않고 전역 객체를 참조합니다.</p>
<p>console.log(this, x)는 전역 객체와 각 배열 요소 값(1, 2, 3, 4, 5)을 출력하게 됩니다.</p>
<p><strong>addEventListener와 this</strong>
HTML 버튼 요소에 클릭 이벤트 리스너를 추가하는 예제입니다.</p>
<p>addEventListener에서의 일반 함수 내부의 this는 이벤트가 발생한 DOM 요소를 참조합니다. 클릭된 버튼 요소가 this가 됩니다.</p>
<p>console.log(this, e)는 this에 클릭된 버튼을, e에는 이벤트 객체를 출력합니다.</p>
<h3 id="생성자-함수-내부에서의-this">생성자 함수 내부에서의 this</h3>
<p>현실 세계에서 &#39;인간&#39;의 공통 특성(직립 보행, 언어 구사, 도구 사용 등)을 바탕으로 인간을 정의한 것이 &#39;클래스&#39;입니다. </p>
<p>각 사람은 인간 클래스에 속하는 인스턴스로 개별적인 개성이 있습니다. 
프로그래밍에서는 &#39;생성자&#39;가 클래스의 공통 속성을 기반으로 구체적인 인스턴스를 생성하는 틀 역할을 합니다. </p>
<p>자바스크립트에서 함수는 생성자 역할을 할 수 있으며 new 명령어와 함께 호출되면 해당 함수는 생성자 함수로 동작합니다. </p>
<p>this는 새로운 인스턴스를 나타내며 생성자의 prototype을 참조한 객체가 만들어집니다.</p>
<pre><code>생성자 함수
var Cat = function (name, age){
    this.bark = &#39;야옹&#39;;
    this.name = name;
    this.age = age;
};
var choco = new Cat(&#39;초코&#39;, 7);
var nabi = new Cat(&#39;나비&#39;, 5);
console.log(choco, nabi);</code></pre><p><strong>생성자 함수 정의:</strong>
Cat은 함수로 생성자 역할을 합니다.
this는 새로 생성되는 인스턴스를 가리키며 bark, name, age라는 속성을 추가합니다.</p>
<p><strong>인스턴스 생성:</strong>
new Cat(&#39;초코&#39;, 7)를 호출하면 Cat 생성자가 실행되고 choco라는 인스턴스가 만들어집니다.
이 인스턴스는 bark: &#39;야옹&#39; name: &#39;초코&#39; age: 7이라는 속성을 가집니다.
new Cat(&#39;나비&#39;, 5)를 호출하면 Cat 생성자가 실행되어 nabi라는 인스턴스가 만들어집니다.
이 인스턴스는 bark: &#39;야옹&#39; name: &#39;나비&#39; age: 5라는 속성을 가집니다.</p>
<p><strong>출력:</strong></p>
<pre><code>Cat { bark: &#39;야옹&#39;, name: &#39;초코&#39;, age: 7 }
Cat { bark: &#39;야옹&#39;, name: &#39;나비&#39;, age: 5 }</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[실행 컨텍스트 2 ]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@sangmin0310-afk/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Wed, 25 Dec 2024 10:55:30 GMT</pubDate>
            <description><![CDATA[<h1 id="lexicalenvironment">LexicalEnvironment</h1>
<p><code>Lexical environment</code>는 주로 &quot;어휘적 환경&quot;이나 &quot;정적 환경&quot;으로 번역되지만, 이러한 표현들은 개념을 충분히 반영하지 못합니다. 대신 &quot;사전적 환경&quot;이라는 번역이 제안되었으며 이는 컨텍스트 내부의 환경 정보를 사전처럼 구성한 것을 의미합니다. 그러나 타인과의 소통을 위해서는 번역어보다 원어를 그대로 사용하는 것이 더 적합하며 <code>variable environment</code>역시 같은 이유로 원어를 사용하는 편이 권장됩니다.</p>
<h2 id="environmentrecord와-호이스팅">environmentRecord와 호이스팅</h2>
<p>Environment Record에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장됩니다.</p>
<p>함수 매개변수, 선언된 함수, <code>var</code>로 선언된 변수의 식별자가 포함됩니다.
실행 컨텍스트 내부를 처음부터 끝까지 순서대로 훑으며 식별자 정보를 수집합니다.
변수 정보를 모두 수집한 후에도 코드는 아직 실행되지 않은 상태입니다.</p>
<p>실행 전에도 자바스크립트 엔진은 해당 환경의 모든 변수명을 알고 있습니다.
이를 바탕으로 호이스팅(Hoisting) 개념이 등장합니다.</p>
<p>호이스팅은 변수 정보를 <strong>&quot;최상단으로 끌어올린다&quot;</strong> 고 가정하는 가상의 개념입니다.
실제로 엔진이 끌어올리지는 않지만 이해를 돕기 위해 그렇게 간주할 수 있습니다.</p>
<blockquote>
<p>전역 실행 컨텍스트는  변수 객체를 생성하는 대신 자바스크립트 구동 환경이 별도로 제공하는
객체, 즉 전역객체(global object)를 활용합니다. 전역 객체에는 브라우저의 window, Node.js
의 global 객체 등이 있습니다. 이들은 자바스크립트 내장 객체(native object)로 분류됩니다.</p>
</blockquote>
<h3 id="호이스팅-규칙">호이스팅 규칙</h3>
<pre><code>매개변수와 변수에 대한 호이스팅(1)-원본 코드

function a (x) { // 수집 대상 1(매개변수)
    console.log(x); // (1)
    var x; // 수집 대상 2(변수 선언)
    console.log(x); // (2)
    var x = 2; // 수집 대상 3(변수 선언)
    console.log(x); // (3)
 }
 a(1)</code></pre><p>자바스크립트에서는 <strong>변수 선언(var)</strong>이 코드의 최상단으로 &quot;끌어올려진다&quot;고 가정합니다.</p>
<pre><code>function a(x) {
    var x; // (호이스팅: 변수 선언이 최상단으로 이동)
    console.log(x); // (1)
    console.log(x); // (2)
    x = 2; // 값 할당
    console.log(x); // (3)
}</code></pre><p>호출: a(1)
함수 a가 호출될 때 매개변수 x는 값 1로 초기화됩니다.</p>
<p>(1): console.log(x)
x는 함수의 매개변수로 1로 초기화되어 있으므로 1이 출력됩니다.</p>
<p>var x;
var x는 이미 매개변수로 선언된 x와 동일한 스코프에 있으므로 무시됩니다. (중복 선언 무시)</p>
<p>(2): console.log(x)
변수의 값은 여전히 1이므로 1이 출력됩니다.</p>
<p>x = 2;
변수 x에 값 2가 할당됩니다.</p>
<p>(3): console.log(x)
x의 값이 2로 변경되었으므로 2가 출력됩니다.</p>
<pre><code>함수 선언의 호이스팅(1) - 원본코드
funtion 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><p>자바스크립트는 <strong>변수 선언(var)</strong>과 함수 선언을 모두 스코프의 최상단으로 끌어올립니다.</p>
<pre><code>function a() {
    var b; // 변수 선언(호이스팅)
    function b() {} // 함수 선언(호이스팅, 우선순위 높음)

    console.log(b); // (1)
    b = &#39;bbb&#39;; // 변수에 값 할당
    console.log(b); // (2)
    console.log(b); // (3)
}</code></pre><p>함수 선언과 변수 선언의 호이스팅
함수 b가 우선적으로 <strong>식별자 b</strong>에 할당됩니다.
변수 b는 선언만 되고 값이 할당되지 않은 상태로 남아있습니다.</p>
<p>(1): console.log(b)
변수 b는 함수 선언에 의해 <strong>함수 b</strong>를 참조하고 있습니다.
따라서, b는 함수 자체를 출력합니다: function b() {}.</p>
<p>b = &#39;bbb&#39;;
변수 b에 값 &#39;bbb&#39;가 할당됩니다.
이제 b는 문자열 &#39;bbb&#39;를 참조합니다.</p>
<p>(2): console.log(b)
변수 b의 값이 &#39;bbb&#39;로 변경되었으므로, bbb가 출력됩니다.</p>
<p>(3): console.log(b)
변수 b는 여전히 문자열 &#39;bbb&#39;를 참조하므로, bbb가 출력됩니다.</p>
<h3 id="함수-선언문과-함수-표현식">함수 선언문과 함수 표현식</h3>
<p><strong>함수 선언문(Function Declaration)</strong> 과 <strong>함수 표현식(Function Expression)</strong> 은 함수를 정의하는 두 가지 방식입니다. 함수 선언문은 <code>function</code> 정의부만 존재하며 별도의 할당 명령이 없고, 반드시 함수명이 정의되어야 합니다. 반면, 함수 표현식은 정의한 <code>function</code>을 변수에 할당하는 방식으로, 함수명을 정의할 수도 있고 생략할 수도 있습니다. 함수명을 정의한 경우 기명 함수 표현식이라 부르며, 생략한 경우 익명 함수 표현식이라고 합니다. 일반적으로 함수 표현식은 익명 함수 표현식을 의미합니다.</p>
<pre><code>함수를 정의하는 세 가지 방식
function a () {/* ... */} // 함수 선언문. 함수명 a가 곧 변수명.
a(); // 실행 ok.

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

var c = function d () {/* ... */} // 기명 함수 표현식. 변수명은 c, 함수명은 d.
c(); // 실행 ok.
d(); // 에러!</code></pre><blockquote>
<p>기명 함수 표현식은 주의할 점이 하나 있습니다. 바로 외부에서는 함수명으로 함수를 호출할 수 없다는 점입니다. 함수명은 오직 함수 내부에서만 접근할 수 있습니다. 그렇다면 기명 함수 표현식에서 함수명은 어떤 용도로 쓰일까요? 과거에는 기명 함수 표현식은 함수명이 잘 출력됐던 반면 익명 함수 표현식은 undefined 또는 unnamed라는 값이 나왔었습니다. 이 때문에 기명 함수 표현식이 디버깅 시 어떤 함수인지를 추적하기에 익명 함수 표현식보다 유리한 측면이 있었습니다. 그러나 이제는 모든 브라우저들이 익명 함수 표현식의 변수명을 함수의 name 프로퍼티에 할당하고 있습니다.한편 с 함수 내부에서는 c()로 호출하든 d()로 호출하든 잘 실행됩니다. 따라서 함수 내부에서 재귀함수를 호출하는 용도로 함수명을 쓸 수 있습니다. 다만 c()로 호출해도 되는 상황에서 굳이 d()로 호출해야 할 필요가 있을지는 의문입니다.</p>
</blockquote>
<pre><code>함수 선언문과 함수 표현식(1) - 원본 코드
console.log(sum(1, 2));
console.log(multiply(3, 4));

function sum (a, b) {  //함수 선언문 sum
    return a + b;
}

var multiply = function (a, b) { //함수 표현식 multiply
    return a * b;
}</code></pre><p>console.log(sum(1, 2));
sum(1, 2)는 먼저 호출됩니다. 이 호출은 a + b를 반환하는 sum 함수를 실행하려는 것입니다.</p>
<p>console.log(multiply(3, 4));
multiply(3, 4)는 multiply 함수가 호출된 것입니다. 그러나 multiply 함수는 함수 표현식으로 선언되었기 때문에, 코드가 해석되는 시점에서 multiply 함수는 아직 정의되지 않았습니다. 그 결과, multiply 함수 호출은 에러를 발생시킵니다.</p>
<pre><code>function sum(a, b) {
    return a + b;
}</code></pre><p>호이스팅: 함수 선언문은 자바스크립트에서 &quot;호이스팅&quot;에 의해 코드의 최상단으로 끌어올려집니다. 즉, sum 함수는 코드가 실행되기 전에 이미 정의되어 있어, console.log(sum(1, 2)); 호출이 정상적으로 실행됩니다.</p>
<pre><code>var multiply = function(a, b) {
    return a * b;
};</code></pre><p>호이스팅되지 않음: 함수 표현식은 변수에 함수가 할당되는 방식이므로, multiply 변수에 함수가 할당되기 전에 multiply를 호출하면 undefined로 평가되어 에러가 발생합니다. 함수 표현식은 정의된 이후에만 호출할 수 있습니다.</p>
<h2 id="스코프-스코프-체인-outerenvironmentrefence">스코프, 스코프 체인, outerEnvironmentRefence</h2>
<p><strong>스코프(Scope)</strong> 는 식별자의 유효범위를 의미합니다. 경계 A의 외부에서 선언한 변수는 A 내부와 외부에서 모두 접근할 수 있지만 A 내부에서 선언한 변수는 A 내부에서만 접근 가능합니다. 이러한 스코프의 개념은 대부분의 언어에 존재하며 자바스크립트도 예외는 아니지만 ES5까지의 자바스크립트는 특이하게도 함수만이 스코프를 생성합니다. 결국, <strong>스코프 체인(Scope Chain)</strong> 은 식별자의 유효범위를 안에서 바깥으로 차례로 검색해 나가는 과정을 의미하며 이를 가능하게 하는 것은 <code>Lexical Environment</code>의 두 번째 수집 자료인 <code>outerEnvironmentReference</code>입니다.</p>
<h3 id="스코프-체인">스코프 체인</h3>
<p><code>outerEnvironmentReference</code>는 현재 호출된 함수가 선언될 당시의 <code>Lexical Environment</code>를 참조합니다.
&quot;선언 시점&quot;에 주목해야 하며 함수 선언은 실행 컨텍스트가 활성화된 상태에서만 가능하므로 함수가 선언되는 시점은 해당 실행 컨텍스트가 활성화될 때입니다.
예를 들어, 함수 A 내부에서 함수 B를 선언하고 함수 B 내부에서 또 다른 함수를 선언하면 함수 B의 <code>outerEnvironmentReference</code>는 함수 A의 <code>Lexical Environment</code>를 참조합니다.
<code>outerEnvironmentReference</code>는 연결리스트 형태로 구성되며 &quot;선언 시점의 <code>Lexical Environment</code>&quot;를 계속 찾아 올라가면 전역 컨텍스트의 <code>Lexical Environment</code>에 도달합니다.
각 <code>outerEnvironmentReference</code>는 자신이 선언된 시점의 <code>Lexical Environment</code>만 참조하므로 스코프 체인에서는 가장 가까운 요소부터 차례대로만 접근할 수 있고 다른 순서로 접근할 수 없습니다.</p>
<pre><code>var a = 1;
var outer = function () {
    var inner = function () {
        console.log(a);
        var a = 3;
    };
    inner();
    console.log(a);
};
outer();
console.log(a);</code></pre><p>전역 컨텍스트:</p>
<pre><code>var a = 1;</code></pre><p>전역에서 a라는 변수가 선언되고 값 1이 할당됩니다.</p>
<p>outer 함수 호출:</p>
<pre><code>outer();</code></pre><p>outer() 함수가 호출됩니다.</p>
<p>outer 함수 실행:</p>
<pre><code>var outer = function () {
    var inner = function () {
        console.log(a);
        var a = 3;
    };
    inner();
    console.log(a);
};</code></pre><p>outer 함수가 실행되면 내부에 inner 함수가 정의됩니다.
그 후 inner() 함수가 호출됩니다.</p>
<p>inner 함수 실행:</p>
<pre><code>var a = 3;
console.log(a);</code></pre><p>inner 함수에서 console.log(a)를 호출하기 전에, var a = 3이 선언됩니다. 호이스팅에 의해 a는 undefined로 초기화되지만, 할당은 나중에 이루어집니다.
따라서 console.log(a)는 <strong>undefined</strong>를 출력합니다 왜냐하면 inner 함수의 스코프 내에서 a가 존재하고 그 값이 아직 할당되지 않았기 때문입니다.</p>
<p>inner 함수 종료 후 outer 함수 실행:
inner() 함수가 실행된 후 outer 함수 내에서 console.log(a)가 호출됩니다.
이때 outer 함수의 스코프 내에서 a는 전역 변수 a를 참조하고, 값은 1입니다. 따라서 console.log(a)는 <strong>1</strong>을 출력합니다.</p>
<p>outer 함수 종료 후 전역 실행:
outer() 함수가 종료된 후, 전역에서 console.log(a)가 호출됩니다.
전역에서의 a 값은 여전히 1입니다. 따라서 마지막 console.log(a)도 <strong>1</strong>을 출력합니다.</p>
<p>스코프 체인 상에 있는 변수라고 해서 무조건 접근 가능한 것은 아닙니다.
예를 들어 a 식별자가 전역 공간과 inner 함수 내부에서 모두 선언된 경우 inner 함수 내부에서 a에 접근하려 하면 스코프 체인에서 첫 번째로 검색되는 inner 스코프의 <code>Lexical Environment</code>에서 a를 찾게 됩니다.
inner 함수에서 a를 선언했기 때문에 전역 공간에서 선언한 동일한 이름의 a 변수에는 접근할 수 없습니다.
이는 <strong>변수 은닉화(variable shadowing)</strong> 라고 하며 내부 스코프에서 외부의 동일한 이름을 덮어쓰는 현상을 의미합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[실행 컨텍스트 (2-1, 2-2)]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-2-1-2-2</link>
            <guid>https://velog.io/@sangmin0310-afk/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-2-1-2-2</guid>
            <pubDate>Thu, 19 Dec 2024 10:03:49 GMT</pubDate>
            <description><![CDATA[<h1 id="실행-컨택스트란">실행 컨택스트란?</h1>
<p>실행할 코드에 필요한 환경 정보를 모아놓은 객체입니다.
실행 컨텍스트는 <strong>콜 스택(Call Stack)</strong>에 쌓이며 스택의 최상단 컨텍스트와 관련된 코드가 실행됩니다.
컨텍스트는 전역 공간, eval() 함수, 함수 실행 등으로 생성됩니다.
함수 실행은 가장 일반적인 실행 컨텍스트 생성 방식입니다.</p>
<p><strong>콜 스택(Call Stack)</strong>은 코드의 실행 순서를 관리하는 메모리 구조입니다.</p>
<h4 id="스택stack"><strong>스택(Stack):</strong></h4>
<p>출입구가 하나뿐인 데이터 구조로 &quot;후입선출(LIFO)&quot; 방식으로 동작합니다.
데이터를 a, b, c 순으로 넣으면 꺼낼 때는 c, b, a 순으로 나옵니다.
스택이 가득 찼을 때 데이터를 더 넣으려 하면 &quot;스택 오버플로우&quot; 에러가 발생합니다.</p>
<h4 id="큐queue"><strong>큐(Queue):</strong></h4>
<p>양쪽이 열린 파이프처럼 동작하며 &quot;선입선출(FIFO)&quot; 방식으로 동작합니다.
데이터를 a, b, c, d 순으로 넣으면 꺼낼 때도 동일한 순서로 나옵니다.</p>
<pre><code>실행 컨텍스트와 콜 스택
var a = 1;
funtion outer() {
    funtion inner() {
        console.log(a); // undefined
        var a = 3;
    }
    inner(); 
    console.log(a);
}
outer();
console.log(a);</code></pre><h3 id="전역-실행-컨텍스트의-시작">전역 실행 컨텍스트의 시작</h3>
<p>자바스크립트 파일을 브라우저에서 실행하면 전역 실행 컨텍스트가 자동으로 생성됩니다. 전역 컨텍스트는 자바스크립트 코드의 최상단 환경으로 파일이 열리는 순간 콜 스택(Call Stack)에 담깁니다.</p>
<p>전역 컨텍스트는 특별한 실행 명령 없이도 자동으로 활성화되며 실행 가능한 다른 코드(함수 호출 등)가 등장하기 전까지 순차적으로 전역 코드가 실행됩니다.</p>
<h3 id="함수-호출과-실행-컨텍스트의-추가">함수 호출과 실행 컨텍스트의 추가</h3>
<p>자바스크립트에서 함수가 호출되면 새로운 실행 컨텍스트가 생성됩니다. 이 컨텍스트는 해당 함수 실행에 필요한 환경 정보를 포함하며 콜 스택의 맨 위에 쌓입니다. </p>
<pre><code>function outer() {
    function inner() {
        let a = 3;
        console.log(a);
    }
    inner();
    console.log(&#39;outer done&#39;);
}

outer();</code></pre><ol>
<li><p><code>outer()</code> 함수가 호출되면 outer 실행 컨텍스트가 생성되어 콜 스택에 추가됩니다.</p>
</li>
<li><p><code>outer()</code> 내부에서 <code>inner()</code> 함수가 호출되면 inner 실행 컨텍스트가 콜 스택의 맨 위에 쌓입니다.</p>
</li>
<li><p><code>inner()</code> 실행이 종료되면 inner 실행 컨텍스트는 콜 스택에서 제거되고 다시 outer 실행 컨텍스트가 활성화됩니다.</p>
</li>
<li><p>마지막으로 <code>outer()</code> 실행이 끝나면 outer 실행 컨텍스트도 제거됩니다.</p>
</li>
</ol>
<h3 id="중단과-재개-그리고-종료">중단과 재개, 그리고 종료</h3>
<p>새로운 실행 컨텍스트가 추가되면 이전에 실행되던 코드는 중단됩니다.
스택의 맨 위 컨텍스트가 실행을 끝내면 중단되었던 아래 컨텍스트로 돌아갑니다.
마지막으로 전역 코드까지 모두 실행되면 콜 스택이 비어 있는 상태로 종료됩니다.</p>
<h3 id="콜-스택의-구조와-흐름">콜 스택의 구조와 흐름</h3>
<p>콜 스택은 &quot;스택(Stack)&quot; 자료구조로 동작하며 후입선출(LIFO) 방식으로 작동합니다. 
가장 최근에 추가된 실행 컨텍스트가 먼저 실행되고 실행이 끝나면 제거됩니다.</p>
<blockquote>
<p><code>VariableEnvironment</code>: 현재 컨택스트 식별자들에 대한 정보 + 외부 환경 정보.
선언 시점의  <code>LexicalEnvironment</code>의 스냅샥으로, 변경 사항은 반영되지 않음</p>
</blockquote>
<blockquote>
<p><code>LexicalEnvironment</code>: 처음에는 <code>VariableEnvironment</code>와 같지만 변경 사항이 실시간으로 반영됨.</p>
</blockquote>
<blockquote>
<p><code>ThisBinding</code>: 식별자가 바라봐야 할 대상 객체</p>
</blockquote>
<h1 id="variableenvironment">VariableEnvironment</h1>
<p><code>VariableEnvironment</code>와 <code>LexicalEnvironment</code> 모두 내부에 <code>environmentRecord</code>와 <code>outerEnvironmentReference</code>로 구성됩니다.
실행 컨텍스트 생성 시 초기에는 동일한 정보를 가집니다.</p>
<p><code>VariableEnvironment</code>는 실행 초기 상태의 스냅샷을 유지합니다.
이후 코드 실행 중에는 주로 <code>LexicalEnvironment</code>가 사용되며 값은 코드 진행에 따라 업데이트됩니다.</p>
<p>실행 컨텍스트 생성 시 <code>VariableEnvironment</code>에 정보가 담기고 이를 복사하여 <code>LexicalEnvironment</code>가 생성됩니다.
코드 실행이 진행되면서 두 환경이 달라질 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 타입]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@sangmin0310-afk/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</guid>
            <pubDate>Thu, 12 Dec 2024 08:24:58 GMT</pubDate>
            <description><![CDATA[<h1 id="메모리와-데이터">메모리와 데이터</h1>
<p>컴퓨터는 데이터를 저장하고 처리할 때, 모든 정보를 0과 1로 변환합니다. 이러한 0과 1을 표현할 수 있는 가장 작은 메모리 단위를 <strong>비트(Bit)</strong>라고 합니다. 메모리는 이러한 비트가 모여 이루어진 구조이며, 각 비트는 고유한 <strong>식별자(Unique Identifier)</strong>를 통해 위치를 확인할 수 있습니다.</p>
<h4 id="비트를-묶는-이유">비트를 묶는 이유</h4>
<p>비트는 단 하나의 값(0 또는 1)만을 표현할 수 있어 활용에 한계가 있습니다. 만약 데이터를 처리하거나 검색할 때 비트 단위로 작업을 한다면, 메모리 용량은 적게 차지할 수 있겠지만 효율이 매우 떨어질 것입니다.</p>
<p>하지만 비트를 지나치게 많이 묶으면, 효율성의 문제가 발생할 수 있습니다. 자주 사용하지 않는 데이터를 표현하기 위해 큰 공간을 남겨두는 것은 메모리 낭비로 이어질 수 있기 때문입니다.</p>
<h1 id="식별자와-변수">식별자와 변수</h1>
<p><strong>변수</strong>는 <strong>변할 수 있는 수 입니다</strong>. 수학 용어를 차용했기 때문에 숫자를 의미하는 &#39;수&#39;가 붙었을 뿐, 값이 반드시 &#39;숫자&#39;여야 하는 것이 아닙니다.
영어 단어 variable은 원래 변할 수 있다라는 형용사이지만 컴퓨터 용어로 쓸 때는 변할 수 있는 &#39;무언가&#39;라는 명사로 확장시켰습니다.</p>
<p>여기서 무언가 = <strong>데이터</strong>를 말합니다. 숫자도 데이터, 문자열도, 객체도, 배열 모두 데이터입니다. <strong>식별자</strong>는 어떤 데이터를 식별하는 데 사용하는 이름, 즉 <strong>변수명</strong>입니다.</p>
<h1 id="변수-선언">변수 선언</h1>
<pre><code>var a; // a라는 변수를 선언, 초기값은 undefined
a = 10; // a에 숫자 10을 저장
a = &quot;Hello, World!&quot;; // a에 문자열 저장
</code></pre><p>변수를 쉽게 이해하려면 데이터를 담는 그릇이라고 생각하면 됩니다.
이 그릇은 어떤 데이터든 담을 수 있으며, 필요에 따라 비우고 새 데이터를 담을 수도 있습니다.</p>
<blockquote>
<p>변경 가능: 한 번 저장한 값이라도 언제든 다른 값으로 대체할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>다양한 데이터 타입을 수용: 숫자, 문자열, 객체 등 다양한 데이터 타입을 저장할 수 있습니다.</p>
</blockquote>
<blockquote>
<p>식별자를 통해 접근: 변수의 이름, 즉 식별자를 통해 데이터를 저장하거나 불러올 수 있습니다.</p>
</blockquote>
<h1 id="데이터-할당">데이터 할당</h1>
<pre><code>var a; // 변수 a 선언
a = &#39;abc&#39;; // 변수 a에 데이터 할당

var a = &#39;abc&#39; // 변수 선언과 할당을 한 문장으로 표현</code></pre><p>자바스크립트에서 변수 선언과 할당은 두 문장으로 나누거나 한 문장으로 작성하더라도, 엔진은 동일한 방식으로 처리합니다. 선언 과정에서는 메모리 공간을 확보하고 이름을 설정하며, 이후 할당 과정에서는 해당 주소에 값을 저장합니다.</p>
<blockquote>
<p>왜 변수 영역에 값을 직접 대입하지 않고 굳이 번거롭게 한 단계를 더 거치는 걸까요?</p>
</blockquote>
<p>자바스크립트는 변수와 데이터를 별도 저장해 데이터 변환의 자유와 메모리 효율성을 높입니다. 숫자는 고정 크기지만, 문자열은 가변적이므로 저장 공간을 미리 늘리거나 이동해야 할 수 있습니다. 이를 방지하려고 변수와 데이터를 분리해 메모리 사용을 최적화 할려고 해서 한 단계를 더 거칩니다.</p>
<h1 id="불변값">불변값</h1>
<p>변수와 상수는 <strong>변수 영역 메모리의 변경 가능성</strong>으로 구분됩니다. 변수는 재할당이 가능하지만, 상수는 불가능합니다. 반면, 불변성은 <strong>데이터 영역 메모리의 변경 가능성</strong>과 관련되며, 숫자, 문자열, boolean 등 기본형 데이터는 모두 불변값입니다.</p>
<pre><code>var a = &#39;abc&#39;;
a = a + &#39;def&#39;;

var b = 5; 
var c = 5;
b = 7;</code></pre><h1 id="가변값">가변값</h1>
<pre><code>var obj1 = {
    a: 1,
    b: &#39;bbb&#39;
};</code></pre><p>가상의 주소를 넣겠습니다. =&gt; (@0000)</p>
<p>변수 영역 확보: 변수 이름(obj1)에 해당하는 주소(@1002)가 할당됩니다.</p>
<p>데이터 그룹 저장: 객체 데이터를 저장하기 위해 별도의 주소(@5001)를 생성하고, 객체 내부 프로퍼티를 관리할 변수 영역(@7103, @7104)을 마련합니다.</p>
<p>프로퍼티 저장: 각 프로퍼티 이름(a, b)을 변수 영역에 지정하고, 값(숫자 1, 문자열 &#39;bbb&#39;)을 데이터 영역(@5003, @5004)에 저장한 후 해당 주소를 프로퍼티 변수에 연결합니다.</p>
<p>기본형 데이터와 달리 참조형 데이터는 프로퍼티 변수 영역이 별도로 존재하며, 데이터 영역의 값은 불변입니다. 그러나 변수는 다른 값을 대입할 수 있어 참조형 데이터를 &quot;가변값&quot;으로 인식하게 됩니다.</p>
<pre><code>참조형 데이터의 프로퍼티 재할당
var obj1 = {
    a: 1,
    b: &#39;bbb&#39;
};
obj1.a = 2;</code></pre><p>obj1의 a 프로퍼티에 숫자 2를 할당하려는 과정에서, 데이터 영역에 숫자 2가 없으면 빈 공간 @5005에 저장됩니다. 이 주소는 @7103에 저장되며, 객체 자체는 새로운 객체로 생성되지 않고 기존 객체(@5001) 내부의 값만 변경됩니다.</p>
<pre><code>중첩된 참조형 데이터(객체)의 프로퍼티 할당
var obj = {
    x: 3,
    arr: [3, 4, 5]
};</code></pre><p>변수 영역 확보: 변수 영역에 빈 공간 @1002를 확보하고 이름을 obj로 지정</p>
<p>객체 생성: 데이터 저장 공간 @5001에 객체를 저장하며, 객체의 프로퍼티를 저장할 변수 영역(@7103~?)을 생성</p>
<p>프로퍼티 지정: @7103에 이름 x, @7104에 이름 arr를 지정</p>
<p>숫자 저장: 데이터 영역에 숫자 3이 없으면 @5002에 저장하고, 그 주소를 @7103에 저장</p>
<p>배열 생성: 배열 데이터 그룹의 변수 영역(@8104~?)을 생성하여 주소 정보를 @5003 → @7104로 저장</p>
<p>배열 인덱스 설정: 배열 요소 3개를 위한 공간을 확보하고 인덱스(0, 1, 2)를 부여</p>
<p>숫자 저장:
인덱스 0: 숫자 3의 주소 @5002를 @8104에 저장
인덱스 1: 숫자 4가 없으면 @5004에 저장하고, 그 주소를 @8105에 저장
인덱스 2: 숫자 5가 없으면 @5005에 저장하고, 그 주소를 @8106에 저장</p>
<h1 id="변수-복사-비교">변수 복사 비교</h1>
<pre><code>var a = 10;
var b = a;

var obj1 = {c: 10, d: &#39;ddd&#39;};
var obj2 = obj1;</code></pre><p>기본형 데이터: 변수 a는 빈 공간 @1001에 저장되며, 숫자 10은 데이터 영역 @5001에 저장
변수 b는 빈 공간 @1002에 생성되며, a의 값(@5001)을 복사해 저장</p>
<p>참조형 데이터: 변수 obj1은 빈 공간 @1003에 생성되며, 데이터 그룹은 @5002에 저장
그룹의 변수 영역 @7103~이 생성되어, c와 d가 각각 @5001(숫자 10)과 새로 생성된 문자열 주소에 연결</p>
<p>복사 과정: 변수 obj2는 빈 공간 @1004에 생성되며, obj1의 값(@5002)을 복사해 저장</p>
<p>기본형 데이터와 참조형 데이터 모두 복사 시 동일한 주소를 바라보게 됩니다(@5001, @5002).
하지만 데이터 할당 과정의 차이로, 참조형 데이터는 복사 후 객체 내부의 값을 공유하는 반면, 기본형 데이터는 독립적인 값을 가짐</p>
<pre><code>변수 복사 이후 값 변경 결과 - 객체의 프로퍼티 변경 시
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>기본형 데이터: 숫자 15는 데이터 영역 @5004에 저장되고, 변수 b의 값(@1002)이 @5004로 변경</p>
<p>참조형 데이터: 숫자 20은 데이터 영역 @5005에 저장되고, obj2의 주소(@1004)가 가리키는 객체(@5002) 내부의 프로퍼티 c의 값이 @5005로 변경</p>
<p>변화 비교:기본형 데이터(a와 b): 변수 b의 값이 변경되면서 서로 다른 주소를 가리키게 됨</p>
<p>참조형 데이터(obj1과 obj2): 여전히 동일한 객체(@5002)를 참조, 객체 내부 프로퍼티만 변경됨</p>
<p>차이점:
기본형은 값이 복사되면서 별개의 주소를 바라봄
참조형은 객체의 주소를 복사하여 동일한 객체를 공유함</p>
<p>자바스크립트의 모든 데이터는 주소를 통해 참조되지만, 기본형은 값 복사가 한 번만 이루어지는 반면, 참조형은 추가 단계(객체 내부의 주소 참조)가 존재
이 차이를 이해하면 변수 복사 및 변경에 따른 동작 원리를 명확히 알 수 있다.</p>
<h1 id="불변-객체를-만드는-방법">불변 객체를 만드는 방법</h1>
<p>불변 객체와 가변 객체는 최근의 React, Vue.js, Angular 등에서 중요한 개념으로, 함수형 프로그래밍과 디자인 패턴에서도 핵심적인 역할을 합니다. 
참조형 데이터의 <strong>가변성</strong>은 객체 내부의 프로퍼티를 변경할 때만 성립하며, 데이터 자체를 변경하려면 새로운 객체를 만들어야 합니다. 이를 통해 객체의 불변성을 유지할 수 있습니다. 불변성을 요구하는 경우, 새로운 객체를 만들어 재할당하거나 자동으로 새로운 객체를 생성하는 도구를 활용하여 관리할 수 있으며, 상황에 따라 불변 객체와 가변 객체를 구분해 사용할 수 있습니다.</p>
<pre><code>var user = {
    name: &#39;Jaenam&#39;,
    gender: &#39;male&#39;
};

var changeName = function(user, newName) {
    var newUser = user;
    newUser.name = newName;
    return newUser;
};

var user2 = changeName(user, &#39;Jung&#39;);

if(user !== user2){
    console.log(&#39;유저 정보가 변경되었습니다.&#39;);
}
console.log(user.name, user2.name);
console.log(user === user2);</code></pre><p>user 객체의 name 프로퍼티를 변경한 후, user2 변수에 그 결과를 할당했지만, 두 변수는 동일한 객체를 참조하므로 서로 다른 객체가 아니게 됩니다.<br>두 변수의 name 프로퍼티가 모두 동일하고, 두 변수가 동일하다고 출력됩니다. 이는 객체가 가변적이어서 참조형 데이터의 변경이 다른 변수에 영향을 미친다는 문제를 나타냅니다.</p>
<pre><code>객체의 가변성에 따른 문제점의 해결 방법
var user = {
    name: &#39;Jaenam&#39;,
    gender: &#39;male&#39;
};

var changeName = funtion (user, newName) {
    return {
        name: newName,
        gender: user.gender
    };
};

var user2 = changeName(user, &#39;Jung&#39;);

if (user !== user2) {
    console.log(&#39;유저 정보가 변경되었습니다.&#39;)
}
console.log(user.name, user2.name); // Jaenam Jung
console.log(user === user2); // false</code></pre><p>user와 user2 객체는 서로 다른 객체이므로 안전하게 변경 전후를 비교할 수 있지만 changeName 함수에서 기존 객체의 프로퍼티를 하드코딩으로 입력하는 방식은 비효율적입니다. 객체의 프로퍼티가 많아질수록 입력해야 할 수고가 증가하기 때문에 모든 프로퍼티를 복사하는 방식을 사용하는 것이 더 효율적입니다.</p>
<h1 id="얕은-복사와-깊은-복사">얕은 복사와 깊은 복사</h1>
<p>얕은 복사는 바로 아래 단계의 값만 복사하는 방법이고,
깊은 복사는 내부 의 모든 값들을 하나하나 찾아서 전부 복사하는 방법입니다.</p>
<pre><code>중첩된 객체에 대한 얕은 복사
var user = {
    name: &#39;Jaenam&#39;,
    urls: {
        portfolio: &#39;http://github.com/abc&#39;,
        blog: &#39;http://blog.com&#39;,
        facebook: &#39;http://facebook.com/abc&#39;
    }
};
var user2 = copyObject(user);

user2.name = &#39;Jung&#39;;
console.log(user.name === user2.name);

user.urls.portfolio = &#39;http://portfolio.com&#39;;
console.log(user.urls.portfolio === user2.urls.portfolio);

user2.urls.blog = &#39;&#39;;
console.log(user.urls.blog === user.urls.blog);</code></pre><p>user2의 name 프로퍼티를 변경해도 원본 객체인 user의 값이 영향을 받지 않았습니다. 하지만 14번째 줄과 17번째 줄에서는 urls 프로퍼티 내부 값이 공유되므로, 원본과 사본 모두에 영향을 미쳤습니다. 이는 객체 내부에 중첩된 프로퍼티들이 참조를 공유하기 때문입니다. 이러한 문제를 방지하려면 user.urls 프로퍼티도 불변 객체로 만들어야 합니다.</p>
<pre><code>중첩된 객체에 대한 깊은 복사
var user2 = copyObject(user);
user2.urls = copyObject(user.urls);

user.urls.portfolio = &#39;http://portfolio.com&#39;;
console.log(user.urls.portfolio === user2.urls.portfolio);

user2.urls.blog = &#39;&#39;;
console.log(user.urls.blog === user.urls.blog);</code></pre><p>객체를 완전히 복사하려면, 기본형 데이터는 그대로 복사하고 참조형 데이터는 내부 프로퍼티들을 재귀적으로 복사해야 합니다. 이렇게 참조형 데이터를 처리하며 복사를 반복해야 깊은 복사가 가능합니다.</p>
<pre><code>객체의 깊은 복사를 수행하는 범용 함수
var copyObjectDeep = function(target) {
    var result = {};
    if (typeof target === &#39;object&#39; &amp;&amp; target !== null) {
        for (var prop in target) {
            result[prop] = copyObjectDeep(target[prop]);
        }
    } else {
        result = target;
    }
    return result;
};</code></pre><p>copyObjectDeep 함수는 3번째 줄에서 객체인 경우 내부 프로퍼티를 순회하며 재귀적으로 호출해 복사하고 객체가 아닌 경우 8번째 줄에서 값을 그대로 복사합니다. 원본과 사본이 완전히 독립된 객체가 되어 한쪽의 변경이 다른 쪽에 영향을 주지 않게 됩니다.</p>
<h1 id="undefined와-null">undefined와 null</h1>
<p>자바스크립트에는 undefined와 null이라는 두 가지 &quot;없음&quot;을 나타내는 값이 있습니다. 이 중 undefined는 값이 지정되지 않은 경우 자바스크립트 엔진이 자동으로 부여합니다.</p>
<ol>
<li>값을 대입하지 않은 변수에 접근할 때.</li>
<li>객체의 존재하지 않는 프로퍼티에 접근할 때.</li>
<li>return 문이 없거나 호출되지 않은 함수의 실행 결과.</li>
</ol>
<pre><code>undefined와 배열
var arr1 = [];
arr1.length = 3;
console.log(arr1); // [empty x 3]

var arr2 = new Arrat(3);
console.log(arr2); // [empty x 3]

var arr3 = [undefined, undefined, undefined];
console.log(arr3); // [undefined, undefined, undefined]</code></pre><p>1번째 줄에서 빈 배열을 만들고 크기를 3으로 설정하면, 3번째 줄에서 [empty x 3]이 출력됩니다. 배열에 빈 요소가 확보되었지만 
값(심지어 undefined)도 할당되지 않았음을 뜻합니다.
5번째 줄에서는 new Array(3)를 사용해 배열을 생성했으며 
결과는 [empty x 3]으로 동일합니다.
8번째 줄에서는 배열 리터럴을 사용해 각 요소에 undefined를 명시적으로 부여했으며 9번째 줄 출력 결과는 [undefined, undefined, undefined]로 앞의 두 결과와 다릅니다.</p>
<p>이처럼 비어있는 요소와 undefined를 할당한 요소는 출력 결과부터 다릅니다.
비어있는 요소는 순회와 관련된 많은 배열 메서드들의 순회 대상에서 제외됩니다.</p>
<pre><code>빈 요소와 배열의 순회
var arr1 = [undefined, 1];
var arr2 = [];
arr[1] = 1;

arr1.forEarch(funtion (v, i) {console.log(v, i); }); // undefined 0/1 1
arr2.forEarch(funtion (v, i) {console.log(v, i); }); // 1 1

arr1.map(function (v, i) {return v + i; }); // [NaN, 2]
arr2.map(function (v, i) {return v + i; }); // [empty, 2]

arr1.filter(function (v) {retrun !v; }); // [undefined]
arr2.filter(function (v) {retrun !v; }); // []

arr1.reduce(function (p, c, i) {retrun p + c + i; }, &#39;&#39;); // undefined011
arr2.reduce(function (p, c, i) {retrun p + c + i; }, &#39;&#39;); // 11</code></pre><p>arr1은 undefined를 명시적으로 할당한 배열이고, arr2는 빈 배열의 특정 인덱스에만 값을 할당한 배열입니다. 
배열 메서드(forEach, map, filter, reduce 등)의 동작에서 차이가 발생합니다.</p>
<p>arr1은 모든 요소를 순회하며 결과를 출력합니다.
arr2는 빈 요소를 건너뛰고 처리하지 않습니다.
빈 요소와 명시적으로 할당된 undefined의 차이 때문입니다.</p>
<blockquote>
<p>&#39;값을 대입하지 않은 변수&#39; 즉 데이터 영역의 메모리 주소를 지정하지 않은 식별자에는 자바스크립트가 직접 undefined를 할당합니다. TC39의 ECMAScript 명세서에서는 다음과 같이 설명하고 있습니다.
var 변수는 environmentRecord가 인스턴스화될 때 생성되면서 undefined로 초기화 됩니다.</p>
</blockquote>
<p>TC39: 자바스크립트 언어의 표준을 정의하고 발전시키는 
Ecma International의 기술 위원회인 <strong>&quot;Technical Committee 39&quot;</strong> 를 의미합니다. 
TC39는 ECMAScript(자바스크립트의 표준 사양)의 제안, 논의, 개발을 담당하며, 언어의 새 기능과 업데이트를 정의하는 중요한 역할을 합니다.</p>
<p>Environment Record는 자바스크립트의 실행 컨텍스트(Execution Context) 내부에서 변수를 저장하고 관리하는 메커니즘 스코프와 관련된 데이터(변수, 함수, 매개변수 등)를 구조화하여 유지합니다. 
자바스크립트 엔진은 코드 실행 중에 Environment Record를 사용해 변수의 선언, 할당, 조회를 처리합니다.</p>
<blockquote>
<p>한편 ES6에서 등장한 let,const에 대해서는 undefined를 할당하지 않은 채로 초기화를 마치며 실제 변수가 평가되기 전까지는 해당 변수에 접근할 수 없습니다. 명세서에는 let과 const변수는 environmentRecord가 인스턴스화 될 때 생성되지만 실제 변수가 평가되기 전까지는 접근할 수 없다고 설명하고 있습니다.</p>
</blockquote>
<h2 id="결론">결론</h2>
<p><strong>메모리와 데이터</strong>
컴퓨터는 데이터를 0과 1의 비트로 저장하며, 효율적인 처리를 위해 비트를 묶어 사용</p>
<p><strong>변수와 식별자</strong>
변수는 데이터를 저장하는 공간 식별자는 변수를 참조하기 위한 이름
변수 선언과 데이터 할당은 별도로 이루어지며 메모리 관리 효율성을 높이기 위해 변수와 데이터를 분리 저장</p>
<p><strong>undefined와 null</strong>
undefined: 값이 없거나 할당되지 않은 상태를 의미하며 자바스크립트 엔진이 자동으로 부여하거나 사용자가 명시적으로 지정
null: 값이 없음을 명시적으로 표현하는 값으로 사용자가 의도적으로 &quot;빈 상태&quot;를 지정할 때 사용</p>
<p><strong>불변값과 가변값</strong>
불변값: 기본형 데이터(number, string 등)는 변경 시 새로운 메모리 공간에 저장
가변값: 참조형 데이터(object, array 등)는 내부 값을 수정 가능하며 주소를 통해 참조</p>
<p><strong>참조형 데이터의 특징</strong>
참조형 데이터는 변수에 주소를 저장하고, 데이터는 별도의 공간에 관리
중첩된 데이터 구조(예: 객체 안의 배열)는 각 요소가 개별 메모리 주소를 가짐</p>
<p><strong>변수 복사</strong>
기본형 데이터는 값을 복사(독립적)
참조형 데이터는 주소를 복사(같은 객체를 공유)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 사옥탐방]]></title>
            <link>https://velog.io/@sangmin0310-afk/AWS-%EC%82%AC%EC%98%A5%ED%83%90%EB%B0%A9</link>
            <guid>https://velog.io/@sangmin0310-afk/AWS-%EC%82%AC%EC%98%A5%ED%83%90%EB%B0%A9</guid>
            <pubDate>Fri, 20 Sep 2024 08:04:33 GMT</pubDate>
            <description><![CDATA[<h1 id="사옥-처음-본-느낌">사옥 처음 본 느낌</h1>
<p>사옥이라는 건물에 들어와서 들어온 느낌은 건물에서 좋은 향기가 나는 분위기를 
가지고 있어서 들어올때 마음을 풀어주는 느낌 을 많이 받았고 엘리베이터를 
사용을 하려면 여기에 필요한 증명서가 있어야지만 사용할 수 있음에 놀랐습니다.</p>
<p>그리고 높은 층에 위치하고 있어서 뷰가 좋습니다.</p>
<h1 id="jam-프로젝트">JAM 프로젝트</h1>
<p>JAM 이라는 이름의 프로젝트를 통해 문제 사항을 주고 이 문제가 발생을 했을 때 우리는 AWS에서 어떻게 활용을 해야 하나 보안 문제에 관한 일이 발생하지 않게 어떻게 예방을 해놓을 것인가에 대한 부분에 학습을 진행하면서 </p>
<p>내가 생각하지 못한 부분의 일이 일어날 수 있고 문제 가 발생했을시에 어떻한 방법이 최선일지 다른 사람들은 어떤 생각을 가지고 이 문제를 해결해 나갈지에 대해 배워 나갔습니다.</p>
<p>문제는 팀과 함께 문제를 해결해 나가는 방식이기에 내 생각뿐만 아닌 팀의 생각도 잘 듣고 이의견을 잘 조율해가며 문제 해결능력을 키워나가는 부분이 좋았습니다. </p>
<p>혼자만의 생각이 완벽한 정답이 될 순 없으니 다른 사람의 의견이 얼마나 중요한지에 대한 부분도 많이 깨달았습니다.</p>
<h1 id="어려웠던-문제">어려웠던 문제</h1>
<p>문제는 대부분 어려웠습니다. </p>
<p>많이 학습하지 않은 저의 문제도 있지만 아예 학습을 하지 않은 수업에서 알려주지 않은 부분까지 문제로 나와 이 문제를 어떻게 해결해야 하나 하는 부분에 있어 어려움이 많았습니다. </p>
<p>오류가 걸리고 하는 부분과 관리자 권한을 받아야 한다는 부분을 뺀 문제중에 제일 어려웠던건 </p>
<p>이 문제였습니다.
<img src="https://velog.velcdn.com/images/sangmin0310-afk/post/93969c4b-393e-483a-aa0c-9feec225063a/image.gif" alt=""></p>
<p>배경:
개발자가 남긴 문서는 아래의 두 Amazon DynamoDB 테이블을 활용하여 비즈니스 목표를 달성할 수 있음을 나타냅니다.</p>
<p>테이블 이름    설명
고객 거래    모든 고객 거래를 저장합니다
고객 프로필    고객 프로필을 저장합니다</p>
<hr>
<p>개발자는 CustProfile 테이블에서 고객의 총 지출과 해당 고객 상태(&quot;일반&quot; 또는 &quot;엘리트&quot;)를 포착하기 위해 두 개의 추가 필드를 추가했습니다.</p>
<p>개발자는 또한 JAM_Lambda_Exec_Function_EDIT_THISCustTransactions 테이블의 변경 사항을 이벤트로 수락하고 CustProfile 테이블을 업데이트하는 Lambda 함수 작업을 시작했습니다. Lambda 함수에는 일부 코드가 누락되어 있으며 개발자는 함수를 실행하기 위해 세부 정보를 입력해야 하는 곳에 &quot;YOUR CODE GOES HERE&quot;라는 주석을 친절하게 추가했습니다.</p>
<blockquote>
<p>당신의 임무:
첫 번째 단계로, 고객이 새 거래를 할 때마다 Amazon DynamoDB 테이블에서 총 거래 가치와 고객 상태를 업데이트하는 AWS Lambda 함수를 완료해야 합니다 CustProfile. 아래의 인벤토리 섹션은 Lambda 함수의 이름과 DynamoDB 테이블의 스키마를 제공합니다. 이 정보를 사용하여 작업을 완료합니다. Lambda 함수를 업데이트하면 아래의 작업 검증 섹션에 있는 테스트 이벤트를 사용하여 함수를 테스트합니다.</p>
</blockquote>
<h3 id="첫번째-어려운점">첫번째 어려운점</h3>
<p>람다식을 배우지 않아서 이것에 대해 학습하는 시간이 매우 오래 걸렸습니다.</p>
<h3 id="두번째-어려운점">두번째 어려운점</h3>
<p>어떻게 DB스키마를 제공받아 업데이트 하는지에 대한 부분이 어려웠습니다.</p>
<h3 id="세번째-어려운점">세번째 어려운점</h3>
<p>누락된 부분의 코드를 어떻게 채워 나가야하는지에 대해 어려웠습니다.</p>
<h1 id="해결한-과정">해결한 과정</h1>
<h3 id="첫번째-해결-과정은">첫번째 해결 과정은</h3>
<p>최대한 간단하게 이해하고 내 스스로 약간의 이해라도 한번 부딪혀 보자라는 부분에 맞춰 팀원들과 부분 나눠 공부를 하고 바로 진행을 했습니다.</p>
<h3 id="두번째-해결-과정은">두번째 해결 과정은</h3>
<p>구글링을 하면서 이부분 저부분 활용을 하면서 이건 왜 이렇게 사용해야하고 저건 왜 이렇게 사용해야 하는지 팀원들과 얘기를 통해 조율을 해나갔습니다.</p>
<h3 id="세번째-해결-과정은">세번째 해결 과정은</h3>
<p>하나 하나 뜯어보면서 이부분이 요구 부분에 있어 어떤 부분 이 필요할 까 에 대한 부분과 서로의 구글링을 통해 맞춰 해결과정이 꽤나 어려웠지만 그래도 다행히 잘 해결해 나간 부분에서 뿌듯했습니다.</p>
<h1 id="마무리">마무리</h1>
<p>오늘 AWS사옥투어를 하면서 느낀점은 서울은 신기한 건물이 많고 
AWS 학습에 대해 전반적인 부족함이 많다는걸 느꼈습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OAuth 2.0으로 소셜 로그인 구현하기 - (Kakao)]]></title>
            <link>https://velog.io/@sangmin0310-afk/OAuth-2.0%EC%9C%BC%EB%A1%9C-%EC%86%8C%EC%85%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-Kakao</link>
            <guid>https://velog.io/@sangmin0310-afk/OAuth-2.0%EC%9C%BC%EB%A1%9C-%EC%86%8C%EC%85%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-Kakao</guid>
            <pubDate>Wed, 04 Sep 2024 05:28:59 GMT</pubDate>
            <description><![CDATA[<h1 id="oauth20의-개념">OAuth2.0의 개념</h1>
<h3 id="oauth20이란-무엇인가요">OAuth2.0이란 무엇인가요?</h3>
<p>OAuth 2.0(Open Authorization 2.0)은 인터넷 사용자들이 비밀번호를 공유하지 않고도 자신이 사용하는 서비스 간에 안전하게 자격 증명을 위임할 수 있게 해주는 업계 표준 프로토콜입니다.</p>
<h3 id="oauth20의-구성-요소">OAuth2.0의 구성 요소</h3>
<ol>
<li>Resource Owner (리소스 소유자):
자원에 대한 소유자이며, 일반적으로 최종 사용자(End User)입니다.</li>
<li>Client (클라이언트):
리소스 소유자를 대신하여 자원 서버에 접근을 요청하는 애플리케이션입니다.</li>
<li>Authorization Server (인가 서버):
클라이언트의 접근 요청을 인증하고 승인하는 서버입니다.</li>
<li>Resource Server (자원 서버):
보호된 자원(데이터)을 호스팅하는 서버입니다.</li>
<li>Access Token (액세스 토큰):
인가 서버가 클라이언트에게 발급하는 자격 증명으로, 클라이언트가 자원 서버에 접근할 수 있는 권한을 증명합니다.</li>
</ol>
<h3 id="oauth20의-흐름-과정">OAuth2.0의 흐름 과정</h3>
<ol>
<li><p>클라이언트가 인가 코드를 요청:
사용자가 클라이언트(애플리케이션)를 통해 자원에 접근하려고 하면, 클라이언트는 인가 서버로 사용자를 리디렉션합니다.
클라이언트는 클라이언트 ID, 리디렉션 URI, 응답 유형(response type) 등을 포함한 요청을 인가 서버에 보냅니다.</p>
</li>
<li><p>사용자 인증 및 승인:
인가 서버는 사용자에게 로그인 및 권한 부여를 요청합니다.
사용자가 성공적으로 로그인하고 클라이언트에 대한 접근을 승인하면, 인가 서버는 클라이언트에 사전 등록된 리디렉션 URI로 인가 코드를 전달합니다.</p>
</li>
<li><p>클라이언트가 액세스 토큰 요청:
클라이언트는 받은 인가 코드를 사용하여 인가 서버에 액세스 토큰을 요청합니다.
이 요청에는 인가 코드, 클라이언트 ID, 클라이언트 시크릿, 리디렉션 URI 등이 포함됩니다.</p>
</li>
<li><p>인가 서버가 액세스 토큰 발급:
인가 서버는 클라이언트를 인증하고 요청이 유효한지 확인한 후, 액세스 토큰과 (선택적으로) 리프레시 토큰을 발급합니다.</p>
</li>
<li><p>클라이언트가 자원 서버에 요청:
클라이언트는 액세스 토큰을 사용하여 자원 서버에 보호된 자원에 대한 접근을 요청합니다.
자원 서버는 액세스 토큰의 유효성을 검증한 후 요청된 자원을 반환합니다.</p>
</li>
</ol>
<h3 id="인가코드authorization-code란-무엇인가요">인가코드(Authorization Code)란 무엇인가요?</h3>
<p><strong>인가 코드(Authorization Code)</strong> 는 OAuth 2.0 프로토콜에서 클라이언트 애플리케이션이 인가 서버로부터 액세스 토큰을 얻기 위해 사용하는 임시 코드입니다. 
인가 코드는 클라이언트가 리소스 소유자의 권한을 받아 인가 서버에서 발급하는 것이며, 짧은 시간 동안만 유효합니다.</p>
<h1 id="oauth-20을-사용한-카카오-로그인-인증하기">OAuth 2.0을 사용한 카카오 로그인 인증하기</h1>
<h3 id="-애플리케이션-등록--로그인-과정까지의-블로깅-→-실제-코드-예제와-설명을-함께-작성해-주세요">• 애플리케이션 등록 ~ 로그인 과정까지의 블로깅 → 실제 코드 예제와 설명을 함께 작성해 주세요.</h3>
<p>login.js</p>
<pre><code>// Kakao SDK 초기화
Kakao.init(&#39;W8UWxgWBRXANaWQ86xKC9IKGYol8l7Jf&#39;); // 실제 JavaScript 키 사용
console.log(Kakao.isInitialized()); // 초기화 확인 (true 출력)</code></pre><p>Kakao.init(): Kakao SDK를 초기화합니다. 
애플리케이션 등록 시 발급받은 JavaScript 키를 사용하여 SDK를 설정합니다.
Kakao.isInitialized(): SDK 초기화 여부를 확인합니다. 
true가 출력되면 초기화가 성공적으로 완료된 것입니다.</p>
<pre><code>// 버튼 요소 선택
const kakaoLoginButton = document.querySelector(&#39;#kakaologinbtn&#39;);
const userImage = document.querySelector(&#39;#user_image&#39;);
const userName = document.querySelector(&#39;#user_name&#39;);
const logoutButton = document.querySelector(&#39;#logout-btn&#39;);

const redirectURI = &#39;http://127.0.0.1:5500&#39;; 

// 로그인 버튼 클릭 이벤트 핸들러
kakaoLoginButton.onclick = () =&gt; {
    Kakao.Auth.authorize({
        redirectUri: redirectURI 
    });
};</code></pre><p>kakaoLoginButton.onclick: 로그인 버튼 클릭 시 Kakao 로그인 페이지로 리디렉션합니다. 
로그인 후 redirectURI로 돌아오게 됩니다.</p>
<pre><code>// 페이지 로드 후 Authorization Code 확인
window.onload = () =&gt; {
    const url = new URL(window.location.href);
    const urlParams = url.searchParams;
    const authorizationCode = urlParams.get(&#39;code&#39;);

    if (authorizationCode) {
        console.log(&#39;Authorization Code:&#39;, authorizationCode);

        // 서버로 Authorization Code를 전달하여 Access Token 요청
        axios.post(&#39;http://localhost:3000/kakao/login&#39;, {
            authorizationCode: authorizationCode
        })
        .then(response =&gt; {
            console.log(&#39;User Info:&#39;, response.data);
            userName.textContent = response.data.nickname;
            userImage.src = response.data.profile_image;
        })
        .catch(error =&gt; {
            console.error(&#39;Error fetching user info:&#39;, error);
        });
    }
};</code></pre><p>window.onload: 페이지가 로드되면 현재 URL에서 Authorization Code를 추출합니다.
axios.post(): 서버로 Authorization Code를 전송하여 Access Token을 요청합니다.
응답 처리: 서버에서 받은 사용자 정보를 페이지에 표시합니다.</p>
<p>server.js</p>
<pre><code>const express = require(&#39;express&#39;);
const cors = require(&#39;cors&#39;);
const axios = require(&#39;axios&#39;);

const app = express();

app.use(cors({
    origin: [&#39;http://localhost:5500&#39;, &#39;http://127.0.0.1:5500&#39;],
    methods: [&quot;OPTIONS&quot;, &quot;POST&quot;, &quot;DELETE&quot;],
}));

app.use(express.json());

const kakaoClientId = &#39;W8UWxgWBRXANaWQ86xKC9IKGYol8l7Jf&#39;; // 실제 JavaScript 키 사용
const redirectURI = &#39;http://127.0.0.1:5500&#39;; 
const clientSecret = &#39;&#39;; </code></pre><p>Express 설정: Express 서버를 설정하고 CORS를 사용하여 특정 도메인에서의 요청을 허용합니다.
kakaoClientId, redirectURI: Kakao 로그인 설정에 필요한 클라이언트 ID와 리디렉션 URI를 설정합니다.
clientSecret: 필요 시 클라이언트 비밀키를 설정합니다.</p>
<pre><code>app.post(&#39;/kakao/login&#39;, async (req, res) =&gt; {
    const authorizationCode = req.body.authorizationCode;

    try {
        // Access Token 요청
        const tokenResponse = await axios.post(&#39;https://kauth.kakao.com/oauth/token&#39;, null, {
            params: {
                grant_type: &#39;authorization_code&#39;,
                client_id: kakaoClientId,
                redirect_uri: redirectURI,
                code: authorizationCode,
                client_secret: clientSecret, 
            },
            headers: {
                &#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;
            }
        });

        const accessToken = tokenResponse.data.access_token;

        // 사용자 정보 요청
        const userResponse = await axios.get(&#39;https://kapi.kakao.com/v2/user/me&#39;, {
            headers: {
                &#39;Authorization&#39;: `Bearer ${accessToken}`
            }
        });

        const userInfo = userResponse.data;
        res.json({
            nickname: userInfo.properties.nickname,
            profile_image: userInfo.properties.profile_image
        });

    } catch (error) {
        console.error(&#39;Error during Kakao login process:&#39;, error);
        res.status(500).json({ message: &#39;Internal Server Error&#39; });
    }
});</code></pre><p>/kakao/login 엔드포인트: 클라이언트에서 받은 Authorization Code를 사용하여 Kakao의 Access Token을 요청합니다.
Access Token 요청: axios.post()를 사용하여 Kakao의 OAuth 서버에 Access Token을 요청합니다.
사용자 정보 요청: Access Token을 사용하여 Kakao API로부터 사용자 정보를 가져옵니다.
에러 처리: 에러가 발생하면 서버가 500 상태 코드와 함께 에러 메시지를 반환합니다.</p>
<pre><code>app.listen(3000, () =&gt; console.log(&#39;서버 열림!&#39;));</code></pre><p>서버 시작: Express 서버를 포트 3000에서 실행합니다.</p>
<h3 id="각-실행-결과에-알맞는-결과도-캡쳐하여-함께-업로드-해주세요">각 실행 결과에 알맞는 결과도 캡쳐하여 함께 업로드 해주세요.</h3>
<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/22b3a3a1-7219-4f80-9372-59a67d8859f6/image.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NEXT.js 간단정리]]></title>
            <link>https://velog.io/@sangmin0310-afk/NEXT.js-%EA%B0%84%EB%8B%A8%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@sangmin0310-afk/NEXT.js-%EA%B0%84%EB%8B%A8%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 20 Aug 2024 14:29:09 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs의-핵심-개념-이해하기-리액트를-기반으로-한-웹-개발-프레임워크">Next.js의 핵심 개념 이해하기: 리액트를 기반으로 한 웹 개발 프레임워크</h1>
<h3 id="nextjs란">Next.js란?</h3>
<p>Next.js는 풀스택 웹 애플리케이션을 빌드하기 위한 React 프레임워크입니다. </p>
<p>React Components를 사용하여 사용자 인터페이스를 빌드하고 Next.js를 사용하여 추가 기능과 최적화를 구현합니다.</p>
<p>후드 아래에서 Next.js는 번들링, 컴파일 등과 같이 React에 필요한 툴링을 추상화하고 자동으로 구성합니다.</p>
<h3 id="서버사이드-렌더링ssr과-클라이언트사이드-렌더링csr-설명">서버사이드 렌더링(SSR)과 클라이언트사이드 렌더링(CSR) 설명</h3>
<p>웹 개발에서 페이지를 렌더링하는 방식은 크게 서버 사이드 렌더링(SSR)과 클라이언트 사이드 렌더링(CSR)으로 나뉩니다. </p>
<p>서버 사이드 렌더링은 서버에서 HTML을 생성하여 클라이언트로 전송하는 방식이며</p>
<p>클라이언트 사이드 렌더링은 클라이언트에서 JavaScript를 사용하여 동적으로 HTML을 생성하는 방식입니다.</p>
<h3 id="nextjs의-프리랜더링-방식">Next.js의 프리랜더링 방식</h3>
<h3 id="프리렌더링이란">프리렌더링이란?</h3>
<p>프리렌더링(Pre-rendering)은 웹 페이지의 HTML을 서버에서 미리 생성하는 작업을 말합니다. 
이를 통해 브라우저에서 페이지를 렌더링하는 시점에 이미 필요한 HTML이 준비되어 있게 되므로 
사용자에게 웹 페이지의 내용을 빠르게 제공할 수 있게 됩니다.
 React 프로젝트를 Next.js를 통해 프리렌더링을 하면 빈 HTML 대신 프리렌더링된 HTML 파일을 제공하므로 검색엔진 최적화가 가능합니다.</p>
<h3 id="프리렌더링-방식">프리렌더링 방식</h3>
<ul>
<li>정적 생성(Static Generation): 이 방식은 빌드 타임에 모든 필요한 HTML을 미리 생성합니다. 
각 페이지는 빌드 타임에 콘텐츠를 불러와 HTML을 생성하며, 이 HTML은 사용자가 페이지를 요청할 때마다 재사용됩니다. 이 방식은 콘텐츠가 사용자에 따라 달라지지 않는 사이트에 적합합니다.</li>
<li>서버-사이드 렌더링 (Server-Side Rendering, SSR): 이 방식은 사용자가 페이지를 요청할 때마다 HTML을 
생성합니다. 이는 콘텐츠가 자주 업데이트되거나 각 사용자에게 개별적으로 맞춤화된 콘텐츠를 제공해야 하는 사이트에 적합합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[문제풀이(오답노트)]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</link>
            <guid>https://velog.io/@sangmin0310-afk/%EB%AC%B8%EC%A0%9C%ED%92%80%EC%9D%B4%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8</guid>
            <pubDate>Tue, 20 Aug 2024 08:21:40 GMT</pubDate>
            <description><![CDATA[<p>전체문제 다시 다 하겠습니다.</p>
<blockquote>
</blockquote>
<p>1/20 Multiple choice 다음 중 Tailwind CSS를 사용하여 글자 색상을 설정하는 클래스는 무엇인가요? (5pt)
text-red-500
bg-red-500
border-red-500
hover:text-red-500</p>
<p>문제풀이
<strong>a. text-red-500 - 이 클래스는 텍스트(글자)의 색상을 빨간색으로 설정합니다. 
text- 접두사는 텍스트 색상을 설정하는 클래스임을 의미하며, red-500은 색상의 구체적인 톤을 나타냅니다.</strong></p>
<p>b. bg-red-500 - 이 클래스는 배경 색상을 빨간색으로 설정합니다. 
bg- 접두사는 배경 색상을 설정하는 클래스임을 나타냅니다.</p>
<p>c. border-red-500 - 이 클래스는 테두리 색상을 빨간색으로 설정합니다. border- 접두사는 테두리 색상을 설정하는 클래스임을 나타냅니다.</p>
<p>d. hover:text-red-500 - 이 클래스는 마우스 오버 시 텍스트 색상을 빨간색으로 설정합니다. 
hover: 접두사는 호버 상태에서 스타일이 적용된다는 것을 의미합니다.</p>
<blockquote>
</blockquote>
<p>2/20 Multiple choice 다음 중 Styled Components의 장점이 아닌 것은 무엇인가요? (5pt)
CSS-in-JS 방식으로 스타일링 가능
컴포넌트 기반으로 스타일을 캡슐화
스타일 시트의 전역 네임스페이스 오염 방지
브라우저 호환성을 자동으로 보장</p>
<p>문제풀이
a. Styled Components의 핵심 장점 중 하나입니다. 
CSS-in-JS 방식은 JavaScript 파일 내에서 직접 CSS를 작성할 수 있게 해 주며 스타일을 컴포넌트와 함께 정의할 수 있습니다.</p>
<p>b. Styled Components는 각 컴포넌트에 대한 스타일을 정의하고 
스타일을 해당 컴포넌트와 연결함으로써 스타일을 캡슐화합니다. 
스타일 캡슐화를 하는 이유는 코드의 재사용성과 유지보수성을 높이고 
스타일 충돌을 방지합니다.</p>
<p>c. Styled Components는 각 컴포넌트에 대해 고유한 클래스를 생성하여 전역 네임스페이스의 오염을 방지합니다. 이는 스타일 충돌을 줄이고, 각각의 컴포넌트가 독립적으로 스타일을 관리할 수 있게 합니다.</p>
<p><strong>d. Styled Components는 CSS-in-JS의 방식으로 스타일을 정의하는 도구일 뿐 (브라우저 호환성을 자동으로 보장하지는 않습니다.)</strong></p>
<blockquote>
</blockquote>
<p>3/20 Multiple choice Styled Components와 Tailwind CSS의 주요 차이점은 무엇인가요? (5pt)
Tailwind CSS는 클래스 유틸리티 기반이며, Styled Components는 CSS-in-JS 기반입니다.
Tailwind CSS는 주로 전역 스타일을 다루며, Styled Components는 컴포넌트별 스타일을 다룹니다.
Tailwind CSS는 CSS를 별도로 작성하지 않고도 스타일을 적용할 수 있습니다.
Styled Components는 자바스크립트 파일 내에서 CSS를 작성하지 못합니다.</p>
<p>문제풀이
a. Tailwind CSS는 클래스 유틸리티 기반이며, Styled Components는 CSS-in-JS 기반입니다.(정답)
이유: Tailwind CSS는 클래스 유틸리티 기반의 프레임워크로 
<strong>사전에 정의된 유틸리티 클래스를 HTML 요소에 적용하여 스타일을 설정합니다.</strong>
Styled Components는 CSS-in-JS 라이브러리로 
<strong>JavaScript 파일 내에서 직접 CSS를 작성하여 컴포넌트에 스타일을 적용합니다.</strong></p>
<p>b.Tailwind CSS는 주로 전역 스타일을 다루며, Styled Components는 컴포넌트별 스타일을 다룹니다.(오류)
Tailwind CSS는 전역 스타일을 사용하는 것이 아니라 전역에서 <code>정의된</code> 유틸리티 클래스를 통해 스타일을 적용합니다. 
Styled Components는 각 컴포넌트별로 스타일을 정의하여 컴포넌트 내에서만 스타일을 적용합니다.</p>
<p>c. Tailwind CSS는 CSS를 별도로 작성하지 않고도 스타일을 적용할 수 있습니다.(오류)
Tailwind CSS는 CSS를 별도로 작성하지 않고도 미리 정의된 유틸리티 클래스를 사용하여 스타일을 적용할 수 있지만 이 설명은 주로 Tailwind의 스타일 적용 방식에 대한 설명이지 차이점 과는 맞지않는 설명입니다. </p>
<p>d. Styled Components는 자바스크립트 파일 내에서 CSS를 작성하지 못합니다. </p>
<blockquote>
</blockquote>
<p>4/20 Multiple choice 다음 중 SCSS에서 변수를 정의하고 사용하는 방법으로 옳은 것은 무엇인가요? (5pt)
$color: red; background-color: $color;
var color = red; background-color: var(color);
--color: red; background-color: var(--color);
color: red; background-color: $color;</p>
<p>문제풀이
a. <strong>SCSS에서 변수를 정의하려면 $ 기호를 사용합니다. 
$color: red;는 변수를 정의하며 background-color: $color;는<br>변수를 사용하여 배경색을 설정합니다.</strong></p>
<p>b. SCSS에서는 변수를 정의할 때 $ 기호를 사용합니다. 
CSS Custom Properties에서 변수를 사용하려면 -- 접두사를 사용해야 합니다.</p>
<p>c. var(--color)를 사용하여 변수를 참조하는 것은 CSS에서의 방식입니다.</p>
<p>d. SCSS에서는 변수를 정의할 때 $ 기호를 사용하지만 
CSS에서는 color: red;와 같은 구문을 사용합니다. 
변수를 사용하기 위해서는 SCSS 문법에 맞게 $color를 정의하고 사용해야 합니다.</p>
<blockquote>
<p>5/20 Multiple choice props drilling을 피하기 위해 선택할 수 있는 가장 적절한 해결책은 무엇인가요? (5pt)
상위 컴포넌트에서 모든 상태를 관리하고, 모든 하위 컴포넌트에서 직접 props로 전달한다.
상위 컴포넌트에서 상태를 관리하고, 상태를 변경할 때마다 하위 컴포넌트를 새로 렌더링한다.
Context API 또는 상태 관리 라이브러리(Redux, MobX 등)를 사용하여 전역 상태를 관리한다.
하위 컴포넌트에서 상태를 직접 관리하고 상위 컴포넌트와의 데이터 전달을 최소화한다.</p>
</blockquote>
<p>문제풀이
a. 상위 컴포넌트가 모든 상태를 관리하고 여러 하위 컴포넌트에 props로 전달하면 컴포넌트 트리가 깊어질수록 전달해야 하는 props가 많아져서 코드가 복잡해지고 유지보수가 어려워질 수 있습니다.</p>
<p>b.상태를 변경할 때마다 하위 컴포넌트를 새로 렌더링하는 것은 성능에 영향을 줄 수 있지만, props drilling 문제를 직접적으로 해결하지는 않습니다.</p>
<p>c. <strong>Context API나 상태 관리 라이브러리를 사용하면 컴포넌트 트리의 깊이에 상관없이 필요한 컴포넌트가 상태에 접근할 수 있습니다.
props drilling 문제를 피할 수 있으며, 상태를 더 중앙 집중식으로 관리할 수 있습니다.</strong></p>
<p>d. 상태가 필요한 모든 컴포넌트에서 직접 상태를 관리하게 되어 코드의 복잡성을 증가시킬 수 있습니다.</p>
<blockquote>
<p>6/20 Multiple choice Redux에서 상태를 변경하는 함수는 무엇인가요? (5pt)
Reducer
Action
Middleware
Store</p>
</blockquote>
<p>문제풀이
a. <strong>Reducer는 현재의 상태와 액션을 입력으로 받아서 새로운 상태를 반환합니다. 
상태를 직접 변경하지 않고, 새로운 상태 객체를 반환하는 불변성을 유지하는 방식으로 동작합니다.</strong></p>
<p>b. Action은 상태를 직접 변경하지 않지만 Reducer에 전달되어 상태를 변경하는 데 필요한 정보를 제공합니다.</p>
<p>c. Middleware는 상태를 직접 변경하지 않으며 액션이 Reducer에 도달하기 전에 중간에서 처리할 수 있는 기능을 제공합니다.</p>
<p>d. Store는 Reducer와 Action을 결합하여 상태를 관리하지만 직접 상태를 변경하는 함수는 아닙니다. 
Store는 상태를 저장하고, 액션을 디스패치하고, 상태를 구독하는 역할을 합니다.</p>
<blockquote>
</blockquote>
<p>7/20 Multiple choice Redux에서 비동기 작업을 처리하기 위해 주로 사용하는 미들웨어는 무엇인가요? (5pt)
thunk
saga
logger
promise</p>
<p>문제풀이
a. <strong>redux-thunk를 사용하면 액션 생성자에서 함수를 반환할 수 있으며 
함수는 비동기 작업을 수행하고 작업이 완료된 후에 디스패치할 액션을 생성할 수 있습니다.</strong></p>
<p>b. redux-saga는 제너레이터 함수(generator functions)를 사용하여 복잡한 비동기 로직을 관리합니다. </p>
<p>c. 비동기 작업과 관련된 처리를 지원하지 않으며 상태 변경을 모니터링하는 데 사용됩니다.</p>
<p>d. 액션이 프로미스를 포함할 때 프로미스가 해결될 때까지 기다렸다가 결과를 액션으로 디스패치합니다. </p>
<blockquote>
</blockquote>
<p>8/20 Sorting Flux 패턴의 데이터 흐름 순서를 올바른 순서로 나열하세요. (5pt)
Action
Store
View
Dispatcher</p>
<p>문제풀이
Action
설명: 사용자의 인터랙션이나 이벤트를 통해 애플리케이션의 상태를 변경하기 위해 생성되는 객체입니다.</p>
<p>Dispatcher
설명: Action을 받아서 Store에 전달하는 역할을 합니다. 
Dispatcher는 모든 Action을 중앙 집중식으로 관리하며 
각 Store에 Action을 분배합니다.</p>
<p>Store
설명: 애플리케이션의 상태와 비즈니스 로직을 관리하는 곳입니다. 
Store는 Action을 받아서 상태를 업데이트하고 
상태가 변경되면 View에 알립니다.</p>
<p>View
설명: 사용자에게 보여지는 UI 컴포넌트입니다. View는 Store의 상태를 기반으로 UI를 렌더링합니다.</p>
<p>Action → Dispatcher → Store → View</p>
<blockquote>
<p>9/20 Fill in the blank 다음 코드에서 Redux Toolkit을 사용하여 increment 액션을 호출할 때 상태의 value 값을 1 증가시키도록 리듀서를 완성하세요.</p>
</blockquote>
<pre><code>import { createSlice } from &#39;@reduxjs/toolkit&#39;;

const counterSlice = createSlice({
    name: &#39;counter&#39;,
    initialState: { value: 0 },
    reducers: {
        increment: (state) =&gt; {
           __(A)__.__(B)__ +=__(C)__;
        }
    }
});

export const { increment } = counterSlice.actions;

export default counterSlice.reducer; 
</code></pre><p>문제풀이
state: createSlice에서 정의한 initialState 객체를 포함한 현재 상태를 나타냅니다. state는 여기서 직접 변경할 수 있습니다.</p>
<p>state.value: initialState에 정의된 value 필드를 참조합니다. 
상태의 value 필드를 직접 접근하여 값을 변경할 수 있습니다.</p>
<p>+= 1: 상태의 value 값을 1 증가시키는 연산입니다.</p>
<pre><code>import { createSlice } from &#39;@reduxjs/toolkit&#39;;

const counterSlice = createSlice({
    name: &#39;counter&#39;,
    initialState: { value: 0 },
    reducers: {
        increment: (state) =&gt; {
           state.value += 1;
        }
    }
});

export const { increment } = counterSlice.actions;

export default counterSlice.reducer; </code></pre><blockquote>
</blockquote>
<p>10/20 Multiple choice 다음 중 Redux의 필수 구성 요소가 아닌 것은 무엇인가요? (5pt)
Action
Reducer
Selector
Store</p>
<p>문제풀이
Action
설명: Action은 상태를 변경하기 위한 &quot;명령&quot;을 나타내는 객체입니다. 
일반적으로 type과 필요한 데이터를 포함하며 Reducer에 전달되어 상태 변경을 요청합니다.</p>
<p>Reducer
설명: Reducer는 현재의 상태와 Action을 입력으로 받아 새로운 상태를 반환하는 함수입니다. 
Reducer는 상태 업데이트의 로직을 담당합니다. 
Redux에서 상태를 변경하는 핵심 요소입니다.</p>
<p>Store
설명: Store는 애플리케이션의 상태를 보관하고 상태를 업데이트할 수 있는 
메소드를 제공합니다. 
Redux의 상태를 중앙에서 관리하고, Action을 디스패치하며, 상태 변화를 구독할 수 있게 합니다.</p>
<p>Selector
설명: Selector는 상태에서 특정 데이터를 추출하는 함수입니다. 
Selector는 Redux의 <code>필수 구성 요소는 아니지만</code> 상태를 선택하고 가공하는 데 유용한 도구입니다. </p>
<blockquote>
<p>11/20 Multiple choice React에서 동일한 함수가 반복해서 생성되지 않도록 하고, 자식 컴포넌트에 함수가 props로 전달될 때 불필요한 리렌더링을 방지하기 위해 어떤 Hook을 사용할 수 있을까요? (5pt)
useEffect
useMemo
useCallback
useState</p>
</blockquote>
<p>문제풀이
useEffect
설명: useEffect는 컴포넌트가 렌더링된 후에 수행할 부수 효과(side effects)를 정의하는 데 사용됩니다. 
비동기 데이터 로딩, 이벤트 구독, 타이머 설정 등이 이 Hook을 통해 이루어집니다.</p>
<p>useMemo
설명: useMemo는 계산된 값을 메모이제이션(memoization)하여 불필요한 계산을 방지하는 데 사용됩니다. 특정 값이 변경될 때만 계산을 다시 수행하고, 그렇지 않으면 이전 계산 결과를 재사용합니다. </p>
<p><strong>useCallback
정답: useCallback은 함수의 참조를 메모이제이션하여, 의존성 배열에 명시된 값이 변경될 때만 함수를 재생성합니다. 
자식 컴포넌트에 전달되는 함수가 불필요하게 새로 생성되지 않도록 하고 자식 컴포넌트의 불필요한 리렌더링을 방지할 수 있습니다.</strong></p>
<p>useState
설명: useState는 상태를 관리하는 Hook으로 컴포넌트의 상태 값을 저장하고 업데이트하는 데 사용됩니다. </p>
<blockquote>
<p>12/20 Multiple choice 다음 중 useMemo를 사용해야 하는 상황은 언제인가요? (5pt)
비동기 데이터 가져오기
복잡한 계산 결과 캐싱
DOM 요소 참조
타이머 설정</p>
</blockquote>
<p>문제풀이
비동기 데이터 가져오기는 useEffect를 사용하여 처리합니다.</p>
<p><strong>useMemo는 주로 복잡한 계산 결과를 메모이제이션하는 데 사용됩니다. 
특정 의존성 배열이 변경될 때만 계산을 다시 수행하고 그렇지 않으면 이전 계산 결과를 재사용하여 렌더링 성능을 개선합니다. 
복잡한 계산이나 비싼 연산이 필요한 경우에 useMemo를 사용하는 것이 적절합니다.</strong></p>
<p>DOM 요소를 참조하거나 조작하려면 useRef를 사용합니다.</p>
<p>타이머를 설정하거나 관리하려면 useEffect를 사용합니다.</p>
<blockquote>
</blockquote>
<p>13/20 Multiple choice 다음 중 useMemo와 React.memo의 차이에 대한 설명으로 가장 적절한 것은 무엇인가요? (5pt)
useMemo는 컴포넌트 자체의 리렌더링을 막고, React.memo는 계산된 값을 메모이제이션합니다.
useMemo는 값의 메모이제이션을 제공하며, React.memo는 컴포넌트의 불필요한 리렌더링을 방지합니다.
useMemo는 비동기 작업을 처리하며, React.memo는 상태를 관리합니다.
useMemo는 함수 컴포넌트에서만 사용 가능하며, React.memo는 클래스 컴포넌트에서만 사용 가능합니다.</p>
<p>문제풀이
useMemo는 값의 메모이제이션을 제공하며 리렌더링을 막지는 않습니다. React.memo는 컴포넌트의 메모이제이션을 통해 불필요한 리렌더링을 방지합니다. </p>
<p><strong>useMemo는 특정 계산 결과를 메모이제이션하여 컴포넌트의 리렌더링 시에 해당 계산을 다시 수행하지 않도록 합니다. 
React.memo는 컴포넌트를 메모이제이션하여 props가 변경되지 않는 한 컴포넌트가 다시 렌더링되지 않도록 합니다. 
useMemo는 값의 메모이제이션을 처리하고 React.memo는 컴포넌트의 불필요한 리렌더링을 방지합니다.</strong></p>
<p>useMemo는 비동기 작업을 처리하지 않으며 비동기 작업은 useEffect로 처리합니다. 
React.memo는 상태를 관리하지 않으며 컴포넌트의 리렌더링을 최적화하는 데 사용됩니다.</p>
<p>useMemo는 함수 컴포넌트에서 사용되며 React.memo는 함수 컴포넌트에 대해 메모이제이션을 제공하는 기능을 합니다. 
클래스 컴포넌트에서의 메모이제이션은 shouldComponentUpdate를 사용하여 관리합니다.</p>
<blockquote>
<p>14/20 Multiple choice 다음 중 
thro≤과 debounce의 차이에 대한 설명으로 가장 적절한 것은 무엇인가요? 
thro≤은 마지막 이벤트 이후 일정 시간 동안 함수를 실행하지 않지만, debounce는 일정 간격마다 함수를 실행합니다.
thro≤은 이벤트가 발생한 마지막 시점에 함수를 실행하지만, debounce
는 이벤트 발생 간격을 기준으로 함수를 실행합니다.
thro≤은 일정 시간 간격으로 이벤트를 제한하지만, debounce
는 마지막 이벤트가 발생한 후 일정 시간 동안 추가 이벤트가 없을 때 함수를 실행합니다.
thro≤과 debounce는 동일하게 작동하며, 둘 다 실시간 검색 기능에서 사용됩니다.</p>
</blockquote>
<p>문제풀이
throttle은 일정 간격마다 함수를 실행하고 debounce는 마지막 이벤트 이후 일정 시간 동안 추가 이벤트가 없을 때 함수를 실행합니다.</p>
<p>throttle은 이벤트 발생 간격을 기준으로 함수를 실행하며 debounce는 마지막 이벤트 후 일정 시간 동안 추가 이벤트가 없을 때 함수를 실행합니다.</p>
<p><strong>throttle은 일정 시간 간격으로 이벤트 핸들러를 호출하여 이벤트 호출 빈도를 제한하고 debounce는 마지막 이벤트 이후 일정 시간이 지나면 핸들러를 실행하여 추가 이벤트가 없을 때만 호출합니다.</strong></p>
<p>throttle과 debounce는 서로 다른 방식으로 작동하며 실시간 검색 기능에서는 보통 debounce를 사용하여 입력이 끝난 후 검색을 수행하는 것이 일반적입니다.</p>
<blockquote>
<p>15/20 Multiple choice 
React.lazy는 어떤 상황에서 사용하나요? 
상태 관리(store)를 초기화할 때
컴포넌트를 동적으로 로드할 때
사용자의 입력을 제한할 때
컴포넌트에서 함수 호출을 제한할 때</p>
</blockquote>
<p>문제풀이
상태 관리(store)를 초기화하는 것은 useState, useReducer 또는 상태 관리 라이브러리의 설정과 관련이 있습니다. 
React.lazy는 상태 관리와 관련이 없습니다.</p>
<p><strong>React.lazy는 컴포넌트를 동적으로 로드하는 데 사용됩니다. 
초기 로딩 시점에서 필요하지 않은 컴포넌트는 로드하지 않고 필요할 때만 로드하여 성능을 최적화합니다.</strong></p>
<p>사용자 입력을 제한하는 것은 useEffect, useState, 또는 입력 제어 컴포넌트를 통해 처리합니다. 
React.lazy는 입력 제어와 관련이 없습니다.</p>
<p>컴포넌트에서 함수 호출을 제한하는 것은 useCallback, useMemo 등의 Hook을 통해 처리할 수 있습니다. 
React.lazy는 함수 호출을 제한하는 기능과는 관련이 없습니다.</p>
<blockquote>
<p>16/20 Multiple choice React에서 느리게 로드되는 비동기 컴포넌트를 처리하고, 해당 컴포넌트가 로드되는 동안 로딩 UI를 표시하기 위해 어떤 것을 사용할 수 있을까요? (5pt)
useEffect
Suspense
useReducer
Context API</p>
</blockquote>
<p>문제풀이
useEffect
설명: useEffect는 컴포넌트가 렌더링된 후에 부수 효과(side effects)를 수행하는 데 사용됩니다. 
데이터 페칭, DOM 업데이트, 구독 등의 작업에 유용하지만, 비동기 컴포넌트 로딩과 로딩 UI 표시를 처리하는 데는 사용되지 않습니다.</p>
<p><strong>Suspense
설명: Suspense는 비동기 컴포넌트 로딩을 처리하고 로딩 상태에 대한 UI를 표시하는 데 사용됩니다. 
React.lazy와 함께 사용되어 컴포넌트가 로드되는 동안 로딩 스피너 또는 다른 로딩 UI를 표시할 수 있습니다. 
Suspense는 비동기적으로 컴포넌트를 로드하고 로딩 상태를 관리할 수 있도록 도와줍니다.</strong></p>
<p>useReducer
설명: useReducer는 컴포넌트의 상태를 관리하고 복잡한 상태 로직을 처리하는 데 사용됩니다. 
상태 관리와 관련된 기능을 제공하지만 비동기 컴포넌트 로딩과 로딩 UI 표시와는 관련이 없습니다.</p>
<p>Context API
설명: Context API는 컴포넌트 트리에서 전역 상태를 공유하는 데 사용됩니다. 
상태 공유와 관련된 기능을 제공하지만 비동기 컴포넌트 로딩과 로딩 UI 표시를 처리하는 데는 사용되지 않습니다.</p>
<blockquote>
</blockquote>
<p>17/20 Multiple choice React에서 상태 업데이트 시 불변성 관리를 해야 하는 가장 중요한 이유는 무엇인가요? (5pt)
상태 업데이트를 동기적으로 처리하기 위해
상태 업데이트가 자동으로 전역에 반영되기 위해
컴포넌트의 리렌더링이 발생하도록 하기 위해
상태 변경이 컴포넌트 간에 공유되기 위해</p>
<p>문제풀이
React의 상태 업데이트는 비동기적으로 처리될 수 있으며, 불변성 관리와 직접적인 관계는 없습니다.</p>
<p>상태가 전역에 반영되는 것은 상태 관리 라이브러리나 React의 상태 관리 방식과 관련이 있습니다.</p>
<p>*<em>불변성을 관리하는 가장 중요한 이유는 상태 변경이 컴포넌트의 리렌더링을 유도하기 위해서입니다. 
React는 상태나 props가 변경되면 컴포넌트를 리렌더링합니다. 
불변성을 유지하면 상태 객체의 참조가 변경되므로 React는 이전 상태와 새로운 상태를 비교하여 필요한 리렌더링을 수행할 수 있습니다. *</em></p>
<p>상태 공유는 Context API나 상태 관리 라이브러리와 관련이 있으며, 불변성 관리의 주요 목적은 컴포넌트의 리렌더링을 정확하게 수행하도록 하는 것입니다.</p>
<blockquote>
<p>18/20 Multiple choice 컴포넌트의 리렌더링을 최소화하면서 리렌더링 시 영향을 주지 않는 변수를 관리할 때 가장 적절한 Hook은 무엇인가요? (5pt)
useState
useReducer
useMemo
useRef</p>
</blockquote>
<p>문제풀이
useState
설명: useState는 컴포넌트의 상태를 관리하는 Hook입니다. 
상태가 변경되면 컴포넌트가 리렌더링됩니다.
useState는 상태가 변경될 때마다 리렌더링을 유발하기 때문에 리렌더링을 최소화하려는 목적에는 적합하지 않습니다.</p>
<p>useReducer
설명: useReducer는 복잡한 상태 로직을 관리하는 데 사용됩니다. useReducer는 상태 업데이트가 발생할 때 컴포넌트를 리렌더링하지만 
상태 관리의 복잡성을 줄이고 구조화된 업데이트를 처리하는 데 유용합니다. 
리렌더링을 최소화하는 데는 직접적인 관계가 없습니다.</p>
<p>useMemo
설명: useMemo는 컴포넌트의 리렌더링 성능을 최적화하기 위해 계산 결과를 메모이제이션합니다. 
의존성 배열이 변경될 때만 메모이제이션된 값을 재계산하여 리렌더링 성능을 개선할 수 있습니다. 
useMemo는 컴포넌트가 렌더링될 때 영향을 주지 않는 값을 캐싱하고 리렌더링을 최적화하는 데 적합합니다.</p>
<p><strong>useRef
설명: useRef는 컴포넌트의 렌더링 사이에서 변수를 유지하는 데 사용됩니다. useRef로 관리되는 변수는 상태를 가지지 않으며 값이 변경되어도 컴포넌트는 리렌더링되지 않습니다. 
따라서 리렌더링 시 영향을 주지 않는 변수를 관리하는 데 가장 적합합니다.</strong></p>
<blockquote>
<p>19/20 Multiple choice Next.js에서 &#39;pages&#39; 디렉토리 내에 &#39;contact.js&#39; 라는 파일을 추가했을 때, 해당 페이지에 접근할 수 있는 URL 경로는 무엇인가요? (5pt)
/contact
/pages/contact
/contact.js
/contact/index</p>
</blockquote>
<p>문제풀이
<strong>/contact
설명: pages 디렉토리 내에 contact.js 파일을 추가했을 때 
이 파일은 Next.js의 기본 라우팅 규칙에 따라 /contact URL 경로에 매핑됩니다. 
Next.js는 pages 디렉토리 내의 파일 이름을 URL 경로로 변환하여 페이지를 제공합니다.</strong></p>
<p>/pages/contact
설명: /pages/contact는 파일 시스템의 실제 경로를 나타내며 
URL 경로가 아닙니다. Next.js는 pages 디렉토리 내의 파일을 URL 경로로 변환하지만 /pages/contact는 URL 경로로 접근할 수 없습니다.</p>
<p>/contact.js
설명: /contact.js는 URL 경로가 아니라 파일 이름을 나타냅니다. Next.js는 파일 이름을 직접 URL 경로로 사용하지 않습니다. 
URL 경로는 파일 이름에서 .js 확장자를 제외한 부분을 사용합니다.</p>
<p>/contact/index
설명: /contact/index는 contact라는 폴더 내에 index.js 파일이 있을 때의 URL 경로입니다. 
contact라는 폴더가 있고 그 안에 index.js가 있는 경우에 /contact URL로 접근할 수 있습니다. 
하지만 contact.js 파일이 pages 디렉토리의 직접적인 파일일 경우에는 해당 URL이 아닙니다.</p>
<blockquote>
<p>20/20 Multiple choice 서버 사이드 렌더링(SSR)을 사용하면 SEO(검색 엔진 최적화)에 어떤 이점을 제공하나요? (5pt)
클라이언트 측에서 JavaScript를 실행하지 않도록 합니다.
서버에서 페이지 콘텐츠를 미리 렌더링하여 검색 엔진 크롤러가 페이지 내용을 쉽게 인식할 수 있도록 합니다.
페이지 로드 속도를 향상시킵니다.
사용자 상호작용을 관리하는 데 도움이 됩니다.</p>
</blockquote>
<p>문제풀이
SSR은 서버에서 페이지 콘텐츠를 렌더링하여 클라이언트 측에서의 JavaScript 실행을 줄일 수 있지만, JavaScript를 아예 실행하지 않도록 만드는 것은 아닙니다.</p>
<p>*<em>SSR을 사용하면 서버에서 페이지를 미리 렌더링하여 완성된 HTML을 클라이언트에 전달합니다. 검색 엔진 크롤러가 페이지의 내용을 더 쉽게 인식하고 색인화할 수 있게 도와줍니다. *</em></p>
<p>페이지 로드 속도는 사용자 경험을 개선할 수 있지만 
SEO의 직접적인 이점은 검색 엔진이 페이지 콘텐츠를 인식할 수 있는가와 관련이 있습니다.</p>
<p>SSR은 주로 페이지의 초기 렌더링을 담당하며 사용자 상호작용 관리에는 직접적인 역할을 하지 않습니다. 
사용자 상호작용은 클라이언트 측 JavaScript에서 주로 처리됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Developer Tools를 활용한 React 애플리케이션 성능 
최적화]]></title>
            <link>https://velog.io/@sangmin0310-afk/React-Developer-Tools%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-React-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94</link>
            <guid>https://velog.io/@sangmin0310-afk/React-Developer-Tools%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-React-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94</guid>
            <pubDate>Wed, 14 Aug 2024 14:58:43 GMT</pubDate>
            <description><![CDATA[<h3 id="debounce의-개념과-사용법"><strong><code>debounce</code>의 개념과 사용법</strong></h3>
<h3 id="debounce의-개념">debounce의 개념</h3>
<p><strong>Debounce</strong>는 자바스크립트에서 특정 함수가 반복적으로 호출되는 것을 제어하기 위해 사용되는 기법입니다. 
주로 사용자가 빠르게 반복해서 실행하는 이벤트(예: 키 입력, 윈도우 리사이즈, 스크롤 등)에 대해 마지막 이벤트만 
실행되도록 제어합니다.</p>
<h3 id="debounce의-사용법">Debounce의 사용법</h3>
<pre><code class="language-jsx">const searchInput = document.getElementById(&#39;search-input&#39;);

function handleSearch(event) {
  console.log(&#39;API 요청: &#39;, event.target.value);
}

const debouncedSearch = debounce(handleSearch, 300);

searchInput.addEventListener(&#39;input&#39;, debouncedSearch);

//사용자가 텍스트 입력을 할 때 debounce를 사용하여 API 요청을 최적화하는 예제입니다.</code></pre>
<blockquote>
<p>Debounce 함수는 자바스크립트로 직접 구현할 수 있으며, 일반적으로 lodash 같은 라이브러리를 통해 쉽게 사용할 수도 있습니다.</p>
</blockquote>
<h3 id="throttle의-개념과-사용법"><strong><code>Throttle</code>의 개념과 사용법</strong></h3>
<h3 id="throttle의-개념">Throttle의 개념</h3>
<p>Throttle(쓰로틀)는 특정 함수가 짧은 시간 간격으로 반복해서 호출되는 것을 제어하는 기법입니다. 
Throttle은 일정한 시간 간격 내에서 함수가 한 번만 실행되도록 제한하여 과도한 함수 호출로 인한 성능 
문제를 방지합니다.</p>
<h3 id="throttle의-사용법">Throttle의 사용법</h3>
<pre><code class="language-jsx">function handleScroll() {
  console.log(&#39;Scroll event at&#39;, new Date().toISOString());
}

const throttledScroll = throttle(handleScroll, 200);

window.addEventListener(&#39;scroll&#39;, throttledScroll);

//스크롤 이벤트에서 throttle을 사용하여 성능을 최적화하는 예제입니다.</code></pre>
<h3 id="debounce와-throttle의-차이점"><strong><code>debounce</code>와 <code>throttle</code>의 차이점</strong></h3>
<p><code>Debounce</code>는 한 묶음의 이벤트를 하나의 이벤트로만 처리한다는 느낌이 강해서 
이벤트 묶음이 끝나야, 즉 일정 시간 동안 이벤트가 발생하지 않아야 합니다.</p>
<p><code>Throttle</code>은 이벤트가 끊임 없이 일어나는 상황에서 
일정 시간마다 주기적으로만 실제 함수를 실행(이벤트를 리슨)합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[번들링과 코드스플리팅]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EB%B2%88%EB%93%A4%EB%A7%81%EA%B3%BC-%EC%BD%94%EB%93%9C%EC%8A%A4%ED%94%8C%EB%A6%AC%ED%8C%85</link>
            <guid>https://velog.io/@sangmin0310-afk/%EB%B2%88%EB%93%A4%EB%A7%81%EA%B3%BC-%EC%BD%94%EB%93%9C%EC%8A%A4%ED%94%8C%EB%A6%AC%ED%8C%85</guid>
            <pubDate>Wed, 14 Aug 2024 14:56:20 GMT</pubDate>
            <description><![CDATA[<h1 id="번들링과-코드스플리팅">번들링과 코드스플리팅</h1>
<h3 id="번들링이란">번들링이란?</h3>
<p>번들링(bundling)은 애플리케이션의 여러 파일(예: JavaScript, CSS, 이미지 등)을 하나 또는 여러 개의 번들 파일로 결합하여 웹 브라우저가 더 효율적으로 로드할 수 있도록 하는 프로세스를 의미합니다.</p>
<h3 id="코드스플러팅이란">코드스플러팅이란?</h3>
<p>코드 스플리팅(Code Splitting)은 웹 애플리케이션에서 전체 코드베이스를 한 번에 로드하지 않고 
필요한 부분만 나누어 로드하는 기법입니다.
초기 로딩 시간을 줄이고, 사용자 경험을 개선할 수 있습니다.</p>
<h3 id="reactlazy와-suspense를-이용한-코드-스플리팅"><strong><code>React.lazy</code>와 <code>Suspense</code>를 이용한 코드 스플리팅</strong></h3>
<h3 id="reactlazy-"><code>React.lazy</code> :</h3>
<p><code>React.lazy</code>는 동적으로 컴포넌트를 불러오는 기능을 제공합니다. 
특정 컴포넌트가 필요한 시점에만 로드되도록 할 수 있습니다.</p>
<h3 id="suspense-"><code>Suspense</code> :</h3>
<p><code>Suspense</code>는 로딩 중 상태를 처리하는 역할을 합니다. 
<code>React.lazy</code>를 사용하여 동적 로딩을 할 때, 로드되는 동안 표시할 대체 UI(예: 로딩 스피너)를 제공할 수 있습니다.</p>
<h3 id="예제-reactlazy와-suspense를-사용한-코드-스플리팅">예제: <code>React.lazy</code>와 <code>Suspense</code>를 사용한 코드 스플리팅</h3>
<pre><code class="language-jsx">import { Suspense } from &#39;react&#39;;

// MyComponent를 동적으로 로드
const MyComponent = React.lazy(() =&gt; import(&#39;./MyComponent&#39;));

function App() {
  return (
    &lt;div&gt;
      &lt;h1&gt;My React App&lt;/h1&gt;

      {/* Suspense를 사용하여 로딩 상태를 처리 */}
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        &lt;MyComponent /&gt;
      &lt;/Suspense&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<h3 id="코드설명">코드설명:</h3>
<ol>
<li><code>React.lazy(() =&gt; import(&#39;./MyComponent&#39;))</code>: 
<code>MyComponent</code>를 동적으로 import하여 필요할 때만 로드합니다. 
이 코드는 JavaScript 청크로 분리되어 브라우저가 필요할 때 로드하게 됩니다.</li>
<li><code>&lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;</code>: <code>Suspense</code>는 동적 로딩이 이루어질 때 &quot;Loading...&quot;
이라는 텍스트를 표시합니다. <code>fallback</code> 속성에는 로딩 중 표시할 UI를 정의합니다. UI는 컴포넌트가 로드될 때까지 화면에 표시됩니다.</li>
<li><code>Suspense</code> 내에 동적 로딩된 <code>MyComponent</code>가 렌더링됩니다. 로딩이 완료되면 <code>MyComponent</code>가 화면에 표시됩니다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[리엑트 성능 최적화 기초 알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EB%A6%AC%EC%97%91%ED%8A%B8-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EA%B8%B0%EC%B4%88-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/%EB%A6%AC%EC%97%91%ED%8A%B8-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EA%B8%B0%EC%B4%88-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Tue, 13 Aug 2024 14:17:22 GMT</pubDate>
            <description><![CDATA[<h1 id="리액트-성능-최적화의-기초-usememo-usecallback-memo">리액트 성능 최적화의 기초: <code>useMemo</code>, <code>useCallback</code>, <code>memo</code></h1>
<h3 id="리액트-생명주기-메서드와-함수형-컴포넌트-생명주기">리액트 생명주기 메서드와 함수형 컴포넌트 생명주기</h3>
<p>함수형 컴포넌트에서는 </p>
<p><code>useEffect</code>, <code>useState</code>, <code>useRef</code> 등 훅(hooks)을 사용하여 생명주기를 관리할 수 있습니다.</p>
<p><strong>생성 (Mounting)</strong></p>
<ul>
<li><code>useEffect(() =&gt; { ... }, [])</code>: 의존성 배열을 빈 배열로 두면 컴포넌트가 마운트될 때 한 번 실행니다다.
<code>componentDidMount</code>와 유사한 역할을 합니다.</li>
</ul>
<p><strong>업데이트 (Updating)</strong></p>
<ul>
<li><code>useEffect(() =&gt; { ... }, [의존성])</code>: 의존성 배열에 포함된 값이 변경될 때마다 실행됩니다. <code>componentDidUpdate</code>와 유사합니다.</li>
</ul>
<p><strong>제거 (Unmounting)</strong></p>
<ul>
<li><code>useEffect(() =&gt; { return () =&gt; { ... }; }, [])</code>: <code>useEffect</code>의 반환 함수는 컴포넌트가 언마운트될 때 실행됩니다. <code>componentWillUnmount</code>와 유사합니다.</li>
</ul>
<h3 id="usememo-usecallback-reactmemo에-대해-설명하기">useMemo, useCallback, React.memo에 대해 설명하기</h3>
<p><code>useMemo</code>, <code>useCallback</code>, <code>React.memo</code>는 React에서 성능 최적화를 위해 자주 사용되는 도구들입니다. 
이 세 가지는 각각 다른 목적을 가지고 있으며 때로는 함께 사용되기도 합니다.</p>
<h3 id="1-usememo">1. <code>useMemo</code></h3>
<ul>
<li><p><strong>목적</strong>: 연산 비용이 높은 함수의 <strong>결과값을 캐싱</strong>하여 불필요한 재계산을 방지하기 위해 사용됩니다.</p>
</li>
<li><p><strong>사용 시기</strong>: 특정 계산이 값의 변화에 따라 반복되지 않도록 하고 싶은 경우에 사용합니다.</p>
</li>
<li><p><strong>구문</strong>:</p>
<pre><code class="language-jsx">
  const memoizedValue = useMemo(() =&gt; 계산할_함수(), [의존성]);</code></pre>
<blockquote>
<p><strong>설명</strong>: <code>useMemo</code>는 특정 값(<code>memoizedValue</code>)을 계산할 때 의존성 배열에 있는 값들이 변경되지 않았다면 이전에 계산된 값을 반환합니다. 
  렌더링 성능을 최적화하는 데 도움이 됩니다. 
  예를 들어, 복잡한 계산이나 큰 데이터 구조의 변환이 자주 일어날 때 <code>useMemo</code>를 사용하여 불필요한 계산을 방지할 수 있습니다.</p>
</blockquote>
</li>
</ul>
<h3 id="2-usecallback">2. <code>useCallback</code></h3>
<ul>
<li><p><strong>목적</strong>: 함수의 <strong>참조값을 캐싱</strong>하여 불필요한 함수 재생성을 방지하기 위해 사용됩니다.</p>
</li>
<li><p><strong>사용 시기</strong>: 특정 함수가 렌더링 시마다 동일한 참조값을 갖도록 하고 싶을 때 사용합니다.</p>
</li>
<li><p><strong>구문</strong>:</p>
<pre><code class="language-jsx">  const memoizedCallback = useCallback(() =&gt; {
    실행할_함수();
  }, [의존성]);</code></pre>
<blockquote>
<p><strong>설명</strong>: <code>useCallback</code>은 주어진 함수를 메모이제이션합니다. 
  의존성 배열에 있는 값들이 변경되지 않았다면, 동일한 함수 참조를 반환합니다. 
  자식 컴포넌트에 콜백 함수를 props로 전달할 때 유용합니다. 
  렌더링 시마다 새로운 함수가 생성되는 것을 방지하여 불필요한 리렌더링을 줄일 수 있습니다.</p>
</blockquote>
</li>
</ul>
<h3 id="3-reactmemo">3. <code>React.memo</code></h3>
<ul>
<li><p><strong>목적</strong>: <strong>불필요한 리렌더링을 방지</strong>하기 위해 컴포넌트의 렌더링을 최적화합니다.</p>
</li>
<li><p><strong>사용 시기</strong>: 특정 컴포넌트가 동일한 props를 받는 경우에도 리렌더링되는 것을 방지하고 싶을 때 사용합니다.</p>
</li>
<li><p><strong>구문</strong>:</p>
<pre><code class="language-jsx">
  const MemoizedComponent = React.memo(컴포넌트);</code></pre>
<blockquote>
<p><strong>설명</strong>: <code>React.memo</code>는 고차 컴포넌트(Higher Order Component, HOC)로 함수형 컴포넌트를 감싸서 메모이제이션된 버전을 만듭니다. 
  이전과 동일한 props를 받으면 해당 컴포넌트를 다시 렌더링하지 않습니다. 
  <code>React.memo</code>는 얕은 비교를 사용하여 props가 변경되지 않은 경우 렌더링을 건너뜁니다.</p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux vs Redux Toolkit알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/ReduxRedux-Toolkit%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/ReduxRedux-Toolkit%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Mon, 12 Aug 2024 14:39:16 GMT</pubDate>
            <description><![CDATA[<h1 id="redux로-전역상태-관리하기">Redux로 전역상태 관리하기</h1>
<h3 id="redux란-무엇인가요">Redux란 무엇인가요?</h3>
<p>Redux는 애플리케이션에서 상태 관리를 위한 라이브러리 입니다.</p>
<p>단일 상태 트리(single state tree) 개념을 사용해 애플리케이션의 상태를 중앙에서 관리하며
예측 가능한 방식으로 상태 변화를 처리합니다.</p>
<p>대규모 애플리케이션에서 상태관리의 복잡성을 줄이는데 도움을 주고
상태를 예측 가능하고 일관성 있게 관리할 수 있도록 도와줍니다.</p>
<h3 id="redux의-데이터-흐름에-대해-설명하기-flux-패턴">Redux의 데이터 흐름에 대해 설명하기 (flux 패턴)</h3>
<ol>
<li><strong>Action</strong>: 애플리케이션의 상태를 변경하기 위한 요청입니다. 
사용자의 입력이나 네트워크 응답 등에서 발생합니다.</li>
<li><strong>Reducer</strong>: Action이 발생하면 Reducer가 현재 상태와 Action을 받아 새로운 상태를 반환합니다. 
상태는 불변성을 유지하며 기존 상태를 복사하여 변경된 부분만 업데이트합니다.</li>
<li><strong>Store</strong>: 애플리케이션의 모든 상태를 담고 있는 객체입니다. 
상태는 하나의 중앙 Store에서 관리되며, Store는 Reducer에 의해 업데이트됩니다.</li>
<li><strong>View</strong>: Store에서 상태를 구독하고 있다가 상태가 변경되면 View가 자동으로 업데이트됩니다.</li>
</ol>
<blockquote>
<p>데이터는 Action -&gt; Reducer -&gt; Store -&gt; View의 순서로 단방향으로 흐르며, 이는 데이터 관리의 일관성을 유지하는 데 도움을 줍니다.</p>
</blockquote>
<h3 id="action-dispatch-reducer-store의-역할">Action, Dispatch, Reducer, Store의 역할</h3>
<p>(간단한 사용 예시코드도 함께 작성해 주세요.)</p>
<h3 id="1-action">1. <strong>Action</strong></h3>
<ul>
<li><strong>역할</strong>: <code>Action</code>은 애플리케이션에서 발생하는 사건을 기술하는 객체입니다. 
Action 객체는 반드시 <code>type</code>이라는 속성을 가지고 있으며 선택적으로 데이터를 포함할 수 있습니다.</li>
<li><strong>예시</strong>: 사용자가 버튼을 클릭했을 때 &quot;증가&quot; 액션을 발생시킬 수 있습니다.</li>
</ul>
<pre><code class="language-jsx">const upAction = {
  type: &#39;UP&#39;,
  payload: 1, 
};</code></pre>
<h3 id="2-dispatch">2. <strong>Dispatch</strong></h3>
<ul>
<li><strong>역할</strong>: <code>Dispatch</code>는 <code>Action</code>을 <code>Store</code>에 보내는 역할을 합니다. 
<code>Store</code>는 전달된 <code>Action</code>을 받아서 적절한 <code>Reducer</code>로 전달하고, 상태를 업데이트합니다.</li>
<li><strong>예시</strong>: 사용자가 버튼을 클릭하면 증가 액션을 <code>Dispatch</code>합니다.</li>
</ul>
<pre><code class="language-jsx">
store.dispatch(upAction);</code></pre>
<h3 id="3-reducer">3. <strong>Reducer</strong></h3>
<ul>
<li><strong>역할</strong>: <code>Reducer</code>는 <code>Action</code>을 처리하여 새로운 상태를 반환하는 함수입니다. 
기존 상태와 <code>Action</code>을 입력받아 새로운 상태를 반환합니다. 
<code>Reducer</code>는 순수 함수여야 하며 입력 값에만 의존하고 부수 효과(side effect)를 가지지 않아야 합니다.</li>
<li><strong>예시</strong>: 상태가 증가하는 로직을 포함한 <code>Reducer</code> 함수입니다.</li>
</ul>
<pre><code class="language-jsx">const counterReducer = (state = 0, action) =&gt; {
  switch (action.type) {
    case &#39;UP&#39;:
      return state + action.payload;
    case &#39;DOWN&#39;:
      return state - action.payload;
    default:
      return state;
  }
};</code></pre>
<h3 id="4-store"><strong>4. Store</strong></h3>
<ul>
<li><strong>역할</strong>: <code>Store</code>는 애플리케이션의 상태를 관리하는 객체입니다. 
상태를 저장하고 <code>Action</code>을 <code>Dispatch</code>하며 상태가 변경될 때마다 
구독자(subscriber)에게 알리는 역할을 합니다.</li>
<li><strong>예시</strong>: <code>Redux Store</code>를 생성하는 코드입니다.</li>
</ul>
<pre><code class="language-jsx">import { createStore } from &#39;redux&#39;;

const store = createStore(counterReducer);

// 초기 상태 조회
console.log(store.getState()); // 출력: 0

// 상태 변경 (Action Dispatch)
store.dispatch(upAction);
console.log(store.getState()); // 출력: 1

store.dispatch({ type: &#39;DOWN&#39;, payload: 1 });
console.log(store.getState()); // 출력: 0
</code></pre>
<h3 id="usedispatch-와-useselector의-역할">useDispatch() 와 useSelector()의 역할</h3>
<h3 id="usedispatch"><code>useDispatch()</code></h3>
<ul>
<li><strong>역할</strong>: Redux 스토어에 액션(action)을 보내기 위한 함수(<code>dispatch</code>)를 반환합니다.</li>
</ul>
<h3 id="useselector"><code>useSelector()</code></h3>
<ul>
<li><strong>역할</strong>: Redux 스토어의 상태(state)에서 필요한 부분을 선택(select)하여 가져오는 역할을 합니다.</li>
</ul>
<h3 id="redux-thunk란-무엇인가요">Redux-Thunk란 무엇인가요?</h3>
<p><code>Thunk</code>는 <a href="https://redux.js.org/style-guide/#use-thunks-and-listeners-for-other-async-logic">Redux 앱에서 비동기 로직을 작성하기 위한 표준적인 접근 방식</a> 이며  일반적으로 데이터 페칭에 
사용됩니다. 그러나 다양한 작업에 사용할 수 있으며 동기 및 비동기 로직을 모두 포함할 수 있습니다.</p>
<h1 id="redux-toolkit으로-전역상태-관리하기">Redux Toolkit으로 전역상태 관리하기</h1>
<h3 id="redux-toolkit이란-무엇인가요-">Redux Toolkit이란 무엇인가요 ?</h3>
<p><strong><code>Redux Toolkit</code></strong>은 <code>Redux</code>애플리케이션을 개발할 때 발생하는 반복적이고 복잡한 작업을 간소화하기 위해 제공되는 공식 패키지입니다. <code>Redux</code>는 상태 관리를 위해 널리 사용되는 JavaScript 라이브러리인데 
(설정이 다소 복잡하고 보일러플레이트 코드가 많다는 단점이 있습니다.) 
이러한 문제를 해결하기 위해 <code>Redux Toolkit</code>이 도입되었습니다.</p>
<h3 id="redux와-차이점은-무엇인가요">Redux와 차이점은 무엇인가요?</h3>
<ul>
<li>Redux는 설정과 보일러플레이트 코드가 많지만 Redux Toolkit은 
<code>configureStore</code>, <code>createSlice</code> 등을 통해 설정을 단순화하고 코드를 줄여줍니다.</li>
<li>Redux에서는 리듀서를 작성할 때 불변성을 직접 관리해야 하지만 Redux Toolkit은 자동으로 불변성을 관리해주고 리듀서와 액션 생성자를 함께 생성해줍니다.</li>
<li>Redux에서는 비동기 로직을 관리하려면 추가 설정이 필요하지만 Redux Toolkit은 <code>createAsyncThunk</code>를 통해 비동기 작업을 쉽게 처리할 수 있습니다.</li>
</ul>
<blockquote>
<p>Redux Toolkit은 Redux의 복잡성을 줄이고 사용을 쉽게 하기 위해 만들어진 도구입니다.</p>
</blockquote>
<h3 id="createslice-configurestore-의-역할">createSlice(), configureStore() 의 역할</h3>
<p>(간단한 사용 예시코드도 함께 작성해 주세요.)</p>
<h3 id="createslice">createSlice()</h3>
<ul>
<li><strong>역할</strong>: <code>createSlice</code>는 Redux의 리듀서와 액션을 함께 생성해주는 함수입니다. 
상태의 초기값, 리듀서 함수, 그리고 액션 타입을 정의할 수 있습니다. 
<code>createSlice</code>는 내부적으로 액션 생성자와 타입을 자동으로 생성해 주기 때문에 보일러플레이트 코드가 줄어듭니다.</li>
</ul>
<pre><code class="language-jsx">import { configureStore, createSlice } from &#39;@reduxjs/toolkit&#39;;

// 1. createSlice로 상태, 리듀서, 액션 생성
const counterSlice = createSlice({
  name: &#39;counter&#39;,
  initialState: { value: 0 },
  reducers: {
    increment: state =&gt; { state.value += 1 },  // 액션 함수 정의
    decrement: state =&gt; { state.value -= 1 },
    reset: state =&gt; { state.value = 0 }
  }
});</code></pre>
<h3 id="configurestore">configureStore()</h3>
<p><code>configureStore</code>는 Redux 스토어를 설정하고 생성하는 함수입니다. 
이 함수는 미들웨어, Redux DevTools 통합, 리듀서 결합 등의 설정을 간편하게 할 수 있도록 도와줍니다. </p>
<pre><code class="language-jsx">// 액션 추출
export const { increment, decrement, reset } = counterSlice.actions;

// 2. configureStore로 스토어 생성
const store = configureStore({
  reducer: {
    counter: counterSlice.reducer
  }
});

// 스토어 사용 예시
store.dispatch(increment());  // 상태가 1 증가
store.dispatch(decrement());  // 상태가 1 감소
store.dispatch(reset());      // 상태가 0으로 리셋

console.log(store.getState()); // { counter: { value: 0 } }</code></pre>
<h3 id="redux-toolkit에서-thunk-사용법">Redux Toolkit에서 Thunk 사용법</h3>
<p>→ createAsyncThunk()란?</p>
<p><code>createAsyncThunk()</code>는 Redux Toolkit에서 비동기 작업(예: API 호출)을 간단하게 처리할 수 있도록 도와주는 유틸리티 함수입니다. 
비동기 작업의 상태(요청 중, 성공, 실패)를 자동으로 관리하고 해당 상태에 맞는 액션을 자동으로 생성해줍니다.</p>
<h3 id="createasyncthunk의-사용법"><code>createAsyncThunk()</code>의 사용법:</h3>
<ol>
<li><strong>비동기 작업 정의</strong>: <code>createAsyncThunk</code>를 사용해 비동기 작업을 정의합니다.</li>
<li><strong>리덕스에 비동기 작업 상태 추가</strong>: 비동기 작업의 상태(요청 중, 성공, 실패)를 처리하는 리덕스를 <code>extraReducers</code>에서 정의합니다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Context API알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/Context-API%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/Context-API%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Fri, 09 Aug 2024 11:06:15 GMT</pubDate>
            <description><![CDATA[<h1 id="context-api란">Context API란?</h1>
<h3 id="context-api란-1">Context API란?</h3>
<p><code>Context API</code> 는 리엑트(React)에서 전역적으로 데이터를 관리하고 전달하는 데 사용합니다.</p>
<p>리엑트 애플리케이션에서는 상태(state)와 props를 이용해 컴포넌트간에 데이터를 전달하지만</p>
<p>컴포넌트 계층이 깊어질수록 상위 컴포넌트에서 하위 컴포넌트로 props를 계속 전달하는 것이 번거러워집니다.</p>
<p>이러한 경우를 해결하기 위해 Context API를 사용하면 중간에 위치한 컴포넌트들을 거치지 않고 데이터를</p>
<p>여러 컴포넌트에 쉽게 전달이 가능합니다.</p>
<h3 id="언제-context-api를-사용하나요">언제 Context API를 사용하나요?</h3>
<ol>
<li>전역 상태 관리가 필요할때</li>
<li>Prop driling을 피하고 싶을 때
Prop driling이란 데이터를 여러 계층의 컴포넌트를 통해 전달해야 하는 상황을 의미합니다.</li>
<li>애플리케이션의 특정 상태나 데이터를 쉽게 공유해야 할 때
리렌더링의 비용이 낮은 경우에 Context API를 사용하면 코드가 훨씬 간결해집니다.</li>
</ol>
<h1 id="context-api-사용방법">Context API 사용방법</h1>
<h3 id="createcontext로-전역상태-만들기-간단한-예시코드">createContext로 전역상태 만들기 (간단한 예시코드)</h3>
<pre><code class="language-jsx">import React, { createContext, useState } from &#39;react&#39;;

// 1. Context 생성
export const MyContext = createContext();

// 2. Provider로 전역 상태 연결
export const MyProvider = ({ children }) =&gt; {
  const [state, setState] = useState(&quot;Hello, World!&quot;);

  return (
    &lt;MyContext.Provider value={{ state, setState }}&gt;
      {children}
    &lt;/MyContext.Provider&gt;
  );
};</code></pre>
<ol>
<li><p><code>createContext()</code> 로 Context생성</p>
<pre><code class="language-jsx"> export const MyContext = createContext();</code></pre>
<p> <code>createContext()</code>는 새로운 Context 객체를 생성합니다.</p>
<p> <code>MyContext</code> 객체는 Provider와 Consumer를 가지고 있으며 여기서는 주로 Provider를 사용합니다.</p>
<p> <code>MyContext</code>를 export함으로써 다른 컴포넌트에서도 이 Context를 사용할 수 있습니다.</p>
</li>
<li><p>Provider로 전역 상태 연결</p>
<pre><code class="language-jsx"> export const MyProvider = ({ children }) =&gt; {
   const [state, setState] = useState(&quot;Hello, World!&quot;);

   return (
     &lt;MyContext.Provider value={{ state, setState }}&gt;
       {children}
     &lt;/MyContext.Provider&gt;
   );
 };</code></pre>
<p> <code>MyProvider</code>는 Context의 <strong>Provider</strong>를 사용하는 컴포넌트입니다.<br> 컴포넌트를 통해 하위 컴포넌트들에 전역 상태를 전달합니다.</p>
<p> <code>useState</code> 훅을 사용해 <code>state</code>와 <code>setState</code>를 정의하고 
 초기값은 <code>&quot;Hello, World!&quot;</code>로 설정되어 있습니다.
 [<code>state</code>: 전역으로 관리하고자 하는 상태 값입니다.]</p>
<p> [<code>setState</code>: 상태 값을 업데이트하는 함수입니다.]</p>
<p> <code>MyContext.Provider</code>는 <code>value</code> prop을 통해 하위 컴포넌트들에게 제공하고자 하는 데이터를 전달합니다.</p>
<p> <code>value</code>는 객체 형태로 전달되며 이 예제에서는 <code>state</code>와 <code>setState</code>를 함께 전달하고 있습니다.</p>
<p> <code>{children}</code>은 <code>MyProvider</code> 컴포넌트의 자식 컴포넌트들을 의미합니다.
  Provider를 통해 전달된 상태와 함수를 이 자식 컴포넌트들이 사용할 수 있게 됩니다.</p>
</li>
</ol>
<h3 id="provider로-전역-상태-연결간단예제">Provider로 전역 상태 연결(간단예제)</h3>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import { MyProvider } from &#39;./MyContext&#39;;
import MyComponent from &#39;./MyComponent&#39;;

const App = () =&gt; {
  return (
    &lt;MyProvider&gt;
      &lt;MyComponent /&gt;
    &lt;/MyProvider&gt;
  );
};

export default App;</code></pre>
<ol>
<li><p><code>MyProvider</code>로 전역 상태 감싸기</p>
<pre><code class="language-jsx"> &lt;MyProvider&gt;
   &lt;MyComponent /&gt;
 &lt;/MyProvider&gt;</code></pre>
<p> <code>MyProvider</code>는 <code>MyContext</code>의 Provider 컴포넌트입니다.</p>
<p>  <code>MyProvider</code> 안에 있는 모든 하위 컴포넌트들은 <code>MyProvider</code>에서 정의된 상태와 함수를 사용할 수 있습니다.</p>
<p> <code>MyComponent</code>는 <code>MyProvider</code>의 자식 컴포넌트로 <code>MyProvider</code>가 제공하는 <code>state</code>와 <code>setState</code>를 사용할 수 있는 상태가 됩니다.</p>
</li>
</ol>
<h3 id="usecontext로-전역-상태-가져오기간단예제">useContext로 전역 상태 가져오기(간단예제)</h3>
<pre><code class="language-jsx">import React, { useContext } from &#39;react&#39;;
import { MyContext } from &#39;./MyContext&#39;;

const MyComponent = () =&gt; {
  // useContext를 사용하여 전역 상태 가져오기
  const { state, setState } = useContext(MyContext);

  return (
    &lt;div&gt;
      &lt;p&gt;{state}&lt;/p&gt;
      &lt;button onClick={() =&gt; setState(&quot;Hello, React Context!&quot;)}&gt;
        Update State
      &lt;/button&gt;
    &lt;/div&gt;
  );
};

export default MyComponent;</code></pre>
<ol>
<li><p><code>MyComponent</code> 컴포넌트 정의</p>
<pre><code class="language-jsx"> const MyComponent = () =&gt; {
   // useContext를 사용하여 전역 상태 가져오기
   const { state, setState } = useContext(MyContext);</code></pre>
<p> <code>useContext</code> 훅을 사용하여 <code>MyContext</code>에서 제공된 값을 가져옵니다.
 <code>state</code>: <code>MyProvider</code>에서 제공된 전역 상태입니다. 
 <code>MyProvider</code>에서 설정된 상태(<code>useState</code>의 초기값인 <code>&quot;Hello, World!&quot;</code>)를 가리킵니다.</p>
<p> <code>setState</code>: 상태를 업데이트하는 함수입니다. 
 <code>useContext</code>를 사용하면 함수형 컴포넌트 내에서 직접적으로 Context의 값을 쉽게 사용할 수 있습니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 심화 1]]></title>
            <link>https://velog.io/@sangmin0310-afk/React-%EC%8B%AC%ED%99%94-1</link>
            <guid>https://velog.io/@sangmin0310-afk/React-%EC%8B%AC%ED%99%94-1</guid>
            <pubDate>Thu, 08 Aug 2024 12:13:13 GMT</pubDate>
            <description><![CDATA[<h1 id="react-내부-구현-상태관리">React 내부 구현 상태관리</h1>
<h3 id="react-내부에서-상태를-관리하는-방법">React 내부에서 상태를 관리하는 방법</h3>
<ol>
<li>useState</li>
</ol>
<pre><code class="language-jsx">import React, { useState } from &#39;react&#39;;

function Counter() {
  const [count, setCount] = useState(0);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<ol>
<li>Context API</li>
</ol>
<pre><code class="language-jsx">const CountContext = createContext();

function CountProvider({ children, initialCount = 0 }) {
  const [count, setCount] = useState(initialCount);
  return (
    &lt;CountContext.Provider value={{ count, setCount }}&gt;
      {children}
    &lt;/CountContext.Provider&gt;
  );
}

function Counter() {
  const { count, setCount } = useContext(CountContext);

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;/button&gt;
      &lt;button onClick={() =&gt; setCount(count - 1)}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<ol>
<li>Redux</li>
</ol>
<pre><code class="language-jsx">import { createStore } from &#39;redux&#39;;
import { Provider, useDispatch, useSelector } from &#39;react-redux&#39;;

const initialState = { count: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case &#39;increment&#39;:
      return { count: state.count + 1 };
    case &#39;decrement&#39;:
      return { count: state.count - 1 };
    default:
      return state;
  }
}

const store = createStore(reducer);

function Counter() {
  const count = useSelector(state =&gt; state.count);
  const dispatch = useDispatch();

  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;increment&#39; })}&gt;Increment&lt;/button&gt;
      &lt;button onClick={() =&gt; dispatch({ type: &#39;decrement&#39; })}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<h3 id="constext-api란">Constext API란?</h3>
<p>React에서 컴포넌트 트리 전체에 전역적인 데이터를 쉽게 전달하기 위해 사용하는 방법입니다.
<code>Constext API</code>를 사용하면 <code>props</code>를 중첩된 컴포넌트에 일일이 전달하지 않고도 데이터나 상태를 컴포넌트 트리의 깊숙한 자손에게 전달이 가능합니다.</p>
<h3 id="constext-api-사용법">Constext API 사용법</h3>
<ol>
<li>Context 생성: <code>createContext</code> 함수를 사용하여 Context 객체를 생성합니다.</li>
</ol>
<pre><code class="language-jsx">import React, { createContext, useContext, useState } from &#39;react&#39;;

const CountContext = createContext();</code></pre>
<ol>
<li>Provider 정의: <code>Provider</code> 컴포넌트를 정의합니다, <code>Provider</code> 컴포넌트는 prop을 통해 하위 컴포넌트에 전달할 데이터를 설정합니다.</li>
</ol>
<pre><code class="language-jsx">function CountProvider({ children }) {
  const [count, setCount] = useState(0);
  return (
    &lt;CountContext.Provider value={{ count, setCount }}&gt;
      {children}
    &lt;/CountContext.Provider&gt;
  );
}</code></pre>
<ol>
<li>Context값 사용: <code>useContext</code> 훅을 상용하여 Context 값을 사용합니다.</li>
</ol>
<pre><code class="language-jsx">function Counter() {
  const { count, setCount } = useContext(CountContext);
  return (
    &lt;div&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p>Provider로 감싸기: <code>Provider</code> 컴포넌트를 사용하여 Context값을 하위 컴포넌트에 전달합니다.</p>
<pre><code class="language-jsx">function App() {
  return (
    &lt;CountProvider&gt;
      &lt;Counter /&gt;
    &lt;/CountProvider&gt;
  );
}

export default App;</code></pre>
<h1 id="react-외부-구현-상태관리">React 외부 구현 상태관리</h1>
<h3 id="react-외부에서-상태를-관리하는-방법">React 외부에서 상태를 관리하는 방법</h3>
<p>React 애플리케이션에서 상태 관리를 위해 외부 라이브러리를 사용해야 합니다.
바로 Redux 입니다. 
Redux는 가장 널리 사용되는 상태 관리 라이브러리 중 하나입니다. 
예측 가능한 상태 관리 패턴을 제공합니다.</p>
<h3 id="redux--redux-toolkit이란">Redux &amp; Redux Toolkit이란?</h3>
<p><strong>Redux</strong>는 중앙 집중식 상태 관리 라이브러리로, 상태, 액션, 리듀서, 미들웨어를 사용하여 상태를 관리합니다.
<strong>Redux Toolkit</strong>은 Redux 애플리케이션 개발을 간편하게 해주는 도구 모음입니다. <code>configureStore</code>, <code>createSlice</code>, <code>createAsyncThunk</code> 등의 기능을 통해 코드의 복잡성을 줄이고 상태 관리와 비동기 작업을 효율적으로 처리할 수 있게 도와줍니다.</p>
<h3 id="redux--redux-toolkit-사용법">Redux &amp; Redux Toolkit 사용법</h3>
<p>슬라이스생성: <code>createSlice</code>를 사용하여 상태와 리듀서를 정의합니다.</p>
<pre><code>            `initialState`와 `reducers`를 설정합니다.</code></pre><p>스토어 설정: <code>configureStore</code>를 사용하여 스토어를 생성하고 슬라이스 리듀서를 스토어    에 추가합니다.</p>
<p>Provider로 스토어 제공: <code>Provider</code>를 사용하여 애플리케이션 전체에 스토어를 제공합니다.</p>
<p>컴포넌트에서 상태 사용: <code>useSelector</code>를 사용하여 상태를 읽고, <code>useDispatch</code>를 사용하여 액션을 디스패치합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tailwind CSS 알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/Tailwind-CSS-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/Tailwind-CSS-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Wed, 07 Aug 2024 07:33:11 GMT</pubDate>
            <description><![CDATA[<h1 id="tailwind-css-설치--사용방법">Tailwind CSS 설치 &amp; 사용방법</h1>
<h3 id="tailwind-css-란">Tailwind CSS 란?</h3>
<p><code>Tailwind CSS</code> 는 <code>Utility-First</code> 접근 방식을 사용하는 CSS 프레임워크 입니다. 
컴포넌트 스타일링 보다는 단일 목적의 유틸리티 클래스를 활용하는 스타일을 정의 합니다.  </p>
<h3 id="utility-first란">Utility-First란?</h3>
<p>여러 개의 작은 유틸리티 클래스들을 조합하여 원하는 스타일을 만드는 방식입니다.
[유틸리티 클래스]는 일반적으로 단일 스타일 속성을 설정하는 짧고 간결한 클래스 입니다.</p>
<h3 id="설치-과정">설치 과정</h3>
<ol>
<li>프로젝트 생성</li>
</ol>
<pre><code class="language-bash">&gt; npm create vite@latest my-project -- --template react
&gt; cd my-project</code></pre>
<ol>
<li>Tailwind CSS설치</li>
</ol>
<pre><code class="language-bash">&gt; npm install -D tailwindcss postcss autoprefixer
&gt; npx tailwindcss init -p</code></pre>
<ol>
<li>템플릿 경로 구성</li>
</ol>
<pre><code class="language-jsx">export default {
    content: [
        &quot;./index.html&quot;,
        &quot;./src/**/*.{js,ts,jsx,tsx}&quot;,
    ],
    them: {
        extend: {},
    },
    plugins: [],
}</code></pre>
<ol>
<li>CSS에 Tailwind 지침을 추가합니다.</li>
</ol>
<pre><code class="language-css">@tailwind base;
@tailwind components;
@tailwind utilities;</code></pre>
<ol>
<li>빌드</li>
</ol>
<pre><code class="language-bash">&gt; npm run dev</code></pre>
<ol>
<li>간단예제</li>
</ol>
<pre><code class="language-bash">// src/App.js
import React from &#39;react&#39;;

function App() {
  return (
    &lt;div className=&quot;bg-blue-500 text-white p-4 rounded&quot;&gt;
      안녕하세요~!
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<h1 id="tailwindcss-장단점">TailwindCSS 장단점</h1>
<h3 id="장점">장점</h3>
<ol>
<li>CSS 코드를 직접 작성하지 않아도 된다.</li>
<li>그만큼 개발 속도가 빠르다.</li>
<li>체계적이고 일관된 디자인 사용이 가능 하다.</li>
</ol>
<h3 id="단점">단점</h3>
<ol>
<li>초기 설정이 조금 복잡할 수 있다.</li>
<li>코드가 안 이뻐짐.</li>
<li>CSS 크기가 커질 수 있다.</li>
</ol>
<h3 id="vscode-의-추천-익스텐션">VScode 의 추천 익스텐션</h3>
<p><code>Tailwind CSS IntelliSense</code> 익스텐션 입니다.
자동완성을 도와줍니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled-Components 의 개념과 장단점 활용 알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/Styled-Components-%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9E%A5%EB%8B%A8%EC%A0%90-%ED%99%9C%EC%9A%A9-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/Styled-Components-%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9E%A5%EB%8B%A8%EC%A0%90-%ED%99%9C%EC%9A%A9-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Tue, 06 Aug 2024 09:49:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/41d4b449-6b54-48e5-823a-8e036c66e6d1/image.webp" alt=""></p>
<h1 id="styled-components의-개념과-장단점">Styled-Components의 개념과 장단점</h1>
<h3 id="styled-components의-개념">Styled-Components의 개념</h3>
<p><code>Styled-Components</code>는 React와 함께 사용되는 <code>CSS-in-JS</code> 라이브러리로, JavaScript파일 내에서 스타일을 정의할 수 있습니다.</p>
<pre><code class="language-jsx">import styled from &#39;styled-components&#39;;

const BlueButton = styled.button`
    background-color: blue;
    color: white;
    padding: 10px;
    border-radius: 4px;
`;

function App() {
    return (
        &lt;&gt;
         &lt;BlueButton&gt;파란색 버튼&lt;BlueButton&gt;
        &lt;/&gt;
    );
}</code></pre>
<h3 id="styled-components의-장단점">Styled-Components의 장단점</h3>
<p>스타일이 컴포넌트에 한정되어 있어서 전역 스타일에 충돌이 발생하지 않습니다.
CSS의 모든 기능을 사용할 수 있으며, SASS와 같은 CSS 전처리기의 기능도 지원합니다.</p>
<p>런타임에 스타일을 생성하므로, 성능에 약간의 영향을 줄 수 있습니다.
프로젝트 크기에 따라 번들 크기가 커질 수 있습니다.</p>
<h1 id="css-in-js-의-개념">CSS-in-JS 의 개념</h1>
<h3 id="css-in-js의-개념">CSS-in-JS의 개념</h3>
<p><code>CSS-in-JS</code> 스타일은 JavaScript의 객체 형태로 정의하고, 컴포넌트와 함께 스타일을 구성합니다.</p>
<h1 id="cdd의-개념">CDD의 개념</h1>
<h3 id="cdd의-개념-1">CDD의 개념</h3>
<p>UI를 개별 컴포넌트 단위로 개발하고 조합하여 전체 애플리케이션을 구성하는 방법</p>
<h3 id="styled-components-설치">styled-Components 설치</h3>
<pre><code class="language-bash">npm install styled-components</code></pre>
<h3 id="간단-예제">간단 예제</h3>
<pre><code class="language-jsx">import styled from &#39;styled-components&#39;;

const BlueButton = styled.button`
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 4px;
  margin: 10px;
  width: 200px;
`;

function App() {
  return (
    &lt;&gt;
      &lt;div&gt;hello&lt;/div&gt;
      &lt;BlueButton&gt;파란색 버튼&lt;/BlueButton&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<h3 id="생성한-컴포넌트를-재사용하는-방법">생성한 컴포넌트를 재사용하는 방법</h3>
<pre><code class="language-jsx">import styled from &#39;styled-components&#39;;

const BlueButton = styled.button`
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 4px;
  margin: 10px;
  width: 200px;
`;

const BigBlueButton = styled(BlueButton)`
    width: 300px;
    height: 300px;
    padding: 15px;
`

function App() {
  return (
    &lt;&gt;
      &lt;div&gt;hello&lt;/div&gt;
      &lt;BlueButton&gt;파란색 버튼&lt;/BlueButton&gt;
      &lt;BigBlueButton&gt;큰 파란색 버튼&lt;/BigBlueButton&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<h3 id="클래스명을-지정하지-않아도-되는-이유">클래스명을 지정하지 않아도 되는 이유</h3>
<p>Styled-Components는 클래스명을 자동으로 생성하여 스타일을 적용하기 때문에 
따로 클래스명을 지정하지 않아도 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SCSS알아보기]]></title>
            <link>https://velog.io/@sangmin0310-afk/SCSS%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/SCSS%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Mon, 05 Aug 2024 15:53:54 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/1679b2b5-c770-438a-bc13-3b0f2843fca1/image.webp" alt=""></p>
<h1 id="scss의-변수-사용법">SCSS의 변수 사용법</h1>
<h3 id="scss-변수-선언">SCSS 변수 선언</h3>
<p>$변수명: 변수의 값;</p>
<p>이 변수는 CSS 스타일시트에서 반복적으로 사용되는 값들을 
재사용하기 위해 선언하고 사용할 수 있는 기능을 제공합니다.</p>
<p>간단예제</p>
<pre><code class="language-scss">$white: #fff;

.white{
    color: $white;
}

$font-size-base: 10px;
$padding-base: 10px;</code></pre>
<p>사용방법</p>
<pre><code class="language-scss">//변수 선언
$color: #000;
$font-size-base: 10px;
$padding-base: 10px;

//변수 사용
body{
    font-size: $font-size-base;
    color: color;
    padding: $padding-base;
}</code></pre>
<h1 id="scss-중첩-규칙-이해-및-활용">SCSS 중첩 규칙 이해 및 활용</h1>
<p>중첩규칙
중첩규칙은 CSS 선택자를 HTML의 구조와 유사하게 SCSS에서 표현할 수 있게 해줍니다.
이는 마크업 구조를 CSS에 직관적으로 반영할 수 있게 하여, 코드의 가독성과 유지보수성을 올려줍니다.
중접규칙을 사용하면, 상위 선택자를 반복해서 작성할 필요 없이, 관련 스타일을 그룹화하여 표현 할 수 있습니다.</p>
<pre><code class="language-scss">nav{
    ul{
        margin: 0;
        padding: 0;
        list-style: none;
    }

    li { display: inline-block; }
    a {
        display: block;
        padding: 6px 12px;
        text-decoration: none;
        }
    }

    nav ul {
        margin: 0;
        padding: 0;
        list-style: none;
    }
    nav li {
        display: inline-block;
    }
    nav a {
        display: block;
        padding: 6px 12px;
        text-decoration: none;
    }</code></pre>
<h3 id="scss의-장단점">SCSS의 장단점</h3>
<ul>
<li>장점: 스타일 시트를 더 가독성 있고 유지 보수하기 쉽게 만들 수 있습니다.</li>
<li>단점: 전처리기를 위한 도구 필요!, 컴파일 시간 소요</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[클래스형 컴포넌트 생명주기,
함수형 컴포넌트 생명주기]]></title>
            <link>https://velog.io/@sangmin0310-afk/%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</link>
            <guid>https://velog.io/@sangmin0310-afk/%ED%81%B4%EB%9E%98%EC%8A%A4%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0</guid>
            <pubDate>Wed, 31 Jul 2024 13:04:21 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스형-컴포넌트-생명주기">클래스형 컴포넌트 생명주기</h1>
<h3 id="componentdidmount"><code>componentDidMount</code></h3>
<p>컴포넌트가 처음으로 DOM에 마운트된 직후에 호출됩니다.</p>
<h3 id="componentdidupdate"><code>componentDidUpdate</code></h3>
<p>컴포넌트가 업데이트된 직후에 호출됩니다.
props나 state가 변경되어 다시 렌더링된 후에 실행됩니다.</p>
<h3 id="componentwillunmount"><code>componentWillUnmount</code></h3>
<p>컴포넌트가 DOM에서 제거되기 직전에 호출됩니다.</p>
<pre><code class="language-jsx">componentDidMount() {
    this.setupConnection();
}</code></pre>
<ul>
<li><code>componentDidMount</code> 메서드에서 <code>this.setupConnection()</code> 
을 호출하는 코드 입니다. 
컴포넌트가 처음 DOM에 마운트된 직후에 <code>setupConnection</code> 메서드를 실행합니다.</li>
</ul>
<pre><code class="language-jsx">componentDidUpdate(prevProps, prevState) {
    if(
        this.props.roomId !== prevProps.roomId ||
        this.state.serverUrl !== prevState.serverUrl
    ) {
        this.destroyConnection();
        this.setupConnection();
    }
}</code></pre>
<ul>
<li><code>componentDidUpdate</code> 는 <code>props</code> 나 <code>state</code> 가 변경됐을때
조건이 맞으면 기존 연결을 종료 후 새 연결을 합니다.</li>
</ul>
<pre><code class="language-jsx">componentWillUnmount() {
    this.destroyConnection();
}</code></pre>
<ul>
<li><code>componentWillUnmount</code> 는 컴포넌트가 언마운트되기 전에 호출
<code>destroyConnection</code> 을 호출하여 연결을 종료 합니다.</li>
</ul>
<h3 id="빈-배열">빈 배열</h3>
<pre><code class="language-jsx">useEffect(callback, []);</code></pre>
<p><code>dependency</code> 배열이 비어있을 때 
<code>useEffect</code> 가 포함된 컴포넌트가 맨 처음 마운트될 때만 callback 함수가 실행됩니다.</p>
<h3 id="dependency의존성">Dependency(의존성)</h3>
<p><code>useEffect</code> 훅에서 <code>dependency</code> 는 의존성 배열의 항목을 의미합니다.
의존성 배열에 포함된 값들이 변경될 때마다 <code>useEffect</code> 가 재실행됩니다.</p>
<h3 id="빈-배열이-아닐-때">빈 배열이 아닐 때</h3>
<pre><code class="language-jsx">useEffect(callback, [dependency]);</code></pre>
<p>컴포넌트가 처음 마운트 될 때, 그리고 <code>dependency</code> 에 포함된 <code>state</code> 나 <code>props</code> 등이 달라질때 callback 함수가 실행됩니다.</p>
<h3 id="배열이-아예-없을-때">배열이 아예 없을 때</h3>
<pre><code class="language-jsx">useEffect(callback);</code></pre>
<p>두 번째 (<code>dependency</code>) 인자가 아예 없는 경우, 컴포넌트가 처음으로 마운트 될 때와 재렌더링 될 때 콜백 함수가 실행됩니다.
하지만 <code>useEffect</code>에서 거의 쓰이지 않는 방법입니다.</p>
<h3 id="마운트">마운트</h3>
<p>DOM 객체가 (렌더링을 통해) 생성되어 브라우저에 나타나는 시점
클래스 컴포넌트 기준으로, 생성자가 호출된 후 <code>render()</code> 메서드가 호출되면 마운트가 발생합니다
컴포넌트의 생명주기 동안 단 한 번, 처음으로 DOM에 컴포넌트가 추가될 때 수행됩니다</p>
<h3 id="언마운트">언마운트</h3>
<p>DOM에서 컴포넌트가 사라질 때, 그 뒷정리를 담당하는 시점
보통 <code>clearInterval</code>, <code>clearTimemout</code> 등 등록된 작업을 제거하는 함수를 호출하거나, 인스턴스를 제거하는 경우에 사용합니다.</p>
<h3 id="리렌더링">리렌더링</h3>
<p>렌더링된 컴포넌트가 상태값 변화를 겪고 다시 렌더링되는 시점
함수 컴포넌트를 다시 호출하고, 이미 마운트된 컴포넌트에 어떤 변화사항을 적용할지 변경점을 가져오는 과정입니다.
가상 돔에 변화가 있었을 때, 컴포넌트 2개를 비교하여 차이를 적용시킬 때의 시점이라고 보면 됩니다.
이 작업 중에 리액트는 리액트만의 알고리즘을 통해 DOM에서 필요한 부분 (변경점) 만을 업데이트하여 실제 DOM 조작을 최소화합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Rest API 2일차]]></title>
            <link>https://velog.io/@sangmin0310-afk/Rest-API-2%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@sangmin0310-afk/Rest-API-2%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Fri, 26 Jul 2024 15:03:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>오늘은 Rest API에서 리소스에 대해 정리를 해보았습니다.
정확하지 않고 틀린 부분이 있을 수 도 있으니
그점 양해 부탁드립니다.</p>
</blockquote>
<blockquote>
<p>리소스란 무엇인가요?</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/31cf029f-81f4-40b7-9aab-edc821216c1e/image.jpg" alt=""></p>
<p>어디서 이 리소스라는걸 들어봤을까 하고 이미지를 찾아 보았을때 마인크래프트가 
떠오르더 라구요 우리는 마인크래프트에서 리소스 리소스 보통은 데이터를 표현 하죠</p>
<p>Rest 에서도 주요 데이터 표현을 <code>리소스</code> 라고 합니다.</p>
<blockquote>
<p>REST API는 상호 연결된 리소스의 집합으로 구성됩니다. 
이 리소스 집합을 REST API  리소스 모델 이라고 합니다.</p>
</blockquote>
<blockquote>
<p><a href="https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_2_1_1">— Roy Fielding의 논문</a>
REST에서 정보의 핵심 추상화는 리소스입니다. 
이름을 지정할 수 있는 모든 정보는 리소스가 될 수 있습니다. 
문서나 이미지, 시간적 서비스(예: &quot;로스앤젤레스의 오늘 날씨&quot;), 
다른 리소스 모음, 비가상 객체(예: 사람) 등이 있습니다.
다시 말해, 저자의 하이퍼텍스트 참조의 대상이 될 수 있는 모든 개념은 리소스의 정의에 맞아야 합니다.
리소스는 특정 시점의 매핑에 해당하는 엔터티가 아닌 엔터티 집합에 대한 개념적 매핑입니다.</p>
</blockquote>
<blockquote>
<p>1-1 싱글톤과 컬렉션 리소스</p>
</blockquote>
<p>리소스 는 <strong>싱글톤이거나 컬렉션</strong>일 수 있습니다.</p>
<p>예를 들어, <code>customers</code> 는 컬렉션 리소스이고 <code>customer</code> 는 싱글톤 리소스
(은행 도메인)입니다.</p>
<p><code>customersURI</code> &quot; &quot; 를 사용하여 &quot; &quot; 컬렉션 리소스를 식별할 수 있습니다. 
URI &quot; &quot;를 사용하여 <code>/customers</code> 단일 &quot; &quot; 리소스를 식별할 수 있습니다 <code>.customer/customers/{customerId}</code></p>
<pre><code>/customers            // 컬렉션 리소스

/customers/{id}        // 싱글톤 리소스</code></pre><blockquote>
<p>1-2 컬렉션 및 하위 컬렉션 리소스</p>
</blockquote>
<p>리소스 에는 <strong>하위 컬렉션 리소스</strong> 도 포함될 수 있습니다.</p>
<p><code>accounts</code> 예를 들어, 특정 &quot; &quot;의 하위 컬렉션 리소스 &quot; &quot;는 <code>customerURN</code>  <code>/customers/{customerId}/accounts</code> (은행 도메인에서)을 사용하여 식별할 수 있습니다.</p>
<p><code>account</code> 마찬가지로, 하위 컬렉션 리소스 &quot; &quot; 내부의 싱글톤 리소스  <code>accounts</code> 는 다음과 같이 식별할 수 있습니다:  <code>/customers/{customerId}/accounts/{accountId}</code></p>
<pre><code>/customers                        //컬렉션 리소스

/customers/{id}/accounts        //서브 컬랙션 리소스 </code></pre><blockquote>
<p>2-1 리소스 식별자</p>
</blockquote>
<p>REST는 리소스 식별자를 사용하여 클라이언트와 서버 구성 요소 간 상호작용에 관련된 각 리소스를 식별합니다.</p>
<blockquote>
<p>2-2 하이퍼 미디어</p>
</blockquote>
<p>표현의 데이터 형식은  <strong>미디어 유형</strong> 이라고 합니다 . 
미디어 유형은 표현이 처리되는 방식을 정의하는 사양을 식별합니다.</p>
<p><strong>RESTful API는  <code>하이퍼텍스트</code> 처럼 보입니다</strong> . 모든 주소 지정 가능한 정보 단위는 명시적으로(예: link 및 id 속성) 또는 암묵적으로(예: 미디어 유형 정의 및 표현 구조에서 파생) 주소를 전달합니다.</p>
<blockquote>
<p>하이퍼텍스트 (또는 하이퍼미디어)는  정보와 제어를 동시에 제공하는 것을 의미  하며, 정보가 사용자(또는 오토마타)에게 선택권을 제공하고 행동을 취할 수 있는 수단이 됩니다.
하이퍼텍스트는 브라우저에서 HTML(또는 XML 또는 JSON)일 필요가 없다는 것을 기억하세요. 기계는 데이터 형식과 관계 유형을 이해하면 링크를 따라갈 수 있습니다.
— 로이 필딩</p>
</blockquote>
<blockquote>
<p>2-3 자기 설명적</p>
</blockquote>
<p><strong>리소스 표현은 자체 설명적이어야 합니다.</strong> 
클라이언트는 리소스가 직원인지 장치인지 알 필요가 없습니다. 
리소스와 연관된 미디어 유형에 따라 작동해야 합니다.</p>
<p>따라서 실제로는 여러 개의  <strong>사용자 정의 미디어 유형을</strong> 만들 것입니다. 
일반적으로 하나의 미디어 유형이 하나의 리소스와 연결됩니다.</p>
<p>모든 미디어 유형은 기본 처리 모델을 정의합니다. 
예를 들어, HTML은 하이퍼텍스트의 렌더링 프로세스와 각 요소 주변의 브라우저 동작을 정의합니다.</p>
<blockquote>
<p>미디어 유형은 일부 미디어 유형 요소가 &quot;특성이 있는 앵커 요소가 선택하면 -인코딩된 특성에 해당하는 URI에서 검색 요청(GET)을 호출하는 하이퍼텍스트 링크를 생성한다&quot;와 같은 프로세스 모델을 정의한다는 사실 외에는 
리소스 메서드 <code>GET href/PUT/POST/DELETE/…</code>와 관련이 없습니다 
.CDATAhref</p>
</blockquote>
<blockquote>
<p>2-4 예제
HTTP 기반 REST API에서 관련 리소스에 대한 링크가 있는 블로그 게시물을 나타내는 다음 REST 리소스를 고려하세요. 
여기에는 블로그 게시물에 대한 필수 정보와 작성자 및 댓글과 같은 관련 리소스에 대한 하이퍼미디어 링크가 있습니다. 
클라이언트는 이러한 링크를 따라 추가 정보를 찾거나 작업을 수행할 수 있습니다.</p>
</blockquote>
<pre><code>{
  &quot;id&quot;: 123,
  &quot;title&quot;: &quot;What is REST&quot;,
  &quot;content&quot;: &quot;REST is an architectural style for building web services...&quot;,
  &quot;published_at&quot;: &quot;2023-11-04T14:30:00Z&quot;,
  &quot;author&quot;: {
    &quot;id&quot;: 456,
    &quot;name&quot;: &quot;John Doe&quot;,
    &quot;profile_url&quot;: &quot;https://example.com/authors/456&quot;
  },
  &quot;comments&quot;: {
    &quot;count&quot;: 5,
    &quot;comments_url&quot;: &quot;https://example.com/posts/123/comments&quot;
  },
  &quot;self&quot;: {
    &quot;link&quot;: &quot;https://example.com/posts/123&quot;
  }
}</code></pre><p><strong>1. id: 123</strong></p>
<p>리소스의 고유 식별자입니다. 이 경우, 게시물의 ID가 123입니다.</p>
<p><strong>2. title: &quot;What is REST&quot;</strong></p>
<p>게시물의 제목입니다. 여기서는 &quot;REST란 무엇인가&quot;라는 제목을 가지고 있습니다.</p>
<p><strong>content: &quot;REST is an architectural style for building web services...&quot;</strong></p>
<p>게시물의 내용입니다. 이 경우 REST가 무엇인지에 대한 설명이 포함되어 있습니다.</p>
<p><strong>published_at: &quot;2023-11-04T14:30:00Z&quot;</strong></p>
<p>게시물이 게시된 날짜와 시간입니다. 여기서는 2023년 11월 4일 14:30 UTC에 게시되었습니다.</p>
<p><strong>author:</strong></p>
<p>id: 456</p>
<ul>
<li>작성자의 고유 식별자입니다. 이 경우, 작성자의 ID가 456입니다.</li>
</ul>
<p>name: &quot;John Doe&quot;</p>
<ul>
<li>작성자의 이름입니다. 여기서는 &quot;John Doe&quot;입니다.</li>
</ul>
<p>profile_url: &quot;<a href="https://example.com/authors/456&quot;">https://example.com/authors/456&quot;</a></p>
<ul>
<li>작성자의 프로필 URL입니다. 이 링크를 통해 작성자의 프로필 페이지로 이동할 수 있습니다.</li>
</ul>
<p><strong>comments:</strong></p>
<p>count: 5</p>
<ul>
<li>이 게시물에 달린 댓글의 수입니다. 여기서는 5개의 댓글이 있습니다.</li>
</ul>
<p>comments_url: &quot;<a href="https://example.com/posts/123/comments&quot;">https://example.com/posts/123/comments&quot;</a></p>
<ul>
<li>댓글들이 있는 URL입니다. 이 링크를 통해 댓글 목록을 볼 수 있습니다.</li>
</ul>
<p><strong>self:</strong></p>
<p>link: &quot;<a href="https://example.com/posts/123&quot;">https://example.com/posts/123&quot;</a></p>
<ul>
<li>이 리소스 자체를 가리키는 URL입니다. 이 링크를 통해 게시물의 상세 페이지로 
이동할 수 있습니다.</li>
</ul>
<p>오늘은 여기까지 하고 다음시간에 Rest API(이론)을 가지고 오도록 하겠습니다.</p>
<blockquote>
<p>아직 어려운점도 부족한 점도 많지만
프론트엔드로 진출하기 위해 한 계단을 오른 프린이 일기였습니다.
끝까지 읽어주신분들 감사합니다~!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[마리오 두더지 잡기 4일차]]></title>
            <link>https://velog.io/@sangmin0310-afk/%EB%A7%88%EB%A6%AC%EC%98%A4-%EB%91%90%EB%8D%94%EC%A7%80-%EC%9E%A1%EA%B8%B0-4%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@sangmin0310-afk/%EB%A7%88%EB%A6%AC%EC%98%A4-%EB%91%90%EB%8D%94%EC%A7%80-%EC%9E%A1%EA%B8%B0-4%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Thu, 25 Jul 2024 17:30:36 GMT</pubDate>
            <description><![CDATA[<p>오늘은 자바스크립트 22일차 되는 날 입니다..
오늘은 제 개인 프로젝트로 저의 학습 능력을
향상 시키기 위해 준비한 프로그램입니다!
클론코딩에 저의 추가 프로그램을 준비해서
만들어보았습니다.</p>
<p>오늘의 프로젝트는 마리오 두더지 잡기 2일차 입니다!
이 프로젝트의 요구사항을 말씀드리겠습니다.</p>
<blockquote>
<p>&lt;추가요구사항&gt;
3일차 4일차 나누기가 너무 추가 범위가 (제대로 정리 안한점 죄송합니다..)
넓어서 제가 추가한 부분에서 처음 알게되고 그 어디에서 도 쓰지않았던 
사운드를 추가해봤습니다.
오늘은 이 사운드에 대해 알려드릴려고 합니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/sangmin0310-afk/post/d4d306d9-a778-4e18-b916-c215e06148db/image.gif" alt=""></p>
<p><strong>이건 전체적으로 추가한 간단한 영상입니다.
영상이 너무 커질까봐 생략된 부분이 많습니다.</strong></p>
<p>우리는 왜 사운드라는 걸 추가를 할까? 라는 질문에 저는 이러한 
주관적인 생각이 나왔습니다.</p>
<p>여러부분이 있다고 생각합니다.</p>
<blockquote>
<ol>
<li>접근성 향상 시각 장애가 있는 사용자에게 사운드는 중요한 정보 제공 수단이 될 수 있고 화면에 나타나는 정보를 음성으로 전달하거나, 
시각적 피드백을 소리로 제공함으로써 접근성을 향상시킬 수 있기 때문에.</li>
<li>위에 맞춰 브랜딩 및 개성 사운드는 프로그램이나 애플리케이션의 브랜드 아이덴티티를 강화하는 데 사용될 수 있어 특정 사운드나 음악은 브랜드와 연결되어 사용자의 기억에 남을 수 있기 때문에. </li>
<li>몰입감 및 분위기 조성 게임이나 멀티미디어 애플리케이션에서는 사운드가 몰입감과 분위기를 조성하는 데 중요한 역할을하고 배경 음악이나 효과음은 사용자가 더 깊이 몰입할 수 있도록 도와주기 때문에.</li>
</ol>
</blockquote>
<p><strong>이것 말고 도 여러 등등 이유가 있고 자기의 프로그램 목적에 맞게 사운드가 사용 되고 있을 것 입니다.</strong> </p>
<p>그러면 저는 이 자바스크립트 프로그램에서 어떻게 사운드를 집어넣어야 할까?
라는 생각이 들었습니다.</p>
<p><strong>어떠한 것이 사운드를 넣을 수 있을까?</strong></p>
<p>HTML5의 <code>&lt;audio&gt;</code> 요소를 사용하면 HTML 문서에 직접 사운드를 삽입하고 자바스크립트를 통해 제어할 수 있습니다.</p>
<blockquote>
<p><code>&lt;audio&gt;</code> 요소 </p>
</blockquote>
<pre><code>&lt;audio id=&quot;background-music&quot; src=&quot;./music/Super Mario Bross - Theme Song.mp3&quot; loop&gt;&lt;/audio&gt;</code></pre><p> 예시코드는 제가 사용한 코드입니다.</p>
<p>이 코드 같은 경우에는 게임이 시작이 되었을때 배경음악을 담당하고 있습니다.</p>
<p>그럼 이 <code>&lt;audio&gt;</code> 요소는 어떻게 자바스크립트에서 활용이 될까요?</p>
<blockquote>
<p>이 함수는 주어진 URL의 사운드 파일을 재생합니다.</p>
</blockquote>
<pre><code>function playSound(soundUrl) {
    const audio = new Audio(soundUrl);
    audio.volume = 0.2; // 볼륨 조절
    audio.play().catch(error =&gt; {
        console.error(&quot;소리 재생 오류: &quot;, error);
    });
}</code></pre><p>Audio 객체를 생성하여 주어진 soundUrl의 사운드를 로드합니다.
볼륨을 0.2로 설정하여 소리의 크기를 조절합니다.
play() 메서드를 호출하여 소리를 재생합니다.
사운드 재생 중 오류가 발생하면, 콘솔에 오류 메시지를 출력합니다.</p>
<p>그리고 </p>
<pre><code>&lt;button id=&quot;instructions-button&quot; data-sound=&quot;./music/설정사운드.wav&quot;&gt;Instructions&lt;/button&gt;

&lt;button id=&quot;start-button&quot; data-sound=&quot;./music/start.wav&quot;&gt;Start&lt;/button&gt;

&lt;button id=&quot;exit-button&quot; data-sound=&quot;./music/게임종료버튼.wav&quot;&gt;Exit&lt;/button&gt;</code></pre><p>버튼에서 도 버튼 클릭 등의 이벤트에 따라 사운드를 재생할 수 있습니다.</p>
<p>그럼 자바스크립트에서는 </p>
<pre><code> document.getElementById(&quot;instructions-button&quot;).addEventListener(&quot;click&quot;, function() {
        playSound(this.getAttribute(&quot;data-sound&quot;)); // 버튼에 설정된 소리 재생
        showInstructions();
    });</code></pre><p>HTML 문서에서 ID가 &quot;instructions-button&quot;인 요소(버튼)를 선택합니다.</p>
<p>addEventListener(&quot;click&quot;, function() { }) 이 버튼에 클릭 이벤트 리스너를 추가합니다. 
버튼이 클릭될 때 실행될 함수(function() { })를 정의합니다.</p>
<p>this.getAttribute(&quot;data-sound&quot;) 클릭된 버튼(this)의 data-sound 속성 값을 가져옵니다 
이 속성 값은 사운드 파일의 경로를 포함하고 있습니다.</p>
<p>playSound(this.getAttribute(&quot;data-sound&quot;)) playSound 함수에 data-sound 속성에서 가져온 경로를 전달합니다. 
playSound 함수는 이 경로를 사용해 사운드를 로드하고 재생합니다.</p>
<blockquote>
<p>이러한 방법으로 사운드를 각자 의 역할에 맞게 배치를 해두면 
원하는 방향의 프로그램이 만들어집니다.</p>
</blockquote>
<p><strong>그럼 제가 자바스크립트에서 사운드를 활용한 코드를 보여드리겠습니다.</strong></p>
<blockquote>
<p>이 함수는 주어진 URL의 사운드 파일을 재생합니다. </p>
</blockquote>
<pre><code>function playSound(soundUrl) {
    const audio = new Audio(soundUrl);
    audio.volume = 0.2; // 볼륨 조절
    audio.play().catch(error =&gt; {
        console.error(&quot;소리 재생 오류: &quot;, error);
    });
}</code></pre><p>Audio 객체를 생성하여 주어진 soundUrl의 사운드를 로드합니다.
볼륨을 0.2로 설정하여 소리의 크기를 조절합니다.
play() 메서드를 호출하여 소리를 재생합니다.
사운드 재생 중 오류가 발생하면, 콘솔에 오류 메시지를 출력합니다.</p>
<blockquote>
<p>이 함수는 배경 음악을 중지하고 재생 위치를 처음으로 되돌립니다.</p>
</blockquote>
<pre><code>function stopBackgroundMusic() {
    const music = document.getElementById(&quot;background-music&quot;);
    music.pause();
    music.currentTime = 0; // 음악 재생 위치를 처음으로 되돌림
}</code></pre><p>pause() 메서드를 호출하여 음악을 일시 정지합니다.
currentTime을 0으로 설정하여 음악의 재생 위치를 처음으로 되돌립니다.</p>
<blockquote>
<p>이 함수는 게임 오버 시 재생할 사운드를 재생합니다. </p>
</blockquote>
<pre><code>function playGameOverSound() {
    const gameOverSound = new Audio(&quot;./music/Game over.wav&quot;);
    gameOverSound.play().catch(error =&gt; {
        console.error(&quot;게임 오버 사운드 재생 오류: &quot;, error);
    });
}</code></pre><p>Audio 객체를 생성하여 &quot;./music/Game over.wav&quot; 파일을 로드합니다.
play() 메서드를 호출하여 사운드를 재생합니다.
사운드 재생 중 오류가 발생하면, 콘솔에 오류 메시지를 출력합니다.</p>
<blockquote>
<p>함수는 게임 승리 시 재생할 사운드를 재생합니다. </p>
</blockquote>
<pre><code>function playWinSound() {
    const winSound = new Audio(&quot;./music/승리시.mp3&quot;);
    winSound.play().catch(error =&gt; {
        console.error(&quot;승리 사운드 재생 오류: &quot;, error);
    });
}</code></pre><p>Audio 객체를 생성하여 &quot;./music/승리시.mp3&quot; 파일을 로드합니다.
play() 메서드를 호출하여 사운드를 재생합니다.
사운드 재생 중 오류가 발생하면, 콘솔에 오류 메시지를 출력합니다.</p>
<blockquote>
<p>버튼 클릭 시 사운드 재생</p>
</blockquote>
<pre><code>document.getElementById(&quot;start-button&quot;).addEventListener(&quot;click&quot;, function() {
    playSound(this.getAttribute(&quot;data-sound&quot;)); // 버튼에 설정된 소리 재생
    // 기타 게임 시작 로직...
});</code></pre><p>각 버튼의 클릭 이벤트 핸들러는 playSound() 함수를 호출하여 해당 버튼에 설정된 소리(data-sound 속성)를 재생합니다. </p>
<blockquote>
<p>이 프로그램에 사운드를 넣으면서 의 가장 큰 문제점은 상호작용인것 같습니다.
음악이 안나오는 경우도 있고 음악이 나왔다 안나왔다 하는 부분에 뭐가 문제지 하는데 
정답은 가까웠습니다.</p>
</blockquote>
<blockquote>
<pre><code>window.onload = function() {
    // 버튼 클릭 이벤트 핸들러 설정
    document.getElementById(&quot;start-button&quot;).addEventListener(&quot;click&quot;, function() {
        playSound(this.getAttribute(&quot;data-sound&quot;)); // 버튼에 설정된 소리 재생
        const music = document.getElementById(&quot;background-music&quot;);
        music.volume = 0.1; // 볼륨 조절 (0.0에서 1.0 사이)
        music.play().catch(error =&gt; {
            console.error(&quot;음악 재생 오류: &quot;, error);
        });
        startGame(); // 게임 시작 함수 호출
    });</code></pre></blockquote>
<pre><code>바로 여기서 문제가 일어 났습니다.

요약해서 설명하자면
1. 페이지가 로드되면, &quot;start-button&quot; ID를 가진 버튼에 클릭 이벤트 리스너가 추가됩니다.
2. 사용자가 이 버튼을 클릭하면, 버튼의 data-sound 속성에 설정된 소리가 재생됩니다.
3. 배경 음악을 찾은 후, 그 볼륨을 설정하고 재생합니다.
4. startGame() 함수를 호출하여 게임을 시작합니다.

여기서 저는 이 4번 startGame()함수를 넣지 않고 사운드 재생오류에 애를 쓰고 있었는데 게임이 시작이 되면 나오는 사운드인데 저는 버튼을 누르면 사운드가 실행이 될줄알고  startGame(); 호출을 뒤늦게 깨달아 넣으니 이문제는 없어졌습니다.

아직 업데이트 중인 프로그램이라 4일차라는 표시를 해놨습니다.

추가 하는 부분은 또 차수에 블로그로 뵙겠습니다.

아직 어려운점도 부족한 점도 많지만
프론트엔드로 진출하기 위해 한 계단을 오른 프린이 일기였습니다.

끝까지 읽어주신분들 감사합니다~!
</code></pre>]]></description>
        </item>
    </channel>
</rss>