<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>100%.log</title>
        <link>https://velog.io/</link>
        <description>Road to FE</description>
        <lastBuildDate>Tue, 04 Jun 2024 08:16:31 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>100%.log</title>
            <url>https://velog.velcdn.com/images/100-100/profile/1b3896c6-b1c1-4908-9378-f5f1dfb0aa46/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 100%.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/100-100" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[React - Redux]]></title>
            <link>https://velog.io/@100-100/React-Redux</link>
            <guid>https://velog.io/@100-100/React-Redux</guid>
            <pubDate>Tue, 04 Jun 2024 08:16:31 GMT</pubDate>
            <description><![CDATA[<h1 id="react---redux">React - redux</h1>
<h2 id="redux란">Redux란?</h2>
<p>크로스 컴포넌트 또는 앱 와이드 상태를 위한 생태 관리 시스템이다.<br>먼저, 상태(state)는 세 가지로 구분된다.   </p>
<ol>
<li>로컬 상태<ul>
<li>데이터가 변경되어서 하나의 컴포넌트에 속하는 UI에 영향을 미치는 상태</li>
<li>예를 들어 특정 UI를 감추거나 보여주는 토글</li>
</ul>
</li>
<li>크로스 컴포넌트 상태<ul>
<li>다수의 컴포넌트에 영향을 미치는 상태</li>
<li>prop 드릴링 발생</li>
</ul>
</li>
<li>앱 와이드 상태<ul>
<li>애플리케이션의 모든 컴포넌트에 영향을 미치는 상태</li>
<li>예를 들어 사용자 인증</li>
</ul>
</li>
</ol>
<h2 id="why-redux">Why Redux?</h2>
<p>리액트 컨텍스트 또한 상태 관리 시스템인데 왜 리덕스가 필요할까?<br>리액트 컨텍스트는 잠재적인 단점이 몇개 있다.   </p>
<ol>
<li>많은 컴포넌트와 내용이 있는 애플리케이션이라면 설정과 상태관리가 복잡해질 수 있다.<ul>
<li>심하게 중첩되는 JSX코드 &amp; 다양하고 많은 ContextProvider 또는 유지하기 어려운 거대한 하나의 ContextProvider</li>
</ul>
</li>
<li>데이터가 자주 변경되는 경우 성능적으로 적합하지 않다.</li>
</ol>
<h2 id="redux의-작동-방식">Redux의 작동 방식</h2>
<p>Redux는 애플리케이션에 있는 하나의 중앙 데이터 저장소이다.<br>여기서 데이터는 <strong>상태</strong>를 가르킨다.<br>애플리케이션은 한 개의 저장소만 갖게되며 그 저장소에 전체 애플리케이션의 모든 상태를 저장한다.<br>그렇다면 관리가 어려울 것 같지만 Redux는 다행히 그 저장소 전체를 항상 직접 관리할 필요가 없다.   </p>
<h3 id="구독subscription">구독(Subscription)</h3>
<p>컴포넌트는 중앙 저장소에 있는 데이터(상태)의 변화를 감지하여 그에 맞는 대응을 하기위해 <strong>구독(Subscription)</strong> 을 설정한다.<br>컴포넌트가 저장소를 구독하면 데이터가 변경될 때마다 컴포넌트에게 알려주게 된다.</p>
<h3 id="reducer-function">Reducer function</h3>
<p>컴포넌트가 구독을 통해 받은 데이터는 변경이 필요하기도하다.<br>저장된 데이터를 어떻게 변경할까? 여기엔 아주 중요한 규칙이 있다.<br>컴포넌트는 절대로 저장된 데이터를 직접 조작하지 않는다.<br>그래서 구독을 하는 것이고 직접적은 흐름으로 봤을때 데이터는 절대로 반대 방향으로 흐르지 않는다.<br>그 대신 <strong>리듀서(Reducer)</strong> 라는 개념을 이용한다.<br>이 리듀서 함수를 설정하고 이 함수는 저장소 데이터의 변경, 즉 업데이트를 담당한다.   </p>
<h3 id="action">Action</h3>
<p>구독과 Reducer가 있다. 이제 컴포넌트와 그 Reducer 함수를 어떻게 연결할까?<br><strong>액션(Action)</strong> 이라는 개념이 있으며 컴포넌트가 액션을 발송한다.<br>예를 들면 어떤 컴포넌트 버튼이 있고 클릭 시 상태를 변경하는 함수를 실행하듯 컴포넌트가 어떤 액션을 트리거한다 말할 수도 있다.<br>액션은 단순한 자바스크립트 객체이며 Reducer가 수행해야 할 작업을 설명하게 된다.   </p>
<h3 id="정리">정리</h3>
<ol>
<li>컴포넌트가 Action을 발송(Action에는 수행해야 할 작업이 설명되어 있지만 그걸 직접하진 않음)</li>
<li>Reducer가 Action이 원하는 작업을 수행하고 새로운 상태를 뱉어낸다. 새로운 상태는 저장소의 기존 상태를 대체하게 된다.</li>
<li>데이터 저장소의 상태가 업데이트되면 구독 중인 컴포넌트가 알림을 받게 되고 컴포넌트는 UI를 업데이트할 수 있게 된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - useMemo(vs useCallback)]]></title>
            <link>https://velog.io/@100-100/React-useMemovs-useCallback</link>
            <guid>https://velog.io/@100-100/React-useMemovs-useCallback</guid>
            <pubDate>Mon, 27 May 2024 04:44:26 GMT</pubDate>
            <description><![CDATA[<h1 id="usememo와-usecallback-react-성능-최적화-훅">useMemo와 useCallback: React 성능 최적화 훅</h1>
<p>React 애플리케이션의 성능을 최적화하기 위해 <code>useMemo</code>와 <code>useCallback</code> 훅을 사용하는 방법에 대해 알아보자.<br>이 두 훅은 컴포넌트가 불필요하게 다시 렌더링되는 것을 방지해 성능을 향상시키는 데 중요한 역할을 한다.</p>
<hr>
<h2 id="usememo">useMemo</h2>
<p><code>useMemo</code>는 메모이제이션된 값을 반환하는 훅이다. 
특정 값이 변경될 때까지 이전에 계산된 값을 재사용할 수 있게 하며, 이는 비용이 많이 드는 계산을 최적화하는 데 유용하다.</p>
<h3 id="사용법">사용법</h3>
<pre><code class="language-javascript">import React, { useMemo } from &#39;react&#39;;

const MyComponent = ({ num }) =&gt; {
  const squaredNum = useMemo(() =&gt; {
    console.log(&#39;Calculating squared number...&#39;);
    return num * num;
  }, [num]);

  return &lt;div&gt;Squared Number: {squaredNum}&lt;/div&gt;;
};</code></pre>
<h3 id="설명">설명</h3>
<ul>
<li><code>useMemo</code>의 첫 번째 인자는 계산 함수.</li>
<li>두 번째 인자는 의존성 배열로, 이 배열의 값이 변경될 때만 계산 함수가 호출된다.</li>
<li>위 예제에서는 num이 변경될 때만 제곱 값이 다시 계산된다.</li>
</ul>
<hr>
<h2 id="usecallback">useCallback</h2>
<p><code>useCallback</code>은 메모이제이션된 콜백 함수를 반환하는 훅이다. 
콜백 함수가 필요 없는 재생성을 방지하여, 자식 컴포넌트에 전달할 때 참조 동일성을 유지할 수 있다.</p>
<h3 id="사용법-1">사용법</h3>
<pre><code class="language-javascript">import React, { useCallback } from &#39;react&#39;;

const MyComponent = ({ onClick }) =&gt; {
  return &lt;button onClick={onClick}&gt;Click Me&lt;/button&gt;;
};

const ParentComponent = () =&gt; {
  const handleClick = useCallback(() =&gt; {
    console.log(&#39;Button clicked&#39;);
  }, []);

  return &lt;MyComponent onClick={handleClick} /&gt;;
};
</code></pre>
<h3 id="설명-1">설명</h3>
<ul>
<li><code>useCallback</code>의 첫 번째 인자는 콜백 함수.</li>
<li>두 번째 인자는 의존성 배열로, 이 배열의 값이 변경될 때만 콜백 함수가 재생성된다.</li>
<li>위 예제에서는 의존성 배열이 비어 있어, <code>handleClick</code> 함수는 컴포넌트의 수명 동안 변경되지 않는다.</li>
</ul>
<hr>
<h3 id="usememo와-usecallback의-차이점">useMemo와 useCallback의 차이점</h3>
<table>
<thead>
<tr>
<th align="left">특정</th>
<th align="left">useMemo</th>
<th align="left">useCallback</th>
</tr>
</thead>
<tbody><tr>
<td align="left">반환 값</td>
<td align="left">메모이제이션된 값</td>
<td align="left">메모이제이션된 함수</td>
</tr>
<tr>
<td align="left">주 사용 사례</td>
<td align="left">계산 비용이 높은 값을 메모이제이션하여 성능 최적화</td>
<td align="left">동일한 함수 참조를 유지하여 불필요한 렌더링 방지</td>
</tr>
<tr>
<td align="left">의존성 배열</td>
<td align="left">값이 변경될 때까지 계산 함수를 재실행하지 않음</td>
<td align="left">의존성이 변경되지 않는 한 함수 참조가 변경되지 않음</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - useCallback]]></title>
            <link>https://velog.io/@100-100/React-useCallback</link>
            <guid>https://velog.io/@100-100/React-useCallback</guid>
            <pubDate>Mon, 08 Apr 2024 02:44:08 GMT</pubDate>
            <description><![CDATA[<h1 id="usecallback">useCallback</h1>
<p>자바스크립트의 함수는 객체의 한 종류이다.   </p>
<pre><code class="language-javascript">const consoleFunction = (str) =&gt; {
   console.log(str);
}</code></pre>
<p>위 코드를 보면 consoleFunction 변수에 함수 객체가 할당되어 있다.<br>이는 리액트에서 컴포넌트가 다시 렌더링된다면 완전히 새로운 함수가 생성됨을 의미한다.<br>말했듯이 <strong>자바스크립트에서 함수는 객체</strong> 이기 때문이다.<br>같은 모양과 같은 값이더라도 자바스크립트의 객체는 이를 동일하다고 여기지 않는다.<br>결국 불필요한 렌더링이 발생할 수 있는 상황이 생기는 것이다.<br>또한 함수를 useEffect같은 훅에서 의존성으로 추가한다면 상황에따라 무한루프를 유발할 위험도 있으며 최적화면에서도 좋지 않을거라 보인다.</p>
<p>useCallback은 함수를 재사용하여 이러한 점들을 개선할 수 있게 해주고 컴포넌트 성능을 최적화 시켜주는 Hook이다.   </p>
<ol>
<li>이벤트 핸들러 함수의 잦은 재생성</li>
<li>하위 컴포넌트에 props로 전달되는 함수의 잦은 재생성</li>
<li>렌더링 최적화가 필요한 경우</li>
</ol>
<h3 id="usecallback-사용">useCallback 사용</h3>
<p>useCallback도 useEffect와 같이 2개의 인자를 받는다.</p>
<pre><code class="language-jsx">import React, { useEffect, useCallback } from &#39;react&#39;;

function App() {

   const consoleFunction = useCallback(() =&gt; { console.log(&#39;useCallback&#39;) }, [dependency]);

   return (
      // 컴포넌트
   )
}</code></pre>
<p>consoleFunction 안에있는 함수는 App 컴포넌트가 렌더링 될 때 만들어져 해당 함수의 주소가 들어간다.<br>그 다음 렌더링부터는 함수를 재생성하는 것이 아니라 기억된 주소를 가지고 재사용하는 것이다.<br>만약 의존성 배열안에 값이 있다면 해당 값이 변경될때만 안에있는 함수를 재생성하게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - useEffect]]></title>
            <link>https://velog.io/@100-100/React-useEffect</link>
            <guid>https://velog.io/@100-100/React-useEffect</guid>
            <pubDate>Mon, 08 Apr 2024 01:30:38 GMT</pubDate>
            <description><![CDATA[<h2 id="react---useeffect">React - useEffect</h2>
<h3 id="useeffct">useEffct</h3>
<p>컴포넌트의 Lifecycle을 3가지로 분류해보자.   </p>
<ol>
<li>컴포넌트 마운트</li>
<li>컴포넌트 업데이트(리렌더링)</li>
<li>컴포넌트 언마운트</li>
</ol>
<p>useEffect는 이러한 생명주기 사이사이에 간섭을 줄 수 있는 Hook이다.   </p>
<h3 id="useeffect-형태">useEffect 형태</h3>
<p>useEffect는 실행할 함수코드 &amp; 의존성 배열, 2가지의 인수를 받으며 컴포넌트가 렌더링 된 후에 실행된다.   </p>
<ol>
<li>기본<ul>
<li>의존성 배열이 없는 경우 컴포넌트가 랜더링 될 때마다 side effect가 실행된다.   <pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;;
</code></pre>
</li>
</ul>
</li>
</ol>
<p>function App() {
  useEffect(() =&gt; {
    console.log(&#39;I am useEffect&#39;);
  })</p>
<p>  return (
    // 컴포넌트
  )
}</p>
<pre><code>
2. 빈 의존성 배열
    - 비어있는 의존성 배열이 있을 경우 컴포넌트가 마운트 될 때 한번만 실행된다.
```jsx
import React, { useEffect } from &#39;react&#39;;

function App() {
  useEffect(() =&gt; {
    console.log(&#39;I am useEffect&#39;);
  }, [])

  return (
    // 컴포넌트
  )
}</code></pre><ol start="3">
<li>값이 있는 의존성 배열<ul>
<li>배열 내의 값이 변경될 때마다 실행된다, 의존성 값이 state라면 당연히 컴포넌트도 다시 렌더링된다.<pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;;
</code></pre>
</li>
</ul>
</li>
</ol>
<p>function App() {
  useEffect(() =&gt; {
    console.log(&#39;I am useEffect&#39;);
  }, [dependency])</p>
<p>  return (
    // 컴포넌트
  )
}</p>
<pre><code>
### clean up
useEffect에 return문으로 함수를 추가하여 clean up 함수를 추가할 수 있다.   
이는 메모리 정리 및 오류를 방지하는데 도움이 된다.
```jsx
import React, { useEffect } from &#39;react&#39;;

function App() {
  useEffect(() =&gt; {
    const timer = setInterval(() =&gt; {
      console.log(&#39;timer&#39;);
    }, 1000);

    return () =&gt; {
      clearInterval(timer);
    }
  }, [dependency])

  return (
    // 컴포넌트
  )
}</code></pre><p>useEffect의 return문, 즉 clean up function은 두 가지 경우에 실행된다.   </p>
<ol>
<li><p>컴포넌트 언마운트 </p>
<ul>
<li>컴포넌트가 DOM에서 제거될 때 실행되어 메모리 누수를 방지하고 컴포넌트 리소스를 정리할 수 있다.   </li>
</ul>
</li>
<li><p>side effect 실행 전</p>
<ul>
<li>의존성 배열에 있는 값이 변경되어 side effect가 다시 실행되기 전에 이전 side effect의 효과를 정리한다.</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - ref & potal]]></title>
            <link>https://velog.io/@100-100/React-ref-potal-i5frfey7</link>
            <guid>https://velog.io/@100-100/React-ref-potal-i5frfey7</guid>
            <pubDate>Tue, 19 Mar 2024 06:57:22 GMT</pubDate>
            <description><![CDATA[<h1 id="react---ref--potal">React - ref &amp; potal</h1>
<h3 id="ref">Ref</h3>
<blockquote>
<p>Ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다.<br>일반적인 React의 데이터 플로우에서 props는 부모 컴포넌트가 자식과 상호작용할 수 있는 유일한 수단입니다.<br>자식을 수정하려면 새로운 props를 전달하여 자식을 다시 렌더링해야 합니다.<br>그러나, 일반적인 데이터 플로우에서 벗어나 직접적으로 자식을 수정해야 하는 경우도 가끔씩 있습니다.<br>수정할 자식은 React 컴포넌트의 인스턴스일 수도 있고, DOM 엘리먼트일 수도 있습니다.<br>React는 두 경우 모두를 위한 해결책을 제공합니다.<br><strong>-React 공식홈페이지-</strong></p>
</blockquote>
<p>바닐라 자바스크립트에선 특정 DOM을 선택하기 위해 querySelector, getElementById 등과 같은 함수를 사용한다.<br>React를 사용하면서도 가끔 DOM을 직접 선택해야하는 상황이 필요한데 그럴때 <strong>useRef</strong> 라는 Reack Hook을 사용한다.<br>예시를 들어보자 !</p>
<pre><code class="language-jsx">import { useState } from &quot;react&quot;;

export default function Player() {

  const [enteredName, setEnteredName] = useState(null);

  function handleClick(evt){
    setEnteredName(evt.target.value);
  }

  return (
    &lt;section id=&quot;player&quot;&gt;
      &lt;h2&gt;Welcome {enteredName ?? &#39;unknown entity&#39;}&lt;/h2&gt;
      &lt;p&gt;
        &lt;input type=&quot;text&quot; onChange={(evt) =&gt; handleClick(evt)}/&gt;
        &lt;button &gt;Set Name&lt;/button&gt;
      &lt;/p&gt;
    &lt;/section&gt;
  );
}</code></pre>
<p>input에서 입력 받은 값을 h2에 출력하려한다.<br>state만을 사용하면 매번 값을 입력할때마다 setEnteredName함수로 인해 렌더링이 일어나고 실시간으로 h2에 출력값이 변경된다.<br><img src="https://velog.velcdn.com/images/100-100/post/d87aebec-ae15-4873-9f78-6f9a37b95ac7/image.gif" alt=""></p>
<p>이런 방식이 아니라 Set Name 버튼을 클릭시 출력되게끔 하고싶다면 useRef 훅을 사용하면 좋다.</p>
<pre><code class="language-jsx">import { useState, useRef } from &quot;react&quot;;

export default function Player() {
  const playerName = useRef();

  const [enteredName, setEnteredName] = useState(null);

  function handleClick(){
    setEnteredName(playerName.current.value);
    // playerName.current.value = &#39;&#39;;
  }

  return (
    &lt;section id=&quot;player&quot;&gt;
      &lt;h2&gt;Welcome {enteredName ?? &#39;unknown entity&#39;}&lt;/h2&gt;
      &lt;p&gt;
        &lt;input ref={playerName} type=&quot;text&quot;/&gt;
        &lt;button onClick={handleClick}&gt;Set Name&lt;/button&gt;
      &lt;/p&gt;
    &lt;/section&gt;
  );
}</code></pre>
<p>useRef 훅을 import해서 참조 값을 생성한다.<br>생성된 참조 값을 변수나 상수에 담고 이를 ref 속성을 통해 JSX요소들과 연결할 수 있다.<br>current 속성이 연결된 JSX의 참조 값을 가지고있으며 위와 같이 input의 value 속성에 접근이 가능하다.<br>결과를 확인해보면 <strong>useRef로 관리하는 값은 변해도 랜더링되지 않음</strong>을  수 있다.<br><img src="https://velog.velcdn.com/images/100-100/post/6975fe86-5112-4a81-b02d-2854e7c7e0e1/image.gif" alt=""></p>
<h3 id="state-vs-ref">State vs Ref</h3>
<ul>
<li>state</li>
</ul>
<ol>
<li>상태가 업데이트되면 컴포넌트가 렌더링된다.</li>
<li>UI에 바로 반영되어야 하는 값들이 있을 때 사용한다.</li>
<li>시스템 내부에 보이지 않는 쪽에서만 다루는 값들이나 UI에 직접적인 영향을 끼치지 않는 값들에는 사용하지 않는다.</li>
</ol>
<ul>
<li>ref</li>
</ul>
<ol>
<li>참조 값이 바뀌었다는 이유로 컴포넌트가 렌더링되지 않는다.</li>
<li>DOM 요소에 직접적인 접근이 필요할 때 사용한다.</li>
<li>ref를 사용한 명령형 코드는 피하도록 조심해야한다.</li>
</ol>
<h3 id="forwarref">forwarRef</h3>
<p>커스텀 컴포넌트는 ref속성이 존재하지 않아서 컴포넌트간 ref를 전달 받을 수 없다.<br>상위 컴포넌트에서 하위 컴포넌트로 ref를 전달하고 싶을때에 forwardRef를 사용하면 가능하다.</p>
<pre><code class="language-jsx">// 상위 컴포넌트
import { useRef } from &quot;react&quot;;
import CustomInput from &quot;./CustomInput&quot;

const customRef = useRef();

function TopComponent() {
  return (
    &lt;&gt;
      &lt;CustomInput name=&quot;peter&quot; ref={customRef} /&gt;
    &lt;/&gt;
  );
}

// 하위 컴포넌트
import { forwardRef } from &quot;react&quot;;

const forwardCustomInput = forwardRef(function CustomInput({name}, ref) {
  return (
    &lt;div&gt;
      &lt;input value={name} ref={ref} /&gt;
    &lt;/div&gt;
  )
})

export default forwardCustomInput;</code></pre>
<p>React에서 forwardRef를 import하고 forwardRef 함수로 컴포넌트 함수를 감싸준다.<br>감싸진 컴포넌트 함수는 첫번째 인자로 props를 받고 두번째로 전달된 ref를 받아서 사용한다.</p>
<h3 id="potal">Potal</h3>
<blockquote>
<p>Portal은 부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법을 제공합니다.<br><strong>-React 공식홈페이지-</strong></p>
</blockquote>
<p>컴포넌트들의 상하 관계, 구조를 가지고 있는 DOM에서 자식 컴포넌트를 부모 컴포넌트 바깥에 있는 다른 컴포넌트에 전달할 수 있다는 뜻이다.<br>주로 <strong>index.html</strong> 의 root div 외에 다른 곳에서 Modal, Dialog 등을 띄우기 위해 많이 사용한다.</p>
<pre><code class="language-jsx">// index.html
&lt;body&gt;
  &lt;div id=&quot;modal&quot;&gt;&lt;/div&gt;
  &lt;div id=&quot;content&quot;&gt;
    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;script type=&quot;module&quot; src=&quot;/src/main.jsx&quot;&gt;&lt;/script&gt;
&lt;/body&gt;

// modal 컴포넌트
import { createPortal } from &quot;react-dom&quot;

function CustomModal() {

    return createPortal(
        &lt;dialog className=&quot;result-modal&quot;&gt;
            &lt;h2&gt;My name is Peter parker&lt;/h2&gt;
            &lt;form method=&quot;dialog&quot;&gt;
                &lt;button&gt;Close&lt;/button&gt;
            &lt;/form&gt;
        &lt;/dialog&gt;,
        document.getElementById(&#39;modal&#39;)
    );
}

export default CustomModal;</code></pre>
<p>React DOM 라이브러리에서 createPortal을 import하고 JSX코드를 감싸준다.<br>두번째 인자로는 JSX코드의 부모가 될 DOM node를 선택해준다.<br><img src="https://velog.velcdn.com/images/100-100/post/5cd88855-4496-45ef-8d59-0c71e7983e56/image.png" alt=""></p>
<p>선택한 node로 modal 컴포넌트가 이동된 것을 확인할 수있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tailwind CSS]]></title>
            <link>https://velog.io/@100-100/Tailwind-CSS</link>
            <guid>https://velog.io/@100-100/Tailwind-CSS</guid>
            <pubDate>Thu, 14 Mar 2024 08:48:46 GMT</pubDate>
            <description><![CDATA[<h2 id="tailwind-css">Tailwind CSS</h2>
<p>Tailwind CSS는 어떤 웹 프로젝트에서든 사용할 수 있는 CSS 프레임워크로 HTML 요소에 <strong>mb-6</strong> , <strong>flex</strong> 와 같이 미리 정의된 클래스를 추가하여 스타일링 할 수 있다.   </p>
<h3 id="설치">설치</h3>
<p>설치법은 공식 문서에 잘 나와있다.<br>본인은 vite를 사용하므로 <a href="https://tailwindcss.com/docs/guides/vite">관련 페이지</a> 에서 설치법을 찾아보았다.   </p>
<ol>
<li>Tailwind CSS를 터미널에서 설치한다.<pre><code class="language-yaml">npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p</code></pre>
</li>
<li>설치 후 생성된 tailwind.config.js 파일에서 경로를 구성한다.<pre><code class="language-javascript">/** @type {import(&#39;tailwindcss&#39;).Config} */
export default {
content: [
 &quot;./index.html&quot;,
 &quot;./src/**/*.{js,ts,jsx,tsx}&quot;,
],
theme: {
 extend: {},
},
plugins: [],
}</code></pre>
</li>
<li>메인 CSS 파일에 아래 코드를 추가하여 Tailwind CSS 스타일을 추가한다.<br><strong>@tailwind</strong> 디렉티브는 빌드시에 CSS 코드로 변환된다고 한다.<pre><code class="language-css">@tailwind base;
@tailwind components;
@tailwind utilities;</code></pre>
</li>
</ol>
<h3 id="추천하는-확장-프로그램">추천하는 확장 프로그램</h3>
<p>Tailwind CSS의 공식 문서에세 정의된 모든 클래스의 이름을 찾아볼 수 있지만 번거로움을 조금이라도 줄이기위한 <strong>Tailwind CSS IntelliSense</strong> 라는 확장 프로그램이 있다.<br>이는 Tailwind 팀에서 자체적으로 출시한 것으로 코드를 작성할때 <strong>클래스 이름을 제안</strong> 받고 해당 클래스가 <strong>어떠한 스타일링이 적용되는지</strong> 미리 확인해볼 수 있는 아주 좋은 프로그램이다.<br>설치하는 것을 적극 추천한다.<br><img src="https://velog.velcdn.com/images/100-100/post/0c685322-bf4d-41b0-a420-8864de7fd741/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/7b879ef5-c2c1-4ce0-96d4-c0fb6e6dd622/image.png" alt=""></p>
<h3 id="장단점">장단점</h3>
<ul>
<li>장점</li>
</ul>
<ol>
<li><p>CSS를 많이 알지 못하더라도 비교적 접근하기 쉽다.</p>
<blockquote>
<p>아래와같이 정의된 클래스들을 넣어주면 스타일이 적용된다.<br><img src="https://velog.velcdn.com/images/100-100/post/d1750f94-bc2d-4e18-91c2-6a1d18cd7a5d/image.png" alt=""></p>
</blockquote>
</li>
<li><p>바닐라 CSS도 사용 가능하다.   </p>
<blockquote>
<p>Tailwind에서 정의한 클래스만 사용하는 것이 아니라 본인이 직접 정한 스타일링 규칙도 CSS 파일에 추가하여 사용한다.<br><img src="https://velog.velcdn.com/images/100-100/post/14b18abf-f5b1-432f-ae82-8c03f1f6499a/image.png" alt=""></p>
</blockquote>
</li>
<li><p>커스텀(사용자 정의)가 가능하다.</p>
<blockquote>
<p>폰트를 설정한 예시<br><img src="https://velog.velcdn.com/images/100-100/post/7d2d1b32-223a-4ba3-8d68-e595b8b86464/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/d93f623c-4337-44ab-96e7-7c1bb7bbc89e/image.png" alt=""></p>
</blockquote>
</li>
<li><p>스타일링된 재사용이 가능한 컴포넌트를 만들 수 있다는 것이 리액트와 잘 어울린다.</p>
</li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>긴 클래스 이름 값을 가진 요소들이 생긴다.</li>
<li>JSX 코드에서 편집이 이루워지므로 스타일 코드와 JSX 코드 사이에 강한 분리가 없다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - vanilla CSS & styled-components]]></title>
            <link>https://velog.io/@100-100/React-vanilla-CSS-styled-components</link>
            <guid>https://velog.io/@100-100/React-vanilla-CSS-styled-components</guid>
            <pubDate>Thu, 14 Mar 2024 07:09:56 GMT</pubDate>
            <description><![CDATA[<h1 id="react---vanilla-css--styled-components">React - vanilla CSS &amp; styled-components</h1>
<h2 id="vanilla-css">Vanilla CSS</h2>
<hr>
<h3 id="장단점">장단점</h3>
<ul>
<li>장점   </li>
</ul>
<ol>
<li>말 그대로 바닐라 CSS이기 때문에 특별한 관례를 따르지 않아도 된다.</li>
<li>컴포넌트 파일에서 import해서 사용하니 스타일링을 추가하려는 사람으로 인해 방해를 받거나 간섭을 받지 않고 컴포넌트 작업을 할 수 있다.</li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>CSS를 알아야 한다.</li>
<li>CSS 코드와 규칙은 여러개의 파일로 나누어 특정 컴포넌트 파일로 import하더라도 해당 컴포넌트로 스코핑되지 않는다.<br>즉, 다른 컴포넌트 간에 스타일 충돌이 발생할 수 있다.</li>
</ol>
<h3 id="inline-스타일">Inline 스타일</h3>
<p>style 속성에 중괄호가 필요하고 카멜 표기법 or 작은 따옴표로 key를 지정한다.</p>
<blockquote>
<p>설정한 jsx 요소에만 영향을 미친다는 장점이 있지만 모든 요소를 개별적으로 스타일하므로 추가와 수정에 효율적이지 않다.   </p>
</blockquote>
<pre><code class="language-jsx">&lt;p style={{textAlign: &#39;center&#39;}}&gt;Inline styling&lt;/p&gt;
// 조건부 스타일링
&lt;input style={{backgroundColor: 1 === 1 ? &#39;red&#39; : &#39;black&#39;}} /&gt;</code></pre>
<h3 id="css-module">CSS module</h3>
<p>CSS 모듈을 사용하여 스타일 코드와 규칙을 컴포넌트에 스코핑되도록 할 수 있다.   </p>
<blockquote>
<p>많은 컴포넌트를 사용하는 큰 프로젝트라면 각각 자체의 CSS 파일을 갖게되는 단점도 있다.</p>
</blockquote>
<p>CSS 파일명에 .module 패턴을 추가한다.<br>이는 기본 빌드 프로세스에 대한 신호로 볼 수 있다.<br><img src="https://velog.velcdn.com/images/100-100/post/26504111-6060-42ed-a1c6-254e233c282b/image.png" alt=""></p>
<p>CSS 모듈을 사용한 컴포넌트에서 아래와 같이 import 한다음 사용하면된다.<br><img src="https://velog.velcdn.com/images/100-100/post/2f160f59-e049-46ed-82e1-7df94b095c3a/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/2ca3c7e9-7dea-4fe5-8e3a-80744d1c41a0/image.png" alt=""></p>
<p>랜더링된 DOM에 적용된 클래스와 헤더 섹션에 주입된 스타일 살펴보면 이상한 이름이 있는 것을 볼 수 있는데 이는 빌드 툴에 의해 자동으로 생성된 것이다.<br>이것이 CSS 모듈의 개념이며 이 클래스 이름은 이제 해당 컴포넌트에 대해 고유하게된다.<br><img src="https://velog.velcdn.com/images/100-100/post/52ff2673-103b-4ca0-a769-5482c8444f5f/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/a682cc77-e37c-4d57-93d7-7a957cd4f759/image.png" alt=""></p>
<h2 id="styled-components">styled-components</h2>
<hr>
<h3 id="개념">개념</h3>
<p>styeld-components 패키지는 바닐라 CSS를 기반으로하는 솔루션 중 하나로 CSS 규칙이나 스타일을 별도의 파일이나 인라인 스타일로 지정하지 않고 해당 패키지의 도움을 받아 생성된 특별한 컴포넌트내에서 정의하는 것이다.<br>터미널에서 npm install styled-components를 실행하여 설치 할 수있다.</p>
<h3 id="적용하기">적용하기</h3>
<p>styled-components로부터 styled를 import하고 자바스크립트 객체인 styled를 사용하여 다른 속성에 접근한다.<br>매핑되는 속성들은 해당 html 요소를 개발자가 설정한 스타일을 가지는 개별 컴포넌트로 만들어준다.<br>작성한 요소 속성 다음 백틱 안에 원하는 스타일을 설정하면 된다.<br><img src="https://velog.velcdn.com/images/100-100/post/6ff9578a-5439-4db0-a161-1ba1fd6ed6ca/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/395521e5-f6bc-4ae1-a1cc-bc1675acc9a3/image.png" alt=""></p>
<p>적용된 스타일을 살펴보면 styled-components는 고유한 CSS 클래스 이름은 생성하고 헤더 섹션에서 해당 클래스에대해 개발자가 작성한 CSS 규칙을 정의한다.<br>그런 다음 생성된 클래스를 요소에 추가한다.<br><img src="https://velog.velcdn.com/images/100-100/post/e6c28417-cef1-4f43-af20-08c0aefa9600/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/93d68ee3-1c17-4e45-b336-c982a28b3c70/image.png" alt=""></p>
<p>조건부 스타일링 또한 가능하며 styled-components 스타일링 코드에서만 사용하고 싶은 속성에는 달러 기호를 사용하는 것이 일반 규칙이다.<br>이렇게하면 내장 속성과 출동하지 않는다.<br><img src="https://velog.velcdn.com/images/100-100/post/d9d1dd1a-9d57-4ed3-acf0-ec4681ad961c/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/a273fcf5-5cbd-4f12-bcb9-42db6a509b21/image.png" alt=""></p>
<h3 id="가상-선택자-중첩-규칙--미디어-쿼리">가상 선택자, 중첩 규칙 &amp; 미디어 쿼리</h3>
<p>&amp; 기호를 사용하여 해당 요소내의 다른 요소들의 규칙이나 미디어 쿼리를 작성한다.<br>아래 사진처럼 &amp; 기호가 header 요소를 가르키는거라 생각하면 될 것같다.   </p>
<blockquote>
<p>&amp; 다음 공백이 있어야 해당 요소의 하위 요소가 목표가된다.
<img src="https://velog.velcdn.com/images/100-100/post/cde1aa85-8baa-4ff7-bc6b-955c1ca2d482/image.png" alt=""></p>
</blockquote>
<p>가상(pseudo) 선택자의 경우 아래와 같이 작성한다.   </p>
<blockquote>
<p>해당 요소 자체가 목표가 되어야 하는 경우 &amp; 기호다음 빈 공간 없이 작성한다.
<img src="https://velog.velcdn.com/images/100-100/post/3e420904-fd0b-4178-b234-a507e1eed214/image.png" alt=""></p>
</blockquote>
<h3 id="장단점-1">장단점</h3>
<ul>
<li>장점</li>
</ul>
<ol>
<li>꽤 간단하며 많은 추가 작업이 필요하지 않다.</li>
<li>스타일이 자동으로 범위가 지정되어 CSS 규칙이나 스타일 충돌이 발생하지 않는다.</li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>바닐라 CSS를 알아야한다.</li>
<li>스타일이 컴포넌트와 동일한 파일 혹은 옆에 정의 되어 있기에 강한 분리가 없다.</li>
<li>버튼이나 입력 컴포넌트와 같은 비교적 작은 래퍼(warpper) 컴포넌트가 많이 생기는 경향이 있다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 이미지/파일 저장소(public vs assets)]]></title>
            <link>https://velog.io/@100-100/React-%EC%9D%B4%EB%AF%B8%EC%A7%80%ED%8C%8C%EC%9D%BC-%EC%A0%80%EC%9E%A5%EC%86%8Cpublic-vs-assets</link>
            <guid>https://velog.io/@100-100/React-%EC%9D%B4%EB%AF%B8%EC%A7%80%ED%8C%8C%EC%9D%BC-%EC%A0%80%EC%9E%A5%EC%86%8Cpublic-vs-assets</guid>
            <pubDate>Tue, 05 Mar 2024 08:38:33 GMT</pubDate>
            <description><![CDATA[<h1 id="이미지-저장소---public-vs-assets">이미지 저장소 - public vs assets</h1>
<h3 id="public폴더">public/폴더</h3>
<p>이미지를 <strong>public/폴더</strong> 에 저장하면 index.html 혹은 index.css 파일에서 직접 참조할 수 있다.   </p>
<p><img src="https://velog.velcdn.com/images/100-100/post/756ca165-de6e-4a29-832e-052c0f614c87/image.png" alt=""><img src="https://velog.velcdn.com/images/100-100/post/0e2db79c-1bf0-43db-825e-51ceeb13b5f1/image.png" alt=""></p>
<p>이러한 이유는 <strong>public/</strong> 에 저장된 이미지(파일)이 프로젝트 개발 서버 및 빌드 프로세스에 의해 <strong>공개적으로 제공</strong> 되기 때문이다.<br>index.html과 마찬가지로, 이 파일들은 브라우저 내에서 직접 방문할 수 있다.<br>ex) localhost:5173/some-image.jpg   </p>
<h3 id="srcassets폴더">src/assets/폴더</h3>
<p>이미지나 파일를 <strong>src</strong> 폴더 또는 <strong>src/assets/(src폴더 어디든)</strong> 과 같은 하위 폴더에 저장하면 이는 공개적으로 제공되지 않는다.<br>localhost:5173/some-image.jpg과 같은 방식으로 웹사이트 방문자가 접근할 수 없다.<br>대신 이러한 파일은 코드 파일에서 사용할 수 있다.<br>코드 파일에가져온 이미지는 빌드 프로세스에 의해 인식되어 최적화되며, 웹사이트에 제공하기 직전에 <strong>public/</strong> 폴더에 <strong>삽입</strong> 된다.   </p>
<h3 id="어떤-폴더를-사용해야-할까">어떤 폴더를 사용해야 할까?</h3>
<p>빌드 프로세스에 의해 처리되지 않는 정적인 이미지나 파일은 <strong>public/</strong> 폴더를 사용한다.<br>예를 들면 index.html이나 파비콘과 같은 이미지가 좋은 후보다.<br>반면 <strong>컴포넌트 내</strong> 에서 사용되는 이미지는 일반적으로 <strong>src/</strong> 폴더에 저장되어야한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 컴포넌트, JSX, props, state 등]]></title>
            <link>https://velog.io/@100-100/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-JSX-props-state-%EB%93%B1-h9di62j9</link>
            <guid>https://velog.io/@100-100/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-JSX-props-state-%EB%93%B1-h9di62j9</guid>
            <pubDate>Mon, 04 Mar 2024 08:37:03 GMT</pubDate>
            <description><![CDATA[<h1 id="react-핵심---컴포넌트-jsx-속성-상태-등">React 핵심 - 컴포넌트, JSX, 속성, 상태 등</h1>
<h3 id="컴포넌트">컴포넌트</h3>
<p>컴포넌트는 잠재적으로 재사용이 가능한 구성 요소로 리액트 개발자가 생성할 수 있고 차후에 혼합하여 전반적인 UI를 구축할 수 있다.<br>결국 리액트 애플리케이션은 컴포넌트를 결합하여 만들어지는 것이다.<br>컴포넌트는 HTML과 경우에 따라 CSS코드, 관련된 자바스크립트 로직 등을 감싼다고 볼 수 있다.<br>이로 인해 복잡한 사용자 인터페이스를 관리하기 쉽도록 작게 분리하여 다른 위치에서도 사용할 수 있게 해준다.<br>컴포넌트 접근 방식의 가장 큰 장점이다.   </p>
<ul>
<li>재사용성</li>
<li>관심사의 분리 : 단일책임으로 복잡성↓, 가독성↑, 협업 &amp; 오류 수정에 용이</li>
<li>리액트에서 컴포넌트로 인식되기 위해 함수의 이름이 대문자로 시작해야하며 렌더링 가능한 값이 반환 되어야한다.</li>
</ul>
<h3 id="jsx">JSX</h3>
<p>JSX는 JavaScript Syntax Extension, 즉 JavaScript 문법 확장자를 의미한다.<br>이 확장자는 개발자가 자바스크립트 파일 내에 HTML 마크업 코드를 작성하여 HTML 요소를 설명하고 생성할 수 있게 해준다.<br>JSX는 브라우저에는 사용할 수 없지만 브라우저에 도달하기 전에 개발 서버에서 변환되어 보다 편리하게 UI를 생성할 수 있다.   </p>
<ul>
<li>반드시 부모 요소 하나가 감싸는 형태여야 한다.<br>→ Virtual DOM에서 컴포넌트 변화를 감지할 때 효율적인 비교를 위해 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 하는 규칙<pre><code class="language-javascript">// div 태그로 감싸기
function App() {
return(
  &lt;div&gt;
    &lt;h2&gt;Hello&lt;/h2&gt;
    &lt;h2&gt;World&lt;/h2&gt;
  &lt;/div&gt;
)
}
</code></pre>
</li>
</ul>
<p>// Fragment(&lt;&gt;&lt;/&gt;)로 감싸기
function App() {
  return(
    <Fragment>
      <h2>Hello</h2>
      <h2>World</h2>
    </Fragment>
  )
}</p>
<p>function App() {
  return(
    &lt;&gt;
      <h2>Hello</h2>
      <h2>World</h2>
    &lt;/&gt;
  )
}</p>
<pre><code>
- JSX 안에서도 중괄호로 자바스크립트 표현식을 사용할 수 있다.
```javascript
function App() {
  const name = &#39;Tom&#39;;
  return(
    &lt;&gt;
      &lt;h2&gt;Hello&lt;/h2&gt;
      &lt;h2&gt;{name}&lt;/h2&gt;
    &lt;/&gt;
  )
}</code></pre><h3 id="props">props</h3>
<p>props는 properties의 줄임말로 상위 컴포넌트가 하위 컴포넌트에 값을 전달할때 사용한다.<br>props는 객체이며 하위 컴포넌트에서 props.이름(key)으로 접근할 수 있다.</p>
<ul>
<li>하위 컴포넌트 입장에서 props는 읽기 전용이다.(수정 불가)</li>
<li>상위 컴포넌트에서 props를 변경하면 해당 props를 사용하고 있는 하위 컴포넌트가 리렌더링된다.</li>
</ul>
<pre><code class="language-javascript">// 상위 컴포넌트
import Header from &#39;./components/Header&#39;;
function App() {
  return(
    &lt;&gt;
      &lt;Header name=&quot;Tom&quot;/&gt;
    &lt;/&gt;
  );
}

// 하위 컴포넌트
function Header(props) {
  return(
    &lt;header&gt;
      &lt;h2&gt;{props.name}&lt;/h2&gt;
    &lt;/header&gt;
  )
}</code></pre>
<ul>
<li><p>구조분해할당도 가능하다.</p>
<pre><code class="language-javascript">// 상위 컴포넌트
import Header from &#39;./components/Header&#39;;
function App() {
const info = {
  name: &#39;Tom&#39;,
  age: 18
}

return(
  &lt;&gt;
    &lt;Header {...info}/&gt;
  &lt;/&gt;
);
}
</code></pre>
</li>
</ul>
<p>// 하위 컴포넌트
function Header({name, age}) {
  return(
    <header>
      <h2>{name}</h2>
      <h2>{age}</h2>
    </header>
  )
}</p>
<pre><code>
- children prop : 리액트에서 설정한 내장 prop으로 컴포넌트 사이 내용(택스트)을 의미한다.
```javascript
// 상위 컴포넌트
import Header from &#39;./components/Header&#39;;
function App() {
  return(
    &lt;&gt;
      &lt;Header&gt;My name is Tom&lt;/Header&gt;
    &lt;/&gt;
  );
}

// 하위 컴포넌트
function Header(props) {
  return(
    &lt;header&gt;
      &lt;h2&gt;{props.children}&lt;/h2&gt; // &lt;h2&gt;My name is Tom&lt;/h2&gt;
    &lt;/header&gt;
  )
}</code></pre><ul>
<li>props를 단일 객체로 그룹화 : ...을 사용하여 하나의 객체에 props로 분류되는 모든 것을 모아온다.<pre><code class="language-javascript">// 상위 컴포넌트
import Header from &#39;./components/Header&#39;;
function App() {
return(
  &lt;&gt;
    &lt;Header id=&quot;basicHeader&quot; className=&quot;headerClass&quot;&gt;
      My name is Tom
    &lt;/Header&gt;
  &lt;/&gt;
);
}
</code></pre>
</li>
</ul>
<p>// 하위 컴포넌트
function Header({children, ...props}) {
  return(
    &lt;header {...props}&gt; // <header id="basicHeader" className="headerClass">
      <h2>{children}</h2>
    </header>
  )
}</p>
<pre><code>
- 기본값 설정
```javascript
// 상위 컴포넌트
import Header from &#39;./components/Header&#39;;
function App() {
  return(
    &lt;&gt;
      &lt;Header id=&quot;basicHeader&quot; className=&quot;headerClass&quot;&gt;
        My name is Tom
      &lt;/Header&gt;
    &lt;/&gt;
  );
}

// 하위 컴포넌트
function Header({children, ...props, HeaderContainer = &#39;div&#39;}) {
  return(
    &lt;HeaderContainer&gt; // &lt;div&gt;로 작동
      &lt;header {...props}&gt; // &lt;header id=&quot;basicHeader&quot; className=&quot;headerClass&quot;&gt;
        &lt;h2&gt;{children}&lt;/h2&gt;
      &lt;/header&gt;
    &lt;/HeaderContainer&gt;
  )
}</code></pre><h3 id="usestate">useState</h3>
<p>리액트 Hook중 하나인 useState는 컴포넌트의 상태를 편하게 생성하고 관리할 수 있는 도구이다.<br>state 생성과 동시에 가져야할 초기값을 useState 함수에 인자로 넣어주면 state와 setState를 배열 형태로 리턴해준다.</p>
<pre><code class="language-javascript">const [state, setState] = useState(); // [현재 상태, 상태 업데이트 함수] </code></pre>
<p>컴포넌트의 현재 상태 값은 state 변수에 담겨져있고, setState함수를 이용해 변경할 수 있다.(state &amp; setState는 마음대로 지정 가능)<br>state가 변경되면 해당 컴포넌트는 다시 렌더링이 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript - 참조형과 기본형]]></title>
            <link>https://velog.io/@100-100/Primitive-Reference-type</link>
            <guid>https://velog.io/@100-100/Primitive-Reference-type</guid>
            <pubDate>Thu, 29 Feb 2024 06:35:15 GMT</pubDate>
            <description><![CDATA[<h1 id="참조형--기본형">참조형 &amp; 기본형</h1>
<h3 id="참조형과-기본형">참조형과 기본형</h3>
<p>String, Number, boolean은 모두 <strong>기본형(Primitive type)</strong> 이다.<br>자바스크립트의 기본형 값의 특징은 변경할 수  없다는 점이다.</p>
<pre><code class="language-javascript">let name = &#39;Tom&#39;;
name = &#39;Tom Holland&#39;;

name = name.concat(&#39; Holland&#39;);

// 재할당을 하면 기존의 값은 삭제되고 새로운 문자열이 생성된다.</code></pre>
<p>객체를 다룰 때는 다르다.<br>자바스크립트 객체는 <strong>참조형(Reference Type)</strong> 값이며 이는 변수에 값을 저장할 때 값 자체를 저장하는것이 아니라, 해당 값의 메모리 주소를 저장한다.<br>만약 push를 호출하면 자바스크립트에서 해당 주소를 찾아 그 주소의 값을 열어 배열을 확인한 후 메모리에 있는 해당 배열에 새 원소를 추가한다.<br>메모리의 배열은 수정되지만 주소는 변하지 않는것이다.</p>
<pre><code class="language-javascript">const name = [&#39;Tom&#39;, &#39;Holland&#39;];
name.push(&#39;Spider-Man&#39;);</code></pre>
<p>따라서 const에 저장된 객체는 재할당 할 수는 없지만 객체는 주소를 참조해 액세스된다는 점을 활용해 메모리 주소에 있는 값을 조작할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript - 화살표 함수]]></title>
            <link>https://velog.io/@100-100/%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@100-100/%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 28 Feb 2024 09:01:21 GMT</pubDate>
            <description><![CDATA[<h1 id="화살표-함수">화살표 함수</h1>
<h3 id="화살표-함수arrow-function">화살표 함수(Arrow function)</h3>
<p>화살표 함수는 표기법이 간단하기 때문에 익명 함수를 다른 함수의 인수로 넘길 때 주로 사용한다.<br>단지 표기법에서만 다른 것이 아니고, 몇가지 미묘한 차이점이 있다.   </p>
<ul>
<li><p>매개변수 목록 괄호 생략하기<br>화살표 함수가 <strong>정확히 하나</strong>의 매개변수만 사용하는 경우, 묶는 괄호를 생략할 수 있다.</p>
<pre><code class="language-javascript">(name) =&gt; {}
// 매개변수가 하나인 함수를
name =&gt; {}
// 위처럼 사용 가능하다. *매개변수가 없는 경우에는 괄호를 생략해서는 안된다.</code></pre>
</li>
<li><p>함수 본문 중괄호 생략하기<br>화살표 함수에 <strong>반환문 외에 다른 로직이 없는 경우</strong>, return 키워드와 중괄호를 생략할 수 있다.   </p>
</li>
<li><p>return 할 값이 객체라면 괄호는 필수이다.</p>
<pre><code class="language-javascript">number =&gt; {return number * 3;}
// ↓
nuber =&gt; number *3;</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript - import & export (모듈)]]></title>
            <link>https://velog.io/@100-100/import-export-%EB%AA%A8%EB%93%88</link>
            <guid>https://velog.io/@100-100/import-export-%EB%AA%A8%EB%93%88</guid>
            <pubDate>Wed, 28 Feb 2024 09:00:36 GMT</pubDate>
            <description><![CDATA[<h1 id="import--export">import &amp; export</h1>
<p>script 태그에 type=&quot;module&quot;로 설정하면 해당 파일은 모듈로서 동작하게된다.</p>
<pre><code class="language-html">&lt;script src=&quot;app.js&quot; type=&quot;module&quot;&gt;</code></pre>
<h3 id="모듈이란">모듈이란?</h3>
<p>JavaScript 코드를 담고 있는 파일이다.<br>다만 일반적인 JavaScript 파일과는 다른 차이점을 가지고 있다.</p>
<ul>
<li>import 혹은 export 구문을 사용할 수 있다.</li>
<li>별다른 처리를 해주지 않아도 엄격 모드로 동작한다.</li>
<li>모듈의 가장 바깥쪽에서 선언된 이름은 전역 스코프가 아니라 <strong>모듈 스코프</strong>에서 선언된다.</li>
</ul>
<h3 id="모듈-스코프">모듈 스코프</h3>
<p>모듈 내부의 가장 바깥 스코프에서 이름을 선언하더라도, 전역 스코프가 아니라 모듈 스코프에서 선언된다.<br>모듈 스코프에 선언된 이름은 export 해주지 않는다면 해당 모듈 내부에서만 접근할 수 있다.   </p>
<pre><code class="language-javascript">// util.js
let apiKey = &#39;Is api key&#39;;

// app.js
import {apiKey} from &#39;./util.js&#39;;

console.log(apiKey); // undefined</code></pre>
<h3 id="import--export-1">import &amp; export</h3>
<p>모듈 스코프에서 정의된 이름은 export 구문을 통해 다른 파일에서 사용할 수있다.<br>단순히 값을 저장하고 있는 변수뿐만 아니라, 함수나 클래스도 export를 통해 여러 모듈에서 재사용할 수 있다.   </p>
<pre><code class="language-javascript">// util.js
let apiKey = &#39;Is api key&#39;;
function add(x, y) {
    return x+y;
}

export {apiKey, add};</code></pre>
<pre><code class="language-javascript">// app.js
import {aptKey, add} from &#39;./util.js&#39;;

console.log(apiKey); // Is api key
console.log(add(1, 2)); // 3</code></pre>
<ul>
<li><p>선언과 동시에 export</p>
<pre><code class="language-javascript">export let name = &#39;Tom&#39;;
export let job = &#39;Spider-Man&#39;;</code></pre>
</li>
<li><p>default export<br>export default 구문을 통해 모듈을 대표하는 하나의 값을 지정하고 그 값을 불러와 사용할 수 있다.</p>
<pre><code class="language-javascript">// util.js
function add(x, y) {
return x + y;
}
</code></pre>
</li>
</ul>
<p>export let name = &#39;Tom&#39;;</p>
<p>export default add;</p>
<pre><code>
```javascript
// app.js
import add from &#39;./util.js&#39;;

console.log(add(1, 2)); // 3</code></pre><ul>
<li>다른 이름으로 import &amp; export 하기<br>default export와 일반적인 export를 동시에 가져올 수 있으며 이름뒤에 as를 붙혀서 다른 이름으로 사용할 수도 있다.<pre><code class="language-javascript">// app.js
import add, {name as myName} from &#39;./util.js&#39;;
</code></pre>
</li>
</ul>
<p>console.log(add(1, 2)); // 3
console.log(myName); // Tom
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React ?]]></title>
            <link>https://velog.io/@100-100/React</link>
            <guid>https://velog.io/@100-100/React</guid>
            <pubDate>Wed, 28 Feb 2024 04:32:12 GMT</pubDate>
            <description><![CDATA[<h1 id="react">React</h1>
<h3 id="react란-무엇이며-왜-사용할까">React란 무엇이며, 왜 사용할까?</h3>
<p><strong>What is React?</strong><br>바닐라 자바스크립트를 이용한 사용자 인터페이스 구축 라이브러리다.   </p>
<p><strong>Why?</strong><br>React를 사용하는 웹사이트를 살펴보자, 예를 들면 넷플릭스.<br>화면의 전환이 매우 부드럽고 반응이 즉각적이며 새 페이지가 로딩되는 듯한 효과가 전혀 없다.<br>React는 자바스크립트 라이브러리라서 브라우저의 자바스크립트를 이용해 웹페이지와 페이지에 표시되는 사용자 인터페이스를 재로딩 없이 업데이트한다.<br>그게 가능한 이유는 자바스크립트가 웹사이트 백그라운드에서 실행되며 로딩이 완료된 페이즈를 읽고 조작할 수 있기 때문에다.   </p>
<p><strong>React vs Vanilla JS</strong><br>React로 작업할땐 코드를 선언형으로 작성한다.<br>즉, 목표로 하는 UI 상태를 정의할 뿐 거쳐야 할 단계는 정의하지 않는다.<br>React가 과정을 알아서 파악해 필요한 단계를 수행한다.<br>반면 바닐라 자바스크립트는 선언형이 아닌 명령형으로 작성한다.<br>다시 말해 목표가 아니라 거쳐야할 단계를 정의한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Developer Tools]]></title>
            <link>https://velog.io/@100-100/React-Developer-Tools</link>
            <guid>https://velog.io/@100-100/React-Developer-Tools</guid>
            <pubDate>Tue, 27 Jun 2023 08:43:07 GMT</pubDate>
            <description><![CDATA[<p>React Developer Tools는 우리가 React를 사용하여 스크립트로 작성한 컴포넌트 구조를 볼 수 있고 변경하며 테스트를 할 수 있도록 도움을 주는 유용한 디버깅 도구이다.</p>
<p>크롬 확장 프로그램에서 추가하면 개발자 모드에서 관련 텝을 사용할 수 있다.
Components 텝에서 우리가 작성한 컴포넌트들만을 확인할 수 있으며</p>
<p><img src="https://velog.velcdn.com/images/100-100/post/4658e262-d3e9-4422-b0fa-60021977c931/image.png" alt=""></p>
<p>해당 컴포넌트의 props와 랜더링되는 부모 요소도 한눈에 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/100-100/post/053feb74-f168-49ec-b0af-b756678bd720/image.png" alt=""></p>
<p>또한 사용중인 hook을 수정하며 테스트가 가능하다.
Input 입력란에 잘못된 값이 들어왔을때 state가 false로 바뀌어 style이 변경되며 입력이 되지 않게 코딩되어 있는데 아래와 같이 devTools에서 state를 수정하여 간편하게 확인할 수 있다.
<img src="https://velog.velcdn.com/images/100-100/post/def428e5-bc50-48f0-81c1-e6eda09ecc13/image.png" alt="">
<img src="https://velog.velcdn.com/images/100-100/post/7dd71f28-9380-4ac9-93dc-35845e314d0a/image.png" alt=""></p>
<p>React를 사용하는 입장에서 좋은 Tool이라 생각된다.
앞으로 잘 애용해보자 :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Cannot read properties of null (reading 'edgesOut') 오류]]></title>
            <link>https://velog.io/@100-100/Cannot-read-properties-of-null-reading-edgesOut-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@100-100/Cannot-read-properties-of-null-reading-edgesOut-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Fri, 23 Jun 2023 04:11:10 GMT</pubDate>
            <description><![CDATA[<p>React 프로젝트에서 styled-component를 설치하는데 아래와 같은 오류를 접했다.
<img src="https://velog.velcdn.com/images/100-100/post/dfb407f9-f62b-4101-b049-7fcd59833fc4/image.png" alt="">
구글링을 해보니 v6에서 발생하는 오류인거 같다. (최신 버전은 아직 불안정한가보다...)</p>
<p>버전을 명시해 v5로 설치하니 문제 없이 잘 설치된다.
<img src="https://velog.velcdn.com/images/100-100/post/15bbf420-bdc4-43d7-b580-f05cf845dd32/image.png" alt="">
<img src="https://velog.velcdn.com/images/100-100/post/9fd00482-ebca-45f9-ad7b-c0876327c1eb/image.png" alt=""></p>
<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[난 지금 행복하다]]></title>
            <link>https://velog.io/@100-100/%EB%82%9C-%EC%A7%80%EA%B8%88-%ED%96%89%EB%B3%B5%ED%95%98%EB%8B%A4</link>
            <guid>https://velog.io/@100-100/%EB%82%9C-%EC%A7%80%EA%B8%88-%ED%96%89%EB%B3%B5%ED%95%98%EB%8B%A4</guid>
            <pubDate>Thu, 01 Jun 2023 08:22:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/100-100/post/8f8d69bd-b1d8-444b-9a77-ae417840f113/image.jpg" alt=""></p>
<p>더 행복하면 불안할 것 같고,
덜 행복하면 불행할 것 같다</p>
<p>그러니까 딱 이 정도만 행복하고 싶다.</p>
<p>난 지금 행복하다 : )</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript - Why?]]></title>
            <link>https://velog.io/@100-100/TypeScript-Why</link>
            <guid>https://velog.io/@100-100/TypeScript-Why</guid>
            <pubDate>Thu, 20 Apr 2023 06:42:16 GMT</pubDate>
            <description><![CDATA[<h1 id="typescript란">TypeScript란?</h1>
<hr>
<h3 id="왜-typescript를-사용할까">왜 TypeScript를 사용할까?</h3>
<p>우리가 사용하는 브라우저들(크롬, 엣지, 파이어폭스, 사파리 등)은 <strong>TypeScript</strong>를 이해하지 못한다.<br>그래서 <strong>Javscript</strong>로 변환해서 로드해야 진행할 수 있다.<br>이렇게만 들었을 땐 번거로울 것 같은데 무슨 장점이 있길래 <strong>TypeScript</strong>를 사용하는 걸까?</p>
<pre><code class="language-javascript">function add(num1, num2) {
    console.log(num1 + num2);
};

add(1,2); // 3
add(1,2,3); // 3
add(&#39;Petter&#39;, &#39; Parker&#39;); // &#39;Petter Parker&#39;</code></pre>
<p>위와 같은 코드가 있다고 가정했을 때 add 함수는 숫자를 더하기 위한 목적으로 개발자가 만들었지만 인수를 잘못 넣어도 <strong>Javascript</strong>는 어떠한 힌트도 주지 않는다.<br>또한 문자열을 넣어도 정상적으로 작동하여 실수가 분명하더라도 알지 못하거나 직접 찾아봐야한다.   </p>
<p>하나의 예시를 더 들어보자.</p>
<pre><code class="language-javascript">function showNumber(arr) {
    arr.forEach((i) =&gt; {
        console.log(i);
    });
};

showNumber([1,2,3]); 
// 1
// 2
// 3

showNumber(1,2,3);
// TypeError: arr.forEach is not a function</code></pre>
<p>showNumber 함수는 배열을 받아 반복문을 실행하는 함수인데 배열이 아닌 다른 인수를 받게되면 forEach 메서드가 없어 TypeError가 발생한다.   </p>
<p>이렇게 <strong>Javascript</strong>는 실행되는 시점, 즉 런타임에 타입이 결정되고 오류가 있다면 그 때 발견하게 되는 <strong>동적언어</strong>다.<br>반면 <strong>Java</strong>같은 <strong>정적언어</strong>는 컴파일 타임에 타입이 결정되고 오류가 발견된다.<br>그래서 코드 작성 시간은 오래 걸리겠지만 초기에 생각을 많이 해서 코드를 작성한다면 안정적으로 작업을 진행할 수 있는 장점이 있다.
<strong>TypeScript</strong>도 이러한 <strong>정적 타입의 언어</strong>이다.   </p>
<p>위에 있는 예제들을 <strong>TypeScript</strong>로 작성 해보자.<br>콜론과 함께 원하는 type을 적어주면 해당 인수는 지정한 type의 데이터만 들어와야하며 이와 맞지 않는 경우 오류들을 잡아준다.   </p>
<p><img src="https://velog.velcdn.com/images/100-100/post/6b6c7841-420c-4894-bcd1-b26757e4b47e/image.png" alt="">
<img src="https://velog.velcdn.com/images/100-100/post/18d79e96-b279-4ce8-9061-287684a5dd26/image.png" alt=""></p>
<hr>
<p><img src="https://velog.velcdn.com/images/100-100/post/0f7af257-ea07-4d62-8613-066b8d4b6274/image.png" alt="">
<img src="https://velog.velcdn.com/images/100-100/post/27931205-0100-426e-bee2-5d3fe401d2d9/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript - Generator]]></title>
            <link>https://velog.io/@100-100/javascript-Generator</link>
            <guid>https://velog.io/@100-100/javascript-Generator</guid>
            <pubDate>Mon, 17 Apr 2023 08:31:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/100-100/post/6ca5a529-03f3-4794-b5ff-fdf388149c1e/image.png" alt="">
Generator
=============</p>
<hr>
<h3 id="generator란">Generator란?</h3>
<p><strong>Generator</strong>는 함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능이다.<br>function 옆에 <em>을 넣어서 만들고 내부에 *</em>yield** 키워드를 사용하며 이를 이용해 함수의 실행을 멈춘다.<br><strong>Generator</strong> 함수를 실행하면 <strong>Generator</strong>객체가 반환되며 <strong>next</strong>, <strong>return</strong>, <strong>throw</strong> 메서드를 가지고있다.</p>
<pre><code class="language-javascript">function* fn() {
    yield 1;
    yield 2;
    yield 3;
    return &#39;end&#39;;
}

const gFn = fn();</code></pre>
<h3 id="next">next()</h3>
<p><strong>next</strong>를 호출하면 가장 가까운 <strong>yield</strong>문을 만날때까지 실행하고 데이터 객체를 반환한다.<br>반환되는 데이터 객체로는 value와 done을 갖으며 value는 <strong>yield</strong> 오른쪽에 있는 값이고 생략한다면 <strong>undefined</strong>이다.<br>done은 함수코드가 끝났는 지를 나타낸다.</p>
<pre><code class="language-javascript">function* fn() {
    console.log(&#39;Tom&#39;);
    yield &#39;Holland&#39;;

    console.log(&#39;Petter&#39;);
    console.log(&#39;Parker&#39;);
    yield &#39;Spider-Man&#39;;

    return &#39;end&#39;;
};

const gFn = fn();

gFn.next();
// &#39;Tom&#39;
// {value: &#39;Holland&#39;, done: false}

gFn.next();
// &#39;Petter&#39;
// &#39;Parker&#39;
// {value: &#39;Spider-Man&#39;, done: false}

gFn.next();
// {value: &#39;end&#39;, done: true}</code></pre>
<h3 id="return--throw">return() / throw()</h3>
<p><strong>return</strong>을 호출하면 그 즉시 done속성 값이 true가 된다.</p>
<pre><code class="language-javascript">function* fn() {
    console.log(&#39;Tom&#39;);
    yield &#39;Holland&#39;;

    console.log(&#39;Petter&#39;);
    console.log(&#39;Parker&#39;);
    yield &#39;Spider-Man&#39;;

    return &#39;end&#39;;
};

const gFn = fn();

gFn.return(&#39;finish&#39;);
// {value: &#39;finish&#39;, done: true}</code></pre>
<p><strong>throw</strong>도 마찬가지로 done을 true로 바꾸며 catch문을 실행한다.</p>
<pre><code class="language-javascript">function* fn() {
    try{
        console.log(&#39;Tom&#39;);
        yield &#39;Holland&#39;;

        console.log(&#39;Petter&#39;);
        console.log(&#39;Parker&#39;);
        yield &#39;Spider-Man&#39;;

        return &#39;end&#39;;
    }catch(e){
        console.log(e);
    }
};

const gFn = fn();

gFn.throw(new Error(&#39;Err...&#39;));
// 49037:1 Uncaught Error: Err... at &lt;anonymous&gt;:18:11</code></pre>
<h3 id="generator--iterable">Generator === iterable</h3>
<p><strong>iterable</strong>이란 반복이 가능하다는 뜻으로 몇가지 조건이 있다.   </p>
<ul>
<li><strong>Symbol.iterator</strong> 메소드가 구현되어있어야 하며 이 메소드를 호출한 결과를 <strong>iterator</strong>라고한다.   </li>
<li><strong>iterator</strong>는 value와 done 속성을 반환하는 <strong>next</strong>메서드를 가진다.<br>배열 또한 <strong>iterable</strong>하다고 볼 수 있다.<pre><code class="language-javascript">const arr = [1,2,3];
const it = arr[Symbol.iterator]();
</code></pre>
</li>
</ul>
<p>it.next();
// {value: 1, done: false}</p>
<p>it.next();
// {value: 2, done: false}</p>
<p>it.next();
// {value: 3, done: false}</p>
<p>it.next();
// {value: undefined, done: true}</p>
<pre><code>
**Generator**는 **iterable**객체이며 **iterable**은 **for of**를 통해 순회할 수 있다.
```javascript
function* fn(){
    yield 1;
    yield 2;
    yield 3;
};

const it = fn();

/*Generator에서 Symbol.iterator를 실행한 값이 자기 자신이다.*/
it === it[Symbol.iterator](); //true

for(let i of it) {
    console.log(i);
};
// 1, 2, 3

/*문자열도 가능할까?*/
const name = &#39;Tom&#39;;
const n = name[Symbol.iterator]();

for(let i of n) {
    console.log(i);
};
// &#39;T&#39;, &#39;o&#39;, &#39;m&#39;</code></pre><h3 id="next에-인수-전달">next()에 인수 전달</h3>
<pre><code class="language-javascript">function* add() {
    const num1 = yield &#39;첫 번째를 숫자 입력하세요&#39;;
    console.log(num1);

    const num2 = yield &#39;두 번째를 숫자 입력하세요&#39;;
    console.log(num2);

    return num1 + num2;
};

const fn = add();

fn.next();
// {value: &#39;첫 번째를 숫자 입력하세요&#39;, done: false}

fn.next(1);
// 1
// {value: &#39;두 번째를 숫자 입력하세요&#39;, done: false}

fn.next(2);
// 2
// {value: 3, done: true}</code></pre>
<h3 id="generator는-값을-미리-만들어-두지-않는다">Generator는 값을 미리 만들어 두지 않는다.</h3>
<p><strong>Generator</strong>는 필요할 때만 값을 연산해주기 때문에 아래와 같은 무한반복자를 만들어 사용해도 브라우저가 뻗지 않는다.</p>
<pre><code class="language-javascript">function* fn(){
    let num = 0;
    while(true){
        yield num++;
    }
};

const a = fn();

a.next(); // {value: 0, done: false}
a.next(); // {value: 1, done: false}
a.next(); // {value: 2, done: false}</code></pre>
<h3 id="yield">yield*</h3>
<p><strong>yield</strong> 옆에 *을 붙혀 반복가능한 다른 객체를 불러올 수 있다.</p>
<pre><code class="language-javascript">function* gen1() {
    yield &#39;T&#39;;
    yield &#39;o&#39;;
    yield &#39;m&#39;;
};

function* gen2() {
    yield &#39;My name is&#39;;
    yield* gen1();
};

/*구조분해할당을 사용하면 for of와 마찬가지로 done이 true가 될때까지 값을 펼쳐주는 역할을 한다.*/
console.log(...gen2());
// My name is T o m</code></pre>
<p><strong>Generator</strong>는 다른 작업을 하다가 다시 돌아와서 <strong>next</strong>를 해주면 진행이 멈췄던 부분부터 이어서 실행할 수 있다는 장점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript - async / await]]></title>
            <link>https://velog.io/@100-100/javascript-async-await</link>
            <guid>https://velog.io/@100-100/javascript-async-await</guid>
            <pubDate>Sun, 16 Apr 2023 14:24:31 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/100-100/post/c042dd16-839c-4958-999f-972ff4596ef4/image.png" alt="">
async / await
=============</p>
<hr>
<h3 id="async">async</h3>
<p><strong>async</strong>와 <strong>await</strong>을 사용하면 <strong>Promise</strong>에 then 메소드를 체인형식으로 호출하는 것보다 가독성이 좋아진다.<br>함수 앞에 <strong>async</strong> 키워드를 붙혀주면 항상 <strong>Promise</strong>를 반환한다. </p>
<pre><code class="language-javascript">async function getName() {
    return &#39;Tom&#39;;
};

console.log(getName());
// Promise {&lt;fulfilled&gt;: &#39;Tom&#39;}

async function getMyName() {
    return new Promise((res, rej) =&gt; {
        res(&#39;Petter&#39;);
    });
};

getMyName().then((name) =&gt; console.log(name)); // &#39;Petter&#39;</code></pre>
<h3 id="await">await</h3>
<p><strong>await</strong> 키워드는 <strong>async</strong> 함수 내부에서만 사용할 수 있다.<br><strong>await</strong> 옆에는 <strong>Promise</strong>가 오고 해당 <strong>Promise</strong>가 처리될 때 까지 기다린다.</p>
<pre><code class="language-javascript">function getName(name) {
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(name);
        }, 3000);
    });
};

async function showName() {
    const result = await getName(&#39;Petter&#39;);
    console.log(result);
};

showName();
// 3초뒤 &#39;Petter&#39;</code></pre>
<p><strong>Promise</strong>의 체인형식 then 메소드를 <strong>async</strong>, <strong>await</strong>으로 바꿔보자.<br>예외처리에는 try /catch 문을 사용해주면 된다.</p>
<pre><code class="language-javascript">const fn1 = () =&gt; {
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;1번 함수 실행&#39;);
        },3000);
    });
};

const fn2 = (msg) =&gt; {
    console.log(msg);
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;2번 함수 실행&#39;);
        },6000);
    });
};

const fn3 = (msg) =&gt; {
    console.log(msg);
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;3번 함수 실행&#39;);
        },2000);
    });
};

console.log(&#39;start&#39;);
console.time(&#39;time-check&#39;);
// fn1()
//     .then((result) =&gt; fn2(result))
//     .then((result) =&gt; fn3(result))
//     .then((result) =&gt; console.log(result))
//     .catch((err) =&gt; console.log(err))
//     .finally(() =&gt; {
//         console.log(&#39;end&#39;);
//         console.timeEnd(&#39;time-check&#39;);
//     });

async function start() {
    try {
        const result1 = await fn1();
        const result2 = await fn2(result1);
        const result3 = await fn3(result2);
        console.log(result3);
    } catch(err) {
        console.log(err);
    }

    console.log(&#39;end&#39;);
    console.timeEnd(&#39;time-check&#39;);
};

start();
// start, 1번 함수 실행, 2번 함수 실행, 3번 함수 실행, end
// time-check: 11024.880859375 ms</code></pre>
<p><strong>promise.all</strong> 또한 사용 가능하다.</p>
<pre><code class="language-javascript">console.log(&#39;start&#39;);
console.time(&#39;time-check&#39;);

async function startAll() {
    try {
        const result = await Promise.all([fn1(), fn2(), fn3()]);
        console.log(result);
    } catch(err) {
        console.log(err);
    }

    console.log(&#39;end&#39;);
    console.timeEnd(&#39;time-check&#39;);
};

startAll();
// start, [&#39;1번 함수 실행&#39;, &#39;2번 함수 실행&#39;, &#39;3번 함수 실행&#39;], end
// time-check: 6006.072998046875 ms</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript - Promise]]></title>
            <link>https://velog.io/@100-100/javascript-Promise</link>
            <guid>https://velog.io/@100-100/javascript-Promise</guid>
            <pubDate>Sat, 15 Apr 2023 09:36:50 GMT</pubDate>
            <description><![CDATA[<h1 id="promise">Promise</h1>
<hr>
<h3 id="promise란-">Promise란 ?</h3>
<p><strong>Promise</strong>는 자바스크립트 비동기 처리에 사용되는 객체다.<br>여기서 자바스크립트의 비동기 처리란 <strong>특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성</strong>을 의미한다.</p>
<pre><code class="language-javascript">const pr = new Promise((resolve, reject) =&gt; {
    // code
})</code></pre>
<p><strong>new Promise</strong>로 생성하며 인수로 함수를 전달 받는데 <strong>resolve</strong>는 성공, <strong>reject</strong>는 실패했을 때 실행되는 함수다.<br>이렇게 어떠한 작업이 완료되고 실행되는 함수를 <strong>callback</strong>함수라고 한다.</p>
<h3 id="promise의-3가지-상태states">Promise의 3가지 상태(states)</h3>
<p><strong>Promise</strong>의 상태란 처리 과정을 의미한다.<br><strong>Promise</strong>를 생성하고 종료될 때까지 3가지 상태를 갖는다.   </p>
<ul>
<li>Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태로 result는 undefined이다.</li>
<li>Fulfilled(이행) : 비동기 처리가 완료되어 resolve를 호출하면 Fulfilled가 된다. 이때 result는 resolve 함수로 전달된 값이다.</li>
<li>Rejected(실패) : 비동기 처리가 실패하면 즉 reject가 호출되면 Rejected가 되며 result는 reject로 전달된 error이다.</li>
</ul>
<h3 id="then--catch--finally">then / catch / finally</h3>
<p><strong>then</strong>을 이용하여 resolve와 reject를 처리할 수 있다.</p>
<pre><code class="language-javascript">const pr = new Promise((resolve, reject) =&gt; {

    let isTrue = true;

    setTimeout(() =&gt; {
        if(isTrue){

            resolve(&#39;success&#39;);
        }else{
            reject(&#39;fail&#39;);
        }
    }, 3000)
});

pr.then(
    function(result){ // 이행 되었을때
        console.log(result); // &#39;success&#39;
    },
    function(err){ // 거부 되었을때
        console.log(err); // &#39;fail&#39;
    }
);</code></pre>
<p><strong>then</strong> 이외에 사용할 수 있는것은 <strong>catch</strong>와 <strong>finally</strong>이다.<br><strong>catch</strong>는 reject인 경우에만 실행된다.<br><strong>catch</strong>문을 사용하면 가독성도 더 좋고 첫 번째 함수를 실행했을때 나오는 error를 잡아줄 수 도 있기때문에 사용하는 것이 더 좋다.   </p>
<pre><code class="language-javascript">pr.then(
    function(result){ 
        console.log(result);
    }
).catch(
    function(err){
        console.log(err);
    };
);</code></pre>
<p><strong>finally</strong>는 이행이든 거부든 처리가 완료되면 항상 실행된다.<br>로딩 화면 같은 것을 없앨 때 유용하다.</p>
<pre><code class="language-javascript">pr.then(
    function(result){ 
        console.log(result);
    }
).catch(
    function(err){
        console.log(err);
    }
).finally(
    function(){
        console.log(&#39;end&#39;);
    }
);
// &#39;success&#39;
// &#39;end&#39;</code></pre>
<h3 id="callback-hell에서-벗어나기">callback hell에서 벗어나기</h3>
<p>아래와 같이 1,2,3번 함수를 실행하는 로직을 <strong>Promise</strong>를 사용하지 않고 구현 한다면 로직이 추가될수록 뎁스가 깊어지면서 callback hell, 콜백 지옥에 빠지게 된다.</p>
<pre><code class="language-javascript">const fn1 = (callback) =&gt; {
    setTimeout(() =&gt; {
        console.log(&#39;1번 함수 실행&#39;);
        callback();
    }, 3000)
};

const fn2 = (callback) =&gt; {
    setTimeout(() =&gt; {
        console.log(&#39;2번 함수 실행&#39;);
        callback();
    }, 6000)
};

const fn3 = (callback) =&gt; {
    setTimeout(() =&gt; {
        console.log(&#39;3번 함수 실행&#39;);
        callback();
    }, 2000)
};



console.log(&#39;start&#39;);
console.time(&#39;time-check&#39;);

fn1(function(){
    fn2(function(){
        fn3(function(){
            console.log(&#39;end&#39;);
            console.timeEnd(&#39;time-check&#39;);
        })
    })
});
// start, 1번 함수 실행, 2번 함수 실행, 3번 함수 실행, end
// time-check: 11027.3369140625 ms</code></pre>
<p><strong>callback</strong>함수가 아닌 <strong>Promise</strong>를 사용하여 구현해보자.<br>아래와 같이 <strong>Promise</strong>들이 연결되는 것을 <strong>Promise chaining</strong>이라 한다.</p>
<pre><code class="language-javascript">const fn1 = () =&gt; {
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;1번 함수 실행&#39;);
        },3000);
    });
};

const fn2 = (msg) =&gt; {
    console.log(msg);
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;2번 함수 실행&#39;);
        },6000);
    });
};

const fn3 = (msg) =&gt; {
    console.log(msg);
    return new Promise((res, rej) =&gt; {
        setTimeout(() =&gt; {
            res(&#39;3번 함수 실행&#39;);
        },2000);
    });
};

console.log(&#39;start&#39;);
console.time(&#39;time-check&#39;);

fn1()
    .then((result) =&gt; fn2(result))
    .then((result) =&gt; fn3(result))
    .then((result) =&gt; console.log(result))
    .catch((err) =&gt; console.log(err))
    .finally(() =&gt; {
        console.log(&#39;end&#39;);
        console.timeEnd(&#39;time-check&#39;);
    });
// start, 1번 함수 실행, 2번 함수 실행, 3번 함수 실행, end
// time-check: 11042.4560546875 ms</code></pre>
<h3 id="promiseall">Promise.all</h3>
<p><strong>Promise.all</strong>은 여러개의 <strong>Promise</strong>들을 비동기적으로 실행하여 처리 할 수 있으며, 하나의 <strong>Promise</strong>라도 reject를 반환하거나 오류가 날 경우 모든 <strong>Promise</strong>들을 reject 처리한다.<br>하나의 정보라도 누락될 경우 화면을 보여줘서는 안될 때 사용하곤 한다.</p>
<pre><code class="language-javascript">console.time(&#39;time-check&#39;);
Promise.all([fn1(), fn2(), fn3()]).then((res, rej) =&gt; {
    console.log(res);
})
.catch((err) =&gt; console.log(err))
.finally(() =&gt; console.timeEnd(&#39;time-check&#39;));
// [&#39;1번 함수 실행&#39;, &#39;2번 함수 실행&#39;, &#39;3번 함수 실행&#39;]
// time-check: 6007.13916015625 ms</code></pre>
<h3 id="promiserace">Promise.race</h3>
<p><strong>Promise.race</strong>는 하나의 <strong>Promise</strong>라도 1등으로 완료되면 종료된다.<br>용량이 큰 이미지들을 로딩하는데 그중 하나라도 완료되면 그 이미지를 보여줄 때 사용하면된다.</p>
<pre><code class="language-javascript">console.time(&#39;time-check&#39;);
Promise.race([fn1(), fn2(), fn3()]).then((res, rej) =&gt; {
    console.log(res);
})
.catch((err) =&gt; console.log(err))
.finally(() =&gt; console.timeEnd(&#39;time-check&#39;));
// 3번 함수 실행
// time-check: 2009.635986328125 ms</code></pre>
]]></description>
        </item>
    </channel>
</rss>