<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Santos의 개발블로그</title>
    <link>https://sangcho.tistory.com/</link>
    <description>Web을 공부하고 있습니다. </description>
    <language>ko</language>
    <pubDate>Sun, 21 Jun 2026 08:32:41 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Santos</managingEditor>
    <image>
      <title>Santos의 개발블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/3444176/attach/1f7a21a01d3b4ff088db4cb1bbb33a32</url>
      <link>https://sangcho.tistory.com</link>
    </image>
    <item>
      <title>가상기억장치</title>
      <link>https://sangcho.tistory.com/entry/%EA%B0%80%EC%83%81%EA%B8%B0%EC%96%B5%EC%9E%A5%EC%B9%98</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf21jk/btqBikhMMXO/NgRL9JvXrI5wkDrtonDtvK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf21jk/btqBikhMMXO/NgRL9JvXrI5wkDrtonDtvK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf21jk/btqBikhMMXO/NgRL9JvXrI5wkDrtonDtvK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf21jk%2FbtqBikhMMXO%2FNgRL9JvXrI5wkDrtonDtvK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1280&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;!-- 중간광고 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;등장 배경&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;컴퓨터 시스템을 이용하여 어떠한 작업을 하기 위해서는 작업을 위한 프로그램과 필요한 데이터가 주기억장치에 저장되어야한다. 주기억장치의 용량은 크면 클수록 좋은데, 충분한 기억용량을 가진 주기억장치는 비싸기 떄문에 경제적이지 못하다는 커다란 단점이 존재하다. 이런 단점을 보완하기 위해 고안된 것이 가상기억장치이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가상기억장치&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;보조 기억장치와 같이 기억용량이 큰 기억장치를 마치 주기억장치처럼 사용하는 것&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;!-- 중간광고 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 가상기억장치의 목적&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;주기억장치의 기억용량이 부족한 점을 개선하기 위하여 비트당 가격과 기억용량이 보조기억장치와 같으며, 속도가 주기억장치와 같은 기억장치를 제공받는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 가상기억장치 개념도&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lh3Er/btqBg8h13P3/IhgDmJeHs3ore2KNLpkHyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lh3Er/btqBg8h13P3/IhgDmJeHs3ore2KNLpkHyk/img.png&quot; data-alt=&quot;- 가상기억장치 개념도 -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lh3Er/btqBg8h13P3/IhgDmJeHs3ore2KNLpkHyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flh3Er%2FbtqBg8h13P3%2FIhgDmJeHs3ore2KNLpkHyk%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;635&quot; height=&quot;317&quot; data-origin-width=&quot;635&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- 가상기억장치 개념도 -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;중앙처리장치가 접근하려는 정보가 보조기억장치에 저장되어 있더라도 주기억장치에 대한 접근을 통하여 그 정보를 얻을 수 있는데, 원하는 정보를 얻기 위해서는 그 정보를 보조기억장치에서 주기억장치로 미리 예측하여 옮겨놓아야 한다. 이는 기억장치 접근의 지역성에 근거하고 있다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;b&gt; 접근의 지역성 &lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;시간 지역성:&lt;/span&gt;&lt;/b&gt; 최근에 참조된 주소의 내용은 곧 다음에도 참조되는 특성을 말한다.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;공간 지역성:&lt;/span&gt; &lt;/b&gt;실제 프로그램이 참조된 주소와 인접한 주소의 내용이 다시 참조되는 특성을 말한다.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;3. 가상기억장치의 동작 원리&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0V8iX/btqBf3odLIz/11NIXEYQ6guKoqwyZhnseK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0V8iX/btqBf3odLIz/11NIXEYQ6guKoqwyZhnseK/img.png&quot; data-alt=&quot;- 가상기억공간과 실제기억공간 -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0V8iX/btqBf3odLIz/11NIXEYQ6guKoqwyZhnseK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0V8iX%2FbtqBf3odLIz%2F11NIXEYQ6guKoqwyZhnseK%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;755&quot; height=&quot;573&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;573&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- 가상기억공간과 실제기억공간 -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가상주소: 중앙처리장치에 의해 수행되는 프로그램의 명령어가 사용하는 주소&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제주소(물리주소): 주기억장치에 접근하기 위하여 실제로 주기억장치에 적용하는 주소&lt;/span&gt;&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;784&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzlxVO/btqBg8I7h1S/O9vGOLA052VQ0qL8iX3cMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzlxVO/btqBg8I7h1S/O9vGOLA052VQ0qL8iX3cMk/img.png&quot; data-alt=&quot;- 가상기억장치의 동작원리 -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzlxVO/btqBg8I7h1S/O9vGOLA052VQ0qL8iX3cMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzlxVO%2FbtqBg8I7h1S%2FO9vGOLA052VQ0qL8iX3cMk%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;784&quot; height=&quot;530&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- 가상기억장치의 동작원리 -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실행할 프로그램을 몇 개의 블록으로 나누고, 실제 주기억장치에는 현재 실행되는 프로그램에 필요한&amp;nbsp; 블록만 기억시키고, 나머지 부분은 보조기억장치에 그대로 두었다가 필요시에 주기억장치에 올라간다. 만약 주기억장치에 저장되어 있는 프로그램 블록 중에 필요 없는 블록이 있다면, 다시 보조기억장치로 옮겨진다. 이러한 일련의 작업이 계속 반복되어 진행된다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4. 주소변환표&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가상주소공간을 블록으로 나누어 놓고 주기억장치와 보조기억장치 사이의 정보 이동은 블록 단위로 이루어지는데, 이때 어떤 블록을 주기억장치로 옮길 것인지 결정하는 표&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;*블록 단위의 기본 개념&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;페이지:&lt;/span&gt; &lt;/b&gt;가상주소공간과 주기억장치의 기억공간이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;일정한 크기&lt;/span&gt;&lt;/b&gt;를 갖는 연속된 공간으로 구분된 것&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;세그먼트: 크기가 일정하지 않는&lt;/span&gt;&lt;/b&gt; 연속된 기억공간으로 구분된 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5. 주소 변환 방법&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.25em;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 페이징 기법&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가상기억공간의 프로그램 블록과 실제 기억공간의 프로그램 블록의 크기가 같고, 각 블록의 크기도 모두 동일하게 나눌 때 이 블록을 페이지라 하며 이러한 페이지를 이용하는 방식&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 페이징 기법의 매핑원리&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;862&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wZ8aK/btqBjCCp12m/1r8RwOaZdwvTSTWyHp7ZR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wZ8aK/btqBjCCp12m/1r8RwOaZdwvTSTWyHp7ZR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wZ8aK/btqBjCCp12m/1r8RwOaZdwvTSTWyHp7ZR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwZ8aK%2FbtqBjCCp12m%2F1r8RwOaZdwvTSTWyHp7ZR1%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;862&quot; height=&quot;622&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #ee2323;&quot;&gt;* 중앙처리장치에서 참조하는 가상주소가 13비트라고 가정하겠습니다. 앞의 3비트는 페이지번호, 나머지 10비틑 상대위치를 의미합니다.&lt;/span&gt;&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;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #ee2323;&quot;&gt;* 매핑테이블 첫 번째 영역은 페이지 번호, 두 번째 영역은 주기억장치의 페이지 번호, 세번 째 영역은 저장되어 있는 페이지 위치(주기억장치에 저장되어 있을 때는 1, 보조기억장치에 저장되어 있을때는 0으로 작성)&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(1) CPU에서 필요한 데이터 가상주소의 페이지 번호가 101이므로 가상 기억공간내에 존재하는 매핑 테이블에서 같은 페이지 번호를 찾는다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(2) 매핑 테이블의 세 번째 영역의 값이 1이므로 101번 페이지는 주기억장치에 저장되어 있다는 것을 알 수있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(3) 주기억장치 페이지 번호와 01번과 페이지에서의 상대적인 위치인 가상 주소 값 010101001은 중앙처리장치의 MAR에 전송이 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(4) 주기억장치에 읽기 제어 신호를 보냄으로써 주소가 지정하는 워드의 내용이 MBR에 저장되어 중앙처리장치에 의해 사용된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;2) &lt;span style=&quot;color: #333333;&quot;&gt;페이징 기법의 &lt;/span&gt;유의할 점&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가상 주소를 실제주소로 변환했을 때 필요한 페이지가 주기억장치에 없다면 보조기억장치에서 필요한 페이지를 가져온 후 주기억장치에 저장된 페이지 중의 하나와 교체를 해야하는데, 이렇게 필요한 페이지를 주기억장치 내에서 찾지 못하는 경우를 &lt;span style=&quot;color: #ee2323;&quot;&gt;페이지 폴트&lt;/span&gt;라고 한다. &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;페이지 폴트가 자주 일어날수록 페이지를 교체하는 데 시간이 오래 걸려 시스테 효율이 떨어지는 단점이 있다.&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;3) 페이징 기법의 단점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;페이징 기법은 일정한 크기로 페이지를 나누기 때문에 프로그램을 논리적으로 구분하여 나누기가 매우 힘들다. 페이지의 크기를 크게 하면 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;단편화 현상&lt;/span&gt;&lt;/b&gt;이 나타나고, 페이지를 작게하면 페이지 교체가 너무 빈번하게 일어나 시스템 효율이 떨어진다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.25em;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 세그먼트 기법&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;페이징 기법의 문제점을 해결하기 위해 나온 기법으로써, 프로그램의 논리적인 구조에 따라 페이지의 크기를 다양하게 나누는 기법&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;1) 세그먼트 기법의 매핑 원리&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;866&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0kD0d/btqBgeiX0gt/hlVDW4g2HA3vjwgSoJEmxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0kD0d/btqBgeiX0gt/hlVDW4g2HA3vjwgSoJEmxK/img.png&quot; data-alt=&quot;- 세그먼트 기법의 매핑 원리 -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0kD0d/btqBgeiX0gt/hlVDW4g2HA3vjwgSoJEmxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0kD0d%2FbtqBgeiX0gt%2FhlVDW4g2HA3vjwgSoJEmxK%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;866&quot; height=&quot;652&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- 세그먼트 기법의 매핑 원리 -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 세그먼트 기법에서는 가상주소를 논리주소라고도 한다.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 세그먼트 번호 필드는 세그먼트 번호를 지정하고, 페이지 번호 필드는 세그먼트 내의 페이지 번호를 지정, 그리고 상대위피 필드는 해당 페이지 내의 주소를 지정한다.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(1) 논리주소로부터 물리주소로의 매핑은 논리주소의 세그먼트 번호를 이용하여 세그먼트 테이블의 값과 페이지 번호를 더하여 페이지 테이블의 시작주소를 얻는 것부터 시작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(2) 페이지 테이블 첫 번째 영역에는 페이지 테이블의 시작주소가 저장되어 있고, 두 번째 영역에는 주기억장치의 페이지 번호가 저장되어 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(3) 페이지 테이블의 시작주소를 이용하여 주기억장치의 페이지 번호를 얻고, 논리주소의 상대위치를 결합하면 주기억장치의 접근할 수 있는 물리주소를 얻을 수 있다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;2) 세그먼트 기법의 단점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;페이징 기법에서는 하나의 맵핑 테이블로 운영이 되었지만, 세그먼트 기법에서는 두개의 테이블로 운영이 되다보니 메모리 소모가 커지게 되어 성능이 저하 될 가능성이 존재한다. 또한 맵핑 과정 자체가 복잡하다는 단점을 가지고 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;lt;참고자료&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&quot;&gt;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;lt;Computer structures&amp;gt; chapter 14&lt;/span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;기억장치 end&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;</description>
      <category>CS(Computer science)/컴퓨터 구조&amp;amp;운영체제</category>
      <category>가상기억장치</category>
      <category>세그먼트기법</category>
      <category>세그먼트기법의 단점</category>
      <category>세그먼트기법의원리</category>
      <category>페이징기법</category>
      <category>페이징기법의 단점</category>
      <category>페이징기법의원리</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/67</guid>
      <comments>https://sangcho.tistory.com/entry/%EA%B0%80%EC%83%81%EA%B8%B0%EC%96%B5%EC%9E%A5%EC%B9%98#entry67comment</comments>
      <pubDate>Sun, 30 Mar 2025 15:12:10 +0900</pubDate>
    </item>
    <item>
      <title>프로세스 관리</title>
      <link>https://sangcho.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B4%80%EB%A6%AC</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VsVOO/btqAVIwm3oe/bJ2DwVpaULUBZ31UxKKEC1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VsVOO/btqAVIwm3oe/bJ2DwVpaULUBZ31UxKKEC1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VsVOO/btqAVIwm3oe/bJ2DwVpaULUBZ31UxKKEC1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVsVOO%2FbtqAVIwm3oe%2FbJ2DwVpaULUBZ31UxKKEC1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1280&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&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;1369&quot; data-origin-height=&quot;858&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEFzjA/btqAQ2DxCVq/ykCDn9a4FhPPrMWyP9moU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEFzjA/btqAQ2DxCVq/ykCDn9a4FhPPrMWyP9moU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEFzjA/btqAQ2DxCVq/ykCDn9a4FhPPrMWyP9moU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEFzjA%2FbtqAQ2DxCVq%2FykCDn9a4FhPPrMWyP9moU0%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;1369&quot; height=&quot;858&quot; data-origin-width=&quot;1369&quot; data-origin-height=&quot;858&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;작업(Job) / 프로그램&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실행할 프로그램과 데이터를 합친 것으로써 컴퓨터 시스템에 실행 요청 전의 상태를 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로세스(Process)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로그램 실행을 위해 시스템(커널)에 등록되고 시스템 성능 향상을 위해 커널에 의해 관리되는 상태를 말한다. 각종 자원들을 요청하고 할당을 받을 수 있으며, 실행 중인 프로그램이라고도 불리운다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;자원&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;커널의 관리하에 프로세스에게 할당되거나 반납되는 수동적인 개체를 말한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;PCB(Process Control Block)&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;OS가 프로세스 관리에 필요한 정보들을 저장하는 공간으로써 프로세스가 생성시 동시에 만들어진다. PCB안에는 하나의 프로세스의 정보가 담긴다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. PCB에 저장되는 정보(Process Metadata)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. PID(Process Identification Number)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 스케줄링 정보&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 프로세스 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;라. 메모리 관리 정보&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;마. 입출력 상태 정보&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;바. Context save area&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;사. 계정 정보&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. PCB의 관리 방법&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. Linked List를 사용하여 관리&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 주소값으로 연결이 이루어진 연결리스트이므로 삽입, 삭제가 용이&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3. PCB가 필요한 이유&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;CPU에서는 프로세스의 상태에 따라 교체작업이 계속적으로 이루어지는데, 다시 수행 할 대기 중인 프로세스에 관한 값을 PCB에 저장함으로써, 프로세스 관리를 효율적으로 할 수 있게 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로세스 실행 순서&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로그램 실행 --&amp;gt; 프로세스 생성 --&amp;gt; 프로세스 주소공간에 코드, 데이터, 스택 생성 --&amp;gt; 프로세스 메타데이터들을 PCB에 저장&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;!-- 중간광고 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로세스 상태&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. Created &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;665&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ch3GkW/btqASy9sVs3/OoLFeykjrAwqozK7v82Pjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ch3GkW/btqASy9sVs3/OoLFeykjrAwqozK7v82Pjk/img.png&quot; data-alt=&quot;- Created State -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ch3GkW/btqASy9sVs3/OoLFeykjrAwqozK7v82Pjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fch3GkW%2FbtqASy9sVs3%2FOoLFeykjrAwqozK7v82Pjk%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;1324&quot; height=&quot;665&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Created State -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 작업을 커널에 등록&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. PCB 할 및 프로세스 생성&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. Ready 또는 Suspended Ready&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. Ready &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eHFXGi/btqATf9DKoX/enTiafr37M9QWd3tPoKZxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eHFXGi/btqATf9DKoX/enTiafr37M9QWd3tPoKZxk/img.png&quot; data-alt=&quot;- Ready State -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eHFXGi/btqATf9DKoX/enTiafr37M9QWd3tPoKZxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeHFXGi%2FbtqATf9DKoX%2FenTiafr37M9QWd3tPoKZxk%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;1208&quot; height=&quot;638&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Ready State -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 프로세서 외에 다른 모든 자원을 할당 받은 상태&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 프로세서 할당 대기 상태&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 즉시 실행 가능 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3. Running &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1269&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biAkzc/btqAUvElbex/kkYkh0zwD1EiUG2dp3uSBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biAkzc/btqAUvElbex/kkYkh0zwD1EiUG2dp3uSBK/img.png&quot; data-alt=&quot;- Running&amp;amp;nbsp; state -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biAkzc/btqAUvElbex/kkYkh0zwD1EiUG2dp3uSBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiAkzc%2FbtqAUvElbex%2FkkYkh0zwD1EiUG2dp3uSBK%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;1269&quot; height=&quot;814&quot; data-origin-width=&quot;1269&quot; data-origin-height=&quot;814&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Running&amp;nbsp; state -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 프로세서와 필요한 자원을 모두 할당 받은 상태&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) Preemption&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; - Running &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;----&amp;gt; Ready &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; - 프로세서 스케줄링 -&amp;gt; Time out, Priority Changes&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 2) Block/Sleep&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;- Running &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;-----&amp;gt; Asleep &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;- I/O 등 외부에서 자원 할당 요청이 되었을 때 Interrupt 발생&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4. Blocked/Asleep &lt;span style=&quot;color: #333333;&quot;&gt;state&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1431&quot; data-origin-height=&quot;591&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EktQb/btqARxb86DP/KbXlaD1d81WRpcRe5ZOZcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EktQb/btqARxb86DP/KbXlaD1d81WRpcRe5ZOZcK/img.png&quot; data-alt=&quot;- Blocked/Asleep state -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EktQb/btqARxb86DP/KbXlaD1d81WRpcRe5ZOZcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEktQb%2FbtqARxb86DP%2FKbXlaD1d81WRpcRe5ZOZcK%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;1431&quot; height=&quot;591&quot; data-origin-width=&quot;1431&quot; data-origin-height=&quot;591&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Blocked/Asleep state -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 프로세서 외에 다른 자원을 기다리는 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) Wake up&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;- Asleep state ----&amp;gt; Ready state&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5. Suspended state&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFZUHh/btqASyhhTdN/REfSiPjzVOTXBKt4wtrvr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFZUHh/btqASyhhTdN/REfSiPjzVOTXBKt4wtrvr1/img.png&quot; data-alt=&quot;- Suspended state -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFZUHh/btqASyhhTdN/REfSiPjzVOTXBKt4wtrvr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFZUHh%2FbtqASyhhTdN%2FREfSiPjzVOTXBKt4wtrvr1%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;1402&quot; height=&quot;642&quot; data-origin-width=&quot;1402&quot; data-origin-height=&quot;642&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Suspended state -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 메모리를 할당 받지 못한 상태&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 메모리 이미지를 Swap device( ex) 하드디스크 )에 보관&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;6. Terminated/Zombie state&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0YGaE/btqASz8kGDC/MVF8lgrgeIOI6eA1ct8LD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0YGaE/btqASz8kGDC/MVF8lgrgeIOI6eA1ct8LD1/img.png&quot; data-alt=&quot;- Terminated/Zombie state -&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0YGaE/btqASz8kGDC/MVF8lgrgeIOI6eA1ct8LD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0YGaE%2FbtqASz8kGDC%2FMVF8lgrgeIOI6eA1ct8LD1%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;1014&quot; height=&quot;228&quot; data-origin-width=&quot;1014&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;- Terminated/Zombie state -&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 프로세스 수행이 끝난 상태&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 모든 자원을 반납 후 커널 내에 일부 PCB정보만 남아 있는 상태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로세스의 상태 정리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;611&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf5oXJ/btqAUvdkmSP/VlwpDbBKrFVdIRHZnrPAK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf5oXJ/btqAUvdkmSP/VlwpDbBKrFVdIRHZnrPAK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf5oXJ/btqAUvdkmSP/VlwpDbBKrFVdIRHZnrPAK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf5oXJ%2FbtqAUvdkmSP%2FVlwpDbBKrFVdIRHZnrPAK1%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;1353&quot; height=&quot;611&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;611&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;lt;참고자료&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&quot;&gt;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;lt;Computer structures&amp;gt; chapter 6&lt;/span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt; 프로세서 관리 &lt;/span&gt;end&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS(Computer science)/컴퓨터 구조&amp;amp;운영체제</category>
      <category>PCB</category>
      <category>자원</category>
      <category>프로그램</category>
      <category>프로세스</category>
      <category>프로세스관리</category>
      <category>프로세스상태</category>
      <category>프로세스컨트롤블럭</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/53</guid>
      <comments>https://sangcho.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B4%80%EB%A6%AC#entry53comment</comments>
      <pubDate>Sun, 16 Mar 2025 15:40:42 +0900</pubDate>
    </item>
    <item>
      <title>프로세스 스케줄링</title>
      <link>https://sangcho.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MiF2R/btqAWw3D33t/Wk2soIKr9KchkMmlhfPg7K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MiF2R/btqAWw3D33t/Wk2soIKr9KchkMmlhfPg7K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MiF2R/btqAWw3D33t/Wk2soIKr9KchkMmlhfPg7K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMiF2R%2FbtqAWw3D33t%2FWk2soIKr9KchkMmlhfPg7K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1280&quot; data-filename=&quot;artificial-intelligence-3382507_1920.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;프로세스 스케줄링&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;- CPU를 사용하려고 하는 프로세스들 사이의 우선순위를 관리하는 일이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;- CPU가 쉬지 않고, 계속 열심히 일할 수 있도로고 효율적인 계획을 잡아주는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;!-- 중간광고 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;스케줄링의 목적&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;1. 시스템의 성능 향상&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 가. CPU 처리율과 이용률 증가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 나. 오버헤드 최소화&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 다. 응답시간, 대기시간, 반환시간 최소화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;2. 목적에 맞는 지표를 고려하여 스케줄링 기법을 선택하는 것이 필요&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;스케줄링 기준&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;1. 우선순위 &lt;span style=&quot;color: #ee2323;&quot;&gt;ex) CPU &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Burst &lt;/span&gt;&lt;/b&gt;vs IO Burst(I/O 사용시간)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;2. 긴급성&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;3. 특성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;!-- 중간광고 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;스케줄링 단계&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;1. Long-term 스케줄링&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 어떤 프로세스를 커널에 등록할 것인가를 결정하는 스케줄링&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;649&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btFTFc/btqAVGTdicZ/KZ0gKmWJwk89MTHOEkQTak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btFTFc/btqAVGTdicZ/KZ0gKmWJwk89MTHOEkQTak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btFTFc/btqAVGTdicZ/KZ0gKmWJwk89MTHOEkQTak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtFTFc%2FbtqAVGTdicZ%2FKZ0gKmWJwk89MTHOEkQTak%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;1352&quot; height=&quot;649&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;649&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;2. Mid-term 스케줄링&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 어떤 프로세스에게 메모리를 할당할 것인가를 결정하는 스케줄링&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czzb7F/btqAVIjbAnz/K9MX7K46bc4cyrsH8GJfq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czzb7F/btqAVIjbAnz/K9MX7K46bc4cyrsH8GJfq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czzb7F/btqAVIjbAnz/K9MX7K46bc4cyrsH8GJfq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczzb7F%2FbtqAVIjbAnz%2FK9MX7K46bc4cyrsH8GJfq0%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;1348&quot; height=&quot;637&quot; data-origin-width=&quot;1348&quot; data-origin-height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;3. Short-term 스케줄링&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 어떤 프로세스에게 CPU를 할당할 것인가를 결정하는 스케줄링&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B97Ty/btqAUu6L6YW/YzWBRb9rphROr5FaFoU6kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B97Ty/btqAUu6L6YW/YzWBRb9rphROr5FaFoU6kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B97Ty/btqAUu6L6YW/YzWBRb9rphROr5FaFoU6kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB97Ty%2FbtqAUu6L6YW%2FYzWBRb9rphROr5FaFoU6kk%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;1260&quot; height=&quot;694&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;스케줄링 선점&amp;amp;비선점&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;스케줄링은 적용 시점에 따라 선점과 비선점형으로 구분한다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 선점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;다른 프로세스가 선점한 자원을 빼앗아 갈 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 타의에 의해 선점한 자원을 빼앗길 수가 있다.&lt;i&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; ex) 할당시간이 종료, 우선순위가 높은 프로세스의 등장&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. Context switch overhead가 크다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 시분할 시스템, 리얼타임 시스템에 적합한 방법이다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 비선점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;다른 프로세스가 선점한 자원을 빼앗아 갈 수 없다. &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 할당자원을 스스로 반납할때까지 사용한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. &lt;span style=&quot;color: #333333;&quot;&gt;Context switch overhead가 적다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 잦은 우선순위 역전, 평균 응답시간이 증가한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;스케줄링의 우선순위&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;프로세스의 우선순위 변동 여부에 따라 정적 스케줄링과 동적 스케줄링으로 구분한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;1. 정적 우선순위&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 프로세스에 부여된 우선순위가 바뀌지 않는다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 구현이 쉽고 Overhead가 적다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 시스템 환경 변화에 대한 대응이 어렵다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;2. 동적 우선순위 &lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. 스케줄링 과정에서 프로세스의 우선순위를 변동시킨다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;나. 구현이 복잡하고, Overhead가 크다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. 시스템 환경 변화에 유연하게 대응이 가능하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;스케줄링 기법&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;스케줄링 기법은 선점형과 비선점형 스케줄링으로 나뉜다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 비선점형 스케줄링&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;가. FIFO(FCFS) - First In First Out&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 선입선출 방식(먼저 들어오면 먼저 나가는 방식)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 2) 우선순위에 상관없이 먼저 도착한 프로세스를 먼저 처리한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 3) FIFO 단점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) 긴 평균 응답시간&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;나) Convey effect 발생&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Convey effect: 수행시간이 긴 프로세스에 의해 다른 프로세스들이 긴 대기시간을 갖게 되는 현상 &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;(대기시간 &amp;gt; 실행시간)&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &lt;b&gt;&lt;i&gt;나. SJF(SPN) - Shorst Job First&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;1) CPU점유 시간이 가장 짧은 프로세스에 CPU를 먼저 할당하는 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;2) SJF의 장점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; 가) 평균 대기시간 최소화&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; 나) 시스템 내 프로세스 수 최소화&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; 다) 메모리 절약 -&amp;gt; 시스템 효율 향상&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;3) SJF의 단점&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; 가) Starvation(무한대기) 현상 발생&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Starvation(무한대기): &lt;span style=&quot;color: #333333;&quot;&gt;CPU점유&lt;/span&gt;시간이 긴 프로세스가 짧은 프로세스에게 계속 밀려 자원을 할당 받지 못하는 상태&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; 나) 정확한 실행시간을 알 수 없음&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &lt;i&gt;&lt;b&gt;다. HRN - Highest Response-ratio Next)&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;1) SJF기법을 보완하기 위한 것으로 대기 시간과 실행 시간을 이용하여 처리하는 방식이다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;2) Response-ratio의 에이징 기법을 이용하여 우선순위를 계산하여 우선순위가 높은 것부터 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;Response-ratio: 우선순위 = (대기시간+실행시간) / 실행시간&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;에이징 기법: 프로세스 자원을 기다리고 있는 시간에 비례하여 우선순위를 부여함으로써 무기한 연기의 문제를 방지하는 기법을 말한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;3) HRN의 장점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;가) Starvation 방지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;4) HRN의 단점&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;가) 실행시간 예측 불가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 선점형 스케줄링&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;가. RR - Round Robin&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 프로세스들 사이에 우선순위를 두지 않고, 순서대로 시간단위로 CPU를 할당하는 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 2) 자원 사용에 제한된 시간이 있으며 할당된 시간이 지나면 자원을 반납(Time Quantum)해야 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 3) 실시간 시스템에 유리하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 4) RR의 장점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) 특정 프로세스의 자원 독점을 방지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 5) RR의 단점&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) Context Switch Overhead가 큼&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;b&gt;나. SRTN - Shortest-Remaining Time Next)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 비선점 스케줄링인 SJF기법을 선점형태로 변경한 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 2) SJF기법과 마찬가지로 CPU점유 시간이 가장 짧은 프로세스에 CPU를 먼저 할당하는 방식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 3) 만약 중요한 프로세스가 있으면 점유시간이 길어도 먼저 실행시킬 수 있는 권한이 추가되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 4) SRTN의 장점&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) SJF 기법의 장점 극대화 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 5) SRTN의 단점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) Context Switch Overhead가 큼&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;다. MLQ - Multi-Level Queue&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) 프로세스를 특정 그룹으로 분류할 수 있을 경우 그룹에 따라 각기 다른 Ready Queue를 사용하는 방법이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; 2) 각각의 Ready Queue는 자신만의 스케줄링 기법을 사용하되, 최초 배정된 Queue를 벗어나지 못한다.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 3) 각각의 Ready Queue 사이에는 우선순위 기반의 스케줄링이 적용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;ex) QueueA가 모두 완료되어야 QueueB의 작업이 실행된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 4) MLQ의 단점&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) 여러개의 큐를 관리해야 하기 때문에 스케줄링 Overhead가 발생하기 쉬움&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;나) 우선순위가 낮은 Queue는 Starvation 현상이 발생&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;라. MFQ - Multi-Level Feedback Queue&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 1) MLQ에서 최초 배정된 Queue를 벗어나지 못하는 기법을 보완하여 프로세스 Queue들 간의 이동이 허용될 수 있도록 개선한 기법이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 2) Feedback을 통해 우선순위를 조정한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;Feedback: 현재까지의 프로세서가 사용되었던 정보(패턴)들을 활용&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; 3) Feedback의 장점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) 프로세스에 대한 사전 정보없이 SJF, SRTN, HRN 기법의 효과를 볼 수 있음&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; 4) Feedback의 단점&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;가) 설계 및 구현이 복잡&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;나) 우선순위가 낮은 큐는 Starvation 현상 발생&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp; &amp;nbsp;다) 스케줄링 Overhead가 큼&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Light';&quot;&gt;스케줄링 기법 정리&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1397&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/03Jyw/btqAVHxRNVS/kL6CL1CnNeOOhSU77RipnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/03Jyw/btqAVHxRNVS/kL6CL1CnNeOOhSU77RipnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/03Jyw/btqAVHxRNVS/kL6CL1CnNeOOhSU77RipnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F03Jyw%2FbtqAVHxRNVS%2FkL6CL1CnNeOOhSU77RipnK%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;1397&quot; height=&quot;510&quot; data-origin-width=&quot;1397&quot; data-origin-height=&quot;510&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;lt;참고자료&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&quot;&gt;https://www.youtube.com/watch?v=EdTtGv9w2sA&amp;amp;list=PLBrGAFAIyf5rby7QylRc6JxU5lzQ9c4tN&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;lt;Computer structures&amp;gt; chapter 7&lt;/span&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;프로세서 스케줄링&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;end&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;</description>
      <category>CS(Computer science)/컴퓨터 구조&amp;amp;운영체제</category>
      <category>FIFO</category>
      <category>hrn</category>
      <category>MFQ</category>
      <category>MLQ</category>
      <category>sjf</category>
      <category>SRTN</category>
      <category>라운드로빈</category>
      <category>스케줄링기법</category>
      <category>스케줄링목적</category>
      <category>프로세스스케줄링</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/54</guid>
      <comments>https://sangcho.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81#entry54comment</comments>
      <pubDate>Sat, 1 Mar 2025 09:14:44 +0900</pubDate>
    </item>
    <item>
      <title>4 React Tips to Instantly Improve Your Code</title>
      <link>https://sangcho.tistory.com/entry/4-React-Tips-to-Instantly-Improve-Your-Code</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnvQod/btsMlG0QU1r/IXSPI8lkGbYBlegyRdLkik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnvQod/btsMlG0QU1r/IXSPI8lkGbYBlegyRdLkik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnvQod/btsMlG0QU1r/IXSPI8lkGbYBlegyRdLkik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnvQod%2FbtsMlG0QU1r%2FIXSPI8lkGbYBlegyRdLkik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;514&quot; height=&quot;289&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 이 글은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;4 React Tips to Instantly Improve Your Code&lt;/a&gt;&lt;/span&gt;를 번역하였습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1739665456526&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;4 React Tips to Instantly Improve Your Code&quot; data-og-description=&quot;Solid knowledge of React is one of the most valuable skills for a front-end developer. Many companies are constantly searching for React&amp;hellip;&quot; data-og-host=&quot;javascript.plainenglish.io&quot; data-og-source-url=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; data-og-url=&quot;https://javascript.plainenglish.io/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bG6dDk/hyYfZ9eOr7/CpVWs44RMCOsWDlSjkRIv1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380&quot;&gt;&lt;a href=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bG6dDk/hyYfZ9eOr7/CpVWs44RMCOsWDlSjkRIv1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380');&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;4 React Tips to Instantly Improve Your Code&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Solid knowledge of React is one of the most valuable skills for a front-end developer. Many companies are constantly searching for React&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;javascript.plainenglish.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 핸들러에서 함수 반환하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핸들러에서 함수(예: 커링 기법)를 반환하여 중복 코드를 줄이고 효율성을 높일 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;export default function App() {
  const [user, setUser] = useState({
    name: &quot;&quot;,
    surname: &quot;&quot;,
    address: &quot;&quot;
  });

  const handleInputChange = (field) =&amp;gt; {
    return (e) =&amp;gt; {
      setUser((prev) =&amp;gt; ({
        ...prev,
        [field]: e.target.value
      }));
    };
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;input value={user.name} onChange={handleInputChange(&quot;name&quot;)} /&amp;gt;
      &amp;lt;input value={user.surname} onChange={handleInputChange(&quot;surname&quot;)} /&amp;gt;
      &amp;lt;input value={user.address} onChange={handleInputChange(&quot;address&quot;)} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 책임 분리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 독립적인 서브 모듈로 나누어 관리하기 쉽게 만듭니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UI 모듈: 시각적 표현 담당&lt;/li&gt;
&lt;li&gt;로직/모델 모듈: 비즈니스 로직 포함 (예: 커스텀 훅)&lt;/li&gt;
&lt;li&gt;라이브러리 모듈: 컴포넌트에 필요한 유틸리티 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;// utils.js
export async function getList(onSuccess) {
  try {
    const resp = await fetch(&quot;https://www.url.com/list&quot;);
    const data = await resp.json();
    onSuccess(data);
  } catch {
    showAlert({ text: &quot;Something went wrong!&quot; });
  }
}

export async function deleteListItem(id, onSuccess) {
  try {
    await fetch(`https://www.url.com/list/${id}`, { method: &quot;DELETE&quot; });
    onSuccess();
  } catch {
    showAlert({ text: &quot;Something went wrong!&quot; });
  }
}

export function trimName(name) {
  return name.slice(0, 30) + (name.length &amp;gt; 30 ? &quot;...&quot; : &quot;&quot;);
}

// hooks.js
export function useList() {
  const [list, setList] = useState([]);

  const handleDeleteItem = useCallback((id) =&amp;gt; {
    return () =&amp;gt; {
      deleteListItem(id, () =&amp;gt; {
        setList((prev) =&amp;gt; prev.filter((x) =&amp;gt; x.id !== id));
      });
    };
  }, []);

  useEffect(() =&amp;gt; {
    getList(setList);
  }, []);

  return useMemo(() =&amp;gt; ({
    list,
    handleDeleteItem
  }), [list, handleDeleteItem]);
}

// ListComponent.js
export function ListComponentItem({ name, onDelete }) {
  return (
    &amp;lt;div className=&quot;list-component__item&quot;&amp;gt;
      {trimName(name)}
      &amp;lt;div onClick={onDelete} className=&quot;list-component__icon&quot;&amp;gt;
        &amp;lt;DeleteIcon /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export function ListComponent() {
  const { list, handleDeleteItem } = useList();

  return (
    &amp;lt;div className=&quot;list-component&quot;&amp;gt;
      {list.map(({ id, name }) =&amp;gt; (
        &amp;lt;ListComponentItem
          key={id}
          name={name}
          onDelete={handleDeleteItem(id)}
        /&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 조건문 대신 객체 맵 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건문을 객체 맵으로 대체하여 코드 가독성을 높이고 유지보수를 용이하게 만듭니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const ACCOUNTS_MAP = {
  'vip': VipAccount,
  'usual': UsualAccount,
  'admin': AdminAccount,
  'moderator': ModeratorAccount,
};

function Account({type}) {
  const Component = ACCOUNTS_MAP[type];

  return (
    &amp;lt;div className='account'&amp;gt;
      &amp;lt;Component /&amp;gt;
      &amp;lt;AccountStatistics /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 독립 변수는 React 생명주기 외부에 배치하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 컴포넌트 생명주기 메서드를 필요로 하지 않는 논리를 컴포넌트 외부로 분리하여 코드 가독성을 개선합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const DEFAULT_ITEMS = [1, 2, 3, 4, 5];

const toggleArrayItem = (arr, val) =&amp;gt; {
  return arr.includes(val) ? arr.filter(el =&amp;gt; el !== val) : [...arr, val];
}

function useItemsList() {
  const [items, setItems] = useState(DEFAULT_ITEMS);

  const handleToggleItem = (num) =&amp;gt; {
    return () =&amp;gt; {
      setItems(toggleArrayItem(items, num));
    }
  }

  return {
    items,
    handleToggleItem,
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&amp;lt; 참고자료 &amp;gt;&lt;/b&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;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;[사이트] # Medium&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739665672360&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;4 React Tips to Instantly Improve Your Code&quot; data-og-description=&quot;Solid knowledge of React is one of the most valuable skills for a front-end developer. Many companies are constantly searching for React&amp;hellip;&quot; data-og-host=&quot;javascript.plainenglish.io&quot; data-og-source-url=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; data-og-url=&quot;https://javascript.plainenglish.io/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bG6dDk/hyYfZ9eOr7/CpVWs44RMCOsWDlSjkRIv1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380&quot;&gt;&lt;a href=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/@pashkapag/4-react-tips-to-instantly-improve-your-code-7456e028cfa3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bG6dDk/hyYfZ9eOr7/CpVWs44RMCOsWDlSjkRIv1/img.png?width=680&amp;amp;height=380&amp;amp;face=0_0_680_380');&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;4 React Tips to Instantly Improve Your Code&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Solid knowledge of React is one of the most valuable skills for a front-end developer. Many companies are constantly searching for React&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;javascript.plainenglish.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;lt;React&amp;gt; 4&amp;nbsp;React&amp;nbsp;Tips&amp;nbsp;to&amp;nbsp;Instantly&amp;nbsp;Improve&amp;nbsp;Your&amp;nbsp;Code&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Language &amp;amp; Framework &amp;amp; Library/React</category>
      <category>React</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/164</guid>
      <comments>https://sangcho.tistory.com/entry/4-React-Tips-to-Instantly-Improve-Your-Code#entry164comment</comments>
      <pubDate>Sun, 16 Feb 2025 09:28:25 +0900</pubDate>
    </item>
    <item>
      <title>Placeholder and Initial data in react query</title>
      <link>https://sangcho.tistory.com/entry/Placeholder-and-Initial-data-in-react-query</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf7a73/btsL4rc4lbK/aQnM0uKru5Wk6egIKQSa7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf7a73/btsL4rc4lbK/aQnM0uKru5Wk6egIKQSa7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf7a73/btsL4rc4lbK/aQnM0uKru5Wk6egIKQSa7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf7a73%2FbtsL4rc4lbK%2FaQnM0uKru5Wk6egIKQSa7K%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;321&quot; height=&quot;204&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;179&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;* 이글은&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Placeholder and Initial data in react query&lt;/span&gt;를 번역하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738496873031&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;Placeholder and Initial Data in React Query&quot; data-og-description=&quot;Learn about the different possibilities to avoid loading spinners in React Query.&quot; data-og-host=&quot;tkdodo.eu&quot; data-og-source-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; data-og-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mAQfC/hyYcfwBV7A/twTXknvdk2v1wINPjnbm0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/dh0MEJ/hyYcdZRO1i/F0XnQsPrV1p9D38ibTXzhk/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/cs4FZy/hyYcjZ5cA0/gIjCY8KndhV1n8nJ4k64v1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480&quot;&gt;&lt;a href=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mAQfC/hyYcfwBV7A/twTXknvdk2v1wINPjnbm0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/dh0MEJ/hyYcdZRO1i/F0XnQsPrV1p9D38ibTXzhk/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/cs4FZy/hyYcjZ5cA0/gIjCY8KndhV1n8nJ4k64v1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480');&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;Placeholder and Initial Data in React Query&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Learn about the different possibilities to avoid loading spinners in React Query.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tkdodo.eu&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;대부분의 경우 귀찮은 로딩 스피너를 싫어합니다. 때로는 로딩 스피너가 필요하지만, 가능한 한 이를 피하고 싶습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;React Query는 이미 많은 상황에서 로딩 스피너를 없앨 수 있는 도구를 제공합니다. 백그라운드에서 업데이트가 진행되는 동안 캐시에서 오래된 데이터를 얻을 수 있고, 나중에 필요할 데이터를 미리 가져올 수 있으며, 쿼리 키가 변경될 때 이전 데이터를 유지해 불필요한 로딩 상태를 방지할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;또 다른 방법은 우리의 사용 사례에 맞을 가능성이 있는 데이터를 동기적으로 미리 캐시에 채워 넣는 것입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;React Query는 이를 위해 두 가지 유사한 접근 방식을 제공합니다. Placeholder Data와 Initial Data입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이들이 공통적으로 가지는 점을 먼저 살펴본 후, 차이점과 어느 상황에서 하나가 다른 것보다 더 적합한지 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Similarities&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이미 언급했듯이, Placeholder Data와 Initial Data는 모두 동기적으로 사용할 수 있는 데이터를 사용해 캐시를 미리 채워 넣는 방법을 제공합니다. 이는 둘 중 하나라도 제공되면, 쿼리가 로딩 상태에 들어가지 않고 바로 성공 상태로 전환된다는 것을 의미합니다. 또한, 둘 다 값 자체일 수도 있고, 값을 반환하는 함수일 수도 있습니다. 값 계산이 비용이 많이 들 때 이러한 방식이 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function Component() {
  // ✅ status will be success even if we have not yet fetched data
  const { data, status } = useQuery({
    queryKey: ['number'],
    queryFn: fetchNumber,
    placeholderData: 23,
  })

  // ✅ same goes for initialData
  const { data, status } = useQuery({
    queryKey: ['number'],
    queryFn: fetchNumber,
    initialData: () =&amp;gt; 42,
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이미 캐시에 데이터가 있는 경우에는 Placeholder Data나 Initial Data 둘 다 효과가 없습니다. 그렇다면 둘 중 하나를 사용하는 것의 차이는 무엇일까요? 이를 이해하려면 React Query의 옵션이 어떻게 작동하는지, 그리고 어떤 &quot;레벨&quot;에서 작동하는지 간단히 살펴봐야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;On Cache level&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;각 &lt;b&gt;Query Key&lt;/b&gt;에 대해 단 하나의 캐시 항목만 존재합니다. 이는 React Query의 강점 중 하나인 데이터를 애플리케이션 내에서 &lt;b&gt;&quot;전역적으로&quot;&lt;/b&gt; 공유할 수 있는 가능성 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우리가 useQuery에 제공하는 몇 가지 옵션은 이 캐시 항목에 영향을 미칩니다. 대표적인 예로 queryFn과 gcTime이 있습니다. 캐시 항목이 하나만 존재하기 때문에, 이러한 옵션들은 해당 항목에 대한 데이터를 어떻게 가져올지 또는 언제 캐시 항목을 제거할지를 결정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;On observer level&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;React Query에서 &lt;b&gt;Observer&lt;/b&gt;는 기본적으로 하나의 캐시 항목에 대한 구독(subscription)을 의미합니다. Observer는 해당 캐시 항목을 감시하며, 항목에 변경이 생길 때마다 정보를 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Observer를 만드는 가장 기본적인 방법은 useQuery를 호출하는 것입니다. 매번 useQuery를 호출할 때마다 Observer가 생성되고, 데이터가 변경되면 해당 컴포넌트가 다시 렌더링됩니다. 즉, 동일한 캐시 항목을 여러 Observer가 감시할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;React Query Devtools에서 Query Key 왼쪽에 표시된 숫자는 해당 Query를 감시하고 있는 Observer의 수를 나타냅니다. 예를 들어, 아래 예시에서는 3개의 Observer가 하나의 Query를 감시하고 있는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWmwrT/btsL3nbqfKH/QvvrNmnGxNDC1CJMUHBaN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWmwrT/btsL3nbqfKH/QvvrNmnGxNDC1CJMUHBaN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWmwrT/btsL3nbqfKH/QvvrNmnGxNDC1CJMUHBaN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWmwrT%2FbtsL3nbqfKH%2FQvvrNmnGxNDC1CJMUHBaN0%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;875&quot; height=&quot;160&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;875&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Observer 레벨&lt;/b&gt;에서 작동하는 몇 가지 옵션에는 select와 refetchInterval이 있습니다. 특히, select 옵션이 데이터 변환에 유용한 이유는 동일한 캐시 항목을 감시하면서도, 각기 다른 컴포넌트에서 해당 데이터의 서로 다른 부분(슬라이스)에 구독할 수 있기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;예를 들어, 여러 컴포넌트가 동일한 Query Key를 사용하는 경우, 각각의 컴포넌트는 select 옵션을 사용해 해당 데이터를 원하는 방식으로 변환하여 사용할 수 있습니다. 이렇게 하면 데이터를 일관되게 캐싱하면서도 각기 다른 컴포넌트에서 필요로 하는 데이터만을 구독하고, 리렌더링을 최적화할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이를 통해 React Query는 동일한 데이터 소스를 사용하면서도 각 컴포넌트가 데이터를 필요한 방식으로 처리하도록 지원합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Differences&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;InitialData가 &lt;b&gt;캐시 레벨&lt;/b&gt;에서 작동하고, placeholderData는 &lt;b&gt;옵저버 레벨&lt;/b&gt;에서 작동한다는 사실은 몇 가지 중요한 차이를 만들어냅니다. 이를 통해 다음과 같은 몇 가지 결과가 나타납니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Persistence&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;InitialData는 캐시에 저장됩니다. 이는 React Query에 &lt;b&gt;&quot;내가 이미 백엔드에서 가져온 것만큼이나 좋은 데이터를 가지고 있다&quot;&lt;/b&gt;는 신호를 주는 방식입니다. 이 데이터는 캐시 레벨에서 동작하기 때문에, 처음 옵저버가 마운트될 때 바로 캐시에 저장됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;따라서 같은 Query Key를 사용하는 다른 옵저버가 다른 initialData로 마운트되더라도, 이미 캐시가 채워졌기 때문에 아무런 변화가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;반면, PlaceholderData는 캐시에 저장되지 않습니다. 일종의 &lt;b&gt;&quot;임시 데이터&quot;&lt;/b&gt;로, 진짜 데이터가 로딩될 때까지 보여주는 데이터라고 생각할 수 있습니다. 이는 옵저버 레벨에서 작동하기 때문에, 여러 컴포넌트에서 서로 다른 placeholderData를 사용할 수 있습니다. 다시 말해, 컴포넌트마다 다른 임시 데이터를 보여줄 수 있지만, 캐시는 영향을 받지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Background refetches&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;placeholderData를 사용할 때는 옵저버가 처음 마운트될 때 항상 백그라운드에서 리패치가 이루어집니다. 왜냐하면 placeholderData는 &lt;b&gt;&quot;실제 데이터&quot;&lt;/b&gt;가 아니기 때문입니다. React Query는 이 &lt;b&gt;&quot;진짜 데이터&quot;&lt;/b&gt;를 가져와야 한다고 판단하고, 로딩하는 동안 useQuery에서 isPlaceholderData 플래그를 반환합니다. 이 플래그를 사용하여 사용자에게 현재 보여지는 데이터가 placeholderData임을 시각적으로 알릴 수 있습니다. 실제 데이터가 도착하면 이 플래그는 false로 전환됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;반면, initialData는 캐시에 유효한 데이터로 저장되기 때문에 &lt;b&gt;staleTime&lt;/b&gt; 설정을 따릅니다. 기본적으로 staleTime이 0이면, 백그라운드에서 리패치가 발생합니다. 그러나 만약 staleTime을 예를 들어 30초로 설정했다면, React Query는 initialData를 보고 &lt;b&gt;&quot;이 데이터는 아직 유효하다&quot;&lt;/b&gt;고 판단하고, staleTime이 지나기 전까지는 리패치를 하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;만약 initialData가 생성된 시점에 따라 리패치를 조정하고 싶다면, initialDataUpdatedAt 옵션을 제공할 수 있습니다. 이를 통해 React Query에게 해당 initialData가 언제 생성되었는지 알려줄 수 있으며, 백그라운드 리패치가 이 정보를 고려하여 발생하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;특히, 기존 캐시 항목에서 initialData를 사용할 때, dataUpdatedAt 타임스탬프를 활용하여 리패치 트리거를 보다 정확하게 제어할 수 있습니다. 이를 통해 리패치 타이밍을 세밀하게 조정할 수 있어, 데이터를 효율적으로 관리하는 데 매우 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const useTodo = (id) =&amp;gt; {
  const queryClient = useQueryClient()

  return useQuery({
    queryKey: ['todo', id],
    queryFn: () =&amp;gt; fetchTodo(id),
    staleTime: 30 * 1000,
    initialData: () =&amp;gt;
      queryClient
        .getQueryData(['todo', 'list'])
        ?.find((todo) =&amp;gt; todo.id === id),
    initialDataUpdatedAt: () =&amp;gt;
      // ✅ will refetch in the background if our list query data
      // is older than the provided staleTime (30 seconds)
      queryClient.getQueryState(['todo', 'list'])?.dataUpdatedAt,
  })
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Error transitions&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;initialData를 제공했을 때&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;initialData는 유효한 데이터로 간주되어 캐시에 저장됩니다. 백그라운드 리패치가 실패하더라도 쿼리는 &lt;b&gt;&quot;성공&quot;&lt;/b&gt; 상태로 유지되며, UI는 계속해서 initialData를 표시하게 됩니다. React Query는 캐시된 데이터가 여전히 충분히 유효하다고 판단하고, 오류 상태로 전환되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;placeholderData를 제공했을 때&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 경우, placeholderData는 유효하지 않으며 &lt;b&gt;&quot;진짜&quot;&lt;/b&gt; 데이터가 아니기 때문에 리패치가 발생합니다. 리패치가 실패하면 쿼리는 오류 상태로 전환되며, UI는 오류 응답을 표시하게 됩니다(오류 처리가 구현되어 있다면). placeholderData는 임시 데이터이기 때문에 유효한 캐시 데이터로 간주되지 않기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 두 가지는 데이터의 유효성과 캐시 상태를 다르게 처리하는 방식에 따른 차이를 강조합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;When to use what&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;언제 initialData와 placeholderData를 사용하는지는 전적으로 개발자에게 달려 있습니다. 개인적으로, 저는 쿼리에서 미리 데이터를 채울 때 initialData를 사용하고, 그 외의 경우에는 placeholderData를 사용하는 것을 선호합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;initialData는 캐시에 저장되며 데이터를 신뢰할 수 있을 때 적합하고, placeholderData는 임시 데이터를 제공하고 즉시 갱신이 필요한 경우에 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&amp;lt; 참고자료 &amp;gt;&lt;/b&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;&amp;nbsp;&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;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;[사이트] # TkDodo's&amp;nbsp; blog&lt;a style=&quot;background-color: #1a202c; color: #000000; text-align: start;&quot; href=&quot;https://tkdodo.eu/blog&quot;&gt;&lt;br /&gt;&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1738497411061&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;Placeholder and Initial Data in React Query&quot; data-og-description=&quot;Learn about the different possibilities to avoid loading spinners in React Query.&quot; data-og-host=&quot;tkdodo.eu&quot; data-og-source-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; data-og-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mAQfC/hyYcfwBV7A/twTXknvdk2v1wINPjnbm0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/dh0MEJ/hyYcdZRO1i/F0XnQsPrV1p9D38ibTXzhk/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/cs4FZy/hyYcjZ5cA0/gIjCY8KndhV1n8nJ4k64v1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480&quot;&gt;&lt;a href=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mAQfC/hyYcfwBV7A/twTXknvdk2v1wINPjnbm0k/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/dh0MEJ/hyYcdZRO1i/F0XnQsPrV1p9D38ibTXzhk/img.png?width=1200&amp;amp;height=630&amp;amp;face=82_500_123_545,https://scrap.kakaocdn.net/dn/cs4FZy/hyYcjZ5cA0/gIjCY8KndhV1n8nJ4k64v1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480');&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;Placeholder and Initial Data in React Query&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Learn about the different possibilities to avoid loading spinners in React Query.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tkdodo.eu&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;lt;React-query&amp;gt; Placeholder&amp;nbsp;and&amp;nbsp;Initial&amp;nbsp;data&amp;nbsp;in&amp;nbsp;react&amp;nbsp;query&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <category>Caching</category>
      <category>data</category>
      <category>fecth</category>
      <category>Initial</category>
      <category>placeholder</category>
      <category>query</category>
      <category>React</category>
      <category>tanstack</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/163</guid>
      <comments>https://sangcho.tistory.com/entry/Placeholder-and-Initial-data-in-react-query#entry163comment</comments>
      <pubDate>Sun, 2 Feb 2025 21:00:11 +0900</pubDate>
    </item>
    <item>
      <title>What&amp;rsquo;s new in React 19</title>
      <link>https://sangcho.tistory.com/entry/What%E2%80%99s-new-in-React-19</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqTXSo/btsLQZWfzrw/JfHjTVpy3tH9t5iPbdwMJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqTXSo/btsLQZWfzrw/JfHjTVpy3tH9t5iPbdwMJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqTXSo/btsLQZWfzrw/JfHjTVpy3tH9t5iPbdwMJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqTXSo%2FbtsLQZWfzrw%2FJfHjTVpy3tH9t5iPbdwMJK%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;425&quot; height=&quot;238&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* 이글은 &lt;a href=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;What's new in React 19&lt;/a&gt;를 번역하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1737248124322&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;What&amp;rsquo;s new in React 19 - Vercel&quot; data-og-description=&quot;React 19 is near. Here's what to expect and how you can get started deploying React 19 on Vercel.&quot; data-og-host=&quot;vercel.com&quot; data-og-source-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; data-og-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fqnyn/hyX0obsoY7/c2yyH2rBBjfHoNYshgbWr0/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/caqgFy/hyX4ugOeKf/fN3TdbHJpXKs1JKBFEbP9k/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/Hdnfm/hyX4pNjZzU/kkSLcqFd9sDLmUxOpyUkxK/img.png?width=829&amp;amp;height=1264&amp;amp;face=0_0_829_1264&quot;&gt;&lt;a href=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fqnyn/hyX0obsoY7/c2yyH2rBBjfHoNYshgbWr0/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/caqgFy/hyX4ugOeKf/fN3TdbHJpXKs1JKBFEbP9k/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/Hdnfm/hyX4pNjZzU/kkSLcqFd9sDLmUxOpyUkxK/img.png?width=829&amp;amp;height=1264&amp;amp;face=0_0_829_1264');&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;What&amp;rsquo;s new in React 19 - Vercel&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React 19 is near. Here's what to expect and how you can get started deploying React 19 on Vercel.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vercel.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Sever Components&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 컴포넌트는 React가 10년 전 처음 출시된 이후 가장 큰 변화 중 하나입니다. 이들은 React 19의 새로운 기능들의 기반 역할을 하며 다음과 같은 개선을 제공합니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;초기 페이지 로드 시간&lt;/b&gt;: 서버에서 컴포넌트를 렌더링하여 클라이언트로 전송되는 JavaScript의 양을 줄임으로써 초기 로드 속도를 빠르게 합니다. 또한, 페이지가 클라이언트에 전송되기 전에 서버에서 데이터 쿼리를 시작할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;코드 이식성&lt;/b&gt;: 서버 컴포넌트를 사용하면 서버와 클라이언트 모두에서 실행 가능한 컴포넌트를 작성할 수 있어 코드 중복을 줄이고 유지보수성을 개선하며 코드베이스 전체에서 논리를 더 쉽게 공유할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;SEO(검색 엔진 최적화)&lt;/b&gt;: 컴포넌트의 서버 측 렌더링은 검색 엔진과 대형 언어 모델(LLM)이 콘텐츠를 더 효과적으로 크롤링하고 인덱싱할 수 있게 하여 검색 엔진 최적화를 향상시킵니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 컴포넌트의 중요성을 이해하기 위해 React 렌더링의 발전 과정을 간략히 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React는 처음에 클라이언트 사이드 렌더링(CSR)으로 시작하여 사용자에게 최소한의 HTML을 제공했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;root&quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script src=&quot;/static/js/bundle.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;연결된 스크립트에는 React, 서드파티 의존성, 그리고 모든 애플리케이션 코드가 포함됩니다. 애플리케이션이 커질수록 번들 크기도 함께 커졌습니다. JavaScript가 다운로드되고 파싱된 후, React는 빈 div 요소에 DOM 요소들을 로드합니다. 이 과정이 진행되는 동안 사용자가 보는 것은 빈 페이지뿐입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;초기 UI가 마침내 표시되더라도 페이지 콘텐츠는 여전히 비어있어, 로딩 스켈레톤이 인기를 얻게 되었습니다. 그 후 데이터가 페치되고, UI가 두 번째로 렌더링되어 로딩 스켈레톤을 실제 콘텐츠로 대체하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;123.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;893&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4tYbq/btsLSgCHYN0/Z7BoU2ELs2Uzn5L9ZiBWY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4tYbq/btsLSgCHYN0/Z7BoU2ELs2Uzn5L9ZiBWY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4tYbq/btsLSgCHYN0/Z7BoU2ELs2Uzn5L9ZiBWY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4tYbq%2FbtsLSgCHYN0%2FZ7BoU2ELs2Uzn5L9ZiBWY0%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;893&quot; data-filename=&quot;123.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;893&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React는 서버 사이드 렌더링(SSR)을 통해 개선되었으며, 첫 번째 렌더링을 서버로 옮겼습니다. 사용자에게 제공되는 HTML이 더 이상 빈 페이지가 아니었으며, 사용자가 초기 UI를 더 빨리 볼 수 있게 되었습니다. 그러나 실제 콘텐츠를 표시하기 위해 여전히 데이터를 페치해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;export default async function Page() {
  const res = await fetch(&quot;https://api.example.com/products&quot;);
  const products = res.json();
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Products&amp;lt;/h1&amp;gt;
      {products.map((product) =&amp;gt; (
        &amp;lt;div key={product.id}&amp;gt;
          &amp;lt;h2&amp;gt;{product.title}&amp;lt;/h2&amp;gt;
          &amp;lt;p&amp;gt;{product.description}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      ))}
    &amp;lt;/&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용자에게 제공되는 HTML은 첫 번째 렌더링 시 실제 콘텐츠로 완전히 채워져 있으며, 추가로 데이터를 가져오거나 두 번째 렌더링을 할 필요가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1231.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;893&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEs6gW/btsLRLXjyk5/uvSigMIL5z9WRdKsvcUzZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEs6gW/btsLRLXjyk5/uvSigMIL5z9WRdKsvcUzZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEs6gW/btsLRLXjyk5/uvSigMIL5z9WRdKsvcUzZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEs6gW%2FbtsLRLXjyk5%2FuvSigMIL5z9WRdKsvcUzZk%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;893&quot; data-filename=&quot;1231.png&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;893&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 컴포넌트는 속도와 성능 면에서 큰 진전을 이루었으며, 개발자와 사용자 모두에게 더 나은 경험을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;New directives&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;디렉티브는 React 19의 기능은 아니지만, 관련이 있습니다. React 서버 컴포넌트의 도입으로 인해 번들러는 컴포넌트와 함수가 실행되는 위치를 구분해야 합니다. 이를 위해 React 컴포넌트를 만들 때 알아두어야 할 두 가지 새로운 디렉티브가 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;'use client'는 클라이언트에서만 실행되는 코드를 표시합니다. 서버 컴포넌트가 기본값이므로, 상호작용과 상태 관리를 위한 훅을 사용하는 클라이언트 컴포넌트에는 'use client'를 추가해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;'use server'는 클라이언트 측 코드에서 호출할 수 있는 서버 측 함수를 표시합니다. 서버 컴포넌트에는 'use server'를 추가할 필요는 없으며, 서버 액션에만 추가하면 됩니다(아래에서 더 자세히 설명). 특정 코드가 서버에서만 실행되도록 하려면 server-only npm 패키지를 사용할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Actions&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 19는 액션(Actions)을 도입했습니다. 이 함수들은 이벤트 핸들러 사용을 대체하며, React 전환 및 동시성 기능과 통합됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;액션은 클라이언트와 서버 모두에서 사용할 수 있습니다. 예를 들어, 클라이언트 액션을 사용하여 폼의 onSubmit을 대체할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이벤트를 파싱할 필요 없이, 액션은 FormData를 직접 전달받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;import { useState } from &quot;react&quot;;

export default function TodoApp() {
  const [items, setItems] = useState([
    { text: &quot;My first todo&quot; },
  ]);

  async function formAction(formData) {
    const newItem = formData.get(&quot;item&quot;);
    // Could make a POST request to the server to save the new item
    setItems((items) =&amp;gt; [...items, { text: newItem }]);
  }

  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Todo List&amp;lt;/h1&amp;gt;
      &amp;lt;form action={formAction}&amp;gt;
        &amp;lt;input type=&quot;text&quot; name=&quot;item&quot; placeholder=&quot;Add todo...&quot; /&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;Add&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;ul&amp;gt;
        {items.map((item, index) =&amp;gt; (
          &amp;lt;li key={index}&amp;gt;{item.text}&amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Sever Actions&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 액션(Server Actions)을 통해 클라이언트 컴포넌트가 서버에서 실행되는 비동기 함수를 호출할 수 있습니다. 이를 통해 파일 시스템을 읽거나 데이터베이스에 직접 호출하는 등의 추가적인 이점을 제공하며, UI를 위한 별도의 API 엔드포인트를 만들 필요가 없어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;액션은 &lt;b&gt;'use server'&lt;/b&gt; 디렉티브로 정의되며, 클라이언트 측 컴포넌트와 통합됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;클라이언트 컴포넌트에서 서버 액션을 호출하려면 새 파일을 생성하고 이를 가져옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;'use server'
 
export async function create() {
  // Insert into database
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&quot;use client&quot;;

import { create } from &quot;./actions&quot;;

export default function TodoList() {
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;Todo List&amp;lt;/h1&amp;gt;
      &amp;lt;form action={create}&amp;gt;
        &amp;lt;input type=&quot;text&quot; name=&quot;item&quot; placeholder=&quot;Add todo...&quot; /&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;Add&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;New hooks&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;액션을 보완하기 위해, React 19는 상태, 상태 확인, 시각적 피드백을 더 쉽게 처리할 수 있도록 세 가지 새로운 훅을 도입했습니다. 이러한 훅들은 특히 폼 작업에 유용하지만, 버튼과 같은 다른 요소에도 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;useActionState&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 훅은 폼 상태와 폼 제출 관리를 간소화합니다. 액션을 사용하여 폼 입력 데이터를 캡처하고, 유효성 검사 및 오류 상태를 처리하며, 사용자 정의 상태 관리 로직의 필요성을 줄입니다. &lt;b&gt;useActionState&lt;/b&gt; 훅은 또한 액션이 실행되는 동안 로딩 표시기를 보여줄 수 있는 대기 상태(pending state)를 노출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;&quot;use client&quot;;

import { useActionState } from &quot;react&quot;;
import { createUser } from &quot;./actions&quot;;

const initialState = {
  message: &quot;&quot;,
};

export function Signup() {
  const [state, formAction, pending] = useActionState(createUser, initialState);

  return (
    &amp;lt;form action={formAction}&amp;gt;
      &amp;lt;label htmlFor=&quot;email&quot;&amp;gt;Email&amp;lt;/label&amp;gt;
      &amp;lt;input type=&quot;text&quot; id=&quot;email&quot; name=&quot;email&quot; required /&amp;gt;
      {/* ... */}
      {state?.message &amp;amp;&amp;amp; &amp;lt;p aria-live=&quot;polite&quot;&amp;gt;{state.message}&amp;lt;/p&amp;gt;}
      &amp;lt;button aria-disabled={pending} type=&quot;submit&quot;&amp;gt;
        {pending ? &quot;Submitting...&quot; : &quot;Sign up&quot;}
      &amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;useFormStatus&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 훅은 마지막 폼 제출의 상태를 관리하며, 반드시 폼 안에 있는 컴포넌트 내부에서 호출되어야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { useFormStatus } from &quot;react-dom&quot;;
import action from &quot;./actions&quot;;

function Submit() {
  const status = useFormStatus();
  return &amp;lt;button disabled={status.pending}&amp;gt;Submit&amp;lt;/button&amp;gt;;
}

export default function App() {
  return (
    &amp;lt;form action={action}&amp;gt;
      &amp;lt;Submit /&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;useActionState&lt;/b&gt; 훅에 내장된 대기 상태(pending status)가 있지만, &lt;b&gt;useFormStatus&lt;/b&gt;는 다음과 같은 경우에 독립적으로 유용합니다&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;폼 상태가 없는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공유되는 폼 컴포넌트를 만드는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;동일한 페이지에 여러 폼이 있는 경우 &lt;b&gt;useFormStatus&lt;/b&gt;는 부모 폼에 대한 상태 정보만 반환합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;useOptimistic&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 훅은 서버 액션이 완료되기 전에 UI를 낙관적으로 업데이트할 수 있게 해주며, 응답을 기다리지 않아도 됩니다. 비동기 액션이 완료되면 서버로부터 최종 상태를 받아 UI가 업데이트됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다음 예시는 새로운 메시지를 스레드에 즉시 추가하면서 동시에 해당 메시지를 서버 액션으로 보내어 영구적으로 저장하는 과정을 낙관적으로 처리하는 방법을 보여줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;&quot;use client&quot;;

import { useOptimistic } from &quot;react&quot;;
import { send } from &quot;./actions&quot;;

export function Thread({ messages }) {
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) =&amp;gt; [...state, { message: newMessage }],
  );

  const formAction = async (formData) =&amp;gt; {
    const message = formData.get(&quot;message&quot;) as string;
    addOptimisticMessage(message);
    await send(message);
  };

  return (
    &amp;lt;div&amp;gt;
      {optimisticMessages.map((m, i) =&amp;gt; (
        &amp;lt;div key={i}&amp;gt;{m.message}&amp;lt;/div&amp;gt;
      ))}
      &amp;lt;form action={formAction}&amp;gt;
        &amp;lt;input type=&quot;text&quot; name=&quot;message&quot; /&amp;gt;
        &amp;lt;button type=&quot;submit&quot;&amp;gt;Send&amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;New API : use&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;use&lt;/b&gt; 함수는 렌더링 중에 프라미스와 컨텍스트에 대한 일급 지원을 제공합니다. 다른 React 훅과는 달리, &lt;b&gt;use&lt;/b&gt;는 반복문, 조건문, 그리고 조기 반환 구문 내에서 호출될 수 있습니다. 오류 처리와 로딩은 가장 가까운 &lt;b&gt;Suspense&lt;/b&gt; 경계에서 처리됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다음 예시는 장바구니 항목의 프라미스가 해결되는 동안 로딩 메시지를 표시하는 방법을 보여줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { use } from &quot;react&quot;;

function Cart({ cartPromise }) {
  // `use` will suspend until the promise resolves
  const cart = use(cartPromise);
  return cart.map((item) =&amp;gt; &amp;lt;p key={item.id}&amp;gt;{item.title}&amp;lt;/p&amp;gt;);
}

function Page({ cartPromise }) {
  return (
    /*{ ... }*/
    // When `use` suspends in Cart, this Suspense boundary will be shown
    &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;}&amp;gt;
      &amp;lt;Cart cartPromise={cartPromise} /&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 기능을 사용하면 모든 컴포넌트의 데이터가 준비되었을 때만 컴포넌트들을 함께 렌더링할 수 있도록 그룹화할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Preloading resources&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 19는 스크립트, 스타일시트, 폰트와 같은 리소스를 로드 및 프리로드하여 페이지 로드 성능과 사용자 경험을 개선하는 여러 새로운 API를 추가했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;prefetchDNS: &lt;/b&gt;&amp;nbsp;연결할 것으로 예상되는 DNS 도메인 이름의 IP 주소를 미리 가져옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;preconnect: &lt;/b&gt;요청할 리소스가 명확하지 않더라도, 연결할 것으로 예상되는 서버에 미리 연결합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;preload:&lt;/b&gt;&amp;nbsp;사용할 것으로 예상되는 스타일시트, 폰트, 이미지 또는 외부 스크립트를 미리 가져옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;preloadModule:&lt;/b&gt;&amp;nbsp;사용할 것으로 예상되는 ESM 모듈을 미리 가져옵니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;preinit:&lt;/b&gt;&amp;nbsp;외부 스크립트를 가져와 평가하거나 스타일시트를 가져와 삽입합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;preinitModule:&lt;/b&gt;&amp;nbsp;ESM 모듈을 가져와 평가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예를 들어, 다음 React 코드는 다음과 같은 HTML 출력 결과를 제공합니다. 링크와 스크립트는 React에서 사용되는 순서가 아닌, 얼마나 빨리 로드되어야 하는지에 따라 우선순위가 매겨집니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;// React code
import { prefetchDNS, preconnect, preload, preinit } from &quot;react-dom&quot;;

function MyComponent() {
  preinit(&quot;https://.../path/to/some/script.js&quot;, { as: &quot;script&quot; });
  preload(&quot;https://.../path/to/some/font.woff&quot;, { as: &quot;font&quot; });
  preload(&quot;https://.../path/to/some/stylesheet.css&quot;, { as: &quot;style&quot; });
  prefetchDNS(&quot;https://...&quot;);
  preconnect(&quot;https://...&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;!-- Resulting HTML --&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;link rel=&quot;prefetch-dns&quot; href=&quot;https://...&quot; /&amp;gt;
    &amp;lt;link rel=&quot;preconnect&quot; href=&quot;https://...&quot; /&amp;gt;
    &amp;lt;link rel=&quot;preload&quot; as=&quot;font&quot; href=&quot;https://.../path/to/some/font.woff&quot; /&amp;gt;
    &amp;lt;link
      rel=&quot;preload&quot;
      as=&quot;style&quot;
      href=&quot;https://.../path/to/some/stylesheet.css&quot;
    /&amp;gt;
    &amp;lt;script async=&quot;&quot; src=&quot;https://.../path/to/some/script.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 프레임워크는 자주 이러한 리소스 로딩을 자동으로 처리해 주기 때문에, 직접 이러한 API를 호출할 필요가 없을 수도 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Other improvements&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;ref as a prop&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;더 이상 &lt;b&gt;forwardRef&lt;/b&gt;를 사용할 필요가 없습니다. React는 전환을 쉽게 하기 위해 코드 변환 도구(codemod)를 제공할 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;function CustomInput({ placeholder, ref }) {
  return &amp;lt;input placeholder={placeholder} ref={ref} /&amp;gt;;
}

// ...

&amp;lt;CustomInput ref={ref} /&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;ref callbacks&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;ref&lt;/b&gt;를 props로 전달하는 것 외에도, &lt;b&gt;refs&lt;/b&gt;는 정리 작업을 위한 콜백 함수도 반환할 수 있습니다. 컴포넌트가 언마운트될 때, React는 이 정리 작업을 위한 콜백 함수를 호출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;input
  ref={(ref) =&amp;gt; {
    // ref created

    // Return a cleanup function to reset
    // ref when element is removed from DOM.
    return () =&amp;gt; {
      // ref cleanup
    };
  }}
/&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Context as a provider&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이제 &amp;lt;Context.Provider&amp;gt;를 사용할 필요가 없습니다. 대신 &amp;lt;Context&amp;gt;를 직접 사용할 수 있습니다. React는 기존의 Provider를 변환할 수 있는 코드 변환 도구(codemod)를 제공할 예정입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const ThemeContext = createContext(&quot;&quot;);

function App({ children }) {
  return &amp;lt;ThemeContext value=&quot;dark&quot;&amp;gt;{children}&amp;lt;/ThemeContext&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;useDeferredValue initial value&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;useDeferredValue&lt;/b&gt;에 &lt;b&gt;initialValue&lt;/b&gt; 옵션이 추가되었습니다. 이 옵션이 제공되면, &lt;b&gt;useDeferredValue&lt;/b&gt;는 초기 렌더링에 해당 값을 사용하고, 백그라운드에서 다시 렌더링을 예약한 후 &lt;b&gt;deferredValue&lt;/b&gt;를 반환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function Search({ deferredValue }) {
  // On initial render the value is ''.
  // Then a re-render is scheduled with the deferredValue.
  const value = useDeferredValue(deferredValue, &quot;&quot;);

  return &amp;lt;Results value={value} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Document metadata support&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 19는 타이틀, 링크, 메타 태그를 네이티브로 올리고 렌더링하며, 심지어 중첩된 컴포넌트에서도 가능합니다. 이제 이러한 태그를 관리하기 위해 서드파티 솔루션을 사용할 필요가 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;function BlogPost({ post }) {
  return (
    &amp;lt;article&amp;gt;
      &amp;lt;h1&amp;gt;{post.title}&amp;lt;/h1&amp;gt;
      &amp;lt;title&amp;gt;{post.title}&amp;lt;/title&amp;gt;
      &amp;lt;meta name=&quot;author&quot; content=&quot;Jane Doe&quot; /&amp;gt;
      &amp;lt;link rel=&quot;author&quot; href=&quot;https://x.com/janedoe&quot; /&amp;gt;
      &amp;lt;meta name=&quot;keywords&quot; content={post.keywords} /&amp;gt;
      &amp;lt;p&amp;gt;...&amp;lt;/p&amp;gt;
    &amp;lt;/article&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Stylesheet support&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 19는 precedence(우선순위)를 사용하여 스타일시트 로딩 순서를 제어할 수 있습니다. 이를 통해 컴포넌트 근처에 스타일시트를 배치하는 것이 더 쉬워지며, React는 해당 스타일시트가 사용될 때만 로드합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;몇 가지 중요한 점을 기억해야 합니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;애플리케이션 내에서 동일한 컴포넌트를 여러 위치에 렌더링할 경우, React는 스타일시트를 중복 제거하여 문서에 한 번만 포함합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 사이드 렌더링 시, React는 스타일시트를 &lt;b&gt;head&lt;/b&gt;에 포함시킵니다. 이를 통해 브라우저가 로드될 때까지 페인트를 하지 않도록 보장합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;스트리밍이 시작된 후 스타일시트가 발견되면, React는 Suspense 경계를 통해 스타일시트에 의존하는 콘텐츠를 노출하기 전에 클라이언트에서 &lt;b&gt;head&lt;/b&gt;에 스타일시트를 삽입합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;클라이언트 사이드 렌더링 중, React는 새로 렌더링된 스타일시트가 로드될 때까지 렌더링을 커밋하지 않고 기다립니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;function ComponentOne() {
  return (
    &amp;lt;Suspense fallback=&quot;loading...&quot;&amp;gt;
      &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;one&quot; precedence=&quot;default&quot; /&amp;gt;
      &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;two&quot; precedence=&quot;high&quot; /&amp;gt;
      &amp;lt;article&amp;gt;...&amp;lt;/article&amp;gt;
    &amp;lt;/Suspense&amp;gt;
  );
}

function ComponentTwo() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;...&amp;lt;/p&amp;gt;
      {/* Stylesheet &quot;three&quot; below will be inserted between &quot;one&quot; and &quot;two&quot; */}
      &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;three&quot; precedence=&quot;default&quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Async scripts support&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;비동기 스크립트를 모든 컴포넌트에서 렌더링할 수 있습니다. 이를 통해 컴포넌트 근처에 스크립트를 배치하는 것이 더 쉬워지며, React는 해당 스크립트가 사용될 때만 로드합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;몇 가지 유의할 점은 다음과 같습니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;애플리케이션 내에서 동일한 컴포넌트를 여러 위치에 렌더링할 경우, React는 스크립트를 중복 제거하여 문서에 한 번만 포함합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 사이드 렌더링 시, 비동기 스크립트는 &lt;b&gt;head&lt;/b&gt;에 포함되며 스타일시트, 폰트, 이미지 프리로드와 같은 페인트를 차단하는 더 중요한 리소스 뒤에 우선순위가 지정됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function Component() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;script async={true} src=&quot;...&quot; /&amp;gt;
      // ...
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;html&amp;gt;
      &amp;lt;body&amp;gt;
        &amp;lt;Component&amp;gt;
          // ...
        &amp;lt;/Component&amp;gt; // Won't duplicate script in the DOM
      &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Custom Elements support&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;커스텀 엘리먼트(Custom Elements)는 개발자가 웹 컴포넌트 사양의 일환으로 자체 HTML 요소를 정의할 수 있게 해줍니다. 이전 버전의 React에서는 React가 인식하지 못한 props를 속성으로 처리하기 때문에 커스텀 엘리먼트를 사용하는 것이 어려웠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;React 19는 커스텀 엘리먼트에 대한 완전한 지원을 추가했으며, Custom Elements Everywhere의 모든 테스트를 통과했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Better error reporting&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;오류 처리 기능이 개선되어 중복된 오류 메시지가 제거되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;213.png&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xXfF6/btsLRTueLGM/ij6hfZnYdhkqL298LYttHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xXfF6/btsLRTueLGM/ij6hfZnYdhkqL298LYttHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xXfF6/btsLRTueLGM/ij6hfZnYdhkqL298LYttHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxXfF6%2FbtsLRTueLGM%2Fij6hfZnYdhkqL298LYttHK%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;1080&quot; height=&quot;389&quot; data-filename=&quot;213.png&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서드파티 스크립트 및 브라우저 확장 프로그램을 사용할 때 발생하는 하이드레이션 오류도 개선되었습니다. 이전에는 서드파티 스크립트나 브라우저 확장 프로그램에 의해 삽입된 요소가 불일치 오류를 유발했으나, React 19에서는 &lt;b&gt;head&lt;/b&gt;와 &lt;b&gt;body&lt;/b&gt;에서 예상치 못한 태그가 발견될 경우 이를 건너뛰고 오류를 발생시키지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;마지막으로, React 19는 기존의 &lt;b&gt;onRecoverableError&lt;/b&gt;에 더해 두 가지 새로운 루트 옵션을 추가하여 오류가 발생한 이유를 더 명확하게 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;onCaughtError&lt;/b&gt;는 React가 오류 경계(Error Boundary) 내에서 오류를 포착했을 때 트리거됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;onUncaughtError&lt;/b&gt;는 오류가 발생했지만 오류 경계에서 포착되지 않았을 때 트리거됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;onRecoverableError&lt;/b&gt;는 오류가 발생하고 자동으로 복구되었을 때 트리거됩니다.&lt;/span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&amp;lt; 참고자료 &amp;gt;&lt;/b&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;&amp;nbsp;&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;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;[사이트] #Vercel&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1737248843069&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;What&amp;rsquo;s new in React 19 - Vercel&quot; data-og-description=&quot;React 19 is near. Here's what to expect and how you can get started deploying React 19 on Vercel.&quot; data-og-host=&quot;vercel.com&quot; data-og-source-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; data-og-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fqnyn/hyX0obsoY7/c2yyH2rBBjfHoNYshgbWr0/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/caqgFy/hyX4ugOeKf/fN3TdbHJpXKs1JKBFEbP9k/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/Hdnfm/hyX4pNjZzU/kkSLcqFd9sDLmUxOpyUkxK/img.png?width=829&amp;amp;height=1264&amp;amp;face=0_0_829_1264&quot;&gt;&lt;a href=&quot;https://vercel.com/blog/whats-new-in-react-19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vercel.com/blog/whats-new-in-react-19&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fqnyn/hyX0obsoY7/c2yyH2rBBjfHoNYshgbWr0/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/caqgFy/hyX4ugOeKf/fN3TdbHJpXKs1JKBFEbP9k/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628,https://scrap.kakaocdn.net/dn/Hdnfm/hyX4pNjZzU/kkSLcqFd9sDLmUxOpyUkxK/img.png?width=829&amp;amp;height=1264&amp;amp;face=0_0_829_1264');&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;What&amp;rsquo;s new in React 19 - Vercel&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React 19 is near. Here's what to expect and how you can get started deploying React 19 on Vercel.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vercel.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;lt;React&amp;gt; What's new in React19?&lt;/span&gt;&lt;/p&gt;</description>
      <category>Language &amp;amp; Framework &amp;amp; Library/React</category>
      <category>forwardRef</category>
      <category>React</category>
      <category>react19</category>
      <category>servercomponent</category>
      <category>Use</category>
      <category>useactionstate</category>
      <category>useformstatus</category>
      <category>vercel</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/162</guid>
      <comments>https://sangcho.tistory.com/entry/What%E2%80%99s-new-in-React-19#entry162comment</comments>
      <pubDate>Sun, 19 Jan 2025 10:08:53 +0900</pubDate>
    </item>
    <item>
      <title>Yes, the Next.js Router Cache is Actually Good</title>
      <link>https://sangcho.tistory.com/entry/Yes-the-Nextjs-Router-Cache-is-Actually-Good</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kT1d5/btsLCq7wMvL/Pq8rxr5ISzOgCt5QNPBHg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kT1d5/btsLCq7wMvL/Pq8rxr5ISzOgCt5QNPBHg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kT1d5/btsLCq7wMvL/Pq8rxr5ISzOgCt5QNPBHg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkT1d5%2FbtsLCq7wMvL%2FPq8rxr5ISzOgCt5QNPBHg0%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;452&quot; height=&quot;259&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #ee2323;&quot;&gt;* 이 글은 &lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://joulev.dev/blogs/yes-nextjs-router-cache-is-actually-good&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Yes, the Next.js Router Cache is Actually Good&lt;/span&gt;&lt;/a&gt; 를 번역하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;TL;DR&lt;/b&gt;&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;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js의 라우터 캐시는 논란이 있지만, 유용한 기능입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;라우터 캐시는 서버 부하를 줄이고, 사용자 경험(UX)을 개선하며, &quot;허용 가능한&quot; 정도의 오래된 데이터를 제공하는 것을 목표로 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용자가 시작하는 변경 작업(mutation)의 경우 서버 액션(server actions)을 사용해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;항상 최신 데이터가 필요한 경우에는 클라이언트 측 데이터 페칭을 사용하십시오.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;staleTimes와 router.refresh는 예외적으로 사용할 수 있는 방법이지만, 라우터 캐시와 관련하여 대부분의 경우 더 나은 해결책이 존재합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;The Controversy Known as the Next.js Router Cache&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;라우터 캐시는 클라이언트 측 데이터 페칭에는 영향을 주지 않습니다. 이 글의 나머지 부분에서는 명시하지 않는 한 서버 측 데이터 페칭(서버 컴포넌트 사용)을 전제로 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;라우터 캐시는 기본적으로 특정 시간 동안 클라이언트에서 경로의 콘텐츠를 저장합니다. 따라서 이 시간 내에 클라이언트 측 네비게이션(e.g., &amp;lt;Link&amp;gt; 태그 사용 시)으로 이동할 경우, 해당 페이지가 동적으로 렌더링되더라도 서버에서 데이터를 가져오는 대신 캐시에서 페이지 콘텐츠가 제공됩니다. 정적 렌더링된 페이지의 경우 기본적으로 이 기간은 5분이고, 동적 렌더링된 페이지는 30초입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이는 대부분의 Next.js 개발자에게 예상치 못한 동작일 것입니다. pages 라우터에서는 동적 페이지가 항상 요청 시점에 렌더링되므로(즉, 클라이언트 측 캐시 시간 프레임이 0) 페이지가 항상 최신 데이터를 가져온다는 것을 보장했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;반면 app 라우터에서는 데이터가 최대 30초 동안 오래된 상태일 수 있습니다. 처음에는 이러한 데이터의 &quot;오래된 상태(stale)&quot; 가능성이 당황스러울 수 있습니다. 페이지를 명시적으로 동적으로 설정했다면 항상 최신 데이터로 동적이어야 하지 않을까요? 그리고 14.2.0 버전 이전에는 이러한 값을 구성하는 것이 불가능했습니다. 사용할 수 있는 유일한 방법은 다음과 같은 무효화(invalidation) 방법을 이용하는 것이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;1. 서버 액션 내에서 revalidatePath 또는 revalidateTag를 사용하여 특정 페이지나 태그를 무효화할 수 있습니다. 그러나 revalidatePath나 revalidateTag를 라우트 핸들러에서 호출하는 것은 라우터 캐시에 아무런 영향을 미치지 않습니다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;2. 클라이언트에서 모든 라우터 캐시를 수동으로 삭제하려면 router.refresh를 사용하십시오. 이는 캐시를 무효화하는 간단한 방법이지만, 다소 임시방편적이고 우아하지 못한 방식입니다. 사실, 이 방법은 임시방편에 불과하므로, 예외적인 경우에만 사용하는 것이 좋습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;라우터 캐시가 너무 논란이 되자, Next.js 팀은 라우터 캐시 지속 시간을 수동으로 설정할 수 있는 staleTimes 옵션을 도입하기로 결정했습니다. 이 옵션은 14.2.0 버전부터 사용할 수 있으며, 작성 시점에서는 여전히 실험적 기능으로 표시되어 있습니다. 이를 통해 동적 페이지를 진정으로 동적으로 만들 수 있게 되었습니다. 좋은 소식이죠?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;몇 개월 전, 제가 아직 반(反) 라우터 캐시 입장이었을 때는 그렇게 생각했을 것입니다. 하지만 이후 앱 라우터를 사용하면서 이제는 라우터 캐시가 좋은 기능이며, Next.js 팀이 이 기능을 포함시킬 만한 충분한 이유가 있다고 확신하게 되었습니다. staleTimes 역시 router.refresh처럼 예외적인 경우에만 고려해야 할 옵션입니다. 이유를 알아보도록 하죠.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Argument For the Router Cache: Spam Tab Switching&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용자 설정 페이지가 여러 탭으로 나누어져 있다고 가정해봅시다. 예를 들어 /settings/account와 /settings/billing 같은 페이지가 있습니다. 이러한 페이지들은 사용자 데이터를 다루기 때문에 동적으로 렌더링해야 합니다. (클라이언트 측 데이터 페칭은 라우터 캐시에 영향을 받지 않으므로 이 옵션은 고려하지 않겠습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;라우터 캐시가 없다고 가정할 때, 사용자가 탭 간을 전환할 때마다 페이지 콘텐츠는 서버에서 매번 가져오게 됩니다. 일반적으로 이는 문제가 되지 않지만, 사용자가 빠르게 탭을 전환하는 경우(예를 들어, 내비게이션 사이드바에서 실수로 잘못된 링크를 클릭한 경우), 서버는 요청 폭탄을 맞게 되어 서버 부하가 증가하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;사용자가 설정을 변경하지 않는다면 페이지 데이터는 동일하게 유지될 것입니다. 따라서 페이지 데이터를 한 번만 가져와 일정 시간 동안 캐시하고, 사용자가 다시 돌아왔을 때는 서버를 다시 호출하는 대신 캐시된 데이터를 제공하는 것이 유리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이러한 서버 호출은 매달 청구되는 비용에 영향을 미칩니다. Vercel에 호스팅하는 경우, 이러한 동적 페이지 요청은 각각 하나의 서버리스 함수 호출로 계산될 가능성이 큽니다. 사이트는 이러한 불필요한 비캐시 서버 호출로 인해 불필요한 추가 비용을 지출하게 될 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;또한 사용자 경험 측면에서도, 페이지를 즉시 제공할 수 있다면 사용자가 페이지 로딩을 몇 초 기다리는 것보다 훨씬 더 부드러운 경험을 할 수 있습니다. 이는 이전 페이지로 즉시 돌아갈 수 있는 bfcache와 비슷합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이것이 라우터 캐시가 있는 이유입니다. 팀의 일원이 아니기 때문에 확실히 말할 수는 없지만, 이 캐시의 아이디어는 서버 부하를 줄이고, 즉시 네비게이션을 통해 bfcache와 같은 사용자 경험 개선을 가능하게 하기 위한 필요성에서 비롯된 것이라고 강하게 믿습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Vercel이 호스팅 제공업체라는 점에서, 이들이 고객들로부터 이러한 불필요한 비캐시 요청으로 인한 비용에 대한 불만을 많이 들어왔을 가능성도 있습니다. 이에 따라 고객들이 이런 상황을 방지하도록 해야 할 필요성을 느꼈을 것이라는 주장도 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Solutions to the Potential of State Data&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하지만 기본값으로 30초의 캐시 지속 시간은 동적 페이지에 오래된 데이터를 표시할 가능성이 있음을 의미합니다. 두 가지 경우를 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;경우 1: 제3자 데이터 업데이트 &amp;ndash; 허용 가능한 오래된 데이터&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;대시보드 페이지를 예로 들어보겠습니다. 이 페이지의 데이터는 외부 소스로부터 매우 자주 업데이트된다고 가정합니다. 예를 들어 EUR/USD 환율, Twitter 팔로워 수, 혹은 사용자가 또 다른 스캠코인에 투자하여 잃은 금액 등을 보여줄 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 경우, 사용자가 페이지를 이동했다가 30초 이내에 다시 돌아오면 오래된 데이터를 볼 가능성이 큽니다. 이는 예상된 상황입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js는 데이터가 다른 곳에서 업데이트되었는지 알 수 없지만, 사용자가 데이터를 직접 수정하지 않았다는 것은 알고 있습니다. 따라서 서버 부하를 줄이기 위해(앞서 설명한 내용 참조), Next.js는 이러한 경우를 &quot;허용 가능한 오래된 데이터&quot;로 간주합니다. 즉, 오래될 수는 있지만 허용 가능한 수준이라는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그래서 캐시 지속 시간이 30초로 설정된 것이지 30분이 아닌 것입니다. 30분이나 뒤처진 대시보드는 심각할 수 있지만, 팔로워 수가 30초 정도 뒤처지는 것은 큰 문제가 아닐 것입니다. 완전히 최신 상태로 보고 싶다면 페이지를 새로 열고 30초를 기다린 후에 30초 정도 지난 데이터를 보게 될 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;물론 30초가 허용되지 않는 경우도 많이 있습니다. 이러한 경우 서버 측 렌더링은 좋은 선택이 아닙니다. 대신 Tanstack Query나 SWR과 같은 클라이언트 측 데이터 페칭을 사용하여 원하는 대로 데이터를 항상 최신 상태로 유지하는 것이 좋습니다(10초마다 업데이트하거나, 탭이 포커스될 때마다 등).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;가능하다면 WebSocket과 같은 기술을 사용해 완전히 실시간 데이터로 전환하는 것도 고려해야 합니다. 항상 최신 데이터를 필요로 하는 경우에는 서버 측 렌더링이 최선의 해결책이 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;경우 2: 사용자 데이터 업데이트 &amp;ndash; 잘못된 방식으로 수행된 변이(Mutation)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;앞서 언급한 설정 페이지 예를 다시 살펴보겠습니다. 사용자가 자신의 바이오(bio)를 업데이트하고자 한다고 가정합니다. /settings/account 페이지에 가서 바이오를 업데이트한 후 다른 페이지로 이동하거나 리디렉션됩니다. 이제 /settings/account 페이지는 30초 동안 캐시됩니다. 사용자가 30초 이내에 /settings/account 페이지로 다시 돌아가면, 업데이트된 바이오가 아닌 이전 바이오가 표시됩니다. 이런 일이 생기면 당황스럽겠죠!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 원인은 아마도 fetch(&quot;/api/users&quot;, { method: &quot;PATCH&quot; }) 같은 방식으로 변이 요청을 보냈기 때문일 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Next.js는 사용자가 페이지에서 무언가를 업데이트했는지 알 수 없고, 단지 서버에 무언가를 하기 위해 HTTP 요청을 보냈다는 것만 알 수 있습니다. 따라서 Next.js는 여전히 이 페이지를 &quot;허용 가능한 오래된 데이터&quot;로 간주하고, 캐시된 바이오 데이터를 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;따라서 위의 PATCH와 같은 수동 데이터 업데이트 요청은 서버 측 렌더링된 페이지를 업데이트하는 올바른 방법이 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;대신 서버 액션(server actions)을 사용해야 하며, 필요한 경우 revalidatePath나 revalidateTag를 함께 사용해야 합니다. 이 방법은 &quot;선택&quot;이 아니라 &quot;필수&quot;입니다. 서버 액션이 Next.js 라우터와 매우 밀접하게 결합되어 있기 때문에, Next.js는 &quot;무언가가 변경되었다&quot;는 것을 알고, 서버 액션 내에서 호출된 revalidatePath나 revalidateTag 함수에 따라 클라이언트 측 캐시를 무효화할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서버 액션 + revalidatePath/revalidateTag를 사용하면 Next.js는 데이터가 더 이상 허용 가능한 오래된 데이터가 아니라고 판단합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;새로운 데이터가 있다는 것이 보장되므로 캐시를 무효화하고 다시 새로운 데이터를 요청합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;수동 REST 스타일의 데이터 업데이트, tRPC, Tanstack Query의 변이 메서드 등은 서버 측 렌더링된 데이터를 업데이트하는 올바른 방법이 아닙니다. 클라이언트 측 렌더링된 데이터를 업데이트하려는 경우에는 괜찮지만, 서버 컴포넌트에서 가져온 데이터를 업데이트하려면 반드시 서버 액션을 사용해야 합니다. 다른 대안은 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이제 라우터 캐시가 세 가지 기반 위에 구축되었음을 알 수 있습니다. 서버 부하 감소의 필요성, UX 개선, 그리고 일부 데이터는 허용 가능한 수준에서 오래될 수 있다는 개념입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이는 전통적으로 기대되는 프레임워크의 동작 방식과는 다르기 때문에, 모든 사람에게 큰 놀라움을 줍니다. 하지만 보시다시피, 이는 좋은 기능입니다. Next.js 팀이 이 기능을 포함시킨 데는 충분한 이유가 있으며, 제가 팀의 아이디어를 충분히 이해하여 잘 설명해 드릴 수 있었기를 바랍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;또한, 클라이언트 측 데이터 페칭을 서버 측 렌더링으로 완전히 대체하는 것은 좋은 아이디어가 아님을 알 수 있습니다. 항상 최신 상태여야 하는 데이터의 경우 클라이언트 측 데이터 페칭이 적합한 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&amp;lt; 참고자료 &amp;gt;&lt;/b&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;&amp;nbsp;&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;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;[사이트]&amp;nbsp;#Midum&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1735947127600&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;Yes, the Next.js Router Cache is Actually Good | joulev.dev &amp;raquo; blogs&quot; data-og-description=&quot;The Next.js Router Cache is controversial to say the least. But I think Vercel and the Next.js team have very good reasons to implement it, and the new &amp;#96;staleTimes&amp;#96; option to configure it should be considered to only be an escape hatch at best. This is why&quot; data-og-host=&quot;joulev.dev&quot; data-og-source-url=&quot;https://joulev.dev/blogs/yes-nextjs-router-cache-is-actually-good&quot; data-og-url=&quot;https://joulev.dev/blogs/yes-nextjs-router-cache-is-actually-good&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0MAVZ/hyXWzv26wB/UF2EwZzrKel7hKP5FlTN60/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/rMe00/hyXWxE0WB0/VO2TVsxmf7zEdlEw1DX3J0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bIGPZX/hyXWnCpvlt/z2jVEnyH2foMNVdpGF1x11/img.png?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://joulev.dev/blogs/yes-nextjs-router-cache-is-actually-good&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joulev.dev/blogs/yes-nextjs-router-cache-is-actually-good&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0MAVZ/hyXWzv26wB/UF2EwZzrKel7hKP5FlTN60/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/rMe00/hyXWxE0WB0/VO2TVsxmf7zEdlEw1DX3J0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bIGPZX/hyXWnCpvlt/z2jVEnyH2foMNVdpGF1x11/img.png?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&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;Yes, the Next.js Router Cache is Actually Good | joulev.dev &amp;raquo; blogs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Next.js Router Cache is controversial to say the least. But I think Vercel and the Next.js team have very good reasons to implement it, and the new `staleTimes` option to configure it should be considered to only be an escape hatch at best. This is why&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joulev.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;lt;Next.js&amp;gt; Yes,&amp;nbsp;the&amp;nbsp;Next.js&amp;nbsp;Router&amp;nbsp;Cache&amp;nbsp;is&amp;nbsp;Actually&amp;nbsp;Good&lt;/span&gt;&lt;/p&gt;</description>
      <category>Language &amp;amp; Framework &amp;amp; Library/Next.js</category>
      <category>cache</category>
      <category>Next.js</category>
      <category>Router</category>
      <category>RSC</category>
      <category>servercomponent</category>
      <category>라우터</category>
      <category>라우터캐시</category>
      <category>서버컴포넌트</category>
      <category>캐시</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/161</guid>
      <comments>https://sangcho.tistory.com/entry/Yes-the-Nextjs-Router-Cache-is-Actually-Good#entry161comment</comments>
      <pubDate>Sat, 4 Jan 2025 08:37:02 +0900</pubDate>
    </item>
    <item>
      <title>How styled-components works: A deep dive under the hood</title>
      <link>https://sangcho.tistory.com/entry/How-styled-components-works-A-deep-dive-under-the-hood</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1041&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/butNds/btsKQAhzQzJ/FRU2b216H8n1EQqpoBCWyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/butNds/btsKQAhzQzJ/FRU2b216H8n1EQqpoBCWyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/butNds/btsKQAhzQzJ/FRU2b216H8n1EQqpoBCWyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbutNds%2FbtsKQAhzQzJ%2FFRU2b216H8n1EQqpoBCWyK%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;564&quot; height=&quot;294&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1041&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Nanum Gothic';&quot;&gt;* 이 글은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How styled-components works: A deep dive under the hood&lt;/a&gt; &lt;/span&gt;를 번역하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732104777054&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;How styled-components works: A deep dive under the hood&quot; data-og-description=&quot;CSS-in-JS is getting more and more common in the modern front-end development and especially in the React community. styled-components&amp;hellip;&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; data-og-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uKd4b/hyXDiUZeW6/SoNFtgzii2m2WwXIoFJmZk/img.png?width=1200&amp;amp;height=624&amp;amp;face=0_0_1200_624,https://scrap.kakaocdn.net/dn/nSc0I/hyXDhofhRs/kEY475EUkpJCNwqkYW3x3K/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/CwVXJ/hyXDiHsDpP/Udmdvp2wVxbhbZclb1R3Fk/img.jpg?width=1358&amp;amp;height=453&amp;amp;face=0_0_1358_453&quot;&gt;&lt;a href=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uKd4b/hyXDiUZeW6/SoNFtgzii2m2WwXIoFJmZk/img.png?width=1200&amp;amp;height=624&amp;amp;face=0_0_1200_624,https://scrap.kakaocdn.net/dn/nSc0I/hyXDhofhRs/kEY475EUkpJCNwqkYW3x3K/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/CwVXJ/hyXDiHsDpP/Udmdvp2wVxbhbZclb1R3Fk/img.jpg?width=1358&amp;amp;height=453&amp;amp;face=0_0_1358_453');&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;How styled-components works: A deep dive under the hood&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CSS-in-JS is getting more and more common in the modern front-end development and especially in the React community. styled-components&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;CSS-in-JS는 현대 프론트엔드 개발, 특히 React 커뮤니티에서 점점 더 보편화되고 있습니다. 그중에서도 styled-components는 태그 템플릿을 사용해 스타일을 정의하는 것만으로도 일반적인 React 컴포넌트를 생성할 수 있어 두드러집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 라이브러리는 CSS 모듈화와 같은 중요한 문제를 해결하고, 중첩과 같은 CSS 외의 기능도 제공하며, 이러한 모든 기능을 별도의 설정 없이 사용할 수 있습니다. 개발자는 CSS 클래스의 고유한 이름에 대해 고민할 필요가 없으며, 클래스 자체에 대해 신경 쓸 필요도 없습니다. 그렇다면 이 강력한 기능은 어떻게 가능할까요?&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Magic Syntax&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;const Button = styled.button`
  color: coral; 
  padding: 0.25rem 1rem; 
  border: solid 2px coral; 
  border-radius: 3px;
  margin: 0.5rem;
  font-size: 1rem;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 styled.button은 단순히 styled('button')의 단축 표현일 뿐이며, 사용 가능한 HTML 요소 목록에서 동적으로 생성된 여러 함수 중 하나입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;태그 템플릿&lt;/span&gt;에 익숙하다면 button이 단순히 함수에 불과하며 배열 파라미터 안에 간단한 문자열과 함께 호출될 수 있다는 것을 알 수 있을 것입니다. 이 코드를 풀어보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1732105196040&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Button = styled('button')([
  'color: coral;' +
  'padding: 0.25rem 1rem;' + 
  'border: solid 2px coral;' +
  'border-radius: 3px;' +
  'margin: 0.5rem;' +
  'font-size: 1rem;'
]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 styled가 단순히 컴포넌트 생성기일 뿐이라는 것을 알았으니, 그 구현이 어떻게 생겼을지 상상해볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;태그템플릿&lt;/span&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1732105040071&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function highlight(strings, ...values) {
    return strings.reduce((result, string, i) =&amp;gt; 
        `${result}${string}&amp;lt;strong&amp;gt;${values[i] || ''}&amp;lt;/strong&amp;gt;`, '');
}

const name = &quot;Alice&quot;;
const age = 25;

// 태그 템플릿 사용
const message = highlight`Hello, my name is ${name} and I am ${age} years old.`;

console.log(message);
// 출력: &quot;Hello, my name is &amp;lt;strong&amp;gt;Alice&amp;lt;/strong&amp;gt; and I am &amp;lt;strong&amp;gt;25&amp;lt;/strong&amp;gt; years old.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Reinvent styled-components&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;const myStyled = (TargetComponent) =&amp;gt; ([style]) =&amp;gt; class extends React.Component {
  componentDidMount() {
    this.element.setAttribute('style', style);
  }

  render() {
    return (
      &amp;lt;TargetComponent {...this.props} ref={element =&amp;gt; this.element = element } /&amp;gt;
    );
  }
};

const Button = myStyled('button')`
  color: coral; 
  padding: 0.25rem 1rem; 
  border: solid 2px coral; 
  border-radius: 3px;
  margin: 0.5rem;
  font-size: 1rem;
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 구현은 상당히 간단합니다. 팩토리는 클로저에 저장된 태그 이름을 기반으로 새 컴포넌트를 생성하고, 마운트된 후에 인라인 스타일을 설정합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 우리 컴포넌트의 스타일이 props에 따라 달라진다면 어떻게 될까요?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;const primaryColor = 'coral';

const Button = styled('button')`
  background: ${({ primary }) =&amp;gt; primary ? 'white ' : primaryColor};
  color: ${({ primary }) =&amp;gt; primary ? primaryColor : 'white'}; 
  padding: 0.25rem 1rem; 
  border: solid 2px ${primaryColor}; 
  border-radius: 3px;
  margin: 0.5rem;
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;컴포넌트가 마운트되거나 props가 업데이트될 때 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;스타일의 interpolations을 평가하도록 구현&lt;/span&gt;을 업데이트해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;const myStyled = (TargetComponent) =&amp;gt; (strs, ...exprs) =&amp;gt; class extends React.Component {
  interpolateStyle() {
    const style = exprs.reduce((result, expr, index) =&amp;gt; {
      const isFunc = typeof expr === 'function';
      const value = isFunc ? expr(this.props) : expr;
      
      return result + value + strs[index + 1];
    }, strs[0]);

    this.element.setAttribute('style', style);
  }

  componentDidMount() {
    this.interpolateStyle();
  }

  componentDidUpdate() {
    this.interpolateStyle();
  }

  render() {
    return &amp;lt;TargetComponent {...this.props} ref={element =&amp;gt; this.element = element } /&amp;gt;
  }
};

const primaryColor = 'coral';

const Button = myStyled('button')`
  background: ${({ primary }) =&amp;gt; primary ? primaryColor : 'white'};
  color: ${({ primary }) =&amp;gt; primary ? 'white' : primaryColor};
  padding: 0.25rem 1rem; 
  border: solid 2px ${primaryColor}; 
  border-radius: 3px;
  margin: 0.5rem;
  font-size: 1rem;
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 가장 까다로운 부분은 스타일 문자열을 얻는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;const style = exprs.reduce((result, expr, index) =&amp;gt; {
  const isFunc = typeof expr === 'function';
  const value = isFunc ? expr(this.props) : expr;
  
  return result + value + strs[index + 1];
}, strs[0]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우리는 모든 문자열 조각을 표현식의 결과와 하나씩 연결합니다. 표현식이 함수인 경우 컴포넌트의 속성(properties)을 전달하여 호출됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 간단한 팩토리의 API는 styled-components에서 제공하는 API와 유사해 보이지만, 실제 구현은 훨씬 흥미롭게 작동합니다. inline 스타일을 사용하지 않기 때문입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled-components를 가져와서 컴포넌트를 생성할 때 무슨 일이 일어나는지 좀 더 자세히 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;styled-components&amp;nbsp;Under The Hood&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Import styled-components&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앱에서 라이브러리를 처음 가져오면, styled 팩토리를 통해 생성된 모든 컴포넌트를 카운트하기 위한 내부 카운터 변수를 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;call styled.tag-name factory&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;const Button = styled.button`
  font-size: ${({ sizeValue }) =&amp;gt; sizeValue + 'px'};
  color: coral; 
  padding: 0.25rem 1rem; 
  border: solid 2px coral; 
  border-radius: 3px;
  margin: 0.5rem;
  &amp;amp;:hover {
    background-color: bisque;
  }
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled-components가 새로운 컴포넌트를 생성할 때, 내부 식별자인 componentId도 생성됩니다. 식별자는 다음과 같이 계산됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;counter++;
const componentId = 'sc-' + hash('sc' + counter);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앱에서 첫 번째 styled 컴포넌트의 componentId는 sc-bdVaJa입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;현재 styled-components는 MurmurHash 알고리즘을 사용하여 고유한 식별자를 생성한 후, 해시 번호를 알파벳 이름으로 변환합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;식별자가 생성되면 styled-components는 페이지의 &amp;lt;head&amp;gt;에 새로운 HTML &amp;lt;style&amp;gt; 요소를 삽입하고(첫 번째 컴포넌트이며 요소가 아직 삽입되지 않은 경우), &lt;span style=&quot;background-color: #9feec3;&quot;&gt;나중에 사용할 수 있도록 이 요소에 componentId가 포함된 특별한 주석 마커를 추가&lt;/span&gt;합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 경우 다음과 같은 결과를 얻습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;style data-styled-components&amp;gt;
  /* sc-component-id: sc-bdVaJa */
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;새 컴포넌트가 생성되면, 팩토리에 전달된 대상 컴포넌트(이 경우 'button')와 componentId가 정적 필드에 저장됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;StyledComponent.componentId = componentId;
StyledComponent.target = TargetComponent;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;보시다시피, 단순히 styled 컴포넌트를 생성하는 것만으로는 성능에 전혀 부담이 가지 않습니다. 수백 개의 컴포넌트를 정의하고 사용하지 않더라도, 얻는 것은 주석이 포함된 하나 이상의 &amp;lt;style&amp;gt; 요소뿐입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled 팩토리를 통해 생성된 컴포넌트에는 중요한 점이 하나 더 있습니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;이들은 hiddenBaseStyledComponent라는 클래스에서 상속되며, 이 클래스는 여러 생명주기 메서드를 구현합니다.&lt;/span&gt; 이 클래스가 담당하는 기능을 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;componentWillMount() 위의 Button 인스턴스를 생성하고 페이지에 마운트해 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;ReactDOM.render(
  &amp;lt;Button sizeValue={24}&amp;gt;I'm a button&amp;lt;/Button&amp;gt;,
  document.getElementById('root')
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;BaseStyledComponent의 생명주기 메서드 componentWillMount()가 실행됩니다. 이 메서드는 몇 가지 중요한 작업을 수행합니다:&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 태그 템플릿 평가&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;알고리즘은 우리가 커스텀 myStyled 팩토리에서 구현한 것과 매우 유사합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;Button sizeValue={24}&amp;gt;I'm a button&amp;lt;/Button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우리는 다음과 같은 evaluatedStyles 문자열을 얻습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;scss&quot;&gt;&lt;code&gt;font-size: 24px;
color: coral; 
padding: 0.25rem 1rem; 
border: solid 2px coral; 
border-radius: 3px;
margin: 0.5rem;
&amp;amp;:hover {
  background-color: bisque;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. CSS 클래스 이름 생성&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;고유한 props를 가진 각 컴포넌트 인스턴스는 componentId와 evaluatedStyles 문자열을 기반으로 동일한 MurmurHash 알고리즘을 통해 생성된 자체 CSS 클래스 이름을 가집니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;const className = hash(componentId + evaluatedStyles);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;우리의 Button 인스턴스의 경우 생성된 className은 jsZVzX입니다. 이 클래스 이름은 generatedClassName으로 컴포넌트 상태에 저장됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. CSS 전처리&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 초고속 stylis CSS 전처리기가 도움을 주어 유효한 CSS 문자열을 얻을 수 있도록 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;const selector = '.' + className;
const cssStr = stylis(selector, evaluatedStyles);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Button 인스턴스에 대한 최종 CSS는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.jsZVzX {
  font-size: 24px;
  color: coral;
  padding: 0.25rem 1rem;
  border: solid 2px coral;
  border-radius: 3px;
  margin: 0.5rem;
}
.jsZVzX:hover{
  background-color: bisque;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. CSS 문자열을 페이지에 삽입&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 CSS는 컴포넌트의 주석 마커 바로 다음에 페이지의 &amp;lt;head&amp;gt; 내 &amp;lt;style&amp;gt; 요소에 삽입됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;&amp;lt;style data-styled-components&amp;gt;
  /* sc-component-id: sc-bdVaJa */
  .sc-bdVaJa {} .jsZVzX{font-size:24px;color:coral; ... }  
  .jsZVzX:hover{background-color:bisque;}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;보시다시피, styled-components는 규칙이 없는 CSS 클래스 형태로 componentId(.sc-bdVaJa)도 함께 삽입합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;render() CSS 처리가 완료되면, styled-components는 이제 해당 className을 가진 요소를 생성하기만 하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;const TargetComponent = this.constructor.target; // In our case just 'button' string.
const componentId = this.constructor.componentId;
const generatedClassName = this.state.generatedClassName;

return ( 
  &amp;lt;TargetComponent 
    {...this.props} 
    className={this.props.className + ' ' + componentId + ' ' + generatedClassName}
  /&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled-components는 3개의 클래스 이름을 가진 요소를 렌더링합니다:&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;this.props.className &amp;mdash; 부모 컴포넌트에 의해 전달된 선택적 클래스 이름.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;componentId &amp;mdash; 컴포넌트의 고유 식별자로, 컴포넌트 인스턴스가 아닌 컴포넌트 자체를 식별합니다. 이 클래스는 실제 CSS 규칙을 가지지 않지만, 다른 컴포넌트를 참조해야 할 때 중첩 선택자에서 사용됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;generatedClassName &amp;mdash; 각 컴포넌트 인스턴스마다 고유하며, 실제 CSS 규칙을 포함합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이렇게 해서 최종 렌더링된 HTML 요소는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;vbnet&quot;&gt;&lt;code&gt;&amp;lt;button class=&quot;sc-bdVaJa jsZVzX&quot;&amp;gt;I'm a button&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;componentWillReceiveProps() 이제 Button이 마운트된 상태에서 props를 변경해 보겠습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이를 위해 Button에 대해 더 상호작용적인 예제를 만들어야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let sizeValue = 24;

const updateButton = () =&amp;gt; {
  ReactDOM.render(
    &amp;lt;Button sizeValue={sizeValue} onClick={updateButton}&amp;gt;
      Font size is {sizeValue}px
    &amp;lt;/Button&amp;gt;,
    document.getElementById('root')
  );
  sizeValue++;
}

updateButton();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;버튼을 클릭할 때마다 componentWillReceiveProps()가 호출되며, 증가된 sizeValue prop과 함께 다음과 같은 작업을 수행합니다:&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;태그 템플릿을 평가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;새로운 CSS 클래스 이름을 생성합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;스타일을 stylis로 전처리합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;전처리된 CSS를 페이지에 삽입합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;몇 번 클릭한 후 개발자 도구에서 생성된 스타일을 확인하면 다음과 같은 결과를 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;&amp;lt;style data-styled-components&amp;gt;
  /* sc-component-id: sc-bdVaJa */
  .sc-bdVaJa {} 
  .jsZVzX{font-size:24px;color:coral; ... } .jsZVzX:hover{background-color:bisque;}
  .kkRXUB{font-size:25px;color:coral; ... } .kkRXUB:hover{background-color:bisque;}
  .jvOYbh{font-size:26px;color:coral; ... } .jvOYbh:hover{background-color:bisque;}
  .ljDvEV{font-size:27px;color:coral; ... } .ljDvEV:hover{background-color:bisque;}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;각 CSS 클래스의 유일한 차이점은 font-size 속성이며, 사용되지 않는 CSS 클래스는 제거되지 않습니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;그 이유는 제거하는 것이 성능에 부담을 주는 반면, 유지하는 것은 성능에 영향을 주지 않기 때문입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기에는 작은 최적화가 하나 있습니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;스타일 문자열에 보간이 없는 컴포넌트는 isStatic으로 표시&lt;/span&gt;되며, 이 플래그는componentWillReceiveProps()에서 동일한 스타일에 대한 불필요한 계산을 건너뛰기 위해 확인됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Performance tips&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled-components의 내부 동작 방식을 알면 성능에 더욱 집중할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;버튼 예제에는 이스터 에그가 하나 있습니다. (힌트: 버튼을 200번 이상 클릭해 보세요. styled-components가 콘솔에 숨겨진 메시지를 표시할 것입니다. 정말입니다!  )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;너무 궁금하다면, 메시지는 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;Over 200 classes were generated for component styled.button. 
Consider using the attrs method, together with a style object for frequently changed styles.
Example:
  const Component = styled.div.attrs({
    style: ({ background }) =&amp;gt; ({
      background,
    }),
  })`width: 100%;`

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;리팩토링 후 Button은 다음과 같은 모습입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;const Button = styled.button.attrs({
  style: ({ sizeValue }) =&amp;gt; ({ fontSize: sizeValue + 'px' })
})`
  color: coral;
  padding: 0.25rem 1rem; 
  border: solid 2px coral; 
  border-radius: 3px;
  margin: 0.5rem;
  &amp;amp;:hover {
    background-color: bisque;
  }
`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 모든 동적 스타일에 이 기법을 사용해야 할까요? 아닙니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;저의 개인적인 규칙은 결과 수가 불확정적인 모든 동적 스타일에는 style 속성을 사용하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;예를 들어, 워드 클라우드나 서버에서 다른 색상으로 로드된 태그 목록처럼 글꼴 크기를 사용자 정의할 수 있는 컴포넌트가 있다면 style 속성을 사용하는 것이 좋습니다. 그러나 기본, 기본(primary), 경고(warn) 등과 같은 다양한 버튼이 하나의 컴포넌트에 있다면, 스타일 문자열에서 조건부 보간(interpolation)을 사용하는 것이 괜찮습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 예제에서는 개발 버전을 사용하지만, 프로덕션 번들에서는 항상 styled-components의 프로덕션 빌드를 사용하는 것이 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;프로덕션 빌드는 더 빠르며, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;React와 마찬가지로 개발 경고를 많이 비활성화할 뿐만 아니라, 개발 버전이 Node.appendChild()를 사용하는 것과 달리 CSSStyleSheet.insertRule()을 사용하여 스타일을 페이지에 삽입&lt;/span&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;또한 babel-plugin-styled-components 사용을 고려하세요. 이 플러그인은 스타일을 로딩 전에 최소화하거나 전처리할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;styled-components의 워크플로우는 매우 간단합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;컴포넌트가 렌더링되기 직전에 필요한 CSS를 즉석에서 생성하며, 태그 문자열을 평가하고 브라우저에서 CSS를 전처리함에도 불구하고 충분히 빠릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 글은 styled-components의 모든 측면을 다루지는 않았지만, 주요한 부분에 초점을 맞추고자 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot; data-remove=&quot;true&quot;&gt;&amp;lt; 참고자료 &amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #333333;&quot;&gt;[사이트]&amp;nbsp;&lt;span style=&quot;color: #333333;&quot; data-remove=&quot;true&quot;&gt;#Midum&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732105713163&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;How styled-components works: A deep dive under the hood&quot; data-og-description=&quot;CSS-in-JS is getting more and more common in the modern front-end development and especially in the React community. styled-components&amp;hellip;&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; data-og-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uKd4b/hyXDiUZeW6/SoNFtgzii2m2WwXIoFJmZk/img.png?width=1200&amp;amp;height=624&amp;amp;face=0_0_1200_624,https://scrap.kakaocdn.net/dn/nSc0I/hyXDhofhRs/kEY475EUkpJCNwqkYW3x3K/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/CwVXJ/hyXDiHsDpP/Udmdvp2wVxbhbZclb1R3Fk/img.jpg?width=1358&amp;amp;height=453&amp;amp;face=0_0_1358_453&quot;&gt;&lt;a href=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/styled-components/how-styled-components-works-618a69970421&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uKd4b/hyXDiUZeW6/SoNFtgzii2m2WwXIoFJmZk/img.png?width=1200&amp;amp;height=624&amp;amp;face=0_0_1200_624,https://scrap.kakaocdn.net/dn/nSc0I/hyXDhofhRs/kEY475EUkpJCNwqkYW3x3K/img.jpg?width=1358&amp;amp;height=905&amp;amp;face=0_0_1358_905,https://scrap.kakaocdn.net/dn/CwVXJ/hyXDiHsDpP/Udmdvp2wVxbhbZclb1R3Fk/img.jpg?width=1358&amp;amp;height=453&amp;amp;face=0_0_1358_453');&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;How styled-components works: A deep dive under the hood&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CSS-in-JS is getting more and more common in the modern front-end development and especially in the React community. styled-components&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;lt;기타&amp;gt; How styled-components works: A deep dive under the hood&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기타</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/160</guid>
      <comments>https://sangcho.tistory.com/entry/How-styled-components-works-A-deep-dive-under-the-hood#entry160comment</comments>
      <pubDate>Wed, 20 Nov 2024 21:35:47 +0900</pubDate>
    </item>
    <item>
      <title>똑똑!! 레포지토리님 어디쯤이신가요?</title>
      <link>https://sangcho.tistory.com/entry/repository-history</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;History (1).jpg&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;339&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ENiXZ/btsKb9rVwrl/WJoYdUF68fLl3CVurwyRkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ENiXZ/btsKb9rVwrl/WJoYdUF68fLl3CVurwyRkK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ENiXZ/btsKb9rVwrl/WJoYdUF68fLl3CVurwyRkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FENiXZ%2FbtsKb9rVwrl%2FWJoYdUF68fLl3CVurwyRkK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;509&quot; height=&quot;339&quot; data-filename=&quot;History (1).jpg&quot; data-origin-width=&quot;509&quot; data-origin-height=&quot;339&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;ldquo;과거를 알면 현재가 보인다&amp;rdquo;&lt;/b&gt;는 말이 있다. 역사는 단순히 지나간 사건들의 기록에 그치지 않고, 과거의 경험은 우리가 현재의 문제를 이해하고 미래를 대비하는 데 중요한 교훈을 제공한다. 과거의 정치적 결정, 사회적 변화, 경제적 위기, 문화적 발전은 현재 우리가 직면한 도전과 기회들을 해석하는 데 도움을 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 역사는 사회적 갈등이나 혁명의 이유를 이해하게 함으로써, 현시대의 문제를 해결할 실마리를 제공하기도 한다. 이렇게 역사는 단순한 기록이 아니라, 우리가 현재를 올바르게 보고, 더 나은 미래를 만들어 가기 위한 나침반과도 같은 역할을 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;새로운 기술들도 마찬가지이다. 현재 사용되고 있는 기술들은 과거에 있었던 갈등이나 문제, 그리고 좌절과 고난에 경험 끝에서 나온 축적물들이다. 불편했던 과정과 좋지 못했던 결과물들을 바로잡기 위한 한 땀 한 땀의 노력들이 모여 지금 우리가 편리하게 사용하고, 조금은 더 나은 환경 속에서 살아갈 수 있는 듯하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;오늘의 이야기는 데이터를 저장하고 관리하는 공간인 &lt;b&gt;&quot;레포지토리&quot;&lt;/b&gt;에 집중을 해보려고 한다. 프로젝트의 소스 코드를 저장하고, 변경 사항을 추적하며, 여러 사람이 협업할 수 있게 도와주는 공간을 어떤 방식으로 운영을 하면 좋을지에 대해 생각 해보려한다. &lt;b&gt;레포지토리의 역사의 과정 속&lt;/b&gt;에서 어떤 불편함으로 인해 어떻게 개선을 할 수 있었는지 알아보고, 더 나은 운영을 위해 어떠한 노력들을 하고 있는지 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;intro.png&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rejMe/btsKbBW2peA/P5isAFsRg0l8g8kbX6urvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rejMe/btsKbBW2peA/P5isAFsRg0l8g8kbX6urvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rejMe/btsKbBW2peA/P5isAFsRg0l8g8kbX6urvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrejMe%2FbtsKbBW2peA%2FP5isAFsRg0l8g8kbX6urvk%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;791&quot; height=&quot;381&quot; data-filename=&quot;intro.png&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;(삼국사) 모놀리식 레포&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;모놀리식 레포란 &lt;b&gt;하나의 대규모 레포지토리에 프로젝트의 모든 코드, 모듈, 구성 요소를 저장하고 관리하는 소프트웨어 개발 방식을 의미&lt;/b&gt;한다. 여러 서비스나 애플리케이션의 코드가 분리된 여러 레포지토리가 아닌, 하나의 통합된 레포지토리에서 함께 관리되는 구조이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Monolithic Architecture Diagram.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezrRVh/btsKbAqjW3R/wSym88hNDHrYG11dMy1xuK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezrRVh/btsKbAqjW3R/wSym88hNDHrYG11dMy1xuK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezrRVh/btsKbAqjW3R/wSym88hNDHrYG11dMy1xuK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezrRVh%2FbtsKbAqjW3R%2FwSym88hNDHrYG11dMy1xuK%2Fimg.webp&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;428&quot; height=&quot;428&quot; data-filename=&quot;Monolithic Architecture Diagram.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;초기 소프트웨어 개발 환경에서는 복잡한 시스템 관리보다 &lt;b&gt;개발과 배포의 단순화&lt;/b&gt;가 중요했다. 하나의 레포지토리에서 모든 코드를 관리하면, 코드 베이스 전체를 한 번에 빌드하고 배포할 수 있어 작업이 단순화 될 수 있었다. 이로 인해 관리가 쉬워졌고, 한 레포지토리 안에서 &lt;b&gt;애플리케이션의 모든 부분을 통합 관리&lt;/b&gt;할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 대규모 소프트웨어 개발보다는 소규모 팀에서 소프트웨어를 개발하였기 때문에 &lt;b&gt;팀 전체가 같은 레포지토리에서 작업을 하면서 변경 사항을 쉽게 공유하고, 코드 리뷰와 협업을 한곳에서 처리&lt;/b&gt;할 수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;통합 테스트 또한 쉽게 수행 가능했다. 모든 코드가 한 곳에 있기 때문에 전체 시스템을 한 번에 테스트하고 빠르게 배포할 수 있었다. 공통된 라이브러리나 유틸리티 코드가 여러 모듈에서 쉽게 활용될 수 있었고, &lt;b&gt;코드 재사용이 간단&lt;/b&gt;했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;간편한 코드 관리, 효율적인 협업, 일관된 빌드 및 배포 프로세스, 통합된 테스트 환경, 코드 재사용성&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 소프트웨어가 점점 더 복잡해지고 팀이 확장됨에 따라, &lt;b&gt;모놀리식 레포에서 발생하는 문제들이 점차 부각&lt;/b&gt;되기 시작했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;레포지토리 자체가 커짐에 따라 &lt;b&gt;코드간의 의존성이 복잡해지고, 유지보수가 어려워졌다.&lt;/b&gt; 이는 빌드 및 테스트, 그리고 배포에도 영향을 끼쳤다. 코드베이스가 커질수록 시간이 증가할 뿐만 아니라 작은 변경 사항에 대한 비효율적인 빌드 및 배포 프로세스가 추가되는 등 필요 없는 시간을 소모해야 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 여러 개발자가 동시에 동일한 레포지토리에서 작업할 때 코드의 빈번한 충돌과 각 모듈이 독립적으로 관리되지 않기에 확장성에도 문제가 있었다. 이런 여러가지 기술적 부채가 쌓여가면서 더 나은 관리 방법의 도입이 필요해졌다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;빌드 및 테스트 속도 저하, 복잡성 증가, 배포의 어려움, 코드 작업 충돌 증가, 확장성 문제&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(고려사) 멀티 레포&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;멀티레포는 소프트웨어 개발이 점점 더 복잡해지고, 대규모 시스템이 확장됨에 따라 기존에 채택되었던 모놀리식 레포의 관리 부담과 비효율성이 두드러지게 되면서 등장하게 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;멀티 레포는 소프트웨어 개발 방식으로, 더 큰 애플리케이션의 서로 다른 프로젝트나 구성 요소를 별도의 레포지토리로 저장하고 관리하는 접근 방식을 의미한다.&amp;nbsp;&lt;/span&gt;각 프로젝트나 구성 요소는 자체 버전 관리 레포지토리를 가지며, 이를 통해 팀은 독립적으로 작업할 수 있다.&amp;nbsp;&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-filename=&quot;DALL&amp;amp;middot;E 2024-10-20 15.47.06 - A very simple and easy-to-understand diagram illustrating the multi-repo approach for a non-technical audience. Show three separate boxes labeled 'Pro.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bY4X9G/btsKbzE0weY/lrKXYcuKq5TWx42Kbu65P1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bY4X9G/btsKbzE0weY/lrKXYcuKq5TWx42Kbu65P1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bY4X9G/btsKbzE0weY/lrKXYcuKq5TWx42Kbu65P1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbY4X9G%2FbtsKbzE0weY%2FlrKXYcuKq5TWx42Kbu65P1%2Fimg.webp&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;460&quot; height=&quot;460&quot; data-filename=&quot;DALL&amp;middot;E 2024-10-20 15.47.06 - A very simple and easy-to-understand diagram illustrating the multi-repo approach for a non-technical audience. Show three separate boxes labeled 'Pro.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;위에 그림과 같이 멀티레포는 독립적으로 레포지토리가 별도 관리되므로 팀들은 서로 방해받지 않고 독립적으로 작업이 가능하다. 또한 프로젝트마다 권한을 설정할 수 있어 &lt;b&gt;보완 관리가 용이&lt;/b&gt;하며, 각 프로젝트나 모듈을 독립적으로 배포할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;새로운 기능이나 프로젝트를 추가 할 때도 꽤나 용이하다. &lt;b&gt;기존 코드와 충돌하지 않고 쉽게 확장&lt;/b&gt;이 가능하며, 각 레포지토리에 따라 독립적으로 관리되기 때문에 &lt;b&gt;소유권이 명확&lt;/b&gt;하면서도, &lt;b&gt;변경사항에 대해 쉽고 빠르게 추적이 가능하여 관리&lt;/b&gt;가 용이한 장점이 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;독립성, 보안강화, 유연한 배포, 확장성, 소유권 명확성, 의존성 관리, 간단한 버전 관리&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;그러나 항상 그렇듯 개선된 관리 포인트에서도 Trade off는 존재한다. 가장 커다란 문제는 &lt;b&gt;코드의 중복&lt;/b&gt;이었다. 여러 레포지토리에서 비슷한 기능을 구현하다 보면, 공통 코드를 공유하기 어렵고, 각 레포지토리마다 유사한 코드가 복제될 가능성이 현저하게 높아지는 것이 문제였다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;그다음으로 발생하는 문제는 &lt;b&gt;협업&lt;/b&gt;과 관련된 부분이었다. 사람 간의 협업, 코드 간의 협업의 아쉬움이 남았다. 각 팀이 독립적으로 프로젝트를 관리하기 때문에 전반적인 목표를 조율하는 데 어려움이 있고, 코드 스타일이나 품질에 대한 일관성 또한 유지하기가 어려운 부분이 있었다.&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;&lt;b&gt;테스트도 문제&lt;/b&gt;였다. 상대적으로 단위, 통합 테스트는 간단할 수 있지만, 하나의 통합된 애플리케이션을 테스트하기 위한 E2E 테스트는 꽤나 복잡한 절차를 거쳐야 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;마지막으로 &lt;b&gt;의존성에 대한 문제&lt;/b&gt;가 발생했다. 다양한 레포지토리가 서로 의존하는 경우 하나의 레포지토리에서 발생한 업데이트를 다른 레포지토리에 반영하는 과정과 이를 관리하는 부담이 늘어났다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 중복, 일관된 코드 품질 유지, 통합 테스트, 복잡한 협업, 의존성 업데이트&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;멀티 레포가 가지는 장점은 명확했지만, 또 다른 문제점이 발견되었다. 그러한 문제점의 어느 정도 커버할 수 있는 관리 방법을 찾아야 했다. 그 때 등장한 관리 방법이 &lt;b&gt;&quot;모노레포&quot;&lt;/b&gt;이다.&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;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(조선사) 모노레포&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;모노레포는 &lt;b&gt;여러 프로젝트의 코드를 동일한 저장소에 저장하는 소프트웨어 개발 전략&lt;/b&gt;이다. 이름에서 알 수 있듯이, 모노레포는 하나의 코드 저장소에 여러 프로젝트가 포함되어 있기 때문에 붙여진 이름이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;개별 프로젝트는 각각 별도의 생명 주기를 가진다. 모노레포는 &lt;b&gt;마이크로 프론트엔드를 사용하지 않고도 단일 저장소에서 여러 프로젝트를 관리하는 방법&lt;/b&gt;이다. 모노레포를 사용하면 단일 저장소에 여러 마이크로 프런트엔드 애플리케이션을 만들 수 있으며, 이러한 개별 마이크로 프런트엔드를 각각의 런타임에서 별도의 생명 주기로 배포할 수 있다. 마이크로 프런트엔드를 모노레포와 결합하면 마이크로 프런트엔드 구현과 관련된 복잡성의 일부를 해결할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Monorepo Diagram 2024-10-20.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FPKtS/btsKdLDm58M/7w4M6Cw2q9pkoRkFSXM7Y0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FPKtS/btsKdLDm58M/7w4M6Cw2q9pkoRkFSXM7Y0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FPKtS/btsKdLDm58M/7w4M6Cw2q9pkoRkFSXM7Y0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFPKtS%2FbtsKdLDm58M%2F7w4M6Cw2q9pkoRkFSXM7Y0%2Fimg.webp&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;396&quot; height=&quot;396&quot; data-filename=&quot;Monorepo Diagram 2024-10-20.webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;모노레포는 전체 코드베이스가 하나의 저장소에 있기 때문에 &lt;b&gt;팀 간의 협업을 더 쉽게 만든다.&lt;/b&gt; 모든 것이 한 곳에 있기 때문에 변경 사항을 추적하고 코드를 공유하기가 더 쉬워지고, &lt;b&gt;작업자들은 통일된 도구와 워크플로를 적용&lt;/b&gt;할 수 있다. 물론 공통적인 코드도 쉽게 공유할 수 있기 때문에 &lt;b&gt;코드 중복을 줄일 수 있다는 장점&lt;/b&gt;이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 의존성 관리를 단순화하는데, 모든 모듈이 단일 저장소에 호스팅되고 소싱되기 때문에 &lt;b&gt;의존성 충돌을 방지&lt;/b&gt;할 수 있고, 하나의 package.json 파일만 존재하기 때문에 의존성을 업데이트할 때마다 각 저장소에 의존성을 설치할 필요가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; letter-spacing: 0px;&quot;&gt;&amp;nbsp;전체 시스템을 한 번에 통합하고 테스트할 수 있어 &lt;b&gt;빌드 및 배포 과정이 단순화되고 일관적&lt;/b&gt;으로 배포가 가능한 환경이 구성된다는 것도 또 다른 장점이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드 공유와 재사용 용이, 일관된 개발 환경, 통합된 테스트 및 배포, 단순화된 의존성 관리, &lt;br /&gt;전체 시스템에 대한 가시성 증가&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;하지만 여전히 단점은 존재했다. 각 레포지토리의 크기가 커질수록 &lt;b&gt;빌드 및 테스트 시간이 길어지고, 수많은 모듈과 팀이 같은 레포지토리에서 작업을 하기 때문에 코드 충돌이나 관리상의 어려움&lt;/b&gt;은 여전히 발생했다. 합의된 컨벤션이 제대로 정해지지 않은 경우에는 코드를 추적하는 것에 어려움을 느낄 수 있었다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 &lt;b&gt;특정 모듈이나 기능만 업데이트해야 하는 경우 전체 애플리케이션을 배포해야 하는 경우&lt;/b&gt;가 생겼다. 부분 배포가 어렵기에 전체 프로젝트를 빌드하고 테스트해야 하는 경우가 빈번하게 생겨 성능 문제가 발생했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;파이프라인을 구성하는 것도 꽤나 복잡해졌는데, 누군가가 모노레포에 변경을 가하면, 파이프라인은 어떤 작업을 수행할지, 무엇이 변경되었는지, &lt;b&gt;해당 변경으로 인해 어떤 작업을 트리거해야 하는지, 무엇을 빌드하고 빌드하지 말아야 하는지를 파악&lt;/b&gt;해야 하는 과정이 추가되어야 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;빌드 및 테스트 성능, 복잡성 증가, 작업 충돌 가능성 증가, 배포의 유연성 저하, 복잡한 파이프라인 구성&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Nanum Gothic';&quot;&gt;(근&amp;amp;현대사)&amp;nbsp;마이크로 프론트&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;마이크로 프런트엔드는&lt;b&gt; 독립적으로 전달 가능한 프론트엔드 애플리케이션 기능들을 조합하여 전체 애플리케이션을 구성하는 소프트웨어 아키텍처 접근 방식&lt;/b&gt;이다. 이 전략에서는 프론트엔드 애플리케이션이 더 작은 애플리케이션이나 모듈로 분해되며, 이러한 각 모듈은 서로 독립적인 애플리케이션으로, 다른 팀들이 다른 기술을 사용해 개발, 테스트 및 배포할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;백엔드 개발에 익숙하다면, &lt;b&gt;마이크로 프론트엔드는 마이크로서비스의 개념을 프런트엔드에 확장한 것이라고 볼 수 있는데, 두 아키텍처는 유사한 개념&lt;/b&gt;을 가지고 있으며, 프런트엔드를 더 작고 관리하기 쉬운 부분으로 나누어 사용자 경험을 더 효과적으로 조정할 수 있는 아키텍처로 등장하게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuwLjl/btsKce0WC7r/FJwVj0pFSCPORGpqnBudtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuwLjl/btsKce0WC7r/FJwVj0pFSCPORGpqnBudtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuwLjl/btsKce0WC7r/FJwVj0pFSCPORGpqnBudtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuwLjl%2FbtsKce0WC7r%2FFJwVj0pFSCPORGpqnBudtK%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;776&quot; height=&quot;260&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;349&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;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;위 그림에서는 세 개의 서로 다른 마이크로 프런트엔드가 있다. 이는 소스 코드 저장소에서 &lt;b&gt;자율적인 팀들이 구축한 개별 기능들&lt;/b&gt;이라고 할 수 있다. 이들은 각각 독립적인 책임을 지며, 별도의 빌드 파이프라인을 가지고 독립적인 애플리케이션으로 배포된다. 따라서 주황색, 녹색, 보라색 박스는 각각 별도로 배포 가능한 요소이며, 실제로는 이 모든 배포 가능한 요소들이 프로덕션 환경에서 하나로 결합된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;예를 들어, 복잡한 전자상거래 애플리케이션에서 쇼핑 카트, 제품 카탈로그, 체크아웃 페이지, 결제 페이지, 사용자 프로필 페이지와 같은 기능별로 별도의 마이크로 프런트엔드를 가질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;이러한 기능들은 &lt;b&gt;독립적으로 개발, 확장, 테스트 및 배포&lt;/b&gt;될 수 있습니다. 각 모듈에 대해 다른 확장 전략을 사용할 수 있으며, 전체 애플리케이션을 확장하지 않고도 하나의 모듈을 더 많은 트래픽을 처리할 수 있도록 확장할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;그렇기에 사용자 프로필 페이지에 변경 사항을 적용했는데 해당 페이지가 제대로 작동하지 않는 경우가 생긴다면, 전체 애플리케이션에는 영향을 미치지 않기에 사용자는 여전히 제품 카탈로그나 쇼핑 카트 페이지를 방문할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;이번 글에 주제이기에 한 번 더 짚고 넘어가도록 하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;마이크로 프런트엔드는 &lt;b&gt;각 팀이 애플리케이션의 일부분을 구상부터 프로덕션까지 책임&lt;/b&gt;질 수 있다. 이는 각 팀에 더 많은 소유권을 부여하며, &lt;b&gt;자신들의 작업에 가장 적합한 기술, 코딩 스타일 및 아키텍처를 선택&lt;/b&gt;할 수 있다. 이는 호스트 페이지를 Vue로 작성하고, 다른 모듈을 React로 작성하는 것도 가능하다는 것을 의미한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 여러 모듈이 각기 다른 빌드를 가지고 있기 때문에 &lt;b&gt;프론트엔드 모듈을 독립적으로 배포&lt;/b&gt;할 수 있다. 각 모듈은 배포 파이프라인이 있어야 하며, 이는 &lt;b&gt;전체 애플리케이션을 다시 배포할 필요 없이 변경된 부분만 다시 배포&lt;/b&gt;할 수 있다는 것을 증명한다. 각 기능을 독립적으로 구현할 수 있기 때문에 &lt;b&gt;개발 속도를 크게 향상&lt;/b&gt;할 수 있고, 독립적인 단위로 분리되어 있어 &lt;b&gt;애플리케이션 진화에 따라 유연하게 확장&lt;/b&gt;을 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;팀의 자유로운 기술 선택, 독립적인 배포, 빠른 구현 및 개발, 확장성&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;최신 소프트웨어 아키텍처 전략이라도 여전히 풀어야 할 숙제는 남아있다. 수많은 모듈들이 독립적으로 운영되기에 &lt;b&gt;분리된 컴포넌트와 마이크로 파트의 배포를 조율하는 작업이 복잡해질 수 있다&lt;/b&gt;. 이를 유지하기 위해 추가적인 노력과 리소스는 존재하며 해당 작업을 수행하는 팀 간의 많은 조정이 요구될 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;또한 여러 모듈이 각각의 독립적인 빌드 및 배포 파이프라인을 가지다 보니, &lt;b&gt;페이지 로드 시 성능에 영향&lt;/b&gt;을 미칠 수 있다. 특히 여러 모듈이 각각의 리소스를 요청하거나 서로 다른 기술 스택을 사용하면 초기 로드 속도가 느려질 수 있다는 단점이 존재한다. 그렇기에 다양한 모듈 간 공통으로 사용할 수 있는 디자인 시스템이나 스타일 가이드를 구축하는 데 추가적이 노력이 필요하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;모듈이 독립적이기 때문에 &lt;b&gt;통신과 관련된 문제가 생길 여지 또한 존재&lt;/b&gt;한다. 각 모듈 간의 통신을 위해 추가적인 API 호출, 데이터 전달 등이 필요할 수 있는데, 이로 인해 오버헤드가 발생하고 성능이 저하될 가능성이 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;이러한 각각의 단점은 &lt;b&gt;관리 비용 및 리소스를 증가시키는 공통적인 원인&lt;/b&gt;이 될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;복잡한 테스트와 배포, 성능 문제, 통신 오버헤드, 관리비용 증가&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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: #333333; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그래서 결론은?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;각 소프트웨어 아키텍처 전략들은 유지와 보수를 위해 현저하게 노력해 왔으며, 지속되는 문제점을 타개하기 위한 해결책을 도출해 내는 과정을 반복해 왔다.&lt;b&gt; 이는 과거 소프트웨어 개발 환경과 시대적 배경과 밀접해 있으며, 상황에 맞게 성장하고 진화했음을 알 수 있다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;각 전략의 핵심들은 이번 정리를 통하여 이론적으로는 어느 정도 이해를 했다. 바깥의 표면의 껍질을 들추어 보았다면, 이제는 들춰 본 껍질 안에 내용을 살펴볼 차례이다. 머릿속에 맴도는 지식들을 코드로 구체화해 나가는 과정을 행동으로 옮겨 보면서 아직 채워지지 않은 빈틈을 채워가보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;lt; 참고자료 &amp;gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1729415226065&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;Monorepo vs. multi-repo: Different strategies for organizing repositories&quot; data-og-description=&quot;Starting a new project? Wondering about the best strategy for managing architecture at the code repository level? In this new blog, Francisco Plaza shares insights into this common challenge. He sheds light on his experiences and weighs the benefits and ch&quot; data-og-host=&quot;www.thoughtworks.com&quot; data-og-source-url=&quot;https://www.thoughtworks.com/insights/blog/agile-engineering-practices/monorepo-vs-multirepo&quot; data-og-url=&quot;https://www.thoughtworks.com/insights/blog/agile-engineering-practices/monorepo-vs-multirepo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/IMqWL/hyXlMWNjRP/qEiL4Qn2q18U8FiMMV8GvK/img.jpg?width=1200&amp;amp;height=677&amp;amp;face=375_421_519_578&quot;&gt;&lt;a href=&quot;https://www.thoughtworks.com/insights/blog/agile-engineering-practices/monorepo-vs-multirepo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.thoughtworks.com/insights/blog/agile-engineering-practices/monorepo-vs-multirepo&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/IMqWL/hyXlMWNjRP/qEiL4Qn2q18U8FiMMV8GvK/img.jpg?width=1200&amp;amp;height=677&amp;amp;face=375_421_519_578');&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;Monorepo vs. multi-repo: Different strategies for organizing repositories&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Starting a new project? Wondering about the best strategy for managing architecture at the code repository level? In this new blog, Francisco Plaza shares insights into this common challenge. He sheds light on his experiences and weighs the benefits and ch&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.thoughtworks.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;figure id=&quot;og_1729415164332&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;대형 웹 애플리케이션 Micro Frontends 전환기 (1) | 요즘IT&quot; data-og-description=&quot;이번 글에서는 플렉스 팀이 기존 제품을 마이크로 프론트엔드 아키텍처로 전환했던 8개월간의 과정에 대해서 소개합니다. 왜 플렉스 웹앱을 마이크로 프론트엔드 아키텍처로 전환했는지, 어떤 &quot; data-og-host=&quot;yozm.wishket.com&quot; data-og-source-url=&quot;https://yozm.wishket.com/magazine/detail/2408/&quot; data-og-url=&quot;https://yozm.wishket.com/magazine/detail/2408/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cc9iys/hyXhK7qP5y/vqxCOPLPhANgycu9WBKbs0/img.jpg?width=4000&amp;amp;height=2250&amp;amp;face=0_0_4000_2250,https://scrap.kakaocdn.net/dn/c6EXe6/hyXhN374c1/msRadapP3EUxA4mP7qAwW0/img.jpg?width=4000&amp;amp;height=2250&amp;amp;face=0_0_4000_2250&quot;&gt;&lt;a href=&quot;https://yozm.wishket.com/magazine/detail/2408/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://yozm.wishket.com/magazine/detail/2408/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cc9iys/hyXhK7qP5y/vqxCOPLPhANgycu9WBKbs0/img.jpg?width=4000&amp;amp;height=2250&amp;amp;face=0_0_4000_2250,https://scrap.kakaocdn.net/dn/c6EXe6/hyXhN374c1/msRadapP3EUxA4mP7qAwW0/img.jpg?width=4000&amp;amp;height=2250&amp;amp;face=0_0_4000_2250');&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;대형 웹 애플리케이션 Micro Frontends 전환기 (1) | 요즘IT&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 플렉스 팀이 기존 제품을 마이크로 프론트엔드 아키텍처로 전환했던 8개월간의 과정에 대해서 소개합니다. 왜 플렉스 웹앱을 마이크로 프론트엔드 아키텍처로 전환했는지, 어떤&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;yozm.wishket.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1729415183000&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;[SaaS] Micro Frontends를 위해 Module Federation 적용하기&quot; data-og-description=&quot;복잡하고 거대한 제품을 효과적으로 개발, 운영, 배포하기 위한 고민과 도전 by 강남언니 블로그&quot; data-og-host=&quot;blog.gangnamunni.com&quot; data-og-source-url=&quot;https://blog.gangnamunni.com/post/saas-microfrontends/&quot; data-og-url=&quot;https://blog.gangnamunni.com/post/saas-microfrontends/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bKWfjS/hyXhNC1akv/Hn2LYW0Dzl8HsnVJ43u4Ik/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/0P3Lx/hyXhNwhk0J/kFqHrL2vQr8apeKLuxQVA0/img.png?width=2226&amp;amp;height=1906&amp;amp;face=0_0_2226_1906,https://scrap.kakaocdn.net/dn/drgzgh/hyXhQGy6JR/qU98s0QNA6KHATfIuZbBJ1/img.png?width=2226&amp;amp;height=1140&amp;amp;face=0_0_2226_1140&quot;&gt;&lt;a href=&quot;https://blog.gangnamunni.com/post/saas-microfrontends/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.gangnamunni.com/post/saas-microfrontends/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bKWfjS/hyXhNC1akv/Hn2LYW0Dzl8HsnVJ43u4Ik/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/0P3Lx/hyXhNwhk0J/kFqHrL2vQr8apeKLuxQVA0/img.png?width=2226&amp;amp;height=1906&amp;amp;face=0_0_2226_1906,https://scrap.kakaocdn.net/dn/drgzgh/hyXhQGy6JR/qU98s0QNA6KHATfIuZbBJ1/img.png?width=2226&amp;amp;height=1140&amp;amp;face=0_0_2226_1140');&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;[SaaS] Micro Frontends를 위해 Module Federation 적용하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;복잡하고 거대한 제품을 효과적으로 개발, 운영, 배포하기 위한 고민과 도전 by 강남언니 블로그&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.gangnamunni.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;똑똑!! 레포지토리님 어디쯤이신가요?&amp;nbsp;end&lt;/span&gt;&lt;/p&gt;</description>
      <category>기타</category>
      <category>micro frontend</category>
      <category>mono repo</category>
      <category>monolith repo</category>
      <category>multi repo</category>
      <category>Repository</category>
      <category>마이크로프론트엔드</category>
      <category>멀티레포</category>
      <category>모노레포</category>
      <category>모놀리식</category>
      <category>소프트웨어 아키텍처 전략</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/158</guid>
      <comments>https://sangcho.tistory.com/entry/repository-history#entry158comment</comments>
      <pubDate>Sun, 20 Oct 2024 18:21:47 +0900</pubDate>
    </item>
    <item>
      <title>글또라는 퍼즐 한 조각</title>
      <link>https://sangcho.tistory.com/entry/%EA%B8%80%EB%98%90%EB%9D%BC%EB%8A%94-%ED%8D%BC%EC%A6%90-%ED%95%9C-%EC%A1%B0%EA%B0%81</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;276&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WMamb/btsJYI2QUJa/63TfKGliaigHSpSmmaHlrK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WMamb/btsJYI2QUJa/63TfKGliaigHSpSmmaHlrK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WMamb/btsJYI2QUJa/63TfKGliaigHSpSmmaHlrK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWMamb%2FbtsJYI2QUJa%2F63TfKGliaigHSpSmmaHlrK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;376&quot; height=&quot;249&quot; data-origin-width=&quot;276&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;얼마전 방 구석 한켠에 쌓여있던 짐들을 정리해야겠다는 마음을 먹고, 뽀얗게 쌓인 먼지와 사투를 벌이며 물건을 하나씩 들추어 보았다. 오랜시간 동안 쌓였던 기억을 더듬어보듯이, 물건을 하나씩 들출 때마다 예전의 기억이 새록새록 떠올랐다. 손끝이 물건에 스칠 때마다 기억의 한 조각이 눈 앞에 펼쳐지는 듯, 과거로 돌아가 그 때의 나를 만날 수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;그 때 낯선 물건 하나를 발견하였다. 빈틈 투성이, 완벽하게 구성되어 있지 않은 퍼즐이었다. &lt;u&gt;군데군데 비어있는 다 채워지지 않은 퍼즐의 모습은 아직은 부족하고 빈틈 투성이인 나를 보는 듯 했다.&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;누군가는 말한다. &lt;b&gt;&quot;세상의 완벽한 사람은 없다&quot;&lt;/b&gt;라고, 여전히 그 믿음을 갖고 인생을 살아가고 있지만, 가끔씩 고개를 갸우뚱하기도 한다. 내가 아직은 세상의 많은 사람들을 만나보지 못한거라 단정을 지으면서 말이다. 의심의 눈초리가 커져갈 무렵, 글또라는 퍼즐 한조각이 내게 찾아왔다. 비어 있는 한 구석에 알맞게 채워 넣으라는 듯, 반성과 탄성을 동시에 지닌 작지만 열정으로 응축된 한 덩어리를 가지고 말이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;u&gt;맞춰진, 그리고 맞출 글또라는 퍼즐 한 조각, 어땠고 어떠할까?&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;글또라는 퍼즐 한 조각&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;세상의 사람은 많고, 그들의 생각은 다르기 때문에, 생각의 폭을 늘리기 위해 그들을 만나고 싶었어요&quot;&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;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;만약 글또 커뮤니티 운영진과 면접에서 &lt;b&gt;&quot;지원 동기&quot;&lt;/b&gt;에 대한 질문을 물어 보았다면, 위와 같이 대답을 했을 것이다. 물론 글의 대한 관심과 욕심도 지대하게 높지만, 좋은 글을 작성하기 위해서 많은 사람들과 많은 것들 보고, 듣고, 말하는 일련의 반복의 과정이 필요하다고 생각한다. 내가 생각하지 못했던 아이디어가 누군가에 의해 도출될 수도 있고, 깊게 오랫동안 고민했던 문제를 쉽게 해결할 수 있다고 생각했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;u&gt;실제 가진 힘보다 더 많은 것을 들어올리는 지렛대처럼 누군가의 생각을 지렛대로 활용해 저 멀리 있던 의문의 섬을 조금 더 빨리 갈수 있는 방법을 찾을 수 있을 거라 생각했다.&lt;/u&gt;&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;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;글 쓰는 개발자 모임, 글또&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글또는 3가지의 비전을 가지고 운영된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;u&gt;1. 글을 작성하는 개발 직군들이 모여서, 좋은 영향을 주고 서로 같이 자랄 수 있는 커뮤니티&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;u&gt;2. 개발자들의 성장을 지원하는 커뮤니티&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;u&gt;3. 각자의 직군에서 얻을 수 있는 내용을 토대로 글쓰기 진행, 부가적으로 삶의 철학, 여러 고민을 나누는 커뮤니티&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개발자의 개인의 성장에 포커싱을 맞추는 것이 아닌, 함께 성장하면서 서로에게 좋은 영향을 주는 것에 비중을 둔 글또가 가지고 있는 힘은 거인의 어깨 정상에 깃발을 꽂고, 아름다운 경치를 바라보는 낭만과 같지 않을까 생각했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;글또 OT의 참석을 했을 때 3가지의 비전을 내세운 이유를 더 확실히 알 수 있었는데, 여러 이야기들 중 가장 공감이 갔던 내용은 아래와 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&quot;사람은 혼자 살 수 없고, 자신이 가지고 있는 지식은 계속 레거시가 된다. 혼자가 아닌 같이 공유하고 성장하는 것의 가치가 크다&quot;&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;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;내가 가지고 있는 지식과 다른 누군가가 가지고 있는 지식을 공유하고 융합했을 때, 생각한 것 보다 더 커다란 시너지를 낼 수 있다는 사실을 경험한 나로서는 너무나 공감이 가는 이야기였다. 그런 황홀한 경험을 글또를 통해 다시 한번 할 수 있을거라 생각을 하니, 이번 6개월간의 성장이 무척이나 기다려졌다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;지금까지 맞춰보았던 퍼즐 조각들&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이번 활동 기수는 10기지만, 사실 난 저번 기수인 9기에도 활동을 하였다. 9기때 느꼈던 좋은 경험들이 모여 10기를 지원했다고 해도 무방하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;오프라인과 온라인 활동을 병행하며 참여할 수 있는 글또에서 조금 더 다양하고 새로운 활동들에 참여하지 못함에 아쉬움도 있지만, 재밌고 즐겁게 활동했던 옛 기억들이 새록새록 떠오르는 지금, 어떤 활동들을 했는지 나열해보려고 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;글쓰기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글또에서 가장 메인이 되는 활동이다. 격주마다 하나의 글을 본인의 블로그를 통해 발행을 해야한다. 커뮤니티에 활동하는 분들께 제출한 글의 피드백도 받아볼 수 있으니 일석이조라 할 수 있다. 9기에서는 약 5개월간 활동했으니 그 기간동안 12개의 글을 작성하고 발행하였다. 글의 짜임새와 물 흐르듯이 잘 읽히는 가독성에 대한 고민을 품고 매번 글을 작성하였는데, 글또에서 발행한 1번째 글과 마지막 글을 살펴 보았을 때 5개월간의 시간이 헛되지 않았음을 조금이나마 느낄 수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;또한 격주에 한 번씩 글을 제출해야 하니 벼락치기를 잘 못하는 나로서는 잠깐 시간의 공백이 생길 때 (10분, 20분) 틈틈히 글을 써야했다. 처음에는 글의 첫 문장을 떼는 것도 힘들었지만, 습관적으로 반복하다보니 글의 단락을 완성할 수 있는 수준까지 올라왔다. 꾸준함의 힘을 지대로 느낄 수 있던 시간이었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;여러 사람들의 피드백을 받아보는 것도 소중한 경험 중 하나였다. 글에 대한 나의 생각과 타인의 생각의 절충점을 포용하는 실력, 타인의 생각에 대해 공감하는 능력, 여러 의견을 받아 조금은 갖혀있던 글을 전개하는 방식의 족쇄를 풀어나가는 시간 또한 값진 경험이었다. 정성스럽게 달아주신 여러 의견들은 글을 쓸 때마다 참고할 수 있는 나의 소중한 사전이 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;커피챗&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글또 활동을 하기 전 글쓰기 다음으로 중요하게 생각했던 목표 중 하나였다. 많은 사람들과 치열한 고민을 통해 올바른 성장의 소스를 함께 찾아보는 것, 커피를 곁들이면서.. 본래 사람을 좋아하고, 이야기를 듣고 말하는 것에 부담을 느끼지 않던 나는 이런 커뮤니티가 가지는 장점을 최대한 활용해보고 싶었다. 어색한 분위기에 초점을 맞추는 것이 아닌 대화의 본질적인 핵심의 귀 기울이는 올바른 방법을 함께 찾아가고 싶었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;글또 9기를 활동하는 동안 5회 이상의 커피챗을 진행하였고, 개발 이외의 다른 환경에서 살아온 삶에 대한 소개와 인생을 마주하는 본인의 방법 등 인간으로서 나눌 수 있는 이상의 가치를 서로가 탐독하고, 공감하는 시간은 내게 있어 그 무엇과도 바꿀 수 없는 소중한 이상의 것이었다. 하나의 조그마한 목소리가 커다란 울림을 주는 경험을 해보고, 무심코 던진 하나의 문장이 새로운 시각으로 바라볼 수 있는 지렛대의 역할을 하는 등, 챗바퀴 처럼 반복적으로 돌아가는 일상의 윤활유를 부어 뻑뻑했던 곳곳의 순간들을 조금은 유연하게 바라볼 수 있도록 도와주었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;크고 작은 오프라인 모임&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글또는 개발자라는 직업을 가진 사람들이 관련 시장에 대해 시시콜콜 이야기하는 공간을 만들어 주는 역할도 하지만, 오로지 개발이란 주제에만 집중하지는 않는다. 내가 느꼈던 글또는 사람에 더 초점을 맞췄다고 생각한다. &lt;u&gt;그들의 취미, 특기, 흥미, 관심사 등 그 순간의 감정을 공유함으로서 성장하고, 생각함으로서 나아가던 길을 뒤 돌아보며 반성하는 그런 장을 만들어 주는 곳이라 생각했다.&lt;/u&gt; 그렇기에 크고 작은 오프라인 모임들이 상당했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;주로 활동했던 소모임은 달리기를 좋아하다보니 자연스럽게 눈길이 갔던 &lt;b&gt;&quot;달리또&quot;&lt;/b&gt;와 글 제출에 있어 방어책을 세워면서도 호기롭게 시작했던 &lt;b&gt;&quot;패스없또&quot;&lt;/b&gt;였다. 물론 같은 지역 구들끼리 모임을 갖기 위한 취지로 만들어진 &lt;b&gt;&quot;은평또&quot;&lt;/b&gt;, 초록색을 좋아해 캠핑을 시작하면서 캠핑 장비에 정보를 얻기 위해 참가했던 &lt;b&gt;&quot;캠핑또&quot;&lt;/b&gt; 등 다른 여러 소모임들도 활동을 하였지만, 우선순위가 높지는 않았다. 공통의 관심사가 있다보니 서로간의 대화가 물 흐르듯 유연하게 흘러갔고, 대화의 티키타카가 날로 발전하다보니 과감한 질문들도 서슴치 않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;그럼에도 불구하고 가장 즐거웠고 알찬 오프라인 모임을 꼽으라면, &lt;b&gt;&quot;프론트 빌리지 반상회&quot;&lt;/b&gt;라 할 수 있을 것 같다. 약 100명(?)에 가까운 대규모 인원이 컨퍼런스가 아닌 네트워킹 목적으로 모여 각 회사에서 일을 하며 느끼는 고민, 프론트 개발자의 미래, 그리고 업무에 대한 경험 공유 등 같은 직무이기 때문에 공감할 수 있는 주제들이 비어있는 공간의 풍성함을 채웠다. 3시간 정도 진행이 되었지만, 그 이상의 것들을 인생의 장바구니에 담아갈 수 있는 유익한 시간이었던 것 같다.&amp;nbsp;&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;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;여전히 남아있는 퍼즐 조각들&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;9기를 넘어 10기 활동을 이어나가고 있는 요즘, 9기에서 달성하지 못했던 또는 생각지 못했던 목표를 이 글을 통해 정리해보려고 한다. 머리속으로만 생각하는 것보다 다수의 사람들에게 10기에서 이루고 싶은 목표를 퍼트리고, 마음가짐을 다잡는 것이 더 좋은 방법이라는 것을 알고 있다. 그렇기에 아직 채워지지 않은 퍼즐 조각들에 대해 하나씩 말씀드려보려 한다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;아직은 해매고 있는 나 톺아보기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;20대 후반, 잘 다니고 있던 직장을 관뒀다. 영업관리자로 첫 번째 커리어를 시작했지만, 매일 다른 가면을 써가며 출근을 했던 모습이 안쓰럽다 못해 불쌍했다. &lt;b&gt;&quot;나라는 존재가 가면에 종속되면 어떡하지&quot;&lt;/b&gt;라는 걱정으로 하루하루를 버텼던 것 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;30대 초반, 나는 개발자로 두 번째 커리어를 시작하였다. 누군가가 &lt;b&gt;&quot;무슨 일 하세요?&quot;&lt;/b&gt; 라고 물어보면, &lt;b&gt;&quot;저 개발하고 있습니다&quot;&lt;/b&gt;라는 답변을 하고 싶어 절실하게 발버둥쳤던 기억이 지금도 생생하다. 주변에 만류에도 불구하고, 내가 좋아하는 색깔의 옷을 입기 위해 부단히 노력했다. 결국 개발자가 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;약 3년정도 프론트 개발자의 길을 걸었을 무렵이었던 것 같다. 비전공자라는 꼬리표를 싹둑 자를 수 없기에, 퇴근 후 온전한 모든 시간을 개발 공부에 쏟았다. 그렇게 3년 정도 하다보니 내 몸에 체득된 개발 공부라는 습관은 어느새 뗄 수 없는 내 친한 친구가 되어 있었다. 성장하려고 하는 무리(동아리, 사이드프로젝트 대원들)들과 함께 하다보니 힘듦보다는 안 쓰던 근육을 썼을 때 찾아오는 근육통 정도의 기분 좋은 아픔이 더 컸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;현재, 나는 약 4년정도 프론트 개발자로의 같은 길을 걷고 있다. &lt;b&gt;&quot;지금도 같은 마음으로 개발에 대한 믿음을 가지고 있습니까?&quot;&lt;/b&gt;라는 질문을 받게 된다면, 나는 이렇게 대답할 것 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;&quot;아니요, 잘 모르겠습니다.&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;&lt;u&gt;모든 선택의 옳음은 존재하지 않고, 그 선택이 옳다고 생각하는 믿음은 존재한다고 했을 때, 내가 걸어가고 있는 이 길이 이후에도 같은 길일지에 대한 믿은은 미지수다.&lt;/u&gt; 나 자신과 대화의 시간을 자주 갖는다고 생각하지만, 여전히 의문 투성이인 질문들은 길을 잃고 떠도는 가여운 길 고양이처럼 내일, 이 길에 대한 믿음을 걱정하기일수다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;개발 공부에만 100% 투자했던 지난 3년간의 나날은 내게는 너무나 중요했기에, 앞으로 남아 있는 삶의 올바른 선택의 믿음을 가져가는 것은 더 중요한 숙제 중 하나이다. 그런 숙제를 이번 글또 10기를 통해 풀어보고 싶다. 수학의 정답을 추론하기 위한 식이 모두 다르듯이, 결과가 아닌 과정에 집중하여, 10기 멤버들의 의견과 생각을 귀 기울여 경청하는 6개월의 시간을 가질 예정이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;시간 분배를 효율적으로 하여, 더 많은 참여를 해내고 싶은 이번 활동은 앞으로 삶의 터닝포인트로 첫 걸음이 될 것 같다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;그 많던 2조각 퍼즐은 올바른 자리에 놓였을까?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&amp;nbsp;어떤 영화는 아름다운 결말이 있는 반면, 어떤 영화는 청중의 생각에 맡기는 열린 결말으로 전개될 때가 있다. 열린 결말일 수록 청중의 생각은 다양하게 펼쳐지고, 그 이후를 상상 하게 된다. 지금 내가 가지고 있는 2조각의 퍼즐 조각은 열린 결말에 대한 조건을 가지고 있다. &lt;u&gt;글또라는 청중들의 생각과 내 인생의 주인공인&lt;b&gt; &quot;나&quot;&lt;/b&gt;의 생각이 만들어 가는 내 삶의 퍼즐 조각들은 어떻게 전개될까?&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글또 활동이 끝나는 시점, 여전히 열린 결말일지, 아름다운 결말일지에 대한 글을 남겨볼 예정이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>기타</category>
      <category>개발자</category>
      <category>글</category>
      <category>글또</category>
      <category>다짐</category>
      <category>인생</category>
      <category>인생의 퍼즐</category>
      <category>커뮤니티</category>
      <author>Santos</author>
      <guid isPermaLink="true">https://sangcho.tistory.com/157</guid>
      <comments>https://sangcho.tistory.com/entry/%EA%B8%80%EB%98%90%EB%9D%BC%EB%8A%94-%ED%8D%BC%EC%A6%90-%ED%95%9C-%EC%A1%B0%EA%B0%81#entry157comment</comments>
      <pubDate>Sat, 12 Oct 2024 23:20:42 +0900</pubDate>
    </item>
  </channel>
</rss>