<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>썸이의 개발 더함</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 26 Aug 2024 05:06:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>썸이의 개발 더함</title>
            <url>https://velog.velcdn.com/images/e-sum-e/profile/fe9d36ea-8b93-4c39-b53d-bebfe4c49c5b/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 썸이의 개발 더함. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/e-sum-e" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[use client]]></title>
            <link>https://velog.io/@e-sum-e/use-client</link>
            <guid>https://velog.io/@e-sum-e/use-client</guid>
            <pubDate>Mon, 26 Aug 2024 05:06:53 GMT</pubDate>
            <description><![CDATA[<h2 id="client-component">Client component</h2>
<p>지금까지 배운 hydrate 되는 client(= client에서 interactive하게 만들어질 components)는 코드 최상단에 <code>“use client”</code> 지시어를 가지고 있는 컴포넌트 뿐이다</p>
<pre><code>// &quot;use client&quot;;

import Link from &quot;next/link&quot;;
import { usePathname } from &quot;next/navigation&quot;;
import { useState } from &quot;react&quot;;

export default function Navigation() {
  const path = usePathname();
  const [count, setCount] = useState(0);
  const handlePlusClick = () =&gt; {
    setCount(count + 1);
  };

  return (
    &lt;nav&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;Link href={&quot;/&quot;}&gt;Home&lt;/Link&gt; {path === &quot;/&quot; ? &quot;🔥&quot; : &quot;&quot;}
        &lt;/li&gt;
        &lt;li&gt;
          &lt;Link href={&quot;/about-us&quot;}&gt;About us&lt;/Link&gt;{&quot; &quot;}
          {path === &quot;/about-us&quot; ? &quot;🔥&quot; : &quot;&quot;}
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;div&gt;
        &lt;h3&gt;{count}&lt;/h3&gt;
        &lt;button onClick={handlePlusClick}&gt;+1&lt;/button&gt;
      &lt;/div&gt;
    &lt;/nav&gt;
  );
}
</code></pre><ul>
<li><p>이렇게 “use client”를 지우면</p>
<p>  <img src="https://velog.velcdn.com/images/e-sum-e/post/5663f0ce-d3af-4f88-bd7c-91375fd72d38/image.png" alt=""></p>
</li>
</ul>
<pre><code>이런식으로 client component에서만 사용할 수 있는 동작을 server component에서 사용했으니 `“use client”`를 마크하라는 에러가 표기된다</code></pre><h2 id="server-component">Server component</h2>
<p><code>“use client”</code> 를 사용하지 않는 모든 컴포넌트는 서버 컴포넌트이다</p>
<h2 id="server-component와-client-component를-분리해서-뭐가-좋아지지">Server component와 Client component를 분리해서 뭐가 좋아지지?</h2>
<p>프레임워크에게 어떤 컴포넌트가 인터렉티브하고 어떤 컴포넌트가 그렇지 않은지 알려준다면 인터렉티브 하지 않은 컴포넌트는 한번만 렌더하고 이후로 렌더하지 않아도 된다</p>
<p>따라서 사용자가 서버 컴포넌트는 Javascript 코드가 필요하지 않아서 Javascript 코드를 다운받지 않아도 되는데 이 말은 즉 사용자가 받아야 할 Javascript 코드의 양이 줄어드는 것이므로 페이지 로딩 속도가 빨라진다</p>
<h2 id="정리">정리</h2>
<p>사용자는 <code>&quot;use client&quot;</code> 를 가진 컴포넌트의 Javascript 코드만 다운받게 된다</p>
<p>client component도 서버에서 먼저 render되고 hydrate 되는 것이다. 서버에서 render를 안하는 게 아니라는 점을 헷갈리지 말자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Hydration]]></title>
            <link>https://velog.io/@e-sum-e/Hydration</link>
            <guid>https://velog.io/@e-sum-e/Hydration</guid>
            <pubDate>Sat, 24 Aug 2024 03:24:30 GMT</pubDate>
            <description><![CDATA[<p>이 개념을 이해하기 위해 몇가지 테스트를 하겠다</p>
<p>브라우저의 Sources에서 disable Javascript 실행 후 anchor를 클릭하여 페이지를 이동해보자
<img src="https://velog.velcdn.com/images/e-sum-e/post/65f4fb0e-bbd1-4f64-bdee-5b2183517319/image.gif" alt=""></p>
<ul>
<li>링크 클릭에 따라 화면이 새로고침된다</li>
<li>자바스크립트를 사용한 건 아니고 그저 a 태그의 link를 따라가는 것이다</li>
</ul>
<p>그럼 다시 enable Javascript 후 이동해보자
<img src="https://velog.velcdn.com/images/e-sum-e/post/12a8e749-7ce7-470f-b282-ca3960a27d25/image.gif" alt=""></p>
<ul>
<li>새로고침 되지 않고 좀 더 빠르다</li>
</ul>
<p>→ <strong>이것이 React Hydrated 된 것이다</strong> <del>(오</del> 모르겠는데<del>)</del>
<br />
처음에는 단순히 a태그였다가 React component로 변환된것이다</p>
<p>그래서 클릭이 발생되면 React가 끼어들어 페이지 전체를 로드하지 않고 빠르게 navigate 할 수 있게 된다. 이는  더 이상 평범한 a 태그가 아니라 Link component로 새로 태어난 것이라고 생각하면 된다</p>
<br />

<h3 id="흐름을-이해해보자">흐름을 이해해보자</h3>
<p>어떤 페이지에 도달하면 UI를 가지고 있는 dummy HTML을 받고 → 프레임워크는 바로 load를 시작한다 → React load, components load.. 그리고 모든것이 initialize 됨 → 이러고나면 내 앱은 React App이 됨 → 이러고 나서야 비로소 interactive 해지고 navigation이 빨라지고… 그렇게 되는 것이다</p>
<p>물론 소스코드에 a 태그가 남아있기는 하지만 이 태그는 단순한 a 태그가 아니라 <strong>javascript에 의해 제어되는 a 태그</strong>인 것이다</p>
<p>만약에 어떤 이유로 javascript 로드하는데 아아아주 오랜 시간이 걸려서 react component가 아직 로드되지 않았다면 hard navigation(지금의 경우는 페이지를 새로고침하면서 이동하는 것)하게 된다</p>
<h3 id="실험해보자"><strong>실험해보자</strong></h3>
<p>useState를 사용하는 코드를 추가하고 브라우저에서 disable Javascript를 실행했다</p>
<pre><code class="language-jsx">&quot;use client&quot;;

import Link from &quot;next/link&quot;;
import { usePathname } from &quot;next/navigation&quot;;
import { useState } from &quot;react&quot;;

export default function Navigation() {
  const path = usePathname();
  const [count, setCount] = useState(0); // 여기 
  const handlePlusClick = () =&gt; {
    setCount(count + 1);
  };

  return (
    &lt;nav&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;Link href={&quot;/&quot;}&gt;Home&lt;/Link&gt; {path === &quot;/&quot; ? &quot;🔥&quot; : &quot;&quot;}
        &lt;/li&gt;
        &lt;li&gt;
          &lt;Link href={&quot;/about-us&quot;}&gt;About us&lt;/Link&gt;{&quot; &quot;}
          {path === &quot;/about-us&quot; ? &quot;🔥&quot; : &quot;&quot;}
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;div&gt;
        &lt;h3&gt;{count}&lt;/h3&gt;
        &lt;button onClick={handlePlusClick}&gt;+1&lt;/button&gt;
      &lt;/div&gt;
    &lt;/nav&gt;
  );
}
</code></pre>
<p>아무리 버튼을 눌러도 count에 변화가 없다<del>(방황하는 마우스)</del>
<img src="https://velog.velcdn.com/images/e-sum-e/post/ae967f51-1dc1-4df6-bc53-fefcbbb9153c/image.gif" alt=""></p>
<ul>
<li>버튼의 eventlistener가 연결되지 않았기 때문이다</li>
<li>initial state는 불러와진걸 볼 수 있는데(0), 이는 최초의 렌더 이후 인터렉션이 안되는 것이기 때문에 초깃값은 적용된것이다<br />

</li>
</ul>
<p>다시 enable Javscript를 실행하면 setState가 동작해서 값이 변화되는 걸 볼 수 있다<del>(편안한 마우스)</del>
<img src="https://velog.velcdn.com/images/e-sum-e/post/6ea5284c-34be-422d-aad7-7fb75fa90e01/image.gif" alt=""></p>
<hr>
<h2 id="그래서-hydration이란">그래서 Hydration이란?</h2>
<p><strong>HTML을 React application으로 초기화하는 작업이다</strong>
⇒ 예제를 사용하자면, 0이 쓰인것 외에 아무것도 없는 버튼을 받고, React를 initialize하여 onClick을 부착하여 기능을 수행하게 하는 것이다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR vs SSR]]></title>
            <link>https://velog.io/@e-sum-e/CSR-vs-SSR</link>
            <guid>https://velog.io/@e-sum-e/CSR-vs-SSR</guid>
            <pubDate>Sat, 24 Aug 2024 02:34:48 GMT</pubDate>
            <description><![CDATA[<p>📖 Redering : component를 가져와서 브라우저가 이해할 수 있는 HTML로 변환하는 작업</p>
<h2 id="react가-application을-렌더하는-방법csr">React가 application을 렌더하는 방법(CSR)</h2>
<p>CRA로 React만을 이용해서 application을 생성하면 client side apllication이 된다 → client가 사용자 브라우저에서 모든 UI를 구축함한다</p>
<ul>
<li>단점<ul>
<li>소스코드를 보면 실제 소스코드는 비어있다(UI가 없음)
  <img src="https://velog.velcdn.com/images/e-sum-e/post/79a2bb1c-3cc1-4659-805f-b26d92a2f3a1/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code>    - 인스펙트에서는 볼 수 있다
        이는 Javascript에 의해서 UI가 추가되었기 때문이다
    - 화면을 새로고침 하다보면 화면에 아무것도 안그려져있는 때가 있는데 이 때가 Javascript가 UI를 그리고 있는 시점이다
    - Javascript가 disabled 되어 있는 상황이거나, 엘베에서 데이터가 안터지는 상황등이라면 내가 생각한것보다 더 오랫동안 빈 화면을 유저가 봐야한다
- SEO 검색 엔진 최적화 문제
    - google등에서 내 페이지가 검색되길 바란다면 google에서 빈 페이지를 보여주지 않는 것이 좋다
        → google은 페이지의 HTML을 보고 검색해주기 때문(가끔 Javascript를 실행하기도 하지만.. 안전하게 HTML을 그려주는게 좋음)</code></pre><p>*<em>👉🏻 client는 Javascript를 로드하고 → 그 후에 Javascript가 UI를 빌드한다
*</em></p>
<hr>
<h2 id="nextjs가-application을-렌더하는-방법ssr">Next.js가 application을 렌더하는 방법(SSR)</h2>
<p>자동적으로 server side render를 한다</p>
<ul>
<li>server, 즉 BE에서 application을 render</li>
<li>Next.js는 서버에서 <strong>나의 모든 컴포넌트(server component건 client component(”use client”)건 상관 없음)</strong> 를 렌더 후 그 HTML을 가지고 브라우저의 request에 대한 response로 준다 → 그래서 소스코드가 안비어 있음</li>
<li>use client를 선언한 client component에서 console.log(path)를 실행시키면<pre><code>      ![](https://velog.velcdn.com/images/e-sum-e/post/17a659d0-7042-4f14-a909-949211bee86e/image.png)</code></pre>  이렇게 브라우저에도 찍히고
  <img src="https://velog.velcdn.com/images/e-sum-e/post/d2ef1d3f-608b-4b1f-9bff-f638d466bf1e/image.png" alt="">
  이렇게 backend server쪽 콘솔에도 찍힌다..!
  <img src="https://velog.velcdn.com/images/e-sum-e/post/b0335457-41f6-4c7f-bedc-c5291aa85a05/image.png" alt=""></li>
<li>그리고 소스코드에서도 페이지의 내용들이 들어있음을 확인할 수 있다 → 화면에 그려질 HTML을 가지고 있기 때문
<img src="https://velog.velcdn.com/images/e-sum-e/post/405fed1f-1015-4438-81e3-79516b80cd7b/image.png" alt=""></li>
</ul>
<h3 id="결론">결론</h3>
<p>모든 컴포넌트와 페이지들은 백엔드에서 먼저 렌더된다</p>
<p>그리고 이것들이 HTML로 변환하고</p>
<p>이 HTML을 브라우저로 보내준다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[typescript에서 any 타입을 쓸 수 없도록 eslint가 잡아내는 경우]]></title>
            <link>https://velog.io/@e-sum-e/typescript%EC%97%90%EC%84%9C-any-%ED%83%80%EC%9E%85%EC%9D%84-%EC%93%B8-%EC%88%98-%EC%97%86%EB%8F%84%EB%A1%9D-eslint%EA%B0%80-%EC%9E%A1%EC%95%84%EB%82%B4%EB%8A%94-%EA%B2%BD%EC%9A%B0</link>
            <guid>https://velog.io/@e-sum-e/typescript%EC%97%90%EC%84%9C-any-%ED%83%80%EC%9E%85%EC%9D%84-%EC%93%B8-%EC%88%98-%EC%97%86%EB%8F%84%EB%A1%9D-eslint%EA%B0%80-%EC%9E%A1%EC%95%84%EB%82%B4%EB%8A%94-%EA%B2%BD%EC%9A%B0</guid>
            <pubDate>Thu, 20 Jun 2024 02:55:09 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-상황">문제 상황</h3>
<p>라이브러리 사용 중에 우선 구현을 먼저 해보려고 타입을 any로 지정했더니 eslint 에러가 발생했다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/ca043676-9004-40f8-a518-14c87b5d49a5/image.png" alt="">
<em>Unexpected any. Specify a different type</em></p>
<h3 id="해결-방법">해결 방법</h3>
<p>eslint 설정 파일에서 규칙을 수정해주면 된다.
나는 <code>.eslintrc.cjs</code> 를 수정해줬다.</p>
<pre><code class="language-json">module.exports = {
    // other configs..
  rules: {
    // other rules..
    &quot;@typescript-eslint/no-explicit-any&quot;: &quot;off&quot;,
  },
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/67e74457-843a-41dd-8130-36f3f6df6dde/image.png" alt="">
이제 any 타입에 대한 에러가 발생하지 않는다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] Object.is]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-Object.is</link>
            <guid>https://velog.io/@e-sum-e/Javascript-Object.is</guid>
            <pubDate>Thu, 13 Jun 2024 14:27:01 GMT</pubDate>
            <description><![CDATA[<p>이전에 <a href="https://velog.io/@e-sum-e/Jest-toBe-vs-toEqual">Jest로 기대 결과값을 비교</a>하면서 잠시 찍힌 메시지가 마음에 걸렸다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/84eadd3e-a84d-4576-a5e3-d7312398096b/image.png" alt="">
<strong><em>Object.is equality?</em></strong></p>
<hr>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is">MDN</a></p>
<p>Javascript에서 값을 비교하는 방법은 크게 세가지가 있다.</p>
<ul>
<li>==</li>
<li>===</li>
<li>Object.is(value1, value2)</li>
</ul>
<br />

<p>각각의 차이점은,</p>
<h3 id="">==</h3>
<p>느슨한 동등
비교 대상의 타입이 다르다면 같은 타입으로 변환하여 비교한다
NaN,  -0/+0에 대한 특수 처리를 한다</p>
<pre><code class="language-javascript">1 == &#39;1&#39;; // true

const obj1 = { a: 1 };
const obj2 = { a: 1 };
obj1 == obj2 // false

NaN == NaN // false

-0 == +0 // true</code></pre>
<h3 id="-1">===</h3>
<p>엄격한 동등
비교 대상의 타입이 다르다면 다른 값으로 인식한다
==와 마찬가지로 NaN, -0/+0에 대한 특수 처리를 한다</p>
<pre><code class="language-javascript">1 == &#39;1&#39;; // false

const obj1 = { a: 1 };
const obj2 = { a: 1 };
obj1 == obj2 // false

NaN == NaN // false

-0 == +0 // true</code></pre>
<p>사실 위 두가지는 알고 있던 것이고..
Object.is는 뭐가 다른걸까?</p>
<h3 id="objectis">Object.is</h3>
<p>==, === 둘 중 무엇과도 같지 않은 동작을 한다
비교 대상의 타입이 다르다면 다른 값으로 인식한다(===과 동일)
하지만 NaN, -0/+0에 대한 처리가 다르다</p>
<pre><code class="language-javascript">Object.is(1, &#39;1&#39;); // false

const obj1 = { a: 1 };
const obj2 = { a: 1 };
Object.is(obj1, obj2); // false

Object.is(NaN, NaN) // ⭐️ true

Object.is(-0, +0) // ⭐️ false</code></pre>
<hr>
<h3 id="결론">결론</h3>
<p>Object.is가 동등 등호를 대체하여 사용할 수는 없다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Jest] toBe vs toEqual vs toStrictEqual]]></title>
            <link>https://velog.io/@e-sum-e/Jest-toBe-vs-toEqual</link>
            <guid>https://velog.io/@e-sum-e/Jest-toBe-vs-toEqual</guid>
            <pubDate>Wed, 12 Jun 2024 14:38:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>코테에서 주어진 조건의 예외 처리를 위해 Jest로 테스트코드 작성중인데, 기대 결과를 <code>toBe()</code> 로 넣고 테스트를 실행하고 있다.</p>
</blockquote>
<h3 id="문제-상황">문제 상황</h3>
<p><strong>|</strong> <a href="https://school.programmers.co.kr/learn/courses/30/lessons/181927">프로그래머스 - 마지막 두 원소</a></p>
<h4 id="풀이">풀이</h4>
<pre><code class="language-javascript">function solution(num_list) {
  /**
   * 2 ≤ num_list의 길이 ≤ 10
   * 1 ≤ num_list의 원소 ≤ 9
   */

  assert(2 &lt;= num_list.length &amp;&amp; num_list.length &lt;= 10, &quot;Invaild array size&quot;);
  for (let i = 0; i &lt; num_list.length; i++) {
    assert(1 &lt;= num_list[i] &amp;&amp; num_list[i] &lt;= 9);
  }

  // length -1 &gt; length-2 이면
  // (length -1) - (length-2) 추가
  const lastIndex = num_list.length - 1;
  if (num_list[lastIndex] &gt; num_list[lastIndex - 1]) {
    num_list.push(num_list[lastIndex] - num_list[lastIndex - 1]);
  } else {
    // 아니면 (length -1)*2 추가
    num_list.push(num_list[lastIndex] * 2);
  }

  return num_list;
}</code></pre>
<h4 id="테스트-코드">테스트 코드</h4>
<pre><code class="language-node">
test(&quot;[5, 2, 1, 7, 5]&quot;, () =&gt; {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toBe([5, 2, 1, 7, 5, 10]);
});</code></pre>
<h4 id="테스트-결과">테스트 결과</h4>
<p>테스트를 실행해보니 아래와 같이 테스트가 제대로 돌지 않았다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/dde09e8c-aa59-4bbf-a2f3-57da01eb9c7e/image.png" alt=""></p>
<p>문제를 잘못 풀었나 싶어서 console에 num_list를 찍어보기도 했다.</p>
<pre><code class="language-javascript">
function solution(num_list) {
  /**
   * 2 ≤ num_list의 길이 ≤ 10
   * 1 ≤ num_list의 원소 ≤ 9
   */

  assert(2 &lt;= num_list.length &amp;&amp; num_list.length &lt;= 10, &quot;Invaild array size&quot;);
  for (let i = 0; i &lt; num_list.length; i++) {
    assert(1 &lt;= num_list[i] &amp;&amp; num_list[i] &lt;= 9);
  }

  // length -1 &gt; length-2 이면
  // (length -1) - (length-2) 추가
  const lastIndex = num_list.length - 1;
  if (num_list[lastIndex] &gt; num_list[lastIndex - 1]) {
    num_list.push(num_list[lastIndex] - num_list[lastIndex - 1]);
  } else {
    // 아니면 (length -1)*2 추가
    num_list.push(num_list[lastIndex] * 2);
  }

  console.log(num_list); // &lt;- 여기 추가
  return num_list;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/088552bd-9acf-497d-be5a-cb86e2128d89/image.png" alt=""></p>
<p>console에 찍어봤을 땐 값이 제대로 들어간 거 같은데 뭐가 문제일까 싶어 toBe의 주석과 Received된 결과를 살펴보았다. → <em>serializes to the same string</em></p>
<h3 id="해결-방법">해결 방법</h3>
<p>우선 받은 결과에 찍힌 문구가 무슨 의미인지 구글링해보았다.
<strong>|</strong> <a href="https://velog.io/@gygy/Testerrorserializes-to-the-same-string">참고 블로그</a>
<strong>|</strong> <a href="https://stackoverflow.com/questions/64652777/jest-received-serializes-to-the-same-string">Stack overflow</a></p>
<ul>
<li>참고한 블로그에 작성을 잘 해주셔서 하나씩 살펴보니 이해가 됐다.</li>
</ul>
<h4 id="toequal의-존재를-깨달음">toEqual의 존재를 깨달음</h4>
<p>지금까지 사용한 <code>toBe()</code> 는 객체가 아닌 그 객체의 참조값(메모리 주소)을 비교하지만, <code>toEqual()</code> 은 객체 내부의 값을 비교한다.
그래서 테스트 코드를 수정하고 다시 테스트를 돌려봤다.</p>
<pre><code class="language-javscript">test(&quot;[5, 2, 1, 7, 5]&quot;, () =&gt; {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toEqual([5, 2, 1, 7, 5, 10]); // &lt;- toBe -&gt; toEqual
});</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/4049be34-61c1-4022-a7a2-9b0757404946/image.png" alt="">
야호 성공이다!</p>
<h4 id="그런데-더-쉬운-방법이-있었다">그런데 더 쉬운 방법이 있었다</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/0ef659bb-5fc5-40db-974e-f09d69f12af8/image.png" alt="">
포스트를 작성하다 보니 친절하게 안내되어 있었다.</p>
<ul>
<li><em><code>toStrictEqual</code> 로 바꿔보세요.</em></li>
</ul>
<p>네.</p>
<pre><code class="language-javascript">test(&quot;[5, 2, 1, 7, 5]&quot;, () =&gt; {
  const num_list = [5, 2, 1, 7, 5];

  expect(solution(num_list)).toStrictEqual([5, 2, 1, 7, 5, 10]); // toEqual -&gt; toStrictEqual
});</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/82b9550f-c8e8-4405-9956-06d7dc3ca79b/image.png" alt="">
야호!</p>
<p>그런데 이러면 toEqual과 toStrictEqual은 무슨 차이가 있는 거지?</p>
<h3 id="tostrictequal">toStrictEqual</h3>
<p><strong>|</strong> <a href="https://jestjs.io/docs/expect#tostrictequalvalue">공식 문서</a>
toEqual보다 엄격한 equal
undefined를 고려한다.</p>
<h4 id="먼저-toequal을-테스트-해보자">먼저 toEqual을 테스트 해보자</h4>
<pre><code class="language-javascript">// toEqual
test(&quot;toEqual의 undefined 구분 여부&quot;, () =&gt; {
  const obj = { a: undefined, b: 1 };

  function test(testObj) {
    return testObj;
  }

  expect(test(obj)).toEqual({ b: 1 });
});

// toStrictEqual
test(&quot;toStrictEqual의 undefined 구분 여부&quot;, () =&gt; {
  const obj = { a: undefined, b: 1 };

  function test(testObj) {
    return testObj;
  }

  expect(test(obj)).toStrictEqual({ b: 1 });
});
</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/9e3765c7-4137-4a67-8f65-dfafad8a112d/image.png" alt="">
toEqual은 테스트가 통과됐지만(undefined가 할당된 a는 없는 값으로 친다), toStrictEqual은 undefined라는 값으로 할당된 값이 있는지를 확인하기 때문에 테스트에 걸렸다.</p>
<h3 id="결론">결론</h3>
<p>객체 타입의 값을 비교할 때에는 <code>toStrictEqual</code> 을 사용하는 게 내가 의도한 값으로 정확히 비교된다.</p>
<hr>
<h4 id="조금의-생각">조금의 생각</h4>
<ul>
<li>정확히 내부가 어떻게 도는지는 모르겠지만.. const로 변수 선언 시 원시 타입은 수정할 수 없지만 객체 타입은 메모리 주소가 할당되기 때문에 이후 수정할 수 있는 메커니즘과 관련있을 거 같다는 생각이 든다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] innerHTML, innerText, textContent]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-innerHTML-innerText-textContent</link>
            <guid>https://velog.io/@e-sum-e/Javascript-innerHTML-innerText-textContent</guid>
            <pubDate>Mon, 10 Jun 2024 10:34:31 GMT</pubDate>
            <description><![CDATA[<p>javascript로 DOM을 조작하다보면 <code>innerHTML</code>, <code>innerText</code>, <code>textContent</code> 를 사용하게 되는데 비슷한 동작을 하지만 각각 어떤 차이가 있는 것인지 알아보도록 하자.</p>
<pre><code class="language-html">// index.html

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  &lt;title&gt;HTML 예제 연습장&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;
      &lt;div class=&quot;innerHTML&quot;&gt;innerHTML&lt;/div&gt;
      &lt;div class=&quot;innerText&quot; style=&quot;display: none&quot;&gt;innerText&lt;/div&gt;
      &lt;div class=&quot;textContent&quot; style=&quot;display: none&quot;&gt;textContent&lt;/div&gt;
      &lt;/div&gt;
      &lt;/body&gt;
  &lt;script script src=&quot;./app.js&quot; &gt;&lt;/script&gt;
&lt;/html&gt;</code></pre>
<h2 id="각각-사용해보기">각각 사용해보기</h2>
<h3 id="innerhtml">innerHTML</h3>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/API/Element/innerHTML">MDN</a></p>
<p>요소(element) 내에 포함 된 HTML 또는 XML 마크업을 가져오거나 설정한다.
값으로 DOMString을 넣어준다</p>
<pre><code class="language-jsx">const innerHTMLDiv = document.querySelector(&quot;.innerHTML&quot;);
console.log(innerHTMLDiv.innerHTML);
innerHTMLDiv.innerHTML = &quot;바꿈&quot;;
console.log(innerHTMLDiv.innerHTML);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/e2e1d35d-f4d8-4edf-b2c5-8d2b5f5cb498/image.png" alt=""></p>
<h3 id="innertext">innerText</h3>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/API/HTMLElement/innerText">MDN</a></p>
<p>요소와 그 자손의 렌더링된 텍스트 콘텐츠를 나타낸다.
사용자가 드래그로 긁어서 복붙할 수 있는 텍스트의 근삿값을 제공한다.</p>
<pre><code class="language-jsx">const innerTextDiv = document.querySelector(&quot;.innerText&quot;);
console.log(innerTextDiv.innerText);
innerTextDiv.innerText = &quot;바꿨지롱&quot;;
console.log(innerTextDiv.innerText);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/e22f4b43-c322-417c-ab63-39e37133e275/image.png" alt=""></p>
<h3 id="textcontent">textContent</h3>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/API/Node/textContent">MDN</a></p>
<p>Node와 그 자손의 텍스트 콘텐츠를 표현한다.</p>
<ul>
<li>위의 innerHTML, innerText는 HTMLElement의 메서드이고 textContent는 Node의 메서드이다.</li>
</ul>
<pre><code class="language-jsx">const textContentDiv = document.querySelector(&quot;.textContent&quot;);
console.log(textContentDiv.textContent);
textContentDiv.textContent = &quot;바꿨어용&quot;;
console.log(textContentDiv.textContent);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/7c5b895d-d08e-429b-a66b-c04a8b616c5c/image.png" alt=""></p>
<p>이렇게 사용해서는 뭐가 다르다는 건지 알기 어렵다. 그래서 HTML 태그를 넣어주기로 했다.</p>
<hr>
<h2 id="본격적으로-비교해보기">본격적으로 비교해보기</h2>
<h3 id="innerhtml-1">innerHTML</h3>
<pre><code class="language-jsx">innerHTMLDiv.innerHTML = `&lt;ul&gt;&lt;li&gt;하나&lt;/li&gt;&lt;li&gt;둘&lt;/li&gt;&lt;/ul&gt;`;
console.log(innerHTMLDiv.innerHTML);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/16cb118e-529d-4db1-822b-7a92aeaa9340/image.png" alt=""></p>
<p>console에는 넣어준 텍스트가 찍히지만 브라우저에는 HTML 문법으로 적용된 모습이다.</p>
<h3 id="innertext-1">innerText</h3>
<pre><code class="language-jsx">innerTextDiv.innerText = `&lt;ul&gt;&lt;li&gt;하나&lt;/li&gt;&lt;li&gt;둘&lt;/li&gt;&lt;/ul&gt;`;
console.log(innerTextDiv.innerText);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/8c4d13db-8c02-49e7-905d-ac7a770f2633/image.png" alt=""></p>
<p>console에 찍힌 문자 그대로 브라우저에도 찍힌 모습이다.
인스펙터로 확인해봐도 실제로 태그가 생성되지 않았다.</p>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/03dd5899-4b89-4667-9fc1-f011a440913a/image.png" alt=""></p>
<h3 id="textcontent-1">textContent</h3>
<pre><code class="language-javascript">textContentDiv.textContent = `&lt;ul&gt;&lt;li&gt;하나&lt;/li&gt;&lt;li&gt;둘&lt;/li&gt;&lt;/ul&gt;`;
console.log(textContentDiv.textContent);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/f7fb721b-395f-4f9f-acc3-2b78fa536e91/image.png" alt=""></p>
<p>innerText와 마찬가지로 console에 찍힌 문자 그대로 브라우저에 찍혔다
인스펙터로 확인해도 같은 모습이다.</p>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/2ed604e6-e562-412a-9f13-85bc272f3aaf/image.png" alt=""></p>
<h4 id="그럼-이제-innerhtml은-알겠는데-innertext와-textcontent의-차이는-뭘까">그럼 이제 innerHTML은 알겠는데 <code>innerText</code>와 <code>textContent</code>의 차이는 뭘까?</h4>
<p>차이를 확인해보기 위해 HTML 구조를 약간 바꿔줬다.</p>
<pre><code class="language-html">// index.html

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
  &lt;title&gt;HTML 예제 연습장&lt;/title&gt;
  &lt;/head&gt;

  &lt;body&gt;
    &lt;div id=&quot;root&quot;&gt;
      &lt;div class=&quot;innerHTML&quot;&gt;innerHTML&lt;/div&gt;
      &lt;div class=&quot;innerText&quot; id=&quot;blue&quot;&gt;
        &lt;style&gt;
          #blue {
            color: blue
          }
        &lt;/style&gt;
        innerText
        &lt;span style=&quot;display: none;&quot; id=&quot;blue&quot;&gt;hide span&lt;/span&gt;
      &lt;/div&gt;
      &lt;div class=&quot;textContent&quot; id=&quot;red&quot;&gt;
        &lt;style&gt;
          #red {
            color: red
          }
        &lt;/style&gt;
        textContent
        &lt;span style=&quot;display: none&quot;&gt;hide span&lt;/span&gt;
      &lt;/div&gt;
      &lt;/div&gt;
      &lt;/body&gt;
  &lt;script src=&quot;app.js&quot;&gt;&lt;/script&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-jsx">// app. js

