<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Mapin</title>
    <link>https://dailymapins.tistory.com/</link>
    <description>다람쥐 입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 20 Aug 2026 23:16:45 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Mapin</managingEditor>
    <image>
      <title>Mapin</title>
      <url>https://tistory1.daumcdn.net/tistory/4992279/attach/0382bf0f2c3540b792f3a84bf6cd44cd</url>
      <link>https://dailymapins.tistory.com</link>
    </image>
    <item>
      <title>블로그 공지</title>
      <link>https://dailymapins.tistory.com/356</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜만입니다.&lt;br /&gt;FE와 JS를 한참 공부하고 제가 3학년때부터 약 1년정도 쓰기 시작했던 블로그였는데, 카카오 화제사건으로 인해 색인이 다 빠져버린 뒤로 블로그 쓸 맛이 안나서 velog로 이사를 갔습니다.&lt;br /&gt;&lt;br /&gt;종종 제 글을 봐주시고, 또 저도 가끔 JS가 기억이 안날때 제 블로그를 뒤지기도 하는데요, 글을 하나 둘 씩 velog로 옮길 생각입니다.(JS ,TS를 다시 한번 보고싶거든요 !)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 근황은 게임개발로 완전 돌아섰습니다. 여러가지 이유가 있지만, 제일 큰건 개인적으로 Web이 재미가 없어졌습니다. 웹을 하면서 &lt;b&gt;프로그래밍을 잘한다&lt;/b&gt;라기 보단 점점 &lt;b&gt;프레임워크의 고수&lt;/b&gt;가 되어가는(?)&amp;nbsp; 그런느낌을 받았기 때문에... 점점 스&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;프링이 없으면 코딩을 못할것 같은 느낌이 들고, 모든 사고 방식이 하나의 프레임워크에 의존적으로 변해가는 자신이 싫더라구요 .&lt;/span&gt;&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;제가 생각하는 엔지니어는 플랫폼이 변해도 적응해서 살아가는 그런 엔지니어라고 생각을 합니다. 하지만, 새로나오는 플랫폼은 &lt;b&gt;기존 시장에서 엄청난 지분을 차지하는 것을 기반&lt;/b&gt;으로 나오기 때문에, 스프링을 하면서 저런 걱정을 한다는것 자체가 잘못됐다고 하실 수 있습니다. 저도 인정합니다.&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;게다가 &lt;b&gt;하나의 프레임워크를 잘 다루고, 잘 이해하는것도 굉장히 어렵고 대단한 능력&lt;/b&gt;입니다.&amp;nbsp; Spring은 20년동안 굳건하게 자리를 지켜왔기 때 문에&amp;nbsp; 앞으로도 쭉 그 자리를 지켜나갈거라고 생각합니다. 하지만, 마음이 불편하니까 점점&amp;nbsp; 흥미도 식고 , 이게 주위 사람들에 비해서 경쟁력도 떨어지게 되더라구요.&amp;nbsp;&lt;/span&gt;&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;그래서, 4학년 2학기때 쯤에 뭘할까.. 여러분야를 생각해보다보니, 하나하나 로우 레벨부터 직접 만드는 재미는 게임만한게 없더라구요. 그리고, 지금까지는 진짜 재밌게 하고 있습니다!&lt;/p&gt;</description>
      <category>Talking</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/356</guid>
      <comments>https://dailymapins.tistory.com/356#entry356comment</comments>
      <pubDate>Sat, 6 Jul 2024 12:08:53 +0900</pubDate>
    </item>
    <item>
      <title>[React/Optimize/Memo] Component를 분리하고, 마지막으로 React의 Memorization을 활용해보자!</title>
      <link>https://dailymapins.tistory.com/355</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Component의 재사용성과 확장성을 갖기위해서 , 컴포넌트의 &quot;합성&quot;를 이용해서 , 좀 더 추상적인 컴포넌트를 만들고 혹은 재사용되는 컴포넌트를 만들고 구체화하는 방식으로 구현했습니다. 하지만, 그에 따른 부작용으로 컴포넌트간의 관계가 복잡해지고, 리렌더링 Issue가 생기기 시작했습니다.&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;&lt;b&gt;현실적으로 FE 개발자에게 &quot;생산성&quot;은 빠질 수 없는 요소이기 때문에, 사실 이러한 이슈에 대해서 깊게 파고드는 것은 당장 필요한 사항은 아닐 수 있습니다.&lt;/b&gt; 세부적인 동작은 모두 React에 일임하고 , 우리는 그것을 사용하면 되니까요. 하지만,한번 깊이감있게 가져가보겠습니다. 재밌기도 하거든요!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;i&gt;Memo를 사용하기 전에, 독립적으로 나눌 수 있는 Component가 없는지 확인해보자 . (By 공식문서)&lt;/i&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저보다 똑똑한 분들이 만든&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;React는 이미 훌륭한 라이브러리이고, 그 React만의 흐름을 잘 타서 활용하는것이 좋은 방법이지 , 이 React 만의 흐름을 깨는것은 바람직하지 못합니다.&lt;s&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;(강아지가 뒤로가고 싶은데 제가 앞에서 목줄을 당긴다면, 힘이 많이 들겠죠!)&lt;/b&gt;&lt;/s&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;google_co_kr_20160412_121814.jpg&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVQVc7/btrQKDOLwWh/LLCUwUUMneBIMYftI3Iyc1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVQVc7/btrQKDOLwWh/LLCUwUUMneBIMYftI3Iyc1/img.jpg&quot; data-alt=&quot;흐름을 거스르지 맙시다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVQVc7/btrQKDOLwWh/LLCUwUUMneBIMYftI3Iyc1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVQVc7%2FbtrQKDOLwWh%2FLLCUwUUMneBIMYftI3Iyc1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;383&quot; height=&quot;383&quot; data-filename=&quot;google_co_kr_20160412_121814.jpg&quot; data-origin-width=&quot;629&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;흐름을 거스르지 맙시다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Memo가 &quot;최적화&quot;방법이라고 하지만, 최적화를 할 수 있는 상황에서 &quot;최적화&quot;이지 , 최적화를 하지 않아도 되는 상황에서 Memo를 사용하면 오히려, 얕은 비교를 실행하여 불필요한 추가연산이 필요해집니다. 생각해보면, &lt;b&gt;Memo&lt;span style=&quot;background-color: #dddddd;&quot;&gt; &quot;동작이 모든 환경에서의 최적화 동작&quot;&lt;/span&gt;을 했다면, 그냥 렌더링의 모든 과정을 memo로 구현하면 되지, 왜 그러지 않았을까요!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만, 저희는 컴퓨터공학도! 입증하려면, React의 코드를 직접 까봐야합니다. 직접 까보는것도 정말 좋겠지만, 우선 저의 시간을 아껴주실 선생님을 모시도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1668052408573&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;React Advanced 2022 - A (Brief) Guide to React Rendering Behavior&quot; data-og-description=&quot;A shorter look at how React rendering actually works&quot; data-og-host=&quot;blog.isquaredsoftware.com&quot; data-og-source-url=&quot;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&quot; data-og-url=&quot;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dDkm6t/hyQwBBqudZ/xRUBdpNIPCrFzFyA3jl8Mk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300&quot;&gt;&lt;a href=&quot;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.isquaredsoftware.com/2022/10/presentations-react-rendering-behavior/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dDkm6t/hyQwBBqudZ/xRUBdpNIPCrFzFyA3jl8Mk/img.png?width=300&amp;amp;height=300&amp;amp;face=0_0_300_300');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;React Advanced 2022 - A (Brief) Guide to React Rendering Behavior&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A shorter look at how React rendering actually works&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.isquaredsoftware.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;렌더링 Issue&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React가 렌더링을 다시하는 경우는 4가지로 정해져 있습니다. &quot;React&quot;는 컴포넌트에 대한 전권을 갖고있습니다. 즉, React가 모든 상황을 통제합니다. &lt;b&gt;React에서는 정확하게는 &quot;렌더링에서 제외되는 조건&quot;&lt;/b&gt;이 정해져있지만 , &quot;렌더링이 제외되는 조건&quot;보다는 렌더링이 되는 조건이 조금 더 직관적인것 같습니다.&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;1.&lt;b&gt; State가 변경이 되었을 때&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉, setState가 실행되면 해당 &lt;b&gt;State가 존재하는 컴포넌트는 리렌더링&lt;/b&gt; 되어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.&quot;새로운&quot; Props가 들어올 때&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부모 컴포넌트로부터,&amp;nbsp;&lt;b&gt;새 props가 들어오면,&amp;nbsp;자식 컴포넌트는 재렌더링 됩니다.&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 기존 Props가 업데이트 되었을 때&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부모 컴포넌트로 받은,&lt;b&gt;&amp;nbsp;props가 변경되면 props 값을 받은 자식 컴포넌트도 재렌더링 됩니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 부모 컴포넌트가 리렌더링 될 때&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;부모 컴포넌트가 재렌더링되면, 자식 컴포넌트도 모두 재렌더링 됩니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;흔한 Counter 예시를 들어보겠습니다. &lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Counter .jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668079760818&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React ,{useState} from &quot;react&quot;

function Inner(){
	console.log(&quot;Inner is Rendered!&quot;);
	return(
    	&amp;lt;div&amp;gt;
        	This is Inner!
        &amp;lt;/div&amp;gt;
    )
}


