<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>천진난만 코딩 스토리</title>
    <link>https://innocentcodingstory.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 2 Jul 2026 09:53:02 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Wisdom_1104</managingEditor>
    <image>
      <title>천진난만 코딩 스토리</title>
      <url>https://tistory1.daumcdn.net/tistory/5464771/attach/03a8ccba24194f6a8898708c9576a1b9</url>
      <link>https://innocentcodingstory.tistory.com</link>
    </image>
    <item>
      <title>2023.06.17) 타입스크립트의 클래스 &amp;amp; 인터페이스 (2)</title>
      <link>https://innocentcodingstory.tistory.com/197</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1.&lt;span&gt; Type&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type 의 특징을 몇 가지 짚어보자면,&lt;/p&gt;
&lt;pre id=&quot;code_1685107317475&quot; class=&quot;rust&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;// 1, 2
type Health = number;
// 3
type Team = &quot;red&quot; | &quot;blue&quot; | &quot;yellow&quot;;

type Player = { nickname: string; team: Team; health: Health };

const rhino: Player = {
  nickname: &quot;ori&quot;,
  team: &quot;blue&quot;,
  health: 1,
};&lt;/code&gt;&lt;/pre&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;Type alias를 만들어줄 수 있다.&lt;/li&gt;
&lt;li&gt;타입을 특정한 값을 가지도록 제한할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Interface&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;type과 비슷한 것이 있는데, 바로 interface 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오브젝트 모양을 타입스크립트에게 설명해 주기 위한 키워드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, type보다 활용도는 떨어지지만 간단하게 나타낼 때 좋다.&lt;/p&gt;
&lt;pre id=&quot;code_1685107727083&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//type
type Player = {
  nickname: string;
  team: Team;
  health: Health;
}
//interface
interface Player {
  nickname: string;
  team: Team;
  health: Health;
}&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;interface의 또 다른 특징으로는 속성들을 '축적'시킬 수 있다는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1685107872092&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
  name: string;
}
interface User {
  lastName: string;
}
interface User {
  health: number;
}
const ori: User = { name: &quot;ori&quot;, lastName: &quot;p&quot;, health: 5 };&lt;/code&gt;&lt;/pre&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;span&gt;3. Type과 &lt;b&gt;Interface 차이점&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1) 타입을 특정한 값이나 alias 자체를 interface가 설정하지 못한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① type&lt;/p&gt;
&lt;pre id=&quot;code_1687003026279&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// O
type Team = &quot;red&quot; | &quot;blue&quot; | &quot;yellow&quot;;
type Mumber = number;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;② interface&lt;/p&gt;
&lt;pre id=&quot;code_1687000582893&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// X
interface Team = &quot;red&quot; | &quot;blue&quot; | &quot;yellow&quot;;
interface Mumber = string;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2) 상속받는 문법 및 중복 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① type&lt;/p&gt;
&lt;pre id=&quot;code_1687003107763&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type A = {
  firstName: string;
};

type AA = A &amp;amp; {
  lastName: string;
};

// 불가능
// 이미 선언되어서 중복이 안됨
type AA = {
  age: number;
};&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;②&lt;span&gt;&amp;nbsp;&lt;/span&gt;interface&lt;/p&gt;
&lt;pre id=&quot;code_1687003190013&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface B {
  firstName: string;
}
interface BB extends B {
  lastName: string;
}
// 가능
interface BB {
  age: number;
}
// 가능
interface B {
  lastName: string;
  age: number;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. Interface 사용&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 객체 지향과 비슷한 문법을 사용해 &lt;b&gt;extends&lt;/b&gt;로 상속받을 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687003449405&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
  name: string;
  readonly age: number; //읽기 전용
}
interface Player extends User {}

const Olaf: Player = {
  name: &quot;Olaf&quot;,
  age: 5,
};
Olaf.age = 7; // X, 읽기 전용 속성이므로 'age'에 할당할 수 없습니다.&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;2)&amp;nbsp; 추상 클래스를 Interface와 접목 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687003728075&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class User {
  constructor(
    protected firstName: string, 
    protected lastName: string
  ) {}
  abstract sayHi(name: string): string;
  abstract fullName(): string;
}
class Player extends User {
  fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string) {
    return `Hello ${name}. My name is ${this.fullName()}`;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 User를 직접적으로 만지지않고, 상속받고 파생되는 클래스와 인스턴스로 사용할건데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS 컴파일 되도 남아있다. 이를 없애고 싶다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Interface를 사용하여 JS로 컴파일 시 사라지고, 클래스보다 훨씬 가벼우면서 교체가능하도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1687003935516&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface User {
  firstName: string;
  lastName: string;
  sayHi(name: string): string;
  fullName(): string;
}
class Player implements User {
  constructor(
    public firstName: string, 
    public lastName: string
  ) { }
  fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
  sayHi(name: string) {
    return `Hello ${name}. My name is ${this.fullName()}`;
  }
}&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;추상클래스는&amp;nbsp;interface로 바꾼다.&lt;/li&gt;
&lt;li&gt;implements&amp;nbsp;키워드를 써서&amp;nbsp;User를 구현해야하는(추상클래스 상속)&amp;nbsp;Player&amp;nbsp;클래스 생성한다.&lt;/li&gt;
&lt;li&gt;추상클래스에 썼던 생성자를 작성한다.&lt;span style=&quot;color: #666666;&quot;&gt;&lt;br /&gt;(보호레벨을 public으로 받는다. 인터페이스를 상속받을 땐 다른 레벨이 아닌 public로만 받아야한다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;구현한 메소드도 그대로 작성한다.&lt;/li&gt;
&lt;li&gt;2개 이상의 인터페이스를 상속받을 수 있다.&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;3) 함수형에서 사용&lt;/p&gt;
&lt;pre id=&quot;code_1687004401579&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 파라미터에 User 적용
function makeUser(user: User) {
  return &quot;Hello!&quot;;
}

// return까지 User 타입으로
function makeUserReturn(user: User): User {
  return { 
  	firstName: &quot;Ol&quot;, 
    lastName: &quot;af&quot;, 
    fullName: () =&amp;gt; &quot;Xx&quot;, sayHi: (name) =&amp;gt; &quot;string&quot;
  };
}
makeUser({ 
	firstName: &quot;Ol&quot;, 
    lastName: &quot;af&quot;, 
    fullName: () =&amp;gt; &quot;Xx&quot;, sayHi: (name) =&amp;gt; &quot;string&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;&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>TIL(Today I Learned)</category>
      <category>extends</category>
      <category>Interface</category>
      <category>type</category>
      <category>추상클래스</category>
      <category>함수형</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/197</guid>
      <comments>https://innocentcodingstory.tistory.com/197#entry197comment</comments>
      <pubDate>Sat, 17 Jun 2023 21:22:32 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.05) Migratory Birds (2)</title>
      <link>https://innocentcodingstory.tistory.com/196</link>
      <description>&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 문제 및 예시&lt;/b&gt;&lt;/h4&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/zVPdj/btsiJ78Xn5p/o4pYlJBQDQIrFlUqotK7eK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zVPdj/btsiJ78Xn5p/o4pYlJBQDQIrFlUqotK7eK/img.png&quot; style=&quot;width: 43.1896%; margin-right: 10px;&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;665&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;43.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zVPdj/btsiJ78Xn5p/o4pYlJBQDQIrFlUqotK7eK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzVPdj%2FbtsiJ78Xn5p%2Fo4pYlJBQDQIrFlUqotK7eK%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;486&quot; height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dj7ftU/btsiFOPpsqQ/IEpfVygYKsjYpqpcDIi7J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dj7ftU/btsiFOPpsqQ/IEpfVygYKsjYpqpcDIi7J1/img.png&quot; style=&quot;width: 55.6476%;&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;514&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;56.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dj7ftU/btsiFOPpsqQ/IEpfVygYKsjYpqpcDIi7J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdj7ftU%2FbtsiFOPpsqQ%2FIEpfVygYKsjYpqpcDIi7J1%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;484&quot; height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 내가 푼 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1685900474506&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function migratoryBirds(arr) {
  let count = {};
  for (let i = 0; i &amp;lt; arr.length; i++) {
    if (count[arr[i]]) {
      count[arr[i]]++;
    } else {
      count[arr[i]] = 1;
    }
  }
  
  let max = 0;
  let most = 0;
  for (const bird in count) {
    if (count[bird] &amp;gt; max) {
      max = count[bird];
      most = bird;
    }
  }
  return most;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 풀이 설명&lt;/b&gt;&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;/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;</description>
      <category>코딩테스트.js/Hacker-Rank</category>
      <category>hackerrank</category>
      <category>JS</category>
      <category>Migratory Birds</category>
      <category>코딩테스트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/196</guid>
      <comments>https://innocentcodingstory.tistory.com/196#entry196comment</comments>
      <pubDate>Mon, 5 Jun 2023 19:50:41 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.04) Migratory Birds (1)</title>
      <link>https://innocentcodingstory.tistory.com/195</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 문제 및 예시&lt;/b&gt;&lt;/h4&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/cOF2XM/btsis1aOb88/Llkkxj53k5btMzIhjzMjVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOF2XM/btsis1aOb88/Llkkxj53k5btMzIhjzMjVk/img.png&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;665&quot; data-is-animation=&quot;false&quot; style=&quot;width: 43.1896%; margin-right: 10px;&quot; data-widthpercent=&quot;43.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOF2XM/btsis1aOb88/Llkkxj53k5btMzIhjzMjVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOF2XM%2Fbtsis1aOb88%2FLlkkxj53k5btMzIhjzMjVk%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;486&quot; height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TQe0U/btsivQZ6ByI/Q6ZyGWrSWxSU9S3nTR7YV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TQe0U/btsivQZ6ByI/Q6ZyGWrSWxSU9S3nTR7YV1/img.png&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;514&quot; data-is-animation=&quot;false&quot; style=&quot;width: 55.6476%;&quot; data-widthpercent=&quot;56.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TQe0U/btsivQZ6ByI/Q6ZyGWrSWxSU9S3nTR7YV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTQe0U%2FbtsivQZ6ByI%2FQ6ZyGWrSWxSU9S3nTR7YV1%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;484&quot; height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&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;2. 내가 푼 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1685899289733&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function migratoryBirds(arr) {
    // Write your code here
    let ar = arr.sort()
    let answer = 0;
    let max = 1;
    let count = 1;
    for(let i=0; i&amp;lt;ar.length; i++){
        count = (ar.lastIndexOf(ar[i]) - ar.indexOf(ar[i])) + 1;
        if(count&amp;gt;max){
            max=count;
            answer=ar[i]
        }
    }
    return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 풀이 설명&lt;/b&gt;&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;pre id=&quot;code_1685899385593&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for(let i=0; i&amp;lt;ar.length; i++){
        count = (ar.lastIndexOf(ar[i]) - ar.indexOf(ar[i])) + 1;
        if(count&amp;gt;max){
            max=count;
            answer=ar[i]
        }
    }&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;if문은 count가 max보다 커졌을 경우에만 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관건은,&lt;/p&gt;
&lt;pre id=&quot;code_1685899441951&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;count = (ar.lastIndexOf(ar[i]) - ar.indexOf(ar[i])) + 1;&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;span style=&quot;color: #8a3db6;&quot;&gt;ar.lastIndexOf(ar[i])&lt;/span&gt; 는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ar[i]인 요소 중 가장 마지막에 위치하는 자리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;ex) ar = [1,2,2,2,2,3,3,4] 에서 ar[2]인 요소는 2이고 2의 마지막 위치는 ar[4]이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;ar.indexOf(ar[i]))&lt;/span&gt; 는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ar[i]인 요소가 가장 처음에 위치하는 자리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;ex) ar = [1,2,2,3,3,4] 에서 ar[2]인 요소는 2이고 2의 처음 위치는 ar[1]이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 1 을 해주는 이유는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 새의 종류가 적어도 1번은 등장했다는 것을 의미한다.&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;ar[2]라면, 4-1+1 = 4가 되어 2가 4번 나왔다는 것을 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;count가 이 횟수보다 커지지 않으면 if문을 실행되지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2를 반환하게 되는 것이다.&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;다른 방법을 찾아보는걸로.....&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>코딩테스트.js/Hacker-Rank</category>
      <category>hackerrank</category>
      <category>JS</category>
      <category>Migratory Birds</category>
      <category>코딩테스트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/195</guid>
      <comments>https://innocentcodingstory.tistory.com/195#entry195comment</comments>
      <pubDate>Mon, 5 Jun 2023 02:31:36 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.02) position의 사용법</title>
      <link>https://innocentcodingstory.tistory.com/194</link>
      <description>&lt;h3 id=&quot;position-속성&quot; style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1. position&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CSS의 속성중 하나&lt;/li&gt;
&lt;li&gt;웹 문서 안 요소들을 어떻게 배치할 지를 정하는 속성&lt;/li&gt;
&lt;li&gt;position 속성을 이용하여 텍스트나 이미지같은 요소들을 원하는 곳에 위치&lt;/li&gt;
&lt;li&gt;&lt;b&gt;position의 종류&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;5가지&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static&lt;/li&gt;
&lt;li&gt;relative&lt;/li&gt;
&lt;li&gt;fixed&lt;/li&gt;
&lt;li&gt;absolute&lt;/li&gt;
&lt;li&gt;sticky&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1) static&lt;/b&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;static은 원래 있어야할 위치이며 기본값&lt;/li&gt;
&lt;li&gt;&lt;b&gt;position속성의 기본 값&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;다른 요소와의 관계에 의해 자동으로 배치&lt;/li&gt;
&lt;li&gt;top, left, right, bottom등의 offset 값을 지정 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2) relative&lt;/b&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;relative는 static인 상태에서의 위치를 기준으로 top, right, bottom, left로 지정된 거리만큼 이동하여 위치&lt;/li&gt;
&lt;li&gt;원래 있던 위치를 기준으로 좌표를 지정&lt;/li&gt;
&lt;li&gt;원래 있던 위치는 position : static(default) 이었을 때를 기준으로 좌표를 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;3) absolute&lt;/b&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;absolute는 &lt;b&gt;가장 가까운 static이 아닌 포지션을 가진&lt;/b&gt; 부모에 대해 상대적인 위치를 가짐&lt;/li&gt;
&lt;li&gt;포지션을 가지는 부모가 없다면 &lt;b&gt;body에 대해 상대적인 위치&lt;/b&gt;를 가짐&lt;/li&gt;
&lt;li&gt;원래 위치와 상관 없이 절대 좌표와 함께 위치를 지정 가능&lt;/li&gt;
&lt;li&gt;absolute 속성은 기준점이 중요&lt;/li&gt;
&lt;li&gt;absolute는 position 값이 static이 아닌 것 중 가장 가까운 요소(부모태그)를 기준&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;4) fixed&lt;/b&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;fixed는 위치를 지정하면 뷰포트(현재 화면에 보여지고 있는 직사각형의 영역, 전체화면)에 대해서 상대적인 위치를 차지함&lt;/li&gt;
&lt;li&gt;absolute속성과 비슷하게 문서의 흐름과 상관없이 절대 좌표와 함께 위치를 정해줌&lt;/li&gt;
&lt;li&gt;기준점은 뷰포트의 왼쪽 위 꼭지점으로 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;5) sticky&lt;/b&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;sticky는 사용자의 스크롤 위치를 기반으로 배치됨&lt;/li&gt;
&lt;li&gt;relative처럼 동작하다가 화면이 스크롤되어 요소가 화면 밖으로 벗어나려고 하면 fixed처럼 동작하여 뷰포트에 고정함&lt;/li&gt;
&lt;li&gt;sticky는 기준점을 넘지 않을 때는 relative처럼 동작하다가 기준점을 벗어나면 fixed처럼 동작함&lt;/li&gt;
&lt;li&gt;scroll이 계속되면 마지막 위치에서 멈춤&lt;/li&gt;
&lt;li&gt;일반적인 상황에서 sticky속성의 기준점은 부모요소가 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; 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;</description>
      <category>TIL(Today I Learned)</category>
      <category>ABSOLUTE</category>
      <category>CSS</category>
      <category>fixed</category>
      <category>position</category>
      <category>relative</category>
      <category>static</category>
      <category>Sticky</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/194</guid>
      <comments>https://innocentcodingstory.tistory.com/194#entry194comment</comments>
      <pubDate>Fri, 2 Jun 2023 14:31:35 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.02) HTTP &amp;amp; HTTP의 메세지 구조</title>
      <link>https://innocentcodingstory.tistory.com/193</link>
      <description>&lt;h3 id=&quot;http란&quot; style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1. HTTP&lt;/span&gt;&lt;/b&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;HTTP는 기본적으로 request(요청)/response(응답) 구조&lt;/li&gt;
&lt;/ul&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;span style=&quot;color: #333333;&quot;&gt;2. HTTP 메세지 구조&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 id=&quot;request-message-구조&quot; style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) Request Message 구조&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① Start Line&lt;/span&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;HTTP method :&lt;/b&gt; 요청의 의도를 담고 있는 GET, POST, PUT, DELETE등&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Request target :&lt;/b&gt; HTTP Request가 전송되는 목표 주소&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP version :&lt;/b&gt; version에 따라 Request 메세지 구조나 데이터가 다를 수 있어서 version을 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② Headers&lt;/span&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;해당 request에 대한 추가 정보를 담고 있는 부분&lt;/li&gt;
&lt;li&gt;request 메세지&lt;/li&gt;
&lt;li&gt;body의 총 길이&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ Body&lt;/span&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;request의 실제 메시지/내용&lt;/li&gt;
&lt;li&gt;전송하는 메세지가 없다면 body부분은 비어있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;response-message-구조&quot; style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) Response Message 구조&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #ececec; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① Status Line&lt;/span&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;Response의 상태를 간략하게 나타내주는 부분&lt;/li&gt;
&lt;li&gt;HTTP version&lt;/li&gt;
&lt;li&gt;Status Code&lt;/li&gt;
&lt;li&gt;Status Text&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② Headers&lt;/span&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;해당 request에 대한 추가 정보&lt;/li&gt;
&lt;li&gt;Response 메세지&lt;/li&gt;
&lt;li&gt;body의 총 길이&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ Body&lt;/span&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;request의 실제 메시지/내용- 모든 Response가 body가 있음&lt;/li&gt;
&lt;li&gt;데이터를 전송할 필요가 없을 경우 body가 비어있음&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>body</category>
      <category>Headers</category>
      <category>HTTP</category>
      <category>Message</category>
      <category>method</category>
      <category>Request</category>
      <category>response</category>
      <category>Start Line</category>
      <category>Status Line</category>
      <category>Version</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/193</guid>
      <comments>https://innocentcodingstory.tistory.com/193#entry193comment</comments>
      <pubDate>Fri, 2 Jun 2023 13:59:52 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.01) 캐시의 장단점과 활용</title>
      <link>https://innocentcodingstory.tistory.com/192</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;1. 캐시란?&lt;/span&gt;&lt;/b&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;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;span style=&quot;color: #333333; text-align: start;&quot;&gt;1) 장점&lt;/span&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;접근 시간과 계산시간을 절약하여 빠른속도로 데이터에 접근할 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;캐시에 저장된 데이터를 다시 불러오면 데이터 처리에 필요한 리소스를 절약할 수 있다.&lt;/li&gt;
&lt;/ul&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;2) 단점&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비용이 비싸다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데이터를 미리 저장하기 때문에 저장 용량이 한정되어 있다.&lt;/li&gt;
&lt;li&gt;리액트에서는 캐싱을 위해 이 데이터가 원래 저장되어진 데이터와 같은지 비교하는 연산이 추가되기 때문에,&lt;/li&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;적합한 상황에 사용하지 않는다면 오히려 손해를 보는 경우가 생길 수 있다.&lt;/ul&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;3) 프론트엔드에서 캐시의 활용&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 브라우저 캐싱에 사용&lt;/span&gt;&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;다음에 이 데이터가 필요할 때, 서버로 요청하지 않고 캐시메모리에서 바로 응답 받을 수 있어 속도를 올릴 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;우리가 한 번 접속한 사이트에 다시 접속할 때 속도가 빠른 이유가 바로 이 캐시때문이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #333333;&quot;&gt;② 리액트에서 React.memo, useCallback, useMemo를 이용해 사용&lt;/span&gt;&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;고비율의 연산을 방지해주는 기능을 수행할 수 있다.&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>React.Memo</category>
      <category>useCallback</category>
      <category>useMemo</category>
      <category>단점</category>
      <category>장점</category>
      <category>캐시</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/192</guid>
      <comments>https://innocentcodingstory.tistory.com/192#entry192comment</comments>
      <pubDate>Thu, 1 Jun 2023 11:42:44 +0900</pubDate>
    </item>
    <item>
      <title>2023.06.01) 프레임워크와 라이브러리 차이점</title>
      <link>https://innocentcodingstory.tistory.com/191</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1. 프레임워크와 라이브러리의 차이점&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;제어흐름이 어디있냐의 차이이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;프레임워크는 전체적인 흐름을 자체적으로 가지고있어 개발자가 프레임워크 안에서 필요한 코드를 작성하고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;라이브러리는 개발자가 흐름을 가져 능동적으로 필요한 곳에 호출하여 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1) 프레임워크&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;뼈대나 기반구조를 뜻한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;완성된 제품을 만들기 위해서 개발자를 도와주는, 기반 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;소프트웨어의 특정 문제를 해결하기위해 상호 협력하는 클래스와 인터페이스의 집합이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(Vue.js, Angularjs, nodejs 등)&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2) 라이브러리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;단순 활용가능한 도구들의 집합이다. 프로그래머가 어떤 기능을 수행하기위해 도움을 주고 필요한 것을 제공해주는 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;개발자가 만든 클래스에서 호출하여 사용, 클래스들의 나열로 필요한 클래스를 불러서 사용하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;( React, Redux, styled-component 등)&lt;/span&gt;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>라이브러리</category>
      <category>프레임워크</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/191</guid>
      <comments>https://innocentcodingstory.tistory.com/191#entry191comment</comments>
      <pubDate>Thu, 1 Jun 2023 11:21:30 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.31) parameter &amp;amp; argument</title>
      <link>https://innocentcodingstory.tistory.com/190</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1. parameter와 argument의 차이에 대해 설명해주세요.&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1) parameter&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;parameter(매개변수)는 함수 내부에 있는 인자로,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 특정한 값으로 정해진 것이 아니라 함수를 어디선가 호출하며 건네준 argument가 담기는 공간이다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2) &lt;span style=&quot;text-align: start;&quot;&gt;argument&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;argument(전달인자)는 함수를 호출할 때 값을 전달한다는 의미로 전달인자라고도 불리며 인수라고도 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>argument</category>
      <category>Parameter</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/190</guid>
      <comments>https://innocentcodingstory.tistory.com/190#entry190comment</comments>
      <pubDate>Wed, 31 May 2023 12:31:36 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.31) Hoisting &amp;amp; TDZ</title>
      <link>https://innocentcodingstory.tistory.com/189</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1. Hoisting 이란?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Hoisiting&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;var&lt;/li&gt;
&lt;li&gt;let&lt;/li&gt;
&lt;li&gt;const&lt;/li&gt;
&lt;li&gt;선언적함수&lt;/li&gt;
&lt;li&gt;class&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 const, let, class는 TDZ의 영향을 받는다.&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;span style=&quot;color: #333333;&quot;&gt;2. TDZ란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TDZ&lt;/b&gt;란 Temporal Dead Zone으로 const, let, class가 호이스팅 시 초기화되지않기 때문에 갖는 일시적 사각지대이다.&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;va&lt;/b&gt;r는 변수객체를 생성한 후&amp;nbsp; AllocateTo메소드를 통해 바로 메모리 공간에 공간을 할당하지만,&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;let&lt;/b&gt;과 &lt;b&gt;const&lt;/b&gt;는 set_initializer_position메소드를 통해 해당 코드의 위치를 의미하는 position값만 정해준다.&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 선언은 되어있지만 변수에 값을 담기 위한 메모리에 공간이 확보되지 않은 상태이기때문에 let과 const는 TDZ의 영향을 받는다.&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;따라서, 선언은 되어있지만 아직 초기화 되지 않아 변수에 담길 값을 위한 공간이 메모리에 할당되지 않은 상태의 구역이 TDZ이다.&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>TIL(Today I Learned)</category>
      <category>Hoisiting</category>
      <category>TDZ</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/189</guid>
      <comments>https://innocentcodingstory.tistory.com/189#entry189comment</comments>
      <pubDate>Wed, 31 May 2023 11:56:59 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.30) 랜더링 &amp;amp; Restful API</title>
      <link>https://innocentcodingstory.tistory.com/188</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 웹페이지가 브라우저에 랜더링되는 과정을 설명해주세요.&lt;/b&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;b&gt;렌더링의 기본적인 동작 과정&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;HTML 파일과 CSS 파일을 파싱해서 각각 Tree를 만든다. (Parsing)&lt;/li&gt;
&lt;li&gt;두 Tree를 결합하여 Rendering Tree를 만든다. (Style)&lt;/li&gt;
&lt;li&gt;Rendering Tree에서 각 노드의 위치와 크기를 계산한다. (Layout)&lt;/li&gt;
&lt;li&gt;계산된 값을 이용해 각 노드를 화면상의 실제 픽셀로 변환하고, 레이어를 만든다. (Paint)&lt;/li&gt;
&lt;li&gt;레이어를 합성하여 실제 화면에 나타낸다. (Composite)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Parsing&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;브라우저가 페이지를 렌더링하려면 가장 먼저 받아온 HTML 파일을 해석해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Parsing 단계는 HTML 파일을 해석하여 DOM(Document Object Model) Tree를 구성하는 단계이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;파싱 중 HTML에 CSS가 포함되어 있다면 CSSOM(CSS Object Model) Tree 구성 작업도 함께 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Style&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Parsing 단계에서 생성된 DOM Tree와 CSSOM Tree를 매칭시켜서 실제로 화면에 그려질 Tree인 ender Tree를 구성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예를 들면 Render Tree를 구성할때&amp;nbsp;visibility: hidden은 요소가 공간을 차지하고,&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;보이지만 않기 때문에 Render Tree에 포함이 되지만,&amp;nbsp;display: none&amp;nbsp;의 경우 Render Tree에서 제외된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Layout&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Render Tree를 화면에 어떻게 배치해야 할 것인지 노드의 정확한 위치와 크기를 계산한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;루트부터 노드를 순회하면서 노드의 정확한 크기와 위치를 계산하고 Render Tree에 반영한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;만약 크기 값을 %로 지정하였다면, Layout 단계에서 % 값을 계산해서 픽셀 단위로 변환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Paint&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Layout 단계에서 계산된 값을 이용해 Render Tree의 각 노드를 화면상의 실제 픽셀로 변환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이때 픽셀로 변환된 결과는 하나의 레이어가 아니라 여러 개의 레이어로 관리된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;당연한 말이지만 스타일이 복잡할수록 Paint 시간도 늘어난다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예를 들어, 단색 배경의 경우 시간과 작업이 적게 필요하지만, 그림자 효과는 시간과 작업이 더 많이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Composite&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Paint 단계에서 생성된 레이어를 합성하여 실제 화면에 나타낸다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리는 화면에서 웹 페이지를 볼 수 있다.&lt;/span&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 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2. Restful API에 대해 설명해주세요. GET,POST 외에 알고있는 메소드와 그 기준을 설명해주세요. RESTful API 가 아닌 것들은 어떤게 있나요?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;RESTful API 구분&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RESTful이란?&amp;nbsp;&lt;/b&gt;REST의 설계규칙을 올바르게 지킨 시스템을 RESTful하다 말할 수 있으며,&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;모든 CRUD 기능을 POST로 처리하는 API 혹은 URI규칙을 지키지 않은 API.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;즉, REST API의 설계 규칙을 올바르게 지키지 못한 시스템은 RESTful하다고 말할 수 없다.&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;&quot;&gt;RESTful API에는 다음과 같은 주요 구성요소를 포함하는 요청이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;고유 리소스 식별자&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;b color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버는 고유한 리소스 식별자로 각 리소스를 식별한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;b color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;REST 서비스의 경우 서버는 일반적으로 URL(Uniform Resource Locator)을 사용하여 리소스 식별을 수행한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;b color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;URL은 리소스에 대한 경로를 지정한다. URL은 웹페이지를 방문하기 위해 브라우저에 입력하는 웹 사이트 주소와 유사하다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;b color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;URL은 요청 엔드포인트라고도 하며 클라이언트가 요구하는 사항을 서버에 명확하게 지정한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;메서드&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;개발자는 종종 Hypertext Transfer Protocol(HTTP)을 사용하여 RESTful API를 구현한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;HTTP 메서드는 리소스에 수행해야 하는 작업을 서버에 알려준다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4가지의 일반적인 HTTP 메서드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) GET&lt;/span&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;클라이언트는 GET을 사용하여 서버의 지정된 URL에 있는 리소스에 액세스한다.&lt;/li&gt;
&lt;li&gt;GET 요청을 캐싱하고 RESTful API 요청에 파라미터를 넣어 전송하여 전송 전에 데이터를 필터링하도록 서버에 지시할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) POST&lt;/span&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;클라이언트는 POST를 사용하여 서버에 데이터를 전송한다.&lt;/li&gt;
&lt;li&gt;여기에는 요청과 함께 데이터 표현이 포함된다.&lt;/li&gt;
&lt;li&gt;동일한 POST 요청을 여러 번 전송하면 동일한 리소스를 여러 번 생성하는 부작용이 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;3) PUT&lt;/span&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;클라이언트는 PUT을 사용하여 서버의 기존 리소스를 업데이트한다.&lt;/li&gt;
&lt;li&gt;POST와 달리, RESTful 웹 서비스에서 동일한 PUT 요청을 여러 번 전송해도 결과는 동일하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4) DELETE&lt;/span&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;클라이언트는 DELETE 요청을 사용하여 리소스를 제거한다. &lt;br /&gt;DELETE 요청은 서버 상태를 변경할 수 있다. 하지만 사용자에게 적절한 인증이 없으면 요청은 실패한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;HTTP 헤더&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;요청 헤더는 클라이언트와 서버 간에 교환되는 메타데이터이다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예를 들어, 요청 헤더는 요청 및 응답의 형식을 나타내고 요청 상태 등에 대한 정보를 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;데이터&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;REST API 요청에는 POST, PUT 및 기타 HTTP 메서드가 성공적으로 작동하기 위한 데이터가 포함될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;파라미터&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;RESTful API 요청에는 수행해야 할 작업에 대한 자세한 정보를 서버에 제공하는 파라미터가 포함될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;파라미터 유형예시&lt;/span&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;URL 세부정보를 지정하는 경로 파라미터.&lt;/li&gt;
&lt;li&gt;리소스에 대한 추가 정보를 요청하는 쿼리 파라미터.&lt;/li&gt;
&lt;li&gt;클라이언트를 빠르게 인증하는 쿠키 파라미터.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/188</guid>
      <comments>https://innocentcodingstory.tistory.com/188#entry188comment</comments>
      <pubDate>Tue, 30 May 2023 13:59:09 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.26) 타입스크립트의 클래스 &amp;amp; 인터페이스 (1)</title>
      <link>https://innocentcodingstory.tistory.com/187</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. classes&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트와 동일하게 타입스크립트에도 class가 있다.&lt;/p&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;/li&gt;
