<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발공부</title>
    <link>https://minimal-dev.tistory.com/</link>
    <description>정보를 지식으로 만드는 글쓰기</description>
    <language>ko</language>
    <pubDate>Sat, 27 Jun 2026 06:04:05 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>개굴이 dev</managingEditor>
    <item>
      <title>Repaint와 Reflow 최적화하기</title>
      <link>https://minimal-dev.tistory.com/57</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;불필요한 태그는 쓰지 않는다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wrapper 역할로만 사용되는 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;,&lt;br /&gt;div 안에 데이터를 넣기 위한 &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하지만 하나의 노드가 추가될 때마다 DOM tree도 깊어진다.&lt;br /&gt;최대한 DOM depth가 많아지지 않도록 해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동적인 스타일 변화는 부모에 주지 않는다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변화가 발생하면 repaint는 자식 요소, reflow는 부모와 자식 요소 관계없이 일어난다.&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;br /&gt;또한 그 요소에도 최대한 자식 요소가 없도록 구조하는 것이 좋다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;inline style 보다는 클래스명이 낫다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스명의 변화도 reflow를 일으킨다.&lt;br /&gt;여러 스타일을 인라인으로 추가한다면 스타일 하나 하나가 reflow를 유발한다.&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;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;code&gt;display: none&lt;/code&gt;, &lt;code&gt;display: block&lt;/code&gt;도 방법이다.&lt;/h2&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;wrapper&quot;&amp;gt;
 ... 
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더링 될 때 비동기 요청이 여러번 발생하거나, 100번의 변화가 발생해야 한다면?&lt;br /&gt;최소 100번의 reflow나 repaint(혹은 둘다)가 일어난다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;요청 전에 &lt;code&gt;.wrapper&lt;/code&gt;를 &lt;code&gt;display: none&lt;/code&gt;한다.&lt;br /&gt;&lt;code&gt;.wrapper&lt;/code&gt;를 백그라운드로 빼 놓는다.&lt;/li&gt;
&lt;li&gt;none인 요소는 DOM tree에 영향을 주지 않는다. 이 때 지지고 볶고 한다.&lt;/li&gt;
&lt;li&gt;요청이 완료되면 &lt;code&gt;display: block&lt;/code&gt;으로 바꾼다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 none(reflow 1, repaint 1)과 block(reflow 1, repaint 1) 총 4번만 일어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하위 요소들은 5번 수정이 되었지만 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100번의 DOM 탐색 횟수 보다 4번이 낫다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;태그 선택자 보다는 class 기반이 좋다.&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;.wrapper {
  .card {
    .card-content {
      div {}
      span {
        img {}
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스명을 직접 작성해야 할 때 보이는 코드다.&lt;br /&gt;좋은 클래스명 아이디어도 없고, 큰 의미도 없는 요소여서 저렇게 작성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스명이 없고 태그를 선택자로만 사용한다면 브라우저는 바빠진다.&lt;br /&gt;그 DOM 전체에 div, span이 얼마나 많을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;reflow가 일어날 때 전체 페이지에서 해당하는 태그명을 검색해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;변수에 할당한다.&lt;/h2&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;const element = documnet.querySelector('.wrapper');

while (element.offsetWidth &amp;lt; 500) {
  뭔가 스타일에 변화주는 코드
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 반복문의 횟수가 크다면 성능에 영향을 주는 코드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복이 돌 때마다 요소의 offsetWidth를 확인해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;code&gt;offestWidth&lt;/code&gt;처럼 계산되야 하는 스타일이 있다면 반복문 외부에서 변수에 할당해 주는 것이 좋다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 도구를 통해 reflow, repaint가 발생하는 요소를 알 수 있다.&lt;br /&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;chrome으로 기준했을 때 performance 탭의 event log에서 볼 수 있다.&lt;br /&gt;또한 DOM tree의 selector나 css의 갯수는 css overview에서 확인할 수 있다.&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;br /&gt;이 부분은 실제로 테스트 해보고 다시 포스팅하려 한다.&lt;/p&gt;</description>
      <category>Web</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/57</guid>
      <comments>https://minimal-dev.tistory.com/57#entry57comment</comments>
      <pubDate>Wed, 24 May 2023 22:51:25 +0900</pubDate>
    </item>
    <item>
      <title>Repaint와 Reflow</title>
      <link>https://minimal-dev.tistory.com/56</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;DOM&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM은 자바스크립트가 웹 페이지에 접근하여 내용과 디자인을 바꿀 수 있게 한다.&lt;br /&gt;다른 프로그래밍 언어도 가능하지만 DOM 조작의 대표적인 언어는 자바스크립트다.&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;그래서 DOM은 프로그래밍 언어가 문서에 접근해서 읽고, 조작할 수 있게 하는 인터페이스다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;DOM은 대표적으로 HTML을 통해서 표현된다. JavaScript로 DOM을 직접 조작하면서 화면은 정적이지 않다.&lt;br /&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;br /&gt;자바스크립트는 DOM을 변경하고 검색한다.&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;&lt;br /&gt;JavaScript가 요소에 변화를 주면 브라우저는 Reflow와 Repaint 과정이 발생한다&lt;br /&gt;화면이 리렌더링 된다고도 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Repaint&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Repaint는 HTML 요소가 비주얼적으로 바뀔 때 일어난다. 위치 와는 관련이 없다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;visibility&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;color&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;background-color&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;code&gt;visibility&lt;/code&gt;를 수정하면 해당 요소의 자식 트리 구조까지 탐색한다.&lt;br /&gt;탐색은 곧 CPU 소모다.&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;br /&gt;자식이 없다면 변경되는 요소에 한 번만 계산된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reflow&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reflow는 위치가 바뀔 때 일어난다. 한 요소의 위치가 바뀌면 엮여 있는 다른 요소들도 다시 걔산된다.&lt;br /&gt;레이아웃에 영향을 주기 때문에 layout이라고도 불린다.&lt;br /&gt;Repaint는 자식까지만 계산한다. 하지만 reflow는 레이아웃에 영향을 받는 모든 요소들에 대해 다시 위치를 계산해야 한다.&lt;br /&gt;그래서 Repaint보다 CPU 소모가 크다.&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;Reflow를 트리거하는 작업들이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM 요소 추가, 제거&lt;/li&gt;
&lt;li&gt;위치 값&lt;/li&gt;
&lt;li&gt;class 변경&lt;/li&gt;
&lt;li&gt;브라우저의 창 크기 조정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;font-family&lt;/code&gt;, &lt;code&gt;font-size&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;display&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;위치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치 변화는 &lt;code&gt;position&lt;/code&gt; 프로퍼티를 사용하는게 좋다.&lt;br /&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;code&gt;position: fixed&lt;/code&gt;로 뷰포트를 기준으로 절대적인 위치를 줄 수 있다.&lt;br /&gt;가까운 부모에 &lt;code&gt;position: relative&lt;/code&gt;를 주고, 변경될 요소는 &lt;code&gt;position: absolute&lt;/code&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;br /&gt;그러므로 변경이 되도 DOM 트리에 영향을 주지 않는 따로국밥 흐름을 가진다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;className&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스명이 바뀌면 자식 트리 구조까지 탐색하고 변경한다.&lt;br /&gt;그래서 클래스명을 바꿔야 할 때는 최대한 하위 노드에서 변경해서 reflow를 최소화 할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;브라우저의 크기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저의 크기가 바뀔 때 요소들에 변화가 일어나기도 한다. (반응형)&lt;br /&gt;재정렬이 필요하므로 reflow가 발생한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Repaint와 Reflow&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교적 단순한 Repaint부터 소개했다.&lt;br /&gt;그렇지만 DOM 렌더링은 reflow -&amp;gt; repaint 순서다.&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;동시에 repaint와 reflow 프로세스가 트리거되는 작업도 있다.&lt;/p&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;properties&lt;/th&gt;
&lt;th&gt;reflow&lt;/th&gt;
&lt;th&gt;repaint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;display: none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;visibility: hidden&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;font-family, &lt;/code&gt;&lt;code&gt;font-size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;background-color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;margin, padding, border-width, border-style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Window resize&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Window scroll&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reflow와 repaint의 트리거 요인을 이해했다면 다른 트리거 작업도 유추가 가능할 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최적화 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;display&lt;/code&gt; 속성은 reflow와 repaint 발생 모두 해당된다.&lt;br /&gt;2번의 계산을 일으키니까 지양해야 할 것 같다.&lt;br /&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;다음 글에서는 reflow와 repaint 계산을 최소화하는 방법에 대해 더 알아 보겠다.&lt;/p&gt;</description>
      <category>Web</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/56</guid>
      <comments>https://minimal-dev.tistory.com/56#entry56comment</comments>
      <pubDate>Tue, 23 May 2023 23:56:39 +0900</pubDate>
    </item>
    <item>
      <title>Webpack 개발 환경에 따라 환경변수 설정하기</title>
      <link>https://minimal-dev.tistory.com/55</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&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;이를 위해 webpack에서 dotenv와 definePlugin을 사용한다.&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;실제 회사에서 개발 환경은 Dev, Beta, Stage, Operation(Production) 과 같이 구분됩니다.&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;그렇지만 우리가 작업하는 로컬인 Dev와 실제 적용된 운영(Production) 환경은 공통됩니다.&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;환경에 따라 크게 다른 부분은 API의 Base URL이 있습니다.&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;이 외에도 환경변수가 필요한 경우는 API의 private한 key값을 숨겨야 하는 경우도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;.env&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경변수를 설정할 파일들을 만듭니다.&lt;br /&gt;이 글에서는 두 개발환경(dev, prod)에 따른 환경변수 파일을 만듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;프로젝트마다 환경변수 파일의 위치는 다를 수 있습니다.&lt;br /&gt;저는 root에서 생성하겠습니다.&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;code&gt;&amp;lt;KEY&amp;gt;=&amp;lt;VALUE&amp;gt;&lt;/code&gt;의 JSON 형태로 이루어져 있습니다.&lt;br /&gt;value는 string입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 개발&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 환경(local)에서 적용될 환경변수 파일입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;./.env.dev&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;API_BASE_URL='http://localhost:8080'&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 배포&lt;/h3&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;&lt;b&gt;/.env&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;API_BASE_URL='http://prod-apiurl.com:8080'&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 패키지 관리 파일인 &lt;code&gt;package.json&lt;/code&gt;에서 npm 스크립트를 추가합니다.&lt;br /&gt;로컬에서 적용될 커맨드는 &lt;code&gt;NODE_ENV=development&lt;/code&gt;, 배포 환경은 &lt;code&gt;NODE_ENV=production&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt; &quot;scripts&quot;: {
    &quot;start&quot;: &quot;NODE_ENV=development webpack-dev-server --config webpack.dev.js --open&quot;,
    &quot;build&quot;: &quot;rm -rf dist &amp;amp;&amp;amp; NODE_ENV=production webpack --config webpack.prod.js&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;EnvironmentPlugin은 필요하지 않습니다.&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;또한 여러명이 window, mac 다양한 OS를 이용하는 프로젝트라면 cross-env 모듈도 확인해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Dotenv&lt;/h2&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;npm i -D dotenv-webpack&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dotenv와는 다르니 확인하고 설치를 진행하세요.&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;dotenv란 &lt;code&gt;.env&lt;/code&gt; 파일에 선언한 환경 변수들을 &lt;code&gt;process.env&lt;/code&gt;에 로드해주는 zero-dependency 모듈입니다.&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;webpack 설정을 합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;const Dotenv = require('dotenv-webpack')

module.exports = {
    ...
  plugins: [
    new Dotenv({
      path: process.env.NODE_ENV === 'production' ? '.env' : '.env.dev',
    }),
  ],
}&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DefinePlugin&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 설정된 process.env 변수들은 node.js 런타임에만 존재합니다.&lt;br /&gt;그래서 webpack이 빌드되는 시점에 선언해주기 위해 webpack의 내장 plugin을 이용합니다.&lt;/p&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;...
const webpack = require('webpack')

module.exports = {
    ...
  plugins: [
    ...
    new webpack.DefinePlugin({
      PRODUCTION: process.env.NODE_ENV === 'production', // 개발할 때 분기처리를 위해 선언
      API_URL: JSON.stringify(process.env.API_URL),
    }),
  ],
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 환경일 경우 분기처리를 아래의 전역변수로 이용할 수 있게 되었습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;function App() {
  console.log('production', PRODUCTION) // true나 false
}&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;API의 URL도 아래와 같이 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;{
  API_BASE_URL: process.env.API_BASE_URL
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고하면 좋을 글&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ui.toast.com/weekly-pick/ko_20191212&quot;&gt;개발(Development) 모드는 어떻게 작동할까?&lt;/a&gt;&lt;/p&gt;</description>
      <category>Tools/Webpack</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/55</guid>
      <comments>https://minimal-dev.tistory.com/55#entry55comment</comments>
      <pubDate>Wed, 3 May 2023 00:04:56 +0900</pubDate>
    </item>
    <item>
      <title>XSS공격이란? 사용 예시</title>
      <link>https://minimal-dev.tistory.com/54</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;XSS 공격&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cross Site Scripting의 약어입니다. CSS가 맞는 줄임이겠지만, 이미 스타일시트로 보편화되어 사용되고 있는 CSS가 있지요.&lt;br /&gt;그래서 CSS가 아니라 XSS로 줄여서 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XSS 공격은 DOM에 악성 &lt;b&gt;자바스크립트 코드를 삽입하여 공격하는 기법&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-28 오후 10.44.29.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCbaYO/btsdbOUFQ72/gEQK8RNSObmYVz50X4pUxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCbaYO/btsdbOUFQ72/gEQK8RNSObmYVz50X4pUxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCbaYO/btsdbOUFQ72/gEQK8RNSObmYVz50X4pUxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCbaYO%2FbtsdbOUFQ72%2FgEQK8RNSObmYVz50X4pUxk%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;1310&quot; height=&quot;416&quot; data-filename=&quot;스크린샷 2023-04-28 오후 10.44.29.png&quot; data-origin-width=&quot;1310&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력창에서 이렇게 스크립트를 삽입할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;lt;input type=&quot;text&quot; id=&quot;name&quot; /&amp;gt;
&amp;lt;button onclick=&quot;displayMessage()&quot;&amp;gt;Submit&amp;lt;/button&amp;gt;

&amp;lt;div id=&quot;message&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function displayMessage() {
    var name = document.getElementById('name').value;
    document.getElementById('message').innerHTML = 'Welcome, ' + name + '!';
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;공격의 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 삽입해 어떤 공격을 할 수 있을까요?&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자의 쿠키를 탈취하는 스크립트&lt;br /&gt;로그인을 구현하다 보면 쿠키에 사용자 정보가 담겨 있을 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;악성 파일이 있는 곳으로 리다이렉트&lt;br /&gt;버튼이나 이미지 등을 삽입하여 악성파일이 있는 곳으로 유도할 수도 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-28 오후 11.19.24.png&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7kpK7/btsdaAWR5PA/RLwKCe2Pjor0EAeH1UPDp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7kpK7/btsdaAWR5PA/RLwKCe2Pjor0EAeH1UPDp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7kpK7/btsdaAWR5PA/RLwKCe2Pjor0EAeH1UPDp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7kpK7%2FbtsdaAWR5PA%2FRLwKCe2Pjor0EAeH1UPDp1%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;1304&quot; height=&quot;424&quot; data-filename=&quot;스크린샷 2023-04-28 오후 11.19.24.png&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;424&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 XSS 공격 기법을 이용해 사용자에게 다양한 공격을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;XSS 공격 방지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시로 보면 사용자가 입력할 때 처리가 필요해 보입니다.&lt;br /&gt;HTML 태그나 특수문자가 입력되지 않도록 유효성 검사를 하거나, 삽입되기 전에 인코딩을 해야 합니다.&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;lt;script&amp;gt;를 입력창에 작성하지만, 삽입할 때 &amp;lt;같은 태그를 &amp;amp;gt;, &amp;gt;는 &amp;amp;lt;로 변환해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 DOM에는 &lt;code&gt;&amp;amp;gt;script&amp;amp;lt;&lt;/code&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;그리고 innerHTML 메소드 사용을 지양해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시들처럼 직접 DOM 조작이 가능해지기 때문입니다.&lt;/p&gt;</description>
      <category>Javascript</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/54</guid>
      <comments>https://minimal-dev.tistory.com/54#entry54comment</comments>
      <pubDate>Fri, 28 Apr 2023 23:30:07 +0900</pubDate>
    </item>
    <item>
      <title>Polling이란 (Polling과 API 호출은 같지 않다)</title>
      <link>https://minimal-dev.tistory.com/53</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Polling이 무엇인지 알아보기에 앞서 Web 통신의 특성에 대해 알아야 합니다.&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;Web&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 통신은 클라이언트가 서버에 요청을 하고, 응답을 받으면 연결이 끊어지는 특징이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 &lt;b&gt;비연결성(Connectionless)&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Polling 방식을 통해서 실시간처럼 보이도록&lt;/b&gt; 할 수 있습니다.&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;폴링(Polling)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴링은 업데이트가 갱신되었을 때, 이를 확인하기 위해 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 말해 새로운 데이터를 계속 보여주기 위해 &lt;b&gt;반복적으로 API 요청을 하는 방식&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 인스타그램과 같은 SNS에 폴링을 적용한다면&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;작동 순서는 대략 이럴 것입니다.&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. 초기 렌더링이 될 때, 서버에서 최신 피드를 받아오기 위한 API 요청이 처음 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 30초 후 - 클라이언트 사이드에서 새 글이 있는 지 확인하기 위해 또 API 요청을 보냅니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 새 글이 있다면 그에 대한 데이터를 받고, 클라이언트 측에서는 리렌더링이 일어납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 그리고 다시 30초 후 API 요청을 보내는 사이클이 이루어 집니다.&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;30초는 임시로 정한 타이머 값입니다. 요청에 대한 간격은 상황에 따라 달라집니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;폴링을 구현하는 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에서 바로 &lt;code&gt;SetInterval&lt;/code&gt; 메소드가 떠오르셨을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드를 이용하여 간격에 맞추어 API 요청을 할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1682262410534&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setInterval(function() {
  getDataFromServer();
}, 30000);

function getDataFromServer() {
  ...
}&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;/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;/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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;폴링은 API 호출 방식 중의 하나&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실시간으로 최신 데이터를 보여주기 위해 &lt;b&gt;반복적으로 API 호출&lt;/b&gt;을 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- HTTP의 비연결성 특징을 보완한다.&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</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/53</guid>
      <comments>https://minimal-dev.tistory.com/53#entry53comment</comments>
      <pubDate>Mon, 24 Apr 2023 00:03:39 +0900</pubDate>
    </item>
    <item>
      <title>프로퍼티의 게터와 세터</title>
      <link>https://minimal-dev.tistory.com/52</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서 객체는 프로퍼티(Property, 속성)를 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 프로퍼티는 이름과 값이 있습니다. &lt;b&gt;이름은 문자열이고, 값은 어떤 타입&lt;/b&gt;이든 가리지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;const obj = {
 name: &quot;객체&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로퍼티는 추가, 삭제가 가능합니다. 그러므로 객체는 프로퍼티의 집합이기도 합니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;데이터 프로퍼티(Data Property)&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;const person = {
 age: 15, // 데이터 프로퍼티
 name: &quot;김개굴&quot; // 데이터 프로퍼티
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 프로퍼티 대부분은 이름과 값이 있는 데이터 프로퍼티입니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;접근자 프로퍼티(Accessor Property)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 데이터 프로퍼티와는 좀 다른 모양새입니다.&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;이 프로퍼티는 &lt;b&gt;접근자 메서드 게터(Getter)와 세터(Setter)를 지원&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;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;obj 객체의 name 값을 읽거나 수정하고 싶다면 이렇게 하면 되지 않나요?&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;const objName = obj.name;
obj.name = &quot;김야옹&quot;&lt;/code&gt;&lt;/pre&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;/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;그래서 &lt;b&gt;의도하지 않았던 변경을 막을 수 있고&lt;/b&gt;, 조건을 추가하여 수정이 가능하도록 할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;let person = {
 age: 15, 
 name: &quot;김개굴&quot;.

 get accessorName() {
  return this.name
 }

 set accessorName(newName) {
  if(newName.length &amp;gt; 4) {
   console.log('4글자가 넘는 이름은 변경할 수 없습니다.')
  } else {
    this.name = newName
  }
 }
}

person.accessorName = &quot;김야옹&quot; // person = { _name: &quot;김야옹&quot; }
person.accessorName = &quot;개굴개굴개굴&quot; // console.log('4글자가 넘는 이름은 변경할 수 없습니다.')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게터 메서드는 인자없이 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;name 게터 메서드는 단순히 값을 반환합니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;person.name = &quot;김야옹&quot;&lt;/code&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;이 코드에서 작성된 name 세터 메서드는 유효성 검사가 통과할 때만 값이 업데이트 됩니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;name 프로퍼티의 경우는 게터와 세터가 모두 있습니다. 읽기와 쓰기가 모두 가능한 프로퍼티라는 의미입니다.&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;/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;만약 이름을 반환할 때, 나이도 같이 반환하고 싶을 때에도 키워드 this를 활용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;let person = {
 age: 15, 
 name: &quot;김개굴&quot;.

 get accessorName() {
  return `${this.name} (${this.age})`
 }

  ...
 }

return person.accessorName // 김개굴 (15)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서 게터와 세터는 객체의 메서드로 호출되므로 this는 객체 person을 가리킵니다.&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;/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;/h3&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;프로퍼티는 이름과 값이 있다.&lt;/li&gt;
&lt;li&gt;객체의 접근자 프로퍼티에 Getter와 Setter가 있다.&lt;/li&gt;
&lt;li&gt;함수처럼 호출되며 데이터 프로퍼티처럼 접근한다.&lt;/li&gt;
&lt;li&gt;접근자 프로퍼티는 접근자 메서드 Getter와 Setter를 갖는다.&lt;/li&gt;
&lt;li&gt;이 메서드들은 원치 않는 변경을 방지하여 코드의 안전성과 유지보수성을 위해 사용된다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Javascript</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/52</guid>
      <comments>https://minimal-dev.tistory.com/52#entry52comment</comments>
      <pubDate>Wed, 12 Apr 2023 23:31:59 +0900</pubDate>
    </item>
    <item>
      <title>사파리에서 SVG 렌더링 이슈 해결하기</title>
      <link>https://minimal-dev.tistory.com/51</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;체크박스 아이콘의 테두리가 잘려 보인다는 QA 요청이 왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈 재현을 해보니 사파리 브라우저에서만 발생하는 이슈였습니다.&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;개발자 도구로 스타일 조작을 해봐도 요지부동이었습니다.&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;그러면 제가 찾아 보았던 방법과 결과를 정리해 보겠습니다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Safari에서 SVG 아이콘 픽셀이 깨짐 (정상 렌더링이 되지 않음)&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Safari 자체에서 SVG 지원이 완벽하지 않음&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;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;img 태그 사용하기&lt;/li&gt;
&lt;li&gt;svg view box 수정&lt;/li&gt;
&lt;li&gt;svg에 attribute 추가&lt;/li&gt;
&lt;li&gt;svg width와 height 단위 변경&lt;/li&gt;
&lt;li&gt;아이콘의 border만 css로 처리하기&lt;/li&gt;
&lt;li&gt;svg 디자인 직접 수정하기 (✅ 이 방법으로 선택했습니다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;img 태그 사용하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지화가 되기 때문에 픽셀 깨짐을 바로 해결할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 태그 사용에서 첫번째로는 직접 경로를 작성하는 방법이 있습니다. (정적 경로)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하지만 이 방법은 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;hover, pressed 같은 마우스 이벤트가 발생해도 이미지가 업데이트 되지 않는 문제가 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1680432075873&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;/static/img/icon_checkbox_normal.svg&quot;&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;그래서 변경이 필요하다면 이미지 모듈화가 필요합니다. 이미지를 모듈화하여 Data-URI 형식으로 인코딩합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680433636628&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;data:image/svg+xml;base64,해시값&amp;rdquo;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;테스트했을 때 모듈화하면 이미지가 이벤트 때마다 정상적으로 업데이트었습니다.&lt;/span&gt;&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;h4 data-ke-size=&quot;size20&quot;&gt;SVG Viewbox 수정&lt;/h4&gt;
&lt;pre id=&quot;code_1680433660856&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;svg viewbox=&quot;0 0 15 14.999&quot; ... /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이슈가 있는 svg 파일의 viewbox에서 소수로 된 부분을 정수로 수정했습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;SVG에 attribute 추가하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shape-rendering 속성을 추가하면 된다는 아티클을 보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shape-rendering: crispedges&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;SVG width와 height 단위 변경&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반응형 지원을 위해 컴포넌트들이 rem 단위로 작성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰포트가 변경될 때마다 정상 노출되기도, 테두리의 픽셀이 깨지기도 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 px 단위로 고정하면 되지 않을까 했습니다. 이전의 렌더링 상태보다는 나아졌지만 완벽하지는 않았습니다.&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;아이콘의 border만 css로 처리하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테두리가 깨져 보이는 문제이므로 border만 css로 처리하면 정상 렌더링될 것이라 생각했습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;SVG 디자인 직접 수정하기&lt;/h4&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;현재 아이콘은 viewbox가 꽉차게 디자인되어 있었는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;야매 방법이라 함은 &lt;b&gt;viewbox에 약간의 padding을 넣어서 svg 파일을 교체하기&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;/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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;효과 ❌&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;svg view box 수정&lt;/li&gt;
&lt;li&gt;svg에 attribute 추가&lt;/li&gt;
&lt;li&gt;svg width와 height 단위 변경&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;효과  &amp;zwj;♀️&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;img 태그 사용&lt;/li&gt;
&lt;li&gt;아이콘의 border만 css로 처리하기&lt;/li&gt;
&lt;li&gt;svg 디자인 직접 수정하기&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>HTML</category>
      <category>트러블슈팅</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/51</guid>
      <comments>https://minimal-dev.tistory.com/51#entry51comment</comments>
      <pubDate>Sun, 2 Apr 2023 20:11:56 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트 객체 정의와 생성 방법, 프로퍼티</title>
      <link>https://minimal-dev.tistory.com/50</link>
      <description>&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;h2 data-ke-size=&quot;size26&quot;&gt;객체란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;br /&gt;자바스크립트의 타입은 원시 타입과 객체 타입으로 나뉘어지죠&lt;/li&gt;
&lt;li&gt;프로퍼티의 순서없는 집합&lt;br /&gt;&lt;code&gt;const 객체 = { name: '김객체' , human: false }&lt;/code&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;br /&gt;자바스크립트가 프로토타입 기반의 객체지향 프로그래밍 언어라고 불리우는 이유입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프로퍼티&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로퍼티는 &lt;b&gt;이름과 값&lt;/b&gt;으로 이루어져 있습니다.&lt;br /&gt;이름은 문자열이나 심벌 타입을 가집니다. 보통 대부분의 이름은 문자열입니다.&lt;br /&gt;값은 이름과 다르게 타입을 가리지 않습니다. 어떤 타입도 가능하고 getter나 setter 또는 둘다가 될 수도 있습니다.&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;/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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체에서 직접 정의한 멍멍이 객체에 age라는 자체 프로퍼티가 생겼습니다.&lt;br /&gt;또한 멍멍이는 Object.prototype 이라는 객체 메서드를 상속합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680099471118&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let 멍멍이 = {} 
멍멍이.age = 3&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상속받은 프로퍼티&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입 객체에서 상속한 뎅뎅이 객체는 멍멍이와 Object.prototype에서 프로퍼티를 상속합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1680099433093&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let 뎅뎅이 = Object.create(멍멍이)
뎅뎅이.age // 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Object.create()는 객체를 생성하는 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;객체 생성&lt;/h2&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;h3 data-ke-size=&quot;size23&quot;&gt;객체 리터럴&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두에게 익숙한 방법이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 리터럴은 콜론으로 이름과 값을 구분하고, 이 쌍들을 콤마로 구분해 중괄호로 감싼 형태입니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;let x = {} // 프로퍼티가 없는 개체
let abc = { a: 0, b: 1, c: 2 }&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;new 키워드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new 연산자는 객체를 &lt;b&gt;생성&lt;/b&gt;하고 &lt;b&gt;초기화&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new 키워드 뒤에는 반드시 함수 호출이 있어야 합니다. 이런 함수를 생성자라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 생성자는 새로 생성된 객체를 초기화합니다.&lt;br /&gt;우리가 익히 알고 있는 자바스크립트에 내장된 생성자들이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;let obj = new Object();
let arr = new Array();
let day = new Date();
let map = new Mpa();&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Object.create() 함수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 인자를 프로토타입 삼아 새 객체를 생성합니다.&lt;/p&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;let xy = Object.create({x: 1, y: 2}) 
xy.x + xy.y //3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xy객체는 x와 y 프로퍼티를 상속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 첫번째 인자에 null을 전달할 수도 있습니다. null을 프로토타입 삼는 것이 되는데&lt;br /&gt;즉, 프로토타입이 없는 객체가 생성됩니다.&lt;br /&gt;이렇게 생성된 객체는 아무것도 상속하지 않으며 기본 메서드조차 없는.. 정말 뭐가 없는 객체입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let empty = {} 
let empty2 = new Object()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 리터럴과 new 연산자를 이용해 생성한 빈 객체입니다.&lt;br /&gt;Object.create() 함수에서도 null 없이도 일반적인 빈 객체를 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;let obj = Object.create(Object.prototype)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Object.prototype을 전달하여 일반적인 프로토타입을 가진 빈 객체가 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&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;프로퍼티를 가질 수 있고, 프로토타입이라는 객체로 인해 다른 객체를 상속받을 수 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Javascript</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/50</guid>
      <comments>https://minimal-dev.tistory.com/50#entry50comment</comments>
      <pubDate>Wed, 29 Mar 2023 23:18:51 +0900</pubDate>
    </item>
    <item>
      <title>로그인이 복잡한 이유 1. 세션과 토큰</title>
      <link>https://minimal-dev.tistory.com/47</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그인이 뭔지 아세요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q. 로그인은 무엇일까?&lt;br /&gt;A. 인증된 사용자라는 것을 알려주기 위한 기능&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;Q. 어떻게 구현해야 할까?&lt;br /&gt;A. JWT 토큰&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;br /&gt;공부를 하기 전에 생각한 제 대답입니다.&lt;br /&gt;제가 어떻게 이해했고, 결론은 어떻게 내렸는 지 써보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;알아볼까요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 서비스에나 있는 로그인과 로그아웃은 간단해 보입니다.&lt;br /&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;&lt;b&gt;사용자가 서비스에 머무는 동안 로그인이 잘 되어 있도록 사용성을 중시해야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그인의 문제점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현에 앞서서 알아야 하는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인을 공부하다 보면 서버와 보안에 대해 알게 됩니다!&lt;/p&gt;
&lt;p&gt;&lt;del&gt;(또 여기서 모르는 용어 나오면 무한 학습 루프에 빠짐...ㅎ)&lt;/del&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size26&quot;&gt;✅ HTTP의 비연결성&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인의 문제점은 HTTP 특성에 있습니다.&lt;br /&gt;HTTP는 인터넷 상에서 데이터를 주고 받기 위한 통신 프로토콜이자 &lt;b&gt;규약&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 서버에게 요청을 보내면 서버는 응답을 보내는 과정을 통해 데이터를 교환합니다.&lt;br /&gt;이렇게 &lt;b&gt;요청과 응답의 처리 과정이 끝나면 HTTP는 연결을 끊어 버립니다.&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;HTTP의 비연결성&lt;/b&gt;이라는 특징입나다.&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;사용자의 로그인을 요청하고, 서버는 이에 관련해 응답합니다.&lt;br /&gt;응답이 성공하여 로그인이 이루어졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 한 번의 요청과 응답 과정이 이루어 졌으니 연결이 끊어집니다.&lt;br /&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;br /&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;h2 data-ke-size=&quot;size26&quot;&gt;인증 유지 방법&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Session ID를 이용하는 방식&lt;/li&gt;
&lt;li&gt;토큰을 이용하는 방식&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size26&quot;&gt;  Session 기반 인증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Session ID를 이용하는 방식은 아래의 순서로 이루어 집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(C는 Client, S는 Server)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;C: 로그인 요청&lt;/li&gt;
&lt;li&gt;S: 세션 생성&lt;/li&gt;
&lt;li&gt;S: 생성된 세션의 ID를 클라이언트에 응답&lt;/li&gt;
&lt;li&gt;C: 클라이언트를 이 세션 ID를 저장하고 있다가 인증이 필요할 때 이 값을 서버에 전송&lt;/li&gt;
&lt;li&gt;S: 서버는 세션을 불러와 유효한 값인지 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Q. 세션과 세션 스토리지는 같을까?&lt;br /&gt;다릅니다!&lt;br /&gt;여기서 말하는 Session은 Session Storage와 다릅니다.&lt;br /&gt;세션은 서버에서 생성하고, 세션 스토리지는 클라이언트에서 관리합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세션은 서버 기반 인증이기도 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size26&quot;&gt;  Token 기반 인증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 토큰을 이용해서 자신의 신원을 확인하고,&lt;b&gt; 자격 증명을 의미하는 토큰을 받는 프로토콜&lt;/b&gt;입니다.&lt;br /&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;요청 -&amp;gt; 확인 -&amp;gt; 토큰 -&amp;gt; 저장소&lt;/b&gt;의 과정으로 진행됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;보통 아이디와 비밀번호를 서버에 보내 액세스를 요청합니다. (로그인 시도)&lt;/li&gt;
&lt;li&gt;서버가 확인하여 권한이 있는 사용자인지 확인합니다.&lt;/li&gt;
&lt;li&gt;확인 후에 서버는 토큰을 발급하고 로그인 요청에 응답합니다. (권한이 있다면 로그인 성공)&lt;/li&gt;
&lt;li&gt;이 토큰은 유효 기간동안 브라우저에 저장됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 토큰은 천년만년 가지고 있을 수 없구요. &lt;b&gt;유효 기간&lt;/b&gt;이 있습니다.&lt;br /&gt;이 기간동안 &lt;b&gt;접근(Access)을 허용하는 Access Token&lt;/b&gt;을 받게 되는 것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;유효 기간은 서비스의 정책에 따라 다르게 설정합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그인에 토큰을 왜 사용해야 하나요?&lt;/h2&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;과거에는 로그인 구현에 있어서 비밀번호에서 세션 기반 인증이 사용되었습니다.&lt;br /&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;할 수 있겠죠.&lt;br /&gt;그래서 Scale-out 인프라에서는 여러 대의 서버가 있는 경우, 요청이 분산되고 각각의 서버에서 처리합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Scale-out: 인프라 확장을 위하여 서버를 여러대 추가해서 확장하는 방식&lt;br /&gt;Scale-up: 기존 서버의 사양을 업그레이드하는 방식&lt;/blockquote&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-filename=&quot;session.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zFMVF/btr4uJ9aoLb/V1cPOWvcOVgfg43AINCpk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zFMVF/btr4uJ9aoLb/V1cPOWvcOVgfg43AINCpk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zFMVF/btr4uJ9aoLb/V1cPOWvcOVgfg43AINCpk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzFMVF%2Fbtr4uJ9aoLb%2FV1cPOWvcOVgfg43AINCpk0%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;1024&quot; height=&quot;768&quot; data-filename=&quot;session.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 로그인을 하고&lt;/li&gt;
&lt;li&gt;해당 사용자의 정보를 담은 세션 객체 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세션 객체(Session ID)들은 하나의 저장소(세션 스토리지)에서 관리됩니다.&lt;br /&gt;여러 서버에서 공유되어야 하기 때문입니다.&lt;br /&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;그래서&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;br /&gt;서버 측에서 유지보수가 필요없기 때문에 토큰 기반 인증 방식이 선호되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Q. 세션 스토리지가 서버에도..?&lt;br /&gt;위에서 말하는 세션 스토리지는 서버에 있는 것입니다. 브라우저에 있는 세션 스토리지와는 다릅니다.&lt;br /&gt;브라우저의 세션 스토리지는 클라이언트에서 사용하는 웹 스토리지입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;요약&lt;/h2&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;요청&amp;harr;️응답 과정이 끝나면 연결이 끊어지는 HTTP의 비연결성때문에 인증 방식이 필요하다.&lt;/li&gt;
&lt;li&gt;Session 방식은 서버 측의 부담이 크고, Token은 그렇지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 JWT를 이용한 토큰 기반 인증에 대해서 자세히 알아 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글을 보기 전에 JWT와 토큰이 같은걸까? 에 대해 생각해보면 좋을 것 같습니다.&lt;/p&gt;</description>
      <category>Server</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/47</guid>
      <comments>https://minimal-dev.tistory.com/47#entry47comment</comments>
      <pubDate>Sun, 19 Mar 2023 00:53:24 +0900</pubDate>
    </item>
    <item>
      <title>Javascript 객체 복제 Object.assign 요약과 React 적용</title>
      <link>https://minimal-dev.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;API에서 날려주는 데이터를 UI에 더 잘 뿌려주기 위해 꼭 알아야 할 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 자세한 개념을 다루지 않고, 제가 기억하고 싶은 부분 중심으로 작성했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;구조&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;Object.assign(target, ...sources)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Object.assign({초기값, 객체들})&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;❓&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;왜 쓰는가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 객체를 복제하고 싶을 때, 쉽게 이용할 수 있는 방법은 또 다른 변수에 객체를 담는 것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1637589539343&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const user = {
	name: &quot;gaegul&quot;,
    gender: &quot;female&quot;
}

const newUser = user; // newUser에 user를 복제

console.log(newUser.name) // gaegul&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;newUser은 user의 내용을 똑같이 담고 있습니다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;newUser에서 뭔가를 바꾸면, user에도 반영이 되는 것입니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1637589716168&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;newUser.age = 99

console.log(newUser)

// ----- Output -----
// newUser: {name: 'gaegul', gender: 'female', age: 99}
// user: {name: 'gaegul', gender: 'female', age: 99}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 newUser에만 새로운 값을 추가했는데, user에도 추가되었습니다.&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;원래 user 데이터가 지켜지지 않습니다.&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;span&gt;✅&amp;nbsp;&lt;/span&gt;객체를 복제하는 방법&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Object.assign을 이용합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1637590158622&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const newUser = Object.assign({}, user); // {}는 초기값 

newUser.name = 'newGaegul'

// ---- Output -----
// newUser: {name: 'newGaegul', gender: 'female', age: 99}
// user: {name: 'gaegul', gender: 'female', age: 99}&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React action이랑 reducer에서 매일 복붙해서 사용중입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1637590656390&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Action
export const setNewRequest = (data) =&amp;gt; (dispatch, getState) =&amp;gt; {
  const store = getState();

  dispatch({
    type: SET_NEW_REQUEST,
    payload: Object.assign({}, store.data, data)
  })
}


// Reducer
const initialState = {
	newRequestData: []
}

export default function RequestReducer(state = initialState, action) {
  switch(action.type) {

    case SET_NEW_REQUEST:
      return Object.assign({}, state, {newRequestData: action.payload}); 
      
    default: return state;
  }
}&lt;/code&gt;&lt;/pre&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;span&gt; &amp;nbsp;&lt;/span&gt;참조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6NZpyA64ZUU&amp;amp;list=PLZKTXPmaJk8JZ2NAC538UzhY_UNqMdZB4&amp;amp;index=3&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>Javascript</category>
      <author>개굴이 dev</author>
      <guid isPermaLink="true">https://minimal-dev.tistory.com/41</guid>
      <comments>https://minimal-dev.tistory.com/41#entry41comment</comments>
      <pubDate>Mon, 22 Nov 2021 23:29:16 +0900</pubDate>
    </item>
  </channel>
</rss>