<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>잼굴 코딩공장</title>
    <link>https://jamgul.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 9 May 2026 03:12:20 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>잼굴</managingEditor>
    <image>
      <title>잼굴 코딩공장</title>
      <url>https://tistory1.daumcdn.net/tistory/5191009/attach/06e26ddee00f414f8e1a1596156e3525</url>
      <link>https://jamgul.tistory.com</link>
    </image>
    <item>
      <title>잼폴</title>
      <link>https://jamgul.tistory.com/87</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;logo.PNG&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QBkGp/btslaHNRFmB/1wZHvaP3pXMMED2t8jp9Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QBkGp/btslaHNRFmB/1wZHvaP3pXMMED2t8jp9Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QBkGp/btslaHNRFmB/1wZHvaP3pXMMED2t8jp9Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQBkGp%2FbtslaHNRFmB%2F1wZHvaP3pXMMED2t8jp9Tk%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;211&quot; height=&quot;105&quot; data-filename=&quot;logo.PNG&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투표 커뮤니티.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 뭐먹을지 골라줘, 옷 어떤거 살지골라줘, 어디 놀러갈지 골라줘 등 일상생활속 선택을 투표로 받는 커뮤니티&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;사용기술&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. React&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. TypeScript&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Redux-toolkit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Axios&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Firebase&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 커뮤니티 게시물 CRUD&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 카테고리별 인기게시물 모으기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 인기게시물 메인좌측 / 랜덤게시물 메인 우측&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 내가 올린 게시물들 모아보기&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;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;진행&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 리액트+파이어베이스 연동 ✔️&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 회원가입 기능 ✔️&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 게시물 CRUD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 투표 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 인기게시물 취합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 랜덤게시물 뿌리기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 신고기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/87</guid>
      <comments>https://jamgul.tistory.com/87#entry87comment</comments>
      <pubDate>Thu, 22 Jun 2023 20:51:34 +0900</pubDate>
    </item>
    <item>
      <title>Next.js  'use client' 에러 고치는방법</title>
      <link>https://jamgul.tistory.com/86</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;error_img.png&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lE0EJ/btscCCnctd5/TXKCKrQrQ1jY6iGS0UkmAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lE0EJ/btscCCnctd5/TXKCKrQrQ1jY6iGS0UkmAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lE0EJ/btscCCnctd5/TXKCKrQrQ1jY6iGS0UkmAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlE0EJ%2FbtscCCnctd5%2FTXKCKrQrQ1jY6iGS0UkmAk%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;236&quot; data-filename=&quot;error_img.png&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;542&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js를 사용한다면&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;Next.js에서 클라이언트 컴포넌트를 사용하기위해서는 코드 최상단에 'use client'를 작성해두면되고, 이후에는 다양한 함수들을 사용할수있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 !!!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;'use client'를 사용하면&lt;/p&gt;
&lt;pre id=&quot;code_1682433090518&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;error - SyntaxError: Unexpected token u in JSON at position 0