&lt;li&gt;문법 오류나 오용 등을 거르고 컴파일 될 때 걸러지게 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1685104181145&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//JavaScript code
class Player {
	constructor(firstname, lastname, nickname) {
    	this.firstname = firstname;
        this.lastname = lastname;
        this.nickname = nickname;
    }
}
const ori = new Player(&quot;ori&quot;, &quot;park&quot;, &quot;박오리&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 자바스크립트에서는 this를 꼭 써주어야 했지만,&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;public 혹은 private 등이 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;private 써준 건 객체 밖에서 사용할 수 없다.&lt;/p&gt;
&lt;pre id=&quot;code_1685104469725&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Player {
  constructor(
    protected firstname: string,
    private lastname: string,
    public nickname:string
  ) {}
}

const olaf = new Player(&quot;olaf&quot;, &quot;park&quot;, &quot;박올라프&quot;)&lt;/code&gt;&lt;/pre&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. Astract&amp;nbsp;Class&lt;/b&gt;&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;/p&gt;
&lt;pre id=&quot;code_1685105117283&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class User {
  constructor(
    protected firstName: string,
    private lastName: string,
    public nickname: string
  ) {}
  getFullName(){
    return `${this.firstName} ${this.lastName}`
  }
}

class Player extends User {
  // 추상 메서드는 추상 클래스를 상속받는 클래스들이 반드시 구현해야하는 메서드.
  getNickname() {
    console.log(this.nickname)
  }
}

// 불가
const ori = new User(&quot;ori&quot;, &quot;park&quot;, &quot;박오리&quot;)
// 가능
const olaf = new Player(&quot;olaf&quot;, &quot;park&quot;, &quot;박올라프&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스의 메소드 getFullName이 무어을 구현해야하는지 단서를 주는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속받은 클래스는 상속을 준 클래스의 메소드도 사용 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1685105204681&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;olaf.getFullName();
olaf.getNickname();&lt;/code&gt;&lt;/pre&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;3. Method&amp;nbsp;in&amp;nbsp;Abstract&amp;nbsp;Class&lt;/b&gt;&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;pre id=&quot;code_1685105332496&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class User {
  constructor(
    protected firstName: string,
    private lastName: string,
    public nickname: string
  ) {}
  abstract getNickname():void
  getFullName() {
    return `${this.firstName} ${this.lastName}`
  }
}

class Player extends User {
  // 추상 메서드는 추상 클래스를 상속받는 클래스들이 반드시 구현해야하는 메서드.
  // 즉, getNickname을 꼭 구현해야한다.
  getNickname() {
    console.log(this.firstName)
    console.log(this.nickname)
  }
}&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;</description>
      <category>TIL(Today I Learned)</category>
      <category>Astract Class</category>
      <category>class</category>
      <category>classes</category>
      <category>Method in Abstract Class</category>
      <category>private</category>
      <category>Public</category>
      <category>This</category>
      <category>typescript</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/187</guid>
      <comments>https://innocentcodingstory.tistory.com/187#entry187comment</comments>
      <pubDate>Fri, 26 May 2023 22:08:43 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.25) 타입스크립트의 함수 (1)</title>
      <link>https://innocentcodingstory.tistory.com/186</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. call signatures&lt;/b&gt;&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;/p&gt;
&lt;pre id=&quot;code_1685003823987&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Add = (a:number, b:number) =&amp;gt; number;    // call signatures

const add:Add = (a, b) =&amp;gt; a + b&lt;/code&gt;&lt;/pre&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. overloading&lt;/b&gt;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현부 : 함수 구현, 모든 선언부를 표현할 수 있어야 함. 선언부의 마지막 부분에 작성되어야 함.&lt;/p&gt;
&lt;pre id=&quot;code_1685005149357&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Config = {
	path: string,
    state: object
}

type Push = {
	(path: string): void
    (config:Config): void
}

const push: Push = (config) =&amp;gt; {
	if (typeof config === &quot;string&quot;) { console.log (config) }
    else {
    	console.log (config.path)
    }
}&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. polymorphism&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러가지 다양한 형태들이란 뜻이다.&lt;/p&gt;
&lt;pre id=&quot;code_1685007270803&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type SuperPrint = {
	&amp;lt;T&amp;gt;(arr: T[]): T
}

const superPrint: SuperPrint = (arr) =&amp;gt; arr[0]

const a= superPrint([1,2,3,4])
const b = superPrint ([true, false])
const c = superPrint ([&quot;a&quot;,&quot;b&quot;,&quot;c&quot;])
const d = superPrint ([1,2,true,&quot;a&quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;generic을 사용하여,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수의&lt;span&gt;&amp;nbsp;&lt;/span&gt;call signatures를 입력할 때 placeholder를 사용하게 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4. generic&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;generic을 쓰는 이유는 any처럼 처리하기 편하면서도 한 함수 안에서 타입을 담아 전달할 수 있기 때문에&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;제네릭 타입의 변수 이름으로 보통 JS 변수처럼 이름을 붙여줘도 되지만 T(타입), V(밸류)를 많이 쓴다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;앞에 브라켓을 넣어서 변수 선언한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1685013643410&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface SuperPrint {
  &amp;lt;T, M&amp;gt;(arr: T[], b: M): T;
}
const superPrint: SuperPrint = (arr) =&amp;gt; {
  return arr[0];
};
const a = superPrint([1, 2, 3], &quot;x&quot;);
const b = superPrint([1, 2, 3], [1]);&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;5. generic의 확장&lt;/p&gt;
&lt;pre id=&quot;code_1685016199824&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Player&amp;lt;E&amp;gt; = {
  name: string;
  extraInfo: E;
};

type OriPlayer = Player&amp;lt;OriExtra&amp;gt;;

type OriExtra = { age: number };

const player: OriPlayer = {
  name: &quot;Ori&quot;,
  extraInfo: {
    age: 5,
  },
};

const olafPlayer: Player&amp;lt;null&amp;gt; = {
  name: &quot;Olaf&quot;,
  extraInfo: null,
};&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;&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>TIL(Today I Learned)</category>
      <category>call signatures</category>
      <category>Generic</category>
      <category>Overloading</category>
      <category>polymorphism</category>
      <category>typescript</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/186</guid>
      <comments>https://innocentcodingstory.tistory.com/186#entry186comment</comments>
      <pubDate>Thu, 25 May 2023 21:04:41 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.25) 타입스크립트의 타입 (3)</title>
      <link>https://innocentcodingstory.tistory.com/185</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. unknown&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;any 타입과 동일하게 모든 값을 허용하지만, 할당된 값이 어떤 타입인지 모르기 때문에 함부로 프로퍼티나 연산을 할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unknown 타입으로 변수를 정의하면 '변수의 타입이 unknown이라 어떤 값이든 올 수 있기에 엄격하게 검사'하도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;unknown과 any 비교&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 36px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style3&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 18px; text-align: center;&quot;&gt;&lt;b&gt;unknown&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 18px; text-align: center;&quot;&gt;&lt;b&gt;any&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 18px; text-align: center;&quot; colspan=&quot;2&quot;&gt;&lt;span&gt;모든 타입을 허용합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span&gt;프로퍼티 또는 연산을 하는 경우 컴파일러가 체크한다. &lt;br /&gt;-&amp;gt; 문제 되는 코드를 미리 예방할 수 있다.&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;span&gt;TypeScript에서 타입 검사를 느슨하게 한다.&lt;br /&gt;-&amp;gt; 개발 당시에는 문제가 없으나 &lt;br /&gt;&amp;nbsp; &amp;nbsp; 애플리케이션 또는 웹 페이지 개발 후 &lt;br /&gt;&amp;nbsp; &amp;nbsp; 예기치 못한 문제가 발생할 가능성이 매우 높다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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. void&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;void는 아무것도 return하지 않는 함수를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통은 따로 void라는 것을 지정해주지 않는다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. never&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많이 사용하지는 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;never는 함수가 절대 return 하지 않을 때 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 함수에서 exception(예외)가 발생했을 경우가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1685003171581&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// return하지 않고 에러를 발생시키는 함수
function hello():never{
	throw new Error(&quot;xxx&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>Any</category>
      <category>Never</category>
      <category>typescript</category>
      <category>Unknown</category>
      <category>void</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/185</guid>
      <comments>https://innocentcodingstory.tistory.com/185#entry185comment</comments>
      <pubDate>Thu, 25 May 2023 17:30:45 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.22) 타입스크립트의 타입 (2)</title>
      <link>https://innocentcodingstory.tistory.com/184</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. readonly 속성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;readonly 속성은 요소를 읽기 전용으로 만들어 준다.&lt;/p&gt;
&lt;pre id=&quot;code_1684405595804&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const names: readonly string[]=[&quot;1&quot;, &quot;2&quot;]
names.push()    //불가능
names.filter()    //가능
names.map()   //가능&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;readonly 속성을 적용하게 되면 값을 수정할 수 없게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, array를 변경하지 않는 즉, 불변성을 지켜주는 filter나 map은 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 정리하면, readonly는 요소이 불변성을 지켜주는 보호장치인 셈이다!&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. Tuple&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tuple은 array를 생성하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 최소한의 길이를 가져야 하고, 특정 위치에 특정 타입이 있어야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1684406241453&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const user:[string, number, boolean] = [&quot;ori&quot;, 5, true]
player[0] = 7   // 오류가 남. player[0]의 요소는 string 타입이기 때문.&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;원한다면 Tuple에 readonly도 적용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1684406329481&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const user:[string, number, boolean] = [&quot;ori&quot;, 5, true]
player[0] = &quot;olaf&quot;   // 타입은 같지만, readonly기 때문에 오류가 남.&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. any&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;any는 typescript에서 빠져나오는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 되면 javascript에 있는 것이 되고, typescript로서의 보호장치를 잃어버리게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1684767662747&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const a : any [] = [1,2,3]
const b : any = true

a + b   //오류가 나지 않는다.&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;&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>TIL(Today I Learned)</category>
      <category>Any</category>
      <category>array</category>
      <category>readOnly</category>
      <category>tuple</category>
      <category>typescript</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/184</guid>
      <comments>https://innocentcodingstory.tistory.com/184#entry184comment</comments>
      <pubDate>Tue, 23 May 2023 00:01:41 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.18) 타입스크립트의 타입 (1)</title>
      <link>https://innocentcodingstory.tistory.com/183</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 타입스크립트에서 타입을 지정해주는 방법&lt;/b&gt;&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;pre id=&quot;code_1684396515713&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[1,2,3]+flase
=&amp;gt; 123flase&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;number와 boolean을 더해주는 말도 안되는 실행을 보여준다.&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;1. 명시적으로 지정해주는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 타입스크립트가 추론하게 하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 두 가지가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1684397039920&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let a : string = &quot;2&quot;    // type: string
let b = &quot;2&quot;    // type: string
let c : number[] = [1,2,3]    // type: number[]
let d = [1,2,3]    // type: number[]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a와 c는 타입을 명시해 주었고, b와 d는 타입을 명시해주지 않았지만,&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 선택적 사용&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1684398039637&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const player : {
	name: string,
    age:number
} = {
	name: &quot;Ori&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 형태로 사용할 때 age를 선택적으로 사용하려고 하면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;player 내에 age가 없을 땐 오류가 나게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럴 땐,&lt;/p&gt;
&lt;pre id=&quot;code_1684398129075&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const player : {
	name: string,
    age?:number
} = {
	name: &quot;Ori&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;?를 사용하게 되면 age?: number | undefined 가 되어서 선택적으로 사용할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 player 객체가 여러개일 때 타입을 저렇게 명시적으로 쓰게 되면 코드가 길어지고 가독성이 좋지 않아진다.&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;3. Alias 타입&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1684398394002&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Player = {
	name: string,
    age?: number
}
const ori : Player = {
	name: &quot;ori&quot;
}
const olaf : Player = {
	name: &quot;olaf&quot;,
    age: &quot;5&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Player라는 Alias를  타입을 적용할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alias 타입은 객체에만 이용되는 것이 아니라, 다른 곳에도 이용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, Alias 안에 Alias를 이용할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 코드 재사용을 할 수 있어서 좋다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 너무 무턱대고 Alias를 마구잡이로 사용하지는 말아야 한다.&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;4. 함수에서의 타입&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1684404802232&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Player = {
	name: string,
    age?: number
}

function playerMaker(name:string):Player {
	return {
    	name
    }
}
//화살표 함수의 경우
const playerMaker = (name:string):Player =&amp;gt; ({name})

const ori = playerMaker(&quot;ori&quot;)
ori.age = 7&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;playerMaker라는 함수의 프로퍼티인 name의 타입을 지정해주고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;return의 타입도 함수의 괄호 옆에 ':타입'을 하여 지정해줄 수 있다.&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>alias</category>
      <category>boolean</category>
      <category>JavaScript</category>
      <category>Number</category>
      <category>string</category>
      <category>typescript</category>
      <category>자바스크립트</category>
      <category>타입</category>
      <category>타입스크립트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/183</guid>
      <comments>https://innocentcodingstory.tistory.com/183#entry183comment</comments>
      <pubDate>Thu, 18 May 2023 19:20:34 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.14) 항해 14주차 회고</title>
      <link>https://innocentcodingstory.tistory.com/182</link>
      <description>&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;/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;&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;끝없는 디벨롭과 공부...&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;이와중에 날씨는 좋고!!!!!!!!&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;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/182</guid>
      <comments>https://innocentcodingstory.tistory.com/182#entry182comment</comments>
      <pubDate>Mon, 15 May 2023 00:03:08 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.14) styled-components와 emotion</title>
      <link>https://innocentcodingstory.tistory.com/181</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;원래는&lt;span&gt;&amp;nbsp;&lt;/span&gt;styled-components 를 사용해서 프로젝트를 해왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이번에 emotion을 알게 되었고, 이 둘을 비교하여 공부를 해봤다.&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;그래서 뭘 써도 상관이 없을 듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 타입스크립트 사용시&lt;span&gt;&amp;nbsp;&lt;/span&gt;styled-components는&lt;/p&gt;
&lt;pre id=&quot;code_1684075383144&quot; class=&quot;css&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@types/styled-components&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;굳이 이 둘을 따로 공부할 필요는 없는 것 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1684075383144&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//스타일드 컴포넌트
@styled-components
@types/styled-components&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1684075383144&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//이모션
@emotion/react
@emotion/styled&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/181</guid>
      <comments>https://innocentcodingstory.tistory.com/181#entry181comment</comments>
      <pubDate>Sun, 14 May 2023 23:43:23 +0900</pubDate>
    </item>
    <item>
      <title>2023.05.13) 타입스크립트 시작하기</title>
      <link>https://innocentcodingstory.tistory.com/180</link>
      <description>&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;/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;pre id=&quot;code_1683986911561&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ yarn create react-app . --template typescript
  // or 
$ npx create-react-app . --template typescript&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;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mysql 설치부터 시작했다.&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;정책에 맞추어 비밀번호를 생성하니 문제없이 패스!!&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;pre id=&quot;code_1683988669835&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx sequelize db:create(스키마 생성)
npm run dev했다가 ctrl + c로 끄기(테이블 생성)
npx sequelize db:seed:all(기초 데이터 넣기)
npm run dev(앞으로 매번 이걸로 백엔드 서버 켜야 함)

localhost:3095에서 서버 돌아가는 중&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조 상 한 파일 내에 front 폴더와 back 폴더가 있기에&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;</description>
      <category>TIL(Today I Learned)</category>
      <category>MySQL</category>
      <category>typescript</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/180</guid>
      <comments>https://innocentcodingstory.tistory.com/180#entry180comment</comments>
      <pubDate>Sun, 14 May 2023 02:24:34 +0900</pubDate>
    </item>
    <item>
      <title>2023.04.25) 항해 79일차 (실시간 시간에 따른 예약 유무 확인)</title>
      <link>https://innocentcodingstory.tistory.com/179</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회의실 예약을 하게 되면 예약한 날짜와 회의 시작, 끝 시간이 들어오게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 시각에 따른 예약 유무를 확인해야해서 고민을 해봤다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;들어오는 데이터를 어떻게 가공을 하고 회의 중인 저 시간에 어떻게 예약 유무를 보여 줄 것인지 고민을 했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;정리를 해서 해야한 고민을 적자면,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;'2023-04-25T13:00'&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;'2023-04-25T13:59'&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;} 이렇게 들어오는 데이터에서&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;날짜와 시간을 따로 꺼내서 어떻게 가공해 쓸 것 인지.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;start와&lt;span&gt;&amp;nbsp;&lt;/span&gt;end의 시간 사이에 현재 시각이 위치 한다면 어떻게 구분해야할지.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;3. 현재 시간은 어떻게 받아와야 할지.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;4. 어떻게 예약 유무를 회의실 요소에 표현할 것인지.&lt;/span&gt;&lt;/span&gt;&lt;/p&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/CXi90/btscGykuQNG/LvF3CuEv3K1JflrVmjPMFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CXi90/btscGykuQNG/LvF3CuEv3K1JflrVmjPMFK/img.png&quot; style=&quot;width:55.46816367906568%&quot; data-origin-width=&quot;420&quot; data-origin-height=&quot;117&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;56.12&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CXi90/btscGykuQNG/LvF3CuEv3K1JflrVmjPMFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCXi90%2FbtscGykuQNG%2FLvF3CuEv3K1JflrVmjPMFK%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;420&quot; height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6wYlh/btscyG4Dsgj/YVKbJNn5ER3Ns4MbnL1QhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6wYlh/btscyG4Dsgj/YVKbJNn5ER3Ns4MbnL1QhK/img.png&quot; style=&quot;width:43.369045623259886%&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;119&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;43.88&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6wYlh/btscyG4Dsgj/YVKbJNn5ER3Ns4MbnL1QhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6wYlh%2FbtscyG4Dsgj%2FYVKbJNn5ER3Ns4MbnL1QhK%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;334&quot; height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;들어오는 데이터와 표시하는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 고민을 해결하기 위해서&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. 데이터를 T로 잘라서 앞은 날짜로 저장하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;뒤는 :로 다시 나눠서 시간 부분만 저장했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. 분까지 계산할 필요는 없고, 시간만 생각하면 될 것 같다고 판단하여 분은 사용하지 않기로했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3. 현재 시간은 getData로 현재 연도, 월, 일, 시간, 분을 반아와서 날짜와 시간에 각각 저장하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;형식은 회의실 예약 데이터에 넘어오는 데이터와 형식을 맞추었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4. 현재 날짜,시간과 예약된&amp;nbsp;날짜, 시간을 검사하여 회의실 예약 유무를 임시로 보여주었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예약이 있다면, 현재 날짜와 같은지 검사하고 같다면 같은 시간이 있는지 검사하여 있다면 배경색을 변경하도록 표시하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아직은 완벽하지 않기 때문에 내일 다시 점검해보고 제대로 연결해보려고 한다.&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>getdata</category>
      <category>데이터</category>
      <category>예약</category>
      <category>유무</category>
      <category>현재시간</category>
      <category>회의실</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/179</guid>
      <comments>https://innocentcodingstory.tistory.com/179#entry179comment</comments>
      <pubDate>Wed, 26 Apr 2023 15:14:26 +0900</pubDate>
    </item>
    <item>
      <title>2023.04.23) 항해 11주차 회고 (협업, 실전프로젝트, 중간발표)</title>
      <link>https://innocentcodingstory.tistory.com/178</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;실전 프로젝트 기간 중 반인 3주가 지났다.&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;구조물 드래그 앤 드롭, 계층형 리스트 드래그 앤 드롭 이라는 큰 과제부터&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;코드는 아예 달랐기에 다시 공부를 하게 되었던 것 같다.&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;하고싶었던 공부인 타입스트립트와 next js를 해보아도 될지 고민을 했다.&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;꾸준한 리펙토링과 함께 공부도 시작해보려 한다.&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;왜냐? 일단 최종 발표는 리더인 내가 할 것 같으니까......&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 헤매면 모두 망하는거야...또륵...........&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <category>드래그 앤 드롭</category>
      <category>리펙토링</category>
      <category>협업</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/178</guid>
      <comments>https://innocentcodingstory.tistory.com/178#entry178comment</comments>
      <pubDate>Mon, 24 Apr 2023 10:41:00 +0900</pubDate>
    </item>
    <item>
      <title>2023.04.09) 항해 9주차 회고 (협업, 실전 프로젝트)</title>
      <link>https://innocentcodingstory.tistory.com/177</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;7주차의 미니프로젝트 주차와&lt;span&gt;&amp;nbsp;&lt;/span&gt;8주차의 클론코딩 프로젝트 주차를 지나서&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;7,8주차에는 일주일동안 만들어내야 해서 뭔가 바쁘게 지나갔던 것 같다.&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;오히려 해야할 것들을 하나하나 해결해 나가며 얻는 뿌듯함이 더 크달까??&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;7주차에는 협업이라는 것에 들떠서 했던 것 같고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8주차에는 클론 답게 똑같이 만드는 과정에 허덕였던 것 같고,&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;이번 실전 프로젝트에서는 드래그 앤 드롭으로 space를 구성하고 space의 요소를 원하는 위치로 옮기며 space를 수정하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;space를 계층형으로 관리하는 작업을 맡았다. 물론 추가될 것 같지만..!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주차 시작하고 이틀은 꼬박 아이디어회의를 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어를 픽스하고 와이어 프레임 구상에 api 명세서까지 했더니 이틀이 뚝딱 사라졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 본격적으로 짜기 시작한 것은 월요일부터였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 보니 6일동안 굉장한 발전을 한 것 같다.&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;select 영역에 있는 요소를 드래서해서 드롭할 때 복제되어 드롭되게 만들어야 했다.&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;라이브러리도 있고 다양한 방법이 있었지만, 내장 api인 드래그 앤 드롭 기능을 사용하여 시도하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 번째 문제&lt;/b&gt;는&amp;nbsp; 기존 요소를 드래그 앤 드롭하는 기능은 잘 되었지만 복제한 요소를 드래그 앤 드롭 기능을 구현 시,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드래그 후 드롭 시 드롭하려는 곳보다&lt;span&gt;&amp;nbsp;&lt;/span&gt;아래쪽에 드롭이 되는 문제점을 발견하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 시도를 해본 결과 요소를&lt;span&gt;&amp;nbsp;&lt;/span&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;복제한 요소를 드롭할 때에는 잘 동작하였지만, 복제된 요소를 다시 드래그하여 드롭할 때에는 영역 구분없이 드롭이 되었다.&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;아니면 드래그 조차 안되게 할 건지의 방법 중에서 후자를 선택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;space를 구성할 때 이렇게 하는 것이 사용자가 이용 시 편하게 사용할 수 있을 것이란 생각이 들었기 때문이다.&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;이 부분에서 반응형으로 제한이 걸려 있던 게 아니어서 반응형으로 동작하도록 변경해주었다.&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;/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;&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;아직은 space CRUD는 다 되었지만, 요소들은&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;</description>
      <category>WIL (Weekly I Learned)</category>
      <category>드래그</category>
      <category>드롭</category>
      <category>복제</category>
      <category>실전</category>
      <category>프로젝트</category>
      <category>항해</category>
      <category>협업</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/177</guid>
      <comments>https://innocentcodingstory.tistory.com/177#entry177comment</comments>
      <pubDate>Sun, 9 Apr 2023 20:07:51 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.14~16) 항해 37~39일차</title>
      <link>https://innocentcodingstory.tistory.com/175</link>
      <description>&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;p data-ke-size=&quot;size16&quot;&gt;일단 느낀 건 thunk는 어렵다...... 리액트 쿼리랑 너무 비교될 정도로 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그치만 thunk로도, 리액트 쿼리로도 과제 구현에 성공했다!!!!&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;먼저 데이터를 받아와서 get을 해주고 상세페이지를 연결해야 하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 컴포넌트에서 get을 한 것이 아니기에 오류가 났다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 아예 Router.js에서 get을 해주고 데이터를 내려주었다.&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;yarn build로 확인해보니!&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;패키지 설치하니 잘 된다!!!!&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>TIL(Today I Learned)</category>
      <category>get</category>
      <category>thunk</category>
      <category>yarn build</category>
      <category>리액트 아이콘</category>
      <category>리액트 쿼리</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/175</guid>
      <comments>https://innocentcodingstory.tistory.com/175#entry175comment</comments>
      <pubDate>Sat, 18 Mar 2023 09:07:30 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.13) 항해 36일차 (4-인증/인가_쿠키,세션,토큰,JWT)</title>
      <link>https://innocentcodingstory.tistory.com/174</link>
      <description>&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;/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;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) 인증&amp;amp;인가&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 인증(Authentication) vs. 인가(Authorization)&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;color: #333333;&quot;&gt;❶인증(Authentication)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;span style=&quot;color: #333333;&quot;&gt;❷인가(Authorization)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② http 프로토콜 통신의 특징&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;color: #333333;&quot;&gt;❶ 무상태 (Stateless)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버는 클라이언트의 상태를 기억하지 않는다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;각 요청마다 서버에서 요구하는 모든 상태 정보를 담아서 요청해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RA28K/btr3kyflj4R/TwBaQvpAGayKQYw9kbl8vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RA28K/btr3kyflj4R/TwBaQvpAGayKQYw9kbl8vK/img.png&quot; data-alt=&quot;서버는 클라이언트를 기억하지 않는다!!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RA28K/btr3kyflj4R/TwBaQvpAGayKQYw9kbl8vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRA28K%2Fbtr3kyflj4R%2FTwBaQvpAGayKQYw9kbl8vK%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;400&quot; height=&quot;490&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;490&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;&lt;span style=&quot;color: #333333;&quot;&gt;상태값은 매 요청마다 클라이언트가 가지고 오기 때문에, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버는 클라이언트의 상태를 별도로 기억할 필요없이 주문받은 대로 응답해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;무상태라는 특성 덕분에 동일한 서버를 여러개로 확장시킬 수 있다. (Scale-Out)&lt;/span&gt;&lt;span style=&quot;color: #333333;&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;span style=&quot;color: #333333;&quot;&gt;❷비연결성 (Connectionless)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버와 클라이언트는 연결되어 있지 않다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버 입장에서는 매번 새로운 요청이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pCBRG/btr3gLzgiPe/Q8QBb60k92qQHKwbiODLtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pCBRG/btr3gLzgiPe/Q8QBb60k92qQHKwbiODLtk/img.png&quot; data-alt=&quot;왼쪽 이미지를 봐야함.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pCBRG/btr3gLzgiPe/Q8QBb60k92qQHKwbiODLtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpCBRG%2Fbtr3gLzgiPe%2FQ8QBb60k92qQHKwbiODLtk%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;400&quot; height=&quot;1024&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1024&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;&lt;span style=&quot;color: #333333;&quot;&gt;비연결성으로 인해 최소한의 서버 자원으로 서버를 유지할 수 있게 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) 쿠키, 세션, 토큰&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 쿠키 (cookie)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;무상태와 비연결성이라는 http 통신의 특징에도 불구하고 ,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;u&gt;마치 서버가 클라이언트의 인증 상태를 기억하는 것처럼 구현할 수 있는 수단&lt;/u&gt;으로 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;쿠키란 브라우저에 저장되는 텍스트 파일이며, key-value 형태로 저장된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;쿠키는 별도로 삭제처리하거나 유효기간이 만료되지 않는 이상 서버와 통신할 때 &lt;u&gt;자동으로 주고 받게 된다.&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버에 특정 API 요청을 했을 때 서버가 응답 시 header 안에 set-cookie 속성으로 쿠키 정보를 담아주면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 응답을 받은 브라우저는 쿠키를 브라우저에 자동으로 저장한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(저장된 쿠키정보는 개발자도구 &amp;rarr; 애플리케이션 &amp;rarr; 저장용량 &amp;rarr; 쿠키 에서 확인 가능해보자!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버에 http 요청 할 때 마다 브라우저에 저장되어 있는 쿠키는 자동으로 서버에 보내진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; (단, 동일한 Origin 또는 CORS를 허용하는 Origin에만 쿠키를 보낸다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(ex- 유튜브 서버에서 받은 쿠키는 유튜브 이용 시에만 주고 받을 수 있다.)&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;span style=&quot;color: #333333;&quot;&gt;❶ Origin&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;출처(origin) 이란 protocol + host + port 를 의미한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XI4kx/btr3ez0niuU/B1YvHAafHf9QzVjrIka7y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XI4kx/btr3ez0niuU/B1YvHAafHf9QzVjrIka7y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XI4kx/btr3ez0niuU/B1YvHAafHf9QzVjrIka7y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXI4kx%2Fbtr3ez0niuU%2FB1YvHAafHf9QzVjrIka7y0%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;400&quot; height=&quot;569&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;569&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❷ CORS&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Cross Origin Resource Sharing(CORS)는 다른 출처에 리소스 요청하는 것을 허용하는 정책이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;브라우저는 보안상의 이유로 기본적으로 Same Origin Policy(SOP)를 원칙으로 하고 있지만, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버와 클라이언트 각각 CORS 설정을 통해 상호합의된 웹사이트는&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 예외적으로 서로 다른 출처(Cross-Origin)임에도 API 요청이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② 세션 (session)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;세션이란 사용자와 서버 간의 연결이 활성화된 상태를 의미하는 개념이다. (또는 인증이 유지되고 있는 상태)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;로그인 성공 &amp;rarr; 서버에서 세션 생성 및 저장(key-value 형식) &amp;rarr; key(sessionId)를 브라우저에 응답(by 쿠키)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❶ 쿠키-세션 인증 방식&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;sup1; 로그인/회원가입 시 세션 인증&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xR8Lv/btr3fuqZfEZ/zmOviFHUMCeK4Y9xEzxUvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xR8Lv/btr3fuqZfEZ/zmOviFHUMCeK4Y9xEzxUvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xR8Lv/btr3fuqZfEZ/zmOviFHUMCeK4Y9xEzxUvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxR8Lv%2Fbtr3fuqZfEZ%2FzmOviFHUMCeK4Y9xEzxUvK%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;500&quot; height=&quot;485&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;485&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;span style=&quot;color: #333333;&quot;&gt;&amp;sup2;로그인/회원가입 성공 시 서버에서 쿠키에 sessionId를 담아서 보내준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;세션 유지 상태 : 서버에서 관리하는 세션 저장소에 회원 데이터가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;span style=&quot;color: #333333;&quot;&gt;&amp;sup3; 인가(Authorization) 필요한 API 요청/응답&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5b7F0/btr3iHDBVyk/VrkNIr7mT4AMO5BQ3UJ0V1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5b7F0/btr3iHDBVyk/VrkNIr7mT4AMO5BQ3UJ0V1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5b7F0/btr3iHDBVyk/VrkNIr7mT4AMO5BQ3UJ0V1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5b7F0%2Fbtr3iHDBVyk%2FVrkNIr7mT4AMO5BQ3UJ0V1%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;500&quot; height=&quot;528&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;528&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;span style=&quot;color: #333333;&quot;&gt;⁴ 서버는 인가가 필요한 API 요청을 받으면 클라이언트 쿠키에 들어 있는 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;sessionId를 세션 저장소에 조회하여 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;있으면 DB에 데이터를 조회하여 응답한다.&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ 토큰 (token)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;클라이언트에서 보관하는 암호화된 인증 정보를 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;세션처럼 서버에서 사용자의 인증 정보를 보관할 필요가 없기 때문에, 서버 부담을 줄여주는 인증 수단이라 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;웹에서 인증 수단으로 사용되는 토큰은 주로 JWT (Json Web Token) 을 이용한다.&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;span style=&quot;color: #333333;&quot;&gt;❶ JWT의 특징&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;header.payload.signature 형식으로 3가지 데이터로 구성되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;국제 인터넷 표준 인증 규격 중 하나이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;암호화된 토큰을 누구나 복호화하여 payload를 볼 수 있다. &amp;rarr; 토큰의 용도는 인증정보(payload)에 대한 보호가 아니라 위조 방지다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;정보(payload)를 토큰화할 때 signature에 secret key가 필요하고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;secret key는 복호화가 아니라 토큰이 유효한 지를 검증하는 데 사용된다.&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;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;❷ JWT 토큰 인증 방식&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;sup1; 로그인/회원가입 시 토큰 인증&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brfHnB/btr3gNYaB9a/eqnFbbTzkRgGxybOtgFRSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brfHnB/btr3gNYaB9a/eqnFbbTzkRgGxybOtgFRSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brfHnB/btr3gNYaB9a/eqnFbbTzkRgGxybOtgFRSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrfHnB%2Fbtr3gNYaB9a%2FeqnFbbTzkRgGxybOtgFRSk%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;500&quot; height=&quot;545&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;sup2;인가(Authorization) 필요한 API 요청/응답&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXBbY6/btr3lEzQC0c/VIdMMuNCgP9PfNmEQGVka0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXBbY6/btr3lEzQC0c/VIdMMuNCgP9PfNmEQGVka0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXBbY6/btr3lEzQC0c/VIdMMuNCgP9PfNmEQGVka0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXBbY6%2Fbtr3lEzQC0c%2FVIdMMuNCgP9PfNmEQGVka0%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;500&quot; height=&quot;485&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;485&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;span style=&quot;color: #333333;&quot;&gt;&amp;sup3; Refresh Token 으로 보안 강화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 접근 인가를 받기 위해 사용되는 토큰을 Access Token 이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Access Token의 만료기간을 길게 잡고 인증상태를 오래 가져갈 경우 서버 부담은 줄어드나 보안성(탈취 당할 경우)에 허점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증 보안이 중요한 서비스의 경우 인증 시 2개의 토큰 (Access Token, Refresh Token)을 발급하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Access Token의 기간은 30분 정도로 짧게 가져 가고, Refresh Token은 1~2주 정도로 길게 잡는 경우가 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 경우 서버에서는 Access Token이 만료되었을 때 Refresh Token 이 유효한 상태면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 새로운 Access Token을 클라이언트에 발급해주고 인증상태를 유지할 수 있도록 하고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Refresh Token 만료 시 다시 로그인하라는 메시지를 응답한다.&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;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❸ 세션 인증 vs. 토큰 인증&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 53.7209%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;세션 인증&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;토큰 인증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인증정보 저장위치&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;클라이언트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;확장성 (Scale-out)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Bad&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Good&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;보안성 (상대적)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Good&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Bad&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;비용 (상대적)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Expensive&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Cheap&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; 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>TIL(Today I Learned)</category>
      <category>jwt</category>
      <category>세션</category>
      <category>인가</category>
      <category>인증</category>
      <category>쿠키</category>
      <category>토큰</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/174</guid>
      <comments>https://innocentcodingstory.tistory.com/174#entry174comment</comments>
      <pubDate>Mon, 13 Mar 2023 20:55:03 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.13) 항해 36일차 (3-Throttling &amp;amp; Debouncing)</title>
      <link>https://innocentcodingstory.tistory.com/173</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 내용은 뭔가 재미있는 부분이었다!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;테스트 하기 위해 버튼을 여러번 타다다다다닥 누르며&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;스트레스를 풀었달까 ㅎㅎㅎㅎㅎ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;많이 어렵지도 않고 재미있어서 좋았다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;하지만 이 부분이 나중에 내게 어떤 어려움으로 다가올지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아주 두근하다.....!!&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) Throttling &amp;amp; Debouncing&lt;/span&gt;&lt;/b&gt;&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;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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Timer Web API 중 setTimeout 메소드를 사용하여&lt;/span&gt;&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;① &lt;/b&gt;&lt;b&gt;Throttling&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&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/zEsLK/btr3cI4Km8F/EV88oUt5ej4FshCKm9DVk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zEsLK/btr3cI4Km8F/EV88oUt5ej4FshCKm9DVk0/img.png&quot; width=&quot;400&quot; height=&quot;195&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;517&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.4&quot; data-filename=&quot;blob&quot; style=&quot;width: 32.6209%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zEsLK/btr3cI4Km8F/EV88oUt5ej4FshCKm9DVk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzEsLK%2Fbtr3cI4Km8F%2FEV88oUt5ej4FshCKm9DVk0%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;1060&quot; height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UOUSE/btr3eA5YHBT/g880PodUYVkVWdvQYZ8L21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UOUSE/btr3eA5YHBT/g880PodUYVkVWdvQYZ8L21/img.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;517&quot; data-is-animation=&quot;false&quot; width=&quot;400&quot; data-widthpercent=&quot;33.4&quot; data-filename=&quot;blob&quot; style=&quot;width: 32.6209%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UOUSE/btr3eA5YHBT/g880PodUYVkVWdvQYZ8L21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUOUSE%2Fbtr3eA5YHBT%2Fg880PodUYVkVWdvQYZ8L21%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;1060&quot; height=&quot;517&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ck7WCZ/btr3uD749uX/AhqbVYdUNM3ieQo9kioqU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ck7WCZ/btr3uD749uX/AhqbVYdUNM3ieQo9kioqU1/img.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;520&quot; data-is-animation=&quot;false&quot; width=&quot;400&quot; data-widthpercent=&quot;33.2&quot; data-filename=&quot;blob&quot; style=&quot;width: 32.4327%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ck7WCZ/btr3uD749uX/AhqbVYdUNM3ieQo9kioqU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fck7WCZ%2Fbtr3uD749uX%2FAhqbVYdUNM3ieQo9kioqU1%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;1060&quot; height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;짧은 시간 간격으로 연속해서 발생한 이벤트들을 일정시간 단위(delay)로 그룹화하여&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 처음 또는 마지막 이벤트 핸들러만 호출되도록 하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;주로 사용되는 예: 무한스크롤&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678634098041&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  // Throttling 예제코드
  const throttle = (delay) =&amp;gt; {
    if (timerId) {
      // timerId가 있으면 바로 함수 종료
      return;
    }
    timerId = setTimeout(() =&amp;gt; {
      console.log(`${delay}ms 지남 추가요청 받음`);
      // alert(&quot;Home / 쓰로틀링 쪽 API호출!&quot;);
      timerId = null;
    }, delay);
  };&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② Debouncing&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwHF67/btr3Bw8Ctyb/Pq0fzvKFYHyw3plX8cuKbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwHF67/btr3Bw8Ctyb/Pq0fzvKFYHyw3plX8cuKbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwHF67/btr3Bw8Ctyb/Pq0fzvKFYHyw3plX8cuKbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwHF67%2Fbtr3Bw8Ctyb%2FPq0fzvKFYHyw3plX8cuKbk%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;400&quot; height=&quot;454&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;454&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;짧은 시간 간격으로 연속해서 이벤트가 발생하면 이벤트 핸들러를 호출하지 않다가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 마지막 이벤트로부터 일정 시간(delay)이 경과한 후에 한 번만 호출하도록 하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;주로 사용되는 예: 입력값 실시간 검색, 화면 resize 이벤트&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678633965141&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Debouncing 예제코드
  const debounce = (delay) =&amp;gt; {
    if (timerId) {
      // 할당되어 있는 timerId에 해당하는 타이머 제거
      clearTimeout(timerId);
    }
    timerId = setTimeout(() =&amp;gt; {
      // timerId에 새로운 타이머 할당
      console.log(`마지막 요청으로부터 ${delay}ms지났으므로 API요청 실행!`);
      timerId = null;
    }, delay);
  };&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ 메모리 누수(Memory Leak)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;필요하지 않은 메모리를 계속 점유하고 있는 현상이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;페이지 이동 전에 setTimeout 으로 인해 타이머가 동작중인 상태에서 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;clearTimeout을 안해주고 페이지 이동 시,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 컴포넌트는 언마운트 되었음에도 불구하고 타이머는 여전히 메모리를 차지하고 동작하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이 경우 메모리 누수(Memory Leak)에 해당한다고 말할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이러한 경우에는&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678633734833&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(()=&amp;gt;{
	return () =&amp;gt; {
    //언마운트 시
    	if(timerId) {
    		clearTimeout(timerId);
    	}
    };
}, []};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위의 코드를 사용하여 이 컴포넌트가 사라질 때 타이머 아이디가 존재하면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기존의 존재하고 있는 이 타이머를 없애달라고 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>clearTimeout</category>
      <category>debouncing</category>
      <category>Memory Leak</category>
      <category>settimeout</category>
      <category>Throttling</category>
      <category>메모리 누수</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/173</guid>
      <comments>https://innocentcodingstory.tistory.com/173#entry173comment</comments>
      <pubDate>Mon, 13 Mar 2023 20:53:51 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.13) 항해 36일차 (2-React Query)</title>
      <link>https://innocentcodingstory.tistory.com/172</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트 쿼리......&amp;nbsp; 생각보다 이 친구가 날 괴롭혔다...&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;썽크를 해서 가볍게 할 줄 알았던 나 반성해....&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결국 이 내용을 이해하기 위해 내가 전에 만들었던 투두리스트 파일을&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;뜯어가며 새로 고쳐보며 이해하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결국 강의에 나오지 않은 부분도 완성하기 성공했다ㅡㅜㅜㅜ&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;너무 감격스러운 것 ㅠㅠㅠㅠㅠ&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;요 몇 주 심각히 힘들었는데 보상받은 기분이라 너무 좋았다!&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) React Query&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 리액트 쿼리란&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❶ 기존 미들웨어의 한계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;우리는 다른 서버와의 API 통신과 비동기 데이터 관리를 위해&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Redux-thunk, Redux-Saga 등 미들웨어를 채택해서 사용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 다음과 같은 문제가 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;보일러 플레이트 : 코드량이 너무 많다.&lt;/li&gt;