const innerTextDiv = document.querySelector(&quot;.innerText&quot;);
console.log(innerTextDiv.innerText);

const textContentDiv = document.querySelector(&quot;.textContent&quot;);
console.log(textContentDiv.textContent);</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/05968402-9d55-48a5-a5dc-ff8a87beef28/image.png" alt=""></p>
<hr>
<h2 id="결론">결론</h2>
<h4 id="innertext-2">innerText</h4>
<ul>
<li>브라우저에 실제로 그려진 내용만(사용자가 드래그해서 복붙할 수 있는 내용만) 표기된다.</li>
<li>style 태그로 작성된 내용, display:none으로 된 자식 등은 표기되지 않는다. (display: block 등 보이는 속성이라면 표기된다.)</li>
</ul>
<h4 id="textcontent-2">textContent</h4>
<ul>
<li>style 태그로 작성된 내용, display:none으로 된 보이지 않는 자식등 자신의 자식 요소도 표기된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] Math.trunc vs Math.floor]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-Math.trunc</link>
            <guid>https://velog.io/@e-sum-e/Javascript-Math.trunc</guid>
            <pubDate>Wed, 05 Jun 2024 11:45:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>프로그래머스 문제를 풀던 중 숫자를 나눈 몫을 구해야 하는 문제가 있었는데, 정수형태여야했다. 평소 이런 문제에서는 크게 Math.round, Math.ceil, Math.floor를 사용했는데 스터디원분이 Math.trunc 라는 메서드를 소개해주셨다.</p>