at JSON.parse (&amp;lt;anonymous&amp;gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐 이런 에러가 자꾸 뜬다.. 공식문서에서 해보라는 대로해도 똑같고 뭐 자꾸 JSON.parse 파싱에러가 자꾸뜬다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 use client를 안쓰면&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1682433359253&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; 1 | // 'use client';
 2 | import { useState } from 'react'
   :          ^^^^^^^^
 3 | 
 4 | export default function Counter() {
 4 |     const [count, setCount] = useState(0);
   `----&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 컴포넌트 선언이 안됐을때 뜨는 오류가 뜬다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 모르겟고...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;해 결 법&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;node_modules\next\dist\build\webpack\loaders\next-flight-loader\index.js 파일에서&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1682433511156&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const proxy = createProxy(&quot;${this.resourcePath}&quot;)


const proxy = createProxy(String.raw\`${this.resourcePath}\`)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;첫줄로 되어있는걸&amp;nbsp; 밑에&lt;br /&gt;const proxy = createProxy(String.raw\`${this.resourcePath}\`)&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이걸로 변경해주면 된다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&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;뭐 찾아보니까 13.3.0버전에서만 일어나는듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;윈도우 환경에서&amp;nbsp; path 경로를 읽을때 백슬래시랑 문자열 이스케이프 과정에서 오류가 발생한단다...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모르겠고 그냥 저 경로에 저 코드만 변경해주면 잘 작동됨 수고링~&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>NEXT.js</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/86</guid>
      <comments>https://jamgul.tistory.com/86#entry86comment</comments>
      <pubDate>Tue, 25 Apr 2023 23:41:41 +0900</pubDate>
    </item>
    <item>
      <title>NEXT.js의 라우팅에 대해.araboja</title>
      <link>https://jamgul.tistory.com/85</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;135F5D43507FA36011.jpg&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DiBvW/btsayWzCBEc/fWk9ED5xsrSxgKM2AxCrek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DiBvW/btsayWzCBEc/fWk9ED5xsrSxgKM2AxCrek/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DiBvW/btsayWzCBEc/fWk9ED5xsrSxgKM2AxCrek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDiBvW%2FbtsayWzCBEc%2FfWk9ED5xsrSxgKM2AxCrek%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;337&quot; height=&quot;385&quot; data-filename=&quot;135F5D43507FA36011.jpg&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;506&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;현재 NEXT.js는 계속 업데이트 되고있다. 지금은 13.3 버전임 ㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12버전&lt;/b&gt; 선배님들은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app폴더랑 pages폴더가 따로 구분되어있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 pages폴더에서 만든 페이지들이 자동으로 라우팅이 됐었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 pages폴더에 apple.tsx 파일만들면&amp;nbsp; localhost:3000/apple 가면 끝났음;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 &lt;b&gt;13버전&lt;/b&gt;으로 바뀌면서 pages 폴더가 사라졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 사용자가 직접 app폴더안에 라우팅 하고자하는 폴더를 만들고 그곳에 page파일을 만어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q) 더 귀찮아진거 같은데.. 하향패치 아님?&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A) ㅇㅇ;; 더 귀찮아지긴했는데.. 공통 컴포넌트 사용면에있어서 상향됨..&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 정적 라우팅&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app폴더 안에 라우팅 하기원하는 폴더 만들고 page파일 만들고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하위 요소들 더 만들고싶으면 자식 폴더 만들고 또 page파일 만들고 뿌리 내리면 됐음.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;330&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vimOI/btsak3zVvV9/wvCULSI1mAYbiJmZK8rB90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vimOI/btsak3zVvV9/wvCULSI1mAYbiJmZK8rB90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vimOI/btsak3zVvV9/wvCULSI1mAYbiJmZK8rB90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvimOI%2Fbtsak3zVvV9%2FwvCULSI1mAYbiJmZK8rB90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;484&quot; height=&quot;282&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;330&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대충 이런식으로 하나하나 하위폴더들 만들면 정적 라우팅 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost:3000/apple/icecream&lt;br /&gt;localhost:3000/apple/juice&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost:3000/apple/candy&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 가면되는데 갑자기 localhost:3000/apple/tree&amp;nbsp; &amp;lt;&amp;lt; 이렇게하면 작동안됨&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;뭔가 자식폴더들 3,4개 수준이 아니라 50개 100개 필요한 경우도 있잖음?&amp;nbsp; 하나하나 정적으로 하드코딩 할순없으니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적으로 만들수있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴땐 리액트의 props 기능을 이용함&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;2. 동적 라우팅&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만드는법:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.app안에 apple폴더를 만들고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. apple폴더 하위에 동적 라우팅이 필요한 자식폴더를 생성하고 폴더명을 [slug]라고 지정함. (이게 국룰이라고 하는데, 원하는 걸로 바꿔도 됨. [food] 이렇게 ㅇㅇ;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl2Xkp/btsahzGoOuV/GDKz89tUZCxRLtZ74UkjEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl2Xkp/btsahzGoOuV/GDKz89tUZCxRLtZ74UkjEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl2Xkp/btsahzGoOuV/GDKz89tUZCxRLtZ74UkjEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl2Xkp%2FbtsahzGoOuV%2FGDKz89tUZCxRLtZ74UkjEk%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;726&quot; height=&quot;182&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;182&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;pre id=&quot;code_1681628555782&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
type Props = {
  params: {
    slug: string;
  };
};

export default function page({ params }: Props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;{params.slug} 레시피!!&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;{params.slug} 무봤나 ㅋㅋ &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해야함. 무조건 {params} &amp;lt;&amp;lt; 라고 받아와야 한다고함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 멋대로 {param} 이라고 해보니까 안되더라; 부모에서 {params}로 넘겨주니까 그런듯 ㅇㅇ;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정하고 이제&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost:3000/apple/applejuice 로 들어가보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ok4dO/btsaqQzZHWU/jb7TYoDBYnzaEXs3MtY641/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ok4dO/btsaqQzZHWU/jb7TYoDBYnzaEXs3MtY641/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ok4dO/btsaqQzZHWU/jb7TYoDBYnzaEXs3MtY641/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fok4dO%2FbtsaqQzZHWU%2Fjb7TYoDBYnzaEXs3MtY641%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;325&quot; height=&quot;285&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;393&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 뜸. 덕분에 이제 100개 1000개도 거뜬할듯&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;근데 또 생각해보면 동적이랑 정적이랑 합쳐서 쓸수도 있음;;;;&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;동적 라우팅 필요한건 [slug]쓰고 무적권 필요한건 apple 하위폴더로 몇개 만들어 두면 되긴함&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세하게 안써도 먼말인지 알지?ㅋ&lt;/p&gt;</description>
      <category>NEXT.js</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/85</guid>
      <comments>https://jamgul.tistory.com/85#entry85comment</comments>
      <pubDate>Sun, 16 Apr 2023 16:08:59 +0900</pubDate>
    </item>
    <item>
      <title>NEXT.js는 CSR임? SSR임?</title>
      <link>https://jamgul.tistory.com/84</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;next-js-logo.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyIcOY/btsak211BWU/cteMlvu734ryWTqFkUH831/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyIcOY/btsak211BWU/cteMlvu734ryWTqFkUH831/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyIcOY/btsak211BWU/cteMlvu734ryWTqFkUH831/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyIcOY%2Fbtsak211BWU%2FcteMlvu734ryWTqFkUH831%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;591&quot; height=&quot;309&quot; data-filename=&quot;next-js-logo.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR과 SSR은 각자 장단점이 있다.&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;background-color: #c1bef9;&quot;&gt;CSR (Client Side Rendering)&lt;/span&gt;&lt;/h3&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;1. 한번만 로딩되면 나머지 동작에서 빠르다. (브라우저에서 한번에 다 다운받아서)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서버의 부하가 적다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 페이지 로딩 시간이 길다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. SEO 최적화 is bad&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 보안취약&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;SSR (Server Side Rendering)&lt;/span&gt;&lt;/h3&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;1. 페이지 로딩 빠름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. SEO 최적화 is godd&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 보안 good&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 실시간 데이터 OK, 사용자별 데이터 OK&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 서버에 부하가 있을수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 요청할때마다 받아와서 조금 느릴수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;NEXT.js를 사용하면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얘는 하이브리드라서&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;CSR이 필요한 곳엔 CSR로, SSR이 필요한곳엔 SSR로, 한페이지라도 CSR+SSR 섞어서 사용가능함 ㄷㄷ;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이지별로 특징에 따라서 최적화 가능함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 하이드레이션(Hydration)이라는 기술도 씀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 정적인 페이지로 HTML, CSS 만 보여주고, 사용자가 상호작용 하기전에 리액트파일을 보냄.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;살짝 느낌은 비동기처리랑 비슷한 느낌인듯?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 초기페이지 로딩속도랑 SEO 개선에 좋음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>NEXT.js</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/84</guid>
      <comments>https://jamgul.tistory.com/84#entry84comment</comments>
      <pubDate>Sun, 16 Apr 2023 14:09:24 +0900</pubDate>
    </item>
    <item>
      <title>Next.js 기본 폴더구조와 역할</title>
      <link>https://jamgul.tistory.com/83</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;457&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfYFLo/btr9Ox2cawx/uh1kSfAcZMLBomt7rJAlfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfYFLo/btr9Ox2cawx/uh1kSfAcZMLBomt7rJAlfk/img.png&quot; data-alt=&quot;보일러플레이트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfYFLo/btr9Ox2cawx/uh1kSfAcZMLBomt7rJAlfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfYFLo%2Fbtr9Ox2cawx%2Fuh1kSfAcZMLBomt7rJAlfk%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;349&quot; height=&quot;457&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;457&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;보일러플레이트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js를 설치하면 해당 폴더구조로 설치된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;app폴더: 코드를 직접 짜는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;page.js : 메인페이지, 리액트의 App.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;layout.js: 메인페이지를 감싸는 용도. 리액트의 index.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;public폴더: 이미지나 static 파일 보관하는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api 폴더 : 서버기능 만드는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;next.config.js : nextjs 설정 파일&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;node_modules 폴더 : 설치한 라이브러리 보관용 폴더&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;package.json : 설치한 라이브러리 버전 기록용 파일&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 구성되어있다. 일단 기존 리액트랑 비슷하다..!&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Next.js 설치방법&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;(터미널을 킨다)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;npx create-next-app@latest --experimental-app&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;2. 프로젝트 명 설정하고, 타입스크립트니 뭐니 여러가지 설정을 한다. (y/n)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;3. npm run dev&amp;nbsp; 쳐서 실행시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;4. http://localhost:3000/&amp;nbsp; 가서 확인한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>NEXT.js</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/83</guid>
      <comments>https://jamgul.tistory.com/83#entry83comment</comments>
      <pubDate>Wed, 12 Apr 2023 21:28:47 +0900</pubDate>
    </item>
    <item>
      <title>Todo List에 타입스크립트 적용해보기</title>
      <link>https://jamgul.tistory.com/82</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;385&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3j5YF/btr8us9oyo2/AjDUAOs1jyfRz9NMHVrCH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3j5YF/btr8us9oyo2/AjDUAOs1jyfRz9NMHVrCH1/img.png&quot; data-alt=&quot;기본 양식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3j5YF/btr8us9oyo2/AjDUAOs1jyfRz9NMHVrCH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3j5YF%2Fbtr8us9oyo2%2FAjDUAOs1jyfRz9NMHVrCH1%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;645&quot; height=&quot;385&quot; data-origin-width=&quot;645&quot; data-origin-height=&quot;385&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본 양식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;HTML&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1680770445278&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;
    &amp;lt;title&amp;gt;Todo List&amp;lt;/title&amp;gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;main.css&quot;&amp;gt;
    
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Todo List&amp;lt;/h1&amp;gt;
    &amp;lt;form&amp;gt;
      &amp;lt;input type=&quot;text&quot; id=&quot;inputTodo&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 id=&quot;todoList&quot;&amp;gt;&amp;lt;/ul&amp;gt;
    &amp;lt;button id=&quot;clearButton&quot;&amp;gt;Clear All&amp;lt;/button&amp;gt;
    &amp;lt;script src=&quot;index.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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;CSS&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1680770463244&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* {
    box-sizing: border-box;
  }
  
  body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
  }
  
  h1 {
    text-align: center;
  }
  
  form {
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }
  
  input[type=&quot;text&quot;] {
    padding: 10px;
    border-radius: 5px;
    border: 1px solid #ccc;
    margin-right: 10px;
    width: 70%;
  }
  
  button[type=&quot;submit&quot;] {
    padding: 10px;
    border-radius: 5px;
    border: none;
    background-color: #4CAF50;
    color: white;
  }
  
  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
  }
  
  li {
    margin: 10px 0;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    display: flex;
    justify-content: space-between;
  }
  
  li span {
    margin-right: 10px;
  }
  
  #clearButton {
    margin-top: 20px;
    padding: 10px;
    border-radius: 5px;
    border: none;
    background-color: #f44336;
    color: white;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;JavaScript&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1680770518880&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const form = document.querySelector('form');
const inputTodo = document.querySelector('#inputTodo');
const todoList = document.querySelector('#todoList');
const clearButton = document.querySelector('#clearButton');
let todos = [];
function renderTodos() {
    todoList.innerHTML = '';
    todos.forEach((todo) =&amp;gt; {
        const li = document.createElement('li');
        li.innerHTML = `${todo.text} &amp;lt;span class=&quot;delete&quot; data-index=&quot;${todo.index}&quot;&amp;gt;삭제&amp;lt;/span&amp;gt;`;
        todoList.appendChild(li);
    });
}
form.addEventListener('submit', (e) =&amp;gt; {
    e.preventDefault();
    if (!inputTodo.value)
        return;
    const newTodo = {
        text: inputTodo.value,
        index: todos.length,
    };
    todos.push(newTodo);
    inputTodo.value = '';
    renderTodos();
    localStorage.setItem('todos', JSON.stringify(todos));
});
todoList.addEventListener('click', (e) =&amp;gt; {
    const target = e.target;
    if (!target.classList.contains('delete'))
        return;
    const index = parseInt(target.dataset.index);
    todos = todos.filter((todo) =&amp;gt; todo.index !== index);
    renderTodos();
    localStorage.setItem('todos', JSON.stringify(todos));
});
clearButton.addEventListener('click', () =&amp;gt; {
    if (confirm('정말 모두 삭제하시겠습니까?')) {
        todos = [];
        renderTodos();
        localStorage.removeItem('todos');
    }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 기본 기능만 가지고 Todo 앱을 뚝딱 만들었따.&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;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 타입스크립트로 적용해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #0593d3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&amp;nbsp;TypeScript&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1680770665943&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const form: HTMLFormElement | null = document.querySelector('form');
const inputTodo: HTMLInputElement | null = document.querySelector('#inputTodo');
const todoList: HTMLUListElement | null = document.querySelector('#todoList');
const clearButton: HTMLButtonElement | null = document.querySelector('#clearButton');
interface Todo {
  text: string;
  index: number;
}

let todos: Todo[] = [];

function renderTodos(): void {
  todoList.innerHTML = '';
  todos.forEach((todo: Todo): void =&amp;gt; {
    const li: HTMLLIElement = document.createElement('li');
    li.innerHTML = `${todo.text} &amp;lt;span class=&quot;delete&quot; data-index=&quot;${todo.index}&quot;&amp;gt;삭제&amp;lt;/span&amp;gt;`;
    todoList.appendChild(li);
  });
}

form.addEventListener('submit', (e: Event): void =&amp;gt; {
  e.preventDefault();
  if (!inputTodo.value) return;
  const newTodo: Todo = {
    text: inputTodo.value,
    index: todos.length,
  };
  todos.push(newTodo);
  inputTodo.value = '';
  renderTodos();
  localStorage.setItem('todos', JSON.stringify(todos));
});

todoList.addEventListener('click', (e: MouseEvent): void =&amp;gt; {
  const target = e.target as HTMLElement;
  if (!target.classList.contains('delete')) return;
  const index: number = parseInt(target.dataset.index!);
  todos = todos.filter((todo: Todo): boolean =&amp;gt; todo.index !== index);
  renderTodos();
  localStorage.setItem('todos', JSON.stringify(todos));
});

clearButton.addEventListener('click', (): void =&amp;gt; {
  if (confirm('정말 모두 삭제하시겠습니까?')) {
    todos = [];
    renderTodos();
    localStorage.removeItem('todos');
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp; 상수에 타입을 정해준다. HTML타입을 정해주고 혹시몰라서 null도 해줬따&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1680770745848&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const form: HTMLFormElement | null = document.querySelector('form');
const inputTodo: HTMLInputElement | null = document.querySelector('#inputTodo');
const todoList: HTMLUListElement | null = document.querySelector('#todoList');
const clearButton: HTMLButtonElement | null = document.querySelector('#clearButton');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp; 계속 사용하게 될 Todo의 타입을 정해줬다. 내용은 text이고 index는 숫자이니까 string과 number로 해줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1680770809682&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Todo {
  text: string;
  index: number;
}

let todos: Todo[] = [];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 함수들은 작동은 하지만 return값이 없기 때문에 void를 줬고, 이벤트 핸들러에 Event 타입을 줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1680770869294&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function renderTodos(): void {
  // ...
}

form.addEventListener('submit', (e: Event): void =&amp;gt; {
  // ...
});

todoList.addEventListener('click', (e: MouseEvent): void =&amp;gt; {
  // ...
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 기존 JS에는 없던것이다. 기존에는 'inputTodo'에서 얻은 값을 직접 'todos' 배열에 추가했지만, 타입스크립트에서는 새로운 변수를 선언해서 할당 해주는게 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 가독성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 디버깅 쉬워짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 코드 유지보수 쉬워짐&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1680770917533&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const newTodo: Todo = {
  text: inputTodo.value,
  index: todos.length,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. as로 e.target의 속성을 HTMLElement로 지정해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1680771032452&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const target = e.target as HTMLElement;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6.&amp;nbsp; parseInt()로 index값을 숫자로 바꿔줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1680771075807&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const index: number = parseInt(target.dataset.index!);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TypeScript</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/82</guid>
      <comments>https://jamgul.tistory.com/82#entry82comment</comments>
      <pubDate>Thu, 6 Apr 2023 17:52:01 +0900</pubDate>
    </item>
    <item>
      <title>Virtual Dom에 대해(feat.리액트).araboja</title>
      <link>https://jamgul.tistory.com/77</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (2).jfif&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;168&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5F00/btrXYajr8eo/KfcmzXzZDFf3LHZvovt4L0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5F00/btrXYajr8eo/KfcmzXzZDFf3LHZvovt4L0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5F00/btrXYajr8eo/KfcmzXzZDFf3LHZvovt4L0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5F00%2FbtrXYajr8eo%2FKfcmzXzZDFf3LHZvovt4L0%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;300&quot; height=&quot;168&quot; data-filename=&quot;다운로드 (2).jfif&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Virtual Dom(가상 DOM)&lt;/b&gt;&lt;/h3&gt;
&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: #000000;&quot;&gt;가상 DOM은&amp;nbsp;실제 DOM에서 처리하는 방식이 아닌 Virtual DOM과 메모리에서 미리 처리하고 저장한 후 실제 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;..?&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; 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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우선 가상 DOM을 이해하기 위해서 DOM이 뭔지 부터, 브라우저 렌더링 과정을 알아야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jamgul.tistory.com/76&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://jamgul.tistory.com/76&lt;/a&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675390652570&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;브라우저 렌더링을.araboja&quot; data-og-description=&quot;브라우저 렌더링 과정을 이해하기 위해서 먼저 웹 브라우저의 구조를 알아야한다. 사용자 인터페이스 : 웹 페이지를 제외하고 사용자와 상호작용 하는 것 ( 주소 표시줄, 이전/다음/새로고침 버&quot; data-og-host=&quot;jamgul.tistory.com&quot; data-og-source-url=&quot;https://jamgul.tistory.com/76&quot; data-og-url=&quot;https://jamgul.tistory.com/76&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DXhmM/hyRt0uh61f/UaG0SCTKhc2VlFVgvjc0Ck/img.png?width=800&amp;amp;height=552&amp;amp;face=0_0_800_552,https://scrap.kakaocdn.net/dn/biUTwp/hyRvdZRhaw/9zFCIDxXGpkf0w8WrZVFk1/img.png?width=800&amp;amp;height=552&amp;amp;face=0_0_800_552,https://scrap.kakaocdn.net/dn/dX1ffD/hyRtPGkUdr/fsJZaScPGd9Cicl4cgF46K/img.png?width=1143&amp;amp;height=513&amp;amp;face=0_0_1143_513&quot;&gt;&lt;a href=&quot;https://jamgul.tistory.com/76&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jamgul.tistory.com/76&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DXhmM/hyRt0uh61f/UaG0SCTKhc2VlFVgvjc0Ck/img.png?width=800&amp;amp;height=552&amp;amp;face=0_0_800_552,https://scrap.kakaocdn.net/dn/biUTwp/hyRvdZRhaw/9zFCIDxXGpkf0w8WrZVFk1/img.png?width=800&amp;amp;height=552&amp;amp;face=0_0_800_552,https://scrap.kakaocdn.net/dn/dX1ffD/hyRtPGkUdr/fsJZaScPGd9Cicl4cgF46K/img.png?width=1143&amp;amp;height=513&amp;amp;face=0_0_1143_513');&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;브라우저 렌더링을.araboja&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;브라우저 렌더링 과정을 이해하기 위해서 먼저 웹 브라우저의 구조를 알아야한다. 사용자 인터페이스 : 웹 페이지를 제외하고 사용자와 상호작용 하는 것 ( 주소 표시줄, 이전/다음/새로고침 버&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jamgul.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요약&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 브라우저가 렌더링할때, HTML파일과 CSS파일을 DOM으로 만들고, 그걸 화면에 어떻게 출력할지 계산하고 출력해준다.&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;color: #000000;&quot;&gt;여기서 이제 문제가 살짝있는데 DOM을 수정하려면 저 렌더링과정을 모두 진행해야해서 많은 연산이 필요함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&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;color: #000000;&quot;&gt;예전엔 SSR 방식(DOM 동작 많이 X)을 많이 사용했는데, CSR방식을 사용하면서 DOM 동작이 많이 복잡해졌다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 DOM조작 하는거 최적화 필요가 생김 =&amp;gt; 가상 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가상DOM이 가벼운 이유&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DOM 노드트리를 복제한 자바스크립트 객체이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 class, style 등의 속성은 가지고있는데, getElementById() 같은 DOM 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;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가상DOM의 동작 방식&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;573&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWy3Tc/btrX2q1989w/L67rrYNFDOdRakBA3vMQ0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWy3Tc/btrX2q1989w/L67rrYNFDOdRakBA3vMQ0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWy3Tc/btrX2q1989w/L67rrYNFDOdRakBA3vMQ0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWy3Tc%2FbtrX2q1989w%2FL67rrYNFDOdRakBA3vMQ0k%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;573&quot; height=&quot;402&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 기존 DOM의 가벼운 버전을 복제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. DOM노드에 변화가 생기면 가상DOM은 다시 새로운 가상DOM을 처음부터 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 변경전의 가상 DOM트리와 변경후의 가상 DOM트리를 비교한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 변경된 부분만 실제DOM에 적용한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 DOM의 변화가 생길때마다 새로 DOM을 만드는거 효율 별로일거 같은데여?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; ㄴㄴ DOM 새로 만드는건 비용 별로 안듬.. 렌더링 하는 과정에서 비용이 많이 드는거임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;(가상 DOM안쓰면 변화할때마다 렌더링 함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 가상 DOM은 &quot;버퍼링&quot;, &quot;캐싱&quot; 느낌이네여?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; ㅇㅇ 변경 부분만 모아서 실제 DOM에 한번만 반영하는거라 그 느낌맞음, 그래서 성능 최적화에 굿임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;리액트에서 Virtual DOM&lt;/b&gt;&lt;/h3&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;1. 작동순서&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/03yg1/btrX2YdfEfd/HxzRhsSPyLEkDkAtd3Wxn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/03yg1/btrX2YdfEfd/HxzRhsSPyLEkDkAtd3Wxn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/03yg1/btrX2YdfEfd/HxzRhsSPyLEkDkAtd3Wxn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F03yg1%2FbtrX2YdfEfd%2FHxzRhsSPyLEkDkAtd3Wxn0%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;692&quot; height=&quot;422&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;507&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;1. JSX문법으로 작성함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Babel같은 툴로 JSX를 JS형식으로 바꿈. 이때 createElement 함수 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 함수에 의해서 객체로 바뀌게 됨.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 객체에서 type은 태그이름, props는 jsx에 포함된 모든 속성들. props의 자식에는 하위 노드들이 포함됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 이 객체를 활용해서 가상 DOM트리를 만듬, 렌더하면 실제 DOM 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 재조정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 공식문서:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Virtual DOM은 UI의 이상적인 또는 가상적인 표현을 메모리에 저장하고&amp;nbsp; ReactDOM과 같은 라이브러리에 의해 실제 DOM과 동기화 하는 프로그래밍 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재조정 =&amp;gt; 가상DOM과 실제DOM을 비교하고 일치시키는 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경전 가상DOM과 변경후 가상DOM 두가지 트리를 비교해서 &lt;b&gt;변화된부분만 실제DOM에 적용&lt;/b&gt;함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에 Diffing 알고리즘을 사용함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Diffing 알고리즘 : jsx가 자바스크립트 객체로 변화된 결과에서 type이라는 키값을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경전 리액트 엘리먼트의 타입과 변경후 엘리먼트 타입을 비교하여 2가지 행동을한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 타입이 같은 경우 : 변경된 속성만 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 타입이 다른 경우 : 이전 트리를 삭제하고 재생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;key prop을 사용하는 이유: 재조정과 연관있음. 재조정 과정에서 이전의 가상돔과 재생성 가상돔을 비교한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식별자로 key prop을 적용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식노드들이 key prop을 갖고있으면 리액트는 키값으로&amp;nbsp; 이전트리와 변경이후트리를 비교한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 첫번째에 새로운 노드들이 추가되어도 문제없이 추가된 노드만 그릴수있따.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키값은 변경되지 않는 유일한 값을 넣어줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만야 배열의 index를 키값으로 주면 배열의 index는 배열이 바뀔때마다 0부터 n가지 새롭게 할당된다. =&amp;gt; 변하는값&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yoR6M/btrX17hqpze/tqrXxpDC6HHkFLP3ikhEWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yoR6M/btrX17hqpze/tqrXxpDC6HHkFLP3ikhEWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yoR6M/btrX17hqpze/tqrXxpDC6HHkFLP3ikhEWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyoR6M%2FbtrX17hqpze%2FtqrXxpDC6HHkFLP3ikhEWk%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;757&quot; height=&quot;482&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/77</guid>
      <comments>https://jamgul.tistory.com/77#entry77comment</comments>
      <pubDate>Sat, 4 Feb 2023 17:04:45 +0900</pubDate>
    </item>
    <item>
      <title>브라우저 렌더링을.araboja</title>
      <link>https://jamgul.tistory.com/76</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img (1).png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;2321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/utNxj/btrXHCaYgz0/KgKHlYuWO5p3FjngQUjdsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/utNxj/btrXHCaYgz0/KgKHlYuWO5p3FjngQUjdsk/img.png&quot; data-alt=&quot;익스플로 쓰는 사람 없제??&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/utNxj/btrXHCaYgz0/KgKHlYuWO5p3FjngQUjdsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FutNxj%2FbtrXHCaYgz0%2FKgKHlYuWO5p3FjngQUjdsk%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;702&quot; height=&quot;485&quot; data-filename=&quot;img (1).png&quot; data-origin-width=&quot;3360&quot; data-origin-height=&quot;2321&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;익스플로 쓰는 사람 없제??&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 렌더링 과정을 이해하기 위해서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 웹 브라우저의 구조를 알아야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;images_thyoondev_post_9cf5cb0d-91bf-41ac-9693-ddf51d2f5fbd_1608995695700browser_structure-min.png&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N2GdE/btrXHB39ZNI/l5RUhYAanymzMuDAHSWgv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N2GdE/btrXHB39ZNI/l5RUhYAanymzMuDAHSWgv0/img.png&quot; data-alt=&quot;웹 브라우저의 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N2GdE/btrXHB39ZNI/l5RUhYAanymzMuDAHSWgv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN2GdE%2FbtrXHB39ZNI%2Fl5RUhYAanymzMuDAHSWgv0%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;441&quot; height=&quot;361&quot; data-filename=&quot;images_thyoondev_post_9cf5cb0d-91bf-41ac-9693-ddf51d2f5fbd_1608995695700browser_structure-min.png&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;361&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;웹 브라우저의 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자 인터페이스 :&amp;nbsp;&lt;/b&gt; 웹 페이지를 제외하고 사용자와 상호작용 하는 것 ( 주소 표시줄, 이전/다음/새로고침 버튼)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;브라우저 엔진:&lt;/b&gt;&amp;nbsp; 유저 인터페이스와 렌더링 엔진을 연결하는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;렌더링 엔진:&lt;/b&gt;&amp;nbsp; HTML과 CSS를 파싱하여 요청한 웹페이지를 표시하는 것&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;통신:&lt;/b&gt;&amp;nbsp; 네트워크 요청을 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UI 백엔드:&lt;/b&gt; 기본적인 위젯을 그려주는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JS엔진:&lt;/b&gt;&amp;nbsp; 자바스크립트 코드를 실행하는 인터프리터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자료 저장소:&lt;/b&gt;&amp;nbsp; 로컬 스토리지나 쿠키같은 보조기억장치에 데이터를 저장하는 파트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 우리는 &lt;b&gt;렌더링 엔진&lt;/b&gt;에 대해서 이야기할것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;렌더링 엔진의 목표&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. HTML,CSS,JS,이미지 등 웹페이지에 포함된 모든 요소들을 화면에 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 업데이트가 필요할 때, 효율적으로 렌더링을 할 수 있도록 자료구조를 생성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; (업데이트: 사용자 동작으로 인한 입력, 애니메이션동작, 비동기 요청에의한 데이터로딩)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더링 엔진의 동작과정을 알아보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1 (1).png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJpZFX/btrXJWMzLoD/mEK9e7zy8ReCcYLhHKz410/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJpZFX/btrXJWMzLoD/mEK9e7zy8ReCcYLhHKz410/img.png&quot; data-alt=&quot;Critical Rendering Pass&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJpZFX/btrXJWMzLoD/mEK9e7zy8ReCcYLhHKz410/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJpZFX%2FbtrXJWMzLoD%2FmEK9e7zy8ReCcYLhHKz410%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;524&quot; height=&quot;581&quot; data-filename=&quot;1 (1).png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;581&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Critical Rendering Pass&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 순서 요약&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. HTML을 DOM으로 =&amp;gt; DOM TREE 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. CSS를 CSSOM으로 =&amp;gt; CSSOM TREE 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 둘이 합쳐서 렌더 트리 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 레이아웃&amp;nbsp; (계산 단계)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 페인트&amp;nbsp; (색칠 단계)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 합성&amp;nbsp; (색칠한거 합치기)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. DOM TREE 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQRe0L/btrXK861VBf/Kn209YCVYw3ma6rTfu8jFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQRe0L/btrXK861VBf/Kn209YCVYw3ma6rTfu8jFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQRe0L/btrXK861VBf/Kn209YCVYw3ma6rTfu8jFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQRe0L%2FbtrXK861VBf%2FKn209YCVYw3ma6rTfu8jFk%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;666&quot; height=&quot;528&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 요청한 HTML 문서를 불러오고 파싱을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘텐츠 트리 내부에서 HTML태그들을 DOM 노드로 변환을 시킨다. 그리고 이 노드들을 연결시켜서 DOM트리를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. CSSOM TREE 생성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;text-align: center; caret-color: transparent; letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/bVfpeZ/btrXHB4bPy3/JgUD48AiKMrRGeeufk7fBK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1137&quot; data-origin-height=&quot;529&quot; data-filename=&quot;제목 없음.png&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS도 DOM 트리처럼 CSSOM 트리를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 렌더트리 생성&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;976&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ye6lv/btrXInxnqJn/hhwvLes7fXpHT9zNwXwo60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ye6lv/btrXInxnqJn/hhwvLes7fXpHT9zNwXwo60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ye6lv/btrXInxnqJn/hhwvLes7fXpHT9zNwXwo60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYe6lv%2FbtrXInxnqJn%2FhhwvLes7fXpHT9zNwXwo60%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;976&quot; height=&quot;526&quot; data-origin-width=&quot;976&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고나면 렌더링엔진이 DOM트리와 CSSOM트리를 합쳐서 렌더트리를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;렌더트리가 만들어지는과정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Document 부터 각 노드들을 순회하면서 각각에 맞는 CSSOM을 찾아서 규칙을 적용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면서 렌더와 관련되 요소들은 렌더트리에 포함을 시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴때 메타 태그나 Display: none 같은 태그는 필요없기때문에 렌더트리에 포함시키지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 브라우저마자 조금씩 다르게 생성되긴함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&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;4. 레이아웃 (계산단계)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰포트 내에서 요소들의 정확한 위치와 크기를 계산하는 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;박스모델에 따라서 텍스트나 요소의 박스가 화면에서 차지하는 영역이나 여백, 스타일 속성이 계산된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 CSS에서 %나 em같은 상대적인 단위를 사용했을때, 기계의 뷰포트에서 맞춰서 픽셀단위로 변환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 페인트 과정 (색칠)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이아웃과정에서 렌더링 엔진이 각 요소들이 어떻게 생겼고 어떻게 보여줄지 알게되면 화면에 실제 픽셀로 그려지도록 변환하느 과정을 거치는데 이것이 바로 페인트 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서&lt;b&gt; 렌더트리에 포함된 요소들이나 텍스트, 이미지들이 실제 픽셀로 그려진다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;번외 과정 !!&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용자 동작으로 JS가 실행되어서 CSS가 변경되거나 애니메이션 재싱이 일어났을 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 3가지 경우가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cf770I/btrXLryKTnQ/43HnNsJsgswI9s2dFepjkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cf770I/btrXLryKTnQ/43HnNsJsgswI9s2dFepjkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf770I/btrXLryKTnQ/43HnNsJsgswI9s2dFepjkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcf770I%2FbtrXLryKTnQ%2F43HnNsJsgswI9s2dFepjkK%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;1154&quot; height=&quot;536&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 레이아웃이 다시 발생하는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 레이아웃 수치를 다시 계산해서 배치해야하기 때문에 다시 발생하는거임. 마지막엔 레이어 합성과정까지 거침&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmtrbu/btrXIjPhiTM/XzpcXKblO2qqFu7OWXqIc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmtrbu/btrXIjPhiTM/XzpcXKblO2qqFu7OWXqIc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmtrbu/btrXIjPhiTM/XzpcXKblO2qqFu7OWXqIc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbmtrbu%2FbtrXIjPhiTM%2FXzpcXKblO2qqFu7OWXqIc0%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;1106&quot; height=&quot;476&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Paint부터 다시 발생 하는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이아웃 수치를 변화시키지 않는 스타일의 변경이 일어났을때 발생. =&amp;gt; 레이아웃 과정이 발생하지 않기 때문에 성능상 이점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1143&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtwGfT/btrXJU83Y0Q/9Jr3xIGkqdohudI93REjN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtwGfT/btrXJU83Y0Q/9Jr3xIGkqdohudI93REjN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtwGfT/btrXJU83Y0Q/9Jr3xIGkqdohudI93REjN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdtwGfT%2FbtrXJU83Y0Q%2F9Jr3xIGkqdohudI93REjN0%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;1143&quot; height=&quot;513&quot; data-origin-width=&quot;1143&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 레이어의 합성만 다시 발생하는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이어의 경우 정해진 기준에 의해서 레이어를 만들고 페인팅할 영역을 나누어 놓는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더트리에 있는 노드객체들은 생성된 객체들은 생성된 레이어에 포함된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이어들은 트리형태로 구성된다. 렌더링 엔진이 각 레이어를 프린팅 과정에서 각각 그려준다음에 하나의 비트맵으로 합성해서 페이지를&amp;nbsp; 완성한다. 이떈 레이아웃과 페인팅 모두 수행하지 않기 때문에 성능상 가장 큰 이점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고자료 : &lt;a href=&quot;https://youtu.be/sJ14cWjrNis&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://youtu.be/sJ14cWjrNis&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS지식</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/76</guid>
      <comments>https://jamgul.tistory.com/76#entry76comment</comments>
      <pubDate>Wed, 1 Feb 2023 11:42:21 +0900</pubDate>
    </item>
    <item>
      <title>CSR과 SSR 차이를(feat.SPA&amp;amp;MPA).araboja</title>
      <link>https://jamgul.tistory.com/75</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjETpD/btrXtRkQ6S3/vFM8LczmDLdTl6Imp9Odm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjETpD/btrXtRkQ6S3/vFM8LczmDLdTl6Imp9Odm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjETpD/btrXtRkQ6S3/vFM8LczmDLdTl6Imp9Odm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjETpD%2FbtrXtRkQ6S3%2FvFM8LczmDLdTl6Imp9Odm0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;263&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;263&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSR: 클라이언트 사이드 렌더링&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SSR: 서버 사이드 렌더링&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CSR&lt;/b&gt; =&amp;nbsp; 클라이언트측에서 렌더링 하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SSR&lt;/b&gt; = 서버측에서 렌더링 하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+)SSG&lt;/b&gt; 라는것도 있음: Static Side Generation&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR이랑 SSG 둘다 서버측에서 HTML을 보내는거라 비슷한데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR은 요청이 들어오면 만들어서 보냄 (미리 만들어두기 어려운 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSG는 미리 다 만들어둔거 (캐싱해두기 좋은 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;CSR의 동작 과정과 특징&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9ELTh/btrXrNv9RM7/9zQecZbC4kuVkfSkj7WOEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9ELTh/btrXrNv9RM7/9zQecZbC4kuVkfSkj7WOEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9ELTh/btrXrNv9RM7/9zQecZbC4kuVkfSkj7WOEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9ELTh%2FbtrXrNv9RM7%2F9zQecZbC4kuVkfSkj7WOEk%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;1051&quot; height=&quot;433&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동작 과정&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 유저가 웹사이트 방문한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 브라우저가 서버에 콘텐츠를 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서버는 빈 뼈대 HTML만 보내준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 브라우저가 연결된 JS링크를 통해 서버를 통해 JS를 다운받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. JS를 이용해 동적으로 페이지를 만들어서 브라우저에 띄운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. CSR은 브라우저가 JS파일을 다운받고, 동적으로 DOM을 생성하는 시간을 기다려야해서&lt;b&gt; 초기 로딩속도가 느리다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 초기 로딩이후에 페이지 일부를 변경할때는 서버에 해당데이터만 요청하면 되기때문에 &lt;b&gt;이후 구동속도가 빠르다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서버는 빈 뼈대 HTML만 주면 되기때문에 서버 부하가 적다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 클라이언트 측에서 연산 라우팅을 직접 처리하기때문에 반응속도가 빠르고, UX도 우수함 =&amp;gt; &lt;b&gt;사용자경험&amp;uarr;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 웹 크롤러가 HTML을 읽는데.. 웹 크롤러 입장에선 빈 뼈대 HTML만 있어서 &lt;b&gt;SEO(검색엔진 최적화)에 불리하다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;SSR의 동작 과정과 특징&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beKEe4/btrXv4KZ7ZG/sm8vPHGfVza07zi2D56840/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beKEe4/btrXv4KZ7ZG/sm8vPHGfVza07zi2D56840/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beKEe4/btrXv4KZ7ZG/sm8vPHGfVza07zi2D56840/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeKEe4%2FbtrXv4KZ7ZG%2Fsm8vPHGfVza07zi2D56840%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;1093&quot; height=&quot;446&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1093&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동작과정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.유저가 웹사이트에 방문한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 브라우저에서 콘텐츠를 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서버에서 즉시 필요한 데이터를 삽입하고 CSS까지 적용해서 렌더링 준비를 마친&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;HTML과 JS 코드를 브라우저로 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 브라우저에서 전달받은 페이지를 띄운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 브라우저가 JS코드를 다운로드하고 HTML에 JS로직을 연결한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 서버에서 렌더링 준비를 마친 HTML을 응답으로 전달함 =&amp;gt;덕분에 SEO에 유리하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. JS코드를 다운받고 실행하기전에 사용자가 화면을 볼수있음 =&amp;gt; &lt;b&gt;초기 구동 속도가 빠름&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; but JS연결이 모두 연결될때까진 사용자가 버튼을 클릭하거나 이동하려해도 반응이 안됨 (렉인줄 앎)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;이걸 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;TTV !== TTI&lt;/span&gt; 이라고함 Time To View !== Time To Interact&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 101.163%; height: 246px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;CSR&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;SSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 78px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 78px; text-align: center;&quot;&gt;장점&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 78px; text-align: center;&quot;&gt;화면 깜빡임 X&lt;br /&gt;초기 로딩이후 구동속도가 빠름&lt;br /&gt;TTV와 TTI 사이 간극 X&lt;br /&gt;서버 부하 분산&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 78px; text-align: center;&quot;&gt;초기 구동속도가 빠름&lt;br /&gt;&lt;br /&gt;SEO에 유리함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 58px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 58px; text-align: center;&quot;&gt;단점&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 58px; text-align: center;&quot;&gt;초기 로딩속도가 느림&lt;br /&gt;SEO에 불리함&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 58px; text-align: center;&quot;&gt;화면 깜빡임이 있음&lt;br /&gt;TTV와 TTI 사이 간극이 있음&lt;br /&gt;서버 부하가 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (1).jpg&quot; data-origin-width=&quot;2418&quot; data-origin-height=&quot;1292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yWqKV/btrXoD8XsrS/TyJAdegzpSTF336jqHpxM0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yWqKV/btrXoD8XsrS/TyJAdegzpSTF336jqHpxM0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yWqKV/btrXoD8XsrS/TyJAdegzpSTF336jqHpxM0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyWqKV%2FbtrXoD8XsrS%2FTyJAdegzpSTF336jqHpxM0%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;2418&quot; height=&quot;1292&quot; data-filename=&quot;image (1).jpg&quot; data-origin-width=&quot;2418&quot; data-origin-height=&quot;1292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SPA&lt;/b&gt;(싱글 페이지 어플리케이션) -&amp;gt; React, Vue, Anguler&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 페이지 하나에서 다 해결됨 =&amp;gt; 원하는 부분만 클라이언트에서 동적으로 갈아끼움, 화면 깜빡임없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MPA&lt;/b&gt;(멀티 페이지 어플리케이션)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 새로운 탭으로 이동할때마다 서버로부터 새로운 HTML을 받아와서 페이지 전체를 새로 렌더링함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 SPA(싱글페이지)는 CSR&amp;nbsp; /// MPA(멀티페이지)는 SSR을 차용함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SPA&lt;/b&gt;는 웹 어플리케이션에서 필요한 정적 리소스를 초반 한번에 다운로드하고, 그 이후 새로운 요청이있을떄 페이지 갱신에 필요한 데이터만 전달받아서 클라이언트에서 페이지를 갱신함. =&amp;gt; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;주로 CSR 사용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MPA&lt;/b&gt;는 새로운 요청이 있을때마다 서버에서 이미 렌더링 된 정적 리소스를 받아오기떄문에 =&amp;gt; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;주로 SSR을 사용함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 페이지가 몇개 렌더링을 어디에서 하냐에 따라서 달라지기도 함&lt;/p&gt;
&lt;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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;요즘 대부분 SPA를 사용하는데.. CSR의 &lt;b&gt;단점보완&lt;/b&gt; 방법은 없을까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0QXZb/btrXBXFzipD/k7pxuu7of5rOQA6rxePDxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0QXZb/btrXBXFzipD/k7pxuu7of5rOQA6rxePDxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0QXZb/btrXBXFzipD/k7pxuu7of5rOQA6rxePDxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0QXZb%2FbtrXBXFzipD%2Fk7pxuu7of5rOQA6rxePDxK%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;1055&quot; height=&quot;498&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;code splitting ,&amp;nbsp; tree-shaking ,&amp;nbsp; chunk 분리를 통해서 &lt;b&gt;JS 번들 크기를 줄여서 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 DOM 생성속도를 줄이기때문에 초기 로딩속도를 보완할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pre-rendering : 웹 라이브러리나 웹팩 플러그인을 통해 각 페이지에 대한 HTML파일을 미리 생성해둔뒤&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 요청하는게 &lt;b&gt;크롤러라면 사전에 렌더링된 HTML버전을 보여주는 방식&lt;/b&gt;으로 개선가능함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR 또는 SSG, ISR를 도입하는 방법도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSG는 수정할수 없는 페이지, 그냥 거의 관상용으로 보기만 하는페이지에서 사용할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ISR은 SSG를 살짝 보완한 것으로, 약 5분마다 서버에서 새로운데이터를 받아온다. 하지만 여전히 사용자가 실시간 데이터는 사용할수 없다는 단점이 있다.&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;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 CSR에 SSR과 SSG를 도입할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법 1.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXDF1u/btrXChYin2o/1jxE2WPz0RiEgkOWtQyhh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXDF1u/btrXChYin2o/1jxE2WPz0RiEgkOWtQyhh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXDF1u/btrXChYin2o/1jxE2WPz0RiEgkOWtQyhh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXDF1u%2FbtrXChYin2o%2F1jxE2WPz0RiEgkOWtQyhh1%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;1001&quot; height=&quot;271&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프레임워크 없이 도입하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;expressJS로 별도의 서버를 운영하는 방법, 타입스크립트가 걱정된다면 nest를 사용할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 프론트엔드 개발자에겐 어려울수있다. (진입장벽)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방법 2.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7rPTP/btrXDBhsB3R/Bfg14DusIWO1GxSIMUan6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7rPTP/btrXDBhsB3R/Bfg14DusIWO1GxSIMUan6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7rPTP/btrXDBhsB3R/Bfg14DusIWO1GxSIMUan6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7rPTP%2FbtrXDBhsB3R%2FBfg14DusIWO1GxSIMUan6K%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;828&quot; height=&quot;564&quot; data-filename=&quot;제목 없음.png&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 SSR/SSG를 쉽게 적용할수있도록 도와주는 프레임워크가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리액트&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NEXT : 페이지의 성격별로 SSR, SSG 사용을 정할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gastsby: SSG에 최적화된 리액트 기반 정적페이지 생성 프레임워크. SSG에 최적화이긴 하지만 CSR, SSR, 레이지로딩도 지원함. 무엇보다 다양한 플러그인이 장점임 // 페이지가 적고 작은 서비스가 사용하기 좋음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;뷰&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NUXT : NEXT에 영감을 받아 만들어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;앵귤러&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNIVERSAL : Angular4부터 코어 모듈에 포함됨. (더이상 프레임워크는 아님)&lt;/p&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;이런 프레임 워크들은 CSR에 비해 코드 복잡도가 올라간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또, 직접 제어할수없는 블랙박스 영역이 존재함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;초기 렌더링 방식으로 SSR을 사용하고 이후엔 CSR을 사용하는 방식을&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Isomorphic App,&amp;nbsp; &amp;nbsp;Universal Rendering&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;초기 로딩 속도 보완, SEO 개선, CSR의 장점을 모두 흡수!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;근데 이렇게 해도 모두 다 단점이 있는데 무엇을 써야할까?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 성격마다 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인정보가 많고 검색엔진 노출필요 X , 유저랑 상호작용이 많다 =&amp;gt; &lt;b&gt;CSR&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 홈페이지, 누구에게나 같은 내용을, 매주 업데이트 한다 =&amp;gt; &lt;b&gt;SSR&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 업데이트가 거의 없다 =&amp;gt; &lt;b&gt;SSG&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에 따라 페이지 내용이 달라짐, 빠른 인터랙션, 검색엔진 노출필요 =&amp;gt; &lt;b&gt;CSR + SSR (Universal Rendering)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고자료:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/YuqB8D6eCKE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://youtu.be/YuqB8D6eCKE&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS지식</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/75</guid>
      <comments>https://jamgul.tistory.com/75#entry75comment</comments>
      <pubDate>Tue, 31 Jan 2023 10:55:32 +0900</pubDate>
    </item>
    <item>
      <title>[22일차] JS 프로그래머스 LV.1</title>
      <link>https://jamgul.tistory.com/74</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;문제 1. 콜라 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU3tGy/btrXgHwMxvp/UgviRqkqxKrUq6QsfWlIfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU3tGy/btrXgHwMxvp/UgviRqkqxKrUq6QsfWlIfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU3tGy/btrXgHwMxvp/UgviRqkqxKrUq6QsfWlIfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU3tGy%2FbtrXgHwMxvp%2FUgviRqkqxKrUq6QsfWlIfK%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;477&quot; height=&quot;383&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image6.png&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;815&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b73PUj/btrXgp4gOej/RscWJGCmKGgYte8eU5ONJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b73PUj/btrXgp4gOej/RscWJGCmKGgYte8eU5ONJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b73PUj/btrXgp4gOej/RscWJGCmKGgYte8eU5ONJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb73PUj%2FbtrXgp4gOej%2FRscWJGCmKGgYte8eU5ONJK%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;481&quot; height=&quot;519&quot; data-filename=&quot;image6.png&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;815&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAP2nj/btrXgZcURmf/0PrWmHQKWwu3N5uxBPGVi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAP2nj/btrXgZcURmf/0PrWmHQKWwu3N5uxBPGVi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAP2nj/btrXgZcURmf/0PrWmHQKWwu3N5uxBPGVi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAP2nj%2FbtrXgZcURmf%2F0PrWmHQKWwu3N5uxBPGVi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;565&quot; height=&quot;504&quot; data-filename=&quot;캡처.PNG&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이 순서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. while문을 사용, 조건은 빈병의 개수(n)가 빈병 요구량(a) 보다 크면 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp; 빈병 개수와 요구량을 나눠주고, 마트에서 주는 콜라 개수를 곱한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 처음에 갖고 있던 빈병과 요구량을 나누고 남은것들이랑 마트에서 받은 콜라빈병이랑 더하고 계산을 다시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1674785413852&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(a, b, n) {
  let answer = 0;
  while (n &amp;gt;= a) {
    const remain = n % a;
      
    n = Math.floor(n / a) * b;
    answer += n;
    n += remain;
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후..&lt;/p&gt;</description>
      <category>알고리즘 문제</category>
      <author>잼굴</author>
      <guid isPermaLink="true">https://jamgul.tistory.com/74</guid>
      <comments>https://jamgul.tistory.com/74#entry74comment</comments>
      <pubDate>Fri, 27 Jan 2023 11:11:29 +0900</pubDate>
    </item>
  </channel>
</rss>