function Counter(){
	const [count,setCount] = useState(0)
    console.log(&quot;Counter is Render&quot;!)
    const handleCount = () =&amp;gt;{
    	setCount((prev)=&amp;gt;prev +1)
    }
	return(
    	&amp;lt;&amp;gt;
        	&amp;lt;button onClick={handleCount}&amp;gt;&amp;lt;/button&amp;gt;
        	&amp;lt;div&amp;gt;{count}&amp;lt;/div&amp;gt;
            &amp;lt;Inner&amp;gt;&amp;lt;/Inner&amp;gt;
        &amp;lt;/&amp;gt;
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9Titb/btrQT69Ulyi/HWKp28473DVVfXBR3KOnO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9Titb/btrQT69Ulyi/HWKp28473DVVfXBR3KOnO1/img.png&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;610&quot; data-is-animation=&quot;false&quot; width=&quot;576&quot; height=&quot;468&quot; style=&quot;width: 60.6552%; margin-right: 10px;&quot; data-widthpercent=&quot;61.37&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9Titb/btrQT69Ulyi/HWKp28473DVVfXBR3KOnO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9Titb%2FbtrQT69Ulyi%2FHWKp28473DVVfXBR3KOnO1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;751&quot; height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/el3lR3/btrQVaqjoUZ/I3ksGC08KKMzppf9cPs7P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/el3lR3/btrQVaqjoUZ/I3ksGC08KKMzppf9cPs7P0/img.png&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;680&quot; data-is-animation=&quot;false&quot; style=&quot;width: 38.1821%;&quot; data-widthpercent=&quot;38.63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/el3lR3/btrQVaqjoUZ/I3ksGC08KKMzppf9cPs7P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fel3lR3%2FbtrQVaqjoUZ%2FI3ksGC08KKMzppf9cPs7P0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;527&quot; height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;버튼을 클릭하면 , 어떻게 될까요 ? 네 , 당연히 Counter가 리렌더링 되면서&amp;nbsp; , Inner가 리렌더링 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜냐하면, Counter 아래에 &amp;lt;Inner&amp;gt;이 있기 때문이죠! 그럼 , 이걸 어떻게 해결할 수 있을까요?&amp;nbsp; &lt;/b&gt;&lt;b&gt;렌더링 되는 원인은 Inner가 Counter 속에 있기 때문입니다.&amp;nbsp; 하지만, Rendering 위치는 변하면 안됩니다. Inner는 정확하게 {count} 아래에 있어야합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;우선, 가장 잘 알려진 Memo기능을 사용할 수 있겠네요!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Child Component는 매번 바뀌지 않기 때문에, &lt;b&gt;Memo 해놓고, 렌더링 시켜주면 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668081155980&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function _Child() {
  console.log(&quot;Child is Render!&quot;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;Hello!&amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
const Child = React.memo(_Child);

function Parent() {
  const [count, setCount] = useState(0);
  const handleClick = () =&amp;gt; {
    setCount((prev) =&amp;gt; prev + 1);
  };
  console.log(&quot;Parent is Render!&quot;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;+1&amp;lt;/button&amp;gt;
      &amp;lt;div&amp;gt;{count}&amp;lt;/div&amp;gt;
      &amp;lt;Child /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default Parent;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/taHsH/btrQU9kGIZw/BkIKBBXG4gLDPjfUe0Dki1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/taHsH/btrQU9kGIZw/BkIKBBXG4gLDPjfUe0Dki1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/taHsH/btrQU9kGIZw/BkIKBBXG4gLDPjfUe0Dki1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtaHsH%2FbtrQU9kGIZw%2FBkIKBBXG4gLDPjfUe0Dki1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;668&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네 잘되네요!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;하지만, 리엑트는 이렇게 권장하고 있습니다. &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 컴포넌트에서 컴포넌트를 분리하고, Props로써 던져주라고요! 저도, 이게 더 좋은것 같습니다. 더 &quot;리엑트&quot;스럽네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Index.js&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668080426814&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Inner() {
  console.log(&quot;Inner is Rendered!&quot;);
  return &amp;lt;div&amp;gt;This is Inner!&amp;lt;/div&amp;gt;;
}

root.render(
  &amp;lt;StrictMode&amp;gt;
    {/*&amp;lt;Parent lastChild={&amp;lt;Child /&amp;gt;} /&amp;gt;*/}
    &amp;lt;Counter props ={&amp;lt;Inner/&amp;gt;}/&amp;gt;
  &amp;lt;/StrictMode&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xTjs9/btrQT7ubQg5/phKTKiZDwBzpFEYSPHjgtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xTjs9/btrQT7ubQg5/phKTKiZDwBzpFEYSPHjgtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xTjs9/btrQT7ubQg5/phKTKiZDwBzpFEYSPHjgtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxTjs9%2FbtrQT7ubQg5%2FphKTKiZDwBzpFEYSPHjgtk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;250&quot; height=&quot;381&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의도했던대로, 하위 컴포넌트가 리렌더링 되지않습니다. 이건, 새로운 Props가 전달되지 않죠! 알아둡시다.&amp;nbsp; &lt;b&gt;컴포넌트는 매번 새롭게 할당되지 않습니다.&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴포넌트 안에 컴포넌트를 생성하면 어떻게 될까요&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1668081924570&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Parent(){
	function Child(){
    	return &amp;lt;div&amp;gt;Im Child!&amp;lt;/div&amp;gt;
    }
    return &amp;lt;Child/&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Child는 Parent가 &quot;렌더링&quot;될 때, 새로운 컴포넌트가 생성이 되어지고, return ,즉&amp;nbsp; Render하는 부분에서 새로운 Component가 생성되어 넘어갑니다. 다른 말로하면 매번 새로운 Reference값이 넘어가는거죠. 이렇게되면, 아래에 있는 모든 DOM노드들은 &lt;b&gt;새롭게 다시 그려지는 비효율이 발생합니다. HOC와 다릅니다 . HOC는 Component 객체를 넘기는거지, &amp;lt;Child&amp;gt;즉, 렌더를 하는게 아닙니다.&lt;/b&gt;&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;&lt;b&gt;절대 Never , Ever 컴포넌트 안에 컴포넌트를 생성하는 일이 없어야 한다고 Mark아저씨는 이야기 합니다. &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아래와 같이, 분리를 하는게 좋습니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668082184333&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Child(){
	return&amp;lt;div&amp;gt;Hi&amp;lt;/div&amp;gt;
}

function Parent(){
	return &amp;lt;Child/&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한가지 예시는 아쉬우니까, &amp;nbsp;&lt;b&gt;TodoList에 뭔가를 추가하게 될 때 최적화를 생각해볼까요! (댓글이라고 생각해도 재밌겠네요.)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TodoList가 간단하게 있다고 하고, 2초마다 지속적으로 TodoList가 하나씩 추가되는 Interval을 주었다고 해봅시다.&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;&lt;b&gt;TodoList.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668084442509&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import TodoItem from &quot;./Todoitem&quot;;

const Todos = [
  { id: 1, doing: &quot;wash&quot; },
  { id: 2, doing: &quot;Coffee&quot; },
  { id: 3, doing: &quot;Yes&quot; },
  { id: 4, doing: &quot;No&quot; },
  { id: 5, doing: &quot;Swimming&quot; }
];

function TodoList() {
  const [Todo, setTodo] = React.useState(Todos);
  
  React.useEffect(() =&amp;gt; {
    const IntervalId = setInterval(() =&amp;gt; {
      setTodo((prev) =&amp;gt; [
        ...prev,
        { id: `${prev.length + 1}`, doing: &quot;newJob&quot; }
      ]);
    }, 2000);
    return () =&amp;gt; clearInterval(IntervalId);
  }, []);
  
  return (
    &amp;lt;div&amp;gt;
      {Todo.map((items) =&amp;gt; (
        &amp;lt;TodoItem key={items.id} props={items.doing} /&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}

export default TodoList;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TodoItem .jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1668084506195&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function TodoItem({ props }) {
  console.log(&quot;TodoItem is Render!&quot;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;{props}&amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default TodoItem;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TodoItem은 상위 TodoItem.jsx의 state가 바뀌기 때문에, 리렌더링이 되고, 그에 따라서 자식인 TodoItem 아래의 모든 자식들이 ReRendering 됩니다. &lt;b&gt;렌더링 되는 횟수를 보시면 어마무시합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어떻게 최적화 시킬 수 있을까요 ? &lt;/b&gt;&amp;nbsp;이럴 때도, HOC를 설계해서 분리하고 해서 최적화를 해줄 수 있습니다만, &lt;b&gt;생각보다 쉬운듯 어렵습니다. 저는 솔직히 아이디어가 떠오르지 않습니다.&amp;nbsp; &lt;/b&gt;그래서, 저는 Memo를 써주겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, props로써 , 함수가 오는 상황이 있을 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1668086859329&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
function TodoItem({ props }) {
  console.log(&quot;TodoItem is Render!&quot;);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;{props}&amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default React.memo(TodoItem);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수는 매번 렌더링 될 때마다, 새로운 ref를 생성하므로, Memo가 올바르게 동작하지 않습니다. 따라서, useCallback이라는 또 다른 Hook을 사용해서, 최적화 시키면 됩니다!&lt;/b&gt;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web Front-end/React</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/355</guid>
      <comments>https://dailymapins.tistory.com/355#entry355comment</comments>
      <pubDate>Thu, 10 Nov 2022 22:29:40 +0900</pubDate>
    </item>
    <item>
      <title>[React/Composition] 리액트 컴포넌트의 확장(React Composition)</title>
      <link>https://dailymapins.tistory.com/354</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React를 잘 사용하기 위해서는 , 컴포넌트 설계능력이 필수적이게 된다.&amp;nbsp; 이건 경험적인 요소라 많이 쓸수록 자연스럽게 늘어나겠지만, 한번 의식적으로 확장을 해보자!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;웹 환경에서의 재사용&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹에서는 생각보다 반복적인 작업이 많다. 예를들어, 아래와 같은 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Modal 창&lt;/b&gt;&lt;/span&gt;을 구현한다고하자. Modal창은 구체화되서, &lt;b&gt;&quot;로그인창&quot;&lt;/b&gt;이 될 수도 있고, &quot;&lt;b&gt;상세정보를 보여주는 Modal창&quot;&lt;/b&gt;이 될 수도있다. 물론 , 각각 폴더로 분리해서 각각의 Component로 구현해도 무방하다. 하지만, 이번에는 &quot;의도적&quot;으로 Modal창을 추상화시키고, Login창과 Detail창을 구현해보도록 하겠습니다. &lt;b&gt;마치 &quot;상속&quot;과 비슷하지 않나요!&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1145&quot; data-origin-height=&quot;429&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi2TX2/btrQuNJRJcW/bK1NsKojlFjAVHD1AFuYs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi2TX2/btrQuNJRJcW/bK1NsKojlFjAVHD1AFuYs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi2TX2/btrQuNJRJcW/bK1NsKojlFjAVHD1AFuYs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi2TX2%2FbtrQuNJRJcW%2FbK1NsKojlFjAVHD1AFuYs0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;1145&quot; height=&quot;429&quot; data-origin-width=&quot;1145&quot; data-origin-height=&quot;429&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;React에서는 상속대신 , Composition&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://reactjs.org/docs/composition-vs-inheritance.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://reactjs.org/docs/composition-vs-inheritance.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667782339330&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Composition vs Inheritance &amp;ndash; React&quot; data-og-description=&quot;A JavaScript library for building user interfaces&quot; data-og-host=&quot;reactjs.org&quot; data-og-source-url=&quot;https://reactjs.org/docs/composition-vs-inheritance.html&quot; data-og-url=&quot;https://reactjs.org/docs/composition-vs-inheritance.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bvo7aH/hyQvhWi4Bf/i8pBBtbwbxmri5OK6MDNJK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://reactjs.org/docs/composition-vs-inheritance.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactjs.org/docs/composition-vs-inheritance.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bvo7aH/hyQvhWi4Bf/i8pBBtbwbxmri5OK6MDNJK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Composition vs Inheritance &amp;ndash; React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A JavaScript library for building user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactjs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;React에서는 상속대신 , 컴포넌트끼리의 합성&lt;/b&gt;을 권장하고 있습니다. 저는 위의 예시처럼, Modal창을 이용해서 여러가지 Modal을 구체화시켜보겠습니다.&amp;nbsp;&lt;b&gt;Title과 Description을 갖고있는 Modal이라는 틀&lt;/b&gt;에 ,&lt;b&gt; 내가 구현한 JSX를 주입하는 식&lt;/b&gt;으로 구현해보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;초기버전&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Modal.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667787699879&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Modal(props) {
  return (
    &amp;lt;div className=&quot;modal&quot;&amp;gt;
      &amp;lt;div className=&quot;modal_wrapper&quot;&amp;gt;
        &amp;lt;div className=&quot;title&quot;&amp;gt;TEST&amp;lt;/div&amp;gt;
        &amp;lt;div className=&quot;description&quot;&amp;gt;TEST&amp;lt;/div&amp;gt;
        {props.children}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal이라는 창안에 , &lt;b&gt;props.children의 JSX를 그대로 던져주면서, 더 큰 &quot;확장성&quot;&lt;/b&gt;을 노려볼 수 있게 되었습니다. LoginModal창을 간단하게 만들어보겠습니다.&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;&lt;b&gt;LoginModal.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667788035271&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Login(){
  return(
    &amp;lt;Modal&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;label htmlFor='id'&amp;gt;ID:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;id&quot;&amp;gt;&amp;lt;/input&amp;gt;
        &amp;lt;br&amp;gt;&amp;lt;/br&amp;gt;
        &amp;lt;label htmlFor='pw'&amp;gt;PW:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;pw&quot;&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/Modal&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6dQDh/btrQyvBP5MN/fP3xjMLmsMuFy05qCMDdSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6dQDh/btrQyvBP5MN/fP3xjMLmsMuFy05qCMDdSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6dQDh/btrQyvBP5MN/fP3xjMLmsMuFy05qCMDdSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6dQDh%2FbtrQyvBP5MN%2FfP3xjMLmsMuFy05qCMDdSk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;394&quot; height=&quot;405&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;431&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흠.. 뭔가 아쉽습니다. 제가 원한건 ,&lt;b&gt; Title과 Description도 , 서비스의 종류에 따라 바꾸고 싶습니다.&amp;nbsp;&lt;/b&gt;&lt;b&gt;modal을 더 확장시켜보겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1차 확장시킨 Modal&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Modal.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667788096013&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Modal(props) {
  return (
    &amp;lt;div className=&quot;modal&quot;&amp;gt;
      &amp;lt;div className=&quot;modal_wrapper&quot;&amp;gt;
        &amp;lt;div className=&quot;title&quot;&amp;gt;{props.title}&amp;lt;/div&amp;gt;
        &amp;lt;div className=&quot;description&quot;&amp;gt;{props.description}&amp;lt;/div&amp;gt;
        {props.children}
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Title과 description&lt;/b&gt;도&lt;b&gt; props.title,props.description&lt;/b&gt;으로 확장을 했습니다. 이제, Login Modal에서 Login을 줘볼까요!&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;&lt;b&gt;Login.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667788206063&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Login(){
  return(
    &amp;lt;Modal title=&quot;Login&quot; description=&quot;Login&quot;&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;label htmlFor='id'&amp;gt;ID:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;id&quot;&amp;gt;&amp;lt;/input&amp;gt;
        &amp;lt;br&amp;gt;&amp;lt;/br&amp;gt;
        &amp;lt;label htmlFor='pw'&amp;gt;PW:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;pw&quot;&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/Modal&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제, &lt;b&gt;Detail 모달창을 만드려면 어떻게하면 될까요?&lt;/b&gt;&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;&lt;b&gt;DetailModal.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667788325940&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react'
import Modal from './Modal'
export default function DetailModal() {
  return (
    &amp;lt;Modal title=&quot;Detail&quot; description=&quot;디테일창&quot;&amp;gt;
      &amp;lt;div&amp;gt;디테일 창입니다~&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;사진사진~!&amp;lt;/div&amp;gt;
    &amp;lt;/Modal&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;454&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOXUuC/btrQyWszmee/awf0Ixh1hBjS0BNDZOiPx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOXUuC/btrQyWszmee/awf0Ixh1hBjS0BNDZOiPx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOXUuC/btrQyWszmee/awf0Ixh1hBjS0BNDZOiPx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOXUuC%2FbtrQyWszmee%2Fawf0Ixh1hBjS0BNDZOiPx0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;454&quot; height=&quot;441&quot; data-origin-width=&quot;454&quot; data-origin-height=&quot;441&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;App.js에서 DetailModal을 부르기만하면 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2차로 확장시켜보자&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal 창은 보통, 버튼으로 구현이 됩니다. 각각의 버튼을 눌러서, &lt;b&gt;Login -&amp;gt; Login Modal을 뜨게하고, Detail -&amp;gt; Detail을 뜨게만들면되겠죠! &lt;/b&gt;간단하게 , App.jsx에서 State를 정해준 뒤에,&amp;nbsp; &lt;b&gt;Modal.jsx에 열려있는지 , 아닌지에 따라서, 화면을 바꿔주는 연습을 해보겠습니다.&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;Flow : 메인화면 -&amp;gt; 버튼클릭 -&amp;gt; Modal창들 보여주기 -&amp;gt; 취소시 원래화면으로 복귀&lt;/b&gt;&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;&lt;b&gt;App.jsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667790109612&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Dimmed(){
  return (
    &amp;lt;div className=&quot;dimmed&quot;&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
function App() {
  const [LoginOpen,setLoginOpen] = React.useState(false)
  const [DetailOpen,setDetailOpen] = React.useState(false)

  const handleDetailModal = () =&amp;gt;{
    setDetailOpen((prev)=&amp;gt;!prev)
  }
  const handleLoginModal = () =&amp;gt;{
    setLoginOpen((prev)=&amp;gt;!prev)
  }
  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;button onClick={handleLoginModal}&amp;gt;로그인창&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={handleDetailModal}&amp;gt;상세창&amp;lt;/button&amp;gt;
      {/*로그인창 클릭시*/}
      {LoginOpen ? &amp;lt;Login handler={handleLoginModal}/&amp;gt;:null}
      {/*상세창 클릭시*/}
      {DetailOpen? &amp;lt;DetailModal handler={handleDetailModal}/&amp;gt;:null}
      {/*Dimmed 처리*/}
      {LoginOpen || DetailOpen ? &amp;lt;Dimmed&amp;gt;&amp;lt;/Dimmed&amp;gt;: null}
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Login.jsx&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;props가 점점 늘어나고 있네요! 흠.. 좋지않은 징조입니다.&amp;nbsp; 태그가 Heavy하면 나중에 좋지 않거든요!&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667790234995&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';
import Modal from './Modal';

export default function Login(props){
  return(
    &amp;lt;Modal title=&quot;Login&quot; description=&quot;Login&quot; handler={props.handler}&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;label htmlFor='id'&amp;gt;ID:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;id&quot;&amp;gt;&amp;lt;/input&amp;gt;
        &amp;lt;br&amp;gt;&amp;lt;/br&amp;gt;
        &amp;lt;label htmlFor='pw'&amp;gt;PW:&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;pw&quot;&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/Modal&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Modal.jsx&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;button에 드디어 handler를 전달했습니다. &lt;b&gt;컴포넌트를 타고타고 들어가는게 너무 번거롭네요 .&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667790299228&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';
import '../../css/modal.css';

export default function Modal(props) {
  //console.log(props)
  return (
    &amp;lt;div className=&quot;modal&quot;&amp;gt;
      &amp;lt;div className=&quot;modal_wrapper&quot;&amp;gt;
        &amp;lt;div className=&quot;title&quot;&amp;gt;{props.title}&amp;lt;/div&amp;gt;
        &amp;lt;div className=&quot;description&quot;&amp;gt;{props.description}&amp;lt;/div&amp;gt;
          {props.children}
          &amp;lt;button className=&quot;button&quot; onClick={props.handler}&amp;gt;취소&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;잠깐잠깐! 뭔가, 더 번거롭고, 복잡해진 느낌이 들지 않나요 ?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희는 &lt;b&gt;재사용성을 위해서,Modal을 컴포넌트화 시키고, Login,Detail에 따라서 다른 view를 구현해줬습니다. 그리고, Modal은 어떤 버튼을 클릭한 후, 해당 Modal창을 띄우는게 일반적이라서, 버튼을 기반으로 onClick으로 이벤트를 구성했습니다.&lt;/b&gt;&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;&lt;b&gt;하지만, &quot;취소&quot;버튼은 최하위인 Modal Component에서 해줘야했습니다. 그런데, 부모의 상태를 자식이 알려면, props를 drilling 해줘야합니다. 지금은 &lt;/b&gt;&lt;b&gt;1~2depth정도 밖에 되지 않습니다만, 웹 페이지는 수많은 기능을 갖고있고, 수많은 wrapper와 component를 갖고있을 수 있습니다. 즉 , 6~7depth까지도 가능할 수 있다는 이야기죠.&lt;/b&gt;&lt;/p&gt;

            &lt;figure class=&quot;unsupported component-kakaotv&quot; contenteditable=&quot;false&quot; style=&quot;background:#000;margin:16px 0;min-height:72px;padding:10px 16px;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box;width:100%;max-width:100%;&quot;&gt;
                &lt;p contenteditable=&quot;false&quot; style=&quot;margin:0;color:#8a8a8a;font-size:13px;line-height:1.6;user-select:none;pointer-events:none;&quot;&gt;동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.&lt;/p&gt;
            &lt;/figure&gt;
        
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;왜 Drilling이 생길 수 밖에 없을까 ?&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;데이터 흐름을 따라가보면 됩니다.&amp;nbsp; &lt;/b&gt;&lt;b&gt;App.js에서 해당 창을 띄울지 안띄울지 판단 -&amp;gt; 자식 컴포넌트에서 , 부모 컴포넌트 State를 조작해야함 -&amp;gt; State가 false가 되면, 원래 창으로 복귀&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 재사용성을 위해 컴포넌트를 분리한다는 이야기는 , Component -&amp;gt; Component 와 같이, 부모-자식관계가 끊임없이 생기는 것입니다. 즉 , 추상화를 시키니까 State 관리가 힘들어졌습니다.&amp;nbsp; 그리고, React가 추구하는 단방향성 데이터 흐름이 깨졌습니다. &lt;/b&gt;이래서, State를 관리하기 위한 Redux, Recoil 등의 상태관리가 생기게 된 것입니다! (Redux -&amp;gt; Flux 모델)&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;다음 글에서는&lt;b&gt; React Component의 상태관리 Redux, useReducer 등을 공부&lt;/b&gt;해보겠습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Web Front-end/React</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/354</guid>
      <comments>https://dailymapins.tistory.com/354#entry354comment</comments>
      <pubDate>Mon, 7 Nov 2022 12:17:48 +0900</pubDate>
    </item>
    <item>
      <title>[JS/비동기/프로미스] JavaScript Promise에 대해서</title>
      <link>https://dailymapins.tistory.com/353</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 Front-End의 중요한 영역인 Data Fetching 에서 사용되는 Promise 문법에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Promise&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프로미스는 비동기 작업의 &lt;b&gt;최종 완료 또는 실패를 나타내는 객체입니다. - MDN&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;promise는 ES6에서 나온 새로운 기능&lt;/b&gt;으로, 어떤 &quot;문제점&quot;을 해결하기 위해서, 나온 기능입니다. 즉, 그 문제점이 뭐냐를 이해하면 Promise의 정체를 밝힐 수 있을 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Promise의 등장배경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;작은 규모의 웹에서는 비동기 요청이 많지 않아서, 각 비동기 요청간의 의존성이 크지 않았다고 합니다&lt;/b&gt;. 웹이 발전하고, 다양한 플랫폼으로 진출하면서 , 단순히 callback만으로는 모든 상태를 통제하기 어려웠다고 합니다. 예를들어, 로그인 과정에서&lt;b&gt; 서버와 통신과정이 필요&lt;/b&gt;합니다.&lt;b&gt; 세션 로그인방식&lt;/b&gt;이라고 생각해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;로그인 과정&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Client]&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로그인 페이지에서, 아이디, 비밀번호를 서버로 POST&lt;/b&gt; 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Server]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버는 기존에 회원가입을 한 사람이면, 서버에서 세션아이디를 만들어줍니다.&lt;/li&gt;
&lt;li&gt;세션 아이디를 담을 변수와 DB공간을 마련해서, 거기에 저장합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;쿠키 안에 Portion해서, Request한 브라우저에 쿠키를 Push해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Client]&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;mypage(로그인 해야만 들어갈 수 있는, 회원페이지)를 요청합니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Server]&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;서버는 해당 요청을 받으면&lt;/b&gt; 일단 로그인 했는지 여부를 확인해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;쿠키에 세션 아이디가 포함되어 있는지 검사&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;만약, 있으면 통과시켜주고 그 과정에서 회원의 이름, 나이, 성별 등의 DB정보가 필요하면 꺼내옴&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, Client의 동작은 연속적으로 일어나야하는걸 알 수 있습니다. &lt;b&gt;즉, client -&amp;gt;아이디, 비밀번호를 Post 한 뒤 쿠기가 Push되면 mypage를 요청합니다.&amp;nbsp; 이때, 브라우저가 멈추면 안되기 때문에, 서버와의 통신은 비동기적으로 일어나게 됩니다. 즉, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;비동기가 연속적으로 일어나야 합니다.&lt;/span&gt;&amp;nbsp; &lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;연속적인 비동기의 문제점(Callback Chain)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;비동기가 연속적으로 일어난다는 이야기는 , callback을 연속적으로 던져줘야했다는 이야기입니다. 그리고&lt;span style=&quot;background-color: #dddddd;&quot;&gt; callback함수로 구현되어지는 비동기 함수는 JS의 실행흐름에 의해서, 따로 분리가 될 수 없습니다.&lt;/span&gt;&amp;nbsp; 왜냐하면,&amp;nbsp; 결과값을 받는 순간을 예측할 수 없기 때문입니다.&amp;nbsp; &lt;/b&gt;즉 , 아래와 같이 코드를 짜야한다는 이야기입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1667197356255&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;UserLogin(()=&amp;gt;{
	//로그인을 한 뒤에, 연속적으로 mypage를 요청해야한다.
    UserLogin(()=&amp;gt;{
    
	})
},1000)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 중첩에 중첩에 중첩을 계속하게되면,&lt;b&gt; 유명한 &quot;콜백지옥&quot;이 완성&lt;/b&gt;됩니다.&amp;nbsp;&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;가독성도 물론 엄청 떨어지지만, 근본적인 원인은 &lt;b&gt;비동기 안에 연속적으로 일어나는 ,또 다른 비동기 로직들을 분리할 수 없던게 문제&lt;/b&gt;였습니다.&amp;nbsp; 그래서, 비동기를 요청한 뒤 , 결괏값을 기억하고 있는 방식으로 구현하기로 했습니다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 &lt;b&gt;비동기 함수 안에 연속적으로 일어나는 로직들을 분리할 수 있는 방식&lt;/b&gt;이&lt;b&gt; 바로 Promise&lt;/b&gt;입니다.&amp;nbsp; 그래서, promise는 비동기 요청을 해놓고, 나중에 then()을 통해서, 결과값을 받을 수 있게 됩니다. 이 말을 다르게 해볼까요 .&lt;span style=&quot;background-color: #dddddd;&quot;&gt; &lt;b&gt;&quot;미래의 어떤 시점에 결과를 제공하는 약속을 하겠다&quot; ==&amp;gt; 그래서,&amp;nbsp; Promise 입니다.&lt;/b&gt;&lt;/span&gt;&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;&lt;b&gt;유명한 callbackHell을 Promise로 바꾸어보기&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (12).jpg&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D2QNE/btrP6hDMBJE/YvugMBFqTacUXeJXc6khGK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D2QNE/btrP6hDMBJE/YvugMBFqTacUXeJXc6khGK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D2QNE/btrP6hDMBJE/YvugMBFqTacUXeJXc6khGK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD2QNE%2FbtrP6hDMBJE%2FYvugMBFqTacUXeJXc6khGK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;670&quot; height=&quot;366&quot; data-filename=&quot;My First Board (12).jpg&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (13).jpg&quot; data-origin-width=&quot;1395&quot; data-origin-height=&quot;716&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhLNf3/btrP7UVOvHk/oJjKRC9mHJaQ304g7zufj1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhLNf3/btrP7UVOvHk/oJjKRC9mHJaQ304g7zufj1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhLNf3/btrP7UVOvHk/oJjKRC9mHJaQ304g7zufj1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhLNf3%2FbtrP7UVOvHk%2FoJjKRC9mHJaQ304g7zufj1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;667&quot; height=&quot;342&quot; data-filename=&quot;My First Board (13).jpg&quot; data-origin-width=&quot;1395&quot; data-origin-height=&quot;716&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로그인하는 예제&lt;/b&gt;입니다. &lt;b&gt;서버가 없기 때문에,setTimeout을 이용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;아래와 같이, UserStorage 객체가 준비되어있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667198731155&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class UserStorage{
  loginUser(id,password,onSuccess,onError){
      setTimeout(()=&amp;gt;{
        if(id===&quot;admin&quot; &amp;amp;&amp;amp; password ===&quot;root&quot;){
          onSuccess(id)
        }else{
          onError(new Error(&quot;not Found!&quot;))
        }
      },2000);
  }
  getRoles(user,onSuccess,onError){
    setTimeout(()=&amp;gt;{
      if (user ===&quot;admin&quot;){
        onSuccess({name:&quot;admin&quot;,role:&quot;admin&quot;});
      }else{
        onError(new Error('no Access'));
      }
    },1000)
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;로그인 과정 분석&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;login했을 때, 성공시에 해당 유저의 권한을 부여&lt;/b&gt;해야합니다. 따라서, onSuccess라는 callback을 던져주는 과정이 필요합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;가독성을 높이기 위해서 , 주석을 달아놨습니다. 하지만, 콜백안에 또 콜백이 있고, 또 콜백이 있고 .. 가독성이 떨어지며 , 프로그래머도 헷갈리기 시작합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;프로그래머가 &quot;헷갈리기 시작&quot;한다 =&amp;gt; 기본적으로 에러날 확률이 높다. 뿐만 아니라, &quot;유지보수&quot;하기가 매우 힘들고, 확장성을 갖기가 힘들다. =&amp;gt; 현재와 같은 고도화된 서비스를 넣기에 충분하지 않다. =&amp;gt; 돈이 되지 않는다. =&amp;gt; &quot;확장성&quot;을 확보하지 않은 코드는 필요가 없다.=&amp;gt; &lt;s&gt;이런 코드를 &amp;nbsp;짜는 사람은 필요가 없다(극단적이지만)&lt;/s&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;즉, 안티 패턴인거죠!&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667269329468&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const userStorage = new UserStorage()

const id = prompt(&quot;아이디 입력&quot;)
const password = prompt(&quot;비밀번호 입력&quot;)


userStorage.loginUser(
	id,
    password,
    //성공 callback
    (user)=&amp;gt;{
    	userStorage.getRoles(
        user,
        //로그인 성공 한뒤, 유저 권한 획득 callback
        (Userdata)=&amp;gt;{
        	alert(`${Userdata.name}님 안녕하세요. ${Userdata.role}권한으로 입장했습니다.`)
        },
        //로그인 한뒤, 유저 권한 획득 실패 callback 
        (error)=&amp;gt;{
        	console.log(&quot;로그인 한뒤, 유저 권한 획득 실패 callback &quot;)
        },
        )
    },
    //error callback
    (error)=&amp;gt;{
    	console.log(&quot;로그인 실패&quot;)
    },
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 문제점을 해결하기 위해서 Promise가 등장했습니다. &lt;b&gt;Promise는 비동기처리를 미리 약속해놓고, 결과값은 &quot;나중에 then을 통해서 너가 원할 때 써라&quot; 입니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Promise의 WorkFlow&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp;Promise는 객체입니다&lt;/b&gt;. 따라서,&lt;b&gt; new 연산자를 통해서 호출&lt;/b&gt;이 됩니다. 내부에 executor이라는 callback함수를 갖고있습니다. executor또한, resolve,reject라는 callback을 갖고있습니다. &quot;콜백 지옥을 해결한다면서 또 콜백을 중첩시키면어쩌자는거야!&quot;라고 할 수 있지만, 진정하고 들어주세요&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667271021577&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const p1 = new Promise((resolve,reject)=&amp;gt;{})&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;Promise의 &lt;b&gt;Executor은 선언되자마자 실행&lt;/b&gt;됩니다. 왜냐하면, Promise또한 객체니까요! new Promise()는 생성자입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (14).jpg&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;823&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5eROT/btrP4uDPPQh/5tTDuTCxDAnlw0oCxcjbLK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5eROT/btrP4uDPPQh/5tTDuTCxDAnlw0oCxcjbLK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5eROT/btrP4uDPPQh/5tTDuTCxDAnlw0oCxcjbLK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5eROT%2FbtrP4uDPPQh%2F5tTDuTCxDAnlw0oCxcjbLK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1214&quot; height=&quot;823&quot; data-filename=&quot;My First Board (14).jpg&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;823&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 로그인 코드를 Promise로 바꾸는 연습을 해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;loginUser&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667271752463&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; loginUser(id, password) {
 	//callback이 아닌, promise를 리턴해준다.
    return new Promise((resolve, reject) =&amp;gt; {
      setTimeout(() =&amp;gt; {
        if (id === &quot;admin&quot; &amp;amp;&amp;amp; password === &quot;root&quot;) {
          resolve(id);
        } else {
          reject(new Error(&quot;error!&quot;));
        }
      }, 2000);
    });
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;getRoles&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667271778232&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  getRoles(user) {
    return new Promise((resolve, reject) =&amp;gt; {
      setTimeout(() =&amp;gt; {
        if (user === &quot;admin&quot;) {
          resolve({ name: &quot;admin&quot;, role: &quot;admin&quot; });
        } else {
          reject(new Error(&quot;no Access&quot;));
        }
      }, 1000);
    });
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667271798809&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const userStorage = new UserStorage();

const id = prompt(&quot;Eneter your id &quot;);
const password = prompt(&quot;Enter your pw ! &quot;);

//then으로 chainning 가능!!
userStorage
  .loginUser(id, password)
  .then(userStorage.getRoles)
  .then((data) =&amp;gt;
    alert(`${data.name}님 환영합니다.${data.role}권한으로 접속했습니다.`)
  )
  .catch(console.log);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, &lt;b&gt;Promise 또한, 작성을 하다보면, then chainning도 엄청 길게 생길 수 있고, promise가 promise를 반환하는 또 ,Promise 지옥이 생길 수 있습니다. Then에서도 Promise를 넘겨주면, 다음 then에서 resolve된 값을 받을 수 있거든요!&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Async Function의 등장&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Promise를 반환해주는 Producer 역할을 하는 함수를 흔하게 작성&lt;/b&gt;합니다.&amp;nbsp; 이와 같은 &lt;b&gt;함수들은 async function으로 작성이 가능&lt;/b&gt;합니다. 즉,&lt;b&gt; async 함수 =&amp;gt; Promise를 Return 해주는 함수&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;await은&lt;/b&gt; async 함수 내에서 사용할 수 있는 키워드로,&lt;b&gt; Promise의 then역할&lt;/b&gt;을 하게 됩니다. 코드의 실행 순서가 오른쪽에서 왼쪽으로 바뀐다고 이야기도 하는데, &lt;b&gt;&quot;delay(3000)이 실행될 때 까지 기다려라!&quot;&lt;/b&gt;라는 이야기 입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1667273297762&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 실행을 ms 만큼 지연시키는 delay
function delay(ms){
	return new Promise((resolve,reject)=&amp;gt;{
    	setTimeout(resolve,ms)
    })
}

async getApple(){
	await delay(3000)
	return &quot;Apple&quot;
}
/* Promise 
function getApple(){
	return delay(3000).then(()=&amp;gt;&quot;Apple&quot;);
}
*/
async getBanana(){
	await delay(3000)
    return &quot;banana&quot;
}
/* Promise 
function getbanana(){
	return delay(3000).then(()=&amp;gt;&quot;Banana&quot;);
}
*/

pickFruits().then(console.log);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Async Function의 편리함&lt;/b&gt;&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;위와같은 Promise(Async 함수)들이 있을 때, 모든 Promise를&amp;nbsp; 논리적으로 한 동작으로 묶어야할 필요가 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, &quot;사과를 딴 뒤에, 바나나를 따고, 그 둘을 출력한다&quot; 와 같이, 이전 &lt;b&gt;Promise의 scope가&lt;/b&gt; 필요할 때, 유용하게 쓸 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1667273737201&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function AsyncpickFruits(){
	const apple = await getApple()
    const banana = await getBanana()
    return `Fruits: ${apple} , ${banana}`
	
}
/* Promise 
function pickFruits (){
	return getApple()
    .then((apple)=&amp;gt;{
    	return getBanana().then(banana=&amp;gt;`Fruits: ${apple} , ${banana}`)
    })
}
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;병렬적으로 처리하기&lt;/b&gt;&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;흠..근데, 굳이 사과를 따고나서, 바나나를 따야할까요?&amp;nbsp; 아니죠! 사과와 바나나는 동시에 딸 수 있습니다. promise.all 혹은 ,promise.allSettled와 같은 메소드를 이용해서, &lt;b&gt;promise들을 한꺼번에 처리&lt;/b&gt;할 수 있습니다!&lt;/p&gt;
&lt;pre id=&quot;code_1667273952153&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function pickAllFruits(){
	return new Promise.allsettled([getApple(),getBanana()])
	.then((fruits)=&amp;gt;fruits.join(','))
}
pickAllFruits().then(console.log)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3줄 정리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Promise는 비동기 상태를 &quot;값&quot;으로 다룰 수 있게 한다는 점이 제일 큰 장점이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&quot;값&quot;으로 다룬 다는 이야기는 변수에 담고, 매개변수에도 넣을 수 있는 1급 객체로 다룬다는 이야기고, 이건 내가 원할 때, &lt;b&gt;비동기 상태의 값들을 쓸 수 있다이야기 입니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;여러개의 Promise를 묶어서, 병렬적으로 처리할 수도 있고, Async/await를 써서, Promise의 then chain지옥을 빠져나갈 수도 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은, Promise의 장점을 활용하여 비동기 상태를 여러 함수를 합성하는 걸 보겠습니다. 그리고, 그걸 가능하게 하는 Monad의 개념에 대해서 간단하게 알아보겠습니다!&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;&lt;b&gt;refer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=1DGAyl4kxhY&amp;amp;t=346s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;제로초님 JS고급강의&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=aoQSOZfz3vQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;엘리님 JS 비동기 강의&lt;/a&gt;&lt;/p&gt;</description>
      <category>Web Front-end/JavaScript</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/353</guid>
      <comments>https://dailymapins.tistory.com/353#entry353comment</comments>
      <pubDate>Tue, 1 Nov 2022 12:39:55 +0900</pubDate>
    </item>
    <item>
      <title>[Python/Django/Framework] Django , WebFramwork에 대해서</title>
      <link>https://dailymapins.tistory.com/352</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Airbnb 클론코딩을 진행하면서, 다양한 개념에 대해서 알게되는것 같습니다! 오늘은 WebFrameWork 장고에 대해서, 배운걸 기록해보겠습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;WebFramWork&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FrameWork는&lt;/b&gt; &quot;&lt;b&gt;모든 레고가 준비되어 있는 큰 레고상자&quot;&lt;/b&gt;라고 생각하면 저는 더 와닿았습니다. 특히,&lt;b&gt; &quot;조립법&quot;&lt;/b&gt;까지 모두 정해져있는 레고상자입니다. &quot;FrameWork&quot;는 정해진 사용법이 있다는게 &lt;b&gt;라이브러리와 큰 차이점&lt;/b&gt;인 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 내에서의 차이점을 보자면, &lt;b&gt;라이브러리는&lt;span style=&quot;background-color: #dddddd;&quot;&gt; 프로그래머가 가져와서 쓰고&lt;/span&gt;&lt;/b&gt; ,&lt;b&gt; FrameWork는 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;프로그래머가 작성한 코드를 가져갑니다.&lt;s&gt;(이게 무슨말이야)&lt;/s&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;s&gt;&lt;/s&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span&gt;즉, 라이브러리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;라이브러리 내의 일종의 함수를 내가 import해서 활용하는 측면이 강하다면&lt;/b&gt;, FrameWork는&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이미 활용법이 정해져 있는 함수와 필드값내에서&lt;/b&gt;, 그 함수에 프로그래머가 직접 코드를 작성하고, 그 코드를 기반으로 동작한다는 이야기 입니다. 프레임워크를 직접 수정할 수 있지만, 절대 권장되지 않습니다. 왜냐하면, 장고 프로젝트를 실행하기 위해서는 Django가 필요한데 , 프레임워크를 수정한 상태라면, 설치되는 PC의 Django 또한 Custom되어야하기 때문입니다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Django&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Django는 Python으로 이루어진 FrameWork입니다. Django는 다양한 기능들을 프로그래머가 직접 구현할 필요없이 , 이미 내제되어 있는 기능들이 많습니다. Django는 객체지향을 기본으로 하는 FrameWork입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Django Project의 구성&lt;/b&gt;&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;Django는 Project 1개에 여러가지 App들이 결합되는 형태로 구성이 됩니다.&lt;b&gt; App은 Data와 Logic이 묶인 하나의 모듈&lt;/b&gt;이라고 생각하면 됩니다. 그리고, &lt;b&gt;Django는 Setting.py를 통해서 , App들을 서로 연결하고 하나의 서비스&lt;/b&gt;로 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;manage.py&lt;/b&gt;는 &lt;b&gt;Terminal에서 &quot;Django 명령어가 실행될 수 있게끔&quot; 해주는 파일&lt;/b&gt;입니다.&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;&lt;b&gt;명령어&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;django-admin startproject [name] [directory]&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (4).jpg&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;868&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxhwsW/btrPK5KmwPU/rbZqHQCYkWvdsmguLBXEuk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxhwsW/btrPK5KmwPU/rbZqHQCYkWvdsmguLBXEuk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxhwsW/btrPK5KmwPU/rbZqHQCYkWvdsmguLBXEuk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxhwsW%2FbtrPK5KmwPU%2FrbZqHQCYkWvdsmguLBXEuk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;651&quot; height=&quot;491&quot; data-filename=&quot;My First Board (4).jpg&quot; data-origin-width=&quot;1151&quot; data-origin-height=&quot;868&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Django App의 구성 &lt;/b&gt;&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;&lt;b&gt;App을 생성하면, model, Admin, Migration,view 등이 생성되게 됩니다.&amp;nbsp; Data는 Model에서 담당합&lt;/b&gt;니다.&amp;nbsp; DB와 연동을 위해서 Migration을 생성하고, Migrate 작업이 필요합니다. 이때, 생성되는 Migration은 Model에 정의된 코드를 기반으로 생성되게 됩니다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;b&gt;Admin&lt;/b&gt;은 장고에서 기본적으로 제공해주는 Admin page를 커스텀할 수 있게 해줍니다. View는 저희가 아는 그 View(화면)입니다.&amp;nbsp;&lt;/span&gt;&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;&lt;b&gt;* Migration&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Application을 개발하다보면, DataBase의 스키마를 변경할 일이 빈번하게 발생합니다. 예를들어, 새로운 서비스를 추가하기 위해서, 테이블의 컬럼(Atrribute)를 추가하거나, 다른 테이블을 생성하거나, 심지어 데이터가 현재의 도메인 구조와 다르다면, 모든 데이터 값을 수정해야 할 수도 있습니다. (기존에 있던 데이터들은 새로운 Column이 생기는 경우) 이러한 과정을 Migration이라고 합니다. &lt;b&gt;즉, 서버에서 DB로 접근하여 DB를 Control하는 과정이라고 볼 수 있습니다. 장고에서는 모델수정(Data) -&amp;gt; make migration -&amp;gt; migrate -&amp;gt; DB 적용의 순서입니다.&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 아키텍쳐, 좋은 설계가 왜 중요한지 점점 더 알게되는 것 같습니다. 데이터의 무결성, 데이터의 중복방지 등, 데이터베이스 설계에 대한 공부도 꾸준히 해야할 것 같습니다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/352</guid>
      <comments>https://dailymapins.tistory.com/352#entry352comment</comments>
      <pubDate>Thu, 27 Oct 2022 23:24:40 +0900</pubDate>
    </item>
    <item>
      <title>[python/poetry/Django] Python Webproject 셋팅하기 -1</title>
      <link>https://dailymapins.tistory.com/351</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;클론코딩을 진행하면서, ToyProject들을 진행해보려고 합니다.큰 마음을 먹고, 백엔드부터, 프론트까지 다 해볼 수 있는 노마드코더님의 Airbnb클론코딩을 질렀습니다!&amp;nbsp;&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;&lt;b&gt;기본적인 강의 내용을 자세하게 포스팅 하기보단, 제가 부딪혔던 문제들을 위주로 ,기록&lt;/b&gt;해보려고 합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Python Project 설정&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Poetry 다운로드&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;패키징 시스템 중 하나&lt;/b&gt;입니다. 각각의 프로젝트에 대해서, 독립적인 개발환경을 만들어줍니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;프로젝트에 따라서, 필요한 환경이 다르기 때문에, 독립적인 개발환경이 필요하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Poetry를 다운로드하면, 환경변수를 등록&lt;/b&gt;해주어야 합니다. 설치를 확인하기 위해,&amp;nbsp; &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;poetry --version을 입력하면, 실행할 수 없는 명령어&lt;/b&gt;&lt;/span&gt;라고 나올 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;환경변수 설정하기&lt;/b&gt;&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;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;[STEP1] &lt;/span&gt;&lt;/b&gt;윈도우키를 눌러, &lt;b&gt;고급 시스템 설정보기&lt;/b&gt;를 검색합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;[STEP2]&lt;/span&gt; 고급 탭&lt;/b&gt;을 선택한 후, &lt;b&gt;환경 변수를 선택&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;[STEP3]&lt;/span&gt; 환경변수(N).. 클릭&lt;/b&gt; 후, 시스템 변수에 Path를 클릭한 후, 편집을 누릅니다.\&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;[STEP4]&lt;/span&gt; 새로 만들기(N)를 클릭 한 후&lt;/b&gt;, &lt;b&gt;Poetry Docs에서 안내하고 있는 경로&lt;/b&gt;를 등록해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경로가 2개가 있는데, 하나씩 등록해보고, poetry --version을 쳐보시면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;%APPDATA%\Python\Scripts&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;%APPDATA%\pypoetry\venv\Scripts\poetry&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 완료되면, 아래와 같이 version이 뜨게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cljxNY/btrPmE8Ntva/VjQO6aECw2AZxd0iWxT1WK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cljxNY/btrPmE8Ntva/VjQO6aECw2AZxd0iWxT1WK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cljxNY/btrPmE8Ntva/VjQO6aECw2AZxd0iWxT1WK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcljxNY%2FbtrPmE8Ntva%2FVjQO6aECw2AZxd0iWxT1WK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;44&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;44&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;가상환경(개발환경)에 필요한 패키지 다운받기&lt;/b&gt;&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;poetry 연결이 되었으면, poetry도 init(초기화)를 통해서, &lt;b&gt;.toml 파일을 만들어줘야합니다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;poetry init&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;poetry init하면 설정들을 할 겁니다. &lt;b&gt;본인의 필요에 맞게 설정&lt;/b&gt;하면 됩니다.&lt;b&gt; toml이 생성&lt;/b&gt;이 성공적으로 되었으면, django를 다운받아줍니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;poetry add django&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;poetry shell로 접속하기&lt;/b&gt;&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;poetry는 가상환경이기 때문에,&lt;b&gt; poetry안에 접속해서 django를 실행&lt;/b&gt;해야 합니다. 따라서, poetry shell이라는 명령어를 실행한 뒤, django를 실행해야합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;poetry shell&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;poetry shell로 접속이 되었으면,&lt;b&gt; django-admin으로 django가 성공적으로 동작하는지 Test&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RUh4Q/btrPoQVuIcY/0KIxkJ8yZTwDOSNZuhbjqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RUh4Q/btrPoQVuIcY/0KIxkJ8yZTwDOSNZuhbjqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RUh4Q/btrPoQVuIcY/0KIxkJ8yZTwDOSNZuhbjqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRUh4Q%2FbtrPoQVuIcY%2F0KIxkJ8yZTwDOSNZuhbjqK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;643&quot; height=&quot;188&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;* &lt;b&gt;Error&amp;nbsp;&lt;/b&gt;&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;여기서, &lt;b&gt;권한이 없다고 오류가 날 수 있습니다&lt;/b&gt;.&lt;b&gt; powershell에서 ExcutionPolicy가 Restricted로 설정&lt;/b&gt;되어 있어서 그렇습니다. (Restricted가 기본값입니다) 권한은 바꿔주면 되겠죠? 저희는 admin이니까요!&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;Policy는 아래와 같이 준비되어 있습니다. 원하는걸로 하면 되지만, &lt;b&gt;저는 RemoteSigned&lt;/b&gt;를 하겠습니다.&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;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Restricted&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;: PowerShell의 실행 권한 정책 중 기본적으로 적용되어있는 옵션. ps1 스크립트 파일을 로드하여 실행할 수 없는 정책&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;AllSigned&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;: 신뢰된 배포자에 의해 서명된 스크립트만 실행 할 수 있는 정책&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;RemoteSigned&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;: 로컬 컴튜퍼에서 본인이 생성한 스크립트만 실행 가능 또는 인터넷에서 다운로드 받은 스크립트는 신뢰된 배포자에 의해 서명된 것만 실행 가능한 정책&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Unrestricted&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;: 제한 없이 모든 스크립트 실행 가능한 정책&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;ByPass&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;: 어떤 것도 차단하지 않고 경고 없이 실행 가능한 정책&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Undefined&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;:&amp;nbsp;정책&amp;nbsp;적용&amp;nbsp;안함&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Set-ExecutionPolicy RemoteSigned&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Project</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/351</guid>
      <comments>https://dailymapins.tistory.com/351#entry351comment</comments>
      <pubDate>Mon, 24 Oct 2022 14:32:50 +0900</pubDate>
    </item>
    <item>
      <title>[git/git-hub] 개발한 결과물을 관리해보자(Git)</title>
      <link>https://dailymapins.tistory.com/350</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Github을 지속적으로 썻지만, git을 CLI로 쓴적은 없습니다. 항상&lt;b&gt; github 홈페이지에 들어가서 페이지가 완성이 되면, 업로드하는 방식&lt;/b&gt;으로 개발을 자주 했다. 혹은 UI tool(Github Desktop)을 이용해서 그냥 commit을 하는 형태로 했다.&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;나의 스킬을 늘리기 위해서, Cli 환경으로 git을 이용해보는 연습을 해보려고 한다. Git hub에 흔적을 남기면서, 이제 프로젝트를 위한 준비단계라고 생각하면 좋을 듯합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Git&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Git은 분산버전관리 시스템&lt;/b&gt;입니다. &lt;b&gt;여러 대의 컴퓨터(여러 명의 프로그래머)에서 하나의 프로젝트&lt;/b&gt;에 대해서 &quot;&lt;b&gt;협업&quot;&lt;/b&gt;을 위해 유용하게 사용할 수 있는 tool입니다.&amp;nbsp; 그림으로 이해를 해보자면, 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (3).jpg&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b039cY/btrPp3FZyJE/sWTyRQrYkwIRvCpPLnA9zk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b039cY/btrPp3FZyJE/sWTyRQrYkwIRvCpPLnA9zk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b039cY/btrPp3FZyJE/sWTyRQrYkwIRvCpPLnA9zk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb039cY%2FbtrPp3FZyJE%2FsWTyRQrYkwIRvCpPLnA9zk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;652&quot; height=&quot;465&quot; data-filename=&quot;My First Board (3).jpg&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터 A,B,C가 모두 같은 작업물에 접근하여, 업데이트 할 수 있게끔 해주는 Tool입니다.&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;&lt;b&gt;Git 설치하기&lt;/b&gt;&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;설치 자체는 간단하다. git 공식홈페이지에 접속해서, &lt;b&gt;OS에 맞게 다운로드&lt;/b&gt;하면 됩니다.&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;&lt;b&gt;Git Cli 환경으로 다루기&lt;/b&gt;&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;Git을 사용하는 방법에는 2가지 방식이 있습니다. Cli(Command Line)을 이용하는 방법 , UI Tool(SourceTree와 같은)을 이용하는 방법이 있습니다.&lt;b&gt; VScode의 Terminal을 이용&lt;/b&gt;할 거기 때문에, &lt;b&gt;Cli 환경을 이용&lt;/b&gt;하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* Tips&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Mac OS를 이용하신다면, Mac에 내장되어있는 Terminal을 그대로 쓰시면 됩니다. Window유저시라면, cmder를 다운로드해서 사용하시는걸 추천드립니다.&lt;b&gt; 하지만 , 기본 powershell , cmd를 쓰셔도 무방&lt;/b&gt;합니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Git 초기설정&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1.&lt;b&gt; git에 연결할 디렉토리에 .git 파일&lt;/b&gt;을 만들어줍니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git init&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git파일을 초기화 해주는 명령어입니다. 해당 경로에서 위의 명령어를 실행하면, git파일이 생성됩니다. powershell보다는 저는&lt;b&gt; cmder이 편해서, 이제 Cmder을 쓰도록 하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;95&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sNbd4/btrPlGLN1u1/Wl4QOMQLYLn9LYyDvbXek0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sNbd4/btrPlGLN1u1/Wl4QOMQLYLn9LYyDvbXek0/img.png&quot; data-alt=&quot;powershell에서 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sNbd4/btrPlGLN1u1/Wl4QOMQLYLn9LYyDvbXek0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsNbd4%2FbtrPlGLN1u1%2FWl4QOMQLYLn9LYyDvbXek0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;95&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;powershell에서 입력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;97&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXUpSe/btrPh83nJdl/BXBk3u3fQqx6l07gc530aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXUpSe/btrPh83nJdl/BXBk3u3fQqx6l07gc530aK/img.png&quot; data-alt=&quot;Cmder에서 git 생성 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXUpSe/btrPh83nJdl/BXBk3u3fQqx6l07gc530aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXUpSe%2FbtrPh83nJdl%2FBXBk3u3fQqx6l07gc530aK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;458&quot; height=&quot;97&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;97&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cmder에서 git 생성 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. &lt;b&gt;각 OS에 맞게 , 문자열 처리에 대한 옵션을 설정&lt;/b&gt;해줍니다.&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;&lt;b&gt;Windows&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git &lt;b&gt;config --global core.autocrlf true&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령어는, &lt;b&gt;문자열 처리 방식에서 OS마다 약간의 차이&lt;/b&gt;가 있기 때문에, Mac에서 업로드한 내용, Window에서 업로드한 내용이&lt;b&gt; 각각의 다른 운영체제에서 볼 때는 달라질 수 있기 때문에, 자동으로 처리해주는 옵션&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (9).jpg&quot; data-origin-width=&quot;1415&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vcyoN/btrPoyNeVaP/3y3ggFqbrB70IwxklK2eL0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vcyoN/btrPoyNeVaP/3y3ggFqbrB70IwxklK2eL0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vcyoN/btrPoyNeVaP/3y3ggFqbrB70IwxklK2eL0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvcyoN%2FbtrPoyNeVaP%2F3y3ggFqbrB70IwxklK2eL0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1415&quot; height=&quot;706&quot; data-filename=&quot;My First Board (9).jpg&quot; data-origin-width=&quot;1415&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시&lt;b&gt;, git 파일을 Editor로 열어서, 수정&lt;/b&gt;하고 싶다면 아래와 같은 방법이 있을 수 있습니다. (command line으로는 여러가지 설정을 하기는 힘들고 , &lt;b&gt;여러가지 설정을 한꺼번에 하고 싶은 경우&lt;/b&gt;)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git config --global -e&amp;nbsp;&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[core] , [user],[filter] 등등의 값이 있습니다. 예를들어, 위처럼 &lt;b&gt;autocrlf 속성을 true로 하고 싶다면,&amp;nbsp; core 옵션에 autocrlf 속성을 넣고, true로 해주면됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;157&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tPbTn/btrPhpK11Jx/WmHXY4ZFPyLceAqAVzFmVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tPbTn/btrPhpK11Jx/WmHXY4ZFPyLceAqAVzFmVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tPbTn/btrPhpK11Jx/WmHXY4ZFPyLceAqAVzFmVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtPbTn%2FbtrPhpK11Jx%2FWmHXY4ZFPyLceAqAVzFmVk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;246&quot; height=&quot;119&quot; data-origin-width=&quot;157&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. git 파일 자체를 삭제하기&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;rm -rf .git&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;rm -rf는 터미널 명령어 입니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Git의 WorkFlow&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git은 일정 WorkFlow에 따라서 , Version Control을 합니다. 따라서, 이 WorkFlow를 제대로 이해해야, Git을 활용할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (11).jpg&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v3peF/btrPgVJXi99/UKCiDwbQxngKGH1TRoeD10/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v3peF/btrPgVJXi99/UKCiDwbQxngKGH1TRoeD10/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v3peF/btrPgVJXi99/UKCiDwbQxngKGH1TRoeD10/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv3peF%2FbtrPgVJXi99%2FUKCiDwbQxngKGH1TRoeD10%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;846&quot; height=&quot;648&quot; data-filename=&quot;My First Board (11).jpg&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;875&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;git 상태 확인 명령어&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;git의 workFlow에 따라, 각각의 파일들이 어떻게 진행되고 있는지 알고싶을 수 있습니다. 그럴 때 이용할 수 있는 명령어입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git status&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;option으로 -s를 이용하면, 짧게 볼 수 있습니다. A(Add) M(Modified)등 여러 정보가 함축적으로 나타납니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;내 컴퓨터의 저장공간 (Local 저장공간)&lt;/b&gt;&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;&lt;b&gt;Working Directory&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내 컴퓨터의 작업공간 입니다.&amp;nbsp; git이 tracking 하거나 tracking하지 못한 파일들이 있는 공간입니다&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;. tracking은 이미 git이 관리하고 있는 파일&lt;/b&gt;&lt;/span&gt;들이고,&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; untracked는 새로 생긴 파일 또는, git이 관리를 하지 않고 있는 파일&lt;/b&gt;&lt;/span&gt;을 이야기 합니다.&lt;/li&gt;
&lt;li&gt;git add 명령어를 통해서, tracked 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git add [파일명]&amp;nbsp;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때,&lt;b&gt; Git에 포함하고 싶지 않은 파일들이 있을 수 있습니다. (module 파일이라던지, log 파일이라던지, 등등)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;eslint,prettier에도 ignore파일이 있듯이, git에서도 .gitignore파일을 준비해놨습니다. &lt;/b&gt;등록하지 않고 싶은 파일을 gitignore파일에 등록해놓으면됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, 나는 module폴더는 제외하고 싶으면, gitignore파일에 /module을 등록해놓으면 됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;echo /module &amp;gt;.gitignore&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;staging Area&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Commit할 파일들을 모아놓는 공간입니다. 즉, Commit할 준비가 된 공간입니다.&lt;/li&gt;
&lt;li&gt;여러개의 파일들을 add해서, commit하기 위해, 예약된 공간입니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Add를 한 순간의 그 파일 상태를 저장&lt;/b&gt;&lt;/span&gt;합니다. &lt;b&gt;즉, add한 뒤, 수정을 하면 , 또 add를 해주어야 합니다.&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;수정된 파일내용 확인하기&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;staging에 올렸다가, Modify가 되어서, 어떤 내용을 수정했는지 확인하고 싶은 경우가 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git diff&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 위와 같은 명령어를 이용하면, 보기가 까다롭다. (읽는 방법이 따로 존재한다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 볼려면, Editor에 있는 기능을 이용하면 훨씬 더 쉽게 볼 수 있다. &lt;b&gt;아래와 같이 config를 설정해주자.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czuIqZ/btrPoy7yajs/nKoynBEhWyF7be92FTDGgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czuIqZ/btrPoy7yajs/nKoynBEhWyF7be92FTDGgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czuIqZ/btrPoy7yajs/nKoynBEhWyF7be92FTDGgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczuIqZ%2FbtrPoy7yajs%2FnKoynBEhWyF7be92FTDGgk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;374&quot; height=&quot;129&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Commit하기&lt;/b&gt;&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;Staging Area에 파일이 자신이 의도한 대로 되었다면, &lt;b&gt;git commit으로 git directory에 넣어줘야한다&lt;/b&gt;.이때, git commit은 단순히 git commit으로 하기 보다는, &lt;b&gt;어떤 내용에 대한 Commit인지 메세지&lt;/b&gt;를 남기는게 좋다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git commit -m [메세지]&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;예를들어, 내 이번 commit이 Login Validation에 대한 내용이면, 아래와 같이 작성할 수 있다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;&lt;b&gt;git commit -m &quot;Add Login Validation&quot;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;원격저장소 (GitHub 연결하기)&lt;/b&gt;&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;&lt;b&gt;&lt;b&gt;Local에서의 설정이 끝났으면, 이제 github에 해당 폴더를 연결시켜주는 작업을 하는게 좋습니다.&lt;/b&gt;&lt;/b&gt;우선, 깃허브에 들어가서, test용 repository를 하나 만들어줍니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git remote add origin [깃허브주소]&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mqi0c/btrPrmexwqg/khimN1cMhTHlwFNovS1kA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mqi0c/btrPrmexwqg/khimN1cMhTHlwFNovS1kA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mqi0c/btrPrmexwqg/khimN1cMhTHlwFNovS1kA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmqi0c%2FbtrPrmexwqg%2FkhimN1cMhTHlwFNovS1kA1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;550&quot; height=&quot;42&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;42&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;git remote가 되어있는지 확인하기&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git remote -v&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;연결이 성공하면, 아래와 같이 뜹니다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;69&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4crBx/btrPjkP3lhT/MkLmWh5hp5J0Qw3AC5mMYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4crBx/btrPjkP3lhT/MkLmWh5hp5J0Qw3AC5mMYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4crBx/btrPjkP3lhT/MkLmWh5hp5J0Qw3AC5mMYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4crBx%2FbtrPjkP3lhT%2FMkLmWh5hp5J0Qw3AC5mMYK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;69&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;연결이 되었다면, 이제 몇가지 작업을 좀 해줘야한다.&lt;/b&gt;&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;&lt;b&gt;1. branch 이름 맞춰주기 .&lt;/b&gt;&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;&lt;b&gt;master -slave의 이름을 이제, main으로 바꾸는 운동을 시작했다. 그래서 ,branch를 main으로 바꾸어주면 된다&lt;/b&gt;&lt;b&gt;. &lt;/b&gt;물론, 다른 branch로 내가 분기를 낼거면, 사실 필요없긴하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git branch -M main&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. git push 해주기&lt;/b&gt;&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;이제, 원격저장소에&lt;b&gt; push할 명령어를 입력해준다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git push -u origin(내가 add때 등록한 이름) main(등록할 branch이름)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;* error 발생&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EVfH8/btrPne2COcK/bKLARTcZ8ZkKokJUwT3Oyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EVfH8/btrPne2COcK/bKLARTcZ8ZkKokJUwT3Oyk/img.png&quot; data-alt=&quot;reject되는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EVfH8/btrPne2COcK/bKLARTcZ8ZkKokJUwT3Oyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEVfH8%2FbtrPne2COcK%2FbKLARTcZ8ZkKokJUwT3Oyk%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;641&quot; height=&quot;125&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;reject되는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와같은 오류사항이 발생할 수 있다. 위 오류사항은, &lt;b&gt;github에 있는 현재 파일과, 내 local에 있는 파일이 달라서&lt;/b&gt; 그걸 check 해달라는 내용이다. 보통, github에서 readme파일을 생성해서, 생기는 오류이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;안전한 방법은 Pull을 이용하는 방법이 있다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git pull origin main&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; &quot;refusing to merge unrelated histories&quot;&lt;/b&gt;&lt;/span&gt;라는 멘트를 뱉어내며, 에러를 발생시킬 수 있다. 이건, 전혀 관련없는 두개의 프로젝트들이 지금 하나로 합쳐지는 경우이기 때문에, 뱉어내는 오류인데, &lt;b&gt;아래의 옵션을 주면 해결&lt;/b&gt;할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezsXE3/btrPoxniXFc/yS0AE6QJ0U8as9KBKD9guK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezsXE3/btrPoxniXFc/yS0AE6QJ0U8as9KBKD9guK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezsXE3/btrPoxniXFc/yS0AE6QJ0U8as9KBKD9guK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezsXE3%2FbtrPoxniXFc%2FyS0AE6QJ0U8as9KBKD9guK%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;397&quot; height=&quot;73&quot; data-origin-width=&quot;397&quot; data-origin-height=&quot;73&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git pull origin 브렌치명 --allow-unrelated-histories&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;강제로 Push하기. (local에 있는 파일을 강제로 프로젝트에 덮어쓰기)&lt;/b&gt;&lt;/b&gt;&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;&lt;b&gt;개인프로젝트인 경우에는, 강제로 push하는 방법이 더 좋을 수 있다.&lt;/b&gt; 왜냐하면, 초기셋팅일 확률이 크고, 뭐 자기자신의 파일과 github에 파일의 차이가 크게없을 수 있기 때문이다.&amp;nbsp; 하지만, 만약 중간에 project에 합류한다거나, &lt;b&gt;어떤 프로젝트를 여러명이서 하고 있을 때는 무적권 pull을 이용하자.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;git push origin&lt;b&gt; +&lt;/b&gt;main&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;Tip&lt;/b&gt;&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;git 명령어를 단축키로 등록할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;git config --global alias.단축키 기능&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, git status가 너무 길어서, st로 줄이고 싶다면, 아래와 같이 명령어를 칠 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;git config --global alias.st status&lt;/b&gt;&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;refer&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;엘리님의 git강의&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발환경</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/350</guid>
      <comments>https://dailymapins.tistory.com/350#entry350comment</comments>
      <pubDate>Mon, 24 Oct 2022 11:48:11 +0900</pubDate>
    </item>
    <item>
      <title>[JS/객체/프로토타입] JS의 프로토타입</title>
      <link>https://dailymapins.tistory.com/349</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 프로토타입형 객체지향 언어이기도 하고, 함수형으로 쓸 수도 있고, 뭐 다양한 측면을 가진 언어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;s&gt;(non-blocking , single-Thread,concurrency ,asynchronized 언어&lt;/s&gt;&lt;/b&gt;이기도 하죠) 자바스크립트의 빼놓을 수 없는 특징 중 하나인, 프토로타입에 대해서 적어봅시다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프로토타입&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현실에서 &quot;프로토타입&quot; 이라는 말 많이 쓸 일이 없지만 , 프로토타입에 대해서 먼저 알아봅시다. 종종 영화같은데나 게임버전 같은데서는&lt;b&gt; Prototype이라는 용어&lt;/b&gt;를 씁니다. &lt;b&gt;아이언맨에서 &quot;프로토타입&quot;이라는 말이 나오는데요 , 구글링을 해보겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;865&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyCcYf/btrPfo418Jx/uC77MzKrIgmFRRv6W6fc00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyCcYf/btrPfo418Jx/uC77MzKrIgmFRRv6W6fc00/img.png&quot; data-alt=&quot;검색결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyCcYf/btrPfo418Jx/uC77MzKrIgmFRRv6W6fc00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyCcYf%2FbtrPfo418Jx%2FuC77MzKrIgmFRRv6W6fc00%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;549&quot; data-origin-width=&quot;759&quot; data-origin-height=&quot;865&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;검색결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이언맨 1에 나오는 초기 슈트입니다!&amp;nbsp; 감은 잡힙니다. &lt;b&gt;&quot;프로토타입&quot;이라고 하면, 뭔가 초기버전 , 근본이 되는 1.0ver같은 그런 느낌이 들긴&lt;/b&gt;합니다. 하지만, Iron man의 가장 매력적인 점은 따뜻한 마음도 있지만, 다양한 슈트가 있다는 점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 프로토타입에서 다른 버전으로 업그레이드 하면서,&amp;nbsp; 다른 특성들을 가지게 되지만 , 우리가 생각하는 &lt;b&gt;&quot;아이언맨&quot;의 원형은 크게 바뀌지 않죠. 즉, 누구나 생각하면 딱 떠오르는 &quot;아이언맨&quot;이라는 원형은 크게 변하지 않습니다.(머리에 씌워져있고, 눈은 빛나면서 가슴 중간에는 토니의 상징인 아크 원자로가 있고, 손과 발에 있는 부스터를 이용해 비행을 하는 등)&lt;/b&gt;&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;프로토타입은 바로 이겁니다&lt;b&gt;. 누구나 생각하는 &quot;이상적인 원형&quot; ,&quot;이상적인 형태&quot;라고 할 수 있습니다. 예를 더 들어볼게요. &lt;/b&gt;&lt;b&gt;대부분 물고기를 그려보라고 하면, 아가미에 , 꼬리는 v자 형태에, 유선형으로 그립니다. 새를 그려보라고 하면, 날개가 있고, 다리가 2개고, 발가락이 3개인 형태를 그립니다.&amp;nbsp;&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;TMI (글쓴이의 주접)&lt;/b&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점에서, JAVA의 class와 다른점이 드러나게 되죠. JAVA는 &quot;특징&quot;들을 정의해놓고(class선언), 틀에서 찍어내게 객체를 정의합니다. 그래서 , JAVA에서는 완벽한 Class를 설계하는 것은 정말 어렵습니다. 이와 다르게, JS에서 객체를 바라보는 시선은 , 이상적인 형태인 각각의 Prototype이 있으며, 그걸 확장시키는 개념인거죠.&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;사실 이 개념은 언어 설계자가 어떤 철학을 가지고 개발했냐에 달렸는것이기 때문에, 객체에 대한 시선은 충분히 사람마다 각자 해석하는 것이 다를 수 있습니다. 단지 ,&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;JS의 개발 철학은 Prototype에 기반&lt;/b&gt;을 두고 있다는 이야기를 하는 것입니다! 프로토타입에 대한 더 정확한 의미는&amp;nbsp;&lt;b&gt;&quot;Eleanor Rosch&quot;의 &quot;프로토 타입이론&quot;&lt;/b&gt;에서 프로토타입에 대한 정의가 나옵니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;JS에서 프로토타입&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS는 내부적으로&lt;b&gt; 객체,함수,배열 등의 Prototype(Function.Prototype,Object.Prototype와 같은)&lt;/b&gt;을 갖고 있습니다. 그리고, 프로그래머가 사용하는 객체들에게&lt;b&gt; Prototype에 정의되어있는 constructor로 생성&lt;/b&gt;하게한 뒤, &lt;b&gt;자신의 정보를 [[Prototype]]객체로 묶어서 넣어주게 됩니다.&lt;/b&gt; 코드로 봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1666340286361&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const arr= [1,2,3,4,5]
const obj = {
	name:&quot;hello&quot;,
}

console.dir(arr)
console.dir(obj)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byvesi/btrPfbyfynw/kKefzkCehkQPk8Dwxh3yh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byvesi/btrPfbyfynw/kKefzkCehkQPk8Dwxh3yh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byvesi/btrPfbyfynw/kKefzkCehkQPk8Dwxh3yh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyvesi%2FbtrPfbyfynw%2FkKefzkCehkQPk8Dwxh3yh0%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;336&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&lt;b&gt;JS에서 Prototype은 객체(함수든, array든,object든)를 생성할 때, 부모객체를 프로토 타입이라고 합니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ECMA Scrip Spec(공식문서)에서는 자바스크립트의 모든 객체는 [[Prototype]]이라는 인터널 슬롯 (interal slot)을 가지고, [[Prototype]]의 값은 null 또는 객체이며 , 상속을 구현하는데 사용된다고 안내하고 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Prototype은 특정 객체를 생성&lt;/b&gt;할 때, &lt;b&gt;부모객체를 &quot;Prototype&quot;&lt;/b&gt;이라고 할 수 있다. (O)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[[Prototype]]를 부모를 통해 받기&lt;/b&gt; 때문에,&lt;b&gt; &quot;상속&quot;이라는 개념&lt;/b&gt;을 구현 할 수 있다. (O)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분 , 조금 만 더 깊게 들어가봅시다. 이거 재밌더라구요! 앞으로, 함수,배열, 객체들을 모두 지칭할 때는 큰 Object, 자바스크립트에서 리터럴로 생성하는 객체를 말할 때는 작은 object라고 쓸겁니다!.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;JS 객체 생성방법&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JS에서 객체를 생성하는 방법은 여러가지가 있습니다. 객체 리터럴, 생성자 함수이용,Object.create가 있습니다. 이 3가지가 묘하게 다른거 아시나요! 왜 이렇게 다양하게 있을까요. 한가지만 있으면 될텐데 말이죠.&lt;/b&gt;&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;함수도 Object 이고 , object도 Object이고, 배열도 Object 입니다. &lt;b&gt;그럼, 특별한 친구가 있죠. &quot;생성자&quot;라는 친구입니다. 생성자라는 친구는 함수이면서, 어떠한 객체(object)를 &quot;생성&quot;하는 친구입니다. 즉, Function.Prototype을 갖고 있으면서, 특정 객체(object)를 생성될 객체(object)한테 가르쳐 줘야합니다. 그래서,함수 타입에는 prototype이라는 property가 있습니다. 이걸 설명하는 이유는 , prototype property와 ~~.prototype이 무지무지 헷갈리기 때문입니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666341644779&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function a(){
}
console.dir(a)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVHZuX/btrPfDgV3JI/ZxiGHsxpk9KUKtnsKKpNG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVHZuX/btrPfDgV3JI/ZxiGHsxpk9KUKtnsKKpNG1/img.png&quot; data-alt=&quot;prototype&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVHZuX/btrPfDgV3JI/ZxiGHsxpk9KUKtnsKKpNG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVHZuX%2FbtrPfDgV3JI%2FZxiGHsxpk9KUKtnsKKpNG1%2Fimg.png&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; loading=&quot;lazy&quot; width=&quot;256&quot; height=&quot;164&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;prototype&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;객체 리터럴로 객체 생성하기&lt;/b&gt;&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;JS로 객체를 생성할 때, 가장 흔하게 쓰는 방법 중 하나인 객체 리터럴입니다. 객체 리터럴의 &lt;b&gt;생성과정을 prototype을 적용해서 생각&lt;/b&gt;을 해보도록 하겠습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666341727199&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj= {
	name:&quot;Mapin&quot;,
    say:&quot;hello!&quot;,

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토 타입관점에서 위의&lt;b&gt; 객체 리터럴을 이용하는 생성과정은 아래와 같은 Prototype Chain이 형성&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 객체의&lt;b&gt; prototype이 Object.prototype으로, &quot;객체 프로토타입&lt;/b&gt;&quot;이 자신의 부모가 되죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (1).jpg&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WzZeg/btrPgevSD2z/SF3vppujQ1GnLlkNKVlzw1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WzZeg/btrPgevSD2z/SF3vppujQ1GnLlkNKVlzw1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WzZeg/btrPgevSD2z/SF3vppujQ1GnLlkNKVlzw1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWzZeg%2FbtrPgevSD2z%2FSF3vppujQ1GnLlkNKVlzw1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;691&quot; height=&quot;429&quot; data-filename=&quot;My First Board (1).jpg&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;생성자를 이용하는 방법&lt;/b&gt;은 어떻게 될까요?&lt;/p&gt;
&lt;pre id=&quot;code_1666496655707&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Obj(name,say){
	this.name=name;
    this.say=say;
    this.sayHello = function(){
    	console.log(`Hello! Im ${this.name} ${this.say}`)
    }
}

const ob = new Obj(&quot;mapin&quot;,&quot;Yob&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토 타입관점에서 위의&lt;b&gt;&lt;span&gt; 생성자 함수를&lt;/span&gt;&amp;nbsp;이용하는 생성과정은 아래와 같은 Prototype Chain이 형성&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성된 객체의&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;prototype이 Obj.prototype으로, 자신을 생성한 부모가 자신의 프로토 타입이 되는것이죠.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (2).jpg&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;807&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnzFMt/btrPkrtT8bv/7AFzzk6FKsF2k8S8GTWWU1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnzFMt/btrPkrtT8bv/7AFzzk6FKsF2k8S8GTWWU1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnzFMt/btrPkrtT8bv/7AFzzk6FKsF2k8S8GTWWU1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnzFMt%2FbtrPkrtT8bv%2F7AFzzk6FKsF2k8S8GTWWU1%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;1237&quot; height=&quot;807&quot; data-filename=&quot;My First Board (2).jpg&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;807&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3줄요약&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;JS에서 객체를 바라보는 관점은 Prototype이다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Prototype은 객체가 생성 되었을 때, 자신의 부모객체를 가리킨다.&lt;b&gt; [[prototype]]객체를 주입받아, &quot;상속&quot;이라는 개념을 이용할 수 있게 된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체를 생성하는 방법에 따라서, prototype chain이 바뀐다.&lt;/b&gt;&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;&lt;b&gt;refer&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://poiemaweb.com/js-prototype#42-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%95%A8%EC%88%98%EB%A1%9C-%EC%83%9D%EC%84%B1%EB%90%9C-%EA%B0%9D%EC%B2%B4%EC%9D%98-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EC%B2%B4%EC%9D%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;프로토타입 deepdive&lt;/a&gt;&lt;/p&gt;</description>
      <category>Web Front-end/JavaScript</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/349</guid>
      <comments>https://dailymapins.tistory.com/349#entry349comment</comments>
      <pubDate>Sun, 23 Oct 2022 13:00:02 +0900</pubDate>
    </item>
    <item>
      <title>[JS/호이스팅/실행 컨텍스트/이벤트 루프] JS 코드의 흐름</title>
      <link>https://dailymapins.tistory.com/348</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저는 var을 한번도 써본적이 없지만, JS는 오래동안 써왔던 언어이므로 ,var를 마주칠 가능성이 높습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(var은 호이스팅을 하기 때문에,&lt;b&gt;&amp;nbsp;선언하지 않아도 접근이 가능&lt;/b&gt;해지며 &lt;b&gt;재할당을 해도 아무런 상관이 없는 문제&lt;/b&gt;가 있었습니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS의 코드의 흐름중에 하나인, &lt;b&gt;호이스팅&lt;/b&gt;부터 짚고 넘어가볼까요!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;호이스팅(Hoisting)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 보시죠! 어떤 문제가 있어보이나요?&lt;/p&gt;
&lt;pre id=&quot;code_1666183960260&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a=5
console.log(a)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아뇨, 없습니다!&amp;nbsp;&lt;b&gt; a=5 라는 결과&lt;/b&gt;가 나올겁니다. 아래의 코드를 보시죠 . 문제가 있을것 같나요?&lt;/p&gt;
&lt;pre id=&quot;code_1666184032086&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(b)
var b=5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;놀랍게도, 아래의 코드도&lt;b&gt; &quot;실행&quot;&lt;/b&gt;은 됩니다. 의도치 않은 결과인 &quot;undefined&quot;를 뱉을 뿐,&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt; 에러는 발생하지 않습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C언어,Java와 같은 정적인 언어를 자주 접해왔던 저는 처음에는&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt; &quot;뭐지 , 이 무근본은 ..?&quot;&lt;/span&gt;&lt;/b&gt;이라고 생각했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언을 하지도 않았는데, &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;이걸 에러를 안뱉어..?&lt;/span&gt;&lt;/b&gt; 그리고, 더 놀라웠던건, &lt;b&gt;같은 이름의 변수를 또 &quot;선언&quot;&lt;/b&gt;할 수 있었다.&lt;/p&gt;
&lt;pre id=&quot;code_1666184566658&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a =5
console.log(a)
var a=7
console.log(a)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 이러한 로직이 가능한건 , 분명한 이유가 있을거고, 바로 그 개념이 &quot;호이스팅&quot;의 개념입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호이스팅은 이렇게 동작합니다. 코드를 실행하기 전에, V8엔진 형님이 먼저 코드를 한번와서 쓱 훑고 , &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;&quot;선언&quot;된 변수들을 미리 적어갑니다.&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;코드 상의 동작으로 따지면, 아래와 같이 움직입니다.&amp;nbsp; a를 최상단으로 옮기는거죠.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;따라서, console.log(a)에 undefined가 나오게 되는겁니다. 아직 &quot;값&quot;자체는 할당되지 않았으니까요!&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666184785850&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(a)

var a=5 

//======== this code convert to below =====

var a 
console.log(a)
a=5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로나온 &lt;b&gt;let, const도 호이스팅을 안할까요?&lt;/b&gt; &lt;b&gt;아닙니다. 합니다! 단 , 값이 &quot;할당&quot;되기전에 접근하는걸 막는겁니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666185024442&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(b)
let b =5

// convert code to below 

let b 
console.log(b)
//TDZ , 할당되기 전까지 b로의 접근을 막는다. b에 접근하면 error!
b=5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Summary&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호이스팅 문제로 인해서, var은 더 이상 쓰지않는다. 하지만, &lt;b&gt;원시코드 형태로 만나볼 수 있으니 알고는 있자.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;호이스팅은&amp;nbsp; V8엔진이 변수를 미리 기억하는 과정&lt;/b&gt;이다. 이 현상 때문에, 코드의 흐름상 &lt;b&gt;제일 위로 끌어올리는 것과 같은 현상이 되는거다.&lt;/b&gt; 이때, var은 undefined로 되고,&lt;b&gt; let,const는 TDZ를 만들어 할당이 되지 않았다면 접근을 막게된다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Scope&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C언어/Java와 같은 정적인 언어를 사용해봤다면, 혹은 Python을 다루어 보았다면 프로그래밍 언어는 &lt;b&gt;&quot;실행블록&quot;&lt;/b&gt;이라는 개념이 있습니다. &lt;b&gt;예를들어, C언어,java는 중괄호&lt;/b&gt; , &lt;b&gt;python은 콜론(:) + 스페이스바 4칸(Tab)으로 구분&lt;/b&gt;을 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1개의 실행블록은, 독립적인 공간&lt;/b&gt;처럼 사용할 수 있어서, &lt;b&gt;외부에서 내부로 접근을 못합니다. 아래와 같이 말입니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666185516006&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void printNumber(){
	int num=5
    printf(&quot;%d&quot;,num)
}

printf(&quot;%d&quot;,num) //error!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;실행블록과 같은 논리적인 범위, 변수값들의 유효범위를 JS에서는 Scope&lt;/span&gt;&lt;/b&gt;라고합니다. var은 이 scope가 애매합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 , &lt;b&gt;지역변수와 전역변수가 애매해진다는거죠. &lt;/b&gt;정확히는&lt;b&gt; var은 함수내부에서는 , 지역변수&lt;/b&gt;입니다만, &lt;b&gt;if,for문과 같은 곳에서는 전역변수&lt;/b&gt;처럼 동작하게 됩니다. 이걸 &lt;b&gt;JS에서는 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&quot;함수스코프를 가졌다&quot;&lt;/span&gt;&lt;/b&gt;고 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1666185707824&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for(var i=0;i&amp;lt;5;i++){
	console.log(&quot;inner&quot;,i)
	
// 1,2,3,4,
}
console.log(&quot;outer&quot;,i)
// boom! 5

function sayHi(){
	var say=&quot;hello&quot;
}
console.log(say)
//error!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;let,const에서 오면서 이걸 고쳤죠! &lt;b&gt;다른 언어와 마찬가지로 ,&lt;span style=&quot;background-color: #dddddd;&quot;&gt; blockScope&lt;/span&gt;로요!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정리하자면, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;Scope란 , 변수 이름, 함수 이름, 클래스 이름과 같은 &quot;식별자(Identifier)&quot;가 본인이 선언된 위치에 따라, 다른 코드에서 자신이 참조 될 수 있을지 없을지 결정 되는걸 이야기&lt;/span&gt; 합니다. 식별자의 유효범위인 셈이죠.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이벤트 루프&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;Chrome을 간소화 시키면 아래와 같은 구조를 띄게 됩니다. &lt;/b&gt;&lt;/b&gt;실행 컨텍스트는&lt;b&gt; 간단하게 이야기하면, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&quot;call stack에 쌓이는 로직들에 대한 모든 내용&quot;&lt;/span&gt;&lt;/b&gt; 입니다. 우리가 실행하는 함수나 로직들은 call stack에 순차적으로 하나씩 쌓이게 됩니다. (즉, 들어온대로 처리가 된다는거죠!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자세하게 들어가면, 전역 컨텍스트 , 함수 컨텍스트 , 지역 컨텍스트 등등 다양하게 있고, lexical scope chain ,this 등이 context마다 있습니다만,&amp;nbsp; Event Loop에서는 &quot;callstack에 쌓이는 로직&quot; 이정도로 이해해도 큰 문제는 없을겁니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (11).jpg&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;877&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kEkue/btrO50we99Y/mMv6t5G7R0jc7HyYDeNfk0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kEkue/btrO50we99Y/mMv6t5G7R0jc7HyYDeNfk0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kEkue/btrO50we99Y/mMv6t5G7R0jc7HyYDeNfk0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkEkue%2FbtrO50we99Y%2FmMv6t5G7R0jc7HyYDeNfk0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;768&quot; height=&quot;591&quot; data-filename=&quot;My First Board (11).jpg&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;877&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;아래의 코드가 JS에서 실행된다고 생각해보죠.&lt;/p&gt;
&lt;pre id=&quot;code_1666188855298&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(&quot;welcome&quot;!);
function func1(){
	console.log(&quot;Hello!&quot;);
}

setTimeout(func1,5000)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0. 메모리 영역에 func1을 등록해놓습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. console.log()가 callstack에 쌓입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (12).jpg&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Z9FR/btrO4heFv4L/WkFbCKAUEdIOD4HaeX4LKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Z9FR/btrO4heFv4L/WkFbCKAUEdIOD4HaeX4LKk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Z9FR/btrO4heFv4L/WkFbCKAUEdIOD4HaeX4LKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Z9FR%2FbtrO4heFv4L%2FWkFbCKAUEdIOD4HaeX4LKk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;474&quot; data-filename=&quot;My First Board (12).jpg&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;878&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. console.log() 실행이 끝나고, setTimeout이 실행됩니다. setTimeout은 실행됬다가, 비동기함수이므로 WebAPI에게 callback을 던집니다. 여기서는 func1을 던지겠네요!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (13).jpg&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAab5s/btrO4fVtXhc/TkiYT31pwktqz7TWErZyyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAab5s/btrO4fVtXhc/TkiYT31pwktqz7TWErZyyk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAab5s/btrO4fVtXhc/TkiYT31pwktqz7TWErZyyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAab5s%2FbtrO4fVtXhc%2FTkiYT31pwktqz7TWErZyyk%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;623&quot; height=&quot;481&quot; data-filename=&quot;My First Board (13).jpg&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;878&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.Timer는&amp;nbsp; setTimeout이 요청했던대로,&lt;b&gt; 5초뒤에&amp;nbsp; Task Queue에 callback을 던집니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (14).jpg&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAQ1NV/btrO44lCb2e/K3H8IENbb0xxIXXMvq33hK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAQ1NV/btrO44lCb2e/K3H8IENbb0xxIXXMvq33hK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAQ1NV/btrO44lCb2e/K3H8IENbb0xxIXXMvq33hK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAQ1NV%2FbtrO44lCb2e%2FK3H8IENbb0xxIXXMvq33hK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;723&quot; height=&quot;561&quot; data-filename=&quot;My First Board (14).jpg&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 이제 더 이상 실행할게 없으므로, call stack에서 annoymous(전역객체)가 마지막으로 나갑니다.&amp;nbsp; event loop는 callstack이 완전이 비어질 때까지 기다립니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&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;&lt;b&gt;5. Event loop는 call stack이 완전히 비어있고, Task Queue에 작업이 남아있다면, 그 작업을 call stack으로 올려줍니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (15).jpg&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;868&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqcBoS/btrOQAywtjQ/mp74VClju8kS0I97kwDzE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqcBoS/btrOQAywtjQ/mp74VClju8kS0I97kwDzE0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqcBoS/btrOQAywtjQ/mp74VClju8kS0I97kwDzE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqcBoS%2FbtrOQAywtjQ%2Fmp74VClju8kS0I97kwDzE0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;585&quot; height=&quot;442&quot; data-filename=&quot;My First Board (15).jpg&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;868&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. callstack에서 callback 함수가 실행되고, 이제 끗! 입니다.&lt;/b&gt;&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;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Eventloop는 , call stack을 항상 지켜보다가 , task queue에 남은 작업이 있다면, call stack으로 올려주는 역할&lt;/span&gt;을 하게됩니다.&amp;nbsp; &lt;/b&gt;&lt;b&gt;예를들어, 아래의 코드는 bar을 즉시 반환할까요? 아닙니다. 콘솔에는 foo bar이 찍힙니다. 이게 자바스크립트의 코드 흐름 때문에 그렇습니다!&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1666189759599&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function func1(){
	console.log(&quot;bar&quot;)
}
setTimeout(func1,0)
console.log(&quot;foo&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음시간에는 실행컨텍스트를 자세하게 들여다보면서, &lt;b&gt;scope chain을 따라서 &quot;this&quot;가 결정되는 과정을 보고, closure패턴을 한번 봅시다!&amp;nbsp; 왜 &quot;this&quot;가 함수 호출시에 결정되는지를 알려면, 실행컨텍스트를 보면됩니다!&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 컨텍스트를 이해하려면, 오늘 적은 스코프,호이스팅,이벤트루프 ,call stack에 대한 개념을 조금 아셔야합니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 컨텍스트가 끝나면 , promise를 포스팅해서 ! 드디어, AJAX 즉 , 웹서버와 통신을 비동기적으로 하는걸 봅시다!&lt;/b&gt;&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;refer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8aGhZQkoFbQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JSconf - EventLoop&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.zerocho.com/category/JavaScript/post/5741d96d094da4986bc950a0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;제로초님 블로그&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Web Front-end/JavaScript</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/348</guid>
      <comments>https://dailymapins.tistory.com/348#entry348comment</comments>
      <pubDate>Wed, 19 Oct 2022 23:36:39 +0900</pubDate>
    </item>
    <item>
      <title>[JS/EventLoop/CS] JS의 코드의 실행을 이해기 위한 CS</title>
      <link>https://dailymapins.tistory.com/347</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 다른 언어들과 다르게, 특이한 흐름이 있습니다. JS는 &quot;싱글 쓰레드&quot;언어이지만, 동시성을 갖고 있는 언어이기도 합니다. 이게 무슨말인지 잘 와닿지 않을 수 있습니다. 여기서는 CS지식이 들어갈 수 밖에 없고, 저는 다행히 전공을 했기 때문에 이해가 가지만, 어려운 개념에는 틀림이 없습니다!&amp;nbsp; 천천히 가보죠!&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;&lt;b&gt;동시성(Concurrency)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로그램 처리 관점에서 Concurrency는 &quot;동시에 수행하는 것 처럼 동작시키는 것&quot;을 이야기합니다. 아래의 예시를 보시죠. &lt;/b&gt;어떤 작업 Task1,Task2가 듀얼코어의 CPU 시스템에서 처리된다고 생각해봅시다. &lt;b&gt;cpu는 1개의 task밖에 처리를 못한다고 가정하겠습니다.&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (6).jpg&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0uZi/btrO0HX9vVS/XSzvlqvBfANejxC2Hr4qE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0uZi/btrO0HX9vVS/XSzvlqvBfANejxC2Hr4qE0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0uZi/btrO0HX9vVS/XSzvlqvBfANejxC2Hr4qE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0uZi%2FbtrO0HX9vVS%2FXSzvlqvBfANejxC2Hr4qE0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;402&quot; data-filename=&quot;My First Board (6).jpg&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이런상황에서 , task 3,task 4를 진행시키고 싶은겁니다.&amp;nbsp; &lt;/b&gt;다른 말로 더 와닿게 말씀드리면,&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; 브라우저 키고, 노래 듣고, 카톡도 하면서 , VScode도 하고 싶은&lt;/b&gt;&lt;/span&gt;겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 할 수 있을까요? 수십장의 그림을 빠르게 넘기면, 우리 눈에는 움직이는것처럼 보입니다.&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; 즉, 끊기지 않고, 연결된 것처럼 보인다는 이야기죠&lt;/b&gt;&lt;/span&gt;.&amp;nbsp; &lt;b&gt;마찬가지로,&amp;nbsp; 작업도 인간이 인지할 수 있는 속도보다 빠르게, 바꿔치기 하면서 조금씩 작업하면&lt;/b&gt;, 마치&lt;b&gt; 끊기지 않는것처럼 느껴지지 않을까요? 아래와 같이 말이죠! 이게 ,&quot;동시성&quot; 입니다. 대표적으로 , 시분할 방식을 쓰는데, OS정리할 때 다시 다루도록 하겠습니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (7).jpg&quot; data-origin-width=&quot;1417&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/77mew/btrO1vXhcv4/sSc0lmcpWskqEDtrCGZ9j0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/77mew/btrO1vXhcv4/sSc0lmcpWskqEDtrCGZ9j0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/77mew/btrO1vXhcv4/sSc0lmcpWskqEDtrCGZ9j0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F77mew%2FbtrO1vXhcv4%2FsSc0lmcpWskqEDtrCGZ9j0%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;703&quot; height=&quot;350&quot; data-filename=&quot;My First Board (7).jpg&quot; data-origin-width=&quot;1417&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;병렬성(Parallelism)&lt;/b&gt;&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;병렬성은 말 그대로, &lt;b&gt;다른 CPU에서 처리&lt;/b&gt;하는걸 이야기합니다. &lt;b&gt;동시성은 Task를 바꿔주는데 비용이 발생&lt;/b&gt;합니다. &lt;b&gt;병렬성은 이런 과정이 필요없습니다.&lt;/b&gt; 진짜 물리적으로 분리되어 있는 공간에서 실행시켜주는 거입니다. CPU1,CPU2에서 task (1,3) (2,4)는 &lt;b&gt;병렬적으로 처리되는걸 병렬성&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;스레드와 프로세스 , 컨텍스트 스위칭 (Context Switching)&lt;/b&gt;&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;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;프로세스는 운영체제로부터, 자원(메모리)을 할당받는 작업 단위&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;스레드는 할당받은 자원을 이용하는 &quot;실행의 단위&quot;&lt;/span&gt;&lt;/b&gt;라고 할 수 있습니다. 프로세스 내에 여러개의 스레드가 실행되는거죠.&amp;nbsp;&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;&lt;b&gt;Multi Process&amp;nbsp;&lt;/b&gt;&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;하나의 프로그램을 &lt;b&gt;여러개의 프로세스로 구성&lt;/b&gt;해서,&lt;b&gt; 각 프로세스가 하나의 작업&lt;/b&gt;을 처리합니다. 즉, 메모리 공간을 추가적으로 OS에서 할당받아서 실행하는 방법입니다. 이때, 각 프로세스를 번갈아 가면서 실행(동시성)하게 되는데, 이&lt;span&gt;&amp;nbsp;작업을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;Context Switching&lt;/b&gt;이라고합니다. &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;프로세스는 독립적인 메모리 공간&lt;/b&gt;&lt;/span&gt;이므로, &lt;b&gt;cache hit율도 낮습니다&lt;/b&gt;. 즉, 캐시메모리 초기화 작업을 해야합니다.&amp;nbsp; 또, 메모리 영역을 할당받는다는 건 &quot;System Call&quot; 즉, OS를 통해서 커널모드로 바꿨다가, &lt;b&gt;사용자 모드로 전환하는 추가작업&lt;/b&gt;도 필요합니다. &lt;b&gt;하지만, 안정적입니다.&lt;/b&gt;&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;&lt;b&gt;Multi Thread&lt;/b&gt;&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;멀티 쓰레드는 , 하나의 프로세스 안에서 여러개의 스레드로 자원을 공유하며 작업을 나누어 수행합니다. 즉, context switching 이 매우 빠르겠죠. 쓰레드는 기본적으로&amp;nbsp; &quot;Function Call&quot;이기 때문에, 시스템 콜이 줄어들어 빠르고, &lt;b&gt;한 프로세스 내에 있기 때문에, cache의 hit율도 높습니다.&amp;nbsp; &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만, 프로세스를 하나의 컨테이너처럼&lt;/b&gt; 사용해서,&lt;b&gt; 여러개의 자원을 공유해서 사용한다는 말은&amp;nbsp; 곧, 여러 쓰레드에서 동시에 접근 할 수 있다는 이야기 입니다. 공유자원을 보호하기 위해서, 동기화(Mutex,spinlock,Semaphore 등의 개념)를 잘 해줘야하고 , 그리고, 구현하기도 까다롭습니다(실수할 확률이 높다 , 사람마다 구현하는 결과물이 천차만별이다).&lt;/b&gt;&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;&amp;nbsp;* JS는 Single Thread입니다. 즉&lt;b&gt;, 1개의 스레드만 돌아간다는거죠! 1번에 1개의 작업만 가능!&lt;/b&gt;&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;들어가기 전에, 블로킹과 논블로킹, 동기와 비동기는 완전히 다른 관점에서 보는겁니다. 둘을 혼동하면 안됩니다!&amp;nbsp;&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;&lt;b&gt;블로킹 &amp;amp; 논 블로킹&lt;/b&gt;&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;블로킹은 말 그대로 , &quot;blocking&quot;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; 실행이 막히느냐 안막히느냐의 관점&lt;/b&gt;&lt;/span&gt;으로 해석을 한겁니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Blocking은 &lt;b&gt;하나의 작업이 끝날 때 까지, 다른 작업을 하지 않습니다. 즉 , 제어권을 B에게 넘긴다음, B가 다시 제어권을 넘길때 까지 아무런 작업을 못합니다. 만약, JS가 Blocking이라면, Ajax요청을 보내면 , 요청이 끝날 때 까지 아무런 화면 클릭도 못할겁니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (8).jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uukH0/btrO2ocxSvQ/7Tb3hdT9lrO66nm5EI55UK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uukH0/btrO2ocxSvQ/7Tb3hdT9lrO66nm5EI55UK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uukH0/btrO2ocxSvQ/7Tb3hdT9lrO66nm5EI55UK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuukH0%2FbtrO2ocxSvQ%2F7Tb3hdT9lrO66nm5EI55UK%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;258&quot; height=&quot;403&quot; data-filename=&quot;My First Board (8).jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;1249&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;논 블로킹&lt;/b&gt;은 반대로, 제어권을 그대로 가지고 있는 상태로, 다른 함수를 &quot;실행&quot;만 시키는 형태입니다. &lt;b&gt;다른함수가 실행될 동안, 나는 내 할일을 하게됩니다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;My First Board (9).jpg&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;1245&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkLUN5/btrOYxbIGR8/XYccffSB0aPKZCfcSKjB8k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkLUN5/btrOYxbIGR8/XYccffSB0aPKZCfcSKjB8k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkLUN5/btrOYxbIGR8/XYccffSB0aPKZCfcSKjB8k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkLUN5%2FbtrOYxbIGR8%2FXYccffSB0aPKZCfcSKjB8k%2Fimg.jpg&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; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;438&quot; data-filename=&quot;My First Board (9).jpg&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;1245&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;&lt;b&gt;Synchronous &amp;amp; Asynchronous&lt;/b&gt;&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;동기와 비동기는 &lt;b&gt;프로세스의 수행 순서가 보장되느냐 관점&lt;/b&gt;입니다. &lt;b&gt;동기이면, 내가 지정한 순서대로 프로세스가 돌아가는걸 이야기&lt;/b&gt;합니다. Code로 따지면, &lt;b&gt;Top-down으로 코드의 흐름이 생성되냐/안되냐&lt;/b&gt;에 따라서 나누는거죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수로 따지면, 호출하는 함수 A가 호출되는 함수 B의 작업이 &quot;언제&quot;완료되는지 계속 물어봅니다.&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;비동기는 함수A가 함수 B를 호출할 때, 함수 B의 실행 순서를 신경쓰지 않습니다. 언제 실행되는지 모르고, 알 필요도 없고, 그냥 관심이 없습니다. 주로 Callback으로 구현합니다. code로 따지면, Top-down으로 코드의 흐름이 생성되지 않습니다.&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;* JS에서 EventListener, SetTimeout등이 비동기라고 불리는 이유는, 코드 상에서 Top-down으로 실행되지도 않고, 단지 Web API를 통해서 callback으로 등록하고 있을 뿐입니다.&lt;/b&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보통 비동기 &amp;amp; non -blocking , 동기 &amp;amp; blocking을 조합&lt;/b&gt;하여 씁니다. 그리고, 간혹가다가 동기&amp;amp;non-blocking도 있습니다.&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;&lt;b&gt;동기&amp;amp;non-blocking&lt;/b&gt;은, A의 함수 자신을 계속 실행하면서,&amp;nbsp; B의 함수의 리턴값이 필요할 때 사용되어집니다.&lt;b&gt; 즉, 중간중간에 계속 함수실행이 완료되었는지 물어보는 상태를 이야기&lt;/b&gt;합니다. 로딩창이 보통 그렇습니다. &lt;b&gt;자신은 계속 실행하면서, 상대방에게 끝났냐 ,끝낫냐 계속 체크를 하니까요.&lt;/b&gt;&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;JS는 비동기 ,non-blocking입니다. 왜 그런지는 다음 글에 담도록하죠!&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Computer Science</category>
      <author>Mapin</author>
      <guid isPermaLink="true">https://dailymapins.tistory.com/347</guid>
      <comments>https://dailymapins.tistory.com/347#entry347comment</comments>
      <pubDate>Wed, 19 Oct 2022 01:25:49 +0900</pubDate>
    </item>
  </channel>
</rss>