<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>cu.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 01 Feb 2024 14:14:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. cu.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/_mak_______" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[4장. 주석]]></title>
            <link>https://velog.io/@_mak_______/4%EC%9E%A5.-%EC%A3%BC%EC%84%9D</link>
            <guid>https://velog.io/@_mak_______/4%EC%9E%A5.-%EC%A3%BC%EC%84%9D</guid>
            <pubDate>Thu, 01 Feb 2024 14:14:16 GMT</pubDate>
            <description><![CDATA[<h3 id="책에서-기억하고-싶은-내용을-써보세요">책에서 기억하고 싶은 내용을 써보세요.</h3>
<ul>
<li><p><em>나쁜 코드에 주석을 달지 마라. 새로 짜라. - 브라이언 W. 커니핸, P.J. 플라우거</em> (p.68)</p>
</li>
<li><p>&quot;이런! 주석을 달아야겠다!&quot; 아니다! 코드를 정리해야 한다! (p.69)</p>
</li>
<li><p>많은 경우 주석으로 달려는 설명을 함수로 만들어 표현해도 충분하다. (p.70)</p>
</li>
<li><p>어떤 용도로 사용하든 시스템에 나쁜 코드를 남겨 놓는 핑계가 되어서는 안 된다. (p.74-75)</p>
</li>
</ul>
<h3 id="오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요">오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</h3>
<ul>
<li><p>주석에도 종류가 많다. 하지만 결국 대부분이 나쁜 주석이다.</p>
</li>
<li><p>&#39;주석은 나쁘다.&#39;의 매우 다양한 표현이 인상적이다. (저자가 주석을 얼마나 싫어하는 건지 가늠할 수 없다.)</p>
</li>
<li><p>주석을 없앨 수 있는 방법은 주석으로 하고 싶은 말을 코드로 하는 것이다.</p>
</li>
<li><p>책의 장을 거듭할 수록 예제의 나쁜 점이 잘 보인다. 예전의 나였다면 &#39;음, 그래..&#39; 하면서 넘어갔을 코드들이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3장. 함수]]></title>
            <link>https://velog.io/@_mak_______/3%EC%9E%A5.-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@_mak_______/3%EC%9E%A5.-%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 30 Jan 2024 16:12:29 GMT</pubDate>
            <description><![CDATA[<h3 id="책에서-기억하고-싶은-내용을-써보세요">책에서 기억하고 싶은 내용을 써보세요.</h3>
<ul>
<li><p>작게! 더 작게! (p. 42)</p>
</li>
<li><p>각 함수가 이야기 하나를 표현했다. 각 함수가 너무도 멋지게 다음 무대를 준비했다. (p. 43)</p>
</li>
<li><p>함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다. 그 한 가지만을 해야 한다. (p. 44)</p>
</li>
<li><p>플래그 인수는 추하다. (p. 52)</p>
</li>
<li><p>인수 2개는 한 값을 표현하는 두 요소다. 두 요소에는 자연적인 순서도 있다. (p. 52)</p>
</li>
<li><p>부수 효과는 거짓말이다. 어느 쪽이든 교활하고 해로운 거짓말이다. (p. 54)</p>
</li>
<li><p>함수 선언부를 찾아보는 행위는 코드를 보다가 주춤하는 행위와 동급이다. 인지적으로 거슬린다는 뜻이므로 피해야 한다. (p. 56)</p>
</li>
</ul>
<h3 id="오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요">오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</h3>
<ul>
<li><p>기본 객체를 가지는데 Object.assign을 사용하는 것을 간과하고 있었다.</p>
</li>
<li><p>여태 2개 이상의 인수의 순서를 외우는 걸 너무도 당연하게 생각하고 있었다.</p>
</li>
<li><p>새로운 부분이 정말 많다. 그만큼 내가 좋지 않는 방법으로 함수를 써왔다는 것이겠지. 위의 기억하고 싶은 내용들은 전부 내가 하지 못했던 행위이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2장. 의미 있는 이름]]></title>
            <link>https://velog.io/@_mak_______/2%EC%9E%A5.-%EC%9D%98%EB%AF%B8-%EC%9E%88%EB%8A%94-%EC%9D%B4%EB%A6%84</link>
            <guid>https://velog.io/@_mak_______/2%EC%9E%A5.-%EC%9D%98%EB%AF%B8-%EC%9E%88%EB%8A%94-%EC%9D%B4%EB%A6%84</guid>
            <pubDate>Tue, 30 Jan 2024 15:19:24 GMT</pubDate>
            <description><![CDATA[<h3 id="책에서-기억하고-싶은-내용을-써보세요">책에서 기억하고 싶은 내용을 써보세요.</h3>
<ul>
<li>좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다. (p.22)</li>
<li>존재 이유는? 수행 기능은? 사용 방법은?. (p.22)</li>
<li>프로그래밍은 사회 활동이기 때문이다. (p.27)</li>
<li>의미를 해독할 책임이 독자에게 있는 논문 모델이 아니라 의도를 밝힐 책임이 저자에게 있는 잡지 모델이 바람직하다. (p.34)</li>
</ul>
<h3 id="오늘-읽은-소감은-떠오르는-생각을-가볍게-적어보세요">오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요</h3>
<ul>
<li>너무 재밌다!</li>
<li>긴 이름을 짓는 게 괜찮을까 고민한 적이 여러 번 있었는데, 짧은 이름으로 이해하지 못하는 것 보다 긴 이름으로 한 번에 이해할 수 있는 편이 더 좋다는 확신을 받았다!</li>
<li>저자와 독자, 사회 활동이라는 단어로 프로그래밍을 설명하니 새로운 이해가 생겼다.</li>
</ul>
<h3 id="궁금한-내용이-있거나-잘-이해되지-않는-내용이-있다면-적어보세요">궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.</h3>
<p>익숙하지 않은 클래스, 메서드 개념이 있어 읽는 데 오래 걸렸다. (이참에 개념은 알아둬야지)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Typescript (in React JS)]]></title>
            <link>https://velog.io/@_mak_______/Typescript</link>
            <guid>https://velog.io/@_mak_______/Typescript</guid>
            <pubDate>Mon, 08 May 2023 08:29:12 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>타입스크립트란, Javascript를 기반으로 한 strongly-typed 언어이다. strongly-typed이란, 프로그래밍 언어가 작동하기 전에 type을 확인 하는 것이다.</p>
<p>아래의 예제 코드를 보자.</p>
<pre><code class="language-javascript">const user = {
  firstName: &quot;Angela&quot;,
  lastName: &quot;Davis&quot;,
  role: &quot;Professor&quot;,
}

console.log(user.name); // undefined</code></pre>
<p>해당 코드를 실행시키면 user에는 name이 없지만 에러는 나지 않고 undefined를 출력한다.
이 코드가 실제 사용자가 있는 사이트에서 실행이 된다면 사용자는 &quot;안녕하세요, undefined님&quot;이란 문구를 보게 될지도 모른다. 이런 Javascript의 모자란 능력을 커버하기 위해 타입스크립트 사용이 권장된다.</p>
<p>하지만 웹 브라우저는 Javascript 외의 언어를 읽을 수 없다. 그럼 타입스크립트는 어떻게 인식하는 걸까?</p>
<p>타입스크립트는 브라우저에 프로그램이 실행 되기 전에 코드를 분석한다. 분석 후 에러 사항이 있다면 프로그램 실행을 막고, 에러 사항이 없다면 <em>JS 코드를 return하여 프로그램을 실행</em> 시킨다.</p>
<h2 id="설치">설치</h2>
<p>프로젝트 작업 도중에 타입스크립트를 추가하고 싶다면 아래 코드로 필요한 모듈을 설치한다.</p>
<pre><code class="language-bash">npm install typescript @types/node @types/react @types/react-dom @types/jest</code></pre>
<p>설치 후 tsconfig.json 파일이 추가 되었는지도 확인해준다. 없다면 <em>tsc --init</em> 으로 추가하여 설정해주자.</p>
<p>참고 : <a href="https://inpa.tistory.com/entry/TS-%F0%9F%93%98-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-tsconfigjson-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0-%EC%B4%9D%EC%A0%95%EB%A6%AC#tsconfig_%EC%83%9D%EC%84%B1" target="_blank">tsconfig.json 설정 총정리</a></p>
<p>따로 모듈을 설치하는게 번거롭다면 아래 코드로 프로젝트를 아예 처음부터 시작하는 방법이 있다.</p>
<pre><code class="language-bash">npx create-react-app my-ts-app --tamplate typescript</code></pre>
<p>타입스크립트 환경에서 작업하면서 다른 모듈을 설치할 때는 @types 처럼 타입 선언이 되어 있는지 확인을 해야한다. npm install 로 간단히 확인할 수 있다.</p>
<pre><code class="language-bash">npm install @types/모듈명</code></pre>
<p>모듈명만 변경하여 install 해보면 타입스크립트 선언이 된 모듈인지 아닌지 바로 확인이 가능하다.</p>
<h2 id="시작">시작</h2>
<p>타입스크립트라 한들 JS와 크게 다르지 않다. 표면적으론 타입을 지정해주는게 다를 뿐이다.
타입을 지정할 때는 아래와 같은 방법을 쓸 수 있다.</p>
<h3 id="직접-타입-지정">직접 타입 지정</h3>
<p>콜론( : )을 사용하여 직업 타입을 지정할 수 있다.</p>
<pre><code class="language-javascript">const plus = (a:number, b:number) =&gt; a + b;</code></pre>
<h3 id="interface">interface</h3>
<p>인터페이스 선언은 객체의 모양(object&#39;s shape)을 설명한다. 인터페이스가 정의된 컴포넌트나 함수는 인터페이스에 있는 props를 반드시 준수해야 한다.</p>
<pre><code class="language-javascript">interface BoxProps {
  bgColor: string;
  borderColor?: string; // string | undefined - optional prop
}

function Box({ bgColor, borderColor }: BoxProps) {
  return &lt;Container bgColor={bgColor] borderColor={borderColor ?? bgColor] /&gt;;
}

// or
function Box(props: BoxProps) {
  return &lt;Container bgColor={props.bgColor} borderColor={props.borderColor} /&gt;;
}

// App.tsx
function App(){
  return &lt;div&gt;
      &lt;Box bgColor=&quot;tomato&quot; borderColor=&quot;black&quot; /&gt;
    &lt;Box bgColor=&quot;teal&quot; /&gt;
  &lt;/div&gt;;
}</code></pre>
<h3 id="usesate">useSate</h3>
<pre><code class="language-javascript">const [value, setValue] = useState&lt;number | string&gt;(0);

setValue(3);
setValue(&quot;hello&quot;);
// setValue(true); Error</code></pre>
<p>useSate에서 초기값을 지정할 경우, 타입을 지정하지 않아도 초기값의 데이터 타입에 따라 앞으로의 value 값을 유추한다.
초기값을 지정하지 않으면 타입은 undefined가 되며, 드물게 복수의 타입이 들어오게 될 경우 &lt;number | string&gt;처럼 지정해준다.</p>
<h3 id="event-type">event type</h3>
<pre><code class="language-javascript">function App(){
  const [value, setValue] = useState(&quot;&quot;);
  const onChange = (event: React.FormEvent&lt;HTMLInputElement&gt;) =&gt; {
    const {
      currentTarget: { value },
    } = event;
    setValue(value);
  };

  const onSubmit = (event: React.FormEvent&lt;HTMLFormElement&gt;) =&gt; {
    event.preventDefault();
    console.log(&quot;hello&quot;, value);
  };

  return (
    &lt;form onSubmit={onSubmit}&gt;
      &lt;input value={value} onChange={onChange} type=&quot;text&quot; placeholder=&quot;username&quot; /&gt;
      &lt;button type=&quot;submit&quot;&gt;Log in&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre>
<p>event 객체를 사용할 때도 타입을 지정해주어야 한다.</p>
<pre><code class="language-javascript">React.FormEvent&lt;HTMLInputElement&gt;;</code></pre>
<p>위 코드는 _리액트의. 폼에서. input에 의해 일어나는 이벤트_를 의미한다. 복잡해서 바로 외우진 못하지만 보통 vscode에서 이벤트(onChange, onClick, onSubmit 등)에 커서를 올리면 친절하게 알림이 뜬다.</p>
<p><img src="https://velog.velcdn.com/images/_mak_______/post/837d0b14-c728-4aeb-9ed4-d7f14e14d637/image.png" alt=""></p>
<p>참고로 FormEvent와 ChangeEvent의 속성은 동일하다.</p>
<p><img src="https://velog.velcdn.com/images/_mak_______/post/62d59baa-1ee4-4959-aaf4-eb80e5c85bf1/image.png" alt=""></p>
<p>다른 리엑트 이벤트가 궁금하다면 &#39;<a href="https://ko.legacy.reactjs.org/docs/events.html" target="_blank">SyntheticEvent 가이드</a>&#39;를 참고하자.</p>
<h2 id="styled-components-theme">styled-components theme</h2>
<p>타입스크립트에서 styled-components를 사용하려면 npm을 따로 설치해주어야 한다.</p>
<pre><code class="language-bash">npm install --save-dev @types/styled-components</code></pre>
<p>그리고 좀 더 효율적으로 사용하기 위해 선언 파일(declarations file)을 만들어 준다. 선언 파일을 생성해주면 어떤 값이 들어가는지 미리 확인이 가능하다. &quot;파일명.d.ts&quot; 처럼 파일명을 지정해준다.</p>
<pre><code class="language-javascript">// styled.d.ts
import &quot;styled-components&quot;;

declare module &quot;styled-components&quot; {
  // Theme interface
  export interface DefaultTheme {
    borderRadius: string;
    colors: {
      main: string;
      secondary: string;
    };
  }
}</code></pre>
<p>작성한 interface를 기반으로 테마나 레이아웃 등 스타일을 선언한다.</p>
<pre><code class="language-javascript">// theme.ts
import { DefaultTheme } from &quot;styled-components&quot;;

export const lightTheme: DefaultTheme = {
  borderRadius: &quot;12px&quot;,
  colors: {
    main: &quot;#222&quot;,
    secondary: &quot;#eee&quot;,
  },
};

export const darkTheme: DefaultTheme = {
  borderRadius: &quot;12px&quot;,
  colors: {
    main: &quot;#fefefe&quot;,
    secondary: &quot;#aaa&quot;,
  },
};</code></pre>
<p>참고 : <a href="https://styled-components.com/docs/api#typescript" target="_blank">styled-components#typescript</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled Components]]></title>
            <link>https://velog.io/@_mak_______/Styled-Components</link>
            <guid>https://velog.io/@_mak_______/Styled-Components</guid>
            <pubDate>Mon, 08 May 2023 07:29:58 GMT</pubDate>
            <description><![CDATA[<h2 id="react-styling">React Styling</h2>
<p>리액트에는 여러 스타일링 방법이 있다.</p>
<blockquote>
<ol>
  <li>inline style</li>
  <li>stylesheet with className</li>
  <li>css module</li>
  <li>CSS-in-JS</li>
</blockquote>
</ol>


<p>CSS-in-JS 방법을 많이 사용하며 그 중에서도 대중적으로 사용하는 <a href="https://styled-components.com/" target="_blank" style="color:black;text-decoration:underline;"><strong>styled-components</strong></a>에 대해 알아보겠다. </p>
<h2 id="설치">설치</h2>
<pre><code class="language-bash">npm i styled-components</code></pre>
<h2 id="시작">시작</h2>
<p>먼저 styled-components를 import 한다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;</code></pre>
<p>styled.button을 생성한다. styled.&lt;태그&gt; 해당 &lt;태그&gt;부분에 html 태그 이름을 넣음으로서 생성이 가능하다. 태그 뒤에는 백틱( ` )을 쓰며 그 안에 스타일을 정의해준다. 스타일은 Scss 정의가 가능하다.</p>
<pre><code class="language-javascript">const Btn = styled.button`
  color: white;
  background-color: tomato;
  border: 0;
  border-radius: 15px;
`;</code></pre>
<p> vscode에서 사용중이라면 아래 extension을 설치해주면 편하다.
<a href="https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components">vscode-styled-components</a></p>
<p><strong>React</strong>
컴포넌트처럼 작성한다.</p>
<pre><code class="language-javascript">function App() {
  return (
      &lt;Btn&gt;Log in&lt;/Btn&gt;
  );
}</code></pre>
<p><strong>HTML</strong>
랜덤한 클래스가 부여되어 스타일이 입혀진다.</p>
<pre><code class="language-html">&lt;button class=&quot;sc-OKtSx hLMzlZ&quot;&gt;Log in&lt;/button&gt;</code></pre>
<h2 id="스타일-확장">스타일 확장</h2>
<p>먼저 정의된 스타일 컴포넌트의 스타일을 상속받아 사용이 가능하다.</p>
<pre><code class="language-javascript">const Box = styled.div`
  background-color: teal;
  width: 100px;
  height: 100px;
`;

const Circle = styled(Box)`
  border-radius: 50px;
`;

&lt;Box /&gt;
&lt;Circle /&gt;</code></pre>
<h2 id="props">props</h2>
<p>스타일 내부에서 props 사용이 가능하다.</p>
<pre><code class="language-javascript">const Box = styled.div`
  background-color: ${props =&gt; props.bgColor};
`;

&lt;Box bgColor=&quot;teal&quot; /&gt;
&lt;Box bgColor=&quot;tomato&quot; &gt;


const Box = styled.div`
  background-color: ${props =&gt; (props.invalid ? &#39;teal&#39; : &#39;tomato&#39;)}
`;

&lt;Box invalid={isValid} /&gt;


const Input = styled.input.attrs({ required: true })`
  background-color: tomato;
`;

&lt;Input /&gt;

// in HTML
&lt;input required=&quot;&quot; class=&quot;sc-kuWgmH cqgciL&quot;&gt;</code></pre>
<h3 id="as-prop">&quot;as&quot; prop</h3>
<p>컴포넌트에 as 속성을 사용하여 스타일은 유지하되 태그 타입만 변경이 가능하다.</p>
<pre><code class="language-javascript">const Btn = styled.button`
  border: 2px solid tomato;
  color: tomato;
`;

&lt;Btn&gt;Button&lt;/Btn&gt;
&lt;Btn as=&quot;a&quot; href=&quot;/&quot;&gt;Link with Btn style&lt;/Btn&gt;


const Component = styled.div`
  color: red;
`;

&lt;Component as=&quot;button&quot; onClick={() =&gt; alert(&#39;It works!&#39;)}&gt;
  Hello World!
&lt;/Component&gt;</code></pre>
<h2 id="selector">Selector</h2>
<p>Scss 방식으로 selector 지정이 가능하다.</p>
<h3 id="class-name">Class Name</h3>
<pre><code class="language-javascript">const Box = styled.div`
  background-color: teal;

  &amp;.isvalid {
    background-color: tomato;
  }
`;

&lt;Box className={isValid &amp;&amp; &quot;isvalid&quot;} /&gt;</code></pre>
<h3 id="component-selector">Component Selector</h3>
<pre><code class="language-javascript">const Emoji = styled.span`
  font-size: 36px;
`;

const Box = styled.div`
  background-color: tomato;

  ${Emoji} {
    &amp;:hover {
      font-size: 56px;
    }
  }
`;

&lt;Box&gt;
  &lt;Emoji&gt;😀&lt;/Emoji&gt;
&lt;/Box&gt;</code></pre>
<h2 id="animation">Animation</h2>
<p>animation을 사용하기 위해선 &#39;keyframes&#39;를 불러와야 한다.</p>
<pre><code class="language-javascript">import styled, { keyframes } from &quot;styled-components&quot;;</code></pre>
<p>그리고 컴포넌트 생성과 비슷하게 작성해준다.</p>
<pre><code class="language-javascript">const rotateAnimate = keyframes`
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
`;

const Box = styled.div`
  animation: ${rotateAnimate} 1s linear infinite;
`;</code></pre>
<p>export하여 다른 곳에서 import하여 사용할 수도 있다.</p>
<h2 id="themes">Themes</h2>
<p>styled-components는 테마 기능을 지원한다.
index.js에서 ThemeProvider를 import하여 사용 가능하다.</p>
<pre><code class="language-javascript">// index.js
import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import { ThemeProvider } from &quot;styled-components&quot;;
import App from &quot;./App&quot;;

const darkTheme = {
  textColor: &quot;whitesmoke&quot;,
  backgroundColor: &quot;#111&quot;,
};

const lightTheme = {
  textColor: &quot;#111&quot;,
  backgroundColor: &quot;whitesmoke&quot;,
};

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(
  &lt;React.StrictMode&gt;
    &lt;ThemeProvider theme={lightTheme}&gt;
      &lt;App /&gt;
    &lt;/ThemeProvider&gt;
  &lt;/React.StrictMode&gt;
);</code></pre>
<pre><code class="language-javascript">// App.js
import styled from &quot;styled-components&quot;;

const Title = styled.h1`
  color: ${(props) =&gt; props.theme.textColor};
`;

const Wrapper = styled.div`
  background-color: ${(props) =&gt; props.theme.backgroundColor};
`;

function App() {
  return (
    &lt;Wrapper&gt;
      &lt;Title&gt;Hello&lt;/Title&gt;
    &lt;/Wrapper&gt;
  );
}</code></pre>
<p>기본적인 설정 방법이며 다크 모드와 라이트 모드의 속성명이 동일해야 한다.</p>
<p>참고 : <a href="https://styled-components.com/docs/basics" target="_blank">styled-components docs</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] Hangman Game]]></title>
            <link>https://velog.io/@_mak_______/Toy-Project-Hangman-Game-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@_mak_______/Toy-Project-Hangman-Game-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Wed, 26 Apr 2023 10:25:09 GMT</pubDate>
            <description><![CDATA[<p>Javascript 공부를 하면서 실습을 위한 토이 프로젝트를 진행해 보았다.
비기너들이 많이 해본다는 코드펜의 행맨 게임이 적당해 보여 참고하였다.</p>
<p><a href="https://codepen.io/cathydutton/pen/JjpxMm" target="_blank">코드펜 행맨 게임</a></p>
<h2 id="목표">목표</h2>
<blockquote>
<ul>
  <li>플로우 차트를 작성해 보자.</li>
  <li>ES6를 최대한 활용해 보자.</li>
  <li>canvas를 사용해 보자.</li>
</blockquote>
</ul>

<h2 id="플로우-차트">플로우 차트</h2>
<p>플로우 차트는 노션으로 작성하였다. 작성하고 보니 로직을 정리하는데 많은 도움이 되었다. 함수 작성하는 순서도 헤매지 않고 쭉 작성할 수 있었다. 그러라고 있는 거지만 새삼 편리성을 느꼈달까.</p>
<p><a href="https://spicy-smartphone-05c.notion.site/JS-Hangman-Game-ab474eef211d4dd5870ad9e69540fe24" target="_blank">노션 플로우 차트</a></p>
<img src="https://velog.velcdn.com/images/_mak_______/post/e3a8fc8c-e4f4-4d6c-815e-409391db7177/image.jpg" alt="플로우 차트 1" />
<img src="https://velog.velcdn.com/images/_mak_______/post/071064cb-c3e5-4129-99d7-bf3a3becdc85/image.jpg" alt="플로우 차트 2" /> 

<p>간략하게 작성해 보자면,</p>
<blockquote>
</blockquote>
<ol>
  <li>게임 시작</li>
  <li>알파벳 버튼 클릭</li>
  <li>정답 단어 스펠링과 비교(true/false)</li>
  <li>맞으면 스펠링 표시, 틀리면 목숨 1 차감 & 행맨 그리기</li>
  <li>단어 스펠링을 전부 맞추면 게임 종료</li>
  <li>목숨이 0이면 게임 종료, 0이 아니면 2번으로 돌아감<br />2번~6번 과정이 반복</li>
  <li>힌트 버튼 클릭 시 힌트 팝업 표시</li>
  <li>다시하기 클릭 시 게임 재시작, 1번으로 돌아감</li>
</ol>

<p>여기서 세부 사항이 여러 갈래로 나뉘니 복잡하게 되었다. 다른 사람이 쓴 플로우 차트를 참고 해보기도 했지만 반복되는 부분이라든지 어떻게 수정해야 더 간결하게 보일지 (노션으로만 해서 그런 건지...)잘 모르겠더라. 피드백이 있는 분은 자유롭게 댓글 남겨주시길 부탁드린다.</p>
<h2 id="코드">코드</h2>
<p>코드펜을 참고하여 작성하면서 좀 더 예쁘게 바꿀 수 있는 부분과 ES6 문법을 사용할 수 있는 부분은 수정하였다. 확실히 실제로 코드를 짜니까 습득이 훨씬 수월했다. 플로우 차트와 조금 다른 부분도 추가되었다(필요 없을 거로 생각했던 맞춘 스펠링 개수 파악 부분이 추가되었다.). 다음에는 사용자가 원하는 데이터를 넣고 사용할 수 있게 플러그인 식으로 써보면 좋겠다는 생각도 들었지만 그건 시간이 된다면 진행해 보기로 한다.</p>
<h3 id="사용한-es6">사용한 ES6</h3>
<h4 id="const-와-let"><strong>const 와 let</strong></h4>
<pre><code>const alphabet = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, ...];

let topic, word, hint, lives, letterBtn, blanks, correctCounter, drawOrder;</code></pre><h4 id="화살표-함수"><strong>화살표 함수</strong></h4>
<pre><code>const frame1 = () =&gt; draw(0, 130, 300, 130);</code></pre><h4 id="template-literals---"><strong>Template Literals ( ` )</strong></h4>
<pre><code>topicText.innerHTML = `주제는 ${topic}입니다.`;</code></pre><h4 id="구조분해할당"><strong>구조분해할당</strong></h4>
<pre><code>({ topic, word, hint } = randomData);
</code></pre><h4 id="spread전개"><strong>Spread(전개)</strong></h4>
<pre><code>if ([...word].indexOf(guessLetter) != -1) {
    // true
    [...word].forEach((correctLetter, i) =&gt; {
         if (correctLetter == guessLetter) {
            blanks[i].innerHTML = correctLetter;
            correctCounter += 1;
            correctCounter == word.length &amp;&amp; gameClear();
        }
    });
}</code></pre><h3 id="canvas">Canvas</h3>
<p>canvas는 처음 사용해보았는데 방식이 svg와 거의 비슷하다. 다만 getContext 메서드를 &#39;2d&#39;로 사용을 했을 때 한정이고, &#39;webgl&#39;이나 &#39;webgl2&#39; 같은 컨텍스트를 사용하게 되면 방식이 아예 달라지는 것 같다. 3d 모션 그래픽을 구현할 때 주로 사용하던데 나중에 꼭 구현해보고 싶다.</p>
<p><a href="https://github.com/mak-somniferum/HangmanGame" target="_blank">Github 보기</a></p>
<p>!codepen[mak-somniferum/embed/OJBmpzX?default-tab=js%2Cresult&amp;theme-id=dark]</p>
<h2 id="마치며">마치며</h2>
<p>솔직히 한 달이면 업무도 하면서 충분히 할 줄 알았는데, 일정이 겹치고 겹쳐서 꽤 바빠지며 시간이 촉박하게 되었다. 시간이 좀 더 있었으면 분명 더 나았을 부분도 있기에 아쉽다. 그래도 어찌어찌 마무리는 되었고 뿌듯함도 느낀다. 아직 갈 길이 멀지만, 앞으로도 토이 프로젝트나 스터디를 하나씩 진행해 가면 분명 발전할 것이라 생각한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NextJS 시작해보기]]></title>
            <link>https://velog.io/@_mak_______/NextJS-%EC%8B%9C%EC%9E%91%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@_mak_______/NextJS-%EC%8B%9C%EC%9E%91%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 19 Jan 2023 07:38:59 GMT</pubDate>
            <description><![CDATA[<style>img {margin: 1rem auto;}</style>

<blockquote>
<p>🐬 Nomad Coder의 <a href="https://nomadcoders.co/nextjs-fundamentals">&#39;NextJS 시작하기&#39;</a> 메모입니다.</p>
</blockquote>
<h2 id="1-시작">1. 시작</h2>
<pre><code>nxp create-next-app</code></pre><p>Next는 Typescript로 많이 쓰는 것 같다. 니코도 그게 제일 좋다고 한다.
처음에 create-next-app을 실행하면 app이름부터 Typescript 사용할건지, eslint 사용할건지, 뭘 많이 물어본다.
<img src="https://velog.velcdn.com/images/_mak_______/post/321c212b-39c4-4bd5-9cf8-1c516c1db005/image.png" alt="">
기본으로 선택되어 있는게 있어서 엔터만 눌렀다. (변경을 어떻게 하는지 몰랐다.)
그럼 아래처럼 디렉토리가 생성된다.
<img src="https://velog.velcdn.com/images/_mak_______/post/517a044c-7bac-49c6-9544-9ae3b402ef89/image.png" alt="">
package.json은 간단하게 되어있다.
<img src="https://velog.velcdn.com/images/_mak_______/post/4a8c42bc-3e90-4607-94e5-291fb60cd523/image.png" alt=""></p>
<h2 id="2-실행">2. 실행</h2>
<pre><code>npm run dev</code></pre><p>localhost로 들어가보면 인트로 화면이 예쁘게 나온다. (요새 블러 처리한 배경이 유행인듯)
<img src="https://velog.velcdn.com/images/_mak_______/post/a537720a-ee9c-461c-8b37-02082f6b75fe/image.png" alt=""></p>
<h2 id="3-페이지-생성">3. 페이지 생성</h2>
<p>/src 경로를 생성하였다면 /src/page 폴더 안의 파일을 전부 삭제 후 index 파일부터 만들어 준다.
컴포넌트 이름은 아무거나 써도 상관없다.
<img src="https://velog.velcdn.com/images/_mak_______/post/7ba82874-f142-4136-a9c4-20477fe62370/image.png" alt="">
<img src="https://velog.velcdn.com/images/_mak_______/post/da4a946d-18b2-4b9f-a46a-db5e6fd15b79/image.png" alt="">
/about 경로의 페이지를 만들고 싶다면 /page 폴더 안에 about 파일만 만들면 된다.
컴포넌트 이름은 아무거나 써도 상관없다.
<img src="https://velog.velcdn.com/images/_mak_______/post/f420eff2-d2fa-41c1-bdb4-f2bf2ce8ce42/image.png" alt="">
<img src="https://velog.velcdn.com/images/_mak_______/post/2fc82a26-a31f-44f4-846c-8ec6283760f1/image.png" alt="">
React에서는 Router 설치하고 render 하고 여러 과정이 있어 많이 헷갈렸는데 Next에서는 암무것도 필요가 없다.</p>
<blockquote>
<p>🐬 pages 폴더 안에 파일명(페이지명)을 신경써서 만들고
🐬 함수를 default로 export하기</p>
</blockquote>
<h2 id="4-페이지-렌더링">4. 페이지 렌더링</h2>
<blockquote>
<p>🐬 React: CSR(Client-Side Rendering)
🐬 Next: SSR(Server-Side Rendering)</p>
</blockquote>
<ul>
<li>리액트가 CSR만 되는건 아님.</li>
</ul>
<p>Next가 React랑 또 다른 점은 페이지 렌더링에서 나타난다.
React는 페이지를 렌더링 할 때 HTML은 id=&quot;root&quot;인 div밖에 나타나 있지 않다. 그래서 Javascript를 렌더링 할 때까지 유저는 빈 화면을 보게 된다. 하지만 Next는 내가 작성한 HTML 요소들을 Javascript가 렌더링 되기 전에 미리 렌더링한다. 그래서 유저들은 Javascript가 렌더링 될 때까지 빈 화면을 보고 있지 않아도 된다.
<img src="https://velog.velcdn.com/images/_mak_______/post/4be5deb6-a170-45c4-9aba-72f60d50c637/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[useNavigate()]]></title>
            <link>https://velog.io/@_mak_______/useNavigate</link>
            <guid>https://velog.io/@_mak_______/useNavigate</guid>
            <pubDate>Mon, 12 Dec 2022 04:02:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>✔ Link가 a 태그와 같이 클릭 시 특정 주소로 이동해주는 태그라면,
useNavigate는 양식이 제출되거나 특정 행동을 하면 페이지 이동을 할 수 있는 &quot;함수를 반환&quot;하는 훅
✔ 특정 조건을 충족할 경우에 페이지 이동이 가능하다.
✔ index를 사용하여 history 기능 사용 가능 -&gt; navigate(-1), navigate(1), ...</p>
</blockquote>
<h2 id="사용방법">사용방법</h2>
<pre><code>import { useNavigate } from &quot;react-router-dom&quot;;

function MainPage() {
  const navigate = useNavigate();

  return(
    &lt;Wrapper&gt;
      &lt;Container&gt;
        &lt;Button title=&quot;글 작성하기&quot; onClick={() =&gt; { navigate(&quot;/post-write&quot;); }} /&gt;
        &lt;PostList posts={data} onClickItem={(item) =&gt; { navigate(`/post/${item.id}`); }} /&gt;
      &lt;/Container&gt;
    &lt;/Wrapper&gt;
  );
}</code></pre><h2 id="usenavigate의-인자">useNavigate()의 인자</h2>
<blockquote>
<p>✔ navigate(&quot;/이동경로&quot;,  { replace: true, state: { 키:값, 키:값 ... }});
✔ 첫 번째 인자로는 주소, 두 번째 인자로 { replace, state } 인수를 사용</p>
</blockquote>
<h3 id="replace-true-or-false">replace (true or false)</h3>
<ul>
<li><p>true를 사용한다면, 이동경로로 넘어간 후 뒤로가기를 하더라도 방금의 페이지로 돌아오지 않음. 
이 때는 자신의 메인 페이지 (&quot;/&quot;)로 돌아오게 됨.</p>
</li>
<li><p>false는 뒤로가기가 가능하며 기본 값.</p>
</li>
</ul>
<h3 id="state-사용-예시">state 사용 예시</h3>
<pre><code>navigate(&quot;/이동경로&quot;, {
    state: {
        id: 1,
        job: &quot;개발자&quot;
    }
});

const navigateState = useNavigate().state;
const [userId, setUserId] = useState(navigateState &amp;&amp; navigateState.id);</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Context]]></title>
            <link>https://velog.io/@_mak_______/Context</link>
            <guid>https://velog.io/@_mak_______/Context</guid>
            <pubDate>Mon, 05 Dec 2022 01:37:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>✔ 데이터를 넘길 때 props를 사용하지 않는 새로운 방식</p>
</blockquote>
<p>아래는 기존에 데이터를 props로 전달하는 방식과 Context로 전달하는 방식을 표현한 예시이다.</p>
<h2 id="기존-방식">기존 방식</h2>
<p><img src="https://velog.velcdn.com/images/_mak_______/post/5f5b7b98-04e5-4faf-b64c-9cc3b24b514c/image.png" alt=""></p>
<h2 id="context-사용">Context 사용</h2>
<p><img src="https://velog.velcdn.com/images/_mak_______/post/fb694d89-f9ff-40ea-89c2-854eaac811e3/image.png" alt=""></p>
<h2 id="언제-사용해야-할까">언제 사용해야 할까</h2>
<p>Context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법이다. 그러한 데이터로는 현재 로그인한 유저, 테마, 언어 등이 있다.</p>
<p><strong>props를 사용한 데이터 전달 예시</strong>
<img src="https://velog.velcdn.com/images/_mak_______/post/e7786d2f-a92a-4a38-85cb-4a6200f8835e/image.png" alt=""></p>
<p><strong>Context를 사용한 데이터 전달 예시</strong> 
<img src="https://velog.velcdn.com/images/_mak_______/post/8f709032-d458-4ee7-9e9b-a28feb8c0e56/image.png" alt=""></p>
<h2 id="사용-방법">사용 방법</h2>
<ol>
<li><p>Context 생성
const  ThemeContext = <strong>creatContext(&quot;light&quot;);</strong></p>
</li>
<li><p>Context 저장
&lt; <strong>ThemeContext.Provider</strong> value=&quot;dark&quot; &gt;</p>
</li>
<li><p>Context 접근하기
3-1. <strong>Context.Consumer</strong>
&lt; ThemeContext.Consumer &gt; {value =&gt; &lt; Button theme={value} /&gt;}
3-2. <strong>useContext(Context)</strong>
<img src="https://velog.velcdn.com/images/_mak_______/post/2898a556-80e9-4719-ad0a-45b4232bd706/image.png" alt="">
3-3. <strong>contextType</strong> - class 컴포넌트
<img src="https://velog.velcdn.com/images/_mak_______/post/12c89cd6-1017-41e2-9df6-1cc5656e8ed7/image.png" alt=""></p>
</li>
</ol>
<h2 id="사용-전-고려할-것">사용 전 고려할 것</h2>
<blockquote>
<p>✔ 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것.
✔ context를 사용하면 컴포넌트를 재사용하기가 어려워지므로 꼭 필요할 때만 쓰는 걸 추천.
✔ context보다 컴포넌트 합성이 더 간단한 해결책일 수도 있다.
✔ Provider의 부모가 렌더링 될 때마다 불필요하게 하위 컴포넌트가 다시 렌더링 되는 문제가 생길 수도 있다. 이를 피하기 위해서는 값을 부모의 state로 끌어올린다.</p>
</blockquote>
<pre><code>&lt;Page user={user} avatarSize={avatarSize} /&gt;
// ... 그 아래에 ...
&lt;PageLayout user={user} avatarSize={avatarSize} /&gt;
// ... 그 아래에 ...
&lt;NavigationBar user={user} avatarSize={avatarSize} /&gt;
// ... 그 아래에 ...
&lt;Link href={user.permalink}&gt;
  &lt;Avatar user={user} size={avatarSize} /&gt;
&lt;/Link&gt;</code></pre><p>user와 avatarSize라는 props를 실제로 사용하는 곳은 Avatar 컴포넌트 뿐인데 props를 여러 단계에 걸쳐 보내줘야 한다는 게 번거로워 보일 수 있다. 게다가 위에서 Avatar 컴포넌트로 보내줘야하는 props가 추가된다면 그 또한 중간 레벨에 모두 추가해줘야 한다.</p>
<p>여기서 Avatar 컴포넌트 자체를 넘겨주면 context를 사용하지 않고 이를 해결할 수 있다. 그러면 중간에 있는 컴포넌트들이 user나 avatarSize 에 대해 전혀 알 필요가 없다.</p>
<pre><code>function Page(props) {
  const user = props.user;
  const userLink = (
    &lt;Link href={user.permalink}&gt;
      &lt;Avatar user={user} size={props.avatarSize} /&gt;
    &lt;/Link&gt;
  );
  return &lt;PageLayout userLink={userLink} /&gt;;
}

// 이제 이렇게 쓸 수 있다.
&lt;Page user={user} avatarSize={avatarSize} /&gt;
// ... 그 아래에 ...
&lt;PageLayout userLink={userLink} /&gt;
// ... 그 아래에 ...
&lt;NavigationBar userLink={userLink} /&gt;
// ... 그 아래에 ...
{props.userLink}</code></pre><p>이렇게 바꾸면 Link와 Avatar 컴포넌트가 user 와 avatarSize props를 쓴다는 걸 알아야 하는 건 가장 위에 있는 Page 뿐이다.</p>
<p>참고 <a href="https://ko.reactjs.org/docs/context.html#gatsby-focus-wrapper">https://ko.reactjs.org/docs/context.html#gatsby-focus-wrapper</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[합성과 상속]]></title>
            <link>https://velog.io/@_mak_______/%ED%95%A9%EC%84%B1%EA%B3%BC-%EC%83%81%EC%86%8D</link>
            <guid>https://velog.io/@_mak_______/%ED%95%A9%EC%84%B1%EA%B3%BC-%EC%83%81%EC%86%8D</guid>
            <pubDate>Mon, 05 Dec 2022 01:36:18 GMT</pubDate>
            <description><![CDATA[<h1 id="합성composition">합성(Composition)</h1>
<blockquote>
<p>✔ 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것.</p>
</blockquote>
<h2 id="containment">Containment</h2>
<p>어떤 컴포넌트들은 어떤 자식 엘리먼트가 들어올 지 미리 예상할 수 없는 경우가 있다. 범용적인 ‘박스’ 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트에서 특히 자주 볼 수 있다.</p>
<p>이러한 컴포넌트에서는 특수한 children prop을 사용하여 자식 엘리먼트를 출력에 그대로 전달하는 것이 좋다.</p>
<pre><code>function FancyBorder(props) {
  return (
    &lt;div className={&#39;FancyBorder FancyBorder-&#39; + props.color}&gt;
      {props.children}
    &lt;/div&gt;
  );
}</code></pre><p>여기서 children은 리액트에서 기본적으로 제공해주는 prop이다.</p>
<pre><code>function WelcomeDialog() {
  return (
    &lt;FancyBorder color=&quot;blue&quot;&gt;
      &lt;h1 className=&quot;Dialog-title&quot;&gt;
        Welcome
      &lt;/h1&gt;
      &lt;p className=&quot;Dialog-message&quot;&gt;
        Thank you for visiting our spacecraft!
      &lt;/p&gt;
    &lt;/FancyBorder&gt;
  );
}</code></pre><p>h1과 p는 FancyBorder의 props.children으로 전달되고, FancyBorder는 {props.children}을 div 안에 렌더링하므로 전달된 엘리먼트들이 최종 출력된다.</p>
<h3 id="여러-개의-children이-필요한-경우">여러 개의 children이 필요한 경우</h3>
<p>여러 개의 children이 필요한 경우 고유한 children이 아닌 자신만의 props를 정의하여 표현 할 수 있다.</p>
<pre><code>function SplitPane(props) {
  return (
    &lt;div className=&quot;SplitPane&quot;&gt;
      &lt;div className=&quot;SplitPane-left&quot;&gt;
        {props.left}
      &lt;/div&gt;
      &lt;div className=&quot;SplitPane-right&quot;&gt;
        {props.right}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

function App() {
  return (
    &lt;SplitPane
      left={
        &lt;Contacts /&gt;
      }
      right={
        &lt;Chat /&gt;
      } /&gt;
  );
}</code></pre><h2 id="specialization특수화">Specialization(특수화)</h2>
<p>때로는 어떤 컴포넌트의 “특수한 경우”인 컴포넌트를 고려해야 하는 경우가 있다. 예를 들어, WelcomeDialog는 Dialog의 특수한 경우라고 할 수 있다. 리액트에서는 합성을 사용하여 특수화를 구현한다.</p>
<p>아래 예시에서는 Dialog라는 범용적인 컴포넌트를 만들고, 거기에 props를 구분하여 WelcomeDialog라는 특수한 경우의 컴포넌트를 만들었다. props.title과 props.message에 어떤 내용을 넣느냐에 따라 경고 다이얼로그가 될 수도 있고, 웰컴 다이얼로그가 될 수도 있다.</p>
<pre><code>function Dialog(props) {
  return (
    &lt;FancyBorder color=&quot;blue&quot;&gt;
      &lt;h1 className=&quot;Dialog-title&quot;&gt;
        {props.title}
      &lt;/h1&gt;
      &lt;p className=&quot;Dialog-message&quot;&gt;
        {props.message}
      &lt;/p&gt;
    &lt;/FancyBorder&gt;
  );
}

function WelcomeDialog() {
  return (
    &lt;Dialog
      title=&quot;어서 오세요!&quot;
      message=&quot;우리 사이트에 방문하신 것을 환영합니다!&quot; /&gt;
  );
}</code></pre><h2 id="containment와-specialization을-함께-사용">Containment와 Specialization을 함께 사용</h2>
<p><img src="https://velog.velcdn.com/images/_mak_______/post/44725bc1-fa9e-489d-ad73-c6b220f2260e/image.png" alt=""></p>
<h1 id="상속inheritance">상속(Inheritance)</h1>
<p>Facebook에서는 수천 개의 React 컴포넌트를 사용하지만, 컴포넌트를 상속 계층 구조로 작성을 권장할만한 사례를 아직 찾지 못했다고 한다.</p>
<p>props와 합성은 명시적이고 안전한 방법으로 컴포넌트의 모양과 동작을 커스터마이징하는데 필요한 모든 유연성을 제공한다. 컴포넌트가 원시 타입의 값, React 엘리먼트 혹은 함수 등 어떠한 props도 받을 수 있다.</p>
<p>UI가 아닌 기능을 여러 컴포넌트에서 재사용하기를 원한다면, 별도의 JavaScript 모듈로 분리하는 것이 좋다. 컴포넌트에서 해당 함수, 객체, 클래스 등을 import 하여 사용할 수 있다. <strong>상속받을 필요 없이 말이다.</strong></p>
<p>참고 <a href="https://ko.reactjs.org/docs/composition-vs-inheritance.html">https://ko.reactjs.org/docs/composition-vs-inheritance.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[state 공유]]></title>
            <link>https://velog.io/@_mak_______/React-state-%EA%B3%B5%EC%9C%A0</link>
            <guid>https://velog.io/@_mak_______/React-state-%EA%B3%B5%EC%9C%A0</guid>
            <pubDate>Thu, 01 Dec 2022 06:04:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>종종 동일한 데이터에 대한 변경사항을 여러 컴포넌트에 반영해야 할 필요가 있다.
이럴 때는 가장 가까운 공통 상위 컴포넌트로 state를 끌어올리는 것이 좋다.</p>
</blockquote>
<p>React 애플리케이션 안에서 변경이 일어나는 데이터에 대해서는 “진리의 원천(source of truth)“을 하나만 두어야 한다. 보통의 경우, <strong><em>1)</em></strong> state는 렌더링에 그 값을 필요로 하는 컴포넌트에 먼저 추가된다. 그러고 나서 <strong><em>2)</em></strong> 다른 컴포넌트도 역시 그 값이 필요하게 되면 그 값을 그들의 가장 가까운 공통 조상으로 끌어올리면 된다.</p>
<p>다른 컴포넌트 간에 존재하는 state를 동기화시키려고 노력하는 대신 <a href="https://ko.reactjs.org/docs/state-and-lifecycle.html#the-data-flows-down">하향식 데이터 흐름</a>에 기대는 걸 추천한다.</p>
<h1 id="다른-컴포넌트로-state-공유">다른 컴포넌트로 state 공유</h1>
<blockquote>
<p>✔ state 공유는 props로 이루어진다.
✔ 상위 &gt; 하위 혹은 하위 &gt; 상위 순서는 상관 없다. 무조건 상위부터 시작한다. (하향식 데이터 흐름)</p>
</blockquote>
<h2 id="example">Example</h2>
<p><strong>상위 컴포넌트</strong></p>
<pre><code>import { useState } from &quot;react&quot;;
import ChildInput from &quot;./ChildInput&quot;;

function ShareValue(){
  const [value, setValue] = useState(&quot;First Value&quot;);

  const handleChangeValue = (childStateValue) =&gt; {
    setValue(childStateValue);
  }

  return (
    &lt;div&gt;
      &lt;ChildInput value={value} onChangeValue={handleChangeValue} /&gt;
      &lt;p&gt;ChildInput 의 value: {value}&lt;/p&gt;
    &lt;/div&gt;
  );
}</code></pre><p><strong>하위 컴포넌트</strong></p>
<pre><code>function ChildInput(props){
  const handleChange = (event) =&gt; {
    props.onChangeValue(event.target.value);
    // props.onChangeValue === 상위 컴포넌트의 handleChangeValue
  }
  return (
    &lt;div&gt;
      &lt;input type=&quot;text&quot; value={props.value} onChange={handleChange} /&gt;
    &lt;/div&gt;
  );
}</code></pre><p><strong>결과</strong>
<img src="https://velog.velcdn.com/images/_mak_______/post/86a16785-9c5f-4e8b-a246-cb7d8699d3a4/image.png" alt=""></p>
<p>위 예제를 보면 input에 &quot;First Value&quot;를 표시하는 데에 아래의 순서를 따르고 있다.</p>
<blockquote>
<ol>
<li><strong>상위 컴포넌트에서 state 최초 선언.</strong>
<em>const [value, setValue] = useState(&quot;First Value&quot;);</em><br><br></li>
<li>하위 컴포넌트에서 상위 컴포넌트의 state를 props로 받아와
_&lt; ChildInput <strong>value={value}</strong> onChangeValue={handleChangeValue} /&gt;_<br><br></li>
<li>하위 컴포넌트 내부에서 props로 받아온 state를 사용하여
_&lt; input type=&quot;text&quot; <strong>value={props.value}</strong> onChange={handleChange} /&gt;_<br><br></li>
<li>하위 컴포넌트의 input에 &quot;First Value&quot;를 표시.</li>
</ol>
</blockquote>
<p>그리고 value의 state를 변경하는 데에는 아래의 순서를 따르고 있다.</p>
<blockquote>
<ol>
<li>하위 컴포넌트에서 상위 컴포넌트의 함수를 props로 받아와
_&lt; ChildInput value={value} <strong>onChangeValue={handleChangeValue}</strong> /&gt;_<br><br></li>
<li>하위 컴포넌트 내부에서 props로 받아온 함수를 사용하여 input의 value를 넘기고
<em>const handleChange = (event) =&gt; { <strong>props.onChangeValue(event.target.value)</strong>; }</em><br><br></li>
<li>상위 컴포넌트의 value에 대입
<em>const handleChangeValue = (childStateValue) =&gt; { <strong>setValue(childStateValue);</strong> }</em></li>
</ol>
</blockquote>
<p>참고 <a href="https://ko.reactjs.org/docs/lifting-state-up.html">https://ko.reactjs.org/docs/lifting-state-up.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[폼(form)]]></title>
            <link>https://velog.io/@_mak_______/React-%ED%8F%BCform</link>
            <guid>https://velog.io/@_mak_______/React-%ED%8F%BCform</guid>
            <pubDate>Thu, 24 Nov 2022 05:53:28 GMT</pubDate>
            <description><![CDATA[<h1 id="제어-컴포넌트">제어 컴포넌트</h1>
<blockquote>
<p>✔ React에 의해 값이 제어되는 입력 폼 엘리먼트.
✔ 제어 컴포넌트의 값은 state, setState, useState 로 관리된다.
✔ &lt; input type=&quot;file&quot; &gt;은 값이 읽기 전용이므로 <a href="https://ko.reactjs.org/docs/uncontrolled-components.html#the-file-input-tag">비제어 컴포넌트</a>다.</p>
</blockquote>
<pre><code>function SignUp(props){
  const [name, setName] = useState(&quot;&quot;);
  const [gender, setGender] = useState(&quot;&quot;);
  const [intro, setIntro] = useState(&quot;&quot;);

  const handleChangeName = (event) =&gt; {
    setName(event.target.value);
  };

  const handleChangeGender = (event) =&gt; {
    setGender(event.target.value);
  };

  const handleChangeIntro = (event) =&gt; {
    setIntro(event.target.value);
  };

  const handleSubmit = (event) =&gt; {
    alert(`이름: ${name}, 성별: ${gender}, 소개: ${intro}`);
    event.preventDefault();
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;label&gt;
        이름: &lt;input type=&quot;text&quot; value={name} onChange={handleChangeName} /&gt;
      &lt;/label&gt;

      &lt;label&gt;
        성별: 
        &lt;select value={gender} onChange={handleChangeGender}&gt;
          &lt;option value=&quot;남자&quot;&gt;남자&lt;/option&gt;
          &lt;option value=&quot;여자&quot;&gt;여자&lt;/option&gt;
        &lt;/select&gt;
      &lt;/label&gt;

      &lt;label&gt;
        소개: &lt;textarea value={intro} onChange={handleChangeIntro}&gt;&lt;/textarea&gt;
      &lt;/label&gt;

      &lt;button type=&quot;submit&quot;&gt;제출&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre><p>&lt; input type=&quot;text&quot; &gt;, &lt; textarea &gt;, &lt; select &gt; 태그들을 제어 컴포넌트로 만드는 방식은 모두 비슷하다. 모두 value라는 attribute를 통해서 값을 전달하고 onChange에서 setValue() 함수를 사용하여 값을 업데이트 한다.</p>
<h1 id="비제어-컴포넌트">비제어 컴포넌트</h1>
<p>대부분 경우에 폼을 구현하는데 제어 컴포넌트를 사용하는 것이 좋다. 모든 state 업데이트에 대한 이벤트 핸들러를 작성하는 대신 비제어 컴포넌트를 만들려면 ref를 사용하여 DOM에서 폼 값을 가져올 수 있다.</p>
<pre><code>function Profile(props) {
  const nameInput = useRef();
  const fileInput = useRef();

  const handleSubmit = (event) =&gt; {
    alert(`이름: ${nameInput.current.value}, 프로필 사진: ${fileInput.current.files[0].name}`);
    event.preventDefault();
  }

  return(
    &lt;form onSubmit={handleSubmit}&gt;
      &lt;label&gt;
        이름: &lt;input type=&quot;text&quot; ref={nameInput} /&gt;
      &lt;/label&gt;

      &lt;label&gt;
        프로필 사진: &lt;input type=&quot;file&quot; ref={fileInput} /&gt;
      &lt;/label&gt;

      &lt;button type=&quot;submit&quot;&gt;제출&lt;/button&gt;
    &lt;/form&gt;
  );
}</code></pre><blockquote>
<p>유효성 검사, 방문한 필드 추적 및 폼 제출 처리와 같은 완벽한 해결을 원한다면 <a href="https://formik.org/">Formik</a>이 대중적인 선택 중 하나.</p>
</blockquote>
<p>참고 <a href="https://ko.reactjs.org/docs/forms.html">https://ko.reactjs.org/docs/forms.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[리스트와 키(key)]]></title>
            <link>https://velog.io/@_mak_______/%EB%A6%AC%EC%8A%A4%ED%8A%B8%EC%99%80-%ED%82%A4key</link>
            <guid>https://velog.io/@_mak_______/%EB%A6%AC%EC%8A%A4%ED%8A%B8%EC%99%80-%ED%82%A4key</guid>
            <pubDate>Thu, 24 Nov 2022 02:04:19 GMT</pubDate>
            <description><![CDATA[<h1 id="기본-리스트-컴포넌트">기본 리스트 컴포넌트</h1>
<pre><code>function NumberList(props) {
  const numbers = [1, 2, 3, 4, 5];
  const listItems = numbers.map((number) =&gt;
    &lt;li&gt;{number}&lt;/li&gt;
  );
  return (
    &lt;ul&gt;{listItems}&lt;/ul&gt;
  );
}</code></pre><p>이 코드를 실행하면 리스트의 각 항목에 key를 넣어야 한다는 경고가 표시된다.</p>
<h1 id="key">Key</h1>
<blockquote>
<p>✔ 리스트에서 아이템을 구분하기 위한 고유한 문자열.
✔ 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.
✔ 배열 내부의 엘리먼트에 지정.
✔ 같은 리스트에 있는 엘리먼트 사이에서만 고유한 값이면 된다.
✔ 대부분 ID를 key로 사용한다.
✔ ID가 없다면 항목의 인덱스를 key로 사용할 수 있다.</p>
</blockquote>
<pre><code>const todoItems = todos.map((todo) =&gt;
  &lt;li key={todo.id}&gt;
    {todo.text}
  &lt;/li&gt;
);

const todoItems = todos.map((todo, index) =&gt;
  // 고유한 ID가 없을 경우에만 사용
  &lt;li key={index}&gt;
    {todo.text}
  &lt;/li&gt;
);</code></pre><p>li 를 ListItem 이라는 컴포넌트로 추출한 경우 ListItem 안에 있는 li 가 아니라 ListItem 컴포넌트가 key를 가져야 한다.</p>
<pre><code>function ListItem(props) {
  // 여기에는 key를 지정할 필요가 없다.
  return &lt;li&gt;{props.value}&lt;/li&gt;;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =&gt;
    // 배열 안에 key를 지정해야 한다.
    &lt;ListItem key={number.toString()} value={number} /&gt;
  );
  return (
    &lt;ul&gt;
      {listItems}
    &lt;/ul&gt;
  );
}</code></pre><p>컴포넌트에서 key와 동일한 값이 필요하면 다른 이름의 prop으로 명시적으로 전달해야 한다.
아래 예시에서 Post 컴포넌트는 props.id를 읽을 수 있지만 <strong>props.key는 읽을 수 없다.</strong></p>
<pre><code>const content = posts.map((post) =&gt;
  &lt;Post
    key={post.id}
    id={post.id}
    title={post.title} /&gt;
);</code></pre><p>JSX를 사용하면 중괄호 안에 모든 표현식을 포함 시킬 수 있으므로 <strong>map() 함수의 결과를 인라인으로 처리할 수 있다.</strong></p>
<pre><code>function NumberList(props) {
  const numbers = props.numbers;
  return (
    &lt;ul&gt;
      {numbers.map((number) =&gt;
        &lt;ListItem key={number.toString()}
                  value={number} /&gt;
      )}
    &lt;/ul&gt;
  );
}</code></pre><p>이 방식을 사용하면 코드가 더 깔끔해 지지만, 이 방식을 남발하는 것은 좋지 않다. JavaScript와 마찬가지로 가독성을 위해 변수로 추출해야 할지 아니면 인라인으로 넣을지는 개발자가 직접 판단해야 한다.
<strong>map() 함수가 너무 중첩된다면 컴포넌트로 추출 하는 것이 좋다.</strong></p>
<p>참고 <a href="https://ko.reactjs.org/docs/lists-and-keys.html">https://ko.reactjs.org/docs/lists-and-keys.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[조건부 렌더링]]></title>
            <link>https://velog.io/@_mak_______/%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@_mak_______/%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Thu, 24 Nov 2022 00:29:13 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>✔ React에서 조건부 렌더링은 JavaScript에서의 조건 처리와 같이 동작한다.
 ✔ if 나 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">조건부 연산자</a> 와 같은 JavaScript 연산자를 현재 상태를 나타내는 엘리먼트를 만드는 데에 사용.</p>
</blockquote>
<pre><code>function UserGreeting(props) {
  return &lt;h1&gt;Welcome back!&lt;/h1&gt;;
}

function GuestGreeting(props) {
  return &lt;h1&gt;Please sign up.&lt;/h1&gt;;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return &lt;UserGreeting /&gt;;
  }
  return &lt;GuestGreeting /&gt;;
}</code></pre><p>위에 나오는 Greeting 컴포넌트는 isLoggedIn이라는 변수의 값이 true에 해당되는 값(<a href="https://developer.mozilla.org/ko/docs/Glossary/Truthy">Truthy</a>)이면 UserGreeting 컴포넌트를 리턴하고, 그렇지 않으면(<a href="https://developer.mozilla.org/ko/docs/Glossary/Falsy">Falsy</a>) GuestGreeting 컴포넌트를 리턴한다. 이처럼 조건에 따라 렌더링의 결과가 달라지도록 하는 것을 조건부 렌더링이라고 한다.</p>
<h2 id="엘리먼트-변수">엘리먼트 변수</h2>
<blockquote>
<p>✔ 컴포넌트를 변수처럼 다룬다.</p>
</blockquote>
<pre><code>function LoginButton(props) {
  return (
    &lt;button onClick={props.onClick}&gt;Login&lt;/button&gt;
  );
}

function LogoutButton(props) {
  return (
    &lt;button onClick={props.onClick}&gt;Logout&lt;/button&gt;
  );
}

function LoginControl(props) {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const handleLoginClick = () =&gt; {
      setIsLoggedIn(true);
  }

  const handleLogoutClick = () =&gt; {
      setIsLoggedIn(false);
  }

  let button;
  if (isLoggedIn) {
      button = &lt;LogoutButton onClick={handleLogoutClick} /&gt;;
  } else {
    button = &lt;LoginButton onClick={handleLoginClick} /&gt;;
  }

  return (
      &lt;div&gt;
      &lt;Greeting isLoggedIn={isLoggedIn} /&gt;
      {button}
    &lt;/div&gt;
  );
}</code></pre><p>위 코드에선 isLoggedIn 값에 따라 button이라는 변수에 컴포넌트를 대입하는 것을 볼 수 있다. 그리고 이렇게 컴포넌트가 대입된 변수를 return에 넣어 실제로 컴포넌트가 렌더링이 되도록 만들고 있다. 이처럼 엘리먼트를 변수처럼 저장해서 사용하는 방법을 엘리먼트 변수라고 한다.</p>
<p>변수를 선언하고 if를 사용해서 조건부로 렌더링 하는 것은 좋은 방법이지만 더 짧은 구문을 사용할 수도 있다.</p>
<h2 id="인라인-조건">인라인 조건</h2>
<h3 id="and-연산">AND 연산</h3>
<blockquote>
<p>true &amp;&amp; expression -&gt; expression
false &amp;&amp; expression -&gt; false</p>
</blockquote>
<pre><code>function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    &lt;div&gt;
      &lt;h1&gt;Hello!&lt;/h1&gt;
      {unreadMessages.length &gt; 0 &amp;&amp;
        &lt;h2&gt;
          You have {unreadMessages.length} unread messages.
        &lt;/h2&gt;
      }
    &lt;/div&gt;
  );
}</code></pre><p>JavaScript의 논리 연산자 &amp;&amp;를 사용하면 쉽게 엘리먼트를 조건부로 넣을 수 있다. JavaScript에서 true &amp;&amp; expression은 항상 expression으로 평가되고 false &amp;&amp; expression은 항상 false로 평가된다.</p>
<p>falsy 표현식을 반환하면 여전히 &amp;&amp; 뒤에 있는 표현식은 건너뛰지만 falsy 표현식이 반환된다는 것에 주의해야 한다. 아래 코드의 결과는 화면에 아무것도 안 나오는 것이 아니라 count의 값인 0이 들어가서 &quot;0&quot; 이 출력된다.</p>
<pre><code>function Counter(props) {
  const count = 0;
  return (
    &lt;div&gt;
      {count &amp;&amp; &lt;h1&gt;카운트: {count}&lt;/h1&gt;}
    &lt;/div&gt;
  );
}</code></pre><h3 id="삼항-연산자">삼항 연산자</h3>
<blockquote>
<p>condition ? true : false</p>
</blockquote>
<pre><code>function LoginControl(props) {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  const handleLoginClick = () =&gt; {
      setIsLoggedIn(true);
  }

  const handleLogoutClick = () =&gt; {
      setIsLoggedIn(false);
  }

  return (
      &lt;div&gt;
      &lt;Greeting isLoggedIn={isLoggedIn} /&gt;
      {isLoggedIn
          ? &lt;LogoutButton onClick={handleLogoutClick} /&gt;
        : &lt;LoginButton onClick={handleLoginClick} /&gt;
      }
    &lt;/div&gt;
  );
}</code></pre><h2 id="null로-컴포넌트-렌더링-막기">null로 컴포넌트 렌더링 막기</h2>
<p>컴포넌트 자체를 숨기고 싶을 때가 있다. 이때는 렌더링 결과를 출력하는 대신 null을 반환한다.
아래의 예시에서는 WarningBanner가 props.warn의 값에 의해서 렌더링된다. warn이 false라면 컴포넌트는 렌더링 되지 않는다.</p>
<pre><code>function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    &lt;div className=&quot;warning&quot;&gt;경고!&lt;/div&gt;
  );
}

function Page(props) {
  const [showWarning, setShowWarning] = useState(false);

  const handleToggleClick = () =&gt; {
      setShowWarning(pervShowWarning =&gt; !prevShowWarning);
  }

  return (
      &lt;div&gt;
      &lt;WarningBanner warning={showWarning} /&gt;
      &lt;button onClick={handleToggleClick}&gt;
          {showWarning ? &quot;감추기&quot; : &quot;보이기&quot;}
      &lt;/button&gt;
    &lt;/div&gt;
  )
}</code></pre><p>참고 <a href="https://ko.reactjs.org/docs/conditional-rendering.html">https://ko.reactjs.org/docs/conditional-rendering.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Event handler(Event listener)]]></title>
            <link>https://velog.io/@_mak_______/React-Event-handlerEvent-listener</link>
            <guid>https://velog.io/@_mak_______/React-Event-handlerEvent-listener</guid>
            <pubDate>Wed, 23 Nov 2022 23:05:55 GMT</pubDate>
            <description><![CDATA[<h1 id="react의-이벤트-핸들러">React의 이벤트 핸들러</h1>
<blockquote>
<p>✔ 이벤트가 발생했을 때 해당 이벤트를 처리하는 함수
✔ 이벤트 리스너라고 부르기도 함</p>
</blockquote>
<h2 id="함수-컴포넌트에서의-사용">함수 컴포넌트에서의 사용</h2>
<pre><code>import { useState } from &quot;react&quot;;

function ConfirmButton(){
  const [isConfirmed, setIsConfirmed] = useState(false);

  // 방법 1. 함수 안의 함수로 작성
  function handleConfirm(){
    setIsConfirmed(!isConfirmed);
  } 

  // 방법 2. Arrow function으로 작성
  const handleConfirm = () =&gt; {
    setIsConfirmed(!isConfirmed);
  }

  return (
    &lt;button onClick={handleConfirm} disabled={isConfirmed}&gt;
      {isConfirmed ? &quot;확인됨&quot; : &quot;확인하기&quot;}
    &lt;/button&gt;
  );
}

export default ConfirmButton;</code></pre><h2 id="클래스-컴포넌트에서의-사용참고만-하자">클래스 컴포넌트에서의 사용(참고만 하자)</h2>
<pre><code>import React from &quot;react&quot;;

class ConfirmButtonClass extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      isConfirmed: false,
    };

    this.handleConfirm = this.handleConfirm.bind(this);
  }

  handleConfirm() {
    this.setState({
      isConfirmed: !this.isConfirmed,
    });
  }

  render() {
    return (
      &lt;button onClick={this.handleConfirm} disabled={this.state.isConfirmed}&gt;
        {this.state.isConfirmed ? &quot;확인됨&quot; : &quot;확인하기&quot;}
      &lt;/button&gt;
    );
  }
}

export default ConfirmButtonClass;</code></pre><p>클래스 컴포넌트에서는 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind</a>를 꼭 해주어야 한다. 기본적으로 Javascript에서 클래스 함수는 바운드가 되지 않기 때문이다. bind를 하지 않으면 this가 함수 바깥의 <a href="https://developer.mozilla.org/ko/docs/Web/API/AudioWorkletGlobalScope">글로벌 스코프(전역 범위)</a>에서 호출 되어 this.handleConfirm이 undefined가 된다.</p>
<p>만약 bind가 번거롭다면 아래처럼 클래스 필드 문법을 사용할 수 있다.</p>
<pre><code>import React from &quot;react&quot;;

class ConfirmButtonClass extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      isConfirmed: false,
    };
  }

  handleConfirm = () =&gt; {
    this.setState({
      isConfirmed: !this.isConfirmed,
    });
  }

  render() {
    return (
      &lt;button onClick={this.handleConfirm} disabled={this.state.isConfirmed}&gt;
        {this.state.isConfirmed ? &quot;확인됨&quot; : &quot;확인하기&quot;}
      &lt;/button&gt;
    );
  }
}

export default ConfirmButtonClass;</code></pre><p>혹은 이벤트 핸들러를 넣는 곳에 Arrow function을 사용할 수도 있다.</p>
<pre><code>import React from &quot;react&quot;;

class ConfirmButtonClass extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      isConfirmed: false,
    };
  }

  handleConfirm() {
    this.setState({
      isConfirmed: !this.isConfirmed,
    });
  }

  render() {
    return (
      &lt;button onClick={() =&gt; this.handleConfirm()} disabled={this.state.isConfirmed}&gt;
        {this.state.isConfirmed ? &quot;확인됨&quot; : &quot;확인하기&quot;}
      &lt;/button&gt;
    );
  }
}

export default ConfirmButtonClass;</code></pre><h1 id="arguments매개변수-전달하기">Arguments(매개변수) 전달하기</h1>
<blockquote>
<p>✔ 함수에 전달할 데이터</p>
</blockquote>
<h2 id="함수-컴포넌트에서의-사용-1">함수 컴포넌트에서의 사용</h2>
<pre><code>function MyButton(props) {
    const handleDelete = (id, event) =&gt; { // id, event가 매개변수
        console.log(id, event.target);
    };

    return (
        &lt;button conClick={(event) =&gt; handleDelete(1, event)}&gt;삭제하기&lt;/button&gt;
    );
}</code></pre><h2 id="클래스-컴포넌트에서의-사용">클래스 컴포넌트에서의 사용</h2>
<pre><code>&lt;button onClick={(event) =&gt; this.deleteItem(id, event)}&gt;삭제하기&lt;/button&gt;
&lt;button onClick={this.deleteItem.bind(this, id)}&gt;삭제하기&lt;/button&gt;</code></pre><p>참고 <a href="https://ko.reactjs.org/docs/handling-events.html">https://ko.reactjs.org/docs/handling-events.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[useMemo()]]></title>
            <link>https://velog.io/@_mak_______/useMemo</link>
            <guid>https://velog.io/@_mak_______/useMemo</guid>
            <pubDate>Mon, 14 Nov 2022 08:52:01 GMT</pubDate>
            <description><![CDATA[<h1 id="usememo">useMemo()</h1>
<blockquote>
<p>✔ <a href="https://www.freecodecamp.org/news/memoization-in-javascript-and-react/">Memoized value</a>를 리턴하는 훅.
✔ 연산량이 높은 작업이 매번 렌더링될 때마다 반복되는 것을 피하기 위해 사용.
✔ 렌더링이 일어나는 동안 실행.
✔ const memoizedValue = useMemo(값 생성 함수, 의존성 배열);
✔ 의존성 배열에 들어있는 변수가 변했을 경우에만 새로 값 생성 함수를 호출하여 결괏값을 반환.
✔ 의존성 배열이 없을 경우 렌더링이 일어날 때마다 매번 값 생성 함수가 실행되므로 useMemo()를 사용하는 의미가 없음.</p>
</blockquote>
<h2 id="example">Example</h2>
<pre><code>import { useMemo, useState } from &quot;react&quot;;

function ExUseMemo() {
  const [count, setCount] = useState(0);
  const [todos, setTodos] = useState([]);

  const increment = () =&gt; {
    setCount(c =&gt; c + 1);
  };

  const addTodo = () =&gt; {
    setTodos(t =&gt; [...t, &quot;New Todo&quot;]);
  };

  const expensiveCalculation = (num) =&gt; {
    console.log(&quot;Calculating...&quot;);
    for (let i = 0; i &lt; 1000000; i++) {
      num += 1;
    }
    return num;
  };

  const calculation = expensiveCalculation(count);

  return (
    &lt;div&gt;
      &lt;div&gt;
        &lt;h2&gt;My Todos&lt;/h2&gt;
        {todos.map((todo, index) =&gt; {
          return &lt;p key={index}&gt;{todo}&lt;/p&gt;;
        })}
        &lt;button onClick={addTodo}&gt;Add Todo&lt;/button&gt;
      &lt;/div&gt;
      &lt;hr /&gt;
      &lt;div&gt;
        Count: {count}
        &lt;button onClick={increment}&gt;+&lt;/button&gt;
        &lt;h2&gt;Expensive Calculation&lt;/h2&gt;
        {calculation}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default ExUseMemo;</code></pre><p>출처 <a href="https://www.w3schools.com/react/react_usememo.asp">W3Schools</a></p>
<p>위 예제는 &#39;Add Todo&#39; 를 클릭할 때 마다 리렌더링 되면서 count 값이 변하지 않음에도 콘솔에 &quot;Calculating...&quot; 이 출력되고 계산량이 큰 for문도 매번 의미없는 작업을 하게 된다. 이를 방지하기 위해 useMemo()를 활용한다.</p>
<pre><code>const calculation = expensiveCalculation(count);</code></pre><p>해당 부분을 아래와 같이 변경한다.</p>
<pre><code>const calculation = useMemo(() =&gt; expensiveCalculation(count), [count]);</code></pre><p>calculation은 이제 렌더링이 될 때 마다 의존성 배열의 count를 이전 count 값과 비교한다. count가 변경되지 않았으면 계산을 거치지 않고 기억했던 이전 값을 그대로 반환하고, 변경이 되었을 땐 expensiveCalculation() 함수를 재계산하여 count의 값을 반환한다. &#39;Add Todo&#39; 를 클릭해도 콘솔에는 &quot;Calculating...&quot; 이 출력되지 않으며, 의미없는 for문 작업도 하지 않는다.</p>
<h2 id="어느-곳에-사용해야하나">어느 곳에 사용해야하나</h2>
<blockquote>
<p>✔ 위의 예제처럼 식의 <strong>부하가 크고</strong>, <strong>자주 바뀌지 않는 값</strong>에 사용하는 것이 유용.
✔ Chrome에 React Developer Tools 프로파일러를 참고하여 시간이 오래 걸리는 코드를 찾고 필요한 경우 사용하는 것을 추천.</p>
</blockquote>
<p>참고 <a href="https://beta.reactjs.org/apis/react/useMemo">https://beta.reactjs.org/apis/react/useMemo</a></p>
]]></description>
        </item>
    </channel>
</rss>