<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>디자인보다 개발이 더 좋아</title>
    <link>https://hamo0.tistory.com/</link>
    <description>FE</description>
    <language>ko</language>
    <pubDate>Fri, 26 Jun 2026 13:07:37 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>햄oOoOo</managingEditor>
    <image>
      <title>디자인보다 개발이 더 좋아</title>
      <url>https://tistory1.daumcdn.net/tistory/6248806/attach/092000ed256c4c219603afcd5b4ae5d6</url>
      <link>https://hamo0.tistory.com</link>
    </image>
    <item>
      <title>운영체제와 브라우저는 우리의 클릭 이벤트를 어떻게 처리할까? (유저 모드, 커널 모드, 인터럽트, 시스템 콜)</title>
      <link>https://hamo0.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;솔직히 운영체제를 배울 때 가장 와닿지 않는 부분이었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;도대체 인터럽트가 언제 일어난다는거야? 본적도 없는데.&lt;br /&gt;난 시스템 콜 발생시켜본적도 없는데?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 기본 개념을 작년에 들었던 운영체제 수업 필기를 참고해서 다시 정리해보았다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;유저모드, 커널모드&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;User mode&lt;/h4&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;OS가 아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;나머지 프로그램은 유저모드에서 돌아간다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Kernel mode&lt;/h4&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;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;CPU에서 제공하는 모든 instruction 수행 가능.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;디바이스 레지스터를 포함한 모든 하드웨어 디바이스에 접근 가능.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;OS는 커널모드에서 돌아간다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;이를 결정하는 것은 CPU이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;인터럽트 (Interrupt)&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Interrupt (하드웨어 Interruption)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;시스템에서 발생한 다양한 종류의 &lt;b&gt;이벤트&lt;/b&gt; or &lt;b&gt;이벤트를 알리는 메커니즘&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;디바이스 하드웨어가 interrupt 신호를 발생&lt;/b&gt;시키면 OS가 커널모드로 전환&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;비동기적&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Trap (소프트웨어 Interruption)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;&lt;b&gt;유저 프로그램이 시스템 콜 호출&lt;/b&gt;, 유저 모드에서 커널 모드로 진입하기 &lt;br /&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-token-index=&quot;1&quot;&gt;Trap&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어로 exception을 발생시킴 (소프트웨어 interrupt 던짐)&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc;&quot;&gt;동기적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;시스템콜 (System call)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영체제에 요청하는 함수들.&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;프로그램: 커널모드의 운영체제야. 난 지금 유저모드인데 건드릴 수 없는 자원 있어&amp;hellip; 이 명령 대신 해줘.&lt;/blockquote&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;시스템 콜의 종류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스/스레드 관련&lt;/li&gt;