&lt;li&gt;규격화 문제 : Redux가 비동기 데이터 관리를 위한 전문 라이브러리가 아님(규격화 문제)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❷ 리액트 쿼리의 강점 &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;너무 쉽고, 책임에서 자유롭다.&lt;/li&gt;
&lt;li&gt;보일러 플레이트 만들다가 오류날 일이 없다!&lt;/li&gt;
&lt;li&gt;내가 만든 부분 아니기 때문에 잘못이 일어난들 내 잘못이 아니다!!&lt;/li&gt;
&lt;li&gt;사용방법이 기존 thunk 대비 너무 쉽구요, 직관적이자.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;②주요 키워드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❶ Query&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 데이터에 대한 요청을 의미한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;axios의 경우 get 요청과 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;ex) const response = await axios.get(&amp;rsquo;&lt;a style=&quot;color: #666666;&quot; href=&quot;http://localhost:3000/todos%E2%80%99&quot;&gt;http://localhost:3000/todos&amp;rsquo;&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❷ Mutation&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 데이터를 변경하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 데이터라 함은, 데이터 그룹 그 자체를 의미한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;바꾼다는 것은 추가, 수정, 삭제를 의미해요. CRUD 중, CUD에 해당한다. (Create, Update, Delete)&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;axios의 경우 post, put, patch, delete 요청과 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;ex) axios.post(&amp;rsquo;&lt;a style=&quot;color: #666666;&quot; href=&quot;http://localhost:3000/todos%E2%80%99.,&quot;&gt;http://localhost:3000/todos&amp;rsquo;.,&lt;/a&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&amp;nbsp;newTodo);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;ex) axios.patch(http://localhost:3000/todos/${id}, {isDone: true});&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❸ Query Invalidation&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;Query를 invalidation. 즉, 무효화 시킨다는 의미이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기존에 가져온 Query는 서버 데이터이기 때문에, 언제든지 변경이 있을 수 있기&lt;/span&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 style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그런 경우, 기존의 쿼리를 무효화 시킨 후 최신화 시켜야 하는데 이런 과정을 React Query에서는 알아서 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;그 유용한 기능이 바로 Query Invalidation이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1009&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSCqTf/btr3Lre2dDd/auHxRetqGxzXB2QRwK1XC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSCqTf/btr3Lre2dDd/auHxRetqGxzXB2QRwK1XC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSCqTf/btr3Lre2dDd/auHxRetqGxzXB2QRwK1XC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSCqTf%2Fbtr3Lre2dDd%2FauHxRetqGxzXB2QRwK1XC1%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;600&quot; height=&quot;432&quot; data-origin-width=&quot;1009&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;뿌듯!!!!&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>mutation</category>
      <category>query</category>
      <category>Query Invalidation</category>
      <category>React Query</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/172</guid>
      <comments>https://innocentcodingstory.tistory.com/172#entry172comment</comments>
      <pubDate>Mon, 13 Mar 2023 20:53:40 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.13) 항해 36일차 (1-미들웨어, thunk)</title>
      <link>https://innocentcodingstory.tistory.com/171</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이 내용들은 &quot;아 이렇게 쓰는거구나.&quot;, &quot;이런식으로 사용하면 되겠네&quot;라는 이해는 되지만&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;그래서 더 분발하고 있지만 내용이 어려운 만큼 시간이 부족한 것 또한 사실이다..&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;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) Redux 미들웨어&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 미들웨어란?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0wKbv/btr3ez6X06p/kFCSfthfLdVaIUVpKfxWz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0wKbv/btr3ez6X06p/kFCSfthfLdVaIUVpKfxWz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0wKbv/btr3ez6X06p/kFCSfthfLdVaIUVpKfxWz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0wKbv%2Fbtr3ez6X06p%2FkFCSfthfLdVaIUVpKfxWz0%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;600&quot; height=&quot;239&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리덕스에서 dispatch를 하면 action 이 리듀서로 전달이 되고, 리듀서는 새로운 state를 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;span style=&quot;color: #333333;&quot;&gt;만약 counter 프로그램에서 더하기 버튼을 클릭했을 때 바로 +1를 더하지 않고 3초를 기다렸다가,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; +1이 되도록 구현하려면 미들웨어를 사용하지 않고서는 구현할 수 없다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 왜냐하면 dispatch가 되자마자 바로 action이 리듀서로 달려가서 새로운 state를 반환해버리기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 즉, 여기서 &amp;ldquo;3초를 기다리는 작업&quot; 이 작업을 미들웨어가 해주는 것이다.&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;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) thunk&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① thunk란&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리덕스에서 많이 사용하고 있는 미들웨어중에 하나이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; thunk를 사용하면 우리가 dispatch를 할때 객체가 아닌 함수를 dispatch 할 수 있게 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 즉 dispatch(객체) 가 아니라 dispatch(함수)를 할 수 있게 되는 것이다! 와우!!&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;span style=&quot;color: #333333;&quot;&gt;그래서 중간에 우리가 하고자 하는 작업을 함수를 통해 넣을 수 있고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;그것이 중간에 실행이 되는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 아래 흐름과 같이 실행이 되는 것이고 , 이 함수를 thunk 함수라고 부른다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;dispatch(함수) &amp;rarr; 함수실행 &amp;rarr; 함수안에서 dispatch(객체)&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② thunk 사용하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;툴킷에서는 createAsyncThunk 라는 API를 사용해서 thunk 함수를 생성할 수 있다.&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이 API는 함수인데, 첫번째 인자에는 Action Value, 두번째 인자에는 함수가 들어간다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수에 우리가 하고 싶은 작업들을 구현하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;두번째로 들어가는 함수에서 2개의 인자를 꺼내 사용할 수 있는데,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;첫번째 인자는 컴포넌트에서 보내준 payload이고, 두번째 인자는 thunk에서 제공하는 여러가지 기능이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;fulfillWithValue&lt;/b&gt; 는 툴킷에서 제공하는 API 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise에서 resolve된 경우, 다시 말해 네트워크 요청이 성공한 경우에 dispatch 해주는 기능을 가진 API&amp;nbsp;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 인자로는 payload를 넣어줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;rejectWithValue&lt;/b&gt; 도 툴킷에서 제공하는 API 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise가 reject 된 경우, 네트워크 요청이 실패한 경우 dispatch 해주는 기능을 가진 API&amp;nbsp;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 인자로 어떤 값을 넣을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1678621701111&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// thunk 함수는 createAsyncThunk 라는 툴킷 API를 사용해서 생성한다.

// __가 함수 이름에 붙는 이유는 이 함수가 thunk 함수라는 것을 표시하기 위한 개인의 convention이다.

export const __addNumber = createAsyncThunk(
	&quot;ADD_NUMBER_WAIT&quot;,
	(arg, thunkAPI)=&amp;gt;{},
);&lt;/code&gt;&lt;/pre&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;span style=&quot;color: #333333;&quot;&gt;③ 코드로 알아보기 1&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;thunk 함수를 만들어보자!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;thunk 함수의 역할은 &amp;ldquo;3초를 기다리는 것&amp;rdquo; 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 그리고 3초가 지나면 원래 하려고 했던 ADD_NUMBER를 해주는 것 까지가 thunk함수가 해야 할 일 이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678621761973&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/counterSlice.js

import { createSlice, createAsyncThunk } from &quot;@reduxjs/toolkit&quot;;

export const __addNumber = createAsyncThunk(
	// 첫번째 인자 : action value
  &quot;addNumber&quot;, 
	// 두번째 인자 : 콜백함수 
  (payload, thunkAPI) =&amp;gt; {
    setTimeout(() =&amp;gt; {
      thunkAPI.dispatch(addNumber(payload));
    }, 3000);
  }
);

const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: &quot;counter&quot;,
  initialState,
  reducers: {
    addNumber: (state, action) =&amp;gt; {
      state.number = state.number + action.payload;
    }
  },
});

export const { addNumber } = counterSlice.actions;
export default counterSlice.reducer;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈에서 thunk로 3초 기다린 후에 실행되도록 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1678621837271&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/App.jsx

import React from &quot;react&quot;;
import { useState } from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;
import { __addNumber } from &quot;./redux/modules/counterSlice&quot;;