</blockquote>
<p><strong>|</strong> <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120805">해당 프로그래머스 문제</a></p>
<h3 id="mathtrunc">Math.trunc</h3>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc">MDN</a>
주어진 값의 소수 부분을 제거하고 숫자의 정수 부분만 반환한다</p>
<h4 id="그럼-mathfloor와의-차이는-뭘까">그럼 Math.floor와의 차이는 뭘까?</h4>
<p>지금까지 나는 floor가 내가 지정한 자릿수외의 소수는 버리는 메서드라고 생각하고 있었는데, 그럼 trunc와 floor의 차이가 뭔지 혼란스러워졌다.</p>
<br />

<h3 id="mathfloor">Math.floor</h3>
<p><strong>|</strong> <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">MDN</a>
주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환한다</p>
<p>예를 들어</p>
<pre><code class="language-javascript">console.log(Math.floor(3.14)) // 3
console.log(Math.floor(5.9)) // 5</code></pre>
<p>여기까지는 내가 이해해온것과 크게 다르지 않다. 결국 작은 정수를 반환하기 때문에 소수를 버리는 것과 같은 결과가 나오기 때문이다. 그럼 음수라면 어떨까?</p>
<pre><code class="language-javascript">console.log(Math.floor(-3.14)) // -4
console.log(Math.floor(-5.9)) // -6</code></pre>
<p>놀랍게도 각각 -3, -5가 아닌 더 작아질 수 있는 정수인 -4, -6이 반환된다.
그럼 같은 숫자를 trunc를 사용했을 땐 어떻게 될까?</p>
<pre><code class="language-javascript">console.log(Math.trunc(-3.14)) // -3
console.log(Math.trunc(-5.9)) // -5</code></pre>
<p>위 코드를 실행한 결과와 같이 trunc로 했을땐 소수는 버리고 정수 부분만 출력되는 것을 알 수 있었다. </p>
<hr>
<h4 id="그림으로-표현">그림으로 표현</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/dccc05e3-78c1-4dd5-bab6-f9b584d3a702/image.png" alt=""></p>
<p>-1.9에서 더 작게 표현할 수 있는 정수는 내림을 한 -2이다
-1.9의 절대값은 1이고 음수를 적용해주면 -1이다</p>
<pre><code class="language-javascript">console.log(Math.floor(-1.9)) // -2
console.log(Math.trunc(-1.9)) // -1</code></pre>
<p>2.3에서 더 작게 표현할 수 있는 정수는 내림을 한 2이다
2.9의 절대값은 2이고 양수를 적용해주면 2이다</p>
<pre><code class="language-javascript">console.log(Math.floor(2.3)) // 2
console.log(Math.trunc(2.3)) // 2</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] TDZ]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-TDZ</link>
            <guid>https://velog.io/@e-sum-e/Javascript-TDZ</guid>
            <pubDate>Tue, 04 Jun 2024 02:26:14 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Javascript 호이스팅에 대한 설명을 듣던 중 var, const, let으로 선언한 변수에 대한 차이를 배웠다. const, let은 선언전에 사용하면 ReferenceError가 발생하는데 그럼 호이스팅이 되지 않는걸까?</p>
</blockquote>
<h2 id="hoisting--호이스팅">Hoisting | 호이스팅</h2>
<p>스코프 내부 어디서든 변수 선언은 최상위에 선언된것처럼 동작한다</p>
<h2 id="tdz">TDZ?</h2>
<p>Temporal Dead Zone(= 일시적 사각지대)
<img src="https://velog.velcdn.com/images/e-sum-e/post/4a61d5bd-01b8-4c9a-ae13-da7e659bd401/image.png" alt=""></p>
<pre><code class="language-javascript">let age = 20;

function showAge() {
  console.log(age);

  let age = 30;
}