&lt;li&gt;파일 I/O 관련&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;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간과 날짜의 설정과 획득(time)&lt;/li&gt;
&lt;li&gt;시스템 데이터의 설정과 획득(date)&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;h2 data-ke-size=&quot;size26&quot;&gt;파일 read 예제&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;665&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r4p8x/btsKdRSqR2B/hieGzBLpCC6J2tDmEGWmT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r4p8x/btsKdRSqR2B/hieGzBLpCC6J2tDmEGWmT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r4p8x/btsKdRSqR2B/hieGzBLpCC6J2tDmEGWmT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr4p8x%2FbtsKdRSqR2B%2FhieGzBLpCC6J2tDmEGWmT1%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;665&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;1398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b47LgW/btsPKfGW0uY/UZn7fn5oXiVEJnOGf7lr20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b47LgW/btsPKfGW0uY/UZn7fn5oXiVEJnOGf7lr20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b47LgW/btsPKfGW0uY/UZn7fn5oXiVEJnOGf7lr20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb47LgW%2FbtsPKfGW0uY%2FUZn7fn5oXiVEJnOGf7lr20%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;540&quot; height=&quot;698&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;1398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;System Call&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Odm3E/btsKdmrOJ0u/DerGydUXdL8mUMczqrYl9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Odm3E/btsKdmrOJ0u/DerGydUXdL8mUMczqrYl9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Odm3E/btsKdmrOJ0u/DerGydUXdL8mUMczqrYl9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOdm3E%2FbtsKdmrOJ0u%2FDerGydUXdL8mUMczqrYl9k%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;535&quot; height=&quot;445&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;1000&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;다시 처음으로 돌아와서&lt;/h2&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;도대체 인터럽트가 언제 일어난다는거야? 본적도 없는데.&lt;br /&gt;난 시스템 콜 발생시켜본적도 없는데?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 콜의 종류에는 파일 I/O, 시간과 날짜 정보 얻기, 프로세스 통신, ... 등이 있었다.&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_1754550045290&quot; class=&quot;typescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question('이름을 입력하세요: ', (name) =&amp;gt; {
  console.log(`안녕하세요, ${name}!`);
  rl.close();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr; node.js가&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&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: #353638; text-align: left;&quot;&gt;&lt;span style=&quot;color: #353638; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;실제로는 해당 코드가 실행되면 I/O 시스템 콜이 CPU로 들어가 &lt;b&gt;소프트웨어 인터럽트&lt;/b&gt;가 발생, 우리가 키보드 입력을 하면 &lt;b&gt;하드웨어 인터럽트&lt;/b&gt;가 발생한 뒤 위에서 설명한 과정을 거쳐 &lt;i&gt;return&lt;/i&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;그럼 브라우저는 우리의 클릭 이벤트를 어떻게 처리할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 브라우저에서는 어떤 원리로 이벤트를 감지할 수 있었을까? 클릭 이벤트, 키보드 이벤트 등은 모두 사용자 &quot;입력&quot;으로 인해 발생한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자가 화면을 클릭하면... (Chrome)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;1. 마우스 클릭으로 인한 입력으로&amp;nbsp;&lt;b&gt;하드웨어 인터럽트 발생&lt;/b&gt;, CPU한테 보내고 CPU는 &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;커널모드로 진입&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;2. 운영체제는 인터럽트 벡터를 통해 인터럽트 핸들러 실행, 네이티브&amp;nbsp;&lt;/span&gt;이벤트를 생성하여 Chrome의 브라우저 프로세스로 &lt;i&gt;return&lt;/i&gt;, 다시 유저 모드로 들어옴&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;3. 브라우저 프로세스는 렌더러 프로세스로&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt; 이벤트의 유형과 좌표만 전달 (브라우저 프로세스는 렌더러 프로세스가 관리하는 컨텐츠 자체는 모르기 때문)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;4. 렌더러 프로세스는 이벤트 타겟을 찾고 DOM 이벤트 객체를 생성&amp;amp;전파. 옵션에 따라 캡쳐링or버블링 단계에서 부착된 이벤트 리스너를 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tanenbaum, A. S. (2006). Modern operating systems (3rd ed.) Prentice Hall.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://chromium.googlesource.com/chromium/src/+/main/docs/ui/input_event/index.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://chromium.googlesource.com/chromium/src/+/main/docs/ui/input_event/index.md&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.chrome.com/blog/inside-browser-part4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.chrome.com/blog/inside-browser-part4&lt;/a&gt;&lt;/p&gt;</description>
      <category>TIL/운영체제</category>
      <category>시스템 콜</category>
      <category>운영체제</category>
      <category>유저모드</category>
      <category>인터럽트</category>
      <category>커널모드</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/104</guid>
      <comments>https://hamo0.tistory.com/104#entry104comment</comments>
      <pubDate>Sun, 10 Aug 2025 11:12:46 +0900</pubDate>
    </item>
    <item>
      <title>[JS] 해시 테이블 - 일반 객체 vs Map과 그 원리</title>
      <link>https://hamo0.tistory.com/103</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Map(=연관 배열, 딕셔너리)이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하는 Map은 자바스크립트가 아닌 일반적인 ADT이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키-값 형태로 저장되는 ADT.&lt;/li&gt;
&lt;li&gt;같은 키를 가지는 쌍은 최대 한 개만 존재한다. (같은 값은 여러 개 가능)&lt;/li&gt;
&lt;li&gt;해시 테이블 or 트리 로 구현할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;ADT(Abstract Data Type) = 추상 자료형&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;구현 방법은 명시하지 않고, 특성과 작업들에 대해서만 설명하는 자료구조.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;규칙들의 나열.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해시 테이블이란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열과 해시 함수를 사용하여 Map을 구현한 자료 구조이다.&lt;/li&gt;
&lt;li&gt;평균 O(1)의 시간복잡도를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해시 함수&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;임의의 크기를 가지는 타입의 데이터를, 고정된 크기를 가지는 타입의 데이터로 변환하는 함수.&lt;/li&gt;
&lt;li&gt;해시 테이블의 해시 함수는 임의 데이터를 정수(해시값)로 변환한다.&lt;/li&gt;
&lt;li&gt;이 hash값을 유한한 해시 테이블에 저장하기 위해, 해시 테이블의 크기로 모듈러 연산을 해서 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해시 충돌&lt;/h3&gt;
&lt;p style=&quot;color: #000000; 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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;키는 다르지만 &lt;b&gt;hash(해시 함수로 변환한 값)가 같을 때&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;키도 hash도 다른데 hash % map_capa 결과가 같을 때 (&lt;b&gt;모듈러 연산의 결과가 같을 때&lt;/b&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비둘기집 원리로, 무한한 값을 유한한 해시 테이블에 저장하려다 보면 생기는 일이다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;해시 충돌의 해결방법 1. 체이닝 (Chaining)&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;해시 충돌의 해결방법 2. 개방 주소법 (Open Addressing)&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;h4 data-ke-size=&quot;size20&quot;&gt;그러면 어떻게 해시 테이블의 탐색을 최적화 할 수 있을까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버킷의 크기를 키우면 된다. 삽입된 엔트리 수가 임계치를 넘으면 resize해서 버킷 수를 늘리고, 순회를 짧게 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;자바스크립트 객체의 생성원리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 객체는 Indexed Properties를 가진 객체와 Named properties를 가진&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;Indexed Properties:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;[1, 2, 3]&lt;/i&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;or&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;{1: &quot;a&quot;, 2: &quot;b&quot;}&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;Named properties:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;{&quot;first&quot;: 1, &quot;second&quot;: 2}&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;히든 클래스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 중 Named properties를 가진&amp;nbsp;객체는 히든 클래스를 참조한다. 히든 클래스는 객체의 모양 정보를 저장하고 있다.&lt;/li&gt;
&lt;li&gt;동일한 구조를 가진 객체는 동일한 히든 클래스를 공유한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQceO4/btsPEp95f98/wnyF4KNkeBFXOrrB3hIAo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQceO4/btsPEp95f98/wnyF4KNkeBFXOrrB3hIAo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQceO4/btsPEp95f98/wnyF4KNkeBFXOrrB3hIAo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQceO4%2FbtsPEp95f98%2FwnyF4KNkeBFXOrrB3hIAo0%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;627&quot; height=&quot;188&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;384&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;/p&gt;
&lt;pre id=&quot;code_1753945283429&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class HiddenClass {
    #name;
    constructor(name) {
        this.#name = name;
    }
}

const ham = new HiddenClass(&quot;ham&quot;);
const jam = new HiddenClass(&quot;jam&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;Map @87495&lt;/i&gt;&amp;nbsp;이부분이 히든 클래스 id를 나타내는 것이라고 한다. 같은 히든 클래스를 가리키고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ2Q1l/btsPDOoWLqD/2r0I5ob3KunU1E7FftunEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ2Q1l/btsPDOoWLqD/2r0I5ob3KunU1E7FftunEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ2Q1l/btsPDOoWLqD/2r0I5ob3KunU1E7FftunEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ2Q1l%2FbtsPDOoWLqD%2F2r0I5ob3KunU1E7FftunEK%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;385&quot; height=&quot;243&quot; data-origin-width=&quot;640&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;그런데 여기서 &lt;i&gt;ham.a = 1;&lt;/i&gt; 딱 요 코드만 추가하면? ham의 Map id가 바뀐 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LeWKc/btsPEqnEZ7V/AEfdlu7VL0YpQkZnIQaDak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LeWKc/btsPEqnEZ7V/AEfdlu7VL0YpQkZnIQaDak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LeWKc/btsPEqnEZ7V/AEfdlu7VL0YpQkZnIQaDak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLeWKc%2FbtsPEqnEZ7V%2FAEfdlu7VL0YpQkZnIQaDak%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;384&quot; height=&quot;274&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;452&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;이것이 바로 히든 클래스 전이이다. 새로운 Named properties를 추가하면 전이된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0C2Gc/btsPCICZiwB/g2RV1pkpNk5kVxakliZrI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0C2Gc/btsPCICZiwB/g2RV1pkpNk5kVxakliZrI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0C2Gc/btsPCICZiwB/g2RV1pkpNk5kVxakliZrI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0C2Gc%2FbtsPCICZiwB%2Fg2RV1pkpNk5kVxakliZrI1%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;695&quot; height=&quot;126&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;232&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;i&gt;jam.a = 2;&lt;/i&gt; 를 해줘서 같은 프로퍼티를 추가하면? 다시 두 객체가 같은 히든 클래스를 가리키게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y39xk/btsPDC9YvxM/gwn7gnYZAFg4fh5auidkG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y39xk/btsPDC9YvxM/gwn7gnYZAFg4fh5auidkG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y39xk/btsPDC9YvxM/gwn7gnYZAFg4fh5auidkG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy39xk%2FbtsPDC9YvxM%2Fgwn7gnYZAFg4fh5auidkG1%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;368&quot; height=&quot;281&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Named properties&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서는 Named properties가 히든 클래스 전이를 유발한다고 했다. 그런데 사실 이 Named properties는 세 종류로 나뉘어진다. 히든 클래스 전이를 유발하는 프로퍼티는 Fast properties 뿐이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm6Az3/btsPEw2snsL/rnbiheEh1aAyzkbeNGL1gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm6Az3/btsPEw2snsL/rnbiheEh1aAyzkbeNGL1gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm6Az3/btsPEw2snsL/rnbiheEh1aAyzkbeNGL1gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm6Az3%2FbtsPEw2snsL%2FrnbiheEh1aAyzkbeNGL1gk%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;605&quot; height=&quot;240&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;In-object properties&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체에 직접적으로 저장되어 가장 빨리 접근 가능&lt;/li&gt;
&lt;li&gt;프로퍼티 수가 객체의 크기에 따라 미리 제한된다.&lt;/li&gt;
&lt;li&gt;객체 크기보다 더 많은 프로퍼티가 추가되면 객체 내부가 아니라 프로퍼티 저장소(히든 클래스가 참조하는)에 저장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Fast properties&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 저장소가 참조하고 있는 배열에서 인덱스로 접근 가능&lt;/li&gt;
&lt;li&gt;같은 히든 클래스끼리는 인라인 캐시 사용해서 빠르다&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;현재 히든 클래스에서 'a' 프로퍼티는 인덱스 0번에 있구나!&quot;&lt;br /&gt;&amp;rarr; 이 정보를 인라인 캐시에 저장&lt;br /&gt;&amp;rarr; 이후 같은 히든 클래스를 가진 다른 객체에서 'a' 프로퍼티를 참조하면 인라인 캐시를 통해 바로 0번 인덱스임을 알 수 있어 빠르다.&lt;/blockquote&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Slow(Dictionary)&lt;span&gt;&amp;nbsp;&lt;/span&gt;properties&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로퍼티 추가와 삭제가 많이 일어나면, 위에서 알아봤듯 히든 클래스 전이가 계속해서 일어나게 된다. 이 히든 클래스들을 저장하기 위해 많은 시간과 메모리 오버헤드가 들기 때문에 Slow properties가 등장하였다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 저장소에 키와 값이 바로 저장, 해시 테이블 구조로 관리&lt;/li&gt;
&lt;li&gt;이 때문에 새로운 히든 클래스를 생성하지 않음&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;h2 data-ke-size=&quot;size26&quot;&gt;직접 실험하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 여러 글에서 이에 대해 다루고 있지만, 정량적으로 어떨 때 어떻다라는 것은 잘 보지 못해 직접 실험해보았다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Map&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;N과 상관 없이 모든 프로퍼티가 &lt;i&gt;OrderedHashMap&lt;/i&gt;이라는 해시 테이블에 저장된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AT8q4/btsPC6RiQea/xCCrOKVZcaIm4R1ty6KL71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AT8q4/btsPC6RiQea/xCCrOKVZcaIm4R1ty6KL71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AT8q4/btsPC6RiQea/xCCrOKVZcaIm4R1ty6KL71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAT8q4%2FbtsPC6RiQea%2FxCCrOKVZcaIm4R1ty6KL71%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;629&quot; height=&quot;42&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;N=10&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;정적 객체 리터럴&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10개 프로퍼티 모두 In-object로 추가된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mSEOG/btsPDXsxPUW/JWtuFYTJCM6ycvzjq4ozt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mSEOG/btsPDXsxPUW/JWtuFYTJCM6ycvzjq4ozt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mSEOG/btsPDXsxPUW/JWtuFYTJCM6ycvzjq4ozt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmSEOG%2FbtsPDXsxPUW%2FJWtuFYTJCM6ycvzjq4ozt0%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;625&quot; height=&quot;157&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;동적 객체 리터럴 - for문으로 추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4개까지만 In-object로 추가, 나머지는 &lt;i&gt;PropertyArray&lt;/i&gt;에 추가된다(Fast Property).&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byuppp/btsPENbUl18/Sas0DnFa7R4b2mMkKhxGbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byuppp/btsPENbUl18/Sas0DnFa7R4b2mMkKhxGbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byuppp/btsPENbUl18/Sas0DnFa7R4b2mMkKhxGbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbyuppp%2FbtsPENbUl18%2FSas0DnFa7R4b2mMkKhxGbK%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;628&quot; height=&quot;152&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;N=100&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;정적 객체 리터럴&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;100개 모두 In-object로 추가된다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;동적 객체 리터럴 - for문으로 추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100개 모두 &lt;i&gt;NameDictionary&lt;/i&gt;에 Slow properties로 추가된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tTUys/btsPDFTc5QK/3ZhMUk5govg75ALWcebwM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tTUys/btsPDFTc5QK/3ZhMUk5govg75ALWcebwM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tTUys/btsPDFTc5QK/3ZhMUk5govg75ALWcebwM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtTUys%2FbtsPDFTc5QK%2F3ZhMUk5govg75ALWcebwM1%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;392&quot; height=&quot;156&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;N이 더 커지면...&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적인 객체 리터럴은 어디까지 되나 보자 하고 실험했는데, 128개까지 In-object 프로퍼티로 추가되었다. 그 이후는 Fast properties로 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;자바스크립트에서 객체 vs Map with GPT&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 실험에서 알아낸 실제 프로퍼티들이 저장되는 자료구조 &lt;i&gt;NameDictionary&lt;/i&gt;와 &lt;i&gt;OrderedHashMap&lt;/i&gt;을, V8 깃허브 소스코드를 까서 알아봐달라고 GPT에게 부탁했다. 결과는 아래와 같다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 76px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;b&gt;객체 (Slow properties)&lt;/b&gt;&lt;br /&gt;&lt;i&gt;NameDictionary&lt;/i&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;&lt;b&gt;Map&lt;/b&gt;&lt;br /&gt;&lt;i&gt;OrderedHashMap&lt;/i&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;해시 충돌 해결&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;Open Addressing 기반 &lt;br /&gt;/ Linear probing&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;Separate Chaining + 삽입 순서 유지 &lt;br /&gt;/ 체인 리스트 (bucket + linked)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;순서 보존&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;❌ 없음&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;✅ 있음 (삽입 순서 유지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;코드 위치 in V8&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;dictionary.h / name-dictionary.h&lt;/td&gt;
&lt;td style=&quot;height: 19px;&quot;&gt;ordered-hash-table.h&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 해시 충돌을 해결하는 방법에 있어서 Map이 더 최적화되어 있어 삽입/삭제에 유리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래서 뭘 언제 써야한다고?&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;b&gt;정적 객체 리터럴&lt;/b&gt;일 때는 In-object, 128개를 넘어가더라도 Fast Property로 처리되기 때문에 Map보다 더 빠르다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러나 이 객체 리터럴을 &lt;b&gt;동적&lt;/b&gt;으로 활용하려고 하면 4개까지만 In-object로 처리되며, 더 많아지면 그냥 전체 프로퍼티가 Slow Property로 저장되어 굉장히 느려지기 때문에 &lt;b&gt;Map&lt;/b&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;h2 data-ke-size=&quot;size26&quot;&gt;참고자료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZBu_slSH5Sk&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;쉬운코드 - 해시 테이블&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://v8.dev/blog/fast-properties&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://v8.dev/blog/fast-properties&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://engineering.linecorp.com/ko/blog/v8-hidden-class&lt;/a&gt;&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <category>javascript</category>
      <category>map</category>
      <category>객체</category>
      <category>해시 충돌</category>
      <category>해시 테이블</category>
      <category>히든 클래스</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/103</guid>
      <comments>https://hamo0.tistory.com/103#entry103comment</comments>
      <pubDate>Thu, 31 Jul 2025 20:23:00 +0900</pubDate>
    </item>
    <item>
      <title>실생활 이슈로 CS 알아보기 (1) - 침착맨과 트위치 코리아 철수 그리고 망 사용료</title>
      <link>https://hamo0.tistory.com/102</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;그러나 2024년 어느 날 트위치가 망 사용료 때문에 한국 사업을 철수했다는 사실을 침착맨 덕분에 알게 되었고, 이게 인터넷의 원리와 연결되어 있다는 사실은 최근에 와서야 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;네트워크란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 기기들이 &lt;b&gt;데이터를 주고 받기 위해 유선 또는 무선으로 연결&lt;/b&gt;된 통신 체계&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1113&quot; data-origin-height=&quot;1131&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R3mmQ/btsPB1by6dI/tQ2d1a1V39i83LATuw46E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R3mmQ/btsPB1by6dI/tQ2d1a1V39i83LATuw46E0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R3mmQ/btsPB1by6dI/tQ2d1a1V39i83LATuw46E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR3mmQ%2FbtsPB1by6dI%2FtQ2d1a1V39i83LATuw46E0%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;379&quot; height=&quot;385&quot; data-origin-width=&quot;1113&quot; data-origin-height=&quot;1131&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LAN (Local Area Network)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집과 같이 제한된 범위 내의 네트워크&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이더넷(Ethernet) - 유선통신&lt;/li&gt;
&lt;li&gt;와이파이(wireless LAN) - 무선통신&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;WAN (Wide Area Network)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 LAN이나 다른 종류의 네트워크들을 하나로 묶어서 멀리 떨어진 기기들도 통신이 가능하도록 만든 네트워크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 은행 ATM 기기, wireless WAN(LTE/5G로 구현), &lt;b&gt;Internet&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;인터넷이란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;The world's largest WAN&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;The network of networks&lt;/li&gt;
&lt;li&gt;Global network&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;ISP(Internet Service Provider)란?&lt;/h2&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;ex) SKT, KT, LG U+&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;서로 다른 ISP면요?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 아는 통신사가 WAN의 일종인 인터넷을 제공한다는 것은 이해가 된다. 그런데 그렇다면 가입하지 않은 다른 통신사, 즉 다른 ISP에 가입한 기기와는 어떻게 통신할 수 있는 것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;➡️ &lt;b&gt;ISP들끼리 연결되어 있기 때문이다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;ISP 티어&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MWUAz/btsPDcpPZtO/Ml89DWKmTaFzkAkaXVx6OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MWUAz/btsPDcpPZtO/Ml89DWKmTaFzkAkaXVx6OK/img.png&quot; data-alt=&quot;By Ludovic.ferre - Internet Connectivity Distribution&amp;amp;amp;Core.svg, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=10030716&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MWUAz/btsPDcpPZtO/Ml89DWKmTaFzkAkaXVx6OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMWUAz%2FbtsPDcpPZtO%2FMl89DWKmTaFzkAkaXVx6OK%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;1920&quot; height=&quot;1120&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;By Ludovic.ferre - Internet Connectivity Distribution&amp;amp;Core.svg, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=10030716&lt;/figcaption&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;ISP는 역할과 규모에 따라 Tier가 나뉜다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Tier1 (=backbone, 인터넷 중추 역할)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;국제 범위의 네트워크 보유&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인터넷의 모든 네트워크 접근 가능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;트래픽 전송 비용이 없다!! (어차피 아쉬운쪽은 낮은 티어임)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Tier2 (일반 사용자, 기업 대상)&lt;/h4&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;Tier1 ISP에 비용을 내고 트래픽 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Tier3 (일반 사용자, 기업 대상)&lt;/h4&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;상위 ISPs에게 비용을 내고 트래픽을 구매해 서비스&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;그러면 ISP들끼리는 어떻게 연결되어 있을까?&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;피어링 (Peering)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피어링은 인터커넥션을 통해 A 네트워크와 B 네트워크의 내부에서 시작되거나 종료되는 트래픽만 흐르게 하는 것이다. 보통 무정산으로 이루어진다. 그냥 서로 왔다갔다하는 트래픽 거기서 거긴데, 정산하지 말고 퉁치자는 것. (실제 국내 통신 3사는 무정산 피어링 중이다)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;트랜짓 (Transit)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: left;&quot;&gt;트랜짓은 인터커넥션을 통해 통신망이 거대한 A 네트워크(ISP)가 상대적으로 통신망이 작은 B 네트워크(개인/기업)에게 글로벌 인터넷에 대한 연결성을 제공하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨텐츠 제공자 CP (Contents Provider)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 자주 사용하는 OTT, 유튜브, 검색엔진과 같은 서비스를 떠올리면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 규모의 CP는 일반 사용자처럼 ISP에 가입해서 서버를 인터넷에 연결하지만, 자체망을 운영하는 CP들도 있다. 너무 규모가 커진 나머지 그냥 티어2나 티어3에 ISP 비용 낼 바엔 자기가 직접 티어1 ISP와 트랜짓 계약을 때려버리는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;CP vs ISP (망 사용료)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 여기서 문제가 생긴다. 개인 이용자가 CP를 사용하려면 티어1 ISP에서 바로 데이터를 받지 못하기 때문이다. CP가 해외 서비스라면 티어2 ISP와 계약하고 있다고 하더라도 티어2에서 티어1 ISP를 거쳐, 다시 국내 티어2 ISP를 거쳐야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황) 트위치 &amp;rarr; Tier1 ISP &amp;rarr; 국내 Tier2 ISP(통신사) &amp;rarr; 사용자&lt;/li&gt;
&lt;li&gt;통신 3사) 우린 트위치 트래픽 감당하려고 장비 샀어, 너네 때문이니까 망 사용료 내놔&lt;/li&gt;
&lt;li data-end=&quot;1330&quot; data-start=&quot;1292&quot;&gt;트위치) 우린 Tier1에 돈 냈으니까 끝난거 아님?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 CP와 ISP 간에 갈등이 발생한다. &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;사실 트위치 뿐 아니라 넷플릭스 vs SKB 사이에서도 과거 갈등이 있었다고 한다. &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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네이버가 국내 Tier2 ISP에 연 1000억원대의 비용을 지불한다는 것을 자료를 찾으면서 알게 되었다. 그에 반해 구글은 한 푼도 내지 않는다고 한다. 그 이유는 GGC(구글 글로벌 캐시) 서버를 구글 측에서 통신사에 설치해 줘서, 자주 사용하는 컨텐츠들은 국내에서 해결할 수 있도록 하는 대신 망 사용료를 요구하지 않는 계약을 했기 때문이라고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 열심히 개발해서 리소스 아끼면 뭐하냐구... 이런 계약 하나로 1000억이 날라가는데.............. 굉장히 허무해졌다. 그와 동시에 인프라에도 흥미가 생겼다! 열심히 공부해보자 ✏️&lt;/p&gt;</description>
      <category>TIL/네트워크</category>
      <category>ISP</category>
      <category>네트워크</category>
      <category>망 사용료</category>
      <category>인터넷</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/102</guid>
      <comments>https://hamo0.tistory.com/102#entry102comment</comments>
      <pubDate>Wed, 30 Jul 2025 18:06:45 +0900</pubDate>
    </item>
    <item>
      <title>25년 2회 정처기 실기 응시 후기  </title>
      <link>https://hamo0.tistory.com/101</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;총평&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24년 2회 필기를 합격하고, 이후 여러 일정들 때문에 실기 응시를 하지 않았다. 1년이 지난 오늘, 25년 2회에 응시했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;24년부터 이어진 경향성으로 25년 1회에는 코딩문제가 어렵게 출제되었으나, 미리 풀어봤을 때 암기에 약한 나는 오히려 약술형이 많고 코딩문제가 쉬운 2024 이전 회차들보다 더 높은 점수가 나왔었다. 이러한 최신 경향을 미리 알았다면 개념 공부에 더더더 힘을 뺐을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 이런 행운으로 가채점 결과 90점으로 합격 예상 !!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;기본 지식과 준비 기간&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;복수전공 수업을 다 들었기 때문에, 기본적인 CS는 준비가 되어있었으나...&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발을 하다 보니 Java에 대한 이해가 전혀 없었다. 또 필기 이후 이미 1년이 지났기 때문에 빨리 합격하고 싶어 공부 기간을 길게 잡았다. 4주간 평일에만 평균 2시간씩 투자했다. 혼자 하면 미룰 것 같아서, 수제비 카페에 공부 인증을 하는 4주 스터디에 참여했다. 4주간의 계획이 이미 짜여져 있어서 편했다. 적혀 있는 일정보다는 빠르게 1회독을 마치고 4일 전부터는 최신 기출 풀이에만 전념했는데, 좋은 선택이었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;1110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGumbl/btsProwg0xB/ZcTnwNv2dZUDbryf11OQr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGumbl/btsProwg0xB/ZcTnwNv2dZUDbryf11OQr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGumbl/btsProwg0xB/ZcTnwNv2dZUDbryf11OQr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGumbl%2FbtsProwg0xB%2FZcTnwNv2dZUDbryf11OQr0%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;509&quot; height=&quot;424&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;1110&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;공부 방법&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 수제비 기본서(2024) 보면서 개념 + 문제 풀이&lt;/b&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; text-align: start;&quot;&gt;사실 작년에 필기를 합격하면서 실기 책을 미리 샀었다. 그래서 2024년 기본서로 공부했다. 먼저 책의 개념을 대충 읽으면서 이전 시험에서 2회 이상 출제된 부분 중 헷갈리는 개념을 노션에 정리했다. 이후 바로 문제풀이를 하고, 모르는 부분은 검색해가며 공부했다. &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;앞에서 언급했듯 2024년부터 기조가 바뀌었기 때문에, 책에 있는 약술형 문제들은 풀지 않고 읽고만 넘어갔다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;선택과 집중이 굉장히 중요하다는 생각이 들었다. 자격증은 100점을 맞는다고 아무도 알아주지 않는다.. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;빈출되는 부분이 아닌 자잘한 개념들은 과감하게 버렸다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;웬만하면 최신 책을 사는 것을 추천한다. 여러 번 언급하지만 2024 이전과 이후가 너무 극명한 차이가 있다. 이전에는 자바를 거의 모르는 나도 문제 풀이를 할 수 있는 정도였는데, 이제는 오버라이딩은 기본이고 제네릭, 예외처리, 참조 비교와 값 비교, &lt;i&gt;static&lt;/i&gt; 개념 등 다양한 자바의 개념을 숙지해야 문제를 풀 수 있다. 또 자료구조를 알고 있다면 쉽게 풀리는 문제들도 나왔다. (큐, 링크드리스트, 트리 등)&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;언어별 차이를 정리한 것이 큰 도움이 되었다. (출력, 참조에 대한 처리, 상속, 자료형 및 형변환 등)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5f9KW/btsPqSxOWmc/dSier00MwJyHoYKE4N4lE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5f9KW/btsPqSxOWmc/dSier00MwJyHoYKE4N4lE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5f9KW/btsPqSxOWmc/dSier00MwJyHoYKE4N4lE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5f9KW%2FbtsPqSxOWmc%2FdSier00MwJyHoYKE4N4lE1%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;1688&quot; height=&quot;1788&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1788&quot;/&gt;&lt;/span&gt;&lt;/figure&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;2. 취약부분 강의 수강&lt;/b&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;b&gt;3. 2023, 2024, 2025 기출 풀이 + 강의 수강&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;수제비 책에서 이미 2020~2023 기출이 커버되었기 때문에, 2024+2025만 2회독을 했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해설강의는 유튜브에 검색해서 조회수 높은 것들 위주로 봤다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;최근 기출의 경우 딱 오답만 정리하는 것이 아니라, 맞았더라도 해당 개념에서 나올 수 있는 것들을 추가로 정리했다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예를 들어 자바의 예외처리 문제에서, 자바에는 어떤 예외 객체가 있으며 &lt;i&gt;catch&lt;/i&gt;문은 어떤 원리로 동작하는지 등.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어 정처기 탈출 !&lt;/p&gt;</description>
      <category>개발일기</category>
      <category>실기</category>
      <category>자격증</category>
      <category>정처기</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/101</guid>
      <comments>https://hamo0.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 20 Jul 2025 10:23:31 +0900</pubDate>
    </item>
    <item>
      <title>렉시컬 환경, 렉시컬 스코프</title>
      <link>https://hamo0.tistory.com/46</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;2024. 01. 30 &amp;gt; 2025. 06. 30 블로그 A/S 프로젝트  로 추가한 글입니다.&lt;br /&gt;설명을 추가하고, 오개념을 바로잡습니다.&lt;/blockquote&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;렉시컬 환경의 구성요소&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 환경 레코드(Environment Record)&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;b&gt;객체&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;this&lt;/i&gt;&amp;nbsp;값과 같은 기타 정보도 여기에 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1.1 객체 환경 레코드 (Object Environment Record)&lt;/span&gt;&lt;/h4&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;background-color: #fdfdfc; color: #333333; text-align: justify;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;&lt;i&gt;BindingObject&lt;/i&gt; 를 참조하고 있으며, 이 객체는 &lt;b&gt;전역 객체&lt;/b&gt;를 참조한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;  전역 객체의 프로퍼티&lt;br /&gt;- &lt;i&gt;var&lt;/i&gt;로&amp;nbsp;선언한&amp;nbsp;전역&amp;nbsp;변수&lt;br /&gt;- &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;내장 전역 객체들의 바인딩&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif;&quot;&gt;- 전역 스코프에서의 함수 선언문, 비동기 함수, 제너레이터, 비동기 제너레이터&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1706714264909&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ObjectEnvironmentRecord = {
	[[BindingObject]]: 전역 객체 참조
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;1.2 선언적 환경 레코드 (Declarative Environment Record)&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;위에서 객체 환경 레코드의 참조 참조하고있는 전역 객체의 프로퍼티가 되지 않는 것들이 모두 여기 등록된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1706714289459&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DeclartionEnvironmentRecord = {
    a: 33,
    b: 'Hello World'
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 외부 렉시컬 환경(Outer Lexical Environment)에 대한 참조&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;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&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;494&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RIj32/btsEa4WMCc4/OHMZCyZQOdlHy1cw1CkCL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RIj32/btsEa4WMCc4/OHMZCyZQOdlHy1cw1CkCL0/img.png&quot; data-alt=&quot;출처: 모던 자바스크립트 튜토리얼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RIj32/btsEa4WMCc4/OHMZCyZQOdlHy1cw1CkCL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRIj32%2FbtsEa4WMCc4%2FOHMZCyZQOdlHy1cw1CkCL0%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;494&quot; height=&quot;102&quot; data-origin-width=&quot;494&quot; data-origin-height=&quot;102&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;렉시컬 환경은 언제 생성되는가?&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;생성시점&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-06-30 오후 12.03.52.png&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcN0yj/btsOWjiXDxR/wZdBD5k78kQmvZHHEWyRA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcN0yj/btsOWjiXDxR/wZdBD5k78kQmvZHHEWyRA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcN0yj/btsOWjiXDxR/wZdBD5k78kQmvZHHEWyRA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcN0yj%2FbtsOWjiXDxR%2FwZdBD5k78kQmvZHHEWyRA1%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;1870&quot; height=&quot;422&quot; data-filename=&quot;스크린샷 2025-06-30 오후 12.03.52.png&quot; data-origin-width=&quot;1870&quot; data-origin-height=&quot;422&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에 &quot;함수가 실행될 때마다 렉시컬 환경이 생성된다&quot; 등의 언급이 있어 헷갈려서 ECMAScript 공식문서를 찾아보았다. 코드가 실행(execution)이 아니라 평가(evaluated)될 때 생성됨이 확실하다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;생성단위&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수&lt;/li&gt;
&lt;li&gt;블록&lt;/li&gt;
&lt;li&gt;&lt;i&gt;try&lt;/i&gt; ~ &lt;i&gt;catch&lt;/i&gt; 의 &lt;i&gt;catch&lt;/i&gt;절&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은, 블록이라고 무조건 렉시컬 환경을 생성하지는 않는다는 점이다. 아래 예시에서 렉시컬 환경은 두개뿐이다. (전역, &lt;i&gt;a&lt;/i&gt; 식별자를 가지고 있는 블록)&lt;/p&gt;
&lt;pre id=&quot;code_1751253294742&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    const a = 1;
    {
    	{
        	console.log(a);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 예시의 렉시컬 환경은 한개뿐이다.&lt;/p&gt;
&lt;pre id=&quot;code_1751253471598&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var funcs = [];

for (var i = 0; i &amp;lt; 3; i++) {
	funcs[i] = function () { 
		return i;
	};
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 블록 레벨 스코프 키워드를 가지고 있어야 새로운 렉시컬 환경이 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;렉시컬 스코프(정적 스코프)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수를 어디서 호출하는지가 아니라 &lt;b&gt;어디에&amp;nbsp;선언&lt;/b&gt;하였는지에 따라 &lt;b&gt;상위 스코프를 결정&lt;/b&gt;하는 것. 자바스크립트는 렉시컬 스코프를 따른다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;렉시컬 환경과의 관계?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 다 &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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[[Environment]]&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수는 &lt;i&gt;[[Environment]]&lt;/i&gt;라 불리는 숨김 프로퍼티를 갖는데, 여기에 &lt;b&gt;함수가 선언된 곳의 외부 스코프&lt;/b&gt;가 저장된다.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;[[Environment]]&lt;/i&gt;는 함수가 생성될 때 딱 한 번 값이 세팅되고 영원히 변하지 않는다.&lt;/li&gt;
&lt;li&gt;즉 이 값은&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;평가&quot;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;시점에 저장되는 것. 그리고 &lt;b&gt;실행되면서 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 할당된다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDYsyw/btsD3rTM1ef/ASjN5kc3lYKl5L0iDmF5Ok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDYsyw/btsD3rTM1ef/ASjN5kc3lYKl5L0iDmF5Ok/img.png&quot; data-alt=&quot;출처: 모던 자바스크립트 튜토리얼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDYsyw/btsD3rTM1ef/ASjN5kc3lYKl5L0iDmF5Ok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDYsyw%2FbtsD3rTM1ef%2FASjN5kc3lYKl5L0iDmF5Ok%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;780&quot; height=&quot;199&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: 모던 자바스크립트 튜토리얼&lt;/figcaption&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;i&gt;counter.[[Environment]]&lt;/i&gt;에는&amp;nbsp;&lt;i&gt;{count: 0}&lt;/i&gt;이 있는 렉시컬 환경에 대한 참조가 저장된다.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;counter()&lt;/i&gt;를 호출하면 각 호출마다&lt;b&gt; 새로운 렉시컬 환경이 생성&lt;/b&gt;된다.&lt;/li&gt;
&lt;li&gt;그리고 생성된 렉시컬 환경은 &lt;i&gt;counter.[[Environment]]&lt;/i&gt;에 저장된 렉시컬 환경을 외부 렉시컬 환경으로서 참조한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>TIL/JavaScript</category>
      <category>렉시컬 스코프</category>
      <category>렉시컬 환경</category>
      <category>스코프</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/46</guid>
      <comments>https://hamo0.tistory.com/46#entry46comment</comments>
      <pubDate>Mon, 30 Jun 2025 12:19:45 +0900</pubDate>
    </item>
    <item>
      <title>실행 컨텍스트</title>
      <link>https://hamo0.tistory.com/42</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;2024. 01. 26 &amp;gt; 2025. 06. 23 블로그 A/S 프로젝트  로 추가한 글입니다.&lt;br /&gt;예시를 다듬고, 오개념을 바로잡습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 컨텍스트(execution context)란?&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 소스코드가 실행되는 단위.&lt;/li&gt;
&lt;li&gt;함수에 있는 정보, 즉 렉시컬 환경(환경 레코드와 외부 렉시컬 환경에 대한 참조)을 참조!&lt;br /&gt;** 환경 레코드 - 식별자와 바인딩된 값&lt;/li&gt;
&lt;li&gt;이 실행 컨텍스트를 콜스택에 쌓아올린 후 실행하여 코드의 환경과 순서를 보장할 수 있게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 컨텍스트는 언제 생성될까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 실행 컨텍스트를 구성할 수 있는 소스코드의 종류는 다음과 같다. 이때 내부 코드는 포함하지 않는다. 그리고 &lt;b&gt;평가 시점&lt;/b&gt;에 각각의 컨텍스트가 생성된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역&lt;/li&gt;
&lt;li&gt;함수&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eval()&lt;/code&gt; 함수&lt;/li&gt;
&lt;li&gt;모듈&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 컨텍스트와 콜스택, 렉시컬 환경&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;var x = 1;
const y = 2;

function foo(a) {
  var x = 3;
  const y = 4;

  function bar(b) {
    const z = 5;
    console.log(a + b + x + y + z);
  }
  bar(10);
}

foo(20);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;실행컨텍스트.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQKpY/btsDZW0w57U/6RBLlo7iNKpF2o3hSO0Xx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQKpY/btsDZW0w57U/6RBLlo7iNKpF2o3hSO0Xx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQKpY/btsDZW0w57U/6RBLlo7iNKpF2o3hSO0Xx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQKpY%2FbtsDZW0w57U%2F6RBLlo7iNKpF2o3hSO0Xx0%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;1432&quot; height=&quot;328&quot; data-filename=&quot;실행컨텍스트.png&quot; data-origin-width=&quot;1432&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 전역 객체 생성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빌트인 전역 프로퍼티(&lt;i&gt;Infinity&lt;/i&gt;, &lt;i&gt;NaN&lt;/i&gt;, &lt;i&gt;undefined&lt;/i&gt;)&lt;/li&gt;
&lt;li&gt;빌트인 전역 함수 (&lt;i&gt;eval&lt;/i&gt;, &lt;i&gt;isFinite&lt;/i&gt;, &lt;i&gt;isNaN&lt;/i&gt;, &lt;i&gt;parseFloat&lt;/i&gt;, &lt;i&gt;parseInt&lt;/i&gt;, &lt;i&gt;encodeURI&lt;/i&gt;/&lt;i&gt;decodeURI&lt;/i&gt;/&lt;i&gt;encodeURIComponent&lt;/i&gt;/&lt;i&gt;decodeURIComponent&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 전역 코드 평가. 전역 실행 컨텍스트 생성. 전역 렉시컬 환경 생성. 호이스팅 및 바인딩.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 실행 컨텍스트는 생성되어 콜스택에 쌓인다.&lt;/li&gt;
&lt;li&gt;전역 렉시컬 환경이 생성되어&lt;span&gt;&amp;nbsp;전역&amp;nbsp;&lt;/span&gt;실행 컨텍스트에 바인딩된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.1. 전역 렉시컬 환경의 환경 레코드 - 객체 환경 레코드의 &lt;i&gt;BindingObject&lt;/i&gt; - 전역 객체&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;foo&lt;/i&gt;는 선언문이므로 전역 객체의 메서드로 [&lt;i&gt;foo&lt;/i&gt; 식별자 - 함수 객체] 바인딩이 이루어진다.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;x&lt;/i&gt;는 &lt;i&gt;var&lt;/i&gt; 키워드로 선언되었으므로 전역 객체의 프로퍼티로 [&lt;i&gt;x&lt;/i&gt; - &lt;i&gt;undefined&lt;/i&gt;] 바인딩이 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.2. 전역 렉시컬 환경의 환경 레코드 - 선언적 환경 레코드&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;y&lt;/i&gt;는 &lt;i&gt;const&lt;/i&gt; 키워드로 선언되었으므로 선언적 환경 레코드에 [&lt;i&gt;y&lt;/i&gt; - &lt;i&gt;&amp;lt;uninitialized&amp;gt;&lt;/i&gt;] 바인딩 (아직 값 바인딩 X)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.3. this 바인딩&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전역 렉시컬 환경의 환경 레코드&lt;/b&gt;의 &lt;i&gt;[[GlobalThisValue]]&lt;/i&gt; 내부 슬롯에 &lt;b&gt;전역 객체&lt;/b&gt;가 바인딩된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.4. 외부 렉시컬 환경에 대한 참조 결정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역 렉시컬 환경은 스코프 체인의 종점. null 할당.&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;3. 전역 코드 실행&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;i&gt;x&lt;/i&gt;, &lt;i&gt;y&lt;/i&gt;, &lt;i&gt;foo&lt;/i&gt;에 대한 검색을 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. foo 함수 호출, 전역 코드 실행 일시 중단, foo 함수 내부로 코드 제어권 이동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. foo 함수 코드 평가. 함수 실행 컨텍스트 생성. 함수 렉시컬 환경 생성.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 실행 컨텍스트는 생성되어 콜스택에 쌓인다.&lt;/li&gt;
&lt;li&gt;함수 렉시컬 환경이 생성되어 &lt;i&gt;foo&lt;/i&gt; 실행 컨텍스트에 바인딩된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5.1. foo 함수 렉시컬 환경의 환경 레코드 생성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록, 관리되는 것들은 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수&lt;/li&gt;
&lt;li&gt;&lt;i&gt;arguments&lt;/i&gt; 객체&lt;/li&gt;
&lt;li&gt;함수 내부의 지역 변수와 중첩 함수&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;5.2. this 바인딩&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 렉시컬 환경의 환경 레코드의 &lt;i&gt;[[ThisValue]]&lt;/i&gt; 내부 슬롯에 전역 객체가 바인딩된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5.3. 외부 렉시컬 환경에 대한 참조 결정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;foo&lt;/i&gt; 함수가 &quot;&lt;b&gt;평가된 시점에 실행 중이었던 실행 컨텍스트&lt;/b&gt;&quot;의 렉시컬 환경의 참조가 할당된다. 즉 전역 실행 컨텍스트의 렉시컬 환경의 참조가 할당된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;6. foo 함수 코드 실행&lt;/h3&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;i&gt;foo&lt;/i&gt; 함수 실행 컨텍스트의 렉시컬 환경에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;x&lt;/i&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;y&lt;/i&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;bar&lt;/i&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;7. bar 함수 호출, foo 함수 코드 실행 일시 중단, bar 함수 내부로 코드 제어권 이동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;8. bar 함수 코드 평가. 함수 실행 컨텍스트 생성. 함수 렉시컬 환경 생성.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;9. bar 함수 코드 실행&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;9.1. console 식별자 검색&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프 체인을 타고 올라가 전역 렉시컬 환경의 객체 환경레코드에 올라간 &lt;i&gt;BindingObject&lt;/i&gt;를 통해 전역 객체에서 찾을 수 있다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;9.2. log 메서드 검색&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;console&lt;/i&gt; 객체의 프로토타입 체인을 통해 검색하여 찾는다. &lt;i&gt;log&lt;/i&gt;는 &lt;i&gt;console&lt;/i&gt;이 가지고 있는 프로퍼티이다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;9.3. a + b + x + y + z의 평가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식별자를 스코프 체인을 통해 검색하여 찾는다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;9.4. console.log 메서드 호출&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;10. bar 함수 코드 실행 종료&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;콜스택에서 &lt;i&gt;bar&lt;/i&gt; 함수 실행 컨텍스트가 팝된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이때, &lt;i&gt;bar&lt;/i&gt; 함수 실행 컨텍스트에 의해 참조되고 있는 렉시컬 환경까지 소멸하는 것은 아니다.&lt;/b&gt; (누군가 참조하고 있다면 GC에 안들어감)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;11. foo 함수 코드 실행 종료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;12. 전역 코드 실행 종료&lt;/h3&gt;</description>
      <category>TIL/JavaScript</category>
      <category>javascript</category>
      <category>실행 컨텍스트</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/42</guid>
      <comments>https://hamo0.tistory.com/42#entry42comment</comments>
      <pubDate>Fri, 27 Jun 2025 20:12:16 +0900</pubDate>
    </item>
    <item>
      <title>리액트 StrictMode 때문에 useEffect가 두 번 호출돼서 로그인 에러가 나서 짜증나서 쓰는 글</title>
      <link>https://hamo0.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 개발자라면 누구나 한번쯤은 겪었을...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;StrictMode&lt;/i&gt; 때문에 &lt;i&gt;useEffect&lt;/i&gt;가 두 번 호출되는 문제! 그냥 삭제하면 안되는걸까? &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1152&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eQ6Z0s/btsOK9VBJlI/TKxpaux3HzIblAv8YDMms1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eQ6Z0s/btsOK9VBJlI/TKxpaux3HzIblAv8YDMms1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eQ6Z0s/btsOK9VBJlI/TKxpaux3HzIblAv8YDMms1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeQ6Z0s%2FbtsOK9VBJlI%2FTKxpaux3HzIblAv8YDMms1%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;1152&quot; height=&quot;430&quot; data-origin-width=&quot;1152&quot; data-origin-height=&quot;430&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;h2 data-ke-size=&quot;size26&quot;&gt;StrictMode 공식문서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서를 보면서 정확히 어떤 일을 하는지 다시 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 이중 렌더링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 작성하는 모든 컴포넌트가 순수 함수라고 가정한다. 즉 컴포넌트를 두번씩 실행시켜서 같은 결과를 생성하는지 확인하는 것!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Effect 두 번 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 &lt;i&gt;useEffect&lt;/i&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. ref 콜백 두 번 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;ref&lt;/i&gt;콜백이 뭐지... &lt;i&gt;ref&lt;/i&gt;는 그냥 객체 넘겨주는거 아님? 궁금해서 타입을 확인해봤다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brmyzs/btsOO99bJ2q/vJIYjW4dFADkkpKPVJtksk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brmyzs/btsOO99bJ2q/vJIYjW4dFADkkpKPVJtksk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brmyzs/btsOO99bJ2q/vJIYjW4dFADkkpKPVJtksk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrmyzs%2FbtsOO99bJ2q%2FvJIYjW4dFADkkpKPVJtksk%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;1274&quot; height=&quot;430&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;430&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오 진짜 콜백도 된다. &lt;a href=&quot;https://react.dev/learn/manipulating-the-dom-with-refs#how-to-manage-a-list-of-refs-using-a-ref-callback&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식문서&lt;/a&gt;를 보니, 리액트에서 훅은 컴포넌트 최상단에서 호출되어야 해서 콜백 내에서 &lt;i&gt;useRef&lt;/i&gt;는 사용 못하니까, Map 객체를 쓰는 방법을 알려주고 있다. 아무튼 &lt;i&gt;ref&lt;/i&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;4. deprecated된 API 호출하는지 체크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말그대로 deprecated된 API들 쓰면 워닝 띄운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;어떻게 한 번만 호출하죠?&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;문제&lt;/h3&gt;
&lt;pre id=&quot;code_1750829660340&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    if (code) {
      loginMutate({ code, lastPath });
    }
}, [code, loginMutate, lastPath]);&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;이제 문제는 명확해졌다. 엄격모드에서는 Effect 싸이클을 두 번 실행시키기 때문에, 여기서 &lt;i&gt;loginMutate&lt;/i&gt;도 두 번 실행된다. 문제점은 &lt;i&gt;loginMutate&lt;/i&gt;가 POST 요청을 날리고 있어서, 멱등하지 않다는 것이다. 서버에서 리다이렉트 시켜준 라우트에서 &lt;i&gt;code&lt;/i&gt;를 가져와 요청을 날리는 식이라, 어떤 사용자 이벤트에 따라 실행되는 것도 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해결 1. useRef&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 &lt;i&gt;loginMutate&lt;/i&gt; 자체를, 같은 &lt;i&gt;code&lt;/i&gt;를 받아왔을 경우 클라이언트 단에서 두 번 호출되지 않도록 막아야 한다. 그래서 처음에는 이렇게 렌더링과 무관한 &lt;i&gt;useRef&lt;/i&gt;를 활용해서 구현했다.&lt;/p&gt;
&lt;pre id=&quot;code_1750822832252&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const isCalled = useRef(false);

useEffect(() =&amp;gt; {
    if (code &amp;amp;&amp;amp; !isCalled.current) {
      loginMutate({ code, lastPath });
      isCalled.current = true;
    }
}, [code, loginMutate, lastPath]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 로직이 한군데 더 있었는데, 캘린더 권한 습득과 관련된 로직이다. 반복은 싫기 때문에 커스텀 훅으로 만들었다.&lt;/p&gt;
&lt;pre id=&quot;code_1750831925185&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useEffect, useRef } from 'react';

interface UseEffectOnceOptions {
  condition?: boolean;
  callback: () =&amp;gt; void;
}

/**
 * 
 * @param options
 * @param options.condition - 콜백을 실행할 조건 (기본값: true)
 * @param options.callback - 한 번만 실행할 콜백 함수. useCallback을 사용하여 메모이제이션하는 것이 좋습니다.
 */
export const useEffectOnce = ({ condition = true, callback }: UseEffectOnceOptions) =&amp;gt; {
  const isCalled = useRef(false);

  useEffect(() =&amp;gt; {
    if (condition &amp;amp;&amp;amp; !isCalled.current) {
      callback();
      isCalled.current = true;
    }
  }, [condition, callback]);
};&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;문제1. 의존성 배열 린트가 안된다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 훅으로 분리하니 의존성 배열을 감지하지 못하는 문제가 있었다. 실제로 리액트 공식문서에서도 커스텀 생명주기 훅을 만들지 말라고 - &lt;i&gt;useEffectOnce&lt;/i&gt; - 경고하고 있다. ㅋㅋ.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;1750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oO2cp/btsOQg0zXpU/nlFHH849F5q4fBnkbgeUIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oO2cp/btsOQg0zXpU/nlFHH849F5q4fBnkbgeUIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oO2cp/btsOQg0zXpU/nlFHH849F5q4fBnkbgeUIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoO2cp%2FbtsOQg0zXpU%2FnlFHH849F5q4fBnkbgeUIk%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;1714&quot; height=&quot;1750&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;1750&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;i&gt;useCallback&lt;/i&gt;으로 미리 의존성 배열에 따라 다른 참조를 뱉을 수 있도록 했고, 이 콜백 자체를 의존성 배열에 넣어 해결했다. 그런데 &lt;i&gt;useCallback&lt;/i&gt; 사용을 강제할 수 없고, 또 소비자 쪽에서 어쨌든 관련 코드를 작성해야하는 제약이 생기기 때문에 상당히 찝찝했다...&lt;/p&gt;
&lt;pre id=&quot;code_1750572994927&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이렇게 사용
const loginCache = useCallback(() =&amp;gt; {
    loginMutate({ code, lastPath });
}, [loginMutate, code, lastPath]);

useEffectOnce({
    condition: Boolean(code),
    callback: loginCache,
});&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;문제 2. 공식문서에서 대놓고 하지 말라는데요?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 추가 자료를 찾던 중, 공식문서에서 &lt;a href=&quot;https://react.dev/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개발환경에서 useEffect 두 번 실행 해결하기&lt;/a&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/VHn2u/btsORDU8euS/kNgUpEvk23c05eNC8k9t1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VHn2u/btsORDU8euS/kNgUpEvk23c05eNC8k9t1k/img.png&quot; data-origin-width=&quot;1766&quot; data-origin-height=&quot;984&quot; data-is-animation=&quot;false&quot; style=&quot;width: 55.5862%; margin-right: 10px;&quot; data-widthpercent=&quot;56.24&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VHn2u/btsORDU8euS/kNgUpEvk23c05eNC8k9t1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVHn2u%2FbtsORDU8euS%2FkNgUpEvk23c05eNC8k9t1k%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;1766&quot; height=&quot;984&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WrBTJ/btsOQtzlTkH/OiMlF4F2B1j39JkkpLkf20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WrBTJ/btsOQtzlTkH/OiMlF4F2B1j39JkkpLkf20/img.png&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;1352&quot; data-is-animation=&quot;false&quot; style=&quot;width: 43.251%;&quot; data-widthpercent=&quot;43.76&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WrBTJ/btsOQtzlTkH/OiMlF4F2B1j39JkkpLkf20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWrBTJ%2FbtsOQtzlTkH%2FOiMlF4F2B1j39JkkpLkf20%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;1888&quot; height=&quot;1352&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만 억울했다. 계속 예시를 저런 가역적인 로직으로 들고 있는데, 나의 POST 요청은 비가역적이다. 그리고 공식문서의 물건을 구매하는 POST 요청과 다르게, 사용자 이벤트가 아닌 컴포넌트의 생명주기에 따라 &lt;i&gt;fetch&lt;/i&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;문제 3. 심지어 이건 버그라면서 고칠 거라는데요?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서에서 왜 &lt;i&gt;ref&lt;/i&gt;를 사용하지 말라고 했는지 알 수 있는 &lt;a href=&quot;https://github.com/reactjs/react.dev/issues/6123&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이슈&lt;/a&gt;를 발견했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 말하고자 하는 핵심은, &quot;&lt;i&gt;useRef()&lt;/i&gt;의 반환값이 StrictMode에서 유지되는 건 버그이다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://react.dev/blog/2022/03/29/react-v18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;리액트 18 릴리즈 공식문서&lt;/a&gt;에는 &quot;StrictMode에서는 컴포넌트를 자동으로 언마운트/마운트 시킨다&quot;라고 적혀 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chOw4U/btsOP9O0fnE/cW7Ef5kZSTnqQxfBTejBs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chOw4U/btsOP9O0fnE/cW7Ef5kZSTnqQxfBTejBs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chOw4U/btsOP9O0fnE/cW7Ef5kZSTnqQxfBTejBs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchOw4U%2FbtsOP9O0fnE%2FcW7Ef5kZSTnqQxfBTejBs0%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;1804&quot; height=&quot;192&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 &lt;i&gt;useRef&lt;/i&gt; 값도 참조가 파괴되어야 하는데 그렇지 않아 혼란스럽다. 이런 내용이다. 실제로 컴포넌트가 언마운트 되었다가 다시 마운트되면 참조든 뭐든 다 초기화되기 때문이다. (재호출일 뿐인 리렌더링과 다름)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어 내가 구현한 것과 같은 내용도 언급되어 있다. 왜냐하면 이게 진짜 &quot;버그&quot;로 취급된다면, 언젠가 고쳐질 것이기 때문에 하지 말아야 할 안티패턴이기 때문. 실제로 리액트 팀도 여기에 수긍하고 버그라고 인정했으며, 공식문서에 하지 말라고 적어둔 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddzw60/btsOQTq85Rg/nRVKDyr7iAU5zZxTXYCclK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddzw60/btsOQTq85Rg/nRVKDyr7iAU5zZxTXYCclK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddzw60/btsOQTq85Rg/nRVKDyr7iAU5zZxTXYCclK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fddzw60%2FbtsOQTq85Rg%2FnRVKDyr7iAU5zZxTXYCclK%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;1396&quot; height=&quot;1202&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;1202&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해결 2. 어 useEffect 안해...&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 굳이 이걸 &lt;i&gt;useEffect&lt;/i&gt; 내부에서 처리해야 할까? 이 컴포넌트가 라우팅의 단위가 되는 컴포넌트인 것에 힌트를 얻었다.&amp;nbsp;컴포넌트 단위가 아니라 라우팅이 되었을 때 딱 한번만 실행시키려면, 다른 방법도 있다. 라우트 레벨에서 처리하는 것. 이렇게 하면 컴포넌트의 생명주기로부터 자유로워진다. 여기서 &lt;i&gt;useMutation&lt;/i&gt;을 사용할 수 없으므로 리액트 컴포넌트 외부에서 사용하는 커스텀 뮤테이션 함수를 만들어 처리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1750847913605&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createFileRoute } from '@tanstack/react-router';

import { jwtMutation } from '@/features/login/api/mutations';
import { getLastRoutePath } from '@/utils/route';

type SearchWithCode = { 
  code?: string; 
};

export const Route = createFileRoute('/oauth/redirect/login/')({
  beforeLoad: async ({ search }: { search: SearchWithCode }) =&amp;gt; {
    const lastPath = getLastRoutePath();
    const { loginMutate } = jwtMutation();
    if (search.code) {
      await loginMutate({ code: search.code, lastPath });
    }
  },
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;a href=&quot;https://react.dev/learn/you-might-not-need-an-effect&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;You might not need an Effect &lt;/span&gt;&lt;/a&gt;&amp;nbsp;글을 보면 생각보다 Effect로 처리하지 않아도 되는 것들이 많다. 다음에도 개발하다가 useEffect 내부 코드가 두 번 실행되는 경우가 있다면, StrictMode를 탓하지 말고 코드를 의심해 봐야겠다. StrictMode는 리액트가 추구하는 순수성을 지키기 위해 중요한 부분이라는 생각이 들었다.&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;StrictMode 켜고 나서도 요청이 한 번만 보내지는 것을 확인하며 마무리!!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ5mh5/btsOKDvTHPT/hfElCC5F445yK2JKqvh4MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ5mh5/btsOKDvTHPT/hfElCC5F445yK2JKqvh4MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ5mh5/btsOKDvTHPT/hfElCC5F445yK2JKqvh4MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ5mh5%2FbtsOKDvTHPT%2FhfElCC5F445yK2JKqvh4MK%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;567&quot; height=&quot;170&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>TIL/React</category>
      <category>React</category>
      <category>strictmode</category>
      <category>useEffect</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/100</guid>
      <comments>https://hamo0.tistory.com/100#entry100comment</comments>
      <pubDate>Wed, 25 Jun 2025 20:15:40 +0900</pubDate>
    </item>
    <item>
      <title>주소창에 www.google.com을 입력하면 발생하는 일</title>
      <link>https://hamo0.tistory.com/63</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;2025. 03. 07 블로그 A/S 프로젝트  로 추가한 글입니다.&lt;br /&gt;기존에는 &quot;웹 브라우저&quot; 로 퉁쳤던 대상을, 정확히 누가 수행하는지 자세히 알아봅시다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주소창에 URI를 입력하면 어떤 일이 생길까?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P9UEe/btsEFgpGKNR/mKOjrdY1JnD8mxTQZR9x6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P9UEe/btsEFgpGKNR/mKOjrdY1JnD8mxTQZR9x6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P9UEe/btsEFgpGKNR/mKOjrdY1JnD8mxTQZR9x6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP9UEe%2FbtsEFgpGKNR%2FmKOjrdY1JnD8mxTQZR9x6k%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;1450&quot; height=&quot;116&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소창에 URI를 입력하면 다음과 같은 일이 진행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;1. handling inputs: 텍스트를 입력했네. 쿼리야 URL이야?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가: &lt;b&gt;브라우저 프로세스&lt;/b&gt;의 &lt;b&gt;UI 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을: &lt;b&gt;주소창에 입력한 텍스트&lt;/b&gt;를&lt;/li&gt;
&lt;li&gt;어떻게
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Search Query&lt;/b&gt;인지, &lt;b&gt;URL&lt;/b&gt;인지 판단&lt;/li&gt;
&lt;li&gt;Search Query - &lt;b&gt;검색엔진&lt;/b&gt;으로 쿼리 보내서 검색 준비&lt;/li&gt;
&lt;li&gt;URL - &lt;b&gt;네트워크 쓰레드&lt;/b&gt;로 URL 값 보낼 준비&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. Start Navigation: enter 눌렀네. 요청 보내자!&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-1. UI 쓰레드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;UI 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;주소창에 입력한 URL&lt;/b&gt;을&lt;/li&gt;
&lt;li&gt;어떻게: &lt;b&gt;네트워크 쓰레드에게 전달&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2-2. 네트워크 쓰레드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;네트워크 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을, 어떻게
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DNS 확인: 어디로 요청 보내지?&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DNS를 조회하여 도메인(www.google.com)의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;IP를 알아낸다&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP 요청(데이터) 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TCP/IP 연결&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;패킷 생성, 전송&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6xaVf/btsEGg3Gu9j/DMuA1xkHeVKR7mQKvVLw3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6xaVf/btsEGg3Gu9j/DMuA1xkHeVKR7mQKvVLw3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6xaVf/btsEGg3Gu9j/DMuA1xkHeVKR7mQKvVLw3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6xaVf%2FbtsEGg3Gu9j%2FDMuA1xkHeVKR7mQKvVLw3K%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;448&quot; height=&quot;135&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;510&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Read response: 응답 왔네. HTML이야 아니야?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLDMZV/btsEFQRJ3ZN/BnFk5t26Osa3N5R4TkOFV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLDMZV/btsEFQRJ3ZN/BnFk5t26Osa3N5R4TkOFV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLDMZV/btsEFQRJ3ZN/BnFk5t26Osa3N5R4TkOFV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLDMZV%2FbtsEFQRJ3ZN%2FBnFk5t26Osa3N5R4TkOFV1%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;448&quot; height=&quot;135&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3-1. 킁킁 이거 무슨타입이지&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;b&gt;네트워크 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을: 응답의 type을 확인&lt;/li&gt;
&lt;li&gt;어떻게: &lt;i&gt;response header&lt;/i&gt;의 &lt;i&gt;content-type&lt;/i&gt;으로&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3-2. 분류 끝냈으니까 넘겨야겠다&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;네트워크 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을: 응답받은 파일을&lt;/li&gt;
&lt;li&gt;어떻게
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTML&lt;/b&gt; - &lt;b&gt;렌더러 프로세스&lt;/b&gt;에게 넘길 준비&lt;/li&gt;
&lt;li&gt;그 외 - 다운로드 매니저에게 넘길 준비&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;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;4. Renderer process한테 넘기기&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4-1. 데이터 받아왔는데 UI 쓰레드야 이것좀 전달해라&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;네트워크 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을, 어떻게: &lt;b&gt;데이터 준비됐어!&lt;/b&gt; 라고 &lt;b&gt;UI 쓰레드에게 알림&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4-2. ㅇㅋ 드디어 넘기는구나&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;UI 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을, 어떻게: 미리 찾아놓은 &lt;b&gt;렌더러 프로세스에게 데이터 전달&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;5. Commit Navigation&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저 프로세스&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;UI 쓰레드&lt;/b&gt;가&lt;/li&gt;
&lt;li&gt;무엇을, 어떻게: &lt;b&gt;IPC &amp;amp; 데이터 스트림을 렌더러 프로세스에게 보냄&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누가:&amp;nbsp;&lt;b&gt;렌더러 프로세스가&lt;/b&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 data-ke-size=&quot;size16&quot;&gt;네비게이션 끝! 렌더링 시작!&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1741344889195&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;브라우저 렌더링, 리플로우, 리페인팅&quot; data-og-description=&quot;2025. 03. 06 블로그 A/S 프로젝트  로 업데이트한 글입니다.1. 브라우저 렌더링 과정사용자가 브라우저를 통해 웹사이트에 접속하고,&amp;nbsp;브라우저가 리소스를 다운받으면서 시작된다. (HTML, CSS, JS 등&quot; data-og-host=&quot;hamo0.tistory.com&quot; data-og-source-url=&quot;https://hamo0.tistory.com/36&quot; data-og-url=&quot;https://hamo0.tistory.com/36&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cYdree/hyYmIAgeRN/DKIHqEHtjxRukiX89KSbXK/img.png?width=800&amp;amp;height=1339&amp;amp;face=0_0_800_1339,https://scrap.kakaocdn.net/dn/E2UqO/hyYneeN5lO/i0n1p2r8dWv58R7CvMkEl1/img.png?width=800&amp;amp;height=1339&amp;amp;face=0_0_800_1339,https://scrap.kakaocdn.net/dn/b30pLH/hyYqahID7p/vEsLPOTQXzLKFjWEX4Vmbk/img.png?width=3584&amp;amp;height=1946&amp;amp;face=0_0_3584_1946&quot;&gt;&lt;a href=&quot;https://hamo0.tistory.com/36&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hamo0.tistory.com/36&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cYdree/hyYmIAgeRN/DKIHqEHtjxRukiX89KSbXK/img.png?width=800&amp;amp;height=1339&amp;amp;face=0_0_800_1339,https://scrap.kakaocdn.net/dn/E2UqO/hyYneeN5lO/i0n1p2r8dWv58R7CvMkEl1/img.png?width=800&amp;amp;height=1339&amp;amp;face=0_0_800_1339,https://scrap.kakaocdn.net/dn/b30pLH/hyYqahID7p/vEsLPOTQXzLKFjWEX4Vmbk/img.png?width=3584&amp;amp;height=1946&amp;amp;face=0_0_3584_1946');&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;브라우저 렌더링, 리플로우, 리페인팅&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2025. 03. 06 블로그 A/S 프로젝트  로 업데이트한 글입니다.1. 브라우저 렌더링 과정사용자가 브라우저를 통해 웹사이트에 접속하고,&amp;nbsp;브라우저가 리소스를 다운받으면서 시작된다. (HTML, CSS, JS 등&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hamo0.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>TIL/네트워크</category>
      <category>네트워크</category>
      <category>웹 브라우저</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/63</guid>
      <comments>https://hamo0.tistory.com/63#entry63comment</comments>
      <pubDate>Fri, 7 Mar 2025 20:08:26 +0900</pubDate>
    </item>
    <item>
      <title>크롬 브라우저 아키텍처 알아보기 (프로세스와 스레드)</title>
      <link>https://hamo0.tistory.com/98</link>
      <description>&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;2025. 03. 07 블로그 A/S 프로젝트  로 추가한 글입니다.&lt;/blockquote&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;br /&gt;운영체제는 정말 프론트엔드와 관련이 없을까? (1)&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;용어정리&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;프로세스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로그램을 구동해,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;프로그램의 상태가 메모리상에서 실행되는 작업 단위&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;하나의 프로그램에는 하나의 프로세스 할당&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;스레드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 프로그램에서 여러 개의 작업을 수행하기 위한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;더 작은 실행 단위&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;하나의 프로세스에는 여러 개의 스레드&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;스레드끼리는 메모리 공유&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;크롬 브라우저를 애용하지만 크롬 브라우저 아키텍처는 모름&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;매일 크롬 브라우저로 개발하지만 아키텍처에 대해서는 모르고 있었다...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DQHjK/btsMFg17P49/hGpdobbG1omPKwyxvxBCS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DQHjK/btsMFg17P49/hGpdobbG1omPKwyxvxBCS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DQHjK/btsMFg17P49/hGpdobbG1omPKwyxvxBCS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDQHjK%2FbtsMFg17P49%2FhGpdobbG1omPKwyxvxBCS1%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;588&quot; height=&quot;339&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&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;이렇게 여러 프로세스를 가지고 있는데, 특히 Renderer 프로세스와 Plugin 프로세스가 여러 개인 점에 주목해보자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;크롬은 &lt;b&gt;멀티 프로세스 아키텍처&lt;/b&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;크롬의 멀티 프로세스 아키텍처 - 장점&lt;/h3&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;&lt;b&gt;독립적인 Renderer 프로세스&lt;/b&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 탭이 죽어도 다른 탭과는 독립적이기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;안정적이다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안에 유리&lt;/b&gt;하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1942&quot; data-origin-height=&quot;1186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBeyWm/btsMDwZ5b5Q/iQOiReYc3KRrSIKIwyZp7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBeyWm/btsMDwZ5b5Q/iQOiReYc3KRrSIKIwyZp7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBeyWm/btsMDwZ5b5Q/iQOiReYc3KRrSIKIwyZp7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBeyWm%2FbtsMDwZ5b5Q%2FiQOiReYc3KRrSIKIwyZp7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;342&quot; data-origin-width=&quot;1942&quot; data-origin-height=&quot;1186&quot;/&gt;&lt;/span&gt;&lt;/figure&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;span&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;iframe&lt;/i&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;별로 다른 프로세스를 돌린다고 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2018&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDT1fm/btsMEN0kpp4/HXiIa4HMl1aCA1gl84ZXH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDT1fm/btsMEN0kpp4/HXiIa4HMl1aCA1gl84ZXH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDT1fm/btsMEN0kpp4/HXiIa4HMl1aCA1gl84ZXH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDT1fm%2FbtsMEN0kpp4%2FHXiIa4HMl1aCA1gl84ZXH0%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;565&quot; height=&quot;287&quot; data-origin-width=&quot;2018&quot; data-origin-height=&quot;1026&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;크롬의 멀티 프로세스 아키텍처 -&lt;span&gt;&amp;nbsp;&lt;/span&gt;단점&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;figure id=&quot;og_1741340323735&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;최신 웹브라우저 들여다보기 (1부) &amp;nbsp;|&amp;nbsp; Blog &amp;nbsp;|&amp;nbsp; Chrome for Developers&quot; data-og-description=&quot;브라우저가 코드를 개략적인 아키텍처에서 구체적인 렌더링 파이프라인에 이르기까지 제대로 작동하는 웹사이트로 변환하는 방법을 알아보세요.&quot; data-og-host=&quot;developer.chrome.com&quot; data-og-source-url=&quot;https://developer.chrome.com/blog/inside-browser-part1?hl=ko&quot; data-og-url=&quot;https://developer.chrome.com/blog/inside-browser-part1?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ca6Z8f/hyYneeNrep/EDeInWBJfoD6Lp6KVEILuK/img.png?width=865&amp;amp;height=499&amp;amp;face=0_0_865_499,https://scrap.kakaocdn.net/dn/ABaC8/hyYqQpRrta/Ar6VLIRO89kqx1NEc17UOK/img.png?width=856&amp;amp;height=491&amp;amp;face=0_0_856_491,https://scrap.kakaocdn.net/dn/bSEAWz/hyYqPYMLTX/cDtiOt6Q0n9KwvzkIOktv0/img.png?width=856&amp;amp;height=491&amp;amp;face=0_0_856_491&quot;&gt;&lt;a href=&quot;https://developer.chrome.com/blog/inside-browser-part1?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.chrome.com/blog/inside-browser-part1?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ca6Z8f/hyYneeNrep/EDeInWBJfoD6Lp6KVEILuK/img.png?width=865&amp;amp;height=499&amp;amp;face=0_0_865_499,https://scrap.kakaocdn.net/dn/ABaC8/hyYqQpRrta/Ar6VLIRO89kqx1NEc17UOK/img.png?width=856&amp;amp;height=491&amp;amp;face=0_0_856_491,https://scrap.kakaocdn.net/dn/bSEAWz/hyYqPYMLTX/cDtiOt6Q0n9KwvzkIOktv0/img.png?width=856&amp;amp;height=491&amp;amp;face=0_0_856_491');&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;최신 웹브라우저 들여다보기 (1부) &amp;nbsp;|&amp;nbsp; Blog &amp;nbsp;|&amp;nbsp; Chrome for Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;브라우저가 코드를 개략적인 아키텍처에서 구체적인 렌더링 파이프라인에 이르기까지 제대로 작동하는 웹사이트로 변환하는 방법을 알아보세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.chrome.com&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/운영체제</category>
      <category>Chrome</category>
      <category>브라우저</category>
      <category>스레드</category>
      <category>프로세스</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/98</guid>
      <comments>https://hamo0.tistory.com/98#entry98comment</comments>
      <pubDate>Fri, 7 Mar 2025 19:01:26 +0900</pubDate>
    </item>
    <item>
      <title>우아한테크코스 2트 합격 후기 ✨ (7기 프론트엔드 FE) + 입과포기?!</title>
      <link>https://hamo0.tistory.com/94</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJdHc1/btsLCHTG4nI/80HkpBtzVRBp5D1Q0P05T0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJdHc1/btsLCHTG4nI/80HkpBtzVRBp5D1Q0P05T0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJdHc1/btsLCHTG4nI/80HkpBtzVRBp5D1Q0P05T0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJdHc1%2FbtsLCHTG4nI%2F80HkpBtzVRBp5D1Q0P05T0%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;986&quot; height=&quot;986&quot; data-origin-width=&quot;986&quot; data-origin-height=&quot;986&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;h2 data-ke-size=&quot;size26&quot;&gt;코드 및 회고 모음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4주간 진행했던 프리코스 코드 및 회고들이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1주차&lt;/h3&gt;
&lt;figure id=&quot;og_1735533278775&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - hamo-o/javascript-calculator-7&quot; data-og-description=&quot;Contribute to hamo-o/javascript-calculator-7 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hamo-o/javascript-calculator-7&quot; data-og-url=&quot;https://github.com/hamo-o/javascript-calculator-7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kgJht/hyXWmW4Jby/KGUM58KAocjla7UwQtozLK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/gcHAc/hyXWCS81w0/90vChZE0rbNWHEF0Envtj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hamo-o/javascript-calculator-7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hamo-o/javascript-calculator-7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kgJht/hyXWmW4Jby/KGUM58KAocjla7UwQtozLK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/gcHAc/hyXWCS81w0/90vChZE0rbNWHEF0Envtj0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - hamo-o/javascript-calculator-7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to hamo-o/javascript-calculator-7 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1735533142686&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[우테코 프리코스 1주차 회고] 첫 TDD는 계획대로 되지 않아&quot; data-og-description=&quot;시작하면서사실 이전 프리코스에서는 &amp;quot;다들 그렇게 하니까&amp;quot; 라는 생각으로 쫓기듯 코드를 작성했다. 하지만 이번 프리코스에서는 &amp;quot;내 코드를 완벽히 이해하자&amp;quot; 라는 목표를 세우고, 나만의 근거&quot; data-og-host=&quot;hamo0.tistory.com&quot; data-og-source-url=&quot;https://hamo0.tistory.com/84&quot; data-og-url=&quot;https://hamo0.tistory.com/84&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/JEGOH/hyXWzPEJHv/IB6KihR24EdyDo1THYMCpK/img.png?width=800&amp;amp;height=126&amp;amp;face=0_0_800_126,https://scrap.kakaocdn.net/dn/pTgxj/hyXWwFonND/vFHMrQKugw2YKoyFAZkOEK/img.png?width=800&amp;amp;height=126&amp;amp;face=0_0_800_126&quot;&gt;&lt;a href=&quot;https://hamo0.tistory.com/84&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hamo0.tistory.com/84&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/JEGOH/hyXWzPEJHv/IB6KihR24EdyDo1THYMCpK/img.png?width=800&amp;amp;height=126&amp;amp;face=0_0_800_126,https://scrap.kakaocdn.net/dn/pTgxj/hyXWwFonND/vFHMrQKugw2YKoyFAZkOEK/img.png?width=800&amp;amp;height=126&amp;amp;face=0_0_800_126');&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;[우테코 프리코스 1주차 회고] 첫 TDD는 계획대로 되지 않아&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작하면서사실 이전 프리코스에서는 &quot;다들 그렇게 하니까&quot; 라는 생각으로 쫓기듯 코드를 작성했다. 하지만 이번 프리코스에서는 &quot;내 코드를 완벽히 이해하자&quot; 라는 목표를 세우고, 나만의 근거&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hamo0.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2주차&lt;/h3&gt;
&lt;figure id=&quot;og_1735533391665&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - hamo-o/javascript-racingcar-7&quot; data-og-description=&quot;Contribute to hamo-o/javascript-racingcar-7 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hamo-o/javascript-racingcar-7&quot; data-og-url=&quot;https://github.com/hamo-o/javascript-racingcar-7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bOJCjj/hyXSEE6lj7/M0rlpf0qg46xgvXpHpljo0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/r7SaB/hyXSsq8AXZ/XXnMM1mG9gKrmIAzXHzJJ0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hamo-o/javascript-racingcar-7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hamo-o/javascript-racingcar-7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bOJCjj/hyXSEE6lj7/M0rlpf0qg46xgvXpHpljo0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/r7SaB/hyXSsq8AXZ/XXnMM1mG9gKrmIAzXHzJJ0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - hamo-o/javascript-racingcar-7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to hamo-o/javascript-racingcar-7 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1735533153707&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[우테코 프리코스 2주차 회고] 넌 전혀 MVC 하고 있지 않아&quot; data-og-description=&quot;시작하면서지난 주 개선 사항은 다음과 같다.테스트 네이밍 관련 내용 조사, 나만의 규칙 만들기It Should, Given/When/Then, Describe/Context/It 등의 방식이 있다.이번 테스트는 BDD 방법론 중 하나의 방법&quot; data-og-host=&quot;hamo0.tistory.com&quot; data-og-source-url=&quot;https://hamo0.tistory.com/92&quot; data-og-url=&quot;https://hamo0.tistory.com/92&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dCM2PK/hyXWwej3MS/mujDIvb28vEMjTumRzcZok/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/L5ZJx/hyXSEE6kNz/DONPCTl1xjbekkOG6x1KB0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://hamo0.tistory.com/92&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hamo0.tistory.com/92&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dCM2PK/hyXWwej3MS/mujDIvb28vEMjTumRzcZok/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/L5ZJx/hyXSEE6kNz/DONPCTl1xjbekkOG6x1KB0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;[우테코 프리코스 2주차 회고] 넌 전혀 MVC 하고 있지 않아&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작하면서지난 주 개선 사항은 다음과 같다.테스트 네이밍 관련 내용 조사, 나만의 규칙 만들기It Should, Given/When/Then, Describe/Context/It 등의 방식이 있다.이번 테스트는 BDD 방법론 중 하나의 방법&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hamo0.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3주차&lt;/h3&gt;
&lt;figure id=&quot;og_1735533439856&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - hamo-o/javascript-lotto-7&quot; data-og-description=&quot;Contribute to hamo-o/javascript-lotto-7 development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hamo-o/javascript-lotto-7&quot; data-og-url=&quot;https://github.com/hamo-o/javascript-lotto-7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iywZr/hyXSB9rDac/YA86M9abVpuESSxpbawZHk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cBUtG7/hyXWwrQNRV/dVJzgXJCXyPGT4ZVRWLwhK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hamo-o/javascript-lotto-7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hamo-o/javascript-lotto-7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iywZr/hyXSB9rDac/YA86M9abVpuESSxpbawZHk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/cBUtG7/hyXWwrQNRV/dVJzgXJCXyPGT4ZVRWLwhK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - hamo-o/javascript-lotto-7&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to hamo-o/javascript-lotto-7 development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1735533173949&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[우테코 프리코스 3주차 회고] 모델: 뷰야, 나 업데이트됐어! 새로 렌더링해조.&quot; data-og-description=&quot;시작하면서지난 주 개선 사항은 다음과 같다.TDD와 BDD를 상호보완적으로 사용하기단위테스트를 억지로 BDD로 작성하려 하지 않고, 기능 개발 시 TDD로 개발하다가 예외 처리와 전체 기능 테스트에&quot; data-og-host=&quot;hamo0.tistory.com&quot; data-og-source-url=&quot;https://hamo0.tistory.com/93&quot; data-og-url=&quot;https://hamo0.tistory.com/93&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/brTb7n/hyXWugvQET/SohNDBqVWq8fWld70BcNe1/img.png?width=800&amp;amp;height=549&amp;amp;face=0_0_800_549,https://scrap.kakaocdn.net/dn/gibs6/hyXWCexd8z/Fe4ACGIuTmTx3hWxS1cnk1/img.png?width=800&amp;amp;height=549&amp;amp;face=0_0_800_549,https://scrap.kakaocdn.net/dn/5w7zb/hyXSubqtHl/afHXbV0hHkPZBFTTg3qlmk/img.png?width=1455&amp;amp;height=1000&amp;amp;face=0_0_1455_1000&quot;&gt;&lt;a href=&quot;https://hamo0.tistory.com/93&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hamo0.tistory.com/93&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/brTb7n/hyXWugvQET/SohNDBqVWq8fWld70BcNe1/img.png?width=800&amp;amp;height=549&amp;amp;face=0_0_800_549,https://scrap.kakaocdn.net/dn/gibs6/hyXWCexd8z/Fe4ACGIuTmTx3hWxS1cnk1/img.png?width=800&amp;amp;height=549&amp;amp;face=0_0_800_549,https://scrap.kakaocdn.net/dn/5w7zb/hyXSubqtHl/afHXbV0hHkPZBFTTg3qlmk/img.png?width=1455&amp;amp;height=1000&amp;amp;face=0_0_1455_1000');&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;[우테코 프리코스 3주차 회고] 모델: 뷰야, 나 업데이트됐어! 새로 렌더링해조.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작하면서지난 주 개선 사항은 다음과 같다.TDD와 BDD를 상호보완적으로 사용하기단위테스트를 억지로 BDD로 작성하려 하지 않고, 기능 개발 시 TDD로 개발하다가 예외 처리와 전체 기능 테스트에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hamo0.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4주차&lt;/h3&gt;
&lt;figure id=&quot;og_1735533521680&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - hamo-o/javascript-convenience-store-7-hamo-o&quot; data-og-description=&quot;Contribute to hamo-o/javascript-convenience-store-7-hamo-o development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/hamo-o/javascript-convenience-store-7-hamo-o&quot; data-og-url=&quot;https://github.com/hamo-o/javascript-convenience-store-7-hamo-o&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bV9FGh/hyXWxdc6Kz/FGRADncm1gKpVufNbk6Vgk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bJMaRl/hyXSFcUqzj/Ny48Qz6Rjn6zVaYMlfiOg0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/hamo-o/javascript-convenience-store-7-hamo-o&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/hamo-o/javascript-convenience-store-7-hamo-o&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bV9FGh/hyXWxdc6Kz/FGRADncm1gKpVufNbk6Vgk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/bJMaRl/hyXSFcUqzj/Ny48Qz6Rjn6zVaYMlfiOg0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - hamo-o/javascript-convenience-store-7-hamo-o&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to hamo-o/javascript-convenience-store-7-hamo-o development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(회고는 만족할만한 코드가 나오면 업로드 예정...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;프리코스를 마치면서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프리코스는 합격보다는 정말로 지원서에 적었던 목표 달성을 위해 신청했던 것이 컸다. 이게 합격을 위해 남들 따라하기 바빴던 저번 프리코스와 크게 달랐던 부분이었다. 아래는 최종 회고 문항 중 일부로, 4주간의 프리코스를 요약하는 문장으로 꼽을 수 있을 것 같다! 기술 키워드로는 TDD, 제어역전, 파일 입출력 등이 기억에 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;지원서나 중간 회고에서 현실적인 목표를 설정하고 이를 달성했다고 생각하나요? 그 이유는 무엇인가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-size: 0.87em; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;- &amp;ldquo;자신이 짠 코드를 완전히 이해하는 프로그래머&amp;rdquo; 목표를 달성했다고 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-size: 0.87em; 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;size16&quot;&gt;그리고 프리코스에서 찍먹해봤던 테스트 관련해서 새로운 목표도 생겼다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 브라우저에서 사용할 수 있는 테스트 작성해보기 (JS, React)&lt;/li&gt;
&lt;li&gt;개인 프로젝트에 TDD 적용해보기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;최종 코테 후기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합격을 위한 프리코스가 아닌 목표 달성을 위한 프리코스를 진행하다 보니, 자연스럽게 1차 합격이 따라왔던 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfjapA/btsLzubbYNe/DCda1ixxVbrGaTdZ1nMUbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfjapA/btsLzubbYNe/DCda1ixxVbrGaTdZ1nMUbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfjapA/btsLzubbYNe/DCda1ixxVbrGaTdZ1nMUbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfjapA%2FbtsLzubbYNe%2FDCda1ixxVbrGaTdZ1nMUbk%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;534&quot; height=&quot;345&quot; data-origin-width=&quot;978&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시험장에는 시작 약 15분쯤 전에 도착했다. 그런데 약 5분? 10분? 전부터 시험 유의사항에 대한 설명이 시작되었고, 와이파이 연결에 대한 공지화면이 넘어가 연결이 어렵게 되었다 ㅜㅜ.. 그래서 상주해 계신 멘토분들께 질문드렸으나 해결하지 못했고... 급하게 핫스팟을 연결해서 시험에 응시했다. 만약 이 글을 보는 8기 지원자 분이 계시다면 꼭 일찍 가서 와이파이 연결부터 하시길 추천!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 시험은 4주차 미션이었던 편의점보다는 쉽고, 지난 최종코테들보다는 어렵게 출제되었다. 종료 약 5분 전에 오류를 찾아내어 미처 수정하지 못하고 4/5로 마쳤다. 그래도 크게 삽질한 것 없이 실력대로 보고 나온 것 같아 만족했다. 그렇지만&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;확실히 4주차와 비슷한 점들이 있어 기출 말고 4주차를 더 열심히 풀었다면 달라졌을까? 싶긴 했다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EgFGb/btsLASCrcCl/8EKlkcgPNNAlkvt1NsAck1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EgFGb/btsLASCrcCl/8EKlkcgPNNAlkvt1NsAck1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EgFGb/btsLASCrcCl/8EKlkcgPNNAlkvt1NsAck1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEgFGb%2FbtsLASCrcCl%2F8EKlkcgPNNAlkvt1NsAck1%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;1394&quot; height=&quot;402&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;402&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;입과 포기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 우테코 최종코테 이전에 소프티어 부트캠프 최종 합격발표가 있었고, 그때부터 김칫국이었지만 고민이 시작되었다... 그리고 우테코를 최종합격하게 되면서 현실이 되었다 ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 고민 끝에 소프티어 부트캠프의 경우 졸업요건 제한이 있어 재지원할 수 없다는 점이 걸려 우테코를 포기하게 되었다   두 부트캠프 모두 재수 후 합격하였고, 합격까지 많은 노력을 들였기에 너무 아까웠지만..! 할 수 있는건 많으니 후회하지 않도록 시간을 알차게 써봐야겠다 ⏰&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n4tKY/btsLBhPwZmq/WPXYK7Ed3xBV6Xu5fF1u11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n4tKY/btsLBhPwZmq/WPXYK7Ed3xBV6Xu5fF1u11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n4tKY/btsLBhPwZmq/WPXYK7Ed3xBV6Xu5fF1u11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn4tKY%2FbtsLBhPwZmq%2FWPXYK7Ed3xBV6Xu5fF1u11%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;438&quot; height=&quot;174&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;294&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;</description>
      <category>개발일기</category>
      <category>우테코</category>
      <author>햄oOoOo</author>
      <guid isPermaLink="true">https://hamo0.tistory.com/94</guid>
      <comments>https://hamo0.tistory.com/94#entry94comment</comments>
      <pubDate>Mon, 30 Dec 2024 14:17:53 +0900</pubDate>
    </item>
  </channel>
</rss>