const App = () =&amp;gt; {
  const dispatch = useDispatch();
  const [number, setNumber] = useState(0);
  const globalNumber = useSelector((state) =&amp;gt; state.counter.number);

  const onChangeHandler = (evnet) =&amp;gt; {
    const { value } = evnet.target;
    setNumber(+value);
  };

  // thunk 함수를 디스패치한다. payload는 thunk함수에 넣어주면,
  // 리덕스 모듈에서 payload로 받을 수 있다.
  const onClickAddNumberHandler = () =&amp;gt; {
    dispatch(__addNumber(number));
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;{globalNumber}&amp;lt;/div&amp;gt;
      &amp;lt;input type=&quot;number&quot; onChange={onChangeHandler} /&amp;gt;
      &amp;lt;button onClick={onClickAddNumberHandler}&amp;gt;더하기&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thunk로 만든 함수를 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; 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;통신 진행중, 실패, 성공&lt;/p&gt;
&lt;pre id=&quot;code_1678625255675&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//모듈
import { createAsyncThunk, createSlice } from &quot;@reduxjs/toolkit&quot;;
import axios from &quot;axios&quot;;

const initialState = {
  todos: [],
  isLoading: false,
  error: null,
};

export const __getTodos = createAsyncThunk(
  &quot;todos/getTodos&quot;,
  async (payload, thunkAPI) =&amp;gt; {
    try {
      const data = await axios.get(&quot;http://localhost:4000/todos&quot;);
      return thunkAPI.fulfillWithValue(data.data);
    } catch (error) {
      return thunkAPI.rejectWithValue(error);
    }
  }
);

export const todosSlice = createSlice({
  name: &quot;todos&quot;,
  initialState,
  reducers: {},
  extraReducers: {
    [__getTodos.pending]: (state) =&amp;gt; {
      state.isLoading = true; // 네트워크 요청이 시작되면 로딩상태를 true로 변경합니다.
    },
    [__getTodos.fulfilled]: (state, action) =&amp;gt; {
      state.isLoading = false; // 네트워크 요청이 끝났으니, false로 변경합니다.
      state.todos = action.payload; // Store에 있는 todos에 서버에서 가져온 todos를 넣습니다.
    },
    [__getTodos.rejected]: (state, action) =&amp;gt; {
      state.isLoading = false; // 에러가 발생했지만, 네트워크 요청이 끝났으니, false로 변경합니다.
      state.error = action.payload; // catch 된 error 객체를 state.error에 넣습니다.
    },
  },
});

export const {} = todosSlice.actions;
export default todosSlice.reducer;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1678625278121&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//브라우저
import React, { useEffect } from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;
import { __getTodos } from &quot;../redux/modules/todosSlice&quot;;

function Second() {
  const dispatch = useDispatch();
  const { isLoading, error, todos } = useSelector((state) =&amp;gt; state.todos);

  useEffect(() =&amp;gt; {
    dispatch(__getTodos());
  }, [dispatch]);

  if (isLoading) {
    return &amp;lt;div&amp;gt;로딩 중....&amp;lt;/div&amp;gt;;
  }

  if (error) {
    return &amp;lt;div&amp;gt;{error.message}&amp;lt;/div&amp;gt;;
  }

  return (
    &amp;lt;div&amp;gt;
      {todos.map((todo) =&amp;gt; (
        &amp;lt;div key={todo.id}&amp;gt;{todo.title}&amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}

export default Second;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>thunk</category>
      <category>리덕스</category>
      <category>미들웨어</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/171</guid>
      <comments>https://innocentcodingstory.tistory.com/171#entry171comment</comments>
      <pubDate>Mon, 13 Mar 2023 20:50:10 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.12) 항해 5주차 회고</title>
      <link>https://innocentcodingstory.tistory.com/170</link>
      <description>&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;/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;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/170</guid>
      <comments>https://innocentcodingstory.tistory.com/170#entry170comment</comments>
      <pubDate>Sun, 12 Mar 2023 23:37:00 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.11) 항해 34일차 (3- 비동기 통신 - axios)</title>
      <link>https://innocentcodingstory.tistory.com/169</link>
      <description>&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;/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;오늘은 좀 늦게까지 공부하느라 힘들긴 했지만 뿌듯하니 됐당!!!!!!!!&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;span style=&quot;color: #333333;&quot;&gt;*이번 내용에서 사용하게 될 기본 명령어 모음!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678524507904&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add react-redux @reduxjs/toolkit //리덕스 툴킷 설치
yarn add json-server //json-server 설치
yarn json-server --watch db.json --port 4000 //json-server의 4000 port 실행&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1) Axios&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;공식문서에 따르면 axios 란 node.js와 브라우저를 위한 Promise 기반 http 클라이언트 라고 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;즉, http를 이용해서 서버와 통신하기 위해 사용하는 패키지이다.&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① Axios 설치하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678522749371&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add axios&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;설치 후 테스트를 해야 하니 json-server도 설치 후 실행해주자!&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2) &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;GET&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① Axios get 사용방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;get은 서버의 데이터를 조회할 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// url에는 서버의 url이 들어가고, config에는 기타 여러가지 설정을 추가할 수 있다.
// config는 axios 공식문서에서 확인하기!

axios.get(url[, config]) // GET&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;참고 공식문서 링크: &lt;a style=&quot;color: #333333;&quot; href=&quot;https://axios-http.com/kr/docs/req_config&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://axios-http.com/kr/docs/req_config&lt;/a&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;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;② 우리가 사용하는 json-server API 명세서 확인하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 Axios를 사용해서 GET 요청 코드를 작성하기에 앞서, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어떤 방식으로 요청 해야할지는 우리가 사용하는 json-server의 방식을 알아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;즉, Axios는 GET 요청을 할 수 있도록 도와주는 패키지일뿐이지,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; &amp;ldquo;어떻게 요청을 해야하지?&amp;rdquo; 와 같은 방식에 대한 확인은 우리가 사용할 API 명세서를 보아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; ex) GET 요청을 할 때 path variable로 해야할지, query로 보내야할지는 API를 만든 사람이 하라는대로 해야 한다....!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&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; color: #333333;&quot;&gt;json-server의 공식문서를 보면, &lt;/span&gt;&lt;/p&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; color: #333333;&quot;&gt;전체 정보나 상세 정보는 아래와 같이 path variable 로 url을 작성하면 된다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4PN4h/btr3efAgkBj/ECnqaIHJQRUAunhzhNPXV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4PN4h/btr3efAgkBj/ECnqaIHJQRUAunhzhNPXV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4PN4h/btr3efAgkBj/ECnqaIHJQRUAunhzhNPXV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4PN4h%2Fbtr3efAgkBj%2FECnqaIHJQRUAunhzhNPXV0%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;1280&quot; height=&quot;182&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그리고 filter와 같은 기능을 위해서 GET 요청을 하고자할 때는 query로 보내라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFoBaB/btr3dSSNpq1/idMQOz37CeLsIv9gosqXnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFoBaB/btr3dSSNpq1/idMQOz37CeLsIv9gosqXnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFoBaB/btr3dSSNpq1/idMQOz37CeLsIv9gosqXnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFoBaB%2Fbtr3dSSNpq1%2FidMQOz37CeLsIv9gosqXnK%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;1280&quot; height=&quot;328&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;328&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;span style=&quot;color: #333333;&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;color: #333333;&quot;&gt;코드를 통해 사용방법을 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 우리가 만든 json-server에 있는 todos를, axios를 이용해서 fetching하고 useState를 통해서 관리하는 로직이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678522586234&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect, useState } from &quot;react&quot;;
import axios from &quot;axios&quot;;

const App = () =&amp;gt; {
  const [todos, setTodos] = useState(null);

  // axios를 통해서 get 요청을 하는 함수를 생성힌다.
  // 비동기처리를 해야하므로 async/await 구문을 통해서 처리한다.
  const fetchTodos = async () =&amp;gt; {
    const { data } = await axios.get(&quot;http://localhost:3001/todos&quot;);
    setTodos(data); // 서버로부터 fetching한 데이터를 useState의 state로 set 한다.
  };

  // 생성한 함수를 컴포넌트가 mount 됐을 떄 실행하기 위해 useEffect를 사용한다.
  useEffect(() =&amp;gt; {
    // effect 구문에 생성한 함수를 넣어 실행한다.
    fetchTodos();
  }, []);

  // data fetching이 정상적으로 되었는지 콘솔을 통해 확인한다.
  console.log(todos);
  return (
    &amp;lt;div&amp;gt;
      {todos?.map((item) =&amp;gt; {
        return (
          &amp;lt;div key={item.id}&amp;gt;
            {item.id} : {item.title}
          &amp;lt;/div&amp;gt;
        );
      })}
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;콘솔로 결과를 확인하니, 우리가 생성한 Todos를 정상적으로 서버에서 가져와서 state가 set 한 것을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDd6EB/btr3ee2vT8l/KAxUVfOaFSQMBV2ApqeUn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDd6EB/btr3ee2vT8l/KAxUVfOaFSQMBV2ApqeUn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDd6EB/btr3ee2vT8l/KAxUVfOaFSQMBV2ApqeUn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDd6EB%2Fbtr3ee2vT8l%2FKAxUVfOaFSQMBV2ApqeUn1%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;227&quot; height=&quot;117&quot; data-origin-width=&quot;227&quot; data-origin-height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;3) POST&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① Axios post 사용방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Axios POSTpost는 보통 서버에 데이터를 추가할 때 사용한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다만 post 요청에 대한 로직은 BE 개발자가 구현하는 것이기때문에 추가외에 다른 용도로 사용될 수 있지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 보통은 클라이언트의 데이터를 body형태로 서버에 보내고자 할 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678546203419&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;axios.post(url[, data[, config]]) // POST&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&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;color: #333333;&quot;&gt;화면에 인풋과 버튼이 있고, 인풋에 어떤 값을 넣고 버튼을 클릭했을 때 onSubmitHandler 이 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;onSubmitHandler 함수의 목적은 todo를 body에 담아 서버로 POST 요청을 보내는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아까의 get을 사용했던 코드에 아래의 코드를 추가만 해 주었다!&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678550428656&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const App = () =&amp;gt; {
  const [todo, setTodo] = useState({
    title: &quot;&quot;,
  });

  // 추가 함수
  const onSubmitHandler = async () =&amp;gt; {
    axios.post(`${process.env.REACT_APP_SEVER_KEY}/todos`, todo);
    setTodos([...todos, todo]);
  };

  return (
    &amp;lt;&amp;gt;
      {/* Input영역 */}
      &amp;lt;form
        onSubmit={(e) =&amp;gt; {
          // submit했을 때 브라우저의 새로고침을 방지한다.
          e.preventDefault();
          onSubmitHandler(todo);
        }}
      &amp;gt;
        &amp;lt;input
          type=&quot;text&quot;
          onChange={(ev) =&amp;gt; {
            const { value } = ev.target;
            setTodo({
              ...todo,
              title: value,
            });
          }}
        /&amp;gt;
        &amp;lt;button&amp;gt;추가하기&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      {/* 데이터 영역 */}
      &amp;lt;div&amp;gt;
        {todos?.map((todo) =&amp;gt; (
          &amp;lt;div key={todo.id}&amp;gt;
            {todo.id} : {todo.title}
          &amp;lt;/div&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;4) DELETE&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① Axios delete 사용방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;DELETE는 저장되어 있는 데이터를 삭제하고자 요청을 보낼 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;axios.&lt;span class=&quot;hljs-keyword&quot;&gt;delete&lt;/span&gt;(url[, &lt;span class=&quot;hljs-built_in&quot;&gt;config&lt;/span&gt;]) &lt;span class=&quot;hljs-comment&quot;&gt;// DELETE&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;② 코드로 알아보기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;onClickDeleteButtonHandler 와 map 을 돌린 항목별로 삭제하기 버튼을 추가해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;삭제 버튼을 누르면 삭제 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기존 위의 코드들에 아래 코드만 추가해주었다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678551989574&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; //삭제 함수
  const onClickDeleteButtonHandler = (id) =&amp;gt; {
    axios.delete(`http://localhost:4000/todos/${id}`);
    setTodos(
      todos.filter((item) =&amp;gt; {
        return item.id !== id;
      })
    );
  };

      &amp;lt;div&amp;gt;
        {todos?.map((todo) =&amp;gt; (
          &amp;lt;div key={todo.id}&amp;gt;
            {todo.id} : {todo.title}
            //삭제 버튼 추가
            &amp;lt;button
              type=&quot;button&quot;
              onClick={() =&amp;gt; onClickDeleteButtonHandler(todo.id)}
            &amp;gt;
              삭제하기
            &amp;lt;/button&amp;gt;
          &amp;lt;/div&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;5) PATCH&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① Axios patch 사용방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;patch는 보통 어떤 데이터를 수정하고자 서버에 요청을 보낼 때 사용하는 메서드 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 다만, 이것은 http 환경에서 서로가 한 약속이자 문맥이기때문에, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;수정을 하고자 반드시 patch, put 을 써야만 하는 것은 아니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; BE에 의해서 POST를 통해서 &amp;ldquo;수정&quot; 이라는 기능은 충분히 만들 수 있기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 다만 이러한 약속들을 대부분의 개발자들이 지키고 있다는 점을 알고 있자!&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;axios.patch(url[, data[, config]])  // PATCH
&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;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;② 코드로 알아보기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Todo를 수정하기 위해 필요한 데이터는 2개가 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;수정하고자하는 Todo의 id, 그리고 수정하고자 하는 값이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 수정하고자 하는 값은 기존에 있던 todo라는 state를 사용하면 될 것이고, &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;id는 직접 입력을 해서 url로 넘겨주는 방식으로 구현했다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;마찬가지로 위의 코드들에 밑의 코드만 추가했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678557383627&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  const [targetId, setTargetId] = useState(&quot;&quot;);
  const [editTodo, setEditTodo] = useState(&quot;&quot;);

  //수정 함수
  const onClickEditButtonHandler = async () =&amp;gt; {
    axios.patch(`http://localhost:4000/todos/${targetId}`, {
      title: editTodo,
    });
    setTodos(
      todos.map((item) =&amp;gt; {
        if (item.id == targetId) {
          return { ...item, title: editTodo };
        } else {
          return item;
        }
      })
    );
    setTargetId(&quot;&quot;);
    setEditTodo(&quot;&quot;);
  };

  return (
        &amp;lt;div&amp;gt;
          &amp;lt;input
            type=&quot;text&quot;
            placeholder=&quot;수정하고싶은 Todo ID&quot;
            value={targetId}
            onChange={(e) =&amp;gt; {
              setTargetId(e.target.value);
            }}
          /&amp;gt;
          &amp;lt;input
            type=&quot;text&quot;
            placeholder=&quot;수정값 입력&quot;
            value={editTodo}
            onChange={(e) =&amp;gt; {
              setEditTodo(e.target.value);
            }}
          /&amp;gt;
          &amp;lt;button
            // type='button' 을 추가해야 form의 영향에서 벗어남
            type=&quot;button&quot;
            onClick={() =&amp;gt; onClickEditButtonHandler()}
          &amp;gt;
            수정하기
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;color: #333333;&quot;&gt;6) ENV&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;변수명은 반드시 'REACT_APP_'으로 시작해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;.gitignore에 env를 등록해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기본으로 세팅이 되어있지만 확인해주도록 하자!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;소스코드에서 import 없이 process.env.REACT_APP_변수명으로 불러오면 적용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;만약 env의 값을 변경하여 적용하고 싶다면, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;변경 후 server를 다시 실행시켜주어야 정상적으로 적용된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678558186267&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect, useState } from &quot;react&quot;;
import axios from &quot;axios&quot;;
const REACT_APP_SEVER_KEY = &quot;http://localhost:4000&quot;;

const App = () =&amp;gt; {
  // 조회 함수
  const fetchTodos = async () =&amp;gt; {
    const { data } = await axios.get(`${REACT_APP_SEVER_KEY}/todos`);
  };

  // 추가 함수
  const onSubmitHandler = async () =&amp;gt; {
    axios.post(`${REACT_APP_SEVER_KEY}/todos`, todo);
  };

  //삭제 함수
  const onClickDeleteButtonHandler = async (id) =&amp;gt; {
    axios.delete(`${REACT_APP_SEVER_KEY}/todos/${id}`);
  };

  //수정 함수
  const onClickEditButtonHandler = async () =&amp;gt; {
    axios.patch(`http://localhost:4000/todos/${targetId}`, {
  };&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;&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;7) instance와 interceptor&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① axios interceptor&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름에서 알 수 있듯, 다음 두 상황에서 흐름을 가로채서 여러분이 어떠한 코드 상의 관여를 할 수 있게 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;요청(request)이 처리되기 전( = http request가 서버에 전달되기 전)&lt;/li&gt;
&lt;li&gt;&amp;nbsp;응답(response)의 then(=성공) 또는 catch(=실패)가 처리되기 전&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BZnn6/btr3bYGHyyi/L7mlLdTBLHD2DwLJ8LM0bK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BZnn6/btr3bYGHyyi/L7mlLdTBLHD2DwLJ8LM0bK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BZnn6/btr3bYGHyyi/L7mlLdTBLHD2DwLJ8LM0bK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBZnn6%2Fbtr3bYGHyyi%2FL7mlLdTBLHD2DwLJ8LM0bK%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;600&quot; height=&quot;632&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;632&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 우리가 가정했던 상황들을 포함하여 요청 및 응답시에 필요한 작업들을 한꺼번에 처리를 할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&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;/ul&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;size18&quot;&gt;&lt;b&gt;② 코드로 알아보기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❶ instance 만들기, baseURL 설정하기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;const data = axios.get(&quot;&amp;lt;http://localhost:4000/&amp;gt;&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios를 사용하는 방법으로 데이터 통신을 해왔다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완전히 plain axios, 순수 axios이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, custom 설정이 전혀 되어있지 않았는데, 이 axios를 인스턴스(instance)라고 한다.&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 파일을 만든다.&lt;/p&gt;
&lt;pre id=&quot;code_1678617890984&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//src &amp;gt; axios &amp;gt; api.js

import axios from &quot;axios&quot;;

// axios.create의 입력값으로 들어가는 객체는 configuration 객체이다.

const instance = axios.create({
	baseURL: &quot;http://localhost:4000&quot;,
});

export default instance;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 app 파일에 연결을 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1678617989749&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import api from &quot;./axios/api&quot;;

  // 조회 함수
  const fetchTodos = async () =&amp;gt; {
    const { data } = await api.get(&quot;/todos&quot;);
  };

  // 추가 함수
  const onSubmitHandler = async () =&amp;gt; {
    api.post(&quot;/todos&quot;, todo);
  };

  //삭제 함수
  const onClickDeleteButtonHandler = async (id) =&amp;gt; {
    api.delete(`/todos/${id}`);
  };

  //수정 함수
  const onClickEditButtonHandler = async () =&amp;gt; {
    api.patch(`/todos/${targetId}`);
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api를 import 하고 기존에 axios.을 사용하였던 것을 api.으로 바꾸고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소도 지워줄 수 있어&amp;nbsp; /todos로 연결할 수 있다.&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;request, response에 적용해보기&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;특정한 일을 수행해야 한다면 interceptors를 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1678618273823&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//api.js

import axios from &quot;axios&quot;;

const instance = axios.create({
  baseURL: &quot;http://localhost:4000&quot;,
  // timeout: 1,
  //0.001초의 시간을 주어 이 시간내에 응답을 못 받으면 오류가 나게 한다.
});

instance.interceptors.request.use(
  // 요청을 보내기 전 수행되는 함수
  function (config) {
    console.log(&quot;인터셉트 요청 성공!&quot;);
    return config;
  },
  // 오류 요청을 보내기 전 수행되는 함수
  function (error) {
    console.log(&quot;인터셉트 요청 오류!&quot;);
    return Promise.reject(error);
  }
);

instance.interceptors.response.use(
  //응답을 내보내기 전 수행되는 함수
  function (response) {
    console.log(&quot;인터넵트 응답 받았어요!&quot;);
    return response;
  },
  // 오류응답을 내보내기 전 수행되는 함수
  function (error) {
    console.log(&quot;인터셉트 응답 못받았어요...ㅠㅠ&quot;);
    return Promise.reject(error);
  }
);

export default instance;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 instance.interceptors를 사용하여 성공 시와 오류가 났을 때의 함수를 만들어준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, request와 response로 요청 시와 응답 시에 실행되도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 settimeout:1을 해주게 되면 0.001초라는 짧은 시간내에 응답을 받아야 하기에 오류가 날 수 밖에 없다.&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;&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;
&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>TIL(Today I Learned)</category>
      <category>axios</category>
      <category>Delete</category>
      <category>ENV</category>
      <category>get</category>
      <category>Instance</category>
      <category>instancer</category>
      <category>Interceptor</category>
      <category>patch</category>
      <category>post</category>
      <category>비동기</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/169</guid>
      <comments>https://innocentcodingstory.tistory.com/169#entry169comment</comments>
      <pubDate>Sun, 12 Mar 2023 14:06:56 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.11) 항해 34일차 (2-json-server, HTTP)</title>
      <link>https://innocentcodingstory.tistory.com/168</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;협업이 곧 얼마 남지 않았음이 와닿는 주차긴 하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;json-server도 사용해보고 HTTP 프로토콜도 배우고 나니&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;뭔가 설레면서 걱정되는 기분이 동시에 들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다른 분들의 발목을 잡지 않기 위해 열심히 해야겠따!!!&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;1) json-server&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;json-server를 통해서 FE에서는 BE가 하고 있는 작업을 기다리지 않고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;FE의 로직과 화면을 구현 할 수 있어 효율적으로 협업을 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;json-server란, 아주 간단한 DB와 API 서버를 생성해주는 패키지&amp;nbsp;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 우리가 json-server를 사용하는 이유는BE에서 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;실제 DB와 API Server가 구축될 때까지,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;FE 개발에 임시적으로 사용할 mock data를 생성하기 위해서다!&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;span style=&quot;color: #333333;&quot;&gt;① json-server 설치하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;yarn add json-server&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;CRA로 프로젝트를 새로 생성하고, yarn 또는 npm을 이용해서 설치한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;나는 yarn을 사용하니 yarn으로 설치했당.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;② json-server 사용하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;json-server가 간단한 패키지이긴 하나, 말그대로 서버 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 리액트와는 별개로 따로 실행을 해줘야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 리액트도 start하고, json-server로 start 해야 한다....!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래야 리액트와 json-server가 서로 통신 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령을 통해 json-sever를 실행하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(명령어의 대략적인 뜻은 db.json 이라는 것을 db로 삼고, 3001 포트에서 서버를 시작하겠다는 뜻)&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;yarn json-server --watch db.json --port 3001&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;③ 설치 후&amp;nbsp; db.json 파일과 코드 자동 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 명령어를 입력하면 db.json이 자동으로 생성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이 json 파일을 db로 사용하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 그리고 posts, comments, profile 라는 기본적인 값들을 자동으로 넣어준다.&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;span style=&quot;color: #333333;&quot;&gt;❶ 설치 후 db.json 파일의 모습&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678515610648&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//db.json 파일
{
  &quot;posts&quot;: [
    {
      &quot;id&quot;: 1,
      &quot;title&quot;: &quot;json-server&quot;,
      &quot;author&quot;: &quot;typicode&quot;
    }
  ],
  &quot;comments&quot;: [
    {
      &quot;id&quot;: 1,
      &quot;body&quot;: &quot;some comment&quot;,
      &quot;postId&quot;: 1
    }
  ],
  &quot;profile&quot;: {
    &quot;name&quot;: &quot;typicode&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❷ 설치 후 터미널의 모습!!&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4atbx/btr3c3UA7wL/9zqrMiEpPdTzuddLM9k1Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4atbx/btr3c3UA7wL/9zqrMiEpPdTzuddLM9k1Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4atbx/btr3c3UA7wL/9zqrMiEpPdTzuddLM9k1Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4atbx%2Fbtr3c3UA7wL%2F9zqrMiEpPdTzuddLM9k1Kk%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;292&quot; height=&quot;225&quot; data-origin-width=&quot;292&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❸ db 수정해보기!&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678515864282&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//db에 todos를 추가해보았다
{
  &quot;todos&quot;: [
    {
      &quot;id&quot;: 1,
      &quot;title&quot;: &quot;json-server&quot;,
      &quot;content&quot;: &quot;json-server를 배워봅시다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;todos가 추가되었고 브라우저도 정상적으로 보인다~&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;span style=&quot;color: #333333;&quot;&gt;❹ 서버 들어가보기! (맥 기준 cmd키를 누르며 주소창 클릭하면 된당)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l21ay/btr3eeuwN9G/xD1hk1iRQGUxS0skhJZ4Ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l21ay/btr3eeuwN9G/xD1hk1iRQGUxS0skhJZ4Ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l21ay/btr3eeuwN9G/xD1hk1iRQGUxS0skhJZ4Ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl21ay%2Fbtr3eeuwN9G%2FxD1hk1iRQGUxS0skhJZ4Ak%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;232&quot; height=&quot;127&quot; data-origin-width=&quot;232&quot; data-origin-height=&quot;127&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버에 들어가보면 터미널에서&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elVVem/btr3dEtr9Nl/fv7CxeOdboZAXgd8D78jx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elVVem/btr3dEtr9Nl/fv7CxeOdboZAXgd8D78jx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elVVem/btr3dEtr9Nl/fv7CxeOdboZAXgd8D78jx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelVVem%2Fbtr3dEtr9Nl%2Ffv7CxeOdboZAXgd8D78jx1%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;229&quot; height=&quot;37&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 누군가 GET했다고 알려준다.&lt;/span&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;2) HTTP&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 프로토콜&lt;/span&gt;&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;그 방식대로 서로 데이터를 주고 받아야만 오류가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;약속을 프로토콜(protocol)이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 특히, 웹에서 서버 &amp;harr; 클라이언트간 주고 받은 상호간의 약속(프로토콜)을 HTTP 프로토콜이라고 하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;데이터를 주고 받기 위해 HTTP 프로토콜을 사용하고 있다.&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② 요청(Request)과 응답(Response)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;서버와 클라이언트가 서로 데이터를 주고 받기 위해서는 항상 &amp;lsquo;요청(request)&amp;rsquo;을 하고, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그에 따른 &amp;lsquo;응답(response)&amp;rsquo;을 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;보통 클라이언트가 대화를 시도하고, 서버는 요청을 받아 그에 따른 응답을 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bS2wjz/btr3bdKruQ4/AozuSmXzhnjh0AyWVq9uNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bS2wjz/btr3bdKruQ4/AozuSmXzhnjh0AyWVq9uNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bS2wjz/btr3bdKruQ4/AozuSmXzhnjh0AyWVq9uNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbS2wjz%2Fbtr3bdKruQ4%2FAozuSmXzhnjh0AyWVq9uNK%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;600&quot; height=&quot;252&quot; data-origin-width=&quot;770&quot; data-origin-height=&quot;324&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ URL&lt;/span&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;URL에서 등장하는 용어들&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;protocol&lt;/li&gt;
&lt;li&gt;domain(sub domain, domain name)&lt;/li&gt;
&lt;li&gt;resource path(path/page)&lt;/li&gt;
&lt;li&gt;query variable, path variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xTnZB/btr3cJ9QGer/fp4IL3F5zKbevg1PRP33h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xTnZB/btr3cJ9QGer/fp4IL3F5zKbevg1PRP33h0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xTnZB/btr3cJ9QGer/fp4IL3F5zKbevg1PRP33h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxTnZB%2Fbtr3cJ9QGer%2Ffp4IL3F5zKbevg1PRP33h0%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;600&quot; height=&quot;253&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;404&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;④ 메서드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;메서드란 HTTP 요청의 종류로, 클라이언트가 서버에 하는 요청의 종류이다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(더 많지만 간략하게 알고, 필요할때 마다 찾아보기!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(참고 링크: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods&lt;/a&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;메서드GET - 조회&lt;/li&gt;
&lt;li&gt;POST - 생성&lt;/li&gt;
&lt;li&gt;PUT, PATCH - 수정(변경)&lt;/li&gt;
&lt;li&gt;DELETE - 삭제&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;span style=&quot;color: #333333;&quot;&gt;⑤ 상태코드&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;클라이언트가 서버에 어떤 요청(request)를 하고 나면, 서버는 그에 맞는 응답(response)를 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&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;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;1xx(정보) :&amp;nbsp;요청을 받았으며 프로세스를 계속 진행합니다.&lt;/li&gt;
&lt;li&gt;2xx(성공) :&amp;nbsp;요청을 성공적으로 받았으며 인식했고 수용하였습니다.&lt;/li&gt;
&lt;li&gt;3xx(리다이렉션) :&amp;nbsp;요청 완료를 위해 추가 작업 조치가 필요합니다.&lt;/li&gt;
&lt;li&gt;4xx(클라이언트 오류) :&amp;nbsp;요청의 문법이 잘못되었거나 요청을 처리할 수 없습니다.&lt;/li&gt;
&lt;li&gt;5xx(서버 오류) :&amp;nbsp;서버가 명백히 유효한 요청에 대한 충족을 실패했습니다.&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;&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>TIL(Today I Learned)</category>
      <category>db.json</category>
      <category>HTTP</category>
      <category>json-server</category>
      <category>URL</category>
      <category>메서드</category>
      <category>상태코드</category>
      <category>프로토콜</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/168</guid>
      <comments>https://innocentcodingstory.tistory.com/168#entry168comment</comments>
      <pubDate>Sun, 12 Mar 2023 14:03:56 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.11) 항해 34일차 (1-리덕스 툴킷)</title>
      <link>https://innocentcodingstory.tistory.com/167</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;/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;이번 주차에서 비동기 부분이 힘들다고 하니 쉽지만은 않겠지만 시작은 좋당!&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;1) 리덕스 툴킷&lt;/b&gt;&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;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;코드는 더 적게 리덕스를 더 편하게 쓰기 위한 기능들을 흡수해서 만든 것이 리덕스툴킷 이고, 줄여서 RTK 라고도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;새로운 것이 아닌, 리덕스의 전체 코드의 양을 줄이기 위해 새로운 API가 추가되었고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;일일히 손으로 만들어 줘야 했던 ducks 패턴의 요소들이 어느정도 자동화 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트에서 useSelector를 통해서 사용하는 것은 모두 똑같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 바뀐 부분은 그저 모듈 파일일 뿐!! &lt;/span&gt;&lt;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 툴킷 설치하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;yarn add react-redux @reduxjs/toolkit&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② 모듈과 스토어 연결&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;일반 리덕스와 큰 차이는 없지만, 조금의 차이는 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678495617709&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/config/configStore.js

import { configureStore } from &quot;@reduxjs/toolkit&quot;; //기존 리덕스와 다르다!!
import counter from &quot;../modules/counterSlice&quot;;
import todos from &quot;../modules/todosSlice&quot;;

//모듈(Slice)이 여러개인 경우, 추가할때마다 reducer 안에 각 모듈의 slice.reducer를 추가해줘야 한다.

//아래 예시는 하나의 프로젝트 안에서 counter 기능과 todos 기능이 모두 있고,
//이것을 각각 모듈로 구현한 다음에 아래 코드로 2개의 모듈을 스토어에 연결해준 것 이다.

const store = configureStore({
  reducer: { counter: counter, todos: todos },
});

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;➂ index.js&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;생성한 store를 export default 해서 최상위의 index.js Provider에 주입해주는 것은 전혀 바뀐게 없다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678495774235&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// index.js

import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import App from &quot;./App&quot;;
import { Provider } from &quot;react-redux&quot;;
import store from &quot;./redux/config/configStore&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(
  &amp;lt;Provider store={store}&amp;gt;
    &amp;lt;App /&amp;gt;
  &amp;lt;/Provider&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;➃ 모듈&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리덕스 툴킷에서는 큰 차이점은 Action Value와 Action Creator를 이제 직접 생성해주지 않고, &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Action Value, Action Creator, Reducer가 하나로 합쳐졌다는 점 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이제 우리는 Slice 라는 API를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이 슬라이스를 사용하면 Action Value, Action Creator, Reducer를 각각 만들어줄 필요 없이,&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;한번에 3개가 모두 만들어진다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678496196023&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/counterSlice.js
// 파일명이 다르다는 것을 눈치채보자!

import { createSlice } from &quot;@reduxjs/toolkit&quot;;

const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: &quot;counter&quot;, // 이 모듈의 이름
  initialState, // 이 모듈의 초기상태 값
  reducers: { // 이 모듈의 Reducer 로직
  // 리듀서 안에서 만든 함수 자체가 리듀서의 로직이자, 액션크리에이터가 된다.
  // 그래서 Reducer만 만들어 주면 된다.
    addNumber: (state, action) =&amp;gt; {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) =&amp;gt; {
      state.number = state.number - action.payload;
    },
  },
});

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;
// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;➄ &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;모듈 조회&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;App.jsx에서는 툴킷을 사용해서 만든 모듈을 조회할 수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;방식은 일반리덕스를 사용했을 때와 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1678495841073&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/App.js

import React from &quot;react&quot;;
import { useSelector } from &quot;react-redux&quot;;

const App = () =&amp;gt; {
  // Store에 있는 todos 모듈 state 조회하기
  const todos = useSelector((state) =&amp;gt; state.todos);

  // Store에 있는 counter 모듈 state 조회하기
  const counter = useSelector((state) =&amp;gt; state.counter);

  return &amp;lt;div&amp;gt;App&amp;lt;/div&amp;gt;;
};

export default App;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>action creator</category>
      <category>Action Value</category>
      <category>ducks 패턴</category>
      <category>reducer</category>
      <category>리덕스</category>
      <category>리덕스 툴킷</category>
      <category>리액트</category>
      <category>모듈</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/167</guid>
      <comments>https://innocentcodingstory.tistory.com/167#entry167comment</comments>
      <pubDate>Sun, 12 Mar 2023 13:58:59 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.10) 항해 33일차</title>
      <link>https://innocentcodingstory.tistory.com/166</link>
      <description>&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;인풋창에 숫자만 입력되게 하고 세자릿수마다 콤마가 찍히도록 하기 위해서&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;pre id=&quot;code_1678455155160&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  const priceChangHandler = (setPrice, e) =&amp;gt; {
    e.target.value = e.target.value.replace(/[^0-9]/g, &quot;&quot;); // 입력값이 숫자가 아니면 공백
    e.target.value = e.target.value.replace(/,/g, &quot;&quot;); // ,값 공백처리
    e.target.value = e.target.value.replace(/\B(?=(\d{3})+(?!\d))/g, &quot;,&quot;); // 정규식을 이용해서 3자리 마다 , 추가
    setPrice(e.target.value);
  };&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모달도 div 박스로 구현해서 true이면 display가 flex로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;false이면 display가 none으로 동작하게 해서 모달창을 구현하였다.&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;pre id=&quot;code_1678455331464&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;onClick={(e) =&amp;gt; e.stopPropagation()}&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;&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;overflow를 사용하니 생각보다 별거 없었다.....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;div박스를 이곳저곳에 만들어보며 별 짓을 다 했는데,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결하고 버튼의 크기가 변하는 것을 막기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;min-heigth도 주었다!!!&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>TIL(Today I Learned)</category>
      <category>Button</category>
      <category>input</category>
      <category>Modal</category>
      <category>select</category>
      <category>리액트</category>
      <category>모달</category>
      <category>버튼</category>
      <category>셀렉터</category>
      <category>인풋</category>
      <category>정규식</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/166</guid>
      <comments>https://innocentcodingstory.tistory.com/166#entry166comment</comments>
      <pubDate>Fri, 10 Mar 2023 23:27:12 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.09) 항해 32일차</title>
      <link>https://innocentcodingstory.tistory.com/165</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;span style=&quot;color: #333333;&quot;&gt;최대한 컴파운드를 기능단위로 쪼개서 칠드런으로 컴파운드를 계속 뱉어 들어간다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이렇게하면 코드 재사용이 매우 편해진다는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;애지간하면 props를 자제하는게 좋은데 분기가 단순한 경우에는&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt; props 한둘 정도는 넣어도 괜찮다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 컴파운드컴포넌트 패턴을 사용하면 복잡한 컴포넌트를 유연하게 사용할수 있다는 장점이 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해당 패턴이 들어가는 컴파운드 부분에서 전체적인 구조를 한눈에 알아 볼 수 있고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;스타일 지정하고 디자인을 변경하는게 아주 용이하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 협업시 다른 개발자가 볼 경우 한번에 뭐가 뭔지 알아볼 수 있게 하는 게 중요하니깐 네이밍이 중요하니 연습이라도 해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;밑은 예시코드이다!&lt;/span&gt;&lt;/div&gt;
&lt;pre id=&quot;code_1678365412927&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
&amp;lt;Wrap&amp;gt;
	&amp;lt;StForm onSubmit={submit}&amp;gt;
		&amp;lt;StRowFlexDiv style={{ justifyContent: 'space-between' }}&amp;gt;
			&amp;lt;StRowFlexDiv style={{ gap: '5px' }}&amp;gt;
				&amp;lt;input ref={titleRef} placeholder='Title' /&amp;gt;
				&amp;lt;input ref={memoRef} placeholder='Memo' /&amp;gt;
			&amp;lt;/StRowFlexDiv&amp;gt;
			&amp;lt;button type='submit'&amp;gt;Submit&amp;lt;/button&amp;gt;
		&amp;lt;/StRowFlexDiv&amp;gt;
	&amp;lt;/StForm&amp;gt;
&amp;lt;/Wrap&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;uuid를 이용한 고유한 값 생성 uuid는 소프트웨어 구축에 쓰이는 식별자 표준이다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;uuidsms 32개의 16진수로 표현되며 총 36개의 문자로 된 8-4-4-4-12라는 5개의 그룹을 하이픈으로 구분한다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;550e8400-e29b-41d4-a716-446655440000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이런식~~~ 으로~~ 표현된다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2.71 * 10^18 개의 UUID를 생성했을 때 최소 1개가 중복(충돌) 될 확률이 약 50%라고 한다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;따라서 uuid가 중복될 걱정은 안하고 고유값으로 사용해도 될 거 같다. &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그리고 실제로도 현업에서도 많이 사용한다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;명령어 - npm install uuid (uuid 생성 패키지를 받는다!)&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;import {v4 as uuidv4} from 'uuid'; uuidv4(); 함수를 실행하면 사용한다!!&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>Compound Component Pattern</category>
      <category>UUID</category>
      <category>컴파운드</category>
      <category>컴파운드 컴포넌트 패턴</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/165</guid>
      <comments>https://innocentcodingstory.tistory.com/165#entry165comment</comments>
      <pubDate>Thu, 9 Mar 2023 21:56:38 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.08) 항해 31일차 (투두리스트 상세페이지)</title>
      <link>https://innocentcodingstory.tistory.com/164</link>
      <description>&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;/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;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;1) 상세 페이지 연결&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1678235101910&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Working 컴포넌트
const navigate = useNavigate();               
&amp;lt;Link to={`/sub/${item.id}`}&amp;gt;상세페이지&amp;lt;/Link&amp;gt; 	  // 1번째 방법
&amp;lt;button 				// 두번째 방법
  onClick={() =&amp;gt; {
    navigate(`/sub/${item.id}`);
  }}
&amp;gt;&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;id로 연결하였고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678235147856&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Router.js
&amp;lt;Route path=&quot;sub/:id&quot; element={&amp;lt;Sub /&amp;gt;} /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라우터 파일에서도 id로 연결되게 했다.&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;별거 없는 것 같지만 3일동안 날 괴롭힌 친구다...&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;a href=&quot;https://todo-redux-2.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://todo-redux-2.vercel.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1678284084859&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;React App&quot; data-og-description=&quot;&quot; data-og-host=&quot;todo-redux-2.vercel.app&quot; data-og-source-url=&quot;https://todo-redux-2.vercel.app/&quot; data-og-url=&quot;https://todo-redux-2.vercel.app/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://todo-redux-2.vercel.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://todo-redux-2.vercel.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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 App&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;todo-redux-2.vercel.app&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;</description>
      <category>TIL(Today I Learned)</category>
      <category>vercel</category>
      <category>리덕스</category>
      <category>리액트</category>
      <category>상세페이지</category>
      <category>수정기능</category>
      <category>투두리스트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/164</guid>
      <comments>https://innocentcodingstory.tistory.com/164#entry164comment</comments>
      <pubDate>Wed, 8 Mar 2023 23:06:44 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.07) 항해 30일차 (깃, 투두리스트)</title>
      <link>https://innocentcodingstory.tistory.com/163</link>
      <description>&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) 깃&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;처음 깃 연결 및 커밋 푸시 할 때,&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;git&amp;nbsp;init&lt;br /&gt;git&amp;nbsp;add&amp;nbsp;.&lt;br /&gt;git&amp;nbsp;commit&amp;nbsp;-m&amp;nbsp;&quot;커밋명&quot;&lt;br /&gt;git&amp;nbsp;remote&amp;nbsp;add&amp;nbsp;origin&amp;nbsp;깃허브주소&lt;br /&gt;git push origin 브랜치명&lt;br /&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;변경 사항 있을때마다,&lt;/b&gt;&lt;br /&gt;git&amp;nbsp;add&amp;nbsp;.&lt;br /&gt;git&amp;nbsp;commit&amp;nbsp;-m&amp;nbsp;&quot;새로운&amp;nbsp;커밋명&quot;&lt;br /&gt;git&amp;nbsp;push&amp;nbsp;origin&amp;nbsp;브랜치명&lt;br /&gt;&lt;br /&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;color: #333333;&quot;&gt;$ git remote -v 현재 연결되어 있는 원격 레파지토리를 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;git remote remove origin을 사용해 주시면 연결되어 있는 저장소를 간단하게 끊을 수 있다.&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;&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) 투두 리스트 대략적인 과정&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BYV4Y/btr2D64aB50/LZkDJ0J2RIsXI1qm7pkGOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BYV4Y/btr2D64aB50/LZkDJ0J2RIsXI1qm7pkGOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BYV4Y/btr2D64aB50/LZkDJ0J2RIsXI1qm7pkGOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBYV4Y%2Fbtr2D64aB50%2FLZkDJ0J2RIsXI1qm7pkGOk%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;169&quot; height=&quot;328&quot; data-origin-width=&quot;169&quot; data-origin-height=&quot;328&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 id=&quot;code_1678168116774&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add react-router-dom  //라우터 돔 패키지 설치
yarn add redux react-redux //리덕스 패키지 설치
yarn add styled-components //스타일드 컴포넌트 패키지 설치&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하기 위한 패키지를 설치한다.&lt;/p&gt;
&lt;pre id=&quot;code_1678167861535&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Router.js

import React from &quot;react&quot;;
// 1. react-router-dom을 사용하기 위해서 아래 API들을 import 합니다.
import { BrowserRouter, Route, Routes } from &quot;react-router-dom&quot;;
import Home from &quot;../pages/Home&quot;;
import Sub from &quot;../pages/Sub&quot;;

// 2. Router 라는 함수를 만들고 아래와 같이 작성합니다.
//BrowserRouter를 Router로 감싸는 이유는,
//SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들어줍니다!
const Router = () =&amp;gt; {
  return (
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path=&quot;/&quot; element={&amp;lt;Home /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;/sub&quot; element={&amp;lt;Sub /&amp;gt;} /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
};

export default Router;&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678167931702&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.js

import React from &quot;react&quot;;
import Router from &quot;./shared/Router&quot;; // 불러오는 주소 조심!!

function App() {
  return &amp;lt;Router /&amp;gt;;
}
export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라우터 import하는 과정에서 경로가 잘못 되어 있어서 오류가 났었따...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의하자!&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1678169237066&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//index.js
// 원래부터 있던 코드
import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import App from &quot;./App&quot;;
import reportWebVitals from &quot;./reportWebVitals&quot;;

// 우리가 추가할 코드
import store from &quot;./redux/config/configStore&quot;;
import { Provider } from &quot;react-redux&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(

	//App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
  &amp;lt;Provider store={store}&amp;gt; 
    &amp;lt;App /&amp;gt;
  &amp;lt;/Provider&amp;gt;
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토어 사용을 위해 추가로 작성해주어야 한당.&lt;/p&gt;
&lt;pre id=&quot;code_1678167587285&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//configStore

import { legacy_createStore as createStore } from &quot;redux&quot;; //스토어를 만들어 주는 api
import { combineReducers } from &quot;redux&quot;; // 리듀서들을 하나로 묶는 역할
import todos from &quot;../modules/todos&quot;; // 모듈을 스토어에 연결하려면 임포트해야 한다!

const rootReducer = combineReducers({ todos });
const store = createStore(rootReducer);

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토어에 기본적으로 적어주는 것들!!!! todos는 당연히 바뀌는 값이다!!!!&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;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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일 완벽하게 마무리 해야겠다!!!&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>깃</category>
      <category>라우터돔</category>
      <category>리덕스</category>
      <category>리액트</category>
      <category>명령어</category>
      <category>투두리스트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/163</guid>
      <comments>https://innocentcodingstory.tistory.com/163#entry163comment</comments>
      <pubDate>Tue, 7 Mar 2023 21:55:43 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.06) 항해 29일차</title>
      <link>https://innocentcodingstory.tistory.com/162</link>
      <description>&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;/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;하루종일 공부하고 정리한 내용이 그대로 모래가...........&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;민망하셨을텐데ㅠㅠㅠㅠ 난 그런거도 안보이고 속상한 맘이 더 컸다...힝 ㅠㅠ&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;평소보다 피곤하진 않다!&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;내일두 완전 열심히 해야지!!!!!&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;파일은 이제부터라도 잘 관리하면 되는거니까!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내일부터는 다시 밝은 모습으로 과제를 해결해봐야겠다!!!!&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/162</guid>
      <comments>https://innocentcodingstory.tistory.com/162#entry162comment</comments>
      <pubDate>Tue, 7 Mar 2023 02:10:53 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.05) 항해 4주차 회고</title>
      <link>https://innocentcodingstory.tistory.com/161</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;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;리액트 훅과 리덕스와 라우터 돔을 공부 한 후에 과제를 해야겠다.&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;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/161</guid>
      <comments>https://innocentcodingstory.tistory.com/161#entry161comment</comments>
      <pubDate>Sun, 5 Mar 2023 21:40:06 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.04) 항해 27일차 (2-React Router Dom)</title>
      <link>https://innocentcodingstory.tistory.com/160</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;라우터 돔은 생각보단 괜찮았는데 손에 익지는 않아서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;내일 리덕스와 함께 해봐야겠다는 생각을 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;일요일이지만 쉴 수 없다.......&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이해 못한 나를 탓해야지...어쩔 수 없지!!!!&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) react-router-dom&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;페이지를 구현할 수 있게 해주는 패키지&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677920659989&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//아래의 명령어로 설치한다
yarn add react-router-dom&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;react-redux처럼 react-router-dom도 폴더를 생성해 주어야 한다.&lt;/li&gt;
&lt;li&gt;pages폴더&amp;nbsp;생성 -&amp;gt; 안에 필요한 여러 페이지 생성 ex)&amp;nbsp;Home.jsx&amp;nbsp;,&amp;nbsp;About.jsx ...&lt;/li&gt;
&lt;li&gt;shared 폴더&amp;nbsp;생성 -&amp;gt; 안에&amp;nbsp;Router.js&amp;nbsp;생성 -&amp;gt; router 설정 코드 작성&lt;/li&gt;
&lt;li&gt;App.js&amp;nbsp;에서 import도 해야한다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Routes안에 있는 Route에는&amp;nbsp;react-router-dom에서 지원하는 props들이&amp;nbsp;있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;path&lt;/span&gt;는 &lt;span style=&quot;color: #ef5369;&quot;&gt;원하는 &quot;주소&quot;&lt;/span&gt;를 넣어준다.&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;element&lt;/span&gt;는 &lt;span style=&quot;color: #ef5369;&quot;&gt;해당 주소로 이동했을 때 보여주고자 하는 page 컴포넌트&lt;/span&gt;를 작성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677920794312&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Router.js
import React from &quot;react&quot;;
import { BrowserRouter, Route, Routes } from &quot;react-router-dom&quot;;
import Home from &quot;../pages/Home&quot;;
import About from &quot;../pages/About&quot;;
import Contact from &quot;../pages/Contact&quot;;
import Works from &quot;../pages/Works&quot;;

const Router = () =&amp;gt; {
  return (
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path=&quot;/&quot; element={&amp;lt;Home /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;about&quot; element={&amp;lt;About /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;contact&quot; element={&amp;lt;Contact /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;works&quot; element={&amp;lt;Works /&amp;gt;} /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
};

export default Router;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Router.js 파일을 App.js에 import 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Router.js를 다른 곳도 아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;App 컴포넌트에 넣어주는 이유는,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 우리가 만든 프로젝트에서 가장 최상위에 존재하는 컴포넌트가 App.js 이기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 ,우리가 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;어떤 컴포넌트를 화면에 띄우던 항상 App.js를 거쳐야만 한다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 path 별로 분기가 되는 Router.js 를 App.js에 위치시키고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 서비스를 이용하는 모든 사용자가 항상 App.js &amp;rarr; Router.js 거치도록 코드를 구현해주는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1677920827511&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.js
import React from &quot;react&quot;;
import Router from &quot;./shared/Router&quot;;

function App() {
  return &amp;lt;Router /&amp;gt;;
}

export default App;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) react-router-dom Hooks&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① useNavigate&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;버튼의 클릭 이벤트 핸들러에 코드를 작성하면 버튼을 클릭했을 때 우리가 보내고자 하는 path로 페이지를 이동시킬 수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;꼭 버튼이 아니더라도, 컴포넌트의 클릭 이벤트 핸들러를 통해서 활용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;navigate 를 생성&lt;/span&gt;하고, &lt;span style=&quot;color: #ef5369;&quot;&gt;navigate(&amp;rsquo;보내고자 하는 url&amp;rsquo;) 을 통해 페이지를 이동&lt;/span&gt; 시킬 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677921069983&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/pages/home.js
import { useNavigate } from &quot;react-router-dom&quot;;

const Home = () =&amp;gt; {
  const navigate = useNavigate();

  return (
    &amp;lt;button
      onClick={() =&amp;gt; {
        navigate(&quot;/works&quot;);
      }}
    &amp;gt;
      works로 이동
    &amp;lt;/button&amp;gt;
  );
};

export default Home;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② Link&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지를 이동시키고자 할때 useNavigate 또는 Link를 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Link 는 훅이 아니지만, 꼭 알아야 할 API이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;Link 는 html 태그중에 a 태그의 기능을 대체하는 API 이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;만약 JSX에서 a 태그를 사용해야 한다면, 반드시 Link 를 사용해서 구현해야 한다.&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;a태그 말고 Link를 사용해야 하는 이유&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;a 태그를 사용하면 페이지를 이동하면서 브라우저가 새로고침(refresh)된다.&lt;/li&gt;
&lt;li&gt;브라우저가 새로고침 되면 모든 컴포넌트가 다시 렌더링되야 하고,&lt;/li&gt;
&lt;li&gt;리덕스나 useState를 통해 메모리상에 구축해놓은 모든 상태값이 초기화 된다.&lt;/li&gt;
&lt;li&gt;이것은 곧 성능에 악역향을 줄 수 있고, 불필요한 움직임이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1677921176788&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { Link, useLocation } from 'react-router-dom';

const Works = () =&amp;gt; {
  const location = useLocation();
  console.log('location :&amp;gt;&amp;gt; ', location);
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;{`현재 페이지 : ${location.pathname.slice(1)}`}&amp;lt;/div&amp;gt;
      &amp;lt;Link to=&quot;/contact&quot;&amp;gt;contact 페이지로 이동하기&amp;lt;/Link&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Works;&lt;/code&gt;&lt;/pre&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;3) Dynamic route 기법과 useParam hook&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① Dynamic Route란?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;동적 라우팅이라고도 말하고, path에 유동적인 값을 넣어서&lt;span style=&quot;color: #ef5369;&quot;&gt; 특정 페이지로 이동&lt;/span&gt;하게끔 구현하는 방법을 말한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;react-router-dom에서 지원하는 Dynamic Routes 기능을 이용해서 간결하게 동적으로 변하는 페이지를 처리할 수 있다.&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;color: #333333;&quot;&gt;Works 페이지에 여러개의 Work가 있고, 그것을 클릭했을 때 각각의 상세페이지로 이동하게끔 구현해봅시다. 일단 Work 라는 페이지가 먼저 있어야겠죠? Work 컴포넌트를 추가해주세요.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677921637257&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/pages/Works.js

import React from &quot;react&quot;;

const Works = () =&amp;gt; {
  return &amp;lt;div&amp;gt;Works&amp;lt;/div&amp;gt;;
};

export default Work;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677921673302&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 { BrowserRouter, Route, Routes } from &quot;react-router-dom&quot;;
import Home from &quot;../pages/Home&quot;;
import Works from &quot;../pages/Works&quot;;

const Router = () =&amp;gt; {
  return (
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path=&quot;/&quot; element={&amp;lt;Home /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;works/:id&quot; element={&amp;lt;Works /&amp;gt;} /&amp;gt; //추가한 코드
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
};

export default Router;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이전과는 다르게&lt;span style=&quot;color: #006dd7;&quot;&gt; path에 works/:id&lt;/span&gt; 라고 path가 들어갑니다. :id 라는 것이 바로 동적인 값을 받겠다라는 의미입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그래서 works/1 로 이동해도 &amp;lt;Work /&amp;gt; 로 이동하고, works/2, works/3 &amp;hellip;. works/100 모두 &amp;lt;Work /&amp;gt; 로 이동하게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그리고 &lt;span style=&quot;color: #ef5369;&quot;&gt;:id 는 useParams 훅에서 조회할 수 있는 값&lt;/span&gt;이 됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;② useParams&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Dynamic Routes를 사용하면 element에 설정된 같은 컴포넌트를 렌더링하게 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 설정한 예제 코드에서도 Work 페이지 컴포넌트를 모두 동일하게 렌더링하겠죠? &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;하지만 &lt;span style=&quot;color: #ef5369;&quot;&gt;useParams를 이용하면 같은 컴포넌트를 렌더링하더라도 각각의 고유한 id 값을 조회&lt;/span&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아래 코드를 추가해볼까요? useParams이라는 훅을 사용해봅시다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useParams 은 path의 있는 id 값을 조회할 수 있게 해주는 훅 입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그래서 만약에 우리가 works/1로 이동하면 1 이라는 값을 주고, works/100으로 이동하면 100 이라는 값을 사용할 수 있게 해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677921783250&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/pages/Work.js

import React from 'react';
import { useParams } from 'react-router-dom';

const data = [
  { id: 1, todo: '리액트 배우기' },
  { id: 2, todo: '노드 배우기' },
  { id: 3, todo: '자바스크립트 배우기' },
];

function Work() {
  const param = useParams();

  const work = data.find((work) =&amp;gt; work.id === parseInt(param.id));

  return &amp;lt;div&amp;gt;{work.todo}&amp;lt;/div&amp;gt;;
}

export default Work;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useParams 훅을 이용해서 불러온 parameter를 가져온다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Router.js에서 설정한 Workd/:id에서 id로 parameter를 설정해놨기 때문에 하위페이지로 넘어왔을때,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이게 무슨 페이지인지 useParams를 이용해서 확인할 수 있게 된 것이다.&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;&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>TIL(Today I Learned)</category>
      <category>Dynamic Route</category>
      <category>LINK</category>
      <category>react-router-dom</category>
      <category>useNavigate</category>
      <category>useParams</category>
      <category>라우터 돔</category>
      <category>라우터 돔 훅</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/160</guid>
      <comments>https://innocentcodingstory.tistory.com/160#entry160comment</comments>
      <pubDate>Sat, 4 Mar 2023 23:00:38 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.04) 항해 27일차 (1-Redux)</title>
      <link>https://innocentcodingstory.tistory.com/159</link>
      <description>&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;/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;다시 보니 조금은 이해가 되긴 했지만&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) 리덕스란&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리덕스란&lt;span style=&quot;color: #ef5369;&quot;&gt; &amp;ldquo;중앙 state 관리소&amp;rdquo;를 사용할 수 있게 도와주는 패키지(라이브러리)이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프론트엔드 개발자들은 &amp;ldquo;리덕스&amp;rdquo;를 전역 상태관리 라이브러리라고 많이 표현한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전역 상태, 즉 Global State를 의미하고 그것을 관리하게 도와주는 라이브러리 (패키지) 이기 때문이다.&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;① useState의 불편함&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트에서 컴포넌트로 State를 보내기 위해서는 반드시 부-모 관계가 되어야 한다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;조부모 컴포넌트에서 손자 컴포넌트로 값을 보내고자 할 때도 반드시 부모 컴포넌트를 거쳐야만 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자식 컴포넌트에서 부모 컴포넌트로 값을 보낼 수 없다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이러한 불편함을 개선하는 그 새로운 도구가 바로 리덕스다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 &lt;span style=&quot;color: #006dd7;&quot;&gt;리덕스를 사용&lt;/span&gt;하면 State를 공유하고자 할때 부-모 관계가 아니어도 되고, 중간에 의미 없이 컴포넌트를 거치지 않아도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자식 컴포넌트에서 만든 State를 부모 컴포넌트에서도 사용할 수 있게 된다.&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;span style=&quot;color: #333333;&quot;&gt;②&amp;nbsp; Global state와 Local state&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;Local state (지역상태)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트에서 useState를 이용해서 생성한 state 다. (좁은 범위 안에서 생성된 State)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Global state (전역상태)&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Global state는 컴포넌트에서 생성되지 않는다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;중앙화된 특별한 곳에서 State들이 생성된다. (중앙 state 관리소)&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;앞으로 State를 Global state와 Local state라는 것을 따로 구분지어서 표현할 것이다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) 리덕스 설정&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1677892957388&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add redux react-redux&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지를 설치하고, 폴더를 생성한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;143&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blIlSP/btr1Y8aFb6s/O1WiAVMfHOCSMWktlqn89K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blIlSP/btr1Y8aFb6s/O1WiAVMfHOCSMWktlqn89K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blIlSP/btr1Y8aFb6s/O1WiAVMfHOCSMWktlqn89K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblIlSP%2Fbtr1Y8aFb6s%2FO1WiAVMfHOCSMWktlqn89K%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;143&quot; height=&quot;113&quot; data-origin-width=&quot;143&quot; data-origin-height=&quot;113&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;redux&lt;/b&gt; : 리덕스와 관련된 코드를 모두 모아 놓을 폴더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;config&lt;/b&gt; : 리덕스 설정과 관련된 파일들을 놓을 폴더&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;configStore&lt;/b&gt; : &amp;ldquo;중앙 state 관리소&quot;인 Store를 만드는 설정 코드들이 있는 파일&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;modules&lt;/b&gt; : 만들 State들의 그룹&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1677893102706&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/configStore.js
import { createStore } from &quot;redux&quot;;  //리덕스의 가장 핵심이 되는 스토어를 만드는 메소드(함수)
import { combineReducers } from &quot;redux&quot;;//여러 개의 독립적인 reducer의 반환 값을 하나의 상태 객체로 만들어준다

const rootReducer = combineReducers({}); 
const store = createStore(rootReducer); 

export default store; 


//index.js
// 원래부터 있던 코드
import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import App from &quot;./App&quot;;
import reportWebVitals from &quot;./reportWebVitals&quot;;

// 우리가 추가할 코드
import store from &quot;./redux/config/configStore&quot;;
import { Provider } from &quot;react-redux&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(

	//App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
  &amp;lt;Provider store={store}&amp;gt; 
    &amp;lt;App /&amp;gt;
  &amp;lt;/Provider&amp;gt;
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) 카운터 프로그램 만들며 설정 이해하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;① 모듈 만들기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677894252081&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/modules/counter.js

// 초기 상태값
const initialState = {
  number: 0,
};

// 리듀서
const counter = (state = initialState, action) =&amp;gt; {
  switch (action.type) {
    default:
      return state;
  }
};

// 모듈파일에서는 리듀서를 export default 한다.
export default counter;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위 코드에서 만든 State의 초기값은 { } (객체)이고, 그 안에 number라는 변수에 초기값 0을 할당해 준 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; 초기값&lt;/span&gt;은 꼭 &lt;span style=&quot;color: #ef5369;&quot;&gt;객체&lt;/span&gt;가 아니고, &lt;span style=&quot;color: #ef5369;&quot;&gt;배열, 원시데이터, 여러 개의 변수를 가진 &lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;객체&lt;/span&gt;도&amp;nbsp;&lt;/span&gt;넣어줄 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;리듀서란, 변화를 일으키는 함수&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;color: #333333;&quot;&gt;리듀서의 인자에 보면 (state = intialState, action)이라고 되어 있는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리듀서 인자 첫 번째 자리에서는 state를, 두 번째 자리에서는 action이라는 것을 꺼내서 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;state = intialState처럼 state에 initialState를 할당해줘야 한다.&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;span style=&quot;color: #333333;&quot;&gt;② 카운터 모듈을 스토어에 연결하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;모듈파일에서 초기 상태값과 리듀서를 작성했고, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이제 만든 모듈을 스토어에 연결시켜야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아직까진 모듈과 스토어가 각각 따로 분리되어 있는 상태이기 때문에 만든 State를 스토어에서 꺼낼 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;configStore.js 파일에 모듈을 연결시켜주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677894330110&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/config/configStore.js


// 원래 있던 코드
import { createStore } from &quot;redux&quot;;
import { combineReducers } from &quot;redux&quot;;

// 새롭게 추가한 부분
import counter from &quot;../modules/counter&quot;;

const rootReducer = combineReducers({
  counter: counter, // &amp;lt;-- 새롭게 추가한 부분
});
const store = createStore(rootReducer);

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ 스토어와 모듈 연결 확인하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;useSelector = 스토어 조회&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 생성한 모듈을 스토어에 잘 연결했는지 확인하는 방법은 컴포넌트에서 스토어를 직접 조회하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 컴포넌트에서 리덕스 스토어를 조회하고자 할 때는 &lt;b&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;useSelector라는 &amp;lsquo;react-redux&amp;rsquo;의 훅을 사용해야 한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677894395437&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//useSelector의 사용법

// 1. store에서 꺼낸 값을 할당 할 변수를 선언합니다.
const number = 

// 2. useSelector()를 변수에 할당해줍니다.
const number = useSelector() 

// 3. useSelector의 인자에 화살표 함수를 넣어줍니다.
const number = useSelector( ()=&amp;gt;{} )

// 4. 화살표 함수의 인자에서 값을 꺼내 return 합니다. 
// 우리가 useSelector를 처음 사용해보는 것이니, state가 어떤 것인지 콘솔로 확인해볼까요?
const number = useSelector((state) =&amp;gt; {
	console.log(state)
	return state
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 화살표 함수에서 꺼낸 state라는 인자는 현재 프로젝트에 존재하는 모든 리덕스 모듈의 state 인 것이다.&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 style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;④ counter.js 모듈의 state 수정 기능 만들기 (+ 1 기능 구현해 보기)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;리덕스에서 값의 수정은 리듀서에서 일어난다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;counter.js 모듈에 있는 number에 +1을 하고 싶으면,&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;리듀서에게 보낼 number를 +1 하라는 &amp;ldquo;Action&amp;rdquo;을 만든다.&lt;/li&gt;
&lt;li&gt;Action을 보낸다.&lt;/li&gt;
&lt;li&gt;리듀서에서 Action을 받아 number +1을 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Action을 코드로 나타내면 객체로 만들어서 이것을 액션 객체 라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;액션 객체는 반드시 type이라는 key&lt;/span&gt;를 가져야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;액션 객체를 리듀서에게 보냈을 때 리듀서는 객체 안에서 type이라는 key를 보기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리덕스 모듈에 있는 state을 변경하기 위해서는 그에 해당하는 액션 객체를 모두 만들어줘야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❶ &lt;span style=&quot;color: #333333;&quot;&gt;액션 객체 보내기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;액션객체를 보내기 리듀서로 보내기 위해서는 &lt;span style=&quot;color: #006dd7;&quot;&gt;useDispatch라는 훅&lt;/span&gt;을 사용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;react-redux에서 import 해서 사용할 수 있으며, 우리가 만든 액션 객체를 리듀서로 보내주는 역할을 하는 훅이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useDispatch라는 훅을 사용하기 위해서는 컴포넌트 안에서 아래와 같이 먼저 코드를 작성해서&lt;span style=&quot;color: #ef5369;&quot;&gt; dispatch라는 변수를 생성&lt;/span&gt;해줘야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 생성한 dispatch는 사용할 때 ()를 붙여서 함수를 실행하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그리고 &lt;span style=&quot;color: #ef5369;&quot;&gt;dispatch를 사용할 때 ( ) 안에 액션객체&lt;/span&gt;를 넣어주면 된다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677898858304&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/App.js

import React from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;; // import

const App = () =&amp;gt; {
  const dispatch = useDispatch(); // dispatch 생성

  const number = useSelector((state) =&amp;gt; state.counter.number);

  return (
    &amp;lt;div&amp;gt;
      {number}
      &amp;lt;button
        onClick={() =&amp;gt; {
          dispatch({ type: &quot;PLUS_ONE&quot; }); 
          //마우스를 클릭했을 때 dispatch가 실행되고, ()안에 있는 액션객체가 리듀서로 전달된다.
        }}
      &amp;gt;
        + 1
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❷ &lt;span data-token-index=&quot;0&quot;&gt;액션객체 명령대로 리듀서가 state값을 변경하는 코드 구현하기&lt;/span&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;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴포넌트로부터 dispatch를 통해 액션객체를 전달받는다.&lt;/li&gt;
&lt;li&gt;action 안에 있는 type을 스위치문을 통해 하나씩 검사해서, 일치하는 case를 찾는다.&lt;/li&gt;
&lt;li&gt;type과 case가 일치하는 경우에, 해당 코드가 실행되고 새로운 state를 반환(return) 한다.&lt;/li&gt;
&lt;li&gt;리듀서가 새로운 state를 반환하면, 그게 새로운 모듈의 state가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1677898961705&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/modules/counter.js

// 초기 상태값
const initialState = {
  number: 0,
};

// 리듀서
const counter = (state = initialState, action) =&amp;gt; {
  console.log(action);
  switch (action.type) {
		// PLUS_ONE이라는 case를 추가한다.
		// 여기서 말하는 case란, action.type을 의미한다.
		// dispatch로부터 전달받은 action의 type이 &quot;PLUS_ONE&quot; 일 때
		// 아래 return 절이 실행된다. 
    case &quot;PLUS_ONE&quot;:
      return {
				// 기존 state에 있던 number에 +1을 더한다.
        number: state.number + 1,
      };

    default:
      return state;
  }
};

// 모듈파일에서는 리듀서를 export default 한다.
export default counter;&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;size18&quot;&gt;&lt;b&gt;⑤ Action Creator&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;만약에 우리가 액션객체의 value를 변경할 일이 생긴다면 코드에서 모두 찾아서 변경해주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 하면 오타가 날 수도 있고 번거롭기 때문에 ,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;액션객체를 한 곳에서 관리할 수 있도록 &amp;ldquo;함수&quot;와 액션 value를 상수로 만들 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677903700795&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/counter.js

const PLUS_ONE = &quot;PLUS_ONE&quot;; // value는 상수로 생성

// 액션객체를 반환하는 함수 생성
// export 가 붙는 이유는 plusOne()는 밖으로 나가서 사용될 예정이기 때문이다.
export const plusOne = () =&amp;gt; { 
  return {
    type: PLUS_ONE, // type에는 위에서 만든 상수로 사용 (vscode에서 자동완성 지원)
  };
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;value를 상수로 생성하고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dispatch() 안에 있던 액션객체를 import 한 Action Creator들로 변경한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677903742543&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/App.js

import React from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;

// 사용할 Action creator를 import 한다.
import { plusOne } from &quot;./redux/modules/counter&quot;;

const App = () =&amp;gt; {
  const dispatch = useDispatch();
  const number = useSelector((state) =&amp;gt; state.counter.number);

  return (
    &amp;lt;div&amp;gt;
      {number}
      &amp;lt;button
        onClick={() =&amp;gt; {
          dispatch(plusOne()); // 액션객체를 Action creator로 변경한다.
        }}
      &amp;gt;
        + 1
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❶ dispatch() 안에는 반드시 객체만 들어가야 한다고 알았지만, 함수가 들어갈 수 있는 이유!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;{type: &amp;ldquo;PLUS_ONE&amp;rdquo;} === plusOne()는 같은 값이다.&lt;/li&gt;
&lt;li&gt;함수를 실행한 것은 함수의 return 값과 같다.&lt;/li&gt;
&lt;li&gt;즉, const one = () =&amp;gt; {return 1; }로 함수를 만들었을 때 one() === 1이다.&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;span style=&quot;color: #333333;&quot;&gt;❷ Action creator를 사용해야 하는 이유&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;휴먼에러 (오타) 방지&lt;/li&gt;
&lt;li&gt;유지보수의 효율성 증가&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;코드 가독성 높임&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;⑥ payload&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;state를 변경할 때 리듀서에게 어떤 값을 같이 보내줘야 하는 경우,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt; payload를 액션객체에 같이 담아&lt;/span&gt; 보낼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677915701285&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/redux/modules/counter.js

// Action Value
const ADD_NUMBER = &quot;ADD_NUMBER&quot;;

// Action Creator
export const addNumber = (payload) =&amp;gt; {
  return {
    type: ADD_NUMBER,
    payload: payload,
  };
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;payload가 필요한 Action Creator에서는 함수를 선언할 때 매개변수 자리에 paylaod를 넣어줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Action Creator를 사용하는 컴포넌트에서 리듀서로 보내고자 하는 payload를 인자로 넣어줘야 하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677915590601&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리듀서

const counter = (state = initialState, action) =&amp;gt; {
  switch (action.type) {
    case ADD_NUMBER:
      return {
// state.number (기존의 nubmer)에 action.paylaod(유저가 더하길 원하는 값)을 더한다.
        number: state.number + action.payload,
      };
    default:
      return state;
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;u&gt;사용자가 컴포넌트에서 Action Creator로 payload를 담아 보내는 것은 액션객체에 담기고,&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;u&gt; 그렇게 담긴 것은 리듀서에서 action.payload에서 꺼내 사용해서 기존의 값에 더해줌으로써 기능을 구현하는 것이다. &lt;/u&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;&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>TIL(Today I Learned)</category>
      <category>action creator</category>
      <category>dispatch</category>
      <category>Payload</category>
      <category>Redux</category>
      <category>useDispatch</category>
      <category>useSelector</category>
      <category>useState</category>
      <category>리덕스</category>
      <category>리듀서</category>
      <category>액션객체</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/159</guid>
      <comments>https://innocentcodingstory.tistory.com/159#entry159comment</comments>
      <pubDate>Sat, 4 Mar 2023 22:58:31 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.03) 항해 26일차 (3-React Hooks 최적화)</title>
      <link>https://innocentcodingstory.tistory.com/158</link>
      <description>&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;/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;span&gt;&amp;nbsp;&lt;/span&gt;React Hooks - 최적화&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;①&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-token-index=&quot;0&quot;&gt;리-렌더링의 발생 조건과 최적화&lt;/span&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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;컴포넌트에서 state가 바뀌었을 때&lt;/li&gt;
&lt;li&gt;컴포넌트가 내려받은 props가 변경되었을 때&lt;/li&gt;
&lt;li&gt;부모 컴포넌트가 리-렌더링 된 경우 자식 컴포넌트는 모두&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yLacu/btr1MnGSRZe/TRkZVJjzokzScdsdRJ3mV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yLacu/btr1MnGSRZe/TRkZVJjzokzScdsdRJ3mV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yLacu/btr1MnGSRZe/TRkZVJjzokzScdsdRJ3mV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyLacu%2Fbtr1MnGSRZe%2FTRkZVJjzokzScdsdRJ3mV1%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;300&quot; height=&quot;473&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;473&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;❷ 최적화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서 &lt;span style=&quot;color: #ef5369;&quot;&gt;리렌더링이 자주 일어난다는 것은 좋지 않다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비용이 발생하는 것은 최대한 줄여야 하는 작업을 최적화(Optimization)이라고 한다.&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;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;memo(React.memo) : 컴포넌트를 캐싱&lt;/li&gt;
&lt;li&gt;useCallback : 함수를 캐싱&lt;/li&gt;
&lt;li&gt;useMemo : 값을 캐싱&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;size18&quot;&gt;&lt;b&gt;② React.memo&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;부모 컴포넌트가 리렌더링 되면 자식컴포넌트는 모두 리렌더링&lt;/span&gt; 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식 컴포넌트의 입장에서는 변경사항이 없지만 &lt;span style=&quot;color: #ef5369;&quot;&gt;불필요하게 렌더링&lt;/span&gt; 될 수 있는데, 이 부분을 돕는 도구가 바로 React.memo이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;React.memo&lt;/span&gt;를 이용해서 &lt;span style=&quot;color: #ef5369;&quot;&gt;컴포넌트를 메모리에 저장해두고 필요할 때 갖다 쓸 수 있다&lt;/span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 하면 부모 컴포넌트의 state의 변경으로 인해 &lt;span style=&quot;color: #ef5369;&quot;&gt;props가 변경이 일어나지 않는 한 컴포넌트는 리렌더링 되지 않는다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이것을 컴포넌트 memoization 이라고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677833441268&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default React.memo(컴포넌트이름);&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;size18&quot;&gt;&lt;b&gt;③ useCallback&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useCallback은 &lt;span style=&quot;color: #ef5369;&quot;&gt;인자로 들어오는 함수 자체를 기억&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;React.memo를 통해서 하위 컴포넌트를 메모이제이션을 했는데도 리렌더링이 되는 이유&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수형 컴포넌트&lt;/span&gt;를 사용하기 때문이고,&amp;nbsp; App.jsx가 &lt;span style=&quot;color: #ef5369;&quot;&gt;리렌더링 되면서 코드가 다시&lt;/span&gt; 만들어지기 때문이다.&lt;/li&gt;
&lt;li&gt;자바스크립트에서는 &lt;span style=&quot;color: #ef5369;&quot;&gt;함수도 객체의 한 종류&lt;/span&gt;이다.&lt;/li&gt;
&lt;li&gt;모양은 같더라도 다시 만들어지면 &lt;span style=&quot;color: #ef5369;&quot;&gt;그 주솟값이 달라지고&lt;/span&gt; 이에 따라 하위 컴포넌트는&lt;span style=&quot;color: #ef5369;&quot;&gt; props가 변경됐다고 인식&lt;/span&gt;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그렇기 때문에, 이 함수를 메모리 공간에 저장해놓고, &lt;span style=&quot;color: #ef5369;&quot;&gt;특정 조건이 아닌 경우엔 변경되지 않도록&lt;/span&gt; 해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677847289550&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 변경 전
const initCount = () =&amp;gt; {
  setCount(0);
};

// 변경 후
const initCount = useCallback(() =&amp;gt; {
  setCount(0);
}, []);&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;④ useMemo&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;동일한 값을 반환하는 함수&lt;/span&gt;를 계속 호출해야 하면 &lt;span style=&quot;color: #ef5369;&quot;&gt;필요없는 렌더링&lt;/span&gt;을 하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 맨 처음 해당 값을 반환할 때 그 값을 &lt;span style=&quot;color: #ef5369;&quot;&gt;특별한 곳(메모리)에 저장&lt;/span&gt;하다면 필요할 때 마다 다시 함수를 호출해서 계산하는게 아니라,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이미 &lt;span style=&quot;color: #ef5369;&quot;&gt;저장한 값을 단순히 꺼내와서 쓸 수 있다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677847572707&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// as-is
const value = 반환할_함수();

// to-be
const value = useMemo(()=&amp;gt; {
	return 반환할_함수()
}, [dependencyArray]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;dependency Array의 값이 변경 될 때만 반환할 함수()가 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그 외의 경우에는 memoization 해놨던 값을 가져오기만 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677847719944&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useEffect, useState } from &quot;react&quot;;

function ObjectComponent() {
  const [isAlive, setIsAlive] = useState(true);
  const [uselessCount, setUselessCount] = useState(0);

  const me = {
    isAlive: isAlive ? &quot;생존&quot; : &quot;사망&quot;,
  };

  useEffect(() =&amp;gt; {
    console.log(&quot;생존여부가 바뀔 때만 호출해주세요!&quot;);
  }, [me]);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;button
          onClick={() =&amp;gt; {
            setIsAlive(!isAlive);
          }}
        &amp;gt;
          누르면 살았다가 죽었다가 해요
        &amp;lt;/button&amp;gt;
        &amp;lt;br /&amp;gt;
        생존여부 : {me.isAlive}
      &amp;lt;/div&amp;gt;
      {uselessCount}
      &amp;lt;br /&amp;gt;
      &amp;lt;button
        onClick={() =&amp;gt; {
          setUselessCount(uselessCount + 1);
        }}
      &amp;gt;
        누르면 숫자가 올라가요
      &amp;lt;/button&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default ObjectComponent;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useEffect hook을 이용해서 me의 정보가 바뀌었을 때만 발동되게끔 dependency array를 넣어놨지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;엉뚱하게도 count를 증가하는button을 눌러보면 계속 log가 찍힌다.&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;span style=&quot;color: #333333;&quot;&gt;이 부분은 &lt;span style=&quot;color: #ef5369;&quot;&gt;불변성&lt;/span&gt;과 관련이 깊다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위 예제에서 버튼이 선택돼서 uselessCount state가 바뀌게 되면 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;rarr; 리렌더링이 되고,&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 컴포넌트 함수가 새로 호출된다 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;rarr; me 객체도 다시 할당한다(이 때, &lt;span style=&quot;color: #ef5369;&quot;&gt;다른 메모리 주소값&lt;/span&gt;을 할당받는다) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;rarr; useEffect의 dependency array에 의해 me 객체가 바뀌었는지 확인해봐야 하는데, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이전 것과 모양은 같은데 주소가 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;rarr; 리액트 입장에서는 me가 바뀌었구나 인식하고 useEffect 내부 로직이 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677847789319&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const me = useMemo(() =&amp;gt; {
  return {
    name: &quot;Ted Chang&quot;,
    age: 21,
    isAlive: isAlive ? &quot;생존&quot; : &quot;사망&quot;,
  };
}, [isAlive]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useMemo()만 이렇게 써주면, uselessCount가 아무리 증가돼도 영향이 없게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;useMemo를 남발하게 되면 별도의 메모리 확보를 너무나 많이 하게 되기 때문에 오히려 성능이 악화될 수 있다.&lt;/li&gt;
&lt;li&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/158</guid>
      <comments>https://innocentcodingstory.tistory.com/158#entry158comment</comments>
      <pubDate>Fri, 3 Mar 2023 22:54:42 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.03) 항해 26일차 (2-React Hooks)</title>
      <link>https://innocentcodingstory.tistory.com/157</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트 훅.......&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이게 매우 중요하다는 것도 알고, 어려운 내용이고 공부할 양이 많다고 다들 말해주셨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;근데 주어진 자료를 보고 자료수집을 더 해보아도,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어떻게 사용하는 것인지, 어떤 상황에서 사용하는지 감은 잡히지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;막상 코드로 작성해보려니 코드적인 상황이 떠오르지 않아서 좀 멘탈이 터졌다...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;많이 사용해보고 적응해야 하는 건 알지만, 아직은 많이 사용해볼 만한 상황을 못 찾았다........&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1) Reat Hooks&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;① useState&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;setState를 사용하는 방식에는 우리가 알고 있는 방식이 아닌&amp;nbsp;또 다른 방식인&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수형 업데이트 방식&lt;/span&gt;이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 업데이트 방식은 버튼을 클릭했을 때 setNumber가 각각 실행되는 것이 아니라,&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;배치(batch)로 처리&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;우리가 onClick을 했을 때 setNumber 라는 명령을 세번 내리지만, 리액트는 그 명령을 하나로 모아 한번만 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 setNumber을 3번 명령하던, 100번 명령하던 1번만 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수형 업데이트 방식&lt;/span&gt;은&amp;nbsp;3번을 동시에 명령을 내리면,&amp;nbsp;그 &lt;span style=&quot;color: #ef5369;&quot;&gt;명령을 모아 순차적으로 각각 1번씩 실행&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0에 1더하고, 그 다음 1에 1을 더하고, 2에 1을 더해서 3이 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState가 이렇게 동작하는 이유는,&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: #ef5369;&quot;&gt;리액트의 성능을 위해 한꺼번에 state를 업데이트&lt;/span&gt; 하기에 나타나는 결과이다.&lt;/p&gt;
&lt;pre id=&quot;code_1677815903223&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const App = () =&amp;gt; {
  const [number, setNumber] = useState(0);
  return (
    &amp;lt;div&amp;gt;
			// 일반적인 방법 {/* 버튼을 누르면 1씩 플러스된다. */}
      &amp;lt;div&amp;gt;{number}&amp;lt;/div&amp;gt; 
      &amp;lt;button
        onClick={() =&amp;gt; {
          setNumber(number + 1); // 첫번째 줄 
          setNumber(number + 1); // 두번쨰 줄
          setNumber(number + 1); // 세번째 줄
        }}
      &amp;gt;
        버튼
      &amp;lt;/button&amp;gt;
			//함수형 업데이트 방법 {/* 버튼을 누르면 3씩 플러스 된다. */}
      &amp;lt;div&amp;gt;{number}&amp;lt;/div&amp;gt;
      &amp;lt;button
        onClick={() =&amp;gt; {
          setNumber((previousState) =&amp;gt; previousState + 1);
          setNumber((previousState) =&amp;gt; previousState + 1);
          setNumber((previousState) =&amp;gt; previousState + 1);
        }}
      &amp;gt;
        버튼
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;
```&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;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;②&amp;nbsp;useEffect&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;useEffect&lt;/span&gt;는 리액트 &lt;span style=&quot;color: #ef5369;&quot;&gt;컴포넌트가 렌더링될 때마다 특정 작업을 수행&lt;/span&gt;하도록 설정할 수 있는 Hook이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어떤 컴포넌트가 화면에 보여졌을 때(혹은 사라졌을 때) 내가 무언가를 실행하고&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 싶다면 useEffect를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677816202243&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//useState와 마찬가지로 React에서 제공하는 훅 (기능) 이므로,
import React, { useEffect } from &quot;react&quot;; 
//로 import 해서 사용해야한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useEffect는 &lt;span style=&quot;color: #ef5369;&quot;&gt;useEffect가 속한 컴포넌트가 화면에 렌더링&lt;/span&gt; 될 때 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기에 &lt;span style=&quot;color: #8a3db6;&quot;&gt;원치 않는 상황&lt;/span&gt;에서도 렌더링에 의해 실행되는 경우도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우에는 &lt;span style=&quot;color: #8a3db6;&quot;&gt;의존성 배열을 사용&lt;/span&gt;하여 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;❶ 의존성 배열(dependency array)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&quot;&lt;span style=&quot;color: #ef5369;&quot;&gt;이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행할게&lt;/span&gt;&quot;&amp;nbsp;라는 것 이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677815903225&quot; class=&quot;stylus&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// useEffect의 두번째 인자가 의존성 배열이 들어가는 곳 입니다.
useEffect(()=&amp;gt;{
	// 실행하고 싶은 함수
}, [의존성배열])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-token-index=&quot;1&quot;&gt;어떤 함수를 컴포넌트가 &lt;span style=&quot;color: #ef5369;&quot;&gt;렌더링 될 때 단 한번&lt;/span&gt;만 실행하고 싶으면 &lt;span style=&quot;color: #ef5369;&quot;&gt;의존성 배열을 [ ] 빈 상태로&lt;/span&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;size18&quot;&gt;&lt;b&gt;➂ useRef&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;DOM 요소에 접근&lt;/span&gt;할 수 있도록 하는 React Hook 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서도 DOM을 선택해야 할 상황이 생길 때, useRef hook을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt; ex) 화면이 렌더링 되자마자 특정 input 태그가 focusing이 돼야 하는 경우 등&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1677818523240&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const ref = useRef(&quot;초기값&quot;);
console.log(&quot;ref 1&quot;, ref);

ref.current = &quot;바꾼 값&quot;;
console.log(&quot;ref 1&quot;, ref);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;다만, 이렇게 설정된 ref 값은 컴포넌트가 계속해서 렌더링 되어도 &lt;span style=&quot;color: #ef5369;&quot;&gt;unmount 전까지 값을 유지&lt;/span&gt;한다는 것을 주의해야한다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 특징 때문에 useRef는 다음 2가지 용도로 사용된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;저장공간
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;state&lt;/span&gt;와 비슷한 역할을 한다. (다만 state는 변화가 일어나면 다시 렌더링이 일어나서 &lt;span style=&quot;color: #009a87;&quot;&gt;내부 변수들은 초기화&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;ref&lt;/span&gt;에 저장한 값은 렌더링을 일으키지 않는다. (ref의 값 변화가 일어나도 내부 변수들이 &lt;span style=&quot;color: #006dd7;&quot;&gt;초기화 X&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;state&lt;/b&gt;는 &lt;u&gt;리렌더링이 꼭 필요한 값&lt;/u&gt;을 다룰 때 쓰면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;ref&lt;/b&gt;는 &lt;u&gt;리렌더링을 발생시키지 않는 값&lt;/u&gt;을 저장할 때 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DOM
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;렌더링 되자마자 특정 input이 focusing 돼야 한다면 useRef를 사용한다.&lt;/li&gt;
&lt;/ul&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;size18&quot;&gt;&lt;b&gt;④ &lt;span data-token-index=&quot;0&quot;&gt;useContext&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props를 하&lt;span style=&quot;color: #333333;&quot;&gt;여 GrandFather 컴포넌트 &amp;gt; Father 컴포넌트 &amp;gt; Child 컴포넌트로 name을 전달해준다하면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Father 컴포넌트는 중간다리 역할을 하게 된다. 근데 만약, &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;Father 컴포넌트가 100개가 넘는다면&lt;/span&gt;?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;굉장히 비효율적&lt;/span&gt;이다. 이 비효율적인 방법을 대신하도록 &lt;span style=&quot;color: #006dd7;&quot;&gt;useContext&lt;/span&gt;를 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1677820751899&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//context &amp;gt; FamilyContext.js
import { createContext } from &quot;react&quot;;

// 여기서 null은 createContext의 기본값이다.
export const FamilyContext = createContext(null);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;context 를 생성하고,&lt;/p&gt;
&lt;pre id=&quot;code_1677820952173&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 Father from &quot;./Father&quot;;
import { FamilyContext } from &quot;../context/FamilyContext&quot;;

function GrandFather() {
  const name=&quot;olaf&quot;;

  return (
    &amp;lt;FamilyContext.Provider value={{ name }}&amp;gt; //Provider란 제공자
      &amp;lt;Father /&amp;gt; //context에서 전해주기에 props가 필요없다.
    &amp;lt;/FamilyContext.Provider&amp;gt;
  );
}

export default GrandFather;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;context에서 전해줄 것이기 때문에 &lt;span style=&quot;color: #ef5369;&quot;&gt;더 이상 props가 필요없다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기에&amp;nbsp; FamilyContext.Provider로 전해주고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props를 받던 Father 컴포넌트에서도 Child에게 props를 줄 필요가 없다.&lt;/p&gt;
&lt;pre id=&quot;code_1677821234428&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useContext } from &quot;react&quot;;
import { FamilyContext } from &quot;../context/FamilyContext&quot;; //연결

function Child({ name }) {
  const data = useContext(FamilyContext); //적용

  return (
    &amp;lt;div&amp;gt;
      이름은 &amp;lt;span style={stressedWord}&amp;gt;{data.name}&amp;lt;/span&amp;gt;랍니다.
      //props로 내려준 값이 아니라 context를 이용해서 값을 받아옴.
    &amp;lt;/div&amp;gt;
  );
}

export default Child;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주의할 점&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;useContext를 사용할 때, Provider에서 제공한 value가 달라진다면,&lt;/li&gt;
&lt;li&gt;useContext를 사용하고 있는 &lt;span style=&quot;color: #ef5369;&quot;&gt;모든 컴포넌트가 리렌더링&lt;/span&gt; 된다.&lt;/li&gt;
&lt;li&gt;value 부분을 항상 신경써야 하고, 그 대안으로 메모이제이션이 있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>dependency array</category>
      <category>Reat Hooks</category>
      <category>useContext</category>
      <category>useEffect</category>
      <category>useRef</category>
      <category>useState</category>
      <category>리렌더링</category>
      <category>배치</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/157</guid>
      <comments>https://innocentcodingstory.tistory.com/157#entry157comment</comments>
      <pubDate>Fri, 3 Mar 2023 22:54:29 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.03) 항해 26일차 (1-CSS-in-JS,전역스타일링)</title>
      <link>https://innocentcodingstory.tistory.com/156</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;styled-components 자체는 크게 어렵지 않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;문법자체도 달라지는게 없었기에 수월하게 할 수 있었지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;새로 배운 개념이기에 정리를 해봤다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1) CSS-in-JS&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;CSS-in-JS방식이란, 단어 그대로 &lt;span style=&quot;color: #ef5369;&quot;&gt;자바스크립트 코드로 CSS 코드를 작성하여 컴포넌트를 꾸미는 방식&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 순수한 CSS코드를 우리가 아니라, 자바스크립트를 이용해서 CSS코드를 만들어내는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; CSS-in-JS 방식을 사용하기 위해&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;u&gt;플러그인 설치 후, 터미널에서 styled-components를 설치&lt;/u&gt;해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677808344862&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 터미널에서 아래 명령어로 설치
yarn add styled-components&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;① styled-components 사용하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;classname을 사용해서 구현하기는 조금 까다로운 조건부 스타일링을 styled-components를 이용하면 간편하게 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-token-index=&quot;0&quot;&gt;CSS-in-JS 방식의 강점이 바로 스타일 코드를 JS코드 작성하듯이 스타일 코드를 작성할 수 있다는 점 이다.&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;span style=&quot;color: #333333;&quot;&gt; props는 부모 컴포넌트에서 자식 컴포넌트로 어떤 정보를 전달하고자 할 때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;styled-components도 말 그대로 컴포넌트&lt;/span&gt; 이기에,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;box에 prosp를 통해서 border color에 대한 정보를 전달해줄 수 있다.&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;span style=&quot;color: #333333;&quot;&gt;즉, props를 통해서 부모 컴포넌트로부터 값을 전달받고, 조건문을 이용해서 조건부 스타일링을 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677811465359&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// src/App.js

import React from &quot;react&quot;;
import styled from &quot;styled-components&quot;; //해주어야 적용이 된다.

const StContainer = styled.div` //styled. 뒤에는 html 요소가 오고 `백틱을 사용한다.
  display: flex;
`;

const StBox = styled.div`
  width: 100px;
  height: 100px;
  border: 1px solid ${(props) =&amp;gt; props.borderColor}; //props를 받는다.
  margin: 20px;
`;
// 박스의 색을 배열에 담는다.
const boxList = [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;];

// 색을 넣으면, 이름을 반환해주는 함수를 만든다.
const getBoxName = (color) =&amp;gt; {
  switch (color) {
    case &quot;red&quot;:
      return &quot;빨간 박스&quot;;
    case &quot;green&quot;:
      return &quot;초록 박스&quot;;
    case &quot;blue&quot;:
      return &quot;파란 박스&quot;;
    default:
      return &quot;검정 박스&quot;;
   }
};
const App = () =&amp;gt; {
  return (
    &amp;lt;StContainer&amp;gt;
			{/* map을 이용해서 StBox를 반복하여 화면에 그린다. */}
      {boxList.map((box) =&amp;gt; (
        &amp;lt;StBox borderColor={box}&amp;gt;{getBoxName(box)}&amp;lt;/StBox&amp;gt;
      ))}
    &amp;lt;/StContainer&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&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) 전역 스타일링 ( 그 외 Sass, css reset)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 전역 스타일링&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;공통적으로 들어가야 할 스타일&lt;/span&gt;을 적용해야 할 상황도 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그럴 경우 &amp;lsquo;전역적으로(globally)&amp;rsquo; 스타일을 지정한다고 하는데, 그럴 때 적용하는 방법이 바로 전역 스타일링이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 때, 공통적으로 적용되는 스타일링 부분은 빼줄 필요가 있다. &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677812126963&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//GlobalStyle.jsx
import { createGlobalStyle } from &quot;styled-components&quot;;

const GlobalStyle = createGlobalStyle`
  body {
    font-family: &quot;Helvetica&quot;, &quot;Arial&quot;, sans-serif;
    line-height: 1.5;
  }
`;

export default GlobalStyle;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 공통적으로 들어가는 스타일을 따로 빼내서&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677812143703&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//App.jsx
import GlobalStyle from &quot;./GlobalStyle&quot;;
import BlogPost from &quot;./BlogPost&quot;;

function App() {
	const title = '전역 스타일링 제목입니다.';
	const contents = '전역 스타일링 내용입니다.';
  return (
    &amp;lt;&amp;gt;
      &amp;lt;GlobalStyle /&amp;gt;
      &amp;lt;BlogPost title={title} contents={contents} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② Sass&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;CSS를 전통적인 방법보다 효율적으로 사용하기 위해 만들어진 언어이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;코드의 재사용성을 높이고, 가독성 또한 향상시켜줄 수 있는 방법이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677812526289&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 변수 사용
$color: #4287f5;

div {
	background: $color;
}
//중첩 사용
label {
      color: $colorPoint;
      
      &amp;amp;:hover {
        color: white;
      }
}
//다른 style 파일 import
//common.scss
$color1: #ed5b46;
$color2: #f26671;
//style.scss
@import &quot;common.scss&quot;;

.box {
	background-color: $color3;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;③ css reset&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;브라우저는&lt;span style=&quot;color: #ef5369;&quot;&gt; 기본적으로 default style&lt;/span&gt;을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;하지만, 다양한 웹브라우저들은 저마다 조금씩은 다른 default style을 제공하고 있기에,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 이를 &lt;span style=&quot;color: #ef5369;&quot;&gt;초기화하고 우리가 정하는대로만 표현&lt;/span&gt;될 수 있도록 하는 방법도 알아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;=&amp;gt; reset.css코드를 작성해 적용시키면 &amp;nbsp;default style이 적용되지 않는다.&lt;/span&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;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>CSS Reset</category>
      <category>CSS-in-JS</category>
      <category>default style</category>
      <category>sass</category>
      <category>styled-components</category>
      <category>전역 스타일링</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/156</guid>
      <comments>https://innocentcodingstory.tistory.com/156#entry156comment</comments>
      <pubDate>Fri, 3 Mar 2023 22:19:10 +0900</pubDate>
    </item>
    <item>
      <title>2023.03.02) 항해 25일차</title>
      <link>https://innocentcodingstory.tistory.com/155</link>
      <description>&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;하위의 컴포넌트도 렌더링이 되지 않도록 연결고리를 끊어야 한다는 것은 알았다.&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;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;/p&gt;
&lt;pre id=&quot;code_1677753950306&quot; class=&quot;armasm&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* 컴포넌트 하나에 props를 전달하는 방식
	* 이 컴포넌트가 어떤 역할을 하는지를 한 눈에 보았을때 추측하기 어렵다.
	* 수정사항이 생길 경우 전달해야 할 props가 늘어날 수 있고, 불필요한 props까지 전달하게 되는 상황이 생길 수 있다. + props가 늘면 코드도 더욱 복잡해진다.
	=&amp;gt; 유지보수 측면에서 어려울 수 있다.

&amp;lt;Modal
  buttonName={&quot;열어주세요.&quot;}
  contents={&quot;안녕하세요&quot;}
  fontColor=&quot;white&quot;
  bc=&quot;red&quot;
  buttonSize=&quot;large&quot;
  margin=&quot;10px&quot;
  position=&quot;right&quot;
/&amp;gt;

-------

const Modal = ({ buttonName, contents, bc, fontColor, buttonSize, margin }) =&amp;gt; {
  const [open, setOpen] = useState(false);
  return (
    &amp;lt;&amp;gt;
      &amp;lt;button
        style={{
          backgroundColor: bc,
          color: fontColor,
          width: buttonSize === &quot;large&quot; ? &quot;120px&quot; : &quot;50px&quot;,
          margin: margin ? margin : &quot;none&quot;
        }}
        onClick={() =&amp;gt; setOpen((pre) =&amp;gt; !pre)}
      &amp;gt;
        {buttonName}
      &amp;lt;/button&amp;gt;
      {open ? &amp;lt;div&amp;gt;{contents}&amp;lt;/div&amp;gt; : null}
    &amp;lt;/&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한눈에 보기 어려운 이 코드를 컴파운드 컴포넌트 패턴으로 다시 작성하면,&lt;/p&gt;
&lt;pre id=&quot;code_1677753950307&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* 컴파운드 패턴
	* 대부분의 인자를 children으로 전달하고, 수정이 간단하다.
	* 굳이 타고 들어가지 않아도 어떤 인자가 어디로 어떻게 전달되는지 추측하기 쉽다.
	* props를 늘려서 코드가 복잡해질 일도 없고, props driling도 상대적으로 줄일 수 있다.
	=&amp;gt; 유지보수 측면에서 좋은 방법

&amp;lt;ComModal.Root&amp;gt;
  &amp;lt;ComModal.Trigger&amp;gt;
    &amp;lt;Button fontColor=&quot;white&quot; bc=&quot;red&quot; buttonSize=&quot;large&quot;&amp;gt;
      열기
    &amp;lt;/Button&amp;gt;
  &amp;lt;/ComModal.Trigger&amp;gt;
	&amp;lt;ComModal.Content&amp;gt;안녕하세요&amp;lt;/ComModal.Content&amp;gt;
&amp;lt;/ComModal.Root&amp;gt;

------

const Context = createContext();

export const ComModalRoot = ({ children }) =&amp;gt; {
  const [open, setOpen] = useState(false);
  return (
    &amp;lt;Context.Provider
      value={{
        open,
        setOpen
      }}
    &amp;gt;
      {children}
    &amp;lt;/Context.Provider&amp;gt;
  );
};

const ComModalTrigger = ({ children }) =&amp;gt; {
  const { setOpen } = useContext(Context);
  return &amp;lt;div onClick={() =&amp;gt; setOpen((pre) =&amp;gt; !pre)}&amp;gt;{children}&amp;lt;/div&amp;gt;;
};

const ComModalContent = ({ children }) =&amp;gt; {
  const { open } = useContext(Context);
  return &amp;lt;div&amp;gt;{open ? children : null}&amp;lt;/div&amp;gt;;
};&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;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/155</guid>
      <comments>https://innocentcodingstory.tistory.com/155#entry155comment</comments>
      <pubDate>Thu, 2 Mar 2023 22:45:29 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.28) 항해 23일차</title>
      <link>https://innocentcodingstory.tistory.com/154</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 어제 만들었던 투두리스트의 컴포넌트를 분리해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리하면서 props를 받을 때 구조분해할당으로 받지 않아서 오류가 났었다.&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;파일에 함수를 옮기고 export 하여 컴포넌트 파일에 import를 하였는데,&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;첫 번째로 export 할 때 매개변수로 넣어준 것들을&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 파일의 함수 적용하는 곳에도 똑같이 넣어주어야 한다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째로 컴포넌트 파일을 분리하며 props로 받아 온 함수를 지워주지 않아서 오류가 났던 것이다..&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;물론 불필요한 리렌더링을 정리해주어야 하는데..&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;팁이 필요해!!!!!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ppGdy/btr0WfKt3VC/DzGULdXDF9CveYOgOsWHaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ppGdy/btr0WfKt3VC/DzGULdXDF9CveYOgOsWHaK/img.png&quot; data-alt=&quot;분리한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ppGdy/btr0WfKt3VC/DzGULdXDF9CveYOgOsWHaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FppGdy%2Fbtr0WfKt3VC%2FDzGULdXDF9CveYOgOsWHaK%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;178&quot; height=&quot;220&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;분리한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>export</category>
      <category>import</category>
      <category>PROPS</category>
      <category>구조분해할당</category>
      <category>리렌더링</category>
      <category>분리</category>
      <category>컴포넌트</category>
      <category>함수</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/154</guid>
      <comments>https://innocentcodingstory.tistory.com/154#entry154comment</comments>
      <pubDate>Wed, 1 Mar 2023 00:33:52 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.27) 항해 22일차</title>
      <link>https://innocentcodingstory.tistory.com/153</link>
      <description>&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;/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;&quot;&gt; 있도록 투두에 ' &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;isDone&lt;/span&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;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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;false '를 기본값으로 주고,&lt;/span&gt;&lt;/p&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;완료 버튼을 클릭하면 false가 true로 바뀌고, 완료 자리로 가도록 하려고 하였다.&lt;/span&gt;&lt;/p&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;그렇게 하기 위해서 map에 if문을 사용하여 바뀌도록 하였다.&lt;/span&gt;&lt;/p&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;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;pre id=&quot;code_1677502655019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  //투두 완료
  const clickDoneBoxHandler = (id) =&amp;gt; {
    const newTodos = todos.map((todo)=&amp;gt;{
      if(todo.id === id){
        todo.isDone = true;
      }
      return todo;
    });
    setTodos(newTodos);
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 진행중인 구역에는 false인 투두만 들어오고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완료인 구역에는 true인 투두가 들어오도록 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1677502712790&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 진행중인 구역
&amp;lt;div className='working'&amp;gt;
          {todos.filter ((item) =&amp;gt; item.isDone === false)
          .map(function (item) {
            return ...
            
// 완료 구역
&amp;lt;div className='done'&amp;gt;
        {todos.filter ((item) =&amp;gt; item.isDone === true)
          .map(function (item) {
            return ...&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;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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;취소 버튼을 누르면 다시 false로 바뀌게 하여 진행중인 구역으로 들어가도록 하였다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEGzQq/btr0WfpgzzC/sc6OKVE7p870N6MYNwOwq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEGzQq/btr0WfpgzzC/sc6OKVE7p870N6MYNwOwq0/img.png&quot; data-alt=&quot;완성된 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEGzQq/btr0WfpgzzC/sc6OKVE7p870N6MYNwOwq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEGzQq%2Fbtr0WfpgzzC%2Fsc6OKVE7p870N6MYNwOwq0%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;600&quot; height=&quot;388&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;666&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;추가로 스타일링도 하고 원하는 폰트도 찾아서 적용시켜 보았다!!&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;</description>
      <category>TIL(Today I Learned)</category>
      <category>CSS</category>
      <category>map</category>
      <category>react</category>
      <category>TODO</category>
      <category>Todo list</category>
      <category>리액트</category>
      <category>삭제</category>
      <category>완료</category>
      <category>취소</category>
      <category>투두리스트</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/153</guid>
      <comments>https://innocentcodingstory.tistory.com/153#entry153comment</comments>
      <pubDate>Mon, 27 Feb 2023 22:02:29 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.26) 항해 3주차 회고</title>
      <link>https://innocentcodingstory.tistory.com/152</link>
      <description>&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;/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;아직까진 쉬운 개념들만 접한건진 몰르겠지만, 생각보다 할만 햇다는 것에 만족!!!!&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;일단 의욕은 충만하다!!&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/152</guid>
      <comments>https://innocentcodingstory.tistory.com/152#entry152comment</comments>
      <pubDate>Sun, 26 Feb 2023 21:31:57 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.25) 항해 20일차</title>
      <link>https://innocentcodingstory.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어제 보던 강의를 마저 보았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;생각보다 많이 어렵지는 않았다. 강의를 보며 차근차근 손코딩 해보며 이해하니까 생각보다 수월했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 전에 css작업도 해보고 순수 자바스크립트 작업도 해보아서 아직까지는 괜찮다!!&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;1) State&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;State&lt;/span&gt;란 &lt;span style=&quot;color: #ef5369;&quot;&gt;컴포넌트 내부에서 바뀔 수 있는 값&lt;/span&gt;을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;name이라는 정보를 const name = &amp;ldquo; &amp;rdquo;;&amp;nbsp;으로 만들었는데, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;만약 name이라는 값이 바뀌어야만 하는 정보였어야 했다면 state로 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;State를 만들 때는 useState()를 사용&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;useState 라는 함수를 이용해서 state를 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; useState 는 state를 만들어주는 리액트에서 제공하는 기능이고, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;ldquo;훅&amp;rdquo;이라고 부른다.&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;span style=&quot;color: #333333;&quot;&gt;① useState 훅을 사용하는 방식&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 선언을 하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;[ ] 빈 배열&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;을 생성하고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;배열의 첫번째 자리에는 이 state의 이름,&amp;nbsp; 두번째 자리에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;set&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;을 붙이고 state의 이름을 붙인다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;useState( )&amp;nbsp;의 인자에는 이 state의&amp;nbsp;원하는 처음값&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;nbsp;&lt;/span&gt;을 넣어준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677297558687&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [ value, setValue ] = useState( 초기값 )&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677295772256&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// state 사용 예시
import React, { useState } from 'react'

function App() {
  const [id,setId]=useState(&quot;&quot;)
  const [password,setPassword]=useState(&quot;&quot;)
  return (
    &amp;lt;div&amp;gt;
      아이디:
      &amp;lt;input 
        type=&quot;text&quot; value={id}
        onChange={function(event){
          setId(event.target.value);
        }}
      /&amp;gt;
      &amp;lt;br/&amp;gt;
      비밀번호:
      &amp;lt;input
        type=&quot;password&quot; value={password}
        onChange={function(event){
          setPassword(event.target.value);
        }}
      /&amp;gt;
      &amp;lt;br/&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; {
        alert(`입력한 아이디는 ${id}이며, 비밀번호는${password}입니다.`);
        setId('');
        setPassword('');
      }}&amp;gt; 로그인&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

  )
}

export default App&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2) 불변성&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트는 화면을 &lt;span style=&quot;color: #006dd7;&quot;&gt;렌더링&lt;/span&gt;할지를 &lt;span style=&quot;color: #ef5369;&quot;&gt;state의 변화에 따라 결정&lt;/span&gt;하고, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;단순 변수는 무시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업이다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;원시 데이터가 아닌, &lt;/span&gt;객체나 배열 등은 스프레드 문법이나 map, filter 등 &lt;span style=&quot;color: #ef5369;&quot;&gt;불변성을 지켜주는 방법&lt;/span&gt;을 사용해서 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;처리한다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;원시데이터는 수정을 했을 때 메모리에 저장된 값 자체는 바꿀 수 없고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt;새로운 메모리 저장공간에 새로운 값을 저장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot;&gt; 원시데이터가 아닌 데이터는 수정했을 때 기존에 저장되어 있던 메모리 저장공간의 값 자체를 바꿔버린다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그때, state가 변했는지 변하지 않았는지 확인하는 방법이 state의 변화 전, 후의&lt;span style=&quot;color: #ef5369;&quot;&gt; 메모리 주소를 비교&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;4&quot;&gt;리액트에서 원시데이터가 아닌 데이터를 수정할 때 불변성을 지켜주지 않고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;4&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;직접 수정을 가하면 값은 바뀌지만 메모리주소는 변함이 없게 되어버려 문제&lt;/span&gt;가 생기는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 setState 할 때 불변성을 지켜주기 위해 직접 수정을 가하지 않고 전개 연산자를 사용해서,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 값을 복사하고 그 이후에 값을 수정하는 식으로 구현한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677320653342&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 'react'
import &quot;./App.css&quot;;

function App() {
  const [fruit = [&quot;딸기&quot;, &quot;수박&quot;, &quot;망고&quot;, &quot;복숭아&quot;, &quot;사과&quot;]]
  return (
    &amp;lt;div className='body'&amp;gt;
      {fruit.filter(function(item){
        return item !== '망고';
      })
      .map(function(item){
        return &amp;lt;div className='box'&amp;gt;{item}&amp;lt;/div&amp;gt;
      })}
    &amp;lt;/div&amp;gt;
  )
}

export default App&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;/p&gt;
&lt;pre id=&quot;code_1677325082140&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//삭제버튼
const clickDeleteBoxHandler = (id) =&amp;gt; {
  const newUser = user.filter(person =&amp;gt; person.id !== id);
  setUser(newUser);
}

const Button =({clickAddBoxHandler}) =&amp;gt; {
  return &amp;lt;button onClick={clickAddBoxHandler}&amp;gt;추가&amp;lt;/button&amp;gt;;
};

export default Button;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677325216348&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 'react'
import &quot;./App.css&quot;;
import Button from 'components/Button';
import User from 'components/User';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <category>react</category>
      <category>state</category>
      <category>useState</category>
      <category>렌더링</category>
      <category>리액트</category>
      <category>메모리주소</category>
      <category>불변성</category>
      <category>컴포넌트</category>
      <category>훅</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/151</guid>
      <comments>https://innocentcodingstory.tistory.com/151#entry151comment</comments>
      <pubDate>Sat, 25 Feb 2023 20:42:51 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.24) 항해 19일차</title>
      <link>https://innocentcodingstory.tistory.com/150</link>
      <description>&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;/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;지금 실력으로는 어림도 없지...!&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1) 개발환경 (npm,&amp;nbsp; yarn)&lt;/b&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 90.2326%; height: 126px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;width: 8.97758%; height: 42px; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 44.5447%; height: 42px; text-align: center;&quot;&gt;&lt;b&gt;npm&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 46.4776%; height: 42px; text-align: center;&quot;&gt;&lt;b&gt;yarn&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;width: 8.97758%; height: 42px; text-align: center;&quot;&gt;&lt;b&gt;공통점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 91.0223%; height: 42px; text-align: left;&quot; colspan=&quot;2&quot;&gt;&lt;span&gt;&amp;nbsp; ①&amp;nbsp; 자바스크립트 런타임 환경인 &lt;span style=&quot;color: #ef5369;&quot;&gt;노드의 패키지 관리자&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp; ②&amp;nbsp; 전 세계의 많은 개발자들이 만든 유용하고 다양한 패키지&lt;br /&gt;&amp;nbsp; ③&amp;nbsp; 프로그램을 올려놓은 '온라인 데이터베잇'에서 쉽게 설치하고, 삭제할 수 있도록 도와주는 관리자&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;width: 8.97758%; height: 42px; text-align: center;&quot;&gt;&lt;b&gt;차이점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 44.5447%; height: 42px; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp; ① node.js를 설치할 때 &lt;span style=&quot;color: #ef5369;&quot;&gt;자동으로 생성&lt;/span&gt;된다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp; ② Node Package Manager의 약자&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp; ③ NPM platform 자체&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 46.4776%; height: 42px; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp; ① 2016년에 페이스북에서 개발한 패키지 관리자&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp; ② npm과 호환성이 좋다.&lt;br /&gt;&amp;nbsp; ③ npm보다 &lt;span style=&quot;color: #ef5369;&quot;&gt;속도, 안정성 측면에서 훨씬 좋다&lt;/span&gt;.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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) CRA (Create-react-app)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트 프로젝트를 하기 위해 필요한 여러 프로그램을 자동으로 설치해주는 도구이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-순서-&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① 터미널에서 원하는 폴더로 들어간 후에 &lt;span style=&quot;color: #006dd7;&quot;&gt;yarn create react-app&lt;/span&gt; week-1를 하여 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;② 생성된 폴더로 이동하여 &lt;span style=&quot;color: #006dd7;&quot;&gt;yarn start&lt;/span&gt;를 하면 리액트 앱이 실행된다.&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;3 ) Component&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트 세계에서 말하는 컴포넌트(블럭)는 즉 함수다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트를 만든다는건 html을 return 하는 함수를 만드는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 &lt;span style=&quot;color: #ef5369;&quot;&gt;컴포넌트를 구분하여 사용&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;897&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KzRPR/btr0AxLm1qU/eRC9nFLbce39qKP6Mz1IY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KzRPR/btr0AxLm1qU/eRC9nFLbce39qKP6Mz1IY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KzRPR/btr0AxLm1qU/eRC9nFLbce39qKP6Mz1IY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKzRPR%2Fbtr0AxLm1qU%2FeRC9nFLbce39qKP6Mz1IY1%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;600&quot; height=&quot;485&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;897&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;컴포넌트는 다른 컴포넌트를 품을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 다른 컴포넌트를 &lt;span style=&quot;color: #ef5369;&quot;&gt;품는 컴포넌트를 부모 컴포넌트&lt;/span&gt;라고 부르고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 컴포넌트 안에서 &lt;span style=&quot;color: #ef5369;&quot;&gt;품어지는 컴포넌트를 자식 컴포넌트&lt;/span&gt;라고 부른다.&lt;/p&gt;
&lt;pre id=&quot;code_1677229752760&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Mom() { //부모 컨포넌트
  return &amp;lt;Child /&amp;gt;
}

function Child() { //자식 컨포넌트
  return &amp;lt;div&amp;gt;나는 딸입니다.&amp;lt;/div&amp;gt;;
}

function App() {
  return &amp;lt;Mom /&amp;gt;;
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4) JSX (JavaScript + HTML)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;리액트에서는 딱 하나의 html 파일만 존재&lt;/span&gt;한다. (public 폴더 아래에 있는 index.html)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;App.js 파일에서 &lt;span style=&quot;color: #ef5369;&quot;&gt;JSX 문법&lt;/span&gt;을 사용해서 React 요소를 만들고 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;span style=&quot;color: #ef5369;&quot;&gt;컴포넌트에서 반환할 수 있는 엘리먼트는 1개&lt;/span&gt;이기 때문에 여러개를 작성하면 오류가 난다.&lt;/p&gt;
&lt;pre id=&quot;code_1677232990838&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이렇게 태그로 전체를 감싸주어 하나로 만들어야 한다
return ( 
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;안녕하세요 :)&amp;lt;/p&amp;gt;
      &amp;lt;input type='text'/&amp;gt;
    &amp;lt;/div&amp;gt;
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① JSX에서 javascript 값, map , 삼항 연산자 가져오기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX에 javascript 값, map , 삼항 연산자 등을 &lt;span style=&quot;color: #ef5369;&quot;&gt;중괄호{ }&lt;/span&gt;를 사용하여 쓸 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSX로 작성하는 태그 내에서 클래스 명을 정해줄 땐 속성 값을 &lt;span style=&quot;color: #ef5369;&quot;&gt;className&lt;/span&gt;으로 사용한다. (id는 id로 사용한다)&lt;/p&gt;
&lt;pre id=&quot;code_1677231667504&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 logo from './logo.svg';
import './App.css';

function App() {
  const number = 1;

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;p&amp;gt;안녕하세요 :)&amp;lt;/p&amp;gt;
      {/* JSX 내에서 코드 주석은 이렇게 쓴다 :) */}
      {/* 삼항 연산자를 사용한다면 */}
      &amp;lt;p&amp;gt;{number &amp;gt; 10 ? number+'은 10보다 크다': number+'은 10보다 작다'}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&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;② 인라인으로 style 주기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타일을 줄 땐, css 문법 대신&lt;span style=&quot;color: #ef5369;&quot;&gt; json 형식&lt;/span&gt;으로 넣어준다.&lt;/p&gt;
&lt;pre id=&quot;code_1677231749820&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 중괄호를 두 번 쓰는 이유? 딕셔너리도 자바스크립트니까!
// 이렇게 쓰거나,
&amp;lt;p style={{color: 'orange', fontSize: '20px'}}&amp;gt;orange&amp;lt;/p&amp;gt;

//혹은 스타일 딕셔너리를 변수로 만들고 쓸 수 있다!
function App() {
  const styles = {
    color: 'orange',
    fontSize: '20px'
  };

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;p style={styles}&amp;gt;orange&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5) Props&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;props&lt;/span&gt;는 부모 컴포넌트로부터 받아온 데이터이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;props&lt;/span&gt;를 받고 전달만 해주는 &lt;span style=&quot;color: #ef5369;&quot;&gt;중간다리&lt;/span&gt; 역할을 하는 현상을&lt;span style=&quot;color: #006dd7;&quot;&gt; Props Drilling&lt;/span&gt;라고 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677244070055&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
  function Grandfa() {
    const name= 'Ori';
    return &amp;lt;Mom grandfaName={name}/&amp;gt; //props로 name을 전달했다.
  }

  //Props Drilling
  function Mom(props){ //이게 바로 props다.
    return &amp;lt;Son grandfaName={props.grandfaName}/&amp;gt; //props로 name을 전달했다.
  }

  function Son(props){ //이게 바로 props다.
    return &amp;lt;div&amp;gt;I'm {props.grandfaName}.&amp;lt;/div&amp;gt;
  }

  return (
    &amp;lt;Grandfa /&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;&lt;b&gt;① children&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;Component props={props} /&amp;gt; 와 다른 방식으로 자식 컴포넌트에 정보를 전달해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Layout 컴포넌트를 만들 때 자주 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677243870198&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 User(props) {
  return &amp;lt;div&amp;gt;{props.children}&amp;lt;/div&amp;gt;; //정보를 받는 방식은 기존과 동일
}

function App() {
  return &amp;lt;User&amp;gt;안녕하세요&amp;lt;/User&amp;gt;; //children props를 보내는 방식
}
export default App;&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;b&gt;② 구조분해할당&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 설명했듯이 &lt;span data-token-index=&quot;1&quot;&gt;props는 object literal 형태의 데이터&lt;/span&gt; 입니다. 그래서 우리는 &lt;span style=&quot;color: #ef5369;&quot;&gt;구조 분해 할당을 이용&lt;/span&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 여러개의 props를 받는다&lt;span style=&quot;color: #333333;&quot;&gt;면, { } 안에 여러개의 props를 그대로 써주면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677248961079&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Todo({ one, two, three, four }){
	return &amp;lt;div&amp;gt;{two}&amp;lt;/div&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;&lt;b&gt;③ defaultProps&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;defaultProps&lt;/span&gt;란, 부모 컴포넌트에서 props를 보내주지 않아도 설정될 &lt;span style=&quot;color: #ef5369;&quot;&gt;초기 값&lt;/span&gt;이다.&lt;/p&gt;
&lt;pre id=&quot;code_1677249331782&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Child({ name }){
	return &amp;lt;div&amp;gt;내 이름은 {name} 입니다. &amp;lt;/div&amp;gt;
}

// 이렇게 defaultProps를 설정한다.
Child.defaultProps={
	name: '기본 이름'
}


// 구조 분해 할당 문법을 사용하면 이렇게도 할 수 있다.
function Child({ name = '기본이름' }){
	return &amp;lt;div&amp;gt;내 이름은 {name} 입니다. &amp;lt;/div&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;/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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL(Today I Learned)</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/150</guid>
      <comments>https://innocentcodingstory.tistory.com/150#entry150comment</comments>
      <pubDate>Fri, 24 Feb 2023 22:08:35 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.23) 항해 18일차</title>
      <link>https://innocentcodingstory.tistory.com/149</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&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;/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;지금 괜히 시도했다간 지금 이해한 내용도 헷갈릴지 몰라...&lt;/p&gt;
&lt;div&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;1) 동기 /&amp;nbsp; 비동기 (태스크큐, 이벤트루프)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;동기&lt;/span&gt;는&amp;nbsp;&lt;span style=&quot;color: #ef5369;&quot;&gt;직렬적으로 태스크를 수행&lt;/span&gt;하고, 태스크는 순차적으로 실행되며 어떤 작업이 수행 중이면 다음 작업은 대기한다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4YMaF/btr0okE72Rj/hoqfjpxfzk2m0UQyPXxQQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4YMaF/btr0okE72Rj/hoqfjpxfzk2m0UQyPXxQQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4YMaF/btr0okE72Rj/hoqfjpxfzk2m0UQyPXxQQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4YMaF%2Fbtr0okE72Rj%2Fhoqfjpxfzk2m0UQyPXxQQK%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;600&quot; height=&quot;129&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;비동기&lt;/span&gt;는&amp;nbsp;&lt;span style=&quot;color: #ef5369;&quot;&gt;병렬적으로 태스크를 수행&lt;/span&gt;하고, 태스크가 종료되지 않은 상태라 하더라도 대기하지 않고 다음 태스크를 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 대부분의 DOM 이벤트 핸들러와 Timer 함수(setTimeout, setInterval), Ajax 요청은 비동기식 처리 모델로 동작한다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HVFdj/btr0uwD3gUV/dmJMO3KuRaZKxdIszIqg4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HVFdj/btr0uwD3gUV/dmJMO3KuRaZKxdIszIqg4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HVFdj/btr0uwD3gUV/dmJMO3KuRaZKxdIszIqg4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHVFdj%2Fbtr0uwD3gUV%2FdmJMO3KuRaZKxdIszIqg4K%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;600&quot; height=&quot;271&quot; data-origin-width=&quot;1157&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&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;① 싱글 쓰레드란&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 &lt;span style=&quot;color: #006dd7;&quot;&gt;싱글쓰레드(single-thread)&lt;/span&gt; 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;싱글 쓰레드는 쓰레드가 하나뿐이라는 의미이며 이말은 곧 &lt;span style=&quot;color: #ef5369;&quot;&gt;하나의 작업(task)만을 처리&lt;/span&gt;할 수 있다는 것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제로 동작하는 웹 애플리케이션은 많은 task가 동시에 처리되는 것처럼 느껴진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 자바스크립트의 동시성(Concurrency)을 지원하는 것이 바로 이벤트 루프(Event Loop)이다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;515&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1C05e/btr0xO56ess/4SPk7yIWeTL4P8dZpCz9iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1C05e/btr0xO56ess/4SPk7yIWeTL4P8dZpCz9iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1C05e/btr0xO56ess/4SPk7yIWeTL4P8dZpCz9iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1C05e%2Fbtr0xO56ess%2F4SPk7yIWeTL4P8dZpCz9iK%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;400&quot; height=&quot;409&quot; data-origin-width=&quot;515&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Call Stack: 자바스크립트에서 수행해야 할 함수들을 순차적으로 스택에 담아 처리&lt;/li&gt;
&lt;li&gt;Web API: 웹 브라우저에서 제공하는 API로 AJAX나 Timeout등의 비동기 작업을 실행&lt;/li&gt;
&lt;li&gt;Task Queue: Web API에서 넘겨받은 Callback함수를 저장&lt;/li&gt;
&lt;li&gt;Event Loop: Call Stack이 비어있다면 Task Queue의 작업을 Call Stack으로 옮김&lt;/li&gt;
&lt;/ul&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;콜백 기반 비동기 처리는 &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;span style=&quot;color: #006dd7;&quot;&gt;콜백 지옥&lt;/span&gt;은 꼬리에 꼬리를 무는 비동기 동작이 많아지면 깊은 중첩 코드가 만들어지는 패턴을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백지옥을 방지하기 위해 &lt;span style=&quot;color: #ef5369;&quot;&gt;promise와 asyanc/await을 사용&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) promise&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new Promise에 전달되는 함수는 executor(실행자, 실행 함수) 라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;executor는 new Promise가 만들어질 때 자동으로 실행되는데, 결과를 최종적으로 만들어내는 제작 코드를 포함한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;executor는 자동으로 실행되는데 여기서 원하는 일이 처리되고,&amp;nbsp;끝나면 executor는 성공 여부에 따라 resolve나 reject를 호출한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;resolve&lt;/span&gt;(value)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; 일이 &lt;span style=&quot;color: #ef5369;&quot;&gt;성공적&lt;/span&gt;으로 끝난 경우 그 결과를 나타내는&lt;span&gt;&amp;nbsp;&lt;/span&gt;value와 함께 호출&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;reject&lt;/span&gt;(error)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;mdash; &lt;span style=&quot;color: #ef5369;&quot;&gt;에러 발생&lt;/span&gt; 시 에러 객체를 나타내는&lt;span&gt;&amp;nbsp;&lt;/span&gt;error와 함께 호출&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Promise 객체는 executor와 결과나 에러를 받을 소비 함수를 이어주는 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소비함수는&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;.then,&amp;nbsp;.catch,&amp;nbsp;.finally&lt;/span&gt;&amp;nbsp;메서드를 사용해 등록된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.then&lt;/span&gt;의 첫 번째 인수는 Promise가 이행되었을 때 실행되는 함수이고, 여기서 실행 결과를 받느다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.then&lt;/span&gt;의 두 번째 인수는 Promise가 거부되었을 때 실행되는 함수이고, 여기서 에러를 받는다.&lt;/li&gt;
&lt;li&gt;에러가 발생한 경우만 다루고 싶다면&amp;nbsp;.then(null, errorHandlingFunction)같이&amp;nbsp;null을 첫 번째 인수로 전달하면 되고,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.catch&lt;/span&gt;를 써도 된다. &lt;span style=&quot;color: #666666;&quot; data-ke-size=&quot;size16&quot;&gt;(.catch는 .then에 null을 전달하는 것과 동일하게 작동한다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.finally&lt;/span&gt;에선 성공&amp;middot;실패 여부에 상관없이 절차를 마무리하는 &amp;lsquo;보편적&amp;rsquo; 동작을 수행한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;.finally&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;① Promise 체이닝&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;promise&amp;nbsp;체이닝&lt;/span&gt;은&amp;nbsp;result가&amp;nbsp;.then&amp;nbsp;핸들러의 체인(사슬)을 통해 전달된다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promise 체이닝이 가능한 이유는 promise.then을 호출하면 promise가 반환되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반환된 프라미스엔 당연히 .then을 호출할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸들러가 값을 반환할 때엔 이 값이 promise의&lt;span&gt;&amp;nbsp;&lt;/span&gt;result가 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1677132814953&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Promise 체이닝 예제코드

new Promise(function(resolve, reject) {

  setTimeout(() =&amp;amp;gt; resolve(1), 1000); // ① 1초 후 최초 프라미스가 이행

}).then(function(result) { // ② 이후 첫번째 .then 핸들러가 호출

  alert(result); // 1
  return result * 2;

}).then(function(result) { // ③ 2에서 반환한 값은 다음 .then 핸들러에 전달

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;② fetch와 체이닝 함께 사용하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;fetch는 자바스크립트를 사용하면 필요할 때 서버에 네트워크 요청을 보내고, 새로운 정보를 받아오는 일을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677133133169&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// url에 네트워크 요청을 보내고 프라미스를 반환한다. 
fetch('/article/promise-chaining/user.json')
  // 원격 서버가 응답하면 .then 아래 코드가 실행된다.
  .then(function(response) {
    // response.text()는 응답 텍스트 전체가 다운로드되면
    // 응답 텍스트를 새로운 이행 프라미스를 만들고, 이를 반환한다.
    return response.text();
  })
  .then(function(text) {
    // 원격에서 받아온 파일의 내용
    alert(text); // {&quot;name&quot;: &quot;Violet-Bora-Lee&quot;, &quot;isAdmin&quot;: true}
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4) Promise API&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;① Promise.all&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;요소 전체가 Promise인 배열(엄밀히 따지면 이터러블 객체이지만, 주로 배열)을 받고 새로운 Promise를 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;모든 Promise가 이행될 때까지 기다렸다가 그 결괏값을 담은 배열을 반환&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 Promise 중 &lt;span style=&quot;color: #ef5369;&quot;&gt;하나라도 실패하면&amp;nbsp;Promise.all는 거부&lt;/span&gt;되고, 나머지 Promise의 결과는 무시된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그렇기에, Promise 결과가&amp;nbsp;모두&amp;nbsp;필요할 때같이 &amp;lsquo;모 아니면 도&amp;rsquo; 일 때 유용하다.&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;② Promise.allSettled&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;모든 프라미스가 처리될 때까지 기다린다&lt;/span&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;반환되는 배열은 다음과 같은 요소를 갖는다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;응답이 성공할 경우 &amp;ndash;&amp;nbsp;{status:&quot;fulfilled&quot;, value:result}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;에러가 발생한 경우 &amp;ndash;&amp;nbsp;{status:&quot;rejected&quot;, reason:error}&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;fetch를 사용해 여러 정보를 가져오고 있고, 여러 요청 중 하나가 실패해도 다른 요청 결과는 여전히 필요하다면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이럴 때 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Promise.allSettled를 사용하면 &lt;span style=&quot;color: #ef5369;&quot;&gt;각 프라미스의 상태와&amp;nbsp;값 또는 에러&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;③ Promise.race&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Promise.all과 비슷하지만 &lt;span style=&quot;color: #ef5369;&quot;&gt;가장 먼저 처리되는 프라미스의 결과(혹은 에러)를 반환&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;첫 번째 프라미스가 가장 빨리 처리상태가 되기 때문에 첫 번째 프라미스의 결과가 result 값이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 Promise.race를 사용하면 &lt;span style=&quot;color: #ef5369;&quot;&gt;결과가 나타난 순간 다른 프라미스의 결과 또는 에러는 무시&lt;/span&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5) &lt;span style=&quot;color: #333333;&quot;&gt;promisification (프로미스화)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;콜백을 받는 함수를 프라미스를 반환하는 함수로 바꾸는 것&lt;/span&gt;이다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프로미스화는 async/await와 함께 사용하면 더 좋지만, &lt;span style=&quot;color: #ef5369;&quot;&gt;콜백을 완전히 대체하지는 못한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;왜냐하면, Promise는 하나의 결과만 가질 수 있지만, 콜백은 여러 번 호출할 수 있기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그렇기에, 프로미스화는 &lt;span style=&quot;color: #ef5369;&quot;&gt;콜백을 단 한 번 호출하는 함수에만 적용&lt;/span&gt;해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;6) async / await&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;async&lt;/span&gt;가 붙은 함수는 &lt;span style=&quot;color: #ef5369;&quot;&gt;반드시 프로미스를 반환&lt;/span&gt;하고, 프로미스가 아닌 것은 프로미스로 감싸 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;await&lt;/span&gt;는 &lt;span style=&quot;color: #ef5369;&quot;&gt;async 함수 안에서만 동작&lt;/span&gt;하는데, 프&lt;span style=&quot;color: #ef5369;&quot;&gt;로미스가 처리될 때까지 기다렸다가&lt;/span&gt; 결과를 반환한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;await는&amp;nbsp;promise.then보다 좀 더 세련되게 프로미스의&amp;nbsp;result&amp;nbsp;값을 얻을 수 있도록 해준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;promise.then보다 가독성 좋고 쓰기도 쉽다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1677158656168&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function f() {

  let promise = new Promise((resolve, reject) =&amp;gt; {
    setTimeout(() =&amp;gt; resolve(&quot;완료!&quot;), 1000)
  });

  let result = await promise; // 프로미스가 이행될 때까지 기다린다.

  alert(result); // &quot;완료!&quot;
}

f();&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;&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>TIL(Today I Learned)</category>
      <category>async</category>
      <category>await</category>
      <category>promise</category>
      <category>Promise API</category>
      <category>Promise 체이닝</category>
      <category>Promisification</category>
      <category>동기</category>
      <category>비동기</category>
      <category>콜백 지옥</category>
      <category>프로미스화</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/149</guid>
      <comments>https://innocentcodingstory.tistory.com/149#entry149comment</comments>
      <pubDate>Thu, 23 Feb 2023 22:30:13 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.22) 항해 17일차</title>
      <link>https://innocentcodingstory.tistory.com/148</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 공부 내용은 this, 콜백 함수, 클로저이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이 세 가지 개념이 모두 어렵다고 생각되었던 내용이기에 쉽지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 this와 콜백 함수는 강의를 보고 책을 읽다 보니 할만했지만 클로저는......&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로저 공부하는 데에 나머지 두 개념보다 시간을 3~4배는 쓴 듯하다....&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;이를 위해 모던 자바스크립트 딥다이브 책도 주문하였다.....ㅎ&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFQyVBMCU4MSVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQyU5RSU5MCVFQiVCMCU5NCVFQyU4QSVBNCVFRCU4MSVBQyVFQiVBNiVCRCVFRCU4QSVCOCVFQyU5NyU5MCVFQyU4NCU5QyVFQyU5RCU5OCUyMHRoaXMlRUIlOEYlODQlMjAlRUIlQTclQTUlRUIlOUQlQkQlRUMlOUQlODAlMjAlRUElQjAlOTklRUMlOEElQjUlRUIlOEIlODglRUIlOEIlQTQuJTIwJUVEJTk0JTg0JUVCJUExJTlDJUVEJThEJUJDJUVEJThCJUIwJUVCJTgyJTk4JTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJUVBJUIwJTgwJTIwJUVDJTlFJTkwJUVBJUI4JUIwJUVCJUE1JUJDJTIwJUVDJUIwJUI4JUVDJUExJUIwJTIwJUVEJTk1JUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVBJUIyJThDJUVCJTgxJTk0JTIwJUVDJTlEJUI4JUVDJThBJUE0JUVEJTg0JUI0JUVDJThBJUE0JTIwJUVDJTgzJTlEJUVDJTg0JUIxJTIwJUVDJTlEJUI0JUVEJTlCJTg0JUVDJTk3JTkwJTIwJUVEJTk1JUI0JUVCJThCJUI5JTIwJUVDJTlEJUI4JUVDJThBJUE0JUVEJTg0JUI0JUVDJThBJUE0JUVCJUE1JUJDJTIwJUVBJUIwJTgwJUVCJUE1JUI0JUVEJTgyJUE0JUVBJUI4JUIwJTIwJUVDJTlDJTg0JUVEJTk1JUI0JUVDJTg0JTlDJTIwJUVDJTgyJUFDJUVDJTlBJUE5JUVEJTk1JUE5JUVCJThCJTg4JUVCJThCJUE0LiUyMCVFRCU5NSU5OCVFQyVBNyU4MCVFQiVBNyU4QyUyMCVFQyU5RSU5MCVFQiVCMCU5NCVFQyU4QSVBNCVFRCU4MSVBQyVFQiVBNiVCRCVFRCU4QSVCOCVFQyU5NyU5MCVFQyU4NCU5QyVFQyU5RCU5OCUyMHRoaXMlRUIlOEElOTQlMjAlRUMlOEIlQTQlRUQlOTYlODklMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglRUElQjAlODAlMjAlRUMlODMlOUQlRUMlODQlQjElRUIlOTAlQTAlMjAlRUIlOTUlOEMlMjAlRUQlOTUlQTglRUElQkIlOTglMjAlRUElQjIlQjAlRUMlQTAlOTUlRUIlOTAlQTklRUIlOEIlODglRUIlOEIlQTQuJTIwJUVDJThCJUE0JUVEJTk2JTg5JTIwJUVDJUJCJUE4JUVEJTg1JThEJUVDJThBJUE0JUVEJThBJUI4JUVCJThBJTk0JTIwJUVEJTk1JUE4JUVDJTg4JTk4JUVCJUE1JUJDJTIwJUVEJTk4JUI4JUVDJUI2JTlDJTIwJUVEJTk1JUEwJTIwJUVCJTk1JThDJTIwJUVDJTgzJTlEJUVDJTg0JUIxJUVCJTkwJTk4JUVCJUFGJTgwJUVCJUExJTlDJTJDJTIwdGhpcyVFQiU4QSU5NCUyMCVFRCU5NSVBOCVFQyU4OCU5OCVFQiVBNSVCQyUyMCU1QyUyMiVFRCU5OCVCOCVFQyVCNiU5QyU1QyUyMiUyMCVFRCU5NSVBMCUyMCVFQiU5NSU4QyUyMCVFQSVCMiVCMCVFQyVBMCU5NSVFQiU5MCU5QyVFQiU4QiVBNCVFQSVCMyVBMCUyMCVFRCU5NSVBMCUyMCVFQyU4OCU5OCUyMCVFQyU5RSU4OCVFQyU4QSVCNSVFQiU4QiU4OCVFQiU4QiVBNC4lMjAlRUElQjclQjglRUIlOUUlOTglRUMlODQlOUMlMjAlRUMlOTYlQjQlRUIlOTYlQTQlMjAlRUIlQjAlQTklRUMlOEIlOUQlRUMlOUMlQkMlRUIlQTElOUMlMjAlRUQlOTglQjglRUMlQjYlOUMlRUQlOTUlOTglRUIlODMlOTAlRUMlOTclOTAlMjAlRUIlOTQlQjAlRUIlOUQlQkMlMjAlRUElQjAlOTIlRUMlOUQlQjQlMjAlRUIlOEIlQUMlRUIlOUQlQkMlRUMlQTclODQlRUIlOEIlQTQlRUElQjMlQTAlMjAlRUQlOTUlOTglRUIlODQlQTQlRUMlOUElOTQuJTIwJUVDJTlEJUI0JUVCJTlGJUFDJUVEJTk1JTlDJTIwJUVCJUE3JUE1JUVCJTlEJUJEJUVDJTk3JTkwJUVDJTg0JTlDJTIwJUVDJTlEJUI0JUVCJUIyJTg4JTIwJUVDJTlFJUE1JUVDJTlEJTg0JTIwJUVDJTlEJUJEJUVDJTk2JUI0JUVBJUIwJTgwJUVDJThCJTlDJUVCJUE5JUI0JTIwJUVDJUEyJThCJUVDJTlEJTg0JTIwJUVBJUIyJTgzJTIwJUVBJUIwJTk5JUVDJThBJUI1JUVCJThCJTg4JUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTJDJTIyc2VsZWN0aW9ucyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmYzZjkzMTRkNTMxODQwYTVhZDc5ZDViN2IwZWRhY2EzJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyODA1NTJlMDI5ZTYyNGU5Nzg0NmFlZDU3NjQ3ZGJlMmIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIzMGQ1ZGIyODc4NWQ0ZmMyYmNjYzljYzdjZmQ5NmUzNSUyMiU3RA==&quot;&gt;1) this&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자바스크립트에서의 this는 &lt;span style=&quot;color: #ef5369;&quot;&gt;어디서든 사용&lt;/span&gt;할 수 있지만,&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;상황에 따라 this가 바라보는 대상이 달라&lt;/span&gt;지는데 엉뚱한 대상을 바라보는 경우도 있다.&lt;/li&gt;
&lt;li&gt;함수와 메서드의 구분이 느슨한 자바스크립트에서 this는 실질적으로 이 둘을 구분하는 거의 유일한 기능이다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;this는 함수를 호출할 때 결정&lt;/span&gt;된다. (this는 실행 컨텍스트가 생성될 때 결정되는데, 실행 컨텍스트는 함수를 호출할 때 생성된다)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;함수 호출 방식에 따라 값이 달라&lt;/span&gt;진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 기본적인 this의 규칙&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;전역 공간&lt;/span&gt;에서 &lt;span style=&quot;color: #006dd7;&quot;&gt;this&lt;/span&gt;는 전역 컨텍스트를 생성하는 주체인 &lt;span style=&quot;color: #ef5369;&quot;&gt;전역 객체&lt;/span&gt;를 가리킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기에 대부분의 경우에서 전역공간의 &lt;span style=&quot;color: #006dd7;&quot;&gt;'전역변수 a = window a= this.a'&lt;/span&gt;가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외의 경우는 delete 연산자를 썼을 경우이다. (delete 연산자 = window.delete)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;처음부터 전역객체의 프로퍼티로 할당한 경우에는 삭제가 되지만, 전역변수로 선언한 경우에는 삭제가 되지 않는다.&lt;/li&gt;
&lt;li&gt;전역변수를 선언하면 자바스크립트 엔진이 이를 자동으로 전역객체의 프로퍼티로 할당하는데,&lt;/li&gt;
&lt;li&gt;이때 해당 프로퍼티의 변경 및 삭제 가능성을 false로 정의하기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;① 함수와 메서드에서의 this&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수&lt;/span&gt;는 그 자체로 &lt;span style=&quot;color: #ef5369;&quot;&gt;독립적인 기능&lt;/span&gt;을 수행하고, &lt;span style=&quot;color: #006dd7;&quot;&gt;메서드&lt;/span&gt;는 자신을 &lt;span style=&quot;color: #ef5369;&quot;&gt;호출한 대상 객체에 관한 동작&lt;/span&gt;을 수행한다는 차이가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;메서드&lt;/span&gt;로 호출 : 점 표기법이나 대괄호 표기법으로 함수를 호출할 때 함수 이름 앞에 객체가 명시되어 있는 경우이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수&lt;/span&gt;로 호출 : 메서드로 호출한 경우를 제외한 경우이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;메서드&lt;/span&gt;로 호출하는 경우 this는 함수명 앞의 객체의 정보를 담는데, 점 표기법의 경우에 마지막 &lt;span style=&quot;color: #ef5369;&quot;&gt;점 앞에 명시된 객체가 this&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수&lt;/span&gt;로 호출하는 경우 this는 지정되어 있지 않고, &lt;span style=&quot;color: #ef5369;&quot;&gt;전역 객체&lt;/span&gt;를 가리킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;화살표 함수&lt;/span&gt;는 실행 컨텍스트를 생성할 때 this의 바인딩 과정 자체가 빠지게 되어 &lt;span style=&quot;color: #ef5369;&quot;&gt;상위 스코프의 this&lt;/span&gt;를 그대로 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;콜백함수&lt;/span&gt;에서 제어권을 받은 함수에서 콜백함수에 별도로 &lt;span style=&quot;color: #ef5369;&quot;&gt;this가 될 대상을 지정하면 그 대상을 참조&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;&lt;span style=&quot;color: #006dd7;&quot;&gt;생성자 함수&lt;/span&gt;로 호출된 경우 내부에서의 this는 &lt;span style=&quot;color: #ef5369;&quot;&gt;곧 새로 만들 구체적인 인스턴스 자신&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;( 생성자는 구체적인 인스턴스를 만들기 위한 일종의 틀이다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2) 명시적 this 바인딩의 경우 (위의 규칙에 부합하지 않는 경우)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;call, apply 메서드&lt;/span&gt;는 this를 명시적으로 지정하며 함수나 메서드를 호출하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;bind 메서드&lt;/span&gt;는 this 및 함수에 넘길 인수를 이루 지정하여 새로운 함수를 만들고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;요소를 순회하며 콜백함수를 반복호출하는 일부 메서드&lt;/span&gt;는 별도의 인자로 this를 받는다.&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;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;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;콜백함수&lt;/span&gt;는 다른 코드에게 인자로 넘겨줌으로써 그 &lt;span style=&quot;color: #ef5369;&quot;&gt;제어권도&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;함께&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&amp;nbsp;위임한 함수&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위임받은 코드는 자체적인 내부 로직에 의해 이 &lt;span style=&quot;color: #ef5369;&quot;&gt;콜백 함수를 적당한 시점에 실행&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(callback은 되돌아&amp;nbsp;호출해 달라는&amp;nbsp;명령이다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;콜백 함수&lt;/span&gt;는 어떤 객체의 메서드를 전달하더라도 그 메서드는 &lt;span style=&quot;color: #ef5369;&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;객체의 메서드를 콜백 함수로 전달하면 해당 객체를 &lt;span style=&quot;color: #ef5369;&quot;&gt;this로 바라볼 수 없게 된다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콜백 함수 내부에서 this가 객체를 바라보게 하고 싶다면 &lt;span style=&quot;color: #ef5369;&quot;&gt;bind 메서드를 사용&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;(1) 콜백 지옥과 동기/비동기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;콜백 지옥&lt;/span&gt;은 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여 쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;동기적인 코드&lt;/span&gt;는 현재 실행 중인 코드가 완료된 후에나 다음 코드를 실행하는 방식이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;즉시 처리가 가능한 대부분의 코드&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;비동기적인 코드&lt;/span&gt;는 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt; 별도의 요청, 실행대기, 보류 등과 관련된 코드&lt;/span&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;&lt;span style=&quot;color: #006dd7;&quot;&gt;promise&lt;/span&gt;는 new 연산자와 함께 호출한 promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 내부에 &lt;span style=&quot;color: #ef5369;&quot;&gt;resolve나 reject&lt;/span&gt; 함수를 호출하는 구문이 있을 경우,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 중 하나가 실행되기 전까지는 다음(then)이나 오류구문(catch)으로 넘어가지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;비동기 작업이 완료될 때 비로소 resolve나 reject를 호출&lt;/span&gt;하는 방법으로 비동기 작업의 동기적 표현이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;asyanc/await&lt;/span&gt;는 &lt;span style=&quot;color: #ef5369;&quot;&gt;비동기 작업을 수행하고자 하는 함수 앞에 async&lt;/span&gt;를 표기하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 내부에서 &lt;span style=&quot;color: #ef5369;&quot;&gt;실질적인 비동기 작업이 필요한 위치마다 await&lt;/span&gt;를 표기하는 것 만으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤의 내용을 promise로 자동전환하고 , 해당 내용이 resolve 된 후에야 다음으로 진행한다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) 클로저&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) 클로저와 LexicalEnvironment&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;클로저&lt;/span&gt;는 함수와 &lt;span style=&quot;color: #ef5369;&quot;&gt;그 함수가 선언될 당시의 LexicalEnvironment의 상호관계&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;자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라, &lt;span style=&quot;color: #ef5369;&quot;&gt;함수를 어디에 정의했는지에 따라 상위 스코프를 결정&lt;/span&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LexicalEnvironment의 outerEnvironmentReference에 호출되는 환경과 상관없이 &lt;span style=&quot;color: #ef5369;&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;가비지 컬렉터의 동작 방식에 의해 실행 종료된 외부 함수의 변수를 여전히 참조할 수 있도록 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1677054734643&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//예제 코드

const x = 1;

function outer() {
    const x = 10;
    const inner = function () { console.log(x) };
    return inner;
}

const innerFunc = outer();
innerFunc();&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;outer 함수를 호출하면 중첩 함수 inner를 반환하게 된다.&lt;br /&gt;그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스탭에서 역할을 다 했기 때문에 제거된다.&lt;br /&gt;inner함수가 innerFunc에 전달되었는데, 이는 outer 함수의 렉시컬환경을 참조하고 있다.&lt;br /&gt;즉, outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;inner함수에서 outer 함수의 변수를 사용하기에 &lt;span style=&quot;color: #ef5369;&quot;&gt;outer 함수의 렉시컬 환경까지 소멸하는 것은 아니다.&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;(2) 클로저가 아닌 경우&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;중첩 함수이지만 상위 스코프를 참조하지 않으면 클로저라고 하지 않는다.&lt;/li&gt;
&lt;li&gt;중첩 함수이고 상위 스코프를 참조하지만 선언 후 바로 실행하고 소멸하는 경우에는 클로저라고 하지 않는다.&lt;/li&gt;
&lt;/ul&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: #ef5369;&quot;&gt;중첩함수이고 상위 스코프의 식별자를 참조하며 outer 함수보다 inner 함수가 더 오래 유지되어야&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;&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>TIL(Today I Learned)</category>
      <category>asyanc/await</category>
      <category>lexicalEnvironment</category>
      <category>promise</category>
      <category>This</category>
      <category>동기</category>
      <category>비동기</category>
      <category>전역 객체</category>
      <category>콜백함수</category>
      <category>클로저</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/148</guid>
      <comments>https://innocentcodingstory.tistory.com/148#entry148comment</comments>
      <pubDate>Wed, 22 Feb 2023 22:06:43 +0900</pubDate>
    </item>
    <item>
      <title>2023.02.21) 항해 16일차</title>
      <link>https://innocentcodingstory.tistory.com/147</link>
      <description>&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 데이터 타입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;데이터 타입에는 크게 두 가지가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;기본형 (숫자, 문자열, 불리언, null, undefined)&lt;span style=&quot;color: #333333;&quot;&gt;은 기본적으로&amp;nbsp;불변성을 띄고,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;참조형 (객체, 배열, 함수, 날짜, 정규표현식)&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;은 가변성을 띄지만 상황에 따라 불변값을 사용하는 경우도 있다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;1bit는 0과 1이고, 1byte는 8bit이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;변수&lt;/span&gt;는 변할 수 있는 무언가(데이터)이고,&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px; color: #006dd7;&quot;&gt;식별자&lt;/span&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;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;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;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;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;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;데이터 할당 시 변수 영역과 데이터 영역이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;변수 영역&lt;/span&gt;의 값에 데이터 영역의 주소를 저장하고, &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px; color: #006dd7;&quot;&gt;데이터 영역&lt;/span&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;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;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;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;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;얕은 복사&lt;/span&gt;는 바로 아래의 단계의 값만 복사하는 방법이고, 원본과 사본이 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;깊은 복사&lt;/span&gt;는 내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법이고, 원본과 사본이 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;기본형 데이터는 그대로 복사하면 되지만, &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;참조형 데이터는 다시 그 내부의 프로퍼티를 복사해야지 &lt;span style=&quot;color: #ef5369;&quot;&gt;깊은 복사가 된다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; undefined와 null&lt;/span&gt;은 모두 '없음'을 나타내는 값이지만 의미와 사용 목적이 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;undefined&lt;/span&gt;는 사용자가 명시적으로 부여도 가능하고 자바스크립트 엔진이 자동으로 부여하기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;bull; 자동으로 부여하는 경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp; - 값을 대입하지 않은 변수&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp; - 객체 내부의 존재하지 않는 프로퍼티&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp; - return문이 없거나 호출되지 않는 함수의 실행결과&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;값으로써 어딘가에 할당된 undefined는 &lt;span style=&quot;color: #ef5369;&quot;&gt;실존하는 데이터&lt;/span&gt;이고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자바스크립트 엔진이 반환해 주는 undefined는 &lt;span style=&quot;color: #ef5369;&quot;&gt;문자 그대로 값이 없다&lt;/span&gt;는 것을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그렇기에 &lt;span style=&quot;color: #ef5369;&quot;&gt;'비어있음'을 명시적으로 나타내고 싶을 때&lt;/span&gt;에는 undefined가 아닌 &lt;span style=&quot;color: #ef5369;&quot;&gt;null을 사용&lt;/span&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;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;1. 다른 언어에서는 어떻게 데이터 타입을 정의할까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;C/C++, 자바 등 정적 타입 언어의 경우 타입별로 할당할 메모리 영역을 2바이트, 4바이트로 나누어 정해놓고 사용한다.&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;span style=&quot;color: #666666;&quot;&gt;2. 다른 언어들처럼 데이터 타입을 다룬다면 장단점은 무엇이 있을까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;받아서 저장해야 할 값이 명확히 정해져 있기 때문에 잘못 입력하게 된다면 오류가 나서 쉽게 문제점을 알 수 있는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&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;span style=&quot;color: #666666;&quot;&gt;3. 기본형 데이터와 참조형 데이터를 굳이 왜 구분해서 다룰까요? 혹시 하나의 방식으로 다 다룰 수는 없을까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;기본형 데이터와 달리&amp;nbsp; 참조형 데이터는 추가로 객체의 변수영역도 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;또한 기본형과 참조형 모두 같은 주소를 바라보게 되는 점과 복사과정을 동일하지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;데이터 할당과정에서 차이가 있고 변수 복사 이후의 동작에서도 큰 차이가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&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;span style=&quot;color: #666666;&quot;&gt;4. 왜 불변 객체를 이용해야 할까요? 어떤 실수가 있을 수 있을까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;값으로 전달받은 객체에 변경을 가하더라도 원본 객체는 변하지 않아야 하는 경우에 불변 객체를 사용하게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;얕은 복사를 하게 된다면 원본과 사본이 같아지는 문제가 생긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;그렇기에 깊은 복사를 하여 원본과 사본은 분리해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;5. 왜 자바스크립트에는 undefined와 null이 있을까요?&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt; undefined와 null은 모두 '없음'을 나타내는 값이지만 의미와 사용 목적이 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot; data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQSVCOCVCMCVFQiVCMyVCOCVFRCU5OCU5NSUyQyUyMCVFQyVCMCVCOCVFQyVBMSVCMCVFRCU5OCU5NSUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCVFQyU4NCVCMSUyQyUyMCVFQiVBOSU5NCVFQiVBQSVBOCVFQiVBNiVBQyUyMCVFQyVBMyVCQyVFQyU4NiU4QyUyQyUyMCVFQyU4QiU5RCVFQiVCMyU4NCVFQyU5RSU5MCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyQyUyMCVFQSVCMCU4MCVFQiVCMyU4MCVFQSVCMCU5MiUyQyUyMCVFQiU4RCVCMCVFQyU5RCVCNCVFRCU4NCVCMCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCMyU4MCVFQyU4OCU5OCUyMCVFQyU5OCU4MSVFQyU5NyVBRCUyQyUyMCVFQiVCNiU4OCVFQiVCMyU4MCUyMCVFQSVCMCU5RCVFQyVCMiVCNCUyQyUyMCVFQyU5NiU5NSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMCVFQSVCOSU4QSVFQyU5RCU4MCUyMCVFQiVCMyVCNSVFQyU4MiVBQyUyQyUyMHVuZGVmaW5lZCUyQyUyMG51bGwlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCUyQyUyMnNlbGVjdGlvbnMlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlODE1NjFlOGQwY2I0Y2ZhYWNhYzUwN2YzMTQ5ZTJhOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdkNmQwZjkzZWI3NTRjMGJhMWIzMjVmODQ0MjkwZmRlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2I0MDNjNjI5OWRmNGMxN2FmYzBkMjg3MDY5MzVmMDklMjIlN0Q=&quot;&gt;undefined는 사용자가 명시적으로 부여도 가능하고 자바스크립트 엔진이 자동으로 부여하기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;값으로써 어딘가에 할당된 undefined는&amp;nbsp;실존하는 데이터이고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;자바스크립트 엔진이 반환해 주는 undefined는&amp;nbsp;문자 그대로 값이 없다는 것을 말하기에 차이가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;그렇기에&amp;nbsp;'비어있음'을 명시적으로 나타내고 싶을 때에는 undefined가 아닌&amp;nbsp;null을 사용한다는 점에서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt; undefined와 null의 차이점이 존재한다.&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;2) 실행 컨텍스트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;스택&lt;/span&gt;은 쌓은 순서대로 뒤에부터 다시 꺼내는 데이터 구조이고, &lt;/span&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;큐&lt;/span&gt;는 쌓은 순서대로 앞에서부터 꺼내는 데이터 구조이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;실행 컨텍스트&lt;/span&gt;는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;콜 스택에 쌓아 올렸다가 위에&amp;nbsp; 있는 것부터 실행하는 전체 코드의 &lt;span style=&quot;color: #ef5369;&quot;&gt;환경과 순서를 보장&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;자바스크립트 코드를 실행하는 순간 콜 스택에 전역 컨텍스트가 담기게 되고, 관련된 함수들을 위에 쌓는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU4QiVBNCVFRCU5NiU4OSUyMCVFQyVCQiVBOCVFRCU4NSU4RCVFQyU4QSVBNCVFRCU4QSVCOCUyQyUyMHRoaXMlMkMlMjAlRUQlOTklOTglRUElQjIlQkQlMjAlRUMlQTAlOTUlRUIlQjMlQjQlMkMlMjAlRUMlOEElQTQlRUQlODMlOUQlMkMlMjAlRUQlODElOTAlMkMlMjAlRUMlQTAlODQlRUMlOTclQUQlMjAlRUMlQkIlQTglRUQlODUlOEQlRUMlOEElQTQlRUQlOEElQjglMkMlMjAlRUMlQkQlOUMlRUMlOEElQTQlRUQlODMlOUQlMkMlMjBWYXJpYWJsZSUyMEVudmlyb25tZW50JTJDJTIwTGV4aWNhbCUyMEVudmlyb25tZW50JTJDJTIwJUVEJTk4JUI4JUVDJTlEJUI0JUVDJThBJUE0JUVEJThDJTg1JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVDJTg0JUEwJUVDJTk2JUI4JUVCJUFDJUI4JTJDJTIwJUVEJTk1JUE4JUVDJTg4JTk4JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JTJDJTIwJUVDJThBJUE0JUVDJUJEJTk0JUVEJTk0JTg0JUVDJUIyJUI0JUVDJTlEJUI4JTJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlMkMlMjJzZWxlY3Rpb25zJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjEyZjFjYmJkY2QxNDE1NGI2NWY5MDliMDI1ZDg4MmYlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhODg5OGNlNWM3NGE0ZDQ1YTBhMDM1MjQzMWI4NmQyOCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjVhMDEzNjliOTQyYzRhNTliMWUzNWFiZjg0YzliZDc2JTIyJTdE&quot;&gt;실행 시 위에서부터 실행하게 되는데 마지막에는 전역 컨텍스트까지 제거되며 콜 스택에는 아무것도 남지 않게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Variable Environment&lt;/span&gt;는 현재 컨택스트 내의 식별자들에 대한 정보+외부환경 정보이다. &lt;span style=&quot;color: #666666;&quot;&gt;(변경사항 반영 X)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Lexical Environment&lt;/span&gt;는 Variable Environment와 처음은 같지만 변경사항이 실시간으로 반영되는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;outerEnvironmentRefernce&lt;/span&gt;는&amp;nbsp; 현재 호출된 함수가 선언될 당시&lt;span style=&quot;color: #333333;&quot;&gt;의 Lexical Environment를 참조한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그렇기에 가장 가까운 요소부터 차례대로만 접근할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수 선언문&lt;/span&gt;은 function 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수 표현식&lt;/span&gt;은 정의한 function을 별도의 변수에 할당하는 것을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;함수 표현식에는 기명 함수 표현식과 익명 함수 표현식이 있는데 &lt;span style=&quot;color: #ef5369;&quot;&gt;일반적으로는 익명 함수 표현식을 사용&lt;/span&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;3) 호이스팅&lt;/b&gt;&lt;/p&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;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;선언 전에 미리 할당&lt;/span&gt;하는 것이다.&lt;/span&gt;&lt;/p&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 style=&quot;color: #006dd7;&quot;&gt;var&lt;/span&gt;로 선언한 변수는 호이스팅 시&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;undefined로 변수를 초기화한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&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;let과&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&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 style=&quot;color: #006dd7;&quot;&gt;const&lt;/span&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;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;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;변수의 선언과 초기화를 분리한 후, 선언만 코드의 최상단으로 옮기는 것&quot;&lt;/span&gt;이라 한다.&lt;/span&gt;&lt;/p&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;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;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;선언과 초기화를 함께&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수행하는 경우,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;선언 코드까지 실행&lt;/span&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;b&gt;4) 스코프&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;스코프&lt;/span&gt;는 식별자에 대한 유효범위이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떤 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;찾아내기 위한 규칙이고, 자바스크립트는 이 규칙대로 식별자를 찾는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;전역 스코프 (Global scope)&lt;/span&gt;는 코드 어디에서든지 참조할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;전역 변수 (Global variable)&lt;/span&gt;는 전역에서 선언된 변수이며 어디에든 참조할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(전역 변수는 전역 스코프를 가진다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;지역 스코프 (Local scope)&lt;/span&gt;는 함수 코드 블록이 만든 스코프로 함수 자신과 하위 함수에서만 참조할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;지역 변수 (Local variable)&lt;/span&gt;는 지역(함수) 내에서 선언된 변수이며 그 지역과 그 지역의 하부 지역에서만 참조할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(지역 변수는 지역 스코프를 가진다)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;함수 레벨 스코프&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;는 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 유효하고 함수 외부에서는 유효하지 않다는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;같은 전역변수와 지역변수가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;중복 선언&lt;/span&gt;되면 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;전역 영역에서는 전역변수만이 참조 가능하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt; 함수 내 &lt;span style=&quot;color: #ef5369;&quot;&gt;지역 영역에서는&lt;/span&gt; 전역과 지역 변수 모두 참조 가능하나 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;지역변수를 우선하여 참조&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;스코프 체인&lt;/span&gt;이란 '식별자의 유효범위'를 안에서부터 바깥으로 차례로 검색해 나가는 것을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 스코프에서 동일한 식별자를 선언한 경우에는&amp;nbsp;&lt;span style=&quot;color: #ef5369;&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;&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>TIL(Today I Learned)</category>
      <category>lexical environment</category>
      <category>Variable Environment</category>
      <category>데이터 타입</category>
      <category>스코프 체인</category>
      <category>실행 컨텍스트</category>
      <category>호이스팅</category>
      <author>Wisdom_1104</author>
      <guid isPermaLink="true">https://innocentcodingstory.tistory.com/147</guid>
      <comments>https://innocentcodingstory.tistory.com/147#entry147comment</comments>
      <pubDate>Tue, 21 Feb 2023 16:54:15 +0900</pubDate>
    </item>
  </channel>
</rss>