<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Dev On The Coffee</title>
    <link>https://dev-on-coffee.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 15 Apr 2026 08:00:45 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Lucian_Cho</managingEditor>
    <item>
      <title>[Lucian Log] 개발자 mindset에 대한 한 줄 생각</title>
      <link>https://dev-on-coffee.tistory.com/234</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발자로 살아갈 때 뿌리가 되어야 할 두 가지 mindset
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;공통적인 부분들을 포괄하는 학습 패러다임을 습득하여 학습 속도가 상승시키자!&lt;/li&gt;
&lt;li&gt;다른 사람들이 배운 것들을 인정하고 열린 마음으로 받아들이는 태도를 가지자! (다만, 스스로 지식을 잘 쌓아 정말 잘못된 것만은 분별하자)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Free Contents</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/234</guid>
      <comments>https://dev-on-coffee.tistory.com/234#entry234comment</comments>
      <pubDate>Thu, 26 Aug 2021 03:24:21 +0900</pubDate>
    </item>
    <item>
      <title>[Lucian Log] 개발 공부하며 느낀 한 줄 생각들</title>
      <link>https://dev-on-coffee.tistory.com/233</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;알고 있는 것과 내 말로 다시 풀어 설명하는 것은 다르다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;훌륭한 개발자는 디자이너, 기획자나 아무것도 모르는 Junior에게 잘 설명할 줄 아는 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;커뮤니케이션 능력을 갖춰야 한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;대부분이 사용하는 방식이 있더라도 그것이 무조건 정답은 아닐 것이다. &lt;br /&gt;개발에도 창의성의 영역이 있음 기억하자.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전부 다 기록하려 하지 말고, 내가 어려움을 겪었던 부분을 첫째 나를 위해, 둘째 다른 사람들을 위해 쓰자!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;외유내강! 개발에 대해 마음 속으로 자신감을 가지고, 새로운 것에 더 용감히 시도해보자. &lt;br /&gt;커뮤니케이션은 상대방에게 기분 나쁘지 않게 잘 할 수 있을 것 같다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;생각을 통해 나온 복붙이라면 거부감 가지지 말자! 괜찮다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;타자를 빠르게 가져가자! &lt;br /&gt;&lt;span&gt;단축키를 포함해 빠르게 이것저것 시도하는 손가락은&lt;/span&gt; 실력있는 개발자의 토대가 된다!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>Free Contents</category>
      <category>개발</category>
      <category>한 줄 생각</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/233</guid>
      <comments>https://dev-on-coffee.tistory.com/233#entry233comment</comments>
      <pubDate>Thu, 26 Aug 2021 03:20:25 +0900</pubDate>
    </item>
    <item>
      <title>[React] Advanced Tip</title>
      <link>https://dev-on-coffee.tistory.com/232</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Programming patterns&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 자주 사용되는 프로그래밍 패턴이 존재합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Scene 1 - Stateful components to stateless components&lt;br /&gt;&lt;br /&gt;Stateful component가 자신의 state setter 함수를 &lt;code&gt;props&lt;/code&gt;로 child component에 전달하면, child component의 어떠한 event에 의해 해당 함수가 호출되어 parent component의 state를 변경합니다. 그리고 parent component는 변경된 state를 &lt;code&gt;props&lt;/code&gt;로 또 다른 child component(=sibling component)에게 전달해 해당 child component에서 화면에 표시합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Scene 2 - Separating container components from presentational components&lt;br /&gt;&lt;br /&gt;State를 가지거나 calculation 등의 functional part를 담당하는 component는 container component로, 렌더링을 담당하는 component는 presentational component로 분리해야 합니다. 분리된 presentational component는 항상 container component에 의해서 렌더링되어야 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Style Name Syntax&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 JavaScript에서 style의 name은 hyphenated-lowercase로 이루어져 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;const styles = {
  'margin-top': '20px',
  'background-color': 'green'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에, 리액트는 style name이 camelCase로 이루어져 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;const styles = {
  marginTop: '20px',
  backgroundColor: 'green'
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Style Value Syntax&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 JavaScript에서는 &lt;code&gt;&quot;450px&quot;&lt;/code&gt;, &lt;code&gt;&quot;20%&quot;&lt;/code&gt; 처럼 숫자와 단위를 함께 적어 string 형태로 style value를 사용해야 합니다. 하지만, 리액트에서는 &lt;code&gt;px&lt;/code&gt;에 한해서 생략이 가능하고, 이 경우 숫자도 string이 아닌 number 그대로 사용하는 것이 가능합니다. 물론 기존의 string 형태도 그대로 사용 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;{ fontSize: 30 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 다른 단위를 사용하고 싶을 때는 기존의 string 형태로 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;{ fontSize: &quot;2em&quot; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;propTypes&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;propTypes&lt;/code&gt;는 리액트에서 자주 사용되는 특징입니다. Prop이 전달될 것이 예상되는 component에 올바른 prop이 전달되었는지에 대한 validation을 도와주고, documentation을 통해 component의 상황을 한눈에 파악할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;import PropTypes from 'prop-types';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;propTypes&lt;/code&gt;를 사용하기 위해선 &lt;code&gt;'prop-types'&lt;/code&gt; 라이브러리를 import해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import React from 'react';
import PropTypes from 'prop-types';

export class MessageDisplayer extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;{this.props.message}&amp;lt;/h1&amp;gt;;
  }
}

// This propTypes object should have
// one property for each expected prop:
MessageDisplayer.propTypes = {
  message: PropTypes.string
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 미리 정의된 component에 위와 같이 property를 추가하는 방식으로 &lt;code&gt;propTypes&lt;/code&gt;를 정의할 수 있습니다. 이 때, &lt;code&gt;propTypes&lt;/code&gt;의 value는 object 형태여야 함을 유의합니다. 그리고 해당 object의 각각의 property는 component에 전달될 것이 기대되는 prop의 이름으로 설정합니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;Runner.propTypes = {
  message:   PropTypes.string.isRequired,
  style:     PropTypes.object.isRequired,
  isMetric:  PropTypes.bool.isRequired,
  miles:     PropTypes.number.isRequired,
  milesToKM: PropTypes.func.isRequired,
  races:     PropTypes.array.isRequired
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;PropTypes&lt;/code&gt;를 통해 설정할 수 있는 data type의 이름은 위와 같습니다. &lt;code&gt;isRequired&lt;/code&gt;의 경우, prop이 잘 전달되는지 확인해서 만일 잘 전달되지 않으면 console에 warning을 띄어주는 역할을 합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const Example = (props) =&amp;gt; {
  return &amp;lt;h1&amp;gt;{props.message}&amp;lt;/h1&amp;gt;;
}
 
Example.propTypes = {
  message: PropTypes.string.isRequired
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 function component에 &lt;code&gt;propTypes&lt;/code&gt;를 추가하고 싶다면, 위와 같이 function component 자체의 property로 &lt;code&gt;propTypes&lt;/code&gt;를 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;React forms&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';

export class Input extends React.Component {
  constructor(props) {
    super(props);
    this.state = { userInput: '' };

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

  handleUserInput(e) {
    this.setState({userInput: e.target.value});
  }

  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;input type=&quot;text&quot; value={this.state.userInput} onChange={this.handleUserInput} /&amp;gt;
        &amp;lt;h1&amp;gt;{this.state.userInput}&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}

ReactDOM.render(
	&amp;lt;Input /&amp;gt;,
	document.getElementById('app')
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 form은 유저가 input field에 계속 타이핑하더라도 submit 버튼을 누르기전까지는 서버에서 그 사실을 알지 못합니다. 즉, submit 이전까지 프론트가 알고 있는 input 정보와 서버가 알고 있는 input 정보 사이에 불일치가 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이러한 불일치는 웹사이트의 third part에서 해당 정보를 필요로 할 때, 프론트냐 서버냐에 따라 다른 결과를 내어 문제가 발생할 수 있습니다. 이를 해결하기 위해, 리액트 form은 모든 new character와 deletion에 대한 프론트 및 서버의 동기화를 지원하여 application의 모든 요소가 일관성 있게 동작하도록 합니다. 특히, 일반적인 &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; tag를 굳이 사용하지 않고 위 코드처럼 &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; tag만으로 이를 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Uncontrolled vs Controlled component&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Uncontrolled component란 스스로 state를 가지고 그 값을 기억하는 component를 말합니다. 반면에 controlled component는 스스로 state를 가지지 않고 다른 component에 의해 관리되어지는 component를 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에는 주로 controlled component가 많고 이러한 component는 스스로에 대한 정보를 &lt;code&gt;props&lt;/code&gt;를 통해 얻게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>advanced tips</category>
      <category>JS</category>
      <category>react</category>
      <category>Tips</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/232</guid>
      <comments>https://dev-on-coffee.tistory.com/232#entry232comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:55:45 +0900</pubDate>
    </item>
    <item>
      <title>[React] Hook</title>
      <link>https://dev-on-coffee.tistory.com/231</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Functional components&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 JavaScript의 클래스를 사용해서 정의한 리액트의 component들은 함수를 사용해서 정의할 수도 있습니다. 이를 function component라고 합니다. Function component는 간단하고 직관적이라는 장점이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;// A component class written in the usual way:
class MyComponentClass extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Hello world&amp;lt;/h1&amp;gt;;
  }
}

// The same component class, written as a stateless functional component:
const MyComponentClass = () =&amp;gt; {
  return &amp;lt;h1&amp;gt;Hello world&amp;lt;/h1&amp;gt;;
}

// Works the same either way:
ReactDOM.render(
	&amp;lt;MyComponentClass /&amp;gt;,
	document.getElementById('app')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function component는 위와 같이 함수 형태로 작성하며, &lt;code&gt;render()&lt;/code&gt; 메서드를 사용하지 않고 JSX expression을 바로 리턴하는 방식으로 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function component는 &lt;code&gt;props&lt;/code&gt; 역시 전달받을 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function WelshCorgi (props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;{props.prompt}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
 
ReactDOM.render(
  &amp;lt;WelshCorgi feed=&quot;High quality dog feed&quot; /&amp;gt;,
  document.getElementById('app');
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;props&lt;/code&gt;는 parameter로 정의해 전달받고, &lt;code&gt;props.propertyName&lt;/code&gt; 형식으로 접근합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Hook&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hook은 function component에서 component의 state와 이후의 렌더링 관련 side effects를 관리하도록 도와주는 함수들입니다. 클래스에서는 작동되지 않지만, function component에서 lifecycle적인 특징들도 관리할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;State hook - &lt;code&gt;useState&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
 
function Toggle() {
  const [toggle, setToggle] = useState('off');
 
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;The toggle is {toggle}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setToggle(&quot;On&quot;)}&amp;gt;On&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setToggle(&quot;Off&quot;)}&amp;gt;Off&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;useState&lt;/code&gt;는 리액트 라이브러리에서 제공하는 JavaScript 함수로, 호출 시 두 가지 value가 담긴 array를 리턴합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;current state&lt;/i&gt; - the current value of this state&lt;/li&gt;
&lt;li&gt;&lt;i&gt;state setter&lt;/i&gt; - a function that we can use to update the value of this state&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;State에 대한 초깃값은 &lt;code&gt;useState&lt;/code&gt;에 인자로 넣어진 값으로 설정할 수 있습니다. 초깃값이 중요하지 않은 경우, 인자를 넣지 않고 초깃값을 &lt;code&gt;undefined&lt;/code&gt; 상태로 두어도 상관없으나 &lt;code&gt;null&lt;/code&gt; 값이라도 넘겨주는 것이 가독성을 높이는 방법이 될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;useState&lt;/code&gt;를 사용해서 임의의 value를 인자로 state setter 함수를 호출하면, 현재 state를 새로운 state로 update할 수 있습니다. 특히 state setter 함수가 호출되면 리액트는 자동으로 해당 component를 다시 렌더링하므로 변경한 새로운 state value가 바로 반영됩니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from 'react';
 
export default function Counter() {
  const [count, setCount] = useState(0);
 
  const increment = () =&amp;gt; setCount(prevCount =&amp;gt; prevCount + 1);
 
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;Wow, you've clicked that button: {count} times&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={increment}&amp;gt;Click here!&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 기존의 state를 활용해 계산한 값으로 state를 update하고 싶다면, state setter 함수에 콜백 함수를 인자로 전달하면 됩니다. 위와 같이 기존 state &lt;code&gt;count&lt;/code&gt;를 활용해 &lt;code&gt;prevCount + 1&lt;/code&gt; 값으로 state를 update하고 싶다면, &lt;code&gt;setCount(prevCount =&amp;gt; prevCount + 1)&lt;/code&gt;처럼 콜백 함수를 state setter 함수의 인자로 넣어줍니다. 특정한 상황에서는 &lt;code&gt;setCount(count +1)&lt;/code&gt; 같이 바로 값을 update할 수도 있지만, 콜백 함수를 사용하는 방법이 모든 상황에서 더 안전하다는 점을 유의합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;
 
const options = [&quot;Bell Pepper&quot;, &quot;Sausage&quot;, &quot;Pepperoni&quot;, &quot;Pineapple&quot;];
 
export default function PersonalPizza() {
  const [selected, setSelected] = useState([]);
 
  const toggleTopping = ({target}) =&amp;gt; {
    const clickedTopping = target.value;
    setSelected((prev) =&amp;gt; {
     // check if clicked topping is already selected
      if (prev.includes(clickedTopping)) {
        // filter the clicked topping out of state
        return prev.filter(t =&amp;gt; t !== clickedTopping);
      } else {
        // add the clicked topping to our state
        return [clickedTopping, ...prev];
      }
    });
  };
 
  return (
    &amp;lt;div&amp;gt;
      {options.map(option =&amp;gt; (
        &amp;lt;button value={option} onClick={toggleTopping} key={option}&amp;gt;
          {selected.includes(option) ? &quot;Remove &quot; : &quot;Add &quot;}
          {option}
        &amp;lt;/button&amp;gt;
      ))}
      &amp;lt;p&amp;gt;Order a {selected.join(&quot;, &quot;)} pizza&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 state의 값이 Array 타입인 경우, state를 update할 때 이전 state의 Array를 그대로 변경하지말고 새로운 Array로 변경 내역을 copy해서 state에 할당해야 함을 유의합니다. 위에서도 &lt;code&gt;return prev.filter(t =&amp;gt; t !== clickedTopping);&lt;/code&gt; 혹은 &lt;code&gt;return [clickedTopping, ...prev];&lt;/code&gt;으로 새로운 Array를 만들어 리턴합니다.&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;export default function Login() {
  const [formState, setFormState] = useState({});
 
  const handleChange = ({ target }) =&amp;gt; {
    const { name, value } = target;
    setFormState((prev) =&amp;gt; ({
      ...prev,
      [name]: value
    }));
  };
 
  return (
    &amp;lt;form&amp;gt;
      &amp;lt;input
        value={formState.firstName}
        onChange={handleChange}
        name=&quot;firstName&quot;
        type=&quot;text&quot;
      /&amp;gt;
      &amp;lt;input
        value={formState.password}
        onChange={handleChange}
        type=&quot;password&quot;
        name=&quot;password&quot;
      /&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;State의 타입이 Object인 경우에도 update할 state 값은 변경된 내역을 새로 copy한 Object가 되어야 합니다. 또 Object를 arrow function에서 return할 때는 &lt;code&gt;{}&lt;/code&gt;가 겹치는 문제가 발생할 수 있기 때문에, 반환할 Object를 &lt;code&gt;()&lt;/code&gt;로 감싸줄 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Separate Hooks for Separate States&lt;/h2&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;function Subject() {
  const [state, setState] = useState({
    currentGrade: 'B',
    classmates: ['Hasan', 'Sam', 'Emma'],
    classDetails: {topic: 'Math', teacher: 'Ms. Barry', room: 201};
    exams: [{unit: 1, score: 91}, {unit: 2, score: 88}]);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;State와 같은 dynamic data를 다루기 위해서는 state 변수마다 각각 hook을 지정해 관리하는 것이 편합니다. 위와 같이 하나의 복잡한 Object를 state로 하여 하나의 hook으로 관리한다면, 복잡한 state들을 각각 copy할 때 매우 불편해집니다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function Subject() {
  const [currentGrade, setGrade] = useState('B');
  const [classmates, setClassmates] = useState(['Hasan', 'Sam', 'Emma']);
  const [classDetails, setClassDetails] = useState({topic: 'Math', teacher: 'Ms. Barry', room: 201});
  const [exams, setExams] = useState([{unit: 1, score: 91}, {unit: 2, score: 88}]);
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 위와 같이 state 변수마다 hook을 만들어 관리한다면 훨씬 간단하고 쉽게 state를 관리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Effect hook&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Effect hook은 렌더링 이후의 side effects를 관리하는 함수입니다. fetch API를 통해 백엔드로부터 데이터를 받아오거나 DOM을 읽고 변화를 주는 등의 side effect를 발생시키는 작업들을 관리하며, 보통 다음 3가지 상황에서 사용합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Component가 DOM에 mount되어 렌더링될 때&lt;/li&gt;
&lt;li&gt;State 혹은 props가 변화하여 component가 다시 렌더링 될 때&lt;/li&gt;
&lt;li&gt;Component가 DOM에서 unmount되어 렌더링될 때&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Effect hook - &lt;code&gt;useEffect&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from 'react';
 
function PageTitle() {
  const [name, setName] = useState('');
 
  useEffect(() =&amp;gt; {
    document.title = `Hi, ${name}`;
  });
 
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;Use the input field below to rename this page!&amp;lt;/p&amp;gt;
      &amp;lt;input onChange={({target}) =&amp;gt; setName(target.value)} value={name} type='text' /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;useEffect&lt;/code&gt;는 component를 렌더링할 때마다 다른 함수를 호출하기 위해 사용합니다. 이로 인해, &lt;code&gt;useEffect&lt;/code&gt;는 첫 번째 인자로 렌더링 후 호출할 목적의 콜백 함수를 받습니다. 그리고 이러한 콜백 함수를 effect라고도 부릅니다. 예를 들어, 위 코드에서는 &lt;code&gt;() =&amp;gt; { document.title = name; }&lt;/code&gt;가 effect입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Effect는 현재 state에도 접근할 수 있습니다. 다만 component 렌더링이 일어난 다음 DOM이 update되면 그 후 effect가 호출되므로, state도 update가 완료된 상태에서 접근하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Clean Up Effects&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떠한 effect들은 메모리 누수를 피하기 위하여 항상 제거하는 작업을 동반해주어야 합니다. 예를 들어, effect를 사용해 직접 DOM 내의 element에 event listener를 추가하는 경우, 원하는 작업이 끝나면 해당 event listener를 반드시 다시 제거해주어야 합니다. 그렇지 않으면 렌더링될 때마다 호출되는 effect hook의 특성으로 인해, 이후 발생하는 수많은 렌더링 상황마다 event listener가 의도치 않게 끊임없이 추가되어 메모리가 터지는 상황이 생길 수 있습니다. 따라서 다음과 같이 &lt;code&gt;useEffect&lt;/code&gt;의 effect 내에서 event listener를 제거하는 함수를 반환하여, 추가했던 event listener를 제거해줍니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;useEffect(()=&amp;gt;{
  document.addEventListener('keydown', handleKeyPress);
  return () =&amp;gt; {
    document.removeEventListener('keydown', handleKeyPress);
  };
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Effect가 반환하는 함수는 &lt;code&gt;useEffect&lt;/code&gt;가 항상 clean up 함수로 간주하므로, 리액트는 effect 작업이 끝나면 자동적으로 이를 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dependency array&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Effect는 기본적으로 매 렌더링이 일어나는 상황마다 호출됩니다. 그러나 dependency array를 사용하면, effect를 원하는 때에만 호출하도록 설정할 수 있습니다. Dependency array는 &lt;code&gt;useEffect&lt;/code&gt;의 두 번째 인자로 넣는 array를 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 component가 mount되어 첫 번째 렌더링을 할 때만 effect hook을 호출하고 최종 렌더링에서 clean up하고 싶다면, 빈 array &lt;code&gt;[]&lt;/code&gt;를 &lt;code&gt;useEffect()&lt;/code&gt;의 두 번째 인자로 넣어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에, dependency array에 특정 변수를 요소로 넣는다면, 해당 변수의 값이 변할 때만 effect가 호출됩니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if the value stored by count changes&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Hook을 사용하는 규칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더욱 복잡한 React 앱에서 혼란을 피하기 위해, hook은 다음과 같은 규칙을 지키며 사용합시다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Hook을 항상 top level에서만 사용합시다.&lt;br /&gt;&lt;br /&gt;리액트는 function component 내에서 정의한 순서에 따라 hook과 함께 관리되는 data와 function들을 인식합니다. 따라서, conditions, loops, nested functions 안에서 hook을 사용하지 말아야 합니다.&lt;br /&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;if (userName !== '') {
  useEffect(() =&amp;gt; {
    localStorage.setItem('savedUserName', userName);
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;조건문을 쓰고 싶다면 위와 같이 쓰지 말고, 다음과 같이 effect 내에서 사용해 동일한 결과를 얻을 수 있습니다.&lt;br /&gt;
&lt;pre id=&quot;code_1629895834703&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  if (userName !== '') {
    localStorage.setItem('savedUserName', userName);
  }
});​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Hook은 react function component 내에서만 사용합시다.&lt;br /&gt;&lt;br /&gt;Function component이외에 hook을 사용할 수 있는 곳은 custom hook을 제외하고 존재하지 않습니다. Class component나 일반적인 JavaScript 함수 내에서 hook을 사용하지 맙시다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Separate Hooks for Separate States&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// Handle menuItems with one useEffect hook.
const [menuItems, setMenuItems] = useState(null);
useEffect(() =&amp;gt; {
  get('/menu').then((response) =&amp;gt; setMenuItems(response.data));
}, []);
 
// Handle position with a separate useEffect hook.
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() =&amp;gt; {
  const handleMove = (event) =&amp;gt;
    setPosition({ x: event.clientX, y: event.clientY });
  window.addEventListener('mousemove', handleMove);
  return () =&amp;gt; window.removeEventListener('mousemove', handleMove);
}, []);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Effect hook 역시 모든 로직을 한 곳에 모아두면 가독성이 떨어지고 복잡해집니다. 따라서 위와 같이 effect 마다 따로 hook을 만드는 것을 지향합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>Function Component</category>
      <category>Hook</category>
      <category>JS</category>
      <category>react</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>함수 컴포넌트</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/231</guid>
      <comments>https://dev-on-coffee.tistory.com/231#entry231comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:53:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] Component Lifecycle Methods</title>
      <link>https://dev-on-coffee.tistory.com/230</link>
      <description>&lt;h1&gt;Component lifecycle methods&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트의 수많은 component들은 각각 자신의 lifecycle을 가집니다. 보통 component의 lifecycle 다음과 같이 구성됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;Mounting&lt;/i&gt;, when the component is being initialized and put into the DOM for the first time&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Updating&lt;/i&gt;, when the component updates as a result of changed state or changed props&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Unmounting&lt;/i&gt;, when the component is being removed from the DOM&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이러한 lifecycle 각각을 제어하기 위해 개발자들이 사용할 수 있는 lifecycle method들이 존재합니다. 대표적으로 &lt;code&gt;constructor()&lt;/code&gt;와 &lt;code&gt;render()&lt;/code&gt; 역시 lifecycle method에 해당됩니다! &lt;code&gt;constructor()&lt;/code&gt;는 mounting phase에 첫 번째로 호출되는 메서드로, &lt;code&gt;render()&lt;/code&gt;는 mounting과 updating phase에 자주 등장하는 메서드로 분류할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;componentDidMount()&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;componentDidMount()&lt;/code&gt; 메서드는 mounting phase에서 마지막으로 호출되는 메서드입니다. Mounting phase 안에서 메서드들은 다음과 같은 순서로 호출됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The constructor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;render()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;componentDidMount()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;componentDidMount()&lt;/code&gt;를 활용하면 1초씩 현 시각을 계속 알려주는 시계를 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }
  render() {
    return &amp;lt;div&amp;gt;{this.state.date.toLocaleTimeString()}&amp;lt;/div&amp;gt;;
  }
  componentDidMount() {
    // Paste your code here.
    const oneSecond = 1000;
    setInterval(() =&amp;gt; {
      this.setState({ date: new Date() });
    }, oneSecond);
  }
}

ReactDOM.render(&amp;lt;Clock /&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;componentWillUnmount&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';

export class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }
  render() {
    return &amp;lt;div&amp;gt;{this.state.date.toLocaleTimeString()}&amp;lt;/div&amp;gt;;
  }
  componentDidMount() {
    const oneSecond = 1000;
    this.intervalID = setInterval(() =&amp;gt; {
      this.setState({ date: new Date() });
    }, oneSecond);
  }
  componentWillUnmount() {
    clearInterval(this.intervalID);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;componentWillUnmount&lt;/code&gt; 메서드는 unmounting phase에서 사용됩니다. Component가 완전히 없어지기 전에 호출되기 때문에, side-effect를 발생시키는 불필요한 비동기 함수를 종료하기 적합한 시기입니다. 위와 같이 시간을 지속적으로 업데이트하는 시계의 &lt;code&gt;setInterval()&lt;/code&gt; 함수를 멈추려면, &lt;code&gt;componentWillUnmount()&lt;/code&gt; 메서드에서 &lt;code&gt;clearInterval()&lt;/code&gt;을 사용합니다. &lt;code&gt;intervalID&lt;/code&gt;를 &lt;code&gt;clearInterval()&lt;/code&gt;의 인자로 전달해주면 해당 &lt;code&gt;setInterval()&lt;/code&gt; 함수를 종료시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;componentDidUpdate&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Updating phase에서 주로 사용하는 메서드는 &lt;code&gt;render()&lt;/code&gt;, &lt;code&gt;componentDidUpdate&lt;/code&gt;입니다. Update는 props와 state의 변화가 일어날 때 발생하는 작업으로, update 관련한 로직은 &lt;code&gt;componentDidUpdate&lt;/code&gt;에서 사용하는 것이 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this interactive diagram&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>Component</category>
      <category>JS</category>
      <category>Lifecycle Method</category>
      <category>react</category>
      <category>리액트</category>
      <category>생명주기</category>
      <category>자바스크립트</category>
      <category>컴포넌트</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/230</guid>
      <comments>https://dev-on-coffee.tistory.com/230#entry230comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:48:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] Component Interacting</title>
      <link>https://dev-on-coffee.tistory.com/229</link>
      <description>&lt;h1&gt;Component interacting&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;639&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNIrsA/btrdd77hsBU/umDaV1YpJx0m9xCaWTgMh0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNIrsA/btrdd77hsBU/umDaV1YpJx0m9xCaWTgMh0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNIrsA/btrdd77hsBU/umDaV1YpJx0m9xCaWTgMh0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNIrsA%2Fbtrdd77hsBU%2FumDaV1YpJx0m9xCaWTgMh0%2Fimg.jpg&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;639&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React application은 몇 십에서 몇 백 개까지 component를 가질 수 있습니다. 각각의 작은 component들은 자신의 역할을 담당하면서 거대한 app을 구성하고 서로 상호작용함으로써 app을 동작시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component 간 상호 작용 유형&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Component가 다른 component를 렌더링하는 것&lt;/li&gt;
&lt;li&gt;Component가 다른 component에게 정보를 전달하는 것&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;A component in a render function&lt;/h2&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class WelshCorgi extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Welsh Corgi wooooow!&amp;lt;/h1&amp;gt;;
  }
}
 
class Dog extends React.Component {
  render() {
    return &amp;lt;WelshCorgi /&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component 클래스의 &lt;code&gt;render()&lt;/code&gt; 메서드는 HTML-like JSX expression 뿐만 아니라 component instance 형태의 JSX expression도 리턴할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';


class WelshCorgi extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Welsh Corgi wooooow!&amp;lt;/h1&amp;gt;;
  }
}


class ProfilePage extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;All About Me!&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;I like Welsh Corgi!!!&amp;lt;/p&amp;gt;
        &amp;lt;WelshCorgi /&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 속성을 활용하면 하나의 component 안에서 다른 여러 개의 component를 함께 렌더링할 수 있습니다. 위의 &lt;code&gt;&amp;lt;WelshCorgi /&amp;gt;&lt;/code&gt; component 인스턴스는 &lt;code&gt;ProfilePage&lt;/code&gt; component가 생성되면 그 안에서 렌더링됩니다. 따라서, &lt;code&gt;ReactDOM.render()&lt;/code&gt;를 통해 &lt;code&gt;ProfilePage&lt;/code&gt; 인스턴스 하나만 렌더링하면 내부에 있는 component들은 자동으로 함께 렌더링되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component 안에 다른 component가 포함되어 렌더링될 수 있다는 특징은 리액트의 강력한 장점입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;Props&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 component가 자식 component에가 전달하는 정보가 담긴 객체를 &lt;code&gt;props&lt;/code&gt;라고 합니다. 모든 component들은 자신의 &lt;code&gt;props&lt;/code&gt;를 가지고 있으며, 이를 통해 부모 component로부터 전달받은 정보를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 component의 &lt;code&gt;props&lt;/code&gt;를 보고 싶다면, &lt;code&gt;this.props&lt;/code&gt;를 사용해 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;lt;Greeting name=&quot;Frarthur&quot; town=&quot;Flundon&quot; age={2} haunted={false} myInfo={[&quot;top&quot;, &quot;secret&quot;, &quot;lol&quot;]} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component에 prop을 추가하고 싶다면, 생성한 인스턴스에 속성으로 추가해주면 됩니다. 위의 코드는 &lt;code&gt;&amp;lt;Greeting /&amp;gt;&lt;/code&gt; component 인스턴스에 &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;town&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, &lt;code&gt;haunted&lt;/code&gt;, &lt;code&gt;myInfo&lt;/code&gt; 등의 props를 부여한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 만일 string이 아닌 정보를 주고 싶다면, &lt;code&gt;{}&lt;/code&gt;로 정보를 감싸서 속성을 부여해야 한다는 점을 유의합시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가한 속성들은 &lt;code&gt;this.props.속성이름&lt;/code&gt;을 통해 접근할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Event handler as prop&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 역시 &lt;code&gt;props&lt;/code&gt;로 넘길 수 있는데, 보통 event handler 함수가 이러한 특징을 활용해 prop으로 자주 전달됩니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';


class Button extends React.Component {
  render() {
    return (
      &amp;lt;button onClick={this.props.talk}&amp;gt;
        Click me!
      &amp;lt;/button&amp;gt;
    );
  }
}


class Talker extends React.Component {
  talk() {
    let speech = '';
    for (let i = 0; i &amp;lt; 10000; i++) {
      speech += 'blah ';
    }
    alert(speech);
  }
  
  render() {
    return &amp;lt;Button talk={this.talk} /&amp;gt;;
  }
}

ReactDOM.render(
  &amp;lt;Talker /&amp;gt;,
  document.getElementById('app')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Event handler는 &lt;code&gt;render()&lt;/code&gt; 메서드와 비슷한 방식으로 임의의 이름의 메서드를 정의하고 필요한 component에 prop으로서 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Naming convention of event handler&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Event handler를 prop으로 전달할 때, 임의로 naming해야 할 부분이 두 군데 생깁니다. 이 때, 반드시 따를 필요는 없지만 통용되는 naming convention이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째는 event handler 메서드를 정의할 때인데, 이벤트의 타입에 따라 handleClick, handleHover 등으로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째는 prop name인데, 이벤트 타입에 따라 onClick, onHover 등으로 정의합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;class MyClass extends React.Component {
  handleHover() {
    alert('I am an event handler.');
    alert('I will listen for a &quot;hover&quot; event.');
  }

  render() {
   return &amp;lt;Child onHover={this.handleHover} /&amp;gt;;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;this.props.children&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 component들은 &lt;code&gt;props&lt;/code&gt; 객체 내에 &lt;code&gt;children&lt;/code&gt; property를 가집니다. 앞서 self-closing tag로 만들었던 component들은 사실 &lt;code&gt;&amp;lt;MyComponentClass&amp;gt;&amp;lt;/MyComponentClass&amp;gt;&lt;/code&gt;로 나뉘어 쓰이는 것 역시 가능합니다. 이 경우, &lt;code&gt;this.props.children&lt;/code&gt;은 나뉘어 쓰이는 태그 사이에 존재하는 모든 것을 리턴합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';


class List extends React.Component {
  render() {
    let titleText = `Favorite ${this.props.type}`;
    if (this.props.children instanceof Array) {
    	titleText += 's';
    }
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;{titleText}&amp;lt;/h1&amp;gt;
        &amp;lt;ul&amp;gt;{this.props.children}&amp;lt;/ul&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}


class App extends React.Component {
  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;List type='Dog'&amp;gt;
          &amp;lt;li&amp;gt;Welsh Corgi&amp;lt;/li&amp;gt;
          &amp;lt;li&amp;gt;Dachshund&amp;lt;/li&amp;gt;
        &amp;lt;/List&amp;gt;
        &amp;lt;List type='Cat'&amp;gt;
          &amp;lt;li&amp;gt;Road cat&amp;lt;/li&amp;gt;
        &amp;lt;/List&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}

ReactDOM.render(
  &amp;lt;App /&amp;gt;, 
  document.getElementById('app')
);	
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 경우, &lt;code&gt;this.props.children&lt;/code&gt;은 각각의 List component 사이에 있는 모든 &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element들을 리턴합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;List type='Dog'&amp;gt;&lt;/code&gt;의 경우&lt;br /&gt;
&lt;pre id=&quot;code_1629895324461&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// return elements
&amp;lt;li&amp;gt;Welsh Corgi&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Dachshund&amp;lt;/li&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;List type='Cat'&amp;gt;&lt;/code&gt;의 경우&lt;br /&gt;
&lt;pre id=&quot;code_1629895351842&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// return element
&amp;lt;li&amp;gt;Road cat&amp;lt;/li&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;defaultProps&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;class Example extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;{this.props.text}&amp;lt;/h1&amp;gt;;
  }
}
 
Example.defaultProps = { text: 'Welsh Corgi' };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 component 인스턴스에 요구되어지는 prop이 전달되지 않았을 때, 해당 prop은 화면에 아무것도 출력하지 않을 것입니다. 이 때, default 값을 prop에 지정해 화면에 항상 무언가가 출력될 수 있게 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 component 클래스의 &lt;code&gt;defaultProps&lt;/code&gt; property를 사용합니다. &lt;code&gt;defaultProps&lt;/code&gt; property에 원하는 &lt;code&gt;props&lt;/code&gt;의 기본값들을 설정한 object를 지정하여 기본값 설정을 완료합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;state&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;축구 경기에서 각 팀의 스코어 정보처럼 변할 수 있는 정보를 dynamic information이라고 합니다. 리액트 component는 이러한 dynamic information을 다뤄야 할 때, &lt;code&gt;props&lt;/code&gt;와 &lt;code&gt;state&lt;/code&gt;를 사용합니다. 그 중, &lt;code&gt;state&lt;/code&gt;란 각각의 component가 가지고 있는 상태를 저장한 것을 뜻하며, component 내부에서 관리됩니다. 렌더링 결과물에 영향을 주는 정보를 갖고 있다는 부분에서도 &lt;code&gt;props&lt;/code&gt;와 공통점이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { mood: 'decent' };
  }
 
  render() {
    return &amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;;
  }
}
 
&amp;lt;Example /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기의 &lt;code&gt;state&lt;/code&gt;는 &lt;code&gt;props&lt;/code&gt;와 달리 component 클래스의 constructor에서 &lt;code&gt;state&lt;/code&gt; property를 지정해 설정합니다. 또한, 각각의 component들은 스스로의 &lt;code&gt;state&lt;/code&gt;를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 component는 &lt;code&gt;super()&lt;/code&gt;를 통해 항상 초기화 시켜야 합니다. 이후, &lt;code&gt;state&lt;/code&gt;에 적절한 객체를 할당해 initial state를 설정합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;class TodayImFeeling extends React.Component {
  constructor(props) {
    super(props);
    this.state = { mood: 'decent' };
  }
 
  render() {
    return (
      &amp;lt;h1&amp;gt;
        I'm feeling {this.state.mood}!
      &amp;lt;/h1&amp;gt;
    );
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component 클래스 내에서 &lt;code&gt;state&lt;/code&gt;에 접근하고 싶다면 &lt;code&gt;this.state.name-of-property&lt;/code&gt; 형태로 접근합니다. 위의 &lt;code&gt;this.state.mood&lt;/code&gt;는 'decent' 값에 접근합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;this.setState()&lt;/code&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component의 현재 &lt;code&gt;state&lt;/code&gt;를 바꾸고 싶다면, &lt;code&gt;this.setState()&lt;/code&gt; 메서드를 사용합니다. &lt;code&gt;setState()&lt;/code&gt;는 변경 요소가 담긴 객체를 첫 번째 인자로 받아 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;{
  mood:   'great',
  hungry: false
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 &lt;code&gt;state&lt;/code&gt;의 상황이 위와 같다고 가정해봅시다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;this.setState({ hungry: true });
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;code&gt;setState()&lt;/code&gt;를 사용해 &lt;code&gt;hungry&lt;/code&gt; 상태를 변경합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;{
  mood:   'great',
  hungry: true
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 결과 위와 같이 &lt;code&gt;hungry&lt;/code&gt; 상태만 &lt;code&gt;true&lt;/code&gt;로 변경되었습니다. &lt;code&gt;setState&lt;/code&gt;는 기본적으로 인자로 받은 객체에 담긴 요소들만 접근해 값을 변경하고 다른 원래의 요소들은 그대로 둡니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setState()와 render()&lt;br /&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;setState()&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt; 메서드에서 유의할 점은 이 메서드가 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;state&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt;를 변경한 후 자동적으로 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;.render()&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt; 메서드까지 호출한다는 부분입니다. 즉, &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;setState()&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt;를 사용하면 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;state&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt;를 변경한 부분이 바로 화면에 반영됩니다. 따라서, &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;setState()&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt;는 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;render()&lt;/code&gt;&lt;span style=&quot;color: #333333; letter-spacing: 0px;&quot;&gt; 메서드 안에서 호출되면 안됩니다. 이를 지키지 않으면 서로 끊임없이 호출하는 무한 루프에 빠지게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>Component interacting</category>
      <category>JS</category>
      <category>react</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>컴포넌트 상호작용</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/229</guid>
      <comments>https://dev-on-coffee.tistory.com/229#entry229comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:46:05 +0900</pubDate>
    </item>
    <item>
      <title>[React] Component</title>
      <link>https://dev-on-coffee.tistory.com/228</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Component of React&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component란 하나의 작업을 수행하는 재사용할 수 있는 작은 코드 뭉치를 의미합니다. 여기서 하나의 작업이란 대체로 HTML 코드를 렌더링하는 것을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Necessary import&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component를 사용하기 위해서는 &lt;code&gt;React&lt;/code&gt; 객체를 import 해두어야 합니다. &lt;code&gt;React&lt;/code&gt; 객체에는 리액트 라이브러리를 사용하기 위한 필수적인 메서드들이 담겨있습니다. JSX expression을 사용하는데도 &lt;code&gt;React&lt;/code&gt; 객체가 반드시 필요하므로, 첫 줄은 항상 다음 코드로 시작하도록 합니다!&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;import React from 'react';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, component 사용을 위해 &lt;code&gt;ReactDOM&lt;/code&gt; 객체도 import합니다. &lt;code&gt;ReactDOM&lt;/code&gt; 객체는 &lt;code&gt;React&lt;/code&gt; 객체와 마찬가지로 React와 관련된 메서드들을 가지고 있습니다. 그러나 &lt;code&gt;React&lt;/code&gt;에는 순수하게 React만을 위한 메서드가 담겨있는 반면, &lt;code&gt;ReactDOM&lt;/code&gt;은 React와 DOM의 상호작용을 돕는 메서드들이 담겨 있다는 차이점이 있습니다. 따라서, 다음 코드 역시 함께 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;import ReactDOM from 'react-dom';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;클래스를 활용한 Component 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 component는 자바스크립트의 클래스 혹은 함수를 통해 생성할 수 있습니다. 여기서는 클래스 component에 초점을 맞추겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 component는 리액트 라이브러리의 &lt;code&gt;Component&lt;/code&gt; 클래스를 상속받아서 정의합니다. 클래스를 사용하면 원하는 만큼 인스턴스로 component를 만들어 렌더링할 수 있다는 이점이 생깁니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';
 
class MyComponentClass extends React.Component {
  render() {
    return &amp;lt;h1&amp;gt;Hello component&amp;lt;/h1&amp;gt;;
  }
}

ReactDOM.render(
  &amp;lt;MyComponentClass /&amp;gt;,
  document.getElementById('app')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 &lt;code&gt;React.Component&lt;/code&gt;를 상속받으면 새로운 component 클래스를 만들어 customizing할 수 있습니다. 여기서 &lt;code&gt;React.Component&lt;/code&gt;는 &lt;code&gt;React&lt;/code&gt; 객체의 property이며, &lt;code&gt;Component&lt;/code&gt;는 클래스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 또 하나 유의할 점은 새로 정의한 component 클래스 body에는 반드시 &lt;code&gt;render()&lt;/code&gt; 메서드를, &lt;code&gt;render()&lt;/code&gt; 메서드 내에는 주로 JSX expression을 반환하는 &lt;code&gt;return&lt;/code&gt; statement를 정의해야 한다는 부분입니다. 해당 클래스에는 어떤 component를 만들 것인지 instruction을 제시해줘야 하기 때문에, 이를 위한 &lt;code&gt;render()&lt;/code&gt; 메서드와 &lt;code&gt;return&lt;/code&gt; statement를 필수적으로 정의합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이렇게 만들어진 클래스를 활용해 component를 자유롭게 생성할 수 있습니다. 앞서 JSX element를 사용했듯이, 클래스의 이름을 사용해 &lt;code&gt;&amp;lt;MyComponentClass /&amp;gt;&lt;/code&gt; 코드를 쓰면 component 인스턴스가 생성됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 생성한 component 인스턴스를 &lt;code&gt;ReactDOM.render()&lt;/code&gt;에 인자로 던져주면, 해당 component를 화면에 렌더링할 수 있습니다. Component는 클래스에서 정의한 &lt;code&gt;render()&lt;/code&gt; 메서드를 가지고 있기 때문에, &lt;code&gt;ReactDOM.render()&lt;/code&gt;는 인자로 받은 component의 &lt;code&gt;render()&lt;/code&gt; 메서드를 자동으로 호출하게끔 하여 JSX expression을 반환받고 화면에 렌더링합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Class component의 naming convention&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로 정의한 클래스 component의 이름은 첫 글자부터 대문자를 사용하는 UpperCamelCase를 따릅니다. 이것은 Java의 naming convention에서 차용되었으며, 원래의 JavaScript 클래스를 만들 때도 마찬가지의 convention을 따릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UpperCamelCase를 사용하는 또 다른 이유는 리액트 자체적으로도 찾을 수 있습니다. JSX element는 HTML-like인 경우와 component인 경우로 나뉩니다. 이 때, UpperCamelCase로 쓰인 JSX element가 있다면, 해당 element가 component instance임을 쉽게 파악할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) ShinyBrownHairOfWelshCorgi&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) &amp;lt;WelshCorgiLegComponent /&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;render() 메서드에 정의할 수 있는 것&lt;/h2&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Random extends React.Component {
  render() {
    // First, some logic that must happen
    // before rendering:
    const n = Math.floor(Math.random() * 10 + 1);
    // Next, a return statement
    // using that logic:
    return &amp;lt;h1&amp;gt;The number of Welsh Corgi is {n}!&amp;lt;/h1&amp;gt;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Component의 &lt;code&gt;render()&lt;/code&gt; 메서드에는 항상 &lt;code&gt;return&lt;/code&gt; statement가 와야 합니다. 다만 이에 더하여, 렌더링 직전의 간단한 계산 역시 둘 수 있는 위치입니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Random extends React.Component {
  // This should be in the render function:
  const n = Math.floor(Math.random() * 10 + 1);
 
  render() {
    return &amp;lt;h1&amp;gt;The number of Welsh Corgi is {n}!&amp;lt;/h1&amp;gt;;
  }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 위와 같이 &lt;code&gt;render()&lt;/code&gt; 메서드 바깥에 변수를 정의하는 것은 syntax error를 유발하니, 메서드 안쪽에서 정의할 것을 유의해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Event listener in a component&lt;/h2&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class MyClass extends React.Component {
  myFunc() {
    alert('Stop it. Stop hovering my Welsh Corgi.');
  }
 
  render() {
    return (
      &amp;lt;div onHover={this.myFunc}&amp;gt;
      &amp;lt;/div&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 component 클래스의 메서드로 정의한 event handler 함수를 사용하여, event listener를 component에 정의할 수 있습니다. Event listener 속성에 &lt;code&gt;this&lt;/code&gt;를 사용해 메서드를 부여하는 것으로 적용 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>Component</category>
      <category>JavaScript</category>
      <category>JS</category>
      <category>react</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>컴포넌트</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/228</guid>
      <comments>https://dev-on-coffee.tistory.com/228#entry228comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:38:23 +0900</pubDate>
    </item>
    <item>
      <title>[React] JSX</title>
      <link>https://dev-on-coffee.tistory.com/227</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;React basic&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React.js는 Facebook 엔지니어들이 개발한 UI 개발 목적의 JavaScript 라이브러리입니다. 리액트의 컴포넌트 기반 개발은 Single Page Application을 비롯한 프론트 개발에 큰 변화를 이끌었으며, 근 5~6년간 자바스크립트 생태계의 가장 중요한 존재 중 하나로 자리해 왔습니다. 최근에는 더 효율적인 프론트 개발 라이브러리들이 많이 등장했지만, 리액트의 영향력은 여전히 직간접적으로 느껴집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JSX&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const h1 = &amp;lt;h1&amp;gt;Welsh Corgi!!&amp;lt;/h1&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX는 리액트에 사용되기 위해 쓰여진 JavaScript의 syntax extension입니다. 보통 JavaScript 파일 속에 JavaScript 코드와 HTML 코드들이 혼용되어 쓰여진 것들로 통용되므로, JSX 코드에는 HTML같은 코드가 포함되지만 실제로 HTML은 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, JSX는 웹 브라우저가 바로 읽을 수 없습니다. 그러므로 JSX가 포함된 JavaScript 파일을 통상적으로 사용하려면, JSX compiler를 통해 일반적인 JavaScript 코드로 컴파일해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JSX element&lt;/h2&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;Hello world&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, JavaScript 파일 속에 HTML과 똑같이 생긴 위와 같은 코드들을 JSX element라고 부릅니다. JSX element는 JavaScript 코드로 간주되어, 변수에 저장되거나 함수의 인자로 입력되는 등 일반적인 모든 프로그래밍에 문제 없이 사용됩니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;const welshCorgi = &amp;lt;img src='images/welsh.jpg' alt='welsh corgi' width='600px' height='600px' /&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX element에는 HTML 때와 마찬가지로 attribute 역시 적용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const welshCorgi = (
  &amp;lt;a href=&quot;https://www.shinybrownhair.com&quot;&amp;gt;
    &amp;lt;h1&amp;gt;
      Bow wow!
    &amp;lt;/h1&amp;gt;
  &amp;lt;/a&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nested한 형태도 기존 HTML처럼 사용할 수 있습니다. 다만, multi-line이 될 경우 &lt;code&gt;()&lt;/code&gt;로 감싸주어야 오류 없이 프로그래밍할 수 있음을 유의합시다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const dogs = (
  &amp;lt;p&amp;gt;I am a Poodle.&amp;lt;/p&amp;gt; 
  &amp;lt;p&amp;gt;I am a Welsh Corgi. Nice to meet you!&amp;lt;/p&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, JSX expression은 하나의 같은 element 단위가 되어야 하기 때문에, 위와 같이 두 개의 element를 한 번에 사용하는 것은 불가능합니다. 만일 위와 같이 쓰고 싶다면, 위 코드를 하나의 &lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; 태그로 감싸서 코드가 올바르게 동작하도록 만드는 방법을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Rendering&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더링(Rendering)이란 코드를 해석해서 화면에 띄우는 작업을 의미합니다. 렌더링은 보통 리액트와 관련된 메서드들을 모아둔 &lt;code&gt;ReactDom&lt;/code&gt; 라이브러리의 &lt;code&gt;ReactDOM.render()&lt;/code&gt; 메서드를 사용해 진행합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(&amp;lt;h1&amp;gt;Hello world&amp;lt;/h1&amp;gt;, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;ReactDOM.render()&lt;/code&gt; 메서드에는 첫 번째 인자로 화면에 띄울 JSX expression을 사용합니다. 그리고 두 번째 인자로 해당 JSX expression을 띄울 container가 될 HTML 태그를 찾아 넘깁니다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;
&amp;lt;head&amp;gt;
	&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;
	&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;/styles.css&quot;&amp;gt;
	&amp;lt;title&amp;gt;Learn ReactJS&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
  &amp;lt;main id=&quot;app&quot;&amp;gt;&amp;lt;/main&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 위와 같은 &lt;code&gt;index.html&lt;/code&gt; 문서가 있다면, &lt;code&gt;&amp;lt;main id=&quot;app&quot;&amp;gt;&amp;lt;/main&amp;gt;&lt;/code&gt; 태그 속에 첫 번째 인자로 넘긴 JSX expression이 위치해 화면에 렌더링됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Virtual DOM&lt;/h2&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;const dog = &amp;lt;h1&amp;gt;Welsh Corgi&amp;lt;/h1&amp;gt;;
 
// This will add &quot;Welsh Corgi&quot; to the screen:
ReactDOM.render(dog, document.getElementById('app'));
 
// This won't do anything at all:
ReactDOM.render(dog, document.getElementById('app'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;ReactDOM.render()&lt;/code&gt;의 장점은 변경이 있는 DOM elements만 update한다는 점입니다. 수많은 DOM elements가 있을 때, 변경된 것들만 update하는 것은 React의 큰 이점입니다. React는 virtual DOM을 통해 이를 실현합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Virtual DOM이란 리액트에서 실제 DOM object와 대응되는 가벼운 카피 버전의 가상 DOM object를 말합니다. Virtual DOM은 실제 DOM과 같은 property들을 가지지만, DOM의 변화를 화면에 직접 띄우는 기능은 없기 때문에, 일반 DOM 조작보다 빠르다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 리액트는 다음과 같은 방식으로 DOM을 update합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 virtual DOM을 업데이트합니다.&lt;/li&gt;
&lt;li&gt;Update한 virtual DOM과 이전 virtual DOM의 snapshot을 비교하여 변화된 부분들을 확인합니다.&lt;/li&gt;
&lt;li&gt;변화된 부분만 실제 DOM object에서 update합니다.&lt;/li&gt;
&lt;li&gt;실제 DOM의 변화가 화면에 반영됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM manipulation의 단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거 일반적인 자바스크립트 라이브러리들은 DOM manipulation을 할 때, DOM element 하나가 변경되면 모든 element들을 다시 update해야 해서 비효율적이었습니다. 덕분에 DOM이 커질수록 cost가 더욱 늘어났는데, 리액트의 virtual DOM 도입은 cost 문제를 혁신적으로 해결했습니다. 변경된 특정 DOM element만 update하는 virtual DOM의 특징이 DOM manipulation 속도를 혁신적으로 향상 됐습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Advanced syntax of JSX&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX의 문법은 대게 HTML과 동일하지만 미묘하게 다른 부분들이 존재하므로 유의해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;className&lt;/h3&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;h1 className=&quot;dog&quot;&amp;gt;Welsh Corgi&amp;lt;/h1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML에서 사용되는 &lt;code&gt;class&lt;/code&gt; 속성은 JSX에서 &lt;code&gt;className&lt;/code&gt;으로 사용합니다. 이는 JavaScript가 &lt;code&gt;class&lt;/code&gt;를 예약어로 갖고 있어서 JSX를 JavaScript로 변압할 때 키워드가 겹치는 문제가 발생하기 때문입니다. 대신 &lt;code&gt;className&lt;/code&gt;은 JSX가 렌더링될 때, &lt;code&gt;class&lt;/code&gt; 속성으로서 자동으로 인식됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;self-closing tag&lt;/h3&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;Fine in HTML with a slash:   &amp;lt;br /&amp;gt; Also fine, without the slash:   &amp;lt;br&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML에서는 &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; 태그나 &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; 태그 같은 요소들의 끝 부분 &lt;code&gt;&amp;gt;&lt;/code&gt; 앞에 &lt;code&gt;/&lt;/code&gt;를 쓰는 것이 선택적입니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;Fine in JSX:   &amp;lt;br /&amp;gt; NOT FINE AT ALL in JSX:   &amp;lt;br&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, JSX에서는 self-closing tag에 &lt;code&gt;/&lt;/code&gt;를 반드시 써줘야 합니다. (그렇지 않으면, 에러가 발생합니다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JavaScript in JSX in JavaScript&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  &amp;lt;h1&amp;gt;{2 + 3}&amp;lt;/h1&amp;gt;,
  document.getElementById('app')
);
// Output on monitor: 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX expression 안에 일반적인 JavaScript 코드를 사용하고 싶다면, &lt;code&gt;{}&lt;/code&gt;를 사용합니다. &lt;code&gt;{}&lt;/code&gt; 안에 위치한 코드들은 JSX expression 안쪽이라도 JavaScript 코드로 인식됩니다. 여기서 &lt;code&gt;{}&lt;/code&gt;는 JSX나 JavaScript가 아니라, JavaScript injection into JSX의 시작과 끝을 나타내는 marker입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Event Listener&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function myFunc() {
  alert('Welsh Corgi!!!!');
}
 
&amp;lt;img onClick={myFunc} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX에서도 HTML과 같이 event listener를 사용할 수 있습니다. &lt;code&gt;on&lt;/code&gt;을 접두어로 하는 속성들을 사용하면 event listener를 적용할 수 있는데, 해당 속성들의 값은 반드시 함수가 되어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, HTML에서 event listener의 이름들은 모두 소문자로 쓰이지만, JSX에서는 camelCase로 사용해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Conditional statement&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX에는 &lt;code&gt;if&lt;/code&gt; 구문을 삽입할 수 없습니다. 하지만, 이를 해결할 몇 가지 방법도 존재합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const sound = 'Bow wow!';
if (sound === 'Bow wow!') {
  message = (
    &amp;lt;h1&amp;gt;
      Hey, good dog!
    &amp;lt;/h1&amp;gt;
  );
} else {
  message = (
    &amp;lt;h1&amp;gt;
      I like a lot of animal!
    &amp;lt;/h1&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, JSX 바깥에서 &lt;code&gt;if&lt;/code&gt;를 사용해 원하는 조건문을 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const sound = 'Bow wow!';
const message = (
  &amp;lt;h1&amp;gt;
    { sound === 'Bow wow!' ? 'Hey, good dog!' : 'I like a lot of animal!' }
  &amp;lt;/h1&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 삼항연산자(ternary operator)를 사용하면 JSX 내부에서도 조건문을 사용할 수 있습니다. React에서는 상당히 자주 사용되는 방법입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const tasty = (
  &amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;Dog feed&amp;lt;/li&amp;gt;
    { !puppy &amp;amp;&amp;amp; &amp;lt;li&amp;gt;Dog gum&amp;lt;/li&amp;gt; }
    { age &amp;gt; 1 &amp;amp;&amp;amp; &amp;lt;li&amp;gt;bone&amp;lt;/li&amp;gt; }
    { age &amp;gt; 5 &amp;amp;&amp;amp; &amp;lt;li&amp;gt;Dog ade&amp;lt;/li&amp;gt; }
    { age &amp;gt; 7 &amp;amp;&amp;amp; &amp;lt;li&amp;gt;Dog cookie&amp;lt;/li&amp;gt; }
  &amp;lt;/ul&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 어떤 조건에서만 action을 취하고 다른 때는 아무 것도 하지 않는 경우라면, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 연산자를 활용하는 것도 적합합니다. 즉, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 연산자의 왼쪽 expression이 true일 경우에만, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; 연산자의 오른쪽 expression이 렌더링될 것입니다. 이러한 형태의 조건문도 React에서 자주 쓰이는 방식입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;map()&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const dogs = ['Welsh Corgi', 'Poodle', 'Dachshund'];
 
const listDogs = dogs.map(dog =&amp;gt; &amp;lt;li&amp;gt;{dog}&amp;lt;/li&amp;gt;);
 
&amp;lt;ul&amp;gt;{listDogs}&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만일 JSX element의 array를 만들고 싶다면, &lt;code&gt;.map()&lt;/code&gt;을 사용하는 것이 유용합니다. React에서 자주 사용되는 방식이므로 기억해두면 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// This is fine in JSX, not in an explicit array:
 
&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;dog 1&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;dog 2&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;dog 3&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
 
// This is also fine!
 
const liArray = [
  &amp;lt;li&amp;gt;dog 1&amp;lt;/li&amp;gt;, 
  &amp;lt;li&amp;gt;dog 2&amp;lt;/li&amp;gt;, 
  &amp;lt;li&amp;gt;dog 3&amp;lt;/li&amp;gt;
];
 
&amp;lt;ul&amp;gt;{liArray}&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; JSX element들이 담긴 array는 위의 &lt;code&gt;{liArray}&lt;/code&gt; 같이 곧바로 &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;과 함께 사용하는 것이 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.createElement()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 코드를 JSX expression을 쓰지 않고도 사용할 수 있는 방법이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const h1 = &amp;lt;h1&amp;gt;Welsh Corgi&amp;lt;/h1&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 JSX expression으로 표현하던 기존의 코드는 다음과 같이 새로 쓰일 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const h1 = React.createElement(
  &quot;h1&quot;,
  null,
  &quot;Welsh Corgi&quot;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;React.createElement()&lt;/code&gt;을 사용하면 JSX expression을 쓰지 않고도 같은 기능을 하는 React 코드를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 JSX element가 컴파일 될 때, 컴파일러는 내부적으로 해당 JSX element를 &lt;code&gt;React.createElement()&lt;/code&gt; 메서드로 변형하여 호출합니다. 즉, JSX expression을 사용하기 전에는 항상 &lt;code&gt;import React from 'react';&lt;/code&gt;로 &lt;code&gt;React&lt;/code&gt; 객체를 import해야 하는데, 그 이유는 내부적으로 항상 &lt;code&gt;React.createElement()&lt;/code&gt; 메서드가 사용 가능해야 하기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/react-101&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Learn React - Codecademy&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://reactjs.org/docs/events.html#supported-events&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Event Listener List - React.js&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>JS</category>
      <category>jsx</category>
      <category>react</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/227</guid>
      <comments>https://dev-on-coffee.tistory.com/227#entry227comment</comments>
      <pubDate>Wed, 25 Aug 2021 21:36:42 +0900</pubDate>
    </item>
    <item>
      <title>[JS] Async-Await</title>
      <link>https://dev-on-coffee.tistory.com/226</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Async-Await&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt;, &lt;code&gt;await&lt;/code&gt;을 사용하는 구문은 ES8에서 소개된 JavaScript의 비동기 처리를 위한 syntactic sugar입니다. 비동기 처리하는 과정이나 결과는 이전 callback 함수를 통해 구현하는 방식이나 혹은 ES6에서부터 사용하는 promise 객체를 사용해 구현하는 방식과 동일하지만, 문법적으로 조금 더 편리하게 비동기 처리를 할 수 있도록 제공됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;async&lt;/code&gt; keyword&lt;/h2&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;async function myFunc() {
  // Function body here
};
 
myFunc();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 함수를 만들기 위해 사용하는 키워드입니다. 구현한 비동기 처리 로직은 위와 같이 &lt;code&gt;async&lt;/code&gt;로 선언된 함수로 감싸서 의도대로 실행할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;const myFunc = async () =&amp;gt; {
  // Function body here
};
 
myFunc();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, &lt;code&gt;async&lt;/code&gt; 함수는 함수 선언식 뿐만 아니라 함수 표현식으로도 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;async&lt;/code&gt; 함수의 리턴 값&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt; 함수는 항상 promise 객체를 리턴합니다. 덕분에, 원래의 promise 비동기 처리 방식대로 &lt;code&gt;.then()&lt;/code&gt;, &lt;code&gt;.catch()&lt;/code&gt; 등을 그대로 사용할 수 있습니다. 다만, 리턴할 때 3가지 상황에 따라 다른 promise 객체를 내어줍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명시적으로 리턴하는 값이 없을 때&lt;br /&gt;&lt;code&gt;undefined&lt;/code&gt;를 resolved value로 사용하는 promise 객체를 리턴합니다.&lt;/li&gt;
&lt;li&gt;명시적으로 promise 객체가 아닌 값을 리턴할 때&lt;br /&gt;해당 리턴 값을 resolved value로 사용하는 promise 객체를 리턴합니다.&lt;/li&gt;
&lt;li&gt;명시적으로 promise 객체를 리턴할 때&lt;br /&gt;해당 promise 객체를 그대로 리턴합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;await&lt;/code&gt; keyword&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt; 키워드 만으로는 비동기 처리를 제대로 할 수 없기 때문에, &lt;code&gt;async&lt;/code&gt; 함수 안에서는 보통 &lt;code&gt;await&lt;/code&gt;을 함께 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;await&lt;/code&gt;은 지정한 함수에서 promise 객체가 리턴 및 resolve될 때까지 &lt;code&gt;async&lt;/code&gt; 함수 실행 자체를 멈추었다가, promise의 resolved value를 받으면 해당 값을 리턴하고 &lt;code&gt;async&lt;/code&gt; 함수의 남은 코드를 다시 실행하는 키워드입니다. 즉, promise를 객체를 받아 해당 promise 객체를 pending 상태에서 resolved 상태까지 실행하여 resolved value를 리턴하는 전 과정을 포괄합니다. 이러한 특이성으로 인해, &lt;code&gt;await&lt;/code&gt;은 주로 라이브러리에서 가져온 promise를 리턴하는 함수와 함께 사용하는 것이 일반적입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;async function asyncFuncExample(){
  let resolvedValue = await myPromise();
  console.log(resolvedValue);
}
 
asyncFuncExample(); // Prints: I am resolved now!
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 &lt;code&gt;myPromise()&lt;/code&gt;는 &lt;code&gt;&quot;I am resolved now!&quot;&lt;/code&gt;라는 string을 resolve할 promise를 리턴하는 함수입니다. 이렇게 promise의 로직을 인지하며 &lt;code&gt;await&lt;/code&gt;을 사용하면, 비동기적인 코드가 순차적인 코드 흐름으로 읽히도록 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Error handling with &lt;code&gt;try... catch&lt;/code&gt;&lt;/h2&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;async function usingTryCatch() {
 try {
   let resolveValue = await asyncFunction('thing that will fail');
   let secondValue = await secondAsyncFunction(resolveValue);
 } catch (err) {
   // Catches any errors in the try block
   console.log(err);
 }
}
 
usingTryCatch();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 promise 객체 비동기 처리 방식에서 chain이 길어질 때, &lt;code&gt;.catch&lt;/code&gt;를 사용해도 어떤 순서에서 error가 발생한 것인지 파악하기 어려웠습니다. 반면에, &lt;code&gt;async... await&lt;/code&gt;에서는 &lt;code&gt;try... catch&lt;/code&gt;를 사용해 쉽게 error handling을 진행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt; 함수에서 &lt;code&gt;try... catch&lt;/code&gt;는 동기적인 코드와 같은 방식으로 error handling을 할 수 있으면서 동시에, 동기 및 비동기 error 모두를 잡아낼 수 있기 때문에, 쉬운 디버깅을 가능하게 한다는 큰 이점이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;async function usingPromiseCatch() {
   let resolveValue = await asyncFunction('thing that will fail');
}
 
let rejectedPromise = usingPromiseCatch();
rejectedPromise.catch((rejectValue) =&amp;gt; {
console.log(rejectValue);
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 &lt;code&gt;async&lt;/code&gt; 함수도 promise 객체의 &lt;code&gt;.catch&lt;/code&gt; 메서드를 종종 사용할 때가 있습니다. 위와 같이, 복잡한 코드의 마지막 에러만 잡아내고 싶을 경우 global scope에서 사용하는 것이 하나의 예입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;독립적인 promise들을 다루는 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다수의 promise 객체들이 서로 의존하고 있을 때는 promise마다 &lt;code&gt;await&lt;/code&gt;을 사용하여 명확한 순서로 비동기 처리를 하는 것이 효율적입니다. 반면에, promise 객체들이 서로 독립적일 때는 순서에 상관없이 모든 promise가 동시에 실행되는 것이 보다 효율적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;async&lt;/code&gt; 함수에서 앞서 이야기한 concurrent 실행을 진행하는 방법을 크게 2가지 소개하겠습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;await in one line&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1629891528329&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 원래의 모습
async function waiting() {
 const firstValue = await firstAsyncThing();
 const secondValue = await secondAsyncThing();
 console.log(firstValue, secondValue);
}
*/ 

// concurrent 실행
async function concurrent() {
 const firstPromise = firstAsyncThing();
 const secondPromise = secondAsyncThing();
console.log(await firstPromise, await secondPromise);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;use &lt;code&gt;Promise.all&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1629891678455&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function asyncPromAll() {
  const resultArray = await Promise.all([asyncTask1(), asyncTask2(), asyncTask3(), asyncTask4()]);
  for (let i = 0; i&amp;lt;resultArray.length; i++){
    console.log(resultArray[i]); 
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/introduction-to-javascript/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Codecademy - introduction to javascript&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming Language/JavaScript</category>
      <category>async</category>
      <category>await</category>
      <category>JavaScript</category>
      <category>JS</category>
      <category>Promise</category>
      <category>비동기</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/226</guid>
      <comments>https://dev-on-coffee.tistory.com/226#entry226comment</comments>
      <pubDate>Wed, 25 Aug 2021 20:37:01 +0900</pubDate>
    </item>
    <item>
      <title>[JS] Browser Compatibility &amp;amp; Transpilation</title>
      <link>https://dev-on-coffee.tistory.com/225</link>
      <description>&lt;h1&gt;Browser Compatibility &amp;amp; Transpilation&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 정기적으로 web browser의 update 알림을 받습니다. 주기적인 update가 필요한 이유는 보통 보안상 취약점을 처리하고 HTML, CSS 혹은 JavaScript의 새로운 syntax 버전을 지원하기 위해서입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, JavaScript의 표준을 관리하는 기관, Ecma International이 2015년에 발표한 ECMAScript2015(흔히, ES6로 불리우는)가 등장했을 때, 많은 개발자들은 장점이 많은 ES6를 바로 채택하고 사용했지만 대부분의 브라우저에서 ES6가 지원되지 않아 브라우저 호환성(browser compatibility) 문제가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 챕터에서는 새로운 syntax 버전과의 gap으로 인해 발생하는 이러한 브라우저 호환성 이슈를 개발자들이 어떤식으로 처리하는지에 초점을 맞추려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;caniuse.com&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;712&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GlFqE/btrdd6m8vXP/YaMdEgp8K50SQWyJSnENdK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GlFqE/btrdd6m8vXP/YaMdEgp8K50SQWyJSnENdK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GlFqE/btrdd6m8vXP/YaMdEgp8K50SQWyJSnENdK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGlFqE%2Fbtrdd6m8vXP%2FYaMdEgp8K50SQWyJSnENdK%2Fimg.jpg&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;712&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;caniuser.com은 브라우저 호환성 정보를 쉽게 찾아볼 수 있는 사이트입니다. 어떤 브라우저의 몇 번째 버전이 특정 라이브러리를 지원하는지 여부를 간단히 체크할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 곳에서 검색해보면, ES5는 여전히 대다수의 브라우저에서 지원됩니다. 이와 달리, ES6는 점진적인 적용을 감안해야 합니다. 그 결과 대부분의 최신 버전 브라우저에서는 ES6가 원활히 지원되는 반면, ES6 module과 같은 ES6의 특정 feature들은 지원되지 않는 브라우저가 아직 대다수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ES6의 장점과 Transpilation의 필요성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ES6는 이전 버전인 ES5에 비해 상당한 이점들이 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Readability and economy of code&lt;/li&gt;
&lt;li&gt;Addresses sources of ES5 bugs&lt;/li&gt;
&lt;li&gt;A similarity to other programming languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 장점들은 많은 web developer들이 ES6를 곧바로 채택하도록 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, ECMA는 이로 인해 발생할 호환성 문제를 미리 예상해, ES6가 ES5 코드로 mapping될 수 있게끔 만들었습니다. 예를 들어, &lt;code&gt;const&lt;/code&gt;나 &lt;code&gt;let&lt;/code&gt; 키워드를 &lt;code&gt;var&lt;/code&gt;로 mapping하거나, interpolation을 concatenation으로 mapping하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 mapping은 충분히 규칙적이기 때문에, 개발자들은 ES6가 자동으로 ES5으로 변환되도록 하는 Babel이라는 JS library를 만들었습니다. 즉, 하나의 프로그래밍 언어를 다른 언어로 변환하는 과정을 transpilation이라고 하며, Babel은 ES6를 ES5로 transpile합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Babel&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Babel은 ES6를 ES5로 손쉽게 transpile해주는 library입니다. 먼저, Babel을 사용하기 위해 ES6의 파일(main.js)의 위치를 &lt;code&gt;./src/main.js&lt;/code&gt;에 둡니다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;project
|_ src
|___ main.js  // ES6 file&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Babel을 설치하기 전에 npm을 사용할 수 있게끔 프로젝트를 setup해야 합니다. npm은 node project manager의 약자로 node package에 대한 접근과 관리를 위해 사용됩니다. npm을 사용하면 작업의 반복과 버그를 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 npm을 init합니다. (Node가 설치되어 있어야 합니다!)&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;npm init&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, metadata에 관한 사항을 적어달라는 prompt가 나오는데, title과 description정도만 입력하고 전부 무시해도 좋습니다. (title, description 역시 선택사항입니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Init 이후에, root 디렉토리에는 &lt;code&gt;package.json&lt;/code&gt; 파일이 생성됩니다. &lt;code&gt;package.json&lt;/code&gt; 파일은 해당 프로젝트의 metadata와 프로젝트를 실행하기 위해 필요한 node package 목록, command line scripts에 해당하는 key-value pair 등을 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Babel은 터미널 창에서 다음과 같이 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Babel package 설치하기 (2개 모두)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;for CLI tool&lt;br /&gt;
&lt;pre id=&quot;code_1629892349728&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install babel-cli -D&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;for mapping information&lt;br /&gt;
&lt;pre id=&quot;code_1629892416694&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install babel-preset-env -D​&lt;/code&gt;&lt;/pre&gt;
실행이 완료되면 Babel 패키지 및 관련된 모든 dependency들이&lt;span&gt;&amp;nbsp;&lt;/span&gt;node_modules&lt;span&gt;&amp;nbsp;&lt;/span&gt;디렉토리에 저장되어 있는 것을 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;-D 옵션&lt;br /&gt;-D는 해당 패키지를 package.json의 devDependencies라는 property에 추가하는 옵션입니다. 일단 devDependencies에 추가된 패키지들은 다른 개발자들이 현재 프로젝트를 실행할 때 각각의 패키지를 install할 필요없이 npm install 커맨드 한 번으로 모두 설치되는 이점을 가집니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Source가 되는 JS version 설정하기&lt;br /&gt;&lt;span&gt;Root 디렉토리에서 &lt;/span&gt;&lt;span&gt;&lt;span&gt;`&lt;/span&gt;.babelrc&lt;span&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 파일을 생성합니다.&lt;/span&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1629892604656&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;touch .babelrc​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;&lt;code&gt;.babelrc&lt;/code&gt; 내에 source가 될 js 파일의 버전을 명시합니다. 아래와 같은 object를 파일에 저장하면, Babel은 ES6+에 대한 코드들을 목표 언어로 변환할 것입니다.&lt;br /&gt;
&lt;pre id=&quot;code_1629891933689&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{ 
  &quot;presets&quot;: [&quot;env&quot;] 
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt;에 Babel 실행을 위한 script 기재하기&lt;br /&gt;package.json에&lt;span&gt;&amp;nbsp;&lt;/span&gt;script&lt;span&gt;&amp;nbsp;&lt;/span&gt;property에 가보면 다음과 같은 객체가 존재함을 확인할 수 있습니다.&lt;br /&gt;
&lt;pre id=&quot;code_1629892097462&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
&quot;scripts&quot;: {
  &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;
}, ...​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;이 객체의 &lt;code&gt;&quot;test&quot;&lt;/code&gt; property 밑에, 다음과 같이 Babel을 실행하기 위한 script를 하나 추가합니다.&lt;br /&gt;
&lt;pre id=&quot;code_1629892154197&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
&quot;scripts&quot;: {
  &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;,
  &quot;build&quot;: &quot;babel src -d lib&quot;
}​&lt;/code&gt;&lt;/pre&gt;
추가한 코드는 각각 다음과 같은 의미를 가지고 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;babel&lt;/code&gt; &amp;mdash; The Babel command call responsible for transpiling code.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt; &amp;mdash; Instructs Babel to transpile all JavaScript code inside the &lt;b&gt;src&lt;/b&gt; directory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-d&lt;/code&gt; &amp;mdash; Instructs Babel to write the transpiled code to a directory.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lib&lt;/code&gt; &amp;mdash; Babel writes the transpiled code to a directory called &lt;code&gt;lib&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Babel 실행하기 (root directory)&lt;br /&gt;
&lt;pre id=&quot;code_1629892198793&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm run build​&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 완료되면 &lt;b&gt;./lib&lt;/b&gt; 디렉토리에 변환된 ES5 코드가 담긴 파일을 확인할 수 있습니다. 파일명은 본래의 ES6 파일명과 동일하게 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적인 디렉토리 구조는 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;project
|_ lib
|___ main.js
|_ node_modules
|___ .bin
|___ ...
|_ src
|___ main.js
|_ .babelrc
|_ package.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.codecademy.com/courses/introduction-to-javascript/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Codecademy - introduction to javascript&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming Language/JavaScript</category>
      <category>babel</category>
      <category>caniuse</category>
      <category>JavaScript</category>
      <category>JS</category>
      <category>transpilation</category>
      <category>브라우저 호환성</category>
      <author>Lucian_Cho</author>
      <guid isPermaLink="true">https://dev-on-coffee.tistory.com/225</guid>
      <comments>https://dev-on-coffee.tistory.com/225#entry225comment</comments>
      <pubDate>Wed, 25 Aug 2021 20:35:08 +0900</pubDate>
    </item>
  </channel>
</rss>