showAge();
</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/f94daa10-aed8-4e47-a2bb-025bcf1086f3/image.png" alt=""></p>
<p>호이스팅은 스코프 단위로 일어나며, showAge 함수에서도 호이스팅이 일어났기 때문에 밖에서 선언한 age=20을 읽지 못한 것이다
<img src="https://velog.velcdn.com/images/e-sum-e/post/15eb3bce-92bb-4fe8-a6dd-6cac45a24173/image.png" alt=""></p>
<h3 id="변수의-생성과정">변수의 생성과정</h3>
<h4 id="var">var</h4>
<ol>
<li>선언 및 초기화</li>
</ol>
<ul>
<li>초기화 : undefined를 할당해주는 단계</li>
</ul>
<ol start="2">
<li>할당</li>
</ol>
<h4 id="let">let</h4>
<ol>
<li>선언 단계</li>
<li>초기화 단계</li>
<li>할당 단계</li>
</ol>
<h4 id="const">const</h4>
<ol>
<li>선언 + 초기화 + 할당</li>
</ol>
<ul>
<li>그래서 선언할때 값을 넣어줘야 하고 이후에는 수정이 불가한 것이다.</li>
</ul>
<h3 id="변수의-스코프">변수의 스코프</h3>
<h4 id="스코프">스코프</h4>
<p>변수가 정의된 영역</p>
<h4 id="var-1">var</h4>
<p>함수 스코프</p>
<ul>
<li>함수 내부에서 선언된 변수는 var로 선언되었다 할지라도 다른 스코프에서 접근할 수 없음</li>
<li>함수 외부에서 var를 사용하면 전역 변수로 선언됨<pre><code class="language-javascript">const age = 20;
</code></pre>
</li>
</ul>
<p>if (age &gt; 19) {
  var type = &quot;성인&quot;;
}</p>
<p>console.log(type); // 성인</p>
<pre><code>
```javascript
function add(num1, num2) {
  var result = num1 + num2;
}

add(2, 3);
console.log(result); // ReferenceError</code></pre><p><img src="https://velog.velcdn.com/images/e-sum-e/post/a3654a74-cf4d-47d5-8f41-d9cd57aec7ca/image.png" alt=""></p>
<h4 id="let-const">let, const</h4>
<p>블록 스코프</p>
<h4 id="var로-선언된-전역-변수와-let으로-선언된-전역변수의-차이">var로 선언된 전역 변수와 let으로 선언된 전역변수의 차이</h4>
<p>var로 선언된 전역 변수는 전역 객체의 프로퍼티로 존재함</p>
<ul>
<li>globalThis로 참조 가능</li>
<li><code>var x = 2</code> === <code>globalThis.x = 2</code></li>
</ul>
<h4 id="무엇으로-선언했건-간에-유일하게-벗어날-수-없는-스코프는-함수-스코프이다">무엇으로 선언했건 간에 유일하게 벗어날 수 없는 스코프는 함수 스코프이다.</h4>
<br />
## 결론

<p>let, const는 호이스팅이 된다.
다만, TDZ에 만들어지고 이는 초기화전에는 사용이 금지되어 있다는 규칙에 의해서 사용할 수 없는 것이다.(ReferenceError)</p>
<hr>
<p><strong>|</strong> <a href="https://youtu.be/ocGc-AmWSnQ?si=MRW_jamr_xHCN8hy">참고 영상</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] Grid]]></title>
            <link>https://velog.io/@e-sum-e/CSS-Grid</link>
            <guid>https://velog.io/@e-sum-e/CSS-Grid</guid>
            <pubDate>Mon, 03 Jun 2024 01:00:05 GMT</pubDate>
            <description><![CDATA[<p><strong>|</strong> <a href="https://www.youtube.com/watch?v=eprXmC_j9A4">참고 영상</a></p>
<h2 id="grid">grid</h2>
<h3 id="먼저-행row-열column-알아보기">먼저 행(row), 열(column) 알아보기</h3>
<p>사실 나는 이게 몇년째 헷갈려서 할 때마다 찾아보고 있다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/1813bb2d-2c1a-4697-ac20-c4480d038165/image.png" alt=""></p>
<h4 id="우선-사용할-기본-문서를-만들어줬다">우선 사용할 기본 문서를 만들어줬다.</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/8f5faa92-3bf7-449a-bb28-8515dfa49a75/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/d2804521-e62b-488c-b164-9ff0b16be736/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/2281a1cc-cba7-4067-ae62-a0c09989a776/image.png" alt=""></p>
<h2 id="container에-적용하는-속성">container에 적용하는 속성</h2>
<p>우선 container에 <code>display: grid</code> 를 적용하면 달라지는 건 없다</p>
<h3 id="grid-template-columns">grid-template-columns</h3>
<p>columns로 정렬했을 때 템플릿의 비율</p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: 40% 60%;
  background-color:whitesmoke
}

// 위 코드와 비슷하지만 더 많이 쓰이는 문법
.container {
  display: grid;
  grid-template-columns: 4fr 6fr;
  background-color: whitesmoke;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/0c0ca9ab-af56-4362-b691-948eddce2beb/image.png" alt=""></p>
<h4 id="왜-fr-단위를-많이-사용할까-→-gap을-넣어보면-알-수-있다">왜 fr 단위를 많이 사용할까? → gap을 넣어보면 알 수 있다.</h4>
<ul>
<li>fr : fractional unit의 준말. 사용 가능한 공간에 대한 비율을 뜻한다.</li>
</ul>
<p>fr일 때</p>
<pre><code class="language-css">  .container {
    display: grid;
    grid-template-columns: 4fr 6fr;
    grid-gap: 1rem; // &lt;- 요거 추가
    background-color: whitesmoke;
  }</code></pre>
<p>  <img src="https://velog.velcdn.com/images/e-sum-e/post/fcb99c45-7865-4e25-a137-5a99b64da3b5/image.png" alt=""></p>
<p>%일 때</p>
<pre><code class="language-css">  .container {
    display: grid;
    grid-template-columns: 40% 60%; // &lt;- %로 수정
    grid-gap: 1rem; // &lt;- 요거는 동일
    background-color: whitesmoke;
  }</code></pre>
<p>  <img src="https://velog.velcdn.com/images/e-sum-e/post/521d0fc0-8e4b-416a-a478-fc19bf485cd2/image.png" alt="">
똑같아 보일 수 있으나 가로 스크롤이 생긴것을 알 수 있다 → gap이 width에 추가적으로 들어가서 그렇다. ⇒ <strong>너비 제어가 어려워진다</strong></p>
<h3 id="repeat">repeat()</h3>
<p>반복할 횟수와 사이즈를 지정할 수 있다.</p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr); // (반복할 횟수, 사이즈)
  // 위 코드와 같은 표현
  // grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 1rem;
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/5fee4d96-9d0a-4670-ae91-05268df237cd/image.png" alt=""></p>
<p>만약에 어떤 부분은 특정 사이즈로 고정하고 나머지의 크기는 유동적이게 하고 싶다면,</p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: 200px 1fr; // 고정하고 싶은 사이즈를 직접 넣으면 된다
  grid-gap: 1rem;
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/e8767d8a-3f9b-4e8d-a994-0da3cb877131/image.png" alt=""></p>
<br />
다음 속성을 적용해보기 위해 요소의 높이를 다르게 주고자 p태그에 내용을 좀 입력해줬다.

<p><img src="https://velog.velcdn.com/images/e-sum-e/post/dc823910-dc86-4a90-9137-71f76f181a58/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/b872880c-7358-404b-9e9a-f38cdb544fd3/image.png" alt=""></p>
<ul>
<li><code>display: grid</code> 가 적용되어 있기 때문에 같은 행에 있는 요소끼리는 높이가 자동으로 맞춰진 모습이다.</li>
</ul>
<br />

<p>하지만! 컨텐츠 내용에 상관없이 높이를 지정해주고 싶어!</p>
<h3 id="grid-auto-rows">grid-auto-rows</h3>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1rem;
  grid-auto-rows: 300px; // &lt;- 이렇게 추가
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/0697ba12-8a97-4e1a-8582-4b6decb14a25/image.png" alt=""></p>
<p>그런데 지정한 높이가 컨텐츠 내용보다 많아서 넘치게 된다면?</p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1rem;
  grid-auto-rows: 250px;
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/b76c25b4-c3d8-423f-b239-28ef20c167cc/image.png" alt=""></p>
<p>** grid-auto-rows: minmax() **</p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1rem;
  grid-auto-rows: minmax(250px, auto); // minmax 추가
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/b43ea6bb-3596-4ab5-a6eb-65d472599e95/image.png" alt="">
(확연한 차이를 알아보기 위해 컨텐츠 내용을 늘렸다)</p>
<ul>
<li>minimum으로 250px이 적용되지만 그보다 높이가 높은 요소가 있다면 해당 요소에 맞추어 높이가 auto로 적용됨</li>
</ul>
<br /> 

<h3 id="justify-items">justify-items</h3>
<p>정렬하기(flex에서의 justify와 동일하다)</p>
<p><strong>justify-items: start</strong></p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1rem;
  grid-auto-rows: minmax(250px, auto);
  justify-items: start; // &lt;- 요기 추가
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/00f4c8db-19fc-483a-b436-bd00567bea65/image.png" alt=""></p>
<p><strong>justify-items: center</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/ea16f441-a296-4d67-b4ab-dac23f77ca49/image.png" alt=""></p>
<p><strong>justify-items: end</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/2bb8bb10-dbe9-4f60-b0bf-e867b2f99469/image.png" alt=""></p>
<h3 id="align-items">align-items</h3>
<p>flex의 align-items와 동일하게 justify축의 수직축을 기준으로 정렬된다</p>
<p><strong>align-items: start</strong></p>
<pre><code class="language-css">.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 1rem;
  grid-auto-rows: minmax(250px, auto);
  align-items: start; // &lt;- 요기 추가
  background-color:whitesmoke
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/16666f34-9b29-4d91-9804-c8e59525a304/image.png" alt=""></p>
<p><strong>align-items: center</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/1e61bdef-8369-4074-a86d-f5a56432de76/image.png" alt=""></p>
<p><strong>align-items: end</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/bf02809d-d196-4b8c-a909-6a5ca3d3322f/image.png" alt=""></p>
<br/>

<h3 id="justify-self">justify-self</h3>
<p>요소 각각의 정렬을 적용할 수 있다.(flex의 align-self처럼)</p>
<pre><code class="language-css">.item:nth-child(5) {
  justify-self: start;
}

// container에 적용한 align-items는 지우고 조정하고 싶은 요소에만 값을 지정해주었다</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/cfcbfe0f-ea85-4d3e-8ae2-fec5dbcdc15e/image.png" alt=""></p>
<h3 id="align-self">align-self</h3>
<p>justify-self처럼 물론 align-self도 가능하다.</p>
<pre><code class="language-css">.item:nth-child(4) {
  justify-self: start;
  align-self: end;
}

// 5번 높이때문에 애매하게 보여서 확연한 차이를 위해 4번으로 적용해줬다</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/74abb49c-1be5-43ad-9a33-9ec008a641f8/image.png" alt=""></p>
<h4 id="응용해보기">응용해보기</h4>
<p>각 요소들을 내가 원하는 사이즈대로 배치시켜보자.
예를 들어 1번은 가로로 한 행을 꽉 채우고 싶다, 2번은 그 남은 영역의 세로로 꽉 채우고 싶다, 3번은 가로 2개 사이즈 만큼을 가지고 싶다.. 등등</p>
<p>이를 위해서는 우선 grid의 column, row가 어떻게 적용되고 있는지를 알아야 한다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/c7413e05-c731-41b4-86ab-90151061ac28/image.png" alt=""></p>
<p><strong>우선 1번이 column으로 꽉 차게 해보겠다</strong></p>
<pre><code class="language-css">.item:first-child {
  grid-column: 1/4; // 분수가 아니라 1부터 4까지라는 의미
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/29f1fe27-3819-47ac-9164-2946e1d44a63/image.png" alt=""></p>
<p><strong>그럼 이번엔 4번이 row로 꽉 차게 해보자</strong>
위에 만든 기준 그림을 참고하면 2~4가 된다</p>
<pre><code class="language-css">.item:nth-child(4) {
  grid-row: 2/4;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/06eb6aa8-0ad0-488b-a626-e6361ef80372/image.png" alt=""></p>
<ul>
<li>오잉? row가 2부터 4까지는 잘 적용이 됐는데.. 순서가 멋대로 바뀌었다 → column을 설정해주면 된다</li>
</ul>
<pre><code class="language-css">.item:nth-child(4) {
  grid-column: 3; // &lt;- 요기 추가
  grid-row: 2/4;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/a97f9777-a670-4ed7-ab97-c4d3a8e1cb2c/image.png" alt=""></p>
<p><strong>이번에는 9번이 4번을 쪼그라트리지 않으면서 침범하게 해보겠다</strong></p>
<pre><code class="language-css">.item:nth-child(9) {
  grid-column: 3;
  grid-row: 3/5;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/63acc503-a148-44b7-82c2-1a2e26688b63/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] Flex]]></title>
            <link>https://velog.io/@e-sum-e/CSS-Flex</link>
            <guid>https://velog.io/@e-sum-e/CSS-Flex</guid>
            <pubDate>Fri, 31 May 2024 07:53:07 GMT</pubDate>
            <description><![CDATA[<p><strong>|</strong> <a href="https://www.youtube.com/watch?v=eprXmC_j9A4">참고 영상</a></p>
<br />

<h2 id="flex">flex</h2>
<h3 id="먼저-행row-열column-알아보기">먼저 행(row), 열(column) 알아보기</h3>
<p>사실 나는 이게 몇년째 헷갈려서 할 때마다 찾아보고 있다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/c5422fb1-bbb0-4b17-a70f-243b960449f1/image.png" alt=""></p>
<h4 id="우선-사용할-기본-문서를-만들어줬다">우선 사용할 기본 문서를 만들어줬다.</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/fed15723-78f5-4227-bcb7-ae9d48471aab/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/7e2926df-28da-4a24-b2c4-e8ebc0e59260/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/3a210c89-54ff-4a06-8720-128f7236fac8/image.png" alt=""></p>
<h2 id="flex-container에-주는-속성">flex container에 주는 속성</h2>
<h3 id="display-flex">display: flex</h3>
<pre><code class="language-css">.container {
  display: flex;
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/a786756c-fdae-4578-80fd-a97d3e9ab8be/image.png" alt="">
flex-direction의 default값이 row이기 때문에 자동으로 행 기준으로 정렬된다.</p>
<h3 id="flex-direction">flex-direction</h3>
<p><strong>flex-direction: column</strong></p>
<pre><code class="language-css">.container {
  display: flex;
  flex-direction: column; // &lt;- 요기 추가
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/0897a5e6-a25e-4a1f-81d9-3fbed4efcf1e/image.png" alt=""></p>
<ul>
<li>열 기준으로 정렬이 된 모양이 된다</li>
</ul>
<br />

<p><strong>flex-direction: row-reverse</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/76fb5cc5-3ed4-426a-af45-145b24a1ca5d/image.png" alt=""></p>
<ul>
<li>row 기준으로 정렬되되 역순으로 정렬된다</li>
</ul>
<h3 id="flex-wrap">flex-wrap</h3>
<p>화면을 줄였을 때 넘치는 요소를 끊어서(나눠서) 보여줄 것인지 여부를 설정할 수 있다</p>
<p><strong>flex-wrap: no-wrap(default. 안끊음)</strong></p>
<pre><code class="language-css">.container {
  display: flex;
  flex-wrap: no-wrap
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/f194951a-ecc6-43dc-afca-b4799ef9e5ba/image.png" alt=""></p>
<br />

<p><strong>flex-wrap: wrap</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/d0e3c813-920c-403f-b373-eb3893fce5eb/image.png" alt="">
화면 너비가 마지막 요소보다 작아지가 끊어서 아래로 내려간 모습이다</p>
<h3 id="justify-content">justify-content</h3>
<p>요소의 정렬을 설정해줄 수 있는데 요소를 오뎅꼬치를 꽂는다고 생각했을 때 꼬치가 축이되는 정렬이다</p>
<pre><code class="language-css">.container {
  display: flex;
  justify-content: flex-start; // &lt;- 요기 추가
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><strong>justify-content: flex-start(default)</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/4de18e99-887c-4ecb-8c80-338efd1c6a3b/image.png" alt=""></p>
<br />

<p><strong>justify-content: center</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/91230edd-7b38-467e-9191-c2f594ecd3bc/image.png" alt=""></p>
<br />

<p><strong>justify-content: space-between</strong>
각 요소별로 전체 여백을 동일하게 나눠 가진다
<img src="https://velog.velcdn.com/images/e-sum-e/post/b4665c21-09ea-4b64-9f3a-6b409c201c58/image.png" alt=""></p>
<br />

<p><strong>justify-content: space-around</strong>
space-between과 비슷하지만 전체 여백을 나눠 가질때 요소의 좌,우로 같이 가지게 된다
<img src="https://velog.velcdn.com/images/e-sum-e/post/074fbe52-d7b6-4f52-96cf-1f7260cfaa1e/image.png" alt=""></p>
<br />

<h3 id="align-items">align-items</h3>
<p>위의 justify-content가 오뎅꼬치를 축으로 삼는다면 align-items는 그 오뎅꼬치의 수직이 되는 축을 축으로 정렬한다.</p>
<pre><code class="language-css">.container {
  display: flex;
  align-items: stretch; // &lt;- 요기 추가
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><strong>align-items: stretch(default)</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/1339a48c-4a02-4a62-8a0b-678d48d9778c/image.png" alt=""></p>
<br />

<p><strong>align-itmes: flex-start</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/0c25062b-b27c-4f7f-a547-d1337b62620f/image.png" alt=""></p>
<br />

<p><strong>align-items: flex-end</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/d26d12fd-b9de-4588-88da-35195ab7660b/image.png" alt=""></p>
<br />

<p><strong>align-items: center</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/557bb715-1f58-42be-a66c-5bb0b40ac809/image.png" alt=""></p>
<br />

<h4 id="응용해보자">응용해보자!</h4>
<p>요소가 행열의 정 중앙으로 오게 하려면?</p>
<pre><code class="language-css">.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/9e819b3c-d4c1-446e-ab7e-ddb5a96f4d5f/image.png" alt=""></p>
<h3 id="align-content">align-content</h3>
<p><code>flex-wrap: wrap</code> 스타일과 함꼐 사용되며, 화면이 좁아져서 요소가 끊어졌을 때 어떻게 보여줄지를 설정할 수 있다.</p>
<pre><code class="language-css">.container {
  display: flex;
  flex-wrap: wrap; // 필요한 스타일
  align-content: flex-start; // &lt;- 요기 추가
  height: 100vh;
  background-color: lightcyan;
}</code></pre>
<p><strong>align-content: flex-start</strong>
위에서 <code>flex-wrap: wrap</code> 만 적용했을떄와 비교해보면 위로 챡 붙어있을을 알 수 있다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/78ea7b06-64df-450c-bf8b-3a9c22c7b1be/image.png" alt=""></p>
<br />

<p><strong>align-content: center</strong>
<img src="https://velog.velcdn.com/images/e-sum-e/post/d5bfe092-7091-4f28-ab1c-62c85eeaabc8/image.png" alt=""></p>
<br />

<p><strong>align-content: space-between</strong>
justify-content와 마찬가지로 남은 여백을 요소별로 나눠 가진 형태이다
<img src="https://velog.velcdn.com/images/e-sum-e/post/8499bb65-5f0c-4737-ab5c-c461c7c80eb6/image.png" alt=""></p>
<br />

<p><strong>align-content: space-around</strong>
justify-content와 마찬가지로 남은 여백을 요소별로 상,하로 나눠 가진 형태이다(축이 바뀌었기 때문에 반대로 나눠 가진다)
<img src="https://velog.velcdn.com/images/e-sum-e/post/fa91ac88-e996-4d47-afbf-287726ded048/image.png" alt=""></p>
<br />

<hr>
<h2 id="flex-item에-주는-속성">flex item에 주는 속성</h2>
<h3 id="flex-grow">flex-grow</h3>
<p>요소가 원래보다 넓어졌을 때 요소 각각을 어떤 비율로 늘어나게 할 지 설정할 수 있다
⚠️ 단, 여백 기준으로 늘리는 것이지 width 기준으로 늘리는 게 아니다</p>
<pre><code class="language-css">.item:nth-child(1){
  flex-grow: 1;
}

.item:nth-child(2){
  flex-grow: 2;
}

.item:nth-child(3){
  flex-grow: 1;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/bbac8863-fca4-473b-9266-32921c2a2f9d/image.png" alt=""></p>
<h3 id="flex-basis">flex-basis</h3>
<p>원래 요소가 점유해야 할 공간을 설정할 수 있다.
설정하게 되면 요소의 너비가 여백이 아닌 내가 지정한 비율대로 너비를 가지게 된다.</p>
<pre><code class="language-css">.item {
  flex-basis: 0;
  background-color:rgba(255, 192, 203, 0.5)
}

.item:nth-child(1){
  flex-grow: 1;
}

.item:nth-child(2){
  flex-grow: 2;
}

.item:nth-child(3){
  flex-grow: 1;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/2bbf89d5-d029-4cac-badc-0d5ef0a0536b/image.png" alt=""></p>
<ul>
<li>아까랑 무슨 차이인가 싶을 수 있는데 flex-basis가 없을 때에는 남은 여백을 기준으로 설정한 비율을 나누기 때문에 B가 A, C의 2배가 아니었다</li>
</ul>
<h3 id="flex-shrink">flex-shrink</h3>
<p><strong>|</strong> <a href="https://youtu.be/7neASrWEFEM?si=MtgkxD5XO3KlFyJm&amp;t=1143">참고 영상</a>
지금까지 보던 영상만으로는 shrink 이해가 잘 되지 않아서 추가적으로 찾아봤다. 근데 기본값을 0라고 알려주시는데 사실은 1이다.</p>
<p>아무튼 flex-shrink는 컨테이너가 작아졌을 때 요소를 어떤 비율로 줄일 것인가를 설정하는 것이다. 확인해보기 위해 스타일을 약간 수정했다.
<img src="https://velog.velcdn.com/images/e-sum-e/post/a3a54380-5bb4-47c3-96ff-7f1646c407e1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/c18dc82d-8889-4989-bf4c-0bff655880f4/image.png" alt=""></p>
<p>그리고 각각의 요소에 flex-shrink를 다르게 적용해보겠다</p>
<pre><code class="language-css">.item:nth-child(1){
  flex-shrink: 3;
}

.item:nth-child(2){
  flex-shrink: 2;
}

.item:nth-child(3){
  flex-shrink: 1;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/d3343a08-c97f-40c2-a83d-d169c2b0ad05/image.gif" alt="">
영상으로 보는게 이해가 더 빨라서 찍어봤다.
컨테이너가 줄어들때 flex-shrink가 3 &gt; 2 &gt; 1인 순으로 줄어드는게 보인다. 줄어드는 비율이기 때문에 숫자가 클수록 빠르게(많이) 줄어든다.</p>
<h3 id="flex-grow-flex-shrink-축약형">flex-grow, flex-shrink 축약형</h3>
<pre><code class="language-css">{ 
    flex-grow: 1
    flex-shrink: 1
}</code></pre>
<p>위 코드는 아래와 같이 축약형으로 쓸 수 있다.</p>
<pre><code class="language-css">{
    flex: 1
}</code></pre>
<p><strong>축약형으로 사용했을 때 달라지는 점</strong>
<code>flex-basis: 0</code>을 적용하지 않아도 요소들이 자동으로 여백이 아닌 너비를 기준으로 나눠 가지게 된다
<img src="https://velog.velcdn.com/images/e-sum-e/post/eb25981e-985c-4830-9ae6-26e72d2b4f69/image.png" alt=""></p>
<h4 id="활용해보기">활용해보기</h4>
<p><strong>하나의 요소에만 flex를 지정했을 때</strong></p>
<pre><code class="language-css">.item:nth-child(2){
  flex: 1;
}

// 나머지 nth-child에는 안넣어줌</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/e2176d78-01a0-4345-8fcb-19019928364c/image.png" alt=""></p>
<p><strong>이를 응용해서 한가지 요소는 너비를 가지고 그 외의 부분을 전체 너비로 가지는 요소를 가지고 싶을 때</strong></p>
<pre><code class="language-css">.item:nth-child(1){
  width: 200px; // 첫번째 요소에만 고정 너비를 주었다
}

.item:nth-child(2){
  flex: 1;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/bbd6dd09-872e-4377-96bb-6610d32c6037/image.png" alt=""></p>
<br />

<h3 id="align-self">align-self</h3>
<p>요소가 자신의 정렬을 스스로 지정할 수 있다
<code>align-items</code> 는 container가 하위 요소들의 정렬을 지정하는 것이기 때문에 다른 것이다</p>
<pre><code class="language-css">.item:nth-child(1){
  flex: 1;
  align-self: flex-start;
}

.item:nth-child(2){
  flex: 2;
  align-self: center;
}

.item:nth-child(3){
  flex: 1;
  align-self: flex-end;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/5d2201d3-4e2f-4e73-818e-920d96f78611/image.png" alt=""></p>
<h3 id="order">order</h3>
<p>요소가 정렬될 순서를 지정할 수 있다</p>
<pre><code class="language-css">.item:nth-child(1){
  flex: 1;
  order: 2;
}

.item:nth-child(2){
  flex: 2;
  order: 1;
}

.item:nth-child(3){
  flex: 1;
  order: 3;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/b6a99d93-eb65-430c-ab36-19a7e4a889e3/image.png" alt=""></p>
<h4 id="마법같이-flex-사용해보기">마법같이 flex 사용해보기</h4>
<p>사실 이런 설명 아니었는데 position등 다른 속성으로 하려면 어려운 작업인데 손쉽게 할 수 있어서 이렇게 제목을 붙여봤다
위에서 만든 예제의 방향을 열 기준으로 바꾸고 싶다면 어째야 할까 정말 막막하다. 그렇게 flex를 사용하면 direction만 수정해주면 아주 쉽게 바꿀 수 있다.</p>
<pre><code class="language-css">.container {
  //...else
  flex-direction: column;
 }</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/11868639-e8aa-42c4-9cb4-ef7602289cc2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] fs module로 파일 데이터 읽어오기]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-fs-module%EB%A1%9C-%ED%8C%8C%EC%9D%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%BD%EC%96%B4%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@e-sum-e/Javascript-fs-module%EB%A1%9C-%ED%8C%8C%EC%9D%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%BD%EC%96%B4%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Thu, 30 May 2024 00:41:05 GMT</pubDate>
            <description><![CDATA[<p><strong>|</strong> <a href="https://nodejs.org/api/fs.html#file-system">공식 문서</a></p>
<p>파일 시스템과 상호작용 할 수 있게 도와주는 모듈
node와 함께 번들링되어 있기 때문에 별도 설치 없이 사용 가능</p>
<pre><code class="language-jsx">const fs = require(&quot;fs&quot;)</code></pre>
<ul>
<li>비슷한 예로 http, url, path 등이 있음</li>
</ul>
<hr>
<p><strong>알고리즘에서 어떻게 사용할것인가?</strong>
파일의 내용을 읽을 수 있다</p>
<pre><code class="language-jsx">// 비동기적
fs.readFile(filename, [options], callback)</code></pre>
<ul>
<li>filename에 해당하는 파일을 [option]의 방식으로 읽은 후 callback으로 받은 함수를 호출한다</li>
</ul>
<pre><code class="language-jsx">// 동기적
fs.readFileSync(filename, [options])</code></pre>
<ul>
<li>filename에 해당하는 파일을 [option]의 방식으로 읽은 후 문자열을 반환한다</li>
</ul>
<hr>
<p>이 외에도 알고리즘에서 활용할 수 있을 진 모르겠으나.. 파일을 쓸 수 있는 기능도 있다</p>
<pre><code class="language-jsx">// 비동기적
fs.writeFile(filenmae, data, [options], callback)</code></pre>
<ul>
<li>filename에 해당하는 파일에 [option]의 방식으로 data 내용을 쓴 후 callback함수를 호출한다</li>
</ul>
<pre><code class="language-jsx">// 동기적
fs.writeFileSync(filename, data, [options])</code></pre>
<ul>
<li>filename에 해당하는 파일에 [option]의 방식으로 data 내용을 쓴다</li>
</ul>
<hr>
<h4 id="사용-방법">사용 방법</h4>
<p><strong>|</strong> <a href="https://www.acmicpc.net/problem/1000">백준 - 1000번문제</a></p>
<pre><code class="language-javascript">const fs = require(&quot;fs&quot;);
const readedData = fs.readFileSync(0, &quot;utf-8&quot;);
const splitedData = readedData.split(&quot; &quot;);
const a = splitedData[0];
const b = splitedData[1];

console.log(a / 1 + b / 1);
</code></pre>
<hr>
<h3 id="readline하고는-뭐가-다르지">readline하고는 뭐가 다르지?</h3>
<p>프로그래머스에서는 데이터를 한 줄씩 입력받아서 처리하는 문제가 몇가지 있었는데 그 땐 readline을 사용했었다</p>
<p><strong>|</strong> <a href="https://velog.io/@e-sum-e/Javascript-readline%EC%9C%BC%EB%A1%9C-%EA%B0%92-%EC%9E%85%EB%A0%A5%EB%B0%9B%EA%B8%B0">해당 내용 포스팅</a></p>
<blockquote>
<p>그럼 fs 모듈도 뭔가 데이터를 입력 받는 거고 readline도 데이터를 입력 받는 건데 뭐가 다른걸까?</p>
</blockquote>
<p>위에서 기술한 것처럼 readline 모듈은 한 번에 한 줄씩 데이터를 읽기 위한 인터페이스를 제공해주는 모듈이고, fs는 파일에 접근해서 데이터를 읽어오는 모듈이라는 점이 다른 거 같다. 코테에서 각각 어떻게 활용할 지는 문제 조건에 따라 다를 듯 하다.</p>
<p><strong>|</strong> <a href="https://mywebproject.tistory.com/182">참고 블로그</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] readline으로 값 입력받기]]></title>
            <link>https://velog.io/@e-sum-e/Javascript-readline%EC%9C%BC%EB%A1%9C-%EA%B0%92-%EC%9E%85%EB%A0%A5%EB%B0%9B%EA%B8%B0</link>
            <guid>https://velog.io/@e-sum-e/Javascript-readline%EC%9C%BC%EB%A1%9C-%EA%B0%92-%EC%9E%85%EB%A0%A5%EB%B0%9B%EA%B8%B0</guid>
            <pubDate>Thu, 30 May 2024 00:33:29 GMT</pubDate>
            <description><![CDATA[<p><strong>|</strong> <a href="https://velog.io/@pexe99/JavaScript-readline-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0">[참고 블로그]</a></p>
<br />

<h3 id="readline">readline?</h3>
<ul>
<li>Readable stream에서 한번에 한 줄씩 데이터를 읽기 위한 인터페이스를 제공하는 모듈<ul>
<li>데이터를 읽기 위해 인터페이스를 제공해주는 모듈</li>
<li>Javascript에 내장되어 있는 듯 하다</li>
</ul>
</li>
</ul>
<hr>
<h3 id="사용-방법">사용 방법</h3>
<h4 id="1-readline-모듈-불러오기">1. readline 모듈 불러오기</h4>
<pre><code class="language-jsx">const readline = require(&quot;readline&quot;);</code></pre>
<h4 id="2-readline-인터페이스-생성하기">2. readline 인터페이스 생성하기</h4>
<pre><code class="language-jsx">const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
})</code></pre>
<ul>
<li><code>process.stdin</code> : standard input에 대한 readable stream</li>
<li><code>process.stdout</code> : standard output에 대한 writable stream<ul>
<li>stream?<ul>
<li>일련의 연속성을 갖는 흐름을 뜻함. 데이터, 파일 등 컴퓨터 프로그램과 환경 사이에 미리 연결된 입출력 통로</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="3-입출력-처리하기">3. 입출력 처리하기</h4>
<pre><code class="language-jsx">rl.on(&quot;line&quot;, (line) =&gt; {
    /* 입력값 처리 코드 */
    rl.close()
})

rl.on(&quot;close&quot;, () =&gt; {
    /* 입력 이후 실행 코드 */ 
    process.exit();
})</code></pre>
<ul>
<li><code>rl.on</code> 을 이용하여 이벤트와 콜백함수를 전달하게 됨<ul>
<li><code>line</code> : 입력 받은 값을 한 줄씩 읽어 문자열 타입으로 전달하는 이벤트</li>
<li><code>close</code> : 더 이상 입력값이 없을 경우에 해당하는 이벤트</li>
</ul>
</li>
<li><code>rl.close()</code> : 인터페이스를 종료하며 무한 입력받기를 방지</li>
<li><code>process.exit()</code> : 프로세스 종료</li>
</ul>
<hr>
<h4 id="사용-예시">사용 예시</h4>
<p><strong>|</strong> <a href="https://school.programmers.co.kr/learn/courses/30/lessons/181952">프로그래머스 - 문자열 출력하기</a></p>
<pre><code class="language-javascript">const readline = require(&#39;readline&#39;);
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on(&#39;line&#39;, function (line) {
    input = [line];
}).on(&#39;close&#39;,function(){
    str = input[0];
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[error] is missing in props validation eslint react/prop-types]]></title>
            <link>https://velog.io/@e-sum-e/error-is-missing-in-props-validation-eslint-reactprop-types</link>
            <guid>https://velog.io/@e-sum-e/error-is-missing-in-props-validation-eslint-reactprop-types</guid>
            <pubDate>Wed, 29 May 2024 07:59:23 GMT</pubDate>
            <description><![CDATA[<h4 id="발생-상황">발생 상황</h4>
<p>jsx로 만든 child component에서 props로 받는데 빨간줄이 생겼다 → 근데 브라우저에서 실행하면 정상 동작이 되긴 한다😡
<img src="https://velog.velcdn.com/images/e-sum-e/post/19d366ad-7ba6-46b3-8c13-4558bfec982b/image.png" alt=""></p>
<h4 id="원인-추측">원인 추측</h4>
<p><strong>|</strong> <a href="https://haerim95.tistory.com/41">참고 블로그</a>
javascript에서는 props의 타입을 지정해주지 않기 때문에 타입이 정확한지 잡아낼 수 없어서 검사해줘야 하는 거 같다.(typescript 쓸 때는 본 적 없는 상황이긴 하다)
참고한 블로그에 의하면 해결 방법으로 props-type 라이브러리를 설치하고 그러는 방법도 있던데 내가 선택한 해결 방법은,</p>
<h4 id="해결방법">해결방법</h4>
<p><strong>|</strong> <a href="https://stackoverflow.com/questions/38684925/react-eslint-error-missing-in-props-validation">참고 스택 오버 플로우</a>
스택 오버 플로우에서 알아낸 방법 두 가지 중 하나를 선택해서 적용하면 된다.</p>
<ol>
<li><code>.eslintrc</code> 의 <code>&quot;rules&quot;</code> 에 옵션 추가<pre><code class="language-javascript">&quot;rules&quot;: {
 &quot;react/prop-types&quot;: &quot;off&quot;
}</code></pre>
</li>
<li>빨간 밑줄이 그어지는 코드 위에 아래 내용 추가(나는 코드의 의미를 위한 내용이 아니라서 싫어하는 방법이다)<pre><code class="language-javascript">/* eslint-disable react/prop-types */</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useState의 initialState를 값으로 넣어주는것과 함수의 반환값을 넣는 것의 차이]]></title>
            <link>https://velog.io/@e-sum-e/React-useState%EC%9D%98-initialState%EB%A5%BC-%EA%B0%92%EC%9C%BC%EB%A1%9C-%EB%84%A3%EC%96%B4%EC%A3%BC%EB%8A%94%EA%B2%83%EA%B3%BC-%ED%95%A8%EC%88%98%EC%9D%98-%EB%B0%98%ED%99%98%EA%B0%92%EC%9D%84-%EB%84%A3%EB%8A%94-%EA%B2%83%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@e-sum-e/React-useState%EC%9D%98-initialState%EB%A5%BC-%EA%B0%92%EC%9C%BC%EB%A1%9C-%EB%84%A3%EC%96%B4%EC%A3%BC%EB%8A%94%EA%B2%83%EA%B3%BC-%ED%95%A8%EC%88%98%EC%9D%98-%EB%B0%98%ED%99%98%EA%B0%92%EC%9D%84-%EB%84%A3%EB%8A%94-%EA%B2%83%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 27 May 2024 10:23:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🤔 이것저것 예제 코드를 치다보니 문득 궁금해졌다. useState의 초깃값으로 값을 넣어주기도 하지만 함수를 넣어서 그 함수의 반환값을 초깃값으로 사용하기도 하는데 무슨 차이가 있는 걸까? 
나는 함수 반환값을 넣어본적이 예제 코드 외에 자의적으로 한 적은 없긴 하지만 사용법을 알면 더 잘 사용하게 될지두....</p>
</blockquote>
<br />

<h4 id="게으른-초기화--lazy-initialization">게으른 초기화 | lazy initialization</h4>
<p>initialState를 설정해줄때 원시값이 아니라 값을 반환해주는 함수를 넣는 것을 게으른 초기화(lazy initialization)이라고 한다</p>
<p><a href="https://legacy.reactjs.org/docs/hooks-reference.html#lazy-initial-state">📘 공식 문서</a></p>
<p>❝
<em>The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render:</em></p>
<hr>
<p><em>initialState 인수는 초기 렌더링 중에 사용되는 상태입니다. 후속 렌더링에서는 무시됩니다. 초기 상태가 비용이 많이 드는 계산의 결과인 경우 대신 초기 렌더링 시에만 실행되는 함수를 제공할 수 있습니다.</em>
❞</p>
<h4 id="예제-만들어서-확인해보기">예제 만들어서 확인해보기</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/49cbcf93-09aa-40d6-9590-379cfd72288b/image.png" alt=""></p>
<ol>
<li><p>useState를 두개 사용해주었다</p>
<ul>
<li>value는 initialState를 값으로,
lazy는 함수의 반환값으로 설정해주되 setState로 컴포넌트가 렌더링 됐을 때 어떻게 보이는 지를 알기 위해 콘솔에 메시지를 찍어주도록 해보았다.</li>
</ul>
</li>
<li><p>렌더 트리거가 일어나서 컴포넌트가 렌더링 될 때마다 콘솔에 메시지를 찍어주도록 해주었다.</p>
</li>
</ol>
<h4 id="결과-확인">결과 확인</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/1574893e-bbfc-40cd-87b9-507f38530e67/image.png" alt=""></p>
<p>실제로 initial state를 설정해주는 callback 함수는 최초 렌더 시에만 동작하고 이후 state의 변화로 인해 리렌더가 일어나도 재실행 되지 않음을 볼 수 있었음</p>
<hr>
<h4 id="👉-결론">👉 결론</h4>
<p>동작 방법에 차이는 없었고 성능을 위해서 정말 무거운 작업을 통해 initial state가 설정될 때 사용하는 거 같다</p>
<br />
<br />
<br />
<br />
<br />


<p>😅 그리고 잠깐 했던 바보같은 생각.</p>
<blockquote>
<p>useMemo로 복잡한 로직을 통해 도출되는 값을 관리하는데 useState의 lazy initialization을 이용해서 두면 되지 않을까?</p>
</blockquote>
<p><del>응 안돼.</del></p>
<p>useState는 component의 render trigger를 일으키는 state를 관리하는 훅이다. 처음에만 지정해놓고 이후에 state의 변화가 없다면(그로 인해 렌더 트리거를 일으키지 않을거라면) 용도에 맞지 않다.
고로,
각자 훅은 제각기 용도가 있으니 맞게 잘 사용하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Redux와 context 차이점 알아보기2]]></title>
            <link>https://velog.io/@e-sum-e/React-Redux%EC%99%80-context-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B02</link>
            <guid>https://velog.io/@e-sum-e/React-Redux%EC%99%80-context-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B02</guid>
            <pubDate>Mon, 27 May 2024 07:28:10 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@e-sum-e/React-Context">► 이전 스텝</a></p>
<blockquote>
<p>리덕스의 동작이 어떻게 이루어지는 지 대충 훑어봤다. state를 단순히 등록하고 가져오는 것 뿐만 아니라 해당 state가 어떻게 변하게 할 것인지, state가 변했을 땐 해당 state를 사용하는 컴포넌트에 렌더링을 일으켜 주는 등 global state를 <strong>관리</strong>해준다는 느낌을 받았다. <br /><em>그럼 이제 context가 뭔지 알아보자.</em></p>
</blockquote>
<br />

<h4 id="context란">context란?</h4>
<p>props drilling이 발생했을 때 props 내려주기를 극복하기 위해 등장한 개념.</p>
<pre><code class="language-jsx">import { PropsWithChildren, createContext, useContext } from &quot;react&quot;;

const MyCotext = createContext&lt;{ hello: string } | undefined&gt;(undefined);

const ContextProvider = ({
  children,
  text,
}: PropsWithChildren&lt;{ text: string }&gt;) =&gt; {
  return (
    &lt;MyCotext.Provider value={{ hello: text }}&gt;{children}&lt;/MyCotext.Provider&gt;
  );
};

const useMyContext = () =&gt; {
  const context = useContext(MyCotext);
  if (context === undefined) {
    throw new Error(
      &quot;useMyContext는 ContextProvider 내부에서만 사용할 수 있습니다&quot;
    );
  }

  return context;
};

const ChildComponent = () =&gt; {
  const { hello } = useMyContext();

  return &lt;h3&gt;{hello}&lt;/h3&gt;;
};

export const ParentComponent = () =&gt; {
  return (
    &lt;ContextProvider text=&quot;react&quot;&gt;
      &lt;ChildComponent /&gt;
    &lt;/ContextProvider&gt;
  );
};
</code></pre>
<ul>
<li>이런식으로 어떤 값을 원하는 곳에서 쓸 수 있게 해주는 <span style="background-color: #fff5b1"><strong>일종의 통로</strong></span> 역할임</li>
<li>값이 꼭 state가 아니어도 됨(예제에서도 그냥 react라는 string일뿐 state가 아님)</li>
</ul>
<br />

<h4 id="usecontext를-사용할-때-주의할-점">useContext를 사용할 때 주의할 점</h4>
<p>useContext를 함수형 컴포넌트 내부에서 사용할 때는 항상 컴포넌트 재활용이 어려워진다는 점을 염두에 둬야 함.
useContext가 선언되어 있으면 Provider에 의존성을 가지고 있는 셈이 되므로 아무데서나 재활용하기에는 어려워질 수 있음.</p>
<ul>
<li>context를 사용하고자 하는 컴포넌트가 Provider의 하위 컴포넌트로 존재해야만 사용할 수 있음 → 재활용 했을 때 컴포넌트의 위치가 자유로울 수 없음</li>
</ul>
<hr>
<p>책에서 발췌한 나를 관통하는 내용이 있어 옮겨적어보겠다.</p>
<div style="text-align:center">❝</div>

<p><em>일부 리액트 개발자들이 콘텍스트와 useContext를 상태 관리를 위한 리액트의 API로 오해하고 있다는 것이다. 엄밀히 따지면 *</em>콘텍스트는 상태를 주입해주는 API**다. 상태 관리 라이브러리가 되기 위해서는 최소한 다음 두 가지 조건을 만족해야 한다.</p>
<ol>
<li>어떠한 상태를 기반으로 다른 상태를 만들어낼 수 있어야 한다.</li>
<li>필요에 따라 이러한 상태 변화를 최적화 할 수 있어야 한다.*</li>
</ol>
<p><em>하지만 context는 둘 중 어느것도 하지 못한다. 단순히 props값을 하위로 전달해 줄 뿐, useContext를 사용한다고 해서 렌저링이 최적화되지도 않는다.</em></p>
<div style="text-align:center">❞</div>

<br />

<blockquote>
<p>확실히 redux는 state를 등록, 관리해주는 느낌이었지만 context는 위에서 기술한것처럼 일단 반드시 state를 내보내지 않아도 될 뿐더러 단순히 어떤 값이 필요해서 꺼내쓰기만 하는 느낌이었다. 이를 global state로 응용하기 위해 useState, useReducer등을 함께 사용하는 것 뿐인 거 같다</p>
</blockquote>
<br />

<hr>
<p>📘 참고 : 모던 리액트 Deep dive - Chapter3</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Redux와 context 차이점 알아보기1]]></title>
            <link>https://velog.io/@e-sum-e/React-Context</link>
            <guid>https://velog.io/@e-sum-e/React-Context</guid>
            <pubDate>Mon, 27 May 2024 05:51:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<p>🤔 리덕스로 전역 상태를 관리하다보니 이전 회사에서는 주로 ContextAPI를 사용했던 기억이 났다. 그러면서 둘의 차이점이 뭘까에 대한 고민이 생겼다. <br />
서치해보니 주로 사용법에 대한 차이점이 기술되어 있었고 나는 그거 말고 개념적으로 무엇이 다른가에 대해 궁금해졌다. <i><strong>그럼 Context는 뭐지?</strong></i></p>
<hr>
<h3 id="일단-redux의-동작을-더-이해해보자">일단 redux의 동작을 더 이해해보자</h3>
<h3 id="usestate로-redux-구현해보기">useState로 redux 구현해보기</h3>
<p>useState로 리덕스를 구현해보면 리덕스의 동작 원리를 이해하는 데 도움이 될 거 같아서 시도해보기로 했다.</p>
<p><strong>예제</strong>
Counter1, Counter2라는 각각의 컴포넌트에서 동일한 state를 이용하는 경우 이를 global state로 관리하는 예제</p>
<br />

<h4 id="store-타입-생성">store 타입 생성</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/019bd1af-26fd-43bd-8205-9f6994838da0/image.png" alt=""></p>
<ul>
<li><code>get</code> : store에서 관리중인 state의 최신 상태를 반환해줌</li>
<li><code>set</code> : store에서 관리중인 state의 상태 변화를 일으키는 함수로써 상태를 반환함 ≒ <code>setState</code> </li>
<li><code>subscribe</code> : store의 변경을 감지하고 싶은 컴포넌트들이 자신의 callback 함수를 등록하는 곳</li>
<li><code>unsubscribe</code> : subscribe 함수가 받아온 callback함수를 등록된 callbacks에서 제거</li>
</ul>
<br />

<h4 id="createstore-usestore-생성">createStore, useStore 생성</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/3766cb73-b53e-4781-8f45-1f7da163c39e/image.png" alt=""></p>
<ul>
<li>사용할 store를 받아서 get으로 최신 상태를 받은 후 useState의 초기값으로 설정</li>
<li>useStore의 <code>useEffect</code> 에서 선언한 <code>callbackFn</code> 함수는 setState로 state를 변화시키기 때문에 리렌더링을 일으킴(렌더 트리거)</li>
<li>clean up이 일어날 때 <code>unsubscribe</code> (callbacks에서 callbackFn 삭제) 실행<ul>
<li>여기에서 약간 헷갈렸는데 clean up 함수는 함수가 일단 등록되고 clean up이 되는 시점에 실행된다. 그런데 useEffect return 함수에 함수가 아니라 함수를 실행시켜버리면(<code>return unsubscribe()</code>), clean up 시점이 오기도 전인 컴포넌트가 렌더링 되자마자 실행되어 버리기 때문에 useStore 함수가 제대로 동작하지 않게 된다 → subscribe 하자마자 unsubscribe 되기 때문에 비정상 동작</li>
</ul>
</li>
</ul>
<br />


<h4 id="컴포넌트에서-store-사용하기">컴포넌트에서 store 사용하기</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/27dd1583-0184-4279-89be-c60a38d9b3e8/image.png" alt=""></p>
<ul>
<li>Counter1, Counter2 라는 각각의 컴포넌트에서 동일한 store의 state 사용</li>
</ul>
<br />

<hr>
<p>이대로 진행하면 각 counter의 버튼을 누를때마다 store를 공유하며 업데이트 되는 것을 알 수 있다. 하지만 store가 원시값이 아니라 객체일 경우, 일부만 바뀌어도 useState가 실행되므로 store의 어떤 값이 바뀌든지 간에 리렌더링이 일어나게 된다.
<strong><em>⇒ 원하는 값이 바뀌었을때만 리렌더링 되도록 수정해보자</em></strong></p>
<hr>
<br />

<h3 id="store에서-원하는-값이-바뀌었을때만-리렌더링하도록-하기">store에서 원하는 값이 바뀌었을때만 리렌더링하도록 하기</h3>
<h4 id="usestoreselector-생성">useStoreSelector 생성</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/57977a71-871e-4a4a-bddc-6931d7ab6f12/image.png" alt=""></p>
<ul>
<li>store에 등록된 상태 중 사용할 상태만 selector라는 콜백 함수로 반환받아서 value로 등록하여 사용</li>
</ul>
<br />

<h4 id="컴포넌트에서-사용해보기">컴포넌트에서 사용해보기</h4>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/e2293fb8-1d58-4842-9aba-008e4c2706df/image.png" alt=""></p>
<ul>
<li><p>store에 등록된 상태는 이제 count, text 이렇게 두가지이다</p>
</li>
<li><p>count를 사용할 컴포넌트에서는 selector 함수로 count만 뽑아서 사용하고, text를 사용할 컴포넌트에서는 selector 함수로 text만 뽑아서 사용한다</p>
</li>
<li><p>근데 이때 selector 함수를 useCallback으로 감싸준다</p>
<ul>
<li><p>dependencies를 빈 배열로 줘서 최초 렌더시에만 등록할 수 있도록 해줬는데 이렇게 하지 않으면 상태의 변화에 따라 컴포넌트가 리렌더 됐을 때 selector 함수는 동일한데 계속해서 unsubscribe → subscribe가 계속 반복되기 때문이다
<img src="https://velog.velcdn.com/images/e-sum-e/post/c94b4308-4f69-4caf-9d87-51e8f2697419/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/a51c2bcd-e597-4334-86d3-977f5c827b90/image.png" alt=""></p>
</li>
<li><p>useCallback을 사용하고 싶지 않다면 컴포넌트 리렌더 시 해당 컴포넌트내에 등록된 함수가 재실행되는게 문제이기 때문에 컴포넌트 바깥에 함수를 생성하고 컴포넌트 안에서 해당 함수를 가져다 쓰는 것도 해결방법이 될 수 있다
<img src="https://velog.velcdn.com/images/e-sum-e/post/3e7b7668-db10-47cb-9432-f3a4a853b8d0/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<hr>
<div style="text-align: right; text-decoration:underline">📘 참고 : 모던 리액트 Deep dive - Chapter5</div>]]></description>
        </item>
        <item>
            <title><![CDATA[mac에서 한영키 상관없이 항상 ₩말고 `만(원화 말고 백틱만) 입력되게 하기]]></title>
            <link>https://velog.io/@e-sum-e/mac%EC%97%90%EC%84%9C-%ED%95%9C%EC%98%81%ED%82%A4-%EC%83%81%EA%B4%80%EC%97%86%EC%9D%B4-%ED%95%AD%EC%83%81-%EB%A7%8C-%EC%9E%85%EB%A0%A5%EB%90%98%EA%B2%8C-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@e-sum-e/mac%EC%97%90%EC%84%9C-%ED%95%9C%EC%98%81%ED%82%A4-%EC%83%81%EA%B4%80%EC%97%86%EC%9D%B4-%ED%95%AD%EC%83%81-%EB%A7%8C-%EC%9E%85%EB%A0%A5%EB%90%98%EA%B2%8C-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 20 May 2024 14:25:19 GMT</pubDate>
            <description><![CDATA[<ul>
<li>mac에선 백틱(`) 위치가 두가지 역할을 한다<ul>
<li>한글 입력 모드일 땐 ₩(원화)</li>
<li>영어 입력 모드일 땐 `(백틱)</li>
</ul>
</li>
<li>그런데 velog, slack, notion등에서 코드 블록을 만들때 ```로 간편하게 하는게 습관이 되어 있어서 설정을 바꾸고 싶어졌다</li>
<li>karaniber를 사용하는 방법도 있지만 최대한 앱은 설치하지 않고 싶었기 때문에 macd의 <code>DefaultKeybindings</code> 를 설정하는 방법으로 진행했다<ul>
<li><a href="https://www.korecmblog.com/blog/backtick-fix">참고 블로그</a></li>
</ul>
</li>
</ul>
<br />

<h3 id="⚠️-문제-발생">⚠️ 문제 발생!</h3>
<ul>
<li>그런데 어째서인지<pre><code>$ vi ~/Library/KeyBindings/DefaultKeyBinding.dict</code></pre>를 실행하면,
<img src="https://velog.velcdn.com/images/e-sum-e/post/b1ed4a99-07a6-4a0f-8359-54737378b0d9/image.png" alt="">
이런 에러 메시지가 뜨는 것이 아니겠는가?<ul>
<li><em>읽을수만 있는 옵션이라 덮어쓸 수 없다고?</em></li>
</ul>
</li>
</ul>
<ul>
<li><p>그래서 혹시나 하는 마음에 <code>vi</code> 대신 <code>touch</code>로 실행해봤다
<img src="https://velog.velcdn.com/images/e-sum-e/post/2ba0707e-8b20-40c1-b9fb-2c50cf3b4573/image.png" alt=""></p>
<ul>
<li>그러면 아까와는 조금 다른 에러 메시지가 보인다</li>
<li><em>흠? 권한이 없다는 데?</em></li>
</ul>
</li>
<li><p>찾아보니 유닉스 코드를 관리자 권한으로 실행하기 위해선 앞에 <strong><code>sudo</code></strong> 를 붙여줘야 한다고 한다
<img src="https://velog.velcdn.com/images/e-sum-e/post/9d00a695-e0e5-459b-899e-377293c299fc/image.png" alt=""></p>
<ul>
<li>Password를 입력하라는 말에 너무 설렜지만 이내 No such file or directory라는 문구를 만나게 되고....</li>
</ul>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/15fa88ec-d829-4fad-a7a9-b6853dd81384/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/94d61630-8d6f-41d1-b8b1-c9d2bc3b7259/image.png" alt=""></p>
<ul>
<li>vi로 다시 재도전하니까 정상적으로 설정할 수 있었다!!</li>
</ul>
</li>
</ul>
<br />

<hr>
<h3 id="🤔-궁금해진-점">🤔 궁금해진 점</h3>
<h4 id="touch-vi의-차이는-뭘까">touch, vi의 차이는 뭘까?</h4>
<ul>
<li><h2 id="touch">touch</h2>
</li>
<li><h2 id="vi">vi</h2>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[💻✨ 새 노트북 세팅하기]]></title>
            <link>https://velog.io/@e-sum-e/%EC%83%88-%EB%85%B8%ED%8A%B8%EB%B6%81-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@e-sum-e/%EC%83%88-%EB%85%B8%ED%8A%B8%EB%B6%81-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 20 May 2024 13:53:13 GMT</pubDate>
            <description><![CDATA[<p>야호 노트북을 새로 샀다!</p>
<ul>
<li>초기 세팅을 해보자</li>
</ul>
<br />

<h3 id="1-homebrew-설치">1. homebrew 설치</h3>
<ul>
<li><p>공식문서 참조하여 설치</p>
</li>
<li><p>설치되고 나서 커맨드 입력하라는 메시지를 무시했더니 brew 명령어 실행이 안됐음
<img src="https://velog.velcdn.com/images/e-sum-e/post/d576b1aa-6196-4964-8304-71833fed5e31/image.png" alt=""></p>
<ul>
<li>자세히 보니 친절하게 뭐뭐 커맨드에 입력하라고 되어 있다😅</li>
</ul>
</li>
</ul>
<br />

<h3 id="2-brew로-node-설치">2. brew로 node 설치</h3>
<pre><code class="language-javascript">    brew install node</code></pre>
<br />

<h3 id="3-nvmnode-version-manager-설치">3. nvm(node version manager) 설치</h3>
<ul>
<li><p>nvm 리포지토리에 있는 문서 참조하여 설치</p>
<pre><code class="language-jsx">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh</code></pre>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/bd48fa07-439e-4566-bbb4-7bf1a99a07c5/image.png" alt=""></p>
<ul>
<li><p>설치가 끝나면 안내 문구에</p>
<pre><code>=&gt; Appending nvm source string to /Users/air/.zprofile </code></pre><ul>
<li>이 나오고 이에 따라 해당 경로의 파일을 열어보면 안내 문구 아래에 있는 명령어가 들어 있었음
<img src="https://velog.velcdn.com/images/e-sum-e/post/00209fbc-ac71-4650-ad7c-0c4dacda6690/image.png" alt=""></li>
</ul>
</li>
</ul>
</li>
<li><p>그리고 호기롭게 nvm 명령어를 입력했는데 실행이 안됨😫
<img src="https://velog.velcdn.com/images/e-sum-e/post/c1b52526-76e6-4ab9-b1b6-3959e9ff0068/image.png" alt=""></p>
</li>
<li><p>그래서 공식문서를 뒤져봄 → <a href="https://github.com/nvm-sh/nvm?tab=readme-ov-file#troubleshooting-on-macos">Troubleshooting on macOS</a> 항목 찾음
• If you use bash, it may be that your <code>.bash_profile</code> (or <code>~/.profile</code>) does not source your <code>~/.bashrc</code> properly. You could fix this by adding <code>source ~/&lt;your_profile_file&gt;</code> to it or following the next step below.</p>
<ul>
<li><p>그래서</p>
<pre><code class="language-jsx">source .zprofile</code></pre>
<ul>
<li>이렇게 하니 잘 작동함!</li>
</ul>
</li>
</ul>
</li>
</ul>
<br />

<h3 id="4-vscode를-code-로-여는-방법">4. vscode를 <code>code</code> 로 여는 방법</h3>
<ul>
<li><a href="https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line">https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line</a></li>
</ul>
<br />

<h3 id="5-pnpm-설치">5. pnpm 설치</h3>
<ul>
<li><a href="https://pnpm.io/installation#using-npm">https://pnpm.io/installation#using-npm</a><ul>
<li>3번에서 Node를 설치해줬기 때문에 npm을 사용할 수 있음</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] Redux의 action.type에 enum을 사용하여 생긴 문제(as const 사용)]]></title>
            <link>https://velog.io/@e-sum-e/TypeScript-as-const</link>
            <guid>https://velog.io/@e-sum-e/TypeScript-as-const</guid>
            <pubDate>Mon, 20 May 2024 10:14:15 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-상황">문제 상황</h3>
<p>  <img src="https://velog.velcdn.com/images/e-sum-e/post/1486d06d-1dab-489c-8b09-d433b1fa5b98/image.png" alt=""></p>
<ul>
<li>redux의 <code>action.type</code> 들을 enum으로 만듬<ul>
<li><code>action.type</code> 은 string이고 이를 enum으로 관리하는 게 좋아 보였기 때문</li>
</ul>
</li>
<li><code>action.type</code> 에 따라 <code>action.payload</code> 가 바뀌어야 함</li>
<li>reducer에서 payload 타입을 제대로 읽어내지 못함</li>
<li>에러
<img src="https://velog.velcdn.com/images/e-sum-e/post/380236d0-28f3-4748-82c7-6d0c2b3eaeed/image.png" alt=""></li>
</ul>
<h3 id="시도-방법">시도 방법</h3>
<ul>
<li><p>리듀서에서 받고 있는 <code>action.payload</code> 의 타입이 어떻게 됐는 지 확인
<img src="https://velog.velcdn.com/images/e-sum-e/post/f3eee53b-7534-4ca9-a780-858e111b39ee/image.png" alt=""></p>
<ul>
<li>어라? 어째서 action creator에서 반환된 값이 지정되지 않지?
→ case의<code>action.type</code> 은 <code>TODO_ACTIONS</code> 중에 하나를 사용하는 것이기 때문에 고정되는 것이 아님 → 그래서 payload 타입도 고정이 되지 않는 것임<blockquote>
<p>💡 아 그럼 ReturnType을 고정시키면 되겠구나</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h3 id="해결-방안">해결 방안</h3>
<h4 id="actionpayload-타입을-actiontype-에-매칭시켜서-고정하자"><code>action.payload</code> 타입을 <code>action.type</code> 에 매칭시켜서 고정하자!</h4>
<ul>
<li>action creator의 반환값에 <code>as const</code> 사용<ul>
<li><em>이 함수가 반환하는 거는 이런 모양이야🔨</em> 라고 못박기
<img src="https://velog.velcdn.com/images/e-sum-e/post/a4f45bed-e94b-4ccf-9aab-cf4018a01d6c/image.png" alt=""></li>
<li>creator 함수 모두의 반환값에 as const를 해주지 않으면 여전히 리듀서에서 헷갈려하기 때문에 모두 바꾼 후에 타입을 확인해야 함</li>
</ul>
</li>
<li>결과
<img src="https://velog.velcdn.com/images/e-sum-e/post/cadf994c-b163-4ce0-a68f-5f24a1087a32/image.png" alt="">
<img src="https://velog.velcdn.com/images/e-sum-e/post/d8a7046c-fb0a-40fd-94e2-8441561f6da6/image.png" alt=""><ul>
<li>각 action.type별로 payload 타입이 고정되었음을 확인했다(나머지 케이스는 너무 길어서 스샷 생략)</li>
</ul>
</li>
</ul>
<hr>
<h3 id="🤔-궁금해진-점">🤔 궁금해진 점</h3>
<ul>
<li><p>왜 action creator의 반환 값을 정해줬는데도 고정이 안된걸까?
<img src="https://velog.velcdn.com/images/e-sum-e/post/f15cd459-1eb4-4c08-b4c6-f7e5226f8c55/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/e-sum-e/post/35445358-d382-4d97-8b83-c82f5a7789d4/image.png" alt=""></p>
<ul>
<li><code>action.type</code> 을 구별해내는 enum이 <code>TODO_ACTIONS</code> 에 할당된 것들중 하나(string)이기 때문에 리듀서의 switch문에서 action.type의 case별로 정확히 구별해낼 수 없음 -&gt; 따라서 TodoAction에 할당된 payload 값들 중에 하나가 될 것이라고 두루뭉술하게 알고 있음</li>
<li>각 action creator별로 정확하게 이런 모양의 값이 반환될거야(= as const)라고 지정해줘서 리듀서에서 정확하게 체크할 수 있게 됨</li>
</ul>
</li>
<li><p>왜 이게 궁금했지? → <code>as const</code> 를 한번에 이해하지 못해서 생긴 궁금점인거 같다</p>
<ul>
<li>공부해보려고 참고한 <a href="https://velog.io/@taewo/Typescript-as-const%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC">블로그</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>